aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-03-26 20:48:46 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-03-26 20:48:46 +0000
commit839a580583d0b255b6b1a9bbb7a75fe836a81366 (patch)
treec20724d49df25c91c15caee6db0ab3a5b036620c
parent5def6fd8a9a367db78430fcd475b01015d723e35 (diff)
downloadbusybox-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.txt2
-rw-r--r--editors/sed.c192
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.
112Since bb_common_bufsiz1 is BUFSIZ + 1 bytes long and BUFSIZ can change 112Since bb_common_bufsiz1 is BUFSIZ + 1 bytes long and BUFSIZ can change
113from one libc to another, you have to add compile-time check for it: 113from one libc to another, you have to add compile-time check for it:
114 114
115if(sizeof(struct globals) > sizeof(bb_common_bufsiz1)) 115if (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
92static const char semicolon_whitespace[] = "; \n\r\t\v"; 92static const char semicolon_whitespace[] = "; \n\r\t\v";
93 93
94struct sed_globals { 94struct 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
124static void sed_free_and_close_stuff(void) 125static 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
159void sed_free_and_close_stuff(void); 160void sed_free_and_close_stuff(void);
@@ -163,7 +164,7 @@ void sed_free_and_close_stuff(void);
163 164
164static void cleanup_outname(void) 165static 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
317static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) 318static 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
568static void pipe_putc(char c) 569static 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
578static void do_subst_w_backrefs(char *line, char *replace) 579static 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
702static void append(char *s) 703static 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
707static void flush_append(void) 708static 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
718static void add_input_file(FILE *file) 719static 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 */
728enum { 729enum {
@@ -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++;
859restart: 860restart:
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
1236void BUG_sed_globals_too_big(void);
1237
1235int sed_main(int argc, char **argv); 1238int sed_main(int argc, char **argv);
1236int sed_main(int argc, char **argv) 1239int 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