diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2023-06-16 19:43:53 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2023-06-16 19:51:01 +0200 |
commit | e1279858394a6079be6816cbedaa3f10e74057cc (patch) | |
tree | 7a7a032ea71978437c8888c9f508db1d4fdf4fe3 | |
parent | f8263528cd44ac5dc95778556c6fd3feea14742e (diff) | |
download | busybox-w32-e1279858394a6079be6816cbedaa3f10e74057cc.tar.gz busybox-w32-e1279858394a6079be6816cbedaa3f10e74057cc.tar.bz2 busybox-w32-e1279858394a6079be6816cbedaa3f10e74057cc.zip |
shell/math: fix ?: to not evaluate not-taken branches
This fixes ash-arith-arith-ternary1/2.tests
function old new delta
evaluate_string 1271 1432 +161
arith_apply 968 1000 +32
arith 22 36 +14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 207/0) Total: 207 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
26 files changed, 131 insertions, 24 deletions
diff --git a/shell/ash_test/ash-arith/arith-ternary-assign.right b/shell/ash_test/ash-arith/arith-ternary-assign.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-assign.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/ash_test/ash-arith/arith-ternary-assign.tests b/shell/ash_test/ash-arith/arith-ternary-assign.tests new file mode 100755 index 000000000..fa18fe7b9 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-assign.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | a='@' | ||
3 | echo 42:$((a=1?42:3,a)) | ||
diff --git a/shell/ash_test/ash-arith/arith-ternary-comma.right b/shell/ash_test/ash-arith/arith-ternary-comma.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-comma.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/ash_test/ash-arith/arith-ternary-comma.tests b/shell/ash_test/ash-arith/arith-ternary-comma.tests new file mode 100755 index 000000000..5e05b58c4 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-comma.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | x='@' | ||
3 | echo 42:$((1?4:x,20*2+2)) | ||
diff --git a/shell/ash_test/ash-arith/arith-ternary-preincr.right b/shell/ash_test/ash-arith/arith-ternary-preincr.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-preincr.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/ash_test/ash-arith/arith-ternary-preincr.tests b/shell/ash_test/ash-arith/arith-ternary-preincr.tests new file mode 100755 index 000000000..3985c7079 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-preincr.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | x='@' | ||
3 | echo 42:$((1?42:++x)) | ||
diff --git a/shell/ash_test/ash-arith/arith-ternary3.right b/shell/ash_test/ash-arith/arith-ternary3.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary3.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/ash_test/ash-arith/arith-ternary3.tests b/shell/ash_test/ash-arith/arith-ternary3.tests new file mode 100755 index 000000000..0bf9f3002 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary3.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | exec 2>&1 | ||
2 | # "EXPR ?..." should check _evaluated_ EXPR, | ||
3 | # not its last value | ||
4 | echo 42:$((1 < 1 ? -1 : 1 > 1 ? 1 : 42)) | ||
diff --git a/shell/ash_test/ash-arith/arith-ternary_nested3.right b/shell/ash_test/ash-arith/arith-ternary_nested3.right new file mode 100644 index 000000000..1a34fde65 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested3.right | |||
@@ -0,0 +1,2 @@ | |||
1 | 42:42 | ||
2 | a=2:2 | ||
diff --git a/shell/ash_test/ash-arith/arith-ternary_nested3.tests b/shell/ash_test/ash-arith/arith-ternary_nested3.tests new file mode 100755 index 000000000..b69dcc6e9 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested3.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | exec 2>&1 | ||
2 | x='@' | ||
3 | a=2 | ||
4 | # After processing nested ?:, outermost ?: should still rememeber to NOT evaluate a*=2 | ||
5 | echo 42:$((1?0?41:42:(a*=2))) | ||
6 | echo "a=2:$a" | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary-assign.right b/shell/hush_test/hush-arith/arith-ternary-assign.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-assign.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/hush_test/hush-arith/arith-ternary-assign.tests b/shell/hush_test/hush-arith/arith-ternary-assign.tests new file mode 100755 index 000000000..fa18fe7b9 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-assign.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | a='@' | ||
3 | echo 42:$((a=1?42:3,a)) | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary-comma.right b/shell/hush_test/hush-arith/arith-ternary-comma.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-comma.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/hush_test/hush-arith/arith-ternary-comma.tests b/shell/hush_test/hush-arith/arith-ternary-comma.tests new file mode 100755 index 000000000..5e05b58c4 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-comma.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | x='@' | ||
3 | echo 42:$((1?4:x,20*2+2)) | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary-preincr.right b/shell/hush_test/hush-arith/arith-ternary-preincr.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-preincr.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/hush_test/hush-arith/arith-ternary-preincr.tests b/shell/hush_test/hush-arith/arith-ternary-preincr.tests new file mode 100755 index 000000000..3985c7079 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-preincr.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | exec 2>&1 | ||
2 | x='@' | ||
3 | echo 42:$((1?42:++x)) | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary1.right b/shell/hush_test/hush-arith/arith-ternary1.right new file mode 100644 index 000000000..6b751d7b8 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | 42:42 | ||
2 | a=0 | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary1.tests b/shell/hush_test/hush-arith/arith-ternary1.tests new file mode 100755 index 000000000..3532ce54d --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary1.tests | |||
@@ -0,0 +1,5 @@ | |||
1 | exec 2>&1 | ||
2 | a=0 | ||
3 | # The not-taken branch should not evaluate | ||
4 | echo 42:$((1 ? 42 : (a+=2))) | ||
5 | echo "a=$a" | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary2.right b/shell/hush_test/hush-arith/arith-ternary2.right new file mode 100644 index 000000000..a549b1b5c --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.right | |||
@@ -0,0 +1,3 @@ | |||
1 | 6:6 | ||
2 | a=b=+err+ | ||
3 | b=6 | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary2.tests b/shell/hush_test/hush-arith/arith-ternary2.tests new file mode 100755 index 000000000..cb3163932 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.tests | |||
@@ -0,0 +1,7 @@ | |||
1 | exec 2>&1 | ||
2 | a='b=+err+' | ||
3 | b=5 | ||
4 | # The not-taken branch should not parse variables | ||
5 | echo 6:$((0 ? a : ++b)) | ||
6 | echo "a=$a" | ||
7 | echo "b=$b" | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary3.right b/shell/hush_test/hush-arith/arith-ternary3.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary3.right | |||
@@ -0,0 +1 @@ | |||
42:42 | |||
diff --git a/shell/hush_test/hush-arith/arith-ternary3.tests b/shell/hush_test/hush-arith/arith-ternary3.tests new file mode 100755 index 000000000..0bf9f3002 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary3.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | exec 2>&1 | ||
2 | # "EXPR ?..." should check _evaluated_ EXPR, | ||
3 | # not its last value | ||
4 | echo 42:$((1 < 1 ? -1 : 1 > 1 ? 1 : 42)) | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary_nested3.right b/shell/hush_test/hush-arith/arith-ternary_nested3.right new file mode 100644 index 000000000..1a34fde65 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested3.right | |||
@@ -0,0 +1,2 @@ | |||
1 | 42:42 | ||
2 | a=2:2 | ||
diff --git a/shell/hush_test/hush-arith/arith-ternary_nested3.tests b/shell/hush_test/hush-arith/arith-ternary_nested3.tests new file mode 100755 index 000000000..b69dcc6e9 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested3.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | exec 2>&1 | ||
2 | x='@' | ||
3 | a=2 | ||
4 | # After processing nested ?:, outermost ?: should still rememeber to NOT evaluate a*=2 | ||
5 | echo 42:$((1?0?41:42:(a*=2))) | ||
6 | echo "a=2:$a" | ||
diff --git a/shell/math.c b/shell/math.c index a398bcb98..b1aabef9d 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -356,6 +356,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
356 | NUMPTR = top_of_stack; /* this decrements NUMPTR */ | 356 | NUMPTR = top_of_stack; /* this decrements NUMPTR */ |
357 | top_of_stack--; /* now points to left side */ | 357 | top_of_stack--; /* now points to left side */ |
358 | 358 | ||
359 | if (math_state->evaluation_disabled) { | ||
360 | dbg("binary op %02x skipped", op); | ||
361 | goto ret_NULL; | ||
362 | } | ||
363 | |||
359 | right_side_val = rez; | 364 | right_side_val = rez; |
360 | rez = top_of_stack->val; | 365 | rez = top_of_stack->val; |
361 | if (op == TOK_BOR || op == TOK_OR_ASSIGN) | 366 | if (op == TOK_BOR || op == TOK_OR_ASSIGN) |
@@ -428,6 +433,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
428 | } | 433 | } |
429 | } | 434 | } |
430 | 435 | ||
436 | if (math_state->evaluation_disabled) { | ||
437 | dbg("unary op %02x skipped", op); | ||
438 | goto ret_NULL; | ||
439 | } | ||
440 | |||
431 | if (is_assign_op(op)) { | 441 | if (is_assign_op(op)) { |
432 | char buf[sizeof(arith_t)*3 + 2]; | 442 | char buf[sizeof(arith_t)*3 + 2]; |
433 | 443 | ||
@@ -446,6 +456,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
446 | } | 456 | } |
447 | 457 | ||
448 | top_of_stack->val = rez; | 458 | top_of_stack->val = rez; |
459 | ret_NULL: | ||
449 | /* Erase var name, it is just a number now */ | 460 | /* Erase var name, it is just a number now */ |
450 | top_of_stack->var_name = NULL; | 461 | top_of_stack->var_name = NULL; |
451 | return NULL; | 462 | return NULL; |
@@ -594,8 +605,10 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) | |||
594 | static arith_t | 605 | static arith_t |
595 | evaluate_string(arith_state_t *math_state, const char *expr) | 606 | evaluate_string(arith_state_t *math_state, const char *expr) |
596 | { | 607 | { |
608 | #define EVAL_DISABLED ((unsigned long long)math_state->evaluation_disabled) | ||
609 | #define TOP_BIT_ULL ((unsigned long long)LLONG_MAX + 1) | ||
597 | operator lasttok; | 610 | operator lasttok; |
598 | const char *errmsg; | 611 | const char *errmsg = NULL; |
599 | const char *start_expr = expr = skip_whitespace(expr); | 612 | const char *start_expr = expr = skip_whitespace(expr); |
600 | unsigned expr_len = strlen(expr) + 2; | 613 | unsigned expr_len = strlen(expr) + 2; |
601 | /* Stack of integers/names */ | 614 | /* Stack of integers/names */ |
@@ -614,7 +627,6 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
614 | /* Start with a left paren */ | 627 | /* Start with a left paren */ |
615 | dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); | 628 | dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); |
616 | *opstackptr++ = lasttok = TOK_LPAREN; | 629 | *opstackptr++ = lasttok = TOK_LPAREN; |
617 | errmsg = NULL; | ||
618 | 630 | ||
619 | while (1) { | 631 | while (1) { |
620 | const char *p; | 632 | const char *p; |
@@ -653,19 +665,26 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
653 | p = endofname(expr); | 665 | p = endofname(expr); |
654 | if (p != expr) { | 666 | if (p != expr) { |
655 | /* Name */ | 667 | /* Name */ |
656 | size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ | 668 | if (!math_state->evaluation_disabled) { |
657 | numstackptr->var_name = alloca(var_name_size); | 669 | size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ |
658 | safe_strncpy(numstackptr->var_name, expr, var_name_size); | 670 | numstackptr->var_name = alloca(var_name_size); |
659 | dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); | 671 | safe_strncpy(numstackptr->var_name, expr, var_name_size); |
660 | expr = skip_whitespace(p); | 672 | dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); |
661 | /* If it is not followed by "=" operator... */ | 673 | expr = skip_whitespace(p); |
662 | if (expr[0] != '=' /* not "=..." */ | 674 | /* If it is not followed by "=" operator... */ |
663 | || expr[1] == '=' /* or "==..." */ | 675 | if (expr[0] != '=' /* not "=..." */ |
664 | ) { | 676 | || expr[1] == '=' /* or "==..." */ |
665 | /* Evaluate variable to value */ | 677 | ) { |
666 | errmsg = arith_lookup_val(math_state, numstackptr); | 678 | /* Evaluate variable to value */ |
667 | if (errmsg) | 679 | errmsg = arith_lookup_val(math_state, numstackptr); |
668 | goto err_with_custom_msg; | 680 | if (errmsg) |
681 | goto err_with_custom_msg; | ||
682 | } | ||
683 | } else { | ||
684 | dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); | ||
685 | numstackptr->var_name = NULL; | ||
686 | numstackptr->val = 0; //paranoia, probably not needed | ||
687 | expr = p; | ||
669 | } | 688 | } |
670 | push_num: | 689 | push_num: |
671 | numstackptr++; | 690 | numstackptr++; |
@@ -814,10 +833,11 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
814 | * pop prev_op | 833 | * pop prev_op |
815 | * if can't evaluate prev_op (it is lower precedence than op): | 834 | * if can't evaluate prev_op (it is lower precedence than op): |
816 | * push prev_op back | 835 | * push prev_op back |
817 | * goto P | 836 | * goto C |
818 | * evaluate prev_op on top of numstack | 837 | * evaluate prev_op on top of numstack |
819 | * P: push op | 838 | * C:if op is "?": check result, set disable flag if needed |
820 | * N: loop to parse the rest of string | 839 | * push op |
840 | * N:loop to parse the rest of string | ||
821 | */ | 841 | */ |
822 | while (opstackptr != opstack) { | 842 | while (opstackptr != opstack) { |
823 | operator prev_op = *--opstackptr; | 843 | operator prev_op = *--opstackptr; |
@@ -840,7 +860,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) | |||
840 | ) { | 860 | ) { |
841 | /* ...x~y@. push @ on opstack */ | 861 | /* ...x~y@. push @ on opstack */ |
842 | opstackptr++; /* undo removal of ~ op */ | 862 | opstackptr++; /* undo removal of ~ op */ |
843 | goto push_op; | 863 | goto check_cond; |
844 | } | 864 | } |
845 | /* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */ | 865 | /* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */ |
846 | } | 866 | } |
@@ -863,21 +883,41 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ | |||
863 | errmsg = "malformed ?: operator"; | 883 | errmsg = "malformed ?: operator"; |
864 | goto err_with_custom_msg; | 884 | goto err_with_custom_msg; |
865 | } | 885 | } |
886 | /* Example: a=1?2:3,a. We just executed ":". | ||
887 | * Prevent assignment from being still disabled. | ||
888 | */ | ||
889 | math_state->evaluation_disabled >>= 1; | ||
890 | dbg("':' executed: evaluation_disabled=%llx (restored)", EVAL_DISABLED); | ||
866 | } | 891 | } |
867 | } /* while (opstack not empty) */ | 892 | } /* while (opstack not empty) */ |
868 | if (op == TOK_RPAREN) /* unpaired RPAREN? */ | 893 | if (op == TOK_RPAREN) /* unpaired RPAREN? */ |
869 | goto err; | 894 | goto err; |
870 | } | 895 | check_cond: |
896 | if (op == TOK_CONDITIONAL) { | ||
897 | /* We know the value of EXPR in "EXPR ? ..." | ||
898 | * Should we stop evaluating now? */ | ||
899 | if (math_state->evaluation_disabled & TOP_BIT_ULL) | ||
900 | goto err; /* >63 levels of ?: nesting not supported */ | ||
901 | math_state->evaluation_disabled <<= 1; | ||
902 | if (numstackptr[-1].val == 0) | ||
903 | math_state->evaluation_disabled |= 1; | ||
904 | dbg("'?' entered: evaluation_disabled=%llx", EVAL_DISABLED); | ||
905 | } | ||
906 | } /* if */ | ||
871 | /* else: LPAREN or UNARY: push it on opstack */ | 907 | /* else: LPAREN or UNARY: push it on opstack */ |
872 | push_op: | 908 | |
873 | /* Push this operator to opstack */ | 909 | /* Push this operator to opstack */ |
874 | dbg("(%d) op:%02x insert_op:%02x", (int)(opstackptr - opstack), op, insert_op); | 910 | dbg("(%d) op:%02x insert_op:%02x", (int)(opstackptr - opstack), op, insert_op); |
875 | *opstackptr++ = lasttok = op; | 911 | *opstackptr++ = lasttok = op; |
876 | next: ; | 912 | next: |
877 | if (insert_op != 0xff) { | 913 | if (insert_op != 0xff) { |
878 | op = insert_op; | 914 | op = insert_op; |
879 | insert_op = 0xff; | 915 | insert_op = 0xff; |
880 | dbg("inserting %02x", op); | 916 | dbg("inserting %02x", op); |
917 | if (op == TOK_CONDITIONAL_SEP) { | ||
918 | math_state->evaluation_disabled ^= 1; | ||
919 | dbg("':' entered: evaluation_disabled=%llx (negated)", EVAL_DISABLED); | ||
920 | } | ||
881 | goto tok_found1; | 921 | goto tok_found1; |
882 | } | 922 | } |
883 | } /* while (1) */ | 923 | } /* while (1) */ |
@@ -896,6 +936,7 @@ arith(arith_state_t *math_state, const char *expr) | |||
896 | { | 936 | { |
897 | math_state->errmsg = NULL; | 937 | math_state->errmsg = NULL; |
898 | math_state->list_of_recursed_names = NULL; | 938 | math_state->list_of_recursed_names = NULL; |
939 | math_state->evaluation_disabled = 0; | ||
899 | return evaluate_string(math_state, expr); | 940 | return evaluate_string(math_state, expr); |
900 | } | 941 | } |
901 | 942 | ||
diff --git a/shell/math.h b/shell/math.h index 41ef6e8df..452ddaddd 100644 --- a/shell/math.h +++ b/shell/math.h | |||
@@ -73,13 +73,12 @@ typedef long arith_t; | |||
73 | 73 | ||
74 | typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); | 74 | typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); |
75 | typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); | 75 | typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); |
76 | //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); | ||
77 | 76 | ||
78 | typedef struct arith_state_t { | 77 | typedef struct arith_state_t { |
79 | const char *errmsg; | 78 | const char *errmsg; |
80 | arith_var_lookup_t lookupvar; | 79 | arith_var_lookup_t lookupvar; |
81 | arith_var_set_t setvar; | 80 | arith_var_set_t setvar; |
82 | // arith_var_endofname_t endofname; | 81 | uint64_t evaluation_disabled; |
83 | void *list_of_recursed_names; | 82 | void *list_of_recursed_names; |
84 | } arith_state_t; | 83 | } arith_state_t; |
85 | 84 | ||