From 16f504a9dca3fe3b70568f67b7d41241ae485288 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 18:49:04 +0200 Subject: Adding upstream version 7.0.6-dfsg. Signed-off-by: Daniel Baumann --- src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore | 2 + src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in | 88 ++ src/libs/xpcom18a4/xpcom/typelib/xpidl/README | 16 + .../xpcom/typelib/xpidl/macplugin/compiler.rsrc | Bin 0 -> 915 bytes .../xpcom/typelib/xpidl/macplugin/linker.rsrc | Bin 0 -> 984 bytes .../xpcom/typelib/xpidl/macplugin/mac_console.c | 139 +++ .../xpcom/typelib/xpidl/macplugin/mac_console.h | 49 + .../xpcom/typelib/xpidl/macplugin/mac_memory.cpp | 146 +++ .../xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp | 58 + .../xpcom/typelib/xpidl/macplugin/mac_strings.cpp | 38 + .../xpcom/typelib/xpidl/macplugin/mac_strings.h | 47 + .../xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp | 417 +++++++ .../xpcom/typelib/xpidl/macplugin/mac_xpidl.h | 25 + .../typelib/xpidl/macplugin/mac_xpidl_panel.cpp | 695 +++++++++++ .../typelib/xpidl/macplugin/mac_xpidl_panel.h | 106 ++ .../typelib/xpidl/macplugin/mac_xpt_linker.cpp | 546 +++++++++ .../xpcom/typelib/xpidl/macplugin/panel.rsrc | Bin 0 -> 16238 bytes .../xpcom/typelib/xpidl/macplugin/version.rsrc | Bin 0 -> 755 bytes src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c | 275 +++++ src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h | 278 +++++ src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c | 312 +++++ .../xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c | 1196 +++++++++++++++++++ src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c | 836 +++++++++++++ .../xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c | 1053 +++++++++++++++++ .../xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c | 1237 ++++++++++++++++++++ .../xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c | 851 ++++++++++++++ 26 files changed, 8410 insertions(+) create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/README create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c create mode 100644 src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c (limited to 'src/libs/xpcom18a4/xpcom/typelib/xpidl') 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 new file mode 100644 index 00000000..fb06f6a3 Binary files /dev/null and b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc differ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc new file mode 100644 index 00000000..bec7c043 Binary files /dev/null and b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc differ 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 +#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 +#include + +#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 +#include + +#include +#include + +#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 +#include +#include + +// 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 +#include +#include + +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 + +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 +#include +#include +#include +#include +#include + +/* system headers */ +#include +#include +#include + +#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 +#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 +#include +#include + +/* system headers */ +#include +#include +#include +#include +#include +#include +#include + +/* compiler headers */ +#include + +/* 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 +#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 +#include +#include + +/* system headers */ +#include +#include +#include +#include + +/* 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 new file mode 100644 index 00000000..c5777088 Binary files /dev/null and b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc differ diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc new file mode 100644 index 00000000..6737d356 Binary files /dev/null and b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc differ 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 +#include +#include +#include +#include +#include /* After glib.h to avoid warnings about shadowing 'index'. */ + +#ifndef XP_MAC +#include +#else +#include +#endif + +#include + +/* + * 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 " *"? */ +#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 () + */ +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, "\n"); + fprintf(state->file, "\n"); + + fprintf(state->file, + "\n", + state->basename); + fprintf(state->file, "documentation for %s.idl interfaces\n", + state->basename); + fprintf(state->file, "\n\n"); + fprintf(state->file, "\n"); + + return TRUE; +} + +static gboolean +doc_epilog(TreeState *state) +{ + fprintf(state->file, "\n"); + fprintf(state->file, "\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, "
    \n"); + while (list != NULL) { + fprintf(outfile, "
  • %s\n", + IDL_IDENT(IDL_LIST(list).data).str); + list = IDL_LIST(list).next; + } + fprintf(outfile, "
\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
\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:
\n"); + fprintf(state->file, "
\n");
+        printlist(state->file, doc_comments);
+        fprintf(state->file, "
\n"); + fprintf(state->file, "
\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:
\n", classname); + print_list(state->file, iter); + fprintf(state->file, "
\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, "
\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
\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 + +#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 + * + * 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 +#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 = ""; + 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 +#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 +#include + + +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 \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 " + */ + + 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 +#include +#include /* 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 : ""); +#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 () + */ +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();''", + 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; +} -- cgit v1.2.3