diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp | |
parent | Initial commit. (diff) | |
download | virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp')
-rw-r--r-- | src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp | 952 |
1 files changed, 952 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp b/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp new file mode 100644 index 00000000..60648beb --- /dev/null +++ b/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp @@ -0,0 +1,952 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Java XPCOM Bindings. + * + * The Initial Developer of the Original Code is + * IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 2005 + * IBM Corporation. All Rights Reserved. + * + * Contributor(s): + * Javier Pedemonte (jhpedemonte@gmail.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsXPCOM.h" +#include "nsString.h" +#include "nsILocalFile.h" +#include "nsIInterfaceInfoManager.h" +#include "xptinfo.h" +#include "nsCOMPtr.h" +#include "prmem.h" +#include "xptcall.h" +#ifdef VBOX +#include "nsFileStreams.h" +static nsresult +NS_NewLocalFileInputStream(nsIInputStream **aResult, + nsIFile *aFile, + PRInt32 aIOFlags = -1, + PRInt32 aPerm = -1, + PRInt32 aBehaviorFlags = 0) +{ + nsFileInputStream* in = new nsFileInputStream(); + nsresult rv; + + rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags); + if (NS_SUCCEEDED(rv)) + NS_ADDREF(*aResult = in); + + return rv; +} + +inline nsresult +NS_NewLocalFileOutputStream(nsIOutputStream **aResult, + nsIFile *aFile, + PRInt32 aIOFlags = -1, + PRInt32 aPerm = -1, + PRInt32 aBehaviorFlags = 0) +{ + nsFileOutputStream* in = new nsFileOutputStream(); + nsresult rv; + + rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags); + if (NS_SUCCEEDED(rv)) + NS_ADDREF(*aResult = in); + + return rv; +} + + +#else +#include "nsNetUtil.h" +#endif +#include "nsHashSets.h" +#include "nsIWeakReference.h" +#include <stdio.h> + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +#define WRITE_NOSCRIPT_METHODS + + +class TypeInfo +{ +public: + static nsresult GetParentInfo(nsIInterfaceInfo* aIInfo, + nsIInterfaceInfo** aParentInfo, + PRUint16* aParentMethodCount, + PRUint16* aParentConstCount) + { + nsCOMPtr<nsIInterfaceInfo> parent; + nsresult rv = aIInfo->GetParent(getter_AddRefs(parent)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!parent) { + *aParentInfo = nsnull; + *aParentMethodCount = 0; + return NS_OK; + } + + rv = parent->GetMethodCount(aParentMethodCount); + NS_ENSURE_SUCCESS(rv, rv); + rv = parent->GetConstantCount(aParentConstCount); + NS_ENSURE_SUCCESS(rv, rv); + + *aParentInfo = parent; + NS_ADDREF(*aParentInfo); + return rv; + } + + static nsresult GetInterfaceName(nsIInterfaceInfo* aIInfo, + PRUint16 aMethodIndex, + const nsXPTParamInfo* aParamInfo, + char** aResult) + { + static const char isupp_str[] = "nsISupports"; + + nsIID* iid; + nsresult rv = aIInfo->GetIIDForParam(aMethodIndex, aParamInfo, &iid); + if (NS_FAILED(rv)) { + // GetIIDForParam will sometimes fail to find an interface, particularly + // if that interface is not defined in an IDL file. In those cases, just + // return |nsISupports|. + // + // For example, the |onStreamComplete| method for the interface + // |nsIUnicharStreamLoaderObserver| takes a param of + // |nsIUnicharInputStream|, which is defined in a simple header file, not + // an IDL file. + *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str)); + rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + + } else { + + // In Javaconnect, we handle weak references internally; no need for the + // |nsIWeakReference| interface. So just return |nsISupports|. + if (iid->Equals(NS_GET_IID(nsIWeakReference))) { + *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str)); + rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + + } else { + + // Some methods take parameters of non-scriptable interfaces. But we + // only output scriptable interfaces. So if one of the param types is + // a non-scriptable interface, output |nsISupports| instead of the + // interface name. + nsCOMPtr<nsIInterfaceInfo> info; + nsCOMPtr<nsIInterfaceInfoManager> iim = + getter_AddRefs(XPTI_GetInterfaceInfoManager()); + NS_ASSERTION(iim, "could not get interface info manager"); + rv = iim->GetInfoForIID(iid, getter_AddRefs(info)); + NS_ENSURE_SUCCESS(rv, rv); + PRBool scriptable; + if (NS_SUCCEEDED(rv)) { + info->IsScriptable(&scriptable); + } + if (NS_FAILED(rv) || !scriptable) { + *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str)); + rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } else { + + // If is scriptable, get name for given IID + rv = iim->GetNameForIID(iid, aResult); + } + } + + nsMemory::Free(iid); + } + + return rv; + } +}; + + +static const char* kJavaKeywords[] = { + "abstract", "default", "if" , "private" , "this" , + "boolean" , "do" , "implements", "protected" , "throw" , + "break" , "double" , "import", "public" , "throws" , + "byte" , "else" , "instanceof", "return" , "transient", + "case" , "extends", "int" , "short" , "try" , + "catch" , "final" , "interface" , "static" , "void" , + "char" , "finally", "long" , "strictfp" , "volatile" , + "class" , "float" , "native" , "super" , "while" , + "const" , "for" , "new" , "switch" , + "continue", "goto" , "package" , "synchronized", + "assert" , /* added in Java 1.4 */ + "enum" , /* added in Java 5.0 */ + "clone" , /* clone is a member function of java.lang.Object */ + "finalize" /* finalize is a member function of java.lang.Object */ +}; + +#ifdef WRITE_NOSCRIPT_METHODS +// SWT uses [noscript] methods of the following interfaces, so we need to +// output the [noscript] methods for these interfaces. +static const char* kNoscriptMethodIfaces[] = { + "nsIBaseWindow", "nsIEmbeddingSiteWindow" +}; +#endif + + +class Generate +{ + nsILocalFile* mOutputDir; + nsCStringHashSet mIfaceTable; + nsCStringHashSet mJavaKeywords; +#ifdef WRITE_NOSCRIPT_METHODS + nsCStringHashSet mNoscriptMethodsTable; +#endif + +public: + Generate(nsILocalFile* aOutputDir) + : mOutputDir(aOutputDir) + { + mIfaceTable.Init(100); + + PRUint32 size = NS_ARRAY_LENGTH(kJavaKeywords); + mJavaKeywords.Init(size); + for (PRUint32 i = 0; i < size; i++) { + mJavaKeywords.Put(nsDependentCString(kJavaKeywords[i])); + } + +#ifdef WRITE_NOSCRIPT_METHODS + size = NS_ARRAY_LENGTH(kNoscriptMethodIfaces); + mNoscriptMethodsTable.Init(size); + for (PRUint32 j = 0; j < size; j++) { + mNoscriptMethodsTable.Put(nsDependentCString(kNoscriptMethodIfaces[j])); + } +#endif + } + + ~Generate() + { + } + + nsresult GenerateInterfaces() + { + nsresult rv; + + nsCOMPtr<nsIInterfaceInfoManager> iim = + getter_AddRefs(XPTI_GetInterfaceInfoManager()); + NS_ASSERTION(iim, "could not get interface info manager"); + nsCOMPtr<nsIEnumerator> etor; + rv = iim->EnumerateInterfaces(getter_AddRefs(etor)); + NS_ENSURE_SUCCESS(rv, rv); + + // loop over interfaces + etor->First(); + do { + // get current interface + nsCOMPtr<nsISupports> item; + rv = etor->CurrentItem(getter_AddRefs(item)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(item)); + if (!iface) + break; + + // we only care about scriptable interfaces, so skip over those + // that aren't + PRBool scriptable; + iface->IsScriptable(&scriptable); + if (!scriptable) { + // XXX SWT uses non-scriptable interface 'nsIAppShell' (bug 270892), so + // include that one. + const char* iface_name; + iface->GetNameShared(&iface_name); + if (strcmp("nsIAppShell", iface_name) != 0) + continue; + } + + rv = WriteOneInterface(iface); + NS_ENSURE_SUCCESS(rv, rv); + + } while (NS_SUCCEEDED(etor->Next())); + + return NS_OK; + } + + nsresult WriteOneInterface(nsIInterfaceInfo* aIInfo) + { + nsresult rv; + + // write each interface only once + const char* iface_name; + aIInfo->GetNameShared(&iface_name); + if (mIfaceTable.Contains(nsDependentCString(iface_name))) + return NS_OK; + + // write any parent interface + nsCOMPtr<nsIInterfaceInfo> parentInfo; + PRUint16 parentMethodCount, parentConstCount; + rv = TypeInfo::GetParentInfo(aIInfo, getter_AddRefs(parentInfo), + &parentMethodCount, &parentConstCount); + NS_ENSURE_SUCCESS(rv, rv); + if (parentInfo) + WriteOneInterface(parentInfo); + + mIfaceTable.Put(nsDependentCString(iface_name)); + + // create file for interface + nsCOMPtr<nsIOutputStream> out; + rv = OpenIfaceFileStream(iface_name, getter_AddRefs(out)); + NS_ENSURE_SUCCESS(rv, rv); + + // write contents to file + rv = WriteHeader(out, iface_name); + NS_ENSURE_SUCCESS(rv, rv); + rv = WriteInterfaceStart(out, aIInfo, parentInfo); + NS_ENSURE_SUCCESS(rv, rv); + rv = WriteIID(out, aIInfo); + NS_ENSURE_SUCCESS(rv, rv); + rv = WriteConstants(out, aIInfo, parentConstCount); + NS_ENSURE_SUCCESS(rv, rv); + rv = WriteMethods(out, aIInfo, parentMethodCount); + NS_ENSURE_SUCCESS(rv, rv); + rv = WriteInterfaceEnd(out); + NS_ENSURE_SUCCESS(rv, rv); + + rv = CloseIfaceFileStream(out); + + return rv; + } + + nsresult OpenIfaceFileStream(const char* aIfaceName, + nsIOutputStream** aResult) + { + nsresult rv; + + // create interface file in output dir + nsCOMPtr<nsIFile> iface_file; + rv = mOutputDir->Clone(getter_AddRefs(iface_file)); + NS_ENSURE_SUCCESS(rv, rv); + nsAutoString filename; + filename.AppendASCII(aIfaceName); + filename.AppendLiteral(".java"); + rv = iface_file->Append(filename); + NS_ENSURE_SUCCESS(rv, rv); + + // create interface file + PRBool exists; + iface_file->Exists(&exists); + if (exists) + iface_file->Remove(PR_FALSE); + rv = iface_file->Create(nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_SUCCESS(rv, rv); + + // create output stream for writing to file + nsCOMPtr<nsIOutputStream> out; + rv = NS_NewLocalFileOutputStream(getter_AddRefs(out), iface_file); + NS_ENSURE_SUCCESS(rv, rv); + + *aResult = out; + NS_ADDREF(*aResult); + return NS_OK; + } + + nsresult CloseIfaceFileStream(nsIOutputStream* out) + { + return out->Close(); + } + + nsresult WriteHeader(nsIOutputStream* out, const char* aIfaceName) + { + static const char kHeader1[] = + "/**\n" + " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n" + " * FOR THE FULL DOCUMENTION AND LICENSE.\n" + " *\n" + " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string="; + static const char kHeader2[]= "\">\n **/\n\n"; + static const char kPackage[] = "package org.mozilla.interfaces;\n\n"; + + PRUint32 count; + nsresult rv = out->Write(kHeader1, sizeof(kHeader1) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + + nsCAutoString searchTerm; + searchTerm.AppendLiteral("interface+"); + searchTerm.AppendASCII(aIfaceName); + // LXR limits to 29 chars + rv = out->Write(searchTerm.get(), PR_MIN(29, searchTerm.Length()), &count); + NS_ENSURE_SUCCESS(rv, rv); + + rv = out->Write(kHeader2, sizeof(kHeader2) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(kPackage, sizeof(kPackage) - 1, &count); + return rv; + } + + nsresult WriteInterfaceStart(nsIOutputStream* out, nsIInterfaceInfo* aIInfo, + nsIInterfaceInfo* aParentInfo) + { + static const char kIfaceDecl1[] = "public interface "; + static const char kParentDecl[] = " extends "; + static const char kIfaceDecl2[] = "\n{\n"; + + const char* iface_name; + aIInfo->GetNameShared(&iface_name); + PRUint32 count; + nsresult rv = out->Write(kIfaceDecl1, sizeof(kIfaceDecl1) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(iface_name, strlen(iface_name), &count); + NS_ENSURE_SUCCESS(rv, rv); + + if (aParentInfo) { + const char* parent_name; + aParentInfo->GetNameShared(&parent_name); + rv = out->Write(kParentDecl, sizeof(kParentDecl) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(parent_name, strlen(parent_name), &count); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = out->Write(kIfaceDecl2, sizeof(kIfaceDecl2) - 1, &count); + return rv; + } + + nsresult WriteInterfaceEnd(nsIOutputStream* out) + { + PRUint32 count; + return out->Write("}\n", 2, &count); + } + + nsresult WriteIID(nsIOutputStream* out, nsIInterfaceInfo* aIInfo) + { + static const char kIIDDecl1[] = " public static final String "; + static const char kIIDDecl2[] = " =\n \""; + static const char kIIDDecl3[] = "\";\n\n"; + + nsIID* iid = nsnull; + aIInfo->GetInterfaceIID(&iid); + if (!iid) + return NS_ERROR_OUT_OF_MEMORY; + + // create iid field name + nsCAutoString iid_name; + const char* iface_name; + aIInfo->GetNameShared(&iface_name); + if (strncmp("ns", iface_name, 2) == 0) { + iid_name.AppendLiteral("NS_"); + iid_name.Append(iface_name + 2); + } else { + iid_name.Append(iface_name); + } + iid_name.AppendLiteral("_IID"); + ToUpperCase(iid_name); + + // get iid string + char* iid_str = iid->ToString(); + if (!iid_str) + return NS_ERROR_OUT_OF_MEMORY; + + PRUint32 count; + nsresult rv = out->Write(kIIDDecl1, sizeof(kIIDDecl1) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(iid_name.get(), iid_name.Length(), &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(kIIDDecl2, sizeof(kIIDDecl2) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(iid_str, strlen(iid_str), &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(kIIDDecl3, sizeof(kIIDDecl3) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + + // cleanup + PR_Free(iid_str); + nsMemory::Free(iid); + return NS_OK; + } + + nsresult WriteConstants(nsIOutputStream* out, nsIInterfaceInfo* aIInfo, + PRUint16 aParentConstCount) + { + static const char kConstDecl1[] = " public static final "; + static const char kConstDecl2[] = " = "; + static const char kConstDecl3[] = ";\n\n"; + + PRUint16 constCount; + nsresult rv = aIInfo->GetConstantCount(&constCount); + NS_ENSURE_SUCCESS(rv, rv); + + for (PRUint16 i = aParentConstCount; i < constCount; i++) { + const nsXPTConstant* constInfo; + rv = aIInfo->GetConstant(i, &constInfo); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 count; + rv = out->Write(kConstDecl1, sizeof(kConstDecl1) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + const nsXPTType &type = constInfo->GetType(); + rv = WriteType(out, &type, aIInfo, nsnull, nsnull); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(" ", 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + const char* name = constInfo->GetName(); + rv = out->Write(name, strlen(name), &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(kConstDecl2, sizeof(kConstDecl2) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + + rv = WriteConstantValue(out, &type, constInfo->GetValue()); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(kConstDecl3, sizeof(kConstDecl3) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; + } + + nsresult WriteConstantValue(nsIOutputStream* out, const nsXPTType* aType, + const nsXPTCMiniVariant* aValue) + { + char buf[32]; + switch (aType->TagPart()) { + case nsXPTType::T_I8: + snprintf(buf, sizeof(buf), "%d", aValue->val.i8); + break; + + case nsXPTType::T_U8: + snprintf(buf, sizeof(buf), "%u", aValue->val.u8); + break; + + case nsXPTType::T_I16: + snprintf(buf, sizeof(buf), "%d", aValue->val.i16); + break; + + case nsXPTType::T_U16: + snprintf(buf, sizeof(buf), "%u", aValue->val.u16); + break; + + case nsXPTType::T_I32: + snprintf(buf, sizeof(buf), "%d", aValue->val.i32); + break; + + case nsXPTType::T_U32: + snprintf(buf, sizeof(buf), "%uL", aValue->val.u32); + break; + + case nsXPTType::T_I64: + snprintf(buf, sizeof(buf), "%lldL", aValue->val.i64); + break; + + case nsXPTType::T_U64: + snprintf(buf, sizeof(buf), "%lluL", aValue->val.u64); + break; + + case nsXPTType::T_FLOAT: + snprintf(buf, sizeof(buf), "%f", aValue->val.f); + break; + + case nsXPTType::T_DOUBLE: + snprintf(buf, sizeof(buf), "%f", aValue->val.d); + break; + + case nsXPTType::T_BOOL: + if (aValue->val.b) + sprintf(buf, "true"); + else + sprintf(buf, "false"); + break; + + case nsXPTType::T_CHAR: + snprintf(buf, sizeof(buf), "%c", aValue->val.c); + break; + + case nsXPTType::T_WCHAR: + snprintf(buf, sizeof(buf), "%c", aValue->val.wc); + break; + + default: + NS_WARNING("unexpected constant type"); + return NS_ERROR_UNEXPECTED; + } + + PRUint32 count; + return out->Write(buf, strlen(buf), &count); + } + + nsresult WriteMethods(nsIOutputStream* out, nsIInterfaceInfo* aIInfo, + PRUint16 aParentMethodCount) + { + PRUint16 methodCount; + nsresult rv = aIInfo->GetMethodCount(&methodCount); + NS_ENSURE_SUCCESS(rv, rv); + +#ifdef DEBUG_bird /* attributes first, then method. For making diffing easier. */ + for (int pass = 0; pass < 2; pass++) +#endif + for (PRUint16 i = aParentMethodCount; i < methodCount; i++) { + const nsXPTMethodInfo* methodInfo; + rv = aIInfo->GetMethodInfo(i, &methodInfo); + NS_ENSURE_SUCCESS(rv, rv); + +#ifdef WRITE_NOSCRIPT_METHODS + // XXX + // SWT makes use of [noscript] methods in some classes, so output them + // for those classes. + + // skip [notxpcom] methods + if (methodInfo->IsNotXPCOM()) + continue; + + // skip most hidden ([noscript]) methods + if (methodInfo->IsHidden()) { + const char* iface_name; + aIInfo->GetNameShared(&iface_name); + if (!mNoscriptMethodsTable.Contains(nsDependentCString(iface_name))) + continue; + } +#else + // skip hidden ([noscript]) or [notxpcom] methods + if (methodInfo->IsHidden() || methodInfo->IsNotXPCOM()) + continue; +#endif +#ifdef DEBUG_bird /* attributes first, then method. For making diffing easier. */ + if ((methodInfo->IsSetter() || methodInfo->IsGetter()) == pass) + continue; +#endif + + rv = WriteOneMethod(out, aIInfo, methodInfo, i); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; + } + + nsresult WriteOneMethod(nsIOutputStream* out, nsIInterfaceInfo* aIInfo, + const nsXPTMethodInfo* aMethodInfo, + PRUint16 aMethodIndex) + { + static const char kMethodDecl1[] = " public "; + static const char kVoidReturn[] = "void"; + static const char kParamSeparator[] = ", "; + static const char kMethodDecl2[] = ");\n\n"; + + PRUint32 count; + nsresult rv = out->Write(kMethodDecl1, sizeof(kMethodDecl1) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + + // write return type + PRUint8 paramCount = aMethodInfo->GetParamCount(); + const nsXPTParamInfo* resultInfo = nsnull; + for (PRUint8 i = 0; i < paramCount; i++) { + const nsXPTParamInfo ¶mInfo = aMethodInfo->GetParam(i); + if (paramInfo.IsRetval()) { + resultInfo = ¶mInfo; + break; + } + } + if (resultInfo) { + rv = WriteParam(out, aIInfo, aMethodIndex, resultInfo, 0); + } else { + rv = out->Write(kVoidReturn, sizeof(kVoidReturn) - 1, &count); + } + NS_ENSURE_SUCCESS(rv, rv); + + // write method name string + nsCAutoString method_name; + const char* name = aMethodInfo->GetName(); + if (aMethodInfo->IsGetter() || aMethodInfo->IsSetter()) { + if (aMethodInfo->IsGetter()) + method_name.AppendLiteral("get"); + else + method_name.AppendLiteral("set"); + method_name.Append(toupper(name[0])); + method_name.AppendASCII(name + 1); + } else { + method_name.Append(tolower(name[0])); + method_name.AppendASCII(name + 1); + // don't use Java keywords as method names + if (mJavaKeywords.Contains(method_name)) + method_name.Append('_'); + } + rv = out->Write(" ", 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write(method_name.get(), method_name.Length(), &count); + NS_ENSURE_SUCCESS(rv, rv); + rv = out->Write("(", 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + + // write parameters + for (PRUint8 j = 0; j < paramCount; j++) { + const nsXPTParamInfo ¶mInfo = aMethodInfo->GetParam(j); + if (paramInfo.IsRetval()) + continue; + + if (j != 0) { + rv = out->Write(kParamSeparator, sizeof(kParamSeparator) - 1, &count); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = WriteParam(out, aIInfo, aMethodIndex, ¶mInfo, j + 1); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = out->Write(kMethodDecl2, sizeof(kMethodDecl2) - 1, &count); + return rv; + } + + nsresult WriteParam(nsIOutputStream* out, nsIInterfaceInfo* aIInfo, + PRUint16 aMethodIndex, const nsXPTParamInfo* aParamInfo, + PRUint8 aIndex) + { + const nsXPTType &type = aParamInfo->GetType(); + nsresult rv = WriteType(out, &type, aIInfo, aMethodIndex, aParamInfo); + NS_ENSURE_SUCCESS(rv, rv); + + // if parameter is 'out' or 'inout', make it a Java array + PRUint32 count; + if (aParamInfo->IsOut() && !aParamInfo->IsRetval()) { + rv = out->Write("[]", 2, &count); + NS_ENSURE_SUCCESS(rv, rv); + } + + // write name for parameter (but not for 'retval' param) + if (aIndex) { + char buf[10]; + snprintf(buf, sizeof(buf), " arg%d", aIndex); + rv = out->Write(buf, strlen(buf), &count); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; + } + + /** + * Write out the Java type for the given XPIDL type. + * + * NOTE: Java doesn't support unsigned types. So for any unsigned XPIDL type, + * we move up to the next largest Java type. This way we ensure that we don't + * lose any info. + */ + nsresult WriteType(nsIOutputStream* out, const nsXPTType* aType, + nsIInterfaceInfo* aIInfo, PRUint16 aMethodIndex, + const nsXPTParamInfo* aParamInfo) + { + nsresult rv; + PRUint32 count; + switch (aType->TagPart()) { + case nsXPTType::T_I8: + rv = out->Write("byte", 4, &count); + break; + + case nsXPTType::T_I16: + case nsXPTType::T_U8: + rv = out->Write("short", 5, &count); + break; + + case nsXPTType::T_I32: + case nsXPTType::T_U16: + rv = out->Write("int", 3, &count); + break; + + case nsXPTType::T_I64: + case nsXPTType::T_U32: + rv = out->Write("long", 4, &count); + break; + + case nsXPTType::T_FLOAT: + rv = out->Write("float", 5, &count); + break; + + // XXX how should we handle 64-bit values? + case nsXPTType::T_U64: + case nsXPTType::T_DOUBLE: + rv = out->Write("double", 6, &count); + break; + + case nsXPTType::T_BOOL: + rv = out->Write("boolean", 7, &count); + break; + + case nsXPTType::T_CHAR: + case nsXPTType::T_WCHAR: + rv = out->Write("char", 4, &count); + break; + + case nsXPTType::T_CHAR_STR: + case nsXPTType::T_WCHAR_STR: + case nsXPTType::T_IID: + case nsXPTType::T_ASTRING: + case nsXPTType::T_DOMSTRING: + case nsXPTType::T_UTF8STRING: + case nsXPTType::T_CSTRING: + case nsXPTType::T_PSTRING_SIZE_IS: + case nsXPTType::T_PWSTRING_SIZE_IS: + rv = out->Write("String", 6, &count); + break; + + case nsXPTType::T_INTERFACE: + { + char* iface_name = nsnull; + rv = TypeInfo::GetInterfaceName(aIInfo, aMethodIndex, aParamInfo, + &iface_name); + if (NS_FAILED(rv) || !iface_name) { + rv = NS_ERROR_FAILURE; + break; + } + + rv = out->Write(iface_name, strlen(iface_name), &count); + nsMemory::Free(iface_name); + break; + } + + case nsXPTType::T_INTERFACE_IS: + rv = out->Write("nsISupports", 11, &count); + break; + + case nsXPTType::T_VOID: + rv = out->Write("int", 3, &count); + break; + + case nsXPTType::T_ARRAY: + { + // get array type + nsXPTType xpttype; + rv = aIInfo->GetTypeForParam(aMethodIndex, aParamInfo, 1, &xpttype); + if (NS_FAILED(rv)) + break; + + rv = WriteType(out, &xpttype, aIInfo, aMethodIndex, aParamInfo); + if (NS_FAILED(rv)) + break; + + rv = out->Write("[]", 2, &count); + break; + } + + default: + fprintf(stderr, "WARNING: unexpected parameter type %d\n", + aType->TagPart()); + return NS_ERROR_UNEXPECTED; + } + + return rv; + } +}; + +void PrintUsage(char** argv) +{ + static const char usage_str[] = + "Usage: %s -d path\n" + " -d output directory for Java interface files\n"; + fprintf(stderr, usage_str, argv[0]); +} +#ifdef VBOX +#include <VBox/com/com.h> +using namespace com; + +#include <iprt/initterm.h> +#include <iprt/string.h> +#include <iprt/alloca.h> +#include <iprt/stream.h> +#endif + +int main(int argc, char** argv) +{ + nsresult rv = NS_OK; + nsCOMPtr<nsILocalFile> output_dir; + +#ifdef VBOX +#if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS) + rv = RTR3InitExe(argc, &argv, 0); +#else + const char *pszHome = getenv("VBOX_PROGRAM_PATH"); + if (pszHome) { + size_t cchHome = strlen(pszHome); + char *pszExePath = (char *)alloca(cchHome + 32); + memcpy(pszExePath, pszHome, cchHome); + memcpy(pszExePath + cchHome, "/pythonfake", sizeof("/pythonfake")); + rc = RTR3InitEx(RTR3INIT_VER_CUR, 0, argc, &argv, pszExePath); + } else { + rv = RTR3InitExe(argc, &argv, 0); + } +#endif +#endif + + // handle command line arguments + for (int i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + rv = NS_ERROR_FAILURE; + break; + } + + switch (argv[i][1]) { + case 'd': { + if (i + 1 == argc) { + fprintf(stderr, "ERROR: missing output directory after -d\n"); + rv = NS_ERROR_FAILURE; + break; + } + + // see if given path exists + rv = NS_NewNativeLocalFile(nsDependentCString(argv[++i]), PR_TRUE, + getter_AddRefs(output_dir)); + PRBool val; + if (NS_FAILED(rv) || NS_FAILED(output_dir->Exists(&val)) || !val || + NS_FAILED(output_dir->IsDirectory(&val)) || !val) + { + fprintf(stderr, + "ERROR: output directory doesn't exist / isn't a directory\n"); + rv = NS_ERROR_FAILURE; + break; + } + + break; + } + + default: { + fprintf(stderr, "ERROR: unknown option %s\n", argv[i]); + rv = NS_ERROR_FAILURE; + break; + } + } + } + + if (NS_FAILED(rv)) { + PrintUsage(argv); + return 1; + } + +#ifdef VBOX + rv = com::Initialize(); +#else + rv = NS_InitXPCOM2(nsnull, nsnull, nsnull); +#endif + NS_ENSURE_SUCCESS(rv, rv); + + Generate gen(output_dir); + rv = gen.GenerateInterfaces(); + +#ifdef VBOX + // very short-living XPCOM processes trigger problem on shutdown - ignoring it not a big deal anyway + //com::Shutdown(); +#else + NS_ShutdownXPCOM(nsnull); +#endif + return rv; +} |