diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/ed.c | 15 | ||||
-rw-r--r-- | editors/sed.c | 31 |
2 files changed, 40 insertions, 6 deletions
diff --git a/editors/ed.c b/editors/ed.c index dfe0f1a77..209ce9942 100644 --- a/editors/ed.c +++ b/editors/ed.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | //applet:IF_ED(APPLET(ed, BB_DIR_BIN, BB_SUID_DROP)) | 19 | //applet:IF_ED(APPLET(ed, BB_DIR_BIN, BB_SUID_DROP)) |
20 | 20 | ||
21 | //usage:#define ed_trivial_usage "[-p PROMPT] [FILE]" | 21 | //usage:#define ed_trivial_usage "[-p PROMPT] [-s] [FILE]" |
22 | //usage:#define ed_full_usage "" | 22 | //usage:#define ed_full_usage "" |
23 | 23 | ||
24 | #include "libbb.h" | 24 | #include "libbb.h" |
@@ -71,6 +71,11 @@ struct globals { | |||
71 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 71 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
72 | } while (0) | 72 | } while (0) |
73 | 73 | ||
74 | #define OPTION_STR "sp:" | ||
75 | enum { | ||
76 | OPT_s = (1 << 0), | ||
77 | }; | ||
78 | |||
74 | static int bad_nums(int num1, int num2, const char *for_what) | 79 | static int bad_nums(int num1, int num2, const char *for_what) |
75 | { | 80 | { |
76 | if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { | 81 | if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { |
@@ -458,7 +463,8 @@ static int readLines(const char *file, int num) | |||
458 | * in the following format: | 463 | * in the following format: |
459 | * "%d\n", <number of bytes read> | 464 | * "%d\n", <number of bytes read> |
460 | */ | 465 | */ |
461 | printf("%u\n", charCount); | 466 | if (!(option_mask32 & OPT_s)) |
467 | printf("%u\n", charCount); | ||
462 | return TRUE; | 468 | return TRUE; |
463 | } | 469 | } |
464 | 470 | ||
@@ -510,7 +516,8 @@ static int writeLines(const char *file, int num1, int num2) | |||
510 | * unless the -s option was specified, in the following format: | 516 | * unless the -s option was specified, in the following format: |
511 | * "%d\n", <number of bytes written> | 517 | * "%d\n", <number of bytes written> |
512 | */ | 518 | */ |
513 | printf("%u\n", charCount); | 519 | if (!(option_mask32 & OPT_s)) |
520 | printf("%u\n", charCount); | ||
514 | return TRUE; | 521 | return TRUE; |
515 | } | 522 | } |
516 | 523 | ||
@@ -1005,7 +1012,7 @@ int ed_main(int argc UNUSED_PARAM, char **argv) | |||
1005 | lines.prev = &lines; | 1012 | lines.prev = &lines; |
1006 | 1013 | ||
1007 | prompt = ""; /* no prompt by default */ | 1014 | prompt = ""; /* no prompt by default */ |
1008 | getopt32(argv, "p:", &prompt); | 1015 | getopt32(argv, OPTION_STR, &prompt); |
1009 | argv += optind; | 1016 | argv += optind; |
1010 | 1017 | ||
1011 | if (argv[0]) { | 1018 | if (argv[0]) { |
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 | } |