Deleted Added
full compact
cond.c (144473) cond.c (144894)
1/*-
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1988, 1989 by Adam de Boor
5 * Copyright (c) 1989 by Berkeley Softworks
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by

--- 26 unchanged lines hidden (view full) ---

35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)cond.c 8.2 (Berkeley) 1/2/94
40 */
41
42#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1988, 1989 by Adam de Boor
5 * Copyright (c) 1989 by Berkeley Softworks
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by

--- 26 unchanged lines hidden (view full) ---

35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)cond.c 8.2 (Berkeley) 1/2/94
40 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/usr.bin/make/cond.c 144473 2005-04-01 12:31:15Z harti $");
43__FBSDID("$FreeBSD: head/usr.bin/make/cond.c 144894 2005-04-11 07:20:10Z harti $");
44
45/*
46 * Functions to handle conditionals in a makefile.
47 *
48 * Interface:
49 * Cond_Eval Evaluate the conditional in the passed line.
50 */
51

--- 70 unchanged lines hidden (view full) ---

122static CondProc CondDoExists;
123static CondProc CondDoTarget;
124static char *CondCvtArg(char *, double *);
125static Token CondToken(Boolean);
126static Token CondT(Boolean);
127static Token CondF(Boolean);
128static Token CondE(Boolean);
129
44
45/*
46 * Functions to handle conditionals in a makefile.
47 *
48 * Interface:
49 * Cond_Eval Evaluate the conditional in the passed line.
50 */
51

--- 70 unchanged lines hidden (view full) ---

122static CondProc CondDoExists;
123static CondProc CondDoTarget;
124static char *CondCvtArg(char *, double *);
125static Token CondToken(Boolean);
126static Token CondT(Boolean);
127static Token CondF(Boolean);
128static Token CondE(Boolean);
129
130static struct If {
131 char *form; /* Form of if */
132 int formlen; /* Length of form */
130static const struct If {
133 Boolean doNot; /* TRUE if default function should be negated */
134 CondProc *defProc; /* Default function to apply */
131 Boolean doNot; /* TRUE if default function should be negated */
132 CondProc *defProc; /* Default function to apply */
133 Boolean isElse; /* actually el<XXX> */
135} ifs[] = {
134} ifs[] = {
136 { "ifdef", 5, FALSE, CondDoDefined },
137 { "ifndef", 6, TRUE, CondDoDefined },
138 { "ifmake", 6, FALSE, CondDoMake },
139 { "ifnmake", 7, TRUE, CondDoMake },
140 { "if", 2, FALSE, CondDoDefined },
141 { NULL, 0, FALSE, NULL }
135 [COND_IF] = { FALSE, CondDoDefined, FALSE },
136 [COND_IFDEF] = { FALSE, CondDoDefined, FALSE },
137 [COND_IFNDEF] = { TRUE, CondDoDefined, FALSE },
138 [COND_IFMAKE] = { FALSE, CondDoMake, FALSE },
139 [COND_IFNMAKE] = { TRUE, CondDoMake, FALSE },
140 [COND_ELIF] = { FALSE, CondDoDefined, TRUE },
141 [COND_ELIFDEF] = { FALSE, CondDoDefined, TRUE },
142 [COND_ELIFNDEF] = { TRUE, CondDoDefined, TRUE },
143 [COND_ELIFMAKE] = { FALSE, CondDoMake, TRUE },
144 [COND_ELIFNMAKE] = { TRUE, CondDoMake, TRUE },
142};
143
144static Boolean condInvert; /* Invert the default function */
145static CondProc *condDefProc; /* default function to apply */
146static char *condExpr; /* The expression to parse */
147static Token condPushBack = None; /* Single push-back token in parsing */
148
149#define MAXIF 30 /* greatest depth of #if'ing */
150
151static Boolean condStack[MAXIF]; /* Stack of conditionals's values */
152static int condLineno[MAXIF]; /* Line numbers of the opening .if */
153static int condTop = MAXIF; /* Top-most conditional */
154static int skipIfLevel = 0; /* Depth of skipped conditionals */
155static int skipIfLineno[MAXIF]; /* Line numbers of skipped .ifs */
145};
146
147static Boolean condInvert; /* Invert the default function */
148static CondProc *condDefProc; /* default function to apply */
149static char *condExpr; /* The expression to parse */
150static Token condPushBack = None; /* Single push-back token in parsing */
151
152#define MAXIF 30 /* greatest depth of #if'ing */
153
154static Boolean condStack[MAXIF]; /* Stack of conditionals's values */
155static int condLineno[MAXIF]; /* Line numbers of the opening .if */
156static int condTop = MAXIF; /* Top-most conditional */
157static int skipIfLevel = 0; /* Depth of skipped conditionals */
158static int skipIfLineno[MAXIF]; /* Line numbers of skipped .ifs */
156static Boolean skipLine = FALSE; /* Whether the parse module is skipping
159Boolean skipLine = FALSE; /* Whether the parse module is skipping
157 * lines */
158
159/**
160 * CondPushBack
161 * Push back the most recent token read. We only need one level of
162 * this, so the thing is just stored in 'condPushback'.
163 *
164 * Side Effects:

--- 835 unchanged lines hidden (view full) ---

1000 */
1001 CondPushBack(o);
1002 }
1003 }
1004 return (l);
1005}
1006
1007/**
160 * lines */
161
162/**
163 * CondPushBack
164 * Push back the most recent token read. We only need one level of
165 * this, so the thing is just stored in 'condPushback'.
166 *
167 * Side Effects:

--- 835 unchanged lines hidden (view full) ---

1003 */
1004 CondPushBack(o);
1005 }
1006 }
1007 return (l);
1008}
1009
1010/**
1008 * Cond_Eval --
1009 * Evaluate the conditional in the passed line. The line
1010 * looks like this:
1011 * .<cond-type> <expr>
1012 * where <cond-type> is any of if, ifmake, ifnmake, ifdef,
1013 * ifndef, elif, elifmake, elifnmake, elifdef, elifndef
1014 * and <expr> consists of &&, ||, !, make(target), defined(variable)
1015 * and parenthetical groupings thereof.
1016 *
1017 * Results:
1018 * COND_PARSE if should parse lines after the conditional
1019 * COND_SKIP if should skip lines after the conditional
1020 * COND_INVALID if not a valid conditional.
1011 * Cond_If
1012 * Handle .if<X> and .elif<X> directives.
1013 * This function is called even when we're skipping.
1021 */
1014 */
1022int
1023Cond_Eval(char *line, int lineno)
1015void
1016Cond_If(char *line, int code, int lineno)
1024{
1017{
1025 struct If *ifp;
1026 Boolean isElse;
1027 Boolean value = FALSE;
1028 int level; /* Level at which to report errors. */
1018 const struct If *ifp;
1019 Boolean value;
1029
1020
1030 level = PARSE_FATAL;
1021 ifp = &ifs[code];
1031
1022
1032 for (line++; *line == ' ' || *line == '\t'; line++) {
1033 continue;
1034 }
1035
1036 /*
1037 * Find what type of if we're dealing with. The result is left
1038 * in ifp and isElse is set TRUE if it's an elif line.
1039 */
1040 if (line[0] == 'e' && line[1] == 'l') {
1041 line += 2;
1042 isElse = TRUE;
1043
1044 } else if (strncmp(line, "endif", 5) == 0) {
1045 /*
1046 * End of a conditional section. If skipIfLevel is non-zero,
1047 * that conditional was skipped, so lines following it should
1048 * also be skipped. Hence, we return COND_SKIP. Otherwise,
1049 * the conditional was read so succeeding lines should be
1050 * parsed (think about it...) so we return COND_PARSE, unless
1051 * this endif isn't paired with a decent if.
1052 */
1053 if (skipIfLevel != 0) {
1054 skipIfLevel -= 1;
1055 return (COND_SKIP);
1056 } else {
1057 if (condTop == MAXIF) {
1058 Parse_Error(level, "if-less endif");
1059 return (COND_INVALID);
1060 } else {
1061 skipLine = FALSE;
1062 condTop += 1;
1063 return (COND_PARSE);
1064 }
1023 if (ifp->isElse) {
1024 if (condTop == MAXIF) {
1025 Parse_Error(PARSE_FATAL, "if-less elif");
1026 return;
1065 }
1027 }
1066 } else {
1067 isElse = FALSE;
1068 }
1069
1070 /*
1071 * Figure out what sort of conditional it is -- what its default
1072 * function is, etc. -- by looking in the table of valid "ifs"
1073 */
1074 for (ifp = ifs; ifp->form != NULL; ifp++) {
1075 if (strncmp(ifp->form, line, ifp->formlen) == 0) {
1076 break;
1077 }
1078 }
1079
1080 if (ifp->form == NULL) {
1081 /*
1082 * Nothing fit. If the first word on the line is actually
1083 * "else", it's a valid conditional whose value is the inverse
1084 * of the previous if we parsed.
1085 */
1086 if (isElse && (line[0] == 's') && (line[1] == 'e')) {
1087 if (condTop == MAXIF) {
1088 Parse_Error(level, "if-less else");
1089 return (COND_INVALID);
1090 } else if (skipIfLevel == 0) {
1091 value = !condStack[condTop];
1092 lineno = condLineno[condTop];
1093 } else {
1094 return (COND_SKIP);
1095 }
1096 } else {
1028 if (skipIfLevel != 0) {
1097 /*
1029 /*
1098 * Not a valid conditional type. No error...
1030 * If skipping this conditional, just ignore
1031 * the whole thing. If we don't, the user
1032 * might be employing a variable that's
1033 * undefined, for which there's an enclosing
1034 * ifdef that we're skipping...
1099 */
1035 */
1100 return (COND_INVALID);
1036 skipIfLineno[skipIfLevel - 1] = lineno;
1037 return;
1101 }
1102
1038 }
1039
1103 } else {
1104 if (isElse) {
1105 if (condTop == MAXIF) {
1106 Parse_Error(level, "if-less elif");
1107 return (COND_INVALID);
1108
1109 } else if (skipIfLevel != 0) {
1110 /*
1111 * If skipping this conditional, just ignore
1112 * the whole thing. If we don't, the user
1113 * might be employing a variable that's
1114 * undefined, for which there's an enclosing
1115 * ifdef that we're skipping...
1116 */
1117 skipIfLineno[skipIfLevel - 1] = lineno;
1118 return (COND_SKIP);
1119 }
1120 } else if (skipLine) {
1121 /*
1122 * Don't even try to evaluate a conditional that's
1123 * not an else if we're skipping things...
1124 */
1125 skipIfLineno[skipIfLevel] = lineno;
1126 skipIfLevel += 1;
1127 return (COND_SKIP);
1128 }
1129
1040 } else if (skipLine) {
1130 /*
1041 /*
1131 * Initialize file-global variables for parsing
1042 * Don't even try to evaluate a conditional that's
1043 * not an else if we're skipping things...
1132 */
1044 */
1133 condDefProc = ifp->defProc;
1134 condInvert = ifp->doNot;
1045 skipIfLineno[skipIfLevel] = lineno;
1046 skipIfLevel += 1;
1047 return;
1048 }
1135
1049
1136 line += ifp->formlen;
1050 /*
1051 * Initialize file-global variables for parsing
1052 */
1053 condDefProc = ifp->defProc;
1054 condInvert = ifp->doNot;
1137
1055
1138 while (*line == ' ' || *line == '\t') {
1139 line++;
1140 }
1056 while (*line == ' ' || *line == '\t') {
1057 line++;
1058 }
1141
1059
1142 condExpr = line;
1143 condPushBack = None;
1060 condExpr = line;
1061 condPushBack = None;
1144
1062
1145 switch (CondE(TRUE)) {
1146 case True:
1147 if (CondToken(TRUE) == EndOfFile) {
1148 value = TRUE;
1149 break;
1150 }
1063 switch (CondE(TRUE)) {
1064 case True:
1065 if (CondToken(TRUE) != EndOfFile)
1151 goto err;
1066 goto err;
1152 /*FALLTHRU*/
1067 value = TRUE;
1068 break;
1153
1069
1154 case False:
1155 if (CondToken(TRUE) == EndOfFile) {
1156 value = FALSE;
1157 break;
1158 }
1159 /*FALLTHRU*/
1070 case False:
1071 if (CondToken(TRUE) != EndOfFile)
1072 goto err;
1073 value = FALSE;
1074 break;
1160
1075
1161 case Err:
1162 err:
1163 Parse_Error(level, "Malformed conditional (%s)", line);
1164 return (COND_INVALID);
1165 default:
1166 break;
1167 }
1076 case Err:
1077 err: Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line);
1078 return;
1079
1080 default:
1081 abort();
1168 }
1082 }
1169 if (!isElse) {
1083
1084 if (!ifp->isElse) {
1085 /* push this value */
1170 condTop -= 1;
1171
1086 condTop -= 1;
1087
1172 } else if ((skipIfLevel != 0) || condStack[condTop]) {
1088 } else if (skipIfLevel != 0 || condStack[condTop]) {
1173 /*
1174 * If this is an else-type conditional, it should only take
1175 * effect if its corresponding if was evaluated and FALSE.
1176 * If its if was TRUE or skipped, we return COND_SKIP (and
1177 * start skipping in case we weren't already), leaving the
1178 * stack unmolested so later elif's don't screw up...
1179 */
1180 skipLine = TRUE;
1089 /*
1090 * If this is an else-type conditional, it should only take
1091 * effect if its corresponding if was evaluated and FALSE.
1092 * If its if was TRUE or skipped, we return COND_SKIP (and
1093 * start skipping in case we weren't already), leaving the
1094 * stack unmolested so later elif's don't screw up...
1095 */
1096 skipLine = TRUE;
1181 return (COND_SKIP);
1097 return;
1182 }
1183
1184 if (condTop < 0) {
1185 /*
1186 * This is the one case where we can definitely proclaim a fatal
1187 * error. If we don't, we're hosed.
1188 */
1098 }
1099
1100 if (condTop < 0) {
1101 /*
1102 * This is the one case where we can definitely proclaim a fatal
1103 * error. If we don't, we're hosed.
1104 */
1189 Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.",
1190 MAXIF);
1191 return (COND_INVALID);
1192 } else {
1193 condStack[condTop] = value;
1194 condLineno[condTop] = lineno;
1195 skipLine = !value;
1196 return (value ? COND_PARSE : COND_SKIP);
1105 Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.",MAXIF);
1106 return;
1197 }
1107 }
1108
1109 /* push */
1110 condStack[condTop] = value;
1111 condLineno[condTop] = lineno;
1112 skipLine = !value;
1198}
1199
1200/**
1113}
1114
1115/**
1116 * Cond_Else
1117 * Handle .else statement.
1118 */
1119void
1120Cond_Else(char *line __unused, int code __unused, int lineno __unused)
1121{
1122
1123 while (isspace((u_char)*line))
1124 line++;
1125
1126 if (*line != '\0') {
1127 Parse_Error(PARSE_WARNING, "junk after .else ignored '%s'", line);
1128 }
1129
1130 if (condTop == MAXIF) {
1131 Parse_Error(PARSE_FATAL, "if-less else");
1132 return;
1133 }
1134 if (skipIfLevel != 0)
1135 return;
1136
1137 if (skipIfLevel != 0 || condStack[condTop]) {
1138 /*
1139 * An else should only take effect if its corresponding if was
1140 * evaluated and FALSE.
1141 * If its if was TRUE or skipped, we return COND_SKIP (and
1142 * start skipping in case we weren't already), leaving the
1143 * stack unmolested so later elif's don't screw up...
1144 * XXX How does this work with two .else's?
1145 */
1146 skipLine = TRUE;
1147 return;
1148 }
1149
1150 /* inverse value */
1151 condStack[condTop] = !condStack[condTop];
1152 skipLine = !condStack[condTop];
1153}
1154
1155/**
1156 * Cond_Endif
1157 * Handle .endif statement.
1158 */
1159void
1160Cond_Endif(char *line __unused, int code __unused, int lineno __unused)
1161{
1162
1163 while (isspace((u_char)*line))
1164 line++;
1165
1166 if (*line != '\0') {
1167 Parse_Error(PARSE_WARNING, "junk after .endif ignored '%s'", line);
1168 }
1169 /*
1170 * End of a conditional section. If skipIfLevel is non-zero,
1171 * that conditional was skipped, so lines following it should
1172 * also be skipped. Hence, we return COND_SKIP. Otherwise,
1173 * the conditional was read so succeeding lines should be
1174 * parsed (think about it...) so we return COND_PARSE, unless
1175 * this endif isn't paired with a decent if.
1176 */
1177 if (skipIfLevel != 0) {
1178 skipIfLevel -= 1;
1179 return;
1180 }
1181
1182 if (condTop == MAXIF) {
1183 Parse_Error(PARSE_FATAL, "if-less endif");
1184 return;
1185 }
1186
1187 /* pop */
1188 skipLine = FALSE;
1189 condTop += 1;
1190}
1191
1192/**
1201 * Cond_End
1202 * Make sure everything's clean at the end of a makefile.
1203 *
1204 * Side Effects:
1205 * Parse_Error will be called if open conditionals are around.
1206 */
1207void
1208Cond_End(void)

--- 20 unchanged lines hidden ---
1193 * Cond_End
1194 * Make sure everything's clean at the end of a makefile.
1195 *
1196 * Side Effects:
1197 * Parse_Error will be called if open conditionals are around.
1198 */
1199void
1200Cond_End(void)

--- 20 unchanged lines hidden ---