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 #include <stdio.h>
21 #include <string.h>
22 
23 #include "cppuoptions.hxx"
24 #include <osl/thread.h>
25 #include <osl/process.h>
26 
27 #ifdef SAL_UNX
28 #define SEPARATOR '/'
29 #else
30 #define SEPARATOR '\\'
31 #endif
32 
initOptions(int ac,char * av[],bool bCmdFile)33 bool CppuOptions::initOptions(int ac, char* av[], bool bCmdFile)
34 {
35     bool    ret = true;
36     int i=0;
37 
38     if (!bCmdFile)
39     {
40         bCmdFile = true;
41 
42         OString name(av[0]);
43         sal_Int32 index = name.lastIndexOf(SEPARATOR);
44         m_program = name.copy(index > 0 ? index+1 : 0);
45 
46         if (ac < 2)
47         {
48             fprintf(stderr, "%s", prepareHelp().getStr());
49             ret = false;
50         }
51 
52         i = 1;
53     }
54     else
55     {
56         i = 0;
57     }
58 
59     char    *s=nullptr;
60     for( ; i < ac; i++)
61     {
62         if (av[i][0] == '-')
63         {
64             switch (av[i][1])
65             {
66                 case 'O':
67                     if (av[i][2] == '\0')
68                     {
69                         if (i < ac - 1 && av[i+1][0] != '-')
70                         {
71                             i++;
72                             s = av[i];
73                         }
74                         else
75                         {
76                             OString tmp("'-O', please check");
77                             if (i <= ac - 1)
78                             {
79                                 tmp += OStringLiteral(" your input '") + av[i+1] + "'";
80                             }
81 
82                             throw IllegalArgument(tmp);
83                         }
84                     }
85                     else
86                     {
87                         s = av[i] + 2;
88                     }
89 
90                     m_options["-O"] = OString(s);
91                     break;
92                 case 'n':
93                     if (av[i][2] != 'D' || av[i][3] != '\0')
94                     {
95                         OString tmp = OStringLiteral("'-nD', please check your input '") + av[i] + "'";
96                         throw IllegalArgument(tmp);
97                     }
98 
99                     m_options["-nD"] = OString();
100                     break;
101                 case 'T':
102                     if (av[i][2] == '\0')
103                     {
104                         if (i < ac - 1 && av[i+1][0] != '-')
105                         {
106                             i++;
107                             s = av[i];
108                         }
109                         else
110                         {
111                             OString tmp("'-T', please check");
112                             if (i <= ac - 1)
113                             {
114                                 tmp += OStringLiteral(" your input '") + av[i+1] + "'";
115                             }
116 
117                             throw IllegalArgument(tmp);
118                         }
119                     }
120                     else
121                     {
122                         s = av[i] + 2;
123                     }
124 
125                     if (m_options.count("-T") > 0)
126                     {
127                         OString tmp = m_options["-T"] + ";" + s;
128                         m_options["-T"] = tmp;
129                     }
130                     else
131                     {
132                         m_options["-T"] = OString(s);
133                     }
134                     break;
135                 case 'L':
136                     if (av[i][2] != '\0')
137                     {
138                         OString tmp("'-L', please check");
139                         if (i <= ac - 1)
140                         {
141                             tmp += OStringLiteral(" your input '") + av[i] + "'";
142                         }
143 
144                         throw IllegalArgument(tmp);
145                     }
146 
147                     if (isValid("-C") || isValid("-CS"))
148                     {
149                         throw IllegalArgument("'-L' could not be combined with '-C' or '-CS' option");
150                     }
151                     m_options["-L"] = OString();
152                     break;
153                 case 'C':
154                     if (av[i][2] == 'S')
155                     {
156                         if (av[i][3] != '\0')
157                         {
158                             OString tmp("'-CS', please check");
159                             if (i <= ac - 1)
160                             {
161                                 tmp += OStringLiteral(" your input '") + av[i] + "'";
162                             }
163 
164                             throw IllegalArgument(tmp);
165                         }
166 
167                         if (isValid("-L") || isValid("-C"))
168                         {
169                             throw IllegalArgument("'-CS' could not be combined with '-L' or '-C' option");
170                         }
171                         m_options["-CS"] = OString();
172                         break;
173                     }
174                     else if (av[i][2] != '\0')
175                     {
176                         OString tmp("'-C', please check");
177                         if (i <= ac - 1)
178                         {
179                             tmp += OStringLiteral(" your input '") + av[i] + "'";
180                         }
181 
182                         throw IllegalArgument(tmp);
183                     }
184 
185                     if (isValid("-L") || isValid("-CS"))
186                     {
187                         throw IllegalArgument("'-C' could not be combined with '-L' or '-CS' option");
188                     }
189                     m_options["-C"] = OString();
190                     break;
191                 case 'G':
192                     if (av[i][2] == 'c')
193                     {
194                         if (av[i][3] != '\0')
195                         {
196                             OString tmp("'-Gc', please check");
197                             if (i <= ac - 1)
198                             {
199                                 tmp += OStringLiteral(" your input '") + av[i] + "'";
200                             }
201 
202                             throw IllegalArgument(tmp);
203                         }
204 
205                         m_options["-Gc"] = OString();
206                         break;
207                     }
208                     else if (av[i][2] != '\0')
209                     {
210                         OString tmp("'-G', please check");
211                         if (i <= ac - 1)
212                         {
213                             tmp += OStringLiteral(" your input '") + av[i] + "'";
214                         }
215 
216                         throw IllegalArgument(tmp);
217                     }
218 
219                     m_options["-G"] = OString();
220                     break;
221                 case 'X': // support for eXtra type rdbs
222                 {
223                     if (av[i][2] == '\0')
224                     {
225                         if (i < ac - 1 && av[i+1][0] != '-')
226                         {
227                             i++;
228                             s = av[i];
229                         }
230                         else
231                         {
232                             OString tmp("'-X', please check");
233                             if (i <= ac - 1)
234                             {
235                                 tmp += OStringLiteral(" your input '") + av[i+1] + "'";
236                             }
237 
238                             throw IllegalArgument(tmp);
239                         }
240                     }
241                     else
242                     {
243                         s = av[i] + 2;
244                     }
245 
246                     m_extra_input_files.emplace_back(s );
247                     break;
248                 }
249 
250                 default:
251                     throw IllegalArgument(OStringLiteral("the option is unknown") + av[i]);
252             }
253         } else
254         {
255             if (av[i][0] == '@')
256             {
257                 FILE* cmdFile = fopen(av[i]+1, "r");
258                 if( cmdFile == nullptr )
259                 {
260                     fprintf(stderr, "%s", prepareHelp().getStr());
261                     ret = false;
262                 }
263                 else
264                 {
265                     int rargc=0;
266                     char* rargv[512];
267                     char  buffer[512];
268 
269                     while (fscanf(cmdFile, "%511s", buffer) != EOF && rargc < 512)
270                     {
271                         rargv[rargc]= strdup(buffer);
272                         rargc++;
273                     }
274                     fclose(cmdFile);
275 
276                     ret = initOptions(rargc, rargv, bCmdFile);
277 
278                     for (int j=0; j < rargc; j++)
279                     {
280                         free(rargv[j]);
281                     }
282                 }
283             }
284             else
285             {
286                 m_inputFiles.emplace_back(av[i]);
287             }
288         }
289     }
290 
291     return ret;
292 }
293 
prepareHelp()294 OString CppuOptions::prepareHelp()
295 {
296     OString help = "\nusing: " +
297         m_program + " [-options] file_1 ... file_n\nOptions:\n"
298         "    -O<path>   = path describes the root directory for the generated output.\n"
299         "                 The output directory tree is generated under this directory.\n"
300         "    -T<name>   = name specifies a type or a list of types. The output for this\n"
301         "      [t1;...]   type is generated. If no '-T' option is specified,\n"
302         "                 then output for all types is generated.\n"
303         "                 Example: 'com.sun.star.uno.XInterface' is a valid type.\n"
304         "    -L         = UNO type functions are generated lightweight, that means only\n"
305         "                 the name and typeclass are given and everything else is retrieved\n"
306         "                 from the type library dynamically. The default is that UNO type\n"
307         "                 functions provides enough type information for bootstrapping C++.\n"
308         "                 '-L' should be the default for external components.\n"
309         "    -C         = UNO type functions are generated comprehensive that means all\n"
310         "                 necessary information is available for bridging the type in UNO.\n"
311         "    -nD        = no dependent types are generated.\n"
312         "    -G         = generate only target files which does not exists.\n"
313         "    -Gc        = generate only target files which content will be changed.\n"
314         "    -X<file>   = extra types which will not be taken into account for generation.\n\n" +
315         prepareVersion();
316 
317     return help;
318 }
319 
prepareVersion() const320 OString CppuOptions::prepareVersion() const
321 {
322     OString version = m_program + " Version 2.0\n\n";
323     return version;
324 }
325 
326 
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
328