| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: parser.c,v 1.75 2010/11/14 19:43:38 christos Exp $ */ | | 1 | /* $NetBSD: parser.c,v 1.76 2010/11/14 19:49:16 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1991, 1993 | | 4 | * Copyright (c) 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. | | 8 | * Kenneth Almquist. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -27,27 +27,27 @@ | | | @@ -27,27 +27,27 @@ |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | #ifndef lint | | 36 | #ifndef lint |
37 | #if 0 | | 37 | #if 0 |
38 | static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; | | 38 | static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; |
39 | #else | | 39 | #else |
40 | __RCSID("$NetBSD: parser.c,v 1.75 2010/11/14 19:43:38 christos Exp $"); | | 40 | __RCSID("$NetBSD: parser.c,v 1.76 2010/11/14 19:49:16 christos Exp $"); |
41 | #endif | | 41 | #endif |
42 | #endif /* not lint */ | | 42 | #endif /* not lint */ |
43 | | | 43 | |
44 | #include <stdlib.h> | | 44 | #include <stdlib.h> |
45 | | | 45 | |
46 | #include "shell.h" | | 46 | #include "shell.h" |
47 | #include "parser.h" | | 47 | #include "parser.h" |
48 | #include "nodes.h" | | 48 | #include "nodes.h" |
49 | #include "expand.h" /* defines rmescapes() */ | | 49 | #include "expand.h" /* defines rmescapes() */ |
50 | #include "eval.h" /* defines commandname */ | | 50 | #include "eval.h" /* defines commandname */ |
51 | #include "redir.h" /* defines copyfd() */ | | 51 | #include "redir.h" /* defines copyfd() */ |
52 | #include "syntax.h" | | 52 | #include "syntax.h" |
53 | #include "options.h" | | 53 | #include "options.h" |
| @@ -886,77 +886,69 @@ breakloop: | | | @@ -886,77 +886,69 @@ breakloop: |
886 | #define PARSEREDIR() {goto parseredir; parseredir_return:;} | | 886 | #define PARSEREDIR() {goto parseredir; parseredir_return:;} |
887 | #define PARSESUB() {goto parsesub; parsesub_return:;} | | 887 | #define PARSESUB() {goto parsesub; parsesub_return:;} |
888 | #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} | | 888 | #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} |
889 | #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} | | 889 | #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} |
890 | #define PARSEARITH() {goto parsearith; parsearith_return:;} | | 890 | #define PARSEARITH() {goto parsearith; parsearith_return:;} |
891 | | | 891 | |
892 | /* | | 892 | /* |
893 | * Keep track of nested doublequotes in dblquote and doublequotep. | | 893 | * Keep track of nested doublequotes in dblquote and doublequotep. |
894 | * We use dblquote for the first 32 levels, and we expand to a malloc'ed | | 894 | * We use dblquote for the first 32 levels, and we expand to a malloc'ed |
895 | * region for levels above that. Usually we never need to malloc. | | 895 | * region for levels above that. Usually we never need to malloc. |
896 | * This code assumes that an int is 32 bits. We don't use uint32_t, | | 896 | * This code assumes that an int is 32 bits. We don't use uint32_t, |
897 | * because the rest of the code does not. | | 897 | * because the rest of the code does not. |
898 | */ | | 898 | */ |
899 | #define VN (varnest - insub) | | 899 | #define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \ |
900 | #define ISDBLQUOTE() ((VN < 32) ? (dblquote & (1 << VN)) : \ | | 900 | (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32)))) |
901 | (dblquotep[(VN / 32) - 1] & (1 << (VN % 32)))) | | | |
902 | | | 901 | |
903 | #define SETDBLQUOTE() \ | | 902 | #define SETDBLQUOTE() \ |
904 | do { \ | | 903 | if (varnest < 32) \ |
905 | TRACE(("setdblquote %d\n", varnest)); \ | | 904 | dblquote |= (1 << varnest); \ |
906 | if (varnest < 32) \ | | 905 | else \ |
907 | dblquote |= (1 << varnest); \ | | 906 | dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32)) |
908 | else \ | | | |
909 | dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32));\ | | | |
910 | } while (/*CONSTCOND*/0) | | | |
911 | | | 907 | |
912 | #define CLRDBLQUOTE() \ | | 908 | #define CLRDBLQUOTE() \ |
913 | do { \ | | 909 | if (varnest < 32) \ |
914 | TRACE(("clrdblquote %d\n", varnest)); \ | | 910 | dblquote &= ~(1 << varnest); \ |
915 | if (varnest < 32) \ | | 911 | else \ |
916 | dblquote &= ~(1 << varnest); \ | | 912 | dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32)) |
917 | else \ | | | |
918 | dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32)); \ | | | |
919 | } while (/*CONSTCOND*/0) | | | |
920 | | | 913 | |
921 | STATIC int | | 914 | STATIC int |
922 | readtoken1(int firstc, char const *syn, char *eofmark, int striptabs) | | 915 | readtoken1(int firstc, char const *syn, char *eofmark, int striptabs) |
923 | { | | 916 | { |
924 | char const * volatile syntax = syn; | | 917 | char const * volatile syntax = syn; |
925 | int c = firstc; | | 918 | int c = firstc; |
926 | char * volatile out; | | 919 | char * volatile out; |
927 | int len; | | 920 | int len; |
928 | char line[EOFMARKLEN + 1]; | | 921 | char line[EOFMARKLEN + 1]; |
929 | struct nodelist *bqlist; | | 922 | struct nodelist *bqlist; |
930 | volatile int quotef; | | 923 | volatile int quotef; |
931 | int * volatile dblquotep = NULL; | | 924 | int * volatile dblquotep = NULL; |
932 | volatile size_t maxnest = 32; | | 925 | volatile size_t maxnest = 32; |
933 | volatile int dblquote; | | 926 | volatile int dblquote; |
934 | volatile size_t varnest; /* levels of variables expansion */ | | 927 | volatile size_t varnest; /* levels of variables expansion */ |
935 | volatile int arinest; /* levels of arithmetic expansion */ | | 928 | volatile int arinest; /* levels of arithmetic expansion */ |
936 | volatile int parenlevel; /* levels of parens in arithmetic */ | | 929 | volatile int parenlevel; /* levels of parens in arithmetic */ |
937 | volatile int oldstyle; | | 930 | volatile int oldstyle; |
938 | volatile int insub; | | | |
939 | char const * volatile prevsyntax; /* syntax before arithmetic */ | | 931 | char const * volatile prevsyntax; /* syntax before arithmetic */ |
940 | #ifdef __GNUC__ | | 932 | #ifdef __GNUC__ |
941 | prevsyntax = NULL; /* XXX gcc4 */ | | 933 | prevsyntax = NULL; /* XXX gcc4 */ |
942 | #endif | | 934 | #endif |
943 | | | 935 | |
944 | startlinno = plinno; | | 936 | startlinno = plinno; |
945 | dblquote = 0; | | 937 | dblquote = 0; |
946 | varnest = 0; | | 938 | varnest = 0; |
947 | insub = 0; | | 939 | if (syntax == DQSYNTAX) { |
948 | if (syntax == DQSYNTAX) | | | |
949 | SETDBLQUOTE(); | | 940 | SETDBLQUOTE(); |
| | | 941 | } |
950 | quotef = 0; | | 942 | quotef = 0; |
951 | bqlist = NULL; | | 943 | bqlist = NULL; |
952 | arinest = 0; | | 944 | arinest = 0; |
953 | parenlevel = 0; | | 945 | parenlevel = 0; |
954 | | | 946 | |
955 | STARTSTACKSTR(out); | | 947 | STARTSTACKSTR(out); |
956 | loop: { /* for each line, until end of word */ | | 948 | loop: { /* for each line, until end of word */ |
957 | #if ATTY | | 949 | #if ATTY |
958 | if (c == '\034' && doprompt | | 950 | if (c == '\034' && doprompt |
959 | && attyset() && ! equal(termval(), "emacs")) { | | 951 | && attyset() && ! equal(termval(), "emacs")) { |
960 | attyline(); | | 952 | attyline(); |
961 | if (syntax == BASESYNTAX) | | 953 | if (syntax == BASESYNTAX) |
962 | return readtoken(); | | 954 | return readtoken(); |
| @@ -992,34 +984,30 @@ readtoken1(int firstc, char const *syn, | | | @@ -992,34 +984,30 @@ readtoken1(int firstc, char const *syn, |
992 | if (c == PEOF) { | | 984 | if (c == PEOF) { |
993 | USTPUTC('\\', out); | | 985 | USTPUTC('\\', out); |
994 | pungetc(); | | 986 | pungetc(); |
995 | break; | | 987 | break; |
996 | } | | 988 | } |
997 | if (c == '\n') { | | 989 | if (c == '\n') { |
998 | if (doprompt) | | 990 | if (doprompt) |
999 | setprompt(2); | | 991 | setprompt(2); |
1000 | else | | 992 | else |
1001 | setprompt(0); | | 993 | setprompt(0); |
1002 | break; | | 994 | break; |
1003 | } | | 995 | } |
1004 | quotef = 1; | | 996 | quotef = 1; |
1005 | TRACE(("varnest=%d doubleq=%d c=%c\n", | | | |
1006 | varnest, ISDBLQUOTE(), c)); | | | |
1007 | if (ISDBLQUOTE() && c != '\\' && | | 997 | if (ISDBLQUOTE() && c != '\\' && |
1008 | c != '`' && c != '$' && | | 998 | c != '`' && c != '$' && |
1009 | (c != '"' || eofmark != NULL)) { | | 999 | (c != '"' || eofmark != NULL)) |
1010 | USTPUTC(CTLESC, out); | | 1000 | USTPUTC('\\', out); |
1011 | USTPUTC(CTLESC, out); | | | |
1012 | } | | | |
1013 | if (SQSYNTAX[c] == CCTL) | | 1001 | if (SQSYNTAX[c] == CCTL) |
1014 | USTPUTC(CTLESC, out); | | 1002 | USTPUTC(CTLESC, out); |
1015 | else if (eofmark == NULL) { | | 1003 | else if (eofmark == NULL) { |
1016 | USTPUTC(CTLQUOTEMARK, out); | | 1004 | USTPUTC(CTLQUOTEMARK, out); |
1017 | USTPUTC(c, out); | | 1005 | USTPUTC(c, out); |
1018 | if (varnest != 0) | | 1006 | if (varnest != 0) |
1019 | USTPUTC(CTLQUOTEEND, out); | | 1007 | USTPUTC(CTLQUOTEEND, out); |
1020 | break; | | 1008 | break; |
1021 | } | | 1009 | } |
1022 | USTPUTC(c, out); | | 1010 | USTPUTC(c, out); |
1023 | break; | | 1011 | break; |
1024 | case CSQUOTE: | | 1012 | case CSQUOTE: |
1025 | if (syntax != SQSYNTAX) { | | 1013 | if (syntax != SQSYNTAX) { |
| @@ -1070,27 +1058,26 @@ readtoken1(int firstc, char const *syn, | | | @@ -1070,27 +1058,26 @@ readtoken1(int firstc, char const *syn, |
1070 | USTPUTC(CTLQUOTEEND, out); | | 1058 | USTPUTC(CTLQUOTEEND, out); |
1071 | syntax = BASESYNTAX; | | 1059 | syntax = BASESYNTAX; |
1072 | CLRDBLQUOTE(); | | 1060 | CLRDBLQUOTE(); |
1073 | } else { | | 1061 | } else { |
1074 | syntax = DQSYNTAX; | | 1062 | syntax = DQSYNTAX; |
1075 | SETDBLQUOTE(); | | 1063 | SETDBLQUOTE(); |
1076 | USTPUTC(CTLQUOTEMARK, out); | | 1064 | USTPUTC(CTLQUOTEMARK, out); |
1077 | } | | 1065 | } |
1078 | break; | | 1066 | break; |
1079 | case CVAR: /* '$' */ | | 1067 | case CVAR: /* '$' */ |
1080 | PARSESUB(); /* parse substitution */ | | 1068 | PARSESUB(); /* parse substitution */ |
1081 | break; | | 1069 | break; |
1082 | case CENDVAR: /* CLOSEBRACE */ | | 1070 | case CENDVAR: /* CLOSEBRACE */ |
1083 | insub = 0; | | | |
1084 | if (varnest > 0 && !ISDBLQUOTE()) { | | 1071 | if (varnest > 0 && !ISDBLQUOTE()) { |
1085 | varnest--; | | 1072 | varnest--; |
1086 | USTPUTC(CTLENDVAR, out); | | 1073 | USTPUTC(CTLENDVAR, out); |
1087 | } else { | | 1074 | } else { |
1088 | USTPUTC(c, out); | | 1075 | USTPUTC(c, out); |
1089 | } | | 1076 | } |
1090 | break; | | 1077 | break; |
1091 | case CLP: /* '(' in arithmetic */ | | 1078 | case CLP: /* '(' in arithmetic */ |
1092 | parenlevel++; | | 1079 | parenlevel++; |
1093 | USTPUTC(c, out); | | 1080 | USTPUTC(c, out); |
1094 | break; | | 1081 | break; |
1095 | case CRP: /* ')' in arithmetic */ | | 1082 | case CRP: /* ')' in arithmetic */ |
1096 | if (parenlevel > 0) { | | 1083 | if (parenlevel > 0) { |
| @@ -1343,29 +1330,27 @@ badsub: synerror("Bad substitution"); | | | @@ -1343,29 +1330,27 @@ badsub: synerror("Bad substitution"); |
1343 | subtype++; | | 1330 | subtype++; |
1344 | else | | 1331 | else |
1345 | pungetc(); | | 1332 | pungetc(); |
1346 | break; | | 1333 | break; |
1347 | } | | 1334 | } |
1348 | } | | 1335 | } |
1349 | } else { | | 1336 | } else { |
1350 | pungetc(); | | 1337 | pungetc(); |
1351 | } | | 1338 | } |
1352 | if (ISDBLQUOTE() || arinest) | | 1339 | if (ISDBLQUOTE() || arinest) |
1353 | flags |= VSQUOTE; | | 1340 | flags |= VSQUOTE; |
1354 | *(stackblock() + typeloc) = subtype | flags; | | 1341 | *(stackblock() + typeloc) = subtype | flags; |
1355 | if (subtype != VSNORMAL) { | | 1342 | if (subtype != VSNORMAL) { |
1356 | TRACE(("varnest=%d subtype=%d\n", varnest, subtype)); | | | |
1357 | varnest++; | | 1343 | varnest++; |
1358 | insub = 1; | | | |
1359 | if (varnest >= maxnest) { | | 1344 | if (varnest >= maxnest) { |
1360 | dblquotep = ckrealloc(dblquotep, maxnest / 8); | | 1345 | dblquotep = ckrealloc(dblquotep, maxnest / 8); |
1361 | dblquotep[(maxnest / 32) - 1] = 0; | | 1346 | dblquotep[(maxnest / 32) - 1] = 0; |
1362 | maxnest += 32; | | 1347 | maxnest += 32; |
1363 | } | | 1348 | } |
1364 | } | | 1349 | } |
1365 | } | | 1350 | } |
1366 | goto parsesub_return; | | 1351 | goto parsesub_return; |
1367 | } | | 1352 | } |
1368 | | | 1353 | |
1369 | | | 1354 | |
1370 | /* | | 1355 | /* |
1371 | * Called to parse command substitutions. Newstyle is set if the command | | 1356 | * Called to parse command substitutions. Newstyle is set if the command |