2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $XConsortium: ifparser.c /main/10 1996/09/28 16:15:18 rws $
26 * Copyright 1992 Network Computing Devices, Inc.
28 * Permission to use, copy, modify, and distribute this software and its
29 * documentation for any purpose and without fee is hereby granted, provided
30 * that the above copyright notice appear in all copies and that both that
31 * copyright notice and this permission notice appear in supporting
32 * documentation, and that the name of Network Computing Devices may not be
33 * used in advertising or publicity pertaining to distribution of the software
34 * without specific, written prior permission. Network Computing Devices makes
35 * no representations about the suitability of this software for any purpose.
36 * It is provided ``as is'' without express or implied warranty.
38 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
39 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
40 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
41 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
42 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
43 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44 * PERFORMANCE OF THIS SOFTWARE.
47 * Network Computing Devices, Inc.
49 * Simple if statement processor
51 * This module can be used to evaluate string representations of C language
52 * if constructs. It accepts the following grammar:
55 * | VALUE BINOP EXPRESSION
57 * VALUE := '(' EXPRESSION ')'
60 * | 'defined' '(' variable ')'
61 * | 'defined' variable
62 * | # variable '(' variable-list ')'
66 * BINOP := '*' | '/' | '%'
69 * | '<' | '>' | '<=' | '>='
74 * The normal C order of precidence is supported.
77 * External Entry Points:
79 * ParseIfExpression parse a string for #if
88 /****************************************************************************
89 Internal Macros and Utilities for Parser
90 ****************************************************************************/
92 #define DO(val) if (!(val)) return NULL
93 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
94 #define SKIPSPACE(ccc) while (isspace((int)*ccc)) ccc++
95 #define isvarfirstletter(ccc) (isalpha((int)ccc) || (ccc) == '_')
99 parse_variable (g, cp, varp)
106 if (!isvarfirstletter (*cp))
107 return CALLFUNC(g, handle_error) (g, cp, "variable name");
111 for (cp++; isalnum((int)*cp) || *cp == '_'; cp++) ;
117 parse_number (g, cp, valp)
125 if (!isdigit((int)*cp))
126 return CALLFUNC(g, handle_error) (g, cp, "number");
132 if ((*cp == 'x') || (*cp == 'X')) {
140 /* Ignore overflows and assume ASCII, what source is usually written in */
144 if ((*cp >= '0') && (*cp <= '7'))
145 increment = *cp++ - '0';
146 } else if (base == 16) {
147 if ((*cp >= '0') && (*cp <= '9'))
148 increment = *cp++ - '0';
149 else if ((*cp >= 'A') && (*cp <= 'F'))
150 increment = *cp++ - ('A' - 10);
151 else if ((*cp >= 'a') && (*cp <= 'f'))
152 increment = *cp++ - ('a' - 10);
153 } else { /* Decimal */
154 if ((*cp >= '0') && (*cp <= '9'))
155 increment = *cp++ - '0';
159 *valp = (*valp * base) + increment;
162 /* Skip trailing qualifiers */
163 while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
168 parse_character (g, cp, valp)
178 case 'n': val = '\n'; break;
179 case 't': val = '\t'; break;
180 case 'v': val = '\v'; break;
181 case 'b': val = '\b'; break;
182 case 'r': val = '\r'; break;
183 case 'f': val = '\f'; break;
184 case 'a': val = '\a'; break;
185 case '\\': val = '\\'; break;
186 case '?': val = '\?'; break;
187 case '\'': val = '\''; break;
188 case '\"': val = '\"'; break;
189 case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
190 default: val = (char) strtol (cp + 1, NULL, 8); break;
194 while (*cp != '\'') cp++;
200 parse_value (g, cp, valp)
205 const char *var, *varend;
215 DO (cp = ParseIfExpression (g, cp + 1, valp));
218 return CALLFUNC(g, handle_error) (g, cp, ")");
220 return cp + 1; /* skip the right paren */
223 DO (cp = parse_value (g, cp + 1, valp));
228 DO (cp = parse_value (g, cp + 1, valp));
233 DO (cp = parse_value (g, cp + 1, valp));
238 DO (cp = parse_value (g, cp + 1, valp));
243 DO (cp = parse_variable (g, cp + 1, &var));
246 return CALLFUNC(g, handle_error) (g, cp, "(");
248 DO (cp = parse_variable (g, cp + 1, &var));
250 } while (*cp && *cp != ')');
252 return CALLFUNC(g, handle_error) (g, cp, ")");
257 DO (cp = parse_character (g, cp + 1, valp));
259 return CALLFUNC(g, handle_error) (g, cp, "'");
263 if (strncmp (cp, "defined", 7) == 0 && !isalnum((int)cp[7])) {
273 DO (cp = parse_variable (g, cp, &var));
276 if (paren && *cp != ')')
277 return CALLFUNC(g, handle_error) (g, cp, ")");
278 *valp = (*(g->funcs.eval_defined)) (g, var, len);
279 return cp + paren; /* skip the right paren */
284 if (isdigit((int)*cp)) {
285 DO (cp = parse_number (g, cp, valp));
286 } else if (!isvarfirstletter(*cp))
287 return CALLFUNC(g, handle_error) (g, cp, "variable or number");
289 DO (cp = parse_variable (g, cp, &var));
293 *valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
297 DO (cp = ParseIfExpression (g, cp + 1, &dummy));
302 return CALLFUNC(g, handle_error) (g, cp, ",");
316 parse_product (g, cp, valp)
323 DO (cp = parse_value (g, cp, valp));
328 DO (cp = parse_product (g, cp + 1, &rightval));
329 *valp = (*valp * rightval);
333 DO (cp = parse_product (g, cp + 1, &rightval));
335 *valp = (*valp / rightval);
341 DO (cp = parse_product (g, cp + 1, &rightval));
342 *valp = (*valp % rightval);
350 parse_sum (g, cp, valp)
357 DO (cp = parse_product (g, cp, valp));
362 DO (cp = parse_sum (g, cp + 1, &rightval));
363 *valp = (*valp + rightval);
367 DO (cp = parse_sum (g, cp + 1, &rightval));
368 *valp = (*valp - rightval);
376 parse_shift (g, cp, valp)
383 DO (cp = parse_sum (g, cp, valp));
389 DO (cp = parse_shift (g, cp + 2, &rightval));
390 *valp = (*valp << rightval);
396 DO (cp = parse_shift (g, cp + 2, &rightval));
397 *valp = (*valp >> rightval);
406 parse_inequality (g, cp, valp)
413 DO (cp = parse_shift (g, cp, valp));
419 DO (cp = parse_inequality (g, cp + 2, &rightval));
420 *valp = (*valp <= rightval);
422 DO (cp = parse_inequality (g, cp + 1, &rightval));
423 *valp = (*valp < rightval);
429 DO (cp = parse_inequality (g, cp + 2, &rightval));
430 *valp = (*valp >= rightval);
432 DO (cp = parse_inequality (g, cp + 1, &rightval));
433 *valp = (*valp > rightval);
442 parse_equality (g, cp, valp)
449 DO (cp = parse_inequality (g, cp, valp));
456 DO (cp = parse_equality (g, cp + 1, &rightval));
457 *valp = (*valp == rightval);
463 DO (cp = parse_equality (g, cp + 2, &rightval));
464 *valp = (*valp != rightval);
472 parse_band (g, cp, valp)
479 DO (cp = parse_equality (g, cp, valp));
485 DO (cp = parse_band (g, cp + 1, &rightval));
486 *valp = (*valp & rightval);
495 parse_bxor (g, cp, valp)
502 DO (cp = parse_band (g, cp, valp));
507 DO (cp = parse_bxor (g, cp + 1, &rightval));
508 *valp = (*valp ^ rightval);
516 parse_bor (g, cp, valp)
523 DO (cp = parse_bxor (g, cp, valp));
529 DO (cp = parse_bor (g, cp + 1, &rightval));
530 *valp = (*valp | rightval);
539 parse_land (g, cp, valp)
546 DO (cp = parse_bor (g, cp, valp));
552 return CALLFUNC(g, handle_error) (g, cp, "&&");
553 DO (cp = parse_land (g, cp + 2, &rightval));
554 *valp = (*valp && rightval);
562 parse_lor (g, cp, valp)
569 DO (cp = parse_land (g, cp, valp));
575 return CALLFUNC(g, handle_error) (g, cp, "||");
576 DO (cp = parse_lor (g, cp + 2, &rightval));
577 *valp = (*valp || rightval);
584 /****************************************************************************
585 External Entry Points
586 ****************************************************************************/
589 ParseIfExpression (g, cp, valp)
594 return parse_lor (g, cp, valp);