/* ansid.c - decode magtape records (eg from t2b) that are ANSI D format */
/*
 * D format says we get 4 decimal digits (a number n) followed by n-4 bytes
 * of data. It is their R.VAR format.
 *
 * We read a stream, and break it up with '\n's in the right places.
 */

/* ufilter5.c - prototype filter program - line (actually record) oriented */
/*
 * Modular, fast, record filter skeleton.
 * Forces FD.CR on output file.
 * Gets file names from argv[1],[2]. Too hard to use stdin,stdout.
 * The record has NOTHING (like free '\n's) added to it.
 * Howlong = the record size in bytes.
 * Designed for R.VAR files.
 * Seperate input & output buffers
 */

#include <stdio.h>
#include <algol68.h>
#include <cx.h>
#include <nboff.h>
#include <fdoff.h>
char *	inbufp;		/* where the input buffer is			*/
int	bufmax;		/* maximum record size, needed for recinp()	*/
#define OUTMAX (bufmax)	/* maximum output record size			*/
FILE	*inf;		/* input file					*/
FILE	*ouf;		/* output file					*/
FDB *	fdbp;		/* obsolete kludge				*/
int	howlong;	/* char length of this record			*/
char *	otbufp;		/* where the output buffer is			*/

char *	p;		/* track input record				*/
char *	q;		/* track output record				*/
int	siz;		/* size of current record			*/
char *	nd;		/* just past end of input record		*/
char *	r;		/* scan erroneous part of input record		*/

main(argc,argv)
char **argv;
BEGIN
char *	recinp();	/* the record-getter: 0 means end-of-file	*/

	IF	((inf=fopen(argv[1],"urn"))==NULL)
	THEN	error("can't find %s\7",argv[1]);
	FI
	fdbp = inf -> io_fdb;
	IF	(!(inbufp=malloc(bufmax=fdbp->f_fatt.f_rsiz)))
	THEN	error("max record size=%d.\7",bufmax);
	FI

	IF	(!(otbufp=malloc(OUTMAX)))
	THEN	error("MAX rec siz=%d.\7",OUTMAX);
	FI
	IF	((ouf=fopen(argv[2],"uwn"))==NULL)
	THEN	error("can't make %s\7",argv[2]);
	FI
	fdbp = ouf -> io_fdb;
	fdbp -> f_fatt . f_ratt |= fd_cr;	/* force fd.cr		*/

	/*
	 * this is the simple logic:
	 */

	WHILE	(recinp(inbufp,bufmax,inf,&howlong))
	DO	nd = inbufp+howlong;
		FOR	(p=inbufp; p<nd && isdigit(*p); )
		DO	siz = 0;
			digit();	digit();	digit();	digit();
			siz -= 4;
			IF	(siz<0)
			THEN	panic("record size too small");
			FI
			q = otbufp;
			WHILE	(siz--)
			DO	*q++=*p++;
			OD
			recout(otbufp,q-otbufp,ouf);
		OD
	OD

	/*
	 * easy wasn't it?
	 */

	IF	(fclose(ouf))
	THEN	error("Can't close\7");
	FI
END

digit()
BEGIN
	IF	(!isdigit(*p))
	THEN	panic("expected digit in record length");
	FI
	siz = siz*10+*p++-'0';
END

panic(winge)
char * winge;
BEGIN
	fprintf(stderr,"\7%s!\n",winge);
	FOR	(r=inbufp; r<=p; r++)
	DO	putc(*r,stderr);
	OD
	exit();
END

char * recinp (where,moby,sewer,lenp)	/* 0==end-file, else buf adr	*/
char *	where;				/* buffer			*/
int	moby;				/* buffer size			*/
FILE *	sewer;				/* input file			*/
int *	lenp;				/* return actual record size	*/
BEGIN
	*lenp = fget(where,moby,sewer);
	IF	(ferror(sewer))
	THEN	error("read failure $$ferr=%oo\7\n",$$ferr);
	FI
	return	(feof(sewer)?NULL:where);
END

recout(where,len,sewer)
char *	where;		/* buffer					*/
int	len;		/* record size					*/
FILE *	sewer;		/* output file					*/
BEGIN
	fput(where,len,sewer);
	IF	(ferror(sewer))
	THEN	error("write failed $$ferr=%oo len=%d.\7\n",$$ferr,len);
	FI
END
/* end: ufilter4.c */
/* end:ansid.c */
