/* String manipulation */

#include "params.h"
#include "gambit.h"
#include "struct.h"
#include "os.h"
#include "mem.h"


/*---------------------------------------------------------------------------*/


long string_length( str )
char *str;
{ long len = 0;
  while (*(str++) != '\0') len++;
  return len;
}


char *string_extend( ptr, str )
char *ptr, *str;
{ while (*str != '\0') *(ptr++) = *(str++);
  *ptr = '\0';
  return ptr;
}


char *string_append( str1, str2 )
char *str1, *str2;
{ char *p1;
  if ((str1 == NULL) || (str2 == NULL)) return NULL;
  p1 = local_malloc8( string_length( str1 ) + string_length( str2 ) + 1 );
  if (p1 == NULL) return NULL;
  string_extend( string_extend( p1, str1 ), str2 );
  return p1;
}


char *string_copy( str )
char *str;
{ return string_append( str, "" );
}


long string_compare( str1, str2 )
char *str1, *str2;
{ while ((*str1 != '\0') && (*str2 != '\0'))
    if (*str1 != *str2) break; else { str1++; str2++; }
  if (*str1 < *str2) return -1;
  if (*str1 > *str2) return 1;
  return 0;
}


long string_to_int( str )
char *str;
{ char *p = str;
  long n = 0;
  if ((*p == '-') || (*p == '+')) p++;
  while ((*p >= '0') && (*p <= '9')) n = n*10 - (*p++ - '0');
  if (*p != '\0')
    return 0;
  else if (*str == '-')
    return n;
  else
    return -n;
}


char *string_to_c_str( str )
SCM_obj str;
{ long len = SCM_length( str );
  char *p = local_malloc8( len + 1 );
  if (p == NULL) return NULL;
  p[len] = '\0';
  while (len-- > 0) p[len] = SCM_obj_to_str(str)[len];
  return p;
}


SCM_obj c_str_to_string( str ) /* converts C string to Scheme, without GC */
char *str;
{ SCM_obj result;
  char *p = str;
  long len = 0;
  while (*(p++) != '\0') len++;

  if (alloc_subtyped( len, (long)SCM_subtype_STRING, &result ))
    return SCM_false;

  p = (char *)(result - SCM_type_SUBTYPED + 4);
  while (*str != '\0') *(p++) = *(str++);
  return result;
}


#define hex( c, var ) \
{ if (((c) >= 'a') && ((c) <= 'f')) var = ((c) - 'a') + 10; \
  else if (((c) >= '0') && ((c) <= '9')) var = (c) - '0'; \
  else return NULL; \
}


char *c_id_to_symbol( str )
char *str;
{ char *buf;
  char c;
  long n = 0, i = 0;

  while (str[i] != '\0') if (str[i++] == 'X') n--; else n++;
  if (n<0) return NULL;
  buf = local_malloc8( n + 1 );
  if (buf == NULL) return NULL;

  for (i=0; i<n; i++)
  { c = *(str++);
    switch (c)
    { case 'D': buf[i] = '-'; break;
      case 'B': buf[i] = '!'; break;
      case 'P': buf[i] = '+'; break;
      case 'A': buf[i] = '*'; break;
      case 'S': buf[i] = '/'; break;
      case 'L': buf[i] = '<'; break;
      case 'E': buf[i] = '='; break;
      case 'G': buf[i] = '>'; break;
      case 'Q': buf[i] = '?'; break;
      default:
        if (((c >= 'a') && (c <= 'z')) ||
            ((c >= '0') && (c <= '9')) ||
            (c == '_'))
          buf[i] = c;
        else if (c == 'X')
          { long h1, h2;
            c = *(str++); hex( c, h1 );
            c = *(str++); hex( c, h2 );
            buf[i] = h1*16+h2;
          }
        else
          return NULL;
    }
  }

  buf[n] = '\0';

  return buf;
}


/*---------------------------------------------------------------------------*/
