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