summaryrefslogtreecommitdiff
path: root/os2/OS2/REXX
diff options
context:
space:
mode:
authorIlya Zakharevich <ilya@math.berkeley.edu>2003-06-14 10:49:57 -0700
committerJarkko Hietaniemi <jhi@iki.fi>2003-06-15 17:08:02 +0000
commit622913ab81739f4a9419ed541a122ff2495c8ab1 (patch)
tree06a71ddf809f0904979a43c23c68dae3939718db /os2/OS2/REXX
parent41be1fbddbbc49a5c34acad74f2905b11dd0ced0 (diff)
downloadperl-622913ab81739f4a9419ed541a122ff2495c8ab1.tar.gz
OS2 patches
Message-ID: <20030615004956.GA28272@math.berkeley.edu> p4raw-id: //depot/perl@19789
Diffstat (limited to 'os2/OS2/REXX')
-rw-r--r--os2/OS2/REXX/DLL/DLL.pm239
-rw-r--r--os2/OS2/REXX/DLL/DLL.xs100
-rw-r--r--os2/OS2/REXX/t/rx_emxrv.t39
-rw-r--r--os2/OS2/REXX/t/rx_objcall.t7
4 files changed, 312 insertions, 73 deletions
diff --git a/os2/OS2/REXX/DLL/DLL.pm b/os2/OS2/REXX/DLL/DLL.pm
index 09e3e37a08..f6660d6cad 100644
--- a/os2/OS2/REXX/DLL/DLL.pm
+++ b/os2/OS2/REXX/DLL/DLL.pm
@@ -5,38 +5,16 @@ our $VERSION = '1.00';
use Carp;
use XSLoader;
-sub AUTOLOAD {
- $AUTOLOAD =~ /^OS2::DLL::.+::(.+)$/
- or confess("Undefined subroutine &$AUTOLOAD called");
- return undef if $1 eq "DESTROY";
- $_[0]->find($1)
- or confess("Can't find entry '$1' to DLL '$_[0]->{File}': $^E");
- goto &$AUTOLOAD;
-}
-
@libs = split(/;/, $ENV{'PERL5REXX'} || $ENV{'PERLREXX'} || $ENV{'LIBPATH'} || $ENV{'PATH'});
%dlls = ();
# Preloaded methods go here. Autoload methods go after __END__, and are
# processed by the autosplit program.
-# Cannot autoload, the autoloader is used for the REXX functions.
+# Cannot be autoload, the autoloader is used for the REXX functions.
-sub new {
- confess 'Usage: OS2::DLL->new( <file> [<dirs>] )' unless @_ >= 2;
- my ($class, $file) = (shift, shift);
- my $handle;
- $handle = $class->load($file, @_) and return $handle;
- my $path = @_ ? " from '@_'" : '';
- my $err = DynaLoader::dl_error();
- $err =~ s/\s+at\s+\S+\s+line\s+\S+\s*\z//;
- croak "Can't load '$file'$path: $err";
-}
-
-sub load
-{
- confess 'Usage: load OS2::DLL <file> [<dirs>]' unless $#_ >= 1;
- my ($class, $file, @where) = (@_, @libs);
+my $load_with_dirs = sub {
+ my ($class, $file, @where) = (@_);
return $dlls{$file} if $dlls{$file};
my $handle;
foreach (@where) {
@@ -45,41 +23,81 @@ sub load
}
$handle = DynaLoader::dl_load_file($file) unless $handle;
return undef unless $handle;
- my $packs = $INC{'OS2/REXX.pm'} ? 'OS2::DLL OS2::REXX' : 'OS2::DLL';
- eval <<EOE or die "eval package $@";
-package OS2::DLL::$file; \@ISA = qw($packs);
-sub AUTOLOAD {
- \$OS2::DLL::AUTOLOAD = \$AUTOLOAD;
- goto &OS2::DLL::AUTOLOAD;
-}
-1;
-EOE
+ my @packs = $INC{'OS2/REXX.pm'} ? qw(OS2::DLL::dll OS2::REXX) : 'OS2::DLL::dll';
+ my $p = "OS2::DLL::dll::$file";
+ @{"$p\::ISA"} = @packs;
+ *{"$p\::AUTOLOAD"} = \&OS2::DLL::dll::AUTOLOAD;
return $dlls{$file} =
- bless {Handle => $handle, File => $file, Queue => 'SESSION' },
- "OS2::DLL::$file";
+ bless {Handle => $handle, File => $file, Queue => 'SESSION' }, $p;
+};
+
+my $new_dll = sub {
+ my ($dirs, $class, $file) = (shift, shift, shift);
+ my $handle;
+ push @_, @libs if $dirs;
+ $handle = $load_with_dirs->($class, $file, @_)
+ and return $handle;
+ my $path = @_ ? " from '@_'" : '';
+ my $err = DynaLoader::dl_error();
+ $err =~ s/\s+at\s+\S+\s+line\s+\S+\s*\z//;
+ croak "Can't load '$file'$path: $err";
+};
+
+sub new {
+ confess 'Usage: OS2::DLL->new( <file> [<dirs>] )' unless @_ >= 2;
+ $new_dll->(1, @_);
}
-sub find
-{
+sub module {
+ confess 'Usage: OS2::DLL->module( <file> [<dirs>] )' unless @_ >= 2;
+ $new_dll->(0, @_);
+}
+
+sub load {
+ confess 'Usage: load OS2::DLL <file> [<dirs>]' unless $#_ >= 1;
+ $load_with_dirs->(@_, @libs);
+}
+
+package OS2::DLL::dll;
+use Carp;
+@ISA = 'OS2::DLL';
+
+sub AUTOLOAD {
+ $AUTOLOAD =~ /^OS2::DLL::dll::.+::(.+)$/
+ or confess("Undefined subroutine &$AUTOLOAD called");
+ return undef if $1 eq "DESTROY";
+ die "AUTOLOAD loop" if $1 eq "AUTOLOAD";
+ $_[0]->find($1) or confess($@);
+ goto &$AUTOLOAD;
+}
+
+sub wrapper_REXX {
+ confess 'Usage: $dllhandle->wrapper_REXX($func_name)' unless @_ == 2;
my $self = shift;
my $file = $self->{File};
my $handle = $self->{Handle};
my $prefix = exists($self->{Prefix}) ? $self->{Prefix} : "";
my $queue = $self->{Queue};
- foreach (@_) {
- my $name = "OS2::DLL::${file}::$_";
- next if defined(&$name);
- my $addr = DynaLoader::dl_find_symbol($handle, uc $prefix.$_)
- || DynaLoader::dl_find_symbol($handle, $prefix.$_)
- or return 0;
- eval <<EOE or die "eval sub";
-package OS2::DLL::$file;
-sub $_ {
- shift;
- OS2::DLL::_call('$_', $addr, '$queue', \@_);
+ my $name = shift;
+ $prefix = '' if $name =~ /^#\d+/; # loading by ordinal
+ my $addr = (DynaLoader::dl_find_symbol($handle, uc $prefix.$name)
+ || DynaLoader::dl_find_symbol($handle, $prefix.$name));
+ return sub {
+ OS2::DLL::_call($name, $addr, $queue, @_);
+ } if $addr;
+ my $err = DynaLoader::dl_error();
+ $err =~ s/\s+at\s+\S+\s+line\s+\S+\s*\z//;
+ croak "Can't find symbol `$name' in DLL `$file': $err";
}
-1;
-EOE
+
+sub find
+{
+ my $self = shift;
+ my $file = $self->{File};
+ my $p = ref $self;
+ foreach (@_) {
+ my $f = eval {$self->wrapper_REXX($_)} or return 0;
+ ${"${p}::"}{$_} = sub { shift; $f->(@_) };
}
return 1;
}
@@ -102,45 +120,124 @@ See documentation of L<OS2::REXX> module if you need the variable pool.
=head1 SYNOPSIS
use OS2::DLL;
- $emx_dll = OS2::DLL->load('emx');
+ $emx_dll = OS2::DLL->module('emx');
$emx_version = $emx_dll->emx_revision();
+ $func_emx_version = $emx_dll->wrapper_REXX('#128'); # emx_revision
+ $emx_version = $func_emx_version->();
=head1 DESCRIPTION
-=head2 Load REXX DLL
+=head2 Create a DLL handle
- $dll = load OS2::DLL NAME [, WHERE];
+ $dll = OS2::DLL->module( NAME [, WHERE] );
-NAME is DLL name, without path and extension.
+Loads an OS/2 module NAME, looking in directories WHERE (adding the
+extension F<.dll>), if the DLL is not found there, loads in the usual OS/2 way
+(via LIBPATH and other settings). Croaks with a verbose report on failure.
-Directories are searched WHERE first (list of dirs), then environment
-paths PERL5REXX, PERLREXX, PATH or, as last resort, OS/2-ish search
-is performed in default DLL path (without adding paths and extensions).
+The DLL is not unloaded when the return value is destroyed.
-The DLL is not unloaded when the variable dies.
+=head2 Create a DLL handle (looking in some strange locations)
-Returns DLL object reference, or undef on failure (in this case one can
-get the reason via C<DynaLoader::dl_error()>).
+ $dll = OS2::DLL->new( NAME [, WHERE] );
-=head2 Create a REXX DLL handle
+Same as L<C<module>|Create a DLL handle>, but in addition to WHERE, looks
+in environment paths PERL5REXX, PERLREXX, PATH (provided for backward
+compatibility).
- $dll = OS2::DLL->new( NAME [, WHERE] );
+=head2 Loads DLL by name
-Same as L<C<load>|Load REXX DLL>, but croaks with a meaningful message on
-failure.
+ $dll = load OS2::DLL NAME [, WHERE];
+
+Same as L<C<new>|Create a DLL handle (looking in some strange locations)>,
+but returns DLL object reference, or undef on failure (in this case one can
+get the reason via C<DynaLoader::dl_error()>) (provided for backward
+compatibility).
=head2 Check for functions (optional):
BOOL = $dll->find(NAME [, NAME [, ...]]);
-Returns true if all functions are available.
+Returns true if all functions are available. As a side effect, creates
+a REXX wrapper with the specified name in the package constructed by the name
+of the DLL so that the next call to C<$dll->NAME()> will pick up the cached
+method.
+
+=head2 Create a Perl wrapper (optional):
+
+ $func = $dll->wrapper_REXX(NAME);
+
+Returns a reference to a Perl function wrapper for the entry point NAME
+in the DLL. Similar to the OS/2 API, the NAME may be C<"#123"> - in this case
+the ordinal is loaded. Croaks with a meaningful error message if NAME does
+not exists (although the message for the case when the name is an ordinal may
+be confusing).
+
+=head2 Call external function with REXX calling convention:
+
+ $ret_string = $dll->function_name(arguments);
+
+Returns the return string if the REXX return code is 0, else undef.
+Dies with error message if the function is not available. On the first call
+resolves the name in the DLL and caches the Perl wrapper; future calls go
+through the wrapper.
+
+Unless used inside REXX environment (see L<OS2::REXX>), the REXX runtime
+environment (variable pool, queue etc.) is not available to the called
+function.
+
+=head1 Low-level API
+
+=over
+
+=item Call a _System linkage function via a pointer
+
+If a function takes up to 20 ULONGs and returns ULONG:
+
+ $res = call20( $pointer, $arg0, $arg1, ...);
+
+=item Same for packed arguments:
+
+ $res = call20_p( $pointer, pack 'L20', $arg0, $arg1, ...);
+
+=item Same for C<regparm(3)> function:
+
+ $res = call20_rp3( $pointer, $arg0, $arg1, ...);
+
+=item Same for packed arguments and C<regparm(3)> function
+
+ $res = call20_rp3_p( $pointer, pack 'L20', $arg0, $arg1, ...);
+
+=item Same for a function which returns non-0 and sets system-error on error
+
+ call20_Dos( $msg, $pointer, $arg0, $arg1, ...); # die("$msg: $^E") if error
+
+[Good for C<Dos*> API - and rare C<Win*> calls.]
+
+=item Same for a function which returns 0 and sets WinLastError() on error
+
+ $res = call20_Win( $msg, $pointer, $arg0, $arg1, ...);
+ # would die("$msg: $^E") if error
+
+[Good for most of C<Win*> API.]
+
+=item Same for a function which returns 0 and sets WinLastError() on error but
+0 is also a valid return
+
+ $res = call20_Win_0OK( $msg, $pointer, $arg0, $arg1, ...);
+ # would die("$msg: $^E") if error
+
+[Good for some of C<Win*> API.]
+
+=item As previous, but without die()
-=head2 Call external REXX function:
+ $res = call20_Win_0OK_survive( $pointer, $arg0, $arg1, ...);
+ if ($res == 0 and $^E) { # Do error processing here
+ }
- $dll->function(arguments);
+[Good for some of C<Win*> API.]
-Returns the return string if the return code is 0, else undef.
-Dies with error message if the function is not available.
+=back
=head1 ENVIRONMENT
@@ -149,7 +246,7 @@ in C<PERL5REXX>, C<PERLREXX>, C<PATH>.
=head1 AUTHOR
-Extracted by Ilya Zakharevich ilya@math.ohio-state.edu from L<OS2::REXX>
+Extracted by Ilya Zakharevich perl-module-OS2-DLL@ilyaz.org from L<OS2::REXX>
written by Andreas Kaiser ak@ananke.s.bawue.de.
=cut
diff --git a/os2/OS2/REXX/DLL/DLL.xs b/os2/OS2/REXX/DLL/DLL.xs
index c8e7c58007..90b14eaf85 100644
--- a/os2/OS2/REXX/DLL/DLL.xs
+++ b/os2/OS2/REXX/DLL/DLL.xs
@@ -21,12 +21,112 @@ needstrs(int n)
}
}
+typedef ULONG (*fptr_UL_20)(ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG);
+typedef __attribute__((regparm(3))) ULONG (*fptr_UL_20_rp3)(ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG, ULONG);
+
+static inline unsigned long
+call20_p(unsigned long fp, char* str)
+{
+ ULONG *argv = (ULONG*)str;
+ fptr_UL_20 f = (fptr_UL_20)fp;
+
+ return f(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18], argv[19]);
+}
+
+static inline unsigned long
+call20(unsigned long fp, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, unsigned long arg8, unsigned long arg9, unsigned long arg10, unsigned long arg11, unsigned long arg12, unsigned long arg13, unsigned long arg14, unsigned long arg15, unsigned long arg16, unsigned long arg17, unsigned long arg18, unsigned long arg19)
+{
+ fptr_UL_20 f = (fptr_UL_20)fp;
+
+ return f(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
+}
+
+static inline unsigned long
+call20_rp3_p(unsigned long fp, char* str)
+{
+ ULONG *argv = (ULONG*)str;
+ fptr_UL_20_rp3 f = (fptr_UL_20_rp3)fp;
+
+ return f(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18], argv[19]);
+}
+
+static inline unsigned long
+call20_rp3(unsigned long fp, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, unsigned long arg8, unsigned long arg9, unsigned long arg10, unsigned long arg11, unsigned long arg12, unsigned long arg13, unsigned long arg14, unsigned long arg15, unsigned long arg16, unsigned long arg17, unsigned long arg18, unsigned long arg19)
+{
+ fptr_UL_20_rp3 f = (fptr_UL_20_rp3)fp;
+
+ return f(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19);
+}
+
+static inline void
+call20_Dos(char *msg, unsigned long fp, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, unsigned long arg8, unsigned long arg9, unsigned long arg10, unsigned long arg11, unsigned long arg12, unsigned long arg13, unsigned long arg14, unsigned long arg15, unsigned long arg16, unsigned long arg17, unsigned long arg18, unsigned long arg19)
+{
+ fptr_UL_20 f = (fptr_UL_20)fp;
+ ULONG rc;
+
+ if (CheckOSError(f(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19)))
+ croak_with_os2error(msg);
+}
+
+static inline unsigned long
+call20_Win(char *msg, unsigned long fp, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, unsigned long arg8, unsigned long arg9, unsigned long arg10, unsigned long arg11, unsigned long arg12, unsigned long arg13, unsigned long arg14, unsigned long arg15, unsigned long arg16, unsigned long arg17, unsigned long arg18, unsigned long arg19)
+{
+ fptr_UL_20 f = (fptr_UL_20)fp;
+
+ if (CheckWinError(f(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19)))
+ croak_with_os2error(msg);
+}
+
+static inline unsigned long
+call20_Win_0OK(char *msg, unsigned long fp, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, unsigned long arg8, unsigned long arg9, unsigned long arg10, unsigned long arg11, unsigned long arg12, unsigned long arg13, unsigned long arg14, unsigned long arg15, unsigned long arg16, unsigned long arg17, unsigned long arg18, unsigned long arg19)
+{
+ fptr_UL_20 f = (fptr_UL_20)fp;
+
+ ResetWinError();
+ return SaveCroakWinError(f(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19),
+ 1 /* Die on error */, /* No prefix */, msg);
+}
+
+static inline unsigned long
+call20_Win_0OK_survive(unsigned long fp, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, unsigned long arg8, unsigned long arg9, unsigned long arg10, unsigned long arg11, unsigned long arg12, unsigned long arg13, unsigned long arg14, unsigned long arg15, unsigned long arg16, unsigned long arg17, unsigned long arg18, unsigned long arg19)
+{
+ fptr_UL_20 f = (fptr_UL_20)fp;
+
+ ResetWinError();
+ return SaveCroakWinError(f(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19),
+ 0 /* No die on error */, /* No prefix */, "N/A");
+}
+
MODULE = OS2::DLL PACKAGE = OS2::DLL
BOOT:
needstrs(8);
trace = getenv("PERL_REXX_DEBUG");
+unsigned long
+call20_p(unsigned long fp, char* argv)
+
+unsigned long
+call20(unsigned long fp, unsigned long arg0 = 0, unsigned long arg1 = 0, unsigned long arg2 = 0, unsigned long arg3 = 0, unsigned long arg4 = 0, unsigned long arg5 = 0, unsigned long arg6 = 0, unsigned long arg7 = 0, unsigned long arg8 = 0, unsigned long arg9 = 0, unsigned long arg10 = 0, unsigned long arg11 = 0, unsigned long arg12 = 0, unsigned long arg13 = 0, unsigned long arg14 = 0, unsigned long arg15 = 0, unsigned long arg16 = 0, unsigned long arg17 = 0, unsigned long arg18 = 0, unsigned long arg19 = 0)
+
+void
+call20_Dos(char* msg, unsigned long fp, unsigned long arg0 = 0, unsigned long arg1 = 0, unsigned long arg2 = 0, unsigned long arg3 = 0, unsigned long arg4 = 0, unsigned long arg5 = 0, unsigned long arg6 = 0, unsigned long arg7 = 0, unsigned long arg8 = 0, unsigned long arg9 = 0, unsigned long arg10 = 0, unsigned long arg11 = 0, unsigned long arg12 = 0, unsigned long arg13 = 0, unsigned long arg14 = 0, unsigned long arg15 = 0, unsigned long arg16 = 0, unsigned long arg17 = 0, unsigned long arg18 = 0, unsigned long arg19 = 0)
+
+unsigned long
+call20_Win(char *msg, unsigned long fp, unsigned long arg0 = 0, unsigned long arg1 = 0, unsigned long arg2 = 0, unsigned long arg3 = 0, unsigned long arg4 = 0, unsigned long arg5 = 0, unsigned long arg6 = 0, unsigned long arg7 = 0, unsigned long arg8 = 0, unsigned long arg9 = 0, unsigned long arg10 = 0, unsigned long arg11 = 0, unsigned long arg12 = 0, unsigned long arg13 = 0, unsigned long arg14 = 0, unsigned long arg15 = 0, unsigned long arg16 = 0, unsigned long arg17 = 0, unsigned long arg18 = 0, unsigned long arg19 = 0)
+
+unsigned long
+call20_Win_0OK(char *msg, unsigned long fp, unsigned long arg0 = 0, unsigned long arg1 = 0, unsigned long arg2 = 0, unsigned long arg3 = 0, unsigned long arg4 = 0, unsigned long arg5 = 0, unsigned long arg6 = 0, unsigned long arg7 = 0, unsigned long arg8 = 0, unsigned long arg9 = 0, unsigned long arg10 = 0, unsigned long arg11 = 0, unsigned long arg12 = 0, unsigned long arg13 = 0, unsigned long arg14 = 0, unsigned long arg15 = 0, unsigned long arg16 = 0, unsigned long arg17 = 0, unsigned long arg18 = 0, unsigned long arg19 = 0)
+
+unsigned long
+call20_Win_0OK_survive(unsigned long fp, unsigned long arg0 = 0, unsigned long arg1 = 0, unsigned long arg2 = 0, unsigned long arg3 = 0, unsigned long arg4 = 0, unsigned long arg5 = 0, unsigned long arg6 = 0, unsigned long arg7 = 0, unsigned long arg8 = 0, unsigned long arg9 = 0, unsigned long arg10 = 0, unsigned long arg11 = 0, unsigned long arg12 = 0, unsigned long arg13 = 0, unsigned long arg14 = 0, unsigned long arg15 = 0, unsigned long arg16 = 0, unsigned long arg17 = 0, unsigned long arg18 = 0, unsigned long arg19 = 0)
+
+unsigned long
+call20_rp3_p(unsigned long fp, char* argv)
+
+unsigned long
+call20_rp3(unsigned long fp, unsigned long arg0 = 0, unsigned long arg1 = 0, unsigned long arg2 = 0, unsigned long arg3 = 0, unsigned long arg4 = 0, unsigned long arg5 = 0, unsigned long arg6 = 0, unsigned long arg7 = 0, unsigned long arg8 = 0, unsigned long arg9 = 0, unsigned long arg10 = 0, unsigned long arg11 = 0, unsigned long arg12 = 0, unsigned long arg13 = 0, unsigned long arg14 = 0, unsigned long arg15 = 0, unsigned long arg16 = 0, unsigned long arg17 = 0, unsigned long arg18 = 0, unsigned long arg19 = 0)
+
SV *
_call(name, address, queue="SESSION", ...)
char * name
diff --git a/os2/OS2/REXX/t/rx_emxrv.t b/os2/OS2/REXX/t/rx_emxrv.t
index d51e1b0e32..5df8c32785 100644
--- a/os2/OS2/REXX/t/rx_emxrv.t
+++ b/os2/OS2/REXX/t/rx_emxrv.t
@@ -8,7 +8,7 @@ BEGIN {
}
}
-print "1..5\n";
+print "1..20\n";
require OS2::DLL;
print "ok 1\n";
@@ -22,3 +22,40 @@ print "ok 4\n";
$reason = '';
$emx_version >= 99 and $reason = ' # skipped: version of EMX 100 or more'; # Be safe
print "ok 5$reason\n";
+
+$emx_fullname = OS2::DLLname 0x202, $emx_dll->{Handle}; # Handle ==> fullname
+print "ok 6\n";
+$emx_dll1 = OS2::DLL->module($emx_fullname);
+print "ok 7\n";
+$emx_dll->{Handle} == $emx_dll1->{Handle} or print "not ";
+print "ok 8\n";
+
+$emx_version1 = $emx_dll1->emx_revision();
+print "ok 9\n";
+$emx_version1 eq $emx_version or print "not ";
+print "ok 10\n";
+
+$emx_revision = $emx_dll->wrapper_REXX('emx_revision');
+print "ok 11\n";
+$emx_version2 = $emx_revision->();
+print "ok 12\n";
+$emx_version2 eq $emx_version or print "not ";
+print "ok 13\n";
+
+$emx_revision1 = $emx_dll1->wrapper_REXX('#128');
+print "ok 14\n";
+$emx_version3 = $emx_revision1->();
+print "ok 15\n";
+$emx_version3 eq $emx_version or print "not ";
+print "ok 16\n";
+
+($emx_fullname1 = $emx_fullname) =~ s,/,\\,g;
+$emx_dll2 = OS2::DLL->new($emx_fullname1);
+print "ok 17\n";
+$emx_dll->{Handle} == $emx_dll2->{Handle} or print "not ";
+print "ok 18\n";
+
+$emx_version4 = $emx_dll2->emx_revision();
+print "ok 19\n";
+$emx_version4 eq $emx_version or print "not ";
+print "ok 20\n";
diff --git a/os2/OS2/REXX/t/rx_objcall.t b/os2/OS2/REXX/t/rx_objcall.t
index b1154757d4..0ec67b112d 100644
--- a/os2/OS2/REXX/t/rx_objcall.t
+++ b/os2/OS2/REXX/t/rx_objcall.t
@@ -30,4 +30,9 @@ print "ok 4\n" if $res[0] == $$;
print "# @pid\n";
eval { $rxu->nixda(); };
-print "ok 5\n" if $@ =~ /^Can't find entry 'nixda\'/;
+my $err = $@;
+if ($err) {
+ $err =~ s/\n/\n#\t/g;
+ print "# \$\@ = '$err'\n";
+}
+print "ok 5\n" if $@ =~ /^Can't find symbol `nixda\'/;