/**---------------------------------------------------------------------------
 ** 
 ** con2db.c -- 
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/08/02 16:21:58
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/08/03 10:39:17
 ** Update Count    : 3
 ** Directory       : /home/pego/pcd1/codas3c/gfi/src/apps/util/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    Undocumented.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **------------------------------------------------------------------------**/

/* ##################################################################

	 -Introduction:

	 Con2db utility. This programme converts data from a contour file into a
	 CODAS database. You will need the CODAS definition file con2db.def for
	 creating the database.

	 ##################################################################
*/

#include "con2db.h"

/* ------------------------------------------------------------------
	 init_con2db:

	 This function initializes pointers and values in global variables.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int init_con2db(CON2DB_TYPE *con2db)
#else
int ()
#endif
{

	/* Initialize number of variables and variable pointers */
	con2db->blk_com.n    = 0;
	con2db->blk_var.n    = 0;
	con2db->prf_var.n    = 0;
	con2db->blk_com.c    = NULL;
	con2db->blk_var.data = NULL;
	con2db->prf_var.data = NULL;
	con2db->input.n      = 0;
	con2db->input.data   = NULL;

	return(0);

}

/* ------------------------------------------------------------------
	 free_data:

	 This function releases memory from specific variables. Use code to define
	 the type of variable to release.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int free_data(char *var, int code)
#else
int ()
#endif
{

	CON2DB_COM_TYPE   *com;
	CON2DB_DATA_TYPE  *data;
	CON2DB_VARS_TYPE  *vars;
	CON2DB_INPUT_TYPE *in;

	int i;

	/* Assign the correct pointer */
	switch(code)
		{
		case BLK_COM:
			com = (CON2DB_COM_TYPE *) var;
			break;
		case PRF_VAR:
		case BLK_VAR:
			vars = (CON2DB_VARS_TYPE *) var;
			break;
		case IN_DATA:
			in = (CON2DB_INPUT_TYPE *) var;
			break;
		default:
			check_error(1, "Unknown variable type code");
			break;
		}
	
	/* Free the corresponding variable */
	switch(code)
		{
		case BLK_COM:
			if(com->c) free(com->c);
			com->c = NULL;
			break;
		case PRF_VAR:
		case BLK_VAR:
			for(i=0; i<(vars->n); i++){
				data = (CON2DB_DATA_TYPE *) vars->data;
				if(data){
					if(data->d) free(data->d);
					data->d = NULL;
					free(data);
					vars->data = NULL;
				}
			}
			break;
		case IN_DATA:
			if(in->data) free(in->data);
			in->data = NULL;
			break;
			break;
		default:
			check_error(1, "Unknown variable type code");
			break;
		}
			
	return(0);

}

/* ------------------------------------------------------------------
	 free_con2db:

	 This function release dynamically allocated memory in global variables. It
	 assumes that non-allocated pointers are set to NULL.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int free_con2db(void)
#else
int ()
#endif
{

	(void) free_data((char *) &(con2db.blk_var), BLK_VAR);
	(void) free_data((char *) &(con2db.prf_var), PRF_VAR);
	(void) free_data((char *) &(con2db.blk_com), BLK_COM);
	(void) free_data((char *) &(con2db.input),   IN_DATA);
		
	return(0);

}

/* ------------------------------------------------------------------
	 con2db_read_com:

	 If com is not NULL, con2db_read_com reads the comments from file fp and
	 store them into com. If com is NULL, it returns the number of characters
	 required to store the comments. Comments start at current position in fp,
	 and end with a line containing the keyword "end" only.

	 This function aborts the programme on error. On success, it returns the
	 number of characters in the comment.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int con2db_read_com(FILE *fp, CON2DB_COM_TYPE *com)
#else
int ()
#endif
{

	char line[MAXLEN];
	int done, n; 

	/* Get comment */
	if(com){
		done = n = 0;
		while(!done){
			/* Get a full line */
			check_error( fgets(line, 81, fp) == NULL, "Reading comment");
			/* Trim leading and trailing spaces */
			(void) strtrim_lt(line);
			/* Keep comment line */
			if(strcmp(line, "end")){
				strcat(line, "\n");
				strcpy(com->c + n, line);
				n += strlen(line);
			}
			else
				done = 1;
		}
	}
	/* Get length of comment */
	else{
		done = n = 0;
		while(!done){
			/* Get a full line */
			check_error( fgets(line, 81, fp) == NULL, "Reading comment");
			/* Trim leading and trailing spaces */
			(void) strtrim_lt(line);
			/* Update character count */
			if(strcmp(line, "end")){
				strcat(line, "\n");
				n += strlen(line);
			}
			else
				done = 1;
		}
	}
		
	return(n);

}

/* ------------------------------------------------------------------
	 con2db_read_var:

	 If var is not NULL, con2db_read_var reads all variables specified in file
	 fp, and store their corresponding identifier in var. If var is NULL, it
	 counts the number of variables. The variable list starts from current
	 position in fp and ends with entry "end".

	 This function aborts the programme on error. On success, it returns the
	 number of variables.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int con2db_read_var(FILE *fp, CON2DB_VARS_TYPE *var)
#else
int ()
#endif
{

	CON2DB_DATA_TYPE *data;

	char name[MAXLEN], line[MAXLEN], msg[200];
	int done, n; 

	/* Get the list of all variables */
	if(var){
		done = n = 0;
		while(!done){
			/* Get variable name */
			sprintf(msg, "Reading variable %-d", n);
			check_error(fscanf(fp, "%s", name) == 0, msg);
			/* Get column number and variable identifier */
			if(strcmp(name, "end")){
				data = var->data + n;
				/* Get column number */
				sprintf(msg, "Reading column for variable %s.", name);
				check_error(fscanf(fp, "%d", &(data->col)) != 1, msg); 
				/* Get identifier */
				sprintf(msg, "Cannot get identifier for variable %s.", name);
				check_error((data->id = 
										 get_code(data_type_list, name)) == BADINT, msg); 
				/* Initialize data structure */
				data->n = 0;
				data->d = NULL;
				n++;
			}
			else
				done = 1;
		}
	}
	/* Get number of variables */
	else{
		done = n = 0;
		while(!done){
			/* Get variable name */
			check_error( fscanf(fp, "%s", line) == 0, "Reading number of variables");
			/* Update variable count */
			if(strcmp(line, "end")){
				n++;
			}
			else
				done = 1;
		}
		n = n/2;
	}

	return(n);

}

/* ------------------------------------------------------------------
	 con2db_check_var:

	 Con2db_check_var looks in the producer definition file (must be opened) if
	 the variable identifier var_id is defined. It also checks if the
	 corresponding type specified by code is correct.

	 This function aborts the programme on error. On success, it return zero. 
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int con2db_check_var(FILE *fp, int id, int freq)
#else
int ()
#endif
{

	char name[MAXLEN], prev[3][MAXLEN], this[MAXLEN], f[MAXLEN];
	char *c;
	char msg[200];
	int done, n, i;

	/* Get variable name */
	sprintf(msg, "Name for variable identifier %d not in list", id);
	check_error( (c = get_name(data_type_list, id)) == NULL, msg);
	strcpy(name, c);

	/* Initialize the producer definition file */
	fseek(fp, 0, SEEK_SET);
	
	/* Loop through the file to get the variable name */
	sprintf(msg, "Looking for variable %s in producer definition file", name);
	for(i=0; i<3; i++) strcpy(prev[i], "");
	done = 0;
	n = 1;
	while(!done && (n > 0)){
		/* Get next non-commented word */
		check_error( (n = getword_nc(fp, this, MAXLEN)) <= 0, msg);
		/* Check word with variable name */
		if(strcmp(name, this) == 0)
			done = 1;
		else{
			for(i=(3-2); i>=0; i--) strcpy(prev[i+1], prev[i]); 
			strcpy(prev[0], this);
		}
	}

	/* Check if the name has been found */
	sprintf(msg, "Variable %s not present if producer definition file", name);
	check_error(!done, msg);
	
	/* Check consistency of variable frequence */
	switch(freq)
		{
		case BLK_COM:
			strcpy(f, "BLOCK_VAR");
			break;  
		case BLK_VAR:
			strcpy(f, "BLOCK_VAR");
			break;
		case PRF_VAR:
			strcpy(f, "PROFILE_VAR");
			break;
		default:
			sprintf(msg, "Unknown frequence code: %d", freq);
			check_error(1, msg);
			break;
		}
	sprintf(msg, "Variable %s is not defined with frequence %s", name, f);
	check_error( strcmp(prev[2], f), msg);
	
	return(0);
	
}

/* ------------------------------------------------------------------
	 con2db_read_vars:

	 Reads entries from file fp and store them in arg, according to the value of
	 code. Name of entries are checked for existence and consistent frequence 
	 in the producer definition file.

	 This function aborts the programme on error. On success, it returns zero.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int con2db_read_vars(FILE *fp, char *arg, int code)
#else
int ()
#endif
{

	CON2DB_COM_TYPE *com;
	CON2DB_VARS_TYPE *var;
	CON2DB_DATA_TYPE *data;

	FILE *prd;
	LONG pos;
	int n, i;

	char name[MAXLEN];
	char msg[200];

	/* Special checking for non-listed variables */
	switch(code)
		{
		case BLK_COM:
			strcpy(name, "BLOCK_COMMENTS");
			break;
		default:
			strcpy(name, "");
			break;
		}
	if(strlen(name)){
		/* Check if this variable is defined in producer file */
		sprintf(msg, "Variable %s not found in data_list", name);
		check_error( (n = get_code(data_type_list, name)) == BADINT, msg);
		prd = check_fopen(prdfile, "r");
		con2db_check_var(prd, n, code);
		fclose(prd);
	}
	
	/* Read list of data from the control file */
	switch(code)
		{
			
		case BLK_COM:
			/* Read a comment */
			com = (CON2DB_COM_TYPE *) arg;
			/* Get number of characters */
			pos = ftell(fp);
			n = con2db_read_com(fp, NULL);
			/* Read comment */
			if(n > 0){
				fseek(fp, pos, SEEK_SET);
				check_error((com->c = (char *) calloc((size_t) n, sizeof(char))) 
										== NULL, "Allocating memory for comment");
				com->n = con2db_read_com(fp, com);
			}
			/* Output message */
			report_msg("\n% ");
			for(i=0; i<com->n; i++){
				if(com->c[i] == '\n')
					report_msg("\n%% ");
				else{
					sprintf(msg, "%c", com->c[i]);
					report_msg(msg);
				}
			}
			break;
		case BLK_VAR:
		case PRF_VAR:
			/* Read a list of variables */
			var = (CON2DB_VARS_TYPE *) arg;
			/* Get number of elements */
			pos = ftell(fp);
			n = con2db_read_var(fp, NULL);
			/* Get the variables */
			if(n > 0){
				fseek(fp, pos, SEEK_SET);
				check_error((var->data = 
										 calloc((size_t) n, sizeof(CON2DB_DATA_TYPE))) == NULL,
										"Allocating memory for data structure");
				var->n = con2db_read_var(fp, var);
				/* Check the presence of all data identifiers */
				prd = check_fopen(prdfile, "r");
				for(i=0; i<n; i++){
					data = (CON2DB_DATA_TYPE *) (var->data + i);
					con2db_check_var(prd, data->id, code);
				}
				fclose(prd);
				/* Output message */
				report_msg("\n% ");
				for(i=0; i<n; i++){
					data = (CON2DB_DATA_TYPE *) (var->data + i);
					sprintf(msg, "   Variable: %s [id=%-d] Column: %-d\n%% ", 
									get_name(data_type_list, data->id), data->id, data->col);
					report_msg(msg);
				}
			}
			break;
		default:
			sprintf(msg, "Unknown variable code %d", code);
			check_error(1, msg);
			break;
		}
			
	return(0);

}

/* ------------------------------------------------------------------
	 get_blk_nmax:

	 This function parses the input file to find the number of different values
	 for a block variable.

	 PARAMETERS:

	    fp   : File pointer to input file (it does not need to point at the
			       beginning of the file)
	    col  : The column number of the variable in the input file
			vmax : Total number of columns in input file

	 RETURNS:

	    The number of elements for this block variable, or EOF on error.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int get_blk_nmax(FILE *fp, int col, int vmax)
#else
int ()
#endif
{

	FLOAT *data;
	int i, n, found, ierr=0;

	char fmt[MAXLEN];
	char msg[MAXLEN];

	/* Reset input file */
	fseek(fp, 0, SEEK_SET);

	/* Build read format */
	strcpy(fmt, "");
	for(i=1; i<=(col-1); i++)
		strcat(fmt, "%*f ");
	strcat(fmt, "%f ");
	for(i=(col+1); i<=vmax; i++)
		strcat(fmt, "%*f ");
	
	/* Allocate tmp array to hold data */
	sprintf(msg, 
					"Allocating memory for temporary data in column %-d\n", col);
	if(error_found( (data = (FLOAT *) calloc(MAX_BINS, sizeof(FLOAT))) == NULL,
									msg))
		return(EOF);
	
	/* Loop through the profiles */
	n = 0;
	while( (ierr = fscanf(fp, fmt, data+n)) == 1){
		/* Check if this value is already known */
		i = found = 0;
		while(!found && (i < n)){
			if(data[i] == data[n])
				found = 1;
			i++;
		}
		/* Update number of different elements */
		if(!found || (n == 0))
			n++;
	}
	/* Check reading errors */
	sprintf(msg, "Parsing column %-d\n", col);
	ierr = error_found(ierr && (ierr != EOF), msg);
	
	/* Release memory */
	free(data);

	if(!ierr && (n > 0))
		return(n);
	else
		return(EOF);

}

/* ------------------------------------------------------------------
	 get_prf_nmax:

	 This function parses the input file to determine the maximal number of data
	 for a given profile variable.

	 PARAMETERS:

	    fp   : File pointer to input file (it does not need to point at the
			       beginning of the file)
	    col  : The column number of the variable in the input file
			vmax : Total number of columns in input file

	 RETURNS:

	    The maximal number of elements for this profile variable, or EOF on
	    error. 
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int get_prf_nmax(FILE *fp, int col, int vmax)
#else
int ()
#endif
{

	FLOAT *data, prev, this;
	int i, nmax, n, ierr=0;
	char fmt[MAXLEN];
	char msg[200];

	/* Reset input file */
	fseek(fp, 0, SEEK_SET);

	/* Build read format */
	strcpy(fmt, "%f ");
	for(i=2; i<=(col-1); i++)
		strcat(fmt, "%*f ");
	strcat(fmt, "%f ");
	for(i=(col+1); i<=vmax; i++)
		strcat(fmt, "%*f ");
	
	/* Allocate space for tmp array to hold data */
	sprintf(msg, 
					"Allocating memory for temporary data in column %-d\n", 
					col);
	if(error_found( (data = (FLOAT *) calloc(MAX_BINS, sizeof(FLOAT))) == NULL,
									msg))
		return(EOF);

	/* Initialize data */
	for(i=0; i<MAX_BINS; i++)
		data[i] = BADFLOAT;

	/* Initialize first profile */
	n = 0;
	sprintf(msg, "Reading first line in column %-d\n", col);
	ierr = error_found(fscanf(fp, fmt, &this, data+n) != 2, msg);

	/* Loop through the profiles */
	nmax = 0;
	while(!ierr){
		
		/* Profile Initializations */
		prev = this;
		n = 0;

		/* Loop inside profile */
		while(!ierr && (prev == this)){
			n++;
			ierr = fscanf(fp, fmt, &this, data+n);
			ierr = (ierr != 2) ? ierr : 0;
		}
		
		/* Get number of data */
		if(!ierr || (ierr == EOF)){
			i = n-1;
			while((i >= 0) && (data[n] > ADJ_BADFLOAT)) i--;
			/* Keep maximal number of data */
			nmax = max_val(nmax, i+1);
			/* Current line is first of next profile */
			data[0] = data[n];
		}
		
	}
	/* Check for error */
	sprintf(msg, "Parsing column %-d\n", col);
	ierr = error_found(ierr && (ierr != EOF), msg);
	
	/* Release memory */
	free(data);

	if(!ierr && (nmax > 0))
		return(nmax);
	else
		return(EOF);

}

/* ------------------------------------------------------------------
	 init_vars:

	 This function set data for all variables to bad. It returns zero on
	 success, and EOF on error.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int init_vars(CON2DB_VARS_TYPE *var)
#else
int ()
#endif
{

	CON2DB_DATA_TYPE *data;
	int i, j;
	char msg[200];

	/* Loop through the variable list */
	for(i=0; i<(var->n); i++){

		data = (CON2DB_DATA_TYPE *) (var->data + i);
		
		/* Check if data should be allocated */
		if(data->d == NULL){
			sprintf(msg, "Allocating memory for data in column %-d\n", data->col);
			if(error_found( (data->d = 
											 (FLOAT *) calloc((size_t) data->n, 
																				sizeof(FLOAT))) == NULL, msg))
				return(EOF);
		}
		
		/* Initialize all variables in list */
		for(j=0; j<(data->n); j++)
			data->d[j] = BADFLOAT;
	}

	return(0);

}

/* ------------------------------------------------------------------
	 get_data:

	 Read a full line of input data, and convert both time and position for use
	 with database. 

	 RETURNS: zero on success, EOF at end of file, or something else on error. 
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int get_input_data(FILE *fp, CON2DB_INPUT_TYPE *in, int year_base)
#else
int ()
#endif
{

	LONG hun;
	int i, ierr=0;

	/* Read mandatory columns */
	ierr = fscanf(fp, "%lf %lf %lf", 
								&(in->yd), &(in->pos.lon), &(in->pos.lat));
	if(ierr != 3){
		error_found(ierr != EOF, "Reading first columns\n");
		return(ierr);
	}
	ierr = 0;

	/* Convert time */
	yd_to_ymdhmh_time(in->yd, year_base, &(in->time));

	/* Convert position */
	hun = (LONG) (in->pos.lon * 360000.0);
	HUNPOS(&(in->position.lon), &hun);
	hun = (LONG) (in->pos.lat * 360000.0);
	HUNPOS(&(in->position.lat), &hun);
	
	/* Read the rest of the data */
	for(i=0; i<(in->n) && !ierr; i++)
		ierr = (fscanf(fp, " %f", in->data + i) != 1);
	if(error_found(ierr, "Reading input data\n"))
		return(ierr);
	
	return(0);

}

/* ------------------------------------------------------------------
	 new_prf:

	 This function creates a new profile with the given time, and loads at the
	 same time the profile position. Returns non-zero on error.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int new_profile(CON2DB_INPUT_TYPE *in)
#else
int ()
#endif
{

	int ierr=0;

	/* Open new profile */
	if(error_found( ierr = open_prf(&(in->time)), "open_prf()\n"))
		return(ierr);

	/* Add profile position */
	ierr = dbadd_cnf(POSITION, (char *) &(in->position), 
									 sizeof(DMSH_POSITION_TYPE), "Adding profile position\n");
	
	return(ierr);

}


/* ------------------------------------------------------------------
	 load_vars:
	 
	 Load the variables given in the list. The code can be used to specify a
	 special structure. Returns non-zero on error.
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int load_vars(char *var, int code)
#else
int ()
#endif
{

	CON2DB_COM_TYPE  *com;
	CON2DB_VARS_TYPE *vars;
	CON2DB_DATA_TYPE *data;

	CON2DB_ACC_VAR_TYPE  acc;
	UBYTE                *pf;

	unsigned int nbad=0;
	int n, i, ierr=0;

	char msg[200];

	/* Load special data structures */
	if(code){
		switch(code)
			{
			case BLK_COM:
				/* Block Comments */
				com = (CON2DB_COM_TYPE *) var;
				ierr = dbadd_cnf(BLOCK_COMMENTS, (char *) com->c, 
												 (unsigned int) com->n, 
												 "Loading block comments\n");
				break;
			case ACC_VAR:
				/* Access Variables */
				n = *((int *) var);
				acc.fgb = 0;
				acc.lgb = (SHORT) n;
				acc.Usa = acc.Vsa = 0.0;
				acc.uf1 = acc.uf2 = acc.uf3 = acc.uf4 = 0; 
				ierr = dbadd_cnf(ACCESS_VARIABLES, (char *) &acc,
												 (unsigned int) sizeof(CON2DB_ACC_VAR_TYPE),
												 "Loading access variables\n");
				break;
			case PRF_FLAGS:
				/* Profile flags */
				n = *((int *) var);
				if(error_found( (pf = (UBYTE *) calloc(n, sizeof(UBYTE))) == NULL,
												 "Allocating memeory for profile flags\n"))
					return(EOF);
				set_byte((UBYTE *) pf, (UBYTE) '\0', (unsigned int) n);
				ierr = dbadd_cnf(PROFILE_FLAGS, (char *) pf,
												 (unsigned int) (n*sizeof(UBYTE)),
												 "Loading profile flags\n");
				free((void *) pf);
				break;				
			default:
				ierr = error_found(1, "Unknown structure code\n");
				break;
			}
	}
	/* Load data variables */
	else{
		vars = (CON2DB_VARS_TYPE *) var;
		/* Loop through the list of variables */
		for(i=0; i<(vars->n) && !ierr; i++){
			/* Pointer to data structure */
			data = (CON2DB_DATA_TYPE *) (vars->data + i);
			/* Add data */
			DBADD_F( &(data->id), data->d, (unsigned int *) &(data->n), &nbad, &ierr);
			/* Check error */
			sprintf(msg, "DBADD_F: Adding %s.", get_name(data_type_list, data->id));
			DBERROR(&ierr, msg);
		}
	}
	
	return(ierr);
}
													
/* ------------------------------------------------------------------
	 Main:
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
void do_it(FILE *fp_cnt)
#else
void ()
#endif
{

	CON2DB_COM_TYPE   *blkc;
	CON2DB_VARS_TYPE  *blkv;
	CON2DB_VARS_TYPE  *prfv;
	CON2DB_INPUT_TYPE *in;
	CON2DB_DATA_TYPE  *data;
	
	FILE *fp;
	double prev;

	int n, i, nvar_max, ierr=0;
	char *c, str[200], msg[200];

	/* Initializations */
	init_con2db(&con2db);
	blkc = (CON2DB_COM_TYPE *)   &(con2db.blk_com);
	blkv = (CON2DB_VARS_TYPE *)  &(con2db.blk_var);
	prfv = (CON2DB_VARS_TYPE *)  &(con2db.prf_var);
	in   = (CON2DB_INPUT_TYPE *) &(con2db.input);

	/* Get parameters */
	check_error(get_parameters(fp_cnt, con2db_param, NULL),
							"Getting parameters");
	print_parameters(stdout, con2db_param, NULL, "\n");
	
	/* Execute options */
	check_error(execute_options(fp_cnt, con2db_options, ECHO) <= 0,
							"Reading options");
	
	/* Initialize input file */
	fp = check_fopen(confile, "r");

	/* Initialize space for an input line */
	in->n = blkv->n + prfv->n;
	ierr = error_found( (in->data = 
											 (FLOAT *) calloc((size_t) in->n, sizeof(FLOAT))) 
											== NULL, "Allocating memory for input line\n");
	if(ierr) goto on_error;
	
	/* Get the max number of elements for all block variables */
	report_msg("\nGetting number of data for block variables ... \n");
	for(i=0; i<(blkv->n) && !ierr; i++){
		data = (CON2DB_DATA_TYPE *) (blkv->data + i);
		ierr = (( data->n = 
							get_blk_nmax(fp, data->col, blkv->n + prfv->n + 3) ) < 0);
		c = get_name(data_type_list, data->id);
		/* Message */
		strcpy(str, c);
		sprintf(msg, "   Found %3d data for %s\n", data->n, str);
		report_msg(msg);
	}
	if(error_found(ierr, "get_blk_nmax()\n")) goto on_error;

	/* Get the max number of elements for all profile variables */
	report_msg("\nGetting number of data for profile variables ...\n");
	nvar_max = 0;
	for(i=0; i<(prfv->n) && !ierr; i++){
		data = (CON2DB_DATA_TYPE *) (prfv->data + i);
		ierr = (( data->n = 
							get_prf_nmax(fp, data->col, blkv->n + prfv->n + 3) ) < 0); 
		nvar_max = max_val(nvar_max, data->n);
		/* Message */
		c = get_name(data_type_list, data->id);
		strcpy(str, c);
		sprintf(msg, "   Found %3d data for %s\n", data->n, str);
		report_msg(msg);
	}
	if(error_found(ierr, "get_prf_nmax()\n")) goto on_error;
	
	/* Initialize data space for data */
	ierr = error_found( init_vars(blkv), 
											"Initializing space for block variables\n");
	if(ierr) goto on_error;
	ierr = error_found( init_vars(prfv), 
											"Initializing space for profile variables\n");
	if(ierr) goto on_error;

	/* Create database */
	ierr = error_found( create_db(1, dbname, prdfile), "create_db()\n");
	if(ierr) goto on_error;
	/* Open new block */
	ierr = error_found( open_blk(), "open_blk()\n");
	if(ierr) goto on_error;
	
	/* Initialize input file */
	fseek(fp, 0, SEEK_SET);

	/* Initialize first profile line */
	ierr = error_found( get_input_data(fp, in, year_base),
											"Reading first line of input data\n");
	if(ierr) goto on_error;

	/* Loop through the profiles */
	while(!ierr){
	
		/* Profile initializations */
		ierr = error_found(new_profile(in), "Adding new profile\n");
		prev = in->yd;
		n = 0;
		
		/* Message */
	  ymdhms_to_str(str, &(in->time), 0);
		sprintf(msg, "  Profile: %s\n", str);
		report_msg(msg);

		/* Loop inside profile */
		while(!ierr && (prev == in->yd)){
			/* Store input data in their corresponding structures */
			for(i=0; i<(blkv->n); i++){
				data = (CON2DB_DATA_TYPE *) blkv->data + i;
				(data->d)[n] = (in->data)[data->col - 3 - 1];
			}
			for(i=0; i<(prfv->n); i++){
				data = (CON2DB_DATA_TYPE *) prfv->data + i;
				(data->d)[n] = (in->data)[data->col - 3 - 1];
			}
			/* Read next input line */
			ierr = get_input_data(fp, in, year_base);

			/* Update data index */
			n++;
		}
		
		/* Check for errors */
		error_found(ierr && (ierr != EOF), "Reading contour data\n");
		
		/* Process current profile */
		if(!ierr || (ierr == EOF)){
			/* Load profile variables */
			if(error_found( load_vars((char *) prfv, 0), 
											"Loading profile variables\n"))
				goto on_error;
			i = nvar_max - 1;
			if(error_found( load_vars((char *) &i, ACC_VAR), "load_vars()\n"))
				goto on_error;
			i = nvar_max;
			if(error_found( load_vars((char *) &i, PRF_FLAGS), "load_vars()\n"))
				goto on_error;
			/* Close profile */
			if(error_found(close_prf(), "Closing profile\n"))
				goto on_error;
			/* Re-initialize profile variables */
			init_vars(prfv);
		}
	}
	/* Check for errors */
 	ierr = error_found(ierr && (ierr != EOF), "Reading contour data\n");
	if(ierr) goto on_error;
	
	/* Load block variables */
	ierr = error_found( load_vars((char *) blkv, 0), 
											"Loading block variables\n");
	if(ierr) goto on_error;

	/* Load other block variables */
	ierr = error_found(load_vars((char *) blkc, BLK_COM),
										 "Loading block comments\n");

on_error:

	/* Close database */
	close_db();

	/* Close files */
	fclose(fp);

	/* Release memory */
	free_con2db();
			
	if(ierr)
		printf("\nCON2DB: ERROR !!!\n");
	else
		printf("\nCON2DB: done.\n");

	return;

}


