aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to 'editors')
-rw-r--r--editors/diff.c2
-rw-r--r--editors/ed.c6
-rw-r--r--editors/sed.c77
-rw-r--r--editors/vi.c2
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
27typedef struct LINE { 28typedef 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
37enum { 38enum {
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
219static void parse_escapes(char *dest, const char *string, int len, char from, char to) 221static 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
238static char *copy_parsing_escapes(const char *string, int len) 250static 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 */
472static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) 483static 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
945static void flush_append(char *last_puts_char, char last_gets_char) 959static 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 */
959static char *get_next_line(char *gets_char, char *last_puts_char, char last_gets_char) 982static 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
254static const char modifying_cmds[] = "cCdDJoOpPrRxX<>~"; 254static const char modifying_cmds[] ALIGN1 = "cCdDJoOpPrRxX<>~";
255#endif 255#endif
256 256
257enum { 257enum {