(file) Return to ifparser.c CVS log (file) (dir) Up to [XFree86 CVS] / xc / config / makedepend

  1 dawes 1.1 /*
  2            * $XConsortium: ifparser.c,v 1.7 94/01/18 21:30:50 rws Exp $
  3            *
  4            * Copyright 1992 Network Computing Devices, Inc.
  5            * 
  6            * Permission to use, copy, modify, and distribute this software and its
  7            * documentation for any purpose and without fee is hereby granted, provided
  8            * that the above copyright notice appear in all copies and that both that
  9            * copyright notice and this permission notice appear in supporting
 10            * documentation, and that the name of Network Computing Devices may not be
 11            * used in advertising or publicity pertaining to distribution of the software
 12            * without specific, written prior permission.  Network Computing Devices makes
 13            * no representations about the suitability of this software for any purpose.
 14            * It is provided ``as is'' without express or implied warranty.
 15            * 
 16            * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 17            * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
 18            * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
 19            * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 20            * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 21            * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 22 dawes 1.1  * PERFORMANCE OF THIS SOFTWARE.
 23            * 
 24            * Author:  Jim Fulton
 25            *          Network Computing Devices, Inc.
 26            * 
 27            * Simple if statement processor
 28            *
 29            * This module can be used to evaluate string representations of C language
 30            * if constructs.  It accepts the following grammar:
 31            * 
 32            *     EXPRESSION	:=	VALUE
 33            * 			 |	VALUE  BINOP	EXPRESSION
 34            * 
 35            *     VALUE		:=	'('  EXPRESSION  ')'
 36            * 			 |	'!'  VALUE
 37            * 			 |	'-'  VALUE
 38            * 			 |	'defined'  '('  variable  ')'
 39            * 			 |	'defined'  variable
 40            *			 |	# variable '(' variable-list ')'
 41            * 			 |	variable
 42            * 			 |	number
 43 dawes 1.1  * 
 44            *     BINOP		:=	'*'	|  '/'	|  '%'
 45            * 			 |	'+'	|  '-'
 46            * 			 |	'<<'	|  '>>'
 47            * 			 |	'<'	|  '>'	|  '<='  |  '>='
 48            * 			 |	'=='	|  '!='
 49            * 			 |	'&'	|  '|'
 50            * 			 |	'&&'	|  '||'
 51            * 
 52            * The normal C order of precidence is supported.
 53            * 
 54            * 
 55            * External Entry Points:
 56            * 
 57            *     ParseIfExpression		parse a string for #if
 58            */
 59           
 60           #include "ifparser.h"
 61           #include <ctype.h>
 62           
 63           /****************************************************************************
 64 dawes 1.1 		   Internal Macros and Utilities for Parser
 65            ****************************************************************************/
 66           
 67           #define DO(val) if (!(val)) return NULL
 68           #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
 69           #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
 70           #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
 71           
 72           
 73           static const char *
 74           parse_variable (g, cp, varp)
 75               IfParser *g;
 76               const char *cp;
 77               const char **varp;
 78           {
 79               SKIPSPACE (cp);
 80           
 81               if (!isvarfirstletter (*cp))
 82           	return CALLFUNC(g, handle_error) (g, cp, "variable name");
 83           
 84               *varp = cp;
 85 dawes 1.1     /* EMPTY */
 86               for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
 87               return cp;
 88           }
 89           
 90           
 91           static const char *
 92           parse_number (g, cp, valp)
 93               IfParser *g;
 94               const char *cp;
 95               int *valp;
 96           {
 97               SKIPSPACE (cp);
 98           
 99               if (!isdigit(*cp))
100           	return CALLFUNC(g, handle_error) (g, cp, "number");
101           
102           #ifdef WIN32
103               *valp = strtol(cp, &cp, 0);
104           #else
105               *valp = atoi (cp);
106 dawes 1.1     /* EMPTY */
107               for (cp++; isdigit(*cp); cp++) ;
108           #endif
109               return cp;
110           }
111           
112           
113           static const char *
114           parse_value (g, cp, valp)
115               IfParser *g;
116               const char *cp;
117               int *valp;
118           {
119               const char *var;
120           
121               *valp = 0;
122           
123               SKIPSPACE (cp);
124               if (!*cp)
125           	return cp;
126           
127 dawes 1.1     switch (*cp) {
128                 case '(':
129           	DO (cp = ParseIfExpression (g, cp + 1, valp));
130           	SKIPSPACE (cp);
131           	if (*cp != ')') 
132           	    return CALLFUNC(g, handle_error) (g, cp, ")");
133           
134           	return cp + 1;			/* skip the right paren */
135           
136                 case '!':
137           	DO (cp = parse_value (g, cp + 1, valp));
138           	*valp = !(*valp);
139           	return cp;
140           
141                 case '-':
142           	DO (cp = parse_value (g, cp + 1, valp));
143           	*valp = -(*valp);
144           	return cp;
145           
146                 case '#':
147           	DO (cp = parse_variable (g, cp + 1, &var));
148 dawes 1.1 	SKIPSPACE (cp);
149           	if (*cp != '(')
150           	    return CALLFUNC(g, handle_error) (g, cp, "(");
151           	do {
152           	    DO (cp = parse_variable (g, cp + 1, &var));
153           	    SKIPSPACE (cp);
154           	} while (*cp && *cp != ')');
155           	if (*cp != ')')
156           	    return CALLFUNC(g, handle_error) (g, cp, ")");
157           	*valp = 1; /* XXX */
158           	return cp + 1;
159           
160                 case 'd':
161           	if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
162           	    int paren = 0;
163           	    cp += 7;
164           	    SKIPSPACE (cp);
165           	    if (*cp == '(') {
166           		paren = 1;
167           		cp++;
168           	    }
169 dawes 1.1 	    DO (cp = parse_variable (g, cp, &var));
170           	    SKIPSPACE (cp);
171           	    if (paren && *cp != ')')
172           		return CALLFUNC(g, handle_error) (g, cp, ")");
173           	    *valp = (*(g->funcs.eval_defined)) (g, var, cp - var);
174           	    return cp + paren;		/* skip the right paren */
175           	}
176           	/* fall out */
177               }
178           
179               if (isdigit(*cp)) {
180           	DO (cp = parse_number (g, cp, valp));
181               } else if (!isvarfirstletter(*cp))
182           	return CALLFUNC(g, handle_error) (g, cp, "variable or number");
183               else {
184           	DO (cp = parse_variable (g, cp, &var));
185           	*valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
186               }
187               
188               return cp;
189           }
190 dawes 1.1 
191           
192           
193           static const char *
194           parse_product (g, cp, valp)
195               IfParser *g;
196               const char *cp;
197               int *valp;
198           {
199               int rightval;
200           
201               DO (cp = parse_value (g, cp, valp));
202               SKIPSPACE (cp);
203           
204               switch (*cp) {
205                 case '*':
206           	DO (cp = parse_product (g, cp + 1, &rightval));
207           	*valp = (*valp * rightval);
208           	break;
209           
210                 case '/':
211 dawes 1.1 	DO (cp = parse_product (g, cp + 1, &rightval));
212           	*valp = (*valp / rightval);
213           	break;
214           
215                 case '%':
216           	DO (cp = parse_product (g, cp + 1, &rightval));
217           	*valp = (*valp % rightval);
218           	break;
219               }
220               return cp;
221           }
222           
223           
224           static const char *
225           parse_sum (g, cp, valp)
226               IfParser *g;
227               const char *cp;
228               int *valp;
229           {
230               int rightval;
231           
232 dawes 1.1     DO (cp = parse_product (g, cp, valp));
233               SKIPSPACE (cp);
234           
235               switch (*cp) {
236                 case '+':
237           	DO (cp = parse_sum (g, cp + 1, &rightval));
238           	*valp = (*valp + rightval);
239           	break;
240           
241                 case '-':
242           	DO (cp = parse_sum (g, cp + 1, &rightval));
243           	*valp = (*valp - rightval);
244           	break;
245               }
246               return cp;
247           }
248           
249           
250           static const char *
251           parse_shift (g, cp, valp)
252               IfParser *g;
253 dawes 1.1     const char *cp;
254               int *valp;
255           {
256               int rightval;
257           
258               DO (cp = parse_sum (g, cp, valp));
259               SKIPSPACE (cp);
260           
261               switch (*cp) {
262                 case '<':
263           	if (cp[1] == '<') {
264           	    DO (cp = parse_shift (g, cp + 2, &rightval));
265           	    *valp = (*valp << rightval);
266           	}
267           	break;
268           
269                 case '>':
270           	if (cp[1] == '>') {
271           	    DO (cp = parse_shift (g, cp + 2, &rightval));
272           	    *valp = (*valp >> rightval);
273           	}
274 dawes 1.1 	break;
275               }
276               return cp;
277           }
278           
279           
280           static const char *
281           parse_inequality (g, cp, valp)
282               IfParser *g;
283               const char *cp;
284               int *valp;
285           {
286               int rightval;
287           
288               DO (cp = parse_shift (g, cp, valp));
289               SKIPSPACE (cp);
290           
291               switch (*cp) {
292                 case '<':
293           	if (cp[1] == '=') {
294           	    DO (cp = parse_inequality (g, cp + 2, &rightval));
295 dawes 1.1 	    *valp = (*valp <= rightval);
296           	} else {
297           	    DO (cp = parse_inequality (g, cp + 1, &rightval));
298           	    *valp = (*valp < rightval);
299           	}
300           	break;
301           
302                 case '>':
303           	if (cp[1] == '=') {
304           	    DO (cp = parse_inequality (g, cp + 2, &rightval));
305           	    *valp = (*valp >= rightval);
306           	} else {
307           	    DO (cp = parse_inequality (g, cp + 1, &rightval));
308           	    *valp = (*valp > rightval);
309           	}
310           	break;
311               }
312               return cp;
313           }
314           
315           
316 dawes 1.1 static const char *
317           parse_equality (g, cp, valp)
318               IfParser *g;
319               const char *cp;
320               int *valp;
321           {
322               int rightval;
323           
324               DO (cp = parse_inequality (g, cp, valp));
325               SKIPSPACE (cp);
326           
327               switch (*cp) {
328                 case '=':
329           	if (cp[1] == '=')
330           	    cp++;
331           	DO (cp = parse_equality (g, cp + 1, &rightval));
332           	*valp = (*valp == rightval);
333           	break;
334           
335                 case '!':
336           	if (cp[1] != '=')
337 dawes 1.1 	    break;
338           	DO (cp = parse_equality (g, cp + 2, &rightval));
339           	*valp = (*valp != rightval);
340           	break;
341               }
342               return cp;
343           }
344           
345           
346           static const char *
347           parse_band (g, cp, valp)
348               IfParser *g;
349               const char *cp;
350               int *valp;
351           {
352               int rightval;
353           
354               DO (cp = parse_equality (g, cp, valp));
355               SKIPSPACE (cp);
356           
357               switch (*cp) {
358 dawes 1.1       case '&':
359           	if (cp[1] != '&') {
360           	    DO (cp = parse_band (g, cp + 1, &rightval));
361           	    *valp = (*valp & rightval);
362           	}
363           	break;
364               }
365               return cp;
366           }
367           
368           
369           static const char *
370           parse_bor (g, cp, valp)
371               IfParser *g;
372               const char *cp;
373               int *valp;
374           {
375               int rightval;
376           
377               DO (cp = parse_band (g, cp, valp));
378               SKIPSPACE (cp);
379 dawes 1.1 
380               switch (*cp) {
381                 case '|':
382           	if (cp[1] != '|') {
383           	    DO (cp = parse_bor (g, cp + 1, &rightval));
384           	    *valp = (*valp | rightval);
385           	}
386           	break;
387               }
388               return cp;
389           }
390           
391           
392           static const char *
393           parse_land (g, cp, valp)
394               IfParser *g;
395               const char *cp;
396               int *valp;
397           {
398               int rightval;
399           
400 dawes 1.1     DO (cp = parse_bor (g, cp, valp));
401               SKIPSPACE (cp);
402           
403               switch (*cp) {
404                 case '&':
405           	if (cp[1] != '&')
406           	    return CALLFUNC(g, handle_error) (g, cp, "&&");
407           	DO (cp = parse_land (g, cp + 2, &rightval));
408           	*valp = (*valp && rightval);
409           	break;
410               }
411               return cp;
412           }
413           
414           
415           static const char *
416           parse_lor (g, cp, valp)
417               IfParser *g;
418               const char *cp;
419               int *valp;
420           {
421 dawes 1.1     int rightval;
422           
423               DO (cp = parse_land (g, cp, valp));
424               SKIPSPACE (cp);
425           
426               switch (*cp) {
427                 case '|':
428           	if (cp[1] != '|')
429           	    return CALLFUNC(g, handle_error) (g, cp, "||");
430           	DO (cp = parse_lor (g, cp + 2, &rightval));
431           	*valp = (*valp || rightval);
432           	break;
433               }
434               return cp;
435           }
436           
437           
438           /****************************************************************************
439           			     External Entry Points
440            ****************************************************************************/
441           
442 dawes 1.1 const char *
443           ParseIfExpression (g, cp, valp)
444               IfParser *g;
445               const char *cp;
446               int *valp;
447           {
448               return parse_lor (g, cp, valp);
449           }
450           
451           

Powered by
ViewCVS 0.9.2