1
/* ---------------------------------------------------------------------
2
* Parse command-line options parse_cmd_args.cpp
4
* ---------------------------------------------------------------------
5
* This file is part of Valkyrie, a front-end for Valgrind
6
* Copyright (C) 2000-2008, OpenWorks LLP <info@open-works.co.uk>
7
* This program is released under the terms of the GNU GPL v.2
8
* See the file COPYING for the full license details.
11
#include "vk_objects.h"
12
#include "valkyrie_object.h" /* for Valkyrie::enums */
16
#include "vk_option.h" /* namespace VkOPTION */
17
#include "vk_config.h"
19
/* return values: error < 0, ok = 0(PARSED_OK), show-help-and-exit = 1 */
20
#define SHOW_HELP_EXIT 1
23
void showHelp( vkPoptContext con, char key, Valkyrie* vk )
27
printf("%s-%s\n", vkConfig->vkName(), vkConfig->vkVersion() );
31
vkPoptPrintHelp( con, stdout, vk->title().latin1() );
32
printf( "\n%s is copyright %s %s\n"
33
"and licensed under the GNU General Public License, version 2.\n"
34
"Bug reports, feedback, praise, abuse, etc, to <%s>\n\n",
35
vkConfig->vkName(), vkConfig->vkCopyright(),
36
vkConfig->vkAuthor(), vkConfig->vkEmail() );
40
vkPoptPrintHelp( con, stdout, NULL );
41
printf("\n%s is copyright %s %s\n",
43
vkConfig->vkCopyright(), vkConfig->vkAuthor() );
44
printf("Valgrind is copyright %s\n\n", vkConfig->vgCopyright() );
48
vk_assert_never_reached();
53
void parseError( vkPoptContext con, const int err )
55
/* don't print anything; sender is dealing with msgs */
56
if ( err != PERROR_DEFAULT ) {
57
fprintf( stderr, "%s: Parse error [%s] : %s\n",
59
vkPoptBadOption(con), parseErrString( err ) );
60
fprintf( stderr, "%s: Use --help for more information.\n",
66
/* determine the total no. of option structs required by counting the
67
no. of entries in the optList. Note: num_options = optList+1
68
because we need a NULL option entry to terminate each option array. */
69
vkPoptOption* getObjOptions( /*IN */VkObject* obj,
70
/*OUT*/vkPoptOption* vkOpts )
75
vk_assert( obj != NULL );
76
vk_assert( vkOpts != NULL );
78
optList = obj->optList();
79
for ( opt = optList.first(); opt; opt = optList.next() ) {
80
vk_assert( opt != NULL );
82
/* ignore non-popt options */
83
if ( opt->m_argType == VkOPTION::NOT_POPT )
86
vkPoptOption* vkopt = &vkOpts[idx++];
87
vkopt->optKey = opt->m_key;
88
vkopt->argType = opt->m_argType;
89
vkopt->shortFlag = opt->m_shortFlag.latin1();
90
vkopt->longFlag = opt->m_longFlag.latin1();
92
vkopt->helptxt = opt->m_longHelp.latin1();
93
vkopt->helpdesc = opt->m_flagDescrip.latin1();
94
/* to later call obj->checkOptArg() */
95
vkopt->objectId = obj->objId();
97
/* null entry terminator */
98
vkOpts[idx] = nullOpt();
103
void getAllOptions( /*IN */VkObjectList objList,
104
/*OUT*/vkPoptOption* allOpts )
108
vkPoptOption* vkOpts;
109
vk_assert( allOpts != NULL );
111
for ( VkObject* obj = objList.first(); obj; obj = objList.next() ) {
112
/* allocate mem for this object's options */
113
nopts = obj->optList().count();
114
nbytes = sizeof(vkPoptOption) * (nopts + 1/*null end*/);
115
vkOpts = (vkPoptOption*)malloc( nbytes );
117
vkPoptOption* tblOpt = &allOpts[idx++];
118
*tblOpt = nullOpt(); /* init null struct */
119
tblOpt->arg = getObjOptions( obj, vkOpts ); /* get this object's options */
120
tblOpt->helptxt = obj->title().latin1(); /* for lookup later */
122
/* null entry terminator */
123
allOpts[idx] = nullOpt();
127
void freeOptions( vkPoptOption* allOpts, int num_objs )
129
for ( int idx=0; idx<num_objs; idx++) {
130
/* free allocated optTable.arg */
131
if (allOpts[idx].arg != NULL) {
132
free( allOpts[idx].arg );
133
allOpts[idx].arg = NULL;
140
int parseCmdArgs( int argc, char** argv, Valkyrie* vk )
142
int rc; // check fn return value / err value
143
char argVal[512]; // store argument values for checking
144
Option* vk_opt = NULL;
147
/* fetch all object options */
148
VkObjectList objList = vk->vkObjList();
149
int num_objs = objList.count();
150
vkPoptOption allOpts[num_objs+1/*null end*/];
151
getAllOptions( objList, allOpts );
153
/* context for parsing cmd-line opts */
154
vkPoptContext optCon =
155
vkPoptGetContext( argc, (const char**)argv, allOpts );
157
/* process the options */
158
const vkPoptOption* opt = NULL;
159
while ( (rc = vkPoptGetNextOpt( optCon, argVal, &opt )) == PARSED_OK ) {
160
/* rc == 1 for the first non-valkyrie/valgrind option */
164
char vk_arg = opt->shortFlag;
165
// printf("vk_arg: '%c'\n", vk_arg);
166
if ( vk_arg == 'h' || vk_arg == 'v' || vk_arg == 'V' ) {
167
showHelp( optCon, vk_arg, vk );
172
VkObject* obj = vk->vkObject( opt->objectId );
173
vk_assert( obj != NULL );
175
rc = obj->checkOptArg( opt->optKey, qs_argval );
177
if ( rc != PARSED_OK ) {
178
parseError( optCon, rc );
182
/* else ok: write option to config
183
Note: not written to disk. The user can do this via option config */
184
vk_opt = obj->findOption( opt->optKey );
185
vk_assert(vk_opt != NULL);
187
if ( opt->objectId == VkObject::ID_VALGRIND &&
188
opt->optKey == Valgrind::SUPPS_SEL ) {
189
/* exception: multiple suppressions are allowed */
190
vkConfig->addEntry( qs_argval, vk_opt->cfgKey(), vk_opt->cfgGroup() );
192
vkConfig->wrEntry( qs_argval, vk_opt->cfgKey(), vk_opt->cfgGroup() );
195
} /* end while ... */
197
/* rc == 1 for the first non-valkyrie/valgrind option */
201
/* an error occurred during option processing */
202
if ( rc != PARSED_OK ) {
203
parseError( optCon, rc );
207
/* get the leftovers: should only be 'myprog --myflags'. check we
208
really do have a valid prog-to-debug here. if yes, then all
209
flags that follow it on the cmd line are assumed to belong to it. */
210
if ( vkPoptPeekArg(optCon) != NULL ) {
211
qs_argval = vkPoptGetArg(optCon);
212
rc = vk->checkOptArg( Valkyrie::BINARY, qs_argval );
213
if ( rc != PARSED_OK ) {
214
parseError( optCon, rc );
218
/* else ok: write option to config (but not to disk yet) */
219
vk_opt = vk->findOption( Valkyrie::BINARY );
220
vk_assert(vk_opt != NULL);
221
vkConfig->wrEntry( qs_argval, vk_opt->cfgKey(), vk_opt->cfgGroup() );
223
/* get client flags, if any */
224
const char **args = vkPoptGetArgs( optCon );
227
while ( args && args[i] != NULL ) {
231
QString flags = aList.join( " " );
232
qs_argval = !flags.isNull() ? flags : "";
233
rc = vk->checkOptArg( Valkyrie::BIN_FLAGS, qs_argval );
235
if ( rc != PARSED_OK ) {
236
parseError( optCon, rc );
240
/* else ok: write option to config (but not to disk yet) */
241
vk_opt = vk->findOption( Valkyrie::BIN_FLAGS );
242
vk_assert(vk_opt != NULL);
243
vkConfig->wrEntry( qs_argval, vk_opt->cfgKey(), vk_opt->cfgGroup() );
248
freeOptions( allOpts, num_objs );
249
vkPoptFreeContext( optCon );