Back to index

glibc  2.9
rpc_scan.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_scan.c 1.11 89/02/22 (C) 1987 SMI
00033  */
00034 
00035 /*
00036  * rpc_scan.c, Scanner for the RPC protocol compiler
00037  * Copyright (C) 1987, Sun Microsystems, Inc.
00038  */
00039 #include <stdio.h>
00040 #include <ctype.h>
00041 #include <string.h>
00042 #include <libintl.h>
00043 #include "rpc_scan.h"
00044 #include "rpc_parse.h"
00045 #include "rpc_util.h"
00046 #include "proto.h"
00047 
00048 #define startcomment(where) (where[0] == '/' && where[1] == '*')
00049 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
00050 
00051 static int pushed = 0;             /* is a token pushed */
00052 static token lasttok;              /* last token, if pushed */
00053 
00054 static void unget_token (token * tokp);
00055 static void findstrconst (const char **str, const char **val);
00056 static void findchrconst (const char **str, const char **val);
00057 static void findconst (const char **str, const char **val);
00058 static void findkind (const char **mark, token * tokp);
00059 static int cppline (const char *line);
00060 static int directive (const char *line);
00061 static void printdirective (const char *line);
00062 static void docppline (const char *line, int *lineno, const char **fname);
00063 
00064 /*
00065  * scan expecting 1 given token
00066  */
00067 void
00068 scan (tok_kind expect, token * tokp)
00069 {
00070   get_token (tokp);
00071   if (tokp->kind != expect)
00072     expected1 (expect);
00073 }
00074 
00075 /*
00076  * scan expecting any of the 2 given tokens
00077  */
00078 void
00079 scan2 (tok_kind expect1, tok_kind expect2, token * tokp)
00080 {
00081   get_token (tokp);
00082   if (tokp->kind != expect1 && tokp->kind != expect2)
00083     {
00084       expected2 (expect1, expect2);
00085     }
00086 }
00087 
00088 /*
00089  * scan expecting any of the 3 given token
00090  */
00091 void
00092 scan3 (tok_kind expect1, tok_kind expect2, tok_kind expect3, token * tokp)
00093 {
00094   get_token (tokp);
00095   if (tokp->kind != expect1 && tokp->kind != expect2
00096       && tokp->kind != expect3)
00097     {
00098       expected3 (expect1, expect2, expect3);
00099     }
00100 }
00101 
00102 /*
00103  * scan expecting a constant, possibly symbolic
00104  */
00105 void
00106 scan_num (token *tokp)
00107 {
00108   get_token (tokp);
00109   switch (tokp->kind)
00110     {
00111     case TOK_IDENT:
00112       break;
00113     default:
00114       error (_("constant or identifier expected"));
00115     }
00116 }
00117 
00118 /*
00119  * Peek at the next token
00120  */
00121 void
00122 peek (token *tokp)
00123 {
00124   get_token (tokp);
00125   unget_token (tokp);
00126 }
00127 
00128 /*
00129  * Peek at the next token and scan it if it matches what you expect
00130  */
00131 int
00132 peekscan (tok_kind expect, token *tokp)
00133 {
00134   peek (tokp);
00135   if (tokp->kind == expect)
00136     {
00137       get_token (tokp);
00138       return 1;
00139     }
00140   return 0;
00141 }
00142 
00143 /*
00144  * Get the next token, printing out any directive that are encountered.
00145  */
00146 void
00147 get_token (token *tokp)
00148 {
00149   int commenting;
00150 
00151   if (pushed)
00152     {
00153       pushed = 0;
00154       *tokp = lasttok;
00155       return;
00156     }
00157   commenting = 0;
00158   for (;;)
00159     {
00160       if (*where == 0)
00161        {
00162          for (;;)
00163            {
00164              if (!fgets (curline, MAXLINESIZE, fin))
00165               {
00166                 tokp->kind = TOK_EOF;
00167                 *curline = 0;
00168                 where = curline;
00169                 return;
00170               }
00171              linenum++;
00172              if (commenting)
00173               {
00174                 break;
00175               }
00176              else if (cppline (curline))
00177               {
00178                 docppline (curline, &linenum,
00179                           &infilename);
00180               }
00181              else if (directive (curline))
00182               {
00183                 printdirective (curline);
00184               }
00185              else
00186               {
00187                 break;
00188               }
00189            }
00190          where = curline;
00191        }
00192       else if (isspace (*where))
00193        {
00194          while (isspace (*where))
00195            {
00196              where++;              /* eat */
00197            }
00198        }
00199       else if (commenting)
00200        {
00201          for (where++; *where; where++)
00202            {
00203              if (endcomment (where))
00204               {
00205                 where++;
00206                 commenting--;
00207                 break;
00208               }
00209            }
00210        }
00211       else if (startcomment (where))
00212        {
00213          where += 2;
00214          commenting++;
00215        }
00216       else
00217        {
00218          break;
00219        }
00220     }
00221 
00222   /*
00223    * 'where' is not whitespace, comment or directive Must be a token!
00224    */
00225   switch (*where)
00226     {
00227     case ':':
00228       tokp->kind = TOK_COLON;
00229       where++;
00230       break;
00231     case ';':
00232       tokp->kind = TOK_SEMICOLON;
00233       where++;
00234       break;
00235     case ',':
00236       tokp->kind = TOK_COMMA;
00237       where++;
00238       break;
00239     case '=':
00240       tokp->kind = TOK_EQUAL;
00241       where++;
00242       break;
00243     case '*':
00244       tokp->kind = TOK_STAR;
00245       where++;
00246       break;
00247     case '[':
00248       tokp->kind = TOK_LBRACKET;
00249       where++;
00250       break;
00251     case ']':
00252       tokp->kind = TOK_RBRACKET;
00253       where++;
00254       break;
00255     case '{':
00256       tokp->kind = TOK_LBRACE;
00257       where++;
00258       break;
00259     case '}':
00260       tokp->kind = TOK_RBRACE;
00261       where++;
00262       break;
00263     case '(':
00264       tokp->kind = TOK_LPAREN;
00265       where++;
00266       break;
00267     case ')':
00268       tokp->kind = TOK_RPAREN;
00269       where++;
00270       break;
00271     case '<':
00272       tokp->kind = TOK_LANGLE;
00273       where++;
00274       break;
00275     case '>':
00276       tokp->kind = TOK_RANGLE;
00277       where++;
00278       break;
00279 
00280     case '"':
00281       tokp->kind = TOK_STRCONST;
00282       findstrconst (&where, &tokp->str);
00283       break;
00284     case '\'':
00285       tokp->kind = TOK_CHARCONST;
00286       findchrconst (&where, &tokp->str);
00287       break;
00288 
00289     case '-':
00290     case '0':
00291     case '1':
00292     case '2':
00293     case '3':
00294     case '4':
00295     case '5':
00296     case '6':
00297     case '7':
00298     case '8':
00299     case '9':
00300       tokp->kind = TOK_IDENT;
00301       findconst (&where, &tokp->str);
00302       break;
00303 
00304     default:
00305       if (!(isalpha (*where) || *where == '_'))
00306        {
00307          char buf[100];
00308          char *p;
00309 
00310          s_print (buf, _("illegal character in file: "));
00311          p = buf + strlen (buf);
00312          if (isprint (*where))
00313            {
00314              s_print (p, "%c", *where);
00315            }
00316          else
00317            {
00318              s_print (p, "%d", *where);
00319            }
00320          error (buf);
00321        }
00322       findkind (&where, tokp);
00323       break;
00324     }
00325 }
00326 
00327 static void
00328 unget_token (token * tokp)
00329 {
00330   lasttok = *tokp;
00331   pushed = 1;
00332 }
00333 
00334 static void
00335 findstrconst (const char **str, const char **val)
00336 {
00337   const char *p;
00338   char *tmp;
00339   int size;
00340 
00341   p = *str;
00342   do
00343     {
00344       p++;
00345     }
00346   while (*p && *p != '"');
00347   if (*p == 0)
00348     {
00349       error (_("unterminated string constant"));
00350     }
00351   p++;
00352   size = p - *str;
00353   tmp = alloc (size + 1);
00354   strncpy (tmp, *str, size);
00355   tmp[size] = 0;
00356   *val = tmp;
00357   *str = p;
00358 }
00359 
00360 static void
00361 findchrconst (const char **str, const char **val)
00362 {
00363   const char *p;
00364   char *tmp;
00365   int size;
00366 
00367   p = *str;
00368   do
00369     {
00370       p++;
00371     }
00372   while (*p && *p != '\'');
00373   if (*p == 0)
00374     {
00375       error (_("unterminated string constant"));
00376     }
00377   p++;
00378   size = p - *str;
00379   if (size != 3)
00380     {
00381       error (_("empty char string"));
00382     }
00383   tmp = alloc (size + 1);
00384   strncpy (tmp, *str, size);
00385   tmp[size] = 0;
00386   *val = tmp;
00387   *str = p;
00388 }
00389 
00390 static void
00391 findconst (const char **str, const char **val)
00392 {
00393   const char *p;
00394   char *tmp;
00395   int size;
00396 
00397   p = *str;
00398   if (*p == '0' && *(p + 1) == 'x')
00399     {
00400       p++;
00401       do
00402        {
00403          p++;
00404        }
00405       while (isxdigit (*p));
00406     }
00407   else
00408     {
00409       do
00410        {
00411          p++;
00412        }
00413       while (isdigit (*p));
00414     }
00415   size = p - *str;
00416   tmp = alloc (size + 1);
00417   strncpy (tmp, *str, size);
00418   tmp[size] = 0;
00419   *val = tmp;
00420   *str = p;
00421 }
00422 
00423 static const token symbols[] =
00424 {
00425   {TOK_CONST, "const"},
00426   {TOK_UNION, "union"},
00427   {TOK_SWITCH, "switch"},
00428   {TOK_CASE, "case"},
00429   {TOK_DEFAULT, "default"},
00430   {TOK_STRUCT, "struct"},
00431   {TOK_TYPEDEF, "typedef"},
00432   {TOK_ENUM, "enum"},
00433   {TOK_OPAQUE, "opaque"},
00434   {TOK_BOOL, "bool"},
00435   {TOK_VOID, "void"},
00436   {TOK_CHAR, "char"},
00437   {TOK_INT, "int"},
00438   {TOK_UNSIGNED, "unsigned"},
00439   {TOK_SHORT, "short"},
00440   {TOK_LONG, "long"},
00441   {TOK_HYPER, "hyper"},
00442   {TOK_FLOAT, "float"},
00443   {TOK_DOUBLE, "double"},
00444   {TOK_STRING, "string"},
00445   {TOK_PROGRAM, "program"},
00446   {TOK_VERSION, "version"},
00447   {TOK_EOF, "??????"},
00448 };
00449 
00450 static void
00451 findkind (const char **mark, token *tokp)
00452 {
00453   int len;
00454   const token *s;
00455   const char *str;
00456   char *tmp;
00457 
00458   str = *mark;
00459   for (s = symbols; s->kind != TOK_EOF; s++)
00460     {
00461       len = strlen (s->str);
00462       if (strncmp (str, s->str, len) == 0)
00463        {
00464          if (!isalnum (str[len]) && str[len] != '_')
00465            {
00466              tokp->kind = s->kind;
00467              tokp->str = s->str;
00468              *mark = str + len;
00469              return;
00470            }
00471        }
00472     }
00473   tokp->kind = TOK_IDENT;
00474   for (len = 0; isalnum (str[len]) || str[len] == '_'; len++);
00475   tmp = alloc (len + 1);
00476   strncpy (tmp, str, len);
00477   tmp[len] = 0;
00478   tokp->str = tmp;
00479   *mark = str + len;
00480 }
00481 
00482 static int
00483 cppline (const char *line)
00484 {
00485   return line == curline && *line == '#';
00486 }
00487 
00488 static int
00489 directive (const char *line)
00490 {
00491   return line == curline && *line == '%';
00492 }
00493 
00494 static void
00495 printdirective (const char *line)
00496 {
00497   f_print (fout, "%s", line + 1);
00498 }
00499 
00500 static void
00501 docppline (const char *line, int *lineno, const char **fname)
00502 {
00503   char *file;
00504   int num;
00505   char *p;
00506 
00507   line++;
00508   while (isspace (*line))
00509     {
00510       line++;
00511     }
00512   num = atoi (line);
00513   while (isdigit (*line))
00514     {
00515       line++;
00516     }
00517   while (isspace (*line))
00518     {
00519       line++;
00520     }
00521   if (*line != '"')
00522     {
00523       error (_("preprocessor error"));
00524     }
00525   line++;
00526   p = file = alloc (strlen (line) + 1);
00527   while (*line && *line != '"')
00528     {
00529       *p++ = *line++;
00530     }
00531   if (*line == 0)
00532     {
00533       error (_("preprocessor error"));
00534     }
00535   *p = 0;
00536   if (*file == 0)
00537     {
00538       free (file);
00539       *fname = NULL;
00540     }
00541   else
00542     {
00543       *fname = file;
00544     }
00545   *lineno = num - 1;
00546 }