?? pval.c
字號:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2006, Digium, Inc. * * Steve Murphy <murf@parsetree.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2. * */#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 168747 $")#include <sys/types.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <regex.h>#include <sys/stat.h>#include "asterisk/pbx.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/logger.h"#include "asterisk/cli.h"#include "asterisk/app.h"#include "asterisk/channel.h"#include "asterisk/callerid.h"#include "asterisk/pval.h"#include "asterisk/ael_structs.h"#ifdef AAL_ARGCHECK#include "asterisk/argdesc.h"#endif#include "asterisk/utils.h"extern int localized_pbx_load_module(void);static char expr_output[2096];#define AST_PBX_MAX_STACK 128/* these functions are in ../ast_expr2.fl */static int errs, warns;static int notes;#ifdef STANDALONEstatic int extensions_dot_conf_loaded = 0;#endifstatic char *registrar = "pbx_ael";static pval *current_db;static pval *current_context;static pval *current_extension;static const char *match_context;static const char *match_exten;static const char *match_label;static int in_abstract_context;static int count_labels; /* true, put matcher in label counting mode */static int label_count; /* labels are only meant to be counted in a context or exten */static int return_on_context_match;static pval *last_matched_label;struct pval *match_pval(pval *item);static void check_timerange(pval *p);static void check_dow(pval *DOW);static void check_day(pval *DAY);static void check_month(pval *MON);static void check_expr2_input(pval *expr, char *str);static int extension_matches(pval *here, const char *exten, const char *pattern);static void check_goto(pval *item);static void find_pval_goto_item(pval *item, int lev);static void find_pval_gotos(pval *item, int lev);static int check_break(pval *item);static int check_continue(pval *item);static void check_label(pval *item);static void check_macro_returns(pval *macro);static struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_cont);static struct pval *find_first_label_in_current_context(char *label, pval *curr_cont);static void print_pval_list(FILE *fin, pval *item, int depth);static struct pval *find_label_in_current_extension(const char *label, pval *curr_ext);static struct pval *find_label_in_current_db(const char *context, const char *exten, const char *label);static pval *get_goto_target(pval *item);static int label_inside_case(pval *label);static void attach_exten(struct ael_extension **list, struct ael_extension *newmem);static void fix_gotos_in_extensions(struct ael_extension *exten);static pval *get_extension_or_contxt(pval *p);static pval *get_contxt(pval *p);static void remove_spaces_before_equals(char *str);/* PRETTY PRINTER FOR AEL: ============================================================================= */static void print_pval(FILE *fin, pval *item, int depth){ int i; pval *lp; for (i=0; i<depth; i++) { fprintf(fin, "\t"); /* depth == indentation */ } switch ( item->type ) { case PV_WORD: fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */ break; case PV_MACRO: fprintf(fin,"macro %s(", item->u1.str); for (lp=item->u2.arglist; lp; lp=lp->next) { if (lp != item->u2.arglist ) fprintf(fin,", "); fprintf(fin,"%s", lp->u1.str); } fprintf(fin,") {\n"); print_pval_list(fin,item->u3.macro_statements,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"};\n\n"); break; case PV_CONTEXT: if ( item->u3.abstract ) fprintf(fin,"abstract context %s {\n", item->u1.str); else fprintf(fin,"context %s {\n", item->u1.str); print_pval_list(fin,item->u2.statements,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"};\n\n"); break; case PV_MACRO_CALL: fprintf(fin,"&%s(", item->u1.str); for (lp=item->u2.arglist; lp; lp=lp->next) { if ( lp != item->u2.arglist ) fprintf(fin,", "); fprintf(fin,"%s", lp->u1.str); } fprintf(fin,");\n"); break; case PV_APPLICATION_CALL: fprintf(fin,"%s(", item->u1.str); for (lp=item->u2.arglist; lp; lp=lp->next) { if ( lp != item->u2.arglist ) fprintf(fin,","); fprintf(fin,"%s", lp->u1.str); } fprintf(fin,");\n"); break; case PV_CASE: fprintf(fin,"case %s:\n", item->u1.str); print_pval_list(fin,item->u2.statements, depth+1); break; case PV_PATTERN: fprintf(fin,"pattern %s:\n", item->u1.str); print_pval_list(fin,item->u2.statements, depth+1); break; case PV_DEFAULT: fprintf(fin,"default:\n"); print_pval_list(fin,item->u2.statements, depth+1); break; case PV_CATCH: fprintf(fin,"catch %s {\n", item->u1.str); print_pval_list(fin,item->u2.statements, depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"};\n"); break; case PV_SWITCHES: fprintf(fin,"switches {\n"); print_pval_list(fin,item->u1.list,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"};\n"); break; case PV_ESWITCHES: fprintf(fin,"eswitches {\n"); print_pval_list(fin,item->u1.list,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"};\n"); break; case PV_INCLUDES: fprintf(fin,"includes {\n"); for (lp=item->u1.list; lp; lp=lp->next) { for (i=0; i<depth+1; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */ if (lp->u2.arglist) fprintf(fin,"|%s|%s|%s|%s", lp->u2.arglist->u1.str, lp->u2.arglist->next->u1.str, lp->u2.arglist->next->next->u1.str, lp->u2.arglist->next->next->next->u1.str ); fprintf(fin,";\n"); /* usually, words are encapsulated in something else */ } for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"};\n"); break; case PV_STATEMENTBLOCK: fprintf(fin,"{\n"); print_pval_list(fin,item->u1.list, depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"}\n"); break; case PV_VARDEC: fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val); break; case PV_LOCALVARDEC: fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val); break; case PV_GOTO: fprintf(fin,"goto %s", item->u1.list->u1.str); if ( item->u1.list->next ) fprintf(fin,",%s", item->u1.list->next->u1.str); if ( item->u1.list->next && item->u1.list->next->next ) fprintf(fin,",%s", item->u1.list->next->next->u1.str); fprintf(fin,"\n"); break; case PV_LABEL: fprintf(fin,"%s:\n", item->u1.str); break; case PV_FOR: fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc); print_pval_list(fin,item->u4.for_statements,depth+1); break; case PV_WHILE: fprintf(fin,"while (%s)\n", item->u1.str); print_pval_list(fin,item->u2.statements,depth+1); break; case PV_BREAK: fprintf(fin,"break;\n"); break; case PV_RETURN: fprintf(fin,"return;\n"); break; case PV_CONTINUE: fprintf(fin,"continue;\n"); break; case PV_RANDOM: case PV_IFTIME: case PV_IF: if ( item->type == PV_IFTIME ) { fprintf(fin,"ifTime ( %s|%s|%s|%s )\n", item->u1.list->u1.str, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->next->next->next->u1.str ); } else if ( item->type == PV_RANDOM ) { fprintf(fin,"random ( %s )\n", item->u1.str ); } else fprintf(fin,"if ( %s )\n", item->u1.str); if ( item->u2.statements && item->u2.statements->next ) { for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"{\n"); print_pval_list(fin,item->u2.statements,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } if ( item->u3.else_statements ) fprintf(fin,"}\n"); else fprintf(fin,"};\n"); } else if (item->u2.statements ) { print_pval_list(fin,item->u2.statements,depth+1); } else { if (item->u3.else_statements ) fprintf(fin, " {} "); else fprintf(fin, " {}; "); } if ( item->u3.else_statements ) { for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"else\n"); print_pval_list(fin,item->u3.else_statements, depth); } break; case PV_SWITCH: fprintf(fin,"switch( %s ) {\n", item->u1.str); print_pval_list(fin,item->u2.statements,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"}\n"); break; case PV_EXTENSION: if ( item->u4.regexten ) fprintf(fin, "regexten "); if ( item->u3.hints ) fprintf(fin,"hints(%s) ", item->u3.hints); fprintf(fin,"%s => ", item->u1.str); print_pval_list(fin,item->u2.statements,depth+1); fprintf(fin,"\n"); break; case PV_IGNOREPAT: fprintf(fin,"ignorepat => %s;\n", item->u1.str); break; case PV_GLOBALS: fprintf(fin,"globals {\n"); print_pval_list(fin,item->u1.statements,depth+1); for (i=0; i<depth; i++) { fprintf(fin,"\t"); /* depth == indentation */ } fprintf(fin,"}\n"); break; }}static void print_pval_list(FILE *fin, pval *item, int depth){ pval *i; for (i=item; i; i=i->next) { print_pval(fin, i, depth); }}void ael2_print(char *fname, pval *tree){ FILE *fin = fopen(fname,"w"); if ( !fin ) { ast_log(LOG_ERROR, "Couldn't open %s for writing.\n", fname); return; } print_pval_list(fin, tree, 0); fclose(fin);}/* EMPTY TEMPLATE FUNCS FOR AEL TRAVERSAL: ============================================================================= */void traverse_pval_template(pval *item, int depth);void traverse_pval_item_template(pval *item, int depth);void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy for a pretty print (indentation), but you may not need it */{ pval *lp; switch ( item->type ) { case PV_WORD: /* fields: item->u1.str == string associated with this (word). */ break; case PV_MACRO: /* fields: item->u1.str == name of macro item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg item->u3.macro_statements == pval list of statements in macro body. */ for (lp=item->u2.arglist; lp; lp=lp->next) { } traverse_pval_item_template(item->u3.macro_statements,depth+1); break; case PV_CONTEXT: /* fields: item->u1.str == name of context item->u2.statements == pval list of statements in context body item->u3.abstract == int 1 if an abstract keyword were present */ traverse_pval_item_template(item->u2.statements,depth+1); break; case PV_MACRO_CALL: /* fields: item->u1.str == name of macro to call item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg */ for (lp=item->u2.arglist; lp; lp=lp->next) { } break; case PV_APPLICATION_CALL: /* fields: item->u1.str == name of application to call item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user item->u2.arglist->u1.str == argument item->u2.arglist->next == next arg */ for (lp=item->u2.arglist; lp; lp=lp->next) { } break; case PV_CASE: /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ traverse_pval_item_template(item->u2.statements,depth+1); break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -