/* find.c - given device, filename - report all fids that show that name etc */
/* understands all flavours of wildcards */
/* based on fid.c */
/* based on bum.c */

#include <stdio.h>
#include <cx.h>
#include <qioret.h>
#include <f11.h>
#include <nboff.h>
#include <fdoff.h>
#include <algol68.h>

extern int $$ferr;		/* the fcb io error status is here	*/
struct	home	homblk;		/* home block				*/
struct	header	hedblk;		/* file header				*/
char	indxnm[100];		/* index file print name		*/

FILE *	indexf;			/* [0,0]indexf.sys;1			*/
unsigned	filnum;		/* file number				*/
unsigned	filoff;		/* (VBN of header (1,1) in indexf.sys)-1*/
unsigned	maxfil;		/* maximum file number (permitted by	*/
				/* bitmap of index file)		*/
FDB *	fdbp;			/* point to fdb of indexf for fcs rape	*/

char	nam[10];		/* file name from this header		*/
char	ext[4];			/* file extension from this header	*/
int	proj;			/* project number from this header	*/
int	prog;			/* programmer number from this header	*/
int	ver;			/* version number from this header	*/

char	wnam[10];		/* the name user is looking for		*/
char	wext[4];		/* the extension user wants		*/
				/* a % in above means match anything	*/
				/* one day we will implement -		*/
int	wproj;			/* the group # user wants		*/
int	wprog;			/* the user # user wants		*/
int	wver;			/* the version user wants		*/
				/* a -1 in above means wild		*/
				/* one day we will mask bits, and range	*/
char	wdev[10];		/* user nominated device		*/

main(argc,argv)
int	argc;
char ** argv;
BEGIN
char *	p;
BOOL	accept;

	IF	(argc<2)
	THEN	printf("usage: %s [device_name:]filespec [-r]\n",argv[0]);
		printf("the filespec may be as wild as [*,*]mum%%%ble.*;*\n");
		printf("-r means RECOVER deleted files, entering them as sy:[current_UIC]recovered.;*\n");
		exit();
	FI;
	$_$uc(argv[1]);		/* uppercase everything */
	IF	(p=strchr(argv[1],':'))
	THEN	p++;
		copy(wdev,argv[1],p-argv[1]);
	ELSE	p = argv[1];
		strcpy(wdev,"");
	FI
	/* p just after ':', wdev known */
	IF	(*p=='[')
	THEN	p++;
		IF	(*p=='*' || *p==',')
		THEN	wproj = -1;
			IF	(*p!=',')
			THEN	p++;
			FI
		ELSE	wproj=0;
			WHILE	(isoctal(*p))
			DO	wproj = wproj*8 + (*p++)-'0';
			OD
		FI
		/* p points to ',' and wproj is known */
		IF	(*p++!=',')
		THEN	error("\7can't see ',' in []");
		FI
		IF	(*p=='*' || *p==']')
		THEN	wprog = -1;
			IF	(*p!=']')
			THEN	p++;
			FI
		ELSE	wprog=0;
			WHILE	(isoctal(*p))
			DO	wprog = wprog*8 + (*p++)-'0';
			OD
		FI
		/* *p -> '[' and wprog is known */
		IF	(*p++!=']')
		THEN	error("\7can't see ']' in []");
		FI
	ELSE	wproj = wprog = -1;
	FI
	/* p points to filename.    wproj,wprog known */
	strcpy(wnam,"%%%%%%%%%");
	strcpy(wext,"%%%");
	constr(wnam,'.',&p);
	IF	(*p=='.')
	THEN	p++;
		constr(wext,';',&p);
	FI
	IF	(*p==';')
	THEN	p++;
		FOR	(wver=0;	isoctal(*p);	p++)
		DO	wver = wver*8 + *p-'0';
		OD
	FI
	IF	(*p)
	THEN	fprintf(stderr,"%s: rest of ambiguous file spec ignored: \"%s\"\n\7"
			,argv[0],p);
	FI
	strcpy(indxnm,wdev);
	strcat(indxnm,"[0,0]indexf.sys");
	IF	(! (indexf=fopenr(indxnm,512)) )
	THEN	error("$$ferr=%oo fopenr: %s",$$ferr,indxnm);
	FI;
	/* now fake end-of-file to fcs: so we can read home block */
	fdbp = indexf -> io_fdb;
	fdbp -> f_fatt . f_hibk = fdbp -> f_fatt . f_efbk = 42;
	IF	(frget(&homblk,512,indexf,2L))
	THEN	error("$$ferr=%oo home",$$ferr);
	FI;
	filoff = 2 + homblk . h_ibsz;
	maxfil = homblk . h_fmax;
	fdbp -> f_fatt . f_hibk = fdbp -> f_fatt . f_efbk = maxfil + 1;
	FOR	(filnum=1;	filnum<maxfil+1;	filnum++)
	DO	IF	(frget(&hedblk,512,indexf,(long)(filnum+filoff)))
		THEN	error("$$ferr=%oo header read",$$ferr);
		ELSE	r50toa(nam,&hedblk.i_fnam,3);
			nam[9] = EOS;
			r50toa(ext,&hedblk.i_ftyp,1);
			ext[3] = EOS;
			proj = hedblk.h_proj & 0xFF;
			prog = hedblk.h_prog & 0xFF;
			accept = TRUE;
			IF	(wproj>=0 && wproj!=proj)
			THEN	accept = FALSE;
			FI
			IF	(wprog>=0 && wprog!=prog)
			THEN	accept = FALSE;
			FI
			IF	(compare(ext,wext,3))
			THEN	accept = FALSE;
			FI
			IF	(compare(nam,wnam,9))
			THEN	accept = FALSE;
			FI
			IF	(accept)
			THEN	printf("[%o,%o]%s.%s;%o\\%d. %o(%o:%o)\n"
				,hedblk.h_proj&0xFF,hedblk.h_prog&0xFF,nam,ext
				,hedblk.i_fver,hedblk.i_rvno,filnum
				,hedblk.h_fnum,hedblk.h_fseq);
			FI
		FI
	OD
END

int	compare(a,b,len)	/* return TRUE if no match */
char	*a;
char	*b;
int	len;
BEGIN

	FOR	(;  len--;  a++,b++)
	DO	IF	(*a!=*b && *a!='%' && *b!='%')
		THEN	return(TRUE);
		FI
	OD
	return(FALSE);
END

constr(dest,stop,pointer)
char *	dest;
char	stop;
char **	pointer;
BEGIN
register	char *	q;
register	char *	p;

	FOR	(q=dest,p=*pointer;	*p && *p!=stop && *q;  p++)
	DO	switch	(*p)
			{
		case '*':	WHILE	(*q)
				DO	*q++ = '%';
				OD
				break;
		default:	*q++ = *p;
				break;
			}
		;
	OD
	/* p points to terminator (usually EOS or stop) */
	*pointer = p;
END

BOOL	isoctal(c)
char	c;
BEGIN
	c &= 0x7F;
	return(c<'8' && c>='0');
END

/* end: find.c */
