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