xref: /freebsd/usr.bin/rpcgen/rpc_util.c (revision abd87254)
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  *
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  *
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  *
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  *
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  */
29 
30 /*
31  * rpc_util.c, Utility routines for the RPC protocol compiler
32  * Copyright (C) 1989, Sun Microsystems, Inc.
33  */
34 #include <err.h>
35 #include <ctype.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include "rpc_parse.h"
40 #include "rpc_scan.h"
41 #include "rpc_util.h"
42 
43 #define	ARGEXT "argument"
44 
45 char curline[MAXLINESIZE];	/* current read line */
46 char *where = curline;		/* current point in line */
47 int linenum = 0;		/* current line number */
48 
49 const char *infilename;		/* input filename */
50 
51 #define	NFILES   7
52 static const char *outfiles[NFILES]; /* output file names */
53 static int nfiles;
54 
55 FILE *fout;			/* file pointer of current output */
56 FILE *fin;			/* file pointer of current input */
57 
58 list *defined;			/* list of defined things */
59 
60 static void printwhere( void );
61 
62 /*
63  * Reinitialize the world
64  */
65 void
66 reinitialize(void)
67 {
68 	memset(curline, 0, MAXLINESIZE);
69 	where = curline;
70 	linenum = 0;
71 	defined = NULL;
72 }
73 
74 /*
75  * string equality
76  */
77 int
78 streq(const char *a, const char *b)
79 {
80 	return (strcmp(a, b) == 0);
81 }
82 
83 /*
84  * find a value in a list
85  */
86 definition *
87 findval(list *lst, const char *val, int (*cmp)(definition *, const char *))
88 {
89 	for (; lst != NULL; lst = lst->next) {
90 		if ((*cmp) (lst->val, val)) {
91 			return (lst->val);
92 		}
93 	}
94 	return (NULL);
95 }
96 
97 /*
98  * store a value in a list
99  */
100 void
101 storeval(list **lstp, definition *val)
102 {
103 	list **l;
104 	list *lst;
105 
106 	for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
107 	lst = XALLOC(list);
108 	lst->val = val;
109 	lst->next = NULL;
110 	*l = lst;
111 }
112 
113 static int
114 findit(definition *def, const char *type)
115 {
116 	return (streq(def->def_name, type));
117 }
118 
119 static const char *
120 fixit(const char *type, const char *orig)
121 {
122 	definition *def;
123 
124 	def = (definition *) FINDVAL(defined, type, findit);
125 	if (def == NULL || def->def_kind != DEF_TYPEDEF) {
126 		return (orig);
127 	}
128 	switch (def->def.ty.rel) {
129 	case REL_VECTOR:
130 		if (streq(def->def.ty.old_type, "opaque"))
131 			return ("char");
132 		else
133 			return (def->def.ty.old_type);
134 
135 	case REL_ALIAS:
136 		return (fixit(def->def.ty.old_type, orig));
137 	default:
138 		return (orig);
139 	}
140 }
141 
142 const char *
143 fixtype(const char *type)
144 {
145 	return (fixit(type, type));
146 }
147 
148 const char *
149 stringfix(const char *type)
150 {
151 	if (streq(type, "string")) {
152 		return ("wrapstring");
153 	} else {
154 		return (type);
155 	}
156 }
157 
158 void
159 ptype(const char *prefix, const char *type, int follow)
160 {
161 	if (prefix != NULL) {
162 		if (streq(prefix, "enum")) {
163 			f_print(fout, "enum ");
164 		} else {
165 			f_print(fout, "struct ");
166 		}
167 	}
168 	if (streq(type, "bool")) {
169 		f_print(fout, "bool_t ");
170 	} else if (streq(type, "string")) {
171 		f_print(fout, "char *");
172 	} else {
173 		f_print(fout, "%s ", follow ? fixtype(type) : type);
174 	}
175 }
176 
177 static int
178 typedefed(definition *def, const char *type)
179 {
180 	if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) {
181 		return (0);
182 	} else {
183 		return (streq(def->def_name, type));
184 	}
185 }
186 
187 int
188 isvectordef(const char *type, relation rel)
189 {
190 	definition *def;
191 
192 	for (;;) {
193 		switch (rel) {
194 		case REL_VECTOR:
195 			return (!streq(type, "string"));
196 		case REL_ARRAY:
197 			return (0);
198 		case REL_POINTER:
199 			return (0);
200 		case REL_ALIAS:
201 			def = (definition *) FINDVAL(defined, type, typedefed);
202 			if (def == NULL) {
203 				return (0);
204 			}
205 			type = def->def.ty.old_type;
206 			rel = def->def.ty.rel;
207 		}
208 	}
209 
210 	return (0);
211 }
212 
213 char *
214 locase(const char *str)
215 {
216 	char c;
217 	static char buf[100];
218 	char *p = buf;
219 
220 	while ( (c = *str++) ) {
221 		*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
222 	}
223 	*p = 0;
224 	return (buf);
225 }
226 
227 void
228 pvname_svc(const char *pname, const char *vnum)
229 {
230 	f_print(fout, "%s_%s_svc", locase(pname), vnum);
231 }
232 
233 void
234 pvname(const char *pname, const char *vnum)
235 {
236 	f_print(fout, "%s_%s", locase(pname), vnum);
237 }
238 
239 /*
240  * print a useful (?) error message, and then die
241  */
242 void
243 error(const char *msg)
244 {
245 	printwhere();
246 	warnx("%s, line %d: %s", infilename, linenum, msg);
247 	crash();
248 }
249 
250 /*
251  * Something went wrong, unlink any files that we may have created and then
252  * die.
253  */
254 void __dead2
255 crash(void)
256 {
257 	int i;
258 
259 	for (i = 0; i < nfiles; i++) {
260 		(void) unlink(outfiles[i]);
261 	}
262 	exit(1);
263 }
264 
265 void
266 record_open(const char *file)
267 {
268 	if (nfiles < NFILES) {
269 		outfiles[nfiles++] = file;
270 	} else {
271 		warnx("too many files");
272 		crash();
273 	}
274 }
275 
276 static char expectbuf[100];
277 static const char *toktostr(tok_kind kind);
278 
279 /*
280  * error, token encountered was not the expected one
281  */
282 void
283 expected1(tok_kind exp1)
284 {
285 	s_print(expectbuf, "expected '%s'",
286 		toktostr(exp1));
287 	error(expectbuf);
288 }
289 
290 /*
291  * error, token encountered was not one of two expected ones
292  */
293 void
294 expected2(tok_kind exp1, tok_kind exp2)
295 {
296 	s_print(expectbuf, "expected '%s' or '%s'",
297 		toktostr(exp1),
298 		toktostr(exp2));
299 	error(expectbuf);
300 }
301 
302 /*
303  * error, token encountered was not one of 3 expected ones
304  */
305 void
306 expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3)
307 {
308 	s_print(expectbuf, "expected '%s', '%s' or '%s'",
309 		toktostr(exp1),
310 		toktostr(exp2),
311 		toktostr(exp3));
312 	error(expectbuf);
313 }
314 
315 void
316 tabify(FILE *f, int tab)
317 {
318 	while (tab--) {
319 		(void) fputc('\t', f);
320 	}
321 }
322 
323 
324 static token tokstrings[] = {
325 			{TOK_IDENT, "identifier"},
326 			{TOK_CONST, "const"},
327 			{TOK_RPAREN, ")"},
328 			{TOK_LPAREN, "("},
329 			{TOK_RBRACE, "}"},
330 			{TOK_LBRACE, "{"},
331 			{TOK_LBRACKET, "["},
332 			{TOK_RBRACKET, "]"},
333 			{TOK_STAR, "*"},
334 			{TOK_COMMA, ","},
335 			{TOK_EQUAL, "="},
336 			{TOK_COLON, ":"},
337 			{TOK_SEMICOLON, ";"},
338 			{TOK_UNION, "union"},
339 			{TOK_STRUCT, "struct"},
340 			{TOK_SWITCH, "switch"},
341 			{TOK_CASE, "case"},
342 			{TOK_DEFAULT, "default"},
343 			{TOK_ENUM, "enum"},
344 			{TOK_TYPEDEF, "typedef"},
345 			{TOK_INT, "int"},
346 			{TOK_SHORT, "short"},
347 			{TOK_LONG, "long"},
348 			{TOK_UNSIGNED, "unsigned"},
349 			{TOK_DOUBLE, "double"},
350 			{TOK_FLOAT, "float"},
351 			{TOK_CHAR, "char"},
352 			{TOK_STRING, "string"},
353 			{TOK_OPAQUE, "opaque"},
354 			{TOK_BOOL, "bool"},
355 			{TOK_VOID, "void"},
356 			{TOK_PROGRAM, "program"},
357 			{TOK_VERSION, "version"},
358 			{TOK_EOF, "??????"}
359 };
360 
361 static const char *
362 toktostr(tok_kind kind)
363 {
364 	token *sp;
365 
366 	for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
367 	return (sp->str);
368 }
369 
370 static void
371 printbuf(void)
372 {
373 	char c;
374 	int i;
375 	int cnt;
376 
377 #	define TABSIZE 4
378 
379 	for (i = 0; (c = curline[i]); i++) {
380 		if (c == '\t') {
381 			cnt = 8 - (i % TABSIZE);
382 			c = ' ';
383 		} else {
384 			cnt = 1;
385 		}
386 		while (cnt--) {
387 			(void) fputc(c, stderr);
388 		}
389 	}
390 }
391 
392 static void
393 printwhere(void)
394 {
395 	int i;
396 	char c;
397 	int cnt;
398 
399 	printbuf();
400 	for (i = 0; i < where - curline; i++) {
401 		c = curline[i];
402 		if (c == '\t') {
403 			cnt = 8 - (i % TABSIZE);
404 		} else {
405 			cnt = 1;
406 		}
407 		while (cnt--) {
408 			(void) fputc('^', stderr);
409 		}
410 	}
411 	(void) fputc('\n', stderr);
412 }
413 
414 char *
415 make_argname(const char *pname, const char *vname)
416 {
417 	char *name;
418 
419 	name = xmalloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3);
420 	sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT);
421 	return (name);
422 }
423 
424 bas_type *typ_list_h;
425 bas_type *typ_list_t;
426 
427 void
428 add_type(int len, const char *type)
429 {
430 	bas_type *ptr;
431 
432 	ptr = XALLOC(bas_type);
433 
434 	ptr->name = type;
435 	ptr->length = len;
436 	ptr->next = NULL;
437 	if (typ_list_t == NULL)
438 	{
439 
440 		typ_list_t = ptr;
441 		typ_list_h = ptr;
442 	}
443 	else
444 	{
445 		typ_list_t->next = ptr;
446 		typ_list_t = ptr;
447 	}
448 }
449 
450 
451 bas_type *
452 find_type(const char *type)
453 {
454 	bas_type * ptr;
455 
456 	ptr = typ_list_h;
457 	while (ptr != NULL)
458 	{
459 		if (strcmp(ptr->name, type) == 0)
460 			return (ptr);
461 		else
462 			ptr = ptr->next;
463 	}
464 	return (NULL);
465 }
466 
467 void *
468 xmalloc(size_t size)
469 {
470 	void *p;
471 
472 	if ((p = malloc(size)) == NULL) {
473 		warnx("malloc failed");
474 		crash();
475 	}
476 	return (p);
477 }
478 
479 void *
480 xrealloc(void *ptr, size_t size)
481 {
482 	void *p;
483 
484 	if ((p = realloc(ptr, size)) == NULL) {
485 		warnx("realloc failed");
486 		crash();
487 	}
488 	return (p);
489 }
490 
491 char *
492 xstrdup(const char *str)
493 {
494 	char *p;
495 
496 	if ((p = strdup(str)) == NULL) {
497 		warnx("strdup failed");
498 		crash();
499 	}
500 	return (p);
501 }
502