xref: /csrg-svn/games/adventure/io.c (revision 47851)
1*47851Sbostic /*-
2*47851Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*47851Sbostic  * All rights reserved.
4*47851Sbostic  *
5*47851Sbostic  * The game adventure was original written Fortran by Will Crowther
6*47851Sbostic  * and Don Woods.  It was later translated to C and enhanced by
7*47851Sbostic  * Jim Gillogly.
8*47851Sbostic  *
9*47851Sbostic  * %sccs.include.redist.c%
10*47851Sbostic  */
11*47851Sbostic 
12*47851Sbostic #ifndef lint
13*47851Sbostic static char sccsid[] = "@(#)io.c	5.1 (Berkeley) 04/08/91";
14*47851Sbostic #endif /* not lint */
15*47851Sbostic 
166736Srrh /*      Re-coding of advent in C: file i/o and user i/o                 */
176736Srrh 
186736Srrh #include "hdr.h"
196736Srrh #include <stdio.h>
206736Srrh 
216736Srrh 
226736Srrh getin(wrd1,wrd2)                        /* get command from user        */
236736Srrh char **wrd1,**wrd2;                     /* no prompt, usually           */
246736Srrh {       register char *s;
256736Srrh 	static char wd1buf[MAXSTR],wd2buf[MAXSTR];
266736Srrh 	int first, numch;
276736Srrh 
286736Srrh 	*wrd1=wd1buf;                   /* return ptr to internal string*/
296736Srrh 	*wrd2=wd2buf;
306736Srrh 	wd2buf[0]=0;                    /* in case it isn't set here    */
316736Srrh 	for (s=wd1buf, first=1, numch=0;;)
326736Srrh 	{       if ((*s=getchar())>='A' && *s <='Z') *s = *s - ('A' -'a');
336736Srrh 					/* convert to upper case        */
346736Srrh 		switch(*s)              /* start reading from user      */
356736Srrh 		{   case '\n':
366736Srrh 			*s=0;
376736Srrh 			return;
386736Srrh 		    case ' ':
396736Srrh 			if (s==wd1buf||s==wd2buf)  /* initial blank   */
406736Srrh 				continue;
416736Srrh 			*s=0;
426736Srrh 			if (first)      /* finished 1st wd; start 2nd   */
436736Srrh 			{       first=numch=0;
446736Srrh 				s=wd2buf;
456736Srrh 				break;
466736Srrh 			}
476736Srrh 			else            /* finished 2nd word            */
486736Srrh 			{       FLUSHLINE;
496736Srrh 				*s=0;
506736Srrh 				return;
516736Srrh 			}
526736Srrh 		    default:
536736Srrh 			if (++numch>=MAXSTR)    /* string too long      */
546736Srrh 			{       printf("Give me a break!!\n");
556736Srrh 				wd1buf[0]=wd2buf[0]=0;
566736Srrh 				FLUSHLINE;
576736Srrh 				return;
586736Srrh 			}
596736Srrh 			s++;
606736Srrh 		}
616736Srrh 	}
626736Srrh }
636736Srrh 
646736Srrh 
656736Srrh confirm(mesg)                           /* confirm irreversible action  */
666736Srrh char *mesg;
676736Srrh {       register int result;
686736Srrh 	printf("%s",mesg);              /* tell him what he did         */
696736Srrh 	if (getchar()=='y')             /* was his first letter a 'y'?  */
706736Srrh 		result=1;
716736Srrh 	else    result=0;
726736Srrh 	FLUSHLINE;
736736Srrh 	return(result);
746736Srrh }
756736Srrh 
766736Srrh yes(x,y,z)                              /* confirm with rspeak          */
776736Srrh int x,y,z;
786736Srrh {       register int result;
796736Srrh 	register char ch;
806736Srrh 	for (;;)
816736Srrh 	{       rspeak(x);                     /* tell him what we want*/
826736Srrh 		if ((ch=getchar())=='y')
836736Srrh 			result=TRUE;
846736Srrh 		else if (ch=='n') result=FALSE;
856736Srrh 		FLUSHLINE;
866736Srrh 		if (ch=='y'|| ch=='n') break;
876736Srrh 		printf("Please answer the question.\n");
886736Srrh 	}
896736Srrh 	if (result==TRUE) rspeak(y);
906736Srrh 	if (result==FALSE) rspeak(z);
916736Srrh 	return(result);
926736Srrh }
936736Srrh 
946736Srrh yesm(x,y,z)                             /* confirm with mspeak          */
956736Srrh int x,y,z;
966736Srrh {       register int result;
976736Srrh 	register char ch;
986736Srrh 	for (;;)
996736Srrh 	{       mspeak(x);                     /* tell him what we want*/
1006736Srrh 		if ((ch=getchar())=='y')
1016736Srrh 			result=TRUE;
1026736Srrh 		else if (ch=='n') result=FALSE;
1036736Srrh 		FLUSHLINE;
1046736Srrh 		if (ch=='y'|| ch=='n') break;
1056736Srrh 		printf("Please answer the question.\n");
1066736Srrh 	}
1076736Srrh 	if (result==TRUE) mspeak(y);
1086736Srrh 	if (result==FALSE) mspeak(z);
1096736Srrh 	return(result);
1106736Srrh }
1116736Srrh 
1126736Srrh FILE *inbuf,*outbuf;
1136736Srrh 
1146736Srrh int adrptr;                             /* current seek adr ptr         */
1156736Srrh int outsw = 0;				/* putting stuff to data file?  */
1166736Srrh 
1176736Srrh char iotape[] = "Ax3F'tt$8hqer*hnGKrX:!l";
1186736Srrh char *tape = iotape;			/* pointer to encryption tape   */
1196736Srrh 
1206736Srrh next()                                  /* next char frm file, bump adr */
1216736Srrh {       register char ch,t;
1226736Srrh 	adrptr++;                       /* seek address in file         */
1236736Srrh 	ch=getc(inbuf);
1246736Srrh 	if (outsw)                      /* putting data in tmp file     */
1256736Srrh 	{       if (*tape==0) tape=iotape; /* rewind encryption tape    */
1266736Srrh 		putc(ch ^ *tape++,outbuf); /* encrypt & output char     */
1276736Srrh 	}
1286736Srrh 	return(ch);
1296736Srrh }
1306736Srrh 
1316736Srrh 
1326736Srrh char breakch;                           /* tell which char ended rnum   */
1336736Srrh 
1346736Srrh 
1356736Srrh rdata()                                 /* read all data from orig file */
1366736Srrh {       register int sect;
1376736Srrh 	register char ch;
1386736Srrh 	if ((inbuf=fopen(DATFILE,"r"))==NULL)     /* all the data lives in here   */
1396736Srrh 	{       printf("Cannot open data file %s\n",DATFILE);
1406736Srrh 		exit(0);
1416736Srrh 	}
1426736Srrh 	if ((outbuf=fopen(TMPFILE,"w"))==NULL)   /* the text lines will go here  */
1436736Srrh 	{       printf("Cannot create output file %s\n",TMPFILE);
1446736Srrh 		exit(0);
1456736Srrh 	}
1466736Srrh 	setup=clsses=1;
1476736Srrh 	for (;;)                        /* read data sections           */
1486736Srrh 	{       sect=next()-'0';        /* 1st digit of section number  */
1496736Srrh 		printf("Section %c",sect+'0');
1506736Srrh 		if ((ch=next())!=LF)    /* is there a second digit?     */
1516736Srrh 		{       FLUSHLF;
1526736Srrh 			putchar(ch);
1536736Srrh 			sect=10*sect+ch-'0';
1546736Srrh 		}
1556736Srrh 		putchar('\n');
1566736Srrh 		switch(sect)
1576736Srrh 		{   case 0:             /* finished reading database    */
1586736Srrh 			fclose(inbuf);
1596736Srrh 			fclose(outbuf);
1606736Srrh 			return;
1616736Srrh 		    case 1:             /* long form descriptions       */
1626736Srrh 			rdesc(1);
1636736Srrh 			break;
1646736Srrh 		    case 2:             /* short form descriptions      */
1656736Srrh 			rdesc(2);
1666736Srrh 			break;
1676736Srrh 		    case 3:             /* travel table                 */
1686736Srrh 			rtrav();   break;
1696736Srrh 		    case 4:             /* vocabulary                   */
1706736Srrh 			rvoc();
1716736Srrh 			break;
1726736Srrh 		    case 5:             /* object descriptions          */
1736736Srrh 			rdesc(5);
1746736Srrh 			break;
1756736Srrh 		    case 6:             /* arbitrary messages           */
1766736Srrh 			rdesc(6);
1776736Srrh 			break;
1786736Srrh 		    case 7:             /* object locations             */
1796736Srrh 			rlocs();   break;
1806736Srrh 		    case 8:             /* action defaults              */
1816736Srrh 			rdflt();   break;
1826736Srrh 		    case 9:             /* liquid assets                */
1836736Srrh 			rliq();    break;
1846736Srrh 		    case 10:            /* class messages               */
1856736Srrh 			rdesc(10);
1866736Srrh 			break;
1876736Srrh 		    case 11:            /* hints                        */
1886736Srrh 			rhints();  break;
1896736Srrh 		    case 12:            /* magic messages               */
1906736Srrh 			rdesc(12);
1916736Srrh 			break;
1926736Srrh 		    default:
1936736Srrh 			printf("Invalid data section number: %d\n",sect);
1946736Srrh 			for (;;) putchar(next());
1956736Srrh 		}
1966736Srrh 		if (breakch!=LF)        /* routines return after "-1"   */
1976736Srrh 			FLUSHLF;
1986736Srrh 	}
1996736Srrh }
2006736Srrh 
2016736Srrh char nbf[12];
2026736Srrh 
2036736Srrh 
2046736Srrh rnum()                                  /* read initial location num    */
2056736Srrh {       register char *s;
2066736Srrh 	tape = iotape;                  /* restart encryption tape      */
2076736Srrh 	for (s=nbf,*s=0;; s++)
2086736Srrh 		if ((*s=next())==TAB || *s=='\n' || *s==LF)
2096736Srrh 			break;
2106736Srrh 	breakch= *s;                    /* save char for rtrav()        */
2116736Srrh 	*s=0;                           /* got the number as ascii      */
2126736Srrh 	if (nbf[0]=='-') return(-1);    /* end of data                  */
2136736Srrh 	return(atoi(nbf));              /* convert it to integer        */
2146736Srrh }
2156736Srrh 
2166736Srrh int seekhere = 1;			/* initial seek for output file */
2176736Srrh 
2186736Srrh rdesc(sect)                             /* read description-format msgs */
2196736Srrh int sect;
2206736Srrh {       register char *s,*t;
2216736Srrh 	register int locc;
2226736Srrh 	int  seekstart, maystart, adrstart;
2236736Srrh 	char *entry;
2246736Srrh 	outsw=1;                        /* these msgs go into tmp file  */
2256736Srrh 	if (sect==1) putc('X',outbuf);  /* so seekadr > 0               */
2266736Srrh 	adrptr=0;
2276736Srrh 	for (oldloc= -1, seekstart=seekhere;;)
2286736Srrh 	{       maystart=adrptr;        /* maybe starting new entry     */
2296736Srrh 		if ((locc=rnum())!=oldloc && oldloc>=0  /* finished msg */
2306736Srrh 		    && ! (sect==5 && (locc==0 || locc>=100)))/* unless sect 5*/
2316736Srrh 		{       switch(sect)    /* now put it into right table  */
2326736Srrh 			{   case 1:     /* long descriptions            */
2336736Srrh 				ltext[oldloc].seekadr=seekhere;
2346736Srrh 				ltext[oldloc].txtlen=maystart-seekstart;
2356736Srrh 				break;
2366736Srrh 			    case 2:     /* short descriptions           */
2376736Srrh 				stext[oldloc].seekadr=seekhere;
2386736Srrh 				stext[oldloc].txtlen=maystart-seekstart;
2396736Srrh 				break;
2406736Srrh 			    case 5:     /* object descriptions          */
2416736Srrh 				ptext[oldloc].seekadr=seekhere;
2426736Srrh 				ptext[oldloc].txtlen=maystart-seekstart;
2436736Srrh 				break;
2446736Srrh 			    case 6:     /* random messages              */
2456736Srrh 				if (oldloc>RTXSIZ)
2466736Srrh 				{       printf("Too many random msgs\n");
2476736Srrh 					exit(0);
2486736Srrh 				}
2496736Srrh 				rtext[oldloc].seekadr=seekhere;
2506736Srrh 				rtext[oldloc].txtlen=maystart-seekstart;
2516736Srrh 				break;
2526736Srrh 			    case 10:    /* class messages               */
2536736Srrh 				ctext[clsses].seekadr=seekhere;
2546736Srrh 				ctext[clsses].txtlen=maystart-seekstart;
2556736Srrh 				cval[clsses++]=oldloc;
2566736Srrh 				break;
2576736Srrh 			    case 12:    /* magic messages               */
2586736Srrh 				if (oldloc>MAGSIZ)
2596736Srrh 				{       printf("Too many magic msgs\n");
2606736Srrh 					exit(0);
2616736Srrh 				}
2626736Srrh 				mtext[oldloc].seekadr=seekhere;
2636736Srrh 				mtext[oldloc].txtlen=maystart-seekstart;
2646736Srrh 				break;
2656736Srrh 			    default:
2666736Srrh 				printf("rdesc called with bad section\n");
2676736Srrh 				exit(0);
2686736Srrh 			}
2696736Srrh 			seekhere += maystart-seekstart;
2706736Srrh 		}
2716736Srrh 		if (locc<0)
2726736Srrh 		{       outsw=0;        /* turn off output              */
2736736Srrh 			seekhere += 3;  /* -1<delimiter>                */
2746736Srrh 			return;
2756736Srrh 		}
2766736Srrh 		if (sect!=5 || (locc>0 && locc<100))
2776736Srrh 		{       if (oldloc!=locc)/* starting a new message       */
2786736Srrh 				seekstart=maystart;
2796736Srrh 			oldloc=locc;
2806736Srrh 		}
2816736Srrh 		FLUSHLF;                /* scan the line                */
2826736Srrh 	}
2836736Srrh }
2846736Srrh 
2856736Srrh 
2866736Srrh rtrav()                                 /* read travel table            */
2876736Srrh {       register int locc;
2886736Srrh 	register struct travlist *t;
2896736Srrh 	register char *s;
2906736Srrh 	char buf[12];
2916736Srrh 	int len,m,n,entries;
2926736Srrh 	for (oldloc= -1;;)              /* get another line             */
2936736Srrh 	{       if ((locc=rnum())!=oldloc && oldloc>=0) /* end of entry */
2946736Srrh 		{
2956736Srrh 			t->next = 0;    /* terminate the old entry      */
2966736Srrh 		/*      printf("%d:%d entries\n",oldloc,entries);       */
2976736Srrh 		/*      twrite(oldloc);                                 */
2986736Srrh 		}
2996736Srrh 		if (locc== -1) return;
3006736Srrh 		if (locc!=oldloc)        /* getting a new entry         */
3016736Srrh 		{       t=travel[locc]=(struct travlist *) malloc(sizeof (struct travlist));
3026736Srrh 		/*      printf("New travel list for %d\n",locc);        */
3036736Srrh 			entries=0;
3046736Srrh 			oldloc=locc;
3056736Srrh 		}
3066736Srrh 		for (s=buf;; *s++)      /* get the newloc number /ASCII */
3076736Srrh 			if ((*s=next())==TAB || *s==LF) break;
3086736Srrh 		*s=0;
3096736Srrh 		len=length(buf)-1;      /* quad long number handling    */
3106736Srrh 	/*      printf("Newloc: %s (%d chars)\n",buf,len);              */
3116736Srrh 		if (len<4)              /* no "m" conditions            */
3126736Srrh 		{       m=0;
3136736Srrh 			n=atoi(buf);    /* newloc mod 1000 = newloc     */
3146736Srrh 		}
3156736Srrh 		else                    /* a long integer               */
3166736Srrh 		{       n=atoi(buf+len-3);
3176736Srrh 			buf[len-3]=0;   /* terminate newloc/1000        */
3186736Srrh 			m=atoi(buf);
3196736Srrh 		}
3206736Srrh 		while (breakch!=LF)     /* only do one line at a time   */
3216736Srrh 		{       if (entries++) t=t->next=(struct travlist *) malloc(sizeof (struct travlist));
3226736Srrh 			t->tverb=rnum();/* get verb from the file       */
3236736Srrh 			t->tloc=n;      /* table entry mod 1000         */
3246736Srrh 			t->conditions=m;/* table entry / 1000           */
3256736Srrh 		/*      printf("entry %d for %d\n",entries,locc);       */
3266736Srrh 		}
3276736Srrh 	}
3286736Srrh }
3296736Srrh 
3306736Srrh 
3316736Srrh twrite(loq)                             /* travel options from this loc */
3326736Srrh int loq;
3336736Srrh {       register struct travlist *t;
3346736Srrh 	printf("If");
3356736Srrh 	speak(&ltext[loq]);
3366736Srrh 	printf("then\n");
3376736Srrh 	for (t=travel[loq]; t!=0; t=t->next)
3386736Srrh 	{       printf("verb %d takes you to ",t->tverb);
3396736Srrh 		if (t->tloc<=300)
3406736Srrh 			speak(&ltext[t->tloc]);
3416736Srrh 		else if (t->tloc<=500)
3426736Srrh 			printf("special code %d\n",t->tloc-300);
3436736Srrh 		else
3446736Srrh 			rspeak(t->tloc-500);
3456736Srrh 		printf("under conditions %d\n",t->conditions);
3466736Srrh 	}
3476736Srrh }
3486736Srrh 
3496736Srrh 
3506736Srrh 
3516736Srrh rvoc()
3526736Srrh {       register char *s;               /* read the vocabulary          */
3536736Srrh 	register int index;
3546736Srrh 	char buf[6];
3556736Srrh 	for (;;)
3566736Srrh 	{       index=rnum();
3576736Srrh 		if (index<0) break;
3586736Srrh 		for (s=buf,*s=0;; s++)  /* get the word                 */
3596736Srrh 			if ((*s=next())==TAB || *s=='\n' || *s==LF
3606736Srrh 				|| *s==' ') break;
3616736Srrh 			/* terminate word with newline, LF, tab, blank  */
3626736Srrh 		if (*s!='\n' && *s!=LF) FLUSHLF;  /* can be comments    */
3636736Srrh 		*s=0;
3646736Srrh 	/*      printf("\"%s\"=%d\n",buf,index);*/
3656736Srrh 		vocab(buf,-2,index);
3666736Srrh 	}
3676736Srrh /*	prht();	*/
3686736Srrh }
3696736Srrh 
3706736Srrh 
3716736Srrh rlocs()                                 /* initial object locations     */
3726736Srrh {	for (;;)
3736736Srrh 	{       if ((obj=rnum())<0) break;
3746736Srrh 		plac[obj]=rnum();       /* initial loc for this obj     */
3756736Srrh 		if (breakch==TAB)       /* there's another entry        */
3766736Srrh 			fixd[obj]=rnum();
3776736Srrh 		else    fixd[obj]=0;
3786736Srrh 	}
3796736Srrh }
3806736Srrh 
3816736Srrh rdflt()                                 /* default verb messages        */
3826736Srrh {	for (;;)
3836736Srrh 	{       if ((verb=rnum())<0) break;
3846736Srrh 		actspk[verb]=rnum();
3856736Srrh 	}
3866736Srrh }
3876736Srrh 
3886736Srrh rliq()                                  /* liquid assets &c: cond bits  */
3896736Srrh {       register int bitnum;
3906736Srrh 	for (;;)                        /* read new bit list            */
3916736Srrh 	{       if ((bitnum=rnum())<0) break;
3926736Srrh 		for (;;)                /* read locs for bits           */
3936736Srrh 		{       cond[rnum()] |= setbit[bitnum];
3946736Srrh 			if (breakch==LF) break;
3956736Srrh 		}
3966736Srrh 	}
3976736Srrh }
3986736Srrh 
3996736Srrh rhints()
4006736Srrh {       register int hintnum,i;
4016736Srrh 	hntmax=0;
4026736Srrh 	for (;;)
4036736Srrh 	{       if ((hintnum=rnum())<0) break;
4046736Srrh 		for (i=1; i<5; i++)
4056736Srrh 			hints[hintnum][i]=rnum();
4066736Srrh 		if (hintnum>hntmax) hntmax=hintnum;
4076736Srrh 	}
4086736Srrh }
4096736Srrh 
4106736Srrh 
4116736Srrh rspeak(msg)
4126736Srrh int msg;
4136736Srrh {       if (msg!=0) speak(&rtext[msg]);
4146736Srrh }
4156736Srrh 
4166736Srrh 
4176736Srrh mspeak(msg)
4186736Srrh int msg;
4196736Srrh {       if (msg!=0) speak(&mtext[msg]);
4206736Srrh }
4216736Srrh 
4226736Srrh 
4236736Srrh doseek(offset)  /* do 2 seeks to get to right place in the file         */
4246736Srrh unsigned offset;
4256736Srrh {
4266736Srrh 	extern unsigned filesize;
4276736Srrh 	lseek(datfd,(long)offset+(long)filesize, 0);
4286736Srrh #ifdef notdef
4296736Srrh 	blockadr=chadr=0;
4306736Srrh 	if (offset<0)                   /* right place is offset+filesize*/
4316736Srrh 	{       blockadr += 64;         /* take off 32768 bytes         */
4326736Srrh 		chadr += offset+32768;  /* & make them into 64 blocks   */
4336736Srrh 	}
4346736Srrh 	else chadr += offset;
4356736Srrh 	if (filesize<0)                 /* data starts after file       */
4366736Srrh 	{       blockadr += 64;         /* which may also be large      */
4376736Srrh 		chadr += filesize+32768;
4386736Srrh 	}
4396736Srrh 	else chadr += filesize;
4406736Srrh 	if (chadr<0)                    /* and the leftovers may be lge */
4416736Srrh 	{       blockadr += 64;
4426736Srrh 		chadr += 32768;
4436736Srrh 	}
4446736Srrh 	seek(datfd,blockadr,3);         /* get within 32767             */
4456736Srrh 	seek(datfd,chadr,1);            /* then the rest of the way     */
4466736Srrh #endif
4476736Srrh }
4486736Srrh 
4496736Srrh 
4506736Srrh speak(msg)       /* read, decrypt, and print a message (not ptext)      */
4516736Srrh struct text *msg;/* msg is a pointer to seek address and length of mess */
4526736Srrh {       register char *s,nonfirst;
4536736Srrh 	register char *tbuf;
4546736Srrh 	doseek(msg->seekadr);
45535697Sbostic 	if ((tbuf=(char *) malloc(msg->txtlen+1)) == 0) bug(109);
4566736Srrh 	read(datfd,tbuf,msg->txtlen);
4576736Srrh 	s=tbuf;
4586736Srrh 	nonfirst=0;
4596736Srrh 	while (s-tbuf<msg->txtlen)      /* read a line at a time        */
4606736Srrh 	{       tape=iotape;            /* restart decryption tape      */
4616736Srrh 		while ((*s++^*tape++)!=TAB); /* read past loc num       */
4626736Srrh 		/* assume tape is longer than location number           */
4636736Srrh 		/*   plus the lookahead put together                    */
4646736Srrh 		if ((*s^*tape)=='>' &&
4656736Srrh 			(*(s+1)^*(tape+1))=='$' &&
4666736Srrh 			(*(s+2)^*(tape+2))=='<') break;
4676736Srrh 		if (blklin&&!nonfirst++) putchar('\n');
4686736Srrh 		do
4696736Srrh 		{       if (*tape==0) tape=iotape;/* rewind decryp tape */
4706736Srrh 			putchar(*s^*tape);
4716736Srrh 		} while ((*s++^*tape++)!=LF);   /* better end with LF   */
4726736Srrh 	}
4736736Srrh 	free(tbuf);
4746736Srrh }
4756736Srrh 
4766736Srrh 
4776736Srrh pspeak(msg,skip) /* read, decrypt an print a ptext message              */
4786736Srrh int msg;         /* msg is the number of all the p msgs for this place  */
4796736Srrh int skip;       /* assumes object 1 doesn't have prop 1, obj 2 no prop 2 &c*/
4806736Srrh {       register char *s,nonfirst;
4816736Srrh 	register char *tbuf;
4826736Srrh 	char *numst;
4836736Srrh 	int lstr;
4846736Srrh 	doseek(ptext[msg].seekadr);
48535697Sbostic 	if ((tbuf=(char *) malloc((lstr=ptext[msg].txtlen)+1)) == 0) bug(108);
4866736Srrh 	read(datfd,tbuf,lstr);
4876736Srrh 	s=tbuf;
4886736Srrh 	nonfirst=0;
4896736Srrh 	while (s-tbuf<lstr)             /* read a line at a time        */
4906736Srrh 	{       tape=iotape;            /* restart decryption tape      */
4916736Srrh 		for (numst=s; (*s^= *tape++)!=TAB; s++); /* get number  */
4926736Srrh 		*s++=0; /* decrypting number within the string          */
4936736Srrh 		if (atoi(numst)!=100*skip && skip>=0)
4946736Srrh 		{       while ((*s++^*tape++)!=LF) /* flush the line    */
4956736Srrh 				if (*tape==0) tape=iotape;
4966736Srrh 			continue;
4976736Srrh 		}
4986736Srrh 		if ((*s^*tape)=='>' && (*(s+1)^*(tape+1))=='$' &&
4996736Srrh 			(*(s+2)^*(tape+2))=='<') break;
5006736Srrh 		if (blklin && ! nonfirst++) putchar('\n');
5016736Srrh 		do
5026736Srrh 		{       if (*tape==0) tape=iotape;
5036736Srrh 			putchar(*s^*tape);
5046736Srrh 		} while ((*s++^*tape++)!=LF);   /* better end with LF   */
5056736Srrh 		if (skip<0) break;
5066736Srrh 	}
5076736Srrh 	free(tbuf);
5086736Srrh }
5096736Srrh 
510