1 /* $OpenBSD: rpc_scan.c,v 1.13 2007/10/03 14:35:48 weingart 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 const 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 void unget_token(token *tokp); 51 static void findstrconst(char **, char **); 52 static void findchrconst(char **, char **); 53 static void findconst(char **, char **); 54 static void findkind(char **, token *); 55 static int cppline(char *); 56 static int directive(char *); 57 static void printdirective(char *); 58 static void docppline(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 * 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 * scan expecting any of the 3 given token 95 */ 96 void 97 scan3(expect1, expect2, expect3, tokp) 98 tok_kind expect1; 99 tok_kind expect2; 100 tok_kind expect3; 101 token *tokp; 102 { 103 get_token(tokp); 104 if (tokp->kind != expect1 && tokp->kind != expect2 && 105 tokp->kind != expect3) 106 expected3(expect1, expect2, expect3); 107 } 108 109 /* 110 * scan expecting a constant, possibly symbolic 111 */ 112 void 113 scan_num(tokp) 114 token *tokp; 115 { 116 get_token(tokp); 117 switch (tokp->kind) { 118 case TOK_IDENT: 119 break; 120 default: 121 error("constant or identifier expected"); 122 } 123 } 124 125 /* 126 * Peek at the next token 127 */ 128 void 129 peek(tokp) 130 token *tokp; 131 { 132 get_token(tokp); 133 unget_token(tokp); 134 } 135 136 /* 137 * Peek at the next token and scan it if it matches what you expect 138 */ 139 int 140 peekscan(expect, tokp) 141 tok_kind expect; 142 token *tokp; 143 { 144 peek(tokp); 145 if (tokp->kind == expect) { 146 get_token(tokp); 147 return (1); 148 } 149 return (0); 150 } 151 152 /* 153 * Get the next token, printing out any directive that are encountered. 154 */ 155 void 156 get_token(tokp) 157 token *tokp; 158 { 159 int commenting; 160 161 if (pushed) { 162 pushed = 0; 163 *tokp = lasttok; 164 return; 165 } 166 commenting = 0; 167 for (;;) { 168 if (*where == 0) { 169 for (;;) { 170 if (!fgets(curline, MAXLINESIZE, fin)) { 171 tokp->kind = TOK_EOF; 172 *where = 0; 173 return; 174 } 175 linenum++; 176 if (commenting) { 177 break; 178 } else if (cppline(curline)) { 179 docppline(curline, &linenum, 180 &infilename); 181 } else if (directive(curline)) { 182 printdirective(curline); 183 } else { 184 break; 185 } 186 } 187 where = curline; 188 } else if (isspace(*where)) { 189 while (isspace(*where)) { 190 where++; /* eat */ 191 } 192 } else if (commenting) { 193 for (where++; *where; where++) { 194 if (endcomment(where)) { 195 where++; 196 commenting--; 197 break; 198 } 199 } 200 } else if (startcomment(where)) { 201 where += 2; 202 commenting++; 203 } else { 204 break; 205 } 206 } 207 208 /* 209 * 'where' is not whitespace, comment or directive Must be a token! 210 */ 211 switch (*where) { 212 case ':': 213 tokp->kind = TOK_COLON; 214 where++; 215 break; 216 case ';': 217 tokp->kind = TOK_SEMICOLON; 218 where++; 219 break; 220 case ',': 221 tokp->kind = TOK_COMMA; 222 where++; 223 break; 224 case '=': 225 tokp->kind = TOK_EQUAL; 226 where++; 227 break; 228 case '*': 229 tokp->kind = TOK_STAR; 230 where++; 231 break; 232 case '[': 233 tokp->kind = TOK_LBRACKET; 234 where++; 235 break; 236 case ']': 237 tokp->kind = TOK_RBRACKET; 238 where++; 239 break; 240 case '{': 241 tokp->kind = TOK_LBRACE; 242 where++; 243 break; 244 case '}': 245 tokp->kind = TOK_RBRACE; 246 where++; 247 break; 248 case '(': 249 tokp->kind = TOK_LPAREN; 250 where++; 251 break; 252 case ')': 253 tokp->kind = TOK_RPAREN; 254 where++; 255 break; 256 case '<': 257 tokp->kind = TOK_LANGLE; 258 where++; 259 break; 260 case '>': 261 tokp->kind = TOK_RANGLE; 262 where++; 263 break; 264 265 case '"': 266 tokp->kind = TOK_STRCONST; 267 findstrconst(&where, &tokp->str); 268 break; 269 case '\'': 270 tokp->kind = TOK_CHARCONST; 271 findchrconst(&where, &tokp->str); 272 break; 273 274 case '-': 275 case '0': 276 case '1': 277 case '2': 278 case '3': 279 case '4': 280 case '5': 281 case '6': 282 case '7': 283 case '8': 284 case '9': 285 tokp->kind = TOK_IDENT; 286 findconst(&where, &tokp->str); 287 break; 288 289 default: 290 if (!(isalpha(*where) || *where == '_')) { 291 char buf[100], chs[20]; 292 293 if (isprint(*where)) { 294 snprintf(chs, sizeof chs, "%c", *where); 295 } else { 296 snprintf(chs, sizeof chs, "%d", *where); 297 } 298 299 snprintf(buf, sizeof buf, 300 "illegal character in file: %s", chs); 301 error(buf); 302 } 303 findkind(&where, tokp); 304 break; 305 } 306 } 307 308 static void 309 unget_token(tokp) 310 token *tokp; 311 { 312 lasttok = *tokp; 313 pushed = 1; 314 } 315 316 static void 317 findstrconst(str, val) 318 char **str; 319 char **val; 320 { 321 char *p; 322 int size; 323 324 p = *str; 325 do { 326 p++; 327 } while (*p && *p != '"'); 328 if (*p == 0) { 329 error("unterminated string constant"); 330 } 331 p++; 332 size = p - *str; 333 *val = alloc(size + 1); 334 if (val == NULL) 335 error("alloc failed"); 336 (void) strncpy(*val, *str, size); 337 (*val)[size] = 0; 338 *str = p; 339 } 340 341 static void 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 if (val == NULL) 363 error("alloc failed"); 364 (void) strncpy(*val, *str, size); 365 (*val)[size] = 0; 366 *str = p; 367 } 368 369 static void 370 findconst(str, val) 371 char **str; 372 char **val; 373 { 374 char *p; 375 int size; 376 377 p = *str; 378 if (*p == '0' && *(p + 1) == 'x') { 379 p++; 380 do { 381 p++; 382 } while (isxdigit(*p)); 383 } else { 384 do { 385 p++; 386 } while (isdigit(*p)); 387 } 388 size = p - *str; 389 *val = alloc(size + 1); 390 if (val == NULL) 391 error("alloc failed"); 392 (void) strncpy(*val, *str, size); 393 (*val)[size] = 0; 394 *str = p; 395 } 396 397 static token symbols[] = { 398 {TOK_CONST, "const"}, 399 {TOK_UNION, "union"}, 400 {TOK_SWITCH, "switch"}, 401 {TOK_CASE, "case"}, 402 {TOK_DEFAULT, "default"}, 403 {TOK_STRUCT, "struct"}, 404 {TOK_TYPEDEF, "typedef"}, 405 {TOK_ENUM, "enum"}, 406 {TOK_OPAQUE, "opaque"}, 407 {TOK_BOOL, "bool"}, 408 {TOK_VOID, "void"}, 409 {TOK_CHAR, "char"}, 410 {TOK_INT, "int"}, 411 {TOK_UNSIGNED, "unsigned"}, 412 {TOK_SHORT, "short"}, 413 {TOK_LONG, "long"}, 414 {TOK_FLOAT, "float"}, 415 {TOK_DOUBLE, "double"}, 416 {TOK_STRING, "string"}, 417 {TOK_PROGRAM, "program"}, 418 {TOK_VERSION, "version"}, 419 {TOK_EOF, "??????"}, 420 }; 421 422 static void 423 findkind(mark, tokp) 424 char **mark; 425 token *tokp; 426 { 427 int len; 428 token *s; 429 char *str; 430 431 str = *mark; 432 for (s = symbols; s->kind != TOK_EOF; s++) { 433 len = strlen(s->str); 434 if (strncmp(str, s->str, len) == 0) { 435 if (!isalnum(str[len]) && str[len] != '_') { 436 tokp->kind = s->kind; 437 tokp->str = s->str; 438 *mark = str + len; 439 return; 440 } 441 } 442 } 443 tokp->kind = TOK_IDENT; 444 for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); 445 tokp->str = alloc(len + 1); 446 if (tokp->str == NULL) 447 error("alloc failed"); 448 (void) strncpy(tokp->str, str, len); 449 tokp->str[len] = 0; 450 *mark = str + len; 451 } 452 453 static int 454 cppline(line) 455 char *line; 456 { 457 return (line == curline && *line == '#'); 458 } 459 460 static int 461 directive(line) 462 char *line; 463 { 464 return (line == curline && *line == '%'); 465 } 466 467 static void 468 printdirective(line) 469 char *line; 470 { 471 fprintf(fout, "%s", line + 1); 472 } 473 474 static void 475 docppline(line, lineno, fname) 476 char *line; 477 int *lineno; 478 char **fname; 479 { 480 char *file; 481 int num; 482 char *p; 483 484 line++; 485 while (isspace(*line)) { 486 line++; 487 } 488 num = atoi(line); 489 while (isdigit(*line)) { 490 line++; 491 } 492 while (isspace(*line)) { 493 line++; 494 } 495 if (*line != '"') { 496 error("preprocessor error"); 497 } 498 line++; 499 p = file = alloc(strlen(line) + 1); 500 if (p == NULL) 501 error("alloc failed"); 502 while (*line && *line != '"') { 503 *p++ = *line++; 504 } 505 if (*line == 0) { 506 error("preprocessor error"); 507 } 508 *p = 0; 509 if (*file == 0) { 510 *fname = NULL; 511 free(file); 512 } else { 513 *fname = file; 514 } 515 *lineno = num - 1; 516 } 517