#ifndef lint static char sccsid[] = "@(#)parser4.c 3.4 4/24/85"; #endif /* * Copyright (c) 1983 Regents of the University of California, * All rights reserved. Redistribution permitted subject to * the terms of the Berkeley Software License Agreement. */ #include "parser.h" /* * | 3 * ^ 4 * & 5 * == != 6 * < <= > >= 7 * << >> 8 * + - 9 * * / % 10 */ p_expr3_10(level, v, flag) register struct value *v; char flag; { struct value l, r; int op; char *opname; if ((level == 10 ? p_expr11(v, flag) : p_expr3_10(level + 1, v, flag)) < 0) return -1; for (;;) { switch (level) { case 3: if (token != T_OR) return 0; opname = "|"; break; case 4: if (token != T_XOR) return 0; opname = "^"; break; case 5: if (token != T_AND) return 0; opname = "&"; break; case 6: if (token == T_EQ) opname = "=="; else if (token == T_NE) opname = "!="; else return 0; break; case 7: switch (token) { case T_LT: opname = "<"; break; case T_LE: opname = "<="; break; case T_GT: opname = ">"; break; case T_GE: opname = ">="; break; default: return 0; } break; case 8: if (token == T_LS) opname = "<<"; else if (token == T_RS) opname = ">>"; else return 0; break; case 9: if (token == T_PLUS) opname = "+"; else if (token == T_MINUS) opname = "-"; else return 0; break; case 10: switch (token) { case T_MUL: opname = "*"; break; case T_DIV: opname = "/"; break; case T_MOD: opname = "%"; break; default: return 0; } break; } l = *v; if (l.v_type == V_ERR) flag = 0; op = token; (void) s_gettok(); if ((level == 10 ? p_expr11(&r, flag) : p_expr3_10(level + 1, &r, flag)) < 0) { p_synerror(); val_free(l); return -1; } if (r.v_type == V_ERR) flag = 0; else switch (op) { case T_EQ: case T_NE: case T_LT: case T_LE: case T_GT: case T_GE: case T_PLUS: if (l.v_type == V_STR) { if (r.v_type == V_NUM) if (p_convstr(&r) < 0) flag = 0; } else if (r.v_type == V_STR) if (p_convstr(&l) < 0) flag = 0; break; case T_LS: case T_RS: if (r.v_type == V_STR) { char *p = r.v_str; r.v_type = V_NUM; r.v_num = strlen(p); str_free(p); } break; case T_OR: case T_XOR: case T_AND: case T_MINUS: case T_MUL: case T_DIV: case T_MOD: default: if (l.v_type == V_STR || r.v_type == V_STR) { p_error("%s: Numeric operands required.", opname); flag = 0; } } if (!flag) { val_free(l); val_free(r); v->v_type = V_ERR; if (p_abort()) return -1; continue; } v->v_type = V_NUM; switch (op) { case T_EQ: case T_NE: case T_LT: case T_LE: case T_GT: case T_GE: if (l.v_type == V_STR) { int tmp = strcmp(l.v_str, r.v_str); str_free(l.v_str); str_free(r.v_str); l.v_type = V_NUM; l.v_num = tmp; r.v_type = V_NUM; r.v_num = 0; } break; } switch (op) { case T_OR: v->v_num = l.v_num | r.v_num; break; case T_XOR: v->v_num = l.v_num ^ r.v_num; break; case T_AND: v->v_num = l.v_num & r.v_num; break; case T_EQ: v->v_num = l.v_num == r.v_num; break; case T_NE: v->v_num = l.v_num != r.v_num; break; case T_LT: v->v_num = l.v_num < r.v_num; break; case T_LE: v->v_num = l.v_num <= r.v_num; break; case T_GT: v->v_num = l.v_num > r.v_num; break; case T_GE: v->v_num = l.v_num >= r.v_num; break; case T_LS: if (l.v_type == V_STR) { int i; if ((i = strlen(l.v_str)) > r.v_num) i = r.v_num; v->v_str = str_ncpy(l.v_str, i); v->v_type = V_STR; } else v->v_num = l.v_num << r.v_num; break; case T_RS: if (l.v_type == V_STR) { int i; if ((i = strlen(l.v_str)) > r.v_num) i -= r.v_num; else i = 0; v->v_str = str_cpy(l.v_str + i); v->v_type = V_STR; } else v->v_num = l.v_num >> r.v_num; break; case T_PLUS: if (l.v_type == V_STR) { v->v_str = str_cat(l.v_str, r.v_str); v->v_type = V_STR; } else v->v_num = l.v_num + r.v_num; break; case T_MINUS: v->v_num = l.v_num - r.v_num; break; case T_MUL: v->v_num = l.v_num * r.v_num; break; case T_DIV: v->v_num = l.v_num / r.v_num; break; case T_MOD: v->v_num = l.v_num % r.v_num; break; } val_free(l); val_free(r); } /*NOTREACHED*/ }