Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / soltools / mkdepend / ifparser.c
blob6518b1e5a974a9e97d08c82c9458b311b0cf186a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * $XConsortium: ifparser.c,v 1.8 95/06/03 00:01:41 gildea Exp $
5 * Copyright 1992 Network Computing Devices, Inc.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Network Computing Devices may not be
12 * used in advertising or publicity pertaining to distribution of the software
13 * without specific, written prior permission. Network Computing Devices makes
14 * no representations about the suitability of this software for any purpose.
15 * It is provided ``as is'' without express or implied warranty.
17 * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
19 * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
20 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
25 * Author: Jim Fulton
26 * Network Computing Devices, Inc.
28 * Simple if statement processor
30 * This module can be used to evaluate string representations of C language
31 * if constructs. It accepts the following grammar:
33 * EXPRESSION := VALUE
34 * | VALUE BINOP EXPRESSION
36 * VALUE := '(' EXPRESSION ')'
37 * | '!' VALUE
38 * | '-' VALUE
39 * | 'defined' '(' variable ')'
40 * | 'defined' variable
41 * | # variable '(' variable-list ')'
42 * | variable
43 * | number
45 * BINOP := '*' | '/' | '%'
46 * | '+' | '-'
47 * | '<<' | '>>'
48 * | '<' | '>' | '<=' | '>='
49 * | '==' | '!='
50 * | '&' | '|'
51 * | '&&' | '||'
53 * The normal C order of precidence is supported.
56 * External Entry Points:
58 * ParseIfExpression parse a string for #if
61 #include "ifparser.h"
62 #include <ctype.h>
63 #include <stdlib.h>
64 #include <string.h>
66 /****************************************************************************
67 Internal Macros and Utilities for Parser
68 ****************************************************************************/
70 #define DO(val) if (!(val)) return NULL
71 #define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
72 #define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
73 #define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
76 static const char *
77 parse_variable (g, cp, varp)
78 IfParser *g;
79 const char *cp;
80 const char **varp;
82 SKIPSPACE (cp);
84 if (!isvarfirstletter (*cp))
85 return CALLFUNC(g, handle_error) (g, cp, "variable name");
87 *varp = cp;
88 /* EMPTY */
89 for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
90 return cp;
94 static const char *
95 parse_number (g, cp, valp)
96 IfParser *g;
97 const char *cp;
98 int *valp;
100 SKIPSPACE (cp);
102 if (!isdigit(*cp))
103 return CALLFUNC(g, handle_error) (g, cp, "number");
105 #ifdef WIN32
107 char *cp2;
108 *valp = strtol(cp, &cp2, 0);
110 #else
111 *valp = atoi (cp);
112 /* EMPTY */
113 for (cp++; isdigit(*cp); cp++) ;
114 #endif
115 return cp;
119 static const char *
120 parse_value (g, cp, valp)
121 IfParser *g;
122 const char *cp;
123 int *valp;
125 const char *var;
127 *valp = 0;
129 SKIPSPACE (cp);
130 if (!*cp)
131 return cp;
133 switch (*cp) {
134 case '(':
135 DO (cp = ParseIfExpression (g, cp + 1, valp));
136 SKIPSPACE (cp);
137 if (*cp != ')')
138 return CALLFUNC(g, handle_error) (g, cp, ")");
140 return cp + 1; /* skip the right paren */
142 case '!':
143 DO (cp = parse_value (g, cp + 1, valp));
144 *valp = !(*valp);
145 return cp;
147 case '-':
148 DO (cp = parse_value (g, cp + 1, valp));
149 *valp = -(*valp);
150 return cp;
152 case '#':
153 DO (cp = parse_variable (g, cp + 1, &var));
154 SKIPSPACE (cp);
155 if (*cp != '(')
156 return CALLFUNC(g, handle_error) (g, cp, "(");
157 do {
158 DO (cp = parse_variable (g, cp + 1, &var));
159 SKIPSPACE (cp);
160 } while (*cp && *cp != ')');
161 if (*cp != ')')
162 return CALLFUNC(g, handle_error) (g, cp, ")");
163 *valp = 1; /* XXX */
164 return cp + 1;
166 case 'd':
167 if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
168 int paren = 0;
169 int len;
171 cp += 7;
172 SKIPSPACE (cp);
173 if (*cp == '(') {
174 paren = 1;
175 cp++;
177 DO (cp = parse_variable (g, cp, &var));
178 len = (int)(cp - var);
179 SKIPSPACE (cp);
180 if (paren && *cp != ')')
181 return CALLFUNC(g, handle_error) (g, cp, ")");
182 *valp = (*(g->funcs.eval_defined)) (g, var, len);
183 return cp + paren; /* skip the right paren */
185 /* fall out */
188 if (isdigit(*cp)) {
189 DO (cp = parse_number (g, cp, valp));
190 } else if (!isvarfirstletter(*cp))
191 return CALLFUNC(g, handle_error) (g, cp, "variable or number");
192 else {
193 DO (cp = parse_variable (g, cp, &var));
194 *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
197 return cp;
202 static const char *
203 parse_product (g, cp, valp)
204 IfParser *g;
205 const char *cp;
206 int *valp;
208 int rightval;
210 DO (cp = parse_value (g, cp, valp));
211 SKIPSPACE (cp);
213 switch (*cp) {
214 case '*':
215 DO (cp = parse_product (g, cp + 1, &rightval));
216 *valp = (*valp * rightval);
217 break;
219 case '/':
220 DO (cp = parse_product (g, cp + 1, &rightval));
222 /* Do nothing in the divide-by-zero case. */
223 if (rightval) {
224 *valp = (*valp / rightval);
226 break;
228 case '%':
229 DO (cp = parse_product (g, cp + 1, &rightval));
230 *valp = (*valp % rightval);
231 break;
233 return cp;
237 static const char *
238 parse_sum (g, cp, valp)
239 IfParser *g;
240 const char *cp;
241 int *valp;
243 int rightval;
245 DO (cp = parse_product (g, cp, valp));
246 SKIPSPACE (cp);
248 switch (*cp) {
249 case '+':
250 DO (cp = parse_sum (g, cp + 1, &rightval));
251 *valp = (*valp + rightval);
252 break;
254 case '-':
255 DO (cp = parse_sum (g, cp + 1, &rightval));
256 *valp = (*valp - rightval);
257 break;
259 return cp;
263 static const char *
264 parse_shift (g, cp, valp)
265 IfParser *g;
266 const char *cp;
267 int *valp;
269 int rightval;
271 DO (cp = parse_sum (g, cp, valp));
272 SKIPSPACE (cp);
274 switch (*cp) {
275 case '<':
276 if (cp[1] == '<') {
277 DO (cp = parse_shift (g, cp + 2, &rightval));
278 *valp = (*valp << rightval);
280 break;
282 case '>':
283 if (cp[1] == '>') {
284 DO (cp = parse_shift (g, cp + 2, &rightval));
285 *valp = (*valp >> rightval);
287 break;
289 return cp;
293 static const char *
294 parse_inequality (g, cp, valp)
295 IfParser *g;
296 const char *cp;
297 int *valp;
299 int rightval;
301 DO (cp = parse_shift (g, cp, valp));
302 SKIPSPACE (cp);
304 switch (*cp) {
305 case '<':
306 if (cp[1] == '=') {
307 DO (cp = parse_inequality (g, cp + 2, &rightval));
308 *valp = (*valp <= rightval);
309 } else {
310 DO (cp = parse_inequality (g, cp + 1, &rightval));
311 *valp = (*valp < rightval);
313 break;
315 case '>':
316 if (cp[1] == '=') {
317 DO (cp = parse_inequality (g, cp + 2, &rightval));
318 *valp = (*valp >= rightval);
319 } else {
320 DO (cp = parse_inequality (g, cp + 1, &rightval));
321 *valp = (*valp > rightval);
323 break;
325 return cp;
329 static const char *
330 parse_equality (g, cp, valp)
331 IfParser *g;
332 const char *cp;
333 int *valp;
335 int rightval;
337 DO (cp = parse_inequality (g, cp, valp));
338 SKIPSPACE (cp);
340 switch (*cp) {
341 case '=':
342 if (cp[1] == '=')
343 cp++;
344 DO (cp = parse_equality (g, cp + 1, &rightval));
345 *valp = (*valp == rightval);
346 break;
348 case '!':
349 if (cp[1] != '=')
350 break;
351 DO (cp = parse_equality (g, cp + 2, &rightval));
352 *valp = (*valp != rightval);
353 break;
355 return cp;
359 static const char *
360 parse_band (g, cp, valp)
361 IfParser *g;
362 const char *cp;
363 int *valp;
365 int rightval;
367 DO (cp = parse_equality (g, cp, valp));
368 SKIPSPACE (cp);
370 switch (*cp) {
371 case '&':
372 if (cp[1] != '&') {
373 DO (cp = parse_band (g, cp + 1, &rightval));
374 *valp = (*valp & rightval);
376 break;
378 return cp;
382 static const char *
383 parse_bor (g, cp, valp)
384 IfParser *g;
385 const char *cp;
386 int *valp;
388 int rightval;
390 DO (cp = parse_band (g, cp, valp));
391 SKIPSPACE (cp);
393 switch (*cp) {
394 case '|':
395 if (cp[1] != '|') {
396 DO (cp = parse_bor (g, cp + 1, &rightval));
397 *valp = (*valp | rightval);
399 break;
401 return cp;
405 static const char *
406 parse_land (g, cp, valp)
407 IfParser *g;
408 const char *cp;
409 int *valp;
411 int rightval;
413 DO (cp = parse_bor (g, cp, valp));
414 SKIPSPACE (cp);
416 switch (*cp) {
417 case '&':
418 if (cp[1] != '&')
419 return CALLFUNC(g, handle_error) (g, cp, "&&");
420 DO (cp = parse_land (g, cp + 2, &rightval));
421 *valp = (*valp && rightval);
422 break;
424 return cp;
428 static const char *
429 parse_lor (g, cp, valp)
430 IfParser *g;
431 const char *cp;
432 int *valp;
434 int rightval;
436 DO (cp = parse_land (g, cp, valp));
437 SKIPSPACE (cp);
439 switch (*cp) {
440 case '|':
441 if (cp[1] != '|')
442 return CALLFUNC(g, handle_error) (g, cp, "||");
443 DO (cp = parse_lor (g, cp + 2, &rightval));
444 *valp = (*valp || rightval);
445 break;
447 return cp;
451 /****************************************************************************
452 External Entry Points
453 ****************************************************************************/
455 const char *
456 ParseIfExpression (g, cp, valp)
457 IfParser *g;
458 const char *cp;
459 int *valp;
461 return parse_lor (g, cp, valp);
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */