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