Bring in a transport-independent RPC (TI-RPC).
[games.git] / usr.bin / rpcgen / rpc_parse.c
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  *
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  *
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  *
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  *
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  *
29  * @(#)rpc_parse.c      1.12    93/07/05 SMI; 1.8 89/02/22 (C) 1987 SMI
30  * $FreeBSD: src/usr.bin/rpcgen/rpc_parse.c,v 1.12 2005/11/13 21:17:24 dwmalone Exp $
31  * $DragonFly: src/usr.bin/rpcgen/rpc_parse.c,v 1.7 2004/06/19 16:40:36 joerg Exp $
32  */
33
34 /*
35  * rpc_parse.c, Parser for the RPC protocol compiler
36  * Copyright (C) 1987 Sun Microsystems, Inc.
37  */
38 #include <stdio.h>
39 #include <string.h>
40 #include "rpc/types.h"
41 #include "rpc_parse.h"
42 #include "rpc_scan.h"
43 #include "rpc_util.h"
44
45 #define ARGNAME "arg"
46
47 static void     isdefined(definition *);
48 static void     def_struct(definition *);
49 static void     def_program(definition *);
50 static void     def_enum(definition *);
51 static void     def_const(definition *);
52 static void     def_union(definition *);
53 static void     def_typedef(definition *);
54 static void     get_declaration(declaration *, defkind);
55 static void     get_prog_declaration(declaration *, defkind, int);
56 static void     get_type(const char **, const char **, defkind);
57 static void     unsigned_dec(const char **);
58
59 /*
60  * return the next definition you see
61  */
62 definition *
63 get_definition(void)
64 {
65         definition *defp;
66         token tok;
67
68         defp = XALLOC(definition);
69         get_token(&tok);
70         switch (tok.kind) {
71         case TOK_STRUCT:
72                 def_struct(defp);
73                 break;
74         case TOK_UNION:
75                 def_union(defp);
76                 break;
77         case TOK_TYPEDEF:
78                 def_typedef(defp);
79                 break;
80         case TOK_ENUM:
81                 def_enum(defp);
82                 break;
83         case TOK_PROGRAM:
84                 def_program(defp);
85                 break;
86         case TOK_CONST:
87                 def_const(defp);
88                 break;
89         case TOK_EOF:
90                 return(NULL);
91         default:
92                 error("definition keyword expected");
93         }
94         scan(TOK_SEMICOLON, &tok);
95         isdefined(defp);
96         return(defp);
97 }
98
99 static void
100 isdefined(definition *defp)
101 {
102         STOREVAL(&defined, defp);
103 }
104
105 static void
106 def_struct(definition *defp)
107 {
108         token tok;
109         declaration dec;
110         decl_list *decls;
111         decl_list **tailp;
112
113         defp->def_kind = DEF_STRUCT;
114
115         scan(TOK_IDENT, &tok);
116         defp->def_name = tok.str;
117         scan(TOK_LBRACE, &tok);
118         tailp = &defp->def.st.decls;
119         do {
120                 get_declaration(&dec, DEF_STRUCT);
121                 decls = XALLOC(decl_list);
122                 decls->decl = dec;
123                 *tailp = decls;
124                 tailp = &decls->next;
125                 scan(TOK_SEMICOLON, &tok);
126                 peek(&tok);
127         } while (tok.kind != TOK_RBRACE);
128         get_token(&tok);
129         *tailp = NULL;
130 }
131
132 static void
133 def_program(definition *defp)
134 {
135         token tok;
136         declaration dec;
137         decl_list *decls;
138         decl_list **tailp;
139         version_list *vlist;
140         version_list **vtailp;
141         proc_list *plist;
142         proc_list **ptailp;
143         int num_args;
144         bool_t isvoid = FALSE;  /* whether first argument is void */
145         defp->def_kind = DEF_PROGRAM;
146         scan(TOK_IDENT, &tok);
147         defp->def_name = tok.str;
148         scan(TOK_LBRACE, &tok);
149         vtailp = &defp->def.pr.versions;
150         tailp = &defp->def.st.decls;
151         scan(TOK_VERSION, &tok);
152         do {
153                 scan(TOK_IDENT, &tok);
154                 vlist = XALLOC(version_list);
155                 vlist->vers_name = tok.str;
156                 scan(TOK_LBRACE, &tok);
157                 ptailp = &vlist->procs;
158                 do {
159                         /* get result type */
160                         plist = XALLOC(proc_list);
161                         get_type(&plist->res_prefix, &plist->res_type,
162                                  DEF_PROGRAM);
163                         if (streq(plist->res_type, "opaque"))
164                                 error("illegal result type");
165                         scan(TOK_IDENT, &tok);
166                         plist->proc_name = tok.str;
167                         scan(TOK_LPAREN, &tok);
168                         /* get args - first one */
169                         num_args = 1;
170                         isvoid = FALSE;
171                         /*
172                          * type of DEF_PROGRAM in the first
173                          * get_prog_declaration and DEF_STURCT in the next
174                          * allows void as argument if it is the only argument
175                          */
176                         get_prog_declaration(&dec, DEF_PROGRAM, num_args);
177                         if (streq(dec.type, "void"))
178                                 isvoid = TRUE;
179                         decls = XALLOC(decl_list);
180                         plist->args.decls = decls;
181                         decls->decl = dec;
182                         tailp = &decls->next;
183                         /* get args */
184                         while (peekscan(TOK_COMMA, &tok)) {
185                                 num_args++;
186                                 get_prog_declaration(&dec, DEF_STRUCT,
187                                                      num_args);
188                                 decls = XALLOC(decl_list);
189                                 decls->decl = dec;
190                                 *tailp = decls;
191                                 if (streq(dec.type, "void"))
192                                         isvoid = TRUE;
193                                 tailp = &decls->next;
194                         }
195                         /* multiple arguments are only allowed in newstyle */
196                         if (!newstyle && num_args > 1)
197                                 error("only one argument is allowed");
198                         if (isvoid && num_args > 1)
199                                 error("illegal use of void in program definition");
200                         *tailp = NULL;
201                         scan(TOK_RPAREN, &tok);
202                         scan(TOK_EQUAL, &tok);
203                         scan_num(&tok);
204                         scan(TOK_SEMICOLON, &tok);
205                         plist->proc_num = tok.str;
206                         plist->arg_num = num_args;
207                         *ptailp = plist;
208                         ptailp = &plist->next;
209                         peek(&tok);
210                 } while (tok.kind != TOK_RBRACE);
211                 *ptailp = NULL;
212                 *vtailp = vlist;
213                 vtailp = &vlist->next;
214                 scan(TOK_RBRACE, &tok);
215                 scan(TOK_EQUAL, &tok);
216                 scan_num(&tok);
217                 vlist->vers_num = tok.str;
218                 /* make the argument structure name for each arg */
219                 for (plist = vlist->procs; plist != NULL; plist = plist->next) {
220                         plist->args.argname = make_argname(plist->proc_name,
221                                                            vlist->vers_num);
222                         /* free the memory ?? */
223                 }
224                 scan(TOK_SEMICOLON, &tok);
225                 scan2(TOK_VERSION, TOK_RBRACE, &tok);
226         } while (tok.kind == TOK_VERSION);
227         scan(TOK_EQUAL, &tok);
228         scan_num(&tok);
229         defp->def.pr.prog_num = tok.str;
230         *vtailp = NULL;
231 }
232
233
234 static void
235 def_enum(definition *defp)
236 {
237         token tok;
238         enumval_list *elist;
239         enumval_list **tailp;
240
241         defp->def_kind = DEF_ENUM;
242         scan(TOK_IDENT, &tok);
243         defp->def_name = tok.str;
244         scan(TOK_LBRACE, &tok);
245         tailp = &defp->def.en.vals;
246         do {
247                 scan(TOK_IDENT, &tok);
248                 elist = XALLOC(enumval_list);
249                 elist->name = tok.str;
250                 elist->assignment = NULL;
251                 scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
252                 if (tok.kind == TOK_EQUAL) {
253                         scan_num(&tok);
254                         elist->assignment = tok.str;
255                         scan2(TOK_COMMA, TOK_RBRACE, &tok);
256                 }
257                 *tailp = elist;
258                 tailp = &elist->next;
259         } while (tok.kind != TOK_RBRACE);
260         *tailp = NULL;
261 }
262
263 static void
264 def_const(definition *defp)
265 {
266         token tok;
267
268         defp->def_kind = DEF_CONST;
269         scan(TOK_IDENT, &tok);
270         defp->def_name = tok.str;
271         scan(TOK_EQUAL, &tok);
272         scan2(TOK_IDENT, TOK_STRCONST, &tok);
273         defp->def.co = tok.str;
274 }
275
276 static void
277 def_union(definition *defp)
278 {
279         token tok;
280         declaration dec;
281         case_list *cases;
282         case_list **tailp;
283         int flag;
284
285         defp->def_kind = DEF_UNION;
286         scan(TOK_IDENT, &tok);
287         defp->def_name = tok.str;
288         scan(TOK_SWITCH, &tok);
289         scan(TOK_LPAREN, &tok);
290         get_declaration(&dec, DEF_UNION);
291         defp->def.un.enum_decl = dec;
292         tailp = &defp->def.un.cases;
293         scan(TOK_RPAREN, &tok);
294         scan(TOK_LBRACE, &tok);
295         scan(TOK_CASE, &tok);
296         while (tok.kind == TOK_CASE) {
297                 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
298                 cases = XALLOC(case_list);
299                 cases->case_name = tok.str;
300                 scan(TOK_COLON, &tok);
301                 /* now peek at next token */
302                 flag = 0;
303                 if (peekscan(TOK_CASE, &tok)){
304                         do {
305                                 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
306                                 cases->contflag = 1;
307                                 /* continued case statement */
308                                 *tailp = cases;
309                                 tailp = &cases->next;
310                                 cases = XALLOC(case_list);
311                                 cases->case_name = tok.str;
312                                 scan(TOK_COLON, &tok);
313                         } while (peekscan(TOK_CASE, &tok));
314                 }
315                 else if (flag) {
316                         *tailp = cases;
317                         tailp = &cases->next;
318                         cases = XALLOC(case_list);
319                 }
320
321                 get_declaration(&dec, DEF_UNION);
322                 cases->case_decl = dec;
323                 cases->contflag = 0; /* no continued case statement */
324                 *tailp = cases;
325                 tailp = &cases->next;
326                 scan(TOK_SEMICOLON, &tok);
327
328                 scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
329         }
330         *tailp = NULL;
331         if (tok.kind == TOK_DEFAULT) {
332                 scan(TOK_COLON, &tok);
333                 get_declaration(&dec, DEF_UNION);
334                 defp->def.un.default_decl = XALLOC(declaration);
335                 *defp->def.un.default_decl = dec;
336                 scan(TOK_SEMICOLON, &tok);
337                 scan(TOK_RBRACE, &tok);
338         } else {
339                 defp->def.un.default_decl = NULL;
340         }
341 }
342
343 static const char *reserved_words[] =
344 {
345         "array",
346         "bytes",
347         "destroy",
348         "free",
349         "getpos",
350         "inline",
351         "pointer",
352         "reference",
353         "setpos",
354         "sizeof",
355         "union",
356         "vector",
357         NULL
358 };
359
360 static const char *reserved_types[] =
361 {
362         "opaque",
363         "string",
364         NULL
365 };
366
367 /*
368  * check that the given name is not one that would eventually result in
369  * xdr routines that would conflict with internal XDR routines.
370  */
371 static void
372 check_type_name(const char *name, int new_type)
373 {
374         int i;
375         char tmp[100];
376
377         for (i = 0; reserved_words[i] != NULL; i++) {
378                 if (strcmp(name, reserved_words[i]) == 0) {
379                         sprintf(tmp,
380                                 "illegal (reserved) name :\'%s\' in type definition",
381                                 name);
382                         error(tmp);
383                 }
384         }
385         if (new_type) {
386                 for (i = 0; reserved_types[i] != NULL; i++) {
387                         if (strcmp(name, reserved_types[i]) == 0) {
388                                 sprintf(tmp,
389                                         "illegal (reserved) name :\'%s\' in type definition",
390                                         name);
391                                 error(tmp);
392                         }
393                 }
394         }
395 }
396
397
398
399 static void
400 def_typedef(definition *defp)
401 {
402         declaration dec;
403
404         defp->def_kind = DEF_TYPEDEF;
405         get_declaration(&dec, DEF_TYPEDEF);
406         defp->def_name = dec.name;
407         check_type_name(dec.name, 1);
408         defp->def.ty.old_prefix = dec.prefix;
409         defp->def.ty.old_type = dec.type;
410         defp->def.ty.rel = dec.rel;
411         defp->def.ty.array_max = dec.array_max;
412 }
413
414 static void
415 get_declaration(declaration *dec, defkind dkind)
416 {
417         token tok;
418
419         get_type(&dec->prefix, &dec->type, dkind);
420         dec->rel = REL_ALIAS;
421         if (streq(dec->type, "void"))
422                 return;
423
424         check_type_name(dec->type, 0);
425         scan2(TOK_STAR, TOK_IDENT, &tok);
426         if (tok.kind == TOK_STAR) {
427                 dec->rel = REL_POINTER;
428                 scan(TOK_IDENT, &tok);
429         }
430         dec->name = tok.str;
431         if (peekscan(TOK_LBRACKET, &tok)) {
432                 if (dec->rel == REL_POINTER)
433                         error("no array-of-pointer declarations -- use typedef");
434                 dec->rel = REL_VECTOR;
435                 scan_num(&tok);
436                 dec->array_max = tok.str;
437                 scan(TOK_RBRACKET, &tok);
438         } else if (peekscan(TOK_LANGLE, &tok)) {
439                 if (dec->rel == REL_POINTER)
440                         error("no array-of-pointer declarations -- use typedef");
441                 dec->rel = REL_ARRAY;
442                 if (peekscan(TOK_RANGLE, &tok)) {
443                         dec->array_max = "~0";  /* unspecified size, use max */
444                 } else {
445                         scan_num(&tok);
446                         dec->array_max = tok.str;
447                         scan(TOK_RANGLE, &tok);
448                 }
449         }
450         if (streq(dec->type, "opaque")) {
451                 if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
452                         error("array declaration expected");
453                 }
454         } else if (streq(dec->type, "string")) {
455                 if (dec->rel != REL_ARRAY) {
456                         error("variable-length array declaration expected");
457                 }
458         }
459 }
460
461
462 static void
463 get_prog_declaration(declaration *dec, defkind dkind, int num)
464 {
465         token tok;
466         char name[10];          /* argument name */
467
468         if (dkind == DEF_PROGRAM) {
469                 peek(&tok);
470                 if (tok.kind == TOK_RPAREN) { /* no arguments */
471                         dec->rel = REL_ALIAS;
472                         dec->type = "void";
473                         dec->prefix = NULL;
474                         dec->name = NULL;
475                         return;
476                 }
477         }
478         get_type(&dec->prefix, &dec->type, dkind);
479         dec->rel = REL_ALIAS;
480         if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
481                 strcpy(name, tok.str);
482         else
483                 sprintf(name, "%s%d", ARGNAME, num);
484         /* default name of argument */
485
486         dec->name = (char *) xstrdup(name);
487         if (streq(dec->type, "void")) {
488                 return;
489         }
490
491         if (streq(dec->type, "opaque"))
492                 error("opaque -- illegal argument type");
493         if (peekscan(TOK_STAR, &tok)) {
494                 if (streq(dec->type, "string"))
495                         error("pointer to string not allowed in program arguments");
496                 dec->rel = REL_POINTER;
497                 if (peekscan(TOK_IDENT, &tok)) {
498                         /* optional name of argument */
499                         dec->name = xstrdup(tok.str);
500                 }
501         }
502         if (peekscan(TOK_LANGLE, &tok)) {
503                 if (!streq(dec->type, "string"))
504                         error("arrays cannot be declared as arguments to procedures -- use typedef");
505                 dec->rel = REL_ARRAY;
506                 if (peekscan(TOK_RANGLE, &tok)) {
507                         dec->array_max = "~0";
508                         /* unspecified size, use max */
509                 } else {
510                         scan_num(&tok);
511                         dec->array_max = tok.str;
512                         scan(TOK_RANGLE, &tok);
513                 }
514         }
515         if (streq(dec->type, "string")) {
516                 if (dec->rel != REL_ARRAY) {
517                         /*
518                          * .x specifies just string as
519                          * type of argument
520                          * - make it string<>
521                          */
522                         dec->rel = REL_ARRAY;
523                         dec->array_max = "~0"; /* unspecified size, use max */
524                 }
525         }
526 }
527
528 static void
529 get_type(const char **prefixp, const char **typep, defkind dkind)
530 {
531         token tok;
532
533         *prefixp = NULL;
534         get_token(&tok);
535         switch (tok.kind) {
536         case TOK_IDENT:
537                 *typep = tok.str;
538                 break;
539         case TOK_STRUCT:
540         case TOK_ENUM:
541         case TOK_UNION:
542                 *prefixp = tok.str;
543                 scan(TOK_IDENT, &tok);
544                 *typep = tok.str;
545                 break;
546         case TOK_UNSIGNED:
547                 unsigned_dec(typep);
548                 break;
549         case TOK_SHORT:
550                 *typep = "short";
551                 peekscan(TOK_INT, &tok);
552                 break;
553         case TOK_LONG:
554                 *typep = "long";
555                 peekscan(TOK_INT, &tok);
556                 break;
557         case TOK_HYPER:
558                 *typep = "int64_t";
559                 peekscan(TOK_INT, &tok);
560                 break;
561
562         case TOK_VOID:
563                 if (dkind != DEF_UNION && dkind != DEF_PROGRAM)
564                         error("voids allowed only inside union and program definitions with one argument");
565                 *typep = tok.str;
566                 break;
567         case TOK_STRING:
568         case TOK_OPAQUE:
569         case TOK_CHAR:
570         case TOK_INT:
571         case TOK_FLOAT:
572         case TOK_DOUBLE:
573         case TOK_BOOL:
574         case TOK_QUAD:
575                 *typep = tok.str;
576                 break;
577         default:
578                 error("expected type specifier");
579         }
580 }
581
582 static void
583 unsigned_dec(const char **typep)
584 {
585         token tok;
586
587         peek(&tok);
588         switch (tok.kind) {
589         case TOK_CHAR:
590                 get_token(&tok);
591                 *typep = "u_char";
592                 break;
593         case TOK_SHORT:
594                 get_token(&tok);
595                 *typep = "u_short";
596                 peekscan(TOK_INT, &tok);
597                 break;
598         case TOK_LONG:
599                 get_token(&tok);
600                 *typep = "u_long";
601                 peekscan(TOK_INT, &tok);
602                 break;
603         case TOK_HYPER:
604                 get_token(&tok);
605                 *typep = "u_int64_t";
606                 peekscan(TOK_INT, &tok);
607                 break;
608         case TOK_INT:
609                 get_token(&tok);
610                 *typep = "u_int";
611                 break;
612         default:
613                 *typep = "u_int";
614                 break;
615         }
616 }