1 /* $NetBSD: rpc_scan.c,v 1.11 2009/05/06 14:30:51 ginsbach Exp $ */ 2 /* 3 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 4 * unrestricted use provided that this legend is included on all tape 5 * media and as a part of the software program in whole or part. Users 6 * may copy or modify Sun RPC without charge, but are not authorized 7 * to license or distribute it to anyone else except as part of a product or 8 * program developed by the user or with the express written consent of 9 * Sun Microsystems, Inc. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 #if defined(__RCSID) && !defined(lint) 38 #if 0 39 static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI"; 40 #else 41 __RCSID("$NetBSD: rpc_scan.c,v 1.11 2009/05/06 14:30:51 ginsbach Exp $"); 42 #endif 43 #endif 44 45 /* 46 * rpc_scan.c, Scanner for the RPC protocol compiler 47 * Copyright (C) 1987, Sun Microsystems, Inc. 48 */ 49 #include <stdlib.h> 50 #include <stdio.h> 51 #include <ctype.h> 52 #include <string.h> 53 #include "rpc_scan.h" 54 #include "rpc_parse.h" 55 #include "rpc_util.h" 56 57 #define startcomment(where) (where[0] == '/' && where[1] == '*') 58 #define endcomment(where) (where[-1] == '*' && where[0] == '/') 59 60 static void unget_token __P((token *)); 61 static void findstrconst __P((char **, char **)); 62 static void findchrconst __P((char **, char **)); 63 static void findconst __P((char **, char **)); 64 static void findkind __P((char **, token *)); 65 static int cppline __P((char *)); 66 static int directive __P((char *)); 67 static void printdirective __P((char *)); 68 static void docppline __P((char *, int *, char **)); 69 70 static int pushed = 0; /* is a token pushed */ 71 static token lasttok; /* last token, if pushed */ 72 73 /* 74 * scan expecting 1 given token 75 */ 76 void 77 scan(expect, tokp) 78 tok_kind expect; 79 token *tokp; 80 { 81 get_token(tokp); 82 if (tokp->kind != expect) { 83 expected1(expect); 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 * scan expecting any of the 3 given token 102 */ 103 void 104 scan3(expect1, expect2, expect3, tokp) 105 tok_kind expect1; 106 tok_kind expect2; 107 tok_kind expect3; 108 token *tokp; 109 { 110 get_token(tokp); 111 if (tokp->kind != expect1 && tokp->kind != expect2 112 && tokp->kind != expect3) { 113 expected3(expect1, expect2, expect3); 114 } 115 } 116 /* 117 * scan expecting a constant, possibly symbolic 118 */ 119 void 120 scan_num(tokp) 121 token *tokp; 122 { 123 get_token(tokp); 124 switch (tokp->kind) { 125 case TOK_IDENT: 126 break; 127 default: 128 error("constant or identifier expected"); 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 * 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 * Get the next token, printing out any directive that are encountered. 158 */ 159 void 160 get_token(tokp) 161 token *tokp; 162 { 163 int commenting; 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 *where = 0; 177 return; 178 } 179 linenum++; 180 if (commenting) { 181 break; 182 } else 183 if (cppline(curline)) { 184 docppline(curline, &linenum, 185 &infilename); 186 } else 187 if (directive(curline)) { 188 printdirective(curline); 189 } else { 190 break; 191 } 192 } 193 where = curline; 194 } else 195 if (isspace((unsigned char)*where)) { 196 while (isspace((unsigned char)*where)) { 197 where++; /* eat */ 198 } 199 } else 200 if (commenting) { 201 for (where++; *where; where++) { 202 if (endcomment(where)) { 203 where++; 204 commenting--; 205 break; 206 } 207 } 208 } else 209 if (startcomment(where)) { 210 where += 2; 211 commenting++; 212 } else { 213 break; 214 } 215 } 216 217 /* 218 * 'where' is not whitespace, comment or directive Must be a token! 219 */ 220 switch (*where) { 221 case ':': 222 tokp->kind = TOK_COLON; 223 where++; 224 break; 225 case ';': 226 tokp->kind = TOK_SEMICOLON; 227 where++; 228 break; 229 case ',': 230 tokp->kind = TOK_COMMA; 231 where++; 232 break; 233 case '=': 234 tokp->kind = TOK_EQUAL; 235 where++; 236 break; 237 case '*': 238 tokp->kind = TOK_STAR; 239 where++; 240 break; 241 case '[': 242 tokp->kind = TOK_LBRACKET; 243 where++; 244 break; 245 case ']': 246 tokp->kind = TOK_RBRACKET; 247 where++; 248 break; 249 case '{': 250 tokp->kind = TOK_LBRACE; 251 where++; 252 break; 253 case '}': 254 tokp->kind = TOK_RBRACE; 255 where++; 256 break; 257 case '(': 258 tokp->kind = TOK_LPAREN; 259 where++; 260 break; 261 case ')': 262 tokp->kind = TOK_RPAREN; 263 where++; 264 break; 265 case '<': 266 tokp->kind = TOK_LANGLE; 267 where++; 268 break; 269 case '>': 270 tokp->kind = TOK_RANGLE; 271 where++; 272 break; 273 274 case '"': 275 tokp->kind = TOK_STRCONST; 276 findstrconst(&where, &tokp->str); 277 break; 278 case '\'': 279 tokp->kind = TOK_CHARCONST; 280 findchrconst(&where, &tokp->str); 281 break; 282 283 case '-': 284 case '0': 285 case '1': 286 case '2': 287 case '3': 288 case '4': 289 case '5': 290 case '6': 291 case '7': 292 case '8': 293 case '9': 294 tokp->kind = TOK_IDENT; 295 findconst(&where, &tokp->str); 296 break; 297 298 default: 299 if (!(isalpha((unsigned char)*where) || *where == '_')) { 300 char buf[100]; 301 char *p; 302 303 s_print(buf, "illegal character in file: "); 304 p = buf + strlen(buf); 305 if (isprint((unsigned char)*where)) { 306 s_print(p, "%c", *where); 307 } else { 308 s_print(p, "%d", *where); 309 } 310 error(buf); 311 } 312 findkind(&where, tokp); 313 break; 314 } 315 } 316 317 static void 318 unget_token(tokp) 319 token *tokp; 320 { 321 lasttok = *tokp; 322 pushed = 1; 323 } 324 325 static void 326 findstrconst(str, val) 327 char **str; 328 char **val; 329 { 330 char *p; 331 int size; 332 333 p = *str; 334 do { 335 p++; 336 } while (*p && *p != '"'); 337 if (*p == 0) { 338 error("unterminated string constant"); 339 } 340 p++; 341 size = p - *str; 342 *val = alloc(size + 1); 343 (void) strncpy(*val, *str, size); 344 (*val)[size] = 0; 345 *str = p; 346 } 347 348 static void 349 findchrconst(str, val) 350 char **str; 351 char **val; 352 { 353 char *p; 354 int size; 355 356 p = *str; 357 do { 358 p++; 359 } while (*p && *p != '\''); 360 if (*p == 0) { 361 error("unterminated string constant"); 362 } 363 p++; 364 size = p - *str; 365 if (size != 3) { 366 error("empty char string"); 367 } 368 *val = alloc(size + 1); 369 (void) strncpy(*val, *str, size); 370 (*val)[size] = 0; 371 *str = p; 372 } 373 374 static void 375 findconst(str, val) 376 char **str; 377 char **val; 378 { 379 char *p; 380 int size; 381 382 p = *str; 383 if (*p == '0' && *(p + 1) == 'x') { 384 p++; 385 do { 386 p++; 387 } while (isxdigit((unsigned char)*p)); 388 } else { 389 do { 390 p++; 391 } while (isdigit((unsigned char)*p)); 392 } 393 size = p - *str; 394 *val = alloc(size + 1); 395 (void) strncpy(*val, *str, size); 396 (*val)[size] = 0; 397 *str = p; 398 } 399 400 static token symbols[] = { 401 {TOK_CONST, "const"}, 402 {TOK_UNION, "union"}, 403 {TOK_SWITCH, "switch"}, 404 {TOK_CASE, "case"}, 405 {TOK_DEFAULT, "default"}, 406 {TOK_STRUCT, "struct"}, 407 {TOK_TYPEDEF, "typedef"}, 408 {TOK_ENUM, "enum"}, 409 {TOK_OPAQUE, "opaque"}, 410 {TOK_BOOL, "bool"}, 411 {TOK_VOID, "void"}, 412 {TOK_CHAR, "char"}, 413 {TOK_INT, "int"}, 414 {TOK_UNSIGNED, "unsigned"}, 415 {TOK_SHORT, "short"}, 416 {TOK_LONG, "long"}, 417 {TOK_HYPER, "hyper"}, 418 {TOK_FLOAT, "float"}, 419 {TOK_DOUBLE, "double"}, 420 {TOK_QUAD, "quadruple"}, 421 {TOK_STRING, "string"}, 422 {TOK_PROGRAM, "program"}, 423 {TOK_VERSION, "version"}, 424 {TOK_EOF, "??????"}, 425 }; 426 427 static void 428 findkind(mark, tokp) 429 char **mark; 430 token *tokp; 431 { 432 int len; 433 token *s; 434 char *str; 435 436 str = *mark; 437 for (s = symbols; s->kind != TOK_EOF; s++) { 438 len = strlen(s->str); 439 if (strncmp(str, s->str, len) == 0) { 440 if (!isalnum((unsigned char)str[len]) && 441 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((unsigned char)str[len]) || 451 str[len] == '_'; len++); 452 tokp->str = alloc(len + 1); 453 (void) strncpy(tokp->str, str, len); 454 tokp->str[len] = 0; 455 *mark = str + len; 456 } 457 458 static int 459 cppline(line) 460 char *line; 461 { 462 return (line == curline && *line == '#'); 463 } 464 465 static int 466 directive(line) 467 char *line; 468 { 469 return (line == curline && *line == '%'); 470 } 471 472 static void 473 printdirective(line) 474 char *line; 475 { 476 f_print(fout, "%s", line + 1); 477 } 478 479 static void 480 docppline(line, lineno, fname) 481 char *line; 482 int *lineno; 483 char **fname; 484 { 485 char *file; 486 int num; 487 char *p; 488 489 line++; 490 while (isspace((unsigned char)*line)) { 491 line++; 492 } 493 num = atoi(line); 494 while (isdigit((unsigned char)*line)) { 495 line++; 496 } 497 while (isspace((unsigned char)*line)) { 498 line++; 499 } 500 if (*line != '"') { 501 error("preprocessor error"); 502 } 503 line++; 504 p = file = alloc(strlen(line) + 1); 505 while (*line && *line != '"') { 506 *p++ = *line++; 507 } 508 if (*line == 0) { 509 error("preprocessor error"); 510 } 511 *p = 0; 512 if (*file == 0) { 513 *fname = NULL; 514 free(file); 515 } else { 516 *fname = file; 517 } 518 *lineno = num - 1; 519 } 520