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