|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: static char sccsid[] = "@(#)parser4.c 3.6 (Berkeley) 6/29/88";
20: #endif /* not lint */
21:
22: #include "parser.h"
23:
24: /*
25: * | 3
26: * ^ 4
27: * & 5
28: * == != 6
29: * < <= > >= 7
30: * << >> 8
31: * + - 9
32: * * / % 10
33: */
34: p_expr3_10(level, v, flag)
35: register struct value *v;
36: char flag;
37: {
38: struct value l, r;
39: int op;
40: char *opname;
41:
42: if ((level == 10 ? p_expr11(v, flag)
43: : p_expr3_10(level + 1, v, flag)) < 0)
44: return -1;
45: for (;;) {
46: switch (level) {
47: case 3:
48: if (token != T_OR)
49: return 0;
50: opname = "|";
51: break;
52: case 4:
53: if (token != T_XOR)
54: return 0;
55: opname = "^";
56: break;
57: case 5:
58: if (token != T_AND)
59: return 0;
60: opname = "&";
61: break;
62: case 6:
63: if (token == T_EQ)
64: opname = "==";
65: else if (token == T_NE)
66: opname = "!=";
67: else
68: return 0;
69: break;
70: case 7:
71: switch (token) {
72: case T_LT:
73: opname = "<";
74: break;
75: case T_LE:
76: opname = "<=";
77: break;
78: case T_GT:
79: opname = ">";
80: break;
81: case T_GE:
82: opname = ">=";
83: break;
84: default:
85: return 0;
86: }
87: break;
88: case 8:
89: if (token == T_LS)
90: opname = "<<";
91: else if (token == T_RS)
92: opname = ">>";
93: else
94: return 0;
95: break;
96: case 9:
97: if (token == T_PLUS)
98: opname = "+";
99: else if (token == T_MINUS)
100: opname = "-";
101: else
102: return 0;
103: break;
104: case 10:
105: switch (token) {
106: case T_MUL:
107: opname = "*";
108: break;
109: case T_DIV:
110: opname = "/";
111: break;
112: case T_MOD:
113: opname = "%";
114: break;
115: default:
116: return 0;
117: }
118: break;
119: }
120: l = *v;
121: if (l.v_type == V_ERR)
122: flag = 0;
123:
124: op = token;
125: (void) s_gettok();
126: if ((level == 10 ? p_expr11(&r, flag)
127: : p_expr3_10(level + 1, &r, flag)) < 0) {
128: p_synerror();
129: val_free(l);
130: return -1;
131: }
132:
133: if (r.v_type == V_ERR)
134: flag = 0;
135: else switch (op) {
136: case T_EQ:
137: case T_NE:
138: case T_LT:
139: case T_LE:
140: case T_GT:
141: case T_GE:
142: case T_PLUS:
143: if (l.v_type == V_STR) {
144: if (r.v_type == V_NUM)
145: if (p_convstr(&r) < 0)
146: flag = 0;
147: } else
148: if (r.v_type == V_STR)
149: if (p_convstr(&l) < 0)
150: flag = 0;
151: break;
152: case T_LS:
153: case T_RS:
154: if (r.v_type == V_STR) {
155: char *p = r.v_str;
156: r.v_type = V_NUM;
157: r.v_num = strlen(p);
158: str_free(p);
159: }
160: break;
161: case T_OR:
162: case T_XOR:
163: case T_AND:
164: case T_MINUS:
165: case T_MUL:
166: case T_DIV:
167: case T_MOD:
168: default:
169: if (l.v_type == V_STR || r.v_type == V_STR) {
170: p_error("%s: Numeric operands required.",
171: opname);
172: flag = 0;
173: }
174: }
175: if (!flag) {
176: val_free(l);
177: val_free(r);
178: v->v_type = V_ERR;
179: if (p_abort())
180: return -1;
181: continue;
182: }
183:
184: v->v_type = V_NUM;
185: switch (op) {
186: case T_EQ:
187: case T_NE:
188: case T_LT:
189: case T_LE:
190: case T_GT:
191: case T_GE:
192: if (l.v_type == V_STR) {
193: int tmp = strcmp(l.v_str, r.v_str);
194: str_free(l.v_str);
195: str_free(r.v_str);
196: l.v_type = V_NUM;
197: l.v_num = tmp;
198: r.v_type = V_NUM;
199: r.v_num = 0;
200: }
201: break;
202: }
203: switch (op) {
204: case T_OR:
205: v->v_num = l.v_num | r.v_num;
206: break;
207: case T_XOR:
208: v->v_num = l.v_num ^ r.v_num;
209: break;
210: case T_AND:
211: v->v_num = l.v_num & r.v_num;
212: break;
213: case T_EQ:
214: v->v_num = l.v_num == r.v_num;
215: break;
216: case T_NE:
217: v->v_num = l.v_num != r.v_num;
218: break;
219: case T_LT:
220: v->v_num = l.v_num < r.v_num;
221: break;
222: case T_LE:
223: v->v_num = l.v_num <= r.v_num;
224: break;
225: case T_GT:
226: v->v_num = l.v_num > r.v_num;
227: break;
228: case T_GE:
229: v->v_num = l.v_num >= r.v_num;
230: break;
231: case T_LS:
232: if (l.v_type == V_STR) {
233: int i;
234: if ((i = strlen(l.v_str)) > r.v_num)
235: i = r.v_num;
236: v->v_str = str_ncpy(l.v_str, i);
237: v->v_type = V_STR;
238: } else
239: v->v_num = l.v_num << r.v_num;
240: break;
241: case T_RS:
242: if (l.v_type == V_STR) {
243: int i;
244: if ((i = strlen(l.v_str)) > r.v_num)
245: i -= r.v_num;
246: else
247: i = 0;
248: v->v_str = str_cpy(l.v_str + i);
249: v->v_type = V_STR;
250: } else
251: v->v_num = l.v_num >> r.v_num;
252: break;
253: case T_PLUS:
254: if (l.v_type == V_STR) {
255: v->v_str = str_cat(l.v_str, r.v_str);
256: v->v_type = V_STR;
257: } else
258: v->v_num = l.v_num + r.v_num;
259: break;
260: case T_MINUS:
261: v->v_num = l.v_num - r.v_num;
262: break;
263: case T_MUL:
264: v->v_num = l.v_num * r.v_num;
265: break;
266: case T_DIV:
267: v->v_num = l.v_num / r.v_num;
268: break;
269: case T_MOD:
270: v->v_num = l.v_num % r.v_num;
271: break;
272: }
273: val_free(l);
274: val_free(r);
275: }
276: /*NOTREACHED*/
277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.