summaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-02-12 08:43:06 +0000
committerRon Yorston <rmy@pobox.com>2019-02-12 08:43:06 +0000
commit7a8bd5ae33d8c390763f0787afe6b8c495e2d978 (patch)
tree29b0abb320d73b37f4fa4d9b355b3b32db42e836 /editors
parent0eda390d68c456975289471e68b615ae096ab33b (diff)
parentf81e0120f4478c58e126bcadb19b9954ed184e8f (diff)
downloadbusybox-w32-7a8bd5ae33d8c390763f0787afe6b8c495e2d978.tar.gz
busybox-w32-7a8bd5ae33d8c390763f0787afe6b8c495e2d978.tar.bz2
busybox-w32-7a8bd5ae33d8c390763f0787afe6b8c495e2d978.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'editors')
-rw-r--r--editors/awk.c41
-rw-r--r--editors/sed.c30
-rw-r--r--editors/vi.c78
3 files changed, 77 insertions, 72 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 86cd9a289..dbb26068d 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -275,18 +275,21 @@ typedef struct tsplitter_s {
275 | TC_STRING | TC_NUMBER | TC_UOPPOST) 275 | TC_STRING | TC_NUMBER | TC_UOPPOST)
276#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE) 276#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
277 277
278#define OF_RES1 0x010000 278#define OF_RES1 0x010000
279#define OF_RES2 0x020000 279#define OF_RES2 0x020000
280#define OF_STR1 0x040000 280#define OF_STR1 0x040000
281#define OF_STR2 0x080000 281#define OF_STR2 0x080000
282#define OF_NUM1 0x100000 282#define OF_NUM1 0x100000
283#define OF_CHECKED 0x200000 283#define OF_CHECKED 0x200000
284#define OF_REQUIRED 0x400000
285
284 286
285/* combined operator flags */ 287/* combined operator flags */
286#define xx 0 288#define xx 0
287#define xV OF_RES2 289#define xV OF_RES2
288#define xS (OF_RES2 | OF_STR2) 290#define xS (OF_RES2 | OF_STR2)
289#define Vx OF_RES1 291#define Vx OF_RES1
292#define Rx (OF_RES1 | OF_NUM1 | OF_REQUIRED)
290#define VV (OF_RES1 | OF_RES2) 293#define VV (OF_RES1 | OF_RES2)
291#define Nx (OF_RES1 | OF_NUM1) 294#define Nx (OF_RES1 | OF_NUM1)
292#define NV (OF_RES1 | OF_NUM1 | OF_RES2) 295#define NV (OF_RES1 | OF_NUM1 | OF_RES2)
@@ -425,7 +428,7 @@ static const uint32_t tokeninfo[] = {
425 0, 428 0,
426 0, /* \n */ 429 0, /* \n */
427 ST_IF, ST_DO, ST_FOR, OC_BREAK, 430 ST_IF, ST_DO, ST_FOR, OC_BREAK,
428 OC_CONTINUE, OC_DELETE|Vx, OC_PRINT, 431 OC_CONTINUE, OC_DELETE|Rx, OC_PRINT,
429 OC_PRINTF, OC_NEXT, OC_NEXTFILE, 432 OC_PRINTF, OC_NEXT, OC_NEXTFILE,
430 OC_RETURN|Vx, OC_EXIT|Nx, 433 OC_RETURN|Vx, OC_EXIT|Nx,
431 ST_WHILE, 434 ST_WHILE,
@@ -593,7 +596,7 @@ static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string";
593static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token"; 596static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token";
594static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero"; 597static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero";
595static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier"; 598static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier";
596static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin"; 599static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments";
597static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array"; 600static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array";
598static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error"; 601static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
599static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function"; 602static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
@@ -1269,7 +1272,7 @@ static node *parse_expr(uint32_t iexp)
1269 debug_printf_parse("%s(%x)\n", __func__, iexp); 1272 debug_printf_parse("%s(%x)\n", __func__, iexp);
1270 1273
1271 sn.info = PRIMASK; 1274 sn.info = PRIMASK;
1272 sn.r.n = glptr = NULL; 1275 sn.r.n = sn.a.n = glptr = NULL;
1273 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; 1276 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
1274 1277
1275 while (!((tc = next_token(xtc)) & iexp)) { 1278 while (!((tc = next_token(xtc)) & iexp)) {
@@ -1291,6 +1294,7 @@ static node *parse_expr(uint32_t iexp)
1291 || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON)) 1294 || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON))
1292 ) { 1295 ) {
1293 vn = vn->a.n; 1296 vn = vn->a.n;
1297 if (!vn->a.n) syntax_error(EMSG_UNEXP_TOKEN);
1294 } 1298 }
1295 if ((t_info & OPCLSMASK) == OC_TERNARY) 1299 if ((t_info & OPCLSMASK) == OC_TERNARY)
1296 t_info += P(6); 1300 t_info += P(6);
@@ -1429,7 +1433,11 @@ static void chain_expr(uint32_t info)
1429 node *n; 1433 node *n;
1430 1434
1431 n = chain_node(info); 1435 n = chain_node(info);
1436
1432 n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM); 1437 n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM);
1438 if ((info & OF_REQUIRED) && !n->l.n)
1439 syntax_error(EMSG_TOO_FEW_ARGS);
1440
1433 if (t_tclass & TC_GRPTERM) 1441 if (t_tclass & TC_GRPTERM)
1434 rollback_token(); 1442 rollback_token();
1435} 1443}
@@ -1609,12 +1617,25 @@ static void parse_program(char *p)
1609 f = newfunc(t_string); 1617 f = newfunc(t_string);
1610 f->body.first = NULL; 1618 f->body.first = NULL;
1611 f->nargs = 0; 1619 f->nargs = 0;
1612 while (next_token(TC_VARIABLE | TC_SEQTERM) & TC_VARIABLE) { 1620 /* Match func arg list: a comma sep list of >= 0 args, and a close paren */
1621 while (next_token(TC_VARIABLE | TC_SEQTERM | TC_COMMA)) {
1622 /* Either an empty arg list, or trailing comma from prev iter
1623 * must be followed by an arg */
1624 if (f->nargs == 0 && t_tclass == TC_SEQTERM)
1625 break;
1626
1627 /* TC_SEQSTART/TC_COMMA must be followed by TC_VARIABLE */
1628 if (t_tclass != TC_VARIABLE)
1629 syntax_error(EMSG_UNEXP_TOKEN);
1630
1613 v = findvar(ahash, t_string); 1631 v = findvar(ahash, t_string);
1614 v->x.aidx = f->nargs++; 1632 v->x.aidx = f->nargs++;
1615 1633
1634 /* Arg followed either by end of arg list or 1 comma */
1616 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM) 1635 if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
1617 break; 1636 break;
1637 if (t_tclass != TC_COMMA)
1638 syntax_error(EMSG_UNEXP_TOKEN);
1618 } 1639 }
1619 seq = &f->body; 1640 seq = &f->body;
1620 chain_group(); 1641 chain_group();
diff --git a/editors/sed.c b/editors/sed.c
index fd56e0e7f..a5cedbd8d 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -377,25 +377,25 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex)
377/* Grab a filename. Whitespace at start is skipped, then goes to EOL. */ 377/* Grab a filename. Whitespace at start is skipped, then goes to EOL. */
378static int parse_file_cmd(/*sed_cmd_t *sed_cmd,*/ const char *filecmdstr, char **retval) 378static int parse_file_cmd(/*sed_cmd_t *sed_cmd,*/ const char *filecmdstr, char **retval)
379{ 379{
380 int start = 0, idx, hack = 0; 380 const char *start;
381 const char *eol;
381 382
382 /* Skip whitespace, then grab filename to end of line */ 383 /* Skip whitespace, then grab filename to end of line */
383 while (isspace(filecmdstr[start])) 384 start = skip_whitespace(filecmdstr);
384 start++; 385 eol = strchrnul(start, '\n');
385 idx = start; 386 if (eol == start)
386 while (filecmdstr[idx] && filecmdstr[idx] != '\n')
387 idx++;
388
389 /* If lines glued together, put backslash back. */
390 if (filecmdstr[idx] == '\n')
391 hack = 1;
392 if (idx == start)
393 bb_error_msg_and_die("empty filename"); 387 bb_error_msg_and_die("empty filename");
394 *retval = xstrndup(filecmdstr+start, idx-start+hack+1);
395 if (hack)
396 (*retval)[idx] = '\\';
397 388
398 return idx; 389 if (*eol) {
390 /* If lines glued together, put backslash back. */
391 *retval = xstrndup(start, eol-start + 1);
392 (*retval)[eol-start] = '\\';
393 } else {
394 /* eol is NUL */
395 *retval = xstrdup(start);
396 }
397
398 return eol - filecmdstr;
399} 399}
400 400
401static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) 401static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
diff --git a/editors/vi.c b/editors/vi.c
index 3c758cca0..a46339813 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -600,6 +600,7 @@ static void check_context(char); // remember context for '' command
600#if ENABLE_FEATURE_VI_UNDO 600#if ENABLE_FEATURE_VI_UNDO
601static void flush_undo_data(void); 601static void flush_undo_data(void);
602static void undo_push(char *, unsigned int, unsigned char); // Push an operation on the undo stack 602static void undo_push(char *, unsigned int, unsigned char); // Push an operation on the undo stack
603static void undo_push_insert(char *, int, int); // convenience function
603static void undo_pop(void); // Undo the last operation 604static void undo_pop(void); // Undo the last operation
604# if ENABLE_FEATURE_VI_UNDO_QUEUE 605# if ENABLE_FEATURE_VI_UNDO_QUEUE
605static void undo_queue_commit(void); // Flush any queued objects to the undo stack 606static void undo_queue_commit(void); // Flush any queued objects to the undo stack
@@ -2013,19 +2014,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2013 c = get_one_char(); 2014 c = get_one_char();
2014 *p = c; 2015 *p = c;
2015#if ENABLE_FEATURE_VI_UNDO 2016#if ENABLE_FEATURE_VI_UNDO
2016 switch (undo) { 2017 undo_push_insert(p, 1, undo);
2017 case ALLOW_UNDO:
2018 undo_push(p, 1, UNDO_INS);
2019 break;
2020 case ALLOW_UNDO_CHAIN:
2021 undo_push(p, 1, UNDO_INS_CHAIN);
2022 break;
2023# if ENABLE_FEATURE_VI_UNDO_QUEUE
2024 case ALLOW_UNDO_QUEUED:
2025 undo_push(p, 1, UNDO_INS_QUEUED);
2026 break;
2027# endif
2028 }
2029#else 2018#else
2030 modified_count++; 2019 modified_count++;
2031#endif /* ENABLE_FEATURE_VI_UNDO */ 2020#endif /* ENABLE_FEATURE_VI_UNDO */
@@ -2053,19 +2042,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2053 if (c == '\n') 2042 if (c == '\n')
2054 undo_queue_commit(); 2043 undo_queue_commit();
2055# endif 2044# endif
2056 switch (undo) { 2045 undo_push_insert(p, 1, undo);
2057 case ALLOW_UNDO:
2058 undo_push(p, 1, UNDO_INS);
2059 break;
2060 case ALLOW_UNDO_CHAIN:
2061 undo_push(p, 1, UNDO_INS_CHAIN);
2062 break;
2063# if ENABLE_FEATURE_VI_UNDO_QUEUE
2064 case ALLOW_UNDO_QUEUED:
2065 undo_push(p, 1, UNDO_INS_QUEUED);
2066 break;
2067# endif
2068 }
2069#else 2046#else
2070 modified_count++; 2047 modified_count++;
2071#endif /* ENABLE_FEATURE_VI_UNDO */ 2048#endif /* ENABLE_FEATURE_VI_UNDO */
@@ -2085,7 +2062,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
2085 p += bias; 2062 p += bias;
2086 q += bias; 2063 q += bias;
2087#if ENABLE_FEATURE_VI_UNDO 2064#if ENABLE_FEATURE_VI_UNDO
2088 undo_push(p, len, UNDO_INS); 2065 undo_push_insert(p, len, undo);
2089#endif 2066#endif
2090 memcpy(p, q, len); 2067 memcpy(p, q, len);
2091 p += len; 2068 p += len;
@@ -2339,16 +2316,18 @@ static void undo_push(char *src, unsigned int length, uint8_t u_type) // Add to
2339 } 2316 }
2340 break; 2317 break;
2341 case UNDO_INS_QUEUED: 2318 case UNDO_INS_QUEUED:
2342 if (length != 1) 2319 if (length < 1)
2343 return; 2320 return;
2344 switch (undo_queue_state) { 2321 switch (undo_queue_state) {
2345 case UNDO_EMPTY: 2322 case UNDO_EMPTY:
2346 undo_queue_state = UNDO_INS; 2323 undo_queue_state = UNDO_INS;
2347 undo_queue_spos = src; 2324 undo_queue_spos = src;
2348 case UNDO_INS: 2325 case UNDO_INS:
2349 undo_q++; // Don't need to save any data for insertions 2326 while (length--) {
2350 if (undo_q == CONFIG_FEATURE_VI_UNDO_QUEUE_MAX) 2327 undo_q++; // Don't need to save any data for insertions
2351 undo_queue_commit(); 2328 if (undo_q == CONFIG_FEATURE_VI_UNDO_QUEUE_MAX)
2329 undo_queue_commit();
2330 }
2352 return; 2331 return;
2353 case UNDO_DEL: 2332 case UNDO_DEL:
2354 // Switch from storing deleted text to inserted text 2333 // Switch from storing deleted text to inserted text
@@ -2394,6 +2373,23 @@ static void undo_push(char *src, unsigned int length, uint8_t u_type) // Add to
2394 modified_count++; 2373 modified_count++;
2395} 2374}
2396 2375
2376static void undo_push_insert(char *p, int len, int undo)
2377{
2378 switch (undo) {
2379 case ALLOW_UNDO:
2380 undo_push(p, len, UNDO_INS);
2381 break;
2382 case ALLOW_UNDO_CHAIN:
2383 undo_push(p, len, UNDO_INS_CHAIN);
2384 break;
2385# if ENABLE_FEATURE_VI_UNDO_QUEUE
2386 case ALLOW_UNDO_QUEUED:
2387 undo_push(p, len, UNDO_INS_QUEUED);
2388 break;
2389# endif
2390 }
2391}
2392
2397static void undo_pop(void) // Undo the last operation 2393static void undo_pop(void) // Undo the last operation
2398{ 2394{
2399 int repeat; 2395 int repeat;
@@ -2667,14 +2663,7 @@ static uintptr_t string_insert(char *p, const char *s, int undo) // insert the s
2667 2663
2668 i = strlen(s); 2664 i = strlen(s);
2669#if ENABLE_FEATURE_VI_UNDO 2665#if ENABLE_FEATURE_VI_UNDO
2670 switch (undo) { 2666 undo_push_insert(p, i, undo);
2671 case ALLOW_UNDO:
2672 undo_push(p, i, UNDO_INS);
2673 break;
2674 case ALLOW_UNDO_CHAIN:
2675 undo_push(p, i, UNDO_INS_CHAIN);
2676 break;
2677 }
2678#endif 2667#endif
2679 bias = text_hole_make(p, i); 2668 bias = text_hole_make(p, i);
2680 p += bias; 2669 p += bias;
@@ -4263,14 +4252,9 @@ static void do_cmd(int c)
4263 case 'r': // r- replace the current char with user input 4252 case 'r': // r- replace the current char with user input
4264 c1 = get_one_char(); // get the replacement char 4253 c1 = get_one_char(); // get the replacement char
4265 if (*dot != '\n') { 4254 if (*dot != '\n') {
4266#if ENABLE_FEATURE_VI_UNDO 4255 dot = text_hole_delete(dot, dot, ALLOW_UNDO);
4267 undo_push(dot, 1, UNDO_DEL); 4256 dot = char_insert(dot, c1, ALLOW_UNDO_CHAIN);
4268 *dot = c1; 4257 dot_left();
4269 undo_push(dot, 1, UNDO_INS_CHAIN);
4270#else
4271 *dot = c1;
4272 modified_count++;
4273#endif
4274 } 4258 }
4275 end_cmd_q(); // stop adding to q 4259 end_cmd_q(); // stop adding to q
4276 break; 4260 break;