xref: /openbsd-src/usr.bin/rpcgen/rpc_util.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /*	$OpenBSD: rpc_util.c,v 1.15 2010/09/01 14:43:34 millert Exp $	*/
2 /*	$NetBSD: rpc_util.c,v 1.6 1995/08/29 23:05:57 cgd Exp $	*/
3 
4 /*
5  * Copyright (c) 2010, Oracle America, Inc.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above
14  *       copyright notice, this list of conditions and the following
15  *       disclaimer in the documentation and/or other materials
16  *       provided with the distribution.
17  *     * Neither the name of the "Oracle America, Inc." nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*
36  * rpc_util.c, Utility routines for the RPC protocol compiler
37  */
38 #include <sys/cdefs.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <unistd.h>
44 #include "rpc_scan.h"
45 #include "rpc_parse.h"
46 #include "rpc_util.h"
47 
48 #define ARGEXT "argument"
49 
50 static void printwhere(void);
51 
52 char curline[MAXLINESIZE];	/* current read line */
53 char *where = curline;		/* current point in line */
54 int linenum = 0;		/* current line number */
55 
56 char *infilename;		/* input filename */
57 
58 #define NFILES 7
59 char *outfiles[NFILES];		/* output file names */
60 int nfiles;
61 
62 FILE *fout;			/* file pointer of current output */
63 FILE *fin;			/* file pointer of current input */
64 
65 list *defined;			/* list of defined things */
66 
67 /*
68  * Reinitialize the world
69  */
70 void
71 reinitialize()
72 {
73 	memset(curline, 0, MAXLINESIZE);
74 	where = curline;
75 	linenum = 0;
76 	defined = NULL;
77 }
78 
79 /*
80  * string equality
81  */
82 int
83 streq(a, b)
84 	char *a;
85 	char *b;
86 {
87 	return (strcmp(a, b) == 0);
88 }
89 
90 /*
91  * find a value in a list
92  */
93 definition *
94 findval(lst, val, cmp)
95 	list *lst;
96 	char *val;
97 	int (*cmp) (definition *, char *);
98 {
99 
100 	for (; lst != NULL; lst = lst->next) {
101 		if ((*cmp) (lst->val, val)) {
102 			return (lst->val);
103 		}
104 	}
105 	return (NULL);
106 }
107 
108 /*
109  * store a value in a list
110  */
111 void
112 storeval(lstp, val)
113 	list **lstp;
114 	definition *val;
115 {
116 	list **l;
117 	list *lst;
118 
119 	for (l = lstp; *l != NULL; l = (list **) & (*l)->next)
120 		;
121 	lst = ALLOC(list);
122 	if (lst == NULL) {
123 		fprintf(stderr, "failed in alloc\n");
124 		exit(1);
125 	}
126 	lst->val = val;
127 	lst->next = NULL;
128 	*l = lst;
129 }
130 
131 static int
132 findit(definition *def, char *type)
133 {
134 	return (streq(def->def_name, type));
135 }
136 
137 static char *
138 fixit(char *type, char *orig)
139 {
140 	definition *def;
141 
142 	def = (definition *) FINDVAL(defined, type, findit);
143 	if (def == NULL || def->def_kind != DEF_TYPEDEF) {
144 		return (orig);
145 	}
146 	switch (def->def.ty.rel) {
147 	case REL_VECTOR:
148 		return (def->def.ty.old_type);
149 	case REL_ALIAS:
150 		return (fixit(def->def.ty.old_type, orig));
151 	default:
152 		return (orig);
153 	}
154 }
155 
156 char *
157 fixtype(type)
158 	char *type;
159 {
160 	return (fixit(type, type));
161 }
162 
163 char *
164 stringfix(type)
165 	char *type;
166 {
167 	if (streq(type, "string")) {
168 		return ("wrapstring");
169 	} else {
170 		return (type);
171 	}
172 }
173 
174 void
175 ptype(prefix, type, follow)
176 	char *prefix;
177 	char *type;
178 	int follow;
179 {
180 	if (prefix != NULL) {
181 		if (streq(prefix, "enum")) {
182 			fprintf(fout, "enum ");
183 		} else {
184 			fprintf(fout, "struct ");
185 		}
186 	}
187 	if (streq(type, "bool")) {
188 		fprintf(fout, "bool_t ");
189 	} else if (streq(type, "string")) {
190 		fprintf(fout, "char *");
191 	} else {
192 		fprintf(fout, "%s ", follow ? fixtype(type) : type);
193 	}
194 }
195 
196 static int
197 typedefed(definition *def, char *type)
198 {
199 	if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL)
200 		return (0);
201 	else
202 		return (streq(def->def_name, type));
203 }
204 
205 int
206 isvectordef(type, rel)
207 	char *type;
208 	relation rel;
209 {
210 	definition *def;
211 
212 	for (;;) {
213 		switch (rel) {
214 		case REL_VECTOR:
215 			return (!streq(type, "string"));
216 		case REL_ARRAY:
217 			return (0);
218 		case REL_POINTER:
219 			return (0);
220 		case REL_ALIAS:
221 			def = (definition *) FINDVAL(defined, type, typedefed);
222 			if (def == NULL)
223 				return (0);
224 			type = def->def.ty.old_type;
225 			rel = def->def.ty.rel;
226 		}
227 	}
228 }
229 
230 char *
231 locase(str)
232 	char *str;
233 {
234 	char c;
235 	static char buf[100];
236 	char *p = buf;
237 
238 	while ((c = *str++))
239 		*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
240 	*p = 0;
241 	return (buf);
242 }
243 
244 void
245 pvname_svc(pname, vnum)
246 	char *pname;
247 	char *vnum;
248 {
249 	fprintf(fout, "%s_%s_svc", locase(pname), vnum);
250 }
251 
252 void
253 pvname(pname, vnum)
254 	char *pname;
255 	char *vnum;
256 {
257 	fprintf(fout, "%s_%s", locase(pname), vnum);
258 }
259 
260 /*
261  * print a useful (?) error message, and then die
262  */
263 void
264 error(msg)
265 	char *msg;
266 {
267 	printwhere();
268 	fprintf(stderr, "%s, line %d: ", infilename, linenum);
269 	fprintf(stderr, "%s\n", msg);
270 	crash();
271 }
272 
273 /*
274  * Something went wrong, unlink any files that we may have created and then
275  * die.
276  */
277 void
278 crash()
279 {
280 	int i;
281 
282 	for (i = 0; i < nfiles; i++) {
283 		(void) unlink(outfiles[i]);
284 	}
285 	exit(1);
286 }
287 
288 void
289 record_open(file)
290 	char *file;
291 {
292 	if (nfiles < NFILES) {
293 		outfiles[nfiles++] = file;
294 	} else {
295 		fprintf(stderr, "too many files!\n");
296 		crash();
297 	}
298 }
299 
300 static char expectbuf[100];
301 static char *toktostr(tok_kind);
302 
303 /*
304  * error, token encountered was not the expected one
305  */
306 void
307 expected1(exp1)
308 	tok_kind exp1;
309 {
310 	snprintf(expectbuf, sizeof expectbuf, "expected '%s'",
311 	    toktostr(exp1));
312 	error(expectbuf);
313 }
314 
315 /*
316  * error, token encountered was not one of two expected ones
317  */
318 void
319 expected2(exp1, exp2)
320 	tok_kind exp1, exp2;
321 {
322 	snprintf(expectbuf, sizeof expectbuf, "expected '%s' or '%s'",
323 	    toktostr(exp1), toktostr(exp2));
324 	error(expectbuf);
325 }
326 
327 /*
328  * error, token encountered was not one of 3 expected ones
329  */
330 void
331 expected3(exp1, exp2, exp3)
332 	tok_kind exp1, exp2, exp3;
333 {
334 	snprintf(expectbuf, sizeof expectbuf, "expected '%s', '%s' or '%s'",
335 	    toktostr(exp1), toktostr(exp2), toktostr(exp3));
336 	error(expectbuf);
337 }
338 
339 void
340 tabify(f, tab)
341 	FILE *f;
342 	int tab;
343 {
344 	while (tab--) {
345 		(void) fputc('\t', f);
346 	}
347 }
348 
349 static token tokstrings[] = {
350 	{TOK_IDENT, "identifier"},
351 	{TOK_CONST, "const"},
352 	{TOK_RPAREN, ")"},
353 	{TOK_LPAREN, "("},
354 	{TOK_RBRACE, "}"},
355 	{TOK_LBRACE, "{"},
356 	{TOK_LBRACKET, "["},
357 	{TOK_RBRACKET, "]"},
358 	{TOK_STAR, "*"},
359 	{TOK_COMMA, ","},
360 	{TOK_EQUAL, "="},
361 	{TOK_COLON, ":"},
362 	{TOK_SEMICOLON, ";"},
363 	{TOK_UNION, "union"},
364 	{TOK_STRUCT, "struct"},
365 	{TOK_SWITCH, "switch"},
366 	{TOK_CASE, "case"},
367 	{TOK_DEFAULT, "default"},
368 	{TOK_ENUM, "enum"},
369 	{TOK_TYPEDEF, "typedef"},
370 	{TOK_INT, "int"},
371 	{TOK_SHORT, "short"},
372 	{TOK_LONG, "long"},
373 	{TOK_UNSIGNED, "unsigned"},
374 	{TOK_DOUBLE, "double"},
375 	{TOK_FLOAT, "float"},
376 	{TOK_CHAR, "char"},
377 	{TOK_STRING, "string"},
378 	{TOK_OPAQUE, "opaque"},
379 	{TOK_BOOL, "bool"},
380 	{TOK_VOID, "void"},
381 	{TOK_PROGRAM, "program"},
382 	{TOK_VERSION, "version"},
383 	{TOK_EOF, "??????"}
384 };
385 
386 static char *
387 toktostr(tok_kind kind)
388 {
389 	token *sp;
390 
391 	for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++)
392 		;
393 	return (sp->str);
394 }
395 
396 static void
397 printbuf(void)
398 {
399 	char c;
400 	int i;
401 	int cnt;
402 
403 #	define TABSIZE 4
404 
405 	for (i = 0; (c = curline[i]); i++) {
406 		if (c == '\t') {
407 			cnt = 8 - (i % TABSIZE);
408 			c = ' ';
409 		} else {
410 			cnt = 1;
411 		}
412 		while (cnt--) {
413 			(void) fputc(c, stderr);
414 		}
415 	}
416 }
417 
418 static void
419 printwhere()
420 {
421 	int i;
422 	char c;
423 	int cnt;
424 
425 	printbuf();
426 	for (i = 0; i < where - curline; i++) {
427 		c = curline[i];
428 		if (c == '\t') {
429 			cnt = 8 - (i % TABSIZE);
430 		} else {
431 			cnt = 1;
432 		}
433 		while (cnt--) {
434 			(void) fputc('^', stderr);
435 		}
436 	}
437 	(void) fputc('\n', stderr);
438 }
439 
440 char *
441 make_argname(pname, vname)
442 	char *pname;
443 	char *vname;
444 {
445 	char *name;
446 	int len = strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3;
447 
448 	name = (char *)malloc(len);
449 	if (!name) {
450 		fprintf(stderr, "failed in malloc\n");
451 		exit(1);
452 	}
453 	snprintf(name, len, "%s_%s_%s", locase(pname), vname, ARGEXT);
454 	return(name);
455 }
456 
457 bas_type *typ_list_h;
458 bas_type *typ_list_t;
459 
460 void
461 add_type(len, type)
462 	int len;
463 	char *type;
464 {
465 	bas_type *ptr;
466 
467 	if ((ptr = (bas_type *)malloc(sizeof(bas_type))) == (bas_type *)NULL) {
468 		fprintf(stderr, "failed in malloc\n");
469 		exit(1);
470 	}
471 
472 	ptr->name = type;
473 	ptr->length = len;
474 	ptr->next = NULL;
475 	if (typ_list_t == NULL) {
476 		typ_list_t = ptr;
477 		typ_list_h = ptr;
478 	} else {
479 		typ_list_t->next = ptr;
480 		typ_list_t = ptr;
481 	}
482 }
483 
484 bas_type *
485 find_type(type)
486 	char *type;
487 {
488 	bas_type * ptr;
489 
490 	ptr = typ_list_h;
491 
492 	while (ptr != NULL) {
493 		if (strcmp(ptr->name, type) == 0)
494 			return(ptr);
495 		else
496 			ptr = ptr->next;
497 	}
498 	return(NULL);
499 }
500 
501