/************************************************************************/
/* $Id: //tools/src/freeware/gsstest/non_ansi.c#3 $
 ************************************************************************
 *
 * Copyright (c) 1998-2000  SAP AG.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * 4. The name "SAP AG" must not be used to endorse or promote products
 *    derived from this software without prior written permission.
 *    For written permission, please contact www.press@sap.com
 *
 * 5. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * THIS SOFTWARE IS PROVIDED BY SAP AG ``AS IS'' AND ANY EXPRESSED
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. SAP AG SHALL BE LIABLE FOR ANY DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE ONLY IF CAUSED BY SAP AG'S
 * INTENT OR GROSS NEGLIGENCE. IN CASE SAP AG IS LIABLE UNDER THIS
 * AGREEMENT FOR DAMAGES CAUSED BY SAP AG'S GROSS NEGLIGENCE SAP AG
 * FURTHER SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT, AND SHALL NOT BE LIABLE IN EXCESS OF THE AMOUNT OF
 * DAMAGES TYPICALLY FORESEEABLE FOR SAP AG, WHICH SHALL IN NO EVENT
 * EXCEED US$ 500.000.- 
 *
 ************************************************************************/



#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "non_ansi.h"




/*
 * Strcaseicmp()
 *
 * Case independent string compare
 *
 */
int
Strcaseicmp( const char *s1, const char *s2 )
{
   const unsigned char  * us1 = (unsigned char *)s1;
   const unsigned char  * us2 = (unsigned char *)s2;
   int                    lc1 = 0;
   int                    lc2 = 0;

   if ( us1==us2 )
      return(0);

   /* make this call safe against calling with NULL ptrs ... */
   if ( us1==0 ) return(-1);
   if ( us2==0 ) return(1);

   for ( ; lc1==lc2 ; us1++, us2++ ) {
      lc1 = tolower(*us1);
      lc2 = tolower(*us2);

      /* stop the comparison when either there is a difference */
      /* or we hit the end of one (or both) of the strings     */
      if ( lc1 != lc2 || lc1==0 || lc2==0 )
         break;
   }

   return( lc1 - lc2 );

} /* Strcaseicmp() */




/*
 * Strncaseicmp()
 *
 * Case independent string compare with a length limit
 *
 */
int
Strncaseicmp( const char *s1, const char *s2, size_t count )
{
   const unsigned char  * us1 = (unsigned char *)s1;
   const unsigned char  * us2 = (unsigned char *)s2;
   int                    lc1 = 0;
   int                    lc2 = 0;
   size_t		  i;

   if ( us1==us2 )
      return(0);

   /* make this call safe against calling with NULL ptrs ... */
   if ( us1==0 ) return(-1);
   if ( us2==0 ) return(1);

   for ( i=0; i<count && lc1==lc2 ; us1++, us2++, i++ ) {
      lc1 = tolower(*us1);
      lc2 = tolower(*us2);

      /* stop the comparison when either there is a difference */
      /* or we hit the end of one (or both) of the strings     */
      if ( lc1 != lc2 || lc1==0 || lc2==0 )
         break;
   }

   return( lc1 - lc2 );

} /* Strncaseicmp() */




/*
 * Strnlen()
 *
 * strlen with a maximum limit
 *
 */
size_t
Strnlen( const char *s1, size_t count )
{
   size_t       i;

   for( i=0 ; i<count && s1[i]!=0 ; i++ );

   return(i);

} /* Strnlen() */




/*
 * Strmaxcpy()
 *
 * copy a string into a limited buffer, possibly truncating it
 * function returns NULL when truncating source string
 *
 */
char *
Strmaxcpy( char *dest, const char *src, size_t count )
{
   char  * ptr = NULL;

   if ( count!=0 ) {
      if ( src==NULL || count<=1 ) {
	 *dest = '\0';
	 if ( src!=NULL && *src!='\0' ) {
	    ptr = dest;
	 }

      } else {

	 strncpy( dest, src, count );
	 if ( dest[count-1]=='\0' ) {
	    ptr = dest;
	 } else {
	    /* strcpy didn't put a NUL here => source was longer than count */
	    dest[count-1] = '\0';
	 }
      }
   }

   return(ptr);

} /* Strmaxcpy() */




/*
 * Strmaxdup()
 *
 * copy a string into dynamic memory when it's less than the max size
 *
 */
char *
Strmaxdup( char * src, size_t  max_len )
{
   char    * ptr = NULL;
   size_t    len;

   for ( len=0 ; src[len]!='\0'  &&  len<max_len ; len++ );
   if ( src[len]=='\0' ) {
      ptr = malloc( len+1 );
      if ( ptr!=NULL )
	 memcpy( ptr, src, len+1 );
   }

   return(ptr);

} /* Strmaxdup() */




/*
 * Xgetopt()
 *
 *  DESCRIPTION
 *      getopt() returns the next option letter in argv (starting from
 *      argv[1]) that matches a letter in optstring.  argc and argv are the
 *      argument count and argument array as passed to main().  optstring is a
 *      string of recognized option characters; if a character is followed by
 *      a colon, the option takes an argument which may or may not be
 *      separated from it by white space.
 *  
 *      optind is the index of the next element of the argv[] vector to be
 *      processed.  It is initialized to 1 by the system, and getopt() updates
 *      it when it finishes with each element of argv[].
 *  
 *      getopt() returns the next option character from argv that matches a
 *      character in optstring, if there is one that matches.  If the option
 *      takes an argument, getopt() sets the variable optarg to point to the
 *      option-argument as follows:
 *  
 *           +  If the option was the last character in the string pointed to
 *              by an element of argv, then optarg contains the next element
 *              of argv, and optind is incremented by 2.  If the resulting
 *              value of optind is greater than argc, this indicates
 *              a missing option argument, and getopt() returns
 *              an error indication.
 *  
 *           +  Otherwise, optarg points to the string following the option
 *              character in that element of argv, and optind is incremented
 *              by 1.
 *  
 *      If, when getopt() is called, argv[optind] is NULL, or the string
 *      pointed to by argv[optind] either does not begin with the character -
 *      or consists only of the character -, getopt() returns -1 without
 *      changing optind.  If argv[optind] points to the string --, getopt()
 *      returns -1 after incrementing optind.
 *  
 *      If getopt() encounters an option character that is not contained in
 *      optstring, it returns the question-mark (?) character.  If it detects
 *      a missing option argument, it returns the colon character (:) if the
 *      first character of optstring was a colon, or a question-mark character
 *      otherwise.  In either case, getopt() sets the variable optopt to the
 *      option character that caused the error.  If the application has not
 *      set the variable opterr to zero and the first character of optstring
 *      is not a colon, getopt() also prints a diagnostic message to standard
 *      error.
 *  
 *      The special option -- can be used to delimit the end of the options;
 *      -1 is returned, and -- is skipped.
 *  
 *   RETURN VALUE
 *      getopt() returns the next option character specified on the command
 *      line.  A colon (:) is returned if getopt() detects a missing argument
 *      and the first character of optstring was a colon (:).
 *  
 *      A question-mark (?) is returned if getopt() encounters an option
 *      character not in optstring or detects a missing argument and the first
 *      character of optstring was not a colon (:).
 *  
 *      Otherwise, getopt() returns -1 when all command line options have been
 *      parsed.
 *  
 *
 */

int     Xoptind = 1;
int     Xopterr = 0;
int     Xoptopt = 0;

char  * Xoptarg;

static char  * Xlastarg = NULL;
static char  * Xnextopt = NULL;

int
Xgetopt( int    p_argc, char   ** p_argv,  char  * p_options )
{
   char   * opos = 0;
   int      rc   = -1;

   Xoptarg = NULL;
   Xoptopt = 0;

   if ( p_options==NULL ) {
      fprintf(stderr, "getopt(): bad option string!\n");
      goto leave;
   }

   if ( Xoptind>=p_argc || p_argv[Xoptind]==NULL ) {
      /* we already passed the end of the argument list */
      goto leave;
   }

   if ( Xlastarg!=NULL && Xlastarg==p_argv[Xoptind] ) {

	/* continuation from previous adjacent option */
	Xoptopt  = (unsigned char)(*Xnextopt);
	Xnextopt++;

   } else if ( p_argv[Xoptind][0]=='-' && p_argv[Xoptind][1]!='\0' ) {

	/* beginning of a new option argument */
	Xoptopt  = (unsigned char) p_argv[Xoptind][1];
	Xnextopt = &(p_argv[Xoptind][2]);
	Xlastarg = NULL;

	if ( Xoptopt=='-' ) {
	    /* this was an option terminator, terminate getopt() processing */
	    Xoptind++;
	    goto leave;
	}

   }

   if ( Xoptopt==0 ) {
	/* no (more) options found, terminate getopt() processing */
	goto leave;
   }

   /* search option string for current option */

   opos = strchr(p_options, Xoptopt);

   if ( opos==NULL ) {

	/* this option is unknown (not contained in options string ) */
	Xoptind++;
	Xlastarg = NULL;
	rc       = '?';

   } else {

	rc = Xoptopt;

	if ( opos[1]==':' ) {

	    /* this is an option that takes an argument */

	    if ( (*Xnextopt)!='\0' ) {
		Xoptarg  = Xnextopt;
		Xoptind += 1;
	    } else {
		Xoptarg  = p_argv[Xoptind+1];
		Xoptind += 2;
		if ( Xoptind>p_argc ) {
		    rc = (unsigned char)((p_options[0]==':') ? ':' : '?' );
		}
	    }

	    Xlastarg = NULL;

        } else {

	    /* this is a boolean option (no additional argument) */

	    if ( *Xnextopt!='\0' ) {
		/* adjacent options in argument, flag it thru Xlastarg */
		Xlastarg = p_argv[Xoptind];
	    } else {
	        /* no more adjacent options within this argument */
	        Xoptind++;
	        Xlastarg = NULL;
	    }

	}

    }

leave:
    return(rc);

} /* Xgetopt() */

