Files
pvvmud/common/lib/utils/option.C
2025-03-05 08:37:43 +01:00

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;
}