#ifndef lint
static char *RCSid = "$Header: /auto/home/flipper/anders/flipper/prosj/rexx/src/RCS/strings.c,v 1.3 1993/05/07 21:23:58 anders Exp anders $";
#endif

/*
 *  The Regina Rexx Interpreter
 *  Copyright (C) 1992-1994  Anders Christensen <anders@pvv.unit.no>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "rexx.h"
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <assert.h>

#if !defined(MIN)
# define MIN(a,b) (((a)>(b))?(b):(a))
#endif


streng *Str_ndup( streng *name, int length )
{
   streng *ptr=NULL ;
   
   assert( Str_len(name) >= length) ;
#if !defined(FLISTS) || defined(TRACEMEM)
   ptr = Str_make( length ) ;
#else
   ptr = get_a_streng(length) ;
#endif
   ptr->len = length ;

   memcpy( ptr->value, name->value, length ) ;
   return ptr ;
}

streng *Str_nodup( streng *name, int offset, int length )
{
   streng *ptr=NULL ;

   assert( Str_len(name) >= (offset+length) ) ;
#if !defined(FLISTS) || defined(TRACEMEM)
   ptr = Str_make( length ) ;
#else
   ptr = get_a_streng( length ) ;
#endif
   memcpy( ptr->value, name->value+offset, length ) ;
   ptr->len = length ;
   return ptr ;
}

streng *Str_dup( streng *input ) 
{
   streng *output=NULL ;

#if !defined(FLISTS) || defined(TRACEMEM)
   output = Str_make( input->len +1 ) ;
#else
   output = get_a_streng(input->len) ;
#endif
   output->len = input->len ;
   memcpy( output->value, input->value, input->len ) ;
   
   return output ;
}


streng* Str_ncpy( streng *to, streng *from, int length )
{
   streng *new=NULL ;

   assert( Str_len(from) >= length ) ;
   if ((new=to)->max<(to->len + length))
   {
      new = Str_make( to->len + length ) ;
      memcpy(new->value, to->value, to->len) ;
      new->len = to->len ;
  /*      Free( to ) ; */
   }

   length = (length>Str_len(from)) ? Str_len(from) : length  ;
   memcpy(new->value, from->value, length ) ;
   new->len += length ;

   return new ;
}
               


streng *Str_ncre( char *from, int length )
{
   streng *result=NULL ;

   assert( length >= 0 ) ;

   result = Str_make( length ) ;
   memcpy( result->value, from, length ) ;

   result->len = length ;
   return result ;
}
   
      

int Str_ncmp( streng *first, streng *second, int limit ) 
{
   int i=0, rlim=0 ;

   rlim = MIN( limit, MIN( first->len, second->len ) ) ;
   for (i=0 ; i<rlim; i++) 
      if (first->value[i] != second->value[i])
	return (first->value[i] - second->value[i]) ;

   if (rlim<limit)
      return (first->len != second->len ) ;
   
   return (0) ;
}



streng *Str_cre( char *input )
{
   streng *result=NULL ;
   char *ptr=NULL ;
      
   for (ptr=input; *ptr; ptr++ ) ;
   result = Str_make( ptr-input ) ;

   memcpy( result->value, input, result->len=(ptr-input) ) ;
   return result ;
}


#if !defined(FLISTS) || defined(TRACEMEM)
streng *Str_make( int size ) 
{
   streng *result=NULL ;

   result = Malloc( size + STRHEAD ) ;
   result->max = size ;
   result->len = 0 ;

   return result ;
}
#endif


static streng *assure( streng *str, int length )
{
   streng *ptr=NULL ;

   if (length > (ptr=str)->max)
   {
      ptr = Str_make( length ) ;
      ptr = Str_cat( ptr, str ) ;
/*      Free_string( str ) ; */
   }
   return ptr ;
}
   


streng *Str_catstr( streng *base, char *append )
{
   streng *ptr=NULL ;
   int tmp=0 ;
 
   ptr = assure( base, (tmp=strlen(append)) + base->len ) ;
   memcpy( &ptr->value[ptr->len], append, tmp ) ;
   ptr->len += tmp ;
   return ptr ;
}



streng *Str_nocat( streng *first, streng *second, int length, int offset )
{
   streng *ptr=NULL ;
   int tmp=0 ;
 
   assert( second->len + 1 >= offset + length ) ;

   tmp = second->len - offset ;
   if (tmp<0 || tmp>length) 
      tmp = length ;

   ptr = assure( first, first->len + tmp);
   memcpy( &first->value[first->len], &second->value[offset], tmp ) ;
   
   ptr->len += tmp ;
   return ptr ;
}



streng *Str_cat( streng *first, streng *second ) 
{
   streng *ptr=NULL ;
   int tmp=0 ;

   ptr = assure( first, (tmp=Str_len(first)+Str_len(second)) ) ;
   memcpy( &first->value[Str_len(first)], second->value, Str_len(second) ) ;
   ptr->len = tmp ;

   return ptr ;
}



streng *Str_ncat( streng *first, streng *second, int length ) 
{
   streng *ptr=NULL ;
   int tmp=0 ;

   ptr = assure( first, Str_len(first) + (tmp=MIN(length,Str_len(second))) ) ;
   memcpy( &first->value[Str_len(first)], second->value, tmp ) ;

   ptr->len += tmp ;
   return ptr ;
}



int Str_cmp( streng *first, streng *second )
{
   register int lim=0 ;

   lim = first->len ;
   if (lim != second->len)
      return 1 ;

   return memcmp( first->value, second->value, lim ) ;
}



int Str_ccmp( streng *first, streng *second )
{
   int tmp=0 ;

   if (Str_len(first) != Str_len(second))
      return 1 ;

   for (tmp=0; tmp<Str_len(first); tmp++ )
      if (RXTOLOW(first->value[tmp]) != RXTOLOW(second->value[tmp]))
         return 1 ;

   return 0 ;
}


int Str_cncmp( streng *first, streng *second, int length )
{
   int tmp=0, top=0, shorter=0 ;

   shorter = MIN( Str_len(first), Str_len(second) ) ;
   if ( ( shorter<length) && (Str_len(first) != Str_len(second)) )
      return 1 ;

   top = MIN( shorter, length ) ;
   for (tmp=0; tmp<top; tmp++ )
      if (RXTOLOW(first->value[tmp]) != RXTOLOW(second->value[tmp]))
         return 1 ;

   return 0 ;
}


int Str_cnocmp( streng *first, streng *second, int length, int offset )
{
   int tmp=0, top=0, shorter=0 ;

   shorter = MIN( Str_len(first), Str_len(second)-offset ) ;
   if ( ( shorter<length) && (Str_len(first) != Str_len(second)-offset) )
      return 1 ;

   top = MIN( shorter, length ) ;
   for (tmp=0; tmp<top; tmp++ )
      if (RXTOLOW(first->value[tmp]) != RXTOLOW(second->value[offset+tmp]))
         return 1 ;

   return 0 ;
}


streng *Str_ify( streng *input ) 
{
   streng *ptr=NULL ;

   ptr = assure( input, Str_len(input) + 1 ) ;
   ptr->value[ptr->len] = 0x00 ;
   return ptr ;
}
      

streng *Str_ncatstr( streng *base, char *input, int length )
{
   streng *ptr=NULL ;
   int top=0 ;

   top = MIN( strlen(input), length ) ;
   ptr = assure( base, Str_len(base) + top ) ;
   memcpy( &ptr->value[Str_len(ptr)], input, top ) ;
   ptr->len += top ;
   return ptr ;
}
   

streng *Str_upper( streng *input )
{
   int i=0;

   for (i=0;i<input->len;i++)
     {
      if (islower(*(input->value+i)))
         *(input->value+i) = toupper(*(input->value+i));
     }
   return input ;
}

streng *Str_strp( streng *input , char chr, char opt)
{
   register int i=0,j=0;

   if (input->len == 0)
      return(input);

   if (opt & STRIP_TRAILING)
   {
      for (i=(input->len)-1;i>-1;i--)
      {
         if (input->value[i] != chr)
            break;
      }
      input->len = i + 1;
   }
   if (opt & STRIP_LEADING)
   {
      for (j=0;j<input->len;j++)
         if (input->value[j] != chr)
            break;
      for (i=0;j<input->len;i++,j++)
         input->value[i] = input->value[j];
      input->len = i;
   }
 return(input);
}

char *str_trans(char *str,char oldch,char newch)
/*
 * Function  : Translate all occurrences of oldch to newch in str
 * Parameters: *str     - string to be amended
 *             oldch    - character to be replaced
 *             newch    - character to replace oldch
 * Return    : same string but with characters translated
 */
{
   register int len=0;
   register int  i=0;

   len = strlen(str);
   for (i=0;i<strlen(str); i++)
   {
      if (*(str+i) == oldch)
         *(str+i) = newch;
   }
   return(str);
}

