From bd9b32bc0df1039ef1962b558ba258e4bdb1bbfd Mon Sep 17 00:00:00 2001
From: Glenn L McGrath <bug1@ihug.co.nz>
Date: Wed, 9 Apr 2003 01:43:54 +0000
Subject: Label ends at a newline, update comments, rename linked list field

---
 editors/sed.c | 73 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 37 insertions(+), 36 deletions(-)

diff --git a/editors/sed.c b/editors/sed.c
index a616c992c..db3171879 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -4,6 +4,7 @@
  * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley
  * Copyright (C) 1999,2000,2001 by Mark Whitley <markw@codepoet.org>
  * Copyright (C) 2002  Matt Kraai
+ * Copyright (C) 2003 by Glenn McGrath <bug1@optushome.com.au>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,6 +32,9 @@
 	 - file commands: (r)ead
 	 - backreferences in substitution expressions (\1, \2...\9)
 	 - grouped commands: {cmd1;cmd2}
+	 - transliteration (y/source-chars/dest-chars/)
+	 - pattern space hold space storing / swapping (g, h, x)
+	 - labels / branching (: label, b, t)
 
 	 (Note: Specifying an address (range) to match is *optional*; commands
 	 default to the whole pattern space if no specific address match was
@@ -38,11 +42,13 @@
 
 	Unsupported features:
 
-	 - transliteration (y/source-chars/dest-chars/) (use 'tr')
-	 - no pattern space hold space storing / swapping (x, etc.)
-	 - no labels / branching (: label, b, t, and friends)
+	 - GNU extensions
 	 - and lots, lots more.
 
+	Bugs:
+	
+	 - Cant subst globally using ^ or $ in regex, eg. "aah" | sed 's/^a/b/g'
+
 	Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
 */
 
@@ -55,19 +61,6 @@
 #include <stdlib.h>
 #include "busybox.h"
 
-/* the spec says label must be at least 8 chars, behavious is unspecified if more than 8 chars */
-#define SED_LABEL_LENGTH	8
-
-/* externs */
-extern void xregcomp(regex_t * preg, const char *regex, int cflags);
-extern int optind;		/* in unistd.h */
-extern char *optarg;	/* ditto */
-
-/* options */
-static int be_quiet = 0;
-static const char bad_format_in_subst[] =
-	"bad format in substitution expression";
-
 typedef struct sed_cmd_s {
 	/* Order by alignment requirements */
 
@@ -109,14 +102,25 @@ typedef struct sed_cmd_s {
 	int invert;			/* the '!' after the address */
 
 	/* Branch commands */
-	char label[SED_LABEL_LENGTH + 1];
+	char *label;
 
 	/* next command in list (sequential list of specified commands) */
-	struct sed_cmd_s *linear;
+	struct sed_cmd_s *next;
 
 } sed_cmd_t;
 
+
+/* externs */
+extern void xregcomp(regex_t * preg, const char *regex, int cflags);
+extern int optind;		/* in unistd.h */
+extern char *optarg;	/* ditto */
+
 /* globals */
+/* options */
+static int be_quiet = 0;
+static const char bad_format_in_subst[] =
+	"bad format in substitution expression";
+
 /* linked list of sed commands */
 static sed_cmd_t sed_cmd_head;
 static sed_cmd_t *sed_cmd_tail = &sed_cmd_head;
@@ -126,13 +130,14 @@ static int in_block = 0;
 const char *const semicolon_whitespace = "; \n\r\t\v\0";
 static regex_t *previous_regex_ptr = NULL;
 
+
 #ifdef CONFIG_FEATURE_CLEAN_UP
 static void destroy_cmd_strs(void)
 {
-	sed_cmd_t *sed_cmd = sed_cmd_head.linear;
+	sed_cmd_t *sed_cmd = sed_cmd_head.next;
 
 	while (sed_cmd) {
-		sed_cmd_t *sed_cmd_next = sed_cmd->linear;
+		sed_cmd_t *sed_cmd_next = sed_cmd->next;
 
 		if (sed_cmd->beg_match) {
 			regfree(sed_cmd->beg_match);
@@ -445,7 +450,7 @@ static int parse_file_cmd(sed_cmd_t * sed_cmd, const char *filecmdstr)
 /*
  *  Process the commands arguments
  */
-static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr)
+static char *parse_cmd_str(sed_cmd_t *sed_cmd, char *cmdstr)
 {
 	/* handle (s)ubstitution command */
 	if (sed_cmd->cmd == 's') {
@@ -469,11 +474,8 @@ static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr)
 		int length;
 
 		cmdstr += strspn(cmdstr, " ");
-		length = strcspn(cmdstr, "; ");
-		if (length > SED_LABEL_LENGTH) {
-			length = SED_LABEL_LENGTH;
-		}
-		strncpy(sed_cmd->label, cmdstr, length);
+		length = strcspn(cmdstr, "; \n");
+		sed_cmd->label = strndup(cmdstr, length);
 		cmdstr += length;
 	}
 	/* translation command */
@@ -595,8 +597,8 @@ static char *add_cmd(sed_cmd_t * sed_cmd, char *cmdstr)
 	cmdstr = parse_cmd_str(sed_cmd, cmdstr);
 
 	/* Add the command to the command array */
-	sed_cmd_tail->linear = sed_cmd;
-	sed_cmd_tail = sed_cmd_tail->linear;
+	sed_cmd_tail->next = sed_cmd;
+	sed_cmd_tail = sed_cmd_tail->next;
 
 	return (cmdstr);
 }
@@ -805,9 +807,8 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line)
 static sed_cmd_t *branch_to(const char *label)
 {
 	sed_cmd_t *sed_cmd;
-
-	for (sed_cmd = sed_cmd_head.linear; sed_cmd; sed_cmd = sed_cmd->linear) {
-		if (strcmp(sed_cmd->label, label) == 0) {
+	for (sed_cmd = sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
+		if ((sed_cmd->label) && (strcmp(sed_cmd->label, label) == 0)) {
 			break;
 		}
 	}
@@ -844,8 +845,8 @@ static void process_file(FILE * file)
 		force_print = 0;
 
 		/* for every line, go through all the commands */
-		for (sed_cmd = sed_cmd_head.linear; sed_cmd;
-			 sed_cmd = sed_cmd->linear) {
+		for (sed_cmd = sed_cmd_head.next; sed_cmd;
+			 sed_cmd = sed_cmd->next) {
 			int deleted = 0;
 
 			/*
@@ -952,8 +953,8 @@ static void process_file(FILE * file)
 					}
 #endif
 					altered |= substituted;
-					if (!be_quiet && altered && ((sed_cmd->linear == NULL)
-												 || (sed_cmd->linear->cmd !=
+					if (!be_quiet && altered && ((sed_cmd->next == NULL)
+												 || (sed_cmd->next->cmd !=
 													 's'))) {
 						force_print = 1;
 					}
@@ -1160,7 +1161,7 @@ extern int sed_main(int argc, char **argv)
 
 	/* if we didn't get a pattern from a -e and no command file was specified,
 	 * argv[optind] should be the pattern. no pattern, no worky */
-	if (sed_cmd_head.linear == NULL) {
+	if (sed_cmd_head.next == NULL) {
 		if (argv[optind] == NULL)
 			bb_show_usage();
 		else {
-- 
cgit v1.2.3-55-g6feb