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