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