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
45char curline[MAXLINESIZE];	/* current read line */
46char *where = curline;		/* current point in line */
47int linenum = 0;		/* current line number */
48
49const char *infilename;		/* input filename */
50
51#define	NFILES   7
52static const char *outfiles[NFILES]; /* output file names */
53static int nfiles;
54
55FILE *fout;			/* file pointer of current output */
56FILE *fin;			/* file pointer of current input */
57
58list *defined;			/* list of defined things */
59
60static void printwhere( void );
61
62/*
63 * Reinitialize the world
64 */
65void
66reinitialize(void)
67{
68	memset(curline, 0, MAXLINESIZE);
69	where = curline;
70	linenum = 0;
71	defined = NULL;
72}
73
74/*
75 * string equality
76 */
77int
78streq(const char *a, const char *b)
79{
80	return (strcmp(a, b) == 0);
81}
82
83/*
84 * find a value in a list
85 */
86definition *
87findval(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 */
100void
101storeval(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
113static int
114findit(definition *def, const char *type)
115{
116	return (streq(def->def_name, type));
117}
118
119static const char *
120fixit(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
142const char *
143fixtype(const char *type)
144{
145	return (fixit(type, type));
146}
147
148const char *
149stringfix(const char *type)
150{
151	if (streq(type, "string")) {
152		return ("wrapstring");
153	} else {
154		return (type);
155	}
156}
157
158void
159ptype(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
177static int
178typedefed(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
187int
188isvectordef(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
213char *
214locase(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
227void
228pvname_svc(const char *pname, const char *vnum)
229{
230	f_print(fout, "%s_%s_svc", locase(pname), vnum);
231}
232
233void
234pvname(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 */
242void
243error(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 */
254void __dead2
255crash(void)
256{
257	int i;
258
259	for (i = 0; i < nfiles; i++) {
260		(void) unlink(outfiles[i]);
261	}
262	exit(1);
263}
264
265void
266record_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
276static char expectbuf[100];
277static const char *toktostr(tok_kind kind);
278
279/*
280 * error, token encountered was not the expected one
281 */
282void
283expected1(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 */
293void
294expected2(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 */
305void
306expected3(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
315void
316tabify(FILE *f, int tab)
317{
318	while (tab--) {
319		(void) fputc('\t', f);
320	}
321}
322
323
324static 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
361static const char *
362toktostr(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
370static void
371printbuf(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
392static void
393printwhere(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
414char *
415make_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
424bas_type *typ_list_h;
425bas_type *typ_list_t;
426
427void
428add_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
451bas_type *
452find_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
467void *
468xmalloc(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
479void *
480xrealloc(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
491char *
492xstrdup(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