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