diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/sed.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/editors/sed.c b/editors/sed.c index e8c82ac63..48b0dbf67 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -97,6 +97,12 @@ enum { | |||
97 | OPT_in_place = 1 << 0, | 97 | OPT_in_place = 1 << 0, |
98 | }; | 98 | }; |
99 | 99 | ||
100 | struct sed_FILE { | ||
101 | struct sed_FILE *next; /* Next (linked list, NULL terminated) */ | ||
102 | const char *fname; | ||
103 | FILE *fp; | ||
104 | }; | ||
105 | |||
100 | /* Each sed command turns into one of these structures. */ | 106 | /* Each sed command turns into one of these structures. */ |
101 | typedef struct sed_cmd_s { | 107 | typedef struct sed_cmd_s { |
102 | /* Ordered by alignment requirements: currently 36 bytes on x86 */ | 108 | /* Ordered by alignment requirements: currently 36 bytes on x86 */ |
@@ -151,6 +157,11 @@ struct globals { | |||
151 | /* linked list of append lines */ | 157 | /* linked list of append lines */ |
152 | llist_t *append_head; | 158 | llist_t *append_head; |
153 | 159 | ||
160 | /* linked list of FILEs opened for 'w' and s///w'. | ||
161 | * Needed to handle duplicate fnames: sed '/a/w F;/b/w F' | ||
162 | */ | ||
163 | struct sed_FILE *FILE_head; | ||
164 | |||
154 | char *add_cmd_line; | 165 | char *add_cmd_line; |
155 | 166 | ||
156 | struct pipeline { | 167 | struct pipeline { |
@@ -211,6 +222,22 @@ static void sed_free_and_close_stuff(void) | |||
211 | void sed_free_and_close_stuff(void); | 222 | void sed_free_and_close_stuff(void); |
212 | #endif | 223 | #endif |
213 | 224 | ||
225 | static FILE *sed_xfopen_w(const char *fname) | ||
226 | { | ||
227 | struct sed_FILE **pp = &G.FILE_head; | ||
228 | struct sed_FILE *cur; | ||
229 | while ((cur = *pp) != NULL) { | ||
230 | if (strcmp(cur->fname, fname) == 0) | ||
231 | return cur->fp; | ||
232 | pp = &cur->next; | ||
233 | } | ||
234 | *pp = cur = xzalloc(sizeof(*cur)); | ||
235 | /*cur->next = NULL; - already is */ | ||
236 | cur->fname = xstrdup(fname); | ||
237 | cur->fp = xfopen_for_write(fname); | ||
238 | return cur->fp; | ||
239 | } | ||
240 | |||
214 | /* If something bad happens during -i operation, delete temp file */ | 241 | /* If something bad happens during -i operation, delete temp file */ |
215 | 242 | ||
216 | static void cleanup_outname(void) | 243 | static void cleanup_outname(void) |
@@ -446,7 +473,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) | |||
446 | { | 473 | { |
447 | char *fname; | 474 | char *fname; |
448 | idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname); | 475 | idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname); |
449 | sed_cmd->sw_file = xfopen_for_write(fname); | 476 | sed_cmd->sw_file = sed_xfopen_w(fname); |
450 | sed_cmd->sw_last_char = '\n'; | 477 | sed_cmd->sw_last_char = '\n'; |
451 | free(fname); | 478 | free(fname); |
452 | break; | 479 | break; |
@@ -561,7 +588,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
561 | } | 588 | } |
562 | cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); | 589 | cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); |
563 | if (sed_cmd->cmd == 'w') { | 590 | if (sed_cmd->cmd == 'w') { |
564 | sed_cmd->sw_file = xfopen_for_write(sed_cmd->string); | 591 | sed_cmd->sw_file = sed_xfopen_w(sed_cmd->string); |
565 | sed_cmd->sw_last_char = '\n'; | 592 | sed_cmd->sw_last_char = '\n'; |
566 | } | 593 | } |
567 | } | 594 | } |