From: <sv...@va...> - 2010-01-08 21:43:57
|
Author: cerion Date: 2010-01-08 21:43:43 +0000 (Fri, 08 Jan 2010) New Revision: 464 Log: Finally, command-line parsing is up and running again. good grief. Added: branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp branches/valkyrie_qt4port/options/vk_parse_cmdline.h branches/valkyrie_qt4port/options/vk_popt.cpp branches/valkyrie_qt4port/options/vk_popt.h Modified: branches/valkyrie_qt4port/main.cpp branches/valkyrie_qt4port/objects/valgrind_object.cpp branches/valkyrie_qt4port/objects/valgrind_object.h branches/valkyrie_qt4port/objects/valkyrie_object.cpp branches/valkyrie_qt4port/objects/valkyrie_object.h branches/valkyrie_qt4port/objects/vk_objects.cpp branches/valkyrie_qt4port/objects/vk_objects.h branches/valkyrie_qt4port/options/valgrind_options_page.cpp branches/valkyrie_qt4port/options/valkyrie_options_page.cpp branches/valkyrie_qt4port/options/vk_option.cpp branches/valkyrie_qt4port/options/vk_option.h branches/valkyrie_qt4port/options/vk_options_page.cpp branches/valkyrie_qt4port/utils/vk_config.cpp branches/valkyrie_qt4port/utils/vk_config.h branches/valkyrie_qt4port/valkyrie.pro Modified: branches/valkyrie_qt4port/main.cpp =================================================================== --- branches/valkyrie_qt4port/main.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/main.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -26,6 +26,7 @@ #include "mainwindow.h" #include "utils/vk_config.h" +#include "options/vk_parse_cmdline.h" VkConfig* vkConfig = 0; @@ -39,7 +40,7 @@ */ int main(int argc, char *argv[]) { - int res = EXIT_SUCCESS; + int exit_status = EXIT_SUCCESS; QApplication* app = 0; MainWindow* vkWin = 0; @@ -69,7 +70,28 @@ cerr << "Error: config not initialised properly: No guarantees from here!" << endl; } + // ------------------------------------------------------------ + // Command-line parsing + // - if a project file is given, the settings will override the initialised vkConfig. + if ( argc > 1 ) { + // parse cmdline args, overwrite vkConfig with any options found. + bool show_help_and_exit; + if ( ! parseCmdArgs( argc, argv, &valkyrie, show_help_and_exit ) ) { + exit_status = EXIT_FAILURE; + goto cleanup_and_exit; + } + if ( show_help_and_exit ) { + goto cleanup_and_exit; + } + } + + // save the working config + vkConfig->sync(); + + + + // ------------------------------------------------------------ // Start up the gui vkWin = new MainWindow( &valkyrie ); vkWin->show(); @@ -79,14 +101,15 @@ // ------------------------------------------------------------ // Hand over to QtApp. - res = app->exec(); + exit_status = app->exec(); +cleanup_and_exit: // ------------------------------------------------------------ // We're done - clean up and return. if ( vkWin ) delete vkWin; if ( vkConfig ) delete vkConfig; if ( app ) delete app; - return res; + return exit_status; } Modified: branches/valkyrie_qt4port/objects/valgrind_object.cpp =================================================================== --- branches/valkyrie_qt4port/objects/valgrind_object.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/objects/valgrind_object.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -517,8 +517,29 @@ -/* check argval for this option, updating if necessary. - called by parseCmdArgs() and gui option pages -------------------- */ + + + +/*! + Update config - special cases +*/ +void Valgrind::updateConfig( int optid, QString& argval ) +{ + // exception: multiple suppressions are allowed + if ( optid == VALGRIND::SUPPS_SEL ) { +//TODO: concat, don't overwrite + // vkConfig->value( vk_opt->configKey() ); + // argval = cfg_argval + argval + } + + VkObject::updateConfig( optid, argval ); +} + + + +/*! + Check \a argval for the option given by \a optid, updating if necessary. +*/ int Valgrind::checkOptArg( int optid, QString& argval ) { optid = optid; argval = argval; Modified: branches/valkyrie_qt4port/objects/valgrind_object.h =================================================================== --- branches/valkyrie_qt4port/objects/valgrind_object.h 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/objects/valgrind_object.h 2010-01-08 21:43:43 UTC (rev 464) @@ -88,6 +88,8 @@ int checkOptArg( int optid, QString& argval ); + void updateConfig( int optid, QString& argval ); + VkOptionsPage* createVkOptionsPage(); #if 0 Modified: branches/valkyrie_qt4port/objects/valkyrie_object.cpp =================================================================== --- branches/valkyrie_qt4port/objects/valkyrie_object.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/objects/valkyrie_object.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -23,7 +23,9 @@ #include "utils/vk_config.h" #include "utils/vk_utils.h" +#include <QFile> + // TODO: put this in a define in the build scripts,or something. // Minimum version of Valgrind required const char* pchVersionVgMin = "3.6.0"; @@ -39,7 +41,7 @@ { setupOptions(); - /* init valgrind */ + // init valgrind m_valgrind = new Valgrind(); } @@ -361,14 +363,74 @@ /*! - Check \a argval for the option given by \a optid, updating if necessary. - Called by parseCmdArgs() and gui option pages + Check \a argval for the option given by \a optGrp and \a optid. + The \a argval may be updated. */ +int Valkyrie::checkOptArg( QString optGrp, int optid, QString& argval ) +{ + VkObjectList objList = this->vkObjList(); + for (int i = 0; i < objList.size(); ++i) { + VkObject* obj = objList.at(i); + + // find the option owner, call checkOptArg for that owner. + if ( obj->objectName() == optGrp ) { + return obj->checkOptArg( optid, argval ); + } + } + return PERROR_BADOPT; +} + + + +/*! + Update config + General access function, when specific object not known +*/ +void Valkyrie::updateConfig( QString optGrp, int optid, QString& argval ) +{ + VkObjectList objList = this->vkObjList(); + for (int i = 0; i < objList.size(); ++i) { + VkObject* obj = objList.at(i); + + // find the option owner, call checkOptArg for that owner. + if ( obj->objectName() == optGrp ) { + return obj->updateConfig( optid, argval ); + } + } +} + + + +/*! + Update config - special cases +*/ +void Valkyrie::updateConfig( int optid, QString& argval ) +{ + // Load config settings from project file + // - load these first before + if ( optid == VALKYRIE::PROJ_FILE ) { + QString proj_filename = argval; + + if ( !QFile::exists( proj_filename ) ) { + vkConfig->createNewProject( proj_filename ); + } else { + vkConfig->openProject( proj_filename ); + } + } + + VkObject::updateConfig( optid, argval ); +} + + + +/*! + Check \a argval for the option given by \a optid, updating if necessary. +*/ int Valkyrie::checkOptArg( int optid, QString& argval ) -{ +{ vk_assert( optid >= 0 && optid < VALKYRIE::NUM_OPTS ); - VkOption* opt = this->options.getOption( optid ); + VkOption* opt = getOption( optid ); #if 0 // TODO int errval = PARSED_OK; @@ -392,7 +454,7 @@ case VALKYRIE::DFLT_LOGDIR: case VALKYRIE::WORKING_DIR: { - /* see if we have an dir with rx permissions */ + // see if we have an dir with rx permissions (void) dirCheck( &errval, argval, true, true ); } break; @@ -402,13 +464,31 @@ argval.replace( ed_file, ed ); } break; + case VALKYRIE::PROJ_FILE: { +#if 0 // TODO: review this + + // TODO: check filname format: ( dir + "/" + proj_name + "." + VK_CFG_EXT ) + + // TODO: check dir exists & perms ok + + // check owner read/write perms ok + if ( QFile::exists( proj_filename ) ) { + QFile::Permissions perms = QFile::permissions( proj_filename ); + if ( ( perms & QFile::WriteOwner ) != QFile::WriteOwner || + ( perms & QFile::ReadOwner ) != QFile::ReadOwner ) { + // TODO: vkError perms + } + } +#endif + } break; + case VALKYRIE::VG_EXEC: { - /* see if we have an executable with rx permissions */ + // see if we have an executable with rx permissions argval = binaryCheck( &errval, argval ); if ( errval != PARSED_OK ) return errval; - /* check the version */ + // check the version QString cmd = argval + " --version 2>&1"; FILE* fp; char line[50]; @@ -428,7 +508,7 @@ if ( !vg_version.startsWith("valgrind") ) { return PERROR_BADFILE; } - /* compare with minimum req'd version: */ + // compare with minimum req'd version int versionVg = strVersion2hex( vg_version ); int versionVgReqd = strVersion2hex( pchVersionVgMin ); if ( versionVg == -1 || versionVgReqd == -1) { @@ -437,7 +517,8 @@ if ( versionVg < versionVgReqd ) { return PERROR_BADVERSION; } - /* looking good... */ + + // if we get here, we're fine. } break; case VALKYRIE::VIEW_LOG: @@ -454,11 +535,12 @@ m_startRunState = VkRunState::VALGRIND; break; - /* can't really test this */ + case VALKYRIE::BIN_FLAGS: + // Can't test this. break; - /* ignore these opts */ + // ignore these opts case VALKYRIE::HELP: case VALKYRIE::VGHELP: case VALKYRIE::OPT_VERSION: @@ -477,6 +559,23 @@ /*! + Find the option owner, find option within that owner. +*/ +VkOption* Valkyrie::findOption( QString optGrp, int optid ) +{ + VkObjectList objList = this->vkObjList(); + for (int i = 0; i < objList.size(); ++i) { + VkObject* obj = objList.at(i); + + if ( obj->objectName() == optGrp ) { + return obj->getOption( optid ); + } + } + return NULL; +} + + +/*! Return list of all VkObjects */ const VkObjectList Valkyrie::vkObjList() Modified: branches/valkyrie_qt4port/objects/valkyrie_object.h =================================================================== --- branches/valkyrie_qt4port/objects/valkyrie_object.h 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/objects/valkyrie_object.h 2010-01-08 21:43:43 UTC (rev 464) @@ -71,8 +71,12 @@ #endif unsigned int maxOptId() { return VALKYRIE::NUM_OPTS; } + int checkOptArg( QString optGrp, int optid, QString& argval ); int checkOptArg( int optid, QString& argval ); + void updateConfig( QString optGrp, int optid, QString& argval ); + void updateConfig( int optid, QString& argval ); + // Generate own options page VkOptionsPage* createVkOptionsPage(); @@ -80,6 +84,10 @@ virtual void setConfigDefaults(); + + + VkOption* findOption( QString optGrp, int optid ); + // list of all objects const VkObjectList vkObjList(); // VkObject* vkObject( int objId ); Modified: branches/valkyrie_qt4port/objects/vk_objects.cpp =================================================================== --- branches/valkyrie_qt4port/objects/vk_objects.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/objects/vk_objects.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -22,6 +22,7 @@ #include "objects/vk_objects.h" #include "utils/vk_config.h" #include "options/vk_option.h" +#include "utils/vk_utils.h" @@ -52,7 +53,33 @@ } +/*! + Return entire optionhash for this object +*/ +OptionHash& VkObject::getOptions() +{ + return options.getOptionHash(); +} + +/*! + Update config - general case +*/ +void VkObject::updateConfig( int optid, QString& argval ) +{ + vk_assert( optid >= 0 && optid < VALKYRIE::NUM_OPTS ); + + VkOption* opt = getOption( optid ); + vk_assert( opt != NULL ); + + vkConfig->setValue( opt->configKey(), argval ); +} + + + +/*! + Setup factory defaults +*/ void VkObject::setConfigDefaults() { vkConfig->beginGroup( this->objectName() ); Modified: branches/valkyrie_qt4port/objects/vk_objects.h =================================================================== --- branches/valkyrie_qt4port/objects/vk_objects.h 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/objects/vk_objects.h 2010-01-08 21:43:43 UTC (rev 464) @@ -51,6 +51,7 @@ called by parseCmdArgs() and gui option pages */ virtual int checkOptArg( int optid, QString& argval ) = 0; + virtual void updateConfig( int optid, QString& argval ); /*! Set default config entries for thies object */ virtual void setConfigDefaults(); @@ -58,12 +59,11 @@ virtual VkOptionsPage* createVkOptionsPage() = 0; VkOption* getOption( int optid ); + OptionHash& getOptions(); protected: virtual void setupOptions() = 0; VkOptionHash options; - - }; Modified: branches/valkyrie_qt4port/options/valgrind_options_page.cpp =================================================================== --- branches/valkyrie_qt4port/options/valgrind_options_page.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/options/valgrind_options_page.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -321,9 +321,9 @@ /* called when user clicks "Apply" / "Ok" / "Reset" buttons. */ void ValgrindOptionsPage::applyOption( int optId ) { + vk_assert( optId >= 0 && optId < VALGRIND::NUM_OPTS ); + #if 0 - vk_assert( optId >= 0 && optId < Valgrind::NUM_OPTS ); - // QString argval = m_itemList[optId]->currValue(); /* apply option */ Modified: branches/valkyrie_qt4port/options/valkyrie_options_page.cpp =================================================================== --- branches/valkyrie_qt4port/options/valkyrie_options_page.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/options/valkyrie_options_page.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -196,16 +196,15 @@ /* called when user clicks "Apply" / "Ok" / "Reset" buttons. */ void ValkyrieOptionsPage::applyOption( int optId ) { - std::cerr << "vk-applyOption(): 0 (" << optId << ")" << std::endl; +// std::cerr << "vk-applyOption(): 0 (" << optId << ")" << std::endl; + vk_assert( optId >= 0 && optId < VALKYRIE::NUM_OPTS ); - vk_assert( optId >= 0 && optId < VALKYRIE::NUM_OPTS ); - OptionWidget* optWidg = m_itemList[optId]; vk_assert( optWidg != 0 ); QString argval = optWidg->currValue(); - std::cerr << "applyOption(): 1" << std::endl; +// std::cerr << "applyOption(): 1" << std::endl; /* apply option */ switch ( optId ) { Modified: branches/valkyrie_qt4port/options/vk_option.cpp =================================================================== --- branches/valkyrie_qt4port/options/vk_option.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/options/vk_option.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -37,6 +37,65 @@ + +/*! + Map error int to error string +*/ +const char* parseErrString( const int error ) +{ + switch ( error ) { + case PERROR_NODASH: + return "Short options do not require a '='"; + case PERROR_NOARG: + return "Missing argument"; + case PERROR_BADARG: + return "Invalid argument"; + case PERROR_BADOPT: + return "Unknown/Disabled option"; + case PERROR_BADOPERATION: + return "Mutually exclusive logical operations requested"; + case PERROR_NULLARG: + return "opt->arg should not be NULL"; + case PERROR_BADQUOTE: + return "Error in parameter quoting"; + case PERROR_BADNUMBER: + return "Invalid numeric value"; + case PERROR_OUTOFRANGE: + return "Numeric value outside valid range"; + case PERROR_OVERFLOW: + return "Number too large or too small"; + case PERROR_MALLOC: + return "Memory allocation failed"; + case PERROR_BADDIR: + return "Invalid directory"; + case PERROR_BADFILE: + return "Invalid file"; + case PERROR_BADNUMFILES: + return "Invalid number of files ( max == 10 )"; + case PERROR_BADFILERD: + return "You do not have read permission"; + case PERROR_BADFILEWR: + return "You do not have write permission"; + case PERROR_BADEXEC: + return "You do not have executable permission"; + case PERROR_DB_CONFLICT: + return "Conflicting argument\n" + "--db-attach=yes conflicts with --trace-children=yes\n" + "Please choose one or the other, but not both."; + case PERROR_DB_OUTPUT: + return "using --db-attach=yes only makes sense " + "when sending output to stderr."; + case PERROR_POWER_OF_TWO: + return "number is not a power of two"; + case PERROR_BADVERSION: + return "Bad program version"; + default: + return "unknown error"; + } +} + + + /***************************************************************************/ /*! Constructs a VkOptionHash Modified: branches/valkyrie_qt4port/options/vk_option.h =================================================================== --- branches/valkyrie_qt4port/options/vk_option.h 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/options/vk_option.h 2010-01-08 21:43:43 UTC (rev 464) @@ -103,9 +103,9 @@ QString binaryCheck( int* err_val, const QString exe_name ); QString dirCheck( int* err_val, const QString fpath, bool rd_perms, bool wr_perms ); +#endif const char* parseErrString( const int error ); -#endif Modified: branches/valkyrie_qt4port/options/vk_options_page.cpp =================================================================== --- branches/valkyrie_qt4port/options/vk_options_page.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/options/vk_options_page.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -148,7 +148,7 @@ if ( m_editList.isEmpty() && m_mod == false ) return true; - std::cerr << "applyEDITS(): 2" << std::endl; +// std::cerr << "applyEDITS(): 2" << std::endl; // user clicked Ok/Apply after editing some items @@ -159,9 +159,9 @@ if ( !checkOption( optw->id() ) ) { return false; } - std::cerr << "applyEDITS(): 3 (" << i << ")" << std::endl; +// std::cerr << "applyEDITS(): 3 (" << i << ")" << std::endl; - // update any Valkyrie state dependent on this option + // update any Valkyrie state dependent on this option applyOption( optw->id() ); } std::cerr << "applyEDITS(): 4" << std::endl; Added: branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp =================================================================== --- branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp (rev 0) +++ branches/valkyrie_qt4port/options/vk_parse_cmdline.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -0,0 +1,293 @@ +/**************************************************************************** +** Parse command-line options implementation +** - Called from main() to parse both valkyrie and valgrind args +** -------------------------------------------------------------------------- +** +** Copyright (C) 2000-2010, OpenWorks LLP. All rights reserved. +** <in...@op...> +** +** This file is part of Valkyrie, a front-end for Valgrind. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file COPYING included in the packaging of +** this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "objects/vk_objects.h" +#include "objects/valkyrie_object.h" // for VALKYRIE::enums + +#include "utils/vk_utils.h" +#include "options/vk_popt.h" +#include "options/vk_option.h" // namespace VkOPT +#include "utils/vk_config.h" + + +void showHelp( vkPoptContext con, char key, Valkyrie* vk ) +{ + QString VkName = vkConfig->vkName; + VkName.replace( 0, 1, vkConfig->vkName[0].toUpper() ); + + switch ( key ) { + case 'v': + printf("%s-%s\n", vkConfig->vkName.toLatin1().constData(), + vkConfig->vkVersion.toLatin1().constData() ); + break; + + case 'h': + vkPoptPrintHelp( con, stdout, vk->objectName().toLatin1().constData() ); + printf( "\n%s is copyright %s %s\n" + "and licensed under the GNU General Public License, version 2.\n" + "Bug reports, feedback, praise, abuse, etc, to <%s>\n\n", + VkName.toLatin1().constData(), + vkConfig->vkCopyright.toLatin1().constData(), + vkConfig->vkAuthor.toLatin1().constData(), + vkConfig->vkEmail.toLatin1().constData() ); + break; + + case 'V': + vkPoptPrintHelp( con, stdout, NULL ); + printf("\n%s is copyright %s %s\n", + VkName.toLatin1().constData(), + vkConfig->vkCopyright.toLatin1().constData(), + vkConfig->vkAuthor.toLatin1().constData() ); +//TODO +// printf("Valgrind is copyright %s\n\n", vkConfig->vgCopyright.toLatin1().constData() ); + break; + + default: + vk_assert_never_reached(); + } +} + + +void parseError( vkPoptContext con, const int err ) +{ + // don't print anything; sender is dealing with msgs + if ( err != PERROR_DEFAULT ) { + fprintf( stderr, "%s: Parse error [%s] : %s\n", + vkConfig->vkName.toLatin1().constData(), + vkPoptBadOption(con), + parseErrString( err ) ); + fprintf( stderr, "%s: Use --help for more information.\n", + vkConfig->vkName.toLatin1().constData() ); + } +} + + +/*! + getObjOptions() + Determine the total no. of option structs required by counting the + no. of entries in the optList. Note: num_options = optList+1 + because we need a NULL option entry to terminate each option array. +*/ +vkPoptOption* getObjOptions( /*IN */VkObject* obj, + /*OUT*/vkPoptOption* vkOpts ) +{ + vk_assert( obj != NULL ); + vk_assert( vkOpts != NULL ); + + int idx = 0; + OptionHash opthash = obj->getOptions(); + for ( Iter_OptionHash it = opthash.begin(); it != opthash.end(); ++it ) { + VkOption* opt = it.value(); + vk_assert( opt != NULL ); + + // ignore non-popt options + if ( opt->argType == VkOPT::NOT_POPT ) + continue; + + vkPoptOption* vkopt = &vkOpts[idx++]; + vkopt->arg = NULL; + vkopt->optId = opt->optid; + vkopt->argType = opt->argType; + vkopt->shortFlag = opt->shortFlag.toLatin1(); + + vkopt->optGrp = (char*)malloc( opt->configGrp.length()+1 ); + strncpy( vkopt->optGrp, opt->configGrp.toLatin1().data(), opt->configGrp.length()+1 ); + + vkopt->longFlag = (char*)malloc( opt->longFlag.length()+1 ); + strncpy( vkopt->longFlag, opt->longFlag.toLatin1().data(), opt->longFlag.length()+1 ); + + vkopt->helptxt = (char*)malloc( opt->longHelp.length()+1 ); + strncpy( vkopt->helptxt, opt->longHelp.toLatin1().data(), opt->longHelp.length()+1 ); + + vkopt->helpdesc = (char*)malloc( opt->flagDescr.length()+1 ); + strncpy( vkopt->helpdesc, opt->flagDescr.toLatin1().data(), opt->flagDescr.length()+1 ); + } + // null entry terminator + vkOpts[idx] = nullOpt(); + return vkOpts; +} + + +void getAllOptions( /*IN */VkObjectList objList, + /*OUT*/vkPoptOption* allOpts ) +{ + int nopts, idx = 0; + size_t nbytes; + vkPoptOption* vkOpts; + vk_assert( allOpts != NULL ); + + for (int i = 0; i < objList.size(); ++i) { + VkObject* obj = objList.at(i); + + // allocate mem for this object's options + nopts = obj->getOptions().count(); + nbytes = sizeof(vkPoptOption) * (nopts + 1/*null end*/); + vkOpts = (vkPoptOption*)malloc( nbytes ); + + vkPoptOption* tblOpt = &allOpts[idx++]; + *tblOpt = nullOpt(); // init null struct + tblOpt->arg = getObjOptions( obj, vkOpts ); // get this object's options + // set table name to option group name + tblOpt->optGrp = (char*)malloc( obj->objectName().length()+1 ); + strncpy( tblOpt->optGrp, obj->objectName().toLatin1().data(), obj->objectName().length()+1 ); + } + // null entry terminator + allOpts[idx] = nullOpt(); +} + + +void freeOptions( vkPoptOption* opt ) +{ + for (; opt && opt->optGrp; opt++ ) { + // recurse and free the opt tree. + if ( opt->arg != NULL ) { + freeOptions( opt->arg ); + _free( opt->arg ); // Do free non-top level opts + } + _free( opt->optGrp ); + _free( opt->longFlag ); + _free( opt->helptxt ); + _free( opt->helpdesc ); + // Don't free top level opts: allocated on stack. + } +} + + +bool parseCmdArgs( int argc, char** argv, Valkyrie* vk, + bool& show_help_and_exit ) +{ + int rc = PARSED_OK; // check fn return value / err value + bool ret = true; // return value + show_help_and_exit = false; // just quit. + char argVal[512]; // store argument values for checking + + // -------------------------------------------------- + // fetch all object options + VkObjectList objList = vk->vkObjList(); + int num_objs = objList.count(); + vkPoptOption allOpts[num_objs+1/*null end*/]; + getAllOptions( objList, allOpts ); + +#if 0 // TODO: rm when done debugging + cerr << "PRINTOUT" << endl; + for ( int i=0; i<num_objs; i++) { + vkPoptOption* opt = &allOpts[i]; + cerr << "TABLE: " << opt->optGrp << endl; + + opt = opt->arg; + while ( opt && opt->optId != -1 ) { + cerr << opt->optGrp << ", " << opt->optId << ", " << opt->longFlag << endl; + opt++; + } + } +#endif + + + // -------------------------------------------------- + // context for parsing cmd-line opts + vkPoptContext optCon = + vkPoptGetContext( argc, (const char**)argv, allOpts ); + + // -------------------------------------------------- + // process the options + while ( true ) { + const vkPoptOption* opt = NULL; + bool done_vk_flags = false; + rc = vkPoptGetNextOpt( optCon, argVal, &opt, done_vk_flags ); + + if ( rc != PARSED_OK ) { + // an error occurred during option processing + parseError( optCon, rc ); + ret = false; + goto done; + } + + if ( done_vk_flags ) { + // no more vk/vg flags - continue on. + break; + } + + vk_assert(opt); + + // Just show help and exit? + char vk_arg = opt->shortFlag; + // printf("vk_arg: '%c'\n", vk_arg); + if ( vk_arg == 'h' || vk_arg == 'v' || vk_arg == 'V' ) { + showHelp( optCon, vk_arg, vk ); + show_help_and_exit = true; + goto done; + } + + // vkObjects check their own arguments + QString qs_argval = argVal; + rc = vk->checkOptArg( opt->optGrp, opt->optId, qs_argval ); + + if ( rc != PARSED_OK ) { + parseError( optCon, rc ); + ret = false; + goto done; + } + + vk->updateConfig( opt->optGrp, opt->optId, qs_argval ); + + } // end while. + + + // -------------------------------------------------- + // Get the leftovers: should only be 'myprog --myflags'. + // - Check we really do have a valid prog-to-debug here. + // If yes, then assume all subsequent flags belong to it. + if ( vkPoptPeekArg(optCon) != NULL ) { + + // First get myprog + QString qs_argval = vkPoptGetArg(optCon); + rc = vk->checkOptArg( VALKYRIE::BINARY, qs_argval ); + if ( rc != PARSED_OK ) { + parseError( optCon, rc ); + ret = false; + goto done; + } + vk->updateConfig( VALKYRIE::BINARY, qs_argval ); + + // Get myprog's flags, if any + const char **args = vkPoptGetArgs( optCon ); + QStringList aList; + for ( int i=0; args && args[i] != NULL; i++ ) { + aList << args[i]; + } + qs_argval = aList.isEmpty() ? "" : aList.join( " " ); + rc = vk->checkOptArg( vk->objectName(), VALKYRIE::BIN_FLAGS, qs_argval ); + + if ( rc != PARSED_OK ) { + parseError( optCon, rc ); + ret = false; + goto done; + } + vk->updateConfig( VALKYRIE::BIN_FLAGS, qs_argval ); + } + + +done: + // -------------------------------------------------- + // Cleanup + freeOptions( allOpts ); + vkPoptFreeContext( optCon ); + return ret; +} Added: branches/valkyrie_qt4port/options/vk_parse_cmdline.h =================================================================== --- branches/valkyrie_qt4port/options/vk_parse_cmdline.h (rev 0) +++ branches/valkyrie_qt4port/options/vk_parse_cmdline.h 2010-01-08 21:43:43 UTC (rev 464) @@ -0,0 +1,33 @@ +/**************************************************************************** +** Parse command-line options +** - Called from main() to parse both valkyrie and valgrind args +** -------------------------------------------------------------------------- +** +** Copyright (C) 2000-2010, OpenWorks LLP. All rights reserved. +** <in...@op...> +** +** This file is part of Valkyrie, a front-end for Valgrind. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file COPYING included in the packaging of +** this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef __VK_PARSE_CMDLINE_H +#define __VK_PARSE_CMDLINE_H + + +/*! + parseCmdArgs() + Command-line args parsing, updates global config settings. +*/ +extern bool parseCmdArgs( int argc, char** argv, Valkyrie* vk, + bool& show_help_and_exit ); + +#endif // #ifndef __VK_PARSE_CMDLINE_H + Added: branches/valkyrie_qt4port/options/vk_popt.cpp =================================================================== --- branches/valkyrie_qt4port/options/vk_popt.cpp (rev 0) +++ branches/valkyrie_qt4port/options/vk_popt.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -0,0 +1,640 @@ +/**************************************************************************** +** Implementation of Popt functions +** This is a seriously hacked version of the popt libraries. +** No credit to me, all thanks and many apologies to the Red Hat team +** -------------------------------------------------------------------------- +** popt is Copyright (C) 1998 Red Hat Software and distributed under +** an X11-style license, which is in turn compatible the GNU GPL v.2. +** See the file COPYING for the full license details. +*/ + +#include "options/vk_popt.h" +#include "options/vk_option.h" // namespace VkOPT +#include "utils/vk_utils.h" + + +/*! + return a vkPoptOption initialised to null +*/ +vkPoptOption nullOpt() +{ + vkPoptOption _nullOpt = TABLE_END; + return _nullOpt; +} + +const char * vkPoptPeekArg( vkPoptContext con ) +{ + const char * ret = NULL; + if ( con && con->leftovers != NULL && + con->nextLeftover < con->numLeftovers ) + ret = con->leftovers[con->nextLeftover]; + return ret; +} + + +const char * vkPoptGetArg( vkPoptContext con ) +{ + const char * ret = NULL; + if ( con && con->leftovers != NULL && + con->nextLeftover < con->numLeftovers ) { + ret = con->leftovers[con->nextLeftover++]; + } + return ret; +} + + +const char ** vkPoptGetArgs( vkPoptContext con ) +{ + if ( con == NULL || con->leftovers == NULL || + con->numLeftovers == con->nextLeftover ) + return NULL; + + // some apps like [like RPM ;-) ] need this NULL terminated + con->leftovers[con->numLeftovers] = NULL; + return (con->leftovers + con->nextLeftover); +} + + +vkPoptContext vkPoptGetContext( int argc, const char ** argv, + const vkPoptOption * options ) +{ + vkPoptContext con = (vkPoptContext)malloc( sizeof(*con) ); + + if ( con == NULL ) { + return NULL; + } + + memset( con, 0, sizeof(*con) ); + + con->os = con->optionStack; + con->os->argc = argc; + con->os->argv = argv; + con->os->next = 1; // skip argv[0] + con->leftovers = (const char**)calloc( (argc + 1), sizeof(*con->leftovers) ); + con->options = options; + con->flags = PCONTEXT_POSIXMEHARDER; + con->finalArgvAlloced = argc * 2; + con->finalArgv = (const char**)calloc( con->finalArgvAlloced, + sizeof(*con->finalArgv) ); + + return con; +} + + +static void vkCleanOSE( struct optionStackEntry *os ) +{ + os->nextArg = (const char*)_free( os->nextArg ); + os->argv = (const char**)_free( os->argv ); +} + + +const vkPoptOption * vkFindOption( const vkPoptOption * opt, + const char * longFlag, + char shortFlag, + int singleDash ) +{ + // this happens when a single - is given + if ( singleDash && !shortFlag && (longFlag && *longFlag == '\0') ) + shortFlag = '-'; + + for (; opt->longFlag || opt->shortFlag || opt->arg; opt++) { + + if ( opt->arg != NULL ) { // is-a table + // recurse on included sub-tables. + const vkPoptOption* opt2 = vkFindOption( opt->arg, longFlag, shortFlag, singleDash ); + if ( opt2 == NULL ) { + // no match in sub-table + continue; + } + // found match: return option + return opt2; + } + else { // is-a leaf + if ( longFlag && opt->longFlag && !singleDash && + !strcmp( longFlag, opt->longFlag ) ) { + // longFlag match + break; + } + if (shortFlag && shortFlag == opt->shortFlag) { + // shortFlag match + break; + } + } + } + + if ( !opt->longFlag && !opt->shortFlag ) { + // end of optArr: no match found + return NULL; + } + + // found match + return opt; +} + + +static const char * vkExpandNextArg( const char * s ) +{ + char *t, *te; + size_t tn = strlen(s) + 1; + char c; + + te = t = (char*)malloc(tn);; + if ( t == NULL ) + return NULL; + while ((c = *s++) != '\0') { + *te++ = c; + } + + *te = '\0'; + // memory leak, hard to plug + t = (char*)realloc(t, strlen(t) + 1); + return t; +} + + +/*! + get next option opt_ret + returns 0 on success, PERROR_* on error +*/ +int vkPoptGetNextOpt( vkPoptContext con, + char *arg_val/*OUT*/, + const vkPoptOption** opt_ret/*OUT*/, + bool& done_vk_flags/*OUT*/ ) +{ + const vkPoptOption * opt = NULL; + int done = 0; + + if ( con == NULL ) { + done_vk_flags = true; + return PARSED_OK; + } + + while ( !done ) { + const char * origOptString = NULL; + const char * longArg = NULL; + int shorty = 0; + + while ( !con->os->nextCharArg && + con->os->next == con->os->argc && + con->os > con->optionStack ) { + vkCleanOSE( con->os-- ); + } + + if ( !con->os->nextCharArg && + con->os->next == con->os->argc ) { + done_vk_flags = true; + *opt_ret = opt; + return PARSED_OK; + } + + // process next long option + if ( !con->os->nextCharArg ) { + char * localOptString, * optString; + int thisopt; + thisopt = con->os->next; + if ( con->os->argv != NULL ) + origOptString = con->os->argv[con->os->next++]; + + if ( origOptString == NULL ) { + return PERROR_BADOPT; + } + if ( strcmp(origOptString, "--") == 0 ) { + return PERROR_BADQUOTE; + } + + if ( con->restLeftover || *origOptString != '-' ) { + if ( con->flags & PCONTEXT_POSIXMEHARDER ) + con->restLeftover = 1; + if ( con->leftovers != NULL ) + con->leftovers[con->numLeftovers++] = origOptString; + continue; + } + + // make a copy we can hack at + localOptString = optString = + strcpy((char*)alloca(strlen(origOptString) + 1), origOptString); + + if ( optString[0] == '\0' ) + return PERROR_BADOPT; + + if ( optString[1] == '-' && !optString[2] ) { + con->restLeftover = 1; + continue; + } else { + char *oe; + int singleDash; + optString++; + if ( *optString == '-' ) + singleDash = 0, optString++; + else + singleDash = 1; + + // Check for "--long=arg" option + for ( oe = optString; *oe && *oe != '='; oe++ ) + { }; + if ( *oe == '=' ) { + // FIX: don't use '=' for shortopts + if ( singleDash ) + return PERROR_NODASH; + *oe++ = '\0'; + + // longArg is mapped back to persistent storage. + longArg = origOptString + (oe - localOptString); + + // FIX: catch cases where --longarg=<no-arg> + if ( strlen(longArg) == 0 ) { + printf("1: returning PERROR_NOARG\n"); + return PERROR_NOARG; + } + } +#if 0 + else if ( singleDash == 0 ) { + /* FIX: catch cases where we didn't find an '=', + and this is a --longarg option */ + //printf("2: returning PERROR_NOARG\n"); + return PERROR_NOARG; + } +#endif + + opt = vkFindOption( con->options, optString, + '\0', singleDash ); + if ( !opt && !singleDash ) { + printf("returning PERROR_BADOPT\n"); + return PERROR_BADOPT; + } + } + + if ( !opt ) { + con->os->nextCharArg = origOptString + 1; + } else { + shorty = 0; + } + } + + // process next short option + if ( con->os->nextCharArg ) { + origOptString = con->os->nextCharArg; + con->os->nextCharArg = NULL; + + opt = vkFindOption( con->options, NULL, *origOptString, 0 ); + if ( !opt ) { + return PERROR_BADOPT; + } + shorty = 1; + + origOptString++; + if ( *origOptString != '\0' ) + con->os->nextCharArg = origOptString; + } + + if ( opt == NULL ) + return PERROR_BADOPT; + + if ( opt->argType != VkOPT::ARG_NONE ) { + con->os->nextArg = (const char*)_free(con->os->nextArg); + if ( longArg ) { + longArg = vkExpandNextArg( longArg ); + con->os->nextArg = longArg; + } else if ( con->os->nextCharArg ) { + longArg = vkExpandNextArg( con->os->nextCharArg); + con->os->nextArg = longArg; + con->os->nextCharArg = NULL; + } else { + while ( con->os->next == con->os->argc && + con->os > con->optionStack ) { + vkCleanOSE( con->os-- ); + } + if ( con->os->next == con->os->argc ) { + // FIX: con->os->argv not defined + return PERROR_NOARG; + con->os->nextArg = NULL; + } else { + if ( con->os->argv != NULL ) { + // watch out: subtle side-effects live here. + longArg = con->os->argv[con->os->next++]; + longArg = vkExpandNextArg( longArg ); + con->os->nextArg = longArg; + } + } + } + longArg = NULL; + + // store the argument value for checking + if ( con->os->nextArg ) { + sprintf( arg_val, "%s", con->os->nextArg ); + } + } // end of "if ! VkOPT::ARG_NONE" + + if ( opt->optId >= 0 ) { // is-a leaf + done = 1; + } + + if ( (con->finalArgvCount + 2) >= (con->finalArgvAlloced) ) { + con->finalArgvAlloced += 10; + con->finalArgv = (const char**)realloc(con->finalArgv, + sizeof(*con->finalArgv) * con->finalArgvAlloced); + } + + if ( con->finalArgv != NULL ) { + char *s = (char*)malloc((opt->longFlag ? strlen(opt->longFlag) : 0) + 3); + if ( s != NULL ) { + if ( opt->longFlag ) { + sprintf(s, "--%s", opt->longFlag); + } else { + sprintf(s, "-%c", opt->shortFlag); + } + con->finalArgv[con->finalArgvCount++] = s; + } else + con->finalArgv[con->finalArgvCount++] = NULL; + } + + if ((opt->arg == NULL/* leaf */) && + (opt->argType != VkOPT::ARG_NONE)) { + if (con->finalArgv != NULL && con->os->nextArg) { + char* s = (char*)malloc( strlen(con->os->nextArg)+1 ); + if (s == NULL) { + vkPrintErr("virtual memory exhausted."); + exit(EXIT_FAILURE); + } else { + con->finalArgv[con->finalArgvCount++] = + strcpy( s, con->os->nextArg ); + } + } + } + } // end while ( !done ) + + //vk_assert( opt != NULL ); + *opt_ret = opt; + return PARSED_OK; +} + + +vkPoptContext vkPoptFreeContext( vkPoptContext con ) +{ + if ( con == NULL ) + return con; + + // poptResetContext( con ); + int i; + while ( con->os > con->optionStack ) { + vkCleanOSE(con->os--); + } + con->os->nextCharArg = NULL; + con->os->nextArg = NULL; + con->os->next = 1; // skip argv[0] + con->numLeftovers = 0; + con->nextLeftover = 0; + con->restLeftover = 0; + + if ( con->finalArgv != NULL ) + for (i = 0; i < con->finalArgvCount; i++) + con->finalArgv[i] = (const char*)_free(con->finalArgv[i]); + con->finalArgvCount = 0; + + con->leftovers = (const char**)_free( con->leftovers ); + con->finalArgv = (const char**)_free( con->finalArgv ); + + con = (vkPoptContext)_free( con ); + return con; +} + + +const char * vkPoptBadOption( vkPoptContext con ) +{ + struct optionStackEntry * os = NULL; + + if ( con != NULL ) + os = con->optionStack; + + return ( os && os->argv ? os->argv[os->next - 1] : NULL ); +} + + + +/* ------ help printing stuff --------------------------------*/ +// set in poptPrintHelp +static int leftColWidth = -1; + + +static const char * vkGetHelpDesc( const vkPoptOption * opt ) +{ + // if ARG_NONE: no arguments to describe + if ( opt->argType == VkOPT::ARG_NONE ) + return NULL; + + if ( opt->helpdesc ) + return opt->helpdesc; + + return NULL; +} + + +/*! + vkSingleOptionHelp() + called from vkTableHelp() for leaf table. +*/ +static void vkSingleOptionHelp( FILE * fp, + const vkPoptOption * opt ) +{ + int indentLength = leftColWidth + 2; + int lineLength = 80 - indentLength; + const char* help = opt->helptxt; + const char* helpdesc = vkGetHelpDesc( opt ); + int helpLength; + char * defs = NULL; + char * left; + int nb = leftColWidth + 1; + + // make sure there's more than enough room in target buffer. + if ( opt->longFlag ) + nb += strlen( opt->longFlag ); + if ( helpdesc ) + nb += strlen( helpdesc ); + + left = (char*)malloc( nb ); + if ( left == NULL ) + return; + left[0] = '\0'; + left[leftColWidth] = '\0'; + + if ( opt->longFlag && opt->shortFlag ) { + sprintf( left, "-%c, --%s", opt->shortFlag, opt->longFlag); + } else if (opt->shortFlag != '\0') { + sprintf( left, "-%c", opt->shortFlag); + } else if (opt->longFlag) { + sprintf( left, "--%s", opt->longFlag ); + } + + if ( !*left ) { + goto out; + } + + if ( helpdesc ) { + char * le = left + strlen( left ); + *le++ = ' '; + strcpy( le, helpdesc ); + le += strlen(le); + *le = '\0'; + } + + if ( help ) { + fprintf( fp," %-*s", leftColWidth, left ); + } else { + fprintf( fp," %s\n", left ); + goto out; + } + + left = (char*)_free(left); + if ( defs ) { + help = defs; + defs = NULL; + } + + helpLength = strlen( help ); + while ( helpLength > lineLength ) { + const char * ch; + char format[100]; + + ch = help + lineLength - 1; + while ( ch > help && !isspace(*ch) ) { + ch--; + } + if ( ch == help ) { + break; // give up + } + while ( ch > (help + 1) && isspace(*ch) ) { + ch--; + } + ch++; + + sprintf( format, "%%.%ds\n%%%ds", + (int) (ch - help), indentLength ); + fprintf( fp, format, help, " " ); + help = ch; + while ( isspace(*help) && *help ) { + help++; + } + helpLength = strlen( help ); + } + + if ( helpLength ) + fprintf( fp, "%s\n", help ); + + out: + defs = (char*)_free(defs); + left = (char*)_free(left); +} + + +static int vkMaxArgWidth( const vkPoptOption * opt ) +{ + int max = 0; + int len = 0; + const char * s; + + if ( opt == NULL ) + return 0; + + for (; opt->longFlag || opt->shortFlag || opt->arg; opt++ ) { + + if ( opt->arg != NULL ) { // is-a table + // recurse on included sub-tables. + len = vkMaxArgWidth( opt->arg ); + if ( len > max ) + max = len; + } + else { // is-a leaf + len = sizeof(" ") - 1; + if ( opt->shortFlag != '\0' ) + len += sizeof("-X")-1; + if ( opt->shortFlag != '\0' && opt->longFlag ) + len += sizeof(", ")-1; + if (opt->longFlag) { + len += sizeof("--") - 1; + len += strlen( opt->longFlag ); + } + + s = vkGetHelpDesc( opt ); + if ( s ) + len += sizeof("=") - 1 + strlen( s ); + if ( len > max ) + max = len; + } + } + return max; +} + + +/*! + vkTableHelp() + this version prints nested tables first. swap 'em over if this + isn't the behaviour you want. +*/ +static void vkTableHelp( FILE * fp, const vkPoptOption * opt ) +{ + if ( opt == NULL ) + return; + + // recurse over all tables + for (; opt->longFlag || opt->shortFlag || opt->arg; opt++) { + if ( opt->arg != NULL ) { // is-a table + // print table title + fprintf( fp, "\n%s options:\n", opt->optGrp ); + // recurse on included sub-tables. + vkTableHelp( fp, opt->arg ); + } + else { // is-a leaf + // print options + vkSingleOptionHelp( fp, opt ); + } + } +} + + +/*! + vkPoptPrintHelp() + if tableName == NULL, recurses over all tables; + else just prints contents of the specified table. +*/ +void vkPoptPrintHelp( vkPoptContext con, FILE * fp, + const char * tableName ) +{ + const char * fn; + + fprintf( fp, "\nUsage:" ); + fn = con->optionStack->argv[0]; + if ( fn != NULL ) { + if ( strchr(fn, '/') ) + fn = strrchr( fn, '/' ) + 1; + fprintf( fp, " %s", fn ); + } + + fprintf( fp, " %s", + "[valkyrie-opts] [valgrind-opts] [prog-and-args]\n" ); + + leftColWidth = vkMaxArgWidth( con->options ); + + if ( tableName == NULL ) { + // print all tables + vkTableHelp( fp, con->options ); + } else { + // trawl through con->options till we find the right table + const vkPoptOption * opt; + for ( opt = con->options; (opt != NULL) && + (opt->optGrp != NULL); opt++ ) { + if ( strcmp( opt->optGrp, tableName ) == 0 ) { + break; + } + } + + // print the table: + if ( opt != NULL) { + if ( opt->optGrp != NULL ) + fprintf( fp, "\n%s options:\n", opt->optGrp ); + else + vkPrintErr("Error: vkPoptPrintHelp(): No match found for table '%s'.", tableName); + vkTableHelp( fp, opt->arg ); + } + } + +} Added: branches/valkyrie_qt4port/options/vk_popt.h =================================================================== --- branches/valkyrie_qt4port/options/vk_popt.h (rev 0) +++ branches/valkyrie_qt4port/options/vk_popt.h 2010-01-08 21:43:43 UTC (rev 464) @@ -0,0 +1,129 @@ +/**************************************************************************** +** Definition of Popt functions +** This is a seriously hacked version of the popt libraries. +** No credit to me, all thanks and many apologies to the Red Hat team +** -------------------------------------------------------------------------- +** popt is Copyright (C) 1998 Red Hat Software and distributed under +** an X11-style license, which is in turn compatible the GNU GPL v.2. +** See the file COPYING for the full license details. +*/ + +#ifndef __VK_POPT_H +#define __VK_POPT_H + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "options/vk_option.h" + + +#define OPTION_DEPTH 10 + +// options can't follow args +#define PCONTEXT_POSIXMEHARDER (1 << 2) + +/*! + vkPoptOption + This may be one of: + - TABLE_END: none set of: shortFlag && longFlag && arg + - table: arg = array of options, optGrp = table title + - option: arg = NULL, remaining vars filled +*/ +typedef struct _vkPoptOption { + struct _vkPoptOption* arg; // table holds ptr to + char* optGrp; // opt group name: "valgrind" etc. + int optId; // eg. VIEW-LOG + VkOPT::ArgType argType; // option type: ARG_*** + char shortFlag; // '\0' || 'h' + char* longFlag; // NULL || --help + char* helptxt; // help text + char* helpdesc; // eg. <file> +} vkPoptOption; + +#define TABLE_END { NULL, NULL, -1, VkOPT::NOT_POPT, '\0', NULL, NULL, NULL } +vkPoptOption nullOpt(); + + +typedef struct vkPoptContext_s* vkPoptContext; + +#ifdef __cplusplus +extern "C" { +#endif + +/* initialize popt context. + - argc no. of arguments + - argv argument array + - options address of popt option table + - returns initialized popt context */ +vkPoptContext vkPoptGetContext( int argc, const char ** argv, + const vkPoptOption * options ); + +/* get next option opt_ret + returns 0 on success, PERROR_* on error */ +int vkPoptGetNextOpt( vkPoptContext con, char *arg_val, + const vkPoptOption** opt/*OUT*/, + bool& done_vk_flags/*OUT*/ ); + +/* return current option's argument, + or NULL if no more options are available */ +const char * vkPoptGetArg( vkPoptContext con ); + +/* return remaining argument array, terminated with NULL */ +const char ** vkPoptGetArgs( vkPoptContext con ); + +/* peek at current option's argument */ +const char * vkPoptPeekArg( vkPoptContext con ); + +/* return the offending option which caused the most recent error */ +const char * vkPoptBadOption( vkPoptContext con ); + +/* destroy context. return NULL always */ +vkPoptContext vkPoptFreeContext( vkPoptContext con ); + +/* print detailed description of options. + fp == ouput file handle */ +void vkPoptPrintHelp( vkPoptContext con, FILE * fp, + const char * tableName ); + +#ifdef __cplusplus +} +#endif + +/*--------------------------------------------------*/ +/* wrapper to free(3), hides const compilation noise, + permit NULL, return NULL always */ +static inline void * _free( const void * p ) +{ + if ( p != NULL ) + free((void *)p); + return NULL; +} + + +struct optionStackEntry { + int argc; + const char ** argv; + int next; + const char * nextArg; + const char * nextCharArg; +}; + + +struct vkPoptContext_s { + struct optionStackEntry optionStack[OPTION_DEPTH]; + struct optionStackEntry * os; + const char ** leftovers; + int numLeftovers; + int nextLeftover; + const vkPoptOption * options; + int restLeftover; + int flags; + const char ** finalArgv; + int finalArgvCount; + int finalArgvAlloced; +}; + + +#endif Modified: branches/valkyrie_qt4port/utils/vk_config.cpp =================================================================== --- branches/valkyrie_qt4port/utils/vk_config.cpp 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/utils/vk_config.cpp 2010-01-08 21:43:43 UTC (rev 464) @@ -90,45 +90,30 @@ bool VkConfig::initCfg( Valkyrie* vk ) { - // First: check Global config file exists: if not, create one from compiled defailts. + // 1) Check Global config file exists: if not, create one from compiled defailts. if ( ! QFile::exists( vkCfgGlblFilename() ) ) { writeConfigDefaults( vk ); } - // Second: read global config file into RUNTIME settings + // 2) Read global config file into RUNTIME settings // check at least owner read/write perms ok QFile::Permissions perms = QFile::permissions( vkCfgGlblFilename() ); if ( ( perms & QFile::WriteOwner ) != QFile::WriteOwner || ( perms & QFile::ReadOwner ) != QFile::ReadOwner ) { - // TODO: vkError permissions - } else { - // first clear all current settings, then read in global - this->clear(); - readFromGlblConfigFile(); - } +//TODO + cerr << "TODO: vkError permissions on vkCfgGlblFilename" << endl; - // Third: if given a Project file on the command line, read and update 'working' config -#if 0 // TODO: command line args: project file (create if !exist) - get proj_filename - - if ( QFile::exists( proj_filename ) ) { - // check at least owner read/write perms ok - QFile::Permissions perms = QFile::permissions( proj_filename ); - if ( ( perms & QFile::WriteOwner ) != QFile::WriteOwner || - ( perms & QFile::ReadOwner ) != QFile::ReadOwner ) { - // TODO: vkError perms - } else { - vkCfgProjectFilePath = proj_filename; - - // don't clear current settings, just update from project cfg file - readFromProjConfigFile(); - } + } else { + // first clear all current settings, then read in global + this->clear(); + readFromGlblConfigFile(); } -#endif - // Fourth: Command line options update 'working' config - // TODO + // 3) If given a Project file on the command line, read and update 'working' config + // Done by parseCmdArgs() -> vkObj::updateConfig(), called after us. + // 4) Command line options update 'working' config + // Done by parseCmdArgs(), called after us. /* vkFatal( 0, "Initialising Config", @@ -150,10 +135,21 @@ */ void VkConfig::createNewProject( QString& dir, QString& proj_name ) { + createNewProject( dir + "/" + proj_name + "." + VK_CFG_EXT ); +} + + +/*! + VkConfig::createNewProject() + Sets project filename to given (new) project config file. + Writes the current config to the given new project config file. + */ +void VkConfig::createNewProject( QString proj_filename ) +{ // ensure any existing project settings are saved first. vkConfig->sync(); - vkCfgProjectFilename = dir + "/" + proj_name + "." + VK_CFG_EXT; + vkCfgProjectFilename = proj_filename; this->saveToProjConfigFile(); } Modified: branches/valkyrie_qt4port/utils/vk_config.h =================================================================== --- branches/valkyrie_qt4port/utils/vk_config.h 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/utils/vk_config.h 2010-01-08 21:43:43 UTC (rev 464) @@ -74,7 +74,8 @@ bool initCfg( Valkyrie* vk ); void createNewProject( QString& dir, QString& proj_name ); - void openProject( QString& proj_name ); + void createNewProject( QString proj_filename ); + void openProject( QString& proj_filename ); void sync(); void readFromProjConfigFile(); Modified: branches/valkyrie_qt4port/valkyrie.pro =================================================================== --- branches/valkyrie_qt4port/valkyrie.pro 2010-01-08 09:18:57 UTC (rev 463) +++ branches/valkyrie_qt4port/valkyrie.pro 2010-01-08 21:43:43 UTC (rev 464) @@ -5,12 +5,14 @@ TEMPLATE = app SOURCES += main.cpp \ mainwindow.cpp \ - objects/vk_objects.cpp \ objects/valkyrie_object.cpp \ objects/valgrind_object.cpp \ + objects/vk_objects.cpp \ + options/vk_option.cpp \ options/vk_options_dialog.cpp \ - options/vk_option.cpp \ options/vk_options_page.cpp \ + options/vk_parse_cmdline.cpp \ + options/vk_popt.cpp \ options/valgrind_options_page.cpp \ options/valkyrie_options_page.cpp \ options/widgets/opt_base_widget.cpp \ @@ -19,18 +21,20 @@ options/widgets/opt_le_widget.cpp \ options/widgets/opt_sp_widget.cpp \ options/widgets/opt_lb_widget.cpp \ + toolview/helgrindview.cpp \ + toolview/memcheckview.cpp \ toolview/toolview.cpp \ - toolview/memcheckview.cpp \ - toolview/helgrindview.cpp \ - utils/vk_utils.cpp \ - utils/vk_config.cpp + utils/vk_config.cpp \ + utils/vk_utils.cpp HEADERS += mainwindow.h \ - objects/vk_objects.h \ objects/valkyrie_object.h \ objects/valgrind_object.h \ + objects/vk_objects.h \ + options/vk_option.h \ options/vk_options_dialog.h \ - options/vk_option.h \ options/vk_options_page.h \ + options/vk_parse_cmdline.h \ + options/vk_popt.h \ options/valgrind_options_page.h \ options/valkyrie_options_page.h \ options/widgets/opt_base_widget.h \ @@ -39,9 +43,9 @@ options/widgets/opt_le_widget.h \ options/widgets/opt_sp_widget.h \ options/widgets/opt_lb_widget.h \ + toolview/helgrindview.h \ + toolview/memcheckview.h \ toolview/toolview.h \ - toolview/memcheckview.h \ - toolview/helgrindview.h \ - utils/vk_utils.h \ - utils/vk_config.h + utils/vk_config.h \ + utils/vk_utils.h RESOURCES += icons.qrc |