Annotation of src/bin/expr/expr.y, Revision 1.14.2.1
1.1 cgd 1: %{
2: /* Written by Pace Willisson (pace@blitz.com)
1.11 jtc 3: * and placed in the public domain.
1.2 cgd 4: *
1.11 jtc 5: * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
6: *
1.12 jtc 7: * $Id : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $
1.1 cgd 8: */
1.12 jtc 9:
1.1 cgd 10: #include <stdio.h>
1.4 cgd 11: #include <stdlib.h>
12: #include <string.h>
1.12 jtc 13: #include <locale.h>
1.1 cgd 14: #include <ctype.h>
1.11 jtc 15: #include <err.h>
1.5 cgd 16:
1.4 cgd 17: enum valtype {
18: integer, string
19: } ;
1.5 cgd 20:
1.1 cgd 21: struct val {
1.4 cgd 22: enum valtype type;
23: union {
24: char *s;
25: int i;
26: } u;
1.5 cgd 27: } ;
1.1 cgd 28:
29: struct val *result;
30: struct val *op_or ();
31: struct val *op_and ();
32: struct val *op_eq ();
33: struct val *op_gt ();
34: struct val *op_lt ();
35: struct val *op_ge ();
36: struct val *op_le ();
37: struct val *op_ne ();
38: struct val *op_plus ();
39: struct val *op_minus ();
40: struct val *op_times ();
41: struct val *op_div ();
42: struct val *op_rem ();
43: struct val *op_colon ();
44:
45: char **av;
46: %}
47:
48: %union
49: {
50: struct val *val;
51: }
52:
53: %left <val> '|'
54: %left <val> '&'
55: %left <val> '=' '>' '<' GE LE NE
56: %left <val> '+' '-'
57: %left <val> '*' '/' '%'
58: %left <val> ':'
59:
60: %token <val> TOKEN
61: %type <val> start expr
62:
63: %%
64:
65: start: expr { result = $$; }
66:
67: expr: TOKEN
68: | '(' expr ')' { $$ = $2; }
69: | expr '|' expr { $$ = op_or ($1, $3); }
70: | expr '&' expr { $$ = op_and ($1, $3); }
71: | expr '=' expr { $$ = op_eq ($1, $3); }
72: | expr '>' expr { $$ = op_gt ($1, $3); }
73: | expr '<' expr { $$ = op_lt ($1, $3); }
74: | expr GE expr { $$ = op_ge ($1, $3); }
75: | expr LE expr { $$ = op_le ($1, $3); }
76: | expr NE expr { $$ = op_ne ($1, $3); }
77: | expr '+' expr { $$ = op_plus ($1, $3); }
78: | expr '-' expr { $$ = op_minus ($1, $3); }
79: | expr '*' expr { $$ = op_times ($1, $3); }
80: | expr '/' expr { $$ = op_div ($1, $3); }
81: | expr '%' expr { $$ = op_rem ($1, $3); }
82: | expr ':' expr { $$ = op_colon ($1, $3); }
83: ;
84:
85:
86: %%
87:
88: struct val *
1.4 cgd 89: make_integer (i)
90: int i;
91: {
92: struct val *vp;
93:
1.5 cgd 94: vp = (struct val *) malloc (sizeof (*vp));
1.4 cgd 95: if (vp == NULL) {
1.11 jtc 96: err (2, NULL);
1.4 cgd 97: }
98:
99: vp->type = integer;
100: vp->u.i = i;
101: return vp;
102: }
103:
104: struct val *
105: make_str (s)
106: char *s;
1.1 cgd 107: {
108: struct val *vp;
109:
1.5 cgd 110: vp = (struct val *) malloc (sizeof (*vp));
1.4 cgd 111: if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
1.11 jtc 112: err (2, NULL);
1.1 cgd 113: }
114:
1.4 cgd 115: vp->type = string;
116: return vp;
117: }
118:
119:
120: void
121: free_value (vp)
122: struct val *vp;
123: {
124: if (vp->type == string)
125: free (vp->u.s);
1.14 jtc 126: free (vp);
1.4 cgd 127: }
128:
1.1 cgd 129:
1.4 cgd 130: int
131: to_integer (vp)
132: struct val *vp;
133: {
134: char *s;
135: int neg;
136: int i;
137:
138: if (vp->type == integer)
139: return 1;
140:
141: s = vp->u.s;
142: i = 0;
143:
144: neg = (*s == '-');
145: if (neg)
146: s++;
147:
148: for (;*s; s++) {
149: if (!isdigit (*s))
150: return 0;
151:
152: i *= 10;
153: i += *s - '0';
1.1 cgd 154: }
155:
1.4 cgd 156: free (vp->u.s);
157: if (neg)
158: i *= -1;
159:
160: vp->type = integer;
161: vp->u.i = i;
162: return 1;
1.1 cgd 163: }
164:
1.4 cgd 165: void
166: to_string (vp)
167: struct val *vp;
1.1 cgd 168: {
1.4 cgd 169: char *tmp;
170:
171: if (vp->type == string)
172: return;
173:
174: tmp = malloc (25);
175: if (tmp == NULL) {
1.11 jtc 176: err (2, NULL);
1.4 cgd 177: }
178:
179: sprintf (tmp, "%d", vp->u.i);
180: vp->type = string;
181: vp->u.s = tmp;
182: }
183:
1.1 cgd 184:
1.4 cgd 185: int
186: isstring (vp)
187: struct val *vp;
188: {
189: return (vp->type == string);
1.1 cgd 190: }
191:
1.4 cgd 192:
1.1 cgd 193: int
194: yylex ()
195: {
196: struct val *vp;
197: char *p;
198:
199: if (*av == NULL)
200: return (0);
201:
202: p = *av++;
203:
204: if (strlen (p) == 1) {
1.4 cgd 205: if (strchr ("|&=<>+-*/%:()", *p))
1.1 cgd 206: return (*p);
207: } else if (strlen (p) == 2 && p[1] == '=') {
208: switch (*p) {
209: case '>': return (GE);
210: case '<': return (LE);
211: case '!': return (NE);
212: }
213: }
214:
1.4 cgd 215: yylval.val = make_str (p);
1.1 cgd 216: return (TOKEN);
217: }
218:
219: int
220: is_zero_or_null (vp)
221: struct val *vp;
222: {
1.4 cgd 223: if (vp->type == integer) {
1.5 cgd 224: return (vp->u.i == 0);
1.4 cgd 225: } else {
1.9 jtc 226: return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
1.4 cgd 227: }
1.5 cgd 228: /* NOTREACHED */
1.1 cgd 229: }
230:
231: void
232: main (argc, argv)
233: int argc;
234: char **argv;
235: {
1.12 jtc 236: setlocale (LC_ALL, "");
237:
1.1 cgd 238: av = argv + 1;
239:
240: yyparse ();
241:
1.4 cgd 242: if (result->type == integer)
243: printf ("%d\n", result->u.i);
1.1 cgd 244: else
1.4 cgd 245: printf ("%s\n", result->u.s);
1.1 cgd 246:
1.12 jtc 247: exit (is_zero_or_null (result));
1.1 cgd 248: }
249:
250: int
251: yyerror (s)
252: char *s;
253: {
1.11 jtc 254: errx (2, "syntax error");
1.1 cgd 255: }
256:
257:
258: struct val *
259: op_or (a, b)
260: struct val *a, *b;
261: {
1.4 cgd 262: if (is_zero_or_null (a)) {
263: free_value (a);
1.1 cgd 264: return (b);
1.4 cgd 265: } else {
266: free_value (b);
1.1 cgd 267: return (a);
1.4 cgd 268: }
1.1 cgd 269: }
270:
271: struct val *
272: op_and (a, b)
273: struct val *a, *b;
274: {
1.4 cgd 275: if (is_zero_or_null (a) || is_zero_or_null (b)) {
276: free_value (a);
277: free_value (b);
1.1 cgd 278: return (make_integer (0));
1.4 cgd 279: } else {
280: free_value (b);
1.1 cgd 281: return (a);
1.4 cgd 282: }
1.1 cgd 283: }
284:
285: struct val *
286: op_eq (a, b)
287: struct val *a, *b;
288: {
1.4 cgd 289: struct val *r;
290:
291: if (isstring (a) || isstring (b)) {
292: to_string (a);
293: to_string (b);
1.10 jtc 294: r = make_integer (strcoll (a->u.s, b->u.s) == 0);
1.4 cgd 295: } else {
296: r = make_integer (a->u.i == b->u.i);
297: }
298:
299: free_value (a);
300: free_value (b);
301: return r;
1.1 cgd 302: }
303:
304: struct val *
305: op_gt (a, b)
306: struct val *a, *b;
307: {
1.4 cgd 308: struct val *r;
309:
310: if (isstring (a) || isstring (b)) {
311: to_string (a);
312: to_string (b);
1.10 jtc 313: r = make_integer (strcoll (a->u.s, b->u.s) > 0);
1.4 cgd 314: } else {
315: r= make_integer (a->u.i > b->u.i);
316: }
317:
318: free_value (a);
319: free_value (b);
320: return r;
1.1 cgd 321: }
322:
323: struct val *
324: op_lt (a, b)
325: struct val *a, *b;
326: {
1.4 cgd 327: struct val *r;
328:
329: if (isstring (a) || isstring (b)) {
330: to_string (a);
331: to_string (b);
1.10 jtc 332: r = make_integer (strcoll (a->u.s, b->u.s) < 0);
1.4 cgd 333: } else {
334: r = make_integer (a->u.i < b->u.i);
335: }
336:
337: free_value (a);
338: free_value (b);
339: return r;
1.1 cgd 340: }
341:
342: struct val *
343: op_ge (a, b)
344: struct val *a, *b;
345: {
1.4 cgd 346: struct val *r;
347:
348: if (isstring (a) || isstring (b)) {
349: to_string (a);
350: to_string (b);
1.10 jtc 351: r = make_integer (strcoll (a->u.s, b->u.s) >= 0);
1.4 cgd 352: } else {
353: r = make_integer (a->u.i >= b->u.i);
354: }
355:
356: free_value (a);
357: free_value (b);
358: return r;
1.1 cgd 359: }
360:
361: struct val *
362: op_le (a, b)
363: struct val *a, *b;
364: {
1.4 cgd 365: struct val *r;
366:
367: if (isstring (a) || isstring (b)) {
368: to_string (a);
369: to_string (b);
1.10 jtc 370: r = make_integer (strcoll (a->u.s, b->u.s) <= 0);
1.4 cgd 371: } else {
372: r = make_integer (a->u.i <= b->u.i);
373: }
374:
375: free_value (a);
376: free_value (b);
377: return r;
1.1 cgd 378: }
379:
380: struct val *
381: op_ne (a, b)
382: struct val *a, *b;
383: {
1.4 cgd 384: struct val *r;
385:
386: if (isstring (a) || isstring (b)) {
387: to_string (a);
388: to_string (b);
1.10 jtc 389: r = make_integer (strcoll (a->u.s, b->u.s) != 0);
1.4 cgd 390: } else {
391: r = make_integer (a->u.i != b->u.i);
392: }
393:
394: free_value (a);
395: free_value (b);
396: return r;
1.1 cgd 397: }
398:
399: struct val *
400: op_plus (a, b)
401: struct val *a, *b;
402: {
1.4 cgd 403: struct val *r;
404:
405: if (!to_integer (a) || !to_integer (b)) {
1.11 jtc 406: errx (2, "non-numeric argument");
1.4 cgd 407: }
1.1 cgd 408:
1.4 cgd 409: r = make_integer (a->u.i + b->u.i);
410: free_value (a);
411: free_value (b);
412: return r;
1.1 cgd 413: }
414:
415: struct val *
416: op_minus (a, b)
417: struct val *a, *b;
418: {
1.4 cgd 419: struct val *r;
420:
421: if (!to_integer (a) || !to_integer (b)) {
1.11 jtc 422: errx (2, "non-numeric argument");
1.4 cgd 423: }
1.1 cgd 424:
1.4 cgd 425: r = make_integer (a->u.i - b->u.i);
426: free_value (a);
427: free_value (b);
428: return r;
1.1 cgd 429: }
430:
431: struct val *
432: op_times (a, b)
433: struct val *a, *b;
434: {
1.4 cgd 435: struct val *r;
1.1 cgd 436:
1.4 cgd 437: if (!to_integer (a) || !to_integer (b)) {
1.11 jtc 438: errx (2, "non-numeric argument");
1.4 cgd 439: }
440:
441: r = make_integer (a->u.i * b->u.i);
442: free_value (a);
443: free_value (b);
444: return (r);
1.1 cgd 445: }
446:
447: struct val *
448: op_div (a, b)
449: struct val *a, *b;
450: {
1.4 cgd 451: struct val *r;
452:
453: if (!to_integer (a) || !to_integer (b)) {
1.11 jtc 454: errx (2, "non-numeric argument");
1.4 cgd 455: }
456:
457: if (b->u.i == 0) {
1.11 jtc 458: errx (2, "division by zero");
1.4 cgd 459: }
1.1 cgd 460:
1.4 cgd 461: r = make_integer (a->u.i / b->u.i);
462: free_value (a);
463: free_value (b);
464: return r;
1.1 cgd 465: }
466:
467: struct val *
468: op_rem (a, b)
469: struct val *a, *b;
470: {
1.4 cgd 471: struct val *r;
472:
473: if (!to_integer (a) || !to_integer (b)) {
1.11 jtc 474: errx (2, "non-numeric argument");
1.4 cgd 475: }
476:
477: if (b->u.i == 0) {
1.11 jtc 478: errx (2, "division by zero");
1.4 cgd 479: }
1.1 cgd 480:
1.4 cgd 481: r = make_integer (a->u.i % b->u.i);
482: free_value (a);
483: free_value (b);
484: return r;
1.1 cgd 485: }
486:
1.6 jtc 487: #include <regex.h>
1.1 cgd 488:
489: struct val *
490: op_colon (a, b)
491: struct val *a, *b;
492: {
1.6 jtc 493: regex_t rp;
1.12 jtc 494: regmatch_t rm[2];
1.6 jtc 495: char errbuf[256];
496: int eval;
497: struct val *v;
498:
1.7 jtc 499: /* coerce to both arguments to strings */
500: to_string(a);
501: to_string(b);
1.6 jtc 502:
503: /* compile regular expression */
1.13 jtc 504: if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
1.6 jtc 505: regerror (eval, &rp, errbuf, sizeof(errbuf));
1.11 jtc 506: errx (2, "%s", errbuf);
1.6 jtc 507: }
508:
509: /* compare string against pattern */
1.13 jtc 510: /* remember that patterns are anchored to the beginning of the line */
511: if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) {
1.6 jtc 512: if (rm[1].rm_so >= 0) {
1.11 jtc 513: *(a->u.s + rm[1].rm_eo) = '\0';
1.6 jtc 514: v = make_str (a->u.s + rm[1].rm_so);
1.1 cgd 515:
516: } else {
1.14.2.1! cgd 517: v = make_integer ((int)(rm[0].rm_eo - rm[0].rm_so));
1.1 cgd 518: }
519: } else {
1.11 jtc 520: if (rp.re_nsub == 0) {
521: v = make_integer (0);
522: } else {
523: v = make_str ("");
524: }
1.1 cgd 525: }
1.6 jtc 526:
527: /* free arguments and pattern buffer */
528: free_value (a);
529: free_value (b);
530: regfree (&rp);
1.5 cgd 531:
1.6 jtc 532: return v;
1.1 cgd 533: }
CVSweb <webmaster@jp.NetBSD.org>