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