Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / rpcgen / 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.
8  * 
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  * 
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  * 
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  * 
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  * 
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  *
29  * $FreeBSD: src/usr.bin/rpcgen/rpc_scan.c,v 1.4.8.1 2001/03/04 08:59:50 kris Exp $
30  * $DragonFly: src/usr.bin/rpcgen/rpc_scan.c,v 1.2 2003/06/17 04:29:31 dillon Exp $
31  *
32  * @(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI
33  */
34
35 #ident  "@(#)rpc_scan.c 1.13    93/07/05 SMI"
36
37 /*
38  * rpc_scan.c, Scanner for the RPC protocol compiler 
39  * Copyright (C) 1987, Sun Microsystems, Inc. 
40  */
41
42 #include <sys/types.h>
43
44 #include <sys/wait.h>
45 #include <stdio.h>
46 #include <ctype.h>
47 #include <string.h>
48 #include "rpc_scan.h"
49 #include "rpc_parse.h"
50 #include "rpc_util.h"
51
52 #define startcomment(where) (where[0] == '/' && where[1] == '*')
53 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
54
55 static int pushed = 0;  /* is a token pushed */
56 static token lasttok;   /* last token, if pushed */
57
58 static void unget_token __P(( token * ));
59 static void findstrconst __P(( char **, char **));
60 static void findchrconst __P(( char **, char **));
61 static void findconst __P(( char **, char **));
62 static void findkind __P(( char **, token * ));
63 static int cppline __P(( char * ));
64 static int directive __P(( char * ));
65 static void printdirective __P(( char * ));
66 static void docppline __P(( char *, int *, char ** ));
67
68 /*
69  * scan expecting 1 given token 
70  */
71 void
72 scan(expect, tokp)
73         tok_kind expect;
74         token *tokp;
75 {
76         get_token(tokp);
77         if (tokp->kind != expect) {
78                 expected1(expect);
79         }
80 }
81
82 /*
83  * scan expecting any of the 2 given tokens 
84  */
85 void
86 scan2(expect1, expect2, tokp)
87         tok_kind expect1;
88         tok_kind expect2;
89         token *tokp;
90 {
91         get_token(tokp);
92         if (tokp->kind != expect1 && tokp->kind != expect2) {
93                 expected2(expect1, expect2);
94         }
95 }
96
97 /*
98  * scan expecting any of the 3 given token 
99  */
100 void
101 scan3(expect1, expect2, expect3, tokp)
102         tok_kind expect1;
103         tok_kind expect2;
104         tok_kind expect3;
105         token *tokp;
106 {
107         get_token(tokp);
108         if (tokp->kind != expect1 && tokp->kind != expect2
109             && tokp->kind != expect3) {
110                 expected3(expect1, expect2, expect3);
111         }
112 }
113
114 /*
115  * scan expecting a constant, possibly symbolic 
116  */
117 void
118 scan_num(tokp)
119         token *tokp;
120 {
121         get_token(tokp);
122         switch (tokp->kind) {
123         case TOK_IDENT:
124                 break;
125         default:
126                 error("constant or identifier expected");
127         }
128 }
129
130 /*
131  * Peek at the next token 
132  */
133 void
134 peek(tokp)
135         token *tokp;
136 {
137         get_token(tokp);
138         unget_token(tokp);
139 }
140
141 /*
142  * Peek at the next token and scan it if it matches what you expect 
143  */
144 int
145 peekscan(expect, tokp)
146         tok_kind expect;
147         token *tokp;
148 {
149         peek(tokp);
150         if (tokp->kind == expect) {
151                 get_token(tokp);
152                 return (1);
153         }
154         return (0);
155 }
156
157 /*
158  * Get the next token, printing out any directive that are encountered. 
159  */
160 void
161 get_token(tokp)
162         token *tokp;
163 {
164         int commenting;
165         int stat = 0;
166         
167         
168         if (pushed) {
169                 pushed = 0;
170                 *tokp = lasttok;
171                 return;
172         }
173         commenting = 0;
174         for (;;) {
175                 if (*where == 0) {
176                         for (;;) {
177                                 if (!fgets(curline, MAXLINESIZE, fin)) {
178                                         tokp->kind = TOK_EOF;
179                                         /* now check if cpp returned non NULL value */
180                                         waitpid(childpid, &stat, WUNTRACED);
181                                         if (stat > 0) {
182                                         /* Set return value from rpcgen */
183                                                 nonfatalerrors = stat >> 8;
184                                         }
185                                         *where = 0;
186                                         return;
187                                 }
188                                 linenum++;
189                                 if (commenting) {
190                                         break;
191                                 } else if (cppline(curline)) {
192                                         docppline(curline, &linenum, 
193                                                   &infilename);
194                                 } else if (directive(curline)) {
195                                         printdirective(curline);
196                                 } else {
197                                         break;
198                                 }
199                         }
200                         where = curline;
201                 } else if (isspace(*where)) {
202                         while (isspace(*where)) {
203                                 where++;        /* eat */
204                         }
205                 } else if (commenting) {
206                         for (where++; *where; where++) {
207                                 if (endcomment(where)) {
208                                         where++;
209                                         commenting--;
210                                         break;
211                                 }
212                         }
213                 } else if (startcomment(where)) {
214                         where += 2;
215                         commenting++;
216                 } else {
217                         break;
218                 }
219         }
220
221         /*
222          * 'where' is not whitespace, comment or directive Must be a token! 
223          */
224         switch (*where) {
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                         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                                 s_print(p, "%c", *where);
311                         } else {
312                                 s_print(p, "%d", *where);
313                         }
314                         error(buf);
315                 }
316                 findkind(&where, tokp);
317                 break;
318         }
319 }
320
321 static void
322 unget_token(tokp)
323         token *tokp;
324 {
325         lasttok = *tokp;
326         pushed = 1;
327 }
328
329 static void
330 findstrconst(str, val)
331         char **str;
332         char **val;
333 {
334         char *p;
335         int size;
336
337         p = *str;
338         do {
339                 p++;
340         } while (*p && *p != '"');
341         if (*p == 0) {
342                 error("unterminated string constant");
343         }
344         p++;
345         size = p - *str;
346         *val = alloc(size + 1);
347         (void) strncpy(*val, *str, size);
348         (*val)[size] = 0;
349         *str = p;
350 }
351
352 static void
353 findchrconst(str, val)
354         char **str;
355         char **val;
356 {
357         char *p;
358         int size;
359
360         p = *str;
361         do {
362                 p++;
363         } while (*p && *p != '\'');
364         if (*p == 0) {
365                 error("unterminated string constant");
366         }
367         p++;
368         size = p - *str;
369         if (size != 3) {
370                 error("empty char string");
371         }
372         *val = alloc(size + 1);
373         (void) strncpy(*val, *str, size);
374         (*val)[size] = 0;
375         *str = p;
376 }
377
378 static void
379 findconst(str, val)
380         char **str;
381         char **val;
382 {
383         char *p;
384         int size;
385
386         p = *str;
387         if (*p == '0' && *(p + 1) == 'x') {
388                 p++;
389                 do {
390                         p++;
391                 } while (isxdigit(*p));
392         } else {
393                 do {
394                         p++;
395                 } while (isdigit(*p));
396         }
397         size = p - *str;
398         *val = alloc(size + 1);
399         (void) strncpy(*val, *str, size);
400         (*val)[size] = 0;
401         *str = p;
402 }
403
404 static token symbols[] = {
405                           {TOK_CONST, "const"},
406                           {TOK_UNION, "union"},
407                           {TOK_SWITCH, "switch"},
408                           {TOK_CASE, "case"},
409                           {TOK_DEFAULT, "default"},
410                           {TOK_STRUCT, "struct"},
411                           {TOK_TYPEDEF, "typedef"},
412                           {TOK_ENUM, "enum"},
413                           {TOK_OPAQUE, "opaque"},
414                           {TOK_BOOL, "bool"},
415                           {TOK_VOID, "void"},
416                           {TOK_CHAR, "char"},
417                           {TOK_INT, "int"},
418                           {TOK_UNSIGNED, "unsigned"},
419                           {TOK_SHORT, "short"},
420                           {TOK_LONG, "long"},
421                           {TOK_HYPER, "hyper"},
422                           {TOK_FLOAT, "float"},
423                           {TOK_DOUBLE, "double"},
424                           {TOK_QUAD, "quadruple"},
425                           {TOK_STRING, "string"},
426                           {TOK_PROGRAM, "program"},
427                           {TOK_VERSION, "version"},
428                           {TOK_EOF, "??????"},
429 };
430
431 static void
432 findkind(mark, tokp)
433         char **mark;
434         token *tokp;
435 {
436         int len;
437         token *s;
438         char *str;
439
440         str = *mark;
441         for (s = symbols; s->kind != TOK_EOF; s++) {
442                 len = strlen(s->str);
443                 if (strncmp(str, s->str, len) == 0) {
444                         if (!isalnum(str[len]) && str[len] != '_') {
445                                 tokp->kind = s->kind;
446                                 tokp->str = s->str;
447                                 *mark = str + len;
448                                 return;
449                         }
450                 }
451         }
452         tokp->kind = TOK_IDENT;
453         for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
454         tokp->str = alloc(len + 1);
455         (void) strncpy(tokp->str, str, len);
456         tokp->str[len] = 0;
457         *mark = str + len;
458 }
459
460 static int
461 cppline(line)
462         char *line;
463 {
464         return (line == curline && *line == '#');
465 }
466
467 static int
468 directive(line)
469         char *line;
470 {
471         return (line == curline && *line == '%');
472 }
473
474 static void
475 printdirective(line)
476         char *line;
477 {
478         f_print(fout, "%s", line + 1);
479 }
480
481 static void
482 docppline(line, lineno, fname)
483         char *line;
484         int *lineno;
485         char **fname;
486 {
487         char *file;
488         int num;
489         char *p;
490
491         line++;
492         while (isspace(*line)) {
493                 line++;
494         }
495         num = atoi(line);
496         while (isdigit(*line)) {
497                 line++;
498         }
499         while (isspace(*line)) {
500                 line++;
501         }
502         if (*line != '"') {
503                 error("preprocessor error");
504         }
505         line++;
506         p = file = alloc(strlen(line) + 1);
507         while (*line && *line != '"') {
508                 *p++ = *line++;
509         }
510         if (*line == 0) {
511                 error("preprocessor error");
512         }
513         *p = 0;
514         if (*file == 0) {
515                 *fname = NULL;
516         } else {
517                 *fname = file;
518         }
519         *lineno = num - 1;
520 }