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