]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - warp/term.c
cgram: properly handle input errors
[bsdgames-darwin.git] / warp / term.c
1 /* Header: term.c,v 7.0.1.2 86/12/12 17:04:09 lwall Exp */
2
3 /* Log: term.c,v
4 * Revision 7.0.1.2 86/12/12 17:04:09 lwall
5 * Baseline for net release.
6 *
7 * Revision 7.0.1.1 86/10/16 10:53:20 lwall
8 * Added Damage. Fixed random bugs.
9 *
10 * Revision 7.0 86/10/08 15:14:02 lwall
11 * Split into separate files. Added amoebas and pirates.
12 *
13 */
14
15 #include "EXTERN.h"
16 #include "warp.h"
17 #include "bang.h"
18 #include "intrp.h"
19 #include "object.h"
20 #include "play.h"
21 #include "score.h"
22 #include "sig.h"
23 #include "us.h"
24 #include "util.h"
25 #include "weapon.h"
26 #include "INTERN.h"
27 #include "term.h"
28
29 int typeahead = false;
30
31 char tcarea[TCSIZE]; /* area for "compiled" termcap strings */
32
33 /* guarantee capability pointer != NULL */
34 /* (I believe terminfo will ignore the &tmpaddr argument.) */
35
36 #define Tgetstr(key) ((tstr = tgetstr(key,&tmpaddr)) ? tstr : nullstr)
37
38 #ifdef PUSHBACK
39 struct keymap {
40 char km_type[128];
41 union km_union {
42 struct keymap *km_km;
43 char *km_str;
44 } km_ptr[128];
45 };
46
47 #define KM_NOTHIN 0
48 #define KM_STRING 1
49 #define KM_KEYMAP 2
50 #define KM_BOGUS 3
51
52 #define KM_TMASK 3
53 #define KM_GSHIFT 4
54 #define KM_GMASK 7
55
56 typedef struct keymap KEYMAP;
57
58 KEYMAP *topmap INIT(NULL);
59
60 void mac_init(char *);
61 static KEYMAP *newkeymap(void);
62 void pushstring(char *);
63 #endif
64
65 /* terminal initialization */
66
67 void
68 term_init(void)
69 {
70 savetty(); /* remember current tty state */
71
72 #if defined(TERMIO) || defined(TERMIOS)
73 ospeed = cfgetospeed(&_tty);
74 ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */
75 KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */
76 #else
77 ospeed = _tty.sg_ospeed; /* for tputs() */
78 ERASECH = _tty.sg_erase; /* for finish_command() */
79 KILLCH = _tty.sg_kill; /* for finish_command() */
80 #endif
81
82 /* The following could be a table but I can't be sure that there isn't */
83 /* some degree of sparsity out there in the world. */
84
85 switch (ospeed) { /* 1 second of padding */
86 #ifdef BEXTA
87 case BEXTA: just_a_sec = 1920; break;
88 #else
89 #ifdef B19200
90 case B19200: just_a_sec = 1920; break;
91 #endif
92 #endif
93 case B9600: just_a_sec = 960; break;
94 case B4800: just_a_sec = 480; break;
95 case B2400: just_a_sec = 240; break;
96 case B1800: just_a_sec = 180; break;
97 case B1200: just_a_sec = 120; break;
98 case B600: just_a_sec = 60; break;
99 case B300: just_a_sec = 30; break;
100 /* do I really have to type the rest of this??? */
101 case B200: just_a_sec = 20; break;
102 case B150: just_a_sec = 15; break;
103 case B134: just_a_sec = 13; break;
104 case B110: just_a_sec = 11; break;
105 case B75: just_a_sec = 8; break;
106 case B50: just_a_sec = 5; break;
107 default: just_a_sec = 960; break;
108 /* if we are running detached I */
109 } /* don't want to know about it! */
110 }
111
112 /* set terminal characteristics */
113
114 void
115 term_set(char *tcbuf) /* temp area for "uncompiled" termcap entry */
116 {
117 char *tmpaddr; /* must not be register */
118 char *tstr;
119 char *s;
120 int retval;
121
122 #ifdef PENDING
123 #ifndef FIONREAD
124 #ifndef RDCHK
125 /* do no delay reads on something that always gets closed on exit */
126
127 devtty = open("/dev/tty",0);
128 if (devtty < 0) {
129 printf(cantopen,"/dev/tty");
130 finalize(1);
131 }
132 fcntl(devtty,F_SETFL,O_NDELAY);
133 #endif
134 #endif
135 #endif
136
137 /* get all that good termcap stuff */
138
139 retval = tgetent(tcbuf,getenv("TERM")); /* get termcap entry */
140 if (retval < 1) {
141 #ifdef VERBOSE
142 printf("No termcap %s found.\n", retval ? "file" : "entry");
143 #else
144 fputs("Termcap botch\n",stdout);
145 #endif
146 finalize(1);
147 }
148 tmpaddr = tcarea; /* set up strange tgetstr pointer */
149 s = Tgetstr("pc"); /* get pad character */
150 PC = *s; /* get it where tputs wants it */
151 if (!tgetflag("bs")) { /* is backspace not used? */
152 BC = Tgetstr("bc"); /* find out what is */
153 if (BC == nullstr) /* terminfo grok's 'bs' but not 'bc' */
154 BC = Tgetstr("le");
155 } else
156 BC = __UNCONST("\b"); /* make a backspace handy */
157 UP = Tgetstr("up"); /* move up a line */
158 ND = Tgetstr("nd"); /* non-destructive move cursor right */
159 DO = Tgetstr("do"); /* move cursor down */
160 if (!*DO)
161 DO = Tgetstr("nl");
162 CL = Tgetstr("cl"); /* get clear string */
163 CE = Tgetstr("ce"); /* clear to end of line string */
164 CM = Tgetstr("cm"); /* cursor motion - PWP */
165 HO = Tgetstr("ho"); /* home cursor if no CM - PWP */
166 CD = Tgetstr("cd"); /* clear to end of display - PWP */
167 SO = Tgetstr("so"); /* begin standout */
168 SE = Tgetstr("se"); /* end standout */
169 if ((SG = tgetnum("sg"))<0)
170 SG = 0; /* blanks left by SG, SE */
171 US = Tgetstr("us"); /* start underline */
172 UE = Tgetstr("ue"); /* end underline */
173 if ((UG = tgetnum("ug"))<0)
174 UG = 0; /* blanks left by US, UE */
175 if (*US)
176 UC = nullstr; /* UC must not be NULL */
177 else
178 UC = Tgetstr("uc"); /* underline a character */
179 if (!*US && !*UC) { /* no underline mode? */
180 US = SO; /* substitute standout mode */
181 UE = SE;
182 UG = SG;
183 }
184 LINES = tgetnum("li"); /* lines per page */
185 COLS = tgetnum("co"); /* columns on page */
186 AM = tgetflag("am"); /* terminal wraps automatically? */
187 XN = tgetflag("xn"); /* then eats next newline? */
188 VB = Tgetstr("vb");
189 if (!*VB)
190 VB = __UNCONST("\007");
191 CR = Tgetstr("cr");
192 if (!*CR) {
193 if (tgetflag("nc") && *UP) {
194 size_t l = strlen(UP) + 2;
195 CR = safemalloc(l);
196 snprintf(CR, l, "%s\r",UP);
197 }
198 else
199 CR = __UNCONST("\r");
200 }
201 if (LINES <= 0)
202 LINES = 24;
203 if (COLS <= 0)
204 COLS = 80;
205
206 BCsize = comp_tc(bsptr,BC,1);
207 BC = bsptr;
208
209 if (!*ND) /* not defined? */
210 NDsize = 1000; /* force cursor addressing */
211 else {
212 NDsize = comp_tc(cmbuffer,ND,1);
213 myND = malloc((unsigned)NDsize);
214 movc3(NDsize,cmbuffer,myND);
215 if (debugging) {
216 int scr;
217
218 printf("ND");
219 for (scr=0; scr<NDsize; scr++)
220 printf(" %d",myND[scr]);
221 printf("\n");
222 }
223 }
224
225 if (!*UP) /* not defined? */
226 UPsize = 1000; /* force cursor addressing */
227 else {
228 UPsize = comp_tc(cmbuffer,UP,1);
229 myUP = malloc((unsigned)UPsize);
230 movc3(UPsize,cmbuffer,myUP);
231 if (debugging) {
232 int scr;
233
234 printf("UP");
235 for (scr=0; scr<UPsize; scr++)
236 printf(" %d",myUP[scr]);
237 printf("\n");
238 }
239 }
240
241 if (!*DO) { /* not defined? */
242 myDO = DO = __UNCONST("\n"); /* assume a newline */
243 DOsize = 1;
244 }
245 else {
246 DOsize = comp_tc(cmbuffer,DO,1);
247 myDO = malloc((unsigned)DOsize);
248 movc3(DOsize,cmbuffer,myDO);
249 if (debugging) {
250 int scr;
251
252 printf("DO");
253 for (scr=0; scr<DOsize; scr++)
254 printf(" %d",myDO[scr]);
255 printf("\n");
256 }
257 }
258 if (debugging)
259 fgets(cmbuffer,(sizeof cmbuffer),stdin);
260
261 CMsize = comp_tc(cmbuffer,tgoto(CM,20,20),0);
262 if (PC != '\0') {
263 char *p;
264
265 for (p=filler+(sizeof filler)-1;!*p;--p)
266 *p = PC;
267 }
268 charsperhalfsec = (speed_t)ospeed >= B9600 ? (speed_t)480 :
269 (speed_t)ospeed == B4800 ? (speed_t)240 :
270 (speed_t)ospeed == B2400 ? (speed_t)120 :
271 (speed_t)ospeed == B1200 ? (speed_t)60 :
272 (speed_t)ospeed == B600 ? (speed_t)30 :
273 /* speed is 300 (?) */ (speed_t)15;
274
275 gfillen = (speed_t)ospeed >= B9600 ? (speed_t)(sizeof filler) :
276 (speed_t)ospeed == B4800 ? (speed_t)13 :
277 (speed_t)ospeed == B2400 ? (speed_t)7 :
278 (speed_t)ospeed == B1200 ? (speed_t)4 :
279 (speed_t)(1+BCsize);
280 if ((speed_t)ospeed < B2400)
281 lowspeed = true;
282
283 strcpy(term,ttyname(2));
284
285 if (!*CM || !BCsize)
286 no_can_do("dumb");
287 if (!scorespec && (LINES < 24 || COLS < 80))
288 no_can_do("puny");
289 // if (LINES > 25)
290 // no_can_do("humongous");
291
292 crmode();
293 raw();
294 noecho(); /* turn off echo */
295 nonl();
296
297 #ifdef PUSHBACK
298 mac_init(tcbuf);
299 #endif
300 }
301
302 #ifdef PUSHBACK
303 void
304 mac_init(char *tcbuf)
305 {
306 char tmpbuf[1024];
307
308 tmpfp = fopen(filexp(getval("WARPMACRO",WARPMACRO)),"r");
309 if (tmpfp != NULL) {
310 while (fgets(tcbuf,1024,tmpfp) != NULL) {
311 mac_line(tcbuf,tmpbuf,(sizeof tmpbuf));
312 }
313 fclose(tmpfp);
314 }
315 }
316
317 void
318 mac_line(char *line, char *tmpbuf, size_t tbsize)
319 {
320 char *s;
321 char *m;
322 KEYMAP *curmap;
323 int ch;
324 int garbage = 0;
325 static const char override[] = "\r\nkeymap overrides string\r\n";
326
327 if (topmap == NULL)
328 topmap = newkeymap();
329 if (*line == '#' || *line == '\n')
330 return;
331 if (line[ch = strlen(line)-1] == '\n')
332 line[ch] = '\0';
333 m = dointerp(tmpbuf,tbsize,line," \t");
334 if (!*m)
335 return;
336 while (*m == ' ' || *m == '\t') m++;
337 for (s=tmpbuf,curmap=topmap; *s; s++) {
338 ch = *s & 0177;
339 if (s[1] == '+' && isdigit((unsigned char)s[2])) {
340 s += 2;
341 garbage = (*s & KM_GMASK) << KM_GSHIFT;
342 }
343 else
344 garbage = 0;
345 if (s[1]) {
346 if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) {
347 puts(override);
348 free(curmap->km_ptr[ch].km_str);
349 curmap->km_ptr[ch].km_str = NULL;
350 }
351 curmap->km_type[ch] = KM_KEYMAP + garbage;
352 if (curmap->km_ptr[ch].km_km == NULL)
353 curmap->km_ptr[ch].km_km = newkeymap();
354 curmap = curmap->km_ptr[ch].km_km;
355 }
356 else {
357 if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP)
358 puts(override);
359 else {
360 curmap->km_type[ch] = KM_STRING + garbage;
361 curmap->km_ptr[ch].km_str = savestr(m);
362 }
363 }
364 }
365 }
366
367 static KEYMAP*
368 newkeymap(void)
369 {
370 int i;
371 KEYMAP *map;
372
373 #ifndef lint
374 map = (KEYMAP*)safemalloc(sizeof(KEYMAP));
375 #else
376 map = Null(KEYMAP*);
377 #endif /* lint */
378 for (i=127; i>=0; --i) {
379 map->km_ptr[i].km_km = NULL;
380 map->km_type[i] = KM_NOTHIN;
381 }
382 return map;
383 }
384
385 #endif
386
387 /* print out a file, stopping at form feeds */
388
389 void
390 page(const char *filename, size_t num)
391 {
392 int linenum = 1;
393
394 tmpfp = fopen(filename,"r");
395 if (tmpfp != NULL) {
396 while (fgets(spbuf,(sizeof spbuf),tmpfp) != NULL) {
397 if (*spbuf == '\f') {
398 printf("[Type anything to continue] ");
399 fflush(stdout);
400 getcmd(spbuf);
401 printf("\r\n");
402 if (*spbuf == INTRCH)
403 finalize(0);
404 if (*spbuf == 'q' || *spbuf == 'Q')
405 break;
406 }
407 else {
408 if (num)
409 printf("%3d %s\r",linenum++,spbuf);
410 else
411 printf("%s\r",spbuf);
412 }
413 }
414 fclose(tmpfp);
415 }
416 }
417
418 void
419 move(int y, int x, int chadd)
420 {
421 int ydist;
422 int xdist;
423 int i;
424 char *s;
425
426 ydist = y - real_y;
427 xdist = x - real_x;
428 i = ydist * (ydist < 0 ? -UPsize : DOsize) +
429 xdist * (xdist < 0 ? -BCsize : NDsize);
430 beg_qwrite();
431 if (i <= CMsize) {
432 if (ydist < 0)
433 for (; ydist; ydist++)
434 for (i=UPsize,s=myUP; i; i--)
435 qaddch(*s++);
436 else
437 for (; ydist; ydist--)
438 for (i=DOsize,s=myDO; i; i--)
439 qaddch(*s++);
440 if (xdist < 0)
441 for (; xdist; xdist++)
442 for (i=BCsize,s=BC; i; i--)
443 qaddch(*s++);
444 else
445 for (; xdist; xdist--)
446 for (i=NDsize,s=myND; i; i--)
447 qaddch(*s++);
448 }
449 else {
450 tputs(tgoto(CM,x,y),0,cmstore);
451 }
452 real_y = y;
453 real_x = x;
454 if (chadd) {
455 qaddch(chadd);
456 }
457 if (maxcmstring != cmbuffer)
458 end_qwrite();
459 }
460
461 void
462 do_tc(const char *s, int l)
463 {
464 beg_qwrite();
465 tputs(s,l,cmstore);
466 end_qwrite();
467 }
468
469 int
470 comp_tc(char *dest, const char *s, int l)
471 {
472 maxcmstring = dest;
473 tputs(s,l,cmstore);
474 return(maxcmstring-dest);
475 }
476
477 void
478 helper(void)
479 {
480 clear();
481 mvaddstr(0,4,"h or 4 left");
482 mvaddstr(1,4,"j or 2 down Use with SHIFT to fire torpedoes.");
483 mvaddstr(2,4,"k or 8 up Use with CTRL or FUNCT to fire");
484 mvaddstr(3,4,"l or 6 right phasers or turbolasers.");
485 mvaddstr(4,4,"b or 1 down and left Use preceded by 'a' or 'r' for");
486 mvaddstr(5,4,"n or 3 down and right attractors or repulsors.");
487 mvaddstr(6,4,"y or 7 up and left Use normally for E or B motion.");
488 mvaddstr(7,4,"u or 9 up and right");
489 mvaddstr(8,4,"");
490 mvaddstr(9,4,"del or % fire photon torpedoes in every (reasonable) direction.");
491 mvaddstr(10,4,"s stop all torpedoes.");
492 mvaddstr(11,4,"S or 0 stop the Enterprise when in warp mode.");
493 mvaddstr(12,4,"d/D destruct all torpedoes/current vessel.");
494 mvaddstr(13,4,"i/w switch to Enterprise & put into impulse/warp mode.");
495 mvaddstr(14,4,"c/v switch to Enterprise & make cloaked/visible.");
496 mvaddstr(15,4,"p switch to Base.");
497 mvaddstr(16,4,"o toggle to other vessel (from E to B, or vice versa.)");
498 mvaddstr(17,4,"z zap (suppress) blasts near Enterprise next cycle");
499 mvaddstr(18,4,"");
500 mvaddstr(19,4,"^R refresh the screen. ^Z suspend the game.");
501 mvaddstr(20,4,"q exit this round (if you haven't typed q within 10 cycles).");
502 mvaddstr(21,4,"Q exit this game.");
503 mvaddstr(22,4,"");
504 mvaddstr(23,4," [Hit space to continue]");
505 fflush(stdout);
506 do {
507 getcmd(spbuf);
508 } while (*spbuf != ' ');
509 rewrite();
510
511 }
512
513 void
514 rewrite(void)
515 {
516 int x;
517 int y;
518 OBJECT *obj;
519
520 clear();
521 for (y=0; y<YSIZE; y++) {
522 for (x=0; x<XSIZE; x++) {
523 if (numamoebas && amb[y][x] != ' ')
524 mvaddc(y+1,x*2,amb[y][x]);
525 if ((obj = occupant[y][x]) != NULL) {
526 if (obj->image != ' ')
527 mvaddc(y+1,x*2,obj->image);
528 }
529 }
530 }
531 snprintf(spbuf, sizeof(spbuf),
532 "%-4s E: %4d %2d B: %5d %3d Enemies: %-3d Stars: %-3d Stardate%5d.%1d %9ld",
533 " ", 0, 0, 0, 0, 0, 0, timer/10+smarts*100, timer%10, 0L);
534 mvaddstr(0,0,spbuf);
535 oldeenergy = oldbenergy = oldcurscore =
536 oldstatus = oldetorp = oldbtorp = oldstrs = oldenemies = -1;
537 /* force everything to fill in */
538 if (damage)
539 olddamage = 0;
540 if (!ent)
541 etorp = 0;
542 if (!base)
543 btorp = 0;
544 display_status();
545 }
546
547 int
548 cmstore(int ch)
549 {
550 *maxcmstring++ = ch;
551 return 0;
552 }
553
554 /* discard any characters typed ahead */
555
556 void
557 eat_typeahead(void)
558 {
559 #ifdef PUSHBACK
560 if (!typeahead && nextin==nextout) /* cancel only keyboard stuff */
561 #else
562 if (!typeahead)
563 #endif
564 {
565 #ifdef PENDING
566 while (input_pending())
567 read_tty(buf,sizeof(buf));
568 #else /* this is probably v7, with no rdchk() */
569 ioctl(_tty_ch,TIOCSETP,&_tty);
570 #endif
571 }
572 }
573
574 void
575 settle_down(void)
576 {
577 dingaling();
578 fflush(stdout);
579 sleep(1);
580 #ifdef PUSHBACK
581 nextout = nextin; /* empty circlebuf */
582 #endif
583 eat_typeahead();
584 }
585
586 #ifdef PUSHBACK
587 /* read a character from the terminal, with multi-character pushback */
588
589 int
590 read_tty(char *addr, ssize_t size) /* ignored for now */
591 {
592 if (nextout != nextin) {
593 *addr = circlebuf[nextout++];
594 nextout %= PUSHSIZE;
595 return 1;
596 }
597 else {
598 size = read(0,addr,1);
599 if (size < 0)
600 sig_catcher(SIGHUP);
601 if (metakey) {
602 if (*addr & 0200) {
603 pushchar(*addr & 0177);
604 *addr = '\001';
605 }
606 }
607 else
608 *addr &= 0177;
609 return 1;
610 }
611 }
612
613 #ifdef PENDING
614 #ifndef FIONREAD
615 #ifndef RDCHK
616 int
617 circfill()
618 {
619 int howmany;
620 int i;
621
622 assert (nextin == nextout);
623 howmany = read(devtty,circlebuf+nextin,metakey?1:PUSHSIZE-nextin);
624 if (howmany > 0) {
625 if (metakey) {
626 if (circlebuf[nextin] & 0200) {
627 circlebuf[nextin] &= 0177;
628 pushchar('\001');
629 }
630 }
631 else
632 for (i = howmany+nextin-1; i >= nextin; i--)
633 circlebuf[i] &= 0177;
634 nextin += howmany;
635 nextin %= PUSHSIZE; /* may end up 1 if metakey */
636 }
637 return howmany;
638 }
639 #endif /* RDCHK */
640 #endif /* FIONREAD */
641 #endif /* PENDING */
642
643 void
644 pushchar(int ch)
645 {
646 nextout--;
647 if (nextout < 0)
648 nextout = PUSHSIZE - 1;
649 if (nextout == nextin) {
650 fputs("\r\npushback buffer overflow\r\n",stdout);
651 sig_catcher(0);
652 }
653 circlebuf[nextout] = ch;
654 }
655
656 #else /* PUSHBACK */
657 #ifndef read_tty
658 /* read a character from the terminal, with hacks for O_NDELAY reads */
659
660 int
661 read_tty(addr,size)
662 char *addr;
663 int size;
664 {
665 if (is_input) {
666 *addr = pending_ch;
667 is_input = false;
668 return 1;
669 }
670 else {
671 size = read(0,addr,size);
672 if (size < 0)
673 sig_catcher(SIGHUP);
674 if (metakey) {
675 if (*addr & 0200) {
676 pending_ch = *addr & 0177;
677 is_input = true;
678 *addr = '\001';
679 }
680 }
681 else
682 *addr &= 0177;
683 return size;
684 }
685 }
686 #endif /* read_tty */
687 #endif /* PUSHBACK */
688
689 int
690 read_nd(char *buff, size_t siz)
691 {
692 if (!input_pending())
693 return 0;
694
695 getcmd(buff);
696 return 1;
697 }
698
699 /* get a character into a buffer */
700
701 void
702 getcmd(char *wbuf)
703 {
704 #ifdef PUSHBACK
705 KEYMAP *curmap;
706 int i;
707 bool no_macros;
708 int times = 0; /* loop detector */
709 char scrchar;
710 unsigned char *whatbuf = (void *)wbuf;
711
712 tryagain:
713 curmap = topmap;
714 /* no_macros = (whatbuf != buf && nextin == nextout); */
715 no_macros = false;
716 #endif
717 for (;;) {
718 errno = 0;
719 if (read_tty(wbuf,1) < 0 && !errno)
720 errno = EINTR;
721 #ifdef read_tty
722 if (metakey) {
723 if (*whatbuf & 0200) {
724 *what_buf &= 037; /* punt and hope they don't notice */
725 }
726 }
727 else
728 *whatbuf &= 0177;
729 #endif /* read_tty */
730 if (errno && errno != EINTR) {
731 perror(readerr);
732 sig_catcher(0);
733 }
734 #ifdef PUSHBACK
735 if (*whatbuf & 0200 || no_macros) {
736 *whatbuf &= 0177;
737 goto got_canonical;
738 }
739 if (curmap == NULL)
740 goto got_canonical;
741 for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){
742 read_tty(&scrchar,1);
743 }
744 switch (curmap->km_type[*whatbuf] & KM_TMASK) {
745 case KM_NOTHIN: /* no entry? */
746 if (curmap == topmap) /* unmapped canonical */
747 goto got_canonical;
748 settle_down();
749 goto tryagain;
750 case KM_KEYMAP: /* another keymap? */
751 curmap = curmap->km_ptr[*whatbuf].km_km;
752 assert(curmap != NULL);
753 break;
754 case KM_STRING: /* a string? */
755 pushstring(curmap->km_ptr[*whatbuf].km_str);
756 if (++times > 20) { /* loop? */
757 fputs("\r\nmacro loop?\r\n",stdout);
758 settle_down();
759 }
760 no_macros = false;
761 goto tryagain;
762 }
763 #else
764 *whatbuf &= 0177;
765 break;
766 #endif
767 }
768
769 got_canonical:
770 #if !defined(TERMIO) && !defined(TERMIOS)
771 if (*whatbuf == '\r')
772 *whatbuf = '\n';
773 #endif
774 if (wbuf == buf)
775 whatbuf[1] = FINISHCMD; /* tell finish_command to work */
776 }
777
778 #ifdef PUSHBACK
779 void
780 pushstring(char *str)
781 {
782 int i;
783 char tmpbuf[PUSHSIZE];
784 char *s = tmpbuf;
785
786 assert(str != NULL);
787 interp(s,PUSHSIZE,str);
788 for (i = strlen(s)-1; i >= 0; --i) {
789 s[i] ^= 0200;
790 pushchar(s[i]);
791 }
792 }
793 #endif