diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/diff.c | 2 | ||||
-rw-r--r-- | editors/ed.c | 6 | ||||
-rw-r--r-- | editors/sed.c | 77 | ||||
-rw-r--r-- | editors/vi.c | 2 |
4 files changed, 57 insertions, 30 deletions
diff --git a/editors/diff.c b/editors/diff.c index a892cfdf2..ff269360f 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -125,6 +125,7 @@ | |||
125 | //usage: "\n -w Ignore all whitespace" | 125 | //usage: "\n -w Ignore all whitespace" |
126 | 126 | ||
127 | #include "libbb.h" | 127 | #include "libbb.h" |
128 | #include "common_bufsiz.h" | ||
128 | 129 | ||
129 | #if 0 | 130 | #if 0 |
130 | # define dbg_error_msg(...) bb_error_msg(__VA_ARGS__) | 131 | # define dbg_error_msg(...) bb_error_msg(__VA_ARGS__) |
@@ -748,6 +749,7 @@ static int diffreg(char *file[2]) | |||
748 | fp[i] = fdopen(fd, "r"); | 749 | fp[i] = fdopen(fd, "r"); |
749 | } | 750 | } |
750 | 751 | ||
752 | setup_common_bufsiz(); | ||
751 | while (1) { | 753 | while (1) { |
752 | const size_t sz = COMMON_BUFSIZE / 2; | 754 | const size_t sz = COMMON_BUFSIZE / 2; |
753 | char *const buf0 = bb_common_bufsiz1; | 755 | char *const buf0 = bb_common_bufsiz1; |
diff --git a/editors/ed.c b/editors/ed.c index a4c419099..c028b78cb 100644 --- a/editors/ed.c +++ b/editors/ed.c | |||
@@ -23,6 +23,7 @@ | |||
23 | //usage:#define ed_full_usage "" | 23 | //usage:#define ed_full_usage "" |
24 | 24 | ||
25 | #include "libbb.h" | 25 | #include "libbb.h" |
26 | #include "common_bufsiz.h" | ||
26 | 27 | ||
27 | typedef struct LINE { | 28 | typedef struct LINE { |
28 | struct LINE *next; | 29 | struct LINE *next; |
@@ -35,8 +36,8 @@ typedef struct LINE { | |||
35 | #define searchString bb_common_bufsiz1 | 36 | #define searchString bb_common_bufsiz1 |
36 | 37 | ||
37 | enum { | 38 | enum { |
38 | USERSIZE = sizeof(searchString) > 1024 ? 1024 | 39 | USERSIZE = COMMON_BUFSIZE > 1024 ? 1024 |
39 | : sizeof(searchString) - 1, /* max line length typed in by user */ | 40 | : COMMON_BUFSIZE - 1, /* max line length typed in by user */ |
40 | INITBUF_SIZE = 1024, /* initial buffer size */ | 41 | INITBUF_SIZE = 1024, /* initial buffer size */ |
41 | }; | 42 | }; |
42 | 43 | ||
@@ -66,6 +67,7 @@ struct globals { | |||
66 | #define lines (G.lines ) | 67 | #define lines (G.lines ) |
67 | #define marks (G.marks ) | 68 | #define marks (G.marks ) |
68 | #define INIT_G() do { \ | 69 | #define INIT_G() do { \ |
70 | setup_common_bufsiz(); \ | ||
69 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 71 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
70 | } while (0) | 72 | } while (0) |
71 | 73 | ||
diff --git a/editors/sed.c b/editors/sed.c index a0c713f58..b629e060a 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -86,6 +86,7 @@ | |||
86 | //usage: "bar\n" | 86 | //usage: "bar\n" |
87 | 87 | ||
88 | #include "libbb.h" | 88 | #include "libbb.h" |
89 | #include "common_bufsiz.h" | ||
89 | #include "xregex.h" | 90 | #include "xregex.h" |
90 | 91 | ||
91 | #if 0 | 92 | #if 0 |
@@ -161,8 +162,9 @@ struct globals { | |||
161 | int len; /* Space allocated */ | 162 | int len; /* Space allocated */ |
162 | } pipeline; | 163 | } pipeline; |
163 | } FIX_ALIASING; | 164 | } FIX_ALIASING; |
164 | #define G (*(struct globals*)&bb_common_bufsiz1) | 165 | #define G (*(struct globals*)bb_common_bufsiz1) |
165 | #define INIT_G() do { \ | 166 | #define INIT_G() do { \ |
167 | setup_common_bufsiz(); \ | ||
166 | BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ | 168 | BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ |
167 | G.sed_cmd_tail = &G.sed_cmd_head; \ | 169 | G.sed_cmd_tail = &G.sed_cmd_head; \ |
168 | } while (0) | 170 | } while (0) |
@@ -216,23 +218,33 @@ static void cleanup_outname(void) | |||
216 | 218 | ||
217 | /* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */ | 219 | /* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */ |
218 | 220 | ||
219 | static void parse_escapes(char *dest, const char *string, int len, char from, char to) | 221 | static unsigned parse_escapes(char *dest, const char *string, int len, char from, char to) |
220 | { | 222 | { |
223 | char *d = dest; | ||
221 | int i = 0; | 224 | int i = 0; |
222 | 225 | ||
226 | if (len == -1) | ||
227 | len = strlen(string); | ||
228 | |||
223 | while (i < len) { | 229 | while (i < len) { |
224 | if (string[i] == '\\') { | 230 | if (string[i] == '\\') { |
225 | if (!to || string[i+1] == from) { | 231 | if (!to || string[i+1] == from) { |
226 | *dest++ = to ? to : string[i+1]; | 232 | if ((*d = to ? to : string[i+1]) == '\0') |
233 | return d - dest; | ||
227 | i += 2; | 234 | i += 2; |
235 | d++; | ||
228 | continue; | 236 | continue; |
229 | } | 237 | } |
230 | *dest++ = string[i++]; | 238 | i++; /* skip backslash in string[] */ |
239 | *d++ = '\\'; | ||
240 | /* fall through: copy next char verbatim */ | ||
231 | } | 241 | } |
232 | /* TODO: is it safe wrt a string with trailing '\\' ? */ | 242 | if ((*d = string[i++]) == '\0') |
233 | *dest++ = string[i++]; | 243 | return d - dest; |
244 | d++; | ||
234 | } | 245 | } |
235 | *dest = '\0'; | 246 | *d = '\0'; |
247 | return d - dest; | ||
236 | } | 248 | } |
237 | 249 | ||
238 | static char *copy_parsing_escapes(const char *string, int len) | 250 | static char *copy_parsing_escapes(const char *string, int len) |
@@ -243,9 +255,8 @@ static char *copy_parsing_escapes(const char *string, int len) | |||
243 | /* sed recognizes \n */ | 255 | /* sed recognizes \n */ |
244 | /* GNU sed also recognizes \t and \r */ | 256 | /* GNU sed also recognizes \t and \r */ |
245 | for (s = "\nn\tt\rr"; *s; s += 2) { | 257 | for (s = "\nn\tt\rr"; *s; s += 2) { |
246 | parse_escapes(dest, string, len, s[1], s[0]); | 258 | len = parse_escapes(dest, string, len, s[1], s[0]); |
247 | string = dest; | 259 | string = dest; |
248 | len = strlen(dest); | ||
249 | } | 260 | } |
250 | return dest; | 261 | return dest; |
251 | } | 262 | } |
@@ -471,7 +482,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) | |||
471 | */ | 482 | */ |
472 | static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | 483 | static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) |
473 | { | 484 | { |
474 | static const char cmd_letters[] = "saicrw:btTydDgGhHlnNpPqx={}"; | 485 | static const char cmd_letters[] ALIGN1 = "saicrw:btTydDgGhHlnNpPqx={}"; |
475 | enum { | 486 | enum { |
476 | IDX_s = 0, | 487 | IDX_s = 0, |
477 | IDX_a, | 488 | IDX_a, |
@@ -514,6 +525,8 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
514 | } | 525 | } |
515 | /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ | 526 | /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ |
516 | else if (idx <= IDX_c) { /* a,i,c */ | 527 | else if (idx <= IDX_c) { /* a,i,c */ |
528 | unsigned len; | ||
529 | |||
517 | if (idx < IDX_c) { /* a,i */ | 530 | if (idx < IDX_c) { /* a,i */ |
518 | if (sed_cmd->end_line || sed_cmd->end_match) | 531 | if (sed_cmd->end_line || sed_cmd->end_match) |
519 | bb_error_msg_and_die("command '%c' uses only one address", sed_cmd->cmd); | 532 | bb_error_msg_and_die("command '%c' uses only one address", sed_cmd->cmd); |
@@ -527,10 +540,11 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
527 | break; | 540 | break; |
528 | cmdstr++; | 541 | cmdstr++; |
529 | } | 542 | } |
530 | sed_cmd->string = xstrdup(cmdstr); | 543 | len = strlen(cmdstr); |
544 | sed_cmd->string = copy_parsing_escapes(cmdstr, len); | ||
545 | cmdstr += len; | ||
531 | /* "\anychar" -> "anychar" */ | 546 | /* "\anychar" -> "anychar" */ |
532 | parse_escapes(sed_cmd->string, sed_cmd->string, strlen(cmdstr), '\0', '\0'); | 547 | parse_escapes(sed_cmd->string, sed_cmd->string, -1, '\0', '\0'); |
533 | cmdstr += strlen(cmdstr); | ||
534 | } | 548 | } |
535 | /* handle file cmds: (r)ead */ | 549 | /* handle file cmds: (r)ead */ |
536 | else if (idx <= IDX_w) { /* r,w */ | 550 | else if (idx <= IDX_w) { /* r,w */ |
@@ -562,8 +576,8 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
562 | 576 | ||
563 | cmdstr += parse_regex_delim(cmdstr, &match, &replace)+1; | 577 | cmdstr += parse_regex_delim(cmdstr, &match, &replace)+1; |
564 | /* \n already parsed, but \delimiter needs unescaping. */ | 578 | /* \n already parsed, but \delimiter needs unescaping. */ |
565 | parse_escapes(match, match, strlen(match), i, i); | 579 | parse_escapes(match, match, -1, i, i); |
566 | parse_escapes(replace, replace, strlen(replace), i, i); | 580 | parse_escapes(replace, replace, -1, i, i); |
567 | 581 | ||
568 | sed_cmd->string = xzalloc((strlen(match) + 1) * 2); | 582 | sed_cmd->string = xzalloc((strlen(match) + 1) * 2); |
569 | for (i = 0; match[i] && replace[i]; i++) { | 583 | for (i = 0; match[i] && replace[i]; i++) { |
@@ -942,13 +956,22 @@ static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char l | |||
942 | *last_puts_char = lpc; | 956 | *last_puts_char = lpc; |
943 | } | 957 | } |
944 | 958 | ||
945 | static void flush_append(char *last_puts_char, char last_gets_char) | 959 | static void flush_append(char *last_puts_char) |
946 | { | 960 | { |
947 | char *data; | 961 | char *data; |
948 | 962 | ||
949 | /* Output appended lines. */ | 963 | /* Output appended lines. */ |
950 | while ((data = (char *)llist_pop(&G.append_head))) { | 964 | while ((data = (char *)llist_pop(&G.append_head)) != NULL) { |
951 | puts_maybe_newline(data, G.nonstdout, last_puts_char, last_gets_char); | 965 | /* Append command does not respect "nonterminated-ness" |
966 | * of last line. Try this: | ||
967 | * $ echo -n "woot" | sed -e '/woot/a woo' - | ||
968 | * woot | ||
969 | * woo | ||
970 | * (both lines are terminated with \n) | ||
971 | * Therefore we do not propagate "last_gets_char" here, | ||
972 | * pass '\n' instead: | ||
973 | */ | ||
974 | puts_maybe_newline(data, G.nonstdout, last_puts_char, '\n'); | ||
952 | free(data); | 975 | free(data); |
953 | } | 976 | } |
954 | } | 977 | } |
@@ -956,13 +979,13 @@ static void flush_append(char *last_puts_char, char last_gets_char) | |||
956 | /* Get next line of input from G.input_file_list, flushing append buffer and | 979 | /* Get next line of input from G.input_file_list, flushing append buffer and |
957 | * noting if we ran out of files without a newline on the last line we read. | 980 | * noting if we ran out of files without a newline on the last line we read. |
958 | */ | 981 | */ |
959 | static char *get_next_line(char *gets_char, char *last_puts_char, char last_gets_char) | 982 | static char *get_next_line(char *gets_char, char *last_puts_char) |
960 | { | 983 | { |
961 | char *temp = NULL; | 984 | char *temp = NULL; |
962 | int len; | 985 | int len; |
963 | char gc; | 986 | char gc; |
964 | 987 | ||
965 | flush_append(last_puts_char, last_gets_char); | 988 | flush_append(last_puts_char); |
966 | 989 | ||
967 | /* will be returned if last line in the file | 990 | /* will be returned if last line in the file |
968 | * doesn't end with either '\n' or '\0' */ | 991 | * doesn't end with either '\n' or '\0' */ |
@@ -1045,7 +1068,7 @@ static void process_files(void) | |||
1045 | int substituted; | 1068 | int substituted; |
1046 | 1069 | ||
1047 | /* Prime the pump */ | 1070 | /* Prime the pump */ |
1048 | next_line = get_next_line(&next_gets_char, &last_puts_char, '\n' /*last_gets_char*/); | 1071 | next_line = get_next_line(&next_gets_char, &last_puts_char); |
1049 | 1072 | ||
1050 | /* Go through every line in each file */ | 1073 | /* Go through every line in each file */ |
1051 | again: | 1074 | again: |
@@ -1059,7 +1082,7 @@ static void process_files(void) | |||
1059 | 1082 | ||
1060 | /* Read one line in advance so we can act on the last line, | 1083 | /* Read one line in advance so we can act on the last line, |
1061 | * the '$' address */ | 1084 | * the '$' address */ |
1062 | next_line = get_next_line(&next_gets_char, &last_puts_char, last_gets_char); | 1085 | next_line = get_next_line(&next_gets_char, &last_puts_char); |
1063 | linenum++; | 1086 | linenum++; |
1064 | 1087 | ||
1065 | /* For every line, go through all the commands */ | 1088 | /* For every line, go through all the commands */ |
@@ -1286,7 +1309,7 @@ static void process_files(void) | |||
1286 | free(pattern_space); | 1309 | free(pattern_space); |
1287 | pattern_space = next_line; | 1310 | pattern_space = next_line; |
1288 | last_gets_char = next_gets_char; | 1311 | last_gets_char = next_gets_char; |
1289 | next_line = get_next_line(&next_gets_char, &last_puts_char, last_gets_char); | 1312 | next_line = get_next_line(&next_gets_char, &last_puts_char); |
1290 | substituted = 0; | 1313 | substituted = 0; |
1291 | linenum++; | 1314 | linenum++; |
1292 | break; | 1315 | break; |
@@ -1322,7 +1345,7 @@ static void process_files(void) | |||
1322 | pattern_space[len] = '\n'; | 1345 | pattern_space[len] = '\n'; |
1323 | strcpy(pattern_space + len+1, next_line); | 1346 | strcpy(pattern_space + len+1, next_line); |
1324 | last_gets_char = next_gets_char; | 1347 | last_gets_char = next_gets_char; |
1325 | next_line = get_next_line(&next_gets_char, &last_puts_char, last_gets_char); | 1348 | next_line = get_next_line(&next_gets_char, &last_puts_char); |
1326 | linenum++; | 1349 | linenum++; |
1327 | break; | 1350 | break; |
1328 | } | 1351 | } |
@@ -1426,7 +1449,7 @@ static void process_files(void) | |||
1426 | 1449 | ||
1427 | /* Delete and such jump here. */ | 1450 | /* Delete and such jump here. */ |
1428 | discard_line: | 1451 | discard_line: |
1429 | flush_append(&last_puts_char, last_gets_char); | 1452 | flush_append(&last_puts_char /*,last_gets_char*/); |
1430 | free(pattern_space); | 1453 | free(pattern_space); |
1431 | 1454 | ||
1432 | goto again; | 1455 | goto again; |
@@ -1512,12 +1535,12 @@ int sed_main(int argc UNUSED_PARAM, char **argv) | |||
1512 | while (opt_f) { // -f | 1535 | while (opt_f) { // -f |
1513 | char *line; | 1536 | char *line; |
1514 | FILE *cmdfile; | 1537 | FILE *cmdfile; |
1515 | cmdfile = xfopen_for_read(llist_pop(&opt_f)); | 1538 | cmdfile = xfopen_stdin(llist_pop(&opt_f)); |
1516 | while ((line = xmalloc_fgetline(cmdfile)) != NULL) { | 1539 | while ((line = xmalloc_fgetline(cmdfile)) != NULL) { |
1517 | add_cmd(line); | 1540 | add_cmd(line); |
1518 | free(line); | 1541 | free(line); |
1519 | } | 1542 | } |
1520 | fclose(cmdfile); | 1543 | fclose_if_not_stdin(cmdfile); |
1521 | } | 1544 | } |
1522 | /* if we didn't get a pattern from -e or -f, use argv[0] */ | 1545 | /* if we didn't get a pattern from -e or -f, use argv[0] */ |
1523 | if (!(opt & 0x30)) { | 1546 | if (!(opt & 0x30)) { |
diff --git a/editors/vi.c b/editors/vi.c index 75ce8d396..243676d5f 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -251,7 +251,7 @@ enum { | |||
251 | // cmds modifying text[] | 251 | // cmds modifying text[] |
252 | // vda: removed "aAiIs" as they switch us into insert mode | 252 | // vda: removed "aAiIs" as they switch us into insert mode |
253 | // and remembering input for replay after them makes no sense | 253 | // and remembering input for replay after them makes no sense |
254 | static const char modifying_cmds[] = "cCdDJoOpPrRxX<>~"; | 254 | static const char modifying_cmds[] ALIGN1 = "cCdDJoOpPrRxX<>~"; |
255 | #endif | 255 | #endif |
256 | 256 | ||
257 | enum { | 257 | enum { |