Fri Jul 24 00:41:00 2009

Asterisk developer's documentation


pbx_ael.c

Go to the documentation of this file.
00001 /* 
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2006, Digium, Inc.
00005  *
00006  * Steve Murphy <murf@parsetree.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2.
00022  * 
00023  */
00024 
00025 /*** MODULEINFO
00026    <depend>res_ael_share</depend>
00027  ***/
00028 
00029 #include "asterisk.h"
00030 
00031 #if !defined(STANDALONE)
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 165794 $")
00033 #endif
00034 
00035 #include <ctype.h>
00036 #include <regex.h>
00037 #include <sys/stat.h>
00038 
00039 #ifdef STANDALONE
00040 #ifdef HAVE_MTX_PROFILE
00041 static int mtx_prof = -1; /* helps the standalone compile with the mtx_prof flag on */
00042 #endif
00043 #endif
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/config.h"
00046 #include "asterisk/module.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/cli.h"
00049 #include "asterisk/app.h"
00050 #include "asterisk/callerid.h"
00051 #include "asterisk/hashtab.h"
00052 #include "asterisk/ael_structs.h"
00053 #include "asterisk/pval.h"
00054 #ifdef AAL_ARGCHECK
00055 #include "asterisk/argdesc.h"
00056 #endif
00057 
00058 /* these functions are in ../ast_expr2.fl */
00059 
00060 #define DEBUG_READ   (1 << 0)
00061 #define DEBUG_TOKENS (1 << 1)
00062 #define DEBUG_MACROS (1 << 2)
00063 #define DEBUG_CONTEXTS (1 << 3)
00064 
00065 static char *config = "extensions.ael";
00066 static char *registrar = "pbx_ael";
00067 static int pbx_load_module(void);
00068 
00069 #ifndef AAL_ARGCHECK
00070 /* for the time being, short circuit all the AAL related structures
00071    without permanently removing the code; after/during the AAL 
00072    development, this code can be properly re-instated 
00073 */
00074 
00075 #endif
00076 
00077 #ifdef AAL_ARGCHECK
00078 int option_matches_j( struct argdesc *should, pval *is, struct argapp *app);
00079 int option_matches( struct argdesc *should, pval *is, struct argapp *app);
00080 int ael_is_funcname(char *name);
00081 #endif
00082 
00083 int check_app_args(pval *appcall, pval *arglist, struct argapp *app);
00084 void check_pval(pval *item, struct argapp *apps, int in_globals);
00085 void check_pval_item(pval *item, struct argapp *apps, int in_globals);
00086 void check_switch_expr(pval *item, struct argapp *apps);
00087 void ast_expr_register_extra_error_info(char *errmsg);
00088 void ast_expr_clear_extra_error_info(void);
00089 struct pval *find_macro(char *name);
00090 struct pval *find_context(char *name);
00091 struct pval *find_context(char *name);
00092 struct pval *find_macro(char *name);
00093 struct ael_priority *new_prio(void);
00094 struct ael_extension *new_exten(void);
00095 void destroy_extensions(struct ael_extension *exten);
00096 void set_priorities(struct ael_extension *exten);
00097 void add_extensions(struct ael_extension *exten);
00098 void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root);
00099 void destroy_pval(pval *item);
00100 void destroy_pval_item(pval *item);
00101 int is_float(char *arg );
00102 int is_int(char *arg );
00103 int is_empty(char *arg);
00104 
00105 /* static void substitute_commas(char *str); */
00106 
00107 static int aeldebug = 0;
00108 
00109 /* interface stuff */
00110 
00111 /* if all the below are static, who cares if they are present? */
00112 
00113 static int pbx_load_module(void)
00114 {
00115    int errs=0, sem_err=0, sem_warn=0, sem_note=0;
00116    char *rfilename;
00117    struct ast_context *local_contexts=NULL, *con;
00118    struct ast_hashtab *local_table=NULL;
00119    
00120    struct pval *parse_tree;
00121 
00122    ast_log(LOG_NOTICE, "Starting AEL load process.\n");
00123    if (config[0] == '/')
00124       rfilename = (char *)config;
00125    else {
00126       rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
00127       sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config);
00128    }
00129    if (access(rfilename,R_OK) != 0) {
00130       ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename);
00131       return AST_MODULE_LOAD_DECLINE;
00132    }
00133    
00134    parse_tree = ael2_parse(rfilename, &errs);
00135    ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename);
00136    ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note);
00137    if (errs == 0 && sem_err == 0) {
00138       ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename);
00139       local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00140       ast_compile_ael2(&local_contexts, local_table, parse_tree);
00141       ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename);
00142       
00143       ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
00144       local_table = NULL; /* it's the dialplan global now */
00145       local_contexts = NULL;
00146       ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename);
00147       for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
00148          ast_context_verify_includes(con);
00149       ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename);
00150    } else {
00151       ast_log(LOG_ERROR, "Sorry, but %d syntax errors and %d semantic errors were detected. It doesn't make sense to compile.\n", errs, sem_err);
00152       destroy_pval(parse_tree); /* free up the memory */
00153       return AST_MODULE_LOAD_DECLINE;
00154    }
00155    destroy_pval(parse_tree); /* free up the memory */
00156    
00157    return AST_MODULE_LOAD_SUCCESS;
00158 }
00159 
00160 /* CLI interface */
00161 static char *handle_cli_ael_debug_multiple_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00162 {
00163    switch (cmd) {
00164    case CLI_INIT:
00165       e->command = "ael debug [read|tokens|macros|contexts|off]";
00166       e->usage =
00167          "Usage: ael debug [read|tokens|macros|contexts|off]\n"
00168          "       Enable AEL read, token, macro, or context debugging,\n"
00169          "       or disable all AEL debugging messages.  Note: this\n"
00170          "       currently does nothing.\n";
00171       return NULL;
00172    case CLI_GENERATE:
00173       return NULL;
00174    }
00175 
00176    if (a->argc != 3)
00177       return CLI_SHOWUSAGE;
00178 
00179    if (!strcasecmp(a->argv[2], "read"))
00180       aeldebug |= DEBUG_READ;
00181    else if (!strcasecmp(a->argv[2], "tokens"))
00182       aeldebug |= DEBUG_TOKENS;
00183    else if (!strcasecmp(a->argv[2], "macros"))
00184       aeldebug |= DEBUG_MACROS;
00185    else if (!strcasecmp(a->argv[2], "contexts"))
00186       aeldebug |= DEBUG_CONTEXTS;
00187    else if (!strcasecmp(a->argv[2], "off"))
00188       aeldebug = 0;
00189    else
00190       return CLI_SHOWUSAGE;
00191 
00192    return CLI_SUCCESS;
00193 }
00194 
00195 static char *handle_cli_ael_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00196 {
00197    switch (cmd) {
00198    case CLI_INIT:
00199       e->command = "ael set debug {read|tokens|macros|contexts|off}";
00200       e->usage =
00201          "Usage: ael set debug {read|tokens|macros|contexts|off}\n"
00202          "       Enable AEL read, token, macro, or context debugging,\n"
00203          "       or disable all AEL debugging messages.  Note: this\n"
00204          "       currently does nothing.\n";
00205       return NULL;
00206    case CLI_GENERATE:
00207       return NULL;
00208    }
00209 
00210    if (a->argc != e->args)
00211       return CLI_SHOWUSAGE;
00212 
00213    if (!strcasecmp(a->argv[3], "read"))
00214       aeldebug |= DEBUG_READ;
00215    else if (!strcasecmp(a->argv[3], "tokens"))
00216       aeldebug |= DEBUG_TOKENS;
00217    else if (!strcasecmp(a->argv[3], "macros"))
00218       aeldebug |= DEBUG_MACROS;
00219    else if (!strcasecmp(a->argv[3], "contexts"))
00220       aeldebug |= DEBUG_CONTEXTS;
00221    else if (!strcasecmp(a->argv[3], "off"))
00222       aeldebug = 0;
00223    else
00224       return CLI_SHOWUSAGE;
00225 
00226    return CLI_SUCCESS;
00227 }
00228 
00229 static char *handle_cli_ael_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00230 {
00231    switch (cmd) {
00232    case CLI_INIT:
00233       e->command = "ael reload";
00234       e->usage =
00235          "Usage: ael reload\n"
00236          "       Reloads AEL configuration.\n";
00237       return NULL;
00238    case CLI_GENERATE:
00239       return NULL;
00240    }
00241 
00242    if (a->argc != 2)
00243       return CLI_SHOWUSAGE;
00244 
00245    return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS);
00246 }
00247 
00248 static struct ast_cli_entry cli_ael_debug_multiple_deprecated = AST_CLI_DEFINE(handle_cli_ael_debug_multiple_deprecated, "Enable AEL debugging flags");
00249 static struct ast_cli_entry cli_ael[] = {
00250    AST_CLI_DEFINE(handle_cli_ael_reload,    "Reload AEL configuration"),
00251    AST_CLI_DEFINE(handle_cli_ael_set_debug, "Enable AEL debugging flags", .deprecate_cmd = &cli_ael_debug_multiple_deprecated)
00252 };
00253 
00254 static int unload_module(void)
00255 {
00256    ast_context_destroy(NULL, registrar);
00257    ast_cli_unregister_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry));
00258    return 0;
00259 }
00260 
00261 static int load_module(void)
00262 {
00263    ast_cli_register_multiple(cli_ael, sizeof(cli_ael) / sizeof(struct ast_cli_entry));
00264    return (pbx_load_module());
00265 }
00266 
00267 static int reload(void)
00268 {
00269    return pbx_load_module();
00270 }
00271 
00272 #ifdef STANDALONE
00273 #define AST_MODULE "ael"
00274 int ael_external_load_module(void);
00275 int ael_external_load_module(void)
00276 {
00277         pbx_load_module();
00278         return 1;
00279 }
00280 #endif
00281 
00282 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk Extension Language Compiler",
00283       .load = load_module,
00284       .unload = unload_module,
00285       .reload = reload,
00286           );
00287 
00288 #ifdef AAL_ARGCHECK
00289 static char *ael_funclist[] =
00290 {
00291    "AGENT",
00292    "ARRAY",
00293    "BASE64_DECODE",
00294    "BASE64_ENCODE",
00295    "CALLERID",
00296    "CDR",
00297    "CHANNEL",
00298    "CHECKSIPDOMAIN",
00299    "CHECK_MD5",
00300    "CURL",
00301    "CUT",
00302    "DB",
00303    "DB_EXISTS",
00304    "DUNDILOOKUP",
00305    "ENUMLOOKUP",
00306    "ENV",
00307    "EVAL",
00308    "EXISTS",
00309    "FIELDQTY",
00310    "FILTER",
00311    "GROUP",
00312    "GROUP_COUNT",
00313    "GROUP_LIST",
00314    "GROUP_MATCH_COUNT",
00315    "IAXPEER",
00316    "IF",
00317    "IFTIME",
00318    "ISNULL",
00319    "KEYPADHASH",
00320    "LANGUAGE",
00321    "LEN",
00322    "MATH",
00323    "MD5",
00324    "MUSICCLASS",
00325    "QUEUEAGENTCOUNT",
00326    "QUEUE_MEMBER_COUNT",
00327    "QUEUE_MEMBER_LIST",
00328    "QUOTE",
00329    "RAND",
00330    "REGEX",
00331    "SET",
00332    "SHA1",
00333    "SIPCHANINFO",
00334    "SIPPEER",
00335    "SIP_HEADER",
00336    "SORT",
00337    "STAT",
00338    "STRFTIME",
00339    "STRPTIME",
00340    "TIMEOUT",
00341    "TXTCIDNAME",
00342    "URIDECODE",
00343    "URIENCODE",
00344    "VMCOUNT"
00345 };
00346 
00347 
00348 int ael_is_funcname(char *name)
00349 {
00350    int s,t;
00351    t = sizeof(ael_funclist)/sizeof(char*);
00352    s = 0;
00353    while ((s < t) && strcasecmp(name, ael_funclist[s])) 
00354       s++;
00355    if ( s < t )
00356       return 1;
00357    else
00358       return 0;
00359 }
00360 #endif    

Generated on Fri Jul 24 00:41:00 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7