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