Annotation of 43BSDTahoe/games/atc/input.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.