/* defgb.h								*/
/*	Supplies constants to defgb package.				*/
/*	Generally, constants are created from user-supplied compiler	*/
/*   -D values and defaults defined somewhere in this file		*/
/*	Some constants are checked for permissible values		*/
/*	Note that "compile-time initialization" can also be done in	*/
/*   the code modules.  Further, run-time initialization can take place	*/
/*   before the system "starts running".  Besides the obvious data	*/
/*   declaration statements, check the init* modules in ioopen_routines	*/

#define DEFGBH_VERSION "defgb.h  version 5.0  30 Aug 2004"
/*	30 Aug 04.  Move MAXLEVELS, ATTRIB_SEP, ATTRIB_DELIMS, 		*/
/*		NO_SUCH_DEVICE to core.h				*/
/*	20 Jul 04.  NO_SUCH_DEVICE (probably belongs in core.h)		*/
/*	13 Jul 04.  Move W_EXTEND to core.h				*/
/*	25 Mar 04.  Add stat structure to outsink structure		*/
/*	 3 Mar 04.  Change to defn of FULL_DEFGBH_VERSION		*/
/*	20 Feb 04.  More stuff to core.h & utils.h			*/
/*	11 Feb 04.  Split off some of this into utils.h			*/
/*		    Remove a few hard-coded things in favor of their	*/
/*		core.h-parametrized values				*/
/*	 4 Feb 04.  Add FULL_DEFGBH_VERSION, which includes versions of	*/
/*		defgb.h's "sub-.h" files				*/
/*	30 Jan 04.  Try splitting some non-defgb stuff out into a	*/
/*		"truly universal" .h file. 				*/
/*		    STDxxx_DEVICE -> STDxxx_NAME			*/
/*		[Begin 5.0]						*/
/*	29 Aug 03.  Define strcasecmp for VMS				*/
/*		    #include INNEROPTIONS, math.h			*/
/*		[Begin 4.8]						*/
/*	 9 Jul 03.  TRANSVAR macro					*/
/*		    Add .buf_size to fileinfo struct			*/
/*	 3 Jul 03.  COPY_INTO_FIXED_LEN_BUFFER macro			*/
/*		[Begin 4.7]						*/
/*	13 Jun 03.  datacomments opt file stuff				*/
/*		    NOT_VALID defn					*/
/*	23 May 03.  Bug fix: length of varlistopts wjstbl		*/
/*	14 May 03.  Enhancements to latlon structure			*/
/*		    Possible fix - default lat/lon conventions &	*/
/*		 formats never seem to have been defined		*/
/*		[Begin 4.6]						*/
/*	 1 Mar 02.  Parametrize time zone conversion types		*/
/*		[Begin 4.5]						*/
/*	[Move pre-2002 comments to defgb_revision.doc. 13 Jun 03]	*/

#include "utils.h"
#include "path_info_routines.h"		/* core.h #include'd here	*/

#define FULL_DEFGBH_VERSION \
 DEFGBH_VERSION"/"FULL_PATH_INFO_ROUTINESH_VERSION"/"FULL_UTILSH_VERSION

#include INNEROPTIONS

#define TRANSVAR_CALL(synonym,variable) \
	transvar((synonym),sizeof((synonym)),(variable))

/*	Characters							*/
/* COMMENT_CHAR			Character in first position of data	*/
/*			    record which indicates that what follows is	*/
/*			    a comment					*/
/* INDIRECT_FILE_CHAR		Prefix character that indicates that	*/
/*			    file name which follows contains name of	*/
/*			    desired file (instead of being that file)	*/
/* LEVEL_CONTINUATION_CHAR 	Character in variable list that indi-	*/
/*			    cates that a new level begins at this point	*/
/* SCRIPT_PARAM_SEP		Character which separates shell script	*/
/* 			    file name from its parameters		*/
/* OMIT_FROM_TAG_CHAR		Character in METHOD_NAME which, if	*/
/*			    present, indicates that it, what follows,	*/
/*			    and any immediately preceding blanks are to	*/
/*			    be omitted from the tag on inserted 	*/
/*			    tags (see diagnostics optional file)	*/
/* OBJECT_PARAM_STRING_SEP	Within a data source string that in-	*/
/*			    dicates a JGOFS object, the character that	*/
/*			    separates parameters within the parameter	*/
/*			    string (if any) of that object		*/
/* QUERY_STRING_CHAR		Char in URL that separates PATH_INFO	*/
/*			    from QUERY_STRING				*/
#define COMMENT_CHAR '#'
#define INDIRECT_FILE_CHAR '@'
#define LEVEL_CONTINUATION_CHAR '>'
#define SCRIPT_PARAM_SEP ' '
#define OMIT_FROM_TAG_CHAR '('
#define OBJECT_PARAM_STRING_SEP ','
#define QUERY_STRING_CHAR '?'

  /*  Params for building a "wjstbl" (see doc in create_wjstbl)		*/
  /*    These characters must not conflict with characters that can	*/
  /*	appear in table entries, and routines that build tables should	*/
  /*	check.  Easiest way to do this is to make them binary, but	*/
  /*	not sure if this can be done w/white space character, which is	*/
  /*	sometimes used to terminate a scanf				*/
  /*	Routines that decode tables do not need to know these		*/
  /*	characters since the separator is the first character of	*/
  /*	a table and the white space character is the last.  If used	*/
  /*	when decoding, be sure table being decoded was built with them	*/
#define DEFAULT_WJSTBL_WHITE_SPACE '\v'
#define DEFAULT_WJSTBL_SEPARATOR 1

/*    Strings								*/
/* *_ENTRY_SEPARATORS		Characters which separate consecutive	*/
/*			    entries in an optional file.  Data struc-	*/
/*			    ture has room for a per-option string,	*/
/*			    but in general, the default is used.  If a	*/
/*			    per-option is desired, define it here and	*/
/*			    use it in init code (probably get_files)	*/
/*			    If null, whole record is 1 entry		*/
/*			    If non-null, should share same whitespace	*/
/*			    chars as *ITEM_SEPARATORS, w/ at least 1	*/
/*			    unique non-whitespace char			*/
/* *_SEPARATORS 		Characters which separate items within 	*/
/* 			    entries in an input file.  See *_ENTRY_SEP-	*/
/*			    ARATORS comment above			*/
/* DEFAULT_ENTRY_SEPARATORS	Separators between "pairs" for "common	*/
/*			    format" opt files.  See DEFAULT_ITEM_	*/
/*			    SEPARATORS					*/
/* DEFAULT_ITEM_SEPARATORS	Separators within "pairs" for "common	*/
/*			    format" opt files.  Must be disjoint from	*/
/*			    DEFAULT_ENTRY_SEPARATORS.  Whitespace	*/
/*			    characters go w/innermost parsing unit,	*/
/*			    which is ITEM				*/
/* REMOVAL_SEPARATORS		Separators for removal opt file		*/
/* REQUIRED_SEPARATORS		Characters which must appear in 	*/
/*			    SEPARATORS string (& hence not in data)	*/
/*			    Reason is that rest of system assumes this,	*/
/*			    so we don't want to accept data that will	*/
/*			    be unusable...				*/
/* DEFAULT_SEPARATORS		Default separators for data files	*/
/* DEFAULT_ALT_SEPARATORS	Default alternate separators		*/
/* COMM_TRUNC_IND		String which indicates truncated comment*/
/* OBJECT_PARAM_STRING_DELIM	Within a data source string that in-	*/
/*			    dicates a JGOFS object, the delimiters that	*/
/*			    surround the parameter string of that object*/
/* TAG_DELIM			Characters that surround comment tag	*/
/* DEFAULT_ERR_PREFIX		Default for ERR_PREFIX string		*/
/* NULL_INPUT			String that represents non-existent	*/
/*			    input.  Will provide a "missing value"	*/
/*			    line for such devices, if necessary		*/
/* FLAG_FOR_COLL_FROM_OBJOBJ	String which, if specified, enables	*/
/*			    COLL_FROM_OBJOBJ stuff.  It's looked for in	*/
/*			    optional file and environment, and is put	*/
/*			    into environment.  Needs coordination.	*/
/*			    Uppercased version of this string is used	*/
/*			    as environment variable name		*/
/* DEFAULT_COLL_FROM_OBJOBJ_OBJ	Default for COLL_FROM_OBJOBJ_OBJ.  See	*/
/*			    below					*/
/* DEF_QUOTES		    Quote chars def removed from tokens.  It	*/
/*			    didn't treat quotes the way we do, but if	*/
/*			    the token is properly quoted, behavior will	*/
/*			    be the same.  Some of the special treatment	*/
/*			    of tokens surrounded by these quotes	*/
/*			    happens in outer, which doesn't use this	*/
/*			    parametrization				*/
/* UNPRINT_REPL_CHARS	    Characters that can be used to replace un-	*/
/*			    printable characters in error messages	*/
/*			    Order generally determines which char gets	*/
/*			    used.  Repeats at end are for those deter-	*/
/*			    minations that pick the "last OK" char in-	*/
/*			    stead of the "first OK" char		*/
#define DEFAULT_ENTRY_SEPARATORS ";"
#define DEFAULT_ITEM_SEPARATORS "=\n \t"
#define REMOVAL_SEPARATORS "\n,; \t"
#define REQUIRED_SEPARATORS "\n\t"
#define DEFAULT_SEPARATORS "\n ,\r\t"
#define DEFAULT_ALT_SEPARATORS "\'\'"
#define COMM_TRUNC_IND " ..."
#define OBJECT_PARAM_STRING_DELIM "()"
#define TAG_DELIM "{}"
#define DEFAULT_ERR_PREFIX JGOFS_ERR_PREFIX	/* Defined in core.h	*/
#define NULL_INPUT NULL_DEVICE			/* Defined in core.h	*/
#define FLAG_FOR_COLL_FROM_OBJOBJ "varname_for_level1_specs"
#define DEFAULT_COLL_FROM_OBJOBJ_OBJ "/list_level1_specs"
#define DEF_QUOTES "\"\""
#define UNPRINT_REPL_CHARS "?@#$&*%!|~^#@?"
/*	Configurable strings-see defgb.h.  Default values come from	*/
/*	this file							*/
/* ERR_PREFIX								*/
/* ALT_SEPARATORS							*/
/* SEPARATORS								*/
/* COLL_FROM_OBJOBJ_OBJ 						*/

  /*  Next statement defines default order of optional file types in  	*/
  /*    indirect input file						*/
  /*  Descriptors are put into place at runtime in init_file_structs,	*/
  /*    among other places.						*/
  /*  Do not change the values of these, since it could break indirect	*/
  /*    files that do not keyword their entries				*/
  /*  Don't know how to parametrize so max value of defines gets to be	*/
  /*    size of array.  						*/
#define DATAFILE 0
#define TRANSVAR 1
#define INPWIDTHS 2
#define REMOVALS 3
#define TIMEDATEPARAMS 4
#define DIAGNOSTICS 5
#define LATLONPARAMS 6
#define DATAFIELDOPTS 7
#define DISPWIDTHS 8
#define VARLIST 9
#define VARLISTOPTS 10
#define DATACOMMENTS 11
#define COMMENTSOURCE 12
#define NFILETYPES 13

/************************************************************************/
/*		Datafield options					*/
    /*  Table contains the 5 keywords (max size 46), 3 TRUE/FALSEs,	*/
    /*  2 separator strings (for convenience, use same size as FALSE;	*/
    /*  namely, 5) and, for each keyword/variable pair, 2 separators	*/
    /*	and a blank							*/
#define NUM_DATAFIELDOPTS 5
#define DATAFIELDOPTS_WJSTBL NUM_DATAFIELDOPTS*(46 + 5 +2 +1)

/************************************************************************/
/*		Time/date options					*/

  /*  Next 2 kind of arbitrary.  With my luck I'll live until 2100...	*/
#define YEAR_MIN 1800
#define YEAR_MAX 2100

  /*  Pick next flag carefully.  For example, -1 cannot be used since	*/
  /*  is a valid time offset.  Fragments can have this flag for far	*/
  /*  more reasons than their input is missing				*/
#define MISSING_TIME_FLAG -9999

struct cumtime {
    /*  Save latest time/date info that passes through calc_timedate.	*/
    /*  It may save calculations.  Code must check that this info is	*/
    /*  applicable to the calculations, however ... mostly done while	*/
    /*  setting up in get_timedateparams				*/
    /*  I suspect that as of v 1.1, these variables (except		*/
    /*  leapyear) could be replaced with outtime[x_FRAG].val, but this	*/
    /*  seems to work...						*/
    /*	  Leap year info is all we want.  However, need to know if	*/
    /*	  saved leap year is valid; hence save year as flag.  While	*/
    /*    we're at it, we use saved year to avoid leap year recalc.	*/
    /*    year is init'ed in init_time_structs				*/
  int year;
  Logical leapyear;
    /*	Process Julian day exactly once and save results in month & day	*/
    /*	Whichever output (day or month) occurs first does calculation;	*/
    /*	the other output just copies the saved value			*/
    /*	Ditto for 24-hour time						*/
  int month,day;
  int hour,minute;
    /*  Save pieces of HHMM time displacement for time zone conversion	*/
  int hours_offset,minutes_offset;
};

  /*		fraction stuff						*/
struct timefrac {
  double frac;		/*  0 <= frac < 1.  Contents are described by	*/
			/*  fractype; vary as we go along		*/
  int julday;		/*  Fractional year input immediately changed	*/
			/*  into this, so that processing fractional	*/
			/*  years is exactly processing the appropriate	*/
			/*  # of julian days				*/
  int fracdigits;	/*  Starts out as number of significant digits	*/
			/*  in fractional part of input string.  Used	*/
			/*  in output of minutes and/or seconds data	*/
			/*  (guess it should be one or other!), so is	*/
			/*  modified w/o changing its variable name	*/
  Logical frac_missing;	/*  Flag for datum in a particular input record	*/
  Logical fracyear;	/*  Set if frac year fragment type is one of	*/
			/*  the several fractional year types.		*/
  char fractype;	/*  Type of data in frac variable		*/
};

  /* wjstbl-format strings for recognized time zone abbreviations with	*/
  /* their displacements.  Displacement is from UTC (which, when added	*/
  /* to UTC, gives the local time).  Takes HH or HHMM format; leading + */
  /* optional, as are leading zeros.					*/
  /* Need separate table for DST since DST zone name conflicts with 	*/
  /* other possible DST input						*/
#define TZTBL \
	"/PST/-8 /MST/-7 /CST/-6 /EST/-5 /AST/-4 /NST/-0330 /GMT/0 /UTC/0 "
#define TZDSTTBL \
	"/PDT/-7 /MDT/-6 /CDT/-5 /EDT/-4 /ADT/-3 /NDT/-0230 "

#define NUM_OUTTIMES 10
  /*  Size of TIMEDATE_WJSTBL changes if lengths of next 2 change	*/
#define TIMEDATE_SEQUENCE_PREFIX "time"
#define TIMEDATE_INPUT_KEYWORD_PREFIX "invar"

    /*  Types of time/date data fragments				*/
#define YEAR_FRAG 0
#define MONTH_FRAG 1
#define DAY_FRAG 2
#define HOUR_FRAG 3
#define TIME_OFFSET_FRAG 4
#define JULIAN_FRAG 5
#define NUM_OUTTIME_VARIABLES 6	/* Count.  keep = last frag + 1		*/
      /*  There is one output variable corresponding to each of the	*/
      /*  input fragments above.  (JULIAN_FRAG is not an input frag,	*/
      /*  though.  Long story)  The variables are: 24 hour time w/opt	*/
      /*  fract min, 4 digit year, month, day, and signed 4 digit	*/
      /*  offset from prime meridian.  Output variable can include	*/
      /*  information from the rest of the input fragments, whose list	*/
      /*  continues below						*/
#define MINUTE_FRAG 6
#define SECOND_FRAG 7
#define FRACTION_FRAG 8
#define DST_FRAG 9
#define AMPM_FRAG 10
#define NUM_TIMEDATE_FRAGS 11	/* Count.  keep = last frag + 1		*/

    /*  A single valid format could theoretically specify every output	*/
    /*  time variable as well as skip an arbitrary number of fields, as	*/
    /*  well has have an arbitrary number of punctuation characters.	*/
    /*  We also stick a %1s (length 3) on the end of each input format	*/
    /*  to check for extra characters in an input field			*/
    /*  A single format conversion specifier can be as big as 21	*/
    /*  (%*99[A-Z,a-z,0-9,+,-]  see code).				*/
    /*  Allow for as many skipped fields as valid ones, and		*/
    /*  15 punctuation characters.  We do NOT check overflow for this	*/
    /*  buffer in the code (since we build it char by char), so it's	*/
    /*  grossly oversized...						*/
#define MAXLEN_TIMEDATE_INPFORMAT 3 + (2 * NUM_OUTTIME_VARIABLES * 21) + 15

    /*  Allow for hhmm.mmmmm, which should be enough precision		*/
    /*  This is well-named, but was being used for the fragbuf size.	*/
    /*    fragbufs hold input data, not output data.  Sigh		*/
#define MAX_OUTTIME_PRECISION 5  
#define MAXLEN_OUTTIME_VARIABLE  5 + MAX_OUTTIME_PRECISION

struct intime {
  int var;		/* Input variable w/time info			*/
  int fragbuf_index;	/*     Index into vector of length numfrags.	*/
			/* Each vector element is a pointer to a buffer	*/
			/* that will hold a fragment.  Buffers are in	*/
			/* order that the fragments appear in this	*/
			/* input variable				*/
  int nstrings;		/* Number of substrings in input variable	*/
  int nfrags_in_substring;
			/* 	If nstrings = 1, how many frags does it	*/
			/* contain?  At present, at most 2 (the 2nd	*/
			/* being the decimal portion of int portion.)	*/
			/* 	Also a flag for whether input template	*/
			/* is widthless (0 = no; >0 = yes)		*/
  char format[MAXLEN_TIMEDATE_INPFORMAT+1]; /* sscanf format string	*/
			/* that gets substrings from variable.		*/
};

  /*  Add offset to utc to get local... that's how whole program is	*/
  /*  supposed to work!							*/
#define CONVERT_LOCAL_TO_UTC 1
#define NO_TIME_ZONE_CONVERSION 0
#define CONVERT_UTC_TO_LOCAL -1

struct outtime {
  int var;		/* Output time/date variable that will include	*/
			/*   this fragment				*/
  int lev;		/* Level var occurs on				*/
  int intime_index;	/* Index of intime structure describing		*/
			/*   input variable from which fragment comes	*/
  int val;		/* Temp buffer for values of this fragment as	*/
			/*   we do processing				*/
  int max;		/* Maximum value for this fragment.  Fixed for	*/
			/*   some fragments, variable for others...	*/
			/*   Largest permissible value for some frags,	*/
			/*   smallest impermissible value for others...	*/
  char *var_type;	/* Name of output variable (not fragment)	*/
			/*   corresponding to this structure		*/
  char *fmt;		/* Output format for this fragment		*/
			/*   Set in init_time_structs			*/
  char fragbuf[DATUMSIZE+1]; 		/* Fragment buffer		*/
  char source_field_type[1+1];		/* Kind of field fragment	*/
			/* was derived from.  Used as flag telling if	*/
			/* fragment found & in error msg if found twice */
			/* String for err msg convenience		*/
  signed char conv;	/* Output conversion info.  Meaning depends on	*/
			/* structure.					*/
			/*  For HOUR (representing hr/min/sec),		*/
			/* indicates UTC/local conversion.		*/
			/*  For JULIAN, it's a template letter indica-	*/
			/* ting the type of julian output.  See tem-	*/
			/* plate documentation or code			*/
};

/************************************************************************/
/*		Lat/lon structure					*/
#define MAXLATLONFORMATSIZE 10
#define DEFAULT_LATLONSEP ' '
#define DEFAULT_LATLONFORMAT "decdeg"
  /*  Upcase direction that defaults to positive is 1st char of nxt 2	*/
#define LEGAL_LATCARDINALS "NnSs"
#define LEGAL_LONCARDINALS "EeWw"
struct latlonformat {
  int var;
  char *legal_cardinal;
  char sep[2];
  char format[MAXLATLONFORMATSIZE+1];
  char convention;
};

/************************************************************************/
/*		Output options						*/

  /*  Parametrize various output levels					*/
  /*    Error output levels						*/
#define NOERROR_OUTPUT 0
#define ERROR_MESSAGE 10
#define ID_INNER 20
#define ID_SESSION 25
#define ID_PROBLEM_FILE 50
#define GET_MORE_FROM_SCRIPT 60
#define ID_ALL_OPEN_FILES 80
  /*    Trace output levels						*/
#define NOTRACE 0
#define TRACE_IOOPEN 10
#define DUMP_ENVIRONMENT 13
#define TRACE_OPTFILE_ROUTINES 20
#define TRACE_PERFILE_ROUTINES 40
#define TRACE_COMMENTS 50
#define TRACE_IOREADREC 70


  /*  Comments sent to ADD_TO_BUFFER_FILE won't go there directly-they	*/
  /*  will be buffered until outer wants them.				*/
#define ADD_TO_BUFFER_FILE STDOUT_NAME

  /*  By default, errors are sent to outer, which takes care of things	*/
  /*  like setting up html environment or issuing JGOFS protocol prefix	*/
  /*  if necessary.  We need to buffer messages sent to outer's sink	*/
  /*  rather than writing them ourselves				*/
#define JGOFS_ERROR_FILE STDOUT_NAME
  /*  Errors in dealing w/sinks go to error sink.  Define where we will	*/
  /*  send messages about errors w/error sink itself.			*/
  /*  If sink changes, stream may have to be opened in the code		*/
#define ULTIMATE_ERROR_STREAM stderr
  /*  Define where to send primary sinks if user spec's duplicate sink	*/
#define PRIMARY_DEBUG_FILE STDERR_NAME 
#define PRIMARY_ERROR_FILE JGOFS_ERROR_FILE

  /*	Characteristics of outinfo structure				*/
#define DATA_COMMENT_SINK 0
#define NON_DATA_COMMENT_SINK 1
#define ERROR_SINK 2
#define DIAG_SINK 3
#define NUM_USER_SPECIFIABLE_SINKS 4  /* Subcount.  User can spec	*/
				/* sinks above here, but not below	*/
#define PRIMARY_ERROR_SINK 4
#define PRIMARY_DIAG_SINK 5
#define NUM_SINKS 6		/* Count.  keep = last sink + 1		*/

#define NUM_DIAG_FLAGS 3	/* inserted_comments, *comment_id	*/
#define NUM_DIAG_LEVELS 2	/* trace_ & error_			*/
#define NUM_EXTRA_DIAG_SOURCES 1  /* maxscriptdiags			*/
 /* Each level has a counter and a addl- counter which user can spec	*/
 /* So does each extra diag source					*/
 /* There is one counter per opt file, iovalstr, iovalreal, and they	*/
 /*   all have an addl- version						*/
#define NUM_DIAG_COUNTERS 2*(NUM_DIAG_LEVELS + NUM_EXTRA_DIAG_SOURCES + \
      NFILETYPES + 2)
 /* Number of things user can specify.					*/
#define NUM_DIAG_KEYWORDS NUM_SINKS + NUM_DIAG_FLAGS + NUM_DIAG_COUNTERS
 /* Size the table.  Max keyword size of 18 comes from doc (must be	*/
 /* maxed w/ biggest descriptor string); +12 is for biggest prefix/	*/
 /* suffix we add ("print__lines" at the moment), +5 is for		*/
 /* addl-; max file size of 40 a punt; max flag value is false-hence	*/
 /* size 5; allow 4 digit counters/levels				*/
#define DIAGS_WJSTBL 40*NUM_SINKS + 5*NUM_DIAG_FLAGS + 4*NUM_DIAG_COUNTERS + \
		     (18+12+5)*NUM_DIAG_KEYWORDS

  /*  Control of how much non-def data is generated, and where it goes	*/
  /*  Structure is filled in in configure_output.  Some defaults are	*/
  /*  hardcoded; some default to values in this file (some of which, in	*/
  /*  turn, can be specified at compile time by the user)		*/
  /*  All _sink strings may be file specifications (including /dev/null	*/
  /*  /dev/stdout or /dev/stderr (latter 2 may be used even if they are	*/
  /*  not defined on a system)).					*/
  /*  Use Logical instead of unsigned int since we want to have 	*/
  /*  pointers to some of the flags					*/
struct outfile {
  Logical *open_ptr;	/*  Will point to one of outsink_open_flags	*/
  FILE **stream_ptr;	/*  Will point to one of outsink_streams[i]	*/
  char **mode_ptr;	/*  Will point to one of outsink_modes		*/
  char *sink;		/*  Will end up non-null.  Expect ptr to 	*/
			/*   /dev/null if people want to chuck stuff;	*/
			/*    will write to /dev/null.  Will skip writ-	*/
			/*     ing if (somehow) 0 len string gets in	*/
  char *descrip;
  struct stat fileinfo;
  Logical processed;	/*  For help during input to protect agnst user	*/
			/*   spec'ing sink > once			*/
  Logical dup;
};
struct outinfo {
    /*  defgb can generate information at the beginning of the main	*/
    /*  comment stream.  The next items allow specification of where	*/
    /*  this data should go, and what it should consist of		*/
  struct outfile file[NUM_SINKS];
  Logical outsink_open_flags[NUM_SINKS];
  FILE *outsink_streams[NUM_SINKS];
  char *outsink_modes[NUM_SINKS];	/* Append or new file		*/
  Logical inserted_comments;		/* Insert lines identfying opt	*/
					/* file & indirect file sources	*/
  Logical inserted_comment_id; 		/* Tag inserted lines with name	*/
					/* of opt file routine		*/
					/* generating line		*/
  Logical opt_file_comment_id;		/* Tag comment lines from opt	*/
					/* files with name of opt file 	*/
					/* routine reading line		*/
    /*  Debugging stuff.  Includes original DEBUG & DEBUG0 output	*/
    /*  Input data dump numbers in fileinfo structure			*/
  int trace_level;	/* Level of output to primary sink		*/
  int dup_trace_level;	/* Level of output to duplicate sink		*/
  int iovalstr;		/* Dump every 'iovalstr'th call to iovalstr	*/
  int iovalreal;	/*	      'iovalreal'th call to iovaldouble	*/
			/*  (or iovalreal - 1 or other is called)	*/
  int dup_iovalstr;	/* Dump every 'dup_iovalstr'th call to iovalstr	*/
			/*  to dup diag sink				*/
  int dup_iovalreal;	/* Dump every 'dup_iovalreal'th call to		*/
			/*  iovaldouble (or iovalreal) to dup diag sink	*/
  int n_iovalstrs;	/* Count of calls to iovalstr			*/
  int n_iovalreals;	/*		     iovaldouble (iovalreal)	*/
    /*  How much error stuff 						*/
  int error_level;		/* Level of output to primary sink	*/
  int dup_error_level;		/* Level of output to duplicate sink	*/
  int maxscriptdiags;		/* # of "extra" script msgs to primary	*/
				/*   sink				*/
};
/****								     ****/
/***************   end defgb_nonconfigurable.h   ************************/

/* ERR_PREFIX			String which, if found at the beginning	*/
/*			    of any data record, indicates that record	*/
/*			    is actually an error message		*/
#ifndef ERR_PREFIX
#define ERR_PREFIX DEFAULT_ERR_PREFIX
#endif

/* COLL_FROM_OBJOBJ_OBJ		Name of object which implements "coll-	*/
/*			    ection from object of objects" feature	*/
/*			    (with punctuation).  Note that it must be	*/
/*			    in the same place on all remote nodes.  See	*/
/*			    varlistopts in param1.doc			*/
#ifndef COLL_FROM_OBJOBJ_OBJ
#define COLL_FROM_OBJOBJ_OBJ DEFAULT_COLL_FROM_OBJOBJ_OBJ		
#endif

  /*  Used to allow METHOD & METHOD_PROTOTYPE as compilation switches	*/
  /*  When those became obsolete (see "switches" doc, issued diagnostic	*/
  /*  now (defgb.h v 4.3) ... too bad if spec'd; they're ignored	*/
#define METHOD DEFGB
#define DEFAULT_METHOD_NAME "defgb"

#ifndef METHOD_NAME
#define METHOD_NAME DEFAULT_METHOD_NAME
#endif
/*********								*/

/*  White space & separator character for optional files.  See doc in	*/
/*  defgb_nonconfig.h & create_wjstbl.  Only spec these if the default	*/
/*  characters are somewhere in opt file data				*/
#ifndef WJSTBL_WHITE_SPACE	/*  Must be a c "white space" character	*/
#define WJSTBL_WHITE_SPACE DEFAULT_WJSTBL_WHITE_SPACE
#endif
#ifndef WJSTBL_SEPARATOR
#define WJSTBL_SEPARATOR DEFAULT_WJSTBL_SEPARATOR
#endif

/*  _OPT switches allow control of optional capabilities spec'd via     */
/*  the indirect parameter file.  The default value of 0 allows 	*/
/*  or disallows capability based on whether or not the relevant file	*/
/*  is provided in the parameter file.  If _OPT is positive, relevant	*/
/*  file MUST be provided in the parameter file.  If _OPT is negative,	*/
/*  file must NOT be provided in parameter file.			*/
#ifndef TRANS_OPT
#define TRANS_OPT 0
#endif
#ifndef INPWIDTH_OPT
#define INPWIDTH_OPT 0
#endif
#ifndef REMOVAL_OPT
#define REMOVAL_OPT 0
#endif
#ifndef TIMEDATE_OPT
#define TIMEDATE_OPT 0
#endif
#ifndef LATLON_OPT
#define LATLON_OPT 0
#endif
#ifndef DATAFIELDOPTS_OPT
#define DATAFIELDOPTS_OPT 0
#endif
#ifndef DISPWIDTH_OPT
#define DISPWIDTH_OPT 0
#endif
#ifndef VARLIST_OPT
#define VARLIST_OPT 0
#endif
#ifndef VARLISTOPTS_OPT
#define VARLISTOPTS_OPT 0
#endif
#ifndef DATACOMMENTS_OPT
#define DATACOMMENTS_OPT 0
#endif

/*	No DIAGS_OPT -can't see purpose of it				*/

#ifndef READ_COMMANDS	/* Compile w/EXEC capability.  Saying NO allows	*/
			/*  defgb use where startchild not written	*/
#define READ_COMMANDS TRUE
#endif

#ifndef READ_OBJECTS	/* Allow use of JGOFS objects as input.  Saying	*/
			/* NO allows defgb use where jdb routines (or	*/
			/* the http libs they use) not available	*/
#define READ_OBJECTS TRUE
#endif

#ifndef OPTIMIZE_OBJECT_TRANSFER
#define OPTIMIZE_OBJECT_TRANSFER READ_OBJECTS
#endif
  /*  No sense to optimize object stuff when method won't read objects	*/
  /*  Be sure we don't try to compile in jdb stuff in this case		*/
#if OPTIMIZE_OBJECT_TRANSFER
#if ! READ_OBJECTS
#undef OPTIMIZE_OBJECT_TRANSFER
#define OPTIMIZE_OBJECT_TRANSFER FALSE
#endif
#endif

#ifndef TOKEN 
#define TOKEN 240
#endif
#if TOKEN < MAXLEN_OUTTIME_VARIABLE
#undef TOKEN
#define TOKEN MAXLEN_OUTTIME_VARIABLE
#endif

#ifndef NVAR 
#define NVAR 250
#endif

  /*  COMMENTLINE, VARNAMESIZE from default.h.  We had called them max	*/
  /*    "since the start" 						*/
  /*  COMMENTLINE does not include # or \n				*/
#define MAXCOMMENTLINE COMMENTLINE
#define MAXVARNAMESIZE VARNAMESIZE

#ifndef DISPLAY_WIDTH		/* To right-justify inserted comments,	*/
#define DISPLAY_WIDTH 80	/*  need to know rightmost column.  In	*/
#endif				/*   html mode, outer inserts a hash &	*/
#define LENGTH_OUTER_DISPLAY_PREFIX 2  /* a blank before each comment	*/
#define EFFECTIVE_DISPLAY_WIDTH DISPLAY_WIDTH-LENGTH_OUTER_DISPLAY_PREFIX

#ifndef COMMENTSIZE 
#define COMMENTSIZE 2430
/*	Note that as of defgb 3.8a, comment buffer is dynamically	*/
/*	allocated, and this is just the "chunk" size.  (jdb, however,	*/
/*	has a static buffer, presumably of this size (coming from	*/
/*	"include OPTIONS" - OPTIONS being spec'ed on compilation line))	*/
#endif

#ifndef MAXREC 
#define MAXREC 10000
/*	Originally 1257.  No particular reason for this value		*/
/*	according to Glenn 3 Dec 96					*/
#endif

/*	Lists that contain input from various opt files			*/
#ifndef TRANS_LIST
#define TRANS_LIST 10000
#endif
#ifndef VAR_DATA_WIDTHS
#define VAR_DATA_WIDTHS 1000
#endif
#ifndef DISP_DATA_WIDTHS
#define DISP_DATA_WIDTHS 1000
#endif

/*	Params below define differences from defw.  Allow these to be	*/
/*	set on compile line						*/
/*	To enable fixed-format input, specify a inpwidths file in an	*/
/*	indirect input file (see doc)					*/

#ifdef SEPARATOR	    /* See also doc for fileinfo struct		*/
#define SEPARATORS SEPARATOR
#else
#define SEPARATORS DEFAULT_SEPARATORS
#endif

  /*  Allow separators within fields by delimiting them with		*/
  /*  separator characters						*/
#ifdef ALT_SEPARATOR
#define ALT_SEPARATORS ALT_SEPARATOR
#else
#define ALT_SEPARATORS DEFAULT_ALT_SEPARATORS
#endif
  /*  If set, consecutive SEPARATORS characters mean empty fields	*/
  /*  This applies only to free field data; not variable lists, and not	*/
  /*    to any subfile field following the data				*/
#ifndef SIGNIFICANT_CONSECUTIVE_SEPARATORS
#define SIGNIFICANT_CONSECUTIVE_SEPARATORS FALSE
#endif
  /*  In fixed fields, does an embedded separator mean 2 fields and,	*/
  /*  therefore, an error?						*/
#ifndef SIGNIFICANT_EMBEDDED_SEPARATORS
#define SIGNIFICANT_EMBEDDED_SEPARATORS TRUE
#endif
  /*  In fixed fields, should we trim off leading and trailing separators? */
	/* #ifndef DATA_FIELD_TRIM	*/
#define DATA_FIELD_TRIM TRUE
	/* #endif			*/


  /*  What character represents a field to skip in a time/date template	*/
#ifndef TIMEDATE_SKIPFIELD_CHAR 
#define TIMEDATE_SKIPFIELD_CHAR '*'
#endif
  /*  Character interpreted by SSCANF to mean "skip this field"		*/
#define SSCANF_SKIPFIELD_CHAR '*'

  /*  Are there variable lists in with the data files or not?		*/
#define MIN_VARLISTS_END -2
  /*  Next value can be any illegal varlists_end value			*/
#define NO_VARLISTS_END_SPECIFIED MIN_VARLISTS_END-1
#ifndef VARLISTS_END	/* Last level w/ variable lists			*/
			/*   0 = traditional defgb_noheader (level 0	*/
			/*      has list; rest don't)			*/
			/*  -1 would be no data files w/lists (must	*/
			/*	spec varlist opt!)			*/
			/*  -2 means all levels have list		*/
			/*  Any positive # OK, too, if they want...	*/
#define VARLISTS_END -2
#endif

/************************************************************************/
/*  Compile-time configurable portions of indirect input files		*/
/*  (should be possible to specify all of these at runtime, too -see	*/
/*  runtime doc)							*/
/*  Also see init* modules in ioopen_routines to see how these values	*/
/*  get applied to the actual data structures.				*/

/*		Output options						*/
  /*    Set up default.  Can be overridden at runtime via diagnostics	*/
  /*	opt file.  Final value set in configure_output			*/
#ifndef DEFAULT_ERROR_LEVEL
#define DEFAULT_ERROR_LEVEL GET_MORE_FROM_SCRIPT
#endif
#ifndef DEFAULT_MAXSCRIPTDIAGS
#define DEFAULT_MAXSCRIPTDIAGS 5
#endif

  /*    Set up default trace level.  Can be overridden at runtime via   */
  /*	diagnostics opt file.  Final value set in configure_output	*/
#ifndef DEFAULT_TRACE_LEVEL
#ifdef DEBUG			/*  Compatibility w/older inners	*/
#define DEFAULT_TRACE_LEVEL TRACE_PERFILE_ROUTINES
#else
#define DEFAULT_TRACE_LEVEL NOTRACE
#endif
#endif
  /*	Data trace default (compatibility w/older inners)		*/
#ifdef DEBUG0
#define DEFAULT_DATA_TRACE 1
#else
#define DEFAULT_DATA_TRACE 0
#endif
  /*  User-changeable default sinks-since there are some messages	*/
  /*  generated before diags get set up.  Note that comments generated	*/
  /*  before the comment sinks are set up are buffered, so we just	*/
  /*  reprocess them from the buffer after we know where they should go	*/
#ifndef DEFAULT_DEBUG_FILE
#define DEFAULT_DEBUG_FILE PRIMARY_DEBUG_FILE
#endif
#ifndef DEFAULT_ERROR_FILE
#define DEFAULT_ERROR_FILE PRIMARY_ERROR_FILE
#endif
#ifndef DEFAULT_OTHER_COMMENT_FILE
#define DEFAULT_OTHER_COMMENT_FILE NULL_DEVICE
#endif

  /*	Inserted comment switch defaults				*/
#ifndef DEFAULT_INSERTED_MSGS
#define DEFAULT_INSERTED_MSGS TRUE
#endif
#ifndef DEFAULT_INSERTED_MSG_TAG
#define DEFAULT_INSERTED_MSG_TAG TRUE
#endif
#ifndef DEFAULT_COMMENT_SOURCE_TAG
#define DEFAULT_COMMENT_SOURCE_TAG TRUE
#endif

  /*  Structure containing info about replacement of unprintable chars	*/
  /*  in error messages.  Mostly a convenience so we don't have to	*/
  /*  sling 6 args between functions.					*/
struct unprint_repl {
  char repl_char;		/*  Replacement character		*/
  int chars_replaced;		/*  How many unprintables were replaced	*/

    /*  First character we replaced.  Unsigned for convenience printing	*/
  unsigned char first_bad_char;
  char *first_repl_char_ptr;    /*  Ptr to first char replaced		*/

    /*  If we are unlucky, all prospective replacement characters ap-	*/
    /*  peared in message somewhere.  Count how many there were before	*/
    /*  we added ours							*/
  int repl_char_already_in_msg;
    /*  Pointer to first replacement character that was in message be-	*/
    /*  fore we added ours						*/
  char *first_repl_char_already_in_msg;
};

    /*  Time/date table contains up to 5 pairs of keyword (max size 26)	*/
    /*  & variable, up to 10 pairs of keyword (max size 18) & variable	*/
    /*  up to 2 pairs of keyword (max size 24) & convention (max size	*/
    /*  5, and up to 10 pairs of keyword (max size 22) & template.	*/
    /*  Each pair also requires 2 separators and a blank		*/
    /*  Note that keyword sizes depend on TIMEDATE*PREFIX params	*/
#define TIMEDATE_WJSTBL NUM_OUTTIME_VARIABLES*(26 + MAXVARNAMESIZE + 2 + 1) \
		     +	NUM_TIMEDATE_FRAGS*(18 + MAXVARNAMESIZE + 2 + 1) \
		     +  2*(24 + 5 + 2 + 1) \
		     +	NUM_TIMEDATE_FRAGS*(22 + TOKEN + 2 + 1)
    /*  Latlon table allows 14 keywords (max size 27), 16 values, and,	*/
    /*  for each keyword/variable pair, 2 separators and a blank.  	*/
    /*  The values can be single characters, formats, or variable names	*/
#define NUM_LATLONPARAMS 14
#if MAXVARNAMESIZE > MAXLATLONFORMATSIZE
#define MAXLATLONVALUESIZE MAXVARNAMESIZE
#else
#define MAXLATLONVALUESIZE MAXLATLONFORMATSIZE
#endif
#define LATLON_WJSTBL NUM_LATLONPARAMS*(27 + MAXLATLONVALUESIZE +2 +1)

    /*  12, 57, 24 & 20 are the sizes of the keywords; 5 is size of	*/
    /*  FALSE;	1 is max # digits in a level; 1 is for possible -,	*/
    /*  MAXVARNAMESIZE is size of a variable name; 2s are wjstbl	*/
    /*  separators; MAXREC here represents the size of a file name -	*/
    /*  only sure limit is max chars defgb will read from an opt file;	*/
    /*  100 is slop so user can enter bad keyword and we		*/
    /*  can diagnose it (also, so we can be wrong about defns of other	*/
    /*  fields!!)							*/
#define VARLISTOPTS_WJSTBL (12 + 1 + 1 + 2) + \
			   (57 + 5 + 2) + \
			   (24 + MAXVARNAMESIZE + 2) + \
			   (20 + MAXREC + 2) + \
			   100

#define MAX_DATACOMMENTS_SOURCES 9
#define VARLIST_PTR ".varlist"
#define LEVEL0_PTR ".level_0"
#define DATACOMMENTS_KEYWORD "source"

#define OBJ_KEY ".objects_parameter"
