summaryrefslogtreecommitdiff
path: root/support/lib/Support/ProgramOptions.cpp
blob: fc50ddcbbb3161648bd580bd25c1ff27dbd30143 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// $Id$
//***************************************************************************
//
// File:
//    ProgramOptions.C
//
// Purpose:
//    General options processing for any program.
//
// History:
//    08/08/95 - adve  - created in the dHPF compiler
//    10/10/96 - mpal, dbaker - converted to const member functions.
//    11/26/96 - adve  - fixed to handle options that consume 0+ arguments
//    07/15/01 - vadve - Copied to LLVM system and modified
//
//**************************************************************************/

//************************** System Include Files **************************/

#include <iostream.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#ifndef MAXINT
#define MAXINT	((1 << sizeof(int)-1) - 1)
#endif

//*************************** User Include Files ***************************/

#include "llvm/Support/ProgramOptions.h"
#include "llvm/Support/ProgramOption.h"


//************************** Method Definitions ****************************/

ProgramOptions::ProgramOptions(int _argc,
			       const char* _argv[],
			       const char* _envp[])
  : optionRegistry(),
    argc(_argc),
    argv(_argv),
    envp(_envp),
    argsConsumed(0)
{}

string ProgramOptions::StringOptionValue(const string &optString) const {
    const StringOption* handler = (const StringOption*)OptionHandler(optString);
    return (handler == NULL) ? string("") : handler->Value();
}

bool
ProgramOptions::FlagOptionValue(const string &optString) const
{
    const FlagOption* handler = (const FlagOption*) OptionHandler(optString);
    return (handler == NULL) ? false : handler->Value();
}

double
ProgramOptions::RealOptionValue(const string &optString) const
{
    const RealValuedOption* handler =
	(const RealValuedOption*) OptionHandler(optString);
    return (handler == NULL) ? MAXFLOAT : handler->Value();
}

int
ProgramOptions::IntOptionValue(const string &optString) const
{
    const IntegerValuedOption* handler =
	(const IntegerValuedOption*) OptionHandler(optString);
    return (handler == NULL) ? MAXINT : handler->Value();
}

bool
ProgramOptions::OptionSpecified(const string &optString) const
{
    const ProgramOption* handler = OptionHandler(optString);
    return handler->OptionSpecified();
}

const char* 
ProgramOptions::ProgramName() const
{
    return argv[0];
}

int
ProgramOptions::NumberOfOtherOptions() const
{
   return argc - argsConsumed;
} 

const char*
ProgramOptions::OtherOption(int i) const
{
   i += argsConsumed;
   assert(i >= 0 && i < argc);
   return argv[i];
}

const char**
ProgramOptions::GetOriginalArgs() const
{
   return argv;
}

vector<string>
ProgramOptions::GetDescription() const
{  
  vector<string> optDesc;
  
  if (optDesc.size() < (unsigned) argc)
    {
      for (hash_map<string,ProgramOption*>::const_iterator iter=optionRegistry.begin();
	   ! (iter == optionRegistry.end());
	   ++iter)
	{
	  const ProgramOption* handler = iter->second;
	  optDesc.push_back(handler->ArgString());	// 1st
	  optDesc.push_back(handler->HelpMesg());	// 2nd
	  optDesc.push_back(handler->GetTextValue());		// 3rd
	}
    }
  
  return optDesc;
}

void
ProgramOptions::Register(ProgramOption* option)
{
  optionRegistry[option->ArgString()] = option;
}

//----------------------------------------------------------------------
// function ProgramOptions::ParseArgs
// 
// Parse command-line options until you run out of options or see
// an unrecognized option.  `getopt' is a standard package to do this,
// but incredibly, it limited to single-letter options.
//
// -- Each option can consume zero or one additional arguments of argv
// -- "--" can be used to mark the end of options
//	  so that a program argument can also start with "-".
//---------------------------------------------------------------------/

void
ProgramOptions::ParseArgs(int argc,
			  const char* argv[],
			  const char* envp[])
{
  if (argc == 0) {
    Usage();
  }
  // consume the program name
  argsConsumed = 1;
  
  while (argsConsumed < argc)
    {
      const char* arg = argv[argsConsumed];
      if (arg[0] == '-')
	{
	  if (strcmp(arg, "--") == 0) {	// "--" marks end of options
	    argsConsumed++;		// consume and
	    break;			// discontinue the for loop
	  }
	  ProgramOption* handler = OptionHandler(arg+1);
	  if (handler == NULL) {
	    cerr << "Unrecognized option: " << arg+1 << endl;
	    Usage();
	  }

	  if (argc - argsConsumed < handler->MinExpectedArgs()) {
	    cerr << "Option " << (char*) arg+1 << " needs "
		 << handler->MinExpectedArgs() << " arguments" << endl;
	    Usage();
	  }

	  argsConsumed++;  // consumed the option

	  const char* nextArg = (argsConsumed < argc)? argv[argsConsumed]
						     : "";
	  int numAdditionalArgsConsumed = handler->EvalOpt(nextArg);
	  if (numAdditionalArgsConsumed < 0)
	    Usage();
	  argsConsumed += numAdditionalArgsConsumed;
	}
      else
	{
	  break; // quit the while loop 
	}
    }
  
  ParseExtraArgs(); 
}

void
ProgramOptions::PrintArgs(ostream& stream) const
{
  for (int i = 0; i < argc; i++) {
    stream << argv[i] << " ";
  }
  stream << endl; 
}


void
ProgramOptions::PrintOptions(ostream& stream) const
{
  stream << "OPTIONS:" << endl;
  stream << "\tUse argument 0 to turn OFF a flag option: "
	 << "-<flag_opt> 0" << endl << endl;
    
  for (hash_map<string,ProgramOption*>::const_iterator iter = optionRegistry.begin();
       iter != optionRegistry.end(); ++iter) {
      const ProgramOption* handler = (*iter).second;
      
      stream << "\t-" << handler->ArgString();
      
      const char* const showarg = " <arg>";
      int i = 1;
      for (i=1; i <= handler->MinExpectedArgs(); i++)
	stream << showarg; 
      
      int numCharsPrinted = 1 + handler->ArgString().length()
	+ 6 * handler->MinExpectedArgs();
      for (i=1; i > numCharsPrinted / 8; i--)
	stream << "\t";
      
      stream << "\t" << handler->HelpMesg()
	     << endl;
    }
}

void
ProgramOptions::Usage() const
{
  PrintUsage(cerr); 
  exit(1); 
}


//**************************************************************************/