summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2006-07-28 15:22:29 +0000
committerTom Tromey <tromey@redhat.com>2006-07-28 15:22:29 +0000
commit1df72fb152a2ed319bfe12ae18c3a558e3b12d53 (patch)
treea50a023bd8c959cb589a5a687269c700b1392da3
parentb169e48309762b3f1d3f2a26976968a581e5c7bf (diff)
downloadclasspath-1df72fb152a2ed319bfe12ae18c3a558e3b12d53.tar.gz
* NEWS: Updated.
* .classpath: Updated. * tools/.cvsignore: Added gjavah. * tools/Makefile.am ($(TOOLS_ZIP)): Only build javah if ASM is available. (GLIBJ_CLASSPATH): Add asm jar. (javah): New macro. (bin_PROGRAMS, bin_SCRIPTS): Added $(javah). (gjavah_SOURCES, gjavah_CFLAGS, gjavah_LDFLAGS): new macros. * tools/gjavah.in: New file. * configure.ac: Added --with-asm option. * tools/gnu/classpath/tools/javah/ClassWrapper.java: New file. * tools/gnu/classpath/tools/javah/CniIncludePrinter.java: Likewise. * tools/gnu/classpath/tools/javah/CniPrintStream.java: Likewise. * tools/gnu/classpath/tools/javah/CniStubPrinter.java: Likewise. * tools/gnu/classpath/tools/javah/FieldHelper.java: Likewise. * tools/gnu/classpath/tools/javah/JniHelper.java: Likewise. * tools/gnu/classpath/tools/javah/JniIncludePrinter.java: Likewise. * tools/gnu/classpath/tools/javah/JniStubPrinter.java: Likewise. * tools/gnu/classpath/tools/javah/Keywords.java: Likewise. * tools/gnu/classpath/tools/javah/Main.java: Likewise. * tools/gnu/classpath/tools/javah/MethodHelper.java: Likewise. * tools/gnu/classpath/tools/javah/PackageWrapper.java: Likewise. * tools/gnu/classpath/tools/javah/PathOptionGroup.java: Likewise. * tools/gnu/classpath/tools/javah/Printer.java: Likewise. * tools/gnu/classpath/tools/javah/Text.java: Likewise.
-rw-r--r--.classpath2
-rw-r--r--ChangeLog29
-rw-r--r--NEWS6
-rw-r--r--configure.ac35
-rw-r--r--tools/.cvsignore1
-rwxr-xr-xtools/Makefile.am30
-rw-r--r--tools/gjavah.in47
-rw-r--r--tools/gnu/classpath/tools/javah/ClassWrapper.java341
-rw-r--r--tools/gnu/classpath/tools/javah/CniIncludePrinter.java69
-rw-r--r--tools/gnu/classpath/tools/javah/CniPrintStream.java243
-rw-r--r--tools/gnu/classpath/tools/javah/CniStubPrinter.java119
-rw-r--r--tools/gnu/classpath/tools/javah/FieldHelper.java97
-rw-r--r--tools/gnu/classpath/tools/javah/JniHelper.java120
-rw-r--r--tools/gnu/classpath/tools/javah/JniIncludePrinter.java144
-rw-r--r--tools/gnu/classpath/tools/javah/JniPrintStream.java115
-rw-r--r--tools/gnu/classpath/tools/javah/JniStubPrinter.java98
-rw-r--r--tools/gnu/classpath/tools/javah/Keywords.java85
-rw-r--r--tools/gnu/classpath/tools/javah/Main.java375
-rw-r--r--tools/gnu/classpath/tools/javah/MethodHelper.java130
-rw-r--r--tools/gnu/classpath/tools/javah/PackageWrapper.java54
-rw-r--r--tools/gnu/classpath/tools/javah/PathOptionGroup.java135
-rw-r--r--tools/gnu/classpath/tools/javah/Printer.java55
-rw-r--r--tools/gnu/classpath/tools/javah/Text.java60
23 files changed, 2380 insertions, 10 deletions
diff --git a/.classpath b/.classpath
index d89a8d1c4..6f1883b80 100644
--- a/.classpath
+++ b/.classpath
@@ -2,7 +2,7 @@
<classpath>
<classpathentry excluding=".externalToolBuilders/|.settings/|ChangeLog*|Makefile*|autom4te.cache/|compat/|config*|doc/|examples/|external/|external/relaxngDatatype/|include/|install/|lib/|m4/|native/|resource/|scripts/|test/|testsuite/|tools/|vm/reference/|gnu/java/awt/peer/x/" kind="src" path=""/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README.txt" kind="src" path="external/relaxngDatatype"/>
- <classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README" kind="src" path="tools"/>
+ <classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README|gnu/classpath/tools/javah/" kind="src" path="tools"/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in" kind="src" path="resource"/>
<classpathentry excluding=".cvsignore|Makefile.am" kind="src" path="vm/reference"/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README" kind="src" path="external/sax"/>
diff --git a/ChangeLog b/ChangeLog
index 8960c1d5f..0193339ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2006-07-28 Tom Tromey <tromey@redhat.com>
+
+ * NEWS: Updated.
+ * .classpath: Updated.
+ * tools/.cvsignore: Added gjavah.
+ * tools/Makefile.am ($(TOOLS_ZIP)): Only build javah if ASM is
+ available.
+ (GLIBJ_CLASSPATH): Add asm jar.
+ (javah): New macro.
+ (bin_PROGRAMS, bin_SCRIPTS): Added $(javah).
+ (gjavah_SOURCES, gjavah_CFLAGS, gjavah_LDFLAGS): new macros.
+ * tools/gjavah.in: New file.
+ * configure.ac: Added --with-asm option.
+ * tools/gnu/classpath/tools/javah/ClassWrapper.java: New file.
+ * tools/gnu/classpath/tools/javah/CniIncludePrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/CniPrintStream.java: Likewise.
+ * tools/gnu/classpath/tools/javah/CniStubPrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/FieldHelper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/JniHelper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/JniIncludePrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/JniStubPrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Keywords.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Main.java: Likewise.
+ * tools/gnu/classpath/tools/javah/MethodHelper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/PackageWrapper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/PathOptionGroup.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Printer.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Text.java: Likewise.
+
2006-07-28 Anthony Balkissoon <abalkiss@redhat.com>
* java/awt/List.java: Committed following patch from Tania.
diff --git a/NEWS b/NEWS
index 402dfc011..ab703e671 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+New in release 0.93 (UNRELEASED)
+
+* The 'javah' tool has been added. It requires the ASM library
+ (see asm.objectweb.org); it can be enabled with the --with-asm
+ option to configure
+
New in release 0.92 (UNRELEASED)
* libjawtgnu.so has been renamed libjawt.so for binary compatibility.
diff --git a/configure.ac b/configure.ac
index 14911bad3..0461faa62 100644
--- a/configure.ac
+++ b/configure.ac
@@ -730,18 +730,43 @@ case "$with_escher" in
use_escher=false
;;
"yes")
- AC_MSG_ERROR([Please suply an absolute path to Escher library])
+ AC_MSG_ERROR([Please supply an absolute path to Escher library])
;;
*)
use_escher=true
PATH_TO_ESCHER=$with_escher
;;
-esac;
+esac
AM_CONDITIONAL(USE_ESCHER, test x$use_escher = xtrue)
AC_SUBST(PATH_TO_ESCHER)
dnl -----------------------------------------------------------
+dnl Build javah using ASM library
+dnl -----------------------------------------------------------
+AC_ARG_WITH([asm],
+ AS_HELP_STRING([--with-asm=ABS.PATH],
+ [specify path to ASM jar for javah]))
+case "$with_asm" in
+"")
+ use_asm=false
+ ;;
+"no")
+ use_asm=false
+ ;;
+"yes")
+ AC_MSG_ERROR([Please supply an absolute path to ASM jar])
+ ;;
+*)
+ use_asm=true
+ PATH_TO_ASM=$with_asm
+ ;;
+esac
+
+AM_CONDITIONAL(USE_ASM, test x$use_asm = xtrue)
+AC_SUBST(PATH_TO_ASM)
+
+dnl -----------------------------------------------------------
dnl Check if local socket support should be included.
dnl -----------------------------------------------------------
AC_ARG_ENABLE([local-sockets],
@@ -828,6 +853,11 @@ AC_CONFIG_COMMANDS([gkeytool],[chmod 755 tools/gkeytool])
AC_CONFIG_COMMANDS([gjar],[chmod 755 tools/gjar])
AC_CONFIG_COMMANDS([gnative2ascii],[chmod 755 tools/gnative2ascii])
AC_CONFIG_COMMANDS([gserialver],[chmod 755 tools/gserialver])
+
+ if test "$use_asm" = true; then
+ AC_CONFIG_FILES([tools/gjavah])
+ AC_CONFIG_COMMANDS([gjavah], [chmod 755 tools/gjavah])
+ fi
fi
AC_CONFIG_COMMANDS([gen-classlist],[chmod 755 lib/gen-classlist.sh])
@@ -839,4 +869,3 @@ cat ${srcdir}/lib/standard.omit.in > lib/standard.omit
if test x$use_escher != xtrue; then
echo gnu/java/awt/peer/x/.*java$ >> lib/standard.omit
fi
-
diff --git a/tools/.cvsignore b/tools/.cvsignore
index 8dce53527..49dfefd00 100644
--- a/tools/.cvsignore
+++ b/tools/.cvsignore
@@ -11,3 +11,4 @@ gkeytool
gjar
gnative2ascii
gserialver
+gjavah
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 2204daef3..e4e9200d2 100755
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,6 +1,6 @@
## Input file for automake to generate the Makefile.in used by configure
-GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
+GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip':$(PATH_TO_ASM)
# Setup the compiler to use the GNU Classpath library we just build
if FOUND_GCJ
@@ -21,10 +21,14 @@ endif
endif
endif
+if USE_ASM
+javah = gjavah
+endif
+
if CREATE_WRAPPERS
bin_SCRIPTS =
bin_PROGRAMS = gappletviewer gjarsigner gkeytool \
- gjar gnative2ascii gserialver
+ gjar gnative2ascii gserialver $(javah)
if FOUND_GCJ
LIBJVM = -lgcj
@@ -76,13 +80,21 @@ gserialver_CFLAGS = \
-DTOOLNAME="\"gserialver\""
gserialver_LDFLAGS = -L$(libdir) $(LIBJVM)
+if USE_ASM
+gjavah_SOURCES = toolwrapper.c
+gjavah_CFLAGS = \
+ -DTOOLPACKAGE="\"javah\"" \
+ -DTOOLNAME="\"gjavah\""
+gjavah_LDFLAGS = -L$(libdir) $(LIBJVM)
+endif
+
else
bin_SCRIPTS = gappletviewer gjarsigner gkeytool \
- gjar gnative2ascii gserialver
+ gjar gnative2ascii gserialver $(javah)
bin_PROGRAMS =
endif
EXTRA_DIST = toolwrapper.c gappletviewer.in gjarsigner.in gkeytool.in \
- gjar.in gnative2ascii.in gserialver.in
+ gjar.in gnative2ascii.in gserialver.in gjavah.in
# All our example java source files
TOOLS_JAVA_FILES = $(srcdir)/gnu/classpath/tools/*.java $(srcdir)/gnu/classpath/tools/*/*.java $(srcdir)/gnu/classpath/tools/*/*/*.java
@@ -145,12 +157,18 @@ $(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
cp $(GRMIC_TEMPLATES) classes/gnu/classpath/tools/giop/grmic/templates
cp $(RMI_HELPS) classes/gnu/classpath/tools/rmi/
cp $(GIOP_HELPS) classes/gnu/classpath/tools/giop/
- $(JCOMPILER) -d classes $(TOOLS_JAVA_FILES)
+ find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst
+ if test -z "$(PATH_TO_ASM)"; then \
+ mv classes.lst classes.tmp; \
+ fgrep -v /javah/ classes.tmp > classes.lst; \
+ rm -f classes.tmp;\
+ fi
+ $(JCOMPILER) -d classes @classes.lst
(cd classes; \
if test "$(ZIP)" != ""; then $(ZIP) -r ../$(TOOLS_ZIP) .; fi; \
if test "$(FASTJAR)" != ""; then $(FASTJAR) cf ../$(TOOLS_ZIP) .; fi; \
cd ..)
- rm -rf classes
+ rm -rf classes classes.lst
# Zip file be gone! (and make sure the classes are gone too)
clean-local:
diff --git a/tools/gjavah.in b/tools/gjavah.in
new file mode 100644
index 000000000..0505bdbc2
--- /dev/null
+++ b/tools/gjavah.in
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+## Copyright (C) 2006 Free Software Foundation, Inc.
+##
+## This file is a part of GNU Classpath.
+##
+## GNU Classpath is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or (at
+## your option) any later version.
+##
+## GNU Classpath is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with GNU Classpath; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+## USA.
+##
+## Linking this library statically or dynamically with other modules is
+## making a combined work based on this library. Thus, the terms and
+## conditions of the GNU General Public License cover the whole
+## combination.
+##
+## As a special exception, the copyright holders of this library give you
+## permission to link this library with independent modules to produce an
+## executable, regardless of the license terms of these independent
+## modules, and to copy and distribute the resulting executable under
+## terms of your choice, provided that you also meet, for each linked
+## independent module, the terms and conditions of the license of that
+## module. An independent module is a module which is not derived from
+## or based on this library. If you modify this library, you may extend
+## this exception to your version of the library, but you are not
+## obligated to do so. If you do not wish to do so, delete this
+## exception statement from your version.
+##
+##
+## A simple shell script to launch the GNU Classpath javah tool.
+##
+
+prefix=@prefix@
+tools_dir=@datadir@/@PACKAGE@
+tools_cp=${tools_dir}/tools.zip:@PATH_TO_ASM@
+
+exec @VM_BINARY@ -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.javah.Main "$@"
diff --git a/tools/gnu/classpath/tools/javah/ClassWrapper.java b/tools/gnu/classpath/tools/javah/ClassWrapper.java
new file mode 100644
index 000000000..778896395
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/ClassWrapper.java
@@ -0,0 +1,341 @@
+/* ClassWrapper.java - wrap ASM class objects
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public class ClassWrapper
+ extends ClassNode
+{
+ Main classpath;
+
+ ClassWrapper superClass;
+
+ ArrayList interfaceClasses;
+
+ // The virtual table for this class.
+ ArrayList vtable;
+
+ // A set of all the bridge method targets we've found.
+ HashSet bridgeTargets;
+
+ // A set of all the method names in this class.
+ HashSet methodNames = new HashSet();
+
+ public ClassWrapper(Main classpath)
+ {
+ this.classpath = classpath;
+ }
+
+ public boolean hasNativeMethod()
+ {
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (Modifier.isNative(method.access))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isThrowable() throws IOException
+ {
+ linkSupers();
+ ClassWrapper self = this;
+ while (self != null)
+ {
+ if (self.name.equals("java/lang/Throwable"))
+ return true;
+ self = self.superClass;
+ }
+ return false;
+ }
+
+ private void linkSupers() throws IOException
+ {
+ if (superName == null)
+ {
+ // Object, do nothing.
+ return;
+ }
+ if (superClass == null)
+ {
+ superClass = classpath.getClass(superName);
+ assert interfaceClasses == null;
+ interfaceClasses = new ArrayList();
+ for (int i = 0; i < interfaces.size(); ++i)
+ {
+ String ifname = (String) interfaces.get(i);
+ ClassWrapper iface = classpath.getClass(ifname);
+ iface.linkSupers();
+ interfaceClasses.add(iface);
+ }
+ }
+ superClass.linkSupers();
+ }
+
+ private int findSlot(MethodNode method)
+ {
+ for (int i = vtable.size() - 1; i >= 0; --i)
+ {
+ MethodNode base = (MethodNode) vtable.get(i);
+ if (MethodHelper.overrides(method, base))
+ return i;
+ }
+ return - 1;
+ }
+
+ private void addInterfaceMethods(ClassWrapper iface)
+ {
+ Iterator i = iface.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode im = (MethodNode) i.next();
+ int slot = findSlot(im);
+ if (slot == - 1)
+ {
+ vtable.add(im);
+ // Also add it to our local methods.
+ methods.add(im);
+ }
+ }
+ addInterfaces(iface);
+ }
+
+ private void addInterfaces(ClassWrapper base)
+ {
+ if (base.interfaceClasses == null)
+ return;
+ Iterator i = base.interfaceClasses.iterator();
+ while (i.hasNext())
+ {
+ ClassWrapper iface = (ClassWrapper) i.next();
+ addInterfaceMethods(iface);
+ }
+ }
+
+ private void addLocalMethods()
+ {
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode meth = (MethodNode) i.next();
+ methodNames.add(meth.name);
+ if (Modifier.isStatic(meth.access))
+ continue;
+ int slot = findSlot(meth);
+ if (slot == - 1)
+ vtable.add(meth);
+ else
+ vtable.set(slot, meth);
+ }
+ }
+
+ private void makeVtable() throws IOException
+ {
+ if (vtable != null)
+ return;
+ if (superClass != null)
+ {
+ superClass.makeVtable();
+ vtable = new ArrayList(superClass.vtable);
+ bridgeTargets = new HashSet(superClass.bridgeTargets);
+ }
+ else
+ {
+ // Object.
+ vtable = new ArrayList();
+ bridgeTargets = new HashSet();
+ }
+ addLocalMethods();
+ addInterfaces(this);
+
+ // Make a set of all the targets of bridge methods.
+ // We rename bridge methods to avoid problems with C++.
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode m = (MethodNode) i.next();
+ String desc = MethodHelper.getBridgeTarget(m);
+ if (desc != null)
+ bridgeTargets.add(m.name + desc);
+ }
+ }
+
+ private void printFields(CniPrintStream out)
+ {
+ Iterator i = fields.iterator();
+ ClassWrapper self = superClass;
+ while (i.hasNext())
+ {
+ FieldNode f = (FieldNode) i.next();
+ boolean hasMethodName = methodNames.contains(f.name);
+ if (FieldHelper.print(out, f, self, hasMethodName))
+ self = null;
+ }
+ }
+
+ private void printMethods(CniPrintStream out) throws IOException
+ {
+ makeVtable();
+
+ // A given method is either static, overrides a super method, or
+ // is already in vtable order.
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode m = (MethodNode) i.next();
+ boolean isTarget = bridgeTargets.contains(m.name + m.desc);
+ MethodHelper.print(out, m, this, isTarget);
+ }
+ }
+
+ private void printTextList(PrintStream out, int what, ArrayList textList)
+ {
+ if (textList == null)
+ return;
+ Iterator i = textList.iterator();
+ boolean first = true;
+ while (i.hasNext())
+ {
+ Text item = (Text) i.next();
+ if (item.type == what)
+ {
+ if (first)
+ {
+ out.println();
+ first = false;
+ }
+ if (what == Text.FRIEND)
+ out.print(" friend ");
+ out.println(item.text);
+ }
+ }
+ }
+
+ public void print(CniPrintStream out)
+ {
+ out.print("::" + name.replaceAll("/", "::"));
+ }
+
+ // This prints the body of a class to a CxxPrintStream.
+ private void printContents(CniPrintStream out, ArrayList textList)
+ throws IOException
+ {
+ printTextList(out, Text.PREPEND, textList);
+ out.println();
+
+ out.print("class ");
+ // Don't use our print() -- we don't want the leading "::".
+ out.print(name.replaceAll("/", "::"));
+ if (superClass != null)
+ {
+ out.print(" : public ");
+ superClass.print(out);
+ }
+ out.println();
+ out.println("{");
+
+ printTextList(out, Text.ADD, textList);
+ out.println();
+
+ // Note: methods must come first, as we build the list
+ // of method names while printing them.
+ printMethods(out);
+ printFields(out);
+
+ out.setModifiers(Modifier.PUBLIC);
+ out.println(" static ::java::lang::Class class$;");
+
+ printTextList(out, Text.FRIEND, textList);
+
+ out.print("}");
+ if (Modifier.isInterface(access))
+ out.print(" __attribute__ ((java_interface))");
+ out.println(";");
+
+ printTextList(out, Text.APPEND, textList);
+ }
+
+ public void printFully(PrintStream out) throws IOException
+ {
+ linkSupers();
+
+ ArrayList textList = classpath.getClassTextList(name);
+
+ out.println("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-");
+ out.println();
+ String xname = "__" + name.replaceAll("/", "_") + "__";
+ out.println("#ifndef " + xname);
+ out.println("#define " + xname);
+ out.println();
+ out.println("#pragma interface");
+ out.println();
+
+ if (superClass != null)
+ {
+ out.print("#include <");
+ out.print(superName);
+ out.println(".h>");
+ }
+
+ // Write the body of the stream here. This lets
+ // us emit the namespaces without a second pass.
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ CniPrintStream cxxOut = new CniPrintStream(bytes);
+ cxxOut.addClass(this);
+ printContents(cxxOut, textList);
+ cxxOut.printNamespaces(out);
+ bytes.writeTo(out);
+
+ out.println();
+ out.println("#endif // " + xname);
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/CniIncludePrinter.java b/tools/gnu/classpath/tools/javah/CniIncludePrinter.java
new file mode 100644
index 000000000..6561169bb
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/CniIncludePrinter.java
@@ -0,0 +1,69 @@
+/* CniIncludePrinter.java - generate CNI header files
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class CniIncludePrinter
+ extends Printer
+{
+
+ protected CniIncludePrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ // Never write Object or Class. This is a hack, maybe
+ // the user would like to see what they look like...
+ if (klass.name.equals("java/lang/Object")
+ || klass.name.equals("java/lang/Class"))
+ return;
+ File klassFile = new File(outputDir, klass.name + ".h");
+ klassFile.getParentFile().mkdirs();
+ PrintStream ps = new PrintStream(new FileOutputStream(klassFile));
+ klass.printFully(ps);
+ ps.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/CniPrintStream.java b/tools/gnu/classpath/tools/javah/CniPrintStream.java
new file mode 100644
index 000000000..574d7fd5f
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/CniPrintStream.java
@@ -0,0 +1,243 @@
+/* CniPrintStream.java - PrintStream that emits CNI declarations
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.objectweb.asm.Type;
+
+public class CniPrintStream
+ extends PrintStream
+{
+ int currentModifiers = Modifier.PRIVATE;
+
+ // True if we saw an array type.
+ boolean sawArray;
+
+ // All the classes referenced by this header.
+ HashSet allClasses = new HashSet();
+
+ String[] previousPackage = new String[0];
+
+ public CniPrintStream(OutputStream out)
+ {
+ super(out);
+ }
+
+ public void addClass(ClassWrapper cw)
+ {
+ allClasses.add(cw.name);
+ }
+
+ public void setModifiers(int newMods)
+ {
+ newMods &= (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE);
+ if (newMods != currentModifiers)
+ {
+ switch (newMods)
+ {
+ case Modifier.PUBLIC:
+ println("public:");
+ break;
+ case Modifier.PROTECTED:
+ println("public: // actually protected");
+ break;
+ case Modifier.PRIVATE:
+ println("private:");
+ break;
+ default:
+ println("public: // actually package-private");
+ break;
+ }
+ currentModifiers = newMods;
+ }
+ }
+
+ private String getName(Type type)
+ {
+ if (type == Type.BOOLEAN_TYPE)
+ return "jboolean";
+ else if (type == Type.BYTE_TYPE)
+ return "jbyte";
+ else if (type == Type.CHAR_TYPE)
+ return "jchar";
+ else if (type == Type.SHORT_TYPE)
+ return "jshort";
+ else if (type == Type.INT_TYPE)
+ return "jint";
+ else if (type == Type.LONG_TYPE)
+ return "jlong";
+ else if (type == Type.FLOAT_TYPE)
+ return "jfloat";
+ else if (type == Type.DOUBLE_TYPE)
+ return "jdouble";
+ else
+ {
+ assert type == Type.VOID_TYPE;
+ return "void";
+ }
+ }
+
+ public String getClassName(Type type)
+ {
+ String name = type.toString();
+ name = name.substring(1, name.length() - 1);
+ // Add the plain class name; we'll handle it when
+ // we process namespaces.
+ allClasses.add(name);
+ return "::" + name.replaceAll("/", "::") + " *";
+ }
+
+ public void print(Type type)
+ {
+ int arrayCount = 0;
+ if (type.getSort() == Type.ARRAY)
+ {
+ arrayCount = type.getDimensions();
+ for (int i = 0; i < arrayCount; ++i)
+ print("JArray< ");
+ type = type.getElementType();
+ sawArray = true;
+ }
+ if (type.getSort() == Type.OBJECT)
+ {
+ print(getClassName(type));
+ }
+ else
+ {
+ print(getName(type));
+ }
+ if (arrayCount > 0)
+ {
+ while (arrayCount-- > 0)
+ {
+ print(" > *");
+ }
+ }
+ }
+
+ private void indent(PrintStream out, int n)
+ {
+ for (int i = 0; i < n; ++i)
+ {
+ out.print(" ");
+ }
+ }
+
+ private void moveToPackage(PrintStream out, String[] pkgParts)
+ {
+ // Find greatest common part.
+ int commonIndex;
+ for (commonIndex = 0; commonIndex < previousPackage.length; ++commonIndex)
+ {
+ if (commonIndex >= pkgParts.length)
+ break;
+ if (! previousPackage[commonIndex].equals(pkgParts[commonIndex]))
+ break;
+ }
+ // Close old parts after the common part.
+ for (int j = previousPackage.length - 1; j >= commonIndex; --j)
+ {
+ indent(out, j + 1);
+ out.println("}");
+ }
+ // Open new parts.
+ for (int j = commonIndex; j < pkgParts.length; ++j)
+ {
+ indent(out, j + 1);
+ out.print("namespace ");
+ out.println(pkgParts[j]);
+ indent(out, j + 1);
+ out.println("{");
+ }
+ previousPackage = pkgParts;
+ }
+
+ private void writeClass(PrintStream out, String klass)
+ {
+ int index = klass.lastIndexOf('/');
+ String pkg = klass.substring(0, index);
+ String[] pkgParts = pkg.split("/");
+ String className = klass.substring(index + 1);
+ moveToPackage(out, pkgParts);
+ indent(out, pkgParts.length + 2);
+ out.print("class ");
+ out.print(className);
+ out.println(";");
+ }
+
+ public void printNamespaces(PrintStream out)
+ {
+ if (sawArray)
+ {
+ out.println("#include <gcj/array.h>");
+ out.println();
+ }
+
+ String[] classes = (String[]) allClasses.toArray(new String[0]);
+ Arrays.sort(classes);
+
+ boolean first = true;
+ boolean seen = false;
+ for (int i = 0; i < classes.length; ++i)
+ {
+ String klass = classes[i];
+ if (klass.startsWith("java/lang/") || klass.startsWith("java/io/")
+ || klass.startsWith("java/util/"))
+ continue;
+ if (first)
+ {
+ out.println("extern \"Java\"");
+ out.println("{");
+ first = false;
+ seen = true;
+ }
+ writeClass(out, klass);
+ }
+ if (seen)
+ {
+ moveToPackage(out, new String[0]);
+ out.println("}");
+ }
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/CniStubPrinter.java b/tools/gnu/classpath/tools/javah/CniStubPrinter.java
new file mode 100644
index 000000000..9732e2941
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/CniStubPrinter.java
@@ -0,0 +1,119 @@
+/* CniStubPrinter.java - Generate a CNI stub file
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+public class CniStubPrinter
+ extends Printer
+{
+
+ protected CniStubPrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ private void printDecl(CniPrintStream out, String className, MethodNode method)
+ {
+ out.print(className);
+ out.print("::");
+ out.print(method.name);
+ out.print("(");
+ Type[] argTypes = Type.getArgumentTypes(method.desc);
+ for (int j = 0; j < argTypes.length; ++j)
+ {
+ if (j > 0)
+ out.print(", ");
+ out.print(argTypes[j]);
+ }
+ out.print(")");
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ if (! klass.hasNativeMethod())
+ return;
+ File klassFile = new File(outputDir, klass.name + ".cc");
+ klassFile.getParentFile().mkdirs();
+ String className = klass.name.replaceAll("/", "::");
+
+ CniPrintStream out = new CniPrintStream(new FileOutputStream(klassFile));
+ out.println("// This file is intended to give you a head start on implementing native");
+ out.println("// methods using CNI.");
+ out.println("// Be aware: running 'gcjh -stubs' once more for this class may");
+ out.println("// overwrite any edits you have made to this file.");
+ out.println();
+
+ out.println("#include <" + klass.name + ".h>");
+ out.println("#include <gcj/cni.h>");
+ out.println("#include <java/lang/UnsupportedOperationException.h>");
+ out.println();
+
+ Iterator i = klass.methods.iterator();
+ boolean first = true;
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ if (! first)
+ out.println();
+ first = false;
+ out.print(Type.getReturnType(method.desc));
+ out.println();
+ printDecl(out, className, method);
+ out.println();
+ out.println("{");
+ out.print(" throw new ::java::lang::UnsupportedOperationException(");
+ out.print("JvNewStringLatin1 (\"");
+ printDecl(out, className, method);
+ out.println("\"));");
+ out.println("}");
+ }
+ out.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/FieldHelper.java b/tools/gnu/classpath/tools/javah/FieldHelper.java
new file mode 100644
index 000000000..ecc82e3c1
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/FieldHelper.java
@@ -0,0 +1,97 @@
+/* FieldHelper.java - field helper methods for CNI
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.lang.reflect.Modifier;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.FieldNode;
+
+public class FieldHelper
+{
+ public static boolean print(CniPrintStream out, FieldNode field,
+ ClassWrapper superType, boolean hasMethodName)
+ {
+ out.setModifiers(field.access);
+ out.print(" ");
+ if (Modifier.isStatic(field.access))
+ out.print("static ");
+ if ((field.value instanceof Integer) || (field.value instanceof Long))
+ out.print("const ");
+ out.print(Type.getType(field.desc));
+ out.print(" ");
+ boolean result = false;
+ if (superType != null && ! Modifier.isStatic(field.access))
+ {
+ out.print("__attribute__((aligned(__alignof__( ");
+ superType.print(out);
+ out.print(")))) ");
+ result = true;
+ }
+ out.print(Keywords.getCxxName(field.name));
+ if (hasMethodName)
+ out.print("__");
+ if (Modifier.isStatic(field.access))
+ {
+ if (field.value instanceof Integer)
+ {
+ out.print(" = ");
+ int val = ((Integer) field.value).intValue();
+ if (val == Integer.MIN_VALUE)
+ out.print("-" + Integer.MAX_VALUE + " - 1");
+ else
+ out.print(val);
+ }
+ else if (field.value instanceof Long)
+ {
+ out.print(" = ");
+ long val = ((Long) field.value).longValue();
+ if (val == Long.MIN_VALUE)
+ out.print("-" + Long.MAX_VALUE + "LL - 1");
+ else
+ {
+ out.print(val);
+ out.print("LL");
+ }
+ }
+ }
+ out.println(";");
+ return result;
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/JniHelper.java b/tools/gnu/classpath/tools/javah/JniHelper.java
new file mode 100644
index 000000000..3104cea5a
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniHelper.java
@@ -0,0 +1,120 @@
+/* JniHelper.java - name mangling and other JNI support
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.IOException;
+
+import org.objectweb.asm.Type;
+
+public class JniHelper
+{
+ public static String getName(Main classpath, Type type) throws IOException
+ {
+ if (type == Type.BOOLEAN_TYPE)
+ return "jboolean";
+ else if (type == Type.BYTE_TYPE)
+ return "jbyte";
+ else if (type == Type.CHAR_TYPE)
+ return "jchar";
+ else if (type == Type.SHORT_TYPE)
+ return "jshort";
+ else if (type == Type.INT_TYPE)
+ return "jint";
+ else if (type == Type.LONG_TYPE)
+ return "jlong";
+ else if (type == Type.FLOAT_TYPE)
+ return "jfloat";
+ else if (type == Type.DOUBLE_TYPE)
+ return "jdouble";
+ else if (type == Type.VOID_TYPE)
+ return "void";
+
+ if (type.getSort() == Type.ARRAY)
+ {
+ Type elt = type.getElementType();
+ int eltSort = elt.getSort();
+ if (eltSort != Type.OBJECT && eltSort != Type.ARRAY)
+ return getName(classpath, elt) + "Array";
+ return "jarray";
+ }
+
+ assert type.getSort() == Type.OBJECT;
+ String className = type.getClassName();
+ // FIXME: is this correct?
+ if (className.equals("java/lang/Class")
+ || className.equals("java.lang.Class"))
+ return "jclass";
+ if (className.equals("java/lang/String")
+ || className.equals("java.lang.String"))
+ return "jstring";
+
+ ClassWrapper klass = classpath.getClass(className);
+ if (klass.isThrowable())
+ return "jthrowable";
+ return "jobject";
+ }
+
+ public static String mangle(String name)
+ {
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < name.length(); ++i)
+ {
+ char c = name.charAt(i);
+ if (c == '_')
+ result.append("_1");
+ else if (c == ';')
+ result.append("_2");
+ else if (c == '[')
+ result.append("_3");
+ else if (c == '/')
+ result.append("_");
+ else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z'))
+ result.append(c);
+ else
+ {
+ result.append("_0");
+ // Sigh.
+ String hex = "0000" + Integer.toHexString(c);
+ result.append(hex.substring(hex.length() - 4));
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/JniIncludePrinter.java b/tools/gnu/classpath/tools/javah/JniIncludePrinter.java
new file mode 100644
index 000000000..36ab33bc1
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniIncludePrinter.java
@@ -0,0 +1,144 @@
+/* JniIncludePrinter.java - Generate a JNI header file
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public class JniIncludePrinter
+ extends Printer
+{
+
+ protected JniIncludePrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ private void writeFields(ClassWrapper klass, JniPrintStream out)
+ {
+ boolean wroteAny = false;
+ for (; klass != null; klass = klass.superClass)
+ {
+ Iterator i = klass.fields.iterator();
+ while (i.hasNext())
+ {
+ FieldNode field = (FieldNode) i.next();
+ if (! Modifier.isStatic(field.access)
+ || ! Modifier.isFinal(field.access) || field.value == null)
+ continue;
+ String name = (JniHelper.mangle(klass.name) + "_" + JniHelper.mangle(field.name));
+ out.print("#undef ");
+ out.println(name);
+ out.print("#define ");
+ out.print(name);
+ out.print(" ");
+ out.print(field.value);
+ if (field.value instanceof Long)
+ out.print("LL");
+ out.println();
+ wroteAny = true;
+ }
+ }
+ if (wroteAny)
+ out.println();
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ if (! klass.hasNativeMethod())
+ return;
+ String xname = JniHelper.mangle(klass.name);
+ File outFile = new File(outputDir, xname + ".h");
+
+ JniPrintStream out = new JniPrintStream(classpath,
+ new FileOutputStream(outFile),
+ klass);
+ out.println("/* DO NOT EDIT THIS FILE - it is machine generated */");
+ out.println();
+ out.print("#ifndef __");
+ out.print(xname);
+ out.println("__");
+ out.print("#define __");
+ out.print(xname);
+ out.println("__");
+ out.println();
+ out.println("#include <jni.h>");
+ out.println();
+ out.println("#ifdef __cplusplus");
+ out.println("extern \"C\"");
+ out.println("{");
+ out.println("#endif");
+ out.println();
+
+ Iterator i = klass.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ out.print("JNIEXPORT ");
+ out.print(Type.getReturnType(method.desc));
+ out.print(" JNICALL ");
+ out.print(method, xname);
+ out.println(";");
+ }
+
+ out.println();
+
+ writeFields(klass, out);
+
+ out.println("#ifdef __cplusplus");
+ out.println("}");
+ out.println("#endif");
+ out.println();
+ out.print("#endif /* __");
+ out.print(xname);
+ out.println("__ */");
+
+ out.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/JniPrintStream.java b/tools/gnu/classpath/tools/javah/JniPrintStream.java
new file mode 100644
index 000000000..a0461f475
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniPrintStream.java
@@ -0,0 +1,115 @@
+/* JniPrintStream.java - PrintStream that emits JNI declarations
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+public class JniPrintStream
+ extends PrintStream
+{
+ Main classpath;
+
+ // This is used to determine whether a method has an overload.
+ HashMap methodNameMap = new HashMap();
+
+ public JniPrintStream(Main classpath, OutputStream out, ClassWrapper klass)
+ {
+ super(out);
+ this.classpath = classpath;
+ computeOverloads(klass);
+ }
+
+ private void computeOverloads(ClassWrapper klass)
+ {
+ Iterator i = klass.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ if (methodNameMap.containsKey(method.name))
+ {
+ Integer val = (Integer) methodNameMap.get(method.name);
+ methodNameMap.put(method.name, new Integer(val.intValue() + 1));
+ }
+ else
+ methodNameMap.put(method.name, new Integer(1));
+ }
+ }
+
+ public void print(Type type) throws IOException
+ {
+ print(JniHelper.getName(classpath, type));
+ }
+
+ public void print(MethodNode method, String className) throws IOException
+ {
+ print("Java_");
+ print(className);
+ print("_");
+ print(JniHelper.mangle(method.name));
+ Integer overloadCount = (Integer) methodNameMap.get(method.name);
+ if (overloadCount.intValue() > 1)
+ {
+ print("__");
+ int lastOffset = method.desc.lastIndexOf(')');
+ print(JniHelper.mangle(method.desc.substring(1, lastOffset)));
+ }
+ print(" (JNIEnv *env");
+ if (Modifier.isStatic(method.access))
+ print(", jclass");
+ else
+ print(", jobject");
+ Type[] types = Type.getArgumentTypes(method.desc);
+ for (int i = 0; i < types.length; ++i)
+ {
+ print(", ");
+ print(types[i]);
+ }
+ print(")");
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/JniStubPrinter.java b/tools/gnu/classpath/tools/javah/JniStubPrinter.java
new file mode 100644
index 000000000..d590a5cd1
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniStubPrinter.java
@@ -0,0 +1,98 @@
+/* JniStubPrinter.java - Generate JNI stub files
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+public class JniStubPrinter
+ extends Printer
+{
+
+ protected JniStubPrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ if (! klass.hasNativeMethod())
+ return;
+ String xname = JniHelper.mangle(klass.name);
+ File outFile = new File(outputDir, xname + ".c");
+
+ JniPrintStream out = new JniPrintStream(classpath,
+ new FileOutputStream(outFile),
+ klass);
+ out.println("/* This file is intended to give you a head start on implementing native");
+ out.println(" methods using CNI.");
+ out.println(" Be aware: running 'gcjh -stubs' once more for this class may");
+ out.println(" overwrite any edits you have made to this file. */");
+ out.println();
+ out.print("#include <");
+ out.print(xname);
+ out.println(".h>");
+
+ Iterator i = klass.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ out.println();
+ out.print(Type.getReturnType(method.desc));
+ out.println();
+ out.print(method, xname);
+ out.println();
+ out.println("{");
+ out.print(" (*env)->FatalError (env, \"");
+ out.print(method, xname);
+ out.println(" not implemented\");");
+ out.println("}");
+ }
+ out.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/Keywords.java b/tools/gnu/classpath/tools/javah/Keywords.java
new file mode 100644
index 000000000..46543ba45
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Keywords.java
@@ -0,0 +1,85 @@
+/* Keywords.java - List of C++ keywords
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.util.HashSet;
+
+public class Keywords
+{
+ private static final String[] words = { "and", "and_eq", "asm", "auto",
+ "bitand", "bitor", "bool", "break",
+ "case", "catch", "char", "class",
+ "compl", "const", "const_cast",
+ "continue", "default", "delete", "do",
+ "double", "dynamic_cast", "else",
+ "enum", "explicit", "export",
+ "extern", "false", "float", "for",
+ "friend", "goto", "if", "inline",
+ "int", "long", "mutable", "namespace",
+ "new", "not", "not_eq", "operator",
+ "or", "or_eq", "private", "protected",
+ "public", "register",
+ "reinterpret_cast", "return", "short",
+ "signed", "sizeof", "static",
+ "static_cast", "struct", "switch",
+ "template", "this", "throw", "true",
+ "try", "typedef", "typeid",
+ "typename", "typeof", "union",
+ "unsigned", "using", "virtual",
+ "void", "volatile", "wchar_t",
+ "while", "xor", "xor_eq" };
+
+ private static final HashSet keywords;
+ static
+ {
+ keywords = new HashSet();
+ for (int i = 0; i < words.length; ++i)
+ keywords.add(words[i]);
+ }
+
+ public static String getCxxName(String name)
+ {
+ int i;
+ for (i = name.length() - 1; i >= 0 && name.charAt(i) == '$'; --i)
+ ;
+ if (keywords.contains(name.substring(0, i + 1)))
+ return name + "$";
+ return name;
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/Main.java b/tools/gnu/classpath/tools/javah/Main.java
new file mode 100644
index 000000000..f9b2f624c
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Main.java
@@ -0,0 +1,375 @@
+/* Main.java - javah main program
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import gnu.classpath.tools.getopt.ClasspathToolParser;
+import gnu.classpath.tools.getopt.Option;
+import gnu.classpath.tools.getopt.OptionException;
+import gnu.classpath.tools.getopt.Parser;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.objectweb.asm.ClassReader;
+
+public class Main
+{
+ // This is an option group for classpath-related options,
+ // and also is used for loading classes.
+ PathOptionGroup classpath = new PathOptionGroup();
+
+ // The output directory.
+ String outputDir;
+
+ // The loader that we use to load class files.
+ URLClassLoader loader;
+
+ // In -all mode, the name of the directory to scan.
+ String allDirectory;
+
+ // True for verbose mode.
+ boolean verbose;
+
+ // True if we're emitting stubs.
+ boolean stubs;
+
+ // True if we're emitting CNI code.
+ boolean cni;
+
+ // Map class names to class wrappers.
+ HashMap classMap = new HashMap();
+
+ // Map class names to lists of Text objects.
+ HashMap textMap = new HashMap();
+
+ void readCommandFile(String textFileName) throws OptionException
+ {
+ FileInputStream fis;
+ try
+ {
+ fis = new FileInputStream(textFileName);
+ }
+ catch (FileNotFoundException ignore)
+ {
+ throw new OptionException("file \"" + textFileName + "\" not found");
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
+ String currentClass = null;
+ ArrayList currentValues = null;
+ while (true)
+ {
+ String line;
+ try
+ {
+ line = reader.readLine();
+ }
+ catch (IOException _)
+ {
+ break;
+ }
+ if (line == null)
+ break;
+ line = line.trim();
+ if (line.length() == 0 || line.charAt(0) == '#')
+ continue;
+ int index = line.indexOf(' ');
+ String cmd = line.substring(0, index);
+ String value = line.substring(index + 1);
+ int cmdValue;
+ if ("class".equals(cmd))
+ {
+ if (currentClass != null)
+ {
+ textMap.put(currentClass, currentValues);
+ }
+ currentClass = value;
+ currentValues = new ArrayList();
+ continue;
+ }
+ if (currentClass == null)
+ throw new OptionException("no class set");
+ if ("add".equals(cmd))
+ cmdValue = Text.ADD;
+ else if ("append".equals(cmd))
+ cmdValue = Text.APPEND;
+ else if ("prepend".equals(cmd))
+ cmdValue = Text.PREPEND;
+ else if ("friend".equals(cmd))
+ cmdValue = Text.FRIEND;
+ else
+ throw new OptionException("unrecognized command: " + cmd);
+ currentValues.add(new Text(cmdValue, value));
+ }
+ if (currentClass != null)
+ {
+ textMap.put(currentClass, currentValues);
+ }
+ }
+
+ void scanDirectory(File dir, final HashSet results)
+ {
+ File[] files = dir.listFiles(new FileFilter()
+ {
+ public boolean accept(File pathname)
+ {
+ if (pathname.isDirectory())
+ {
+ scanDirectory(pathname, results);
+ return false;
+ }
+ return pathname.getName().endsWith(".class");
+ }
+ });
+ if (files != null)
+ results.addAll(Arrays.asList(files));
+ }
+
+ private Parser getParser()
+ {
+ ClasspathToolParser result = new ClasspathToolParser("gcjh", true);
+ result.setHeader("usage: gcjh [OPTIONS] CLASS...");
+ result.add(classpath);
+ result.add(new Option('d', "Set output directory", "DIR")
+ {
+ public void parsed(String dir) throws OptionException
+ {
+ if (outputDir != null)
+ throw new OptionException("-d already seen");
+ outputDir = dir;
+ }
+ });
+ result.add(new Option("cmdfile", "Read command file", "FILE")
+ {
+ public void parsed(String file) throws OptionException
+ {
+ readCommandFile(file);
+ }
+ });
+ result.add(new Option("all", "Operate on all class files under directory",
+ "DIR")
+ {
+ public void parsed(String arg) throws OptionException
+ {
+ // FIXME: lame restriction...
+ if (allDirectory != null)
+ throw new OptionException("-all already specified");
+ allDirectory = arg;
+ }
+ });
+ result.add(new Option("stubs", "Emit stub implementation")
+ {
+ public void parsed(String arg0) throws OptionException
+ {
+ stubs = true;
+ }
+ });
+ result.add(new Option("cni", "Emit CNI stubs or header (default JNI)")
+ {
+ public void parsed(String arg0) throws OptionException
+ {
+ cni = true;
+ }
+ });
+ result.add(new Option("verbose", "Set verbose mode")
+ {
+ public void parsed(String arg0) throws OptionException
+ {
+ verbose = true;
+ }
+ });
+ return result;
+ }
+
+ private File makeOutputDirectory() throws IOException
+ {
+ File outputFile;
+ if (outputDir == null)
+ outputFile = new File(".");
+ else
+ {
+ outputFile = new File(outputDir);
+ outputFile.mkdirs();
+ }
+ return outputFile;
+ }
+
+ private void writeHeaders(ArrayList klasses, Printer printer,
+ File outputDirFile) throws IOException
+ {
+ Iterator i = klasses.iterator();
+ while (i.hasNext())
+ {
+ ClassWrapper klass = (ClassWrapper) i.next();
+ if (verbose)
+ System.err.println("[writing " + klass + "]");
+ printer.printClass(outputDirFile, klass);
+ }
+ }
+
+ private void run(String[] args) throws IOException
+ {
+ Parser p = getParser();
+ String[] classNames = p.parse(args);
+ loader = classpath.getLoader();
+
+ File outputFile = makeOutputDirectory();
+ Printer printer;
+ if (! cni)
+ {
+ if (stubs)
+ printer = new JniStubPrinter(this);
+ else
+ printer = new JniIncludePrinter(this);
+ }
+ else
+ {
+ if (stubs)
+ printer = new CniStubPrinter(this);
+ else
+ printer = new CniIncludePrinter(this);
+ }
+
+ // First we load all of the files. That way if
+ // there are references between the files we will
+ // be loading the set that the user asked for.
+ HashSet klasses = new HashSet();
+ if (allDirectory != null)
+ scanDirectory(new File(allDirectory), klasses);
+ // Add the command-line arguments. We use the type of
+ // an item in 'klasses' to decide how to load each class.
+ for (int i = 0; i < classNames.length; ++i)
+ {
+ if (classNames[i].endsWith(".class"))
+ {
+ klasses.add(new File(classNames[i]));
+ }
+ else
+ {
+ klasses.add(classNames[i]);
+ }
+ }
+
+ Iterator i = klasses.iterator();
+ ArrayList results = new ArrayList();
+ while (i.hasNext())
+ {
+ // Let user specify either kind of class name or a
+ // file name.
+ Object item = i.next();
+ ClassWrapper klass;
+ if (item instanceof File)
+ {
+ // Load class from file.
+ if (verbose)
+ System.err.println("[reading file " + item + "]");
+ klass = getClass((File) item);
+ }
+ else
+ {
+ // Load class given the class name.
+ String className = ((String) item).replace('.', '/');
+ if (verbose)
+ System.err.println("[reading class " + className + "]");
+ klass = getClass(className);
+ }
+ results.add(klass);
+ }
+
+ writeHeaders(results, printer, outputFile);
+ }
+
+ public ArrayList getClassTextList(String name)
+ {
+ return (ArrayList) textMap.get(name);
+ }
+
+ private ClassWrapper readClass(InputStream is) throws IOException
+ {
+ ClassReader r = new ClassReader(is);
+ ClassWrapper result = new ClassWrapper(this);
+ r.accept(result, true);
+ is.close();
+ return result;
+ }
+
+ private ClassWrapper getClass(File fileName) throws IOException
+ {
+ InputStream is = new FileInputStream(fileName);
+ ClassWrapper result = readClass(is);
+ if (classMap.containsKey(result.name))
+ throw new IllegalArgumentException("class " + result.name
+ + " already loaded");
+ classMap.put(result.name, result);
+ return result;
+ }
+
+ public ClassWrapper getClass(String name) throws IOException
+ {
+ if (! classMap.containsKey(name))
+ {
+ String resource = name.replace('.', '/') + ".class";
+ URL url = loader.findResource(resource);
+ if (url == null)
+ throw new IOException("can't find class file " + resource);
+ InputStream is = url.openStream();
+ ClassWrapper result = readClass(is);
+ classMap.put(name, result);
+ }
+ return (ClassWrapper) classMap.get(name);
+ }
+
+ public static void main(String[] args) throws IOException
+ {
+ Main m = new Main();
+ m.run(args);
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/MethodHelper.java b/tools/gnu/classpath/tools/javah/MethodHelper.java
new file mode 100644
index 000000000..6657f115a
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/MethodHelper.java
@@ -0,0 +1,130 @@
+/* MethodHelper.java - helper class for manipulating methods
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public class MethodHelper
+{
+
+ public static boolean overrides(MethodNode derived, MethodNode base)
+ {
+ if (! derived.name.equals(base.name))
+ return false;
+ if (! derived.desc.equals(base.desc))
+ return false;
+ // FIXME: permission madness?
+ return true;
+ }
+
+ public static String getBridgeTarget(MethodNode meth)
+ {
+ if ((meth.access & Opcodes.ACC_BRIDGE) == 0)
+ return null;
+ Iterator i = meth.instructions.iterator();
+ while (i.hasNext())
+ {
+ AbstractInsnNode insn = (AbstractInsnNode) i.next();
+ if (! (insn instanceof MethodInsnNode))
+ continue;
+ return ((MethodInsnNode) insn).desc;
+ }
+ return null;
+ }
+
+ public static void print(CniPrintStream out, MethodNode meth,
+ ClassWrapper declarer, boolean isBridgeTarget)
+ {
+ if ("<clinit>".equals(meth.name))
+ return;
+ boolean isInit = "<init>".equals(meth.name);
+ out.setModifiers(meth.access);
+ out.print(" ");
+ if (Modifier.isStatic(meth.access))
+ out.print("static ");
+ // If a class is final then we might as well skip 'virtual'.
+ // The reason here is that it is safe in this case for C++
+ // ABI code to generate a direct call. The method does end
+ // up in the vtable (for BC code) but we don't care. Also,
+ // the class can't be derived from anyway.
+ else if (! isInit && ! Modifier.isPrivate(meth.access)
+ && ! Modifier.isFinal(declarer.access))
+ out.print("virtual ");
+ if (! isInit)
+ {
+ out.print(Type.getReturnType(meth.desc));
+ out.print(" ");
+ if (isBridgeTarget)
+ {
+ out.print("target$");
+ out.print(meth.name);
+ }
+ else
+ {
+ out.print(Keywords.getCxxName(meth.name));
+ }
+ }
+ else
+ {
+ String name = declarer.name;
+ int index = name.lastIndexOf('/');
+ name = name.substring(index + 1);
+ out.print(name);
+ }
+ out.print("(");
+ Type[] argTypes = Type.getArgumentTypes(meth.desc);
+ for (int i = 0; i < argTypes.length; ++i)
+ {
+ if (i > 0)
+ out.print(", ");
+ out.print(argTypes[i]);
+ }
+ out.print(")");
+ if (Modifier.isAbstract(meth.access))
+ out.print(" = 0");
+ out.println(";");
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/PackageWrapper.java b/tools/gnu/classpath/tools/javah/PackageWrapper.java
new file mode 100644
index 000000000..11b38b20f
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/PackageWrapper.java
@@ -0,0 +1,54 @@
+/* PackageWrapper.java - represent a package
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+public class PackageWrapper
+{
+ // This is null if there is no parent package.
+ PackageWrapper parent;
+
+ // Name of this package relative to its parent's name.
+ String name;
+
+ public PackageWrapper(PackageWrapper parent, String name)
+ {
+ this.parent = parent;
+ this.name = name;
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/PathOptionGroup.java b/tools/gnu/classpath/tools/javah/PathOptionGroup.java
new file mode 100644
index 000000000..f11077fa0
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/PathOptionGroup.java
@@ -0,0 +1,135 @@
+/* PathOptionGroup.java - handle classpath-setting options
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import gnu.classpath.tools.getopt.Option;
+import gnu.classpath.tools.getopt.OptionException;
+import gnu.classpath.tools.getopt.OptionGroup;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+public class PathOptionGroup
+ extends OptionGroup
+{
+ ArrayList classpath = new ArrayList();
+
+ ArrayList bootclasspath = new ArrayList();
+
+ void setPath(ArrayList list, String path)
+ {
+ list.clear();
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ while (st.hasMoreTokens())
+ {
+ list.add(st.nextToken());
+ }
+ }
+
+ void addExtDirs(ArrayList list, String path)
+ {
+ StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
+ while (tok.hasMoreTokens())
+ {
+ File dir = new File(tok.nextToken());
+ list.addAll(Arrays.asList(dir.list(new FilenameFilter()
+ {
+ public boolean accept(File dir, String name)
+ {
+ return name.endsWith(".zip") || name.endsWith(".jar");
+ }
+ })));
+ }
+ }
+
+ public PathOptionGroup()
+ {
+ super("Class path options");
+
+ add(new Option("classpath", "Set the class path", "PATH")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ setPath(classpath, path);
+ }
+ });
+ add(new Option('I', "Add directory to class path", "DIR")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ classpath.add(path);
+ }
+ });
+ add(new Option("bootclasspath", "Set the boot class path", "PATH")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ setPath(bootclasspath, path);
+ }
+ });
+ add(new Option("extdirs", "Set the extension directory path", "PATH")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ addExtDirs(classpath, path);
+ }
+ });
+ }
+
+ public URLClassLoader getLoader() throws MalformedURLException
+ {
+ ArrayList urls = new ArrayList();
+ classpath.addAll(bootclasspath);
+ Iterator i = classpath.iterator();
+ while (i.hasNext())
+ {
+ String f = (String) i.next();
+ urls.add(new File(f).toURL());
+ }
+ URL[] urlArray = (URL[]) urls.toArray(new URL[0]);
+ return new URLClassLoader(urlArray);
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/Printer.java b/tools/gnu/classpath/tools/javah/Printer.java
new file mode 100644
index 000000000..0c25934e2
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Printer.java
@@ -0,0 +1,55 @@
+/* Print.java - abstract base class for printing classes
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.IOException;
+
+public abstract class Printer
+{
+ protected Main classpath;
+
+ protected Printer(Main classpath)
+ {
+ this.classpath = classpath;
+ }
+
+ public abstract void printClass(File outputDir, ClassWrapper klass)
+ throws IOException;
+}
diff --git a/tools/gnu/classpath/tools/javah/Text.java b/tools/gnu/classpath/tools/javah/Text.java
new file mode 100644
index 000000000..37a1ad669
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Text.java
@@ -0,0 +1,60 @@
+/* Text.java - convenience class for CNI header text insertions
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+public class Text
+{
+ public static final int ADD = 0;
+
+ public static final int APPEND = 1;
+
+ public static final int FRIEND = 2;
+
+ public static final int PREPEND = 3;
+
+ public int type;
+
+ public String text;
+
+ public Text(int type, String text)
+ {
+ this.type = type;
+ this.text = text;
+ }
+}