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