1 1.15 dholland /* $NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $ */ 2 1.1 glass /* 3 1.1 glass * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 4 1.1 glass * unrestricted use provided that this legend is included on all tape 5 1.1 glass * media and as a part of the software program in whole or part. Users 6 1.1 glass * may copy or modify Sun RPC without charge, but are not authorized 7 1.1 glass * to license or distribute it to anyone else except as part of a product or 8 1.4 pk * program developed by the user or with the express written consent of 9 1.4 pk * Sun Microsystems, Inc. 10 1.4 pk * 11 1.1 glass * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 1.1 glass * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 1.1 glass * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 1.4 pk * 15 1.1 glass * Sun RPC is provided with no support and without any obligation on the 16 1.1 glass * part of Sun Microsystems, Inc. to assist in its use, correction, 17 1.1 glass * modification or enhancement. 18 1.4 pk * 19 1.1 glass * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 1.1 glass * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 1.1 glass * OR ANY PART THEREOF. 22 1.4 pk * 23 1.1 glass * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 1.1 glass * or profits or other special, indirect and consequential damages, even if 25 1.1 glass * Sun has been advised of the possibility of such damages. 26 1.4 pk * 27 1.1 glass * Sun Microsystems, Inc. 28 1.1 glass * 2550 Garcia Avenue 29 1.1 glass * Mountain View, California 94043 30 1.1 glass */ 31 1.4 pk 32 1.9 jmc #if HAVE_NBTOOL_CONFIG_H 33 1.9 jmc #include "nbtool_config.h" 34 1.9 jmc #endif 35 1.9 jmc 36 1.5 christos #include <sys/cdefs.h> 37 1.8 tv #if defined(__RCSID) && !defined(lint) 38 1.5 christos #if 0 39 1.4 pk static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI"; 40 1.5 christos #else 41 1.15 dholland __RCSID("$NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $"); 42 1.5 christos #endif 43 1.1 glass #endif 44 1.1 glass 45 1.1 glass /* 46 1.6 lukem * rpc_scan.c, Scanner for the RPC protocol compiler 47 1.6 lukem * Copyright (C) 1987, Sun Microsystems, Inc. 48 1.1 glass */ 49 1.4 pk #include <stdlib.h> 50 1.1 glass #include <stdio.h> 51 1.1 glass #include <ctype.h> 52 1.4 pk #include <string.h> 53 1.1 glass #include "rpc_scan.h" 54 1.4 pk #include "rpc_parse.h" 55 1.1 glass #include "rpc_util.h" 56 1.1 glass 57 1.1 glass #define startcomment(where) (where[0] == '/' && where[1] == '*') 58 1.1 glass #define endcomment(where) (where[-1] == '*' && where[0] == '/') 59 1.1 glass 60 1.13 christos static void unget_token(token *); 61 1.13 christos static void findstrconst(char **, const char **); 62 1.13 christos static void findchrconst(char **, const char **); 63 1.13 christos static void findconst(char **, const char **); 64 1.13 christos static void findkind(char **, token *); 65 1.13 christos static int cppline(const char *); 66 1.13 christos static int directive(const char *); 67 1.13 christos static void printdirective(const char *); 68 1.13 christos static void docppline(char *, int *, const char **); 69 1.5 christos 70 1.6 lukem static int pushed = 0; /* is a token pushed */ 71 1.6 lukem static token lasttok; /* last token, if pushed */ 72 1.1 glass 73 1.1 glass /* 74 1.6 lukem * scan expecting 1 given token 75 1.1 glass */ 76 1.1 glass void 77 1.12 dholland scan(tok_kind expect, token *tokp) 78 1.1 glass { 79 1.1 glass get_token(tokp); 80 1.1 glass if (tokp->kind != expect) { 81 1.1 glass expected1(expect); 82 1.1 glass } 83 1.1 glass } 84 1.1 glass /* 85 1.6 lukem * scan expecting any of the 2 given tokens 86 1.1 glass */ 87 1.1 glass void 88 1.12 dholland scan2(tok_kind expect1, tok_kind expect2, token *tokp) 89 1.1 glass { 90 1.1 glass get_token(tokp); 91 1.1 glass if (tokp->kind != expect1 && tokp->kind != expect2) { 92 1.1 glass expected2(expect1, expect2); 93 1.1 glass } 94 1.1 glass } 95 1.1 glass /* 96 1.6 lukem * scan expecting any of the 3 given token 97 1.1 glass */ 98 1.1 glass void 99 1.12 dholland scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp) 100 1.1 glass { 101 1.1 glass get_token(tokp); 102 1.1 glass if (tokp->kind != expect1 && tokp->kind != expect2 103 1.1 glass && tokp->kind != expect3) { 104 1.1 glass expected3(expect1, expect2, expect3); 105 1.1 glass } 106 1.1 glass } 107 1.1 glass /* 108 1.6 lukem * scan expecting a constant, possibly symbolic 109 1.1 glass */ 110 1.1 glass void 111 1.12 dholland scan_num(token *tokp) 112 1.1 glass { 113 1.1 glass get_token(tokp); 114 1.1 glass switch (tokp->kind) { 115 1.1 glass case TOK_IDENT: 116 1.1 glass break; 117 1.1 glass default: 118 1.14 dholland error("Expected constant or identifier"); 119 1.1 glass } 120 1.1 glass } 121 1.1 glass /* 122 1.6 lukem * Peek at the next token 123 1.1 glass */ 124 1.1 glass void 125 1.12 dholland peek(token *tokp) 126 1.1 glass { 127 1.1 glass get_token(tokp); 128 1.1 glass unget_token(tokp); 129 1.1 glass } 130 1.1 glass /* 131 1.6 lukem * Peek at the next token and scan it if it matches what you expect 132 1.1 glass */ 133 1.1 glass int 134 1.12 dholland peekscan(tok_kind expect, token *tokp) 135 1.1 glass { 136 1.1 glass peek(tokp); 137 1.1 glass if (tokp->kind == expect) { 138 1.1 glass get_token(tokp); 139 1.1 glass return (1); 140 1.1 glass } 141 1.1 glass return (0); 142 1.1 glass } 143 1.1 glass /* 144 1.6 lukem * Get the next token, printing out any directive that are encountered. 145 1.1 glass */ 146 1.1 glass void 147 1.12 dholland get_token(token *tokp) 148 1.1 glass { 149 1.6 lukem int commenting; 150 1.1 glass 151 1.1 glass if (pushed) { 152 1.1 glass pushed = 0; 153 1.1 glass *tokp = lasttok; 154 1.1 glass return; 155 1.1 glass } 156 1.1 glass commenting = 0; 157 1.1 glass for (;;) { 158 1.1 glass if (*where == 0) { 159 1.1 glass for (;;) { 160 1.1 glass if (!fgets(curline, MAXLINESIZE, fin)) { 161 1.1 glass tokp->kind = TOK_EOF; 162 1.1 glass *where = 0; 163 1.1 glass return; 164 1.1 glass } 165 1.1 glass linenum++; 166 1.1 glass if (commenting) { 167 1.1 glass break; 168 1.6 lukem } else 169 1.6 lukem if (cppline(curline)) { 170 1.6 lukem docppline(curline, &linenum, 171 1.6 lukem &infilename); 172 1.6 lukem } else 173 1.6 lukem if (directive(curline)) { 174 1.6 lukem printdirective(curline); 175 1.6 lukem } else { 176 1.6 lukem break; 177 1.6 lukem } 178 1.1 glass } 179 1.1 glass where = curline; 180 1.6 lukem } else 181 1.7 christos if (isspace((unsigned char)*where)) { 182 1.7 christos while (isspace((unsigned char)*where)) { 183 1.6 lukem where++; /* eat */ 184 1.4 pk } 185 1.6 lukem } else 186 1.6 lukem if (commenting) { 187 1.6 lukem for (where++; *where; where++) { 188 1.6 lukem if (endcomment(where)) { 189 1.6 lukem where++; 190 1.6 lukem commenting--; 191 1.6 lukem break; 192 1.6 lukem } 193 1.6 lukem } 194 1.6 lukem } else 195 1.6 lukem if (startcomment(where)) { 196 1.6 lukem where += 2; 197 1.6 lukem commenting++; 198 1.6 lukem } else { 199 1.6 lukem break; 200 1.6 lukem } 201 1.1 glass } 202 1.1 glass 203 1.1 glass /* 204 1.6 lukem * 'where' is not whitespace, comment or directive Must be a token! 205 1.1 glass */ 206 1.1 glass switch (*where) { 207 1.1 glass case ':': 208 1.1 glass tokp->kind = TOK_COLON; 209 1.1 glass where++; 210 1.1 glass break; 211 1.1 glass case ';': 212 1.1 glass tokp->kind = TOK_SEMICOLON; 213 1.1 glass where++; 214 1.1 glass break; 215 1.1 glass case ',': 216 1.1 glass tokp->kind = TOK_COMMA; 217 1.1 glass where++; 218 1.1 glass break; 219 1.1 glass case '=': 220 1.1 glass tokp->kind = TOK_EQUAL; 221 1.1 glass where++; 222 1.1 glass break; 223 1.1 glass case '*': 224 1.1 glass tokp->kind = TOK_STAR; 225 1.1 glass where++; 226 1.1 glass break; 227 1.1 glass case '[': 228 1.1 glass tokp->kind = TOK_LBRACKET; 229 1.1 glass where++; 230 1.1 glass break; 231 1.1 glass case ']': 232 1.1 glass tokp->kind = TOK_RBRACKET; 233 1.1 glass where++; 234 1.1 glass break; 235 1.1 glass case '{': 236 1.1 glass tokp->kind = TOK_LBRACE; 237 1.1 glass where++; 238 1.1 glass break; 239 1.1 glass case '}': 240 1.1 glass tokp->kind = TOK_RBRACE; 241 1.1 glass where++; 242 1.1 glass break; 243 1.1 glass case '(': 244 1.1 glass tokp->kind = TOK_LPAREN; 245 1.1 glass where++; 246 1.1 glass break; 247 1.1 glass case ')': 248 1.1 glass tokp->kind = TOK_RPAREN; 249 1.1 glass where++; 250 1.1 glass break; 251 1.1 glass case '<': 252 1.1 glass tokp->kind = TOK_LANGLE; 253 1.1 glass where++; 254 1.1 glass break; 255 1.1 glass case '>': 256 1.1 glass tokp->kind = TOK_RANGLE; 257 1.1 glass where++; 258 1.1 glass break; 259 1.1 glass 260 1.1 glass case '"': 261 1.1 glass tokp->kind = TOK_STRCONST; 262 1.1 glass findstrconst(&where, &tokp->str); 263 1.1 glass break; 264 1.4 pk case '\'': 265 1.4 pk tokp->kind = TOK_CHARCONST; 266 1.4 pk findchrconst(&where, &tokp->str); 267 1.4 pk break; 268 1.1 glass 269 1.1 glass case '-': 270 1.1 glass case '0': 271 1.1 glass case '1': 272 1.1 glass case '2': 273 1.1 glass case '3': 274 1.1 glass case '4': 275 1.1 glass case '5': 276 1.1 glass case '6': 277 1.1 glass case '7': 278 1.1 glass case '8': 279 1.1 glass case '9': 280 1.1 glass tokp->kind = TOK_IDENT; 281 1.1 glass findconst(&where, &tokp->str); 282 1.1 glass break; 283 1.1 glass 284 1.1 glass default: 285 1.7 christos if (!(isalpha((unsigned char)*where) || *where == '_')) { 286 1.7 christos if (isprint((unsigned char)*where)) { 287 1.15 dholland error("Illegal character '%c' in file", *where); 288 1.1 glass } else { 289 1.15 dholland error("Illegal character %d in file", *where); 290 1.1 glass } 291 1.1 glass } 292 1.1 glass findkind(&where, tokp); 293 1.1 glass break; 294 1.1 glass } 295 1.1 glass } 296 1.1 glass 297 1.5 christos static void 298 1.12 dholland unget_token(token *tokp) 299 1.1 glass { 300 1.1 glass lasttok = *tokp; 301 1.1 glass pushed = 1; 302 1.1 glass } 303 1.1 glass 304 1.5 christos static void 305 1.12 dholland findstrconst(char **str, const char **val) 306 1.1 glass { 307 1.12 dholland char *p; 308 1.6 lukem int size; 309 1.12 dholland char *tmp; 310 1.1 glass 311 1.1 glass p = *str; 312 1.1 glass do { 313 1.5 christos p++; 314 1.1 glass } while (*p && *p != '"'); 315 1.1 glass if (*p == 0) { 316 1.14 dholland error("Unterminated string constant"); 317 1.1 glass } 318 1.1 glass p++; 319 1.1 glass size = p - *str; 320 1.12 dholland tmp = alloc(size + 1); 321 1.12 dholland (void) strncpy(tmp, *str, size); 322 1.12 dholland tmp[size] = 0; 323 1.12 dholland *val = tmp; 324 1.1 glass *str = p; 325 1.1 glass } 326 1.1 glass 327 1.5 christos static void 328 1.12 dholland findchrconst(char **str, const char **val) 329 1.4 pk { 330 1.12 dholland char *p; 331 1.6 lukem int size; 332 1.12 dholland char *tmp; 333 1.4 pk 334 1.4 pk p = *str; 335 1.4 pk do { 336 1.5 christos p++; 337 1.4 pk } while (*p && *p != '\''); 338 1.4 pk if (*p == 0) { 339 1.14 dholland error("Unterminated string constant"); 340 1.4 pk } 341 1.4 pk p++; 342 1.4 pk size = p - *str; 343 1.4 pk if (size != 3) { 344 1.14 dholland error("Empty character"); 345 1.4 pk } 346 1.12 dholland tmp = alloc(size + 1); 347 1.12 dholland (void) strncpy(tmp, *str, size); 348 1.12 dholland tmp[size] = 0; 349 1.12 dholland *val = tmp; 350 1.4 pk *str = p; 351 1.4 pk } 352 1.4 pk 353 1.5 christos static void 354 1.12 dholland findconst(char **str, const char **val) 355 1.1 glass { 356 1.12 dholland char *p; 357 1.6 lukem int size; 358 1.12 dholland char *tmp; 359 1.1 glass 360 1.1 glass p = *str; 361 1.1 glass if (*p == '0' && *(p + 1) == 'x') { 362 1.1 glass p++; 363 1.1 glass do { 364 1.1 glass p++; 365 1.7 christos } while (isxdigit((unsigned char)*p)); 366 1.1 glass } else { 367 1.1 glass do { 368 1.1 glass p++; 369 1.7 christos } while (isdigit((unsigned char)*p)); 370 1.1 glass } 371 1.1 glass size = p - *str; 372 1.12 dholland tmp = alloc(size + 1); 373 1.12 dholland (void) strncpy(tmp, *str, size); 374 1.12 dholland tmp[size] = 0; 375 1.12 dholland *val = tmp; 376 1.1 glass *str = p; 377 1.1 glass } 378 1.1 glass 379 1.12 dholland static const token symbols[] = { 380 1.6 lukem {TOK_CONST, "const"}, 381 1.6 lukem {TOK_UNION, "union"}, 382 1.6 lukem {TOK_SWITCH, "switch"}, 383 1.6 lukem {TOK_CASE, "case"}, 384 1.6 lukem {TOK_DEFAULT, "default"}, 385 1.6 lukem {TOK_STRUCT, "struct"}, 386 1.6 lukem {TOK_TYPEDEF, "typedef"}, 387 1.6 lukem {TOK_ENUM, "enum"}, 388 1.6 lukem {TOK_OPAQUE, "opaque"}, 389 1.6 lukem {TOK_BOOL, "bool"}, 390 1.6 lukem {TOK_VOID, "void"}, 391 1.6 lukem {TOK_CHAR, "char"}, 392 1.6 lukem {TOK_INT, "int"}, 393 1.6 lukem {TOK_UNSIGNED, "unsigned"}, 394 1.6 lukem {TOK_SHORT, "short"}, 395 1.6 lukem {TOK_LONG, "long"}, 396 1.11 ginsbach {TOK_HYPER, "hyper"}, 397 1.6 lukem {TOK_FLOAT, "float"}, 398 1.6 lukem {TOK_DOUBLE, "double"}, 399 1.11 ginsbach {TOK_QUAD, "quadruple"}, 400 1.6 lukem {TOK_STRING, "string"}, 401 1.6 lukem {TOK_PROGRAM, "program"}, 402 1.6 lukem {TOK_VERSION, "version"}, 403 1.6 lukem {TOK_EOF, "??????"}, 404 1.1 glass }; 405 1.1 glass 406 1.5 christos static void 407 1.12 dholland findkind(char **mark, token *tokp) 408 1.1 glass { 409 1.6 lukem int len; 410 1.12 dholland const token *s; 411 1.12 dholland char *str; 412 1.12 dholland char *tmp; 413 1.1 glass 414 1.1 glass str = *mark; 415 1.1 glass for (s = symbols; s->kind != TOK_EOF; s++) { 416 1.1 glass len = strlen(s->str); 417 1.1 glass if (strncmp(str, s->str, len) == 0) { 418 1.7 christos if (!isalnum((unsigned char)str[len]) && 419 1.7 christos str[len] != '_') { 420 1.1 glass tokp->kind = s->kind; 421 1.1 glass tokp->str = s->str; 422 1.1 glass *mark = str + len; 423 1.1 glass return; 424 1.1 glass } 425 1.1 glass } 426 1.1 glass } 427 1.1 glass tokp->kind = TOK_IDENT; 428 1.7 christos for (len = 0; isalnum((unsigned char)str[len]) || 429 1.7 christos str[len] == '_'; len++); 430 1.12 dholland tmp = alloc(len + 1); 431 1.12 dholland (void) strncpy(tmp, str, len); 432 1.12 dholland tmp[len] = 0; 433 1.12 dholland tokp->str = tmp; 434 1.1 glass *mark = str + len; 435 1.1 glass } 436 1.1 glass 437 1.5 christos static int 438 1.12 dholland cppline(const char *line) 439 1.1 glass { 440 1.1 glass return (line == curline && *line == '#'); 441 1.1 glass } 442 1.1 glass 443 1.5 christos static int 444 1.12 dholland directive(const char *line) 445 1.1 glass { 446 1.1 glass return (line == curline && *line == '%'); 447 1.1 glass } 448 1.1 glass 449 1.5 christos static void 450 1.12 dholland printdirective(const char *line) 451 1.1 glass { 452 1.1 glass f_print(fout, "%s", line + 1); 453 1.1 glass } 454 1.1 glass 455 1.5 christos static void 456 1.12 dholland docppline(char *line, int *lineno, const char **fname) 457 1.6 lukem { 458 1.6 lukem char *file; 459 1.6 lukem int num; 460 1.6 lukem char *p; 461 1.1 glass 462 1.1 glass line++; 463 1.7 christos while (isspace((unsigned char)*line)) { 464 1.1 glass line++; 465 1.1 glass } 466 1.1 glass num = atoi(line); 467 1.7 christos while (isdigit((unsigned char)*line)) { 468 1.1 glass line++; 469 1.1 glass } 470 1.7 christos while (isspace((unsigned char)*line)) { 471 1.1 glass line++; 472 1.1 glass } 473 1.1 glass if (*line != '"') { 474 1.14 dholland error("Preprocessor error"); 475 1.1 glass } 476 1.1 glass line++; 477 1.1 glass p = file = alloc(strlen(line) + 1); 478 1.1 glass while (*line && *line != '"') { 479 1.1 glass *p++ = *line++; 480 1.1 glass } 481 1.1 glass if (*line == 0) { 482 1.14 dholland error("Preprocessor error"); 483 1.1 glass } 484 1.1 glass *p = 0; 485 1.1 glass if (*file == 0) { 486 1.1 glass *fname = NULL; 487 1.10 elad free(file); 488 1.1 glass } else { 489 1.1 glass *fname = file; 490 1.1 glass } 491 1.1 glass *lineno = num - 1; 492 1.1 glass } 493