/* tlr.c: read a R.VAR file from telex paper tape on tl: */
/* please assign tl: to a full-duplex-driver tty: terminal */
#include <stdio.h>
#include <cx.h>
#include <qiofun.h>
#include <qioret.h>
#include <qiottdrv.h>
#include <spcio.h>
#define EFN 1
#define LUN 6
helpless()
{puts("usage: TLR >output-file-name");
 puts("will copy a telex tape from tl: to STDOUT");
 puts("type a SPACE on the TTY to signal end-of-tape");
 exit();
}
main(argc)
int		argc;
{int		dev;		/* device name in ascii */
 int		dsw;		/* directive status word */
 char		getachar();	/* suck one char from TL: */
 char		ascii();	/* convert baudot to ascii */
 char		fromtl;		/* the char from TL: */
 char		tooutput;	/* the char we output */
 int		lettershift;	/* TRUE if currently in lettershift */
 int		endoffile;	/* TRUE when tape end hit */
 if	(argc>1)	helpless();
 dev = 'T' | 'L'<<8;
 dsw = alun(LUN,dev,0);
 if	(dsw!=IS_SUC)
	{error("\7Can't attach to teletype %c%c:   dsw=%o#",dev,dev>>8,dsw);
	}
 ;
/*
	assume TL: is
	^Q
	SET /WRAP=TL:
	SET /RPA=TL:
	SET /FDX=TL:
	SET /FORMFEED=TL:
	SET /HFILL=TL:0
	SET /HHT=TL:
	SET /ECHO=TL:
	SET /TYPEAHEAD=TL:
	SET /NOCRT=TL:
	SET /SLAVE=TL:
	SET /LOWER=TL:
	SET /TERM=TL:ASR33
	SET /NOVFILL=TL:
	SET /EBC=TL:
*/
 errputs("+--------------------------------------+\r");
 errputs("|                                      |\r");
 errputs("| Please turn paper tape reader on NOW |\r");
 errputs("|                                      |\r");
 errputs("+--------------------------------------+\r");
/* we could achieve above with a SF.SMC QIO - but the task would then need
   priviledge: so trust boot to set up these parameters */
/* ordinary telex tape will only generate codes 11100000 - 11111111
   so when user types a space (x0100000) we use that as end-of-file */
/* endoffile is also set if there is a timeout */
 endoffile = FALSE;
 while ( (fromtl=getachar(&endoffile)) , fromtl == 0 || endoffile )
	endoffile = FALSE;
	/* ignore timeouts and blank tape until at least 1 char read */
 while	(endoffile==FALSE)
	{if	(fromtl==' ')
		{endoffile = TRUE;	/* space means end of file */
		}
	 ;
	 if	(endoffile==FALSE)
		{if	(fromtl)	/* if not clear tape leader */
			{tooutput = ascii(fromtl,&lettershift);
			 if	(tooutput)	putchar(tooutput);
			}
		 ;
		}
	 ;
	 fromtl = getachar(&endoffile);
	}
 ;
}

char	ascii	(telex,lettershift)	/* return 0 or ASCII char */
char	telex;		/* telex char as read */
int	*lettershift;	/* TRUE if currently letter shifted */
			/* returns with new value */
/*

	|       o     |
	|       o     |
	|       o     |
	|       o     |
	| A B C o D E |	bits in the telex tape, looking down
	|       o     |	front of TTY
	\	o     /	hole: 1		no hole: 0
	 \	o    /
	  \     o   /
	   \	o  /
	    \   o /
	     \  o/
	      \	/
	       V

	+-+-+-+-+-+-+-+-+
	|A|B|C|D|E|     |	bits as they appear in a C char
	+-+-+-+-+-+-+-+-+
	 l             m
	 s             s
         b             b



	+-+-+-+-+-+-+-+-+
	|     |E|D|C|B|A|	bits as they appear in a C char
	+-+-+-+-+-+-+-+-+
	 m	       l
	 s	       s
	 b	       b



	m    l
	s    s
	b    b
	ED CBA
	  .   	leader	leader
	  .  *	T	5
	  . * 	car-ret	car-ret
	  . **	O	9
	  .*  	space	space
	  .* *	H	unknown
	  .** 	N	,
	  .***	M	.
	 *.   	linefed	linefed
	 *.  *	L	)
	 *. * 	R	4
	 *. **	G	$
	 *.*  	I	8
	 *.* *	P	0
	 *.** 	C	:
	 *.***	V	=
	* .   	E	3
	* .  *	Z	+
	* . * 	D	who-r-u
	* . **	B	?
	* .*  	S	'
	* .* *	Y	6
	* .** 	F	%
	* .***	X	/
	**.   	A	-
	**.  *	W	2
	**. * 	J	bell
	**. **		figure
	**.*  	U	7
	**.* *	Q	1
	**.** 	K	(
	**.***	letter
	ED CBA
	m     l
	s     s
	b     b


*/
{int	let;		/* TRUE if letter shift */
 char	*c;		/* 0th: letter		1st: number */
 let = *lettershift;
 switch	(telex & 0x1F)
	{
 case  0:	c = "\0\0";			break;
 case  1:	c = "T5";			break;
 case  2:	c = "\r\r";			break;
 case  3:	c = "O9";			break;
 case  4:	c = "  ";			break;
 case  5:	c = "H*";			break;
 case  6:	c = "N,";			break;
 case  7:	c = "M.";			break;
 case  8:	c = "\n\n";			break;
 case  9:	c = "L)";			break;
 case 10:	c = "R4";			break;
 case 11:	c = "G$";			break;
 case 12:	c = "I8";			break;
 case 13:	c = "P0";			break;
 case 14:	c = "C:";			break;
 case 15:	c = "V=";			break;
 case 16:	c = "E3";			break;
 case 17:	c = "Z+";			break;
 case 18:	c = "D\5";			break;
 case 19:	c = "B?";			break;
 case 20:	c = "S'";			break;
 case 21:	c = "Y6";			break;
 case 22:	c = "F%";			break;
 case 23:	c = "X/";			break;
 case 24:	c = "A-";			break;
 case 25:	c = "W2";			break;
 case 26:	c = "J\7";			break;
 case 27:	c = "\0\0";	 let = FALSE;	break;
 case 28:	c = "U7";			break;
 case 29:	c = "Q1";			break;
 case 30:	c = "K(";			break;
 case 31:	c = "\0\0";	 let = TRUE;	break;
	}
 ;
 *lettershift = let;
 return	(c[let?0:1]);
}

char	getachar(endoffile)	/* get a char from TL: */
int		*endoffile;	/* set TRUE if timeout occurs */
{
 int		qiow();
 int		dsw;		/* directive status word */
 int		isb[2];		/* io status block */
 int		prl[6];		/* QIOW parameter list */
 int		mask[32];	/* says "pass all chars as terminators" */
 int		i;
 for	(i=31;	i--;	)	mask[i] = -1;	/* set all bits in mask */
 prl[0] = mask;		/* buffer address: we never read into it,
				   so use mask as buffer */
 prl[1] = 1;			/* give it 1 byte so FDX term driver is happy */
 prl[2] = 1;			/* wait ten seconds until time-out (end-of-file) */
 prl[3] = mask;			/* the character mask that says ALL chars break */
 dsw = qiow(IO_RTT|TF_TMO,LUN,EFN,isb,0,prl);
/* expect in isb:
	byte 0:		directive status code:	1 for success
	byte 1:		character input
	byte 2-3:	the count of characters input to buffer
			this is always zero, because we break on every character
*/
/* check for return code 2: timeout */
 if	( (dsw & 0xFF) == IS_SUC && (isb[0] & 0xFF) == IS_TMO )
	{/* timeout */
	 *endoffile = TRUE;
	 isb[0] = IS_SUC;	/* lies, damned lies and comments */
	}
 ;
 if	( (dsw & 0xFF) != IS_SUC || (isb[0] & 0xFF) != IS_SUC )
	{error("\7Can't read from TL: dsw=%xx isb=%xx %xx",dsw,isb[0],isb[1]);
	}
 ;
 return ((isb[0]>>8) & 0x7F);	/* only yield 7 bits */
}
errputs(string)		/* put a string to human */
char	*string;
{int	strlen();
 fput(string,strlen(string),stderr);
}
