/* * 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 #else #include "getopt.h" #endif // _HAVE_GETOPT_LONG #include #include #include 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; }