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