//-----------------------------------------------------------------------------
// COPYRIGHT  (c)  1997 
// THE REGENTS OF THE UNIVERSITY OF MICHIGAN
// ALL RIGHTS RESERVED
// 
// PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS 
// AND REDISTRIBUTE THIS SOFTWARE AND SUCH DERIVATIVE WORKS FOR 
// ANY PURPOSE, SO LONG AS NO FEE IS CHARGED, AND SO LONG AS 
// THE COPYRIGHT NOTICE ABOVE, THIS GRANT OF PERMISSION, AND 
// THE DISCLAIMER BELOW APPEAR IN ALL COPIES MADE; AND SO LONG 
// AS THE NAME OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY 
// ADVERTISING OR PUBLICITY PERTAINING TO THE USE OR 
// DISTRIBUTION OF THIS SOFTWARE WITHOUT SPECIFIC, WRITTEN 
// PRIOR AUTHORIZATION.
// 
// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 
// FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS 
// FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE 
// UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR 
// IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
// REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 
// FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 
// CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT 
// HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH 
// DAMAGES.
//-----------------------------------------------------------------------------

//
// file:      cmdArg.cc
// purpose:   code declarations for command argument class
//
// Author: Joao Paulo Silva
//
// RCS Version:
//     $Id: cmdArg.cc,v 1.1.1.1 2002/05/01 14:23:27 mguthaus Exp $
//

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <stdlib.h>
#include <vector>
#include <map>
#include <list>
using namespace std;

#include "defs.hh"
#include "cmdArg.hh"


//
// Allocates space and fills a string.
//
void cmdArg::define_arg(char *str)
{
    int len = strlen(str);
    //_string = (char*) malloc (sizeof(char)*(len+1));
    _string = new char [len+1];
    char *p = _string;
    char *q = str;
    while(*(p++) = *(q++)) ;
    _ref_ptr = _string;
    DBGn(cout<<"\t-> Input arg:  "<<str<<endl;
	 cout<<"\t-> Output arg: "<<_string<<endl;);
}


/* the following = operators seem to cause the STL vector class to break */
/* they don't seem to be used anyway, so commenting them out.  - MAR     */
//
// assignment operator (from cmdArg)
//
//cmdArg &cmdArg::operator= (cmdArg &arg) {
//    DBGn(cout<<"\t-> Cmd oper = ARG"<<endl;);
//    define_arg(arg._string);
//    return *this;
//}
//
// assignment operator (from char*)
//
//cmdArg &cmdArg::operator= (char *arg) {
//    DBGn(cout<<"\t-> Cmd oper = CHAR"<<endl;);
//    define_arg(arg);
//    return *this;
//}

//-----------------------------------------------------------------------------
// Access complete string.
//-----------------------------------------------------------------------------

char *cmdArg::string() { return _ref_ptr; }


//-----------------------------------------------------------------------------
// access argument as a string
//-----------------------------------------------------------------------------

cmdArg::operator char*(void) {
    return _string;
}

//
// access argument as if it were an integer
//
cmdArg::operator int(void) {
    int value;
    if (sscanf (_string, "%d", &value) == 1)
	return value;
    else if (matches("TRUE"))
	return 1;
    else if (matches("FALSE"))
	return 0;
    else if (matches("ON"))
	return 1;
    else if (matches("OFF"))
	return 0;
    else // throw an exception?
	return 0;
}

//
// access argument as if it were a long integer
//
cmdArg::operator long(void) {
    long value;
    if (sscanf (_string, "%ld", &value) == 1)
	return value;
    else // throw an exception?
	return 0;
}

//
// access argument as if it were a float
//
cmdArg::operator float(void) {
    float value;
    if (sscanf (_string, "%f", &value) == 1)
	return value;
    else // throw an exception?
	return 0;
}

//
// access argument as if it were a double
//
cmdArg::operator double() {
    double value;
    if (sscanf (_string, "%lf", &value) == 1) {
	return value;
    } else { // throw an exception?
	return 0;
    }
}


//-----------------------------------------------------------------------------
// Shifts the string pointer by pos positions.
//-----------------------------------------------------------------------------

cmdArg &cmdArg::operator>> ( int pos )
{
    for( int k = 0; k < pos && *_string; k++ ) {
	_string++;
    }
    CHECK(if(!*_string)cout<<"Shifted argument out of bounds!?"<<endl;);
    return *this;
}


//
// Test argument to see if it matches a given key.
//
// The match rules for a key "THISkey" are:
//      1. All initial capitalized letters in the key must be matched
//      2. Any additional argument characters must match the remaining 
//         lowercase key
//
// Keys MUST begin with capital letters, and can optionally be 
// followed by lowercase letters.  No capitals can follow a lower
// case letter.
//
int cmdArg::matches (char *str) {
    DBGn(cout<<"\t-> CMD STRING: "<<_string<<endl;
	 cout<<"\t-> CMP STRING: "<<str<<endl;);
    char *c = str;
    char *p = _string;
    //
    // Match all characters of the input string.
    //
    while(*c) {
	if (*c++ != *p++)
	    return FALSE;
    }
    return TRUE;
}

