|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Ed James. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that: (1) source distributions retain this entire copyright ! 10: * notice and comment, and (2) distributions including binaries display ! 11: * the following acknowledgement: ``This product includes software ! 12: * developed by the University of California, Berkeley and its contributors'' ! 13: * in the documentation or other materials provided with the distribution ! 14: * and in all advertising materials mentioning features or use of this ! 15: * software. Neither the name of the University nor the names of its ! 16: * contributors may be used to endorse or promote products derived ! 17: * from this software without specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: /* ! 24: * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved. ! 25: * ! 26: * Copy permission is hereby granted provided that this notice is ! 27: * retained on all partial or complete copies. ! 28: * ! 29: * For more info on this and all of my stuff, mail [email protected]. ! 30: */ ! 31: ! 32: #ifndef lint ! 33: static char sccsid[] = "@(#)input.c 5.4 (Berkeley) 4/30/90"; ! 34: #endif not lint ! 35: ! 36: #include "include.h" ! 37: #include "pathnames.h" ! 38: ! 39: #define MAXRULES 6 ! 40: #define MAXDEPTH 15 ! 41: ! 42: #define RETTOKEN '\n' ! 43: #ifdef SYSV ! 44: #define CRTOKEN '\r' ! 45: #endif ! 46: #define REDRAWTOKEN '\014' /* CTRL(L) */ ! 47: #define SHELLTOKEN '!' ! 48: #define HELPTOKEN '?' ! 49: #define ALPHATOKEN 256 ! 50: #define NUMTOKEN 257 ! 51: ! 52: typedef struct { ! 53: int token; ! 54: int to_state; ! 55: char *str; ! 56: char *(*func)(); ! 57: } RULE; ! 58: ! 59: typedef struct { ! 60: int num_rules; ! 61: RULE *rule; ! 62: } STATE; ! 63: ! 64: typedef struct { ! 65: char str[20]; ! 66: int state; ! 67: int rule; ! 68: int ch; ! 69: int pos; ! 70: } STACK; ! 71: ! 72: #define T_RULE stack[level].rule ! 73: #define T_STATE stack[level].state ! 74: #define T_STR stack[level].str ! 75: #define T_POS stack[level].pos ! 76: #define T_CH stack[level].ch ! 77: ! 78: #define NUMELS(a) (sizeof (a) / sizeof (*(a))) ! 79: ! 80: #define NUMSTATES NUMELS(st) ! 81: ! 82: char *setplane(), *circle(), *left(), *right(), *Left(), *Right(), ! 83: *beacon(), *ex_it(), *climb(), *descend(), *setalt(), *setrelalt(), ! 84: *benum(), *to_dir(), *rel_dir(), *delayb(), *mark(), *unmark(), ! 85: *airport(), *turn(), *ignore(); ! 86: ! 87: RULE state0[] = { { ALPHATOKEN, 1, "%c:", setplane}, ! 88: { RETTOKEN, -1, "", NULL }, ! 89: #ifdef SYSV ! 90: { CRTOKEN, -1, "", NULL }, ! 91: #endif ! 92: { HELPTOKEN, 12, " [a-z]<ret>", NULL }}, ! 93: state1[] = { { 't', 2, " turn", turn }, ! 94: { 'a', 3, " altitude:", NULL }, ! 95: { 'c', 4, " circle", circle }, ! 96: { 'm', 7, " mark", mark }, ! 97: { 'u', 7, " unmark", unmark }, ! 98: { 'i', 7, " ignore", ignore }, ! 99: { HELPTOKEN, 12, " tacmui", NULL }}, ! 100: state2[] = { { 'l', 6, " left", left }, ! 101: { 'r', 6, " right", right }, ! 102: { 'L', 4, " left 90", Left }, ! 103: { 'R', 4, " right 90", Right }, ! 104: { 't', 11, " towards", NULL }, ! 105: { 'w', 4, " to 0", to_dir }, ! 106: { 'e', 4, " to 45", to_dir }, ! 107: { 'd', 4, " to 90", to_dir }, ! 108: { 'c', 4, " to 135", to_dir }, ! 109: { 'x', 4, " to 180", to_dir }, ! 110: { 'z', 4, " to 225", to_dir }, ! 111: { 'a', 4, " to 270", to_dir }, ! 112: { 'q', 4, " to 315", to_dir }, ! 113: { HELPTOKEN, 12, " lrLRt<dir>", NULL }}, ! 114: state3[] = { { '+', 10, " climb", climb }, ! 115: { 'c', 10, " climb", climb }, ! 116: { '-', 10, " descend", descend }, ! 117: { 'd', 10, " descend", descend }, ! 118: { NUMTOKEN, 7, " %c000 feet", setalt }, ! 119: { HELPTOKEN, 12, " +-cd[0-9]", NULL }}, ! 120: state4[] = { { '@', 9, " at", NULL }, ! 121: { 'a', 9, " at", NULL }, ! 122: { RETTOKEN, -1, "", NULL }, ! 123: #ifdef SYSV ! 124: { CRTOKEN, -1, "", NULL }, ! 125: #endif ! 126: { HELPTOKEN, 12, " @a<ret>", NULL }}, ! 127: state5[] = { { NUMTOKEN, 7, "%c", delayb }, ! 128: { HELPTOKEN, 12, " [0-9]", NULL }}, ! 129: state6[] = { { '@', 9, " at", NULL }, ! 130: { 'a', 9, " at", NULL }, ! 131: { 'w', 4, " 0", rel_dir }, ! 132: { 'e', 4, " 45", rel_dir }, ! 133: { 'd', 4, " 90", rel_dir }, ! 134: { 'c', 4, " 135", rel_dir }, ! 135: { 'x', 4, " 180", rel_dir }, ! 136: { 'z', 4, " 225", rel_dir }, ! 137: { 'a', 4, " 270", rel_dir }, ! 138: { 'q', 4, " 315", rel_dir }, ! 139: { RETTOKEN, -1, "", NULL }, ! 140: #ifdef SYSV ! 141: { CRTOKEN, -1, "", NULL }, ! 142: #endif ! 143: { HELPTOKEN, 12, " @a<dir><ret>",NULL }}, ! 144: state7[] = { { RETTOKEN, -1, "", NULL }, ! 145: #ifdef SYSV ! 146: { CRTOKEN, -1, "", NULL }, ! 147: #endif ! 148: { HELPTOKEN, 12, " <ret>", NULL }}, ! 149: state8[] = { { NUMTOKEN, 4, "%c", benum }, ! 150: { HELPTOKEN, 12, " [0-9]", NULL }}, ! 151: state9[] = { { 'b', 5, " beacon #", NULL }, ! 152: { '*', 5, " beacon #", NULL }, ! 153: { HELPTOKEN, 12, " b*", NULL }}, ! 154: state10[] = { { NUMTOKEN, 7, " %c000 ft", setrelalt}, ! 155: { HELPTOKEN, 12, " [0-9]", NULL }}, ! 156: state11[] = { { 'b', 8, " beacon #", beacon }, ! 157: { '*', 8, " beacon #", beacon }, ! 158: { 'e', 8, " exit #", ex_it }, ! 159: { 'a', 8, " airport #", airport }, ! 160: { HELPTOKEN, 12, " b*ea", NULL }}, ! 161: state12[] = { { -1, -1, "", NULL }}; ! 162: ! 163: #define DEF_STATE(s) { NUMELS(s), (s) } ! 164: ! 165: STATE st[] = { ! 166: DEF_STATE(state0), DEF_STATE(state1), DEF_STATE(state2), ! 167: DEF_STATE(state3), DEF_STATE(state4), DEF_STATE(state5), ! 168: DEF_STATE(state6), DEF_STATE(state7), DEF_STATE(state8), ! 169: DEF_STATE(state9), DEF_STATE(state10), DEF_STATE(state11), ! 170: DEF_STATE(state12) ! 171: }; ! 172: ! 173: PLANE p; ! 174: STACK stack[MAXDEPTH]; ! 175: int level; ! 176: int tval; ! 177: int dest_type, dest_no, dir; ! 178: ! 179: pop() ! 180: { ! 181: if (level == 0) ! 182: return (-1); ! 183: level--; ! 184: ! 185: ioclrtoeol(T_POS); ! 186: ! 187: strcpy(T_STR, ""); ! 188: T_RULE = -1; ! 189: T_CH = -1; ! 190: return (0); ! 191: } ! 192: ! 193: rezero() ! 194: { ! 195: iomove(0); ! 196: ! 197: level = 0; ! 198: T_STATE = 0; ! 199: T_RULE = -1; ! 200: T_CH = -1; ! 201: T_POS = 0; ! 202: strcpy(T_STR, ""); ! 203: } ! 204: ! 205: push(ruleno, ch) ! 206: { ! 207: int newstate, newpos; ! 208: ! 209: (void)sprintf(T_STR, st[T_STATE].rule[ruleno].str, tval); ! 210: T_RULE = ruleno; ! 211: T_CH = ch; ! 212: newstate = st[T_STATE].rule[ruleno].to_state; ! 213: newpos = T_POS + strlen(T_STR); ! 214: ! 215: ioaddstr(T_POS, T_STR); ! 216: ! 217: if (level == 0) ! 218: ioclrtobot(); ! 219: level++; ! 220: T_STATE = newstate; ! 221: T_POS = newpos; ! 222: T_RULE = -1; ! 223: strcpy(T_STR, ""); ! 224: } ! 225: ! 226: getcommand() ! 227: { ! 228: int c, i, done; ! 229: char *s, *(*func)(); ! 230: PLANE *pp; ! 231: ! 232: rezero(); ! 233: ! 234: do { ! 235: c = gettoken(); ! 236: if (c == tty_new.sg_erase) { ! 237: if (pop() < 0) ! 238: noise(); ! 239: } else if (c == tty_new.sg_kill) { ! 240: while (pop() >= 0) ! 241: ; ! 242: } else { ! 243: done = 0; ! 244: for (i = 0; i < st[T_STATE].num_rules; i++) { ! 245: if (st[T_STATE].rule[i].token == c || ! 246: st[T_STATE].rule[i].token == tval) { ! 247: push(i, (c >= ALPHATOKEN) ? tval : c); ! 248: done = 1; ! 249: break; ! 250: } ! 251: } ! 252: if (!done) ! 253: noise(); ! 254: } ! 255: } while (T_STATE != -1); ! 256: ! 257: if (level == 1) ! 258: return (1); /* forced update */ ! 259: ! 260: dest_type = T_NODEST; ! 261: ! 262: for (i = 0; i < level; i++) { ! 263: func = st[stack[i].state].rule[stack[i].rule].func; ! 264: if (func != NULL) ! 265: if ((s = (*func)(stack[i].ch)) != NULL) { ! 266: ioerror(stack[i].pos, strlen(stack[i].str), s); ! 267: return (-1); ! 268: } ! 269: } ! 270: ! 271: pp = findplane(p.plane_no); ! 272: if (pp->new_altitude != p.new_altitude) ! 273: pp->new_altitude = p.new_altitude; ! 274: else if (pp->status != p.status) ! 275: pp->status = p.status; ! 276: else { ! 277: pp->new_dir = p.new_dir; ! 278: pp->delayd = p.delayd; ! 279: pp->delayd_no = p.delayd_no; ! 280: } ! 281: return (0); ! 282: } ! 283: ! 284: noise() ! 285: { ! 286: putchar('\07'); ! 287: fflush(stdout); ! 288: } ! 289: ! 290: gettoken() ! 291: { ! 292: while ((tval = getAChar()) == REDRAWTOKEN || tval == SHELLTOKEN) ! 293: { ! 294: if (tval == SHELLTOKEN) ! 295: { ! 296: #ifdef BSD ! 297: struct itimerval itv; ! 298: itv.it_value.tv_sec = 0; ! 299: itv.it_value.tv_usec = 0; ! 300: setitimer(ITIMER_REAL, &itv, NULL); ! 301: #endif ! 302: #ifdef SYSV ! 303: int aval; ! 304: aval = alarm(0); ! 305: #endif ! 306: if (fork() == 0) /* child */ ! 307: { ! 308: char *shell, *base, *getenv(), *strrchr(); ! 309: ! 310: setuid(getuid()); /* turn off setuid bit */ ! 311: done_screen(); ! 312: ! 313: /* run user's favorite shell */ ! 314: if ((shell = getenv("SHELL")) != NULL) ! 315: { ! 316: base = strrchr(shell, '/'); ! 317: if (base == NULL) ! 318: base = shell; ! 319: else ! 320: base++; ! 321: execl(shell, base, 0); ! 322: } ! 323: else ! 324: execl(_PATH_BSHELL, "sh", 0); ! 325: ! 326: exit(0); /* oops */ ! 327: } ! 328: ! 329: wait(0); ! 330: #ifdef BSD ! 331: ioctl(fileno(stdin), TIOCSETP, &tty_new); ! 332: itv.it_value.tv_sec = 0; ! 333: itv.it_value.tv_usec = 1; ! 334: itv.it_interval.tv_sec = sp->update_secs; ! 335: itv.it_interval.tv_usec = 0; ! 336: setitimer(ITIMER_REAL, &itv, NULL); ! 337: #endif ! 338: #ifdef SYSV ! 339: ioctl(fileno(stdin), TCSETAW, &tty_new); ! 340: alarm(aval); ! 341: #endif ! 342: } ! 343: redraw(); ! 344: } ! 345: ! 346: if (isdigit(tval)) ! 347: return (NUMTOKEN); ! 348: else if (isalpha(tval)) ! 349: return (ALPHATOKEN); ! 350: else ! 351: return (tval); ! 352: } ! 353: ! 354: char * ! 355: setplane(c) ! 356: { ! 357: PLANE *pp; ! 358: ! 359: pp = findplane(number(c)); ! 360: if (pp == NULL) ! 361: return ("Unknown Plane"); ! 362: bcopy(pp, &p, sizeof (p)); ! 363: p.delayd = 0; ! 364: return (NULL); ! 365: } ! 366: ! 367: char * ! 368: turn(c) ! 369: { ! 370: if (p.altitude == 0) ! 371: return ("Planes at airports may not change direction"); ! 372: return (NULL); ! 373: } ! 374: ! 375: char * ! 376: circle(c) ! 377: { ! 378: if (p.altitude == 0) ! 379: return ("Planes cannot circle on the ground"); ! 380: p.new_dir = MAXDIR; ! 381: return (NULL); ! 382: } ! 383: ! 384: char * ! 385: left(c) ! 386: { ! 387: dir = D_LEFT; ! 388: p.new_dir = p.dir - 1; ! 389: if (p.new_dir < 0) ! 390: p.new_dir += MAXDIR; ! 391: return (NULL); ! 392: } ! 393: ! 394: char * ! 395: right(c) ! 396: { ! 397: dir = D_RIGHT; ! 398: p.new_dir = p.dir + 1; ! 399: if (p.new_dir > MAXDIR) ! 400: p.new_dir -= MAXDIR; ! 401: return (NULL); ! 402: } ! 403: ! 404: char * ! 405: Left(c) ! 406: { ! 407: p.new_dir = p.dir - 2; ! 408: if (p.new_dir < 0) ! 409: p.new_dir += MAXDIR; ! 410: return (NULL); ! 411: } ! 412: ! 413: char * ! 414: Right(c) ! 415: { ! 416: p.new_dir = p.dir + 2; ! 417: if (p.new_dir > MAXDIR) ! 418: p.new_dir -= MAXDIR; ! 419: return (NULL); ! 420: } ! 421: ! 422: char * ! 423: delayb(c) ! 424: { ! 425: int xdiff, ydiff; ! 426: ! 427: c -= '0'; ! 428: ! 429: if (c >= sp->num_beacons) ! 430: return ("Unknown beacon"); ! 431: xdiff = sp->beacon[c].x - p.xpos; ! 432: xdiff = SGN(xdiff); ! 433: ydiff = sp->beacon[c].y - p.ypos; ! 434: ydiff = SGN(ydiff); ! 435: if (xdiff != displacement[p.dir].dx || ydiff != displacement[p.dir].dy) ! 436: return ("Beacon is not in flight path"); ! 437: p.delayd = 1; ! 438: p.delayd_no = c; ! 439: ! 440: if (dest_type != T_NODEST) { ! 441: switch (dest_type) { ! 442: case T_BEACON: ! 443: xdiff = sp->beacon[dest_no].x - sp->beacon[c].x; ! 444: ydiff = sp->beacon[dest_no].y - sp->beacon[c].y; ! 445: break; ! 446: case T_EXIT: ! 447: xdiff = sp->exit[dest_no].x - sp->beacon[c].x; ! 448: ydiff = sp->exit[dest_no].y - sp->beacon[c].y; ! 449: break; ! 450: case T_AIRPORT: ! 451: xdiff = sp->airport[dest_no].x - sp->beacon[c].x; ! 452: ydiff = sp->airport[dest_no].y - sp->beacon[c].y; ! 453: break; ! 454: default: ! 455: return ("Bad case in delayb! Get help!"); ! 456: break; ! 457: } ! 458: if (xdiff == 0 && ydiff == 0) ! 459: return ("Would already be there"); ! 460: p.new_dir = DIR_FROM_DXDY(xdiff, ydiff); ! 461: if (p.new_dir == p.dir) ! 462: return ("Already going in that direction"); ! 463: } ! 464: return (NULL); ! 465: } ! 466: ! 467: char * ! 468: beacon(c) ! 469: { ! 470: dest_type = T_BEACON; ! 471: return (NULL); ! 472: } ! 473: ! 474: char * ! 475: ex_it(c) ! 476: { ! 477: dest_type = T_EXIT; ! 478: return (NULL); ! 479: } ! 480: ! 481: char * ! 482: airport(c) ! 483: { ! 484: dest_type = T_AIRPORT; ! 485: return (NULL); ! 486: } ! 487: ! 488: char * ! 489: climb(c) ! 490: { ! 491: dir = D_UP; ! 492: return (NULL); ! 493: } ! 494: ! 495: char * ! 496: descend(c) ! 497: { ! 498: dir = D_DOWN; ! 499: return (NULL); ! 500: } ! 501: ! 502: char * ! 503: setalt(c) ! 504: { ! 505: if ((p.altitude == c - '0') && (p.new_altitude == p.altitude)) ! 506: return ("Already at that altitude"); ! 507: p.new_altitude = c - '0'; ! 508: return (NULL); ! 509: } ! 510: ! 511: char * ! 512: setrelalt(c) ! 513: { ! 514: if (c == 0) ! 515: return ("altitude not changed"); ! 516: ! 517: switch (dir) { ! 518: case D_UP: ! 519: p.new_altitude = p.altitude + c - '0'; ! 520: break; ! 521: case D_DOWN: ! 522: p.new_altitude = p.altitude - (c - '0'); ! 523: break; ! 524: default: ! 525: return ("Unknown case in setrelalt! Get help!"); ! 526: break; ! 527: } ! 528: if (p.new_altitude < 0) ! 529: return ("Altitude would be too low"); ! 530: else if (p.new_altitude > 9) ! 531: return ("Altitude would be too high"); ! 532: return (NULL); ! 533: } ! 534: ! 535: char * ! 536: benum(c) ! 537: { ! 538: dest_no = c -= '0'; ! 539: ! 540: switch (dest_type) { ! 541: case T_BEACON: ! 542: if (c >= sp->num_beacons) ! 543: return ("Unknown beacon"); ! 544: p.new_dir = DIR_FROM_DXDY(sp->beacon[c].x - p.xpos, ! 545: sp->beacon[c].y - p.ypos); ! 546: break; ! 547: case T_EXIT: ! 548: if (c >= sp->num_exits) ! 549: return ("Unknown exit"); ! 550: p.new_dir = DIR_FROM_DXDY(sp->exit[c].x - p.xpos, ! 551: sp->exit[c].y - p.ypos); ! 552: break; ! 553: case T_AIRPORT: ! 554: if (c >= sp->num_airports) ! 555: return ("Unknown airport"); ! 556: p.new_dir = DIR_FROM_DXDY(sp->airport[c].x - p.xpos, ! 557: sp->airport[c].y - p.ypos); ! 558: break; ! 559: default: ! 560: return ("Unknown case in benum! Get help!"); ! 561: break; ! 562: } ! 563: return (NULL); ! 564: } ! 565: ! 566: char * ! 567: to_dir(c) ! 568: { ! 569: p.new_dir = dir_no(c); ! 570: return (NULL); ! 571: } ! 572: ! 573: char * ! 574: rel_dir(c) ! 575: { ! 576: int angle; ! 577: ! 578: angle = dir_no(c); ! 579: switch (dir) { ! 580: case D_LEFT: ! 581: p.new_dir = p.dir - angle; ! 582: if (p.new_dir < 0) ! 583: p.new_dir += MAXDIR; ! 584: break; ! 585: case D_RIGHT: ! 586: p.new_dir = p.dir + angle; ! 587: if (p.new_dir >= MAXDIR) ! 588: p.new_dir -= MAXDIR; ! 589: break; ! 590: default: ! 591: return ("Bizarre direction in rel_dir! Get help!"); ! 592: break; ! 593: } ! 594: return (NULL); ! 595: } ! 596: ! 597: char * ! 598: mark(c) ! 599: { ! 600: if (p.altitude == 0) ! 601: return ("Cannot mark planes on the ground"); ! 602: if (p.status == S_MARKED) ! 603: return ("Already marked"); ! 604: p.status = S_MARKED; ! 605: return (NULL); ! 606: } ! 607: ! 608: char * ! 609: unmark(c) ! 610: { ! 611: if (p.altitude == 0) ! 612: return ("Cannot unmark planes on the ground"); ! 613: if (p.status == S_UNMARKED) ! 614: return ("Already unmarked"); ! 615: p.status = S_UNMARKED; ! 616: return (NULL); ! 617: } ! 618: ! 619: char * ! 620: ignore(c) ! 621: { ! 622: if (p.altitude == 0) ! 623: return ("Cannot ignore planes on the ground"); ! 624: if (p.status == S_IGNORED) ! 625: return ("Already ignored"); ! 626: p.status = S_IGNORED; ! 627: return (NULL); ! 628: } ! 629: ! 630: dir_no(ch) ! 631: char ch; ! 632: { ! 633: int dir; ! 634: ! 635: switch (ch) { ! 636: case 'w': dir = 0; break; ! 637: case 'e': dir = 1; break; ! 638: case 'd': dir = 2; break; ! 639: case 'c': dir = 3; break; ! 640: case 'x': dir = 4; break; ! 641: case 'z': dir = 5; break; ! 642: case 'a': dir = 6; break; ! 643: case 'q': dir = 7; break; ! 644: default: ! 645: fprintf(stderr, "bad character in dir_no\n"); ! 646: break; ! 647: } ! 648: return (dir); ! 649: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.