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) 06/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 } 278