1 /*
2 * util/CmdLine.cc
3 * avida-core
4 *
5 * Copyright 1999-2011 Michigan State University. All rights reserved.
6 * Copyright 1993-2003 California Institute of Technology.
7 * http://avida.devosoft.org/
8 *
9 *
10 * This file is part of Avida.
11 *
12 * Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
14 *
15 * Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License along with Avida.
19 * If not, see <http://www.gnu.org/licenses/>.
20 *
21 * Authors: David M. Bryson <david@programerror.com>
22 *
23 */
24
25 #include "avida/util/CmdLine.h"
26
27 #include "apto/core/FileSystem.h"
28
29 #include "cActionLibrary.h"
30 #include "cAvidaConfig.h"
31 #include "cString.h"
32 #include "cStringIterator.h"
33 #include "cUserFeedback.h"
34 #include "tDictionary.h"
35
36 #include <iostream>
37 #include <cstdio>
38
39
40 using namespace std;
41
42
processArgs(cStringList & argv,cAvidaConfig * cfg)43 static void processArgs(cStringList &argv, cAvidaConfig* cfg)
44 {
45 int argc = argv.GetSize();
46 int arg_num = 1; // Argument number being looked at.
47
48 // Load all of the args into string objects for ease of access.
49 cString* args = new cString[argc];
50 //for (int i = 0; i < argc; i++) args[i] = argv[i];
51 cStringIterator list_it(argv);
52 for (int i = 0; (i < argc) && (list_it.AtEnd() == false); i++) {
53 list_it.Next();
54 args[i] = list_it.Get();
55 }
56
57 cString config_filename = "avida.cfg";
58 tDictionary<cString> sets;
59 tDictionary<cString> defs;
60
61 bool flag_analyze = false;
62 bool flag_interactive = false;
63 bool flag_review = false;
64 bool flag_verbosity = false; int val_verbosity = 0;
65 bool flag_seed = false; int val_seed = 0;
66 bool flag_warn_default = false;
67
68 // Then scan through and process the rest of the args.
69 while (arg_num < argc) {
70 cString cur_arg = args[arg_num];
71
72 // Test against the possible inputs.
73
74 // Print out a list of all possibel actions (was events).
75 if (cur_arg == "-e" || cur_arg == "-events" || cur_arg == "-actions") {
76 cout << endl << "Supported Actions:" << endl;
77 cout << cActionLibrary::GetInstance().DescribeAll() << endl;
78 exit(0);
79 }
80
81 // Review configuration options, listing those non-default.
82 else if (cur_arg == "-review" || cur_arg == "-r") {
83 flag_review = true;
84 }
85
86 else if (cur_arg == "--help" || cur_arg == "-help" || cur_arg == "-h") {
87 cout << "Options:"<<endl
88 << " -a[nalyze] Process analyze.cfg instead of normal "
89 << "run." << endl
90 << " -c[onfig] <filename> Set config file to be <filename>"<<endl
91 << " -def <name> <value> Define config include variables" << endl
92 << " -e; -actions Print a list of all known actions"<< endl
93 << " -h[elp] Help on options (this listing)"<<endl
94 << " -i[nteractive] Run analyze mode interactively" << endl
95 << " -l[oad] <filename> Load a clone file" << endl
96 << " -r[eview] Review avida.cfg settings." << endl
97 << " -s[eed] <value> Set random seed to <value>" << endl
98 << " -set <name> <value> Override values in avida.cfg" << endl
99 << " -v[ersion] Prints the version number" << endl
100 << " -v0 -v1 -v2 -v3 -v4 Set output verbosity to 0..4" << endl
101 << " -w[arn] Warn when default config settings are used." << endl
102 << " --generate-config Generate the default configration files" << endl
103 << endl;
104
105 exit(0);
106 }
107 else if (cur_arg == "-seed" || cur_arg == "-s") {
108 if (arg_num + 1 == argc || args[arg_num + 1][0] == '-') {
109 cerr << "Error: Must include a number as the random seed!" << endl;
110 exit(0);
111 } else {
112 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
113 val_seed = cur_arg.AsInt();
114 }
115 flag_seed = true;
116 } else if (cur_arg == "-analyze" || cur_arg == "-a") {
117 flag_analyze = true;
118 } else if (cur_arg == "-interactive" || cur_arg == "-i") {
119 flag_interactive = true;
120 } else if (cur_arg == "-warn" || cur_arg == "-w") {
121 flag_warn_default = true;
122 } else if (cur_arg == "-version" || cur_arg == "-v") {
123 // We've already showed version info, so just quit.
124 exit(0);
125 } else if (cur_arg.Substring(0, 2) == "-v") {
126 val_verbosity = cur_arg.Substring(2, cur_arg.GetSize() - 2).AsInt();
127 flag_verbosity = true;
128 } else if (cur_arg == "-set") {
129 if (arg_num + 1 == argc || arg_num + 2 == argc) {
130 cerr << "'-set' option must be followed by name and value" << endl;
131 exit(0);
132 }
133 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
134 cString name(cur_arg);
135 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
136 cString value(cur_arg);
137 sets.Set(name, value);
138 } else if (cur_arg == "-def") {
139 if (arg_num + 1 == argc || arg_num + 2 == argc) {
140 cerr << "'-def' option must be followed by name and value" << endl;
141 exit(0);
142 }
143 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
144 cString name(cur_arg);
145 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
146 cString value(cur_arg);
147 defs.Set(name, value);
148 } else if (cur_arg == "-c" || cur_arg == "-config") {
149 if (arg_num + 1 == argc || args[arg_num + 1][0] == '-') {
150 cerr << "Error: Filename for configuration must be specified." << endl;
151 exit(0);
152 }
153 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
154 config_filename = cur_arg;
155 } else if (cur_arg == "--generate-config") {
156 cerr << "Generating default avida.cfg" << endl;
157 cfg->Print(cString(Apto::FileSystem::PathAppend(Apto::FileSystem::GetCWD(), "avida.cfg")));
158 exit(0);
159 } else {
160 cerr << "Error: Unknown Option '" << args[arg_num] << "'" << endl
161 << "Type: \"" << args[0] << " -h\" for a full option list." << endl;
162 exit(0);
163 }
164
165 arg_num++; if (arg_num < argc) cur_arg = args[arg_num];
166 }
167
168 delete [] args;
169
170 // Load configuration file
171 cUserFeedback feedback;
172 cfg->Load(config_filename, cString(Apto::FileSystem::GetCWD()), &feedback, &defs, flag_warn_default);
173 for (int i = 0; i < feedback.GetNumMessages(); i++) {
174 switch (feedback.GetMessageType(i)) {
175 case cUserFeedback::UF_ERROR: cerr << "error: "; break;
176 case cUserFeedback::UF_WARNING: cerr << "warning: "; break;
177 default: break;
178 };
179 cerr << feedback.GetMessage(i) << endl;
180 }
181 if (feedback.GetNumErrors()) exit(-1);
182
183
184 // Process Command Line Flags
185 if (flag_analyze) if (cfg->ANALYZE_MODE.Get() < 1) cfg->ANALYZE_MODE.Set(1);
186 if (flag_interactive) if (cfg->ANALYZE_MODE.Get() < 2) cfg->ANALYZE_MODE.Set(2);
187 if (flag_seed) cfg->RANDOM_SEED.Set(val_seed);
188 if (flag_verbosity) cfg->VERBOSITY.Set(val_verbosity);
189
190 cfg->Set(sets); // Process all command line -set statements
191
192 if (sets.GetSize()) {
193 tList<cString> keys;
194 sets.GetKeys(keys);
195 cString* keystr = NULL;
196 while ((keystr = keys.Pop())) {
197 cerr << "error: unrecognized command line configuration setting '" << *keystr << "'." << endl;
198 }
199 exit(1);
200 }
201
202
203 if (flag_review) {
204 cfg->PrintReview();
205 exit(0);
206 }
207 }
208
ProcessCmdLineArgs(int argc,char * argv[],cAvidaConfig * cfg)209 void Avida::Util::ProcessCmdLineArgs(int argc, char* argv[], cAvidaConfig* cfg)
210 {
211 cStringList sl;
212 for(int i=0; i<argc; i++){
213 sl.PushRear(argv[i]);
214 }
215 processArgs(sl, cfg);
216 }
217