xref: /openbsd/usr.bin/rpcgen/rpc_util.c (revision cfff592f)
1 /*	$OpenBSD: rpc_util.c,v 1.17 2015/08/20 22:32:41 deraadt 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 <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <unistd.h>
43 #include "rpc_scan.h"
44 #include "rpc_parse.h"
45 #include "rpc_util.h"
46 
47 #define ARGEXT "argument"
48 
49 static void printwhere(void);
50 
51 char curline[MAXLINESIZE];	/* current read line */
52 char *where = curline;		/* current point in line */
53 int linenum = 0;		/* current line number */
54 
55 char *infilename;		/* input filename */
56 
57 #define NFILES 7
58 char *outfiles[NFILES];		/* output file names */
59 int nfiles;
60 
61 FILE *fout;			/* file pointer of current output */
62 FILE *fin;			/* file pointer of current input */
63 
64 list *defined;			/* list of defined things */
65 
66 /*
67  * Reinitialize the world
68  */
69 void
reinitialize()70 reinitialize()
71 {
72 	memset(curline, 0, MAXLINESIZE);
73 	where = curline;
74 	linenum = 0;
75 	defined = NULL;
76 }
77 
78 /*
79  * string equality
80  */
81 int
streq(a,b)82 streq(a, b)
83 	char *a;
84 	char *b;
85 {
86 	return (strcmp(a, b) == 0);
87 }
88 
89 /*
90  * find a value in a list
91  */
92 definition *
findval(lst,val,cmp)93 findval(lst, val, cmp)
94 	list *lst;
95 	char *val;
96 	int (*cmp) (definition *, char *);
97 {
98 
99 	for (; lst != NULL; lst = lst->next) {
100 		if ((*cmp) (lst->val, val)) {
101 			return (lst->val);
102 		}
103 	}
104 	return (NULL);
105 }
106 
107 /*
108  * store a value in a list
109  */
110 void
storeval(lstp,val)111 storeval(lstp, val)
112 	list **lstp;
113 	definition *val;
114 {
115 	list **l;
116 	list *lst;
117 
118 	for (l = lstp; *l != NULL; l = (list **) & (*l)->next)
119 		;
120 	lst = malloc(sizeof(list));
121 	if (lst == NULL) {
122 		fprintf(stderr, "failed in alloc\n");
123 		exit(1);
124 	}
125 	lst->val = val;
126 	lst->next = NULL;
127 	*l = lst;
128 }
129 
130 static int
findit(definition * def,char * type)131 findit(definition *def, char *type)
132 {
133 	return (streq(def->def_name, type));
134 }
135 
136 static char *
fixit(char * type,char * orig)137 fixit(char *type, char *orig)
138 {
139 	definition *def;
140 
141 	def = (definition *) FINDVAL(defined, type, findit);
142 	if (def == NULL || def->def_kind != DEF_TYPEDEF) {
143 		return (orig);
144 	}
145 	switch (def->def.ty.rel) {
146 	case REL_VECTOR:
147 		return (def->def.ty.old_type);
148 	case REL_ALIAS:
149 		return (fixit(def->def.ty.old_type, orig));
150 	default:
151 		return (orig);
152 	}
153 }
154 
155 char *
fixtype(type)156 fixtype(type)
157 	char *type;
158 {
159 	return (fixit(type, type));
160 }
161 
162 char *
stringfix(type)163 stringfix(type)
164 	char *type;
165 {
166 	if (streq(type, "string")) {
167 		return ("wrapstring");
168 	} else {
169 		return (type);
170 	}
171 }
172 
173 void
ptype(prefix,type,follow)174 ptype(prefix, type, follow)
175 	char *prefix;
176 	char *type;
177 	int follow;
178 {
179 	if (prefix != NULL) {
180 		if (streq(prefix, "enum")) {
181 			fprintf(fout, "enum ");
182 		} else {
183 			fprintf(fout, "struct ");
184 		}
185 	}
186 	if (streq(type, "bool")) {
187 		fprintf(fout, "bool_t ");
188 	} else if (streq(type, "string")) {
189 		fprintf(fout, "char *");
190 	} else {
191 		fprintf(fout, "%s ", follow ? fixtype(type) : type);
192 	}
193 }
194 
195 static int
typedefed(definition * def,char * type)196 typedefed(definition *def, 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 int
isvectordef(type,rel)205 isvectordef(type, rel)
206 	char *type;
207 	relation rel;
208 {
209 	definition *def;
210 
211 	for (;;) {
212 		switch (rel) {
213 		case REL_VECTOR:
214 			return (!streq(type, "string"));
215 		case REL_ARRAY:
216 			return (0);
217 		case REL_POINTER:
218 			return (0);
219 		case REL_ALIAS:
220 			def = (definition *) FINDVAL(defined, type, typedefed);
221 			if (def == NULL)
222 				return (0);
223 			type = def->def.ty.old_type;
224 			rel = def->def.ty.rel;
225 		}
226 	}
227 }
228 
229 char *
locase(str)230 locase(str)
231 	char *str;
232 {
233 	char c;
234 	static char buf[100];
235 	char *p = buf;
236 
237 	while ((c = *str++))
238 		*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
239 	*p = 0;
240 	return (buf);
241 }
242 
243 void
pvname_svc(pname,vnum)244 pvname_svc(pname, vnum)
245 	char *pname;
246 	char *vnum;
247 {
248 	fprintf(fout, "%s_%s_svc", locase(pname), vnum);
249 }
250 
251 void
pvname(pname,vnum)252 pvname(pname, vnum)
253 	char *pname;
254 	char *vnum;
255 {
256 	fprintf(fout, "%s_%s", locase(pname), vnum);
257 }
258 
259 /*
260  * print a useful (?) error message, and then die
261  */
262 void
error(msg)263 error(msg)
264 	char *msg;
265 {
266 	printwhere();
267 	fprintf(stderr, "%s, line %d: ", infilename, linenum);
268 	fprintf(stderr, "%s\n", msg);
269 	crash();
270 }
271 
272 /*
273  * Something went wrong, unlink any files that we may have created and then
274  * die.
275  */
276 void
crash()277 crash()
278 {
279 	int i;
280 
281 	for (i = 0; i < nfiles; i++) {
282 		(void) unlink(outfiles[i]);
283 	}
284 	exit(1);
285 }
286 
287 void
record_open(file)288 record_open(file)
289 	char *file;
290 {
291 	if (nfiles < NFILES) {
292 		outfiles[nfiles++] = file;
293 	} else {
294 		fprintf(stderr, "too many files!\n");
295 		crash();
296 	}
297 }
298 
299 static char expectbuf[100];
300 static char *toktostr(tok_kind);
301 
302 /*
303  * error, token encountered was not the expected one
304  */
305 void
expected1(exp1)306 expected1(exp1)
307 	tok_kind exp1;
308 {
309 	snprintf(expectbuf, sizeof expectbuf, "expected '%s'",
310 	    toktostr(exp1));
311 	error(expectbuf);
312 }
313 
314 /*
315  * error, token encountered was not one of two expected ones
316  */
317 void
expected2(exp1,exp2)318 expected2(exp1, exp2)
319 	tok_kind exp1, exp2;
320 {
321 	snprintf(expectbuf, sizeof expectbuf, "expected '%s' or '%s'",
322 	    toktostr(exp1), toktostr(exp2));
323 	error(expectbuf);
324 }
325 
326 /*
327  * error, token encountered was not one of 3 expected ones
328  */
329 void
expected3(exp1,exp2,exp3)330 expected3(exp1, exp2, exp3)
331 	tok_kind exp1, exp2, exp3;
332 {
333 	snprintf(expectbuf, sizeof expectbuf, "expected '%s', '%s' or '%s'",
334 	    toktostr(exp1), toktostr(exp2), toktostr(exp3));
335 	error(expectbuf);
336 }
337 
338 void
tabify(f,tab)339 tabify(f, tab)
340 	FILE *f;
341 	int tab;
342 {
343 	while (tab--) {
344 		(void) fputc('\t', f);
345 	}
346 }
347 
348 static token tokstrings[] = {
349 	{TOK_IDENT, "identifier"},
350 	{TOK_CONST, "const"},
351 	{TOK_RPAREN, ")"},
352 	{TOK_LPAREN, "("},
353 	{TOK_RBRACE, "}"},
354 	{TOK_LBRACE, "{"},
355 	{TOK_LBRACKET, "["},
356 	{TOK_RBRACKET, "]"},
357 	{TOK_STAR, "*"},
358 	{TOK_COMMA, ","},
359 	{TOK_EQUAL, "="},
360 	{TOK_COLON, ":"},
361 	{TOK_SEMICOLON, ";"},
362 	{TOK_UNION, "union"},
363 	{TOK_STRUCT, "struct"},
364 	{TOK_SWITCH, "switch"},
365 	{TOK_CASE, "case"},
366 	{TOK_DEFAULT, "default"},
367 	{TOK_ENUM, "enum"},
368 	{TOK_TYPEDEF, "typedef"},
369 	{TOK_INT, "int"},
370 	{TOK_SHORT, "short"},
371 	{TOK_LONG, "long"},
372 	{TOK_UNSIGNED, "unsigned"},
373 	{TOK_DOUBLE, "double"},
374 	{TOK_FLOAT, "float"},
375 	{TOK_CHAR, "char"},
376 	{TOK_STRING, "string"},
377 	{TOK_OPAQUE, "opaque"},
378 	{TOK_BOOL, "bool"},
379 	{TOK_VOID, "void"},
380 	{TOK_PROGRAM, "program"},
381 	{TOK_VERSION, "version"},
382 	{TOK_EOF, "??????"}
383 };
384 
385 static char *
toktostr(tok_kind kind)386 toktostr(tok_kind kind)
387 {
388 	token *sp;
389 
390 	for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++)
391 		;
392 	return (sp->str);
393 }
394 
395 static void
printbuf(void)396 printbuf(void)
397 {
398 	char c;
399 	int i;
400 	int cnt;
401 
402 #	define TABSIZE 4
403 
404 	for (i = 0; (c = curline[i]); i++) {
405 		if (c == '\t') {
406 			cnt = 8 - (i % TABSIZE);
407 			c = ' ';
408 		} else {
409 			cnt = 1;
410 		}
411 		while (cnt--) {
412 			(void) fputc(c, stderr);
413 		}
414 	}
415 }
416 
417 static void
printwhere()418 printwhere()
419 {
420 	int i;
421 	char c;
422 	int cnt;
423 
424 	printbuf();
425 	for (i = 0; i < where - curline; i++) {
426 		c = curline[i];
427 		if (c == '\t') {
428 			cnt = 8 - (i % TABSIZE);
429 		} else {
430 			cnt = 1;
431 		}
432 		while (cnt--) {
433 			(void) fputc('^', stderr);
434 		}
435 	}
436 	(void) fputc('\n', stderr);
437 }
438 
439 char *
make_argname(pname,vname)440 make_argname(pname, vname)
441 	char *pname;
442 	char *vname;
443 {
444 	char *name;
445 	int len = strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3;
446 
447 	name = malloc(len);
448 	if (!name) {
449 		fprintf(stderr, "failed in malloc\n");
450 		exit(1);
451 	}
452 	snprintf(name, len, "%s_%s_%s", locase(pname), vname, ARGEXT);
453 	return(name);
454 }
455 
456 bas_type *typ_list_h;
457 bas_type *typ_list_t;
458 
459 void
add_type(len,type)460 add_type(len, type)
461 	int len;
462 	char *type;
463 {
464 	bas_type *ptr;
465 
466 	if ((ptr = malloc(sizeof(bas_type))) == (bas_type *)NULL) {
467 		fprintf(stderr, "failed in malloc\n");
468 		exit(1);
469 	}
470 
471 	ptr->name = type;
472 	ptr->length = len;
473 	ptr->next = NULL;
474 	if (typ_list_t == NULL) {
475 		typ_list_t = ptr;
476 		typ_list_h = ptr;
477 	} else {
478 		typ_list_t->next = ptr;
479 		typ_list_t = ptr;
480 	}
481 }
482 
483 bas_type *
find_type(type)484 find_type(type)
485 	char *type;
486 {
487 	bas_type * ptr;
488 
489 	ptr = typ_list_h;
490 
491 	while (ptr != NULL) {
492 		if (strcmp(ptr->name, type) == 0)
493 			return(ptr);
494 		else
495 			ptr = ptr->next;
496 	}
497 	return(NULL);
498 }
499 
500