/* *************************************************************
 * *                                                           *
 * *       Header file for CONFIG library definitions          *
 * *                                                           *
 * *************************************************************
 * File: include/config_lib.h
 *
 *   COPYRIGHT (c) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 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.
 */
#define SIGMET_CONFIG_LIB_H 1

#ifdef __cplusplus
extern "C" {
#endif

#define        LIM_BADELEMENT 1
#define CONFIG_LIM_BADELEMENT (CONFIG_FACILITY + LIM_BADELEMENT)
#define        LIM_BADOP      2
#define CONFIG_LIM_BADOP      (CONFIG_FACILITY + LIM_BADOP)
#define        LIM_BADSTRUCT  3
#define CONFIG_LIM_BADSTRUCT  (CONFIG_FACILITY + LIM_BADSTRUCT)
#define        LIM_CANTMOD    4
#define CONFIG_LIM_CANTMOD    (CONFIG_FACILITY + LIM_CANTMOD)
#define        LIM_INTEXT     5
#define CONFIG_LIM_INTEXT     (CONFIG_FACILITY + LIM_INTEXT)
#define        LIM_NULLFILE   6
#define CONFIG_LIM_NULLFILE   (CONFIG_FACILITY + LIM_NULLFILE)
#define        LIM_TESTVAL    7
#define CONFIG_LIM_TESTVAL    (CONFIG_FACILITY + LIM_TESTVAL)
#define        STUBCALLED     8
#define CONFIG_STUBCALLED     (CONFIG_FACILITY + STUBCALLED)

#ifndef MESSAGE_ONLY                      

#ifdef SIGMET_SETUP_H
MESSAGE agc_load		/*File: agcal_load.c */
( const char *sRemoteHostname_a,
  volatile struct dsp_agc_cal *pcal_a
  );
MESSAGE agc_save		/*File: agcal_load.c */
( const char *sRemoteHostname_a,
  const struct dsp_agc_cal *pcal_a
  );
MESSAGE ant_load_setup		/* File: ant_load.c */
( const char *sRemoteHostname_a,
  volatile struct ant_manual_setup *pAntSetup_a );

MESSAGE ant_save_setup		/* File: ant_load.c */
( const char *sRemoteHostname_a,
  volatile const struct ant_manual_setup *pAntSetup_a );

MESSAGE color_save		/* File: iris_load.c */
( const char *sRemoteHostname_a,
  volatile const struct color_setup *pColor_a );

MESSAGE color_load		/* File: iris_load.c */
( const char *sRemoteHostname_a,
  volatile struct color_setup *pColor_a );
#endif  /* #ifdef SIGMET_SETUP_H */

#ifdef SIGMET_ANTENNA_LIB_H
MESSAGE bitex_load_conf
( const char *sRemoteHostname_a,
  volatile struct bitex_setup *pBitexSetup_a ) ;
MESSAGE bitex_save_conf
( const char *sRemoteHostname_a, 
  volatile const struct bitex_setup *pBitexSetup_a ) ;

MESSAGE bitexWgt_load_conf
( const char *sRemoteHostname_a,
  volatile struct bitexWgt_setup *pBitexWgtSetup_a ) ;
MESSAGE bitexWgt_save_conf
( const char *sRemoteHostname_a, 
  volatile const struct bitexWgt_setup *pBitexWgtSetup_a ) ;
#endif /* #ifdef SIGMET_ANTENNA_LIB_H */

#ifdef SIGMET_SETUP_H
  /* Companion load function is local to the 2 places it is called */
MESSAGE dsp_save_setup		/* File: dsp_load.c */
( const char *sRemoteHostname_a, 
  volatile const struct dsp_manual_setup *pdsp_a ) ;

void dspManualSetup_from_legacy	/* File: dsp_load.c */
( volatile       struct dsp_manual_setup    *current_a,
  volatile const struct dsp_manual_setup722 *legacy_a ) ;
void dspManualSetup_to_legacy	/* File: dsp_load.c */
( volatile       struct dsp_manual_setup722 *legacy_a,
  volatile const struct dsp_manual_setup    *current_a ) ;

FLT4 fsiggen_cal_lookup		/* File: zcal_load.c */
( const struct dsp_siggen_cal *pcal_a,
  SINT4 ivalue_a
  );
MESSAGE gain_load		/* File: gain_load.c */
( const char *sRemoteHostname_a, struct dsp_gain_cal *pgain_a
  );
MESSAGE gain_save		/* File: gain_load.c */
( const char *sRemoteHostname_a, const struct dsp_gain_cal *pgain_a
  );
#endif  /* #ifdef SIGMET_SETUP_H */
  
#ifdef SIGMET_SETUP_H
MESSAGE irisload		/*File iris_load.c */
( const char *sRemoteHostname_a,  volatile struct iris_setup *pIrisSetup_a
  );
MESSAGE irissave		/*File iris_load.c */
( const char *sRemoteHostname_a, volatile const struct iris_setup *pIrisSetup_a
  );
#endif  /* #ifdef SIGMET_SETUP_H */

#ifdef SIGMET_SETUP_H
MESSAGE license_load_setup      /* File: license_load.c */
( const char *sRemoteHostname_a,
  volatile struct license_setup *pLSetup_a );

MESSAGE license_save_setup      /* File: license_load.c */
( const char *sRemoteHostname_a,
  const struct license_setup *pLSetup_a );
#endif  /* #ifdef SIGMET_SETUP_H */

FILE *sigrfopen(const char *hostname_a, const char *path_a, const char *mode_a);
FILE *sigrcmd(const char *hostname_a, const char *path_a);
void  sigrclose(FILE *fp_a);

#define SETUP_MINVAL       0	/* Minimum value */
#define SETUP_MAXVAL       1	/* Maximum value */
#define SETUP_DEFVAL       2	/* Default value */
#define SETUP_TEST         3	/* Check Min/Max to determine validity */
#define SETUP_REPAIR       4	/* Replace invalid entries with default */
#define SETUP_CLASS        5	/* Classify types of structure elements */
#define SETUP_TYPEOUT      6	/* Print only relevant contents + comments */
#define SETUP_TYPEALL      7	/* Print entire contents + no comments */
#define SETUP_READIN       8	/* Read in a structure's contents */
#define SETUP_READIN_ERR   9	/*   (Giving complete error reports) */
#define SETUP_READIN_MOD  10	/*   (ERR + Only allow SLCLASS_IRISMOD elements) */
#define SETUP_READIN_MEM  11	/* Read from memory, not FILE* */

#define SLCLASS(ARG) (*(UINT1 *)(ARG))
#define SLCLASS_IRISMOD  0x01	/* IRIS value that can be modified while running */
#define SLCLASS_ENCODED  0x02	/* Value can not be seen as plain text in file */

MESSAGE setup_limits		/* File: setup_limits.c */
( const char *sname_a,		/* Name of structure */
  volatile void *item_a,	/* Pointer to structure */
  SINT4 ioper_a,		/* Operation to perform */
  void *file_a ) ;		/* Diagnostic messages, or NULL */

MESSAGE bitex_limits		/* File: bitex_limits.c */
( const char *sname_a, volatile void *item_a, SINT4 ioper_a, void *file_a ) ;
MESSAGE dsp_limits		/* File: dsp_limits.c */
( const char *sname_a, volatile void *item_a, SINT4 ioper_a, void *file_a ) ;
MESSAGE rcp_limits		/* File: rcp_limits.c */
( const char *sname_a, volatile void *item_a, SINT4 ioper_a, void *file_a ) ;
MESSAGE rda_limits		/* File: rda_limits.c */
( const char *sname_a, volatile void *item_a, SINT4 ioper_a, void *file_a ) ;

/* Used when reading from memory rather than from a FILE*
 */
struct lim_memory {
  char *sPointer ;
  SINT4 iSize ;
} ;

typedef MESSAGE (*LimitsProc)
  ( const char *sname_a, volatile void *item_a, SINT4 ioper_a, void *file_a ) ;
  
MESSAGE lim_loadFile
( const char *sRemoteHostname_a,
  const char *sFileName_a,
  const char *sStructName_a,
  volatile void *pStruct_a,
  LimitsProc func_limits_a );

MESSAGE lim_loadFileDir
( const char *sRemoteHostname_a,
  const char *sDirEnv_a,           /* Directory environment variable */
  const char *sFileName_a,
  const char *sStructName_a,
  volatile void *pStruct_a,
  LimitsProc func_limits_a );

MESSAGE lim_loadMemory
( struct lim_memory *pMemory_a,
  const char *sStructName_a,
  volatile void *pStruct_a,
  LimitsProc func_limits_a );

MESSAGE lim_saveFile
( const char *sRemoteHostname_a,
  const char *sFileName_a,
  const char *sStructName_a,
  volatile const void *pStruct_a,
  LimitsProc func_limits_a );

MESSAGE lim_saveFileDir
( const char *sRemoteHostname_a,
  const char *sDirEnv_a,           /* Directory environment variable */
  const char *sFileName_a,
  const char *sStructName_a,
  volatile const void *pStruct_a,
  LimitsProc func_limits_a );

MESSAGE lim_diffStructs
( volatile const void *pStructX_a,
  volatile const void *pStructY_a,
  const char *sStructName_a, LimitsProc func_limits_a,
  const char *sFormat_a, FILE *file_a ) ;

#ifdef SIGMET_PRODUCT_H
MESSAGE menu_load_pom_headers	/* File: menu_load.c */
( const char *sName_a,
  struct pom_save_sends_list *pPomHeaders_a );

MESSAGE menu_save_pom_headers        /* File: menu_load.c */
( const char *sName_a,
  const struct pom_save_sends_list *pPomHeaders_a );
#endif  /* #ifdef SIGMET_PRODUCT_H */

#ifdef SIGMET_SETUP_H  /* Must include setup.h first! */
#ifdef SIGMET_PRODUCT_H
  /* This subroutine reads just the default values into the structure. */
MESSAGE menu_load_pom_defaults
( struct device_output_options PomOptions_a[MAX_OUT_DEVICES] );

MESSAGE menu_load_pom_options          /* File: menu_load_pom.c */
( const char *sName_a,                     /* File name to load */
  struct device_output_options PomOptions_a[MAX_OUT_DEVICES] );

MESSAGE menu_save_pom_options       /* File: menu_load_pom.c */
( const char *sName_a,                    /* File name to load */
  const struct device_output_options PomOptions_a[MAX_OUT_DEVICES] );

#endif  /* #ifdef SIGMET_PRODUCT_H */
#endif  /* #ifdef SIGMET_SETUP_H */

UINT4 mtimeIrisConfigFile( const char *sFileName_a ) ;

#ifdef SIGMET_SETUP_H
MESSAGE RtdispLoadSetup
( const char *sRemoteHostname_a,
  volatile struct rtdisp_setup *pRtdispSetup_a ) ;
#endif  /* #ifdef SIGMET_SETUP_H */

#ifdef SIGMET_SETUP_H
MESSAGE RtdispSaveSetup
( const char *sRemoteHostname_a, 
  volatile const struct rtdisp_setup *pSetup_a ) ;
#endif  /* #ifdef SIGMET_SETUP_H */

#ifdef SIGMET_RVP8_H
MESSAGE rvp8_load_conf		/* File: dsp_limits.c */
( const char *sRemoteHostname_a, volatile struct rvp8NV *pRvp8NV_a ) ;
MESSAGE rvp8_save_conf		/* File: dsp_limits.c */
( const char *sRemoteHostname_a, volatile const struct rvp8NV *pRvp8NV_a ) ;

#ifdef SIGMET_RDASUBS_LIB_H
MESSAGE rvp8ts_load_conf
( const char *sRemoteHostname_a, volatile struct rvp8tsConfig *pConfig_a ) ;
MESSAGE rvp8ts_save_conf
( const char *sRemoteHostname_a, volatile const struct rvp8tsConfig *pConfig_a ) ;
#endif /* #ifdef SIGMET_RDASUBS_LIB_H */
#endif /* #ifdef SIGMET_RVP8_H */

#ifdef SIGMET_PCICARDS_LIB_H
#ifdef SIGMET_SOFTPLANE_LIB_H
MESSAGE spl_load_conf
( const char *sRemoteHostname_a, volatile struct splConfig *pSplConfig_a ) ;
MESSAGE spl_save_conf
( const char *sRemoteHostname_a, volatile const struct splConfig *pSplConfig_a ) ;
#endif /* #ifdef SIGMET_SOFTPLANE_LIB_H */
#endif /* #ifdef SIGMET_PCICARDS_LIB_H */

#ifdef SIGMET_SETUP_H
MESSAGE siggen_cal_load( struct dsp_siggen_cal *pcal_a ) ;
#endif  /* #ifdef SIGMET_SETUP_H */

MESSAGE stcwave_load		/* File: stcwave_load.c */
( FLT4 fstcwave_a[3]
  );
MESSAGE stcwave_save		/* File: stcwave_load.c */
( const FLT4 fstcwave_a[3]
  );
MESSAGE trigger_load		/* File: trigger_load.c */
( volatile FLT4 fstart_a[4][6],
  volatile FLT4 fwidth_a[4][6],
  volatile FLT4 fpol_time_a[4],
  volatile UINT2 *ilevel_a,
  volatile SINT2 *icount_a
  );
MESSAGE trigger_save		/* File: trigger_load.c */
( const FLT4 fstart_a[4][6],
  const FLT4 fwidth_a[4][6],
  const FLT4 fpol_time_a[4],
  const UINT2 *ilevel_a,
  const SINT2 *icount_a
  );

#ifdef SIGMET_PRODUCT_H
MESSAGE window_load_conf
( const char *sRemoteHostname_a,
  volatile const UINT4 iWindowNumber, 
  volatile struct WindowSetup *pWindowSetup_a ) ;
MESSAGE window_save_conf
( const char *sRemoteHostname_a, 
  volatile const UINT4 iWindowNumber, 
  volatile const struct WindowSetup *pWindowSetup_a ) ;
#endif

/* ***********************************
 * *                                 *
 * * Definitions for Limits Checking *
 * *     and ASCII File Formats      *
 * *                                 *
 * ***********************************
 */
#ifdef LIM_DEFINITIONS		/* Omit entirely unless needed... */

#define CFGINLINES   150	/* Number of lines to binary search at once */
#define CFGLINELEN   200	/* Maximum length of a SETUP file line */

struct lim_inLine {		/* Data for one input line */
  char sLine[ CFGLINELEN ] ;	/*   Text line (MUST be first, for bsearch() hack) */
  UINT1 lUsed ;			/*   This line's data has been used */
} ;
struct lim_inText {		/* Structure used during READIN */
  SINT4 nLines ;		/*   Number of lines inserted */
  struct lim_inLine lines[ CFGINLINES ] ; /* Data for each line */
  struct lim_inLine *perm[ CFGINLINES ] ; /* Sorted permutation line pointers */
} ;

MESSAGE lim_toplevel
( const char *sname_a,		/* Name of structure */
  volatile void *item_a,	/* Pointer to structure */
  SINT4 ioper_a,		/* Operation to perform */
  void *file_a,			/* Diagnostic messages, or NULL */
  MESSAGE (*lim_kernel_a)	/* Case handler function */
  ( const char *sname_a, void *item_a, SINT4 ioper_a,
    const char *spath_a, void *ioarg_a ) ) ;

char *slim_actual_item
( const char *spath_a,		/* Name of prefix portion */
  const char *sitem_a,		/* Name of the item (possibly dimensioned) */
  SINT4 idim1_a,		/* Possible dimensions */
  SINT4 idim2_a) ;

void lim_opTestRepairString
( char *sString_a,		/* String to be Tested/Repaired */
  SINT4 iLength_a,		/* Length of the string */
  FILE *file_a,			/* Where to write errors */
  const char *sItemName_a,  	/* Name of the structure element */
  UINT1 lRepair_a ) ;		/* Test vs Repair */

void lim_opTypeoutString
( char *sString_a,		/* String to be typed */
  SINT4 iLength_a,		/* Length of the string */
  FILE *file_a,			/* Where to write */
  const char *sItemName_a,  	/* Name of the structure element */
  SINT4 iClass_a ) ;		/* Classification of this element */

void lim_opReadinString
( char *sString_a,		/* String to be filled in */
  SINT4 iLength_a,		/* Length of the string */
  struct lim_inLine **pLine_a,	/* Processed line of text */
  MESSAGE *iStatus_a,		/* Error status, only written on error */
  SINT4 ioper_a,		/* Type of READIN being done */
  SINT4 iClass_a ) ;		/* Classification of this element */

FLT8 flim_opReadinScalar
( FLT8 fValue_a,		/* Pre-existing value */
  FLT8 fMin_a, FLT8 fMax_a,	/* Bounds */
  const char *sItemName_a, 	/* Name of the structure element */
  struct lim_inLine **pLine_a,	/* Processed line of text */
  MESSAGE *iStatus_a,		/* Error status, only written on error */
  SINT4 ioper_a,		/* Type of READIN being done */
  SINT4 iClass_a ) ; 		/* Classification of this element */

int ilim_cmpInText( const void *arg1_a, const void *arg2_a ) ;

void lim_opTestScalar
( FLT8 fValue_a,		/* Value to be tested */
  FLT8 fMin_a, FLT8 fMax_a,	/* Bounds */
  const char *sItemName_a, 	/* Name of the structure element */
  FILE *file_a,			/* Where to write */
  MESSAGE *iStatus_a ) ;	/* Error status, only written on error */

FLT8 flim_opRepairScalar
( FLT8 fValue_a,		/* Value to be tested */
  FLT8 fMin_a, FLT8 fMax_a,	/* Bounds */
  FLT8 fDef_a,			/* Default value */
  const char *sItemName_a, 	/* Name of the structure element */
  FILE *file_a ) ;		/* Where to write */

/* ======================================================================
 * Macros to make the definition of structures and scalars easy.
 * Each element of a structure is either another structure, or a
 * scalar. Special macros are provided in case either of those
 * types of elements are dimensioned.
 */
#define SUBSTRUCTURE( SNAME, ITEM ) { MESSAGE istt ; \
  sprintf( spath, "%s.%s", spath_a, #ITEM ) ; \
  istt = LIM_KERNEL ( #SNAME, &item->ITEM, ioper_a, spath, ioarg_a ) ; \
  if( istt != SS_NORMAL ) istatus = istt ; \
}

#define SUBSTRUCTURE_1D( SNAME, ITEM, DIM1 ) {  MESSAGE istt ; \
  for( idim1=0 ; idim1 < (DIM1) ; idim1++ ) { \
    sprintf( spath, "%s.%s[%d]", spath_a, #ITEM, idim1 ) ; \
    istt = LIM_KERNEL ( #SNAME, &item->ITEM[idim1], ioper_a, spath, ioarg_a ) ; \
    if( istt != SS_NORMAL ) istatus = istt ; \
  } \
}

#define SUBSTRUCTURE_2D( SNAME, ITEM, DIM1, DIM2 ) {  MESSAGE istt ; \
  for( idim1=0 ; idim1 < (DIM1) ; idim1++ ) { \
    for( idim2=0 ; idim2 < (DIM2) ; idim2++ ) { \
      sprintf( spath, "%s.%s[%d][%d]", spath_a, #ITEM, idim1, idim2 ) ; \
      istt = LIM_KERNEL ( #SNAME, &item->ITEM[idim1][idim2], ioper_a, \
                                  spath, ioarg_a ) ; \
      if( istt != SS_NORMAL ) istatus = istt ; \
    } \
  } \
}

/* Assignment coercion are done implicitly in C, and with explicit
 * conversion routines in C++.
 */
#ifdef __cplusplus
#define ASSIGNVALUE( OUT, IN ) AssignValue( &(OUT), IN )
#else
#define ASSIGNVALUE( OUT, IN ) OUT = (IN) ;
#endif

/* Perform operations on scalar items, or on arrays of them.  Use
 * SCALAR() to define elements having no class flags set.  Use
 * M_SCALAR() for elements that can be modified while IRIS is
 * running.
 */
#define   SCALAR( ITEM, MINVAL, MAXVAL, DEFVAL ) \
        xxSCALAR( ITEM, MINVAL, MAXVAL, DEFVAL, 0 )
#define M_SCALAR( ITEM, MINVAL, MAXVAL, DEFVAL ) \
        xxSCALAR( ITEM, MINVAL, MAXVAL, DEFVAL, SLCLASS_IRISMOD )
#define xxSCALAR( ITEM, MINVAL, MAXVAL, DEFVAL, CLASS ) { \
  sItem = slim_actual_item( spath_a, #ITEM, idim1, idim2 ) ; \
  switch( ioper_a ) { \
  case SETUP_MINVAL: item->ITEM = (MINVAL) ; break ; \
  case SETUP_MAXVAL: item->ITEM = (MAXVAL) ; break ; \
  case SETUP_DEFVAL: item->ITEM = (DEFVAL) ; break ; \
  case SETUP_CLASS: SLCLASS(&item->ITEM) = (CLASS) ; break ; \
  case SETUP_TEST: \
    lim_opTestScalar( (FLT8)item->ITEM, (FLT8)(MINVAL), (FLT8)(MAXVAL), \
		      sItem, (FILE *)ioarg_a, &istatus ) ; \
    break ; \
  case SETUP_REPAIR: \
    ASSIGNVALUE( item->ITEM, flim_opRepairScalar \
      ( (FLT8)item->ITEM, (FLT8)(MINVAL), (FLT8)(MAXVAL), (FLT8)(DEFVAL), \
      sItem, (FILE *)ioarg_a ) ) ; \
    break ; \
  case SETUP_TYPEOUT: \
  case SETUP_TYPEALL: \
    if( ioarg_a ) { \
      fprintf( (FILE *)ioarg_a, "%s = %.10G\n", sItem, (FLT8)item->ITEM ) ; \
    } \
    break ; \
  case SETUP_READIN: \
  case SETUP_READIN_ERR: \
  case SETUP_READIN_MOD: \
  case SETUP_READIN_MEM: \
    pLine = (struct lim_inLine **)bsearch( &sItem, ((struct lim_inText *)ioarg_a)->perm, \
                     ((struct lim_inText *)ioarg_a)->nLines, sizeof(void *), \
	             ilim_cmpInText ) ; \
    ASSIGNVALUE( item->ITEM, flim_opReadinScalar \
                   ( (FLT8)item->ITEM, (FLT8)(MINVAL), (FLT8)(MAXVAL), sItem, \
                     pLine, &istatus, ioper_a, (CLASS) ) ) ; \
    break ; \
  } \
}

/* Backward compatible version of SCALAR.  Only used for reading
 * in a value that used to be called something else.
 */
#define   RALACS( ITEM, MINVAL, MAXVAL, DEFVAL, OLDITEM ) \
        xxRALACS( ITEM, MINVAL, MAXVAL, DEFVAL, OLDITEM, 0 )
#define M_RALACS( ITEM, MINVAL, MAXVAL, DEFVAL, OLDITEM ) \
        xxRALACS( ITEM, MINVAL, MAXVAL, DEFVAL, OLDITEM, SLCLASS_IRISMOD )
#define xxRALACS( ITEM, MINVAL, MAXVAL, DEFVAL, OLDITEM, CLASS ) { \
  sItem = slim_actual_item( spath_a, #OLDITEM, idim1, idim2 ) ; \
  switch( ioper_a ) { \
  case SETUP_READIN: \
  case SETUP_READIN_ERR: \
  case SETUP_READIN_MOD: \
  case SETUP_READIN_MEM: \
    pLine = bsearch( &sItem, ((struct lim_inText *)ioarg_a)->perm, \
                     ((struct lim_inText *)ioarg_a)->nLines, sizeof(void *), \
                     ilim_cmpInText ) ; \
    ASSIGNVALUE( item->ITEM, flim_opReadinScalar \
                   ( (FLT8)item->ITEM, (FLT8)(MINVAL), (FLT8)(MAXVAL), sItem, \
                     pLine, &istatus, ioper_a, (CLASS) ) ) ; \
    break ; \
  } \
}

#define   SCALAR_1D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1 ) \
        xxSCALAR_1D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, 0 )
#define M_SCALAR_1D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1 ) \
        xxSCALAR_1D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, SLCLASS_IRISMOD )
#define xxSCALAR_1D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, CLASS ) { \
  for( idim1=0 ; idim1 < (DIM1) ; idim1++ ) \
    xxSCALAR( ITEM[idim1], MINVAL, MAXVAL, DEFVAL, CLASS ) ; \
}

#define   SCALAR_2D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, DIM2 ) \
        xxSCALAR_2D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, DIM2, 0 )
#define M_SCALAR_2D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, DIM2 ) \
        xxSCALAR_2D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, DIM2, SLCLASS_IRISMOD )
#define xxSCALAR_2D( ITEM, MINVAL, MAXVAL, DEFVAL, DIM1, DIM2, CLASS ) { \
  for( idim1=0 ; idim1 < (DIM1) ; idim1++ ) \
    for( idim2=0 ; idim2 < (DIM2) ; idim2++ ) \
      xxSCALAR( ITEM[idim1][idim2], MINVAL, MAXVAL, DEFVAL, CLASS ) ; \
}

/* Perform operations on character strings.  See notes for SCALAR
 * regarding prefix conventions.
 */
#define   STRING( ITEM, DEFVAL ) xxSTRING( ITEM, DEFVAL, 0 )
#define M_STRING( ITEM, DEFVAL ) xxSTRING( ITEM, DEFVAL, SLCLASS_IRISMOD )
#define xxSTRING( ITEM, DEFVAL, CLASS ) { \
  sItem = slim_actual_item( spath_a, #ITEM, idim1, idim2 ) ; \
  switch( ioper_a ) { \
  case SETUP_DEFVAL: strcpy( item->ITEM, DEFVAL ) ; break ; \
  case SETUP_CLASS: SLCLASS(&item->ITEM) = (CLASS) ; break ; \
  case SETUP_TEST: \
  case SETUP_REPAIR: \
    lim_opTestRepairString( item->ITEM, sizeof(item->ITEM), (FILE *)ioarg_a, \
                            sItem, (ioper_a == SETUP_REPAIR) ) ; \
    break ; \
  case SETUP_TYPEOUT: \
  case SETUP_TYPEALL: \
    lim_opTypeoutString( item->ITEM, sizeof(item->ITEM), (FILE *)ioarg_a, \
                         sItem, (CLASS) ) ; \
    break ; \
  case SETUP_READIN: \
  case SETUP_READIN_ERR: \
  case SETUP_READIN_MOD: \
  case SETUP_READIN_MEM: \
    pLine = (struct lim_inLine **)bsearch( &sItem, ((struct lim_inText *)ioarg_a)->perm, \
		     ((struct lim_inText *)ioarg_a)->nLines, sizeof(void *), \
                     ilim_cmpInText ) ; \
    lim_opReadinString( item->ITEM, sizeof(item->ITEM), pLine, &istatus, \
	 	        ioper_a, (CLASS) ) ; \
    break ; \
  } \
}

/* Backward compatible version of STRING.  Only used for reading
 * in a value that used to be called something else.
 */
#define   GNIRTS( ITEM, OLDITEM ) xxGNIRTS( ITEM, OLDITEM, 0 )
#define M_GNIRTS( ITEM, OLDITEM ) xxGNIRTS( ITEM, OLDITEM, SLCLASS_IRISMOD )
#define xxGNIRTS( ITEM, OLDITEM, CLASS ) { \
  sItem = slim_actual_item( spath_a, #OLDITEM, idim1, idim2 ) ; \
  switch( ioper_a ) { \
  case SETUP_READIN: \
  case SETUP_READIN_ERR: \
  case SETUP_READIN_MOD: \
  case SETUP_READIN_MEM: \
    pLine = bsearch( &sItem, ((struct lim_inText *)ioarg_a)->perm, \
                     ((struct lim_inText *)ioarg_a)->nLines, sizeof(void *), \
                     ilim_cmpInText ) ; \
    lim_opReadinString( item->ITEM, sizeof(item->ITEM), pLine, &istatus, \
	 	        ioper_a, (CLASS) ) ; \
    break ; \
  } \
}

#define   STRING_1D( ITEM, DEFVAL, DIM1 ) xxSTRING_1D( ITEM, DEFVAL, DIM1, 0 )
#define M_STRING_1D( ITEM, DEFVAL, DIM1 ) xxSTRING_1D( ITEM, DEFVAL, DIM1, SLCLASS_IRISMOD )
#define xxSTRING_1D( ITEM, DEFVAL, DIM1, CLASS ) \
  for( idim1=0 ; idim1 < (DIM1) ; idim1++ ) xxSTRING( ITEM[idim1], DEFVAL, CLASS ) ;

/* Macro to insert a comment annotation in the typeout text.  The
 * first character in each comment line must be either whitespace or
 * the '#'.
 */
#define COMMENTEXT( TEXT ) \
  if( ioper_a == SETUP_TYPEOUT ) fprintf( (FILE *)ioarg_a, TEXT ) ;

#define COMMENTFUNC( FUNC, ARG ) \
  if( ioper_a == SETUP_TYPEOUT ) FUNC( (FILE *)ioarg_a, ARG ) ;

/* If the operation we are performing might override an entry value of
 * an item, then use the more recently "thought about" value instead.
 */
#define CONDITIONAL_DISCRIMINANT \
  if( (ioper_a == SETUP_REPAIR    ) || \
      (ioper_a == SETUP_READIN    ) || \
      (ioper_a == SETUP_READIN_ERR) || \
      (ioper_a == SETUP_READIN_MOD) || \
      (ioper_a == SETUP_READIN_MEM) )

/* This macro is TRUE if the operation being performed should be
 * carried out using the actual dimensions of an array, rather
 * than the maximum allocated size.
 */
#define USEACTUALSIZES( OPER ) \
  ( ((OPER) == SETUP_TEST   ) || \
    ((OPER) == SETUP_REPAIR ) || \
    ((OPER) == SETUP_TYPEOUT) )

#endif /* #ifdef LIM_DEFINITIONS */

#endif /* #ifndef MESSAGE_ONLY */

#ifdef __cplusplus
}
/* Overloaded function to convert a FLT8 value to all possible other
 * units.
 */
void AssignValue( UINT4 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue( UINT2 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue( UINT1 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue( SINT4 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue( SINT2 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue( SINT1 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue(  FLT8 *pValue_a, FLT8 fNewValue_a ) ;
void AssignValue(  FLT4 *pValue_a, FLT8 fNewValue_a ) ;

#endif
