summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-11-10 10:49:42 +0000
committerEric Andersen <andersen@codepoet.org>2001-11-10 10:49:42 +0000
commitc52a6b0f1023268f021d04ddf224db5c5dd7b13e (patch)
tree7d6eb161fcd9d581d1d280503c05e4f2d4517dd0
parente5d58c3dcc83c007dce35eaecf0a35c6ae598648 (diff)
downloadbusybox-w32-c52a6b0f1023268f021d04ddf224db5c5dd7b13e.tar.gz
busybox-w32-c52a6b0f1023268f021d04ddf224db5c5dd7b13e.tar.bz2
busybox-w32-c52a6b0f1023268f021d04ddf224db5c5dd7b13e.zip
|2001-10-08 Rodney Brown <rbrown64@csc.com.au>
| | * editors/sed.c: Fix multiline [aic] commands. Make # an endline | comment for compatibility. Codespace reduction. | * tests/testcases: Cope with move to subdirectories. | * testsuite/sed/sed-aic-commands: Add. | | text data bss dec hex filename | 3772 16 0 3788 ecc editors/sed.o | 4516 16 0 4532 11b4 editors/sed.o.bu
-rw-r--r--editors/sed.c187
-rw-r--r--tests/testcases16
-rw-r--r--testsuite/sed/sed-aic-commands134
3 files changed, 243 insertions, 94 deletions
diff --git a/editors/sed.c b/editors/sed.c
index 10cab7d56..428b516ad 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -61,41 +61,40 @@ static int be_quiet = 0;
61 61
62 62
63struct sed_cmd { 63struct sed_cmd {
64 64 /* Order by alignment requirements */
65
66 /* GENERAL FIELDS */
67 char delimiter; /* The delimiter used to separate regexps */
68 65
69 /* address storage */ 66 /* address storage */
70 int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */
71 int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */
72 regex_t *beg_match; /* sed -e '/match/cmd' */ 67 regex_t *beg_match; /* sed -e '/match/cmd' */
73 regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ 68 regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */
74 69
75 /* the command */
76 char cmd; /* p,d,s (add more at your leisure :-) */
77
78
79 /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ 70 /* SUBSTITUTION COMMAND SPECIFIC FIELDS */
80 71
81 /* sed -e 's/sub_match/replace/' */ 72 /* sed -e 's/sub_match/replace/' */
82 regex_t *sub_match; 73 regex_t *sub_match;
83 char *replace; 74 char *replace;
75
76 /* EDIT COMMAND (a,i,c) SPECIFIC FIELDS */
77 char *editline;
78
79 /* FILE COMMAND (r) SPECIFIC FIELDS */
80 char *filename;
81
82 /* address storage */
83 int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */
84 int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */
85 /* SUBSTITUTION COMMAND SPECIFIC FIELDS */
86
84 unsigned int num_backrefs:4; /* how many back references (\1..\9) */ 87 unsigned int num_backrefs:4; /* how many back references (\1..\9) */
85 /* Note: GNU/POSIX sed does not save more than nine backrefs, so 88 /* Note: GNU/POSIX sed does not save more than nine backrefs, so
86 * we only use 4 bits to hold the number */ 89 * we only use 4 bits to hold the number */
87 unsigned int sub_g:1; /* sed -e 's/foo/bar/g' (global) */ 90 unsigned int sub_g:1; /* sed -e 's/foo/bar/g' (global) */
88 unsigned int sub_p:2; /* sed -e 's/foo/bar/p' (print substitution) */ 91 unsigned int sub_p:2; /* sed -e 's/foo/bar/p' (print substitution) */
89 92
93 /* GENERAL FIELDS */
94 char delimiter; /* The delimiter used to separate regexps */
90 95
91 /* EDIT COMMAND (a,i,c) SPEICIFIC FIELDS */ 96 /* the command */
92 97 char cmd; /* p,d,s (add more at your leisure :-) */
93 char *editline;
94
95
96 /* FILE COMMAND (r) SPEICIFIC FIELDS */
97
98 char *filename;
99}; 98};
100 99
101/* globals */ 100/* globals */
@@ -104,6 +103,8 @@ static int ncmds = 0; /* number of sed commands */
104 103
105/*static char *cur_file = NULL;*/ /* file currently being processed XXX: do I need this? */ 104/*static char *cur_file = NULL;*/ /* file currently being processed XXX: do I need this? */
106 105
106const char * const semicolon_whitespace = "; \n\r\t\v\0";
107
107#ifdef CONFIG_FEATURE_CLEAN_UP 108#ifdef CONFIG_FEATURE_CLEAN_UP
108static void destroy_cmd_strs() 109static void destroy_cmd_strs()
109{ 110{
@@ -142,23 +143,24 @@ static void destroy_cmd_strs()
142 * expression delimiter (typically a forward * slash ('/')) not preceeded by 143 * expression delimiter (typically a forward * slash ('/')) not preceeded by
143 * a backslash ('\'). 144 * a backslash ('\').
144 */ 145 */
145static int index_of_next_unescaped_regexp_delim(struct sed_cmd *sed_cmd, const char *str, int idx) 146static int index_of_next_unescaped_regexp_delim(const struct sed_cmd * const sed_cmd, const char *str, int idx)
146{ 147{
147 int bracket = -1; 148 int bracket = -1;
148 int escaped = 0; 149 int escaped = 0;
150 char ch;
149 151
150 for ( ; str[idx]; idx++) { 152 for ( ; (ch = str[idx]); idx++) {
151 if (bracket != -1) { 153 if (bracket != -1) {
152 if (str[idx] == ']' && !(bracket == idx - 1 || 154 if (ch == ']' && !(bracket == idx - 1 ||
153 (bracket == idx - 2 && str[idx-1] == '^'))) 155 (bracket == idx - 2 && str[idx-1] == '^')))
154 bracket = -1; 156 bracket = -1;
155 } else if (escaped) 157 } else if (escaped)
156 escaped = 0; 158 escaped = 0;
157 else if (str[idx] == '\\') 159 else if (ch == '\\')
158 escaped = 1; 160 escaped = 1;
159 else if (str[idx] == '[') 161 else if (ch == '[')
160 bracket = idx; 162 bracket = idx;
161 else if (str[idx] == sed_cmd->delimiter) 163 else if (ch == sed_cmd->delimiter)
162 return idx; 164 return idx;
163 } 165 }
164 166
@@ -208,7 +210,7 @@ static int get_address(struct sed_cmd *sed_cmd, const char *str, int *linenum, r
208 return idx; 210 return idx;
209} 211}
210 212
211static int parse_subst_cmd(struct sed_cmd *sed_cmd, const char *substr) 213static int parse_subst_cmd(struct sed_cmd * const sed_cmd, const char *substr)
212{ 214{
213 int oldidx, cflags = REG_NEWLINE; 215 int oldidx, cflags = REG_NEWLINE;
214 char *match; 216 char *match;
@@ -271,7 +273,7 @@ static int parse_subst_cmd(struct sed_cmd *sed_cmd, const char *substr)
271 break; 273 break;
272 default: 274 default:
273 /* any whitespace or semicolon trailing after a s/// is ok */ 275 /* any whitespace or semicolon trailing after a s/// is ok */
274 if (strchr("; \t\v\n\r", substr[idx])) 276 if (strchr(semicolon_whitespace, substr[idx]))
275 goto out; 277 goto out;
276 /* else */ 278 /* else */
277 error_msg_and_die("bad option in substitution expression"); 279 error_msg_and_die("bad option in substitution expression");
@@ -287,6 +289,11 @@ out:
287 return idx; 289 return idx;
288} 290}
289 291
292static void move_back(char *str, int offset)
293{
294 memmove(str, str + offset, strlen(str + offset) + 1);
295}
296
290static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr) 297static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
291{ 298{
292 int idx = 0; 299 int idx = 0;
@@ -334,8 +341,7 @@ static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
334 } 341 }
335 } 342 }
336 /* move the newline over the '\' before it (effectively eats the '\') */ 343 /* move the newline over the '\' before it (effectively eats the '\') */
337 memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1])); 344 move_back(&ptr[idx], 1);
338 ptr[strlen(ptr)-1] = 0;
339 slashes_eaten++; 345 slashes_eaten++;
340 /* substitue \r for \n if needed */ 346 /* substitue \r for \n if needed */
341 if (ptr[idx] == '\r') 347 if (ptr[idx] == '\r')
@@ -343,10 +349,6 @@ static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
343 } 349 }
344 350
345out: 351out:
346 /* this accounts for discrepancies between the modified string and the
347 * original string passed in to this function */
348 idx += slashes_eaten;
349
350 /* figure out if we need to add a newline */ 352 /* figure out if we need to add a newline */
351 if (ptr[idx-1] != '\n') { 353 if (ptr[idx-1] != '\n') {
352 ptr[idx] = '\n'; 354 ptr[idx] = '\n';
@@ -355,10 +357,13 @@ out:
355 357
356 /* terminate string */ 358 /* terminate string */
357 ptr[idx]= 0; 359 ptr[idx]= 0;
360
361 /* this accounts for discrepancies between the modified string and the
362 * original string passed in to this function */
363
358 /* adjust for opening 2 chars [aic]\ */ 364 /* adjust for opening 2 chars [aic]\ */
359 idx += 2;
360 365
361 return idx; 366 return idx + slashes_eaten + 2;
362} 367}
363 368
364 369
@@ -391,7 +396,7 @@ static int parse_file_cmd(struct sed_cmd *sed_cmd, const char *filecmdstr)
391 396
392 /* the first non-whitespace we get is a filename. the filename ends when we 397 /* the first non-whitespace we get is a filename. the filename ends when we
393 * hit a normal sed command terminator or end of string */ 398 * hit a normal sed command terminator or end of string */
394 filenamelen = strcspn(&filecmdstr[idx], "; \n\r\t\v\0"); 399 filenamelen = strcspn(&filecmdstr[idx], semicolon_whitespace);
395 sed_cmd->filename = xmalloc(filenamelen + 1); 400 sed_cmd->filename = xmalloc(filenamelen + 1);
396 safe_strncpy(sed_cmd->filename, &filecmdstr[idx], filenamelen + 1); 401 safe_strncpy(sed_cmd->filename, &filecmdstr[idx], filenamelen + 1);
397 402
@@ -399,7 +404,7 @@ static int parse_file_cmd(struct sed_cmd *sed_cmd, const char *filecmdstr)
399} 404}
400 405
401 406
402static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr) 407static char *parse_cmd_str(struct sed_cmd * const sed_cmd, const char *const cmdstr)
403{ 408{
404 int idx = 0; 409 int idx = 0;
405 410
@@ -424,7 +429,7 @@ static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr)
424 429
425 /* if it was a single-letter command that takes no arguments (such as 'p' 430 /* if it was a single-letter command that takes no arguments (such as 'p'
426 * or 'd') all we need to do is increment the index past that command */ 431 * or 'd') all we need to do is increment the index past that command */
427 if (strchr("pd", cmdstr[idx])) { 432 if (strchr("pd", sed_cmd->cmd)) {
428 idx++; 433 idx++;
429 } 434 }
430 /* handle (s)ubstitution command */ 435 /* handle (s)ubstitution command */
@@ -451,21 +456,21 @@ static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr)
451 return (char *)&cmdstr[idx]; 456 return (char *)&cmdstr[idx];
452} 457}
453 458
454static void add_cmd_str(const char *cmdstr) 459static void add_cmd_str(const char * const cmdstr)
455{ 460{
456 char *mystr = (char *)cmdstr; 461 char *mystr = (char *)cmdstr;
457 462
458 do { 463 do {
459 464
460 /* trim leading whitespace and semicolons */ 465 /* trim leading whitespace and semicolons */
461 memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr)); 466 move_back(mystr, strspn(mystr, semicolon_whitespace));
462 /* if we ate the whole thing, that means there was just trailing 467 /* if we ate the whole thing, that means there was just trailing
463 * whitespace or a final / no-op semicolon. either way, get out */ 468 * whitespace or a final / no-op semicolon. either way, get out */
464 if (strlen(mystr) == 0) 469 if (strlen(mystr) == 0)
465 return; 470 return;
466 /* if this is a comment, jump past it and keep going */ 471 /* if this is a comment, jump past it and keep going */
467 if (mystr[0] == '#') { 472 if (mystr[0] == '#') {
468 mystr = strpbrk(mystr, ";\n\r"); 473 mystr = strpbrk(mystr, "\n\r");
469 continue; 474 continue;
470 } 475 }
471 /* grow the array */ 476 /* grow the array */
@@ -503,23 +508,41 @@ static void load_cmd_file(char *filename)
503 } 508 }
504} 509}
505 510
511struct pipeline {
512 char *buf;
513 int idx;
514 int len;
515};
516
506#define PIPE_MAGIC 0x7f 517#define PIPE_MAGIC 0x7f
507#define PIPE_GROW 64 518#define PIPE_GROW 64
508#define pipeputc(c) \ 519
520void pipe_putc(struct pipeline *const pipeline, char c)
521{
522 if (pipeline->buf[pipeline->idx] == PIPE_MAGIC) {
523 pipeline->buf =
524 xrealloc(pipeline->buf, pipeline->len + PIPE_GROW);
525 memset(pipeline->buf + pipeline->len, 0, PIPE_GROW);
526 pipeline->len += PIPE_GROW;
527 pipeline->buf[pipeline->len - 1] = PIPE_MAGIC;
528 }
529 pipeline->buf[pipeline->idx++] = (c);
530}
531
532#define pipeputc(c) pipe_putc(pipeline, c)
533
534#if 0
509{ if (pipeline[pipeline_idx] == PIPE_MAGIC) { \ 535{ if (pipeline[pipeline_idx] == PIPE_MAGIC) { \
510 pipeline = xrealloc(pipeline, pipeline_len+PIPE_GROW); \ 536 pipeline = xrealloc(pipeline, pipeline_len+PIPE_GROW); \
511 memset(pipeline+pipeline_len, 0, PIPE_GROW); \ 537 memset(pipeline+pipeline_len, 0, PIPE_GROW); \
512 pipeline_len += PIPE_GROW; \ 538 pipeline_len += PIPE_GROW; \
513 pipeline[pipeline_len-1] = PIPE_MAGIC; } \ 539 pipeline[pipeline_len-1] = PIPE_MAGIC; } \
514 pipeline[pipeline_idx++] = (c); } 540 pipeline[pipeline_idx++] = (c); }
541#endif
515 542
516static void print_subst_w_backrefs(const char *line, const char *replace, 543static void print_subst_w_backrefs(const char *line, const char *replace,
517 regmatch_t *regmatch, char **pipeline_p, int *pipeline_idx_p, 544 regmatch_t *regmatch, struct pipeline *const pipeline, int matches)
518 int *pipeline_len_p, int matches)
519{ 545{
520 char *pipeline = *pipeline_p;
521 int pipeline_idx = *pipeline_idx_p;
522 int pipeline_len = *pipeline_len_p;
523 int i; 546 int i;
524 547
525 /* go through the replacement string */ 548 /* go through the replacement string */
@@ -558,17 +581,13 @@ static void print_subst_w_backrefs(const char *line, const char *replace,
558 else 581 else
559 pipeputc(replace[i]); 582 pipeputc(replace[i]);
560 } 583 }
561 *pipeline_p = pipeline;
562 *pipeline_idx_p = pipeline_idx;
563 *pipeline_len_p = pipeline_len;
564} 584}
565 585
566static int do_subst_command(const struct sed_cmd *sed_cmd, char **line) 586static int do_subst_command(const struct sed_cmd *sed_cmd, char **line)
567{ 587{
568 char *hackline = *line; 588 char *hackline = *line;
569 char *pipeline = 0; 589 struct pipeline thepipe = { NULL, 0 , 0};
570 int pipeline_idx = 0; 590 struct pipeline *const pipeline = &thepipe;
571 int pipeline_len = 0;
572 int altered = 0; 591 int altered = 0;
573 regmatch_t *regmatch = NULL; 592 regmatch_t *regmatch = NULL;
574 593
@@ -581,11 +600,10 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, char **line)
581 600
582 /* allocate more PIPE_GROW bytes 601 /* allocate more PIPE_GROW bytes
583 if replaced string is larger than original */ 602 if replaced string is larger than original */
584 pipeline_len = strlen(hackline)+PIPE_GROW; 603 thepipe.len = strlen(hackline)+PIPE_GROW;
585 pipeline = xmalloc(pipeline_len); 604 thepipe.buf = xcalloc(1, thepipe.len);
586 memset(pipeline, 0, pipeline_len);
587 /* buffer magic */ 605 /* buffer magic */
588 pipeline[pipeline_len-1] = PIPE_MAGIC; 606 thepipe.buf[thepipe.len-1] = PIPE_MAGIC;
589 607
590 /* and now, as long as we've got a line to try matching and if we can match 608 /* and now, as long as we've got a line to try matching and if we can match
591 * the search string, we make substitutions */ 609 * the search string, we make substitutions */
@@ -599,8 +617,7 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, char **line)
599 617
600 /* then print the substitution string */ 618 /* then print the substitution string */
601 print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, 619 print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch,
602 &pipeline, &pipeline_idx, &pipeline_len, 620 pipeline, sed_cmd->num_backrefs);
603 sed_cmd->num_backrefs);
604 621
605 /* advance past the match */ 622 /* advance past the match */
606 hackline += regmatch[0].rm_eo; 623 hackline += regmatch[0].rm_eo;
@@ -613,13 +630,13 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, char **line)
613 } 630 }
614 631
615 for (; *hackline; hackline++) pipeputc(*hackline); 632 for (; *hackline; hackline++) pipeputc(*hackline);
616 if (pipeline[pipeline_idx] == PIPE_MAGIC) pipeline[pipeline_idx] = 0; 633 if (thepipe.buf[thepipe.idx] == PIPE_MAGIC) thepipe.buf[thepipe.idx] = 0;
617 634
618 /* cleanup */ 635 /* cleanup */
619 free(regmatch); 636 free(regmatch);
620 637
621 free(*line); 638 free(*line);
622 *line = pipeline; 639 *line = thepipe.buf;
623 return altered; 640 return altered;
624} 641}
625 642
@@ -641,6 +658,7 @@ static void process_file(FILE *file)
641 658
642 /* for every line, go through all the commands */ 659 /* for every line, go through all the commands */
643 for (i = 0; i < ncmds; i++) { 660 for (i = 0; i < ncmds; i++) {
661 struct sed_cmd *sed_cmd = &sed_cmds[i];
644 662
645 663
646 /* 664 /*
@@ -648,13 +666,13 @@ static void process_file(FILE *file)
648 */ 666 */
649 if ( 667 if (
650 /* no range necessary */ 668 /* no range necessary */
651 (sed_cmds[i].beg_line == 0 && sed_cmds[i].end_line == 0 && 669 (sed_cmd->beg_line == 0 && sed_cmd->end_line == 0 &&
652 sed_cmds[i].beg_match == NULL && 670 sed_cmd->beg_match == NULL &&
653 sed_cmds[i].end_match == NULL) || 671 sed_cmd->end_match == NULL) ||
654 /* this line number is the first address we're looking for */ 672 /* this line number is the first address we're looking for */
655 (sed_cmds[i].beg_line && (sed_cmds[i].beg_line == linenum)) || 673 (sed_cmd->beg_line && (sed_cmd->beg_line == linenum)) ||
656 /* this line matches our first address regex */ 674 /* this line matches our first address regex */
657 (sed_cmds[i].beg_match && (regexec(sed_cmds[i].beg_match, line, 0, NULL, 0) == 0)) || 675 (sed_cmd->beg_match && (regexec(sed_cmd->beg_match, line, 0, NULL, 0) == 0)) ||
658 /* we are currently within the beginning & ending address range */ 676 /* we are currently within the beginning & ending address range */
659 still_in_range 677 still_in_range
660 ) { 678 ) {
@@ -662,7 +680,7 @@ static void process_file(FILE *file)
662 /* 680 /*
663 * actual sedding 681 * actual sedding
664 */ 682 */
665 switch (sed_cmds[i].cmd) { 683 switch (sed_cmd->cmd) {
666 684
667 case 'p': 685 case 'p':
668 puts(line); 686 puts(line);
@@ -693,17 +711,17 @@ static void process_file(FILE *file)
693 /* if the user specified that they didn't want anything printed (i.e., a -n 711 /* if the user specified that they didn't want anything printed (i.e., a -n
694 * flag and no 'p' flag after the s///), then there's really no point doing 712 * flag and no 'p' flag after the s///), then there's really no point doing
695 * anything here. */ 713 * anything here. */
696 if (be_quiet && !sed_cmds[i].sub_p) 714 if (be_quiet && !sed_cmd->sub_p)
697 break; 715 break;
698 716
699 /* we print the line once, unless we were told to be quiet */ 717 /* we print the line once, unless we were told to be quiet */
700 if (!be_quiet) 718 if (!be_quiet)
701 altered |= do_subst_command(&sed_cmds[i], &line); 719 altered |= do_subst_command(sed_cmd, &line);
702 720
703 /* we also print the line if we were given the 'p' flag 721 /* we also print the line if we were given the 'p' flag
704 * (this is quite possibly the second printing) */ 722 * (this is quite possibly the second printing) */
705 if (sed_cmds[i].sub_p) 723 if (sed_cmd->sub_p)
706 altered |= do_subst_command(&sed_cmds[i], &line); 724 altered |= do_subst_command(sed_cmd, &line);
707 if (altered && (i+1 >= ncmds || sed_cmds[i+1].cmd != 's')) 725 if (altered && (i+1 >= ncmds || sed_cmds[i+1].cmd != 's'))
708 puts(line); 726 puts(line);
709 727
@@ -711,27 +729,24 @@ static void process_file(FILE *file)
711 729
712 case 'a': 730 case 'a':
713 puts(line); 731 puts(line);
714 fputs(sed_cmds[i].editline, stdout); 732 fputs(sed_cmd->editline, stdout);
715 altered++; 733 altered++;
716 break; 734 break;
717 735
718 case 'i': 736 case 'i':
719 fputs(sed_cmds[i].editline, stdout); 737 fputs(sed_cmd->editline, stdout);
720 break; 738 break;
721 739
722 case 'c': 740 case 'c':
723 /* single-address case */ 741 /* single-address case */
724 if (sed_cmds[i].end_match == NULL && sed_cmds[i].end_line == 0) { 742 if ((sed_cmd->end_match == NULL && sed_cmd->end_line == 0)
725 fputs(sed_cmds[i].editline, stdout);
726 }
727 /* multi-address case */ 743 /* multi-address case */
728 else { 744 /* - matching text */
729 /* matching text */ 745 || (sed_cmd->end_match && (regexec(sed_cmd->end_match, line, 0, NULL, 0) == 0))
730 if (sed_cmds[i].end_match && (regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)) 746 /* - matching line numbers */
731 fputs(sed_cmds[i].editline, stdout); 747 || (sed_cmd->end_line > 0 && sed_cmd->end_line == linenum))
732 /* matching line numbers */ 748 {
733 if (sed_cmds[i].end_line > 0 && sed_cmds[i].end_line == linenum) 749 fputs(sed_cmd->editline, stdout);
734 fputs(sed_cmds[i].editline, stdout);
735 } 750 }
736 altered++; 751 altered++;
737 752
@@ -740,7 +755,7 @@ static void process_file(FILE *file)
740 case 'r': { 755 case 'r': {
741 FILE *outfile; 756 FILE *outfile;
742 puts(line); 757 puts(line);
743 outfile = fopen(sed_cmds[i].filename, "r"); 758 outfile = fopen(sed_cmd->filename, "r");
744 if (outfile) 759 if (outfile)
745 print_file(outfile); 760 print_file(outfile);
746 /* else if we couldn't open the output file, 761 /* else if we couldn't open the output file,
@@ -755,14 +770,14 @@ static void process_file(FILE *file)
755 */ 770 */
756 if ( 771 if (
757 /* this is a single-address command or... */ 772 /* this is a single-address command or... */
758 (sed_cmds[i].end_line == 0 && sed_cmds[i].end_match == NULL) || ( 773 (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) || (
759 /* we were in the middle of our address range (this 774 /* we were in the middle of our address range (this
760 * isn't the first time through) and.. */ 775 * isn't the first time through) and.. */
761 (still_in_range == 1) && ( 776 (still_in_range == 1) && (
762 /* this line number is the last address we're looking for or... */ 777 /* this line number is the last address we're looking for or... */
763 (sed_cmds[i].end_line && (sed_cmds[i].end_line == linenum)) || 778 (sed_cmd->end_line && (sed_cmd->end_line == linenum)) ||
764 /* this line matches our last address regex */ 779 /* this line matches our last address regex */
765 (sed_cmds[i].end_match && (regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)) 780 (sed_cmd->end_match && (regexec(sed_cmd->end_match, line, 0, NULL, 0) == 0))
766 ) 781 )
767 ) 782 )
768 ) { 783 ) {
diff --git a/tests/testcases b/tests/testcases
index 2c28bf389..37e741260 100644
--- a/tests/testcases
+++ b/tests/testcases
@@ -156,12 +156,12 @@ free
156# getopt 156# getopt
157 157
158# grep 158# grep
159grep -l strdup ../*.c 159grep -l strdup ../*utils/*.c
160grep -c strdup ../*.c 160grep -c strdup ../*utils/*.c
161grep -lc strdup ../*.c 161grep -lc strdup ../*utils/*.c
162grep -cv strdup ../*.c 162grep -cv strdup ../*utils/*.c
163grep -i null ../grep.c 163grep -i null ../findutils/grep.c
164grep -e strdup -e regcomp -e atexit ../grep.c 164grep -e strdup -e regcomp -e atexit ../findutils/grep.c
165 165
166# gunzip 166# gunzip
167 167
@@ -304,8 +304,8 @@ echo -e "foo\\n\\nbar" | sed -ne '/^$/p'
304sed -e '/test$/d' testcases 304sed -e '/test$/d' testcases
305sed -e '/^echo/d' testcases 305sed -e '/^echo/d' testcases
306sed -e '/test/s/dangerous/PELIGROSO/' testcases 306sed -e '/test/s/dangerous/PELIGROSO/' testcases
307sed -ne '1,/getopt/p' ../pwd.c 307sed -ne '1,/getopt/p' ../shellutils/pwd.c
308sed -e '/getopt/r ../pwd.c' ../sed.c 308sed -e '/getopt/r ../shellutils/pwd.c' ../editors/sed.c
309 309
310 310
311# setkeycodes 311# setkeycodes
diff --git a/testsuite/sed/sed-aic-commands b/testsuite/sed/sed-aic-commands
new file mode 100644
index 000000000..b41c14ab8
--- /dev/null
+++ b/testsuite/sed/sed-aic-commands
@@ -0,0 +1,134 @@
1cat - >input <<EOF
22i\\
3before 2
45c\\
5Change 5
610a\\
7After 10
822i\\
9before 22\\
10Continued
1125c\\
12Change 25\\
13Continued
1420a\\
15After 20\\
16Continued
17 32i\\
18before 32\\
19Continued 1\\
20Continued 2\\
21Continued 3
22 35c\\
23Change 35\\
24Continued 1\\
25Continued 2\\
26Continued 3
27 30a\\
28After 30\\
29Continued 1\\
30Continued 2\\
31Continued 3
32EOF
33busybox sed -f input >output <<EOF
34 1 y
35 2 y
36 3 y
37 4 y
38 5 y
39 6 y
40 7 y
41 8 y
42 9 y
43 10 y
44 11 y
45 12 y
46 13 y
47 14 y
48 15 y
49 16 y
50 17 y
51 18 y
52 19 y
53 20 y
54 21 y
55 22 y
56 23 y
57 24 y
58 25 y
59 26 y
60 27 y
61 28 y
62 29 y
63 30 y
64 31 y
65 32 y
66 33 y
67 34 y
68 35 y
69 36 y
70 37 y
71 38 y
72 39 y
73 40 y
74EOF
75cmp -s output - <<EOF
76 1 y
77before 2
78 2 y
79 3 y
80 4 y
81Change 5
82 6 y
83 7 y
84 8 y
85 9 y
86 10 y
87After 10
88 11 y
89 12 y
90 13 y
91 14 y
92 15 y
93 16 y
94 17 y
95 18 y
96 19 y
97 20 y
98After 20
99Continued
100 21 y
101before 22
102Continued
103 22 y
104 23 y
105 24 y
106Change 25
107Continued
108 26 y
109 27 y
110 28 y
111 29 y
112 30 y
113After 30
114Continued 1
115Continued 2
116Continued 3
117 31 y
118before 32
119Continued 1
120Continued 2
121Continued 3
122 32 y
123 33 y
124 34 y
125Change 35
126Continued 1
127Continued 2
128Continued 3
129 36 y
130 37 y
131 38 y
132 39 y
133 40 y
134EOF