1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)parser5.c 3.11 (Berkeley) 06/29/88"; 20 #endif /* not lint */ 21 22 #include "parser.h" 23 #include "var.h" 24 25 /* 26 * unary $ $? + - ! ~ 27 */ 28 p_expr11(v, flag) 29 register struct value *v; 30 char flag; 31 { 32 int op; 33 char *opname; 34 35 switch (token) { 36 case T_DOLLAR: 37 opname = "$"; 38 break; 39 case T_DQ: 40 opname = "$?"; 41 break; 42 case T_PLUS: 43 opname = "unary +"; 44 break; 45 case T_MINUS: 46 opname = "unary -"; 47 break; 48 case T_NOT: 49 opname = "!"; 50 break; 51 case T_COMP: 52 opname = "~"; 53 break; 54 default: 55 return p_expr12(v, flag); 56 } 57 op = token; 58 (void) s_gettok(); 59 if (p_expr11(v, flag) < 0) 60 return -1; 61 switch (v->v_type) { 62 case V_NUM: 63 break; 64 case V_STR: 65 switch (op) { 66 case T_MINUS: 67 case T_NOT: 68 case T_COMP: 69 p_error("%s: Numeric operand required.", opname); 70 str_free(v->v_str); 71 v->v_type = V_ERR; 72 return 0; 73 } 74 break; 75 case V_ERR: 76 return 0; 77 } 78 switch (op) { 79 case T_DOLLAR: 80 case T_DQ: 81 if (v->v_type == V_NUM) { 82 int tmp = cx.x_type == X_BUF && cx.x_arg != 0 && 83 v->v_num > 0 && v->v_num <= cx.x_narg; 84 if (op == T_DQ) 85 v->v_num = tmp; 86 else if (tmp) 87 *v = cx.x_arg[v->v_num - 1]; 88 else { 89 p_error("%d: No such argument.", v->v_num); 90 v->v_type = V_ERR; 91 } 92 } else { 93 char *name = v->v_str; 94 struct var *r = var_lookup(name); 95 if (op == T_DQ) { 96 v->v_type = V_NUM; 97 v->v_num = r != 0; 98 } else if (r != 0) 99 *v = r->r_val; 100 else { 101 p_error("%s: Undefined variable.", name); 102 v->v_type = V_ERR; 103 } 104 str_free(name); 105 } 106 if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) { 107 p_memerror(); 108 return -1; 109 } 110 break; 111 case T_MINUS: 112 v->v_num = - v->v_num; 113 break; 114 case T_NOT: 115 v->v_num = ! v->v_num; 116 break; 117 case T_COMP: 118 v->v_num = ~ v->v_num; 119 break; 120 } 121 return 0; 122 } 123 124 /* 125 * string, number, ( expr ) 126 * Plus function calls. 127 * 128 * Always return v_type == V_ERR when flag == 0. 129 */ 130 p_expr12(v, flag) 131 register struct value *v; 132 char flag; 133 { 134 v->v_type = V_ERR; 135 switch (token) { 136 case T_NUM: 137 if (flag) { 138 v->v_type = V_NUM; 139 v->v_num = token_num; 140 } 141 (void) s_gettok(); 142 break; 143 case T_STR: 144 if (flag) { 145 v->v_type = V_STR; 146 v->v_str = token_str; 147 } else 148 str_free(token_str); 149 (void) s_gettok(); 150 break; 151 case T_LP: 152 (void) s_gettok(); 153 if (p_expr(v, flag) < 0) { 154 p_synerror(); 155 return -1; 156 } 157 if (token != T_RP) { 158 p_synerror(); 159 val_free(*v); 160 return -1; 161 } 162 (void) s_gettok(); 163 break; 164 default: 165 return -1; 166 } 167 while (token == T_LP) { 168 char *cmd; 169 170 if (p_convstr(v) < 0) 171 return -1; 172 cmd = v->v_type == V_STR ? v->v_str : 0; 173 if (p_function(cmd, v, flag) < 0) { 174 if (cmd) 175 str_free(cmd); 176 return -1; 177 } 178 if (cmd) 179 str_free(cmd); 180 } 181 return 0; 182 } 183