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