/* --- CFIG.C
   --- Copyright 1993 Trident Robotics and Research, Inc.
   ---
   --- This file contains all the functions related to the
   --- configuration file utilities.
   ---
   --- CFIG files can contain comments beginning with "#" and
   --- VT_INT, VT_FLOAT, VT_DOUBLE, VT_STRING
   ---
   --- 02/12/97 RMV     If EOF is found at end of file it does
   ---                  not return I_ERROR.
   --- */

#define  CFIG_SRC

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "cfig.h"
#include "vtypes.h"

/* This function initializes the cfig structure and opens the file. */
cfigfile_t *cfigInit(char *file, int flags)
{
  cfigfile_t    *cfig;

  /* allocate the cfigfile structure */

   printf("In cfginit\n");

  cfig = (cfigfile_t *)malloc(sizeof(cfigfile_t));
  if (cfig == NULL)
    return NULL;
          	 
  switch (flags & CFIG_RW) {
    case CFIG_R:
      if ((cfig->fp = fopen(file,"rt")) == NULL){
        printf("%s: File not found \n",file);
        free(cfig);
        return NULL;
      } /* endif */
      break;
    case CFIG_W:
      if ((cfig->fp = fopen(file,"wt")) == NULL){
        printf("Can't open config file \n");
        free(cfig);
        return NULL;
      } /* endif */
      break;
    case CFIG_RW:
      if ((cfig->fp = fopen(file,"rt+")) == NULL){
        printf("Can't find config file \n");
        free(cfig);
        return NULL;
      } /* endif */
      break;
    default:
      printf("Bad file mode \n");
      free(cfig);
      return NULL;
  } /* endswitch */

  /* Copy the filename into the cfig structure and return. */
  strncpy(cfig->filename, file, 127);
  cfig->filename[127] = 0;
  cfig->buffer[0] = 0;
  return cfig;
}

/* This function searches a cfig file for the desginated tag. If the
   tag is not present, an error occurs and the file is closed. */
int cfigCompulsory(cfigfile_t *cfig, char *tag, void *buf, int type, int num)
{
  char  temp[256];
  char  *t;
  int   len, i;

  if ((cfig == NULL) || (cfig->fp == NULL))
    return I_ERROR;

  while (cfig->buffer[0] == 0){
    if (fgets(temp, 256, cfig->fp) == NULL){
      printf("CFIG: Premature end-of-file encountered\n");
      fclose(cfig->fp);
      cfig->fp = NULL;
      free(cfig);
      return I_ERROR;
    } /* endif */
    temp[255] = 0;
    t = temp;
    while (isspace(*t))
      t++;
    if (*t != '#'){
      strcpy(cfig->buffer, t);
    } /* endif */
  } /* endwhile */

  /* Check for the end of the file marker */
  if (strstr(cfig->buffer, "EOF") != NULL){
    fclose(cfig->fp);
    cfig->fp = NULL;
    free(cfig);
    return I_ERROR;
  } /* endif */

  /* Check for the correct tag. If it's not there, close file and return */
  if ((t = strstr(cfig->buffer,tag)) == NULL){
    fclose(cfig->fp);
    cfig->fp = NULL;
    free(cfig);
    return I_ERROR;
  } /* endif */

  /* first skip over the tag then skip over the spaces */
  len = strlen(tag);
  t = &t[len];
  while (isspace(*t))
    t++;
  switch (type) {
    case VT_SHORT:
    case VT_INT:
      for (i=0; i<num; i++){
        if (sscanf(t, "%i", &((int *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_LONG:
      for (i=0; i<num; i++){
        if (sscanf(t, "%i", &((int *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_FLOAT:
      for (i=0; i<num; i++){
        if (sscanf(t, "%f", &((float *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_DOUBLE:
      for (i=0; i<num; i++){
        if (sscanf(t, "%lf", &((double *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_STRING:
      sprintf(temp, "%%%ds", num);
      if (sscanf(t, temp, (char *)buf) != 1){
        printf("Failure reading cfig file\n");
        fclose(cfig->fp);
        cfig->fp = NULL;
        free(cfig);
        return I_ERROR;
      } /* endif */
      break;
    default:
      printf("Unsupported type \n");
  } /* endswitch */
  cfig->buffer[0] = 0;

  /* Now look for the next tag. */
  while (cfig->buffer[0] == 0){
    if (fgets(temp, 256, cfig->fp) == NULL){
      printf("CFIG: Premature end-of-file encountered\n");
      fclose(cfig->fp);
      cfig->fp = NULL;
      free(cfig);
      return I_ERROR;
    } /* endif */
    temp[255] = 0;              /* make sure string in null-terminated */
    t = temp;
    while (isspace(*t))         /* strip off spaces */
      t++;
    if (*t != '#'){             /* check for comment line */
      strcpy(cfig->buffer, t);
    } /* endif */
  } /* endwhile */

  /* Check for the end of the file marker */
  if (strstr(cfig->buffer, "EOF") != NULL){
/*    printf("CFIG: closing the file \n"); */
    fclose(cfig->fp);
    cfig->fp = NULL;
    free(cfig);
    return I_OK;        /* changed from I_ERROR on 2/12/97 */
  } /* endif */

  return I_OK;
}

/* This function is identical to cfigCompulsory() except that if the
   tag is not present, an error occurs but the file is not closed. */
int cfigOptional(cfigfile_t *cfig, char *tag, void *buf, int type, int num)
{
  char  temp[256];
  char  *t;
  int   len, i;

  if ((cfig == NULL) || (cfig->fp == NULL))
    return I_ERROR;

  while (cfig->buffer[0] == 0){
    if (fgets(temp, 256, cfig->fp) == NULL){
      printf("CFIG: Premature end-of-file encountered\n");
      fclose(cfig->fp);
      cfig->fp = NULL;
      free(cfig);
      return I_ERROR;
    } /* endif */
    temp[255] = 0;
    t = temp;
    while (isspace(*t))
      t++;
    if (*t != '#'){
      strcpy(cfig->buffer, t);
    } /* endif */
  } /* endwhile */

  /* Check for the end of the file marker */
  if (strstr(cfig->buffer, "EOF") != NULL){
    fclose(cfig->fp);
    cfig->fp = NULL;
    free(cfig);
    return I_ERROR;
  } /* endif */

  /* Check for the correct tag */
  if ((t = strstr(cfig->buffer,tag)) == NULL)
    return I_ERROR;

  /* first skip over the tag then skip over the spaces */
  len = strlen(tag);
  t = &t[len];
  while (isspace(*t))
    t++;
  switch (type) {
    case VT_SHORT:
    case VT_INT:
      for (i=0; i<num; i++){
        if (sscanf(t, "%i", &((int *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_LONG:
      for (i=0; i<num; i++){
        if (sscanf(t, "%i", &((int *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_FLOAT:
      for (i=0; i<num; i++){
        if (sscanf(t, "%f", &((float *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_DOUBLE:
      for (i=0; i<num; i++){
        if (sscanf(t, "%lf", &((double *)buf)[i]) != 1){
          printf("Failure reading cfig file\n");
          fclose(cfig->fp);
          cfig->fp = NULL;
          free(cfig);
          return I_ERROR;
        } /* endif */
        /* Skip over the scanned field then skip over the spaces */
        while (!isspace(*t))
          t++;
        while (isspace(*t))
          t++;
      } /* endfor */
      break;
    case VT_STRING:
      sprintf(temp, "%%%ds", num);
      if (sscanf(t, temp, (char *)buf) != 1){
        printf("Failure reading cfig file\n");
        fclose(cfig->fp);
        cfig->fp = NULL;
        free(cfig);
        return I_ERROR;
      } /* endif */
      break;
    default:
      printf("Unsupported type \n");
  } /* endswitch */
  cfig->buffer[0] = 0;

  /* Now look for the next tag. */
  while (cfig->buffer[0] == 0){
    if (fgets(temp, 256, cfig->fp) == NULL){
      printf("CFIG: Premature end-of-file encountered\n");
      fclose(cfig->fp);
      cfig->fp = NULL;
      free(cfig);
      return I_ERROR;
    } /* endif */
    temp[255] = 0;              /* make sure string in null-terminated */
    t = temp;
    while (isspace(*t))         /* strip off spaces */
      t++;
    if (*t != '#'){             /* check for comment line */
      strcpy(cfig->buffer, t);
    } /* endif */
  } /* endwhile */

  /* Check for the end of the file marker */
  if (strstr(cfig->buffer, "EOF") != NULL){
/*    printf("CFIG: closing the file \n"); */
    fclose(cfig->fp);
    cfig->fp = NULL;
    free(cfig);
    return I_OK;        /* changed from I_ERROR on 02/12/97 */
  } /* endif */

  return I_OK;
}
