2 * XXX this file probably need a fair amount of cleanup, at the very least:
4 * - documenting its purpose;
5 * - removing all unnecessary headers and other stuff from the sources
7 * - fixing the formatting
11 <support_level>extended</support_level>
21 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
23 #include "asterisk/backtrace.h"
24 #include "asterisk/channel.h"
25 #include "asterisk/ast_expr.h"
26 #include "asterisk/module.h"
27 #include "asterisk/app.h"
28 #include "asterisk/lock.h"
29 #include "asterisk/hashtab.h"
30 #include "asterisk/ael_structs.h"
31 #include "asterisk/extconf.h"
34 int option_verbose = 0;
35 #if !defined(LOW_MEMORY)
36 void ast_register_file_version(const char *file, const char *version) { }
37 void ast_unregister_file_version(const char *file) { }
40 struct ast_flags ast_compat = { 7 };
43 <depend>res_ael_share</depend>
50 struct namelist *next;
58 struct namelist *includes;
59 struct namelist *ignorepats;
60 struct namelist *switches;
61 struct namelist *eswitches;
63 struct namelist *includes_last;
64 struct namelist *ignorepats_last;
65 struct namelist *switches_last;
66 struct namelist *eswitches_last;
68 struct ast_context *next;
71 #define ADD_LAST(headptr,memptr) if(!headptr){ headptr=(memptr); (headptr##_last)=(memptr);} else {(headptr##_last)->next = (memptr); (headptr##_last) = (memptr);}
73 void destroy_namelist(struct namelist *x);
74 void destroy_namelist(struct namelist *x)
76 struct namelist *z,*z2;
85 struct namelist *create_name(const char *name);
86 struct namelist *create_name(const char *name)
88 struct namelist *x = calloc(1, sizeof(*x));
91 strncpy(x->name, name, sizeof(x->name) - 1);
95 struct ast_context *context_list;
96 struct ast_context *last_context;
97 struct namelist *globalvars;
98 struct namelist *globalvars_last;
100 int conts=0, extens=0, priors=0;
101 char last_exten[18000];
103 static char config_dir[PATH_MAX];
104 static char var_dir[PATH_MAX];
105 const char *ast_config_AST_CONFIG_DIR = config_dir;
106 const char *ast_config_AST_VAR_DIR = var_dir;
108 void ast_cli_register_multiple(void);
109 int ast_add_extension2(struct ast_context *con,
110 int replace, const char *extension, int priority, const char *label, const char *callerid,
111 const char *application, void *data, void (*datad)(void *),
112 const char *registrar);
113 void pbx_builtin_setvar(void *chan, void *data);
114 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar);
115 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar);
116 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
117 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar);
118 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar);
119 void ast_merge_contexts_and_delete(void);
120 void ast_context_verify_includes(void);
121 struct ast_context * ast_walk_contexts(void);
122 void ast_cli_unregister_multiple(void);
123 void ast_context_destroy(void);
124 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...);
125 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
126 void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...);
127 struct ast_app *pbx_findapp(const char *app);
128 void filter_leading_space_from_exprs(char *str);
129 void filter_newlines(char *str);
130 static int quiet = 0;
131 static int no_comp = 0;
132 static int use_curr_dir = 0;
133 static int dump_extensions = 0;
134 static int FIRST_TIME = 0;
135 static FILE *dumpfile;
137 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
142 printf("LOG: lev:%d file:%s line:%d func: %s ",
143 level, file, line, function);
149 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
150 struct ast_context *bypass,
151 struct pbx_find_info *q,
156 const char *callerid,
157 enum ext_match_t action);
159 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
160 struct ast_context *bypass,
161 struct pbx_find_info *q,
166 const char *callerid,
167 enum ext_match_t action)
169 return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action);
172 struct ast_app *pbx_findapp(const char *app)
174 return (struct ast_app*)1; /* so as not to trigger an error */
177 struct ast_custom_function *ast_custom_function_find(const char *name);
180 struct ast_custom_function *ast_custom_function_find(const char *name)
182 return 0; /* in "standalone" mode, functions are just not avail */
185 #if !defined(LOW_MEMORY)
186 int ast_add_profile(const char *x, uint64_t scale)
189 printf("Executed ast_add_profile();\n");
195 int ast_loader_register(int (*updater)(void))
200 int ast_loader_unregister(int (*updater)(void))
204 void ast_module_register(const struct ast_module_info *x)
208 void ast_module_unregister(const struct ast_module_info *x)
213 void ast_cli_register_multiple(void)
216 printf("Executed ast_cli_register_multiple();\n");
219 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
220 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
223 strncpy(cp2,cp1,AST_MAX_EXTENSION); /* Right now, this routine is ONLY being called for
224 a possible var substitution on extension names,
230 int ast_add_extension2(struct ast_context *con,
231 int replace, const char *extension, int priority, const char *label, const char *callerid,
232 const char *application, void *data, void (*datad)(void *),
233 const char *registrar)
236 con->extension_count++;
237 if (strcmp(extension,last_exten) != 0) {
239 strcpy(last_exten, extension);
248 application = "(null)";
252 printf("Executed ast_add_extension2(context=%s, rep=%d, exten=%s, priority=%d, label=%s, callerid=%s, appl=%s, data=%s, FREE, registrar=%s);\n",
253 con->name, replace, extension, priority, label, callerid, application, (data?(char*)data:"(null)"), registrar);
255 if( dump_extensions && dumpfile ) {
262 fprintf(dumpfile,"[globals]\n");
264 for(n=globalvars;n;n=n->next) {
265 fprintf(dumpfile, "%s\n", n->name);
269 /* print out each extension , possibly the context header also */
270 if( con != last_context ) {
271 fprintf(dumpfile,"\n\n[%s]\n", con->name);
273 for(n=con->ignorepats;n;n=n->next) {
274 fprintf(dumpfile, "ignorepat => %s\n", n->name);
276 for(n=con->includes;n;n=n->next) {
277 fprintf(dumpfile, "include => %s\n", n->name);
279 for(n=con->switches;n;n=n->next) {
280 fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
282 for(n=con->eswitches;n;n=n->next) {
283 fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
288 filter_newlines((char*)data);
289 filter_leading_space_from_exprs((char*)data);
290 /* in previous versions, commas were converted to '|' to separate
291 args in app calls, but now, commas are used. There used to be
292 code here to insert backslashes (escapes) before any commas
293 that may have been embedded in the app args. This code is no more. */
295 if( strcmp(label,"(null)") != 0 )
296 fprintf(dumpfile,"exten => %s,%d(%s),%s(%s)\n", extension, priority, label, application, (char*)data);
298 fprintf(dumpfile,"exten => %s,%d,%s(%s)\n", extension, priority, application, (char*)data);
302 if( strcmp(label,"(null)") != 0 )
303 fprintf(dumpfile,"exten => %s,%d(%s),%s\n", extension, priority, label, application);
305 fprintf(dumpfile,"exten => %s,%d,%s\n", extension, priority, application);
309 /* since add_extension2 is responsible for the malloc'd data stuff */
314 void pbx_builtin_setvar(void *chan, void *data)
316 struct namelist *x = create_name(data);
318 printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data);
320 if( dump_extensions ) {
321 x = create_name(data);
322 ADD_LAST(globalvars,x);
327 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar)
329 struct ast_context *x = calloc(1, sizeof(*x));
332 x->next = context_list;
335 printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name, registrar);
337 strncpy(x->name, name, sizeof(x->name) - 1);
338 strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
342 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar)
344 struct ast_context *x = calloc(1, sizeof(*x));
347 x->next = context_list;
350 printf("Executed ast_context_find_or_create(conts, name=%s, registrar=%s);\n", name, registrar);
352 strncpy(x->name, name, sizeof(x->name) - 1);
353 strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
357 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
360 printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value, registrar);
361 if( dump_extensions ) {
363 x = create_name(value);
364 ADD_LAST(con->ignorepats,x);
368 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
371 printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value, registrar);
372 if( dump_extensions ) {
374 x = create_name((char*)value);
375 ADD_LAST(con->includes,x);
379 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
382 printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value, data, eval, registrar);
383 if( dump_extensions ) {
385 x = create_name((char*)value);
386 strncpy(x->name2,data,100);
389 ADD_LAST(con->switches,x);
393 ADD_LAST(con->eswitches,x);
398 void ast_merge_contexts_and_delete(void)
401 printf("Executed ast_merge_contexts_and_delete();\n");
404 void ast_context_verify_includes(void)
407 printf("Executed ast_context_verify_includes();\n");
410 struct ast_context * ast_walk_contexts(void)
413 printf("Executed ast_walk_contexts();\n");
417 void ast_cli_unregister_multiple(void)
420 printf("Executed ast_cli_unregister_multiple();\n");
423 void ast_context_destroy(void)
426 printf("Executed ast_context_destroy();\n");
429 const char *ast_get_context_name(struct ast_context *con);
430 const char *ast_get_context_name(struct ast_context *con)
432 return con ? con->name : NULL;
435 struct ast_exten *ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten);
436 struct ast_exten *ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
441 struct ast_include *ast_walk_context_includes(struct ast_context *con, struct ast_include *inc);
442 struct ast_include *ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
447 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip);
448 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip)
453 struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
454 struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw)
459 void filter_leading_space_from_exprs(char *str)
461 /* Mainly for aesthetics */
462 char *t, *v, *u = str;
466 if( *u == '$' && *(u+1) == '[' ) {
468 while( *t == '\n' || *t == '\r' || *t == '\t' || *t == ' ' ) {
481 void filter_newlines(char *str)
483 /* remove all newlines, returns */
486 if( *t == '\n' || *t == '\r' ) {
487 *t = ' '; /* just replace newlines and returns with spaces; they act as
488 token separators, and just blindly removing them could be
496 extern struct module_symbols mod_data;
497 int ael_external_load_module(void);
500 int main(int argc, char **argv)
504 struct ast_context *lp,*lp2;
506 for(i=1;i<argc;i++) {
507 if( argv[i][0] == '-' && argv[i][1] == 'n' )
509 if( argv[i][0] == '-' && argv[i][1] == 'q' ) {
513 if( argv[i][0] == '-' && argv[i][1] == 'd' )
515 if( argv[i][0] == '-' && argv[i][1] == 'w' )
520 printf("\n(If you find progress and other non-error messages irritating, you can use -q to suppress them)\n");
522 printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n");
524 printf("\n(You can use the -d option if you want to use the current working directory as the CONFIG_DIR. I will look in this dir for extensions.ael* and its included files)\n\n");
525 if( !dump_extensions )
526 printf("\n(You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)\n");
530 strcpy(config_dir, ".");
531 localized_use_local_dir();
534 strcpy(config_dir, "/etc/asterisk");
535 localized_use_conf_dir();
537 strcpy(var_dir, "/var/lib/asterisk");
539 if( dump_extensions ) {
540 dumpfile = fopen("extensions.conf.aeldump","w");
542 printf("\n\nSorry, cannot open extensions.conf.aeldump for writing! Correct the situation and try again!\n\n");
550 ael_external_load_module();
552 ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors);
554 if( dump_extensions && dumpfile ) {
556 for( lp = context_list; lp; lp = lp->next ) { /* print out any contexts that didn't have any
557 extensions in them */
558 if( lp->extension_count == 0 ) {
560 fprintf(dumpfile,"\n\n[%s]\n", lp->name);
562 for(n=lp->ignorepats;n;n=n->next) {
563 fprintf(dumpfile, "ignorepat => %s\n", n->name);
565 for(n=lp->includes;n;n=n->next) {
566 fprintf(dumpfile, "include => %s\n", n->name);
568 for(n=lp->switches;n;n=n->next) {
569 fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
571 for(n=lp->eswitches;n;n=n->next) {
572 fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
578 if( dump_extensions && dumpfile )
581 for( lp = context_list; lp; lp = lp2 ) { /* free the ast_context structs */
585 destroy_namelist(lp->includes);
586 destroy_namelist(lp->ignorepats);
587 destroy_namelist(lp->switches);
588 destroy_namelist(lp->eswitches);
596 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
598 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
603 unsigned int ast_hashtab_hash_contexts(const void *obj);
605 unsigned int ast_hashtab_hash_contexts(const void *obj)
611 #if !defined(LOW_MEMORY)
612 void ast_mark_lock_acquired(void *lock_addr)
616 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
620 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
621 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
625 int __ast_bt_get_addresses(struct ast_bt *bt)
630 char **__ast_bt_get_symbols(void **addresses, size_t num_frames)
632 char **foo = calloc(num_frames, sizeof(char *) + 1);
635 for (i = 0; i < num_frames; i++) {
636 foo[i] = (char *) foo + sizeof(char *) * num_frames;
642 void ast_remove_lock_info(void *lock_addr)
646 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
647 int line_num, const char *func, const char *lock_name, void *lock_addr)
650 #endif /* HAVE_BKTR */
651 #endif /* !defined(LOW_MEMORY) */
652 #endif /* DEBUG_THREADS */