blob: 6b5d33975f2c0a4f2a57c0e5317bf772f5661dc5 [file] [log] [blame]
Reid Spencercbabe7f2004-08-19 21:17:53 +00001//===- Configuration.cpp - Configuration Data Mgmt --------------*- C++ -*-===//
Reid Spencer2594c9a2004-08-13 20:21:22 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Reid Spencer and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the parsing of configuration files for the LLVM Compiler
11// Driver (llvmc).
12//
13//===------------------------------------------------------------------------===
14
Reid Spencerf51a87c2004-08-19 21:52:49 +000015#include "Configuration.h"
Reid Spencer68fb37a2004-08-14 09:37:15 +000016#include "ConfigLexer.h"
Reid Spencer2594c9a2004-08-13 20:21:22 +000017#include "CompilerDriver.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000018#include "llvm/Config/config.h"
19#include "llvm/Support/CommandLine.h"
20#include "llvm/ADT/StringExtras.h"
Reid Spencer2594c9a2004-08-13 20:21:22 +000021#include <iostream>
Reid Spencer68fb37a2004-08-14 09:37:15 +000022#include <fstream>
Reid Spencer2594c9a2004-08-13 20:21:22 +000023
24using namespace llvm;
25
Reid Spencerb38e4052004-08-20 09:24:07 +000026namespace sys {
27 // From CompilerDriver.cpp (for now)
Reid Spencerf384db32004-08-24 14:03:23 +000028 extern bool FileIsReadable(const std::string& fname);
Reid Spencerb38e4052004-08-20 09:24:07 +000029}
30
Reid Spencer68fb37a2004-08-14 09:37:15 +000031namespace llvm {
Reid Spencerbae68252004-08-19 04:49:47 +000032 ConfigLexerInfo ConfigLexerState;
Reid Spencer68fb37a2004-08-14 09:37:15 +000033 InputProvider* ConfigLexerInput = 0;
Reid Spencer68fb37a2004-08-14 09:37:15 +000034
35 InputProvider::~InputProvider() {}
36 void InputProvider::error(const std::string& msg) {
Reid Spencerbae68252004-08-19 04:49:47 +000037 std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " <<
38 msg << "\n";
Reid Spencer68fb37a2004-08-14 09:37:15 +000039 errCount++;
40 }
41
42 void InputProvider::checkErrors() {
43 if (errCount > 0) {
44 std::cerr << name << " had " << errCount << " errors. Terminating.\n";
45 exit(errCount);
46 }
47 }
48
49}
50
Reid Spencer2594c9a2004-08-13 20:21:22 +000051namespace {
52
Reid Spencer68fb37a2004-08-14 09:37:15 +000053 class FileInputProvider : public InputProvider {
54 public:
55 FileInputProvider(const std::string & fname)
56 : InputProvider(fname)
57 , F(fname.c_str()) {
58 ConfigLexerInput = this;
59 }
60 virtual ~FileInputProvider() { F.close(); ConfigLexerInput = 0; }
61 virtual unsigned read(char *buffer, unsigned max_size) {
62 if (F.good()) {
63 F.read(buffer,max_size);
64 if ( F.gcount() ) return F.gcount() - 1;
65 }
66 return 0;
67 }
Reid Spencer2594c9a2004-08-13 20:21:22 +000068
Reid Spencer68fb37a2004-08-14 09:37:15 +000069 bool okay() { return F.good(); }
70 private:
71 std::ifstream F;
72 };
Reid Spencer2594c9a2004-08-13 20:21:22 +000073
Reid Spencerbae68252004-08-19 04:49:47 +000074 cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden, cl::init(false),
75 cl::desc("Dump lexical tokens (debug use only)."));
76
Reid Spencerbf437722004-08-15 08:19:46 +000077 struct Parser
Reid Spencer68fb37a2004-08-14 09:37:15 +000078 {
Reid Spencerbae68252004-08-19 04:49:47 +000079 Parser() {
80 token = EOFTOK;
81 provider = 0;
82 confDat = 0;
83 ConfigLexerState.lineNum = 1;
84 ConfigLexerState.in_value = false;
85 ConfigLexerState.StringVal.clear();
86 ConfigLexerState.IntegerVal = 0;
87 };
88
Reid Spencerbf437722004-08-15 08:19:46 +000089 ConfigLexerTokens token;
Reid Spencer68fb37a2004-08-14 09:37:15 +000090 InputProvider* provider;
91 CompilerDriver::ConfigData* confDat;
Reid Spencer2594c9a2004-08-13 20:21:22 +000092
Reid Spencer52c2dc12004-08-29 19:26:56 +000093 inline int next() {
Reid Spencerbae68252004-08-19 04:49:47 +000094 token = Configlex();
95 if (DumpTokens)
96 std::cerr << token << "\n";
97 return token;
98 }
Reid Spencer68fb37a2004-08-14 09:37:15 +000099
Reid Spencer52c2dc12004-08-29 19:26:56 +0000100 inline bool next_is_real() {
Reid Spencerbae68252004-08-19 04:49:47 +0000101 next();
Reid Spencer68fb37a2004-08-14 09:37:15 +0000102 return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
Reid Spencer2594c9a2004-08-13 20:21:22 +0000103 }
104
Reid Spencer52c2dc12004-08-29 19:26:56 +0000105 inline void eatLineRemnant() {
Reid Spencer68fb37a2004-08-14 09:37:15 +0000106 while (next_is_real()) ;
Reid Spencer2594c9a2004-08-13 20:21:22 +0000107 }
108
Reid Spencer68fb37a2004-08-14 09:37:15 +0000109 void error(const std::string& msg, bool skip = true) {
110 provider->error(msg);
111 if (skip)
112 eatLineRemnant();
113 }
Reid Spencer2594c9a2004-08-13 20:21:22 +0000114
Reid Spencer68fb37a2004-08-14 09:37:15 +0000115 std::string parseName() {
116 std::string result;
117 if (next() == EQUALS) {
118 while (next_is_real()) {
119 switch (token ) {
120 case STRING :
121 case OPTION :
Reid Spencerbae68252004-08-19 04:49:47 +0000122 result += ConfigLexerState.StringVal + " ";
Reid Spencer68fb37a2004-08-14 09:37:15 +0000123 break;
124 default:
125 error("Invalid name");
126 break;
127 }
128 }
129 if (result.empty())
130 error("Name exepected");
131 else
132 result.erase(result.size()-1,1);
133 } else
134 error("= expected");
135 return result;
136 }
Reid Spencer2594c9a2004-08-13 20:21:22 +0000137
Reid Spencer68fb37a2004-08-14 09:37:15 +0000138 bool parseBoolean() {
139 bool result = true;
140 if (next() == EQUALS) {
141 if (next() == FALSETOK) {
142 result = false;
143 } else if (token != TRUETOK) {
144 error("Expecting boolean value");
145 return false;
146 }
147 if (next() != EOLTOK && token != 0) {
148 error("Extraneous tokens after boolean");
149 }
150 }
151 else
152 error("Expecting '='");
153 return result;
154 }
Reid Spencer2594c9a2004-08-13 20:21:22 +0000155
Reid Spencerbae68252004-08-19 04:49:47 +0000156 bool parseSubstitution(CompilerDriver::StringVector& optList) {
157 switch (token) {
Reid Spencerf384db32004-08-24 14:03:23 +0000158 case ARGS_SUBST: optList.push_back("%args%"); break;
Reid Spencerca01f9b2004-08-30 06:29:06 +0000159 case DEFS_SUBST: optList.push_back("%defs%"); break;
Reid Spencer52c2dc12004-08-29 19:26:56 +0000160 case FORCE_SUBST: optList.push_back("%force%"); break;
Reid Spencerca01f9b2004-08-30 06:29:06 +0000161 case IN_SUBST: optList.push_back("%in%"); break;
162 case INCLS_SUBST: optList.push_back("%incls%"); break;
163 case LIBS_SUBST: optList.push_back("%libs%"); break;
164 case OPT_SUBST: optList.push_back("%opt%"); break;
165 case OUT_SUBST: optList.push_back("%out%"); break;
166 case TARGET_SUBST: optList.push_back("%target%"); break;
167 case STATS_SUBST: optList.push_back("%stats%"); break;
168 case TIME_SUBST: optList.push_back("%time%"); break;
Reid Spencer52c2dc12004-08-29 19:26:56 +0000169 case VERBOSE_SUBST: optList.push_back("%verbose%"); break;
Reid Spencerbae68252004-08-19 04:49:47 +0000170 default:
171 return false;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000172 }
Reid Spencerbae68252004-08-19 04:49:47 +0000173 return true;
174 }
175
176 void parseOptionList(CompilerDriver::StringVector& optList ) {
177 if (next() == EQUALS) {
178 while (next_is_real()) {
179 if (token == STRING || token == OPTION)
180 optList.push_back(ConfigLexerState.StringVal);
181 else if (!parseSubstitution(optList)) {
182 error("Expecting a program argument or substitution", false);
183 break;
184 }
185 }
186 } else
187 error("Expecting '='");
Reid Spencerbf437722004-08-15 08:19:46 +0000188 }
189
Reid Spencer59a745a2004-08-22 18:03:25 +0000190 void parseVersion() {
191 if (next() == EQUALS) {
192 while (next_is_real()) {
193 if (token == STRING || token == OPTION)
194 confDat->version = ConfigLexerState.StringVal;
195 else
196 error("Expecting a version string");
197 }
198 } else
199 error("Expecting '='");
200 }
201
Reid Spencerbf437722004-08-15 08:19:46 +0000202 void parseLang() {
203 switch (next() ) {
204 case NAME:
205 confDat->langName = parseName();
206 break;
207 case OPT1:
208 parseOptionList(confDat->opts[CompilerDriver::OPT_FAST_COMPILE]);
209 break;
210 case OPT2:
211 parseOptionList(confDat->opts[CompilerDriver::OPT_SIMPLE]);
212 break;
213 case OPT3:
214 parseOptionList(confDat->opts[CompilerDriver::OPT_AGGRESSIVE]);
215 break;
216 case OPT4:
217 parseOptionList(confDat->opts[CompilerDriver::OPT_LINK_TIME]);
218 break;
219 case OPT5:
220 parseOptionList(
221 confDat->opts[CompilerDriver::OPT_AGGRESSIVE_LINK_TIME]);
222 break;
223 default:
224 error("Expecting 'name' or 'optN' after 'lang.'");
225 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000226 }
227 }
Reid Spencer2594c9a2004-08-13 20:21:22 +0000228
Reid Spencer68fb37a2004-08-14 09:37:15 +0000229 void parseCommand(CompilerDriver::Action& action) {
230 if (next() == EQUALS) {
Reid Spencerbf437722004-08-15 08:19:46 +0000231 if (next() == EOLTOK) {
Reid Spencer68fb37a2004-08-14 09:37:15 +0000232 // no value (valid)
233 action.program.clear();
234 action.args.clear();
Reid Spencer68fb37a2004-08-14 09:37:15 +0000235 } else {
236 if (token == STRING || token == OPTION) {
Reid Spencer52c2dc12004-08-29 19:26:56 +0000237 action.program.set_file(ConfigLexerState.StringVal);
Reid Spencer2594c9a2004-08-13 20:21:22 +0000238 } else {
Reid Spencer68fb37a2004-08-14 09:37:15 +0000239 error("Expecting a program name");
240 }
241 while (next_is_real()) {
Reid Spencerbf437722004-08-15 08:19:46 +0000242 if (token == STRING || token == OPTION) {
Reid Spencerbae68252004-08-19 04:49:47 +0000243 action.args.push_back(ConfigLexerState.StringVal);
244 } else if (!parseSubstitution(action.args)) {
245 error("Expecting a program argument or substitution", false);
Reid Spencerbf437722004-08-15 08:19:46 +0000246 break;
247 }
Reid Spencer2594c9a2004-08-13 20:21:22 +0000248 }
249 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000250 }
Reid Spencer2594c9a2004-08-13 20:21:22 +0000251 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000252
Reid Spencerbf437722004-08-15 08:19:46 +0000253 void parsePreprocessor() {
254 switch (next()) {
255 case COMMAND:
256 parseCommand(confDat->PreProcessor);
257 break;
258 case REQUIRED:
259 if (parseBoolean())
260 confDat->PreProcessor.set(CompilerDriver::REQUIRED_FLAG);
261 else
262 confDat->PreProcessor.clear(CompilerDriver::REQUIRED_FLAG);
263 break;
264 default:
Reid Spencerf384db32004-08-24 14:03:23 +0000265 error("Expecting 'command' or 'required' but found '" +
266 ConfigLexerState.StringVal);
Reid Spencerbf437722004-08-15 08:19:46 +0000267 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000268 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000269 }
270
Reid Spencerf384db32004-08-24 14:03:23 +0000271 bool parseOutputFlag() {
272 if (next() == EQUALS) {
273 if (next() == ASSEMBLY) {
274 return true;
275 } else if (token == BYTECODE) {
276 return false;
277 } else {
278 error("Expecting output type value");
279 return false;
280 }
281 if (next() != EOLTOK && token != 0) {
282 error("Extraneous tokens after output value");
283 }
284 }
285 else
286 error("Expecting '='");
287 return false;
288 }
289
Reid Spencer68fb37a2004-08-14 09:37:15 +0000290 void parseTranslator() {
Reid Spencerbf437722004-08-15 08:19:46 +0000291 switch (next()) {
292 case COMMAND:
293 parseCommand(confDat->Translator);
294 break;
295 case REQUIRED:
296 if (parseBoolean())
297 confDat->Translator.set(CompilerDriver::REQUIRED_FLAG);
298 else
299 confDat->Translator.clear(CompilerDriver::REQUIRED_FLAG);
300 break;
301 case PREPROCESSES:
302 if (parseBoolean())
303 confDat->Translator.set(CompilerDriver::PREPROCESSES_FLAG);
304 else
305 confDat->Translator.clear(CompilerDriver::PREPROCESSES_FLAG);
306 break;
Reid Spencerf384db32004-08-24 14:03:23 +0000307 case OUTPUT:
308 if (parseOutputFlag())
Reid Spencerbae68252004-08-19 04:49:47 +0000309 confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
Reid Spencerbf437722004-08-15 08:19:46 +0000310 else
Reid Spencerbae68252004-08-19 04:49:47 +0000311 confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
Reid Spencerbf437722004-08-15 08:19:46 +0000312 break;
Reid Spencerbae68252004-08-19 04:49:47 +0000313
Reid Spencerbf437722004-08-15 08:19:46 +0000314 default:
Reid Spencerf384db32004-08-24 14:03:23 +0000315 error("Expecting 'command', 'required', 'preprocesses', or "
316 "'output' but found '" + ConfigLexerState.StringVal +
317 "' instead");
Reid Spencerbf437722004-08-15 08:19:46 +0000318 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000319 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000320 }
321
322 void parseOptimizer() {
Reid Spencerbf437722004-08-15 08:19:46 +0000323 switch (next()) {
324 case COMMAND:
325 parseCommand(confDat->Optimizer);
326 break;
Reid Spencerbae68252004-08-19 04:49:47 +0000327 case PREPROCESSES:
328 if (parseBoolean())
329 confDat->Optimizer.set(CompilerDriver::PREPROCESSES_FLAG);
330 else
331 confDat->Optimizer.clear(CompilerDriver::PREPROCESSES_FLAG);
332 break;
333 case TRANSLATES:
334 if (parseBoolean())
335 confDat->Optimizer.set(CompilerDriver::TRANSLATES_FLAG);
336 else
337 confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG);
338 break;
Reid Spencerf384db32004-08-24 14:03:23 +0000339 case REQUIRED:
Reid Spencerbf437722004-08-15 08:19:46 +0000340 if (parseBoolean())
Reid Spencerf384db32004-08-24 14:03:23 +0000341 confDat->Optimizer.set(CompilerDriver::REQUIRED_FLAG);
Reid Spencerbf437722004-08-15 08:19:46 +0000342 else
Reid Spencerf384db32004-08-24 14:03:23 +0000343 confDat->Optimizer.clear(CompilerDriver::REQUIRED_FLAG);
Reid Spencerbf437722004-08-15 08:19:46 +0000344 break;
Reid Spencerf384db32004-08-24 14:03:23 +0000345 case OUTPUT:
346 if (parseOutputFlag())
Reid Spencerbae68252004-08-19 04:49:47 +0000347 confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
Reid Spencerbf437722004-08-15 08:19:46 +0000348 else
Reid Spencerbae68252004-08-19 04:49:47 +0000349 confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
Reid Spencerbf437722004-08-15 08:19:46 +0000350 break;
351 default:
Reid Spencerf384db32004-08-24 14:03:23 +0000352 error(std::string("Expecting 'command', 'preprocesses', ") +
353 "'translates' or 'output' but found '" +
354 ConfigLexerState.StringVal + "' instead");
Reid Spencerbf437722004-08-15 08:19:46 +0000355 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000356 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000357 }
358
359 void parseAssembler() {
Reid Spencerbf437722004-08-15 08:19:46 +0000360 switch(next()) {
361 case COMMAND:
362 parseCommand(confDat->Assembler);
363 break;
364 default:
365 error("Expecting 'command'");
366 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000367 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000368 }
369
370 void parseLinker() {
Reid Spencerbf437722004-08-15 08:19:46 +0000371 switch(next()) {
Reid Spencerf384db32004-08-24 14:03:23 +0000372 case LIBS:
373 break; //FIXME
374 case LIBPATHS:
375 break; //FIXME
Reid Spencerbf437722004-08-15 08:19:46 +0000376 default:
Reid Spencerf384db32004-08-24 14:03:23 +0000377 error("Expecting 'libs' or 'libpaths'");
Reid Spencerbf437722004-08-15 08:19:46 +0000378 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000379 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000380 }
381
382 void parseAssignment() {
383 switch (token) {
Reid Spencer59a745a2004-08-22 18:03:25 +0000384 case VERSION: parseVersion(); break;
Reid Spencerbf437722004-08-15 08:19:46 +0000385 case LANG: parseLang(); break;
386 case PREPROCESSOR: parsePreprocessor(); break;
387 case TRANSLATOR: parseTranslator(); break;
388 case OPTIMIZER: parseOptimizer(); break;
389 case ASSEMBLER: parseAssembler(); break;
390 case LINKER: parseLinker(); break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000391 case EOLTOK: break; // just ignore
392 case ERRORTOK:
393 default:
Reid Spencerbf437722004-08-15 08:19:46 +0000394 error("Invalid top level configuration item");
395 break;
Reid Spencer68fb37a2004-08-14 09:37:15 +0000396 }
397 }
398
399 void parseFile() {
Reid Spencerbf437722004-08-15 08:19:46 +0000400 while ( next() != EOFTOK ) {
401 if (token == ERRORTOK)
402 error("Invalid token");
403 else if (token != EOLTOK)
404 parseAssignment();
Reid Spencer68fb37a2004-08-14 09:37:15 +0000405 }
406 provider->checkErrors();
407 }
408 };
409
410 void
411 ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
Reid Spencerbf437722004-08-15 08:19:46 +0000412 Parser p;
413 p.token = EOFTOK;
414 p.provider = &provider;
415 p.confDat = &confDat;
Reid Spencerbf437722004-08-15 08:19:46 +0000416 p.parseFile();
Reid Spencer2594c9a2004-08-13 20:21:22 +0000417 }
418}
419
420CompilerDriver::ConfigData*
Reid Spencer68fb37a2004-08-14 09:37:15 +0000421LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
422 CompilerDriver::ConfigData* result = 0;
Reid Spencer52c2dc12004-08-29 19:26:56 +0000423 sys::Path confFile;
424 if (configDir.is_empty()) {
Reid Spencerb38e4052004-08-20 09:24:07 +0000425 // Try the environment variable
426 const char* conf = getenv("LLVM_CONFIG_DIR");
427 if (conf) {
Reid Spencer52c2dc12004-08-29 19:26:56 +0000428 confFile.set_directory(conf);
429 confFile.append_file(ftype);
430 if (!confFile.readable())
Reid Spencerca01f9b2004-08-30 06:29:06 +0000431 throw std::string("Configuration file for '") + ftype +
432 "' is not available.";
Reid Spencerb38e4052004-08-20 09:24:07 +0000433 } else {
434 // Try the user's home directory
Reid Spencer52c2dc12004-08-29 19:26:56 +0000435 confFile = sys::Path::GetUserHomeDirectory();
436 if (!confFile.is_empty()) {
437 confFile.append_directory(".llvm");
438 confFile.append_directory("etc");
439 confFile.append_file(ftype);
440 if (!confFile.readable())
441 confFile.clear();
442 }
443 if (!confFile.is_empty()) {
444 // Okay, try the LLVM installation directory
445 confFile = sys::Path::GetLLVMConfigDir();
446 confFile.append_file(ftype);
447 if (!confFile.readable()) {
448 // Okay, try the "standard" place
449 confFile = sys::Path::GetLLVMDefaultConfigDir();
450 confFile.append_file(ftype);
451 if (!confFile.readable()) {
Reid Spencerca01f9b2004-08-30 06:29:06 +0000452 throw std::string("Configuration file for '") + ftype +
453 "' is not available.";
Reid Spencerb38e4052004-08-20 09:24:07 +0000454 }
455 }
456 }
Reid Spencer68fb37a2004-08-14 09:37:15 +0000457 }
458 } else {
Reid Spencer52c2dc12004-08-29 19:26:56 +0000459 confFile = configDir;
460 confFile.append_file(ftype);
461 if (!confFile.readable())
Reid Spencerca01f9b2004-08-30 06:29:06 +0000462 throw std::string("Configuration file for '") + ftype +
463 "' is not available.";
Reid Spencer2594c9a2004-08-13 20:21:22 +0000464 }
Reid Spencer52c2dc12004-08-29 19:26:56 +0000465 FileInputProvider fip( confFile.get() );
Reid Spencerb38e4052004-08-20 09:24:07 +0000466 if (!fip.okay()) {
Reid Spencerca01f9b2004-08-30 06:29:06 +0000467 throw std::string("Configuration file for '") + ftype +
468 "' is not available.";
Reid Spencerb38e4052004-08-20 09:24:07 +0000469 }
470 result = new CompilerDriver::ConfigData();
471 ParseConfigData(fip,*result);
Reid Spencer68fb37a2004-08-14 09:37:15 +0000472 return result;
Reid Spencer2594c9a2004-08-13 20:21:22 +0000473}
474
Reid Spencer2594c9a2004-08-13 20:21:22 +0000475LLVMC_ConfigDataProvider::~LLVMC_ConfigDataProvider()
476{
477 ConfigDataMap::iterator cIt = Configurations.begin();
478 while (cIt != Configurations.end()) {
479 CompilerDriver::ConfigData* cd = cIt->second;
480 ++cIt;
481 delete cd;
482 }
483 Configurations.clear();
484}
485
486CompilerDriver::ConfigData*
487LLVMC_ConfigDataProvider::ProvideConfigData(const std::string& filetype) {
488 CompilerDriver::ConfigData* result = 0;
489 if (!Configurations.empty()) {
490 ConfigDataMap::iterator cIt = Configurations.find(filetype);
491 if ( cIt != Configurations.end() ) {
492 // We found one in the case, return it.
493 result = cIt->second;
494 }
495 }
496 if (result == 0) {
497 // The configuration data doesn't exist, we have to go read it.
498 result = ReadConfigData(filetype);
499 // If we got one, cache it
Reid Spencer52c2dc12004-08-29 19:26:56 +0000500 if (result != 0)
Reid Spencer2594c9a2004-08-13 20:21:22 +0000501 Configurations.insert(std::make_pair(filetype,result));
502 }
503 return result; // Might return 0
504}
505
506// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab