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