From d84a604830a7ee3f8fb5f3908ae0d54513393a20 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 25 Sep 2021 22:04:45 +0200 Subject: shell: fix arithmentic evaluation of "++7" and such (it is + + 7, i.e. 7) function old new delta evaluate_string 945 988 +43 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith.right | 20 +++++++++++++------- shell/ash_test/ash-arith/arith.tests | 10 +++++----- shell/ash_test/ash-arith/arith1.sub | 4 ++-- shell/ash_test/ash-arith/arith2.sub | 10 +++++----- shell/hush_test/hush-arith/arith.right | 20 +++++++++++++------- shell/hush_test/hush-arith/arith.tests | 10 +++++----- shell/hush_test/hush-arith/arith1.sub | 4 ++-- shell/hush_test/hush-arith/arith2.sub | 10 +++++----- shell/math.c | 23 +++++++++++++++-------- 9 files changed, 65 insertions(+), 46 deletions(-) (limited to 'shell') diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 6936f1269..99ef825f5 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -97,6 +97,7 @@ ghi 3 3 4 4 4 4 +7 7 ./arith.tests: line 257: arithmetic syntax error ./arith.tests: line 259: arithmetic syntax error ./arith.tests: line 260: arithmetic syntax error @@ -105,6 +106,8 @@ ghi 4 4 7 7 -7 -7 +7 +7 ./arith1.sub: line 2: arithmetic syntax error ./arith1.sub: line 3: arithmetic syntax error ./arith1.sub: line 4: arithmetic syntax error @@ -119,11 +122,12 @@ ghi 2 2 -2 -2 1 1 -./arith1.sub: line 37: arithmetic syntax error -./arith2.sub: line 2: arithmetic syntax error -./arith2.sub: line 3: arithmetic syntax error -./arith2.sub: line 4: arithmetic syntax error -./arith2.sub: line 5: arithmetic syntax error +7 +7 +7 +7 +7 +7 5 5 1 1 6 6 @@ -132,8 +136,10 @@ ghi 1 1 4 4 0 0 -./arith2.sub: line 42: arithmetic syntax error -./arith2.sub: line 47: arithmetic syntax error +-7 +-7 +7 +7 8 12 ./arith.tests: line 290: arithmetic syntax error 42 diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests index d65758e7d..746ccab71 100755 --- a/shell/ash_test/ash-arith/arith.tests +++ b/shell/ash_test/ash-arith/arith.tests @@ -252,8 +252,8 @@ echo 3 $x echo 4 $(( ++x )) echo 4 $x -# bash 3.2 apparently thinks that ++7 is 7 -#ash# echo 7 $(( ++7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo 7 $(( ++7 )) ( echo $(( 7-- )) ) ( echo $(( --x=7 )) ) @@ -267,9 +267,9 @@ echo 4 $x echo 7 $(( +7 )) echo -7 $(( -7 )) -# bash 3.2 apparently thinks that ++7 is 7 -#ash# echo $(( ++7 )) -#ash# echo $(( --7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo $(( ++7 )) +echo $(( --7 )) ${THIS_SH} ./arith1.sub ${THIS_SH} ./arith2.sub diff --git a/shell/ash_test/ash-arith/arith1.sub b/shell/ash_test/ash-arith/arith1.sub index 80aa99922..a36785c67 100755 --- a/shell/ash_test/ash-arith/arith1.sub +++ b/shell/ash_test/ash-arith/arith1.sub @@ -35,6 +35,6 @@ echo 1 $a #ash# (( ++ )) ( echo $(( +++7 )) ) -# bash 3.2 apparently thinks that ++ +7 is 7 -#ash# echo $(( ++ + 7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo $(( ++ + 7 )) #ash# (( -- )) diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub index 9105059db..29f9471d6 100755 --- a/shell/ash_test/ash-arith/arith2.sub +++ b/shell/ash_test/ash-arith/arith2.sub @@ -1,4 +1,4 @@ -# bash 3.2 apparently thinks that ++7 is 7 etc +# ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences ( echo $(( --7 )) ) ( echo $(( ++7 )) ) ( echo $(( -- 7 )) ) @@ -37,13 +37,13 @@ echo 4 $(( 4 - -- a )) echo 0 $a #ash# (( -- )) -# bash 3.2 apparently thinks that ---7 is -7 -#ash# echo $(( ---7 )) +# -- is not a dec operator on non-variable, it is the - - sequence +echo $(( ---7 )) ( echo $(( -- - 7 )) ) #ash# (( ++ )) -# bash 3.2: 7 -#ash# echo 7 $(( ++7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo $(( ++7 )) ( echo $(( ++ + 7 )) ) # bash 3.2: -7 diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index c48e468a5..2c389caea 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -106,6 +106,7 @@ hush: arithmetic syntax error 3 3 4 4 4 4 +7 7 hush: arithmetic syntax error hush: arithmetic syntax error hush: arithmetic syntax error @@ -114,6 +115,8 @@ hush: arithmetic syntax error 4 4 7 7 -7 -7 +7 +7 hush: arithmetic syntax error hush: arithmetic syntax error hush: arithmetic syntax error @@ -128,11 +131,12 @@ hush: arithmetic syntax error 2 2 -2 -2 1 1 -hush: arithmetic syntax error -hush: arithmetic syntax error -hush: arithmetic syntax error -hush: arithmetic syntax error -hush: arithmetic syntax error +7 +7 +7 +7 +7 +7 5 5 1 1 6 6 @@ -141,8 +145,10 @@ hush: arithmetic syntax error 1 1 4 4 0 0 -hush: arithmetic syntax error -hush: arithmetic syntax error +-7 +-7 +7 +7 8 12 hush: arithmetic syntax error 42 diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests index bc6b341d1..a7aded17d 100755 --- a/shell/hush_test/hush-arith/arith.tests +++ b/shell/hush_test/hush-arith/arith.tests @@ -255,8 +255,8 @@ echo 3 $x echo 4 $(( ++x )) echo 4 $x -# bash 3.2 apparently thinks that ++7 is 7 -#ash# echo 7 $(( ++7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo 7 $(( ++7 )) ( echo $(( 7-- )) ) ( echo $(( --x=7 )) ) @@ -270,9 +270,9 @@ echo 4 $x echo 7 $(( +7 )) echo -7 $(( -7 )) -# bash 3.2 apparently thinks that ++7 is 7 -#ash# echo $(( ++7 )) -#ash# echo $(( --7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo $(( ++7 )) +echo $(( --7 )) ${THIS_SH} ./arith1.sub ${THIS_SH} ./arith2.sub diff --git a/shell/hush_test/hush-arith/arith1.sub b/shell/hush_test/hush-arith/arith1.sub index 80aa99922..a36785c67 100755 --- a/shell/hush_test/hush-arith/arith1.sub +++ b/shell/hush_test/hush-arith/arith1.sub @@ -35,6 +35,6 @@ echo 1 $a #ash# (( ++ )) ( echo $(( +++7 )) ) -# bash 3.2 apparently thinks that ++ +7 is 7 -#ash# echo $(( ++ + 7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo $(( ++ + 7 )) #ash# (( -- )) diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub index 9105059db..29f9471d6 100755 --- a/shell/hush_test/hush-arith/arith2.sub +++ b/shell/hush_test/hush-arith/arith2.sub @@ -1,4 +1,4 @@ -# bash 3.2 apparently thinks that ++7 is 7 etc +# ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences ( echo $(( --7 )) ) ( echo $(( ++7 )) ) ( echo $(( -- 7 )) ) @@ -37,13 +37,13 @@ echo 4 $(( 4 - -- a )) echo 0 $a #ash# (( -- )) -# bash 3.2 apparently thinks that ---7 is -7 -#ash# echo $(( ---7 )) +# -- is not a dec operator on non-variable, it is the - - sequence +echo $(( ---7 )) ( echo $(( -- - 7 )) ) #ash# (( ++ )) -# bash 3.2: 7 -#ash# echo 7 $(( ++7 )) +# ++ is not a inc operator on non-variable, it is the + + sequence +echo $(( ++7 )) ( echo $(( ++ + 7 )) ) # bash 3.2: -7 diff --git a/shell/math.c b/shell/math.c index 2942cdd26..049d5703b 100644 --- a/shell/math.c +++ b/shell/math.c @@ -668,19 +668,26 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* Should be an operator */ - /* Special case: NUM-- and NUM++ are not recognized if NUM - * is a literal number, not a variable. IOW: + /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized + * only if XYZ is a variable name, not a number or EXPR. IOW: * "a+++v" is a++ + v. * "7+++v" is 7 + ++v, not 7++ + v. + * "--7" is - - 7, not --7. + * "++++a" is + + ++a, not ++ ++ a. + * (we still mishandle "(a)+++7", should be treated as (a) + + + 7, but we do increment a) */ - if (lasttok == TOK_NUM && !numstackptr[-1].var /* number literal */ - && (expr[0] == '+' || expr[0] == '-') + if ((expr[0] == '+' || expr[0] == '-') && (expr[1] == expr[0]) ) { - //bb_error_msg("special %c%c", expr[0], expr[0]); - op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); - expr += 1; - goto tok_found1; + if (numstackptr == numstack || !numstackptr[-1].var) { /* not a VAR++ */ + char next = skip_whitespace(expr + 2)[0]; + if (!(isalpha(next) || next == '_')) { /* not a ++VAR */ + //bb_error_msg("special %c%c", expr[0], expr[0]); + op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); + expr++; + goto tok_found1; + } + } } p = op_tokens; -- cgit v1.2.3-55-g6feb From 62e433131b289ea90e465cf0c5f78c8c226fc692 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 25 Sep 2021 22:25:19 +0200 Subject: shell: enable more tests which are passing now Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith.right | 58 ++++++++++++++++++++++++---------- shell/ash_test/ash-arith/arith.tests | 45 +++++++++++++------------- shell/ash_test/ash-arith/arith2.sub | 14 +++----- shell/hush_test/hush-arith/arith.right | 17 ++++++++++ shell/hush_test/hush-arith/arith.tests | 30 +++++++++--------- shell/hush_test/hush-arith/arith2.sub | 14 +++----- 6 files changed, 105 insertions(+), 73 deletions(-) (limited to 'shell') diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 99ef825f5..61fcab55e 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -43,40 +43,60 @@ Format: 'expected actual' 4 4 29 29 5 5 +unary plus, minus -4 -4 4 4 +conditional expressions 1 1 32 32 32 32 1 1 1 1 32 32 +check that the unevaluated part of the ternary operator does not do evaluation or assignment 20 20 30 30 20 20 30 30 -./arith.tests: line 117: arithmetic syntax error +check precedence of assignment vs. conditional operator +./arith.tests: line 116: arithmetic syntax error +check precedence of assignment vs. conditional operator +associativity of assignment-operator operator 6 6 6,5,3 6,5,3 +octal, hex 263 263 255 255 40 40 -./arith.tests: line 163: arithmetic syntax error -./arith.tests: line 165: divide by zero -./arith.tests: let: line 166: arithmetic syntax error -./arith.tests: line 167: arithmetic syntax error -./arith.tests: let: line 168: arithmetic syntax error +other bases +10 10 +10 10 +10 10 +10 10 +10 10 +10 10 +36 36 +36 36 +62 62 +63 63 +missing number after base +0 0 +./arith.tests: line 162: arithmetic syntax error +./arith.tests: line 164: divide by zero +./arith.tests: let: line 165: arithmetic syntax error +./arith.tests: line 166: arithmetic syntax error +./arith.tests: let: line 167: arithmetic syntax error abc def ghi -./arith.tests: line 191: arithmetic syntax error +./arith.tests: line 190: arithmetic syntax error 16 16 -./arith.tests: line 196: arithmetic syntax error -./arith.tests: line 197: malformed ?: operator -./arith.tests: line 198: arithmetic syntax error +./arith.tests: line 195: arithmetic syntax error +./arith.tests: line 196: malformed ?: operator +./arith.tests: line 197: arithmetic syntax error 9 9 -./arith.tests: line 205: arithmetic syntax error -./arith.tests: line 208: arithmetic syntax error +./arith.tests: line 204: arithmetic syntax error +./arith.tests: line 207: arithmetic syntax error 9 9 9 9 9 9 @@ -98,11 +118,11 @@ ghi 4 4 4 4 7 7 -./arith.tests: line 257: arithmetic syntax error +./arith.tests: line 256: arithmetic syntax error +./arith.tests: line 258: arithmetic syntax error ./arith.tests: line 259: arithmetic syntax error -./arith.tests: line 260: arithmetic syntax error +./arith.tests: line 261: arithmetic syntax error ./arith.tests: line 262: arithmetic syntax error -./arith.tests: line 263: arithmetic syntax error 4 4 7 7 -7 -7 @@ -140,9 +160,13 @@ ghi -7 7 7 +-7 -7 +-7 -7 +7 7 +7 7 8 12 -./arith.tests: line 290: arithmetic syntax error +./arith.tests: line 289: arithmetic syntax error 42 42 42 -./arith.tests: line 302: a[b[c]d]=e: not found +./arith.tests: line 301: a[b[c]d]=e: not found diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests index 746ccab71..b9cb8ba4c 100755 --- a/shell/ash_test/ash-arith/arith.tests +++ b/shell/ash_test/ash-arith/arith.tests @@ -75,11 +75,11 @@ echo 4 $(( iv &= 4 )) echo 29 $(( iv += (jv + 9))) echo 5 $(( (iv + 4) % 7 )) -# unary plus, minus +echo unary plus, minus echo -4 $(( +4 - 8 )) echo 4 $(( -4 + 8 )) -# conditional expressions +echo conditional expressions echo 1 $(( 4<5 ? 1 : 32)) echo 32 $(( 4>5 ? 1 : 32)) echo 32 $(( 4>(2+3) ? 1 : 32)) @@ -87,8 +87,7 @@ echo 1 $(( 4<(2+3) ? 1 : 32)) echo 1 $(( (2+2)<(2+3) ? 1 : 32)) echo 32 $(( (2+2)>(2+3) ? 1 : 32)) -# check that the unevaluated part of the ternary operator does not do -# evaluation or assignment +echo check that the unevaluated part of the ternary operator does not do evaluation or assignment x=i+=2 y=j+=2 #ash# declare -i i=1 j=1 @@ -109,20 +108,20 @@ echo 20 $((1 ? 20 : (x+=2))) echo 30 $((0 ? (y+=2) : 30)) #ash# echo $i,$y # ash mishandles this -# check precedence of assignment vs. conditional operator +echo check precedence of assignment vs. conditional operator # should be an error #ash# declare -i x=2 x=2 #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: ( y=$((1 ? 20 : x+=2)) ) -# check precedence of assignment vs. conditional operator +echo check precedence of assignment vs. conditional operator #ash# declare -i x=2 x=2 # ash says "line NNN: syntax error: 0 ? x+=2 : 20" #ash# echo 20 $((0 ? x+=2 : 20)) -# associativity of assignment-operator operator +echo associativity of assignment-operator operator #ash# declare -i i=1 j=2 k=3 i=1 j=2 @@ -130,7 +129,7 @@ k=3 echo 6 $((i += j += k)) echo 6,5,3 $i,$j,$k -# octal, hex +echo octal, hex echo 263 $(( 0x100 | 007 )) echo 255 $(( 0xff )) #ash# echo 255 $(( 16#ff )) @@ -139,25 +138,25 @@ echo 255 $(( 0xff )) echo 40 $(( 8 ^ 32 )) -#ash# # other bases -#ash# echo 10 $(( 16#a )) -#ash# echo 10 $(( 32#a )) -#ash# echo 10 $(( 56#a )) -#ash# echo 10 $(( 64#a )) -#ash# -#ash# echo 10 $(( 16#A )) -#ash# echo 10 $(( 32#A )) -#ash# echo 36 $(( 56#A )) -#ash# echo 36 $(( 64#A )) -#ash# -#ash# echo 62 $(( 64#@ )) -#ash# echo 63 $(( 64#_ )) +echo other bases +echo 10 $(( 16#a )) +echo 10 $(( 32#a )) +echo 10 $(( 56#a )) +echo 10 $(( 64#a )) + +echo 10 $(( 16#A )) +echo 10 $(( 32#A )) +echo 36 $(( 56#A )) +echo 36 $(( 64#A )) + +echo 62 $(( 64#@ )) +echo 63 $(( 64#_ )) #ash# # weird bases (error) #ash# echo $(( 3425#56 )) -#ash# # missing number after base -#ash# echo 0 $(( 2# )) +echo missing number after base +echo 0 $(( 2# )) # these should generate errors ( echo $(( 7 = 43 )) ) diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub index 29f9471d6..8d7918114 100755 --- a/shell/ash_test/ash-arith/arith2.sub +++ b/shell/ash_test/ash-arith/arith2.sub @@ -46,12 +46,8 @@ echo $(( ---7 )) echo $(( ++7 )) ( echo $(( ++ + 7 )) ) -# bash 3.2: -7 -#ash# echo -7 $(( ++-7 )) -# bash 3.2: -7 -#ash# echo -7 $(( ++ - 7 )) - -# bash 3.2: 7 -#ash# echo 7 $(( +--7 )) -# bash 3.2: 7 -#ash# echo 7 $(( -- + 7 )) +echo -7 $(( ++-7 )) +echo -7 $(( ++ - 7 )) + +echo 7 $(( +--7 )) +echo 7 $(( -- + 7 )) diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index 2c389caea..a8612295e 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -70,6 +70,19 @@ octal, hex 263 263 255 255 40 40 +other bases +10 10 +10 10 +10 10 +10 10 +10 10 +10 10 +36 36 +36 36 +62 62 +63 63 +missing number after base +0 0 hush: arithmetic syntax error hush: divide by zero hush: can't execute 'let': No such file or directory @@ -149,6 +162,10 @@ hush: arithmetic syntax error -7 7 7 +-7 -7 +-7 -7 +7 7 +7 7 8 12 hush: arithmetic syntax error 42 diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests index a7aded17d..6b707486c 100755 --- a/shell/hush_test/hush-arith/arith.tests +++ b/shell/hush_test/hush-arith/arith.tests @@ -142,25 +142,25 @@ echo 255 $(( 0xff )) echo 40 $(( 8 ^ 32 )) -#ash# # other bases -#ash# echo 10 $(( 16#a )) -#ash# echo 10 $(( 32#a )) -#ash# echo 10 $(( 56#a )) -#ash# echo 10 $(( 64#a )) -#ash# -#ash# echo 10 $(( 16#A )) -#ash# echo 10 $(( 32#A )) -#ash# echo 36 $(( 56#A )) -#ash# echo 36 $(( 64#A )) -#ash# -#ash# echo 62 $(( 64#@ )) -#ash# echo 63 $(( 64#_ )) +echo other bases +echo 10 $(( 16#a )) +echo 10 $(( 32#a )) +echo 10 $(( 56#a )) +echo 10 $(( 64#a )) + +echo 10 $(( 16#A )) +echo 10 $(( 32#A )) +echo 36 $(( 56#A )) +echo 36 $(( 64#A )) + +echo 62 $(( 64#@ )) +echo 63 $(( 64#_ )) #ash# # weird bases (error) #ash# echo $(( 3425#56 )) -#ash# # missing number after base -#ash# echo 0 $(( 2# )) +echo missing number after base +echo 0 $(( 2# )) # these should generate errors ( echo $(( 7 = 43 )) ) diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub index 29f9471d6..8d7918114 100755 --- a/shell/hush_test/hush-arith/arith2.sub +++ b/shell/hush_test/hush-arith/arith2.sub @@ -46,12 +46,8 @@ echo $(( ---7 )) echo $(( ++7 )) ( echo $(( ++ + 7 )) ) -# bash 3.2: -7 -#ash# echo -7 $(( ++-7 )) -# bash 3.2: -7 -#ash# echo -7 $(( ++ - 7 )) - -# bash 3.2: 7 -#ash# echo 7 $(( +--7 )) -# bash 3.2: 7 -#ash# echo 7 $(( -- + 7 )) +echo -7 $(( ++-7 )) +echo -7 $(( ++ - 7 )) + +echo 7 $(( +--7 )) +echo 7 $(( -- + 7 )) -- cgit v1.2.3-55-g6feb From 1be73dd9ad6d2cf6747934374c1d58bd9bc211b4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 26 Sep 2021 13:25:49 +0200 Subject: shell: fix parsing of $(( (v)++ + NUM )) function old new delta evaluate_string 988 1011 +23 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-postinc.right | 3 ++ shell/ash_test/ash-arith/arith-postinc.tests | 4 ++ shell/hush_test/hush-arith/arith-postinc.right | 3 ++ shell/hush_test/hush-arith/arith-postinc.tests | 4 ++ shell/math.c | 52 +++++++++++++++----------- 5 files changed, 44 insertions(+), 22 deletions(-) (limited to 'shell') diff --git a/shell/ash_test/ash-arith/arith-postinc.right b/shell/ash_test/ash-arith/arith-postinc.right index c95ce02bf..5cd4ba6b4 100644 --- a/shell/ash_test/ash-arith/arith-postinc.right +++ b/shell/ash_test/ash-arith/arith-postinc.right @@ -2,4 +2,7 @@ 1 1 1 1 1 1 +6 6 +7 7 +7 7 Ok:0 diff --git a/shell/ash_test/ash-arith/arith-postinc.tests b/shell/ash_test/ash-arith/arith-postinc.tests index 3fd9bfed5..f2ae778df 100755 --- a/shell/ash_test/ash-arith/arith-postinc.tests +++ b/shell/ash_test/ash-arith/arith-postinc.tests @@ -2,4 +2,8 @@ echo 1 $((0++1)) echo 1 $((0--1)) x=-1; echo 1 $((0-$x)) x=+1; echo 1 $((0+$x)) +a=3 +echo 6 $((a+++3)) # a++ + 3 +echo 7 $(((a)+++3)) # a + + + 3 +echo 7 $(((a)+++3)) # a + + + 3 echo Ok:$? diff --git a/shell/hush_test/hush-arith/arith-postinc.right b/shell/hush_test/hush-arith/arith-postinc.right index c95ce02bf..5cd4ba6b4 100644 --- a/shell/hush_test/hush-arith/arith-postinc.right +++ b/shell/hush_test/hush-arith/arith-postinc.right @@ -2,4 +2,7 @@ 1 1 1 1 1 1 +6 6 +7 7 +7 7 Ok:0 diff --git a/shell/hush_test/hush-arith/arith-postinc.tests b/shell/hush_test/hush-arith/arith-postinc.tests index 3fd9bfed5..f2ae778df 100755 --- a/shell/hush_test/hush-arith/arith-postinc.tests +++ b/shell/hush_test/hush-arith/arith-postinc.tests @@ -2,4 +2,8 @@ echo 1 $((0++1)) echo 1 $((0--1)) x=-1; echo 1 $((0-$x)) x=+1; echo 1 $((0+$x)) +a=3 +echo 6 $((a+++3)) # a++ + 3 +echo 7 $(((a)+++3)) # a + + + 3 +echo 7 $(((a)+++3)) # a + + + 3 echo Ok:$? diff --git a/shell/math.c b/shell/math.c index 049d5703b..76d22c9bd 100644 --- a/shell/math.c +++ b/shell/math.c @@ -116,10 +116,6 @@ #include "libbb.h" #include "math.h" -#define lookupvar (math_state->lookupvar) -#define setvar (math_state->setvar ) -//#define endofname (math_state->endofname) - typedef unsigned char operator; /* An operator's token id is a bit of a bitfield. The lower 5 bits are the @@ -258,7 +254,7 @@ static const char* arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) { if (t->var) { - const char *p = lookupvar(t->var); + const char *p = math_state->lookupvar(t->var); if (p) { remembered_name *cur; remembered_name cur_save; @@ -445,16 +441,15 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (top_of_stack->var == NULL) { /* Hmm, 1=2 ? */ -//TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8 goto err; } /* Save to shell variable */ sprintf(buf, ARITH_FMT, rez); - setvar(top_of_stack->var, buf); + math_state->setvar(top_of_stack->var, buf); /* After saving, make previous value for v++ or v-- */ if (op == TOK_POST_INC) rez--; - else if (op == TOK_POST_DEC) + if (op == TOK_POST_DEC) rez++; } @@ -607,11 +602,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) const char *p; operator op; operator prec; - char arithval; expr = skip_whitespace(expr); - arithval = *expr; - if (arithval == '\0') { + if (*expr == '\0') { if (expr == start_expr) { /* Null expression */ numstack->val = 0; @@ -628,6 +621,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) * append a closing right paren * and let the loop process it */ expr = ptr_to_rparen; +//bb_error_msg("expr=')'"); continue; } /* At this point, we're done with the expression */ @@ -635,19 +629,16 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* ...but if there isn't, it's bad */ goto err; } - if (numstack->var) { - /* expression is $((var)) only, lookup now */ - errmsg = arith_lookup_val(math_state, numstack); - } goto ret; } p = endofname(expr); if (p != expr) { /* Name */ - size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ + size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ numstackptr->var = alloca(var_name_size); safe_strncpy(numstackptr->var, expr, var_name_size); +//bb_error_msg("var:'%s'", numstackptr->var); expr = p; num: numstackptr->second_val_present = 0; @@ -656,11 +647,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) continue; } - if (isdigit(arithval)) { + if (isdigit(*expr)) { /* Number */ numstackptr->var = NULL; errno = 0; numstackptr->val = strto_arith_t(expr, (char**) &expr); +//bb_error_msg("val:%lld", numstackptr->val); if (errno) numstackptr->val = 0; /* bash compat */ goto num; @@ -671,10 +663,10 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized * only if XYZ is a variable name, not a number or EXPR. IOW: * "a+++v" is a++ + v. + * "(a)+++7" is ( a ) + + + 7. * "7+++v" is 7 + ++v, not 7++ + v. * "--7" is - - 7, not --7. - * "++++a" is + + ++a, not ++ ++ a. - * (we still mishandle "(a)+++7", should be treated as (a) + + + 7, but we do increment a) + * "++++a" is + + ++a, not ++ ++a. */ if ((expr[0] == '+' || expr[0] == '-') && (expr[1] == expr[0]) @@ -756,26 +748,40 @@ evaluate_string(arith_state_t *math_state, const char *expr) * "applied" in this way. */ prec = PREC(op); +//bb_error_msg("prec:%02x", prec); if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { /* not left paren or unary */ if (lasttok != TOK_NUM) { /* binary op must be preceded by a num */ goto err; } + /* The algorithm employed here is simple: while we don't + * hit an open paren nor the bottom of the stack, pop + * tokens and apply them */ while (stackptr != stack) { operator prev_op = *--stackptr; if (op == TOK_RPAREN) { - /* The algorithm employed here is simple: while we don't - * hit an open paren nor the bottom of the stack, pop - * tokens and apply them */ +//bb_error_msg("op == TOK_RPAREN"); if (prev_op == TOK_LPAREN) { +//bb_error_msg("prev_op == TOK_LPAREN"); +//bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var); + if (numstackptr[-1].var) { + /* Expression is (var), lookup now */ + errmsg = arith_lookup_val(math_state, &numstackptr[-1]); + if (errmsg) + goto err_with_custom_msg; + /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ + numstackptr[-1].var = NULL; + } /* Any operator directly after a * close paren should consider itself binary */ lasttok = TOK_NUM; goto next; } +//bb_error_msg("prev_op != TOK_LPAREN"); } else { operator prev_prec = PREC(prev_op); +//bb_error_msg("op != TOK_RPAREN"); fix_assignment_prec(prec); fix_assignment_prec(prev_prec); if (prev_prec < prec @@ -785,6 +791,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) break; } } +//bb_error_msg("arith_apply(prev_op:%02x)", prev_op); errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); if (errmsg) goto err_with_custom_msg; @@ -794,6 +801,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) } /* Push this operator to the stack and remember it */ +//bb_error_msg("push op:%02x", op); *stackptr++ = lasttok = op; next: ; } /* while (1) */ -- cgit v1.2.3-55-g6feb From 5b026d1ecf2df93d31248153a7f5d0c45a5d12fa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 28 Sep 2021 17:41:56 +0200 Subject: ash: fix compile breakage in !ENABLE_ASH_ALIAS config Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 4bc4f55d0..4bf0615ea 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10941,14 +10941,14 @@ static void freestrings(struct strpush *sp) INT_OFF; do { struct strpush *psp; - +#if ENABLE_ASH_ALIAS if (sp->ap) { sp->ap->flag &= ~ALIASINUSE; if (sp->ap->flag & ALIASDEAD) { unalias(sp->ap->name); } } - +#endif psp = sp; sp = sp->spfree; -- cgit v1.2.3-55-g6feb From 1f925038ab9c6bd8f6b3cd40ed7aab0ef10d898e Mon Sep 17 00:00:00 2001 From: YU Jincheng Date: Wed, 29 Sep 2021 17:37:26 +0800 Subject: *: generalize "const trick" While at it, change all "__asm__" to "asm" Co-authored-by: canyie <31466456+canyie@users.noreply.github.com> Signed-off-by: YU Jincheng Signed-off-by: Denys Vlasenko --- coreutils/test.c | 5 ++--- include/libbb.h | 34 +++++++++++++++++++++++++--------- libbb/appletlib.c | 3 +-- libbb/lineedit.c | 5 ++--- procps/powertop.c | 2 +- shell/ash.c | 23 +++-------------------- 6 files changed, 34 insertions(+), 38 deletions(-) (limited to 'shell') diff --git a/coreutils/test.c b/coreutils/test.c index 7c6574334..fc956724b 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -435,7 +435,7 @@ struct test_statics { }; /* See test_ptr_hack.c */ -extern struct test_statics *const test_ptr_to_statics; +extern struct test_statics *BB_GLOBAL_CONST test_ptr_to_statics; #define S (*test_ptr_to_statics) #define args (S.args ) @@ -446,8 +446,7 @@ extern struct test_statics *const test_ptr_to_statics; #define leaving (S.leaving ) #define INIT_S() do { \ - (*(struct test_statics**)not_const_pp(&test_ptr_to_statics)) = xzalloc(sizeof(S)); \ - barrier(); \ + ASSIGN_CONST_PTR(test_ptr_to_statics, xzalloc(sizeof(S))); \ } while (0) #define DEINIT_S() do { \ free(group_array); \ diff --git a/include/libbb.h b/include/libbb.h index dfcaa05ec..02cc008f0 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -365,13 +365,27 @@ struct BUG_off_t_size_is_misdetected { #endif #endif +/* We use a trick to have more optimized code (fewer pointer reloads + * and reduced binary size by a few kilobytes) like: + * ash.c: extern struct globals *const ash_ptr_to_globals; + * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; + * This way, compiler in ash.c knows the pointer can not change. + * + * However, this may break on weird arches or toolchains. In this case, + * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable + * this optimization. + */ +#ifndef BB_GLOBAL_CONST +# define BB_GLOBAL_CONST const +#endif + #if defined(errno) /* If errno is a define, assume it's "define errno (*__errno_location())" * and we will cache it's result in this variable */ -extern int *const bb_errno; -#undef errno -#define errno (*bb_errno) -#define bb_cached_errno_ptr 1 +extern int *BB_GLOBAL_CONST bb_errno; +# undef errno +# define errno (*bb_errno) +# define bb_cached_errno_ptr 1 #endif #if !(ULONG_MAX > 0xffffffff) @@ -2270,6 +2284,8 @@ struct globals; * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ extern struct globals *const ptr_to_globals; +#define barrier() asm volatile ("":::"memory") + #if defined(__clang_major__) && __clang_major__ >= 9 /* Clang/llvm drops assignment to "constant" storage. Silently. * Needs serious convincing to not eliminate the store. @@ -2277,7 +2293,7 @@ extern struct globals *const ptr_to_globals; static ALWAYS_INLINE void* not_const_pp(const void *p) { void *pp; - __asm__ __volatile__( + asm volatile ( "# forget that p points to const" : /*outputs*/ "=r" (pp) : /*inputs*/ "0" (p) @@ -2288,13 +2304,13 @@ static ALWAYS_INLINE void* not_const_pp(const void *p) static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; } #endif -/* At least gcc 3.4.6 on mipsel system needs optimization barrier */ -#define barrier() __asm__ __volatile__("":::"memory") -#define SET_PTR_TO_GLOBALS(x) do { \ - (*(struct globals**)not_const_pp(&ptr_to_globals)) = (void*)(x); \ +#define ASSIGN_CONST_PTR(p, v) do { \ + *(void**)not_const_pp(&p) = (void*)(v); \ + /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \ barrier(); \ } while (0) +#define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(ptr_to_globals, x) #define FREE_PTR_TO_GLOBALS() do { \ if (ENABLE_FEATURE_CLEAN_UP) { \ free(ptr_to_globals); \ diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 5c5d7eb95..bf26c99e9 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -247,8 +247,7 @@ void lbb_prepare(const char *applet IF_FEATURE_INDIVIDUAL(, char **argv)) { #ifdef bb_cached_errno_ptr - (*(int **)not_const_pp(&bb_errno)) = get_perrno(); - barrier(); + ASSIGN_CONST_PTR(bb_errno, get_perrno()); #endif applet_name = applet; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index a7a3ee103..3c87abcf9 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -192,7 +192,7 @@ struct lineedit_statics { }; /* See lineedit_ptr_hack.c */ -extern struct lineedit_statics *const lineedit_ptr_to_statics; +extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics; #define S (*lineedit_ptr_to_statics) #define state (S.state ) @@ -214,8 +214,7 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; #define delbuf (S.delbuf ) #define INIT_S() do { \ - (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ - barrier(); \ + ASSIGN_CONST_PTR(lineedit_ptr_to_statics, xzalloc(sizeof(S))); \ } while (0) static void deinit_S(void) diff --git a/procps/powertop.c b/procps/powertop.c index fc6018b7a..24c2b320f 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -505,7 +505,7 @@ static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { /* EAX value specifies what information to return */ - __asm__( + asm ( " pushl %%ebx\n" /* Save EBX */ " cpuid\n" " movl %%ebx, %1\n" /* Save content of EBX */ diff --git a/shell/ash.c b/shell/ash.c index 4bf0615ea..7b85981ec 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -303,20 +303,6 @@ typedef long arith_t; # error "Do not even bother, ash will not run on NOMMU machine" #endif -/* We use a trick to have more optimized code (fewer pointer reloads): - * ash.c: extern struct globals *const ash_ptr_to_globals; - * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; - * This way, compiler in ash.c knows the pointer can not change. - * - * However, this may break on weird arches or toolchains. In this case, - * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable - * this optimization. - */ -#ifndef BB_GLOBAL_CONST -# define BB_GLOBAL_CONST const -#endif - - /* ============ Hash table sizes. Configurable. */ #define VTABSIZE 39 @@ -518,8 +504,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; #define random_gen (G_misc.random_gen ) #define backgndpid (G_misc.backgndpid ) #define INIT_G_misc() do { \ - (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ - barrier(); \ + ASSIGN_CONST_PTR(ash_ptr_to_globals_misc, xzalloc(sizeof(G_misc))); \ savestatus = -1; \ curdir = nullstr; \ physdir = nullstr; \ @@ -1597,8 +1582,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; #define g_stacknleft (G_memstack.g_stacknleft) #define stackbase (G_memstack.stackbase ) #define INIT_G_memstack() do { \ - (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ - barrier(); \ + ASSIGN_CONST_PTR(ash_ptr_to_globals_memstack, xzalloc(sizeof(G_memstack))); \ g_stackp = &stackbase; \ g_stacknxt = stackbase.space; \ g_stacknleft = MINSIZE; \ @@ -2229,8 +2213,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #endif #define INIT_G_var() do { \ unsigned i; \ - (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ - barrier(); \ + ASSIGN_CONST_PTR(ash_ptr_to_globals_var, xzalloc(sizeof(G_var))); \ for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ varinit[i].flags = varinit_data[i].flags; \ varinit[i].var_text = varinit_data[i].var_text; \ -- cgit v1.2.3-55-g6feb From 21e8dbfd9d11a461ed7f91b495fa39d8a9131b28 Mon Sep 17 00:00:00 2001 From: Alin Mr Date: Wed, 28 Jul 2021 11:40:01 +0300 Subject: ash.c: speedup ${s:} substring (no quotes) This trivial patch makes ${s:...} at least as fast as ${s#??..} in simple tests. It's probably faster for longer substrings, but then one wouldn't use ${s#"1024???s"} anyway - one would switch away from sh. function old new delta subevalvar 1457 1503 +46 Signed-off-by: Alin Mr Signed-off-by: Denys Vlasenko --- shell/ash.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 7b85981ec..e8ec0b1a6 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7185,14 +7185,19 @@ subevalvar(char *start, char *str, int strloc, if ((unsigned)len > (orig_len - pos)) len = orig_len - pos; - for (vstr = startp; pos; vstr++, pos--) { - if (quotes && (unsigned char)*vstr == CTLESC) + if (!quotes) { + loc = mempcpy(startp, startp + pos, len); + } else { + for (vstr = startp; pos != 0; pos--) { + if ((unsigned char)*vstr == CTLESC) + vstr++; vstr++; - } - for (loc = startp; len; len--) { - if (quotes && (unsigned char)*vstr == CTLESC) + } + for (loc = startp; len != 0; len--) { + if ((unsigned char)*vstr == CTLESC) + *loc++ = *vstr++; *loc++ = *vstr++; - *loc++ = *vstr++; + } } *loc = '\0'; goto out; -- cgit v1.2.3-55-g6feb From 5aaeb550b76f063ffddef8587d9d91f7fddc4406 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 9 Oct 2021 03:32:20 +0200 Subject: ash: speed up ${x//\*/|} too, make it independent of ASH_OPTIMIZE_FOR_SIZE function old new delta subevalvar 1503 1545 +42 Signed-off-by: Denys Vlasenko --- shell/ash.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index e8ec0b1a6..199975191 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7251,7 +7251,7 @@ subevalvar(char *start, char *str, int strloc, #if BASH_PATTERN_SUBST workloc = expdest - (char *)stackblock(); if (subtype == VSREPLACE || subtype == VSREPLACEALL) { - size_t no_meta_len; + size_t no_meta_len, first_escaped; int len; char *idx, *end; @@ -7269,28 +7269,34 @@ subevalvar(char *start, char *str, int strloc, if (str[0] == '\0') goto out1; - no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); + first_escaped = (str[0] == '\\' && str[1]); + /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" + * as literal too (as it is semi-common, and easy to accomodate + * by just using str + 1). + */ + no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str); len = 0; idx = startp; end = str - 1; while (idx <= end) { try_to_match: if (no_meta_len == 0) { - /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ + /* pattern has meta chars, have to glob */ loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); } else { /* Testcase for very slow replace (performs about 22k replaces): * x=:::::::::::::::::::::: * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} * echo "${x//:/|}" + * To test "first_escaped" logic, replace : with *. */ - if (strncmp(rmesc, str, no_meta_len) != 0) + if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0) goto no_match; loc = idx; if (!quotes) { - loc += no_meta_len; + loc += no_meta_len - first_escaped; } else { - size_t n = no_meta_len; + size_t n = no_meta_len - first_escaped; do { if ((unsigned char)*loc == CTLESC) loc++; -- cgit v1.2.3-55-g6feb From 49bcf9f40cff1320a761d674cf89a0c0ab97ef49 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 9 Oct 2021 03:52:04 +0200 Subject: hush: speed up ${x//\*/|} too function old new delta expand_one_var 2502 2544 +42 Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index 6d472337f..87fc2f445 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) /* ${var/[/]pattern[/repl]} helpers */ static char *strstr_pattern(char *val, const char *pattern, int *size) { - int sz = strcspn(pattern, "*?[\\"); - if (pattern[sz] == '\0') { + int first_escaped = (pattern[0] == '\\' && pattern[1]); + /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" + * as literal too (as it is semi-common, and easy to accomodate + * by just using str + 1). + */ + int sz = strcspn(pattern + first_escaped * 2, "*?[\\"); + if ((pattern + first_escaped * 2)[sz] == '\0') { /* Optimization for trivial patterns. * Testcase for very slow replace (performs about 22k replaces): * x=:::::::::::::::::::::: * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} * echo "${x//:/|}" */ - *size = sz; - return strstr(val, pattern); + *size = sz + first_escaped; + return strstr(val, pattern + first_escaped); } while (1) { -- cgit v1.2.3-55-g6feb From 5156b245536ce0f07165793f07c63fd9fa5dd3b7 Mon Sep 17 00:00:00 2001 From: YU Jincheng Date: Sun, 10 Oct 2021 02:19:51 +0800 Subject: Make const ptr assign as function call in clang - This can act as memory barrier in clang to avoid read before assign of a const ptr Signed-off-by: LoveSy Signed-off-by: Denys Vlasenko --- coreutils/test.c | 2 +- include/libbb.h | 21 +++++++++++++++------ libbb/Kbuild.src | 1 + libbb/appletlib.c | 2 +- libbb/const_hack.c | 16 ++++++++++++++++ libbb/lineedit.c | 2 +- shell/ash.c | 6 +++--- 7 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 libbb/const_hack.c (limited to 'shell') diff --git a/coreutils/test.c b/coreutils/test.c index fc956724b..a914c7490 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -446,7 +446,7 @@ extern struct test_statics *BB_GLOBAL_CONST test_ptr_to_statics; #define leaving (S.leaving ) #define INIT_S() do { \ - ASSIGN_CONST_PTR(test_ptr_to_statics, xzalloc(sizeof(S))); \ + XZALLOC_CONST_PTR(&test_ptr_to_statics, sizeof(S)); \ } while (0) #define DEINIT_S() do { \ free(group_array); \ diff --git a/include/libbb.h b/include/libbb.h index 296417dae..a340f27d2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2280,6 +2280,7 @@ extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */ extern const int const_int_0; //extern const int const_int_1; + /* This struct is deliberately not defined. */ /* See docs/keep_data_small.txt */ struct globals; @@ -2304,23 +2305,31 @@ static ALWAYS_INLINE void* not_const_pp(const void *p) ); return pp; } +# define ASSIGN_CONST_PTR(pptr, v) do { \ + *(void**)not_const_pp(pptr) = (void*)(v); \ + barrier(); \ +} while (0) +/* XZALLOC_CONST_PTR() is an out-of-line function to prevent + * clang from reading pointer before it is assigned. + */ +void XZALLOC_CONST_PTR(const void *pptr, size_t size) FAST_FUNC; #else -static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; } -#endif - -#define ASSIGN_CONST_PTR(p, v) do { \ - *(void**)not_const_pp(&p) = (void*)(v); \ +# define ASSIGN_CONST_PTR(pptr, v) do { \ + *(void**)(pptr) = (void*)(v); \ /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \ barrier(); \ } while (0) +# define XZALLOC_CONST_PTR(pptr, size) ASSIGN_CONST_PTR(pptr, xzalloc(size)) +#endif -#define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(ptr_to_globals, x) +#define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(&ptr_to_globals, x) #define FREE_PTR_TO_GLOBALS() do { \ if (ENABLE_FEATURE_CLEAN_UP) { \ free(ptr_to_globals); \ } \ } while (0) + /* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it, * use bb_default_login_shell and following defines. * If you change LIBBB_DEFAULT_LOGIN_SHELL, diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 676300801..2fa239857 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -24,6 +24,7 @@ lib-y += chomp.o lib-y += compare_string_array.o lib-y += concat_path_file.o lib-y += concat_subpath_file.o +lib-y += const_hack.o lib-y += copy_file.o lib-y += copyfd.o lib-y += crc32.o diff --git a/libbb/appletlib.c b/libbb/appletlib.c index bf26c99e9..e8c308467 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -247,7 +247,7 @@ void lbb_prepare(const char *applet IF_FEATURE_INDIVIDUAL(, char **argv)) { #ifdef bb_cached_errno_ptr - ASSIGN_CONST_PTR(bb_errno, get_perrno()); + ASSIGN_CONST_PTR(&bb_errno, get_perrno()); #endif applet_name = applet; diff --git a/libbb/const_hack.c b/libbb/const_hack.c new file mode 100644 index 000000000..9575e6d67 --- /dev/null +++ b/libbb/const_hack.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * Trick to assign a const ptr with barrier for clang + * + * Copyright (C) 2021 by YU Jincheng + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +#include "libbb.h" + +#if defined(__clang_major__) && __clang_major__ >= 9 +void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size) +{ + ASSIGN_CONST_PTR(pptr, xzalloc(size)); +} +#endif diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 3c87abcf9..9960448ec 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -214,7 +214,7 @@ extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics; #define delbuf (S.delbuf ) #define INIT_S() do { \ - ASSIGN_CONST_PTR(lineedit_ptr_to_statics, xzalloc(sizeof(S))); \ + XZALLOC_CONST_PTR(&lineedit_ptr_to_statics, sizeof(S)); \ } while (0) static void deinit_S(void) diff --git a/shell/ash.c b/shell/ash.c index 199975191..2d3cc8a61 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -504,7 +504,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; #define random_gen (G_misc.random_gen ) #define backgndpid (G_misc.backgndpid ) #define INIT_G_misc() do { \ - ASSIGN_CONST_PTR(ash_ptr_to_globals_misc, xzalloc(sizeof(G_misc))); \ + XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \ savestatus = -1; \ curdir = nullstr; \ physdir = nullstr; \ @@ -1582,7 +1582,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; #define g_stacknleft (G_memstack.g_stacknleft) #define stackbase (G_memstack.stackbase ) #define INIT_G_memstack() do { \ - ASSIGN_CONST_PTR(ash_ptr_to_globals_memstack, xzalloc(sizeof(G_memstack))); \ + XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \ g_stackp = &stackbase; \ g_stacknxt = stackbase.space; \ g_stacknleft = MINSIZE; \ @@ -2213,7 +2213,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #endif #define INIT_G_var() do { \ unsigned i; \ - ASSIGN_CONST_PTR(ash_ptr_to_globals_var, xzalloc(sizeof(G_var))); \ + XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \ for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ varinit[i].flags = varinit_data[i].flags; \ varinit[i].var_text = varinit_data[i].var_text; \ -- cgit v1.2.3-55-g6feb From 53b2fdcdba4ced600da963147be425a21d0f6e53 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 10 Oct 2021 13:50:53 +0200 Subject: *: add NOINLINEs where code noticeably shrinks function old new delta display 85 1463 +1378 -73 bytes select_and_cluster - 1088 +1088 -139 bytes parse_reply - 979 +979 -109 bytes zbc_num_sqrt - 632 +632 -191 bytes show_bridge_port - 585 +585 -56 bytes sp_256_proj_point_add_8 - 576 +576 -45 bytes encode_then_append_var_plusminus - 554 +554 -118 bytes read_mode_db - 537 +537 -47 bytes fbset_main 1331 747 -584 sp_256_ecc_mulmod_8 1157 536 -621 brctl_main 2189 1548 -641 expand_one_var 2544 1872 -672 zxc_vm_process 6412 5589 -823 send_queries 1813 725 -1088 recv_and_process_peer_pkt 2245 1018 -1227 bb_dump_dump 1531 80 -1451 ------------------------------------------------------------------------------ (add/remove: 7/0 grow/shrink: 1/8 up/down: 6329/-7107) Total: -778 bytes Signed-off-by: Denys Vlasenko --- libbb/dump.c | 2 +- miscutils/bc.c | 2 +- networking/brctl.c | 2 +- networking/nslookup.c | 2 +- networking/ntpd.c | 2 +- networking/tls_sp_c32.c | 2 +- shell/hush.c | 2 +- util-linux/fbset.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'shell') diff --git a/libbb/dump.c b/libbb/dump.c index f8bb6fd03..fcdee8343 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -532,7 +532,7 @@ static void conv_u(PR *pr, unsigned char *p) } } -static void display(priv_dumper_t* dumper) +static NOINLINE void display(priv_dumper_t* dumper) { unsigned char *bp; unsigned char savech = '\0'; diff --git a/miscutils/bc.c b/miscutils/bc.c index f9b08b01e..ae370ff55 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2261,7 +2261,7 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size } #define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) +static NOINLINE BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) { BcStatus s; BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; diff --git a/networking/brctl.c b/networking/brctl.c index c83aac6e0..956bd91f3 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -318,7 +318,7 @@ static void printf_xstrtou(const char *fmt) printf(fmt, xstrtou(filedata, 0)); } -static void show_bridge_port(const char *name) +static NOINLINE void show_bridge_port(const char *name) { char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 8]; char *sfx; diff --git a/networking/nslookup.c b/networking/nslookup.c index de7b5c0e7..6da97baf4 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -335,7 +335,7 @@ enum { OPT_debug = (1 << 0), }; -static int parse_reply(const unsigned char *msg, size_t len) +static NOINLINE int parse_reply(const unsigned char *msg, size_t len) { HEADER *header; diff --git a/networking/ntpd.c b/networking/ntpd.c index 5bd4d2d3e..204e1d7c2 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1152,7 +1152,7 @@ fit(peer_t *p, double rd) // return 0; return 1; } -static peer_t* +static NOINLINE peer_t* select_and_cluster(void) { peer_t *p; diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c index 4c0cd320b..4d4ecdd74 100644 --- a/networking/tls_sp_c32.c +++ b/networking/tls_sp_c32.c @@ -1162,7 +1162,7 @@ static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p) * p Frist point to add. * q Second point to add. */ -static void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q) +static NOINLINE void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q) { sp_digit t1[2*8]; sp_digit t2[2*8]; diff --git a/shell/hush.c b/shell/hush.c index 87fc2f445..7156297cf 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6311,7 +6311,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int /* Expanding ARG in ${var+ARG}, ${var-ARG} */ -static int encode_then_append_var_plusminus(o_string *output, int n, +static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n, char *str, int dquoted) { struct in_str input; diff --git a/util-linux/fbset.c b/util-linux/fbset.c index cc5413b40..41cc29f37 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -267,7 +267,7 @@ static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what) * vsync high * endmode */ -static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, +static NOINLINE int read_mode_db(struct fb_var_screeninfo *base, const char *fn, const char *mode) { char *token[2], *p, *s; -- cgit v1.2.3-55-g6feb From 5acf5e1f870fb5382556d4b434158f7d497893ca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Oct 2021 18:39:25 +0200 Subject: shell: fix script's comm field if ENABLE_FEATURE_PREFER_APPLETS=y function old new delta re_execed_comm - 46 +46 main 72 86 +14 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 60/0) Total: 60 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ libbb/appletlib.c | 10 ++++++++-- libbb/vfork_daemon_rexec.c | 16 ++++++++++++++++ shell/ash_test/ash-comm/comm.right | 6 ++++++ shell/ash_test/ash-comm/comm.tests | 20 ++++++++++++++++++++ shell/hush_test/hush-comm/comm.right | 6 ++++++ shell/hush_test/hush-comm/comm.tests | 20 ++++++++++++++++++++ 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 shell/ash_test/ash-comm/comm.right create mode 100755 shell/ash_test/ash-comm/comm.tests create mode 100644 shell/hush_test/hush-comm/comm.right create mode 100755 shell/hush_test/hush-comm/comm.tests (limited to 'shell') diff --git a/include/libbb.h b/include/libbb.h index a340f27d2..2a0b272c6 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1271,8 +1271,10 @@ void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_ #endif void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC; #if defined(__linux__) +int re_execed_comm(void) FAST_FUNC; void set_task_comm(const char *comm) FAST_FUNC; #else +# define re_execed_comm() 0 # define set_task_comm(name) ((void)0) #endif diff --git a/libbb/appletlib.c b/libbb/appletlib.c index e8c308467..03389f541 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -1112,8 +1112,14 @@ int main(int argc UNUSED_PARAM, char **argv) || ENABLE_FEATURE_PREFER_APPLETS || !BB_MMU ) { - if (NUM_APPLETS > 1) - set_task_comm(applet_name); + if (NUM_APPLETS > 1) { + /* Careful, do not trash comm of "SCRIPT.sh" - + * the case when started from e.g. #!/bin/ash script. + * (not limited to shells - #!/bin/awk scripts also exist) + */ + if (re_execed_comm()) + set_task_comm(applet_name); + } } parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index a49fe8e01..31e97051f 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -28,6 +28,22 @@ # ifndef PR_GET_NAME # define PR_GET_NAME 16 # endif +# if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS || !BB_MMU +int FAST_FUNC re_execed_comm(void) +{ + const char *e, *expected_comm; + char comm[16]; + + BUILD_BUG_ON(CONFIG_BUSYBOX_EXEC_PATH[0] != '/'); + e = CONFIG_BUSYBOX_EXEC_PATH; + /* Hopefully (strrchr(e) - e) evaluates to constant at compile time: */ + expected_comm = bb_busybox_exec_path + (strrchr(e, '/') - e) + 1; + + prctl(PR_GET_NAME, (long)comm, 0, 0, 0); + //bb_error_msg("comm:'%.*s' expected:'%s'", 16, comm, expected_comm); + return strcmp(comm, expected_comm) == 0; +} +# endif void FAST_FUNC set_task_comm(const char *comm) { /* okay if too long (truncates) */ diff --git a/shell/ash_test/ash-comm/comm.right b/shell/ash_test/ash-comm/comm.right new file mode 100644 index 000000000..1d836656f --- /dev/null +++ b/shell/ash_test/ash-comm/comm.right @@ -0,0 +1,6 @@ +./SCRIPT.sh: + /proc/N/comm: SCRIPT.sh +exec ./SCRIPT.sh: + /proc/N/comm: SCRIPT.sh +sh ./SCRIPT.sh: + /proc/N/comm: ash diff --git a/shell/ash_test/ash-comm/comm.tests b/shell/ash_test/ash-comm/comm.tests new file mode 100755 index 000000000..671bfc176 --- /dev/null +++ b/shell/ash_test/ash-comm/comm.tests @@ -0,0 +1,20 @@ +{ +echo "#!$THIS_SH" +echo 'procdir=/proc/$$' +#echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"' +echo 'echo " /proc/N/comm: $(cat $procdir/comm)"' +} >SCRIPT.sh +chmod 755 SCRIPT.sh + +# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y +echo './SCRIPT.sh:' +./SCRIPT.sh + +# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y +echo 'exec ./SCRIPT.sh:' +(exec ./SCRIPT.sh) + +echo 'sh ./SCRIPT.sh:' +$THIS_SH ./SCRIPT.sh + +rm SCRIPT.sh diff --git a/shell/hush_test/hush-comm/comm.right b/shell/hush_test/hush-comm/comm.right new file mode 100644 index 000000000..1b62b617e --- /dev/null +++ b/shell/hush_test/hush-comm/comm.right @@ -0,0 +1,6 @@ +./SCRIPT.sh: + /proc/N/comm: SCRIPT.sh +exec ./SCRIPT.sh: + /proc/N/comm: SCRIPT.sh +sh ./SCRIPT.sh: + /proc/N/comm: hush diff --git a/shell/hush_test/hush-comm/comm.tests b/shell/hush_test/hush-comm/comm.tests new file mode 100755 index 000000000..671bfc176 --- /dev/null +++ b/shell/hush_test/hush-comm/comm.tests @@ -0,0 +1,20 @@ +{ +echo "#!$THIS_SH" +echo 'procdir=/proc/$$' +#echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"' +echo 'echo " /proc/N/comm: $(cat $procdir/comm)"' +} >SCRIPT.sh +chmod 755 SCRIPT.sh + +# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y +echo './SCRIPT.sh:' +./SCRIPT.sh + +# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y +echo 'exec ./SCRIPT.sh:' +(exec ./SCRIPT.sh) + +echo 'sh ./SCRIPT.sh:' +$THIS_SH ./SCRIPT.sh + +rm SCRIPT.sh -- cgit v1.2.3-55-g6feb From 7c3e96d4b3d419d76f97e17d42a4401ee685b7ec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Oct 2021 01:24:32 +0200 Subject: shell: use more compact SHELL_ASH / HUSH config defines. no code changes Signed-off-by: Denys Vlasenko --- include/libbb.h | 12 ++---------- shell/hush.c | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'shell') diff --git a/include/libbb.h b/include/libbb.h index 2a0b272c6..a48782832 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1502,16 +1502,8 @@ int scripted_main(int argc, char** argv) MAIN_EXTERNALLY_VISIBLE; /* Applets which are useful from another applets */ int bb_cat(char** argv) FAST_FUNC; -int ash_main(int argc, char** argv) -#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH - MAIN_EXTERNALLY_VISIBLE -#endif -; -int hush_main(int argc, char** argv) -#if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH - MAIN_EXTERNALLY_VISIBLE -#endif -; +int ash_main(int argc, char** argv) IF_SHELL_ASH(MAIN_EXTERNALLY_VISIBLE); +int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); /* If shell needs them, they exist even if not enabled as applets */ int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); diff --git a/shell/hush.c b/shell/hush.c index 7156297cf..38d924a3f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -373,7 +373,7 @@ # define F_DUPFD_CLOEXEC F_DUPFD #endif -#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH # include "embedded_scripts.h" #else # define NUM_SCRIPTS 0 -- cgit v1.2.3-55-g6feb From 62f1eed1e1916afbff8f9ce3f820626348e8b867 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Oct 2021 22:39:11 +0200 Subject: hush: in a comment, document what -i might be doing Signed-off-by: Denys Vlasenko --- shell/ash.c | 5 ++--- shell/hush.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 2d3cc8a61..1982a24b7 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -14657,11 +14657,10 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } state2: state = 3; - if ( + if (iflag #ifndef linux - getuid() == geteuid() && getgid() == getegid() && + && getuid() == geteuid() && getgid() == getegid() #endif - iflag ) { const char *shinit = lookupvar("ENV"); if (shinit != NULL && *shinit != '\0') diff --git a/shell/hush.c b/shell/hush.c index 38d924a3f..3a17f5bd5 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3360,7 +3360,7 @@ static int glob_brace(char *pattern, o_string *o, int n) * NEXT points past the terminator of the first element, and REST * points past the final }. We will accumulate result names from * recursive runs for each brace alternative in the buffer using - * GLOB_APPEND. */ + * GLOB_APPEND. */ p = begin + 1; while (1) { @@ -10225,7 +10225,7 @@ int hush_main(int argc, char **argv) cached_getpid = getpid(); /* for tcsetpgrp() during init */ G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ - G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ + G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ /* Deal with HUSH_VERSION */ debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); @@ -10356,6 +10356,29 @@ int hush_main(int argc, char **argv) /* Well, we cannot just declare interactiveness, * we have to have some stuff (ctty, etc) */ /* G_interactive_fd++; */ +//There are a few cases where bash -i -c 'SCRIPT' +//has visible effect (differs from bash -c 'SCRIPT'): +//it ignores TERM: +// bash -i -c 'kill $$; echo ALIVE' +// ALIVE +//it resets SIG_INGed HUP to SIG_DFL: +// trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' +// Hangup [the message is not printed by bash, it's the shell which started it] +//is talkative about jobs and exiting: +// bash -i -c 'sleep 1 & exit' +// [1] 16170 +// exit +//includes $ENV file (only if run as "sh"): +// echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE' +// last: cannot open /var/log/wtmp: No such file or directory +// HERE +//(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i). +// +//ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting +//(this may be a bug, bash does not do this). +//(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed) +// +//None of the above feel like useful features people would rely on. break; case 's': G.opt_s = 1; @@ -11732,7 +11755,7 @@ static int FAST_FUNC builtin_fg_bg(char **argv) /* TODO: bash prints a string representation * of job being foregrounded (like "sleep 1 | cat") */ if (argv[0][0] == 'f' && G_saved_tty_pgrp) { - /* Put the job into the foreground. */ + /* Put the job into the foreground. */ tcsetpgrp(G_interactive_fd, pi->pgrp); } -- cgit v1.2.3-55-g6feb From aaf3d5ba74c5da97ff80b61f30cb8dd225d39096 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Oct 2021 11:15:52 +0200 Subject: shell: tweak --help Even though formally it is -s [ARGS], "sh -s" without ARGS is the same as just "sh". And we are already over 80 chars wide for ash --help, so make it shorter. Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- shell/hush.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 1982a24b7..827643808 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -14455,7 +14455,7 @@ init(void) //usage:#define ash_trivial_usage -//usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" +//usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" //////// comes from ^^^^^^^^^^optletters //usage:#define ash_full_usage "\n\n" //usage: "Unix shell interpreter" diff --git a/shell/hush.c b/shell/hush.c index 3a17f5bd5..6a27b1634 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -339,7 +339,7 @@ * therefore we don't show them either. */ //usage:#define hush_trivial_usage -//usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" +//usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" //usage:#define hush_full_usage "\n\n" //usage: "Unix shell interpreter" -- cgit v1.2.3-55-g6feb