[asterisk-commits] murf: branch murf/bug_7638 r58959 - in
/team/murf/bug_7638: main/ pbx/ utils/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Mar 15 20:44:47 MST 2007
Author: murf
Date: Thu Mar 15 22:44:47 2007
New Revision: 58959
URL: http://svn.digium.com/view/asterisk?view=rev&rev=58959
Log:
OK! I got an app to compile and link. Now on to conf2ael; I have to refactor it to use the stuff in extconf.c; I may need access to more funcs there.
Modified:
team/murf/bug_7638/main/pval.c
team/murf/bug_7638/pbx/pbx_ael.c
team/murf/bug_7638/utils/Makefile
team/murf/bug_7638/utils/ael_main.c
team/murf/bug_7638/utils/conf2ael.c
team/murf/bug_7638/utils/extconf.c
Modified: team/murf/bug_7638/main/pval.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/main/pval.c?view=diff&rev=58959&r1=58958&r2=58959
==============================================================================
--- team/murf/bug_7638/main/pval.c (original)
+++ team/murf/bug_7638/main/pval.c Thu Mar 15 22:44:47 2007
@@ -51,11 +51,13 @@
#endif
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;
+static int extensions_dot_conf_loaded = 0;
static char *registrar = "pbx_ael";
static pval *current_db;
@@ -100,6 +102,51 @@
static void remove_spaces_before_equals(char *str);
static void substitute_commas(char *str);
+/*!
+ * When looking up extensions, we can have different requests
+ * identified by the 'action' argument, as follows.
+ * Note that the coding is such that the low 4 bits are the
+ * third argument to extension_match_core.
+ */
+enum ext_match_t {
+ E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */
+ E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */
+ E_MATCH = 0x02, /* extension is an exact match */
+ E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
+ E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */
+ E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */
+};
+
+#define STATUS_NO_CONTEXT 1
+#define STATUS_NO_EXTENSION 2
+#define STATUS_NO_PRIORITY 3
+#define STATUS_NO_LABEL 4
+#define STATUS_SUCCESS 5
+
+/* request and result for pbx_find_extension */
+struct pbx_find_info {
+#if 0
+ const char *context;
+ const char *exten;
+ int priority;
+#endif
+
+ char *incstack[AST_PBX_MAX_STACK]; /* filled during the search */
+ int stacklen; /* modified during the search */
+ int status; /* set on return */
+ struct ast_switch *swo; /* set on return */
+ const char *data; /* set on return */
+ const char *foundcontext; /* set on return */
+};
+
+struct ast_exten *external_find_extension(struct ast_context *bypass,
+ struct pbx_find_info *q,
+ const char *context,
+ const char *exten,
+ int priority,
+ const char *label,
+ const char *callerid,
+ enum ext_match_t action);
/* I am adding this code to substitute commas with vertbars in the args to apps */
@@ -1330,11 +1377,19 @@
}
} else {
/* here is where code would go to check for target existence in extensions.conf files */
- extern int this_target_in_extensions_dot_conf(char *context, char *exten, char *label);
+ struct pbx_find_info pfiq;
+ extern int localized_pbx_load_module(void);
- if (!this_target_in_extensions_dot_conf(first->u1.str, second->u1.str, third->u1.str))
- ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: no context %s could be found that matches the goto target!\n",
- item->filename, item->startline, item->endline, item->u1.list->u1.str);
+ if (!extensions_dot_conf_loaded)
+ localized_pbx_load_module();
+
+ external_find_extension(NULL, &pfiq, first->u1.str, second->u1.str, atoi(third->u1.str),
+ atoi(third->u1.str) ? NULL : third->u1.str, NULL,
+ atoi(third->u1.str) ? E_MATCH : E_FINDLABEL);
+
+ if (pfiq.status != STATUS_SUCCESS)
+ ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s, not even in extensions.conf!\n",
+ item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
warns++;
}
} else {
@@ -2894,6 +2949,10 @@
str++;
}
}
+
+/* =============================================================================================== */
+/* "CODE" GENERATOR -- Convert the AEL representation to asterisk extension language */
+/* =============================================================================================== */
static void gen_match_to_pattern(char *pattern, char *result)
{
Modified: team/murf/bug_7638/pbx/pbx_ael.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/pbx/pbx_ael.c?view=diff&rev=58959&r1=58958&r2=58959
==============================================================================
--- team/murf/bug_7638/pbx/pbx_ael.c (original)
+++ team/murf/bug_7638/pbx/pbx_ael.c Thu Mar 15 22:44:47 2007
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2007, Digium, Inc.
+ * Copyright (C) 2006, Digium, Inc.
*
* Steve Murphy <murf at parsetree.com>
*
@@ -38,37 +38,113 @@
#include "asterisk/pbx.h"
#include "asterisk/config.h"
-#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/callerid.h"
#include "asterisk/ael_structs.h"
+#ifdef AAL_ARGCHECK
+#include "asterisk/argdesc.h"
+#endif
+
+/* these functions are in ../ast_expr2.fl */
#define DEBUG_READ (1 << 0)
#define DEBUG_TOKENS (1 << 1)
#define DEBUG_MACROS (1 << 2)
#define DEBUG_CONTEXTS (1 << 3)
+static char *config = "extensions.ael";
static char *registrar = "pbx_ael";
static int pbx_load_module(void);
-#define AST_MODULE "pbx_ael"
-
-void ael2_semantic_check(pval *item, int *arg_errs, int *arg_warns, int *arg_notes);
+
+#ifndef AAL_ARGCHECK
+/* for the time being, short circuit all the AAL related structures
+ without permanently removing the code; after/during the AAL
+ development, this code can be properly re-instated
+*/
+
+#endif
+
+#ifdef AAL_ARGCHECK
+int option_matches_j( struct argdesc *should, pval *is, struct argapp *app);
+int option_matches( struct argdesc *should, pval *is, struct argapp *app);
+int ael_is_funcname(char *name);
+#endif
+
+int check_app_args(pval *appcall, pval *arglist, struct argapp *app);
+void check_pval(pval *item, struct argapp *apps, int in_globals);
+void check_pval_item(pval *item, struct argapp *apps, int in_globals);
+void check_switch_expr(pval *item, struct argapp *apps);
+void ast_expr_register_extra_error_info(char *errmsg);
+void ast_expr_clear_extra_error_info(void);
+int ast_expr(char *expr, char *buf, int length);
+struct pval *find_macro(char *name);
+struct pval *find_context(char *name);
+struct pval *find_context(char *name);
+struct pval *find_macro(char *name);
+struct ael_priority *new_prio(void);
+struct ael_extension *new_exten(void);
+void linkprio(struct ael_extension *exten, struct ael_priority *prio);
+void destroy_extensions(struct ael_extension *exten);
+void set_priorities(struct ael_extension *exten);
+void add_extensions(struct ael_extension *exten);
void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root);
void destroy_pval(pval *item);
+void destroy_pval_item(pval *item);
+int is_float(char *arg );
+int is_int(char *arg );
+int is_empty(char *arg);
static int aeldebug = 0;
/* interface stuff */
/* if all the below are static, who cares if they are present? */
-extern int do_pbx_load_module(void);
static int pbx_load_module(void)
{
- return do_pbx_load_module();
+ int errs, sem_err, sem_warn, sem_note;
+ char *rfilename;
+ struct ast_context *local_contexts=NULL, *con;
+ struct pval *parse_tree;
+
+ ast_log(LOG_NOTICE, "Starting AEL load process.\n");
+ if (config[0] == '/')
+ rfilename = (char *)config;
+ else {
+ rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
+ sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config);
+ }
+ ast_log(LOG_NOTICE, "AEL load process: calculated config file name '%s'.\n", rfilename);
+
+ if (access(rfilename,R_OK) != 0) {
+ ast_log(LOG_NOTICE, "File %s not found; AEL declining load\n", rfilename);
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ parse_tree = ael2_parse(rfilename, &errs);
+ ast_log(LOG_NOTICE, "AEL load process: parsed config file name '%s'.\n", rfilename);
+ ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note);
+ if (errs == 0 && sem_err == 0) {
+ ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename);
+ ast_compile_ael2(&local_contexts, parse_tree);
+ ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename);
+
+ ast_merge_contexts_and_delete(&local_contexts, registrar);
+ ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename);
+ for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
+ ast_context_verify_includes(con);
+ ast_log(LOG_NOTICE, "AEL load process: verified config file name '%s'.\n", rfilename);
+ } else {
+ 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);
+ destroy_pval(parse_tree); /* free up the memory */
+ return AST_MODULE_LOAD_FAILURE;
+ }
+ destroy_pval(parse_tree); /* free up the memory */
+
+ return AST_MODULE_LOAD_SUCCESS;
}
/* CLI interface */
@@ -150,6 +226,16 @@
{
return pbx_load_module();
}
+
+#ifdef STANDALONE_AEL
+#define AST_MODULE "ael"
+int ael_external_load_module(void);
+int ael_external_load_module(void)
+{
+ pbx_load_module();
+ return 1;
+}
+#endif
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk Extension Language Compiler",
.load = load_module,
@@ -158,3 +244,6 @@
);
+
+
+
Modified: team/murf/bug_7638/utils/Makefile
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/utils/Makefile?view=diff&rev=58959&r1=58958&r2=58959
==============================================================================
--- team/murf/bug_7638/utils/Makefile (original)
+++ team/murf/bug_7638/utils/Makefile Thu Mar 15 22:44:47 2007
@@ -110,11 +110,9 @@
aelparse: aelparse.o aelbison.o pbx_ael.o ael_main.o ast_expr2f.o ast_expr2.o strcompat.o pval.o extconf.o
-config_external.o : config_external.c
-
extconf.o : extconf.c
-conf2ael: conf2ael.o config_external.o ast_expr2f.o ast_expr2.o aelbison.o aelparse.o pbx_ael.o pval.o extconf.o
+conf2ael: conf2ael.o ast_expr2f.o ast_expr2.o aelbison.o aelparse.o pbx_ael.o pval.o extconf.o
testexpr2s: ../main/ast_expr2f.c ../main/ast_expr2.c ../main/ast_expr2.h
Modified: team/murf/bug_7638/utils/ael_main.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/utils/ael_main.c?view=diff&rev=58959&r1=58958&r2=58959
==============================================================================
--- team/murf/bug_7638/utils/ael_main.c (original)
+++ team/murf/bug_7638/utils/ael_main.c Thu Mar 15 22:44:47 2007
@@ -105,6 +105,18 @@
static int FIRST_TIME = 0;
static FILE *dumpfile;
+void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
+{
+ va_list vars;
+ va_start(vars,fmt);
+
+ printf("LOG: lev:%d file:%s line:%d func: %s ",
+ level, file, line, function);
+ vprintf(fmt, vars);
+ fflush(stdout);
+ va_end(vars);
+}
+
struct ast_app *pbx_findapp(const char *app)
{
return (struct ast_app*)1; /* so as not to trigger an error */
@@ -350,10 +362,23 @@
printf("Executed ast_context_verify_includes();\n");
}
+struct ast_context * ast_walk_contexts(void)
+{
+ if(!no_comp)
+ printf("Executed ast_walk_contexts();\n");
+ return 0;
+}
+
void ast_cli_unregister_multiple(void)
{
if(!no_comp)
printf("Executed ast_cli_unregister_multiple();\n");
+}
+
+void ast_context_destroy(void)
+{
+ if( !no_comp)
+ printf("Executed ast_context_destroy();\n");
}
void filter_leading_space_from_exprs(char *str)
@@ -396,14 +421,6 @@
extern struct module_symbols mod_data;
int ael_external_load_module(void);
-
-#define AST_MODULE "ael"
-int ael_external_load_module(void);
-int ael_external_load_module(void)
-{
- do_pbx_load_module();
- return 1;
-}
int main(int argc, char **argv)
{
Modified: team/murf/bug_7638/utils/conf2ael.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/utils/conf2ael.c?view=diff&rev=58959&r1=58958&r2=58959
==============================================================================
--- team/murf/bug_7638/utils/conf2ael.c (original)
+++ team/murf/bug_7638/utils/conf2ael.c Thu Mar 15 22:44:47 2007
@@ -58,6 +58,17 @@
int pbx_load_config(const char *config_file);
void get_start_stop(unsigned int *word, int bitsperword, int totalbits, int *start, int *end);
int all_bits_set(unsigned int *word, int bitsperword, int totalbits);
+void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
+{
+ va_list vars;
+ va_start(vars,fmt);
+
+ printf("LOG: lev:%d file:%s line:%d func: %s ",
+ level, file, line, function);
+ vprintf(fmt, vars);
+ fflush(stdout);
+ va_end(vars);
+}
extern char *days[];
extern char *months[];
Modified: team/murf/bug_7638/utils/extconf.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/utils/extconf.c?view=diff&rev=58959&r1=58958&r2=58959
==============================================================================
--- team/murf/bug_7638/utils/extconf.c (original)
+++ team/murf/bug_7638/utils/extconf.c Thu Mar 15 22:44:47 2007
@@ -664,15 +664,15 @@
static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable);
static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments);
-static struct ast_config *ast_config_load_with_comments(const char *filename);
+struct ast_config *localized_config_load_with_comments(const char *filename);
static char *ast_category_browse(struct ast_config *config, const char *prev);
-struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
+static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category);
static void ast_variables_destroy(struct ast_variable *v);
static void ast_config_destroy(struct ast_config *cfg);
-struct ast_variable *ast_variable_new(const char *name, const char *value);
-
-struct ast_variable *ast_variable_new(const char *name, const char *value)
+static struct ast_variable *ast_variable_new(const char *name, const char *value);
+
+static struct ast_variable *ast_variable_new(const char *name, const char *value)
{
struct ast_variable *variable;
int name_len = strlen(name) + 1;
@@ -687,9 +687,9 @@
return variable;
}
-void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
-
-void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
+static void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
+
+static void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
{
if (!variable)
return;
@@ -700,6 +700,43 @@
category->last = variable;
while (category->last->next)
category->last = category->last->next;
+}
+
+static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
+
+static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
+{
+ struct ast_category *cat;
+
+ /* try exact match first, then case-insensitive match */
+ for (cat = config->root; cat; cat = cat->next) {
+ if (cat->name == category_name && (ignored || !cat->ignored))
+ return cat;
+ }
+
+ for (cat = config->root; cat; cat = cat->next) {
+ if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
+ return cat;
+ }
+
+ return NULL;
+}
+
+static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
+{
+ return category_get(config, category_name, 0);
+}
+
+static struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
+{
+ struct ast_category *cat = NULL;
+
+ if (category && config->last_browse && (config->last_browse->name == category))
+ cat = config->last_browse;
+ else
+ cat = ast_category_get(config, category);
+
+ return (cat) ? cat->root : NULL;
}
static const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
@@ -2323,8 +2360,8 @@
AST_LIST_HEAD_NOLOCK(varshead, ast_var_t);
+AST_RWLOCK_DEFINE_STATIC(globalslock);
static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
-
/* IN CONFLICT: struct ast_var_t *ast_var_assign(const char *name, const char *value); */
@@ -2382,7 +2419,7 @@
};
-extern char *config; /* define this where you define main */
+static char *config = "extensions.ael";
static char *registrar = "conf2ael";
static char userscontext[AST_MAX_EXTENSION] = "default";
static int static_config = 0;
@@ -2391,8 +2428,7 @@
static int clearglobalvars_config = 0;
/*! Go no deeper than this through includes (not counting loops) */
#define AST_PBX_MAX_STACK 128
-static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
-void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
+static void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
/* taken from strings.h */
@@ -2783,39 +2819,6 @@
#endif
-static struct ast_custom_function *ast_custom_function_find(const char *name)
-{
- struct ast_custom_function *acf = NULL;
-
- AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
- if (!strcmp(name, acf->name))
- break;
- }
-
- return acf;
-}
-
-
-/*! \brief return a pointer to the arguments of the function,
- * and terminates the function name with '\\0'
- */
-static char *func_args(const char *function)
-{
- char *args = strchr(function, '(');
-
- if (!args)
- ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
- else {
- char *p;
- *args++ = '\0';
- if ((p = strrchr(args, ')')) )
- *p = '\0';
- else
- ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
- }
- return args;
-}
-
static struct ast_var_t *ast_var_assign(const char *name, const char *value)
{
struct ast_var_t *var;
@@ -2840,61 +2843,13 @@
}
+/* chopped this one off at the knees! */
static int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
{
- char *args = func_args(function);
- struct ast_custom_function *acfptr = ast_custom_function_find(function);
-
- if (acfptr == NULL)
- ast_log(LOG_ERROR, "Function %s not registered\n", function);
- else if (!acfptr->write)
- ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
- else
- return acfptr->write(chan, function, args, value);
+
+ ast_log(LOG_ERROR, "Function %s not registered\n", function);
return -1;
-}
-
-static unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
-{
- int argc;
- char *scan;
- int paren = 0, quote = 0;
-
- if (!buf || !array || !arraylen)
- return 0;
-
- memset(array, 0, arraylen * sizeof(*array));
-
- scan = buf;
-
- for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
- array[argc] = scan;
- for (; *scan; scan++) {
- if (*scan == '(')
- paren++;
- else if (*scan == ')') {
- if (paren)
- paren--;
- } else if (*scan == '"' && delim != '"') {
- quote = quote ? 0 : 1;
- /* Remove quote character from argument */
- memmove(scan, scan + 1, strlen(scan));
- scan--;
- } else if (*scan == '\\') {
- /* Literal character, don't parse */
- memmove(scan, scan + 1, strlen(scan));
- } else if ((*scan == delim) && !paren && !quote) {
- *scan++ = '\0';
- break;
- }
- }
- }
-
- if (*scan)
- array[argc++] = scan;
-
- return argc;
}
static void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
@@ -3146,29 +3101,9 @@
return category;
}
-static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored);
-
-static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
-{
- struct ast_category *cat;
-
- /* try exact match first, then case-insensitive match */
- for (cat = config->root; cat; cat = cat->next) {
- if (cat->name == category_name && (ignored || !cat->ignored))
- return cat;
- }
-
- for (cat = config->root; cat; cat = cat->next) {
- if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
- return cat;
- }
-
- return NULL;
-}
-
-static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name);
-
-static struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
+struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name);
+
+struct ast_category *localized_category_get(const struct ast_config *config, const char *category_name)
{
return category_get(config, category_name, 0);
}
@@ -3647,9 +3582,9 @@
return config;
}
-static struct ast_config *ast_config_load(const char *filename);
-
-static struct ast_config *ast_config_load(const char *filename)
+struct ast_config *localized_config_load(const char *filename);
+
+struct ast_config *localized_config_load(const char *filename)
{
struct ast_config *cfg;
struct ast_config *result;
@@ -3665,7 +3600,9 @@
return result;
}
-static struct ast_config *ast_config_load_with_comments(const char *filename)
+struct ast_config *localized_config_load_with_comments(const char *filename);
+
+struct ast_config *localized_config_load_with_comments(const char *filename)
{
struct ast_config *cfg;
struct ast_config *result;
@@ -3722,13 +3659,6 @@
-static int bit_at(unsigned int *word, int bitsperword, int bitnum);
-
-static int bit_at(unsigned int *word, int bitsperword, int bitnum)
-{
- return word[bitnum/bitsperword] & (1 << (bitnum % bitsperword));
-}
-
void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat);
void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat)
@@ -3737,9 +3667,9 @@
cfg->current = (struct ast_category *) cat;
}
-static int config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator);
-
-static int config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator)
+int localized_config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator);
+
+int localized_config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator)
{
FILE *f;
char fn[256];
@@ -4738,11 +4668,6 @@
return ast_rwlock_wrlock(&conlock);
}
-static int ast_rdlock_contexts(void)
-{
- return ast_rwlock_rdlock(&conlock);
-}
-
static int ast_unlock_contexts(void)
{
return ast_rwlock_unlock(&conlock);
@@ -4751,11 +4676,6 @@
static int ast_wrlock_context(struct ast_context *con)
{
return ast_rwlock_wrlock(&con->lock);
-}
-
-static int ast_rdlock_context(struct ast_context *con)
-{
- return ast_rwlock_rdlock(&con->lock);
}
static int ast_unlock_context(struct ast_context *con)
@@ -5091,15 +5011,351 @@
return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
}
-static struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
- return __ast_context_create(extcontexts, name, registrar, 0);
-}
-
static struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
{
return __ast_context_create(extcontexts, name, registrar, 1);
}
+
+
+/* chopped this one off at the knees */
+static int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
+{
+ ast_log(LOG_ERROR, "Function %s not registered\n", function);
+ return -1;
+}
+
+/*! \brief extract offset:length from variable name.
+ * Returns 1 if there is a offset:length part, which is
+ * trimmed off (values go into variables)
+ */
+static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
+{
+ int parens=0;
+
+ *offset = 0;
+ *length = INT_MAX;
+ *isfunc = 0;
+ for (; *var; var++) {
+ if (*var == '(') {
+ (*isfunc)++;
+ parens++;
+ } else if (*var == ')') {
+ parens--;
+ } else if (*var == ':' && parens == 0) {
+ *var++ = '\0';
+ sscanf(var, "%d:%d", offset, length);
+ return 1; /* offset:length valid */
+ }
+ }
+ return 0;
+}
+
+static const char *ast_var_value(const struct ast_var_t *var)
+{
+ return (var ? var->value : NULL);
+}
+
+/*! \brief takes a substring. It is ok to call with value == workspace.
+ *
+ * offset < 0 means start from the end of the string and set the beginning
+ * to be that many characters back.
+ * length is the length of the substring. A value less than 0 means to leave
+ * that many off the end.
+ * Always return a copy in workspace.
+ */
+static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
+{
+ char *ret = workspace;
+ int lr; /* length of the input string after the copy */
+
+ ast_copy_string(workspace, value, workspace_len); /* always make a copy */
+
+ lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
+
+ /* Quick check if no need to do anything */
+ if (offset == 0 && length >= lr) /* take the whole string */
+ return ret;
+
+ if (offset < 0) { /* translate negative offset into positive ones */
+ offset = lr + offset;
+ if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
+ offset = 0;
+ }
+
+ /* too large offset result in empty string so we know what to return */
+ if (offset >= lr)
+ return ret + lr; /* the final '\0' */
+
+ ret += offset; /* move to the start position */
+ if (length >= 0 && length < lr - offset) /* truncate if necessary */
+ ret[length] = '\0';
+ else if (length < 0) {
+ if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
+ ret[lr + length - offset] = '\0';
+ else
+ ret[0] = '\0';
+ }
+
+ return ret;
+}
+
+/*! \brief Support for Asterisk built-in variables in the dialplan
+\note See also
+ - \ref AstVar Channel variables
+ - \ref AstCauses The HANGUPCAUSE variable
+ */
+static void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
+{
+ const char not_found = '\0';
+ char *tmpvar;
+ const char *s; /* the result */
+ int offset, length;
+ int i, need_substring;
+ struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
+
+ /*
+ * Make a copy of var because parse_variable_name() modifies the string.
+ * Then if called directly, we might need to run substring() on the result;
+ * remember this for later in 'need_substring', 'offset' and 'length'
+ */
+ tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
+ need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
+
+ /*
+ * Look first into predefined variables, then into variable lists.
+ * Variable 's' points to the result, according to the following rules:
+ * s == ¬_found (set at the beginning) means that we did not find a
+ * matching variable and need to look into more places.
+ * If s != ¬_found, s is a valid result string as follows:
+ * s = NULL if the variable does not have a value;
+ * you typically do this when looking for an unset predefined variable.
+ * s = workspace if the result has been assembled there;
+ * typically done when the result is built e.g. with an snprintf(),
+ * so we don't need to do an additional copy.
+ * s != workspace in case we have a string, that needs to be copied
+ * (the ast_copy_string is done once for all at the end).
+ * Typically done when the result is already available in some string.
+ */
+ s = ¬_found; /* default value */
+ if (s == ¬_found) { /* look for more */
+ if (!strcmp(var, "EPOCH")) {
+ snprintf(workspace, workspacelen, "%u",(int)time(NULL));
+ }
+
+ s = workspace;
+ }
+ /* if not found, look into chanvars or global vars */
+ for (i = 0; s == ¬_found && i < (sizeof(places) / sizeof(places[0])); i++) {
+ struct ast_var_t *variables;
+ if (!places[i])
+ continue;
+ if (places[i] == &globals)
+ ast_rwlock_rdlock(&globalslock);
+ AST_LIST_TRAVERSE(places[i], variables, entries) {
+ if (strcasecmp(ast_var_name(variables), var)==0) {
+ s = ast_var_value(variables);
+ break;
+ }
+ }
+ if (places[i] == &globals)
+ ast_rwlock_unlock(&globalslock);
+ }
+ if (s == ¬_found || s == NULL)
+ *ret = NULL;
+ else {
+ if (s != workspace)
+ ast_copy_string(workspace, s, workspacelen);
+ *ret = workspace;
+ if (need_substring)
+ *ret = substring(*ret, offset, length, workspace, workspacelen);
+ }
+}
+
+static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
+{
+ /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
+ zero-filled */
+ char *cp4;
+ const char *tmp, *whereweare;
+ int length, offset, offset2, isfunction;
+ char *workspace = NULL;
+ char *ltmp = NULL, *var = NULL;
+ char *nextvar, *nextexp, *nextthing;
+ char *vars, *vare;
+ int pos, brackets, needsub, len;
+
+ whereweare=tmp=cp1;
+ while (!ast_strlen_zero(whereweare) && count) {
+ /* Assume we're copying the whole remaining string */
+ pos = strlen(whereweare);
+ nextvar = NULL;
+ nextexp = NULL;
+ nextthing = strchr(whereweare, '$');
+ if (nextthing) {
+ switch (nextthing[1]) {
+ case '{':
+ nextvar = nextthing;
+ pos = nextvar - whereweare;
+ break;
+ case '[':
+ nextexp = nextthing;
+ pos = nextexp - whereweare;
+ break;
+ }
+ }
+
+ if (pos) {
+ /* Can't copy more than 'count' bytes */
+ if (pos > count)
+ pos = count;
+
+ /* Copy that many bytes */
+ memcpy(cp2, whereweare, pos);
+
+ count -= pos;
+ cp2 += pos;
+ whereweare += pos;
+ }
+
+ if (nextvar) {
+ /* We have a variable. Find the start and end, and determine
+ if we are going to have to recursively call ourselves on the
+ contents */
+ vars = vare = nextvar + 2;
+ brackets = 1;
+ needsub = 0;
+
+ /* Find the end of it */
+ while (brackets && *vare) {
+ if ((vare[0] == '$') && (vare[1] == '{')) {
+ needsub++;
+ } else if (vare[0] == '{') {
+ brackets++;
+ } else if (vare[0] == '}') {
+ brackets--;
+ } else if ((vare[0] == '$') && (vare[1] == '['))
+ needsub++;
+ vare++;
+ }
+ if (brackets)
+ ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
+ len = vare - vars - 1;
+
+ /* Skip totally over variable string */
+ whereweare += (len + 3);
+
+ if (!var)
+ var = alloca(VAR_BUF_SIZE);
+
+ /* Store variable name (and truncate) */
+ ast_copy_string(var, vars, len + 1);
+
+ /* Substitute if necessary */
+ if (needsub) {
+ if (!ltmp)
+ ltmp = alloca(VAR_BUF_SIZE);
+
+ memset(ltmp, 0, VAR_BUF_SIZE);
+ pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
+ vars = ltmp;
+ } else {
+ vars = var;
+ }
+
+ if (!workspace)
+ workspace = alloca(VAR_BUF_SIZE);
+
+ workspace[0] = '\0';
+
+ parse_variable_name(vars, &offset, &offset2, &isfunction);
+ if (isfunction) {
+ /* Evaluate function */
+ cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
+ } else {
+ /* Retrieve variable value */
+ pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
+ }
+ if (cp4) {
+ cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
+
+ length = strlen(cp4);
+ if (length > count)
+ length = count;
+ memcpy(cp2, cp4, length);
+ count -= length;
+ cp2 += length;
+ }
+ } else if (nextexp) {
+ /* We have an expression. Find the start and end, and determine
+ if we are going to have to recursively call ourselves on the
+ contents */
+ vars = vare = nextexp + 2;
+ brackets = 1;
+ needsub = 0;
+
+ /* Find the end of it */
+ while (brackets && *vare) {
+ if ((vare[0] == '$') && (vare[1] == '[')) {
+ needsub++;
+ brackets++;
+ vare++;
+ } else if (vare[0] == '[') {
+ brackets++;
+ } else if (vare[0] == ']') {
+ brackets--;
+ } else if ((vare[0] == '$') && (vare[1] == '{')) {
+ needsub++;
+ vare++;
+ }
+ vare++;
+ }
+ if (brackets)
+ ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
+ len = vare - vars - 1;
+
+ /* Skip totally over expression */
+ whereweare += (len + 3);
+
+ if (!var)
+ var = alloca(VAR_BUF_SIZE);
+
+ /* Store variable name (and truncate) */
+ ast_copy_string(var, vars, len + 1);
+
+ /* Substitute if necessary */
+ if (needsub) {
+ if (!ltmp)
+ ltmp = alloca(VAR_BUF_SIZE);
+
+ memset(ltmp, 0, VAR_BUF_SIZE);
+ pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
+ vars = ltmp;
+ } else {
+ vars = var;
+ }
+
+ length = ast_expr(vars, cp2, count);
+
+ if (length) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
+ count -= length;
+ cp2 += length;
+ }
+ } else
+ break;
+ }
+}
+
+static void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
+{
+ pbx_substitute_variables_helper_full(c, NULL, cp1, cp2, count);
+}
+
+
+static int pbx_load_config(const char *config_file);
static int pbx_load_config(const char *config_file)
{
@@ -5113,7 +5369,7 @@
const char *cxt;
const char *aft;
- cfg = ast_config_load(config_file);
+ cfg = localized_config_load(config_file);
if (!cfg)
return 0;
@@ -5326,7 +5582,9 @@
}
}
-static void ast_context_destroy(struct ast_context *con, const char *registrar)
+void localized_context_destroy(struct ast_context *con, const char *registrar);
+
+void localized_context_destroy(struct ast_context *con, const char *registrar)
{
ast_wrlock_contexts();
__ast_context_destroy(con,registrar);
@@ -5393,7 +5651,9 @@
return res;
}
-static int pbx_load_module(void)
+int localized_pbx_load_module(void);
+
+int localized_pbx_load_module(void)
{
struct ast_context *con;
More information about the asterisk-commits
mailing list