/***************************************************************************
 *									    
 *			_ p a r s e f n   F u n c t i o n		    
 *			---------------------------------		    
 *	Copyright 1983 by Digital Research Inc.  All rights reserved.	    
 *									    
 *	Function "_parsefn()" is used to parse a filename into the CP/M fcb.
 *	NOTE: For PCDOS, an OS call is written in assembler ("_pc_parse()").
 *									    
 *	Calling Sequence:						    
 *		ret = _parsefn(filnam,fcbp);				    
 *									    
 *	Where:								    
 *		filnam	Is a null-terminated CP/M filename		    
 *		ret	Is NULLPTR if entire string parsed,		    
 *			  -1 if there was an error, or			    
 *			  a pointer to the next item to parse		    
 *		fcbp	Is the address of a CP/M File Control Block (fcb).  
 *			  Note: password will get stuffed into bytes 16-23  
 *			  user # (plus 1) in byte 24, if supplied in filnam.
 *	File Spec:							    
 *		#d:filename.typ;passwd					    
 *									    
 *	Modified:
 *	1/84 whf	handle 68K parsing error.
 ****************************************************************************/
#include "portab.h"
#include "osif.h"
#include "ctype.h"

#define FAILPTR ((BYTE *)(-1))			/* FAILURE		    */

    BYTE *					/****************************/
_parsefn(filnam,fcbp)				/*			    */
    REG	BYTE		*filnam;		/* -> filename		    */
    struct fcbtab	*fcbp;			/* -> FCB address	    */
{						/****************************/



#if PCDOS /*================================================================*/
	REG BYTE *retp;				/* To convert to ret val    */
	BYTE *_pc_parse();			/* Use PC-DOS parse call    */
						/*			    */
	retp = _pc_parse(filnam,fcbp);		/* return 1st char after fnam*/
	if( fcbp->fname[0] == ' ' )		/* PC-DOS convention for bad*/
		return FAILPTR;			/* ...filename		    */
	while( isspace(*retp) )			/* skip trailing white stuff*/
		++retp;				/*			    */
	if( *retp == NULL )			/* parsed to EOS?	    */
		return NULLPTR;			/*   yes, say so	    */
	else 	return retp;			/*   no, return ptr	    */
}	


#endif	/*==================================================================*/

#if CPM	/*==================================================================*/
	BYTE	tokbuf[32];			/* Token temporary buffer   */
	BYTE	*get_token();			/* Tokenize the file name   */
						/****************************/
	blkfill(fcbp,NULL,32);			/* Init fcb area to NULLs   */
	blkfill(&(fcbp->fname[0]),' ',11);	/* with name area to spaces */
						/*			    */
	filnam = get_token(filnam,tokbuf,32);	/* Get the first token	    */
	if(*filnam == ':')			/* Is the delim a colon?    */
	{					/* If yes, then a drive spec*/
	  if(stuff_drive(fcbp,tokbuf) == FAILURE) /* Check drive OK	    */
		return FAILPTR;			/* Return error if bad	    */
	  filnam=get_token(++filnam,tokbuf,32);	/* Get next token	    */
	}					/****************************/
						/*			    */
	if(*filnam == '*')			/* Delimiter is a "*"??	    */
	{					/*			    */
	  blkfill(&(fcbp->fname[0]),'?',8);	/* Yes, fill with ?'s 1st   */
	  filnam++;				/* Bump to next character   */
	}					/****************************/
	_strcpy(tokbuf,fcbp->fname,8);		/* Copy the file name in    */
	if(*filnam == '.')			/* If extension specified   */
	{					/*			    */
	  filnam=get_token(++filnam,tokbuf,32);	/* get extension token	    */
	  if(*filnam == '*')			/* Is wildcarded ext?	    */
	  {					/*			    */
	    blkfill(&(fcbp->fname[8]),'?',3);	/* If yes, fill with ?'s    */
	    filnam++;				/* Bump to next character   */
	  }					/*			    */
	  _strcpy(tokbuf,&(fcbp->fname[8]),3);	/* Copy the string	    */
	}					/*			    */
	if(*filnam == ';')			/* If password specified    */
	{					/*			    */
	  filnam=get_token(++filnam,tokbuf,32);	/* get extension token	    */
	  _strcpy(tokbuf,&(fcbp->fpasswd[0]),8);/* Copy the string	    */
	}					/*			    */
	switch(*filnam)				/* Check for EOS	    */
	{					/*			    */
	  case NULL:				/* Null terminated	    */
	  case '\n':				/* CCPM compatible	    */
	  case '\r':				/*   "      "		    */
		return NULLPTR;			/* everything a-ok	    */
	}					/****			    */
	return FAILPTR;				/* Not legal file name	    */
}						/****************************/


MLOCAL _strcpy(s,d,c)				/* Special string copy func */
REG	BYTE	*s;				/* Source string	    */
REG	BYTE	*d;				/* Destination area	    */
REG	WORD	 c;				/* Count		    */
{						/****************************/
	while ((*s) && (c))			/* 			    */
	{					/*			    */
		*d++ = toupper(*s);		/* Copy a byte		    */
		s++;				/* Up source		    */
		c--;				/* Down count		    */
	}					/*			    */
}						/****************************/

/****************************************************************************/
/*									    */
/*		    G e t _ t o k e n   R o u t i n e			    */
/*		    ---------------------------------			    */
/*									    */
/*	Routine get_token takes the next token from the input string.	    */
/*									    */
/*	Calling Sequence:						    */
/*		ret = get_token(src,dest,len);				    */
/*									    */
/*	Where:								    */
/*		src	is the address of the source string		    */
/*		dest	is the address of the destination area		    */
/*		len 	is the number of bytes in "dest".		    */
/*									    */
/*		ret	is the returned address of the delimiter	    */
/*									    */
/****************************************************************************/
MLOCAL BYTE *_delim="<>.,=:|[]*\n\r";		/* Delimiter set	    */
MLOCAL BYTE *get_token(src,dest,len)		/*			    */
REG	BYTE	*src;				/* -> source		    */
REG	BYTE	*dest;				/* -> destination	    */
REG	WORD	 len;				/* output area size	    */
{						/****************************/
	while(*src && (!strchr(_delim,*src)) && len)/* Until done	    */
	{					/*			    */
	  *dest++ = *src++;			/* Move 1 byte		    */
	   len--;				/* Down count		    */
	}					/****************************/
	*dest = '\0';				/* Drop in null terminator  */
	return(src);				/* Return delimiter addr.   */
}						/****************************/

/****************************************************************************/
/*									    */
/*		   S t u f f _ d r i v e   F u n c t i o n		    */
/*		   ---------------------------------------		    */
/*									    */
/*	Routine "stuff_drive" loads the user and drive code fields from     */
/*	the filename string.						    */
/*									    */
/*	Calling sequence:						    */
/*		ret = stuff_drive(fcbp,src);				    */
/*									    */
/*	Where:								    */
/*		fcbp	Is the FCB address within the ccb		    */
/*		src	Is the source filename string			    */
/*		ret	Is SUCCESS if ok, FAILURE o.w.			    */
/*									    */
/****************************************************************************/
MLOCAL	WORD	stuff_drive(fcbp,src)		/*			    */
	struct fcbtab *fcbp;			/* -> FCB area		    */
REG	BYTE	*src;				/* -> Source string	    */
{						/****************************/
REG	WORD	i;				/* Accumulator		    */
	i = 0;					/* Zap to zero		    */
	while(isdigit(*src))			/* As long as source is dig.*/
	{					/*			    */
	  i = (i*10) + *src++ - '0';		/* Convert to number	    */
	  fcbp->fuser = i+1;			/* store user number	    */
	}					/****************************/
						/*			    */
	if(*src)				/* Drive code letter?	    */
	{					/* Here => yes		    */
	  fcbp->drive = toupper(*src)-'A'+1;	/* get drive code byte	    */
	  src++;				/* Increment source pointer */
	}					/*			    */
	if(*src || 				/* Illegal  stuff?	    */
		(fcbp->fuser > 15) ||		/* Bad user #?		    */
		(fcbp->drive > 15) )		/* Bad drive?		    */
		return(FAILURE);		/* Yes, quit		    */
	return(SUCCESS);			/* OK to continue	    */
}						/****************************/

#endif	/*==================================================================*/
