1 %{
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23 %}
24 /*
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 %{
33 #pragma ident "%Z%%M% %I% %E% SMI"
34 %}
35
36 /* Yacc productions for "expr" command: */
37
38 %{
39 typedef char *yystype;
40 #define YYSTYPE yystype
41 %}
42
43 %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
44 %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
45
46 /* operators listed below in increasing precedence: */
47 %left OR
48 %left AND
49 %left EQ LT GT GEQ LEQ NEQ
50 %left ADD SUBT
51 %left MULT DIV REM
52 %left MCH
53 %left MATCH
54 %left SUBSTR
55 %left LENGTH INDEX
56 %%
57
58 /* a single `expression' is evaluated and printed: */
59
60 expression: expr NOARG = {
61 printf("%s\n", $1);
62 exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
63 }
64 ;
65
66
67 expr: '(' expr ')' = { $$ = $2; }
68 | expr OR expr = { $$ = conj(OR, $1, $3); }
69 | expr AND expr = { $$ = conj(AND, $1, $3); }
70 | expr EQ expr = { $$ = rel(EQ, $1, $3); }
71 | expr GT expr = { $$ = rel(GT, $1, $3); }
72 | expr GEQ expr = { $$ = rel(GEQ, $1, $3); }
73 | expr LT expr = { $$ = rel(LT, $1, $3); }
74 | expr LEQ expr = { $$ = rel(LEQ, $1, $3); }
75 | expr NEQ expr = { $$ = rel(NEQ, $1, $3); }
76 | expr ADD expr = { $$ = arith(ADD, $1, $3); }
77 | expr SUBT expr = { $$ = arith(SUBT, $1, $3); }
78 | expr MULT expr = { $$ = arith(MULT, $1, $3); }
79 | expr DIV expr = { $$ = arith(DIV, $1, $3); }
80 | expr REM expr = { $$ = arith(REM, $1, $3); }
81 | expr MCH expr = { $$ = match($1, $3); }
82 | MATCH expr expr = { $$ = match($2, $3); }
83 | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
84 | LENGTH expr = { $$ = length($2); }
85 | INDEX expr expr = { $$ = index($2, $3); }
86 | A_STRING
87 ;
88 %%
89
90 #define ESIZE 256
91 #define EQL(x,y) !strcmp(x,y)
92
93 #define INIT char *sp = instring;
94 #define GETC() (*sp++)
95 #define PEEKC() (*sp)
96 #define UNGETC(c) (--sp)
97 #define RETURN(c) return(c)
98 #define ERROR(c) errxx(c)
99 #include <regexp.h>
100 #include <malloc.h>
101 #include <stdlib.h>
102
103 char **Av;
104 int Ac;
105 int Argi;
106
107 char *ltoa(long l);
108
109 char Mstring[1][128];
110
111
112 char *operator[] = {
113 "|", "&", "+", "-", "*", "/", "%", ":",
114 "=", "==", "<", "<=", ">", ">=", "!=",
115 "match", "substr", "length", "index", "\0" };
116 int op[] = {
117 OR, AND, ADD, SUBT, MULT, DIV, REM, MCH,
118 EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
119 MATCH, SUBSTR, LENGTH, INDEX };
120 int
yylex(void)121 yylex(void)
122 {
123 char *p;
124 int i;
125
126 if(Argi >= Ac) return NOARG;
127
128 p = Av[Argi++];
129
130 if((*p == '(' || *p == ')') && p[1] == '\0' )
131 return (int)*p;
132 for(i = 0; *operator[i]; ++i)
133 if(EQL(operator[i], p))
134 return op[i];
135
136 yylval = p;
137 return A_STRING;
138 }
139
140 char *
rel(int oper,char * r1,char * r2)141 rel(int oper, char *r1, char *r2)
142 {
143 long i;
144
145 if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
146 i = atol(r1) - atol(r2);
147 else
148 i = strcmp(r1, r2);
149 switch(oper) {
150 case EQ:
151 i = i==0;
152 break;
153 case GT:
154 i = i>0;
155 break;
156 case GEQ:
157 i = i>=0;
158 break;
159 case LT:
160 i = i<0;
161 break;
162 case LEQ:
163 i = i<=0;
164 break;
165 case NEQ:
166 i = i!=0;
167 break;
168 }
169 return i? "1": "0";
170 }
171
arith(oper,r1,r2)172 char *arith(oper, r1, r2) char *r1, *r2;
173 {
174 long i1, i2;
175 char *rv;
176
177 if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
178 yyerror("non-numeric argument");
179 i1 = atol(r1);
180 i2 = atol(r2);
181
182 switch(oper) {
183 case ADD:
184 i1 = i1 + i2;
185 break;
186 case SUBT:
187 i1 = i1 - i2;
188 break;
189 case MULT:
190 i1 = i1 * i2;
191 break;
192 case DIV:
193 if (i2 == 0)
194 yyerror("division by zero");
195 i1 = i1 / i2;
196 break;
197 case REM:
198 if (i2 == 0)
199 yyerror("division by zero");
200 i1 = i1 % i2;
201 break;
202 }
203 rv = malloc(16);
204 (void) strcpy(rv, ltoa(i1));
205 return rv;
206 }
conj(oper,r1,r2)207 char *conj(oper, r1, r2) char *r1, *r2;
208 {
209 char *rv;
210
211 switch(oper) {
212
213 case OR:
214 if(EQL(r1, "0")
215 || EQL(r1, ""))
216 if(EQL(r2, "0")
217 || EQL(r2, ""))
218 rv = "0";
219 else
220 rv = r2;
221 else
222 rv = r1;
223 break;
224 case AND:
225 if(EQL(r1, "0")
226 || EQL(r1, ""))
227 rv = "0";
228 else if(EQL(r2, "0")
229 || EQL(r2, ""))
230 rv = "0";
231 else
232 rv = r1;
233 break;
234 }
235 return rv;
236 }
237
238 char *
substr(char * v,char * s,char * w)239 substr(char *v, char *s, char *w)
240 {
241 int si, wi;
242 char *res;
243
244 si = atol(s);
245 wi = atol(w);
246 while(--si) if(*v) ++v;
247
248 res = v;
249
250 while(wi--) if(*v) ++v;
251
252 *v = '\0';
253 return res;
254 }
255
256 char *
index(char * s,char * t)257 index(char *s, char *t)
258 {
259 long i, j;
260 char *rv;
261
262 for(i = 0; s[i] ; ++i)
263 for(j = 0; t[j] ; ++j)
264 if(s[i]==t[j]) {
265 (void) strcpy(rv = malloc(8), ltoa(++i));
266 return rv;
267 }
268 return "0";
269 }
270
271 char *
length(char * s)272 length(char *s)
273 {
274 long i = 0;
275 char *rv;
276
277 while(*s++) ++i;
278
279 rv = malloc(8);
280 (void) strcpy(rv, ltoa(i));
281 return rv;
282 }
283
284 char *
match(char * s,char * p)285 match(char *s, char *p)
286 {
287 char *rv;
288
289 (void) strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
290 if(nbra) {
291 rv = malloc((unsigned) strlen(Mstring[0]) + 1);
292 (void) strcpy(rv, Mstring[0]);
293 }
294 return rv;
295 }
296
297 int
ematch(char * s,char * p)298 ematch(char *s, char *p)
299 {
300 static char expbuf[ESIZE];
301 char *compile();
302 int num;
303 extern char *braslist[], *braelist[], *loc2;
304
305 compile(p, expbuf, &expbuf[ESIZE], 0);
306 if(nbra > 1)
307 yyerror("Too many '\\('s");
308 if(advance(s, expbuf)) {
309 if(nbra == 1) {
310 p = braslist[0];
311 num = braelist[0] - p;
312 if ((num > 127) || (num < 0)) yyerror("Paren problem");
313 (void) strncpy(Mstring[0], p, num);
314 Mstring[0][num] = '\0';
315 }
316 return(loc2-s);
317 }
318 return(0);
319 }
320
321 int
errxx(int err)322 errxx(int err)
323 {
324 char *message;
325
326 switch(err) {
327 case 11:
328 message = "Range endpoint too large";
329 break;
330 case 16:
331 message = "Bad number";
332 break;
333 case 25:
334 message = "``\\digit'' out of range";
335 break;
336 case 36:
337 message = "Illegal or missing delimiter";
338 break;
339 case 41:
340 message = "No remembered search string";
341 break;
342 case 42:
343 message = "\\( \\) imbalance";
344 break;
345 case 43:
346 message = "Too many \\(";
347 break;
348 case 44:
349 message = "More than 2 numbers given in \\{ \\}";
350 break;
351 case 45:
352 message = "} expected after \\";
353 break;
354 case 46:
355 message = "First number exceeds second in \\{ \\}";
356 break;
357 case 49:
358 message = "[ ] imbalance";
359 break;
360 case 50:
361 message = "Regular expression too long";
362 break;
363 default:
364 message = "Unknown regexp error code!!";
365 break;
366 }
367 yyerror(message);
368 /* NOTREACHED */
369 return (0);
370 }
371
372 int
yyerror(char * s)373 yyerror(char *s)
374 {
375 (void) write(2, "expr: ", 6);
376 (void) write(2, s, (unsigned) strlen(s));
377 (void) write(2, "\n", 1);
378 exit(2);
379 /* NOTREACHED */
380 return (0);
381 }
382
383 char *
ltoa(long l)384 ltoa(long l)
385 {
386 static char str[20];
387 char *sp;
388 int i;
389 int neg;
390
391 if(l == 0x80000000L)
392 return "-2147483648";
393 neg = 0;
394 if(l < 0)
395 ++neg, l = -l;
396 sp = &str[20];
397 *--sp = '\0';
398 do {
399 i = l % 10;
400 *--sp = '0' + i;
401 l /= 10;
402 }
403 while(l);
404 if(neg)
405 *--sp = '-';
406 return sp;
407 }
408
409 int
main(int argc,char ** argv)410 main(int argc, char **argv)
411 {
412 Ac = argc;
413 Argi = 1;
414 Av = argv;
415 yyparse();
416 return (0);
417 }
418