|
|
1.1 ! root 1: /********************************************************************* ! 2: * COPYRIGHT NOTICE * ! 3: ********************************************************************** ! 4: * This software is copyright (C) 1982 by Pavel Curtis * ! 5: * * ! 6: * Permission is granted to reproduce and distribute * ! 7: * this file by any means so long as no fee is charged * ! 8: * above a nominal handling fee and so long as this * ! 9: * notice is always included in the copies. * ! 10: * * ! 11: * Other rights are reserved except as explicitly granted * ! 12: * by written permission of the author. * ! 13: * Pavel Curtis * ! 14: * Computer Science Dept. * ! 15: * 405 Upson Hall * ! 16: * Cornell University * ! 17: * Ithaca, NY 14853 * ! 18: * * ! 19: * Ph- (607) 256-4934 * ! 20: * * ! 21: * Pavel.Cornell@Udel-Relay (ARPAnet) * ! 22: * decvax!cornell!pavel (UUCPnet) * ! 23: *********************************************************************/ ! 24: ! 25: /* ! 26: * comp_scan.c --- Lexical scanner for terminfo compiler. ! 27: * ! 28: * $Log: comp_scan.c,v $ ! 29: * Revision 1.1 92/03/13 10:45:48 bin ! 30: * Initial revision ! 31: * ! 32: * Revision 2.1 82/10/25 14:45:55 pavel ! 33: * Added Copyright Notice ! 34: * ! 35: * Revision 2.0 82/10/24 15:17:12 pavel ! 36: * Beta-one Test Release ! 37: * ! 38: * Revision 1.3 82/08/23 22:30:03 pavel ! 39: * The REAL Alpha-one Release Version ! 40: * ! 41: * Revision 1.2 82/08/19 19:10:06 pavel ! 42: * Alpha Test Release One ! 43: * ! 44: * Revision 1.1 82/08/12 18:37:46 pavel ! 45: * Initial revision ! 46: * ! 47: * ! 48: */ ! 49: ! 50: #ifndef COHERENT ! 51: static char RCSid[] = ! 52: "$Header: /src386/usr/bin/tic/RCS/comp_scan.c,v 1.1 92/03/13 10:45:48 bin Exp $"; ! 53: #endif ! 54: ! 55: #include <stdio.h> ! 56: #include <ctype.h> ! 57: #include "compiler.h" ! 58: ! 59: #define iswhite(ch) (ch == ' ' || ch == '\t') ! 60: ! 61: ! 62: static int first_column; /* See 'next_char()' below */ ! 63: ! 64: ! 65: ! 66: /* ! 67: * int ! 68: * get_token() ! 69: * ! 70: * Scans the input for the next token, storing the specifics in the ! 71: * global structure 'curr_token' and returning one of the following: ! 72: * ! 73: * NAMES A line beginning in column 1. 'name' ! 74: * will be set to point to everything up to ! 75: * but not including the first comma on the line. ! 76: * BOOLEAN An entry consisting of a name followed by ! 77: * a comma. 'name' will be set to point to the ! 78: * name of the capability. ! 79: * NUMBER An entry of the form ! 80: * name#digits, ! 81: * 'name' will be set to point to the capability ! 82: * name and 'valnumber' to the number given. ! 83: * STRING An entry of the form ! 84: * name=characters, ! 85: * 'name' is set to the capability name and ! 86: * 'valstring' to the string of characters, with ! 87: * input translations done. ! 88: * CANCEL An entry of the form ! 89: * name@, ! 90: * 'name' is set to the capability name and ! 91: * 'valnumber' to -1. ! 92: * EOF The end of the file has been reached. ! 93: * ! 94: */ ! 95: ! 96: int ! 97: get_token() ! 98: { ! 99: long number; ! 100: int type; ! 101: register char ch; ! 102: static char buffer[1024]; ! 103: register char *ptr; ! 104: int dot_flag = FALSE; ! 105: ! 106: while ((ch = next_char()) == '\n' || iswhite(ch)) ! 107: ; ! 108: ! 109: if (ch == EOF) ! 110: type = EOF; ! 111: else ! 112: { ! 113: if (ch == '.') ! 114: { ! 115: dot_flag = TRUE; ! 116: ! 117: while ((ch = next_char()) == ' ' || ch == '\t') ! 118: ; ! 119: } ! 120: ! 121: if (! isalnum(ch)) ! 122: { ! 123: warning("Illegal character - '%c'", ch); ! 124: panic_mode(','); ! 125: } ! 126: ! 127: ptr = buffer; ! 128: *(ptr++) = ch; ! 129: ! 130: if (first_column) ! 131: { ! 132: while ((ch = next_char()) != ',' && ch != '\n' && ch != EOF) ! 133: *(ptr++) = ch; ! 134: ! 135: if (ch == EOF) ! 136: err_abort("Premature EOF"); ! 137: else if (ch == '\n') { ! 138: warning("Newline in middle of terminal name"); ! 139: panic_mode(','); ! 140: } ! 141: ! 142: *ptr = '\0'; ! 143: curr_token.tk_name = buffer; ! 144: type = NAMES; ! 145: } ! 146: else ! 147: { ! 148: ch = next_char(); ! 149: while (isalnum(ch)) ! 150: { ! 151: *(ptr++) = ch; ! 152: ch = next_char(); ! 153: } ! 154: ! 155: *ptr++ = '\0'; ! 156: switch (ch) ! 157: { ! 158: case ',': ! 159: curr_token.tk_name = buffer; ! 160: type = BOOLEAN; ! 161: break; ! 162: ! 163: case '@': ! 164: if (next_char() != ',') ! 165: warning("Missing comma"); ! 166: curr_token.tk_name = buffer; ! 167: type = CANCEL; ! 168: break; ! 169: ! 170: case '#': ! 171: number = 0; ! 172: while (isdigit(ch = next_char())) ! 173: number = number * 10 + ch - '0'; ! 174: if (ch != ',') ! 175: warning("Missing comma"); ! 176: curr_token.tk_name = buffer; ! 177: curr_token.tk_valnumber = number; ! 178: type = NUMBER; ! 179: break; ! 180: ! 181: case '=': ! 182: ch = trans_string(ptr); ! 183: if (ch != ',') ! 184: warning("Missing comma"); ! 185: curr_token.tk_name = buffer; ! 186: curr_token.tk_valstring = ptr; ! 187: type = STRING; ! 188: break; ! 189: ! 190: default: ! 191: warning("Illegal character - '%c'", ch); ! 192: } ! 193: } /* end else (first_column == FALSE) */ ! 194: } /* end else (ch != EOF) */ ! 195: ! 196: if (dot_flag == TRUE) ! 197: DEBUG(8, "Commented out ", ""); ! 198: ! 199: if (debug_level >= 8) ! 200: { ! 201: fprintf(stderr, "Token: "); ! 202: switch (type) ! 203: { ! 204: case BOOLEAN: ! 205: fprintf(stderr, "Boolean; name='%s'\n", ! 206: curr_token.tk_name); ! 207: break; ! 208: ! 209: case NUMBER: ! 210: fprintf(stderr, "Number; name='%s', value=%d\n", ! 211: curr_token.tk_name, curr_token.tk_valnumber); ! 212: break; ! 213: ! 214: case STRING: ! 215: fprintf(stderr, "String; name='%s', value='%s'\n", ! 216: curr_token.tk_name, curr_token.tk_valstring); ! 217: break; ! 218: ! 219: case CANCEL: ! 220: fprintf(stderr, "Cancel; name='%s'\n", ! 221: curr_token.tk_name); ! 222: break; ! 223: ! 224: case NAMES: ! 225: ! 226: fprintf(stderr, "Names; value='%s'\n", ! 227: curr_token.tk_name); ! 228: break; ! 229: ! 230: case EOF: ! 231: fprintf(stderr, "End of file\n"); ! 232: break; ! 233: ! 234: default: ! 235: warning("Bad token type"); ! 236: } ! 237: } ! 238: ! 239: if (dot_flag == TRUE) /* if commented out, use the next one */ ! 240: type = get_token(); ! 241: ! 242: return(type); ! 243: } ! 244: ! 245: ! 246: ! 247: /* ! 248: * char ! 249: * next_char() ! 250: * ! 251: * Returns the next character in the input stream. Comments and leading ! 252: * white space are stripped. The global state variable 'firstcolumn' is ! 253: * set TRUE if the character returned is from the first column of the input ! 254: * line. The global variable curr_line is incremented for each new line. ! 255: * The global variable curr_file_pos is set to the file offset of the ! 256: * beginning of each line. ! 257: * ! 258: */ ! 259: ! 260: int curr_column = -1; ! 261: char line[1024]; ! 262: ! 263: char ! 264: next_char() ! 265: { ! 266: char *rtn_value; ! 267: long ftell(); ! 268: ! 269: if (curr_column < 0 || curr_column > 1023 || ! 270: line[curr_column] == '\0') ! 271: { ! 272: do ! 273: { ! 274: curr_file_pos = ftell(stdin); ! 275: ! 276: if ((rtn_value = fgets(line, 1024, stdin)) != NULL) ! 277: curr_line++; ! 278: } while (rtn_value != NULL && line[0] == '#'); ! 279: ! 280: if (rtn_value == NULL) ! 281: return (EOF); ! 282: ! 283: curr_column = 0; ! 284: while (iswhite(line[curr_column])) ! 285: curr_column++; ! 286: } ! 287: ! 288: if (curr_column == 0 && line[0] != '\n') ! 289: first_column = TRUE; ! 290: else ! 291: first_column = FALSE; ! 292: ! 293: return (line[curr_column++]); ! 294: } ! 295: ! 296: ! 297: backspace() ! 298: { ! 299: curr_column--; ! 300: ! 301: if (curr_column < 0) ! 302: syserr_abort("Backspaced off beginning of line"); ! 303: } ! 304: ! 305: ! 306: ! 307: /* ! 308: * reset_input() ! 309: * ! 310: * Resets the input-reading routines. Used after a seek has been done. ! 311: * ! 312: */ ! 313: ! 314: reset_input() ! 315: { ! 316: curr_column = -1; ! 317: } ! 318: ! 319: ! 320: ! 321: /* ! 322: * char ! 323: * trans_string(ptr) ! 324: * ! 325: * Reads characters using next_char() until encountering a comma, newline ! 326: * or end-of-file. The returned value is the character which caused ! 327: * reading to stop. The following translations are done on the input: ! 328: * ! 329: * ^X goes to ctrl-X (i.e. X & 037) ! 330: * {\E,\n,\r,\b,\t,\f} go to ! 331: * {ESCAPE,newline,carriage-return,backspace,tab,formfeed} ! 332: * {\^,\\} go to {carat,backslash} ! 333: * \ddd (for ddd = up to three octal digits) goes to ! 334: * the character ddd ! 335: * ! 336: * \e == \E ! 337: * \0 == \200 ! 338: * ! 339: */ ! 340: ! 341: char ! 342: trans_string(ptr) ! 343: char *ptr; ! 344: { ! 345: register int count = 0; ! 346: int number; ! 347: int i; ! 348: char ch; ! 349: ! 350: while ((ch = next_char()) != ',' && ch != EOF) ! 351: { ! 352: if (ch == '^') ! 353: { ! 354: ch = next_char(); ! 355: if (ch == EOF) ! 356: err_abort("Premature EOF"); ! 357: ! 358: if (! isprint(ch)) ! 359: { ! 360: warning("Illegal ^ character - '%c'", ch); ! 361: } ! 362: ! 363: *(ptr++) = ch & 037; ! 364: } ! 365: else if (ch == '\\') ! 366: { ! 367: ch = next_char(); ! 368: if (ch == EOF) ! 369: err_abort("Premature EOF"); ! 370: ! 371: if (ch >= '0' && ch <= '7') ! 372: { ! 373: number = ch - '0'; ! 374: for (i=0; i < 2; i++) ! 375: { ! 376: ch = next_char(); ! 377: if (ch == EOF) ! 378: err_abort("Premature EOF"); ! 379: ! 380: if (ch < '0' || ch > '7') ! 381: { ! 382: backspace(); ! 383: break; ! 384: } ! 385: ! 386: number = number * 8 + ch - '0'; ! 387: } ! 388: ! 389: if (number == 0) ! 390: number = 0200; ! 391: *(ptr++) = (char) number; ! 392: } ! 393: else ! 394: { ! 395: switch (ch) ! 396: { ! 397: case 'E': ! 398: case 'e': *(ptr++) = '\033'; break; ! 399: ! 400: case 'l': ! 401: case 'n': *(ptr++) = '\n'; break; ! 402: ! 403: case 'r': *(ptr++) = '\r'; break; ! 404: ! 405: case 'b': *(ptr++) = '\b'; break; ! 406: ! 407: case 's': *(ptr++) = ' '; break; ! 408: ! 409: case 'f': *(ptr++) = '\014'; break; ! 410: ! 411: case 't': *(ptr++) = '\t'; break; ! 412: ! 413: case '\\': *(ptr++) = '\\'; break; ! 414: ! 415: case '^': *(ptr++) = '^'; break; ! 416: ! 417: case ',': *(ptr++) = ','; break; ! 418: ! 419: case ':': *(ptr++) = ':'; break; ! 420: ! 421: default: ! 422: warning("Illegal character in \\ sequence"); ! 423: *(ptr++) = ch; ! 424: } /* endswitch (ch) */ ! 425: } /* endelse (ch < '0' || ch > '7') */ ! 426: } /* end else if (ch == '\\') */ ! 427: else ! 428: { ! 429: *(ptr++) = ch; ! 430: } ! 431: ! 432: count ++; ! 433: ! 434: if (count > 500) ! 435: warning("Very long string found. Missing comma?"); ! 436: } /* end while */ ! 437: ! 438: *ptr = '\0'; ! 439: ! 440: return(ch); ! 441: } ! 442: ! 443: /* ! 444: * Panic mode error recovery - skip everything until a "ch" is found. ! 445: */ ! 446: panic_mode(ch) ! 447: char ch; ! 448: { ! 449: int c; ! 450: ! 451: for (;;) { ! 452: c = next_char(); ! 453: if (c == ch) ! 454: return; ! 455: if (c == EOF); ! 456: return; ! 457: } ! 458: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.