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