Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "idlc/options.hxx"
22 :
23 : #include "osl/diagnose.h"
24 : #include "rtl/string.hxx"
25 : #include "rtl/strbuf.hxx"
26 :
27 : #include <stdio.h>
28 : #include <string.h>
29 :
30 : using ::rtl::OString;
31 : using ::rtl::OStringBuffer;
32 : #ifdef SAL_UNX
33 : #define SEPARATOR '/'
34 : #else
35 : #define SEPARATOR '\\'
36 : #endif
37 :
38 138 : Options::Options(char const * progname)
39 138 : : m_program(progname), m_stdin(false), m_verbose(false), m_quiet(false)
40 : {
41 138 : }
42 :
43 138 : Options::~Options()
44 : {
45 138 : }
46 :
47 : // static
48 6284 : bool Options::checkArgument (std::vector< std::string > & rArgs, char const * arg, size_t len)
49 : {
50 6284 : bool result = ((arg != 0) && (len > 0));
51 : OSL_PRECOND(result, "idlc::Options::checkArgument(): invalid arguments");
52 6284 : if (result)
53 : {
54 6284 : switch(arg[0])
55 : {
56 : case '@':
57 138 : if ((result = (len > 1)) == true)
58 : {
59 : // "@<cmdfile>"
60 138 : result = Options::checkCommandFile (rArgs, &(arg[1]));
61 : }
62 138 : break;
63 : case '-':
64 685 : if ((result = (len > 1)) == true)
65 : {
66 : // "-<option>"
67 685 : switch (arg[1])
68 : {
69 : case 'O':
70 : case 'M':
71 : case 'I':
72 : case 'D':
73 : {
74 : // "-<option>[<param>]
75 547 : std::string option(&(arg[0]), 2);
76 547 : rArgs.push_back(option);
77 547 : if (len > 2)
78 : {
79 : // "-<option><param>"
80 271 : std::string param(&(arg[2]), len - 2);
81 271 : rArgs.push_back(param);
82 : }
83 547 : break;
84 : }
85 : default:
86 : // "-<option>" ([long] option, w/o param)
87 138 : rArgs.push_back(std::string(arg, len));
88 138 : break;
89 : }
90 : }
91 685 : break;
92 : default:
93 : // "<param>"
94 5461 : rArgs.push_back(std::string(arg, len));
95 5461 : break;
96 : }
97 : }
98 6284 : return (result);
99 : }
100 :
101 : // static
102 138 : bool Options::checkCommandFile (std::vector< std::string > & rArgs, char const * filename)
103 : {
104 138 : FILE * fp = fopen(filename, "r");
105 138 : if (fp == 0)
106 : {
107 0 : fprintf(stderr, "ERROR: can't open command file \"%s\"\n", filename);
108 0 : return (false);
109 : }
110 :
111 138 : std::string buffer;
112 138 : buffer.reserve(256);
113 :
114 138 : bool quoted = false;
115 138 : int c = EOF;
116 388854 : while ((c = fgetc(fp)) != EOF)
117 : {
118 388578 : switch(c)
119 : {
120 : case '\"':
121 0 : quoted = !quoted;
122 0 : break;
123 : case ' ':
124 : case '\t':
125 : case '\r':
126 : case '\n':
127 5461 : if (!quoted)
128 : {
129 5461 : if (!buffer.empty())
130 : {
131 : // append current argument.
132 5185 : if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size()))
133 : {
134 0 : (void) fclose(fp);
135 0 : return (false);
136 : }
137 5185 : buffer.clear();
138 : }
139 5461 : break;
140 : }
141 : default:
142 : // quoted white-space fall through
143 383117 : buffer.push_back(sal::static_int_cast<char>(c));
144 383117 : break;
145 : }
146 : }
147 138 : if (!buffer.empty())
148 : {
149 : // append unterminated argument.
150 0 : if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size()))
151 : {
152 0 : (void) fclose(fp);
153 0 : return (false);
154 : }
155 0 : buffer.clear();
156 : }
157 138 : return (fclose(fp) == 0);
158 : }
159 :
160 0 : bool Options::badOption(char const * reason, std::string const & rArg) throw(IllegalArgument)
161 : {
162 0 : OStringBuffer message;
163 0 : if (reason != 0)
164 : {
165 0 : message.append(reason); message.append(" option '"); message.append(rArg.c_str()); message.append("'");
166 0 : throw IllegalArgument(message.makeStringAndClear());
167 : }
168 0 : return false;
169 : }
170 :
171 138 : bool Options::setOption(char const * option, std::string const & rArg)
172 : {
173 138 : bool result = (0 == strcmp(option, rArg.c_str()));
174 138 : if (result)
175 138 : m_options[rArg.c_str()] = OString(rArg.c_str(), rArg.size());
176 138 : return (result);
177 : }
178 :
179 138 : bool Options::initOptions(std::vector< std::string > & rArgs) throw(IllegalArgument)
180 : {
181 138 : std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end();
182 6008 : for (; first != last; ++first)
183 : {
184 5870 : if ((*first)[0] != '-')
185 : {
186 5185 : OString filename((*first).c_str(), (*first).size());
187 5185 : OString tmp(filename.toAsciiLowerCase());
188 5185 : if (tmp.lastIndexOf(".idl") != (tmp.getLength() - 4))
189 : {
190 0 : throw IllegalArgument("'" + filename + "' is not a valid input file, only '*.idl' files will be accepted");
191 : }
192 5185 : m_inputFiles.push_back(filename);
193 5185 : continue;
194 : }
195 :
196 685 : std::string const option(*first);
197 685 : switch((*first)[1])
198 : {
199 : case 'O':
200 : {
201 138 : if (!((++first != last) && ((*first)[0] != '-')))
202 : {
203 0 : return badOption("invalid", option);
204 : }
205 138 : OString param((*first).c_str(), (*first).size());
206 138 : m_options["-O"] = param;
207 138 : break;
208 : }
209 : case 'M':
210 : {
211 138 : if (!((++first != last) && ((*first)[0] != '-')))
212 : {
213 0 : return badOption("invalid", option);
214 : }
215 138 : OString param((*first).c_str(), (*first).size());
216 138 : m_options["-M"] = param;
217 138 : break;
218 : }
219 : case 'I':
220 : {
221 271 : if (!((++first != last) && ((*first)[0] != '-')))
222 : {
223 0 : return badOption("invalid", option);
224 : }
225 271 : OString param((*first).c_str(), (*first).size());
226 : {
227 : // quote param token(s).
228 271 : OStringBuffer buffer;
229 271 : sal_Int32 k = 0;
230 271 : do
231 : {
232 271 : if (buffer.getLength() > 0)
233 0 : buffer.append(' ');
234 : // buffer.append("-I\"");
235 271 : buffer.append(param.getToken(0, ';', k));
236 : // buffer.append("\"");
237 : } while (k != -1);
238 271 : param = buffer.makeStringAndClear();
239 : }
240 271 : if (m_options.count("-I") > 0)
241 : {
242 : // append param.
243 133 : OStringBuffer buffer(m_options["-I"]);
244 133 : buffer.append(' '); buffer.append(param);
245 133 : param = buffer.makeStringAndClear();
246 : }
247 271 : m_options["-I"] = param;
248 271 : break;
249 : }
250 : case 'D':
251 : {
252 0 : if (!((++first != last) && ((*first)[0] != '-')))
253 : {
254 0 : return badOption("invalid", option);
255 : }
256 0 : OString param("-D"); param += OString((*first).c_str(), (*first).size());
257 0 : if (m_options.count("-D") > 0)
258 : {
259 0 : OStringBuffer buffer(m_options["-D"]);
260 0 : buffer.append(' '); buffer.append(param);
261 0 : param = buffer.makeStringAndClear();
262 : }
263 0 : m_options["-D"] = param;
264 0 : break;
265 : }
266 : case 'C':
267 : {
268 0 : if (!setOption("-C", option))
269 : {
270 0 : return badOption("invalid", option);
271 : }
272 0 : break;
273 : }
274 : case 'c':
275 : {
276 0 : if (!setOption("-cid", option))
277 : {
278 0 : return badOption("invalid", option);
279 : }
280 0 : break;
281 : }
282 : case 'q':
283 : {
284 0 : if (!setOption("-quiet", option))
285 : {
286 0 : return badOption("invalid", option);
287 : }
288 0 : m_quiet = true;
289 0 : break;
290 : }
291 : case 'v':
292 : {
293 138 : if (!setOption("-verbose", option))
294 : {
295 0 : return badOption("invalid", option);
296 : }
297 138 : m_verbose = true;
298 138 : break;
299 : }
300 : case 'w':
301 : {
302 0 : if (!(setOption("-w", option) || setOption("-we", option)))
303 : {
304 0 : return badOption("invalid", option);
305 : }
306 0 : break;
307 : }
308 : case 'h':
309 : case '?':
310 : {
311 0 : if (!(setOption("-h", option) || setOption("-?", option)))
312 : {
313 0 : return badOption("invalid", option);
314 : }
315 : {
316 0 : (void) fprintf(stdout, "%s", prepareHelp().getStr());
317 0 : return (false);
318 : }
319 : // break; // Unreachable
320 : }
321 : case 's':
322 : {
323 0 : if (!setOption("-stdin", option))
324 : {
325 0 : return badOption("invalid", option);
326 : }
327 0 : m_stdin = true;
328 0 : break;
329 : }
330 : default:
331 0 : return badOption("unknown", option);
332 : }
333 685 : }
334 138 : return (true);
335 : }
336 :
337 0 : OString Options::prepareHelp()
338 : {
339 0 : OString help("\nusing: ");
340 0 : help += m_program + " [-options] <file_1> ... <file_n> | @<filename> | -stdin\n";
341 0 : help += " <file_n> = file_n specifies one or more idl files.\n";
342 0 : help += " Only files with the extension '.idl' are valid.\n";
343 0 : help += " @<filename> = filename specifies the name of a command file.\n";
344 0 : help += " -stdin = read idl file from standard input.\n";
345 0 : help += " Options:\n";
346 0 : help += " -O<path> = path specifies the output directory.\n";
347 0 : help += " The generated output is a registry file with\n";
348 0 : help += " the same name as the idl input file (or 'stdin'\n";
349 0 : help += " for -stdin).\n";
350 0 : help += " -M<path> = path specifies the output directory for deps.\n";
351 0 : help += " Generate GNU make dependency files with the\n";
352 0 : help += " same name as the idl input file.\n";
353 0 : help += " -I<path> = path specifies a directory where include\n";
354 0 : help += " files will be searched by the preprocessor.\n";
355 0 : help += " Multiple directories can be combined with ';'.\n";
356 0 : help += " -D<name> = name defines a macro for the preprocessor.\n";
357 0 : help += " -C = generate complete type information, including\n";
358 0 : help += " documentation.\n";
359 0 : help += " -cid = check if identifiers fulfill the UNO naming\n";
360 0 : help += " requirements.\n";
361 0 : help += " -quiet = no output.\n";
362 0 : help += " -verbose = verbose output.\n";
363 0 : help += " -w = display warning messages.\n";
364 0 : help += " -we = treat warnings as errors.\n";
365 0 : help += " -h|-? = print this help message and exit.\n\n";
366 0 : help += prepareVersion();
367 :
368 0 : return help;
369 : }
370 :
371 138 : OString Options::prepareVersion()
372 : {
373 138 : OString version(m_program);
374 138 : version += " Version 1.1\n\n";
375 138 : return version;
376 : }
377 :
378 341 : const OString& Options::getProgramName() const
379 : {
380 341 : return m_program;
381 : }
382 :
383 48045 : bool Options::isValid(const OString& option)
384 : {
385 48045 : return (m_options.count(option) > 0);
386 : }
387 :
388 15555 : const OString& Options::getOption(const OString& option)
389 : throw( IllegalArgument )
390 : {
391 15555 : if (!isValid(option))
392 : {
393 0 : throw IllegalArgument("Option is not valid or currently not set.");
394 : }
395 15555 : return m_options[option];
396 : }
397 :
398 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|