summaryrefslogtreecommitdiffstats
path: root/commline
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
commit8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch)
treebd328a4dd4f92d32202241b5e3a7f36177792c5f /commline
downloadrasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip
Initial commitv8.0
Diffstat (limited to 'commline')
-rw-r--r--commline/Makefile.am31
-rw-r--r--commline/cmlparser.cc915
-rw-r--r--commline/cmlparser.hh242
-rw-r--r--commline/test/Makefile43
-rw-r--r--commline/test/functest.cc59
-rw-r--r--commline/test/test_cml.cc101
6 files changed, 1391 insertions, 0 deletions
diff --git a/commline/Makefile.am b/commline/Makefile.am
new file mode 100644
index 0000000..6ff5043
--- /dev/null
+++ b/commline/Makefile.am
@@ -0,0 +1,31 @@
+# -*-Makefile-*-
+#
+# This file is part of rasdaman community.
+#
+# Rasdaman community is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Rasdaman community is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+# rasdaman GmbH.
+#
+# For more information please see <http://www.rasdaman.org>
+# or contact Peter Baumann via <baumann@rasdaman.com>.
+#
+# MODULE: commline
+#
+# COMMENTS:
+#
+##################################################################
+
+noinst_LIBRARIES=libcommline.a
+libcommline_a_SOURCES=cmlparser.cc cmlparser.hh
diff --git a/commline/cmlparser.cc b/commline/cmlparser.cc
new file mode 100644
index 0000000..7c3d50d
--- /dev/null
+++ b/commline/cmlparser.cc
@@ -0,0 +1,915 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * SOURCE: cmlparser.cc
+ *
+ * MODULE: akinside/commline
+ *
+ * PURPOSE:
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+#include <cmlparser.hh>
+
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstring>
+
+#include <ctype.h>
+#include <vector>
+#include <iomanip>
+#include <cstdlib>
+
+using namespace std;
+
+static const char rcsid[] = "@(#)commline,cmlparser: $Id: cmlparser.cc,v 1.5 2006/01/17 07:50:07 rasdev Exp $";
+
+const char* CommandLineParserVersion = "1.0 (c) 2003 Dr. Peter Baumann";
+
+//#############################################################
+
+char*
+dupString(const char* cc)
+{
+ if(cc)
+ {
+ // strdup uses malloc, we would like to avoid it
+ char *dup = new char[strlen(cc)+1];
+ // new throws? we hope
+ strcpy(dup,cc);
+ return dup;
+ }
+
+ return NULL;
+}
+
+CmlException::CmlException(const string& whatString)
+:problem(whatString)
+{
+}
+
+CmlException::~CmlException() throw()
+{
+}
+
+const char* CmlException::what() const throw()
+{
+ return problem.c_str();
+}
+
+
+//############################################################
+
+const char* CommandLineParameter::defaultTitle = "default: ";
+const char* CommandLineParameter::descSep = " ";
+const char* CommandLineParameter::descTab = "\t";
+const char* CommandLineParameter::descIndent = " ";
+const char* CommandLineParameter::descLineSep = "\n";
+const char CommandLineParameter::descOpen = '<';
+const char CommandLineParameter::descClose = '>';
+const char* CommandLineParameter::descLeftDefault = "(";
+const char* CommandLineParameter::descRightDefault = ")";
+
+
+
+CommandLineParameter::CommandLineParameter(char newShortName, const char* newLongName, const char* newDefaultValue) throw(CmlException)
+ : longName(NULL), defaultValue(NULL), descriptionText(NULL), paramDescription(NULL)
+{
+
+ if((!isalnum(newShortName) || (newShortName == CommandLineParser::noShortName))
+ && (!newLongName || !strcmp(newLongName, CommandLineParser::noLongName)))
+ throw CmlException(string("") + "Invalid option: shortName='" + newShortName + "' longName='" + (newLongName? newLongName: "NULL") + "'");
+
+ shortName = newShortName;
+ longName = dupString(newLongName);
+ present = false;
+ wasLongName = false;
+ defaultValue = dupString(newDefaultValue);
+
+ shNameString[0] = newShortName;
+ shNameString[1] = 0;
+
+ paramDescription = NULL;
+ descriptionText = NULL;
+}
+
+CommandLineParameter::CommandLineParameter(char newShortName, const char* newLongName, long newDefaultValue) throw(CmlException)
+ : longName(NULL), defaultValue(NULL), descriptionText(NULL), paramDescription(NULL)
+{
+
+ if((!isalnum(newShortName) || (newShortName == CommandLineParser::noShortName))
+ && (!newLongName || !strcmp(newLongName, CommandLineParser::noLongName)))
+ throw CmlException(string("") + "Invalid option: shortName='" + newShortName + "' longName='" + (newLongName? newLongName: "NULL") + "'");
+
+ shortName = newShortName;
+ longName = dupString(newLongName);
+ present = false;
+ wasLongName = false;
+
+ // convert default to ASCII, for uniform handling
+ stringstream s;
+ s << newDefaultValue;
+ defaultValue = dupString( s.str().c_str() );
+
+ shNameString[0] = newShortName;
+ shNameString[1] = 0;
+
+ paramDescription = NULL;
+ descriptionText = NULL;
+}
+
+const char* CommandLineParameter::calledName()
+{
+ const char* retval=NULL;
+
+ if(shortName == CommandLineParser::noShortName)
+ retval = longName;
+ else
+ if(!strcmp(longName, CommandLineParser::noLongName))
+ retval = shNameString;
+ else
+ retval = (wasLongName && longName) ? longName : shNameString;
+ return retval;
+}
+
+void CommandLineParameter::reset()
+{
+ present=false;
+ wasLongName=false;
+}
+
+
+CommandLineParameter::~CommandLineParameter()
+{
+ if(longName)
+ delete[] longName;
+
+ if(defaultValue)
+ delete[] defaultValue;
+
+ // paramDescription and descriptionText point both to the same string
+ // but depends on the context which has to be deleted
+ if(paramDescription)
+ {
+ delete[] paramDescription;
+ paramDescription = NULL;
+ descriptionText = NULL;
+ }
+ if(descriptionText)
+ delete[] descriptionText;
+}
+
+void CommandLineParameter::setDescription(const char *desc)
+{
+ // cleaning the previous paramDescription
+ // paramDescription and descriptionText point both to the same string
+ // but depends on the context which has to be deleted
+ if(paramDescription)
+ {
+ delete[] paramDescription;
+ paramDescription = NULL;
+ descriptionText = NULL;
+ }
+ if(descriptionText) delete[] descriptionText;
+
+ if(desc==NULL)
+ {
+ paramDescription=NULL;
+ descriptionText =NULL;
+ }
+ else
+ {
+ paramDescription = dupString(desc);
+
+ // if the string is "<text> line1...", for options with parameters
+ if(paramDescription[0]==descOpen)
+ {
+ int len = strlen(paramDescription);
+ int i=0;
+ for(i=0;i<len;i++)
+ {
+ if((paramDescription[i]==descClose) && (i<len-1))
+ {
+ paramDescription[i+1]=0;
+ descriptionText = paramDescription+i+2;
+ break;
+ }
+ }
+
+ if(i>=len-1) // I didn't find descClose
+ {
+ descriptionText=paramDescription;
+ paramDescription=NULL;
+ }
+ }
+ else
+ {
+ // the string is just "line1..." for options without parameters
+ descriptionText = paramDescription;
+ paramDescription = NULL;
+ }
+ }
+
+#ifdef DEBUG
+ cout<<"desc="<<desc<<endl;
+ if(paramDescription==NULL)
+ cout<<"paramDescription=NULL"<<endl;
+ else
+ cout<<"paramDescription="<<paramDescription<<endl;
+
+ if(descriptionText==NULL)
+ cout<<"descriptionText=NULL"<<endl;
+ else
+ cout<<"descriptionText="<<descriptionText<<endl;
+#endif
+}
+
+bool CommandLineParameter::doesMatch(char c)
+{
+ if(shortName==CommandLineParser::noShortName)
+ return false;
+ return shortName==c ? true:false;
+}
+
+bool CommandLineParameter::doesMatch(const char* s)
+{
+ if(longName==NULL)
+ return false;
+ if(s == NULL)
+ return false;
+ if(!strcmp(longName, CommandLineParser::noLongName))
+ return false;
+ return strcmp(longName,s)==0 ? true:false;
+}
+
+char CommandLineParameter::getShortName() const
+{
+ return shortName;
+}
+
+const char* CommandLineParameter::getLongName() const
+{
+ return longName;
+}
+
+/// print help text, composed from the option descriptions passwd to cml
+ostream& CommandLineParameter::printHelp(ostream &os)
+{
+ if(descriptionText == NULL)
+ return os;
+
+ static const unsigned int longNameLen=30;
+ static const unsigned int longParamLen=30;
+
+ os << CommandLineParameter::descIndent;
+
+ if(isalnum(shortName) && (shortName != CommandLineParser::noShortName))
+ os<< CommandLineParser::ShortSign <<shortName;
+ // we want a flush left display, don't adjust short/long params each -- PB 2003-jul-05
+ // else
+ // os << " ";
+
+ if((isalnum(shortName) && (shortName != CommandLineParser::noShortName)) &&
+ (longName && strcmp(longName, CommandLineParser::noLongName)))
+ os << ", ";
+ // we want a flush left display, don't adjust short/long params each -- PB 2003-jul-05
+ // else
+ // os << " ";
+
+ // we want the parameter to appear right after the option, no adjustment -- PB 2003-jul-
+ // os.setf(ios::left);
+ // os << setw(longNameLen);
+
+ if(longName && strcmp(longName, CommandLineParser::noLongName))
+ {
+ string s;
+ s += CommandLineParser::LongSign;
+ s += longName;
+ os << s.c_str();
+ }
+ else
+ os << "";
+
+ // separator between param name and value
+ os << CommandLineParameter::descSep;
+
+ // no adjustment, again
+ // os.setf(ios::left);
+ // os << setw(longParamLen);
+
+ // param value, such as "<database>"
+ if(paramDescription)
+ os << paramDescription;
+
+ // separator between param value and default
+ if(defaultValue)
+ os << CommandLineParameter::descTab;
+
+ // print default, if any: "(default: 42)"
+ if(defaultValue)
+ os << CommandLineParameter::descLeftDefault << defaultTitle << defaultValue << CommandLineParameter::descRightDefault;
+
+ // in a second line, print description text (2*indent)
+ if(descriptionText)
+ os << CommandLineParameter::descLineSep << CommandLineParameter::descIndent << CommandLineParameter::descIndent << descriptionText;
+
+ os<<flush;
+
+ return os;
+}
+
+//#####################################################################
+
+FlagParameter::FlagParameter(char nShortName, const char* nLongName) throw(CmlException)
+:CommandLineParameter(nShortName,nLongName,(const char*)NULL)
+{
+}
+
+bool FlagParameter::needsValue()
+{
+ return false;
+}
+
+bool FlagParameter::takeValue(const char*)
+{
+ return false;
+}
+
+void FlagParameter::popValue()
+{
+}
+
+bool FlagParameter::isPresent()
+{
+ return present;
+}
+
+bool FlagParameter::setPresent(char c) throw(CmlException)
+{
+ if(c && c==shortName)
+ {
+ if(present==true)
+ {
+ if(wasLongName==true)
+ throw CmlException(string("") + "Parameter '" + longName + "' clashes with parameter '" + shortName + "'");
+ else
+ throw CmlException(string("") + "Parameter '" + shortName + "' was already present");
+ }
+ present=true;
+ return true;
+ }
+ return false;
+}
+
+bool FlagParameter::setPresent(const char* s) throw(CmlException)
+{
+ if(longName != NULL && !strcmp(longName,s))
+ {
+ if(present==true)
+ {
+ if(wasLongName==true)
+ throw CmlException(string("") + "Parameter '" + longName + "' was already present");
+ else
+ throw CmlException(string("") + "Parameter '" + longName + "' clashes with parameter '" + shortName + "'");
+ }
+ wasLongName=true;
+ present=true;
+ return true;
+ }
+ return false;
+}
+
+const char* FlagParameter::getValueAsString() throw(CmlException)
+{
+ throw CmlException("Flag parameter can't return a string value");
+}
+
+long FlagParameter::getValueAsLong() throw(CmlException)
+{
+ throw CmlException("Flag parameter can't return a 'long' value");
+}
+
+double FlagParameter::getValueAsDouble() throw(CmlException)
+{
+ throw CmlException("Flag parameter can't return a 'double' value");
+}
+
+ostream& FlagParameter::printStatus(ostream &os)
+{
+ if(present)
+ os<<"option '"<<calledName()<<"' present";
+ else
+ os<<"option '"<<calledName()<<"' missing";
+
+ return os;
+}
+//#####################################################################
+StringParameter::StringParameter(char nShortName, const char* nLongName, const char* newDefaultValue) throw(CmlException)
+:CommandLineParameter(nShortName,nLongName,newDefaultValue)
+{
+ value.clear();
+}
+
+StringParameter::StringParameter(char nShortName, const char* nLongName, long newDefaultValue) throw(CmlException)
+:CommandLineParameter(nShortName,nLongName,newDefaultValue)
+{
+ value.clear();
+}
+
+StringParameter::~StringParameter()
+{
+ reset();
+}
+
+bool StringParameter::setPresent(char c) throw(CmlException)
+{
+ if(c && c==shortName)
+ {
+ present=true;
+ return true;
+ }
+ return false;
+}
+
+bool StringParameter::setPresent(const char* s) throw(CmlException)
+{
+ if(longName != NULL && !strcmp(longName,s))
+ {
+ wasLongName=true;
+ present=true;
+ return true;
+ }
+ return false;
+}
+
+bool StringParameter::isPresent()
+{
+ return ( ! value.empty() );
+}
+
+void StringParameter::reset()
+{
+ list<char*>::iterator iter = value.begin();
+/* FIXME: free mem to avoid mem leaks
+ while ( iter != value.end() )
+ {
+ if (*iter != NULL)
+ delete[] *iter;
+ }
+*/
+ value.clear();
+
+ CommandLineParameter::reset();
+}
+
+
+bool StringParameter::needsValue()
+{
+ return true;
+}
+
+bool StringParameter::takeValue(const char* s)
+{
+ char *aux = dupString(s);
+ value.push_back( aux );
+ return true;
+}
+
+void StringParameter::popValue()
+{
+ if ( ! value.empty() )
+ value.pop_front();
+}
+
+const char* StringParameter::getValueAsString() throw(CmlException)
+{
+ return ( !value.empty() ? value.front() : defaultValue );
+}
+
+long StringParameter::getValueAsLong() throw(CmlException)
+{
+ const char *r = ( !value.empty() ? value.front() : defaultValue );
+
+ if(r == NULL)
+ throw CmlException(string("") + "No value for parameter '" + calledName() + "'");
+
+ char *endptr;
+
+ long result = strtol( r, &endptr, 0);
+
+ if( *endptr != 0 )
+ throw CmlException(string("") + "Invalid integer value for parameter '" + calledName() + "'");
+
+ return result;
+}
+
+double StringParameter::getValueAsDouble() throw(CmlException)
+{
+ const char *r = ( !value.empty() ? value.front() : defaultValue );
+
+ if(r == NULL)
+ throw CmlException(string("") + "No value for parameter '" + calledName() + "'");
+
+ char *endptr;
+
+ double result = strtod( r, &endptr);
+
+ if( *endptr != 0 )
+ throw CmlException(string("") + "Invalid double value for parameter '" + calledName() + "'");
+
+ return result;
+}
+
+ostream& StringParameter::printStatus(ostream &os)
+{
+ if(value.empty())
+ os<<"option '"<<calledName()<<"' empty.";
+ else
+ {
+ os<<"option '"<<calledName()<<"' present: ";
+ list<char*>::iterator iter = value.begin();
+ while ( iter != value.end() )
+ {
+ os<< "'" << (*iter ? *iter : "(null)") << "' ";
+ iter++;
+ }
+ }
+ return os;
+}
+
+//##########################################################
+const char CommandLineParser::noShortName = '-';
+const char* CommandLineParser::noLongName = "--";
+const char* CommandLineParser::ShortSign = "-";
+const char* CommandLineParser::LongSign = "--";
+
+CommandLineParser* CommandLineParser::myself = NULL;
+
+CommandLineParser& CommandLineParser::getInstance()
+{
+ if(myself == NULL)
+ myself = new CommandLineParser;
+ return *myself;
+}
+
+CommandLineParser::CommandLineParser()
+{
+ lastParameter = NULL;
+ nextTokenIsValue = false;
+}
+
+CommandLineParser::~CommandLineParser()
+{
+ delete myself;
+ myself=NULL;
+
+ lastParameter=NULL;
+
+ list<CommandLineParameter*>::iterator iter = cmlParameter.begin();
+ for(unsigned int i=0;i<cmlParameter.size();i++,iter++)
+ delete *iter;
+}
+
+
+CommandLineParameter& CommandLineParser::addFlagParameter(char shortName, const char *longName, const char *description) throw(CmlException)
+{
+ CommandLineParameter *cp = new FlagParameter(shortName,longName);
+ cp->setDescription(description);
+ cmlParameter.push_back(cp);
+ return *cp;
+}
+
+CommandLineParameter& CommandLineParser::addStringParameter(char shortName, const char* longName, const char *description, const char* newDefaultValue) throw(CmlException)
+{
+ CommandLineParameter *cp = new StringParameter(shortName,longName,newDefaultValue);
+ cp->setDescription(description);
+ cmlParameter.push_back(cp);
+ return *cp;
+}
+
+CommandLineParameter& CommandLineParser::addLongParameter(char shortName, const char* longName, const char *description, long newDefaultValue) throw(CmlException)
+{
+ CommandLineParameter *cp = new StringParameter(shortName,longName,newDefaultValue);
+ cp->setDescription(description);
+ cmlParameter.push_back(cp);
+ return *cp;
+}
+
+bool CommandLineParser::isPresent(char shortName) throw(CmlException)
+{
+ StringParameter *sp;
+ FlagParameter *fp;
+ bool result;
+
+ CommandLineParameter &cml = getParameter(shortName);
+ if ((sp = dynamic_cast<StringParameter*>(&cml)))
+ result = sp->isPresent();
+ else if ((fp = dynamic_cast<FlagParameter*>(&cml)))
+ result = fp->isPresent();
+ return result;
+}
+
+bool CommandLineParser::isPresent(const char* longName) throw(CmlException)
+{
+ StringParameter *sp;
+ FlagParameter *fp;
+ bool result;
+
+ CommandLineParameter &cml = getParameter(longName);
+ if ((sp = dynamic_cast<StringParameter*>(&cml)))
+ result = sp->isPresent();
+ else if ((fp = dynamic_cast<FlagParameter*>(&cml)))
+ result = fp->isPresent();
+ return result;
+}
+
+const char* CommandLineParser::getValueAsString(char shortName) throw(CmlException)
+{
+ CommandLineParameter &cml = getParameter(shortName);
+ return cml.getValueAsString();
+}
+
+long CommandLineParser::getValueAsLong(char shortName) throw(CmlException)
+{
+ CommandLineParameter &cml = getParameter(shortName);
+ return cml.getValueAsLong();
+}
+
+double CommandLineParser::getValueAsDouble(char shortName) throw(CmlException)
+{
+ CommandLineParameter &cml = getParameter(shortName);
+ return cml.getValueAsDouble();
+}
+
+const char* CommandLineParser::getValueAsString(const char* longName) throw(CmlException)
+{
+ CommandLineParameter &cml = getParameter(longName);
+ return cml.getValueAsString();
+}
+
+long CommandLineParser::getValueAsLong(const char* longName) throw(CmlException)
+{
+ CommandLineParameter &cml = getParameter(longName);
+ return cml.getValueAsLong();
+}
+
+double CommandLineParser::getValueAsDouble(const char* longName) throw(CmlException)
+{
+ CommandLineParameter &cml = getParameter(longName);
+ return cml.getValueAsDouble();
+}
+
+
+void CommandLineParser::processCommandLine(int argc, char** argv) throw(CmlException)
+{
+ for(int i=1;i<argc;i++)
+ {
+ char *nextToken=argv[i];
+
+// bool sw1 = (nextToken[0]=='-') ? true:false; // token starts with "-"
+// bool sw2 = (sw1 && nextToken[1]=='-') ? true:false; // token starts with "--"
+
+ bool sw1 = (!strncmp(nextToken, ShortSign, strlen(ShortSign))) ? true:false; // token starts with ShortSign
+ bool sw2 = (!strncmp(nextToken, LongSign, strlen(LongSign))) ? true:false; // token starts with LongSign
+
+ //check only for ShortSign/LongSign
+ if(sw1 && !strcmp(nextToken, ShortSign))
+ throw CmlException(string("") + "Syntax error: '" + ShortSign + "' with no parameter in command line");
+ if(sw2 && !strcmp(nextToken, LongSign))
+ throw CmlException(string("") + "Syntax error: '" + LongSign + "' with no parameter in command line");
+
+ if(nextTokenIsValue)
+ setValue(nextToken);
+ else if(sw2)
+ longNameParameter(nextToken);
+ else if(sw1)
+ shortNameParameter(nextToken);
+ else
+ {
+ throw CmlException(string("") + "Syntax error: unexpected token '" + nextToken + "' in command line");
+ }
+ }
+ if(nextTokenIsValue)
+ throw CmlException(string("") + "Syntax error: missing value for parameter '" + lastParameter->calledName() + "' in command line");
+}
+
+
+CommandLineParameter& CommandLineParser::getParameter(char shortName) throw(CmlException)
+{
+ list<CommandLineParameter*>::iterator iter = cmlParameter.begin();
+
+ for(unsigned int i=0;i<cmlParameter.size();i++,iter++)
+ {
+ if( (*iter)->doesMatch(shortName) )
+ {
+ return *(*iter);
+ }
+ }
+ throw CmlException(string("") + "Syntax error: unknown parameter '" + shortName + "' in command line");
+}
+
+CommandLineParameter& CommandLineParser::getParameter(const char* longName) throw(CmlException)
+{
+ list<CommandLineParameter*>::iterator iter = cmlParameter.begin();
+
+ for(unsigned int i=0;i<cmlParameter.size();i++,iter++)
+ {
+ if( (*iter)->doesMatch(longName) )
+ {
+ return *(*iter);
+ }
+ }
+ throw CmlException(string("") + "Syntax error: unknown parameter '" + longName + "' in command line");
+}
+
+
+void CommandLineParser::setValue(const char* value) throw(CmlException)
+{
+ if(lastParameter == NULL)
+ {
+ throw CmlException("internal error: setValue - lastParameter==null");
+ }
+ lastParameter->takeValue(value);
+ nextTokenIsValue=false;
+}
+
+void CommandLineParser::longNameParameter(const char *nextToken) throw(CmlException)
+{
+ const char* longName = nextToken + strlen(LongSign); // sari peste LongSign (former "--")
+
+ CommandLineParameter &cml = getParameter(longName);
+ cml.setPresent(longName);
+ if(cml.needsValue())
+ {
+ lastParameter = &cml;
+ nextTokenIsValue=true;
+ }
+}
+
+void CommandLineParser::shortNameParameter(const char *nextToken) throw(CmlException)
+{
+ int tokenLength = strlen(nextToken);
+
+ for(int i=strlen(ShortSign);i<tokenLength;i++) //former i=1 for '-'
+ {
+ char shortName = nextToken[i];
+ CommandLineParameter &cml = getParameter(shortName);
+ cml.setPresent(shortName);
+
+ if(cml.needsValue())
+ {
+ if(i==tokenLength-1)
+ {
+ lastParameter = &cml;
+ nextTokenIsValue=true;
+ }
+ else
+ {
+ const char *value = nextToken + i+1;
+ cml.takeValue(value);
+ }
+ break;
+ }
+ }
+
+}
+
+void CommandLineParser::printHelp()
+{
+ std::list<CommandLineParameter*>::const_iterator iter=cmlParameter.begin();
+ std::list<CommandLineParameter*>::const_iterator iterEnd=cmlParameter.end();
+ for(; iter!=iterEnd; ++iter)
+ {
+ CommandLineParameter* ptr=*iter;
+ ptr->printHelp( std::cout );
+ std::cout << std::endl;
+ }
+ return;
+}
+
+void CommandLineParser::printStatus()
+{
+ std::list<CommandLineParameter*>::const_iterator iter=cmlParameter.begin();
+ std::list<CommandLineParameter*>::const_iterator iterEnd=cmlParameter.end();
+
+ for(; iter!=iterEnd; ++iter)
+ {
+ CommandLineParameter* ptr=*iter;
+ ptr->printStatus( std::cout ) << std::endl;
+ }
+
+ std::cout <<std::endl;
+
+}
+
+bool CommandLineParser::testProcessCommandLine(const char *testCml)
+{
+ std::list<CommandLineParameter*>::const_iterator iter=cmlParameter.begin();
+ std::list<CommandLineParameter*>::const_iterator iterEnd=cmlParameter.end();
+ string test;
+ string::size_type posStart, posEnd;
+ const char* spaceSep = " \t\v\f\n\r";
+ const char* prgName = "program";
+ std::vector<std::string> argList;
+ char **argv=NULL;
+ unsigned int argc=0, i=0, n=0;
+ static unsigned int counter=1;
+
+ if(!testCml)
+ {
+ std::cout << "Error: test_cml is null" << endl;
+ printStatus();
+ return false;
+ }
+
+ std::cout << "Test " << counter << " commandline='" << testCml << "'" << std::endl;
+
+ //converting to argc, argv
+ test=testCml;
+ posEnd=0;
+ while(true)
+ {
+ posStart=test.find_first_not_of(spaceSep, posEnd);
+ if(posStart != string::npos)
+ {
+ posEnd=test.find_first_of(spaceSep, posStart);
+ if(posEnd != string::npos)
+ {
+ std::cout << "arg " << argList.size() + 1 << "='" << test.substr(posStart, posEnd-posStart) << "'" << std::endl;
+ argList.push_back(test.substr(posStart, posEnd-posStart));
+ }
+ else //last element
+ {
+ std::cout << "arg " << argList.size() + 1 << "='" << test.substr(posStart, test.size()-posStart) << "'" << std::endl;
+ argList.push_back(test.substr(posStart, test.size()-posStart));
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ //build argv in C style
+ n=argList.size();
+ argc = n + 1;
+ argv=new char*[ argc ];
+ argv[0] = dupString(prgName);
+ for(i=0; i < n; i++)
+ argv[i + 1] = dupString(argList[i].c_str());
+
+ std::cout << "Test " << counter++ << " output:" << std::endl;
+
+ try
+ {
+ //reset all options
+ for(; iter!=iterEnd; ++iter)
+ {
+ (*iter)->reset();
+ }
+ //process commandline
+ processCommandLine(argc, argv);
+ }
+ catch(CmlException &e)
+ {
+ std::cout<<"Error: "<<e.what()<<std::endl;
+ for(i=0; i < argc; i++)
+ delete [] argv[i];
+ delete[] argv;
+
+ printStatus();
+ return false;
+ }
+
+ for(i=0; i < argc; i++)
+ delete [] argv[i];
+ delete[] argv;
+
+ printStatus();
+ return true;
+}
+
diff --git a/commline/cmlparser.hh b/commline/cmlparser.hh
new file mode 100644
index 0000000..1a29ded
--- /dev/null
+++ b/commline/cmlparser.hh
@@ -0,0 +1,242 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+/
+/**
+ * INCLUDE: cmlparser.hh
+ *
+ * MODULE: command line interpreter
+ *
+ * PURPOSE:
+ * Tool for interpreting command line arguments
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+#ifndef AK_CMLPARSER_HH
+#define AK_CMLPARSER_HH
+
+
+
+#include <list>
+#include <string>
+#include <exception>
+#include <iostream>
+
+using std::string;
+using std::list;
+using std::ostream;
+using std::cout;
+
+// Command Line Parser version
+extern const char* CommandLineParserVersion;
+
+// specific errors thrown by the parser
+class CmlException : public std::exception
+ {
+ public:
+ explicit CmlException(const string& whatString);
+ virtual ~CmlException() throw();
+ virtual const char* what() const throw();
+
+ protected:
+ string problem;
+ };
+
+
+class CommandLineParameter
+ {
+ public:
+
+ static const char* defaultTitle;
+ static const char* descSep;
+ static const char* descTab;
+ static const char* descIndent;
+ static const char* descLineSep;
+ static const char descOpen;
+ static const char descClose;
+ static const char* descLeftDefault;
+ static const char* descRightDefault;
+
+ virtual ~CommandLineParameter();
+
+ //interface for Parser
+ void setDescription(const char*);
+
+ bool doesMatch(char c);
+ bool doesMatch(const char* s);
+
+ char getShortName() const;
+ const char* getLongName() const;
+
+ virtual bool setPresent(char c) throw(CmlException) = 0;
+ virtual bool setPresent(const char* s) throw(CmlException) = 0;
+
+ virtual bool needsValue() = 0;
+ virtual bool takeValue(const char* s) = 0;
+ virtual void popValue() = 0;
+
+ void virtual reset();
+ const char *calledName();
+
+ // has a (at least one) value been assigned?
+ virtual bool isPresent() = 0;
+
+ virtual const char* getValueAsString() throw(CmlException) = 0;
+ virtual long getValueAsLong() throw(CmlException) = 0;
+ virtual double getValueAsDouble() throw(CmlException) = 0;
+
+ virtual ostream& printStatus(ostream& = cout) = 0;
+ ostream& printHelp(ostream& = cout);
+
+ protected:
+ CommandLineParameter(char newShortName, const char* newLongName, const char* newDefaultValue) throw(CmlException);
+ CommandLineParameter(char newShortName, const char* newLongName, long newDefaultValue) throw(CmlException);
+
+ protected:
+
+ char shortName;
+ char* longName;
+ bool present;
+ bool wasLongName;
+
+ char* defaultValue;
+ char shNameString[2];
+
+ char *descriptionText;
+ char *paramDescription;
+ };
+
+
+class FlagParameter: public CommandLineParameter
+ {
+ public:
+ FlagParameter(char nShortName, const char*nLongName) throw(CmlException);
+
+ bool setPresent(char c) throw(CmlException);
+ bool setPresent(const char* s) throw(CmlException);
+ bool isPresent();
+
+ bool needsValue();
+ bool takeValue(const char* s);
+ void popValue();
+
+ const char* getValueAsString() throw(CmlException);
+ long getValueAsLong() throw(CmlException);
+ double getValueAsDouble() throw(CmlException);
+
+ ostream& printStatus(ostream& = cout);
+ };
+
+class StringParameter: public CommandLineParameter
+ {
+ private:
+ list<char*> value;
+
+ public:
+ StringParameter(char nShortName, const char* nLongName, const char *newDefaultValue = NULL) throw(CmlException);
+ StringParameter(char nShortName, const char* nLongName, long newDefaultValue = 0L) throw(CmlException);
+ ~StringParameter();
+
+ bool setPresent(char c) throw(CmlException);
+ bool setPresent(const char* s) throw(CmlException);
+ bool isPresent();
+
+ bool needsValue();
+ bool takeValue(const char* s);
+ void popValue();
+
+ const char* getValueAsString() throw(CmlException);
+ long getValueAsLong() throw(CmlException);
+ double getValueAsDouble() throw(CmlException);
+
+ void reset();
+
+ ostream& printStatus(ostream& = cout);
+
+ };
+
+
+class CommandLineParser
+ {
+ public:
+ static const char noShortName;
+ static const char* noLongName;
+ static const char* ShortSign;
+ static const char* LongSign;
+
+
+ static CommandLineParser& getInstance();
+
+ ~CommandLineParser();
+
+ /*
+ These functions take a parameter called description. This is a string used in printHelp
+ The format of this string has to be:
+ <name of parameter> line1\n\t\tline2...\n\t\tlineN
+ brackets<> and space after are mandatory if there is a parameter!
+ Otherwise no <>!
+ */
+ CommandLineParameter& addFlagParameter(char shortName, const char* longName, const char* description) throw(CmlException);
+ CommandLineParameter& addStringParameter(char shortName, const char* longName, const char* description, const char *newDefaultValue = NULL) throw(CmlException);
+ CommandLineParameter& addLongParameter(char shortName, const char* longName, const char* description, long newDefaultValue = 0L ) throw(CmlException);
+
+ bool isPresent(char shortName) throw(CmlException);
+ bool isPresent(const char* longName) throw(CmlException);
+
+ const char* getValueAsString(char shortName) throw(CmlException);
+ long getValueAsLong(char shortName) throw(CmlException);
+ double getValueAsDouble(char shortName) throw(CmlException);
+
+ const char* getValueAsString(const char* longName) throw(CmlException);
+ long getValueAsLong(const char* longName) throw(CmlException);
+ double getValueAsDouble(const char* longName) throw(CmlException);
+
+ void processCommandLine(int argc, char** argv) throw(CmlException);
+
+ bool testProcessCommandLine(const char* test_cml);
+
+ void printHelp();
+ void printStatus();
+
+ private:
+ static CommandLineParser* myself;
+
+ list<CommandLineParameter*> cmlParameter;
+
+ CommandLineParameter *lastParameter;
+ bool nextTokenIsValue;
+
+ CommandLineParser();
+
+ CommandLineParameter& getParameter(char shortName) throw(CmlException);
+ CommandLineParameter& getParameter(const char* longName) throw(CmlException);
+
+ void setValue(const char* value) throw(CmlException);
+
+ void longNameParameter(const char* nextToken) throw(CmlException);
+
+ void shortNameParameter(const char* nextToken) throw(CmlException);
+ };
+
+#endif
diff --git a/commline/test/Makefile b/commline/test/Makefile
new file mode 100644
index 0000000..7297c80
--- /dev/null
+++ b/commline/test/Makefile
@@ -0,0 +1,43 @@
+#
+# This file is part of rasdaman community.
+#
+# Rasdaman community is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Rasdaman community is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+# rasdaman GmbH.
+#
+# For more information please see <http://www.rasdaman.org>
+# or contact Peter Baumann via <baumann@rasdaman.com>. # Top Level makefile. This points to the various modules that have to be build
+# and/or deployed
+
+include $(RMANBASE)/Makefile.inc
+
+OBJS = test_cml.o
+BINS = test_cml functest
+LIBS =
+MISCS = core
+
+CXXFLAGS += ${COMPFLAGS}
+
+all: $(BINS)
+
+test_cml: test_cml.cc ../cmlparser.o
+ $(CXX) $(CXXFLAGS) -I. -I.. -o test_cml test_cml.cc ../cmlparser.o
+
+functest: functest.cc ../cmlparser.o
+ $(CXX) $(CXXFLAGS) -I. -I.. -o functest functest.cc ../cmlparser.o
+
+clean:
+ -rm $(OBJS) $(MISC)
+
diff --git a/commline/test/functest.cc b/commline/test/functest.cc
new file mode 100644
index 0000000..96bd87d
--- /dev/null
+++ b/commline/test/functest.cc
@@ -0,0 +1,59 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+static const char rcsid[] = "@(#)commline,functest: $Id: functest.cc,v 1.1 2005/09/15 12:55:37 rasdev Exp $";
+
+#include<cmlparser.hh>
+
+using std::cout;
+using std::endl;
+
+
+int main()
+ {
+ CommandLineParser &cmlp = CommandLineParser::getInstance();
+
+ try
+ {
+ cmlp.addFlagParameter('f', "fragmented", "fragment file until there is no file any more");
+ cmlp.addFlagParameter(0 , "delete", "delete root directory");
+ cmlp.addFlagParameter('s', NULL, "use server for crushing system");
+
+ cmlp.addStringParameter('u', "user", "<name> user name\n\t\tcucubau", "rasguest");
+ cmlp.addStringParameter( CommandLineParser::noShortName, "passwd", "<password> user password", "rasguest");
+ cmlp.addStringParameter('d', CommandLineParser::noLongName, "<databasename> database name");
+ }
+ catch(CmlException e)
+ {
+ cout << "Error defining options:" << endl;
+ cout << e.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ cmlp.printHelp();
+
+ return EXIT_SUCCESS;
+ }
+
+
+
+
diff --git a/commline/test/test_cml.cc b/commline/test/test_cml.cc
new file mode 100644
index 0000000..df9a072
--- /dev/null
+++ b/commline/test/test_cml.cc
@@ -0,0 +1,101 @@
+/*
+* This file is part of rasdaman community.
+*
+* Rasdaman community is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Rasdaman community is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
+*
+* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
+rasdaman GmbH.
+*
+* For more information please see <http://www.rasdaman.org>
+* or contact Peter Baumann via <baumann@rasdaman.com>.
+*/
+
+static const char rcsid[] = "@(#)commline,test_cml.cc: $Id: test_cml.cc,v 1.3 2005/12/21 23:02:06 rasdev Exp $";
+
+#include "cmlparser.hh"
+
+using std::cout;
+using std::endl;
+
+//set to 1 for testing invalid options
+const int TESTOPT=0;
+
+int
+main(int argc, char** argv)
+ {
+ CommandLineParser& cmlInter = CommandLineParser::getInstance();
+
+ if(TESTOPT)
+ cout<<"------ Defining Test options -----"<<endl;
+
+ //defines options
+ try
+ {
+ CommandLineParameter& a = cmlInter.addFlagParameter('r',"resistent", "r desc");
+ CommandLineParameter& b = cmlInter.addFlagParameter('g',"ab", "ab desc");
+ CommandLineParameter& c = cmlInter.addStringParameter('f',"file", "<filename f desc");
+ CommandLineParameter& d = cmlInter.addStringParameter('s',"server", "server> s desc");
+ CommandLineParameter& e = cmlInter.addStringParameter(CommandLineParser::noShortName,"ts", "<ts> test -");
+ CommandLineParameter& f = cmlInter.addStringParameter('t', CommandLineParser::noLongName, "<tl> test --", "test --");
+
+ if(TESTOPT)
+ CommandLineParameter& g = cmlInter.addStringParameter(CommandLineParser::noShortName, CommandLineParser::noLongName, "<tl> - --");
+
+ }
+ catch(CmlException& e)
+ {
+ cout << "Erorr:" << e.what() << endl;
+ return 1;
+ }
+
+ cout<<"------ Test options -----"<<endl;
+ cmlInter.printHelp();
+
+ cout<<"------ Correct Start -----"<<endl;
+ cmlInter.testProcessCommandLine("-r --ab --file testFile -s serverName");
+ cmlInter.testProcessCommandLine("-r --ab --file testFile ");
+ cmlInter.testProcessCommandLine("-r --ab -s serverName");
+ cmlInter.testProcessCommandLine("-rf testFile -s serverName");
+ cmlInter.testProcessCommandLine("-rgf testFile -s serverName");
+ cmlInter.testProcessCommandLine(" --ab --file testFile -s serverName");
+ cmlInter.testProcessCommandLine("--resistent");
+ cmlInter.testProcessCommandLine("--file testFile --server serverName");
+ cmlInter.testProcessCommandLine("-r --ab --file testFile -s -1");
+ cmlInter.testProcessCommandLine("-r --ab --file test -s \"serverName\"");
+ cmlInter.testProcessCommandLine("");
+ cmlInter.testProcessCommandLine(" ");
+ cmlInter.testProcessCommandLine(" ");
+
+ cout<<"------ Multiple Options Start -----"<<endl;
+ cmlInter.testProcessCommandLine("-f F1 -f F2 --file F3 --file F4");
+
+ cout<<"------ Errors Start -----"<<endl;
+ cmlInter.testProcessCommandLine("-r -r --resistent --resistent"); // multiple flags not allowed
+ cmlInter.testProcessCommandLine("-r --ab --file testFile -s");
+ cmlInter.testProcessCommandLine("-r --ab -file testFile");
+ cmlInter.testProcessCommandLine("-r --ab --file -s serverName");
+ cmlInter.testProcessCommandLine("r --ab --file testFile -s serverName");
+ cmlInter.testProcessCommandLine("-r -ab --file testFile -s serverName");
+ cmlInter.testProcessCommandLine("-r ab --file testFile -s serverName");
+ cmlInter.testProcessCommandLine("-rfs testFile serverName");
+ cmlInter.testProcessCommandLine("- r");
+ cmlInter.testProcessCommandLine("-");
+ cmlInter.testProcessCommandLine("--");
+ cmlInter.testProcessCommandLine("-r --");
+ cmlInter.testProcessCommandLine("-r -- ab --file testFile -s serverName");
+
+ cout<<"------ Test End -----"<<endl;
+
+ return 0;
+ }