aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to 'editors')
-rw-r--r--editors/awk.c132
-rw-r--r--editors/patch.c14
-rw-r--r--editors/patch_toybox.c4
3 files changed, 91 insertions, 59 deletions
diff --git a/editors/awk.c b/editors/awk.c
index f47d1ab02..2245cad03 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -17,10 +17,14 @@
17/* If you comment out one of these below, it will be #defined later 17/* If you comment out one of these below, it will be #defined later
18 * to perform debug printfs to stderr: */ 18 * to perform debug printfs to stderr: */
19#define debug_printf_walker(...) do {} while (0) 19#define debug_printf_walker(...) do {} while (0)
20#define debug_printf_eval(...) do {} while (0)
20 21
21#ifndef debug_printf_walker 22#ifndef debug_printf_walker
22# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) 23# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__))
23#endif 24#endif
25#ifndef debug_printf_eval
26# define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__))
27#endif
24 28
25 29
26 30
@@ -700,14 +704,27 @@ static ALWAYS_INLINE int isalnum_(int c)
700 704
701static double my_strtod(char **pp) 705static double my_strtod(char **pp)
702{ 706{
707 char *cp = *pp;
703#if ENABLE_DESKTOP 708#if ENABLE_DESKTOP
704 if ((*pp)[0] == '0' 709 if (cp[0] == '0') {
705 && ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1])) 710 /* Might be hex or octal integer: 0x123abc or 07777 */
706 ) { 711 char c = (cp[1] | 0x20);
707 return strtoull(*pp, pp, 0); 712 if (c == 'x' || isdigit(cp[1])) {
713 unsigned long long ull = strtoull(cp, pp, 0);
714 if (c == 'x')
715 return ull;
716 c = **pp;
717 if (!isdigit(c) && c != '.')
718 return ull;
719 /* else: it may be a floating number. Examples:
720 * 009.123 (*pp points to '9')
721 * 000.123 (*pp points to '.')
722 * fall through to strtod.
723 */
724 }
708 } 725 }
709#endif 726#endif
710 return strtod(*pp, pp); 727 return strtod(cp, pp);
711} 728}
712 729
713/* -------- working with variables (set/get/copy/etc) -------- */ 730/* -------- working with variables (set/get/copy/etc) -------- */
@@ -817,17 +834,21 @@ static double getvar_i(var *v)
817 v->number = 0; 834 v->number = 0;
818 s = v->string; 835 s = v->string;
819 if (s && *s) { 836 if (s && *s) {
837 debug_printf_eval("getvar_i: '%s'->", s);
820 v->number = my_strtod(&s); 838 v->number = my_strtod(&s);
839 debug_printf_eval("%f (s:'%s')\n", v->number, s);
821 if (v->type & VF_USER) { 840 if (v->type & VF_USER) {
822 s = skip_spaces(s); 841 s = skip_spaces(s);
823 if (*s != '\0') 842 if (*s != '\0')
824 v->type &= ~VF_USER; 843 v->type &= ~VF_USER;
825 } 844 }
826 } else { 845 } else {
846 debug_printf_eval("getvar_i: '%s'->zero\n", s);
827 v->type &= ~VF_USER; 847 v->type &= ~VF_USER;
828 } 848 }
829 v->type |= VF_CACHED; 849 v->type |= VF_CACHED;
830 } 850 }
851 debug_printf_eval("getvar_i: %f\n", v->number);
831 return v->number; 852 return v->number;
832} 853}
833 854
@@ -849,6 +870,7 @@ static var *copyvar(var *dest, const var *src)
849 if (dest != src) { 870 if (dest != src) {
850 clrvar(dest); 871 clrvar(dest);
851 dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR)); 872 dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR));
873 debug_printf_eval("copyvar: number:%f string:'%s'\n", src->number, src->string);
852 dest->number = src->number; 874 dest->number = src->number;
853 if (src->string) 875 if (src->string)
854 dest->string = xstrdup(src->string); 876 dest->string = xstrdup(src->string);
@@ -965,7 +987,6 @@ static uint32_t next_token(uint32_t expected)
965 const char *tl; 987 const char *tl;
966 uint32_t tc; 988 uint32_t tc;
967 const uint32_t *ti; 989 const uint32_t *ti;
968 int l;
969 990
970 if (t_rollback) { 991 if (t_rollback) {
971 t_rollback = FALSE; 992 t_rollback = FALSE;
@@ -1031,7 +1052,7 @@ static uint32_t next_token(uint32_t expected)
1031 char *pp = p; 1052 char *pp = p;
1032 t_double = my_strtod(&pp); 1053 t_double = my_strtod(&pp);
1033 p = pp; 1054 p = pp;
1034 if (*pp == '.') 1055 if (*p == '.')
1035 syntax_error(EMSG_UNEXP_TOKEN); 1056 syntax_error(EMSG_UNEXP_TOKEN);
1036 tc = TC_NUMBER; 1057 tc = TC_NUMBER;
1037 1058
@@ -1041,52 +1062,51 @@ static uint32_t next_token(uint32_t expected)
1041 tc = 0x00000001; 1062 tc = 0x00000001;
1042 ti = tokeninfo; 1063 ti = tokeninfo;
1043 while (*tl) { 1064 while (*tl) {
1044 l = *tl++; 1065 int l = (unsigned char) *tl++;
1045 if (l == NTCC) { 1066 if (l == (unsigned char) NTCC) {
1046 tc <<= 1; 1067 tc <<= 1;
1047 continue; 1068 continue;
1048 } 1069 }
1049 /* if token class is expected, token 1070 /* if token class is expected,
1050 * matches and it's not a longer word, 1071 * token matches,
1051 * then this is what we are looking for 1072 * and it's not a longer word,
1052 */ 1073 */
1053 if ((tc & (expected | TC_WORD | TC_NEWLINE)) 1074 if ((tc & (expected | TC_WORD | TC_NEWLINE))
1054 && *tl == *p && strncmp(p, tl, l) == 0 1075 && strncmp(p, tl, l) == 0
1055 && !((tc & TC_WORD) && isalnum_(p[l])) 1076 && !((tc & TC_WORD) && isalnum_(p[l]))
1056 ) { 1077 ) {
1078 /* then this is what we are looking for */
1057 t_info = *ti; 1079 t_info = *ti;
1058 p += l; 1080 p += l;
1059 break; 1081 goto token_found;
1060 } 1082 }
1061 ti++; 1083 ti++;
1062 tl += l; 1084 tl += l;
1063 } 1085 }
1064 1086 /* not a known token */
1065 if (!*tl) { 1087
1066 /* it's a name (var/array/function), 1088 /* is it a name? (var/array/function) */
1067 * otherwise it's something wrong 1089 if (!isalnum_(*p))
1068 */ 1090 syntax_error(EMSG_UNEXP_TOKEN); /* no */
1069 if (!isalnum_(*p)) 1091 /* yes */
1070 syntax_error(EMSG_UNEXP_TOKEN); 1092 t_string = --p;
1071 1093 while (isalnum_(*++p)) {
1072 t_string = --p; 1094 p[-1] = *p;
1073 while (isalnum_(*++p)) { 1095 }
1074 p[-1] = *p; 1096 p[-1] = '\0';
1075 } 1097 tc = TC_VARIABLE;
1076 p[-1] = '\0'; 1098 /* also consume whitespace between functionname and bracket */
1077 tc = TC_VARIABLE; 1099 if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY))
1078 /* also consume whitespace between functionname and bracket */ 1100 p = skip_spaces(p);
1079 if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY)) 1101 if (*p == '(') {
1080 p = skip_spaces(p); 1102 tc = TC_FUNCTION;
1081 if (*p == '(') { 1103 } else {
1082 tc = TC_FUNCTION; 1104 if (*p == '[') {
1083 } else { 1105 p++;
1084 if (*p == '[') { 1106 tc = TC_ARRAY;
1085 p++;
1086 tc = TC_ARRAY;
1087 }
1088 } 1107 }
1089 } 1108 }
1109 token_found: ;
1090 } 1110 }
1091 g_pos = p; 1111 g_pos = p;
1092 1112
@@ -1164,6 +1184,7 @@ static node *parse_expr(uint32_t iexp)
1164 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; 1184 xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
1165 1185
1166 while (!((tc = next_token(xtc)) & iexp)) { 1186 while (!((tc = next_token(xtc)) & iexp)) {
1187
1167 if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { 1188 if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
1168 /* input redirection (<) attached to glptr node */ 1189 /* input redirection (<) attached to glptr node */
1169 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); 1190 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
@@ -1500,10 +1521,10 @@ static node *mk_splitter(const char *s, tsplitter *spl)
1500 regfree(re); 1521 regfree(re);
1501 regfree(ire); // TODO: nuke ire, use re+1? 1522 regfree(ire); // TODO: nuke ire, use re+1?
1502 } 1523 }
1503 if (strlen(s) > 1) { 1524 if (s[0] && s[1]) { /* strlen(s) > 1 */
1504 mk_re_node(s, n, re); 1525 mk_re_node(s, n, re);
1505 } else { 1526 } else {
1506 n->info = (uint32_t) *s; 1527 n->info = (uint32_t) s[0];
1507 } 1528 }
1508 1529
1509 return n; 1530 return n;
@@ -1560,24 +1581,22 @@ static void fsrealloc(int size)
1560 if (size >= maxfields) { 1581 if (size >= maxfields) {
1561 i = maxfields; 1582 i = maxfields;
1562 maxfields = size + 16; 1583 maxfields = size + 16;
1563 Fields = xrealloc(Fields, maxfields * sizeof(var)); 1584 Fields = xrealloc(Fields, maxfields * sizeof(Fields[0]));
1564 for (; i < maxfields; i++) { 1585 for (; i < maxfields; i++) {
1565 Fields[i].type = VF_SPECIAL; 1586 Fields[i].type = VF_SPECIAL;
1566 Fields[i].string = NULL; 1587 Fields[i].string = NULL;
1567 } 1588 }
1568 } 1589 }
1569 1590 /* if size < nfields, clear extra field variables */
1570 if (size < nfields) { 1591 for (i = size; i < nfields; i++) {
1571 for (i = size; i < nfields; i++) { 1592 clrvar(Fields + i);
1572 clrvar(Fields + i);
1573 }
1574 } 1593 }
1575 nfields = size; 1594 nfields = size;
1576} 1595}
1577 1596
1578static int awk_split(const char *s, node *spl, char **slist) 1597static int awk_split(const char *s, node *spl, char **slist)
1579{ 1598{
1580 int l, n = 0; 1599 int l, n;
1581 char c[4]; 1600 char c[4];
1582 char *s1; 1601 char *s1;
1583 regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... 1602 regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
@@ -1591,6 +1610,7 @@ static int awk_split(const char *s, node *spl, char **slist)
1591 if (*getvar_s(intvar[RS]) == '\0') 1610 if (*getvar_s(intvar[RS]) == '\0')
1592 c[2] = '\n'; 1611 c[2] = '\n';
1593 1612
1613 n = 0;
1594 if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */ 1614 if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */
1595 if (!*s) 1615 if (!*s)
1596 return n; /* "": zero fields */ 1616 return n; /* "": zero fields */
@@ -1636,7 +1656,7 @@ static int awk_split(const char *s, node *spl, char **slist)
1636 } 1656 }
1637 if (*s1) 1657 if (*s1)
1638 n++; 1658 n++;
1639 while ((s1 = strpbrk(s1, c))) { 1659 while ((s1 = strpbrk(s1, c)) != NULL) {
1640 *s1++ = '\0'; 1660 *s1++ = '\0';
1641 n++; 1661 n++;
1642 } 1662 }
@@ -2347,18 +2367,25 @@ static var *evaluate(node *op, var *res)
2347 opn = (opinfo & OPNMASK); 2367 opn = (opinfo & OPNMASK);
2348 g_lineno = op->lineno; 2368 g_lineno = op->lineno;
2349 op1 = op->l.n; 2369 op1 = op->l.n;
2370 debug_printf_eval("opinfo:%08x opn:%08x XC:%x\n", opinfo, opn, XC(opinfo & OPCLSMASK));
2350 2371
2351 /* execute inevitable things */ 2372 /* execute inevitable things */
2352 if (opinfo & OF_RES1) 2373 if (opinfo & OF_RES1)
2353 L.v = evaluate(op1, v1); 2374 L.v = evaluate(op1, v1);
2354 if (opinfo & OF_RES2) 2375 if (opinfo & OF_RES2)
2355 R.v = evaluate(op->r.n, v1+1); 2376 R.v = evaluate(op->r.n, v1+1);
2356 if (opinfo & OF_STR1) 2377 if (opinfo & OF_STR1) {
2357 L.s = getvar_s(L.v); 2378 L.s = getvar_s(L.v);
2358 if (opinfo & OF_STR2) 2379 debug_printf_eval("L.s:'%s'\n", L.s);
2380 }
2381 if (opinfo & OF_STR2) {
2359 R.s = getvar_s(R.v); 2382 R.s = getvar_s(R.v);
2360 if (opinfo & OF_NUM1) 2383 debug_printf_eval("R.s:'%s'\n", R.s);
2384 }
2385 if (opinfo & OF_NUM1) {
2361 L_d = getvar_i(L.v); 2386 L_d = getvar_i(L.v);
2387 debug_printf_eval("L_d:%f\n", L_d);
2388 }
2362 2389
2363 switch (XC(opinfo & OPCLSMASK)) { 2390 switch (XC(opinfo & OPCLSMASK)) {
2364 2391
@@ -2526,6 +2553,7 @@ static var *evaluate(node *op, var *res)
2526 break; 2553 break;
2527 2554
2528 case XC( OC_MOVE ): 2555 case XC( OC_MOVE ):
2556 debug_printf_eval("MOVE\n");
2529 /* if source is a temporary string, jusk relink it to dest */ 2557 /* if source is a temporary string, jusk relink it to dest */
2530//Disabled: if R.v is numeric but happens to have cached R.v->string, 2558//Disabled: if R.v is numeric but happens to have cached R.v->string,
2531//then L.v ends up being a string, which is wrong 2559//then L.v ends up being a string, which is wrong
@@ -2777,6 +2805,7 @@ static var *evaluate(node *op, var *res)
2777 case XC( OC_BINARY ): 2805 case XC( OC_BINARY ):
2778 case XC( OC_REPLACE ): { 2806 case XC( OC_REPLACE ): {
2779 double R_d = getvar_i(R.v); 2807 double R_d = getvar_i(R.v);
2808 debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn);
2780 switch (opn) { 2809 switch (opn) {
2781 case '+': 2810 case '+':
2782 L_d += R_d; 2811 L_d += R_d;
@@ -2805,6 +2834,7 @@ static var *evaluate(node *op, var *res)
2805 L_d -= (int)(L_d / R_d) * R_d; 2834 L_d -= (int)(L_d / R_d) * R_d;
2806 break; 2835 break;
2807 } 2836 }
2837 debug_printf_eval("BINARY/REPLACE result:%f\n", L_d);
2808 res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d); 2838 res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d);
2809 break; 2839 break;
2810 } 2840 }
diff --git a/editors/patch.c b/editors/patch.c
index c40f54155..66a9474fe 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -344,14 +344,12 @@ static int apply_one_hunk(void)
344 while (plist && *plist->data == "+-"[reverse]) { 344 while (plist && *plist->data == "+-"[reverse]) {
345 if (data && !strcmp(data, plist->data+1)) { 345 if (data && !strcmp(data, plist->data+1)) {
346 if (!backwarn) { 346 if (!backwarn) {
347 backwarn++; 347 backwarn = TT.linenum;
348 if (option_mask32 & FLAG_IGNORE) { 348 if (option_mask32 & FLAG_IGNORE) {
349 dummy_revert = 1; 349 dummy_revert = 1;
350 reverse ^= 1; 350 reverse ^= 1;
351 continue; 351 continue;
352 } 352 }
353 fdprintf(2,"Possibly reversed hunk %d at %ld\n",
354 TT.hunknum, TT.linenum);
355 } 353 }
356 } 354 }
357 plist = plist->next; 355 plist = plist->next;
@@ -364,6 +362,10 @@ static int apply_one_hunk(void)
364 // Does this hunk need to match EOF? 362 // Does this hunk need to match EOF?
365 if (!plist && matcheof) break; 363 if (!plist && matcheof) break;
366 364
365 if (backwarn)
366 fdprintf(2,"Possibly reversed hunk %d at %ld\n",
367 TT.hunknum, TT.linenum);
368
367 // File ended before we found a place for this hunk. 369 // File ended before we found a place for this hunk.
368 fail_hunk(); 370 fail_hunk();
369 goto done; 371 goto done;
@@ -552,7 +554,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
552 int oldsum, newsum, del = 0; 554 int oldsum, newsum, del = 0;
553 char *name; 555 char *name;
554 556
555 oldsum = TT.oldline + TT.oldlen; 557 oldsum = TT.oldline + TT.oldlen;
556 newsum = TT.newline + TT.newlen; 558 newsum = TT.newline + TT.newlen;
557 559
558 name = reverse ? oldname : newname; 560 name = reverse ? oldname : newname;
@@ -589,10 +591,10 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
589 xmkpath(name, -1); 591 xmkpath(name, -1);
590 *s = '/'; 592 *s = '/';
591 } 593 }
592 TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); 594 TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR);
593 } else { 595 } else {
594 printf("patching file %s\n", name); 596 printf("patching file %s\n", name);
595 TT.filein = xopen(name, O_RDWR); 597 TT.filein = xopen(name, O_RDONLY);
596 } 598 }
597 TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); 599 TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname);
598 TT.linenum = 0; 600 TT.linenum = 0;
diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c
index 7f3234e66..a60bf070f 100644
--- a/editors/patch_toybox.c
+++ b/editors/patch_toybox.c
@@ -522,7 +522,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
522 int oldsum, newsum, del = 0; 522 int oldsum, newsum, del = 0;
523 char *s, *name; 523 char *s, *name;
524 524
525 oldsum = TT.oldline + TT.oldlen; 525 oldsum = TT.oldline + TT.oldlen;
526 newsum = TT.newline + TT.newlen; 526 newsum = TT.newline + TT.newlen;
527 527
528 name = reverse ? oldname : newname; 528 name = reverse ? oldname : newname;
@@ -559,7 +559,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
559 xmkpath(name, -1); 559 xmkpath(name, -1);
560 *s = '/'; 560 *s = '/';
561 } 561 }
562 TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); 562 TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR);
563 } else { 563 } else {
564 printf("patching file %s\n", name); 564 printf("patching file %s\n", name);
565 TT.filein = xopen(name, O_RDWR); 565 TT.filein = xopen(name, O_RDWR);