/************************************************************************
 *									*
 *			Copyright (c) 1982, Fred Fish			*
 *			    All Rights Reserved				*
 *									*
 *	This software and/or documentation is released for public	*
 *	distribution for personal, non-commercial use only.		*
 *	Limited rights to use, modify, and redistribute are hereby	*
 *	granted for non-commercial purposes, provided that all		*
 *	copyright notices remain intact and all changes are clearly	*
 *	documented.  The author makes no warranty of any kind with	*
 *	respect to this product and explicitly disclaims any implied	*
 *	warranties of merchantability or fitness for any particular	*
 *	purpose.							*
 *									*
 ************************************************************************
 */


/*
 *  FILE
 *
 *	dex2.c   utility routines for DEX modules
 *
 *  KEY WORDS
 *
 *	dex files
 *	utility routines
 *
 *  DESCRIPTION
 *
 *	Contains miscellaneous utility routines which will
 *	eventually show up the the author's "ce" (C Environment)
 *	library, which supplements the stdio library.
 *
 *  FUNCTIONS
 *
 *	nextw     return pointer to next word in a string
 *	skpnbt    skip non-blanks and non-tabs
 *	skpbt     skip blanks and tabs
 *	xfield    extract next field from string
 *	index     find first occurrence of character
 *	rindex    find last occurrence of character
 *
 *  AUTHOR
 *
 *	Fred Fish
 *
 */

#include <stdio.h>

/*
 *  FUNCTION
 *
 *	NEXTW	return pointer to next word in a string
 *
 *  KEY WORDS
 *
 *	string functions
 *	words
 *	nextw
 *	string pointers
 *
 *  SYNOPSIS
 *
 *	char *nextw(buffer)
 *	char *buffer;
 *
 *  DESCRIPTION
 *
 *	Nextw searches from the current pointer location for the
 *	next occurrence of <tab or space><non-tab and non-space>
 *	which is taken to be the start of a new word.  If found,
 *	a pointer to the <non-tab and non-space> character is
 *	returned. If the end of the string is found, a pointer to it
 *	is returned.
 *
 *  RETURNS
 *
 *	Returns pointer to next word in buffer, if one is found.
 *	Returns pointer to terminating null if no word found.
 *
 *  BUGS
 *
 *	"Words" are taken to be anything which is neither tab nor
 *	blank.  It might be hard to pronounce some of them.
 *	Also note that control characters (ie newline) preceded
 *	by tabs or blanks are also considered to be words.
 *
 */

/*
 *  PSEUDO CODE
 *
 *	 Begin nextw
 *	    Skip over any non-tabs and non-blanks.
 *	    Skip over any tabs or blanks.
 *	    Return resulting pointer to first char of word.
 *	 End nextw
 *				
 */

char *nextw(buffer)
char *buffer;
{
    char *skpbt(), *skpnbt();

    buffer = skpnbt(buffer);
    buffer = skpbt(buffer);
    return (buffer);
}

/*
 *  FUNCTION
 *
 *	skpnbt   return pointer to next tab or blank character
 *
 *  KEY WORDS
 *
 *	string functions
 *	words
 *	skpnbt
 *	string pointers
 *
 *  SYNOPSIS
 *
 *	char *skpnbt(buffer)
 *	char *buffer;
 *
 *  DESCRIPTION
 *
 *	Starting at the current pointer, as long as a NULL is
 *	not encountered, skpnbt skips over anything which is not
 *	a blank or tab, returning a pointer to the first blank
 *	or tab found.  If the end of the string is found first,
 *	a pointer to it is returned.
 *
 *  RETURNS
 *
 *	Returns pointer to next blank or tab character.
 *
 */

/*
 *  PSEUDO CODE
 *
 *	Begin skpnbt
 *	    If passed point is not NULL then   
 *	        While the current char is not a tab, blank, or null
 *		    Skip to next character.
 *	        End while
 *	    End if
 *	    Return pointer to the character found.
 *	End skpnbt
 *				
 */

char *skpnbt(buffer)
char *buffer;
{
    if (buffer != NULL) {
        while (*buffer != '\t' && *buffer != ' ' && *buffer != '\n') {
	    buffer++;
	}
    }
    return (buffer);
}

/*
 *  FUNCTION
 *
 *	skpbt	return pointer to next non-tab non-blank character
 *
 *  KEY WORDS
 *
 *	string functions
 *	words
 *	skpbt
 *	string pointers
 *
 *  SYNOPSIS
 *
 *	char *skpbt(buffer)
 *	char *buffer;
 *
 *  DESCRIPTION
 *
 *	Starting at the current pointer, skpbt skips over blanks
 *	and tabs, returning pointer to the first non-tab non-blank
 *	character found (which may be current).
 *
 *  RETURNS
 *
 *	Returns pointer to next non-tab and non-blank character.
 *
 */

/*
 *  PSEUDO CODE
 *
 *	Begin skpbt
 *	    If pointer is not NULL then
 *	        While the current character is a tab or blank
 *		    Skip to next character.
 *	        End while
 *	    End if
 *	    Return pointer to the character found.
 *	End skpbt
 *				
 */

char *skpbt(buffer)
char *buffer;
{
    if (buffer != NULL) {
        while (*buffer == '\t' || *buffer == ' ') {
	    buffer++;
	}
    }
    return (buffer);
}

/*
 *  FUNCTION
 *
 *	xfield   extract a field from string
 *
 *  SYNOPSIS
 *
 *	char *xfield(out,in)
 *	char *out;
 *	char *in;
 *
 *  DESCRIPTION
 *
 *	Extracts field from a string up to next tab, blank,
 *	newline, or NULL character.
 *
 *	If the field begins with a double quote then only another
 *	double quote or a NULL will terminate the extraction.
 *
 *  RETURNS
 *
 *	Returns pointer to next character not transfered, or "in"
 *	if no characters are transfered.
 *
 */

/*
 *  PSEUDO CODE
 *
 *	Begin xfield
 *	    If both pointers are ok then
 *		If the field is quoted then
 *		    Discard the leading quote.
 *		    While end is not found
 *			Transfer characters.
 *		    End while
 *		    If terminating character is quote
 *			Discard the terminating quote.
 *		    End if
 *		    Terminate output string properly.
 *		Else
 *		    While end is not found
 *			Transfer characters.
 *		    End while
 *		    Terminate output string properly.
 *		End if
 *	    End if
 *	    Return pointer to next input character.
 *	End xfield
 *
 */

char *xfield(out,in)
char *out;
char *in;
{
    if (out != NULL && in != NULL) {
	if (*in == '"') {
	    in++;
	    while (*in != '"' && *in != NULL) {
		*out++ = *in++;
	    } 
	    if (*in == '"') {
		in++;
	    }
	    *out = NULL;
	} else {
	    while(*in != ' ' && *in != '\t' && *in != NULL && *in != '\n') {
	        *out++ = *in++;
	    }
	    *out = NULL;
	}
    }
    return(in);
}

/*
 *  FUNCTION
 *
 *	index   return pointer to occurrence of a character
 *
 *  KEY WORDS
 *
 *	index
 *	character functions
 *
 *  SYNOPSIS
 *
 *	char *index(s,c)
 *	char *s;
 *	char c;
 *
 *  DESCRIPTION
 *
 *	Find first occurrence of a the specified character in
 *	the specified string.
 *
 *  RETURNS
 *
 *	Pointer to character if found.
 *	NULL if no occurrence found.
 *
 */

/*
 *  PSEUDO CODE
 *
 *	Begin index
 *	    If string pointer valid then
 *	        Scan for character or end of string.
 *	        If end of string found then
 *		    Return NULL.
 *	        Else
 *		    Return pointer.
 *	        End if
 *	    Else
 *		Return NULL.
 *	    End if
 *	End index
 *
 */

char *index(s,c)
char *s;
char c;
{
    if (s != NULL) {
	while (*s != NULL && *s != c) {s++;}
	if (*s == NULL) {
	    return(NULL);
	} else {
	    return(s);
	}
    } else {
	return(NULL);
    }
}

/*
 *  FUNCTION
 *
 *	rindex   return pointer to last occurrence of a character
 *
 *  KEY WORDS
 *
 *	string functions
 *	rindex
 *
 *  SYNOPSIS
 *
 *	char *rindex(s,c)
 *	string *s;
 *	char c;
 *
 *  DESCRIPTION
 *
 *	Find the last occurrence of the specified character in
 *	the specified string.
 *
 *  RETURNS
 *
 *	Pointer to last occurrence if character found.
 *	NULL if character not found.
 *
 */

/*
 *  PSEUDO CODE
 *
 *	Begin rindex
 *	    Initialize return value to NULL.
 *	    If string pointer is not invalid then
 *		For each character in string
 *		    If character matches then
 *			Save pointer.
 *		    End if
 *		End for
 *	    End if
 *	    Return pointer.
 *	End rindex
 *
 */

char *rindex(s,c)
char *s;
char c;
{
    char *rtn;

    rtn = NULL;
    if (s != NULL) {
	for ( ; *s != NULL; *s++) {
	    if (*s == c) {
		rtn = s;
	    }
	}
    }
    return(rtn);
}
