/**---------------------------------------------------------------------------
 ** 
 ** xoption.c -- 
 ** 
 ** Author          : Pierre Jaccard
 ** Created On      : 1999/07/15 21:13:13
 ** Last Modified By: Pierre Jaccard
 ** Last Modified On: 1999/08/02 12:11:35
 ** Update Count    : 8
 ** Directory       : /home/pego/pcd1/codas3c/gfi/src/libs/misc/
 ** Version         : 0.0
 ** Status          : Unknown
 ** ---------------------------------------------------------------------- ** 
 ** DESCRIPTION: 
 ** 
 **    Undocumented.
 ** 
 ** ---------------------------------------------------------------------- ** 
 ** REVISIONS: 
 ** ---------------------------------------------------------------------- ** 
 ** CHANGES: 
 **------------------------------------------------------------------------**/

#include "xoption.h"

/* ------------------------------------------------------------------ 
	 Read a keyword from a control file and execute corresponding options. 

	 Parameter arg must be a pointer to an array of KEYWORD_LIST_ENTRY_TYPE
	 and code the index_code in this array, defining which options to
	 execute. These are:

	    - If name_list pointer is defined, the code is converted to the one
				corresponding to the keyword.

			- If function is defined, it is called as

			       <function>(<fp>, <arg>, <code>)

			- The following assignements and actions are carried out, according to
				the elements the KEYWORD_LIST_ENTRY_TYPE:

				  1) pointers to <variable> and <function> are NULL: the function
						 returns <code>.

					2) pointer to <variable> is defined, and <type_code> is zero:
						 <variable> is assigned to <code>. Hence, <variable> must be
						 declared as an integer. Therefore, assignement is also carried
						 out if <type_code> is TYPE_INT. Assignement is performed whether
						 or not the pointer to <function> is defined, and carried out
						 before executing <function> (if defined).

					3) only pointer to <variable> is NULL: <function> is executed
						 without considering its return value. Of course, nothing is
						 assigned to <variable>.

					4) both <variable> and <function> are defined, and <type_code> is
						 positive and corresponds to one of the TYPE_CODES defined in
						 `ioserv.h': <variable> is assigned to the return value of
						 <function> (which is converted to <type_code> before).
   
   RETURNS: 1
   ------------------------------------------------------------------ */

#if PROTOTYPE_ALLOWED
int op_get_keyword(/* Pointer to control file */
                   FILE *fp, 
                   /* The argument: the list of keywords */
                   char *arg, 
                   /* The code: index to the xoption in the list of keywords */
                   int code)
#else
int op_get_keyword(fp, arg, code)
FILE *fp;
char *arg;
int code;
#endif
{

	XOPTION_TYPE *kwl, *kw;
	NAME_LIST_ENTRY_TYPE    *nml;
	char par[80], *c, msg[200];

	/* Initializations */
	c = NULL;
	kwl = (XOPTION_TYPE *) arg;

	/* Read the keyword from the file */
	op_get_param(fp, par, TYPE_STRING);

	/* Get the correct keyword entry from the list */
	kw = kwl;
	while((kw->index_code > 0) && (kw->index_code != code))
		kw++;
	check_error(kw->index_code != code, 
							"Cannot find the correct entry in keyword list");
	
	/* Get new code value */
	if(kw->name_list != NULL) 
		code = get_code(kw->name_list, par);
	if(code == BADINT){
		sprintf(msg, "\n Unknown keyword:  %s\n\n Possible keywords are:\n\t", par);
		report_msg(msg);
		nml = kw->name_list;
		while(nml->name != NULL){
			sprintf(msg, "%s\n\t", nml->name);
			report_msg(msg);
			nml++;
		}
		exit(-1);
	}
	
	/* Check if the variable should be assigned to code */
	if((kw->variable != NULL) 
		 && ((kw->type_code == 0) || (kw->type_code == TYPE_INT)))
		*((int *) kw->variable) = code;
	
	/* Check for a function to be called */
	if(kw->function != NULL)
		c = (*kw->function)(fp, kw->arg, code);
	
	/* Check if variable should be assigned to the content of c */
	if((c != NULL) && (kw->type_code > 0) && (kw->variable != NULL)){
		switch(kw->type_code)
			{
			case TYPE_INT:
				*((int *) kw->variable) = *((int *) c);
				break;
			default:
				sprintf(msg, "\n\n ERROR: Type code %d is not implemented yet\n\n",
								code);
				report_msg(msg);
				exit(-1);
			}
	}
	return(1);

}

/* ------------------------------------------------------------------
	 Read a range from a control file.

   RETURNS: 1
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int op_get_range(/* Pointer to control file */
                 FILE *fp, 
                 /* The argument: a pointer to a RANGE_TYPE structure */
                 char *arg, 
                 /* The code: not used */
                 int code)
#else
int op_get_range()
FILE *fp;
char *arg;
int code;
#endif
{

	RANGE_TYPE *rng;

	rng = (RANGE_TYPE *) arg;

	check_error(get_range(fp, rng), "Getting range");
	print_range(stdout, rng, "\n%%");

	return(1);

}

/* ------------------------------------------------------------------
	 Interface to function fget_ymdhms_time() for option lists.

   RETURNS: 1
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int op_get_ymdhmh_time(/* Pointer to control file */
                       FILE *fp, 
                       /* The argument: pointer to an YMDHMS time structure */
                       char *arg, 
                       /* The code: input is reported if set to TRUE */
                       int code)
#else
int op_get_ymdhmh_time()
#endif
{

	YMDHMS_TIME_TYPE *time;
	char msg[50], str[50];

	time = (YMDHMS_TIME_TYPE *) arg;

	check_error(fget_ymdhmh_time(fp, time), "fget_ymdhmh_time()");
	
	if(code){
		ymdhms_to_str(str, time, 0);
		sprintf(msg, " %s", str);
		report_msg(msg);
	}
	
	return(1);

}

/* ------------------------------------------------------------------
	 Interface to get_time_range() for option lists.

   RETURNS: 1
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int op_get_time_range(/* Pointer to control file */
                      FILE *fp, 
                      /* The argument: a pointer to an array of two YMDHMS
                         time structures 
                       */
                      char *arg, 
                      /* The code: input is reported if set to TRUE */
                      int code)
#else
int op_get_time_range()
#endif
{

	YMDHMS_TIME_TYPE *time;
	char str[50], msg[50];

	time = (YMDHMS_TIME_TYPE *) arg;

	check_error(get_time_range(fp, time, time+1) != 1,
							"get_time_range()");
	
	if(code){
		time_range_to_str(str, time, time+1);
		sprintf(msg, " %s", str);
		report_msg(msg);
	}

	return(1);

}

/* ------------------------------------------------------------------
	 Interface to get_dmsh_position() for use in control files.

   RETURNS: 1
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int op_get_dmsh_position(/* Pointer to control file */
                         FILE *fp, 
                         /* The argument: a pointer to DMSH position */
                         char *arg, 
                         /* The code: 1 or 11 for latitude. Values larger than
                            5 will report the read value */
                         int code)
#else
int op_get_dmsh_position()
#endif
{

	DMSH_POSITION_TYPE *pos;
	int c, lat;
	char str[50], msg[50];

	/* Initializations */
	pos = (DMSH_POSITION_TYPE *) arg;
	c = (code > 5) ? code-10 : code;
	lat = (c == 1) ? 1 : 0;

	check_error(get_dmsh_position(fp, pos, c), "get_dmsh_position()\n");
	check_error(invalid_position(pos, lat), "Invalid position\n");
	
	if(code > 5){
		dmsh_to_str(str, pos, c, DM_FORMAT_CODE);
		sprintf(msg, " %s", str);
		report_msg(msg);
	}

	return(1);

}

/* ------------------------------------------------------------------
	 Interface to get_position_range() for use in control files.

   RETURNS: 1
	 ------------------------------------------------------------------ */
#if PROTOTYPE_ALLOWED
int op_get_position_range(/* Pointer to control file */
                          FILE *fp, 
                          /* The argument: array of four DMSH position
                             structures */
                          char *arg, 
                          /* The code: input is reported if set to TRUE */
                          int code)
#else
int op_get_position_range()
#endif
{

	DMSH_POSITION_TYPE *pos;
	char str[200], msg[200];

	/* Initializations */
	pos = (DMSH_POSITION_TYPE *) arg;

	check_error(get_position_range(fp, pos, pos+2), "get_position_range()");

	if(code){
		position_range_to_str(str, pos, DM_FORMAT_CODE);
		sprintf(msg, " %s", str);
		report_msg(msg);
	}

	return(1);

}

