Back to index

glibc  2.9
rpc_parse.c
Go to the documentation of this file.
00001 /*
00002  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
00003  * unrestricted use provided that this legend is included on all tape
00004  * media and as a part of the software program in whole or part.  Users
00005  * may copy or modify Sun RPC without charge, but are not authorized
00006  * to license or distribute it to anyone else except as part of a product or
00007  * program developed by the user or with the express written consent of
00008  * Sun Microsystems, Inc.
00009  *
00010  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
00011  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
00012  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
00013  *
00014  * Sun RPC is provided with no support and without any obligation on the
00015  * part of Sun Microsystems, Inc. to assist in its use, correction,
00016  * modification or enhancement.
00017  *
00018  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
00019  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
00020  * OR ANY PART THEREOF.
00021  *
00022  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
00023  * or profits or other special, indirect and consequential damages, even if
00024  * Sun has been advised of the possibility of such damages.
00025  *
00026  * Sun Microsystems, Inc.
00027  * 2550 Garcia Avenue
00028  * Mountain View, California  94043
00029  */
00030 
00031 /*
00032  * From: @(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI
00033  */
00034 
00035 /*
00036  * rpc_parse.c, Parser for the RPC protocol compiler
00037  * Copyright (C) 1987 Sun Microsystems, Inc.
00038  */
00039 #include <stdio.h>
00040 #include <string.h>
00041 #include "rpc/types.h"
00042 #include "rpc_scan.h"
00043 #include "rpc_parse.h"
00044 #include "rpc_util.h"
00045 #include "proto.h"
00046 
00047 #define ARGNAME "arg"
00048 
00049 static void isdefined (definition * defp);
00050 static void def_struct (definition * defp);
00051 static void def_program (definition * defp);
00052 static void def_enum (definition * defp);
00053 static void def_const (definition * defp);
00054 static void def_union (definition * defp);
00055 static void check_type_name (const char *name, int new_type);
00056 static void def_typedef (definition * defp);
00057 static void get_declaration (declaration * dec, defkind dkind);
00058 static void get_prog_declaration (declaration * dec, defkind dkind, int num);
00059 static void get_type (const char **prefixp, const char **typep, defkind dkind);
00060 static void unsigned_dec (const char **typep);
00061 
00062 /*
00063  * return the next definition you see
00064  */
00065 definition *
00066 get_definition (void)
00067 {
00068   definition *defp;
00069   token tok;
00070 
00071   defp = ALLOC (definition);
00072   get_token (&tok);
00073   switch (tok.kind)
00074     {
00075     case TOK_STRUCT:
00076       def_struct (defp);
00077       break;
00078     case TOK_UNION:
00079       def_union (defp);
00080       break;
00081     case TOK_TYPEDEF:
00082       def_typedef (defp);
00083       break;
00084     case TOK_ENUM:
00085       def_enum (defp);
00086       break;
00087     case TOK_PROGRAM:
00088       def_program (defp);
00089       break;
00090     case TOK_CONST:
00091       def_const (defp);
00092       break;
00093     case TOK_EOF:
00094       free (defp);
00095       return (NULL);
00096     default:
00097       error ("definition keyword expected");
00098     }
00099   scan (TOK_SEMICOLON, &tok);
00100   isdefined (defp);
00101   return (defp);
00102 }
00103 
00104 static void
00105 isdefined (definition * defp)
00106 {
00107   STOREVAL (&defined, defp);
00108 }
00109 
00110 static void
00111 def_struct (definition * defp)
00112 {
00113   token tok;
00114   declaration dec;
00115   decl_list *decls;
00116   decl_list **tailp;
00117 
00118   defp->def_kind = DEF_STRUCT;
00119 
00120   scan (TOK_IDENT, &tok);
00121   defp->def_name = tok.str;
00122   scan (TOK_LBRACE, &tok);
00123   tailp = &defp->def.st.decls;
00124   do
00125     {
00126       get_declaration (&dec, DEF_STRUCT);
00127       decls = ALLOC (decl_list);
00128       decls->decl = dec;
00129       *tailp = decls;
00130       tailp = &decls->next;
00131       scan (TOK_SEMICOLON, &tok);
00132       peek (&tok);
00133     }
00134   while (tok.kind != TOK_RBRACE);
00135   get_token (&tok);
00136   *tailp = NULL;
00137 }
00138 
00139 static void
00140 def_program (definition * defp)
00141 {
00142   token tok;
00143   declaration dec;
00144   decl_list *decls;
00145   decl_list **tailp;
00146   version_list *vlist;
00147   version_list **vtailp;
00148   proc_list *plist;
00149   proc_list **ptailp;
00150   int num_args;
00151   bool_t isvoid = FALSE;    /* whether first argument is void */
00152   defp->def_kind = DEF_PROGRAM;
00153   scan (TOK_IDENT, &tok);
00154   defp->def_name = tok.str;
00155   scan (TOK_LBRACE, &tok);
00156   vtailp = &defp->def.pr.versions;
00157   tailp = &defp->def.st.decls;
00158   scan (TOK_VERSION, &tok);
00159   do
00160     {
00161       scan (TOK_IDENT, &tok);
00162       vlist = ALLOC (version_list);
00163       vlist->vers_name = tok.str;
00164       scan (TOK_LBRACE, &tok);
00165       ptailp = &vlist->procs;
00166       do
00167        {
00168          /* get result type */
00169          plist = ALLOC (proc_list);
00170          get_type (&plist->res_prefix, &plist->res_type,
00171                   DEF_PROGRAM);
00172          if (streq (plist->res_type, "opaque"))
00173            {
00174              error ("illegal result type");
00175            }
00176          scan (TOK_IDENT, &tok);
00177          plist->proc_name = tok.str;
00178          scan (TOK_LPAREN, &tok);
00179          /* get args - first one */
00180          num_args = 1;
00181          isvoid = FALSE;
00182          /* type of DEF_PROGRAM in the first
00183           * get_prog_declaration and DEF_STURCT in the next
00184           * allows void as argument if it is the only argument
00185           */
00186          get_prog_declaration (&dec, DEF_PROGRAM, num_args);
00187          if (streq (dec.type, "void"))
00188            isvoid = TRUE;
00189          decls = ALLOC (decl_list);
00190          plist->args.decls = decls;
00191          decls->decl = dec;
00192          tailp = &decls->next;
00193          /* get args */
00194          while (peekscan (TOK_COMMA, &tok))
00195            {
00196              num_args++;
00197              get_prog_declaration (&dec, DEF_STRUCT,
00198                                 num_args);
00199              decls = ALLOC (decl_list);
00200              decls->decl = dec;
00201              *tailp = decls;
00202              if (streq (dec.type, "void"))
00203               isvoid = TRUE;
00204              tailp = &decls->next;
00205            }
00206          /* multiple arguments are only allowed in newstyle */
00207          if (!newstyle && num_args > 1)
00208            {
00209              error ("only one argument is allowed");
00210            }
00211          if (isvoid && num_args > 1)
00212            {
00213              error ("illegal use of void in program definition");
00214            }
00215          *tailp = NULL;
00216          scan (TOK_RPAREN, &tok);
00217          scan (TOK_EQUAL, &tok);
00218          scan_num (&tok);
00219          scan (TOK_SEMICOLON, &tok);
00220          plist->proc_num = tok.str;
00221          plist->arg_num = num_args;
00222          *ptailp = plist;
00223          ptailp = &plist->next;
00224          peek (&tok);
00225        }
00226       while (tok.kind != TOK_RBRACE);
00227       *ptailp = NULL;
00228       *vtailp = vlist;
00229       vtailp = &vlist->next;
00230       scan (TOK_RBRACE, &tok);
00231       scan (TOK_EQUAL, &tok);
00232       scan_num (&tok);
00233       vlist->vers_num = tok.str;
00234       /* make the argument structure name for each arg */
00235       for (plist = vlist->procs; plist != NULL;
00236           plist = plist->next)
00237        {
00238          plist->args.argname = make_argname (plist->proc_name,
00239                                          vlist->vers_num);
00240          /* free the memory ?? */
00241        }
00242       scan (TOK_SEMICOLON, &tok);
00243       scan2 (TOK_VERSION, TOK_RBRACE, &tok);
00244     }
00245   while (tok.kind == TOK_VERSION);
00246   scan (TOK_EQUAL, &tok);
00247   scan_num (&tok);
00248   defp->def.pr.prog_num = tok.str;
00249   *vtailp = NULL;
00250 }
00251 
00252 
00253 static void
00254 def_enum (definition * defp)
00255 {
00256   token tok;
00257   enumval_list *elist;
00258   enumval_list **tailp;
00259 
00260   defp->def_kind = DEF_ENUM;
00261   scan (TOK_IDENT, &tok);
00262   defp->def_name = tok.str;
00263   scan (TOK_LBRACE, &tok);
00264   tailp = &defp->def.en.vals;
00265   do
00266     {
00267       scan (TOK_IDENT, &tok);
00268       elist = ALLOC (enumval_list);
00269       elist->name = tok.str;
00270       elist->assignment = NULL;
00271       scan3 (TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
00272       if (tok.kind == TOK_EQUAL)
00273        {
00274          scan_num (&tok);
00275          elist->assignment = tok.str;
00276          scan2 (TOK_COMMA, TOK_RBRACE, &tok);
00277        }
00278       *tailp = elist;
00279       tailp = &elist->next;
00280     }
00281   while (tok.kind != TOK_RBRACE);
00282   *tailp = NULL;
00283 }
00284 
00285 static void
00286 def_const (definition * defp)
00287 {
00288   token tok;
00289 
00290   defp->def_kind = DEF_CONST;
00291   scan (TOK_IDENT, &tok);
00292   defp->def_name = tok.str;
00293   scan (TOK_EQUAL, &tok);
00294   scan2 (TOK_IDENT, TOK_STRCONST, &tok);
00295   defp->def.co = tok.str;
00296 }
00297 
00298 static void
00299 def_union (definition *defp)
00300 {
00301   token tok;
00302   declaration dec;
00303   case_list *cases;
00304 /*  case_list *tcase; */
00305   case_list **tailp;
00306 #if 0
00307   int flag;
00308 #endif
00309 
00310   defp->def_kind = DEF_UNION;
00311   scan (TOK_IDENT, &tok);
00312   defp->def_name = tok.str;
00313   scan (TOK_SWITCH, &tok);
00314   scan (TOK_LPAREN, &tok);
00315   get_declaration (&dec, DEF_UNION);
00316   defp->def.un.enum_decl = dec;
00317   tailp = &defp->def.un.cases;
00318   scan (TOK_RPAREN, &tok);
00319   scan (TOK_LBRACE, &tok);
00320   scan (TOK_CASE, &tok);
00321   while (tok.kind == TOK_CASE)
00322     {
00323       scan2 (TOK_IDENT, TOK_CHARCONST, &tok);
00324       cases = ALLOC (case_list);
00325       cases->case_name = tok.str;
00326       scan (TOK_COLON, &tok);
00327       /* now peek at next token */
00328 #if 0
00329       flag = 0;
00330 #endif
00331       if (peekscan (TOK_CASE, &tok))
00332        {
00333 
00334          do
00335            {
00336              scan2 (TOK_IDENT, TOK_CHARCONST, &tok);
00337              cases->contflag = 1;  /* continued case statement */
00338              *tailp = cases;
00339              tailp = &cases->next;
00340              cases = ALLOC (case_list);
00341              cases->case_name = tok.str;
00342              scan (TOK_COLON, &tok);
00343 
00344            }
00345          while (peekscan (TOK_CASE, &tok));
00346        }
00347 #if 0
00348       else if (flag)
00349        {
00350 
00351          *tailp = cases;
00352          tailp = &cases->next;
00353          cases = ALLOC (case_list);
00354        };
00355 #endif
00356 
00357       get_declaration (&dec, DEF_UNION);
00358       cases->case_decl = dec;
00359       cases->contflag = 0;  /* no continued case statement */
00360       *tailp = cases;
00361       tailp = &cases->next;
00362       scan (TOK_SEMICOLON, &tok);
00363 
00364       scan3 (TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
00365     }
00366   *tailp = NULL;
00367   if (tok.kind == TOK_DEFAULT)
00368     {
00369       scan (TOK_COLON, &tok);
00370       get_declaration (&dec, DEF_UNION);
00371       defp->def.un.default_decl = ALLOC (declaration);
00372       *defp->def.un.default_decl = dec;
00373       scan (TOK_SEMICOLON, &tok);
00374       scan (TOK_RBRACE, &tok);
00375     }
00376   else
00377     {
00378       defp->def.un.default_decl = NULL;
00379     }
00380 }
00381 
00382 static const char *reserved_words[] =
00383 {
00384   "array",
00385   "bytes",
00386   "destroy",
00387   "free",
00388   "getpos",
00389   "inline",
00390   "pointer",
00391   "reference",
00392   "setpos",
00393   "sizeof",
00394   "union",
00395   "vector",
00396   NULL
00397 };
00398 
00399 static const char *reserved_types[] =
00400 {
00401   "opaque",
00402   "string",
00403   NULL
00404 };
00405 
00406 /*
00407  * check that the given name is not one that would eventually result in
00408  * xdr routines that would conflict with internal XDR routines.
00409  */
00410 static void
00411 check_type_name (const char *name, int new_type)
00412 {
00413   int i;
00414   char tmp[100];
00415 
00416   for (i = 0; reserved_words[i] != NULL; i++)
00417     {
00418       if (strcmp (name, reserved_words[i]) == 0)
00419        {
00420          sprintf (tmp,
00421               "illegal (reserved) name :\'%s\' in type definition", name);
00422          error (tmp);
00423        }
00424     }
00425   if (new_type)
00426     {
00427       for (i = 0; reserved_types[i] != NULL; i++)
00428        {
00429          if (strcmp (name, reserved_types[i]) == 0)
00430            {
00431              sprintf (tmp,
00432               "illegal (reserved) name :\'%s\' in type definition", name);
00433              error (tmp);
00434            }
00435        }
00436     }
00437 }
00438 
00439 
00440 
00441 static void
00442 def_typedef (definition * defp)
00443 {
00444   declaration dec;
00445 
00446   defp->def_kind = DEF_TYPEDEF;
00447   get_declaration (&dec, DEF_TYPEDEF);
00448   defp->def_name = dec.name;
00449   check_type_name (dec.name, 1);
00450   defp->def.ty.old_prefix = dec.prefix;
00451   defp->def.ty.old_type = dec.type;
00452   defp->def.ty.rel = dec.rel;
00453   defp->def.ty.array_max = dec.array_max;
00454 }
00455 
00456 static void
00457 get_declaration (declaration * dec, defkind dkind)
00458 {
00459   token tok;
00460 
00461   get_type (&dec->prefix, &dec->type, dkind);
00462   dec->rel = REL_ALIAS;
00463   if (streq (dec->type, "void"))
00464     {
00465       return;
00466     }
00467 
00468   check_type_name (dec->type, 0);
00469 
00470   scan2 (TOK_STAR, TOK_IDENT, &tok);
00471   if (tok.kind == TOK_STAR)
00472     {
00473       dec->rel = REL_POINTER;
00474       scan (TOK_IDENT, &tok);
00475     }
00476   dec->name = tok.str;
00477   if (peekscan (TOK_LBRACKET, &tok))
00478     {
00479       if (dec->rel == REL_POINTER)
00480        {
00481          error ("no array-of-pointer declarations -- use typedef");
00482        }
00483       dec->rel = REL_VECTOR;
00484       scan_num (&tok);
00485       dec->array_max = tok.str;
00486       scan (TOK_RBRACKET, &tok);
00487     }
00488   else if (peekscan (TOK_LANGLE, &tok))
00489     {
00490       if (dec->rel == REL_POINTER)
00491        {
00492          error ("no array-of-pointer declarations -- use typedef");
00493        }
00494       dec->rel = REL_ARRAY;
00495       if (peekscan (TOK_RANGLE, &tok))
00496        {
00497          dec->array_max = "~0";    /* unspecified size, use max */
00498        }
00499       else
00500        {
00501          scan_num (&tok);
00502          dec->array_max = tok.str;
00503          scan (TOK_RANGLE, &tok);
00504        }
00505     }
00506   if (streq (dec->type, "opaque"))
00507     {
00508       if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR)
00509        {
00510          error ("array declaration expected");
00511        }
00512     }
00513   else if (streq (dec->type, "string"))
00514     {
00515       if (dec->rel != REL_ARRAY)
00516        {
00517          error ("variable-length array declaration expected");
00518        }
00519     }
00520 }
00521 
00522 static void
00523 get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
00524 {
00525   token tok;
00526   char name[10];            /* argument name */
00527 
00528   if (dkind == DEF_PROGRAM)
00529     {
00530       peek (&tok);
00531       if (tok.kind == TOK_RPAREN)
00532        {                    /* no arguments */
00533          dec->rel = REL_ALIAS;
00534          dec->type = "void";
00535          dec->prefix = NULL;
00536          dec->name = NULL;
00537          return;
00538        }
00539     }
00540   get_type (&dec->prefix, &dec->type, dkind);
00541   dec->rel = REL_ALIAS;
00542   if (peekscan (TOK_IDENT, &tok))  /* optional name of argument */
00543     strcpy (name, tok.str);
00544   else
00545     sprintf (name, "%s%d", ARGNAME, num); /* default name of argument */
00546 
00547   dec->name = (char *) strdup (name);
00548 
00549   if (streq (dec->type, "void"))
00550     {
00551       return;
00552     }
00553 
00554   if (streq (dec->type, "opaque"))
00555     {
00556       error ("opaque -- illegal argument type");
00557     }
00558   if (peekscan (TOK_STAR, &tok))
00559     {
00560       if (streq (dec->type, "string"))
00561        {
00562          error ("pointer to string not allowed in program arguments\n");
00563        }
00564       dec->rel = REL_POINTER;
00565       if (peekscan (TOK_IDENT, &tok))     /* optional name of argument */
00566        dec->name = strdup (tok.str);
00567     }
00568   if (peekscan (TOK_LANGLE, &tok))
00569     {
00570       if (!streq (dec->type, "string"))
00571        {
00572          error ("arrays cannot be declared as arguments to procedures -- use typedef");
00573        }
00574       dec->rel = REL_ARRAY;
00575       if (peekscan (TOK_RANGLE, &tok))
00576        {
00577          dec->array_max = "~0";    /* unspecified size, use max */
00578        }
00579       else
00580        {
00581          scan_num (&tok);
00582          dec->array_max = tok.str;
00583          scan (TOK_RANGLE, &tok);
00584        }
00585     }
00586   if (streq (dec->type, "string"))
00587     {
00588       if (dec->rel != REL_ARRAY)
00589        {                    /* .x specifies just string as
00590                              * type of argument
00591                              * - make it string<>
00592                              */
00593          dec->rel = REL_ARRAY;
00594          dec->array_max = "~0";    /* unspecified size, use max */
00595        }
00596     }
00597 }
00598 
00599 static void
00600 get_type (const char **prefixp, const char **typep, defkind dkind)
00601 {
00602   token tok;
00603 
00604   *prefixp = NULL;
00605   get_token (&tok);
00606   switch (tok.kind)
00607     {
00608     case TOK_IDENT:
00609       *typep = tok.str;
00610       break;
00611     case TOK_STRUCT:
00612     case TOK_ENUM:
00613     case TOK_UNION:
00614       *prefixp = tok.str;
00615       scan (TOK_IDENT, &tok);
00616       *typep = tok.str;
00617       break;
00618     case TOK_UNSIGNED:
00619       unsigned_dec (typep);
00620       break;
00621     case TOK_SHORT:
00622       *typep = "short";
00623       (void) peekscan (TOK_INT, &tok);
00624       break;
00625     case TOK_LONG:
00626       *typep = "long";
00627       (void) peekscan (TOK_INT, &tok);
00628       break;
00629     case TOK_HYPER:
00630       *typep = "quad_t";
00631       (void) peekscan(TOK_INT, &tok);
00632       break;
00633     case TOK_VOID:
00634       if (dkind != DEF_UNION && dkind != DEF_PROGRAM)
00635        {
00636          error ("voids allowed only inside union and program definitions with one argument");
00637        }
00638       *typep = tok.str;
00639       break;
00640     case TOK_STRING:
00641     case TOK_OPAQUE:
00642     case TOK_CHAR:
00643     case TOK_INT:
00644     case TOK_FLOAT:
00645     case TOK_DOUBLE:
00646     case TOK_BOOL:
00647       *typep = tok.str;
00648       break;
00649     default:
00650       error ("expected type specifier");
00651     }
00652 }
00653 
00654 static void
00655 unsigned_dec (const char **typep)
00656 {
00657   token tok;
00658 
00659   peek (&tok);
00660   switch (tok.kind)
00661     {
00662     case TOK_CHAR:
00663       get_token (&tok);
00664       *typep = "u_char";
00665       break;
00666     case TOK_SHORT:
00667       get_token (&tok);
00668       *typep = "u_short";
00669       (void) peekscan (TOK_INT, &tok);
00670       break;
00671     case TOK_LONG:
00672       get_token (&tok);
00673       *typep = "u_long";
00674       (void) peekscan (TOK_INT, &tok);
00675       break;
00676     case TOK_HYPER:
00677       get_token (&tok);
00678       *typep = "u_quad_t";
00679       (void) peekscan(TOK_INT, &tok);
00680       break;
00681     case TOK_INT:
00682       get_token (&tok);
00683       *typep = "u_int";
00684       break;
00685     default:
00686       *typep = "u_int";
00687       break;
00688     }
00689 }