diff options
Diffstat (limited to 'editors/sed.c')
-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 73034438a..374830f3f 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -100,6 +100,12 @@ enum { | |||
100 | OPT_in_place = 1 << 0, | 100 | OPT_in_place = 1 << 0, |
101 | }; | 101 | }; |
102 | 102 | ||
103 | struct sed_FILE { | ||
104 | struct sed_FILE *next; /* Next (linked list, NULL terminated) */ | ||
105 | const char *fname; | ||
106 | FILE *fp; | ||
107 | }; | ||
108 | |||
103 | /* Each sed command turns into one of these structures. */ | 109 | /* Each sed command turns into one of these structures. */ |
104 | typedef struct sed_cmd_s { | 110 | typedef struct sed_cmd_s { |
105 | /* Ordered by alignment requirements: currently 36 bytes on x86 */ | 111 | /* Ordered by alignment requirements: currently 36 bytes on x86 */ |
@@ -157,6 +163,11 @@ struct globals { | |||
157 | /* linked list of append lines */ | 163 | /* linked list of append lines */ |
158 | llist_t *append_head; | 164 | llist_t *append_head; |
159 | 165 | ||
166 | /* linked list of FILEs opened for 'w' and s///w'. | ||
167 | * Needed to handle duplicate fnames: sed '/a/w F;/b/w F' | ||
168 | */ | ||
169 | struct sed_FILE *FILE_head; | ||
170 | |||
160 | char *add_cmd_line; | 171 | char *add_cmd_line; |
161 | 172 | ||
162 | struct pipeline { | 173 | struct pipeline { |
@@ -217,6 +228,22 @@ static void sed_free_and_close_stuff(void) | |||
217 | void sed_free_and_close_stuff(void); | 228 | void sed_free_and_close_stuff(void); |
218 | #endif | 229 | #endif |
219 | 230 | ||
231 | static FILE *sed_xfopen_w(const char *fname) | ||
232 | { | ||
233 | struct sed_FILE **pp = &G.FILE_head; | ||
234 | struct sed_FILE *cur; | ||
235 | while ((cur = *pp) != NULL) { | ||
236 | if (strcmp(cur->fname, fname) == 0) | ||
237 | return cur->fp; | ||
238 | pp = &cur->next; | ||
239 | } | ||
240 | *pp = cur = xzalloc(sizeof(*cur)); | ||
241 | /*cur->next = NULL; - already is */ | ||
242 | cur->fname = xstrdup(fname); | ||
243 | cur->fp = xfopen_for_write(fname); | ||
244 | return cur->fp; | ||
245 | } | ||
246 | |||
220 | /* If something bad happens during -i operation, delete temp file */ | 247 | /* If something bad happens during -i operation, delete temp file */ |
221 | 248 | ||
222 | static void cleanup_outname(void) | 249 | static void cleanup_outname(void) |
@@ -452,7 +479,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) | |||
452 | { | 479 | { |
453 | char *fname; | 480 | char *fname; |
454 | idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname); | 481 | idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname); |
455 | sed_cmd->sw_file = xfopen_for_write(fname); | 482 | sed_cmd->sw_file = sed_xfopen_w(fname); |
456 | sed_cmd->sw_last_char = '\n'; | 483 | sed_cmd->sw_last_char = '\n'; |
457 | free(fname); | 484 | free(fname); |
458 | break; | 485 | break; |
@@ -567,7 +594,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
567 | } | 594 | } |
568 | cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); | 595 | cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); |
569 | if (sed_cmd->cmd == 'w') { | 596 | if (sed_cmd->cmd == 'w') { |
570 | sed_cmd->sw_file = xfopen_for_write(sed_cmd->string); | 597 | sed_cmd->sw_file = sed_xfopen_w(sed_cmd->string); |
571 | sed_cmd->sw_last_char = '\n'; | 598 | sed_cmd->sw_last_char = '\n'; |
572 | } | 599 | } |
573 | } | 600 | } |