Listing 5

Example 5. Public Interface Between MEL and Any
Application Program Using It. (Excerpted from mel.h header file.)

/* if using MEL for input (#define MEL_INPUT), then must
  define the MEL input data object: */
#ifdef MEL_INPUT

/* firstly, define input constants (all must be
  CUSTOMIZED for specific application program): */

#define MELI_MAX_DESCRIP_STR_LEN 256
   /* maximum number of characters in any input descriptor
     string. */
#define MELI_MAX_PARAMS 6
   /* maximum number of parameters for any descriptor (min
     num = 1). */
#define MELI_MAX_PARAM_STR_LEN 80
#define MELI_MAX_PARAM_ARRAY_STR_LEN 1
   /* largest allowable parameter string lengths (min size
     = 1) */
#define MELI_MAX_PARAM_INT_ARRAY_LEN 1
#define MELI_MAX_PARAM_REAL_ARRAY_LEN 1
#define MELI_MAX_PARAM_STR_ARRAY_LEN 1
   /* maximum number of elements in parameter data arrays
     (min = 1). */
#define MELI_UNITS_STR_LEN 80
   /* maximum length of units associated with any param
     (min = 1) */

/* secondly, define input data structures: */

union meli_param_data {
   int integer;  /* also holds boolean type */
   double real;
   char string[MELI_MAX_PARAM_STR_LEN+1];
   int integer_array [MELI_MAX_PARAM_INT_ARRAY_LEN];
   double real_array[MELI_MAX_PARAM_REAL_ARRAY_LEN];
   char string_array [MELI_MAX_PARAM_STR_ARRAY_LEN]
             [MELI_MAX_PARAM_ARRAY_STR_LEN+1];
};
/* this is used for input parameter data. it may either be
  an integer, real, string, array of integers, array of
  reals, or an array of strings. (to save space a union was
  used.) */

/* thirdly, define input variables: */

char meli_descriptor_string[MELI_MAX_DESCRIP_STR_LEN+1];
   /* global storage for the input descriptor string. */

/* lastly, define input functions (typically they return 0
  if no error encountered, else some nonzero error
  code): */

int meli_file(FILE *meli_file_handle);
   /* read a descriptor string from the input stream and
     call meli(). also, put copy of string read into
     meli_descriptor_string. */
int meli(void);
   /* translate meli_descriptor_string and put information
     into a private data structure (meli_datum). */
char *meli_descrip_type (void);
   /* return pointer to name of type of descriptor read by
     meli(). */
int meli_num_params(void);
   /* return number of parameters read by meli(). */
int meli_param(int param_num, char *param, union
   meli_param_data *data, char *units, int *array_len, int
   *unknown_flag);
   /* fill arguement list with param_num'th parameter read
     by meli(). (start with param_num = 0.) */
int meli_data(char *param, union meli_param_data *data,
   char *units, int *array_len, int *unknown_flag);
   /* see if *param was input. if it was, then fill
     argument list with data from meli_datum. */

#endif /* MEL_INPUT */

/* if using MEL for output, must define the MEL output data
  object: */
#ifdef MEL_OUTPUT

/* firstly, define output constants (all must be
  CUSTOMIZED): */

#define MELO_MAX_DESCRIP_STR_LEN 256
   /* how many characters can be in an output descriptor
     string? */
#define MELO_MAX_PARAMS 6
   /* maximum number of parameters for any descriptor. */
#define MELO_MAX_PARAM_STR_LEN 80
#define MELO_MAX_PARAM_ARRAY_STR_LEN 1
   /* largest allowable parameter string length. */
#define MELO_MAX_PARAM_INT_ARRAY_LEN 1
#define MELO_MAX_PARAM_REAL_ARRAY_LEN 1
#define MELO_MAX_PARAM_STR_ARRAY_LEN 1
   /* maximum number of elements in array of parameter
     data. */
#define MELO_UNITS_STR_LEN 80
   /* maximum string length of any units associated with a
     param. */

/* secondly, define output data structures: */

union melo_param_data {
   int integer;
   double real;
   char string[MELO_MAX_PARAM_STR_LEN+1];
   int integer_array[MELO_MAX_PARAM_INT_ARRAY_LEN];
   double real_array[MELO_MAX_PARAM_REAL_ARRAY_LEN];
   char string_array[MELO_MAX_PARAM_STR_ARRAY_LEN]
             [MELO_MAX_PARAM_ARRAY_STR_LEN+1];
};
/* this is for output parameter data. it may either be an
  integer, real, string, array of integers, array of reals, or
  an array of strings. (to save space a union was used.) */

/* thirdly, define output variables: */

char melo_descriptor_string[MELO_MAX_DESCRIP_STR_LEN+1];
   /* global storage for the output descriptor string. */

/* lastly, define output functions (typically return 0 if no
  error): */

int melo_init(char *descrip_type);
   /* initialize private data structure (melo_datum) to
     accept parameter data from following functions.
     output descriptor type will be descrip_type. returns
     0 if no errors were encountered. */
int melo_data(char *param, union melo_param_data *data, char
   *units, int array_len, int unknown_flag);
   /* put data for parameter *param into the proper place
     in melo_datum. returns zero if no errors were
     encountered. */
void melo(int melo_verbose_flag);
   /* takes the information in melo_datum and translates it
     into melo_descriptor_string. user must set
     melo_verbose_flag = 1 to make output as readable as
     possible, set it equal to zero to make output as
     terse as possible (and still remain in MEL
     format). */
int melo_file(FILE *melo_file_handle, int melo_verbose_flag);
   /* take the information in melo_datum, translate it into
     melo_descriptor string, and output it to file. */

#endif /* MEL_OUTPUT */

/* now define data objects common to both input and
  output: */

/* if an error occurs, MEL will try and tell you what
  happened. so define required error handling
  information: */

#define MEL_MAX_ERR_MSG_LEN 80

struct mel_errors {
   enum {    /* which error occured? */
      mel_no_err,
      mel_read_err,
      mel_write_err,
      mel_end_of_file_err,
      mel_end_of_data_err,
      mel_syntax_err,
      mel_unknown_descrip_name_err,
      mel_unknown_param_name_err,
      mel_missing_param_name_err,
      mel_param_data_err,
      mel_missing_paren_err,
      mel_too_many_param_err,
      mel_missing_bracket_err,
   } type;
   int, start_line;  /* on which lines did err occur? */
   int end_line;    /* (meaningful for input only.) */
   char msg[MEL_MAX_ERR_MSG_LEN+1];
          /* additional info describing err */
} mel_err;  /* (not same as messages below). */

#define MEL_MAX_NUM_ERR_MESSAGES 13

#ifdef MEL-INIT

/* the following describes each type of enumerated error: */
char mel_err_msg[MEL_MAX_NUM_ERR_MESSAGES]
          [MEL_MAX_ERR_MSG_LEN+1]
   ={"No errors encountered",
     "Can't read file",
     "Can't write file",
     "Unexpected end of file encountered",
     "End of input data encountered",
     "Descriptor/parameter syntax error",
     "Unknown descriptor name",
     "Unknown parameter name",
     "A (or another) parameter name was expected but is "
        "missing",
     "Unable to read parameter value(s) for this "
        "descriptor",
     "Missing right parenthesis while reading units",
     "Too many (or duplicate) parameters given for this "
        "descriptor",
     "Missing brackets around array data"};

#else

extern char mel_err_msg[MEL_MAX_NUM_ERR_MESSAGES]
             [MEL_MAX_ERR_MSG_LEN+1];

#endif /* MEL_INIT */