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