bc: shrink zdc_lex_string()
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 18 Dec 2018 12:48:37 +0000 (13:48 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 18 Dec 2018 12:48:37 +0000 (13:48 +0100)
This actually fixes a rather obscure bug. This was failing to find
end of the string:

$ echo -n '[foo]' | dc
dc: string end could not be found

function                                             old     new   delta
zbc_lex_next                                        2230    2141     -89
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-89)             Total: -89 bytes
   text    data     bss     dec     hex filename
 981461     485    7296  989242   f183a busybox_old
 981372     485    7296  989153   f17e1 busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
miscutils/bc.c

index 37c9012f9ed34e5bb52e2866c96769c0f4765e88..5d969c9d0ef1101743618c55b03b719495f34ec7 100644 (file)
@@ -3272,25 +3272,31 @@ static BC_STATUS zdc_lex_register(BcLex *l)
 
 static BC_STATUS zdc_lex_string(BcLex *l)
 {
-       size_t depth = 1, nls = 0, i = l->i;
-       char c;
+       size_t depth, nls, i;
 
        l->t.t = BC_LEX_STR;
        bc_vec_pop_all(&l->t.v);
 
-       for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) {
-
-               depth += (c == '[' && (i == l->i || l->buf[i - 1] != '\\'));
-               depth -= (c == ']' && (i == l->i || l->buf[i - 1] != '\\'));
+       nls = 0;
+       depth = 1;
+       i = l->i;
+       for (;;) {
+               char c = l->buf[i];
+               if (c == '\0') {
+                       l->i = i;
+                       RETURN_STATUS(bc_error("string end could not be found"));
+               }
                nls += (c == '\n');
-
-               if (depth) bc_vec_push(&l->t.v, &c);
-       }
-
-       if (c == '\0') {
-               l->i = i;
-               RETURN_STATUS(bc_error("string end could not be found"));
+               if (i == l->i || l->buf[i - 1] != '\\') {
+                       if (c == '[') depth++;
+                       if (c == ']')
+                               if (--depth == 0)
+                                       break;
+               }
+               bc_vec_push(&l->t.v, &l->buf[i]);
+               i++;
        }
+       i++;
 
        bc_vec_pushZeroByte(&l->t.v);
        // This check makes sense only if size_t is (much) larger than BC_MAX_STRING.