diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-11-10 10:49:42 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-11-10 10:49:42 +0000 |
commit | c52a6b0f1023268f021d04ddf224db5c5dd7b13e (patch) | |
tree | 7d6eb161fcd9d581d1d280503c05e4f2d4517dd0 | |
parent | e5d58c3dcc83c007dce35eaecf0a35c6ae598648 (diff) | |
download | busybox-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.c | 187 | ||||
-rw-r--r-- | tests/testcases | 16 | ||||
-rw-r--r-- | testsuite/sed/sed-aic-commands | 134 |
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 | ||
63 | struct sed_cmd { | 63 | struct 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 | ||
106 | const char * const semicolon_whitespace = "; \n\r\t\v\0"; | ||
107 | |||
107 | #ifdef CONFIG_FEATURE_CLEAN_UP | 108 | #ifdef CONFIG_FEATURE_CLEAN_UP |
108 | static void destroy_cmd_strs() | 109 | static 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 | */ |
145 | static int index_of_next_unescaped_regexp_delim(struct sed_cmd *sed_cmd, const char *str, int idx) | 146 | static 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 | ||
211 | static int parse_subst_cmd(struct sed_cmd *sed_cmd, const char *substr) | 213 | static 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 | ||
292 | static void move_back(char *str, int offset) | ||
293 | { | ||
294 | memmove(str, str + offset, strlen(str + offset) + 1); | ||
295 | } | ||
296 | |||
290 | static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr) | 297 | static 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 | ||
345 | out: | 351 | out: |
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 | ||
402 | static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr) | 407 | static 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 | ||
454 | static void add_cmd_str(const char *cmdstr) | 459 | static 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 | ||
511 | struct 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 | |
520 | void 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 | ||
516 | static void print_subst_w_backrefs(const char *line, const char *replace, | 543 | static 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 | ||
566 | static int do_subst_command(const struct sed_cmd *sed_cmd, char **line) | 586 | static 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 |
159 | grep -l strdup ../*.c | 159 | grep -l strdup ../*utils/*.c |
160 | grep -c strdup ../*.c | 160 | grep -c strdup ../*utils/*.c |
161 | grep -lc strdup ../*.c | 161 | grep -lc strdup ../*utils/*.c |
162 | grep -cv strdup ../*.c | 162 | grep -cv strdup ../*utils/*.c |
163 | grep -i null ../grep.c | 163 | grep -i null ../findutils/grep.c |
164 | grep -e strdup -e regcomp -e atexit ../grep.c | 164 | grep -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' | |||
304 | sed -e '/test$/d' testcases | 304 | sed -e '/test$/d' testcases |
305 | sed -e '/^echo/d' testcases | 305 | sed -e '/^echo/d' testcases |
306 | sed -e '/test/s/dangerous/PELIGROSO/' testcases | 306 | sed -e '/test/s/dangerous/PELIGROSO/' testcases |
307 | sed -ne '1,/getopt/p' ../pwd.c | 307 | sed -ne '1,/getopt/p' ../shellutils/pwd.c |
308 | sed -e '/getopt/r ../pwd.c' ../sed.c | 308 | sed -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 @@ | |||
1 | cat - >input <<EOF | ||
2 | 2i\\ | ||
3 | before 2 | ||
4 | 5c\\ | ||
5 | Change 5 | ||
6 | 10a\\ | ||
7 | After 10 | ||
8 | 22i\\ | ||
9 | before 22\\ | ||
10 | Continued | ||
11 | 25c\\ | ||
12 | Change 25\\ | ||
13 | Continued | ||
14 | 20a\\ | ||
15 | After 20\\ | ||
16 | Continued | ||
17 | 32i\\ | ||
18 | before 32\\ | ||
19 | Continued 1\\ | ||
20 | Continued 2\\ | ||
21 | Continued 3 | ||
22 | 35c\\ | ||
23 | Change 35\\ | ||
24 | Continued 1\\ | ||
25 | Continued 2\\ | ||
26 | Continued 3 | ||
27 | 30a\\ | ||
28 | After 30\\ | ||
29 | Continued 1\\ | ||
30 | Continued 2\\ | ||
31 | Continued 3 | ||
32 | EOF | ||
33 | busybox 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 | ||
74 | EOF | ||
75 | cmp -s output - <<EOF | ||
76 | 1 y | ||
77 | before 2 | ||
78 | 2 y | ||
79 | 3 y | ||
80 | 4 y | ||
81 | Change 5 | ||
82 | 6 y | ||
83 | 7 y | ||
84 | 8 y | ||
85 | 9 y | ||
86 | 10 y | ||
87 | After 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 | ||
98 | After 20 | ||
99 | Continued | ||
100 | 21 y | ||
101 | before 22 | ||
102 | Continued | ||
103 | 22 y | ||
104 | 23 y | ||
105 | 24 y | ||
106 | Change 25 | ||
107 | Continued | ||
108 | 26 y | ||
109 | 27 y | ||
110 | 28 y | ||
111 | 29 y | ||
112 | 30 y | ||
113 | After 30 | ||
114 | Continued 1 | ||
115 | Continued 2 | ||
116 | Continued 3 | ||
117 | 31 y | ||
118 | before 32 | ||
119 | Continued 1 | ||
120 | Continued 2 | ||
121 | Continued 3 | ||
122 | 32 y | ||
123 | 33 y | ||
124 | 34 y | ||
125 | Change 35 | ||
126 | Continued 1 | ||
127 | Continued 2 | ||
128 | Continued 3 | ||
129 | 36 y | ||
130 | 37 y | ||
131 | 38 y | ||
132 | 39 y | ||
133 | 40 y | ||
134 | EOF | ||