1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)parser5.c 8.1 (Berkeley) 06/06/93"; 13 #endif /* not lint */ 14 15 #include "parser.h" 16 #include "var.h" 17 18 /* 19 * unary $ $? + - ! ~ 20 */ 21 p_expr11(v, flag) 22 register struct value *v; 23 char flag; 24 { 25 int op; 26 char *opname; 27 28 switch (token) { 29 case T_DOLLAR: 30 opname = "$"; 31 break; 32 case T_DQ: 33 opname = "$?"; 34 break; 35 case T_PLUS: 36 opname = "unary +"; 37 break; 38 case T_MINUS: 39 opname = "unary -"; 40 break; 41 case T_NOT: 42 opname = "!"; 43 break; 44 case T_COMP: 45 opname = "~"; 46 break; 47 default: 48 return p_expr12(v, flag); 49 } 50 op = token; 51 (void) s_gettok(); 52 if (p_expr11(v, flag) < 0) 53 return -1; 54 switch (v->v_type) { 55 case V_NUM: 56 break; 57 case V_STR: 58 switch (op) { 59 case T_MINUS: 60 case T_NOT: 61 case T_COMP: 62 p_error("%s: Numeric operand required.", opname); 63 str_free(v->v_str); 64 v->v_type = V_ERR; 65 return 0; 66 } 67 break; 68 case V_ERR: 69 return 0; 70 } 71 switch (op) { 72 case T_DOLLAR: 73 case T_DQ: 74 if (v->v_type == V_NUM) { 75 int tmp = cx.x_type == X_BUF && cx.x_arg != 0 && 76 v->v_num > 0 && v->v_num <= cx.x_narg; 77 if (op == T_DQ) 78 v->v_num = tmp; 79 else if (tmp) 80 *v = cx.x_arg[v->v_num - 1]; 81 else { 82 p_error("%d: No such argument.", v->v_num); 83 v->v_type = V_ERR; 84 } 85 } else { 86 char *name = v->v_str; 87 struct var *r = var_lookup(name); 88 if (op == T_DQ) { 89 v->v_type = V_NUM; 90 v->v_num = r != 0; 91 } else if (r != 0) 92 *v = r->r_val; 93 else { 94 p_error("%s: Undefined variable.", name); 95 v->v_type = V_ERR; 96 } 97 str_free(name); 98 } 99 if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) { 100 p_memerror(); 101 return -1; 102 } 103 break; 104 case T_MINUS: 105 v->v_num = - v->v_num; 106 break; 107 case T_NOT: 108 v->v_num = ! v->v_num; 109 break; 110 case T_COMP: 111 v->v_num = ~ v->v_num; 112 break; 113 } 114 return 0; 115 } 116 117 /* 118 * string, number, ( expr ) 119 * Plus function calls. 120 * 121 * Always return v_type == V_ERR when flag == 0. 122 */ 123 p_expr12(v, flag) 124 register struct value *v; 125 char flag; 126 { 127 v->v_type = V_ERR; 128 switch (token) { 129 case T_NUM: 130 if (flag) { 131 v->v_type = V_NUM; 132 v->v_num = token_num; 133 } 134 (void) s_gettok(); 135 break; 136 case T_STR: 137 if (flag) { 138 v->v_type = V_STR; 139 v->v_str = token_str; 140 } else 141 str_free(token_str); 142 (void) s_gettok(); 143 break; 144 case T_LP: 145 (void) s_gettok(); 146 if (p_expr(v, flag) < 0) { 147 p_synerror(); 148 return -1; 149 } 150 if (token != T_RP) { 151 p_synerror(); 152 val_free(*v); 153 return -1; 154 } 155 (void) s_gettok(); 156 break; 157 default: 158 return -1; 159 } 160 while (token == T_LP) { 161 char *cmd; 162 163 if (p_convstr(v) < 0) 164 return -1; 165 cmd = v->v_type == V_STR ? v->v_str : 0; 166 if (p_function(cmd, v, flag) < 0) { 167 if (cmd) 168 str_free(cmd); 169 return -1; 170 } 171 if (cmd) 172 str_free(cmd); 173 } 174 return 0; 175 } 176