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