Sun agreed to a change of the license for the RPC code to a BSD-like license.
[platform/upstream/glibc.git] / sunrpc / rpc_parse.c
1 /*
2  * From: @(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  *       copyright notice, this list of conditions and the following
12  *       disclaimer in the documentation and/or other materials
13  *       provided with the distribution.
14  *     * Neither the name of Sun Microsystems, Inc. nor the names of its
15  *       contributors may be used to endorse or promote products derived
16  *       from this software without specific prior written permission.
17  *
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /*
33  * rpc_parse.c, Parser for the RPC protocol compiler
34  * Copyright (C) 1987 Sun Microsystems, Inc.
35  */
36 #include <stdio.h>
37 #include <string.h>
38 #include "rpc/types.h"
39 #include "rpc_scan.h"
40 #include "rpc_parse.h"
41 #include "rpc_util.h"
42 #include "proto.h"
43
44 #define ARGNAME "arg"
45
46 static void isdefined (definition * defp);
47 static void def_struct (definition * defp);
48 static void def_program (definition * defp);
49 static void def_enum (definition * defp);
50 static void def_const (definition * defp);
51 static void def_union (definition * defp);
52 static void check_type_name (const char *name, int new_type);
53 static void def_typedef (definition * defp);
54 static void get_declaration (declaration * dec, defkind dkind);
55 static void get_prog_declaration (declaration * dec, defkind dkind, int num);
56 static void get_type (const char **prefixp, const char **typep, defkind dkind);
57 static void unsigned_dec (const char **typep);
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 = ALLOC (definition);
69   get_token (&tok);
70   switch (tok.kind)
71     {
72     case TOK_STRUCT:
73       def_struct (defp);
74       break;
75     case TOK_UNION:
76       def_union (defp);
77       break;
78     case TOK_TYPEDEF:
79       def_typedef (defp);
80       break;
81     case TOK_ENUM:
82       def_enum (defp);
83       break;
84     case TOK_PROGRAM:
85       def_program (defp);
86       break;
87     case TOK_CONST:
88       def_const (defp);
89       break;
90     case TOK_EOF:
91       free (defp);
92       return (NULL);
93     default:
94       error ("definition keyword expected");
95     }
96   scan (TOK_SEMICOLON, &tok);
97   isdefined (defp);
98   return (defp);
99 }
100
101 static void
102 isdefined (definition * defp)
103 {
104   STOREVAL (&defined, defp);
105 }
106
107 static void
108 def_struct (definition * defp)
109 {
110   token tok;
111   declaration dec;
112   decl_list *decls;
113   decl_list **tailp;
114
115   defp->def_kind = DEF_STRUCT;
116
117   scan (TOK_IDENT, &tok);
118   defp->def_name = tok.str;
119   scan (TOK_LBRACE, &tok);
120   tailp = &defp->def.st.decls;
121   do
122     {
123       get_declaration (&dec, DEF_STRUCT);
124       decls = ALLOC (decl_list);
125       decls->decl = dec;
126       *tailp = decls;
127       tailp = &decls->next;
128       scan (TOK_SEMICOLON, &tok);
129       peek (&tok);
130     }
131   while (tok.kind != TOK_RBRACE);
132   get_token (&tok);
133   *tailp = NULL;
134 }
135
136 static void
137 def_program (definition * defp)
138 {
139   token tok;
140   declaration dec;
141   decl_list *decls;
142   decl_list **tailp;
143   version_list *vlist;
144   version_list **vtailp;
145   proc_list *plist;
146   proc_list **ptailp;
147   int num_args;
148   bool_t isvoid = FALSE;        /* whether first argument is void */
149   defp->def_kind = DEF_PROGRAM;
150   scan (TOK_IDENT, &tok);
151   defp->def_name = tok.str;
152   scan (TOK_LBRACE, &tok);
153   vtailp = &defp->def.pr.versions;
154   tailp = &defp->def.st.decls;
155   scan (TOK_VERSION, &tok);
156   do
157     {
158       scan (TOK_IDENT, &tok);
159       vlist = ALLOC (version_list);
160       vlist->vers_name = tok.str;
161       scan (TOK_LBRACE, &tok);
162       ptailp = &vlist->procs;
163       do
164         {
165           /* get result type */
166           plist = ALLOC (proc_list);
167           get_type (&plist->res_prefix, &plist->res_type,
168                     DEF_PROGRAM);
169           if (streq (plist->res_type, "opaque"))
170             {
171               error ("illegal result type");
172             }
173           scan (TOK_IDENT, &tok);
174           plist->proc_name = tok.str;
175           scan (TOK_LPAREN, &tok);
176           /* get args - first one */
177           num_args = 1;
178           isvoid = FALSE;
179           /* type of DEF_PROGRAM in the first
180            * get_prog_declaration and DEF_STURCT in the next
181            * allows void as argument if it is the only argument
182            */
183           get_prog_declaration (&dec, DEF_PROGRAM, num_args);
184           if (streq (dec.type, "void"))
185             isvoid = TRUE;
186           decls = ALLOC (decl_list);
187           plist->args.decls = decls;
188           decls->decl = dec;
189           tailp = &decls->next;
190           /* get args */
191           while (peekscan (TOK_COMMA, &tok))
192             {
193               num_args++;
194               get_prog_declaration (&dec, DEF_STRUCT,
195                                     num_args);
196               decls = ALLOC (decl_list);
197               decls->decl = dec;
198               *tailp = decls;
199               if (streq (dec.type, "void"))
200                 isvoid = TRUE;
201               tailp = &decls->next;
202             }
203           /* multiple arguments are only allowed in newstyle */
204           if (!newstyle && num_args > 1)
205             {
206               error ("only one argument is allowed");
207             }
208           if (isvoid && num_args > 1)
209             {
210               error ("illegal use of void in program definition");
211             }
212           *tailp = NULL;
213           scan (TOK_RPAREN, &tok);
214           scan (TOK_EQUAL, &tok);
215           scan_num (&tok);
216           scan (TOK_SEMICOLON, &tok);
217           plist->proc_num = tok.str;
218           plist->arg_num = num_args;
219           *ptailp = plist;
220           ptailp = &plist->next;
221           peek (&tok);
222         }
223       while (tok.kind != TOK_RBRACE);
224       *ptailp = NULL;
225       *vtailp = vlist;
226       vtailp = &vlist->next;
227       scan (TOK_RBRACE, &tok);
228       scan (TOK_EQUAL, &tok);
229       scan_num (&tok);
230       vlist->vers_num = tok.str;
231       /* make the argument structure name for each arg */
232       for (plist = vlist->procs; plist != NULL;
233            plist = plist->next)
234         {
235           plist->args.argname = make_argname (plist->proc_name,
236                                               vlist->vers_num);
237           /* free the memory ?? */
238         }
239       scan (TOK_SEMICOLON, &tok);
240       scan2 (TOK_VERSION, TOK_RBRACE, &tok);
241     }
242   while (tok.kind == TOK_VERSION);
243   scan (TOK_EQUAL, &tok);
244   scan_num (&tok);
245   defp->def.pr.prog_num = tok.str;
246   *vtailp = NULL;
247 }
248
249
250 static void
251 def_enum (definition * defp)
252 {
253   token tok;
254   enumval_list *elist;
255   enumval_list **tailp;
256
257   defp->def_kind = DEF_ENUM;
258   scan (TOK_IDENT, &tok);
259   defp->def_name = tok.str;
260   scan (TOK_LBRACE, &tok);
261   tailp = &defp->def.en.vals;
262   do
263     {
264       scan (TOK_IDENT, &tok);
265       elist = ALLOC (enumval_list);
266       elist->name = tok.str;
267       elist->assignment = NULL;
268       scan3 (TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
269       if (tok.kind == TOK_EQUAL)
270         {
271           scan_num (&tok);
272           elist->assignment = tok.str;
273           scan2 (TOK_COMMA, TOK_RBRACE, &tok);
274         }
275       *tailp = elist;
276       tailp = &elist->next;
277     }
278   while (tok.kind != TOK_RBRACE);
279   *tailp = NULL;
280 }
281
282 static void
283 def_const (definition * defp)
284 {
285   token tok;
286
287   defp->def_kind = DEF_CONST;
288   scan (TOK_IDENT, &tok);
289   defp->def_name = tok.str;
290   scan (TOK_EQUAL, &tok);
291   scan2 (TOK_IDENT, TOK_STRCONST, &tok);
292   defp->def.co = tok.str;
293 }
294
295 static void
296 def_union (definition *defp)
297 {
298   token tok;
299   declaration dec;
300   case_list *cases;
301 /*  case_list *tcase; */
302   case_list **tailp;
303 #if 0
304   int flag;
305 #endif
306
307   defp->def_kind = DEF_UNION;
308   scan (TOK_IDENT, &tok);
309   defp->def_name = tok.str;
310   scan (TOK_SWITCH, &tok);
311   scan (TOK_LPAREN, &tok);
312   get_declaration (&dec, DEF_UNION);
313   defp->def.un.enum_decl = dec;
314   tailp = &defp->def.un.cases;
315   scan (TOK_RPAREN, &tok);
316   scan (TOK_LBRACE, &tok);
317   scan (TOK_CASE, &tok);
318   while (tok.kind == TOK_CASE)
319     {
320       scan2 (TOK_IDENT, TOK_CHARCONST, &tok);
321       cases = ALLOC (case_list);
322       cases->case_name = tok.str;
323       scan (TOK_COLON, &tok);
324       /* now peek at next token */
325 #if 0
326       flag = 0;
327 #endif
328       if (peekscan (TOK_CASE, &tok))
329         {
330
331           do
332             {
333               scan2 (TOK_IDENT, TOK_CHARCONST, &tok);
334               cases->contflag = 1;      /* continued case statement */
335               *tailp = cases;
336               tailp = &cases->next;
337               cases = ALLOC (case_list);
338               cases->case_name = tok.str;
339               scan (TOK_COLON, &tok);
340
341             }
342           while (peekscan (TOK_CASE, &tok));
343         }
344 #if 0
345       else if (flag)
346         {
347
348           *tailp = cases;
349           tailp = &cases->next;
350           cases = ALLOC (case_list);
351         };
352 #endif
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 }