diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/awk.c | 132 | ||||
-rw-r--r-- | editors/patch.c | 14 | ||||
-rw-r--r-- | editors/patch_toybox.c | 4 |
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 | ||
701 | static double my_strtod(char **pp) | 705 | static 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 | ||
1578 | static int awk_split(const char *s, node *spl, char **slist) | 1597 | static 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); |