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