1 /* Yacc productions for "expr" command: */
2
3 %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ
4 %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH
5
6 /* operators listed below in increasing precedence: */
7 %left OR
8 %left AND
9 %left EQ LT GT GEQ LEQ NEQ
10 %left ADD SUBT
11 %left MULT DIV REM
12 %left MCH
13 %left MATCH
14 %left SUBSTR
15 %left LENGTH INDEX
16
17 %{
18 #define YYSTYPE charp
19
20 typedef char *charp;
21 %}
22
23 %%
24
25 /* a single `expression' is evaluated and printed: */
26
27 expression: expr NOARG = {
28 prt(1, $1);
29 exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0);
30 }
31 ;
32
33
34 expr: '(' expr ')' = { $$ = $2; }
35 | expr OR expr = { $$ = conj(OR, $1, $3); }
36 | expr AND expr = { $$ = conj(AND, $1, $3); }
37 | expr EQ expr = { $$ = rel(EQ, $1, $3); }
38 | expr GT expr = { $$ = rel(GT, $1, $3); }
39 | expr GEQ expr = { $$ = rel(GEQ, $1, $3); }
40 | expr LT expr = { $$ = rel(LT, $1, $3); }
41 | expr LEQ expr = { $$ = rel(LEQ, $1, $3); }
42 | expr NEQ expr = { $$ = rel(NEQ, $1, $3); }
43 | expr ADD expr = { $$ = arith(ADD, $1, $3); }
44 | expr SUBT expr = { $$ = arith(SUBT, $1, $3); }
45 | expr MULT expr = { $$ = arith(MULT, $1, $3); }
46 | expr DIV expr = { $$ = arith(DIV, $1, $3); }
47 | expr REM expr = { $$ = arith(REM, $1, $3); }
48 | expr MCH expr = { $$ = match($1, $3); }
49 | MATCH expr expr = { $$ = match($2, $3); }
50 | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); }
51 | LENGTH expr = { $$ = length($2); }
52 | INDEX expr expr = { $$ = index($2, $3); }
53 | A_STRING
54 ;
55 %%
56 /* expression command */
57 #include <stdio.h>
58 /* get rid of yacc debug printf's */
59 #define printf
60 #define ESIZE 512
61 #define error(c) errxx(c)
62 #define EQL(x,y) !strcmp(x,y)
63 long atol();
64 char *ltoa();
65 char **Av;
66 int Ac;
67 int Argi;
68
69 char Mstring[1][128];
70 char *malloc();
71 extern int nbra;
72 int yyparse(void);
73
main(argc,argv)74 main(argc, argv) char **argv; {
75 Ac = argc;
76 Argi = 1;
77 Av = argv;
78 yyparse();
79 }
80
81 char *operator[] = { "|", "&", "+", "-", "*", "/", "%", ":",
82 "=", "==", "<", "<=", ">", ">=", "!=",
83 "match", "substr", "length", "index", "\0" };
84 int op[] = { OR, AND, ADD, SUBT, MULT, DIV, REM, MCH,
85 EQ, EQ, LT, LEQ, GT, GEQ, NEQ,
86 MATCH, SUBSTR, LENGTH, INDEX };
yylex()87 yylex() {
88 register char *p;
89 register i;
90
91 if(Argi >= Ac) return NOARG;
92
93 p = Av[Argi++];
94
95 if(*p == '(' || *p == ')')
96 return (int)*p;
97 for(i = 0; *operator[i]; ++i)
98 if(EQL(operator[i], p))
99 return op[i];
100
101 yylval = p;
102 return A_STRING;
103 }
104
rel(op,r1,r2)105 char *rel(op, r1, r2) register char *r1, *r2; {
106 register i;
107
108 if(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$"))
109 i = atol(r1) - atol(r2);
110 else
111 i = strcmp(r1, r2);
112 switch(op) {
113 case EQ: i = i==0; break;
114 case GT: i = i>0; break;
115 case GEQ: i = i>=0; break;
116 case LT: i = i<0; break;
117 case LEQ: i = i<=0; break;
118 case NEQ: i = i!=0; break;
119 }
120 return i? "1": "0";
121 }
122
arith(op,r1,r2)123 char *arith(op, r1, r2) char *r1, *r2; {
124 long i1, i2;
125 register char *rv;
126
127 if(!(ematch(r1, "-\\{0,1\\}[0-9]*$") && ematch(r2, "-\\{0,1\\}[0-9]*$")))
128 yyerror("non-numeric argument");
129 i1 = atol(r1);
130 i2 = atol(r2);
131
132 switch(op) {
133 case ADD: i1 = i1 + i2; break;
134 case SUBT: i1 = i1 - i2; break;
135 case MULT: i1 = i1 * i2; break;
136 case DIV: i1 = i1 / i2; break;
137 case REM: i1 = i1 % i2; break;
138 }
139 rv = malloc(16);
140 strcpy(rv, ltoa(i1));
141 return rv;
142 }
conj(op,r1,r2)143 char *conj(op, r1, r2) char *r1, *r2; {
144 register char *rv;
145
146 switch(op) {
147
148 case OR:
149 if(EQL(r1, "0")
150 || EQL(r1, ""))
151 if(EQL(r2, "0")
152 || EQL(r2, ""))
153 rv = "0";
154 else
155 rv = r2;
156 else
157 rv = r1;
158 break;
159 case AND:
160 if(EQL(r1, "0")
161 || EQL(r1, ""))
162 rv = "0";
163 else if(EQL(r2, "0")
164 || EQL(r2, ""))
165 rv = "0";
166 else
167 rv = r1;
168 break;
169 }
170 return rv;
171 }
172
substr(v,s,w)173 char *substr(v, s, w) char *v, *s, *w; {
174 register si, wi;
175 register char *res;
176
177 si = atol(s);
178 wi = atol(w);
179 while(--si) if(*v) ++v;
180
181 res = v;
182
183 while(wi--) if(*v) ++v;
184
185 *v = '\0';
186 return res;
187 }
188
length(s)189 char *length(s) register char *s; {
190 register i = 0;
191 register char *rv;
192
193 while(*s++) ++i;
194
195 rv = malloc(8);
196 strcpy(rv, ltoa((long)i));
197 return rv;
198 }
199
index(s,t)200 char *index(s, t) char *s, *t; {
201 register i, j;
202 register char *rv;
203
204 for(i = 0; s[i] ; ++i)
205 for(j = 0; t[j] ; ++j)
206 if(s[i]==t[j]) {
207 strcpy(rv=malloc(8), ltoa((long)++i));
208 return rv;
209 }
210 return "0";
211 }
212
match(s,p)213 char *match(s, p)
214 {
215 register char *rv;
216
217 strcpy(rv=malloc(8), ltoa((long)ematch(s, p)));
218 if(nbra) {
219 rv = malloc(strlen(Mstring[0])+1);
220 strcpy(rv, Mstring[0]);
221 }
222 return rv;
223 }
224
225 #define INIT register char *sp = instring;
226 #define GETC() (*sp++)
227 #define PEEKC() (*sp)
228 #define UNGETC(c) (--sp)
229 #define RETURN(c) return
230 #define ERROR(c) errxx(c)
231
232
ematch(s,p)233 ematch(s, p)
234 char *s;
235 register char *p;
236 {
237 static char expbuf[ESIZE];
238 char *compile();
239 register num;
240 extern char *braslist[], *braelist[], *loc2;
241
242 compile(p, expbuf, &expbuf[ESIZE], 0);
243 if(nbra > 1)
244 yyerror("Too many '\\('s");
245 if(advance(s, expbuf)) {
246 if(nbra == 1) {
247 p = braslist[0];
248 num = braelist[0] - p;
249 strncpy(Mstring[0], p, num);
250 Mstring[0][num] = '\0';
251 }
252 return(loc2-s);
253 }
254 return(0);
255 }
256
errxx(c)257 errxx(c)
258 {
259 yyerror("RE error");
260 }
261
262 #include "regexp.h"
yyerror(s)263 yyerror(s)
264
265 {
266 write(2, "expr: ", 6);
267 prt(2, s);
268 exit(2);
269 }
prt(fd,s)270 prt(fd, s)
271 char *s;
272 {
273 write(fd, s, strlen(s));
274 write(fd, "\n", 1);
275 }
ltoa(l)276 char *ltoa(l)
277 long l;
278 {
279 static char str[20];
280 register char *sp = &str[18];
281 register i;
282 register neg = 0;
283
284 if(l < 0)
285 ++neg, l *= -1;
286 str[19] = '\0';
287 do {
288 i = l % 10;
289 *sp-- = '0' + i;
290 l /= 10;
291 } while(l);
292 if(neg)
293 *sp-- = '-';
294 return ++sp;
295 }
296