8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / ucbcmd / expr / expr.y
blob3a4259c8026a76b6adb62f0fa14e943314fb18bd
1 %{
2 /*
3 * CDDL HEADER START
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.
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.
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]
21 * CDDL HEADER END
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
33 #pragma ident "%Z%%M% %I% %E% SMI"
36 /* Yacc productions for "expr" command: */
39 typedef char *yystype;
40 #define YYSTYPE yystype
43 %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
44 %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
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
58 /* a single `expression' is evaluated and printed: */
60 expression: expr NOARG = {
61 printf("%s\n", $1);
62 exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
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
90 #define ESIZE 256
91 #define EQL(x,y) !strcmp(x,y)
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>
103 char **Av;
104 int Ac;
105 int Argi;
107 char *ltoa(long l);
109 char Mstring[1][128];
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 };
121 yylex(void)
123 char *p;
124 int i;
126 if(Argi >= Ac) return NOARG;
128 p = Av[Argi++];
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];
136 yylval = p;
137 return A_STRING;
140 char *
141 rel(int oper, char *r1, char *r2)
143 long i;
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;
169 return i? "1": "0";
172 char *arith(oper, r1, r2) char *r1, *r2;
174 long i1, i2;
175 char *rv;
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);
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;
203 rv = malloc(16);
204 (void) strcpy(rv, ltoa(i1));
205 return rv;
207 char *conj(oper, r1, r2) char *r1, *r2;
209 char *rv;
211 switch(oper) {
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;
235 return rv;
238 char *
239 substr(char *v, char *s, char *w)
241 int si, wi;
242 char *res;
244 si = atol(s);
245 wi = atol(w);
246 while(--si) if(*v) ++v;
248 res = v;
250 while(wi--) if(*v) ++v;
252 *v = '\0';
253 return res;
256 char *
257 index(char *s, char *t)
259 long i, j;
260 char *rv;
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;
268 return "0";
271 char *
272 length(char *s)
274 long i = 0;
275 char *rv;
277 while(*s++) ++i;
279 rv = malloc(8);
280 (void) strcpy(rv, ltoa(i));
281 return rv;
284 char *
285 match(char *s, char *p)
287 char *rv;
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]);
294 return rv;
298 ematch(char *s, char *p)
300 static char expbuf[ESIZE];
301 char *compile();
302 int num;
303 extern char *braslist[], *braelist[], *loc2;
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';
316 return(loc2-s);
318 return(0);
322 errxx(int err)
324 char *message;
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;
367 yyerror(message);
368 /* NOTREACHED */
369 return (0);
373 yyerror(char *s)
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);
383 char *
384 ltoa(long l)
386 static char str[20];
387 char *sp;
388 int i;
389 int neg;
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;
403 while(l);
404 if(neg)
405 *--sp = '-';
406 return sp;
410 main(int argc, char **argv)
412 Ac = argc;
413 Argi = 1;
414 Av = argv;
415 yyparse();
416 return (0);