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 edjames@berkeley.edu.
   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: }

Defined functions

Left defined in line 381; used 2 times
Right defined in line 390; used 2 times
airport defined in line 458; used 6 times
beacon defined in line 444; used 15 times
benum defined in line 512; used 2 times
circle defined in line 352; used 2 times
climb defined in line 465; used 3 times
delayb defined in line 399; used 2 times
descend defined in line 472; used 3 times
dir_no defined in line 607; used 4 times
ex_it defined in line 451; used 2 times
getcommand defined in line 203; used 1 times
gettoken defined in line 267; used 1 times
ignore defined in line 596; used 2 times
left defined in line 361; used 2 times
mark defined in line 574; used 2 times
noise defined in line 261; used 2 times
pop defined in line 156; used 2 times
push defined in line 182; used 1 times
rel_dir defined in line 550; used 9 times
rezero defined in line 170; used 1 times
right defined in line 371; used 2 times
setalt defined in line 479; used 2 times
setplane defined in line 331; used 2 times
setrelalt defined in line 488; used 2 times
to_dir defined in line 543; used 9 times
turn defined in line 344; used 2 times
unmark defined in line 585; used 2 times

Defined variables

dest_no defined in line 154; used 7 times
dest_type defined in line 154; used 7 times
dir defined in line 154; used 25 times
level defined in line 152; used 12 times
p defined in line 150; used 76 times
sccsid defined in line 11; never used
tval defined in line 153; used 9 times

Defined macros

ALPHATOKEN defined in line 26; used 3 times
CRTOKEN defined in line 21; used 4 times
DEF_STATE defined in line 140; used 13 times
HELPTOKEN defined in line 25; used 12 times
MAXDEPTH defined in line 17; used 1 times
MAXRULES defined in line 16; never used
NUMELS defined in line 55; used 2 times
NUMSTATES defined in line 57; never used
NUMTOKEN defined in line 27; used 5 times
REDRAWTOKEN defined in line 23; used 1 times
RETTOKEN defined in line 19; used 4 times
SHELLTOKEN defined in line 24; used 2 times
T_CH defined in line 53; used 3 times
T_POS defined in line 52; used 5 times
T_RULE defined in line 49; used 4 times
T_STATE defined in line 50; used 8 times
T_STR defined in line 51; used 6 times
Last modified: 1987-10-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5241
Valid CSS Valid XHTML 1.0 Strict