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