Experimental support for embeded newline. (im evil)
authorGlenn L McGrath <bug1@ihug.co.nz>
Sun, 30 Mar 2003 03:41:53 +0000 (03:41 -0000)
committerGlenn L McGrath <bug1@ihug.co.nz>
Sun, 30 Mar 2003 03:41:53 +0000 (03:41 -0000)
Fix segfault when using 'N' with an odd number of lines.

editors/Config.in
editors/sed.c

index 4f281759838d9d0da2b05e2d49d30ac5d8e5c2c3..c752677594365ce6616b36e99aa2185417abbb1a 100644 (file)
@@ -24,6 +24,15 @@ config CONFIG_SED
        help
          Please submit a patch to add help text for this item.
 
+config CONFIG_FEATURE_SED_EMBEDED_NEWLINE
+       bool " Embeded newline (EXPERIMENTAL)"
+       default n
+       depends on CONFIG_SED
+       help
+         This is a hack to allow matching of '\n' in regular expressions.
+         It works by translating '\n' to "\n" and back.
+         It may introduce unexpected results if you use "\n" in your text.
+
 config CONFIG_VI
        bool "vi"
        default n
index 1cbf974b650755183e0fd4e0874282365ff368a7..292bc8662aa324fcada3bb368b02437c78c2f170 100644 (file)
@@ -430,7 +430,7 @@ static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr)
 
 static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
 {
-       
+
        /* Skip over leading whitespace and semicolons */
        cmdstr += strspn(cmdstr, semicolon_whitespace);
 
@@ -491,7 +491,6 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
                        cmdstr++;
                }
 #endif
-
        }
 
        /* last part (mandatory) will be a command */
@@ -529,6 +528,18 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
 
 static void add_cmd_str(char *cmdstr)
 {
+#ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE
+       char *cmdstr_ptr = cmdstr;
+
+       /* HACK: convert "\n" to match tranlated '\n' string */
+       while((cmdstr_ptr = strstr(cmdstr_ptr, "\\n")) != NULL) {
+               cmdstr = xrealloc(cmdstr, strlen(cmdstr) + 2);
+               cmdstr_ptr = strstr(cmdstr, "\\n");
+               memmove(cmdstr_ptr + 1, cmdstr_ptr, strlen(cmdstr_ptr) + 1);
+               cmdstr_ptr[0] = '\\';
+               cmdstr_ptr += 3;
+       }
+#endif
        do {
                sed_cmd_t *sed_cmd;
                sed_cmd = xcalloc(1, sizeof(sed_cmd_t));
@@ -795,8 +806,35 @@ static void process_file(FILE *file)
                                                 *    flag exists in the first place.
                                                 */
 
+#ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE
+                                               /* HACK: escape newlines twice so regex can match them */
+                                               {
+                                                       int offset = 0;
+                                                       while(strchr(line + offset, '\n') != NULL) {
+                                                               char *tmp;
+                                                               line = xrealloc(line, strlen(line) + 2);
+                                                               tmp = strchr(line + offset, '\n');
+                                                               memmove(tmp + 1, tmp, strlen(tmp) + 1);
+                                                               tmp[0] = '\\';
+                                                               tmp[1] = 'n';
+                                                               offset = tmp - line + 2;
+                                                       }
+                                               }
+#endif
                                                /* we print the line once, unless we were told to be quiet */
                                                substituted = do_subst_command(sed_cmd, &line);
+
+#ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE
+                                               /* undo HACK: escape newlines twice so regex can match them */
+                                               {
+                                                       char *tmp = line;
+
+                                                       while((tmp = strstr(tmp, "\\n")) != NULL) {
+                                                               memmove(tmp, tmp + 1, strlen(tmp + 1) + 1);
+                                                               tmp[0] = '\n';
+                                                       }
+                                               }
+#endif
                                                altered |= substituted;
                                                if (!be_quiet && altered && ((sed_cmd->linear == NULL) || (sed_cmd->linear->cmd != 's'))) {
                                                        force_print = 1;
@@ -857,11 +895,13 @@ static void process_file(FILE *file)
                                                linenum++;
                                                break;
                                        case 'N':       /* Append the next line to the current line */
-                                               line = realloc(line, strlen(line) + strlen(next_line) + 2);
-                                               strcat(line, "\n");
-                                               strcat(line, next_line);
-                                               next_line = bb_get_chomped_line_from_file(file);
-                                               linenum++;
+                                               if (next_line) {
+                                                       line = realloc(line, strlen(line) + strlen(next_line) + 2);
+                                                       strcat(line, "\n");
+                                                       strcat(line, next_line);
+                                                       next_line = bb_get_chomped_line_from_file(file);
+                                                       linenum++;
+                                               }
                                                break;
                                        case 'b':
                                                sed_cmd = branch_to(sed_cmd->label);
@@ -934,9 +974,12 @@ extern int sed_main(int argc, char **argv)
                        case 'n':
                                be_quiet++;
                                break;
-                       case 'e':
-                               add_cmd_str(optarg);
+                       case 'e': {
+                               char *str_cmd = strdup(optarg);
+                               add_cmd_str(str_cmd);
+                               free(str_cmd);
                                break;
+                       }
                        case 'f': 
                                load_cmd_file(optarg);
                                break;
@@ -951,7 +994,9 @@ extern int sed_main(int argc, char **argv)
                if (argv[optind] == NULL)
                        bb_show_usage();
                else {
-                       add_cmd_str(argv[optind]);
+                       char *str_cmd = strdup(argv[optind]);
+                       add_cmd_str(strdup(str_cmd));
+                       free(str_cmd);
                        optind++;
                }
        }