VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp@ 30971

Last change on this file since 30971 was 29179, checked in by vboxsync, 15 years ago

GenerateJavaInterfaces.cpp: two DEBUG_bird changes for making diff'ing against the xpidl easier.

  • Property svn:eol-style set to native
File size: 28.2 KB
Line 
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"
48static nsresult
49NS_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
65inline nsresult
66NS_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
97class TypeInfo
98{
99public:
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
188static 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.
208static const char* kNoscriptMethodIfaces[] = {
209 "nsIBaseWindow", "nsIEmbeddingSiteWindow"
210};
211#endif
212
213
214class Generate
215{
216 nsILocalFile* mOutputDir;
217 nsCStringHashSet mIfaceTable;
218 nsCStringHashSet mJavaKeywords;
219#ifdef WRITE_NOSCRIPT_METHODS
220 nsCStringHashSet mNoscriptMethodsTable;
221#endif
222
223public:
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#ifdef DEBUG_bird /* attributes first, then method. For making diffing easier. */
600 for (int pass = 0; pass < 2; pass++)
601#endif
602 for (PRUint16 i = aParentMethodCount; i < methodCount; i++) {
603 const nsXPTMethodInfo* methodInfo;
604 rv = aIInfo->GetMethodInfo(i, &methodInfo);
605 NS_ENSURE_SUCCESS(rv, rv);
606
607#ifdef WRITE_NOSCRIPT_METHODS
608 // XXX
609 // SWT makes use of [noscript] methods in some classes, so output them
610 // for those classes.
611
612 // skip [notxpcom] methods
613 if (methodInfo->IsNotXPCOM())
614 continue;
615
616 // skip most hidden ([noscript]) methods
617 if (methodInfo->IsHidden()) {
618 const char* iface_name;
619 aIInfo->GetNameShared(&iface_name);
620 if (!mNoscriptMethodsTable.Contains(nsDependentCString(iface_name)))
621 continue;
622 }
623#else
624 // skip hidden ([noscript]) or [notxpcom] methods
625 if (methodInfo->IsHidden() || methodInfo->IsNotXPCOM())
626 continue;
627#endif
628#ifdef DEBUG_bird /* attributes first, then method. For making diffing easier. */
629 if ((methodInfo->IsSetter() || methodInfo->IsGetter()) == pass)
630 continue;
631#endif
632
633 rv = WriteOneMethod(out, aIInfo, methodInfo, i);
634 NS_ENSURE_SUCCESS(rv, rv);
635 }
636
637 return NS_OK;
638 }
639
640 nsresult WriteOneMethod(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
641 const nsXPTMethodInfo* aMethodInfo,
642 PRUint16 aMethodIndex)
643 {
644 static const char kMethodDecl1[] = " public ";
645 static const char kVoidReturn[] = "void";
646 static const char kParamSeparator[] = ", ";
647 static const char kMethodDecl2[] = ");\n\n";
648
649 PRUint32 count;
650 nsresult rv = out->Write(kMethodDecl1, sizeof(kMethodDecl1) - 1, &count);
651 NS_ENSURE_SUCCESS(rv, rv);
652
653 // write return type
654 PRUint8 paramCount = aMethodInfo->GetParamCount();
655 const nsXPTParamInfo* resultInfo = nsnull;
656 for (PRUint8 i = 0; i < paramCount; i++) {
657 const nsXPTParamInfo &paramInfo = aMethodInfo->GetParam(i);
658 if (paramInfo.IsRetval()) {
659 resultInfo = &paramInfo;
660 break;
661 }
662 }
663 if (resultInfo) {
664 rv = WriteParam(out, aIInfo, aMethodIndex, resultInfo, 0);
665 } else {
666 rv = out->Write(kVoidReturn, sizeof(kVoidReturn) - 1, &count);
667 }
668 NS_ENSURE_SUCCESS(rv, rv);
669
670 // write method name string
671 nsCAutoString method_name;
672 const char* name = aMethodInfo->GetName();
673 if (aMethodInfo->IsGetter() || aMethodInfo->IsSetter()) {
674 if (aMethodInfo->IsGetter())
675 method_name.AppendLiteral("get");
676 else
677 method_name.AppendLiteral("set");
678 method_name.Append(toupper(name[0]));
679 method_name.AppendASCII(name + 1);
680 } else {
681 method_name.Append(tolower(name[0]));
682 method_name.AppendASCII(name + 1);
683 // don't use Java keywords as method names
684 if (mJavaKeywords.Contains(method_name))
685 method_name.Append('_');
686 }
687 rv = out->Write(" ", 1, &count);
688 NS_ENSURE_SUCCESS(rv, rv);
689 rv = out->Write(method_name.get(), method_name.Length(), &count);
690 NS_ENSURE_SUCCESS(rv, rv);
691 rv = out->Write("(", 1, &count);
692 NS_ENSURE_SUCCESS(rv, rv);
693
694 // write parameters
695 for (PRUint8 j = 0; j < paramCount; j++) {
696 const nsXPTParamInfo &paramInfo = aMethodInfo->GetParam(j);
697 if (paramInfo.IsRetval())
698 continue;
699
700 if (j != 0) {
701 rv = out->Write(kParamSeparator, sizeof(kParamSeparator) - 1, &count);
702 NS_ENSURE_SUCCESS(rv, rv);
703 }
704
705 rv = WriteParam(out, aIInfo, aMethodIndex, &paramInfo, j + 1);
706 NS_ENSURE_SUCCESS(rv, rv);
707 }
708
709 rv = out->Write(kMethodDecl2, sizeof(kMethodDecl2) - 1, &count);
710 return rv;
711 }
712
713 nsresult WriteParam(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
714 PRUint16 aMethodIndex, const nsXPTParamInfo* aParamInfo,
715 PRUint8 aIndex)
716 {
717 const nsXPTType &type = aParamInfo->GetType();
718 nsresult rv = WriteType(out, &type, aIInfo, aMethodIndex, aParamInfo);
719 NS_ENSURE_SUCCESS(rv, rv);
720
721 // if parameter is 'out' or 'inout', make it a Java array
722 PRUint32 count;
723 if (aParamInfo->IsOut() && !aParamInfo->IsRetval()) {
724 rv = out->Write("[]", 2, &count);
725 NS_ENSURE_SUCCESS(rv, rv);
726 }
727
728 // write name for parameter (but not for 'retval' param)
729 if (aIndex) {
730 char buf[10];
731 snprintf(buf, sizeof(buf), " arg%d", aIndex);
732 rv = out->Write(buf, strlen(buf), &count);
733 NS_ENSURE_SUCCESS(rv, rv);
734 }
735
736 return NS_OK;
737 }
738
739 /**
740 * Write out the Java type for the given XPIDL type.
741 *
742 * NOTE: Java doesn't support unsigned types. So for any unsigned XPIDL type,
743 * we move up to the next largest Java type. This way we ensure that we don't
744 * lose any info.
745 */
746 nsresult WriteType(nsIOutputStream* out, const nsXPTType* aType,
747 nsIInterfaceInfo* aIInfo, PRUint16 aMethodIndex,
748 const nsXPTParamInfo* aParamInfo)
749 {
750 nsresult rv;
751 PRUint32 count;
752 switch (aType->TagPart()) {
753 case nsXPTType::T_I8:
754 rv = out->Write("byte", 4, &count);
755 break;
756
757 case nsXPTType::T_I16:
758 case nsXPTType::T_U8:
759 rv = out->Write("short", 5, &count);
760 break;
761
762 case nsXPTType::T_I32:
763 case nsXPTType::T_U16:
764 rv = out->Write("int", 3, &count);
765 break;
766
767 case nsXPTType::T_I64:
768 case nsXPTType::T_U32:
769 rv = out->Write("long", 4, &count);
770 break;
771
772 case nsXPTType::T_FLOAT:
773 rv = out->Write("float", 5, &count);
774 break;
775
776 // XXX how should we handle 64-bit values?
777 case nsXPTType::T_U64:
778 case nsXPTType::T_DOUBLE:
779 rv = out->Write("double", 6, &count);
780 break;
781
782 case nsXPTType::T_BOOL:
783 rv = out->Write("boolean", 7, &count);
784 break;
785
786 case nsXPTType::T_CHAR:
787 case nsXPTType::T_WCHAR:
788 rv = out->Write("char", 4, &count);
789 break;
790
791 case nsXPTType::T_CHAR_STR:
792 case nsXPTType::T_WCHAR_STR:
793 case nsXPTType::T_IID:
794 case nsXPTType::T_ASTRING:
795 case nsXPTType::T_DOMSTRING:
796 case nsXPTType::T_UTF8STRING:
797 case nsXPTType::T_CSTRING:
798 case nsXPTType::T_PSTRING_SIZE_IS:
799 case nsXPTType::T_PWSTRING_SIZE_IS:
800 rv = out->Write("String", 6, &count);
801 break;
802
803 case nsXPTType::T_INTERFACE:
804 {
805 char* iface_name = nsnull;
806 rv = TypeInfo::GetInterfaceName(aIInfo, aMethodIndex, aParamInfo,
807 &iface_name);
808 if (NS_FAILED(rv) || !iface_name) {
809 rv = NS_ERROR_FAILURE;
810 break;
811 }
812
813 rv = out->Write(iface_name, strlen(iface_name), &count);
814 nsMemory::Free(iface_name);
815 break;
816 }
817
818 case nsXPTType::T_INTERFACE_IS:
819 rv = out->Write("nsISupports", 11, &count);
820 break;
821
822 case nsXPTType::T_VOID:
823 rv = out->Write("int", 3, &count);
824 break;
825
826 case nsXPTType::T_ARRAY:
827 {
828 // get array type
829 nsXPTType xpttype;
830 rv = aIInfo->GetTypeForParam(aMethodIndex, aParamInfo, 1, &xpttype);
831 if (NS_FAILED(rv))
832 break;
833
834 rv = WriteType(out, &xpttype, aIInfo, aMethodIndex, aParamInfo);
835 if (NS_FAILED(rv))
836 break;
837
838 rv = out->Write("[]", 2, &count);
839 break;
840 }
841
842 default:
843 fprintf(stderr, "WARNING: unexpected parameter type %d\n",
844 aType->TagPart());
845 return NS_ERROR_UNEXPECTED;
846 }
847
848 return rv;
849 }
850};
851
852void PrintUsage(char** argv)
853{
854 static const char usage_str[] =
855 "Usage: %s -d path\n"
856 " -d output directory for Java interface files\n";
857 fprintf(stderr, usage_str, argv[0]);
858}
859#ifdef VBOX
860#include <VBox/com/com.h>
861using namespace com;
862
863#include <iprt/initterm.h>
864#include <iprt/string.h>
865#include <iprt/alloca.h>
866#include <iprt/stream.h>
867#endif
868
869int main(int argc, char** argv)
870{
871 nsresult rv = NS_OK;
872 nsCOMPtr<nsILocalFile> output_dir;
873
874#ifdef VBOX
875#if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
876 rv = RTR3Init();
877#else
878 const char *home = getenv("VBOX_PROGRAM_PATH");
879 if (home) {
880 size_t len = strlen(home);
881 char *exepath = (char *)alloca(len + 32);
882 memcpy(exepath, home, len);
883 memcpy(exepath + len, "/pythonfake", sizeof("/pythonfake"));
884 rv = RTR3InitWithProgramPath(exepath);
885 } else {
886 rv = RTR3Init();
887 }
888#endif
889#endif
890
891 // handle command line arguments
892 for (int i = 1; i < argc; i++) {
893 if (argv[i][0] != '-') {
894 rv = NS_ERROR_FAILURE;
895 break;
896 }
897
898 switch (argv[i][1]) {
899 case 'd': {
900 if (i + 1 == argc) {
901 fprintf(stderr, "ERROR: missing output directory after -d\n");
902 rv = NS_ERROR_FAILURE;
903 break;
904 }
905
906 // see if given path exists
907 rv = NS_NewNativeLocalFile(nsDependentCString(argv[++i]), PR_TRUE,
908 getter_AddRefs(output_dir));
909 PRBool val;
910 if (NS_FAILED(rv) || NS_FAILED(output_dir->Exists(&val)) || !val ||
911 NS_FAILED(output_dir->IsDirectory(&val)) || !val)
912 {
913 fprintf(stderr,
914 "ERROR: output directory doesn't exist / isn't a directory\n");
915 rv = NS_ERROR_FAILURE;
916 break;
917 }
918
919 break;
920 }
921
922 default: {
923 fprintf(stderr, "ERROR: unknown option %s\n", argv[i]);
924 rv = NS_ERROR_FAILURE;
925 break;
926 }
927 }
928 }
929
930 if (NS_FAILED(rv)) {
931 PrintUsage(argv);
932 return 1;
933 }
934
935#ifdef VBOX
936 rv = com::Initialize();
937#else
938 rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
939#endif
940 NS_ENSURE_SUCCESS(rv, rv);
941
942 Generate gen(output_dir);
943 rv = gen.GenerateInterfaces();
944
945#ifdef VBOX
946 // very short-living XPCOM processes trigger problem on shutdown - ignoring it not a big deal anyway
947 //com::Shutdown();
948#else
949 NS_ShutdownXPCOM(nsnull);
950#endif
951 return rv;
952}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette