Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / soltools / mkdepend / ifparser.c
blob8777e795f18e39816b52ff6e145502e1ac292225
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((unsigned char)*ccc)) ccc++
73 #define isvarfirstletter(ccc) (isalpha((unsigned char)(ccc)) || (ccc) == '_')
76 static const char *
77 parse_variable (IfParser *g, const char *cp, const char **varp)
79 SKIPSPACE (cp);
81 if (!isvarfirstletter (*cp))
82 return CALLFUNC(g, handle_error) (g, cp, "variable name");
84 *varp = cp;
85 /* EMPTY */
86 for (cp++; isalnum((unsigned char)*cp) || *cp == '_'; cp++) ;
87 return cp;
91 static const char *
92 parse_number (IfParser *g, const char *cp, int *valp)
94 SKIPSPACE (cp);
96 if (!isdigit((unsigned char)*cp))
97 return CALLFUNC(g, handle_error) (g, cp, "number");
99 #ifdef _WIN32
101 char *cp2;
102 *valp = strtol(cp, &cp2, 0);
104 #else
105 *valp = atoi (cp);
106 /* EMPTY */
107 for (cp++; isdigit((unsigned char)*cp); cp++) ;
108 #endif
109 return cp;
113 static const char *
114 parse_value (IfParser *g, const char *cp, int *valp)
116 const char *var;
118 *valp = 0;
120 SKIPSPACE (cp);
121 if (!*cp)
122 return cp;
124 switch (*cp) {
125 case '(':
126 DO (cp = ParseIfExpression (g, cp + 1, valp));
127 SKIPSPACE (cp);
128 if (*cp != ')')
129 return CALLFUNC(g, handle_error) (g, cp, ")");
131 return cp + 1; /* skip the right paren */
133 case '!':
134 DO (cp = parse_value (g, cp + 1, valp));
135 *valp = !(*valp);
136 return cp;
138 case '-':
139 DO (cp = parse_value (g, cp + 1, valp));
140 *valp = -(*valp);
141 return cp;
143 case '#':
144 DO (cp = parse_variable (g, cp + 1, &var));
145 SKIPSPACE (cp);
146 if (*cp != '(')
147 return CALLFUNC(g, handle_error) (g, cp, "(");
148 do {
149 DO (cp = parse_variable (g, cp + 1, &var));
150 SKIPSPACE (cp);
151 } while (*cp && *cp != ')');
152 if (*cp != ')')
153 return CALLFUNC(g, handle_error) (g, cp, ")");
154 *valp = 1; /* XXX */
155 return cp + 1;
157 case 'd':
158 if (strncmp (cp, "defined", 7) == 0 && !isalnum((unsigned char)cp[7])) {
159 int paren = 0;
160 size_t len;
162 cp += 7;
163 SKIPSPACE (cp);
164 if (*cp == '(') {
165 paren = 1;
166 cp++;
168 DO (cp = parse_variable (g, cp, &var));
169 len = (size_t)(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, len);
174 return cp + paren; /* skip the right paren */
176 /* fall out */
179 if (isdigit((unsigned char)*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, (size_t)(cp - var));
188 return cp;
193 static const char *
194 parse_product (IfParser *g, const char *cp, int *valp)
196 int rightval;
198 DO (cp = parse_value (g, cp, valp));
199 SKIPSPACE (cp);
201 switch (*cp) {
202 case '*':
203 DO (cp = parse_product (g, cp + 1, &rightval));
204 *valp = (*valp * rightval);
205 break;
207 case '/':
208 DO (cp = parse_product (g, cp + 1, &rightval));
210 /* Do nothing in the divide-by-zero case. */
211 if (rightval) {
212 *valp = (*valp / rightval);
214 break;
216 case '%':
217 DO (cp = parse_product (g, cp + 1, &rightval));
218 *valp = (*valp % rightval);
219 break;
221 return cp;
225 static const char *
226 parse_sum (IfParser *g, const char *cp, int *valp)
228 int rightval;
230 DO (cp = parse_product (g, cp, valp));
231 SKIPSPACE (cp);
233 switch (*cp) {
234 case '+':
235 DO (cp = parse_sum (g, cp + 1, &rightval));
236 *valp = (*valp + rightval);
237 break;
239 case '-':
240 DO (cp = parse_sum (g, cp + 1, &rightval));
241 *valp = (*valp - rightval);
242 break;
244 return cp;
248 static const char *
249 parse_shift (IfParser *g, const char *cp, int *valp)
251 int rightval;
253 DO (cp = parse_sum (g, cp, valp));
254 SKIPSPACE (cp);
256 switch (*cp) {
257 case '<':
258 if (cp[1] == '<') {
259 DO (cp = parse_shift (g, cp + 2, &rightval));
260 *valp = (*valp << rightval);
262 break;
264 case '>':
265 if (cp[1] == '>') {
266 DO (cp = parse_shift (g, cp + 2, &rightval));
267 *valp = (*valp >> rightval);
269 break;
271 return cp;
275 static const char *
276 parse_inequality (IfParser *g, const char *cp, int *valp)
278 int rightval;
280 DO (cp = parse_shift (g, cp, valp));
281 SKIPSPACE (cp);
283 switch (*cp) {
284 case '<':
285 if (cp[1] == '=') {
286 DO (cp = parse_inequality (g, cp + 2, &rightval));
287 *valp = (*valp <= rightval);
288 } else {
289 DO (cp = parse_inequality (g, cp + 1, &rightval));
290 *valp = (*valp < rightval);
292 break;
294 case '>':
295 if (cp[1] == '=') {
296 DO (cp = parse_inequality (g, cp + 2, &rightval));
297 *valp = (*valp >= rightval);
298 } else {
299 DO (cp = parse_inequality (g, cp + 1, &rightval));
300 *valp = (*valp > rightval);
302 break;
304 return cp;
308 static const char *
309 parse_equality (IfParser *g, const char *cp, int *valp)
311 int rightval;
313 DO (cp = parse_inequality (g, cp, valp));
314 SKIPSPACE (cp);
316 switch (*cp) {
317 case '=':
318 if (cp[1] == '=')
319 cp++;
320 DO (cp = parse_equality (g, cp + 1, &rightval));
321 *valp = (*valp == rightval);
322 break;
324 case '!':
325 if (cp[1] != '=')
326 break;
327 DO (cp = parse_equality (g, cp + 2, &rightval));
328 *valp = (*valp != rightval);
329 break;
331 return cp;
335 static const char *
336 parse_band (IfParser *g, const char *cp, int *valp)
338 int rightval;
340 DO (cp = parse_equality (g, cp, valp));
341 SKIPSPACE (cp);
343 switch (*cp) {
344 case '&':
345 if (cp[1] != '&') {
346 DO (cp = parse_band (g, cp + 1, &rightval));
347 *valp = (*valp & rightval);
349 break;
351 return cp;
355 static const char *
356 parse_bor (IfParser *g, const char *cp, int *valp)
358 int rightval;
360 DO (cp = parse_band (g, cp, valp));
361 SKIPSPACE (cp);
363 switch (*cp) {
364 case '|':
365 if (cp[1] != '|') {
366 DO (cp = parse_bor (g, cp + 1, &rightval));
367 *valp = (*valp | rightval);
369 break;
371 return cp;
375 static const char *
376 parse_land (IfParser *g, const char *cp, int *valp)
378 int rightval;
380 DO (cp = parse_bor (g, cp, valp));
381 SKIPSPACE (cp);
383 switch (*cp) {
384 case '&':
385 if (cp[1] != '&')
386 return CALLFUNC(g, handle_error) (g, cp, "&&");
387 DO (cp = parse_land (g, cp + 2, &rightval));
388 *valp = (*valp && rightval);
389 break;
391 return cp;
395 static const char *
396 parse_lor (IfParser *g, const char *cp, int *valp)
398 int rightval;
400 DO (cp = parse_land (g, cp, valp));
401 SKIPSPACE (cp);
403 switch (*cp) {
404 case '|':
405 if (cp[1] != '|')
406 return CALLFUNC(g, handle_error) (g, cp, "||");
407 DO (cp = parse_lor (g, cp + 2, &rightval));
408 *valp = (*valp || rightval);
409 break;
411 return cp;
415 /****************************************************************************
416 External Entry Points
417 ****************************************************************************/
419 const char *
420 ParseIfExpression (IfParser *g, const char *cp, int *valp)
422 return parse_lor (g, cp, valp);
426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */