nelson@sun.soe.clarkson.edu (Russ Nelson) (03/17/88)
/*
* This is a replacement for Turbo C's SEARCHP module. The old one
* would fail to find executables if they were in the root directory and
* the root directory was the current directory.
*
* I reverse compiled Borland's module and fixed the bug. If you wish to
* see what was wrong, then #define bug. If you do this, then the code
* that is generated is identical to Borland's.
*
* It compiles under any memory module.
*/
#pragma asm
#include <dir.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
#define LARGEDATA
#endif
static char *pascal strlcase(char *to, char *from)
{
#ifdef LARGEDATA
asm push ds
asm lds si,from
asm les di,to
#else
_SI = (int) from;
_DI = (int) to;
#endif
asm cld;
again:
asm lodsb
asm cmp al,'a'
asm jb upper
asm cmp al,'z'
asm ja upper
asm sub al,20h
upper:
asm stosb
asm or al,al
asm jne again
asm dec di
#ifdef LARGEDATA
asm mov ax,di
asm mov dx,es
asm pop ds
#else
return ((char *)_DI);
#endif
}
static pascal findone(char *path, char *drive, char *dir, char *name, char *ext, int foo)
{
struct ffblk ff;
char *si, *di;
di = drive;
si = path;
if (*di == '\0') *di = getdisk() + 'A';
else *di &= ~0x20;
/* copy the drive in */
*si++ = *di;
*si++ = ':';
/* absolutize the filename */
if (*dir != '\\' && *dir != '/') {
*si++ = '\\';
getcurdir(*di & ~0x3f, si);
si = strlcase(si, si);
#ifdef bug
*si++ = '\\';
#else
/* if the pathname doesn't end in '\' or '/', add one */
if (si[-1] != '\\' && si[-1] != '/') *si++ = '\\';
#endif
}
si = strlcase(si, dir);
/* if the pathname doesn't end in '\' or '/', add one */
if (si[-1] != '\\' && si[-1] != '/') *si++ = '\\';
si = strlcase(si, name);
if (ext) strlcase(si, ext);
return (findfirst(path, &ff, (foo&2)?0x27:0x37)+1);
}
char *pascal
__SEARCHPATH(const char *fn, int foo)
{
register char *di, *si;
int bar;
static char drive[MAXDRIVE];
static char ext[MAXEXT];
static char path[MAXPATH];
static char dir[MAXDIR];
static char name[MAXFILE];
di = path;
si = NULL;
bar = 0;
if (fn != NULL || *fn != '\0') {
bar = fnsplit(fn, drive, dir, name, ext);
}
if ((bar & 5) != 4) return NULL;
if (foo & 2) {
if (bar & 8) foo &= ~1;
if (bar & 2) foo &= ~2;
}
if (foo & 1) {
si = getenv("PATH");
}
for (;;) {
if (findone(di, drive, dir, name, ext, foo)) break;
if (foo & 2 && findone(di, drive, dir, name, ".COM", foo)) break;
if (findone(di, drive, dir, name, ".EXE", foo)) break;
if (si == NULL || *si == '\0') {
di = NULL;
break;
}
bar = 0;
if (si[1] == ':') {
drive[bar++] = *si++;
drive[bar++] = *si++;
}
drive[bar] = 0;
for (bar = 0; (dir[bar] = *si++) != '\0'; bar++) {
if (dir[bar] == ';') {
dir[bar] = '\0';
break;
}
}
}
return di;
}
char *_Cdecl searchpath (const char *file)
{
return (__SEARCHPATH(file, 1));
}nelson@sun.soe.clarkson.edu (Russ Nelson) (03/23/88)
In article <569@sun.soe.clarkson.edu> nelson@sun.soe.clarkson.edu (Russ Nelson) writes:
Oops. I mistook:
ADD AX,FFC0 << right!
for:
AND AX,FFC0 << wrong!
And these are the diffs to fix it on a source level:
*** searchp.bak
--- searchp.c
**************
*** 70,76
/* absolutize the filename */
if (*dir != '\\' && *dir != '/') {
*si++ = '\\';
! getcurdir(*di & ~0x3f, si);
si = strlcase(si, si);
#ifdef bug
*si++ = '\\';
--- 70,76 -----
/* absolutize the filename */
if (*dir != '\\' && *dir != '/') {
*si++ = '\\';
! getcurdir(*di - '@', si);
si = strlcase(si, si);
#ifdef bug
*si++ = '\\';
--
-russ
AT&T: (315)268-6591 BITNET: NELSON@CLUTX Internet: nelson@clutx.clarkson.edu
GEnie: BH01 Compu$erve: 70441,205