/******************************************************************************
*******************************************************************************

   Site:	Western Michigan University Academic Computer Center

   System:	Directory/File Maintenance
  
   Program:	MAINT

   Version=01	Level=01	08/05/88	Leonard J. Peirce

   Purpose:	General-purpose C subroutines.

   Arguments:	See descriptions for individual routines.

   External variables:	none

   WMU external functions:

          Defined:	banystr,cat,strindex,strins,strmcpy

          Called:

   Files accessed:	none

   Return codes:	See descriptions for individual routines

   Compiling instructions:	$ CC SUBS.C/OPTIMIZE

   Linking instructions:	See linking instructions for MAINT.C

********************************************************************************
*******************************************************************************/

/******************************************************************************/
/*                                                                            */
/*                        # I N C L U D E   F I L E S                         */
/*                                                                            */
/******************************************************************************/

#ifdef unix
#include <stdio.h>			/* to get define for NULL	      */
#include <varargs.h>			/* variable-length argument header    */
#else
#include stdio				/* to get define for NULL	      */
#include varargs			/* variable-length argument header    */
#endif

/******************************************************************************/
/*                                                                            */
/*                             # D E F I N E S                                */
/*                                                                            */
/******************************************************************************/


/******************************************************************************/
/*                                                                            */
/*          S T R U C T U R E S ,   U N I O N S ,   T Y P E D E F S           */
/*                                                                            */
/******************************************************************************/


/******************************************************************************/
/*                                                                            */
/*   E X T E R N A L   D E F I N I T I O N S   &   D E C L A R A T I O N S    */
/*                                                                            */
/******************************************************************************/

	 char	  *cat(),
		  *strmcpy();

	 int	  banystr(),
		  strindex(),
		  strins();

/******************************************************************************/
/*                                                                            */
/*     S T A T I C   D E F I N I T I O N S   &   D E C L A R A T I O N S      */
/*                                                                            */
/******************************************************************************/
/*eject*/
/*******************************************************************************
********************************************************************************

  Function:	banystr

  Purpose:	Determine if a null-terminated character string contains
		any characters from a second null-terminated character
		string.

  Formal parameters:

	Name			Description
	----			-----------
	str1			string that is to be searched
	str2			string containing the characters that are to
				be searched for in str1
  Global variables:

	Name			Examine/Modify/Use/Read/Write
	----			-----------------------------
	none

  Return Codes:

	Code			Reason
	----			------
	>=0			match found; return code is the offset into
				str1 where the character was found
	 -1			no common characters in the two strings

********************************************************************************
*******************************************************************************/

int banystr(str1,str2)
register char	  *str1,
		  *str2;

{	/*** banystr ***/
					/********   LOCAL  VARIABLES   ********/
register int	  offset1,		/* offset into string str1	      */
		  offset2;		/* offset into string str2	      */


   if(str1 == NULL || str2 == NULL)
      return(-1);

   if((*str1 == '\0') || (*str2 == '\0'))
      return(-1);

   offset1 = 0;

   while(*(str1+offset1) != '\0')
   {
      offset2 = 0;
      while(*(str2+offset2) != '\0')
      {
	 if(*(str1+offset1) == *(str2+offset2))
	 {
	    return(offset1);		/* match found; return offset	      */
	 }
	 ++offset2;
      }
      ++offset1;
   }

   return(-1);				/* no match; return -1		      */

}	/*** banystr ***/
/*eject*/
/*******************************************************************************
********************************************************************************

  Function:	cat

  Purpose:	Concatenate a variable number of NUL-terminated strings into
		one output string.

  Description of Linkage:

		char	*rc,
			*cat();

		rc = cat(dest,source1,source2,...sourcen);

  Formal parameters:

	Name			Description
	----			-----------
	dest			pointer to an array where the result will
				be stored
				be searched for in str1
	source1...sourcen	NUL-terminated characters strings that are to
				be concatenated together


  Global variables:

	Name			Examine/Modify/Use/Read/Write
	----			-----------------------------
	none

  Return Codes:

	Code			Reason
	----			------
	retval			pointer to destination string
	nullptr			pointer to NULL string; returned when no
				arguments are passed

********************************************************************************
*******************************************************************************/

char *cat(va_alist)
					/*******   FORMAL  PARAMETERS   *******/
	 va_dcl				/* variable-length parameter list     */

{	/*** cat ***/
					/********   LOCAL  VARIABLES   ********/
register char	  *dest,		/* pointer to destination string      */
		  *source;		/* pointer to current source string   */
	 char	  *retval;		/* to save pointer to destination     */
register int	  count;		/* number of arguments passed	      */
	 va_list  incrmtr;		/* argument list incrementor	      */
static	 char	  *nullptr = "";	/* null string pointer		      */


   va_start(incrmtr);			/* begin everything....		      */

   va_count(count);			/* get number of arguments	      */

   if(count == 0)			/* were any arguments specified?      */
      return(nullptr);			/* nope, get out of here...	      */

   dest = va_arg(incrmtr,char*);	/* get the destination pointer	      */
   retval = dest;			/* save pointer to destination	      */

   source = va_arg(incrmtr,char*);	/* get the first source pointer	      */

   while(--count > 0)			/* process all of the source strings  */
   {
      while(*dest++ = *source++)	/* cat the source to the destination  */
	 ;

      dest--;				/* back over the null character	      */
      source = va_arg(incrmtr,char*);	/* get the next argument	      */
   }

   *dest = '\0';			/* terminate the destination	      */
   va_end(incrmtr);			/* end varargs session		      */

   return(retval);			/* return pointer to destination      */

}	/*** cat ***/
/*eject*/
/*******************************************************************************
********************************************************************************

  Function:	strindex

  Purpose:	Return the offset of one NUL-terminated string in another.

  Formal parameters:

	Name			Description
	----			-----------
	str			string to search
	key			string to search str for

  Global variables:

	Name			Examine/Modify/Use/Read/Write
	----			-----------------------------
	none

  Return Codes:

	Code			Reason
	----			------
	 -1			key not found in str or key is a null
				pointer or str is a null pointer
	offset 			offset into str where key is located

********************************************************************************
*******************************************************************************/

int strindex(str,key)
register char	  *str,
		  *key;

{	/*** strindex ***/
					/********   LOCAL  VARIABLES   ********/
register int	  i,			/* primary pointer to str	      */
		  j,			/* secondary pointer to str for com-  */
					/* parison			      */
		  k;			/* pointer to key for comparison      */


   if(str == NULL || key == NULL || *str == '\0' || *key == '\0')
      return(-1);

   i = 0;
   while(*(str+i) != '\0')
   {
      j = i;
      k = 0;

      /* look for a match */

      while((*(str+j) == *(key+k)) && (*(str+j) != '\0') && (*(key+k) != '\0'))
      {
	 ++j;
	 ++k;
      }

      if(*(key+k) == '\0')
	 return(i);			/* key was found		      */
      else if(*(str+j) == '\0')
	 return(-1);			/* key was not found		      */

      ++i;				/* not sure yet; keep trying...	      */
   }

   /* if we get to here, the key was not found */

   return(-1);

}	/*** strindex ***/
/*eject*/
/*******************************************************************************
********************************************************************************

  Function:	strins

  Purpose:	Insert a character string into another at a specified
		position.

  Formal parameters:

	Name			Description
	----			-----------
	str			string to be updated; should be large
				enough to accomodate the new string
	new			string to be inserted
	position		place to insert new into str

  Global variables:

	Name			Examine/Modify/Use/Read/Write
	----			-----------------------------
	none

  Return Codes:

	Code			Reason
	----			------
	  0 			string insert successful
	 -1			unable to insert string because

********************************************************************************
*******************************************************************************/

int strins(str,new,position)
register char	  *str,
		  *new;
register int	  position;

{	/*** strins ***/
					/********   LOCAL  VARIABLES   ********/
register int	  i,			/* loop and array index		      */
		  j;			/* temporary variable		      */
	 int	  new_len,		/* length of string to insert	      */
		  str_len;		/* length of str		      */


   str_len = strlen(str);		/* get length of current str	      */

   if((position > str_len) || (position < 0))
      i = -1;
   else
   {
      new_len = strlen(new);		/* get length of string to insert     */
      i = new_len + str_len - 1;	/* get where to start when we shift   */
      *(str+i+1) = '\0'; 		/* terminate it first 		      */
      j = str_len - 1;			/* point to last char of str	      */

      /* now shift everything over to make room for the new string */

      while(j >= position)
      {
	 *(str+i) = *(str+j);
	 --i;
	 --j;
      }

      /* now add the new string in the right slot */

      for(i = 0,j = position; *(new+i) != '\0'; i++,j++)
         *(str+j) = *(new+i);      

      i = 0;
   }

   return(i);

}	/*** strins ***/      
/*eject*/
/*******************************************************************************
********************************************************************************

  Function:	strmcpy

  Purpose:	Copy at most max characters from the source string into the
		dest string.  The resultant string is guaranteed to be null-
		terminated.  This provides an alternative to strncpy() which
		does not guarantee that strings are null-terminated.

  Formal parameters:

	Name			Description
	----			-----------
	dest			pointer to destination string
	source			pointer to source string
	max			maximum number of characters to be
				copied

  Global variables:

	Name			Examine/Modify/Use/Read/Write
	----			-----------------------------
	none

  Return Codes:

	Code			Reason
	----			------
	dest			pointer to destination string

********************************************************************************
*******************************************************************************/

char *strmcpy(dest,source,max)
register char	  *dest,
		  *source;
register int	  max;

{	/*** strmcpy ***/
					/********   LOCAL  VARIABLES   ********/
register int	  i;			/* loop and array index		      */


   for(i = 0;i < max && *(source+i); i++)
      *(dest+i) = *(source+i);

   *(dest+i) = '\0';			/* terminate the destination string   */

   return(dest);

}	/*** strmcpy ***/
