char *hithere = 
"Perfect Speller Version 1.01\nCopyright (c) 1982 Perfect Software, Inc.";

#define NP      7               /* number of primes (& hashing functions) */
#define NW      30              /* max word length */
#define MAXPRE  60              /* maximum number of prefixes allowed */
#define MAXSUF  100             /* maximum number of suffixes allowed */
#define MAXLEV  2               /* maximum number of suffix recursion levels */
#define LISTMIN 512             /* minimum for unrecognized word list */
#define FORIO   2000            /* # bytes I/O requires at TOP */

#define APOST   047
#define BEL     007
#define ESC     033
#define BKSP    010
#define CTLZ    032
#define CTLC    003

#define PRINDICT -1             /* Prefix(..) return codes */
#define NOMATCH 0
/* Prefix(..) > 0 ==> offset of match */

#define FATAL   0               /* error codes -- determine 'err' return */
#define WARNING 1

char *dictnry = "DICTNARY.SPL";
char *upddict = "A:UPDDICT.$$$";
char *affix = "AFFIXTAB.SPL";
char *addfile = "ADDDICT.SPL";
char *editor = "PW";            /* enough space to patch in any editor */
char *edparams = "-SPELL                ";      /* space for filename! */
char *fullname;                 /* full filename found by spfopen() */

char *hashtab;
int tablen1 = 0;        /* Length(s) of hash table */
int tablen2 = 0;
unsigned tablen = 0;

unsigned *pow2[NP];
int p[NP] =
{   
	241, 239, 233, 229, 227, 223, 211   };

char *pretab[MAXPRE];  
int npre;        /* prefix table */
char *suftab[MAXSUF];  
int nsuf;        /* suffix table */
int maxlev = MAXLEV;    /* variable for maximum number of suffix recursion */
int addonly = 0;        /* flag signifying to only add words to dictionary */
int lookup = 0;         /* flag signifying dictionary lookup only */
int newdict = 0;        /* flag denoting dictionary change */
int debug = 0;          /* for programmer only -- undocumented "feature" */
int no_affix = 0;	/* flag for not using affix-stripper */

char oldc = 0;          /* previously-read lower-case character for GetWord */
char oldrc = 0;         /* previously-read raw char, as above */

/* linked list maintenance data */
char *freeptr;          /* pointer to next avail byte in linked list buf */
unsigned bufleft = 0;   /* space left in linked list buffer */
char *List[26];         /* array of pointers to first elements--each letter*/
int wc = 0, mc = 0;     /* word count; missed (unrecognized) count */

char backname[20];      /* backup filename -- read from when marking */
char *backext = "BAK";  /* default extension for backup file */
char marker = 0223;     /* ~^S = default marker for misspelled words */
int keepbak = 1;        /* flag denoting whether or not to keep backup */
char inp_buf[NW] = {
	NW};/* buffer for user input via cgets() */
char strspace[75];      /* space for free string space */
char *strptr, *endstr;  /* pointers into free string space */

#include "stdio.h"
#include "ctype.h"
#include "printf.c"     /* special small {format(); printf();} */
int _stack = 512;       /* only need a small run-time stack */
char *cgets(), *PreA();  
FILE *spfopen();

main(argc, argv)
int argc;  
char *argv[];
{       
	char word[NW], rawword[NW], filename[20], *np, *dp;
	int i=1, j, remain, wlok, n, c, countdown = 100;  
	FILE *fp;

	while (--argc > 0 && *argv[i] == '-')
	{       
		switch (maklower(*(argv[i]+1))) {
/* add dict */  case 'a':       
			addonly = 1;
			if (addonly && isnum(*(argv[i+1])))
			{   
				for (np=argv[++i]; isnum(*np); )
					tablen = tablen*10 + *np++ - '0';
				--argc;
			} 
			break;
/* backup ext */case 'b':       
			keepbak = 1;  
			backext = argv[++i];  
			--argc;
			break;
/* dict name */ case 'd':       
			dictnry = argv[++i];  
			--argc;  
			break;
/* editor */    case 'e':       
			editor = argv[++i];  
			--argc;  
			break;
/* lookup */    case 'l':       
			lookup = 1;  
			break;
/* marker */    case 'm':       
			marker = *argv[++i];  
			--argc;  
			break;
/* no backup */ case 'n':       
			keepbak = 0;  
			break;
/* no afx use */case 's':	
			no_affix = 1;  
			break;
/* affix name */case 'x':       
			affix = argv[++i];  
			--argc;  
			break;
/* debug */     case '^':       
			debug = 1;  
			break;
		default:        
			err(WARNING, "Illegal option ", argv[i]+1);
		}
		i++;
	}
	if (!lookup) puts(hithere);
	Init();

	if ((fp=spfopen(addfile,"r")) != NULL)  /* grow dictionary */
	{   
		addfile = fullname;         /* remember full name */
		while (GetWord(fp, word, rawword))
		{   
			mc += AddDict(word);
			if (debug) {
				format("%u %u\r");  
				printf(wc);  
				printf(mc);
			}
		}
		format("%u words added to dictionary.\n");  
		printf(wc);
		mc = wc = 0;  
		newdict = 1;  
		fclose(fp);
	}

	if (*(dictnry+1) == ':') /* MS-DOS filename prefix */
		*upddict = *dictnry;
	else upddict += 2;      /* delete prefix to use default disk */

	if (argc >= 1)  np = argv[i];
	else if (addonly) {
		WriteDict();  
		quit();
	} 
	else
	{   
		cputs("File to check: ");  
		np = cgets(inp_buf);  
		putch('\n');  
	}
	strcpy(filename, np);  
	strcpy(&edparams[7], np);
	if ((fp=fopen(filename,"r")) == NULL)
		err(FATAL, "Cannot open ", filename);

	wlok = 1;       /* set to 0 if out of space */
	while (GetWord(fp, word, rawword) && wlok)
	{   
		if (!InDict(word) && (no_affix || !Suffix(word,1,Prefix(word))))
			wlok = ChkIns(rawword, 1);
		if (--countdown == 0 && !lookup)
		{   
			format("%u words processed.  %u words not recognized...\r");
			printf(wc);  
			printf(mc);  
			countdown = 100;
		}
	}
	fclose(fp);
	if (lookup) {
		PrList();  
		quit();
	}
	format("%u words processed.  %u words not recognized.\n");
	printf(wc);  
	printf(mc);

	if (RemList())
	{   
		format("Scan list of unrecognized words now <Yes>? ");
		fflush(stdout);  
		if (Query()) Decide();
	}
	if (newdict) WriteDict();
	if (RemList())
	{   
		format("Marking misspelled words in %s...\n");  
		printf(filename);
		Backup(filename);  
		Mark(filename);
	}
	format("Exit directly to %s <Yes>? ");  
	printf(editor); 
	fflush(stdout);
	if (Query())
	{   
		exec(editor, edparams);
		exec(PreA(editor), edparams);
		format("Cannot find %s.\n");  
		printf(editor);
	}
	quit();
}       

Query()         /* return yes or no answer to a question sent to user */
{       
	int ans;
	if((ans=maklower(getch())) != '\n')  putchar('\n');
	return(ans == '\n' || ans == 'y');      /* <return> == YES */
}

quit()          /* don't ever just exit() -- call this instead */
{    
	exec("MENU","");  
	exec("A:MENU", "");  
	exit(0);   
}

/*
exec(prog, param)
char *prog, *param;
{   
	exit(0);   
}
*/

isnum(c)        /* is c a numeric character? */
char c;
{       
	return(c >= '0' && c <= '9');   
}

/* Special routine to find a file.  If a disk prefix is specified, then only 
   that disk is searched.  If not, the current disk is searched first;
   if not found, disk A: is then searched.  If found, spfopen() returns
   the file pointer of the open file and leaves the full filename
   which (possibly) includes a disk prefix indicating where the
   file was located in the global *fullname; if not found, returns 0.
   Space for the new filename comes through *strptr. */

FILE *spfopen(filename, type)
char *filename, *type;
{   
	FILE *fp;
	if ((fp=fopen(filename, type)) != NULL)
	{   
		fullname = filename;  
		return(fp);   
	}
	if (*(filename+1) != ':')
	{   
		fullname = PreA(filename);
		if (fullname && (fp=fopen(fullname, type)) != NULL)  return(fp);
		strptr = fullname;
	}
	return(NULL);
}

char *PreA(filename)    /* return a string (in string buffer) prefixed by A: */
char *filename;
{   
	char *Aname;
	if (strptr >= endstr-15) return(0);
	Aname = strptr;  
	*strptr++ = 'A';  
	*strptr++ = ':';
	while (*filename) *strptr++ = *filename++;  
	*strptr++ = 0;
	return(Aname);
}

err(type, msg, par)     /* general error routine -- quit() if FATAL */
int type; 
char *msg, *par;
{       
	format((type==FATAL)? "\007FATAL ERROR: " : "\007WARNING: ");
	format(msg);  
	if (par) format(par);
	putchar('\n');  
	if (type == FATAL) quit();
}

Init()
{       
	int chan, i, j;  
	unsigned *lp, h;
	char *tp, *getmem();  
	FILE *fp;

	strptr = strspace;  
	endstr = strptr+75;
	/* read prefixes and suffixes from 'affix' file */
	if ((fp=spfopen(affix, "r")) == NULL)
		err(FATAL, "Cannot open ", affix);
	npre = getaffix(fp, pretab, MAXPRE);
	nsuf = getaffix(fp, suftab, MAXSUF);
	fclose(fp);

	/* read basic dictionary from file 'dictnry' */
	chan = open(dictnry, 0x8000);
	if (chan != -1)
	{   
		if (read(chan, &tablen, 2) <= 0) /* first byte contains length */
			err(FATAL, "Cannot read ", dictnry);
	} 
	else if (!addonly) err(FATAL, "Cannot open ", dictnry);
	else if (tablen == 0) err(FATAL, "Specify length following -A", 0);
	tablen1 = tablen >> 1;  
	tablen2 = tablen - tablen1;
	if ((hashtab = getmem(tablen)) == NULL) 
	{ 
ful: 
		err(FATAL, "Not enough memory.", 0); 
	}
	if (addonly && chan == -1)  setmem(hashtab, tablen, 0);
	else
	{   
		if ((read(chan, hashtab, tablen1) < 0) ||
		    (read(chan, hashtab + tablen1, tablen2) < 0))
			err(FATAL, "Cannot read ", dictnry);
		close(chan);
	}

	for (i=0; i<NP; i++)
	{       
		pow2[i] = (unsigned *) getmem(NW+NW);
		h = *(lp = pow2[i]) = 1<<7;
		for (j=0; j<NW; j++)
			h = *++lp = (h<<7) % p[i];
	}

	/* Finally, get linked list space */
	if ((allmem() < 0) || 
	    ((bufleft = (sizmem() << 1) - FORIO) <= LISTMIN)) goto ful;
	if ((freeptr=getmem(bufleft)) == NULL) goto ful;
	if (debug) {
		format("List = %u\n");  
		printf(bufleft);
	}
}

getaffix(fp, affixtab, maxafx)      /* fills 'affixtab' and returns total */
FILE *fp;  
char *affixtab[];  
int maxafx;
{       
	int i, c;  
	char *tp, *xp, temp[NW], *getmem();

	for (i=0; ; )
	{   
		tp = &temp[0];
		while ((c=getc(fp)) != '\n' && c != EOF) *tp++ = c;  
		*tp = '\0';
		if (tp == &temp[0] || c == EOF) break;
		if (i == maxafx-1)
		{   
			err(WARNING, "Affix table overflow at ", temp); 
			break;   
		}
		xp = affixtab[i++] = getmem(tp - &temp[0] + 1);
		if (maxafx == MAXPRE) strcpy(xp, temp); 
		else
		{   
			while (tp > &temp[0]) *xp++ = *--tp; /* reverse suffixes */
			*xp = '\0';   
		}
	}
	return(i);
}

GetWord(fp, word, rawword)
FILE *fp;  
char *word, *rawword;
{       
	int c, rc, numlett;
	if (!oldrc) c = maklower(rc=getc(fp));
	else {
		c = oldc;  
		rc = oldrc;  
		oldc = oldrc = 0;
	}
	while (!isalpha(c) && rc != EOF)  c = maklower(rc=getc(fp));
	if (rc == EOF) return(0);
	numlett = NW;
	do  /* got a first letter -- now process the word */
	{   
		if (!--numlett) break;      /* space for NW chars only */
		if ((c=maklower(rc)) == '-')/* ignore hyphens at line ends */
		{   
			if ((rc=getc(fp)) == '\n') continue;
			oldc=maklower(oldrc=rc);
		}
		if (!isalpha(c) && c != APOST) break;   /* must be end then */
		*word++ = c;  
		*rawword++ = rc;
	} 
	while ((rc=getc(fp)) != EOF);
	*word = *rawword = 0;  
	wc++;
	return(1);
}

maklower(c)
int c;
{   
	c &= 0x7F; 
	return(isupper(c)? c + ('a'-'A') : c);   
}

InDict(word)
char *word;
{       
	unsigned i, h, h2, *lp;  
	char *wp;

	for (i=0; i<NP; i++)
	{   
		for (wp=word, h = h2 = 0, lp = pow2[i]; *wp; ++wp)
		{   
			h += *wp * *lp;  
			h2 += *wp & *++lp;   
		}
		h2 = 1 << (h2 & 7);
		while (h >= tablen) h -= tablen;
		if (!(*(hashtab+h) & h2)) return(0);
	}
	return(1);
}

Suffix(word, level, trypre)    /* try some possible suffixes and prefixes */
char *word; 
int level, trypre;
{       
	char locword[30];  
	int changed, i;
	char *lwp, *wp, *sp, *endwrd;

	if (trypre == PRINDICT) return(1);
	changed = 1;
	for (i=0; i<nsuf; i++)
	{       
		if (changed)
		{   
			wp = word;  
			lwp = &locword[0];
			while (*wp) *lwp++ = *wp++;  
			*lwp = '\0';
			endwrd = lwp-1;  
			changed = 0; 
		}
		sp = suftab[i];  
		lwp = endwrd;
		while (*lwp == *sp) { 
			--lwp; 
			++sp; 
		}
		if (*sp != '+') continue;            
		if (*++sp == 'C')
		{       
			if (vowel(*lwp) || *lwp != *(lwp-1))  continue;
			else lwp--;
		} 
		else
			if (*(wp=sp))
			{       
				while (*wp != '-') wp++;
				while (--wp >= sp) *++lwp = *wp;
			}
		*++lwp = '\0';  
		changed = 1;
		if (InDict(locword)) return(1);
		if (level < maxlev)     /* recursive call up to maxlev */
			if (Suffix(locword, level+1, trypre)) return(1);
		if (trypre && InDict(locword+trypre)) return(1);
	}
	return(0);
}

vowel(c)
char c;
{       
	switch(c)  {
	case 'a':
	case 'e':
	case 'i':
	case 'o':
	case 'u':
	case 'y': 
		return(1);
	}
	return(0);
}

Prefix(word)            /* match against pretab for prefixes */
char *word;
{       
	int i, trypre;  
	char *pp, *wp;
	trypre = NOMATCH;
	for (i=0; i<npre; i++)
	{       
		pp = pretab[i];  
		wp = word;
		while (*pp++ == *wp++) ;                
		if (*--pp) continue;                    
		trypre = --wp - word;
		if (InDict(wp)) return(PRINDICT);
	}       
	return(trypre);
}

ChkIns(word, add)       /* check to see if word is on list */
char *word; 
int add;    /* add if requested by "add" flag */
{       
	char **lp, **olp;  
	int cp;
	lp = (char **) List[maklower(*word) - 'a'];
	olp = &List[maklower(*word) - 'a'];
	while (lp)
	{   
		if ((cp=compare(lp,word)) == 0)  return(1);
		if (cp < 0) break;
		/* otherwise, must be > 0 meaning we haven't gone far enuf */
		olp = lp;  
		lp = (char **) *lp;
	}
	return((add)? insert(olp, word) : 0);
}

compare(lwp,word)
char *lwp, *word;
{       
	int cmp, i;  
	char *nwp;
	nwp = word;  
	cmp = 0;  
	lwp += 2;
	for (i=0; i<NW; i++)
	{       
		if (*nwp == 0 && *lwp == 0) {
			cmp = 0; 
			break;
		}
		if (maklower(*nwp) > maklower(*lwp)) {
			cmp = 1;  
			break;
		}
		if (maklower(*nwp++) < maklower(*lwp++)) {
			cmp = -1;  
			break;
		}
		/* these two characters are equal -- continue */
	}
	return(cmp);
}

insert(lwp, word)
char **lwp;  
char *word;
{       
	char **element, *next;
	mc++;   /* increment misspelled wordcount */
	next = *lwp;
	*lwp = freeptr;  
	element = (char **) freeptr;  
	*element = next;
	freeptr += 2;  
	bufleft -= 3;   /* anticipate trailing '\0' */
	while (*word)
	{       
		*freeptr++ = *word++;  
		bufleft--;       
	}
	*freeptr++ = '\0';
	if (bufleft < 100)
	{       
		err(WARNING, "Out of space on misspelled wordlist.", 0);
		return(0);      
	}
	return(1);
}

PrList()
{       
	int i;  
	char *lp, **ip;
	for (i=0; i<26; i++)
	{       
		lp = List[i];
		while (lp)
		{       
			format("%s\n");  
			printf(lp+2);
			ip = (char **) lp;  
			lp = *ip;   
		}
	}
}

Decide()        /* scan linked list, asking user to decide disposition */
{       
	int oldmode, i, ansok, c;  
	char *lp, *wp, **ip;

	for (i=0; i<26; i++)
	{       
		lp = List[i];
		while (lp)
		{       
			ansok = 0;  
			cputs(lp+2);  
			cputs("? ");
			switch(c = maklower(getch())) {
/* add Root only */     case 'r':       
				cputs("root = ");
				wp = cgets(inp_buf);  
				putch('\n');
				if (*wp)
				{   
					AddDict(wp);  
					delword(lp+2);
					ansok = 1;  
					newdict = 1;  
				} 
				break;
/* Add to dictnry */    case 'a':       
				AddDict(lp+2);  
				newdict = 1;
				delword(lp+2);  
				ansok = 1;
				cputs("add\r\n");  
				break;
/* Ignore */            case 'i':       
				delword(lp+2);  
				ansok = 1;
				cputs("ignore\r\n");  
				break;
/* Change */            case 'c':       
				ansok = 1; 
				cputs("change\r\n"); 
				break;
/* go Edit now */       case 'e':       
				cputs("edit\r\n");  
				return;
			case CTLC:      
				exit(1);
			default:        
				putch(c);  
				cputs("\nAnswer with:\r\n");
				format("  a - Add word to dictionary\r\n");
				format("  i - Ignore word\r\n");
				format("  c - mark word to be Changed\r\n");
				format("  r - enter word's Root into dictionary\r\n");
				format("  e - mark remaining words and Edit text\r\n\n");
			}
			if (ansok) {
				ip = (char **)lp;  
				lp = *ip;
			}
		}
	}
}

AddDict(word)
char *word;
{       
	unsigned i, c, h, h2, ans, *lp;  
	char *wp, locword[NW], *lwp;
	ans = 1;
	for (lwp = &locword[0]; *lwp++ = maklower(*word++); );
	for (i=0; i<NP; i++)
	{       
		for (wp=locword, h = h2 = 0, lp = pow2[i]; c = *wp++; )
		{       
			h += c * *lp;  
			h2 += c & *++lp;   
		}
		h2 = 1 << (h2 & 7);
		while (h >= tablen) h -= tablen;
		if ((*(hashtab+h) & h2) == 0) ans = 0;
		*(hashtab+h) |= h2;
	}
	return ans;
}


delword(word)    /* delete word from linked list */
char *word;
{       
	int cp;  
	char **lp, **olp;
	lp = (char **) List[maklower(*word) - 'a'];  
	olp = &List[maklower(*word) - 'a'];
	while (lp)
	{       
		if ((cp=compare(lp,word)) == 0)  {
			*olp = *lp;  
			return(1);
		}
		if (cp < 0) break;
		/* otherwise, must be > 0 meaning we haven't gone far enuf */
		olp = lp;  
		lp = (char **) *lp;
	}
	err(FATAL, "Bad wordlist structure", 0);
}

WriteDict()     /* output updated dictionary -- messy to handle errors */
{   
	int chan, trouble, answer;
	do
	    {   
		trouble = 0;
		if ((chan = creat(upddict, 0x8001)) == -1)
		{   
			err(WARNING, "Cannot write new dictionary", 0);  
			return(0); 
		}
		write(chan, &tablen, 2);        /* write length */
		if (write(chan, hashtab, tablen1) != tablen1 ||
		    write(chan, hashtab+tablen1, tablen2) != tablen2)
		{   
			close(chan);
			err(WARNING, "Trouble writing new dictionary", 0);
			format("Delete old dictionary before writing (Risky!)? ");
			if (maklower(putch(getch())) == 'y') 
			{   
				unlink(dictnry);  
				trouble = 1;   
			}
			else {
				unlink(upddict);  
				return(0);
			}
		}
	} 
	while (trouble);
	close(chan);  
	unlink(addfile);  
	unlink(dictnry);
	rename(upddict, dictnry);
}

RemList()       /* check wordlist for remaining words */
{       
	int i;
	for (i=0; i<26; i++)
		if (List[i]) return(1);
	return(0);
}

Backup(file)
char *file;
{       
	char newfile[20], oldfile[20], *ofp, *nfp;  
	int ext, i;
	ext = 0;  
	ofp=file;  
	nfp=oldfile;
	while (*ofp) if ((*nfp++ = *ofp++) == ':') ext = 1;
	*nfp = '\0';  
	nfp = newfile;  
	ofp = oldfile;
	while (*ofp && *ofp != '.') *nfp++ = *ofp++;
	*nfp++ = '.';  
	ofp = backext;
	for (i=0; i<4; i++) *(nfp+i) = 0;   /* to handle null extensions */
	strcpy(nfp, backext);  
	strcpy(backname, newfile);  
	unlink(newfile);
	if (!rename(oldfile, newfile)) err(FATAL,"Cannot backup %s", file);  
}

Mark(wfile)     /* Marks misspelled words with 'marker' */
char *wfile;
{       
	int nc;  
	char word[NW], rawword[50], *wp;  
	FILE *rfp, *wfp;

	if ((rfp=fopen(backname,"r")) == NULL ||
	    (wfp=fopen(wfile, "w")) == NULL)
	{   
		err(WARNING,"Cannot mark ", wfile);   
		rename(backname, wfile);
		format("Misspelled words follow:\n");  
		PrList();  
		quit();
	}
	oldc = oldrc = 0;               /* initialize params */
	while (nc=ScanWord(rfp, wfp, word, &rawword[1]))
	{       
		wp = &rawword[1];
		if (ChkIns(word, 0))
		{   
			*--wp = marker;
		}
		PutWord(wfp, wp, nc);
	}
	putc(CTLZ, wfp);  
	fclose(rfp);  
	fclose(wfp);
	if (!keepbak) unlink(backname);  /* delete backup if user wants */
}

ScanWord(rfp, wfp, word, rawword) /* like GetWord; writes non-words thru */
FILE *rfp, *wfp;  
char *word, *rawword;
{       
	int c, rc, numlett;
	if (!oldc) c = maklower(rc=getc(rfp));
	else {
		c = oldc;  
		rc = oldrc;  
		oldc = oldrc = 0;
	}
	while (!isalpha(c) && rc != EOF)
	{   
		putc(rc, wfp);  
		c = maklower(rc=getc(rfp));  
	}
	if (rc == EOF) return(0);

	numlett = NW;
	do      /* got a first letter -- now process the word */
	{   
		if(!--numlett) break;
		if ((c=maklower(rc)) == '-')        /* check for hyphenation */
		{   
			if ((rc=getc(rfp)) == '\r')
			{   
				*rawword++ = c;  
				*rawword++ = rc;
				*rawword++ = getc(rfp);  
				continue;
			}
			else {
				oldc=maklower(oldrc=rc);  
				rc = c;
			}
		}
		if (!isalpha(c) && c != APOST) break;   /* must be end then */
		*word++ = c;  
		*rawword++ = rc;
	} 
	while ((rc=getc(rfp)) != EOF);
	*word = *rawword = 0;  
	return(rc);
}

PutWord(fp, rawword, nxtchar)
FILE *fp;  
char *rawword;  
int nxtchar;
{   
	while (*rawword) putc(*rawword++, fp);
	if (nxtchar != EOF) putc(nxtchar, fp);
}

rename(from, to)        /* roll-your-own rename function */
char *from, *to;
{   
	int curr_drive, drive1, drive2;  
	char FCB[37], *fcb = FCB;
	setmem(fcb, 37, ' ');
	parsefile(from, &drive1, (fcb + 1), (fcb + 9));
	parsefile(to, &drive2, (fcb + 17), (fcb + 25));
	/* make sure the drives specified are equal */
	curr_drive = bdos(0x19) + 1;
	if (!drive1) drive1 = curr_drive;  
	if (!drive2) drive2 = curr_drive;
	if (drive1 != drive2) return(0);
	/* complete the FCB and issue the command */
	*fcb = (char) drive1;  
	return(!bdos(0x17, fcb));
}

parsefile (s, drive, fname, ext)
char  *s;  
int *drive;  
char *fname, *ext;
{   
	*drive = 0;
	if (*(s+1) == ':') {
		*drive = maklower(*s) - 'a' + 1;  
		s += 2;
	}
	while (*s && *s != '.') *fname++ = *s++;
	if (*s) while (*++s) *ext++ = *s;
}
