Skip to content

Commit

Permalink
Initial handling of calls to static Java methods
Browse files Browse the repository at this point in the history
Changes mostly include:
* New option `--with{out}-java` for `configure` script
* Runtime support for calling `static void (void)` methods
* Lookup of JVM library when JAVA_HOME is set, and pre-load when
  possible
* Two preliminary tests

Co-authored-by: Nicolas Berthier <[email protected]>
Co-authored-by: Simon Sobisch <[email protected]>
  • Loading branch information
3 people committed Aug 21, 2024
1 parent 4edf4a4 commit 675d244
Show file tree
Hide file tree
Showing 28 changed files with 1,123 additions and 22 deletions.
8 changes: 7 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@

2024-07-12 Vedant Tewari <[email protected]>

2023-02-25 Ron Norman <[email protected]>
* ax_prog_java.m4: Added macro for jni check
* ax_jni_include_dir.m4: Added macro for jni check
* configure.ac: added support for Java interoperability through JNI

2023-02-25 Ron Norman <[email protected]>

* configure.ac: Add check for sys/time.h

Expand Down
15 changes: 15 additions & 0 deletions DEPENDENCIES
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,21 @@ The following libraries ARE required WHEN :

JSON-C is distributed under Expat License.

5) JNI (Java Native Interface) support is used

BOTH runtime AND development components required.

Java Development Kit (JDK) 8 or later

https://openjdk.org/

The JDK is distributed under various open-source licenses depending
on the vendor and version. Common licenses include the GNU General
Public License (GPL) and the Oracle Binary Code License Agreement.

To enable JNI support, ensure that the JDK is installed on your system,
and set the appropriate environment variables (e.g., JAVA_HOME) to point
to the JDK installation directory.

See HACKING if you wish to hack the GnuCOBOL source or build directly
from version control as this includes the list of additional tools
Expand Down
10 changes: 10 additions & 0 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,13 @@ Support for GENERATE JSON is provided by *one* of the following:

JSON-C is distributed under Expat License.

JNI Support
------------

Support for JNI (Java Native Interface) is provided by:

* [Java Development Kit (JDK)](https://openjdk.java.net/) 8 or later.

The JDK is distributed under various open-source licenses depending on the vendor and version. Common licenses include the GNU General Public License (GPL) and the Oracle Binary Code License Agreement.

To enable JNI support, ensure that the JDK is installed on your system, and set the appropriate environment variables (e.g., JAVA_HOME) to point to the JDK installation directory.
2 changes: 1 addition & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ NEWS - user visible changes -*- outline -*-


* New GnuCOBOL features

** Initial support for Java interoperability through JNI (new optional dependency JDK)
** file handling: added backends for ODBC (so far PostgrSQL, MySQL, SQLite,
MSSQL) and OCI, along with new directory COB_SCHEMA_DIR containing the
necessary internal schema files to match the file definition to the
Expand Down
4 changes: 4 additions & 0 deletions cobc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@

2024-08-14 Nicolas Berthier <[email protected]>

* cobc.c (cobc_print_info): added note for Java interoperability

2024-08-04 David Declerck <[email protected]>

Adjustments to merge 2022-12-21:
Expand Down
6 changes: 6 additions & 0 deletions cobc/cobc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,12 @@ cobc_print_info (void)

cobc_var_print (_("JSON library"), _(WITH_JSON), 0);

#ifdef WITH_JNI
cobc_var_print (_("Java interoperability"), _("enabled"), 0);
#else
cobc_var_print (_("Java interoperability"), _("disabled"), 0);
#endif

#ifdef COB_DEBUG_LOG
cobc_var_print ("DEBUG_LOG", _("enabled"), 0);
#endif
Expand Down
68 changes: 67 additions & 1 deletion cobc/codegen.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
Copyright (C) 2003-2024 Free Software Foundation, Inc.
Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch,
Edward Hart
Edward Hart, Vedant Tewari
This file is part of GnuCOBOL.
Expand Down Expand Up @@ -147,6 +147,7 @@ static struct literal_list *literal_cache = NULL;
static struct field_list *field_cache = NULL;
static struct field_list *local_field_cache = NULL;
static struct call_list *call_cache = NULL;
static struct call_list *call_java_cache = NULL;
static struct call_list *func_call_cache = NULL;
static struct static_call_list *static_call_cache = NULL;
static struct base_list *base_cache = NULL;
Expand Down Expand Up @@ -395,6 +396,22 @@ lookup_source (const char *p)
return source_id++;
}

static void
lookup_java_call(const char *p)
{
struct call_list *clp;

for (clp = call_java_cache; clp; clp = clp->next) {
if (strcmp (p, clp->call_name) == 0) {
return;
}
}
clp = cobc_parse_malloc (sizeof (struct call_list));
clp->call_name = p;
clp->next = call_java_cache;
call_java_cache = clp;
}

static void
lookup_call (const char *p)
{
Expand Down Expand Up @@ -1978,6 +1995,11 @@ output_call_cache (void)
output_local ("static cob_call_union\tcall_%s;\n",
call->call_name);
}
call_java_cache = call_list_reverse (call_java_cache);
for (call = call_java_cache; call; call = call->next) {
output_local ("static cob_java_handle*\tcall_java_%s;\n",
call->call_name);
}
func_call_cache = call_list_reverse (func_call_cache);
for (call = func_call_cache; call; call = call->next) {
output_local ("static cob_call_union\tfunc_%s;\n",
Expand Down Expand Up @@ -7068,6 +7090,45 @@ output_field_constant (cb_tree x, int n, const char *flagname)
output_newline ();
}

static void
output_java_call (struct cb_call *p)
{
char* full_name = (char *)CB_LITERAL(p->name)->data; /* Assume java.prefix (enforced in `parser.y`, rule `call_body`)*/
char* class_and_method_name = full_name + 5;
char *last_dot;
char *method_name;
const char *class_name;
char* mangled;

mangled = strdup(class_and_method_name);
for (size_t i = 0; i < strlen(mangled) + 1; i++) {
mangled[i] = (mangled[i] == '.') ? '_' : mangled[i];
}

last_dot = strrchr(class_and_method_name, '.');
if (last_dot == NULL) {
cobc_err_msg (_("malformed call '%s' to a Java method"), class_and_method_name);
COBC_ABORT ();
}

*last_dot = '\0';
method_name = last_dot + 1;
class_name = class_and_method_name;

lookup_java_call(mangled);
output_line("if (call_java_%s == NULL)", mangled);
output_block_open();

output_prefix();
output_line("call_java_%s = ", mangled);
output("cob_resolve_java(\"%s\", \"%s\", \"()V\");", class_name, method_name);
output_newline ();
output_prefix ();
output_line("cob_call_java(call_java_%s);\n", mangled);
output_newline();
output_block_close();
}

static void
output_call (struct cb_call *p)
{
Expand Down Expand Up @@ -7097,6 +7158,11 @@ output_call (struct cb_call *p)
}
system_call = NULL;

if (p->convention & CB_CONV_JAVA) {
output_java_call(p);
return;
}

#ifdef _WIN32
if (p->convention & CB_CONV_STDCALL) {
convention = "_std";
Expand Down
5 changes: 5 additions & 0 deletions cobc/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -12253,6 +12253,11 @@ call_body:

/* Check parameter conformance, if we can work out what is being called. */
if (CB_LITERAL_P ($3)) {
/* Check for "Java." prefix and set call convention */
char* s = (char *)CB_LITERAL ($3)->data;
if (strncasecmp("Java.", s, 5) == 0) {
call_conv = CB_CONV_JAVA;
}
cb_check_conformance ($3, $7, $8);
} else if (CB_REFERENCE_P ($3)) {
cb_tree ref = cb_ref ($3);
Expand Down
1 change: 1 addition & 0 deletions cobc/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ enum cb_tag {
#define CB_CONV_THUNK_16 (1 << 5)
#define CB_CONV_STDCALL (1 << 6)
#define CB_CONV_COBOL (1 << 15)
#define CB_CONV_JAVA (1 << 16)
#define CB_CONV_C (0)
#define CB_CONV_PASCAL (CB_CONV_L_TO_R | CB_CONV_CALLEE_STACK)

Expand Down
62 changes: 61 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ AH_TEMPLATE([WITH_JSON], [JSON handler])
AH_TEMPLATE([WITH_CJSON], [Use cJSON library/source as JSON handler])
AH_TEMPLATE([WITH_JSON_C], [Use JSON-C library as JSON handler])

AH_TEMPLATE([WITH_JNI], [Support for Java calls through JNI])

AH_TEMPLATE([COB_EXPORT_DYN], [Compile/link option for exporting symbols])
AH_TEMPLATE([COB_PIC_FLAGS], [Compile/link option for PIC code])
AH_TEMPLATE([COB_DEBUG_FLAGS], [Compile/link option for debugging])
Expand Down Expand Up @@ -483,7 +485,6 @@ AC_CHECK_HEADERS([sys/types.h signal.h stddef.h], [],
# optional:
AC_CHECK_HEADERS([sys/time.h locale.h fcntl.h dlfcn.h sys/wait.h sys/sysmacros.h])


# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_BIGENDIAN
Expand Down Expand Up @@ -933,7 +934,56 @@ AS_IF([test "$with_xml2" = "yes" -o "$with_xml2" = "check"], [
LIBS="$curr_libs"; CPPFLAGS="$curr_cppflags"
])

# Check for JNI
AC_ARG_WITH([java],
[AS_HELP_STRING([--without-java],
[disable Java Interoperability])])
cob_has_jni=no
AS_IF([test "x$with_java" != "xno"], [
dnl Find `java` and $JAVA_HOME (we need the latter to locate libjvm).
dnl AX_CHECK_JAVA_HOME dnl (<- does not appear to work properly)
AX_PROG_JAVA
if test "x$JAVA_HOME" = x; then
JAVA_HOME="$( $JAVA -XshowSettings:properties -version 2>&1 >/dev/null | \
$SED -e '/^[ ]*java.home/!d' -e 's/.*=[ ]*//' )"
AC_MSG_NOTICE([Found Java home: ${JAVA_HOME}])
else
AC_MSG_NOTICE([Given Java home: ${JAVA_HOME}])
fi
dnl Note: AX_PROG_JAVAC might find a `javac` binary that does
dnl not match the version of `$JAVA` found above, so we set
dnl its path manually.
JAVAC="$JAVA_HOME/bin/javac"
AX_PROG_JAVAC_WORKS
AX_JNI_INCLUDE_DIR
AS_IF([test "$JNI_INCLUDE_DIRS" != ""], [
for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do
JNI_CPPFLAGS="$JNI_CPPFLAGS -I$JNI_INCLUDE_DIR"
done
for _dir in "${JAVA_HOME}/jre/lib" "${JAVA_HOME}/lib"; do
if test -d "$_dir"; then
JNI_LIBS="$JNI_LIBS -L$_dir"
fi
if test -d "$_dir/server"; then
JNI_LIBS="$JNI_LIBS -L$_dir/server"
fi
done
curr_LIBS="$LIBS"
LIBS="$LIBS $JNI_LIBS"
AC_CHECK_LIB([jvm], [JNI_CreateJavaVM], [
AC_DEFINE([WITH_JNI], [1])
JNI_LDFLAGS="$JNI_LIBS"
JNI_LIBS="-ljvm"
cob_has_jni=yes
])
LIBS="$curr_LIBS"
])
])
AS_IF([test "x$with_java" = "xyes" -a "x$cob_has_jni" != "xyes"], [
AC_MSG_ERROR([Java interoperability requested, but JNI was not found])
])

# Checks for cjson/json-c.
AC_MSG_NOTICE([Checks for JSON handler])
Expand Down Expand Up @@ -2570,6 +2620,8 @@ AM_CONDITIONAL([COB_MAKE_LMDB_LIB], [test "$cob_gen_lmdb" = "yes"])
AM_CONDITIONAL([LOCAL_CJSON],[test "$USE_JSON" = "local"])
AM_CONDITIONAL([COB_HAS_JNI], [test "$cob_has_jni" = "yes"])
unset COB_USES_GCC
unset COB_USES_GCC_NO_ICC
unset COB_USES_ICC_ONLY
Expand Down Expand Up @@ -2660,6 +2712,11 @@ AC_SUBST([OCI_CFLAGS])
AC_SUBST([BDB_CFLAGS])
AC_SUBST([LMDB_CFLAGS])
AC_SUBST([JAVAC])
AC_SUBST([JNI_LIBS])
AC_SUBST([JNI_LDFLAGS])
AC_SUBST([JNI_CPPFLAGS])
dnl was used in bin/Makefile.am - seems not to be needed
dnl AC_SUBST([COB_EXPORT_DYN])
Expand All @@ -2683,6 +2740,7 @@ AC_SUBST([COB_HAS_OCEXTFH])
AC_SUBST([COB_HAS_CURSES])
AC_SUBST([COB_HAS_XML2])
AC_SUBST([COB_HAS_JSON])
AC_SUBST([COB_HAS_JNI])
AC_SUBST([COB_HAS_64_BIT_POINTER])
AC_SUBST([COB_PATCH_LEVEL], [$with_patch_level]) # needed for bin/cob-config
Expand Down Expand Up @@ -2804,4 +2862,6 @@ case "$USE_JSON" in
;;
esac
AC_MSG_NOTICE([ Build with Java interoperability: ${cob_has_jni}])
unset DEFINE_DL
10 changes: 10 additions & 0 deletions libcob/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@

2024-08-14 Nicolas Berthier <[email protected]>

* common.c (print_info_detailed): added note for Java interoperability

2024-06-12 Vedant Tewari <[email protected]>

* Makefile.am: Updated to include JNI-related files
* common.h: Added internal state for JNI support
* java.c: Implemented JNI support for GnuCOBOL

2024-08-04 David Declerck <[email protected]>

Adjustments to merge 2022-12-21:
Expand Down
16 changes: 13 additions & 3 deletions libcob/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#
# Makefile gnucobol/libcob
#
# Copyright (C) 2003-2012, 2014, 2017-2023 Free Software Foundation, Inc.
# Written by Keisuke Nishida, Roger While, Simon Sobisch
# Copyright (C) 2003-2012, 2014, 2017-2024 Free Software Foundation, Inc.
# Written by Keisuke Nishida, Roger While, Simon Sobisch, Vedant Tewari
#
# This file is part of GnuCOBOL.
#
Expand Down Expand Up @@ -125,8 +125,18 @@ else
lib_lm =
endif

if COB_HAS_JNI
lib_jni = libcobjni.la
libcobjni_la_LIBADD = libcob.la $(JNI_LIBS)
libcobjni_la_SOURCES = java.c
libcobjni_la_LDFLAGS = $(AM_LDFLAGS) $(JNI_LDFLAGS) -version-info 1:0:0
libcobjni_la_CFLAGS = $(AM_CFLAGS) $(JNI_CPPFLAGS)
else
lib_jni =
endif

lib_LTLIBRARIES = libcob.la $(lib_ci) $(lib_di) $(lib_vb) $(lib_vc) \
$(lib_od) $(lib_oc) $(lib_db) $(lib_lm)
$(lib_od) $(lib_oc) $(lib_db) $(lib_lm) $(lib_jni)

EXTRA_DIST = fisam.c
pkgincludedir = $(includedir)/libcob
Expand Down
Loading

0 comments on commit 675d244

Please sign in to comment.