1 /* @(#)rpc_scan.c 2.1 88/08/01 4.0 RPCSRC */ 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. 9 * 10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 13 * 14 * Sun RPC is provided with no support and without any obligation on the 15 * part of Sun Microsystems, Inc. to assist in its use, correction, 16 * modification or enhancement. 17 * 18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 20 * OR ANY PART THEREOF. 21 * 22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 23 * or profits or other special, indirect and consequential damages, even if 24 * Sun has been advised of the possibility of such damages. 25 * 26 * Sun Microsystems, Inc. 27 * 2550 Garcia Avenue 28 * Mountain View, California 94043 29 */ 30 #ifndef lint 31 static char sccsid[] = "@(#)rpc_scan.c 1.6 87/06/24 (C) 1987 SMI"; 32 #endif 33 34 /* 35 * rpc_scan.c, Scanner for the RPC protocol compiler 36 * Copyright (C) 1987, Sun Microsystems, Inc. 37 */ 38 #include <stdio.h> 39 #include <ctype.h> 40 #include <strings.h> 41 #include "rpc_scan.h" 42 #include "rpc_util.h" 43 44 #define startcomment(where) (where[0] == '/' && where[1] == '*') 45 #define endcomment(where) (where[-1] == '*' && where[0] == '/') 46 47 static int pushed = 0; /* is a token pushed */ 48 static token lasttok; /* last token, if pushed */ 49 50 static int unget_token(), findstrconst(), findconst(), findkind(), cppline(), 51 directive(), printdirective(), docppline(); 52 /* 53 * scan expecting 1 given token 54 */ 55 void 56 scan(expect, tokp) 57 tok_kind expect; 58 token *tokp; 59 { 60 get_token(tokp); 61 if (tokp->kind != expect) { 62 expected1(expect); 63 } 64 } 65 66 /* 67 * scan expecting 2 given tokens 68 */ 69 void 70 scan2(expect1, expect2, tokp) 71 tok_kind expect1; 72 tok_kind expect2; 73 token *tokp; 74 { 75 get_token(tokp); 76 if (tokp->kind != expect1 && tokp->kind != expect2) { 77 expected2(expect1, expect2); 78 } 79 } 80 81 /* 82 * scan expecting 3 given token 83 */ 84 void 85 scan3(expect1, expect2, expect3, tokp) 86 tok_kind expect1; 87 tok_kind expect2; 88 tok_kind expect3; 89 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 /* 100 * scan expecting a constant, possibly symbolic 101 */ 102 void 103 scan_num(tokp) 104 token *tokp; 105 { 106 get_token(tokp); 107 switch (tokp->kind) { 108 case TOK_IDENT: 109 break; 110 default: 111 error("constant or identifier expected"); 112 } 113 } 114 115 116 /* 117 * Peek at the next token 118 */ 119 void 120 peek(tokp) 121 token *tokp; 122 { 123 get_token(tokp); 124 unget_token(tokp); 125 } 126 127 128 /* 129 * Peek at the next token and scan it if it matches what you expect 130 */ 131 int 132 peekscan(expect, tokp) 133 tok_kind expect; 134 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 145 146 /* 147 * Get the next token, printing out any directive that are encountered. 148 */ 149 void 150 get_token(tokp) 151 token *tokp; 152 { 153 int commenting; 154 155 if (pushed) { 156 pushed = 0; 157 *tokp = lasttok; 158 return; 159 } 160 commenting = 0; 161 for (;;) { 162 if (*where == 0) { 163 for (;;) { 164 if (!fgets(curline, MAXLINESIZE, fin)) { 165 tokp->kind = TOK_EOF; 166 *where = 0; 167 return; 168 } 169 linenum++; 170 if (commenting) { 171 break; 172 } else if (cppline(curline)) { 173 docppline(curline, &linenum, 174 &infilename); 175 } else if (directive(curline)) { 176 printdirective(curline); 177 } else { 178 break; 179 } 180 } 181 where = curline; 182 } else if (isspace(*where)) { 183 while (isspace(*where)) { 184 where++; /* eat */ 185 } 186 } else if (commenting) { 187 where++; 188 if (endcomment(where)) { 189 where++; 190 commenting--; 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 262 case '-': 263 case '0': 264 case '1': 265 case '2': 266 case '3': 267 case '4': 268 case '5': 269 case '6': 270 case '7': 271 case '8': 272 case '9': 273 tokp->kind = TOK_IDENT; 274 findconst(&where, &tokp->str); 275 break; 276 277 278 default: 279 if (!(isalpha(*where) || *where == '_')) { 280 char buf[100]; 281 char *p; 282 283 s_print(buf, "illegal character in file: "); 284 p = buf + strlen(buf); 285 if (isprint(*where)) { 286 s_print(p, "%c", *where); 287 } else { 288 s_print(p, "%d", *where); 289 } 290 error(buf); 291 } 292 findkind(&where, tokp); 293 break; 294 } 295 } 296 297 298 299 static 300 unget_token(tokp) 301 token *tokp; 302 { 303 lasttok = *tokp; 304 pushed = 1; 305 } 306 307 308 static 309 findstrconst(str, val) 310 char **str; 311 char **val; 312 { 313 char *p; 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 } 323 p++; 324 size = p - *str; 325 *val = alloc(size + 1); 326 (void) strncpy(*val, *str, size); 327 (*val)[size] = 0; 328 *str = p; 329 } 330 331 static 332 findconst(str, val) 333 char **str; 334 char **val; 335 { 336 char *p; 337 int size; 338 339 p = *str; 340 if (*p == '0' && *(p + 1) == 'x') { 341 p++; 342 do { 343 p++; 344 } while (isxdigit(*p)); 345 } else { 346 do { 347 p++; 348 } while (isdigit(*p)); 349 } 350 size = p - *str; 351 *val = alloc(size + 1); 352 (void) strncpy(*val, *str, size); 353 (*val)[size] = 0; 354 *str = p; 355 } 356 357 358 359 static token symbols[] = { 360 {TOK_CONST, "const"}, 361 {TOK_UNION, "union"}, 362 {TOK_SWITCH, "switch"}, 363 {TOK_CASE, "case"}, 364 {TOK_DEFAULT, "default"}, 365 {TOK_STRUCT, "struct"}, 366 {TOK_TYPEDEF, "typedef"}, 367 {TOK_ENUM, "enum"}, 368 {TOK_OPAQUE, "opaque"}, 369 {TOK_BOOL, "bool"}, 370 {TOK_VOID, "void"}, 371 {TOK_CHAR, "char"}, 372 {TOK_INT, "int"}, 373 {TOK_UNSIGNED, "unsigned"}, 374 {TOK_SHORT, "short"}, 375 {TOK_LONG, "long"}, 376 {TOK_FLOAT, "float"}, 377 {TOK_DOUBLE, "double"}, 378 {TOK_STRING, "string"}, 379 {TOK_PROGRAM, "program"}, 380 {TOK_VERSION, "version"}, 381 {TOK_EOF, "??????"}, 382 }; 383 384 385 static 386 findkind(mark, tokp) 387 char **mark; 388 token *tokp; 389 { 390 391 int len; 392 token *s; 393 char *str; 394 395 str = *mark; 396 for (s = symbols; s->kind != TOK_EOF; s++) { 397 len = strlen(s->str); 398 if (strncmp(str, s->str, len) == 0) { 399 if (!isalnum(str[len]) && str[len] != '_') { 400 tokp->kind = s->kind; 401 tokp->str = s->str; 402 *mark = str + len; 403 return; 404 } 405 } 406 } 407 tokp->kind = TOK_IDENT; 408 for (len = 0; isalnum(str[len]) || str[len] == '_'; len++); 409 tokp->str = alloc(len + 1); 410 (void) strncpy(tokp->str, str, len); 411 tokp->str[len] = 0; 412 *mark = str + len; 413 } 414 415 static 416 cppline(line) 417 char *line; 418 { 419 return (line == curline && *line == '#'); 420 } 421 422 static 423 directive(line) 424 char *line; 425 { 426 return (line == curline && *line == '%'); 427 } 428 429 static 430 printdirective(line) 431 char *line; 432 { 433 f_print(fout, "%s", line + 1); 434 } 435 436 static 437 docppline(line, lineno, fname) 438 char *line; 439 int *lineno; 440 char **fname; 441 { 442 char *file; 443 int num; 444 char *p; 445 446 line++; 447 while (isspace(*line)) { 448 line++; 449 } 450 num = atoi(line); 451 while (isdigit(*line)) { 452 line++; 453 } 454 while (isspace(*line)) { 455 line++; 456 } 457 if (*line != '"') { 458 error("preprocessor error"); 459 } 460 line++; 461 p = file = alloc(strlen(line) + 1); 462 while (*line && *line != '"') { 463 *p++ = *line++; 464 } 465 if (*line == 0) { 466 error("preprocessor error"); 467 } 468 *p = 0; 469 if (*file == 0) { 470 *fname = NULL; 471 } else { 472 *fname = file; 473 } 474 *lineno = num - 1; 475 } 476