diff --git a/UPGRADE.txt b/UPGRADE.txt
index f986544523def174bfb5b2dbdcd3544f10783829..1e76c4130e7ae479b5df80c254b5d4f4155f6ccd 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -35,6 +35,16 @@ Core:
   like sin, cos, tan, log, pow, etc. The ability to call external functions
   like CDR(), etc. was also added, without having to use the ${...} notation.
  
+* The delimiter passed to applications has been changed to the comma (','), as
+  that is what people are used to using within extensions.conf.  If you are
+  using realtime extensions, you will need to translate your existing dialplan
+  to use this separator.  To use a literal comma, you need merely to escape it
+  with a backslash ('\').  Another possible side effect is that you may need to
+  remove the obscene level of backslashing that was necessary for the dialplan
+  to work correctly in 1.4 and previous versions.  This should make writing
+  dialplans less painful in the future, albeit with the pain of a one-time
+  conversion.
+
 Voicemail:
 
 * The voicemail configuration values 'maxmessage' and 'minmessage' have
diff --git a/apps/app_channelredirect.c b/apps/app_channelredirect.c
index 2164521a484711ff213d7246a0e4b93787b0631c..0f654251f740982b2a67ea9302997573aebab9dd 100644
--- a/apps/app_channelredirect.c
+++ b/apps/app_channelredirect.c
@@ -45,15 +45,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static char *app = "ChannelRedirect";
 static char *synopsis = "Redirects given channel to a dialplan target.";
 static char *descrip = 
-"ChannelRedirect(channel|[[context|]extension|]priority):\n"
+"ChannelRedirect(channel,[[context,]extension,]priority)\n"
 "  Sends the specified channel to the specified extension priority\n";
 
 
 static int asyncgoto_exec(struct ast_channel *chan, void *data)
 {
 	int res = -1;
-	char *info, *context, *exten, *priority;
-	int prio = 1;
+	char *info;
 	struct ast_channel *chan2 = NULL;
 
 	AST_DECLARE_APP_ARGS(args,
@@ -62,7 +61,7 @@ static int asyncgoto_exec(struct ast_channel *chan, void *data)
 	);
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "%s requires an argument (channel|[[context|]exten|]priority)\n", app);
+		ast_log(LOG_WARNING, "%s requires an argument (channel,[[context,]exten,]priority)\n", app);
 		return -1;
 	}
 
@@ -70,7 +69,7 @@ static int asyncgoto_exec(struct ast_channel *chan, void *data)
 	AST_STANDARD_APP_ARGS(args, info);
 
 	if (ast_strlen_zero(args.channel) || ast_strlen_zero(args.label)) {
-		ast_log(LOG_WARNING, "%s requires an argument (channel|[[context|]exten|]priority)\n", app);
+		ast_log(LOG_WARNING, "%s requires an argument (channel,[[context,]exten,]priority)\n", app);
 		goto quit;
 	}
 
@@ -80,38 +79,10 @@ static int asyncgoto_exec(struct ast_channel *chan, void *data)
 		goto quit;
 	}
 
-	/* Parsed right to left, so standard parsing won't work */
-	context = strsep(&args.label, "|");
-	exten = strsep(&args.label, "|");
-	if (exten) {
-		priority = strsep(&args.label, "|");
-		if (!priority) {
-			priority = exten;
-			exten = context;
-			context = NULL;
-		}
-	} else {
-		priority = context;
-		context = NULL;
-	}
-
-	/* ast_findlabel_extension does not convert numeric priorities; it only does a lookup */
-	if (!(prio = atoi(priority)) && !(prio = ast_findlabel_extension(chan2, S_OR(context, chan2->context),
-									S_OR(exten, chan2->exten), priority, chan2->cid.cid_num))) {
-		ast_log(LOG_WARNING, "'%s' is not a known priority or label\n", priority);
-		goto chanquit;
-	}
-
-	ast_debug(2, "Attempting async goto (%s) to %s|%s|%d\n", args.channel, S_OR(context, chan2->context), S_OR(exten, chan2->exten), prio);
-
-	if (ast_async_goto_if_exists(chan2, S_OR(context, chan2->context), S_OR(exten, chan2->exten), prio))
-		ast_log(LOG_WARNING, "%s failed for %s\n", app, args.channel);
-	else
-		res = 0;
+	res = ast_parseable_goto(chan2, args.label);
 
- chanquit:
 	ast_mutex_unlock(&chan2->lock);
- quit:
+quit:
 
 	return res;
 }
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c
index 80f3c530c30b62390a703baa8b0603a6d1ccb587..78817451594d9ce306c52da59f6910cefc70f355 100644
--- a/apps/app_chanspy.c
+++ b/apps/app_chanspy.c
@@ -626,33 +626,27 @@ exit:
 
 static int chanspy_exec(struct ast_channel *chan, void *data)
 {
-	char *options = NULL;
-	char *spec = NULL;
-	char *argv[2];
 	char *mygroup = NULL;
 	char *recbase = NULL;
 	int fd = 0;
 	struct ast_flags flags;
 	int oldwf = 0;
-	int argc = 0;
 	int volfactor = 0;
 	int res;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(spec);
+		AST_APP_ARG(options);
+	);
+	char *opts[OPT_ARG_ARRAY_SIZE];
 
 	data = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, data);
 
-	if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
-		spec = argv[0];
-		if (argc > 1)
-			options = argv[1];
+	if (args.spec && !strcmp(args.spec, "all"))
+		args.spec = NULL;
 
-		if (ast_strlen_zero(spec) || !strcmp(spec, "all"))
-			spec = NULL;
-	}
-
-	if (options) {
-		char *opts[OPT_ARG_ARRAY_SIZE];
-		
-		ast_app_parse_options(spy_opts, &flags, opts, options);
+	if (args.options) {
+		ast_app_parse_options(spy_opts, &flags, opts, args.options);
 		if (ast_test_flag(&flags, OPTION_GROUP))
 			mygroup = opts[OPT_ARG_GROUP];
 
@@ -690,7 +684,7 @@ static int chanspy_exec(struct ast_channel *chan, void *data)
 		}
 	}
 
-	res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
+	res = common_exec(chan, &flags, volfactor, fd, mygroup, args.spec, NULL, NULL);
 
 	if (fd)
 		close(fd);
@@ -703,35 +697,35 @@ static int chanspy_exec(struct ast_channel *chan, void *data)
 
 static int extenspy_exec(struct ast_channel *chan, void *data)
 {
-	char *options = NULL;
-	char *exten = NULL;
-	char *context = NULL;
-	char *argv[2];
+	char *ptr, *exten = NULL;
 	char *mygroup = NULL;
 	char *recbase = NULL;
 	int fd = 0;
 	struct ast_flags flags;
 	int oldwf = 0;
-	int argc = 0;
 	int volfactor = 0;
 	int res;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(context);
+		AST_APP_ARG(options);
+	);
 
 	data = ast_strdupa(data);
 
-	if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
-		context = argv[0];
-		if (!ast_strlen_zero(argv[0]))
-			exten = strsep(&context, "@");
-		if (ast_strlen_zero(context))
-			context = ast_strdupa(chan->context);
-		if (argc > 1)
-			options = argv[1];
+	AST_STANDARD_APP_ARGS(args, data);
+	if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
+		exten = args.context;
+		*ptr++ = '\0';
+		args.context = ptr;
 	}
 
-	if (options) {
+	if (ast_strlen_zero(args.context))
+		args.context = ast_strdupa(chan->context);
+
+	if (args.options) {
 		char *opts[OPT_ARG_ARRAY_SIZE];
 		
-		ast_app_parse_options(spy_opts, &flags, opts, options);
+		ast_app_parse_options(spy_opts, &flags, opts, args.options);
 		if (ast_test_flag(&flags, OPTION_GROUP))
 			mygroup = opts[OPT_ARG_GROUP];
 
@@ -769,7 +763,7 @@ static int extenspy_exec(struct ast_channel *chan, void *data)
 		}
 	}
 
-	res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
+	res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, args.context);
 
 	if (fd)
 		close(fd);
diff --git a/apps/app_controlplayback.c b/apps/app_controlplayback.c
index 8f7a7fd617ca72ec757e0261c369055ae03147a5..113cf25faaaa0093a5d26fcea7e90d75af90a679 100644
--- a/apps/app_controlplayback.c
+++ b/apps/app_controlplayback.c
@@ -94,20 +94,18 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
 	long offsetms = 0;
 	char offsetbuf[20];
 	char *tmp;
-	int argc;
-	char *argv[8] = { NULL, };
-	enum arg_ids {
-		arg_file = 0,
-		arg_skip = 1,
-		arg_fwd = 2,
-		arg_rev = 3,
-		arg_stop = 4,
-		arg_pause = 5,
-		arg_restart = 6,
-		options = 7,
-	};
 	struct ast_flags opts = { 0, };
 	char *opt_args[OPT_ARG_ARRAY_LEN];
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(filename);
+		AST_APP_ARG(skip);
+		AST_APP_ARG(fwd);
+		AST_APP_ARG(rev);
+		AST_APP_ARG(stop);
+		AST_APP_ARG(pause);
+		AST_APP_ARG(restart);
+		AST_APP_ARG(options);
+	);
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
@@ -115,39 +113,36 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
 	}
 	
 	tmp = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, tmp);
 
-	argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
-
-	if (argc < 1) {
+	if (args.argc < 1) {
 		ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
 		return -1;
 	}
 
-	skipms = argv[arg_skip] ? atoi(argv[arg_skip]) : 3000;
-	if (!skipms)
-		skipms = 3000;
-
-	if (!argv[arg_fwd] || !is_on_phonepad(*argv[arg_fwd]))
-		argv[arg_fwd] = "#";
-	if (!argv[arg_rev] || !is_on_phonepad(*argv[arg_rev]))
-		argv[arg_rev] = "*";
-	if (argv[arg_stop] && !is_on_phonepad(*argv[arg_stop]))
-		argv[arg_stop] = NULL;
-	if (argv[arg_pause] && !is_on_phonepad(*argv[arg_pause]))
-		argv[arg_pause] = NULL;
-	if (argv[arg_restart] && !is_on_phonepad(*argv[arg_restart]))
-		argv[arg_restart] = NULL;
-
-	if (argv[options]) {
-		ast_app_parse_options(cpb_opts, &opts, opt_args, argv[options]);		
+	skipms = args.skip ? (atoi(args.skip) ? atoi(args.skip) : 3000) : 3000;
+
+	if (!args.fwd || !is_on_phonepad(*args.fwd))
+		args.fwd = "#";
+	if (!args.rev || !is_on_phonepad(*args.rev))
+		args.rev = "*";
+	if (args.stop && !is_on_phonepad(*args.stop))
+		args.stop = NULL;
+	if (args.pause && !is_on_phonepad(*args.pause))
+		args.pause = NULL;
+	if (args.restart && !is_on_phonepad(*args.restart))
+		args.restart = NULL;
+
+	if (args.options) {
+		ast_app_parse_options(cpb_opts, &opts, opt_args, args.options);		
 		if (ast_test_flag(&opts, OPT_OFFSET))
 			offsetms = atol(opt_args[OPT_ARG_OFFSET]);
 	}
 
-	res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms, &offsetms);
+	res = ast_control_streamfile(chan, args.filename, args.fwd, args.rev, args.stop, args.pause, args.restart, skipms, &offsetms);
 
 	/* If we stopped on one of our stop keys, return 0  */
-	if (argv[arg_stop] && strchr(argv[arg_stop], res)) {
+	if (args.stop && strchr(args.stop, res)) {
 		res = 0;
 		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
 	} else {
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 29f059a02d92d703f9bebd4393c3da25aef1fc1f..0acdc1751d471a7e48286413cb270ef376cfe737 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -66,7 +66,7 @@ static char *app = "Dial";
 static char *synopsis = "Place a call and connect to the current channel";
 
 static char *descrip =
-"  Dial(Technology/resource[&Tech2/resource2...][|timeout][|options][|URL]):\n"
+"  Dial(Technology/resource[&Tech2/resource2...][,timeout][,options][,URL]):\n"
 "This application will place calls to one or more specified channels. As soon\n"
 "as one of the requested channels answers, the originating channel will be\n"
 "answered, if it has not already been answered. These two channels will then\n"
@@ -215,7 +215,7 @@ static char *descrip =
 static char *rapp = "RetryDial";
 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
 static char *rdescrip =
-"  RetryDial(announce|sleep|retries|dialargs): This application will attempt to\n"
+"  RetryDial(announce,sleep,retries,dialargs): This application will attempt to\n"
 "place a call using the normal Dial application. If no channel can be reached,\n"
 "the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
 "seconds before retying the call. After 'retires' number of attempts, the\n"
@@ -840,7 +840,7 @@ static void replace_macro_delimiter(char *s)
 {
 	for (; *s; s++)
 		if (*s == '^')
-			*s = '|';
+			*s = ',';
 }
 
 
@@ -1856,41 +1856,33 @@ static int dial_exec(struct ast_channel *chan, void *data)
 
 static int retrydial_exec(struct ast_channel *chan, void *data)
 {
-	char *announce = NULL, *dialdata = NULL;
+	char *parse;
 	const char *context = NULL;
 	int sleep = 0, loops = 0, res = -1;
-	struct ast_flags64 peerflags;
-	
+	struct ast_flags64 peerflags = { 0, };
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(announce);
+		AST_APP_ARG(sleep);
+		AST_APP_ARG(retries);
+		AST_APP_ARG(dialdata);
+	);
+
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
 		return -1;
 	}	
 
-	announce = ast_strdupa(data);
-
-	memset(&peerflags, 0, sizeof(peerflags));
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
 
-	if ((dialdata = strchr(announce, '|'))) {
-		*dialdata++ = '\0';
-		if (sscanf(dialdata, "%d", &sleep) == 1) {
-			sleep *= 1000;
-		} else {
-			ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
-			goto done;
-		}
-		if ((dialdata = strchr(dialdata, '|'))) {
-			*dialdata++ = '\0';
-			if (sscanf(dialdata, "%d", &loops) != 1) {
-				ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
-				goto done;
-			}
-		}
+	if ((sleep = atoi(args.sleep))) {
+		sleep *= 1000;
 	}
-	
-	if ((dialdata = strchr(dialdata, '|'))) {
-		*dialdata++ = '\0';
-	} else {
-		ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
+
+	loops = atoi(args.retries);
+
+	if (!args.dialdata) {
+		ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp);
 		goto done;
 	}
 		
@@ -1910,18 +1902,18 @@ static int retrydial_exec(struct ast_channel *chan, void *data)
 		if (ast_test_flag(chan, AST_FLAG_MOH))
 			ast_moh_stop(chan);
 
-		res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec);
+		res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec);
 		if (continue_exec)
 			break;
 
 		if (res == 0) {
 			if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) {
-				if (!ast_strlen_zero(announce)) {
-					if (ast_fileexists(announce, NULL, chan->language) > 0) {
-						if(!(res = ast_streamfile(chan, announce, chan->language)))								
+				if (!ast_strlen_zero(args.announce)) {
+					if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
+						if(!(res = ast_streamfile(chan, args.announce, chan->language)))								
 							ast_waitstream(chan, AST_DIGIT_ANY);
 					} else
-						ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
+						ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
 				}
 				if (!res && sleep) {
 					if (!ast_test_flag(chan, AST_FLAG_MOH))
@@ -1929,12 +1921,12 @@ static int retrydial_exec(struct ast_channel *chan, void *data)
 					res = ast_waitfordigit(chan, sleep);
 				}
 			} else {
-				if (!ast_strlen_zero(announce)) {
-					if (ast_fileexists(announce, NULL, chan->language) > 0) {
-						if (!(res = ast_streamfile(chan, announce, chan->language)))
+				if (!ast_strlen_zero(args.announce)) {
+					if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
+						if (!(res = ast_streamfile(chan, args.announce, chan->language)))
 							res = ast_waitstream(chan, "");
 					} else
-						ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
+						ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
 				}
 				if (sleep) {
 					if (!ast_test_flag(chan, AST_FLAG_MOH))
diff --git a/apps/app_exec.c b/apps/app_exec.c
index b953e81292e5f51ec659a15ae319fd4b2c9a9c0f..2423580fe158e0f6783f699764f806e75fd62906 100644
--- a/apps/app_exec.c
+++ b/apps/app_exec.c
@@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
+#include "asterisk/app.h"
 
 /* Maximum length of any variable */
 #define MAXRESULT	1024
@@ -83,7 +84,7 @@ static char *tryexec_descrip =
 static char *app_execif = "ExecIf";
 static char *execif_synopsis = "Executes dialplan application, conditionally";
 static char *execif_descrip = 
-"Usage:  ExecIF (<expr>|<app>|<data>)\n"
+"Usage:  ExecIF (<expr>?<app>(<data>):<app2>(<data2>))\n"
 "If <expr> is true, execute and return the result of <app>(<data>).\n"
 "If <expr> is true, but <app> is not found, then the application\n"
 "will return a non-zero value.\n";
@@ -152,33 +153,47 @@ static int tryexec_exec(struct ast_channel *chan, void *data)
 static int execif_exec(struct ast_channel *chan, void *data)
 {
 	int res = 0;
-	char *myapp = NULL;
-	char *mydata = NULL;
-	char *expr = NULL;
+	char *truedata = NULL, *falsedata = NULL, *end;
 	struct ast_app *app = NULL;
+	AST_DECLARE_APP_ARGS(expr,
+		AST_APP_ARG(expr);
+		AST_APP_ARG(remainder);
+	);
+	AST_DECLARE_APP_ARGS(apps,
+		AST_APP_ARG(true);
+		AST_APP_ARG(false);
+	);
+	char *parse = ast_strdupa(data);
+
+	AST_NONSTANDARD_APP_ARGS(expr, parse, '?');
+	AST_NONSTANDARD_APP_ARGS(apps, expr.remainder, ':');
+
+	if (apps.true && (truedata = strchr(apps.true, '('))) {
+		*truedata++ = '\0';
+		if ((end = strrchr(truedata, ')')))
+			*end = '\0';
+	}
+
+	if (apps.false && (falsedata = strchr(apps.false, '('))) {
+		*falsedata++ = '\0';
+		if ((end = strrchr(falsedata, ')')))
+			*end = '\0';
+	}
 
-	expr = ast_strdupa(data);
-
-	if ((myapp = strchr(expr,'|'))) {
-		*myapp = '\0';
-		myapp++;
-		if ((mydata = strchr(myapp,'|'))) {
-			*mydata = '\0';
-			mydata++;
-		} else
-			mydata = "";
-
-		if (pbx_checkcondition(expr)) { 
-			if ((app = pbx_findapp(myapp))) {
-				res = pbx_exec(chan, app, mydata);
-			} else {
-				ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
-				res = -1;
-			}
+	if (pbx_checkcondition(expr.expr)) { 
+		if (!ast_strlen_zero(apps.true) && (app = pbx_findapp(apps.true))) {
+			res = pbx_exec(chan, app, S_OR(truedata, ""));
+		} else {
+			ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.true);
+			res = -1;
 		}
 	} else {
-		ast_log(LOG_ERROR,"Invalid Syntax.\n");
-		res = -1;
+		if (!ast_strlen_zero(apps.false) && (app = pbx_findapp(apps.false))) {
+			res = pbx_exec(chan, app, S_OR(falsedata, ""));
+		} else {
+			ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.false);
+			res = -1;
+		}
 	}
 
 	return res;
diff --git a/apps/app_externalivr.c b/apps/app_externalivr.c
index 63c182337fcfd4e1b9d516e18141d2c868c85406..31cdafd0a3f00d3a96facf6663032d067df81b56 100644
--- a/apps/app_externalivr.c
+++ b/apps/app_externalivr.c
@@ -58,7 +58,7 @@ static const char *app = "ExternalIVR";
 static const char *synopsis = "Interfaces with an external IVR application";
 
 static const char *descrip = 
-"  ExternalIVR(command[|arg[|arg...]]): Forks an process to run the supplied command,\n"
+"  ExternalIVR(command[,arg[,arg...]]): Forks an process to run the supplied command,\n"
 "and starts a generator on the channel. The generator's play list is\n"
 "controlled by the external application, which can add and clear entries\n"
 "via simple commands issued over its stdout. The external application\n"
@@ -244,7 +244,6 @@ static struct playlist_entry *make_entry(const char *filename)
 static int app_exec(struct ast_channel *chan, void *data)
 {
 	struct playlist_entry *entry;
-	const char *args = data;
 	int child_stdin[2] = { 0,0 };
 	int child_stdout[2] = { 0,0 };
 	int child_stderr[2] = { 0,0 };
@@ -252,7 +251,6 @@ static int app_exec(struct ast_channel *chan, void *data)
 	int gen_active = 0;
 	int pid;
 	char *argv[32];
-	int argc = 1;
 	char *buf, *command;
 	FILE *child_commands = NULL;
 	FILE *child_errors = NULL;
@@ -263,6 +261,9 @@ static int app_exec(struct ast_channel *chan, void *data)
 	};
 	struct ivr_localuser *u = &foo;
 	sigset_t fullset, oldset;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(cmd)[32];
+	);
 
 	sigfillset(&fullset);
 	pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
@@ -270,14 +271,13 @@ static int app_exec(struct ast_channel *chan, void *data)
 	u->abort_current_sound = 0;
 	u->chan = chan;
 	
-	if (ast_strlen_zero(args)) {
+	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
 		return -1;	
 	}
 
 	buf = ast_strdupa(data);
-
-	argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0]));
+	AST_STANDARD_APP_ARGS(args, buf);
 
 	if (pipe(child_stdin)) {
 		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
diff --git a/apps/app_macro.c b/apps/app_macro.c
index 5f71bcd7f865b8240ec5a153de0c416206f83e42..aa24dd94cbeeb0c5969b6344a039005478d02da2 100644
--- a/apps/app_macro.c
+++ b/apps/app_macro.c
@@ -197,7 +197,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
 
 	tmp = ast_strdupa(data);
 	rest = tmp;
-	macro = strsep(&rest, "|");
+	macro = strsep(&rest, ",");
 	if (ast_strlen_zero(macro)) {
 		ast_log(LOG_WARNING, "Invalid macro name specified\n");
 		return 0;
@@ -255,7 +255,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
 	ast_copy_string(chan->context, fullmacro, sizeof(chan->context));
 	chan->priority = 1;
 
-	while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
+	while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
 		const char *s;
   		/* Save copy of old arguments if we're overwriting some, otherwise
 	   	let them pass through to the other macro */
diff --git a/apps/app_page.c b/apps/app_page.c
index 8edb1583312d6465cab7937e9dc07b9fe3672f42..8b90fc0b44cffd49020b4263a479a6d14e1e9669 100644
--- a/apps/app_page.c
+++ b/apps/app_page.c
@@ -86,7 +86,7 @@ AST_APP_OPTIONS(page_opts, {
 static int page_exec(struct ast_channel *chan, void *data)
 {
 	char *options, *tech, *resource, *tmp;
-	char meetmeopts[88], originator[AST_CHANNEL_NAME];
+	char meetmeopts[88], originator[AST_CHANNEL_NAME], *opts[0];
 	struct ast_flags flags = { 0 };
 	unsigned int confid = ast_random();
 	struct ast_app *app;
@@ -109,9 +109,9 @@ static int page_exec(struct ast_channel *chan, void *data)
 	if ((tmp = strchr(originator, '-')))
 		*tmp = '\0';
 
-	tmp = strsep(&options, "|");
+	tmp = strsep(&options, ",");
 	if (options)
-		ast_app_parse_options(page_opts, &flags, NULL, options);
+		ast_app_parse_options(page_opts, &flags, opts, options);
 
 	snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe|%ud|%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
 		(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
diff --git a/apps/app_parkandannounce.c b/apps/app_parkandannounce.c
index 138694c5ae400c1b0bf6a192b30e833a095b1aca..d7d5fc787ac84f1d2e5208ef21d524b43e112d40 100644
--- a/apps/app_parkandannounce.c
+++ b/apps/app_parkandannounce.c
@@ -50,6 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/say.h"
 #include "asterisk/lock.h"
 #include "asterisk/utils.h"
+#include "asterisk/app.h"
 
 static char *app = "ParkAndAnnounce";
 
@@ -76,113 +77,72 @@ static char *descrip =
 
 static int parkandannounce_exec(struct ast_channel *chan, void *data)
 {
-	int res=0;
-	char *return_context;
+	int res = -1;
 	int lot, timeout = 0, dres;
-	char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
-	char *template, *tpl_working, *tpl_current;
-	char *tmp[100];
-	char buf[13];
-	int looptemp=0,i=0;
+	char *dialtech, *tmp[100], buf[13];
+	int looptemp, i;
 	char *s;
 
 	struct ast_channel *dchan;
-	struct outgoing_helper oh;
+	struct outgoing_helper oh = { 0, };
 	int outstate;
-
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(template);
+		AST_APP_ARG(timeout);
+		AST_APP_ARG(dial);
+		AST_APP_ARG(return_context);
+	);
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
 		return -1;
 	}
   
 	s = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, s);
 
-	template=strsep(&s,"|");
-	if(! template) {
-		ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
-		return -1;
-	}
-  
-	if(s) {
-		timeout = atoi(strsep(&s, "|"));
-		timeout *= 1000;
-	}
-	dial=strsep(&s, "|");
-	if(!dial) {
+	if (args.timeout)
+		timeout = atoi(args.timeout) * 1000;
+
+	if (ast_strlen_zero(args.dial)) {
 		ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
 		return -1;
-	} else {
-		dialtech=strsep(&dial, "/");
-		dialstr=dial;
-		ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
 	}
 
-	return_context = s;
-  
-	if(return_context != NULL) {
-		/* set the return context. Code borrowed from the Goto builtin */
-    
-		working = return_context;
-		context = strsep(&working, "|");
-		exten = strsep(&working, "|");
-		if(!exten) {
-			/* Only a priority in this one */
-			priority = context;
-			exten = NULL;
-			context = NULL;
-		} else {
-			priority = strsep(&working, "|");
-			if(!priority) {
-				/* Only an extension and priority in this one */
-				priority = exten;
-				exten = context;
-				context = NULL;
-		}
-	}
-	if(atoi(priority) < 0) {
-		ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
-		return -1;
-	}
-	/* At this point we have a priority and maybe an extension and a context */
-	chan->priority = atoi(priority);
-	if (exten)
-		ast_copy_string(chan->exten, exten, sizeof(chan->exten));
-	if (context)
-		ast_copy_string(chan->context, context, sizeof(chan->context));
-	} else {  /* increment the priority by default*/
-		chan->priority++;
-	}
+	dialtech = strsep(&args.dial, "/");
+	if (option_verbose > 2)
+		ast_verbose(VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech, args.dial);
+
+	if (!ast_strlen_zero(args.return_context))
+		ast_parseable_goto(chan, args.return_context);
 
-	if(option_verbose > 2) {
-		ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
-		if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
-			ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
+	if (option_verbose > 2) {
+		ast_verbose(VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context, chan->exten, chan->priority, chan->cid.cid_num);
+		if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
+			ast_verbose(VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
 		}
 	}
-  
+
 	/* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
 	before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
 
 	ast_masq_park_call(chan, NULL, timeout, &lot);
 
-	res=-1; 
-
-	ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
+	if (option_verbose > 2)
+		ast_verbose(VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, args.return_context);
 
-	/* Now place the call to the extention */
+	/* Now place the call to the extension */
 
 	snprintf(buf, sizeof(buf), "%d", lot);
-	memset(&oh, 0, sizeof(oh));
 	oh.parent_channel = chan;
 	oh.vars = ast_variable_new("_PARKEDAT", buf);
-	dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
+	dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, args.dial, 30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
 
-	if(dchan) {
-		if(dchan->_state == AST_STATE_UP) {
-			if(option_verbose > 3)
+	if (dchan) {
+		if (dchan->_state == AST_STATE_UP) {
+			if (option_verbose > 3)
 				ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
 		} else {
-			if(option_verbose > 3)
+			if (option_verbose > 3)
 				ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
         			ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
 			ast_hangup(dchan);
@@ -197,24 +157,21 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
 
 	/* now we have the call placed and are ready to play stuff to it */
 
-	ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
+	if (option_verbose > 3)
+		ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", args.template);
 
-	tpl_working = template;
-	tpl_current=strsep(&tpl_working, ":");
-
-	while(tpl_current && looptemp < sizeof(tmp)) {
-		tmp[looptemp]=tpl_current;
-		looptemp++;
-		tpl_current=strsep(&tpl_working,":");
-	}
+	for (looptemp = 0, tmp[looptemp++] = strsep(&args.template, ":");
+		 looptemp < sizeof(tmp) / sizeof(tmp[0]);
+		 tmp[looptemp++] = strsep(&args.template, ":"));
 
-	for(i=0; i<looptemp; i++) {
-		ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
-		if(!strcmp(tmp[i], "PARKED")) {
+	for (i = 0; i < looptemp; i++) {
+		if (option_verbose > 3)
+			ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
+		if (!strcmp(tmp[i], "PARKED")) {
 			ast_say_digits(dchan, lot, "", dchan->language);
 		} else {
 			dres = ast_streamfile(dchan, tmp[i], dchan->language);
-			if(!dres) {
+			if (!dres) {
 				dres = ast_waitstream(dchan, "");
 			} else {
 				ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
diff --git a/apps/app_queue.c b/apps/app_queue.c
index a99b38593c4069356797bfcef111ae2e612c0a14..dafbafb8af354af88088b25051e46d58b7b34e3f 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -930,11 +930,11 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
 		else
 			q->announceholdtime = 0;
 	} else if (!strcasecmp(param, "periodic-announce")) {
-		if (strchr(val, '|')) {
+		if (strchr(val, ',')) {
 			char *s, *buf = ast_strdupa(val);
 			unsigned int i = 0;
 
-			while ((s = strsep(&buf, "|"))) {
+			while ((s = strsep(&buf, ",|"))) {
 				ast_copy_string(q->sound_periodicannounce[i], s, sizeof(q->sound_periodicannounce[i]));
 				i++;
 				if (i == MAX_PERIODIC_ANNOUNCEMENTS)
@@ -3179,7 +3179,7 @@ static void reload_queue_members(void)
 			continue;
 
 		cur_ptr = queue_data;
-		while ((member = strsep(&cur_ptr, "|"))) {
+		while ((member = strsep(&cur_ptr, ",|"))) {
 			if (ast_strlen_zero(member))
 				continue;
 
diff --git a/apps/app_readfile.c b/apps/app_readfile.c
index e857f8318d521624df4974150e06dcfbfefa0d51..c230376106394410264df1de9cd01915e30aeec2 100644
--- a/apps/app_readfile.c
+++ b/apps/app_readfile.c
@@ -67,7 +67,7 @@ static int readfile_exec(struct ast_channel *chan, void *data)
 	s = ast_strdupa(data);
 
 	varname = strsep(&s, "=");
-	file = strsep(&s, "|");
+	file = strsep(&s, ",");
 	length = s;
 
 	if (!varname || !file) {
diff --git a/apps/app_record.c b/apps/app_record.c
index 0bbe0b0082d6bfb7f063b5d973bbe3f14706a4e2..1742e0796d68c21a20297e09941f79f67286619b 100644
--- a/apps/app_record.c
+++ b/apps/app_record.c
@@ -74,19 +74,35 @@ static char *descrip =
 "If the user should hangup during a recording, all data will be lost and the\n"
 "application will teminate. \n";
 
+enum {
+	OPTION_APPEND = (1 << 0),
+	OPTION_NOANSWER = (1 << 1),
+	OPTION_QUIET = (1 << 2),
+	OPTION_SKIP = (1 << 3),
+	OPTION_STAR_TERMINATE = (1 << 4),
+	OPTION_IGNORE_TERMINATE = (1 << 5),
+	FLAG_HAS_PERCENT = (1 << 6),
+};
+
+AST_APP_OPTIONS(app_opts,{
+	AST_APP_OPTION('a', OPTION_APPEND),
+	AST_APP_OPTION('n', OPTION_NOANSWER),
+	AST_APP_OPTION('q', OPTION_QUIET),
+	AST_APP_OPTION('s', OPTION_SKIP),
+	AST_APP_OPTION('t', OPTION_STAR_TERMINATE),
+	AST_APP_OPTION('x', OPTION_IGNORE_TERMINATE),
+});
 
 static int record_exec(struct ast_channel *chan, void *data)
 {
 	int res = 0;
 	int count = 0;
-	int percentflag = 0;
-	char *filename, *ext = NULL, *silstr, *maxstr, *options;
-	char *file, *dir;
-	char *vdata, *p;
+	char *ext = NULL, *opts[0];
+	char *parse, *dir, *file;
 	int i = 0;
 	char tmp[256];
 
-	struct ast_filestream *s = '\0';
+	struct ast_filestream *s = NULL;
 	struct ast_frame *f = NULL;
 	
 	struct ast_dsp *sildet = NULL;   	/* silence detector dsp */
@@ -96,15 +112,18 @@ static int record_exec(struct ast_channel *chan, void *data)
 	int gotsilence = 0;		/* did we timeout for silence? */
 	int maxduration = 0;		/* max duration of recording in milliseconds */
 	int gottimeout = 0;		/* did we timeout for maxduration exceeded? */
-	int option_skip = 0;
-	int option_noanswer = 0;
-	int option_append = 0;
 	int terminator = '#';
-	int option_quiet = 0;
 	int rfmt = 0;
-	int flags;
+	int ioflags;
 	int waitres;
 	struct ast_silence_generator *silgen = NULL;
+	struct ast_flags flags;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(filename);
+		AST_APP_ARG(silence);
+		AST_APP_ARG(maxduration);
+		AST_APP_ARG(options);
+	);
 	
 	/* The next few lines of code parse out the filename and header from the input string */
 	if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
@@ -112,21 +131,17 @@ static int record_exec(struct ast_channel *chan, void *data)
 		return -1;
 	}
 
-	/* Yay for strsep being easy */
-	vdata = ast_strdupa(data);
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+	if (args.argc == 4)
+		ast_app_parse_options(app_opts, &flags, opts, args.options);
 
-	p = vdata;
-	filename = strsep(&p, "|");
-	silstr = strsep(&p, "|");
-	maxstr = strsep(&p, "|");	
-	options = strsep(&p, "|");
-	
-	if (filename) {
-		if (strstr(filename, "%d"))
-			percentflag = 1;
-		ext = strrchr(filename, '.'); /* to support filename with a . in the filename, not format */
+	if (!ast_strlen_zero(args.filename)) {
+		if (strstr(args.filename, "%d"))
+			ast_set_flag(&flags, FLAG_HAS_PERCENT);
+		ext = strrchr(args.filename, '.'); /* to support filename with a . in the filename, not format */
 		if (!ext)
-			ext = strchr(filename, ':');
+			ext = strchr(args.filename, ':');
 		if (ext) {
 			*ext = '\0';
 			ext++;
@@ -136,52 +151,36 @@ static int record_exec(struct ast_channel *chan, void *data)
 		ast_log(LOG_WARNING, "No extension specified to filename!\n");
 		return -1;
 	}
-	if (silstr) {
-		if ((sscanf(silstr, "%d", &i) == 1) && (i > -1)) {
+	if (args.silence) {
+		if ((sscanf(args.silence, "%d", &i) == 1) && (i > -1)) {
 			silence = i * 1000;
-		} else if (!ast_strlen_zero(silstr)) {
-			ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", silstr);
+		} else if (!ast_strlen_zero(args.silence)) {
+			ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", args.silence);
 		}
 	}
 	
-	if (maxstr) {
-		if ((sscanf(maxstr, "%d", &i) == 1) && (i > -1))
+	if (args.maxduration) {
+		if ((sscanf(args.maxduration, "%d", &i) == 1) && (i > -1))
 			/* Convert duration to milliseconds */
 			maxduration = i * 1000;
-		else if (!ast_strlen_zero(maxstr))
-			ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", maxstr);
+		else if (!ast_strlen_zero(args.maxduration))
+			ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", args.maxduration);
 	}
-	if (options) {
-		/* Retain backwards compatibility with old style options */
-		if (!strcasecmp(options, "skip"))
-			option_skip = 1;
-		else if (!strcasecmp(options, "noanswer"))
-			option_noanswer = 1;
-		else {
-			if (strchr(options, 's'))
-				option_skip = 1;
-			if (strchr(options, 'n'))
-				option_noanswer = 1;
-			if (strchr(options, 'a'))
-				option_append = 1;
-			if (strchr(options, 't'))
-				terminator = '*';
-			if (strchr(options, 'x'))
-				terminator = 0;
-			if (strchr(options, 'q'))
-				option_quiet = 1;
-		}
-	}
-	
+
+	if (ast_test_flag(&flags, OPTION_STAR_TERMINATE))
+		terminator = '*';
+	if (ast_test_flag(&flags, OPTION_IGNORE_TERMINATE))
+		terminator = '\0';
+
 	/* done parsing */
-	
+
 	/* these are to allow the use of the %d in the config file for a wild card of sort to
 	  create a new file with the inputed name scheme */
-	if (percentflag) {
+	if (ast_test_flag(&flags, FLAG_HAS_PERCENT)) {
 		AST_DECLARE_APP_ARGS(fname,
 			AST_APP_ARG(piece)[100];
 		);
-		char *tmp2 = ast_strdupa(filename);
+		char *tmp2 = ast_strdupa(args.filename);
 		char countstring[15];
 		int i;
 
@@ -210,27 +209,25 @@ static int record_exec(struct ast_channel *chan, void *data)
 		} while (ast_fileexists(tmp, ext, chan->language) > 0);
 		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
 	} else
-		ast_copy_string(tmp, filename, sizeof(tmp));
+		ast_copy_string(tmp, args.filename, sizeof(tmp));
 	/* end of routine mentioned */
-	
-	
-	
+
 	if (chan->_state != AST_STATE_UP) {
-		if (option_skip) {
+		if (ast_test_flag(&flags, OPTION_SKIP)) {
 			/* At the user's option, skip if the line is not up */
 			return 0;
-		} else if (!option_noanswer) {
+		} else if (!ast_test_flag(&flags, OPTION_NOANSWER)) {
 			/* Otherwise answer unless we're supposed to record while on-hook */
 			res = ast_answer(chan);
 		}
 	}
-	
+
 	if (res) {
 		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
 		goto out;
 	}
-	
-	if (!option_quiet) {
+
+	if (!ast_test_flag(&flags, OPTION_QUIET)) {
 		/* Some code to play a nice little beep to signify the start of the record operation */
 		res = ast_streamfile(chan, "beep", chan->language);
 		if (!res) {
@@ -240,9 +237,9 @@ static int record_exec(struct ast_channel *chan, void *data)
 		}
 		ast_stopstream(chan);
 	}
-		
+
 	/* The end of beep code.  Now the recording starts */
-		
+
 	if (silence > 0) {
 		rfmt = chan->readformat;
 		res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
@@ -264,23 +261,23 @@ static int record_exec(struct ast_channel *chan, void *data)
 		*file++ = '\0';
 	ast_mkdir (dir, 0777);
 
-	flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
-	s = ast_writefile( tmp, ext, NULL, flags , 0, AST_FILE_MODE);
-		
+	ioflags = ast_test_flag(&flags, OPTION_APPEND) ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
+	s = ast_writefile(tmp, ext, NULL, ioflags, 0, AST_FILE_MODE);
+
 	if (!s) {
-		ast_log(LOG_WARNING, "Could not create file %s\n", filename);
+		ast_log(LOG_WARNING, "Could not create file %s\n", args.filename);
 		goto out;
 	}
 
 	if (ast_opt_transmit_silence)
 		silgen = ast_channel_start_silence_generator(chan);
-	
+
 	/* Request a video update */
 	ast_indicate(chan, AST_CONTROL_VIDUPDATE);
-	
+
 	if (maxduration <= 0)
 		maxduration = -1;
-	
+
 	while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
 		if (maxduration > 0) {
 			if (waitres == 0) {
@@ -289,7 +286,7 @@ static int record_exec(struct ast_channel *chan, void *data)
 			}
 			maxduration = waitres;
 		}
-		
+
 		f = ast_read(chan);
 		if (!f) {
 			res = -1;
@@ -297,13 +294,13 @@ static int record_exec(struct ast_channel *chan, void *data)
 		}
 		if (f->frametype == AST_FRAME_VOICE) {
 			res = ast_writestream(s, f);
-			
+
 			if (res) {
 				ast_log(LOG_WARNING, "Problem writing frame\n");
 				ast_frfree(f);
 				break;
 			}
-			
+
 			if (silence > 0) {
 				dspsilence = 0;
 				ast_dsp_silence(sildet, f, &dspsilence);
@@ -321,7 +318,7 @@ static int record_exec(struct ast_channel *chan, void *data)
 			}
 		} else if (f->frametype == AST_FRAME_VIDEO) {
 			res = ast_writestream(s, f);
-			
+
 			if (res) {
 				ast_log(LOG_WARNING, "Problem writing frame\n");
 				ast_frfree(f);
@@ -338,9 +335,9 @@ static int record_exec(struct ast_channel *chan, void *data)
 		ast_debug(1, "Got hangup\n");
 		res = -1;
 	}
-			
+
 	if (gotsilence) {
-		ast_stream_rewind(s, silence-1000);
+		ast_stream_rewind(s, silence - 1000);
 		ast_truncstream(s);
 	} else if (!gottimeout) {
 		/* Strip off the last 1/4 second of it */
@@ -351,8 +348,8 @@ static int record_exec(struct ast_channel *chan, void *data)
 
 	if (silgen)
 		ast_channel_stop_silence_generator(chan, silgen);
-	
- out:
+
+out:
 	if ((silence > 0) && rfmt) {
 		res = ast_set_read_format(chan, rfmt);
 		if (res)
diff --git a/apps/app_skel.c b/apps/app_skel.c
index 9cd759c69ed2f4028c21a0284ee9e80b2866c7bb..527fc776df4174ffbc8b1a6fb272e85c5d87e4f0 100644
--- a/apps/app_skel.c
+++ b/apps/app_skel.c
@@ -84,7 +84,7 @@ static int app_exec(struct ast_channel *chan, void *data)
 	);
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n", app);
+		ast_log(LOG_WARNING, "%s requires an argument (dummy[,options])\n", app);
 		return -1;
 	}
 
diff --git a/apps/app_softhangup.c b/apps/app_softhangup.c
index 42f48aac7a8338dab54eea55e5b495732dd2663f..5bc90fdfe2e1a35e586bc68e59802ee842c5e30b 100644
--- a/apps/app_softhangup.c
+++ b/apps/app_softhangup.c
@@ -41,10 +41,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
 #include "asterisk/lock.h"
+#include "asterisk/app.h"
 
 static char *synopsis = "Soft Hangup Application";
 
-static char *desc = "  SoftHangup(Technology/resource|options)\n"
+static char *desc = "SoftHangup(Technology/resource[,options])\n"
 "Hangs up the requested channel.  If there are no channels to hangup,\n"
 "the application will report it.\n"
 "- 'options' may contain the following letter:\n"
@@ -52,46 +53,62 @@ static char *desc = "  SoftHangup(Technology/resource|options)\n"
 
 static char *app = "SoftHangup";
 
+enum {
+	OPTION_ALL = (1 << 0),
+};
+
+AST_APP_OPTIONS(app_opts,{
+	AST_APP_OPTION('a', OPTION_ALL),
+});
 
 static int softhangup_exec(struct ast_channel *chan, void *data)
 {
-	struct ast_channel *c=NULL;
-	char *options, *cut, *cdata, *match;
-	char name[AST_CHANNEL_NAME] = "";
-	int all = 0;
+	struct ast_channel *c = NULL;
+	char *cut, *opts[0];
+	char name[AST_CHANNEL_NAME] = "", *parse;
+	struct ast_flags flags;
+	int lenmatch;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(channel);
+		AST_APP_ARG(options);
+	);
 	
 	if (ast_strlen_zero(data)) {
-                ast_log(LOG_WARNING, "SoftHangup requires an argument (Technology/resource)\n");
+		ast_log(LOG_WARNING, "SoftHangup requires an argument (Technology/resource)\n");
 		return 0;
 	}
-	
-	cdata = ast_strdupa(data);
-	match = strsep(&cdata, "|");
-	options = strsep(&cdata, "|");
-	all = options && strchr(options,'a');
-	c = ast_channel_walk_locked(NULL);
-	while (c) {
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+
+	if (args.argc == 2)
+		ast_app_parse_options(app_opts, &flags, opts, args.options);
+	lenmatch = strlen(args.channel);
+
+	for (c = ast_walk_channel_by_name_prefix_locked(NULL, args.channel, lenmatch);
+		 c;
+		 c = ast_walk_channel_by_name_prefix_locked(c, args.channel, lenmatch)) {
 		ast_copy_string(name, c->name, sizeof(name));
-		ast_mutex_unlock(&c->lock);
-		/* XXX watch out, i think it is wrong to access c-> after unlocking! */
-		if (all) {
+		if (ast_test_flag(&flags, OPTION_ALL)) {
 			/* CAPI is set up like CAPI[foo/bar]/clcnt */ 
 			if (!strcmp(c->tech->type, "CAPI")) 
-				cut = strrchr(name,'/');
+				cut = strrchr(name, '/');
 			/* Basically everything else is Foo/Bar-Z */
 			else
-				cut = strchr(name,'-');
+				cut = strchr(name, '-');
 			/* Get rid of what we've cut */
 			if (cut)
 				*cut = 0;
 		}
-		if (!strcasecmp(name, match)) {
-			ast_log(LOG_WARNING, "Soft hanging %s up.\n",c->name);
+		if (!strcasecmp(name, args.channel)) {
+			ast_log(LOG_WARNING, "Soft hanging %s up.\n", c->name);
 			ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
-			if(!all)
+			if (!ast_test_flag(&flags, OPTION_ALL)) {
+				ast_mutex_unlock(&c->lock);
 				break;
+			}
 		}
-		c = ast_channel_walk_locked(c);
+		ast_mutex_unlock(&c->lock);
 	}
 
 	return 0;
diff --git a/apps/app_talkdetect.c b/apps/app_talkdetect.c
index 9e4d2a4eea6b909e71e36e623b638cf87ffd0251..0438111c559434135b669a43b9aa933ac8c91153 100644
--- a/apps/app_talkdetect.c
+++ b/apps/app_talkdetect.c
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/dsp.h"
 #include "asterisk/options.h"
+#include "asterisk/app.h"
 
 static char *app = "BackgroundDetect";
 
@@ -64,17 +65,21 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
 {
 	int res = 0;
 	char *tmp;
-	char *options;
-	char *stringp;
 	struct ast_frame *fr;
-	int notsilent=0;
+	int notsilent = 0;
 	struct timeval start = { 0, 0};
 	int sil = 1000;
 	int min = 100;
 	int max = -1;
 	int x;
 	int origrformat=0;
-	struct ast_dsp *dsp;
+	struct ast_dsp *dsp = NULL;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(filename);
+		AST_APP_ARG(silence);
+		AST_APP_ARG(min);
+		AST_APP_ARG(max);
+	);
 	
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
@@ -82,118 +87,112 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
 	}
 
 	tmp = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, tmp);
 
-	stringp=tmp;
-	strsep(&stringp, "|");
-	options = strsep(&stringp, "|");
-	if (options) {
-		if ((sscanf(options, "%d", &x) == 1) && (x > 0))
-			sil = x;
-		options = strsep(&stringp, "|");
-		if (options) {
-			if ((sscanf(options, "%d", &x) == 1) && (x > 0))
-				min = x;
-			options = strsep(&stringp, "|");
-			if (options) {
-				if ((sscanf(options, "%d", &x) == 1) && (x > 0))
-					max = x;
-			}
+	if ((sscanf(args.silence, "%d", &x) == 1) && (x > 0))
+		sil = x;
+	if ((sscanf(args.min, "%d", &x) == 1) && (x > 0))
+		min = x;
+	if ((sscanf(args.max, "%d", &x) == 1) && (x > 0))
+		max = x;
+
+	ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d\n", args.filename, sil, min, max);
+	do {
+		if (chan->_state != AST_STATE_UP) {
+			if ((res = ast_answer(chan)))
+				break;
 		}
-	}
-	ast_debug(1, "Preparing detect of '%s', sil=%d,min=%d,max=%d\n", tmp, sil, min, max);
-	if (chan->_state != AST_STATE_UP) {
-		/* Otherwise answer unless we're supposed to send this while on-hook */
-		res = ast_answer(chan);
-	}
-	if (!res) {
+
 		origrformat = chan->readformat;
-		if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) 
+		if ((ast_set_read_format(chan, AST_FORMAT_SLINEAR))) {
 			ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
-	}
-	if (!(dsp = ast_dsp_new())) {
-		ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
-		res = -1;
-	}
-	if (!res) {
+			res = -1;
+			break;
+		}
+
+		if (!(dsp = ast_dsp_new())) {
+			ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
+			res = -1;
+			break;
+		}
 		ast_stopstream(chan);
-		res = ast_streamfile(chan, tmp, chan->language);
-		if (!res) {
-			while(chan->stream) {
-				res = ast_sched_wait(chan->sched);
-				if ((res < 0) && !chan->timingfunc) {
-					res = 0;
-					break;
-				}
-				if (res < 0)
-					res = 1000;
-				res = ast_waitfor(chan, res);
-				if (res < 0) {
-					ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
+		if (ast_streamfile(chan, tmp, chan->language)) {
+			ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
+			break;
+		}
+
+		while (chan->stream) {
+			res = ast_sched_wait(chan->sched);
+			if ((res < 0) && !chan->timingfunc) {
+				res = 0;
+				break;
+			}
+			if (res < 0)
+				res = 1000;
+			res = ast_waitfor(chan, res);
+			if (res < 0) {
+				ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
+				break;
+			} else if (res > 0) {
+				fr = ast_read(chan);
+				if (!fr) {
+					res = -1;
 					break;
-				} else if (res > 0) {
-					fr = ast_read(chan);
-					if (!fr) {
-						res = -1;
+				} else if (fr->frametype == AST_FRAME_DTMF) {
+					char t[2];
+					t[0] = fr->subclass;
+					t[1] = '\0';
+					if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
+						/* They entered a valid  extension, or might be anyhow */
+						res = fr->subclass;
+						ast_frfree(fr);
 						break;
-					} else if (fr->frametype == AST_FRAME_DTMF) {
-						char t[2];
-						t[0] = fr->subclass;
-						t[1] = '\0';
-						if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
-							/* They entered a valid  extension, or might be anyhow */
-							res = fr->subclass;
-							ast_frfree(fr);
-							break;
-						}
-					} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
-						int totalsilence;
-						int ms;
-						res = ast_dsp_silence(dsp, fr, &totalsilence);
-						if (res && (totalsilence > sil)) {
-							/* We've been quiet a little while */
-							if (notsilent) {
-								/* We had heard some talking */
-								ms = ast_tvdiff_ms(ast_tvnow(), start);
-								ms -= sil;
-								if (ms < 0)
-									ms = 0;
-								if ((ms > min) && ((max < 0) || (ms < max))) {
-									char ms_str[10];
-									ast_debug(1, "Found qualified token of %d ms\n", ms);
-
-									/* Save detected talk time (in milliseconds) */ 
-									sprintf(ms_str, "%d", ms );	
-									pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
-									
-									ast_goto_if_exists(chan, chan->context, "talk", 1);
-									res = 0;
-									ast_frfree(fr);
-									break;
-								} else {
-									ast_debug(1, "Found unqualified token of %d ms\n", ms);
-								}
-								notsilent = 0;
-							}
-						} else {
-							if (!notsilent) {
-								/* Heard some audio, mark the begining of the token */
-								start = ast_tvnow();
-								ast_debug(1, "Start of voice token!\n");
-								notsilent = 1;
+					}
+				} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
+					int totalsilence;
+					int ms;
+					res = ast_dsp_silence(dsp, fr, &totalsilence);
+					if (res && (totalsilence > sil)) {
+						/* We've been quiet a little while */
+						if (notsilent) {
+							/* We had heard some talking */
+							ms = ast_tvdiff_ms(ast_tvnow(), start);
+							ms -= sil;
+							if (ms < 0)
+								ms = 0;
+							if ((ms > min) && ((max < 0) || (ms < max))) {
+								char ms_str[10];
+								ast_debug(1, "Found qualified token of %d ms\n", ms);
+
+								/* Save detected talk time (in milliseconds) */ 
+								sprintf(ms_str, "%d", ms );	
+								pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
+
+								ast_goto_if_exists(chan, chan->context, "talk", 1);
+								res = 0;
+								ast_frfree(fr);
+								break;
+							} else {
+								ast_debug(1, "Found unqualified token of %d ms\n", ms);
 							}
+							notsilent = 0;
+						}
+					} else {
+						if (!notsilent) {
+							/* Heard some audio, mark the begining of the token */
+							start = ast_tvnow();
+							ast_debug(1, "Start of voice token!\n");
+							notsilent = 1;
 						}
-						
 					}
-					ast_frfree(fr);
 				}
-				ast_sched_runq(chan->sched);
+				ast_frfree(fr);
 			}
-			ast_stopstream(chan);
-		} else {
-			ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
-			res = 0;
+			ast_sched_runq(chan->sched);
 		}
-	}
+		ast_stopstream(chan);
+	} while (0);
+
 	if (res > -1) {
 		if (origrformat && ast_set_read_format(chan, origrformat)) {
 			ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 
diff --git a/apps/app_url.c b/apps/app_url.c
index 46db0d37ec40b45aa4e37af1688e86659e9b2348..e0ec68e441a4bdb0512e8379e68c3037c22e2a2c 100644
--- a/apps/app_url.c
+++ b/apps/app_url.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/translate.h"
 #include "asterisk/image.h"
 #include "asterisk/options.h"
+#include "asterisk/app.h"
 
 static char *app = "SendURL";
 
@@ -56,22 +57,32 @@ static char *descrip =
 "    NOLOAD        Client failed to load URL (wait enabled)\n"
 "    UNSUPPORTED   Channel does not support URL transport\n"
 "\n"
-"If the option 'wait' is specified, execution will wait for an\n"
+"If the option 'w' is specified, execution will wait for an\n"
 "acknowledgement that the URL has been loaded before continuing\n"
 "\n"
 "SendURL continues normally if the URL was sent correctly or if the channel\n"
 "does not support HTML transport.  Otherwise, the channel is hung up.\n";
 
+enum {
+	OPTION_WAIT = (1 << 0),
+} option_flags;
+
+AST_APP_OPTIONS(app_opts,{
+	AST_APP_OPTION('w', OPTION_WAIT),
+});
 
 static int sendurl_exec(struct ast_channel *chan, void *data)
 {
 	int res = 0;
 	char *tmp;
-	char *options;
-	int local_option_wait=0;
 	struct ast_frame *f;
-	char *stringp=NULL;
 	char *status = "FAILURE";
+	char *opts[0];
+	struct ast_flags flags;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(url);
+		AST_APP_ARG(options);
+	);
 	
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "SendURL requires an argument (URL)\n");
@@ -81,24 +92,22 @@ static int sendurl_exec(struct ast_channel *chan, void *data)
 
 	tmp = ast_strdupa(data);
 
-	stringp=tmp;
-	strsep(&stringp, "|");
-	options = strsep(&stringp, "|");
-	if (options && !strcasecmp(options, "wait"))
-		local_option_wait = 1;
+	AST_STANDARD_APP_ARGS(args, tmp);
+	if (args.argc == 2)
+		ast_app_parse_options(app_opts, &flags, opts, args.options);
 	
 	if (!ast_channel_supports_html(chan)) {
 		/* Does not support transport */
 		pbx_builtin_setvar_helper(chan, "SENDURLSTATUS", "UNSUPPORTED");
 		return 0;
 	}
-	res = ast_channel_sendurl(chan, tmp);
+	res = ast_channel_sendurl(chan, args.url);
 	if (res == -1) {
 		pbx_builtin_setvar_helper(chan, "SENDURLSTATUS", "FAILURE");
 		return res;
 	}
 	status = "SUCCESS";
-	if (local_option_wait) {
+	if (ast_test_flag(&flags, OPTION_WAIT)) {
 		for(;;) {
 			/* Wait for an event */
 			res = ast_waitfor(chan, -1);
@@ -120,7 +129,7 @@ static int sendurl_exec(struct ast_channel *chan, void *data)
 					break;
 				case AST_HTML_NOSUPPORT:
 					/* Does not support transport */
-					status ="UNSUPPORTED";
+					status = "UNSUPPORTED";
 					res = 0;
 					ast_frfree(f);
 					goto out;
diff --git a/apps/app_verbose.c b/apps/app_verbose.c
index e4808b49d9f6801db3174ac4fabfb58553e6ab0b..97e441afc66c9d6a0972d30732f1e0d292ccf5c7 100644
--- a/apps/app_verbose.c
+++ b/apps/app_verbose.c
@@ -38,55 +38,61 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
+#include "asterisk/app.h"
 
 static char *app_verbose = "Verbose";
 static char *verbose_synopsis = "Send arbitrary text to verbose output";
 static char *verbose_descrip =
-"Verbose([<level>|]<message>)\n"
+"Verbose([<level>,]<message>)\n"
 "  level must be an integer value.  If not specified, defaults to 0.\n";
 
 static char *app_log = "Log";
 static char *log_synopsis = "Send arbitrary text to a selected log level";
 static char *log_descrip =
-"Log(<level>|<message>)\n"
+"Log(<level>,<message>)\n"
 "  level must be one of ERROR, WARNING, NOTICE, DEBUG, VERBOSE, DTMF\n";
 
 
 static int verbose_exec(struct ast_channel *chan, void *data)
 {
-	char *vtext, *tmp;
 	int vsize;
+	char *parse;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(level);
+		AST_APP_ARG(msg);
+	);
 
-	if (ast_strlen_zero(data))
+	if (ast_strlen_zero(data)) {
 		return 0;
-	
-	vtext = ast_strdupa(data);
-	tmp = strsep(&vtext, "|");
-	if (vtext) {
-		if (sscanf(tmp, "%d", &vsize) != 1) {
-			vsize = 0;
-			ast_log(LOG_WARNING, "'%s' is not a verboser number\n", vtext);
-		}
-	} else {
-		vtext = tmp;
+	}
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+	if (args.argc == 1) {
+		args.msg = args.level;
+		args.level = "0";
+	}
+
+	if (sscanf(args.level, "%d", &vsize) != 1) {
 		vsize = 0;
+		ast_log(LOG_WARNING, "'%s' is not a verboser number\n", args.level);
 	}
 	if (option_verbose >= vsize) {
 		switch (vsize) {
 		case 0:
-			ast_verbose("%s\n", vtext);
+			ast_verbose("%s\n", args.msg);
 			break;
 		case 1:
-			ast_verbose(VERBOSE_PREFIX_1 "%s\n", vtext);
+			ast_verbose(VERBOSE_PREFIX_1 "%s\n", args.msg);
 			break;
 		case 2:
-			ast_verbose(VERBOSE_PREFIX_2 "%s\n", vtext);
+			ast_verbose(VERBOSE_PREFIX_2 "%s\n", args.msg);
 			break;
 		case 3:
-			ast_verbose(VERBOSE_PREFIX_3 "%s\n", vtext);
+			ast_verbose(VERBOSE_PREFIX_3 "%s\n", args.msg);
 			break;
 		default:
-			ast_verbose(VERBOSE_PREFIX_4 "%s\n", vtext);
+			ast_verbose(VERBOSE_PREFIX_4 "%s\n", args.msg);
 		}
 	}
 
@@ -95,40 +101,43 @@ static int verbose_exec(struct ast_channel *chan, void *data)
 
 static int log_exec(struct ast_channel *chan, void *data)
 {
-	char *level, *ltext;
+	char *parse;
 	int lnum = -1;
 	char extension[AST_MAX_EXTENSION + 5], context[AST_MAX_EXTENSION + 2];
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(level);
+		AST_APP_ARG(msg);
+	);
 
 	if (ast_strlen_zero(data))
 		return 0;
 
-	ltext = ast_strdupa(data);
-
-	level = strsep(&ltext, "|");
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
 
-	if (!strcasecmp(level, "ERROR")) {
+	if (!strcasecmp(args.level, "ERROR")) {
 		lnum = __LOG_ERROR;
-	} else if (!strcasecmp(level, "WARNING")) {
+	} else if (!strcasecmp(args.level, "WARNING")) {
 		lnum = __LOG_WARNING;
-	} else if (!strcasecmp(level, "NOTICE")) {
+	} else if (!strcasecmp(args.level, "NOTICE")) {
 		lnum = __LOG_NOTICE;
-	} else if (!strcasecmp(level, "DEBUG")) {
+	} else if (!strcasecmp(args.level, "DEBUG")) {
 		lnum = __LOG_DEBUG;
-	} else if (!strcasecmp(level, "VERBOSE")) {
+	} else if (!strcasecmp(args.level, "VERBOSE")) {
 		lnum = __LOG_VERBOSE;
-	} else if (!strcasecmp(level, "DTMF")) {
+	} else if (!strcasecmp(args.level, "DTMF")) {
 		lnum = __LOG_DTMF;
-	} else if (!strcasecmp(level, "EVENT")) {
+	} else if (!strcasecmp(args.level, "EVENT")) {
 		lnum = __LOG_EVENT;
 	} else {
-		ast_log(LOG_ERROR, "Unknown log level: '%s'\n", level);
+		ast_log(LOG_ERROR, "Unknown log level: '%s'\n", args.level);
 	}
 
 	if (lnum > -1) {
 		snprintf(context, sizeof(context), "@ %s", chan->context);
 		snprintf(extension, sizeof(extension), "Ext. %s", chan->exten);
 
-		ast_log(lnum, extension, chan->priority, context, "%s\n", ltext);
+		ast_log(lnum, extension, chan->priority, context, "%s\n", args.msg);
 	}
 
 	return 0;
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index f12c5cb459fc68071118fd46c4deb33e25ab6aef..de3b72dc5930a50657a7d4473adacdc1c412b27b 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -7465,8 +7465,8 @@ static int vmauthenticate(struct ast_channel *chan, void *data)
 	
 	if (s) {
 		s = ast_strdupa(s);
-		user = strsep(&s, "|");
-		options = strsep(&s, "|");
+		user = strsep(&s, ",");
+		options = strsep(&s, ",");
 		if (user) {
 			s = user;
 			user = strsep(&s, "@");
@@ -8159,7 +8159,7 @@ static int load_config(void)
 			stringp = ast_strdupa(s);
 			for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
 				if (!ast_strlen_zero(stringp)) {
-					q = strsep(&stringp,",");
+					q = strsep(&stringp, ",");
 					while ((*q == ' ')||(*q == '\t')) /* Eat white space between contexts */
 						q++;
 					ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
diff --git a/apps/app_zapras.c b/apps/app_zapras.c
index 5456ffb29ce60cbaafce238c6071f86073b3a2cf..95b34d8203f9e177f97eb85587af2741433ac2a6 100644
--- a/apps/app_zapras.c
+++ b/apps/app_zapras.c
@@ -68,7 +68,7 @@ static char *descrip =
 "The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
 "channel to be able to use this function (No modem emulation is included).\n"
 "Your pppd must be patched to be zaptel aware. Arguments should be\n"
-"separated by | characters.\n";
+"separated by , characters.\n";
 
 
 #define PPP_MAX_ARGS	32
@@ -122,10 +122,10 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
 
 	/* And all the other arguments */
 	stringp=args;
-	c = strsep(&stringp, "|");
+	c = strsep(&stringp, ",");
 	while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
 		argv[argc++] = c;
-		c = strsep(&stringp, "|");
+		c = strsep(&stringp, ",");
 	}
 
 	argv[argc++] = "plugin";
diff --git a/channels/chan_local.c b/channels/chan_local.c
index b4072cecc46a8710777ef2fa2818ac96302f99a7..3d814d177fc42f5e3162d9f593cea6c00e8287a1 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -608,8 +608,8 @@ static struct ast_channel *local_new(struct local_pvt *p, int state)
 		ama = p->owner->amaflags;
 	else
 		ama = 0;
-	if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 
-			|| !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {
+	if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;1", p->exten, p->context, randnum)) 
+			|| !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;2", p->exten, p->context, randnum))) {
 		if (tmp)
 			ast_channel_free(tmp);
 		if (tmp2)
diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c
index 462f887b5c2c17b54b94d63bef7ce9ebf9bad390..f218c8edd2e821bcfc22581ddd1b782ae2aa4f65 100644
--- a/funcs/func_callerid.c
+++ b/funcs/func_callerid.c
@@ -63,10 +63,10 @@ static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
 	if (!chan)
 		return -1;
 
-	if (strchr(opt, '|')) {
+	if (strchr(opt, ',')) {
 		char name[80], num[80];
 
-		data = strsep(&opt, "|");
+		data = strsep(&opt, ",");
 		ast_callerid_split(opt, name, sizeof(name), num, sizeof(num));
 
 		if (!strncasecmp("all", data, 3)) {
diff --git a/funcs/func_cut.c b/funcs/func_cut.c
index 41710b978c82412a4f9a07c55863a0ae732a8289..4466e3269663db5d40741136c6dff6c9b1e65455 100644
--- a/funcs/func_cut.c
+++ b/funcs/func_cut.c
@@ -78,7 +78,7 @@ static int sort_internal(struct ast_channel *chan, char *data, char *buffer, siz
 	strings = ast_strdupa(data);
 
 	for (ptrkey = strings; *ptrkey; ptrkey++) {
-		if (*ptrkey == '|')
+		if (*ptrkey == ',')
 			count++;
 	}
 
@@ -88,7 +88,7 @@ static int sort_internal(struct ast_channel *chan, char *data, char *buffer, siz
 
 	/* Parse each into a struct */
 	count2 = 0;
-	while ((ptrkey = strsep(&strings, "|"))) {
+	while ((ptrkey = strsep(&strings, ","))) {
 		ptrvalue = index(ptrkey, ':');
 		if (!ptrvalue) {
 			count--;
diff --git a/funcs/func_env.c b/funcs/func_env.c
index 20af01636583668679d16d5166c6891acc9ec6a7..3e69666ce77fb1dfad3bd620051e01e3cdfd1c12 100644
--- a/funcs/func_env.c
+++ b/funcs/func_env.c
@@ -76,7 +76,7 @@ static int stat_read(struct ast_channel *chan, const char *cmd, char *data,
 
 	*buf = '\0';
 
-	action = strsep(&data, "|");
+	action = strsep(&data, ",");
 	if (stat(data, &s)) {
 		return -1;
 	} else {
diff --git a/funcs/func_logic.c b/funcs/func_logic.c
index 24080cc37a66dcabee586f175702012072c90bf8..92c4f8b17e4e77871ed38cdf285d161c9ac1b8fc 100644
--- a/funcs/func_logic.c
+++ b/funcs/func_logic.c
@@ -140,6 +140,29 @@ static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf,
 	return 0;
 }
 
+static int acf_import(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(channel);
+		AST_APP_ARG(varname);
+	);
+	AST_STANDARD_APP_ARGS(args, data);
+	memset(buf, 0, len);
+
+	if (!ast_strlen_zero(args.varname)) {
+		struct ast_channel *chan2 = ast_get_channel_by_name_locked(args.channel);
+		if (chan2) {
+			char *s = alloca(strlen(args.varname) + 4);
+			if (s) {
+				sprintf(s, "${%s}", args.varname);
+				pbx_substitute_variables_helper(chan2, s, buf, len);
+			}
+			ast_channel_unlock(chan2);
+		}
+	}
+	return 0;
+}
+
 static struct ast_custom_function isnull_function = {
 	.name = "ISNULL",
 	.synopsis = "NULL Test: Returns 1 if NULL or 0 otherwise",
@@ -164,7 +187,7 @@ static struct ast_custom_function exists_function = {
 static struct ast_custom_function if_function = {
 	.name = "IF",
 	.synopsis =
-		"Conditional: Returns the data following '?' if true else the data following ':'",
+		"Conditional: Returns the data following '?' if true, else the data following ':'",
 	.syntax = "IF(<expr>?[<true>][:<false>])",
 	.read = acf_if,
 };
@@ -172,11 +195,19 @@ static struct ast_custom_function if_function = {
 static struct ast_custom_function if_time_function = {
 	.name = "IFTIME",
 	.synopsis =
-		"Temporal Conditional: Returns the data following '?' if true else the data following ':'",
+		"Temporal Conditional: Returns the data following '?' if true, else the data following ':'",
 	.syntax = "IFTIME(<timespec>?[<true>][:<false>])",
 	.read = iftime,
 };
 
+static struct ast_custom_function import_function = {
+	.name = "IMPORT",
+	.synopsis =
+		"Retrieve the value of a variable from another channel\n",
+	.syntax = "IMPORT(channel,variable)",
+	.read = acf_import,
+};
+
 static int unload_module(void)
 {
 	int res = 0;
@@ -186,6 +217,7 @@ static int unload_module(void)
 	res |= ast_custom_function_unregister(&exists_function);
 	res |= ast_custom_function_unregister(&if_function);
 	res |= ast_custom_function_unregister(&if_time_function);
+	res |= ast_custom_function_unregister(&import_function);
 
 	return res;
 }
@@ -199,6 +231,7 @@ static int load_module(void)
 	res |= ast_custom_function_register(&exists_function);
 	res |= ast_custom_function_register(&if_function);
 	res |= ast_custom_function_register(&if_time_function);
+	res |= ast_custom_function_register(&import_function);
 
 	return res;
 }
diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c
index 4852a08673d3c4692a364bd9e96ee6051b192186..2eac1eeb9f89e51146e419e023de57ab6ed2a3ec 100644
--- a/funcs/func_odbc.c
+++ b/funcs/func_odbc.c
@@ -179,8 +179,7 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
 	}
 
 	/* Parse values, just like arguments */
-	/* Can't use the pipe, because app Set removes them */
-	AST_NONSTANDARD_APP_ARGS(values, t, ',');
+	AST_STANDARD_APP_ARGS(values, t);
 	for (i = 0; i < values.argc; i++) {
 		snprintf(varname, sizeof(varname), "VAL%d", i + 1);
 		pbx_builtin_pushvar_helper(chan, varname, values.field[i]);
diff --git a/funcs/func_rand.c b/funcs/func_rand.c
index 8885904a942a4810e4c16ad520454d1c997e1d15..d989b0ad605fa356c550f7f174abe1d9deed708b 100644
--- a/funcs/func_rand.c
+++ b/funcs/func_rand.c
@@ -76,11 +76,11 @@ static int acf_rand_exec(struct ast_channel *chan, const char *cmd,
 static struct ast_custom_function acf_rand = {
 	.name = "RAND",
 	.synopsis = "Choose a random number in a range",
-	.syntax = "RAND([min][|max])",
+	.syntax = "RAND([min][,max])",
 	.desc =
 		"Choose a random number between min and max.  Min defaults to 0, if not\n"
 		"specified, while max defaults to RAND_MAX (2147483647 on many systems).\n"
-		"  Example:  Set(junky=${RAND(1|8)}); \n"
+		"  Example:  Set(junky=${RAND(1,8)}); \n"
 		"  Sets junky to a random number between 1 and 8, inclusive.\n",
 	.read = acf_rand_exec,
 };
diff --git a/funcs/func_realtime.c b/funcs/func_realtime.c
index 611e6ecc64159da067159c8c56692f5c0cc8edd0..1f67fcb464086cc27c4af32e5ebcb051f3c74998 100644
--- a/funcs/func_realtime.c
+++ b/funcs/func_realtime.c
@@ -60,14 +60,14 @@ static int function_realtime_read(struct ast_channel *chan, const char *cmd, cha
 	);
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "Syntax: REALTIME(family|fieldmatch[|value[|delim1[|delim2]]]) - missing argument!\n");
+		ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) - missing argument!\n");
 		return -1;
 	}
 
 	AST_STANDARD_APP_ARGS(args, data);
 
 	if (!args.delim1)
-		args.delim1 = "|";
+		args.delim1 = ",";
 	if (!args.delim2)
 		args.delim2 = "=";
 
@@ -102,7 +102,7 @@ static int function_realtime_write(struct ast_channel *chan, const char *cmd, ch
 	);
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "Syntax: REALTIME(family|fieldmatch|value|newcol) - missing argument!\n");
+		ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch,value,newcol) - missing argument!\n");
 		return -1;
 	}
 
@@ -120,14 +120,14 @@ static int function_realtime_write(struct ast_channel *chan, const char *cmd, ch
 struct ast_custom_function realtime_function = {
 	.name = "REALTIME",
 	.synopsis = "RealTime Read/Write Functions",
-	.syntax = "REALTIME(family|fieldmatch[|value[|delim1[|delim2]]]) on read\n"
-		  "REALTIME(family|fieldmatch|value|field) on write\n",
+	.syntax = "REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) on read\n"
+		  "REALTIME(family,fieldmatch,value,field) on write",
 	.desc = "This function will read or write values from/to a RealTime repository.\n"
 		"REALTIME(....) will read names/values from the repository, and \n"
 		"REALTIME(....)= will write a new value/field to the repository. On a\n"
 		"read, this function returns a delimited text string. The name/value \n"
 		"pairs are delimited by delim1, and the name and value are delimited \n"
-		"between each other with delim2. The default for delim1 is '|' and   \n"
+		"between each other with delim2. The default for delim1 is ',' and   \n"
 		"the default for delim2 is '='. If there is no match, NULL will be   \n"
 		"returned by the function. On a write, this function will always     \n"
 		"return NULL. \n",
diff --git a/funcs/func_strings.c b/funcs/func_strings.c
index c44c49921f83f633d9dfd7fc9e3ffa4c7e9e8099..5eab9930f8814d81aac3d87c447ad103c6bf527b 100644
--- a/funcs/func_strings.c
+++ b/funcs/func_strings.c
@@ -88,7 +88,7 @@ static int function_fieldqty(struct ast_channel *chan, const char *cmd,
 static struct ast_custom_function fieldqty_function = {
 	.name = "FIELDQTY",
 	.synopsis = "Count the fields, with an arbitrary delimiter",
-	.syntax = "FIELDQTY(<varname>|<delim>)",
+	.syntax = "FIELDQTY(<varname>,<delim>)",
 	.read = function_fieldqty,
 };
 
@@ -104,7 +104,7 @@ static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *
 	AST_STANDARD_APP_ARGS(args, parse);
 
 	if (!args.string) {
-		ast_log(LOG_ERROR, "Usage: FILTER(<allowed-chars>|<string>)\n");
+		ast_log(LOG_ERROR, "Usage: FILTER(<allowed-chars>,<string>)\n");
 		return -1;
 	}
 
@@ -120,7 +120,7 @@ static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *
 static struct ast_custom_function filter_function = {
 	.name = "FILTER",
 	.synopsis = "Filter the string to include only the allowed characters",
-	.syntax = "FILTER(<allowed-chars>|<string>)",
+	.syntax = "FILTER(<allowed-chars>,<string>)",
 	.read = filter,
 };
 
@@ -237,15 +237,9 @@ static int array(struct ast_channel *chan, const char *cmd, char *var,
 	 * delimiter, but we'll fall back to vertical bars if commas aren't found.
 	 */
 	ast_debug(1, "array (%s=%s)\n", var, value2);
-	if (strchr(var, ','))
-		AST_NONSTANDARD_APP_ARGS(arg1, var, ',');
-	else
-		AST_STANDARD_APP_ARGS(arg1, var);
+	AST_STANDARD_APP_ARGS(arg1, var);
 
-	if (strchr(value2, ','))
-		AST_NONSTANDARD_APP_ARGS(arg2, value2, ',');
-	else
-		AST_STANDARD_APP_ARGS(arg2, value2);
+	AST_STANDARD_APP_ARGS(arg2, value2);
 
 	for (i = 0; i < arg1.argc; i++) {
 		ast_debug(1, "array set value (%s=%s)\n", arg1.var[i],
@@ -302,7 +296,7 @@ static int hash_write(struct ast_channel *chan, const char *cmd, char *var, cons
 		AST_APP_ARG(hashkey);
 	);
 
-	if (!strchr(var, '|')) {
+	if (!strchr(var, ',')) {
 		/* Single argument version */
 		return array(chan, "HASH", var, value);
 	}
@@ -363,7 +357,7 @@ static int hash_read(struct ast_channel *chan, const char *cmd, char *data, char
 static struct ast_custom_function hash_function = {
 	.name = "HASH",
 	.synopsis = "Implementation of a dialplan associative array",
-	.syntax = "HASH(hashname[|hashkey])",
+	.syntax = "HASH(hashname[,hashkey])",
 	.write = hash_write,
 	.read = hash_read,
 	.desc =
@@ -387,15 +381,13 @@ static struct ast_custom_function hashkeys_function = {
 static struct ast_custom_function array_function = {
 	.name = "ARRAY",
 	.synopsis = "Allows setting multiple variables at once",
-	.syntax = "ARRAY(var1[|var2[...][|varN]])",
+	.syntax = "ARRAY(var1[,var2[...][,varN]])",
 	.write = array,
 	.desc =
 		"The comma-separated list passed as a value to which the function is set will\n"
 		"be interpreted as a set of values to which the comma-separated list of\n"
 		"variable names in the argument should be set.\n"
-		"Hence, Set(ARRAY(var1|var2)=1\\,2) will set var1 to 1 and var2 to 2\n"
-		"Note: remember to either backslash your commas in extensions.conf or quote the\n"
-		"entire argument, since Set can take multiple arguments itself.\n",
+		"Hence, Set(ARRAY(var1,var2)=1,2) will set var1 to 1 and var2 to 2.\n",
 };
 
 static int acf_sprintf(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
@@ -533,7 +525,7 @@ sprintf_fail:
 static struct ast_custom_function sprintf_function = {
 	.name = "SPRINTF",
 	.synopsis = "Format a variable according to a format string",
-	.syntax = "SPRINTF(<format>|<arg1>[|...<argN>])",
+	.syntax = "SPRINTF(<format>,<arg1>[,...<argN>])",
 	.read = acf_sprintf,
 	.desc =
 "Parses the format string specified and returns a string matching that format.\n"
@@ -623,7 +615,7 @@ static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
 static struct ast_custom_function strftime_function = {
 	.name = "STRFTIME",
 	.synopsis = "Returns the current date/time in a specified format.",
-	.syntax = "STRFTIME([<epoch>][|[timezone][|format]])",
+	.syntax = "STRFTIME([<epoch>][,[timezone][,format]])",
 	.desc =
 "STRFTIME sports all of the same formats as the underlying C function\n"
 "strftime(3) - see the man page for details.  It also supports the\n"
@@ -660,7 +652,7 @@ static int acf_strptime(struct ast_channel *chan, const char *cmd, char *data,
 
 	if (ast_strlen_zero(args.format)) {
 		ast_log(LOG_ERROR,
-				"No format supplied to STRPTIME(<timestring>|<timezone>|<format>)");
+				"No format supplied to STRPTIME(<timestring>,<timezone>,<format>)");
 		return -1;
 	}
 
@@ -677,14 +669,14 @@ static struct ast_custom_function strptime_function = {
 	.name = "STRPTIME",
 	.synopsis =
 		"Returns the epoch of the arbitrary date/time string structured as described in the format.",
-	.syntax = "STRPTIME(<datetime>|<timezone>|<format>)",
+	.syntax = "STRPTIME(<datetime>,<timezone>,<format>)",
 	.desc =
 		"This is useful for converting a date into an EPOCH time, possibly to pass to\n"
 		"an application like SayUnixTime or to calculate the difference between two\n"
 		"date strings.\n"
 		"\n"
 		"Example:\n"
-		"  ${STRPTIME(2006-03-01 07:30:35|America/Chicago|%Y-%m-%d %H:%M:%S)} returns 1141219835\n",
+		"  ${STRPTIME(2006-03-01 07:30:35,America/Chicago,%Y-%m-%d %H:%M:%S)} returns 1141219835\n",
 	.read = acf_strptime,
 };
 
diff --git a/funcs/func_vmcount.c b/funcs/func_vmcount.c
index 8183b8c74ec4003a66c50f05ce49c3ec2b0693b8..0e6cfef1eac367e512de796530e0c3026896f207 100644
--- a/funcs/func_vmcount.c
+++ b/funcs/func_vmcount.c
@@ -76,7 +76,7 @@ static int acf_vmcount_exec(struct ast_channel *chan, const char *cmd, char *arg
 struct ast_custom_function acf_vmcount = {
 	.name = "VMCOUNT",
 	.synopsis = "Counts the voicemail in a specified mailbox",
-	.syntax = "VMCOUNT(vmbox[@context][|folder])",
+	.syntax = "VMCOUNT(vmbox[@context][,folder])",
 	.desc =
 	"  context - defaults to \"default\"\n"
 	"  folder  - defaults to \"INBOX\"\n",
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index 1fb0e04eb0fae560173fc03a663f3854b83c1e83..1d3fcdfb5a6fdda25a5b82bae72b6652adc88a22 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -289,7 +289,7 @@ int ast_app_group_list_unlock(void);
   the argc argument counter field.
  */
 #define AST_STANDARD_APP_ARGS(args, parse) \
-	args.argc = ast_app_separate_args(parse, '|', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0]))
+	args.argc = ast_app_separate_args(parse, ',', args.argv, (sizeof(args) - sizeof(args.argc)) / sizeof(args.argv[0]))
 	
 /*!
   \brief Performs the 'nonstandard' argument separation process for an application.
diff --git a/main/pbx.c b/main/pbx.c
index bb9692ab178a11984ad1861e89169f7c9a0c0d31..34b3eeeb948235613ef0ba2099c843f15f9f459d 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -303,7 +303,7 @@ static struct pbx_builtin {
 
 	{ "BackGround", pbx_builtin_background,
 	"Play an audio file while waiting for digits of an extension to go to.",
-	"  Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
+	"  Background(filename1[&filename2...][,options[,langoverride][,context]]):\n"
 	"This application will play the given list of files while waiting for an\n"
 	"extension to be dialed by the calling channel. To continue waiting for digits\n"
 	"after this application has finished playing files, the WaitExten application\n"
@@ -344,14 +344,14 @@ static struct pbx_builtin {
 
 	{ "ExecIfTime", pbx_builtin_execiftime,
 	"Conditional application execution based on the current time",
-	"  ExecIfTime(<times>|<weekdays>|<mdays>|<months>?appname[|appargs]):\n"
+	"  ExecIfTime(<times>,<weekdays>,<mdays>,<months>?appname[(appargs)]):\n"
 	"This application will execute the specified dialplan application, with optional\n"
 	"arguments, if the current time matches the given time specification.\n"
 	},
 
 	{ "Goto", pbx_builtin_goto,
 	"Jump to a particular priority, extension, or context",
-	"  Goto([[context|]extension|]priority): This application will set the current\n"
+	"  Goto([[context,]extension,]priority): This application will set the current\n"
 	"context, extension, and priority in the channel structure. After it completes, the\n"
 	"pbx engine will continue dialplan execution at the specified location.\n"
 	"If no specific extension, or extension and context, are specified, then this\n"
@@ -391,7 +391,7 @@ static struct pbx_builtin {
 
 	{ "GotoIfTime", pbx_builtin_gotoiftime,
 	"Conditional Goto based on the current time",
-	"  GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]exten|]priority):\n"
+	"  GotoIfTime(<times>,<weekdays>,<mdays>,<months>?[[context,]exten,]priority):\n"
 	"This application will set the context, extension, and priority in the channel structure\n"
 	"if the current time matches the given time specification. Otherwise, nothing is done.\n"
         "Further information on the time specification can be found in examples\n"
@@ -401,7 +401,7 @@ static struct pbx_builtin {
 
 	{ "ImportVar", pbx_builtin_importvar,
 	"Import a variable from a channel into a new variable",
-	"  ImportVar(newvar=channelname|variable): This application imports a variable\n"
+	"  ImportVar(newvar=channelname,variable): This application imports a variable\n"
 	"from the specified channel (as opposed to the current one) and stores it as\n"
 	"a variable in the current channel (the channel that is calling this\n"
 	"application). Variables created by this application have the same inheritance\n"
@@ -476,16 +476,13 @@ static struct pbx_builtin {
 
 	{ "Set", pbx_builtin_setvar,
 	"Set channel variable(s) or function value(s)",
-	"  Set(name1=value1|name2=value2|..[|options])\n"
+	"  Set(name1=value1)\n"
 	"This function can be used to set the value of channel variables or dialplan\n"
 	"functions. It will accept up to 24 name/value pairs. When setting variables,\n"
 	"if the variable name is prefixed with _, the variable will be inherited into\n"
 	"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"
-	"    g - Set variable globally instead of on the channel\n"
-	"        (applies only to variables, not functions)\n"
 	},
 
 	{ "SetAMAFlags", pbx_builtin_setamaflags,
@@ -504,7 +501,7 @@ static struct pbx_builtin {
 
 	{ "WaitExten", pbx_builtin_waitexten,
 	"Waits for an extension to be entered",
-	"  WaitExten([seconds][|options]): This application waits for the user to enter\n"
+	"  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"
@@ -4252,13 +4249,13 @@ int ast_build_timing(struct ast_timing *i, const char *info_in)
 	i->daymask = 0x7fffffffU; /* 31 bits */
 	i->dowmask = 0x7f; /* 7 bits */
 	/* on each call, use strsep() to move info to the next argument */
-	get_timerange(i, strsep(&info, "|"));
+	get_timerange(i, strsep(&info, "|,"));
 	if (info)
-		i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
+		i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
 	if (info)
-		i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
+		i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
 	if (info)
-		i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
+		i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
 	return 1;
 }
 
@@ -4329,7 +4326,7 @@ int ast_context_add_include2(struct ast_context *con, const char *value,
 	new_include->rname = p;
 	strcpy(p, value);
 	/* Strip off timing info, and process if it is there */
-	if ( (c = strchr(p, '|')) ) {
+	if ( (c = strchr(p, ',')) ) {
 		*c++ = '\0';
 	        new_include->hastime = ast_build_timing(&(new_include->timing), c);
 	}
@@ -5499,14 +5496,14 @@ static int pbx_builtin_gotoiftime(struct ast_channel *chan, void *data)
 	struct ast_timing timing;
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n  <time range>|<days of week>|<days of month>|<months>?[[context|]extension|]priority\n");
+		ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>?[[context,]extension,]priority\n");
 		return -1;
 	}
 
 	ts = s = ast_strdupa(data);
 
 	/* Separate the Goto path */
-	strsep(&ts,"?");
+	strsep(&ts, "?");
 
 	/* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
 	if (ast_build_timing(&timing, s) && ast_check_timing(&timing))
@@ -5523,7 +5520,7 @@ static int pbx_builtin_execiftime(struct ast_channel *chan, void *data)
 	char *s, *appname;
 	struct ast_timing timing;
 	struct ast_app *app;
-	static const char *usage = "ExecIfTime requires an argument:\n  <time range>|<days of week>|<days of month>|<months>?<appname>[|<appargs>]";
+	static const char *usage = "ExecIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>?<appname>[(<appargs>)]";
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "%s\n", usage);
@@ -5532,7 +5529,7 @@ static int pbx_builtin_execiftime(struct ast_channel *chan, void *data)
 
 	appname = ast_strdupa(data);
 
-	s = strsep(&appname,"?");	/* Separate the timerange and application name/data */
+	s = strsep(&appname, "?");	/* Separate the timerange and application name/data */
 	if (!appname) {	/* missing application */
 		ast_log(LOG_WARNING, "%s\n", usage);
 		return -1;
@@ -5546,9 +5543,16 @@ static int pbx_builtin_execiftime(struct ast_channel *chan, void *data)
 	if (!ast_check_timing(&timing))	/* outside the valid time window, just return */
 		return 0;
 
-	/* now split appname|appargs */
-	if ((s = strchr(appname, '|')))
+	/* now split appname(appargs) */
+	if ((s = strchr(appname, '('))) {
+		char *e;
 		*s++ = '\0';
+		if ((e = strrchr(s, ')')))
+			*e = '\0';
+		else
+			ast_log(LOG_WARNING, "Failed to find closing parenthesis\n");
+	}
+		
 
 	if ((app = pbx_findapp(appname))) {
 		return pbx_exec(chan, app, S_OR(s, ""));
@@ -5568,7 +5572,7 @@ static int pbx_builtin_wait(struct ast_channel *chan, void *data)
 
 	/* Wait for "n" seconds */
 	if (data && (s = atof(data)) > 0.0) {
-		ms = s*1000.0;
+		ms = s * 1000.0;
 		return ast_safe_sleep(chan, ms);
 	}
 	return 0;
@@ -5720,7 +5724,7 @@ static int pbx_builtin_goto(struct ast_channel *chan, void *data)
 {
 	int res = ast_parseable_goto(chan, data);
 	if (!res)
-		ast_verb(3, "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
+		ast_verb(3, "Goto (%s,%s,%d)\n", chan->context, chan->exten, chan->priority + 1);
 	return res;
 }
 
@@ -5738,7 +5742,7 @@ int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **b
 	(*buf)->str[0] = '\0';
 
 	AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
-		if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
+		if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
 		   /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
 		   ) {
 			if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
@@ -5819,7 +5823,7 @@ void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const
 	const char *nametail = name;
 
 	/* XXX may need locking on the channel ? */
-	if (name[strlen(name)-1] == ')') {
+	if (name[strlen(name) - 1] == ')') {
 		char *function = ast_strdupa(name);
 
 		ast_func_write(chan, function, value);
@@ -5867,35 +5871,17 @@ void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const
 int pbx_builtin_setvar(struct ast_channel *chan, void *data)
 {
 	char *name, *value, *mydata;
-	int argc;
-	char *argv[24];		/* this will only support a maximum of 24 variables being set in a single operation */
-	int global = 0;
-	int x;
 
 	if (ast_strlen_zero(data)) {
-		ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
+		ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
 		return 0;
 	}
 
 	mydata = ast_strdupa(data);
-	argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
-
-	/* check for a trailing flags argument */
-	if ((argc > 1) && !strchr(argv[argc-1], '=')) {
-		argc--;
-		if (strchr(argv[argc], 'g'))
-			global = 1;
-	}
-
-	for (x = 0; x < argc; x++) {
-		name = argv[x];
-		if ((value = strchr(name, '='))) {
-			*value++ = '\0';
-			pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
-		} else
-			ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
-	}
+	name = strsep(&mydata, "=");
+	value = mydata;
 
+	pbx_builtin_setvar_helper(chan, name, value);
 	return(0);
 }
 
@@ -5905,15 +5891,21 @@ int pbx_builtin_importvar(struct ast_channel *chan, void *data)
 	char *value;
 	char *channel;
 	char tmp[VAR_BUF_SIZE]="";
+	static int deprecation_warning = 0;
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
 		return 0;
 	}
 
+	if (!deprecation_warning) {
+		ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
+		deprecation_warning = 1;
+	}
+
 	value = ast_strdupa(data);
 	name = strsep(&value,"=");
-	channel = strsep(&value,"|");
+	channel = strsep(&value,",");
 	if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
 		struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
 		if (chan2) {
@@ -5958,7 +5950,6 @@ int pbx_checkcondition(const char *condition)
 static int pbx_builtin_gotoif(struct ast_channel *chan, void *data)
 {
 	char *condition, *branch1, *branch2, *branch;
-	int rc;
 	char *stringp;
 
 	if (ast_strlen_zero(data)) {
@@ -5977,9 +5968,7 @@ static int pbx_builtin_gotoif(struct ast_channel *chan, void *data)
 		return 0;
 	}
 
-	rc = pbx_builtin_goto(chan, branch);
-
-	return rc;
+	return pbx_builtin_goto(chan, branch);
 }
 
 static int pbx_builtin_saynumber(struct ast_channel *chan, void *data)
@@ -5993,10 +5982,10 @@ static int pbx_builtin_saynumber(struct ast_channel *chan, void *data)
 		return -1;
 	}
 	ast_copy_string(tmp, data, sizeof(tmp));
-	strsep(&number, "|");
-	options = strsep(&number, "|");
+	strsep(&number, ",");
+	options = strsep(&number, ",");
 	if (options) {
-		if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
+		if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
 			strcasecmp(options, "c") && strcasecmp(options, "n") ) {
 			ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
 			return -1;
@@ -6313,13 +6302,13 @@ int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
 	int mode = 0;
 
 	if (ast_strlen_zero(goto_string)) {
-		ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
+		ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
 		return -1;
 	}
 	stringp = ast_strdupa(goto_string);
-	context = strsep(&stringp, "|");	/* guaranteed non-null */
-	exten = strsep(&stringp, "|");
-	pri = strsep(&stringp, "|");
+	context = strsep(&stringp, ",");	/* guaranteed non-null */
+	exten = strsep(&stringp, ",");
+	pri = strsep(&stringp, ",");
 	if (!exten) {	/* Only a priority in this one */
 		pri = context;
 		exten = NULL;
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index 799892ba966348681236fa6723838ac3b9e22a77..5a7280c9af2b38866fdd9d56f811121b1c4842cc 100644
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -1386,7 +1386,7 @@ static int pbx_load_config(const char *config_file)
 				if (tc) {
 					int ipri = -2;
 					char realext[256]="";
-					char *plus, *firstp, *firstc;
+					char *plus, *firstp;
 					char *pri, *appl, *data, *cidmatch;
 					char *stringp = tc;
 					char *ext = strsep(&stringp, ",");
@@ -1433,19 +1433,12 @@ static int pbx_load_config(const char *config_file)
 						ipri = 0;
 					}
 					appl = S_OR(stringp, "");
-					/* Find the first occurrence of either '(' or ',' */
-					firstc = strchr(appl, ',');
+					/* Find the first occurrence of '(' */
 					firstp = strchr(appl, '(');
-					if (firstc && (!firstp || firstc < firstp)) {
-						/* comma found, no parenthesis */
-						/* or both found, but comma found first */
-						appl = strsep(&stringp, ",");
-						data = stringp;
-					} else if (!firstc && !firstp) {
-						/* Neither found */
+					if (!firstp) {
+						/* No arguments */
 						data = "";
 					} else {
-						/* Final remaining case is parenthesis found first */
 						appl = strsep(&stringp, "(");
 						data = stringp;
 						end = strrchr(data, ')');
@@ -1454,11 +1447,10 @@ static int pbx_load_config(const char *config_file)
 						} else {
 							ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
 						}
-						ast_process_quotes_and_slashes(data, ',', '|');
 					}
 
 					if (!data)
-						data="";
+						data = "";
 					appl = ast_skip_blanks(appl);
 					if (ipri) {
 						if (plus)
@@ -1483,7 +1475,7 @@ static int pbx_load_config(const char *config_file)
 				if (ast_context_add_ignorepat2(con, realvalue, registrar))
 					ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
 			} else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
-				char *stringp= realvalue;
+				char *stringp = realvalue;
 				char *appl, *data;
 
 				memset(realvalue, 0, sizeof(realvalue));
@@ -1492,9 +1484,7 @@ static int pbx_load_config(const char *config_file)
 				else
 					ast_copy_string(realvalue, v->value, sizeof(realvalue));
 				appl = strsep(&stringp, "/");
-				data = strsep(&stringp, ""); /* XXX what for ? */
-				if (!data)
-					data = "";
+				data = S_OR(stringp, "");
 				if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar))
 					ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
 			} else {