Commit | Line | Data |
---|---|---|
60de5df9 | 1 | /* |
46e9ea25 KB |
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 | |
5e8b0e60 KB |
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. | |
60de5df9 EW |
16 | */ |
17 | ||
46e9ea25 | 18 | #ifndef lint |
5e8b0e60 | 19 | static char sccsid[] = "@(#)parser5.c 3.11 (Berkeley) %G%"; |
46e9ea25 KB |
20 | #endif /* not lint */ |
21 | ||
dc2a07ab | 22 | #include "parser.h" |
0173496c | 23 | #include "var.h" |
dc2a07ab EW |
24 | |
25 | /* | |
5119bdf8 | 26 | * unary $ $? + - ! ~ |
dc2a07ab EW |
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; | |
5119bdf8 EW |
39 | case T_DQ: |
40 | opname = "$?"; | |
41 | break; | |
dc2a07ab EW |
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: | |
dc2a07ab EW |
63 | break; |
64 | case V_STR: | |
65 | switch (op) { | |
66 | case T_MINUS: | |
67 | case T_NOT: | |
68 | case T_COMP: | |
5119bdf8 | 69 | p_error("%s: Numeric operand required.", opname); |
dc2a07ab EW |
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) { | |
5119bdf8 EW |
79 | case T_DOLLAR: |
80 | case T_DQ: | |
bb4a0c0b | 81 | if (v->v_type == V_NUM) { |
5119bdf8 EW |
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 { | |
bb4a0c0b EW |
89 | p_error("%d: No such argument.", v->v_num); |
90 | v->v_type = V_ERR; | |
bb4a0c0b | 91 | } |
bb4a0c0b | 92 | } else { |
5119bdf8 EW |
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); | |
bb4a0c0b | 102 | v->v_type = V_ERR; |
bb4a0c0b | 103 | } |
5119bdf8 | 104 | str_free(name); |
dc2a07ab | 105 | } |
5119bdf8 | 106 | if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) { |
bb4a0c0b EW |
107 | p_memerror(); |
108 | return -1; | |
dc2a07ab EW |
109 | } |
110 | break; | |
dc2a07ab EW |
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. | |
dc2a07ab EW |
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; | |
dc2a07ab | 135 | switch (token) { |
dc2a07ab | 136 | case T_NUM: |
dc2a07ab EW |
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: | |
dc2a07ab EW |
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: | |
dc2a07ab EW |
165 | return -1; |
166 | } | |
167 | while (token == T_LP) { | |
168 | char *cmd; | |
169 | ||
bb4a0c0b EW |
170 | if (p_convstr(v) < 0) |
171 | return -1; | |
172 | cmd = v->v_type == V_STR ? v->v_str : 0; | |
dc2a07ab | 173 | if (p_function(cmd, v, flag) < 0) { |
f8e2d916 EW |
174 | if (cmd) |
175 | str_free(cmd); | |
dc2a07ab EW |
176 | return -1; |
177 | } | |
f8e2d916 EW |
178 | if (cmd) |
179 | str_free(cmd); | |
dc2a07ab EW |
180 | } |
181 | return 0; | |
182 | } |