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