]> git.sesse.net Git - rdpsrv/blob - Xserver/config/makedepend/ifparser.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / config / makedepend / ifparser.c
1 /*
2  * $XConsortium: ifparser.c /main/10 1996/09/28 16:15:18 rws $
3  * $XFree86: xc/config/makedepend/ifparser.c,v 3.6 1996/12/30 13:57:55 dawes Exp $
4  *
5  * Copyright 1992 Network Computing Devices, Inc.
6  * 
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.
16  * 
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.
24  * 
25  * Author:  Jim Fulton
26  *          Network Computing Devices, Inc.
27  * 
28  * Simple if statement processor
29  *
30  * This module can be used to evaluate string representations of C language
31  * if constructs.  It accepts the following grammar:
32  * 
33  *     EXPRESSION       :=      VALUE
34  *                       |      VALUE  BINOP    EXPRESSION
35  *                       |      VALUE   '?'     EXPRESSION ':'  EXPRESSION
36  * 
37  *     VALUE            :=      '('  EXPRESSION  ')'
38  *                       |      '!'  VALUE
39  *                       |      '-'  VALUE
40  *                       |      '~'  VALUE
41  *                       |      'defined'  '('  variable  ')'
42  *                       |      'defined'  variable
43  *                       |      # variable '(' variable-list ')'
44  *                       |      variable
45  *                       |      number
46  * 
47  *     BINOP            :=      '*'     |  '/'  |  '%'
48  *                       |      '+'     |  '-'
49  *                       |      '<<'    |  '>>'
50  *                       |      '<'     |  '>'  |  '<='  |  '>='
51  *                       |      '=='    |  '!='
52  *                       |      '&'     |  '^'  |  '|'
53  *                       |      '&&'    |  '||'
54  * 
55  * The normal C order of precedence is supported.
56  * 
57  * 
58  * External Entry Points:
59  * 
60  *     ParseIfExpression                parse a string for #if
61  */
62
63 #include "ifparser.h"
64 #include <ctype.h>
65
66 /****************************************************************************
67                    Internal Macros and Utilities for Parser
68  ****************************************************************************/
69
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) == '_')
74
75
76 static const char *
77 parse_variable (g, cp, varp)
78     IfParser *g;
79     const char *cp;
80     const char **varp;
81 {
82     SKIPSPACE (cp);
83
84     if (!isvarfirstletter (*cp))
85         return CALLFUNC(g, handle_error) (g, cp, "variable name");
86
87     *varp = cp;
88     /* EMPTY */
89     for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
90     return cp;
91 }
92
93
94 static const char *
95 parse_number (g, cp, valp)
96     IfParser *g;
97     const char *cp;
98     long *valp;
99 {
100     SKIPSPACE (cp);
101
102     if (!isdigit(*cp))
103         return CALLFUNC(g, handle_error) (g, cp, "number");
104
105     *valp = strtol(cp, &cp, 0);
106     /* skip trailing qualifiers */
107     while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
108 #if 0
109     *valp = atoi (cp);
110     /* EMPTY */
111     for (cp++; isdigit(*cp); cp++) ;
112 #endif
113     return cp;
114 }
115
116 static const char *
117 parse_character (g, cp, valp)
118     IfParser *g;
119     const char *cp;
120     long *valp;
121 {
122     char val;
123
124     SKIPSPACE (cp);
125     if (*cp == '\\')
126         switch (cp[1]) {
127         case 'n': val = '\n'; break;
128         case 't': val = '\t'; break;
129         case 'v': val = '\v'; break;
130         case 'b': val = '\b'; break;
131         case 'r': val = '\r'; break;
132         case 'f': val = '\f'; break;
133         case 'a': val = '\a'; break;
134         case '\\': val = '\\'; break;
135         case '?': val = '\?'; break;
136         case '\'': val = '\''; break;
137         case '\"': val = '\"'; break;
138         case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
139         default: val = (char) strtol (cp + 1, NULL, 8); break;
140         }
141     else
142         val = *cp;
143     while (*cp != '\'') cp++;
144     *valp = (long) val;
145     return cp;
146 }
147
148 static const char *
149 parse_value (g, cp, valp)
150     IfParser *g;
151     const char *cp;
152     long *valp;
153 {
154     const char *var;
155
156     *valp = 0;
157
158     SKIPSPACE (cp);
159     if (!*cp)
160         return cp;
161
162     switch (*cp) {
163       case '(':
164         DO (cp = ParseIfExpression (g, cp + 1, valp));
165         SKIPSPACE (cp);
166         if (*cp != ')') 
167             return CALLFUNC(g, handle_error) (g, cp, ")");
168
169         return cp + 1;                  /* skip the right paren */
170
171       case '!':
172         DO (cp = parse_value (g, cp + 1, valp));
173         *valp = !(*valp);
174         return cp;
175
176       case '-':
177         DO (cp = parse_value (g, cp + 1, valp));
178         *valp = -(*valp);
179         return cp;
180
181       case '~':
182         DO (cp = parse_value (g, cp + 1, valp));
183         *valp = ~(*valp);
184         return cp;
185
186       case '#':
187         DO (cp = parse_variable (g, cp + 1, &var));
188         SKIPSPACE (cp);
189         if (*cp != '(')
190             return CALLFUNC(g, handle_error) (g, cp, "(");
191         do {
192             DO (cp = parse_variable (g, cp + 1, &var));
193             SKIPSPACE (cp);
194         } while (*cp && *cp != ')');
195         if (*cp != ')')
196             return CALLFUNC(g, handle_error) (g, cp, ")");
197         *valp = 1; /* XXX */
198         return cp + 1;
199
200       case '\'':
201         DO (cp = parse_character (g, cp + 1, valp));
202         if (*cp != '\'')
203             return CALLFUNC(g, handle_error) (g, cp, "'");
204         return cp + 1;
205
206       case 'd':
207         if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
208             int paren = 0;
209             int len;
210
211             cp += 7;
212             SKIPSPACE (cp);
213             if (*cp == '(') {
214                 paren = 1;
215                 cp++;
216             }
217             DO (cp = parse_variable (g, cp, &var));
218             len = cp - var;
219             SKIPSPACE (cp);
220             if (paren && *cp != ')')
221                 return CALLFUNC(g, handle_error) (g, cp, ")");
222             *valp = (*(g->funcs.eval_defined)) (g, var, len);
223             return cp + paren;          /* skip the right paren */
224         }
225         /* fall out */
226     }
227
228     if (isdigit(*cp)) {
229         DO (cp = parse_number (g, cp, valp));
230     } else if (!isvarfirstletter(*cp))
231         return CALLFUNC(g, handle_error) (g, cp, "variable or number");
232     else {
233         DO (cp = parse_variable (g, cp, &var));
234         *valp = (*(g->funcs.eval_variable)) (g, var, cp - var);
235     }
236     
237     return cp;
238 }
239
240
241
242 static const char *
243 parse_product (g, cp, valp)
244     IfParser *g;
245     const char *cp;
246     long *valp;
247 {
248     long rightval;
249
250     DO (cp = parse_value (g, cp, valp));
251     SKIPSPACE (cp);
252
253     switch (*cp) {
254       case '*':
255         DO (cp = parse_product (g, cp + 1, &rightval));
256         *valp = (*valp * rightval);
257         break;
258
259       case '/':
260         DO (cp = parse_product (g, cp + 1, &rightval));
261         *valp = (*valp / rightval);
262         break;
263
264       case '%':
265         DO (cp = parse_product (g, cp + 1, &rightval));
266         *valp = (*valp % rightval);
267         break;
268     }
269     return cp;
270 }
271
272
273 static const char *
274 parse_sum (g, cp, valp)
275     IfParser *g;
276     const char *cp;
277     long *valp;
278 {
279     long rightval;
280
281     DO (cp = parse_product (g, cp, valp));
282     SKIPSPACE (cp);
283
284     switch (*cp) {
285       case '+':
286         DO (cp = parse_sum (g, cp + 1, &rightval));
287         *valp = (*valp + rightval);
288         break;
289
290       case '-':
291         DO (cp = parse_sum (g, cp + 1, &rightval));
292         *valp = (*valp - rightval);
293         break;
294     }
295     return cp;
296 }
297
298
299 static const char *
300 parse_shift (g, cp, valp)
301     IfParser *g;
302     const char *cp;
303     long *valp;
304 {
305     long rightval;
306
307     DO (cp = parse_sum (g, cp, valp));
308     SKIPSPACE (cp);
309
310     switch (*cp) {
311       case '<':
312         if (cp[1] == '<') {
313             DO (cp = parse_shift (g, cp + 2, &rightval));
314             *valp = (*valp << rightval);
315         }
316         break;
317
318       case '>':
319         if (cp[1] == '>') {
320             DO (cp = parse_shift (g, cp + 2, &rightval));
321             *valp = (*valp >> rightval);
322         }
323         break;
324     }
325     return cp;
326 }
327
328
329 static const char *
330 parse_inequality (g, cp, valp)
331     IfParser *g;
332     const char *cp;
333     long *valp;
334 {
335     long rightval;
336
337     DO (cp = parse_shift (g, cp, valp));
338     SKIPSPACE (cp);
339
340     switch (*cp) {
341       case '<':
342         if (cp[1] == '=') {
343             DO (cp = parse_inequality (g, cp + 2, &rightval));
344             *valp = (*valp <= rightval);
345         } else {
346             DO (cp = parse_inequality (g, cp + 1, &rightval));
347             *valp = (*valp < rightval);
348         }
349         break;
350
351       case '>':
352         if (cp[1] == '=') {
353             DO (cp = parse_inequality (g, cp + 2, &rightval));
354             *valp = (*valp >= rightval);
355         } else {
356             DO (cp = parse_inequality (g, cp + 1, &rightval));
357             *valp = (*valp > rightval);
358         }
359         break;
360     }
361     return cp;
362 }
363
364
365 static const char *
366 parse_equality (g, cp, valp)
367     IfParser *g;
368     const char *cp;
369     long *valp;
370 {
371     long rightval;
372
373     DO (cp = parse_inequality (g, cp, valp));
374     SKIPSPACE (cp);
375
376     switch (*cp) {
377       case '=':
378         if (cp[1] == '=')
379             cp++;
380         DO (cp = parse_equality (g, cp + 1, &rightval));
381         *valp = (*valp == rightval);
382         break;
383
384       case '!':
385         if (cp[1] != '=')
386             break;
387         DO (cp = parse_equality (g, cp + 2, &rightval));
388         *valp = (*valp != rightval);
389         break;
390     }
391     return cp;
392 }
393
394
395 static const char *
396 parse_band (g, cp, valp)
397     IfParser *g;
398     const char *cp;
399     long *valp;
400 {
401     long rightval;
402
403     DO (cp = parse_equality (g, cp, valp));
404     SKIPSPACE (cp);
405
406     switch (*cp) {
407       case '&':
408         if (cp[1] != '&') {
409             DO (cp = parse_band (g, cp + 1, &rightval));
410             *valp = (*valp & rightval);
411         }
412         break;
413     }
414     return cp;
415 }
416
417
418 static const char *
419 parse_bxor (g, cp, valp)
420     IfParser *g;
421     const char *cp;
422     long *valp;
423 {
424     long rightval;
425
426     DO (cp = parse_band (g, cp, valp));
427     SKIPSPACE (cp);
428
429     switch (*cp) {
430       case '^':
431         DO (cp = parse_bxor (g, cp + 1, &rightval));
432         *valp = (*valp ^ rightval);
433         break;
434     }
435     return cp;
436 }
437
438
439 static const char *
440 parse_bor (g, cp, valp)
441     IfParser *g;
442     const char *cp;
443     long *valp;
444 {
445     long rightval;
446
447     DO (cp = parse_bxor (g, cp, valp));
448     SKIPSPACE (cp);
449
450     switch (*cp) {
451       case '|':
452         if (cp[1] != '|') {
453             DO (cp = parse_bor (g, cp + 1, &rightval));
454             *valp = (*valp | rightval);
455         }
456         break;
457     }
458     return cp;
459 }
460
461
462 static const char *
463 parse_land (g, cp, valp)
464     IfParser *g;
465     const char *cp;
466     long *valp;
467 {
468     long rightval;
469
470     DO (cp = parse_bor (g, cp, valp));
471     SKIPSPACE (cp);
472
473     switch (*cp) {
474       case '&':
475         if (cp[1] != '&')
476             return CALLFUNC(g, handle_error) (g, cp, "&&");
477         DO (cp = parse_land (g, cp + 2, &rightval));
478         *valp = (*valp && rightval);
479         break;
480     }
481     return cp;
482 }
483
484
485 static const char *
486 parse_lor (g, cp, valp)
487     IfParser *g;
488     const char *cp;
489     long *valp;
490 {
491     long rightval;
492
493     DO (cp = parse_land (g, cp, valp));
494     SKIPSPACE (cp);
495
496     switch (*cp) {
497       case '|':
498         if (cp[1] != '|')
499             return CALLFUNC(g, handle_error) (g, cp, "||");
500         DO (cp = parse_lor (g, cp + 2, &rightval));
501         *valp = (*valp || rightval);
502         break;
503     }
504     return cp;
505 }
506
507
508 static const char *
509 parse_cond(g, cp, valp)
510     IfParser *g;
511     const char *cp;
512     long *valp;
513 {
514     long trueval, falseval;
515
516     DO (cp = parse_lor (g, cp, valp));
517     SKIPSPACE (cp);
518
519     switch (*cp) {
520       case '?':
521         DO (cp = parse_cond (g, cp + 1, &trueval));
522         SKIPSPACE (cp);
523         if (*cp != ':')
524             return CALLFUNC(g, handle_error) (g, cp, ":");
525         DO (cp = parse_cond (g, cp + 1, &falseval));
526         *valp = (*valp ? trueval : falseval);
527         break;
528     }
529     return cp;
530 }
531
532
533 /****************************************************************************
534                              External Entry Points
535  ****************************************************************************/
536
537 const char *
538 ParseIfExpression (g, cp, valp)
539     IfParser *g;
540     const char *cp;
541     long *valp;
542 {
543     return parse_cond (g, cp, valp);
544 }