/* argparse.c  94.04.29
 * Copyright 1983-1992   Albert Davis
 * parse name followed by numeric argument from command line
 * to call...  list the arguments:
 *   each is:
 *	string to match (upper case part must match, lower may match
 *		user string is not case sensitive
 *	variable type (see argparse.h)
 *	pointer to variable to fill
 *	if enumerated type: value
 *	if "2double": second argument
 *   end with either null pointer or null string
 *
 * cnt is incrmented to the next argument in the input string
 * returns YES if it did something, NO if not.
 *
 * will try to handle as many arguments as possible.
 */
#include "ecah.h"
#include "argparse.h"
#include "error.h"
#include "declare.h"
/*--------------------------------------------------------------------------*/
	int	argparse(const char*,int*,int,...);
/*--------------------------------------------------------------------------*/
extern	const char e_int[];
/*--------------------------------------------------------------------------*/
int argparse(const char *cmd, int *cnt, int mode, ...)
{
 char *key;
 va_list marker;
 int type;
 int did = NO;

 setmatch(cmd,cnt);
 do {
    va_start(marker,mode);
    while (key = va_arg(marker,char*),  key && *key){
       type = va_arg(marker,int);
       if (type == aDOUBLE || type == aUDOUBLE || type == aODOUBLE
			   || type == a2DOUBLE || type == aSDOUBLE
	|| type ==aIDOUBLE || type ==aOIDOUBLE || type ==aSIDOUBLE){
	  double *arg1;
	  double *arg2;
	  double offset;
	  double scale;
	  arg1 = va_arg(marker,double*);
	  arg2 = (type==a2DOUBLE) ? va_arg(marker,double*) : (double*)NULL;
	  offset = (type==aODOUBLE  ||  type==aOIDOUBLE)
	    			  ? va_arg(marker,double)  : 0.;
	  scale  = (type==aSDOUBLE  ||  type==aSIDOUBLE)
	    			  ? va_arg(marker,double)  : 1.;
	  if (rematch(key)){
	     *arg1 = (type==aUDOUBLE) ? fabs(ctof(cmd,cnt)) : ctof(cmd,cnt);
	     *arg1 += offset;
	     *arg1 *= scale;
	     if (type==aIDOUBLE || type==aOIDOUBLE || type==aSIDOUBLE)
		if (*arg1 != 0.)
		   *arg1 = 1. / *arg1;
	     if (arg2)
		*arg2 = ctof(cmd,cnt);
	     did = YES;
	     break;
	  }
       }else if (type == aINT || type == aUINT  ||  type == aFINT
			      || type == aOCTAL ||  type == aHEX){
	  int *arg;
	  arg = va_arg(marker,int*);
	  if (rematch(key)){
	     switch (type){
		case aUINT:	*arg = abs(ctoi(cmd,cnt));	break;
		case aINT:	*arg = ctoi(cmd,cnt);		break;
		case aOCTAL:	*arg = ctoo(cmd,cnt);		break;
		case aHEX:	*arg = ctox(cmd,cnt);		break;
		case aFINT:	*arg = (int)ctof(cmd,cnt);	break;
	     }
	     did = YES;
	     break;
	  }
       }else if (type == aENUM || type == aORENUM || type == aANDENUM){
	  int *arg;
	  int value;
	  arg = va_arg(marker,int*);
	  value = va_arg(marker,int);
	  if (rematch(key)){
	     switch (type){
		case aENUM:	*arg = value;	break;
		case aORENUM:   *arg |= value;	break;
		case aANDENUM:  *arg &= value;	break;
	     }
	     did = YES;
	     break;
	  }
       }else if (type == aFUNCTION || type == a2FUNCTION){
	  void *arg1;
	  void *arg2;
	  arg1 = va_arg(marker,void*);
	  arg2 = (type==a2FUNCTION) ? va_arg(marker,void*) : NULL;
	  if (rematch(key)){
	     void (*argf)(const char*,int*);
	     argf = (void(*)(const char*,int*))arg1;
	     (*argf)(cmd,cnt);
	     if (arg2){
	        argf = (void(*)(const char*,int*))arg2;
		(*argf)(cmd,cnt);
	     }
	     did = YES;
	     break;
	  }
       }else{
	  error(bERROR, e_int, "argparse");
       }
    }
    va_end(marker);
 } while (key && *key && mode==REPEAT);
 return did;
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
