/* Compile with HiTech C for CP/M-80 v3.09 */

#include <cpm.h>
#include <stddef.h>
#include <ctype.h>
#include <stat.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> 

#include "B:BDOS.H"

void PrintFCB(struct CPMfcb * pFCB, int pFull)
{
int i;
 fprintf(stderr,"\n");
 fprintf(stderr," %02x ",pFCB->dr);
 for (i=0;i<8;i++)fprintf(stderr,"  %c ",pFCB->name[i]);
 for (i=0;i<3;i++)fprintf(stderr,"  %c ",pFCB->ft[i]);
 fprintf(stderr," %02x ",pFCB->ex);
 for (i=0;i<2;i++)fprintf(stderr," %02x ",pFCB->fil[i]);
 fprintf(stderr," %02x ",pFCB->rc);
 fprintf(stderr,"\n");
 for (i=0;i<16;i++)fprintf(stderr," %02x ",pFCB->dm[i]);
if (pFull==1)
{
 fprintf(stderr," %2x ",pFCB->nr);
 for (i=0;i<3;i++)fprintf(stderr," %2x ",pFCB->ranrec[i]);
}
fprintf(stderr,"\n");
}
void InitFCB(struct CPMfcb * pFCB, char pChar)
{
 int i;
 pFCB->dr=0;
 for (i=0;i<8;i++)pFCB->name[i]=pChar;
 for (i=0;i<3;i++)pFCB->ft[i]=pChar;
 pFCB->ex=0;
 for (i=0;i<2;i++)pFCB->fil[i]=0;
 pFCB->rc=0;
 for (i=0;i<16;i++)pFCB->dm[i]=0;
 pFCB->nr=0;
 for (i=0;i<3;i++)pFCB->ranrec[i]=0;
}
int FindChar (char * pString, char pChar, int pOccur)
{
int i;
int c=0;

for (i=0; i<strlen(pString); i++)
 {
   if (pString[i]==pChar) {c++; if (c==pOccur) return(i);}
 }
return(-1);
}
int IsInvalid (char pChar , int pUFN)
{
 if ((pUFN==1) && ( (pChar=='*')||(pChar=='?') ))return(-1); /* invalid character */
 if ( 	(pChar=='<')||(pChar=='>')|| 
	(pChar=='.')||(pChar==',')||
	(pChar==';')||(pChar=='=')|| 
	(pChar=='[')||(pChar==']')||
	(pChar=='^')||(pChar=='!') /* bang for CPM3 */
     )return(-1); /* invalid character */
 return(0);
}
int IsDrive(char pChar)
{
return ( (pChar>='A') && (pChar<='P') );
}
int SubParseDRU (struct CPMfcb* pFCB, char * pFilename, int pStart, int pEnd)
{
int DRcnt=0;
int i;
for (i=pStart; i<=pEnd; i++)
 { 
	if (IsDrive(pFilename[i]) ) 
	{
		DRcnt++;
		if (DRcnt!=1) return(-3);/* too many drives */
		pFCB->dr=pFilename[i]-'@';
	}
 }

if (IsDrive(pFilename[pStart])) pStart++;
if (IsDrive(pFilename[pEnd])) pEnd--;

if (pStart>pEnd)return(-1);/* def user */
if ( (pEnd-pStart) >2)return(-2); /* invalid User */
if ( !isdigit(pFilename[pStart]) )return(-2);
if ( !isdigit(pFilename[pEnd]) )return(-2);
if (pStart==pEnd)return(pFilename[pStart]-'0');
DRcnt=(((pFilename[pStart]-'0')*10) + (pFilename[pEnd]-'0'));
if (DRcnt>15)return(-2);else return(DRcnt);
}
int ParseFN (struct CPMfcb* pFCB, char * pFilename, int pUFN)
{
int Colon1,Colon2,Colon3,Dot1,Dot2;

int i,j;

int NameStart=0;
int NameEnd;
int ExtStart=0;
int ExtEnd;

int StrLen;
int RTN=0;

StrLen=strlen(pFilename);

Colon1=FindChar (pFilename,':',1);
Colon2=FindChar (pFilename,':',2);
Colon3=FindChar (pFilename,':',3);
if (Colon3!=-1)return(-4); /* too many colons */
Dot1=FindChar (pFilename,'.',1);
Dot2=FindChar (pFilename,'.',2);
if (Dot2!=-1)return(-5); /* too many dots */

if (Colon1!=-1) NameStart=Colon1+1;
if (Colon2!=-1) NameStart=Colon2+1;
if (Dot1!=-1) {ExtStart=Dot1+1;NameEnd=Dot1-1;}else NameEnd=StrLen-1;
ExtEnd=StrLen-1;

if (NameStart>NameEnd)RTN=2; /* null name */
if (ExtStart>ExtEnd)RTN=3; /* null ext */
if ( (NameStart>NameEnd) && (ExtStart>ExtEnd) ) RTN=4; /* null name and ext */
if (NameStart>ExtEnd)RTN=1; /* no filename */

if (((NameEnd-NameStart))>7)return(-1); /* name too long */
if (ExtStart!=0) if (((ExtEnd-ExtStart))>2)return(-2); /* ext too long */

for (i=NameStart; i<=NameEnd;i++)if (IsInvalid(pFilename[i],pUFN)!=0)return(-3); /* invalid character */
if (ExtStart!=0)for (i=ExtStart; i<=ExtEnd;i++)if (IsInvalid(pFilename[i],pUFN)!=0)return(-4); /* invalid character */

j=0;
for (i=NameStart; i<=NameEnd;i++)if (pFilename[i]=='*')j+=1;
if (j>1)return(-5); /* too many * in filename */
if (j==1)for (i=0;i<8;i++)pFCB->name[i]='?';

j=0;
if (ExtStart!=0)for (i=ExtStart; i<=ExtEnd;i++) if (pFilename[i]=='*')j+=1;
if (j>1)return(-6); /* too many * in ext */
if (j==1)for (i=0;i<3;i++)pFCB->ft[i]='?';

j=0;
for (i=NameStart; i<=NameEnd;i++){if (pFilename[i]=='*')break;pFCB->name[j]=pFilename[i];j++;}
j=0;
if (ExtStart!=0)for (i=ExtStart; i<=ExtEnd;i++){if (pFilename[i]=='*')break;pFCB->ft[j]=pFilename[i];j++;}

/* fprintf(stderr,"%d: %d: %d: %d. %d.",Colon1,Colon2,Colon3,Dot1,Dot2); */
/* fprintf(stderr,"\n%d %d %d %d ",NameStart,NameEnd,ExtStart,ExtEnd); */

return(RTN);

/* 1 no filename, 2 null name, 3 null ext, 4 FN.EX both null */
/* -1 filename too long, -2 ext too long, -3 ch invalid name, -4 ch invalid ext */
/* -5 too many * in FN, - 6 too many * in EXT  */
}
int ParseDRU (struct CPMfcb* pFCB, char * pFilename)
{
int Colon1,Colon2,Colon3;

int i,j,k;

int StrLen;

StrLen=strlen(pFilename);

Colon1=FindChar (pFilename,':',1);
Colon2=FindChar (pFilename,':',2);
Colon3=FindChar (pFilename,':',3);
if (Colon3!=-1)return(-4); /* too many colons */

if (Colon1<=0) 
	j=-1; /* def user */
else
	j=SubParseDRU (pFCB, pFilename, 0, Colon1-1);

if (Colon2==-1)return(j);

if ( (Colon2-Colon1)<2 )return (j);
k=pFCB->dr;
i=SubParseDRU (pFCB, pFilename, Colon1+1, Colon2-1);
if ( (k!=0) && (k!=pFCB->dr) )return (-3);
if ( (i!=-1) && (j!=-1) )return (-2);
if (i==-1)return(j);
return(i);

/* -1 DefUSR,-2 BadUsr,-3 Bad Disk */
}

