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