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