/**
* module	FFC\Filespec
*
* purpose	Parse and Make Filespecs.
*
* logic 	Simple string manipulation.
*
* cautions	All output-pointers to char arrays that are to be "filled in"
*		must have their memory allocated per #defines in "filespec.h".
*
* includes	<ffc/filespec.h>
*
* copyright	(c) Fran Finnegan Associates 1986
**/

#ifndef LINT_ARGS
#define LINT_ARGS
#endif
//	#include <string.h>
//	#include <ffc/const.h>
//	#include <ffc/filespec.h>
//	#include <ffc/string.h>

#define PATH		'\\'    /* PATH delimiter */
#define MAX_SPEC_CHARS	(FILESPEC - 1)		/* should be 63 */
#define MAX_PATH_CHARS	(FILESPEC_PATH - 1)	/* should be 62 */
#define MAX_NAME_CHARS	(FILESPEC_NAME - 1)	/* should be 8 */
#define MAX_EXT_CHARS	(FILESPEC_EXT - 2)	/* should be 3 */

static	char		mszFilespec[FILESPEC];
static	char		mszNull[] = "";
static	char		mszNUL[] = "NUL";

/*p*/

/**
* function	MakeFilespec
*
* purpose	Builds a filespec from supplied components.
*
* logic 	See commented code.
*
* cautions	A PATH gets suffixed to pszPath;  a '.' gets prefixed to pszExt.
*		All output-pointers to char arrays that are to be "filled in"
*		must have their memory allocated per #defines in "filespec.h".
*
* usage 	pszFilespec = MakeFilespec(pszFilespec, pszDrive, pszPath,
*			pszName, pszExt);
*
* arguments			(any of these may be NULL)
*		Output:
*			char	*pszFilespec;	 "d:\\path\\filename.ext"
*		Input:
*			char	*pszDrive;	 "d:", "d" or ""
*			char	*pszPath;	 "\\path\\", "\\", "",
*						 "\\path" or "path\\"
*			char	*pszName;	 "filename"
*			char	*pszExt;	 ".ext", "ext" or ""
*
* returns	pszFilespec = Filespec.
*
* modifies	no externals.
*
* examples	Obvious.
*
* copyright	(c) Fran Finnegan Associates 1986
**/

extern	char		*MakeFilespec(pszFilespec, pszDrive, pszPath, pszName,
				pszExt)

	char		*pszFilespec,
			*pszDrive,
			*pszPath,
			*pszName,
			*pszExt;
{
register char		*pc;

if (no pszFilespec)			/* allow Filespec to be NULL	*/
    pszFilespec = mszFilespec;
memset(pszFilespec, Null, FILESPEC);	/* zero out Filespec		*/
if (no pszDrive)			/* allow Drive to be NULL	*/
    pszDrive = mszNull;
if (no pszPath) 			/* allow Path to be NULL	*/
    pszPath = mszNull;
if (no pszName) 			/* allow Name to be NULL	*/
    pszName = mszNull;
if (no pszExt)				/* allow Ext to be NULL 	*/
    pszExt = mszNull;
					/********** Drive ***************/
pszFilespec[0] = *pszDrive;		/* begin with possible Drive	*/
pszFilespec[1] = ':';                   /* assume it was supplied       */
					/********** Path ****************/
if (!IsStrNull(pszPath)) {		/* if a Path was supplied:	*/
    strncat(pszFilespec, pszPath,	/*	add Path		*/
	    MAX_PATH_CHARS);		/*	  only the valid bytes	*/
    pc = StrNull(pszFilespec);		/*	find end-of-string	*/
    if (*(pc - 1) != PATH)		/*	see if it's not PATH:   */
	*pc = PATH;			/*		add PATH	*/
    }
					/********** Name ****************/
strncat(pszFilespec, pszName,		/* add Name			*/
	MAX_NAME_CHARS);		/*   only the valid bytes	*/
					/********** Ext *****************/
if (!IsStrNull(pszExt)) {		/* if an Ext was supplied:	*/
    strcat(pszFilespec, ".");           /*      add '.'                 */
    strncat(pszFilespec,		/*	add Ext 		*/
	    StrSkip(pszExt, "."),       /*        check for a '.':      */
	    MAX_EXT_CHARS);		/*	  only the valid bytes	*/
    }
					/********** Filespec ************/
if (IsStrNull(pszFilespec))		/* allow Filespec to be Null	*/
    strcat(pszFilespec, mszNUL);	/*	convert it to NUL:	*/
return (strupr(pszFilespec));		/* convert it to upper case	*/
}

/*p*/

/**
* function	ParseFilespec
*
* purpose	Breaks up a filespec into its components.
*
* logic 	See commented code.
*
* cautions	All output-pointers to char arrays that are to be "filled in"
*		must have their memory allocated per #defines in "filespec.h".
*
* usage 	ParseFilespec(pszFilespec, pszDrive, pszPath, pszName, pszExt);
*
* arguments			(any of these may be NULL)
*		Input:
*			char	*pszFilespec;	 "d:\\path\\filename.ext"
*		Output:
*			char	*pszDrive;	 "d:" or ""
*			char	*pszPath;	 "\\path", "\\" or ""
*			char	*pszName;	 "filename"
*			char	*pszExt;	 "ext" or ""
*
* returns	nothing.  Filespec components are passed via the arguments.
*
* modifies	no externals.
*
* examples	Obvious.
*
* copyright	(c) Fran Finnegan Associates 1986
**/

extern	void		ParseFilespec(pszFilespec, pszDrive, pszPath, pszName,
				pszExt)

	char		*pszFilespec,
			*pszDrive,
			*pszPath,
			*pszName,
			*pszExt;
{
register char		*pc;

auto	char		szSpec[FILESPEC];

if (no pszFilespec)			/* allow Filespec to be NULL	*/
    pszFilespec = mszNUL;
if (no pszDrive)			/* allow Drive to be NULL	*/
    pszDrive = mszFilespec;
if (no pszPath) 			/* allow Path to be NULL	*/
    pszPath = mszFilespec;
if (no pszName) 			/* allow Name to be NULL	*/
    pszName = mszFilespec;
if (no pszExt)				/* allow Ext to be NULL 	*/
    pszExt = mszFilespec;
memset(pszDrive, Null, FILESPEC_DRIVE); /* zero out Drive		*/
memset(pszPath , Null, FILESPEC_PATH ); /* zero out Path		*/
memset(pszExt  , Null, FILESPEC_EXT  ); /* zero out Ext 		*/
pszName[MAX_NAME_CHARS] =		/* end Name buffer		*/
 szSpec[MAX_SPEC_CHARS] = Null; 	/* end Spec buffer		*/
					/********** Filespec ************/
pszFilespec =				/* use the upper case version	*/
	strupr(strncpy(szSpec,		/*   convert it to upper case	*/
	pszFilespec, MAX_SPEC_CHARS));	/*   only the valid bytes	*/
					/********** Drive ***************/
if (pszFilespec[1] == ':') {            /* if it looks like a Drive:    */
    *pszDrive++ = *pszFilespec; 	/*	copy Drive		*/
    *pszDrive = ':';                    /*      add ':'                 */
    pszFilespec += 2;			/*	move past Drive 	*/
    }
					/********** Path ****************/
if (pc = strrchr(pszFilespec, PATH)) {	/* find last PATH in Filespec:	*/
    *pc++ = Null;			/*	end Path		*/
    strncpy(pszPath, pszFilespec,	/*	copy Path		*/
	    MAX_PATH_CHARS - 1);	/*	  only the valid bytes	*/
    if (IsStrNull(pszPath))		/*	take root into account: */
	*pszPath = PATH;		/*		set root	*/
    pszFilespec = pc;			/*	move past Path		*/
    }
					/********** Name ****************/
if (pc = strchr(pszFilespec, '.'))      /* find first '.' in Filespec:  */
    *pc++ = Null;			/*	end Name		*/
strncpy(pszName, pszFilespec,		/* copy Name			*/
	MAX_NAME_CHARS);		/*   only the valid bytes	*/
					/********** Ext *****************/
if (pc) 				/* if a '.' exists:             */
    strncpy(pszExt, pc, MAX_EXT_CHARS); /*	copy Ext		*/
}
