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 /* 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_parse.h" 50 #include "rpc_scan.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 **, const char **); 61 static void findchrconst(char **, const char **); 62 static void findconst(char **, const 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 *, const char **); 68 69 /* 70 * scan expecting 1 given token 71 */ 72 void 73 scan(tok_kind expect, token *tokp) 74 { 75 get_token(tokp); 76 if (tokp->kind != expect) { 77 expected1(expect); 78 } 79 } 80 81 /* 82 * scan expecting any of the 2 given tokens 83 */ 84 void 85 scan2(tok_kind expect1, tok_kind expect2, token *tokp) 86 { 87 get_token(tokp); 88 if (tokp->kind != expect1 && tokp->kind != expect2) { 89 expected2(expect1, expect2); 90 } 91 } 92 93 /* 94 * scan expecting any of the 3 given token 95 */ 96 void 97 scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp) 98 { 99 get_token(tokp); 100 if (tokp->kind != expect1 && tokp->kind != expect2 101 && tokp->kind != expect3) { 102 expected3(expect1, expect2, expect3); 103 } 104 } 105 106 /* 107 * scan expecting a constant, possibly symbolic 108 */ 109 void 110 scan_num(token *tokp) 111 { 112 get_token(tokp); 113 switch (tokp->kind) { 114 case TOK_IDENT: 115 break; 116 default: 117 error("constant or identifier expected"); 118 } 119 } 120 121 /* 122 * Peek at the next token 123 */ 124 void 125 peek(token *tokp) 126 { 127 get_token(tokp); 128 unget_token(tokp); 129 } 130 131 /* 132 * Peek at the next token and scan it if it matches what you expect 133 */ 134 int 135 peekscan(tok_kind expect, token *tokp) 136 { 137 peek(tokp); 138 if (tokp->kind == expect) { 139 get_token(tokp); 140 return (1); 141 } 142 return (0); 143 } 144 145 /* 146 * Get the next token, printing out any directive that are encountered. 147 */ 148 void 149 get_token(token *tokp) 150 { 151 int commenting; 152 int stat = 0; 153 154 155 if (pushed) { 156 pushed = 0; 157 *tokp = lasttok; 158 return; 159 } 160 commenting = 0; 161 for (;;) { 162 if (*where == 0) { 163 for (;;) { 164 if (!fgets(curline, MAXLINESIZE, fin)) { 165 tokp->kind = TOK_EOF; 166 /* now check if cpp returned non NULL value */ 167 waitpid(childpid, &stat, WUNTRACED); 168 if (stat > 0) { 169 /* Set return value from rpcgen */ 170 nonfatalerrors = stat >> 8; 171 } 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]; 292 char *p; 293 294 s_print(buf, "illegal character in file: "); 295 p = buf + strlen(buf); 296 if (isprint(*where)) { 297 s_print(p, "%c", *where); 298 } else { 299 s_print(p, "%d", *where); 300 } 301 error(buf); 302 } 303 findkind(&where, tokp); 304 break; 305 } 306 } 307 308 static void 309 unget_token(token *tokp) 310 { 311 lasttok = *tokp; 312 pushed = 1; 313 } 314 315 static void 316 findstrconst(char **str, const char **val) 317 { 318 char *p; 319 char *tmp; 320 int size; 321 322 p = *str; 323 do { 324 p++; 325 } while (*p && *p != '"'); 326 if (*p == 0) { 327 error("unterminated string constant"); 328 } 329 p++; 330 size = p - *str + 1; 331 tmp = xmalloc(size); 332 (void) strlcpy(tmp, *str, size); 333 *val = tmp; 334 *str = p; 335 } 336 337 static void 338 findchrconst(char **str, const char **val) 339 { 340 char *p; 341 char *tmp; 342 int size; 343 344 p = *str; 345 do { 346 p++; 347 } while (*p && *p != '\''); 348 if (*p == 0) { 349 error("unterminated string constant"); 350 } 351 p++; 352 size = p - *str + 1; 353 if (size != 4) { 354 error("empty char string"); 355 } 356 tmp = xmalloc(size); 357 (void) strlcpy(tmp, *str, size); 358 *val = tmp; 359 *str = p; 360 } 361 362 static void 363 findconst(char **str, const char **val) 364 { 365 char *p; 366 char *tmp; 367 int size; 368 369 p = *str; 370 if (*p == '0' && *(p + 1) == 'x') { 371 p++; 372 do { 373 p++; 374 } while (isxdigit(*p)); 375 } else { 376 do { 377 p++; 378 } while (isdigit(*p)); 379 } 380 size = p - *str + 1; 381 tmp = xmalloc(size); 382 (void) strlcpy(tmp, *str, size); 383 *val = tmp; 384 *str = p; 385 } 386 387 static token symbols[] = { 388 {TOK_CONST, "const"}, 389 {TOK_UNION, "union"}, 390 {TOK_SWITCH, "switch"}, 391 {TOK_CASE, "case"}, 392 {TOK_DEFAULT, "default"}, 393 {TOK_STRUCT, "struct"}, 394 {TOK_TYPEDEF, "typedef"}, 395 {TOK_ENUM, "enum"}, 396 {TOK_OPAQUE, "opaque"}, 397 {TOK_BOOL, "bool"}, 398 {TOK_VOID, "void"}, 399 {TOK_CHAR, "char"}, 400 {TOK_INT, "int"}, 401 {TOK_UNSIGNED, "unsigned"}, 402 {TOK_SHORT, "short"}, 403 {TOK_LONG, "long"}, 404 {TOK_HYPER, "hyper"}, 405 {TOK_FLOAT, "float"}, 406 {TOK_DOUBLE, "double"}, 407 {TOK_QUAD, "quadruple"}, 408 {TOK_STRING, "string"}, 409 {TOK_PROGRAM, "program"}, 410 {TOK_VERSION, "version"}, 411 {TOK_EOF, "??????"}, 412 }; 413 414 static void 415 findkind(char **mark, token *tokp) 416 { 417 int len; 418 token *s; 419 char *str, *tmp; 420 421 str = *mark; 422 for (s = symbols; s->kind != TOK_EOF; s++) { 423 len = strlen(s->str); 424 if (strncmp(str, s->str, len) == 0) { 425 if (!isalnum(str[len]) && str[len] != '_') { 426 tokp->kind = s->kind; 427 tokp->str = s->str; 428 *mark = str + len; 429 return; 430 } 431 } 432 } 433 tokp->kind = TOK_IDENT; 434 for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); 435 tmp = xmalloc(len + 1); 436 (void) strlcpy(tmp, str, len + 1); 437 tokp->str = tmp; 438 *mark = str + len; 439 } 440 441 static int 442 cppline(char *line) 443 { 444 return (line == curline && *line == '#'); 445 } 446 447 static int 448 directive(char *line) 449 { 450 return (line == curline && *line == '%'); 451 } 452 453 static void 454 printdirective(char *line) 455 { 456 f_print(fout, "%s", line + 1); 457 } 458 459 static void 460 docppline(char *line, int *lineno, const char **fname) 461 { 462 char *file; 463 int num; 464 char *p; 465 466 line++; 467 while (isspace(*line)) { 468 line++; 469 } 470 num = atoi(line); 471 while (isdigit(*line)) { 472 line++; 473 } 474 while (isspace(*line)) { 475 line++; 476 } 477 if (*line != '"') { 478 error("preprocessor error"); 479 } 480 line++; 481 p = file = xmalloc(strlen(line) + 1); 482 while (*line && *line != '"') { 483 *p++ = *line++; 484 } 485 if (*line == 0) { 486 error("preprocessor error"); 487 } 488 *p = 0; 489 if (*file == 0) { 490 *fname = NULL; 491 free(file); 492 } else { 493 *fname = file; 494 } 495 *lineno = num - 1; 496 } 497