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