Branch data 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 : 166 : Options::Options(char const * progname)
39 [ + - ][ + - ]: 166 : : m_program(progname), m_stdin(false), m_verbose(false), m_quiet(false)
40 : : {
41 : 166 : }
42 : :
43 [ + - ]: 166 : Options::~Options()
44 : : {
45 : 166 : }
46 : :
47 : : // static
48 : 7298 : bool Options::checkArgument (std::vector< std::string > & rArgs, char const * arg, size_t len)
49 : : {
50 [ + - ][ + - ]: 7298 : bool result = ((arg != 0) && (len > 0));
51 : : OSL_PRECOND(result, "idlc::Options::checkArgument(): invalid arguments");
52 [ + - ]: 7298 : if (result)
53 : : {
54 [ + + + ]: 7298 : switch(arg[0])
55 : : {
56 : : case '@':
57 [ + - ]: 165 : if ((result = (len > 1)) == true)
58 : : {
59 : : // "@<cmdfile>"
60 : 165 : result = Options::checkCommandFile (rArgs, &(arg[1]));
61 : : }
62 : 165 : break;
63 : : case '-':
64 [ + - ]: 825 : if ((result = (len > 1)) == true)
65 : : {
66 : : // "-<option>"
67 [ + + ]: 825 : switch (arg[1])
68 : : {
69 : : case 'O':
70 : : case 'M':
71 : : case 'I':
72 : : case 'D':
73 : : {
74 : : // "-<option>[<param>]
75 [ + - ]: 658 : std::string option(&(arg[0]), 2);
76 [ + - ]: 658 : rArgs.push_back(option);
77 [ + + ]: 658 : if (len > 2)
78 : : {
79 : : // "-<option><param>"
80 [ + - ]: 328 : std::string param(&(arg[2]), len - 2);
81 [ + - ]: 328 : rArgs.push_back(param);
82 : : }
83 : 658 : break;
84 : : }
85 : : default:
86 : : // "-<option>" ([long] option, w/o param)
87 [ + - ][ + - ]: 167 : rArgs.push_back(std::string(arg, len));
88 : 825 : break;
89 : : }
90 : : }
91 : 825 : break;
92 : : default:
93 : : // "<param>"
94 [ + - ][ + - ]: 6308 : rArgs.push_back(std::string(arg, len));
95 : 7298 : break;
96 : : }
97 : : }
98 : 7298 : return (result);
99 : : }
100 : :
101 : : // static
102 : 165 : bool Options::checkCommandFile (std::vector< std::string > & rArgs, char const * filename)
103 : : {
104 [ + - ]: 165 : FILE * fp = fopen(filename, "r");
105 [ - + ]: 165 : if (fp == 0)
106 : : {
107 [ # # ]: 0 : fprintf(stderr, "ERROR: can't open command file \"%s\"\n", filename);
108 : 0 : return (false);
109 : : }
110 : :
111 [ + - ]: 165 : std::string buffer;
112 [ + - ]: 165 : buffer.reserve(256);
113 : :
114 : 165 : bool quoted = false;
115 : 165 : int c = EOF;
116 [ + - ][ + + ]: 498506 : while ((c = fgetc(fp)) != EOF)
117 : : {
118 [ - + + ]: 498341 : switch(c)
119 : : {
120 : : case '\"':
121 : 0 : quoted = !quoted;
122 : 0 : break;
123 : : case ' ':
124 : : case '\t':
125 : : case '\r':
126 : : case '\n':
127 [ + - ]: 7452 : if (!quoted)
128 : : {
129 [ + + ]: 7452 : if (!buffer.empty())
130 : : {
131 : : // append current argument.
132 [ + - ][ - + ]: 7128 : if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size()))
133 : : {
134 [ # # ]: 0 : (void) fclose(fp);
135 : 0 : return (false);
136 : : }
137 : 7128 : buffer.clear();
138 : : }
139 : 7452 : break;
140 : : }
141 : : default:
142 : : // quoted white-space fall through
143 [ + - ]: 490889 : buffer.push_back(sal::static_int_cast<char>(c));
144 : 490889 : break;
145 : : }
146 : : }
147 [ - + ]: 165 : 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 [ + - ]: 165 : 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 : 168 : bool Options::setOption(char const * option, std::string const & rArg)
172 : : {
173 : 168 : bool result = (0 == strcmp(option, rArg.c_str()));
174 [ + + ]: 168 : if (result)
175 [ + - ]: 167 : m_options[rArg.c_str()] = OString(rArg.c_str(), rArg.size());
176 : 168 : return (result);
177 : : }
178 : :
179 : 166 : bool Options::initOptions(std::vector< std::string > & rArgs) throw(IllegalArgument)
180 : : {
181 [ + - ][ + - ]: 166 : std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end();
182 [ + - ][ + - ]: 6969 : for (; first != last; ++first)
[ + + ]
183 : : {
184 [ + - ][ + - ]: 6803 : if ((*first)[0] != '-')
[ + + ]
185 : : {
186 [ + - ][ + - ]: 5978 : OString filename((*first).c_str(), (*first).size());
187 : 5978 : OString tmp(filename.toAsciiLowerCase());
188 [ - + ]: 5978 : 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 [ + - ]: 5978 : m_inputFiles.push_back(filename);
193 : 5978 : continue;
194 : : }
195 : :
196 [ + - ][ + - ]: 825 : std::string const option(*first);
197 [ + - ][ + - ]: 825 : switch((*first)[1])
[ + + + -
- + - + +
- - - ]
198 : : {
199 : : case 'O':
200 : : {
201 [ + - ][ + - ]: 166 : if (!((++first != last) && ((*first)[0] != '-')))
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
202 : : {
203 [ # # ]: 0 : return badOption("invalid", option);
204 : : }
205 [ + - ][ + - ]: 166 : OString param((*first).c_str(), (*first).size());
206 [ + - ]: 166 : m_options["-O"] = param;
207 : 166 : break;
208 : : }
209 : : case 'M':
210 : : {
211 [ + - ][ + - ]: 165 : if (!((++first != last) && ((*first)[0] != '-')))
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
212 : : {
213 [ # # ]: 0 : return badOption("invalid", option);
214 : : }
215 [ + - ][ + - ]: 165 : OString param((*first).c_str(), (*first).size());
216 [ + - ]: 165 : m_options["-M"] = param;
217 : 165 : break;
218 : : }
219 : : case 'I':
220 : : {
221 [ + - ][ + - ]: 327 : if (!((++first != last) && ((*first)[0] != '-')))
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
222 : : {
223 [ # # ]: 0 : return badOption("invalid", option);
224 : : }
225 [ + - ][ + - ]: 327 : OString param((*first).c_str(), (*first).size());
226 : : {
227 : : // quote param token(s).
228 : 327 : OStringBuffer buffer;
229 : 327 : sal_Int32 k = 0;
230 [ - + ]: 327 : do
231 : : {
232 [ - + ]: 327 : if (buffer.getLength() > 0)
233 [ # # ]: 0 : buffer.append(' ');
234 : : // buffer.append("-I\"");
235 [ + - ]: 327 : buffer.append(param.getToken(0, ';', k));
236 : : // buffer.append("\"");
237 : : } while (k != -1);
238 : 327 : param = buffer.makeStringAndClear();
239 : : }
240 [ + + ][ + - ]: 327 : if (m_options.count("-I") > 0)
241 : : {
242 : : // append param.
243 [ + - ][ + - ]: 161 : OStringBuffer buffer(m_options["-I"]);
244 [ + - ][ + - ]: 161 : buffer.append(' '); buffer.append(param);
245 : 161 : param = buffer.makeStringAndClear();
246 : : }
247 [ + - ]: 327 : m_options["-I"] = param;
248 : 327 : 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 [ + - ][ - + ]: 1 : if (!setOption("-cid", option))
277 : : {
278 [ # # ]: 0 : return badOption("invalid", option);
279 : : }
280 : 1 : 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 [ + - ][ - + ]: 165 : if (!setOption("-verbose", option))
294 : : {
295 [ # # ]: 0 : return badOption("invalid", option);
296 : : }
297 : 165 : m_verbose = true;
298 : 165 : break;
299 : : }
300 : : case 'w':
301 : : {
302 [ + - ][ + - ]: 1 : if (!(setOption("-w", option) || setOption("-we", option)))
[ + - ][ - + ]
[ - + ]
303 : : {
304 [ # # ]: 0 : return badOption("invalid", option);
305 : : }
306 : 1 : 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 [ # # ]: 825 : return badOption("unknown", option);
332 : : }
333 [ + - ]: 825 : }
334 : 166 : 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 : 165 : OString Options::prepareVersion()
372 : : {
373 : 165 : OString version(m_program);
374 : 165 : version += " Version 1.1\n\n";
375 : 165 : return version;
376 : : }
377 : :
378 : 406 : const OString& Options::getProgramName() const
379 : : {
380 : 406 : return m_program;
381 : : }
382 : :
383 : 56419 : bool Options::isValid(const OString& option)
384 : : {
385 : 56419 : return (m_options.count(option) > 0);
386 : : }
387 : :
388 : 17933 : const OString& Options::getOption(const OString& option)
389 : : throw( IllegalArgument )
390 : : {
391 [ - + ]: 17933 : if (!isValid(option))
392 : : {
393 : 0 : throw IllegalArgument("Option is not valid or currently not set.");
394 : : }
395 : 17933 : return m_options[option];
396 : : }
397 : :
398 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|