/*  Interface for FORTRAN programs to trigram/un_trigram utilities	*/
/*							Mar 1999	*/
/*  Defines entries trigram_ and un_trigram_.  In Solaris FORTRAN, any-	*/
/*	way, these are called from FORTRAN programs as trigram and	*/
/*	un_trigram							*/
/*  Please be familiar with trigram/un_trigram doc before use of	*/
/*	trigram_/un_trigram_						*/
/*  Arguments (in FORTRAN terms):					*/
/*	1) FORTRAN BYTE array into which result will be stored.  If	*/
/*	   character string is used, be sure it's implemented as an	*/
/*	   array, and not as, say, a VMS character string descriptor	*/
/*	   If there is enough room, the byte after the result will be	*/
/*	   set to 0.  This byte is not included in the count returned	*/
/*	   in the last argument, so if that count = the initial value	*/
/*	   that argument, no 0 has been added				*/
/*	2) FORTRAN BYTE array containing string to be trigrammed/un-	*/
/*	   untrigrammed.  See above re: character strings.  If		*/
/*	   possible, the byte following the last character to be tri-	*/
/*	   grammed/untrigrammed should be a 0.				*/
/*	3) FORTRAN INTEGER containing the number of characters to be	*/
/*	   trigrammed/untrigrammed or 0 if it was possible to include	*/
/*	   a trailing 0 character.  Size of this argument should match	*/
/*	   size of system's default c "int" type.  Presumably, not	*/
/*	   specifying *2, *4, etc, should work; eg, just INTEGER	*/
/*	4) For trigram_ only: FORTRAN BYTE array containing the list of	*/
/*	   characters to be converted to trigrams.  See argument 2 re:	*/
/*	   trailing 0 character						*/
/*	5) For trigram_ only: FORTRAN INTEGER containing length of arg	*/
/*	   4.  Please see arg 3 for description				*/
/*	6) FORTRAN BYTE variable containing the trigram key		*/
/*	7) FORTRAN INTEGER.  At start, contains length of argument 1.	*/
/*	   On return, contains length of string put into argument 1 or	*/
/*	   status information.  See argument 3 for info about size	*/
/*  Function return values:						*/
/*	1	OK							*/
/*	0	Problem from trigram/untrigram, which returned NULL	*/
/*		Argument 1 to these routines are unchanged.		*/
/*		If calling un_trigram_, last argument to these routines	*/
/*		  has more information (see len_result discussion in	*/
/*		  trigram/untrigram; note that un_trigram_ alters 	*/
/*		  len_result so that if it is a displacement, it's rel-	*/
/*		  tive to character 1, not character 0)			*/
/*	-1	Problem in these routines relating to buffer sizes	*/
/*		  1) Initial value of last argument too small.		*/
/*		     If <= 0, no args changed on return.  Otherwise,	*/
/*		     last arg contains size of desired result, and the	*/
/*		     first byte of argument 1 is set to 0		*/
/*		  2) Argument 3 or 5 non-zero, requiring these routines	*/
/*		     to add a trailing 0 to arg 2 or 4.  Attempt to	*/
/*		     allocate memory for this purpose failed.  Argument	*/
/*		     1 unchanged.  Last argument set to -1		*/

char id[] = "trigram_fortran v 1.0  2 Mar 99";
/*   2 Mar 99.  v 1.0.  WJS						*/
/*	[Needs outer_utils v 1.0]					*/
/*	[Begin 1.0]							*/

#include <string.h>
#include <stdlib.h>

char *trigram(),*un_trigram();

char *null_term(s,len_s)
char *s;
int len_s;
{
  char *ptr;
  if (len_s == 0) return s;
  else {
    ptr = (char *) malloc (len_s + 1);
    if (ptr != NULL) {
      strncpy (ptr,s,len_s);
      *(ptr + len_s) = '\0';
    }
    return ptr;
  }
}

int trigram_(result,s,len_s,replacement_list,len_list,trigram_key,len_result)
char *result,*s,*replacement_list,*trigram_key;
int *len_result,*len_list,*len_s;
{
  char *ptr,*input,*list;
  int result_size,retval;

  result_size = *len_result;
  if (result_size <= 0) return -1;
  *len_result = -1;		/*  In case null_term's fail		*/
  input = null_term(s,*len_s);
  if (input == NULL) return -1;
  list = null_term(replacement_list,*len_list);
  if (list == NULL) {
    if (input != s) free (input);
    return -1;
  }

  ptr = trigram(input,list,*trigram_key,len_result);

  if (ptr == NULL) retval = 0;
  else {
    if (*len_result > result_size) {
      *result = '\0';
      retval = -1;
    } else {
      strncpy(result,ptr,*len_result);
      if (*len_result < result_size) *(result + *len_result) = '\0';
      retval = 1;
    }
    free (ptr);
  }

  if (input != s) free (input);
  if (list != replacement_list) free (list);
  return retval;
}


int un_trigram_(result,s,len_s,trigram_key,len_result)
char *result,*s,*trigram_key;
int *len_result,*len_s;
{
  char *ptr,*input;
  int retval,result_size;

  if (  (result_size = *len_result) <= 0  ) return -1;
  if (  (input = null_term(s,*len_s)) == NULL  ) {
    *len_result = -1;
    return -1;
  }

  ptr = un_trigram(input,*trigram_key,len_result);

  if (ptr == NULL) {
    retval = 0;
      /*  For FORTRAN, make displacement relative to char 1		*/
    if (*len_result > 0) (*len_result)++;
  } else {
    if (*len_result > result_size) {
      *result = '\0';
      retval = -1;
    } else {
      strncpy(result,ptr,*len_result);
      if (*len_result < result_size) *(result + *len_result) = '\0';
      retval = 1;
    }
    free (ptr);
  }

  if (input != s) free (input);
  return retval;
}
