🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: alt.msdos.programmer
Article #226

Turbo C wildcard expansion

#226
From: Frank Whaley
Date: Wed, 25 Oct 1989 21:43
372 lines
6973 bytes
/*
 *	setargv.c ->	parse arguments
 *
 *	This code evolved out of a requirement for expansion of wild-card
 *	arguments given on the command line.  Turbo C's wildarg.obj
 *	actually produces a reference to __wildargv, which still doesn't
 *	do the job I needed (for example, directory names are not
 *	expanded).
 *
 *	This version both expands wild-card arguments and converts them
 *	to lower case (a cosmetic thing for me).  Arguments that are
 *	quoted (with either " or ') are left alone, but the quote
 *	characters are stripped.  A leading quote may be escaped with
 *	a backslash (\" or \').  Quotes within arguments (ARG="a b c")
 *	are not handled in the Un*x fashion.  If no matching filename
 *	is found, the argument is passed unchanged.
 *
 *	Two conditional-compilation flags are provided:
 *		FIXARG0:	convert argv[0] to lower case and switch
 *				all backslashes to slashes (cosmetic)
 *		SORTARGS:	use qsort() to sort the expansions of
 *				each argument
 *
 *	Further enhancements greatly appreciated.
 *
 *	This code placed in the public domain on October 25, 1989 by
 *	its original author, Frank Whaley.
 */

#define	MAXARG	1024	/*  max arguments  */

#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <mem.h>
#include <string.h>
#include <alloc.h>

	/*  let's do some things with macros...  */
#define	ISQUOTE(c)	(((c)=='"')||((c)=='\''))
#define	ISBLANK(c)	(((c)==' ')||((c)=='\t'))


static char *cl;		/*  -> local copy of command line  */

	/*  the following are used by run-time startup (c0?.obj)  */
extern int _argc;		/*  number of args  */
extern char **_argv;		/*  arg ptrs  */

	/*  forward declarations  */
static void *allocopy(void *src, int len);
static void getreg(char *av[]);
static void getwild(char *av[]);


/*
 *	_setargv() ->	set argument vector
 */
void
_setargv()
{
	char buf[128];		/*  working buffer  */
	char far *cline;	/*  generic far ptr  */
	char *av[MAXARG];	/*  working vector  */
	int len;		/*  command line length  */

	/*  copy program name from environment  */
	cl = buf;
	cline = MK_FP(*(int far *)MK_FP(_psp, 0x2c), 0);
	while ( *cline )
	{
		if ( !*++cline )
		{
			cline++;
		}
	}
	cline += 3;
	while ( *cline )
	{
#ifdef	FIXARG0
		*cl = tolower(*cline++);
		if ( *cl == '\\' )
		{
			*cl = '/';
		}
		cl++;
#else
		*cl++ = *cline++;
#endif
	}
	*cl = '\0';
	av[0] = allocopy(buf, strlen(buf) + 1);

	/*  copy cmd line from PSP  */
	cl = buf;
	cline = MK_FP(_psp, 0x80);
	len = *cline++;
	while ( len )
	{
		*cl++ = *cline++;
		len--;
	}
	*cl = 0;

	_argc = 1;
	cl = buf;
	while ( *cl )
	{
		/*  deblank  */
		while ( ISBLANK(*cl) )
		{
			cl++;
		}

		/*  pick next argument  */
		while ( *cl && (_argc < MAXARG) )
		{
			if ( iswild() )
			{
				getwild(av);
			}
			else
			{
				getreg(av);
			}

			/*  deblank  */
			while ( ISBLANK(*cl) )
			{
				cl++;
			}
		}
	}

	/*  copy argument vector  */
	_argv = allocopy(av, _argc * sizeof(char *));
}


/*
 *	does current argument contain a wildcard ??
 */
static int
iswild()
{
	char *s = cl;

	if ( ISQUOTE(*s) )
	{
		return ( 0 );
	}

	while ( *s && !ISBLANK(*s) )
	{
		if ( (*s == '\\') && ISQUOTE(*(s + 1)) )
		{
			s += 2;
		}
		else if ( (*s == '?') || (*s == '*') )
		{
			return ( 1 );
		}

		s++;
	}

	return ( 0 );
}


/*
 *	allocopy() ->	allocate space for a copy of something
 */
static void *
allocopy(void *src, int len)
{
	void *copy;

	copy = sbrk(len);
	if ( copy == (void *)(-1) )
	{
		write(2, "\nMemory shortage\n", 17);
		exit(1);
	}
	return ( memcpy(copy, src, len) );
}


/*
 *	getreg() ->	pick a regular argument from command line
 */
static void
getreg(char *av[])
{
	char buf[128];
	char *bp = buf;
	char quote;

	/*  copy argument (minus quotes) into local buffer  */
	if ( ISQUOTE(*cl) )
	{
		quote = *cl++;
		while ( *cl&& (*cl != quote) )
		{
			*bp++ = *cl++;
		}
	}
	else
	{
		while ( *cl && !ISBLANK(*cl) )
		{
			if ( (*cl == '\\') && ISQUOTE(*(cl + 1)) )
			{
				cl++;
			}

			*bp++ = *cl++;
		}
	}
	*bp = '\0';

	/*  skip over terminator char  */
	if ( *cl )
	{
		cl++;
	}

	/*  store ptr to copy of string  */
	av[_argc++] = allocopy(buf, strlen(buf) + 1);
}


/*
 *	lwrcat() ->	concatenate strings, conver to lower case
 */
static char *
lwrcat(char *s, char *t)
{
	char *cp = s;

	while ( *cp )
	{
		cp++;
	}
	/*  avoid a warning  */
	while ( *t )
	{
		*cp++ = tolower(*t++);
	}
	*cp = '\0';

	return ( s );
	}


/*
 *	pickpath() ->	pick pathname from argument
 */
static void
pickpath(char *arg, char *path)
{
	char *t;
	int n;

	/*  find beginning of basename  */
	for ( t = arg + strlen(arg) - 1; t >= arg; t-- )
	{
		if ( (*t == '\\') || (*t == '/') || (*t == ':') )
		{
			break;
		}
	}

	/*  pick off path  */
	for ( n = (t - arg) + 1, t = arg; n--; )
	{
		*path = tolower(*t);
		path++;
		t++;
	}
	*path = '\0';
}


#ifdef	SORTARGS
/*
 *	mycmp() ->	comparison routine for qsort()
 */
static int
mycmp(char **s, char **t)
{
	return ( strcmp(*s, *t) );
}
#endif


/*
 *	getwild() ->	get wildcard argument from command line
 */
static void
getwild(char *av[])
{
	char path[128];
	char srch[128];
	char *s = srch;
	struct ffblk f;
#ifdef	SORTARGS
	char **firstv = &av[_argc];
	int nmatched = 0;
#endif

	/*  pick search string  */
	while ( *cl && !ISBLANK(*cl) )
	{
		*s++ = *cl++;
	}
	*s = '\0';

	pickpath(srch, path);

	if ( findfirst(srch, &f, 0x17) )
	{
		/*  no match, just copy argument  */
		av[_argc++] = allocopy(srch, strlen(srch) + 1);
		return;
	}

	/*  add name if not "." or ".."  */
	if ( f.ff_name[0] != '.' )
	{
		strcpy(srch, path);
		lwrcat(srch, f.ff_name);
		av[_argc++] = allocopy(srch, strlen(srch) + 1);
#ifdef	SORTARGS
		nmatched++;
#endif
	}

	/*  find the rest  */
	while ( !findnext(&f) && (_argc < MAXARG) )
	{
		if ( f.ff_name[0] != '.' )
		{
			strcpy(srch, path);
			lwrcat(srch, f.ff_name);
			av[_argc++] = allocopy(srch, strlen(srch) + 1);
#ifdef	SORTARGS
			nmatched++;
#endif
		}
	}

#ifdef	SORTARGS
	/*  sort these entries  */
	qsort(firstv, nmatched, sizeof(char *), mycmp);
#endif
}


/*
 *	END of setargv.c
 */
-- 
Frank Whaley
Senior Development Engineer
Quadratron Systems Incorporated
few@quad1.quad.com
uunet!ccicpg!quad1!few

Water separates the people of the world;
Wine unites them.
Technical Details
Message-ID: <3574@gouda.quad.com>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wuarchive!gem.mps.ohio-state.edu!usc!srhqla!quad1!few

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!wuarchive!gem.mps.ohio-state.edu!usc!srhqla!quad1!few
From: few@quad1.quad.com (Frank Whaley)
Newsgroups: alt.msdos.programmer,comp.sys.ibm.pc
Subject: Turbo C wildcard expansion
Keywords: TurboC wildcard
Message-ID: <3574@gouda.quad.com>
Date: 25 Oct 89 21:43:24 GMT
Organization: Quadratron Systems, Westlake Village, CA
Lines: 372