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