/****************** Start of $RCSfile$  ****************
*
* $Source$
* $Revision$
* $Date$
* $Author$
* 
*
******* description ***********************************************
*
*  
*
*******************************************************************/

#include <conf.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/stat.h>
#include <math.h>
#include <mvals.h>
#include <fcntl.h>
#include <signal.h>
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#else
# include <termio.h>
#endif
#ifdef	__FreeBSD__
# define O_SYNC O_FSYNC
#endif
#include <utils.h>
#include <x_data.h>
#include <fileutil.h>
#include <sys/types.h>
#include <time.h>

#define	GETOUT	{ goto getout; }
#define	CLEANUP	{ goto cleanup; }

static	char	*compiler_error = "Compiler problems. Call for maintainance\n";

static void
util_fatal(UChar * s)
{
    fprintf(stderr, "\n%s failed !\n", s);
    exit(-1);
}

Int32
FSEEK_SAFE(
    FILE	*fp,
    Int32	start,
    Int32	flag)
{ 
    Int32	val;		/* exit on failed fseek */

    if((val = fseek(fp, start, flag)) != 0)
	util_fatal("fseek");

    return(val);
}

void *
MALLOC_SAFE(Int32 nr)
{
    void	*ret;		/* exit on failed malloc */

    if((ret = (void *) malloc(nr)) == NULL)
	util_fatal("malloc");

    return(ret);
}

void *
REALLOC_SAFE(void * old_ptr, Int32 nr)
{
    void	*ret;		/* exit on failed realloc */

    if((ret = (void *) realloc((void *) old_ptr, nr)) == NULL)
	util_fatal("realloc");

    return(ret);
}

UChar *
STRDUP_SAFE(UChar * str)
{
    UChar	*ret;

    if((ret = strdup(str)) == NULL)
	util_fatal("strdup");

    return(ret);
}

Int32
empty_string(UChar * str)
{
  Int32	i, o;

  o = strlen(str);

  for(i = 0; i < o; i++)
    if(! isspace(str[i]))
      return(0);

  return(1);
}

UChar *
first_nospace(UChar * string)
{
  if(!string){
    errno = EINVAL;
    return(NULL);
  }

  while(isspace(*string) && *string)
    string++;

  return(string);
}

UChar *
first_space(UChar * string)
{
  if(!string){
    errno = EINVAL;
    return(NULL);
  }

  while(!isspace(*string) && *string)
    string++;

  return(string);
}

Int32			/* look, if file "name" exists, */
existfile(UChar * name)		/* make sure, it's no directory */
				/* return 1, if ok, else 0 */
{		
    struct stat	stp;

    if(stat(name, &stp) != 0){
	if(errno == NO_SUCH_FILE)
	    errno = 0;
	return(0);
    }

    if(S_ISDIR(stp.st_mode))
	return(0);

    return(1);
}

FILE *
FOPEN_SAFE(
    UChar	*name,
    UChar	*mode)
{
    FILE	*fp;

    fp = fopen(name, mode);

    if(fp == NULL)
	util_fatal("fopen");

    return(fp);
}

#define	MEMSWAPMAXSIZE	512

Int32
memswap(		/* exchange values of miscallaneous */
  void	*var1,		/* types of variables */
  void	*var2,
  Int32	size)
{
  UChar	*ptr1, *ptr2;
  UChar	memswapspace[MEMSWAPMAXSIZE];
  Int32	i;

  if(size < 0 || !var1 || !var2){
    errno = EINVAL;
    return(-1);
  }

  ptr1 = (UChar *) var1;
  ptr2 = (UChar *) var2;

  while(size > 0){
    i = size > MEMSWAPMAXSIZE ? MEMSWAPMAXSIZE : size;

    memcpy(memswapspace, ptr1, i);
    memcpy(ptr1, ptr2, i);
    memcpy(ptr2, memswapspace, i);
    ptr1 += i;
    ptr2 += i;
    size -= i;
  }

  return(0);
}

UChar *
memfind(UChar * mem1, Int32 len1, UChar * mem2, Int32 len2)
{
  UChar		*cptr1, *eptr, *cptr2, *cptr3;
  Int32	i;

  if(len2 > len1 || len2 == 0)
    return(NULL);

  eptr = mem1 + len1 - len2;
  len2--;
  for(cptr1 = mem1; cptr1 <= eptr; cptr1++){
    if(*cptr1 == *mem2){
      cptr2 = cptr1;
      cptr2++;
      cptr3 = mem2;
      cptr3++;
      for(i = len2; i; i--, cptr2++, cptr3++){
	if(*cptr2 != *cptr3)
	  break;
      }

      if(! i)
	return(cptr1);
    }
  }

  return(NULL);
}

#define	MEMMOVEBUFSIZE	512

void *
mem_move(void * vdest, void * vsrc, size_t n)
{
  UChar		buf[MEMMOVEBUFSIZE], *src, *dest;
  Int32		i;

  if(n < 0 || !vsrc || !vdest){
    errno = EINVAL;
    return(NULL);
  }

  src = (UChar *) vsrc;
  dest = (UChar *) vdest;

  if(dest > src + n || src > dest + n){
    memcpy(dest, src, n);
    return(vdest);
  }

  if(dest > src){
    dest += n;
    src += n;

    while(n > 0){
	i = n > MEMMOVEBUFSIZE ? MEMMOVEBUFSIZE : n;

	src -= i;
	dest -= i;
	n -= i;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
    }
  }
  else{
    while(n > 0){
	i = n > MEMMOVEBUFSIZE ? MEMMOVEBUFSIZE : n;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
	n -= i;

	src += i;
	dest += i;
    }
  }

  return(vdest);
}

void *
mem_move2(void * vdest, void * vsrc, size_t n)
{
  UChar		buf[(MEMMOVEBUFSIZE << 3)], *src, *dest;
  Int32		i;

  if(n < 0 || !vsrc || !vdest){
    errno = EINVAL;
    return(NULL);
  }

  src = (UChar *) vsrc;
  dest = (UChar *) vdest;

  if(dest > src + n || src > dest + n){
    memcpy(dest, src, n);
    return(vdest);
  }

  if(dest > src){
    dest += n;
    src += n;

    while(n > 0){
	i = n > (MEMMOVEBUFSIZE << 3) ? (MEMMOVEBUFSIZE << 3) : n;

	src -= i;
	dest -= i;
	n -= i;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
    }
  }
  else{
    while(n > 0){
	i = n > (MEMMOVEBUFSIZE << 3) ? (MEMMOVEBUFSIZE << 3) : n;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
	n -= i;

	src += i;
	dest += i;
    }
  }

  return(vdest);
}

void *
mem_move3(void * vdest, void * vsrc, size_t n)
{
  UChar		buf[(MEMMOVEBUFSIZE << 6)], *src, *dest;
  Int32		i;

  if(n < 0 || !vsrc || !vdest){
    errno = EINVAL;
    return(NULL);
  }

  src = (UChar *) vsrc;
  dest = (UChar *) vdest;

  if(dest > src + n || src > dest + n){
    memcpy(dest, src, n);
    return(vdest);
  }

  if(dest > src){
    dest += n;
    src += n;

    while(n > 0){
	i = n > (MEMMOVEBUFSIZE << 6) ? (MEMMOVEBUFSIZE << 6) : n;

	src -= i;
	dest -= i;
	n -= i;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
    }
  }
  else{
    while(n > 0){
	i = n > (MEMMOVEBUFSIZE << 6) ? (MEMMOVEBUFSIZE << 6) : n;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
	n -= i;

	src += i;
	dest += i;
    }
  }

  return(vdest);
}

void *
mem_move4(void * vdest, void * vsrc, size_t n)
{
  UChar		buf[(MEMMOVEBUFSIZE << 9)], *src, *dest;
  Int32		i;

  if(n < 0 || !vsrc || !vdest){
    errno = EINVAL;
    return(NULL);
  }

  src = (UChar *) vsrc;
  dest = (UChar *) vdest;

  if(dest > src + n || src > dest + n){
    memcpy(dest, src, n);
    return(vdest);
  }

  if(dest > src){
    dest += n;
    src += n;

    while(n > 0){
	i = n > (MEMMOVEBUFSIZE << 9) ? (MEMMOVEBUFSIZE << 9) : n;

	src -= i;
	dest -= i;
	n -= i;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
    }
  }
  else{
    while(n > 0){
	i = n > (MEMMOVEBUFSIZE << 9) ? (MEMMOVEBUFSIZE << 9) : n;

	memcpy(buf, src, i);
	memcpy(dest, buf, i);
	n -= i;

	src += i;
	dest += i;
    }
  }

  return(vdest);
}

void
repl_esc_seq(UChar * string, UChar escchar)
{
  UChar	*cptr1, *cptr2, c;
  Int32	i, n;

  for(cptr1 = cptr2 = string; *cptr1; cptr1++, cptr2++){
    if(*cptr1 == escchar){
      c = *(++cptr1);

      switch(c){
	case 'n':
	  *cptr2 = '\n';
	  break;
	case 't':
	  *cptr2 = '\t';
	  break;
	case 'a':
	  *cptr2 = '\a';
	  break;
	case 'b':
	  *cptr2 = '\b';
	  break;
	case 'r':
	  *cptr2 = '\r';
	  break;
	case 'f':
	  *cptr2 = '\f';
	  break;
	case 'v':
	  *cptr2 = '\v';
	  break;
	default:
	  if(c >= '0' && c <= '7'){
	    n = 0;
	    for(i = 0; i < 3; i++){
	      c = cptr1[i];
	      if(c < '0' || c > '7')
		break;

	      n = (n << 3) | (c - '0');
	    }

	    cptr1 += i - 1;

	    *cptr2 = (UChar) n;
	  }
	  else{
	    *cptr2 = *cptr1;

	    if(! *cptr2)
	      cptr1--;
	  }
      }
    }
    else{
      *cptr2 = *cptr1;
    }
  }

  *cptr2 = '\0';
}

UChar *
mk_esc_seq(UChar * string, UChar escchar, UChar * ret_string)
{
  UChar	*new_string, *cptr, c, *strptr, r, obuf[5], *endp;
  Int32	len;

  len = strlen(string);
  strptr = string + len;

  if(!ret_string){
    new_string = NEWP(UChar, (len << 2) + 1);
    if(!new_string)
	return(NULL);
  }
  else
    new_string = ret_string;

  endp = cptr = new_string + (len << 2);
  *cptr = '\0';
  for(; len > 0; len--){
    c = *(--strptr);
    if(c == '\"' || c == escchar){
	*(--cptr) = c;
	*(--cptr) = escchar;
    }
    else{
	if(isprint(c) || ((c & 0x80) && (c & 0x60))){
	  *(--cptr) = c;
	}
	else{
	  r = '\0';

	  switch(c){
	   case '\n':
	    r = 'n';
	    break;
	   case '\t':
	    r = 't';
	    break;
	   case '\a':
	    r = 'a';
	    break;
	   case '\b':
	    r = 'b';
	    break;
	   case '\r':
	    r = 'r';
	    break;
	   case '\f':
	    r = 'f';
	    break;
	   case '\v':
	    r = 'v';
	    break;
	  }

	  if(r){
	    *(--cptr) = r;
	    *(--cptr) = escchar;
	  }
	  else{
	    cptr -= 2;
	    sprintf(obuf, "%03o", (int) c);
	    memcpy(--cptr, obuf, 3 * sizeof(UChar));
	    *(--cptr) = escchar;
	  }
	}
    }
  }

  len = endp - cptr;
  memmove(new_string, cptr, ++len);
  if(!ret_string)
    new_string = RENEWP(new_string, UChar, len);

  return(new_string);
}

Int32
memrepl(
  UChar		*buf,
  Int32	buflen,
  UChar		*repl,
  Int32	repllen,
  UChar		*new,
  Int32	newlen)
{
  UChar		*cptr, *cptr2, *cptr3, *eptr, *sptr;

  sptr = buf;
  while( (cptr = memfind(sptr, buflen - (sptr - buf), repl, repllen)) ){
    cptr += repllen;
    if(newlen > repllen){
	cptr2 = buf + buflen - 1;
	cptr3 = cptr2 + newlen - repllen;
	while(cptr2 >= cptr)
	  *(cptr3--) = *(cptr2--);
    }
    if(newlen < repllen){
	cptr3 = cptr;
	cptr2 = cptr3 + newlen - repllen;
	eptr = buf + buflen;
	while(cptr3 < eptr)
	  *(cptr2++) = *(cptr3++);
    }

    memcpy(cptr - repllen, new, newlen * sizeof(UChar));
    buflen += newlen - repllen;
    sptr = cptr - repllen + newlen;
  }

  return(buflen);
}

Int32
fscanword(
   FILE         *fp,
   UChar         *string)
{
   Int32  i = 0;
   UChar 	a;

   do{
        if(fread(&a, sizeof(UChar), 1, fp) < 1){
            fclose(fp);
            return((Int32) EOF);
        }
   } while(isspace(a));
   
   string[0] = a;

   do{
        i++;
        if(fread(&a, sizeof(UChar), 1, fp) < 1){
            fclose(fp);
            return((Int32) EOF);
        }
        string[i] = a;
   } while(!isspace(a));

   string[i] = '\0';

   return(NO_ERROR);
}

Int32
fscanwordq(
   FILE         *fp,
   UChar         *string)
{
   Int32	i = 0, quote = 0;
   UChar 	a = '\0', prev;

   do{
	prev = a;
        if(fread(&a, sizeof(UChar), 1, fp) < 1){
            fclose(fp);
            return((Int32) EOF);
        }
   } while(isspace(a));

   string[0] = a;

   if(a == '\\')
	i--;
   if(a == '\"'){
	quote = 1;
	i--;
   }

   do{
        i++;
	prev = a;
        if(fread(&a, sizeof(UChar), 1, fp) < 1){
            fclose(fp);
	    string[i] = '\0';
            return(NO_ERROR);
        }
	if(a == '\\'){
	    if(prev != a){
		prev = a;
		if(fread(&a, sizeof(UChar), 1, fp) < 1){
		    fclose(fp);
		    string[i] = '\0';
		    return(NO_ERROR);
		}
	    }
	}
	else{
	    do{
		if(a == '\"' && prev != '\\'){
		    prev = a;
		    quote = !quote;
        	    if(fread(&a, sizeof(UChar), 1, fp) < 1){
			fclose(fp);
			string[i] = '\0';
			return(NO_ERROR);
        	    }
		}
	    } while(a == '\"' && prev != '\\');
	}
        string[i] = a;
	if(a == '\\')
	    a = '\0';
   } while(!isspace(a) || quote);

   string[i] = '\0';

   return(NO_ERROR);
}

UChar *
sscanword(
   UChar         *str,
   UChar         *string)
{
   Int32  i = 0, pos = 0;

   while(ISSPACE(str[pos])){
	if(str[pos] == '\0'){
	    string[0] = '\0';
	    return(NULL);
	}
	pos++;
   }

   while(!ISSPACE(str[pos])){
	string[i] = str[pos];
	pos++;
	i++;
   }

   string[i] = '\0';

   return(str + pos);
}

UChar *
sscanwordq(
   UChar         *str,
   UChar         *string)
{
   Int32  i = 0, quote = 0, pos = -1;
   UChar 	a = '\0', prev;

   do{
	prev = a;
	pos++;
        if((a = str[pos]) == '\0'){
	    string[0] = '\0';
            return(NULL);
        }
   } while(isspace(a));

   string[0] = a;

   if(a == '\\')
	i--;
   if(a == '\"'){
	quote = 1;
	i--;
   }

   do{
        i++;
	prev = a;
	pos++;
        if((a = str[pos]) == '\0'){
            string[i] = '\0';
            return(str + pos);
        }
	if(a == '\\'){
	    if(prev != a){
		prev = a;
		pos++;
		if((a = str[pos]) == '\0'){
		    string[i] = '\0';
		    return(str + pos);
		}
	    }
	}
	else{
	    do{
		if(a == '\"' && prev != '\\'){
		    prev = a;
		    quote = !quote;
		    pos++;
        	    if((a = str[pos]) == '\0'){
			string[i] = '\0';
			return(str + pos);
        	    }
		}
	    } while(a == '\"' && prev != '\\');
	}
        string[i] = a;
	if(a == '\\')
	    a = '\0';
   } while(!isspace(a) || quote);

   string[i] = '\0';

   return(str + pos + 1);
}

Int32
fprintwordq(
  FILE	*file,
  UChar	*word)
{
  Int32	i;

  if(! word)
    i = fprintf(file, "\"\"");
  else if(word_count(word) != 1)
    i = fprintf(file, "\"%s\"", word);
  else
    i = fprintf(file, "%s", word);

  return(i);
}

Int32
ffindword(
    FILE	*fp,
    UChar	*string)
{
    UChar	d[200];

    do{
	if(fscanword(fp, d) == EOF)
	    return((Int32) EOF);
    } while(strcmp(d, string) != 0);

    return(NO_ERROR);
}

#ifndef	HAVE_STRRSTR	/* exists in HP-UX (!) */
UChar *
strrstr(UChar * string, UChar * substr)
{
  Int32	len, sublen;
  UChar		*cptr;

  if(!string || !substr)
    return(NULL);

  len = strlen(string);
  sublen = strlen(substr);

  if(len < sublen || len == 0 || sublen == 0)
    return(NULL);

  for(cptr = string + len - sublen; cptr >= string; cptr--)
    if(*cptr == substr[0])
      if(!strncmp(cptr, substr, sublen))
	return(cptr);

  return(NULL);
}
#endif

#ifndef HAVE_STRCASESTR
UChar *
strcasestr(UChar * str1, UChar * str2)
{
  UChar         *result = NULL, *lstr1, *lstr2, *cptr;

  if(!str1 || !str2){
    errno = EINVAL;
    return(NULL);
  }

  lstr1 = strdup(str1);
  lstr2 = strdup(str2);
  if(!lstr1 || !lstr2)
    GETOUT;

  for(cptr = lstr1; *cptr; cptr++)
    *cptr = tolower(*cptr);
  for(cptr = lstr2; *cptr; cptr++)
    *cptr = tolower(*cptr);

  cptr = strstr(lstr1, lstr2);
  if(cptr)
    result = str1 + (cptr - lstr1);

 getout:
  ZFREE(lstr1);
  ZFREE(lstr2);

  return(result);
}
#endif

UChar *
strword(UChar * str, Int32 n)
{
  Int32		numw, l;
  UChar		*cptr;

  if(!str){
    errno = EINVAL;
    return(NULL);
  }

  while(*str && isspace(*str))
    str++;

  numw = word_count(str);
  if(numw < 1)
    return(NULL);

  if(n < 0)
    n += numw;

  if(n < 0 || n >= numw){
    errno = ERANGE;
    return(NULL);
  }

  while(n > 0){
    while(*str && !isspace(*str))
	str++;
    while(*str && isspace(*str))
	str++;
    n--;
  }

  for(cptr = str; *cptr && !isspace(*cptr); cptr++);
  l = cptr - str;

  cptr = NEWP(UChar, l + 1);
  if(cptr){
    strncpy(cptr, str, l);
    cptr[l] = '\0';
  }

  return(cptr);
}

Int32
ffindwordb(FILE *fp, UChar *string) 
{ 
    UChar   c; 
    Int32 word_len; 
    Int32 i; 
 
    if (!fp || !string) 
        return (EINVAL); 
     
    word_len = strlen((char*)string);  
     
    do 
    { 
        /* Erstes gesuchtes Zeichen finden */ 
         
        do 
        { 
            if (fread(&c, sizeof(UChar), 1, fp) < 1) 
                return (Int32)EOF; 
        } 
        while (c != string[0]); 
     
        /* Erstes Zeichen gefunden, stimmt der Rest auch? */ 
     
        for (i = 1; i < word_len && string[i-1] == c; i++) 
        { 
            if (fread(&c, sizeof(UChar), 1, fp) < 1) 
                return (Int32)EOF; 
        } /* for */ 
    } 
    while(i < word_len); 
     
    return(NO_ERROR); 
} 

Int32
ishn(UChar * str)
{
  UChar	c;

  while( (c = *(str++)) ){
    if(!ishnchr(c))
	return(0);
  }

  return(1);
}

Int32
isfqhn(UChar * str)
{
  UChar	c;

  while( (c = *(str++)) ){
    if(!isfqhnchr(c))
	return(0);
  }

  return(1);
}

Int32
minmax(
    Real64	*array,
    Int32	nr,
    Real64	*min,
    Real64	*max)
{
    Int32	i;
    Real64	mini, maxi;

    if(nr <= 0)
	return(-1);


    mini = maxi = *array;

    for(i = 1; i < nr; i++){
	if(*(array + i) > maxi)
	    maxi = *(array + i);
	if(*(array + i) < mini)
	    mini = *(array + i);
    }

    if(min)
	*min = mini;
    if(max)
	*max = maxi;

    return(NO_ERROR);
}

Int32
ffindchr(FILE * fp, UChar c)
{
    UChar	a;

    do{
	if(fread(&a, sizeof(UChar), 1, fp) < 1)
	    return((Int32) EOF);
    } while (c != a);

    return(NO_ERROR);
}

Int32
word_count(UChar * line)
{
    Int32        i = 0, nr = 0;

    for (;;) {
	while (ISSPACE(line[i])) {
	    if (line[i] == '\n' || line[i] == '\0')
		return (nr);
	    i++;
	}
	if (line[i] == '\0')
	    return (nr);

	nr++;
	while (!ISSPACE(line[i]))
	    i++;
    }
}

UChar **
read_asc_file(
  UChar		*filename,
  Int32		*rows)
{
  FILE		*fp;
  Int32		i, num_lines = 0, leng, old_size;
  UChar		*line_buf;
  UChar		**file, **newfile;

  if(!filename)
    filename = "";

  if(filename[0])
    fp = fopen(filename, "r");
  else
    fp = stdin;

  if(!fp)
    return(NULL);

  old_size = sizeof(UChar **);
  file = (UChar **) seg_malloc(old_size);
  if(!file)
    GETOUT;

  file[0] = NULL;

  while(!feof(fp)){
    line_buf = fget_alloc_str(fp);
    if(!line_buf)
	continue;

    leng = strlen(line_buf) - 1;
    if(line_buf[leng] == '\n')
	line_buf[leng] = '\0';
    num_lines++;
    newfile = (UChar **) seg_realloc(file, (num_lines + 1) * sizeof(UChar *),
				old_size);
    if(! newfile)
	GETOUT;
    old_size = (num_lines + 1) * sizeof(UChar *);

    file = newfile;
    file[num_lines - 1] = strdup(line_buf);
    file[num_lines] = NULL;
    free(line_buf);

    if(!file[num_lines - 1])
	GETOUT;
  }

  if(rows)
    *rows = num_lines;

 cleanup:
  if(filename[0])
    fclose(fp);


  return(file);

 getout:
  if(file){
    for(i = 0; file[i]; i++)
	free(file[i]);
    ZFREE(file);
  }

  CLEANUP;
}

void
free_asc_file(
  UChar		**file,
  Int32	rows)
{
  Int32		i;

  for(i = 0; i < rows; i++)
    free(file[i]);
  free(file);
}


static void
__q_sort__(
  void		*p1,
  void		*p2,
  Uns32		size,
  UChar		*array,
  void		*buffer,
  Int32		(*str_cmp_func)(void *, void *)
)
{
  UChar		*ptr1 = (UChar *) p1, *ptr2 = (UChar *) p2;
  Int32		forward = 1;

  if(ptr1 + size < ptr2){
    memcpy(buffer, ptr2, size);

    do{
      if(forward){
	if(str_cmp_func(ptr1, buffer) > 0){
	  memcpy(ptr2, ptr1, size);
	  forward = 0;
	}
      }
      else{
	if(str_cmp_func(ptr2, buffer) < 0){
	  memcpy(ptr1, ptr2, size);
	  forward = 1;
	}
      }
      if(forward)
	ptr1 += size;
      else
	ptr2 -= size;

    }while(ptr1 < ptr2);

    memcpy(ptr1, buffer, size);

    if((UChar *) p1 < ptr1 - size)
      __q_sort__(p1, ptr1 - size, size, array, buffer, str_cmp_func);
    if(ptr1 + size < (UChar *) p2)
      __q_sort__(ptr1 + size, p2, size, array, buffer, str_cmp_func);
  }
  else if(ptr1 + size == ptr2){
    if(str_cmp_func(p1, p2) > 0){
	memcpy(buffer, p1, size);
	memcpy(p1, p2, size);
	memcpy(p2, buffer, size);
    }
  }
}

void q_sort(
  void		*base,
  Uns32		nel,
  Uns32		width,
  Int32		(*comp)(void *, void *))
{
  UChar		*buffer, *array;

  if(nel < 2)
    return;

  array = (UChar *) base;
  buffer = NEWP(UChar, width);

  if(! buffer)
    return;

  nel--;

  if(nel == 1){
    if(comp(array, array + width) > 0){
	memcpy(buffer, array, width);
	memcpy(array, array + width, width);
	memcpy(array + width, buffer, width);
    }
  }
  else
    __q_sort__(array, array + nel * width, width, array, buffer, comp);

  free(buffer);
}

void *b_search(
  void		*key,
  void		*base,
  Uns32		nel,
  Uns32		size,
  Int32	(*comp)(void *, void *))
{
  UChar		*ptr, *eptr;
  Int32	act_idx, i, d, prev, prev_d;

  if(! nel || ! size || ! key || ! base || ! comp)
    return(NULL);

  act_idx = ((nel - 1) >> 1) + 1;
  prev_d = d = ((act_idx - 1) >> 1) + 1;
  prev = 0;
  eptr = ((UChar *) base) + size * (nel - 1);

  i = comp(key, base);
  if(! i)
    return(base);
  if(i < 0)
    return(NULL);
  i = comp(key, eptr);
  if(! i)
    return(eptr);
  if(i > 0)
    return(NULL);

  /*q_sort(base, nel, size, comp);*/

  forever{
    ptr = ((UChar *) base) + (act_idx - 1) * size;

    i = comp(key, ptr);

    if(i == 0)
	return(ptr);

    if(((prev > 0 && i < 0) || (prev < 0 && i > 0)) && prev_d <= 1)
	return(NULL);

    prev = i;

    if(i > 0){
	act_idx += d;
	if(act_idx > nel){
	  if(d == 1)
	    return(NULL);
	  act_idx -= d;
	  d = ((nel - act_idx - 1) >> 1) + 1;
	  act_idx += d;
	  if(act_idx > nel){
	    fprintf(stderr, compiler_error);
	    exit(0);
	  }
	}
    }
    else{
	act_idx -= d;
	if(act_idx < 1){
	  if(d == 1)
	    return(NULL);
	  act_idx += d;
	  d = ((act_idx - 1) >> 1) + 1;
	  act_idx -= d;
	  if(act_idx < 1){
	    fprintf(stderr, compiler_error);
	    exit(0);
	  }
	}
    }

    prev_d = d;
    d = ((d - 1) >> 1) + 1;

    if(!d)
	return(NULL);
  }

  return(NULL);
}

void *l_find(
  void		*key,
  void		*base,
  Uns32	*nelp,
  Uns32	width,
  Int32	(*comp)(void *, void *))
{
  UChar		*ptr, *eptr;

  eptr = ((UChar *) base) + (*nelp * width);

  for(ptr = (UChar *) base; ptr < eptr; ptr += width){
    if(comp(ptr, key) == 0)
	return(ptr);
  }

  return(NULL);
}

void *l_search(
  void		*key,
  void		*base,
  Uns32		*nelp,
  Uns32		width,
  Int32		(*comp)(void *, void *))
{
  UChar		*ptr, *eptr;

  eptr = ((UChar *) base) + (*nelp * width);

  for(ptr = (UChar *) base; ptr < eptr; ptr += width){
    if(comp(ptr, key) == 0)
	return(ptr);
  }

  (*nelp)++;

  base = realloc(base, (*nelp * width));
  eptr = ((UChar *) base) + width * (*nelp - 1);
  memcpy(eptr, key, width);

  return((void *) eptr);
}


#define	GRANULARITY	200

void * seg_malloc(Int32 size)
{
  Int32	new_size;

  if(size <= 0)
    return(NULL);

  new_size = (((size - 1) / GRANULARITY + 1) * GRANULARITY);

  return(malloc(new_size));
}

void * seg_realloc(
  void		*old_ptr,
  Int32	size,
  Int32	old_size)
{
  Int32	new_p, old_p;

  if(size < 0)
    size = 0;
  if(old_size < 0)
    old_size = 0;

  new_p = (((size - 1) / GRANULARITY + 1) * GRANULARITY);
  old_p = (((old_size - 1) / GRANULARITY + 1) * GRANULARITY);

  if(! old_size)
    old_p = 0;
  if(! size)
    new_p = 0;

  if(! new_p)
    return(old_ptr);

  if(new_p == old_p)
    return(old_ptr);
  else if(! old_p && ! old_ptr)
    return(malloc(new_p));
  else
    return(realloc(old_ptr, new_p));
}

Int32 __internal_sm_import(
  void		***memlist,
  Int8		**tmpflags,
  Int32		*num,
  Int8		tmp,
  void		*ptr)
{
  Int32		n;
  void		**newmem;
  Int8		*newflags;

  n = *num;

  if(*num){
    newmem = SRENEWP(*memlist, void *, n + 1, n);
    newflags = SRENEWP(*tmpflags, Int8, n + 1, n);
  }
  else{
    newmem = SNEWP(void *, 1);
    newflags = SNEWP(Int8, 1);
  }

  if(! newmem || !newflags){
    if(newmem)
      free(newmem);
    if(newflags)
      free(newflags);

    return(-1);
  }

  *memlist = newmem;
  *tmpflags = newflags;

  newmem[n] = ptr;
  newflags[n] = (tmp ? 1 : 0);

  (*num)++;

  return(0);
}

void * __internal_sm_malloc(
  void		***memlist,
  Int8		**tmpflags,
  Int32		*num,
  Int8		tmp,
  size_t	size)
{
  void	*newmem;

  newmem = (void *) malloc(size);
  if(!newmem)
    return(NULL);

  if(__internal_sm_import(memlist, tmpflags, num, tmp, newmem)){
    free(newmem);
    return(NULL);
  }

  return(newmem);
}

void
__internal_sm_freeall(
  void		**memlist,
  Int8		*tmpflags,
  Int32		num,
  Int8		tmp)
{
  Int8		*fptr;
  void		**mptr;

  num--;
  for(fptr = tmpflags + num, mptr = memlist + num; num >= 0;
			num--, fptr--, mptr--){
    if((!tmp || *fptr) && *mptr){
	free(*mptr);
    }
  }

  if(memlist)
    free(memlist);
  if(tmpflags)
    free(tmpflags);
}

void
__internal_sm_free(
  void		**memlist,
  Int8		*tmpflags,
  Int32		*num,
  void		*ptr)
{
  void		**mptr;
  Int32		n, i;

  n = *num;

  for(i = 0, mptr = memlist; i < n; i++, mptr++){
    if((void *) ptr == (void *) (*mptr)){
	free(ptr);
	n--;
	memmove(mptr, mptr + 1, (n - i) * sizeof(void *));
	memmove(tmpflags + i, tmpflags + i + 1,
				(n - i) * sizeof(Int8));
	(*num)--;
	return;
    }
  }
}

void *
__internal_sm_realloc(
  void		***memlist,
  Int8		**tmpflags,
  Int32		*num,
  void		*ptr,
  Int8		tmp,
  size_t	size)
{
  void		**mptr, *newptr;
  Int32		n, i;

  n = *num;

  for(i = 0, mptr = *memlist; i < n; i++, mptr++){
    if((void *) ptr == (void *) (*mptr)){
	newptr = (void *) realloc(ptr, size);
	if(!newptr)
	  return(NULL);

	(*memlist)[i] = newptr;
	(*tmpflags)[i] = (tmp ? 1 : 0);
	return(newptr);
    }
  }

  /* pointer not found. Perform malloc */
  newptr = __internal_sm_malloc(memlist, tmpflags, num, tmp, size);
  if(!newptr)
    return(NULL);

  if(ptr){
    memcpy(newptr, ptr, size);
    free(ptr);
  }

  return(newptr);
}

UChar * __internal_sm_strdup(
  void		***memlist,
  Int8		**tmpflags,
  Int32		*num,
  Int8		tmp,
  UChar		*str)
{
  UChar		*newstr;

  newstr = __internal_sm_malloc(memlist, tmpflags, num, tmp,
			strlen(str) + 1);
  if(!newstr)
    return(NULL);

  strcpy(newstr, str);

  return(newstr);
}

UChar * __internal_sm_strapp(
  void		***memlist,
  Int8		**tmpflags,
  Int32		*num,
  Int8		tmp,
  UChar		*str1,
  UChar		*str2)
{
  UChar		*newstr;

  newstr = __internal_sm_malloc(memlist, tmpflags, num, tmp,
			strlen(str1) + strlen(str2) + 1);
  if(!newstr)
    return(NULL);

  strcpy(newstr, str1);
  strcat(newstr, str2);

  return(newstr);
}

UChar * __internal_sm_strchain(
  void		***memlist,
  Int8		**tmpflags,
  Int32		*num,
  Int8		tmp,
  ...)
{
  UChar		*newstr, *next, **cpptr;
  va_list	args;

  newstr = __internal_sm_strdup(memlist, tmpflags, num, tmp, "");
  if(!newstr)
    return(NULL);

  va_start(args, tmp);

  cpptr = (UChar **) (*memlist + *num - 1);
  if(newstr != *cpptr)
    return(NULL);

  while( (next = va_arg(args, UChar *)) ){
    newstr = RENEWP(*cpptr, UChar, strlen(next) + strlen(*cpptr) + 1);
    if(!newstr){
	va_end(args);
	return(NULL);
    }
    *cpptr = newstr;
    strcat(newstr, next);
  }

  va_end(args);

  return(*cpptr);
}

#if 0
UChar *
fget_alloc_str(FILE * fp)
{
  UChar		*str, *ret;
  Int32	len;
  Int16	ende;

  str = (UChar *) seg_malloc(sizeof(UChar));
  if(! str)
    return(NULL);

  *str = '\0';

  len = 1;
  ende = 0;

  while(1){
    str = (UChar *) seg_realloc(str, (len + 1) * sizeof(UChar),
							len * sizeof(UChar));
    if(! str)
	return(NULL);

    if(fread(str + len - 1, sizeof(UChar), 1, fp) < 1){
	if(len == 1){
	  free(str);
	  return(NULL);
	}
	ende = 1;
    }
    if(str[len - 1] == '\n')
	ende = 1;

    if(ende){
	str[len] = '\0';
	ret = strdup(str);
	free(str);
	return(ret);
    }

    len++;
  }
}

#else

#define	PSIZE	GRANULARITY

UChar *
fget_alloc_str(FILE * fp)
{
  UChar		piece[PSIZE];
  UChar		*line, *cptr;
  Int32	newlen, oldlen, plen;

  line = NULL;
  oldlen = 0;

  forever{
    cptr = fgets(piece, PSIZE, fp);
    if(!cptr)
	return(line);

    plen = strlen(piece);

    if(line){
	newlen = strlen(line) + plen + 1;
	line = SRENEWP(line, UChar, newlen, oldlen);
	oldlen = newlen;
    }
    else{
	newlen = oldlen = plen + 1;
	line = SNEWP(UChar, newlen);
	if(line)
	  line[0] = '\0';
    }

    if(!line)
	return(NULL);

    strcat(line, piece);

    if(newlen > 1 && plen > 0)
      if(piece[plen - 1] == '\n' ||
		(line[newlen - 2] != '\n' && plen < PSIZE - 1))
	return(line);
  }
}

#endif

void *ba_search(
  void		*key,
  void		*base,
  Uns32	nel,
  Uns32	size,
  Int32	(*comp)(void *, void *))
{
  UChar		*ptr, *eptr;
  Int32	act_idx, i, d, prev, prev_d;

  if(! key || ! base || ! nel || ! size || ! comp)
    return(NULL);

  act_idx = ((nel - 1) >> 1) + 1;
  prev_d = d = ((act_idx - 1) >> 1) + 1;
  prev = 0;
  eptr = ((UChar *) base) + size * (nel - 1);

  i = comp(key, base);
  if(! i)
    return(base);
  if(i < 0)
    return(NULL);
  i = comp(key, eptr);
  if(i >= 0)
    return(eptr);

  forever{
    ptr = ((UChar *) base) + (act_idx - 1) * size;

    i = comp(key, ptr);

    if(i == 0)
	return(ptr);

    if(((prev > 0 && i < 0) || (prev < 0 && i > 0)) && prev_d <= 1)
	return(i < 0 ? ptr - size : ptr);

    prev = i;

    if(i > 0){
	act_idx += d;
	if(act_idx > nel){
	  if(d == 1)
	    return(ptr);
	  act_idx -= d;
	  i = nel - act_idx - 1;
	  if(i <= 1)
	    return(ptr);
	  d = (i >> 1) + 1;
	  act_idx += d;
	  if(act_idx > nel){
	    fprintf(stderr, compiler_error);
	    exit(0);
	  }
	}
    }
    else{
	act_idx -= d;
	if(act_idx < 1){
	  if(d == 1)
	    return(NULL);
	  act_idx += d;
	  d = ((act_idx - 1) >> 1) + 1;
	  act_idx -= d;
	  if(act_idx < 1){
	    fprintf(stderr, compiler_error);
	    exit(0);
	  }
	}
    }

    prev_d = d;
    d = ((d - 1) >> 1) + 1;

    if(!d)
	return(NULL);
  }

  return(NULL);
}

void
massage_string(UChar * str)
{
  UChar		*c1;

  c1 = str;
  while(isspace(*c1) && *c1)
    c1++;

  if(! *c1){
    *str = '\0';
    return;
  }

  while(*c1)
    *(str++) = *(c1++);

  do{
    *(str--) = '\0';
  } while(isspace(*str));
}

UChar *
strapp(UChar * string1, UChar * string2)
{
  UChar		*newstr;

  newstr = (UChar *) malloc((strlen(string1) + strlen(string2) + 1)
				* sizeof(UChar));

  if(!newstr)
    return(NULL);

  strcpy(newstr, string1);
  strcat(newstr, string2);

  return(newstr);
}

UChar *
strchain(UChar * str, ...)
{
  UChar		*newstr;
  Int32		len;
  va_list	args;

  va_start(args, str);

  if(!str)
    GETOUT;
  str = strdup(str);
  if(!str)
    GETOUT;

  while( (newstr = va_arg(args, UChar *)) ){
    len = strlen(str) + strlen(newstr) + 1;

    str = RENEWP(str, UChar, len);
    if(!str)
	break;

    strcat(str, newstr);
  }

 getout:
  va_end(args);

  return(str);
}

UChar *			/* replace pattern by substitute in string */
repl_substring(UChar * string, UChar * pattern, UChar * substitute)
{
  UChar	*result, *subst, *walking, *newone, *working;

  result = (UChar *) strdup("");
  if(!result)
    return(NULL);
  working = (UChar *) strdup(string);
  if(!working){
    free(result);
    return(NULL);
  }

  walking = working;

  while( (subst = strstr(walking, pattern)) ){
    *subst = '\0';
    newone = strapp(result, walking);
    *subst = pattern[0];

    free(result);

    if(!newone){
	free(working);
	return(NULL);
    }

    result = strapp(newone, substitute);
    free(newone);

    if(!result){
	free(working);
	return(NULL);
    }

    walking = subst + strlen(pattern);
  }

  newone = strapp(result, walking);

  free(result);
  free(working);
  if(! newone)
    return(NULL);

  return(newone);
}

#if	defined(unix) || defined(_AIX)

int
fd_system_fork(char * prnam, int * fds)
{
  int	infd[2], outfd[2], errfd[2], i, flags;
  char	*the_shell, *cptr;

  if(!fds || !prnam){
    errno = EINVAL;
    return(-1);
  }

  if(!(the_shell = getenv("SHELL")))
    the_shell = "sh";

  i = pipe(infd);
  if(i)
    return(-1);
  i = pipe(outfd);
  if(i)
    return(-1);
  i = pipe(errfd);
  if(i)
    return(-1);

  i = fork();
  if(i < 0)
    return(-1);

  cptr = strapp("exec ", prnam);
  if(!cptr)
    return(-1);

  prnam = cptr;

  if(i == 0){			/* child */
    dup2(infd[0], 0);
    dup2(outfd[1], 1);
    dup2(errfd[1], 2);

    close(infd[1]);
    close(outfd[0]);
    close(errfd[0]);

    flags = fcntl(1, F_GETFL);
    fcntl(1, F_SETFL, flags | O_SYNC);
    flags = fcntl(2, F_GETFL);
    fcntl(2, F_SETFL, flags | O_SYNC);

    cptr = FN_LASTDIRDELIM(the_shell);
    execlp(the_shell, (cptr ? cptr + 1 : the_shell), "-c", prnam, NULL);

    fprintf(stderr, "Error: could not start subprocess \"%s\".\n",
			prnam);

    exit(1);
  }

  fds[0] = infd[1];
  fds[1] = outfd[0];
  fds[2] = errfd[0];

  close(infd[0]);
  close(outfd[1]);
  close(errfd[1]);

  free(prnam);

  return(i);
}

int
fp_system_fork(char * pnam, FILE ** fps)
{
  int	fds[3], pid;

  if(!fps || !pnam){
    errno = EINVAL;
    return(-1);
  }

  pid = fd_system_fork(pnam, fds);

  if(pid < 1)
    return(pid);

  fps[0] = fdopen(fds[0], "w");
  fps[1] = fdopen(fds[1], "r");
  fps[2] = fdopen(fds[2], "r");

  if(!fps[0] || !fps[1] || !fps[2]){
    if(fps[0])
	fclose(fps[0]);
    if(fps[1])
	fclose(fps[1]);
    if(fps[2])
	fclose(fps[2]);

    return(-1);
  }

  return(pid);
}

#endif	/* defined(unix) */

Int32
str2words(UChar *** wordsp, UChar * str)
{
  Int32		i, w;
  UChar		**words = NULL, *cptr, *strc = NULL, c;

  if(!wordsp || !str){
    errno = EINVAL;
    return(-1);
  }

  w = word_count(str);
  words = NEWP(UChar *, w + 1);
  memset(words, 0, sizeof(UChar *) * (w + 1));
  strc = strdup(str);

  if(!words || !strc)
    GETOUT;

  cptr = strc;
  for(i = 0; i < w; i++){
    while(isspace(*cptr) && *cptr)
	cptr++;
    if(! *cptr)
	break;

    str = cptr;
    while(!isspace(*cptr) && *cptr)
	cptr++;
    c = *cptr;
    *cptr = '\0';

    words[i] = strdup(str);
    if(!words[i])
	GETOUT;

    *cptr = c;
  }

  free(strc);

  *wordsp = words;
  return(w);

 getout:
  if(strc)
    free(strc);
  if(words){
    for(i = 0; i < w; i++)
	if(words[i])
	  free(words[i]);
    free(words);
  }

  return(-1);
}

Int32
str2wordsq(UChar *** wordsp, UChar * str)
{
  UChar		*buf = NULL, *cptr;
  UChar		**words = NULL, **w;
  Int32		ret = 0, n;

  if(!wordsp || !str){
    errno = EINVAL;
    GETOUT;
  }

  buf = strdup(str);
  if(!buf)
    GETOUT;

  words = NEWP(UChar *, 1);
  if(!words)
    GETOUT;
  *words = NULL;

  cptr = str;
  n = 0;
  while( (cptr = sscanwordq(cptr, buf)) ){
    words = RENEWP(words, UChar *, n + 2);
    if(!words)
	GETOUT;

    words[n + 1] = NULL;
    words[n] = strdup(buf);
    if(!words[n])
	GETOUT;
    n++;
  }
  ret = n;

  *wordsp = words;

 cleanup:
  if(buf)
    free(buf);

  return(ret);

 getout:
  ret = -1;
  if(words){
    for(w = words; *w; w++)
	free(*w);
    free(words);
  }

  CLEANUP;
}

void
sscancchars(UChar * source, UChar * target)
{
  UChar		c, a;
  int		i;

  while(*source){
    if(*source != '\\'){
	*(target++) = *(source++);
	continue;
    }
    else{
	source++;
	switch(*source){
	  case 'a':
	    c = '\a';
	    break;
	  case 'b':
	    c = '\b';
	    break;
	  case 'n':
	    c = '\n';
	    break;
	  case 'f':
	    c = '\f';
	    break;
	  case 'r':
	    c = '\r';
	    break;
	  case 't':
	    c = '\t';
	    break;
	  case 'v':
	    c = '\v';
	    break;
	  default:
	    if(*source >= '0' && *source <= '7'){
		c = 0;
		for(i = 0; i < 3; i++){
		  if(c > 037)
		    break;
		  a = source[i];
		  if(a > '7' || a < '0')
		    break;
		  c = (c << 3) | (a - '0');
		}

		source += i - 1;
	    }
	    else{
		c = *source;
	    }
	}
	source++;
	*(target++) = c;
    }
  }

  *target = '\0';
}

UChar *
sscancstr(UChar * source, UChar * target)
{
  UChar		*str, *cptr, *cptr2, escaped;

  if(*source != '\"'){
    errno = EINVAL;
    return(NULL);
  }
  source++;

  for(cptr = strchr(source, '\"'); cptr; cptr = strchr(cptr + 1, '\"')){
    escaped = 0;
    for(cptr2 = cptr - 1; cptr2 >= source; cptr2--){
      if(*cptr2 == '\\')
	escaped = ! escaped;
      else
	break;
    }

    if(!escaped)
	break;
  }

  if(!cptr){
    errno = EINVAL;
    return(NULL);
  }

  if(! (str = strdup(source)))
    return(NULL);

  str[cptr - source] = '\0';

  sscancchars(str, target);
  free(str);

  return(source + 1);
}

static Int32
_cmd2argv_(char *** argvp, char * cmd, UChar flags)
{
  UChar		**words, *cptr, *cptr2, quoted, fullpath;
  Int32		i, w;

  quoted = flags & 1;
  fullpath = flags & 2;

  w = word_count(cmd);
  if(w < 1){
    errno = EINVAL;
    return(-1);
  }

  if(quoted)
    w = str2wordsq(&(words), (UChar *) cmd);
  else
    w = str2words(&(words), (UChar *) cmd);

  if(w < 0)
    return(w);

  words = (UChar **) realloc(words, sizeof(UChar *) * (w + 2));

  if(!words)
    return(-1);

  words[w + 1] = NULL;
  for(i = w - 1; i >= 0; i--)
    words[i + 1] = words[i];

  if(fullpath)
    words[1] = strdup(words[0]);
  else{
    cptr = FN_LASTDIRDELIM(words[0]);
    if(cptr)
	cptr2 = strdup(cptr + 1);
    else
      cptr2 = strdup(words[1]);

    if(cptr2)
	words[1] = cptr2;
    else{
      if(cptr)
	words[1] = cptr + 1;
    }
  }

  *argvp = (char **) words;

  return(0);
}

Int32
cmd2argv(char *** argvp, char * cmd)
{
  return(_cmd2argv_(argvp, cmd, 0));
}

Int32
cmd2argvq(char *** argvp, char * cmd)
{
  return(_cmd2argv_(argvp, cmd, 1));
}

Int32
cmd2argvf(char *** argvp, char * cmd)
{
  return(_cmd2argv_(argvp, cmd, 2 + 0));
}

Int32
cmd2argvqf(char *** argvp, char * cmd)
{
  return(_cmd2argv_(argvp, cmd, 2 + 1));
}

Int32
sscanXValue(UChar * str, void * tvalue, X_Type type, Int32 * nchars)
{
  double	dbuf;
  long int	ibuf;
  long unsigned ubuf;
  Int32	i, dn;
  int		n;
  UChar		c;

  if(!str)
    return(ILLEGAL_ARGUMENT);

  if(!nchars)
    nchars = &dn;

  switch(type){
    case TypeReal64:
	i = sscanf(str, "%lg%n", &dbuf, &n);
	if(i > 0){
	  *((Real64 *) tvalue) = dbuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeReal32:
	i = sscanf(str, "%lg%n", &dbuf, &n);
	if(i > 0){
	  *((Real32 *) tvalue) = dbuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeInt32:
	i = sscanf(str, "%ld%n", &ibuf, &n);
	if(i > 0){
	  *((Int32 *) tvalue) = ibuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeInt16:
	i = sscanf(str, "%ld%n", &ibuf, &n);
	if(i > 0){
	  *((Int16 *) tvalue) = ibuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeUns32:
	i = sscanf(str, "%lu%n", &ubuf, &n);
	if(i > 0){
	  *((Uns32 *) tvalue) = ubuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeUns16:
	i = sscanf(str, "%lu%n", &ubuf, &n);
	if(i > 0){
	  *((Uns16 *) tvalue) = ubuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeUChar:
	i = sscanf(str, "%c%n", &c, &n);
	if(i > 0){
	  *((UChar *) tvalue) = c;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeSChar:
	i = sscanf(str, "%c%n", &c, &n);
	if(i > 0){
	  *((SChar *) tvalue) = c;
	  *nchars = n;
	}
	return(i);
	break;

    default:
	return(-1);
  }

  return(0);
}

Int32
fscanXValue(FILE * fp, void * tvalue, X_Type type, Int32 * nchars)
{
  double	dbuf;
  long int	ibuf;
  long unsigned ubuf;
  Int32	i, dn;
  int		n;
  UChar		c;

  if(!fp)
    return(ILLEGAL_ARGUMENT);

  if(!nchars)
    nchars = &dn;

  switch(type){
    case TypeReal64:
	i = fscanf(fp, "%lg%n", &dbuf, &n);
	if(i > 0){
	  *((Real64 *) tvalue) = dbuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeReal32:
	i = fscanf(fp, "%lg%n", &dbuf, &n);
	if(i > 0){
	  *((Real32 *) tvalue) = dbuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeInt32:
	i = fscanf(fp, "%ld%n", &ibuf, &n);
	if(i > 0){
	  *((Int32 *) tvalue) = ibuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeInt16:
	i = fscanf(fp, "%ld%n", &ibuf, &n);
	if(i > 0){
	  *((Int16 *) tvalue) = ibuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeUns32:
	i = fscanf(fp, "%lu%n", &ubuf, &n);
	if(i > 0){
	  *((Uns32 *) tvalue) = ubuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeUns16:
	i = fscanf(fp, "%lu%n", &ubuf, &n);
	if(i > 0){
	  *((Uns16 *) tvalue) = ubuf;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeUChar:
	i = fscanf(fp, "%c%n", &c, &n);
	if(i > 0){
	  *((UChar *) tvalue) = c;
	  *nchars = n;
	}
	return(i);
	break;

    case TypeSChar:
	i = fscanf(fp, "%c%n", &c, &n);
	if(i > 0){
	  *((SChar *) tvalue) = c;
	  *nchars = n;
	}
	return(i);
	break;

    default:
	return(-1);
  }

  return(0);
}

/************ end of $RCSfile$ ******************/
