* sunrpc/etc.rpc (fedfs_admin): Add entry.
[platform/upstream/glibc.git] / sunrpc / rpc_scan.c
1 /*
2  * From: @(#)rpc_scan.c 1.11 89/02/22
3  *
4  * Copyright (c) 2010, Oracle America, Inc.
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials
14  *       provided with the distribution.
15  *     * Neither the name of the "Oracle America, Inc." nor the names of its
16  *       contributors may be used to endorse or promote products derived
17  *       from this software without specific prior written permission.
18  *
19  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * rpc_scan.c, Scanner for the RPC protocol compiler
35  * Copyright (C) 1987, Sun Microsystems, Inc.
36  */
37 #include <stdio.h>
38 #include <ctype.h>
39 #include <string.h>
40 #include <libintl.h>
41 #include "rpc_scan.h"
42 #include "rpc_parse.h"
43 #include "rpc_util.h"
44 #include "proto.h"
45
46 #define startcomment(where) (where[0] == '/' && where[1] == '*')
47 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
48
49 static int pushed = 0;          /* is a token pushed */
50 static token lasttok;           /* last token, if pushed */
51
52 static void unget_token (token * tokp);
53 static void findstrconst (const char **str, const char **val);
54 static void findchrconst (const char **str, const char **val);
55 static void findconst (const char **str, const char **val);
56 static void findkind (const char **mark, token * tokp);
57 static int cppline (const char *line);
58 static int directive (const char *line);
59 static void printdirective (const char *line);
60 static void docppline (const char *line, int *lineno, const char **fname);
61
62 /*
63  * scan expecting 1 given token
64  */
65 void
66 scan (tok_kind expect, token * tokp)
67 {
68   get_token (tokp);
69   if (tokp->kind != expect)
70     expected1 (expect);
71 }
72
73 /*
74  * scan expecting any of the 2 given tokens
75  */
76 void
77 scan2 (tok_kind expect1, tok_kind expect2, token * tokp)
78 {
79   get_token (tokp);
80   if (tokp->kind != expect1 && tokp->kind != expect2)
81     {
82       expected2 (expect1, expect2);
83     }
84 }
85
86 /*
87  * scan expecting any of the 3 given token
88  */
89 void
90 scan3 (tok_kind expect1, tok_kind expect2, tok_kind expect3, token * tokp)
91 {
92   get_token (tokp);
93   if (tokp->kind != expect1 && tokp->kind != expect2
94       && tokp->kind != expect3)
95     {
96       expected3 (expect1, expect2, expect3);
97     }
98 }
99
100 /*
101  * scan expecting a constant, possibly symbolic
102  */
103 void
104 scan_num (token *tokp)
105 {
106   get_token (tokp);
107   switch (tokp->kind)
108     {
109     case TOK_IDENT:
110       break;
111     default:
112       error (_("constant or identifier expected"));
113     }
114 }
115
116 /*
117  * Peek at the next token
118  */
119 void
120 peek (token *tokp)
121 {
122   get_token (tokp);
123   unget_token (tokp);
124 }
125
126 /*
127  * Peek at the next token and scan it if it matches what you expect
128  */
129 int
130 peekscan (tok_kind expect, token *tokp)
131 {
132   peek (tokp);
133   if (tokp->kind == expect)
134     {
135       get_token (tokp);
136       return 1;
137     }
138   return 0;
139 }
140
141 /*
142  * Get the next token, printing out any directive that are encountered.
143  */
144 void
145 get_token (token *tokp)
146 {
147   int commenting;
148
149   if (pushed)
150     {
151       pushed = 0;
152       *tokp = lasttok;
153       return;
154     }
155   commenting = 0;
156   for (;;)
157     {
158       if (*where == 0)
159         {
160           for (;;)
161             {
162               if (!fgets (curline, MAXLINESIZE, fin))
163                 {
164                   tokp->kind = TOK_EOF;
165                   *curline = 0;
166                   where = curline;
167                   return;
168                 }
169               linenum++;
170               if (commenting)
171                 {
172                   break;
173                 }
174               else if (cppline (curline))
175                 {
176                   docppline (curline, &linenum,
177                              &infilename);
178                 }
179               else if (directive (curline))
180                 {
181                   printdirective (curline);
182                 }
183               else
184                 {
185                   break;
186                 }
187             }
188           where = curline;
189         }
190       else if (isspace (*where))
191         {
192           while (isspace (*where))
193             {
194               where++;          /* eat */
195             }
196         }
197       else if (commenting)
198         {
199           for (where++; *where; where++)
200             {
201               if (endcomment (where))
202                 {
203                   where++;
204                   commenting--;
205                   break;
206                 }
207             }
208         }
209       else if (startcomment (where))
210         {
211           where += 2;
212           commenting++;
213         }
214       else
215         {
216           break;
217         }
218     }
219
220   /*
221    * 'where' is not whitespace, comment or directive Must be a token!
222    */
223   switch (*where)
224     {
225     case ':':
226       tokp->kind = TOK_COLON;
227       where++;
228       break;
229     case ';':
230       tokp->kind = TOK_SEMICOLON;
231       where++;
232       break;
233     case ',':
234       tokp->kind = TOK_COMMA;
235       where++;
236       break;
237     case '=':
238       tokp->kind = TOK_EQUAL;
239       where++;
240       break;
241     case '*':
242       tokp->kind = TOK_STAR;
243       where++;
244       break;
245     case '[':
246       tokp->kind = TOK_LBRACKET;
247       where++;
248       break;
249     case ']':
250       tokp->kind = TOK_RBRACKET;
251       where++;
252       break;
253     case '{':
254       tokp->kind = TOK_LBRACE;
255       where++;
256       break;
257     case '}':
258       tokp->kind = TOK_RBRACE;
259       where++;
260       break;
261     case '(':
262       tokp->kind = TOK_LPAREN;
263       where++;
264       break;
265     case ')':
266       tokp->kind = TOK_RPAREN;
267       where++;
268       break;
269     case '<':
270       tokp->kind = TOK_LANGLE;
271       where++;
272       break;
273     case '>':
274       tokp->kind = TOK_RANGLE;
275       where++;
276       break;
277
278     case '"':
279       tokp->kind = TOK_STRCONST;
280       findstrconst (&where, &tokp->str);
281       break;
282     case '\'':
283       tokp->kind = TOK_CHARCONST;
284       findchrconst (&where, &tokp->str);
285       break;
286
287     case '-':
288     case '0':
289     case '1':
290     case '2':
291     case '3':
292     case '4':
293     case '5':
294     case '6':
295     case '7':
296     case '8':
297     case '9':
298       tokp->kind = TOK_IDENT;
299       findconst (&where, &tokp->str);
300       break;
301
302     default:
303       if (!(isalpha (*where) || *where == '_'))
304         {
305           char buf[100];
306           char *p;
307
308           s_print (buf, _("illegal character in file: "));
309           p = buf + strlen (buf);
310           if (isprint (*where))
311             {
312               s_print (p, "%c", *where);
313             }
314           else
315             {
316               s_print (p, "%d", *where);
317             }
318           error (buf);
319         }
320       findkind (&where, tokp);
321       break;
322     }
323 }
324
325 static void
326 unget_token (token * tokp)
327 {
328   lasttok = *tokp;
329   pushed = 1;
330 }
331
332 static void
333 findstrconst (const char **str, const char **val)
334 {
335   const char *p;
336   char *tmp;
337   int size;
338
339   p = *str;
340   do
341     {
342       p++;
343     }
344   while (*p && *p != '"');
345   if (*p == 0)
346     {
347       error (_("unterminated string constant"));
348     }
349   p++;
350   size = p - *str;
351   tmp = alloc (size + 1);
352   strncpy (tmp, *str, size);
353   tmp[size] = 0;
354   *val = tmp;
355   *str = p;
356 }
357
358 static void
359 findchrconst (const char **str, const char **val)
360 {
361   const char *p;
362   char *tmp;
363   int size;
364
365   p = *str;
366   do
367     {
368       p++;
369     }
370   while (*p && *p != '\'');
371   if (*p == 0)
372     {
373       error (_("unterminated string constant"));
374     }
375   p++;
376   size = p - *str;
377   if (size != 3)
378     {
379       error (_("empty char string"));
380     }
381   tmp = alloc (size + 1);
382   strncpy (tmp, *str, size);
383   tmp[size] = 0;
384   *val = tmp;
385   *str = p;
386 }
387
388 static void
389 findconst (const char **str, const char **val)
390 {
391   const char *p;
392   char *tmp;
393   int size;
394
395   p = *str;
396   if (*p == '0' && *(p + 1) == 'x')
397     {
398       p++;
399       do
400         {
401           p++;
402         }
403       while (isxdigit (*p));
404     }
405   else
406     {
407       do
408         {
409           p++;
410         }
411       while (isdigit (*p));
412     }
413   size = p - *str;
414   tmp = alloc (size + 1);
415   strncpy (tmp, *str, size);
416   tmp[size] = 0;
417   *val = tmp;
418   *str = p;
419 }
420
421 static const token symbols[] =
422 {
423   {TOK_CONST, "const"},
424   {TOK_UNION, "union"},
425   {TOK_SWITCH, "switch"},
426   {TOK_CASE, "case"},
427   {TOK_DEFAULT, "default"},
428   {TOK_STRUCT, "struct"},
429   {TOK_TYPEDEF, "typedef"},
430   {TOK_ENUM, "enum"},
431   {TOK_OPAQUE, "opaque"},
432   {TOK_BOOL, "bool"},
433   {TOK_VOID, "void"},
434   {TOK_CHAR, "char"},
435   {TOK_INT, "int"},
436   {TOK_UNSIGNED, "unsigned"},
437   {TOK_SHORT, "short"},
438   {TOK_LONG, "long"},
439   {TOK_HYPER, "hyper"},
440   {TOK_FLOAT, "float"},
441   {TOK_DOUBLE, "double"},
442   {TOK_STRING, "string"},
443   {TOK_PROGRAM, "program"},
444   {TOK_VERSION, "version"},
445   {TOK_EOF, "??????"},
446 };
447
448 static void
449 findkind (const char **mark, token *tokp)
450 {
451   int len;
452   const token *s;
453   const char *str;
454   char *tmp;
455
456   str = *mark;
457   for (s = symbols; s->kind != TOK_EOF; s++)
458     {
459       len = strlen (s->str);
460       if (strncmp (str, s->str, len) == 0)
461         {
462           if (!isalnum (str[len]) && str[len] != '_')
463             {
464               tokp->kind = s->kind;
465               tokp->str = s->str;
466               *mark = str + len;
467               return;
468             }
469         }
470     }
471   tokp->kind = TOK_IDENT;
472   for (len = 0; isalnum (str[len]) || str[len] == '_'; len++);
473   tmp = alloc (len + 1);
474   strncpy (tmp, str, len);
475   tmp[len] = 0;
476   tokp->str = tmp;
477   *mark = str + len;
478 }
479
480 static int
481 cppline (const char *line)
482 {
483   return line == curline && *line == '#';
484 }
485
486 static int
487 directive (const char *line)
488 {
489   return line == curline && *line == '%';
490 }
491
492 static void
493 printdirective (const char *line)
494 {
495   f_print (fout, "%s", line + 1);
496 }
497
498 static void
499 docppline (const char *line, int *lineno, const char **fname)
500 {
501   char *file;
502   int num;
503   char *p;
504
505   line++;
506   while (isspace (*line))
507     {
508       line++;
509     }
510   num = atoi (line);
511   while (isdigit (*line))
512     {
513       line++;
514     }
515   while (isspace (*line))
516     {
517       line++;
518     }
519   if (*line != '"')
520     {
521       error (_("preprocessor error"));
522     }
523   line++;
524   p = file = alloc (strlen (line) + 1);
525   while (*line && *line != '"')
526     {
527       *p++ = *line++;
528     }
529   if (*line == 0)
530     {
531       error (_("preprocessor error"));
532     }
533   *p = 0;
534   if (*file == 0)
535     {
536       free (file);
537       *fname = NULL;
538     }
539   else
540     {
541       *fname = file;
542     }
543   *lineno = num - 1;
544 }