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