Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/dash/arith_yacc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1122 - (hide annotations) (download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 7322 byte(s)
-updated to klibc-1.5.19
1 niro 1122 /*-
2     * Copyright (c) 1993
3     * The Regents of the University of California. All rights reserved.
4     * Copyright (c) 2007
5     * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
6     *
7     * This code is derived from software contributed to Berkeley by
8     * Kenneth Almquist.
9     *
10     * Redistribution and use in source and binary forms, with or without
11     * modification, are permitted provided that the following conditions
12     * are met:
13     * 1. Redistributions of source code must retain the above copyright
14     * notice, this list of conditions and the following disclaimer.
15     * 2. Redistributions in binary form must reproduce the above copyright
16     * notice, this list of conditions and the following disclaimer in the
17     * documentation and/or other materials provided with the distribution.
18     * 3. Neither the name of the University nor the names of its contributors
19     * may be used to endorse or promote products derived from this software
20     * without specific prior written permission.
21     *
22     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25     * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32     * SUCH DAMAGE.
33     */
34    
35     #include <inttypes.h>
36     #include <stdint.h>
37     #include <stdlib.h>
38     #include "arith_yacc.h"
39     #include "expand.h"
40     #include "shell.h"
41     #include "error.h"
42     #include "output.h"
43     #include "var.h"
44    
45     #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
46     #error Arithmetic tokens are out of order.
47     #endif
48    
49     static const char *arith_startbuf;
50    
51     const char *arith_buf;
52     union yystype yylval;
53    
54     static int last_token;
55    
56     #define ARITH_PRECEDENCE(op, prec) [op - ARITH_BINOP_MIN] = prec
57    
58     static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = {
59     ARITH_PRECEDENCE(ARITH_MUL, 0),
60     ARITH_PRECEDENCE(ARITH_DIV, 0),
61     ARITH_PRECEDENCE(ARITH_REM, 0),
62     ARITH_PRECEDENCE(ARITH_ADD, 1),
63     ARITH_PRECEDENCE(ARITH_SUB, 1),
64     ARITH_PRECEDENCE(ARITH_LSHIFT, 2),
65     ARITH_PRECEDENCE(ARITH_RSHIFT, 2),
66     ARITH_PRECEDENCE(ARITH_LT, 3),
67     ARITH_PRECEDENCE(ARITH_LE, 3),
68     ARITH_PRECEDENCE(ARITH_GT, 3),
69     ARITH_PRECEDENCE(ARITH_GE, 3),
70     ARITH_PRECEDENCE(ARITH_EQ, 4),
71     ARITH_PRECEDENCE(ARITH_NE, 4),
72     ARITH_PRECEDENCE(ARITH_BAND, 5),
73     ARITH_PRECEDENCE(ARITH_BXOR, 6),
74     ARITH_PRECEDENCE(ARITH_BOR, 7),
75     };
76    
77     #define ARITH_MAX_PREC 8
78    
79     static void yyerror(const char *s) __attribute__ ((noreturn));
80     static void yyerror(const char *s)
81     {
82     sh_error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
83     /* NOTREACHED */
84     }
85    
86     static inline int arith_prec(int op)
87     {
88     return prec[op - ARITH_BINOP_MIN];
89     }
90    
91     static inline int higher_prec(int op1, int op2)
92     {
93     return arith_prec(op1) < arith_prec(op2);
94     }
95    
96     static intmax_t do_binop(int op, intmax_t a, intmax_t b)
97     {
98     #ifdef HAVE_IMAXDIV
99     imaxdiv_t div;
100     #endif
101    
102     switch (op) {
103     default:
104     case ARITH_REM:
105     case ARITH_DIV:
106     if (!b)
107     yyerror("division by zero");
108     #ifdef HAVE_IMAXDIV
109     div = imaxdiv(a, b);
110     return op == ARITH_REM ? div.rem : div.quot;
111     #else
112     return op == ARITH_REM ? a % b : a / b;
113     #endif
114     case ARITH_MUL:
115     return a * b;
116     case ARITH_ADD:
117     return a + b;
118     case ARITH_SUB:
119     return a - b;
120     case ARITH_LSHIFT:
121     return a << b;
122     case ARITH_RSHIFT:
123     return a >> b;
124     case ARITH_LT:
125     return a < b;
126     case ARITH_LE:
127     return a <= b;
128     case ARITH_GT:
129     return a > b;
130     case ARITH_GE:
131     return a >= b;
132     case ARITH_EQ:
133     return a == b;
134     case ARITH_NE:
135     return a != b;
136     case ARITH_BAND:
137     return a & b;
138     case ARITH_BXOR:
139     return a ^ b;
140     case ARITH_BOR:
141     return a | b;
142     }
143     }
144    
145     static intmax_t assignment(int var, int noeval);
146    
147     static intmax_t primary(int token, union yystype *val, int op, int noeval)
148     {
149     intmax_t result;
150    
151     again:
152     switch (token) {
153     case ARITH_LPAREN:
154     result = assignment(op, noeval);
155     if (last_token != ARITH_RPAREN)
156     yyerror("expecting ')'");
157     last_token = yylex();
158     return result;
159     case ARITH_NUM:
160     last_token = op;
161     return val->val;
162     case ARITH_VAR:
163     last_token = op;
164     return noeval ? val->val : lookupvarint(val->name);
165     case ARITH_ADD:
166     token = op;
167     *val = yylval;
168     op = yylex();
169     goto again;
170     case ARITH_SUB:
171     *val = yylval;
172     return -primary(op, val, yylex(), noeval);
173     case ARITH_NOT:
174     *val = yylval;
175     return !primary(op, val, yylex(), noeval);
176     case ARITH_BNOT:
177     *val = yylval;
178     return ~primary(op, val, yylex(), noeval);
179     default:
180     yyerror("expecting primary");
181     }
182     }
183    
184     static intmax_t binop2(intmax_t a, int op, int prec, int noeval)
185     {
186     for (;;) {
187     union yystype val;
188     intmax_t b;
189     int op2;
190     int token;
191    
192     token = yylex();
193     val = yylval;
194    
195     b = primary(token, &val, yylex(), noeval);
196    
197     op2 = last_token;
198     if (op2 >= ARITH_BINOP_MIN && op2 < ARITH_BINOP_MAX &&
199     higher_prec(op2, op)) {
200     b = binop2(b, op2, arith_prec(op), noeval);
201     op2 = last_token;
202     }
203    
204     a = noeval ? b : do_binop(op, a, b);
205    
206     if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX ||
207     arith_prec(op2) >= prec)
208     return a;
209    
210     op = op2;
211     }
212     }
213    
214     static intmax_t binop(int token, union yystype *val, int op, int noeval)
215     {
216     intmax_t a = primary(token, val, op, noeval);
217    
218     op = last_token;
219     if (op < ARITH_BINOP_MIN || op >= ARITH_BINOP_MAX)
220     return a;
221    
222     return binop2(a, op, ARITH_MAX_PREC, noeval);
223     }
224    
225     static intmax_t and(int token, union yystype *val, int op, int noeval)
226     {
227     intmax_t a = binop(token, val, op, noeval);
228     intmax_t b;
229    
230     op = last_token;
231     if (op != ARITH_AND)
232     return a;
233    
234     token = yylex();
235     *val = yylval;
236    
237     b = and(token, val, yylex(), noeval | !a);
238    
239     return a && b;
240     }
241    
242     static intmax_t or(int token, union yystype *val, int op, int noeval)
243     {
244     intmax_t a = and(token, val, op, noeval);
245     intmax_t b;
246    
247     op = last_token;
248     if (op != ARITH_OR)
249     return a;
250    
251     token = yylex();
252     *val = yylval;
253    
254     b = or(token, val, yylex(), noeval | !!a);
255    
256     return a || b;
257     }
258    
259     static intmax_t cond(int token, union yystype *val, int op, int noeval)
260     {
261     intmax_t a = or(token, val, op, noeval);
262     intmax_t b;
263     intmax_t c;
264    
265     if (last_token != ARITH_QMARK)
266     return a;
267    
268     b = assignment(yylex(), noeval | !a);
269    
270     if (last_token != ARITH_COLON)
271     yyerror("expecting ':'");
272    
273     token = yylex();
274     *val = yylval;
275    
276     c = cond(token, val, yylex(), noeval | !!a);
277    
278     return a ? b : c;
279     }
280    
281     static intmax_t assignment(int var, int noeval)
282     {
283     union yystype val = yylval;
284     int op = yylex();
285     intmax_t result;
286    
287     if (var != ARITH_VAR)
288     return cond(var, &val, op, noeval);
289    
290     if (op != ARITH_ASS && (op < ARITH_ASS_MIN || op >= ARITH_ASS_MAX))
291     return cond(var, &val, op, noeval);
292    
293     result = assignment(yylex(), noeval);
294     if (noeval)
295     return result;
296    
297     return setvarint(val.name,
298     op == ARITH_ASS ? result :
299     do_binop(op - 11, lookupvarint(val.name), result), 0);
300     }
301    
302     intmax_t arith(const char *s)
303     {
304     intmax_t result;
305    
306     arith_buf = arith_startbuf = s;
307    
308     result = assignment(yylex(), 0);
309    
310     if (last_token)
311     yyerror("expecting EOF");
312    
313     return result;
314     }