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