1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include "defs.h"
6 #include "externs.h"
7 #include "protos.h"
8
9 struct t_func *func_tbl[256];
10 struct t_func *func_ptr;
11 char func_line[128];
12 char func_arg[8][10][80];
13 int func_idx;
14
15
16 /* ----
17 * do_func()
18 * ----
19 * .func pseudo
20 */
21
22 void
do_func(int * ip)23 do_func(int *ip)
24 {
25 if (pass == LAST_PASS)
26 println();
27 else {
28 /* error checking */
29 if (lablptr == NULL) {
30 error("No name for this function!");
31 return;
32 }
33 if (lablptr->refcnt) {
34 switch (lablptr->type) {
35 case MACRO:
36 fatal_error("Symbol already used by a macro!");
37
38 case FUNC:
39 fatal_error("Function already defined!");
40 return;
41
42 default:
43 fatal_error("Symbol already used by a label!");
44 return;
45 }
46 }
47
48 /* install this new function in the hash table */
49 if (!func_install(*ip))
50 return;
51 }
52 }
53
54 /* search a function */
55
56 int
func_look(void)57 func_look(void)
58 {
59 int hash;
60
61 /* search the function in the hash table */
62 hash = symhash();
63 func_ptr = func_tbl[hash];
64 while (func_ptr) {
65 if (!strcmp(&symbol[1], func_ptr->name))
66 break;
67 func_ptr = func_ptr->next;
68 }
69
70 /* ok */
71 if (func_ptr)
72 return (1);
73
74 /* didn't find a function with this name */
75 return (0);
76 }
77
78 /* install a function in the hash table */
79
80 int
func_install(int ip)81 func_install(int ip)
82 {
83 int hash;
84
85 /* mark the function name as reserved */
86 lablptr->type = FUNC;
87
88 /* check function name syntax */
89 if (strchr(&symbol[1], '.')) {
90 error("Invalid function name!");
91 return (0);
92 }
93
94 /* extract function body */
95 if (func_extract(ip) == -1)
96 return (0);
97
98 /* allocate a new func struct */
99 if ((func_ptr = (void *)malloc(sizeof(struct t_func))) == NULL) {
100 error("Out of memory!");
101 return (0);
102 }
103
104 /* initialize it */
105 strcpy(func_ptr->name, &symbol[1]);
106 strcpy(func_ptr->line, func_line);
107 hash = symhash();
108 func_ptr->next = func_tbl[hash];
109 func_tbl[hash] = func_ptr;
110
111 /* ok */
112 return (1);
113 }
114
115 /* extract function body */
116
117 int
func_extract(int ip)118 func_extract(int ip)
119 {
120 char *ptr;
121 char c;
122 int i, arg, max_arg;
123 int end;
124
125 /* skip spaces */
126 while (isspace(prlnbuf[ip]))
127 ip++;
128
129 /* get function body */
130 ptr = func_line;
131 max_arg = 0;
132 end = 0;
133 i = 0;
134
135 while (!end) {
136 c = prlnbuf[ip++];
137 switch (c) {
138 /* end of line */
139 case ';':
140 case '\0':
141 *ptr++ = '\0';
142 end = 1;
143 break;
144
145 /* function arg */
146 case '\\':
147 *ptr++ = c;
148 i++;
149 c = prlnbuf[ip++];
150 if ((c < '1') || (c > '9')) {
151 error("Invalid function argument!");
152 return (-1);
153 }
154 arg = c - '1';
155 if (max_arg < arg)
156 max_arg = arg;
157
158 /* other */
159 default:
160 *ptr++ = c;
161 i++;
162 if (i == 127) {
163 error("Function line too long!");
164 return (-1);
165 }
166 break;
167 }
168 }
169
170 /* return the number of args */
171 return (max_arg);
172 }
173
174 /* extract function args */
175
176 int
func_getargs(void)177 func_getargs(void)
178 {
179 char c, *ptr, *line;
180 int arg, level, space, flag;
181 int i, x;
182
183 /* can not nest too much macros */
184 if (func_idx == 7) {
185 error("Too many nested function calls!");
186 return (0);
187 }
188
189 /* skip spaces */
190 while (isspace(*expr))
191 expr++;
192
193 /* function args must be enclosed in parenthesis */
194 if (*expr++ != '(')
195 return (0);
196
197 /* initialize args */
198 line = NULL;
199 ptr = func_arg[func_idx][0];
200 arg = 0;
201
202 for (i = 0; i < 9; i++)
203 func_arg[func_idx][i][0] = '\0';
204
205 /* get args one by one */
206 for (;;) {
207 /* skip spaces */
208 while (isspace(*expr))
209 expr++;
210
211 c = *expr++;
212 switch (c) {
213 /* empty arg */
214 case ',':
215 arg++;
216 ptr = func_arg[func_idx][arg];
217 if (arg == 9) {
218 error("Too many arguments for a function!");
219 return (0);
220 }
221 break;
222
223 /* end of line */
224 case ';':
225 case '\0':
226 error("Syntax error in function call!");
227 return (0);
228
229 /* end of function */
230 case ')':
231 return (1);
232
233 /* arg */
234 default:
235 space = 0;
236 level = 0;
237 flag = 0;
238 i = 0;
239 x = 0;
240 for (;;) {
241 if (c == '\0') {
242 if (flag == 0)
243 break;
244 else {
245 flag = 0;
246 c = *expr++;
247 continue;
248 }
249 }
250 else if (c == ';') {
251 break;
252 }
253 else if (c == ',') {
254 if (level == 0)
255 break;
256 }
257 else if (c == '\\') {
258 if (func_idx == 0) {
259 error("Syntax error!");
260 return (0);
261 }
262 c = *expr++;
263 if (c < '1' || c > '9') {
264 error("Invalid function argument index!");
265 return (0);
266 }
267 line = func_arg[func_idx - 1][c - '1'];
268 flag = 1;
269 c = *line++;
270 continue;
271 }
272 else if (c == '(') {
273 level++;
274 }
275 else if (c == ')') {
276 if (level == 0)
277 break;
278 level--;
279 }
280 if (space) {
281 if (c != ' ') {
282 while (i < x)
283 ptr[i++] = ' ';
284 ptr[i++] = c;
285 space = 0;
286 }
287 }
288 else if (c == ' ') {
289 space = 1;
290 }
291 else {
292 ptr[i++] = c;
293 }
294 if (i == 80) {
295 error("Invalid function argument length!");
296 return (0);
297 }
298 x++;
299 if (flag)
300 c = *line++;
301 else
302 c = *expr++;
303 }
304 ptr[i] = '\0';
305 expr--;
306 break;
307 }
308 }
309 }
310
311