[asterisk-commits] branch group/new_loader_completion r26175 - in /team/group/new_loader_complet...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue May 9 09:26:26 MST 2006


Author: kpfleming
Date: Tue May  9 11:26:25 2006
New Revision: 26175

URL: http://svn.digium.com/view/asterisk?rev=26175&view=rev
Log:
commit more changes... still broken

Modified:
    team/group/new_loader_completion/   (props changed)
    team/group/new_loader_completion/app.c
    team/group/new_loader_completion/apps/app_chanspy.c
    team/group/new_loader_completion/apps/app_zapscan.c
    team/group/new_loader_completion/build_tools/menuselect.c
    team/group/new_loader_completion/build_tools/menuselect.h
    team/group/new_loader_completion/build_tools/menuselect_curses.c
    team/group/new_loader_completion/build_tools/prep_moduledeps
    team/group/new_loader_completion/channels/chan_oss.c
    team/group/new_loader_completion/include/asterisk/app.h
    team/group/new_loader_completion/pbx.c

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue May  9 11:26:25 2006
@@ -1,1 +1,1 @@
-/trunk:1-25894
+/trunk:1-25958

Modified: team/group/new_loader_completion/app.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/app.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/app.c (original)
+++ team/group/new_loader_completion/app.c Tue May  9 11:26:25 2006
@@ -142,86 +142,6 @@
 		fto = to = 1000000000;
 	res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
 	return res;
-}
-
-int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
-{
-	int res;
-	struct ast_filestream *writer;
-	int rfmt;
-	int totalms=0, total;
-	
-	struct ast_frame *f;
-	struct ast_dsp *sildet;
-	/* Play prompt if requested */
-	if (prompt) {
-		res = ast_stream_and_wait(c, prompt, c->language, "");
-		if (res < 0)
-			return res;
-	}
-	rfmt = c->readformat;
-	res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
-	if (res < 0) {
-		ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
-		return -1;
-	}
-	sildet = ast_dsp_new();
-	if (!sildet) {
-		ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
-		return -1;
-	}
-	writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
-	if (!writer) {
-		ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
-		ast_dsp_free(sildet);
-		return -1;
-	}
-	for(;;) {
-		if ((res = ast_waitfor(c, 2000)) < 0) {
-			ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
-			break;
-		}
-		if (res) {
-			f = ast_read(c);
-			if (!f) {
-				ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
-				break;
-			}
-			if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
-				/* Ended happily with DTMF */
-				ast_frfree(f);
-				break;
-			} else if (f->frametype == AST_FRAME_VOICE) {
-				ast_dsp_silence(sildet, f, &total); 
-				if (total > silence) {
-					/* Ended happily with silence */
-					ast_frfree(f);
-					break;
-				}
-				totalms += f->samples / 8;
-				if (totalms > maxsec * 1000) {
-					/* Ended happily with too much stuff */
-					ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
-					ast_frfree(f);
-					break;
-				}
-				res = ast_writestream(writer, f);
-				if (res < 0) {
-					ast_log(LOG_WARNING, "Failed to write to stream at %s!\n", dest);
-					ast_frfree(f);
-					break;
-				}
-					
-			}
-			ast_frfree(f);
-		}
-	}
-	res = ast_set_read_format(c, rfmt);
-	if (res)
-		ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
-	ast_dsp_free(sildet);
-	ast_closestream(writer);
-	return 0;
 }
 
 static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;

Modified: team/group/new_loader_completion/apps/app_chanspy.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_chanspy.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_chanspy.c (original)
+++ team/group/new_loader_completion/apps/app_chanspy.c Tue May  9 11:26:25 2006
@@ -56,7 +56,7 @@
 #define ALL_DONE(u, ret) ast_module_user_remove(u); return ret;
 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
 
-static const char *synopsis = "Listen to the audio of an active channel";
+static const char *tdesc = "Listen to the audio of an active channel";
 static const char *app = "ChanSpy";
 static const char *desc = 
 "  ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
@@ -582,12 +582,12 @@
 
 static int load_module(void)
 {
-	return ast_register_application(app, chanspy_exec, synopsis, desc);
+	return ast_register_application(app, chanspy_exec, tdesc, desc);
 }
 
 static const char *description(void)
 {
-	return (char *) synopsis;
+	return (char *) tdesc;
 }
 
 static const char *key(void)

Modified: team/group/new_loader_completion/apps/app_zapscan.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_zapscan.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_zapscan.c (original)
+++ team/group/new_loader_completion/apps/app_zapscan.c Tue May  9 11:26:25 2006
@@ -63,8 +63,6 @@
 #include "asterisk/utils.h"
 #include "asterisk/cli.h"
 #include "asterisk/say.h"
-
-static char *tdesc = "Scan Zap channels application";
 
 static char *app = "ZapScan";
 
@@ -382,15 +380,5 @@
 	return ast_register_application(app, conf_exec, synopsis, descrip);
 }
 
-static const char *description(void)
-{
-	return tdesc;
-}
-
-static const char *key(void)
-{
-	return ASTERISK_GPL_KEY;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, XXX);
-
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Scan Zap channels application");
+

Modified: team/group/new_loader_completion/build_tools/menuselect.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/build_tools/menuselect.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/build_tools/menuselect.c (original)
+++ team/group/new_loader_completion/build_tools/menuselect.c Tue May  9 11:26:25 2006
@@ -206,6 +206,7 @@
 				return -1;
 			
 			mem->name = mxmlElementGetAttr(cur2, "name");
+			mem->displayname = mxmlElementGetAttr(cur2, "displayname");
 		
 			if (!cat->positive_output)
 				mem->enabled = 1;

Modified: team/group/new_loader_completion/build_tools/menuselect.h
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/build_tools/menuselect.h?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/build_tools/menuselect.h (original)
+++ team/group/new_loader_completion/build_tools/menuselect.h Tue May  9 11:26:25 2006
@@ -37,6 +37,8 @@
 struct member {
 	/*! What will be sent to the makeopts file */
 	const char *name;
+	/*! Display name if known */
+	const char *displayname;
 	/*! Default setting */
 	const char *defaultenabled;
 	/*! This module is currently selected */

Modified: team/group/new_loader_completion/build_tools/menuselect_curses.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/build_tools/menuselect_curses.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/build_tools/menuselect_curses.c (original)
+++ team/group/new_loader_completion/build_tools/menuselect_curses.c Tue May  9 11:26:25 2006
@@ -128,6 +128,7 @@
 	int j = 0;
 	struct member *mem;
 	char buf[64];
+	const char *desc = NULL;
 
 	wclear(menu);
 
@@ -142,11 +143,17 @@
 			snprintf(buf, sizeof(buf), "XXX %d.%s %s", i, i < 10 ? " " : "", mem->name);
 		else
 			snprintf(buf, sizeof(buf), "[%s] %d.%s %s", mem->enabled ? "*" : " ", i, i < 10 ? " " : "", mem->name);
+		if (curopt + 1== i)
+			desc = mem->displayname;
 		waddstr(menu, buf);
 		if (i == end)
 			break;
 	}
 
+	if (desc) {
+		wmove(menu, end - start + 2, max_x / 2 - 16);
+		waddstr(menu, desc);
+	}
 	wmove(menu, curopt - start, max_x / 2 - 9);
 
 	wrefresh(menu);
@@ -157,7 +164,7 @@
 	struct category *cat;
 	int i = 0;
 	int start = 0;
-	int end = max_y - TITLE_HEIGHT - 2;
+	int end = max_y - TITLE_HEIGHT - 6;
 	int c;
 	int curopt = 0;
 	int maxopt;

Modified: team/group/new_loader_completion/build_tools/prep_moduledeps
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/build_tools/prep_moduledeps?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/build_tools/prep_moduledeps (original)
+++ team/group/new_loader_completion/build_tools/prep_moduledeps Tue May  9 11:26:25 2006
@@ -1,4 +1,30 @@
 #!/bin/sh
+
+get_description() {
+	x=${1}
+	TDESC=`cat $x | grep -e *tdesc | cut -f 2 -d '"'`
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -A 2 -e *description | grep -e '\"'  | cut -f 2 -d '"'` 
+	fi
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -e MODULE_DESCRIPTION | grep -v return | cut -f 2 -d '"'`
+	fi
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -e tdesc\\\[\\\] | cut -f 2 -d '"'`
+	fi
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -e desc\\\[\\\] | grep -v description | cut -f 2 -d '"'`
+	fi
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -e *desc | grep -v descrip | cut -f 2 -d '"'`
+	fi
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -e *dtext | grep static | cut -f 2 -d '"'`
+	fi
+	if [ "$TDESC" = "" ]; then
+		TDESC=`cat $x | grep -A 2 -e *synopsis | grep -e '\"'  | cut -f 2 -d '"'` 
+	fi
+}
 
 process_dir() {
 	dir=${1}
@@ -13,7 +39,9 @@
 		continue
 	    fi
 	    fname=${file##${dir}/}
-	    echo -e "\t\t<member name=\"${fname%%.c}.so\">"
+	    get_description ${file}
+	    desc=${TDESC}
+	    echo -e "\t\t<member name=\"${fname%%.c}.so\" displayname=\"${desc}\">"
 	    awk -f build_tools/get_moduledeps ${file}
 	    echo -e "\t\t</member>"
 	done

Modified: team/group/new_loader_completion/channels/chan_oss.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/channels/chan_oss.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/channels/chan_oss.c (original)
+++ team/group/new_loader_completion/channels/chan_oss.c Tue May  9 11:26:25 2006
@@ -375,10 +375,11 @@
 static int oss_write(struct ast_channel *chan, struct ast_frame *f);
 static int oss_indicate(struct ast_channel *chan, int cond);
 static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static char tdesc[] = "OSS Console Channel Driver";
 
 static const struct ast_channel_tech oss_tech = {
 	.type =	"Console",
-	.description =	"OSS Console Channel Driver",
+	.description =	tdesc,
 	.capabilities =	AST_FORMAT_SLINEAR,
 	.requester = oss_request,
 	.send_digit = oss_digit,

Modified: team/group/new_loader_completion/include/asterisk/app.h
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/include/asterisk/app.h?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/include/asterisk/app.h (original)
+++ team/group/new_loader_completion/include/asterisk/app.h Tue May  9 11:26:25 2006
@@ -99,9 +99,6 @@
 /*! \brief Full version with audiofd and controlfd.  NOTE: returns '2' on ctrlfd available, not '1' like other full functions */
 int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
 
-/*! Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#' */
-int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec);
-
 void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder),
 			      int (*messagecount_func)(const char *mailbox, int *newmsgs, int *oldmsgs));
   

Modified: team/group/new_loader_completion/pbx.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/pbx.c?rev=26175&r1=26174&r2=26175&view=diff
==============================================================================
--- team/group/new_loader_completion/pbx.c (original)
+++ team/group/new_loader_completion/pbx.c Tue May  9 11:26:25 2006
@@ -20,7 +20,7 @@
  *
  * \brief Core PBX routines.
  *
- * \author Mark Spencer <markster at digium.com> 
+ * \author Mark Spencer <markster at digium.com>
  */
 
 #include <sys/types.h>
@@ -67,7 +67,7 @@
  *		The speed of extension handling will likely be among the most important
  * aspects of this PBX.  The switching scheme as it exists right now isn't
  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
- * of priorities, but a constant search time here would be great ;-) 
+ * of priorities, but a constant search time here would be great ;-)
  *
  */
 
@@ -106,7 +106,7 @@
 struct ast_context;
 
 /*!
-   \brief ast_exten: An extension 
+   \brief ast_exten: An extension
 	The dialplan is saved as a linked list with each context
 	having it's own linked list of extensions - one item per
 	priority.
@@ -129,7 +129,7 @@
 
 /*! \brief ast_include: include= support in extensions.conf */
 struct ast_include {
-	const char *name;		
+	const char *name;
 	const char *rname;			/*!< Context to include */
 	const char *registrar;			/*!< Registrar */
 	int hastime;				/*!< If time construct exists */
@@ -186,7 +186,7 @@
 	ast_state_cb_type callback;
 	struct ast_state_cb *next;
 };
-	    
+
 /*! \brief Structure for dial plan hints
 
   Hints are pointers from an extension in the dialplan to one or
@@ -252,13 +252,13 @@
 	int (*execute)(struct ast_channel *chan, void *data);
 	char *synopsis;
 	char *description;
-} builtins[] = 
+} builtins[] =
 {
 	/* These applications are built into the PBX core and do not
 	   need separate modules */
 
-	{ "Answer", pbx_builtin_answer, 
-	"Answer a channel if ringing", 
+	{ "Answer", pbx_builtin_answer,
+	"Answer a channel if ringing",
 	"  Answer([delay]): If the call has not been answered, this application will\n"
 	"answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
 	"Asterisk will wait this number of milliseconds before answering the call.\n"
@@ -302,7 +302,7 @@
 	"Otherwise, this application will wait until the calling channel hangs up.\n"
 	},
 
-	{ "Goto", pbx_builtin_goto, 
+	{ "Goto", pbx_builtin_goto,
 	"Jump to a particular priority, extension, or context",
 	"  Goto([[context|]extension|]priority): This application will cause the\n"
 	"calling channel to continue dialplan execution at the specified priority.\n"
@@ -329,7 +329,7 @@
 	"This application will have the calling channel jump to the speicified location\n"
 	"int the dialplan if the current time matches the given time specification.\n"
 	"Further information on the time specification can be found in examples\n"
-	"illustrating how to do time-based context includes in the dialplan.\n" 
+	"illustrating how to do time-based context includes in the dialplan.\n"
 	},
 
 	{ "ExecIfTime", pbx_builtin_execiftime,
@@ -340,7 +340,7 @@
 	"information on the time speicification can be found in examples illustrating\n"
 	"how to do time-based context includes in the dialplan.\n"
 	},
-	
+
 	{ "Hangup", pbx_builtin_hangup,
 	"Hang up the calling channel",
 	"  Hangup(): This application will hang up the calling channel.\n"
@@ -351,7 +351,7 @@
 	"  NoOp(): This applicatiion does nothing. However, it is useful for debugging\n"
 	"purposes. Any text that is provided as arguments to this application can be\n"
 	"viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
-	"variables or functions without having any effect." 
+	"variables or functions without having any effect."
 	},
 
 	{ "Progress", pbx_builtin_progress,
@@ -381,7 +381,7 @@
 	"  SayNumber(digits[,gender]): This application will play the sounds that\n"
 	"correspond to the given number. Optionally, a gender may be specified.\n"
 	"This will use the language that is currently set for the channel. See the\n"
-	"LANGUAGE function for more information on setting the language for the channel.\n"	
+	"LANGUAGE function for more information on setting the language for the channel.\n"
 	},
 
 	{ "SayDigits", pbx_builtin_saydigits,
@@ -395,7 +395,7 @@
 	{ "SayAlpha", pbx_builtin_saycharacters,
 	"Say Alpha",
 	"  SayAlpha(string): This application will play the sounds that correspond to\n"
-	"the letters of the given string.\n" 
+	"the letters of the given string.\n"
 	},
 
 	{ "SayPhonetic", pbx_builtin_sayphonetic,
@@ -425,7 +425,7 @@
 	"channels created from the current channel. If the variable name is prefixed\n"
 	"with __, the variable will be inherited into channels created from the current\n"
 	"channel and all children channels.\n"
-	"  Options:\n" 
+	"  Options:\n"
 	"    g - Set variable globally instead of on the channel\n"
 	"        (applies only to variables, not functions)\n"
 	},
@@ -440,20 +440,20 @@
 	"Set for more information.\n"
 	},
 
-	{ "Wait", pbx_builtin_wait, 
-	"Waits for some time", 
+	{ "Wait", pbx_builtin_wait,
+	"Waits for some time",
 	"  Wait(seconds): This application waits for a specified number of seconds.\n"
 	"Then, dialplan execution will continue at the next priority.\n"
 	"  Note that the seconds can be passed with fractions of a second. For example,\n"
-	"'1.5' will ask the application to wait for 1.5 seconds.\n" 
+	"'1.5' will ask the application to wait for 1.5 seconds.\n"
 	},
 
-	{ "WaitExten", pbx_builtin_waitexten, 
-	"Waits for an extension to be entered", 
+	{ "WaitExten", pbx_builtin_waitexten,
+	"Waits for an extension to be entered",
 	"  WaitExten([seconds][|options]): This application waits for the user to enter\n"
 	"a new extension for a specified number of seconds.\n"
 	"  Note that the seconds can be passed with fractions of a second. For example,\n"
-	"'1.5' will ask the application to wait for 1.5 seconds.\n" 
+	"'1.5' will ask the application to wait for 1.5 seconds.\n"
 	"  Options:\n"
 	"    m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
 	"               Optionally, specify the class for music on hold within parenthesis.\n"
@@ -478,7 +478,7 @@
 static AST_LIST_HEAD_STATIC(hints, ast_hint);
 struct ast_state_cb *statecbs = NULL;
 
-/* 
+/*
    \note This function is special. It saves the stack so that no matter
    how many times it is called, it returns to the same place */
 int pbx_exec(struct ast_channel *c, 		/*!< Channel */
@@ -486,10 +486,10 @@
 		void *data)			/*!< Data for execution */
 {
 	int res;
-	
+
 	const char *saved_c_appl;
 	const char *saved_c_data;
-	
+
 	if (c->cdr)
 		ast_cdr_setapp(c->cdr, app->name, data);
 
@@ -517,15 +517,9 @@
 /*! Go no deeper than this through includes (not counting loops) */
 #define AST_PBX_MAX_STACK	128
 
-#define HELPER_EXISTS 0
-#define HELPER_SPAWN 1
-#define HELPER_CANMATCH 3
-#define HELPER_MATCHMORE 4
-#define HELPER_FINDLABEL 5
-
 /*! \brief Find application handle in linked list
  */
-struct ast_app *pbx_findapp(const char *app) 
+struct ast_app *pbx_findapp(const char *app)
 {
 	struct ast_app *tmp;
 
@@ -534,8 +528,8 @@
 		if (!strcasecmp(tmp->name, app))
 			break;
 	}
-	AST_LIST_UNLOCK(&apps);	
-	
+	AST_LIST_UNLOCK(&apps);
+
 	return tmp;
 }
 
@@ -566,115 +560,143 @@
 	free(p);
 }
 
-#define EXTENSION_MATCH_CORE(data,pattern,match) {\
-	/* All patterns begin with _ */\
-	if (pattern[0] != '_') \
-		return 0;\
-	/* Start optimistic */\
-	match=1;\
-	pattern++;\
-	while(match && *data && *pattern && (*pattern != '/')) {\
-		while (*data == '-' && (*(data+1) != '\0')) data++;\
-		switch(toupper(*pattern)) {\
-		case '[': \
-		{\
-			int i,border=0;\
-			char *where;\
-			match=0;\
-			pattern++;\
-			where=strchr(pattern,']');\
-			if (where)\
-				border=(int)(where-pattern);\
-			if (!where || border > strlen(pattern)) {\
-				ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");\
-				return match;\
-			}\
-			for (i=0; i<border; i++) {\
-				int res=0;\
-				if (i+2<border)\
-					if (pattern[i+1]=='-') {\
-						if (*data >= pattern[i] && *data <= pattern[i+2]) {\
-							res=1;\
-						} else {\
-							i+=2;\
-							continue;\
-						}\
-					}\
-				if (res==1 || *data==pattern[i]) {\
-					match = 1;\
-					break;\
-				}\
-			}\
-			pattern+=border;\
-			break;\
-		}\
-		case 'N':\
-			if ((*data < '2') || (*data > '9'))\
-				match=0;\
-			break;\
-		case 'X':\
-			if ((*data < '0') || (*data > '9'))\
-				match = 0;\
-			break;\
-		case 'Z':\
-			if ((*data < '1') || (*data > '9'))\
-				match = 0;\
-			break;\
-		case '.':\
-			/* Must match */\
-			return 1;\
-		case '!':\
-			/* Early match */\
-			return 2;\
-		case ' ':\
-		case '-':\
-			/* Ignore these characters */\
-			data--;\
-			break;\
-		default:\
-			if (*data != *pattern)\
-				match =0;\
-		}\
-		data++;\
-		pattern++;\
-	}\
-	/* If we ran off the end of the data and the pattern ends in '!', match */\
-	if (match && !*data && (*pattern == '!'))\
-		return 2;\
+/*!
+ * 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 */
+};
+
+/*
+ * 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 (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 _ */
+	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.
+ */
+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)
 {
-	int match;
-	/* If they're the same return */
-	if (!strcmp(pattern, data))
-		return 1;
-	EXTENSION_MATCH_CORE(data,pattern,match);
-	/* Must be at the end of both */
-	if (*data || (*pattern && (*pattern != '/')))
-		match = 0;
-	return match;
+	return extension_match_core(pattern, data, E_MATCH);
 }
 
 int ast_extension_close(const char *pattern, const char *data, int needmore)
 {
-	int match;
-	/* If "data" is longer, it can'be a subset of pattern unless
-	   pattern is a pattern match */
-	if ((strlen(pattern) < strlen(data)) && (pattern[0] != '_'))
-		return 0;
-	
-	if ((ast_strlen_zero((char *)data) || !strncasecmp(pattern, data, strlen(data))) && 
-		(!needmore || (strlen(pattern) > strlen(data)))) {
-		return 1;
-	}
-	EXTENSION_MATCH_CORE(data,pattern,match);
-	/* If there's more or we don't care about more, or if it's a possible early match, 
-	   return non-zero; otherwise it's a miss */
-	if (!needmore || *pattern || match == 2) {
-		return match;
-	} else
-		return 0;
+	if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
+		ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
+	return extension_match_core(pattern, data, needmore);
 }
 
 struct ast_context *ast_context_find(const char *name)
@@ -726,35 +748,33 @@
 };
 
 static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
-	struct ast_context *bypass,
+	struct ast_context *bypass, struct pbx_find_info *q,
 	const char *context, const char *exten, int priority,
-	const char *label, const char *callerid, int action,
-	char *incstack[], int *stacklen, int *status, struct ast_switch **swo,
-	char **data, const char **foundcontext)
+	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;
-	struct ast_switch *asw;
 
 	struct ast_exten *earlymatch = NULL;
 
 	/* Initialize status if appropriate */
-	if (!*stacklen) {
-		*status = STATUS_NO_CONTEXT;
-		*swo = NULL;
-		*data = NULL;
+	if (q->stacklen == 0) {
+		q->status = STATUS_NO_CONTEXT;
+		q->swo = NULL;
+		q->data = NULL;
+		q->foundcontext = NULL;
 	}
 	/* Check for stack overflow */
-	if (*stacklen >= AST_PBX_MAX_STACK) {
+	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 < *stacklen; x++) {
-		if (!strcasecmp(incstack[x], context))
+	for (x = 0; x < q->stacklen; x++) {
+		if (!strcasecmp(q->incstack[x], context))
 			return NULL;
 	}
 	if (bypass)	/* bypass means we only look there */
@@ -767,37 +787,37 @@
 		if (!tmp)
 			return NULL;
 	}
-
-	if (*status < STATUS_NO_EXTENSION)
-		*status = STATUS_NO_EXTENSION;
+	if (q->status < STATUS_NO_EXTENSION)
+		q->status = STATUS_NO_EXTENSION;
 	for (eroot = tmp->root; eroot; eroot = eroot->next) {
-		int match = 0;
+		int match;
 		/* Match extension */
-		if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
-		     ((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
-		     ((action == HELPER_MATCHMORE) && (match = ast_extension_close(eroot->exten, exten, 1)))) &&
+		if ( (match = extension_match_core(eroot->exten, exten, action)) &&
 		     (!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
 
-			if (action == HELPER_MATCHMORE && match == 2 && !earlymatch) {
+			if (action == E_MATCHMORE && match == 2 && !earlymatch) {
+				/* XXX not sure the logic is correct here.
+				 * we should go in irrespective of earlymatch
+				 */
 				/* It matched an extension ending in a '!' wildcard
 				   So ignore it for now, unless there's a better match */
 				earlymatch = eroot;
 			} else {
-				if (*status < STATUS_NO_PRIORITY)
-					*status = STATUS_NO_PRIORITY;
+				if (q->status < STATUS_NO_PRIORITY)
+					q->status = STATUS_NO_PRIORITY;
 				for (e = eroot; e; e = e->peer) {
 					/* Match priority */
-					if (action == HELPER_FINDLABEL) {
-						if (*status < STATUS_NO_LABEL)
-							*status = STATUS_NO_LABEL;
+					if (action == E_FINDLABEL) {
+						if (q->status < STATUS_NO_LABEL)
+							q->status = STATUS_NO_LABEL;
 						if (label && e->label && !strcmp(label, e->label)) {
-							*status = STATUS_SUCCESS;
-							*foundcontext = context;
+							q->status = STATUS_SUCCESS;
+							q->foundcontext = context;
 							return e;
 						}
 					} else if (e->priority == priority) {
-						*status = STATUS_SUCCESS;
-						*foundcontext = context;
+						q->status = STATUS_SUCCESS;
+						q->foundcontext = context;
 						return e;
 					}
 				}
@@ -805,7 +825,7 @@
 		}
 	}
 	if (earlymatch) {
-		/* Bizarre logic for HELPER_MATCHMORE. We return zero to break out 
+		/* Bizarre logic for E_MATCHMORE. We return zero to break out
 		   of the loop waiting for more digits, and _then_ match (normally)
 		   the extension we ended up with. We got an early-matching wildcard
 		   pattern, so return NULL to break out of the loop. */
@@ -813,40 +833,45 @@
 	}
 	/* Check alternative switches */
 	AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
-		if ((asw = pbx_findswitch(sw->name))) {
-			/* Substitute variables now */
-			if (sw->eval) 
-				pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
-			if (action == HELPER_CANMATCH)
-				res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
-			else if (action == HELPER_MATCHMORE)
-				res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
-			else
-				res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
-			if (res) {
-				/* Got a match */
-				*swo = asw;
-				*data = sw->eval ? sw->tmpdata : sw->data;
-				*foundcontext = context;
-				return NULL;
-			}
-		} else {
+		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);
-		}
-	}
-	/* Setup the stack */
-	incstack[*stacklen] = tmp->name;
-	(*stacklen)++;
+			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
+			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, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext))) 
+			if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
 				return e;
-			if (*swo) 
+			if (q->swo)
 				return NULL;
 		}
 	}
-
 	return NULL;
 }
 
@@ -1029,7 +1054,7 @@
 	}
 }
 
-/*! \brief CLI function to show installed custom functions 
+/*! \brief CLI function to show installed custom functions
     \addtogroup CLI_functions
  */
 static int handle_show_functions(int fd, int argc, char *argv[])
@@ -1083,7 +1108,7 @@
 	else
 		synopsis_size = strlen("Not available") + 23;
 	synopsis = alloca(synopsis_size);
-	
+
 	if (acf->desc)
 		description_size = strlen(acf->desc) + 23;
 	else
@@ -1110,7 +1135,7 @@
 	term_color(description,
 		   acf->desc ? acf->desc : "Not available",
 		   COLOR_CYAN, 0, description_size);
-	
+
 	ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
 
 	return RESULT_SUCCESS;
@@ -1133,10 +1158,10 @@
 	}
 	AST_LIST_UNLOCK(&acf_root);
 
-	return ret; 
-}
-
-struct ast_custom_function *ast_custom_function_find(const char *name) 
+	return ret;
+}
+
+struct ast_custom_function *ast_custom_function_find(const char *name)
 {
 	struct ast_custom_function *acf = NULL;
 
@@ -1146,11 +1171,11 @@
 			break;
 	}
 	AST_LIST_UNLOCK(&acf_root);
-	
+
 	return acf;
 }
 
-int ast_custom_function_unregister(struct ast_custom_function *acf) 
+int ast_custom_function_unregister(struct ast_custom_function *acf)
 {
 	struct ast_custom_function *cur;
 
@@ -1167,12 +1192,12 @@
 		}
 	}
 	AST_LIST_TRAVERSE_SAFE_END
-	AST_LIST_UNLOCK(&acf_root);		
+	AST_LIST_UNLOCK(&acf_root);
 
 	return acf ? 0 : -1;
 }
 
-int ast_custom_function_register(struct ast_custom_function *acf) 
+int ast_custom_function_register(struct ast_custom_function *acf)
 {
 	struct ast_custom_function *cur;
 
@@ -1190,7 +1215,7 @@
 	/* Store in alphabetical order */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
 		if (strcasecmp(acf->name, cur->name) < 0) {
-			AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);	
+			AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
 			break;
 		}
 	}
@@ -1257,6 +1282,8 @@
 
 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;
@@ -1265,9 +1292,7 @@
 	char *nextvar, *nextexp, *nextthing;
 	char *vars, *vare;
 	int pos, brackets, needsub, len;
-	
-	/* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
-	   zero-filled */
+
 	whereweare=tmp=cp1;
 	while (!ast_strlen_zero(whereweare) && count) {
 		/* Assume we're copying the whole remaining string */
@@ -1292,15 +1317,15 @@
 			/* 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
@@ -1398,16 +1423,16 @@
 			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)
@@ -1445,75 +1470,79 @@
 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
 {
 	memset(passdata, 0, datalen);
-		
+
 	/* No variables or expressions in e->data, so why scan it? */
 	if (!strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
 		ast_copy_string(passdata, e->data, datalen);
 		return;
 	}
-	
+
 	pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
-}		                                                
-
-static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, int action) 
+}
+
+/*! \brief The return value depends on the action:
+ *
+ * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
+ *	and return 0 on failure, -1 on match;
+ * E_FINDLABEL maps the label to a priority, and returns
+ *	the priority on success, ... XXX
+ * E_SPAWN, spawn an application,
+ *	and return 0 on success, -1 on failure.
+ */
+static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
+	const char *context, const char *exten, int priority,
+	const char *label, const char *callerid, enum ext_match_t action)
 {
 	struct ast_exten *e;
 	struct ast_app *app;
-	struct ast_switch *sw;
-	char *data;
-	const char *foundcontext=NULL;
 	int res;
-	int status = 0;
-	char *incstack[AST_PBX_MAX_STACK];
+	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
 	char passdata[EXT_DATA_SIZE];
-	int stacklen = 0;
-	char tmp[80];
-	char tmp2[80];
-	char tmp3[EXT_DATA_SIZE];
-	char atmp[80];
-	char atmp2[EXT_DATA_SIZE+100];
+
+	int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
 
 	ast_mutex_lock(&conlock);
-
-	e = pbx_find_extension(c, con, context, exten, priority, label, callerid, action, incstack, &stacklen, &status, &sw, &data, &foundcontext);
+	e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
 	if (e) {
-		switch(action) {
-		case HELPER_CANMATCH:
+		if (matching_action) {
 			ast_mutex_unlock(&conlock);
-			return -1;
-		case HELPER_EXISTS:
-			ast_mutex_unlock(&conlock);
-			return -1;
-		case HELPER_FINDLABEL:
+			return -1;	/* success, we found it */
+		} else if (action == E_FINDLABEL) { /* map the label to a priority */
 			res = e->priority;
 			ast_mutex_unlock(&conlock);
-			return res;
-		case HELPER_MATCHMORE:
-			ast_mutex_unlock(&conlock);
-			return -1;
-		case HELPER_SPAWN:
+			return res;	/* the priority we were looking for */
+		} else {	/* spawn */
 			app = pbx_findapp(e->app);
 			ast_mutex_unlock(&conlock);
-			if (app) {
-				if (c->context != context)
-					ast_copy_string(c->context, context, sizeof(c->context));
-				if (c->exten != exten)
-					ast_copy_string(c->exten, exten, sizeof(c->exten));
-				c->priority = priority;
-				pbx_substitute_variables(passdata, sizeof(passdata), c, e);
-				if (option_debug) {
-						ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);

[... 1910 lines stripped ...]


More information about the asterisk-commits mailing list