Commit | Line | Data |
---|---|---|
60de5df9 | 1 | /* |
46e9ea25 KB |
2 | * Copyright (c) 1983 Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
3dd3a9e5 KB |
5 | * This code is derived from software contributed to Berkeley by |
6 | * Edward Wang at The University of California, Berkeley. | |
7 | * | |
87f529ec | 8 | * %sccs.include.redist.c% |
60de5df9 EW |
9 | */ |
10 | ||
46e9ea25 | 11 | #ifndef lint |
3dd3a9e5 | 12 | static char sccsid[] = "@(#)parser5.c 3.13 (Berkeley) %G%"; |
46e9ea25 KB |
13 | #endif /* not lint */ |
14 | ||
dc2a07ab | 15 | #include "parser.h" |
0173496c | 16 | #include "var.h" |
dc2a07ab EW |
17 | |
18 | /* | |
5119bdf8 | 19 | * unary $ $? + - ! ~ |
dc2a07ab EW |
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; | |
5119bdf8 EW |
32 | case T_DQ: |
33 | opname = "$?"; | |
34 | break; | |
dc2a07ab EW |
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: | |
dc2a07ab EW |
56 | break; |
57 | case V_STR: | |
58 | switch (op) { | |
59 | case T_MINUS: | |
60 | case T_NOT: | |
61 | case T_COMP: | |
5119bdf8 | 62 | p_error("%s: Numeric operand required.", opname); |
dc2a07ab EW |
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) { | |
5119bdf8 EW |
72 | case T_DOLLAR: |
73 | case T_DQ: | |
bb4a0c0b | 74 | if (v->v_type == V_NUM) { |
5119bdf8 EW |
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 { | |
bb4a0c0b EW |
82 | p_error("%d: No such argument.", v->v_num); |
83 | v->v_type = V_ERR; | |
bb4a0c0b | 84 | } |
bb4a0c0b | 85 | } else { |
5119bdf8 EW |
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); | |
bb4a0c0b | 95 | v->v_type = V_ERR; |
bb4a0c0b | 96 | } |
5119bdf8 | 97 | str_free(name); |
dc2a07ab | 98 | } |
5119bdf8 | 99 | if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) { |
bb4a0c0b EW |
100 | p_memerror(); |
101 | return -1; | |
dc2a07ab EW |
102 | } |
103 | break; | |
dc2a07ab EW |
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. | |
dc2a07ab EW |
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; | |
dc2a07ab | 128 | switch (token) { |
dc2a07ab | 129 | case T_NUM: |
dc2a07ab EW |
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: | |
dc2a07ab EW |
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: | |
dc2a07ab EW |
158 | return -1; |
159 | } | |
160 | while (token == T_LP) { | |
161 | char *cmd; | |
162 | ||
bb4a0c0b EW |
163 | if (p_convstr(v) < 0) |
164 | return -1; | |
165 | cmd = v->v_type == V_STR ? v->v_str : 0; | |
dc2a07ab | 166 | if (p_function(cmd, v, flag) < 0) { |
f8e2d916 EW |
167 | if (cmd) |
168 | str_free(cmd); | |
dc2a07ab EW |
169 | return -1; |
170 | } | |
f8e2d916 EW |
171 | if (cmd) |
172 | str_free(cmd); | |
dc2a07ab EW |
173 | } |
174 | return 0; | |
175 | } |