diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-03-26 20:48:46 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-03-26 20:48:46 +0000 |
commit | 839a580583d0b255b6b1a9bbb7a75fe836a81366 (patch) | |
tree | c20724d49df25c91c15caee6db0ab3a5b036620c | |
parent | 5def6fd8a9a367db78430fcd475b01015d723e35 (diff) | |
download | busybox-w32-839a580583d0b255b6b1a9bbb7a75fe836a81366.tar.gz busybox-w32-839a580583d0b255b6b1a9bbb7a75fe836a81366.tar.bz2 busybox-w32-839a580583d0b255b6b1a9bbb7a75fe836a81366.zip |
sed: a communal variable managed to slip past 'size'
('size' happily displays 0 bytes in data and bss,
but in reality sed.o used 180 bytes of it). Oh well.
function old new delta
pipe_putc 67 76 +9
sed_main 627 633 +6
get_next_line 161 166 +5
bbg 180 - -180
(add/remove: 0/1 grow/shrink: 3/0 up/down: 20/-180) Total: -160 bytes
sed: also make sed -i failure message less cryptic
git-svn-id: svn://busybox.net/trunk/busybox@18251 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | docs/keep_data_small.txt | 2 | ||||
-rw-r--r-- | editors/sed.c | 192 |
2 files changed, 100 insertions, 94 deletions
diff --git a/docs/keep_data_small.txt b/docs/keep_data_small.txt index 3c3d27396..55f4fc95a 100644 --- a/docs/keep_data_small.txt +++ b/docs/keep_data_small.txt | |||
@@ -112,7 +112,7 @@ Be careful, though, and use it only if globals fit into bb_common_bufsiz1. | |||
112 | Since bb_common_bufsiz1 is BUFSIZ + 1 bytes long and BUFSIZ can change | 112 | Since bb_common_bufsiz1 is BUFSIZ + 1 bytes long and BUFSIZ can change |
113 | from one libc to another, you have to add compile-time check for it: | 113 | from one libc to another, you have to add compile-time check for it: |
114 | 114 | ||
115 | if(sizeof(struct globals) > sizeof(bb_common_bufsiz1)) | 115 | if (sizeof(struct globals) > sizeof(bb_common_bufsiz1)) |
116 | BUG_<applet>_globals_too_big(); | 116 | BUG_<applet>_globals_too_big(); |
117 | 117 | ||
118 | 118 | ||
diff --git a/editors/sed.c b/editors/sed.c index f7f22f750..e4d753d72 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -21,7 +21,7 @@ | |||
21 | add_cmd() is called on each line of sed command text (from a file or from | 21 | add_cmd() is called on each line of sed command text (from a file or from |
22 | the command line). It calls get_address() and parse_cmd_args(). The | 22 | the command line). It calls get_address() and parse_cmd_args(). The |
23 | resulting sed_cmd_t structures are appended to a linked list | 23 | resulting sed_cmd_t structures are appended to a linked list |
24 | (bbg.sed_cmd_head/bbg.sed_cmd_tail). | 24 | (G.sed_cmd_head/G.sed_cmd_tail). |
25 | 25 | ||
26 | add_input_file() adds a FILE * to the list of input files. We need to | 26 | add_input_file() adds a FILE * to the list of input files. We need to |
27 | know all input sources ahead of time to find the last line for the $ match. | 27 | know all input sources ahead of time to find the last line for the $ match. |
@@ -91,7 +91,7 @@ typedef struct sed_cmd_s { | |||
91 | 91 | ||
92 | static const char semicolon_whitespace[] = "; \n\r\t\v"; | 92 | static const char semicolon_whitespace[] = "; \n\r\t\v"; |
93 | 93 | ||
94 | struct sed_globals { | 94 | struct globals { |
95 | /* options */ | 95 | /* options */ |
96 | int be_quiet, regex_type; | 96 | int be_quiet, regex_type; |
97 | FILE *nonstdout; | 97 | FILE *nonstdout; |
@@ -117,15 +117,16 @@ struct sed_globals { | |||
117 | int idx; /* Space used */ | 117 | int idx; /* Space used */ |
118 | int len; /* Space allocated */ | 118 | int len; /* Space allocated */ |
119 | } pipeline; | 119 | } pipeline; |
120 | } bbg; | 120 | }; |
121 | 121 | ||
122 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
122 | 123 | ||
123 | #if ENABLE_FEATURE_CLEAN_UP | 124 | #if ENABLE_FEATURE_CLEAN_UP |
124 | static void sed_free_and_close_stuff(void) | 125 | static void sed_free_and_close_stuff(void) |
125 | { | 126 | { |
126 | sed_cmd_t *sed_cmd = bbg.sed_cmd_head.next; | 127 | sed_cmd_t *sed_cmd = G.sed_cmd_head.next; |
127 | 128 | ||
128 | llist_free(bbg.append_head, free); | 129 | llist_free(G.append_head, free); |
129 | 130 | ||
130 | while (sed_cmd) { | 131 | while (sed_cmd) { |
131 | sed_cmd_t *sed_cmd_next = sed_cmd->next; | 132 | sed_cmd_t *sed_cmd_next = sed_cmd->next; |
@@ -150,10 +151,10 @@ static void sed_free_and_close_stuff(void) | |||
150 | sed_cmd = sed_cmd_next; | 151 | sed_cmd = sed_cmd_next; |
151 | } | 152 | } |
152 | 153 | ||
153 | if (bbg.hold_space) free(bbg.hold_space); | 154 | if (G.hold_space) free(G.hold_space); |
154 | 155 | ||
155 | while (bbg.current_input_file < bbg.input_file_count) | 156 | while (G.current_input_file < G.input_file_count) |
156 | fclose(bbg.input_file_list[bbg.current_input_file++]); | 157 | fclose(G.input_file_list[G.current_input_file++]); |
157 | } | 158 | } |
158 | #else | 159 | #else |
159 | void sed_free_and_close_stuff(void); | 160 | void sed_free_and_close_stuff(void); |
@@ -163,7 +164,7 @@ void sed_free_and_close_stuff(void); | |||
163 | 164 | ||
164 | static void cleanup_outname(void) | 165 | static void cleanup_outname(void) |
165 | { | 166 | { |
166 | if (bbg.outname) unlink(bbg.outname); | 167 | if (G.outname) unlink(G.outname); |
167 | } | 168 | } |
168 | 169 | ||
169 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ | 170 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ |
@@ -282,7 +283,7 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex) | |||
282 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); | 283 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); |
283 | temp = copy_parsing_escapes(pos, next); | 284 | temp = copy_parsing_escapes(pos, next); |
284 | *regex = xmalloc(sizeof(regex_t)); | 285 | *regex = xmalloc(sizeof(regex_t)); |
285 | xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE); | 286 | xregcomp(*regex, temp, G.regex_type|REG_NEWLINE); |
286 | free(temp); | 287 | free(temp); |
287 | /* Move position to next character after last delimiter */ | 288 | /* Move position to next character after last delimiter */ |
288 | pos += (next+1); | 289 | pos += (next+1); |
@@ -316,7 +317,7 @@ static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr, char **ret | |||
316 | 317 | ||
317 | static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) | 318 | static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) |
318 | { | 319 | { |
319 | int cflags = bbg.regex_type; | 320 | int cflags = G.regex_type; |
320 | char *match; | 321 | char *match; |
321 | int idx; | 322 | int idx; |
322 | 323 | ||
@@ -478,18 +479,18 @@ static void add_cmd(const char *cmdstr) | |||
478 | int temp; | 479 | int temp; |
479 | 480 | ||
480 | /* Append this line to any unfinished line from last time. */ | 481 | /* Append this line to any unfinished line from last time. */ |
481 | if (bbg.add_cmd_line) { | 482 | if (G.add_cmd_line) { |
482 | char *tp = xasprintf("%s\n%s", bbg.add_cmd_line, cmdstr); | 483 | char *tp = xasprintf("%s\n%s", G.add_cmd_line, cmdstr); |
483 | free(bbg.add_cmd_line); | 484 | free(G.add_cmd_line); |
484 | bbg.add_cmd_line = tp; | 485 | G.add_cmd_line = tp; |
485 | } | 486 | } |
486 | 487 | ||
487 | /* If this line ends with backslash, request next line. */ | 488 | /* If this line ends with backslash, request next line. */ |
488 | temp = strlen(cmdstr); | 489 | temp = strlen(cmdstr); |
489 | if (temp && cmdstr[temp-1] == '\\') { | 490 | if (temp && cmdstr[temp-1] == '\\') { |
490 | if (!bbg.add_cmd_line) | 491 | if (!G.add_cmd_line) |
491 | bbg.add_cmd_line = xstrdup(cmdstr); | 492 | G.add_cmd_line = xstrdup(cmdstr); |
492 | bbg.add_cmd_line[temp-1] = 0; | 493 | G.add_cmd_line[temp-1] = 0; |
493 | return; | 494 | return; |
494 | } | 495 | } |
495 | 496 | ||
@@ -505,7 +506,7 @@ static void add_cmd(const char *cmdstr) | |||
505 | if (*cmdstr == '#') { | 506 | if (*cmdstr == '#') { |
506 | /* "#n" is the same as using -n on the command line */ | 507 | /* "#n" is the same as using -n on the command line */ |
507 | if (cmdstr[1] == 'n') | 508 | if (cmdstr[1] == 'n') |
508 | bbg.be_quiet++; | 509 | G.be_quiet++; |
509 | cmdstr = strpbrk(cmdstr, "\n\r"); | 510 | cmdstr = strpbrk(cmdstr, "\n\r"); |
510 | if (!cmdstr) break; | 511 | if (!cmdstr) break; |
511 | continue; | 512 | continue; |
@@ -552,13 +553,13 @@ static void add_cmd(const char *cmdstr) | |||
552 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); | 553 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
553 | 554 | ||
554 | /* Add the command to the command array */ | 555 | /* Add the command to the command array */ |
555 | bbg.sed_cmd_tail->next = sed_cmd; | 556 | G.sed_cmd_tail->next = sed_cmd; |
556 | bbg.sed_cmd_tail = bbg.sed_cmd_tail->next; | 557 | G.sed_cmd_tail = G.sed_cmd_tail->next; |
557 | } | 558 | } |
558 | 559 | ||
559 | /* If we glued multiple lines together, free the memory. */ | 560 | /* If we glued multiple lines together, free the memory. */ |
560 | free(bbg.add_cmd_line); | 561 | free(G.add_cmd_line); |
561 | bbg.add_cmd_line = NULL; | 562 | G.add_cmd_line = NULL; |
562 | } | 563 | } |
563 | 564 | ||
564 | /* Append to a string, reallocating memory as necessary. */ | 565 | /* Append to a string, reallocating memory as necessary. */ |
@@ -567,12 +568,12 @@ static void add_cmd(const char *cmdstr) | |||
567 | 568 | ||
568 | static void pipe_putc(char c) | 569 | static void pipe_putc(char c) |
569 | { | 570 | { |
570 | if (bbg.pipeline.idx == bbg.pipeline.len) { | 571 | if (G.pipeline.idx == G.pipeline.len) { |
571 | bbg.pipeline.buf = xrealloc(bbg.pipeline.buf, | 572 | G.pipeline.buf = xrealloc(G.pipeline.buf, |
572 | bbg.pipeline.len + PIPE_GROW); | 573 | G.pipeline.len + PIPE_GROW); |
573 | bbg.pipeline.len += PIPE_GROW; | 574 | G.pipeline.len += PIPE_GROW; |
574 | } | 575 | } |
575 | bbg.pipeline.buf[bbg.pipeline.idx++] = c; | 576 | G.pipeline.buf[G.pipeline.idx++] = c; |
576 | } | 577 | } |
577 | 578 | ||
578 | static void do_subst_w_backrefs(char *line, char *replace) | 579 | static void do_subst_w_backrefs(char *line, char *replace) |
@@ -585,10 +586,10 @@ static void do_subst_w_backrefs(char *line, char *replace) | |||
585 | if (replace[i] == '\\') { | 586 | if (replace[i] == '\\') { |
586 | unsigned backref = replace[++i] - '0'; | 587 | unsigned backref = replace[++i] - '0'; |
587 | if (backref <= 9) { | 588 | if (backref <= 9) { |
588 | /* print out the text held in bbg.regmatch[backref] */ | 589 | /* print out the text held in G.regmatch[backref] */ |
589 | if (bbg.regmatch[backref].rm_so != -1) { | 590 | if (G.regmatch[backref].rm_so != -1) { |
590 | j = bbg.regmatch[backref].rm_so; | 591 | j = G.regmatch[backref].rm_so; |
591 | while (j < bbg.regmatch[backref].rm_eo) | 592 | while (j < G.regmatch[backref].rm_eo) |
592 | pipe_putc(line[j++]); | 593 | pipe_putc(line[j++]); |
593 | } | 594 | } |
594 | continue; | 595 | continue; |
@@ -602,8 +603,8 @@ static void do_subst_w_backrefs(char *line, char *replace) | |||
602 | } | 603 | } |
603 | /* if we find an unescaped '&' print out the whole matched text. */ | 604 | /* if we find an unescaped '&' print out the whole matched text. */ |
604 | if (replace[i] == '&') { | 605 | if (replace[i] == '&') { |
605 | j = bbg.regmatch[0].rm_so; | 606 | j = G.regmatch[0].rm_so; |
606 | while (j < bbg.regmatch[0].rm_eo) | 607 | while (j < G.regmatch[0].rm_eo) |
607 | pipe_putc(line[j++]); | 608 | pipe_putc(line[j++]); |
608 | continue; | 609 | continue; |
609 | } | 610 | } |
@@ -621,20 +622,20 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
621 | 622 | ||
622 | /* Handle empty regex. */ | 623 | /* Handle empty regex. */ |
623 | if (sed_cmd->sub_match == NULL) { | 624 | if (sed_cmd->sub_match == NULL) { |
624 | current_regex = bbg.previous_regex_ptr; | 625 | current_regex = G.previous_regex_ptr; |
625 | if (!current_regex) | 626 | if (!current_regex) |
626 | bb_error_msg_and_die("no previous regexp"); | 627 | bb_error_msg_and_die("no previous regexp"); |
627 | } else | 628 | } else |
628 | bbg.previous_regex_ptr = current_regex = sed_cmd->sub_match; | 629 | G.previous_regex_ptr = current_regex = sed_cmd->sub_match; |
629 | 630 | ||
630 | /* Find the first match */ | 631 | /* Find the first match */ |
631 | if (REG_NOMATCH == regexec(current_regex, oldline, 10, bbg.regmatch, 0)) | 632 | if (REG_NOMATCH == regexec(current_regex, oldline, 10, G.regmatch, 0)) |
632 | return 0; | 633 | return 0; |
633 | 634 | ||
634 | /* Initialize temporary output buffer. */ | 635 | /* Initialize temporary output buffer. */ |
635 | bbg.pipeline.buf = xmalloc(PIPE_GROW); | 636 | G.pipeline.buf = xmalloc(PIPE_GROW); |
636 | bbg.pipeline.len = PIPE_GROW; | 637 | G.pipeline.len = PIPE_GROW; |
637 | bbg.pipeline.idx = 0; | 638 | G.pipeline.idx = 0; |
638 | 639 | ||
639 | /* Now loop through, substituting for matches */ | 640 | /* Now loop through, substituting for matches */ |
640 | do { | 641 | do { |
@@ -644,7 +645,7 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
644 | echo " a.b" | busybox sed 's [^ .]* x g' | 645 | echo " a.b" | busybox sed 's [^ .]* x g' |
645 | The match_count check is so not to break | 646 | The match_count check is so not to break |
646 | echo "hi" | busybox sed 's/^/!/g' */ | 647 | echo "hi" | busybox sed 's/^/!/g' */ |
647 | if (!bbg.regmatch[0].rm_so && !bbg.regmatch[0].rm_eo && match_count) { | 648 | if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { |
648 | pipe_putc(*oldline++); | 649 | pipe_putc(*oldline++); |
649 | continue; | 650 | continue; |
650 | } | 651 | } |
@@ -654,26 +655,26 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
654 | /* If we aren't interested in this match, output old line to | 655 | /* If we aren't interested in this match, output old line to |
655 | end of match and continue */ | 656 | end of match and continue */ |
656 | if (sed_cmd->which_match && sed_cmd->which_match != match_count) { | 657 | if (sed_cmd->which_match && sed_cmd->which_match != match_count) { |
657 | for (i = 0; i < bbg.regmatch[0].rm_eo; i++) | 658 | for (i = 0; i < G.regmatch[0].rm_eo; i++) |
658 | pipe_putc(*oldline++); | 659 | pipe_putc(*oldline++); |
659 | continue; | 660 | continue; |
660 | } | 661 | } |
661 | 662 | ||
662 | /* print everything before the match */ | 663 | /* print everything before the match */ |
663 | for (i = 0; i < bbg.regmatch[0].rm_so; i++) | 664 | for (i = 0; i < G.regmatch[0].rm_so; i++) |
664 | pipe_putc(oldline[i]); | 665 | pipe_putc(oldline[i]); |
665 | 666 | ||
666 | /* then print the substitution string */ | 667 | /* then print the substitution string */ |
667 | do_subst_w_backrefs(oldline, sed_cmd->string); | 668 | do_subst_w_backrefs(oldline, sed_cmd->string); |
668 | 669 | ||
669 | /* advance past the match */ | 670 | /* advance past the match */ |
670 | oldline += bbg.regmatch[0].rm_eo; | 671 | oldline += G.regmatch[0].rm_eo; |
671 | /* flag that something has changed */ | 672 | /* flag that something has changed */ |
672 | altered++; | 673 | altered++; |
673 | 674 | ||
674 | /* if we're not doing this globally, get out now */ | 675 | /* if we're not doing this globally, get out now */ |
675 | if (sed_cmd->which_match) break; | 676 | if (sed_cmd->which_match) break; |
676 | } while (*oldline && (regexec(current_regex, oldline, 10, bbg.regmatch, 0) != REG_NOMATCH)); | 677 | } while (*oldline && (regexec(current_regex, oldline, 10, G.regmatch, 0) != REG_NOMATCH)); |
677 | 678 | ||
678 | /* Copy rest of string into output pipeline */ | 679 | /* Copy rest of string into output pipeline */ |
679 | 680 | ||
@@ -682,7 +683,7 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
682 | pipe_putc(0); | 683 | pipe_putc(0); |
683 | 684 | ||
684 | free(*line); | 685 | free(*line); |
685 | *line = bbg.pipeline.buf; | 686 | *line = G.pipeline.buf; |
686 | return altered; | 687 | return altered; |
687 | } | 688 | } |
688 | 689 | ||
@@ -691,7 +692,7 @@ static sed_cmd_t *branch_to(char *label) | |||
691 | { | 692 | { |
692 | sed_cmd_t *sed_cmd; | 693 | sed_cmd_t *sed_cmd; |
693 | 694 | ||
694 | for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | 695 | for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
695 | if (sed_cmd->cmd == ':' && sed_cmd->string && !strcmp(sed_cmd->string, label)) { | 696 | if (sed_cmd->cmd == ':' && sed_cmd->string && !strcmp(sed_cmd->string, label)) { |
696 | return sed_cmd; | 697 | return sed_cmd; |
697 | } | 698 | } |
@@ -701,7 +702,7 @@ static sed_cmd_t *branch_to(char *label) | |||
701 | 702 | ||
702 | static void append(char *s) | 703 | static void append(char *s) |
703 | { | 704 | { |
704 | llist_add_to_end(&bbg.append_head, xstrdup(s)); | 705 | llist_add_to_end(&G.append_head, xstrdup(s)); |
705 | } | 706 | } |
706 | 707 | ||
707 | static void flush_append(void) | 708 | static void flush_append(void) |
@@ -709,20 +710,20 @@ static void flush_append(void) | |||
709 | char *data; | 710 | char *data; |
710 | 711 | ||
711 | /* Output appended lines. */ | 712 | /* Output appended lines. */ |
712 | while ((data = (char *)llist_pop(&bbg.append_head))) { | 713 | while ((data = (char *)llist_pop(&G.append_head))) { |
713 | fprintf(bbg.nonstdout, "%s\n", data); | 714 | fprintf(G.nonstdout, "%s\n", data); |
714 | free(data); | 715 | free(data); |
715 | } | 716 | } |
716 | } | 717 | } |
717 | 718 | ||
718 | static void add_input_file(FILE *file) | 719 | static void add_input_file(FILE *file) |
719 | { | 720 | { |
720 | bbg.input_file_list = xrealloc(bbg.input_file_list, | 721 | G.input_file_list = xrealloc(G.input_file_list, |
721 | (bbg.input_file_count + 1) * sizeof(FILE *)); | 722 | (G.input_file_count + 1) * sizeof(FILE *)); |
722 | bbg.input_file_list[bbg.input_file_count++] = file; | 723 | G.input_file_list[G.input_file_count++] = file; |
723 | } | 724 | } |
724 | 725 | ||
725 | /* Get next line of input from bbg.input_file_list, flushing append buffer and | 726 | /* Get next line of input from G.input_file_list, flushing append buffer and |
726 | * noting if we ran out of files without a newline on the last line we read. | 727 | * noting if we ran out of files without a newline on the last line we read. |
727 | */ | 728 | */ |
728 | enum { | 729 | enum { |
@@ -740,8 +741,8 @@ static char *get_next_line(char *gets_char) | |||
740 | /* will be returned if last line in the file | 741 | /* will be returned if last line in the file |
741 | * doesn't end with either '\n' or '\0' */ | 742 | * doesn't end with either '\n' or '\0' */ |
742 | gc = NO_EOL_CHAR; | 743 | gc = NO_EOL_CHAR; |
743 | while (bbg.current_input_file < bbg.input_file_count) { | 744 | while (G.current_input_file < G.input_file_count) { |
744 | FILE *fp = bbg.input_file_list[bbg.current_input_file]; | 745 | FILE *fp = G.input_file_list[G.current_input_file]; |
745 | /* Read line up to a newline or NUL byte, inclusive, | 746 | /* Read line up to a newline or NUL byte, inclusive, |
746 | * return malloc'ed char[]. length of the chunk read | 747 | * return malloc'ed char[]. length of the chunk read |
747 | * is stored in len. NULL if EOF/error */ | 748 | * is stored in len. NULL if EOF/error */ |
@@ -773,7 +774,7 @@ static char *get_next_line(char *gets_char) | |||
773 | } | 774 | } |
774 | /* Close this file and advance to next one */ | 775 | /* Close this file and advance to next one */ |
775 | fclose(fp); | 776 | fclose(fp); |
776 | bbg.current_input_file++; | 777 | G.current_input_file++; |
777 | } | 778 | } |
778 | *gets_char = gc; | 779 | *gets_char = gc; |
779 | return temp; | 780 | return temp; |
@@ -827,7 +828,7 @@ static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char l | |||
827 | *last_puts_char = lpc; | 828 | *last_puts_char = lpc; |
828 | } | 829 | } |
829 | 830 | ||
830 | #define sed_puts(s, n) (puts_maybe_newline(s, bbg.nonstdout, &last_puts_char, n)) | 831 | #define sed_puts(s, n) (puts_maybe_newline(s, G.nonstdout, &last_puts_char, n)) |
831 | 832 | ||
832 | /* Process all the lines in all the files */ | 833 | /* Process all the lines in all the files */ |
833 | 834 | ||
@@ -858,7 +859,7 @@ again: | |||
858 | linenum++; | 859 | linenum++; |
859 | restart: | 860 | restart: |
860 | /* for every line, go through all the commands */ | 861 | /* for every line, go through all the commands */ |
861 | for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | 862 | for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
862 | int old_matched, matched; | 863 | int old_matched, matched; |
863 | 864 | ||
864 | old_matched = sed_cmd->in_match; | 865 | old_matched = sed_cmd->in_match; |
@@ -916,7 +917,7 @@ restart: | |||
916 | if (sed_cmd->invert ? !matched : matched) { | 917 | if (sed_cmd->invert ? !matched : matched) { |
917 | /* Update last used regex in case a blank substitute BRE is found */ | 918 | /* Update last used regex in case a blank substitute BRE is found */ |
918 | if (sed_cmd->beg_match) { | 919 | if (sed_cmd->beg_match) { |
919 | bbg.previous_regex_ptr = sed_cmd->beg_match; | 920 | G.previous_regex_ptr = sed_cmd->beg_match; |
920 | } | 921 | } |
921 | 922 | ||
922 | /* actual sedding */ | 923 | /* actual sedding */ |
@@ -924,7 +925,7 @@ restart: | |||
924 | 925 | ||
925 | /* Print line number */ | 926 | /* Print line number */ |
926 | case '=': | 927 | case '=': |
927 | fprintf(bbg.nonstdout, "%d\n", linenum); | 928 | fprintf(G.nonstdout, "%d\n", linenum); |
928 | break; | 929 | break; |
929 | 930 | ||
930 | /* Write the current pattern space up to the first newline */ | 931 | /* Write the current pattern space up to the first newline */ |
@@ -1026,7 +1027,7 @@ restart: | |||
1026 | 1027 | ||
1027 | /* Read next line from input */ | 1028 | /* Read next line from input */ |
1028 | case 'n': | 1029 | case 'n': |
1029 | if (!bbg.be_quiet) | 1030 | if (!G.be_quiet) |
1030 | sed_puts(pattern_space, last_gets_char); | 1031 | sed_puts(pattern_space, last_gets_char); |
1031 | if (next_line) { | 1032 | if (next_line) { |
1032 | free(pattern_space); | 1033 | free(pattern_space); |
@@ -1099,7 +1100,7 @@ restart: | |||
1099 | } | 1100 | } |
1100 | case 'g': /* Replace pattern space with hold space */ | 1101 | case 'g': /* Replace pattern space with hold space */ |
1101 | free(pattern_space); | 1102 | free(pattern_space); |
1102 | pattern_space = xstrdup(bbg.hold_space ? bbg.hold_space : ""); | 1103 | pattern_space = xstrdup(G.hold_space ? G.hold_space : ""); |
1103 | break; | 1104 | break; |
1104 | case 'G': /* Append newline and hold space to pattern space */ | 1105 | case 'G': /* Append newline and hold space to pattern space */ |
1105 | { | 1106 | { |
@@ -1108,49 +1109,49 @@ restart: | |||
1108 | 1109 | ||
1109 | if (pattern_space) | 1110 | if (pattern_space) |
1110 | pattern_space_size += strlen(pattern_space); | 1111 | pattern_space_size += strlen(pattern_space); |
1111 | if (bbg.hold_space) | 1112 | if (G.hold_space) |
1112 | hold_space_size = strlen(bbg.hold_space); | 1113 | hold_space_size = strlen(G.hold_space); |
1113 | pattern_space = xrealloc(pattern_space, | 1114 | pattern_space = xrealloc(pattern_space, |
1114 | pattern_space_size + hold_space_size); | 1115 | pattern_space_size + hold_space_size); |
1115 | if (pattern_space_size == 2) | 1116 | if (pattern_space_size == 2) |
1116 | pattern_space[0] = 0; | 1117 | pattern_space[0] = 0; |
1117 | strcat(pattern_space, "\n"); | 1118 | strcat(pattern_space, "\n"); |
1118 | if (bbg.hold_space) | 1119 | if (G.hold_space) |
1119 | strcat(pattern_space, bbg.hold_space); | 1120 | strcat(pattern_space, G.hold_space); |
1120 | last_gets_char = '\n'; | 1121 | last_gets_char = '\n'; |
1121 | 1122 | ||
1122 | break; | 1123 | break; |
1123 | } | 1124 | } |
1124 | case 'h': /* Replace hold space with pattern space */ | 1125 | case 'h': /* Replace hold space with pattern space */ |
1125 | free(bbg.hold_space); | 1126 | free(G.hold_space); |
1126 | bbg.hold_space = xstrdup(pattern_space); | 1127 | G.hold_space = xstrdup(pattern_space); |
1127 | break; | 1128 | break; |
1128 | case 'H': /* Append newline and pattern space to hold space */ | 1129 | case 'H': /* Append newline and pattern space to hold space */ |
1129 | { | 1130 | { |
1130 | int hold_space_size = 2; | 1131 | int hold_space_size = 2; |
1131 | int pattern_space_size = 0; | 1132 | int pattern_space_size = 0; |
1132 | 1133 | ||
1133 | if (bbg.hold_space) | 1134 | if (G.hold_space) |
1134 | hold_space_size += strlen(bbg.hold_space); | 1135 | hold_space_size += strlen(G.hold_space); |
1135 | if (pattern_space) | 1136 | if (pattern_space) |
1136 | pattern_space_size = strlen(pattern_space); | 1137 | pattern_space_size = strlen(pattern_space); |
1137 | bbg.hold_space = xrealloc(bbg.hold_space, | 1138 | G.hold_space = xrealloc(G.hold_space, |
1138 | hold_space_size + pattern_space_size); | 1139 | hold_space_size + pattern_space_size); |
1139 | 1140 | ||
1140 | if (hold_space_size == 2) | 1141 | if (hold_space_size == 2) |
1141 | *bbg.hold_space = 0; | 1142 | *G.hold_space = 0; |
1142 | strcat(bbg.hold_space, "\n"); | 1143 | strcat(G.hold_space, "\n"); |
1143 | if (pattern_space) | 1144 | if (pattern_space) |
1144 | strcat(bbg.hold_space, pattern_space); | 1145 | strcat(G.hold_space, pattern_space); |
1145 | 1146 | ||
1146 | break; | 1147 | break; |
1147 | } | 1148 | } |
1148 | case 'x': /* Exchange hold and pattern space */ | 1149 | case 'x': /* Exchange hold and pattern space */ |
1149 | { | 1150 | { |
1150 | char *tmp = pattern_space; | 1151 | char *tmp = pattern_space; |
1151 | pattern_space = bbg.hold_space ? : xzalloc(1); | 1152 | pattern_space = G.hold_space ? : xzalloc(1); |
1152 | last_gets_char = '\n'; | 1153 | last_gets_char = '\n'; |
1153 | bbg.hold_space = tmp; | 1154 | G.hold_space = tmp; |
1154 | break; | 1155 | break; |
1155 | } | 1156 | } |
1156 | } | 1157 | } |
@@ -1163,7 +1164,7 @@ restart: | |||
1163 | discard_commands: | 1164 | discard_commands: |
1164 | /* we will print the line unless we were told to be quiet ('-n') | 1165 | /* we will print the line unless we were told to be quiet ('-n') |
1165 | or if the line was suppressed (ala 'd'elete) */ | 1166 | or if the line was suppressed (ala 'd'elete) */ |
1166 | if (!bbg.be_quiet) | 1167 | if (!G.be_quiet) |
1167 | sed_puts(pattern_space, last_gets_char); | 1168 | sed_puts(pattern_space, last_gets_char); |
1168 | 1169 | ||
1169 | /* Delete and such jump here. */ | 1170 | /* Delete and such jump here. */ |
@@ -1232,6 +1233,8 @@ static void add_files_link(llist_t *opt_f) | |||
1232 | free(opt_f); | 1233 | free(opt_f); |
1233 | } | 1234 | } |
1234 | 1235 | ||
1236 | void BUG_sed_globals_too_big(void); | ||
1237 | |||
1235 | int sed_main(int argc, char **argv); | 1238 | int sed_main(int argc, char **argv); |
1236 | int sed_main(int argc, char **argv) | 1239 | int sed_main(int argc, char **argv) |
1237 | { | 1240 | { |
@@ -1242,7 +1245,10 @@ int sed_main(int argc, char **argv) | |||
1242 | llist_t *opt_e, *opt_f; | 1245 | llist_t *opt_e, *opt_f; |
1243 | int status = EXIT_SUCCESS; | 1246 | int status = EXIT_SUCCESS; |
1244 | 1247 | ||
1245 | bbg.sed_cmd_tail = &bbg.sed_cmd_head; | 1248 | if (sizeof(struct globals) > sizeof(bb_common_bufsiz1)) |
1249 | BUG_sed_globals_too_big(); | ||
1250 | |||
1251 | G.sed_cmd_tail = &G.sed_cmd_head; | ||
1246 | 1252 | ||
1247 | /* destroy command strings on exit */ | 1253 | /* destroy command strings on exit */ |
1248 | if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); | 1254 | if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); |
@@ -1258,14 +1264,14 @@ int sed_main(int argc, char **argv) | |||
1258 | opt_complementary = "e::f::" /* can occur multiple times */ | 1264 | opt_complementary = "e::f::" /* can occur multiple times */ |
1259 | "nn"; /* count -n */ | 1265 | "nn"; /* count -n */ |
1260 | opt = getopt32(argc, argv, "irne:f:", &opt_e, &opt_f, | 1266 | opt = getopt32(argc, argv, "irne:f:", &opt_e, &opt_f, |
1261 | &bbg.be_quiet); /* counter for -n */ | 1267 | &G.be_quiet); /* counter for -n */ |
1262 | argc -= optind; | 1268 | argc -= optind; |
1263 | argv += optind; | 1269 | argv += optind; |
1264 | if (opt & OPT_in_place) { // -i | 1270 | if (opt & OPT_in_place) { // -i |
1265 | atexit(cleanup_outname); | 1271 | atexit(cleanup_outname); |
1266 | } | 1272 | } |
1267 | if (opt & 0x2) bbg.regex_type |= REG_EXTENDED; // -r | 1273 | if (opt & 0x2) G.regex_type |= REG_EXTENDED; // -r |
1268 | //if (opt & 0x4) bbg.be_quiet++; // -n | 1274 | //if (opt & 0x4) G.be_quiet++; // -n |
1269 | if (opt & 0x8) { // -e | 1275 | if (opt & 0x8) { // -e |
1270 | /* getopt32 reverses order of arguments, handle it */ | 1276 | /* getopt32 reverses order of arguments, handle it */ |
1271 | add_cmds_link(opt_e); | 1277 | add_cmds_link(opt_e); |
@@ -1285,7 +1291,7 @@ int sed_main(int argc, char **argv) | |||
1285 | add_cmd(""); | 1291 | add_cmd(""); |
1286 | 1292 | ||
1287 | /* By default, we write to stdout */ | 1293 | /* By default, we write to stdout */ |
1288 | bbg.nonstdout = stdout; | 1294 | G.nonstdout = stdout; |
1289 | 1295 | ||
1290 | /* argv[0..(argc-1)] should be names of file to process. If no | 1296 | /* argv[0..(argc-1)] should be names of file to process. If no |
1291 | * files were specified or '-' was specified, take input from stdin. | 1297 | * files were specified or '-' was specified, take input from stdin. |
@@ -1318,11 +1324,11 @@ int sed_main(int argc, char **argv) | |||
1318 | continue; | 1324 | continue; |
1319 | } | 1325 | } |
1320 | 1326 | ||
1321 | bbg.outname = xasprintf("%sXXXXXX", argv[i]); | 1327 | G.outname = xasprintf("%sXXXXXX", argv[i]); |
1322 | nonstdoutfd = mkstemp(bbg.outname); | 1328 | nonstdoutfd = mkstemp(G.outname); |
1323 | if (-1 == nonstdoutfd) | 1329 | if (-1 == nonstdoutfd) |
1324 | bb_error_msg_and_die("no temp file"); | 1330 | bb_perror_msg_and_die("cannot create temp file %s", G.outname); |
1325 | bbg.nonstdout = fdopen(nonstdoutfd, "w"); | 1331 | G.nonstdout = fdopen(nonstdoutfd, "w"); |
1326 | 1332 | ||
1327 | /* Set permissions of output file */ | 1333 | /* Set permissions of output file */ |
1328 | 1334 | ||
@@ -1330,16 +1336,16 @@ int sed_main(int argc, char **argv) | |||
1330 | fchmod(nonstdoutfd, statbuf.st_mode); | 1336 | fchmod(nonstdoutfd, statbuf.st_mode); |
1331 | add_input_file(file); | 1337 | add_input_file(file); |
1332 | process_files(); | 1338 | process_files(); |
1333 | fclose(bbg.nonstdout); | 1339 | fclose(G.nonstdout); |
1334 | 1340 | ||
1335 | bbg.nonstdout = stdout; | 1341 | G.nonstdout = stdout; |
1336 | /* unlink(argv[i]); */ | 1342 | /* unlink(argv[i]); */ |
1337 | // FIXME: error check / message? | 1343 | // FIXME: error check / message? |
1338 | rename(bbg.outname, argv[i]); | 1344 | rename(G.outname, argv[i]); |
1339 | free(bbg.outname); | 1345 | free(G.outname); |
1340 | bbg.outname = 0; | 1346 | G.outname = 0; |
1341 | } | 1347 | } |
1342 | if (bbg.input_file_count > bbg.current_input_file) | 1348 | if (G.input_file_count > G.current_input_file) |
1343 | process_files(); | 1349 | process_files(); |
1344 | } | 1350 | } |
1345 | 1351 | ||