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