[comp.binaries.ibm.pc] Turbo C's searchpath

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