summaryrefslogtreecommitdiff
path: root/ifparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'ifparser.c')
-rw-r--r--ifparser.c144
1 files changed, 85 insertions, 59 deletions
diff --git a/ifparser.c b/ifparser.c
index aa51748..49dff21 100644
--- a/ifparser.c
+++ b/ifparser.c
@@ -2,7 +2,7 @@
* $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $
*
* Copyright 1992 Network Computing Devices, Inc.
- *
+ *
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
@@ -12,7 +12,7 @@
* without specific, written prior permission. Network Computing Devices makes
* no representations about the suitability of this software for any purpose.
* It is provided ``as is'' without express or implied warranty.
- *
+ *
* NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
* IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
@@ -20,46 +20,47 @@
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
- *
+ *
* Author: Jim Fulton
* Network Computing Devices, Inc.
- *
+ *
* Simple if statement processor
*
* This module can be used to evaluate string representations of C language
* if constructs. It accepts the following grammar:
- *
+ *
* EXPRESSION := VALUE
- * | VALUE BINOP EXPRESSION
+ * | VALUE BINOP EXPRESSION
* | VALUE '?' EXPRESSION ':' EXPRESSION
- *
+ *
* VALUE := '(' EXPRESSION ')'
- * | '!' VALUE
- * | '-' VALUE
- * | '+' VALUE
+ * | '!' VALUE
+ * | '-' VALUE
+ * | '+' VALUE
* | '~' VALUE
- * | 'defined' '(' variable ')'
- * | 'defined' variable
+ * | 'defined' '(' variable_name ')'
+ * | 'defined' variable_name
* | # variable '(' variable-list ')'
- * | variable
- * | number
- *
+ * | variable(arglist)
+ * | variable
+ * | number
+ *
* BINOP := '*' | '/' | '%'
- * | '+' | '-'
- * | '<<' | '>>'
- * | '<' | '>' | '<=' | '>='
- * | '==' | '!='
- * | '&' | '^' | '|'
- * | '&&' | '||'
- *
+ * | '+' | '-'
+ * | '<<' | '>>'
+ * | '<' | '>' | '<=' | '>='
+ * | '==' | '!='
+ * | '&' | '^' | '|'
+ * | '&&' | '||'
+ *
* The normal C order of precedence is supported.
- *
- *
+ *
+ *
* External Entry Points:
- *
+ *
* ParseIfExpression parse a string for #if
*/
-/* $XFree86: xc/config/makedepend/ifparser.c,v 3.10tsi Exp $ */
+/* $XFree86: xc/config/makedepend/ifparser.c,v 3.12 2004/03/05 16:02:58 tsi Exp $ */
#include "ifparser.h"
#include <ctype.h>
@@ -77,16 +78,53 @@
static const char *
-parse_variable (IfParser *g, const char *cp, const char **varp)
+parse_variable_name (IfParser *g, const char *cp, const char **varp, int *varlenp)
+{
+ *varlenp = 0;
+
+ SKIPSPACE (cp);
+
+ if (!isvarfirstletter(*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "variable name");
+
+ *varp = cp;
+ for (cp++; isalnum(*cp) || *cp == '_'; cp++) /* EMPTY */;
+ *varlenp = cp - *varp;
+
+ return cp;
+}
+
+
+static const char *
+parse_variable (IfParser *g, const char *cp, const char **varp, int *varlenp, const char **argsp)
{
+ *argsp = NULL;
+ *varlenp = 0;
+
SKIPSPACE (cp);
+ /* this error handling call might prevent us from merging with above code */
if (!isvarfirstletter (*cp))
return CALLFUNC(g, handle_error) (g, cp, "variable name");
*varp = cp;
- /* EMPTY */
- for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
+ for (cp++; isalnum(*cp) || *cp == '_'; cp++) /* EMPTY */;
+ *varlenp = cp - *varp;
+
+ if (variable_has_args(g, *varp, *varlenp))
+ {
+ SKIPSPACE (cp);
+ if (*cp != '(')
+ {
+ return CALLFUNC(g, handle_error) (g, cp, "argument list");
+ }
+ cp++;
+
+ *argsp = cp;
+ for (cp++; *cp != ')'; cp++) /* EMPTY */;
+ cp++;
+ }
+
return cp;
}
@@ -171,7 +209,8 @@ parse_character (IfParser *g, const char *cp, long *valp)
static const char *
parse_value (IfParser *g, const char *cp, long *valp)
{
- const char *var, *varend;
+ const char *var, *args;
+ int varlen;
*valp = 0;
@@ -183,7 +222,7 @@ parse_value (IfParser *g, const char *cp, long *valp)
case '(':
DO (cp = ParseIfExpression (g, cp + 1, valp));
SKIPSPACE (cp);
- if (*cp != ')')
+ if (*cp != ')')
return CALLFUNC(g, handle_error) (g, cp, ")");
return cp + 1; /* skip the right paren */
@@ -208,12 +247,12 @@ parse_value (IfParser *g, const char *cp, long *valp)
return cp;
case '#':
- DO (cp = parse_variable (g, cp + 1, &var));
+ DO (cp = parse_variable (g, cp + 1, &var, &varlen, &args));
SKIPSPACE (cp);
if (*cp != '(')
return CALLFUNC(g, handle_error) (g, cp, "(");
do {
- DO (cp = parse_variable (g, cp + 1, &var));
+ DO (cp = parse_variable (g, cp + 1, &var, &varlen, &args));
SKIPSPACE (cp);
} while (*cp && *cp != ')');
if (*cp != ')')
@@ -230,7 +269,6 @@ parse_value (IfParser *g, const char *cp, long *valp)
case 'd':
if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
int paren = 0;
- int len;
cp += 7;
SKIPSPACE (cp);
@@ -238,43 +276,31 @@ parse_value (IfParser *g, const char *cp, long *valp)
paren = 1;
cp++;
}
- DO (cp = parse_variable (g, cp, &var));
- len = cp - var;
+ DO (cp = parse_variable_name (g, cp, &var, &varlen));
SKIPSPACE (cp);
if (paren && *cp != ')')
return CALLFUNC(g, handle_error) (g, cp, ")");
- *valp = (*(g->funcs.eval_defined)) (g, var, len);
+ *valp = (*(g->funcs.eval_defined)) (g, var, varlen);
return cp + paren; /* skip the right paren */
}
/* fall out */
}
if (isdigit(*cp)) {
+ /* determine the numeric value */
DO (cp = parse_number (g, cp, valp));
- } else if (!isvarfirstletter(*cp))
- return CALLFUNC(g, handle_error) (g, cp, "variable or number");
+ } else if (isvarfirstletter(*cp)) {
+ /* resolve the value of this macro.
+ * (macro argument substitution will take place
+ * and recursive macro resolvement will apply) */
+ DO (cp = parse_variable (g, cp, &var, &varlen, &args));
+ *valp = (*(g->funcs.eval_variable)) (g, var, varlen, args);
+ }
else {
- DO (cp = parse_variable (g, cp, &var));
- varend = cp;
- SKIPSPACE(cp);
- if (*cp != '(') {
- *valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
- } else {
- do {
- long dummy;
- DO (cp = ParseIfExpression (g, cp + 1, &dummy));
- SKIPSPACE(cp);
- if (*cp == ')')
- break;
- if (*cp != ',')
- return CALLFUNC(g, handle_error) (g, cp, ",");
- } while (1);
-
- *valp = 1; /* XXX */
- cp++;
- }
+ /* we finally got something that does not fit the syntax rules */
+ return CALLFUNC(g, handle_error) (g, cp, "variable or number");
}
-
+
return cp;
}