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