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