312ed700f2b0b0bbe5554c68c7e8a5db64c2a05c
[asterisk/asterisk.git] / utils / conf2ael.c
1 /*  
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Digium, Inc.
5  *
6  * Steve Murphy <murf@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*
20  *
21  * Reverse compile extensions.conf code into prototype AEL code
22  *
23  */
24
25 /*** MODULEINFO
26         <depend>res_ael_share</depend>
27  ***/
28
29 #include "asterisk/autoconfig.h"
30
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <locale.h>
37 #include <ctype.h>
38 #if !defined(SOLARIS) && !defined(__CYGWIN__)
39 #include <err.h>
40 #endif
41 #include <errno.h>
42 #include <regex.h>
43 #include <limits.h>
44
45 #include "asterisk/compat.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/ast_expr.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/chanvars.h"
50 #include "asterisk/module.h"
51 #include "asterisk/app.h"
52 #include "asterisk/config.h"
53 #include "asterisk/options.h"
54 #include "asterisk/callerid.h"
55 #include "asterisk/ael_structs.h"
56 #include "asterisk/devicestate.h"
57 #include "asterisk/stringfields.h"
58 #include "asterisk/pval.h"
59 #include "asterisk/extconf.h"
60
61 void get_start_stop(unsigned int *word, int bitsperword, int totalbits, int *start, int *end);
62 int all_bits_set(unsigned int *word, int bitsperword, int totalbits);
63 extern char *days[];
64 extern char *months[];
65 char ast_config_AST_CONFIG_DIR[PATH_MAX];
66
67 char *config = "extensions.conf";
68
69 /* 
70 static char *registrar = "conf2ael";
71 static char userscontext[AST_MAX_EXTENSION] = "default";
72 static int static_config = 0;
73 static int write_protect_config = 1;
74 static int autofallthrough_config = 0;
75 static int clearglobalvars_config = 0;
76 char ast_config_AST_SYSTEM_NAME[20] = ""; */
77
78 /*! Go no deeper than this through includes (not counting loops) */
79 #define AST_PBX_MAX_STACK       128
80 /* static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function); */
81 extern char ast_config_AST_CONFIG_DIR[PATH_MAX];
82
83 /* modulation */
84 void ast_add_profile(void);
85 void ast_register_file_version(void);
86 void ast_unregister_file_version(void);
87
88 void ast_add_profile(void)
89 {
90 }
91 void ast_register_file_version(void)
92 {
93         /* if(!no_comp)
94            printf("Executed ast_register_file_version();\n"); */
95         /* I'm erasing this, because I don't think anyone really ever needs to see it anyway */
96 }
97
98 void ast_unregister_file_version(void)
99 {
100         /* if(!no_comp)
101                 printf("Executed ast_unregister_file_version();\n"); */
102         /* I'm erasing this, because I don't think anyone really ever needs to see it anyway */
103 }
104
105 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
106 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
107
108 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
109 {
110         va_list vars;
111         va_start(vars,fmt);
112         
113         printf("LOG: lev:%d file:%s  line:%d func: %s  ",
114                    level, file, line, function);
115         vprintf(fmt, vars);
116         fflush(stdout);
117         va_end(vars);
118 }
119
120 /* stolen from pbx.c */
121 struct ast_context;
122 struct ast_app;
123 #ifdef LOW_MEMORY
124 #define EXT_DATA_SIZE 256
125 #else
126 #define EXT_DATA_SIZE 8192
127 #endif
128
129 #define SWITCH_DATA_LENGTH 256
130
131 #define VAR_BUF_SIZE 4096
132
133 #define VAR_NORMAL              1
134 #define VAR_SOFTTRAN    2
135 #define VAR_HARDTRAN    3
136
137 #define BACKGROUND_SKIP         (1 << 0)
138 #define BACKGROUND_NOANSWER     (1 << 1)
139 #define BACKGROUND_MATCHEXTEN   (1 << 2)
140 #define BACKGROUND_PLAYBACK     (1 << 3)
141
142 /*!
143    \brief ast_exten: An extension
144         The dialplan is saved as a linked list with each context
145         having it's own linked list of extensions - one item per
146         priority.
147 */
148 struct ast_exten {
149         char *exten;                    /*!< Extension name */
150         int matchcid;                   /*!< Match caller id ? */
151         const char *cidmatch;           /*!< Caller id to match for this extension */
152         int priority;                   /*!< Priority */
153         const char *label;              /*!< Label */
154         struct ast_context *parent;     /*!< The context this extension belongs to  */
155         const char *app;                /*!< Application to execute */
156         struct ast_app *cached_app;     /*!< Cached location of application */
157         void *data;                     /*!< Data to use (arguments) */
158         void (*datad)(void *);          /*!< Data destructor */
159         struct ast_exten *peer;         /*!< Next higher priority with our extension */
160         const char *registrar;          /*!< Registrar */
161         struct ast_exten *next;         /*!< Extension with a greater ID */
162         char stuff[0];
163 };
164
165
166 /*! \brief ast_include: include= support in extensions.conf */
167 struct ast_include {
168         const char *name;
169         const char *rname;                      /*!< Context to include */
170         const char *registrar;                  /*!< Registrar */
171         int hastime;                            /*!< If time construct exists */
172         struct ast_timing timing;               /*!< time construct */
173         struct ast_include *next;               /*!< Link them together */
174         char stuff[0];
175 };
176
177 /*! \brief ast_sw: Switch statement in extensions.conf */
178 struct ast_sw {
179         char *name;
180         const char *registrar;                  /*!< Registrar */
181         char *data;                             /*!< Data load */
182         int eval;
183         AST_LIST_ENTRY(ast_sw) list;
184         char *tmpdata;
185         char stuff[0];
186 };
187
188 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
189 struct ast_ignorepat {
190         const char *registrar;
191         struct ast_ignorepat *next;
192         const char pattern[0];
193 };
194
195 /*! \brief ast_context: An extension context */
196 struct ast_context {
197         ast_rwlock_t lock;                      /*!< A lock to prevent multiple threads from clobbering the context */
198         struct ast_exten *root;                 /*!< The root of the list of extensions */
199         struct ast_context *next;               /*!< Link them together */
200         struct ast_include *includes;           /*!< Include other contexts */
201         struct ast_ignorepat *ignorepats;       /*!< Patterns for which to continue playing dialtone */
202         const char *registrar;                  /*!< Registrar */
203         AST_LIST_HEAD_NOLOCK(, ast_sw) alts;    /*!< Alternative switches */
204         ast_mutex_t macrolock;                  /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
205         char name[0];                           /*!< Name of the context */
206 };
207
208
209 /*! \brief ast_app: A registered application */
210 struct ast_app {
211         int (*execute)(struct ast_channel *chan, void *data);
212         const char *synopsis;                   /*!< Synopsis text for 'show applications' */
213         const char *description;                /*!< Description (help text) for 'show application &lt;name&gt;' */
214         AST_RWLIST_ENTRY(ast_app) list;         /*!< Next app in list */
215         struct module *module;                  /*!< Module this app belongs to */
216         char name[0];                           /*!< Name of the application */
217 };
218
219 /*! \brief ast_state_cb: An extension state notify register item */
220 struct ast_state_cb {
221         int id;
222         void *data;
223         ast_state_cb_type callback;
224         struct ast_state_cb *next;
225 };
226
227 /*! \brief Structure for dial plan hints
228
229   \note Hints are pointers from an extension in the dialplan to one or
230   more devices (tech/name) 
231         - See \ref AstExtState
232 */
233 struct ast_hint {
234         struct ast_exten *exten;        /*!< Extension */
235         int laststate;                  /*!< Last known state */
236         struct ast_state_cb *callbacks; /*!< Callback list for this extension */
237         AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */
238 };
239
240 struct store_hint {
241         char *context;
242         char *exten;
243         struct ast_state_cb *callbacks;
244         int laststate;
245         AST_LIST_ENTRY(store_hint) list;
246         char data[1];
247 };
248
249 AST_LIST_HEAD(store_hints, store_hint);
250
251 static const struct cfextension_states {
252         int extension_state;
253         const char * const text;
254 } extension_states[] = {
255         { AST_EXTENSION_NOT_INUSE,                     "Idle" },
256         { AST_EXTENSION_INUSE,                         "InUse" },
257         { AST_EXTENSION_BUSY,                          "Busy" },
258         { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
259         { AST_EXTENSION_RINGING,                       "Ringing" },
260         { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
261         { AST_EXTENSION_ONHOLD,                        "Hold" },
262         { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
263 };
264 #define STATUS_NO_CONTEXT       1
265 #define STATUS_NO_EXTENSION     2
266 #define STATUS_NO_PRIORITY      3
267 #define STATUS_NO_LABEL         4
268 #define STATUS_SUCCESS          5
269
270 extern struct ast_context *local_contexts;
271 extern struct ast_context *contexts;
272
273
274 struct ast_custom_function *ast_custom_function_find(const char *name);
275
276
277 struct ast_custom_function *ast_custom_function_find(const char *name)
278 {
279         return 0; /* in "standalone" mode, functions are just not avail */
280 }
281
282
283 struct profile_entry {
284         const char *name;
285         uint64_t        scale;  /* if non-zero, values are scaled by this */
286         int64_t mark;
287         int64_t value;
288         int64_t events;
289 };
290
291 struct profile_data {
292         int entries;
293         int max_size;
294         struct profile_entry e[0];
295 };
296
297 static int bit_at(unsigned int *word, int bitsperword, int bitnum)
298 {
299         return word[bitnum/bitsperword] & (1 << (bitnum % bitsperword));
300 }
301
302 void get_start_stop(unsigned int *word, int bitsperword, int totalbits, int *start, int *end)
303 {
304         int i;
305         int thisbit, thatbit = bit_at(word, bitsperword, totalbits-1);
306         
307         for (i=0; i<totalbits; i++) {
308                 thisbit = bit_at(word, bitsperword, i);
309                 
310                 if (thisbit != thatbit ) {
311                         if (thisbit) {
312                                 *start = i;
313                         } else {
314                                 *end = i;
315                         }
316                 }
317                 thatbit = thisbit;
318         }
319 }
320
321 int all_bits_set(unsigned int *word, int bitsperword, int totalbits )
322 {
323         
324         int i, total=totalbits/bitsperword,bitmask = 0;
325         
326         for (i=0; i<bitsperword; i++)
327         {
328                 bitmask |= (1 << i);
329         }
330         
331         for (i=0; i<total; i++)
332         {
333                 if (word[i] != bitmask)
334                         return 0;
335         }
336         return 1;
337 }
338
339
340 int main(int argc, char **argv)
341 {
342         struct ast_context *tmp;
343         struct ast_exten *e, *eroot;
344         pval *tree, *tmptree, *sws;
345         struct ast_include *tmpi;
346         struct ast_sw *sw = 0;
347         struct ast_ignorepat *ipi;
348         pval *incl=0;
349         int localdir = 0, i;
350
351         tree = 0;
352         tmptree = 0;
353
354         /* process the command line args */
355         for (i=1; i<argc; i++)
356         {
357                 if (strcmp(argv[i],"-d")==0)
358                         localdir =1;
359         }
360         
361         /* 3 simple steps: */
362         /*   1. read in the extensions.conf config file 
363          *   2. traverse, and build an AEL tree
364          *   3. Output the AEL tree into a file
365          */
366         printf("WARNING: This is an EXTREMELY preliminary version of a program\n");
367         printf("         that will someday hopefully do a thoughful and intelligent\n");
368         printf("         job of transforming your extensions.conf file into an\n");
369         printf("         extensions.ael file.\n");
370         printf("         This version has absolutely no intelligence, and pretty\n");
371         printf("         much just does a direct conversion\n");
372         printf("         The result will most likely need careful attention to\n");
373         printf("         finish the job!!!!!\n");
374
375         if (!localdir)
376                 printf(" (You could use -d the use the extensions.conf in the current directory!)\n");
377
378         strcpy(ast_config_AST_CONFIG_DIR,"/etc/asterisk");
379         
380         printf("Loading %s/%s...\n", ast_config_AST_CONFIG_DIR, config);
381
382         if (!localdir)
383                 localized_use_conf_dir();
384         localized_pbx_load_module();
385         
386         printf("... Done!\n");
387         
388         tmp = 0;
389         while ((tmp = localized_walk_contexts(tmp)) ) {
390                 printf("Context: %s\n", tmp->name);
391         }
392         printf("=========\n");
393         tmp = 0;
394         while ((tmp = localized_walk_contexts(tmp)) ) {
395                 /* printf("Context: %s\n", tmp->name); */
396                 tmptree = pvalCreateNode(PV_CONTEXT);
397                 if (!tree)
398                         tree = tmptree;
399                 else
400                         pvalTopLevAddObject(tree, tmptree);
401                 
402                 pvalContextSetName(tmptree, ast_strdup(tmp->name));
403                 
404                 if (tmp->includes) {
405                         incl = pvalCreateNode(PV_INCLUDES);
406                         pvalContextAddStatement(tmptree, incl);
407                         for (tmpi = tmp->includes; tmpi; ) { /* includes */
408                                 if (strchr(tmpi->name,'|')==0) {
409                                         if (tmpi->hastime)
410                                         {
411                                                 char timerange[15];
412                                                 char dowrange[10];
413                                                 char domrange[10];
414                                                 char monrange[10];
415                                                 int startbit=0, endbit=0;
416                                                 
417                                                 if (all_bits_set(tmpi->timing.minmask, 30, 720))
418                                                         strcpy(timerange, "*");
419                                                 else {
420                                                         int hr, min;
421                                                         char tbuf[20];
422                                                         get_start_stop(tmpi->timing.minmask, 30, 720, &startbit, &endbit);
423                                                         hr = startbit/30;
424                                                         min = (startbit % 30) * 2;
425                                                         sprintf(tbuf,"%02d:%02d", hr, min);
426                                                         strcpy(timerange, tbuf);
427                                                         hr = endbit/30;
428                                                         min = (endbit % 30) * 2;
429                                                         sprintf(tbuf,"%02d:%02d", hr, min);
430                                                         strcat(timerange,"-");
431                                                         strcat(timerange,tbuf);
432                                                 }
433                                                 
434                                                 if (all_bits_set(&tmpi->timing.dowmask, 7, 7))
435                                                         strcpy(dowrange, "*");
436                                                 else {
437                                                         get_start_stop(&tmpi->timing.dowmask, 7, 7, &startbit, &endbit);
438                                                         strcpy(dowrange, days[startbit]);
439                                                         strcat(dowrange,"-");
440                                                         strcat(dowrange, days[endbit]);
441                                                 }
442                                                 
443                                                 if (all_bits_set(&tmpi->timing.monthmask, 12, 12))
444                                                         strcpy(monrange, "*");
445                                                 else {
446                                                         get_start_stop(&tmpi->timing.monthmask, 12, 12, &startbit, &endbit);
447                                                         strcpy(monrange, months[startbit]);
448                                                         strcat(monrange,"-");
449                                                         strcat(monrange, months[endbit]);
450                                                 }
451                                                 
452                                                 if (all_bits_set(&tmpi->timing.daymask, 31, 31))
453                                                         strcpy(domrange, "*");
454                                                 else {
455                                                         char tbuf[20];
456                                                         get_start_stop(&tmpi->timing.daymask, 31, 31, &startbit, &endbit);
457                                                         sprintf(tbuf,"%d", startbit);
458                                                         strcpy(domrange, tbuf);
459                                                         strcat(domrange,"-");
460                                                         sprintf(tbuf,"%d", endbit);
461                                                         strcat(domrange, tbuf);
462                                                 }
463                                                 /* now all 4 fields are set; what do we do? */
464                                                 pvalIncludesAddIncludeWithTimeConstraints(incl, strdup(tmpi->name), strdup(timerange), strdup(domrange), strdup(dowrange), strdup(monrange));
465                                                 
466                                         } else {
467                                                 pvalIncludesAddInclude(incl, strdup(tmpi->name));
468                                         }
469                                 } else { /* it appears the timing constraint info is tacked onto the name, carve it up and divvy it out */
470                                         char *dow,*dom,*mon;
471                                         char *all = strdup(tmpi->name);
472                                         char *hr = strchr(all,'|');
473                                         if (hr) {
474                                                 *hr++ = 0;
475                                                 dow = strchr(hr,'|');
476                                                 if (dow) {
477                                                         *dow++ = 0;
478                                                         dom = strchr(dow,'|');
479                                                         if (dom) {
480                                                                 *dom++ = 0;
481                                                                 mon = strchr(dom,'|');
482                                                                 if (mon) {
483                                                                         *mon++ = 0;
484                                                                         /* now all 4 fields are set; what do we do? */
485                                                                         pvalIncludesAddIncludeWithTimeConstraints(incl, all, hr, dow, dom, mon);
486                                                                         /* the original data is always best to keep (no 2-min rounding) */
487                                                                 } else {
488                                                                         ast_log(LOG_ERROR,"No month spec attached to include!\n");
489                                                                 }
490                                                         } else {
491                                                                 ast_log(LOG_ERROR,"No day of month spec attached to include!\n");
492                                                         }
493                                                 } else {
494                                                         ast_log(LOG_ERROR,"No day of week spec attached to include!\n");
495                                                 }
496                                         }
497                                 }
498                                 tmpi = tmpi->next;
499                         }
500                 }
501                 for (ipi = tmp->ignorepats; ipi; ) { /* ignorepats */
502                         incl = pvalCreateNode(PV_IGNOREPAT);
503                         pvalIgnorePatSetPattern(incl,(char *)ipi->pattern);
504                         pvalContextAddStatement(tmptree, incl);
505                         ipi = ipi->next;
506                 }
507                 eroot=0;
508                 while ( (eroot = localized_walk_context_extensions(tmp, eroot)) ) {
509                         pval *exten = pvalCreateNode(PV_EXTENSION);
510                         pvalContextAddStatement(tmptree, exten);
511                         pvalExtenSetName(exten, ast_strdup(eroot->exten));
512                 
513                         if (eroot->peer) {
514                                 pval *block = pvalCreateNode(PV_STATEMENTBLOCK);
515                                 pvalExtenSetStatement(exten, block);
516                                 
517                                 e = 0;
518                                 while ( (e = localized_walk_extension_priorities(eroot, e)) ) {
519                                         
520                                         pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL);
521                                         pval *args = pvalCreateNode(PV_WORD);
522                                         
523                                         /* printf("           %s(%s)\n", e->app, (char*)e->data); */
524
525                                         pvalAppCallSetAppName(statemnt, ast_strdup(e->app));
526                                         pvalWordSetString(args, ast_strdup(e->data));
527                                         pvalAppCallAddArg(statemnt, args);
528                                         
529                                         pvalStatementBlockAddStatement(block, statemnt);
530                                 }
531                         } else if (eroot->priority == -1) {
532
533                                 pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL);
534                                 pval *args = pvalCreateNode(PV_WORD);
535
536                                 /* printf("Mike, we have a hint on exten %s with data %s\n", eroot->exten, eroot->app); */
537
538                                 pvalAppCallSetAppName(statemnt, "NoOp");
539                                 pvalWordSetString(args, ast_strdup(eroot->app));
540
541
542                                 pvalExtenSetStatement(exten, statemnt);
543                                 pvalExtenSetHints(exten, ast_strdup(eroot->app));
544                         } else {
545
546                                 pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL);
547                                 pval *args = pvalCreateNode(PV_WORD);
548         
549                                 /* printf("           %s (%s)\n", eroot->app, (char *)eroot->data); */
550                                 
551                                 pvalAppCallSetAppName(statemnt, ast_strdup(eroot->app));
552                                 pvalWordSetString(args, ast_strdup(eroot->data));
553
554                                 
555                                 pvalAppCallAddArg(statemnt, args);
556                                 pvalExtenSetStatement(exten, statemnt);
557                         }
558
559                         /* printf("   extension: %s\n", eroot->exten); */
560                 }
561                 if (AST_LIST_FIRST(&tmp->alts)) {
562                         sws = pvalCreateNode(PV_SWITCHES);
563                         pvalContextAddStatement(tmptree,sws);
564                         
565                         sw = 0;
566                         while ((sw = localized_walk_context_switches(tmp,sw)) ) {
567                                 pvalSwitchesAddSwitch(sws, ast_strdup(sw->name));
568                         }
569                 }
570         }
571         printf("Generating aelout.ael file...\n");
572         
573         ael2_print("aelout.ael", tree);
574         
575         printf("...Done!\n");
576         return 0;
577 }
578
579
580 /* ==================================== for linking internal stuff to external stuff */
581
582 int pbx_builtin_setvar(struct ast_channel *chan, void *data)
583 {
584         return localized_pbx_builtin_setvar(chan, data);
585 }
586
587 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
588 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
589 {
590         if (cp1 && *cp1)
591                 strncpy(cp2,cp1,AST_MAX_EXTENSION); /* Right now, this routine is ONLY being called for 
592                                                                                            a possible var substitution on extension names,
593                                                                                            so....! */
594         else
595                 *cp2 = 0;
596 }
597
598 int ast_add_extension2(struct ast_context *con,
599                                            int replace, const char *extension, int priority, const char *label, const char *callerid,
600                                            const char *application, void *data, void (*datad)(void *),
601                                            const char *registrar)
602 {
603         return localized_add_extension2(con, replace, extension, priority, label, callerid, application, data, datad, registrar);
604 }
605
606 int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
607 {
608         
609         return localized_context_add_ignorepat2(con, value, registrar);
610 }
611
612 int ast_context_add_switch2(struct ast_context *con, const char *value,
613                                                                  const char *data, int eval, const char *registrar)
614 {
615         
616         return localized_context_add_switch2(con, value, data, eval, registrar);
617 }
618
619 int ast_context_add_include2(struct ast_context *con, const char *value,
620                                                                   const char *registrar)
621 {
622         
623         return localized_context_add_include2(con, value,registrar);
624 }
625
626 struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
627 {
628         printf("Creating context %s, registrar=%s\n", name, registrar);
629         
630         return localized_context_create(extcontexts, name, registrar);
631 }
632
633 void ast_cli_register_multiple(void);
634
635 void ast_cli_register_multiple(void)
636 {
637 }
638
639 void ast_module_register(const struct ast_module_info *x)
640 {
641 }
642
643 void ast_module_unregister(const struct ast_module_info *x)
644 {
645 }
646
647 void ast_cli_unregister_multiple(void);
648
649 void ast_cli_unregister_multiple(void)
650 {
651 }
652
653 struct ast_context *ast_walk_contexts(struct ast_context *con);
654 struct ast_context *ast_walk_contexts(struct ast_context *con)
655 {
656         return localized_walk_contexts(con);
657 }
658
659 void ast_context_destroy(struct ast_context *con, const char *registrar);
660
661 void ast_context_destroy(struct ast_context *con, const char *registrar)
662 {
663         return localized_context_destroy(con, registrar);
664 }
665
666 int ast_context_verify_includes(struct ast_context *con);
667
668 int ast_context_verify_includes(struct ast_context *con)
669 {
670         return  localized_context_verify_includes(con);
671 }
672
673 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar);
674
675 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
676 {
677         localized_merge_contexts_and_delete(extcontexts, registrar);
678 }
679
680 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
681                                                                          struct ast_context *bypass,
682                                                                          struct pbx_find_info *q,
683                                                                          const char *context, 
684                                                                          const char *exten, 
685                                                                          int priority,
686                                                                          const char *label, 
687                                                                          const char *callerid, 
688                                                                          enum ext_match_t action);
689
690 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
691                                                                          struct ast_context *bypass,
692                                                                          struct pbx_find_info *q,
693                                                                          const char *context, 
694                                                                          const char *exten, 
695                                                                          int priority,
696                                                                          const char *label, 
697                                                                          const char *callerid, 
698                                                                          enum ext_match_t action)
699 {
700         return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action);
701 }
702