home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / atc / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  13.8 KB  |  664 lines

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