354 lines
9.3 KiB
C
354 lines
9.3 KiB
C
/*
|
|
* PVVMUD a 3D MUD
|
|
* Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org)
|
|
*
|
|
* This program 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 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
#include "pvvmud.H"
|
|
#include "option.H"
|
|
#ifdef _HAVE_GETOPT_LONG
|
|
#include <getopt.h>
|
|
#else
|
|
#include "getopt.h"
|
|
#endif // _HAVE_GETOPT_LONG
|
|
|
|
#include <iostream.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
char * COptionItem::m_typeString[] = {"string","integer","double"};
|
|
|
|
COptionItem::COptionItem(char * name, char abbreviation, char * strValue){
|
|
setName(name);
|
|
setAbbreviation(abbreviation);
|
|
setValue(strValue);
|
|
}
|
|
|
|
COptionItem::COptionItem(char * name, char abbreviation, int intValue){
|
|
setName(name);
|
|
setAbbreviation(abbreviation);
|
|
setValue(intValue);
|
|
}
|
|
|
|
COptionItem::COptionItem(char * name, char abbreviation, double doubleValue){
|
|
setName(name);
|
|
setAbbreviation(abbreviation);
|
|
setValue(doubleValue);
|
|
}
|
|
|
|
void COptionItem::setAbbreviation(char abbreviation){
|
|
m_abbreviation = abbreviation;
|
|
}
|
|
|
|
char COptionItem::getAbbreviation(){
|
|
return m_abbreviation;
|
|
}
|
|
|
|
|
|
void COptionItem::setValue(char * strValue){
|
|
m_type = STR_VALUE;
|
|
if (m_value.strValue != NULL) cdebug << "COptionItem::setValue(char * strValue) Posible memory leak!\n";
|
|
m_value.strValue = (char*)malloc(strlen(strValue)+1);
|
|
strcpy(m_value.strValue,strValue);
|
|
}
|
|
|
|
void COptionItem::setValue(int intValue){
|
|
m_type = INT_VALUE;
|
|
m_value.intValue = intValue;
|
|
}
|
|
|
|
void COptionItem::setValue(double doubleValue){
|
|
m_type = DOUBLE_VALUE;
|
|
m_value.doubleValue = doubleValue;
|
|
}
|
|
|
|
void COptionItem::updateValue(char * valueString){
|
|
switch (m_type){
|
|
case STR_VALUE: setValue(valueString); break;
|
|
case INT_VALUE: setValue(atoi(valueString)); break;
|
|
case DOUBLE_VALUE: setValue(atof(valueString)); break;
|
|
}
|
|
}
|
|
|
|
char * COptionItem::getString(){
|
|
if (m_type != STR_VALUE){
|
|
cdebug << "COptionItem " << getName() << " don't have string!\n";
|
|
return "Don't have string\n";
|
|
}
|
|
return m_value.strValue;
|
|
}
|
|
|
|
int COptionItem::getInt(){
|
|
if (m_type != INT_VALUE){
|
|
cdebug << "COptionItem " << getName() << " don't have int!\n";
|
|
return 0;
|
|
}
|
|
return m_value.intValue;
|
|
}
|
|
|
|
double COptionItem::getDouble(){
|
|
if (m_type != DOUBLE_VALUE){
|
|
cdebug << "COptionItem " << getName() << " don't have double!\n";
|
|
return 0.0;
|
|
}
|
|
return m_value.doubleValue;
|
|
}
|
|
|
|
void COptionItem::dump(){
|
|
cdebug << "Item: " << getName() << " Type: " << m_typeString[m_type]
|
|
<< " Abbreviation: " << getAbbreviation() << " Value: ";
|
|
switch (m_type){
|
|
case STR_VALUE:
|
|
cdebug << m_value.strValue;
|
|
break;
|
|
case INT_VALUE:
|
|
cdebug << m_value.intValue;
|
|
break;
|
|
case DOUBLE_VALUE:
|
|
cdebug << m_value.doubleValue;
|
|
break;
|
|
}
|
|
cdebug << "\n";
|
|
}
|
|
|
|
|
|
COption::COption(){
|
|
}
|
|
|
|
void COption::setValue(char * name, char abbreviation, char * strValue){
|
|
COptionItem * item = findOptionItem(name);
|
|
if (item == NULL){
|
|
item = new COptionItem(name,abbreviation,strValue);
|
|
addFirst(item);
|
|
} else {
|
|
item->setValue(strValue);
|
|
}
|
|
}
|
|
|
|
void COption::setValue(char * name, char abbreviation, int intValue){
|
|
COptionItem * item = findOptionItem(name);
|
|
if (item == NULL){
|
|
item = new COptionItem(name,abbreviation,intValue);
|
|
addFirst(item);
|
|
} else {
|
|
item->setValue(intValue);
|
|
}
|
|
}
|
|
|
|
void COption::setValue(char * name, char abbreviation, double doubleValue){
|
|
COptionItem * item = findOptionItem(name);
|
|
if (item == NULL){
|
|
item = new COptionItem(name,abbreviation,doubleValue);
|
|
addFirst(item);
|
|
} else {
|
|
item->setValue(doubleValue);
|
|
}
|
|
}
|
|
|
|
|
|
char * COption::getString(char * name){
|
|
COptionItem * item = findOptionItem(name);
|
|
if (item != NULL){
|
|
return item->getString();
|
|
} else {
|
|
cdebug << "COption::getString() : Unknown name " << name << "\n";
|
|
return "Unknown name\n";
|
|
}
|
|
}
|
|
|
|
int COption::getInt(char * name){
|
|
COptionItem * item = findOptionItem(name);
|
|
if (item != NULL){
|
|
return item->getInt();
|
|
} else {
|
|
cdebug << "COption::getInt() : Unknown name " << name << "\n";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
double COption::getDouble(char * name){
|
|
COptionItem * item = findOptionItem(name);
|
|
if (item != NULL){
|
|
return item->getDouble();
|
|
} else {
|
|
cdebug << "COption::getDouble() : Unknown name " << name << "\n";
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
void COption::parseArguments(int argc, char * argv[]){
|
|
int maxNumItems = getNumItems();
|
|
|
|
// Alloc memory for optstring
|
|
int optStringMaxLength = maxNumItems*2+sizeof(char);
|
|
char * optString =(char*)malloc(sizeof(char)*optStringMaxLength);
|
|
memset(optString,0,sizeof(char)*optStringMaxLength);
|
|
char* optStringPtr = optString;
|
|
// Alloc memory for longopt structs
|
|
struct option * longOpts =
|
|
(struct option*)malloc(sizeof(struct option)*(maxNumItems+1));
|
|
memset(longOpts,0,sizeof(struct option)*(maxNumItems+1));
|
|
struct option * longOptsPtr = longOpts;
|
|
|
|
// Build longOpts array and optString
|
|
CObjectListItem * item = getFirst();
|
|
while (item != NULL){
|
|
COptionItem * optionItem = (COptionItem*)item->getObject();
|
|
|
|
if (optionItem->getName() != NULL){
|
|
longOptsPtr->name = optionItem->getName();
|
|
// TODO: Incoude test for required arguemnt, no argument
|
|
// or optional argument
|
|
longOptsPtr->has_arg = required_argument;
|
|
longOptsPtr->flag = NULL; // getopt_long return val
|
|
longOptsPtr->val = 0;
|
|
longOptsPtr++;
|
|
}
|
|
|
|
if (optionItem->getAbbreviation() != '\0'){
|
|
*optStringPtr++ = optionItem->getAbbreviation();
|
|
// TODO: Include test if option is needed or optional.
|
|
// Put ':' in optString if needed and '::' if optional.
|
|
*optStringPtr++ = ':';
|
|
}
|
|
|
|
item = item->getNext();
|
|
}
|
|
|
|
// Optionure getopt_long
|
|
// opterr = 0; // Turn off printing of error messages to stderr
|
|
|
|
int c,optionIndex;
|
|
while ((c = getopt_long(argc,argv,optString,
|
|
longOpts,&optionIndex)) != EOF){
|
|
switch (c){
|
|
case 0: // Long option
|
|
cdebug << "Long option " << longOpts[optionIndex].name;
|
|
if (optarg){
|
|
cdebug << " with arg " << optarg;
|
|
updateName(longOpts[optionIndex].name,optarg);
|
|
}
|
|
cdebug << "\n";
|
|
break;
|
|
case ':': // Missing parameter
|
|
// cdebug << "WARNING: Option '" << optarg << "' missing parameter!\n";
|
|
break;
|
|
case '?': // Unknown option
|
|
// cdebug << "WARNING: Unknown option '" << argv[optind] <<"'\n";
|
|
break;
|
|
default: // Option char
|
|
cdebug << "Option " << (char)c;
|
|
if (optarg){
|
|
cdebug << " with value " << optarg;
|
|
updateAbbreviation(c,optarg);
|
|
}
|
|
cdebug << "\n";
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Free memory
|
|
free(optString);
|
|
free(longOpts);
|
|
}
|
|
|
|
void COption::loadOption(char * fileName){
|
|
FILE * file = fopen(fileName,"rt");
|
|
if (file != NULL){
|
|
loadOption(file);
|
|
fclose(file);
|
|
} else {
|
|
cdebug << "Failed to load optionuration file : " << fileName << "\n";
|
|
}
|
|
}
|
|
|
|
#define MAX_LINELENGTH 1024
|
|
|
|
int getLine(FILE * file, char * line, int length){
|
|
int index,ch;
|
|
do {
|
|
for (index = 0; (index < (length-1)) && ((ch = fgetc(file)) != EOF ) && (ch != '\n') && (ch != '#'); index++)
|
|
line[index] = ch;
|
|
line[index] = '\0';
|
|
if (ch == '#') while (((ch = fgetc(file)) != EOF) && (ch != '\n'));
|
|
} while ( (index == 0) && (ch != EOF) );
|
|
return index;
|
|
}
|
|
|
|
void COption::loadOption(FILE * file){
|
|
char line[MAX_LINELENGTH];
|
|
while (getLine(file,line,MAX_LINELENGTH) > 0){
|
|
char * chVal = strchr(line,'=');
|
|
if (chVal != NULL){
|
|
*chVal = '\0'; chVal++; // Cut string in two pices
|
|
|
|
updateName(line,chVal);
|
|
}
|
|
|
|
// cdebug << "Line: " << line << "\n";
|
|
}
|
|
}
|
|
|
|
|
|
void COption::updateName(const char * name, char * valueString){
|
|
COptionItem * optionItem = findOptionItem(name);
|
|
if (optionItem != NULL){
|
|
optionItem->updateValue(valueString);
|
|
}
|
|
}
|
|
|
|
void COption::updateAbbreviation(char abbreviation, char * valueString){
|
|
COptionItem * optionItem = findOptionItemByAbbreviation(abbreviation);
|
|
if (optionItem != NULL){
|
|
optionItem->updateValue(valueString);
|
|
}
|
|
}
|
|
|
|
|
|
void COption::dump(){
|
|
CObjectListItem * item = getFirst();
|
|
while (item != NULL){
|
|
COptionItem * optionItem = (COptionItem*)item->getObject();
|
|
optionItem->dump();
|
|
item = item->getNext();
|
|
}
|
|
}
|
|
|
|
COptionItem * COption::findOptionItem(const char * name){
|
|
CObjectListItem * item = getFirst();
|
|
while (item != NULL){
|
|
COptionItem * optionItem = (COptionItem*)item->getObject();
|
|
if ((optionItem->getName() != NULL) && (strcmp(name,optionItem->getName())) == 0){
|
|
return optionItem;
|
|
}
|
|
item = item->getNext();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
COptionItem * COption::findOptionItemByAbbreviation(char abbreviation){
|
|
CObjectListItem * item = getFirst();
|
|
while (item != NULL){
|
|
COptionItem * optionItem = (COptionItem*)item->getObject();
|
|
if (abbreviation == optionItem->getAbbreviation()){
|
|
return optionItem;
|
|
}
|
|
item = item->getNext();
|
|
}
|
|
return NULL;
|
|
}
|