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