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