14 #include "asterisk/ast_expr.h"
15 #include "asterisk/channel.h"
16 #include "asterisk/module.h"
17 #include "asterisk/app.h"
18 #include "asterisk/ael_structs.h"
21 <depend>pbx_ael</depend>
28 struct namelist
*next
;
36 struct namelist
*includes
;
37 struct namelist
*ignorepats
;
38 struct namelist
*switches
;
39 struct namelist
*eswitches
;
41 struct namelist
*includes_last
;
42 struct namelist
*ignorepats_last
;
43 struct namelist
*switches_last
;
44 struct namelist
*eswitches_last
;
46 struct ast_context
*next
;
49 #define ADD_LAST(headptr,memptr) if(!headptr){ headptr=(memptr); (headptr##_last)=(memptr);} else {(headptr##_last)->next = (memptr); (headptr##_last) = (memptr);}
51 void destroy_namelist(struct namelist
*x
);
52 void destroy_namelist(struct namelist
*x
)
54 struct namelist
*z
,*z2
;
63 struct namelist
*create_name(const char *name
);
64 struct namelist
*create_name(const char *name
)
66 struct namelist
*x
= calloc(1, sizeof(*x
));
69 strncpy(x
->name
, name
, sizeof(x
->name
) - 1);
73 struct ast_context
*context_list
;
74 struct ast_context
*last_context
;
75 struct namelist
*globalvars
;
76 struct namelist
*globalvars_last
;
78 int conts
=0, extens
=0, priors
=0;
79 char last_exten
[18000];
80 char ast_config_AST_CONFIG_DIR
[PATH_MAX
];
81 char ast_config_AST_VAR_DIR
[PATH_MAX
];
83 void ast_cli_register_multiple(void);
84 int ast_add_extension2(struct ast_context
*con
,
85 int replace
, const char *extension
, int priority
, const char *label
, const char *callerid
,
86 const char *application
, void *data
, void (*datad
)(void *),
87 const char *registrar
);
88 void pbx_builtin_setvar(void *chan
, void *data
);
89 struct ast_context
* ast_context_create(void **extcontexts
, const char *name
, const char *registrar
);
90 struct ast_context
* ast_context_find_or_create(void **extcontexts
, const char *name
, const char *registrar
);
91 void ast_context_add_ignorepat2(struct ast_context
*con
, const char *value
, const char *registrar
);
92 void ast_context_add_include2(struct ast_context
*con
, const char *value
, const char *registrar
);
93 void ast_context_add_switch2(struct ast_context
*con
, const char *value
, const char *data
, int eval
, const char *registrar
);
94 void ast_merge_contexts_and_delete(void);
95 void ast_context_verify_includes(void);
96 struct ast_context
* ast_walk_contexts(void);
97 void ast_cli_unregister_multiple(void);
98 void ast_context_destroy(void);
99 void ast_log(int level
, const char *file
, int line
, const char *function
, const char *fmt
, ...);
100 char *ast_process_quotes_and_slashes(char *start
, char find
, char replace_with
);
101 void ast_verbose(const char *fmt
, ...);
102 struct ast_app
*pbx_findapp(const char *app
);
103 void filter_leading_space_from_exprs(char *str
);
104 void filter_newlines(char *str
);
105 static int quiet
= 0;
106 static int no_comp
= 0;
107 static int use_curr_dir
= 0;
108 static int dump_extensions
= 0;
109 static int FIRST_TIME
= 0;
110 static FILE *dumpfile
;
112 struct ast_app
*pbx_findapp(const char *app
)
114 return (struct ast_app
*)1; /* so as not to trigger an error */
117 int ast_loader_register(int (*updater
)(void))
122 int ast_loader_unregister(int (*updater
)(void))
126 void ast_module_register(const struct ast_module_info
*x
)
130 void ast_module_unregister(const struct ast_module_info
*x
)
135 void ast_cli_register_multiple(void)
138 printf("Executed ast_cli_register_multiple();\n");
141 void pbx_substitute_variables_helper(struct ast_channel
*c
,const char *cp1
,char *cp2
,int count
);
142 void pbx_substitute_variables_helper(struct ast_channel
*c
,const char *cp1
,char *cp2
,int count
)
145 strncpy(cp2
,cp1
,AST_MAX_EXTENSION
); /* Right now, this routine is ONLY being called for
146 a possible var substitution on extension names,
152 int ast_add_extension2(struct ast_context
*con
,
153 int replace
, const char *extension
, int priority
, const char *label
, const char *callerid
,
154 const char *application
, void *data
, void (*datad
)(void *),
155 const char *registrar
)
158 con
->extension_count
++;
159 if (strcmp(extension
,last_exten
) != 0) {
161 strcpy(last_exten
, extension
);
170 application
= "(null)";
174 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",
175 con
->name
, replace
, extension
, priority
, label
, callerid
, application
, (data
?(char*)data
:"(null)"), registrar
);
177 if( dump_extensions
&& dumpfile
) {
179 char *data2
,*data3
=0;
186 fprintf(dumpfile
,"[globals]\n");
188 for(n
=globalvars
;n
;n
=n
->next
) {
189 fprintf(dumpfile
, "%s\n", n
->name
);
193 /* print out each extension , possibly the context header also */
194 if( con
!= last_context
) {
195 fprintf(dumpfile
,"\n\n[%s]\n", con
->name
);
197 for(n
=con
->ignorepats
;n
;n
=n
->next
) {
198 fprintf(dumpfile
, "ignorepat => %s\n", n
->name
);
200 for(n
=con
->includes
;n
;n
=n
->next
) {
201 fprintf(dumpfile
, "include => %s\n", n
->name
);
203 for(n
=con
->switches
;n
;n
=n
->next
) {
204 fprintf(dumpfile
, "switch => %s/%s\n", n
->name
, n
->name2
);
206 for(n
=con
->eswitches
;n
;n
=n
->next
) {
207 fprintf(dumpfile
, "eswitch => %s/%s\n", n
->name
, n
->name2
);
212 filter_newlines((char*)data
);
213 filter_leading_space_from_exprs((char*)data
);
215 /* compiling turns commas into vertical bars in the app data, and also removes the backslash from before escaped commas;
216 we have to restore the escaping backslash in front of any commas; the vertical bars are OK to leave as-is */
217 for (data2
= data
; *data2
; data2
++) {
219 commacount
++; /* we need to know how much bigger the string will grow-- one backslash for each comma */
225 data2
= (char*)malloc(strlen(data
)+commacount
+1);
231 *d4
++ = '\\'; /* put a backslash in front of each comma */
234 *d4
++ = *d3
++; /* or just copy the char */
236 *d4
++ = 0; /* cap off the new string */
241 if( strcmp(label
,"(null)") != 0 )
242 fprintf(dumpfile
,"exten => %s,%d(%s),%s(%s)\n", extension
, priority
, label
, application
, (char*)data
);
244 fprintf(dumpfile
,"exten => %s,%d,%s(%s)\n", extension
, priority
, application
, (char*)data
);
249 data
= data3
; /* restore data to pre-messedup state */
254 if( strcmp(label
,"(null)") != 0 )
255 fprintf(dumpfile
,"exten => %s,%d(%s),%s\n", extension
, priority
, label
, application
);
257 fprintf(dumpfile
,"exten => %s,%d,%s\n", extension
, priority
, application
);
261 /* since add_extension2 is responsible for the malloc'd data stuff */
267 void pbx_builtin_setvar(void *chan
, void *data
)
269 struct namelist
*x
= create_name(data
);
271 printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data
);
273 if( dump_extensions
) {
274 x
= create_name(data
);
275 ADD_LAST(globalvars
,x
);
280 struct ast_context
* ast_context_create(void **extcontexts
, const char *name
, const char *registrar
)
282 struct ast_context
*x
= calloc(1, sizeof(*x
));
285 x
->next
= context_list
;
288 printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name
, registrar
);
290 strncpy(x
->name
, name
, sizeof(x
->name
) - 1);
291 strncpy(x
->registrar
, registrar
, sizeof(x
->registrar
) - 1);
295 struct ast_context
* ast_context_find_or_create(void **extcontexts
, const char *name
, const char *registrar
)
297 struct ast_context
*x
= calloc(1, sizeof(*x
));
300 x
->next
= context_list
;
303 printf("Executed ast_context_find_or_create(conts, name=%s, registrar=%s);\n", name
, registrar
);
305 strncpy(x
->name
, name
, sizeof(x
->name
) - 1);
306 strncpy(x
->registrar
, registrar
, sizeof(x
->registrar
) - 1);
310 void ast_context_add_ignorepat2(struct ast_context
*con
, const char *value
, const char *registrar
)
313 printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value
, registrar
);
314 if( dump_extensions
) {
316 x
= create_name(value
);
317 ADD_LAST(con
->ignorepats
,x
);
321 void ast_context_add_include2(struct ast_context
*con
, const char *value
, const char *registrar
)
324 printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value
, registrar
);
325 if( dump_extensions
) {
327 x
= create_name((char*)value
);
328 ADD_LAST(con
->includes
,x
);
332 void ast_context_add_switch2(struct ast_context
*con
, const char *value
, const char *data
, int eval
, const char *registrar
)
335 printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value
, data
, eval
, registrar
);
336 if( dump_extensions
) {
338 x
= create_name((char*)value
);
339 strncpy(x
->name2
,data
,100);
342 ADD_LAST(con
->switches
,x
);
346 ADD_LAST(con
->eswitches
,x
);
351 void ast_merge_contexts_and_delete(void)
354 printf("Executed ast_merge_contexts_and_delete();\n");
357 void ast_context_verify_includes(void)
360 printf("Executed ast_context_verify_includes();\n");
363 struct ast_context
* ast_walk_contexts(void)
366 printf("Executed ast_walk_contexts();\n");
370 void ast_cli_unregister_multiple(void)
373 printf("Executed ast_cli_unregister_multiple();\n");
376 void ast_context_destroy(void)
379 printf("Executed ast_context_destroy();\n");
382 void ast_log(int level
, const char *file
, int line
, const char *function
, const char *fmt
, ...)
386 if( !quiet
|| level
> 2 ) {
387 printf("LOG: lev:%d file:%s line:%d func: %s ",
388 level
, file
, line
, function
);
395 void ast_verbose(const char *fmt
, ...)
406 char *ast_process_quotes_and_slashes(char *start
, char find
, char replace_with
)
408 char *dataPut
= start
;
412 for (; *start
; start
++) {
414 *dataPut
++ = *start
; /* Always goes verbatim */
417 if (*start
== '\\') {
418 inEscape
= 1; /* Do not copy \ into the data */
419 } else if (*start
== '\'') {
420 inQuotes
= 1-inQuotes
; /* Do not copy ' into the data */
422 /* Replace , with |, unless in quotes */
423 *dataPut
++ = inQuotes
? *start
: ((*start
==find
) ? replace_with
: *start
);
427 if (start
!= dataPut
)
432 void filter_leading_space_from_exprs(char *str
)
434 /* Mainly for aesthetics */
435 char *t
, *v
, *u
= str
;
439 if( *u
== '$' && *(u
+1) == '[' ) {
441 while( *t
== '\n' || *t
== '\r' || *t
== '\t' || *t
== ' ' ) {
454 void filter_newlines(char *str
)
456 /* remove all newlines, returns */
459 if( *t
== '\n' || *t
== '\r' ) {
460 *t
= ' '; /* just replace newlines and returns with spaces; they act as
461 token separators, and just blindly removing them could be
469 extern struct module_symbols mod_data
;
470 extern int ael_external_load_module(void);
472 int main(int argc
, char **argv
)
476 struct ast_context
*lp
,*lp2
;
478 for(i
=1;i
<argc
;i
++) {
479 if( argv
[i
][0] == '-' && argv
[i
][1] == 'n' )
481 if( argv
[i
][0] == '-' && argv
[i
][1] == 'q' ) {
485 if( argv
[i
][0] == '-' && argv
[i
][1] == 'd' )
487 if( argv
[i
][0] == '-' && argv
[i
][1] == 'w' )
492 printf("\n(If you find progress and other non-error messages irritating, you can use -q to suppress them)\n");
494 printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n");
496 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");
497 if( !dump_extensions
)
498 printf("\n(You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)\n");
502 strcpy(ast_config_AST_CONFIG_DIR
, ".");
505 strcpy(ast_config_AST_CONFIG_DIR
, "/etc/asterisk");
507 strcpy(ast_config_AST_VAR_DIR
, "/var/lib/asterisk");
509 if( dump_extensions
) {
510 dumpfile
= fopen("extensions.conf.aeldump","w");
512 printf("\n\nSorry, cannot open extensions.conf.aeldump for writing! Correct the situation and try again!\n\n");
520 ael_external_load_module();
522 ast_log(4, "ael2_parse", __LINE__
, "main", "%d contexts, %d extensions, %d priorities\n", conts
, extens
, priors
);
524 if( dump_extensions
&& dumpfile
) {
526 for( lp
= context_list
; lp
; lp
= lp
->next
) { /* print out any contexts that didn't have any
527 extensions in them */
528 if( lp
->extension_count
== 0 ) {
530 fprintf(dumpfile
,"\n\n[%s]\n", lp
->name
);
532 for(n
=lp
->ignorepats
;n
;n
=n
->next
) {
533 fprintf(dumpfile
, "ignorepat => %s\n", n
->name
);
535 for(n
=lp
->includes
;n
;n
=n
->next
) {
536 fprintf(dumpfile
, "include => %s\n", n
->name
);
538 for(n
=lp
->switches
;n
;n
=n
->next
) {
539 fprintf(dumpfile
, "switch => %s/%s\n", n
->name
, n
->name2
);
541 for(n
=lp
->eswitches
;n
;n
=n
->next
) {
542 fprintf(dumpfile
, "eswitch => %s/%s\n", n
->name
, n
->name2
);
548 if( dump_extensions
&& dumpfile
)
551 for( lp
= context_list
; lp
; lp
= lp2
) { /* free the ast_context structs */
555 destroy_namelist(lp
->includes
);
556 destroy_namelist(lp
->ignorepats
);
557 destroy_namelist(lp
->switches
);
558 destroy_namelist(lp
->eswitches
);