xref: /illumos-gate/usr/src/cmd/rpcgen/rpc_util.c (revision 683007910b81ed9ff942db7c464d1b6df524048a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 /*
30  * University Copyright- Copyright (c) 1982, 1986, 1988
31  * The Regents of the University of California
32  * All Rights Reserved
33  *
34  * University Acknowledgment- Portions of this document are derived from
35  * software developed by the University of California, Berkeley, and its
36  * contributors.
37  */
38 
39 #pragma ident	"%Z%%M%	%I%	%E% SMI"
40 
41 /*
42  * rpc_util.c, Utility routines for the RPC protocol compiler
43  */
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <ctype.h>
48 #include <string.h>
49 #include "rpc_scan.h"
50 #include "rpc_parse.h"
51 #include "rpc_util.h"
52 
53 extern void crash(void);
54 
55 static void printwhere(void);
56 
57 #define	ARGEXT "argument"
58 
59 char curline[MAXLINESIZE];	/* current read line */
60 char *where = curline;		/* current point in line */
61 int linenum = 0;		/* current line number */
62 
63 char *infilename;		/* input filename */
64 
65 #define	NFILES   15
66 char *outfiles[NFILES];		/* output file names */
67 int nfiles;
68 
69 FILE *fout;			/* file pointer of current output */
70 FILE *fin;			/* file pointer of current input */
71 
72 list *defined;			/* list of defined things */
73 
74 /*
75  * Reinitialize the world
76  */
77 void
78 reinitialize(void)
79 {
80 	(void) memset(curline, 0, MAXLINESIZE);
81 	where = curline;
82 	linenum = 0;
83 	defined = NULL;
84 }
85 
86 /*
87  * string equality
88  */
89 int
90 streq(char *a, char *b)
91 {
92 	return (strcmp(a, b) == 0);
93 }
94 
95 /*
96  * find a value in a list
97  */
98 definition *
99 findval(list *lst, char *val, int (*cmp)())
100 {
101 	for (; lst != NULL; lst = lst->next) {
102 		if ((*cmp) (lst->val, val))
103 			return (lst->val);
104 	}
105 	return (NULL);
106 }
107 
108 /*
109  * store a value in a list
110  */
111 void
112 storeval(list **lstp, definition *val)
113 {
114 	list **l;
115 	list *lst;
116 
117 	for (l = lstp; *l != NULL; l = (list **)&(*l)->next);
118 	lst = calloc(1, sizeof (list));
119 	lst->val = val;
120 	lst->next = NULL;
121 	*l = lst;
122 }
123 
124 static int
125 findit(definition *def, char *type)
126 {
127 	return (streq(def->def_name, type));
128 }
129 
130 static char *
131 fixit(char *type, char *orig)
132 {
133 	definition *def;
134 
135 	def = (definition *)FINDVAL(defined, type, findit);
136 	if (def == NULL || def->def_kind != DEF_TYPEDEF)
137 		return (orig);
138 	switch (def->def.ty.rel) {
139 	case REL_VECTOR:
140 		if (streq(def->def.ty.old_type, "opaque"))
141 			return ("char");
142 		return (def->def.ty.old_type);
143 
144 	case REL_ALIAS:
145 		return (fixit(def->def.ty.old_type, orig));
146 	default:
147 		return (orig);
148 	}
149 }
150 
151 char *
152 fixtype(char *type)
153 {
154 	return (fixit(type, type));
155 }
156 
157 char *
158 stringfix(char *type)
159 {
160 	if (streq(type, "string"))
161 		return ("wrapstring");
162 	return (type);
163 }
164 
165 void
166 ptype(char *prefix, char *type, int follow)
167 {
168 	if (prefix != NULL) {
169 		if (streq(prefix, "enum")) {
170 			f_print(fout, "enum ");
171 		} else {
172 			f_print(fout, "struct ");
173 		}
174 	}
175 	if (streq(type, "bool")) {
176 		f_print(fout, "bool_t ");
177 	} else if (streq(type, "string")) {
178 		f_print(fout, "char *");
179 	} else if (streq(type, "oneway")) {
180 		f_print(fout, "void ");
181 	} else {
182 		f_print(fout, "%s ", follow ? fixtype(type) : type);
183 	}
184 }
185 
186 static int
187 typedefed(definition *def, char *type)
188 {
189 	if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL)
190 		return (0);
191 	return (streq(def->def_name, type));
192 }
193 
194 int
195 isvectordef(char *type, relation rel)
196 {
197 	definition *def;
198 
199 	for (;;) {
200 		switch (rel) {
201 		case REL_VECTOR:
202 			return (!streq(type, "string"));
203 		case REL_ARRAY:
204 			return (0);
205 		case REL_POINTER:
206 			return (0);
207 		case REL_ALIAS:
208 			def = (definition *)FINDVAL(defined, type, typedefed);
209 			if (def == NULL)
210 				return (0);
211 			type = def->def.ty.old_type;
212 			rel = def->def.ty.rel;
213 		}
214 	}
215 }
216 
217 char *
218 locase(char *str)
219 {
220 	char c;
221 	static char buf[100];
222 	char *p = buf;
223 
224 	while (c = *str++)
225 		*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
226 	*p = 0;
227 	return (buf);
228 }
229 
230 void
231 pvname_svc(char *pname, char *vnum)
232 {
233 	f_print(fout, "%s_%s_svc", locase(pname), vnum);
234 }
235 
236 void
237 pvname(char *pname, char *vnum)
238 {
239 	f_print(fout, "%s_%s", locase(pname), vnum);
240 }
241 
242 /*
243  * print a useful (?) error message, and then die
244  */
245 void
246 error(char *msg)
247 {
248 	printwhere();
249 	f_print(stderr, "%s, line %d: ", infilename, linenum);
250 	f_print(stderr, "%s\n", msg);
251 	crash();
252 }
253 
254 /*
255  * Something went wrong, unlink any files that we may have created and then
256  * die.
257  */
258 void
259 crash(void)
260 {
261 	int i;
262 
263 	for (i = 0; i < nfiles; i++)
264 		(void) unlink(outfiles[i]);
265 	exit(1);
266 }
267 
268 void
269 record_open(char *file)
270 {
271 	if (nfiles < NFILES) {
272 		outfiles[nfiles++] = file;
273 		return;
274 	}
275 	f_print(stderr, "too many files!\n");
276 	crash();
277 }
278 
279 static char expectbuf[100];
280 static char *toktostr();
281 
282 /*
283  * error, token encountered was not the expected one
284  */
285 void
286 expected1(tok_kind exp1)
287 {
288 	(void) snprintf(expectbuf,
289 		sizeof (expectbuf), "expected '%s'", toktostr(exp1));
290 	error(expectbuf);
291 }
292 
293 /*
294  * error, token encountered was not one of two expected ones
295  */
296 void
297 expected2(tok_kind exp1, tok_kind exp2)
298 {
299 	(void) snprintf(expectbuf,
300 		sizeof (expectbuf), "expected '%s' or '%s'", toktostr(exp1),
301 		toktostr(exp2));
302 	error(expectbuf);
303 }
304 
305 /*
306  * error, token encountered was not one of 3 expected ones
307  */
308 void
309 expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3)
310 {
311 	(void) snprintf(expectbuf,
312 		sizeof (expectbuf), "expected '%s', '%s' or '%s'",
313 		toktostr(exp1), toktostr(exp2), toktostr(exp3));
314 	error(expectbuf);
315 }
316 
317 void
318 tabify(FILE *f, int tab)
319 {
320 	while (tab--)
321 		(void) fputc('\t', f);
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 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]) != '\0'; 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 static void
392 printwhere(void)
393 {
394 	int i;
395 	char c;
396 	int cnt;
397 
398 	printbuf();
399 	for (i = 0; i < where - curline; i++) {
400 		c = curline[i];
401 		if (c == '\t') {
402 			cnt = 8 - (i % TABSIZE);
403 		} else {
404 			cnt = 1;
405 		}
406 		while (cnt--)
407 			(void) fputc('^', stderr);
408 	}
409 	(void) fputc('\n', stderr);
410 }
411 
412 char *
413 make_argname(char *pname, char *vname)
414 {
415 	char *name;
416 	size_t nlen;
417 
418 	nlen = strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3;
419 	name = malloc(nlen);
420 	if (name == NULL) {
421 		(void) fprintf(stderr, "failed in malloc");
422 		exit(1);
423 	}
424 	(void) snprintf(name, nlen, "%s_%s_%s", locase(pname), vname, ARGEXT);
425 	return (name);
426 }
427 
428 bas_type *typ_list_h;
429 bas_type *typ_list_t;
430 
431 void
432 add_type(int len, char *type)
433 {
434 	bas_type *ptr;
435 
436 	if ((ptr = malloc(sizeof (bas_type))) == NULL) {
437 		(void) fprintf(stderr, "failed in malloc");
438 		exit(1);
439 	}
440 
441 	ptr->name = type;
442 	ptr->length = len;
443 	ptr->next = NULL;
444 	if (typ_list_t == NULL) {
445 		typ_list_t = ptr;
446 		typ_list_h = ptr;
447 	} else {
448 		typ_list_t->next = ptr;
449 		typ_list_t = ptr;
450 	}
451 }
452 
453 
454 bas_type *
455 find_type(char *type)
456 {
457 	bas_type *ptr;
458 
459 	ptr = typ_list_h;
460 	while (ptr != NULL) {
461 		if (strcmp(ptr->name, type) == 0)
462 			return (ptr);
463 		ptr = ptr->next;
464 	}
465 	return (NULL);
466 }
467