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