diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/libs/xpcom18a4/xpcom/typelib | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/typelib')
48 files changed, 13894 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/typelib/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/typelib/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/Makefile.in new file mode 100644 index 00000000..43d92023 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/Makefile.in @@ -0,0 +1,49 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +DIRS = xpt xpidl + +include $(topsrcdir)/config/rules.mk + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore new file mode 100644 index 00000000..8e5eac0d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore @@ -0,0 +1,2 @@ +xpidl +Makefile diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in new file mode 100644 index 00000000..ae228ef0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in @@ -0,0 +1,88 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +PROGRAM = xpidl$(BIN_SUFFIX) +INTERNAL_TOOLS = 1 + +# glib and libIDL link against the non-debug msvcrt +MOZ_NO_DEBUG_RTL=1 + +CSRCS = \ + xpidl.c \ + xpidl_idl.c \ + xpidl_util.c \ + xpidl_header.c \ + xpidl_typelib.c \ + xpidl_doc.c \ + xpidl_java.c \ + $(NULL) + +SDK_BINARY = \ + $(PROGRAM) \ + $(NULL) + +ifdef CROSS_COMPILE +HOST_PROGRAM = host_xpidl$(HOST_BIN_SUFFIX) +HOST_CSRCS = $(CSRCS) +endif + +include $(topsrcdir)/config/rules.mk + +CFLAGS += $(LIBIDL_CFLAGS) + +# Compile directly against the static lib, so we can use xpidl during the build +# without the shared library path being set. +ifeq (WINNT,$(OS_ARCH)) +DEFINES += -DEXPORT_XPT_API +ifndef GNU_CC +LDFLAGS += -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRTD +endif +endif + +# Tell the $(PROGRAM) target that we need to be recompiled when libxpt changes. +LIBS = $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX) $(LIBIDL_LIBS) +EXTRA_DEPS = $(wildcard $(DIST)/lib/$(LIB_PREFIX)xpt.*) + +ifdef CROSS_COMPILE +HOST_CFLAGS += $(HOST_LIBIDL_CFLAGS) +HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX) $(HOST_LIBIDL_LIBS) +HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*) + +ifdef HOST_NSPR_MDCPUCFG +HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG) +endif +endif + +ifdef MACOS_SDK_DIR +NEXT_ROOT= +OS_LIBS := $(patsubst -L$(MACOS_SDK_DIR)/usr/lib%,,$(OS_LIBS)) +endif + +export:: + @$(MAKE) libs diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/README b/src/libs/xpcom18a4/xpcom/typelib/xpidl/README new file mode 100644 index 00000000..b7a400e0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/README @@ -0,0 +1,16 @@ +Wed Dec 2 14:35:41 EST 1998 + +xpidl depends on Andrew Veliath and Elliot Lee's libIDL, a part of the +GNOME ORBit C ORB. We currently require libIDL >= 0.6.3, which in turn +requires glib >= 1.2.0. + +libIDL builds for Linux and Win32 can be found, along with source +tarballs, at http://www.rpi.edu/~veliaa/libIDL/, and Win32 users will +need glib 1.2 and glib 1.2-dev from +http://user.sgic.fi/~tml/gimp/win32/. Source and Linux RPMs are also +available from ftp://ftp.mozilla.org/pub/mozilla/libraries, and Win32 +binaries are included in the wintools.zip file at +ftp://ftp.mozilla.org/pub/mozilla/source/wintools.zip. A Mac project +is in progress, and should be appearing shortly. + +glib tarballs and RPMs for Linux can be found through http://www.gtk.org. diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc Binary files differnew file mode 100644 index 00000000..fb06f6a3 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc Binary files differnew file mode 100644 index 00000000..bec7c043 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c new file mode 100644 index 00000000..ecda11e0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c @@ -0,0 +1,139 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "mac_console.h" + +#ifndef __CONSOLE__ +#include <console.h> +#endif + +extern CWPluginContext gPluginContext; + +UInt32 mac_console_count = 0; +CWMemHandle mac_console_handle = NULL; + +/* + * The following four functions provide the UI for the console package. + * Users wishing to replace SIOUX with their own console package need + * only provide the four functions below in a library. + */ + +/* + * extern short InstallConsole(short fd); + * + * Installs the Console package, this function will be called right + * before any read or write to one of the standard streams. + * + * short fd: The stream which we are reading/writing to/from. + * returns short: 0 no error occurred, anything else error. + */ + +short InstallConsole(short fd) +{ +#pragma unused (fd) + mac_console_count = 0; + CWAllocMemHandle(gPluginContext, 8192, false, &mac_console_handle); + return 0; +} + +/* + * extern void RemoveConsole(void); + * + * Removes the console package. It is called after all other streams + * are closed and exit functions (installed by either atexit or _atexit) + * have been called. Since there is no way to recover from an error, + * this function doesn't need to return any. + */ + +void RemoveConsole(void) +{ + if (mac_console_handle != NULL) { + CWFreeMemHandle(gPluginContext, mac_console_handle); + mac_console_handle = NULL; + } +} + +/* + * extern long WriteCharsToConsole(char *buffer, long n); + * + * Writes a stream of output to the Console window. This function is + * called by write. + * + * char *buffer: Pointer to the buffer to be written. + * long n: The length of the buffer to be written. + * returns short: Actual number of characters written to the stream, + * -1 if an error occurred. + */ + +long WriteCharsToConsole(char *buffer, long n) +{ + long size = 0; + void* ptr = NULL; + + if (CWGetMemHandleSize(gPluginContext, mac_console_handle, &size) == noErr) { + if (mac_console_count + n >= size) { + size += 8192; + if (CWResizeMemHandle(gPluginContext, mac_console_handle, size) != noErr) + return -1; + } + } + + if (CWLockMemHandle(gPluginContext, mac_console_handle, false, &ptr) == noErr) { + BlockMoveData(buffer, (char *)ptr + mac_console_count, n); + mac_console_count += n; + CWUnlockMemHandle(gPluginContext, mac_console_handle); + } + + return 0; +} + +/* + * extern long ReadCharsFromConsole(char *buffer, long n); + * + * Reads from the Console into a buffer. This function is called by + * read. + * + * char *buffer: Pointer to the buffer which will recieve the input. + * long n: The maximum amount of characters to be read (size of + * buffer). + * returns short: Actual number of characters read from the stream, + * -1 if an error occurred. + */ + +long ReadCharsFromConsole(char *buffer, long n) +{ + return 0; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h new file mode 100644 index 00000000..88809f85 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h @@ -0,0 +1,49 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_console.h + */ + +#pragma once + +#include <Files.h> +#include <Memory.h> + +#include "CWPlugins.h" + +extern UInt32 mac_console_count; +extern CWMemHandle mac_console_handle; diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp new file mode 100644 index 00000000..41d03d88 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp @@ -0,0 +1,146 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_memory.cpp + */ + +#include <new.h> +#include <stdlib.h> + +#include <Files.h> +#include <Memory.h> + +#include "DropInCompilerLinker.h" +#include "CompilerMapping.h" +#include "CWPluginErrors.h" + +extern CWPluginContext gPluginContext; + +/** + * Note: memory allocated by these operators will automatically be freed after the + * current call into xpidl_compiler completes. This should be fine in most cases, + * as we are also having the compiler be reloaded for every request to reinitialize + * global data. Just be careful out there! + */ + +const Boolean kTemporaryAllocation = false; + +void* operator new(size_t size) +{ + void* ptr = NULL; + if (CWAllocateMemory(gPluginContext, size, kTemporaryAllocation, &ptr) == cwNoErr) + return ptr; + return NULL; +} + +void operator delete(void* ptr) +{ + if (ptr != NULL) + CWFreeMemory(gPluginContext, ptr, kTemporaryAllocation); +} + +void* operator new[] (size_t size) +{ + void* ptr = NULL; + if (CWAllocateMemory(gPluginContext, size, kTemporaryAllocation, &ptr) == cwNoErr) + return ptr; + return NULL; +} + +void operator delete[](void* ptr) +{ + if (ptr != NULL) + CWFreeMemory(gPluginContext, ptr, kTemporaryAllocation); +} + +namespace std { + +#define TRACK_ALLOCATION +#define kTrackedCookie 'TRKD' + +void* malloc(size_t size) +{ +#if defined(TRACK_ALLOCATION) + OSType* ptr = (OSType*) new char[sizeof(OSType) + size]; + if (ptr != NULL) + *ptr++ = kTrackedCookie; + return ptr; +#else + return new char[size]; +#endif +} + +void free(void *ptr) +{ +#if defined(TRACK_ALLOCATION) + OSType* type = (OSType*)ptr; + if (*--type == kTrackedCookie) + delete[] (char*) type; + else + DebugStr("\pillegal block passed to free."); +#else + delete[] (char*) ptr; +#endif +} + +void* calloc(size_t nmemb, size_t size) +{ + size *= nmemb; + void* ptr = malloc(size); + if (ptr != NULL) { + BlockZero(ptr, size); + } + return ptr; +} + +void* realloc(void * ptr, size_t size) +{ + void* newptr = NULL; + + if (size > 0) + newptr = malloc(size); + + if (ptr != NULL && newptr != NULL) + BlockMoveData(ptr, newptr, size); + + if (ptr != NULL) + free(ptr); + + return newptr; +} + +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp new file mode 100644 index 00000000..881dcb0b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp @@ -0,0 +1,58 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_stdlib.cpp + + replacement functions for the CodeWarrior plugin. + + by Patrick C. Beard. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <setjmp.h> + +// simply throw us out of here! + +jmp_buf exit_jump; +int exit_status = 0; + +void std::exit(int status) +{ + exit_status = status; + longjmp(exit_jump, -1); +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp new file mode 100644 index 00000000..37e389e5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp @@ -0,0 +1,38 @@ +/* + mac_strings.cpp + */ + +#include "mac_strings.h" + +#include <string.h> +#include <Memory.h> +#include <new> + +StringPtr c2p_strcpy(StringPtr pstr, const char* cstr) +{ + size_t len = ::strlen(cstr); + if (len > 255) len = 255; + BlockMoveData(cstr, pstr + 1, len); + pstr[0] = len; + return pstr; +} + +char* p2c_strcpy(char* cstr, const StringPtr pstr) +{ + size_t len = pstr[0]; + BlockMoveData(pstr + 1, cstr, len); + cstr[len] = '\0'; + return cstr; +} + +char* p2c_strdup(StringPtr pstr) +{ + size_t len = pstr[0]; + char* cstr = new char[1 + len]; + if (cstr != NULL) { + BlockMoveData(pstr + 1, cstr, len); + cstr[len] = '\0'; + } + return cstr; +} + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h new file mode 100644 index 00000000..44f39312 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h @@ -0,0 +1,47 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_strings.h + */ + +#pragma once + +#include <MacTypes.h> + +StringPtr c2p_strcpy(StringPtr pstr, const char* cstr); +char* p2c_strcpy(char* cstr, const StringPtr pstr); +char* p2c_strdup(StringPtr pstr); diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp new file mode 100644 index 00000000..49f061d9 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp @@ -0,0 +1,417 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_xpidl.cpp + + Metrowerks Codewarrior IDL plugin. + + by Patrick C. Beard. + */ + +/* standard headers */ +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <new.h> +#include <setjmp.h> + +/* system headers */ +#include <Files.h> +#include <Errors.h> +#include <Strings.h> + +#include "FullPath.h" +#include "MoreFilesExtras.h" + +/* compiler headers */ +#include "DropInCompilerLinker.h" +#include "CompilerMapping.h" +#include "CWPluginErrors.h" + +/* local headers. */ +#include "mac_xpidl.h" +#include "mac_console.h" +#include "mac_strings.h" +#include "mac_xpidl_panel.h" + +/* prototypes of local functions */ +static CWResult Compile(CWPluginContext context); +static CWResult Disassemble(CWPluginContext context); +static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file); + +/* external variables */ +extern jmp_buf exit_jump; +extern int exit_status; + +/* global variables */ +CWPluginContext gPluginContext; + +/* local variables */ +static CWFileSpec gSourceFile; +static char* gSourcePath = NULL; +static CWFileSpec gOutputFile; + +extern "C" { +pascal short xpidl_compiler(CWPluginContext context); +int xpidl_main(int argc, char* argv[]); +int xptdump_main(int argc, char* argv[]); + +FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode); +} + +pascal short xpidl_compiler(CWPluginContext context) +{ + long request; + if (CWGetPluginRequest(context, &request) != cwNoErr) + return cwErrRequestFailed; + + gPluginContext = context; + short result = cwNoErr; + + /* dispatch on compiler request */ + switch (request) { + case reqInitCompiler: + /* compiler has just been loaded into memory */ + break; + + case reqTermCompiler: + /* compiler is about to be unloaded from memory */ + break; + + case reqCompile: + /* compile a source file */ + result = Compile(context); + break; + + case reqCompDisassemble: + /* disassemble a source file */ + result = Disassemble(context); + break; + + default: + result = cwErrRequestFailed; + break; + } + + /* is this necessary? */ + CWDonePluginRequest(context, result); + + /* return result code */ + return (result); +} + +static char* full_path_to(const FSSpec& file) +{ + short len = 0; + Handle fullPath = NULL; + if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) { + char* path = new char[1 + len]; + if (path != NULL) { + BlockMoveData(*fullPath, path, len); + path[len] = '\0'; + } + DisposeHandle(fullPath); + return path; + } + return NULL; +} + +static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings) +{ + CWMemHandle settingsHand; + CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand); + if (!CWSUCCESS(err)) + return (err); + + XPIDLSettings* settingsPtr = NULL; + err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr); + if (!CWSUCCESS(err)) + return (err); + + settings = *settingsPtr; + + err = CWUnlockMemHandle(context, settingsHand); + if (!CWSUCCESS(err)) + return (err); + + return noErr; +} + +static CWResult Compile(CWPluginContext context) +{ + CWResult err = CWGetMainFileSpec(context, &gSourceFile); + if (!CWSUCCESS(err)) + return (err); + + long fileNum; + err = CWGetMainFileNumber(context, &fileNum); + if (!CWSUCCESS(err)) + return (err); + + // get the name of the source file to compile. + gSourcePath = p2c_strdup(gSourceFile.name); + if (gSourcePath == NULL) + return cwErrOutOfMemory; + + // build an argument list and call the compiler. + XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeHeader, false, false }; + GetSettings(context, settings); + +#if 0 + // if generating .xpt files, let the IDE tell us where to put the output file. + // otherwise, put them in the project's output directory. + if (settings.mode == kXPIDLModeTypelib) + err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile); + else + err = CWGetOutputFileDirectory(gPluginContext, &gOutputFile); +#else + // always generate the output file into the project target's data directory. + err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile); +#endif + if (!CWSUCCESS(err)) + return (err); + + int argc = 3; + char* modes[] = { "header", "java", "typelib", "doc" }; + char* argv[] = { "xpidl", "-m", modes[settings.mode - 1], NULL, NULL, NULL, NULL, }; + if (settings.warnings) argv[argc++] = "-w"; + if (settings.verbose) argv[argc++] = "-v"; + argv[argc++] = gSourcePath; + + if (setjmp(exit_jump) == 0) { + if (xpidl_main(argc, argv) != 0) + err = cwErrRequestFailed; + } else { + // evidently the good old exit function got called. + if (exit_status != 0) + err = cwErrRequestFailed; + } + + // if the compilation succeeded, tell CodeWarrior about the output file. + // this ensures several things: 1. if the output file is deleted by the user, + // then the IDE will know to recompile it, which is good for dirty builds, + // where the output files may be hand deleted; 2. if the user elects to remove + // objects, the output files are deleted. Thanks to robv@metrowerks.com for + // pointing this new CWPro4 API out. + if (err == cwNoErr) { + CWObjectData objectData; + BlockZero(&objectData, sizeof(objectData)); + + // for fun, show how large the output file is in the data area. + long dataSize, rsrcSize; + if (FSpGetFileSize(&gOutputFile, &dataSize, &rsrcSize) == noErr) + objectData.idatasize = dataSize; + + // tell the IDE that this file was generated by the compiler. + objectData.objectfile = &gOutputFile; + + err = CWStoreObjectData(context, fileNum, &objectData); + } else { + // an error occured, delete the output file, which might be a partial file. + if (gOutputFile.name[0] != 0) { + ::FSpDelete(&gOutputFile); + } + } + + delete[] gSourcePath; + gSourcePath = NULL; + + return (err); +} + +static CWResult Disassemble(CWPluginContext context) +{ + // the disassembly code has moved to the linker. + return noErr; +} + +static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file) +{ + /* prefill the CWFileInfo struct */ + CWFileInfo fileinfo; + BlockZero(&fileinfo, sizeof(fileinfo)); + // memset(&fileinfo, 0, sizeof(fileinfo)); + fileinfo.fullsearch = true; + fileinfo.suppressload = true; + fileinfo.dependencyType = cwNormalDependency; + fileinfo.isdependentoffile = kCurrentCompiledFile; + + /* locate the file name using the project's access paths */ + CWResult err = CWFindAndLoadFile(context, filename, &fileinfo); + if (err == cwNoErr) { + file = fileinfo.filespec; + } else if (err == cwErrFileNotFound) { + char errmsg[200]; + sprintf(errmsg, "Can't locate file \"%s\".", filename); + CWResult callbackResult = CWReportMessage(context, 0, errmsg, 0, messagetypeError, 0); + } + + return (err); +} + +/** + * Substitute for standard fopen, treats certain filenames specially, + * and also considers the mode argument. If a file is being opened + * for reading, the file is assumed to be locateable using CodeWarrior's + * standard access paths. If it's for writing, the file is opened in + * the current project's output directory. + */ +FILE* std::fopen(const char* filename, const char *mode) +{ + FSSpec filespec; + CWResult err = noErr; + do { + if (filename == gSourcePath || strcmp(filename, gSourcePath) == 0) { + // opening the main source file. + filespec = gSourceFile; + } else if (mode[0] == 'w') { + // if an output file, open it in the current compilation's output directory. + c2p_strcpy(filespec.name, filename); + filespec.vRefNum = gOutputFile.vRefNum; + filespec.parID = gOutputFile.parID; + c2p_strcpy(gOutputFile.name, filename); + } else { + // an input file, use CodeWarrior's search paths to find the named source file. + err = LocateFile(gPluginContext, filename, filespec); + } + } while (0); + // if all went well, we have a file to open. + return (err == noErr ? FSp_fopen(&filespec, mode) : NULL); +} + +/** + * Returns the length of a file, assuming it is always located in the + * project's output directory. + */ +size_t mac_get_file_length(const char* filename) +{ + long dataSize= 0, rsrcSize = 0; + FSSpec filespec; + if (CWGetOutputFileDirectory(gPluginContext, &filespec) != noErr) + return 0; + c2p_strcpy(filespec.name, filename); + if (FSpGetFileSize(&filespec, &dataSize, &rsrcSize) != noErr) + return 0; + return dataSize; +} + +void mac_warning(const char* warning_message) +{ + CWReportMessage(gPluginContext, 0, warning_message, 0, messagetypeWarning, 0); +} + +void mac_error(const char* error_message) +{ + CWReportMessage(gPluginContext, 0, error_message, 0, messagetypeError, 0); +} + +// plugin compiler exports. + +#if CW_USE_PRAGMA_EXPORT +#pragma export on +#endif + +CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize) +{ + static const DropInFlags sFlags = { + kCurrentDropInFlagsVersion, + CWDROPINCOMPILERTYPE, + DROPINCOMPILERLINKERAPIVERSION, + (kGeneratescode | /* kCandisassemble | */ kCompMultiTargAware | kCompAlwaysReload), + Lang_MISC, + DROPINCOMPILERLINKERAPIVERSION + }; + + *flags = &sFlags; + *flagsSize = sizeof(sFlags); + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName) +{ + static const char* sDropInName = "xpidl"; + + *dropinName = sDropInName; + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName) +{ + static const char* sDisplayName = "xpidl"; + + *displayName = sDisplayName; + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList) +{ + static const char* sPanelName = kXPIDLPanelName; + static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName }; + + *panelList = &sPanelList; + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList) +{ + static CWDataType sCPU = '****'; + static CWDataType sOS = '****'; + static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS }; + + *targetList = &sTargetList; + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList) +{ + static CWExtensionMapping sExtension = { 'TEXT', ".idl", 0 }; + static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension }; + + *defaultMappingList = &sExtensionMapList; + + return cwNoErr; +} + +#if CW_USE_PRAGMA_EXPORT +#pragma export off +#endif diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h new file mode 100644 index 00000000..bb1c5048 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h @@ -0,0 +1,25 @@ +/* + mac_xpidl.h + + prototypes for the Mac CodeWarrior plugin version of xpidl. + + by Patrick C. Beard. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _STDIO_H +#include <stdio.h> +#endif + +size_t mac_get_file_length(const char* filename); +void mac_warning(const char* warning_message); +void mac_error(const char* error_message); + +#ifdef __cplusplus +} +#endif diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp new file mode 100644 index 00000000..b046071d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp @@ -0,0 +1,695 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_xpidl_panel.cpp + */ + +#define CW_STRICT_DIALOGS 1 + +/* standard headers */ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +/* system headers */ +#include <AERegistry.h> +#include <Drag.h> +#include <Palettes.h> +#include <Resources.h> +#include <Scrap.h> +#include <TextUtils.h> +#include <Sound.h> + +/* compiler headers */ +#include <DropInPanel.h> + +/* project headers */ +#include "mac_xpidl_panel.h" + +enum { + kFactoryPrefsID = 128, + kCW7ItemListID = 128, + kCW8ItemListID = 129, + + kXPIDLModeItem = 1, + kXPIDLWarningsItem, + kXPIDLVerboseItem, + + kXPTLinkerOutputItem = 4 +}; + + +/* local variables */ +static RgnHandle sDragRgn; +static Boolean sHighlightOn; + + +/* prototypes of local functions */ +static short InitDialog(PanelParameterBlock *pb); +static void TermDialog(PanelParameterBlock *pb); +static void PutData(PanelParameterBlock *pb, Handle options); +static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy); +static void ByteSwapData(XPIDLSettingsHandle options); +static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit); +static void ItemHit(PanelParameterBlock *pb); +static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset); +static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings); +static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings); +static short GetFactory(Handle settings); +static short UpdatePref(Handle settings); +static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2); +static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2); +static void OutlineRect(const Rect* focusRect, Boolean outlineOn); +static OSErr DragEnter(PanelParameterBlock *pb); +static void DragWithin(PanelParameterBlock *pb); +static void DragExit(PanelParameterBlock *pb); +static void DragDrop(PanelParameterBlock *pb); + +extern "C" { + +pascal short xpidl_panel(PanelParameterBlock *pb); + +} + +/* + * main - entry-point for Drop-In Preferences Panel + * + */ + +pascal short xpidl_panel(PanelParameterBlock *pb) +{ + short result; + + result = noErr; + + switch (pb->request) + { + case reqInitPanel: + /* panel has just been loaded into memory */ + break; + + case reqTermPanel: + /* panel is about to be unloaded from memory */ + break; + + case reqFirstLoad: + /* first time panel was loaded. */ + break; + + case reqInitDialog: + /* hook our dialog item list into the preferences dialog */ + result = InitDialog(pb); + break; + + case reqTermDialog: + /* unhook our dialog item list from the preferences dialog */ + TermDialog(pb); + break; + + case reqPutData: + /* put the data in the given handle into our dialog items */ + PutData(pb, pb->currentPrefs); + break; + + case reqGetData: + /* fill in the given handle with our dialog items */ + result = GetData(pb, pb->currentPrefs, true); + break; + + case reqByteSwapData: + /* byte swap the data in the handle */ + ByteSwapData((XPIDLSettingsHandle)pb->currentPrefs); + break; + + case reqFilter: + /* filter an event in the dialog */ + result = Filter(pb, pb->event, &pb->itemHit); + break; + + case reqItemHit: + /* handle a hit on one of our dialog items */ + ItemHit(pb); + break; + + case reqDrawCustomItem: + /* handle a request to draw one of our user items (CW/8 and later) */ + break; + + case reqActivateItem: + break; + + case reqDeactivateItem: + break; + + case reqHandleKey: + break; + + case reqHandleClick: + break; + + case reqFindStatus: + break; + + case reqObeyCommand: + break; + + case reqAEGetPref: + /* return one item in the given handle as an Apple Event descriptor */ + result = GetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs); + break; + + case reqAESetPref: + /* change one item in the given handle according to the given Apple Event descriptor */ + result = SetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs); + break; + + case reqValidate: + /* determine if we need to reset paths, recompile, or relink */ + Validate(pb->originalPrefs, pb->currentPrefs, &pb->recompile, &pb->relink, &pb->reset); + break; + + case reqGetFactory: + /* return our factory settings */ + result = GetFactory(pb->factoryPrefs); + break; + + case reqUpdatePref: + /* update the given handle to use the current format for our prefs data */ + result = UpdatePref(pb->currentPrefs); + break; + + case reqDragEnter: + /* determine if we can accept the drag and, if so, start tracking */ + result = DragEnter(pb); + break; + + case reqDragWithin: + /* continue tracking */ + DragWithin(pb); + break; + + case reqDragExit: + /* stop tracking */ + DragExit(pb); + break; + + case reqDragDrop: + /* the user has dropped in our panel */ + DragDrop(pb); + break; + + default: + result = paramErr; + break; + } + + return (result); +} + +/* + * InitDialog - initialize Dialog Box items for this panel + * + */ + +static short InitDialog(PanelParameterBlock *pb) +{ + OSErr err; + + // The library function will call the IDE to append the dialog items + // if possible; else it will call AppendDITL itself. This way, you + // don't have to worry about it. + + err = CWPanlAppendItems(pb, kCW8ItemListID); + if (err != noErr) + return (err); + + sDragRgn = NewRgn(); + + return (err); +} + +/* + * TermDialog - destroy Dialog Box items for this panel + * + */ + +static void TermDialog(PanelParameterBlock *pb) +{ + DisposeRgn(sDragRgn); +} + +inline Boolean hasLinkerOutput(short mode) +{ + return (mode == kXPIDLModeHeader || mode == kXPIDLModeTypelib); +} + +/* + * PutData - copy the options data from the handle to the screen + * + */ + +static void PutData(PanelParameterBlock *pb, Handle options) +{ + // make sure the options are the right size. + UpdatePref(options); + + XPIDLSettings prefsData = **(XPIDLSettingsHandle) options; + + CWPanlSetItemValue(pb, kXPIDLModeItem, prefsData.mode); + CWPanlSetItemValue(pb, kXPIDLWarningsItem, prefsData.warnings); + CWPanlSetItemValue(pb, kXPIDLVerboseItem, prefsData.verbose); + + CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(prefsData.mode)); + CWPanlSetItemText(pb, kXPTLinkerOutputItem, prefsData.output); +} + +/* + * GetData - copy the options data from screen to the handle + * + */ + +static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy) +{ + XPIDLSettings prefsData = **(XPIDLSettingsHandle) options; + long mode, warnings, verbose; + + CWPanlGetItemValue(pb, kXPIDLModeItem, &mode); + CWPanlGetItemValue(pb, kXPIDLWarningsItem, &warnings); + CWPanlGetItemValue(pb, kXPIDLVerboseItem, &verbose); + + prefsData.mode = (short) mode; + prefsData.warnings = (Boolean) warnings; + prefsData.verbose = (Boolean) verbose; + + CWPanlGetItemText(pb, kXPTLinkerOutputItem, prefsData.output, sizeof(Str32)); + + ** (XPIDLSettingsHandle) options = prefsData; + + return (noErr); +} + +static void ByteSwapShort(short* x) +{ + union { + short s; + char c[2]; + } from,to; + + from.s=*x; + to.c[0]=from.c[1]; + to.c[1]=from.c[0]; + *x = to.s; +} + +/* + * ByteSwapData - byte-swap the options data + * + */ + +static void ByteSwapData(XPIDLSettingsHandle options) +{ + ByteSwapShort(&(**options).version); + ByteSwapShort(&(**options).mode); +} + +/* + * Filter - filter an event for the Preferences panel + * + */ +static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit) +{ +#pragma unused(pb, event, itemHit) + + return (noErr); +} + +/* + * ItemHit - handle an itemHit in a Preferences panel + * + */ + +static void ItemHit(PanelParameterBlock *pb) +{ + short theItem = pb->itemHit - pb->baseItems; + long oldValue; + + switch (theItem) { + case kXPIDLModeItem: + CWPanlGetItemValue(pb, theItem, &oldValue); + CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(oldValue)); + break; + + case kXPIDLWarningsItem: + case kXPIDLVerboseItem: + CWPanlGetItemValue(pb, theItem, &oldValue); + break; + } + + GetData(pb, pb->currentPrefs, false); + + pb->canRevert = !ComparePrefs(pb->originalPrefs, pb->currentPrefs); + pb->canFactory = !ComparePrefs(pb->factoryPrefs, pb->currentPrefs); +} + +/* + * Validate - check if panel's changes require a recompile or relink + * + */ + +static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset) +{ +#pragma unused(original, current) + XPIDLSettings& origSettings = **(XPIDLSettingsHandle) original; + XPIDLSettings& currentSettings = **(XPIDLSettingsHandle) current; + + *recompile = currentSettings.mode != origSettings.mode; + *relink = *recompile && hasLinkerOutput(currentSettings.mode); + *reset = false; +} + +/* + * GetPref - get a specified Preference setting for an AppleEvent request + * + */ +static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings) +{ +#if 0 + XPIDLSettings prefsData = ** (XPIDLSettingsHandle) settings; + DescType anEnum; + OSErr err; + + switch (keyword) { + case prefsLN_GenerateSymFile: + err = AECreateDesc(typeBoolean, &prefsData.linksym, sizeof(Boolean), prefsDesc); + break; + + case prefsPR_ProjectType: + switch (prefsData.projtype) + { + case kProjTypeApplication: anEnum = enum_Project_Application; break; + case kProjTypeLibrary: anEnum = enum_Project_Library; break; + case kProjTypeSharedLib: anEnum = enum_Project_SharedLibrary; break; + case kProjTypeCodeResource: anEnum = enum_Project_CodeResource; break; + case kProjTypeMPWTool: anEnum = enum_Project_MPWTool; break; + default: return (paramErr); + } + err = AECreateDesc(typeEnumeration, &anEnum, sizeof(anEnum), prefsDesc); + break; + + case prefsPR_FileName: + err = AECreateDesc(typeChar, prefsData.outfile+1, StrLength(prefsData.outfile), prefsDesc); + break; + + default: + err = errAECantHandleClass; + break; + } + + return (err); +#else + return (errAECantHandleClass); +#endif +} + +/* + * SetPref - set a specified Preference setting from an AppleEvent request + * + */ + +static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings) +{ +#if 0 + XPIDLSettings prefsData = ** (XPIDLSettingsHandle) settings; + AEDesc toDesc = { typeNull, NULL }; + OSErr err = noErr; + Handle dataHand; + Size textLength; + DescType anEnum; + + switch (keyword) + { + case prefsLN_GenerateSymFile: + if (prefsDesc->descriptorType == typeBoolean) + { + dataHand = prefsDesc->dataHandle; + } + else + { + err = AECoerceDesc(prefsDesc, typeBoolean, &toDesc); + if (err == noErr) + dataHand = toDesc.dataHandle; + } + if (err == noErr) + { + prefsData.linksym = ** (Boolean **) dataHand; + } + break; + + case prefsPR_ProjectType: + if (prefsDesc->descriptorType != typeEnumeration) + { + err = errAETypeError; + break; + } + + anEnum = ** (DescType **) prefsDesc->dataHandle; + + switch (anEnum) + { + case enum_Project_Application: prefsData.projtype = kProjTypeApplication; break; + case enum_Project_Library: prefsData.projtype = kProjTypeLibrary; break; + case enum_Project_SharedLibrary: prefsData.projtype = kProjTypeSharedLib; break; + case enum_Project_CodeResource: prefsData.projtype = kProjTypeCodeResource; break; + case enum_Project_MPWTool: prefsData.projtype = kProjTypeMPWTool; break; + default: return (errAECoercionFail); + } + break; + + case prefsPR_FileName: + if (prefsDesc->descriptorType == typeChar) + { + dataHand = prefsDesc->dataHandle; + } + else + { + err = AECoerceDesc(prefsDesc, typeChar, &toDesc); + if (err == noErr) + dataHand = toDesc.dataHandle; + } + if (err == noErr) + { + textLength = GetHandleSize(dataHand); + if (textLength > sizeof(prefsData.outfile) - 1) + textLength = sizeof(prefsData.outfile) - 1; + BlockMoveData(*dataHand, prefsData.outfile+1, textLength); + prefsData.outfile[0] = textLength; + } + break; + + default: + err = errAECantHandleClass; + break; + } + + if (err == noErr) + { + ** (XPIDLSettingsHandle) settings = prefsData; + } + + AEDisposeDesc(&toDesc); + + return (err); +#else + return (errAECantHandleClass); +#endif +} + +/* + * GetFactory - retrieve factory settings + * + */ + +static short GetFactory(Handle settings) +{ + Handle factory; + Size size; + OSErr err; + + factory = Get1Resource('pref', kFactoryPrefsID); + if (factory == NULL) { + err = ResError(); + if (err == noErr) + err = resNotFound; + return (err); + } + + size = GetHandleSize(factory); + SetHandleSize(settings, size); + err = MemError(); + + if (err == noErr) { + BlockMoveData(*factory, *settings, size); + } + + return (err); +} + +/* + * UpdatePref - "upgrade" a pref to the current version + */ +static short UpdatePref(Handle settings) +{ + if (GetHandleSize(settings) != sizeof(XPIDLSettings)) + GetFactory(settings); + + return (noErr); +} + +/* + * ComparePrefs + * + */ +static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2) +{ + XPIDLSettings& prefs1 = **(XPIDLSettingsHandle) prefsHand1; + XPIDLSettings& prefs2 = **(XPIDLSettingsHandle) prefsHand2; + + return ((prefs1.mode == prefs2.mode) && + (prefs1.warnings == prefs2.warnings) && + (prefs1.verbose == prefs2.verbose) && + (EqualString(prefs1.output, prefs2.output, true, true))); +} + +static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2) +{ + return ((prefs1.mode == prefs2.mode) && + (prefs1.warnings == prefs2.warnings) && + (prefs1.verbose == prefs2.verbose) && + (EqualString(prefs1.output, prefs2.output, true, true))); +} + +/* + * OutlineRect + * + */ +static void OutlineRect(const Rect* focusRect, Boolean outlineOn) +{ + ColorSpec savedForeColor, backColor; + PenState savedPen; + + GetPenState(&savedPen); + PenNormal(); + + if (!outlineOn) + { + SaveFore(&savedForeColor); + SaveBack(&backColor); + RestoreFore(&backColor); + } + + PenSize(2, 2); + FrameRect(focusRect); + + SetPenState(&savedPen); + + if (!outlineOn) + { + RestoreFore(&savedForeColor); + } +} + +/* + * DragEnter + * + */ +static OSErr DragEnter(PanelParameterBlock *pb) +{ +#if 0 + short theItem = pb->itemHit - pb->baseItems; + unsigned short itemCount; + Rect itemRect; + OSErr err; +#endif + + /* Return paramErr if the user is on a item that can't be dropped on */ + return (paramErr); +} + +/* + * DragWithin + * + */ +static void DragWithin(PanelParameterBlock *pb) +{ +#pragma unused(pb) + + /* there's nothing to do */ + +/// SysBreakStr("\preqDragWithin"); +} + +/* + * DragExit + * + */ +static void DragExit(PanelParameterBlock *pb) +{ + OSErr err; + +/// SysBreakStr("\preqDragExit"); + + if (sHighlightOn) { + err = HideDragHilite(pb->dragref); + if (err == noErr) + sHighlightOn = false; + } +} + +/* + * DragDrop + * + */ +static void DragDrop(PanelParameterBlock *pb) +{ +#if 0 + Rect itemRect; +#endif + +/// SysBreakStr("\preqDragDrop"); + + DragExit(pb); +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h new file mode 100644 index 00000000..582b1055 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h @@ -0,0 +1,106 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_xpidl_panel.h + */ + +#pragma once + +#ifndef __MAC_XPIDL_PANEL__ +#define __MAC_XPIDL_PANEL__ + +#ifndef __TYPES__ +#include <Types.h> +#endif + +#pragma options align=mac68k + +/* this is the name of the panel, as shown in the Finder */ +#define kXPIDLPanelName "xpidl Settings" + +/* + * AppleScript dictionary info. As a rule of thumb, dropin panels should use the + * same terminology and numeric code in their 'aete' that the IDE uses if there + * is already a similar item in the IDE's 'aete'. That is the case here, so we + * merely duplicate applicable 68K Project and 68K Linker user terms below. + */ + +enum { +/* Symbolic Name Code AETE Terminology */ + class_XPIDL = 'XIDL', + + prefsPR_ProjectType = 'PR01', /* Project Type */ + prefsPR_FileName = 'PR02', /* File Name */ + prefsLN_GenerateSymFile = 'LN02', /* Generate SYM File */ + + /* enumeration for project type */ + enumeration_ProjectType = 'PRPT', + enum_Project_Application = 'PRPA', /* application */ + enum_Project_Library = 'PRPL', /* library */ + enum_Project_SharedLibrary = 'PRPS', /* shared library */ + enum_Project_CodeResource = 'PRPC', /* code resource */ + enum_Project_MPWTool = 'PRPM' /* MPW tool */ +}; + +enum { + kXPIDLModeHeader = 1, + kXPIDLModeJava, + kXPIDLModeTypelib, + kXPIDLModeDoc +}; + +/* This is the structure that is manipulated by the panel. The sample + * compiler & linker both "know" about this structure. + */ + +enum { + kXPIDLSettingsVersion = 0x0100 +}; + +struct XPIDLSettings { + short version; /* version # of settings data */ + short mode; /* one of kXPIDLModeHeader, ... */ + Boolean warnings; /* generate warnings. */ + Boolean verbose; /* verbose mode */ + Str32Field output; /* name of the output file */ +}; + +typedef struct XPIDLSettings XPIDLSettings, **XPIDLSettingsHandle; + +#pragma options align=reset + +#endif /* __MAC_XPIDL_PANEL__ */ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp new file mode 100644 index 00000000..fe137959 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp @@ -0,0 +1,546 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + mac_xpt_linker.cpp + + CodeWarrior plugin linker, links together multiple .xpt files. + + by Patrick C. Beard. + */ + +/* standard headers */ +#include <stdio.h> +#include <string.h> +#include <setjmp.h> + +/* system headers */ +#include <Files.h> +#include <Strings.h> +#include <Aliases.h> +#include <Resources.h> + +/* compiler headers */ +#include "DropInCompilerLinker.h" +#include "CompilerMapping.h" +#include "CWPluginErrors.h" + +/* project headers */ +#include "mac_xpidl_panel.h" +#include "mac_console.h" +#include "mac_strings.h" +#include "FullPath.h" +#include "MoreFilesExtras.h" + +/* use standard CodeWarrior debugger */ +#define kDebuggerCreator 'MWDB' + +/* prototypes of local functions */ +static CWResult Link(CWPluginContext context); +static CWResult Disassemble(CWPluginContext context); +static CWResult GetTargetInfo(CWPluginContext context); + +extern "C" { +pascal short xpt_linker(CWPluginContext context); +int xptlink_main(int argc, char* argv[]); +int xptdump_main(int argc, char* argv[]); + +FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode); +size_t mac_get_file_length(const char* filename); +} + +/* external variables */ +extern jmp_buf exit_jump; +extern int exit_status; + +/* global variables */ +CWPluginContext gPluginContext; + +/* local variables */ +static CWFileSpec gOutputDirectory; +static CWFileSpec gObjectCodeDirectory; + +/* + * xpt_linker - main entry-point for linker plugin + * + */ +pascal short xpt_linker(CWPluginContext context) +{ + long request; + if (CWGetPluginRequest(context, &request) != cwNoErr) + return cwErrRequestFailed; + + gPluginContext = context; + short result = cwNoErr; + + /* dispatch on linker request */ + switch (request) { + case reqInitLinker: + /* linker has just been loaded into memory */ + break; + + case reqTermLinker: + /* linker is about to be unloaded from memory */ + break; + + case reqLink: + /* build the final executable */ + result = Link(context); + break; + + case reqDisassemble: + /* disassemble object code for a given project file */ + result = Disassemble(context); + break; + + case reqTargetInfo: + /* return info describing target characteristics */ + result = GetTargetInfo(context); + break; + + default: + result = cwErrRequestFailed; + break; + } + + result = CWDonePluginRequest(context, result); + + /* return result code */ + return result; +} + +static char* full_path_to(const FSSpec& file) +{ + short len = 0; + Handle fullPath = NULL; + if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) { + char* path = new char[1 + len]; + if (path != NULL) { + BlockMoveData(*fullPath, path, len); + path[len] = '\0'; + } + DisposeHandle(fullPath); + return path; + } + return NULL; +} + +/** + * Provides the full path name to a given directory. + */ +static char* full_path_to(short vRefNum, long dirID) +{ + long parID; + if (GetParentID(vRefNum, dirID, NULL, &parID) == noErr) { + FSSpec dirSpec = { vRefNum, parID }; + if (GetDirName(vRefNum, dirID, dirSpec.name) == noErr) { + return full_path_to(dirSpec); + } + } + return NULL; +} + +/** + * Returns the length of a file, assuming it is always located in the + * project's object code directory. + */ +size_t mac_get_file_length(const char* filename) +{ + FSSpec fileSpec = { gObjectCodeDirectory.vRefNum, gObjectCodeDirectory.parID }; + c2p_strcpy(fileSpec.name, filename); + long dataSize, rsrcSize; + if (FSpGetFileSize(&fileSpec, &dataSize, &rsrcSize) != noErr) + dataSize = 0; + return dataSize; +} + +/** + * replaces standard fopen -- opens files for writing in the project's output directory, + * and files for reading in the object code directory. + */ +FILE* std::fopen(const char* filename, const char *mode) +{ + CWFileSpec& fileDir = (mode[0] == 'r' ? gObjectCodeDirectory : gOutputDirectory); + FSSpec fileSpec = { fileDir.vRefNum, fileDir.parID }; + c2p_strcpy(fileSpec.name, filename); + return FSp_fopen(&fileSpec, mode); +} + +static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings) +{ + CWMemHandle settingsHand; + CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand); + if (!CWSUCCESS(err)) + return err; + + XPIDLSettings* settingsPtr = NULL; + err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr); + if (!CWSUCCESS(err)) + return err; + + settings = *settingsPtr; + + err = CWUnlockMemHandle(context, settingsHand); + if (!CWSUCCESS(err)) + return err; + + return cwNoErr; +} + +static CWResult LinkHeaders(CWPluginContext context, XPIDLSettings& settings) +{ + // find out how many files there are to link. + long fileCount = 0; + CWResult err = CWGetProjectFileCount(context, &fileCount); + if (err != cwNoErr || fileCount == 0) + return err; + + // get the output directory. + FSSpec outputDir; + err = CWGetOutputFileDirectory(context, &outputDir); + if (!CWSUCCESS(err)) + return err; + + // enumerate all of the output header files, and make aliases to them in + // the output directory. + for (long index = 0; (err == cwNoErr) && (index < fileCount); index++) { + // get the name of each output file. + CWFileSpec outputFile; + err = CWGetStoredObjectFileSpec(context, index, &outputFile); + if (err == cwNoErr) { + FInfo info; + err = FSpGetFInfo(&outputFile, &info); + + FSSpec aliasFile = { outputDir.vRefNum, outputDir.parID }; + BlockMoveData(outputFile.name, aliasFile.name, 1 + outputFile.name[0]); + + AliasHandle alias = NULL; + if (NewAliasMinimal(&outputFile, &alias) == noErr) { + // recreate the alias file from scratch. + FSpDelete(&aliasFile); + FSpCreateResFile(&aliasFile, info.fdCreator, info.fdType, smRoman); + short refNum = FSpOpenResFile(&aliasFile, fsRdWrPerm); + if (refNum != -1) { + UseResFile(refNum); + AddResource(Handle(alias), rAliasType, 0, aliasFile.name); + ReleaseResource(Handle(alias)); + UpdateResFile(refNum); + CloseResFile(refNum); + } + // finally, mark the newly created file as an alias file. + FSpGetFInfo(&aliasFile, &info); + info.fdFlags |= kIsAlias; + FSpSetFInfo(&aliasFile, &info); + } + } + } + + // create the target file in the output directory. + BlockMoveData(settings.output, outputDir.name, 1 + settings.output[0]); + FILE* outputFile = FSp_fopen(&outputDir, "w"); + if (outputFile != NULL) fclose(outputFile); + + return err; +} + +static CWResult LinkTypeLib(CWPluginContext context, XPIDLSettings& settings) +{ + // find out how many files there are to link. + long fileCount = 0; + CWResult err = CWGetProjectFileCount(context, &fileCount); + if (err != cwNoErr || fileCount == 0) + return err; + + // assemble the argument list. + // { "xpt_link", outputFile, inputFile1, ..., inputFileN, NULL } + char** argv = new char*[2 + fileCount + 1]; + int argc = 0; + argv[argc++] = "xpt_link"; + + // get the output directory. + err = CWGetOutputFileDirectory(context, &gOutputDirectory); + if (!CWSUCCESS(err)) + return err; + + // get the object code directory. + err = CWGetStoredObjectFileSpec(context, 0, &gObjectCodeDirectory); + if (!CWSUCCESS(err)) + return err; + + // push the output file name. + if ((argv[argc++] = p2c_strdup(settings.output)) == NULL) + return cwErrOutOfMemory; + + for (long index = 0; (err == cwNoErr) && (index < fileCount); index++) { + // get the name of each output file. + CWFileSpec outputFile; + err = CWGetStoredObjectFileSpec(context, index, &outputFile); + if (err == cwNoErr) { + if ((argv[argc++] = p2c_strdup(outputFile.name)) == NULL) { + err = cwErrOutOfMemory; + break; + } + } + } + + if (err != cwNoErr) + return err; + + // trap calls to exit, which longjmp back to here. + if (setjmp(exit_jump) == 0) { + if (xptlink_main(argc, argv) != 0) + err = cwErrRequestFailed; + } else { + // evidently the good old exit function got called. + if (exit_status != 0) + err = cwErrRequestFailed; + } + + return err; +} + +static CWResult Link(CWPluginContext context) +{ + // load the relevant prefs. + XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false }; + CWResult err = GetSettings(context, settings); + if (err != cwNoErr) + return err; + + switch (settings.mode) { + case kXPIDLModeHeader: + return LinkHeaders(context, settings); + case kXPIDLModeTypelib: + return LinkTypeLib(context, settings); + default: + return cwNoErr; + } +} + +static CWResult Disassemble(CWPluginContext context) +{ + CWResult err = noErr; + + // cache the project's output directory. + err = CWGetOutputFileDirectory(gPluginContext, &gOutputDirectory); + if (!CWSUCCESS(err)) + return err; + + long fileNum; + err = CWGetMainFileNumber(context, &fileNum); + if (!CWSUCCESS(err)) + return err; + + // get the output file's location from the stored object data. + err = CWGetStoredObjectFileSpec(context, fileNum, &gObjectCodeDirectory); + if (!CWSUCCESS(err)) + return err; + + char* outputName = p2c_strdup(gObjectCodeDirectory.name); + if (outputName == NULL) + return cwErrOutOfMemory; + + XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false }; + GetSettings(context, settings); + + // build an argument list and call xpt_dump. + int argc = 1; + char* argv[] = { "xpt_dump", NULL, NULL, NULL }; + if (settings.verbose) argv[argc++] = "-v"; + argv[argc++] = outputName; + + // trap calls to exit, which longjmp back to here. + if (setjmp(exit_jump) == 0) { + if (xptdump_main(argc, argv) != 0) + err = cwErrRequestFailed; + } else { + // evidently the good old exit function got called. + if (exit_status != 0) + err = cwErrRequestFailed; + } + + delete[] outputName; + + if (err == noErr) { + // display the disassembly in its own fresh text window. + CWNewTextDocumentInfo info = { + NULL, + mac_console_handle, + false + }; + CWResizeMemHandle(context, mac_console_handle, mac_console_count); + err = CWCreateNewTextDocument(context, &info); + } + + return err; +} + +static CWResult GetTargetInfo(CWPluginContext context) +{ + CWTargetInfo targ; + memset(&targ, 0, sizeof(targ)); + + CWResult err = CWGetOutputFileDirectory(context, &targ.outfile); + targ.outputType = linkOutputFile; + targ.symfile = targ.outfile; /* location of SYM file */ + targ.linkType = exelinkageFlat; + targ.targetCPU = '****'; + targ.targetOS = '****'; + + // load the relevant settings. + XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false }; + err = GetSettings(context, settings); + if (err != cwNoErr) + return err; + +#if CWPLUGIN_HOST == CWPLUGIN_HOST_MACOS + // tell the IDE about the output file. + targ.outfileCreator = 'MMCH'; + targ.outfileType = 'CWIE'; + targ.debuggerCreator = kDebuggerCreator; /* so IDE can locate our debugger */ + + BlockMoveData(settings.output, targ.outfile.name, 1 + settings.output[0]); + targ.symfile.name[0] = 0; +#endif + +#if CWPLUGIN_HOST == CWPLUGIN_HOST_WIN32 + targ.debugHelperIsRegKey = true; + *(long*)targ.debugHelperName = kDebuggerCreator; + targ.debugHelperName[4] = 0; + strcat(targ.outfile.path, "\\"); + strcat(targ.outfile.path, prefsData.outfile); + strcpy(targ.symfile.path, targ.outfile.path); + strcat(targ.symfile.path, ".SYM"); +#endif + + targ.runfile = targ.outfile; + targ.linkAgainstFile = targ.outfile; + + /* we can only run applications */ + // targ.canRun = (prefsData.projtype == kProjTypeApplication); + + /* we can only debug if we have a SYM file */ + // targ.canDebug = prefsData.linksym; + + err = CWSetTargetInfo(context, &targ); + + return err; +} + +#if 0 + +#if CW_USE_PRAGMA_EXPORT +#pragma export on +#endif + +CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize) +{ + static const DropInFlags sFlags = { + kCurrentDropInFlagsVersion, + CWDROPINLINKERTYPE, + DROPINCOMPILERLINKERAPIVERSION_7, + (linkMultiTargAware | linkAlwaysReload), + 0, + DROPINCOMPILERLINKERAPIVERSION + }; + + *flags = &sFlags; + *flagsSize = sizeof(sFlags); + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName) +{ + static const char* sDropInName = "xpt Linker"; + *dropinName = sDropInName; + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName) +{ + static const char* sDisplayName = "xpt Linker"; + *displayName = sDisplayName; + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList) +{ + // +++Turn this on when the sample panel has been converted! + static const char* sPanelName = kXPIDLPanelName; + static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName }; + + *panelList = &sPanelList; + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList) +{ + static CWDataType sCPU = '****'; + static CWDataType sOS = '****'; + static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS }; + + *targetList = &sTargetList; + + return cwNoErr; +} + +CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList) +{ + static CWExtensionMapping sExtension = { 'MMCH', ".xpt", 0 }; + static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension }; + + *defaultMappingList = &sExtensionMapList; + + return cwNoErr; +} + +CWPLUGIN_ENTRY (CWPlugin_GetFamilyList)(const CWFamilyList** familyList) +{ + static CWFamily sFamily = { 'XIDL', "xpidl Settings" }; + static CWFamilyList sFamilyList = { kCurrentCWFamilyListVersion, 0, &sFamily }; + + *familyList = &sFamilyList; + + return cwNoErr; +} + +#if CW_USE_PRAGMA_EXPORT +#pragma export off +#endif + +#endif diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc Binary files differnew file mode 100644 index 00000000..c5777088 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc Binary files differnew file mode 100644 index 00000000..6737d356 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c new file mode 100644 index 00000000..e1a7c58d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c @@ -0,0 +1,275 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Main xpidl program entry point. + */ + +#include "xpidl.h" + +static ModeData modes[] = { + {"header", "Generate C++ header", "h", xpidl_header_dispatch}, + {"typelib", "Generate XPConnect typelib", "xpt", xpidl_typelib_dispatch}, + {"doc", "Generate HTML documentation", "html", xpidl_doc_dispatch}, + {"java", "Generate Java interface", "java", xpidl_java_dispatch}, + {0, 0, 0, 0} +}; + +static ModeData * +FindMode(char *mode) +{ + int i; + for (i = 0; modes[i].mode; i++) { + if (!strcmp(modes[i].mode, mode)) + return &modes[i]; + } + return NULL; +} + +gboolean enable_debug = FALSE; +gboolean enable_warnings = FALSE; +gboolean verbose_mode = FALSE; +gboolean emit_typelib_annotations = FALSE; +gboolean explicit_output_filename = FALSE; + +/* The following globals are explained in xpt_struct.h */ +PRUint8 major_version = XPT_MAJOR_VERSION; +PRUint8 minor_version = XPT_MINOR_VERSION; + +static char xpidl_usage_str[] = +"Usage: %s -m mode [-w] [-v] [-t version number]\n" +" [-I path] [-o basename | -e filename.ext] filename.idl\n" +" -a emit annotations to typelib\n" +" -w turn on warnings (recommended)\n" +" -v verbose mode (NYI)\n" +" -t create a typelib of a specific version number\n" +" -I add entry to start of include path for ``#include \"nsIThing.idl\"''\n" +" -o use basename (e.g. ``/tmp/nsIThing'') for output\n" +" -e use explicit output filename\n" +" -m specify output mode:\n"; + +static void +xpidl_usage(int argc, char *argv[]) +{ + int i; + fprintf(stderr, xpidl_usage_str, argv[0]); + for (i = 0; modes[i].mode; i++) { + fprintf(stderr, " %-12s %-30s (.%s)\n", modes[i].mode, + modes[i].modeInfo, modes[i].suffix); + } +} + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) +#define main xpidl_main +int xpidl_main(int argc, char *argv[]); +#endif + +int main(int argc, char *argv[]) +{ + int i; + IncludePathEntry *inc, *inc_head, **inc_tail; + char *file_basename = NULL; + ModeData *mode = NULL; + gboolean create_old_typelib = FALSE; + + /* turn this on for extra checking of our code */ +/* IDL_check_cast_enable(TRUE); */ + + inc_head = xpidl_malloc(sizeof *inc); +#ifndef XP_MAC + inc_head->directory = "."; +#else + inc_head->directory = ""; +#endif + inc_head->next = NULL; + inc_tail = &inc_head->next; + + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') + break; + switch (argv[i][1]) { + case '-': + argc++; /* pretend we didn't see this */ + /* fall through */ + case 0: /* - is a legal input filename (stdin) */ + goto done_options; + case 'a': + emit_typelib_annotations = TRUE; + break; + case 'w': + enable_warnings = TRUE; + break; + case 'v': + verbose_mode = TRUE; + break; + case 't': + { + /* Parse for "-t version number" and store it into global boolean + * and string variables. + */ + const gchar* typelib_version_string = NULL; + + /* + * If -t is the last argument on the command line, we have a problem + */ + + if (i + 1 == argc) { + fprintf(stderr, "ERROR: missing version number after -t\n"); + xpidl_usage(argc, argv); + return 1; + } + + /* Do not allow more than one "-t" definition */ + if (create_old_typelib) { + fprintf(stderr, + "ERROR: -t argument used twice. " + "Cannot specify more than one version\n"); + xpidl_usage(argc, argv); + return 1; + } + + /* + * Assume that the argument after "-t" is the version number string + * and search for it in our internal list of acceptable version + * numbers. + */ + switch (XPT_ParseVersionString(argv[++i], &major_version, + &minor_version)) { + case XPT_VERSION_CURRENT: + break; + case XPT_VERSION_OLD: + create_old_typelib = TRUE; + break; + case XPT_VERSION_UNSUPPORTED: + fprintf(stderr, "ERROR: version \"%s\" not supported.\n", + argv[i]); + xpidl_usage(argc, argv); + return 1; + case XPT_VERSION_UNKNOWN: + default: + fprintf(stderr, "ERROR: version \"%s\" not recognised.\n", + argv[i]); + xpidl_usage(argc, argv); + return 1; + } + break; + } + case 'I': + if (argv[i][2] == '\0' && i == argc) { + fputs("ERROR: missing path after -I\n", stderr); + xpidl_usage(argc, argv); + return 1; + } + inc = xpidl_malloc(sizeof *inc); + if (argv[i][2] == '\0') { + /* is it the -I foo form? */ + inc->directory = argv[++i]; + } else { + /* must be the -Ifoo form. Don't preincrement i. */ + inc->directory = argv[i] + 2; + } +#ifdef DEBUG_shaver_includes + fprintf(stderr, "adding %s to include path\n", inc->directory); +#endif + inc->next = NULL; + *inc_tail = inc; + inc_tail = &inc->next; + break; + case 'o': + if (i == argc) { + fprintf(stderr, "ERROR: missing basename after -o\n"); + xpidl_usage(argc, argv); + return 1; + } + file_basename = argv[++i]; + explicit_output_filename = FALSE; + break; + case 'e': + if (i == argc) { + fprintf(stderr, "ERROR: missing basename after -e\n"); + xpidl_usage(argc, argv); + return 1; + } + file_basename = argv[++i]; + explicit_output_filename = TRUE; + break; + case 'm': + if (i + 1 == argc) { + fprintf(stderr, "ERROR: missing modename after -m\n"); + xpidl_usage(argc, argv); + return 1; + } + if (mode) { + fprintf(stderr, + "ERROR: must specify exactly one mode " + "(first \"%s\", now \"%s\")\n", mode->mode, + argv[i + 1]); + xpidl_usage(argc, argv); + return 1; + } + mode = FindMode(argv[++i]); + if (!mode) { + fprintf(stderr, "ERROR: unknown mode \"%s\"\n", argv[i]); + xpidl_usage(argc, argv); + return 1; + } + break; + default: + fprintf(stderr, "unknown option %s\n", argv[i]); + xpidl_usage(argc, argv); + return 1; + } + } + done_options: + if (!mode) { + fprintf(stderr, "ERROR: must specify output mode\n"); + xpidl_usage(argc, argv); + return 1; + } + if (argc != i + 1) { + fprintf(stderr, "ERROR: extra arguments after input file\n"); + } + + /* + * Don't try to process multiple files, given that we don't handle -o + * multiply. + */ + if (xpidl_process_idl(argv[i], inc_head, file_basename, mode)) + return 0; + + return 1; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h new file mode 100644 index 00000000..857bfdf8 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h @@ -0,0 +1,278 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Intramodule declarations. + */ + +#ifndef __xpidl_h +#define __xpidl_h + +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <glib.h> +#include <string.h> /* After glib.h to avoid warnings about shadowing 'index'. */ + +#ifndef XP_MAC +#include <libIDL/IDL.h> +#else +#include <IDL.h> +#endif + +#include <xpt_struct.h> + +/* + * IDL_tree_warning bombs on libIDL version 6.5, and I don't want to not write + * warnings... so I define a versioned one here. Thanks to Mike Shaver for the + * this solution, which allows us to pass through varargs calls. + */ +#if !(LIBIDL_MAJOR_VERSION == 0 && LIBIDL_MINOR_VERSION == 6 && \ + LIBIDL_MICRO_VERSION == 5) && !defined(DEBUG_shaver) +/* + * This turns a varargs call to XPIDL_WARNING directly into a varargs + * call to IDL_tree_warning or xpidl_tree_warning as appropriate. The + * only tricky bit is that you must call XPIDL_WARNING with extra + * parens, e.g. XPIDL_WARNING((foo, bar, "sil")) + * + * Probably best removed when we leave 6.5. */ +#define XPIDL_WARNING(x) IDL_tree_warning x +#else +extern void xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...); +#define XPIDL_WARNING(x) xpidl_tree_warning x +#endif + +/* + * Internal operation flags. + */ +extern gboolean enable_debug; +extern gboolean enable_warnings; +extern gboolean verbose_mode; +extern gboolean emit_typelib_annotations; +extern gboolean explicit_output_filename; + +extern PRUint8 major_version; +extern PRUint8 minor_version; + +typedef struct TreeState TreeState; + +/* + * A function to handle an IDL_tree type. + */ +typedef gboolean (*nodeHandler)(TreeState *); + +/* + * Struct containing functions to define the behavior of a given output mode. + */ +typedef struct backend { + nodeHandler *dispatch_table; /* nodeHandlers table, indexed by node type. */ + nodeHandler emit_prolog; /* called at beginning of output generation. */ + nodeHandler emit_epilog; /* called at end. */ +} backend; + +/* Function that produces a struct of output-generation functions */ +typedef backend *(*backendFactory)(); + +extern backend *xpidl_header_dispatch(void); +extern backend *xpidl_typelib_dispatch(void); +extern backend *xpidl_doc_dispatch(void); +extern backend *xpidl_java_dispatch(void); + +typedef struct ModeData { + char *mode; + char *modeInfo; + char *suffix; + backendFactory factory; +} ModeData; + +typedef struct IncludePathEntry { + char *directory; + struct IncludePathEntry *next; +} IncludePathEntry; + +struct TreeState { + FILE *file; + /* Maybe supplied by -o. Not related to (g_)basename from string.h or glib */ + char *basename; + IDL_ns ns; + IDL_tree tree; + GSList *base_includes; + nodeHandler *dispatch; + void *priv; /* mode-private data */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + char *real_outname; +#endif + +}; + +/* + * Process an IDL file, generating InterfaceInfo, documentation and headers as + * appropriate. + */ +int +xpidl_process_idl(char *filename, IncludePathEntry *include_path, + char *file_basename, ModeData *mode); + +/* + * Iterate over an IDLN_LIST -- why is this not part of libIDL? + */ +void +xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data); + +/* + * Wrapper whines to stderr then exits after null return from malloc or strdup. + */ +void * +xpidl_malloc(size_t nbytes); + +char * +xpidl_strdup(const char *s); + +/* + * Return a newly allocated string to the start of the base filename of path. + * Free with g_free(). + */ +char * +xpidl_basename(const char * path); + +/* + * Process an XPIDL node and its kids, if any. + */ +gboolean +xpidl_process_node(TreeState *state); + +/* + * Write a newline folllowed by an indented, one-line comment containing IDL + * source decompiled from state->tree. + */ +void +xpidl_write_comment(TreeState *state, int indent); + + + +/* + * Functions for parsing and printing UUIDs. + */ + +/* + * How large should the buffer supplied to xpidl_sprint_IID be? + */ +#define UUID_LENGTH 37 + +/* + * Print an iid to into a supplied buffer; the buffer should be at least + * UUID_LENGTH bytes. + */ +gboolean +xpidl_sprint_iid(nsID *iid, char iidbuf[]); + +/* + * Parse a uuid string into an nsID struct. We cannot link against libxpcom, + * so we re-implement nsID::Parse here. + */ +gboolean +xpidl_parse_iid(nsID *id, const char *str); + + +/* Try to common a little node-handling stuff. */ + +/* is this node from an aggregate type (interface)? */ +#define UP_IS_AGGREGATE(node) \ + (IDL_NODE_UP(node) && \ + (IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_INTERFACE || \ + IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_FORWARD_DCL)) + +#define UP_IS_NATIVE(node) \ + (IDL_NODE_UP(node) && \ + IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_NATIVE) + +/* is this type output in the form "<foo> *"? */ +#define STARRED_TYPE(node) (IDL_NODE_TYPE(node) == IDLN_TYPE_STRING || \ + IDL_NODE_TYPE(node) == IDLN_TYPE_WIDE_STRING || \ + (IDL_NODE_TYPE(node) == IDLN_IDENT && \ + UP_IS_AGGREGATE(node))) + +#define DIPPER_TYPE(node) \ + (NULL != IDL_tree_property_get(node, "domstring") || \ + NULL != IDL_tree_property_get(node, "utf8string") || \ + NULL != IDL_tree_property_get(node, "cstring") || \ + NULL != IDL_tree_property_get(node, "astring")) + +/* + * Find the underlying type of an identifier typedef. Returns NULL + * (and doesn't complain) on failure. + */ +IDL_tree /* IDL_TYPE_DCL */ +find_underlying_type(IDL_tree typedef_ident); + +/* + * Check that const declarations match their stated sign and are of the + * appropriate types. + */ +gboolean +verify_const_declaration(IDL_tree const_tree); + +/* + * Check that scriptable attributes in scriptable interfaces actually are. + */ +gboolean +verify_attribute_declaration(IDL_tree method_tree); + +/* + * Perform various validation checks on methods. + */ +gboolean +verify_method_declaration(IDL_tree method_tree); + +/* + * Verifies the interface declaration + */ +gboolean +verify_interface_declaration(IDL_tree method_tree); + +/* + * Verify that a native declaration has an associated C++ expression, i.e. that + * it's of the form native <idl-name>(<c++-name>) + */ +gboolean +check_native(TreeState *state); + +void +printlist(FILE *outfile, GSList *slist); + +#endif /* __xpidl_h */ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c new file mode 100644 index 00000000..d560e407 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c @@ -0,0 +1,312 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "xpidl.h" + +/* + * Generates documentation from javadoc-style comments in XPIDL files. + */ + +static gboolean +doc_prolog(TreeState *state) +{ + fprintf(state->file, "<html>\n"); + fprintf(state->file, "<head>\n"); + + fprintf(state->file, + "<!-- this file is generated from %s.idl -->\n", + state->basename); + fprintf(state->file, "<title>documentation for %s.idl interfaces</title>\n", + state->basename); + fprintf(state->file, "</head>\n\n"); + fprintf(state->file, "<body>\n"); + + return TRUE; +} + +static gboolean +doc_epilog(TreeState *state) +{ + fprintf(state->file, "</body>\n"); + fprintf(state->file, "</html>\n"); + + return TRUE; +} + + +static gboolean +doc_list(TreeState *state) +{ + IDL_tree iter; + for (iter = state->tree; iter; iter = IDL_LIST(iter).next) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + return TRUE; +} + +static gboolean +print_list(FILE *outfile, IDL_tree list) +{ + if (list == NULL) + return TRUE; + + fprintf(outfile, "<ul>\n"); + while (list != NULL) { + fprintf(outfile, " <li>%s\n", + IDL_IDENT(IDL_LIST(list).data).str); + list = IDL_LIST(list).next; + } + fprintf(outfile, "</ul>\n"); + return TRUE; +} + +static gboolean +doc_interface(TreeState *state) +{ + IDL_tree iface = state->tree; + IDL_tree iter; + IDL_tree orig; + char *classname = IDL_IDENT(IDL_INTERFACE(iface).ident).str; + GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments; + + fprintf(state->file, "interface %s<br>\n", classname); + + /* Much more could happen at this step. */ + /* + * If parsing doc comments, you might need to take some care with line + * endings, as the xpidl frontend will return comments containing of /r, + * /n, /r/n depending on the platform. It's best to leave out platform + * #defines and just treat them all as equivalent. + */ + if (doc_comments != NULL) { + fprintf(state->file, "doc comments:<br>\n"); + fprintf(state->file, "<pre>\n"); + printlist(state->file, doc_comments); + fprintf(state->file, "</pre>\n"); + fprintf(state->file, "<br>\n"); + } + + /* inherits from */ + /* + * Note that we accept multiple inheritance here (for e.g. gnome idl) + * even though the header backend (specific to mozilla idl) rejects it. + */ + if ((iter = IDL_INTERFACE(iface).inheritance_spec)) { + fprintf(state->file, "%s inherits from:<br>\n", classname); + print_list(state->file, iter); + fprintf(state->file, "<br>\n"); + } + + /* + * Call xpidl_process_node to recur through list of declarations in + * interface body; another option would be to explicitly iterate through + * the list. xpidl_process_node currently requires twiddling the state to + * get the right node; I'll fix that soon to just take the node. Makes it + * easier to follow what's going on, I think... + */ + orig = state->tree; + state->tree = IDL_INTERFACE(iface).body; + if (state->tree && !xpidl_process_node(state)) + return FALSE; + state->tree = orig; + + return TRUE; +} + +/* + * Copied from xpidl_header.c. You'll probably want to change it; if you can + * use it verbatim or abstract it, we could move it to xpidl_util.c and share + * it from there. + */ +static gboolean +write_type(IDL_tree type_tree, FILE *outfile) +{ + if (!type_tree) { + fputs("void", outfile); + return TRUE; + } + + switch (IDL_NODE_TYPE(type_tree)) { + case IDLN_TYPE_INTEGER: { + gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed; + switch (IDL_TYPE_INTEGER(type_tree).f_type) { + case IDL_INTEGER_TYPE_SHORT: + fputs(sign ? "PRInt16" : "PRUint16", outfile); + break; + case IDL_INTEGER_TYPE_LONG: + fputs(sign ? "PRInt32" : "PRUint32", outfile); + break; + case IDL_INTEGER_TYPE_LONGLONG: + fputs(sign ? "PRInt64" : "PRUint64", outfile); + break; + default: + g_error("Unknown integer type %d\n", + IDL_TYPE_INTEGER(type_tree).f_type); + return FALSE; + } + break; + } + case IDLN_TYPE_CHAR: + fputs("char", outfile); + break; + case IDLN_TYPE_WIDE_CHAR: + fputs("PRUnichar", outfile); /* wchar_t? */ + break; + case IDLN_TYPE_WIDE_STRING: + fputs("PRUnichar *", outfile); + break; + case IDLN_TYPE_STRING: + fputs("char *", outfile); + break; + case IDLN_TYPE_BOOLEAN: + fputs("PRBool", outfile); + break; + case IDLN_TYPE_OCTET: + fputs("PRUint8", outfile); + break; + case IDLN_TYPE_FLOAT: + switch (IDL_TYPE_FLOAT(type_tree).f_type) { + case IDL_FLOAT_TYPE_FLOAT: + fputs("float", outfile); + break; + case IDL_FLOAT_TYPE_DOUBLE: + fputs("double", outfile); + break; + /* XXX 'long double' just ignored, or what? */ + default: + fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree)); + break; + } + break; + case IDLN_IDENT: + if (UP_IS_NATIVE(type_tree)) { + fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile); + if (IDL_tree_property_get(type_tree, "ptr")) { + fputs(" *", outfile); + } else if (IDL_tree_property_get(type_tree, "ref")) { + fputs(" &", outfile); + } + } else { + fputs(IDL_IDENT(type_tree).str, outfile); + } + if (UP_IS_AGGREGATE(type_tree)) + fputs(" *", outfile); + break; + default: + fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree)); + break; + } + return TRUE; +} + +/* handle ATTR_DCL (attribute declaration) nodes */ +static gboolean +doc_attribute_declaration(TreeState *state) +{ + IDL_tree attr = state->tree; + + if (!verify_attribute_declaration(attr)) + return FALSE; + /* + * Attribute idents can also take doc comments. They're ignored here; + * should they be? + */ + + if (IDL_ATTR_DCL(attr).f_readonly) + fprintf(state->file, "readonly "); + + fprintf(state->file, "attribute "); + + if (!write_type(IDL_ATTR_DCL(attr).param_type_spec, state->file)) + return FALSE; + + fprintf(state->file, "\n"); + print_list(state->file, IDL_ATTR_DCL(attr).simple_declarations); + fprintf(state->file, "<br>\n"); + + return TRUE; +} + +/* handle OP_DCL (method declaration) nodes */ +static gboolean +doc_method_declaration(TreeState *state) +{ + /* + * Doc comment for attributes also applies here. + */ + + /* + * Look at 'write_method_signature' in xpidl_header.c for an example of how + * to navigate parse trees for methods. For here, I just print the method + * name. + */ + + fprintf(state->file, + "method %s<br>\n", + IDL_IDENT(IDL_OP_DCL(state->tree).ident).str); + + return TRUE; +} + +backend * +xpidl_doc_dispatch(void) +{ + static backend result; + static nodeHandler table[IDLN_LAST]; + static gboolean initialized = FALSE; + + result.emit_prolog = doc_prolog; + result.emit_epilog = doc_epilog; + + if (!initialized) { + /* Initialize non-NULL elements */ + + /* I just handle a few... many still to be filled in! */ + + table[IDLN_LIST] = doc_list; + table[IDLN_INTERFACE] = doc_interface; + table[IDLN_ATTR_DCL] = doc_attribute_declaration; + table[IDLN_OP_DCL] = doc_method_declaration; + + initialized = TRUE; + } + + result.dispatch_table = table; + return &result; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c new file mode 100644 index 00000000..f4fe9d5b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c @@ -0,0 +1,1196 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Generate XPCOM headers from XPIDL. + */ + +#include "xpidl.h" +#include <ctype.h> + +#define AS_DECL 0 +#define AS_CALL 1 +#define AS_IMPL 2 + +static gboolean write_method_signature(IDL_tree method_tree, FILE *outfile, + int mode, const char *className); +static gboolean write_attr_accessor(IDL_tree attr_tree, FILE * outfile, + gboolean getter, + int mode, const char *className); + +static void +write_indent(FILE *outfile) { + fputs(" ", outfile); +} + +static gboolean +header_prolog(TreeState *state) +{ + char *define = xpidl_basename(state->basename); + fprintf(state->file, "/*\n * DO NOT EDIT. THIS FILE IS GENERATED FROM" + " %s.idl\n */\n", state->basename); + fprintf(state->file, + "\n#ifndef __gen_%s_h__\n" + "#define __gen_%s_h__\n", + define, define); + g_free(define); + if (state->base_includes != NULL) { + guint len = g_slist_length(state->base_includes); + guint i; + + fputc('\n', state->file); + for (i = 0; i < len; i++) { + char *ident, *dot; + + ident = (char *)g_slist_nth_data(state->base_includes, i); + + /* suppress any trailing .extension */ + + /* XXX use g_basename instead ? ? */ + + dot = strrchr(ident, '.'); + if (dot != NULL) + *dot = '\0'; + + + /* begin include guard */ + fprintf(state->file, + "\n#ifndef __gen_%s_h__\n", + ident); + + fprintf(state->file, "#include \"%s.h\"\n", + (char *)g_slist_nth_data(state->base_includes, i)); + + fprintf(state->file, "#endif\n"); + + } + if (i > 0) + fputc('\n', state->file); + } + /* + * Support IDL files that don't include a root IDL file that defines + * NS_NO_VTABLE. + */ + fprintf(state->file, + "/* For IDL files that don't want to include root IDL files. */\n" + "#ifndef NS_NO_VTABLE\n" + "#define NS_NO_VTABLE\n" + "#endif\n"); + + return TRUE; +} + +static gboolean +header_epilog(TreeState *state) +{ + char *define = xpidl_basename(state->basename); + fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define); + g_free(define); + return TRUE; +} + +static void +write_classname_iid_define(FILE *file, const char *className) +{ + const char *iidName; + if (className[0] == 'n' && className[1] == 's') { + /* backcompat naming styles */ + fputs("NS_", file); + iidName = className + 2; + } else { + iidName = className; + } + while (*iidName) + fputc(toupper(*iidName++), file); + fputs("_IID", file); +} + +static gboolean +interface(TreeState *state) +{ + IDL_tree iface = state->tree, iter, orig; + char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str; + char *classNameUpper = NULL; + char *classNameImpl = NULL; + char *cp; + gboolean ok = TRUE; + gboolean keepvtable; + const char *iid; + const char *name_space; + struct nsID id; + char iid_parsed[UUID_LENGTH]; + GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments; + + if (!verify_interface_declaration(iface)) + return FALSE; + +#define FAIL do {ok = FALSE; goto out;} while(0) + + fprintf(state->file, "\n/* starting interface: %s */\n", + className); + + name_space = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "namespace"); + if (name_space) { + fprintf(state->file, "/* namespace: %s */\n", + name_space); + fprintf(state->file, "/* fully qualified name: %s.%s */\n", + name_space,className); + } + + iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid"); + if (iid) { + /* Redundant, but a better error than 'cannot parse.' */ + if (strlen(iid) != 36) { + IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid); + FAIL; + } + + /* + * Parse uuid and then output resulting nsID to string, to validate + * uuid and normalize resulting .h files. + */ + if (!xpidl_parse_iid(&id, iid)) { + IDL_tree_error(state->tree, "cannot parse IID %s\n", iid); + FAIL; + } + if (!xpidl_sprint_iid(&id, iid_parsed)) { + IDL_tree_error(state->tree, "error formatting IID %s\n", iid); + FAIL; + } + + /* #define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046" */ + fputs("#define ", state->file); + write_classname_iid_define(state->file, className); + fprintf(state->file, "_STR \"%s\"\n", iid_parsed); + fputc('\n', state->file); + + /* #define NS_ISUPPORTS_IID { {0x00000000 .... 0x46 }} */ + fprintf(state->file, "#define "); + write_classname_iid_define(state->file, className); + fprintf(state->file, " \\\n" + " {0x%.8x, 0x%.4x, 0x%.4x, \\\n" + " { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, " + "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }}\n", + id.m0, id.m1, id.m2, + id.m3[0], id.m3[1], id.m3[2], id.m3[3], + id.m3[4], id.m3[5], id.m3[6], id.m3[7]); + fputc('\n', state->file); + } else { + IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n", + className); + FAIL; + } + + if (doc_comments != NULL) + printlist(state->file, doc_comments); + + /* + * NS_NO_VTABLE is defined in nsISupportsUtils.h, and defined on windows + * to __declspec(novtable) on windows. This optimization is safe + * whenever the constructor calls no virtual methods. Writing in IDL + * almost guarantees this, except for the case when a %{C++ block occurs in + * the interface. We detect that case, and emit a macro call that disables + * the optimization. + */ + keepvtable = FALSE; + for (iter = IDL_INTERFACE(state->tree).body; + iter != NULL; + iter = IDL_LIST(iter).next) + { + IDL_tree data = IDL_LIST(iter).data; + if (IDL_NODE_TYPE(data) == IDLN_CODEFRAG) + keepvtable = TRUE; + } + + /* The interface declaration itself. */ + fprintf(state->file, + "class %s%s", + (keepvtable ? "" : "NS_NO_VTABLE "), className); + + if ((iter = IDL_INTERFACE(iface).inheritance_spec)) { + fputs(" : ", state->file); + if (IDL_LIST(iter).next != NULL) { + IDL_tree_error(iter, + "multiple inheritance is not supported by xpidl"); + FAIL; + } + fprintf(state->file, "public %s", IDL_IDENT(IDL_LIST(iter).data).str); + } + fputs(" {\n" + " public: \n\n", state->file); + if (iid) { + fputs(" NS_DEFINE_STATIC_IID_ACCESSOR(", state->file); + write_classname_iid_define(state->file, className); + fputs(")\n\n", state->file); + } + + orig = state->tree; /* It would be nice to remove this state-twiddling. */ + + state->tree = IDL_INTERFACE(iface).body; + + if (state->tree && !xpidl_process_node(state)) + FAIL; + + fputs("};\n", state->file); + fputc('\n', state->file); + + /* + * #define NS_DECL_NSIFOO - create method prototypes that can be used in + * class definitions that support this interface. + * + * Walk the tree explicitly to prototype a reworking of xpidl to get rid of + * the callback mechanism. + */ + state->tree = orig; + fputs("/* Use this macro when declaring classes that implement this " + "interface. */\n", state->file); + fputs("#define NS_DECL_", state->file); + classNameUpper = xpidl_strdup(className); + for (cp = classNameUpper; *cp != '\0'; cp++) + *cp = toupper(*cp); + fprintf(state->file, "%s \\\n", classNameUpper); + if (IDL_INTERFACE(state->tree).body == NULL) { + write_indent(state->file); + fputs("/* no methods! */\n", state->file); + } + + for (iter = IDL_INTERFACE(state->tree).body; + iter != NULL; + iter = IDL_LIST(iter).next) + { + IDL_tree data = IDL_LIST(iter).data; + + switch(IDL_NODE_TYPE(data)) { + case IDLN_OP_DCL: + write_indent(state->file); + write_method_signature(data, state->file, AS_DECL, NULL); + break; + + case IDLN_ATTR_DCL: + write_indent(state->file); + if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL)) + FAIL; + if (!IDL_ATTR_DCL(data).f_readonly) { + fputs("; \\\n", state->file); /* Terminate the previous one. */ + write_indent(state->file); + if (!write_attr_accessor(data, state->file, + FALSE, AS_DECL, NULL)) + FAIL; + /* '; \n' at end will clean up. */ + } + break; + + case IDLN_CONST_DCL: + /* ignore it here; it doesn't contribute to the macro. */ + continue; + + case IDLN_CODEFRAG: + XPIDL_WARNING((iter, IDL_WARNING1, + "%%{ .. %%} code fragment within interface " + "ignored when generating NS_DECL_%s macro; " + "if the code fragment contains method " + "declarations, the macro probably isn't " + "complete.", classNameUpper)); + continue; + + default: + IDL_tree_error(iter, + "unexpected node type %d! " + "Please file a bug against the xpidl component.", + IDL_NODE_TYPE(data)); + FAIL; + } + + if (IDL_LIST(iter).next != NULL) { + fprintf(state->file, "; \\\n"); + } else { + fprintf(state->file, "; \n"); + } + } + fputc('\n', state->file); + + /* XXX abstract above and below into one function? */ + /* + * #define NS_FORWARD_NSIFOO - create forwarding methods that can delegate + * behavior from in implementation to another object. As generated by + * idlc. + */ + fprintf(state->file, + "/* Use this macro to declare functions that forward the " + "behavior of this interface to another object. */\n" + "#define NS_FORWARD_%s(_to) \\\n", + classNameUpper); + if (IDL_INTERFACE(state->tree).body == NULL) { + write_indent(state->file); + fputs("/* no methods! */\n", state->file); + } + + for (iter = IDL_INTERFACE(state->tree).body; + iter != NULL; + iter = IDL_LIST(iter).next) + { + IDL_tree data = IDL_LIST(iter).data; + + switch(IDL_NODE_TYPE(data)) { + case IDLN_OP_DCL: + write_indent(state->file); + write_method_signature(data, state->file, AS_DECL, NULL); + fputs(" { return _to ", state->file); + write_method_signature(data, state->file, AS_CALL, NULL); + break; + + case IDLN_ATTR_DCL: + write_indent(state->file); + if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL)) + FAIL; + fputs(" { return _to ", state->file); + if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL)) + FAIL; + if (!IDL_ATTR_DCL(data).f_readonly) { + fputs("; } \\\n", state->file); /* Terminate the previous one. */ + write_indent(state->file); + if (!write_attr_accessor(data, state->file, + FALSE, AS_DECL, NULL)) + FAIL; + fputs(" { return _to ", state->file); + if (!write_attr_accessor(data, state->file, + FALSE, AS_CALL, NULL)) + FAIL; + /* '; } \n' at end will clean up. */ + } + break; + + case IDLN_CONST_DCL: + case IDLN_CODEFRAG: + continue; + + default: + FAIL; + } + + if (IDL_LIST(iter).next != NULL) { + fprintf(state->file, "; } \\\n"); + } else { + fprintf(state->file, "; } \n"); + } + } + fputc('\n', state->file); + + + /* XXX abstract above and below into one function? */ + /* + * #define NS_FORWARD_SAFE_NSIFOO - create forwarding methods that can delegate + * behavior from in implementation to another object. As generated by + * idlc. + */ + fprintf(state->file, + "/* Use this macro to declare functions that forward the " + "behavior of this interface to another object in a safe way. */\n" + "#define NS_FORWARD_SAFE_%s(_to) \\\n", + classNameUpper); + if (IDL_INTERFACE(state->tree).body == NULL) { + write_indent(state->file); + fputs("/* no methods! */\n", state->file); + } + + for (iter = IDL_INTERFACE(state->tree).body; + iter != NULL; + iter = IDL_LIST(iter).next) + { + IDL_tree data = IDL_LIST(iter).data; + + switch(IDL_NODE_TYPE(data)) { + case IDLN_OP_DCL: + write_indent(state->file); + write_method_signature(data, state->file, AS_DECL, NULL); + fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file); + write_method_signature(data, state->file, AS_CALL, NULL); + break; + + case IDLN_ATTR_DCL: + write_indent(state->file); + if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL)) + FAIL; + fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file); + if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL)) + FAIL; + if (!IDL_ATTR_DCL(data).f_readonly) { + fputs("; } \\\n", state->file); /* Terminate the previous one. */ + write_indent(state->file); + if (!write_attr_accessor(data, state->file, + FALSE, AS_DECL, NULL)) + FAIL; + fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file); + if (!write_attr_accessor(data, state->file, + FALSE, AS_CALL, NULL)) + FAIL; + /* '; } \n' at end will clean up. */ + } + break; + + case IDLN_CONST_DCL: + case IDLN_CODEFRAG: + continue; + + default: + FAIL; + } + + if (IDL_LIST(iter).next != NULL) { + fprintf(state->file, "; } \\\n"); + } else { + fprintf(state->file, "; } \n"); + } + } + fputc('\n', state->file); + + /* + * Build a sample implementation template. + */ + if (strlen(className) >= 3 && className[2] == 'I') { + classNameImpl = xpidl_strdup(className); + if (!classNameImpl) + FAIL; + memmove(&classNameImpl[2], &classNameImpl[3], strlen(classNameImpl) - 2); + } else { + classNameImpl = xpidl_strdup("_MYCLASS_"); + if (!classNameImpl) + FAIL; + } + + fputs("#if 0\n" + "/* Use the code below as a template for the " + "implementation class for this interface. */\n" + "\n" + "/* Header file */" + "\n", + state->file); + fprintf(state->file, "class %s : public %s\n", classNameImpl, className); + fputs("{\n" + "public:\n", state->file); + write_indent(state->file); + fputs("NS_DECL_ISUPPORTS\n", state->file); + write_indent(state->file); + fprintf(state->file, "NS_DECL_%s\n", classNameUpper); + fputs("\n", state->file); + write_indent(state->file); + fprintf(state->file, "%s();\n", classNameImpl); + fputs("\n" + "private:\n", state->file); + write_indent(state->file); + fprintf(state->file, "~%s();\n", classNameImpl); + fputs("\n" + "protected:\n", state->file); + write_indent(state->file); + fputs("/* additional members */\n", state->file); + fputs("};\n\n", state->file); + + fputs("/* Implementation file */\n", state->file); + + fprintf(state->file, + "NS_IMPL_ISUPPORTS1(%s, %s)\n", classNameImpl, className); + fputs("\n", state->file); + + fprintf(state->file, "%s::%s()\n", classNameImpl, classNameImpl); + fputs("{\n", state->file); + write_indent(state->file); + fputs("/* member initializers and constructor code */\n", state->file); + fputs("}\n\n", state->file); + + fprintf(state->file, "%s::~%s()\n", classNameImpl, classNameImpl); + fputs("{\n", state->file); + write_indent(state->file); + fputs("/* destructor code */\n", state->file); + fputs("}\n\n", state->file); + + for (iter = IDL_INTERFACE(state->tree).body; + iter != NULL; + iter = IDL_LIST(iter).next) + { + IDL_tree data = IDL_LIST(iter).data; + + switch(IDL_NODE_TYPE(data)) { + case IDLN_OP_DCL: + /* It would be nice to remove this state-twiddling. */ + orig = state->tree; + state->tree = data; + xpidl_write_comment(state, 0); + state->tree = orig; + + write_method_signature(data, state->file, AS_IMPL, classNameImpl); + fputs("\n{\n", state->file); + write_indent(state->file); + write_indent(state->file); + fputs("return NS_ERROR_NOT_IMPLEMENTED;\n" + "}\n" + "\n", state->file); + break; + + case IDLN_ATTR_DCL: + /* It would be nice to remove this state-twiddling. */ + orig = state->tree; + state->tree = data; + xpidl_write_comment(state, 0); + state->tree = orig; + + if (!write_attr_accessor(data, state->file, TRUE, + AS_IMPL, classNameImpl)) + FAIL; + fputs("\n{\n", state->file); + write_indent(state->file); + write_indent(state->file); + fputs("return NS_ERROR_NOT_IMPLEMENTED;\n" + "}\n", state->file); + + if (!IDL_ATTR_DCL(data).f_readonly) { + if (!write_attr_accessor(data, state->file, FALSE, + AS_IMPL, classNameImpl)) + FAIL; + fputs("\n{\n", state->file); + write_indent(state->file); + write_indent(state->file); + fputs("return NS_ERROR_NOT_IMPLEMENTED;\n" + "}\n", state->file); + } + fputs("\n", state->file); + break; + + case IDLN_CONST_DCL: + case IDLN_CODEFRAG: + continue; + + default: + FAIL; + } + } + + fputs("/* End of implementation class template. */\n" + "#endif\n" + "\n", state->file); + +#undef FAIL + +out: + if (classNameUpper) + free(classNameUpper); + if (classNameImpl) + free(classNameImpl); + return ok; +} + +static gboolean +list(TreeState *state) +{ + IDL_tree iter; + for (iter = state->tree; iter; iter = IDL_LIST(iter).next) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + return TRUE; +} + +static gboolean +write_type(IDL_tree type_tree, gboolean is_out, FILE *outfile) +{ + if (!type_tree) { + fputs("void", outfile); + return TRUE; + } + + switch (IDL_NODE_TYPE(type_tree)) { + case IDLN_TYPE_INTEGER: { + gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed; + switch (IDL_TYPE_INTEGER(type_tree).f_type) { + case IDL_INTEGER_TYPE_SHORT: + fputs(sign ? "PRInt16" : "PRUint16", outfile); + break; + case IDL_INTEGER_TYPE_LONG: + fputs(sign ? "PRInt32" : "PRUint32", outfile); + break; + case IDL_INTEGER_TYPE_LONGLONG: + fputs(sign ? "PRInt64" : "PRUint64", outfile); + break; + default: + g_error("Unknown integer type %d\n", + IDL_TYPE_INTEGER(type_tree).f_type); + return FALSE; + } + break; + } + case IDLN_TYPE_CHAR: + fputs("char", outfile); + break; + case IDLN_TYPE_WIDE_CHAR: + fputs("PRUnichar", outfile); /* wchar_t? */ + break; + case IDLN_TYPE_WIDE_STRING: + fputs("PRUnichar *", outfile); + break; + case IDLN_TYPE_STRING: + fputs("char *", outfile); + break; + case IDLN_TYPE_BOOLEAN: + fputs("PRBool", outfile); + break; + case IDLN_TYPE_OCTET: + fputs("PRUint8", outfile); + break; + case IDLN_TYPE_FLOAT: + switch (IDL_TYPE_FLOAT(type_tree).f_type) { + case IDL_FLOAT_TYPE_FLOAT: + fputs("float", outfile); + break; + case IDL_FLOAT_TYPE_DOUBLE: + fputs("double", outfile); + break; + /* XXX 'long double' just ignored, or what? */ + default: + fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree)); + break; + } + break; + case IDLN_IDENT: + if (UP_IS_NATIVE(type_tree)) { + if (IDL_tree_property_get(type_tree, "domstring") || + IDL_tree_property_get(type_tree, "astring")) { + fputs("nsAString", outfile); + } else if (IDL_tree_property_get(type_tree, "utf8string")) { + fputs("nsACString", outfile); + } else if (IDL_tree_property_get(type_tree, "cstring")) { + fputs("nsACString", outfile); + } else { + fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile); + } + if (IDL_tree_property_get(type_tree, "ptr")) { + fputs(" *", outfile); + } else if (IDL_tree_property_get(type_tree, "ref")) { + fputs(" &", outfile); + } + } else { + fputs(IDL_IDENT(type_tree).str, outfile); + } + if (UP_IS_AGGREGATE(type_tree)) + fputs(" *", outfile); + break; + default: + fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree)); + break; + } + return TRUE; +} + +/* + * An attribute declaration looks like: + * + * [ IDL_ATTR_DCL] + * - param_type_spec [IDL_TYPE_* or NULL for void] + * - simple_declarations [IDL_LIST] + * - data [IDL_IDENT] + * - next [IDL_LIST or NULL if no more idents] + * - data [IDL_IDENT] + */ + +#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data)) +#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec) +#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree))) + +/* + * AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)' + * AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)' + * AS_CALL writes 'foo(bar, sil)' + */ +static gboolean +write_attr_accessor(IDL_tree attr_tree, FILE * outfile, + gboolean getter, int mode, const char *className) +{ + char *attrname = ATTR_IDENT(attr_tree).str; + + if (mode == AS_DECL) { + fputs("NS_IMETHOD ", outfile); + } else if (mode == AS_IMPL) { + fprintf(outfile, "NS_IMETHODIMP %s::", className); + } + fprintf(outfile, "%cet%c%s(", + getter ? 'G' : 'S', + toupper(*attrname), attrname + 1); + if (mode == AS_DECL || mode == AS_IMPL) { + /* Setters for string, wstring, nsid, domstring, utf8string, + * cstring and astring get const. + */ + if (!getter && + (IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_STRING || + IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_WIDE_STRING || + IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "nsid") || + IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "domstring") || + IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "utf8string") || + IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "cstring") || + IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "astring"))) + { + fputs("const ", outfile); + } + + if (!write_type(ATTR_TYPE_DECL(attr_tree), getter, outfile)) + return FALSE; + fprintf(outfile, "%s%s", + (STARRED_TYPE(attr_tree) ? "" : " "), + (getter && !DIPPER_TYPE(ATTR_TYPE_DECL(attr_tree)))? "*" : ""); + } + fprintf(outfile, "a%c%s)", toupper(attrname[0]), attrname + 1); + return TRUE; +} + +static gboolean +attr_dcl(TreeState *state) +{ + GSList *doc_comments; + + if (!verify_attribute_declaration(state->tree)) + return FALSE; + + doc_comments = + IDL_IDENT(IDL_LIST(IDL_ATTR_DCL + (state->tree).simple_declarations).data).comments; + + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); + } + + /* + * XXX lists of attributes with the same type, e.g. + * attribute string foo, bar sil; + * are legal IDL... but we don't do anything with 'em. + */ + if (IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).next != NULL) { + XPIDL_WARNING((state->tree, IDL_WARNING1, + "multiple attributes in a single declaration aren't " + "currently supported by xpidl")); + } + + xpidl_write_comment(state, 2); + + write_indent(state->file); + if (!write_attr_accessor(state->tree, state->file, TRUE, AS_DECL, NULL)) + return FALSE; + fputs(" = 0;\n", state->file); + + if (!IDL_ATTR_DCL(state->tree).f_readonly) { + write_indent(state->file); + if (!write_attr_accessor(state->tree, state->file, FALSE, AS_DECL, NULL)) + return FALSE; + fputs(" = 0;\n", state->file); + } + fputc('\n', state->file); + + return TRUE; +} + +static gboolean +do_enum(TreeState *state) +{ + IDL_tree_error(state->tree, "enums not supported, " + "see http://bugzilla.mozilla.org/show_bug.cgi?id=8781"); + return FALSE; +} + +static gboolean +do_const_dcl(TreeState *state) +{ + struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree); + const char *name = IDL_IDENT(dcl->ident).str; + gboolean is_signed; + GSList *doc_comments = IDL_IDENT(dcl->ident).comments; + IDL_tree real_type; + const char *const_format; + + if (!verify_const_declaration(state->tree)) + return FALSE; + + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); + } + + /* Could be a typedef; try to map it to the real type. */ + real_type = find_underlying_type(dcl->const_type); + real_type = real_type ? real_type : dcl->const_type; + is_signed = IDL_TYPE_INTEGER(real_type).f_signed; + + const_format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "uU"; + write_indent(state->file); + fprintf(state->file, "enum { %s = ", name); + fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value); + fprintf(state->file, " };\n\n"); + + return TRUE; +} + +static gboolean +do_typedef(TreeState *state) +{ + IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec; + IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls; + IDL_tree complex; + GSList *doc_comments; + + if (IDL_NODE_TYPE(type) == IDLN_TYPE_SEQUENCE) { + XPIDL_WARNING((state->tree, IDL_WARNING1, + "sequences not supported, ignored")); + } else { + if (IDL_NODE_TYPE(complex = IDL_LIST(dcls).data) == IDLN_TYPE_ARRAY) { + IDL_tree dim = IDL_TYPE_ARRAY(complex).size_list; + doc_comments = IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).comments; + + if (doc_comments != NULL) + printlist(state->file, doc_comments); + + fputs("typedef ", state->file); + if (!write_type(type, FALSE, state->file)) + return FALSE; + fputs(" ", state->file); + + fprintf(state->file, "%s", + IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).str); + do { + fputc('[', state->file); + if (IDL_LIST(dim).data) { + fprintf(state->file, "%ld", + (long)IDL_INTEGER(IDL_LIST(dim).data).value); + } + fputc(']', state->file); + } while ((dim = IDL_LIST(dim).next) != NULL); + } else { + doc_comments = IDL_IDENT(IDL_LIST(dcls).data).comments; + + if (doc_comments != NULL) + printlist(state->file, doc_comments); + + fputs("typedef ", state->file); + if (!write_type(type, FALSE, state->file)) + return FALSE; + fputs(" ", state->file); + fputs(IDL_IDENT(IDL_LIST(dcls).data).str, state->file); + } + fputs(";\n\n", state->file); + } + return TRUE; +} + +/* + * param generation: + * in string foo --> nsString *foo + * out string foo --> nsString **foo; + * inout string foo --> nsString **foo; + */ + +/* If notype is true, just write the param name. */ +static gboolean +write_param(IDL_tree param_tree, FILE *outfile) +{ + IDL_tree param_type_spec = IDL_PARAM_DCL(param_tree).param_type_spec; + gboolean is_in = IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_IN; + /* in string, wstring, nsid, domstring, utf8string, cstring and + * astring any explicitly marked [const] are const + */ + + if (is_in && + (IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_STRING || + IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_WIDE_STRING || + IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator, + "const") || + IDL_tree_property_get(param_type_spec, "nsid") || + IDL_tree_property_get(param_type_spec, "domstring") || + IDL_tree_property_get(param_type_spec, "utf8string") || + IDL_tree_property_get(param_type_spec, "cstring") || + IDL_tree_property_get(param_type_spec, "astring"))) { + fputs("const ", outfile); + } + else if (IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_OUT && + IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator, + "shared")) { + fputs("const ", outfile); + } + + if (!write_type(param_type_spec, !is_in, outfile)) + return FALSE; + + /* unless the type ended in a *, add a space */ + if (!STARRED_TYPE(param_type_spec)) + fputc(' ', outfile); + + /* out and inout params get a bonus '*' (unless this is type that has a + * 'dipper' class that is passed in to receive 'out' data) + */ + if (IDL_PARAM_DCL(param_tree).attr != IDL_PARAM_IN && + !DIPPER_TYPE(param_type_spec)) { + fputc('*', outfile); + } + /* arrays get a bonus * too */ + /* XXX Should this be a leading '*' or a trailing "[]" ?*/ + if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator, + "array")) + fputc('*', outfile); + + fputs(IDL_IDENT(IDL_PARAM_DCL(param_tree).simple_declarator).str, outfile); + + return TRUE; +} + +/* + * A forward declaration, usually an interface. + */ +static gboolean +forward_dcl(TreeState *state) +{ + IDL_tree iface = state->tree; + const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str; + + if (!className) + return FALSE; + + fprintf(state->file, "class %s; /* forward declaration */\n\n", className); + return TRUE; +} + +/* + * Shared between the interface class declaration and the NS_DECL_IFOO macro + * provided to aid declaration of implementation classes. + * mode... + * AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)' + * AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)' + * AS_CALL writes 'foo(bar, sil)' + */ +static gboolean +write_method_signature(IDL_tree method_tree, FILE *outfile, int mode, + const char *className) +{ + struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree); + gboolean no_generated_args = TRUE; + gboolean op_notxpcom = + (IDL_tree_property_get(op->ident, "notxpcom") != NULL); + const char *name; + IDL_tree iter; + + if (mode == AS_DECL) { + if (op_notxpcom) { + fputs("NS_IMETHOD_(", outfile); + if (!write_type(op->op_type_spec, FALSE, outfile)) + return FALSE; + fputc(')', outfile); + } else { + fputs("NS_IMETHOD", outfile); + } + fputc(' ', outfile); + } + else if (mode == AS_IMPL) { + if (op_notxpcom) { + fputs("NS_IMETHODIMP_(", outfile); + if (!write_type(op->op_type_spec, FALSE, outfile)) + return FALSE; + fputc(')', outfile); + } else { + fputs("NS_IMETHODIMP", outfile); + } + fputc(' ', outfile); + } + name = IDL_IDENT(op->ident).str; + if (mode == AS_IMPL) { + fprintf(outfile, "%s::%c%s(", className, toupper(*name), name + 1); + } else { + fprintf(outfile, "%c%s(", toupper(*name), name + 1); + } + for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) { + if (mode == AS_DECL || mode == AS_IMPL) { + if (!write_param(IDL_LIST(iter).data, outfile)) + return FALSE; + } else { + fputs(IDL_IDENT(IDL_PARAM_DCL(IDL_LIST(iter).data) + .simple_declarator).str, + outfile); + } + if ((IDL_LIST(iter).next || + (!op_notxpcom && op->op_type_spec) || op->f_varargs)) + fputs(", ", outfile); + no_generated_args = FALSE; + } + + /* make IDL return value into trailing out argument */ + if (op->op_type_spec && !op_notxpcom) { + IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT, + op->op_type_spec, + IDL_ident_new("_retval")); + if (!fake_param) + return FALSE; + if (mode == AS_DECL || mode == AS_IMPL) { + if (!write_param(fake_param, outfile)) + return FALSE; + } else { + fputs("_retval", outfile); + } + if (op->f_varargs) + fputs(", ", outfile); + no_generated_args = FALSE; + } + + /* varargs go last */ + if (op->f_varargs) { + if (mode == AS_DECL || mode == AS_IMPL) { + fputs("nsVarArgs *", outfile); + } + fputs("_varargs", outfile); + no_generated_args = FALSE; + } + + /* + * If generated method has no arguments, output 'void' to avoid C legacy + * behavior of disabling type checking. + */ + if (no_generated_args && mode == AS_DECL) { + fputs("void", outfile); + } + + fputc(')', outfile); + + return TRUE; +} + +/* + * A method is an `operation', therefore a method decl is an `op dcl'. + * I blame Elliot. + */ +static gboolean +op_dcl(TreeState *state) +{ + GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments; + + /* + * Verify that e.g. non-scriptable methods in [scriptable] interfaces + * are declared so. Do this in a separate verification pass? + */ + if (!verify_method_declaration(state->tree)) + return FALSE; + + if (doc_comments != NULL) { + write_indent(state->file); + printlist(state->file, doc_comments); + } + xpidl_write_comment(state, 2); + + write_indent(state->file); + if (!write_method_signature(state->tree, state->file, AS_DECL, NULL)) + return FALSE; + fputs(" = 0;\n\n", state->file); + + return TRUE; +} + +static void +write_codefrag_line(gpointer data, gpointer user_data) +{ + TreeState *state = (TreeState *)user_data; + const char *line = (const char *)data; + fputs(line, state->file); + fputc('\n', state->file); +} + +static gboolean +codefrag(TreeState *state) +{ + const char *desc = IDL_CODEFRAG(state->tree).desc; + GSList *lines = IDL_CODEFRAG(state->tree).lines; + guint fragment_length; + + if (strcmp(desc, "C++") && /* libIDL bug? */ strcmp(desc, "C++\r")) { + XPIDL_WARNING((state->tree, IDL_WARNING1, + "ignoring '%%{%s' escape. " + "(Use '%%{C++' to escape verbatim C++ code.)", desc)); + + return TRUE; + } + + /* + * Emit #file directive to point debuggers back to the original .idl file + * for the duration of the code fragment. We look at internal IDL node + * properties _file, _line to do this; hopefully they won't change. + * + * _line seems to refer to the line immediately after the closing %}, so + * we backtrack to get the proper line for the beginning of the block. + */ + /* + * Looks like getting this right means maintaining an accurate line + * count of everything generated, so we can set the file back to the + * correct line in the generated file afterwards. Skipping for now... + */ + + fragment_length = g_slist_length(lines); +/* fprintf(state->file, "#line %d \"%s\"\n", */ +/* state->tree->_line - fragment_length - 1, */ +/* state->tree->_file); */ + + g_slist_foreach(lines, write_codefrag_line, (gpointer)state); + + return TRUE; +} + +backend * +xpidl_header_dispatch(void) +{ + static backend result; + static nodeHandler table[IDLN_LAST]; + static gboolean initialized = FALSE; + + result.emit_prolog = header_prolog; + result.emit_epilog = header_epilog; + + if (!initialized) { + table[IDLN_LIST] = list; + table[IDLN_ATTR_DCL] = attr_dcl; + table[IDLN_OP_DCL] = op_dcl; + table[IDLN_FORWARD_DCL] = forward_dcl; + table[IDLN_TYPE_ENUM] = do_enum; + table[IDLN_INTERFACE] = interface; + table[IDLN_CODEFRAG] = codefrag; + table[IDLN_TYPE_DCL] = do_typedef; + table[IDLN_CONST_DCL] = do_const_dcl; + table[IDLN_NATIVE] = check_native; + initialized = TRUE; + } + + result.dispatch_table = table; + return &result; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c new file mode 100644 index 00000000..175f379a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c @@ -0,0 +1,836 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Ang <mang@subcarrier.org> + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Common IDL-processing code. + */ + +#include "xpidl.h" + +#ifdef XP_MAC +#include <stat.h> +#endif + +static gboolean parsed_empty_file; + +/* + * The bulk of the generation happens here. + */ +gboolean +xpidl_process_node(TreeState *state) +{ + gint type; + nodeHandler *dispatch, handler; + + XPT_ASSERT(state->tree); + type = IDL_NODE_TYPE(state->tree); + + if ((dispatch = state->dispatch) && (handler = dispatch[type])) + return handler(state); + return TRUE; +} + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) +extern void mac_warning(const char* warning_message); +#endif + +static int +msg_callback(int level, int num, int line, const char *file, + const char *message) +{ + char *warning_message; + + /* + * Egregious hack to permit empty files. + * XXX libIDL needs an API to detect this case robustly. + */ + if (0 == strcmp(message, "File empty after optimization")) { + parsed_empty_file = TRUE; + return 1; + } + + if (!file) + file = "<unknown file>"; + warning_message = g_strdup_printf("%s:%d: %s\n", file, line, message); + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) + mac_warning(warning_message); +#else + fputs(warning_message, stderr); +#endif + + g_free(warning_message); + return 1; +} + +/* + * To keep track of the state associated with a given input file. The 'next' + * field lets us maintain a stack of input files. + */ +typedef struct input_data { + char *filename; /* where did I come from? */ + unsigned int lineno; /* last lineno processed */ + char *buf; /* contents of file */ + char *point; /* next char to feed to libIDL */ + char *max; /* 1 past last char in buf */ + struct input_data *next; /* file from which we were included */ +} input_data; + +/* + * Passed to us by libIDL. Holds global information and the current stack of + * include files. + */ +typedef struct input_callback_state { + struct input_data *input_stack; /* linked list of input_data */ + GHashTable *already_included; /* to prevent redundant includes */ + IncludePathEntry *include_path; /* search path for included files */ + GSList *base_includes; /* to accumulate #includes from *first* file; + * for passing thru TreeState to + * xpidl_header backend. */ +} input_callback_state; + +static FILE * +fopen_from_includes(const char *filename, const char *mode, + IncludePathEntry *include_path) +{ + IncludePathEntry *current_path = include_path; + char *pathname; + FILE *inputfile; + if (!strcmp(filename, "-")) + return stdin; + + if (filename[0] != '/') { + while (current_path) { + pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", + current_path->directory, filename); + if (!pathname) + return NULL; + inputfile = fopen(pathname, mode); + g_free(pathname); + if (inputfile) + return inputfile; + current_path = current_path->next; + } + } else { + inputfile = fopen(filename, mode); + if (inputfile) + return inputfile; + } + return NULL; +} + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) +extern FILE* mac_fopen(const char* filename, const char *mode); +#endif + +static input_data * +new_input_data(const char *filename, IncludePathEntry *include_path) +{ + input_data *new_data; + FILE *inputfile; + char *buffer = NULL; + size_t offset = 0; + size_t buffer_size; +#ifdef XP_MAC + size_t i; +#endif + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) + /* on Mac, fopen knows how to find files. */ + inputfile = fopen(filename, "r"); +#elif defined(XP_OS2) || defined(XP_WIN32) + /* + * if filename is fully qualified (starts with driver letter), then + * just call fopen(); else, go with fopen_from_includes() + */ + if( filename[1] == ':' ) + inputfile = fopen(filename, "r"); + else + inputfile = fopen_from_includes(filename, "r", include_path); +#else + inputfile = fopen_from_includes(filename, "r", include_path); +#endif + + if (!inputfile) + return NULL; + +#ifdef XP_MAC + { + struct stat input_stat; + if (fstat(fileno(inputfile), &input_stat)) + return NULL; + buffer = malloc(input_stat.st_size + 1); + if (!buffer) + return NULL; + offset = fread(buffer, 1, input_stat.st_size, inputfile); + if (ferror(inputfile)) + return NULL; + } +#else + /* + * Rather than try to keep track of many different varieties of state + * around the boundaries of a circular buffer, we just read in the entire + * file. + * + * We iteratively grow the buffer here; an alternative would be to use + * stat to find the exact buffer size we need, as xpt_dump does. + */ + for (buffer_size = 8191; ; buffer_size *= 2) { + size_t just_read; + buffer = realloc(buffer, buffer_size + 1); /* +1 for trailing nul */ + just_read = fread(buffer + offset, 1, buffer_size - offset, inputfile); + if (ferror(inputfile)) + return NULL; + + if (just_read < buffer_size - offset || just_read == 0) { + /* Done reading. */ + offset += just_read; + break; + } + offset += just_read; + } +#endif + + fclose(inputfile); + +#ifdef XP_MAC + /* + * libIDL doesn't speak '\r' properly - always make sure lines end with + * '\n'. + */ + for (i = 0; i < offset; i++) { + if (buffer[i] == '\r') + buffer[i] = '\n'; + } +#endif + + new_data = xpidl_malloc(sizeof (struct input_data)); + new_data->point = new_data->buf = buffer; + new_data->max = buffer + offset; + *new_data->max = '\0'; + new_data->filename = xpidl_strdup(filename); + /* libIDL expects the line number to be that of the *next* line */ + new_data->lineno = 2; + new_data->next = NULL; + + return new_data; +} + +/* process pending raw section */ +static int +NextIsRaw(input_data *data, char **startp, int *lenp) +{ + char *end, *start; + + /* + * XXXmccabe still needed: an in_raw flag to handle the case where we're in + * a raw block, but haven't managed to copy it all to xpidl. This will + * happen when we have a raw block larger than + * IDL_input_data->fill.max_size (currently 8192.) + */ + if (!(data->point[0] == '%' && data->point[1] == '{')) + return 0; + + start = *startp = data->point; + + end = NULL; + while (start < data->max && (end = strstr(start, "%}"))) { + if (end[-1] == '\r' || + end[-1] == '\n') + break; + start = end + 1; + } + + if (end && start < data->max) { + *lenp = end - data->point + 2; + return 1; + } else { + const char *filename; + int lineno; + + IDL_file_get(&filename, &lineno); + msg_callback(IDL_ERROR, 0, lineno, filename, + "unterminated %{ block"); + return -1; + } +} + +/* process pending comment */ +static int +NextIsComment(input_data *data, char **startp, int *lenp) +{ + char *end; + + if (!(data->point[0] == '/' && data->point[1] == '*')) + return 0; + + end = strstr(data->point, "*/"); + *lenp = 0; + if (end) { + int skippedLines = 0; + char *tempPoint; + + /* get current lineno */ + IDL_file_get(NULL,(int *)&data->lineno); + + /* get line count */ + for (tempPoint = data->point; tempPoint < end; tempPoint++) { + if (*tempPoint == '\n') + skippedLines++; + } + + data->lineno += skippedLines; + IDL_file_set(data->filename, (int)data->lineno); + + *startp = end + 2; + + /* If it's a ** comment, tell libIDL about it. */ + if (data->point[2] == '*') { + /* hack termination. +2 to get past '*' '/' */ + char t = *(end + 2); + *(end + 2) = '\0'; + IDL_queue_new_ident_comment(data->point); + *(end + 2) = t; + } + + data->point = *startp; /* XXXmccabe move this out of function? */ + return 1; + } else { + const char *filename; + int lineno; + + IDL_file_get(&filename, &lineno); + msg_callback(IDL_ERROR, 0, lineno, filename, + "unterminated comment"); + return -1; + } +} + +static int +NextIsInclude(input_callback_state *callback_state, char **startp, + int *lenp) +{ + input_data *data = callback_state->input_stack; + input_data *new_data; + char *filename, *end; + const char *scratch; + + /* process the #include that we're in now */ + if (strncmp(data->point, "#include \"", 10)) { + return 0; + } + + filename = data->point + 10; /* skip #include " */ + XPT_ASSERT(filename < data->max); + end = filename; + while (end < data->max) { + if (*end == '\"' || *end == '\n' || *end == '\r') + break; + end++; + } + + if (*end != '\"') { + /* + * Didn't find end of include file. Scan 'til next whitespace to find + * some reasonable approximation of the filename, and use it to report + * an error. + */ + + end = filename; + while (end < data->max) { + if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t') + break; + end++; + } + *end = '\0'; + + /* make sure we have accurate line info */ + IDL_file_get(&scratch, (int *)&data->lineno); + fprintf(stderr, + "%s:%u: didn't find end of quoted include name \"%s\n", + scratch, data->lineno, filename); + return -1; + } + + *end = '\0'; + *startp = end + 1; + + if (data->next == NULL) { + /* + * If we're in the initial file, add this filename to the list + * of filenames to be turned into #include "filename.h" + * directives in xpidl_header.c. We do it here rather than in the + * block below so it still gets added to the list even if it's + * already been recursively included from some other file. + */ + char *filename_cp = xpidl_strdup(filename); + + /* note that g_slist_append accepts and likes null as list-start. */ + callback_state->base_includes = + g_slist_append(callback_state->base_includes, filename_cp); + } + + /* store offset for when we pop, or if we skip this one */ + data->point = *startp; + + if (!g_hash_table_lookup(callback_state->already_included, filename)) { + filename = xpidl_strdup(filename); + g_hash_table_insert(callback_state->already_included, + filename, (void *)TRUE); + new_data = new_input_data(filename, callback_state->include_path); + if (!new_data) { + char *error_message; + IDL_file_get(&scratch, (int *)&data->lineno); + error_message = + g_strdup_printf("can't open included file %s for reading\n", + filename); + msg_callback(IDL_ERROR, 0, + data->lineno, scratch, error_message); + g_free(error_message); + return -1; + } + + new_data->next = data; + /* tell libIDL to exclude this IDL from the toplevel tree */ + IDL_inhibit_push(); + IDL_file_get(&scratch, (int *)&data->lineno); + callback_state->input_stack = new_data; + IDL_file_set(new_data->filename, (int)new_data->lineno); + } + + *lenp = 0; /* this is magic, see the comment below */ + return 1; +} + +static void +FindSpecial(input_data *data, char **startp, int *lenp) +{ + char *point = data->point; + + /* magic sequences are: + * "%{" raw block + * "/\*" comment + * "#include \"" include + * The first and last want a newline [\r\n] before, or the start of the + * file. + */ + +#define LINE_START(data, point) (point == data->buf || \ + (point > data->point && \ + (point[-1] == '\r' || point[-1] == '\n'))) + + while (point < data->max) { + if (point[0] == '/' && point[1] == '*') + break; + if (LINE_START(data, point)) { + if (point[0] == '%' && point[1] == '{') + break; + if (point[0] == '#' && !strncmp(point + 1, "include \"", 9)) + break; + } + point++; + } + +#undef LINE_START + + *startp = data->point; + *lenp = point - data->point; +} + +/* set this with a debugger to see exactly what libIDL sees */ +static FILE *tracefile; + +static int +input_callback(IDL_input_reason reason, union IDL_input_data *cb_data, + gpointer user_data) +{ + input_callback_state *callback_state = user_data; + input_data *data = callback_state->input_stack; + input_data *new_data = NULL; + unsigned int len, copy; + int rv; + char *start; + + switch(reason) { + case IDL_INPUT_REASON_INIT: + if (data == NULL || data->next == NULL) { + /* + * This is the first file being processed. As it's the target + * file, we only look for it in the first entry in the include + * path, which we assume to be the current directory. + */ + + /* XXXmccabe proper assumption? Do we handle files in other + directories? */ + + IncludePathEntry first_entry; + + first_entry.directory = callback_state->include_path->directory; + first_entry.next = NULL; + + new_data = new_input_data(cb_data->init.filename, + &first_entry); + } else { + new_data = new_input_data(cb_data->init.filename, + callback_state->include_path); + } + + if (!new_data) + return -1; + + IDL_file_set(new_data->filename, (int)new_data->lineno); + callback_state->input_stack = new_data; + return 0; + + case IDL_INPUT_REASON_FILL: + start = NULL; + len = 0; + + while (data->point >= data->max) { + if (!data->next) + return 0; + + /* Current file is done; revert to including file */ + callback_state->input_stack = data->next; + free(data->filename); + free(data->buf); + free(data); + data = callback_state->input_stack; + + IDL_file_set(data->filename, (int)data->lineno); + IDL_inhibit_pop(); + } + + /* + * Now we scan for sequences which require special attention: + * \n#include begins an include statement + * \n%{ begins a raw-source block + * /\* begins a comment + * + * We used to be fancier here, so make sure that we sent the most + * data possible at any given time. To that end, we skipped over + * \n%{ raw \n%} blocks and then _continued_ the search for special + * sequences like \n#include or /\* comments . + * + * It was really ugly, though -- liberal use of goto! lots of implicit + * state! what fun! -- so now we just do this: + * + * if (special at start) { + * process that special - + * - raw: send it to libIDL, and don't look inside for specials + * - comments: adjust point and start over + * - includes: push new input_data struct for included file, and + * start over + * } else { + * scan for next special + * send data up to that special to libIDL + * } + * + * If len is set to zero, it is a sentinel value indicating we a comment + * or include was found, and parsing should start over. + * + * XXX const string foo = "/\*" will just screw us horribly. + * Hm but. We could treat strings as we treat raw blocks, eh? + */ + + /* + * Order is important, so that you can have /\* comments and + * #includes within raw sections, and so that you can comment out + * #includes. + */ + rv = NextIsRaw(data, &start, (int *)&len); + if (rv == -1) return -1; + if (!rv) { + /* + * When NextIsComment succeeds, it returns a 0 len (requesting a + * restart) and adjusts data->point to pick up after the comment. + */ + rv = NextIsComment(data, &start, (int *)&len); + if (rv == -1) return -1; + if (!rv) { + /* + * NextIsInclude might push a new input_data struct; if so, it + * will return a 0 len, letting the callback pick up the new + * file the next time around. + */ + rv = NextIsInclude(callback_state, &start, (int *)&len); + if (rv == -1) return -1; + if (!rv) + FindSpecial(data, &start, (int *)&len); + } + } + + if (len == 0) { + /* + * len == 0 is a sentinel value that means we found a comment or + * include. If we found a comment, point has been adjusted to + * point past the comment. If we found an include, a new input_data + * has been pushed. In both cases, calling the input_callback again + * will pick up the new state. + */ + return input_callback(reason, cb_data, user_data); + } + + copy = MIN(len, (unsigned int) cb_data->fill.max_size); + memcpy(cb_data->fill.buffer, start, copy); + data->point = start + copy; + + if (tracefile) + fwrite(cb_data->fill.buffer, copy, 1, tracefile); + + return copy; + + case IDL_INPUT_REASON_ABORT: + case IDL_INPUT_REASON_FINISH: + while (data != NULL) { + input_data *next; + + next = data->next; + free(data->filename); + free(data->buf); + free(data); + data = next; + } + return 0; + + default: + g_error("unknown input reason %d!", reason); + return -1; + } +} + +static void +free_ghash_key(gpointer key, gpointer value, gpointer user_data) +{ + /* We're only storing TRUE in the value... */ + free(key); +} + +static void +free_gslist_data(gpointer data, gpointer user_data) +{ + free(data); +} + +/* Pick up unlink. */ +#ifdef XP_UNIX +#include <unistd.h> +#elif XP_WIN +/* We get it from stdio.h. */ +#endif + +int +xpidl_process_idl(char *filename, IncludePathEntry *include_path, + char *file_basename, ModeData *mode) +{ + char *tmp, *outname, *real_outname = NULL; + IDL_tree top; + TreeState state; + int rv; + input_callback_state callback_state; + gboolean ok = TRUE; + backend *emitter; + + callback_state.input_stack = NULL; + callback_state.base_includes = NULL; + callback_state.include_path = include_path; + callback_state.already_included = g_hash_table_new(g_str_hash, g_str_equal); + + if (!callback_state.already_included) { + fprintf(stderr, "failed to create hashtable. out of memory?\n"); + return 0; + } + + state.basename = xpidl_strdup(filename); + + /* if basename has an .extension, truncate it. */ + tmp = strrchr(state.basename, '.'); + if (tmp) + *tmp = '\0'; + + if (!file_basename) + outname = xpidl_strdup(state.basename); + else + outname = xpidl_strdup(file_basename); + + /* so we don't include it again! */ + g_hash_table_insert(callback_state.already_included, + xpidl_strdup(filename), (void *)TRUE); + + parsed_empty_file = FALSE; + + rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state, + msg_callback, &top, + &state.ns, + IDLF_IGNORE_FORWARDS | + IDLF_XPIDL, + enable_warnings ? IDL_WARNING1 : + IDL_ERROR); + if (parsed_empty_file) { + /* + * If we've detected (via hack in msg_callback) that libIDL returned + * failure because it found a file with no IDL, set the parse tree to + * null and proceed. Allowing this is useful to permit .idl files that + * collect #includes. + */ + top = NULL; + state.ns = NULL; + } else if (rv != IDL_SUCCESS) { + if (rv == -1) { + g_warning("Parse of %s failed: %s", filename, g_strerror(errno)); + } else { + g_warning("Parse of %s failed", filename); + } + return 0; + } + + state.basename = xpidl_strdup(filename); + tmp = strrchr(state.basename, '.'); + if (tmp) + *tmp = '\0'; + + /* so xpidl_header.c can use it to generate a list of #include directives */ + state.base_includes = callback_state.base_includes; + + emitter = mode->factory(); + state.dispatch = emitter->dispatch_table; + + if (strcmp(outname, "-")) { + const char *fopen_mode; + char *out_basename; + + /* explicit_output_filename can't be true without a filename */ + if (explicit_output_filename) { + real_outname = g_strdup(outname); + } else { +/* + *This combination seems a little strange, what about OS/2? + * Assume it's some build issue + */ +#if defined(XP_UNIX) || defined(XP_WIN) + if (!file_basename) { + out_basename = xpidl_basename(outname); + } else { + out_basename = outname; + } +#else + out_basename = outname; +#endif + real_outname = g_strdup_printf("%s.%s", out_basename, mode->suffix); + if (out_basename != outname) + g_free(out_basename); + } + + /* Use binary write for typelib mode */ + fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb"; + state.file = fopen(real_outname, fopen_mode); + if (!state.file) { + perror("error opening output file"); + return 0; + } + } else { + state.file = stdout; + } + state.tree = top; +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + state.real_outname = real_outname; +#endif + + if (emitter->emit_prolog) + emitter->emit_prolog(&state); + if (state.tree) /* Only if we have a tree to process. */ + ok = xpidl_process_node(&state); + if (emitter->emit_epilog) + emitter->emit_epilog(&state); + + if (state.file != stdout) + fclose(state.file); + free(state.basename); + free(outname); + g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL); + g_hash_table_destroy(callback_state.already_included); + g_slist_foreach(callback_state.base_includes, free_gslist_data, NULL); + + if (state.ns) + IDL_ns_free(state.ns); + if (top) + IDL_tree_free(top); + + if (real_outname != NULL) { + /* + * Delete partial output file on failure. (Mac does this in the plugin + * driver code, if the compiler returns failure.) + */ +#if defined(XP_UNIX) || defined(XP_WIN) + if (!ok) + unlink(real_outname); +#endif + g_free(real_outname); + } + + return ok; +} + +/* + * Our own version of IDL_tree_warning, which we use when IDL_tree_warning + * would crash on us. + */ +void +xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...) +{ + va_list ap; + char *msg, *file; + int lineno; + + /* XXX need to check against __IDL_max_msg_level, no accessor */ + va_start(ap, fmt); + msg = g_strdup_vprintf(fmt, ap); + + if (p) { + file = p->_file; + lineno = p->_line; + } else { + file = NULL; + lineno = 0; + } + + /* call our message callback, like IDL_tree_warning would */ + msg_callback(level, 0, lineno, file, msg); + g_free(msg); + va_end(ap); +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c new file mode 100644 index 00000000..4f708027 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c @@ -0,0 +1,1053 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is Sun Microsystems, + * Inc. Portions created by Sun are + * Copyright (C) 1999 Sun Microsystems, Inc. All + * Rights Reserved. + * + * Contributor(s): + * Michael Allen (michael.allen@sun.com) + * Frank Mitchell (frank.mitchell@sun.com) + */ + +/* + * Generate Java interfaces from XPIDL. + */ + +#include "xpidl.h" +#include <ctype.h> +#include <glib.h> + + +struct java_priv_data { + GHashTable *typedefTable; +}; + +#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable) + +static gboolean +write_classname_iid_define(FILE *file, const char *className) +{ + const char *iidName; + if (className[0] == 'n' && className[1] == 's') { + /* backcompat naming styles */ + fputs("NS_", file); + iidName = className + 2; + } else { + iidName = className; + } + + while (*iidName) { + fputc(toupper(*iidName++), file); + } + + fputs("_IID", file); + return TRUE; +} + +static gboolean +java_prolog(TreeState *state) +{ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + const char *basename; + const char *ext; +#endif + + state->priv = calloc(1, sizeof(struct java_priv_data)); + if (!state->priv) + return FALSE; + TYPEDEFS(state) = 0; + TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal); + if (!TYPEDEFS(state)) { + /* XXX report error */ + free(state->priv); + return FALSE; + } + + /* + * First pass + */ + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + basename = xpidl_basename(state->real_outname ? state->real_outname : state->basename); + ext = strrchr(basename, '.'); + if (!ext) + ext = strchr(basename, '\0'); + fprintf(state->file, + "/**\n" + " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n" + " * FOR THE FULL DOCUMENTATION AND LICENSE.\n" + " *\n" + " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=interface+%.*s\">\n" + " **/\n" + "\n" + "package org.mozilla.interfaces;\n\n" + "import java.math.BigInteger;\n\n" + "\n" + , ext - basename >= 19 ? 19 : (int)(ext - basename), basename); + g_free(basename); +#else + fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n", + state->file); + + fprintf(state->file, + " *\n * This file was automatically generated from %s.idl.\n", + state->basename); + + fputs(" */\n\n", state->file); +#endif + + return TRUE; +} + +static gboolean +java_epilog(TreeState *state) +{ + /* points to other elements of the tree, so just destroy the table */ + g_hash_table_destroy(TYPEDEFS(state)); + free(state->priv); + state->priv = NULL; + +#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + /* + * Last pass + */ + + fprintf(state->file, "\n/*\n * end\n */\n"); +#endif + + return TRUE; +} + +static gboolean +forward_declaration(TreeState *state) +{ + /* + * Java doesn't need forward declarations unless the declared + * class resides in a different package. + */ +#if 0 + IDL_tree iface = state->tree; + const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str; + const char *pkgName = "org.mozilla.xpcom"; + if (!className) + return FALSE; + /* XXX: Get package name and compare */ + fprintf(state->file, "import %s.%s;\n", pkgName, className); +#endif + return TRUE; +} + + +static gboolean +interface_declaration(TreeState *state) +{ + IDL_tree interface = state->tree; + IDL_tree iterator = NULL; + char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str; + const char *iid = NULL; + + if (!verify_interface_declaration(interface)) + return FALSE; +#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + /* + * Write out JavaDoc comment + */ + + fprintf(state->file, "\n/**\n * Interface %s\n", interface_name); +#endif + +#ifndef LIBIDL_MAJOR_VERSION + iid = IDL_tree_property_get(interface, "uuid"); +#else + iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid"); +#endif + +#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + if (iid != NULL) { + fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid); + } else { + fputs(" */\n\n", state->file); + } +#endif + + /* + * Write "public interface <foo>" + */ + + fprintf(state->file, "public interface %s ", interface_name); + + /* + * Check for inheritence, and iterator over the inherited names, + * if any. + */ + + if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) { + fputs("extends ", state->file); + + do { + + fprintf(state->file, "%s", + IDL_IDENT(IDL_LIST(iterator).data).str); + + if (IDL_LIST(iterator).next) { + fputs(", ", state->file); + } + } while ((iterator = IDL_LIST(iterator).next)); + + } + + fputs("\n{\n", state->file); + + if (iid) { + /* + * Write interface constants for IID + */ + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fputs(" public static final String ", state->file); +#else + fputs(" public static final String ", state->file); +#endif + + /* XXX s.b just "IID" ? */ + if (!write_classname_iid_define(state->file, interface_name)) { + return FALSE; + } + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + fputs(" =\n \"{", state->file); + while (*iid) { + fputc(tolower(*iid++), state->file); + } + fputs("}\";\n", state->file); + +#else + fprintf(state->file, "_STRING =\n \"%s\";\n\n", iid); + + fputs(" public static final nsID ", state->file); + + /* XXX s.b just "IID" ? */ + if (!write_classname_iid_define(state->file, interface_name)) { + return FALSE; + } + + fprintf(state->file, " =\n new nsID(\"%s\");\n\n", iid); +#endif + } + + /* + * Advance the state of the tree, go on to process more + */ + + state->tree = IDL_INTERFACE(interface).body; + + if (state->tree && !xpidl_process_node(state)) { + return FALSE; + } + + + fputs("\n}\n", state->file); + + return TRUE; +} + +static gboolean +process_list(TreeState *state) +{ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + /* To make the diffing simple, group the constants, methods and attributes. */ + IDL_tree list = state->tree; + IDL_tree iter; + for (iter = list; iter; iter = IDL_LIST(iter).next) { + if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_CONST_DCL) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + } + for (iter = list; iter; iter = IDL_LIST(iter).next) { + if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_ATTR_DCL) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + } + for (iter = list; iter; iter = IDL_LIST(iter).next) { + if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_OP_DCL) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + } + for (iter = list; iter; iter = IDL_LIST(iter).next) { + if ( IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_CONST_DCL + && IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_OP_DCL + && IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_ATTR_DCL ) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + } + +#else + IDL_tree iter; + for (iter = state->tree; iter; iter = IDL_LIST(iter).next) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } +#endif + return TRUE; +} + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES +static gboolean +interface_declaration_wrapper(TreeState *state) +{ + IDL_tree interface = state->tree; + char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str; + FILE *org_file = state->file; + char *org_name = state->real_outname; + void *org_priv = state->priv; + gboolean rc; + + /* + * Skip non-scriptable interfaces. + */ + if ( !IDL_tree_property_get(IDL_INTERFACE(interface).ident, "scriptable") + && strcmp(interface_name, "nsIAppShell") ) + return TRUE; + + /* + * GROSS HACK: If the interface isn't the same as the file name, + * temporarily switch output file. + */ + if (state->real_outname) { + const char *basename = xpidl_basename(state->real_outname); + const char *ext = strrchr(basename, '.'); + if ( ext + && !strcmp(ext, ".java") + && ( strncmp(interface_name, basename, ext - basename) + || interface_name[ext - basename] != '.') ) { + size_t needed = strlen(state->real_outname) + strlen(interface_name) + strlen(".java") + 4; + char *tmp = malloc(needed); + if (basename != state->real_outname) + sprintf(tmp,"%.*s/%s.java", (int)(basename - state->real_outname - 1), state->real_outname, interface_name); + else + sprintf(tmp,"%s.java", interface_name); + state->file = fopen(tmp, "w"); + if (!state->file) { + perror("error opening output file"); + state->file = org_file; + free(tmp); + return FALSE; + } + state->real_outname = tmp; + java_prolog(state); + } + g_free(basename); + } + + rc = interface_declaration(state); + + if (state->file != org_file) { + java_epilog(state); + fclose(state->file); + free(state->real_outname); + state->file = org_file; + state->real_outname = org_name; + state->priv = org_priv; + } + return rc; +} +#endif /* VBOX_XPIDL_EMULATE_GENJIFACES */ + +static gboolean +xpcom_to_java_type (TreeState *state) +{ + if (!state->tree) { + fputs("Object", state->file); + return TRUE; + } + + switch(IDL_NODE_TYPE(state->tree)) { + + case IDLN_TYPE_INTEGER: { + + switch(IDL_TYPE_INTEGER(state->tree).f_type) { + + case IDL_INTEGER_TYPE_SHORT: +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + if (IDL_TYPE_INTEGER(state->tree).f_signed) + fputs("short", state->file); + else + fputs("int", state->file); +#else + fputs("short", state->file); +#endif + break; + + case IDL_INTEGER_TYPE_LONG: +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + if (IDL_TYPE_INTEGER(state->tree).f_signed) + fputs("int", state->file); + else + fputs("long", state->file); +#else + fputs("int", state->file); +#endif + break; + + case IDL_INTEGER_TYPE_LONGLONG: +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + if (IDL_TYPE_INTEGER(state->tree).f_signed) + fputs("long", state->file); + else + fputs("double", state->file); +#else + fputs("long", state->file); +#endif + break; + + default: + g_error(" Unknown integer type: %d\n", + IDL_TYPE_INTEGER(state->tree).f_type); + return FALSE; + + } + + break; + } + + case IDLN_TYPE_CHAR: + case IDLN_TYPE_WIDE_CHAR: + fputs("char", state->file); + break; + + case IDLN_TYPE_WIDE_STRING: + case IDLN_TYPE_STRING: + fputs("String", state->file); + break; + + case IDLN_TYPE_BOOLEAN: + fputs("boolean", state->file); + break; + + case IDLN_TYPE_OCTET: +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + fputs("short", state->file); +#else + fputs("byte", state->file); +#endif + break; + + case IDLN_TYPE_FLOAT: + switch(IDL_TYPE_FLOAT(state->tree).f_type) { + + case IDL_FLOAT_TYPE_FLOAT: + fputs("float", state->file); + break; + + case IDL_FLOAT_TYPE_DOUBLE: + fputs("double", state->file); + break; + + default: + g_error(" Unknown floating point typ: %d\n", + IDL_NODE_TYPE(state->tree)); + break; + } + break; + + + case IDLN_IDENT: + if (IDL_NODE_UP(state->tree) && + IDL_NODE_TYPE(IDL_NODE_UP(state->tree)) == IDLN_NATIVE) { + const char *user_type = IDL_NATIVE(IDL_NODE_UP(state->tree)).user_type; + if (strcmp(user_type, "void") == 0) { +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + fputs("nsISupports", state->file); +#else + fputs("Object", state->file); +#endif + } + else if (strcmp(user_type, "nsID") == 0 || + strcmp(user_type, "nsIID") == 0 || + strcmp(user_type, "nsCID") == 0) { + /* XXX: s.b test for "iid" attribute */ + /* XXX: special class for nsIDs */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + fputs("String", state->file); +#else + fputs("nsID", state->file); +#endif + } + else { + /* XXX: special class for opaque types */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + fputs("String", state->file); +#else + fputs("OpaqueValue", state->file); +#endif + } + } else { + const char *ident_str = IDL_IDENT(state->tree).str; + + /* XXX: big kludge; s.b. way to match to typedefs */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + if (strcmp(ident_str, "PRInt8") == 0) { + fputs("byte", state->file); + } + else if (strcmp(ident_str, "PRInt16") == 0 || + strcmp(ident_str, "PRUint8") == 0) { + fputs("short", state->file); + } + else if (strcmp(ident_str, "PRInt32") == 0 || + strcmp(ident_str, "PRUint16") == 0) { + fputs("int", state->file); + } + else if (strcmp(ident_str, "PRInt64") == 0 || + strcmp(ident_str, "PRUint32") == 0 || + strcmp(ident_str, "PRThreadPriority") == 0 || + strcmp(ident_str, "PRThreadScope") == 0 || + strcmp(ident_str, "PRThreadState") == 0) { + fputs("long", state->file); + } + else if (strcmp(ident_str, "PRUint64") == 0) { + fputs("double", state->file); + } +#else + if (strcmp(ident_str, "PRInt8") == 0 || + strcmp(ident_str, "PRUint8") == 0) { + fputs("byte", state->file); + } + else if (strcmp(ident_str, "PRInt16") == 0 || + strcmp(ident_str, "PRUint16") == 0) { + fputs("short", state->file); + } + else if (strcmp(ident_str, "PRInt32") == 0 || + strcmp(ident_str, "PRUint32") == 0) { + fputs("int", state->file); + } + else if (strcmp(ident_str, "PRInt64") == 0 || + strcmp(ident_str, "PRUint64") == 0) { + fputs("long", state->file); + } +#endif + else if (strcmp(ident_str, "PRBool") == 0) { + fputs("boolean", state->file); + } + else if (strcmp(ident_str, "nsrefcnt") == 0) { + fputs("int", state->file); + } +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + /* XXX: Use find_underlying_type instead? */ + else if ( strcmp(ident_str, "nsresult") == 0 + || strcmp(ident_str, "size_t") == 0) { + fputs("long", state->file); + } + else if ( strcmp(ident_str, "PRTime") == 0) { + fputs("double", state->file); + } + /* In Javaconnect, we handle weak references internally; no need for the + |nsIWeakReference| interface. So just return |nsISupports|. */ + else if (strcmp(ident_str, "nsIWeakReference") == 0) { + fputs("nsISupports", state->file); + } +#endif + else { + IDL_tree real_type = + g_hash_table_lookup(TYPEDEFS(state), ident_str); + + if (real_type) { + IDL_tree orig_tree = state->tree; + + state->tree = real_type; + xpcom_to_java_type(state); + + state->tree = orig_tree; + } + else { + fputs(ident_str, state->file); + } + } + } + + break; + + case IDLN_TYPE_ENUM: + case IDLN_TYPE_OBJECT: + default: + g_error(" Unknown type: %d\n", + IDL_TYPE_FLOAT(state->tree).f_type); + break; + } + + return TRUE; + +} + +static gboolean +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF +xpcom_to_java_param(TreeState *state, unsigned nparam) +#else +xpcom_to_java_param(TreeState *state) +#endif +{ + IDL_tree param = state->tree; + state->tree = IDL_PARAM_DCL(param).param_type_spec; + + /* + * Put in type of parameter + */ + + if (!xpcom_to_java_type(state)) { + return FALSE; + } + + /* + * If the parameter is out or inout, make it a Java array of the + * appropriate type + */ + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + /* XXX: Causes nsILineInputStream::readLine(String[] arg1) where genjifaces drops the []. */ +#endif + if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) { + fputs("[]", state->file); + } +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + /*XXX: nsIConsoleService::getMessageArray ends up with [][] arg1... */ + /*else*/ if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array")) { + fputs("[]", state->file); + } +#endif + + /* + * Put in name of parameter + */ + + fputc(' ', state->file); + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fprintf(state->file, "arg%u", nparam+1); +#else + fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file); +#endif + + return TRUE; +} + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES +static gboolean is_java_keyword(char ch0, const char *name) +{ + static const char * const 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 */ + }; + unsigned i; + for (i = 0; i < sizeof(kJavaKeywords) / sizeof(kJavaKeywords[0]); i++) { + if (kJavaKeywords[i][0] == ch0 && !strcmp(&kJavaKeywords[i][1], &name[1])) { + return TRUE; + } + } + return FALSE; +} +#endif + +static gboolean +type_declaration(TreeState *state) +{ + /* + * Unlike C, Java has no type declaration directive. + * Instead, we record the mapping, and look up the actual type + * when needed. + */ + IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec; + IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls; + + /* XXX: check for illegal types */ + + g_hash_table_insert(TYPEDEFS(state), + IDL_IDENT(IDL_LIST(dcls).data).str, + type); + + return TRUE; +} + +static gboolean +method_declaration(TreeState *state) +{ + /* IDL_tree method_tree = state->tree; */ + struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree); + gboolean method_notxpcom = + (IDL_tree_property_get(method->ident, "notxpcom") != NULL); + gboolean method_noscript = + (IDL_tree_property_get(method->ident, "noscript") != NULL); + IDL_tree iterator = NULL; + IDL_tree retval_param = NULL; + const char *method_name = IDL_IDENT(method->ident).str; +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + unsigned nparam = 0; +#endif + + if (!verify_method_declaration(state->tree)) + return FALSE; + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + /* + * Skip most (todo) non-scriptable and not-xpcom methods. + */ + if (method_noscript || method_notxpcom) { + return TRUE; + } +#endif + + fputc('\n', state->file); +#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + xpidl_write_comment(state, 4); +#endif + + /* + * Write beginning of method declaration + */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fputs(" ", state->file); +#else + fputs(" ", state->file); +#endif + if (!method_noscript) { + /* Nonscriptable methods become package-protected */ + fputs("public ", state->file); + } + + /* + * Write return type + * Unlike C++ headers, Java interfaces return the declared + * return value; an exception indicates XPCOM method failure. + */ + if (method_notxpcom || method->op_type_spec) { + state->tree = method->op_type_spec; + if (!xpcom_to_java_type(state)) { + return FALSE; + } + } else { + /* Check for retval attribute */ + for (iterator = method->parameter_dcls; iterator != NULL; + iterator = IDL_LIST(iterator).next) { + + IDL_tree original_tree = state->tree; + + state->tree = IDL_LIST(iterator).data; + + if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, + "retval")) { + retval_param = iterator; + + state->tree = IDL_PARAM_DCL(state->tree).param_type_spec; + + /* + * Put in type of parameter + */ + + if (!xpcom_to_java_type(state)) { + return FALSE; + } +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + if (IDL_tree_property_get(IDL_PARAM_DCL(IDL_LIST(iterator).data).simple_declarator, "array")) { + fputs("[]", state->file); + } +#endif + } + + state->tree = original_tree; + } + + if (retval_param == NULL) { + fputs("void", state->file); + } + } + + /* + * Write method name + */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + if (is_java_keyword(tolower(method_name[0]), method_name)) { + fprintf(state->file, " %c%s_(", tolower(method_name[0]), method_name + 1); + } else { + fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1); + } +#else + fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1); +#endif + + /* + * Write parameters + */ + for (iterator = method->parameter_dcls; iterator != NULL; + iterator = IDL_LIST(iterator).next) { + + /* Skip "retval" */ + if (iterator == retval_param) { + continue; + } + + if (iterator != method->parameter_dcls) { + fputs(", ", state->file); + } + + state->tree = IDL_LIST(iterator).data; + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + if (!xpcom_to_java_param(state, nparam++)) { +#else + if (!xpcom_to_java_param(state)) { +#endif + return FALSE; + } + } + + fputs(")", state->file); + + if (method->raises_expr) { + IDL_tree iter = method->raises_expr; + IDL_tree dataNode = IDL_LIST(iter).data; + + fputs(" throws ", state->file); + fputs(IDL_IDENT(dataNode).str, state->file); + iter = IDL_LIST(iter).next; + + while (iter) { + dataNode = IDL_LIST(iter).data; + fprintf(state->file, ", %s", IDL_IDENT(dataNode).str); + iter = IDL_LIST(iter).next; + } + } + + fputs(";\n", state->file); + + return TRUE; + +} + + +static gboolean +constant_declaration(TreeState *state) +{ + struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree); + const char *name = IDL_IDENT(declaration->ident).str; + IDL_tree real_type; + + if (!verify_const_declaration(state->tree)) + return FALSE; + + /* Could be a typedef; try to map it to the real type. */ + real_type = find_underlying_type(declaration->const_type); + real_type = real_type ? real_type : declaration->const_type; + + fputc('\n', state->file); +#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + xpidl_write_comment(state, 4); +#endif + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES +# ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fputs(" public static final ", state->file); +# else + fputs(" public static final ", state->file); +# endif + if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) { + if (IDL_TYPE_INTEGER(real_type).f_signed) + fprintf(state->file, "int %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value); + else + fprintf(state->file, "long %s = %" IDL_LL "uL;\n", name, IDL_INTEGER(declaration->const_exp).value); + } else { + if (IDL_TYPE_INTEGER(real_type).f_signed) + fprintf(state->file, "short %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value); + else + fprintf(state->file, "int %s = %" IDL_LL "u;\n", name, IDL_INTEGER(declaration->const_exp).value); + } +#else /* !VBOX_XPIDL_EMULATE_GENJIFACES */ + fprintf(state->file, " public static final %s %s = %d;\n", + (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG + ? "long" : "short"), + name, (int) IDL_INTEGER(declaration->const_exp).value); +#endif /* !VBOX_XPIDL_EMULATE_GENJIFACES */ + + return TRUE; + +} + +#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)) +#define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data) +#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec) + + +static gboolean +attribute_declaration(TreeState *state) +{ + gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly; + char *attribute_name = ATTR_IDENT(state->tree).str; + + gboolean method_noscript = + (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL); + +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + /* + * Skip most non-scriptable attributes. + */ + if (method_noscript) { + return TRUE; + } +#endif + +#if 0 + /* + * Disabled here because I can't verify this check against possible + * users of the java xpidl backend. + */ + if (!verify_attribute_declaration(state->tree)) + return FALSE; +#endif + + /* Comment */ + fputc('\n', state->file); +#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + xpidl_write_comment(state, 4); +#endif + + state->tree = ATTR_TYPE_DECL(state->tree); + + /* + * Write access permission ("public" unless nonscriptable) + */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fputs(" ", state->file); +#else + fputs(" ", state->file); +#endif + if (!method_noscript) { + fputs("public ", state->file); + } + + /* + * Write the proper Java return value for the get operation + */ + if (!xpcom_to_java_type(state)) { + return FALSE; + } + + /* + * Write the name of the accessor ("get") method. + */ + fprintf(state->file, " get%c%s();\n", + toupper(attribute_name[0]), attribute_name + 1); + + + if (!read_only) { + /* Nonscriptable methods become package-protected */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fputs("\n ", state->file); +#else + fputs(" ", state->file); +#endif + if (!method_noscript) { + fputs("public ", state->file); + } + + /* + * Write attribute access method name and return type + */ + fprintf(state->file, "void set%c%s(", + toupper(attribute_name[0]), + attribute_name+1); + + /* + * Write the proper Java type for the set operation + */ + if (!xpcom_to_java_type(state)) { + return FALSE; + } + + /* + * Write the name of the formal parameter. + */ +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF + fputs(" arg1);\n", state->file); +#else + fputs(" value);\n", state->file); +#endif + } + + return TRUE; +} + + +static gboolean +enum_declaration(TreeState *state) +{ + XPIDL_WARNING((state->tree, IDL_WARNING1, + "enums not supported, enum \'%s\' ignored", + IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str)); + return TRUE; +} + +backend * +xpidl_java_dispatch(void) +{ + static backend result; + static nodeHandler table[IDLN_LAST]; + static gboolean initialized = FALSE; + + result.emit_prolog = java_prolog; + result.emit_epilog = java_epilog; + + if (!initialized) { +#ifdef VBOX_XPIDL_EMULATE_GENJIFACES + table[IDLN_INTERFACE] = interface_declaration_wrapper; +#else + table[IDLN_INTERFACE] = interface_declaration; +#endif + table[IDLN_LIST] = process_list; + + table[IDLN_OP_DCL] = method_declaration; + table[IDLN_ATTR_DCL] = attribute_declaration; + table[IDLN_CONST_DCL] = constant_declaration; + + table[IDLN_TYPE_DCL] = type_declaration; + table[IDLN_FORWARD_DCL] = forward_declaration; + + table[IDLN_TYPE_ENUM] = enum_declaration; + + initialized = TRUE; + } + + result.dispatch_table = table; + return &result; +} + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c new file mode 100644 index 00000000..f2daae0d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c @@ -0,0 +1,1237 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Generate typelib files for use with InterfaceInfo. + * http://www.mozilla.org/scriptable/typelib_file.html + */ + +#include "xpidl.h" +#include <xpt_xdr.h> +#include <xpt_struct.h> +#include <time.h> /* XXX XP? */ + +struct priv_data { + XPTHeader *header; + uint16 ifaces; + GHashTable *interface_map; + XPTInterfaceDescriptor *current; + XPTArena *arena; + uint16 next_method; + uint16 next_const; + uint16 next_type; /* used for 'additional_types' for idl arrays */ +}; + +#define HEADER(state) (((struct priv_data *)state->priv)->header) +#define IFACES(state) (((struct priv_data *)state->priv)->ifaces) +#define IFACE_MAP(state) (((struct priv_data *)state->priv)->interface_map) +#define CURRENT(state) (((struct priv_data *)state->priv)->current) +#define ARENA(state) (((struct priv_data *)state->priv)->arena) +#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method) +#define NEXT_CONST(state) (((struct priv_data *)state->priv)->next_const) +#define NEXT_TYPE(state) (((struct priv_data *)state->priv)->next_type) + +#ifdef DEBUG_shaver +/* #define DEBUG_shaver_sort */ +#endif + +typedef struct { + char *full_name; + char *name; + char *name_space; + char *iid; + gboolean is_forward_dcl; +} NewInterfaceHolder; + +static NewInterfaceHolder* +CreateNewInterfaceHolder(char *name, char *name_space, char *iid, + gboolean is_forward_dcl) +{ + NewInterfaceHolder *holder = calloc(1, sizeof(NewInterfaceHolder)); + if (holder) { + holder->is_forward_dcl = is_forward_dcl; + if (name) + holder->name = xpidl_strdup(name); + if (name_space) + holder->name_space = xpidl_strdup(name_space); + if (holder->name && holder->name_space) { + holder->full_name = calloc(1, strlen(holder->name) + + strlen(holder->name_space) + 2); + } + if (holder->full_name) { + strcpy(holder->full_name, holder->name_space); + strcat(holder->full_name, "."); + strcat(holder->full_name, holder->name); + } + else + holder->full_name = holder->name; + if (iid) + holder->iid = xpidl_strdup(iid); + } + return holder; +} + +static void +DeleteNewInterfaceHolder(NewInterfaceHolder *holder) +{ + if (holder) { + if (holder->full_name && holder->full_name != holder->name) + free(holder->full_name); + if (holder->name) + free(holder->name); + if (holder->name_space) + free(holder->name_space); + if (holder->iid) + free(holder->iid); + free(holder); + } +} + +/* + * If p is an ident for an interface, and we don't have an entry in the + * interface map yet, add one. + */ +static gboolean +add_interface_maybe(IDL_tree_func_data *tfd, gpointer user_data) +{ + TreeState *state = user_data; + IDL_tree up; + if (IDL_NODE_TYPE(tfd->tree) == IDLN_IDENT) { + IDL_tree_type node_type = IDL_NODE_TYPE((up = IDL_NODE_UP(tfd->tree))); + if (node_type == IDLN_INTERFACE || node_type == IDLN_FORWARD_DCL) { + + /* We only want to add a new entry if there is no entry by this + * name or if the previously found entry was just a forward + * declaration and the new entry is not. + */ + + char *iface = IDL_IDENT(tfd->tree).str; + NewInterfaceHolder *old_holder = (NewInterfaceHolder *) + g_hash_table_lookup(IFACE_MAP(state), iface); + if (old_holder && old_holder->is_forward_dcl && + node_type != IDLN_FORWARD_DCL) + { + g_hash_table_remove(IFACE_MAP(state), iface); + DeleteNewInterfaceHolder(old_holder); + old_holder = NULL; + } + if (!old_holder) { + /* XXX should we parse here and store a struct nsID *? */ + char *iid = (char *)IDL_tree_property_get(tfd->tree, "uuid"); + char *name_space = (char *) + IDL_tree_property_get(tfd->tree, "namespace"); + NewInterfaceHolder *holder = + CreateNewInterfaceHolder(iface, name_space, iid, + (gboolean) node_type == IDLN_FORWARD_DCL); + if (!holder) + return FALSE; + g_hash_table_insert(IFACE_MAP(state), + holder->full_name, holder); + IFACES(state)++; +#ifdef DEBUG_shaver_ifaces + fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state), + iface, iid[0] ? iid : "<unresolved>"); +#endif + } + } else { +#ifdef DEBUG_shaver_ifaces + fprintf(stderr, "ident %s isn't an interface (%s)\n", + IDL_IDENT(tfd->tree).str, IDL_NODE_TYPE_NAME(up)); +#endif + } + } + + return TRUE; +} + +/* Find all the interfaces referenced in the tree (uses add_interface_maybe) */ +static gboolean +find_interfaces(IDL_tree_func_data *tfd, gpointer user_data) +{ + IDL_tree node = NULL; + + switch (IDL_NODE_TYPE(tfd->tree)) { + case IDLN_ATTR_DCL: + node = IDL_ATTR_DCL(tfd->tree).param_type_spec; + break; + case IDLN_OP_DCL: + IDL_tree_walk_in_order(IDL_OP_DCL(tfd->tree).parameter_dcls, find_interfaces, + user_data); + node = IDL_OP_DCL(tfd->tree).op_type_spec; + break; + case IDLN_PARAM_DCL: + node = IDL_PARAM_DCL(tfd->tree).param_type_spec; + break; + case IDLN_INTERFACE: + node = IDL_INTERFACE(tfd->tree).inheritance_spec; + if (node) + xpidl_list_foreach(node, add_interface_maybe, user_data); + node = IDL_INTERFACE(tfd->tree).ident; + break; + case IDLN_FORWARD_DCL: + node = IDL_FORWARD_DCL(tfd->tree).ident; + break; + default: + node = NULL; + } + + if (node && IDL_NODE_TYPE(node) == IDLN_IDENT) { + IDL_tree_func_data new_tfd; + new_tfd.tree = node; + add_interface_maybe(&new_tfd, user_data); + } + + return TRUE; +} + +#ifdef DEBUG_shaver +/* for calling from gdb */ +static void +print_IID(struct nsID *iid, FILE *file) +{ + char iid_buf[UUID_LENGTH]; + + xpidl_sprint_iid(iid, iid_buf); + fprintf(file, "%s\n", iid_buf); +} +#endif + +/* fill the interface_directory IDE table from the interface_map */ +static gboolean +fill_ide_table(gpointer key, gpointer value, gpointer user_data) +{ + TreeState *state = user_data; + NewInterfaceHolder *holder = (NewInterfaceHolder *) value; + struct nsID id; + XPTInterfaceDirectoryEntry *ide; + + XPT_ASSERT(holder); + +#ifdef DEBUG_shaver_ifaces + fprintf(stderr, "filling %s\n", holder->full_name); +#endif + + if (holder->iid) { + if (strlen(holder->iid) != 36) { + IDL_tree_error(state->tree, "IID %s is the wrong length\n", + holder->iid); + return FALSE; + } + if (!xpidl_parse_iid(&id, holder->iid)) { + IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid); + return FALSE; + } + } else { + memset(&id, 0, sizeof(id)); + } + + ide = &(HEADER(state)->interface_directory[IFACES(state)]); + if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name, + holder->name_space, NULL)) { + IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n", + holder->full_name); + return FALSE; + } + + IFACES(state)++; + DeleteNewInterfaceHolder(holder); + return TRUE; +} + +static int +compare_IDEs(const void *ap, const void *bp) +{ + const XPTInterfaceDirectoryEntry *a = ap, *b = bp; + const nsID *aid = &a->iid, *bid = &b->iid; + const char *ans, *bns; + + int i; +#define COMPARE(field) if (aid->field > bid->field) return 1; \ + if (bid->field > aid->field) return -1; + COMPARE(m0); + COMPARE(m1); + COMPARE(m2); + for (i = 0; i < 8; i++) { + COMPARE(m3[i]); + } + + /* defend against NULL name_space by using empty string. */ + ans = a->name_space ? a->name_space : ""; + bns = b->name_space ? b->name_space : ""; + + if (a->name_space && b->name_space) { + if ((i = strcmp(a->name_space, b->name_space))) + return i; + } else { + if (a->name_space || b->name_space) { + if (a->name_space) + return -1; + return 1; + } + } + /* these had better not be NULL... */ + return strcmp(a->name, b->name); +#undef COMPARE +} + +/* sort the IDE block as per the typelib spec: IID order, unresolved first */ +static void +sort_ide_block(TreeState *state) +{ + XPTInterfaceDirectoryEntry *ide; + int i; + + /* boy, I sure hope qsort works correctly everywhere */ +#ifdef DEBUG_shaver_sort + fputs("before sort:\n", stderr); + for (i = 0; i < IFACES(state); i++) { + fputs(" ", stderr); + print_IID(&HEADER(state)->interface_directory[i].iid, stderr); + fputc('\n', stderr); + } +#endif + qsort(HEADER(state)->interface_directory, IFACES(state), + sizeof(*ide), compare_IDEs); +#ifdef DEBUG_shaver_sort + fputs("after sort:\n", stderr); + for (i = 0; i < IFACES(state); i++) { + fputs(" ", stderr); + print_IID(&HEADER(state)->interface_directory[i].iid, stderr); + fputc('\n', stderr); + } +#endif + + for (i = 0; i < IFACES(state); i++) { + ide = HEADER(state)->interface_directory + i; + g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1)); + } + + return; +} + +static gboolean +typelib_list(TreeState *state) +{ + IDL_tree iter; + for (iter = state->tree; iter; iter = IDL_LIST(iter).next) { + state->tree = IDL_LIST(iter).data; + if (!xpidl_process_node(state)) + return FALSE; + } + return TRUE; +} + +static gboolean +typelib_prolog(TreeState *state) +{ + state->priv = calloc(1, sizeof(struct priv_data)); + if (!state->priv) + return FALSE; + IFACES(state) = 0; + IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal); + if (!IFACE_MAP(state)) { + /* XXX report error */ + free(state->priv); + return FALSE; + } + /* find all interfaces, top-level and referenced by others */ + IDL_tree_walk_in_order(state->tree, find_interfaces, state); + ARENA(state) = XPT_NewArena(1024, sizeof(double), "main xpidl arena"); + HEADER(state) = XPT_NewHeader(ARENA(state), IFACES(state), + major_version, minor_version); + + /* fill IDEs from hash table */ + IFACES(state) = 0; + g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state); + + /* if any are left then we must have failed in fill_ide_table */ + if (g_hash_table_size(IFACE_MAP(state))) + return FALSE; + + /* sort the IDEs by IID order and store indices in the interface map */ + sort_ide_block(state); + + return TRUE; +} + +static gboolean +typelib_epilog(TreeState *state) +{ + XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0); + XPTCursor curs, *cursor = &curs; + PRUint32 i, len, header_sz; + PRUint32 oldOffset; + PRUint32 newOffset; + char *data; + + /* Write any annotations */ + if (emit_typelib_annotations) { + PRUint32 annotation_len, written_so_far; + char *annotate_val, *timestr; + time_t now; + static char *annotation_format = + "Created from %s.idl\nCreation date: %sInterfaces:"; + + /* fill in the annotations, listing resolved interfaces in order */ + + (void)time(&now); + timestr = ctime(&now); + + /* Avoid dependence on nspr; no PR_smprintf and friends. */ + + /* How large should the annotation string be? */ + annotation_len = strlen(annotation_format) + strlen(state->basename) + + strlen(timestr); +#ifdef VBOX + /* note that '%s' is contained two times in annotation_format and both + * format specifiers are replaced by a string. So in fact we reserve 4 + * bytes minus one byte (for the terminating '\0') more than necessary. */ +#endif + for (i = 0; i < HEADER(state)->num_interfaces; i++) { + XPTInterfaceDirectoryEntry *ide; + ide = &HEADER(state)->interface_directory[i]; + if (ide->interface_descriptor) { + annotation_len += strlen(ide->name) + 1; + } + } + + annotate_val = (char *) malloc(annotation_len); + written_so_far = sprintf(annotate_val, annotation_format, + state->basename, timestr); + + for (i = 0; i < HEADER(state)->num_interfaces; i++) { + XPTInterfaceDirectoryEntry *ide; + ide = &HEADER(state)->interface_directory[i]; + if (ide->interface_descriptor) { + written_so_far += sprintf(annotate_val + written_so_far, " %s", + ide->name); + } + } + + HEADER(state)->annotations = + XPT_NewAnnotation(ARENA(state), + XPT_ANN_LAST | XPT_ANN_PRIVATE, + XPT_NewStringZ(ARENA(state), "xpidl 0.99.9"), + XPT_NewStringZ(ARENA(state), annotate_val)); + free(annotate_val); + } else { + HEADER(state)->annotations = + XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST, NULL, NULL); + } + + if (!HEADER(state)->annotations) { + /* XXX report out of memory error */ + return FALSE; + } + + /* Write the typelib */ + header_sz = XPT_SizeOfHeaderBlock(HEADER(state)); + + if (!xstate || + !XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor)) + goto destroy_header; + oldOffset = cursor->offset; + if (!XPT_DoHeader(ARENA(state), cursor, &HEADER(state))) + goto destroy; + newOffset = cursor->offset; + XPT_GetXDRDataLength(xstate, XPT_HEADER, &len); + HEADER(state)->file_length = len; + XPT_GetXDRDataLength(xstate, XPT_DATA, &len); + HEADER(state)->file_length += len; + XPT_SeekTo(cursor, oldOffset); + if (!XPT_DoHeaderPrologue(ARENA(state), cursor, &HEADER(state), NULL)) + goto destroy; + XPT_SeekTo(cursor, newOffset); + XPT_GetXDRData(xstate, XPT_HEADER, &data, &len); + fwrite(data, len, 1, state->file); + XPT_GetXDRData(xstate, XPT_DATA, &data, &len); + fwrite(data, len, 1, state->file); + + destroy: + XPT_DestroyXDRState(xstate); + destroy_header: + /* XXX XPT_DestroyHeader(HEADER(state)) */ + + XPT_FreeHeader(ARENA(state), HEADER(state)); + XPT_DestroyArena(ARENA(state)); + + /* XXX should destroy priv_data here */ + + return TRUE; +} + +static XPTInterfaceDirectoryEntry * +FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces, + const char *name) +{ + uint16 i; + for (i = 0; i < num_interfaces; i++) { + if (!strcmp(ides[i].name, name)) + return &ides[i]; + } + return NULL; +} + +static gboolean +typelib_interface(TreeState *state) +{ + IDL_tree iface = state->tree, iter; + char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str; + XPTInterfaceDirectoryEntry *ide; + XPTInterfaceDescriptor *id; + uint16 parent_id = 0; + PRUint8 interface_flags = 0; + + if (!verify_interface_declaration(iface)) + return FALSE; + + if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")) + interface_flags |= XPT_ID_SCRIPTABLE; + + if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function")) + interface_flags |= XPT_ID_FUNCTION; + + ide = FindInterfaceByName(HEADER(state)->interface_directory, + HEADER(state)->num_interfaces, name); + if (!ide) { + IDL_tree_error(iface, "ERROR: didn't find interface %s in " + "IDE block. Giving up.\n", name); + return FALSE; + } + + if ((iter = IDL_INTERFACE(iface).inheritance_spec)) { + char *parent; + if (IDL_LIST(iter).next) { + IDL_tree_error(iface, + "ERROR: more than one parent interface for %s\n", + name); + return FALSE; + } + parent = IDL_IDENT(IDL_LIST(iter).data).str; + parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state), + parent); + if (!parent_id) { + IDL_tree_error(iface, + "ERROR: no index found for %s. Giving up.\n", + parent); + return FALSE; + } + } + + id = XPT_NewInterfaceDescriptor(ARENA(state), parent_id, 0, 0, + interface_flags); + if (!id) + return FALSE; + + CURRENT(state) = ide->interface_descriptor = id; +#ifdef DEBUG_shaver_ifaces + fprintf(stderr, "DBG: starting interface %s @ %p\n", name, id); +#endif + + NEXT_METH(state) = 0; + NEXT_CONST(state) = 0; + NEXT_TYPE(state) = 0; + + state->tree = IDL_INTERFACE(iface).body; + if (state->tree && !xpidl_process_node(state)) + return FALSE; +#ifdef DEBUG_shaver_ifaces + fprintf(stderr, "DBG: ending interface %s\n", name); +#endif + return TRUE; +} + +static gboolean +find_arg_with_name(TreeState *state, const char *name, int16 *argnum) +{ + int16 count; + IDL_tree params; + + XPT_ASSERT(state); + XPT_ASSERT(name); + XPT_ASSERT(argnum); + + params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls; + for (count = 0; + params != NULL && IDL_LIST(params).data != NULL; + params = IDL_LIST(params).next, count++) + { + const char *cur_name = IDL_IDENT( + IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str; + if (!strcmp(cur_name, name)) { + /* XXX ought to verify that this is the right type here */ + /* XXX for iid_is this must be an iid */ + /* XXX for size_is and length_is this must be a uint32 */ + *argnum = count; + return TRUE; + } + } + return FALSE; +} + +/* return value is for success or failure */ +static gboolean +get_size_and_length(TreeState *state, IDL_tree type, + int16 *size_is_argnum, int16 *length_is_argnum, + gboolean *has_size_is, gboolean *has_length_is) +{ + *has_size_is = FALSE; + *has_length_is = FALSE; + + if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { + IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator; + const char *size_is; + const char *length_is; + + /* only if size_is is found does any of this matter */ + size_is = IDL_tree_property_get(sd, "size_is"); + if (!size_is) + return TRUE; + + if (!find_arg_with_name(state, size_is, size_is_argnum)) { + IDL_tree_error(state->tree, "can't find matching argument for " + "[size_is(%s)]\n", size_is); + return FALSE; + } + *has_size_is = TRUE; + + /* length_is is optional */ + length_is = IDL_tree_property_get(sd, "length_is"); + if (length_is) { + *has_length_is = TRUE; + if (!find_arg_with_name(state, length_is, length_is_argnum)) { + IDL_tree_error(state->tree, "can't find matching argument for " + "[length_is(%s)]\n", length_is); + return FALSE; + } + } + } + return TRUE; +} + +static gboolean +fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type) +{ + IDL_tree up; + int16 size_is_argnum; + int16 length_is_argnum; + gboolean has_size_is; + gboolean has_length_is; + gboolean is_array = FALSE; + + if (type) { + + /* deal with array */ + + if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { + IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator; + if (IDL_tree_property_get(sd, "array")) { + + is_array = TRUE; + + /* size_is is required! */ + if (!get_size_and_length(state, type, + &size_is_argnum, &length_is_argnum, + &has_size_is, &has_length_is)) { + /* error was reported by helper function */ + return FALSE; + } + + if (!has_size_is) { + IDL_tree_error(state->tree, "[array] requires [size_is()]\n"); + return FALSE; + } + + td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER; + td->argnum = size_is_argnum; + + if (has_length_is) + td->argnum2 = length_is_argnum; + else + td->argnum2 = size_is_argnum; + + /* + * XXX - NOTE - this will be broken for multidimensional + * arrays because of the realloc XPT_InterfaceDescriptorAddTypes + * uses. The underlying 'td' can change as we recurse in to get + * additional dimensions. Luckily, we don't yet support more + * than on dimension in the arrays + */ + /* setup the additional_type */ + if (!XPT_InterfaceDescriptorAddTypes(ARENA(state), + CURRENT(state), 1)) { + g_error("out of memory\n"); + return FALSE; + } + td->type.additional_type = NEXT_TYPE(state); + td = &CURRENT(state)->additional_types[NEXT_TYPE(state)]; + NEXT_TYPE(state)++ ; + } + } + +handle_typedef: + switch (IDL_NODE_TYPE(type)) { + case IDLN_TYPE_INTEGER: { + gboolean sign = IDL_TYPE_INTEGER(type).f_signed; + switch(IDL_TYPE_INTEGER(type).f_type) { + case IDL_INTEGER_TYPE_SHORT: + td->prefix.flags = sign ? TD_INT16 : TD_UINT16; + break; + case IDL_INTEGER_TYPE_LONG: + td->prefix.flags = sign ? TD_INT32 : TD_UINT32; + break; + case IDL_INTEGER_TYPE_LONGLONG: + td->prefix.flags = sign ? TD_INT64 : TD_UINT64; + break; + } + break; + } + case IDLN_TYPE_CHAR: + td->prefix.flags = TD_CHAR; + break; + case IDLN_TYPE_WIDE_CHAR: + td->prefix.flags = TD_WCHAR; + break; + case IDLN_TYPE_STRING: + if (is_array) { + td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER; + } else { + if (!get_size_and_length(state, type, + &size_is_argnum, &length_is_argnum, + &has_size_is, &has_length_is)) { + /* error was reported by helper function */ + return FALSE; + } + if (has_size_is) { + td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER; + td->argnum = size_is_argnum; + if (has_length_is) + td->argnum2 = length_is_argnum; + else + td->argnum2 = size_is_argnum; + } else { + td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER; + } + } + break; + case IDLN_TYPE_WIDE_STRING: + if (is_array) { + td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER; + } else { + if (!get_size_and_length(state, type, + &size_is_argnum, &length_is_argnum, + &has_size_is, &has_length_is)) { + /* error was reported by helper function */ + return FALSE; + } + if (has_size_is) { + td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER; + td->argnum = size_is_argnum; + if (has_length_is) + td->argnum2 = length_is_argnum; + else + td->argnum2 = size_is_argnum; + } else { + td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER; + } + } + break; + case IDLN_TYPE_BOOLEAN: + td->prefix.flags = TD_BOOL; + break; + case IDLN_TYPE_OCTET: + td->prefix.flags = TD_UINT8; + break; + case IDLN_TYPE_FLOAT: + switch (IDL_TYPE_FLOAT (type).f_type) { + case IDL_FLOAT_TYPE_FLOAT: + td->prefix.flags = TD_FLOAT; + break; + case IDL_FLOAT_TYPE_DOUBLE: + td->prefix.flags = TD_DOUBLE; + break; + /* XXX 'long double' just ignored, or what? */ + default: break; + } + break; + case IDLN_IDENT: + if (!(up = IDL_NODE_UP(type))) { + IDL_tree_error(state->tree, + "ERROR: orphan ident %s in param list\n", + IDL_IDENT(type).str); + return FALSE; + } + switch (IDL_NODE_TYPE(up)) { + /* This whole section is abominably ugly */ + case IDLN_FORWARD_DCL: + case IDLN_INTERFACE: { + XPTInterfaceDirectoryEntry *ide, *ides; + uint16 num_ifaces; + char *className; + const char *iid_is; +handle_iid_is: + ides = HEADER(state)->interface_directory; + num_ifaces = HEADER(state)->num_interfaces; + /* might get here via the goto, so re-check type */ + if (IDL_NODE_TYPE(up) == IDLN_INTERFACE) + className = IDL_IDENT(IDL_INTERFACE(up).ident).str; + else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL) + className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str; + else + className = IDL_IDENT(IDL_NATIVE(up).ident).str; + iid_is = NULL; + + if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) { + iid_is = + IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, + "iid_is"); + } + if (iid_is) { + int16 argnum; + if (!find_arg_with_name(state, iid_is, &argnum)) { + IDL_tree_error(state->tree, + "can't find matching argument for " + "[iid_is(%s)]\n", iid_is); + return FALSE; + } + td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER; + td->argnum = argnum; + } else { + td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER; + ide = FindInterfaceByName(ides, num_ifaces, className); + if (!ide || ide < ides || ide > ides + num_ifaces) { + IDL_tree_error(state->tree, + "unknown iface %s in param\n", + className); + return FALSE; + } + td->type.iface = ide - ides + 1; +#ifdef DEBUG_shaver_index + fprintf(stderr, "DBG: index %d for %s\n", + td->type.iface, className); +#endif + } + break; + } + case IDLN_NATIVE: { + char *ident; + + /* jband - adding goto for iid_is when type is native */ + if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL && + IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator, + "iid_is")) + goto handle_iid_is; + + ident = IDL_IDENT(type).str; + if (IDL_tree_property_get(type, "nsid")) { + td->prefix.flags = TD_PNSIID; + if (IDL_tree_property_get(type, "ref")) + td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE; + else if (IDL_tree_property_get(type,"ptr")) + td->prefix.flags |= XPT_TDP_POINTER; + } else if (IDL_tree_property_get(type, "domstring")) { + td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER; + if (IDL_tree_property_get(type, "ref")) + td->prefix.flags |= XPT_TDP_REFERENCE; + } else if (IDL_tree_property_get(type, "astring")) { + td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER; + if (IDL_tree_property_get(type, "ref")) + td->prefix.flags |= XPT_TDP_REFERENCE; + } else if (IDL_tree_property_get(type, "utf8string")) { + td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER; + if (IDL_tree_property_get(type, "ref")) + td->prefix.flags |= XPT_TDP_REFERENCE; + } else if (IDL_tree_property_get(type, "cstring")) { + td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER; + if (IDL_tree_property_get(type, "ref")) + td->prefix.flags |= XPT_TDP_REFERENCE; + } else { + td->prefix.flags = TD_VOID | XPT_TDP_POINTER; + } + break; + } + default: + if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) { + /* restart with the underlying type */ + IDL_tree new_type; + new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec; +#ifdef DEBUG_shaver_misc + fprintf(stderr, "following %s typedef to %s\n", + IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type)); +#endif + /* + * Do a nice messy goto rather than recursion so that + * we can avoid screwing up the *array* information. + */ +/* return fill_td_from_type(state, td, new_type); */ + if (new_type) { + type = new_type; + goto handle_typedef; + } else { + /* do what we would do in recursion if !type */ + td->prefix.flags = TD_VOID; + return TRUE; + } + } + IDL_tree_error(state->tree, + "can't handle %s ident in param list\n", +#ifdef DEBUG_shaver + /* XXX is this safe to use on Win now? */ + IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) +#else + "that type of" +#endif + ); +#ifdef DEBUG_shaver + XPT_ASSERT(0); +#endif + return FALSE; + } + break; + default: + IDL_tree_error(state->tree, "can't handle %s in param list\n", +#ifdef DEBUG_shaver + /* XXX is this safe to use on Win now? */ + IDL_NODE_TYPE_NAME(IDL_NODE_UP(type)) +#else + "that type" +#endif + ); + return FALSE; + } + } else { + td->prefix.flags = TD_VOID; + } + + return TRUE; +} + +static gboolean +fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags, + IDL_tree type) +{ + pd->flags = flags; + return fill_td_from_type(state, &pd->type, type); +} + +static gboolean +fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree) +{ + uint8 flags = 0; + gboolean is_dipper_type = DIPPER_TYPE(IDL_PARAM_DCL(tree).param_type_spec); + + switch (IDL_PARAM_DCL(tree).attr) { + case IDL_PARAM_IN: + flags = XPT_PD_IN; + break; + case IDL_PARAM_OUT: + flags = XPT_PD_OUT; + break; + case IDL_PARAM_INOUT: + flags = XPT_PD_IN | XPT_PD_OUT; + break; + } + + if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator, + "retval")) { + if (flags != XPT_PD_OUT) { + IDL_tree_error(tree, "can't have [retval] with in%s param " + "(only out)\n", + flags & XPT_PD_OUT ? "out" : ""); + return FALSE; + } + flags |= XPT_PD_RETVAL; + } + + if (is_dipper_type && (flags & XPT_PD_OUT)) { + flags &= ~XPT_PD_OUT; + flags |= XPT_PD_IN | XPT_PD_DIPPER; + } + + if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator, + "shared")) { + if (flags & XPT_PD_IN) { + IDL_tree_error(tree, "can't have [shared] with in%s param " + "(only out)\n", + flags & XPT_PD_OUT ? "out" : ""); + return FALSE; + } + flags |= XPT_PD_SHARED; + } + + /* stick param where we can see it later */ + state->tree = tree; + return fill_pd_from_type(state, pd, flags, + IDL_PARAM_DCL(tree).param_type_spec); +} + +/* XXXshaver common with xpidl_header.c */ +#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data)) +#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec) +#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree))) + +static gboolean +fill_pd_as_nsresult(XPTParamDescriptor *pd) +{ + pd->type.prefix.flags = TD_UINT32; /* TD_NSRESULT */ + return TRUE; +} + +static gboolean +typelib_attr_accessor(TreeState *state, XPTMethodDescriptor *meth, + gboolean getter, gboolean hidden) +{ + uint8 methflags = 0; + uint8 pdflags = 0; + + methflags |= getter ? XPT_MD_GETTER : XPT_MD_SETTER; + methflags |= hidden ? XPT_MD_HIDDEN : 0; + if (!XPT_FillMethodDescriptor(ARENA(state), meth, methflags, + ATTR_IDENT(state->tree).str, 1)) + return FALSE; + + if (getter) { + if (DIPPER_TYPE(ATTR_TYPE_DECL(state->tree))) { + pdflags |= (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER); + } else { + pdflags |= (XPT_PD_RETVAL | XPT_PD_OUT); + } + } else { + pdflags |= XPT_PD_IN; + } + + if (!fill_pd_from_type(state, meth->params, pdflags, + ATTR_TYPE_DECL(state->tree))) + return FALSE; + + fill_pd_as_nsresult(meth->result); + NEXT_METH(state)++; + return TRUE; +} + +static gboolean +typelib_attr_dcl(TreeState *state) +{ + XPTInterfaceDescriptor *id = CURRENT(state); + XPTMethodDescriptor *meth; + gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly; + + /* XXX this only handles the first ident; elsewhere too... */ + IDL_tree ident = + IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).data; + + /* If it's marked [noscript], mark it as hidden in the typelib. */ + gboolean hidden = (IDL_tree_property_get(ident, "noscript") != NULL); + + if (!verify_attribute_declaration(state->tree)) + return FALSE; + + if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, + (PRUint16) (read_only ? 1 : 2))) + return FALSE; + + meth = &id->method_descriptors[NEXT_METH(state)]; + + return typelib_attr_accessor(state, meth, TRUE, hidden) && + (read_only || typelib_attr_accessor(state, meth + 1, FALSE, hidden)); +} + +static gboolean +typelib_op_dcl(TreeState *state) +{ + XPTInterfaceDescriptor *id = CURRENT(state); + XPTMethodDescriptor *meth; + struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree); + IDL_tree iter; + uint16 num_args = 0; + uint8 op_flags = 0; + gboolean op_notxpcom = (IDL_tree_property_get(op->ident, "notxpcom") + != NULL); + gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript") + != NULL); + + if (!verify_method_declaration(state->tree)) + return FALSE; + + if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, 1)) + return FALSE; + + meth = &id->method_descriptors[NEXT_METH(state)]; + + for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) + num_args++; /* count params */ + if (op->op_type_spec && !op_notxpcom) + num_args++; /* fake param for _retval */ + + if (op_noscript) + op_flags |= XPT_MD_HIDDEN; + if (op_notxpcom) + op_flags |= XPT_MD_NOTXPCOM; + + /* XXXshaver constructor? */ + +#ifdef DEBUG_shaver_method + fprintf(stdout, "DBG: adding method %s (nargs %d)\n", + IDL_IDENT(op->ident).str, num_args); +#endif + if (!XPT_FillMethodDescriptor(ARENA(state), meth, op_flags, + IDL_IDENT(op->ident).str, + (uint8) num_args)) + return FALSE; + + for (num_args = 0, iter = op->parameter_dcls; iter; + iter = IDL_LIST(iter).next, num_args++) { + XPTParamDescriptor *pd = &meth->params[num_args]; + if (!fill_pd_from_param(state, pd, IDL_LIST(iter).data)) + return FALSE; + } + + /* stick retval param where we can see it later */ + state->tree = op->op_type_spec; + + /* XXX unless [notxpcom] */ + if (!op_notxpcom) { + if (op->op_type_spec) { + uint8 pdflags = DIPPER_TYPE(op->op_type_spec) ? + (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER) : + (XPT_PD_RETVAL | XPT_PD_OUT); + + if (!fill_pd_from_type(state, &meth->params[num_args], + pdflags, op->op_type_spec)) + return FALSE; + } + + if (!fill_pd_as_nsresult(meth->result)) + return FALSE; + } else { +#ifdef DEBUG_shaver_notxpcom + fprintf(stderr, "%s is notxpcom\n", IDL_IDENT(op->ident).str); +#endif + if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL, + op->op_type_spec)) + return FALSE; + } + NEXT_METH(state)++; + return TRUE; +} + +static gboolean +typelib_const_dcl(TreeState *state) +{ + struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree); + const char *name = IDL_IDENT(dcl->ident).str; + gboolean is_long; + gboolean sign; + IDL_tree real_type; + XPTInterfaceDescriptor *id; + XPTConstDescriptor *cd; + IDL_longlong_t value; + + if (!verify_const_declaration(state->tree)) + return FALSE; + + /* Could be a typedef; try to map it to the real type. */ + real_type = find_underlying_type(dcl->const_type); + real_type = real_type ? real_type : dcl->const_type; + is_long = (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG); + + id = CURRENT(state); + if (!XPT_InterfaceDescriptorAddConsts(ARENA(state), id, 1)) + return FALSE; + cd = &id->const_descriptors[NEXT_CONST(state)]; + + cd->name = IDL_IDENT(dcl->ident).str; +#ifdef DEBUG_shaver_const + fprintf(stderr, "DBG: adding const %s\n", cd->name); +#endif + if (!fill_td_from_type(state, &cd->type, dcl->const_type)) + return FALSE; + + value = IDL_INTEGER(dcl->const_exp).value; + sign = IDL_TYPE_INTEGER(dcl->const_type).f_signed; + if (is_long) { + if (sign) + cd->value.i32 = value; + else + cd->value.ui32 = value; + } else { + if (sign) + cd->value.i16 = value; + else + cd->value.ui16 = value; + } + NEXT_CONST(state)++; + return TRUE; +} + +static gboolean +typelib_enum(TreeState *state) +{ + XPIDL_WARNING((state->tree, IDL_WARNING1, + "enums not supported, enum \'%s\' ignored", + IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str)); + return TRUE; +} + +backend * +xpidl_typelib_dispatch(void) +{ + static backend result; + static nodeHandler table[IDLN_LAST]; + static gboolean initialized = FALSE; + + result.emit_prolog = typelib_prolog; + result.emit_epilog = typelib_epilog; + + if (!initialized) { + /* Initialize non-NULL elements */ + table[IDLN_LIST] = typelib_list; + table[IDLN_ATTR_DCL] = typelib_attr_dcl; + table[IDLN_OP_DCL] = typelib_op_dcl; + table[IDLN_INTERFACE] = typelib_interface; + table[IDLN_CONST_DCL] = typelib_const_dcl; + table[IDLN_TYPE_ENUM] = typelib_enum; + table[IDLN_NATIVE] = check_native; + initialized = TRUE; + } + + result.dispatch_table = table; + return &result; +} + + + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c new file mode 100644 index 00000000..25d04212 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c @@ -0,0 +1,851 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Utility functions called by various backends. + */ + +#include "xpidl.h" + +/* XXXbe static */ char OOM[] = "ERROR: out of memory\n"; + +void * +xpidl_malloc(size_t nbytes) +{ + void *p = malloc(nbytes); + if (!p) { + fputs(OOM, stderr); + exit(1); + } + return p; +} + +char * +xpidl_strdup(const char *s) +{ +#if defined(XP_MAC) || defined(XP_SOLARIS) /* bird: dunno why this is required, but whatever*/ + size_t len = strlen(s); + char *ns = malloc(len + 1); + if (ns) + memcpy(ns, s, len + 1); +#else + char *ns = strdup(s); +#endif + if (!ns) { + fputs(OOM, stderr); + exit(1); + } + return ns; +} + +void +xpidl_write_comment(TreeState *state, int indent) +{ + fprintf(state->file, "%*s/* ", indent, ""); + IDL_tree_to_IDL(state->tree, state->ns, state->file, + IDLF_OUTPUT_NO_NEWLINES | + IDLF_OUTPUT_NO_QUALIFY_IDENTS | + IDLF_OUTPUT_PROPERTIES); + fputs(" */\n", state->file); +} + +/* + * Print an iid to into a supplied buffer; the buffer should be at least + * UUID_LENGTH bytes. + */ +gboolean +xpidl_sprint_iid(nsID *id, char iidbuf[]) +{ + int printed; + + printed = sprintf(iidbuf, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2, + (PRUint32) id->m3[0], (PRUint32) id->m3[1], + (PRUint32) id->m3[2], (PRUint32) id->m3[3], + (PRUint32) id->m3[4], (PRUint32) id->m3[5], + (PRUint32) id->m3[6], (PRUint32) id->m3[7]); + +#ifdef SPRINTF_RETURNS_STRING + return (printed && strlen((char *)printed) == 36); +#else + return (printed == 36); +#endif +} + +/* We only parse the {}-less format. */ +static const char nsIDFmt2[] = + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; + +/* + * Parse a uuid string into an nsID struct. We cannot link against libxpcom, + * so we re-implement nsID::Parse here. + */ +gboolean +xpidl_parse_iid(nsID *id, const char *str) +{ + PRInt32 count = 0; + PRInt32 n1, n2, n3[8]; + PRInt32 n0, i; + + XPT_ASSERT(str != NULL); + + if (strlen(str) != 36) { + return FALSE; + } + +#ifdef DEBUG_shaver_iid + fprintf(stderr, "parsing iid %s\n", str); +#endif + + count = sscanf(str, nsIDFmt2, + &n0, &n1, &n2, + &n3[0],&n3[1],&n3[2],&n3[3], + &n3[4],&n3[5],&n3[6],&n3[7]); + + id->m0 = (PRInt32) n0; + id->m1 = (PRInt16) n1; + id->m2 = (PRInt16) n2; + for (i = 0; i < 8; i++) { + id->m3[i] = (PRInt8) n3[i]; + } + +#ifdef DEBUG_shaver_iid + if (count == 11) { + fprintf(stderr, "IID parsed to "); + print_IID(id, stderr); + fputs("\n", stderr); + } +#endif + return (gboolean)(count == 11); +} + +gboolean +verify_const_declaration(IDL_tree const_tree) { + struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(const_tree); + const char *name = IDL_IDENT(dcl->ident).str; + IDL_tree real_type; + + /* const -> list -> interface */ + if (!IDL_NODE_UP(IDL_NODE_UP(const_tree)) || + IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(const_tree))) + != IDLN_INTERFACE) { + IDL_tree_error(const_tree, + "const declaration \'%s\' outside interface", + name); + return FALSE; + } + + /* Could be a typedef; try to map it to the real type. */ + real_type = find_underlying_type(dcl->const_type); + real_type = real_type ? real_type : dcl->const_type; + if (IDL_NODE_TYPE(real_type) == IDLN_TYPE_INTEGER && + (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_SHORT || + IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG)) + { + if (!IDL_TYPE_INTEGER(real_type).f_signed && + IDL_INTEGER(dcl->const_exp).value < 0) + { +#ifndef G_HAVE_GINT64 + /* + * For platforms without longlong support turned on we can get + * confused by the high bit of the long value and think that it + * represents a negative value in an unsigned declaration. + * In that case we don't know if it is the programmer who is + * confused or the compiler. So we issue a warning instead of + * an error. + */ + if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) + { + XPIDL_WARNING((const_tree, IDL_WARNING1, + "unsigned const declaration \'%s\' " + "initialized with (possibly) negative constant", + name)); + return TRUE; + } +#endif + IDL_tree_error(const_tree, + "unsigned const declaration \'%s\' initialized with " + "negative constant", + name); + return FALSE; + } + } else { + IDL_tree_error(const_tree, + "const declaration \'%s\' must be of type short or long", + name); + return FALSE; + } + + return TRUE; +} + + + +/* + * This method consolidates error checking needed when coercing the XPIDL compiler + * via the -t flag to generate output for a specific version of XPConnect. + */ +static gboolean +verify_type_fits_version(IDL_tree in_tree, IDL_tree error_tree) +{ + if (major_version == 1 && minor_version == 1) + { + /* XPIDL Version 1.1 checks */ + + /* utf8string, cstring, and astring types are not supported */ + if (IDL_tree_property_get(in_tree, "utf8string") != NULL || + IDL_tree_property_get(in_tree, "cstring") != NULL || + IDL_tree_property_get(in_tree, "astring") != NULL) + { + IDL_tree_error(error_tree, + "Cannot use [utf8string], [cstring] and [astring] " + "types when generating version 1.1 typelibs\n"); + return FALSE; + } + } + return TRUE; +} + +gboolean +verify_attribute_declaration(IDL_tree attr_tree) +{ + IDL_tree iface; + IDL_tree ident; + IDL_tree attr_type; + gboolean scriptable_interface; + + /* We don't support attributes named IID, conflicts with static GetIID + * member. The conflict is due to certain compilers (VC++) choosing a + * different vtable order, placing GetIID at the beginning regardless + * of it's placement + */ + if (strcmp( + IDL_IDENT( + IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str, + "IID") == 0) { + IDL_tree_error(attr_tree, + "Attributes named IID not supported, causes vtable " + "ordering problems"); + return FALSE; + } + /* + * Verify that we've been called on an interface, and decide if the + * interface was marked [scriptable]. + */ + if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) && + IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree))) + == IDLN_INTERFACE) + { + scriptable_interface = + (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") + != NULL); + } else { + IDL_tree_error(attr_tree, + "verify_attribute_declaration called on a non-interface?"); + return FALSE; + } + + /* + * Grab the first of the list of idents and hope that it'll + * say scriptable or no. + */ + ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data; + + /* + * If the interface isn't scriptable, or the attribute is marked noscript, + * there's no need to check. + */ + if (!scriptable_interface || + IDL_tree_property_get(ident, "noscript") != NULL) + return TRUE; + + /* + * If it should be scriptable, check that the type is non-native. nsid, + * domstring, utf8string, cstring, astring are exempted. + */ + attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec; + + if (attr_type != NULL) + { + if (UP_IS_NATIVE(attr_type) && + IDL_tree_property_get(attr_type, "nsid") == NULL && + IDL_tree_property_get(attr_type, "domstring") == NULL && + IDL_tree_property_get(attr_type, "utf8string") == NULL && + IDL_tree_property_get(attr_type, "cstring") == NULL && + IDL_tree_property_get(attr_type, "astring") == NULL) + { + IDL_tree_error(attr_tree, + "attributes in [scriptable] interfaces that are " + "non-scriptable because they refer to native " + "types must be marked [noscript]\n"); + return FALSE; + } + /* + * We currently don't support properties of type nsid that aren't + * pointers or references, unless they are marked [notxpcom} and + * must be read-only + */ + + if ((IDL_tree_property_get(ident, "notxpcom") == NULL || !(IDL_ATTR_DCL(attr_tree).f_readonly)) && + IDL_tree_property_get(attr_type,"nsid") != NULL && + IDL_tree_property_get(attr_type,"ptr") == NULL && + IDL_tree_property_get(attr_type,"ref") == NULL) + { + IDL_tree_error(attr_tree, + "Feature not currently supported: " + "attributes with a type of nsid must be marked " + "either [ptr] or [ref], or " + "else must be marked [notxpcom] " + "and must be read-only\n"); + return FALSE; + } + + /* + * Run additional error checks on the attribute type if targetting an + * older version of XPConnect. + */ + + if (!verify_type_fits_version(attr_type, attr_tree)) + return FALSE; + } + + if (IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).next != NULL) + { + IDL_tree_error(attr_tree, + "multiple attributes in a single declaration is not supported\n"); + return FALSE; + } + return TRUE; +} + +/* + * Find the underlying type of an identifier typedef. + * + * All the needed tree-walking seems pretty shaky; isn't there something in + * libIDL to automate this? + */ +IDL_tree /* IDL_TYPE_DCL */ +find_underlying_type(IDL_tree typedef_ident) +{ + IDL_tree up; + + if (typedef_ident == NULL || IDL_NODE_TYPE(typedef_ident) != IDLN_IDENT) + return NULL; + + up = IDL_NODE_UP(typedef_ident); + if (up == NULL || IDL_NODE_TYPE(up) != IDLN_LIST) + return NULL; + up = IDL_NODE_UP(up); + if (up == NULL || IDL_NODE_TYPE(up) != IDLN_TYPE_DCL) + return NULL; + + return IDL_TYPE_DCL(up).type_spec; +} + +static IDL_tree /* IDL_PARAM_DCL */ +find_named_parameter(IDL_tree method_tree, const char *param_name) +{ + IDL_tree iter; + for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter; + iter = IDL_LIST(iter).next) + { + IDL_tree param = IDL_LIST(iter).data; + IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; + const char *current_name = IDL_IDENT(simple_decl).str; + if (strcmp(current_name, param_name) == 0) + return param; + } + return NULL; +} + +typedef enum ParamAttrType { + IID_IS, + LENGTH_IS, + SIZE_IS +} ParamAttrType; + +/* + * Check that parameters referred to by attributes such as size_is exist and + * refer to parameters of the appropriate type. + */ +static gboolean +check_param_attribute(IDL_tree method_tree, IDL_tree param, + ParamAttrType whattocheck) +{ + const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str; + const char *referred_name = NULL; + IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec; + IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator; + const char *param_name = IDL_IDENT(simple_decl).str; + const char *attr_name; + const char *needed_type; + + if (whattocheck == IID_IS) { + attr_name = "iid_is"; + needed_type = "IID"; + } else if (whattocheck == LENGTH_IS) { + attr_name = "length_is"; + needed_type = "unsigned long (or PRUint32)"; + } else if (whattocheck == SIZE_IS) { + attr_name = "size_is"; + needed_type = "unsigned long (or PRUint32)"; + } else { + XPT_ASSERT("asked to check an unknown attribute type!"); + return TRUE; + } + + referred_name = IDL_tree_property_get(simple_decl, attr_name); + if (referred_name != NULL) { + IDL_tree referred_param = find_named_parameter(method_tree, + referred_name); + IDL_tree referred_param_type; + if (referred_param == NULL) { + IDL_tree_error(method_tree, + "attribute [%s(%s)] refers to missing " + "parameter \"%s\"", + attr_name, referred_name, referred_name); + return FALSE; + } + if (referred_param == param) { + IDL_tree_error(method_tree, + "attribute [%s(%s)] refers to it's own parameter", + attr_name, referred_name); + return FALSE; + } + + referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec; + if (whattocheck == IID_IS) { + /* require IID type */ + if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) { + IDL_tree_error(method_tree, + "target \"%s\" of [%s(%s)] attribute " + "must be of %s type", + referred_name, attr_name, referred_name, + needed_type); + return FALSE; + } + } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) { + /* require PRUint32 type */ + IDL_tree real_type; + + /* Could be a typedef; try to map it to the real type. */ + real_type = find_underlying_type(referred_param_type); + real_type = real_type ? real_type : referred_param_type; + + if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER || + IDL_TYPE_INTEGER(real_type).f_signed != FALSE || + IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG) + { + IDL_tree_error(method_tree, + "target \"%s\" of [%s(%s)] attribute " + "must be of %s type", + referred_name, attr_name, referred_name, + needed_type); + + return FALSE; + } + } + } + + return TRUE; +} + + +/* + * Common method verification code, called by *op_dcl in the various backends. + */ +gboolean +verify_method_declaration(IDL_tree method_tree) +{ + struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree); + IDL_tree iface; + IDL_tree iter; + gboolean notxpcom; + gboolean scriptable_interface; + gboolean scriptable_method; + gboolean seen_retval = FALSE; + const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str; + + /* We don't support attributes named IID, conflicts with static GetIID + * member. The conflict is due to certain compilers (VC++) choosing a + * different vtable order, placing GetIID at the beginning regardless + * of it's placement + */ + if (strcmp(method_name, "GetIID") == 0) { + IDL_tree_error(method_tree, + "Methods named GetIID not supported, causes vtable " + "ordering problems"); + return FALSE; + } + if (op->f_varargs) { + /* We don't currently support varargs. */ + IDL_tree_error(method_tree, "varargs are not currently supported"); + return FALSE; + } + + /* + * Verify that we've been called on an interface, and decide if the + * interface was marked [scriptable]. + */ + if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) && + IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree))) + == IDLN_INTERFACE) + { + scriptable_interface = + (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable") + != NULL); + } else { + IDL_tree_error(method_tree, + "verify_method_declaration called on a non-interface?"); + return FALSE; + } + + /* + * Require that any method in an interface marked as [scriptable], that + * *isn't* scriptable because it refers to some native type, be marked + * [noscript] or [notxpcom]. + * + * Also check that iid_is points to nsid, and length_is, size_is points + * to unsigned long. + */ + notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL; + + scriptable_method = scriptable_interface && + !notxpcom && + IDL_tree_property_get(op->ident, "noscript") == NULL; + + /* Loop through the parameters and check. */ + for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) { + IDL_tree param = IDL_LIST(iter).data; + IDL_tree param_type = + IDL_PARAM_DCL(param).param_type_spec; + IDL_tree simple_decl = + IDL_PARAM_DCL(param).simple_declarator; + const char *param_name = IDL_IDENT(simple_decl).str; + + /* + * Reject this method if it should be scriptable and some parameter is + * native that isn't marked with either nsid, domstring, utf8string, + * cstring, astring or iid_is. + */ + if (scriptable_method && + UP_IS_NATIVE(param_type) && + IDL_tree_property_get(param_type, "nsid") == NULL && + IDL_tree_property_get(simple_decl, "iid_is") == NULL && + IDL_tree_property_get(param_type, "domstring") == NULL && + IDL_tree_property_get(param_type, "utf8string") == NULL && + IDL_tree_property_get(param_type, "cstring") == NULL && + IDL_tree_property_get(param_type, "astring") == NULL) + { + IDL_tree_error(method_tree, + "methods in [scriptable] interfaces that are " + "non-scriptable because they refer to native " + "types (parameter \"%s\") must be marked " + "[noscript]", param_name); + return FALSE; + } + + /* + * nsid's parameters that aren't ptr's or ref's are not currently + * supported in xpcom or non-xpcom (marked with [notxpcom]) methods + * as input parameters + */ + if (!(notxpcom && IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) && + IDL_tree_property_get(param_type, "nsid") != NULL && + IDL_tree_property_get(param_type, "ptr") == NULL && + IDL_tree_property_get(param_type, "ref") == NULL) + { + IDL_tree_error(method_tree, + "Feature currently not supported: " + "parameter \"%s\" is of type nsid and " + "must be marked either [ptr] or [ref] " + "or method \"%s\" must be marked [notxpcom] " + "and must not be an input parameter", + param_name, + method_name); + return FALSE; + } + /* + * Sanity checks on return values. + */ + if (IDL_tree_property_get(simple_decl, "retval") != NULL) { + if (IDL_LIST(iter).next != NULL) { + IDL_tree_error(method_tree, + "only the last parameter can be marked [retval]"); + return FALSE; + } + if (op->op_type_spec) { + IDL_tree_error(method_tree, + "can't have [retval] with non-void return type"); + return FALSE; + } + /* In case XPConnect relaxes the retval-is-last restriction. */ + if (seen_retval) { + IDL_tree_error(method_tree, + "can't have more than one [retval] parameter"); + return FALSE; + } + seen_retval = TRUE; + } + + /* + * Confirm that [shared] attributes are only used with string, wstring, + * or native (but not nsid, domstring, utf8string, cstring or astring) + * and can't be used with [array]. + */ + if (IDL_tree_property_get(simple_decl, "shared") != NULL) { + IDL_tree real_type; + real_type = find_underlying_type(param_type); + real_type = real_type ? real_type : param_type; + + if (IDL_tree_property_get(simple_decl, "array") != NULL) { + IDL_tree_error(method_tree, + "[shared] parameter \"%s\" cannot " + "be of array type", param_name); + return FALSE; + } + + if (!(IDL_NODE_TYPE(real_type) == IDLN_TYPE_STRING || + IDL_NODE_TYPE(real_type) == IDLN_TYPE_WIDE_STRING || + (UP_IS_NATIVE(real_type) && + !IDL_tree_property_get(real_type, "nsid") && + !IDL_tree_property_get(real_type, "domstring") && + !IDL_tree_property_get(real_type, "utf8string") && + !IDL_tree_property_get(real_type, "cstring") && + !IDL_tree_property_get(real_type, "astring")))) + { + IDL_tree_error(method_tree, + "[shared] parameter \"%s\" must be of type " + "string, wstring or native", param_name); + return FALSE; + } + } + + /* + * inout is not allowed with "domstring", "UTF8String", "CString" + * and "AString" types + */ + if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT && + UP_IS_NATIVE(param_type) && + (IDL_tree_property_get(param_type, "domstring") != NULL || + IDL_tree_property_get(param_type, "utf8string") != NULL || + IDL_tree_property_get(param_type, "cstring") != NULL || + IDL_tree_property_get(param_type, "astring") != NULL )) { + IDL_tree_error(method_tree, + "[domstring], [utf8string], [cstring], [astring] " + "types cannot be used as inout parameters"); + return FALSE; + } + + + /* + * arrays of domstring, utf8string, cstring, astring types not allowed + */ + if (IDL_tree_property_get(simple_decl, "array") != NULL && + UP_IS_NATIVE(param_type) && + (IDL_tree_property_get(param_type, "domstring") != NULL || + IDL_tree_property_get(param_type, "utf8string") != NULL || + IDL_tree_property_get(param_type, "cstring") != NULL || + IDL_tree_property_get(param_type, "astring") != NULL)) { + IDL_tree_error(method_tree, + "[domstring], [utf8string], [cstring], [astring] " + "types cannot be used in array parameters"); + return FALSE; + } + + if (!check_param_attribute(method_tree, param, IID_IS) || + !check_param_attribute(method_tree, param, LENGTH_IS) || + !check_param_attribute(method_tree, param, SIZE_IS)) + return FALSE; + + /* + * Run additional error checks on the parameter type if targetting an + * older version of XPConnect. + */ + + if (!verify_type_fits_version(param_type, method_tree)) + return FALSE; + + } + + /* XXX q: can return type be nsid? */ + /* Native return type? */ + if (scriptable_method && + op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) && + IDL_tree_property_get(op->op_type_spec, "nsid") == NULL && + IDL_tree_property_get(op->op_type_spec, "domstring") == NULL && + IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL && + IDL_tree_property_get(op->op_type_spec, "cstring") == NULL && + IDL_tree_property_get(op->op_type_spec, "astring") == NULL) + { + IDL_tree_error(method_tree, + "methods in [scriptable] interfaces that are " + "non-scriptable because they return native " + "types must be marked [noscript]"); + return FALSE; + } + + + /* + * nsid's parameters that aren't ptr's or ref's are not currently + * supported in xpcom + */ + if (!notxpcom && + op->op_type_spec != NULL && + IDL_tree_property_get(op->op_type_spec, "nsid") != NULL && + IDL_tree_property_get(op->op_type_spec, "ptr") == NULL && + IDL_tree_property_get(op->op_type_spec, "ref") == NULL) + { + IDL_tree_error(method_tree, + "Feature currently not supported: " + "return value is of type nsid and " + "must be marked either [ptr] or [ref], " + "or else method \"%s\" must be marked [notxpcom] ", + method_name); + return FALSE; + } + + /* + * Run additional error checks on the return type if targetting an + * older version of XPConnect. + */ + + if (op->op_type_spec != NULL && + !verify_type_fits_version(op->op_type_spec, method_tree)) + { + return FALSE; + } + + return TRUE; +} + +/* + * Verify that a native declaration has an associated C++ expression, i.e. that + * it's of the form native <idl-name>(<c++-name>) + */ +gboolean +check_native(TreeState *state) +{ + char *native_name; + /* require that native declarations give a native type */ + if (IDL_NATIVE(state->tree).user_type) + return TRUE; + native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str; + IDL_tree_error(state->tree, + "``native %s;'' needs C++ type: ``native %s(<C++ type>);''", + native_name, native_name); + return FALSE; +} + +/* + * Print a GSList as char strings to a file. + */ +void +printlist(FILE *outfile, GSList *slist) +{ + guint i; + guint len = g_slist_length(slist); + + for(i = 0; i < len; i++) { + fprintf(outfile, + "%s\n", (char *)g_slist_nth_data(slist, i)); + } +} + +void +xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data) +{ + IDL_tree_func_data tfd; + + while (p) { + struct _IDL_LIST *list = &IDL_LIST(p); + tfd.tree = list->data; + if (!foreach(&tfd, user_data)) + return; + p = list->next; + } +} + +/* + * Verify that the interface declaration is correct + */ +gboolean +verify_interface_declaration(IDL_tree interface_tree) +{ + IDL_tree iter; + /* + * If we have the scriptable attribute then make sure all of our direct + * parents have it as well. + * NOTE: We don't recurse since all interfaces will fall through here + */ + if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident, + "scriptable")) { + for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter; + iter = IDL_LIST(iter).next) { + if (IDL_tree_property_get( + IDL_INTERFACE(iter).ident, "scriptable") == 0) { + XPIDL_WARNING((interface_tree,IDL_WARNING1, + "%s is scriptable but inherits from the non-scriptable interface %s\n", + IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str, + IDL_IDENT(IDL_INTERFACE(iter).ident).str)); + } + } + } + return TRUE; +} + +/* + * Return a pointer to the start of the base filename of path + */ +char * +xpidl_basename(const char * path) +{ + char * result = g_path_get_basename(path); + /* + *If this is windows then we'll handle either / or \ as a separator + * g_basename only handles \ for windows + */ +#if defined(XP_WIN32) +# error adapt regarding g_basename() vs. g_path_get_basename()! + const char * slash = strrchr(path, '/'); + /* If we found a slash and its after the current default OS separator */ + if (slash != NULL && (slash > result)) + result = slash + 1; +#endif + return result; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in new file mode 100644 index 00000000..1447128f --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in @@ -0,0 +1,50 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom + +DIRS = public src tools + +include $(topsrcdir)/config/rules.mk + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in new file mode 100644 index 00000000..3e452486 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in @@ -0,0 +1,51 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom + +EXPORTS = xpt_arena.h xpt_struct.h xpt_xdr.h +EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) + +include $(topsrcdir)/config/rules.mk + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h new file mode 100644 index 00000000..2b277467 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h @@ -0,0 +1,145 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* + * Simple arena allocator for xpt (which avoids using NSPR). + */ + +#ifndef __xpt_arena_h__ +#define __xpt_arena_h__ + +#include "prtypes.h" +#include <stdlib.h> + +#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP +#define XPT_NewArena VBoxNsxpXPT_NewArena +#define XPT_ArenaMalloc VBoxNsxpXPT_ArenaMalloc +#define XPT_DestroyArena VBoxNsxpXPT_DestroyArena +#define XPT_ArenaFree VBoxNsxpXPT_ArenaFree +#define XPT_DestroyArena VBoxNsxpXPT_DestroyArena +#define XPT_DumpStats VBoxNsxpXPT_DumpStats +#define XPT_NotifyDoneLoading VBoxNsxpXPT_NotifyDoneLoading +#define XPT_ArenaStrDup VBoxNsxpXPT_ArenaStrDup +#define XPT_AssertFailed VBoxNsxpXPT_AssertFailed +#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */ + +/* + * The linkage of XPT API functions differs depending on whether the file is + * used within the XPT library or not. Any source file within the XPT + * library should define EXPORT_XPT_API whereas any client of the library + * should not. + */ +#ifdef EXPORT_XPT_API +#define XPT_PUBLIC_API(t) PR_IMPLEMENT(t) +#define XPT_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t) +#else +#ifdef _WIN32 +# define XPT_PUBLIC_API(t) __declspec(dllimport) t +# define XPT_PUBLIC_DATA(t) __declspec(dllimport) t +#else +# define XPT_PUBLIC_API(t) PR_IMPLEMENT(t) +# define XPT_PUBLIC_DATA(t) t +#endif +#endif +#define XPT_FRIEND_API(t) XPT_PUBLIC_API(t) +#define XPT_FRIEND_DATA(t) XPT_PUBLIC_DATA(t) + +PR_BEGIN_EXTERN_C + +/* + * Simple Arena support. Use with caution! + */ + +typedef struct XPTArena XPTArena; + +XPT_PUBLIC_API(XPTArena *) +XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name); + +XPT_PUBLIC_API(void) +XPT_DestroyArena(XPTArena *arena); + +XPT_PUBLIC_API(void) +XPT_DumpStats(XPTArena *arena); + +XPT_PUBLIC_API(void *) +XPT_ArenaMalloc(XPTArena *arena, size_t size); + +XPT_PUBLIC_API(char *) +XPT_ArenaStrDup(XPTArena *arena, const char * s); + +XPT_PUBLIC_API(void) +XPT_NotifyDoneLoading(XPTArena *arena); + +XPT_PUBLIC_API(void) +XPT_ArenaFree(XPTArena *arena, void* block); + +/* --------------------------------------------------------- */ + +#define XPT_MALLOC(_arena, _bytes) \ + XPT_ArenaMalloc((_arena), (_bytes)) + +#ifdef DEBUG +#define XPT_FREE(_arena, _ptr) \ + XPT_ArenaFree((_arena), (_ptr)) +#else +#define XPT_FREE(_arena, _ptr) \ + ((void)0) +#endif + +#define XPT_STRDUP(_arena, _s) \ + XPT_ArenaStrDup((_arena), (_s)) + +#define XPT_CALLOC(_arena, _size) XPT_MALLOC((_arena), (_size)) +#define XPT_NEW(_arena, _struct) ((_struct *) XPT_MALLOC((_arena), sizeof(_struct))) +#define XPT_NEWZAP(_arena, _struct) XPT_NEW((_arena), _struct) +#define XPT_DELETE(_arena, _ptr) do{XPT_FREE((_arena), (_ptr)); ((_ptr)) = NULL;}while(0) +#define XPT_FREEIF(_arena, _ptr) do{if ((_ptr)) XPT_FREE((_arena), (_ptr));}while(0) + +/* --------------------------------------------------------- */ + +#ifdef DEBUG +XPT_PUBLIC_API(void) +XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno); +#define XPT_ASSERT(_expr) \ + ((_expr)?((void)0):XPT_AssertFailed(# _expr, __FILE__, __LINE__)) +#else +#define XPT_ASSERT(_expr) ((void)0) +#endif + +PR_END_EXTERN_C + +#endif /* __xpt_arena_h__ */ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h new file mode 100644 index 00000000..c7f36f2d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h @@ -0,0 +1,562 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* + * Structures matching the in-memory representation of typelib structures. + * http://www.mozilla.org/scriptable/typelib_file.html + */ + +#ifndef __xpt_struct_h__ +#define __xpt_struct_h__ + +#include "xpt_arena.h" + +#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP +#define XPT_NewHeader VBoxNsxpXPT_NewHeader +#define XPT_NewStringZ VBoxNsxpXPT_NewStringZ +#define XPT_NewAnnotation VBoxNsxpXPT_NewAnnotation +#define XPT_SizeOfHeaderBlock VBoxNsxpXPT_SizeOfHeaderBlock +#define XPT_NewInterfaceDescriptor VBoxNsxpXPT_NewInterfaceDescriptor +#define XPT_FillInterfaceDirectoryEntry VBoxNsxpXPT_FillInterfaceDirectoryEntry +#define XPT_FillMethodDescriptor VBoxNsxpXPT_FillMethodDescriptor +#define XPT_FreeHeader VBoxNsxpXPT_FreeHeader +#define XPT_ParseVersionString VBoxNsxpXPT_ParseVersionString +#define XPT_DestroyInterfaceDirectoryEntry VBoxNsxpXPT_DestroyInterfaceDirectoryEntry +#define XPT_FillParamDescriptor VBoxNsxpXPT_FillParamDescriptor +#define XPT_FreeInterfaceDescriptor VBoxNsxpXPT_FreeInterfaceDescriptor +#define XPT_InterfaceDescriptorAddConsts VBoxNsxpXPT_InterfaceDescriptorAddConsts +#define XPT_InterfaceDescriptorAddMethods VBoxNsxpXPT_InterfaceDescriptorAddMethods +#define XPT_InterfaceDescriptorAddTypes VBoxNsxpXPT_InterfaceDescriptorAddTypes +#define XPT_GetInterfaceIndexByName VBoxNsxpXPT_GetInterfaceIndexByName +#define XPT_NewString VBoxNsxpXPT_NewString +#define XPT_SizeOfHeader VBoxNsxpXPT_SizeOfHeader +#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */ + +PR_BEGIN_EXTERN_C + +/* + * Originally, I was going to have structures that exactly matched the on-disk + * representation, but that proved difficult: different compilers can pack + * their structs differently, and that makes overlaying them atop a + * read-from-disk byte buffer troublesome. So now I just have some structures + * that are used in memory, and we're going to write a nice XDR library to + * write them to disk and stuff. It is pure joy. -- shaver + */ + +/* Structures for the typelib components */ + +typedef struct XPTHeader XPTHeader; +typedef struct XPTInterfaceDirectoryEntry XPTInterfaceDirectoryEntry; +typedef struct XPTInterfaceDescriptor XPTInterfaceDescriptor; +typedef struct XPTConstDescriptor XPTConstDescriptor; +typedef struct XPTMethodDescriptor XPTMethodDescriptor; +typedef struct XPTParamDescriptor XPTParamDescriptor; +typedef struct XPTTypeDescriptor XPTTypeDescriptor; +typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix; +typedef struct XPTString XPTString; +typedef struct XPTAnnotation XPTAnnotation; +#ifndef nsID_h__ +/* + * We can't include nsID.h, because it's full of C++ goop and we're not doing + * C++ here, so we define our own minimal struct. We protect against multiple + * definitions of this struct, though, and use the same field naming. + */ +struct nsID { + PRUint32 m0; + PRUint16 m1; + PRUint16 m2; + PRUint8 m3[8]; +}; + +typedef struct nsID nsID; +#endif + +#define XPT_COPY_IID(to, from) \ + (to).m0 = (from).m0; \ + (to).m1 = (from).m1; \ + (to).m2 = (from).m2; \ + (to).m3[0] = (from).m3[0]; \ + (to).m3[1] = (from).m3[1]; \ + (to).m3[2] = (from).m3[2]; \ + (to).m3[3] = (from).m3[3]; \ + (to).m3[4] = (from).m3[4]; \ + (to).m3[5] = (from).m3[5]; \ + (to).m3[6] = (from).m3[6]; \ + (to).m3[7] = (from).m3[7]; + + +/* + * Every XPCOM typelib file begins with a header. + */ +struct XPTHeader { + PRUint8 magic[16]; + PRUint8 major_version; + PRUint8 minor_version; + PRUint16 num_interfaces; + PRUint32 file_length; + XPTInterfaceDirectoryEntry *interface_directory; + PRUint32 data_pool; + XPTAnnotation *annotations; +}; + +#define XPT_MAGIC "XPCOM\nTypeLib\r\n\032" +/* For error messages. */ +#define XPT_MAGIC_STRING "XPCOM\\nTypeLib\\r\\n\\032" +#define XPT_MAJOR_VERSION 0x01 +#define XPT_MINOR_VERSION 0x02 + +/* Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION + * or higher is to be considered incompatible by this version of xpt and + * we will refuse to read it. We will return a header with magic, major and + * minor versions set from the file. num_interfaces and file_length will be + * set to zero to confirm our inability to read the file; i.e. even if some + * client of this library gets out of sync with us regarding the agreed upon + * value for XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces and + * file_length are both zero we *know* that this library refused to read the + * file due to version imcompatibility. + */ +#define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02 + +/* + * The "[-t version number]" cmd line parameter to the XPIDL compiler and XPT + * linker specifies the major and minor version number of the output + * type library. + * + * The goal is for the compiler to check that the input IDL file only uses + * constructs that are supported in the version specified. The linker will + * check that all typelib files it reads are of the version specified or + * below. + * + * Both the compiler and the linker will report errors and abort if these + * checks fail. + * + * When you rev up major or minor versions of the type library in the future, + * think about the new stuff that you added to the type library and add checks + * to make sure that occurrences of that new "stuff" will get caught when [-t + * version number] is used with the compiler. Here's what you'll probably + * have to do each time you rev up major/minor versions: + * + * 1) Add the current version number string (before your change) to the + * XPT_TYPELIB_VERSIONS list. + * + * 2) Do your changes add new features to XPIDL? Ensure that those new + * features are rejected by the XPIDL compiler when any version number in + * the XPT_TYPELIB_VERSIONS list is specified on the command line. The + * one place that currently does this kind of error checking is the function + * verify_type_fits_version() in xpidl_util.c. It currently checks + * attribute types, parameter types, and return types. You'll probably have + * to add to it or generalize it further based on what kind of changes you + * are making. + * + * 3) You will probably NOT need to make any changes to the error checking + * in the linker. + */ + +#define XPT_VERSION_UNKNOWN 0 +#define XPT_VERSION_UNSUPPORTED 1 +#define XPT_VERSION_OLD 2 +#define XPT_VERSION_CURRENT 3 + +typedef struct { + const char* str; + PRUint8 major; + PRUint8 minor; + PRUint16 code; +} XPT_TYPELIB_VERSIONS_STRUCT; + +/* Currently accepted list of versions for typelibs */ +#define XPT_TYPELIB_VERSIONS { \ + {"1.0", 1, 0, XPT_VERSION_UNSUPPORTED}, \ + {"1.1", 1, 1, XPT_VERSION_OLD}, \ + {"1.2", 1, 2, XPT_VERSION_CURRENT} \ +} + +extern XPT_PUBLIC_API(PRUint16) +XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor); + +extern XPT_PUBLIC_API(XPTHeader *) +XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces, + PRUint8 major_version, PRUint8 minor_version); + +extern XPT_PUBLIC_API(void) +XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader); + +/* size of header and annotations */ +extern XPT_PUBLIC_API(PRUint32) +XPT_SizeOfHeader(XPTHeader *header); + +/* size of header and annotations and InterfaceDirectoryEntries */ +extern XPT_PUBLIC_API(PRUint32) +XPT_SizeOfHeaderBlock(XPTHeader *header); + +/* + * A contiguous array of fixed-size InterfaceDirectoryEntry records begins at + * the byte offset identified by the interface_directory field in the file + * header. The array is used to quickly locate an interface description + * using its IID. No interface should appear more than once in the array. + */ +struct XPTInterfaceDirectoryEntry { + nsID iid; + char *name; + char *name_space; + XPTInterfaceDescriptor *interface_descriptor; + +#if 0 /* not yet */ + /* not stored on disk */ + PRUint32 offset; /* the offset for an ID still to be read */ +#endif +}; + +extern XPT_PUBLIC_API(PRBool) +XPT_FillInterfaceDirectoryEntry(XPTArena *arena, + XPTInterfaceDirectoryEntry *ide, + nsID *iid, char *name, char *name_space, + XPTInterfaceDescriptor *descriptor); + +extern XPT_PUBLIC_API(void) +XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena, + XPTInterfaceDirectoryEntry* ide); + +/* + * An InterfaceDescriptor is a variable-size record used to describe a + * single XPCOM interface, including all of its methods. + */ +struct XPTInterfaceDescriptor { + PRUint16 parent_interface; + PRUint16 num_methods; + XPTMethodDescriptor *method_descriptors; + PRUint16 num_constants; + XPTConstDescriptor *const_descriptors; + PRUint8 flags; + + /* additional_types are used for arrays where we may need multiple + * XPTTypeDescriptors for a single XPTMethodDescriptor. Since we still + * want to have a simple array of XPTMethodDescriptor (each with a single + * embedded XPTTypeDescriptor), a XPTTypeDescriptor can have a reference + * to an 'additional_type'. That reference is an index in this + * "additional_types" array. So a given XPTMethodDescriptor might have + * a whole chain of these XPTTypeDescriptors to represent, say, a multi + * dimensional array. + * + * Note that in the typelib file these additional types are stored 'inline' + * in the MethodDescriptor. But, in the typelib MethodDescriptors can be + * of varying sizes, where in XPT's in memory mapping of the data we want + * them to be of fixed size. This additional_types scheme is here to allow + * for that. + */ + + XPTTypeDescriptor *additional_types; + PRUint16 num_additional_types; +}; + +#define XPT_ID_SCRIPTABLE 0x80 +#define XPT_ID_FUNCTION 0x40 +#define XPT_ID_FLAGMASK 0xc0 +#define XPT_ID_TAGMASK (~XPT_ID_FLAGMASK) +#define XPT_ID_TAG(id) ((id).flags & XPT_ID_TAGMASK) + +#define XPT_ID_IS_SCRIPTABLE(flags) (flags & XPT_ID_SCRIPTABLE) +#define XPT_ID_IS_FUNCTION(flags) (flags & XPT_ID_FUNCTION) + +extern XPT_PUBLIC_API(PRBool) +XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block, + PRUint16 num_interfaces, char *name, + PRUint16 *indexp); + +extern XPT_PUBLIC_API(XPTInterfaceDescriptor *) +XPT_NewInterfaceDescriptor(XPTArena *arena, + PRUint16 parent_interface, PRUint16 num_methods, + PRUint16 num_constants, PRUint8 flags); + +extern XPT_PUBLIC_API(void) +XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id); + +extern XPT_PUBLIC_API(PRBool) +XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id, + PRUint16 num); + +extern XPT_PUBLIC_API(PRBool) +XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id, + PRUint16 num); + +extern XPT_PUBLIC_API(PRBool) +XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id, + PRUint16 num); + +/* + * This is our special string struct with a length value associated with it, + * which means that it can contains embedded NULs. + */ +struct XPTString { + PRUint16 length; + char *bytes; +}; + +extern XPT_PUBLIC_API(XPTString *) +XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes); + +extern XPT_PUBLIC_API(XPTString *) +XPT_NewStringZ(XPTArena *arena, char *bytes); + +/* + * A TypeDescriptor is a variable-size record used to identify the type of a + * method argument or return value. + * + * There are three types of TypeDescriptors: + * + * SimpleTypeDescriptor + * InterfaceTypeDescriptor + * InterfaceIsTypeDescriptor + * + * The tag field in the prefix indicates which of the variant TypeDescriptor + * records is being used, and hence the way any remaining fields should be + * parsed. Values from 0 to 17 refer to SimpleTypeDescriptors. The value 18 + * designates an InterfaceTypeDescriptor, while 19 represents an + * InterfaceIsTypeDescriptor. + */ + +/* why bother with a struct? - other code relies on this being a struct */ +struct XPTTypeDescriptorPrefix { + PRUint8 flags; +}; + +/* flag bits -- fur and jband were right, I was miserably wrong */ +#define XPT_TDP_POINTER 0x80 +#define XPT_TDP_UNIQUE_POINTER 0x40 +#define XPT_TDP_REFERENCE 0x20 +#define XPT_TDP_FLAGMASK 0xe0 +#define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK) +#define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK) + +#define XPT_TDP_IS_POINTER(flags) (flags & XPT_TDP_POINTER) +#define XPT_TDP_IS_UNIQUE_POINTER(flags) (flags & XPT_TDP_UNIQUE_POINTER) +#define XPT_TDP_IS_REFERENCE(flags) (flags & XPT_TDP_REFERENCE) + +/* + * The following enum maps mnemonic names to the different numeric values + * of XPTTypeDescriptor->tag. + */ +enum XPTTypeDescriptorTags { + TD_INT8 = 0, + TD_INT16 = 1, + TD_INT32 = 2, + TD_INT64 = 3, + TD_UINT8 = 4, + TD_UINT16 = 5, + TD_UINT32 = 6, + TD_UINT64 = 7, + TD_FLOAT = 8, + TD_DOUBLE = 9, + TD_BOOL = 10, + TD_CHAR = 11, + TD_WCHAR = 12, + TD_VOID = 13, + TD_PNSIID = 14, + TD_DOMSTRING = 15, + TD_PSTRING = 16, + TD_PWSTRING = 17, + TD_INTERFACE_TYPE = 18, + TD_INTERFACE_IS_TYPE = 19, + TD_ARRAY = 20, + TD_PSTRING_SIZE_IS = 21, + TD_PWSTRING_SIZE_IS = 22, + TD_UTF8STRING = 23, + TD_CSTRING = 24, + TD_ASTRING = 25 +}; + +struct XPTTypeDescriptor { + XPTTypeDescriptorPrefix prefix; + PRUint8 argnum; /* used for iid_is and size_is */ + PRUint8 argnum2; /* used for length_is */ + union { + PRUint16 iface; /* used for TD_INTERFACE_TYPE */ + PRUint16 additional_type; /* used for TD_ARRAY */ + } type; +}; + +#define XPT_COPY_TYPE(to, from) \ + (to).prefix.flags = (from).prefix.flags; \ + (to).argnum = (from).argnum; \ + (to).argnum2 = (from).argnum2; \ + (to).type.additional_type = (from).type.additional_type; + +/* + * A ConstDescriptor is a variable-size record that records the name and + * value of a scoped interface constant. + * + * The types of the method parameter are restricted to the following subset + * of TypeDescriptors: + * + * int8, uint8, int16, uint16, int32, uint32, + * int64, uint64, wchar_t, char, string + * + * The type (and thus the size) of the value record is determined by the + * contents of the associated TypeDescriptor record. For instance, if type + * corresponds to int16, then value is a two-byte record consisting of a + * 16-bit signed integer. For a ConstDescriptor type of string, the value + * record is of type String*, i.e. an offset within the data pool to a + * String record containing the constant string. + */ +union XPTConstValue { + PRInt8 i8; + PRUint8 ui8; + PRInt16 i16; + PRUint16 ui16; + PRInt32 i32; + PRUint32 ui32; + PRInt64 i64; + PRUint64 ui64; + float flt; + double dbl; + PRBool bul; + char ch; + PRUint16 wch; + nsID *iid; + XPTString *string; + char *str; + PRUint16 *wstr; +}; /* varies according to type */ + +struct XPTConstDescriptor { + char *name; + XPTTypeDescriptor type; + union XPTConstValue value; +}; + +/* + * A ParamDescriptor is a variable-size record used to describe either a + * single argument to a method or a method's result. + */ +struct XPTParamDescriptor { + PRUint8 flags; + XPTTypeDescriptor type; +}; + +/* flag bits -- jband and fur were right, and I was miserably wrong */ +#define XPT_PD_IN 0x80 +#define XPT_PD_OUT 0x40 +#define XPT_PD_RETVAL 0x20 +#define XPT_PD_SHARED 0x10 +#define XPT_PD_DIPPER 0x08 +#define XPT_PD_FLAGMASK 0xf8 + +#define XPT_PD_IS_IN(flags) (flags & XPT_PD_IN) +#define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT) +#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL) +#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED) +#define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER) + +/* this is bogus +#define XPT_PARAMDESCRIPTOR_SIZE (XPT_TYPEDESCRIPTOR_SIZE + 1) +*/ + +extern XPT_PUBLIC_API(PRBool) +XPT_FillParamDescriptor(XPTArena *arena, + XPTParamDescriptor *pd, PRUint8 flags, + XPTTypeDescriptor *type); + +/* + * A MethodDescriptor is a variable-size record used to describe a single + * interface method. + */ +struct XPTMethodDescriptor { + char *name; + XPTParamDescriptor *params; + XPTParamDescriptor *result; + PRUint8 flags; + PRUint8 num_args; +}; + +/* flag bits -- jband and fur were right, and I was miserably wrong */ +#define XPT_MD_GETTER 0x80 +#define XPT_MD_SETTER 0x40 +#define XPT_MD_NOTXPCOM 0x20 +#define XPT_MD_CTOR 0x10 +#define XPT_MD_HIDDEN 0x08 +#define XPT_MD_FLAGMASK 0xf8 + +#define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER) +#define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER) +#define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM) +#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR) +#define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN) + +extern XPT_PUBLIC_API(PRBool) +XPT_FillMethodDescriptor(XPTArena *arena, + XPTMethodDescriptor *meth, PRUint8 flags, char *name, + PRUint8 num_args); + +/* + * Annotation records are variable-size records used to store secondary + * information about the typelib, e.g. such as the name of the tool that + * generated the typelib file, the date it was generated, etc. The + * information is stored with very loose format requirements so as to + * allow virtually any private data to be stored in the typelib. + * + * There are two types of Annotations: + * + * EmptyAnnotation + * PrivateAnnotation + * + * The tag field of the prefix discriminates among the variant record + * types for Annotation's. If the tag is 0, this record is an + * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to + * indicate an array of Annotation's that's completely empty. If the tag + * is 1, the record is a PrivateAnnotation. + */ + +struct XPTAnnotation { + XPTAnnotation *next; + PRUint8 flags; + /* remaining fields are present in typelib iff XPT_ANN_IS_PRIVATE */ + XPTString *creator; + XPTString *private_data; +}; + +#define XPT_ANN_LAST 0x80 +#define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST) +#define XPT_ANN_PRIVATE 0x40 +#define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE) + +extern XPT_PUBLIC_API(XPTAnnotation *) +XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator, + XPTString *private_data); + +PR_END_EXTERN_C + +#endif /* __xpt_struct_h__ */ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h new file mode 100644 index 00000000..89d1c3f6 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h @@ -0,0 +1,240 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* + * Basic APIs for streaming typelib structures to/from disk. + */ + +#ifndef __xpt_xdr_h__ +#define __xpt_xdr_h__ + +#include "xpt_struct.h" + +#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP +#define XPT_Do8 VBoxNsxpXPT_Do8 +#define XPT_Do16 VBoxNsxpXPT_Do16 +#define XPT_Do32 VBoxNsxpXPT_Do32 +#define XPT_Do64 VBoxNsxpXPT_Do64 +#define XPT_DoIID VBoxNsxpXPT_DoIID +#define XPT_DoCString VBoxNsxpXPT_DoCString +#define XPT_DoString VBoxNsxpXPT_DoString +#define XPT_DoStringInline VBoxNsxpXPT_DoStringInline +#define XPT_NewXDRState VBoxNsxpXPT_NewXDRState +#define XPT_SetDataOffset VBoxNsxpXPT_SetDataOffset +#define XPT_SeekTo VBoxNsxpXPT_SeekTo +#define XPT_MakeCursor VBoxNsxpXPT_MakeCursor +#define XPT_DestroyXDRState VBoxNsxpXPT_DestroyXDRState +#define XPT_GetXDRData VBoxNsxpXPT_GetXDRData +#define XPT_GetXDRDataLength VBoxNsxpXPT_GetXDRDataLength +#define XPT_DoHeader VBoxNsxpXPT_DoHeader +#define XPT_DoHeaderPrologue VBoxNsxpXPT_DoHeaderPrologue +#define XPT_UpdateFileLength VBoxNsxpXPT_UpdateFileLength +#define XPT_DataOffset VBoxNsxpXPT_DataOffset +#define XPT_GetOffsetForAddr VBoxNsxpXPT_GetOffsetForAddr +#define XPT_SetOffsetForAddr VBoxNsxpXPT_SetOffsetForAddr +#define XPT_SetAddrForOffset VBoxNsxpXPT_SetAddrForOffset +#define XPT_GetAddrForOffset VBoxNsxpXPT_GetAddrForOffset +#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */ + +PR_BEGIN_EXTERN_C + +typedef struct XPTState XPTState; +typedef struct XPTDatapool XPTDatapool; +typedef struct XPTCursor XPTCursor; + +/* Opaque type, for internal use */ +typedef struct XPTHashTable XPTHashTable; + +extern XPT_PUBLIC_API(PRBool) +XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp); + +extern XPT_PUBLIC_API(PRBool) +XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp); + +extern XPT_PUBLIC_API(PRBool) +XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **strp); + +extern XPT_PUBLIC_API(PRBool) +XPT_DoIID(XPTCursor *cursor, nsID *iidp); + +extern XPT_PUBLIC_API(PRBool) +XPT_Do64(XPTCursor *cursor, PRInt64 *u64p); + +extern XPT_PUBLIC_API(PRBool) +XPT_Do32(XPTCursor *cursor, PRUint32 *u32p); + +extern XPT_PUBLIC_API(PRBool) +XPT_Do16(XPTCursor *cursor, PRUint16 *u16p); + +extern XPT_PUBLIC_API(PRBool) +XPT_Do8(XPTCursor *cursor, PRUint8 *u8p); + +extern XPT_PUBLIC_API(PRBool) +XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset); +extern XPT_PUBLIC_API(PRBool) +XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp); + +typedef enum { + XPT_ENCODE, + XPT_DECODE +} XPTMode; + +typedef enum { + XPT_HEADER = 0, + XPT_DATA = 1 +} XPTPool; + +struct XPTState { + XPTMode mode; + PRUint32 data_offset; + PRUint32 next_cursor[2]; + XPTDatapool *pool; + XPTArena *arena; +}; + +struct XPTDatapool { + XPTHashTable *offset_map; + char *data; + PRUint32 count; + PRUint32 allocated; +}; + +struct XPTCursor { + XPTState *state; + XPTPool pool; + PRUint32 offset; + PRUint8 bits; +}; + +extern XPT_PUBLIC_API(XPTState *) +XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len); + +extern XPT_PUBLIC_API(PRBool) +XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor); + +extern XPT_PUBLIC_API(PRBool) +XPT_SeekTo(XPTCursor *cursor, PRUint32 offset); + +extern XPT_PUBLIC_API(void) +XPT_DestroyXDRState(XPTState *state); + +/* Set file_length based on the data used in the state. (Only ENCODE.) */ +extern XPT_PUBLIC_API(PRBool) +XPT_UpdateFileLength(XPTState *state); + +/* returns the length of the specified data block */ +extern XPT_PUBLIC_API(void) +XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len); + +extern XPT_PUBLIC_API(void) +XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len); + +/* set or get the data offset for the state, depending on mode */ +extern XPT_PUBLIC_API(void) +XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp); + +extern XPT_PUBLIC_API(void) +XPT_SetDataOffset(XPTState *state, PRUint32 data_offset); + +extern XPT_PUBLIC_API(PRUint32) +XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr); + +extern XPT_PUBLIC_API(PRBool) +XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset); + +extern XPT_PUBLIC_API(PRBool) +XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr); + +extern XPT_PUBLIC_API(void *) +XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset); + +/* all data structures are big-endian */ + +#if defined IS_BIG_ENDIAN +# ifdef VBOX +# error "Misconfigured endian!" +# endif +# define XPT_SWAB32(x) x +# define XPT_SWAB16(x) x +#elif defined IS_LITTLE_ENDIAN +# define XPT_SWAB32(x) (((x) >> 24) | \ + (((x) >> 8) & 0xff00) | \ + (((x) << 8) & 0xff0000) | \ + ((x) << 24)) +# define XPT_SWAB16(x) (((x) >> 8) | ((x) << 8)) +#else +# error "unknown byte order" +#endif + +/* + * If we're decoding, we want to read the offset before we check + * for already-decoded values. + * + * Then we check for repetition: CheckForRepeat will see if we've already + * encoded/decoded this value, and if so will set offset/addr correctly + * and make already be true. If not, it will set up the cursor for + * encoding (reserve space) or decoding (seek to correct location) as + * appropriate. In the encode case, it will also set the addr->offset + * mapping. + */ + +#define XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \ + XPTMode mode = cursor->state->mode; \ + if (!(mode == XPT_ENCODE || XPT_Do32(cursor, &new_curs.offset)) || \ + !CheckForRepeat(cursor, (void **)addrp, pool, \ + mode == XPT_ENCODE ? size : 0u, &new_curs, \ + &already) || \ + !(mode == XPT_DECODE || XPT_Do32(cursor, &new_curs.offset))) \ + return PR_FALSE; \ + if (already) \ + return PR_TRUE; \ + +#define XPT_PREAMBLE_NO_ALLOC(cursor, addrp, pool, size, new_curs, already) \ + { \ + XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \ + } + +#define XPT_ERROR_HANDLE(arena, free_it) \ + error: \ + if (cursor->state->mode == XPT_DECODE) \ + XPT_FREEIF(arena, free_it); \ + return PR_FALSE; + + +PR_END_EXTERN_C + +#endif /* __xpt_xdr_h__ */ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in new file mode 100644 index 00000000..e0578556 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in @@ -0,0 +1,76 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +LIBRARY_NAME = xpt +LIB_IS_C_ONLY = 1 +ifdef CROSS_COMPILE +HOST_LIBRARY_NAME = hostxpt +endif + +CSRCS = xpt_arena.c xpt_struct.c xpt_xdr.c +HOST_CSRCS = $(CSRCS) + +# we don't want the shared lib, but we want to force the creation of a static lib. +FORCE_STATIC_LIB = 1 + +# Force use of PIC +FORCE_USE_PIC = 1 + +include $(topsrcdir)/config/rules.mk + +DEFINES += -DEXPORT_XPT_API +HOST_CFLAGS += -DEXPORT_XPT_API + +# Build libxpt early so that it'll be available to xpidl, which also +# must be built early. +export:: + @$(MAKE) libs + +ifdef CROSS_COMPILE +ifdef HOST_NSPR_MDCPUCFG +HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG) +endif +endif + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c new file mode 100644 index 00000000..a0813b8f --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c @@ -0,0 +1,358 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* Quick arena hack for xpt. */ + +/* XXX This exists because we don't want to drag in NSPR. It *seemed* +* to make more sense to write a quick and dirty arena than to clone +* plarena (like js/src did). This is not optimal, but it works. +* Half of the code here is instrumentation. +*/ + +#include "xpt_arena.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef VBOX_USE_IPRT_IN_XPCOM +# include <iprt/mem.h> +#endif + + +/*************************/ +/* logging stats support */ + +#if 0 && defined(DEBUG_jband) +#define XPT_ARENA_LOGGING 1 +#endif + +#ifdef XPT_ARENA_LOGGING + +#define LOG_MALLOC(_a, _req, _used) \ + do{ \ + XPT_ASSERT((_a)); \ + ++(_a)->LOG_MallocCallCount; \ + (_a)->LOG_MallocTotalBytesRequested += (_req); \ + (_a)->LOG_MallocTotalBytesUsed += (_used); \ + } while(0) + +#define LOG_REAL_MALLOC(_a, _size) \ + do{ \ + XPT_ASSERT((_a)); \ + ++(_a)->LOG_RealMallocCallCount; \ + (_a)->LOG_RealMallocTotalBytesRequested += (_size); \ + } while(0) + +#define LOG_FREE(_a) \ + do{ \ + XPT_ASSERT((_a)); \ + ++(_a)->LOG_FreeCallCount; \ + } while(0) + +#define LOG_DONE_LOADING(_a) \ + do{ \ + XPT_ASSERT((_a)); \ + (_a)->LOG_LoadingFreeCallCount = (_a)->LOG_FreeCallCount; \ + } while(0) + +#define PRINT_STATS(_a) xpt_DebugPrintArenaStats((_a)) +static void xpt_DebugPrintArenaStats(XPTArena *arena); + +#else /* !XPT_ARENA_LOGGING */ + +#define LOG_MALLOC(_a, _req, _used) ((void)0) +#define LOG_REAL_MALLOC(_a, _size) ((void)0) +#define LOG_FREE(_a) ((void)0) + +#define LOG_DONE_LOADING(_a) ((void)0) +#define PRINT_STATS(_a) ((void)0) + +#endif /* XPT_ARENA_LOGGING */ + +/****************************************************/ + +/* Block header for each block in the arena */ +typedef struct BLK_HDR BLK_HDR; +struct BLK_HDR +{ + BLK_HDR *next; + size_t size; +}; + +#define XPT_MIN_BLOCK_SIZE 32 + +/* XXX this is lame. Should clone the code to do this bitwise */ +#define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a))) + +struct XPTArena +{ + BLK_HDR *first; + PRUint8 *next; + size_t space; + size_t alignment; + size_t block_size; + char *name; + +#ifdef XPT_ARENA_LOGGING + PRUint32 LOG_MallocCallCount; + PRUint32 LOG_MallocTotalBytesRequested; + PRUint32 LOG_MallocTotalBytesUsed; + PRUint32 LOG_FreeCallCount; + PRUint32 LOG_LoadingFreeCallCount; + PRUint32 LOG_RealMallocCallCount; + PRUint32 LOG_RealMallocTotalBytesRequested; +#endif /* XPT_ARENA_LOGGING */ +}; + +XPT_PUBLIC_API(XPTArena *) +XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name) +{ +#ifdef VBOX_USE_IPRT_IN_XPCOM + XPTArena *arena = RTMemAllocZ(sizeof(XPTArena)); +#else + XPTArena *arena = calloc(1, sizeof(XPTArena)); +#endif + if (arena) { + XPT_ASSERT(alignment); + if (alignment > sizeof(double)) + alignment = sizeof(double); + arena->alignment = alignment; + + if (block_size < XPT_MIN_BLOCK_SIZE) + block_size = XPT_MIN_BLOCK_SIZE; + arena->block_size = ALIGN_RND(block_size, alignment); + + /* must have room for at least one item! */ + XPT_ASSERT(arena->block_size >= + ALIGN_RND(sizeof(BLK_HDR), alignment) + + ALIGN_RND(1, alignment)); + + if (name) { + arena->name = XPT_STRDUP(arena, name); +#ifdef XPT_ARENA_LOGGING + /* fudge the stats since we are using space in the arena */ + arena->LOG_MallocCallCount = 0; + arena->LOG_MallocTotalBytesRequested = 0; + arena->LOG_MallocTotalBytesUsed = 0; +#endif /* XPT_ARENA_LOGGING */ + } + } + return arena; +} + +XPT_PUBLIC_API(void) +XPT_DestroyArena(XPTArena *arena) +{ + BLK_HDR* cur; + BLK_HDR* next; + + cur = arena->first; + while (cur) { + next = cur->next; +#ifdef VBOX_USE_IPRT_IN_XPCOM + RTMemFree(cur); +#else + free(cur); +#endif + cur = next; + } +#ifdef VBOX_USE_IPRT_IN_XPCOM + RTMemFree(arena); +#else + free(arena); +#endif +} + +XPT_PUBLIC_API(void) +XPT_DumpStats(XPTArena *arena) +{ + PRINT_STATS(arena); +} + + +/* +* Our alignment rule is that we always round up the size of each allocation +* so that the 'arena->next' pointer one will point to properly aligned space. +*/ + +XPT_PUBLIC_API(void *) +XPT_ArenaMalloc(XPTArena *arena, size_t size) +{ + PRUint8 *cur; + size_t bytes; + + if (!size) + return NULL; + + if (!arena) { + XPT_ASSERT(0); + return NULL; + } + + bytes = ALIGN_RND(size, arena->alignment); + + LOG_MALLOC(arena, size, bytes); + + if (bytes > arena->space) { + BLK_HDR* new_block; + size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment); + size_t new_space = arena->block_size; + + if (bytes > new_space - block_header_size) + new_space += bytes; + +#ifdef VBOX_USE_IPRT_IN_XPCOM + new_block = (BLK_HDR*) RTMemAllocZ(new_space/arena->alignment * (size_t)arena->alignment); +#else + new_block = (BLK_HDR*) calloc(new_space/arena->alignment, + arena->alignment); +#endif + if (!new_block) { + arena->next = NULL; + arena->space = 0; + return NULL; + } + + LOG_REAL_MALLOC(arena, new_space); + + /* link block into the list of blocks for use when we destroy */ + new_block->next = arena->first; + arena->first = new_block; + + /* save other block header info */ + new_block->size = new_space; + + /* set info for current block */ + arena->next = ((PRUint8*)new_block) + block_header_size; + arena->space = new_space - block_header_size; + +#ifdef DEBUG + /* mark block for corruption check */ + memset(arena->next, 0xcd, arena->space); +#endif + } + +#ifdef DEBUG + { + /* do corruption check */ + size_t i; + for (i = 0; i < bytes; ++i) { + XPT_ASSERT(arena->next[i] == 0xcd); + } + /* we guarantee that the block will be filled with zeros */ + memset(arena->next, 0, bytes); + } +#endif + + cur = arena->next; + arena->next += bytes; + arena->space -= bytes; + + return cur; +} + + +XPT_PUBLIC_API(char *) +XPT_ArenaStrDup(XPTArena *arena, const char * s) +{ + size_t len; + char* cur; + + if (!s) + return NULL; + + len = strlen(s)+1; + cur = XPT_ArenaMalloc(arena, len); + memcpy(cur, s, len); + return cur; +} + +XPT_PUBLIC_API(void) +XPT_NotifyDoneLoading(XPTArena *arena) +{ +#ifdef XPT_ARENA_LOGGING + if (arena) { + LOG_DONE_LOADING(arena); + } +#endif +} + +XPT_PUBLIC_API(void) +XPT_ArenaFree(XPTArena *arena, void *block) +{ + LOG_FREE(arena); +} + +#ifdef XPT_ARENA_LOGGING +static void xpt_DebugPrintArenaStats(XPTArena *arena) +{ + printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n"); + printf("Start xpt arena stats for \"%s\"\n", + arena->name ? arena->name : "unnamed arena"); + printf("\n"); + printf("%d times arena malloc called\n", (int) arena->LOG_MallocCallCount); + printf("%d total bytes requested from arena malloc\n", (int) arena->LOG_MallocTotalBytesRequested); + printf("%d average bytes requested per call to arena malloc\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0); + printf("%d average bytes used per call (accounts for alignment overhead)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0); + printf("%d average bytes used per call (accounts for all overhead and waste)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_RealMallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0); + printf("\n"); + printf("%d during loading times arena free called\n", (int) arena->LOG_LoadingFreeCallCount); + printf("%d during loading approx total bytes not freed\n", (int) arena->LOG_LoadingFreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0)); + printf("\n"); + printf("%d total times arena free called\n", (int) arena->LOG_FreeCallCount); + printf("%d approx total bytes not freed until arena destruction\n", (int) arena->LOG_FreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0 )); + printf("\n"); + printf("%d times arena called system malloc\n", (int) arena->LOG_RealMallocCallCount); + printf("%d total bytes arena requested from system\n", (int) arena->LOG_RealMallocTotalBytesRequested); + printf("%d byte block size specified at arena creation time\n", (int) arena->block_size); + printf("%d byte block alignment specified at arena creation time\n", (int) arena->alignment); + printf("\n"); + printf("End xpt arena stats\n"); + printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n"); +} +#endif + +/***************************************************************************/ + +#ifdef DEBUG +XPT_PUBLIC_API(void) +XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno) +{ + fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", + s, file, lineno); + abort(); +} +#endif diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c new file mode 100644 index 00000000..93435910 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c @@ -0,0 +1,956 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* Implementation of XDR routines for typelib structures. */ + +#include "xpt_xdr.h" +#include "xpt_struct.h" +#include <string.h> +#include <stdio.h> + +/***************************************************************************/ +/* Forward declarations. */ + +static PRUint32 +SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id); + +static PRUint32 +SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id); + +static PRUint32 +SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id); + +static PRUint32 +SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id); + +static PRBool +DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor, + XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index); + +static PRBool +DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd, + XPTInterfaceDescriptor *id); + +static PRBool +DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md, + XPTInterfaceDescriptor *id); + +static PRBool +DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp); + +static PRBool +DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp); + +static PRBool +DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp); + +static PRBool +DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td, + XPTInterfaceDescriptor *id); + +static PRBool +DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd, + XPTInterfaceDescriptor *id); + +/***************************************************************************/ + +XPT_PUBLIC_API(PRUint32) +XPT_SizeOfHeader(XPTHeader *header) +{ + XPTAnnotation *ann, *last; + PRUint32 size = 16 /* magic */ + + 1 /* major */ + 1 /* minor */ + + 2 /* num_interfaces */ + 4 /* file_length */ + + 4 /* interface_directory */ + 4 /* data_pool */; + + ann = header->annotations; + do { + size += 1; /* Annotation prefix */ + if (XPT_ANN_IS_PRIVATE(ann->flags)) + size += 2 + ann->creator->length + 2 + ann->private_data->length; + last = ann; + ann = ann->next; + } while (!XPT_ANN_IS_LAST(last->flags)); + + return size; +} + +XPT_PUBLIC_API(PRUint32) +XPT_SizeOfHeaderBlock(XPTHeader *header) +{ + PRUint32 size = XPT_SizeOfHeader(header); + + size += header->num_interfaces * sizeof (XPTInterfaceDirectoryEntry); + + return size; +} + +XPT_PUBLIC_API(XPTHeader *) +XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces, PRUint8 major_version, PRUint8 minor_version) +{ + XPTHeader *header = XPT_NEWZAP(arena, XPTHeader); + if (!header) + return NULL; + memcpy(header->magic, XPT_MAGIC, 16); + header->major_version = major_version; + header->minor_version = minor_version; + header->num_interfaces = num_interfaces; + if (num_interfaces) { + header->interface_directory = + XPT_CALLOC(arena, + num_interfaces * sizeof(XPTInterfaceDirectoryEntry)); + if (!header->interface_directory) { + XPT_DELETE(arena, header); + return NULL; + } + } + header->data_pool = 0; /* XXX do we even need this struct any more? */ + + return header; +} + +XPT_PUBLIC_API(void) +XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader) +{ + if (aHeader) { + XPTAnnotation* ann; + XPTInterfaceDirectoryEntry* entry = aHeader->interface_directory; + XPTInterfaceDirectoryEntry* end = entry + aHeader->num_interfaces; + for (; entry < end; entry++) { + XPT_DestroyInterfaceDirectoryEntry(arena, entry); + } + + ann = aHeader->annotations; + while (ann) { + XPTAnnotation* next = ann->next; + if (XPT_ANN_IS_PRIVATE(ann->flags)) { + XPT_FREEIF(arena, ann->creator); + XPT_FREEIF(arena, ann->private_data); + } + XPT_DELETE(arena, ann); + ann = next; + } + + XPT_FREEIF(arena, aHeader->interface_directory); + XPT_DELETE(arena, aHeader); + } +} + +XPT_PUBLIC_API(PRBool) +XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset) +{ + XPTMode mode = cursor->state->mode; + unsigned int i; + XPTHeader * header; + + if (mode == XPT_DECODE) { + header = XPT_NEWZAP(arena, XPTHeader); + if (!header) + return PR_FALSE; + *headerp = header; + } else { + header = *headerp; + } + + if (mode == XPT_ENCODE) { + /* IDEs appear after header, including annotations */ + if (ide_offset != NULL) + { + *ide_offset = XPT_SizeOfHeader(*headerp) + 1; /* one-based offset */ + } + header->data_pool = XPT_SizeOfHeaderBlock(*headerp); + XPT_SetDataOffset(cursor->state, header->data_pool); + } + + for (i = 0; i < sizeof(header->magic); i++) { + if (!XPT_Do8(cursor, &header->magic[i])) + goto error; + } + + if (mode == XPT_DECODE && + strncmp((const char*)header->magic, XPT_MAGIC, 16) != 0) + { + /* Require that the header contain the proper magic */ + fprintf(stderr, + "libxpt: bad magic header in input file; " + "found '%s', expected '%s'\n", + header->magic, XPT_MAGIC_STRING); + goto error; + } + + if (!XPT_Do8(cursor, &header->major_version) || + !XPT_Do8(cursor, &header->minor_version)) { + goto error; + } + + if (mode == XPT_DECODE && + header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) { + /* This file is newer than we are and set to an incompatible version + * number. We must set the header state thusly and return. + */ + header->num_interfaces = 0; + header->file_length = 0; + return PR_TRUE; + } + + if (!XPT_Do16(cursor, &header->num_interfaces) || + !XPT_Do32(cursor, &header->file_length) || + (ide_offset != NULL && !XPT_Do32(cursor, ide_offset))) { + goto error; + } + return PR_TRUE; + /* XXX need to free child data sometimes! */ + XPT_ERROR_HANDLE(arena, header); +} + +XPT_PUBLIC_API(PRBool) +XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp) +{ + const int HEADER_SIZE = 24; + XPTMode mode = cursor->state->mode; + XPTHeader * header; + PRUint32 ide_offset; + int i; + XPTAnnotation *ann, *next, **annp; + + if (!XPT_DoHeaderPrologue(arena, cursor, headerp, &ide_offset)) + return PR_FALSE; + header = *headerp; + /* + * Make sure the file length reported in the header is the same size as + * as our buffer unless it is zero (not set) + */ + if (mode == XPT_DECODE && (header->file_length != 0 && + cursor->state->pool->allocated < header->file_length)) { + fputs("libxpt: File length in header does not match actual length. File may be corrupt\n", + stderr); + goto error; + } + + if (mode == XPT_ENCODE) + XPT_DataOffset(cursor->state, &header->data_pool); + if (!XPT_Do32(cursor, &header->data_pool)) + goto error; + if (mode == XPT_DECODE) + XPT_DataOffset(cursor->state, &header->data_pool); + + if (mode == XPT_DECODE && header->num_interfaces) { + header->interface_directory = + XPT_CALLOC(arena, header->num_interfaces * + sizeof(XPTInterfaceDirectoryEntry)); + if (!header->interface_directory) + goto error; + } + + /* + * Iterate through the annotations rather than recurring, to avoid blowing + * the stack on large xpt files. + */ + ann = next = header->annotations; + annp = &header->annotations; + do { + ann = next; + if (!DoAnnotation(arena, cursor, &ann)) + goto error; + if (mode == XPT_DECODE) { + /* + * Make sure that we store the address of the newly allocated + * annotation in the previous annotation's ``next'' slot, or + * header->annotations for the first one. + */ + *annp = ann; + annp = &ann->next; + } + next = ann->next; + } while (!XPT_ANN_IS_LAST(ann->flags)); + + /* shouldn't be necessary now, but maybe later */ + XPT_SeekTo(cursor, ide_offset); + + for (i = 0; i < header->num_interfaces; i++) { + if (!DoInterfaceDirectoryEntry(arena, cursor, + &header->interface_directory[i], + (PRUint16)(i + 1))) + goto error; + } + + return PR_TRUE; + + /* XXX need to free child data sometimes! */ + XPT_ERROR_HANDLE(arena, header); +} + +XPT_PUBLIC_API(PRBool) +XPT_FillInterfaceDirectoryEntry(XPTArena *arena, + XPTInterfaceDirectoryEntry *ide, + nsID *iid, char *name, char *name_space, + XPTInterfaceDescriptor *descriptor) +{ + XPT_COPY_IID(ide->iid, *iid); + ide->name = name ? XPT_STRDUP(arena, name) : NULL; /* what good is it w/o a name? */ + ide->name_space = name_space ? XPT_STRDUP(arena, name_space) : NULL; + ide->interface_descriptor = descriptor; + return PR_TRUE; +} + +XPT_PUBLIC_API(void) +XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena, + XPTInterfaceDirectoryEntry* ide) +{ + if (ide) { + if (ide->name) XPT_FREE(arena, ide->name); + if (ide->name_space) XPT_FREE(arena, ide->name_space); + XPT_FreeInterfaceDescriptor(arena, ide->interface_descriptor); + } +} + +/* InterfaceDirectoryEntry records go in the header */ +PRBool +DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor, + XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index) +{ + XPTMode mode = cursor->state->mode; + + /* write the IID in our cursor space */ + if (!XPT_DoIID(cursor, &(ide->iid)) || + + /* write the name string in the data pool, and the offset in our + cursor space */ + !XPT_DoCString(arena, cursor, &(ide->name)) || + + /* write the name_space string in the data pool, and the offset in our + cursor space */ + !XPT_DoCString(arena, cursor, &(ide->name_space)) || + + /* do InterfaceDescriptors -- later, only on encode (see below) */ + !DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) { + goto error; + } + + if (mode == XPT_DECODE) + XPT_SetOffsetForAddr(cursor, ide, entry_index); + + return PR_TRUE; + + XPT_ERROR_HANDLE(arena, ide); +} + +XPT_PUBLIC_API(XPTInterfaceDescriptor *) +XPT_NewInterfaceDescriptor(XPTArena *arena, + PRUint16 parent_interface, PRUint16 num_methods, + PRUint16 num_constants, PRUint8 flags) +{ + + XPTInterfaceDescriptor *id = XPT_NEWZAP(arena, XPTInterfaceDescriptor); + if (!id) + return NULL; + + if (num_methods) { + id->method_descriptors = XPT_CALLOC(arena, num_methods * + sizeof(XPTMethodDescriptor)); + if (!id->method_descriptors) + goto free_id; + id->num_methods = num_methods; + } + + if (num_constants) { + id->const_descriptors = XPT_CALLOC(arena, num_constants * + sizeof(XPTConstDescriptor)); + if (!id->const_descriptors) + goto free_meth; + id->num_constants = num_constants; + } + + if (parent_interface) { + id->parent_interface = parent_interface; + } else { + id->parent_interface = 0; + } + + id->flags = flags; + + return id; + + free_meth: + XPT_FREEIF(arena, id->method_descriptors); + free_id: + XPT_DELETE(arena, id); + return NULL; +} + +XPT_PUBLIC_API(void) +XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id) +{ + if (id) { + XPTMethodDescriptor *md, *mdend; + XPTConstDescriptor *cd, *cdend; + + /* Free up method descriptors */ + md = id->method_descriptors; + mdend = md + id->num_methods; + for (; md < mdend; md++) { + XPT_FREEIF(arena, md->name); + XPT_FREEIF(arena, md->params); + XPT_FREEIF(arena, md->result); + } + XPT_FREEIF(arena, id->method_descriptors); + + /* Free up const descriptors */ + cd = id->const_descriptors; + cdend = cd + id->num_constants; + for (; cd < cdend; cd++) { + XPT_FREEIF(arena, cd->name); + } + XPT_FREEIF(arena, id->const_descriptors); + + /* Free up type descriptors */ + XPT_FREEIF(arena, id->additional_types); + + XPT_DELETE(arena, id); + } +} + +XPT_PUBLIC_API(PRBool) +XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id, + PRUint16 num) +{ + XPTTypeDescriptor *old = id->additional_types; + XPTTypeDescriptor *new; + size_t old_size = id->num_additional_types * sizeof(XPTTypeDescriptor); + size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size; + + /* XXX should grow in chunks to minimize alloc overhead */ + new = XPT_CALLOC(arena, new_size); + if (!new) + return PR_FALSE; + if (old) { + if (old_size) + memcpy(new, old, old_size); + XPT_FREE(arena, old); + } + id->additional_types = new; + id->num_additional_types += num; + return PR_TRUE; +} + +XPT_PUBLIC_API(PRBool) +XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id, + PRUint16 num) +{ + XPTMethodDescriptor *old = id->method_descriptors; + XPTMethodDescriptor *new; + size_t old_size = id->num_methods * sizeof(XPTMethodDescriptor); + size_t new_size = (num * sizeof(XPTMethodDescriptor)) + old_size; + + /* XXX should grow in chunks to minimize alloc overhead */ + new = XPT_CALLOC(arena, new_size); + if (!new) + return PR_FALSE; + if (old) { + if (old_size) + memcpy(new, old, old_size); + XPT_FREE(arena, old); + } + id->method_descriptors = new; + id->num_methods += num; + return PR_TRUE; +} + +XPT_PUBLIC_API(PRBool) +XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id, + PRUint16 num) +{ + XPTConstDescriptor *old = id->const_descriptors; + XPTConstDescriptor *new; + size_t old_size = id->num_constants * sizeof(XPTConstDescriptor); + size_t new_size = (num * sizeof(XPTConstDescriptor)) + old_size; + + /* XXX should grow in chunks to minimize alloc overhead */ + new = XPT_CALLOC(arena, new_size); + if (!new) + return PR_FALSE; + if (old) { + if (old_size) + memcpy(new, old, old_size); + XPT_FREE(arena, old); + } + id->const_descriptors = new; + id->num_constants += num; + return PR_TRUE; +} + +PRUint32 +SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id) +{ + PRUint32 size = 1; /* prefix */ + + switch (XPT_TDP_TAG(td->prefix)) { + case TD_INTERFACE_TYPE: + size += 2; /* interface_index */ + break; + case TD_INTERFACE_IS_TYPE: + size += 1; /* argnum */ + break; + case TD_ARRAY: + size += 2 + SizeOfTypeDescriptor( + &id->additional_types[td->type.additional_type], id); + break; + case TD_PSTRING_SIZE_IS: + size += 2; /* argnum + argnum2 */ + break; + case TD_PWSTRING_SIZE_IS: + size += 2; /* argnum + argnum2 */ + break; + default: + /* nothing special */ + break; + } + return size; +} + +PRUint32 +SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id) +{ + PRUint32 i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */; + + for (i = 0; i < md->num_args; i++) + size += 1 + SizeOfTypeDescriptor(&md->params[i].type, id); + + size += 1 + SizeOfTypeDescriptor(&md->result->type, id); + return size; +} + +PRUint32 +SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id) +{ + PRUint32 size = 4 /* name */ + SizeOfTypeDescriptor(&cd->type, id); + + switch (XPT_TDP_TAG(cd->type.prefix)) { + case TD_INT8: + case TD_UINT8: + case TD_CHAR: + size ++; + break; + case TD_INT16: + case TD_UINT16: + case TD_WCHAR: + size += 2; + break; + case TD_INT32: + case TD_UINT32: + case TD_PSTRING: + size += 4; + break; + case TD_INT64: + case TD_UINT64: + size += 8; + break; + default: + fprintf(stderr, "libxpt: illegal type in ConstDescriptor: 0x%02x\n", + XPT_TDP_TAG(cd->type.prefix)); + return 0; + } + + return size; +} + +PRUint32 +SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id) +{ + PRUint32 size = 2 /* parent interface */ + 2 /* num_methods */ + + 2 /* num_constants */ + 1 /* flags */, i; + for (i = 0; i < id->num_methods; i++) + size += SizeOfMethodDescriptor(&id->method_descriptors[i], id); + for (i = 0; i < id->num_constants; i++) + size += SizeOfConstDescriptor(&id->const_descriptors[i], id); + return size; +} + +PRBool +DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, + XPTInterfaceDescriptor **idp) +{ + XPTMode mode = outer->state->mode; + XPTInterfaceDescriptor *id; + XPTCursor curs, *cursor = &curs; + PRUint32 i, id_sz = 0; + + if (mode == XPT_DECODE) { + id = XPT_NEWZAP(arena, XPTInterfaceDescriptor); + if (!id) + return PR_FALSE; + *idp = id; + } else { + id = *idp; + if (!id) { + id_sz = 0; + return XPT_Do32(outer, &id_sz); + } + id_sz = SizeOfInterfaceDescriptor(id); + } + + if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor)) + goto error; + + if (!XPT_Do32(outer, &cursor->offset)) + goto error; + if (mode == XPT_DECODE && !cursor->offset) { + XPT_DELETE(arena, *idp); + return PR_TRUE; + } + if(!XPT_Do16(cursor, &id->parent_interface) || + !XPT_Do16(cursor, &id->num_methods)) { + goto error; + } + + if (mode == XPT_DECODE && id->num_methods) { + id->method_descriptors = XPT_CALLOC(arena, id->num_methods * + sizeof(XPTMethodDescriptor)); + if (!id->method_descriptors) + goto error; + } + + for (i = 0; i < id->num_methods; i++) { + if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id)) + goto error; + } + + if (!XPT_Do16(cursor, &id->num_constants)) { + goto error; + } + + if (mode == XPT_DECODE && id->num_constants) { + id->const_descriptors = XPT_CALLOC(arena, id->num_constants * + sizeof(XPTConstDescriptor)); + if (!id->const_descriptors) + goto error; + } + + for (i = 0; i < id->num_constants; i++) { + if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) { + goto error; + } + } + + if (!XPT_Do8(cursor, &id->flags)) { + goto error; + } + + return PR_TRUE; + + XPT_ERROR_HANDLE(arena, id); +} + +PRBool +DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd, + XPTInterfaceDescriptor *id) +{ + PRBool ok = PR_FALSE; + + if (!XPT_DoCString(arena, cursor, &cd->name) || + !DoTypeDescriptor(arena, cursor, &cd->type, id)) { + + return PR_FALSE; + } + + switch(XPT_TDP_TAG(cd->type.prefix)) { + case TD_INT8: + ok = XPT_Do8(cursor, (PRUint8*) &cd->value.i8); + break; + case TD_INT16: + ok = XPT_Do16(cursor, (PRUint16*) &cd->value.i16); + break; + case TD_INT32: + ok = XPT_Do32(cursor, (PRUint32*) &cd->value.i32); + break; + case TD_INT64: + ok = XPT_Do64(cursor, &cd->value.i64); + break; + case TD_UINT8: + ok = XPT_Do8(cursor, &cd->value.ui8); + break; + case TD_UINT16: + ok = XPT_Do16(cursor, &cd->value.ui16); + break; + case TD_UINT32: + ok = XPT_Do32(cursor, &cd->value.ui32); + break; + case TD_UINT64: + ok = XPT_Do64(cursor, (PRInt64 *)&cd->value.ui64); + break; + case TD_CHAR: + ok = XPT_Do8(cursor, (PRUint8*) &cd->value.ch); + break; + case TD_WCHAR: + ok = XPT_Do16(cursor, &cd->value.wch); + break; + /* fall-through */ + default: + fprintf(stderr, "illegal type!\n"); + break; + } + + return ok; + +} + +XPT_PUBLIC_API(PRBool) +XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth, + PRUint8 flags, char *name, PRUint8 num_args) +{ + meth->flags = flags & XPT_MD_FLAGMASK; + meth->name = XPT_STRDUP(arena, name); + if (!meth->name) + return PR_FALSE; + meth->num_args = num_args; + if (num_args) { + meth->params = XPT_CALLOC(arena, num_args * sizeof(XPTParamDescriptor)); + if (!meth->params) + goto free_name; + } else { + meth->params = NULL; + } + meth->result = XPT_NEWZAP(arena, XPTParamDescriptor); + if (!meth->result) + goto free_params; + return PR_TRUE; + + free_params: + XPT_DELETE(arena, meth->params); + free_name: + XPT_DELETE(arena, meth->name); + return PR_FALSE; +} + +PRBool +DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md, + XPTInterfaceDescriptor *id) +{ + XPTMode mode = cursor->state->mode; + int i; + + if (!XPT_Do8(cursor, &md->flags) || + !XPT_DoCString(arena, cursor, &md->name) || + !XPT_Do8(cursor, &md->num_args)) + return PR_FALSE; + + if (mode == XPT_DECODE && md->num_args) { + md->params = XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor)); + if (!md->params) + return PR_FALSE; + } + + for(i = 0; i < md->num_args; i++) { + if (!DoParamDescriptor(arena, cursor, &md->params[i], id)) + goto error; + } + + if (mode == XPT_DECODE) { + md->result = XPT_NEWZAP(arena, XPTParamDescriptor); + if (!md->result) + return PR_FALSE; + } + + if (!md->result || + !DoParamDescriptor(arena, cursor, md->result, id)) + goto error; + + return PR_TRUE; + + XPT_ERROR_HANDLE(arena, md->params); +} + +XPT_PUBLIC_API(PRBool) +XPT_FillParamDescriptor(XPTArena *arena, XPTParamDescriptor *pd, PRUint8 flags, + XPTTypeDescriptor *type) +{ + pd->flags = flags & XPT_PD_FLAGMASK; + XPT_COPY_TYPE(pd->type, *type); + return PR_TRUE; +} + +PRBool +DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd, + XPTInterfaceDescriptor *id) +{ + if (!XPT_Do8(cursor, &pd->flags) || + !DoTypeDescriptor(arena, cursor, &pd->type, id)) + return PR_FALSE; + + return PR_TRUE; +} + +PRBool +DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp) +{ + return XPT_Do8(cursor, &tdp->flags); +} + +PRBool +DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td, + XPTInterfaceDescriptor *id) +{ + if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) { + goto error; + } + + switch (XPT_TDP_TAG(td->prefix)) { + case TD_INTERFACE_TYPE: + if (!XPT_Do16(cursor, &td->type.iface)) + goto error; + break; + case TD_INTERFACE_IS_TYPE: + if (!XPT_Do8(cursor, &td->argnum)) + goto error; + break; + case TD_ARRAY: + if (!XPT_Do8(cursor, &td->argnum) || + !XPT_Do8(cursor, &td->argnum2)) + goto error; + + if (cursor->state->mode == XPT_DECODE) { + if(!XPT_InterfaceDescriptorAddTypes(arena, id, 1)) + goto error; + td->type.additional_type = id->num_additional_types - 1; + } + + if (!DoTypeDescriptor(arena, cursor, + &id->additional_types[td->type.additional_type], + id)) + goto error; + break; + case TD_PSTRING_SIZE_IS: + case TD_PWSTRING_SIZE_IS: + if (!XPT_Do8(cursor, &td->argnum) || + !XPT_Do8(cursor, &td->argnum2)) + goto error; + break; + + default: + /* nothing special */ + break; + } + return PR_TRUE; + + XPT_ERROR_HANDLE(arena, td); +} + +XPT_PUBLIC_API(XPTAnnotation *) +XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator, + XPTString *private_data) +{ + XPTAnnotation *ann = XPT_NEWZAP(arena, XPTAnnotation); + if (!ann) + return NULL; + ann->flags = flags; + if (XPT_ANN_IS_PRIVATE(flags)) { + ann->creator = creator; + ann->private_data = private_data; + } + return ann; +} + +PRBool +DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp) +{ + XPTMode mode = cursor->state->mode; + XPTAnnotation *ann; + + if (mode == XPT_DECODE) { + ann = XPT_NEWZAP(arena, XPTAnnotation); + if (!ann) + return PR_FALSE; + *annp = ann; + } else { + ann = *annp; + } + + if (!XPT_Do8(cursor, &ann->flags)) + goto error; + + if (XPT_ANN_IS_PRIVATE(ann->flags)) { + if (!XPT_DoStringInline(arena, cursor, &ann->creator) || + !XPT_DoStringInline(arena, cursor, &ann->private_data)) + goto error_2; + } + + return PR_TRUE; + + error_2: + if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) { + XPT_FREEIF(arena, ann->creator); + XPT_FREEIF(arena, ann->private_data); + } + XPT_ERROR_HANDLE(arena, ann); +} + +PRBool +XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block, + PRUint16 num_interfaces, char *name, + PRUint16 *indexp) +{ + int i; + + for (i=1; i<=num_interfaces; i++) { + fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name); + if (strcmp(ide_block[i].name, name) == 0) { + *indexp = i; + return PR_TRUE; + } + } + *indexp = 0; + return PR_FALSE; +} + +static XPT_TYPELIB_VERSIONS_STRUCT versions[] = XPT_TYPELIB_VERSIONS; +#define XPT_TYPELIB_VERSIONS_COUNT (sizeof(versions) / sizeof(versions[0])) + +XPT_PUBLIC_API(PRUint16) +XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor) +{ + int i; + for (i = 0; i < XPT_TYPELIB_VERSIONS_COUNT; i++) { + if (!strcmp(versions[i].str, str)) { + *major = versions[i].major; + *minor = versions[i].minor; + return versions[i].code; + } + } + return XPT_VERSION_UNKNOWN; +} + + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c new file mode 100644 index 00000000..cd9261d0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c @@ -0,0 +1,665 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* Implementation of XDR primitives. */ + +#include "xpt_xdr.h" +#include "nspr.h" +#include <string.h> /* strchr */ + +static PRBool +CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len, + XPTCursor *new_cursor, PRBool *already); + +#define ENCODING(cursor) \ + ((cursor)->state->mode == XPT_ENCODE) + +#define CURS_POOL_OFFSET_RAW(cursor) \ + ((cursor)->pool == XPT_HEADER \ + ? (cursor)->offset \ + : (XPT_ASSERT((cursor)->state->data_offset), \ + (cursor)->offset + (cursor)->state->data_offset)) + +#define CURS_POOL_OFFSET(cursor) \ + (CURS_POOL_OFFSET_RAW(cursor) - 1) + +/* can be used as lvalue */ +#define CURS_POINT(cursor) \ + ((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)]) + +#if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe) +#define DBG(x) printf##x +#else +#define DBG(x) (0) +#endif + +/* XXX fail if XPT_DATA and !state->data_offset */ +#define CHECK_COUNT_(cursor, space) \ + /* if we're in the header, then exceeding the data_offset is illegal */ \ +((cursor)->pool == XPT_HEADER ? \ + (ENCODING(cursor) && \ + ((cursor)->state->data_offset && \ + ((cursor)->offset - 1 + (space) > (cursor)->state->data_offset)) \ + ? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \ + (space), (cursor)->state->data_offset)) && PR_FALSE) \ + : PR_TRUE) : \ + /* if we're in the data area and we're about to exceed the allocation */ \ + (CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ? \ + /* then grow if we're in ENCODE mode */ \ + (ENCODING(cursor) ? GrowPool((cursor)->state->arena, \ + (cursor)->state->pool, \ + (cursor)->state->pool->allocated, \ + 0, CURS_POOL_OFFSET(cursor) + (space)) \ + /* and fail if we're in DECODE mode */ \ + : (DBG(("can't extend in DECODE")) && PR_FALSE)) \ + /* otherwise we're OK */ \ + : PR_TRUE)) + +#define CHECK_COUNT(cursor, space) \ + (CHECK_COUNT_(cursor, space) \ + ? PR_TRUE \ + : (XPT_ASSERT(0), \ + fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \ + PR_FALSE)) + +/* increase the data allocation for the pool by XPT_GROW_CHUNK */ +#define XPT_GROW_CHUNK 8192 + +/* + * quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib. + * XXXmccabe it might turn out that we could use a simpler data structure here. + */ +typedef struct XPTHashRecord { + void *key; + void *value; + struct XPTHashRecord *next; +} XPTHashRecord; + +#define XPT_HASHSIZE 512 + +struct XPTHashTable { /* it's already typedef'ed from before. */ + XPTHashRecord *buckets[XPT_HASHSIZE]; + XPTArena *arena; +}; + +static XPTHashTable * +XPT_NewHashTable(XPTArena *arena) { + XPTHashTable *table; + table = XPT_NEWZAP(arena, XPTHashTable); + if (table) + table->arena = arena; + return table; +} + +static void trimrecord(XPTArena* arena, XPTHashRecord *record) { + if (record == NULL) + return; + trimrecord(arena, record->next); + XPT_DELETE(arena, record); +} + +static void +XPT_HashTableDestroy(XPTHashTable *table) { + int i; + for (i = 0; i < XPT_HASHSIZE; i++) + trimrecord(table->arena, table->buckets[i]); + XPT_FREE(table->arena, table); +} + +static void * +XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) { + XPTHashRecord **bucketloc = table->buckets + + (((PRUint32)(uintptr_t)key) % XPT_HASHSIZE); + XPTHashRecord *bucket; + + while (*bucketloc != NULL) + bucketloc = &((*bucketloc)->next); + + bucket = XPT_NEW(table->arena, XPTHashRecord); + bucket->key = key; + bucket->value = value; + bucket->next = NULL; + *bucketloc = bucket; + return value; +} + +static void * +XPT_HashTableLookup(XPTHashTable *table, void *key) { + XPTHashRecord *bucket = table->buckets[(PRUint32)(uintptr_t)key % XPT_HASHSIZE]; + while (bucket != NULL) { + if (bucket->key == key) + return bucket->value; + bucket = bucket->next; + } + return NULL; +} + +XPT_PUBLIC_API(XPTState *) +XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len) +{ + XPTState *state; + XPTArena *arena; + + arena = XPT_NewArena(512, sizeof(double), "an XDRState"); + if (!arena) + return NULL; + + state = XPT_NEWZAP(arena, XPTState); + if (!state) + goto err_free_arena; + + state->arena = arena; + state->mode = mode; + state->pool = XPT_NEW(arena, XPTDatapool); + state->next_cursor[0] = state->next_cursor[1] = 1; + if (!state->pool) + goto err_free_state; + + state->pool->count = 0; + state->pool->offset_map = XPT_NewHashTable(arena); + + if (!state->pool->offset_map) + goto err_free_pool; + if (mode == XPT_DECODE) { + state->pool->data = data; + state->pool->allocated = len; + } else { + state->pool->data = XPT_MALLOC(arena, XPT_GROW_CHUNK); + if (!state->pool->data) + goto err_free_hash; + state->pool->allocated = XPT_GROW_CHUNK; + } + + return state; + + err_free_hash: + XPT_HashTableDestroy(state->pool->offset_map); + err_free_pool: + XPT_DELETE(arena, state->pool); + err_free_state: + XPT_DELETE(arena, state); + err_free_arena: + if (arena) + XPT_DestroyArena(arena); + return NULL; +} + +XPT_PUBLIC_API(void) +XPT_DestroyXDRState(XPTState *state) +{ + XPTArena *arena = state->arena; + + if (state->pool->offset_map) + XPT_HashTableDestroy(state->pool->offset_map); + if (state->mode == XPT_ENCODE) + XPT_DELETE(arena, state->pool->data); + XPT_DELETE(arena, state->pool); + XPT_DELETE(arena, state); + if (arena) + XPT_DestroyArena(arena); +} + +XPT_PUBLIC_API(void) +XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len) +{ + *len = state->next_cursor[pool] - 1; +} + +XPT_PUBLIC_API(void) +XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len) +{ + if (pool == XPT_HEADER) { + *data = state->pool->data; + } else { + *data = state->pool->data + state->data_offset; + } + *len = state->next_cursor[pool] - 1; +} + +/* All offsets are 1-based */ +XPT_PUBLIC_API(void) +XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp) +{ + if (state->mode == XPT_DECODE) + XPT_SetDataOffset(state, *data_offsetp); + else + *data_offsetp = state->data_offset; +} + +/* if 'exact' is set use that, else grow by the next chunk but + * be sure to grow no less that 'at_least' so that we can't get + * behind on required space. + */ +static PRBool +GrowPool(XPTArena *arena, XPTDatapool *pool, PRUint32 old_size, + PRUint32 exact, PRUint32 at_least) +{ + PRUint32 total_size; + char *newdata; + + if (exact) { + XPT_ASSERT(exact > pool->allocated); + total_size = exact; + } else { + total_size = pool->allocated + XPT_GROW_CHUNK; + if (at_least > total_size) + total_size = at_least; + } + + newdata = XPT_MALLOC(arena, total_size); + if (!newdata) + return PR_FALSE; + if (pool->data) { + if (old_size) + memcpy(newdata, pool->data, old_size); + XPT_FREE(arena, pool->data); + } + pool->data = newdata; + pool->allocated = total_size; + return PR_TRUE; +} + +XPT_PUBLIC_API(void) +XPT_SetDataOffset(XPTState *state, PRUint32 data_offset) +{ + state->data_offset = data_offset; + /* make sure we've allocated enough space for the header */ + if (state->mode == XPT_ENCODE && + data_offset > state->pool->allocated) { + (void)GrowPool(state->arena, state->pool, state->pool->allocated, + data_offset, 0); + } +} + +XPT_PUBLIC_API(PRBool) +XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor) +{ + cursor->state = state; + cursor->pool = pool; + cursor->bits = 0; + cursor->offset = state->next_cursor[pool]; + + if (!(CHECK_COUNT(cursor, len))) + return PR_FALSE; + + /* this check should be in CHECK_CURSOR */ + if (pool == XPT_DATA && !state->data_offset) { + fprintf(stderr, "no data offset for XPT_DATA cursor!\n"); + return PR_FALSE; + } + + state->next_cursor[pool] += len; + + return PR_TRUE; +} + +XPT_PUBLIC_API(PRBool) +XPT_SeekTo(XPTCursor *cursor, PRUint32 offset) +{ + /* XXX do some real checking and update len and stuff */ + cursor->offset = offset; + return PR_TRUE; +} + +XPT_PUBLIC_API(XPTString *) +XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes) +{ + XPTString *str = XPT_NEW(arena, XPTString); + if (!str) + return NULL; + str->length = length; + /* Alloc one extra to store the trailing nul. */ + str->bytes = XPT_MALLOC(arena, length + 1u); + if (!str->bytes) { + XPT_DELETE(arena, str); + return NULL; + } + memcpy(str->bytes, bytes, length); + /* nul-terminate it. */ + str->bytes[length] = '\0'; + return str; +} + +XPT_PUBLIC_API(XPTString *) +XPT_NewStringZ(XPTArena *arena, char *bytes) +{ + PRUint32 length = strlen(bytes); + if (length > 0xffff) + return NULL; /* too long */ + return XPT_NewString(arena, (PRUint16)length, bytes); +} + +XPT_PUBLIC_API(PRBool) +XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp) +{ + XPTString *str = *strp; + XPTMode mode = cursor->state->mode; + int i; + + if (mode == XPT_DECODE) { + str = XPT_NEWZAP(arena, XPTString); + if (!str) + return PR_FALSE; + *strp = str; + } + + if (!XPT_Do16(cursor, &str->length)) + goto error; + + if (mode == XPT_DECODE) + if (!(str->bytes = XPT_MALLOC(arena, str->length + 1u))) + goto error; + + for (i = 0; i < str->length; i++) + if (!XPT_Do8(cursor, (PRUint8 *)&str->bytes[i])) + goto error_2; + + if (mode == XPT_DECODE) + str->bytes[str->length] = 0; + + return PR_TRUE; + error_2: + XPT_DELETE(arena, str->bytes); + error: + XPT_DELETE(arena, str); + return PR_FALSE; +} + +XPT_PUBLIC_API(PRBool) +XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp) +{ + XPTCursor my_cursor; + XPTString *str = *strp; + PRBool already; + + XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2, my_cursor, + already) + + return XPT_DoStringInline(arena, &my_cursor, strp); +} + +XPT_PUBLIC_API(PRBool) +XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp) +{ + XPTCursor my_cursor; + char *ident = *identp; + PRUint32 offset = 0; + + XPTMode mode = cursor->state->mode; + + if (mode == XPT_DECODE) { + char *start, *end; + int len; + + if (!XPT_Do32(cursor, &offset)) + return PR_FALSE; + + if (!offset) { + *identp = NULL; + return PR_TRUE; + } + + my_cursor.pool = XPT_DATA; + my_cursor.offset = offset; + my_cursor.state = cursor->state; + start = &CURS_POINT(&my_cursor); + + end = strchr(start, 0); /* find the end of the string */ + if (!end) { + fprintf(stderr, "didn't find end of string on decode!\n"); + return PR_FALSE; + } + len = end - start; + XPT_ASSERT(len > 0); + + ident = XPT_MALLOC(arena, len + 1u); + if (!ident) + return PR_FALSE; + + memcpy(ident, start, (size_t)len); + ident[len] = 0; + *identp = ident; + + } else { + + if (!ident) { + offset = 0; + if (!XPT_Do32(cursor, &offset)) + return PR_FALSE; + return PR_TRUE; + } + + if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1, + &my_cursor) || + !XPT_Do32(cursor, &my_cursor.offset)) + return PR_FALSE; + + while(*ident) + if (!XPT_Do8(&my_cursor, (PRUint8 *)ident++)) + return PR_FALSE; + if (!XPT_Do8(&my_cursor, (PRUint8 *)ident)) /* write trailing zero */ + return PR_FALSE; + } + + return PR_TRUE; +} + +/* XXXjband it bothers me that this is one hashtable instead of two. + */ +XPT_PUBLIC_API(PRUint32) +XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr) +{ + return (PRUint32)(uintptr_t)XPT_HashTableLookup(cursor->state->pool->offset_map, addr); +} + +XPT_PUBLIC_API(PRBool) +XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset) +{ + return XPT_HashTableAdd(cursor->state->pool->offset_map, + addr, (void *)(uintptr_t)offset) != NULL; +} + +XPT_PUBLIC_API(PRBool) +XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr) +{ + return XPT_HashTableAdd(cursor->state->pool->offset_map, + (void *)(uintptr_t)offset, addr) != NULL; +} + +XPT_PUBLIC_API(void *) +XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset) +{ + return XPT_HashTableLookup(cursor->state->pool->offset_map, (void *)(uintptr_t)offset); +} + +/* Used by XPT_PREAMBLE_NO_ALLOC. */ +static PRBool +CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len, + XPTCursor *new_cursor, PRBool *already) +{ + void *last = *addrp; + + *already = PR_FALSE; + new_cursor->state = cursor->state; + new_cursor->pool = pool; + new_cursor->bits = 0; + + if (cursor->state->mode == XPT_DECODE) { + + last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset); + + if (last) { + *already = PR_TRUE; + *addrp = last; + } + + } else { + + new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last); + if (new_cursor->offset) { + *already = PR_TRUE; + return PR_TRUE; + } + + /* haven't already found it, so allocate room for it. */ + if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) || + !XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset)) + return PR_FALSE; + } + return PR_TRUE; +} + +/* + * IIDs are written in struct order, in the usual big-endian way. From the + * typelib file spec: + * + * "For example, this IID: + * {00112233-4455-6677-8899-aabbccddeeff} + * is converted to the 128-bit value + * 0x00112233445566778899aabbccddeeff + * Note that the byte storage order corresponds to the layout of the nsIID + * C-struct on a big-endian architecture." + * + * (http://www.mozilla.org/scriptable/typelib_file.html#iid) + */ +XPT_PUBLIC_API(PRBool) +XPT_DoIID(XPTCursor *cursor, nsID *iidp) +{ + int i; + + if (!XPT_Do32(cursor, &iidp->m0) || + !XPT_Do16(cursor, &iidp->m1) || + !XPT_Do16(cursor, &iidp->m2)) + return PR_FALSE; + + for (i = 0; i < 8; i++) + if (!XPT_Do8(cursor, (PRUint8 *)&iidp->m3[i])) + return PR_FALSE; + + return PR_TRUE; +} + +XPT_PUBLIC_API(PRBool) +XPT_Do64(XPTCursor *cursor, PRInt64 *u64p) +{ + return XPT_Do32(cursor, (PRUint32 *)u64p) && + XPT_Do32(cursor, ((PRUint32 *)u64p) + 1); +} + +/* + * When we're writing 32- or 16-bit quantities, we write a byte at a time to + * avoid alignment issues. Someone could come and optimize this to detect + * well-aligned cases and do a single store, if they cared. I might care + * later. + */ +XPT_PUBLIC_API(PRBool) +XPT_Do32(XPTCursor *cursor, PRUint32 *u32p) +{ + union { + PRUint8 b8[4]; + PRUint32 b32; + } u; + + if (!CHECK_COUNT(cursor, 4)) + return PR_FALSE; + + if (ENCODING(cursor)) { + u.b32 = XPT_SWAB32(*u32p); + CURS_POINT(cursor) = u.b8[0]; + cursor->offset++; + CURS_POINT(cursor) = u.b8[1]; + cursor->offset++; + CURS_POINT(cursor) = u.b8[2]; + cursor->offset++; + CURS_POINT(cursor) = u.b8[3]; + } else { + u.b8[0] = CURS_POINT(cursor); + cursor->offset++; + u.b8[1] = CURS_POINT(cursor); + cursor->offset++; + u.b8[2] = CURS_POINT(cursor); + cursor->offset++; + u.b8[3] = CURS_POINT(cursor); + *u32p = XPT_SWAB32(u.b32); + } + cursor->offset++; + return PR_TRUE; +} + +XPT_PUBLIC_API(PRBool) +XPT_Do16(XPTCursor *cursor, PRUint16 *u16p) +{ + union { + PRUint8 b8[2]; + PRUint16 b16; + } u; + + if (!CHECK_COUNT(cursor, 2)) + return PR_FALSE; + + if (ENCODING(cursor)) { + u.b16 = XPT_SWAB16(*u16p); + CURS_POINT(cursor) = u.b8[0]; + cursor->offset++; + CURS_POINT(cursor) = u.b8[1]; + } else { + u.b8[0] = CURS_POINT(cursor); + cursor->offset++; + u.b8[1] = CURS_POINT(cursor); + *u16p = XPT_SWAB16(u.b16); + } + cursor->offset++; + + return PR_TRUE; +} + +XPT_PUBLIC_API(PRBool) +XPT_Do8(XPTCursor *cursor, PRUint8 *u8p) +{ + if (!CHECK_COUNT(cursor, 1)) + return PR_FALSE; + if (cursor->state->mode == XPT_ENCODE) + CURS_POINT(cursor) = *u8p; + else + *u8p = CURS_POINT(cursor); + + cursor->offset++; + + return PR_TRUE; +} + + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore new file mode 100644 index 00000000..ebc62d94 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore @@ -0,0 +1,3 @@ +Makefile +PrimitiveTest +SimpleTypeLib diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in new file mode 100644 index 00000000..afdc31b3 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in @@ -0,0 +1,59 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +CPP_PROG_LINK = 1 + +SIMPLE_PROGRAMS = PrimitiveTest$(BIN_SUFFIX) SimpleTypeLib$(BIN_SUFFIX) + +CSRCS = PrimitiveTest.c SimpleTypeLib.c + +LIBS = \ + $(XPCOM_LIBS) \ + $(NSPR_LIBS) \ + $(NULL) + +include $(topsrcdir)/config/rules.mk + +DEFINES += -DEXPORT_XPT_API diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c new file mode 100644 index 00000000..aad33ccc --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c @@ -0,0 +1,157 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* Test the xdr primitives from xpt_xdr.c */ + +#include "xpt_xdr.h" +#include <stdio.h> +#include <string.h> /* for memcpy */ + +#define PASS(msg) \ + fprintf(stderr, "PASSED : %s\n", msg); + +#define FAIL(msg) \ + fprintf(stderr, "FAILURE: %s\n", msg); + +#define TRY_(msg, cond, silent) \ + if ((cond) && !silent) { \ + PASS(msg); \ + } else { \ + FAIL(msg); \ + return 1; \ + } + +#define TRY(msg, cond) TRY_(msg, cond, 0) +#define TRY_Q(msg, cond) TRY_(msg, cond, 1); + +XPTString in_str = { 4, "bazz" }; + +struct TestData { + PRUint32 bit32; + PRUint16 bit16; + PRUint8 bit8[2]; + char *cstr; + XPTString *str; +} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, "foobar", &in_str}, + output = {0, 0, {0, 0}, NULL, NULL }; + +void +dump_struct(char *label, struct TestData *str) +{ + fprintf(stderr, "%s: {%#08x, %#04x, {%#02x, %#02x}, %s, %d/%s}\n", + label, str->bit32, str->bit16, str->bit8[0], str->bit8[1], + str->cstr, str->str->length, str->str->bytes); +} + +PRBool +XDR(XPTArena *arena, XPTCursor *cursor, struct TestData *str) +{ + TRY("Do32", XPT_Do32(cursor, &str->bit32)); + TRY("Do16", XPT_Do16(cursor, &str->bit16)); + TRY("Do8", XPT_Do8 (cursor, &str->bit8[0])); + TRY("Do8", XPT_Do8 (cursor, &str->bit8[1])); + TRY("DoCString", XPT_DoCString(arena, cursor, &str->cstr)); + TRY("DoString", XPT_DoString(arena, cursor, &str->str)); + return 0; +} + +int +main(int argc, char **argv) +{ + XPTArena *arena; + XPTState *state; + XPTCursor curs, *cursor = &curs; + char *header, *data, *whole; + PRUint32 hlen, dlen, i; + + TRY("XPT_NewArena", (arena = XPT_NewArena(1024, sizeof(double), "main"))); + + TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0))); + + XPT_SetDataOffset(state, sizeof input); + + TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor)); + + dump_struct("before", &input); + + if (XDR(arena, cursor, &input)) + return 1; + + fprintf(stderr, "ENCODE successful\n"); + XPT_GetXDRData(state, XPT_HEADER, &header, &hlen); + fprintf(stderr, "XDR header %d bytes at %p:", + hlen, header); + for (i = 0; i < hlen; i++) + fprintf(stderr, "%c%02x", i ? ',' : ' ', (uint8)header[i]); + fprintf(stderr, "\n"); + + XPT_GetXDRData(state, XPT_DATA, &data, &dlen); + + fprintf(stderr, "XDR data %d bytes at %p:", + dlen, data); + for (i = 0; i < dlen; i++) + fprintf(stderr, "%c%02x/%c", i ? ',' : ' ', (uint8)data[i], + (uint8)data[i]); + fprintf(stderr, "\n"); + + whole = malloc(dlen + hlen); + if (!whole) { + fprintf(stderr, "malloc %d failed!\n", dlen + hlen); + return 1; + } + + /* TRY_Q("malloc", (data2 = malloc(len))); */ + memcpy(whole, header, hlen); + memcpy(whole + hlen, data, dlen); + XPT_DestroyXDRState(state); + + TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, whole, + hlen + dlen))); + + TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor)); + XPT_SetDataOffset(state, sizeof input); + + if (XDR(arena, cursor, &output)) + return 1; + + dump_struct("after", &output); + XPT_DestroyXDRState(state); + XPT_DestroyArena(arena); + free(whole); + + return 0; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c new file mode 100644 index 00000000..305b8520 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c @@ -0,0 +1,192 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* Test the structure creation and serialization APIs from xpt_struct.c */ +#include <stdio.h> + +#include "xpt_xdr.h" +#include "xpt_struct.h" + +#define PASS(msg) \ + fprintf(stderr, "PASSED : %s\n", msg); + +#define FAIL(msg) \ + fprintf(stderr, "FAILURE: %s\n", msg); + +#define TRY_(msg, cond, silent) \ + if ((cond) && !silent) { \ + PASS(msg); \ + } else { \ + FAIL(msg); \ + return 1; \ + } + +#define TRY(msg, cond) TRY_(msg, cond, 0) +#define TRY_Q(msg, cond) TRY_(msg, cond, 1); + +struct nsID iid = { + 0x00112233, + 0x4455, + 0x6677, + {0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff} +}; + +XPTTypeDescriptor td_void; + +int +main(int argc, char **argv) +{ + XPTArena *arena; + XPTHeader *header; + XPTAnnotation *ann; + XPTInterfaceDescriptor *id; + XPTMethodDescriptor *meth; + + XPTState *state; + XPTCursor curs, *cursor = &curs; + char *data, *head; + FILE *out; + PRUint32 len, header_sz; + + PRBool ok; + + td_void.prefix.flags = TD_VOID; + +#ifdef XP_MAC + if (argc == 0) { + static char* args[] = { "SimpleTypeLib", "simple.xpt", NULL }; + argc = 2; + argv = args; + } +#endif + + if (argc != 2) { + fprintf(stderr, "Usage: %s <filename.xpt>\n" + " Creates a simple typelib file.\n", argv[0]); + + return 1; + } + + arena = XPT_NewArena(1024, sizeof(double), "main"); + TRY("XPT_NewArena", arena); + + /* construct a header */ + header = XPT_NewHeader(arena, 1, XPT_MAJOR_VERSION, XPT_MINOR_VERSION); + TRY("NewHeader", header); + + + ann = XPT_NewAnnotation(arena, XPT_ANN_LAST | XPT_ANN_PRIVATE, + XPT_NewStringZ(arena, "SimpleTypeLib 1.0"), + XPT_NewStringZ(arena, "See You In Rome")); + TRY("NewAnnotation", ann); + header->annotations = ann; + + header_sz = XPT_SizeOfHeaderBlock(header); + + id = XPT_NewInterfaceDescriptor(arena, 0, 2, 2, 0); + TRY("NewInterfaceDescriptor", id); + + ok = XPT_FillInterfaceDirectoryEntry(arena, header->interface_directory, &iid, + "Interface", "NS", id); + TRY("FillInterfaceDirectoryEntry", ok); + + /* void method1(void) */ + meth = &id->method_descriptors[0]; + ok = XPT_FillMethodDescriptor(arena, meth, 0, "method1", 0); + TRY("FillMethodDescriptor", ok); + meth->result->flags = 0; + meth->result->type.prefix.flags = TD_VOID; + + /* wstring method2(in uint32, in bool) */ + meth = &id->method_descriptors[1]; + ok = XPT_FillMethodDescriptor(arena, meth, 0, "method2", 2); + TRY("FillMethodDescriptor", ok); + + meth->result->flags = 0; + meth->result->type.prefix.flags = TD_PSTRING | XPT_TDP_POINTER; + meth->params[0].type.prefix.flags = TD_UINT32; + meth->params[0].flags = XPT_PD_IN; + meth->params[1].type.prefix.flags = TD_BOOL; + meth->params[1].flags = XPT_PD_IN; + +#if 0 + /* const one = 1; */ + id->const_descriptors[0].name = "one"; + id->const_descriptors[0].type.prefix.flags = TD_UINT16; + id->const_descriptors[0].value.ui16 = 1; + + /* const squeamish = "ossifrage"; */ + id->const_descriptors[1].name = "squeamish"; + id->const_descriptors[1].type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER; + id->const_descriptors[1].value.string = XPT_NewStringZ(arena, "ossifrage"); +#endif + + /* serialize it */ + state = XPT_NewXDRState(XPT_ENCODE, NULL, 0); + TRY("NewState (ENCODE)", state); + + ok = XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor); + TRY("MakeCursor", ok); + + ok = XPT_DoHeader(arena, cursor, &header); + TRY("DoHeader", ok); + + out = fopen(argv[1], "wb"); + if (!out) { + perror("FAILED: fopen"); + return 1; + } + + XPT_GetXDRData(state, XPT_HEADER, &head, &len); + fwrite(head, len, 1, out); + + XPT_GetXDRData(state, XPT_DATA, &data, &len); + fwrite(data, len, 1, out); + + if (ferror(out) != 0 || fclose(out) != 0) { + fprintf(stderr, "\nError writing file: %s\n\n", argv[1]); + } else { + fprintf(stderr, "\nFile written: %s\n\n", argv[1]); + } + XPT_DestroyXDRState(state); + + XPT_FreeHeader(arena, header); + XPT_DestroyArena(arena); + + return 0; +} + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore new file mode 100644 index 00000000..985cc7a7 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore @@ -0,0 +1,3 @@ +Makefile +xpt_dump +xpt_link diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in new file mode 100644 index 00000000..bedece8e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in @@ -0,0 +1,90 @@ +# +# ***** 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 mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +INTERNAL_TOOLS = 1 + +SIMPLE_PROGRAMS = xpt_dump$(BIN_SUFFIX) xpt_link$(BIN_SUFFIX) + +CSRCS = xpt_dump.c xpt_link.c + +SDK_BINARY = \ + $(SIMPLE_PROGRAMS) \ + $(NULL) + +ifdef CROSS_COMPILE +HOST_SIMPLE_PROGRAMS = $(addprefix host_, $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=$(HOST_BIN_SUFFIX))) +HOST_CSRCS = $(CSRCS) +endif + +include $(topsrcdir)/config/rules.mk + +# Compile directly against the static lib, so we can use the tools +# during the build without the shared library path being set. +ifeq ($(OS_ARCH),WINNT) +DEFINES += -DEXPORT_XPT_API +endif + +LIBS = $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX) + +# Tell the $(SIMPLE_PROGRAMS) target that we need to be recompiled +# when libxpt changes. +EXTRA_DEPS = $(wildcard $(DIST)/lib/$(LIB_PREFIX)xpt.*) + +ifdef CROSS_COMPILE +HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX) +HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*) + +ifdef HOST_NSPR_MDCPUCFG +HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG) +endif +endif + + +# Build xpt_link and xpt_dump early. (libs creates .deps used by libs.) +export:: + @$(MAKE) libs + + + diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c new file mode 100644 index 00000000..8926b9c9 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c @@ -0,0 +1,941 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* + * A utility for dumping the contents of a typelib file (.xpt) to screen + */ + +#include "xpt_xdr.h" +#include <stdio.h> +#ifdef XP_MAC +#include <stat.h> +#include <StandardFile.h> +#include "FullPath.h" +#else +#ifdef XP_OS2_EMX +#include <sys/types.h> +#endif +#include <sys/stat.h> +#endif +#include <stdlib.h> +#include <string.h> +#include "prprf.h" + +#define BASE_INDENT 3 + +static char *type_array[32] = + {"int8", "int16", "int32", "int64", + "uint8", "uint16", "uint32", "uint64", + "float", "double", "boolean", "char", + "wchar_t", "void", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved"}; + +static char *ptype_array[32] = + {"int8 *", "int16 *", "int32 *", "int64 *", + "uint8 *", "uint16 *", "uint32 *", "uint64 *", + "float *", "double *", "boolean *", "char *", + "wchar_t *", "void *", "nsIID *", "DOMString *", + "string", "wstring", "Interface *", "InterfaceIs *", + "array", "string_s", "wstring_s", "UTF8String *", + "CString *", "AString *", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved"}; + +static char *rtype_array[32] = + {"int8 &", "int16 &", "int32 &", "int64 &", + "uint8 &", "uint16 &", "uint32 &", "uint64 &", + "float &", "double &", "boolean &", "char &", + "wchar_t &", "void &", "nsIID &", "DOMString &", + "string &", "wstring &", "Interface &", "InterfaceIs &", + "array &", "string_s &", "wstring_s &", "UTF8String &", + "CString &", "AString &", "reserved", "reserved", + "reserved", "reserved", "reserved", "reserved"}; + +PRBool param_problems = PR_FALSE; + +PRBool +XPT_DumpHeader(XPTCursor *cursor, XPTHeader *header, + const int indent, PRBool verbose_mode); + +PRBool +XPT_DumpAnnotations(XPTAnnotation *ann, const int indent, PRBool verbose_mode); + +PRBool +XPT_DumpInterfaceDirectoryEntry(XPTCursor *cursor, + XPTInterfaceDirectoryEntry *ide, + XPTHeader *header, const int indent, + PRBool verbose_mode); + +PRBool +XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id, + XPTHeader *header, const int indent, + PRBool verbose_mode); + +PRBool +XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md, + XPTInterfaceDescriptor *id, + const int indent, PRBool verbose_mode); +PRBool +XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td, + XPTInterfaceDescriptor *id, + char **type_string); + +PRBool +XPT_DumpXPTString(XPTString *str); + +PRBool +XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd, + XPTInterfaceDescriptor *id, + const int indent, PRBool verbose_mode, + PRBool is_result); + +PRBool +XPT_DumpTypeDescriptor(XPTTypeDescriptor *td, + XPTInterfaceDescriptor *id, + int indent, PRBool verbose_mode); + +PRBool +XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd, + XPTInterfaceDescriptor *id, + const int indent, PRBool verbose_mode); + +static void +xpt_dump_usage(char *argv[]) { + fprintf(stdout, "Usage: %s [-v] <filename.xpt>\n" + " -v verbose mode\n", argv[0]); +} + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) + +#define main xptdump_main +int xptdump_main(int argc, char *argv[]); + +#define get_file_length mac_get_file_length +extern size_t mac_get_file_length(const char* filename); + +#else /* !(XP_MAC && XPIDL_PLUGIN) */ + +static size_t get_file_length(const char* filename) +{ + struct stat file_stat; + if (stat(filename, &file_stat) != 0) { + perror("FAILED: get_file_length"); + exit(1); + } + return file_stat.st_size; +} + +#endif /* !(XP_MAC && XPIDL_PLUGIN) */ + +int +main(int argc, char **argv) +{ + PRBool verbose_mode = PR_FALSE; + XPTArena *arena; + XPTState *state; + XPTCursor curs, *cursor = &curs; + XPTHeader *header; + size_t flen; + char *name; + char *whole; + FILE *in; + int result = 1; + + switch (argc) { + case 2: + if (argv[1][0] == '-') { + xpt_dump_usage(argv); + return 1; + } + name = argv[1]; + flen = get_file_length(name); + in = fopen(name, "rb"); + break; + case 3: + verbose_mode = PR_TRUE; + if (argv[1][0] != '-' || argv[1][1] != 'v') { + xpt_dump_usage(argv); + return 1; + } + name = argv[2]; + flen = get_file_length(name); + in = fopen(name, "rb"); + break; + default: + xpt_dump_usage(argv); + return 1; + } + + if (!in) { + perror("FAILED: fopen"); + return 1; + } + + arena = XPT_NewArena(1024, sizeof(double), "main xpt_dump arena"); + if (!arena) { + perror("XPT_NewArena failed"); + return 1; + } + + /* after arena creation all exits via 'goto out' */ + + whole = XPT_MALLOC(arena, flen); + if (!whole) { + perror("FAILED: XPT_MALLOC for whole"); + goto out; + } + + if (flen > 0) { + size_t rv = fread(whole, 1, flen, in); + if (rv < flen) { + fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen); + goto out; + } + if (ferror(in) != 0 || fclose(in) != 0) + perror("FAILED: Unable to read typelib file.\n"); + + state = XPT_NewXDRState(XPT_DECODE, whole, flen); + if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) { + fprintf(stdout, "XPT_MakeCursor failed for %s\n", name); + goto out; + } + if (!XPT_DoHeader(arena, cursor, &header)) { + fprintf(stdout, + "DoHeader failed for %s. Is %s a valid .xpt file?\n", + name, name); + goto out; + } + + if (!XPT_DumpHeader(cursor, header, BASE_INDENT, verbose_mode)) { + perror("FAILED: XPT_DumpHeader"); + goto out; + } + + if (param_problems) { + fprintf(stdout, "\nWARNING: ParamDescriptors are present with " + "bad in/out/retval flag information.\n" + "These have been marked with 'XXX'.\n" + "Remember, retval params should always be marked as out!\n"); + } + + XPT_DestroyXDRState(state); + XPT_FREE(arena, whole); + + } else { + fclose(in); + perror("FAILED: file length <= 0"); + goto out; + } + + result = 0; + +out: + XPT_DestroyArena(arena); + return result; +} + +PRBool +XPT_DumpHeader(XPTCursor *cursor, XPTHeader *header, + const int indent, PRBool verbose_mode) +{ + int i; + + fprintf(stdout, "Header:\n"); + + if (verbose_mode) { + fprintf(stdout, "%*sMagic beans: ", indent, " "); + for (i=0; i<16; i++) { + fprintf(stdout, "%02x", header->magic[i]); + } + fprintf(stdout, "\n"); + if (strncmp((const char*)header->magic, XPT_MAGIC, 16) == 0) + fprintf(stdout, "%*s PASSED\n", indent, " "); + else + fprintf(stdout, "%*s FAILED\n", indent, " "); + } + fprintf(stdout, "%*sMajor version: %d\n", indent, " ", + header->major_version); + fprintf(stdout, "%*sMinor version: %d\n", indent, " ", + header->minor_version); + fprintf(stdout, "%*sNumber of interfaces: %d\n", indent, " ", + header->num_interfaces); + + if (verbose_mode) { + fprintf(stdout, "%*sFile length: %d\n", indent, " ", + header->file_length); + fprintf(stdout, "%*sData pool offset: %d\n\n", indent, " ", + header->data_pool); + } + + fprintf(stdout, "%*sAnnotations:\n", indent, " "); + if (!XPT_DumpAnnotations(header->annotations, indent*2, verbose_mode)) + return PR_FALSE; + + fprintf(stdout, "\nInterface Directory:\n"); + for (i=0; i<header->num_interfaces; i++) { + if (verbose_mode) { + fprintf(stdout, "%*sInterface #%d:\n", indent, " ", i); + if (!XPT_DumpInterfaceDirectoryEntry(cursor, + &header->interface_directory[i], + header, indent*2, + verbose_mode)) { + return PR_FALSE; + } + } else { + if (!XPT_DumpInterfaceDirectoryEntry(cursor, + &header->interface_directory[i], + header, indent, + verbose_mode)) { + return PR_FALSE; + } + } + } + + return PR_TRUE; +} + +PRBool +XPT_DumpAnnotations(XPTAnnotation *ann, const int indent, PRBool verbose_mode) +{ + int i = -1; + XPTAnnotation *last; + int new_indent = indent + BASE_INDENT; + + do { + i++; + if (XPT_ANN_IS_PRIVATE(ann->flags)) { + if (verbose_mode) { + fprintf(stdout, "%*sAnnotation #%d is private.\n", + indent, " ", i); + } else { + fprintf(stdout, "%*sAnnotation #%d:\n", + indent, " ", i); + } + fprintf(stdout, "%*sCreator: ", new_indent, " "); + if (!XPT_DumpXPTString(ann->creator)) + return PR_FALSE; + fprintf(stdout, "\n"); + fprintf(stdout, "%*sPrivate Data: ", new_indent, " "); + if (!XPT_DumpXPTString(ann->private_data)) + return PR_FALSE; + fprintf(stdout, "\n"); + } else { + fprintf(stdout, "%*sAnnotation #%d is empty.\n", + indent, " ", i); + } + last = ann; + ann = ann->next; + } while (!XPT_ANN_IS_LAST(last->flags)); + + if (verbose_mode) { + fprintf(stdout, "%*sAnnotation #%d is the last annotation.\n", + indent, " ", i); + } + + return PR_TRUE; +} + +static void +print_IID(struct nsID *iid, FILE *file) +{ + fprintf(file, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (PRUint32) iid->m0, (PRUint32) iid->m1,(PRUint32) iid->m2, + (PRUint32) iid->m3[0], (PRUint32) iid->m3[1], + (PRUint32) iid->m3[2], (PRUint32) iid->m3[3], + (PRUint32) iid->m3[4], (PRUint32) iid->m3[5], + (PRUint32) iid->m3[6], (PRUint32) iid->m3[7]); + +} + +PRBool +XPT_DumpInterfaceDirectoryEntry(XPTCursor *cursor, + XPTInterfaceDirectoryEntry *ide, + XPTHeader *header, const int indent, + PRBool verbose_mode) +{ + int new_indent = indent + BASE_INDENT; + + if (verbose_mode) { + fprintf(stdout, "%*sIID: ", indent, " "); + print_IID(&ide->iid, stdout); + fprintf(stdout, "\n"); + + fprintf(stdout, "%*sName: %s\n", + indent, " ", ide->name); + fprintf(stdout, "%*sNamespace: %s\n", + indent, " ", ide->name_space ? ide->name_space : "none"); + fprintf(stdout, "%*sAddress of interface descriptor: %p\n", + indent, " ", ide->interface_descriptor); + + fprintf(stdout, "%*sDescriptor:\n", indent, " "); + + if (!XPT_DumpInterfaceDescriptor(cursor, ide->interface_descriptor, + header, new_indent, verbose_mode)) { + return PR_FALSE; + } + } else { + fprintf(stdout, "%*s- %s::%s (", indent, " ", + ide->name_space ? ide->name_space : "", ide->name); + print_IID(&ide->iid, stdout); + fprintf(stdout, "):\n"); + if (!XPT_DumpInterfaceDescriptor(cursor, ide->interface_descriptor, + header, new_indent, verbose_mode)) { + return PR_FALSE; + } + } + + return PR_TRUE; +} + +PRBool +XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id, + XPTHeader *header, const int indent, + PRBool verbose_mode) +{ + XPTInterfaceDirectoryEntry *parent_ide; + int i; + int new_indent = indent + BASE_INDENT; + int more_indent = new_indent + BASE_INDENT; + + if (!id) { + fprintf(stdout, "%*s[Unresolved]\n", indent, " "); + return PR_TRUE; + } + + if (id->parent_interface) { + + parent_ide = &header->interface_directory[id->parent_interface - 1]; + + fprintf(stdout, "%*sParent: %s::%s\n", indent, " ", + parent_ide->name_space ? + parent_ide->name_space : "", + parent_ide->name); + } + + fprintf(stdout, "%*sFlags:\n", indent, " "); + + fprintf(stdout, "%*sScriptable: %s\n", new_indent, " ", + XPT_ID_IS_SCRIPTABLE(id->flags) ? "TRUE" : "FALSE"); + + fprintf(stdout, "%*sFunction: %s\n", new_indent, " ", + XPT_ID_IS_FUNCTION(id->flags) ? "TRUE" : "FALSE"); + + if (verbose_mode) { + if (id->parent_interface) { + fprintf(stdout, + "%*sIndex of parent interface (in data pool): %d\n", + indent, " ", id->parent_interface); + + } + } else { + } + + if (id->num_methods > 0) { + if (verbose_mode) { + fprintf(stdout, + "%*s# of Method Descriptors: %d\n", + indent, " ", id->num_methods); + } else { + fprintf(stdout, "%*sMethods:\n", indent, " "); + } + + for (i=0; i<id->num_methods; i++) { + if (verbose_mode) { + fprintf(stdout, "%*sMethod #%d:\n", new_indent, " ", i); + if (!XPT_DumpMethodDescriptor(header, + &id->method_descriptors[i], id, + more_indent, verbose_mode)) { + return PR_FALSE; + } + } else { + if (!XPT_DumpMethodDescriptor(header, + &id->method_descriptors[i], id, + new_indent, verbose_mode)) { + return PR_FALSE; + } + } + } + } else { + fprintf(stdout, "%*sMethods:\n", indent, " "); + fprintf(stdout, "%*sNo Methods\n", new_indent, " "); + } + + if (id->num_constants > 0) { + if (verbose_mode) { + fprintf(stdout, + "%*s# of Constant Descriptors: %d\n", + indent, " ", id->num_constants); + } else { + fprintf(stdout, "%*sConstants:\n", indent, " "); + } + + for (i=0; i<id->num_constants; i++) { + if (verbose_mode) { + fprintf(stdout, "%*sConstant #%d:\n", new_indent, " ", i); + if (!XPT_DumpConstDescriptor(header, + &id->const_descriptors[i], id, + more_indent, verbose_mode)) + return PR_FALSE; + } else { + if (!XPT_DumpConstDescriptor(header, + &id->const_descriptors[i], id, + new_indent, verbose_mode)) { + return PR_FALSE; + } + } + } + } else { + fprintf(stdout, "%*sConstants:\n", indent, " "); + fprintf(stdout, "%*sNo Constants\n", new_indent, " "); + } + + return PR_TRUE; +} + +PRBool +XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md, + XPTInterfaceDescriptor *id, + const int indent, PRBool verbose_mode) +{ + int i; + int new_indent = indent + BASE_INDENT; + int more_indent = new_indent + BASE_INDENT; + + if (verbose_mode) { + fprintf(stdout, "%*sName: %s\n", indent, " ", md->name); + fprintf(stdout, "%*sIs Getter? ", indent, " "); + if (XPT_MD_IS_GETTER(md->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sIs Setter? ", indent, " "); + if (XPT_MD_IS_SETTER(md->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sIs NotXPCOM? ", indent, " "); + if (XPT_MD_IS_NOTXPCOM(md->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sIs Constructor? ", indent, " "); + if (XPT_MD_IS_CTOR(md->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sIs Hidden? ", indent, " "); + if (XPT_MD_IS_HIDDEN(md->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*s# of arguments: %d\n", indent, " ", md->num_args); + fprintf(stdout, "%*sParameter Descriptors:\n", indent, " "); + + for (i=0; i<md->num_args; i++) { + fprintf(stdout, "%*sParameter #%d:\n", new_indent, " ", i); + + if (!XPT_DumpParamDescriptor(header, &md->params[i], id, + more_indent, verbose_mode, PR_FALSE)) + return PR_FALSE; + } + + fprintf(stdout, "%*sResult:\n", indent, " "); + if (!XPT_DumpParamDescriptor(header, md->result, id, new_indent, + verbose_mode, PR_TRUE)) { + return PR_FALSE; + } + } else { + char *param_type; + XPTParamDescriptor *pd; + + if (!XPT_GetStringForType(header, &md->result->type, id, ¶m_type)) { + return PR_FALSE; + } + fprintf(stdout, "%*s%c%c%c%c%c %s %s(", indent - 6, " ", + XPT_MD_IS_GETTER(md->flags) ? 'G' : ' ', + XPT_MD_IS_SETTER(md->flags) ? 'S' : ' ', + XPT_MD_IS_HIDDEN(md->flags) ? 'H' : ' ', + XPT_MD_IS_NOTXPCOM(md->flags) ? 'N' : ' ', + XPT_MD_IS_CTOR(md->flags) ? 'C' : ' ', + param_type, md->name); + for (i=0; i<md->num_args; i++) { + if (i!=0) { + fprintf(stdout, ", "); + } + pd = &md->params[i]; + if (XPT_PD_IS_IN(pd->flags)) { + fprintf(stdout, "in"); + if (XPT_PD_IS_OUT(pd->flags)) { + fprintf(stdout, "out "); + if (XPT_PD_IS_RETVAL(pd->flags)) { + fprintf(stdout, "retval "); + } + if (XPT_PD_IS_SHARED(pd->flags)) { + fprintf(stdout, "shared "); + } + } else { + fprintf(stdout, " "); + if (XPT_PD_IS_DIPPER(pd->flags)) { + fprintf(stdout, "dipper "); + } + if (XPT_PD_IS_RETVAL(pd->flags)) { + fprintf(stdout, "retval "); + } + } + } else { + if (XPT_PD_IS_OUT(pd->flags)) { + fprintf(stdout, "out "); + if (XPT_PD_IS_RETVAL(pd->flags)) { + fprintf(stdout, "retval "); + } + if (XPT_PD_IS_SHARED(pd->flags)) { + fprintf(stdout, "shared "); + } + } else { + param_problems = PR_TRUE; + fprintf(stdout, "XXX "); + } + } + if (!XPT_GetStringForType(header, &pd->type, id, ¶m_type)) { + return PR_FALSE; + } + fprintf(stdout, "%s", param_type); + } + fprintf(stdout, ");\n"); + } + return PR_TRUE; +} + +PRBool +XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td, + XPTInterfaceDescriptor *id, + char **type_string) +{ + static char buf[128]; /* ugly non-reentrant use of static buffer! */ + PRBool isArray = PR_FALSE; + + int tag = XPT_TDP_TAG(td->prefix); + + if (tag == TD_ARRAY) { + isArray = PR_TRUE; + td = &id->additional_types[td->type.additional_type]; + tag = XPT_TDP_TAG(td->prefix); + } + + if (tag == TD_INTERFACE_TYPE) { + int idx = td->type.iface; + if (!idx || idx > header->num_interfaces) + *type_string = "UNKNOWN_INTERFACE"; + else + *type_string = header->interface_directory[idx-1].name; + } else if (XPT_TDP_IS_POINTER(td->prefix.flags)) { + if (XPT_TDP_IS_REFERENCE(td->prefix.flags)) + *type_string = rtype_array[tag]; + else + *type_string = ptype_array[tag]; + } else { + *type_string = type_array[tag]; + } + + if(isArray) { + sprintf(buf, "%s []", *type_string); + *type_string = buf; + } + + return PR_TRUE; +} + +PRBool +XPT_DumpXPTString(XPTString *str) +{ + int i; + for (i=0; i<str->length; i++) { + fprintf(stdout, "%c", str->bytes[i]); + } + return PR_TRUE; +} + +PRBool +XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd, + XPTInterfaceDescriptor *id, + const int indent, PRBool verbose_mode, + PRBool is_result) +{ + int new_indent = indent + BASE_INDENT; + + if (!XPT_PD_IS_IN(pd->flags) && + !XPT_PD_IS_OUT(pd->flags) && + (XPT_PD_IS_RETVAL(pd->flags) || + XPT_PD_IS_SHARED(pd->flags))) { + param_problems = PR_TRUE; + fprintf(stdout, "XXX\n"); + } else { + if (!XPT_PD_IS_IN(pd->flags) && !XPT_PD_IS_OUT(pd->flags)) { + if (is_result) { + if (XPT_TDP_TAG(pd->type.prefix) != TD_UINT32 && + XPT_TDP_TAG(pd->type.prefix) != TD_VOID) { + param_problems = PR_TRUE; + fprintf(stdout, "XXX\n"); + } + } else { + param_problems = PR_TRUE; + fprintf(stdout, "XXX\n"); + } + } + } + + fprintf(stdout, "%*sIn Param? ", indent, " "); + if (XPT_PD_IS_IN(pd->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sOut Param? ", indent, " "); + if (XPT_PD_IS_OUT(pd->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sRetval? ", indent, " "); + if (XPT_PD_IS_RETVAL(pd->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sShared? ", indent, " "); + if (XPT_PD_IS_SHARED(pd->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sDipper? ", indent, " "); + if (XPT_PD_IS_DIPPER(pd->flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + + fprintf(stdout, "%*sType Descriptor:\n", indent, " "); + if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode)) + return PR_FALSE; + + return PR_TRUE; +} + +PRBool +XPT_DumpTypeDescriptor(XPTTypeDescriptor *td, + XPTInterfaceDescriptor *id, + int indent, PRBool verbose_mode) +{ + int new_indent; + + if (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { + fprintf(stdout, "%*sArray (size in arg %d and length in arg %d) of...\n", + indent, " ", td->argnum, td->argnum2); + td = &id->additional_types[td->type.additional_type]; + indent += BASE_INDENT; + } + + new_indent = indent + BASE_INDENT; + + fprintf(stdout, "%*sIs Pointer? ", indent, " "); + if (XPT_TDP_IS_POINTER(td->prefix.flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sIs Unique Pointer? ", indent, " "); + if (XPT_TDP_IS_UNIQUE_POINTER(td->prefix.flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sIs Reference? ", indent, " "); + if (XPT_TDP_IS_REFERENCE(td->prefix.flags)) + fprintf(stdout, "TRUE\n"); + else + fprintf(stdout, "FALSE\n"); + + fprintf(stdout, "%*sTag: %d\n", indent, " ", + XPT_TDP_TAG(td->prefix)); + + if (XPT_TDP_TAG(td->prefix) == TD_PSTRING_SIZE_IS || + XPT_TDP_TAG(td->prefix) == TD_PWSTRING_SIZE_IS) { + fprintf(stdout, "%*s - size in arg %d and length in arg %d\n", + indent, " ", td->argnum, td->argnum2); + } + + if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) { + fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " "); + fprintf(stdout, "%*sIndex of IDE: %d\n", new_indent, " ", + td->type.iface); + } + + if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) { + fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " "); + fprintf(stdout, "%*sIndex of Method Argument: %d\n", new_indent, " ", + td->argnum); + } + + return PR_TRUE; +} + +PRBool +XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd, + XPTInterfaceDescriptor *id, + const int indent, PRBool verbose_mode) +{ + int new_indent = indent + BASE_INDENT; + char *const_type; +/* char *out; */ + PRUint32 uintout; + PRInt32 intout; + + if (verbose_mode) { + fprintf(stdout, "%*sName: %s\n", indent, " ", cd->name); + fprintf(stdout, "%*sType Descriptor: \n", indent, " "); + if (!XPT_DumpTypeDescriptor(&cd->type, id, new_indent, verbose_mode)) + return PR_FALSE; + fprintf(stdout, "%*sValue: ", indent, " "); + } else { + if (!XPT_GetStringForType(header, &cd->type, id, &const_type)) { + return PR_FALSE; + } + fprintf(stdout, "%*s%s %s = ", indent, " ", const_type, cd->name); + } + + switch(XPT_TDP_TAG(cd->type.prefix)) { + case TD_INT8: + fprintf(stdout, "%d", cd->value.i8); + break; + case TD_INT16: + fprintf(stdout, "%d", cd->value.i16); + break; + case TD_INT64: + /* XXX punt for now to remove NSPR linkage... + * borrow from mozilla/nsprpub/pr/src/io/prprf.c::cvt_ll? */ + +/* out = PR_smprintf("%lld", cd->value.i64); */ +/* fputs(out, stdout); */ +/* PR_smprintf_free(out); */ + LL_L2I(intout, cd->value.i64); + fprintf(stdout, "%d", intout); + break; + case TD_INT32: + fprintf(stdout, "%d", cd->value.i32); + break; + case TD_UINT8: + fprintf(stdout, "%u", cd->value.ui8); + break; + case TD_UINT16: + fprintf(stdout, "%u", cd->value.ui16); + break; + case TD_UINT64: +/* out = PR_smprintf("%lld", cd->value.ui64); */ +/* fputs(out, stdout); */ +/* PR_smprintf_free(out); */ + /* XXX punt for now to remove NSPR linkage. */ + LL_L2UI(uintout, cd->value.ui64); + fprintf(stdout, "%u", uintout); + break; + case TD_UINT32: + fprintf(stdout, "%u", cd->value.ui32); + break; + case TD_FLOAT: + fprintf(stdout, "%f", cd->value.flt); + break; + case TD_DOUBLE: + fprintf(stdout, "%g", cd->value.dbl); + break; + case TD_BOOL: + if (cd->value.bul) + fprintf(stdout, "TRUE"); + else + fprintf(stdout, "FALSE"); + break; + case TD_CHAR: + fprintf(stdout, "%c", cd->value.ch); + break; + case TD_WCHAR: + fprintf(stdout, "%c", cd->value.wch & 0xff); + break; + case TD_VOID: + fprintf(stdout, "VOID"); + break; + case TD_PNSIID: + if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) { + print_IID(cd->value.iid, stdout); + } else + return PR_FALSE; + break; + case TD_PSTRING: + if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) { + fprintf(stdout, "%s", cd->value.str); + } else + return PR_FALSE; + break; + case TD_PWSTRING: + if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) { + PRUint16 *ch = cd->value.wstr; + while (*ch) { + fprintf(stdout, "%c", *ch & 0xff); + ch++; + } + } else + return PR_FALSE; + break; + default: + perror("Unrecognized type"); + return PR_FALSE; + break; + } + + if (verbose_mode) { + fprintf(stdout, "\n"); + } else { + fprintf(stdout, ";\n"); + } + + return PR_TRUE; +} diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c new file mode 100644 index 00000000..872b96fd --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c @@ -0,0 +1,883 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* + * A utility for linking multiple typelib files. + */ + +#include "xpt_xdr.h" +#include <stdio.h> +#ifdef XP_MAC +#include <stat.h> +#else +#include <sys/stat.h> +#endif +#include <stdlib.h> +#include <string.h> +#include "prlong.h" + +#ifndef NULL +#define NULL (void *) 0 +#endif + +/* Forward declarations. */ +typedef struct fixElement fixElement; +static int compare_IDEs_by_IID(const void *ap, const void *bp); +static int compare_IDE_with_zero(const void *ap); +static int compare_IDEs_by_name(const void *ap, const void *bp); +static int compare_IDEs_by_name_space(const void *ap, const void *bp); +static int compare_strings(const void *ap, const void *bp); +static int compare_pointers(const void *ap, const void *bp); +static int compare_fixElements_by_IID(const void *ap, const void *bp); +static int compare_fixElements_by_name(const void *ap, const void *bp); +static int compare_IIDs(const void *ap, const void *bp); +PRBool shrink_IDE_array(XPTInterfaceDirectoryEntry *ide, + int element_to_delete, int num_interfaces); +PRBool update_fix_array(XPTArena *arena, fixElement *fix, int element_to_delete, + int num_interfaces, int replacement); +static int get_new_index(const fixElement *fix, int num_elements, + int target_file, int target_interface); +PRBool copy_IDE(XPTInterfaceDirectoryEntry *from, + XPTInterfaceDirectoryEntry *to); +PRBool copy_fixElement(fixElement *from, fixElement *to); +static void print_IID(struct nsID *iid, FILE *file); +static void xpt_link_usage(char *argv[]); + +struct fixElement { + nsID iid; + char* name; + int file_num; + int interface_num; + PRBool is_deleted; + /* These next two variables will point you to the substitute interface + * if this one has been deleted. + */ + int maps_to_file_num; + int maps_to_interface_num; +}; + +/* Global variables. */ +PRUint16 trueNumberOfInterfaces = 0; +PRUint16 totalNumberOfInterfaces = 0; +PRUint16 oldTotalNumberOfInterfaces = 0; + +/* The following globals are explained in xpt_struct.h */ +PRUint8 major_version = XPT_MAJOR_VERSION; +PRUint8 minor_version = XPT_MINOR_VERSION; + +#if defined(XP_MAC) && defined(XPIDL_PLUGIN) + +#define main xptlink_main +int xptlink_main(int argc, char *argv[]); +extern size_t mac_get_file_length(const char* filename); +#define get_file_length mac_get_file_length + +#else + +static size_t get_file_length(const char* filename) +{ + struct stat file_stat; + if (stat(filename, &file_stat) != 0) { + perror("FAILED: get_file_length"); + exit(1); + } + return file_stat.st_size; +} + +#endif /* XP_MAC && XPIDL_PLUGIN */ + +int +main(int argc, char **argv) +{ + XPTArena *arena; + XPTState *state; + XPTCursor curs, *cursor = &curs; + XPTHeader *header; + XPTInterfaceDirectoryEntry *IDE_array = NULL; + XPTInterfaceDescriptor *id; + XPTTypeDescriptor *td; + XPTAnnotation *ann, *first_ann; + PRUint32 header_sz, len; + PRUint32 oldOffset; + PRUint32 newOffset; + size_t flen = 0; + char *head, *data, *whole; + const char *outFileName; + FILE *in, *out; + fixElement *fix_array = NULL; + int i,j; + int k = 0; + + if (argc < 3) { + xpt_link_usage(argv); + return 1; + } + + arena = XPT_NewArena(1024 * 10, sizeof(double), "main xpt_link arena"); + if (!arena) { + perror("FAILED: XPT_NewArena"); + return 1; + } + + first_ann = XPT_NewAnnotation(arena, XPT_ANN_LAST, NULL, NULL); + + /* Check if the "-t version numnber" cmd line arg is present */ + i = 1; + if (argv[i][0] == '-' && argv[i][1] == 't') { + /* Parse for "-t version number" */ + + /* If -t is the last argument on the command line, we have a problem */ + if (i + 1 == argc) { + fprintf(stderr, "ERROR: missing version number after -t\n"); + xpt_link_usage(argv); + return 1; + } + + /* + * Assume that the argument after "-t" is the version number string + * and search for it in our internal list of acceptable version + * numbers. + */ + + switch (XPT_ParseVersionString(argv[++i], &major_version, + &minor_version)) { + case XPT_VERSION_CURRENT: + case XPT_VERSION_OLD: + break; + case XPT_VERSION_UNSUPPORTED: + fprintf(stderr, "ERROR: version \"%s\" not supported.\n", + argv[i]); + xpt_link_usage(argv); + return 1; + case XPT_VERSION_UNKNOWN: + default: + fprintf(stderr, "ERROR: version \"%s\" not recognised.\n", + argv[i]); + xpt_link_usage(argv); + return 1; + } + + /* Hang onto the output file name. It's needed later. */ + outFileName = argv[++i]; + + /* Increment i to the cmd line arg after outFileName */ + i++; + } + else { + outFileName = argv[1]; + i = 2; + } + + for ( /* use i from earlier */ ; i < argc; i++) { + char *name = argv[i]; + + flen = get_file_length(name); + if (!flen) { + fprintf(stderr, "ERROR: file %s is zero length\n", name); + return 1; + } + + in = fopen(name, "rb"); + if (!in) { + perror("FAILED: fopen"); + return 1; + } + + whole = XPT_MALLOC(arena, flen); + if (!whole) { + perror("FAILED: XPT_MALLOC for whole"); + return 1; + } + + if (flen > 0) { + size_t rv = fread(whole, 1, flen, in); + if (rv < flen) { + fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen); + return 1; + } + if (ferror(in) != 0 || fclose(in) != 0) { + perror("FAILED: Unable to read typelib file.\n"); + return 1; + } + + state = XPT_NewXDRState(XPT_DECODE, whole, flen); + if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) { + fprintf(stdout, "XPT_MakeCursor failed for %s\n", name); + return 1; + } + if (!XPT_DoHeader(arena, cursor, &header)) { + fprintf(stdout, + "DoHeader failed for %s. Is %s a valid .xpt file?\n", + name, name); + return 1; + } + + /* + * Make sure that the version of the typelib file is less than or + * equal to the version specified in the -t cmd line arg. + */ + + if (header && + (header->major_version > major_version || + (header->major_version == major_version && + header->minor_version > minor_version))) { + fprintf(stderr, "FAILED: %s's version, %d.%d, is newer than " + "the version (%d.%d) specified in the -t " + "command line argument.\n", + name, header->major_version, header->minor_version, + major_version, minor_version); + return 1; + } + + oldTotalNumberOfInterfaces = totalNumberOfInterfaces; + totalNumberOfInterfaces += header->num_interfaces; + if (header->num_interfaces > 0) { + XPTInterfaceDirectoryEntry *newIDE; + fixElement *newFix; + + newIDE = (XPTInterfaceDirectoryEntry *) + XPT_MALLOC(arena, totalNumberOfInterfaces * + sizeof(XPTInterfaceDirectoryEntry)); + if (!newIDE) { + perror("FAILED: XPT_MALLOC of IDE_array"); + return 1; + } + + if (IDE_array) { + if (oldTotalNumberOfInterfaces) + memcpy(newIDE, IDE_array, + oldTotalNumberOfInterfaces * + sizeof(XPTInterfaceDirectoryEntry)); + XPT_FREE(arena, IDE_array); + } + IDE_array = newIDE; + + + newFix = (fixElement *) + XPT_MALLOC(arena, + totalNumberOfInterfaces * sizeof(fixElement)); + if (!newFix) { + perror("FAILED: XPT_MALLOC of fix_array"); + return 1; + } + + if (fix_array) { + if (oldTotalNumberOfInterfaces) + memcpy(newFix, fix_array, + oldTotalNumberOfInterfaces * + sizeof(fixElement)); + XPT_FREE(arena, fix_array); + } + fix_array = newFix; + + for (j=0; j<header->num_interfaces; j++) { + if (!copy_IDE(&header->interface_directory[j], + &IDE_array[k])) { + perror("FAILED: 1st copying of IDE"); + return 1; + } + fix_array[k].iid = IDE_array[k].iid; + fix_array[k].name = IDE_array[k].name; + fix_array[k].file_num = i-2; + fix_array[k].interface_num = j+1; + fix_array[k].is_deleted = PR_FALSE; + fix_array[k].maps_to_file_num = i-2; + fix_array[k].maps_to_interface_num = j+1; + + k++; + } + } + + /* Copy the annotations if they are not 'empty' + */ + if (header->annotations != NULL && + header->annotations->flags != XPT_ANN_LAST) { + ann = first_ann; + while (ann->next != NULL) { + ann = ann->next; + } + ann->next = header->annotations; + } + + XPT_FREEIF(arena, header); + if (state) + XPT_DestroyXDRState(state); + XPT_FREE(arena, whole); + flen = 0; + + } else { + fclose(in); + perror("FAILED: file length <= 0"); + return 1; + } + } + + /* Make sure the last annotation is the only one marked as XP_ANN_LAST. + */ + ann = first_ann; + while (ann->next != NULL) { + ann->flags &= ~XPT_ANN_LAST; + ann = ann->next; + } + ann->flags |= XPT_ANN_LAST; + + /* Sort both IDE_array and fix_array by name so we can check for + * name_space::name collisions. + */ + qsort(IDE_array, + totalNumberOfInterfaces, + sizeof(XPTInterfaceDirectoryEntry), + compare_IDEs_by_name); + + qsort(fix_array, + totalNumberOfInterfaces, + sizeof(fixElement), + compare_fixElements_by_name); + + /* trueNumberOfInterfaces == number of interfaces left after deletions + * are made. Initialize it here to be the same as the total number of + * interfaces we'ce encountered thus far. + */ + trueNumberOfInterfaces = totalNumberOfInterfaces; + + /* Iterate through the sorted interfaces. Start at one so we don't + * accidentally walk off the end of the array. + */ + i = 1; + while (i != trueNumberOfInterfaces) { + + /* Check for name_space::name collision. + */ + if (compare_strings(IDE_array[i-1].name, + IDE_array[i].name) == 0 && + compare_strings(IDE_array[i-1].name_space, + IDE_array[i].name_space) == 0) { + + /* If one of the interfaces is unresolved, delete that one + * preferentailly. + */ + if (!IDE_array[i-1].interface_descriptor) { + /* Shrink the IDE_array to delete the duplicate interface. + */ + if (!shrink_IDE_array(IDE_array, + i-1, + trueNumberOfInterfaces)) { + perror("FAILED: shrink_IDE_array"); + return 1; + } + /* Update the fix array. This involves moving the deleted + * entry to the end of the array (rather than deleting it) + * and mapping it to the "replacement" element so we can + * update interface indices appropriately later. + */ + update_fix_array(arena, fix_array, i-1, + totalNumberOfInterfaces, i); + /* Decrement the true number of interfaces since we just + * deleted one. There's more than one way to get out of + * this loop. + */ + trueNumberOfInterfaces--; + } else { + if (!IDE_array[i].interface_descriptor || + (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0)) + { + /* Shrink the IDE_array to delete the duplicate interface. + */ + if (!shrink_IDE_array(IDE_array, + i, + trueNumberOfInterfaces)) { + perror("FAILED: shrink_IDE_array"); + return 1; + } + /* Update the fix array. This involves moving the deleted + * entry to the end of the array (rather than deleting it) + * and mapping it to the "replacement" element so we can + * update interface indices appropriately later. + */ + update_fix_array(arena, fix_array, i, + totalNumberOfInterfaces, i-1); + /* Decrement the true number of interfaces since we just + * deleted one. There's more than one way to get out of + * this loop. + */ + trueNumberOfInterfaces--; + } else { + /* Found interfaces with duplicate names but different + * iids! */ + char *ns = IDE_array[i].name_space; + fprintf(stderr, + "ERROR: found duplicate definitions of interface " + "%s%s%s with iids \n", + ns ? ns : "", ns ? "::" : "", IDE_array[i].name); + print_IID(&IDE_array[i].iid, stderr); + fprintf(stderr, " and "); + print_IID(&IDE_array[i-1].iid, stderr); + fprintf(stderr, "\n"); + return 1; + } + } + } else { + /* Only increment if there was no name_space::name collision. + */ + i++; + } + } + + /* Sort the IDE_array (put them in their final order) so that updating + * of indices will be meaningful. + */ + qsort(IDE_array, + trueNumberOfInterfaces, + sizeof(XPTInterfaceDirectoryEntry), + compare_IDEs_by_IID); + + /* Sort the fix_array to match the IDE_array. + */ + qsort(fix_array, + trueNumberOfInterfaces, + sizeof(fixElement), + compare_fixElements_by_IID); + + /* Iterate through the remaining interfaces (those not deleted) + * looking for references to interfaces (such as id->parent_interface) + * which need an updated index number. + */ + for (i=0; i<trueNumberOfInterfaces; i++) { + + /* Define id to save some keystrokes. + */ + id = IDE_array[i].interface_descriptor; + + /* Check for unresolved interface. + */ + if (id) { + + /* Fix parent_interface first. + */ + if (id->parent_interface && id->parent_interface != 0) { + id->parent_interface = + get_new_index(fix_array, totalNumberOfInterfaces, + fix_array[i].file_num, id->parent_interface); + } + /* Iterate through the method descriptors looking for params of + * type TD_INTERFACE_TYPE. + */ + for (j=0; j<id->num_methods; j++) { + /* Cycle through the params first. + */ + for (k=0; k<id->method_descriptors[j].num_args; k++) { + /* Define td to save some keystrokes. + */ + td = &id->method_descriptors[j].params[k].type; + + while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { + td = &id->additional_types[td->type.additional_type]; + } + + if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) { + td->type.iface = + get_new_index(fix_array, + totalNumberOfInterfaces, + fix_array[i].file_num, + td->type.iface); + } + } + + /* Check the result param too. Define td again to save + * some keystrokes. + */ + td = &id->method_descriptors[j].result->type; + if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) { + td->type.iface = + get_new_index(fix_array, totalNumberOfInterfaces, + fix_array[i].file_num, + td->type.iface); + } + } + } + } + + /* Iterate through the array quickly looking for duplicate IIDS. + * This shouldn't happen, i.e. is a failure condition, so bail + * if we find a duplicate. If we have more than one entry, start + * at one so we don't accidentally grep the ether. + */ + if (trueNumberOfInterfaces>1) { + for (i=1; i<trueNumberOfInterfaces; i++) { + /* Only complain if the IIDs are identical and nonzero. */ + if (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0 && + compare_IDE_with_zero(&IDE_array[i]) != 0) { + fprintf(stderr, "FATAL ERROR:\n" + "Duplicate IID detected ("); + print_IID(&IDE_array[i-1].iid, stderr); + fprintf(stderr, ") in\n" + "interface %s::%s from %s\n" + "and\n" + "interface %s::%s from %s\n", + IDE_array[i-1].name_space ? + IDE_array[i-1].name_space : "", + IDE_array[i-1].name, + argv[fix_array[i-1].file_num+2], + IDE_array[i].name_space ? + IDE_array[i].name_space : "", + IDE_array[i].name, + argv[fix_array[i].file_num+2]); + return 1; + } + } + } + + header = XPT_NewHeader(arena, (PRUint16)trueNumberOfInterfaces, + major_version, minor_version); + + header->annotations = first_ann; + for (i=0; i<trueNumberOfInterfaces; i++) { + if (!copy_IDE(&IDE_array[i], &header->interface_directory[i])) { + perror("FAILED: 2nd copying of IDE"); + return 1; + } + } + + header_sz = XPT_SizeOfHeaderBlock(header); + + state = XPT_NewXDRState(XPT_ENCODE, NULL, 0); + if (!state) { + perror("FAILED: error creating XDRState"); + return 1; + } + + XPT_SetDataOffset(state, header_sz); + + if (!XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor)) { + perror("FAILED: error making cursor"); + return 1; + } + oldOffset = cursor->offset; + if (!XPT_DoHeader(arena, cursor, &header)) { + perror("FAILED: error doing Header"); + return 1; + } + newOffset = cursor->offset; + XPT_GetXDRDataLength(state, XPT_HEADER, &len); + header->file_length = len; + XPT_GetXDRDataLength(state, XPT_DATA, &len); + header->file_length += len; + XPT_SeekTo(cursor, oldOffset); + if (!XPT_DoHeaderPrologue(arena, cursor, &header, NULL)) { + perror("FAILED: error doing Header"); + return 1; + } + XPT_SeekTo(cursor, newOffset); + out = fopen(outFileName, "wb"); + if (!out) { + perror("FAILED: fopen"); + return 1; + } + + XPT_GetXDRData(state, XPT_HEADER, &head, &len); + fwrite(head, len, 1, out); + + XPT_GetXDRData(state, XPT_DATA, &data, &len); + fwrite(data, len, 1, out); + + if (ferror(out) != 0 || fclose(out) != 0) { + fprintf(stderr, "Error writing file: %s\n", argv[1]); + } else { +/* fprintf(stderr, "File written: %s\n", argv[1]); */ + } + + if (state) + XPT_DestroyXDRState(state); + + XPT_DestroyArena(arena); + + return 0; +} + +static int +compare_IDEs_by_IID(const void *ap, + const void *bp) +{ + const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp; + + int answer = compare_IIDs(&ide1->iid, &ide2->iid); + if(!answer) + answer = compare_strings(ide1->name, ide2->name); + + return answer; +} + +/* For detecting unresolved interfaces. */ +const nsID iid_zero = { 0x0, 0x0, 0x0, + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }; + +static int +compare_IDE_with_zero(const void *ap) +{ + const XPTInterfaceDirectoryEntry *ide1 = ap; + + return compare_IIDs(&ide1->iid, &iid_zero); +} + +static int +compare_fixElements_by_IID(const void *ap, + const void *bp) +{ + const fixElement *fix1 = ap, *fix2 = bp; + + int answer = compare_IIDs(&fix1->iid, &fix2->iid); + if(!answer) + answer = compare_strings(fix1->name, fix2->name); + + return answer; +} + +static int +compare_IDEs_by_name(const void *ap, + const void *bp) +{ + const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp; + + int answer = compare_strings(ide1->name, ide2->name); + if(!answer) + answer = compare_pointers(ide1->name, ide2->name); + + return answer; +} + +static int +compare_IDEs_by_name_space(const void *ap, + const void *bp) +{ + const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp; + + return compare_strings(ide1->name_space, ide2->name_space); +} + +static int +compare_strings(const void *ap, const void *bp) +{ + const char *string1 = ap, *string2 = bp; + + if (!string1 && !string2) + return 0; + if (!string1) + return -1; + if (!string2) + return 1; + + return strcmp(string1, string2); +} + +static int +compare_pointers(const void *ap, const void *bp) +{ + if (ap == bp) { +#ifdef DEBUG_jband + perror("name addresses were equal!"); +#endif + return 0; + } + if (ap > bp) + return 1; + return -1; +} + +static int +compare_fixElements_by_name(const void *ap, + const void *bp) +{ + const fixElement *fix1 = ap, *fix2 = bp; + + int answer= compare_strings(fix1->name, fix2->name); + if(!answer) + answer = compare_pointers(fix1->name, fix2->name); + + return answer; +} + +static int +compare_IIDs(const void *ap, const void *bp) +{ + const nsID *a = ap, *b = bp; + int i; +#define COMPARE(field) if (a->field > b->field) return 1; \ + if (b->field > a->field) return -1; + COMPARE(m0); + COMPARE(m1); + COMPARE(m2); + for (i = 0; i < 8; i++) { + COMPARE(m3[i]); + } + return 0; +#undef COMPARE +} + +PRBool +shrink_IDE_array(XPTInterfaceDirectoryEntry *ide, int element_to_delete, + int num_interfaces) +{ + int i; + + if (element_to_delete >= num_interfaces) { + return PR_FALSE; + } + + for (i=element_to_delete+1; i<num_interfaces; i++) { + if (!copy_IDE(&ide[i], &ide[i-1])) { + return PR_FALSE; + } + } + + return PR_TRUE; +} + +/* update_fix_array marks a fixElement as deleted, updates its mapping + * to point to the "replacement" element, and moves it to the end of + * the array. + */ +PRBool +update_fix_array(XPTArena *arena, fixElement *fix, int element_to_delete, + int num_interfaces, int replacement) +{ + fixElement *deleted; + int i; + + if (element_to_delete >= num_interfaces) { + return PR_FALSE; + } + + deleted = XPT_CALLOC(arena, sizeof(fixElement)); + if (!copy_fixElement(&fix[element_to_delete], deleted)) { + return PR_FALSE; + } + deleted->is_deleted = PR_TRUE; + deleted->maps_to_file_num = fix[replacement].file_num; + deleted->maps_to_interface_num = fix[replacement].interface_num; + + for (i=element_to_delete+1; i<num_interfaces; i++) { + if (!copy_fixElement(&fix[i], &fix[i-1])) { + return PR_FALSE; + } + } + + if (!copy_fixElement(deleted, &fix[num_interfaces-1])) { + return PR_FALSE; + } + + return PR_TRUE; +} + +/* get_new_index returns the new interface index by walking the fix_array + * until the file_num and interface_num match the target values. If a match + * is found, it checks to see if that element has been deleted. If it has + * been deleted, it follows that elements mapping until it gets to the + * proper interface (recursion). FYI, Indices are one-based; zero + * represents the special case (no parent interface). + */ +static int +get_new_index(const fixElement *fix, int num_elements, + int target_file, int target_interface) +{ + int i; + + for (i=0; i<num_elements; i++) { + if (fix[i].file_num == target_file && + fix[i].interface_num == target_interface) { + if (fix[i].is_deleted) { + return get_new_index(fix, num_elements, + fix[i].maps_to_file_num, + fix[i].maps_to_interface_num); + } + return i+1; + } + } + + return 0; +} + +PRBool +copy_IDE(XPTInterfaceDirectoryEntry *from, XPTInterfaceDirectoryEntry *to) +{ + if (!from || !to) { + return PR_FALSE; + } + + to->iid = from->iid; + to->name = from->name; + to->name_space = from->name_space; + to->interface_descriptor = from->interface_descriptor; + return PR_TRUE; +} + +PRBool +copy_fixElement(fixElement *from, fixElement *to) +{ + if (!from || !to) { + return PR_FALSE; + } + + to->iid = from->iid; + to->name = from->name; + to->file_num = from->file_num; + to->interface_num = from->interface_num; + to->is_deleted = from->is_deleted; + to->maps_to_file_num = from->maps_to_file_num; + to->maps_to_interface_num = from->maps_to_interface_num; + + return PR_TRUE; +} + +static void +print_IID(struct nsID *iid, FILE *file) +{ + fprintf(file, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (PRUint32) iid->m0, (PRUint32) iid->m1,(PRUint32) iid->m2, + (PRUint32) iid->m3[0], (PRUint32) iid->m3[1], + (PRUint32) iid->m3[2], (PRUint32) iid->m3[3], + (PRUint32) iid->m3[4], (PRUint32) iid->m3[5], + (PRUint32) iid->m3[6], (PRUint32) iid->m3[7]); +} + +static void +xpt_link_usage(char *argv[]) +{ + fprintf(stdout, "Usage: %s [-t version number] outfile file1.xpt file2.xpt ...\n" + " Links multiple typelib files into one outfile\n" + " -t create a typelib of an older version number\n", argv[0]); +} + |