[asterisk-commits] murf: branch murf/bug_7638 r57752 - /team/murf/bug_7638/utils/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sat Mar 3 11:06:31 MST 2007


Author: murf
Date: Sat Mar  3 12:06:30 2007
New Revision: 57752

URL: http://svn.digium.com/view/asterisk?view=rev&rev=57752
Log:
refactored most of the extensions.conf parser into extconf.c

Added:
    team/murf/bug_7638/utils/extconf.c   (with props)
Modified:
    team/murf/bug_7638/utils/Makefile
    team/murf/bug_7638/utils/conf2ael.c

Modified: team/murf/bug_7638/utils/Makefile
URL: http://svn.digium.com/view/asterisk/team/murf/bug_7638/utils/Makefile?view=diff&rev=57752&r1=57751&r2=57752
==============================================================================
--- team/murf/bug_7638/utils/Makefile (original)
+++ team/murf/bug_7638/utils/Makefile Sat Mar  3 12:06:30 2007
@@ -112,7 +112,9 @@
 
 config_external.o : config_external.c
 
-conf2ael: conf2ael.o config_external.o ast_expr2f.o ast_expr2.o aelbison.o aelparse.o pbx_ael.o pval.o
+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
 
 
 testexpr2s: ../main/ast_expr2f.c ../main/ast_expr2.c ../main/ast_expr2.h

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=57752&r1=57751&r2=57752
==============================================================================
--- team/murf/bug_7638/utils/conf2ael.c (original)
+++ team/murf/bug_7638/utils/conf2ael.c Sat Mar  3 12:06:30 2007
@@ -55,20 +55,28 @@
 #include "asterisk/ael_structs.h"
 #include "asterisk/pval.h"
 
-
-static char *config = "extensions.conf";
+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);
+
+extern char *days[];
+extern char *months[];
+extern char *config;
+char ast_config_AST_CONFIG_DIR[PATH_MAX];
+
+/* static char *config = "extensions.conf";
 static char *registrar = "conf2ael";
 static char userscontext[AST_MAX_EXTENSION] = "default";
 static int static_config = 0;
 static int write_protect_config = 1;
 static int autofallthrough_config = 0;
 static int clearglobalvars_config = 0;
-char ast_config_AST_SYSTEM_NAME[20] = "";
+char ast_config_AST_SYSTEM_NAME[20] = ""; */
+
 /*! 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);
-char ast_config_AST_CONFIG_DIR[PATH_MAX];
-extern char *my_file;
+/* static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function); */
+extern char ast_config_AST_CONFIG_DIR[PATH_MAX];
 
 /* modulation */
 void ast_register_file_version(void);
@@ -89,71 +97,6 @@
 
 }
 
-/* stolen from callerid.c */
-
-/*! \brief Clean up phone string
- * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
- * Basically, remove anything that could be invalid in a pattern.
- */
-void ast_shrink_phone_number(char *n)
-{
-	int x, y=0;
-	int bracketed = 0;
-
-	for (x=0; n[x]; x++) {
-		switch(n[x]) {
-		case '[':
-			bracketed++;
-			n[y++] = n[x];
-			break;
-		case ']':
-			bracketed--;
-			n[y++] = n[x];
-			break;
-		case '-':
-			if (bracketed)
-				n[y++] = n[x];
-			break;
-		case '.':
-			if (!n[x+1])
-				n[y++] = n[x];
-			break;
-		default:
-			if (!strchr("()", n[x]))
-				n[y++] = n[x];
-		}
-	}
-	n[y] = '\0';
-}
-
-
-/* stolen from chanvars.c */
-
-const char *ast_var_name(const struct ast_var_t *var)
-{
-	const char *name;
-
-	if (var == NULL || (name = var->name) == NULL)
-		return NULL;
-	/* Return the name without the initial underscores */
-	if (name[0] == '_') {
-		name++;
-		if (name[0] == '_')
-			name++;
-	}
-	return name;
-}
-
-const char *ast_var_value(const struct ast_var_t *var)
-{
-	return (var ? var->value : NULL);
-}
-
-
-/* stolen from asterisk.c */
-struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
-int option_verbose = 0;                         /*!< Verbosity level */
-int option_debug = 0;                           /*!< Debug level */
 
 
 /* experiment 1: see if it's easier just to use existing config code
@@ -165,90 +108,6 @@
 
 /* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */
 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
-
-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);
-}
-
-void ast_verbose(const char *fmt, ...)
-{
-	va_list vars;
-	va_start(vars,fmt);
-	
-	printf("VERBOSE: ");
-	vprintf(fmt, vars);
-	fflush(stdout);
-	va_end(vars);
-}
-
-/* stolen from main/utils.c */
-char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
-{
- 	char *dataPut = start;
-	int inEscape = 0;
-	int inQuotes = 0;
-
-	for (; *start; start++) {
-		if (inEscape) {
-			*dataPut++ = *start;       /* Always goes verbatim */
-			inEscape = 0;
-		} else {
-			if (*start == '\\') {
-				inEscape = 1;      /* Do not copy \ into the data */
-			} else if (*start == '\'') {
-				inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
-			} else {
-				/* Replace , with |, unless in quotes */
-				*dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
-			}
-		}
-	}
-	if (start != dataPut)
-		*dataPut = 0;
-	return dataPut;
-}
-
-int ast_true(const char *s)
-{
-	if (ast_strlen_zero(s))
-		return 0;
-
-	/* Determine if this is a true value */
-	if (!strcasecmp(s, "yes") ||
-	    !strcasecmp(s, "true") ||
-	    !strcasecmp(s, "y") ||
-	    !strcasecmp(s, "t") ||
-	    !strcasecmp(s, "1") ||
-	    !strcasecmp(s, "on"))
-		return -1;
-
-	return 0;
-}
-
-int ast_false(const char *s)
-{
-	if (ast_strlen_zero(s))
-		return 0;
-
-	/* Determine if this is a false value */
-	if (!strcasecmp(s, "no") ||
-	    !strcasecmp(s, "false") ||
-	    !strcasecmp(s, "n") ||
-	    !strcasecmp(s, "f") ||
-	    !strcasecmp(s, "0") ||
-	    !strcasecmp(s, "off"))
-		return -1;
-
-	return 0;
-}
 
 /* stolen from pbx.c */
 struct ast_context;
@@ -273,7 +132,6 @@
 	E_FINDLABEL =	0x22	/* returns the priority for a given label. Requires exact match */
 };
 
-static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
 
 #define SWITCH_DATA_LENGTH 256
 
@@ -415,12 +273,10 @@
 #define STATUS_NO_PRIORITY	3
 #define STATUS_NO_LABEL		4
 #define STATUS_SUCCESS		5
-static struct ast_context *local_contexts = NULL;
-static struct ast_context *contexts = NULL;
-static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
-
-static AST_RWLIST_HEAD_STATIC(hints, ast_hint);
-struct ast_state_cb *statecbs = NULL;
+
+extern struct ast_context *local_contexts;
+extern struct ast_context *contexts;
+
 
 /* request and result for pbx_find_extension */
 struct pbx_find_info {
@@ -438,156 +294,7 @@
 	const char *foundcontext;       /* set on return */
 };
 
-/*
- * Internal function for ast_extension_{match|close}
- * return 0 on no-match, 1 on match, 2 on early match.
- * mode is as follows:
- *	E_MATCH		success only on exact match
- *	E_MATCHMORE	success only on partial match (i.e. leftover digits in pattern)
- *	E_CANMATCH	either of the above.
- */
-
-static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
-{
-	mode &= E_MATCH_MASK;	/* only consider the relevant bits */
-
-	if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
-		return 1;
-
-	if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
-		int ld = strlen(data), lp = strlen(pattern);
-
-		if (lp < ld)		/* pattern too short, cannot match */
-			return 0;
-		/* depending on the mode, accept full or partial match or both */
-		if (mode == E_MATCH)
-			return !strcmp(pattern, data); /* 1 on match, 0 on fail */
-		if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
-			return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
-		else
-			return 0;
-	}
-	pattern++; /* skip leading _ */
-	/*
-	 * XXX below we stop at '/' which is a separator for the CID info. However we should
-	 * not store '/' in the pattern at all. When we insure it, we can remove the checks.
-	 */
-	while (*data && *pattern && *pattern != '/') {
-		const char *end;
-
-		if (*data == '-') { /* skip '-' in data (just a separator) */
-			data++;
-			continue;
-		}
-		switch (toupper(*pattern)) {
-		case '[':	/* a range */
-			end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
-			if (end == NULL) {
-				ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
-				return 0;	/* unconditional failure */
-			}
-			for (pattern++; pattern != end; pattern++) {
-				if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
-					if (*data >= pattern[0] && *data <= pattern[2])
-						break;	/* match found */
-					else {
-						pattern += 2; /* skip a total of 3 chars */
-						continue;
-					}
-				} else if (*data == pattern[0])
-					break;	/* match found */
-			}
-			if (pattern == end)
-				return 0;
-			pattern = end;	/* skip and continue */
-			break;
-		case 'N':
-			if (*data < '2' || *data > '9')
-				return 0;
-			break;
-		case 'X':
-			if (*data < '0' || *data > '9')
-				return 0;
-			break;
-		case 'Z':
-			if (*data < '1' || *data > '9')
-				return 0;
-			break;
-		case '.':	/* Must match, even with more digits */
-			return 1;
-		case '!':	/* Early match */
-			return 2;
-		case ' ':
-		case '-':	/* Ignore these in patterns */
-			data--; /* compensate the final data++ */
-			break;
-		default:
-			if (*data != *pattern)
-				return 0;
-		}
-		data++;
-		pattern++;
-	}
-	if (*data)			/* data longer than pattern, no match */
-		return 0;
-	/*
-	 * match so far, but ran off the end of the data.
-	 * Depending on what is next, determine match or not.
-	 */
-	if (*pattern == '\0' || *pattern == '/')	/* exact match */
-		return (mode == E_MATCHMORE) ? 0 : 1;	/* this is a failure for E_MATCHMORE */
-	else if (*pattern == '!')			/* early match */
-		return 2;
-	else						/* partial match */
-		return (mode == E_MATCH) ? 0 : 1;	/* this is a failure for E_MATCH */
-}
-
-/*
- * Wrapper around _extension_match_core() to do performance measurement
- * using the profiling code.
- */
-int ast_check_timing(const struct ast_timing *i)
-{
-	struct tm tm;
-	time_t t = time(NULL);
-
-	localtime_r(&t,&tm);
-
-	/* If it's not the right month, return */
-	if (!(i->monthmask & (1 << tm.tm_mon)))
-		return 0;
-
-	/* If it's not that time of the month.... */
-	/* Warning, tm_mday has range 1..31! */
-	if (!(i->daymask & (1 << (tm.tm_mday-1))))
-		return 0;
-
-	/* If it's not the right day of the week */
-	if (!(i->dowmask & (1 << tm.tm_wday)))
-		return 0;
-
-	/* Sanity check the hour just to be safe */
-	if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
-		ast_log(LOG_WARNING, "Insane time...\n");
-		return 0;
-	}
-
-	/* Now the tough part, we calculate if it fits
-	   in the right time based on min/hour */
-	if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
-		return 0;
-
-	/* If we got this far, then we're good */
-	return 1;
-}
-
-static inline int include_valid(struct ast_include *i)
-{
-	if (!i->hastime)
-		return 1;
-
-	return ast_check_timing(&(i->timing));
-}
+
 
 struct profile_entry {
 	const char *name;
@@ -603,2243 +310,6 @@
 	struct profile_entry e[0];
 };
 
-static struct profile_data *prof_data;
-
-/*! \brief allocates a counter with a given name and scale.
- * \return Returns the identifier of the counter.
- */
-int ast_add_profile(const char *name, uint64_t scale);
-
-int ast_add_profile(const char *name, uint64_t scale)
-{
-	int l = sizeof(struct profile_data);
-	int n = 10;	/* default entries */
-
-	if (prof_data == NULL) {
-		prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
-		if (prof_data == NULL)
-			return -1;
-		prof_data->entries = 0;
-		prof_data->max_size = n;
-	}
-	if (prof_data->entries >= prof_data->max_size) {
-		void *p;
-		n = prof_data->max_size + 20;
-		p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
-		if (p == NULL)
-			return -1;
-		prof_data = p;
-		prof_data->max_size = n;
-	}
-	n = prof_data->entries++;
-	prof_data->e[n].name = ast_strdup(name);
-	prof_data->e[n].value = 0;
-	prof_data->e[n].events = 0;
-	prof_data->e[n].mark = 0;
-	prof_data->e[n].scale = scale;
-	return n;
-}
-
-int64_t ast_profile(int i, int64_t delta);
-
-int64_t ast_profile(int i, int64_t delta)
-{
-	if (!prof_data || i < 0 || i > prof_data->entries)	/* invalid index */
-		return 0;
-	if (prof_data->e[i].scale > 1)
-		delta /= prof_data->e[i].scale;
-	prof_data->e[i].value += delta;
-	prof_data->e[i].events++;
-	return prof_data->e[i].value;
-}
-
-#if defined ( __i386__) && (defined(__FreeBSD__) || defined(linux))
-#if defined(__FreeBSD__)
-#include <machine/cpufunc.h>
-#elif defined(linux)
-static __inline uint64_t
-rdtsc(void)
-{ 
-	uint64_t rv;
-
-	__asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
-	return (rv);
-}
-#endif
-#else	/* supply a dummy function on other platforms */
-static __inline uint64_t
-rdtsc(void)
-{
-	return 0;
-}
-#endif
-
-int64_t ast_mark(int i, int startstop);
-
-int64_t ast_mark(int i, int startstop)
-{
-	if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
-		return 0;
-	if (startstop == 1)
-		prof_data->e[i].mark = rdtsc();
-	else {
-		prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
-		if (prof_data->e[i].scale > 1)
-			prof_data->e[i].mark /= prof_data->e[i].scale;
-		prof_data->e[i].value += prof_data->e[i].mark;
-		prof_data->e[i].events++;
-	}
-	return prof_data->e[i].mark;
-}
-static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
-{
-	int i;
-	static int prof_id = -2;	/* marker for 'unallocated' id */
-	if (prof_id == -2)
-		prof_id = ast_add_profile("ext_match", 0);
-	ast_mark(prof_id, 1);
-	i = _extension_match_core(pattern, data, mode);
-	ast_mark(prof_id, 0);
-	return i;
-}
-int ast_extension_match(const char *pattern, const char *data)
-{
-	return extension_match_core(pattern, data, E_MATCH);
-}
-
-static int matchcid(const char *cidpattern, const char *callerid)
-{
-	/* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
-	   failing to get a number should count as a match, otherwise not */
-
-	if (ast_strlen_zero(callerid))
-		return ast_strlen_zero(cidpattern) ? 1 : 0;
-
-	return ast_extension_match(cidpattern, callerid);
-}
-static struct ast_switch *pbx_findswitch(const char *sw)
-{
-	struct ast_switch *asw;
-
-	AST_RWLIST_TRAVERSE(&switches, asw, list) {
-		if (!strcasecmp(asw->name, sw))
-			break;
-	}
-
-	return asw;
-}
-struct ast_context *ast_walk_contexts(struct ast_context *con)
-{
-	return con ? con->next : contexts;
-}
-
-struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
-	struct ast_exten *exten)
-{
-	if (!exten)
-		return con ? con->root : NULL;
-	else
-		return exten->next;
-}
-
-struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
-	struct ast_exten *priority)
-{
-	return priority ? priority->peer : exten;
-}
-
-struct ast_include *ast_walk_context_includes(struct ast_context *con,
-	struct ast_include *inc)
-{
-	if (!inc)
-		return con ? con->includes : NULL;
-	else
-		return inc->next;
-}
-
-
-
-static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
-	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)
-{
-	int x, res;
-	struct ast_context *tmp;
-	struct ast_exten *e, *eroot;
-	struct ast_include *i;
-	struct ast_sw *sw;
-
-	/* Initialize status if appropriate */
-	if (q->stacklen == 0) {
-		q->status = STATUS_NO_CONTEXT;
-		q->swo = NULL;
-		q->data = NULL;
-		q->foundcontext = NULL;
-	}
-	/* Check for stack overflow */
-	if (q->stacklen >= AST_PBX_MAX_STACK) {
-		ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
-		return NULL;
-	}
-	/* Check first to see if we've already been checked */
-	for (x = 0; x < q->stacklen; x++) {
-		if (!strcasecmp(q->incstack[x], context))
-			return NULL;
-	}
-	if (bypass)	/* bypass means we only look there */
-		tmp = bypass;
-	else {	/* look in contexts */
-		tmp = NULL;
-		while ((tmp = ast_walk_contexts(tmp)) ) {
-			if (!strcmp(tmp->name, context))
-				break;
-		}
-		if (!tmp)
-			return NULL;
-	}
-	if (q->status < STATUS_NO_EXTENSION)
-		q->status = STATUS_NO_EXTENSION;
-
-	/* scan the list trying to match extension and CID */
-	eroot = NULL;
-	while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
-		int match = extension_match_core(eroot->exten, exten, action);
-		/* 0 on fail, 1 on match, 2 on earlymatch */
-
-		if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
-			continue;	/* keep trying */
-		if (match == 2 && action == E_MATCHMORE) {
-			/* We match an extension ending in '!'.
-			 * The decision in this case is final and is NULL (no match).
-			 */
-			return NULL;
-		}
-		/* found entry, now look for the right priority */
-		if (q->status < STATUS_NO_PRIORITY)
-			q->status = STATUS_NO_PRIORITY;
-		e = NULL;
-		while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
-			/* Match label or priority */
-			if (action == E_FINDLABEL) {
-				if (q->status < STATUS_NO_LABEL)
-					q->status = STATUS_NO_LABEL;
-				if (label && e->label && !strcmp(label, e->label))
-					break;	/* found it */
-			} else if (e->priority == priority) {
-				break;	/* found it */
-			} /* else keep searching */
-		}
-		if (e) {	/* found a valid match */
-			q->status = STATUS_SUCCESS;
-			q->foundcontext = context;
-			return e;
-		}
-	}
-	/* Check alternative switches */
-	AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
-		struct ast_switch *asw = pbx_findswitch(sw->name);
-		ast_switch_f *aswf = NULL;
-		char *datap;
-
-		if (!asw) {
-			ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
-			continue;
-		}
-		/* Substitute variables now */
-		if (sw->eval)
-			pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
-
-		/* equivalent of extension_match_core() at the switch level */
-		if (action == E_CANMATCH)
-			aswf = asw->canmatch;
-		else if (action == E_MATCHMORE)
-			aswf = asw->matchmore;
-		else /* action == E_MATCH */
-			aswf = asw->exists;
-		datap = sw->eval ? sw->tmpdata : sw->data;
-		res = !aswf ? 0 : aswf(chan, context, exten, priority, callerid, datap);
-		if (res) {	/* Got a match */
-			q->swo = asw;
-			q->data = datap;
-			q->foundcontext = context;
-			/* XXX keep status = STATUS_NO_CONTEXT ? */
-			return NULL;
-		}
-	}
-	q->incstack[q->stacklen++] = tmp->name;	/* Setup the stack */
-	/* Now try any includes we have in this context */
-	for (i = tmp->includes; i; i = i->next) {
-		if (include_valid(i)) {
-			if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
-				return e;
-			if (q->swo)
-				return NULL;
-		}
-	}
-	return NULL;
-}
-
-/*! \brief  ast_hint_extension: Find hint for given extension in context */
-static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
-{
-	struct ast_exten *e;
-	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
-
-	e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
-
-	return e;
-}
-
-const char *ast_get_extension_app(struct ast_exten *e)
-{
-	return e ? e->app : NULL;
-}
-
-void *ast_get_extension_app_data(struct ast_exten *e)
-{
-	return e ? e->data : NULL;
-}
-
-const char *ast_get_extension_name(struct ast_exten *exten)
-{
-	return exten ? exten->exten : NULL;
-}
-
-
-/*! \brief  ast_get_hint: Get hint for channel */
-int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
-{
-	struct ast_exten *e = ast_hint_extension(c, context, exten);
-
-	if (e) {
-		if (hint)
-			ast_copy_string(hint, ast_get_extension_app(e), hintsize);
-		if (name) {
-			const char *tmp = ast_get_extension_app_data(e);
-			if (tmp)
-				ast_copy_string(name, tmp, namesize);
-		}
-		return -1;
-	}
-	return 0;
-}
-
-/*! \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;
-}
-
-/*! \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 and functions in the dialplan
-
-\note	See also
-	- \ref AstVar	Channel variables
-	- \ref AstCauses The HANGUPCAUSE variable
- */
-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 */
-
-	if (c) {
-		places[0] = &c->varshead;
-	}
-	/*
-	 * 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 == &not_found (set at the beginning) means that we did not find a
-	 *	matching variable and need to look into more places.
-	 * If s != &not_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 = &not_found;	/* default value */
-	if (c) {	/* This group requires a valid channel */
-		/* Names with common parts are looked up a piece at a time using strncmp. */
-		if (!strncmp(var, "CALL", 4)) {
-			if (!strncmp(var + 4, "ING", 3)) {
-				if (!strcmp(var + 7, "PRES")) {			/* CALLINGPRES */
-					snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
-					s = workspace;
-				} else if (!strcmp(var + 7, "ANI2")) {		/* CALLINGANI2 */
-					snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
-					s = workspace;
-				} else if (!strcmp(var + 7, "TON")) {		/* CALLINGTON */
-					snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
-					s = workspace;
-				} else if (!strcmp(var + 7, "TNS")) {		/* CALLINGTNS */
-					snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
-					s = workspace;
-				}
-			}
-		} else if (!strcmp(var, "HINT")) {
-			s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
-		} else if (!strcmp(var, "HINTNAME")) {
-			s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
-		} else if (!strcmp(var, "EXTEN")) {
-			s = c->exten;
-		} else if (!strcmp(var, "CONTEXT")) {
-			s = c->context;
-		} else if (!strcmp(var, "PRIORITY")) {
-			snprintf(workspace, workspacelen, "%d", c->priority);
-			s = workspace;
-		} else if (!strcmp(var, "CHANNEL")) {
-			s = c->name;
-		} else if (!strcmp(var, "UNIQUEID")) {
-			s = c->uniqueid;
-		} else if (!strcmp(var, "HANGUPCAUSE")) {
-			snprintf(workspace, workspacelen, "%d", c->hangupcause);
-			s = workspace;
-		}
-	}
-	if (s == &not_found) { /* look for more */
-		if (!strcmp(var, "EPOCH")) {
-			snprintf(workspace, workspacelen, "%u",(int)time(NULL));
-			s = workspace;
-		} else if (!strcmp(var, "SYSTEMNAME")) {
-			s = ast_config_AST_SYSTEM_NAME;
-		}
-	}
-	/* if not found, look into chanvars or global vars */
-	for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
-		struct ast_var_t *variables;
-		if (!places[i])
-			continue;
-		AST_LIST_TRAVERSE(places[i], variables, entries) {
-			if (strcasecmp(ast_var_name(variables), var)==0) {
-				s = ast_var_value(variables);
-				break;
-			}
-		}
-	}
-	if (s == &not_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);
-	}
-}
-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;
-}
-
-int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
-{
-	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->read)
-		ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
-	else
-		return acfptr->read(chan, function, args, workspace, len);
-	return -1;
-}
-
-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;
-	}
-}
-
-void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
-{
-	pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
-}
-
-void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
-{
-	pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
-}
-
-/*! \brief  ast_remove_hint: Remove hint from extension */
-static int ast_remove_hint(struct ast_exten *e)
-{
-	/* Cleanup the Notifys if hint is removed */
-	struct ast_hint *hint;
-	struct ast_state_cb *cblist, *cbprev;
-	int res = -1;
-
-	if (!e)
-		return -1;
-
-	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
-		if (hint->exten == e) {
-			cbprev = NULL;
-			cblist = hint->callbacks;
-			while (cblist) {
-				/* Notify with -1 and remove all callbacks */
-				cbprev = cblist;
-				cblist = cblist->next;
-				free(cbprev);
-			}
-			hint->callbacks = NULL;
-			AST_RWLIST_REMOVE_CURRENT(&hints, list);
-			free(hint);
-	   		res = 0;
-			break;
-		}
-	}
-	AST_RWLIST_TRAVERSE_SAFE_END
-
-	return res;
-}
-
-static void destroy_exten(struct ast_exten *e)
-{
-	if (e->priority == PRIORITY_HINT)
-		ast_remove_hint(e);
-
-	if (e->datad)
-		e->datad(e->data);
-	free(e);
-}
-
-void ast_context_destroy(struct ast_context *con, const char *registrar)
-{
-	struct ast_context *tmp, *tmpl=NULL;
-	struct ast_exten *e, *el, *en;
-	struct ast_include *tmpi;
-	struct ast_sw *sw;
-	struct ast_ignorepat *ipi;
-
-	for (tmp = contexts; tmp; ) {
-		struct ast_context *next;	/* next starting point */
-		for (; tmp; tmpl = tmp, tmp = tmp->next) {
-			if (option_debug)
-				ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
-			if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
-			     (!con || !strcasecmp(tmp->name, con->name)) )
-				break;	/* found it */
-		}
-		if (!tmp)	/* not found, we are done */
-			break;
-		if (option_debug)
-			ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
-		next = tmp->next;
-		if (tmpl)
-			tmpl->next = next;
-		else
-			contexts = next;
-		/* Okay, now we're safe to let it go -- in a sense, we were
-		   ready to let it go as soon as we locked it. */
-		for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
-			struct ast_include *tmpil = tmpi;
-			tmpi = tmpi->next;
-			free(tmpil);
-		}
-		for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
-			struct ast_ignorepat *ipl = ipi;
-			ipi = ipi->next;
-			free(ipl);
-		}
-		while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
-			free(sw);
-		for (e = tmp->root; e;) {
-			for (en = e->peer; en;) {
-				el = en;
-				en = en->peer;
-				destroy_exten(el);
-			}
-			el = e;
-			e = e->next;
-			destroy_exten(el);
-		}
-		free(tmp);
-		/* if we have a specific match, we are done, otherwise continue */
-		tmp = con ? NULL : next;
-	}
-}
-
-static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
-{
-	struct ast_context *tmp, **local_contexts;
-	int length = sizeof(struct ast_context) + strlen(name) + 1;
-
-	if (!extcontexts) {
-		local_contexts = &contexts;
-	} else
-		local_contexts = extcontexts;
-
-	for (tmp = *local_contexts; tmp; tmp = tmp->next) {
-		if (!strcasecmp(tmp->name, name)) {
-			if (!existsokay) {
-				ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
-				tmp = NULL;
-			}
-			return tmp;
-		}
-	}
-	if ((tmp = ast_calloc(1, length))) {
-		strcpy(tmp->name, name);
-		tmp->root = NULL;
-		tmp->registrar = registrar;
-		tmp->next = *local_contexts;
-		tmp->includes = NULL;
-		tmp->ignorepats = NULL;
-		*local_contexts = tmp;
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
-		if (option_verbose > 2)
-			ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
-	}
-
-	return tmp;
-}
-
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
-	return __ast_context_create(extcontexts, name, registrar, 0);
-}
-
-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);
-}
-
-struct ast_var_t *ast_var_assign(const char *name, const char *value)
-{	
-	struct ast_var_t *var;
-	int name_len = strlen(name) + 1;
-	int value_len = strlen(value) + 1;
-
-	if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
-		return NULL;
-	}
-
-	ast_copy_string(var->name, name, name_len);
-	var->value = var->name + name_len;
-	ast_copy_string(var->value, value, value_len);
-	
-	return var;
-}	
-	
-void ast_var_delete(struct ast_var_t *var)
-{
-	if (var)
-		free(var);
-}
-
-
-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);
-
-	return -1;
-}
-
-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;
-}
-
-void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
-{
-	struct ast_var_t *newvariable;
-	struct varshead *headp;
-	const char *nametail = name;
-
-	/* XXX may need locking on the channel ? */
-	if (name[strlen(name)-1] == ')') {
-		char *function = ast_strdupa(name);
-
-		ast_func_write(chan, function, value);
-		return;
-	}
-
-	headp = (chan) ? &chan->varshead : &globals;
-
-	/* For comparison purposes, we have to strip leading underscores */
-	if (*nametail == '_') {
-		nametail++;
-		if (*nametail == '_')
-			nametail++;
-	}
-
-	AST_LIST_TRAVERSE (headp, newvariable, entries) {
-		if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
-			/* there is already such a variable, delete it */
-			AST_LIST_REMOVE(headp, newvariable, entries);
-			ast_var_delete(newvariable);
-			break;
-		}
-	}
-
-	if (value) {
-		if ((option_verbose > 1) && (headp == &globals))
-			ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
-		newvariable = ast_var_assign(name, value);

[... 4094 lines stripped ...]


More information about the asterisk-commits mailing list