aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlandley <landley@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-05-09 03:53:55 +0000
committerlandley <landley@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-05-09 03:53:55 +0000
commitabc6bec2d1b0bc18d4fb93eeb6f9bf0880735aa3 (patch)
tree523e92ac10be5b5935a5a548de7a8c3a5f9aa215
parent3c1f902d48dacded4e60c0607c7abb0a275390fd (diff)
downloadbusybox-w32-abc6bec2d1b0bc18d4fb93eeb6f9bf0880735aa3.tar.gz
busybox-w32-abc6bec2d1b0bc18d4fb93eeb6f9bf0880735aa3.tar.bz2
busybox-w32-abc6bec2d1b0bc18d4fb93eeb6f9bf0880735aa3.zip
Convert sed's static variables to a single global structure.
git-svn-id: svn://busybox.net/trunk/busybox@15041 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--editors/sed.c253
1 files changed, 130 insertions, 123 deletions
diff --git a/editors/sed.c b/editors/sed.c
index a3b825028..893931153 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 (sed_cmd_head/sed_cmd_tail). 24 (bbg.sed_cmd_head/bbg.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.
@@ -60,13 +60,14 @@
60 60
61#include <stdio.h> 61#include <stdio.h>
62#include <unistd.h> /* for getopt() */ 62#include <unistd.h> /* for getopt() */
63#include <string.h> /* for strdup() */
64#include <errno.h> 63#include <errno.h>
65#include <ctype.h> /* for isspace() */ 64#include <ctype.h> /* for isspace() */
66#include <stdlib.h> 65#include <stdlib.h>
66#include <string.h>
67#include "busybox.h" 67#include "busybox.h"
68#include "xregex.h" 68#include "xregex.h"
69 69
70/* Each sed command turns into one of these structures. */
70typedef struct sed_cmd_s { 71typedef struct sed_cmd_s {
71 /* Ordered by alignment requirements: currently 36 bytes on x86 */ 72 /* Ordered by alignment requirements: currently 36 bytes on x86 */
72 73
@@ -88,43 +89,52 @@ typedef struct sed_cmd_s {
88 unsigned int no_newline:1; /* Last line written by (sw) had no '\n' */ 89 unsigned int no_newline:1; /* Last line written by (sw) had no '\n' */
89 unsigned int sub_p:1; /* (s) print option */ 90 unsigned int sub_p:1; /* (s) print option */
90 91
91
92 /* GENERAL FIELDS */ 92 /* GENERAL FIELDS */
93 char cmd; /* The command char: abcdDgGhHilnNpPqrstwxy:={} */ 93 char cmd; /* The command char: abcdDgGhHilnNpPqrstwxy:={} */
94 struct sed_cmd_s *next; /* Next command (linked list, NULL terminated) */ 94 struct sed_cmd_s *next; /* Next command (linked list, NULL terminated) */
95} sed_cmd_t; 95} sed_cmd_t;
96 96
97/* globals */
98/* options */
99static int be_quiet, in_place, regex_type;
100static FILE *nonstdout;
101static char *outname,*hold_space;
102
103/* List of input files */
104static int input_file_count,current_input_file;
105static FILE **input_file_list;
106
107static const char bad_format_in_subst[] = 97static const char bad_format_in_subst[] =
108 "bad format in substitution expression"; 98 "bad format in substitution expression";
109static const char *const semicolon_whitespace = "; \n\r\t\v"; 99static const char *const semicolon_whitespace = "; \n\r\t\v";
110 100
111static regmatch_t regmatch[10]; 101struct sed_globals
112static regex_t *previous_regex_ptr; 102{
103 /* options */
104 int be_quiet, in_place, regex_type;
105 FILE *nonstdout;
106 char *outname, *hold_space;
107
108 /* List of input files */
109 int input_file_count,current_input_file;
110 FILE **input_file_list;
111
112 regmatch_t regmatch[10];
113 regex_t *previous_regex_ptr;
114
115 /* linked list of sed commands */
116 sed_cmd_t sed_cmd_head, *sed_cmd_tail;
113 117
114/* linked list of sed commands */ 118 /* Linked list of append lines */
115static sed_cmd_t sed_cmd_head; 119 llist_t *append_head;
116static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; 120
121 char *add_cmd_line;
122
123 struct pipeline {
124 char *buf; /* Space to hold string */
125 int idx; /* Space used */
126 int len; /* Space allocated */
127 } pipeline;
128} bbg;
117 129
118/* Linked list of append lines */
119static llist_t *append_head=NULL;
120 130
121void sed_free_and_close_stuff(void); 131void sed_free_and_close_stuff(void);
122#if ENABLE_FEATURE_CLEAN_UP 132#if ENABLE_FEATURE_CLEAN_UP
123void sed_free_and_close_stuff(void) 133void sed_free_and_close_stuff(void)
124{ 134{
125 sed_cmd_t *sed_cmd = sed_cmd_head.next; 135 sed_cmd_t *sed_cmd = bbg.sed_cmd_head.next;
126 136
127 llist_free_contents(append_head); 137 llist_free_contents(bbg.append_head);
128 138
129 while (sed_cmd) { 139 while (sed_cmd) {
130 sed_cmd_t *sed_cmd_next = sed_cmd->next; 140 sed_cmd_t *sed_cmd_next = sed_cmd->next;
@@ -149,10 +159,10 @@ void sed_free_and_close_stuff(void)
149 sed_cmd = sed_cmd_next; 159 sed_cmd = sed_cmd_next;
150 } 160 }
151 161
152 if(hold_space) free(hold_space); 162 if(bbg.hold_space) free(bbg.hold_space);
153 163
154 while(current_input_file<input_file_count) 164 while(bbg.current_input_file<bbg.input_file_count)
155 fclose(input_file_list[current_input_file++]); 165 fclose(bbg.input_file_list[bbg.current_input_file++]);
156} 166}
157#endif 167#endif
158 168
@@ -160,7 +170,7 @@ void sed_free_and_close_stuff(void)
160 170
161static void cleanup_outname(void) 171static void cleanup_outname(void)
162{ 172{
163 if(outname) unlink(outname); 173 if(bbg.outname) unlink(bbg.outname);
164} 174}
165 175
166/* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ 176/* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */
@@ -282,7 +292,7 @@ static int get_address(char *my_str, int *linenum, regex_t ** regex)
282 292
283 temp=copy_parsing_escapes(pos,next); 293 temp=copy_parsing_escapes(pos,next);
284 *regex = (regex_t *) xmalloc(sizeof(regex_t)); 294 *regex = (regex_t *) xmalloc(sizeof(regex_t));
285 xregcomp(*regex, temp, regex_type|REG_NEWLINE); 295 xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE);
286 free(temp); 296 free(temp);
287 /* Move position to next character after last delimiter */ 297 /* Move position to next character after last delimiter */
288 pos+=(next+1); 298 pos+=(next+1);
@@ -291,7 +301,7 @@ static int get_address(char *my_str, int *linenum, regex_t ** regex)
291} 301}
292 302
293/* Grab a filename. Whitespace at start is skipped, then goes to EOL. */ 303/* Grab a filename. Whitespace at start is skipped, then goes to EOL. */
294static int parse_file_cmd(sed_cmd_t * sed_cmd, const char *filecmdstr, char **retval) 304static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr, char **retval)
295{ 305{
296 int start = 0, idx, hack=0; 306 int start = 0, idx, hack=0;
297 307
@@ -308,9 +318,9 @@ static int parse_file_cmd(sed_cmd_t * sed_cmd, const char *filecmdstr, char **re
308 return idx; 318 return idx;
309} 319}
310 320
311static int parse_subst_cmd(sed_cmd_t * const sed_cmd, char *substr) 321static int parse_subst_cmd(sed_cmd_t *const sed_cmd, char *substr)
312{ 322{
313 int cflags = regex_type; 323 int cflags = bbg.regex_type;
314 char *match; 324 char *match;
315 int idx = 0; 325 int idx = 0;
316 326
@@ -463,27 +473,21 @@ static char *parse_cmd_args(sed_cmd_t *sed_cmd, char *cmdstr)
463 473
464static void add_cmd(char *cmdstr) 474static void add_cmd(char *cmdstr)
465{ 475{
466 static char *add_cmd_line=NULL;
467 sed_cmd_t *sed_cmd; 476 sed_cmd_t *sed_cmd;
468 int temp; 477 int temp;
469 478
470 /* Append this line to any unfinished line from last time. */ 479 /* Append this line to any unfinished line from last time. */
471 if(add_cmd_line) { 480 if (bbg.add_cmd_line) {
472 int lastlen=strlen(add_cmd_line); 481 cmdstr = bb_xasprintf("%s\n%s", bbg.add_cmd_line, cmdstr);
473 char *tmp=xmalloc(lastlen+strlen(cmdstr)+2); 482 free(bbg.add_cmd_line);
474 483 bbg.add_cmd_line = cmdstr;
475 memcpy(tmp,add_cmd_line,lastlen); 484 } else bbg.add_cmd_line=NULL;
476 tmp[lastlen]='\n';
477 strcpy(tmp+lastlen+1,cmdstr);
478 free(add_cmd_line);
479 cmdstr=add_cmd_line=tmp;
480 } else add_cmd_line=NULL;
481 485
482 /* If this line ends with backslash, request next line. */ 486 /* If this line ends with backslash, request next line. */
483 temp=strlen(cmdstr); 487 temp=strlen(cmdstr);
484 if(temp && cmdstr[temp-1]=='\\') { 488 if(temp && cmdstr[temp-1]=='\\') {
485 if(!add_cmd_line) add_cmd_line=strdup(cmdstr); 489 if (!bbg.add_cmd_line) bbg.add_cmd_line = bb_xstrdup(cmdstr);
486 add_cmd_line[temp-1]=0; 490 bbg.add_cmd_line[temp-1] = 0;
487 return; 491 return;
488 } 492 }
489 493
@@ -498,7 +502,7 @@ static void add_cmd(char *cmdstr)
498 /* if this is a comment, jump past it and keep going */ 502 /* if this is a comment, jump past it and keep going */
499 if (*cmdstr == '#') { 503 if (*cmdstr == '#') {
500 /* "#n" is the same as using -n on the command line */ 504 /* "#n" is the same as using -n on the command line */
501 if (cmdstr[1] == 'n') be_quiet++; 505 if (cmdstr[1] == 'n') bbg.be_quiet++;
502 if(!(cmdstr=strpbrk(cmdstr, "\n\r"))) break; 506 if(!(cmdstr=strpbrk(cmdstr, "\n\r"))) break;
503 continue; 507 continue;
504 } 508 }
@@ -520,7 +524,7 @@ static void add_cmd(char *cmdstr)
520 524
521 cmdstr++; 525 cmdstr++;
522 idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); 526 idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
523 if (!idx) bb_error_msg_and_die("get_address: no address found in string\n"); 527 if (!idx) bb_error_msg_and_die("no address after comma\n");
524 cmdstr += idx; 528 cmdstr += idx;
525 } 529 }
526 530
@@ -542,32 +546,27 @@ static void add_cmd(char *cmdstr)
542 cmdstr = parse_cmd_args(sed_cmd, cmdstr); 546 cmdstr = parse_cmd_args(sed_cmd, cmdstr);
543 547
544 /* Add the command to the command array */ 548 /* Add the command to the command array */
545 sed_cmd_tail->next = sed_cmd; 549 bbg.sed_cmd_tail->next = sed_cmd;
546 sed_cmd_tail = sed_cmd_tail->next; 550 bbg.sed_cmd_tail = bbg.sed_cmd_tail->next;
547 } 551 }
548 552
549 /* If we glued multiple lines together, free the memory. */ 553 /* If we glued multiple lines together, free the memory. */
550 free(add_cmd_line); 554 free(bbg.add_cmd_line);
551 add_cmd_line=NULL; 555 bbg.add_cmd_line = NULL;
552} 556}
553 557
554/* Append to a string, reallocating memory as necessary. */ 558/* Append to a string, reallocating memory as necessary. */
555 559
556static struct pipeline {
557 char *buf; /* Space to hold string */
558 int idx; /* Space used */
559 int len; /* Space allocated */
560} pipeline;
561
562#define PIPE_GROW 64 560#define PIPE_GROW 64
563 561
564static void pipe_putc(char c) 562static void pipe_putc(char c)
565{ 563{
566 if(pipeline.idx==pipeline.len) { 564 if(bbg.pipeline.idx==bbg.pipeline.len) {
567 pipeline.buf = xrealloc(pipeline.buf, pipeline.len + PIPE_GROW); 565 bbg.pipeline.buf = xrealloc(bbg.pipeline.buf,
568 pipeline.len+=PIPE_GROW; 566 bbg.pipeline.len + PIPE_GROW);
567 bbg.pipeline.len+=PIPE_GROW;
569 } 568 }
570 pipeline.buf[pipeline.idx++] = (c); 569 bbg.pipeline.buf[bbg.pipeline.idx++] = c;
571} 570}
572 571
573static void do_subst_w_backrefs(const char *line, const char *replace) 572static void do_subst_w_backrefs(const char *line, const char *replace)
@@ -580,10 +579,10 @@ static void do_subst_w_backrefs(const char *line, const char *replace)
580 if (replace[i] == '\\' && replace[i+1]>='0' && replace[i+1]<='9') { 579 if (replace[i] == '\\' && replace[i+1]>='0' && replace[i+1]<='9') {
581 int backref=replace[++i]-'0'; 580 int backref=replace[++i]-'0';
582 581
583 /* print out the text held in regmatch[backref] */ 582 /* print out the text held in bbg.regmatch[backref] */
584 if(regmatch[backref].rm_so != -1) 583 if(bbg.regmatch[backref].rm_so != -1)
585 for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) 584 for (j = bbg.regmatch[backref].rm_so;
586 pipe_putc(line[j]); 585 j < bbg.regmatch[backref].rm_eo; j++) pipe_putc(line[j]);
587 } 586 }
588 587
589 /* if we find a backslash escaped character, print the character */ 588 /* if we find a backslash escaped character, print the character */
@@ -591,14 +590,14 @@ static void do_subst_w_backrefs(const char *line, const char *replace)
591 590
592 /* if we find an unescaped '&' print out the whole matched text. */ 591 /* if we find an unescaped '&' print out the whole matched text. */
593 else if (replace[i] == '&') 592 else if (replace[i] == '&')
594 for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) 593 for (j = bbg.regmatch[0].rm_so; j < bbg.regmatch[0].rm_eo; j++)
595 pipe_putc(line[j]); 594 pipe_putc(line[j]);
596 /* Otherwise just output the character. */ 595 /* Otherwise just output the character. */
597 else pipe_putc(replace[i]); 596 else pipe_putc(replace[i]);
598 } 597 }
599} 598}
600 599
601static int do_subst_command(sed_cmd_t * sed_cmd, char **line) 600static int do_subst_command(sed_cmd_t *sed_cmd, char **line)
602{ 601{
603 char *oldline = *line; 602 char *oldline = *line;
604 int altered = 0; 603 int altered = 0;
@@ -607,19 +606,19 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line)
607 606
608 /* Handle empty regex. */ 607 /* Handle empty regex. */
609 if (sed_cmd->sub_match == NULL) { 608 if (sed_cmd->sub_match == NULL) {
610 current_regex = previous_regex_ptr; 609 current_regex = bbg.previous_regex_ptr;
611 if(!current_regex) 610 if(!current_regex)
612 bb_error_msg_and_die("No previous regexp."); 611 bb_error_msg_and_die("No previous regexp.");
613 } else previous_regex_ptr = current_regex = sed_cmd->sub_match; 612 } else bbg.previous_regex_ptr = current_regex = sed_cmd->sub_match;
614 613
615 /* Find the first match */ 614 /* Find the first match */
616 if(REG_NOMATCH==regexec(current_regex, oldline, 10, regmatch, 0)) 615 if(REG_NOMATCH==regexec(current_regex, oldline, 10, bbg.regmatch, 0))
617 return 0; 616 return 0;
618 617
619 /* Initialize temporary output buffer. */ 618 /* Initialize temporary output buffer. */
620 pipeline.buf=xmalloc(PIPE_GROW); 619 bbg.pipeline.buf=xmalloc(PIPE_GROW);
621 pipeline.len=PIPE_GROW; 620 bbg.pipeline.len=PIPE_GROW;
622 pipeline.idx=0; 621 bbg.pipeline.idx=0;
623 622
624 /* Now loop through, substituting for matches */ 623 /* Now loop through, substituting for matches */
625 do { 624 do {
@@ -629,7 +628,7 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line)
629 echo " a.b" | busybox sed 's [^ .]* x g' 628 echo " a.b" | busybox sed 's [^ .]* x g'
630 The match_count check is so not to break 629 The match_count check is so not to break
631 echo "hi" | busybox sed 's/^/!/g' */ 630 echo "hi" | busybox sed 's/^/!/g' */
632 if(!regmatch[0].rm_so && !regmatch[0].rm_eo && match_count) { 631 if(!bbg.regmatch[0].rm_so && !bbg.regmatch[0].rm_eo && match_count) {
633 pipe_putc(*(oldline++)); 632 pipe_putc(*(oldline++));
634 continue; 633 continue;
635 } 634 }
@@ -639,25 +638,25 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line)
639 /* If we aren't interested in this match, output old line to 638 /* If we aren't interested in this match, output old line to
640 end of match and continue */ 639 end of match and continue */
641 if(sed_cmd->which_match && sed_cmd->which_match!=match_count) { 640 if(sed_cmd->which_match && sed_cmd->which_match!=match_count) {
642 for(i=0;i<regmatch[0].rm_eo;i++) 641 for(i=0;i<bbg.regmatch[0].rm_eo;i++)
643 pipe_putc(oldline[i]); 642 pipe_putc(oldline[i]);
644 continue; 643 continue;
645 } 644 }
646 645
647 /* print everything before the match */ 646 /* print everything before the match */
648 for (i = 0; i < regmatch[0].rm_so; i++) pipe_putc(oldline[i]); 647 for (i = 0; i < bbg.regmatch[0].rm_so; i++) pipe_putc(oldline[i]);
649 648
650 /* then print the substitution string */ 649 /* then print the substitution string */
651 do_subst_w_backrefs(oldline, sed_cmd->string); 650 do_subst_w_backrefs(oldline, sed_cmd->string);
652 651
653 /* advance past the match */ 652 /* advance past the match */
654 oldline += regmatch[0].rm_eo; 653 oldline += bbg.regmatch[0].rm_eo;
655 /* flag that something has changed */ 654 /* flag that something has changed */
656 altered++; 655 altered++;
657 656
658 /* if we're not doing this globally, get out now */ 657 /* if we're not doing this globally, get out now */
659 if (sed_cmd->which_match) break; 658 if (sed_cmd->which_match) break;
660 } while (*oldline && (regexec(current_regex, oldline, 10, regmatch, 0) != REG_NOMATCH)); 659 } while (*oldline && (regexec(current_regex, oldline, 10, bbg.regmatch, 0) != REG_NOMATCH));
661 660
662 /* Copy rest of string into output pipeline */ 661 /* Copy rest of string into output pipeline */
663 662
@@ -665,7 +664,7 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line)
665 pipe_putc(0); 664 pipe_putc(0);
666 665
667 free(*line); 666 free(*line);
668 *line = pipeline.buf; 667 *line = bbg.pipeline.buf;
669 return altered; 668 return altered;
670} 669}
671 670
@@ -674,7 +673,7 @@ static sed_cmd_t *branch_to(const char *label)
674{ 673{
675 sed_cmd_t *sed_cmd; 674 sed_cmd_t *sed_cmd;
676 675
677 for (sed_cmd = sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { 676 for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
678 if ((sed_cmd->cmd == ':') && (sed_cmd->string) && (strcmp(sed_cmd->string, label) == 0)) { 677 if ((sed_cmd->cmd == ':') && (sed_cmd->string) && (strcmp(sed_cmd->string, label) == 0)) {
679 return (sed_cmd); 678 return (sed_cmd);
680 } 679 }
@@ -684,7 +683,7 @@ static sed_cmd_t *branch_to(const char *label)
684 683
685static void append(char *s) 684static void append(char *s)
686{ 685{
687 append_head=llist_add_to_end(append_head, bb_xstrdup(s)); 686 bbg.append_head = llist_add_to_end(bbg.append_head, bb_xstrdup(s));
688} 687}
689 688
690static void flush_append(void) 689static void flush_append(void)
@@ -692,19 +691,20 @@ static void flush_append(void)
692 char *data; 691 char *data;
693 692
694 /* Output appended lines. */ 693 /* Output appended lines. */
695 while((data = (char *)llist_pop(&append_head))) { 694 while((data = (char *)llist_pop(&bbg.append_head))) {
696 fprintf(nonstdout,"%s\n",data); 695 fprintf(bbg.nonstdout,"%s\n",data);
697 free(data); 696 free(data);
698 } 697 }
699} 698}
700 699
701static void add_input_file(FILE *file) 700static void add_input_file(FILE *file)
702{ 701{
703 input_file_list=xrealloc(input_file_list,(input_file_count+1)*sizeof(FILE *)); 702 bbg.input_file_list=xrealloc(bbg.input_file_list,
704 input_file_list[input_file_count++]=file; 703 (bbg.input_file_count + 1) * sizeof(FILE *));
704 bbg.input_file_list[bbg.input_file_count++] = file;
705} 705}
706 706
707/* Get next line of input from input_file_list, flushing append buffer and 707/* Get next line of input from bbg.input_file_list, flushing append buffer and
708 * noting if we ran out of files without a newline on the last line we read. 708 * noting if we ran out of files without a newline on the last line we read.
709 */ 709 */
710static char *get_next_line(int *no_newline) 710static char *get_next_line(int *no_newline)
@@ -713,14 +713,14 @@ static char *get_next_line(int *no_newline)
713 int len; 713 int len;
714 714
715 flush_append(); 715 flush_append();
716 while (current_input_file<input_file_count) { 716 while (bbg.current_input_file<bbg.input_file_count) {
717 temp = bb_get_chunk_from_file(input_file_list[current_input_file],&len); 717 temp = bb_get_chunk_from_file(bbg.input_file_list[bbg.current_input_file],&len);
718 if (temp) { 718 if (temp) {
719 *no_newline = !(len && temp[len-1]=='\n'); 719 *no_newline = !(len && temp[len-1]=='\n');
720 if (!*no_newline) temp[len-1] = 0; 720 if (!*no_newline) temp[len-1] = 0;
721 break; 721 break;
722 // Close this file and advance to next one 722 // Close this file and advance to next one
723 } else fclose(input_file_list[current_input_file++]); 723 } else fclose(bbg.input_file_list[bbg.current_input_file++]);
724 } 724 }
725 725
726 return temp; 726 return temp;
@@ -744,7 +744,7 @@ static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int no_n
744 return no_newline; 744 return no_newline;
745} 745}
746 746
747#define sed_puts(s,n) missing_newline=puts_maybe_newline(s,nonstdout,missing_newline,n) 747#define sed_puts(s,n) missing_newline=puts_maybe_newline(s,bbg.nonstdout,missing_newline,n)
748 748
749/* Process all the lines in all the files */ 749/* Process all the lines in all the files */
750 750
@@ -772,7 +772,8 @@ static void process_files(void)
772 linenum++; 772 linenum++;
773restart: 773restart:
774 /* for every line, go through all the commands */ 774 /* for every line, go through all the commands */
775 for (sed_cmd = sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { 775 for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next)
776 {
776 int old_matched, matched; 777 int old_matched, matched;
777 778
778 old_matched = sed_cmd->in_match; 779 old_matched = sed_cmd->in_match;
@@ -828,7 +829,7 @@ restart:
828 if (sed_cmd->invert ? !matched : matched) { 829 if (sed_cmd->invert ? !matched : matched) {
829 /* Update last used regex in case a blank substitute BRE is found */ 830 /* Update last used regex in case a blank substitute BRE is found */
830 if (sed_cmd->beg_match) { 831 if (sed_cmd->beg_match) {
831 previous_regex_ptr = sed_cmd->beg_match; 832 bbg.previous_regex_ptr = sed_cmd->beg_match;
832 } 833 }
833 834
834 /* actual sedding */ 835 /* actual sedding */
@@ -836,7 +837,7 @@ restart:
836 837
837 /* Print line number */ 838 /* Print line number */
838 case '=': 839 case '=':
839 fprintf(nonstdout,"%d\n", linenum); 840 fprintf(bbg.nonstdout,"%d\n", linenum);
840 break; 841 break;
841 842
842 /* Write the current pattern space up to the first newline */ 843 /* Write the current pattern space up to the first newline */
@@ -931,7 +932,7 @@ restart:
931 932
932 /* Read next line from input */ 933 /* Read next line from input */
933 case 'n': 934 case 'n':
934 if (!be_quiet) 935 if (!bbg.be_quiet)
935 sed_puts(pattern_space,no_newline); 936 sed_puts(pattern_space,no_newline);
936 if (next_line) { 937 if (next_line) {
937 free(pattern_space); 938 free(pattern_space);
@@ -1007,7 +1008,7 @@ restart:
1007 } 1008 }
1008 case 'g': /* Replace pattern space with hold space */ 1009 case 'g': /* Replace pattern space with hold space */
1009 free(pattern_space); 1010 free(pattern_space);
1010 pattern_space = strdup(hold_space ? hold_space : ""); 1011 pattern_space = bb_xstrdup(bbg.hold_space ? bbg.hold_space : "");
1011 break; 1012 break;
1012 case 'G': /* Append newline and hold space to pattern space */ 1013 case 'G': /* Append newline and hold space to pattern space */
1013 { 1014 {
@@ -1016,42 +1017,46 @@ restart:
1016 1017
1017 if (pattern_space) 1018 if (pattern_space)
1018 pattern_space_size += strlen(pattern_space); 1019 pattern_space_size += strlen(pattern_space);
1019 if (hold_space) hold_space_size = strlen(hold_space); 1020 if (bbg.hold_space)
1020 pattern_space = xrealloc(pattern_space, pattern_space_size + hold_space_size); 1021 hold_space_size = strlen(bbg.hold_space);
1022 pattern_space = xrealloc(pattern_space,
1023 pattern_space_size + hold_space_size);
1021 if (pattern_space_size == 2) pattern_space[0]=0; 1024 if (pattern_space_size == 2) pattern_space[0]=0;
1022 strcat(pattern_space, "\n"); 1025 strcat(pattern_space, "\n");
1023 if (hold_space) strcat(pattern_space, hold_space); 1026 if (bbg.hold_space)
1027 strcat(pattern_space, bbg.hold_space);
1024 no_newline=0; 1028 no_newline=0;
1025 1029
1026 break; 1030 break;
1027 } 1031 }
1028 case 'h': /* Replace hold space with pattern space */ 1032 case 'h': /* Replace hold space with pattern space */
1029 free(hold_space); 1033 free(bbg.hold_space);
1030 hold_space = strdup(pattern_space); 1034 bbg.hold_space = bb_xstrdup(pattern_space);
1031 break; 1035 break;
1032 case 'H': /* Append newline and pattern space to hold space */ 1036 case 'H': /* Append newline and pattern space to hold space */
1033 { 1037 {
1034 int hold_space_size = 2; 1038 int hold_space_size = 2;
1035 int pattern_space_size = 0; 1039 int pattern_space_size = 0;
1036 1040
1037 if (hold_space) hold_space_size += strlen(hold_space); 1041 if (bbg.hold_space)
1042 hold_space_size += strlen(bbg.hold_space);
1038 if (pattern_space) 1043 if (pattern_space)
1039 pattern_space_size = strlen(pattern_space); 1044 pattern_space_size = strlen(pattern_space);
1040 hold_space = xrealloc(hold_space, 1045 bbg.hold_space = xrealloc(bbg.hold_space,
1041 hold_space_size + pattern_space_size); 1046 hold_space_size + pattern_space_size);
1042 1047
1043 if (hold_space_size == 2) hold_space[0]=0; 1048 if (hold_space_size == 2) *bbg.hold_space=0;
1044 strcat(hold_space, "\n"); 1049 strcat(bbg.hold_space, "\n");
1045 if (pattern_space) strcat(hold_space, pattern_space); 1050 if (pattern_space) strcat(bbg.hold_space, pattern_space);
1046 1051
1047 break; 1052 break;
1048 } 1053 }
1049 case 'x': /* Exchange hold and pattern space */ 1054 case 'x': /* Exchange hold and pattern space */
1050 { 1055 {
1051 char *tmp = pattern_space; 1056 char *tmp = pattern_space;
1052 pattern_space = hold_space; 1057 pattern_space = bbg.hold_space;
1053 no_newline=0; 1058 no_newline=0;
1054 hold_space = tmp; 1059 bbg.hold_space = tmp;
1055 break; 1060 break;
1056 } 1061 }
1057 } 1062 }
@@ -1064,7 +1069,7 @@ restart:
1064discard_commands: 1069discard_commands:
1065 /* we will print the line unless we were told to be quiet ('-n') 1070 /* we will print the line unless we were told to be quiet ('-n')
1066 or if the line was suppressed (ala 'd'elete) */ 1071 or if the line was suppressed (ala 'd'elete) */
1067 if (!be_quiet) sed_puts(pattern_space,no_newline); 1072 if (!bbg.be_quiet) sed_puts(pattern_space,no_newline);
1068 1073
1069 /* Delete and such jump here. */ 1074 /* Delete and such jump here. */
1070discard_line: 1075discard_line:
@@ -1095,6 +1100,8 @@ int sed_main(int argc, char **argv)
1095{ 1100{
1096 int status = EXIT_SUCCESS, opt, getpat = 1; 1101 int status = EXIT_SUCCESS, opt, getpat = 1;
1097 1102
1103 bbg.sed_cmd_tail=&bbg.sed_cmd_head;
1104
1098 /* destroy command strings on exit */ 1105 /* destroy command strings on exit */
1099 if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); 1106 if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff);
1100 1107
@@ -1108,14 +1115,14 @@ int sed_main(int argc, char **argv)
1108 while ((opt = getopt(argc, argv, "irne:f:")) > 0) { 1115 while ((opt = getopt(argc, argv, "irne:f:")) > 0) {
1109 switch (opt) { 1116 switch (opt) {
1110 case 'i': 1117 case 'i':
1111 in_place++; 1118 bbg.in_place++;
1112 atexit(cleanup_outname); 1119 atexit(cleanup_outname);
1113 break; 1120 break;
1114 case 'r': 1121 case 'r':
1115 regex_type|=REG_EXTENDED; 1122 bbg.regex_type|=REG_EXTENDED;
1116 break; 1123 break;
1117 case 'n': 1124 case 'n':
1118 be_quiet++; 1125 bbg.be_quiet++;
1119 break; 1126 break;
1120 case 'e': 1127 case 'e':
1121 add_cmd_block(optarg); 1128 add_cmd_block(optarg);
@@ -1153,13 +1160,13 @@ int sed_main(int argc, char **argv)
1153 add_cmd(""); 1160 add_cmd("");
1154 1161
1155 /* By default, we write to stdout */ 1162 /* By default, we write to stdout */
1156 nonstdout=stdout; 1163 bbg.nonstdout=stdout;
1157 1164
1158 /* argv[(optind)..(argc-1)] should be names of file to process. If no 1165 /* argv[(optind)..(argc-1)] should be names of file to process. If no
1159 * files were specified or '-' was specified, take input from stdin. 1166 * files were specified or '-' was specified, take input from stdin.
1160 * Otherwise, we process all the files specified. */ 1167 * Otherwise, we process all the files specified. */
1161 if (argv[optind] == NULL) { 1168 if (argv[optind] == NULL) {
1162 if(in_place) bb_error_msg_and_die("Filename required for -i"); 1169 if(bbg.in_place) bb_error_msg_and_die("Filename required for -i");
1163 add_input_file(stdin); 1170 add_input_file(stdin);
1164 process_files(); 1171 process_files();
1165 } else { 1172 } else {
@@ -1167,21 +1174,21 @@ int sed_main(int argc, char **argv)
1167 FILE *file; 1174 FILE *file;
1168 1175
1169 for (i = optind; i < argc; i++) { 1176 for (i = optind; i < argc; i++) {
1170 if(!strcmp(argv[i], "-") && !in_place) { 1177 if(!strcmp(argv[i], "-") && !bbg.in_place) {
1171 add_input_file(stdin); 1178 add_input_file(stdin);
1172 process_files(); 1179 process_files();
1173 } else { 1180 } else {
1174 file = bb_wfopen(argv[i], "r"); 1181 file = bb_wfopen(argv[i], "r");
1175 if (file) { 1182 if (file) {
1176 if(in_place) { 1183 if(bbg.in_place) {
1177 struct stat statbuf; 1184 struct stat statbuf;
1178 int nonstdoutfd; 1185 int nonstdoutfd;
1179 1186
1180 outname=bb_xstrndup(argv[i],strlen(argv[i])+6); 1187 bbg.outname=bb_xstrndup(argv[i],strlen(argv[i])+6);
1181 strcat(outname,"XXXXXX"); 1188 strcat(bbg.outname,"XXXXXX");
1182 if(-1==(nonstdoutfd=mkstemp(outname))) 1189 if(-1==(nonstdoutfd=mkstemp(bbg.outname)))
1183 bb_error_msg_and_die("no temp file"); 1190 bb_error_msg_and_die("no temp file");
1184 nonstdout=fdopen(nonstdoutfd,"w"); 1191 bbg.nonstdout=fdopen(nonstdoutfd,"w");
1185 1192
1186 /* Set permissions of output file */ 1193 /* Set permissions of output file */
1187 1194
@@ -1189,20 +1196,20 @@ int sed_main(int argc, char **argv)
1189 fchmod(nonstdoutfd,statbuf.st_mode); 1196 fchmod(nonstdoutfd,statbuf.st_mode);
1190 add_input_file(file); 1197 add_input_file(file);
1191 process_files(); 1198 process_files();
1192 fclose(nonstdout); 1199 fclose(bbg.nonstdout);
1193 1200
1194 nonstdout=stdout; 1201 bbg.nonstdout=stdout;
1195 unlink(argv[i]); 1202 unlink(argv[i]);
1196 rename(outname,argv[i]); 1203 rename(bbg.outname,argv[i]);
1197 free(outname); 1204 free(bbg.outname);
1198 outname=0; 1205 bbg.outname=0;
1199 } else add_input_file(file); 1206 } else add_input_file(file);
1200 } else { 1207 } else {
1201 status = EXIT_FAILURE; 1208 status = EXIT_FAILURE;
1202 } 1209 }
1203 } 1210 }
1204 } 1211 }
1205 if(input_file_count>current_input_file) process_files(); 1212 if(bbg.input_file_count>bbg.current_input_file) process_files();
1206 } 1213 }
1207 1214
1208 return status; 1215 return status;