|
|
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.