1 /* @(#)parser4.c 8.1 (Berkeley) 6/6/93 */ 2 /* $NetBSD: parser4.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Edward Wang at The University of California, Berkeley. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <string.h> 37 #include "defs.h" 38 #include "parser.h" 39 40 /* 41 * | 3 42 * ^ 4 43 * & 5 44 * == != 6 45 * < <= > >= 7 46 * << >> 8 47 * + - 9 48 * * / % 10 49 */ 50 int 51 p_expr3_10(int level, struct value *v, char flag) 52 { 53 struct value l, r; 54 int op; 55 const char *opname = NULL; 56 57 if ((level == 10 ? p_expr11(v, flag) 58 : p_expr3_10(level + 1, v, flag)) < 0) 59 return -1; 60 for (;;) { 61 switch (level) { 62 case 3: 63 if (token != T_OR) 64 return 0; 65 opname = "|"; 66 break; 67 case 4: 68 if (token != T_XOR) 69 return 0; 70 opname = "^"; 71 break; 72 case 5: 73 if (token != T_AND) 74 return 0; 75 opname = "&"; 76 break; 77 case 6: 78 if (token == T_EQ) 79 opname = "=="; 80 else if (token == T_NE) 81 opname = "!="; 82 else 83 return 0; 84 break; 85 case 7: 86 switch (token) { 87 case T_LT: 88 opname = "<"; 89 break; 90 case T_LE: 91 opname = "<="; 92 break; 93 case T_GT: 94 opname = ">"; 95 break; 96 case T_GE: 97 opname = ">="; 98 break; 99 default: 100 return 0; 101 } 102 break; 103 case 8: 104 if (token == T_LS) 105 opname = "<<"; 106 else if (token == T_RS) 107 opname = ">>"; 108 else 109 return 0; 110 break; 111 case 9: 112 if (token == T_PLUS) 113 opname = "+"; 114 else if (token == T_MINUS) 115 opname = "-"; 116 else 117 return 0; 118 break; 119 case 10: 120 switch (token) { 121 case T_MUL: 122 opname = "*"; 123 break; 124 case T_DIV: 125 opname = "/"; 126 break; 127 case T_MOD: 128 opname = "%"; 129 break; 130 default: 131 return 0; 132 } 133 break; 134 } 135 l = *v; 136 if (l.v_type == V_ERR) 137 flag = 0; 138 139 op = token; 140 (void) s_gettok(); 141 if ((level == 10 ? p_expr11(&r, flag) 142 : p_expr3_10(level + 1, &r, flag)) < 0) { 143 p_synerror(); 144 val_free(l); 145 return -1; 146 } 147 148 if (r.v_type == V_ERR) 149 flag = 0; 150 else switch (op) { 151 case T_EQ: 152 case T_NE: 153 case T_LT: 154 case T_LE: 155 case T_GT: 156 case T_GE: 157 case T_PLUS: 158 if (l.v_type == V_STR) { 159 if (r.v_type == V_NUM) 160 if (p_convstr(&r) < 0) 161 flag = 0; 162 } else 163 if (r.v_type == V_STR) 164 if (p_convstr(&l) < 0) 165 flag = 0; 166 break; 167 case T_LS: 168 case T_RS: 169 if (r.v_type == V_STR) { 170 char *p = r.v_str; 171 r.v_type = V_NUM; 172 r.v_num = strlen(p); 173 str_free(p); 174 } 175 break; 176 case T_OR: 177 case T_XOR: 178 case T_AND: 179 case T_MINUS: 180 case T_MUL: 181 case T_DIV: 182 case T_MOD: 183 default: 184 if (l.v_type == V_STR || r.v_type == V_STR) { 185 p_error("%s: Numeric operands required.", 186 opname); 187 flag = 0; 188 } 189 } 190 if (!flag) { 191 val_free(l); 192 val_free(r); 193 v->v_type = V_ERR; 194 if (p_abort()) 195 return -1; 196 continue; 197 } 198 199 v->v_type = V_NUM; 200 switch (op) { 201 case T_EQ: 202 case T_NE: 203 case T_LT: 204 case T_LE: 205 case T_GT: 206 case T_GE: 207 if (l.v_type == V_STR) { 208 int tmp = strcmp(l.v_str, r.v_str); 209 str_free(l.v_str); 210 str_free(r.v_str); 211 l.v_type = V_NUM; 212 l.v_num = tmp; 213 r.v_type = V_NUM; 214 r.v_num = 0; 215 } 216 break; 217 } 218 switch (op) { 219 case T_OR: 220 v->v_num = l.v_num | r.v_num; 221 break; 222 case T_XOR: 223 v->v_num = l.v_num ^ r.v_num; 224 break; 225 case T_AND: 226 v->v_num = l.v_num & r.v_num; 227 break; 228 case T_EQ: 229 v->v_num = l.v_num == r.v_num; 230 break; 231 case T_NE: 232 v->v_num = l.v_num != r.v_num; 233 break; 234 case T_LT: 235 v->v_num = l.v_num < r.v_num; 236 break; 237 case T_LE: 238 v->v_num = l.v_num <= r.v_num; 239 break; 240 case T_GT: 241 v->v_num = l.v_num > r.v_num; 242 break; 243 case T_GE: 244 v->v_num = l.v_num >= r.v_num; 245 break; 246 case T_LS: 247 if (l.v_type == V_STR) { 248 int i; 249 if ((i = strlen(l.v_str)) > r.v_num) 250 i = r.v_num; 251 v->v_str = str_ncpy(l.v_str, i); 252 v->v_type = V_STR; 253 } else 254 v->v_num = l.v_num << r.v_num; 255 break; 256 case T_RS: 257 if (l.v_type == V_STR) { 258 int i; 259 if ((i = strlen(l.v_str)) > r.v_num) 260 i -= r.v_num; 261 else 262 i = 0; 263 v->v_str = str_cpy(l.v_str + i); 264 v->v_type = V_STR; 265 } else 266 v->v_num = l.v_num >> r.v_num; 267 break; 268 case T_PLUS: 269 if (l.v_type == V_STR) { 270 v->v_str = str_cat(l.v_str, r.v_str); 271 v->v_type = V_STR; 272 } else 273 v->v_num = l.v_num + r.v_num; 274 break; 275 case T_MINUS: 276 v->v_num = l.v_num - r.v_num; 277 break; 278 case T_MUL: 279 v->v_num = l.v_num * r.v_num; 280 break; 281 case T_DIV: 282 v->v_num = l.v_num / r.v_num; 283 break; 284 case T_MOD: 285 v->v_num = l.v_num % r.v_num; 286 break; 287 } 288 val_free(l); 289 val_free(r); 290 } 291 /*NOTREACHED*/ 292 } 293