[comp.sys.atari.st] Extra functions for XARG implementation

daemon@stag.UUCP (11/23/87)

It seems that in the source code which accompanies the recently posted
extended argument passing proposal, I assumed the existence of some
functions and a header file which are in dLibs, but are missing from
the libraries of some other C compilers.  The following code fragments
are extracted from dLibs for the benifit of those trying to use the
new XARG structure under other compiler/library combinations.

----------------------------------CUT--HERE---------------------------------
[BASEPAGE.H]
/*
 *	BASEPAGE.H	Definition of the basepage structure
 */
typedef struct
	{
	char	*p_lowtpa;
	char	*p_hitpa;
	char	*p_tbase;
	long	p_tlen;
	char	*p_dbase;
	long	p_dlen;
	char	*p_bbase;
	long	p_blen;
	char	*p_dta;
	char	*p_parent;
	char	*p_reserved;
	char	*p_env;
	long	p_undefined[20];
	char	p_cmdlin[128];
	}
	BASEPAGE;

[STRTOK.C]
#include <stdio.h>

static	char	*_strtok = NULL;	/* local token pointer */

char *strtok(string, delim)
	register char *string;
	register char *delim;
/*
 *	Return a token from <string>.  If <string> in not NULL, it is
 *	the beginning of a string from which tokens are to be extracted.
 *	Characters found in <delim> are skipped over to find the start
 *	of a token, characters are then accumulated until a character in
 *	<delim> is found, or the terminator of <string> is reached.
 *	A pointer to the '\0' terminated token is then returned.  Note
 *	that this function modifies <string> (by inserting '\0's) in
 *	the process.  Subsequent calls to strtok() may specify NULL as
 *	the <string> argument, in which case subsequent tokens are
 *	returned, or NULL if there are no more tokens.
 */
	{
	register char *p;
	char *strchr();

	if(string == NULL)
		string = _strtok;
	while(*string && strchr(delim, *string))
		++string;
	if(*string == '\0')		/* no more tokens */
		return(NULL);
	p = string;
	while(*string && !strchr(delim, *string))
		++string;
	if(*string != '\0')
		*string++ = '\0';
	_strtok = string;
	return(p);
	}

[BLKCPY.S]
*	char *blkcpy(dest, source, len)
*		register char *dest;
*		register char *source;
*		register int len;
*	/*
*	 *	Copies the <source> block to the <dest>.  <len> bytes are
*	 *	always copied.  No terminator is added to <dest>.  A pointer
*	 *	to <dest> is returned.
*	 */
*		{
*		register char *p = dest;
*	
*		if(source < dest)
*			{
*			dest += len;
*			source += len;
*			while(len--)
*				*--dest = *--source;
*			}
*		else
*			{
*			while(len--)
*				*dest++ = *source++;
*			}
*		return(p);
*		}

.text
.globl _lblkcpy
_lblkcpy:
	move.l	12(a7),d0	; number of bytes
	bra	blkcpy0
.globl _blkcpy
_blkcpy:
	move.w	12(a7),d0	; number of bytes
blkcpy0:
	move.l	4(a7),a1	; destination
	move.l	8(a7),a0	; source
	cmp.l	a0,a1		; check copy direction
	ble	blkcpy4
	add.l	d0,a0		; move pointers to end
	add.l	d0,a1
	bra	blkcpy2
blkcpy1:
	move.b	-(a0),-(a1)	; (s < d) copy loop
blkcpy2:
	dbra	d0,blkcpy1
	bra	blkcpy5
blkcpy3:
	move.b	(a0)+,(a1)+	; (s >= d) copy loop
blkcpy4:
	dbra	d0,blkcpy3
blkcpy5:
	move.l	4(a7),d0	; return destination pointer
	rts

[PUTENV.C]
#include <stdio.h>

extern char	*_envp;

#define	ENVSIZ	2048

static	int	envset = FALSE;		/* local env created? */

int putenv(entry)
	char *entry;
/*
 *	Add <entry> to the environment.  <entry> can be any of the following
 *	forms:
 *		<VARIABLE>
 *		<VARIABLE>=
 *		<VARIABLE>=<value>
 *	The first form removes <VARIABLE> from the environment.  getenv()
 *	will return NULL if looking for this variable.  The second form adds
 *	<VARIABLE> to the environment, with a null value.  getenv() will
 *	return a pointer to a '\0' character if looking for this variable.
 *	Many environment handlers don't support such "tag variables", so
 *	their use is not recommended.  The final form is the most common,
 *	and safest to use.  <VARIABLE> is installed (or replaced) with the
 *	value <value>.  It should be noted that this function itself is not
 *	supported in many systems and should be used will care to prevent
 *	overflowing the space allocated for the environment.
 */
	{
	register char *p, *q, *t, c;
	register int len;
	char *malloc(), *getenv();

	if(!envset)					/* no local env */
		{
		if((p = malloc(ENVSIZ)) == NULL)
			return(FALSE);
		q = _envp;
		_envp = p;
		envset = TRUE;
		if(q)
			{
			while(*q)
				while(*p++ = *q++)
					;
			}
		else
			*p++ = '\0';
		*p++ = '\0';
		*p = 0xFF;
		}
	for(t=entry; (c = *t) && (c != '='); ++t)
		;
	*t = '\0';
	if(p = getenv(entry))				/* remove old var */
		{
		q = p;
		while(*q++)			/* find end of old val */
			;
		p -= (len = strlen(entry));
		while(strncmp(--p, entry, len))	/* find start of old var */
			;
		while(*q)			/* copy environment tail */
			while(*p++ = *q++)
				;
		*p++ = '\0';			/* tie off environment */
		*p = 0xFF;
		}
	if(c == '=')					/* install new var */
		{
		p = _envp;
		while(*p)			/* find end of env */
			while(*p++)
				;
		*t = c;
		q = entry;
		while(*p++ = *q++)		/* copy new entry */
			;
		*p++ = '\0';			/* tie off environment */
		*p = 0xFF;
		}
	return(TRUE);
	}

----------------------------------CUT--HERE---------------------------------

You should also check the operation of your strchr() and strrchr() functions.
If '\0' is specified as the character to search for, these functions should
return a pointer to the '\0' which terminates the string.  This is how the
Un*x libraries (at least the ones I've used) work, and the XARG code uses
strrchr() in this way.

I've included putenv(), but not getenv() since most libraries provide one
already.  If you need getenv(), send me mail and I'll send you a copy of
one that handles MWC-style and TOS-style environment variable, even if they
are intermixed (*ack*).

                Dale Schumacher
                ..ihnp4!meccts!stag!syntel!dal
                (alias: Dalnefre')