1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)parser4.c 8.1 (Berkeley) 06/06/93"; 13 #endif /* not lint */ 14 15 #include "parser.h" 16 17 /* 18 * | 3 19 * ^ 4 20 * & 5 21 * == != 6 22 * < <= > >= 7 23 * << >> 8 24 * + - 9 25 * * / % 10 26 */ 27 p_expr3_10(level, v, flag) 28 register struct value *v; 29 char flag; 30 { 31 struct value l, r; 32 int op; 33 char *opname; 34 35 if ((level == 10 ? p_expr11(v, flag) 36 : p_expr3_10(level + 1, v, flag)) < 0) 37 return -1; 38 for (;;) { 39 switch (level) { 40 case 3: 41 if (token != T_OR) 42 return 0; 43 opname = "|"; 44 break; 45 case 4: 46 if (token != T_XOR) 47 return 0; 48 opname = "^"; 49 break; 50 case 5: 51 if (token != T_AND) 52 return 0; 53 opname = "&"; 54 break; 55 case 6: 56 if (token == T_EQ) 57 opname = "=="; 58 else if (token == T_NE) 59 opname = "!="; 60 else 61 return 0; 62 break; 63 case 7: 64 switch (token) { 65 case T_LT: 66 opname = "<"; 67 break; 68 case T_LE: 69 opname = "<="; 70 break; 71 case T_GT: 72 opname = ">"; 73 break; 74 case T_GE: 75 opname = ">="; 76 break; 77 default: 78 return 0; 79 } 80 break; 81 case 8: 82 if (token == T_LS) 83 opname = "<<"; 84 else if (token == T_RS) 85 opname = ">>"; 86 else 87 return 0; 88 break; 89 case 9: 90 if (token == T_PLUS) 91 opname = "+"; 92 else if (token == T_MINUS) 93 opname = "-"; 94 else 95 return 0; 96 break; 97 case 10: 98 switch (token) { 99 case T_MUL: 100 opname = "*"; 101 break; 102 case T_DIV: 103 opname = "/"; 104 break; 105 case T_MOD: 106 opname = "%"; 107 break; 108 default: 109 return 0; 110 } 111 break; 112 } 113 l = *v; 114 if (l.v_type == V_ERR) 115 flag = 0; 116 117 op = token; 118 (void) s_gettok(); 119 if ((level == 10 ? p_expr11(&r, flag) 120 : p_expr3_10(level + 1, &r, flag)) < 0) { 121 p_synerror(); 122 val_free(l); 123 return -1; 124 } 125 126 if (r.v_type == V_ERR) 127 flag = 0; 128 else switch (op) { 129 case T_EQ: 130 case T_NE: 131 case T_LT: 132 case T_LE: 133 case T_GT: 134 case T_GE: 135 case T_PLUS: 136 if (l.v_type == V_STR) { 137 if (r.v_type == V_NUM) 138 if (p_convstr(&r) < 0) 139 flag = 0; 140 } else 141 if (r.v_type == V_STR) 142 if (p_convstr(&l) < 0) 143 flag = 0; 144 break; 145 case T_LS: 146 case T_RS: 147 if (r.v_type == V_STR) { 148 char *p = r.v_str; 149 r.v_type = V_NUM; 150 r.v_num = strlen(p); 151 str_free(p); 152 } 153 break; 154 case T_OR: 155 case T_XOR: 156 case T_AND: 157 case T_MINUS: 158 case T_MUL: 159 case T_DIV: 160 case T_MOD: 161 default: 162 if (l.v_type == V_STR || r.v_type == V_STR) { 163 p_error("%s: Numeric operands required.", 164 opname); 165 flag = 0; 166 } 167 } 168 if (!flag) { 169 val_free(l); 170 val_free(r); 171 v->v_type = V_ERR; 172 if (p_abort()) 173 return -1; 174 continue; 175 } 176 177 v->v_type = V_NUM; 178 switch (op) { 179 case T_EQ: 180 case T_NE: 181 case T_LT: 182 case T_LE: 183 case T_GT: 184 case T_GE: 185 if (l.v_type == V_STR) { 186 int tmp = strcmp(l.v_str, r.v_str); 187 str_free(l.v_str); 188 str_free(r.v_str); 189 l.v_type = V_NUM; 190 l.v_num = tmp; 191 r.v_type = V_NUM; 192 r.v_num = 0; 193 } 194 break; 195 } 196 switch (op) { 197 case T_OR: 198 v->v_num = l.v_num | r.v_num; 199 break; 200 case T_XOR: 201 v->v_num = l.v_num ^ r.v_num; 202 break; 203 case T_AND: 204 v->v_num = l.v_num & r.v_num; 205 break; 206 case T_EQ: 207 v->v_num = l.v_num == r.v_num; 208 break; 209 case T_NE: 210 v->v_num = l.v_num != r.v_num; 211 break; 212 case T_LT: 213 v->v_num = l.v_num < r.v_num; 214 break; 215 case T_LE: 216 v->v_num = l.v_num <= r.v_num; 217 break; 218 case T_GT: 219 v->v_num = l.v_num > r.v_num; 220 break; 221 case T_GE: 222 v->v_num = l.v_num >= r.v_num; 223 break; 224 case T_LS: 225 if (l.v_type == V_STR) { 226 int i; 227 if ((i = strlen(l.v_str)) > r.v_num) 228 i = r.v_num; 229 v->v_str = str_ncpy(l.v_str, i); 230 v->v_type = V_STR; 231 } else 232 v->v_num = l.v_num << r.v_num; 233 break; 234 case T_RS: 235 if (l.v_type == V_STR) { 236 int i; 237 if ((i = strlen(l.v_str)) > r.v_num) 238 i -= r.v_num; 239 else 240 i = 0; 241 v->v_str = str_cpy(l.v_str + i); 242 v->v_type = V_STR; 243 } else 244 v->v_num = l.v_num >> r.v_num; 245 break; 246 case T_PLUS: 247 if (l.v_type == V_STR) { 248 v->v_str = str_cat(l.v_str, r.v_str); 249 v->v_type = V_STR; 250 } else 251 v->v_num = l.v_num + r.v_num; 252 break; 253 case T_MINUS: 254 v->v_num = l.v_num - r.v_num; 255 break; 256 case T_MUL: 257 v->v_num = l.v_num * r.v_num; 258 break; 259 case T_DIV: 260 v->v_num = l.v_num / r.v_num; 261 break; 262 case T_MOD: 263 v->v_num = l.v_num % r.v_num; 264 break; 265 } 266 val_free(l); 267 val_free(r); 268 } 269 /*NOTREACHED*/ 270 } 271