/* ***************************************
 * *                                     *
 * *  Support routines for IrisToAdids   *
 * *                                     *
 * ***************************************
 * File: utils/adids/AdidsSubs.C
 *
 *                      COPYRIGHT (c) 2003  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */

/* Note if you are modifying this program, and wish to insert a diagnostic
 * printf, be sure to write it to the error output.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#define INCLUDE_TERMIOS_PROTOTYPES 1

#include "sigtypes.h"
#include "misc_lib.h"
#include "user_lib.h"

#include "SigAdids.h"

static UINT2 ProcessConfigLine
(char *sline_a,
 struct convert_config *pConfig_a );


/* ============================================================
 * Function to load the convert setup from a configuration file.
 */
void LoadSetup
( struct convert_config *pCSetup_a,
  const char* sFile_a,                  /* Filename of config file */
  int iDevice_a )                       /* Device number */
{
  char sPath[PATHNAME_SIZE];
  char sline[81], *sptr;
  FILE* stream;
  SINT4 iline;
  UINT2 lerror;

  /* Initialize the data to the default values */
  memset( pCSetup_a, 0, sizeof(*pCSetup_a) );

  /* Default File logging */
  pCSetup_a->lLogToFile=TRUE;
  pCSetup_a->iOutputFormat=OUTPUT_FILE;
  strcpy(pCSetup_a->SerialSpec.sDevice, "/dev/ttyS0" );
  pCSetup_a->SerialSpec.iBaud = 9600;
  pCSetup_a->SerialSpec.iParity = TTYPARITY_NONE;
  pCSetup_a->SerialSpec.lLockDevice = TRUE;
  pCSetup_a->SerialSpec.lWriteOnly = TRUE;

  /* Generate the file name and open the file */
  sptr = getenv( "IRIS_CONFIG" );
  if (NULL == sptr) 
    {
      sig_signal_va( USER_NO_ENV, 1, "IRIS_CONFIG" );
      exit(EXIT_FAILURE);
    }

  strncpy( sPath, sptr, DIRECTORY_SIZE-1 );
  sPath[DIRECTORY_SIZE-1] = 0;
  strcat( sPath, sFile_a );
  stream = fopen( sPath, "r" );

  /* Don't worry about a missing config file */
  if (NULL == stream) return;

  /* now loop through the file reading and parsing lines */
  iline = 1;
  sptr = fgets( sline, 81, stream );
  while (NULL != sptr)
    {
      lerror = ProcessConfigLine( sptr, pCSetup_a );
      if (lerror) fprintf( stderr, "Syntax error on .conf file line %d\n", iline );
      iline +=1;
      sptr = fgets( sline, 81, stream );
    }

  fclose( stream );

  return;
}

/* ===============================================================
 * Process one line from the configuration file.  Returns nonzero if there
 * is a syntax error.
 *
 * The config can contain the following commands.  All blank lines and
 * lines beginning with "#" are ignored.  Commands can be in any order.
 * Commands take effect in the order received.  For example, syntax errors
 * before the LOG command will not be logged.
 *
 * LOG              <FILE TERM BOTH NONE>
 * PROJECT_NAME     <name>
 * VERBOSE
 */
static UINT2 ProcessConfigLine
(char *sline_a,
 struct convert_config *pConfig_a )
{
  char *stokens[9], *sptr;
  UINT4 icount, ioffset;
  
  ioffset = 0;
  icount  = 0;
  /* Process up to 9 tokens, stop when the line is exhausted. */
  while (icount<9) 
    {
      stokens[icount] = sigtok( sline_a, &ioffset );
      if (NULL == stokens[icount])
	break;
      else
	icount++;
    }
  
  /* Blank lines are allowed and skipped */
  if (icount == 0) return FALSE;
  
  /* Skip commented lines */
  if (stokens[0][0] == '#') return FALSE;
  
  if ( 0 == strcmp( "APPEND_TO_LOG", stokens[0] ) )
    {
      pConfig_a->lAppendToLog=TRUE;
      return FALSE;
    }

  /* See if the line contains the LOG file command */
  if ( 0 == strcmp( "LOG", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      if      ( 0 == strcmp( "BOTH", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "FILE", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=FALSE;}
      else if ( 0 == strcmp( "TERM", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "NONE", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=FALSE;}
      else
	return TRUE;
      return FALSE;
    }

  /* Specify the type of output */
  if ( 0 == strcmp( "OUTPUT", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      if ( 0 == strcmp( "FILE", stokens[1] ) ) 
	pConfig_a->iOutputFormat=OUTPUT_FILE;
      else if ( 0 == strcmp( "SERIAL", stokens[1] ) )
	pConfig_a->iOutputFormat=OUTPUT_SERIAL;
      else
	return TRUE;
      return FALSE;
    }

  /* Read an entry in the site table.
   * Syntax is: PRODUCT <Command Code> <P-Type> <P-Name> */
  if ( 0 == strcmp( "PRODUCT", stokens[0] ) )
    {
      long iValue;
      struct convert_product_table *pOneProduct;
      if ( icount < 5 ) return TRUE;
      if (pConfig_a->iProductCount >= MAX_CONVERT_PRODUCTS) return TRUE;

      pOneProduct = &(pConfig_a->Products[pConfig_a->iProductCount]);
      
      /* Command Code */
      iValue = strtol( stokens[1], &sptr, 10 );
      if (sptr == stokens[1]) return TRUE;
      /* Number is  8-bit value */
      if (iValue < 0 ) return TRUE;
      if (iValue > 63 ) return TRUE;
      pOneProduct->iCommandCode = iValue;
      
      /* Read Site Name */
      strncpy( pOneProduct->sSiteName16, stokens[2], 19 );
      pOneProduct->sSiteName16[19] = 0;

      /* Read product type */
      iValue = iprod_type( stokens[3] );
      if (iValue <= 0 ) return TRUE;
      pOneProduct->iPType = iValue;
      
      /* Read product name */
      strncpy( pOneProduct->sPName, stokens[4], 15 );
      pOneProduct->sPName[15] = 0;
            
      pConfig_a->iProductCount++;
      return FALSE;
    }

  /* Specify the serial baud rate */
  if ( 0 == strcmp( "SERIAL_BAUD", stokens[0] ) )
    {
      long iValue;
      if ( icount < 2 ) return TRUE;

      iValue = strtol( stokens[1], &sptr, 10 );
      if (sptr == stokens[1]) return TRUE;

      if (iValue < 0 ) return TRUE;
      pConfig_a->SerialSpec.iBaud = iValue;
      return FALSE;
    }

  /* Specify the serial device */
  if ( 0 == strcmp( "SERIAL_DEVICE", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      strncpy( pConfig_a->SerialSpec.sDevice, stokens[1], PATHNAME_SIZE-1 );
      pConfig_a->SerialSpec.sDevice[PATHNAME_SIZE-1]=0;
      return FALSE;
    }

  /* Specify the parity */
  if ( 0 == strcmp( "SERIAL_PARITY", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      if ( 0 == strcmp( "NONE", stokens[1] ) ) 
	pConfig_a->SerialSpec.iParity=TTYPARITY_NONE;
      else if ( 0 == strcmp( "ODD", stokens[1] ) )
	pConfig_a->SerialSpec.iParity=TTYPARITY_ODD;
      else if ( 0 == strcmp( "EVEN", stokens[1] ) )
	pConfig_a->SerialSpec.iParity=TTYPARITY_EVEN;
      else
	return TRUE;
      return FALSE;
    }

  if ( 0 == strcmp( "VERBOSE", stokens[0] ) )
    {
      pConfig_a->lVerbose = TRUE;
      return FALSE;
    }

  /* Unrecognized lines will generate a syntax error */
  return TRUE;
}

/* ===========================================
 * Print string to log and terminal, if desired.
 */
void Lprintf
( const struct convert_config *pCSetup_a,
  const char *sString_a )
{
  if (pCSetup_a->lLogToTerm) fputs( sString_a, stderr );
  if (pCSetup_a->lLogToFile)
    {
      fputs( sString_a, pCSetup_a->iLogFile );
      fflush( pCSetup_a->iLogFile );
    }
}

