/* function.c
 *          *
 *        Emilio            4/13/2001
 *          In SetModelParameters(), enlarged the size of the szLine char array
 *          to be able to read longer lines from config file. Changed several
 *          instances of the use of FILENAMELEN for the length of string arrays,
 *          to LINELEN (longer). Added support for a mix of float and string
 *          global parameters in SetModelParameters(). Changed GlobalCleanUp()
 *          to free this memory. Did other minor fixes and cleanups.
 *          *
 * Function file for all the C programs written to analyze binary and NetCDF
 * input and output for modelling using the Environmental Modeling Utilities,
 * or "EMU" package.
 ******************************************************************************/

#include "emu.h"

#define  SYSCFGFILE   "./system.cfg"

/* EXTERNAL VARIABLE defined in main application program file */
extern const char * cpszUsage;


BOOL bSelectedConfigFileName;
BOOL bNamedVariables;
char * pszProgramName;
char * pszConfigFile, * pszSystemConfigFile;
char * pszCDLFile;       /* is this functionality/variable actually used anymore ??? */


extern void ReadMask(void);

/* LOCAL FUNCTIONS: Important "system" functions*/
BOOL  ProcessDefaultCommandLineArgs(int * pArgc, char * argv[]);
void  Usage(const char * cpszUsage);
void  ReadSystemConfigFile(void);
void  SetModelParameters(void);
void  ReadConfigVariables(void);
short ProcessNetcdfVariable(int v, VAR *tmpVars);
void  VariableCleanUp(void);

void ReplaceAlias(VAR * pstVar, int nFlag);
void ReplaceDynAlias(char * pszDest, char * pszAlias, float fData, emu_type EmuType);
BOOL GetFileName(VAR * pVar, char * pszDest);
int  SplitString(char * pszSrc, char * pszFirst, char cSep1, char * pszMid,
                char cSep2, char * pszLastName);
void ParseFileList(char * pszLine, DYNFILE * pstDyn);
int  ExtractFileElements(char * pszSeg, DYNFILE * pstDyn);

/* LOCAL FUNCTIONS: "utilities" used to support the above functions */
int getVarLine(FILE *fpin, char *pszLine);
int GetLine(FILE * fpin, char * pszLine, char * pszMarker, BOOL bFromStart);
int ReadConfigLine(char * pszLine, char * pszMarker);
int GetTimeType(char *pszTimeType);
dataorg_type  GetDataOrgType(char * pszDataOrgType);
emu_type      GetEmuType(char * pszDataType);
BOOL          IsValidFileType(char *pszLineElement);



/* ================================================================= */
/* Call the necessary functions to read input files, settings, mask, etc. */

void Initialize(int * argc, char * argv[], short option)
{
  if (!ProcessDefaultCommandLineArgs(argc, argv))
    ExitError("Could not process default command-line arguments %s \n", "uff");

  /* print out date and time */
  if (!bQuiet)
  {
    printf("\n ============ BEGINNING OF PROGRAM ============= \n");
    PrintTime();
    printf(" ================================================= \n");
  }

  ReadSystemConfigFile();
  ProcessCommandLineArgs(argc, argv);
  SetModelParameters();

  if (option == NOMASK)
    bNoMask = TRUE;
  else if (option == DOMASK || bNoMask == FALSE)
  {
    bNoMask = FALSE;
    ReadMask();
  }

  ReadConfigVariables();
}

/* ================================================================= */
short GetVarNo(char *varname)
{
  short v=0;

  while (v < nVars)
    if (istype(pstVars[v].name, varname))
      return(v);
    else
      v++;

 /* WHAT HAPPENS IF THERE IS NO SUCH VARNAME ??! */
  return(0);
}

/* ================================================================= */
/* Copy all the elements of a VAR variable to another VAR variable   *
 * for value and string arrays, allocate memory and then copy        */

void CopyVar(VAR *varto, VAR *varfrom)
{
  int i, j;

  strcpy(varto->name, varfrom->name);
  strcpy(varto->filetype, varfrom->filetype);
  strcpy(varto->path, varfrom->path);
  strcpy(varto->param, varfrom->param);
  varto->bIsMetaData  = varfrom->bIsMetaData;
  varto->nCols        = varfrom->nCols;
  varto->nRows        = varfrom->nRows;
  strcpy(varto->YDir, varfrom->YDir);
  varto->tTimeType    = varfrom->tTimeType;
  varto->t1           = varfrom->t1;
  strcpy(varto->szUnit, varfrom->szUnit);
  varto->YearOrigin   = varfrom->YearOrigin;
  varto->tEmuType     = varfrom->tEmuType;
  varto->scale_factor = varfrom->scale_factor;
  varto->add_offset   = varfrom->add_offset;
  varto->nFillValue   = varfrom->nFillValue;
  varto->fFillValue   = varfrom->fFillValue;
  varto->tDataOrg     = varfrom->tDataOrg;
  varto->nBands       = varfrom->nBands;
  varto->bByteSwap    = varfrom->bByteSwap;
  varto->delimeter    = varfrom->delimeter;
  varto->ncid         = varfrom->ncid;
  varto->var_id       = varfrom->var_id;

  varto->nDyn         = varfrom->nDyn;
  if (varto->nDyn)
  {
    varto->pstDyn = (DYNFILE *) malloc(sizeof(DYNFILE) * varto->nDyn);

    for (j = 0; j<varto->nDyn; j++)
    {
      varto->pstDyn[j].nElements = varfrom->pstDyn[j].nElements;
      strcpy(varto->pstDyn[j].szFormat, varfrom->pstDyn[j].szFormat);
      strcpy(varto->pstDyn[j].szName, varfrom->pstDyn[j].szName);
      varto->pstDyn[j].ppszElement = (char * *) malloc(sizeof(char *) * varto->pstDyn[j].nElements);
      for (i=0; i<varto->pstDyn[j].nElements; i++)
        AssignString(&varto->pstDyn[j].ppszElement[i], varfrom->pstDyn[j].ppszElement[i]);
    }
  }
  else
    varto->pstDyn = NULL;

  varto->nParams = varfrom->nParams;
  if (varto->nParams)
  {
    varto->P = alloc1d_f(0,varto->nParams-1);
    for (i=0; i<varto->nParams; i++)
      varto->P[i] = varfrom->P[i];
  }

  varto->nStrParams = varfrom->nStrParams;
  for (i=0; i < varto->nStrParams; i++)
    AssignString(&varto->szP[i], varfrom->szP[i]);
}

/* ================================================================= */
nc_type EMUtoNCType(emu_type EmuType)
{
  switch(EmuType)
  {
    case EMU_BYTE:
      return(NC_BYTE);
      break;
    case EMU_SHORT:
      return(NC_SHORT);
      break;
    case EMU_INT:
      return(NC_INT);
      break;
    case EMU_FLOAT:
      return(NC_FLOAT);
      break;
    case EMU_DOUBLE:
      return(NC_DOUBLE);
      break;
    default:
      return(NC_FLOAT);
      break;
  }
}

/* ================================================================= */
emu_type NCtoEMUType(nc_type NCType)
{
  switch(NCType)
  {
    case NC_BYTE:
      return(EMU_BYTE);
      break;
    case NC_SHORT:
      return(EMU_SHORT);
      break;
    case NC_INT:
      return(EMU_INT);
      break;
    case NC_FLOAT:
      return(EMU_FLOAT);
      break;
    case NC_DOUBLE:
      return(EMU_DOUBLE);
      break;
    default:
      return(EMU_FLOAT);
      break;
  }
}

/* ================================================================= */
size_t EmuTypeSize(emu_type EmuType)
{
  if (EmuType == EMU_BYTE)
    return(sizeof(BYTE));
  else if (EmuType == EMU_CHAR)
    return(sizeof(char));
  else if (EmuType == EMU_SHORT)
    return(sizeof(short));
  else if (EmuType == EMU_USHORT)
    return(sizeof(unsigned short));
  else if (EmuType == EMU_INT)
    return(sizeof(int));
  else if (EmuType == EMU_FLOAT)
    return(sizeof(float));
  else if (EmuType == EMU_DOUBLE)
    return(sizeof(double));
  else if (EmuType == EMU_WORD)
    return(sizeof(WORD));
  else if (EmuType == EMU_LONG)
    return(sizeof(long));
  else if (EmuType == EMU_ULONG)
    return(sizeof(unsigned long));
  else if (EmuType == EMU_DWORD)
    return(sizeof(DWORD));
  return(sizeof(BYTE));
}

/* ================================================================= */
void CleanUp(void)
{
  LocalCleanUp();
  GlobalCleanUp();

  /* print out date and time */
  if (!bQuiet)
  {
    printf("\n================ END OF PROGRAM ================ \n");
    PrintTime();
    printf("================================================== \n");
  }
}

/* ================================================================= */
void GlobalCleanUp(void)
{
  int i;

  VariableCleanUp();

  CheckDeallocation();

  if (pszConfigFile != NULL)
    free(pszConfigFile);

  if (pszSystemConfigFile != NULL)
    free(pszSystemConfigFile);

  if (pszOutputFile != NULL)
    free(pszOutputFile);

  if (pszNCtitle != NULL)
    free(pszNCtitle);

  if (pszNChist != NULL)
    free(pszNChist);

  if (nParams > 0)
    free1d_f(P,0,nParams-1);

  if (nStrParams > 0)
    for (i=0; i < nStrParams; i++)
      free(szP[i]);
}



/* ================================================================= */
/* ======================= LOCAL FUNCTIONS ========================= */

/* ================================================================= */
/* Check to see if there are command-line switches to be processed,
 * and move real arguments to front of the line, and changes argc */

BOOL ProcessDefaultCommandLineArgs(int * pArgc, char * argv[])
{
  int i;
  BOOL bProcess = TRUE;
  int nArgv = 1;

  pszProgramName = argv[0];
  pszConfigFile = malloc(strlen(pszProgramName)+10);
  sprintf(pszConfigFile, "%s.cfg", pszProgramName);
  AssignString(&pszOutputFile, pszProgramName);
  AssignString(&pszSystemConfigFile, SYSCFGFILE);
  if (pszNCtitle == NULL)  AssignString(&pszNCtitle, "Title");
  if (pszNChist == NULL)   AssignString(&pszNChist, "File History");


  for (i=1; i<*pArgc; i++)
  {
    if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help" ) == 0)
    {
      Usage(cpszUsage);
      bProcess = FALSE;
      exit(0);
    }
    else if (strcmp(argv[i], "-v") == 0)
    {
      printf("Running using verbose mode\n");
      bVerbose = TRUE;
    }
    else if (strcmp(argv[i], "-q") == 0)
      bQuiet = TRUE;
    else if (strcmp(argv[i], "-i") == 0)
      bInteractive = TRUE;
    else if (strcmp(argv[i], "-d") == 0)
    {
      printf("Running using debug mode\n");
      bDebug = TRUE;
    }
    else if (strcmp(argv[i], "-nm") == 0  || strcmp(argv[i], "-nomask") == 0)
      bNoMask = TRUE;
    else if (strcmp(argv[i], "-f") == 0)
    {
      bSelectedConfigFileName = TRUE;
      free(pszConfigFile);
      AssignString(&pszConfigFile, argv[++i]);
    }
    else if (strcmp(argv[i], "-scf") == 0)
    {
      free(pszSystemConfigFile);
      AssignString(&pszSystemConfigFile, argv[++i]);
    }
    else if (strcmp(argv[i], "-o") == 0)
    {
      free(pszOutputFile);
      AssignString(&pszOutputFile, argv[++i]);
    }
    else if (strcmp(argv[i], "-ob") == 0)
      bOutBinary = TRUE;
    else if (strcmp(argv[i], "-cdl") == 0)
    {
      free(pszCDLFile);
      AssignString(&pszCDLFile, argv[++i]);
    }
    else if (strcmp(argv[i], "-tit") == 0)
    {
      free(pszNCtitle);
      AssignString(&pszNCtitle, argv[++i]);
    }
    else if (strcmp(argv[i], "-hist") == 0)
    {
      free(pszNChist);
      AssignString(&pszNChist, argv[++i]);
    }
    else
      argv[nArgv++] = argv[i];

  }

  *pArgc = nArgv;

  return(bProcess);
}

/* ================================================================= */
/* Display the default usage message and the usage message for the
 * current application  */

void Usage(const char * cpszUsage)
{
  printf(cpszUsage);
  printf("\nStandard command line switches for emu are:\n");
  printf("\t-f Filename        - sets configuration file (default: %s.cfg) \n", pszProgramName);
  printf("\t-scf Filename      - sets system configuration file (default .\\system.cfg) \n");
  printf("\t-o Output Filename - sets output file name (default: %s), w/o extension \n", pszProgramName);
  printf("\t-ob Output Binary  - sets flag usually used to output binary file types\n");
  printf("\t-nm or -nomask     - Don't use a mask.\n");
  printf("\t-h or -help        - usage screen\n");
  printf("\t-d                 - sets debug mode\n");
  printf("\t-q                 - sets quiet mode (no output to stdout)\n");
  printf("\t-cdl CDL Filename  - sets CDL filename to create netcdf output file\n");
  printf("\t-hist              - Enter 'history' global attribute for netcdf files\n");
  printf("\t-tit               - Enter 'title' global attribute for netcdf files\n");

  printf("These switches are reserved but generally unsupported\n");
  printf("\t-v   - sets verbose mode (lots of output to stdout)\n");
  printf("\t-i   - sets interactive mode\n");
}

/* ================================================================= */
/* read in local system configuration information */

void ReadSystemConfigFile(void)
{
  FILE * fpc;
  char szLine[LINELEN];
  char s[LINELEN];

  if ((fpc = fopen(pszSystemConfigFile, "rt")) == NULL)
     Warning("Couldn't open file %s for reading in ReadSystemConfigFile\n", pszSystemConfigFile);
  else
  {
    if (GetLine(fpc, szLine, "# CONFIGFILE", TRUE))
    {
      sscanf(szLine, "%s", s);
      if (!istype(s, "programname") && !bSelectedConfigFileName)
      {
        free(pszConfigFile);
        AssignString(&pszConfigFile, s);
      }
    }
    else if (bDebug)
      Warning("In %s, need entry for variable CONFIGFILE", pszSystemConfigFile);

    if (GetLine(fpc, szLine, "# BYTEORDER", TRUE))
    {
      if (istype(szLine, "m"))
        tByteOrder = MOTOROLA;
      else if (istype(szLine, "d"))
        tByteOrder = DEC;
      else if (istype(szLine, "i"))
        tByteOrder = INTEL;
      else
        tByteOrder = INTEL;
    }
    else if (bDebug)
      Warning("Couldn't find \"# BYTEORDER\" in file %s in ReadSystemConfigFile\n", pszSystemConfigFile);

    if (GetLine(fpc, szLine, "# YEARORIGIN", TRUE))
      sscanf(szLine, "%d", &YEARORIGIN);
    else if (bDebug)
      Warning("Couldn't find \"# YEARORIGIN\" in file %s in ReadSystemConfigFile\n", pszSystemConfigFile);

    if (GetLine(fpc, szLine, "# OUTPUTPATH", TRUE))
    {
      sscanf(szLine, "%s", s);
      AssignString(&pszOutputFilePath, s);
    }
    else if (bDebug)
      Warning("In %s, need entry for variable OUTPUTPATH", pszSystemConfigFile);

#ifndef NONETCDF
    if (GetLine(fpc, szLine, "# NCGEN", TRUE))
    {
      sscanf(szLine, "%s", s);
      AssignString(&pszNCGenFile, s);
    }
    else if (bDebug)
      Warning("In %s, need entry for variable NCGEN", pszSystemConfigFile);

    if (GetLine(fpc, szLine, "# CDLFILE", TRUE))
    {
      sscanf(szLine, "%s", s);
      AssignString(&pszCDLFile, s);
    }
    else if (bDebug)
      Warning("In %s, need entry for variable CDLFILE", pszSystemConfigFile);

    DoesFileExist(pszCDLFile);
#endif

    fclose(fpc);
  }
}

/* ================================================================= */
/* read in the values of nRows and nCols;
 * read the geographic location (corners of the image, in lat/lon degrees;
 * read the initial and final year/month into TIME struct   */

void SetModelParameters(void)
{
  FILE * fpc;
  char szLine[LINELEN], *s, c1, c2, *VarArgs[50], *ss[10];
  float ptmp[50];
  int mo, i, nLineArgs, ParamsIndx;


  if (!bQuiet)
    printf("\n---- Reading Global Parameters in SetModelParameters() \n");

  if ((fpc = fopen(pszConfigFile, "rt")) == NULL)
     ExitError("Couldn't open file %s for reading in SetmodelParameters\n", pszConfigFile);

  /* ================ read in spatial information ================ */
  if (GetLine(fpc, szLine, "# SIZE", TRUE))
  {
    nLineArgs = GetLineElements(VarArgs, szLine, ' ');

    nCols = atoi(VarArgs[0]);
    nRows = atoi(VarArgs[1]);
    if (nLineArgs == 3)
    {
      nYBlocks   = atoi(VarArgs[2]);
      nBlockRows = (int) (nRows/nYBlocks);
    }

    /* clear the allocated memory for VarArgs */
    for (i=0; i<nLineArgs; i++)
      free(VarArgs[i]);
  }
  else if (bDebug)
    Warning("Couldn't find \"# SIZE\" in file %s in SetModelParameters\n", pszConfigFile);

  if (GetLine(fpc, szLine, "# GEOGRAPHIC", TRUE))
  {
    sscanf(szLine, "%f %f %f %f", &fLatTop, &fLatBtm, &fLonRight, &fLonLeft);
    fVScale = (fLatTop - fLatBtm) / (float) nRows;
    fHScale = (fLonRight - fLonLeft) / (float) nCols;
  }
  else if (bDebug)
    Warning("Couldn't find \"# GEOGRAPHIC\" in file %s in SetModelParameters\n", pszConfigFile);


  /* ============== read time information into global TIME struct ============= */
  if (GetLine(fpc, szLine, "# TIME", TRUE))
  {
    sscanf(szLine, "%d %d %d %d", &nFirstYear, &nFirstMonth, &nLastYear, &nLastMonth);

    /* read number of years for looping and I/O fpc */
    nTotalYears  = nLastYear - nFirstYear + 1;
    nTimeSteps = (12-nFirstMonth+1) + (nTotalYears-2)*12 + nLastMonth;

    if (!bQuiet)
      printf("\nFrom %d/%d to %d/%d; %d months, in %d different years\n",
              nFirstMonth, nFirstYear, nLastMonth, nLastYear, nTimeSteps, nTotalYears);

    for (mo = 0; mo < YEAR2MONTH; mo++)
      if (nLastMonth < nFirstMonth)
      {
        if ((mo+1) < nFirstMonth && (mo+1) > nLastMonth)
          nTotalMonths[mo] = nTotalYears - 2;
        else
          nTotalMonths[mo] = nTotalYears - 1;
      }
      else
      {
        if ((mo+1) <= nLastMonth && (mo+1) >= nFirstMonth)
          nTotalMonths[mo] = nTotalYears;
        else
          nTotalMonths[mo] = nTotalYears - 1;
      }
  }
  else if (bDebug)
    Warning("Couldn't find \"# TIME\" in file %s in SetModelParameters\n", pszConfigFile);


  /* ===== read-in customized, global parameters into global arrays P and szP ==== */
  nParams    = 0;
  nStrParams = 0;
  if (GetLine(fpc, szLine, "# PARAM", TRUE))
  {
    nLineArgs = GetLineElements(VarArgs, szLine, ' ');

    for (ParamsIndx=0; ParamsIndx < nLineArgs; ParamsIndx++)
    {
      /* if 1st character is a digit, or 1st character is a '.', '+', or '-' and   *
       * 2nd character is a digit, parameter is assumed to be a number             *
       * (-.5 won't be recognized!)                                                */
      c1 = VarArgs[ParamsIndx][0];
      c2 = VarArgs[ParamsIndx][1];
      if (isdigit(c1) || ((c1 == '+' || c1 == '-' || c1 == '.') && isdigit(c2)))
        ptmp[nParams++] = (float) atof(VarArgs[ParamsIndx]);
      else
        AssignString(&ss[nStrParams++], VarArgs[ParamsIndx]);
      if(bDebug)  printf("<%s>", VarArgs[ParamsIndx]);
    }
    if(bDebug)   printf("\n FloatParams=%d,  StrParams=%d  ", nParams,nStrParams);

    /* process number parameters */
    if (nParams > 0)
    {
      P = alloc1d_f(0,nParams-1);
      for (i = 0; i < nParams; i++)
        P[i] = ptmp[i];
    }

    /* process string parameters and free allocated memory for ss */
    for (i = 0; i < nStrParams; i++)
    {
      AssignString(&szP[i], ss[i]);
      free(ss[i]);
    }

    /* clear the allocated memory for VarArgs */
    for (i=0; i<nLineArgs; i++)
      free(VarArgs[i]);
  }
  else if (bDebug)
    Warning("Couldn't find \"# PARAM\" in file %s in SetModelParameters\n", pszConfigFile);


  /* =========== read in the NAMEDVARIABLES option state ================ */
  bNamedVariables = FALSE;
  if (GetLine(fpc, szLine, "# NAMEDVARIABLES", TRUE))
  {
    s = (char *) malloc(strlen(szLine)+1);
    sscanf(szLine, "%s", s);

    if (istype(s, "yes"))
      bNamedVariables = TRUE;

    free(s);
  }
  else if (bDebug)
    Warning("Couldn't find \"# NAMEDVARIABLES\" in file %s in SetModelParameters\n", pszConfigFile);


  fclose(fpc);
}

/* ================================================================= */

void ReadConfigVariables(void)
{
  FILE * fpc;                           int debug=0;
  int v=0, i, nLineArgs;
  int os;        /* index offset */
  int nArgs;     /* number of default, fixed arguments for a particular filetype */
  int nVarParams, FloatParams, StrParams;
  char c1, c2, *VarArgs[50], *ss[10];
  char szFileType[20], szLine[LINELEN];
  float ptmp[50];
  short ncvars;
  VAR * tmpVars;


  tmpVars = alloc1d_VAR(0,100);
  if (!bQuiet)
    printf("\n---- Reading Paths and variable info. in ReadConfigVariables() \n");

  if ((fpc = fopen(pszConfigFile, "rt")) == NULL)
    ExitError("Couldn't open configuration file %s for reading\n", pszConfigFile);

  if (GetLine(fpc, szLine, "# VAR", TRUE) == FALSE)
    ExitError("Couldn't find # VAR line in configuration file, %s\n", pszConfigFile);


  /* ===== READ AND PARSE EACH VARIABLE LINE IN THE CONFIG FILE ====== */
  while (getVarLine(fpc, szLine) != 0)
  {
    /* read the var line */
    nLineArgs = GetLineElements(VarArgs, szLine, ' ');

    /* process the elements variable name (optional) and filetype */
    if (bNamedVariables || !IsValidFileType(VarArgs[0]))
    {
      os = 1;
      strcpy(tmpVars[v].name, VarArgs[0]);
      strcpy(tmpVars[v].filetype, VarArgs[1]);
      strcpy(szFileType, VarArgs[1]);
    }
    else
    {
      os = 0;
      strcpy(tmpVars[v].name, "none");
      strcpy(tmpVars[v].filetype, VarArgs[0]);
      strcpy(szFileType, VarArgs[0]);
    }


    /* ====== process line elements according to filetype ====== */
    /* ============ BINARY FILETYPE ============= */
    if (istype(szFileType, "bin") || istype(szFileType, "motorola")
        || istype(szFileType, "intel"))
    {
      if (bDebug)  printf("\n v=%d: binary file type\n", v);
      /* Args: filetype,datatype,filepath,filename(param),dataorg,nbands */
      nArgs = 6 + os;

      strcpy(tmpVars[v].filetype, "bin");
      if ((istype(szFileType, "motorola") && tByteOrder == INTEL) ||
          (istype(szFileType, "intel") && tByteOrder == MOTOROLA) )
        tmpVars[v].bByteSwap = TRUE;
      else
        tmpVars[v].bByteSwap = FALSE;

      tmpVars[v].tEmuType = GetEmuType(VarArgs[1+os]);

      strcpy(tmpVars[v].path, VarArgs[2+os]);
      strcpy(tmpVars[v].param, VarArgs[3+os]);

      if (VarArgs[4+os][0] == '-')
        tmpVars[v].tDataOrg = GetDataOrgType("fsq");
      else
        tmpVars[v].tDataOrg = GetDataOrgType(VarArgs[4+os]);

      if (tmpVars[v].tDataOrg == BADTYPE)
      {
        tmpVars[v].tDataOrg  = GetDataOrgType("fsq");
        tmpVars[v].tTimeType = GetTimeType(VarArgs[4+os]);
      }
      else
        tmpVars[v].tTimeType = NOTIME;

      if (nLineArgs < nArgs+os)  /* nBands ARGUMENT MAY NOT BE NEEDED */
        tmpVars[v].nBands = 1;
      else if (VarArgs[5+os][0] == '-')
        tmpVars[v].nBands = 1;
      else
        tmpVars[v].nBands = atoi(VarArgs[5+os]);
    }
    /* ================= ASCII FILETYPE ================ */
    else if (istype(szFileType, "ascii"))
    {
      if (bDebug)  printf("\n v=%d: ascii file type\n", v);
      /* Args: filetype,datatype,filepath,filename(param),timetype,delimeter */
      nArgs = 6 + os;

      tmpVars[v].tEmuType = GetEmuType(VarArgs[1+os]);

      strcpy(tmpVars[v].path, VarArgs[2+os]);
      strcpy(tmpVars[v].param, VarArgs[3+os]);

      if (VarArgs[4+os][0] != '-')
        tmpVars[v].tTimeType = GetTimeType(VarArgs[4+os]);
      else
        tmpVars[v].tTimeType = NOTIME;

      if (VarArgs[5+os][0] == 't')    /* tab delimeter */
        tmpVars[v].delimeter = '\t';
      else    /* all other single-character delimeters */
        tmpVars[v].delimeter = VarArgs[5+os][0];
    }
    /* ================ NETCDF FILETYPE ================ */
    else if (istype(szFileType, "nc"))
    {
      if (bDebug)  printf("\n v=%d: netcdf file type\n", v);
      /* Args: filetype,full filepath,NC variable name(param),timetype */
      nArgs = 4 + os;

      strcpy(tmpVars[v].path, VarArgs[1+os]);
      strcpy(tmpVars[v].param, VarArgs[2+os]);

      tmpVars[v].tTimeType = GetTimeType(VarArgs[3+os]);
    }
    /* ====================================================== */
    else
      ExitError("File type %s not handled", tmpVars[v].filetype);
    /* ====================================================== */

    /* ======== REPLACE ALIASES IN FILEPATH AND FILENAME ======== */
    ReplaceAlias(&tmpVars[v], PATH);
    ReplaceAlias(&tmpVars[v], PARAM);

    /* ====== INITIALIZE OTHER ELEMENTS OF THE PSTVAR STRUCTURE ====== */
    tmpVars[v].t1           = 1.0F;
    tmpVars[v].scale_factor = 1.0F;
    tmpVars[v].add_offset   = 0.0F;

    /* ========= HANDLE OPTIONAL nCols & nRows  ============= */
    if (nLineArgs < nArgs + 2)
    {
      tmpVars[v].nCols = nCols;
      tmpVars[v].nRows = nRows;
    }
    else
    {
      tmpVars[v].nCols = (VarArgs[nArgs][0]   == '-') ? nCols : atoi(VarArgs[nArgs]);
      tmpVars[v].nRows = (VarArgs[nArgs+1][0] == '-') ? nRows : atoi(VarArgs[nArgs+1]);
    }

    if (bDebug)
      printf("\n nLineArgs=%d, tmpVars[%d].name=%s, .filetype=%s, .path=%s, .param=%s, .nCols=%d, .nRows=%d \n",
        nLineArgs,v,tmpVars[v].name,tmpVars[v].filetype,tmpVars[v].path,tmpVars[v].param,tmpVars[v].nCols,tmpVars[v].nRows);

    /* ======== HANDLE OPTIONAL VARIABLE PARAMETERS ========== */
    FloatParams = 0;
    StrParams   = 0;
    if (nLineArgs <= nArgs + 2)  /* this isn't really needed now that these field are initialized in alloc1d_VAR */
    {
      tmpVars[v].nParams    = 0;
      tmpVars[v].nStrParams = 0;
    }
    else
    {
      for (nVarParams=nArgs+2; nVarParams < nLineArgs; nVarParams++)
      {
        /* if 1st character is a digit, or 1st character is a '.', '+', or '-' and   *
         * 2nd character is a digit, parameter is assumed to be a number             *
         * (-.5 won't be recognized!)                                                */
        c1 = VarArgs[nVarParams][0];
        c2 = VarArgs[nVarParams][1];
        if (isdigit(c1) || ((c1 == '+' || c1 == '-' || c1 == '.') && isdigit(c2)))
          ptmp[FloatParams++] = (float) atof(VarArgs[nVarParams]);
        else
          AssignString(&ss[StrParams++], VarArgs[nVarParams]);
        if(bDebug)  printf("<%s>", VarArgs[nVarParams]);
      }
      if(bDebug)   printf("\n FloatParams=%d,  StrParams=%d  ", FloatParams,StrParams);

      /* process number parameters */
      tmpVars[v].nParams = FloatParams;
      if (FloatParams > 0)
      {
        tmpVars[v].P = alloc1d_f(0,FloatParams-1);
        for (i = 0; i < FloatParams; i++)
          tmpVars[v].P[i] = ptmp[i];
      }

      /* process string parameters and free allocated memory for ss */
      tmpVars[v].nStrParams = StrParams;
      for (i = 0; i < StrParams; i++)
      {
        AssignString(&tmpVars[v].szP[i], ss[i]);
        free(ss[i]);
      }
    }

    /* clear the allocated memory for VarArgs */
    for (i=0; i<nLineArgs; i++)
      free(VarArgs[i]);

    /* ============== PROCESS METADATA OPTIONAL SPECIFIER ================ */
    if (tmpVars[v].nStrParams >= 1)
      tmpVars[v].bIsMetaData = istype(tmpVars[v].szP[0], "metadata") ? TRUE : FALSE;
    else
      tmpVars[v].bIsMetaData = FALSE;

    /* ============== PROCESS NETCDF VARIABLES ================ */
    if (istype(tmpVars[v].filetype, "nc"))
    {
      /* if the variable is only a metadata specifier, do not try to *
       * process the netcdf file                                     */
      if (tmpVars[v].bIsMetaData) /* read the data type metadata */
        tmpVars[v].tEmuType = GetEmuType(tmpVars[v].szP[2]);
      else /* process the netcdf file and variables */
      {
        ncvars = ProcessNetcdfVariable(v, tmpVars);
        v += ncvars - 1;
      }
    }

    if (bDebug)   printf("EMU_TYPE=%d, tDataOrg=%d, tTimeType=%d, nBands=%d, bByteSwap=%d\n",
              tmpVars[v].tEmuType,tmpVars[v].tDataOrg,tmpVars[v].tTimeType,tmpVars[v].nBands,tmpVars[v].bByteSwap);

    v++;
  }

  fclose(fpc);


  /* ==== COPY FROM THE TEMPORARY VAR STRUCTURE, TO THE FINAL VAR STRUCTURE ==== */
  /* allocate memory space to pstVars containing nVars variables */
  nVars = v;
  pstVars = alloc1d_VAR(0,nVars-1);

  for (v=0; v < nVars; v++)
  {
    CopyVar(&pstVars[v], &tmpVars[v]);

    /* print out parameter values, for debugging */
    if(bDebug)
    {
      printf("\n");
      for (i = 0; i < pstVars[v].nParams; i++)
        printf(" P[%d]=%f ", i,pstVars[v].P[i]);

      for (i = 0; i < pstVars[v].nStrParams; i++)
        if(bDebug)   printf(" szP[%d]=%s ", i,pstVars[v].szP[i]);
    }
  }


  free1d_VAR(tmpVars,0,100);

  if (!bQuiet)
    printf("\n %d Variables\n---- Copied final VAR structure, Done with ReadConfigVariables() \n",nVars);
}

/* ================================================================= */
short ProcessNetcdfVariable(int v, VAR *tmpVars)
{
  char szName[NAMELEN], szUnit[NAMELEN];
  int ncID, varID, tmpncdims, tmpncvars, ncv;
  int tID, recID;
  char szTimeOrigin[100], s[100], *pCh, szYearOrigin[5];
  size_t t_index=0;
  nc_type ncType;


  if (bDebug)   printf("\n  ** Beginning ProcessNetcdfVariable()\n");

  /* open netCDF file, get its ID, variable ID  */
  errnc = nc_open(tmpVars[v].path, NC_NOWRITE, &ncID); /* USE NC_WRITE OR NC_SHARE INSTEAD ? */
  tmpVars[v].ncid = ncID;

  /* ========== Time Axis information: units, 1st time step, etc. ============ */
/* BUT THIS WILL WORK ONLY IF THE TIME DIMENSION IS DECLARED AS NC_UNLIMITED !!!! */
  errnc = nc_inq_unlimdim(ncID, &recID);
  errnc = nc_inq_dimname(ncID, recID, szName);
  errnc = nc_inq_varid(ncID, szName, &tID);

  /* extract the YearOrigin */
  ClearString(szTimeOrigin, 100);
  errnc = nc_get_att_text(ncID, tID, "time_origin", szTimeOrigin);
  if (bDebug)   printf("\n     szTimeOrigin = |%s|\n", szTimeOrigin);
  strcpy(s, szTimeOrigin);
  /* this scheme will work only with time origin years in the 1900's *
   * (ie, 19**); and assumes DEC-15 of the previous year             */
  while ((pCh = strchr(s, '1')) != NULL)
    if (*(pCh+1) == '9')
      break;
    else
      strcpy(s, ++pCh);

  if (pCh != NULL)  /* found the substring beginning with '19' */
  {
    *(pCh+4) = '\0';
    strcpy(szYearOrigin, pCh);
    tmpVars[v].YearOrigin = (short) strtol(szYearOrigin, NULL, 0);
  }
  else
    Warning("Could not find YearOrigin in nc file %s\n", tmpVars[v].path);

  /* what happens if .tTimeType != MONTHLY (eg, ANNUAL) !? */
  if (tmpVars[v].tTimeType == MONTHLY)
    errnc = nc_get_var1_double(ncID, tID, &t_index, &tmpVars[v].t1);

  if (bDebug)   printf(" READ tmpVars[v].t1: .t1=%f \n", tmpVars[v].t1);

  /* now read time unit, and then make conversion to MONTH unit   */
  errnc = nc_get_att_text(ncID, tID, "units", szUnit);

  if (istype(szUnit, "mon") || istype(szUnit, "MON"))
    strcpy(tmpVars[v].szUnit, "month");
  else if (istype(szUnit, "day") || istype(szUnit, "DAY"))
  {
    strcpy(tmpVars[v].szUnit, "day");
    tmpVars[v].t1 = floor(tmpVars[v].t1/MONTH2DAY + 0.5);
  }
  if (istype(szUnit, "hou") || istype(szUnit, "HOU"))
  {
    strcpy(tmpVars[v].szUnit, "hour");
    tmpVars[v].t1 = floor(tmpVars[v].t1/MONTH2HOUR + 0.5);
  }

  if (bDebug)  printf(" NC type v=%d: ncid=%d, szUnit=%s, t1=%f, YearOrigin=%d\n",
                    v,ncID,tmpVars[v].szUnit,tmpVars[v].t1,tmpVars[v].YearOrigin);


  /* ===== Variable-specific information: ID, name, scale, offset, FillValue ==== */
  /* ========= Also, copy the VAR element for this new variable ================= */

  /* if param code is "all", query the NC file and extract number of data variables */
  if (istype(tmpVars[v].param, "all"))
  {
    errnc = nc_inq_ndims(ncID, &tmpncdims);
    errnc = nc_inq_nvars(ncID, &tmpncvars);
    tmpncvars = tmpncvars - tmpncdims;
  }
  else
    tmpncvars = 1;


  for (ncv = v; ncv < v+tmpncvars; ncv++)
  {
    if (tmpncvars > 1)
    {
      CopyVar(&tmpVars[ncv], &tmpVars[v]);

      tmpVars[ncv].var_id = tmpncdims + ncv;
      errnc = nc_inq_varname(ncID, tmpVars[ncv].var_id, tmpVars[ncv].param);
    }
    else
      errnc = nc_inq_varid(ncID, tmpVars[ncv].param, &tmpVars[ncv].var_id);

    varID = tmpVars[ncv].var_id;
    if (bDebug)  printf("  Variable name: %s \n", tmpVars[ncv].param);

    errnc = nc_inq_vartype(ncID, varID, &ncType);
    tmpVars[ncv].tEmuType = NCtoEMUType(ncType);

    /* scale_factor and add_offset attributes */
    /* if attribute doesn't exist the NC 3.4 lib returns the error code NC_ENOTATT */
    errnc = nc_get_att_float(ncID, varID, "scale_factor", &tmpVars[ncv].scale_factor);
    errnc = nc_get_att_float(ncID, varID, "add_offset", &tmpVars[ncv].add_offset);

    /* FillValue attributes */
    errnc = nc_inq_atttype(ncID, tmpVars[ncv].var_id, "_FillValue", &ncType);
    if (ncType == NC_SHORT)
      errnc = nc_get_att_short(ncID, varID, "_FillValue", &tmpVars[ncv].nFillValue);
    else if (ncType == NC_FLOAT)
      errnc = nc_get_att_float(ncID, varID, "_FillValue", &tmpVars[ncv].fFillValue);


    if (bDebug)
      printf(" NC variable ncv=%d: .param=%s, .var_id=%d, scale_factor=%f \n", ncv,
             tmpVars[ncv].param,tmpVars[ncv].var_id,tmpVars[ncv].scale_factor);
  } /* END OF ncv FOR-LOOP */

  if (bDebug)  printf("  tmpncvars=%d    \n", tmpncvars);

  return(tmpncvars);
}

/* ================================================================= */
void VariableCleanUp(void)
{
  int v, flagncid = -999, axis;

  /* close netcdf files */
  for (v = 0; v < nVars; v++)
    if (!pstVars[v].bIsMetaData)
      if (istype(pstVars[v].filetype, "nc") && (pstVars[v].ncid != flagncid))
      {
        errnc = nc_close(pstVars[v].ncid);
        flagncid = pstVars[v].ncid;
      }

  /* free VAR-related variables */
  if (nVars != 0)
    free1d_VAR(pstVars,0,nVars-1);
  if (pstInput != NULL)
    free1d_VAR(pstInput,0,0);
  if (pstOutput != NULL)
    free1d_VAR(pstOutput,0,0);

  /* free variables related to the mask */
  if (!bNoMask)
  {
    free1d_l(pMask,0,nRows*nCols-1);
    free1d_MASK(Masks,0,MskSitesN-1);
    free1d_i(FlMskSitesIDs,0,FlMskSitesN-1);
    free1d_i(FlMskSitesCellcount,0,FlMskSitesN-1);
    free1d_d(FlMskSitesArea,0,FlMskSitesN-1);
    free1d_i(MskSitesIDs,0,MskSitesN-1);
  }

  /* free coordinate variable arrays (used for writing files) */
  for (axis=0; axis < 4; axis++)
    if (stAxes[axis].active)
      free1d_d(stAxes[axis].values, 0,stAxes[axis].length-1);
}


/* ================================================================= */
/* ================================================================= */

void ReplaceAlias(VAR * pstVar, int nFlag)
{
  char szFirst[LINELEN];
  char szMid[LINELEN];
  char szLast[LINELEN];
  char szLine[LINELEN];
  char szSrc[LINELEN];
  char szDest[LINELEN];
  char szName[LINELEN];
  char szArg[LINELEN];
  char s[LINELEN];
  int l_nDyn;
  DYNFILE * pstDyn;

  if (nFlag == PARAM)
    strcpy(szSrc, pstVar->param);
  else if (nFlag == PATH)
    strcpy(szSrc, pstVar->path);

  strcpy(szDest, "");
  while (SplitString(szSrc, szFirst, '(', szMid, ')', szLast))
  {
    sprintf(s, "# %s", szMid);
    if (ReadConfigLine(szLine, s))
    {
      sscanf(szLine, "%s", szMid);
      strcat(szDest, szFirst);
      strcat(szDest, szMid);

      strcpy(szSrc, szLast);
    }
    else if (strchr(szMid, ':') != NULL)  /* look for dynamic filename separator */
    {
      strcat(szDest, szFirst);
      strcat(szDest, "(");
      strcat(szDest, szMid);
      strcat(szDest, ")");

      strcpy(szSrc, szLast);

      SplitString(szMid, szName, ':', szArg, '\0', NULL);

      if (pstVar->pstDyn == NULL)
      {
        pstVar->nDyn = strcnt(szLast, ':') + 1;  /* need to include this one */
        pstVar->pstDyn = (DYNFILE *) malloc(sizeof(DYNFILE) * pstVar->nDyn);
        l_nDyn = 0;
      }
      else
        l_nDyn++;

      pstDyn = &(pstVar->pstDyn[l_nDyn]);
      strcpy(pstDyn->szName, szName);
      strcpy(pstDyn->szFormat, szArg);
      sprintf(s, "# %s", szName);

      if (ReadConfigLine(szLine, s))
        ParseFileList(szLine, pstDyn);
      else
        pstDyn->nElements = 0;

    }
    else
      Warning("Alias %s not found in ReplaceAlias in config file\n", szMid);
  }
  strcat(szDest, szSrc);

  if (nFlag == PARAM)
    strcpy(pstVar->param, szDest);
  else if (nFlag == PATH)
    strcpy(pstVar->path, szDest);
}

/* ================================================================= */
/* EmuType can be *only* EMU_INT or EMU_FLOAT */
void ReplaceDynAlias(char * pszDest, char * pszAlias, float fData, emu_type EmuType)
{
  char szFirst[LINELEN];
  char szMid[LINELEN];
  char szLast[LINELEN];
  char szSrc[LINELEN];
  char szName[LINELEN];
  char szArg[LINELEN];
  char s[LINELEN];
  BOOL bFoundAlias = FALSE;


  strcpy(szSrc, pszDest);
  strcpy(pszDest, "");

  while (SplitString(szSrc, szFirst, '(', szMid, ')', szLast))
  {
    bFoundAlias = TRUE;
    SplitString(szMid, szName, ':', szArg, '\0', NULL);
    if (!strcmp(szName, pszAlias))
    {
      strcat(pszDest, szFirst);
      if (EmuType == EMU_INT)
        sprintf(s, szArg, roundoff(fData));
      else if (EmuType == EMU_FLOAT)
        sprintf(s, szArg, fData);
      strcat(pszDest, s);
      break;
    }
    else
    {
      strcat(pszDest, szFirst);
      strcat(pszDest, "(");
      strcat(pszDest, szMid);
      strcat(pszDest, ")");
    }
    strcpy(szSrc, szLast);  /* place everything after close paren into szLast */
  }

  if (bFoundAlias)
    strcat(pszDest, szLast);
  else
    strcpy(pszDest, szSrc);
}

/* ================================================================= */
BOOL GetFileName(VAR * pVar, char * pszDest)
{
  strcpy(pszDest, pVar->path);
  strcat(pszDest, pVar->param);
  if (strchr(pszDest, '(') == NULL)
    return(FALSE);
  else
    return(TRUE);
}

/* ================================================================= */
int SplitString(char * pszSrc, char * pszFirst, char cSep1, char * pszMid, char cSep2, char * pszLast)
{
  char * pszSep;

  strcpy(pszFirst, pszSrc);
  if ((pszSep = strchr(pszFirst, cSep1)) != NULL)
  {
    *pszSep++ = '\0';
    strcpy(pszMid, pszSep);

    if (cSep2 != '\0')
    {
      if ((pszSep = strchr(pszMid, cSep2)) != NULL)
      {
        *pszSep++ = '\0';
        strcpy(pszLast, pszSep);
      }
      else
        Warning("%s not closed in SplitString\n", &cSep2);
    }
    return(TRUE);
  }
  else
    return(FALSE);
}

/* ================================================================= */
void ParseFileList(char * pszLine, DYNFILE * pstDyn)
{
  char  * pCh;
  char s[NAMELEN];
  int n = 0;

  /* count elements first */
  strcpy(s, pszLine);        /* copy string into s from that point  */
  while ((pCh = strchr(s, ',')) != NULL)
  {
    *pCh = '\0';
    pCh++;

    n += ExtractFileElements(s, NULL);
    strcpy(s, pCh);        /* copy string into s from that point  */
  }
  n += ExtractFileElements(s, NULL);

  pstDyn->ppszElement = (char * *) malloc(sizeof(char *) * n);
  pstDyn->nElements = n;

  strcpy(s, pszLine);        /* copy string into s from that point  */
  while ((pCh = strchr(s, ',')) != NULL)
  {
    *pCh = '\0';
    pCh++;

    ExtractFileElements(s, pstDyn);
    strcpy(s, pCh);        /* copy string into s from that point  */
  }
  ExtractFileElements(s, pstDyn);
}

/* ================================================================= */
int ExtractFileElements(char * pszSeg, DYNFILE * pstDyn)
{
  char s[NAMELEN];
  char s1[NAMELEN];
  char * pDash;
  int n = 0;
  int nFirstIndex;
  int nLastIndex;

  strcpy(s, pszSeg);        /* copy string into s from that point  */
  if ((pDash = strchr(s, '-')) == NULL)
  {  /* no -  */
    if (pstDyn != NULL)
    {
      pstDyn->ppszElement[pstDyn->nElements] = (char *) malloc(strlen(s)+1);
      strcpy(pstDyn->ppszElement[pstDyn->nElements++], s);
    }
    n=1;
  }
  else
  {
    *pDash = '\0';
    pDash++;

    sscanf(s, "%d", &nFirstIndex);
    strcpy(s1, pDash);
    sscanf(s1, "%d", &nLastIndex);

    if (pstDyn != NULL)
    {
      for (n = nFirstIndex; n<=nLastIndex; n++)
      {
        sprintf(s1, "%s", pstDyn->szFormat);
        sprintf(s, s1, n);
        pstDyn->ppszElement[pstDyn->nElements] = (char *) malloc(strlen(s)+1);
        strcpy(pstDyn->ppszElement[pstDyn->nElements++], s);
      }
    }
    n = nLastIndex - nFirstIndex + 1;
  }
  return(n);
}


/* ================================================================= */
/* ================================================================= */

int getVarLine(FILE *fpin, char *pszLine)
{
  while (strncmp(fgets(pszLine, LINELEN, fpin), "##", 2) == 0
    || strlen(pszLine) == 1)
    ;

  if (pszLine == NULL || strncmp(pszLine, "# END", 5) == 0 ||
      strncmp(pszLine, "# VAREND", 8) == 0 )
    return(0);
  else
    return(strlen(pszLine));
}

/* ================================================================= */
/* find line with pszMarker, read next line, return length of line */

int GetLine(FILE * fpin, char * pszLine, char * pszMarker, BOOL bFromStart)
{
  int nMatch;

  /* always start from the beginning so order is not important */
  if (bFromStart)
    rewind(fpin);

  do
  {
    nMatch = strncmp(fgets(pszLine, LINELEN, fpin), pszMarker, strlen(pszMarker));
    if (strncmp(pszLine, "# END", 5) == 0)
      return(0);
  } while (nMatch != 0 && pszLine != NULL);

  if (fgets(pszLine, LINELEN, fpin) == NULL)
    return(0);
  else
    return(strlen(pszLine));
}

/* ================================================================= */
/* open configuration file, then use GetLine() to find line with pszMarker *
 * and return parameter string, return length of line                      */

int ReadConfigLine(char * pszLine, char * pszMarker)
{
  FILE * fpc;

  if ((fpc = fopen(pszConfigFile, "rt")) == NULL)
    ExitError("Couldn't open file %s for reading\n", pszConfigFile);

  if (GetLine(fpc, pszLine, pszMarker, TRUE))
  {
    fclose(fpc);
    return(strlen(pszLine));
  }
  else if (bDebug)
    Warning("Couldn't find \"%s\" in config file in ReadConfigLine\n", pszMarker);

  fclose(fpc);

  return(0);
}

/* ================================================================= */
int GetTimeType(char *pszTimeType)
{
  if (istype(pszTimeType, "monthly"))
    return(MONTHLY);
  else if (istype(pszTimeType, "monmean"))
    return(MONMEAN);
  else if (istype(pszTimeType, "annual"))
      return(ANNUAL);
  else if (istype(pszTimeType, "xy"))
    return(NOTIME);
  else
    return(NOTIME);
}

/* ================================================================= */
dataorg_type GetDataOrgType(char * pszDataOrgType)
{
  if (istype(pszDataOrgType, "fsq"))
    return(FSQ);
  else if (istype(pszDataOrgType, "bsq"))
    return(BSQ);
  else if (istype(pszDataOrgType, "bil"))
    return(BIL);
  else if (istype(pszDataOrgType, "bip"))
    return(BIP);
  else
    return(BADTYPE);
}

/* ================================================================= */
emu_type GetEmuType(char * pszDataType)
{
  if (istype(pszDataType, "b"))
    return(EMU_BYTE);
  else if (istype(pszDataType, "c"))
    return(EMU_CHAR);
  else if (istype(pszDataType, "s"))
    return(EMU_SHORT);
  else if (istype(pszDataType, "l"))
    return(EMU_LONG);
  else if (istype(pszDataType, "f"))
    return(EMU_FLOAT);
  else if (istype(pszDataType, "d"))
    return(EMU_DOUBLE);
  else if (istype(pszDataType, "us"))
    return(EMU_USHORT);
  else if (istype(pszDataType, "w"))
    return(EMU_USHORT);
  else if (istype(pszDataType, "ul"))
    return(EMU_ULONG);
  else if (istype(pszDataType, "dw"))
    return(EMU_ULONG);
  return(EMU_BYTE);
}

/* ================================================================= */
BOOL IsValidFileType(char *pszLineElement)
{
  if (istype(pszLineElement, "intel") || istype(pszLineElement, "motorola")
      || istype(pszLineElement, "bin")
      || istype(pszLineElement, "ascii")
      || istype(pszLineElement, "nc"))
    return(TRUE);
  else
    return(FALSE);
}



/* ================================================================= */
/* ================================================================= */
/* ==== OBSOLESCENT FUNCTIONS, KEPT FOR BACKWARDS COMPATIBILITY ==== */


void SimpleInitialize(int * argc, char * argv[])
{
  Initialize(argc, argv, NOMASK);
}
/* ================================================================= */
void ReadVariable(VAR * pstVar, char * pszVarKeyword)
{
  CopyVar(pstVar, &pstVars[GetVarNo(pszVarKeyword)]);
}
/* ================================================================= */
void ReadInput(void)
{
  pstInput = alloc1d_VAR(0,0);

  ReadVariable(pstInput, "# INPUT ");
}
/* ================================================================= */
void ReadOutput(void)
{
  pstOutput = alloc1d_VAR(0,0);

  ReadVariable(pstOutput, "# OUTPUT ");
}