external/mksh
Revision | 811a575c0f6a5ef00a921d14c1830ef5ae1bd796 (tree) |
---|---|
Time | 2013-08-15 06:33:39 |
Author | Thorsten Glaser <tg@mirb...> |
Commiter | Thorsten Glaser |
Update to mksh R48
Change-Id: I4d1bef9bf8ddc7899cfb32a6f2fa9e6f632bc53f
@@ -37,6 +37,7 @@ LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src | ||
37 | 37 | LOCAL_CFLAGS:= -DMKSHRC_PATH=\"/system/etc/mkshrc\" \ |
38 | 38 | -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \ |
39 | 39 | -DMKSH_DEFAULT_TMPDIR=\"/data/local\" \ |
40 | + -Wno-deprecated-declarations \ | |
40 | 41 | -fno-asynchronous-unwind-tables -fwrapv \ |
41 | 42 | -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS \ |
42 | 43 | -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH \ |
@@ -62,9 +63,8 @@ LOCAL_CFLAGS:= -DMKSHRC_PATH=\"/system/etc/mkshrc\" \ | ||
62 | 63 | -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 \ |
63 | 64 | -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \ |
64 | 65 | -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 \ |
65 | - -DHAVE_PERSISTENT_HISTORY=0 -DHAVE_SILENT_IDIVWRAPV=0 \ | |
66 | - -DMKSH_BUILD_R=431 | |
66 | + -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=481 | |
67 | 67 | |
68 | -# check categories: shell:legacy-no int:32 android convfds no-histfile | |
68 | +# check_categories= shell:legacy-no int:32 android convfds no-histfile | |
69 | 69 | |
70 | 70 | include $(BUILD_EXECUTABLE) |
@@ -64,7 +64,6 @@ addvar CPPFLAGS \ | ||
64 | 64 | -isystem $aospdir/frameworks/native/opengl/include \ |
65 | 65 | -isystem $aospdir/frameworks/av/include \ |
66 | 66 | -isystem $aospdir/frameworks/base/include \ |
67 | - -isystem $aospdir/frameworks/base/opengl/include \ | |
68 | 67 | -isystem $aospdir/external/skia/include \ |
69 | 68 | -isystem $aospdir/out/target/product/generic/obj/include \ |
70 | 69 | -isystem $aospdir/bionic/libc/arch-arm/include \ |
@@ -75,11 +74,10 @@ addvar CPPFLAGS \ | ||
75 | 74 | -isystem $aospdir/bionic/libm/include \ |
76 | 75 | -isystem $aospdir/bionic/libm/include/arm \ |
77 | 76 | -isystem $aospdir/bionic/libthread_db/include \ |
78 | - -D_FORTIFY_SOURCE=1 \ | |
77 | + -D_FORTIFY_SOURCE=2 \ | |
79 | 78 | -include $aospdir/build/core/combo/include/arch/linux-arm/AndroidConfig.h \ |
80 | 79 | -I$aospdir/build/core/combo/include/arch/linux-arm/ \ |
81 | 80 | -DANDROID -DNDEBUG -UDEBUG |
82 | -# who would have thought the AOSP devs are funny? -fno-builtin-sin | |
83 | 81 | addvar CFLAGS \ |
84 | 82 | -fno-exceptions \ |
85 | 83 | -Wno-multichar \ |
@@ -123,6 +121,7 @@ addvar CFLAGS \ | ||
123 | 121 | addvar LDFLAGS \ |
124 | 122 | -nostdlib \ |
125 | 123 | -Bdynamic \ |
124 | + -fPIE \ | |
126 | 125 | -pie \ |
127 | 126 | -Wl,-dynamic-linker,/system/bin/linker \ |
128 | 127 | -Wl,--gc-sections \ |
@@ -131,6 +130,7 @@ addvar LDFLAGS \ | ||
131 | 130 | -Wl,-z,relro \ |
132 | 131 | -Wl,-z,now \ |
133 | 132 | -Wl,--warn-shared-textrel \ |
133 | + -Wl,--fatal-warnings \ | |
134 | 134 | -Wl,--icf=safe \ |
135 | 135 | -Wl,--fix-cortex-a8 \ |
136 | 136 | -Wl,--no-undefined \ |
@@ -138,9 +138,9 @@ addvar LDFLAGS \ | ||
138 | 138 | addvar LIBS \ |
139 | 139 | -L$aospdir/out/target/product/generic/obj/lib \ |
140 | 140 | -Wl,-rpath-link=$aospdir/out/target/product/generic/obj/lib \ |
141 | - -lc \ | |
142 | 141 | -Wl,--no-whole-archive \ |
143 | - $aospdir/out/target/product/generic/obj/STATIC_LIBRARIES/libcompiler-rt-extras_intermediates/libcompiler-rt-extras.a \ | |
142 | + $aospdir/out/target/product/generic/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a \ | |
143 | + -lc \ | |
144 | 144 | $aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/../lib/gcc/arm-linux-androideabi/4.7/armv7-a/libgcc.a \ |
145 | 145 | $aospdir/out/target/product/generic/obj/lib/crtend_android.o |
146 | 146 |
@@ -181,11 +181,6 @@ export HAVE_CAN_FNOSTRICTALIASING HAVE_CAN_FSTACKPROTECTORALL HAVE_CAN_WALL | ||
181 | 181 | # even the idea of persistent history on a phone is funny |
182 | 182 | HAVE_PERSISTENT_HISTORY=0; export HAVE_PERSISTENT_HISTORY |
183 | 183 | |
184 | -# this is a run-time check and dependent on the target CPU | |
185 | -# architecture (at _least_!) and cannot be auto-detected, | |
186 | -# so always include the safety check even if unnecessary | |
187 | -HAVE_SILENT_IDIVWRAPV=0; export HAVE_SILENT_IDIVWRAPV | |
188 | - | |
189 | 184 | # ... and run it! |
190 | 185 | export CC CPPFLAGS CFLAGS LDFLAGS LIBS TARGET_OS |
191 | 186 | sh ../src/Build.sh $args |
@@ -9,12 +9,13 @@ | ||
9 | 9 | : ${TERM:=vt100} ${HOME:=/data} ${MKSH:=/system/bin/sh} ${HOSTNAME:=$(getprop ro.product.device)} |
10 | 10 | : ${SHELL:=$MKSH} ${USER:=$(typeset x=$(id); x=${x#*\(}; print -r -- ${x%%\)*})} ${HOSTNAME:=android} |
11 | 11 | if (( USER_ID )); then PS1='$'; else PS1='#'; fi |
12 | -function precmd { | |
13 | - typeset e=$? | |
12 | +PS4='[$EPOCHREALTIME] '; PS1='${| | |
13 | + local e=$? | |
14 | 14 | |
15 | - (( e )) && print -n "$e|" | |
16 | -} | |
17 | -PS1='$(precmd)$USER@$HOSTNAME:${PWD:-?} '"$PS1 " | |
15 | + (( e )) && REPLY+="$e|" | |
16 | + | |
17 | + return $e | |
18 | +}$USER@$HOSTNAME:${PWD:-?} '"$PS1 " | |
18 | 19 | export HOME HOSTNAME MKSH SHELL TERM USER |
19 | 20 | alias l='ls' |
20 | 21 | alias la='l -a' |
@@ -22,7 +23,34 @@ alias ll='l -l' | ||
22 | 23 | alias lo='l -a -l' |
23 | 24 | |
24 | 25 | function hd { |
25 | - cat "$@" | command hd /proc/self/fd/0 | |
26 | + local -Uui16 -Z11 pos=0 | |
27 | + local -Uui16 -Z5 hv=2147483647 | |
28 | + local dasc line i | |
29 | + | |
30 | + cat "$@" | { set +U; if read -arN -1 line; then | |
31 | + typeset -i1 line | |
32 | + i=0 | |
33 | + while (( i < ${#line[*]} )); do | |
34 | + hv=${line[i++]} | |
35 | + if (( (pos & 15) == 0 )); then | |
36 | + (( pos )) && print -r -- "$dasc|" | |
37 | + print -n "${pos#16#} " | |
38 | + dasc=' |' | |
39 | + fi | |
40 | + print -n "${hv#16#} " | |
41 | + if (( (hv < 32) || (hv > 126) )); then | |
42 | + dasc+=. | |
43 | + else | |
44 | + dasc+=${line[i-1]#1#} | |
45 | + fi | |
46 | + (( (pos++ & 15) == 7 )) && print -n -- '- ' | |
47 | + done | |
48 | + while (( pos & 15 )); do | |
49 | + print -n ' ' | |
50 | + (( (pos++ & 15) == 7 )) && print -n -- '- ' | |
51 | + done | |
52 | + (( hv == 2147483647 )) || print -r -- "$dasc|" | |
53 | + fi; } | |
26 | 54 | } |
27 | 55 | |
28 | 56 | function more { |
@@ -1,5 +1,5 @@ | ||
1 | 1 | #!/bin/sh |
2 | -srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.622 2013/02/19 18:45:15 tg Exp $' | |
2 | +srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $' | |
3 | 3 | #- |
4 | 4 | # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
5 | 5 | # 2011, 2012, 2013 |
@@ -28,6 +28,9 @@ srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.622 2013/02/19 18:45:15 tg Exp $' | ||
28 | 28 | LC_ALL=C |
29 | 29 | export LC_ALL |
30 | 30 | |
31 | +echo "For the build logs, demonstrate that /dev/null and /dev/tty exist:" | |
32 | +ls -l /dev/null /dev/tty | |
33 | + | |
31 | 34 | case $ZSH_VERSION:$VERSION in |
32 | 35 | :zsh*) ZSH_VERSION=2 ;; |
33 | 36 | esac |
@@ -63,7 +66,7 @@ vq() { | ||
63 | 66 | rmf() { |
64 | 67 | for _f in "$@"; do |
65 | 68 | case $_f in |
66 | - Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|mksh.1) ;; | |
69 | + Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|*.ico|*.1) ;; | |
67 | 70 | *) rm -f "$_f" ;; |
68 | 71 | esac |
69 | 72 | done |
@@ -190,6 +193,7 @@ ac_testn() { | ||
190 | 193 | ac_ifcpp() { |
191 | 194 | expr=$1; shift |
192 | 195 | ac_testn "$@" <<-EOF |
196 | + extern int thiswillneverbedefinedIhope(void); | |
193 | 197 | int main(void) { return ( |
194 | 198 | #$expr |
195 | 199 | 0 |
@@ -458,7 +462,7 @@ oswarn= | ||
458 | 462 | ccpc=-Wc, |
459 | 463 | ccpl=-Wl, |
460 | 464 | tsts= |
461 | -ccpr='|| for _f in ${tcfn}*; do case $_f in Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|mksh.1) ;; *) rm -f "$_f" ;; esac; done' | |
465 | +ccpr='|| for _f in ${tcfn}*; do case $_f in Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|*.ico|*.1) ;; *) rm -f "$_f" ;; esac; done' | |
462 | 466 | |
463 | 467 | # Evil hack |
464 | 468 | if test x"$TARGET_OS" = x"Android"; then |
@@ -686,8 +690,11 @@ Plan9) | ||
686 | 690 | add_cppflags -D_SUSV2_SOURCE |
687 | 691 | add_cppflags -DMKSH_ASSUME_UTF8; HAVE_ISSET_MKSH_ASSUME_UTF8=1 |
688 | 692 | add_cppflags -DMKSH_NO_CMDLINE_EDITING |
693 | + add_cppflags -DMKSH__NO_SETEUGID | |
689 | 694 | oswarn=' and will currently not work' |
690 | 695 | add_cppflags -DMKSH_UNEMPLOYED |
696 | + # this is for detecting kencc | |
697 | + add_cppflags -DMKSH_MAYBE_KENCC | |
691 | 698 | ;; |
692 | 699 | PW32*) |
693 | 700 | HAVE_SIG_T=0 # incompatible |
@@ -766,7 +773,7 @@ esac | ||
766 | 773 | |
767 | 774 | : ${HAVE_MKNOD=0} |
768 | 775 | |
769 | -: ${AWK=awk} ${CC=cc} ${NROFF=nroff} | |
776 | +: ${AWK=awk} ${CC=cc} ${NROFF=nroff} ${SIZE=size} | |
770 | 777 | test 0 = $r && echo | $NROFF -v 2>&1 | grep GNU >/dev/null 2>&1 && \ |
771 | 778 | NROFF="$NROFF -c" |
772 | 779 |
@@ -876,6 +883,9 @@ ct="ucode" | ||
876 | 883 | ct="uslc" |
877 | 884 | #elif defined(__LCC__) |
878 | 885 | ct="lcc" |
886 | +#elif defined(MKSH_MAYBE_KENCC) | |
887 | +/* and none of the above matches */ | |
888 | +ct="kencc" | |
879 | 889 | #else |
880 | 890 | ct="unknown" |
881 | 891 | #endif |
@@ -952,6 +962,9 @@ iar) | ||
952 | 962 | icc) |
953 | 963 | vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN $LIBS -V" |
954 | 964 | ;; |
965 | +kencc) | |
966 | + vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -v conftest.c $LIBS" | |
967 | + ;; | |
955 | 968 | lcc) |
956 | 969 | vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -v conftest.c $LIBS" |
957 | 970 | add_cppflags -D__inline__=__inline |
@@ -1074,19 +1087,23 @@ if ac_ifcpp 'if 0' compiler_fails '' \ | ||
1074 | 1087 | 'if the compiler does not fail correctly'; then |
1075 | 1088 | save_CFLAGS=$CFLAGS |
1076 | 1089 | : ${HAVE_CAN_DELEXE=x} |
1077 | - if test $ct = dmc; then | |
1078 | - CFLAGS="$CFLAGS ${ccpl}/DELEXECUTABLE" | |
1079 | - ac_testn can_delexe compiler_fails 0 'for the /DELEXECUTABLE linker option' <<-EOF | |
1080 | - int main(void) { return (0); } | |
1081 | - EOF | |
1082 | - elif test $ct = dec; then | |
1090 | + case $ct in | |
1091 | + dec) | |
1083 | 1092 | CFLAGS="$CFLAGS ${ccpl}-non_shared" |
1084 | 1093 | ac_testn can_delexe compiler_fails 0 'for the -non_shared linker option' <<-EOF |
1085 | 1094 | int main(void) { return (0); } |
1086 | 1095 | EOF |
1087 | - else | |
1096 | + ;; | |
1097 | + dmc) | |
1098 | + CFLAGS="$CFLAGS ${ccpl}/DELEXECUTABLE" | |
1099 | + ac_testn can_delexe compiler_fails 0 'for the /DELEXECUTABLE linker option' <<-EOF | |
1100 | + int main(void) { return (0); } | |
1101 | + EOF | |
1102 | + ;; | |
1103 | + *) | |
1088 | 1104 | exit 1 |
1089 | - fi | |
1105 | + ;; | |
1106 | + esac | |
1090 | 1107 | test 1 = $HAVE_CAN_DELEXE || CFLAGS=$save_CFLAGS |
1091 | 1108 | ac_testn compiler_still_fails '' 'if the compiler still does not fail correctly' <<-EOF |
1092 | 1109 | EOF |
@@ -1099,49 +1116,65 @@ if ac_ifcpp 'ifdef __TINYC__' couldbe_tcc '!' compiler_known 0 \ | ||
1099 | 1116 | HAVE_COMPILER_KNOWN=1 |
1100 | 1117 | fi |
1101 | 1118 | |
1102 | -if test $ct = sunpro; then | |
1103 | - test x"$save_NOWARN" = x"" && save_NOWARN='-errwarn=%none' | |
1104 | - ac_flags 0 errwarnnone "$save_NOWARN" | |
1105 | - test 1 = $HAVE_CAN_ERRWARNNONE || save_NOWARN= | |
1106 | - ac_flags 0 errwarnall "-errwarn=%all" | |
1107 | - test 1 = $HAVE_CAN_ERRWARNALL && DOWARN="-errwarn=%all" | |
1108 | -elif test $ct = hpcc; then | |
1119 | +case $ct in | |
1120 | +bcc) | |
1121 | + save_NOWARN="${ccpc}-w" | |
1122 | + DOWARN="${ccpc}-w!" | |
1123 | + ;; | |
1124 | +dec) | |
1125 | + # -msg_* flags not used yet, or is -w2 correct? | |
1126 | + ;; | |
1127 | +dmc) | |
1128 | + save_NOWARN="${ccpc}-w" | |
1129 | + DOWARN="${ccpc}-wx" | |
1130 | + ;; | |
1131 | +hpcc) | |
1109 | 1132 | save_NOWARN= |
1110 | 1133 | DOWARN=+We |
1111 | -elif test $ct = mipspro; then | |
1134 | + ;; | |
1135 | +kencc) | |
1136 | + save_NOWARN= | |
1137 | + DOWARN= | |
1138 | + ;; | |
1139 | +mipspro) | |
1112 | 1140 | save_NOWARN= |
1113 | 1141 | DOWARN="-diag_error 1-10000" |
1114 | -elif test $ct = msc; then | |
1142 | + ;; | |
1143 | +msc) | |
1115 | 1144 | save_NOWARN="${ccpc}/w" |
1116 | 1145 | DOWARN="${ccpc}/WX" |
1117 | -elif test $ct = dmc; then | |
1118 | - save_NOWARN="${ccpc}-w" | |
1119 | - DOWARN="${ccpc}-wx" | |
1120 | -elif test $ct = bcc; then | |
1121 | - save_NOWARN="${ccpc}-w" | |
1122 | - DOWARN="${ccpc}-w!" | |
1123 | -elif test $ct = dec; then | |
1124 | - : -msg_* flags not used yet, or is -w2 correct? | |
1125 | -elif test $ct = xlc; then | |
1126 | - save_NOWARN=-qflag=i:e | |
1127 | - DOWARN=-qflag=i:i | |
1128 | -elif test $ct = tendra; then | |
1146 | + ;; | |
1147 | +sunpro) | |
1148 | + test x"$save_NOWARN" = x"" && save_NOWARN='-errwarn=%none' | |
1149 | + ac_flags 0 errwarnnone "$save_NOWARN" | |
1150 | + test 1 = $HAVE_CAN_ERRWARNNONE || save_NOWARN= | |
1151 | + ac_flags 0 errwarnall "-errwarn=%all" | |
1152 | + test 1 = $HAVE_CAN_ERRWARNALL && DOWARN="-errwarn=%all" | |
1153 | + ;; | |
1154 | +tendra) | |
1129 | 1155 | save_NOWARN=-w |
1130 | -elif test $ct = ucode; then | |
1156 | + ;; | |
1157 | +ucode) | |
1131 | 1158 | save_NOWARN= |
1132 | 1159 | DOWARN=-w2 |
1133 | -elif test $ct = watcom; then | |
1160 | + ;; | |
1161 | +watcom) | |
1134 | 1162 | save_NOWARN= |
1135 | 1163 | DOWARN=-Wc,-we |
1136 | -else | |
1164 | + ;; | |
1165 | +xlc) | |
1166 | + save_NOWARN=-qflag=i:e | |
1167 | + DOWARN=-qflag=i:i | |
1168 | + ;; | |
1169 | +*) | |
1137 | 1170 | test x"$save_NOWARN" = x"" && save_NOWARN=-Wno-error |
1138 | 1171 | ac_flags 0 wnoerror "$save_NOWARN" |
1139 | 1172 | test 1 = $HAVE_CAN_WNOERROR || save_NOWARN= |
1140 | 1173 | ac_flags 0 werror -Werror |
1141 | 1174 | test 1 = $HAVE_CAN_WERROR && DOWARN=-Werror |
1142 | -fi | |
1143 | - | |
1144 | -test $ct = icc && DOWARN="$DOWARN -wd1419" | |
1175 | + test $ct = icc && DOWARN="$DOWARN -wd1419" | |
1176 | + ;; | |
1177 | +esac | |
1145 | 1178 | NOWARN=$save_NOWARN |
1146 | 1179 | |
1147 | 1180 | # |
@@ -1149,7 +1182,16 @@ NOWARN=$save_NOWARN | ||
1149 | 1182 | # |
1150 | 1183 | i=`echo :"$orig_CFLAGS" | sed 's/^://' | tr -c -d $alll$allu$alln` |
1151 | 1184 | # optimisation: only if orig_CFLAGS is empty |
1152 | -test x"$i" = x"" && if test $ct = sunpro; then | |
1185 | +test x"$i" = x"" && case $ct in | |
1186 | +hpcc) | |
1187 | + phase=u | |
1188 | + ac_flags 1 otwo +O2 | |
1189 | + phase=x | |
1190 | + ;; | |
1191 | +kencc|tcc|tendra) | |
1192 | + # no special optimisation | |
1193 | + ;; | |
1194 | +sunpro) | |
1153 | 1195 | cat >x <<-'EOF' |
1154 | 1196 | int main(void) { return (0); } |
1155 | 1197 | #define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p |
@@ -1159,25 +1201,37 @@ test x"$i" = x"" && if test $ct = sunpro; then | ||
1159 | 1201 | yes pad | head -n 256 >>x |
1160 | 1202 | ac_flags - 1 otwo -xO2 <x |
1161 | 1203 | rmf x |
1162 | -elif test $ct = hpcc; then | |
1163 | - phase=u | |
1164 | - ac_flags 1 otwo +O2 | |
1165 | - phase=x | |
1166 | -elif test $ct = xlc; then | |
1204 | + ;; | |
1205 | +xlc) | |
1167 | 1206 | ac_flags 1 othree "-O3 -qstrict" |
1168 | 1207 | test 1 = $HAVE_CAN_OTHREE || ac_flags 1 otwo -O2 |
1169 | -elif test $ct = tcc || test $ct = tendra; then | |
1170 | - : no special optimisation | |
1171 | -else | |
1208 | + ;; | |
1209 | +*) | |
1172 | 1210 | ac_flags 1 otwo -O2 |
1173 | 1211 | test 1 = $HAVE_CAN_OTWO || ac_flags 1 optimise -O |
1174 | -fi | |
1212 | + ;; | |
1213 | +esac | |
1175 | 1214 | # other flags: just add them if they are supported |
1176 | 1215 | i=0 |
1177 | -if test $ct = gcc; then | |
1216 | +case $ct in | |
1217 | +bcc) | |
1218 | + ac_flags 1 strpool "${ccpc}-d" 'if string pooling can be enabled' | |
1219 | + ;; | |
1220 | +clang) | |
1221 | + i=1 | |
1222 | + ;; | |
1223 | +dec) | |
1224 | + ac_flags 0 verb -verbose | |
1225 | + ac_flags 1 rodata -readonly_strings | |
1226 | + ;; | |
1227 | +dmc) | |
1228 | + ac_flags 1 decl "${ccpc}-r" 'for strict prototype checks' | |
1229 | + ac_flags 1 schk "${ccpc}-s" 'for stack overflow checking' | |
1230 | + ;; | |
1231 | +gcc) | |
1178 | 1232 | # The following tests run with -Werror (gcc only) if possible |
1179 | 1233 | NOWARN=$DOWARN; phase=u |
1180 | - ac_flags 0 wnooverflow -Wno-overflow | |
1234 | + ac_flags 1 wnodeprecateddecls -Wno-deprecated-declarations | |
1181 | 1235 | # mksh is not written in CFrustFrust! |
1182 | 1236 | ac_flags 1 no_eh_frame -fno-asynchronous-unwind-tables |
1183 | 1237 | ac_flags 1 fnostrictaliasing -fno-strict-aliasing |
@@ -1186,15 +1240,19 @@ if test $ct = gcc; then | ||
1186 | 1240 | *\ -fplugin=*dragonegg*) ;; |
1187 | 1241 | *) ac_flags 1 fplugin_dragonegg -fplugin=dragonegg ;; |
1188 | 1242 | esac |
1189 | - if test $cm = lto; then | |
1190 | - fv=0 | |
1191 | - checks='1 2 3 4 5 6 7 8' | |
1192 | - elif test $cm = combine; then | |
1243 | + case $cm in | |
1244 | + combine) | |
1193 | 1245 | fv=0 |
1194 | 1246 | checks='7 8' |
1195 | - else | |
1247 | + ;; | |
1248 | + lto) | |
1249 | + fv=0 | |
1250 | + checks='1 2 3 4 5 6 7 8' | |
1251 | + ;; | |
1252 | + *) | |
1196 | 1253 | fv=1 |
1197 | - fi | |
1254 | + ;; | |
1255 | + esac | |
1198 | 1256 | test $fv = 1 || for what in $checks; do |
1199 | 1257 | test $fv = 1 && break |
1200 | 1258 | case $what in |
@@ -1223,32 +1281,23 @@ if test $ct = gcc; then | ||
1223 | 1281 | "if gcc supports $t_cflags $t_ldflags" "$t_ldflags" |
1224 | 1282 | done |
1225 | 1283 | i=1 |
1226 | -elif test $ct = icc; then | |
1227 | - ac_flags 1 fnobuiltinsetmode -fno-builtin-setmode | |
1228 | - ac_flags 1 fnostrictaliasing -fno-strict-aliasing | |
1229 | - ac_flags 1 fstacksecuritycheck -fstack-security-check | |
1230 | - i=1 | |
1231 | -elif test $ct = sunpro; then | |
1232 | - phase=u | |
1233 | - ac_flags 1 v -v | |
1234 | - ac_flags 1 ipo -xipo 'for cross-module optimisation' | |
1235 | - phase=x | |
1236 | -elif test $ct = hpcc; then | |
1284 | + ;; | |
1285 | +hpcc) | |
1237 | 1286 | phase=u |
1238 | 1287 | # probably not needed |
1239 | 1288 | #ac_flags 1 agcc -Agcc 'for support of GCC extensions' |
1240 | 1289 | phase=x |
1241 | -elif test $ct = dec; then | |
1242 | - ac_flags 0 verb -verbose | |
1243 | - ac_flags 1 rodata -readonly_strings | |
1244 | -elif test $ct = dmc; then | |
1245 | - ac_flags 1 decl "${ccpc}-r" 'for strict prototype checks' | |
1246 | - ac_flags 1 schk "${ccpc}-s" 'for stack overflow checking' | |
1247 | -elif test $ct = bcc; then | |
1248 | - ac_flags 1 strpool "${ccpc}-d" 'if string pooling can be enabled' | |
1249 | -elif test $ct = mipspro; then | |
1290 | + ;; | |
1291 | +icc) | |
1292 | + ac_flags 1 fnobuiltinsetmode -fno-builtin-setmode | |
1293 | + ac_flags 1 fnostrictaliasing -fno-strict-aliasing | |
1294 | + ac_flags 1 fstacksecuritycheck -fstack-security-check | |
1295 | + i=1 | |
1296 | + ;; | |
1297 | +mipspro) | |
1250 | 1298 | ac_flags 1 fullwarn -fullwarn 'for remark output support' |
1251 | -elif test $ct = msc; then | |
1299 | + ;; | |
1300 | +msc) | |
1252 | 1301 | ac_flags 1 strpool "${ccpc}/GF" 'if string pooling can be enabled' |
1253 | 1302 | echo 'int main(void) { char test[64] = ""; return (*test); }' >x |
1254 | 1303 | ac_flags - 1 stackon "${ccpc}/GZ" 'if stack checks can be enabled' <x |
@@ -1257,24 +1306,33 @@ elif test $ct = msc; then | ||
1257 | 1306 | rmf x |
1258 | 1307 | ac_flags 1 wall "${ccpc}/Wall" 'to enable all warnings' |
1259 | 1308 | ac_flags 1 wp64 "${ccpc}/Wp64" 'to enable 64-bit warnings' |
1260 | -elif test $ct = xlc; then | |
1309 | + ;; | |
1310 | +nwcc) | |
1311 | + i=1 | |
1312 | + #broken# ac_flags 1 ssp -stackprotect | |
1313 | + ;; | |
1314 | +sunpro) | |
1315 | + phase=u | |
1316 | + ac_flags 1 v -v | |
1317 | + ac_flags 1 ipo -xipo 'for cross-module optimisation' | |
1318 | + phase=x | |
1319 | + ;; | |
1320 | +tcc) | |
1321 | + : #broken# ac_flags 1 boundschk -b | |
1322 | + ;; | |
1323 | +tendra) | |
1324 | + ac_flags 0 ysystem -Ysystem | |
1325 | + test 1 = $HAVE_CAN_YSYSTEM && CPPFLAGS="-Ysystem $CPPFLAGS" | |
1326 | + ac_flags 1 extansi -Xa | |
1327 | + ;; | |
1328 | +xlc) | |
1261 | 1329 | ac_flags 1 rodata "-qro -qroconst -qroptr" |
1262 | 1330 | ac_flags 1 rtcheck -qcheck=all |
1263 | 1331 | #ac_flags 1 rtchkc -qextchk # reported broken |
1264 | 1332 | ac_flags 1 wformat "-qformat=all -qformat=nozln" |
1265 | 1333 | #ac_flags 1 wp64 -qwarn64 # too verbose for now |
1266 | -elif test $ct = tendra; then | |
1267 | - ac_flags 0 ysystem -Ysystem | |
1268 | - test 1 = $HAVE_CAN_YSYSTEM && CPPFLAGS="-Ysystem $CPPFLAGS" | |
1269 | - ac_flags 1 extansi -Xa | |
1270 | -elif test $ct = tcc; then | |
1271 | - : #broken# ac_flags 1 boundschk -b | |
1272 | -elif test $ct = clang; then | |
1273 | - i=1 | |
1274 | -elif test $ct = nwcc; then | |
1275 | - i=1 | |
1276 | - : #broken# ac_flags 1 ssp -stackprotect | |
1277 | -fi | |
1334 | + ;; | |
1335 | +esac | |
1278 | 1336 | # flags common to a subset of compilers (run with -Werror on gcc) |
1279 | 1337 | if test 1 = $i; then |
1280 | 1338 | ac_flags 1 wall -Wall |
@@ -1291,6 +1349,7 @@ test $ct = pcc && phase=u | ||
1291 | 1349 | # |
1292 | 1350 | ac_test attribute_bounded '' 'for __attribute__((__bounded__))' <<-'EOF' |
1293 | 1351 | #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2)) |
1352 | + extern int thiswillneverbedefinedIhope(void); | |
1294 | 1353 | /* force a failure: TenDRA and gcc 1.42 have false positive here */ |
1295 | 1354 | int main(void) { return (thiswillneverbedefinedIhope()); } |
1296 | 1355 | #else |
@@ -1311,6 +1370,7 @@ ac_test attribute_bounded '' 'for __attribute__((__bounded__))' <<-'EOF' | ||
1311 | 1370 | EOF |
1312 | 1371 | ac_test attribute_format '' 'for __attribute__((__format__))' <<-'EOF' |
1313 | 1372 | #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2)) |
1373 | + extern int thiswillneverbedefinedIhope(void); | |
1314 | 1374 | /* force a failure: TenDRA and gcc 1.42 have false positive here */ |
1315 | 1375 | int main(void) { return (thiswillneverbedefinedIhope()); } |
1316 | 1376 | #else |
@@ -1325,6 +1385,7 @@ ac_test attribute_format '' 'for __attribute__((__format__))' <<-'EOF' | ||
1325 | 1385 | EOF |
1326 | 1386 | ac_test attribute_noreturn '' 'for __attribute__((__noreturn__))' <<-'EOF' |
1327 | 1387 | #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2)) |
1388 | + extern int thiswillneverbedefinedIhope(void); | |
1328 | 1389 | /* force a failure: TenDRA and gcc 1.42 have false positive here */ |
1329 | 1390 | int main(void) { return (thiswillneverbedefinedIhope()); } |
1330 | 1391 | #else |
@@ -1337,6 +1398,7 @@ ac_test attribute_noreturn '' 'for __attribute__((__noreturn__))' <<-'EOF' | ||
1337 | 1398 | EOF |
1338 | 1399 | ac_test attribute_unused '' 'for __attribute__((__unused__))' <<-'EOF' |
1339 | 1400 | #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2)) |
1401 | + extern int thiswillneverbedefinedIhope(void); | |
1340 | 1402 | /* force a failure: TenDRA and gcc 1.42 have false positive here */ |
1341 | 1403 | int main(void) { return (thiswillneverbedefinedIhope()); } |
1342 | 1404 | #else |
@@ -1346,6 +1408,7 @@ ac_test attribute_unused '' 'for __attribute__((__unused__))' <<-'EOF' | ||
1346 | 1408 | EOF |
1347 | 1409 | ac_test attribute_used '' 'for __attribute__((__used__))' <<-'EOF' |
1348 | 1410 | #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2)) |
1411 | + extern int thiswillneverbedefinedIhope(void); | |
1349 | 1412 | /* force a failure: TenDRA and gcc 1.42 have false positive here */ |
1350 | 1413 | int main(void) { return (thiswillneverbedefinedIhope()); } |
1351 | 1414 | #else |
@@ -1368,8 +1431,8 @@ if ac_ifcpp 'ifdef MKSH_SMALL' isset_MKSH_SMALL '' \ | ||
1368 | 1431 | check_categories="$check_categories smksh" |
1369 | 1432 | HAVE_ISSET_MKSH_CONSERVATIVE_FDS=1 # from sh.h |
1370 | 1433 | fi |
1371 | -ac_ifcpp 'ifdef MKSH_BINSHREDUCED' isset_MKSH_BINSHREDUCED '' \ | |
1372 | - "if a reduced-feature sh is requested" && \ | |
1434 | +ac_ifcpp 'if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)' \ | |
1435 | + isset_MKSH_BINSH '' 'if invoking as sh should be handled specially' && \ | |
1373 | 1436 | check_categories="$check_categories binsh" |
1374 | 1437 | ac_ifcpp 'ifdef MKSH_UNEMPLOYED' isset_MKSH_UNEMPLOYED '' \ |
1375 | 1438 | "if mksh will be built without job control" && \ |
@@ -1491,14 +1554,16 @@ ac_testn sig_t <<-'EOF' | ||
1491 | 1554 | #include <sys/types.h> |
1492 | 1555 | #include <signal.h> |
1493 | 1556 | #include <stddef.h> |
1494 | - int main(void) { return ((int)(ptrdiff_t)(sig_t)(ptrdiff_t)kill(0,0)); } | |
1557 | + volatile sig_t foo = (sig_t)0; | |
1558 | + int main(void) { return (foo == (sig_t)0); } | |
1495 | 1559 | EOF |
1496 | 1560 | |
1497 | 1561 | ac_testn sighandler_t '!' sig_t 0 <<-'EOF' |
1498 | 1562 | #include <sys/types.h> |
1499 | 1563 | #include <signal.h> |
1500 | 1564 | #include <stddef.h> |
1501 | - int main(void) { return ((int)(ptrdiff_t)(sighandler_t)(ptrdiff_t)kill(0,0)); } | |
1565 | + volatile sighandler_t foo = (sighandler_t)0; | |
1566 | + int main(void) { return (foo == (sighandler_t)0); } | |
1502 | 1567 | EOF |
1503 | 1568 | if test 1 = $HAVE_SIGHANDLER_T; then |
1504 | 1569 | add_cppflags -Dsig_t=sighandler_t |
@@ -1509,7 +1574,8 @@ ac_testn __sighandler_t '!' sig_t 0 <<-'EOF' | ||
1509 | 1574 | #include <sys/types.h> |
1510 | 1575 | #include <signal.h> |
1511 | 1576 | #include <stddef.h> |
1512 | - int main(void) { return ((int)(ptrdiff_t)(__sighandler_t)(ptrdiff_t)kill(0,0)); } | |
1577 | + volatile __sighandler_t foo = (__sighandler_t)0; | |
1578 | + int main(void) { return (foo == (__sighandler_t)0); } | |
1513 | 1579 | EOF |
1514 | 1580 | if test 1 = $HAVE___SIGHANDLER_T; then |
1515 | 1581 | add_cppflags -Dsig_t=__sighandler_t |
@@ -1532,7 +1598,7 @@ else | ||
1532 | 1598 | #define EXTERN |
1533 | 1599 | #define MKSH_INCLUDES_ONLY |
1534 | 1600 | #include "sh.h" |
1535 | - __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.622 2013/02/19 18:45:15 tg Exp $"); | |
1601 | + __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $"); | |
1536 | 1602 | int main(void) { printf("Hello, World!\n"); return (0); } |
1537 | 1603 | EOF |
1538 | 1604 | case $cm in |
@@ -1748,7 +1814,7 @@ EOF | ||
1748 | 1814 | ac_test setresugid <<-'EOF' |
1749 | 1815 | #include <sys/types.h> |
1750 | 1816 | #include <unistd.h> |
1751 | - int main(void) { setresuid(0,0,0); return (setresgid(0,0,0)); } | |
1817 | + int main(void) { return (setresuid(0,0,0) + setresgid(0,0,0)); } | |
1752 | 1818 | EOF |
1753 | 1819 | |
1754 | 1820 | ac_test setgroups setresugid 0 <<-'EOF' |
@@ -1848,7 +1914,6 @@ ac_testdone | ||
1848 | 1914 | ac_cppflags |
1849 | 1915 | |
1850 | 1916 | save_CFLAGS=$CFLAGS |
1851 | -test x1 = x$HAVE_CAN_WNOOVERFLOW && CFLAGS="$CFLAGS -Wno-overflow" | |
1852 | 1917 | ac_testn compile_time_asserts_$$ '' 'whether compile-time assertions pass' <<-'EOF' |
1853 | 1918 | #define MKSH_INCLUDES_ONLY |
1854 | 1919 | #include "sh.h" |
@@ -1875,13 +1940,8 @@ cta(long_size_no_matter_of_signedness, sizeof(long) == sizeof(unsigned long)); | ||
1875 | 1940 | #ifndef MKSH_LEGACY_MODE |
1876 | 1941 | /* the next assertion is probably not really needed */ |
1877 | 1942 | cta(ari_is_4_char, sizeof(mksh_ari_t) == 4); |
1878 | -/* but the next two are; we REQUIRE signed integer wraparound */ | |
1943 | +/* but this is */ | |
1879 | 1944 | cta(ari_has_31_bit, 0 < (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1)); |
1880 | -#ifndef MKSH_GCC55009 | |
1881 | -cta(ari_sign_32_bit_and_wrap, | |
1882 | - (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1) > | |
1883 | - (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 2)); | |
1884 | -#endif | |
1885 | 1945 | /* the next assertion is probably not really needed */ |
1886 | 1946 | cta(uari_is_4_char, sizeof(mksh_uari_t) == 4); |
1887 | 1947 | /* but the next three are; we REQUIRE unsigned integer wraparound */ |
@@ -1890,10 +1950,15 @@ cta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 | ||
1890 | 1950 | cta(uari_wrap_32_bit, |
1891 | 1951 | (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) > |
1892 | 1952 | (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4)); |
1953 | +#define NUM 22 | |
1954 | +#else | |
1955 | +#define NUM 16 | |
1893 | 1956 | #endif |
1894 | 1957 | /* these are always required */ |
1895 | 1958 | cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0); |
1896 | 1959 | cta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0); |
1960 | +/* we require these to have the precisely same size and assume 2s complement */ | |
1961 | +cta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t)); | |
1897 | 1962 | |
1898 | 1963 | cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t)); |
1899 | 1964 | cta(ptrdifft_sizet_same_size, sizeof(ptrdiff_t) == sizeof(size_t)); |
@@ -1901,17 +1966,10 @@ cta(ptrdifft_voidptr_same_size, sizeof(ptrdiff_t) == sizeof(void *)); | ||
1901 | 1966 | cta(ptrdifft_funcptr_same_size, sizeof(ptrdiff_t) == sizeof(void (*)(void))); |
1902 | 1967 | /* our formatting routines assume this */ |
1903 | 1968 | cta(ptr_fits_in_long, sizeof(ptrdiff_t) <= sizeof(long)); |
1969 | +/* for struct alignment people */ | |
1970 | + char padding[64 - NUM]; | |
1904 | 1971 | }; |
1905 | -#ifndef MKSH_LEGACY_MODE | |
1906 | -#ifndef MKSH_GCC55009 | |
1907 | -#define NUM 22 | |
1908 | -#else | |
1909 | -#define NUM 21 | |
1910 | -#endif | |
1911 | -#else | |
1912 | -#define NUM 15 | |
1913 | -#endif | |
1914 | -char ctasserts_dblcheck[sizeof(struct ctasserts) == NUM ? 1 : -1]; | |
1972 | +char ctasserts_dblcheck[sizeof(struct ctasserts) == 64 ? 1 : -1]; | |
1915 | 1973 | int main(void) { return (sizeof(ctasserts_dblcheck)); } |
1916 | 1974 | EOF |
1917 | 1975 | CFLAGS=$save_CFLAGS |
@@ -1957,71 +2015,6 @@ EOF | ||
1957 | 2015 | fi |
1958 | 2016 | |
1959 | 2017 | # |
1960 | -# runtime checks | |
1961 | -# once this is more than one, check if we can do runtime | |
1962 | -# checks (not cross-compiling) first to save on warnings | |
1963 | -# | |
1964 | -$e "${bi}run-time checks follow$ao, please ignore any weird errors" | |
1965 | - | |
1966 | -if ac_testnnd silent_idivwrapv '' '(run-time) whether signed integer division overflows wrap silently' <<-'EOF' | |
1967 | - #define MKSH_INCLUDES_ONLY | |
1968 | - #include "sh.h" | |
1969 | - #if !defined(MKSH_LEGACY_MODE) || HAVE_LONG_32BIT | |
1970 | - #define IDIVWRAPV_VL (mksh_uari_t)0x80000000UL | |
1971 | - #elif HAVE_LONG_64BIT | |
1972 | - #define IDIVWRAPV_VL (mksh_uari_t)0x8000000000000000UL | |
1973 | - #else | |
1974 | - # error "cannot check this" | |
1975 | - #endif | |
1976 | - #ifdef SIGFPE | |
1977 | - static void fpe_catcher(int) MKSH_A_NORETURN; | |
1978 | - #endif | |
1979 | - int main(int ac, char **av) { | |
1980 | - mksh_ari_t o1, o2, r1, r2; | |
1981 | - | |
1982 | - #ifdef SIGFPE | |
1983 | - signal(SIGFPE, fpe_catcher); | |
1984 | - #endif | |
1985 | - o1 = (mksh_ari_t)IDIVWRAPV_VL; | |
1986 | - o2 = -ac; | |
1987 | - r1 = o1 / o2; | |
1988 | - r2 = o1 % o2; | |
1989 | - if (r1 == o1 && r2 == 0) { | |
1990 | - printf("si"); | |
1991 | - return (0); | |
1992 | - } | |
1993 | - printf("no %d %d %d %d %s", (int)o1, (int)o2, (int)r1, | |
1994 | - (int)r2, av[0]); | |
1995 | - return (1); | |
1996 | - } | |
1997 | - #ifdef SIGFPE | |
1998 | - static const char fpe_msg[] = "no, got SIGFPE, what were they smoking?"; | |
1999 | - #define fpe_msglen (sizeof(fpe_msg) - 1) | |
2000 | - static void fpe_catcher(int sig MKSH_A_UNUSED) { | |
2001 | - _exit(write(1, fpe_msg, fpe_msglen) == fpe_msglen ? 2 : 3); | |
2002 | - } | |
2003 | - #endif | |
2004 | -EOF | |
2005 | -then | |
2006 | - if test $fv = 0; then | |
2007 | - echo "| hrm, compiling this failed, but we will just failback" | |
2008 | - else | |
2009 | - echo "| running test programme; this will fail if cross-compiling" | |
2010 | - echo "| in which case we will gracefully degrade to the default" | |
2011 | - ./$tcfn >vv.out 2>&1 | |
2012 | - rv=$? | |
2013 | - echo "| result: `cat vv.out`" | |
2014 | - fv=0 | |
2015 | - test $rv = 0 && test x"`cat vv.out`" = x"si" && fv=1 | |
2016 | - fi | |
2017 | - rmf conftest.c conftest.o ${tcfn}* vv.out | |
2018 | - ac_testdone | |
2019 | -fi | |
2020 | -ac_cppflags | |
2021 | - | |
2022 | -$e "${bi}end of run-time checks$ao" | |
2023 | - | |
2024 | -# | |
2025 | 2018 | # Compiler: Praeprocessor (only if needed) |
2026 | 2019 | # |
2027 | 2020 | test 0 = $HAVE_SYS_SIGNAME && if ac_testinit cpp_dd '' \ |
@@ -2120,7 +2113,7 @@ addsrcs USE_PRINTF_BUILTIN printf.c | ||
2120 | 2113 | test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN |
2121 | 2114 | test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose" |
2122 | 2115 | test -n "$LDSTATIC" && add_cppflags -DMKSH_OPTSTATIC |
2123 | -add_cppflags -DMKSH_BUILD_R=431 | |
2116 | +add_cppflags -DMKSH_BUILD_R=481 | |
2124 | 2117 | |
2125 | 2118 | $e $bi$me: Finished configuration testing, now producing output.$ao |
2126 | 2119 |
@@ -2219,13 +2212,17 @@ cat >test.sh <<-EOF | ||
2219 | 2212 | exit \$rv |
2220 | 2213 | EOF |
2221 | 2214 | chmod 755 test.sh |
2222 | -if test $cm = llvm; then | |
2223 | - emitbc="-emit-llvm -c" | |
2224 | -elif test $cm = dragonegg; then | |
2215 | +case $cm in | |
2216 | +dragonegg) | |
2225 | 2217 | emitbc="-S -flto" |
2226 | -else | |
2218 | + ;; | |
2219 | +llvm) | |
2220 | + emitbc="-emit-llvm -c" | |
2221 | + ;; | |
2222 | +*) | |
2227 | 2223 | emitbc=-c |
2228 | -fi | |
2224 | + ;; | |
2225 | +esac | |
2229 | 2226 | echo ": # work around NeXTstep bug" >Rebuild.sh |
2230 | 2227 | echo set -x >>Rebuild.sh |
2231 | 2228 | for file in $SRCS; do |
@@ -2254,7 +2251,7 @@ dragonegg|llvm) | ||
2254 | 2251 | esac |
2255 | 2252 | echo tcfn=$mkshexe >>Rebuild.sh |
2256 | 2253 | echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh |
2257 | -echo 'test -f $tcfn || exit 1; size $tcfn' >>Rebuild.sh | |
2254 | +echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh | |
2258 | 2255 | if test $cm = makefile; then |
2259 | 2256 | extras='emacsfn.h sh.h sh_flags.h var_spec.h' |
2260 | 2257 | test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc" |
@@ -2335,15 +2332,17 @@ test $cm = combine || v "$CC $CFLAGS $LDFLAGS -o $tcfn $lobjs $LIBS $ccpr" | ||
2335 | 2332 | test -f $tcfn || exit 1 |
2336 | 2333 | test 1 = $r || v "$NROFF -mdoc <'$srcdir/mksh.1' >$tfn.cat1" || \ |
2337 | 2334 | rmf $tfn.cat1 |
2338 | -test 0 = $eq && v size $tcfn | |
2335 | +test 0 = $eq && v $SIZE $tcfn | |
2339 | 2336 | i=install |
2340 | 2337 | test -f /usr/ucb/$i && i=/usr/ucb/$i |
2341 | 2338 | test 1 = $eq && e=: |
2342 | 2339 | $e |
2343 | 2340 | $e Installing the shell: |
2344 | 2341 | $e "# $i -c -s -o root -g bin -m 555 $tfn /bin/$tfn" |
2345 | -$e "# grep -x /bin/$tfn /etc/shells >/dev/null || echo /bin/$tfn >>/etc/shells" | |
2346 | -$e "# $i -c -o root -g bin -m 444 dot.mkshrc /usr/share/doc/mksh/examples/" | |
2342 | +if test $legacy = 0; then | |
2343 | + $e "# grep -x /bin/$tfn /etc/shells >/dev/null || echo /bin/$tfn >>/etc/shells" | |
2344 | + $e "# $i -c -o root -g bin -m 444 dot.mkshrc /usr/share/doc/mksh/examples/" | |
2345 | +fi | |
2347 | 2346 | $e |
2348 | 2347 | $e Installing the manual: |
2349 | 2348 | if test -f $tfn.cat1; then |
@@ -2351,7 +2350,7 @@ if test -f $tfn.cat1; then | ||
2351 | 2350 | "/usr/share/man/cat1/$tfn.0" |
2352 | 2351 | $e or |
2353 | 2352 | fi |
2354 | -$e "# $i -c -o root -g bin -m 444 mksh.1 /usr/share/man/man1/$tfn.1" | |
2353 | +$e "# $i -c -o root -g bin -m 444 $tfn.1 /usr/share/man/man1/$tfn.1" | |
2355 | 2354 | $e |
2356 | 2355 | $e Run the regression test suite: ./test.sh |
2357 | 2356 | $e Please also read the sample file dot.mkshrc and the fine manual. |
@@ -2389,6 +2388,7 @@ DEBUG_LEAKS enable freeing resources before exiting | ||
2389 | 2388 | MKSHRC_PATH "~/.mkshrc" (do not change) |
2390 | 2389 | MKSH_A4PB force use of arc4random_pushb |
2391 | 2390 | MKSH_ASSUME_UTF8 (0=disabled, 1=enabled; default: unset) |
2391 | +MKSH_BINSHPOSIX if */sh or */-sh, enable set -o posix | |
2392 | 2392 | MKSH_BINSHREDUCED if */sh or */-sh, enable set -o sh |
2393 | 2393 | MKSH_CLRTOEOL_STRING "\033[K" |
2394 | 2394 | MKSH_CLS_STRING "\033[;H\033[J" |
@@ -2400,7 +2400,6 @@ MKSH_DISABLE_DEPRECATED disable code paths scheduled for later removal | ||
2400 | 2400 | MKSH_DISABLE_EXPERIMENTAL disable code not yet comfy for (LTS) snapshots |
2401 | 2401 | MKSH_DISABLE_TTY_WARNING shut up warning about ctty if OS cant be fixed |
2402 | 2402 | MKSH_DONT_EMIT_IDSTRING omit RCS IDs from binary |
2403 | -MKSH_GCC55009 DANGER! see http://www.mirbsd.org/mksh.htm#p41 | |
2404 | 2403 | MKSH_MIDNIGHTBSD01ASH_COMPAT set -o sh: additional compatibility quirk |
2405 | 2404 | MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use) |
2406 | 2405 | MKSH_NOPWNAM skip PAM calls, for -static on eglibc, Solaris |
@@ -1,7 +1,8 @@ | ||
1 | -# $MirOS: src/bin/mksh/check.pl,v 1.31 2012/04/06 12:22:14 tg Exp $ | |
2 | -# $OpenBSD: th,v 1.13 2006/05/18 21:27:23 miod Exp $ | |
1 | +# $MirOS: src/bin/mksh/check.pl,v 1.32 2013/07/21 18:35:56 tg Exp $ | |
2 | +# $OpenBSD: th,v 1.16 2013/06/14 20:52:08 millert Exp $ | |
3 | 3 | #- |
4 | -# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 | |
4 | +# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, | |
5 | +# 2012, 2013 | |
5 | 6 | # Thorsten Glaser <tg@mirbsd.org> |
6 | 7 | # |
7 | 8 | # Provided that these terms and disclaimer and all copyright notices |
@@ -171,13 +172,15 @@ BEGIN { | ||
171 | 172 | |
172 | 173 | use Getopt::Std; |
173 | 174 | use Config; |
175 | +use File::Temp qw/ :mktemp /; | |
174 | 176 | |
175 | 177 | $os = defined $^O ? $^O : 'unknown'; |
176 | 178 | |
177 | 179 | ($prog = $0) =~ s#.*/##; |
178 | 180 | |
179 | 181 | $Usage = <<EOF ; |
180 | -Usage: $prog [-Pv] [-C cat] [-e e=v] [-p prog] [-s fn] [-t tmo] name ... | |
182 | +Usage: $prog [-Pv] [-C cat] [-e e=v] [-p prog] [-s fn] [-T dir] \ | |
183 | + [-t tmo] name ... | |
181 | 184 | -C c Specify the comma separated list of categories the program |
182 | 185 | belongs to (see category field). |
183 | 186 | -e e=v Set the environment variable e to v for all tests |
@@ -188,6 +191,7 @@ Usage: $prog [-Pv] [-C cat] [-e e=v] [-p prog] [-s fn] [-t tmo] name ... | ||
188 | 191 | -p p Use p as the program to test |
189 | 192 | -s s Read tests from file s; if s is a directory, it is recursively |
190 | 193 | scaned for test files (which end in .t). |
194 | + -T dir Use dir instead of /tmp to hold temporary files | |
191 | 195 | -t t Use t as default time limit for tests (default is unlimited) |
192 | 196 | -v Verbose mode: print reason test failed. |
193 | 197 | name specifies the name of the test(s) to run; if none are |
@@ -229,12 +233,6 @@ EOF | ||
229 | 233 | "os:$os", '1' |
230 | 234 | ); |
231 | 235 | |
232 | -$temps = "/tmp/rts$$"; | |
233 | -$tempi = "/tmp/rti$$"; | |
234 | -$tempo = "/tmp/rto$$"; | |
235 | -$tempe = "/tmp/rte$$"; | |
236 | -$tempdir = "/tmp/rtd$$"; | |
237 | - | |
238 | 236 | $nfailed = 0; |
239 | 237 | $nifailed = 0; |
240 | 238 | $nxfailed = 0; |
@@ -243,7 +241,7 @@ $nxpassed = 0; | ||
243 | 241 | |
244 | 242 | %known_tests = (); |
245 | 243 | |
246 | -if (!getopts('C:e:Pp:s:t:v')) { | |
244 | +if (!getopts('C:e:Pp:s:T:t:v')) { | |
247 | 245 | print STDERR $Usage; |
248 | 246 | exit 1; |
249 | 247 | } |
@@ -253,6 +251,7 @@ die "$prog: no test set specified (use -s)\n" if !defined $opt_s; | ||
253 | 251 | $test_prog = $opt_p; |
254 | 252 | $verbose = defined $opt_v && $opt_v; |
255 | 253 | $test_set = $opt_s; |
254 | +$temp_dir = $opt_T || "/tmp"; | |
256 | 255 | if (defined $opt_t) { |
257 | 256 | die "$prog: bad -t argument (should be number > 0): $opt_t\n" |
258 | 257 | if $opt_t !~ /^\d+$/ || $opt_t <= 0; |
@@ -297,8 +296,6 @@ if (defined $opt_e) { | ||
297 | 296 | } |
298 | 297 | %old_env = %ENV; |
299 | 298 | |
300 | -die "$prog: couldn't make directory $tempdir - $!\n" if !mkdir($tempdir, 0777); | |
301 | - | |
302 | 299 | chop($pwd = `pwd 2>/dev/null`); |
303 | 300 | die "$prog: couldn't get current working directory\n" if $pwd eq ''; |
304 | 301 | die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd); |
@@ -316,6 +313,17 @@ $SIG{'ALRM'} = 'catch_sigalrm'; | ||
316 | 313 | |
317 | 314 | $| = 1; |
318 | 315 | |
316 | +# Create temp files | |
317 | +($fh, $temps) = mkstemp("${temp_dir}/rts.XXXXXXXX"); | |
318 | +close($fh); | |
319 | +($fh, $tempi) = mkstemp("${temp_dir}/rti.XXXXXXXX"); | |
320 | +close($fh); | |
321 | +($fh, $tempo) = mkstemp("${temp_dir}/rto.XXXXXXXX"); | |
322 | +close($fh); | |
323 | +($fh, $tempe) = mkstemp("${temp_dir}/rte.XXXXXXXX"); | |
324 | +close($fh); | |
325 | +$tempdir = mkdtemp("${temp_dir}/rtd.XXXXXXXX"); | |
326 | + | |
319 | 327 | if (-d $test_set) { |
320 | 328 | $file_prefix_skip = length($test_set) + 1; |
321 | 329 | $ret = &process_test_dir($test_set); |
@@ -433,6 +441,8 @@ run_test | ||
433 | 441 | local(*test) = @_; |
434 | 442 | local($name) = $test{':full-name'}; |
435 | 443 | |
444 | + return undef if !&scrub_dir($tempdir); | |
445 | + | |
436 | 446 | if (defined $test{'stdin'}) { |
437 | 447 | return undef if !&write_file($tempi, $test{'stdin'}); |
438 | 448 | $ifile = $tempi; |
@@ -444,8 +454,6 @@ run_test | ||
444 | 454 | return undef if !&write_file($temps, $test{'script'}); |
445 | 455 | } |
446 | 456 | |
447 | - return undef if !&scrub_dir($tempdir); | |
448 | - | |
449 | 457 | if (!chdir($tempdir)) { |
450 | 458 | print STDERR "$prog: couldn't cd to $tempdir - $!\n"; |
451 | 459 | return undef; |
@@ -1,7 +1,9 @@ | ||
1 | -# $MirOS: src/bin/mksh/check.t,v 1.597 2013/02/19 18:45:17 tg Exp $ | |
1 | +# $MirOS: src/bin/mksh/check.t,v 1.629 2013/08/14 20:26:15 tg Exp $ | |
2 | 2 | # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ |
3 | 3 | # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ |
4 | 4 | # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ |
5 | +# $OpenBSD: regress.t,v 1.15 2013/07/01 17:25:27 jca Exp $ | |
6 | +# $OpenBSD: obsd-regress.t,v 1.5 2013/07/01 17:25:27 jca Exp $ | |
5 | 7 | #- |
6 | 8 | # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
7 | 9 | # 2011, 2012, 2013 |
@@ -29,7 +31,7 @@ | ||
29 | 31 | # http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD |
30 | 32 | |
31 | 33 | expected-stdout: |
32 | - @(#)MIRBSD KSH R43 2013/02/19 | |
34 | + @(#)MIRBSD KSH R48 2013/08/14 | |
33 | 35 | description: |
34 | 36 | Check version of shell. |
35 | 37 | stdin: |
@@ -38,7 +40,7 @@ name: KSH_VERSION | ||
38 | 40 | category: shell:legacy-no |
39 | 41 | --- |
40 | 42 | expected-stdout: |
41 | - @(#)LEGACY KSH R43 2013/02/19 | |
43 | + @(#)LEGACY KSH R48 2013/08/14 | |
42 | 44 | description: |
43 | 45 | Check version of legacy shell. |
44 | 46 | stdin: |
@@ -290,6 +292,22 @@ stdin: | ||
290 | 292 | expected-stdout: |
291 | 293 | = 4 2 = |
292 | 294 | --- |
295 | +name: arith-lazy-4 | |
296 | +description: | |
297 | + Check that preun/postun not done on non-evaluated side of ternary | |
298 | + operator | |
299 | +stdin: | |
300 | + (( m = n = 0, 1 ? n++ : m++ ? 2 : 3 )) | |
301 | + echo "($n, $m)" | |
302 | + m=0; echo $(( 0 ? ++m : 2 )); echo $m | |
303 | + m=0; echo $(( 0 ? m++ : 2 )); echo $m | |
304 | +expected-stdout: | |
305 | + (1, 0) | |
306 | + 2 | |
307 | + 0 | |
308 | + 2 | |
309 | + 0 | |
310 | +--- | |
293 | 311 | name: arith-ternary-prec-1 |
294 | 312 | description: |
295 | 313 | Check precedence of ternary operator vs assignment |
@@ -363,30 +381,35 @@ expected-stdout: | ||
363 | 381 | --- |
364 | 382 | name: arith-mandatory |
365 | 383 | description: |
366 | - If MKSH_GCC55009 is set when compiling, passing of | |
367 | - this test is *mandatory* for a valid mksh executable! | |
384 | + Passing of this test is *mandatory* for a valid mksh executable! | |
368 | 385 | category: shell:legacy-no |
369 | 386 | stdin: |
370 | 387 | typeset -i sari=0 |
371 | 388 | typeset -Ui uari=0 |
372 | 389 | typeset -i x=0 |
373 | - print -r -- $((x++)):$sari=$uari. | |
390 | + print -r -- $((x++)):$sari=$uari. #0 | |
374 | 391 | let --sari --uari |
375 | - print -r -- $((x++)):$sari=$uari. | |
392 | + print -r -- $((x++)):$sari=$uari. #1 | |
376 | 393 | sari=2147483647 uari=2147483647 |
377 | - print -r -- $((x++)):$sari=$uari. | |
394 | + print -r -- $((x++)):$sari=$uari. #2 | |
378 | 395 | let ++sari ++uari |
379 | - print -r -- $((x++)):$sari=$uari. | |
396 | + print -r -- $((x++)):$sari=$uari. #3 | |
380 | 397 | let --sari --uari |
381 | 398 | let 'sari *= 2' 'uari *= 2' |
382 | 399 | let ++sari ++uari |
383 | - print -r -- $((x++)):$sari=$uari. | |
400 | + print -r -- $((x++)):$sari=$uari. #4 | |
384 | 401 | let ++sari ++uari |
385 | - print -r -- $((x++)):$sari=$uari. | |
402 | + print -r -- $((x++)):$sari=$uari. #5 | |
386 | 403 | sari=-2147483648 uari=-2147483648 |
387 | - print -r -- $((x++)):$sari=$uari. | |
404 | + print -r -- $((x++)):$sari=$uari. #6 | |
388 | 405 | let --sari --uari |
389 | - print -r -- $((x++)):$sari=$uari. | |
406 | + print -r -- $((x++)):$sari=$uari. #7 | |
407 | + (( sari = -5 >> 1 )) | |
408 | + ((# uari = -5 >> 1 )) | |
409 | + print -r -- $((x++)):$sari=$uari. #8 | |
410 | + (( sari = -2 )) | |
411 | + ((# uari = sari )) | |
412 | + print -r -- $((x++)):$sari=$uari. #9 | |
390 | 413 | expected-stdout: |
391 | 414 | 0:0=0. |
392 | 415 | 1:-1=4294967295. |
@@ -396,6 +419,8 @@ expected-stdout: | ||
396 | 419 | 5:0=0. |
397 | 420 | 6:-2147483648=2147483648. |
398 | 421 | 7:2147483647=2147483647. |
422 | + 8:-3=2147483645. | |
423 | + 9:-2=4294967294. | |
399 | 424 | --- |
400 | 425 | name: arith-unsigned-1 |
401 | 426 | description: |
@@ -2530,30 +2555,6 @@ expected-stdout: | ||
2530 | 2555 | \END |
2531 | 2556 | end |
2532 | 2557 | --- |
2533 | -name: heredoc-quoting-unsubst | |
2534 | -description: | |
2535 | - Check for correct handling of quoted characters in | |
2536 | - here documents without substitution (marker is quoted). | |
2537 | -stdin: | |
2538 | - foo=bar | |
2539 | - cat <<-'EOF' | |
2540 | - x " \" \ \\ $ \$ `echo baz` \`echo baz\` $foo \$foo x | |
2541 | - EOF | |
2542 | -expected-stdout: | |
2543 | - x " \" \ \\ $ \$ `echo baz` \`echo baz\` $foo \$foo x | |
2544 | ---- | |
2545 | -name: heredoc-quoting-subst | |
2546 | -description: | |
2547 | - Check for correct handling of quoted characters in | |
2548 | - here documents with substitution (marker is not quoted). | |
2549 | -stdin: | |
2550 | - foo=bar | |
2551 | - cat <<-EOF | |
2552 | - x " \" \ \\ $ \$ `echo baz` \`echo baz\` $foo \$foo x | |
2553 | - EOF | |
2554 | -expected-stdout: | |
2555 | - x " \" \ \ $ $ baz `echo baz` bar $foo x | |
2556 | ---- | |
2557 | 2558 | name: heredoc-tmpfile-1 |
2558 | 2559 | description: |
2559 | 2560 | Check that heredoc temp files aren't removed too soon or too late. |
@@ -2736,6 +2737,131 @@ expected-stdout: | ||
2736 | 2737 | hi |
2737 | 2738 | Left overs: * |
2738 | 2739 | --- |
2740 | +name: heredoc-quoting-unsubst | |
2741 | +description: | |
2742 | + Check for correct handling of quoted characters in | |
2743 | + here documents without substitution (marker is quoted). | |
2744 | +stdin: | |
2745 | + foo=bar | |
2746 | + cat <<-'EOF' | |
2747 | + x " \" \ \\ $ \$ `echo baz` \`echo baz\` $foo \$foo x | |
2748 | + EOF | |
2749 | +expected-stdout: | |
2750 | + x " \" \ \\ $ \$ `echo baz` \`echo baz\` $foo \$foo x | |
2751 | +--- | |
2752 | +name: heredoc-quoting-subst | |
2753 | +description: | |
2754 | + Check for correct handling of quoted characters in | |
2755 | + here documents with substitution (marker is not quoted). | |
2756 | +stdin: | |
2757 | + foo=bar | |
2758 | + cat <<-EOF | |
2759 | + x " \" \ \\ $ \$ `echo baz` \`echo baz\` $foo \$foo x | |
2760 | + EOF | |
2761 | +expected-stdout: | |
2762 | + x " \" \ \ $ $ baz `echo baz` bar $foo x | |
2763 | +--- | |
2764 | +name: single-quotes-in-braces | |
2765 | +description: | |
2766 | + Check that single quotes inside unquoted {} are treated as quotes | |
2767 | +stdin: | |
2768 | + foo=1 | |
2769 | + echo ${foo:+'blah $foo'} | |
2770 | +expected-stdout: | |
2771 | + blah $foo | |
2772 | +--- | |
2773 | +name: single-quotes-in-quoted-braces | |
2774 | +description: | |
2775 | + Check that single quotes inside quoted {} are treated as | |
2776 | + normal char | |
2777 | +stdin: | |
2778 | + foo=1 | |
2779 | + echo "${foo:+'blah $foo'}" | |
2780 | +expected-stdout: | |
2781 | + 'blah 1' | |
2782 | +--- | |
2783 | +name: single-quotes-in-braces-nested | |
2784 | +description: | |
2785 | + Check that single quotes inside unquoted {} are treated as quotes, | |
2786 | + even if that's inside a double-quoted command expansion | |
2787 | +stdin: | |
2788 | + foo=1 | |
2789 | + echo "$( echo ${foo:+'blah $foo'})" | |
2790 | +expected-stdout: | |
2791 | + blah $foo | |
2792 | +--- | |
2793 | +name: single-quotes-in-brace-pattern | |
2794 | +description: | |
2795 | + Check that single quotes inside {} pattern are treated as quotes | |
2796 | +stdin: | |
2797 | + foo=1234 | |
2798 | + echo ${foo%'2'*} "${foo%'2'*}" ${foo%2'*'} "${foo%2'*'}" | |
2799 | +expected-stdout: | |
2800 | + 1 1 1234 1234 | |
2801 | +--- | |
2802 | +name: single-quotes-in-heredoc-braces | |
2803 | +description: | |
2804 | + Check that single quotes inside {} in heredoc are treated | |
2805 | + as normal char | |
2806 | +stdin: | |
2807 | + foo=1 | |
2808 | + cat <<EOM | |
2809 | + ${foo:+'blah $foo'} | |
2810 | + EOM | |
2811 | +expected-stdout: | |
2812 | + 'blah 1' | |
2813 | +--- | |
2814 | +name: single-quotes-in-nested-braces | |
2815 | +description: | |
2816 | + Check that single quotes inside nested unquoted {} are | |
2817 | + treated as quotes | |
2818 | +stdin: | |
2819 | + foo=1 | |
2820 | + echo ${foo:+${foo:+'blah $foo'}} | |
2821 | +expected-stdout: | |
2822 | + blah $foo | |
2823 | +--- | |
2824 | +name: single-quotes-in-nested-quoted-braces | |
2825 | +description: | |
2826 | + Check that single quotes inside nested quoted {} are treated | |
2827 | + as normal char | |
2828 | +stdin: | |
2829 | + foo=1 | |
2830 | + echo "${foo:+${foo:+'blah $foo'}}" | |
2831 | +expected-stdout: | |
2832 | + 'blah 1' | |
2833 | +--- | |
2834 | +name: single-quotes-in-nested-braces-nested | |
2835 | +description: | |
2836 | + Check that single quotes inside nested unquoted {} are treated | |
2837 | + as quotes, even if that's inside a double-quoted command expansion | |
2838 | +stdin: | |
2839 | + foo=1 | |
2840 | + echo "$( echo ${foo:+${foo:+'blah $foo'}})" | |
2841 | +expected-stdout: | |
2842 | + blah $foo | |
2843 | +--- | |
2844 | +name: single-quotes-in-nested-brace-pattern | |
2845 | +description: | |
2846 | + Check that single quotes inside nested {} pattern are treated as quotes | |
2847 | +stdin: | |
2848 | + foo=1234 | |
2849 | + echo ${foo:+${foo%'2'*}} "${foo:+${foo%'2'*}}" ${foo:+${foo%2'*'}} "${foo:+${foo%2'*'}}" | |
2850 | +expected-stdout: | |
2851 | + 1 1 1234 1234 | |
2852 | +--- | |
2853 | +name: single-quotes-in-heredoc-nested-braces | |
2854 | +description: | |
2855 | + Check that single quotes inside nested {} in heredoc are treated | |
2856 | + as normal char | |
2857 | +stdin: | |
2858 | + foo=1 | |
2859 | + cat <<EOM | |
2860 | + ${foo:+${foo:+'blah $foo'}} | |
2861 | + EOM | |
2862 | +expected-stdout: | |
2863 | + 'blah 1' | |
2864 | +--- | |
2739 | 2865 | name: history-basic |
2740 | 2866 | description: |
2741 | 2867 | See if we can test history at all |
@@ -3466,10 +3592,10 @@ stdin: | ||
3466 | 3592 | showargs 3 $@ |
3467 | 3593 | showargs 4 "$@" |
3468 | 3594 | expected-stdout: |
3469 | - <1> <A B C> | |
3595 | + <1> <A> <B> <C> | |
3470 | 3596 | <2> <ABC> |
3471 | - <3> <A B C> | |
3472 | - <4> <A B C> | |
3597 | + <3> <A> <B> <C> | |
3598 | + <4> <A> <B> <C> | |
3473 | 3599 | --- |
3474 | 3600 | name: IFS-space-colon-1 |
3475 | 3601 | description: |
@@ -3772,22 +3898,17 @@ expected-stdout: | ||
3772 | 3898 | --- |
3773 | 3899 | name: integer-base-check-flat |
3774 | 3900 | description: |
3775 | - Check behaviour does not match POSuX, because a not type-safe | |
3776 | - scripting language has *no* business interpreting "010" as octal | |
3777 | -category: shell:legacy-no | |
3901 | + Check behaviour does not match POSuX (except if set -o posix), | |
3902 | + because a not type-safe scripting language has *no* business | |
3903 | + interpreting the string "010" as octal numer eight (dangerous). | |
3778 | 3904 | stdin: |
3779 | - echo :$((10)).$((010)).$((0x10)). | |
3905 | + echo 1 "$("$__progname" -c 'echo :$((10))/$((010)),$((0x10)):')" . | |
3906 | + echo 2 "$("$__progname" -o posix -c 'echo :$((10))/$((010)),$((0x10)):')" . | |
3907 | + echo 3 "$("$__progname" -o sh -c 'echo :$((10))/$((010)),$((0x10)):')" . | |
3780 | 3908 | expected-stdout: |
3781 | - :10.10.16. | |
3782 | ---- | |
3783 | -name: integer-base-check-flat-legacy | |
3784 | -description: | |
3785 | - Check behaviour matches POSuX for LEGACY KSH | |
3786 | -category: shell:legacy-yes | |
3787 | -stdin: | |
3788 | - echo :$((10)).$((010)).$((0x10)). | |
3789 | -expected-stdout: | |
3790 | - :10.8.16. | |
3909 | + 1 :10/10,16: . | |
3910 | + 2 :10/8,16: . | |
3911 | + 3 :10/10,16: . | |
3791 | 3912 | --- |
3792 | 3913 | name: integer-base-check-numeric-from |
3793 | 3914 | description: |
@@ -3913,6 +4034,13 @@ expected-stdout: | ||
3913 | 4034 | s:-9223372036854775808.-1.0. |
3914 | 4035 | u:9223372036854775808.18446744073709551615.0. |
3915 | 4036 | --- |
4037 | +name: integer-size-FAIL-to-detect | |
4038 | +description: | |
4039 | + Notify the user that their ints are not 32 or 64 bit | |
4040 | +category: int:u | |
4041 | +stdin: | |
4042 | + : | |
4043 | +--- | |
3916 | 4044 | name: lineno-stdin |
3917 | 4045 | description: |
3918 | 4046 | See if $LINENO is updated and can be modified. |
@@ -4245,7 +4373,7 @@ description: | ||
4245 | 4373 | should print 0 according to POSIX (dash, bash, ksh93, posh) |
4246 | 4374 | but not 0 according to the getopt(1) manual page, ksh88, and |
4247 | 4375 | Bourne sh (such as /bin/sh on Solaris). |
4248 | - In mksh R39b, we honour POSIX except when -o sh is set. | |
4376 | + We honour POSIX except when -o sh is set. | |
4249 | 4377 | category: shell:legacy-no |
4250 | 4378 | stdin: |
4251 | 4379 | showf() { |
@@ -4265,10 +4393,15 @@ stdin: | ||
4265 | 4393 | showf |
4266 | 4394 | set -- `false` |
4267 | 4395 | echo rv=$? |
4396 | + set -o posix -o sh | |
4397 | + showf | |
4398 | + set -- `false` | |
4399 | + echo rv=$? | |
4268 | 4400 | expected-stdout: |
4269 | 4401 | FPOSIX=0 FSH=0 rv=0 |
4270 | 4402 | FPOSIX=0 FSH=1 rv=1 |
4271 | 4403 | FPOSIX=1 FSH=0 rv=0 |
4404 | + FPOSIX=1 FSH=1 rv=0 | |
4272 | 4405 | --- |
4273 | 4406 | name: regression-10-legacy |
4274 | 4407 | description: |
@@ -4297,10 +4430,15 @@ stdin: | ||
4297 | 4430 | showf |
4298 | 4431 | set -- `false` |
4299 | 4432 | echo rv=$? |
4433 | + set -o posix -o sh | |
4434 | + showf | |
4435 | + set -- `false` | |
4436 | + echo rv=$? | |
4300 | 4437 | expected-stdout: |
4301 | 4438 | FPOSIX=0 FSH=0 rv=1 |
4302 | 4439 | FPOSIX=0 FSH=1 rv=1 |
4303 | - FPOSIX=1 FSH=0 rv=1 | |
4440 | + FPOSIX=1 FSH=0 rv=0 | |
4441 | + FPOSIX=1 FSH=1 rv=0 | |
4304 | 4442 | --- |
4305 | 4443 | name: regression-11 |
4306 | 4444 | description: |
@@ -4663,18 +4801,16 @@ expected-stdout: | ||
4663 | 4801 | --- |
4664 | 4802 | name: regression-39 |
4665 | 4803 | description: |
4666 | - set -e: errors in command substitutions aren't ignored | |
4667 | - Not clear if they should be or not... bash passes here | |
4668 | - this may actually be required for make, so changed the | |
4669 | - test to make this an mksh feature, not a bug | |
4670 | -arguments: !-e! | |
4804 | + Only posh and oksh(2013-07) say “hi” below; FreeBSD sh, | |
4805 | + GNU bash in POSIX mode, dash, ksh93, mksh don’t. All of | |
4806 | + them exit 0. The POSIX behaviour is needed by BSD make. | |
4671 | 4807 | stdin: |
4808 | + set -e | |
4672 | 4809 | echo `false; echo hi` |
4673 | -#expected-fail: yes | |
4674 | -#expected-stdout: | |
4675 | -# hi | |
4810 | + echo $? | |
4676 | 4811 | expected-stdout: |
4677 | 4812 | |
4813 | + 0 | |
4678 | 4814 | --- |
4679 | 4815 | name: regression-40 |
4680 | 4816 | description: |
@@ -5984,6 +6120,27 @@ expected-stdout: | ||
5984 | 6120 | EXtrap |
5985 | 6121 | = noeval-undef 1 . |
5986 | 6122 | --- |
6123 | +name: exit-trap-interactive | |
6124 | +description: | |
6125 | + Check that interactive shell doesn't exit via EXIT trap on syntax error | |
6126 | +arguments: !-i! | |
6127 | +stdin: | |
6128 | + trap -- EXIT | |
6129 | + echo Syntax error < | |
6130 | + echo 'After error 1' | |
6131 | + trap 'echo Exit trap' EXIT | |
6132 | + echo Syntax error < | |
6133 | + echo 'After error 2' | |
6134 | + trap 'echo Exit trap' EXIT | |
6135 | + exit | |
6136 | + echo 'After exit' | |
6137 | +expected-stdout: | |
6138 | + After error 1 | |
6139 | + After error 2 | |
6140 | + Exit trap | |
6141 | +expected-stderr-pattern: | |
6142 | + /syntax error: 'newline' unexpected/ | |
6143 | +--- | |
5987 | 6144 | name: test-stlt-1 |
5988 | 6145 | description: |
5989 | 6146 | Check that test also can handle string1 < string2 etc. |
@@ -6178,7 +6335,7 @@ expected-stdout: | ||
6178 | 6335 | --- |
6179 | 6336 | name: sh-mode-2a |
6180 | 6337 | description: |
6181 | - Check that sh mode is *not* automatically turned on | |
6338 | + Check that posix or sh mode is *not* automatically turned on | |
6182 | 6339 | category: !binsh |
6183 | 6340 | stdin: |
6184 | 6341 | ln -s "$__progname" ksh || cp "$__progname" ksh |
@@ -6187,7 +6344,7 @@ stdin: | ||
6187 | 6344 | ln -s "$__progname" ./-sh || cp "$__progname" ./-sh |
6188 | 6345 | for shell in {,-}{,k}sh; do |
6189 | 6346 | print -- $shell $(./$shell +l -c \ |
6190 | - '[[ $(set +o) == *@(-o sh)@(| *) ]] && echo sh || echo nosh') | |
6347 | + '[[ $(set +o) == *"-o "@(sh|posix)@(| *) ]] && echo sh || echo nosh') | |
6191 | 6348 | done |
6192 | 6349 | expected-stdout: |
6193 | 6350 | sh nosh |
@@ -6197,7 +6354,7 @@ expected-stdout: | ||
6197 | 6354 | --- |
6198 | 6355 | name: sh-mode-2b |
6199 | 6356 | description: |
6200 | - Check that sh mode *is* automatically turned on | |
6357 | + Check that posix or sh mode *is* automatically turned on | |
6201 | 6358 | category: binsh |
6202 | 6359 | stdin: |
6203 | 6360 | ln -s "$__progname" ksh || cp "$__progname" ksh |
@@ -6206,7 +6363,7 @@ stdin: | ||
6206 | 6363 | ln -s "$__progname" ./-sh || cp "$__progname" ./-sh |
6207 | 6364 | for shell in {,-}{,k}sh; do |
6208 | 6365 | print -- $shell $(./$shell +l -c \ |
6209 | - '[[ $(set +o) == *@(-o sh)@(| *) ]] && echo sh || echo nosh') | |
6366 | + '[[ $(set +o) == *"-o "@(sh|posix)@(| *) ]] && echo sh || echo nosh') | |
6210 | 6367 | done |
6211 | 6368 | expected-stdout: |
6212 | 6369 | sh sh |
@@ -6275,6 +6432,28 @@ expected-stdout: | ||
6275 | 6432 | PIPESTATUS[0]=0 |
6276 | 6433 | 8 PIPESTATUS[0]=0 PIPESTATUS[1]=0 . |
6277 | 6434 | --- |
6435 | +name: pipeline-4 | |
6436 | +description: | |
6437 | + Check that "set -o pipefail" does what it's supposed to | |
6438 | +stdin: | |
6439 | + echo 1 "$("$__progname" -c '(exit 12) | (exit 23) | (exit 42); echo $?')" . | |
6440 | + echo 2 "$("$__progname" -c '! (exit 12) | (exit 23) | (exit 42); echo $?')" . | |
6441 | + echo 3 "$("$__progname" -o pipefail -c '(exit 12) | (exit 23) | (exit 42); echo $?')" . | |
6442 | + echo 4 "$("$__progname" -o pipefail -c '! (exit 12) | (exit 23) | (exit 42); echo $?')" . | |
6443 | + echo 5 "$("$__progname" -c '(exit 23) | (exit 42) | :; echo $?')" . | |
6444 | + echo 6 "$("$__progname" -c '! (exit 23) | (exit 42) | :; echo $?')" . | |
6445 | + echo 7 "$("$__progname" -o pipefail -c '(exit 23) | (exit 42) | :; echo $?')" . | |
6446 | + echo 8 "$("$__progname" -o pipefail -c '! (exit 23) | (exit 42) | :; echo $?')" . | |
6447 | +expected-stdout: | |
6448 | + 1 42 . | |
6449 | + 2 0 . | |
6450 | + 3 42 . | |
6451 | + 4 0 . | |
6452 | + 5 0 . | |
6453 | + 6 1 . | |
6454 | + 7 42 . | |
6455 | + 8 0 . | |
6456 | +--- | |
6278 | 6457 | name: persist-history-1 |
6279 | 6458 | description: |
6280 | 6459 | Check if persistent history saving works |
@@ -7551,6 +7730,28 @@ stdin: | ||
7551 | 7730 | expected-stdout: |
7552 | 7731 | ab |
7553 | 7732 | --- |
7733 | +name: print-cr | |
7734 | +description: | |
7735 | + Check that CR+LF is not collapsed into LF as some MSYS shells wrongly do | |
7736 | +stdin: | |
7737 | + echo '#!'"$__progname" >foo | |
7738 | + cat >>foo <<-'EOF' | |
7739 | + print -n -- '220-blau.mirbsd.org ESMTP ready at Thu, 25 Jul 2013 15:57:57 GMT\r\n220->> Bitte keine Werbung einwerfen! <<\r\r\n220 Who do you wanna pretend to be today' | |
7740 | + print \? | |
7741 | + EOF | |
7742 | + chmod +x foo | |
7743 | + echo "[$(./foo)]" | |
7744 | + ./foo | while IFS= read -r line; do | |
7745 | + print -r -- "{$line}" | |
7746 | + done | |
7747 | +expected-stdout: | |
7748 | + [220-blau.mirbsd.org ESMTP ready at Thu, 25 Jul 2013 15:57:57 GMT | |
7749 | + 220->> Bitte keine Werbung einwerfen! << | |
7750 | + 220 Who do you wanna pretend to be today? ] | |
7751 | + {220-blau.mirbsd.org ESMTP ready at Thu, 25 Jul 2013 15:57:57 GMT } | |
7752 | + {220->> Bitte keine Werbung einwerfen! << } | |
7753 | + {220 Who do you wanna pretend to be today? } | |
7754 | +--- | |
7554 | 7755 | name: print-nul-chars |
7555 | 7756 | description: |
7556 | 7757 | Check handling of NUL characters for print and COMSUB |
@@ -8363,6 +8564,7 @@ name: bashiop-1 | ||
8363 | 8564 | description: |
8364 | 8565 | Check if GNU bash-like I/O redirection works |
8365 | 8566 | Part 1: this is also supported by GNU bash |
8567 | +category: shell:legacy-no | |
8366 | 8568 | stdin: |
8367 | 8569 | exec 3>&1 |
8368 | 8570 | function threeout { |
@@ -8383,6 +8585,7 @@ name: bashiop-2a | ||
8383 | 8585 | description: |
8384 | 8586 | Check if GNU bash-like I/O redirection works |
8385 | 8587 | Part 2: this is *not* supported by GNU bash |
8588 | +category: shell:legacy-no | |
8386 | 8589 | stdin: |
8387 | 8590 | exec 3>&1 |
8388 | 8591 | function threeout { |
@@ -8403,6 +8606,7 @@ name: bashiop-2b | ||
8403 | 8606 | description: |
8404 | 8607 | Check if GNU bash-like I/O redirection works |
8405 | 8608 | Part 2: this is *not* supported by GNU bash |
8609 | +category: shell:legacy-no | |
8406 | 8610 | stdin: |
8407 | 8611 | exec 3>&1 |
8408 | 8612 | function threeout { |
@@ -8423,6 +8627,7 @@ name: bashiop-2c | ||
8423 | 8627 | description: |
8424 | 8628 | Check if GNU bash-like I/O redirection works |
8425 | 8629 | Part 2: this is supported by GNU bash 4 only |
8630 | +category: shell:legacy-no | |
8426 | 8631 | stdin: |
8427 | 8632 | echo mir >foo |
8428 | 8633 | set -o noclobber |
@@ -8446,6 +8651,7 @@ name: bashiop-3a | ||
8446 | 8651 | description: |
8447 | 8652 | Check if GNU bash-like I/O redirection fails correctly |
8448 | 8653 | Part 1: this is also supported by GNU bash |
8654 | +category: shell:legacy-no | |
8449 | 8655 | stdin: |
8450 | 8656 | echo mir >foo |
8451 | 8657 | set -o noclobber |
@@ -8467,6 +8673,7 @@ name: bashiop-3b | ||
8467 | 8673 | description: |
8468 | 8674 | Check if GNU bash-like I/O redirection fails correctly |
8469 | 8675 | Part 2: this is *not* supported by GNU bash |
8676 | +category: shell:legacy-no | |
8470 | 8677 | stdin: |
8471 | 8678 | echo mir >foo |
8472 | 8679 | set -o noclobber |
@@ -8490,6 +8697,7 @@ description: | ||
8490 | 8697 | Check if GNU bash-like I/O redirection works |
8491 | 8698 | Part 4: this is also supported by GNU bash, |
8492 | 8699 | but failed in some mksh versions |
8700 | +category: shell:legacy-no | |
8493 | 8701 | stdin: |
8494 | 8702 | exec 3>&1 |
8495 | 8703 | function threeout { |
@@ -8511,6 +8719,34 @@ expected-stdout: | ||
8511 | 8719 | ras |
8512 | 8720 | dwa |
8513 | 8721 | --- |
8722 | +name: bashiop-5-normal | |
8723 | +description: | |
8724 | + Check if GNU bash-like I/O redirection is only supported | |
8725 | + in !POSIX !sh mode as it breaks existing scripts' syntax | |
8726 | +category: shell:legacy-no | |
8727 | +stdin: | |
8728 | + :>x; echo 1 "$("$__progname" -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" . | |
8729 | + :>x; echo 2 "$("$__progname" -o posix -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" . | |
8730 | + :>x; echo 3 "$("$__progname" -o sh -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" . | |
8731 | +expected-stdout: | |
8732 | + 1 = foo echo bar . | |
8733 | + 2 = bar . | |
8734 | + 3 = bar . | |
8735 | +--- | |
8736 | +name: bashiop-5-legacy | |
8737 | +description: | |
8738 | + Check if GNU bash-like I/O redirection is not parsed | |
8739 | + in lksh as it breaks existing scripts' syntax | |
8740 | +category: shell:legacy-yes | |
8741 | +stdin: | |
8742 | + :>x; echo 1 "$("$__progname" -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" . | |
8743 | + :>x; echo 2 "$("$__progname" -o posix -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" . | |
8744 | + :>x; echo 3 "$("$__progname" -o sh -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" . | |
8745 | +expected-stdout: | |
8746 | + 1 = bar . | |
8747 | + 2 = bar . | |
8748 | + 3 = bar . | |
8749 | +--- | |
8514 | 8750 | name: mkshiop-1 |
8515 | 8751 | description: |
8516 | 8752 | Check for support of more than 9 file descriptors |
@@ -8534,10 +8770,57 @@ expected-stdout: | ||
8534 | 8770 | bar |
8535 | 8771 | baz |
8536 | 8772 | --- |
8537 | -name: oksh-shcrash | |
8773 | +name: oksh-eval | |
8538 | 8774 | description: |
8539 | - src/regress/bin/ksh/shcrash.sh,v 1.1 | |
8775 | + $OpenBSD: eval.sh,v 1.1 2010/03/24 08:29:44 fgsch Exp $ | |
8540 | 8776 | stdin: |
8777 | + a= | |
8778 | + for n in ${a#*=}; do echo 1hu ${n} .; done | |
8779 | + for n in "${a#*=}"; do echo 1hq ${n} .; done | |
8780 | + for n in ${a##*=}; do echo 2hu ${n} .; done | |
8781 | + for n in "${a##*=}"; do echo 2hq ${n} .; done | |
8782 | + for n in ${a%=*}; do echo 1pu ${n} .; done | |
8783 | + for n in "${a%=*}"; do echo 1pq ${n} .; done | |
8784 | + for n in ${a%%=*}; do echo 2pu ${n} .; done | |
8785 | + for n in "${a%%=*}"; do echo 2pq ${n} .; done | |
8786 | +expected-stdout: | |
8787 | + 1hq . | |
8788 | + 2hq . | |
8789 | + 1pq . | |
8790 | + 2pq . | |
8791 | +--- | |
8792 | +name: oksh-and-list-error-1 | |
8793 | +description: | |
8794 | + Test exit status of rightmost element in 2 element && list in -e mode | |
8795 | +stdin: | |
8796 | + true && false | |
8797 | + echo "should not print" | |
8798 | +arguments: !-e! | |
8799 | +expected-exit: e != 0 | |
8800 | +--- | |
8801 | +name: oksh-and-list-error-2 | |
8802 | +description: | |
8803 | + Test exit status of rightmost element in 3 element && list in -e mode | |
8804 | +stdin: | |
8805 | + true && true && false | |
8806 | + echo "should not print" | |
8807 | +arguments: !-e! | |
8808 | +expected-exit: e != 0 | |
8809 | +--- | |
8810 | +name: oksh-or-list-error-1 | |
8811 | +description: | |
8812 | + Test exit status of || list in -e mode | |
8813 | +stdin: | |
8814 | + false || false | |
8815 | + echo "should not print" | |
8816 | +arguments: !-e! | |
8817 | +expected-exit: e != 0 | |
8818 | +--- | |
8819 | +name: oksh-longline-crash | |
8820 | +description: | |
8821 | + This used to cause a core dump | |
8822 | +stdin: | |
8823 | + ulimit -c 0 | |
8541 | 8824 | deplibs="-lz -lpng /usr/local/lib/libjpeg.la -ltiff -lm -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libglib.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgtk.la -ltiff -ljpeg -lz -lpng -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk_pixbuf.la -lz -lpng /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libglib.la -lm -lm /usr/local/lib/libaudiofile.la -lm -lm -laudiofile -L/usr/local/lib /usr/local/lib/libesd.la -lm -lz -L/usr/local/lib /usr/local/lib/libgnomesupport.la -lm -lz -lm -lglib -L/usr/local/lib /usr/local/lib/libgnome.la -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgtk.la -lICE -lSM -lz -lpng /usr/local/lib/libungif.la /usr/local/lib/libjpeg.la -ltiff -lm -lz -lpng /usr/local/lib/libungif.la -lz /usr/local/lib/libjpeg.la -ltiff -L/usr/local/lib -L/usr/X11R6/lib /usr/local/lib/libgdk_imlib.la -lm -L/usr/local/lib /usr/local/lib/libart_lgpl.la -lm -lz -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lICE -lSM -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -L/usr/X11R6/lib -lm -lz -lpng -lungif -lz -ljpeg -ltiff -ljpeg -lgdk_imlib -lglib -lm -laudiofile -lm -laudiofile -lesd -L/usr/local/lib /usr/local/lib/libgnomeui.la -lz -lz /usr/local/lib/libxml.la -lz -lz -lz /usr/local/lib/libxml.la -lm -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libglib.la /usr/local/lib/libgmodule.la -lintl -lglib -lgmodule /usr/local/lib/libgdk.la /usr/local/lib/libgtk.la -L/usr/X11R6/lib -L/usr/local/lib /usr/local/lib/libglade.la -lz -lz -lz /usr/local/lib/libxml.la /usr/local/lib/libglib.la -lm -lm /usr/local/lib/libaudiofile.la -lm -lm -laudiofile /usr/local/lib/libesd.la -lm -lz /usr/local/lib/libgnomesupport.la -lm -lz -lm -lglib /usr/local/lib/libgnome.la -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -lglib -lgmodule /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -lglib -lgmodule /usr/local/lib/libgtk.la -lICE -lSM -lz -lpng /usr/local/lib/libungif.la /usr/local/lib/libjpeg.la -ltiff -lm -lz -lz /usr/local/lib/libgdk_imlib.la /usr/local/lib/libart_lgpl.la -lm -lz -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lm -lz -lungif -lz -ljpeg -ljpeg -lgdk_imlib -lglib -lm -laudiofile -lm -laudiofile -lesd /usr/local/lib/libgnomeui.la -L/usr/X11R6/lib -L/usr/local/lib /usr/local/lib/libglade-gnome.la /usr/local/lib/libglib.la -lm -lm /usr/local/lib/libaudiofile.la -lm -lm -laudiofile -L/usr/local/lib /usr/local/lib/libesd.la -lm -lz -L/usr/local/lib /usr/local/lib/libgnomesupport.la -lm -lz -lm -lglib -L/usr/local/lib /usr/local/lib/libgnome.la -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgtk.la -lICE -lSM -lz -lpng /usr/local/lib/libungif.la /usr/local/lib/libjpeg.la -ltiff -lm -lz -lpng /usr/local/lib/libungif.la -lz /usr/local/lib/libjpeg.la -ltiff -L/usr/local/lib -L/usr/X11R6/lib /usr/local/lib/libgdk_imlib.la -lm -L/usr/local/lib /usr/local/lib/libart_lgpl.la -lm -lz -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lICE -lSM -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -L/usr/X11R6/lib -lm -lz -lpng -lungif -lz -ljpeg -ltiff -ljpeg -lgdk_imlib -lglib -lm -laudiofile -lm -laudiofile -lesd -L/usr/local/lib /usr/local/lib/libgnomeui.la -L/usr/X11R6/lib -L/usr/local/lib" |
8542 | 8825 | specialdeplibs="-lgnomeui -lart_lgpl -lgdk_imlib -ltiff -ljpeg -lungif -lpng -lz -lSM -lICE -lgtk -lgdk -lgmodule -lintl -lXext -lX11 -lgnome -lgnomesupport -lesd -laudiofile -lm -lglib" |
8543 | 8826 | for deplib in $deplibs; do |
@@ -8554,6 +8837,99 @@ stdin: | ||
8554 | 8837 | esac |
8555 | 8838 | done |
8556 | 8839 | --- |
8840 | +name: oksh-seterror-1 | |
8841 | +description: | |
8842 | + The -e flag should be ignored when executing a compound list | |
8843 | + followed by an if statement. | |
8844 | +stdin: | |
8845 | + if true; then false && false; fi | |
8846 | + true | |
8847 | +arguments: !-e! | |
8848 | +expected-exit: e == 0 | |
8849 | +--- | |
8850 | +name: oksh-seterror-2 | |
8851 | +description: | |
8852 | + The -e flag should be ignored when executing a compound list | |
8853 | + followed by an if statement. | |
8854 | +stdin: | |
8855 | + if true; then if true; then false && false; fi; fi | |
8856 | + true | |
8857 | +arguments: !-e! | |
8858 | +expected-exit: e == 0 | |
8859 | +--- | |
8860 | +name: oksh-seterror-3 | |
8861 | +description: | |
8862 | + The -e flag should be ignored when executing a compound list | |
8863 | + followed by an elif statement. | |
8864 | +stdin: | |
8865 | + if true; then :; elif true; then false && false; fi | |
8866 | +arguments: !-e! | |
8867 | +expected-exit: e == 0 | |
8868 | +--- | |
8869 | +name: oksh-seterror-4 | |
8870 | +description: | |
8871 | + The -e flag should be ignored when executing a pipeline | |
8872 | + beginning with '!' | |
8873 | +stdin: | |
8874 | + for i in 1 2 3 | |
8875 | + do | |
8876 | + false && false | |
8877 | + true || false | |
8878 | + done | |
8879 | +arguments: !-e! | |
8880 | +expected-exit: e == 0 | |
8881 | +--- | |
8882 | +name: oksh-seterror-5 | |
8883 | +description: | |
8884 | + The -e flag should be ignored when executing a pipeline | |
8885 | + beginning with '!' | |
8886 | +stdin: | |
8887 | + ! true | false | |
8888 | + true | |
8889 | +arguments: !-e! | |
8890 | +expected-exit: e == 0 | |
8891 | +--- | |
8892 | +name: oksh-seterror-6 | |
8893 | +description: | |
8894 | + When trapping ERR and EXIT, both traps should run in -e mode | |
8895 | + when an error occurs. | |
8896 | +stdin: | |
8897 | + trap 'echo EXIT' EXIT | |
8898 | + trap 'echo ERR' ERR | |
8899 | + set -e | |
8900 | + false | |
8901 | + echo DONE | |
8902 | + exit 0 | |
8903 | +arguments: !-e! | |
8904 | +expected-exit: e != 0 | |
8905 | +expected-stdout: | |
8906 | + ERR | |
8907 | + EXIT | |
8908 | +--- | |
8909 | +name: oksh-seterror-7 | |
8910 | +description: | |
8911 | + The -e flag within a command substitution should be honored | |
8912 | +stdin: | |
8913 | + echo $( set -e; false; echo foo ) | |
8914 | +arguments: !-e! | |
8915 | +expected-stdout: | |
8916 | + | |
8917 | +--- | |
8918 | +name: oksh-input-comsub | |
8919 | +description: | |
8920 | + A command substitution using input redirection should exit with | |
8921 | + failure if the input file does not exist. | |
8922 | +stdin: | |
8923 | + var=$(< non-existent) | |
8924 | +expected-exit: e != 0 | |
8925 | +expected-stderr-pattern: /non-existent/ | |
8926 | +--- | |
8927 | +name: oksh-empty-for-list | |
8928 | +description: | |
8929 | + A for list which expands to zero items should not execute the body. | |
8930 | +stdin: | |
8931 | + set foo bar baz ; for out in ; do echo $out ; done | |
8932 | +--- | |
8557 | 8933 | name: oksh-varfunction-mod1 |
8558 | 8934 | description: |
8559 | 8935 | $OpenBSD: varfunction.sh,v 1.1 2003/12/15 05:28:40 otto Exp $ |
@@ -8846,8 +9222,8 @@ stdin: | ||
8846 | 9222 | EOFI |
8847 | 9223 | #IORDWR_IODUP |
8848 | 9224 | sh 1<>/dev/console 0<&1 2>&1 |
8849 | - #COMSUB_EXPRSUB | |
8850 | - echo $(true) $((1+ 2)) | |
9225 | + #COMSUB_EXPRSUB_FUNSUB_VALSUB | |
9226 | + echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} | |
8851 | 9227 | #QCHAR_OQUOTE_CQUOTE |
8852 | 9228 | echo fo\ob\"a\`r\'b\$az |
8853 | 9229 | echo "fo\ob\"a\`r\'b\$az" |
@@ -9041,7 +9417,7 @@ expected-stdout: | ||
9041 | 9417 | } |
9042 | 9418 | inline_TWHILE() { |
9043 | 9419 | i=1 |
9044 | - while let " i < 10 " | |
9420 | + while let] " i < 10 " | |
9045 | 9421 | do |
9046 | 9422 | echo $i |
9047 | 9423 | let ++i |
@@ -9051,20 +9427,20 @@ expected-stdout: | ||
9051 | 9427 | i=1; while (( i < 10 )); do echo $i; let ++i; done |
9052 | 9428 | ); } |
9053 | 9429 | function comsub_TWHILE { |
9054 | - x=$(i=1 ; while let " i < 10 " ; do echo $i ; let ++i ; done ) | |
9430 | + x=$(i=1 ; while let] " i < 10 " ; do echo $i ; let ++i ; done ) | |
9055 | 9431 | } |
9056 | 9432 | function reread_TWHILE { x=$(( |
9057 | 9433 | i=1; while (( i < 10 )); do echo $i; let ++i; done |
9058 | 9434 | )|tr u x); } |
9059 | 9435 | function reread_TWHILE { |
9060 | - x=$(( i=1 ; while let " i < 10 " ; do echo $i ; let ++i ; done ) | tr u x ) | |
9436 | + x=$(( i=1 ; while let] " i < 10 " ; do echo $i ; let ++i ; done ) | tr u x ) | |
9061 | 9437 | } |
9062 | 9438 | inline_TUNTIL() { |
9063 | 9439 | i=10; until (( !--i )) ; do echo $i; done |
9064 | 9440 | } |
9065 | 9441 | inline_TUNTIL() { |
9066 | 9442 | i=10 |
9067 | - until let " !--i " | |
9443 | + until let] " !--i " | |
9068 | 9444 | do |
9069 | 9445 | echo $i |
9070 | 9446 | done |
@@ -9073,13 +9449,13 @@ expected-stdout: | ||
9073 | 9449 | i=10; until (( !--i )) ; do echo $i; done |
9074 | 9450 | ); } |
9075 | 9451 | function comsub_TUNTIL { |
9076 | - x=$(i=10 ; until let " !--i " ; do echo $i ; done ) | |
9452 | + x=$(i=10 ; until let] " !--i " ; do echo $i ; done ) | |
9077 | 9453 | } |
9078 | 9454 | function reread_TUNTIL { x=$(( |
9079 | 9455 | i=10; until (( !--i )) ; do echo $i; done |
9080 | 9456 | )|tr u x); } |
9081 | 9457 | function reread_TUNTIL { |
9082 | - x=$(( i=10 ; until let " !--i " ; do echo $i ; done ) | tr u x ) | |
9458 | + x=$(( i=10 ; until let] " !--i " ; do echo $i ; done ) | tr u x ) | |
9083 | 9459 | } |
9084 | 9460 | inline_TCOPROC() { |
9085 | 9461 | cat * |& ls |
@@ -9229,23 +9605,23 @@ expected-stdout: | ||
9229 | 9605 | function reread_IORDWR_IODUP { |
9230 | 9606 | x=$(( sh 1<>/dev/console <&1 2>&1 ) | tr u x ) |
9231 | 9607 | } |
9232 | - inline_COMSUB_EXPRSUB() { | |
9233 | - echo $(true) $((1+ 2)) | |
9608 | + inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() { | |
9609 | + echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} | |
9234 | 9610 | } |
9235 | - inline_COMSUB_EXPRSUB() { | |
9236 | - echo $(true ) $((1+ 2)) | |
9611 | + inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() { | |
9612 | + echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} | |
9237 | 9613 | } |
9238 | - function comsub_COMSUB_EXPRSUB { x=$( | |
9239 | - echo $(true) $((1+ 2)) | |
9614 | + function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$( | |
9615 | + echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} | |
9240 | 9616 | ); } |
9241 | - function comsub_COMSUB_EXPRSUB { | |
9242 | - x=$(echo $(true ) $((1+ 2)) ) | |
9617 | + function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { | |
9618 | + x=$(echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) | |
9243 | 9619 | } |
9244 | - function reread_COMSUB_EXPRSUB { x=$(( | |
9245 | - echo $(true) $((1+ 2)) | |
9620 | + function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(( | |
9621 | + echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} | |
9246 | 9622 | )|tr u x); } |
9247 | - function reread_COMSUB_EXPRSUB { | |
9248 | - x=$(( echo $(true ) $((1+ 2)) ) | tr u x ) | |
9623 | + function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { | |
9624 | + x=$(( echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) | tr u x ) | |
9249 | 9625 | } |
9250 | 9626 | inline_QCHAR_OQUOTE_CQUOTE() { |
9251 | 9627 | echo fo\ob\"a\`r\'b\$az |
@@ -9693,7 +10069,7 @@ expected-stdout: | ||
9693 | 10069 | } |
9694 | 10070 | inline_TWHILE() { |
9695 | 10071 | i=1 |
9696 | - while let " i < 10 " >&3 | |
10072 | + while let] " i < 10 " >&3 | |
9697 | 10073 | do |
9698 | 10074 | echo $i |
9699 | 10075 | let ++i |
@@ -9703,20 +10079,20 @@ expected-stdout: | ||
9703 | 10079 | i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 |
9704 | 10080 | ); } |
9705 | 10081 | function comsub_TWHILE { |
9706 | - x=$(i=1 ; while let " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | |
10082 | + x=$(i=1 ; while let] " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | |
9707 | 10083 | } |
9708 | 10084 | function reread_TWHILE { x=$(( |
9709 | 10085 | i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 |
9710 | 10086 | )|tr u x); } |
9711 | 10087 | function reread_TWHILE { |
9712 | - x=$(( i=1 ; while let " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x ) | |
10088 | + x=$(( i=1 ; while let] " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x ) | |
9713 | 10089 | } |
9714 | 10090 | inline_TUNTIL() { |
9715 | 10091 | i=10; until (( !--i )) >&3 ; do echo $i; done >&3 |
9716 | 10092 | } |
9717 | 10093 | inline_TUNTIL() { |
9718 | 10094 | i=10 |
9719 | - until let " !--i " >&3 | |
10095 | + until let] " !--i " >&3 | |
9720 | 10096 | do |
9721 | 10097 | echo $i |
9722 | 10098 | done >&3 |
@@ -9725,13 +10101,13 @@ expected-stdout: | ||
9725 | 10101 | i=10; until (( !--i )) >&3 ; do echo $i; done >&3 |
9726 | 10102 | ); } |
9727 | 10103 | function comsub_TUNTIL { |
9728 | - x=$(i=10 ; until let " !--i " >&3 ; do echo $i ; done >&3 ) | |
10104 | + x=$(i=10 ; until let] " !--i " >&3 ; do echo $i ; done >&3 ) | |
9729 | 10105 | } |
9730 | 10106 | function reread_TUNTIL { x=$(( |
9731 | 10107 | i=10; until (( !--i )) >&3 ; do echo $i; done >&3 |
9732 | 10108 | )|tr u x); } |
9733 | 10109 | function reread_TUNTIL { |
9734 | - x=$(( i=10 ; until let " !--i " >&3 ; do echo $i ; done >&3 ) | tr u x ) | |
10110 | + x=$(( i=10 ; until let] " !--i " >&3 ; do echo $i ; done >&3 ) | tr u x ) | |
9735 | 10111 | } |
9736 | 10112 | inline_TCOPROC() { |
9737 | 10113 | cat * >&3 |& >&3 ls |
@@ -9831,6 +10207,38 @@ expected-stdout: | ||
9831 | 10207 | 2:ya x2,1,0. |
9832 | 10208 | 3:ya,1,3. |
9833 | 10209 | --- |
10210 | +name: valsub-1 | |
10211 | +description: | |
10212 | + Check that "value substitutions" work as advertised | |
10213 | +stdin: | |
10214 | + x=1 | |
10215 | + y=2 | |
10216 | + z=3 | |
10217 | + REPLY=4 | |
10218 | + echo "before: x<$x> y<$y> z<$z> R<$REPLY>" | |
10219 | + x=${| | |
10220 | + local y | |
10221 | + echo "begin: x<$x> y<$y> z<$z> R<$REPLY>" | |
10222 | + x=5 | |
10223 | + y=6 | |
10224 | + z=7 | |
10225 | + REPLY=8 | |
10226 | + echo "end: x<$x> y<$y> z<$z> R<$REPLY>" | |
10227 | + } | |
10228 | + echo "after: x<$x> y<$y> z<$z> R<$REPLY>" | |
10229 | + # ensure trailing newlines are kept | |
10230 | + t=${|REPLY=$'foo\n\n';} | |
10231 | + typeset -p t | |
10232 | + echo -n this used to segfault | |
10233 | + echo ${|true;}$(true). | |
10234 | +expected-stdout: | |
10235 | + before: x<1> y<2> z<3> R<4> | |
10236 | + begin: x<1> y<> z<3> R<> | |
10237 | + end: x<5> y<6> z<7> R<8> | |
10238 | + after: x<8> y<2> z<7> R<4> | |
10239 | + typeset t=$'foo\n\n' | |
10240 | + this used to segfault. | |
10241 | +--- | |
9834 | 10242 | name: test-stnze-1 |
9835 | 10243 | description: |
9836 | 10244 | Check that the short form [ $x ] works |
@@ -10156,7 +10564,7 @@ description: | ||
10156 | 10564 | time-limit: 3 |
10157 | 10565 | stdin: |
10158 | 10566 | baz() { |
10159 | - typeset -n foo=foo | |
10567 | + typeset -n foo=fnord fnord=foo | |
10160 | 10568 | foo[0]=bar |
10161 | 10569 | } |
10162 | 10570 | set -A foo bad |
@@ -10165,7 +10573,9 @@ stdin: | ||
10165 | 10573 | echo blah $foo . |
10166 | 10574 | expected-stdout: |
10167 | 10575 | sind bad . |
10168 | - blah bar . | |
10576 | + blah bad . | |
10577 | +expected-stderr-pattern: | |
10578 | + /fnord: expression recurses on parameter/ | |
10169 | 10579 | --- |
10170 | 10580 | name: better-parens-1a |
10171 | 10581 | description: |
@@ -10743,3 +11153,19 @@ stdin: | ||
10743 | 11153 | done |
10744 | 11154 | Lb64decode $s >/dev/null |
10745 | 11155 | --- |
11156 | +name: xtrace-1 | |
11157 | +description: | |
11158 | + Check that "set -x" doesn't redirect too quickly | |
11159 | +stdin: | |
11160 | + print '#!'"$__progname" >bash | |
11161 | + cat >>bash <<'EOF' | |
11162 | + echo 'GNU bash, version 2.05b.0(1)-release (i386-ecce-mirbsd10) | |
11163 | + Copyright (C) 2002 Free Software Foundation, Inc.' | |
11164 | + EOF | |
11165 | + chmod +x bash | |
11166 | + "$__progname" -xc 'foo=$(./bash --version 2>&1 | head -1); echo "=$foo="' | |
11167 | +expected-stdout: | |
11168 | + =GNU bash, version 2.05b.0(1)-release (i386-ecce-mirbsd10)= | |
11169 | +expected-stderr-pattern: | |
11170 | + /.*/ | |
11171 | +--- |
@@ -1,5 +1,5 @@ | ||
1 | 1 | # $Id$ |
2 | -# $MirOS: src/bin/mksh/dot.mkshrc,v 1.77 2013/02/17 15:58:26 tg Exp $ | |
2 | +# $MirOS: src/bin/mksh/dot.mkshrc,v 1.84 2013/08/10 13:43:50 tg Exp $ | |
3 | 3 | #- |
4 | 4 | # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, |
5 | 5 | # 2011, 2012, 2013 |
@@ -22,35 +22,76 @@ | ||
22 | 22 | #- |
23 | 23 | # ${ENV:-~/.mkshrc}: mksh initialisation file for interactive shells |
24 | 24 | |
25 | +# catch non-mksh (including lksh) trying to shell this file | |
26 | +case $KSH_VERSION in | |
27 | +*MIRBSD\ KSH*) ;; | |
28 | +*) return 0 ;; | |
29 | +esac | |
30 | + | |
25 | 31 | PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \ |
26 | 32 | 2>/dev/null)} = *([ ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \ |
27 | 33 | 2>/dev/null); : ${EDITOR:=/bin/ed} ${HOSTNAME:=nil} ${TERM:=vt100} |
28 | -function precmd { | |
34 | +: ${MKSH:=$(whence -p mksh)}; PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${| | |
29 | 35 | local e=$? |
30 | 36 | |
31 | - (( e )) && print -n "$e|" | |
32 | - # precmd is required to retain the errorlevel when ${ …;} is used | |
37 | + (( e )) && REPLY+="$e|" | |
38 | + REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)} | |
39 | + REPLY+=@${HOSTNAME%%.*}: | |
40 | + | |
41 | + local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~} | |
42 | + local m=${%d} n p=...; (( m > 0 )) || m=${#d} | |
43 | + (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p= | |
44 | + REPLY+=$p$d | |
45 | + | |
33 | 46 | return $e |
34 | -} | |
35 | -PS1=$'\001\r''${ precmd;}${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \? | |
36 | - )}@${HOSTNAME%%.*}:${ local e=$? d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || \ | |
37 | - d=${d/#$p/~}; local m=${%d} n p=...; (( m > 0 )) || m=${#d} | |
38 | - (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || \ | |
39 | - p=; print -nr -- "$p$d"; return $e;} '"$PS1 " | |
40 | -: ${MKSH:=$(whence -p mksh)}; export EDITOR HOSTNAME MKSH TERM USER | |
47 | +} '"$PS1 "; export EDITOR HOSTNAME MKSH TERM USER | |
41 | 48 | alias ls=ls |
42 | 49 | unalias ls |
43 | 50 | alias l='ls -F' |
44 | 51 | alias la='l -a' |
45 | 52 | alias ll='l -l' |
46 | 53 | alias lo='l -alo' |
54 | +alias doch='sudo mksh -c "$(fc -ln -1)"' | |
47 | 55 | whence -p rot13 >/dev/null || alias rot13='tr \ |
48 | 56 | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \ |
49 | 57 | nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM' |
50 | -whence -p hd >/dev/null || function hd { | |
51 | - hexdump -e '"%08.8_ax " 8/1 "%02X " " - " 8/1 "%02X "' \ | |
52 | - -e '" |" "%_p"' -e '"|\n"' "$@" | |
53 | -} | |
58 | +if whence -p hd >/dev/null; then :; elif whence -p hexdump >/dev/null; then | |
59 | + function hd { | |
60 | + hexdump -e '"%08.8_ax " 8/1 "%02X " " - " 8/1 "%02X "' \ | |
61 | + -e '" |" "%_p"' -e '"|\n"' "$@" | |
62 | + } | |
63 | +else | |
64 | + function hd { | |
65 | + local -Uui16 -Z11 pos=0 | |
66 | + local -Uui16 -Z5 hv=2147483647 | |
67 | + local dasc line i | |
68 | + | |
69 | + cat "$@" | { set +U; if read -arN -1 line; then | |
70 | + typeset -i1 line | |
71 | + i=0 | |
72 | + while (( i < ${#line[*]} )); do | |
73 | + hv=${line[i++]} | |
74 | + if (( (pos & 15) == 0 )); then | |
75 | + (( pos )) && print -r -- "$dasc|" | |
76 | + print -n "${pos#16#} " | |
77 | + dasc=' |' | |
78 | + fi | |
79 | + print -n "${hv#16#} " | |
80 | + if (( (hv < 32) || (hv > 126) )); then | |
81 | + dasc+=. | |
82 | + else | |
83 | + dasc+=${line[i-1]#1#} | |
84 | + fi | |
85 | + (( (pos++ & 15) == 7 )) && print -n -- '- ' | |
86 | + done | |
87 | + while (( pos & 15 )); do | |
88 | + print -n ' ' | |
89 | + (( (pos++ & 15) == 7 )) && print -n -- '- ' | |
90 | + done | |
91 | + (( hv == 2147483647 )) || print -r -- "$dasc|" | |
92 | + fi; } | |
93 | + } | |
94 | +fi | |
54 | 95 | |
55 | 96 | # Berkeley C shell compatible dirs, popd, and pushd functions |
56 | 97 | # Z shell compatible chpwd() hook, used to update DIRSTACK[0] |
@@ -222,7 +263,7 @@ function Lb64decode { | ||
222 | 263 | [[ -o utf8-mode ]]; local u=$? |
223 | 264 | set +U |
224 | 265 | local c s="$*" t= |
225 | - [[ -n $s ]] || { s=$(cat;print x); s=${s%x}; } | |
266 | + [[ -n $s ]] || { s=$(cat; print x); s=${s%x}; } | |
226 | 267 | local -i i=0 j=0 n=${#s} p=0 v x |
227 | 268 | local -i16 o |
228 | 269 |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: edit.c,v 1.37 2013/01/21 10:13:24 halex Exp $ */ | |
1 | +/* $OpenBSD: edit.c,v 1.38 2013/06/03 15:41:59 tedu Exp $ */ | |
2 | 2 | /* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */ |
3 | 3 | /* $OpenBSD: emacs.c,v 1.44 2011/09/05 04:50:33 marco Exp $ */ |
4 | 4 | /* $OpenBSD: vi.c,v 1.26 2009/06/29 22:50:19 martynas Exp $ */ |
@@ -28,7 +28,7 @@ | ||
28 | 28 | |
29 | 29 | #ifndef MKSH_NO_CMDLINE_EDITING |
30 | 30 | |
31 | -__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.265 2013/02/10 19:05:36 tg Exp $"); | |
31 | +__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.270 2013/08/14 20:26:17 tg Exp $"); | |
32 | 32 | |
33 | 33 | /* |
34 | 34 | * in later versions we might use libtermcap for this, but since external |
@@ -66,7 +66,7 @@ static X_chars edchars; | ||
66 | 66 | static char editmode; |
67 | 67 | static int xx_cols; /* for Emacs mode */ |
68 | 68 | static int modified; /* buffer has been "modified" */ |
69 | -static char holdbuf[LINE]; /* place to hold last edit buffer */ | |
69 | +static char *holdbufp; /* place to hold last edit buffer */ | |
70 | 70 | |
71 | 71 | static int x_getc(void); |
72 | 72 | static void x_putcf(int); |
@@ -81,10 +81,10 @@ static char *x_glob_hlp_tilde_and_rem_qchar(char *, bool); | ||
81 | 81 | static int x_basename(const char *, const char *); |
82 | 82 | static void x_free_words(int, char **); |
83 | 83 | static int x_escape(const char *, size_t, int (*)(const char *, size_t)); |
84 | -static int x_emacs(char *, size_t); | |
84 | +static int x_emacs(char *); | |
85 | 85 | static void x_init_prompt(void); |
86 | 86 | #if !MKSH_S_NOVI |
87 | -static int x_vi(char *, size_t); | |
87 | +static int x_vi(char *); | |
88 | 88 | #endif |
89 | 89 | |
90 | 90 | #define x_flush() shf_flush(shl_out) |
@@ -110,17 +110,17 @@ static int x_e_rebuildline(const char *); | ||
110 | 110 | * read an edited command line |
111 | 111 | */ |
112 | 112 | int |
113 | -x_read(char *buf, size_t len) | |
113 | +x_read(char *buf) | |
114 | 114 | { |
115 | 115 | int i; |
116 | 116 | |
117 | 117 | x_mode(true); |
118 | 118 | modified = 1; |
119 | 119 | if (Flag(FEMACS) || Flag(FGMACS)) |
120 | - i = x_emacs(buf, len); | |
120 | + i = x_emacs(buf); | |
121 | 121 | #if !MKSH_S_NOVI |
122 | 122 | else if (Flag(FVI)) |
123 | - i = x_vi(buf, len); | |
123 | + i = x_vi(buf); | |
124 | 124 | #endif |
125 | 125 | else |
126 | 126 | /* internal error */ |
@@ -919,7 +919,6 @@ static bool x_adj_ok; | ||
919 | 919 | */ |
920 | 920 | static int x_adj_done; /* is incremented by x_adjust() */ |
921 | 921 | |
922 | -static int x_col; | |
923 | 922 | static int x_displen; |
924 | 923 | static int x_arg; /* general purpose arg */ |
925 | 924 | static bool x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */ |
@@ -944,9 +943,6 @@ static int x_curprefix; | ||
944 | 943 | static char *macroptr; /* bind key macro active? */ |
945 | 944 | #endif |
946 | 945 | #if !MKSH_S_NOVI |
947 | -static int cur_col; /* current column on line */ | |
948 | -static int pwidth; /* width of prompt */ | |
949 | -static int prompt_trunc; /* how much of prompt to truncate */ | |
950 | 946 | static int winwidth; /* width of window */ |
951 | 947 | static char *wbuf[2]; /* window buffers */ |
952 | 948 | static int wbuf_len; /* length of window buffers (x_cols - 3) */ |
@@ -955,13 +951,16 @@ static char morec; /* more character at right of window */ | ||
955 | 951 | static int lastref; /* argument to last refresh() */ |
956 | 952 | static int holdlen; /* length of holdbuf */ |
957 | 953 | #endif |
958 | -static bool prompt_redraw; /* false if newline forced after prompt */ | |
954 | +static int pwidth; /* width of prompt */ | |
955 | +static int prompt_trunc; /* how much of prompt to truncate or -1 */ | |
956 | +static int x_col; /* current column on line */ | |
959 | 957 | |
960 | 958 | static int x_ins(const char *); |
961 | 959 | static void x_delete(size_t, bool); |
962 | 960 | static size_t x_bword(void); |
963 | 961 | static size_t x_fword(bool); |
964 | 962 | static void x_goto(char *); |
963 | +static char *x_bs0(char *, char *); | |
965 | 964 | static void x_bs3(char **); |
966 | 965 | static int x_size_str(char *); |
967 | 966 | static int x_size2(char *, char **); |
@@ -1170,30 +1169,25 @@ x_e_getmbc(char *sbuf) | ||
1170 | 1169 | static void |
1171 | 1170 | x_init_prompt(void) |
1172 | 1171 | { |
1173 | - x_col = promptlen(prompt); | |
1174 | - x_adj_ok = true; | |
1175 | - prompt_redraw = true; | |
1176 | - if (x_col >= xx_cols) | |
1177 | - x_col %= xx_cols; | |
1178 | - x_displen = xx_cols - 2 - x_col; | |
1179 | - x_adj_done = 0; | |
1180 | - | |
1181 | - pprompt(prompt, 0); | |
1182 | - if (x_displen < 1) { | |
1183 | - x_col = 0; | |
1184 | - x_displen = xx_cols - 2; | |
1172 | + prompt_trunc = pprompt(prompt, 0); | |
1173 | + pwidth = prompt_trunc % x_cols; | |
1174 | + prompt_trunc -= pwidth; | |
1175 | + if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) { | |
1176 | + /* force newline after prompt */ | |
1177 | + prompt_trunc = -1; | |
1178 | + pwidth = 0; | |
1185 | 1179 | x_e_putc2('\n'); |
1186 | - prompt_redraw = false; | |
1187 | 1180 | } |
1188 | 1181 | } |
1189 | 1182 | |
1190 | 1183 | static int |
1191 | -x_emacs(char *buf, size_t len) | |
1184 | +x_emacs(char *buf) | |
1192 | 1185 | { |
1193 | 1186 | int c, i; |
1194 | 1187 | unsigned char f; |
1195 | 1188 | |
1196 | - xbp = xbuf = buf; xend = buf + len; | |
1189 | + xbp = xbuf = buf; | |
1190 | + xend = buf + LINE; | |
1197 | 1191 | xlp = xcp = xep = buf; |
1198 | 1192 | *xcp = 0; |
1199 | 1193 | xlp_valid = true; |
@@ -1202,8 +1196,10 @@ x_emacs(char *buf, size_t len) | ||
1202 | 1196 | x_histp = histptr + 1; |
1203 | 1197 | x_last_command = XFUNC_error; |
1204 | 1198 | |
1205 | - xx_cols = x_cols; | |
1206 | 1199 | x_init_prompt(); |
1200 | + x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth); | |
1201 | + x_adj_done = 0; | |
1202 | + x_adj_ok = true; | |
1207 | 1203 | |
1208 | 1204 | x_histncp = NULL; |
1209 | 1205 | if (x_nextcmd >= 0) { |
@@ -1561,11 +1557,7 @@ x_fword(bool move) | ||
1561 | 1557 | static void |
1562 | 1558 | x_goto(char *cp) |
1563 | 1559 | { |
1564 | - if (cp >= xep) | |
1565 | - cp = xep; | |
1566 | - else if (UTFMODE) | |
1567 | - while ((cp > xbuf) && ((*cp & 0xC0) == 0x80)) | |
1568 | - --cp; | |
1560 | + cp = cp >= xep ? xep : x_bs0(cp, xbuf); | |
1569 | 1561 | if (cp < xbp || cp >= utf_skipcols(xbp, x_displen)) { |
1570 | 1562 | /* we are heading off screen */ |
1571 | 1563 | xcp = cp; |
@@ -1581,16 +1573,22 @@ x_goto(char *cp) | ||
1581 | 1573 | } |
1582 | 1574 | } |
1583 | 1575 | |
1576 | +static char * | |
1577 | +x_bs0(char *cp, char *lower_bound) | |
1578 | +{ | |
1579 | + if (UTFMODE) | |
1580 | + while ((!lower_bound || (cp > lower_bound)) && | |
1581 | + ((*(unsigned char *)cp & 0xC0) == 0x80)) | |
1582 | + --cp; | |
1583 | + return (cp); | |
1584 | +} | |
1585 | + | |
1584 | 1586 | static void |
1585 | 1587 | x_bs3(char **p) |
1586 | 1588 | { |
1587 | 1589 | int i; |
1588 | 1590 | |
1589 | - (*p)--; | |
1590 | - if (UTFMODE) | |
1591 | - while (((unsigned char)**p & 0xC0) == 0x80) | |
1592 | - (*p)--; | |
1593 | - | |
1591 | + *p = x_bs0((*p) - 1, NULL); | |
1594 | 1592 | i = x_size2(*p, NULL); |
1595 | 1593 | while (i--) |
1596 | 1594 | x_e_putc2('\b'); |
@@ -1824,7 +1822,7 @@ x_load_hist(char **hp) | ||
1824 | 1822 | char *sp = NULL; |
1825 | 1823 | |
1826 | 1824 | if (hp == histptr + 1) { |
1827 | - sp = holdbuf; | |
1825 | + sp = holdbufp; | |
1828 | 1826 | modified = 0; |
1829 | 1827 | } else if (hp < history || hp > histptr) { |
1830 | 1828 | x_e_putc2(7); |
@@ -1835,7 +1833,7 @@ x_load_hist(char **hp) | ||
1835 | 1833 | x_histp = hp; |
1836 | 1834 | oldsize = x_size_str(xbuf); |
1837 | 1835 | if (modified) |
1838 | - strlcpy(holdbuf, xbuf, sizeof(holdbuf)); | |
1836 | + strlcpy(holdbufp, xbuf, LINE); | |
1839 | 1837 | strlcpy(xbuf, sp, xend - xbuf); |
1840 | 1838 | xbp = xbuf; |
1841 | 1839 | xep = xcp = xbuf + strlen(xbuf); |
@@ -2080,7 +2078,7 @@ x_cls(int c MKSH_A_UNUSED) | ||
2080 | 2078 | static void |
2081 | 2079 | x_redraw(int limit) |
2082 | 2080 | { |
2083 | - int i, j, x_trunc = 0; | |
2081 | + int i, j; | |
2084 | 2082 | char *cp; |
2085 | 2083 | |
2086 | 2084 | x_adj_ok = false; |
@@ -2090,19 +2088,11 @@ x_redraw(int limit) | ||
2090 | 2088 | x_e_putc2('\r'); |
2091 | 2089 | x_flush(); |
2092 | 2090 | if (xbp == xbuf) { |
2093 | - x_col = promptlen(prompt); | |
2094 | - if (x_col >= xx_cols) | |
2095 | - x_trunc = (x_col / xx_cols) * xx_cols; | |
2096 | - if (prompt_redraw) | |
2097 | - pprompt(prompt, x_trunc); | |
2098 | - } | |
2099 | - if (x_col >= xx_cols) | |
2100 | - x_col %= xx_cols; | |
2101 | - x_displen = xx_cols - 2 - x_col; | |
2102 | - if (x_displen < 1) { | |
2103 | - x_col = 0; | |
2104 | - x_displen = xx_cols - 2; | |
2091 | + if (prompt_trunc != -1) | |
2092 | + pprompt(prompt, prompt_trunc); | |
2093 | + x_col = pwidth; | |
2105 | 2094 | } |
2095 | + x_displen = xx_cols - 2 - x_col; | |
2106 | 2096 | xlp_valid = false; |
2107 | 2097 | x_zots(xbp); |
2108 | 2098 | if (xbp != xbuf || xep > xlp) |
@@ -2816,16 +2806,42 @@ do_complete( | ||
2816 | 2806 | static void |
2817 | 2807 | x_adjust(void) |
2818 | 2808 | { |
2819 | - /* flag the fact that we were called. */ | |
2809 | + int col_left, n; | |
2810 | + | |
2811 | + /* flag the fact that we were called */ | |
2820 | 2812 | x_adj_done++; |
2813 | + | |
2821 | 2814 | /* |
2822 | - * we had a problem if the prompt length > xx_cols / 2 | |
2815 | + * calculate the amount of columns we need to "go back" | |
2816 | + * from xcp to set xbp to (but never < xbuf) to 2/3 of | |
2817 | + * the display width; take care of pwidth though | |
2823 | 2818 | */ |
2824 | - if ((xbp = xcp - (x_displen / 2)) < xbuf) | |
2825 | - xbp = xbuf; | |
2826 | - if (UTFMODE) | |
2827 | - while ((xbp > xbuf) && ((*xbp & 0xC0) == 0x80)) | |
2828 | - --xbp; | |
2819 | + if ((col_left = xx_cols * 2 / 3) < MIN_EDIT_SPACE) { | |
2820 | + /* | |
2821 | + * cowardly refuse to do anything | |
2822 | + * if the available space is too small; | |
2823 | + * fall back to dumb pdksh code | |
2824 | + */ | |
2825 | + if ((xbp = xcp - (x_displen / 2)) < xbuf) | |
2826 | + xbp = xbuf; | |
2827 | + /* elide UTF-8 fixup as penalty */ | |
2828 | + goto x_adjust_out; | |
2829 | + } | |
2830 | + | |
2831 | + /* fix up xbp to just past a character end first */ | |
2832 | + xbp = xcp >= xep ? xep : x_bs0(xcp, xbuf); | |
2833 | + /* walk backwards */ | |
2834 | + while (xbp > xbuf && col_left > 0) { | |
2835 | + xbp = x_bs0(xbp - 1, xbuf); | |
2836 | + col_left -= (n = x_size2(xbp, NULL)); | |
2837 | + } | |
2838 | + /* check if we hit the prompt */ | |
2839 | + if (xbp == xbuf && xcp != xbuf && col_left >= 0 && col_left < pwidth) { | |
2840 | + /* so we did; force scrolling occurs */ | |
2841 | + xbp += utf_ptradj(xbp); | |
2842 | + } | |
2843 | + | |
2844 | + x_adjust_out: | |
2829 | 2845 | xlp_valid = false; |
2830 | 2846 | x_redraw(xx_cols); |
2831 | 2847 | x_flush(); |
@@ -3345,9 +3361,9 @@ static void yank_range(int, int); | ||
3345 | 3361 | static int bracktype(int); |
3346 | 3362 | static void save_cbuf(void); |
3347 | 3363 | static void restore_cbuf(void); |
3348 | -static int putbuf(const char *, ssize_t, int); | |
3364 | +static int putbuf(const char *, ssize_t, bool); | |
3349 | 3365 | static void del_range(int, int); |
3350 | -static int findch(int, int, int, int); | |
3366 | +static int findch(int, int, bool, bool); | |
3351 | 3367 | static int forwword(int); |
3352 | 3368 | static int backword(int); |
3353 | 3369 | static int endword(int); |
@@ -3411,11 +3427,11 @@ static const unsigned char classify[128] = { | ||
3411 | 3427 | /* 8 @ A B C D E F G */ |
3412 | 3428 | vC|vX, vC, vM, vC, vC, vM, vM|vX, vC|vU|vZ, |
3413 | 3429 | /* 9 H I J K L M N O */ |
3414 | - 0, vC, 0, 0, 0, 0, vC|vU, 0, | |
3430 | + 0, vC, 0, 0, 0, 0, vC|vU, vU, | |
3415 | 3431 | /* A P Q R S T U V W */ |
3416 | 3432 | vC, 0, vC, vC, vM|vX, vC, 0, vM, |
3417 | 3433 | /* B X Y Z [ \ ] ^ _ */ |
3418 | - vC, vC|vU, 0, 0, vC|vZ, 0, vM, vC|vZ, | |
3434 | + vC, vC|vU, 0, vU, vC|vZ, 0, vM, vC|vZ, | |
3419 | 3435 | /* C ` a b c d e f g */ |
3420 | 3436 | 0, vC, vM, vE, vE, vM, vM|vX, vC|vZ, |
3421 | 3437 | /* D h i j k l m n o */ |
@@ -3443,25 +3459,24 @@ static const unsigned char classify[128] = { | ||
3443 | 3459 | #define VLIT 8 /* ^V */ |
3444 | 3460 | #define VSEARCH 9 /* /, ? */ |
3445 | 3461 | #define VVERSION 10 /* <ESC> ^V */ |
3446 | - | |
3447 | -static char undocbuf[LINE]; | |
3462 | +#define VPREFIX2 11 /* ^[[ and ^[O in insert mode */ | |
3448 | 3463 | |
3449 | 3464 | static struct edstate *save_edstate(struct edstate *old); |
3450 | 3465 | static void restore_edstate(struct edstate *old, struct edstate *news); |
3451 | 3466 | static void free_edstate(struct edstate *old); |
3452 | 3467 | |
3453 | 3468 | static struct edstate ebuf; |
3454 | -static struct edstate undobuf = { undocbuf, 0, LINE, 0, 0 }; | |
3469 | +static struct edstate undobuf; | |
3455 | 3470 | |
3456 | -static struct edstate *es; /* current editor state */ | |
3471 | +static struct edstate *es; /* current editor state */ | |
3457 | 3472 | static struct edstate *undo; |
3458 | 3473 | |
3459 | -static char ibuf[LINE]; /* input buffer */ | |
3460 | -static int first_insert; /* set when starting in insert mode */ | |
3474 | +static char *ibuf; /* input buffer */ | |
3475 | +static bool first_insert; /* set when starting in insert mode */ | |
3461 | 3476 | static int saved_inslen; /* saved inslen for first insert */ |
3462 | 3477 | static int inslen; /* length of input buffer */ |
3463 | 3478 | static int srchlen; /* length of current search pattern */ |
3464 | -static char ybuf[LINE]; /* yank buffer */ | |
3479 | +static char *ybuf; /* yank buffer */ | |
3465 | 3480 | static int yanklen; /* length of yank buffer */ |
3466 | 3481 | static int fsavecmd = ' '; /* last find command */ |
3467 | 3482 | static int fsavech; /* character to find */ |
@@ -3469,7 +3484,7 @@ static char lastcmd[MAXVICMD]; /* last non-move command */ | ||
3469 | 3484 | static int lastac; /* argcnt for lastcmd */ |
3470 | 3485 | static int lastsearch = ' '; /* last search command */ |
3471 | 3486 | static char srchpat[SRCHLEN]; /* last search pattern */ |
3472 | -static int insert; /* non-zero in insert mode */ | |
3487 | +static int insert; /* <>0 in insert mode */ | |
3473 | 3488 | static int hnum; /* position in history */ |
3474 | 3489 | static int ohnum; /* history line copied (after mod) */ |
3475 | 3490 | static int hlast; /* 1 past last position in history */ |
@@ -3495,7 +3510,7 @@ static enum expand_mode { | ||
3495 | 3510 | } expanded; |
3496 | 3511 | |
3497 | 3512 | static int |
3498 | -x_vi(char *buf, size_t len) | |
3513 | +x_vi(char *buf) | |
3499 | 3514 | { |
3500 | 3515 | int c; |
3501 | 3516 |
@@ -3503,36 +3518,29 @@ x_vi(char *buf, size_t len) | ||
3503 | 3518 | ohnum = hnum = hlast = histnum(-1) + 1; |
3504 | 3519 | insert = INSERT; |
3505 | 3520 | saved_inslen = inslen; |
3506 | - first_insert = 1; | |
3521 | + first_insert = true; | |
3507 | 3522 | inslen = 0; |
3508 | 3523 | vi_macro_reset(); |
3509 | 3524 | |
3525 | + ebuf.cbuf = buf; | |
3526 | + if (undobuf.cbuf == NULL) { | |
3527 | + ibuf = alloc(LINE, AEDIT); | |
3528 | + ybuf = alloc(LINE, AEDIT); | |
3529 | + undobuf.cbuf = alloc(LINE, AEDIT); | |
3530 | + } | |
3531 | + undobuf.cbufsize = ebuf.cbufsize = LINE; | |
3532 | + undobuf.linelen = ebuf.linelen = 0; | |
3533 | + undobuf.cursor = ebuf.cursor = 0; | |
3534 | + undobuf.winleft = ebuf.winleft = 0; | |
3510 | 3535 | es = &ebuf; |
3511 | - es->cbuf = buf; | |
3512 | 3536 | undo = &undobuf; |
3513 | - undo->cbufsize = es->cbufsize = len > LINE ? LINE : len; | |
3514 | - | |
3515 | - es->linelen = undo->linelen = 0; | |
3516 | - es->cursor = undo->cursor = 0; | |
3517 | - es->winleft = undo->winleft = 0; | |
3518 | 3537 | |
3519 | - cur_col = promptlen(prompt); | |
3520 | - prompt_trunc = (cur_col / x_cols) * x_cols; | |
3521 | - cur_col -= prompt_trunc; | |
3522 | - | |
3523 | - pprompt(prompt, 0); | |
3524 | - if ((mksh_uari_t)cur_col > (mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE) { | |
3525 | - prompt_redraw = false; | |
3526 | - cur_col = 0; | |
3527 | - x_putc('\n'); | |
3528 | - } else | |
3529 | - prompt_redraw = true; | |
3530 | - pwidth = cur_col; | |
3538 | + x_init_prompt(); | |
3539 | + x_col = pwidth; | |
3531 | 3540 | |
3532 | - if (!wbuf_len || wbuf_len != x_cols - 3) { | |
3533 | - wbuf_len = x_cols - 3; | |
3534 | - wbuf[0] = aresize(wbuf[0], wbuf_len, APERM); | |
3535 | - wbuf[1] = aresize(wbuf[1], wbuf_len, APERM); | |
3541 | + if (wbuf_len != x_cols - 3 && ((wbuf_len = x_cols - 3))) { | |
3542 | + wbuf[0] = aresize(wbuf[0], wbuf_len, AEDIT); | |
3543 | + wbuf[1] = aresize(wbuf[1], wbuf_len, AEDIT); | |
3536 | 3544 | } |
3537 | 3545 | if (wbuf_len) { |
3538 | 3546 | memset(wbuf[0], ' ', wbuf_len); |
@@ -3589,11 +3597,11 @@ x_vi(char *buf, size_t len) | ||
3589 | 3597 | x_putc('\n'); |
3590 | 3598 | x_flush(); |
3591 | 3599 | |
3592 | - if (c == -1 || (ssize_t)len <= es->linelen) | |
3600 | + if (c == -1 || (ssize_t)LINE <= es->linelen) | |
3593 | 3601 | return (-1); |
3594 | 3602 | |
3595 | 3603 | if (es->cbuf != buf) |
3596 | - memmove(buf, es->cbuf, es->linelen); | |
3604 | + memcpy(buf, es->cbuf, es->linelen); | |
3597 | 3605 | |
3598 | 3606 | buf[es->linelen++] = '\n'; |
3599 | 3607 |
@@ -3644,10 +3652,8 @@ vi_hook(int ch) | ||
3644 | 3652 | save_cbuf(); |
3645 | 3653 | es->cursor = 0; |
3646 | 3654 | es->linelen = 0; |
3647 | - if (ch == '/') { | |
3648 | - if (putbuf("/", 1, 0) != 0) | |
3649 | - return (-1); | |
3650 | - } else if (putbuf("?", 1, 0) != 0) | |
3655 | + if (putbuf(ch == '/' ? "/" : "?", 1, | |
3656 | + false) != 0) | |
3651 | 3657 | return (-1); |
3652 | 3658 | refresh(0); |
3653 | 3659 | } |
@@ -3656,7 +3662,7 @@ vi_hook(int ch) | ||
3656 | 3662 | es->cursor = 0; |
3657 | 3663 | es->linelen = 0; |
3658 | 3664 | putbuf(KSH_VERSION, |
3659 | - strlen(KSH_VERSION), 0); | |
3665 | + strlen(KSH_VERSION), false); | |
3660 | 3666 | refresh(0); |
3661 | 3667 | } |
3662 | 3668 | } |
@@ -3805,10 +3811,35 @@ vi_hook(int ch) | ||
3805 | 3811 | return (0); |
3806 | 3812 | } |
3807 | 3813 | break; |
3814 | + | |
3815 | + case VPREFIX2: | |
3816 | + state = VFAIL; | |
3817 | + switch (ch) { | |
3818 | + case 'A': | |
3819 | + /* the cursor may not be at the BOL */ | |
3820 | + if (!es->cursor) | |
3821 | + break; | |
3822 | + /* nor further in the line than we can search for */ | |
3823 | + if ((size_t)es->cursor >= sizeof(srchpat) - 1) | |
3824 | + es->cursor = sizeof(srchpat) - 2; | |
3825 | + /* anchor the search pattern */ | |
3826 | + srchpat[0] = '^'; | |
3827 | + /* take the current line up to the cursor */ | |
3828 | + memmove(srchpat + 1, es->cbuf, es->cursor); | |
3829 | + srchpat[es->cursor + 1] = '\0'; | |
3830 | + /* set a magic flag */ | |
3831 | + argc1 = 2 + (int)es->cursor; | |
3832 | + /* and emulate a backwards history search */ | |
3833 | + lastsearch = '/'; | |
3834 | + *curcmd = 'n'; | |
3835 | + goto pseudo_VCMD; | |
3836 | + } | |
3837 | + break; | |
3808 | 3838 | } |
3809 | 3839 | |
3810 | 3840 | switch (state) { |
3811 | 3841 | case VCMD: |
3842 | + pseudo_VCMD: | |
3812 | 3843 | state = VNORMAL; |
3813 | 3844 | switch (vi_cmd(argc1, curcmd)) { |
3814 | 3845 | case -1: |
@@ -3962,7 +3993,7 @@ vi_insert(int ch) | ||
3962 | 3993 | case Ctrl('['): |
3963 | 3994 | expanded = NONE; |
3964 | 3995 | if (first_insert) { |
3965 | - first_insert = 0; | |
3996 | + first_insert = false; | |
3966 | 3997 | if (inslen == 0) { |
3967 | 3998 | inslen = saved_inslen; |
3968 | 3999 | return (redo_insert(0)); |
@@ -4074,12 +4105,12 @@ vi_cmd(int argcnt, const char *cmd) | ||
4074 | 4105 | * at this point, it's fairly reasonable that |
4075 | 4106 | * nlen + olen + 2 doesn't overflow |
4076 | 4107 | */ |
4077 | - nbuf = alloc(nlen + 1 + olen, APERM); | |
4108 | + nbuf = alloc(nlen + 1 + olen, AEDIT); | |
4078 | 4109 | memcpy(nbuf, ap->val.s, nlen); |
4079 | 4110 | nbuf[nlen++] = cmd[1]; |
4080 | 4111 | if (macro.p) { |
4081 | 4112 | memcpy(nbuf + nlen, macro.p, olen); |
4082 | - afree(macro.buf, APERM); | |
4113 | + afree(macro.buf, AEDIT); | |
4083 | 4114 | nlen += olen; |
4084 | 4115 | } else { |
4085 | 4116 | nbuf[nlen++] = '\0'; |
@@ -4164,7 +4195,8 @@ vi_cmd(int argcnt, const char *cmd) | ||
4164 | 4195 | hnum = hlast; |
4165 | 4196 | if (es->linelen != 0) |
4166 | 4197 | es->cursor++; |
4167 | - while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0) | |
4198 | + while (putbuf(ybuf, yanklen, false) == 0 && | |
4199 | + --argcnt > 0) | |
4168 | 4200 | ; |
4169 | 4201 | if (es->cursor != 0) |
4170 | 4202 | es->cursor--; |
@@ -4176,7 +4208,8 @@ vi_cmd(int argcnt, const char *cmd) | ||
4176 | 4208 | modified = 1; |
4177 | 4209 | hnum = hlast; |
4178 | 4210 | any = 0; |
4179 | - while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0) | |
4211 | + while (putbuf(ybuf, yanklen, false) == 0 && | |
4212 | + --argcnt > 0) | |
4180 | 4213 | any = 1; |
4181 | 4214 | if (any && es->cursor != 0) |
4182 | 4215 | es->cursor--; |
@@ -4378,6 +4411,11 @@ vi_cmd(int argcnt, const char *cmd) | ||
4378 | 4411 | hnum = c2; |
4379 | 4412 | ohnum = hnum; |
4380 | 4413 | } |
4414 | + if (argcnt >= 2) { | |
4415 | + /* flag from cursor-up command */ | |
4416 | + es->cursor = argcnt - 2; | |
4417 | + return (0); | |
4418 | + } | |
4381 | 4419 | break; |
4382 | 4420 | case '_': |
4383 | 4421 | { |
@@ -4422,8 +4460,8 @@ vi_cmd(int argcnt, const char *cmd) | ||
4422 | 4460 | argcnt++; |
4423 | 4461 | p++; |
4424 | 4462 | } |
4425 | - if (putbuf(" ", 1, 0) != 0 || | |
4426 | - putbuf(sp, argcnt, 0) != 0) { | |
4463 | + if (putbuf(" ", 1, false) != 0 || | |
4464 | + putbuf(sp, argcnt, false) != 0) { | |
4427 | 4465 | if (es->cursor != 0) |
4428 | 4466 | es->cursor--; |
4429 | 4467 | return (-1); |
@@ -4498,6 +4536,16 @@ vi_cmd(int argcnt, const char *cmd) | ||
4498 | 4536 | case Ctrl('x'): |
4499 | 4537 | expand_word(1); |
4500 | 4538 | break; |
4539 | + | |
4540 | + | |
4541 | + /* mksh: cursor movement */ | |
4542 | + case '[': | |
4543 | + case 'O': | |
4544 | + state = VPREFIX2; | |
4545 | + if (es->linelen != 0) | |
4546 | + es->cursor++; | |
4547 | + insert = INSERT; | |
4548 | + return (0); | |
4501 | 4549 | } |
4502 | 4550 | if (insert == 0 && es->cursor != 0 && es->cursor >= es->linelen) |
4503 | 4551 | es->cursor--; |
@@ -4556,7 +4604,8 @@ domove(int argcnt, const char *cmd, int sub) | ||
4556 | 4604 | t = fsavecmd > 'a'; |
4557 | 4605 | if (*cmd == ',') |
4558 | 4606 | t = !t; |
4559 | - if ((ncursor = findch(fsavech, argcnt, t, i)) < 0) | |
4607 | + if ((ncursor = findch(fsavech, argcnt, tobool(t), | |
4608 | + tobool(i))) < 0) | |
4560 | 4609 | return (-1); |
4561 | 4610 | if (sub && t) |
4562 | 4611 | ncursor++; |
@@ -4656,7 +4705,7 @@ static int | ||
4656 | 4705 | redo_insert(int count) |
4657 | 4706 | { |
4658 | 4707 | while (count-- > 0) |
4659 | - if (putbuf(ibuf, inslen, insert == REPLACE) != 0) | |
4708 | + if (putbuf(ibuf, inslen, tobool(insert == REPLACE)) != 0) | |
4660 | 4709 | return (-1); |
4661 | 4710 | if (es->cursor > 0) |
4662 | 4711 | es->cursor--; |
@@ -4707,9 +4756,9 @@ bracktype(int ch) | ||
4707 | 4756 | static void |
4708 | 4757 | save_cbuf(void) |
4709 | 4758 | { |
4710 | - memmove(holdbuf, es->cbuf, es->linelen); | |
4759 | + memmove(holdbufp, es->cbuf, es->linelen); | |
4711 | 4760 | holdlen = es->linelen; |
4712 | - holdbuf[holdlen] = '\0'; | |
4761 | + holdbufp[holdlen] = '\0'; | |
4713 | 4762 | } |
4714 | 4763 | |
4715 | 4764 | static void |
@@ -4717,7 +4766,7 @@ restore_cbuf(void) | ||
4717 | 4766 | { |
4718 | 4767 | es->cursor = 0; |
4719 | 4768 | es->linelen = holdlen; |
4720 | - memmove(es->cbuf, holdbuf, holdlen); | |
4769 | + memmove(es->cbuf, holdbufp, holdlen); | |
4721 | 4770 | } |
4722 | 4771 | |
4723 | 4772 | /* return a new edstate */ |
@@ -4726,8 +4775,8 @@ save_edstate(struct edstate *old) | ||
4726 | 4775 | { |
4727 | 4776 | struct edstate *news; |
4728 | 4777 | |
4729 | - news = alloc(sizeof(struct edstate), APERM); | |
4730 | - news->cbuf = alloc(old->cbufsize, APERM); | |
4778 | + news = alloc(sizeof(struct edstate), AEDIT); | |
4779 | + news->cbuf = alloc(old->cbufsize, AEDIT); | |
4731 | 4780 | memcpy(news->cbuf, old->cbuf, old->linelen); |
4732 | 4781 | news->cbufsize = old->cbufsize; |
4733 | 4782 | news->linelen = old->linelen; |
@@ -4749,8 +4798,8 @@ restore_edstate(struct edstate *news, struct edstate *old) | ||
4749 | 4798 | static void |
4750 | 4799 | free_edstate(struct edstate *old) |
4751 | 4800 | { |
4752 | - afree(old->cbuf, APERM); | |
4753 | - afree(old, APERM); | |
4801 | + afree(old->cbuf, AEDIT); | |
4802 | + afree(old, AEDIT); | |
4754 | 4803 | } |
4755 | 4804 | |
4756 | 4805 | /* |
@@ -4759,11 +4808,11 @@ free_edstate(struct edstate *old) | ||
4759 | 4808 | static int |
4760 | 4809 | x_vi_putbuf(const char *s, size_t len) |
4761 | 4810 | { |
4762 | - return (putbuf(s, len, 0)); | |
4811 | + return (putbuf(s, len, false)); | |
4763 | 4812 | } |
4764 | 4813 | |
4765 | 4814 | static int |
4766 | -putbuf(const char *buf, ssize_t len, int repl) | |
4815 | +putbuf(const char *buf, ssize_t len, bool repl) | |
4767 | 4816 | { |
4768 | 4817 | if (len == 0) |
4769 | 4818 | return (0); |
@@ -4793,7 +4842,7 @@ del_range(int a, int b) | ||
4793 | 4842 | } |
4794 | 4843 | |
4795 | 4844 | static int |
4796 | -findch(int ch, int cnt, int forw, int incl) | |
4845 | +findch(int ch, int cnt, bool forw, bool incl) | |
4797 | 4846 | { |
4798 | 4847 | int ncursor; |
4799 | 4848 |
@@ -4989,8 +5038,8 @@ grabsearch(int save, int start, int fwd, const char *pat) | ||
4989 | 5038 | start--; |
4990 | 5039 | anchored = *pat == '^' ? (++pat, 1) : 0; |
4991 | 5040 | if ((hist = findhist(start, fwd, pat, anchored)) < 0) { |
4992 | - /* (start != 0 && fwd && match(holdbuf, pat) >= 0) */ | |
4993 | - if (start != 0 && fwd && strcmp(holdbuf, pat) >= 0) { | |
5041 | + /* (start != 0 && fwd && match(holdbufp, pat) >= 0) */ | |
5042 | + if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) { | |
4994 | 5043 | restore_cbuf(); |
4995 | 5044 | return (0); |
4996 | 5045 | } else |
@@ -5016,9 +5065,9 @@ redraw_line(bool newl) | ||
5016 | 5065 | x_putc('\r'); |
5017 | 5066 | x_putc('\n'); |
5018 | 5067 | } |
5019 | - if (prompt_redraw) | |
5068 | + if (prompt_trunc != -1) | |
5020 | 5069 | pprompt(prompt, prompt_trunc); |
5021 | - cur_col = pwidth; | |
5070 | + x_col = pwidth; | |
5022 | 5071 | morec = ' '; |
5023 | 5072 | } |
5024 | 5073 |
@@ -5136,10 +5185,10 @@ display(char *wb1, char *wb2, int leftside) | ||
5136 | 5185 | twb2 = wb2; |
5137 | 5186 | while (cnt--) { |
5138 | 5187 | if (*twb1 != *twb2) { |
5139 | - if (cur_col != col) | |
5188 | + if (x_col != col) | |
5140 | 5189 | ed_mov_opt(col, wb1); |
5141 | 5190 | x_putc(*twb1); |
5142 | - cur_col++; | |
5191 | + x_col++; | |
5143 | 5192 | } |
5144 | 5193 | twb1++; |
5145 | 5194 | twb2++; |
@@ -5160,34 +5209,34 @@ display(char *wb1, char *wb2, int leftside) | ||
5160 | 5209 | if (mc != morec) { |
5161 | 5210 | ed_mov_opt(pwidth + winwidth + 1, wb1); |
5162 | 5211 | x_putc(mc); |
5163 | - cur_col++; | |
5212 | + x_col++; | |
5164 | 5213 | morec = mc; |
5165 | 5214 | } |
5166 | - if (cur_col != ncol) | |
5215 | + if (x_col != ncol) | |
5167 | 5216 | ed_mov_opt(ncol, wb1); |
5168 | 5217 | } |
5169 | 5218 | |
5170 | 5219 | static void |
5171 | 5220 | ed_mov_opt(int col, char *wb) |
5172 | 5221 | { |
5173 | - if (col < cur_col) { | |
5174 | - if (col + 1 < cur_col - col) { | |
5222 | + if (col < x_col) { | |
5223 | + if (col + 1 < x_col - col) { | |
5175 | 5224 | x_putc('\r'); |
5176 | - if (prompt_redraw) | |
5225 | + if (prompt_trunc != -1) | |
5177 | 5226 | pprompt(prompt, prompt_trunc); |
5178 | - cur_col = pwidth; | |
5179 | - while (cur_col++ < col) | |
5227 | + x_col = pwidth; | |
5228 | + while (x_col++ < col) | |
5180 | 5229 | x_putcf(*wb++); |
5181 | 5230 | } else { |
5182 | - while (cur_col-- > col) | |
5231 | + while (x_col-- > col) | |
5183 | 5232 | x_putc('\b'); |
5184 | 5233 | } |
5185 | 5234 | } else { |
5186 | - wb = &wb[cur_col - pwidth]; | |
5187 | - while (cur_col++ < col) | |
5235 | + wb = &wb[x_col - pwidth]; | |
5236 | + while (x_col++ < col) | |
5188 | 5237 | x_putcf(*wb++); |
5189 | 5238 | } |
5190 | - cur_col = col; | |
5239 | + x_col = col; | |
5191 | 5240 | } |
5192 | 5241 | |
5193 | 5242 |
@@ -5229,7 +5278,7 @@ expand_word(int cmd) | ||
5229 | 5278 | rval = -1; |
5230 | 5279 | break; |
5231 | 5280 | } |
5232 | - if (++i < nwords && putbuf(" ", 1, 0) != 0) { | |
5281 | + if (++i < nwords && putbuf(" ", 1, false) != 0) { | |
5233 | 5282 | rval = -1; |
5234 | 5283 | break; |
5235 | 5284 | } |
@@ -5347,7 +5396,7 @@ complete_word(int cmd, int count) | ||
5347 | 5396 | */ |
5348 | 5397 | if (match_len > 0 && match[match_len - 1] != '/' && |
5349 | 5398 | !(flags & XCF_IS_NOSPACE)) |
5350 | - rval = putbuf(" ", 1, 0); | |
5399 | + rval = putbuf(" ", 1, false); | |
5351 | 5400 | } |
5352 | 5401 | x_free_words(nwords, words); |
5353 | 5402 |
@@ -5404,7 +5453,7 @@ static void | ||
5404 | 5453 | vi_macro_reset(void) |
5405 | 5454 | { |
5406 | 5455 | if (macro.p) { |
5407 | - afree(macro.buf, APERM); | |
5456 | + afree(macro.buf, AEDIT); | |
5408 | 5457 | memset((char *)¯o, 0, sizeof(macro)); |
5409 | 5458 | } |
5410 | 5459 | } |
@@ -5425,8 +5474,11 @@ x_init(void) | ||
5425 | 5474 | /* ^W */ |
5426 | 5475 | edchars.werase = 027; |
5427 | 5476 | |
5428 | - /* initialise Emacs command line editing mode */ | |
5477 | + /* command line editing specific memory allocation */ | |
5429 | 5478 | ainit(AEDIT); |
5479 | + holdbufp = alloc(LINE, AEDIT); | |
5480 | + | |
5481 | + /* initialise Emacs command line editing mode */ | |
5430 | 5482 | x_nextcmd = -1; |
5431 | 5483 | |
5432 | 5484 | x_tab = alloc2(X_NTABS, sizeof(*x_tab), AEDIT); |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: eval.c,v 1.37 2011/10/11 14:32:43 otto Exp $ */ | |
1 | +/* $OpenBSD: eval.c,v 1.39 2013/07/01 17:25:27 jca Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
@@ -23,7 +23,7 @@ | ||
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
26 | -__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.136 2013/02/10 23:43:59 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.142 2013/07/24 18:03:57 tg Exp $"); | |
27 | 27 | |
28 | 28 | /* |
29 | 29 | * string expansion |
@@ -33,15 +33,21 @@ __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.136 2013/02/10 23:43:59 tg Exp $"); | ||
33 | 33 | */ |
34 | 34 | |
35 | 35 | /* expansion generator state */ |
36 | -typedef struct Expand { | |
37 | - /* int type; */ /* see expand() */ | |
38 | - const char *str; /* string */ | |
36 | +typedef struct { | |
37 | + /* not including an "int type;" member, see expand() */ | |
38 | + /* string */ | |
39 | + const char *str; | |
40 | + /* source */ | |
39 | 41 | union { |
40 | - const char **strv; /* string[] */ | |
41 | - struct shf *shf; /* file */ | |
42 | - } u; /* source */ | |
43 | - struct tbl *var; /* variable in ${var..} */ | |
44 | - bool split; /* split "$@" / call waitlast $() */ | |
42 | + /* string[] */ | |
43 | + const char **strv; | |
44 | + /* file */ | |
45 | + struct shf *shf; | |
46 | + } u; | |
47 | + /* variable in ${var...} */ | |
48 | + struct tbl *var; | |
49 | + /* split "$@" / call waitlast in $() */ | |
50 | + bool split; | |
45 | 51 | } Expand; |
46 | 52 | |
47 | 53 | #define XBASE 0 /* scanning original */ |
@@ -59,7 +65,7 @@ typedef struct Expand { | ||
59 | 65 | |
60 | 66 | static int varsub(Expand *, const char *, const char *, int *, int *); |
61 | 67 | static int comsub(Expand *, const char *, int); |
62 | -static void funsub(struct op *); | |
68 | +static char *valsub(struct op *, Area *); | |
63 | 69 | static char *trimsub(char *, char *, int); |
64 | 70 | static void glob(char *, XPtrV *, bool); |
65 | 71 | static void globit(XString *, char **, char *, XPtrV *, int); |
@@ -198,33 +204,46 @@ typedef struct SubType { | ||
198 | 204 | } SubType; |
199 | 205 | |
200 | 206 | void |
201 | -expand(const char *cp, /* input word */ | |
202 | - XPtrV *wp, /* output words */ | |
203 | - int f) /* DO* flags */ | |
207 | +expand( | |
208 | + /* input word */ | |
209 | + const char *ccp, | |
210 | + /* output words */ | |
211 | + XPtrV *wp, | |
212 | + /* DO* flags */ | |
213 | + int f) | |
204 | 214 | { |
205 | 215 | int c = 0; |
206 | - int type; /* expansion type */ | |
207 | - int quote = 0; /* quoted */ | |
208 | - XString ds; /* destination string */ | |
209 | - char *dp; /* destination */ | |
210 | - const char *sp; /* source */ | |
211 | - int fdo, word; /* second pass flags; have word */ | |
212 | - int doblank; /* field splitting of parameter/command subst */ | |
216 | + /* expansion type */ | |
217 | + int type; | |
218 | + /* quoted */ | |
219 | + int quote = 0; | |
220 | + /* destination string and live pointer */ | |
221 | + XString ds; | |
222 | + char *dp; | |
223 | + /* source */ | |
224 | + const char *sp; | |
225 | + /* second pass flags */ | |
226 | + int fdo; | |
227 | + /* have word */ | |
228 | + int word; | |
229 | + /* field splitting of parameter/command substitution */ | |
230 | + int doblank; | |
231 | + /* expansion variables */ | |
213 | 232 | Expand x = { |
214 | - /* expansion variables */ | |
215 | 233 | NULL, { NULL }, NULL, 0 |
216 | 234 | }; |
217 | 235 | SubType st_head, *st; |
218 | - /* For trailing newlines in COMSUB */ | |
236 | + /* record number of trailing newlines in COMSUB */ | |
219 | 237 | int newlines = 0; |
220 | 238 | bool saw_eq, make_magic; |
221 | 239 | int tilde_ok; |
222 | 240 | size_t len; |
241 | + char *cp; | |
223 | 242 | |
224 | - if (cp == NULL) | |
243 | + if (ccp == NULL) | |
225 | 244 | internal_errorf("expand(NULL)"); |
226 | 245 | /* for alias, readonly, set, typeset commands */ |
227 | - if ((f & DOVACHECK) && is_wdvarassign(cp)) { | |
246 | + if ((f & DOVACHECK) && is_wdvarassign(ccp)) { | |
228 | 247 | f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE); |
229 | 248 | f |= DOASNTILDE; |
230 | 249 | } |
@@ -238,7 +257,7 @@ expand(const char *cp, /* input word */ | ||
238 | 257 | /* init destination string */ |
239 | 258 | Xinit(ds, dp, 128, ATEMP); |
240 | 259 | type = XBASE; |
241 | - sp = cp; | |
260 | + sp = ccp; | |
242 | 261 | fdo = 0; |
243 | 262 | saw_eq = false; |
244 | 263 | /* must be 1/0 */ |
@@ -279,27 +298,26 @@ expand(const char *cp, /* input word */ | ||
279 | 298 | continue; |
280 | 299 | case COMSUB: |
281 | 300 | case FUNSUB: |
301 | + case VALSUB: | |
282 | 302 | tilde_ok = 0; |
283 | 303 | if (f & DONTRUNCOMMAND) { |
284 | 304 | word = IFS_WORD; |
285 | 305 | *dp++ = '$'; |
286 | - if (c == FUNSUB) { | |
287 | - *dp++ = '{'; | |
288 | - *dp++ = ' '; | |
289 | - } else | |
290 | - *dp++ = '('; | |
306 | + *dp++ = c == COMSUB ? '(' : '{'; | |
307 | + if (c != COMSUB) | |
308 | + *dp++ = c == FUNSUB ? ' ' : '|'; | |
291 | 309 | while (*sp != '\0') { |
292 | 310 | Xcheck(ds, dp); |
293 | 311 | *dp++ = *sp++; |
294 | 312 | } |
295 | - if (c == FUNSUB) { | |
313 | + if (c != COMSUB) { | |
296 | 314 | *dp++ = ';'; |
297 | 315 | *dp++ = '}'; |
298 | 316 | } else |
299 | 317 | *dp++ = ')'; |
300 | 318 | } else { |
301 | 319 | type = comsub(&x, sp, c); |
302 | - if (type == XCOM && (f&DOBLANK)) | |
320 | + if (type != XBASE && (f & DOBLANK)) | |
303 | 321 | doblank++; |
304 | 322 | sp = strnul(sp) + 1; |
305 | 323 | newlines = 0; |
@@ -317,7 +335,6 @@ expand(const char *cp, /* input word */ | ||
317 | 335 | *dp++ = ')'; *dp++ = ')'; |
318 | 336 | } else { |
319 | 337 | struct tbl v; |
320 | - char *p; | |
321 | 338 | |
322 | 339 | v.flag = DEFINED|ISSET|INTEGER; |
323 | 340 | /* not default */ |
@@ -326,9 +343,10 @@ expand(const char *cp, /* input word */ | ||
326 | 343 | v_evaluate(&v, substitute(sp, 0), |
327 | 344 | KSH_UNWIND_ERROR, true); |
328 | 345 | sp = strnul(sp) + 1; |
329 | - for (p = str_val(&v); *p; ) { | |
346 | + cp = str_val(&v); | |
347 | + while (*cp) { | |
330 | 348 | Xcheck(ds, dp); |
331 | - *dp++ = *p++; | |
349 | + *dp++ = *cp++; | |
332 | 350 | } |
333 | 351 | } |
334 | 352 | continue; |
@@ -394,8 +412,7 @@ expand(const char *cp, /* input word */ | ||
394 | 412 | if (stype) |
395 | 413 | sp += slen; |
396 | 414 | switch (stype & 0x17F) { |
397 | - case 0x100 | '#': | |
398 | - { | |
415 | + case 0x100 | '#': { | |
399 | 416 | char *beg, *end; |
400 | 417 | mksh_ari_t seed; |
401 | 418 | register uint32_t h; |
@@ -416,8 +433,7 @@ expand(const char *cp, /* input word */ | ||
416 | 433 | (unsigned int)h); |
417 | 434 | break; |
418 | 435 | } |
419 | - case 0x100 | 'Q': | |
420 | - { | |
436 | + case 0x100 | 'Q': { | |
421 | 437 | struct shf shf; |
422 | 438 | |
423 | 439 | shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf); |
@@ -839,7 +855,10 @@ expand(const char *cp, /* input word */ | ||
839 | 855 | if (c == 0) { |
840 | 856 | if (quote && !x.split) |
841 | 857 | continue; |
858 | + /* this is so we don't terminate */ | |
842 | 859 | c = ' '; |
860 | + /* now force-emit a word */ | |
861 | + goto emit_word; | |
843 | 862 | } |
844 | 863 | if (quote && x.split) { |
845 | 864 | /* terminate word for "$@" */ |
@@ -850,14 +869,19 @@ expand(const char *cp, /* input word */ | ||
850 | 869 | break; |
851 | 870 | |
852 | 871 | case XCOM: |
853 | - if (newlines) { | |
854 | - /* Spit out saved NLs */ | |
872 | + if (x.u.shf == NULL) { | |
873 | + /* $(<...) failed */ | |
874 | + subst_exstat = 1; | |
875 | + /* fake EOF */ | |
876 | + c = EOF; | |
877 | + } else if (newlines) { | |
878 | + /* spit out saved NLs */ | |
855 | 879 | c = '\n'; |
856 | 880 | --newlines; |
857 | 881 | } else { |
858 | 882 | while ((c = shf_getc(x.u.shf)) == 0 || c == '\n') |
859 | 883 | if (c == '\n') |
860 | - /* Save newlines */ | |
884 | + /* save newlines */ | |
861 | 885 | newlines++; |
862 | 886 | if (newlines && c != EOF) { |
863 | 887 | shf_ungetc(c, x.u.shf); |
@@ -867,7 +891,8 @@ expand(const char *cp, /* input word */ | ||
867 | 891 | } |
868 | 892 | if (c == EOF) { |
869 | 893 | newlines = 0; |
870 | - shf_close(x.u.shf); | |
894 | + if (x.u.shf) | |
895 | + shf_close(x.u.shf); | |
871 | 896 | if (x.split) |
872 | 897 | subst_exstat = waitlast(); |
873 | 898 | type = XBASE; |
@@ -895,21 +920,21 @@ expand(const char *cp, /* input word */ | ||
895 | 920 | */ |
896 | 921 | if (word == IFS_WORD || |
897 | 922 | (!ctype(c, C_IFSWS) && c && word == IFS_NWS)) { |
898 | - char *p; | |
899 | - | |
923 | + emit_word: | |
900 | 924 | *dp++ = '\0'; |
901 | - p = Xclose(ds, dp); | |
925 | + cp = Xclose(ds, dp); | |
902 | 926 | if (fdo & DOBRACE) |
903 | 927 | /* also does globbing */ |
904 | - alt_expand(wp, p, p, | |
905 | - p + Xlength(ds, (dp - 1)), | |
928 | + alt_expand(wp, cp, cp, | |
929 | + cp + Xlength(ds, (dp - 1)), | |
906 | 930 | fdo | (f & DOMARKDIRS)); |
907 | 931 | else if (fdo & DOGLOB) |
908 | - glob(p, wp, tobool(f & DOMARKDIRS)); | |
932 | + glob(cp, wp, tobool(f & DOMARKDIRS)); | |
909 | 933 | else if ((f & DOPAT) || !(fdo & DOMAGIC)) |
910 | - XPput(*wp, p); | |
934 | + XPput(*wp, cp); | |
911 | 935 | else |
912 | - XPput(*wp, debunk(p, p, strlen(p) + 1)); | |
936 | + XPput(*wp, debunk(cp, cp, | |
937 | + strlen(cp) + 1)); | |
913 | 938 | fdo = 0; |
914 | 939 | saw_eq = false; |
915 | 940 | tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; |
@@ -920,10 +945,8 @@ expand(const char *cp, /* input word */ | ||
920 | 945 | return; |
921 | 946 | } else if (type == XSUB && ctype(c, C_IFS) && |
922 | 947 | !ctype(c, C_IFSWS) && Xlength(ds, dp) == 0) { |
923 | - char *p; | |
924 | - | |
925 | - *(p = alloc(1, ATEMP)) = '\0'; | |
926 | - XPput(*wp, p); | |
948 | + *(cp = alloc(1, ATEMP)) = '\0'; | |
949 | + XPput(*wp, cp); | |
927 | 950 | type = XSUBMID; |
928 | 951 | } |
929 | 952 | if (word != IFS_NWS) |
@@ -932,10 +955,8 @@ expand(const char *cp, /* input word */ | ||
932 | 955 | if (type == XSUB) { |
933 | 956 | if (word == IFS_NWS && |
934 | 957 | Xlength(ds, dp) == 0) { |
935 | - char *p; | |
936 | - | |
937 | - *(p = alloc(1, ATEMP)) = '\0'; | |
938 | - XPput(*wp, p); | |
958 | + *(cp = alloc(1, ATEMP)) = '\0'; | |
959 | + XPput(*wp, cp); | |
939 | 960 | } |
940 | 961 | type = XSUBMID; |
941 | 962 | } |
@@ -1002,18 +1023,17 @@ expand(const char *cp, /* input word */ | ||
1002 | 1023 | if (type == XBASE && |
1003 | 1024 | (f & (DOTILDE|DOASNTILDE)) && |
1004 | 1025 | (tilde_ok & 2)) { |
1005 | - const char *p; | |
1006 | - char *dp_x; | |
1026 | + const char *tcp; | |
1027 | + char *tdp = dp; | |
1007 | 1028 | |
1008 | - dp_x = dp; | |
1009 | - p = maybe_expand_tilde(sp, | |
1010 | - &ds, &dp_x, | |
1029 | + tcp = maybe_expand_tilde(sp, | |
1030 | + &ds, &tdp, | |
1011 | 1031 | f & DOASNTILDE); |
1012 | - if (p) { | |
1013 | - if (dp != dp_x) | |
1032 | + if (tcp) { | |
1033 | + if (dp != tdp) | |
1014 | 1034 | word = IFS_WORD; |
1015 | - dp = dp_x; | |
1016 | - sp = p; | |
1035 | + dp = tdp; | |
1036 | + sp = tcp; | |
1017 | 1037 | continue; |
1018 | 1038 | } |
1019 | 1039 | } |
@@ -1176,8 +1196,10 @@ varsub(Expand *xp, const char *sp, const char *word, | ||
1176 | 1196 | c = sp[0]; |
1177 | 1197 | if (c == '*' || c == '@') { |
1178 | 1198 | switch (stype & 0x17F) { |
1179 | - case '=': /* can't assign to a vector */ | |
1180 | - case '%': /* can't trim a vector (yet) */ | |
1199 | + /* can't assign to a vector */ | |
1200 | + case '=': | |
1201 | + /* can't trim a vector (yet) */ | |
1202 | + case '%': | |
1181 | 1203 | case '#': |
1182 | 1204 | case '0': |
1183 | 1205 | case '/': |
@@ -1204,8 +1226,10 @@ varsub(Expand *xp, const char *sp, const char *word, | ||
1204 | 1226 | XPtrV wv; |
1205 | 1227 | |
1206 | 1228 | switch (stype & 0x17F) { |
1207 | - case '=': /* can't assign to a vector */ | |
1208 | - case '%': /* can't trim a vector (yet) */ | |
1229 | + /* can't assign to a vector */ | |
1230 | + case '=': | |
1231 | + /* can't trim a vector (yet) */ | |
1232 | + case '%': | |
1209 | 1233 | case '#': |
1210 | 1234 | case '?': |
1211 | 1235 | case '0': |
@@ -1317,33 +1341,41 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED) | ||
1317 | 1341 | shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0, |
1318 | 1342 | SHF_MAPHI|SHF_CLEXEC); |
1319 | 1343 | if (shf == NULL) |
1320 | - errorf("%s: %s %s", name, "can't open", "$() input"); | |
1344 | + warningf(!Flag(FTALKING), "%s: %s %s: %s", name, | |
1345 | + "can't open", "$(<...) input", cstrerror(errno)); | |
1321 | 1346 | } else if (fn == FUNSUB) { |
1322 | 1347 | int ofd1; |
1323 | 1348 | struct temp *tf = NULL; |
1324 | 1349 | |
1325 | - /* create a temporary file, open for writing */ | |
1350 | + /* | |
1351 | + * create a temporary file, open for reading and writing, | |
1352 | + * with an shf open for reading (buffered) but yet unused | |
1353 | + */ | |
1326 | 1354 | maketemp(ATEMP, TT_FUNSUB, &tf); |
1327 | 1355 | if (!tf->shf) { |
1328 | 1356 | errorf("can't %s temporary file %s: %s", |
1329 | 1357 | "create", tf->tffn, cstrerror(errno)); |
1330 | 1358 | } |
1331 | - /* save stdout and make the temporary file it */ | |
1359 | + /* extract shf from temporary file, unlink and free it */ | |
1360 | + shf = tf->shf; | |
1361 | + unlink(tf->tffn); | |
1362 | + afree(tf, ATEMP); | |
1363 | + /* save stdout and let it point to the tempfile */ | |
1332 | 1364 | ofd1 = savefd(1); |
1333 | - ksh_dup2(shf_fileno(tf->shf), 1, false); | |
1365 | + ksh_dup2(shf_fileno(shf), 1, false); | |
1334 | 1366 | /* |
1335 | 1367 | * run tree, with output thrown into the tempfile, |
1336 | 1368 | * in a new function block |
1337 | 1369 | */ |
1338 | - funsub(t); | |
1370 | + valsub(t, NULL); | |
1339 | 1371 | subst_exstat = exstat & 0xFF; |
1340 | - /* close the tempfile and restore regular stdout */ | |
1341 | - shf_close(tf->shf); | |
1372 | + /* rewind the tempfile and restore regular stdout */ | |
1373 | + lseek(shf_fileno(shf), (off_t)0, SEEK_SET); | |
1342 | 1374 | restfd(1, ofd1); |
1343 | - /* now open, unlink and free the tempfile for reading */ | |
1344 | - shf = shf_open(tf->tffn, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC); | |
1345 | - unlink(tf->tffn); | |
1346 | - afree(tf, ATEMP); | |
1375 | + } else if (fn == VALSUB) { | |
1376 | + xp->str = valsub(t, ATEMP); | |
1377 | + subst_exstat = exstat & 0xFF; | |
1378 | + return (XSUB); | |
1347 | 1379 | } else { |
1348 | 1380 | int ofd1, pv[2]; |
1349 | 1381 |
@@ -1495,11 +1527,11 @@ globit(XString *xs, /* dest string */ | ||
1495 | 1527 | */ |
1496 | 1528 | if ((check & GF_EXCHECK) || |
1497 | 1529 | ((check & GF_MARKDIR) && (check & GF_GLOBBED))) { |
1498 | -#define stat_check() (stat_done ? stat_done : \ | |
1499 | - (stat_done = stat(Xstring(*xs, xp), &statb) < 0 \ | |
1500 | - ? -1 : 1)) | |
1530 | +#define stat_check() (stat_done ? stat_done : (stat_done = \ | |
1531 | + stat(Xstring(*xs, xp), &statb) < 0 ? -1 : 1)) | |
1501 | 1532 | struct stat lstatb, statb; |
1502 | - int stat_done = 0; /* -1: failed, 1 ok */ | |
1533 | + /* -1: failed, 1 ok, 0 not yet done */ | |
1534 | + int stat_done = 0; | |
1503 | 1535 | |
1504 | 1536 | if (mksh_lstat(Xstring(*xs, xp), &lstatb) < 0) |
1505 | 1537 | return; |
@@ -1801,12 +1833,21 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) | ||
1801 | 1833 | } |
1802 | 1834 | |
1803 | 1835 | /* helper function due to setjmp/longjmp woes */ |
1804 | -static void | |
1805 | -funsub(struct op *t) | |
1836 | +static char * | |
1837 | +valsub(struct op *t, Area *ap) | |
1806 | 1838 | { |
1839 | + char * volatile cp = NULL; | |
1840 | + struct tbl * volatile vp = NULL; | |
1841 | + | |
1842 | + newenv(E_FUNC); | |
1807 | 1843 | newblock(); |
1808 | - e->type = E_FUNC; | |
1844 | + if (ap) | |
1845 | + vp = local("REPLY", false); | |
1809 | 1846 | if (!kshsetjmp(e->jbuf)) |
1810 | 1847 | execute(t, XXCOM | XERROK, NULL); |
1811 | - popblock(); | |
1848 | + if (vp) | |
1849 | + strdupx(cp, str_val(vp), ap); | |
1850 | + quitenv(NULL); | |
1851 | + | |
1852 | + return (cp); | |
1812 | 1853 | } |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy Exp $ */ | |
1 | +/* $OpenBSD: exec.c,v 1.50 2013/06/10 21:09:27 millert Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
@@ -23,7 +23,7 @@ | ||
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
26 | -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.116 2013/02/17 05:40:15 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.125 2013/07/21 20:44:44 tg Exp $"); | |
27 | 27 | |
28 | 28 | #ifndef MKSH_DEFAULT_EXECSHELL |
29 | 29 | #define MKSH_DEFAULT_EXECSHELL "/bin/sh" |
@@ -106,7 +106,7 @@ execute(struct op * volatile t, | ||
106 | 106 | /* set variable to its expanded value */ |
107 | 107 | z = strlen(cp) + 1; |
108 | 108 | if (notoktomul(z, 2) || notoktoadd(z * 2, n)) |
109 | - internal_errorf(Toomem, (unsigned long)-1); | |
109 | + internal_errorf(Toomem, (size_t)-1); | |
110 | 110 | dp = alloc(z * 2 + n, ATEMP); |
111 | 111 | memcpy(dp, t->vars[0], n); |
112 | 112 | t->vars[0] = dp; |
@@ -138,14 +138,6 @@ execute(struct op * volatile t, | ||
138 | 138 | /* Allow option parsing (bizarre, but POSIX) */ |
139 | 139 | timex_hook(t, &up); |
140 | 140 | ap = (const char **)up; |
141 | - if (Flag(FXTRACE) && ap[0]) { | |
142 | - shf_puts(substitute(str_val(global("PS4")), 0), | |
143 | - shl_out); | |
144 | - for (i = 0; ap[i]; i++) | |
145 | - shf_fprintf(shl_out, "%s%c", ap[i], | |
146 | - ap[i + 1] ? ' ' : '\n'); | |
147 | - shf_flush(shl_out); | |
148 | - } | |
149 | 141 | if (ap[0]) |
150 | 142 | tp = findcom(ap[0], FC_BI|FC_FUNC); |
151 | 143 | } |
@@ -305,10 +297,12 @@ execute(struct op * volatile t, | ||
305 | 297 | case TAND: |
306 | 298 | rv = execute(t->left, XERROK, xerrok); |
307 | 299 | if ((rv == 0) == (t->type == TAND)) |
308 | - rv = execute(t->right, XERROK, xerrok); | |
309 | - flags |= XERROK; | |
310 | - if (xerrok) | |
311 | - *xerrok = 1; | |
300 | + rv = execute(t->right, flags & XERROK, xerrok); | |
301 | + else { | |
302 | + flags |= XERROK; | |
303 | + if (xerrok) | |
304 | + *xerrok = 1; | |
305 | + } | |
312 | 306 | break; |
313 | 307 | |
314 | 308 | case TBANG: |
@@ -335,6 +329,7 @@ execute(struct op * volatile t, | ||
335 | 329 | case TFOR: |
336 | 330 | case TSELECT: { |
337 | 331 | volatile bool is_first = true; |
332 | + | |
338 | 333 | ap = (t->vars == NULL) ? e->loc->argv + 1 : |
339 | 334 | (const char **)eval((const char **)t->vars, |
340 | 335 | DOBLANK | DOGLOB | DOTILDE); |
@@ -639,27 +634,44 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | ||
639 | 634 | l_assign = e->loc; |
640 | 635 | if (Flag(FEXPORT)) |
641 | 636 | type_flags |= EXPORT; |
637 | + if (Flag(FXTRACE)) | |
638 | + change_xtrace(2, false); | |
642 | 639 | for (i = 0; t->vars[i]; i++) { |
643 | 640 | /* do NOT lookup in the new var/fn block just created */ |
644 | 641 | e->loc = l_expand; |
645 | 642 | cp = evalstr(t->vars[i], DOASNTILDE); |
646 | 643 | e->loc = l_assign; |
647 | - /* but assign in there as usual */ | |
648 | - | |
649 | 644 | if (Flag(FXTRACE)) { |
650 | - if (i == 0) | |
651 | - shf_puts(substitute(str_val(global("PS4")), 0), | |
652 | - shl_out); | |
653 | - shf_fprintf(shl_out, "%s%c", cp, | |
654 | - t->vars[i + 1] ? ' ' : '\n'); | |
655 | - if (!t->vars[i + 1]) | |
656 | - shf_flush(shl_out); | |
645 | + const char *ccp; | |
646 | + | |
647 | + ccp = skip_varname(cp, true); | |
648 | + if (*ccp == '+') | |
649 | + ++ccp; | |
650 | + if (*ccp == '=') | |
651 | + ++ccp; | |
652 | + shf_write(cp, ccp - cp, shl_xtrace); | |
653 | + print_value_quoted(shl_xtrace, ccp); | |
654 | + shf_putc(' ', shl_xtrace); | |
657 | 655 | } |
656 | + /* but assign in there as usual */ | |
658 | 657 | typeset(cp, type_flags, 0, 0, 0); |
659 | 658 | if (bourne_function_call && !(type_flags & EXPORT)) |
660 | 659 | typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0); |
661 | 660 | } |
662 | 661 | |
662 | + if (Flag(FXTRACE)) { | |
663 | + change_xtrace(2, false); | |
664 | + if (ap[rv = 0]) { | |
665 | + xtrace_ap_loop: | |
666 | + print_value_quoted(shl_xtrace, ap[rv]); | |
667 | + if (ap[++rv]) { | |
668 | + shf_putc(' ', shl_xtrace); | |
669 | + goto xtrace_ap_loop; | |
670 | + } | |
671 | + } | |
672 | + change_xtrace(1, false); | |
673 | + } | |
674 | + | |
663 | 675 | if ((cp = *ap) == NULL) { |
664 | 676 | rv = subst_exstat; |
665 | 677 | goto Leave; |
@@ -700,10 +712,9 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | ||
700 | 712 | break; |
701 | 713 | } |
702 | 714 | if (include(tp->u.fpath, 0, NULL, false) < 0) { |
703 | - rv = errno; | |
704 | 715 | warningf(true, "%s: %s %s %s: %s", cp, |
705 | 716 | "can't open", "function definition file", |
706 | - tp->u.fpath, cstrerror(rv)); | |
717 | + tp->u.fpath, cstrerror(errno)); | |
707 | 718 | rv = 127; |
708 | 719 | break; |
709 | 720 | } |
@@ -740,9 +751,9 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | ||
740 | 751 | getopts_reset(1); |
741 | 752 | } |
742 | 753 | |
743 | - old_xflag = Flag(FXTRACE); | |
744 | - Flag(FXTRACE) |= tp->flag & TRACE ? 1 : 0; | |
745 | - | |
754 | + old_xflag = Flag(FXTRACE) ? 1 : 0; | |
755 | + change_xtrace((Flag(FXTRACEREC) ? old_xflag : 0) | | |
756 | + ((tp->flag & TRACE) ? 1 : 0), false); | |
746 | 757 | old_inuse = tp->flag & FINUSE; |
747 | 758 | tp->flag |= FINUSE; |
748 | 759 |
@@ -751,9 +762,11 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, | ||
751 | 762 | execute(tp->val.t, flags & XERROK, NULL); |
752 | 763 | i = LRETURN; |
753 | 764 | } |
765 | + | |
754 | 766 | kshname = old_kshname; |
755 | - Flag(FXTRACE) = old_xflag; | |
767 | + change_xtrace(old_xflag, false); | |
756 | 768 | tp->flag = (tp->flag & ~FINUSE) | old_inuse; |
769 | + | |
757 | 770 | /* |
758 | 771 | * Were we deleted while executing? If so, free the |
759 | 772 | * execution tree. TODO: Unfortunately, the table entry |
@@ -1033,25 +1046,23 @@ const char * | ||
1033 | 1046 | builtin(const char *name, int (*func) (const char **)) |
1034 | 1047 | { |
1035 | 1048 | struct tbl *tp; |
1036 | - uint32_t flag; | |
1049 | + uint32_t flag = DEFINED; | |
1037 | 1050 | |
1038 | 1051 | /* see if any flags should be set for this builtin */ |
1039 | - for (flag = 0; ; name++) { | |
1052 | + while (1) { | |
1040 | 1053 | if (*name == '=') |
1041 | 1054 | /* command does variable assignment */ |
1042 | 1055 | flag |= KEEPASN; |
1043 | 1056 | else if (*name == '*') |
1044 | 1057 | /* POSIX special builtin */ |
1045 | 1058 | flag |= SPEC_BI; |
1046 | - else if (*name == '+') | |
1047 | - /* POSIX regular builtin */ | |
1048 | - flag |= REG_BI; | |
1049 | 1059 | else |
1050 | 1060 | break; |
1061 | + name++; | |
1051 | 1062 | } |
1052 | 1063 | |
1053 | 1064 | tp = ktenter(&builtins, name, hash(name)); |
1054 | - tp->flag = DEFINED | flag; | |
1065 | + tp->flag = flag; | |
1055 | 1066 | tp->type = CSHELL; |
1056 | 1067 | tp->val.f = func; |
1057 | 1068 |
@@ -1083,7 +1094,7 @@ findcom(const char *name, int flags) | ||
1083 | 1094 | tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL; |
1084 | 1095 | /* |
1085 | 1096 | * POSIX says special builtins first, then functions, then |
1086 | - * POSIX regular builtins, then search path... | |
1097 | + * regular builtins, then search path... | |
1087 | 1098 | */ |
1088 | 1099 | if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI)) |
1089 | 1100 | tp = tbi; |
@@ -1098,9 +1109,7 @@ findcom(const char *name, int flags) | ||
1098 | 1109 | &tp->u2.errnov); |
1099 | 1110 | } |
1100 | 1111 | } |
1101 | - if (!tp && (flags & FC_REGBI) && tbi && (tbi->flag & REG_BI)) | |
1102 | - tp = tbi; | |
1103 | - if (!tp && (flags & FC_UNREGBI) && tbi) | |
1112 | + if (!tp && (flags & FC_NORMBI) && tbi) | |
1104 | 1113 | tp = tbi; |
1105 | 1114 | if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) { |
1106 | 1115 | tp = ktsearch(&taliases, name, h); |
@@ -1298,10 +1307,11 @@ iosetup(struct ioword *iop, struct tbl *tp) | ||
1298 | 1307 | iotmp.name = (iotype == IOHERE) ? NULL : cp; |
1299 | 1308 | iotmp.flag |= IONAMEXP; |
1300 | 1309 | |
1301 | - if (Flag(FXTRACE)) | |
1302 | - shellf("%s%s\n", | |
1303 | - substitute(str_val(global("PS4")), 0), | |
1304 | - snptreef(NULL, 32, "%R", &iotmp)); | |
1310 | + if (Flag(FXTRACE)) { | |
1311 | + change_xtrace(2, false); | |
1312 | + fptreef(shl_xtrace, 0, "%R", &iotmp); | |
1313 | + change_xtrace(1, false); | |
1314 | + } | |
1305 | 1315 | |
1306 | 1316 | switch (iotype) { |
1307 | 1317 | case IOREAD: |
@@ -1345,8 +1355,11 @@ iosetup(struct ioword *iop, struct tbl *tp) | ||
1345 | 1355 | } else if ((u = check_fd(cp, |
1346 | 1356 | X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK), |
1347 | 1357 | &emsg)) < 0) { |
1358 | + char *sp; | |
1359 | + | |
1348 | 1360 | warningf(true, "%s: %s", |
1349 | - snptreef(NULL, 32, "%R", &iotmp), emsg); | |
1361 | + (sp = snptreef(NULL, 32, "%R", &iotmp)), emsg); | |
1362 | + afree(sp, ATEMP); | |
1350 | 1363 | return (-1); |
1351 | 1364 | } |
1352 | 1365 | if (u == iop->unit) |
@@ -1395,12 +1408,14 @@ iosetup(struct ioword *iop, struct tbl *tp) | ||
1395 | 1408 | else if (u != iop->unit) { |
1396 | 1409 | if (ksh_dup2(u, iop->unit, true) < 0) { |
1397 | 1410 | int eno; |
1411 | + char *sp; | |
1398 | 1412 | |
1399 | 1413 | eno = errno; |
1400 | 1414 | warningf(true, "%s %s %s", |
1401 | 1415 | "can't finish (dup) redirection", |
1402 | - snptreef(NULL, 32, "%R", &iotmp), | |
1416 | + (sp = snptreef(NULL, 32, "%R", &iotmp)), | |
1403 | 1417 | cstrerror(eno)); |
1418 | + afree(sp, ATEMP); | |
1404 | 1419 | if (iotype != IODUP) |
1405 | 1420 | close(u); |
1406 | 1421 | return (-1); |
@@ -1548,10 +1563,8 @@ do_selectargs(const char **ap, bool print_menu) | ||
1548 | 1563 | if (call_builtin(findcom("read", FC_BI), read_args, Tselect)) |
1549 | 1564 | return (NULL); |
1550 | 1565 | s = str_val(global("REPLY")); |
1551 | - if (*s) { | |
1552 | - getn(s, &i); | |
1566 | + if (*s && getn(s, &i)) | |
1553 | 1567 | return ((i >= 1 && i <= argct) ? ap[i - 1] : null); |
1554 | - } | |
1555 | 1568 | print_menu = true; |
1556 | 1569 | } |
1557 | 1570 | } |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: expr.c,v 1.21 2009/06/01 19:00:57 deraadt Exp $ */ | |
1 | +/* $OpenBSD: expr.c,v 1.22 2013/03/28 08:39:28 nicm Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
@@ -23,23 +23,9 @@ | ||
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
26 | -__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.61 2013/02/15 18:36:48 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.72 2013/07/21 18:38:56 tg Exp $"); | |
27 | 27 | |
28 | -#if !HAVE_SILENT_IDIVWRAPV | |
29 | -#if !defined(MKSH_LEGACY_MODE) || HAVE_LONG_32BIT | |
30 | -#define IDIVWRAPV_VL (mksh_uari_t)0x80000000UL | |
31 | -#define IDIVWRAPV_VR (mksh_uari_t)0xFFFFFFFFUL | |
32 | -#elif HAVE_LONG_64BIT | |
33 | -#define IDIVWRAPV_VL (mksh_uari_t)0x8000000000000000UL | |
34 | -#define IDIVWRAPV_VR (mksh_uari_t)0xFFFFFFFFFFFFFFFFUL | |
35 | -#else | |
36 | -# warning "cannot guarantee integer division wraparound" | |
37 | -#undef HAVE_SILENT_IDIVWRAPV | |
38 | -#define HAVE_SILENT_IDIVWRAPV 1 | |
39 | -#endif | |
40 | -#endif | |
41 | - | |
42 | -/* The order of these enums is constrained by the order of opinfo[] */ | |
28 | +/* the order of these enums is constrained by the order of opinfo[] */ | |
43 | 29 | enum token { |
44 | 30 | /* some (long) unary operators */ |
45 | 31 | O_PLUSPLUS = 0, O_MINUSMINUS, |
@@ -47,7 +33,14 @@ enum token { | ||
47 | 33 | O_EQ, O_NE, |
48 | 34 | /* assignments are assumed to be in range O_ASN .. O_BORASN */ |
49 | 35 | O_ASN, O_TIMESASN, O_DIVASN, O_MODASN, O_PLUSASN, O_MINUSASN, |
36 | +#ifndef MKSH_LEGACY_MODE | |
37 | + O_ROLASN, O_RORASN, | |
38 | +#endif | |
50 | 39 | O_LSHIFTASN, O_RSHIFTASN, O_BANDASN, O_BXORASN, O_BORASN, |
40 | + /* binary non-assignment operators */ | |
41 | +#ifndef MKSH_LEGACY_MODE | |
42 | + O_ROL, O_ROR, | |
43 | +#endif | |
51 | 44 | O_LSHIFT, O_RSHIFT, |
52 | 45 | O_LE, O_GE, O_LT, O_GT, |
53 | 46 | O_LAND, |
@@ -67,14 +60,13 @@ enum token { | ||
67 | 60 | /* things that don't appear in the opinfo[] table */ |
68 | 61 | VAR, LIT, END, BAD |
69 | 62 | }; |
70 | -#define IS_BINOP(op) (((int)op) >= (int)O_EQ && ((int)op) <= (int)O_COMMA) | |
71 | 63 | #define IS_ASSIGNOP(op) ((int)(op) >= (int)O_ASN && (int)(op) <= (int)O_BORASN) |
72 | 64 | |
73 | 65 | /* precisions; used to be enum prec but we do arithmetics on it */ |
74 | -#define P_PRIMARY 0 /* VAR, LIT, (), ~ ! - + */ | |
66 | +#define P_PRIMARY 0 /* VAR, LIT, (), ! ~ ++ -- */ | |
75 | 67 | #define P_MULT 1 /* * / % */ |
76 | 68 | #define P_ADD 2 /* + - */ |
77 | -#define P_SHIFT 3 /* << >> */ | |
69 | +#define P_SHIFT 3 /* <<< >>> << >> */ | |
78 | 70 | #define P_RELATION 4 /* < <= > >= */ |
79 | 71 | #define P_EQUALITY 5 /* == != */ |
80 | 72 | #define P_BAND 6 /* & */ |
@@ -83,60 +75,72 @@ enum token { | ||
83 | 75 | #define P_LAND 9 /* && */ |
84 | 76 | #define P_LOR 10 /* || */ |
85 | 77 | #define P_TERN 11 /* ?: */ |
86 | -#define P_ASSIGN 12 /* = *= /= %= += -= <<= >>= &= ^= |= */ | |
78 | + /* = += -= *= /= %= <<<= >>>= <<= >>= &= ^= |= */ | |
79 | +#define P_ASSIGN 12 | |
87 | 80 | #define P_COMMA 13 /* , */ |
88 | 81 | #define MAX_PREC P_COMMA |
89 | 82 | |
90 | 83 | struct opinfo { |
91 | - char name[4]; | |
92 | - int len; /* name length */ | |
93 | - int prec; /* precedence: lower is higher */ | |
84 | + char name[5]; | |
85 | + /* name length */ | |
86 | + uint8_t len; | |
87 | + /* precedence: lower is higher */ | |
88 | + uint8_t prec; | |
94 | 89 | }; |
95 | 90 | |
96 | -/* Tokens in this table must be ordered so the longest are first | |
91 | +/* | |
92 | + * Tokens in this table must be ordered so the longest are first | |
97 | 93 | * (eg, += before +). If you change something, change the order |
98 | 94 | * of enum token too. |
99 | 95 | */ |
100 | 96 | static const struct opinfo opinfo[] = { |
101 | - { "++", 2, P_PRIMARY }, /* before + */ | |
102 | - { "--", 2, P_PRIMARY }, /* before - */ | |
103 | - { "==", 2, P_EQUALITY }, /* before = */ | |
104 | - { "!=", 2, P_EQUALITY }, /* before ! */ | |
105 | - { "=", 1, P_ASSIGN }, /* keep assigns in a block */ | |
106 | - { "*=", 2, P_ASSIGN }, | |
107 | - { "/=", 2, P_ASSIGN }, | |
108 | - { "%=", 2, P_ASSIGN }, | |
109 | - { "+=", 2, P_ASSIGN }, | |
110 | - { "-=", 2, P_ASSIGN }, | |
111 | - { "<<=", 3, P_ASSIGN }, | |
112 | - { ">>=", 3, P_ASSIGN }, | |
113 | - { "&=", 2, P_ASSIGN }, | |
114 | - { "^=", 2, P_ASSIGN }, | |
115 | - { "|=", 2, P_ASSIGN }, | |
116 | - { "<<", 2, P_SHIFT }, | |
117 | - { ">>", 2, P_SHIFT }, | |
118 | - { "<=", 2, P_RELATION }, | |
119 | - { ">=", 2, P_RELATION }, | |
120 | - { "<", 1, P_RELATION }, | |
121 | - { ">", 1, P_RELATION }, | |
122 | - { "&&", 2, P_LAND }, | |
123 | - { "||", 2, P_LOR }, | |
124 | - { "*", 1, P_MULT }, | |
125 | - { "/", 1, P_MULT }, | |
126 | - { "%", 1, P_MULT }, | |
127 | - { "+", 1, P_ADD }, | |
128 | - { "-", 1, P_ADD }, | |
129 | - { "&", 1, P_BAND }, | |
130 | - { "^", 1, P_BXOR }, | |
131 | - { "|", 1, P_BOR }, | |
132 | - { "?", 1, P_TERN }, | |
133 | - { ",", 1, P_COMMA }, | |
134 | - { "~", 1, P_PRIMARY }, | |
135 | - { "!", 1, P_PRIMARY }, | |
136 | - { "(", 1, P_PRIMARY }, | |
137 | - { ")", 1, P_PRIMARY }, | |
138 | - { ":", 1, P_PRIMARY }, | |
139 | - { "", 0, P_PRIMARY } | |
97 | + { "++", 2, P_PRIMARY }, /* before + */ | |
98 | + { "--", 2, P_PRIMARY }, /* before - */ | |
99 | + { "==", 2, P_EQUALITY }, /* before = */ | |
100 | + { "!=", 2, P_EQUALITY }, /* before ! */ | |
101 | + { "=", 1, P_ASSIGN }, /* keep assigns in a block */ | |
102 | + { "*=", 2, P_ASSIGN }, | |
103 | + { "/=", 2, P_ASSIGN }, | |
104 | + { "%=", 2, P_ASSIGN }, | |
105 | + { "+=", 2, P_ASSIGN }, | |
106 | + { "-=", 2, P_ASSIGN }, | |
107 | +#ifndef MKSH_LEGACY_MODE | |
108 | + { "<<<=", 4, P_ASSIGN }, /* before <<< */ | |
109 | + { ">>>=", 4, P_ASSIGN }, /* before >>> */ | |
110 | +#endif | |
111 | + { "<<=", 3, P_ASSIGN }, | |
112 | + { ">>=", 3, P_ASSIGN }, | |
113 | + { "&=", 2, P_ASSIGN }, | |
114 | + { "^=", 2, P_ASSIGN }, | |
115 | + { "|=", 2, P_ASSIGN }, | |
116 | +#ifndef MKSH_LEGACY_MODE | |
117 | + { "<<<", 3, P_SHIFT }, /* before << */ | |
118 | + { ">>>", 3, P_SHIFT }, /* before >> */ | |
119 | +#endif | |
120 | + { "<<", 2, P_SHIFT }, | |
121 | + { ">>", 2, P_SHIFT }, | |
122 | + { "<=", 2, P_RELATION }, | |
123 | + { ">=", 2, P_RELATION }, | |
124 | + { "<", 1, P_RELATION }, | |
125 | + { ">", 1, P_RELATION }, | |
126 | + { "&&", 2, P_LAND }, | |
127 | + { "||", 2, P_LOR }, | |
128 | + { "*", 1, P_MULT }, | |
129 | + { "/", 1, P_MULT }, | |
130 | + { "%", 1, P_MULT }, | |
131 | + { "+", 1, P_ADD }, | |
132 | + { "-", 1, P_ADD }, | |
133 | + { "&", 1, P_BAND }, | |
134 | + { "^", 1, P_BXOR }, | |
135 | + { "|", 1, P_BOR }, | |
136 | + { "?", 1, P_TERN }, | |
137 | + { ",", 1, P_COMMA }, | |
138 | + { "~", 1, P_PRIMARY }, | |
139 | + { "!", 1, P_PRIMARY }, | |
140 | + { "(", 1, P_PRIMARY }, | |
141 | + { ")", 1, P_PRIMARY }, | |
142 | + { ":", 1, P_PRIMARY }, | |
143 | + { "", 0, P_PRIMARY } | |
140 | 144 | }; |
141 | 145 | |
142 | 146 | typedef struct expr_state { |
@@ -151,18 +155,13 @@ typedef struct expr_state { | ||
151 | 155 | /* token from token() */ |
152 | 156 | enum token tok; |
153 | 157 | /* don't do assignments (for ?:, &&, ||) */ |
154 | - short noassign; | |
158 | + uint8_t noassign; | |
155 | 159 | /* evaluating an $(()) expression? */ |
156 | 160 | bool arith; |
157 | 161 | /* unsigned arithmetic calculation */ |
158 | 162 | bool natural; |
159 | 163 | } Expr_state; |
160 | 164 | |
161 | -#define bivui(x, op, y) (es->natural ? \ | |
162 | - (mksh_uari_t)((x)->val.u op (y)->val.u) : \ | |
163 | - (mksh_uari_t)((x)->val.i op (y)->val.i) \ | |
164 | -) | |
165 | - | |
166 | 165 | enum error_type { |
167 | 166 | ET_UNEXPECTED, ET_BADLIT, ET_RECURSIVE, |
168 | 167 | ET_LVALUE, ET_RDONLY, ET_STR |
@@ -170,7 +169,7 @@ enum error_type { | ||
170 | 169 | |
171 | 170 | static void evalerr(Expr_state *, enum error_type, const char *) |
172 | 171 | MKSH_A_NORETURN; |
173 | -static struct tbl *evalexpr(Expr_state *, int); | |
172 | +static struct tbl *evalexpr(Expr_state *, unsigned int); | |
174 | 173 | static void exprtoken(Expr_state *); |
175 | 174 | static struct tbl *do_ppmm(Expr_state *, enum token, struct tbl *, bool); |
176 | 175 | static void assign_check(Expr_state *, enum token, struct tbl *); |
@@ -185,7 +184,7 @@ evaluate(const char *expr, mksh_ari_t *rval, int error_ok, bool arith) | ||
185 | 184 | struct tbl v; |
186 | 185 | int ret; |
187 | 186 | |
188 | - v.flag = DEFINED|INTEGER; | |
187 | + v.flag = DEFINED | INTEGER; | |
189 | 188 | v.type = 0; |
190 | 189 | ret = v_evaluate(&v, expr, error_ok, arith); |
191 | 190 | *rval = v.val.i; |
@@ -307,52 +306,103 @@ evalerr(Expr_state *es, enum error_type type, const char *str) | ||
307 | 306 | unwind(LAEXPR); |
308 | 307 | } |
309 | 308 | |
309 | +/* do a ++ or -- operation */ | |
310 | 310 | static struct tbl * |
311 | -evalexpr(Expr_state *es, int prec) | |
311 | +do_ppmm(Expr_state *es, enum token op, struct tbl *vasn, bool is_prefix) | |
312 | +{ | |
313 | + struct tbl *vl; | |
314 | + mksh_uari_t oval; | |
315 | + | |
316 | + assign_check(es, op, vasn); | |
317 | + | |
318 | + vl = intvar(es, vasn); | |
319 | + oval = vl->val.u; | |
320 | + if (op == O_PLUSPLUS) | |
321 | + ++vl->val.u; | |
322 | + else | |
323 | + --vl->val.u; | |
324 | + if (!es->noassign) { | |
325 | + if (vasn->flag & INTEGER) | |
326 | + setint_v(vasn, vl, es->arith); | |
327 | + else | |
328 | + setint(vasn, vl->val.i); | |
329 | + } | |
330 | + if (!is_prefix) | |
331 | + /* undo the increment/decrement */ | |
332 | + vl->val.u = oval; | |
333 | + | |
334 | + return (vl); | |
335 | +} | |
336 | + | |
337 | +static struct tbl * | |
338 | +evalexpr(Expr_state *es, unsigned int prec) | |
312 | 339 | { |
313 | 340 | struct tbl *vl, *vr = NULL, *vasn; |
314 | 341 | enum token op; |
315 | - mksh_uari_t res = 0; | |
342 | + mksh_uari_t res = 0, t1, t2, t3; | |
316 | 343 | |
317 | 344 | if (prec == P_PRIMARY) { |
318 | - op = es->tok; | |
319 | - if (op == O_BNOT || op == O_LNOT || op == O_MINUS || | |
320 | - op == O_PLUS) { | |
345 | + switch ((int)(op = es->tok)) { | |
346 | + case O_BNOT: | |
347 | + case O_LNOT: | |
348 | + case O_MINUS: | |
349 | + case O_PLUS: | |
321 | 350 | exprtoken(es); |
322 | 351 | vl = intvar(es, evalexpr(es, P_PRIMARY)); |
323 | - if (op == O_BNOT) | |
324 | - vl->val.i = ~vl->val.i; | |
325 | - else if (op == O_LNOT) | |
326 | - vl->val.i = !vl->val.i; | |
327 | - else if (op == O_MINUS) | |
328 | - vl->val.i = -vl->val.i; | |
329 | - /* op == O_PLUS is a no-op */ | |
330 | - } else if (op == OPEN_PAREN) { | |
352 | + switch ((int)op) { | |
353 | + case O_BNOT: | |
354 | + vl->val.u = ~vl->val.u; | |
355 | + break; | |
356 | + case O_LNOT: | |
357 | + vl->val.u = !vl->val.u; | |
358 | + break; | |
359 | + case O_MINUS: | |
360 | + vl->val.u = -vl->val.u; | |
361 | + break; | |
362 | + case O_PLUS: | |
363 | + /* nop */ | |
364 | + break; | |
365 | + } | |
366 | + break; | |
367 | + | |
368 | + case OPEN_PAREN: | |
331 | 369 | exprtoken(es); |
332 | 370 | vl = evalexpr(es, MAX_PREC); |
333 | 371 | if (es->tok != CLOSE_PAREN) |
334 | 372 | evalerr(es, ET_STR, "missing )"); |
335 | 373 | exprtoken(es); |
336 | - } else if (op == O_PLUSPLUS || op == O_MINUSMINUS) { | |
374 | + break; | |
375 | + | |
376 | + case O_PLUSPLUS: | |
377 | + case O_MINUSMINUS: | |
337 | 378 | exprtoken(es); |
338 | 379 | vl = do_ppmm(es, op, es->val, true); |
339 | 380 | exprtoken(es); |
340 | - } else if (op == VAR || op == LIT) { | |
381 | + break; | |
382 | + | |
383 | + case VAR: | |
384 | + case LIT: | |
341 | 385 | vl = es->val; |
342 | 386 | exprtoken(es); |
343 | - } else { | |
387 | + break; | |
388 | + | |
389 | + default: | |
344 | 390 | evalerr(es, ET_UNEXPECTED, NULL); |
345 | 391 | /* NOTREACHED */ |
346 | 392 | } |
393 | + | |
347 | 394 | if (es->tok == O_PLUSPLUS || es->tok == O_MINUSMINUS) { |
348 | 395 | vl = do_ppmm(es, es->tok, vl, false); |
349 | 396 | exprtoken(es); |
350 | 397 | } |
398 | + | |
351 | 399 | return (vl); |
400 | + /* prec == P_PRIMARY */ | |
352 | 401 | } |
402 | + | |
353 | 403 | vl = evalexpr(es, prec - 1); |
354 | - for (op = es->tok; IS_BINOP(op) && opinfo[(int)op].prec == prec; | |
355 | - op = es->tok) { | |
404 | + while ((int)(op = es->tok) >= (int)O_EQ && (int)op <= (int)O_COMMA && | |
405 | + opinfo[(int)op].prec == prec) { | |
356 | 406 | exprtoken(es); |
357 | 407 | vasn = vl; |
358 | 408 | if (op != O_ASN) |
@@ -362,152 +412,204 @@ evalexpr(Expr_state *es, int prec) | ||
362 | 412 | if (!es->noassign) |
363 | 413 | assign_check(es, op, vasn); |
364 | 414 | vr = intvar(es, evalexpr(es, P_ASSIGN)); |
365 | - } else if (op != O_TERN && op != O_LAND && op != O_LOR) | |
415 | + } else if (op == O_TERN) { | |
416 | + bool ev = vl->val.u != 0; | |
417 | + | |
418 | + if (!ev) | |
419 | + es->noassign++; | |
420 | + vl = evalexpr(es, MAX_PREC); | |
421 | + if (!ev) | |
422 | + es->noassign--; | |
423 | + if (es->tok != CTERN) | |
424 | + evalerr(es, ET_STR, "missing :"); | |
425 | + exprtoken(es); | |
426 | + if (ev) | |
427 | + es->noassign++; | |
428 | + vr = evalexpr(es, P_TERN); | |
429 | + if (ev) | |
430 | + es->noassign--; | |
431 | + vl = ev ? vl : vr; | |
432 | + continue; | |
433 | + } else if (op != O_LAND && op != O_LOR) | |
366 | 434 | vr = intvar(es, evalexpr(es, prec - 1)); |
367 | - if ((op == O_DIV || op == O_MOD || op == O_DIVASN || | |
368 | - op == O_MODASN) && vr->val.i == 0) { | |
369 | - if (es->noassign) | |
370 | - vr->val.i = 1; | |
371 | - else | |
372 | - evalerr(es, ET_STR, "zero divisor"); | |
435 | + | |
436 | + /* common ops setup */ | |
437 | + switch ((int)op) { | |
438 | + case O_DIV: | |
439 | + case O_DIVASN: | |
440 | + case O_MOD: | |
441 | + case O_MODASN: | |
442 | + if (vr->val.u == 0) { | |
443 | + if (!es->noassign) | |
444 | + evalerr(es, ET_STR, "zero divisor"); | |
445 | + vr->val.u = 1; | |
446 | + } | |
447 | + /* calculate the absolute values */ | |
448 | + t1 = vl->val.i < 0 ? -vl->val.u : vl->val.u; | |
449 | + t2 = vr->val.i < 0 ? -vr->val.u : vr->val.u; | |
450 | + break; | |
451 | +#ifndef MKSH_LEGACY_MODE | |
452 | + case O_LSHIFT: | |
453 | + case O_LSHIFTASN: | |
454 | + case O_RSHIFT: | |
455 | + case O_RSHIFTASN: | |
456 | + case O_ROL: | |
457 | + case O_ROLASN: | |
458 | + case O_ROR: | |
459 | + case O_RORASN: | |
460 | + t1 = vl->val.u; | |
461 | + t2 = vr->val.u & 31; | |
462 | + break; | |
463 | +#endif | |
464 | + case O_LAND: | |
465 | + case O_LOR: | |
466 | + t1 = vl->val.u; | |
467 | + t2 = 0; /* gcc */ | |
468 | + break; | |
469 | + default: | |
470 | + t1 = vl->val.u; | |
471 | + t2 = vr->val.u; | |
472 | + break; | |
373 | 473 | } |
474 | + | |
475 | +#define cmpop(op) (es->natural ? \ | |
476 | + (mksh_uari_t)(vl->val.u op vr->val.u) : \ | |
477 | + (mksh_uari_t)(vl->val.i op vr->val.i) \ | |
478 | +) | |
479 | + | |
480 | + /* op calculation */ | |
374 | 481 | switch ((int)op) { |
375 | 482 | case O_TIMES: |
376 | 483 | case O_TIMESASN: |
377 | - res = bivui(vl, *, vr); | |
484 | + res = t1 * t2; | |
378 | 485 | break; |
486 | + case O_MOD: | |
487 | + case O_MODASN: | |
488 | + if (es->natural) { | |
489 | + res = vl->val.u % vr->val.u; | |
490 | + break; | |
491 | + } | |
492 | + goto signed_division; | |
379 | 493 | case O_DIV: |
380 | 494 | case O_DIVASN: |
381 | -#if !HAVE_SILENT_IDIVWRAPV | |
495 | + if (es->natural) { | |
496 | + res = vl->val.u / vr->val.u; | |
497 | + break; | |
498 | + } | |
499 | + signed_division: | |
382 | 500 | /* |
383 | - * we are doing the comparisons here for the | |
384 | - * signed arithmetics (!es->natural) case, | |
385 | - * but the exact value checks and the bypass | |
386 | - * case assignments are done unsignedly as | |
387 | - * several compilers bitch around otherwise | |
501 | + * a / b = abs(a) / abs(b) * sgn((u)a^(u)b) | |
388 | 502 | */ |
389 | - if (!es->natural && | |
390 | - vl->val.u == IDIVWRAPV_VL && | |
391 | - vr->val.u == IDIVWRAPV_VR) { | |
392 | - /* -2147483648 / -1 = 2147483648 */ | |
393 | - /* this ^ is really (1 << 31) though */ | |
394 | - res = IDIVWRAPV_VL; | |
395 | - } else | |
396 | -#endif | |
397 | - res = bivui(vl, /, vr); | |
398 | - break; | |
399 | - case O_MOD: | |
400 | - case O_MODASN: | |
401 | -#if !HAVE_SILENT_IDIVWRAPV | |
402 | - /* see O_DIV / O_DIVASN for the reason behind this */ | |
403 | - if (!es->natural && | |
404 | - vl->val.u == IDIVWRAPV_VL && | |
405 | - vr->val.u == IDIVWRAPV_VR) { | |
406 | - /* -2147483648 % -1 = 0 */ | |
407 | - res = 0; | |
408 | - } else | |
503 | + t3 = t1 / t2; | |
504 | +#ifndef MKSH_LEGACY_MODE | |
505 | + res = ((vl->val.u ^ vr->val.u) & 0x80000000) ? -t3 : t3; | |
506 | +#else | |
507 | + res = ((t1 == vl->val.u ? 0 : 1) ^ | |
508 | + (t2 == vr->val.u ? 0 : 1)) ? -t3 : t3; | |
409 | 509 | #endif |
410 | - res = bivui(vl, %, vr); | |
510 | + if (op == O_MOD || op == O_MODASN) { | |
511 | + /* | |
512 | + * primitive modulo, to get the sign of | |
513 | + * the result correct: | |
514 | + * (a % b) = a - ((a / b) * b) | |
515 | + * the subtraction and multiplication | |
516 | + * are, amazingly enough, sign ignorant | |
517 | + */ | |
518 | + res = vl->val.u - (res * vr->val.u); | |
519 | + } | |
411 | 520 | break; |
412 | 521 | case O_PLUS: |
413 | 522 | case O_PLUSASN: |
414 | - res = bivui(vl, +, vr); | |
523 | + res = t1 + t2; | |
415 | 524 | break; |
416 | 525 | case O_MINUS: |
417 | 526 | case O_MINUSASN: |
418 | - res = bivui(vl, -, vr); | |
527 | + res = t1 - t2; | |
528 | + break; | |
529 | +#ifndef MKSH_LEGACY_MODE | |
530 | + case O_ROL: | |
531 | + case O_ROLASN: | |
532 | + res = (t1 << t2) | (t1 >> (32 - t2)); | |
419 | 533 | break; |
534 | + case O_ROR: | |
535 | + case O_RORASN: | |
536 | + res = (t1 >> t2) | (t1 << (32 - t2)); | |
537 | + break; | |
538 | +#endif | |
420 | 539 | case O_LSHIFT: |
421 | 540 | case O_LSHIFTASN: |
422 | - res = bivui(vl, <<, vr); | |
541 | + res = t1 << t2; | |
423 | 542 | break; |
424 | 543 | case O_RSHIFT: |
425 | 544 | case O_RSHIFTASN: |
426 | - res = bivui(vl, >>, vr); | |
545 | + res = es->natural || vl->val.i >= 0 ? | |
546 | + t1 >> t2 : | |
547 | + ~(~t1 >> t2); | |
427 | 548 | break; |
428 | 549 | case O_LT: |
429 | - res = bivui(vl, <, vr); | |
550 | + res = cmpop(<); | |
430 | 551 | break; |
431 | 552 | case O_LE: |
432 | - res = bivui(vl, <=, vr); | |
553 | + res = cmpop(<=); | |
433 | 554 | break; |
434 | 555 | case O_GT: |
435 | - res = bivui(vl, >, vr); | |
556 | + res = cmpop(>); | |
436 | 557 | break; |
437 | 558 | case O_GE: |
438 | - res = bivui(vl, >=, vr); | |
559 | + res = cmpop(>=); | |
439 | 560 | break; |
440 | 561 | case O_EQ: |
441 | - res = bivui(vl, ==, vr); | |
562 | + res = t1 == t2; | |
442 | 563 | break; |
443 | 564 | case O_NE: |
444 | - res = bivui(vl, !=, vr); | |
565 | + res = t1 != t2; | |
445 | 566 | break; |
446 | 567 | case O_BAND: |
447 | 568 | case O_BANDASN: |
448 | - res = bivui(vl, &, vr); | |
569 | + res = t1 & t2; | |
449 | 570 | break; |
450 | 571 | case O_BXOR: |
451 | 572 | case O_BXORASN: |
452 | - res = bivui(vl, ^, vr); | |
573 | + res = t1 ^ t2; | |
453 | 574 | break; |
454 | 575 | case O_BOR: |
455 | 576 | case O_BORASN: |
456 | - res = bivui(vl, |, vr); | |
577 | + res = t1 | t2; | |
457 | 578 | break; |
458 | 579 | case O_LAND: |
459 | - if (!vl->val.i) | |
580 | + if (!t1) | |
460 | 581 | es->noassign++; |
461 | 582 | vr = intvar(es, evalexpr(es, prec - 1)); |
462 | - res = bivui(vl, &&, vr); | |
463 | - if (!vl->val.i) | |
583 | + res = t1 && vr->val.u; | |
584 | + if (!t1) | |
464 | 585 | es->noassign--; |
465 | 586 | break; |
466 | 587 | case O_LOR: |
467 | - if (vl->val.i) | |
588 | + if (t1) | |
468 | 589 | es->noassign++; |
469 | 590 | vr = intvar(es, evalexpr(es, prec - 1)); |
470 | - res = bivui(vl, ||, vr); | |
471 | - if (vl->val.i) | |
591 | + res = t1 || vr->val.u; | |
592 | + if (t1) | |
472 | 593 | es->noassign--; |
473 | 594 | break; |
474 | - case O_TERN: | |
475 | - { | |
476 | - bool ev = vl->val.i != 0; | |
477 | - | |
478 | - if (!ev) | |
479 | - es->noassign++; | |
480 | - vl = evalexpr(es, MAX_PREC); | |
481 | - if (!ev) | |
482 | - es->noassign--; | |
483 | - if (es->tok != CTERN) | |
484 | - evalerr(es, ET_STR, "missing :"); | |
485 | - exprtoken(es); | |
486 | - if (ev) | |
487 | - es->noassign++; | |
488 | - vr = evalexpr(es, P_TERN); | |
489 | - if (ev) | |
490 | - es->noassign--; | |
491 | - vl = ev ? vl : vr; | |
492 | - } | |
493 | - break; | |
494 | 595 | case O_ASN: |
495 | - res = vr->val.u; | |
496 | - break; | |
497 | 596 | case O_COMMA: |
498 | - res = vr->val.u; | |
597 | + res = t2; | |
499 | 598 | break; |
500 | 599 | } |
600 | + | |
601 | +#undef cmpop | |
602 | + | |
501 | 603 | if (IS_ASSIGNOP(op)) { |
502 | 604 | vr->val.u = res; |
503 | 605 | if (!es->noassign) { |
504 | 606 | if (vasn->flag & INTEGER) |
505 | 607 | setint_v(vasn, vr, es->arith); |
506 | 608 | else |
507 | - setint(vasn, (mksh_ari_t)res); | |
609 | + setint(vasn, vr->val.i); | |
508 | 610 | } |
509 | 611 | vl = vr; |
510 | - } else if (op != O_TERN) | |
612 | + } else | |
511 | 613 | vl->val.u = res; |
512 | 614 | } |
513 | 615 | return (vl); |
@@ -520,13 +622,14 @@ exprtoken(Expr_state *es) | ||
520 | 622 | int c; |
521 | 623 | char *tvar; |
522 | 624 | |
523 | - /* skip white space */ | |
625 | + /* skip whitespace */ | |
524 | 626 | skip_spaces: |
525 | 627 | while ((c = *cp), ksh_isspace(c)) |
526 | 628 | ++cp; |
527 | 629 | if (es->tokp == es->expression && c == '#') { |
528 | 630 | /* expression begins with # */ |
529 | - es->natural = true; /* switch to unsigned */ | |
631 | + /* switch to unsigned */ | |
632 | + es->natural = true; | |
530 | 633 | ++cp; |
531 | 634 | goto skip_spaces; |
532 | 635 | } |
@@ -544,12 +647,6 @@ exprtoken(Expr_state *es) | ||
544 | 647 | if (len == 0) |
545 | 648 | evalerr(es, ET_STR, "missing ]"); |
546 | 649 | cp += len; |
547 | - } else if (c == '(' /*)*/ ) { | |
548 | - /* todo: add math functions (all take single argument): | |
549 | - * abs acos asin atan cos cosh exp int log sin sinh sqrt | |
550 | - * tan tanh | |
551 | - */ | |
552 | - ; | |
553 | 650 | } |
554 | 651 | if (es->noassign) { |
555 | 652 | es->val = tempvar(); |
@@ -610,39 +707,6 @@ exprtoken(Expr_state *es) | ||
610 | 707 | es->tokp = cp; |
611 | 708 | } |
612 | 709 | |
613 | -/* Do a ++ or -- operation */ | |
614 | -static struct tbl * | |
615 | -do_ppmm(Expr_state *es, enum token op, struct tbl *vasn, bool is_prefix) | |
616 | -{ | |
617 | - struct tbl *vl; | |
618 | - mksh_ari_t oval; | |
619 | - | |
620 | - assign_check(es, op, vasn); | |
621 | - | |
622 | - vl = intvar(es, vasn); | |
623 | - oval = vl->val.i; | |
624 | - if (op == O_PLUSPLUS) { | |
625 | - if (es->natural) | |
626 | - ++vl->val.u; | |
627 | - else | |
628 | - ++vl->val.i; | |
629 | - } else { | |
630 | - if (es->natural) | |
631 | - --vl->val.u; | |
632 | - else | |
633 | - --vl->val.i; | |
634 | - } | |
635 | - if (vasn->flag & INTEGER) | |
636 | - setint_v(vasn, vl, es->arith); | |
637 | - else | |
638 | - setint(vasn, vl->val.i); | |
639 | - if (!is_prefix) | |
640 | - /* undo the increment/decrement */ | |
641 | - vl->val.i = oval; | |
642 | - | |
643 | - return (vl); | |
644 | -} | |
645 | - | |
646 | 710 | static void |
647 | 711 | assign_check(Expr_state *es, enum token op, struct tbl *vasn) |
648 | 712 | { |
@@ -833,129 +897,6 @@ utf_wctomb(char *dst, unsigned int wc) | ||
833 | 897 | return ((char *)d - dst); |
834 | 898 | } |
835 | 899 | |
836 | - | |
837 | -#ifndef MKSH_mirbsd_wcwidth | |
838 | -/* --- begin of wcwidth.c excerpt --- */ | |
839 | -/*- | |
840 | - * Markus Kuhn -- 2007-05-26 (Unicode 5.0) | |
841 | - * | |
842 | - * Permission to use, copy, modify, and distribute this software | |
843 | - * for any purpose and without fee is hereby granted. The author | |
844 | - * disclaims all warranties with regard to this software. | |
845 | - */ | |
846 | - | |
847 | -__RCSID("$miros: src/lib/libc/i18n/wcwidth.c,v 1.11 2012/09/01 23:46:43 tg Exp $"); | |
848 | - | |
849 | -int | |
850 | -utf_wcwidth(unsigned int c) | |
851 | -{ | |
852 | - static const struct cbset { | |
853 | - unsigned short first; | |
854 | - unsigned short last; | |
855 | - } comb[] = { | |
856 | - /* Unicode 6.1.0 BMP */ | |
857 | - { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD }, | |
858 | - { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 }, | |
859 | - { 0x05C7, 0x05C7 }, { 0x0600, 0x0604 }, { 0x0610, 0x061A }, | |
860 | - { 0x064B, 0x065F }, { 0x0670, 0x0670 }, { 0x06D6, 0x06DD }, | |
861 | - { 0x06DF, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, | |
862 | - { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, | |
863 | - { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0816, 0x0819 }, | |
864 | - { 0x081B, 0x0823 }, { 0x0825, 0x0827 }, { 0x0829, 0x082D }, | |
865 | - { 0x0859, 0x085B }, { 0x08E4, 0x08FE }, { 0x0900, 0x0902 }, | |
866 | - { 0x093A, 0x093A }, { 0x093C, 0x093C }, { 0x0941, 0x0948 }, | |
867 | - { 0x094D, 0x094D }, { 0x0951, 0x0957 }, { 0x0962, 0x0963 }, | |
868 | - { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, | |
869 | - { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, | |
870 | - { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, | |
871 | - { 0x0A4B, 0x0A4D }, { 0x0A51, 0x0A51 }, { 0x0A70, 0x0A71 }, | |
872 | - { 0x0A75, 0x0A75 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, | |
873 | - { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, | |
874 | - { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, | |
875 | - { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B44 }, { 0x0B4D, 0x0B4D }, | |
876 | - { 0x0B56, 0x0B56 }, { 0x0B62, 0x0B63 }, { 0x0B82, 0x0B82 }, | |
877 | - { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, | |
878 | - { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, | |
879 | - { 0x0C62, 0x0C63 }, { 0x0CBC, 0x0CBC }, { 0x0CBF, 0x0CBF }, | |
880 | - { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, { 0x0CE2, 0x0CE3 }, | |
881 | - { 0x0D41, 0x0D44 }, { 0x0D4D, 0x0D4D }, { 0x0D62, 0x0D63 }, | |
882 | - { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, | |
883 | - { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, | |
884 | - { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, | |
885 | - { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, | |
886 | - { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, | |
887 | - { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F8D, 0x0F97 }, | |
888 | - { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, | |
889 | - { 0x1032, 0x1037 }, { 0x1039, 0x103A }, { 0x103D, 0x103E }, | |
890 | - { 0x1058, 0x1059 }, { 0x105E, 0x1060 }, { 0x1071, 0x1074 }, | |
891 | - { 0x1082, 0x1082 }, { 0x1085, 0x1086 }, { 0x108D, 0x108D }, | |
892 | - { 0x109D, 0x109D }, { 0x1160, 0x11FF }, { 0x135D, 0x135F }, | |
893 | - { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, | |
894 | - { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, | |
895 | - { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, | |
896 | - { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, | |
897 | - { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, | |
898 | - { 0x1A17, 0x1A18 }, { 0x1A56, 0x1A56 }, { 0x1A58, 0x1A5E }, | |
899 | - { 0x1A60, 0x1A60 }, { 0x1A62, 0x1A62 }, { 0x1A65, 0x1A6C }, | |
900 | - { 0x1A73, 0x1A7C }, { 0x1A7F, 0x1A7F }, { 0x1B00, 0x1B03 }, | |
901 | - { 0x1B34, 0x1B34 }, { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, | |
902 | - { 0x1B42, 0x1B42 }, { 0x1B6B, 0x1B73 }, { 0x1B80, 0x1B81 }, | |
903 | - { 0x1BA2, 0x1BA5 }, { 0x1BA8, 0x1BA9 }, { 0x1BAB, 0x1BAB }, | |
904 | - { 0x1BE6, 0x1BE6 }, { 0x1BE8, 0x1BE9 }, { 0x1BED, 0x1BED }, | |
905 | - { 0x1BEF, 0x1BF1 }, { 0x1C2C, 0x1C33 }, { 0x1C36, 0x1C37 }, | |
906 | - { 0x1CD0, 0x1CD2 }, { 0x1CD4, 0x1CE0 }, { 0x1CE2, 0x1CE8 }, | |
907 | - { 0x1CED, 0x1CED }, { 0x1CF4, 0x1CF4 }, { 0x1DC0, 0x1DE6 }, | |
908 | - { 0x1DFC, 0x1DFF }, { 0x200B, 0x200F }, { 0x202A, 0x202E }, | |
909 | - { 0x2060, 0x2064 }, { 0x206A, 0x206F }, { 0x20D0, 0x20F0 }, | |
910 | - { 0x2CEF, 0x2CF1 }, { 0x2D7F, 0x2D7F }, { 0x2DE0, 0x2DFF }, | |
911 | - { 0x302A, 0x302D }, { 0x3099, 0x309A }, { 0xA66F, 0xA672 }, | |
912 | - { 0xA674, 0xA67D }, { 0xA69F, 0xA69F }, { 0xA6F0, 0xA6F1 }, | |
913 | - { 0xA802, 0xA802 }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, | |
914 | - { 0xA825, 0xA826 }, { 0xA8C4, 0xA8C4 }, { 0xA8E0, 0xA8F1 }, | |
915 | - { 0xA926, 0xA92D }, { 0xA947, 0xA951 }, { 0xA980, 0xA982 }, | |
916 | - { 0xA9B3, 0xA9B3 }, { 0xA9B6, 0xA9B9 }, { 0xA9BC, 0xA9BC }, | |
917 | - { 0xAA29, 0xAA2E }, { 0xAA31, 0xAA32 }, { 0xAA35, 0xAA36 }, | |
918 | - { 0xAA43, 0xAA43 }, { 0xAA4C, 0xAA4C }, { 0xAAB0, 0xAAB0 }, | |
919 | - { 0xAAB2, 0xAAB4 }, { 0xAAB7, 0xAAB8 }, { 0xAABE, 0xAABF }, | |
920 | - { 0xAAC1, 0xAAC1 }, { 0xAAEC, 0xAAED }, { 0xAAF6, 0xAAF6 }, | |
921 | - { 0xABE5, 0xABE5 }, { 0xABE8, 0xABE8 }, { 0xABED, 0xABED }, | |
922 | - { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE26 }, | |
923 | - { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB } | |
924 | - }; | |
925 | - size_t min = 0, mid, max = NELEM(comb) - 1; | |
926 | - | |
927 | - /* test for 8-bit control characters */ | |
928 | - if (c < 32 || (c >= 0x7F && c < 0xA0)) | |
929 | - return (c ? -1 : 0); | |
930 | - | |
931 | - /* binary search in table of non-spacing characters */ | |
932 | - if (c >= comb[0].first && c <= comb[max].last) | |
933 | - while (max >= min) { | |
934 | - mid = (min + max) / 2; | |
935 | - if (c > comb[mid].last) | |
936 | - min = mid + 1; | |
937 | - else if (c < comb[mid].first) | |
938 | - max = mid - 1; | |
939 | - else | |
940 | - return (0); | |
941 | - } | |
942 | - | |
943 | - /* if we arrive here, c is not a combining or C0/C1 control char */ | |
944 | - | |
945 | - return ((c >= 0x1100 && ( | |
946 | - c <= 0x115F || /* Hangul Jamo init. consonants */ | |
947 | - c == 0x2329 || c == 0x232A || | |
948 | - (c >= 0x2E80 && c <= 0xA4CF && c != 0x303F) || /* CJK ... Yi */ | |
949 | - (c >= 0xAC00 && c <= 0xD7A3) || /* Hangul Syllables */ | |
950 | - (c >= 0xF900 && c <= 0xFAFF) || /* CJK Compatibility Ideographs */ | |
951 | - (c >= 0xFE10 && c <= 0xFE19) || /* Vertical forms */ | |
952 | - (c >= 0xFE30 && c <= 0xFE6F) || /* CJK Compatibility Forms */ | |
953 | - (c >= 0xFF00 && c <= 0xFF60) || /* Fullwidth Forms */ | |
954 | - (c >= 0xFFE0 && c <= 0xFFE6))) ? 2 : 1); | |
955 | -} | |
956 | -/* --- end of wcwidth.c excerpt --- */ | |
957 | -#endif | |
958 | - | |
959 | 900 | /* |
960 | 901 | * Wrapper around access(2) because it says root can execute everything |
961 | 902 | * on some operating systems. Does not set errno, no user needs it. Use |
@@ -974,3 +915,277 @@ ksh_access(const char *fn, int mode) | ||
974 | 915 | |
975 | 916 | return (rv); |
976 | 917 | } |
918 | + | |
919 | +#ifndef MKSH_mirbsd_wcwidth | |
920 | +/* From: X11/xc/programs/xterm/wcwidth.c,v 1.6 2013/05/31 23:27:09 tg Exp $ */ | |
921 | + | |
922 | +struct mb_ucsrange { | |
923 | + unsigned short beg; | |
924 | + unsigned short end; | |
925 | +}; | |
926 | + | |
927 | +static int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems, | |
928 | + unsigned int val); | |
929 | + | |
930 | +/* | |
931 | + * Generated by MirOS: contrib/code/Snippets/eawparse,v 1.1 2013/05/31 23:27:16 tg Exp $ | |
932 | + * from Unicode 6.2.0 | |
933 | + */ | |
934 | + | |
935 | +static const struct mb_ucsrange mb_ucs_combining[] = { | |
936 | + { 0x0300, 0x036F }, | |
937 | + { 0x0483, 0x0489 }, | |
938 | + { 0x0591, 0x05BD }, | |
939 | + { 0x05BF, 0x05BF }, | |
940 | + { 0x05C1, 0x05C2 }, | |
941 | + { 0x05C4, 0x05C5 }, | |
942 | + { 0x05C7, 0x05C7 }, | |
943 | + { 0x0600, 0x0604 }, | |
944 | + { 0x0610, 0x061A }, | |
945 | + { 0x064B, 0x065F }, | |
946 | + { 0x0670, 0x0670 }, | |
947 | + { 0x06D6, 0x06DD }, | |
948 | + { 0x06DF, 0x06E4 }, | |
949 | + { 0x06E7, 0x06E8 }, | |
950 | + { 0x06EA, 0x06ED }, | |
951 | + { 0x070F, 0x070F }, | |
952 | + { 0x0711, 0x0711 }, | |
953 | + { 0x0730, 0x074A }, | |
954 | + { 0x07A6, 0x07B0 }, | |
955 | + { 0x07EB, 0x07F3 }, | |
956 | + { 0x0816, 0x0819 }, | |
957 | + { 0x081B, 0x0823 }, | |
958 | + { 0x0825, 0x0827 }, | |
959 | + { 0x0829, 0x082D }, | |
960 | + { 0x0859, 0x085B }, | |
961 | + { 0x08E4, 0x08FE }, | |
962 | + { 0x0900, 0x0902 }, | |
963 | + { 0x093A, 0x093A }, | |
964 | + { 0x093C, 0x093C }, | |
965 | + { 0x0941, 0x0948 }, | |
966 | + { 0x094D, 0x094D }, | |
967 | + { 0x0951, 0x0957 }, | |
968 | + { 0x0962, 0x0963 }, | |
969 | + { 0x0981, 0x0981 }, | |
970 | + { 0x09BC, 0x09BC }, | |
971 | + { 0x09C1, 0x09C4 }, | |
972 | + { 0x09CD, 0x09CD }, | |
973 | + { 0x09E2, 0x09E3 }, | |
974 | + { 0x0A01, 0x0A02 }, | |
975 | + { 0x0A3C, 0x0A3C }, | |
976 | + { 0x0A41, 0x0A42 }, | |
977 | + { 0x0A47, 0x0A48 }, | |
978 | + { 0x0A4B, 0x0A4D }, | |
979 | + { 0x0A51, 0x0A51 }, | |
980 | + { 0x0A70, 0x0A71 }, | |
981 | + { 0x0A75, 0x0A75 }, | |
982 | + { 0x0A81, 0x0A82 }, | |
983 | + { 0x0ABC, 0x0ABC }, | |
984 | + { 0x0AC1, 0x0AC5 }, | |
985 | + { 0x0AC7, 0x0AC8 }, | |
986 | + { 0x0ACD, 0x0ACD }, | |
987 | + { 0x0AE2, 0x0AE3 }, | |
988 | + { 0x0B01, 0x0B01 }, | |
989 | + { 0x0B3C, 0x0B3C }, | |
990 | + { 0x0B3F, 0x0B3F }, | |
991 | + { 0x0B41, 0x0B44 }, | |
992 | + { 0x0B4D, 0x0B4D }, | |
993 | + { 0x0B56, 0x0B56 }, | |
994 | + { 0x0B62, 0x0B63 }, | |
995 | + { 0x0B82, 0x0B82 }, | |
996 | + { 0x0BC0, 0x0BC0 }, | |
997 | + { 0x0BCD, 0x0BCD }, | |
998 | + { 0x0C3E, 0x0C40 }, | |
999 | + { 0x0C46, 0x0C48 }, | |
1000 | + { 0x0C4A, 0x0C4D }, | |
1001 | + { 0x0C55, 0x0C56 }, | |
1002 | + { 0x0C62, 0x0C63 }, | |
1003 | + { 0x0CBC, 0x0CBC }, | |
1004 | + { 0x0CBF, 0x0CBF }, | |
1005 | + { 0x0CC6, 0x0CC6 }, | |
1006 | + { 0x0CCC, 0x0CCD }, | |
1007 | + { 0x0CE2, 0x0CE3 }, | |
1008 | + { 0x0D41, 0x0D44 }, | |
1009 | + { 0x0D4D, 0x0D4D }, | |
1010 | + { 0x0D62, 0x0D63 }, | |
1011 | + { 0x0DCA, 0x0DCA }, | |
1012 | + { 0x0DD2, 0x0DD4 }, | |
1013 | + { 0x0DD6, 0x0DD6 }, | |
1014 | + { 0x0E31, 0x0E31 }, | |
1015 | + { 0x0E34, 0x0E3A }, | |
1016 | + { 0x0E47, 0x0E4E }, | |
1017 | + { 0x0EB1, 0x0EB1 }, | |
1018 | + { 0x0EB4, 0x0EB9 }, | |
1019 | + { 0x0EBB, 0x0EBC }, | |
1020 | + { 0x0EC8, 0x0ECD }, | |
1021 | + { 0x0F18, 0x0F19 }, | |
1022 | + { 0x0F35, 0x0F35 }, | |
1023 | + { 0x0F37, 0x0F37 }, | |
1024 | + { 0x0F39, 0x0F39 }, | |
1025 | + { 0x0F71, 0x0F7E }, | |
1026 | + { 0x0F80, 0x0F84 }, | |
1027 | + { 0x0F86, 0x0F87 }, | |
1028 | + { 0x0F8D, 0x0F97 }, | |
1029 | + { 0x0F99, 0x0FBC }, | |
1030 | + { 0x0FC6, 0x0FC6 }, | |
1031 | + { 0x102D, 0x1030 }, | |
1032 | + { 0x1032, 0x1037 }, | |
1033 | + { 0x1039, 0x103A }, | |
1034 | + { 0x103D, 0x103E }, | |
1035 | + { 0x1058, 0x1059 }, | |
1036 | + { 0x105E, 0x1060 }, | |
1037 | + { 0x1071, 0x1074 }, | |
1038 | + { 0x1082, 0x1082 }, | |
1039 | + { 0x1085, 0x1086 }, | |
1040 | + { 0x108D, 0x108D }, | |
1041 | + { 0x109D, 0x109D }, | |
1042 | + { 0x1160, 0x11FF }, | |
1043 | + { 0x135D, 0x135F }, | |
1044 | + { 0x1712, 0x1714 }, | |
1045 | + { 0x1732, 0x1734 }, | |
1046 | + { 0x1752, 0x1753 }, | |
1047 | + { 0x1772, 0x1773 }, | |
1048 | + { 0x17B4, 0x17B5 }, | |
1049 | + { 0x17B7, 0x17BD }, | |
1050 | + { 0x17C6, 0x17C6 }, | |
1051 | + { 0x17C9, 0x17D3 }, | |
1052 | + { 0x17DD, 0x17DD }, | |
1053 | + { 0x180B, 0x180D }, | |
1054 | + { 0x18A9, 0x18A9 }, | |
1055 | + { 0x1920, 0x1922 }, | |
1056 | + { 0x1927, 0x1928 }, | |
1057 | + { 0x1932, 0x1932 }, | |
1058 | + { 0x1939, 0x193B }, | |
1059 | + { 0x1A17, 0x1A18 }, | |
1060 | + { 0x1A56, 0x1A56 }, | |
1061 | + { 0x1A58, 0x1A5E }, | |
1062 | + { 0x1A60, 0x1A60 }, | |
1063 | + { 0x1A62, 0x1A62 }, | |
1064 | + { 0x1A65, 0x1A6C }, | |
1065 | + { 0x1A73, 0x1A7C }, | |
1066 | + { 0x1A7F, 0x1A7F }, | |
1067 | + { 0x1B00, 0x1B03 }, | |
1068 | + { 0x1B34, 0x1B34 }, | |
1069 | + { 0x1B36, 0x1B3A }, | |
1070 | + { 0x1B3C, 0x1B3C }, | |
1071 | + { 0x1B42, 0x1B42 }, | |
1072 | + { 0x1B6B, 0x1B73 }, | |
1073 | + { 0x1B80, 0x1B81 }, | |
1074 | + { 0x1BA2, 0x1BA5 }, | |
1075 | + { 0x1BA8, 0x1BA9 }, | |
1076 | + { 0x1BAB, 0x1BAB }, | |
1077 | + { 0x1BE6, 0x1BE6 }, | |
1078 | + { 0x1BE8, 0x1BE9 }, | |
1079 | + { 0x1BED, 0x1BED }, | |
1080 | + { 0x1BEF, 0x1BF1 }, | |
1081 | + { 0x1C2C, 0x1C33 }, | |
1082 | + { 0x1C36, 0x1C37 }, | |
1083 | + { 0x1CD0, 0x1CD2 }, | |
1084 | + { 0x1CD4, 0x1CE0 }, | |
1085 | + { 0x1CE2, 0x1CE8 }, | |
1086 | + { 0x1CED, 0x1CED }, | |
1087 | + { 0x1CF4, 0x1CF4 }, | |
1088 | + { 0x1DC0, 0x1DE6 }, | |
1089 | + { 0x1DFC, 0x1DFF }, | |
1090 | + { 0x200B, 0x200F }, | |
1091 | + { 0x202A, 0x202E }, | |
1092 | + { 0x2060, 0x2064 }, | |
1093 | + { 0x206A, 0x206F }, | |
1094 | + { 0x20D0, 0x20F0 }, | |
1095 | + { 0x2CEF, 0x2CF1 }, | |
1096 | + { 0x2D7F, 0x2D7F }, | |
1097 | + { 0x2DE0, 0x2DFF }, | |
1098 | + { 0x302A, 0x302D }, | |
1099 | + { 0x3099, 0x309A }, | |
1100 | + { 0xA66F, 0xA672 }, | |
1101 | + { 0xA674, 0xA67D }, | |
1102 | + { 0xA69F, 0xA69F }, | |
1103 | + { 0xA6F0, 0xA6F1 }, | |
1104 | + { 0xA802, 0xA802 }, | |
1105 | + { 0xA806, 0xA806 }, | |
1106 | + { 0xA80B, 0xA80B }, | |
1107 | + { 0xA825, 0xA826 }, | |
1108 | + { 0xA8C4, 0xA8C4 }, | |
1109 | + { 0xA8E0, 0xA8F1 }, | |
1110 | + { 0xA926, 0xA92D }, | |
1111 | + { 0xA947, 0xA951 }, | |
1112 | + { 0xA980, 0xA982 }, | |
1113 | + { 0xA9B3, 0xA9B3 }, | |
1114 | + { 0xA9B6, 0xA9B9 }, | |
1115 | + { 0xA9BC, 0xA9BC }, | |
1116 | + { 0xAA29, 0xAA2E }, | |
1117 | + { 0xAA31, 0xAA32 }, | |
1118 | + { 0xAA35, 0xAA36 }, | |
1119 | + { 0xAA43, 0xAA43 }, | |
1120 | + { 0xAA4C, 0xAA4C }, | |
1121 | + { 0xAAB0, 0xAAB0 }, | |
1122 | + { 0xAAB2, 0xAAB4 }, | |
1123 | + { 0xAAB7, 0xAAB8 }, | |
1124 | + { 0xAABE, 0xAABF }, | |
1125 | + { 0xAAC1, 0xAAC1 }, | |
1126 | + { 0xAAEC, 0xAAED }, | |
1127 | + { 0xAAF6, 0xAAF6 }, | |
1128 | + { 0xABE5, 0xABE5 }, | |
1129 | + { 0xABE8, 0xABE8 }, | |
1130 | + { 0xABED, 0xABED }, | |
1131 | + { 0xFB1E, 0xFB1E }, | |
1132 | + { 0xFE00, 0xFE0F }, | |
1133 | + { 0xFE20, 0xFE26 }, | |
1134 | + { 0xFEFF, 0xFEFF }, | |
1135 | + { 0xFFF9, 0xFFFB } | |
1136 | +}; | |
1137 | + | |
1138 | +static const struct mb_ucsrange mb_ucs_fullwidth[] = { | |
1139 | + { 0x1100, 0x115F }, | |
1140 | + { 0x2329, 0x232A }, | |
1141 | + { 0x2E80, 0x303E }, | |
1142 | + { 0x3040, 0xA4CF }, | |
1143 | + { 0xA960, 0xA97F }, | |
1144 | + { 0xAC00, 0xD7A3 }, | |
1145 | + { 0xF900, 0xFAFF }, | |
1146 | + { 0xFE10, 0xFE19 }, | |
1147 | + { 0xFE30, 0xFE6F }, | |
1148 | + { 0xFF00, 0xFF60 }, | |
1149 | + { 0xFFE0, 0xFFE6 } | |
1150 | +}; | |
1151 | + | |
1152 | +/* simple binary search in ranges, with bounds optimisation */ | |
1153 | +static int | |
1154 | +mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems, unsigned int val) | |
1155 | +{ | |
1156 | + size_t min = 0, mid, max = elems; | |
1157 | + | |
1158 | + if (val < arr[min].beg || val > arr[max - 1].end) | |
1159 | + return (0); | |
1160 | + | |
1161 | + while (min < max) { | |
1162 | + mid = (min + max) / 2; | |
1163 | + | |
1164 | + if (val < arr[mid].beg) | |
1165 | + max = mid; | |
1166 | + else if (val > arr[mid].end) | |
1167 | + min = mid + 1; | |
1168 | + else | |
1169 | + return (1); | |
1170 | + } | |
1171 | + return (0); | |
1172 | +} | |
1173 | + | |
1174 | +/* Unix column width of a wide character (Unicode code point, really) */ | |
1175 | +int | |
1176 | +utf_wcwidth(unsigned int wc) | |
1177 | +{ | |
1178 | + /* except NUL, C0/C1 control characters and DEL yield -1 */ | |
1179 | + if (wc < 0x20 || (wc >= 0x7F && wc < 0xA0)) | |
1180 | + return (wc ? -1 : 0); | |
1181 | + | |
1182 | + /* combining characters use 0 screen columns */ | |
1183 | + if (mb_ucsbsearch(mb_ucs_combining, NELEM(mb_ucs_combining), wc)) | |
1184 | + return (0); | |
1185 | + | |
1186 | + /* all others use 1 or 2 screen columns */ | |
1187 | + if (mb_ucsbsearch(mb_ucs_fullwidth, NELEM(mb_ucs_fullwidth), wc)) | |
1188 | + return (2); | |
1189 | + return (1); | |
1190 | +} | |
1191 | +#endif |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* $OpenBSD: c_ksh.c,v 1.33 2009/02/07 14:03:24 kili Exp $ */ |
2 | -/* $OpenBSD: c_sh.c,v 1.41 2010/03/27 09:10:01 jmc Exp $ */ | |
2 | +/* $OpenBSD: c_sh.c,v 1.43 2013/04/19 17:39:45 deraadt Exp $ */ | |
3 | 3 | /* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */ |
4 | 4 | /* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */ |
5 | 5 |
@@ -38,7 +38,7 @@ | ||
38 | 38 | #endif |
39 | 39 | #endif |
40 | 40 | |
41 | -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.238 2013/02/18 22:47:32 tg Exp $"); | |
41 | +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.244 2013/06/03 22:28:32 tg Exp $"); | |
42 | 42 | |
43 | 43 | #if HAVE_KILLPG |
44 | 44 | /* |
@@ -84,70 +84,69 @@ c_false(const char **wp MKSH_A_UNUSED) | ||
84 | 84 | } |
85 | 85 | |
86 | 86 | /* |
87 | - * A leading = means assignments before command are kept; | |
88 | - * a leading * means a POSIX special builtin; | |
89 | - * a leading + means a POSIX regular builtin | |
90 | - * (* and + should not be combined). | |
87 | + * A leading = means assignments before command are kept. | |
88 | + * A leading * means a POSIX special builtin. | |
91 | 89 | */ |
92 | 90 | const struct builtin mkshbuiltins[] = { |
93 | 91 | {"*=.", c_dot}, |
94 | 92 | {"*=:", c_true}, |
95 | 93 | {"[", c_test}, |
94 | + /* no =: AT&T manual wrong */ | |
95 | + {Talias, c_alias}, | |
96 | 96 | {"*=break", c_brkcont}, |
97 | 97 | {Tgbuiltin, c_builtin}, |
98 | + {"cat", c_cat}, | |
99 | + {"cd", c_cd}, | |
100 | + /* dash compatibility hack */ | |
101 | + {"chdir", c_cd}, | |
102 | + {"command", c_command}, | |
98 | 103 | {"*=continue", c_brkcont}, |
104 | + {"echo", c_print}, | |
99 | 105 | {"*=eval", c_eval}, |
100 | 106 | {"*=exec", c_exec}, |
101 | 107 | {"*=exit", c_exitreturn}, |
102 | - {"+false", c_false}, | |
103 | - {"*=return", c_exitreturn}, | |
104 | - {Tsgset, c_set}, | |
105 | - {"*=shift", c_shift}, | |
106 | - {"=times", c_times}, | |
107 | - {"*=trap", c_trap}, | |
108 | - {"+=wait", c_wait}, | |
109 | - {"+read", c_read}, | |
110 | - {"test", c_test}, | |
111 | - {"+true", c_true}, | |
112 | - {"ulimit", c_ulimit}, | |
113 | - {"+umask", c_umask}, | |
114 | - {Tsgunset, c_unset}, | |
115 | - /* no =: AT&T manual wrong */ | |
116 | - {Tpalias, c_alias}, | |
117 | - {"+cd", c_cd}, | |
118 | - /* dash compatibility hack */ | |
119 | - {"chdir", c_cd}, | |
120 | - {"+command", c_command}, | |
121 | - {"echo", c_print}, | |
122 | 108 | {Tsgexport, c_typeset}, |
123 | - {"+fc", c_fc}, | |
124 | - {"+getopts", c_getopts}, | |
109 | + {"false", c_false}, | |
110 | + {"fc", c_fc}, | |
111 | + {"getopts", c_getopts}, | |
125 | 112 | {"=global", c_typeset}, |
126 | - {"+jobs", c_jobs}, | |
127 | - {"+kill", c_kill}, | |
113 | + {"jobs", c_jobs}, | |
114 | + {"kill", c_kill}, | |
128 | 115 | {"let", c_let}, |
116 | + {"let]", c_let}, | |
129 | 117 | {"print", c_print}, |
130 | -#ifdef MKSH_PRINTF_BUILTIN | |
131 | - {"printf", c_printf}, | |
132 | -#endif | |
133 | 118 | {"pwd", c_pwd}, |
119 | + {"read", c_read}, | |
134 | 120 | {Tsgreadonly, c_typeset}, |
121 | + {"realpath", c_realpath}, | |
122 | + {"rename", c_rename}, | |
123 | + {"*=return", c_exitreturn}, | |
124 | + {Tsgset, c_set}, | |
125 | + {"*=shift", c_shift}, | |
126 | + {"test", c_test}, | |
127 | + {"*=times", c_times}, | |
128 | + {"*=trap", c_trap}, | |
129 | + {"true", c_true}, | |
135 | 130 | {T_typeset, c_typeset}, |
136 | - {Tpunalias, c_unalias}, | |
131 | + {"ulimit", c_ulimit}, | |
132 | + {"umask", c_umask}, | |
133 | + {Tunalias, c_unalias}, | |
134 | + {Tsgunset, c_unset}, | |
135 | + {"=wait", c_wait}, | |
137 | 136 | {"whence", c_whence}, |
138 | 137 | #ifndef MKSH_UNEMPLOYED |
139 | - {"+bg", c_fgbg}, | |
140 | - {"+fg", c_fgbg}, | |
138 | + {"bg", c_fgbg}, | |
139 | + {"fg", c_fgbg}, | |
141 | 140 | #endif |
142 | 141 | #ifndef MKSH_NO_CMDLINE_EDITING |
143 | 142 | {"bind", c_bind}, |
144 | 143 | #endif |
145 | - {"cat", c_cat}, | |
146 | 144 | #if HAVE_MKNOD |
147 | 145 | {"mknod", c_mknod}, |
148 | 146 | #endif |
149 | - {"realpath", c_realpath}, | |
150 | - {"rename", c_rename}, | |
147 | +#ifdef MKSH_PRINTF_BUILTIN | |
148 | + {"printf", c_printf}, | |
149 | +#endif | |
151 | 150 | #if HAVE_SELECT |
152 | 151 | {"sleep", c_sleep}, |
153 | 152 | #endif |
@@ -836,7 +835,7 @@ c_typeset(const char **wp) | ||
836 | 835 | shf_putc('\n', shl_stdout); |
837 | 836 | } |
838 | 837 | } else if (!typeset(wp[i], fset, fclr, field, base)) { |
839 | - bi_errorf("%s: %s", wp[i], "not identifier"); | |
838 | + bi_errorf("%s: %s", wp[i], "is not an identifier"); | |
840 | 839 | goto errout; |
841 | 840 | } |
842 | 841 | } |
@@ -2253,7 +2252,7 @@ c_trap(const char **wp) | ||
2253 | 2252 | wp += builtin_opt.optind; |
2254 | 2253 | |
2255 | 2254 | if (*wp == NULL) { |
2256 | - for (p = sigtraps, i = NSIG+1; --i >= 0; p++) | |
2255 | + for (p = sigtraps, i = NSIG + 1; --i >= 0; p++) | |
2257 | 2256 | if (p->trap != NULL) { |
2258 | 2257 | shf_puts("trap -- ", shl_stdout); |
2259 | 2258 | print_value_quoted(shl_stdout, p->trap); |
@@ -2427,12 +2426,13 @@ c_set(const char **wp) | ||
2427 | 2426 | * which assumes the exit value set will be that of the $() |
2428 | 2427 | * (subst_exstat is cleared in execute() so that it will be 0 |
2429 | 2428 | * if there are no command substitutions). |
2430 | - * Switched ksh (!posix !sh) to POSIX in mksh R39b. | |
2431 | 2429 | */ |
2432 | 2430 | #ifdef MKSH_LEGACY_MODE |
2433 | - return (subst_exstat); | |
2431 | + /* traditional behaviour, unless set -o posix */ | |
2432 | + return (Flag(FPOSIX) ? 0 : subst_exstat); | |
2434 | 2433 | #else |
2435 | - return (Flag(FSH) ? subst_exstat : 0); | |
2434 | + /* conformant behaviour, unless set -o sh +o posix */ | |
2435 | + return (Flag(FSH) && !Flag(FPOSIX) ? subst_exstat : 0); | |
2436 | 2436 | #endif |
2437 | 2437 | } |
2438 | 2438 |
@@ -3726,7 +3726,7 @@ c_cat(const char **wp) | ||
3726 | 3726 | rv = 0; |
3727 | 3727 | |
3728 | 3728 | if ((buf = malloc_osfunc(MKSH_CAT_BUFSIZ)) == NULL) { |
3729 | - bi_errorf(Toomem, (unsigned long)MKSH_CAT_BUFSIZ); | |
3729 | + bi_errorf(Toomem, (size_t)MKSH_CAT_BUFSIZ); | |
3730 | 3730 | return (1); |
3731 | 3731 | } |
3732 | 3732 |
@@ -1,7 +1,8 @@ | ||
1 | -/* $OpenBSD: jobs.c,v 1.38 2009/12/12 04:28:44 deraadt Exp $ */ | |
1 | +/* $OpenBSD: jobs.c,v 1.39 2009/12/13 04:36:48 deraadt Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | - * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 | |
4 | + * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, | |
5 | + * 2012, 2013 | |
5 | 6 | * Thorsten Glaser <tg@mirbsd.org> |
6 | 7 | * |
7 | 8 | * Provided that these terms and disclaimer and all copyright notices |
@@ -22,7 +23,7 @@ | ||
22 | 23 | |
23 | 24 | #include "sh.h" |
24 | 25 | |
25 | -__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.94 2012/12/28 02:28:36 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.100 2013/07/26 20:33:23 tg Exp $"); | |
26 | 27 | |
27 | 28 | #if HAVE_KILLPG |
28 | 29 | #define mksh_killpg killpg |
@@ -44,12 +45,11 @@ struct proc { | ||
44 | 45 | int state; |
45 | 46 | int status; /* wait status */ |
46 | 47 | /* process command string from vistree */ |
47 | - char command[64 - (ALLOC_SIZE + sizeof(Proc *) + sizeof(pid_t) + | |
48 | + char command[256 - (ALLOC_SIZE + sizeof(Proc *) + sizeof(pid_t) + | |
48 | 49 | 2 * sizeof(int))]; |
49 | 50 | }; |
50 | 51 | |
51 | 52 | /* Notify/print flag - j_print() argument */ |
52 | -#define JP_NONE 0 /* don't print anything */ | |
53 | 53 | #define JP_SHORT 1 /* print signals processes were killed by */ |
54 | 54 | #define JP_MEDIUM 2 /* print [job-num] -/+ command */ |
55 | 55 | #define JP_LONG 3 /* print [job-num] -/+ pid command */ |
@@ -102,17 +102,14 @@ struct job { | ||
102 | 102 | #define JW_PIPEST 0x08 /* want PIPESTATUS */ |
103 | 103 | |
104 | 104 | /* Error codes for j_lookup() */ |
105 | -#define JL_OK 0 | |
106 | -#define JL_NOSUCH 1 /* no such job */ | |
107 | -#define JL_AMBIG 2 /* %foo or %?foo is ambiguous */ | |
108 | -#define JL_INVALID 3 /* non-pid, non-% job id */ | |
105 | +#define JL_NOSUCH 0 /* no such job */ | |
106 | +#define JL_AMBIG 1 /* %foo or %?foo is ambiguous */ | |
107 | +#define JL_INVALID 2 /* non-pid, non-% job id */ | |
109 | 108 | |
110 | 109 | static const char * const lookup_msgs[] = { |
111 | - null, | |
112 | 110 | "no such job", |
113 | 111 | "ambiguous", |
114 | - "argument must be %job or process id", | |
115 | - NULL | |
112 | + "argument must be %job or process id" | |
116 | 113 | }; |
117 | 114 | |
118 | 115 | static Job *job_list; /* job list */ |
@@ -463,7 +460,7 @@ exchild(struct op *t, int flags, | ||
463 | 460 | forksleep <<= 1; |
464 | 461 | } |
465 | 462 | /* ensure $RANDOM changes between parent and child */ |
466 | - rndset((long)cldpid); | |
463 | + rndset((unsigned long)cldpid); | |
467 | 464 | /* fork failed? */ |
468 | 465 | if (cldpid < 0) { |
469 | 466 | kill_job(j, SIGKILL); |
@@ -506,9 +503,6 @@ exchild(struct op *t, int flags, | ||
506 | 503 | /* Do this before restoring signal */ |
507 | 504 | if (flags & XCOPROC) |
508 | 505 | coproc_cleanup(false); |
509 | -#ifndef MKSH_NOPROSPECTOFWORK | |
510 | - sigprocmask(SIG_SETMASK, &omask, NULL); | |
511 | -#endif | |
512 | 506 | cleanup_parents_env(); |
513 | 507 | #ifndef MKSH_UNEMPLOYED |
514 | 508 | /* |
@@ -543,6 +537,10 @@ exchild(struct op *t, int flags, | ||
543 | 537 | } |
544 | 538 | /* in case of $(jobs) command */ |
545 | 539 | remove_job(j, "child"); |
540 | +#ifndef MKSH_NOPROSPECTOFWORK | |
541 | + /* remove_job needs SIGCHLD blocked still */ | |
542 | + sigprocmask(SIG_SETMASK, &omask, NULL); | |
543 | +#endif | |
546 | 544 | nzombie = 0; |
547 | 545 | #ifndef MKSH_UNEMPLOYED |
548 | 546 | ttypgrp_ok = false; |
@@ -906,7 +904,7 @@ j_jobs(const char *cp, int slp, | ||
906 | 904 | zflag = 1; |
907 | 905 | } |
908 | 906 | if (cp) { |
909 | - int ecode; | |
907 | + int ecode; | |
910 | 908 | |
911 | 909 | if ((j = j_lookup(cp, &ecode)) == NULL) { |
912 | 910 | #ifndef MKSH_NOPROSPECTOFWORK |
@@ -1220,6 +1218,8 @@ j_waitj(Job *j, | ||
1220 | 1218 | ARRAY | INT_U | AINDEX; |
1221 | 1219 | got_array: |
1222 | 1220 | vp->val.i = proc_errorlevel(p); |
1221 | + if (Flag(FPIPEFAIL) && vp->val.i) | |
1222 | + rv = vp->val.i; | |
1223 | 1223 | p = p->next; |
1224 | 1224 | } |
1225 | 1225 | } |
@@ -1251,8 +1251,7 @@ j_waitj(Job *j, | ||
1251 | 1251 | static void |
1252 | 1252 | j_sigchld(int sig MKSH_A_UNUSED) |
1253 | 1253 | { |
1254 | - /* this runs inside interrupt context, with errno saved */ | |
1255 | - | |
1254 | + int saved_errno = errno; | |
1256 | 1255 | Job *j; |
1257 | 1256 | Proc *p = NULL; |
1258 | 1257 | pid_t pid; |
@@ -1340,7 +1339,7 @@ j_sigchld(int sig MKSH_A_UNUSED) | ||
1340 | 1339 | #ifdef MKSH_NO_SIGSUSPEND |
1341 | 1340 | sigprocmask(SIG_SETMASK, &omask, NULL); |
1342 | 1341 | #endif |
1343 | - /* nothing */; | |
1342 | + errno = saved_errno; | |
1344 | 1343 | } |
1345 | 1344 | |
1346 | 1345 | /* |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /*- |
2 | - * Copyright (c) 2009, 2010, 2011 | |
2 | + * Copyright (c) 2009, 2010, 2011, 2013 | |
3 | 3 | * Thorsten Glaser <tg@mirbsd.org> |
4 | 4 | * |
5 | 5 | * Provided that these terms and disclaimer and all copyright notices |
@@ -20,7 +20,7 @@ | ||
20 | 20 | |
21 | 21 | #include "sh.h" |
22 | 22 | |
23 | -__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.19 2011/09/07 15:24:16 tg Exp $"); | |
23 | +__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20 2013/06/03 22:28:33 tg Exp $"); | |
24 | 24 | |
25 | 25 | /* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */ |
26 | 26 | #if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0) |
@@ -100,7 +100,7 @@ aresize(void *ptr, size_t numb, Area *ap) | ||
100 | 100 | || ALLOC_ISUNALIGNED(lp) |
101 | 101 | #endif |
102 | 102 | ) |
103 | - internal_errorf(Toomem, (unsigned long)numb); | |
103 | + internal_errorf(Toomem, numb); | |
104 | 104 | /* this only works because Area is an ALLOC_ITEM */ |
105 | 105 | lp->next = ap->next; |
106 | 106 | ap->next = lp; |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: lex.c,v 1.46 2013/01/20 14:47:46 stsp Exp $ */ | |
1 | +/* $OpenBSD: lex.c,v 1.47 2013/03/03 19:11:34 guenther Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
@@ -23,7 +23,7 @@ | ||
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
26 | -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.182 2013/02/19 18:45:20 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.188 2013/08/10 13:44:31 tg Exp $"); | |
27 | 27 | |
28 | 28 | /* |
29 | 29 | * states while lexing word |
@@ -102,8 +102,6 @@ static void gethere(bool); | ||
102 | 102 | static Lex_state *push_state_i(State_info *, Lex_state *); |
103 | 103 | static Lex_state *pop_state_i(State_info *, Lex_state *); |
104 | 104 | |
105 | -static int dopprompt(const char *, int, bool); | |
106 | - | |
107 | 105 | static int backslash_skip; |
108 | 106 | static int ignore_backslash_newline; |
109 | 107 |
@@ -338,7 +336,9 @@ yylex(int cf) | ||
338 | 336 | } |
339 | 337 | break; |
340 | 338 | case '\'': |
341 | - open_ssquote: | |
339 | + open_ssquote_unless_heredoc: | |
340 | + if ((cf & HEREDOC)) | |
341 | + goto store_char; | |
342 | 342 | *wp++ = OQUOTE; |
343 | 343 | ignore_backslash_newline++; |
344 | 344 | PUSH_STATE(SSQUOTE); |
@@ -421,8 +421,14 @@ yylex(int cf) | ||
421 | 421 | wp += cz; |
422 | 422 | } |
423 | 423 | } else if (c == '{') /*}*/ { |
424 | - c = getsc(); | |
425 | - if (ctype(c, C_IFSWS)) { | |
424 | + if ((c = getsc()) == '|') { | |
425 | + /* | |
426 | + * non-subenvironment | |
427 | + * value substitution | |
428 | + */ | |
429 | + c = VALSUB; | |
430 | + goto subst_command2; | |
431 | + } else if (ctype(c, C_IFSWS)) { | |
426 | 432 | /* |
427 | 433 | * non-subenvironment |
428 | 434 | * "command" substitution |
@@ -495,7 +501,8 @@ yylex(int cf) | ||
495 | 501 | PUSH_STATE(STBRACEKORN); |
496 | 502 | } else { |
497 | 503 | ungetsc(c); |
498 | - if (state == SDQUOTE) | |
504 | + if (state == SDQUOTE || | |
505 | + state == SQBRACE) | |
499 | 506 | PUSH_STATE(SQBRACE); |
500 | 507 | else |
501 | 508 | PUSH_STATE(SBRACE); |
@@ -616,6 +623,8 @@ yylex(int cf) | ||
616 | 623 | case SSQUOTE: |
617 | 624 | if (c == '\'') { |
618 | 625 | POP_STATE(); |
626 | + if ((cf & HEREDOC) || state == SQBRACE) | |
627 | + goto store_char; | |
619 | 628 | *wp++ = CQUOTE; |
620 | 629 | ignore_backslash_newline--; |
621 | 630 | } else { |
@@ -693,7 +702,7 @@ yylex(int cf) | ||
693 | 702 | |
694 | 703 | case SBRACE: |
695 | 704 | if (c == '\'') |
696 | - goto open_ssquote; | |
705 | + goto open_ssquote_unless_heredoc; | |
697 | 706 | else if (c == '\\') |
698 | 707 | goto getsc_qchar; |
699 | 708 | common_SQBRACE: |
@@ -812,7 +821,7 @@ yylex(int cf) | ||
812 | 821 | } |
813 | 822 | break; |
814 | 823 | case '\'': |
815 | - goto open_ssquote; | |
824 | + goto open_ssquote_unless_heredoc; | |
816 | 825 | case '$': |
817 | 826 | if ((c2 = getsc()) == '\'') { |
818 | 827 | open_sequote: |
@@ -898,7 +907,11 @@ yylex(int cf) | ||
898 | 907 | state = SBASE; |
899 | 908 | |
900 | 909 | dp = Xstring(ws, wp); |
901 | - if ((c == '<' || c == '>' || c == '&') && state == SBASE) { | |
910 | + if (state == SBASE && ( | |
911 | +#ifndef MKSH_LEGACY_MODE | |
912 | + (c == '&' && !Flag(FSH) && !Flag(FPOSIX)) || | |
913 | +#endif | |
914 | + c == '<' || c == '>')) { | |
902 | 915 | struct ioword *iop = alloc(sizeof(struct ioword), ATEMP); |
903 | 916 | |
904 | 917 | if (Xlength(ws, wp) == 0) |
@@ -1374,7 +1387,7 @@ getsc_line(Source *s) | ||
1374 | 1387 | Flag(FEMACS) || Flag(FGMACS))) { |
1375 | 1388 | int nread; |
1376 | 1389 | |
1377 | - nread = x_read(xp, LINE); | |
1390 | + nread = x_read(xp); | |
1378 | 1391 | if (nread < 0) |
1379 | 1392 | /* read error */ |
1380 | 1393 | nread = 0; |
@@ -1505,8 +1518,8 @@ set_prompt(int to, Source *s) | ||
1505 | 1518 | } |
1506 | 1519 | } |
1507 | 1520 | |
1508 | -static int | |
1509 | -dopprompt(const char *cp, int ntruncate, bool doprint) | |
1521 | +int | |
1522 | +pprompt(const char *cp, int ntruncate) | |
1510 | 1523 | { |
1511 | 1524 | int columns = 0, lines = 0; |
1512 | 1525 | bool indelimit = false; |
@@ -1539,35 +1552,21 @@ dopprompt(const char *cp, int ntruncate, bool doprint) | ||
1539 | 1552 | else if (UTFMODE && ((unsigned char)*cp > 0x7F)) { |
1540 | 1553 | const char *cp2; |
1541 | 1554 | columns += utf_widthadj(cp, &cp2); |
1542 | - if (doprint && (indelimit || | |
1543 | - (ntruncate < (x_cols * lines + columns)))) | |
1555 | + if (indelimit || | |
1556 | + (ntruncate < (x_cols * lines + columns))) | |
1544 | 1557 | shf_write(cp, cp2 - cp, shl_out); |
1545 | 1558 | cp = cp2 - /* loop increment */ 1; |
1546 | 1559 | continue; |
1547 | 1560 | } else |
1548 | 1561 | columns++; |
1549 | - if (doprint && (*cp != delimiter) && | |
1562 | + if ((*cp != delimiter) && | |
1550 | 1563 | (indelimit || (ntruncate < (x_cols * lines + columns)))) |
1551 | 1564 | shf_putc(*cp, shl_out); |
1552 | 1565 | } |
1553 | - if (doprint) | |
1554 | - shf_flush(shl_out); | |
1566 | + shf_flush(shl_out); | |
1555 | 1567 | return (x_cols * lines + columns); |
1556 | 1568 | } |
1557 | 1569 | |
1558 | - | |
1559 | -void | |
1560 | -pprompt(const char *cp, int ntruncate) | |
1561 | -{ | |
1562 | - dopprompt(cp, ntruncate, true); | |
1563 | -} | |
1564 | - | |
1565 | -int | |
1566 | -promptlen(const char *cp) | |
1567 | -{ | |
1568 | - return (dopprompt(cp, 0, false)); | |
1569 | -} | |
1570 | - | |
1571 | 1570 | /* |
1572 | 1571 | * Read the variable part of a ${...} expression (i.e. up to but not |
1573 | 1572 | * including the :[-+?=#%] or close-brace). |
@@ -0,0 +1,297 @@ | ||
1 | +.\" $MirOS: src/bin/mksh/lksh.1,v 1.5 2013/05/22 18:18:06 tg Exp $ | |
2 | +.\"- | |
3 | +.\" Copyright (c) 2008, 2009, 2010, 2012, 2013 | |
4 | +.\" Thorsten “mirabilos” Glaser <tg@mirbsd.org> | |
5 | +.\" | |
6 | +.\" Provided that these terms and disclaimer and all copyright notices | |
7 | +.\" are retained or reproduced in an accompanying document, permission | |
8 | +.\" is granted to deal in this work without restriction, including un‐ | |
9 | +.\" limited rights to use, publicly perform, distribute, sell, modify, | |
10 | +.\" merge, give away, or sublicence. | |
11 | +.\" | |
12 | +.\" This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to | |
13 | +.\" the utmost extent permitted by applicable law, neither express nor | |
14 | +.\" implied; without malicious intent or gross negligence. In no event | |
15 | +.\" may a licensor, author or contributor be held liable for indirect, | |
16 | +.\" direct, other damage, loss, or other issues arising in any way out | |
17 | +.\" of dealing in the work, even if advised of the possibility of such | |
18 | +.\" damage or existence of a defect, except proven that it results out | |
19 | +.\" of said person’s immediate fault when using the work as intended. | |
20 | +.\"- | |
21 | +.\" Try to make GNU groff and AT&T nroff more compatible | |
22 | +.\" * ` generates ‘ in gnroff, so use \` | |
23 | +.\" * ' generates ’ in gnroff, \' generates ´, so use \*(aq | |
24 | +.\" * - generates ‐ in gnroff, \- generates −, so .tr it to - | |
25 | +.\" thus use - for hyphens and \- for minus signs and option dashes | |
26 | +.\" * ~ is size-reduced and placed atop in groff, so use \*(TI | |
27 | +.\" * ^ is size-reduced and placed atop in groff, so use \*(ha | |
28 | +.\" * \(en does not work in nroff, so use \*(en | |
29 | +.\" * <>| are problematic, so redefine and use \*(Lt\*(Gt\*(Ba | |
30 | +.\" Also make sure to use \& especially with two-letter words. | |
31 | +.\" The section after the "doc" macropackage has been loaded contains | |
32 | +.\" additional code to convene between the UCB mdoc macropackage (and | |
33 | +.\" its variant as BSD mdoc in groff) and the GNU mdoc macropackage. | |
34 | +.\" | |
35 | +.ie \n(.g \{\ | |
36 | +. if \*[.T]ascii .tr \-\N'45' | |
37 | +. if \*[.T]latin1 .tr \-\N'45' | |
38 | +. if \*[.T]utf8 .tr \-\N'45' | |
39 | +. ds <= \[<=] | |
40 | +. ds >= \[>=] | |
41 | +. ds Rq \[rq] | |
42 | +. ds Lq \[lq] | |
43 | +. ds sL \(aq | |
44 | +. ds sR \(aq | |
45 | +. if \*[.T]utf8 .ds sL ` | |
46 | +. if \*[.T]ps .ds sL ` | |
47 | +. if \*[.T]utf8 .ds sR ' | |
48 | +. if \*[.T]ps .ds sR ' | |
49 | +. ds aq \(aq | |
50 | +. ds TI \(ti | |
51 | +. ds ha \(ha | |
52 | +. ds en \(en | |
53 | +.\} | |
54 | +.el \{\ | |
55 | +. ds aq ' | |
56 | +. ds TI ~ | |
57 | +. ds ha ^ | |
58 | +. ds en \(em | |
59 | +.\} | |
60 | +.\" | |
61 | +.\" Implement .Dd with the Mdocdate RCS keyword | |
62 | +.\" | |
63 | +.rn Dd xD | |
64 | +.de Dd | |
65 | +.ie \\$1$Mdocdate: \{\ | |
66 | +. xD \\$2 \\$3, \\$4 | |
67 | +.\} | |
68 | +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 | |
69 | +.. | |
70 | +.\" | |
71 | +.\" .Dd must come before definition of .Mx, because when called | |
72 | +.\" with -mandoc, it might implement .Mx itself, but we want to | |
73 | +.\" use our own definition. And .Dd must come *first*, always. | |
74 | +.\" | |
75 | +.Dd $Mdocdate: May 22 2013 $ | |
76 | +.\" | |
77 | +.\" Check which macro package we use, and do other -mdoc setup. | |
78 | +.\" | |
79 | +.ie \n(.g \{\ | |
80 | +. if \*[.T]utf8 .tr \[la]\*(Lt | |
81 | +. if \*[.T]utf8 .tr \[ra]\*(Gt | |
82 | +. ie d volume-ds-1 .ds tT gnu | |
83 | +. el .ds tT bsd | |
84 | +.\} | |
85 | +.el .ds tT ucb | |
86 | +.\" | |
87 | +.\" Implement .Mx (MirBSD) | |
88 | +.\" | |
89 | +.ie "\*(tT"gnu" \{\ | |
90 | +. eo | |
91 | +. de Mx | |
92 | +. nr curr-font \n[.f] | |
93 | +. nr curr-size \n[.ps] | |
94 | +. ds str-Mx \f[\n[curr-font]]\s[\n[curr-size]u] | |
95 | +. ds str-Mx1 \*[Tn-font-size]\%MirOS\*[str-Mx] | |
96 | +. if !\n[arg-limit] \ | |
97 | +. if \n[.$] \{\ | |
98 | +. ds macro-name Mx | |
99 | +. parse-args \$@ | |
100 | +. \} | |
101 | +. if (\n[arg-limit] > \n[arg-ptr]) \{\ | |
102 | +. nr arg-ptr +1 | |
103 | +. ie (\n[type\n[arg-ptr]] == 2) \ | |
104 | +. as str-Mx1 \~\*[arg\n[arg-ptr]] | |
105 | +. el \ | |
106 | +. nr arg-ptr -1 | |
107 | +. \} | |
108 | +. ds arg\n[arg-ptr] "\*[str-Mx1] | |
109 | +. nr type\n[arg-ptr] 2 | |
110 | +. ds space\n[arg-ptr] "\*[space] | |
111 | +. nr num-args (\n[arg-limit] - \n[arg-ptr]) | |
112 | +. nr arg-limit \n[arg-ptr] | |
113 | +. if \n[num-args] \ | |
114 | +. parse-space-vector | |
115 | +. print-recursive | |
116 | +.. | |
117 | +. ec | |
118 | +. ds sP \s0 | |
119 | +. ds tN \*[Tn-font-size] | |
120 | +.\} | |
121 | +.el \{\ | |
122 | +. de Mx | |
123 | +. nr cF \\n(.f | |
124 | +. nr cZ \\n(.s | |
125 | +. ds aa \&\f\\n(cF\s\\n(cZ | |
126 | +. if \\n(aC==0 \{\ | |
127 | +. ie \\n(.$==0 \&MirOS\\*(aa | |
128 | +. el .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 | |
129 | +. \} | |
130 | +. if \\n(aC>\\n(aP \{\ | |
131 | +. nr aP \\n(aP+1 | |
132 | +. ie \\n(C\\n(aP==2 \{\ | |
133 | +. as b1 \&MirOS\ #\&\\*(A\\n(aP\\*(aa | |
134 | +. ie \\n(aC>\\n(aP \{\ | |
135 | +. nr aP \\n(aP+1 | |
136 | +. nR | |
137 | +. \} | |
138 | +. el .aZ | |
139 | +. \} | |
140 | +. el \{\ | |
141 | +. as b1 \&MirOS\\*(aa | |
142 | +. nR | |
143 | +. \} | |
144 | +. \} | |
145 | +.. | |
146 | +.\} | |
147 | +.\"- | |
148 | +.Dt LKSH 1 | |
149 | +.Os MirBSD | |
150 | +.Sh NAME | |
151 | +.Nm lksh | |
152 | +.Nd Legacy Korn shell built on mksh | |
153 | +.Sh SYNOPSIS | |
154 | +.Nm | |
155 | +.Bk -words | |
156 | +.Op Fl +abCefhiklmnprUuvXx | |
157 | +.Op Fl +o Ar opt | |
158 | +.Oo | |
159 | +.Fl c Ar string \*(Ba | |
160 | +.Fl s \*(Ba | |
161 | +.Ar file | |
162 | +.Op Ar args ... | |
163 | +.Oc | |
164 | +.Ek | |
165 | +.Sh DESCRIPTION | |
166 | +.Nm | |
167 | +is a command interpreter intended exclusively for running legacy | |
168 | +shell scripts. | |
169 | +It is built on | |
170 | +.Nm mksh ; | |
171 | +refer to its manual page for details on the scripting language. | |
172 | +It is recommended to port scripts to | |
173 | +.Nm mksh | |
174 | +instead of relying on legacy or idiotic POSIX-mandated behaviour, | |
175 | +since the MirBSD Korn Shell scripting language is much more consistent. | |
176 | +.Sh LEGACY MODE | |
177 | +.Nm | |
178 | +has the following differences from | |
179 | +.Nm mksh : | |
180 | +.Bl -bullet | |
181 | +.It | |
182 | +There is no explicit support for interactive use, | |
183 | +nor any command line editing or history code. | |
184 | +Hence, | |
185 | +.Nm | |
186 | +is not suitable as a user's login shell, either; use | |
187 | +.Nm mksh | |
188 | +instead. | |
189 | +.It | |
190 | +The | |
191 | +.Ev KSH_VERSION | |
192 | +string identifies | |
193 | +.Nm | |
194 | +as | |
195 | +.Dq LEGACY KSH | |
196 | +instead of | |
197 | +.Dq MIRBSD KSH . | |
198 | +.It | |
199 | +.Nm | |
200 | +only offers the traditional ten file descriptors to scripts. | |
201 | +.It | |
202 | +.Nm | |
203 | +uses | |
204 | +.Tn POSIX | |
205 | +arithmetics, which has quite a few implications: | |
206 | +The data type for arithmetics is the host ISO C | |
207 | +.Vt long | |
208 | +data type. | |
209 | +Signed integer wraparound is Undefined Behaviour. | |
210 | +The sign of the result of a modulo operation with at least one | |
211 | +negative operand is unspecified. | |
212 | +Shift operations on negative numbers are unspecified. | |
213 | +Division of the largest negative number by \-1 is Undefined Behaviour. | |
214 | +The compiler is permitted to delete all data and crash the system | |
215 | +if Undefined Behaviour occurs. | |
216 | +.It | |
217 | +The rotation arithmetic operators are not available. | |
218 | +.It | |
219 | +The shift arithmetic operators take all bits of the second operand into | |
220 | +account; if they exceed permitted precision, the result is unspecified. | |
221 | +.It | |
222 | +The | |
223 | +.Tn GNU | |
224 | +.Nm bash | |
225 | +extension &\*(Gt to redirect stdout and stderr in one go is not parsed. | |
226 | +.It | |
227 | +The | |
228 | +.Nm mksh | |
229 | +command line option | |
230 | +.Fl T | |
231 | +is not available. | |
232 | +.It | |
233 | +Unless | |
234 | +.Ic set -o posix | |
235 | +is active, | |
236 | +.Nm | |
237 | +always uses traditional mode for constructs like: | |
238 | +.Bd -literal -offset indent | |
239 | +$ set -- $(getopt ab:c "$@") | |
240 | +$ echo $? | |
241 | +.Ed | |
242 | +.Pp | |
243 | +POSIX mandates this to show 0, but traditional mode | |
244 | +passes through the errorlevel from the | |
245 | +.Xr getopt 1 | |
246 | +command. | |
247 | +.It | |
248 | +.Nm lksh , | |
249 | +unlike | |
250 | +.At | |
251 | +.Nm ksh , | |
252 | +does not keep file descriptors \*(Gt 2 private. | |
253 | +.El | |
254 | +.Sh SEE ALSO | |
255 | +.Xr mksh 1 | |
256 | +.Pp | |
257 | +.Pa https://www.mirbsd.org/mksh.htm | |
258 | +.Pp | |
259 | +.Pa https://www.mirbsd.org/ksh\-chan.htm | |
260 | +.Sh CAVEATS | |
261 | +To use | |
262 | +.Nm | |
263 | +as | |
264 | +.Pa /bin/sh , | |
265 | +compilation to enable | |
266 | +.Ic set -o posix | |
267 | +by default is highly recommended for better standards compliance. | |
268 | +.Pp | |
269 | +.Nm | |
270 | +tries to make a cross between a legacy bourne/posix compatibl-ish | |
271 | +shell and a legacy pdksh-alike but | |
272 | +.Dq legacy | |
273 | +is not exactly specified. | |
274 | +.Pp | |
275 | +The | |
276 | +.Ic set | |
277 | +built-in command does not have all options one would expect | |
278 | +from a full-blown | |
279 | +.Nm mksh | |
280 | +or | |
281 | +.Nm pdksh . | |
282 | +.Pp | |
283 | +Talk to the | |
284 | +.Mx | |
285 | +development team using the mailing list at | |
286 | +.Aq miros\-mksh@mirbsd.org | |
287 | +or the | |
288 | +.Li \&#\&!/bin/mksh | |
289 | +.Pq or Li \&#ksh | |
290 | +IRC channel at | |
291 | +.Pa irc.freenode.net | |
292 | +.Pq Port 6697 SSL, 6667 unencrypted | |
293 | +if you need any further quirks or assistance, | |
294 | +and consider migrating your legacy scripts to work with | |
295 | +.Nm mksh | |
296 | +instead of requiring | |
297 | +.Nm . |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: main.c,v 1.51 2012/09/10 01:25:30 tedu Exp $ */ | |
1 | +/* $OpenBSD: main.c,v 1.52 2013/06/15 17:25:19 millert Exp $ */ | |
2 | 2 | /* $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt Exp $ */ |
3 | 3 | /* $OpenBSD: io.c,v 1.22 2006/03/17 16:30:13 millert Exp $ */ |
4 | 4 | /* $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */ |
@@ -34,7 +34,7 @@ | ||
34 | 34 | #include <locale.h> |
35 | 35 | #endif |
36 | 36 | |
37 | -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.260 2013/02/10 21:42:16 tg Exp $"); | |
37 | +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.269 2013/07/25 18:07:46 tg Exp $"); | |
38 | 38 | |
39 | 39 | extern char **environ; |
40 | 40 |
@@ -48,6 +48,7 @@ extern char **environ; | ||
48 | 48 | |
49 | 49 | static uint8_t isuc(const char *); |
50 | 50 | static int main_init(int, const char *[], Source **, struct block **); |
51 | +uint32_t chvt_rndsetup(const void *, size_t); | |
51 | 52 | void chvt_reinit(void); |
52 | 53 | static void reclaim(void); |
53 | 54 | static void remove_temps(struct temp *); |
@@ -137,15 +138,25 @@ rndsetup(void) | ||
137 | 138 | /* introduce variation (and yes, second arg MBZ for portability) */ |
138 | 139 | mksh_TIME(bufptr->tv); |
139 | 140 | |
141 | + h = chvt_rndsetup(bufptr, sizeof(*bufptr)); | |
142 | + | |
143 | + afree(cp, APERM); | |
144 | + return ((mksh_uari_t)h); | |
145 | +} | |
146 | + | |
147 | +uint32_t | |
148 | +chvt_rndsetup(const void *bp, size_t sz) | |
149 | +{ | |
150 | + register uint32_t h; | |
151 | + | |
140 | 152 | NZATInit(h); |
141 | 153 | /* variation through pid, ppid, and the works */ |
142 | 154 | NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate)); |
143 | 155 | /* some variation, some possibly entropy, depending on OE */ |
144 | - NZATUpdateMem(h, bufptr, sizeof(*bufptr)); | |
156 | + NZATUpdateMem(h, bp, sz); | |
145 | 157 | NZAATFinish(h); |
146 | 158 | |
147 | - afree(cp, APERM); | |
148 | - return ((mksh_uari_t)h); | |
159 | + return (h); | |
149 | 160 | } |
150 | 161 | |
151 | 162 | void |
@@ -238,7 +249,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp) | ||
238 | 249 | |
239 | 250 | /* define built-in commands and see if we were called as one */ |
240 | 251 | ktinit(APERM, &builtins, |
241 | - /* currently up to 50 builtins: 75% of 128 = 2^7 */ | |
252 | + /* currently up to 51 builtins: 75% of 128 = 2^7 */ | |
242 | 253 | 7); |
243 | 254 | for (i = 0; mkshbuiltins[i].name != NULL; i++) |
244 | 255 | if (!strcmp(ccp, builtin(mkshbuiltins[i].name, |
@@ -251,11 +262,20 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp) | ||
251 | 262 | if (argi < 0) |
252 | 263 | return (1); |
253 | 264 | |
265 | +#if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED) | |
266 | + /* are we called as -sh or /bin/sh or so? */ | |
267 | + if (!strcmp(ccp, "sh")) { | |
268 | + /* either also turns off braceexpand */ | |
269 | +#ifdef MKSH_BINSHPOSIX | |
270 | + /* enable better POSIX conformance */ | |
271 | + change_flag(FPOSIX, OF_FIRSTTIME, true); | |
272 | +#endif | |
254 | 273 | #ifdef MKSH_BINSHREDUCED |
255 | - /* set FSH if we're called as -sh or /bin/sh or so */ | |
256 | - if (!strcmp(ccp, "sh")) | |
274 | + /* enable kludge/compat mode */ | |
257 | 275 | change_flag(FSH, OF_FIRSTTIME, true); |
258 | 276 | #endif |
277 | + } | |
278 | +#endif | |
259 | 279 | } |
260 | 280 | |
261 | 281 | initvar(); |
@@ -323,6 +343,11 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp) | ||
323 | 343 | */ |
324 | 344 | Flag(FBRACEEXPAND) = 1; |
325 | 345 | |
346 | + /* | |
347 | + * Turn on "set -x" inheritance by default. | |
348 | + */ | |
349 | + Flag(FXTRACEREC) = 1; | |
350 | + | |
326 | 351 | #ifndef MKSH_NO_CMDLINE_EDITING |
327 | 352 | /* |
328 | 353 | * Set edit mode to emacs by default, may be overridden |
@@ -411,7 +436,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp) | ||
411 | 436 | return (1); |
412 | 437 | } |
413 | 438 | |
414 | -#ifdef DEBUG | |
439 | +#if defined(DEBUG) && !defined(MKSH_LEGACY_MODE) | |
415 | 440 | /* test wraparound of arithmetic types */ |
416 | 441 | { |
417 | 442 | volatile long xl; |
@@ -442,7 +467,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp) | ||
442 | 467 | xc = 0; |
443 | 468 | --xc; |
444 | 469 | if ((xua2 != 2147483648UL) || |
445 | - (xl != -2147483648L) || (xul != 2147483648UL) || | |
470 | + (xl != (-2147483647L-1)) || (xul != 2147483648UL) || | |
446 | 471 | (xi != -1) || (xui != 4294967295U) || |
447 | 472 | (xa != 0) || (xua != 0) || (xc != 255)) |
448 | 473 | errorf("integer wraparound test failed"); |
@@ -889,8 +914,9 @@ unwind(int i) | ||
889 | 914 | } |
890 | 915 | |
891 | 916 | /* ordering for EXIT vs ERR is a bit odd (this is what AT&T ksh does) */ |
892 | - if (i == LEXIT || | |
893 | - ((i == LERROR || i == LINTR) && sigtraps[ksh_SIGEXIT].trap)) { | |
917 | + if (i == LEXIT || ((i == LERROR || i == LINTR) && | |
918 | + sigtraps[ksh_SIGEXIT].trap && | |
919 | + (!Flag(FTALKING) || Flag(FERREXIT)))) { | |
894 | 920 | ++trap_nested; |
895 | 921 | runtrap(&sigtraps[ksh_SIGEXIT], trap_nested == 1); |
896 | 922 | --trap_nested; |
@@ -1006,6 +1032,10 @@ quitenv(struct shf *shf) | ||
1006 | 1032 | #ifndef MKSH_NO_CMDLINE_EDITING |
1007 | 1033 | x_done(); |
1008 | 1034 | #endif |
1035 | +#ifndef MKSH_NOPROSPECTOFWORK | |
1036 | + /* block at least SIGCHLD during/after afreeall */ | |
1037 | + sigprocmask(SIG_BLOCK, &sm_sigchld, NULL); | |
1038 | +#endif | |
1009 | 1039 | afreeall(APERM); |
1010 | 1040 | for (fd = 3; fd < NUFILE; fd++) |
1011 | 1041 | if ((i = fcntl(fd, F_GETFD, 0)) != -1 && |
@@ -1364,7 +1394,7 @@ initio(void) | ||
1364 | 1394 | /* force buffer allocation */ |
1365 | 1395 | shf_fdopen(1, SHF_WR, shl_stdout); |
1366 | 1396 | shf_fdopen(2, SHF_WR, shl_out); |
1367 | - shf_fdopen(2, SHF_WR, shl_spare); | |
1397 | + shf_fdopen(2, SHF_WR, shl_xtrace); | |
1368 | 1398 | #ifdef DF |
1369 | 1399 | if ((lfp = getenv("SDMKSH_PATH")) == NULL) { |
1370 | 1400 | if ((lfp = getenv("HOME")) == NULL || *lfp != '/') |
@@ -1594,7 +1624,7 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist) | ||
1594 | 1624 | { |
1595 | 1625 | char *cp; |
1596 | 1626 | size_t len; |
1597 | - int i; | |
1627 | + int i, j; | |
1598 | 1628 | struct temp *tp; |
1599 | 1629 | const char *dir; |
1600 | 1630 | struct stat sb; |
@@ -1644,17 +1674,19 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist) | ||
1644 | 1674 | } |
1645 | 1675 | |
1646 | 1676 | if (type == TT_FUNSUB) { |
1647 | - int nfd; | |
1648 | - | |
1649 | 1677 | /* map us high and mark as close-on-exec */ |
1650 | - if ((nfd = savefd(i)) != i) { | |
1678 | + if ((j = savefd(i)) != i) { | |
1651 | 1679 | close(i); |
1652 | - i = nfd; | |
1680 | + i = j; | |
1653 | 1681 | } |
1654 | - } | |
1682 | + | |
1683 | + /* operation mode for the shf */ | |
1684 | + j = SHF_RD; | |
1685 | + } else | |
1686 | + j = SHF_WR; | |
1655 | 1687 | |
1656 | 1688 | /* shf_fdopen cannot fail, so no fd leak */ |
1657 | - tp->shf = shf_fdopen(i, SHF_WR, NULL); | |
1689 | + tp->shf = shf_fdopen(i, j, NULL); | |
1658 | 1690 | |
1659 | 1691 | maketemp_out: |
1660 | 1692 | tp->next = *tlist; |
@@ -3,7 +3,7 @@ | ||
3 | 3 | |
4 | 4 | /*- |
5 | 5 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
6 | - * 2011, 2012 | |
6 | + * 2011, 2012, 2013 | |
7 | 7 | * Thorsten Glaser <tg@mirbsd.org> |
8 | 8 | * |
9 | 9 | * Provided that these terms and disclaimer and all copyright notices |
@@ -30,7 +30,7 @@ | ||
30 | 30 | #include <grp.h> |
31 | 31 | #endif |
32 | 32 | |
33 | -__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.205 2012/12/17 23:18:08 tg Exp $"); | |
33 | +__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.214 2013/08/11 14:57:09 tg Exp $"); | |
34 | 34 | |
35 | 35 | #define KSH_CHVT_FLAG |
36 | 36 | #ifdef MKSH_SMALL |
@@ -54,7 +54,7 @@ static int do_gmatch(const unsigned char *, const unsigned char *, | ||
54 | 54 | const unsigned char *, const unsigned char *); |
55 | 55 | static const unsigned char *cclass(const unsigned char *, unsigned char); |
56 | 56 | #ifdef KSH_CHVT_CODE |
57 | -static void chvt(const char *); | |
57 | +static void chvt(const Getopt *); | |
58 | 58 | #endif |
59 | 59 | |
60 | 60 | /*XXX this should go away */ |
@@ -123,10 +123,15 @@ Xcheck_grow(XString *xsp, const char *xp, size_t more) | ||
123 | 123 | return (xsp->beg + (xp - old_beg)); |
124 | 124 | } |
125 | 125 | |
126 | + | |
126 | 127 | #define SHFLAGS_DEFNS |
127 | 128 | #include "sh_flags.h" |
128 | 129 | |
129 | -const struct shoption options[] = { | |
130 | +#define OFC(i) (options[i][-2]) | |
131 | +#define OFF(i) (((const unsigned char *)options[i])[-1]) | |
132 | +#define OFN(i) (options[i]) | |
133 | + | |
134 | +const char * const options[] = { | |
130 | 135 | #define SHFLAGS_ITEMS |
131 | 136 | #include "sh_flags.h" |
132 | 137 | }; |
@@ -137,15 +142,20 @@ const struct shoption options[] = { | ||
137 | 142 | size_t |
138 | 143 | option(const char *n) |
139 | 144 | { |
140 | - size_t i; | |
145 | + size_t i = 0; | |
141 | 146 | |
142 | - if ((n[0] == '-' || n[0] == '+') && n[1] && !n[2]) { | |
143 | - for (i = 0; i < NELEM(options); i++) | |
144 | - if (options[i].c == n[1]) | |
147 | + if ((n[0] == '-' || n[0] == '+') && n[1] && !n[2]) | |
148 | + while (i < NELEM(options)) { | |
149 | + if (OFC(i) == n[1]) | |
150 | + return (i); | |
151 | + ++i; | |
152 | + } | |
153 | + else | |
154 | + while (i < NELEM(options)) { | |
155 | + if (!strcmp(OFN(i), n)) | |
145 | 156 | return (i); |
146 | - } else for (i = 0; i < NELEM(options); i++) | |
147 | - if (options[i].name && strcmp(options[i].name, n) == 0) | |
148 | - return (i); | |
157 | + ++i; | |
158 | + } | |
149 | 159 | |
150 | 160 | return ((size_t)-1); |
151 | 161 | } |
@@ -165,7 +175,7 @@ options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) | ||
165 | 175 | const struct options_info *oi = (const struct options_info *)arg; |
166 | 176 | |
167 | 177 | shf_snprintf(buf, buflen, "%-*s %s", |
168 | - oi->opt_width, options[oi->opts[i]].name, | |
178 | + oi->opt_width, OFN(oi->opts[i]), | |
169 | 179 | Flag(oi->opts[i]) ? "on" : "off"); |
170 | 180 | return (buf); |
171 | 181 | } |
@@ -184,12 +194,11 @@ printoptions(bool verbose) | ||
184 | 194 | |
185 | 195 | oi.opt_width = 0; |
186 | 196 | while (i < NELEM(options)) { |
187 | - if (options[i].name) { | |
197 | + if ((len = strlen(OFN(i)))) { | |
188 | 198 | oi.opts[n++] = i; |
189 | - len = strlen(options[i].name); | |
190 | 199 | if (len > octs) |
191 | 200 | octs = len; |
192 | - len = utf_mbswidth(options[i].name); | |
201 | + len = utf_mbswidth(OFN(i)); | |
193 | 202 | if ((int)len > oi.opt_width) |
194 | 203 | oi.opt_width = (int)len; |
195 | 204 | } |
@@ -200,10 +209,9 @@ printoptions(bool verbose) | ||
200 | 209 | } else { |
201 | 210 | /* short version like AT&T ksh93 */ |
202 | 211 | shf_puts(Tset, shl_stdout); |
203 | - while (i < (int)NELEM(options)) { | |
204 | - if (Flag(i) && options[i].name) | |
205 | - shprintf("%s %s %s", null, "-o", | |
206 | - options[i].name); | |
212 | + while (i < NELEM(options)) { | |
213 | + if (Flag(i) && OFN(i)[0]) | |
214 | + shprintf(" -o %s", OFN(i)); | |
207 | 215 | ++i; |
208 | 216 | } |
209 | 217 | shf_putc('\n', shl_stdout); |
@@ -213,13 +221,15 @@ printoptions(bool verbose) | ||
213 | 221 | char * |
214 | 222 | getoptions(void) |
215 | 223 | { |
216 | - size_t i; | |
217 | - char m[(int)FNFLAGS + 1]; | |
224 | + size_t i = 0; | |
225 | + char c, m[(int)FNFLAGS + 1]; | |
218 | 226 | char *cp = m; |
219 | 227 | |
220 | - for (i = 0; i < NELEM(options); i++) | |
221 | - if (options[i].c && Flag(i)) | |
222 | - *cp++ = options[i].c; | |
228 | + while (i < NELEM(options)) { | |
229 | + if ((c = OFC(i)) && Flag(i)) | |
230 | + *cp++ = c; | |
231 | + ++i; | |
232 | + } | |
223 | 233 | strndupx(cp, m, cp - m, ATEMP); |
224 | 234 | return (cp); |
225 | 235 | } |
@@ -229,8 +239,12 @@ void | ||
229 | 239 | change_flag(enum sh_flag f, int what, bool newset) |
230 | 240 | { |
231 | 241 | unsigned char oldval; |
232 | - unsigned char newval; | |
242 | + unsigned char newval = (newset ? 1 : 0); | |
233 | 243 | |
244 | + if (f == FXTRACE) { | |
245 | + change_xtrace(newval, true); | |
246 | + return; | |
247 | + } | |
234 | 248 | oldval = Flag(f); |
235 | 249 | Flag(f) = newval = (newset ? 1 : 0); |
236 | 250 | #ifndef MKSH_UNEMPLOYED |
@@ -277,16 +291,46 @@ change_flag(enum sh_flag f, int what, bool newset) | ||
277 | 291 | setgid(kshegid); |
278 | 292 | #endif |
279 | 293 | } else if ((f == FPOSIX || f == FSH) && newval) { |
280 | - Flag(FPOSIX) = Flag(FSH) = Flag(FBRACEEXPAND) = 0; | |
281 | - Flag(f) = newval; | |
282 | - } | |
283 | - /* Changing interactive flag? */ | |
284 | - if (f == FTALKING) { | |
294 | + /* Turning on -o posix or -o sh? */ | |
295 | + Flag(FBRACEEXPAND) = 0; | |
296 | + } else if (f == FTALKING) { | |
297 | + /* Changing interactive flag? */ | |
285 | 298 | if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid) |
286 | 299 | Flag(FTALKING_I) = newval; |
287 | 300 | } |
288 | 301 | } |
289 | 302 | |
303 | +void | |
304 | +change_xtrace(unsigned char newval, bool dosnapshot) | |
305 | +{ | |
306 | + if (!dosnapshot && newval == Flag(FXTRACE)) | |
307 | + return; | |
308 | + | |
309 | + if (Flag(FXTRACE) == 2) { | |
310 | + shf_putc('\n', shl_xtrace); | |
311 | + Flag(FXTRACE) = 1; | |
312 | + shf_flush(shl_xtrace); | |
313 | + } | |
314 | + | |
315 | + if (!dosnapshot && Flag(FXTRACE) == 1) | |
316 | + switch (newval) { | |
317 | + case 1: | |
318 | + return; | |
319 | + case 2: | |
320 | + goto changed_xtrace; | |
321 | + } | |
322 | + | |
323 | + shf_flush(shl_xtrace); | |
324 | + if (shl_xtrace->fd != 2) | |
325 | + close(shl_xtrace->fd); | |
326 | + if (!newval || (shl_xtrace->fd = savefd(2)) == -1) | |
327 | + shl_xtrace->fd = 2; | |
328 | + | |
329 | + changed_xtrace: | |
330 | + if ((Flag(FXTRACE) = newval) == 2) | |
331 | + shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace); | |
332 | +} | |
333 | + | |
290 | 334 | /* |
291 | 335 | * Parse command line and set command arguments. Returns the index of |
292 | 336 | * non-option arguments, -1 if there is an error. |
@@ -306,10 +350,11 @@ parse_args(const char **argv, | ||
306 | 350 | size_t i; |
307 | 351 | int optc, arrayset = 0; |
308 | 352 | bool sortargs = false; |
353 | + bool fcompatseen = false; | |
309 | 354 | |
310 | 355 | /* First call? Build option strings... */ |
311 | 356 | if (cmd_opts[0] == '\0') { |
312 | - char *p = cmd_opts, *q = set_opts; | |
357 | + char ch, *p = cmd_opts, *q = set_opts; | |
313 | 358 | |
314 | 359 | /* see cmd_opts[] declaration */ |
315 | 360 | *p++ = 'o'; |
@@ -326,11 +371,11 @@ parse_args(const char **argv, | ||
326 | 371 | *q++ = 's'; |
327 | 372 | |
328 | 373 | for (i = 0; i < NELEM(options); i++) { |
329 | - if (options[i].c) { | |
330 | - if (options[i].flags & OF_CMDLINE) | |
331 | - *p++ = options[i].c; | |
332 | - if (options[i].flags & OF_SET) | |
333 | - *q++ = options[i].c; | |
374 | + if ((ch = OFC(i))) { | |
375 | + if (OFF(i) & OF_CMDLINE) | |
376 | + *p++ = ch; | |
377 | + if (OFF(i) & OF_SET) | |
378 | + *q++ = ch; | |
334 | 379 | } |
335 | 380 | } |
336 | 381 | *p = '\0'; |
@@ -379,6 +424,17 @@ parse_args(const char **argv, | ||
379 | 424 | break; |
380 | 425 | } |
381 | 426 | i = option(go.optarg); |
427 | + if ((i == FPOSIX || i == FSH) && set && !fcompatseen) { | |
428 | + /* | |
429 | + * If running 'set -o posix' or | |
430 | + * 'set -o sh', turn off the other; | |
431 | + * if running 'set -o posix -o sh' | |
432 | + * allow both to be set though. | |
433 | + */ | |
434 | + Flag(FPOSIX) = 0; | |
435 | + Flag(FSH) = 0; | |
436 | + fcompatseen = true; | |
437 | + } | |
382 | 438 | if ((i != (size_t)-1) && (set ? 1U : 0U) == Flag(i)) |
383 | 439 | /* |
384 | 440 | * Don't check the context if the flag |
@@ -387,7 +443,7 @@ parse_args(const char **argv, | ||
387 | 443 | * if the output of "set +o" is to be used. |
388 | 444 | */ |
389 | 445 | ; |
390 | - else if ((i != (size_t)-1) && (options[i].flags & what)) | |
446 | + else if ((i != (size_t)-1) && (OFF(i) & what)) | |
391 | 447 | change_flag((enum sh_flag)i, what, set); |
392 | 448 | else { |
393 | 449 | bi_errorf("%s: %s", go.optarg, "bad option"); |
@@ -403,7 +459,7 @@ parse_args(const char **argv, | ||
403 | 459 | errorf("no TIOCSCTTY ioctl"); |
404 | 460 | #else |
405 | 461 | change_flag(FTALKING, OF_CMDLINE, true); |
406 | - chvt(go.optarg); | |
462 | + chvt(&go); | |
407 | 463 | break; |
408 | 464 | #endif |
409 | 465 | #endif |
@@ -420,8 +476,8 @@ parse_args(const char **argv, | ||
420 | 476 | break; |
421 | 477 | } |
422 | 478 | for (i = 0; i < NELEM(options); i++) |
423 | - if (optc == options[i].c && | |
424 | - (what & options[i].flags)) { | |
479 | + if (optc == OFC(i) && | |
480 | + (what & OFF(i))) { | |
425 | 481 | change_flag((enum sh_flag)i, what, set); |
426 | 482 | break; |
427 | 483 | } |
@@ -433,8 +489,10 @@ parse_args(const char **argv, | ||
433 | 489 | (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') && |
434 | 490 | argv[go.optind][1] == '\0') { |
435 | 491 | /* lone - clears -v and -x flags */ |
436 | - if (argv[go.optind][0] == '-') | |
437 | - Flag(FVERBOSE) = Flag(FXTRACE) = 0; | |
492 | + if (argv[go.optind][0] == '-') { | |
493 | + Flag(FVERBOSE) = 0; | |
494 | + change_xtrace(0, false); | |
495 | + } | |
438 | 496 | /* set skips lone - or + option */ |
439 | 497 | go.optind++; |
440 | 498 | } |
@@ -472,9 +530,11 @@ int | ||
472 | 530 | getn(const char *s, int *ai) |
473 | 531 | { |
474 | 532 | char c; |
475 | - unsigned int i = 0; | |
533 | + mksh_ari_u num; | |
476 | 534 | bool neg = false; |
477 | 535 | |
536 | + num.u = 0; | |
537 | + | |
478 | 538 | do { |
479 | 539 | c = *s++; |
480 | 540 | } while (ksh_isspace(c)); |
@@ -492,18 +552,20 @@ getn(const char *s, int *ai) | ||
492 | 552 | if (!ksh_isdigit(c)) |
493 | 553 | /* not numeric */ |
494 | 554 | return (0); |
495 | - if (i > 214748364U) | |
555 | + if (num.u > 214748364U) | |
496 | 556 | /* overflow on multiplication */ |
497 | 557 | return (0); |
498 | - i = i * 10U + (unsigned int)(c - '0'); | |
499 | - /* now: i <= 2147483649U */ | |
558 | + num.u = num.u * 10U + (unsigned int)(c - '0'); | |
559 | + /* now: num.u <= 2147483649U */ | |
500 | 560 | } while ((c = *s++)); |
501 | 561 | |
502 | - if (i > (neg ? 2147483648U : 2147483647U)) | |
562 | + if (num.u > (neg ? 2147483648U : 2147483647U)) | |
503 | 563 | /* overflow for signed 32-bit int */ |
504 | 564 | return (0); |
505 | 565 | |
506 | - *ai = neg ? -(int)i : (int)i; | |
566 | + if (neg) | |
567 | + num.u = -num.u; | |
568 | + *ai = num.i; | |
507 | 569 | return (1); |
508 | 570 | } |
509 | 571 |
@@ -1206,20 +1268,19 @@ print_columns(struct shf *shf, unsigned int n, | ||
1206 | 1268 | /* if we can only print one column anyway, skip the goo */ |
1207 | 1269 | if (cols < 2) { |
1208 | 1270 | for (i = 0; i < n; ++i) |
1209 | - shf_fprintf(shf, "%s \n", | |
1271 | + shf_fprintf(shf, "%s\n", | |
1210 | 1272 | (*func)(str, max_oct, i, arg)); |
1211 | 1273 | goto out; |
1212 | 1274 | } |
1213 | 1275 | |
1214 | 1276 | rows = (n + cols - 1) / cols; |
1215 | 1277 | if (prefcol && cols > rows) { |
1216 | - i = rows; | |
1217 | - rows = cols > n ? n : cols; | |
1218 | - cols = i; | |
1278 | + cols = rows; | |
1279 | + rows = (n + cols - 1) / cols; | |
1219 | 1280 | } |
1220 | 1281 | |
1282 | + nspace = (x_cols - max_col * cols) / cols; | |
1221 | 1283 | max_col = -max_col; |
1222 | - nspace = (x_cols + max_col * cols) / cols; | |
1223 | 1284 | if (nspace <= 0) |
1224 | 1285 | nspace = 1; |
1225 | 1286 | for (r = 0; r < rows; r++) { |
@@ -1911,59 +1972,69 @@ c_cd(const char **wp) | ||
1911 | 1972 | |
1912 | 1973 | |
1913 | 1974 | #ifdef KSH_CHVT_CODE |
1975 | +extern uint32_t chvt_rndsetup(const void *, size_t); | |
1914 | 1976 | extern void chvt_reinit(void); |
1915 | 1977 | |
1916 | 1978 | static void |
1917 | -chvt(const char *fn) | |
1979 | +chvt(const Getopt *go) | |
1918 | 1980 | { |
1919 | - char dv[20]; | |
1920 | - struct stat sb; | |
1981 | + const char *dv = go->optarg; | |
1982 | + char *cp = NULL; | |
1921 | 1983 | int fd; |
1922 | 1984 | |
1923 | - if (*fn == '-') { | |
1924 | - memcpy(dv, "-/dev/null", sizeof("-/dev/null")); | |
1925 | - fn = dv + 1; | |
1926 | - } else { | |
1927 | - if (stat(fn, &sb)) { | |
1928 | - memcpy(dv, "/dev/ttyC", 9); | |
1929 | - strlcpy(dv + 9, fn, sizeof(dv) - 9); | |
1985 | + switch (*dv) { | |
1986 | + case '-': | |
1987 | + dv = "/dev/null"; | |
1988 | + break; | |
1989 | + case '!': | |
1990 | + ++dv; | |
1991 | + /* FALLTHROUGH */ | |
1992 | + default: { | |
1993 | + struct stat sb; | |
1994 | + | |
1995 | + if (stat(dv, &sb)) { | |
1996 | + cp = shf_smprintf("/dev/ttyC%s", dv); | |
1997 | + dv = cp; | |
1930 | 1998 | if (stat(dv, &sb)) { |
1931 | - strlcpy(dv + 8, fn, sizeof(dv) - 8); | |
1932 | - if (stat(dv, &sb)) | |
1933 | - errorf("%s: %s %s", "chvt", | |
1934 | - "can't find tty", fn); | |
1999 | + memmove(cp + 1, cp, /* /dev/tty */ 8); | |
2000 | + dv = cp + 1; | |
2001 | + if (stat(dv, &sb)) { | |
2002 | + errorf("%s: %s: %s", "chvt", | |
2003 | + "can't find tty", go->optarg); | |
2004 | + } | |
1935 | 2005 | } |
1936 | - fn = dv; | |
1937 | 2006 | } |
1938 | 2007 | if (!(sb.st_mode & S_IFCHR)) |
1939 | - errorf("%s %s %s", "chvt: not a char", "device", fn); | |
1940 | - if ((sb.st_uid != 0) && chown(fn, 0, 0)) | |
1941 | - warningf(false, "%s: %s %s", "chvt", "can't chown root", fn); | |
1942 | - if (((sb.st_mode & 07777) != 0600) && chmod(fn, (mode_t)0600)) | |
1943 | - warningf(false, "%s: %s %s", "chvt", "can't chmod 0600", fn); | |
2008 | + errorf("%s: %s: %s", "chvt", "not a char device", dv); | |
2009 | +#ifndef MKSH_DISABLE_REVOKE_WARNING | |
1944 | 2010 | #if HAVE_REVOKE |
1945 | - if (revoke(fn)) | |
2011 | + if (revoke(dv)) | |
1946 | 2012 | #endif |
1947 | 2013 | warningf(false, "%s: %s %s", "chvt", |
1948 | 2014 | "new shell is potentially insecure, can't revoke", |
1949 | - fn); | |
2015 | + dv); | |
2016 | +#endif | |
2017 | + } | |
1950 | 2018 | } |
1951 | - if ((fd = open(fn, O_RDWR)) < 0) { | |
2019 | + if ((fd = open(dv, O_RDWR)) < 0) { | |
1952 | 2020 | sleep(1); |
1953 | - if ((fd = open(fn, O_RDWR)) < 0) | |
1954 | - errorf("%s: %s %s", "chvt", "can't open", fn); | |
2021 | + if ((fd = open(dv, O_RDWR)) < 0) { | |
2022 | + errorf("%s: %s %s", "chvt", "can't open", dv); | |
2023 | + } | |
1955 | 2024 | } |
1956 | - switch (fork()) { | |
1957 | - case -1: | |
1958 | - errorf("%s: %s %s", "chvt", "fork", "failed"); | |
1959 | - case 0: | |
1960 | - break; | |
1961 | - default: | |
1962 | - exit(0); | |
2025 | + if (go->optarg[0] != '!') { | |
2026 | + switch (fork()) { | |
2027 | + case -1: | |
2028 | + errorf("%s: %s %s", "chvt", "fork", "failed"); | |
2029 | + case 0: | |
2030 | + break; | |
2031 | + default: | |
2032 | + exit(0); | |
2033 | + } | |
1963 | 2034 | } |
1964 | 2035 | if (setsid() == -1) |
1965 | 2036 | errorf("%s: %s %s", "chvt", "setsid", "failed"); |
1966 | - if (fn != dv + 1) { | |
2037 | + if (go->optarg[0] != '-') { | |
1967 | 2038 | if (ioctl(fd, TIOCSCTTY, NULL) == -1) |
1968 | 2039 | errorf("%s: %s %s", "chvt", "TIOCSCTTY", "failed"); |
1969 | 2040 | if (tcflush(fd, TCIOFLUSH)) |
@@ -1974,14 +2045,7 @@ chvt(const char *fn) | ||
1974 | 2045 | ksh_dup2(fd, 2, false); |
1975 | 2046 | if (fd > 2) |
1976 | 2047 | close(fd); |
1977 | - { | |
1978 | - register uint32_t h; | |
1979 | - | |
1980 | - NZATInit(h); | |
1981 | - NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate)); | |
1982 | - NZAATFinish(h); | |
1983 | - rndset((long)h); | |
1984 | - } | |
2048 | + rndset((unsigned long)chvt_rndsetup(go, sizeof(Getopt))); | |
1985 | 2049 | chvt_reinit(); |
1986 | 2050 | } |
1987 | 2051 | #endif |
@@ -1,5 +1,5 @@ | ||
1 | -.\" $MirOS: src/bin/mksh/mksh.1,v 1.305 2013/02/19 18:45:20 tg Exp $ | |
2 | -.\" $OpenBSD: ksh.1,v 1.145 2013/01/17 21:20:25 jmc Exp $ | |
1 | +.\" $MirOS: src/bin/mksh/mksh.1,v 1.320 2013/08/10 14:11:39 tg Exp $ | |
2 | +.\" $OpenBSD: ksh.1,v 1.147 2013/06/13 19:43:09 millert Exp $ | |
3 | 3 | .\"- |
4 | 4 | .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
5 | 5 | .\" 2010, 2011, 2012, 2013 |
@@ -74,7 +74,7 @@ | ||
74 | 74 | .\" with -mandoc, it might implement .Mx itself, but we want to |
75 | 75 | .\" use our own definition. And .Dd must come *first*, always. |
76 | 76 | .\" |
77 | -.Dd $Mdocdate: February 19 2013 $ | |
77 | +.Dd $Mdocdate: August 10 2013 $ | |
78 | 78 | .\" |
79 | 79 | .\" Check which macro package we use, and do other -mdoc setup. |
80 | 80 | .\" |
@@ -157,7 +157,11 @@ | ||
157 | 157 | .Nm |
158 | 158 | .Bk -words |
159 | 159 | .Op Fl +abCefhiklmnprUuvXx |
160 | -.Op Fl T Ar /dev/ttyCn \*(Ba \- | |
160 | +.Oo | |
161 | +.Fl T Oo Ar \&! Oc Ns Ar tty | |
162 | +\*(Ba | |
163 | +.Ar \&\- | |
164 | +.Oc | |
161 | 165 | .Op Fl +o Ar option |
162 | 166 | .Oo |
163 | 167 | .Fl c Ar string \*(Ba |
@@ -295,16 +299,28 @@ Redirections that create files can't be used (i.e.\& | ||
295 | 299 | .It Fl s |
296 | 300 | The shell reads commands from standard input; all non-option arguments |
297 | 301 | are positional parameters. |
298 | -.It Fl T Ar tty | |
302 | +.It Fl T Ar name | |
299 | 303 | Spawn |
300 | 304 | .Nm |
301 | 305 | on the |
302 | 306 | .Xr tty 4 |
303 | 307 | device given. |
304 | -Superuser only. | |
308 | +The paths | |
309 | +.Ar name , | |
310 | +.Pa /dev/ttyC Ns Ar name | |
311 | +and | |
312 | +.Pa /dev/tty Ns Ar name | |
313 | +are attempted in order. | |
314 | +Unless | |
315 | +.Ar name | |
316 | +begins with an exclamation mark | |
317 | +.Pq Sq \&! , | |
318 | +this is done in a subshell and returns immediately. | |
305 | 319 | If |
306 | -.Ar tty | |
307 | -is a dash, detach from controlling terminal (daemonise) instead. | |
320 | +.Ar name | |
321 | +is a dash | |
322 | +.Pq Sq \&\- , | |
323 | +detach from controlling terminal (daemonise) instead. | |
308 | 324 | .El |
309 | 325 | .Pp |
310 | 326 | In addition to the above, the options described in the |
@@ -514,7 +530,9 @@ token to form pipelines, in which the standard output of each command but the | ||
514 | 530 | last is piped (see |
515 | 531 | .Xr pipe 2 ) |
516 | 532 | to the standard input of the following command. |
517 | -The exit status of a pipeline is that of its last command. | |
533 | +The exit status of a pipeline is that of its last command, unless the | |
534 | +.Ic pipefail | |
535 | +option is set (see there). | |
518 | 536 | All commands of a pipeline are executed in separate subshells; |
519 | 537 | this is allowed by POSIX but differs from both variants of |
520 | 538 | .At |
@@ -1180,6 +1198,15 @@ work, and in that | ||
1180 | 1198 | .Ic exit |
1181 | 1199 | terminates the parent shell. |
1182 | 1200 | .Pp |
1201 | +Another variant of substitution are the valsubs (value substitutions) | |
1202 | +.Pf ${\*(Ba\& Ns Ar command Ns \&;} | |
1203 | +which are also executed in the current environment, like funsubs, but | |
1204 | +share their I/O with the parent; instead, they evaluate to whatever | |
1205 | +the, initially empty, expression-local variable | |
1206 | +.Ev REPLY | |
1207 | +is set to within the | |
1208 | +.Ar command Ns No s . | |
1209 | +.Pp | |
1183 | 1210 | If a substitution appears outside of double quotes, the results of the |
1184 | 1211 | substitution are generally subject to word or field splitting according to |
1185 | 1212 | the current value of the |
@@ -2037,6 +2064,9 @@ Parameter, command, and arithmetic substitutions are performed | ||
2037 | 2064 | before it is printed. |
2038 | 2065 | The default is |
2039 | 2066 | .Sq +\ \& . |
2067 | +You may want to set it to | |
2068 | +.Sq \&[$EPOCHREALTIME]\ \& | |
2069 | +instead, to include timestamps. | |
2040 | 2070 | .It Ev PWD |
2041 | 2071 | The current working directory. |
2042 | 2072 | May be unset or |
@@ -2431,6 +2461,13 @@ in | ||
2431 | 2461 | .Nm |
2432 | 2462 | but a syntax error in GNU |
2433 | 2463 | .Nm bash . |
2464 | +Setting the | |
2465 | +.Fl o Ar posix | |
2466 | +or | |
2467 | +.Fl o Ar sh | |
2468 | +shell options disable parsing of this redirection; | |
2469 | +it's a compatibility feature to legacy scripts, to | |
2470 | +not be used when writing new shell code. | |
2434 | 2471 | .It Xo |
2435 | 2472 | .No &\*(Gt\*(Ba Ar file , |
2436 | 2473 | .No &\*(Gt\*(Gt Ar file , |
@@ -2515,15 +2552,15 @@ Unary operators: | ||
2515 | 2552 | Binary operators: |
2516 | 2553 | .Bd -literal -offset indent |
2517 | 2554 | , |
2518 | -= *= /= %= += \-= \*(Lt\*(Lt= \*(Gt\*(Gt= &= \*(ha= \*(Ba= | |
2555 | += += \-= *= /= %= \*(Lt\*(Lt\*(Lt= \*(Gt\*(Gt\*(Gt= \*(Lt\*(Lt= \*(Gt\*(Gt= &= \*(ha= \*(Ba= | |
2519 | 2556 | \*(Ba\*(Ba |
2520 | 2557 | && |
2521 | 2558 | \*(Ba |
2522 | 2559 | \*(ha |
2523 | 2560 | & |
2524 | 2561 | == != |
2525 | -\*(Lt \*(Lt= \*(Gt= \*(Gt | |
2526 | -\*(Lt\*(Lt \*(Gt\*(Gt | |
2562 | +\*(Lt \*(Lt= \*(Gt \*(Gt= | |
2563 | +\*(Lt\*(Lt\*(Lt \*(Gt\*(Gt\*(Gt \*(Lt\*(Lt \*(Gt\*(Gt | |
2527 | 2564 | + \- |
2528 | 2565 | * / % |
2529 | 2566 | .Ed |
@@ -2553,9 +2590,14 @@ Additionally, base-16 integers may be specified by prefixing them with | ||
2553 | 2590 | in all forms of arithmetic expressions, except as numeric arguments to the |
2554 | 2591 | .Ic test |
2555 | 2592 | built-in command. |
2556 | -It is discouraged to prefix numbers with a sole zero | |
2557 | -.Pq Sq 0 , | |
2558 | -because some shells may interpret them as base-8 integers. | |
2593 | +Prefixing numbers with a sole digit zero | |
2594 | +.Pq Sq 0 | |
2595 | +leads to the shell interpreting it as base-8 integer in | |
2596 | +.Ic posix | |
2597 | +mode | |
2598 | +.Em only ; | |
2599 | +historically, (pd)ksh has never done so either anyway, | |
2600 | +and it's unsafe to do that, but POSIX demands it nowadays. | |
2559 | 2601 | As a special |
2560 | 2602 | .Nm mksh |
2561 | 2603 | extension, numbers to the base of one are treated as either (8-bit |
@@ -2609,8 +2651,8 @@ The result is the value of the expression on the right-hand side. | ||
2609 | 2651 | .It = |
2610 | 2652 | Assignment; the variable on the left is set to the value on the right. |
2611 | 2653 | .It Xo |
2612 | -.No *= /= += \-= \*(Lt\*(Lt= | |
2613 | -.No \*(Gt\*(Gt= &= \*(ha= \*(Ba= | |
2654 | +.No += \-= *= /= %= \*(Lt\*(Lt\*(Lt= \*(Gt\*(Gt\*(Gt= | |
2655 | +.No \*(Lt\*(Lt= \*(Gt\*(Gt= &= \*(ha= \*(Ba= | |
2614 | 2656 | .Xc |
2615 | 2657 | Assignment operators. |
2616 | 2658 | .Sm off |
@@ -2656,10 +2698,15 @@ Not equal; the result is 0 if both arguments are equal, 1 if not. | ||
2656 | 2698 | .It \*(Lt |
2657 | 2699 | Less than; the result is 1 if the left argument is less than the right, 0 if |
2658 | 2700 | not. |
2659 | -.It \*(Lt= \*(Gt= \*(Gt | |
2701 | +.It \*(Lt= \*(Gt \*(Gt= | |
2660 | 2702 | Less than or equal, greater than or equal, greater than. |
2661 | 2703 | See |
2662 | 2704 | .Ic \*(Lt . |
2705 | +.It \*(Lt\*(Lt\*(Lt \*(Gt\*(Gt\*(Gt | |
2706 | +Rotate left (right); the result is similar to shift (see | |
2707 | +.Ic \*(Lt\*(Lt ) | |
2708 | +except that the bits shifted out at one end are shifted in | |
2709 | +at the other end, instead of zero or sign bits. | |
2663 | 2710 | .It \*(Lt\*(Lt \*(Gt\*(Gt |
2664 | 2711 | Shift left (right); the result is the left argument with its bits shifted left |
2665 | 2712 | (right) by the amount given in the right argument. |
@@ -2668,7 +2715,6 @@ Addition, subtraction, multiplication, and division. | ||
2668 | 2715 | .It % |
2669 | 2716 | Remainder; the result is the remainder of the division of the left argument by |
2670 | 2717 | the right. |
2671 | -The sign of the result is unspecified if either argument is negative. | |
2672 | 2718 | .It Xo |
2673 | 2719 | .Sm off |
2674 | 2720 | .Aq Ar arg1 ? |
@@ -2682,6 +2728,7 @@ is non-zero, the result is | ||
2682 | 2728 | .Aq Ar arg2 ; |
2683 | 2729 | otherwise the result is |
2684 | 2730 | .Aq Ar arg3 . |
2731 | +The non-result argument is not evaluated. | |
2685 | 2732 | .El |
2686 | 2733 | .Ss Co-processes |
2687 | 2734 | A co-process (which is a pipeline created with the |
@@ -2753,8 +2800,7 @@ However, unlike | ||
2753 | 2800 | shell arguments (i.e. positional parameters $1, $2, etc.)\& |
2754 | 2801 | are never visible inside them. |
2755 | 2802 | When the shell is determining the location of a command, functions |
2756 | -are searched after special built-in commands, before regular and | |
2757 | -non-regular built-ins, and before the | |
2803 | +are searched after special built-in commands, before builtins and the | |
2758 | 2804 | .Ev PATH |
2759 | 2805 | is searched. |
2760 | 2806 | .Pp |
@@ -2868,8 +2914,8 @@ returns. | ||
2868 | 2914 | .El |
2869 | 2915 | .Ss Command execution |
2870 | 2916 | After evaluation of command-line arguments, redirections, and parameter |
2871 | -assignments, the type of command is determined: a special built-in, a | |
2872 | -function, a regular built-in, or the name of a file to execute found using the | |
2917 | +assignments, the type of command is determined: a special built-in command, | |
2918 | +a function, a normal builtin, or the name of a file to execute found using the | |
2873 | 2919 | .Ev PATH |
2874 | 2920 | parameter. |
2875 | 2921 | The checks are made in the above order. |
@@ -2885,46 +2931,30 @@ parameter is not used to find them. | ||
2885 | 2931 | The original |
2886 | 2932 | .Nm ksh |
2887 | 2933 | and POSIX differ somewhat in which commands are considered |
2888 | -special or regular: | |
2934 | +special or regular. | |
2889 | 2935 | .Pp |
2890 | -POSIX special commands | |
2936 | +POSIX special built-in utilities: | |
2891 | 2937 | .Pp |
2892 | 2938 | .Ic \&. , \&: , break , continue , |
2893 | 2939 | .Ic eval , exec , exit , export , |
2894 | 2940 | .Ic readonly , return , set , shift , |
2895 | -.Ic trap , unset , wait | |
2941 | +.Ic times , trap , unset | |
2896 | 2942 | .Pp |
2897 | 2943 | Additional |
2898 | 2944 | .Nm |
2899 | -special commands | |
2900 | -.Pp | |
2901 | -.Ic builtin , global , times , typeset | |
2902 | -.Pp | |
2903 | -Very special commands | |
2904 | -.Pq non-POSIX | |
2945 | +commands keeping assignments: | |
2905 | 2946 | .Pp |
2906 | -.Ic alias , readonly , set , typeset | |
2947 | +.Ic builtin , global , typeset , wait | |
2907 | 2948 | .Pp |
2908 | -POSIX regular commands | |
2949 | +Builtins that are not special: | |
2909 | 2950 | .Pp |
2910 | -.Ic alias , bg , cd , command , | |
2951 | +.Ic [ , alias , bg , bind , | |
2952 | +.Ic cat , cd , command , echo , | |
2911 | 2953 | .Ic false , fc , fg , getopts , |
2912 | -.Ic jobs , kill , read , true , | |
2913 | -.Ic umask , unalias | |
2914 | -.Pp | |
2915 | -Additional | |
2916 | -.Nm | |
2917 | -regular commands | |
2918 | -.Pp | |
2919 | -.Ic \&[ , chdir , bind , cat , | |
2920 | -.Ic echo , let , mknod , print , | |
2921 | -.Ic pwd , realpath , rename , sleep , | |
2922 | -.Ic test , ulimit , whence | |
2923 | -.Pp | |
2924 | -In the future, the additional | |
2925 | -.Nm | |
2926 | -special and regular commands may be treated | |
2927 | -differently from the POSIX special and regular commands. | |
2954 | +.Ic jobs , kill , let , mknod , | |
2955 | +.Ic print , pwd , read , realpath , | |
2956 | +.Ic rename , sleep , test , true , | |
2957 | +.Ic ulimit , umask , unalias , whence | |
2928 | 2958 | .Pp |
2929 | 2959 | Once the type of command has been determined, any command-line parameter |
2930 | 2960 | assignments are performed and exported for the duration of the command. |
@@ -2952,6 +2982,10 @@ those of the environment the command is used in. | ||
2952 | 2982 | The null command. |
2953 | 2983 | Exit status is set to zero. |
2954 | 2984 | .Pp |
2985 | +.It Ic \&[ Ar expression Ic \&] | |
2986 | +See | |
2987 | +.Ic test . | |
2988 | +.Pp | |
2955 | 2989 | .It Xo Ic alias |
2956 | 2990 | .Oo Fl d \*(Ba t Oo Fl r Oc \*(Ba |
2957 | 2991 | .Cm +\-x Oc |
@@ -3506,6 +3540,10 @@ resetting | ||
3506 | 3540 | .Ev OPTIND , |
3507 | 3541 | may lead to unexpected results. |
3508 | 3542 | .Pp |
3543 | +.It global Ar ... | |
3544 | +See | |
3545 | +.Ic typeset . | |
3546 | +.Pp | |
3509 | 3547 | .It Xo |
3510 | 3548 | .Ic hash |
3511 | 3549 | .Op Fl r |
@@ -3585,6 +3623,10 @@ Since expressions may need to be quoted, | ||
3585 | 3623 | is syntactic sugar for |
3586 | 3624 | .No let \&" Ns Ar expr Ns \&" . |
3587 | 3625 | .Pp |
3626 | +.It let] | |
3627 | +Internally used alias for | |
3628 | +.Ic let . | |
3629 | +.Pp | |
3588 | 3630 | .It Xo |
3589 | 3631 | .Ic mknod |
3590 | 3632 | .Op Fl m Ar mode |
@@ -4004,11 +4046,14 @@ explicitly tested by a shell construct such as | ||
4004 | 4046 | .Ic if , |
4005 | 4047 | .Ic until , |
4006 | 4048 | .Ic while , |
4007 | -.Ic && , | |
4008 | -.Ic \*(Ba\*(Ba , | |
4009 | 4049 | or |
4010 | 4050 | .Ic !\& |
4011 | 4051 | statements. |
4052 | +For | |
4053 | +.Ic && | |
4054 | +or | |
4055 | +.Ic \*(Ba\*(Ba , | |
4056 | +only the status of the last command is tested. | |
4012 | 4057 | .It Fl f \*(Ba Fl o Ic noglob |
4013 | 4058 | Do not expand file name patterns. |
4014 | 4059 | .It Fl h \*(Ba Fl o Ic trackall |
@@ -4097,7 +4142,7 @@ Mark directories with a trailing | ||
4097 | 4142 | .Ql / |
4098 | 4143 | during file name generation. |
4099 | 4144 | .It Fl x \*(Ba Fl o Ic xtrace |
4100 | -Print commands and parameter assignments when they are executed, preceded by | |
4145 | +Print command trees when they are executed, preceded by | |
4101 | 4146 | the value of |
4102 | 4147 | .Ev PS4 . |
4103 | 4148 | .It Fl o Ic bgnice |
@@ -4120,6 +4165,11 @@ must be used. | ||
4120 | 4165 | To avoid infinite loops, the shell will exit if |
4121 | 4166 | .Dv EOF |
4122 | 4167 | is read 13 times in a row. |
4168 | +.It Fl o Ic inherit\-xtrace | |
4169 | +Do not reset | |
4170 | +.Fl o Ic xtrace | |
4171 | +upon entering functions. | |
4172 | +This is enabled by default. | |
4123 | 4173 | .It Fl o Ic nohup |
4124 | 4174 | Do not kill running jobs with a |
4125 | 4175 | .Dv SIGHUP |
@@ -4162,6 +4212,9 @@ See the | ||
4162 | 4212 | and |
4163 | 4213 | .Ic pwd |
4164 | 4214 | commands above for more details. |
4215 | +.It Fl o Ic pipefail | |
4216 | +Make the exit status of a pipeline (before logically complementing) the | |
4217 | +rightmost non-zero errorlevel, or zero if all commands exited with zero. | |
4165 | 4218 | .It Fl o Ic posix |
4166 | 4219 | Enable a somewhat more |
4167 | 4220 | .Px |
@@ -6020,6 +6073,11 @@ Search for the | ||
6020 | 6073 | .Ar n Ns th |
6021 | 6074 | occurrence of the last search string; |
6022 | 6075 | the direction of the search is the opposite of the last search. |
6076 | +.It Ar ANSI-CurUp | |
6077 | +Take the characters from the beginning of the line to the current | |
6078 | +cursor position as search string and do a backwards history search | |
6079 | +for lines beginning with this string; keep the cursor position. | |
6080 | +This works only in insert mode and keeps it enabled. | |
6023 | 6081 | .El |
6024 | 6082 | .Pp |
6025 | 6083 | Edit commands |
@@ -6309,21 +6367,53 @@ all contributors, such as the Debian and OpenBSD projects. | ||
6309 | 6367 | .\" Open Source licence. |
6310 | 6368 | .\" |
6311 | 6369 | See the documentation, CVS, and web site for details. |
6370 | +.Pp | |
6371 | +The BSD daemon is Copyright \(co Marshall Kirk McKusick. | |
6372 | +The complete legalese is at: | |
6373 | +.Pa https://www.mirbsd.org/TaC\-mksh.txt | |
6374 | +.\" | |
6375 | +.\" This boils down to: feel free to use mksh.ico as application icon | |
6376 | +.\" or shortcut for mksh or mksh/Win32; distro patches are ok (but we | |
6377 | +.\" request they amend $KSH_VERSION when modifying mksh). Authors are | |
6378 | +.\" Marshall Kirk McKusick (UCB), Rick Collette (ekkoBSD), Thorsten | |
6379 | +.\" Glaser, Benny Siegert (MirBSD), Michael Langguth (mksh/Win32). | |
6380 | +.\" | |
6381 | +.\" As far as MirBSD is concerned, the files themselves are free | |
6382 | +.\" to modification and distribution under BSD/MirOS Licence, the | |
6383 | +.\" restriction on use stems only from trademark law's requirement | |
6384 | +.\" to protect it or lose it, which McKusick almost did. | |
6385 | +.\" | |
6312 | 6386 | .Sh CAVEATS |
6313 | 6387 | .Nm |
6314 | 6388 | only supports the Unicode BMP (Basic Multilingual Plane). |
6315 | -It has a different scope model from | |
6389 | +.Pp | |
6390 | +.Nm | |
6391 | +has a different scope model from | |
6316 | 6392 | .At |
6317 | 6393 | .Nm ksh , |
6318 | 6394 | which leads to subtile differences in semantics for identical builtins. |
6395 | +This can cause issues with a | |
6396 | +.Ic nameref | |
6397 | +to suddenly point to a local variable by accident; fixing this is hard. | |
6319 | 6398 | .Pp |
6320 | 6399 | The parts of a pipeline, like below, are executed in subshells. |
6321 | -Thus, variable assignments inside them fail. | |
6400 | +Thus, variable assignments inside them are not visible in the | |
6401 | +surrounding execution environment. | |
6322 | 6402 | Use co-processes instead. |
6323 | 6403 | .Bd -literal -offset indent |
6324 | 6404 | foo \*(Ba bar \*(Ba read baz # will not change $baz |
6325 | 6405 | foo \*(Ba bar \*(Ba& read \-p baz # will, however, do so |
6326 | 6406 | .Ed |
6407 | +.Pp | |
6408 | +.Nm mksh | |
6409 | +provides a consistent set of 32-bit integer arithmetics, both signed | |
6410 | +and unsigned, with defined wraparound and sign of the result of a modulo | |
6411 | +operation, even (defying POSIX) on 64-bit systems. | |
6412 | +If you require 64-bit integer arithmetics, use | |
6413 | +.Nm lksh Pq legacy mksh | |
6414 | +instead, but be aware that, in POSIX, it's legal for the OS to make | |
6415 | +.Li print $((2147483647 + 1)) | |
6416 | +delete all files on your system, as it's Undefined Behaviour. | |
6327 | 6417 | .Sh BUGS |
6328 | 6418 | Suspending (using \*(haZ) pipelines like the one below will only suspend |
6329 | 6419 | the currently running part of the pipeline; in this example, |
@@ -6335,7 +6425,7 @@ $ /bin/sleep 666 && echo fubar | ||
6335 | 6425 | .Ed |
6336 | 6426 | .Pp |
6337 | 6427 | This document attempts to describe |
6338 | -.Nm mksh\ R43 | |
6428 | +.Nm mksh\ R48 | |
6339 | 6429 | and up, |
6340 | 6430 | compiled without any options impacting functionality, such as |
6341 | 6431 | .Dv MKSH_SMALL , |
@@ -3,7 +3,7 @@ | ||
3 | 3 | /* $OpenBSD: table.h,v 1.8 2012/02/19 07:52:30 otto Exp $ */ |
4 | 4 | /* $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $ */ |
5 | 5 | /* $OpenBSD: expand.h,v 1.6 2005/03/30 17:16:37 deraadt Exp $ */ |
6 | -/* $OpenBSD: lex.h,v 1.12 2013/01/20 14:47:46 stsp Exp $ */ | |
6 | +/* $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $ */ | |
7 | 7 | /* $OpenBSD: proto.h,v 1.34 2012/06/27 07:17:19 otto Exp $ */ |
8 | 8 | /* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */ |
9 | 9 | /* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */ |
@@ -164,9 +164,9 @@ | ||
164 | 164 | #endif |
165 | 165 | |
166 | 166 | #ifdef EXTERN |
167 | -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.639 2013/02/19 18:45:22 tg Exp $"); | |
167 | +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.667 2013/08/14 20:26:19 tg Exp $"); | |
168 | 168 | #endif |
169 | -#define MKSH_VERSION "R43 2013/02/19" | |
169 | +#define MKSH_VERSION "R48 2013/08/14" | |
170 | 170 | |
171 | 171 | /* arithmetic types: C implementation */ |
172 | 172 | #if !HAVE_CAN_INTTYPES |
@@ -370,6 +370,7 @@ extern int revoke(const char *); | ||
370 | 370 | #endif |
371 | 371 | |
372 | 372 | #if defined(DEBUG) || !HAVE_STRERROR |
373 | +#undef strerror | |
373 | 374 | #define strerror /* poisoned */ dontuse_strerror |
374 | 375 | #define cstrerror /* replaced */ cstrerror |
375 | 376 | extern const char *cstrerror(int); |
@@ -415,7 +416,7 @@ extern int __cdecl setegid(gid_t); | ||
415 | 416 | |
416 | 417 | /* remove redundancies */ |
417 | 418 | |
418 | -#if defined(MirBSD) && (MirBSD >= 0x08A8) && !defined(MKSH_OPTSTATIC) | |
419 | +#if defined(MirBSD) && (MirBSD >= 0x0AB3) && !defined(MKSH_OPTSTATIC) | |
419 | 420 | #define MKSH_mirbsd_wcwidth |
420 | 421 | #define utf_wcwidth(i) wcwidth((__WCHAR_TYPE__)i) |
421 | 422 | extern int wcwidth(__WCHAR_TYPE__); |
@@ -443,8 +444,6 @@ extern int wcwidth(__WCHAR_TYPE__); | ||
443 | 444 | #define MAGIC (7) /* prefix for *?[!{,} during expand */ |
444 | 445 | #define ISMAGIC(c) ((unsigned char)(c) == MAGIC) |
445 | 446 | |
446 | -#define LINE 4096 /* input line size */ | |
447 | - | |
448 | 447 | EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ |
449 | 448 | |
450 | 449 | #ifdef MKSH_LEGACY_MODE |
@@ -471,6 +470,14 @@ union mksh_ccphack { | ||
471 | 470 | const char **ro; |
472 | 471 | }; |
473 | 472 | |
473 | +/* | |
474 | + * Evil hack since casting uint to sint is implementation-defined | |
475 | + */ | |
476 | +typedef union { | |
477 | + mksh_ari_t i; | |
478 | + mksh_uari_t u; | |
479 | +} mksh_ari_u; | |
480 | + | |
474 | 481 | /* for const debugging */ |
475 | 482 | #if defined(DEBUG) && defined(__GNUC__) && !defined(__ICC) && \ |
476 | 483 | !defined(__INTEL_COMPILER) && !defined(__SUNPRO_C) |
@@ -511,8 +518,9 @@ char *ucstrstr(char *, const char *); | ||
511 | 518 | #define mkssert(e) do { } while (/* CONSTCOND */ 0) |
512 | 519 | #endif |
513 | 520 | |
514 | -#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 431) | |
521 | +#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 481) | |
515 | 522 | #error Must run Build.sh to compile this. |
523 | +extern void thiswillneverbedefinedIhope(void); | |
516 | 524 | int |
517 | 525 | im_sorry_dave(void) |
518 | 526 | { |
@@ -763,18 +771,11 @@ EXTERN struct { | ||
763 | 771 | #define OF_FIRSTTIME 0x10 /* as early as possible, once */ |
764 | 772 | #define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL) |
765 | 773 | |
766 | -struct shoption { | |
767 | - const char *name; /* long name of option */ | |
768 | - char c; /* character flag (if any) */ | |
769 | - unsigned char flags; /* OF_* */ | |
770 | -}; | |
771 | -extern const struct shoption options[]; | |
772 | - | |
773 | 774 | /* null value for variable; comparison pointer for unset */ |
774 | 775 | EXTERN char null[] E_INIT(""); |
775 | 776 | /* helpers for string pooling */ |
776 | 777 | EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented"); |
777 | -EXTERN const char Toomem[] E_INIT("can't allocate %lu data bytes"); | |
778 | +EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes"); | |
778 | 779 | #if defined(__GNUC__) |
779 | 780 | /* trust this to have string pooling; -Wformat bitches otherwise */ |
780 | 781 | #define Tsynerr "syntax error" |
@@ -788,10 +789,8 @@ EXTERN const char Tr_fc_e_dash[] E_INIT("r=fc -e -"); | ||
788 | 789 | EXTERN const char Tlocal_typeset[] E_INIT("local=typeset"); |
789 | 790 | #define T_typeset (Tlocal_typeset + 5) /* "=typeset" */ |
790 | 791 | #define Ttypeset (Tlocal_typeset + 6) /* "typeset" */ |
791 | -EXTERN const char Tpalias[] E_INIT("+alias"); | |
792 | -#define Talias (Tpalias + 1) /* "alias" */ | |
793 | -EXTERN const char Tpunalias[] E_INIT("+unalias"); | |
794 | -#define Tunalias (Tpunalias + 1) /* "unalias" */ | |
792 | +EXTERN const char Talias[] E_INIT("alias"); | |
793 | +EXTERN const char Tunalias[] E_INIT("unalias"); | |
795 | 794 | EXTERN const char Tsgset[] E_INIT("*=set"); |
796 | 795 | #define Tset (Tsgset + 2) /* "set" */ |
797 | 796 | EXTERN const char Tsgunset[] E_INIT("*=unset"); |
@@ -830,7 +829,7 @@ struct temp { | ||
830 | 829 | * stdio and our IO routines |
831 | 830 | */ |
832 | 831 | |
833 | -#define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ | |
832 | +#define shl_xtrace (&shf_iob[0]) /* for set -x */ | |
834 | 833 | #define shl_stdout (&shf_iob[1]) |
835 | 834 | #define shl_out (&shf_iob[2]) |
836 | 835 | #ifdef DF |
@@ -984,6 +983,8 @@ EXTERN uint32_t builtin_flag; | ||
984 | 983 | /* current working directory */ |
985 | 984 | EXTERN char *current_wd; |
986 | 985 | |
986 | +/* input line size */ | |
987 | +#define LINE (4096 - ALLOC_SIZE) | |
987 | 988 | /* |
988 | 989 | * Minimum required space to work with on a line - if the prompt leaves |
989 | 990 | * less space than this on a line, the prompt is truncated. |
@@ -1151,7 +1152,6 @@ EXTERN struct tbl vtemp; | ||
1151 | 1152 | #define FDELETE BIT(10) /* function deleted while it was executing */ |
1152 | 1153 | #define FKSH BIT(11) /* function defined with function x (vs x()) */ |
1153 | 1154 | #define SPEC_BI BIT(12) /* a POSIX special builtin */ |
1154 | -#define REG_BI BIT(13) /* a POSIX regular builtin */ | |
1155 | 1155 | /* |
1156 | 1156 | * Attributes that can be set by the user (used to decide if an unset |
1157 | 1157 | * param should be repoted by set/typeset). Does not include ARRAY or |
@@ -1180,12 +1180,11 @@ EXTERN enum { | ||
1180 | 1180 | |
1181 | 1181 | /* Flags for findcom()/comexec() */ |
1182 | 1182 | #define FC_SPECBI BIT(0) /* special builtin */ |
1183 | -#define FC_FUNC BIT(1) /* function builtin */ | |
1184 | -#define FC_REGBI BIT(2) /* regular builtin */ | |
1185 | -#define FC_UNREGBI BIT(3) /* un-regular builtin (!special,!regular) */ | |
1186 | -#define FC_BI (FC_SPECBI|FC_REGBI|FC_UNREGBI) | |
1187 | -#define FC_PATH BIT(4) /* do path search */ | |
1188 | -#define FC_DEFPATH BIT(5) /* use default path in path search */ | |
1183 | +#define FC_FUNC BIT(1) /* function */ | |
1184 | +#define FC_NORMBI BIT(2) /* not special builtin */ | |
1185 | +#define FC_BI (FC_SPECBI | FC_NORMBI) | |
1186 | +#define FC_PATH BIT(3) /* do path search */ | |
1187 | +#define FC_DEFPATH BIT(4) /* use default path in path search */ | |
1189 | 1188 | |
1190 | 1189 | |
1191 | 1190 | #define AF_ARGV_ALLOC 0x1 /* argv[] array allocated */ |
@@ -1254,10 +1253,6 @@ EXTERN const char *prompt; | ||
1254 | 1253 | EXTERN int cur_prompt; /* PS1 or PS2 */ |
1255 | 1254 | EXTERN int current_lineno; /* LINENO value */ |
1256 | 1255 | |
1257 | -#define NOBLOCK ((struct op *)NULL) | |
1258 | -#define NOWORD ((char *)NULL) | |
1259 | -#define NOWORDS ((char **)NULL) | |
1260 | - | |
1261 | 1256 | /* |
1262 | 1257 | * Description of a command or an operation on commands. |
1263 | 1258 | */ |
@@ -1326,6 +1321,7 @@ struct op { | ||
1326 | 1321 | #define CPAT 11 /* close pattern: ) */ |
1327 | 1322 | #define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */ |
1328 | 1323 | #define FUNSUB 14 /* ${ foo;} substitution (NUL terminated) */ |
1324 | +#define VALSUB 15 /* ${|foo;} substitution (NUL terminated) */ | |
1329 | 1325 | |
1330 | 1326 | /* |
1331 | 1327 | * IO redirection |
@@ -1680,7 +1676,7 @@ void x_init(void); | ||
1680 | 1676 | #ifdef DEBUG_LEAKS |
1681 | 1677 | void x_done(void); |
1682 | 1678 | #endif |
1683 | -int x_read(char *, size_t); | |
1679 | +int x_read(char *); | |
1684 | 1680 | #endif |
1685 | 1681 | void x_mkraw(int, mksh_ttyst *, bool); |
1686 | 1682 | /* eval.c */ |
@@ -1834,8 +1830,7 @@ void yyerror(const char *, ...) | ||
1834 | 1830 | MKSH_A_FORMAT(__printf__, 1, 2); |
1835 | 1831 | Source *pushs(int, Area *); |
1836 | 1832 | void set_prompt(int, Source *); |
1837 | -void pprompt(const char *, int); | |
1838 | -int promptlen(const char *); | |
1833 | +int pprompt(const char *, int); | |
1839 | 1834 | /* main.c */ |
1840 | 1835 | int include(const char *, int, const char **, bool); |
1841 | 1836 | int command(const char *, int); |
@@ -1903,6 +1898,7 @@ void initctypes(void); | ||
1903 | 1898 | size_t option(const char *); |
1904 | 1899 | char *getoptions(void); |
1905 | 1900 | void change_flag(enum sh_flag, int, bool); |
1901 | +void change_xtrace(unsigned char, bool); | |
1906 | 1902 | int parse_args(const char **, int, bool *); |
1907 | 1903 | int getn(const char *, int *); |
1908 | 1904 | int gmatchx(const char *, const char *, bool); |
@@ -2011,7 +2007,7 @@ char *arrayname(const char *); | ||
2011 | 2007 | mksh_uari_t set_array(const char *, bool, const char **); |
2012 | 2008 | uint32_t hash(const void *); |
2013 | 2009 | mksh_ari_t rndget(void); |
2014 | -void rndset(long); | |
2010 | +void rndset(unsigned long); | |
2015 | 2011 | |
2016 | 2012 | enum Test_op { |
2017 | 2013 | /* non-operator */ |
@@ -1,11 +1,22 @@ | ||
1 | 1 | #if defined(SHFLAGS_DEFNS) |
2 | -__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.12 2012/06/28 20:14:17 tg Exp $"); | |
3 | -#define FN(sname,cname,ochar,flags) /* nothing */ | |
2 | +__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.16 2013/08/11 14:57:11 tg Exp $"); | |
3 | +#define FN(sname,cname,ochar,flags) \ | |
4 | + static const struct { \ | |
5 | + /* character flag (if any) */ \ | |
6 | + char c; \ | |
7 | + /* OF_* */ \ | |
8 | + unsigned char optflags; \ | |
9 | + /* long name of option */ \ | |
10 | + char name[sizeof(sname)]; \ | |
11 | + } shoptione_ ## cname = { \ | |
12 | + ochar, flags, sname \ | |
13 | + }; | |
4 | 14 | #elif defined(SHFLAGS_ENUMS) |
5 | 15 | #define FN(sname,cname,ochar,flags) cname, |
6 | 16 | #define F0(sname,cname,ochar,flags) cname = 0, |
7 | 17 | #elif defined(SHFLAGS_ITEMS) |
8 | -#define FN(sname,cname,ochar,flags) { sname, ochar, flags }, | |
18 | +#define FN(sname,cname,ochar,flags) \ | |
19 | + ((const char *)(&shoptione_ ## cname)) + 2, | |
9 | 20 | #endif |
10 | 21 | |
11 | 22 | #ifndef F0 |
@@ -45,6 +56,9 @@ FN("gmacs", FGMACS, 0, OF_ANY) | ||
45 | 56 | /* ./. reading EOF does not exit */ |
46 | 57 | FN("ignoreeof", FIGNOREEOF, 0, OF_ANY) |
47 | 58 | |
59 | +/* ./. inherit -x flag */ | |
60 | +FN("inherit-xtrace", FXTRACEREC, 0, OF_ANY) | |
61 | + | |
48 | 62 | /* -i interactive shell */ |
49 | 63 | FN("interactive", FTALKING, 'i', OF_CMDLINE) |
50 | 64 |
@@ -88,7 +102,10 @@ FN("nounset", FNOUNSET, 'u', OF_ANY) | ||
88 | 102 | /* ./. don't do logical cds/pwds (non-standard) */ |
89 | 103 | FN("physical", FPHYSICAL, 0, OF_ANY) |
90 | 104 | |
91 | -/* ./. pdksh compat: somewhat more POSIXish mode (non-standard) */ | |
105 | +/* ./. errorlevel of a pipeline is the rightmost nonzero value */ | |
106 | +FN("pipefail", FPIPEFAIL, 0, OF_ANY) | |
107 | + | |
108 | +/* ./. adhere more closely to POSIX even when undesirable */ | |
92 | 109 | FN("posix", FPOSIX, 0, OF_ANY) |
93 | 110 | |
94 | 111 | /* -p use suid_profile; privileged shell */ |
@@ -97,7 +114,7 @@ FN("privileged", FPRIVILEGED, 'p', OF_ANY) | ||
97 | 114 | /* -r restricted shell */ |
98 | 115 | FN("restricted", FRESTRICTED, 'r', OF_CMDLINE) |
99 | 116 | |
100 | -/* ./. pdksh compat: called as sh not mksh; kludge mode (non-standard) */ | |
117 | +/* ./. kludge mode for better compat with traditional sh (OS-specific) */ | |
101 | 118 | FN("sh", FSH, 0, OF_ANY) |
102 | 119 | |
103 | 120 | /* -s (invocation) parse stdin (pseudo non-standard) */ |
@@ -130,17 +147,17 @@ FN("viraw", FVIRAW, 0, OF_ANY) | ||
130 | 147 | FN("xtrace", FXTRACE, 'x', OF_ANY) |
131 | 148 | |
132 | 149 | /* -c (invocation) execute specified command */ |
133 | -FN(NULL, FCOMMAND, 'c', OF_CMDLINE) | |
150 | +FN("", FCOMMAND, 'c', OF_CMDLINE) | |
134 | 151 | |
135 | 152 | /* |
136 | 153 | * anonymous flags: used internally by shell only (not visible to user) |
137 | 154 | */ |
138 | 155 | |
139 | 156 | /* ./. direct builtin call (divined from argv[0] multi-call binary) */ |
140 | -FN(NULL, FAS_BUILTIN, 0, OF_INTERNAL) | |
157 | +FN("", FAS_BUILTIN, 0, OF_INTERNAL) | |
141 | 158 | |
142 | 159 | /* ./. (internal) initial shell was interactive */ |
143 | -FN(NULL, FTALKING_I, 0, OF_INTERNAL) | |
160 | +FN("", FTALKING_I, 0, OF_INTERNAL) | |
144 | 161 | |
145 | 162 | #undef FN |
146 | 163 | #undef F0 |
@@ -1,7 +1,8 @@ | ||
1 | -/* $OpenBSD: shf.c,v 1.15 2006/04/02 00:48:33 deraadt Exp $ */ | |
1 | +/* $OpenBSD: shf.c,v 1.16 2013/04/19 17:36:09 millert Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | - * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 | |
4 | + * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, | |
5 | + * 2012, 2013 | |
5 | 6 | * Thorsten Glaser <tg@mirbsd.org> |
6 | 7 | * |
7 | 8 | * Provided that these terms and disclaimer and all copyright notices |
@@ -24,7 +25,7 @@ | ||
24 | 25 | |
25 | 26 | #include "sh.h" |
26 | 27 | |
27 | -__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.56 2013/01/01 03:32:44 tg Exp $"); | |
28 | +__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.61 2013/07/21 18:36:03 tg Exp $"); | |
28 | 29 | |
29 | 30 | /* flags to shf_emptybuf() */ |
30 | 31 | #define EB_READSW 0x01 /* about to switch to reading */ |
@@ -51,7 +52,7 @@ shf_open(const char *name, int oflags, int mode, int sflags) | ||
51 | 52 | ssize_t bsize = |
52 | 53 | /* at most 512 */ |
53 | 54 | sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; |
54 | - int fd; | |
55 | + int fd, eno; | |
55 | 56 | |
56 | 57 | /* Done before open so if alloca fails, fd won't be lost. */ |
57 | 58 | shf = alloc(sizeof(struct shf) + bsize, ATEMP); |
@@ -63,16 +64,20 @@ shf_open(const char *name, int oflags, int mode, int sflags) | ||
63 | 64 | |
64 | 65 | fd = open(name, oflags, mode); |
65 | 66 | if (fd < 0) { |
67 | + eno = errno; | |
66 | 68 | afree(shf, shf->areap); |
69 | + errno = eno; | |
67 | 70 | return (NULL); |
68 | 71 | } |
69 | 72 | if ((sflags & SHF_MAPHI) && fd < FDBASE) { |
70 | 73 | int nfd; |
71 | 74 | |
72 | 75 | nfd = fcntl(fd, F_DUPFD, FDBASE); |
76 | + eno = errno; | |
73 | 77 | close(fd); |
74 | 78 | if (nfd < 0) { |
75 | 79 | afree(shf, shf->areap); |
80 | + errno = eno; | |
76 | 81 | return (NULL); |
77 | 82 | } |
78 | 83 | fd = nfd; |
@@ -740,8 +745,6 @@ shf_smprintf(const char *fmt, ...) | ||
740 | 745 | return (shf_sclose(&shf)); |
741 | 746 | } |
742 | 747 | |
743 | -#define BUF_SIZE 128 | |
744 | - | |
745 | 748 | #define FL_HASH 0x001 /* '#' seen */ |
746 | 749 | #define FL_PLUS 0x002 /* '+' seen */ |
747 | 750 | #define FL_RIGHT 0x004 /* '-' seen */ |
@@ -985,6 +988,10 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) | ||
985 | 988 | case 's': |
986 | 989 | if ((s = VA(const char *)) == NULL) |
987 | 990 | s = "(null)"; |
991 | + else if (flags & FL_HASH) { | |
992 | + print_value_quoted(shf, s); | |
993 | + continue; | |
994 | + } | |
988 | 995 | len = utf_mbswidth(s); |
989 | 996 | break; |
990 | 997 |
@@ -1,8 +1,8 @@ | ||
1 | -/* $OpenBSD: syn.c,v 1.28 2008/07/23 16:34:38 jaredy Exp $ */ | |
1 | +/* $OpenBSD: syn.c,v 1.29 2013/06/03 18:40:05 jca Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
5 | - * 2011, 2012 | |
5 | + * 2011, 2012, 2013 | |
6 | 6 | * Thorsten Glaser <tg@mirbsd.org> |
7 | 7 | * |
8 | 8 | * Provided that these terms and disclaimer and all copyright notices |
@@ -23,7 +23,7 @@ | ||
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
26 | -__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.88 2012/12/28 02:28:39 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.92 2013/06/03 22:28:17 tg Exp $"); | |
27 | 27 | |
28 | 28 | struct nesting_state { |
29 | 29 | int start_token; /* token than began nesting (eg, FOR) */ |
@@ -53,7 +53,7 @@ static struct op *caselist(void); | ||
53 | 53 | static struct op *casepart(int); |
54 | 54 | static struct op *function_body(char *, bool); |
55 | 55 | static char **wordlist(void); |
56 | -static struct op *block(int, struct op *, struct op *, char **); | |
56 | +static struct op *block(int, struct op *, struct op *); | |
57 | 57 | static struct op *newtp(int); |
58 | 58 | static void syntaxerr(const char *) MKSH_A_NORETURN; |
59 | 59 | static void nesting_push(struct nesting_state *, int); |
@@ -108,9 +108,9 @@ pipeline(int cf) | ||
108 | 108 | if ((p = get_command(CONTIN)) == NULL) |
109 | 109 | syntaxerr(NULL); |
110 | 110 | if (tl == NULL) |
111 | - t = tl = block(TPIPE, t, p, NOWORDS); | |
111 | + t = tl = block(TPIPE, t, p); | |
112 | 112 | else |
113 | - tl = tl->right = block(TPIPE, tl->right, p, NOWORDS); | |
113 | + tl = tl->right = block(TPIPE, tl->right, p); | |
114 | 114 | } |
115 | 115 | REJECT; |
116 | 116 | } |
@@ -128,7 +128,7 @@ andor(void) | ||
128 | 128 | while ((c = token(0)) == LOGAND || c == LOGOR) { |
129 | 129 | if ((p = pipeline(CONTIN)) == NULL) |
130 | 130 | syntaxerr(NULL); |
131 | - t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); | |
131 | + t = block(c == LOGAND? TAND: TOR, t, p); | |
132 | 132 | } |
133 | 133 | REJECT; |
134 | 134 | } |
@@ -157,16 +157,15 @@ c_list(bool multi) | ||
157 | 157 | } else if (!p) |
158 | 158 | break; |
159 | 159 | else if (c == '&' || c == COPROC) |
160 | - p = block(c == '&' ? TASYNC : TCOPROC, | |
161 | - p, NOBLOCK, NOWORDS); | |
160 | + p = block(c == '&' ? TASYNC : TCOPROC, p, NULL); | |
162 | 161 | else if (c != ';') |
163 | 162 | have_sep = false; |
164 | 163 | if (!t) |
165 | 164 | t = p; |
166 | 165 | else if (!tl) |
167 | - t = tl = block(TLIST, t, p, NOWORDS); | |
166 | + t = tl = block(TLIST, t, p); | |
168 | 167 | else |
169 | - tl = tl->right = block(TLIST, tl->right, p, NOWORDS); | |
168 | + tl = tl->right = block(TLIST, tl->right, p); | |
170 | 169 | if (!have_sep) |
171 | 170 | break; |
172 | 171 | } |
@@ -240,11 +239,11 @@ nested(int type, int smark, int emark) | ||
240 | 239 | t = c_list(true); |
241 | 240 | musthave(emark, KEYWORD|sALIAS); |
242 | 241 | nesting_pop(&old_nesting); |
243 | - return (block(type, t, NOBLOCK, NOWORDS)); | |
242 | + return (block(type, t, NULL)); | |
244 | 243 | } |
245 | 244 | |
246 | 245 | static const char let_cmd[] = { |
247 | - CHAR, 'l', CHAR, 'e', CHAR, 't', EOS | |
246 | + CHAR, 'l', CHAR, 'e', CHAR, 't', CHAR, ']', EOS | |
248 | 247 | }; |
249 | 248 | static const char setA_cmd0[] = { |
250 | 249 | CHAR, 's', CHAR, 'e', CHAR, 't', EOS |
@@ -465,7 +464,7 @@ get_command(int cf) | ||
465 | 464 | t = pipeline(0); |
466 | 465 | if (t == NULL) |
467 | 466 | syntaxerr(NULL); |
468 | - t = block(TBANG, NOBLOCK, t, NOWORDS); | |
467 | + t = block(TBANG, NULL, t); | |
469 | 468 | break; |
470 | 469 | |
471 | 470 | case TIME: |
@@ -477,7 +476,7 @@ get_command(int cf) | ||
477 | 476 | t->str[0] = '\0'; |
478 | 477 | t->str[1] = '\0'; |
479 | 478 | } |
480 | - t = block(TTIME, t, NOBLOCK, NOWORDS); | |
479 | + t = block(TTIME, t, NULL); | |
481 | 480 | break; |
482 | 481 | |
483 | 482 | case FUNCTION: |
@@ -505,7 +504,7 @@ get_command(int cf) | ||
505 | 504 | XPput(args, NULL); |
506 | 505 | t->args = (const char **)XPclose(args); |
507 | 506 | XPput(vars, NULL); |
508 | - t->vars = (char **) XPclose(vars); | |
507 | + t->vars = (char **)XPclose(vars); | |
509 | 508 | } else { |
510 | 509 | XPfree(args); |
511 | 510 | XPfree(vars); |
@@ -632,7 +631,7 @@ casepart(int endtok) | ||
632 | 631 | } while (token(0) == '|'); |
633 | 632 | REJECT; |
634 | 633 | XPput(ptns, NULL); |
635 | - t->vars = (char **) XPclose(ptns); | |
634 | + t->vars = (char **)XPclose(ptns); | |
636 | 635 | musthave(')', 0); |
637 | 636 | |
638 | 637 | t->left = c_list(true); |
@@ -743,13 +742,8 @@ wordlist(void) | ||
743 | 742 | XPput(args, yylval.cp); |
744 | 743 | if (c != '\n' && c != ';') |
745 | 744 | syntaxerr(NULL); |
746 | - if (XPsize(args) == 0) { | |
747 | - XPfree(args); | |
748 | - return (NULL); | |
749 | - } else { | |
750 | - XPput(args, NULL); | |
751 | - return ((char **)XPclose(args)); | |
752 | - } | |
745 | + XPput(args, NULL); | |
746 | + return ((char **)XPclose(args)); | |
753 | 747 | } |
754 | 748 | |
755 | 749 | /* |
@@ -757,14 +751,13 @@ wordlist(void) | ||
757 | 751 | */ |
758 | 752 | |
759 | 753 | static struct op * |
760 | -block(int type, struct op *t1, struct op *t2, char **wp) | |
754 | +block(int type, struct op *t1, struct op *t2) | |
761 | 755 | { |
762 | 756 | struct op *t; |
763 | 757 | |
764 | 758 | t = newtp(type); |
765 | 759 | t->left = t1; |
766 | 760 | t->right = t2; |
767 | - t->vars = wp; | |
768 | 761 | return (t); |
769 | 762 | } |
770 | 763 |
@@ -1131,7 +1124,7 @@ yyrecursive(int subtype MKSH_A_UNUSED) | ||
1131 | 1124 | struct yyrecursive_state *ys; |
1132 | 1125 | int stok, etok; |
1133 | 1126 | |
1134 | - if (subtype == FUNSUB) { | |
1127 | + if (subtype != COMSUB) { | |
1135 | 1128 | stok = '{'; |
1136 | 1129 | etok = '}'; |
1137 | 1130 | } else { |
@@ -2,7 +2,7 @@ | ||
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
5 | - * 2011, 2012 | |
5 | + * 2011, 2012, 2013 | |
6 | 6 | * Thorsten Glaser <tg@mirbsd.org> |
7 | 7 | * |
8 | 8 | * Provided that these terms and disclaimer and all copyright notices |
@@ -23,12 +23,12 @@ | ||
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
26 | -__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.67 2012/12/04 01:10:35 tg Exp $"); | |
26 | +__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.71 2013/07/26 20:33:24 tg Exp $"); | |
27 | 27 | |
28 | 28 | #define INDENT 8 |
29 | 29 | |
30 | 30 | static void ptree(struct op *, int, struct shf *); |
31 | -static void pioact(struct shf *, int, struct ioword *); | |
31 | +static void pioact(struct shf *, struct ioword *); | |
32 | 32 | static const char *wdvarput(struct shf *, const char *, int, int); |
33 | 33 | static void vfptreef(struct shf *, int, const char *, va_list); |
34 | 34 | static struct ioword **iocopy(struct ioword **, Area *); |
@@ -214,7 +214,7 @@ ptree(struct op *t, int indent, struct shf *shf) | ||
214 | 214 | bool need_nl = false; |
215 | 215 | |
216 | 216 | while (*ioact != NULL) |
217 | - pioact(shf, indent, *ioact++); | |
217 | + pioact(shf, *ioact++); | |
218 | 218 | /* Print here documents after everything else... */ |
219 | 219 | ioact = t->ioact; |
220 | 220 | while (*ioact != NULL) { |
@@ -244,7 +244,7 @@ ptree(struct op *t, int indent, struct shf *shf) | ||
244 | 244 | } |
245 | 245 | |
246 | 246 | static void |
247 | -pioact(struct shf *shf, int indent, struct ioword *iop) | |
247 | +pioact(struct shf *shf, struct ioword *iop) | |
248 | 248 | { |
249 | 249 | int flag = iop->flag; |
250 | 250 | int type = flag & IOTYPE; |
@@ -259,16 +259,20 @@ pioact(struct shf *shf, int indent, struct ioword *iop) | ||
259 | 259 | |
260 | 260 | switch (type) { |
261 | 261 | case IOREAD: |
262 | - shf_puts("<", shf); | |
262 | + shf_putc('<', shf); | |
263 | 263 | break; |
264 | 264 | case IOHERE: |
265 | - shf_puts(flag & IOSKIP ? "<<-" : "<<", shf); | |
265 | + shf_puts("<<", shf); | |
266 | + if (flag & IOSKIP) | |
267 | + shf_putc('-', shf); | |
266 | 268 | break; |
267 | 269 | case IOCAT: |
268 | 270 | shf_puts(">>", shf); |
269 | 271 | break; |
270 | 272 | case IOWRITE: |
271 | - shf_puts(flag & IOCLOB ? ">|" : ">", shf); | |
273 | + shf_putc('>', shf); | |
274 | + if (flag & IOCLOB) | |
275 | + shf_putc('|', shf); | |
272 | 276 | break; |
273 | 277 | case IORDWR: |
274 | 278 | shf_puts("<>", shf); |
@@ -283,9 +287,13 @@ pioact(struct shf *shf, int indent, struct ioword *iop) | ||
283 | 287 | wdvarput(shf, iop->delim, 0, WDS_TPUTS); |
284 | 288 | if (iop->flag & IOHERESTR) |
285 | 289 | shf_putc(' ', shf); |
286 | - } else if (iop->name) | |
287 | - fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ", | |
288 | - iop->name); | |
290 | + } else if (iop->name) { | |
291 | + if (iop->flag & IONAMEXP) | |
292 | + print_value_quoted(shf, iop->name); | |
293 | + else | |
294 | + wdvarput(shf, iop->name, 0, WDS_TPUTS); | |
295 | + shf_putc(' ', shf); | |
296 | + } | |
289 | 297 | prevent_semicolon = false; |
290 | 298 | } |
291 | 299 |
@@ -345,7 +353,14 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode) | ||
345 | 353 | shf_puts(cs, shf); |
346 | 354 | break; |
347 | 355 | case FUNSUB: |
348 | - shf_puts("${ ", shf); | |
356 | + c = ' '; | |
357 | + if (0) | |
358 | + /* FALLTHROUGH */ | |
359 | + case VALSUB: | |
360 | + c = '|'; | |
361 | + shf_putc('$', shf); | |
362 | + shf_putc('{', shf); | |
363 | + shf_putc(c, shf); | |
349 | 364 | cs = ";}"; |
350 | 365 | goto pSUB; |
351 | 366 | case EXPRSUB: |
@@ -485,7 +500,7 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va) | ||
485 | 500 | break; |
486 | 501 | case 'R': |
487 | 502 | /* I/O redirection */ |
488 | - pioact(shf, indent, va_arg(va, struct ioword *)); | |
503 | + pioact(shf, va_arg(va, struct ioword *)); | |
489 | 504 | break; |
490 | 505 | default: |
491 | 506 | shf_putc(c, shf); |
@@ -588,6 +603,7 @@ wdscan(const char *wp, int c) | ||
588 | 603 | break; |
589 | 604 | case COMSUB: |
590 | 605 | case FUNSUB: |
606 | + case VALSUB: | |
591 | 607 | case EXPRSUB: |
592 | 608 | while (*wp++ != 0) |
593 | 609 | ; |
@@ -745,8 +761,8 @@ vistree(char *dst, size_t sz, struct op *t) | ||
745 | 761 | char *cp, *buf; |
746 | 762 | size_t n; |
747 | 763 | |
748 | - buf = alloc(sz + 8, ATEMP); | |
749 | - snptreef(buf, sz + 8, "%T", t); | |
764 | + buf = alloc(sz + 16, ATEMP); | |
765 | + snptreef(buf, sz + 16, "%T", t); | |
750 | 766 | cp = buf; |
751 | 767 | vist_loop: |
752 | 768 | if (UTFMODE && (n = utf_mbtowc(&c, cp)) != (size_t)-1) { |
@@ -830,6 +846,9 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel) | ||
830 | 846 | case FUNSUB: |
831 | 847 | shf_puts("FUNSUB<", shf); |
832 | 848 | goto dumpsub; |
849 | + case VALSUB: | |
850 | + shf_puts("VALSUB<", shf); | |
851 | + goto dumpsub; | |
833 | 852 | case EXPRSUB: |
834 | 853 | shf_puts("EXPRSUB<", shf); |
835 | 854 | goto dumpsub; |
@@ -1,4 +1,4 @@ | ||
1 | -/* $OpenBSD: var.c,v 1.34 2007/10/15 02:16:35 deraadt Exp $ */ | |
1 | +/* $OpenBSD: var.c,v 1.35 2013/04/05 01:31:30 tedu Exp $ */ | |
2 | 2 | |
3 | 3 | /*- |
4 | 4 | * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
@@ -27,7 +27,7 @@ | ||
27 | 27 | #include <sys/sysctl.h> |
28 | 28 | #endif |
29 | 29 | |
30 | -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.166 2013/02/18 22:24:52 tg Exp $"); | |
30 | +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.173 2013/05/31 22:47:14 tg Exp $"); | |
31 | 31 | |
32 | 32 | /*- |
33 | 33 | * Variables |
@@ -49,7 +49,7 @@ static void unspecial(const char *); | ||
49 | 49 | static void getspec(struct tbl *); |
50 | 50 | static void setspec(struct tbl *); |
51 | 51 | static void unsetspec(struct tbl *); |
52 | -static int getint(struct tbl *, mksh_ari_t *, bool); | |
52 | +static int getint(struct tbl *, mksh_ari_u *, bool); | |
53 | 53 | static const char *array_index_calc(const char *, bool *, uint32_t *); |
54 | 54 | |
55 | 55 | /* |
@@ -347,7 +347,7 @@ str_val(struct tbl *vp) | ||
347 | 347 | else { |
348 | 348 | /* integer source */ |
349 | 349 | mksh_uari_t n; |
350 | - int base; | |
350 | + unsigned int base; | |
351 | 351 | /** |
352 | 352 | * worst case number length is when base == 2: |
353 | 353 | * 1 (minus) + 2 (base, up to 36) + 1 ('#') + |
@@ -361,8 +361,8 @@ str_val(struct tbl *vp) | ||
361 | 361 | if (vp->flag & INT_U) |
362 | 362 | n = vp->val.u; |
363 | 363 | else |
364 | - n = (vp->val.i < 0) ? -vp->val.i : vp->val.i; | |
365 | - base = (vp->type == 0) ? 10 : vp->type; | |
364 | + n = (vp->val.i < 0) ? -vp->val.u : vp->val.u; | |
365 | + base = (vp->type == 0) ? 10U : (unsigned int)vp->type; | |
366 | 366 | |
367 | 367 | if (base == 1 && n == 0) |
368 | 368 | base = 2; |
@@ -471,48 +471,43 @@ setint(struct tbl *vq, mksh_ari_t n) | ||
471 | 471 | } |
472 | 472 | |
473 | 473 | static int |
474 | -getint(struct tbl *vp, mksh_ari_t *nump, bool arith) | |
474 | +getint(struct tbl *vp, mksh_ari_u *nump, bool arith) | |
475 | 475 | { |
476 | - int c, base, neg; | |
477 | - mksh_uari_t num; | |
476 | + mksh_uari_t c, num, base; | |
478 | 477 | const char *s; |
479 | - bool have_base = false; | |
478 | + bool have_base = false, neg = false; | |
480 | 479 | |
481 | 480 | if (vp->flag&SPECIAL) |
482 | 481 | getspec(vp); |
483 | - /* XXX is it possible for ISSET to be set and val.s to be 0? */ | |
482 | + /* XXX is it possible for ISSET to be set and val.s to be NULL? */ | |
484 | 483 | if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL)) |
485 | 484 | return (-1); |
486 | 485 | if (vp->flag&INTEGER) { |
487 | - *nump = vp->val.i; | |
486 | + nump->i = vp->val.i; | |
488 | 487 | return (vp->type); |
489 | 488 | } |
490 | 489 | s = vp->val.s + vp->type; |
491 | 490 | base = 10; |
492 | 491 | num = 0; |
493 | - neg = 0; | |
494 | 492 | if (arith && s[0] == '0' && (s[1] | 0x20) == 'x') { |
495 | 493 | s += 2; |
496 | 494 | base = 16; |
497 | 495 | have_base = true; |
498 | 496 | } |
499 | -#ifdef MKSH_LEGACY_MODE | |
500 | - if (arith && s[0] == '0' && ksh_isdigit(s[1]) && | |
497 | + if (Flag(FPOSIX) && arith && s[0] == '0' && ksh_isdigit(s[1]) && | |
501 | 498 | !(vp->flag & ZEROFIL)) { |
502 | 499 | /* interpret as octal (deprecated) */ |
503 | 500 | base = 8; |
504 | 501 | have_base = true; |
505 | 502 | } |
506 | -#endif | |
507 | 503 | while ((c = *s++)) { |
508 | 504 | if (c == '-') { |
509 | - neg++; | |
505 | + neg = true; | |
510 | 506 | continue; |
511 | 507 | } else if (c == '#') { |
512 | 508 | if (have_base || num < 1 || num > 36) |
513 | 509 | return (-1); |
514 | - base = (int)num; | |
515 | - if (base == 1) { | |
510 | + if ((base = num) == 1) { | |
516 | 511 | unsigned int wc; |
517 | 512 | |
518 | 513 | if (!UTFMODE) |
@@ -525,7 +520,7 @@ getint(struct tbl *vp, mksh_ari_t *nump, bool arith) | ||
525 | 520 | * not round-tripping correctly XXX) |
526 | 521 | */ |
527 | 522 | wc = 0xEF00 + *(const unsigned char *)s; |
528 | - *nump = (mksh_ari_t)wc; | |
523 | + nump->u = (mksh_uari_t)wc; | |
529 | 524 | return (1); |
530 | 525 | } |
531 | 526 | num = 0; |
@@ -539,11 +534,13 @@ getint(struct tbl *vp, mksh_ari_t *nump, bool arith) | ||
539 | 534 | c -= 'A' - 10; |
540 | 535 | else |
541 | 536 | return (-1); |
542 | - if (c < 0 || c >= base) | |
537 | + if (c >= base) | |
543 | 538 | return (-1); |
544 | 539 | num = num * base + c; |
545 | 540 | } |
546 | - *nump = neg ? -((mksh_ari_t)num) : (mksh_ari_t)num; | |
541 | + if (neg) | |
542 | + num = -num; | |
543 | + nump->u = num; | |
547 | 544 | return (base); |
548 | 545 | } |
549 | 546 |
@@ -555,11 +552,11 @@ struct tbl * | ||
555 | 552 | setint_v(struct tbl *vq, struct tbl *vp, bool arith) |
556 | 553 | { |
557 | 554 | int base; |
558 | - mksh_ari_t num; | |
555 | + mksh_ari_u num; | |
559 | 556 | |
560 | 557 | if ((base = getint(vp, &num, arith)) == -1) |
561 | 558 | return (NULL); |
562 | - setint_n(vq, num, 0); | |
559 | + setint_n(vq, num.i, 0); | |
563 | 560 | if (vq->type == 0) |
564 | 561 | /* default base */ |
565 | 562 | vq->type = base; |
@@ -708,6 +705,10 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base) | ||
708 | 705 | |
709 | 706 | /* check for valid variable name, search for value */ |
710 | 707 | val = skip_varname(var, false); |
708 | + if (val == var) { | |
709 | + /* no variable name given */ | |
710 | + return (NULL); | |
711 | + } | |
711 | 712 | if (*val == '[') { |
712 | 713 | if (set_refflag != SRF_NOP) |
713 | 714 | errorf("%s: %s", var, |
@@ -742,7 +743,6 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base) | ||
742 | 743 | * must have a = when setting a variable by importing |
743 | 744 | * the original environment, otherwise be empty; we |
744 | 745 | * also end up here when a variable name was invalid |
745 | - * or none given | |
746 | 746 | */ |
747 | 747 | return (NULL); |
748 | 748 | } else { |
@@ -768,10 +768,15 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base) | ||
768 | 768 | if (vp != NULL) |
769 | 769 | qval = str_val(vp); |
770 | 770 | } |
771 | - /* silently ignore 'nameref foo=foo' */ | |
772 | - if (qval != NULL && !strcmp(qval, tvar)) { | |
773 | - afree(tvar, ATEMP); | |
774 | - return (&vtemp); | |
771 | + /* prevent nameref loops */ | |
772 | + while (qval) { | |
773 | + if (!strcmp(qval, tvar)) | |
774 | + errorf("%s: %s", qval, | |
775 | + "expression recurses on parameter"); | |
776 | + varsearch(e->loc, &vp, qval, hash(qval)); | |
777 | + qval = NULL; | |
778 | + if (vp && ((vp->flag & (ARRAY|ASSOC)) == ASSOC)) | |
779 | + qval = str_val(vp); | |
775 | 780 | } |
776 | 781 | } |
777 | 782 |
@@ -1094,7 +1099,7 @@ static int user_lineno; /* what user set $LINENO to */ | ||
1094 | 1099 | static void |
1095 | 1100 | getspec(struct tbl *vp) |
1096 | 1101 | { |
1097 | - register mksh_ari_t i; | |
1102 | + mksh_ari_u num; | |
1098 | 1103 | int st; |
1099 | 1104 | struct timeval tv; |
1100 | 1105 |
@@ -1114,19 +1119,19 @@ getspec(struct tbl *vp) | ||
1114 | 1119 | } |
1115 | 1120 | switch (st) { |
1116 | 1121 | case V_BASHPID: |
1117 | - i = (mksh_ari_t)procpid; | |
1122 | + num.u = (mksh_uari_t)procpid; | |
1118 | 1123 | break; |
1119 | 1124 | case V_COLUMNS: |
1120 | - i = x_cols; | |
1125 | + num.i = x_cols; | |
1121 | 1126 | break; |
1122 | 1127 | case V_HISTSIZE: |
1123 | - i = histsize; | |
1128 | + num.i = histsize; | |
1124 | 1129 | break; |
1125 | 1130 | case V_LINENO: |
1126 | - i = current_lineno + user_lineno; | |
1131 | + num.i = current_lineno + user_lineno; | |
1127 | 1132 | break; |
1128 | 1133 | case V_LINES: |
1129 | - i = x_lins; | |
1134 | + num.i = x_lins; | |
1130 | 1135 | break; |
1131 | 1136 | case V_EPOCHREALTIME: { |
1132 | 1137 | /* 10(%u) + 1(.) + 6 + NUL */ |
@@ -1141,10 +1146,10 @@ getspec(struct tbl *vp) | ||
1141 | 1146 | return; |
1142 | 1147 | } |
1143 | 1148 | case V_OPTIND: |
1144 | - i = user_opt.uoptind; | |
1149 | + num.i = user_opt.uoptind; | |
1145 | 1150 | break; |
1146 | 1151 | case V_RANDOM: |
1147 | - i = rndget(); | |
1152 | + num.i = rndget(); | |
1148 | 1153 | break; |
1149 | 1154 | case V_SECONDS: |
1150 | 1155 | /* |
@@ -1154,7 +1159,7 @@ getspec(struct tbl *vp) | ||
1154 | 1159 | */ |
1155 | 1160 | if (vp->flag & ISSET) { |
1156 | 1161 | mksh_TIME(tv); |
1157 | - i = tv.tv_sec - seconds; | |
1162 | + num.i = tv.tv_sec - seconds; | |
1158 | 1163 | } else |
1159 | 1164 | return; |
1160 | 1165 | break; |
@@ -1163,14 +1168,14 @@ getspec(struct tbl *vp) | ||
1163 | 1168 | return; |
1164 | 1169 | } |
1165 | 1170 | vp->flag &= ~SPECIAL; |
1166 | - setint_n(vp, i, 0); | |
1171 | + setint_n(vp, num.i, 0); | |
1167 | 1172 | vp->flag |= SPECIAL; |
1168 | 1173 | } |
1169 | 1174 | |
1170 | 1175 | static void |
1171 | 1176 | setspec(struct tbl *vp) |
1172 | 1177 | { |
1173 | - mksh_ari_t i; | |
1178 | + mksh_ari_u num; | |
1174 | 1179 | char *s; |
1175 | 1180 | int st; |
1176 | 1181 |
@@ -1228,11 +1233,11 @@ setspec(struct tbl *vp) | ||
1228 | 1233 | case V_SECONDS: |
1229 | 1234 | case V_TMOUT: |
1230 | 1235 | vp->flag &= ~SPECIAL; |
1231 | - if (getint(vp, &i, false) == -1) { | |
1236 | + if (getint(vp, &num, false) == -1) { | |
1232 | 1237 | s = str_val(vp); |
1233 | 1238 | if (st != V_RANDOM) |
1234 | 1239 | errorf("%s: %s: %s", vp->name, "bad number", s); |
1235 | - i = hash(s); | |
1240 | + num.u = hash(s); | |
1236 | 1241 | } |
1237 | 1242 | vp->flag |= SPECIAL; |
1238 | 1243 | break; |
@@ -1245,40 +1250,40 @@ setspec(struct tbl *vp) | ||
1245 | 1250 | |
1246 | 1251 | switch (st) { |
1247 | 1252 | case V_COLUMNS: |
1248 | - if (i >= MIN_COLS) | |
1249 | - x_cols = i; | |
1253 | + if (num.i >= MIN_COLS) | |
1254 | + x_cols = num.i; | |
1250 | 1255 | break; |
1251 | 1256 | case V_HISTSIZE: |
1252 | - sethistsize(i); | |
1257 | + sethistsize(num.i); | |
1253 | 1258 | break; |
1254 | 1259 | case V_LINENO: |
1255 | 1260 | /* The -1 is because line numbering starts at 1. */ |
1256 | - user_lineno = (unsigned int)i - current_lineno - 1; | |
1261 | + user_lineno = num.u - current_lineno - 1; | |
1257 | 1262 | break; |
1258 | 1263 | case V_LINES: |
1259 | - if (i >= MIN_LINS) | |
1260 | - x_lins = i; | |
1264 | + if (num.i >= MIN_LINS) | |
1265 | + x_lins = num.i; | |
1261 | 1266 | break; |
1262 | 1267 | case V_OPTIND: |
1263 | - getopts_reset((int)i); | |
1268 | + getopts_reset((int)num.i); | |
1264 | 1269 | break; |
1265 | 1270 | case V_RANDOM: |
1266 | 1271 | /* |
1267 | 1272 | * mksh R39d+ no longer has the traditional repeatability |
1268 | 1273 | * of $RANDOM sequences, but always retains state |
1269 | 1274 | */ |
1270 | - rndset((long)i); | |
1275 | + rndset((unsigned long)num.u); | |
1271 | 1276 | break; |
1272 | 1277 | case V_SECONDS: |
1273 | 1278 | { |
1274 | 1279 | struct timeval tv; |
1275 | 1280 | |
1276 | 1281 | mksh_TIME(tv); |
1277 | - seconds = tv.tv_sec - i; | |
1282 | + seconds = tv.tv_sec - num.i; | |
1278 | 1283 | } |
1279 | 1284 | break; |
1280 | 1285 | case V_TMOUT: |
1281 | - ksh_tmout = i >= 0 ? i : 0; | |
1286 | + ksh_tmout = num.i >= 0 ? num.i : 0; | |
1282 | 1287 | break; |
1283 | 1288 | } |
1284 | 1289 | } |
@@ -1534,7 +1539,7 @@ rndget(void) | ||
1534 | 1539 | } |
1535 | 1540 | |
1536 | 1541 | void |
1537 | -rndset(long v) | |
1542 | +rndset(unsigned long v) | |
1538 | 1543 | { |
1539 | 1544 | register uint32_t h; |
1540 | 1545 |