1 /* @(#)rpc_scan.c 1.1 87/11/04 3.9 RPCSRC */
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.
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.
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.
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.
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.
26 * Sun Microsystems, Inc.
28 * Mountain View, California 94043
32 * rpc_scan.c, Scanner for the RPC protocol compiler
33 * Copyright (C) 1987, Sun Microsystems, Inc.
36 /* Portions Copyright (c) 2003 Apple Computer, Inc. */
37 #include <afsconfig.h>
38 #include <afs/param.h>
45 #include "rpc_parse.h"
48 #define startcomment(where) (where[0] == '/' && where[1] == '*')
49 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
50 #define verbatimstart(p) (*(p) == '@' && *((p) + 1) == '{')
51 #define verbatimend(p) (*(p) == '@' && *((p) + 1) == '}')
53 int pushed
= 0; /* is a token pushed */
54 token lasttok
; /* last token, if pushed */
57 /* static prototypes */
58 static void findstrconst(char **str
, char **val
);
59 static void findconst(char **str
, char **val
);
60 static int cppline(char *line
);
61 static int directive(char *line
);
62 static void docppline(char *line
, int *lineno
, char **fname
);
64 static void deverbatim(void);
69 * scan expecting 1 given token
72 scan(tok_kind expect
, token
* tokp
)
75 if (tokp
->kind
!= expect
) {
81 * scan expecting 2 given tokens
84 scan2(tok_kind expect1
, tok_kind expect2
, token
* tokp
)
87 if (tokp
->kind
!= expect1
&& tokp
->kind
!= expect2
) {
88 expected2(expect1
, expect2
);
93 * scan expecting 3 given token
96 scan3(tok_kind expect1
, tok_kind expect2
, tok_kind expect3
, token
* tokp
)
99 if (tokp
->kind
!= expect1
&& tokp
->kind
!= expect2
100 && tokp
->kind
!= expect3
) {
101 expected3(expect1
, expect2
, expect3
);
107 * scan expecting 4 given token
110 scan4(tok_kind expect1
, tok_kind expect2
, tok_kind expect3
, tok_kind expect4
,
114 if (tokp
->kind
!= expect1
&& tokp
->kind
!= expect2
115 && tokp
->kind
!= expect3
&& tokp
->kind
!= expect4
) {
116 expected4(expect1
, expect2
, expect3
, expect4
);
121 * scan expecting a constant, possibly symbolic
124 scan_num(token
* tokp
)
127 switch (tokp
->kind
) {
131 error("constant or identifier expected");
137 * Peek at the next token
148 * Peek at the next token and scan it if it matches what you expect
151 peekscan(tok_kind expect
, token
* tokp
)
154 if (tokp
->kind
== expect
) {
164 * Get the next token, printing out any directive that are encountered.
167 get_token(token
* tokp
)
181 if (!fgets(curline
, MAXLINESIZE
, fin
)) {
182 tokp
->kind
= TOK_EOF
;
188 fputs(curline
, fout
);
193 } else if (cppline(curline
)) {
194 #if defined(AFS_DARWIN_ENV)
195 if (strncmp(curline
, "#pragma", 7) == 0)
197 #endif /* defined(AFS_DARWIN_ENV) */
198 docppline(curline
, &linenum
, &infilename
);
199 } else if (directive(curline
)) {
200 printdirective(curline
);
206 } else if (isspace(*where
)) {
207 while (isspace(*where
)) {
210 } else if (verbatim
) {
212 if (verbatimend(where
)) {
216 } else if (verbatimstart(where
)) {
219 } else if (commenting
) {
221 if (endcomment(where
)) {
225 } else if (startcomment(where
)) {
234 * 'where' is not whitespace, comment or directive Must be a token!
238 tokp
->kind
= TOK_COLON
;
242 tokp
->kind
= TOK_SEMICOLON
;
246 tokp
->kind
= TOK_COMMA
;
250 tokp
->kind
= TOK_EQUAL
;
254 tokp
->kind
= TOK_STAR
;
258 tokp
->kind
= TOK_LBRACKET
;
262 tokp
->kind
= TOK_RBRACKET
;
266 tokp
->kind
= TOK_LBRACE
;
270 tokp
->kind
= TOK_RBRACE
;
274 tokp
->kind
= TOK_LPAREN
;
278 tokp
->kind
= TOK_RPAREN
;
282 tokp
->kind
= TOK_LANGLE
;
286 tokp
->kind
= TOK_RANGLE
;
291 tokp
->kind
= TOK_STRCONST
;
292 findstrconst(&where
, &tokp
->str
);
306 tokp
->kind
= TOK_IDENT
;
307 findconst(&where
, &tokp
->str
);
312 if (!(isalpha(*where
) || *where
== '_')) {
316 s_print(buf
, "illegal character in file: ");
317 p
= buf
+ strlen(buf
);
318 if (isprint(*where
)) {
319 s_print(p
, "%c", *where
);
321 s_print(p
, "%d", *where
);
325 findkind(&where
, tokp
);
332 unget_token(token
* tokp
)
340 findstrconst(char **str
, char **val
)
348 } while (*p
&& *p
!= '"');
350 error("unterminated string constant");
353 size
= (int)(p
- *str
);
354 *val
= alloc(size
+ 1);
355 (void)strncpy(*val
, *str
, size
);
361 findconst(char **str
, char **val
)
367 if (*p
== '0' && *(p
+ 1) == 'x') {
371 } while (isxdigit(*p
));
375 } while (isdigit(*p
));
377 size
= (int)(p
- *str
);
378 *val
= alloc(size
+ 1);
379 (void)strncpy(*val
, *str
, size
);
386 static token symbols
[] = {
387 {TOK_CONST
, "const"},
388 {TOK_UNION
, "union"},
389 {TOK_SWITCH
, "switch"},
391 {TOK_DEFAULT
, "default"},
392 {TOK_STRUCT
, "struct"},
393 {TOK_TYPEDEF
, "typedef"},
395 {TOK_OPAQUE
, "opaque"},
400 {TOK_UNSIGNED
, "unsigned"},
401 {TOK_SHORT
, "short"},
402 {TOK_INT32
, "afs_int32"},
403 {TOK_FLOAT
, "float"},
404 {TOK_DOUBLE
, "double"},
405 {TOK_STRING
, "string"},
406 {TOK_PACKAGE
, "package"},
407 {TOK_PREFIX
, "prefix"},
408 {TOK_STATINDEX
, "statindex"},
409 {TOK_SPECIAL
, "special"},
410 {TOK_STARTINGOPCODE
, "startingopcode"},
411 {TOK_CUSTOMIZED
, "customized"},
413 {TOK_SPLITPREFIX
, "splitprefix"},
414 {TOK_SPLIT
, "split"},
415 {TOK_MULTI
, "multi"},
418 {TOK_INOUT
, "INOUT"},
419 {TOK_AFSUUID
, "afsUUID"},
425 findkind(char **mark
, token
* tokp
)
433 for (s
= symbols
; s
->kind
!= TOK_EOF
; s
++) {
434 len
= (int)strlen(s
->str
);
435 if (strncmp(str
, s
->str
, len
) == 0) {
436 if (!isalnum(str
[len
]) && str
[len
] != '_') {
437 tokp
->kind
= s
->kind
;
444 tokp
->kind
= TOK_IDENT
;
445 for (len
= 0; isalnum(str
[len
]) || str
[len
] == '_'; len
++);
446 tokp
->str
= alloc(len
+ 1);
447 (void)strncpy(tokp
->str
, str
, len
);
455 return (line
== curline
&& *line
== '#');
459 directive(char *line
)
461 return (line
== curline
&& *line
== '%');
465 printdirective(char *line
)
467 f_print(fout
, "%s", line
+ 1);
471 docppline(char *line
, int *lineno
, char **fname
)
478 while (isspace(*line
)) {
482 while (isdigit(*line
)) {
485 while (isspace(*line
)) {
497 if (!strncmp(line
, "line", 4)) {
505 error("preprocessor error");
508 p
= file
= alloc(strlen(line
) + 1);
509 while (*line
&& *line
!= '"') {
513 error("preprocessor error");
527 /* doesn't appear to be used */
531 for (where
+= 2; !verbatimend(where
); where
++) {
533 if (!fgets(curline
, MAXLINESIZE
, fin
)) {
534 error("unterminated code: %} is missing");
538 if (verbatimend(curline
)) {
542 fputs(curline
, fout
);