1 | /* ***** BEGIN LICENSE BLOCK *****
|
---|
2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
---|
3 | *
|
---|
4 | * The contents of this file are subject to the Mozilla Public License Version
|
---|
5 | * 1.1 (the "License"); you may not use this file except in compliance with
|
---|
6 | * the License. You may obtain a copy of the License at
|
---|
7 | * http://www.mozilla.org/MPL/
|
---|
8 | *
|
---|
9 | * Software distributed under the License is distributed on an "AS IS" basis,
|
---|
10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
---|
11 | * for the specific language governing rights and limitations under the
|
---|
12 | * License.
|
---|
13 | *
|
---|
14 | * The Original Code is Java XPCOM Bindings.
|
---|
15 | *
|
---|
16 | * The Initial Developer of the Original Code is
|
---|
17 | * IBM Corporation.
|
---|
18 | * Portions created by the Initial Developer are Copyright (C) 2005
|
---|
19 | * IBM Corporation. All Rights Reserved.
|
---|
20 | *
|
---|
21 | * Contributor(s):
|
---|
22 | * Javier Pedemonte ([email protected])
|
---|
23 | *
|
---|
24 | * Alternatively, the contents of this file may be used under the terms of
|
---|
25 | * either the GNU General Public License Version 2 or later (the "GPL"), or
|
---|
26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
---|
27 | * in which case the provisions of the GPL or the LGPL are applicable instead
|
---|
28 | * of those above. If you wish to allow use of your version of this file only
|
---|
29 | * under the terms of either the GPL or the LGPL, and not to allow others to
|
---|
30 | * use your version of this file under the terms of the MPL, indicate your
|
---|
31 | * decision by deleting the provisions above and replace them with the notice
|
---|
32 | * and other provisions required by the GPL or the LGPL. If you do not delete
|
---|
33 | * the provisions above, a recipient may use your version of this file under
|
---|
34 | * the terms of any one of the MPL, the GPL or the LGPL.
|
---|
35 | *
|
---|
36 | * ***** END LICENSE BLOCK ***** */
|
---|
37 |
|
---|
38 | #include "nsXPCOM.h"
|
---|
39 | #include "nsString.h"
|
---|
40 | #include "nsILocalFile.h"
|
---|
41 | #include "nsIInterfaceInfoManager.h"
|
---|
42 | #include "xptinfo.h"
|
---|
43 | #include "nsCOMPtr.h"
|
---|
44 | #include "prmem.h"
|
---|
45 | #include "xptcall.h"
|
---|
46 | #ifdef VBOX
|
---|
47 | #include "nsFileStreams.h"
|
---|
48 | static nsresult
|
---|
49 | NS_NewLocalFileInputStream(nsIInputStream **aResult,
|
---|
50 | nsIFile *aFile,
|
---|
51 | PRInt32 aIOFlags = -1,
|
---|
52 | PRInt32 aPerm = -1,
|
---|
53 | PRInt32 aBehaviorFlags = 0)
|
---|
54 | {
|
---|
55 | nsFileInputStream* in = new nsFileInputStream();
|
---|
56 | nsresult rv;
|
---|
57 |
|
---|
58 | rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
---|
59 | if (NS_SUCCEEDED(rv))
|
---|
60 | NS_ADDREF(*aResult = in);
|
---|
61 |
|
---|
62 | return rv;
|
---|
63 | }
|
---|
64 |
|
---|
65 | inline nsresult
|
---|
66 | NS_NewLocalFileOutputStream(nsIOutputStream **aResult,
|
---|
67 | nsIFile *aFile,
|
---|
68 | PRInt32 aIOFlags = -1,
|
---|
69 | PRInt32 aPerm = -1,
|
---|
70 | PRInt32 aBehaviorFlags = 0)
|
---|
71 | {
|
---|
72 | nsFileOutputStream* in = new nsFileOutputStream();
|
---|
73 | nsresult rv;
|
---|
74 |
|
---|
75 | rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
|
---|
76 | if (NS_SUCCEEDED(rv))
|
---|
77 | NS_ADDREF(*aResult = in);
|
---|
78 |
|
---|
79 | return rv;
|
---|
80 | }
|
---|
81 |
|
---|
82 |
|
---|
83 | #else
|
---|
84 | #include "nsNetUtil.h"
|
---|
85 | #endif
|
---|
86 | #include "nsHashSets.h"
|
---|
87 | #include "nsIWeakReference.h"
|
---|
88 | #include <stdio.h>
|
---|
89 |
|
---|
90 | #ifdef WIN32
|
---|
91 | #define snprintf _snprintf
|
---|
92 | #endif
|
---|
93 |
|
---|
94 | #define WRITE_NOSCRIPT_METHODS
|
---|
95 |
|
---|
96 |
|
---|
97 | class TypeInfo
|
---|
98 | {
|
---|
99 | public:
|
---|
100 | static nsresult GetParentInfo(nsIInterfaceInfo* aIInfo,
|
---|
101 | nsIInterfaceInfo** aParentInfo,
|
---|
102 | PRUint16* aParentMethodCount,
|
---|
103 | PRUint16* aParentConstCount)
|
---|
104 | {
|
---|
105 | nsCOMPtr<nsIInterfaceInfo> parent;
|
---|
106 | nsresult rv = aIInfo->GetParent(getter_AddRefs(parent));
|
---|
107 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
108 |
|
---|
109 | if (!parent) {
|
---|
110 | *aParentInfo = nsnull;
|
---|
111 | *aParentMethodCount = 0;
|
---|
112 | return NS_OK;
|
---|
113 | }
|
---|
114 |
|
---|
115 | rv = parent->GetMethodCount(aParentMethodCount);
|
---|
116 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
117 | rv = parent->GetConstantCount(aParentConstCount);
|
---|
118 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
119 |
|
---|
120 | *aParentInfo = parent;
|
---|
121 | NS_ADDREF(*aParentInfo);
|
---|
122 | return rv;
|
---|
123 | }
|
---|
124 |
|
---|
125 | static nsresult GetInterfaceName(nsIInterfaceInfo* aIInfo,
|
---|
126 | PRUint16 aMethodIndex,
|
---|
127 | const nsXPTParamInfo* aParamInfo,
|
---|
128 | char** aResult)
|
---|
129 | {
|
---|
130 | static const char isupp_str[] = "nsISupports";
|
---|
131 |
|
---|
132 | nsIID* iid;
|
---|
133 | nsresult rv = aIInfo->GetIIDForParam(aMethodIndex, aParamInfo, &iid);
|
---|
134 | if (NS_FAILED(rv)) {
|
---|
135 | // GetIIDForParam will sometimes fail to find an interface, particularly
|
---|
136 | // if that interface is not defined in an IDL file. In those cases, just
|
---|
137 | // return |nsISupports|.
|
---|
138 | //
|
---|
139 | // For example, the |onStreamComplete| method for the interface
|
---|
140 | // |nsIUnicharStreamLoaderObserver| takes a param of
|
---|
141 | // |nsIUnicharInputStream|, which is defined in a simple header file, not
|
---|
142 | // an IDL file.
|
---|
143 | *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
|
---|
144 | rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
---|
145 |
|
---|
146 | } else {
|
---|
147 |
|
---|
148 | // In Javaconnect, we handle weak references internally; no need for the
|
---|
149 | // |nsIWeakReference| interface. So just return |nsISupports|.
|
---|
150 | if (iid->Equals(NS_GET_IID(nsIWeakReference))) {
|
---|
151 | *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
|
---|
152 | rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
---|
153 |
|
---|
154 | } else {
|
---|
155 |
|
---|
156 | // Some methods take parameters of non-scriptable interfaces. But we
|
---|
157 | // only output scriptable interfaces. So if one of the param types is
|
---|
158 | // a non-scriptable interface, output |nsISupports| instead of the
|
---|
159 | // interface name.
|
---|
160 | nsCOMPtr<nsIInterfaceInfo> info;
|
---|
161 | nsCOMPtr<nsIInterfaceInfoManager> iim =
|
---|
162 | getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
---|
163 | NS_ASSERTION(iim, "could not get interface info manager");
|
---|
164 | rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
|
---|
165 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
166 | PRBool scriptable;
|
---|
167 | if (NS_SUCCEEDED(rv)) {
|
---|
168 | info->IsScriptable(&scriptable);
|
---|
169 | }
|
---|
170 | if (NS_FAILED(rv) || !scriptable) {
|
---|
171 | *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
|
---|
172 | rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
---|
173 | } else {
|
---|
174 |
|
---|
175 | // If is scriptable, get name for given IID
|
---|
176 | rv = iim->GetNameForIID(iid, aResult);
|
---|
177 | }
|
---|
178 | }
|
---|
179 |
|
---|
180 | nsMemory::Free(iid);
|
---|
181 | }
|
---|
182 |
|
---|
183 | return rv;
|
---|
184 | }
|
---|
185 | };
|
---|
186 |
|
---|
187 |
|
---|
188 | static const char* kJavaKeywords[] = {
|
---|
189 | "abstract", "default", "if" , "private" , "this" ,
|
---|
190 | "boolean" , "do" , "implements", "protected" , "throw" ,
|
---|
191 | "break" , "double" , "import", "public" , "throws" ,
|
---|
192 | "byte" , "else" , "instanceof", "return" , "transient",
|
---|
193 | "case" , "extends", "int" , "short" , "try" ,
|
---|
194 | "catch" , "final" , "interface" , "static" , "void" ,
|
---|
195 | "char" , "finally", "long" , "strictfp" , "volatile" ,
|
---|
196 | "class" , "float" , "native" , "super" , "while" ,
|
---|
197 | "const" , "for" , "new" , "switch" ,
|
---|
198 | "continue", "goto" , "package" , "synchronized",
|
---|
199 | "assert" , /* added in Java 1.4 */
|
---|
200 | "enum" , /* added in Java 5.0 */
|
---|
201 | "clone" , /* clone is a member function of java.lang.Object */
|
---|
202 | "finalize" /* finalize is a member function of java.lang.Object */
|
---|
203 | };
|
---|
204 |
|
---|
205 | #ifdef WRITE_NOSCRIPT_METHODS
|
---|
206 | // SWT uses [noscript] methods of the following interfaces, so we need to
|
---|
207 | // output the [noscript] methods for these interfaces.
|
---|
208 | static const char* kNoscriptMethodIfaces[] = {
|
---|
209 | "nsIBaseWindow", "nsIEmbeddingSiteWindow"
|
---|
210 | };
|
---|
211 | #endif
|
---|
212 |
|
---|
213 |
|
---|
214 | class Generate
|
---|
215 | {
|
---|
216 | nsILocalFile* mOutputDir;
|
---|
217 | nsCStringHashSet mIfaceTable;
|
---|
218 | nsCStringHashSet mJavaKeywords;
|
---|
219 | #ifdef WRITE_NOSCRIPT_METHODS
|
---|
220 | nsCStringHashSet mNoscriptMethodsTable;
|
---|
221 | #endif
|
---|
222 |
|
---|
223 | public:
|
---|
224 | Generate(nsILocalFile* aOutputDir)
|
---|
225 | : mOutputDir(aOutputDir)
|
---|
226 | {
|
---|
227 | mIfaceTable.Init(100);
|
---|
228 |
|
---|
229 | PRUint32 size = NS_ARRAY_LENGTH(kJavaKeywords);
|
---|
230 | mJavaKeywords.Init(size);
|
---|
231 | for (PRUint32 i = 0; i < size; i++) {
|
---|
232 | mJavaKeywords.Put(nsDependentCString(kJavaKeywords[i]));
|
---|
233 | }
|
---|
234 |
|
---|
235 | #ifdef WRITE_NOSCRIPT_METHODS
|
---|
236 | size = NS_ARRAY_LENGTH(kNoscriptMethodIfaces);
|
---|
237 | mNoscriptMethodsTable.Init(size);
|
---|
238 | for (PRUint32 j = 0; j < size; j++) {
|
---|
239 | mNoscriptMethodsTable.Put(nsDependentCString(kNoscriptMethodIfaces[j]));
|
---|
240 | }
|
---|
241 | #endif
|
---|
242 | }
|
---|
243 |
|
---|
244 | ~Generate()
|
---|
245 | {
|
---|
246 | }
|
---|
247 |
|
---|
248 | nsresult GenerateInterfaces()
|
---|
249 | {
|
---|
250 | nsresult rv;
|
---|
251 |
|
---|
252 | nsCOMPtr<nsIInterfaceInfoManager> iim =
|
---|
253 | getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
---|
254 | NS_ASSERTION(iim, "could not get interface info manager");
|
---|
255 | nsCOMPtr<nsIEnumerator> etor;
|
---|
256 | rv = iim->EnumerateInterfaces(getter_AddRefs(etor));
|
---|
257 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
258 |
|
---|
259 | // loop over interfaces
|
---|
260 | etor->First();
|
---|
261 | do {
|
---|
262 | // get current interface
|
---|
263 | nsCOMPtr<nsISupports> item;
|
---|
264 | rv = etor->CurrentItem(getter_AddRefs(item));
|
---|
265 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
266 |
|
---|
267 | nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(item));
|
---|
268 | if (!iface)
|
---|
269 | break;
|
---|
270 |
|
---|
271 | // we only care about scriptable interfaces, so skip over those
|
---|
272 | // that aren't
|
---|
273 | PRBool scriptable;
|
---|
274 | iface->IsScriptable(&scriptable);
|
---|
275 | if (!scriptable) {
|
---|
276 | // XXX SWT uses non-scriptable interface 'nsIAppShell' (bug 270892), so
|
---|
277 | // include that one.
|
---|
278 | const char* iface_name;
|
---|
279 | iface->GetNameShared(&iface_name);
|
---|
280 | if (strcmp("nsIAppShell", iface_name) != 0)
|
---|
281 | continue;
|
---|
282 | }
|
---|
283 |
|
---|
284 | rv = WriteOneInterface(iface);
|
---|
285 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
286 |
|
---|
287 | } while (NS_SUCCEEDED(etor->Next()));
|
---|
288 |
|
---|
289 | return NS_OK;
|
---|
290 | }
|
---|
291 |
|
---|
292 | nsresult WriteOneInterface(nsIInterfaceInfo* aIInfo)
|
---|
293 | {
|
---|
294 | nsresult rv;
|
---|
295 |
|
---|
296 | // write each interface only once
|
---|
297 | const char* iface_name;
|
---|
298 | aIInfo->GetNameShared(&iface_name);
|
---|
299 | if (mIfaceTable.Contains(nsDependentCString(iface_name)))
|
---|
300 | return NS_OK;
|
---|
301 |
|
---|
302 | // write any parent interface
|
---|
303 | nsCOMPtr<nsIInterfaceInfo> parentInfo;
|
---|
304 | PRUint16 parentMethodCount, parentConstCount;
|
---|
305 | rv = TypeInfo::GetParentInfo(aIInfo, getter_AddRefs(parentInfo),
|
---|
306 | &parentMethodCount, &parentConstCount);
|
---|
307 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
308 | if (parentInfo)
|
---|
309 | WriteOneInterface(parentInfo);
|
---|
310 |
|
---|
311 | mIfaceTable.Put(nsDependentCString(iface_name));
|
---|
312 |
|
---|
313 | // create file for interface
|
---|
314 | nsCOMPtr<nsIOutputStream> out;
|
---|
315 | rv = OpenIfaceFileStream(iface_name, getter_AddRefs(out));
|
---|
316 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
317 |
|
---|
318 | // write contents to file
|
---|
319 | rv = WriteHeader(out, iface_name);
|
---|
320 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
321 | rv = WriteInterfaceStart(out, aIInfo, parentInfo);
|
---|
322 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
323 | rv = WriteIID(out, aIInfo);
|
---|
324 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
325 | rv = WriteConstants(out, aIInfo, parentConstCount);
|
---|
326 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
327 | rv = WriteMethods(out, aIInfo, parentMethodCount);
|
---|
328 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
329 | rv = WriteInterfaceEnd(out);
|
---|
330 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
331 |
|
---|
332 | rv = CloseIfaceFileStream(out);
|
---|
333 |
|
---|
334 | return rv;
|
---|
335 | }
|
---|
336 |
|
---|
337 | nsresult OpenIfaceFileStream(const char* aIfaceName,
|
---|
338 | nsIOutputStream** aResult)
|
---|
339 | {
|
---|
340 | nsresult rv;
|
---|
341 |
|
---|
342 | // create interface file in output dir
|
---|
343 | nsCOMPtr<nsIFile> iface_file;
|
---|
344 | rv = mOutputDir->Clone(getter_AddRefs(iface_file));
|
---|
345 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
346 | nsAutoString filename;
|
---|
347 | filename.AppendASCII(aIfaceName);
|
---|
348 | filename.AppendLiteral(".java");
|
---|
349 | rv = iface_file->Append(filename);
|
---|
350 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
351 |
|
---|
352 | // create interface file
|
---|
353 | PRBool exists;
|
---|
354 | iface_file->Exists(&exists);
|
---|
355 | if (exists)
|
---|
356 | iface_file->Remove(PR_FALSE);
|
---|
357 | rv = iface_file->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
|
---|
358 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
359 |
|
---|
360 | // create output stream for writing to file
|
---|
361 | nsCOMPtr<nsIOutputStream> out;
|
---|
362 | rv = NS_NewLocalFileOutputStream(getter_AddRefs(out), iface_file);
|
---|
363 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
364 |
|
---|
365 | *aResult = out;
|
---|
366 | NS_ADDREF(*aResult);
|
---|
367 | return NS_OK;
|
---|
368 | }
|
---|
369 |
|
---|
370 | nsresult CloseIfaceFileStream(nsIOutputStream* out)
|
---|
371 | {
|
---|
372 | return out->Close();
|
---|
373 | }
|
---|
374 |
|
---|
375 | nsresult WriteHeader(nsIOutputStream* out, const char* aIfaceName)
|
---|
376 | {
|
---|
377 | static const char kHeader1[] =
|
---|
378 | "/**\n"
|
---|
379 | " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n"
|
---|
380 | " * FOR THE FULL DOCUMENTION AND LICENSE.\n"
|
---|
381 | " *\n"
|
---|
382 | " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=";
|
---|
383 | static const char kHeader2[]= "\">\n **/\n\n";
|
---|
384 | static const char kPackage[] = "package org.mozilla.interfaces;\n\n";
|
---|
385 |
|
---|
386 | PRUint32 count;
|
---|
387 | nsresult rv = out->Write(kHeader1, sizeof(kHeader1) - 1, &count);
|
---|
388 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
389 |
|
---|
390 | nsCAutoString searchTerm;
|
---|
391 | searchTerm.AppendLiteral("interface+");
|
---|
392 | searchTerm.AppendASCII(aIfaceName);
|
---|
393 | // LXR limits to 29 chars
|
---|
394 | rv = out->Write(searchTerm.get(), PR_MIN(29, searchTerm.Length()), &count);
|
---|
395 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
396 |
|
---|
397 | rv = out->Write(kHeader2, sizeof(kHeader2) - 1, &count);
|
---|
398 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
399 | rv = out->Write(kPackage, sizeof(kPackage) - 1, &count);
|
---|
400 | return rv;
|
---|
401 | }
|
---|
402 |
|
---|
403 | nsresult WriteInterfaceStart(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
|
---|
404 | nsIInterfaceInfo* aParentInfo)
|
---|
405 | {
|
---|
406 | static const char kIfaceDecl1[] = "public interface ";
|
---|
407 | static const char kParentDecl[] = " extends ";
|
---|
408 | static const char kIfaceDecl2[] = "\n{\n";
|
---|
409 |
|
---|
410 | const char* iface_name;
|
---|
411 | aIInfo->GetNameShared(&iface_name);
|
---|
412 | PRUint32 count;
|
---|
413 | nsresult rv = out->Write(kIfaceDecl1, sizeof(kIfaceDecl1) - 1, &count);
|
---|
414 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
415 | rv = out->Write(iface_name, strlen(iface_name), &count);
|
---|
416 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
417 |
|
---|
418 | if (aParentInfo) {
|
---|
419 | const char* parent_name;
|
---|
420 | aParentInfo->GetNameShared(&parent_name);
|
---|
421 | rv = out->Write(kParentDecl, sizeof(kParentDecl) - 1, &count);
|
---|
422 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
423 | rv = out->Write(parent_name, strlen(parent_name), &count);
|
---|
424 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
425 | }
|
---|
426 |
|
---|
427 | rv = out->Write(kIfaceDecl2, sizeof(kIfaceDecl2) - 1, &count);
|
---|
428 | return rv;
|
---|
429 | }
|
---|
430 |
|
---|
431 | nsresult WriteInterfaceEnd(nsIOutputStream* out)
|
---|
432 | {
|
---|
433 | PRUint32 count;
|
---|
434 | return out->Write("}\n", 2, &count);
|
---|
435 | }
|
---|
436 |
|
---|
437 | nsresult WriteIID(nsIOutputStream* out, nsIInterfaceInfo* aIInfo)
|
---|
438 | {
|
---|
439 | static const char kIIDDecl1[] = " public static final String ";
|
---|
440 | static const char kIIDDecl2[] = " =\n \"";
|
---|
441 | static const char kIIDDecl3[] = "\";\n\n";
|
---|
442 |
|
---|
443 | nsIID* iid = nsnull;
|
---|
444 | aIInfo->GetInterfaceIID(&iid);
|
---|
445 | if (!iid)
|
---|
446 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
447 |
|
---|
448 | // create iid field name
|
---|
449 | nsCAutoString iid_name;
|
---|
450 | const char* iface_name;
|
---|
451 | aIInfo->GetNameShared(&iface_name);
|
---|
452 | if (strncmp("ns", iface_name, 2) == 0) {
|
---|
453 | iid_name.AppendLiteral("NS_");
|
---|
454 | iid_name.Append(iface_name + 2);
|
---|
455 | } else {
|
---|
456 | iid_name.Append(iface_name);
|
---|
457 | }
|
---|
458 | iid_name.AppendLiteral("_IID");
|
---|
459 | ToUpperCase(iid_name);
|
---|
460 |
|
---|
461 | // get iid string
|
---|
462 | char* iid_str = iid->ToString();
|
---|
463 | if (!iid_str)
|
---|
464 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
465 |
|
---|
466 | PRUint32 count;
|
---|
467 | nsresult rv = out->Write(kIIDDecl1, sizeof(kIIDDecl1) - 1, &count);
|
---|
468 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
469 | rv = out->Write(iid_name.get(), iid_name.Length(), &count);
|
---|
470 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
471 | rv = out->Write(kIIDDecl2, sizeof(kIIDDecl2) - 1, &count);
|
---|
472 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
473 | rv = out->Write(iid_str, strlen(iid_str), &count);
|
---|
474 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
475 | rv = out->Write(kIIDDecl3, sizeof(kIIDDecl3) - 1, &count);
|
---|
476 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
477 |
|
---|
478 | // cleanup
|
---|
479 | PR_Free(iid_str);
|
---|
480 | nsMemory::Free(iid);
|
---|
481 | return NS_OK;
|
---|
482 | }
|
---|
483 |
|
---|
484 | nsresult WriteConstants(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
|
---|
485 | PRUint16 aParentConstCount)
|
---|
486 | {
|
---|
487 | static const char kConstDecl1[] = " public static final ";
|
---|
488 | static const char kConstDecl2[] = " = ";
|
---|
489 | static const char kConstDecl3[] = ";\n\n";
|
---|
490 |
|
---|
491 | PRUint16 constCount;
|
---|
492 | nsresult rv = aIInfo->GetConstantCount(&constCount);
|
---|
493 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
494 |
|
---|
495 | for (PRUint16 i = aParentConstCount; i < constCount; i++) {
|
---|
496 | const nsXPTConstant* constInfo;
|
---|
497 | rv = aIInfo->GetConstant(i, &constInfo);
|
---|
498 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
499 |
|
---|
500 | PRUint32 count;
|
---|
501 | rv = out->Write(kConstDecl1, sizeof(kConstDecl1) - 1, &count);
|
---|
502 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
503 | const nsXPTType &type = constInfo->GetType();
|
---|
504 | rv = WriteType(out, &type, aIInfo, nsnull, nsnull);
|
---|
505 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
506 | rv = out->Write(" ", 1, &count);
|
---|
507 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
508 | const char* name = constInfo->GetName();
|
---|
509 | rv = out->Write(name, strlen(name), &count);
|
---|
510 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
511 | rv = out->Write(kConstDecl2, sizeof(kConstDecl2) - 1, &count);
|
---|
512 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
513 |
|
---|
514 | rv = WriteConstantValue(out, &type, constInfo->GetValue());
|
---|
515 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
516 | rv = out->Write(kConstDecl3, sizeof(kConstDecl3) - 1, &count);
|
---|
517 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
518 | }
|
---|
519 |
|
---|
520 | return NS_OK;
|
---|
521 | }
|
---|
522 |
|
---|
523 | nsresult WriteConstantValue(nsIOutputStream* out, const nsXPTType* aType,
|
---|
524 | const nsXPTCMiniVariant* aValue)
|
---|
525 | {
|
---|
526 | char buf[32];
|
---|
527 | switch (aType->TagPart()) {
|
---|
528 | case nsXPTType::T_I8:
|
---|
529 | snprintf(buf, sizeof(buf), "%d", aValue->val.i8);
|
---|
530 | break;
|
---|
531 |
|
---|
532 | case nsXPTType::T_U8:
|
---|
533 | snprintf(buf, sizeof(buf), "%u", aValue->val.u8);
|
---|
534 | break;
|
---|
535 |
|
---|
536 | case nsXPTType::T_I16:
|
---|
537 | snprintf(buf, sizeof(buf), "%d", aValue->val.i16);
|
---|
538 | break;
|
---|
539 |
|
---|
540 | case nsXPTType::T_U16:
|
---|
541 | snprintf(buf, sizeof(buf), "%u", aValue->val.u16);
|
---|
542 | break;
|
---|
543 |
|
---|
544 | case nsXPTType::T_I32:
|
---|
545 | snprintf(buf, sizeof(buf), "%d", aValue->val.i32);
|
---|
546 | break;
|
---|
547 |
|
---|
548 | case nsXPTType::T_U32:
|
---|
549 | snprintf(buf, sizeof(buf), "%uL", aValue->val.u32);
|
---|
550 | break;
|
---|
551 |
|
---|
552 | case nsXPTType::T_I64:
|
---|
553 | snprintf(buf, sizeof(buf), "%lldL", aValue->val.i64);
|
---|
554 | break;
|
---|
555 |
|
---|
556 | case nsXPTType::T_U64:
|
---|
557 | snprintf(buf, sizeof(buf), "%lluL", aValue->val.u64);
|
---|
558 | break;
|
---|
559 |
|
---|
560 | case nsXPTType::T_FLOAT:
|
---|
561 | snprintf(buf, sizeof(buf), "%f", aValue->val.f);
|
---|
562 | break;
|
---|
563 |
|
---|
564 | case nsXPTType::T_DOUBLE:
|
---|
565 | snprintf(buf, sizeof(buf), "%f", aValue->val.d);
|
---|
566 | break;
|
---|
567 |
|
---|
568 | case nsXPTType::T_BOOL:
|
---|
569 | if (aValue->val.b)
|
---|
570 | sprintf(buf, "true");
|
---|
571 | else
|
---|
572 | sprintf(buf, "false");
|
---|
573 | break;
|
---|
574 |
|
---|
575 | case nsXPTType::T_CHAR:
|
---|
576 | snprintf(buf, sizeof(buf), "%c", aValue->val.c);
|
---|
577 | break;
|
---|
578 |
|
---|
579 | case nsXPTType::T_WCHAR:
|
---|
580 | snprintf(buf, sizeof(buf), "%c", aValue->val.wc);
|
---|
581 | break;
|
---|
582 |
|
---|
583 | default:
|
---|
584 | NS_WARNING("unexpected constant type");
|
---|
585 | return NS_ERROR_UNEXPECTED;
|
---|
586 | }
|
---|
587 |
|
---|
588 | PRUint32 count;
|
---|
589 | return out->Write(buf, strlen(buf), &count);
|
---|
590 | }
|
---|
591 |
|
---|
592 | nsresult WriteMethods(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
|
---|
593 | PRUint16 aParentMethodCount)
|
---|
594 | {
|
---|
595 | PRUint16 methodCount;
|
---|
596 | nsresult rv = aIInfo->GetMethodCount(&methodCount);
|
---|
597 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
598 |
|
---|
599 | for (PRUint16 i = aParentMethodCount; i < methodCount; i++) {
|
---|
600 | const nsXPTMethodInfo* methodInfo;
|
---|
601 | rv = aIInfo->GetMethodInfo(i, &methodInfo);
|
---|
602 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
603 |
|
---|
604 | #ifdef WRITE_NOSCRIPT_METHODS
|
---|
605 | // XXX
|
---|
606 | // SWT makes use of [noscript] methods in some classes, so output them
|
---|
607 | // for those classes.
|
---|
608 |
|
---|
609 | // skip [notxpcom] methods
|
---|
610 | if (methodInfo->IsNotXPCOM())
|
---|
611 | continue;
|
---|
612 |
|
---|
613 | // skip most hidden ([noscript]) methods
|
---|
614 | if (methodInfo->IsHidden()) {
|
---|
615 | const char* iface_name;
|
---|
616 | aIInfo->GetNameShared(&iface_name);
|
---|
617 | if (!mNoscriptMethodsTable.Contains(nsDependentCString(iface_name)))
|
---|
618 | continue;
|
---|
619 | }
|
---|
620 | #else
|
---|
621 | // skip hidden ([noscript]) or [notxpcom] methods
|
---|
622 | if (methodInfo->IsHidden() || methodInfo->IsNotXPCOM())
|
---|
623 | continue;
|
---|
624 | #endif
|
---|
625 |
|
---|
626 | rv = WriteOneMethod(out, aIInfo, methodInfo, i);
|
---|
627 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
628 | }
|
---|
629 |
|
---|
630 | return NS_OK;
|
---|
631 | }
|
---|
632 |
|
---|
633 | nsresult WriteOneMethod(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
|
---|
634 | const nsXPTMethodInfo* aMethodInfo,
|
---|
635 | PRUint16 aMethodIndex)
|
---|
636 | {
|
---|
637 | static const char kMethodDecl1[] = " public ";
|
---|
638 | static const char kVoidReturn[] = "void";
|
---|
639 | static const char kParamSeparator[] = ", ";
|
---|
640 | static const char kMethodDecl2[] = ");\n\n";
|
---|
641 |
|
---|
642 | PRUint32 count;
|
---|
643 | nsresult rv = out->Write(kMethodDecl1, sizeof(kMethodDecl1) - 1, &count);
|
---|
644 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
645 |
|
---|
646 | // write return type
|
---|
647 | PRUint8 paramCount = aMethodInfo->GetParamCount();
|
---|
648 | const nsXPTParamInfo* resultInfo = nsnull;
|
---|
649 | for (PRUint8 i = 0; i < paramCount; i++) {
|
---|
650 | const nsXPTParamInfo ¶mInfo = aMethodInfo->GetParam(i);
|
---|
651 | if (paramInfo.IsRetval()) {
|
---|
652 | resultInfo = ¶mInfo;
|
---|
653 | break;
|
---|
654 | }
|
---|
655 | }
|
---|
656 | if (resultInfo) {
|
---|
657 | rv = WriteParam(out, aIInfo, aMethodIndex, resultInfo, 0);
|
---|
658 | } else {
|
---|
659 | rv = out->Write(kVoidReturn, sizeof(kVoidReturn) - 1, &count);
|
---|
660 | }
|
---|
661 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
662 |
|
---|
663 | // write method name string
|
---|
664 | nsCAutoString method_name;
|
---|
665 | const char* name = aMethodInfo->GetName();
|
---|
666 | if (aMethodInfo->IsGetter() || aMethodInfo->IsSetter()) {
|
---|
667 | if (aMethodInfo->IsGetter())
|
---|
668 | method_name.AppendLiteral("get");
|
---|
669 | else
|
---|
670 | method_name.AppendLiteral("set");
|
---|
671 | method_name.Append(toupper(name[0]));
|
---|
672 | method_name.AppendASCII(name + 1);
|
---|
673 | } else {
|
---|
674 | method_name.Append(tolower(name[0]));
|
---|
675 | method_name.AppendASCII(name + 1);
|
---|
676 | // don't use Java keywords as method names
|
---|
677 | if (mJavaKeywords.Contains(method_name))
|
---|
678 | method_name.Append('_');
|
---|
679 | }
|
---|
680 | rv = out->Write(" ", 1, &count);
|
---|
681 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
682 | rv = out->Write(method_name.get(), method_name.Length(), &count);
|
---|
683 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
684 | rv = out->Write("(", 1, &count);
|
---|
685 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
686 |
|
---|
687 | // write parameters
|
---|
688 | for (PRUint8 j = 0; j < paramCount; j++) {
|
---|
689 | const nsXPTParamInfo ¶mInfo = aMethodInfo->GetParam(j);
|
---|
690 | if (paramInfo.IsRetval())
|
---|
691 | continue;
|
---|
692 |
|
---|
693 | if (j != 0) {
|
---|
694 | rv = out->Write(kParamSeparator, sizeof(kParamSeparator) - 1, &count);
|
---|
695 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
696 | }
|
---|
697 |
|
---|
698 | rv = WriteParam(out, aIInfo, aMethodIndex, ¶mInfo, j + 1);
|
---|
699 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
700 | }
|
---|
701 |
|
---|
702 | rv = out->Write(kMethodDecl2, sizeof(kMethodDecl2) - 1, &count);
|
---|
703 | return rv;
|
---|
704 | }
|
---|
705 |
|
---|
706 | nsresult WriteParam(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
|
---|
707 | PRUint16 aMethodIndex, const nsXPTParamInfo* aParamInfo,
|
---|
708 | PRUint8 aIndex)
|
---|
709 | {
|
---|
710 | const nsXPTType &type = aParamInfo->GetType();
|
---|
711 | nsresult rv = WriteType(out, &type, aIInfo, aMethodIndex, aParamInfo);
|
---|
712 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
713 |
|
---|
714 | // if parameter is 'out' or 'inout', make it a Java array
|
---|
715 | PRUint32 count;
|
---|
716 | if (aParamInfo->IsOut() && !aParamInfo->IsRetval()) {
|
---|
717 | rv = out->Write("[]", 2, &count);
|
---|
718 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
719 | }
|
---|
720 |
|
---|
721 | // write name for parameter (but not for 'retval' param)
|
---|
722 | if (aIndex) {
|
---|
723 | char buf[10];
|
---|
724 | snprintf(buf, sizeof(buf), " arg%d", aIndex);
|
---|
725 | rv = out->Write(buf, strlen(buf), &count);
|
---|
726 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
727 | }
|
---|
728 |
|
---|
729 | return NS_OK;
|
---|
730 | }
|
---|
731 |
|
---|
732 | /**
|
---|
733 | * Write out the Java type for the given XPIDL type.
|
---|
734 | *
|
---|
735 | * NOTE: Java doesn't support unsigned types. So for any unsigned XPIDL type,
|
---|
736 | * we move up to the next largest Java type. This way we ensure that we don't
|
---|
737 | * lose any info.
|
---|
738 | */
|
---|
739 | nsresult WriteType(nsIOutputStream* out, const nsXPTType* aType,
|
---|
740 | nsIInterfaceInfo* aIInfo, PRUint16 aMethodIndex,
|
---|
741 | const nsXPTParamInfo* aParamInfo)
|
---|
742 | {
|
---|
743 | nsresult rv;
|
---|
744 | PRUint32 count;
|
---|
745 | switch (aType->TagPart()) {
|
---|
746 | case nsXPTType::T_I8:
|
---|
747 | rv = out->Write("byte", 4, &count);
|
---|
748 | break;
|
---|
749 |
|
---|
750 | case nsXPTType::T_I16:
|
---|
751 | case nsXPTType::T_U8:
|
---|
752 | rv = out->Write("short", 5, &count);
|
---|
753 | break;
|
---|
754 |
|
---|
755 | case nsXPTType::T_I32:
|
---|
756 | case nsXPTType::T_U16:
|
---|
757 | rv = out->Write("int", 3, &count);
|
---|
758 | break;
|
---|
759 |
|
---|
760 | case nsXPTType::T_I64:
|
---|
761 | case nsXPTType::T_U32:
|
---|
762 | rv = out->Write("long", 4, &count);
|
---|
763 | break;
|
---|
764 |
|
---|
765 | case nsXPTType::T_FLOAT:
|
---|
766 | rv = out->Write("float", 5, &count);
|
---|
767 | break;
|
---|
768 |
|
---|
769 | // XXX how should we handle 64-bit values?
|
---|
770 | case nsXPTType::T_U64:
|
---|
771 | case nsXPTType::T_DOUBLE:
|
---|
772 | rv = out->Write("double", 6, &count);
|
---|
773 | break;
|
---|
774 |
|
---|
775 | case nsXPTType::T_BOOL:
|
---|
776 | rv = out->Write("boolean", 7, &count);
|
---|
777 | break;
|
---|
778 |
|
---|
779 | case nsXPTType::T_CHAR:
|
---|
780 | case nsXPTType::T_WCHAR:
|
---|
781 | rv = out->Write("char", 4, &count);
|
---|
782 | break;
|
---|
783 |
|
---|
784 | case nsXPTType::T_CHAR_STR:
|
---|
785 | case nsXPTType::T_WCHAR_STR:
|
---|
786 | case nsXPTType::T_IID:
|
---|
787 | case nsXPTType::T_ASTRING:
|
---|
788 | case nsXPTType::T_DOMSTRING:
|
---|
789 | case nsXPTType::T_UTF8STRING:
|
---|
790 | case nsXPTType::T_CSTRING:
|
---|
791 | case nsXPTType::T_PSTRING_SIZE_IS:
|
---|
792 | case nsXPTType::T_PWSTRING_SIZE_IS:
|
---|
793 | rv = out->Write("String", 6, &count);
|
---|
794 | break;
|
---|
795 |
|
---|
796 | case nsXPTType::T_INTERFACE:
|
---|
797 | {
|
---|
798 | char* iface_name = nsnull;
|
---|
799 | rv = TypeInfo::GetInterfaceName(aIInfo, aMethodIndex, aParamInfo,
|
---|
800 | &iface_name);
|
---|
801 | if (NS_FAILED(rv) || !iface_name) {
|
---|
802 | rv = NS_ERROR_FAILURE;
|
---|
803 | break;
|
---|
804 | }
|
---|
805 |
|
---|
806 | rv = out->Write(iface_name, strlen(iface_name), &count);
|
---|
807 | nsMemory::Free(iface_name);
|
---|
808 | break;
|
---|
809 | }
|
---|
810 |
|
---|
811 | case nsXPTType::T_INTERFACE_IS:
|
---|
812 | rv = out->Write("nsISupports", 11, &count);
|
---|
813 | break;
|
---|
814 |
|
---|
815 | case nsXPTType::T_VOID:
|
---|
816 | rv = out->Write("int", 3, &count);
|
---|
817 | break;
|
---|
818 |
|
---|
819 | case nsXPTType::T_ARRAY:
|
---|
820 | {
|
---|
821 | // get array type
|
---|
822 | nsXPTType xpttype;
|
---|
823 | rv = aIInfo->GetTypeForParam(aMethodIndex, aParamInfo, 1, &xpttype);
|
---|
824 | if (NS_FAILED(rv))
|
---|
825 | break;
|
---|
826 |
|
---|
827 | rv = WriteType(out, &xpttype, aIInfo, aMethodIndex, aParamInfo);
|
---|
828 | if (NS_FAILED(rv))
|
---|
829 | break;
|
---|
830 |
|
---|
831 | rv = out->Write("[]", 2, &count);
|
---|
832 | break;
|
---|
833 | }
|
---|
834 |
|
---|
835 | default:
|
---|
836 | fprintf(stderr, "WARNING: unexpected parameter type %d\n",
|
---|
837 | aType->TagPart());
|
---|
838 | return NS_ERROR_UNEXPECTED;
|
---|
839 | }
|
---|
840 |
|
---|
841 | return rv;
|
---|
842 | }
|
---|
843 | };
|
---|
844 |
|
---|
845 | void PrintUsage(char** argv)
|
---|
846 | {
|
---|
847 | static const char usage_str[] =
|
---|
848 | "Usage: %s -d path\n"
|
---|
849 | " -d output directory for Java interface files\n";
|
---|
850 | fprintf(stderr, usage_str, argv[0]);
|
---|
851 | }
|
---|
852 | #ifdef VBOX
|
---|
853 | #include <VBox/com/com.h>
|
---|
854 | using namespace com;
|
---|
855 |
|
---|
856 | #include <iprt/initterm.h>
|
---|
857 | #include <iprt/string.h>
|
---|
858 | #include <iprt/alloca.h>
|
---|
859 | #include <iprt/stream.h>
|
---|
860 | #endif
|
---|
861 |
|
---|
862 | int main(int argc, char** argv)
|
---|
863 | {
|
---|
864 | nsresult rv = NS_OK;
|
---|
865 | nsCOMPtr<nsILocalFile> output_dir;
|
---|
866 |
|
---|
867 | #ifdef VBOX
|
---|
868 | #if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
|
---|
869 | rv = RTR3Init();
|
---|
870 | #else
|
---|
871 | const char *home = getenv("VBOX_PROGRAM_PATH");
|
---|
872 | if (home) {
|
---|
873 | size_t len = strlen(home);
|
---|
874 | char *exepath = (char *)alloca(len + 32);
|
---|
875 | memcpy(exepath, home, len);
|
---|
876 | memcpy(exepath + len, "/pythonfake", sizeof("/pythonfake"));
|
---|
877 | rv = RTR3InitWithProgramPath(exepath);
|
---|
878 | } else {
|
---|
879 | rv = RTR3Init();
|
---|
880 | }
|
---|
881 | #endif
|
---|
882 | #endif
|
---|
883 |
|
---|
884 | // handle command line arguments
|
---|
885 | for (int i = 1; i < argc; i++) {
|
---|
886 | if (argv[i][0] != '-') {
|
---|
887 | rv = NS_ERROR_FAILURE;
|
---|
888 | break;
|
---|
889 | }
|
---|
890 |
|
---|
891 | switch (argv[i][1]) {
|
---|
892 | case 'd': {
|
---|
893 | if (i + 1 == argc) {
|
---|
894 | fprintf(stderr, "ERROR: missing output directory after -d\n");
|
---|
895 | rv = NS_ERROR_FAILURE;
|
---|
896 | break;
|
---|
897 | }
|
---|
898 |
|
---|
899 | // see if given path exists
|
---|
900 | rv = NS_NewNativeLocalFile(nsDependentCString(argv[++i]), PR_TRUE,
|
---|
901 | getter_AddRefs(output_dir));
|
---|
902 | PRBool val;
|
---|
903 | if (NS_FAILED(rv) || NS_FAILED(output_dir->Exists(&val)) || !val ||
|
---|
904 | NS_FAILED(output_dir->IsDirectory(&val)) || !val)
|
---|
905 | {
|
---|
906 | fprintf(stderr,
|
---|
907 | "ERROR: output directory doesn't exist / isn't a directory\n");
|
---|
908 | rv = NS_ERROR_FAILURE;
|
---|
909 | break;
|
---|
910 | }
|
---|
911 |
|
---|
912 | break;
|
---|
913 | }
|
---|
914 |
|
---|
915 | default: {
|
---|
916 | fprintf(stderr, "ERROR: unknown option %s\n", argv[i]);
|
---|
917 | rv = NS_ERROR_FAILURE;
|
---|
918 | break;
|
---|
919 | }
|
---|
920 | }
|
---|
921 | }
|
---|
922 |
|
---|
923 | if (NS_FAILED(rv)) {
|
---|
924 | PrintUsage(argv);
|
---|
925 | return 1;
|
---|
926 | }
|
---|
927 |
|
---|
928 | #ifdef VBOX
|
---|
929 | rv = com::Initialize();
|
---|
930 | #else
|
---|
931 | rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
---|
932 | #endif
|
---|
933 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
934 |
|
---|
935 | Generate gen(output_dir);
|
---|
936 | rv = gen.GenerateInterfaces();
|
---|
937 |
|
---|
938 | #ifdef VBOX
|
---|
939 | // very short-living XPCOM processes trigger problem on shutdown - ignoring it not a big deal anyway
|
---|
940 | //com::Shutdown();
|
---|
941 | #else
|
---|
942 | NS_ShutdownXPCOM(nsnull);
|
---|
943 | #endif
|
---|
944 | return rv;
|
---|
945 | }
|
---|