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