[BusyBox-cvs] busybox/editors sed.c,1.100,1.101

Glenn McGrath bug1 at busybox.net
Sun Mar 9 15:12:27 UTC 2003


Update of /var/cvs/busybox/editors
In directory winder:/tmp/cvs-serv8552/editors

Modified Files:
	sed.c 
Log Message:
Support grouped commands, i.e. {cmd1;cmd2}


Index: sed.c
===================================================================
RCS file: /var/cvs/busybox/editors/sed.c,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -d -r1.100 -r1.101
--- sed.c	9 Mar 2003 11:06:38 -0000	1.100
+++ sed.c	9 Mar 2003 15:12:24 -0000	1.101
@@ -30,7 +30,8 @@
 	 - edit commands: (a)ppend, (i)nsert, (c)hange
 	 - file commands: (r)ead
 	 - backreferences in substitution expressions (\1, \2...\9)
-	 
+	 - grouped commands: {cmd1;cmd2}
+
 	 (Note: Specifying an address (range) to match is *optional*; commands
 	 default to the whole pattern space if no specific address match was
 	 requested.)
@@ -226,7 +227,7 @@
 
 	/* verify that the 's' is followed by something.  That something
 	 * (typically a 'slash') is now our regexp delimiter... */
-	if (!substr[++idx])
+	if (substr[idx] == '\0')
 		error_msg_and_die("bad format in substitution expression");
 	else
 	    sed_cmd->delimiter=substr[idx];
@@ -287,11 +288,6 @@
 	return idx;
 }
 
-static void move_back(char *str, int offset)
-{
-	memmove(str, str + offset, strlen(str + offset) + 1);
-}
-
 static int parse_edit_cmd(sed_cmd_t *sed_cmd, const char *editstr)
 {
 	int i, j;
@@ -317,15 +313,15 @@
 	 * is a-ok.
 	 *
 	 */
-
-	if (editstr[1] != '\\' || (editstr[2] != '\n' && editstr[2] != '\r'))
+	if ((*editstr != '\\') || ((editstr[1] != '\n') && (editstr[1] != '\r'))) {
 		error_msg_and_die("bad format in edit expression");
+	}
 
 	/* store the edit line text */
-	sed_cmd->editline = xmalloc(strlen(&editstr[3]) + 2);
-	for (i = 3, j = 0; editstr[i] != '\0' && strchr("\r\n", editstr[i]) == NULL;
+	sed_cmd->editline = xmalloc(strlen(&editstr[2]) + 2);
+	for (i = 2, j = 0; editstr[i] != '\0' && strchr("\r\n", editstr[i]) == NULL;
 			i++, j++) {
-		if (editstr[i] == '\\' && strchr("\n\r", editstr[i+1]) != NULL) {
+		if ((editstr[i] == '\\') && strchr("\n\r", editstr[i+1]) != NULL) {
 			sed_cmd->editline[j] = '\n';
 			i++;
 		} else
@@ -382,6 +378,53 @@
 
 static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr)
 {
+	/* if it was a single-letter command that takes no arguments (such as 'p'
+	 * or 'd') all we need to do is increment the index past that command */
+	if (strchr("pd=", sed_cmd->cmd)) {
+		cmdstr++;
+	}
+	/* handle (s)ubstitution command */
+	else if (sed_cmd->cmd == 's') {
+		cmdstr += parse_subst_cmd(sed_cmd, cmdstr);
+	}
+	/* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */
+	else if (strchr("aic", sed_cmd->cmd)) {
+		if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c')
+			error_msg_and_die("only a beginning address can be specified for edit commands");
+		cmdstr += parse_edit_cmd(sed_cmd, cmdstr);
+	}
+	/* handle file cmds: (r)ead */
+	else if (sed_cmd->cmd == 'r') {
+		if (sed_cmd->end_line || sed_cmd->end_match)
+			error_msg_and_die("Command only uses one address");
+		cmdstr += parse_file_cmd(sed_cmd, cmdstr);
+	}
+	/* handle grouped commands */
+	else {
+		error_msg_and_die("Unsupported command %c", sed_cmd->cmd);
+	}
+
+	/* give back whatever's left over */
+	return(cmdstr);
+}
+
+static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
+{
+	
+	/* Skip over leading whitespace and semicolons */
+	cmdstr += strspn(cmdstr, semicolon_whitespace);
+
+	/* if we ate the whole thing, that means there was just trailing
+	 * whitespace or a final / no-op semicolon. either way, get out */
+	if (*cmdstr == '\0') {
+		return(NULL);
+	}
+
+	/* if this is a comment, jump past it and keep going */
+	if (*cmdstr == '#') {
+		return(strpbrk(cmdstr, "\n\r"));
+	}
+
 	/* parse the command
 	 * format is: [addr][,addr]cmd
 	 *            |----||-----||-|
@@ -389,26 +432,26 @@
 	 */
 
 	/* first part (if present) is an address: either a '$', a number or a /regex/ */
-	cmdstr += get_address(&sed_cmd->delimiter, cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match);
+	cmdstr += get_address(&(sed_cmd->delimiter), cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match);
 
 	/* second part (if present) will begin with a comma */
 	if (*cmdstr == ',') {
-		int tmp_idx;
+		int idx;
 		cmdstr++;
-		tmp_idx = get_address(&sed_cmd->delimiter, cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
-		if (tmp_idx == 0) {
+		idx = get_address(&(sed_cmd->delimiter), cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
+		if (idx == 0) {
 			error_msg_and_die("get_address: no address found in string\n"
 				"\t(you probably didn't check the string you passed me)");
 		}
-		cmdstr += tmp_idx;
+		cmdstr += idx;
 	}
 
 	/* skip whitespace before the command */
-	while (isspace(*cmdstr))
+	while (isspace(*cmdstr)) {
 		cmdstr++;
+	}
 
 	/* there my be the inversion flag between part2 and part3 */
-	sed_cmd->invert = 0;
 	if (*cmdstr == '!') {
 		sed_cmd->invert = 1;
 		cmdstr++;
@@ -419,14 +462,16 @@
 		 * and conforming applications shall not follow a '!' character
 		 * with <blank>s.
 		 */
-		if (isblank(*cmdstr) {
+		if (isblank(cmdstr[idx]) {
 			error_msg_and_die("blank follows '!'");
 		}
 #else 
 		/* skip whitespace before the command */
-		while (isspace(*cmdstr))
+		while (isspace(*cmdstr)) {
 			cmdstr++;
+		}
 #endif
+
 	}
 
 	/* last part (mandatory) will be a command */
@@ -434,61 +479,34 @@
 		error_msg_and_die("missing command");
 
 	sed_cmd->cmd = *cmdstr;
+	cmdstr++;
 
-	/* if it was a single-letter command that takes no arguments (such as 'p'
-	 * or 'd') all we need to do is increment the index past that command */
-	if (strchr("pd=", sed_cmd->cmd)) {
-		cmdstr++;
-	}
-	/* handle (s)ubstitution command */
-	else if (sed_cmd->cmd == 's') {
-		cmdstr += parse_subst_cmd(sed_cmd, cmdstr);
-	}
-	/* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */
-	else if (strchr("aic", sed_cmd->cmd)) {
-		if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c')
-			error_msg_and_die("only a beginning address can be specified for edit commands");
-		cmdstr += parse_edit_cmd(sed_cmd, cmdstr);
-	}
-	/* handle file cmds: (r)ead */
-	else if (sed_cmd->cmd == 'r') {
-		if (sed_cmd->end_line || sed_cmd->end_match)
-			error_msg_and_die("Command only uses one address");
-		cmdstr += parse_file_cmd(sed_cmd, cmdstr);
-	}
-	else {
-		error_msg_and_die("Unsupported command %c", sed_cmd->cmd);
-	}
+	if (sed_cmd->cmd == '{') {
+		do {
+			char *end_ptr = strpbrk(cmdstr, ";}");
+			*end_ptr = '\0';
+			add_cmd(sed_cmd, cmdstr);
+			cmdstr = end_ptr + 1;
+		} while (*cmdstr != '\0');
+	} else {
 
-	/* give back whatever's left over */
+		cmdstr = parse_cmd_str(sed_cmd, cmdstr);
+
+		/* Add the command to the command array */
+		sed_cmds = xrealloc(sed_cmds, sizeof(sed_cmd_t) * (++ncmds));
+		sed_cmds[ncmds-1] = xmalloc(sizeof(sed_cmd_t));
+		memcpy(sed_cmds[ncmds-1], sed_cmd, sizeof(sed_cmd_t));
+	}
 	return(cmdstr);
 }
 
-static void add_cmd_str(const char * const cmdstr)
+static void add_cmd_str(char *cmdstr)
 {
-	char *mystr = (char *)cmdstr;
-
 	do {
-
-		/* trim leading whitespace and semicolons */
-		move_back(mystr, strspn(mystr, semicolon_whitespace));
-		/* if we ate the whole thing, that means there was just trailing
-		 * whitespace or a final / no-op semicolon. either way, get out */
-		if (strlen(mystr) == 0)
-			return;
-		/* if this is a comment, jump past it and keep going */
-		if (mystr[0] == '#') {
-			mystr = strpbrk(mystr, "\n\r");
-			continue;
-		}
-		/* grow the array */
-		sed_cmds = xrealloc(sed_cmds, sizeof(sed_cmd_t *) * (++ncmds));
-		/* zero new element */
-		sed_cmds[ncmds-1] = xcalloc(1, sizeof(sed_cmd_t));
-		/* load command string into new array element, get remainder */
-		mystr = parse_cmd_str(sed_cmds[ncmds-1], mystr);
-
-	} while (mystr && strlen(mystr));
+		sed_cmd_t *sed_cmd;
+		sed_cmd = xcalloc(1, sizeof(sed_cmd_t));
+		cmdstr = add_cmd(sed_cmd, cmdstr);
+	} while (cmdstr && strlen(cmdstr));
 }
 
 
@@ -867,7 +885,6 @@
 			optind++;
 		}
 	}
-
 
 	/* argv[(optind)..(argc-1)] should be names of file to process. If no
 	 * files were specified or '-' was specified, take input from stdin.




More information about the busybox-cvs mailing list