/*
 * $Id: inner.c,v 1.12 1996/06/13 12:30:23 jgofs Exp jgofs $
 * Currently locked by $Locker: jgofs $ (not locked if blank)
 * (Time in GMT, EST=GMT-5:00
 * $Log: inner.c,v $
 * Revision 1.12  1996/06/13  12:30:23  jgofs
 * For some reason, can't rely upon PATH_INFO environment variable
 * to determine what level you're at in inner.c.  Instead, have to
 * look at calling sequence of ioreadrec_ and iocommout_ to
 * determine what comments are valid.  Put in boolean flags to
 * mark this.  Also, changed comment from being arrays of
 * static character arrays into dynamically allocated arrays.
 *
 * Revision 1.11  1996/06/12  16:42:41  jgofs
 * Changed io, now all variables are stored internally as strings.
 * Has made all html links seem to work.  Also, was using incorrect
 * netcdf varid when asking for level 1 values.  Duhhh...
 * Only thing that doesn't seem to work is comments thru the web.
 *
 * Revision 1.10  1996/06/12  13:42:07  jgofs
 * Now handles some of the html queries correctly.  Problem was
 * that some of the arguments passed into ioopen_ thru "s"
 * aren't necessarily all valid variable names.  Some might be
 * projections.  Have realized that level 1 comments cannot be
 * grabbed until we enter level 1.  Html queries on depth
 * still don't work.
 *
 * Revision 1.9  1996/06/12  11:43:07  jgofs
 * Now all comments are forced to be null terminated.  Still
 * unsure as to why html stuff is weird.  Has something to do
 * with outer:test subroutine, though.
 *
 * Revision 1.8  1996/06/11  13:17:01  jgofs
 * Valid variables were not being marked correctly as so.
 * Only things not working are comments in html and certain
 * QUERY_STRINGs, such as mooring, depth, etc.  Weird...
 *
 * Revision 1.7  1996/06/10  12:19:53  jgofs
 * Not sure exactly why ncattget wasn't working for min and max
 * values before.  All I did to fix it was to delete the offending
 * line and retype it in.  Perhaps there was a control character
 * embedded in there?  Actually, it was just the min attribute that
 * was causing problems...
 *
 * Revision 1.6  1996/06/03  13:25:04  jgofs
 * Can retrieve units attribute ( level 1 comment )
 * but cannot seem to get min and max extents...
 *
 * Revision 1.5  1996/06/03  12:51:26  jgofs
 * something weird, need to recheck out 1.4
 *
 * Revision 1.4  1996/05/31  14:24:51  jgofs
 * Level 0 and level 1 comments almost done.  Only thing left
 * is to get the unit measurements for the particular variable.
 *
 * Revision 1.3  1996/05/30  16:53:41  jgofs
 * The command line
 * gom2 /usr/users/jgofs/data/gom_moor/hourly-vane.hdr lat lon
 *
 * produces good level 0 output.  Need to get level 1 comments,
 * level 1 ioreadrec implemented.
 *
 * Revision 1.2  1996/05/30  13:43:22  jgofs
 * Actually runs with arguments
 * /usr/users/jgofs/data/gom_moor/hourly-vane.hdr lat lon
 *
 * Time to implement variable reads.
 *
 * Revision 1.1  1996/05/29  20:24:42  jgofs
 * Initial revision
 *
 *
 */

/*
 * If this code looks bad in your editor, maybe you should
 * look at it in vi with these settings...
 * These come from the .exrc file used in the original 
 * source code directory that this file was written in.

   set nu
   set autoindent
   set tabstop=4
   set shiftwidth=4
   set showmatch
   map b :w
:!make
 
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "netcdf.h"


/*
 * Local prototypes not defined in outer.c
 */
void setup_level_zero_comments ( );
void setup_level_one_comments ( );
void setup_variables ( int *nparams, char *param_list[] );




/*
 * Local structure defs.
 */
#include "gom_object_def.h";


#define MAX_LINE_LENGTH MAX_NC_NAME
#define JGOFS_SUCCESS 1
#define JGOFS_FAILURE 0




/*
 * GLOBAL VARIABLES
 * ================
 */

/*
 * This is the jgofs object.
 */
static Gom_Obj		gom_obj; 	

/*
 * Listing of level 0, some level 1 variable names.
 */
char 		*level_0_varnames[8] = { "mooring", 
									 "g_start_date", 
									 "g_stop_date", 
									 "lat", 
									 "lon", 
									 "depth", 
									 "j_start_date", 
									 "j_stop_date" };
char		*level_1_varnames[2] = { "time",
									 "time2" };


/*
 * Placeholder for path of header file.
 */
char		pathname[MAX_LINE_LENGTH];





/*
 * EXTERNAL VARIABLES
 * ==================
 */

/* 
 * This setting disables error messages and fatal errors, 
 * allows us to recover gracefully.                  
 */
extern int ncopts;   







/*
 * ioopen_
 *
 * Open the data set at the topmost level.
 *
 * Parameters
 * s:  parameter array, first element has file name.  It is CRUCIAL that
 *     this array contain ALL of the variables that we want to project.
 *     The default is NO variables, so one can't just invoke the method
 *     on the header file and expect to see data...
 * nparams:  points to number of parameters in s
 * total:  total number of variables
 *
 * Return value:  ID number of the highest level, NOT the
 *                number of levels.
 */
int ioopen_ ( char *s[], int *nparams, int *ntotal )
{

	Gom_Obj *obj = &gom_obj;


	/*
	* need a character buffer for various things
	*/
	char buffer[500];


	/*
	 * Used to get the pathname.
	 */
	char *tok;






	/*
     * We want neither fatal errors nor error messages
     * from netcdf functions.
     */
    ncopts = 0;


	/*
	 * Need to grab pathname off of header filename.
	 * This is necessary in order to find the netcdf
	 * files later.
	 */
	strcpy ( pathname, s[0] );
	if ((tok = strrchr ( pathname, '/' )) != NULL )
		*(tok+1) = '\0';
	else 
		pathname[0] = '\0';


	/*
	 * Open the header file.
	 */
	if ( (gom_obj.header_fp = fopen ( s[0], "r" )) == NULL ) {
		fprintf ( stderr, "Could not open %s\n", s[0] );
		exit ( EXIT_FAILURE );
	}


	setup_level_zero_comments();
	gom_obj.level_0_comments_valid = TRUE;



	setup_variables ( nparams, s );


	/*
	 * Read one more line and we'll be properly positioned.
	 */
	fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );


   /*
    * Last thing to do is to zero out the first paramter 
	* and set return parameters.
    */
	*ntotal = gom_obj.num0v + gom_obj.num1v;
    s[0][0] = '\0';


   /*
    * There are two levels, but it is zero based, so return 1.
    */
   return 1;


}




/*
 * iocommout
 * 
 * Extracts the next comment and puts it in the string str.
 * 
 * Parameters
 * str:  will contain the comment.
 *
 * Return value: 1 if successful, 0 if not
 */
int iocommout_ ( char *str )
{

	int *index = &(gom_obj.current_comment);



	/*
	 * If at level 0, just output level 0 comments.
	 */
	if ( gom_obj.level_0_comments_valid ) {
		if ( gom_obj.current_comment < gom_obj.num_level0_comments ) {
			strcpy ( str, gom_obj.comment[(*index)++] ); 
			return ( JGOFS_SUCCESS );
		} 
		else
			return ( JGOFS_FAILURE );
	}
	/*
	 * If at level 1, output level 0 AND level 1 comments.
	 */
	else {
		if ( gom_obj.current_comment < gom_obj.num_comments ) {
			strcpy ( str, gom_obj.comment[(*index)++] );
			return ( JGOFS_SUCCESS );
		} 
		else
			return ( JGOFS_FAILURE );
	}


}





/*
 * ioname_
 *
 * Returns the name of the v(n)th variable.  Must be null terminated.
 *
 * Parameters
 * *vn:  integer id for a particular jgofs variable
 * s:    where the name is placed
 */
void ioname_ ( int *vn, char *s )
{
	sprintf ( s, "%s\0", gom_obj.var[*vn].name );
}





/*
 * iovarlevel_
 *
 * Provides the hierarchical structure of the variable indicated by *vn.
 * As far as I can tell, there are only 2 levels to a netcdf
 * file, and the first ones are always the dimensions, which
 * would be level 0.
 *
 * Parameters
 * *vn:  integer id for a particular jgofs variable
 * 
 * Return value:  the level of the indicated jgofs variable
 */
int iovarlevel_ ( int *vn )
{

	return ( gom_obj.var[*vn].level );

}





/*
 * ioattrout_
 *
 * Returns the next attribute associated with a particular variable.
 *
 * Parameters
 * *vn:  integer id for a particular jgofs variable
 * *str: string containing the attribute
 *
 * Return value:  1 for a successful attribute retrieval, 0 for failure. 
 */
int ioattrout_ ( int *vn, char *str )
{
	return ( 0 );
}





/*
 * iovalreal_
 * 
 * Returns the real number value of the variable whose index is
 * passed in.
 *
 * Parameters
 * *vn:  integer id for a particular jgofs variable
 * *f:   points to real value cast of indicated jgofs variable
 *
 */
void iovalreal_ ( int *vn, float *f )
{
	sscanf ( gom_obj.var[*vn].value, "%f", f );

}








/*
 * iovalstr_
 *
 * Returns character string equivalent of a variable.
 *
 * Parameters
 * *vn:  integer id for a particular jgofs variable
 * *str: string containing the value, null terminated.
 *
 */
void iovalstr_ ( int *vn, char *str )
{

	Gom_Var *var = &gom_obj.var[*vn];

	strcpy ( str, gom_obj.var[*vn].value );

}




/*
 * ioreadrec_
 *
 * Actually does the reading of records from the data set.
 *
 * Parameters
 * *level:  Integer indicating jgofs level to read at.
 *
 * Return value:  1 for a successful read, 0 for failure. 
 *
 */
int ioreadrec_ ( int *level )
{

	/*
	* Need a buffer for reads.
	*/
	char buffer[MAX_LINE_LENGTH];

	/*
	* Need buffer for level 0 netcdf filename
	*/
	char current_netcdf_filename[MAX_LINE_LENGTH];

	/*
	 * Multidimensional index of the variable to be read.
	 */
	static long int record_index[4] = {0, 0, 0, 0};



	/*
	 * Jgofs id variables.
	 */
	int
		jg_id,			/* loop variable */
		netcdf_varid,
		time_id, 
		time2_id;		/* For variables "time" and "time2" */

	int
		status;			/* Result of netcdf operation. */

	long int
		time1_val,
		time2_val;
	double
		time_val;		/* Special values for netcdf time variables. */

	int
		i;


	float
		datum;			/*
						 * Can't think of any level 1 variables that
						 * aren't floats.  This may have to be changed,
						 * though.
						 */


	/*
	 * Level 0 read 
	 */
	if ( *level == 0 ) {
		
		if ( fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp ) == NULL ) 
			return JGOFS_FAILURE;

		
		/*
		 * first reset all values to null
		 */
		for ( i = 0; i < gom_obj.num0v;  ++i ) 
			memset ( gom_obj.var[i].value, '\0', strlen(gom_obj.var[i].value) );

		sscanf ( buffer,
				 "%s %s %s %s %s %s %s %s %s\n",
				 current_netcdf_filename,
				 gom_obj.var[jg_gregorian_start_date_id].value,
				 gom_obj.var[jg_gregorian_stop_date_id].value,
			     gom_obj.var[jg_julian_start_date_id].value,
				 gom_obj.var[jg_julian_stop_date_id].value,
				 gom_obj.var[jg_mooring_id].value,
				 gom_obj.var[jg_lat_id].value,
				 gom_obj.var[jg_lon_id].value,
				 gom_obj.var[jg_depth_id].value
				 );

		/*
		 * Contruct full pathname of current netcdf file.
		 */
		 strcpy ( gom_obj.ncfilename, pathname );
		 strcat ( gom_obj.ncfilename, current_netcdf_filename );

		/*
		 * Open the netcdf file for subsequent level 1 reads.
		 */
		gom_obj.ncid = ncopen ( gom_obj.ncfilename, NC_NOWRITE );


		setup_level_one_comments ();


		/*
		 * ioreadrec was successful
		 */
		 return JGOFS_SUCCESS;
	}	


	/*
	 * Level 1 read.
	 */
	gom_obj.level_0_comments_valid = FALSE;
	gom_obj.level_1_comments_valid = TRUE;
	if ( *level == 1 ) {
		/*
		 * first reset all values to null
		 */
		for ( i = gom_obj.num0v; i < gom_obj.num_vars;  ++i ) 
			memset ( gom_obj.var[i].value, '\0', strlen(gom_obj.var[i].value) );

		/*
		 * Getting the time information is not general.  The time
		 * information is split between the "time" and "time2" 
		 * variables.  Want to read them both in and combine.
		 * In the combining, we also want to subtract off the
		 * julian day of Jan 1, 1970.
		 */
		time_id = ncvarid ( gom_obj.ncid, "time" );
		time2_id = ncvarid ( gom_obj.ncid, "time2" );
	
		status = ncvarget1 ( gom_obj.ncid,
							 time_id, 
							 record_index, 
							 (void *)&time1_val );
		status = ncvarget1 ( gom_obj.ncid, 
							 time2_id, 	
							 record_index, 	
							 (void *)&time2_val );
		time_val = (double)time1_val + (double)time2_val/8.64e7 - 2415021.0;
		sprintf ( gom_obj.var[jg_time_id].value, "%lf", time_val );
	
					
	
							
		
		/*
		 * Now proceed with the rest of the level 1 variables.
		 */
		for ( jg_id = jg_time_id+1; jg_id < gom_obj.num_vars; ++jg_id ) {
			netcdf_varid = ncvarid ( gom_obj.ncid,
									 gom_obj.var[jg_id].name );
			status = ncvarget1 ( gom_obj.ncid,
								 netcdf_varid,
								 record_index,
								 (void *)&datum );
			sprintf ( gom_obj.var[jg_id].value, "%f\0", datum );
	
	 	}
			
	
	
		/*
		 * If status == -1, then we were unable to retrieve data at
		 * level 1.  So we must be done with this level.  Get ready
		 * to go back to level 0.
		 */
		if ( status == -1 ) {
			record_index[0] = 0;
			ncclose ( gom_obj.ncid );
			return JGOFS_FAILURE;
		} else {
			record_index[0]++;
			return JGOFS_SUCCESS;
		}
	
		return (JGOFS_FAILURE);
	}

	/*
	 * If we're here, must have tried a level 2 read.  No such thing...
	 */
	return ( JGOFS_FAILURE );

}





/*
 * ioclose_
 *
 * Closes any open files.  Yeah right, like anyone cares.
 */
void ioclose_ ()
{
	ncclose ( gom_obj.ncid );
}








/*
 * setup_level_zero_comments
 *
 * This helper routine gets all level 0 comments for the object.
 * These comments are found in the header file.
 */
void setup_level_zero_comments ( ) {

	/*
	 * helps dbx to debug
	 */
	Gom_Obj *obj = &gom_obj;

	/*
	 * need a character buffer for various things
  	 */
	char buffer[MAX_LINE_LENGTH];


	/*
	 * Loop variables, indices into arrays.
	 */
	int 	i,
			last_char_index,
			comm_index;



	fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );
	comm_index = 0;
	gom_obj.num_level0_comments = 0;
	gom_obj.num_level1_comments = 0;

	while ( strncmp ( buffer, "File", 4 ) ) {

		buffer[strlen(buffer)-1] = '\0';
		gom_obj.comment[comm_index] = malloc ( (strlen(buffer)*2) * sizeof(char));
		strcpy ( gom_obj.comment[comm_index++], buffer+2 );
		memset ( (void *)buffer, '\0', sizeof(buffer) );
		fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );

	}

	gom_obj.num_level0_comments = comm_index;
	gom_obj.num_comments = comm_index;



	/*
	 * Last thing is to make sure that all comments are null
	 * terminated and have no newline characters.  Do this by 
	 * looking at last character in each comment.  If it's a
	 * newline, replace it with null char.  Otherwise put 
	 * null char in after last char.
	 */
	for ( i = 0; i < gom_obj.num_level0_comments;  ++i ) {
		last_char_index = strlen ( gom_obj.comment[i] ) - 1;
		if ( gom_obj.comment[i][last_char_index] == '\n' )
			gom_obj.comment[i][last_char_index] = '\0';
		else
			gom_obj.comment[i][last_char_index+1] = '\0';
	}


}










/*
 * setup_level_one_comments
 *
 * This helper routine gets all level 1 comments for the object.
 */
void setup_level_one_comments ( ) {

	/*
	 * helps dbx to debug
	 */
	Gom_Obj *obj = &gom_obj;

	/*
	 * need a character buffer for various things
  	 */
	char buffer[MAX_LINE_LENGTH];


	/*
	 * Loop variables, indices into arrays.
	 */
	int 	i,
			last_char_index,
			comm_index = gom_obj.num_level0_comments;

	/*
	 * Used to read in different netcdf comment types.
	 */
	int			byte_val;
	char		str_val[MAX_LINE_LENGTH];
	int			short_val;
	long int	long_val;
	float		float_val;
	double		double_val;

	/*
	 * jgofs and netcdf variable id numbers
	 */
	int			jg_varid, netcdf_varid;


	/*
	 * Return values from netcdf operations.
	 */
	int 	status,	
			status_min, status_max,
			num_global_atts,	
			attribute_length;
	float	min_val, max_val;
	char	attribute_name[MAX_LINE_LENGTH];
	nc_type	data_type;



	/*
	 * Get the number of global attributes 
	 * which make up some of the level 1 comments.
	 */
	status = ncinquire ( gom_obj.ncid, 
						 (int *)NULL,
						 (int *)NULL,
						 &num_global_atts,
						 (int *)NULL );
	for ( i = 0; i < num_global_atts; ++i ) {

		/*
		 * Get name of attribute
		 */
		status = ncattname ( gom_obj.ncid,
							  NC_GLOBAL,
							  i,
							  attribute_name );
		if ( status == -1 ) {
			fprintf ( stderr, "get_comments:  ncattname failed\n" );
			exit ( EXIT_FAILURE );
		}


		/*
		 * Get data type and length.
		 */
		status = ncattinq ( gom_obj.ncid,
							NC_GLOBAL,
							attribute_name,
							&data_type,
							&attribute_length );
		if ( status == -1 ) {
			fprintf ( stderr, "get_comments:  ncattinq failed\n" );
			exit ( EXIT_FAILURE );
		}


		gom_obj.comment[comm_index] = malloc ( MAX_LINE_LENGTH * sizeof(char));


		/*
		 * Now get the actual attribute ( level 1 comment ).
		 */
		 switch ( data_type ) {
		 case NC_BYTE:
			status = ncattget ( gom_obj.ncid,
								NC_GLOBAL,
								attribute_name,
								(void *)&byte_val );
			if ( status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget failed" );
				exit ( EXIT_FAILURE );
			}
			sprintf ( gom_obj.comment[comm_index++], 
					  "%s = %#X",
					  attribute_name, byte_val );
			break;

		
		/*
		 * character case is slightly different.  Must end with
		 * a null char, otherwise it looks weird.
		 */
		case NC_CHAR:
			status = ncattget ( gom_obj.ncid,
								NC_GLOBAL,
								attribute_name,
								(void *)str_val );
			if ( status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget failed" );
				exit ( EXIT_FAILURE );
			}
			str_val[strlen(str_val)] = '\0';
			sprintf ( gom_obj.comment[comm_index++], 
					  "%s = %s",
					  attribute_name, str_val );
			break;

		 case NC_SHORT:
			status = ncattget ( gom_obj.ncid,
								NC_GLOBAL,
								attribute_name,
								(void *)&short_val );
			if ( status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget failed" );
				exit ( EXIT_FAILURE );
			}
			sprintf ( gom_obj.comment[comm_index++], 
					  "%s = %i",
					  attribute_name, short_val );
			break;
						 
	
		 case NC_LONG:
			status = ncattget ( gom_obj.ncid,
								NC_GLOBAL,
								attribute_name,
								(void *)&long_val );
			if ( status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget failed" );
				exit ( EXIT_FAILURE );
			}
			sprintf ( gom_obj.comment[comm_index++], 
					  "%s = %li",
					  attribute_name, long_val );
			break;
						 
		 case NC_FLOAT:
			status = ncattget ( gom_obj.ncid,
								NC_GLOBAL,
								attribute_name,
								(void *)&float_val );
			if ( status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget failed" );
				exit ( EXIT_FAILURE );
			}
			sprintf ( gom_obj.comment[comm_index++], 
					  "%s = %f",
					  attribute_name, float_val );
			break;
						 
		 case NC_DOUBLE:
			status = ncattget ( gom_obj.ncid,
								NC_GLOBAL,
								attribute_name,
								(void *)&double_val );
			if ( status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget failed" );
				exit ( EXIT_FAILURE );
			}
			sprintf ( gom_obj.comment[comm_index++], 
					  "%s = %lf",
					  attribute_name, double_val );
			break;
						 
		default:
			fprintf ( stderr, "Unknown netcdf type encountered in get_comments\n" );
			exit ( EXIT_FAILURE );

		}

	}


	/*
	 * Now get the particular comments.
	 * This means that we want units of measurement for all
	 * level 1 variables, and extents for all level 1 variables
	 * except for time.
	 *
	 */
	for ( jg_varid = jg_time_id; 
		  jg_varid < gom_obj.num_vars; 
	      ++jg_varid ) {	
		
		/*
		 * Get the name of the variable.
		 */
		netcdf_varid = ncvarid ( gom_obj.ncid,
						  gom_obj.var[jg_varid].name );
		if ( netcdf_varid == -1 ) {
			fprintf ( stderr, "get_comments: ncvarid failed\n" );
			exit ( EXIT_FAILURE );
		}

		/*
		 * get the units attribute
		 */
		memset ( (void *)buffer, '\0', sizeof(buffer) );	
		status = ncattget ( gom_obj.ncid, 
							netcdf_varid,
							"units",
							(void *)buffer );
		if ( status == -1 ) {
			fprintf ( stderr, "get_comments:ncattget failed\n" );
			exit ( EXIT_FAILURE );
		}
		else {
			gom_obj.comment[comm_index] = malloc ( MAX_LINE_LENGTH * sizeof(char));
			sprintf ( gom_obj.comment[comm_index++],
					  "%s units of measurement:  %s\0",
					  gom_obj.var[jg_varid].name,
					  buffer );
		}


		/*
		 * get the measurement extents
		 */
		status_min = ncattinq ( gom_obj.ncid,
								netcdf_varid,
								"minimum",
								&data_type,
								&attribute_length );

		status_max = ncattinq ( gom_obj.ncid,
								netcdf_varid,
								"maximum",
								&data_type,
								&attribute_length );

		if ( (status_min != -1) && (status_max != -1) ) {

			status = ncattget ( gom_obj.ncid,
								netcdf_varid,
								"maximum",
								(void *)&max_val );
			if (status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget max failed\n" );
				exit ( EXIT_FAILURE );
			}
			status = ncattget ( gom_obj.ncid,
								netcdf_varid,
								"minimum",
								(void *)&min_val );
			if (status == -1 ) {
				fprintf ( stderr, "get_comments:  ncattget min failed\n" );
				exit ( EXIT_FAILURE );
			} else {
				gom_obj.comment[comm_index] = malloc ( MAX_LINE_LENGTH * sizeof(char));
				sprintf ( gom_obj.comment[comm_index++],
							"%s range: [%f, %f]\0",
							gom_obj.var[jg_varid].name,
							min_val, max_val );
			}

		}

							
	}



	/*
	 * Now finalize the comment numbers.
	 */
	gom_obj.num_comments = comm_index;
	gom_obj.num_level1_comments = gom_obj.num_comments - gom_obj.num_level0_comments;
	gom_obj.current_comment = 0;


	/*
	 * Last thing is to make sure that all comments are null
	 * terminated and have no newline characters.  Do this by 
	 * looking at last character in each comment.  If it's a
	 * newline, replace it with null char.  Otherwise put 
	 * null char in after last char.
	 */
	for ( i = 0; i < gom_obj.num_comments;  ++i ) {
		last_char_index = strlen ( gom_obj.comment[i] ) - 1;
		if ( gom_obj.comment[i][last_char_index] == '\n' )
			gom_obj.comment[i][last_char_index] = '\0';
		else
			gom_obj.comment[i][last_char_index+1] = '\0';
	}


}










/*
 *
 */
void setup_variables ( int *nparams, char *arg_list[] ) {

	/*
	 * need a character buffer for various things
  	 */
	char buffer[MAX_LINE_LENGTH];


	/*
	 * Netcdf file to grab global comments from.
	 */
	char	netcdf_filename[MAX_LINE_LENGTH];
	char	full_pathname[MAX_LINE_LENGTH];
	int		ncid;

	/*
	 * Need to peek ahead in header file to grab the first
	 * netcdf file.  Therefore, need to keep track of
	 * original position in header file.
	 */
	int 	orig_pos;


	/*
	 * Pointer to a jgofs variable in object.
	 */
	Gom_Var *var;


	/*
	 * Indices, loop varibles.
	 */
	int	
			i, j, index;


	/*
	 * Used to determine whether or not something in the
	 * argument list is a valid variable or not.  If not,
	 * that doesn't necessarily imply an error...
	 */
	int
			keep_it,
			varid;


	/*
	 * Define the level 0 variables for all objects, even if
	 * they are not necessarily present...
	 * These particular variables are present in the header
	 * files, and must be at least defined.  Not necessary 
	 * to use them during testing...
	 */
	gom_obj.num0v = 8;
	var = gom_obj.var;
	for ( i = 0; i < gom_obj.num0v; ++i ) {
		strcpy ( var[i].name, level_0_varnames[i] );
		var[i].name[ strlen(level_0_varnames[i]) ] = '\0';
		var[i].level = 0;

		/*
		* Determine whether or not the variable is valid or not.
		* If it is, it is one of the parameters in s.
		*/
		var[i].valid = 0;
		for ( j = 1; j < (*nparams); ++j ) 
			if ( !strcmp ( var[i].name, arg_list[j] ) ) 
				var[i].valid = 1;
			
	}
	gom_obj.var[jg_mooring_id].data_type = NC_LONG;	
	gom_obj.var[jg_gregorian_start_date_id].data_type = NC_SHORT;
	gom_obj.var[jg_gregorian_stop_date_id].data_type = NC_SHORT;
	gom_obj.var[jg_lat_id].data_type = NC_FLOAT;
	gom_obj.var[jg_lon_id].data_type = NC_FLOAT;
	gom_obj.var[jg_depth_id].data_type = NC_FLOAT;
	gom_obj.var[jg_julian_start_date_id].data_type = NC_DOUBLE;
	gom_obj.var[jg_julian_stop_date_id].data_type = NC_DOUBLE;




	/*
	 * Now go thru the paramter list, looking for any
	 * level 1 variables. 
	 *
	 * First thing to do is peek ahead at the first netcdf
	 * file in the header file.  Need to do this in order
	 * to compare variable names in the arg_list to 
	 * existing variable names in the netcdf files.  The
	 * assumption is that if a variable name is not present
	 * in the first netcdf file, it won't be present in 
	 * any of the other netcdf files.
	 */
	orig_pos = ftell ( gom_obj.header_fp );
	rewind ( gom_obj.header_fp );
	fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );
	while ( strncmp ( buffer, "File", 4 ) ) 
		fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );
		
	fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );
	fgets ( buffer, MAX_LINE_LENGTH, gom_obj.header_fp );
	sscanf ( buffer, "%s", netcdf_filename );
	fseek ( gom_obj.header_fp, orig_pos, SEEK_SET );

	/*
	 * Construct full pathname.
	 */
	strcpy ( full_pathname, pathname );
	strcat ( full_pathname, netcdf_filename );
	ncid = ncopen ( full_pathname, NC_NOWRITE );

	gom_obj.num1v = 0;
	index = gom_obj.num0v;
	var = gom_obj.var;
	for ( j = 1; j < *nparams; ++j ) {

		/* 
		 * make sure it's not a level 0 variable already 
		 */
		keep_it = TRUE;
		for ( i = 0; i < gom_obj.num0v; ++i ) { 
			if ( !strcmp( var[i].name, arg_list[j] ) ) 
				keep_it = FALSE;
		}

		/*
		 * Now make sure the variable name exits in the
		 * first netcdf file.
		 */
		if ( keep_it ) {
			varid = ncvarid ( ncid, arg_list[j] );
			if ( varid == -1 ) 
				keep_it = FALSE;	
		}

		if ( keep_it ) {

			strcpy ( var[index].name, arg_list[j] );
			var[index].name[strlen(arg_list[j])] = '\0';
			var[index].level = 1;
			var[index].data_type = NC_FLOAT;
			var[index].valid = TRUE;

			index++;

		}
		
	}

	ncclose ( ncid );

	gom_obj.num1v = index - gom_obj.num0v;

	gom_obj.var[jg_time_id].data_type = NC_DOUBLE;



	gom_obj.num_vars = gom_obj.num0v + gom_obj.num1v;


}

