blob: e22ae1e54f9ed40dc899997d586a3f7fca0bd4ad [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Stephen Hinese639eb52010-11-08 19:27:20 -080017#include <cstdlib>
18#include <list>
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070019#include <set>
20#include <string>
Stephen Hinese639eb52010-11-08 19:27:20 -080021#include <utility>
22#include <vector>
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070023
24#include "clang/Driver/Arg.h"
25#include "clang/Driver/ArgList.h"
26#include "clang/Driver/DriverDiagnostic.h"
27#include "clang/Driver/Option.h"
28#include "clang/Driver/OptTable.h"
29
30#include "clang/Frontend/DiagnosticOptions.h"
31#include "clang/Frontend/TextDiagnosticPrinter.h"
32
Stephen Hinese639eb52010-11-08 19:27:20 -080033#include "llvm/ADT/SmallVector.h"
Loganbe274822011-02-16 22:02:54 +080034#include "llvm/ADT/IntrusiveRefCntPtr.h"
35#include "llvm/ADT/OwningPtr.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080036
37#include "llvm/Support/CommandLine.h"
38#include "llvm/Support/ManagedStatic.h"
39#include "llvm/Support/MemoryBuffer.h"
Loganbe274822011-02-16 22:02:54 +080040#include "llvm/Support/Path.h"
41#include "llvm/Support/system_error.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080042
43#include "slang.h"
Stephen Hines6e6578a2011-02-07 18:05:48 -080044#include "slang_assert.h"
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070045#include "slang_rs.h"
46#include "slang_rs_reflect_utils.h"
47
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070048// Class under clang::driver used are enumerated here.
Stephen Hinese639eb52010-11-08 19:27:20 -080049using clang::driver::arg_iterator;
50using clang::driver::options::DriverOption;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070051using clang::driver::Arg;
52using clang::driver::ArgList;
53using clang::driver::InputArgList;
54using clang::driver::Option;
55using clang::driver::OptTable;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -070056
57// SaveStringInSet, ExpandArgsFromBuf and ExpandArgv are all copied from
58// $(CLANG_ROOT)/tools/driver/driver.cpp for processing argc/argv passed in
59// main().
60static inline const char *SaveStringInSet(std::set<std::string> &SavedStrings,
61 llvm::StringRef S) {
62 return SavedStrings.insert(S).first->c_str();
63}
64static void ExpandArgsFromBuf(const char *Arg,
65 llvm::SmallVectorImpl<const char*> &ArgVector,
66 std::set<std::string> &SavedStrings);
67static void ExpandArgv(int argc, const char **argv,
68 llvm::SmallVectorImpl<const char*> &ArgVector,
69 std::set<std::string> &SavedStrings);
70
71enum {
72 OPT_INVALID = 0, // This is not an option ID.
73#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
74 HELPTEXT, METAVAR) OPT_##ID,
75#include "RSCCOptions.inc"
76 LastOption
77#undef OPTION
78};
79
80static const OptTable::Info RSCCInfoTable[] = {
81#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
82 HELPTEXT, METAVAR) \
83 { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
84 OPT_##GROUP, OPT_##ALIAS },
85#include "RSCCOptions.inc"
86};
87
88class RSCCOptTable : public OptTable {
89 public:
90 RSCCOptTable()
91 : OptTable(RSCCInfoTable,
92 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {
93 }
94};
95
96OptTable *createRSCCOptTable() {
97 return new RSCCOptTable();
98}
99
100///////////////////////////////////////////////////////////////////////////////
101
102class RSCCOptions {
103 public:
104 // The include search paths
105 std::vector<std::string> mIncludePaths;
106
107 // The output directory, if any.
108 std::string mOutputDir;
109
110 // The output type
Stephen Hinese639eb52010-11-08 19:27:20 -0800111 slang::Slang::OutputType mOutputType;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700112
113 unsigned mAllowRSPrefix : 1;
114
115 // If given, the name of the target triple to compile for. If not given the
116 // target will be selected to match the host.
117 std::string mTriple;
118
119 // If given, the name of the target CPU to generate code for.
120 std::string mCPU;
121
122 // The list of target specific features to enable or disable -- this should
123 // be a list of strings starting with by '+' or '-'.
124 std::vector<std::string> mFeatures;
125
126 std::string mJavaReflectionPathBase;
127
128 std::string mJavaReflectionPackageName;
129
Stephen Hinese639eb52010-11-08 19:27:20 -0800130 slang::BitCodeStorageType mBitcodeStorage;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700131
132 unsigned mOutputDep : 1;
133
134 std::string mOutputDepDir;
135
136 std::vector<std::string> mAdditionalDepTargets;
137
138 unsigned mShowHelp : 1; // Show the -help text.
139 unsigned mShowVersion : 1; // Show the -version text.
140
141 RSCCOptions() {
Stephen Hinese639eb52010-11-08 19:27:20 -0800142 mOutputType = slang::Slang::OT_Bitcode;
143 mBitcodeStorage = slang::BCST_APK_RESOURCE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700144 mOutputDep = 0;
145 mShowHelp = 0;
146 mShowVersion = 0;
147 }
148};
149
150// ParseArguments -
151static void ParseArguments(llvm::SmallVectorImpl<const char*> &ArgVector,
152 llvm::SmallVectorImpl<const char*> &Inputs,
153 RSCCOptions &Opts,
154 clang::Diagnostic &Diags) {
155 if (ArgVector.size() > 1) {
156 const char **ArgBegin = ArgVector.data() + 1;
157 const char **ArgEnd = ArgVector.data() + ArgVector.size();
158 unsigned MissingArgIndex, MissingArgCount;
159 llvm::OwningPtr<OptTable> OptParser(createRSCCOptTable());
160 llvm::OwningPtr<InputArgList> Args(
161 OptParser->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
162
163 // Check for missing argument error.
164 if (MissingArgCount)
165 Diags.Report(clang::diag::err_drv_missing_argument)
166 << Args->getArgString(MissingArgIndex) << MissingArgCount;
167
168 // Issue errors on unknown arguments.
169 for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
170 ie = Args->filtered_end(); it != ie; ++it)
171 Diags.Report(clang::diag::err_drv_unknown_argument)
172 << (*it)->getAsString(*Args);
173
174 for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
175 it != ie; ++it) {
176 const Arg *A = *it;
177 if (A->getOption().getKind() == Option::InputClass)
178 Inputs.push_back(A->getValue(*Args));
179 }
180
181 Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
182
183 Opts.mOutputDir = Args->getLastArgValue(OPT_o);
184
185 if (const Arg *A = Args->getLastArg(OPT_M_Group)) {
186 switch (A->getOption().getID()) {
187 case OPT_M: {
188 Opts.mOutputDep = 1;
Stephen Hinese639eb52010-11-08 19:27:20 -0800189 Opts.mOutputType = slang::Slang::OT_Dependency;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700190 break;
191 }
192 case OPT_MD: {
193 Opts.mOutputDep = 1;
Stephen Hinese639eb52010-11-08 19:27:20 -0800194 Opts.mOutputType = slang::Slang::OT_Bitcode;
Patrick Scott190ac892010-10-21 14:47:31 -0400195 break;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700196 }
197 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800198 slangAssert(false && "Invalid option in M group!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700199 }
200 }
201 }
202
203 if (const Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
204 switch (A->getOption().getID()) {
205 case OPT_emit_asm: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800206 Opts.mOutputType = slang::Slang::OT_Assembly;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700207 break;
208 }
209 case OPT_emit_llvm: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800210 Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700211 break;
212 }
213 case OPT_emit_bc: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800214 Opts.mOutputType = slang::Slang::OT_Bitcode;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700215 break;
216 }
217 case OPT_emit_nothing: {
Stephen Hinese639eb52010-11-08 19:27:20 -0800218 Opts.mOutputType = slang::Slang::OT_Nothing;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700219 break;
220 }
221 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800222 slangAssert(false && "Invalid option in output type group!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700223 }
224 }
225 }
226
Zonr Change8c263a2010-10-12 00:35:29 +0800227 if (Opts.mOutputDep &&
Stephen Hinese639eb52010-11-08 19:27:20 -0800228 ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
229 (Opts.mOutputType != slang::Slang::OT_Dependency)))
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700230 Diags.Report(clang::diag::err_drv_argument_not_allowed_with)
231 << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
232 << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
233
234 Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
235
Shih-wei Liao603217c2010-10-11 00:00:52 -0700236 Opts.mTriple = Args->getLastArgValue(OPT_triple,
237 "armv7-none-linux-gnueabi");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700238 Opts.mCPU = Args->getLastArgValue(OPT_target_cpu);
239 Opts.mFeatures = Args->getAllArgValues(OPT_target_feature);
240
241 Opts.mJavaReflectionPathBase =
242 Args->getLastArgValue(OPT_java_reflection_path_base);
243 Opts.mJavaReflectionPackageName =
244 Args->getLastArgValue(OPT_java_reflection_package_name);
245
246 llvm::StringRef BitcodeStorageValue =
247 Args->getLastArgValue(OPT_bitcode_storage);
248 if (BitcodeStorageValue == "ar")
Stephen Hinese639eb52010-11-08 19:27:20 -0800249 Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700250 else if (BitcodeStorageValue == "jc")
Stephen Hinese639eb52010-11-08 19:27:20 -0800251 Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700252 else if (!BitcodeStorageValue.empty())
253 Diags.Report(clang::diag::err_drv_invalid_value)
254 << OptParser->getOptionName(OPT_bitcode_storage)
255 << BitcodeStorageValue;
256
257 Opts.mOutputDepDir =
258 Args->getLastArgValue(OPT_output_dep_dir, Opts.mOutputDir);
259 Opts.mAdditionalDepTargets =
260 Args->getAllArgValues(OPT_additional_dep_target);
261
262 Opts.mShowHelp = Args->hasArg(OPT_help);
263 Opts.mShowVersion = Args->hasArg(OPT_version);
264 }
265
266 return;
267}
268
269static const char *DetermineOutputFile(const std::string &OutputDir,
270 const char *InputFile,
Stephen Hinese639eb52010-11-08 19:27:20 -0800271 slang::Slang::OutputType OutputType,
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700272 std::set<std::string> &SavedStrings) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800273 if (OutputType == slang::Slang::OT_Nothing)
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700274 return "/dev/null";
275
276 std::string OutputFile(OutputDir);
277
278 // Append '/' to Opts.mOutputDir if not presents
279 if (!OutputFile.empty() &&
Raphael8d5a2f62011-02-08 00:15:05 -0800280 (OutputFile[OutputFile.size() - 1]) != OS_PATH_SEPARATOR)
281 OutputFile.append(1, OS_PATH_SEPARATOR);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700282
Stephen Hinese639eb52010-11-08 19:27:20 -0800283 if (OutputType == slang::Slang::OT_Dependency) {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700284 // The build system wants the .d file name stem to be exactly the same as
285 // the source .rs file, instead of the .bc file.
Stephen Hinese639eb52010-11-08 19:27:20 -0800286 OutputFile.append(slang::RSSlangReflectUtils::GetFileNameStem(InputFile));
287 } else {
288 OutputFile.append(
289 slang::RSSlangReflectUtils::BCFileNameFromRSFileName(InputFile));
290 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700291
Stephen Hinese639eb52010-11-08 19:27:20 -0800292 switch (OutputType) {
293 case slang::Slang::OT_Dependency: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700294 OutputFile.append(".d");
295 break;
296 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800297 case slang::Slang::OT_Assembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700298 OutputFile.append(".S");
299 break;
300 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800301 case slang::Slang::OT_LLVMAssembly: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700302 OutputFile.append(".ll");
303 break;
304 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800305 case slang::Slang::OT_Object: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700306 OutputFile.append(".o");
307 break;
308 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800309 case slang::Slang::OT_Bitcode: {
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700310 OutputFile.append(".bc");
311 break;
312 }
Stephen Hinese639eb52010-11-08 19:27:20 -0800313 case slang::Slang::OT_Nothing:
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700314 default: {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800315 slangAssert(false && "Invalid output type!");
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700316 }
317 }
318
319 return SaveStringInSet(SavedStrings, OutputFile);
320}
321
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700322int main(int argc, const char **argv) {
323 std::set<std::string> SavedStrings;
324 llvm::SmallVector<const char*, 256> ArgVector;
325 RSCCOptions Opts;
326 llvm::SmallVector<const char*, 16> Inputs;
327 std::string Argv0;
328
329 atexit(llvm::llvm_shutdown);
330
331 ExpandArgv(argc, argv, ArgVector, SavedStrings);
332
333 // Argv0
Logan Chien6f4e0a92011-03-10 01:10:25 +0800334 Argv0 = llvm::sys::path::stem(ArgVector[0]);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700335
336 // Setup diagnostic engine
337 clang::TextDiagnosticPrinter *DiagClient =
338 new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions());
339 DiagClient->setPrefix(Argv0);
Loganbe274822011-02-16 22:02:54 +0800340
341 llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
342 new clang::DiagnosticIDs());
343
344 clang::Diagnostic Diags(DiagIDs, DiagClient, true);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700345
Stephen Hinese639eb52010-11-08 19:27:20 -0800346 slang::Slang::GlobalInitialization();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700347
348 ParseArguments(ArgVector, Inputs, Opts, Diags);
349
350 // Exits when there's any error occurred during parsing the arguments
Loganbe274822011-02-16 22:02:54 +0800351 if (Diags.hasErrorOccurred())
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700352 return 1;
353
354 if (Opts.mShowHelp) {
355 llvm::OwningPtr<OptTable> OptTbl(createRSCCOptTable());
356 OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
357 "RenderScript source compiler");
358 return 0;
359 }
360
361 if (Opts.mShowVersion) {
362 llvm::cl::PrintVersionMessage();
363 return 0;
364 }
365
366 // No input file
367 if (Inputs.empty()) {
368 Diags.Report(clang::diag::err_drv_no_input_files);
369 return 1;
370 }
371
Zonr Changcf6af6a2010-10-12 12:38:51 +0800372 // Prepare input data for RS compiler.
373 std::list<std::pair<const char*, const char*> > IOFiles;
374 std::list<std::pair<const char*, const char*> > DepFiles;
375
Stephen Hinese639eb52010-11-08 19:27:20 -0800376 llvm::OwningPtr<slang::SlangRS> Compiler(new slang::SlangRS());
Zonr Chang641558f2010-10-12 21:07:06 +0800377
378 Compiler->init(Opts.mTriple, Opts.mCPU, Opts.mFeatures);
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700379
380 for (int i = 0, e = Inputs.size(); i != e; i++) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800381 const char *InputFile = Inputs[i];
382 const char *OutputFile =
383 DetermineOutputFile(Opts.mOutputDir, InputFile,
384 Opts.mOutputType, SavedStrings);
385
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700386 if (Opts.mOutputDep) {
Zonr Changcf6af6a2010-10-12 12:38:51 +0800387 const char *BCOutputFile, *DepOutputFile;
Zonr Change8c263a2010-10-12 00:35:29 +0800388
Stephen Hinese639eb52010-11-08 19:27:20 -0800389 if (Opts.mOutputType == slang::Slang::OT_Bitcode)
Zonr Change8c263a2010-10-12 00:35:29 +0800390 BCOutputFile = OutputFile;
391 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800392 BCOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
393 InputFile,
394 slang::Slang::OT_Bitcode,
395 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800396
Stephen Hinese639eb52010-11-08 19:27:20 -0800397 if (Opts.mOutputType == slang::Slang::OT_Dependency)
Zonr Changcf6af6a2010-10-12 12:38:51 +0800398 DepOutputFile = OutputFile;
399 else
Stephen Hinese639eb52010-11-08 19:27:20 -0800400 DepOutputFile = DetermineOutputFile(Opts.mOutputDepDir,
401 InputFile,
402 slang::Slang::OT_Dependency,
403 SavedStrings);
Zonr Changcf6af6a2010-10-12 12:38:51 +0800404
405 DepFiles.push_back(std::make_pair(BCOutputFile, DepOutputFile));
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700406 }
Zonr Changcf6af6a2010-10-12 12:38:51 +0800407
408 IOFiles.push_back(std::make_pair(InputFile, OutputFile));
409 }
410
411 // Let's rock!
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800412 int CompileFailed = !Compiler->compile(IOFiles,
413 DepFiles,
414 Opts.mIncludePaths,
415 Opts.mAdditionalDepTargets,
416 Opts.mOutputType,
417 Opts.mBitcodeStorage,
418 Opts.mAllowRSPrefix,
419 Opts.mOutputDep,
420 Opts.mJavaReflectionPathBase,
421 Opts.mJavaReflectionPackageName);
422 llvm::errs() << Compiler->getErrorMessage();
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700423
Stephen Hinesd7f0ea22011-02-22 17:45:19 -0800424 return CompileFailed;
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700425}
426
427///////////////////////////////////////////////////////////////////////////////
428
429// ExpandArgsFromBuf -
430static void ExpandArgsFromBuf(const char *Arg,
431 llvm::SmallVectorImpl<const char*> &ArgVector,
432 std::set<std::string> &SavedStrings) {
433 const char *FName = Arg + 1;
Loganbe274822011-02-16 22:02:54 +0800434 llvm::OwningPtr<llvm::MemoryBuffer> MemBuf;
435 if (llvm::MemoryBuffer::getFile(FName, MemBuf)) {
436 // Unable to open the file
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700437 ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
438 return;
439 }
440
441 const char *Buf = MemBuf->getBufferStart();
442 char InQuote = ' ';
443 std::string CurArg;
444
445 for (const char *P = Buf; ; ++P) {
446 if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
447 if (!CurArg.empty()) {
448 if (CurArg[0] != '@') {
449 ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
450 } else {
451 ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
452 }
453
454 CurArg = "";
455 }
456 if (*P == '\0')
457 break;
458 else
459 continue;
460 }
461
462 if (isspace(*P)) {
463 if (InQuote != ' ')
464 CurArg.push_back(*P);
465 continue;
466 }
467
468 if (*P == '"' || *P == '\'') {
469 if (InQuote == *P)
470 InQuote = ' ';
471 else if (InQuote == ' ')
472 InQuote = *P;
473 else
474 CurArg.push_back(*P);
475 continue;
476 }
477
478 if (*P == '\\') {
479 ++P;
480 if (*P != '\0')
481 CurArg.push_back(*P);
482 continue;
483 }
484 CurArg.push_back(*P);
485 }
Shih-wei Liaob81c6a42010-10-10 14:15:00 -0700486}
487
488// ExpandArgsFromBuf -
489static void ExpandArgv(int argc, const char **argv,
490 llvm::SmallVectorImpl<const char*> &ArgVector,
491 std::set<std::string> &SavedStrings) {
492 for (int i = 0; i < argc; ++i) {
493 const char *Arg = argv[i];
494 if (Arg[0] != '@') {
495 ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
496 continue;
497 }
498
499 ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
500 }
501}