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