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