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