1package OS2::REXX;
2
3require Exporter;
4use XSLoader;
5require OS2::DLL;
6
7@ISA = qw(Exporter);
8# Items to export into callers namespace by default
9# (move infrequently used names to @EXPORT_OK below)
10@EXPORT = qw(REXX_call REXX_eval REXX_eval_with);
11# Other items we are prepared to export if requested
12@EXPORT_OK = qw(drop register);
13
14$VERSION = '1.05';
15
16# We cannot just put OS2::DLL in @ISA, since some scripts would use
17# function interface, not method interface...
18
19*_call = \&OS2::DLL::_call;
20*load = \&OS2::DLL::load;
21*find = \&OS2::DLL::find;
22
23XSLoader::load 'OS2::REXX';
24
25# Preloaded methods go here.  Autoload methods go after __END__, and are
26# processed by the autosplit program.
27
28sub register {_register($_) for @_}
29
30sub prefix
31{
32	my $self = shift;
33	$self->{Prefix} = shift;
34}
35
36sub queue
37{
38	my $self = shift;
39	$self->{Queue} = shift;
40}
41
42sub drop
43{				# Supposedly should drop anything with
44                                # the given prefix. Unfortunately a
45                                # loop is needed after fixpack17.
46&OS2::REXX::_drop(@_);
47}
48
49sub dropall
50{				# Supposedly should drop anything with
51                                # the given prefix. Unfortunately a
52                                # loop is needed after fixpack17.
53  &OS2::REXX::_drop(@_);	# Try to drop them all.
54  my $name;
55  for (@_) {
56    if (/\.$/) {
57      OS2::REXX::_fetch('DUMMY'); # reset REXX's first/next iterator
58      while (($name) = OS2::REXX::_next($_)) {
59	OS2::REXX::_drop($_ . $name);
60      }
61    }
62  }
63}
64
65sub TIESCALAR
66{
67	my ($obj, $name) = @_;
68	$name =~ s/^([\w!?]+)/\U$1\E/;
69	return bless \$name, OS2::REXX::_SCALAR;
70}
71
72sub TIEARRAY
73{
74	my ($obj, $name) = @_;
75	$name =~ s/^([\w!?]+)/\U$1\E/;
76	return bless [$name, 0], OS2::REXX::_ARRAY;
77}
78
79sub TIEHASH
80{
81	my ($obj, $name) = @_;
82	$name =~ s/^([\w!?]+)/\U$1\E/;
83	return bless {Stem => $name}, OS2::REXX::_HASH;
84}
85
86#############################################################################
87package OS2::REXX::_SCALAR;
88
89sub FETCH
90{
91	return OS2::REXX::_fetch(${$_[0]});
92}
93
94sub STORE
95{
96	return OS2::REXX::_set(${$_[0]}, $_[1]);
97}
98
99sub DESTROY
100{
101	return OS2::REXX::_drop(${$_[0]});
102}
103
104#############################################################################
105package OS2::REXX::_ARRAY;
106
107sub FETCH
108{
109	$_[0]->[1] = $_[1] if $_[1] > $_[0]->[1];
110	return OS2::REXX::_fetch($_[0]->[0].'.'.(0+$_[1]));
111}
112
113sub STORE
114{
115	$_[0]->[1] = $_[1] if $_[1] > $_[0]->[1];
116	return OS2::REXX::_set($_[0]->[0].'.'.(0+$_[1]), $_[2]);
117}
118
119#############################################################################
120package OS2::REXX::_HASH;
121
122require Tie::Hash;
123@ISA = ('Tie::Hash');
124
125sub FIRSTKEY
126{
127	my ($self) = @_;
128	my $stem = $self->{Stem};
129
130	delete $self->{List} if exists $self->{List};
131
132	my @list = ();
133	my ($name, $value);
134	OS2::REXX::_fetch('DUMMY'); # reset REXX's first/next iterator
135	while (($name) = OS2::REXX::_next($stem)) {
136		push @list, $name;
137	}
138	my $key = pop @list;
139
140	$self->{List} = \@list;
141	return $key;
142}
143
144sub NEXTKEY
145{
146	return pop @{$_[0]->{List}};
147}
148
149sub EXISTS
150{
151	return defined OS2::REXX::_fetch($_[0]->{Stem}.$_[1]);
152}
153
154sub FETCH
155{
156	return OS2::REXX::_fetch($_[0]->{Stem}.$_[1]);
157}
158
159sub STORE
160{
161	return OS2::REXX::_set($_[0]->{Stem}.$_[1], $_[2]);
162}
163
164sub DELETE
165{
166	OS2::REXX::_drop($_[0]->{Stem}.$_[1]);
167}
168
169#############################################################################
170package OS2::REXX;
171
1721;
173__END__
174
175=head1 NAME
176
177OS2::REXX - access to DLLs with REXX calling convention and REXX runtime.
178
179=head2 NOTE
180
181By default, the REXX variable pool is not available, neither
182to Perl, nor to external REXX functions. To enable it, you need to put
183your code inside C<REXX_call> function.  REXX functions which do not use
184variables may be usable even without C<REXX_call> though.
185
186=head1 SYNOPSIS
187
188	use OS2::REXX;
189	$ydb = load OS2::REXX "ydbautil" or die "Cannot load: $!";
190	@pid = $ydb->RxProcId();
191	REXX_call {
192	  tie $s, OS2::REXX, "TEST";
193	  $s = 1;
194	};
195
196=head1 DESCRIPTION
197
198=head2 Load REXX DLL
199
200	$dll = load OS2::REXX NAME [, WHERE];
201
202NAME is DLL name, without path and extension.
203
204Directories are searched WHERE first (list of dirs), then environment
205paths PERL5REXX, PERLREXX, PATH or, as last resort, OS/2-ish search
206is performed in default DLL path (without adding paths and extensions).
207
208The DLL is not unloaded when the variable dies.
209
210Returns DLL object reference, or undef on failure.
211
212=head2 Define function prefix:
213
214	$dll->prefix(NAME);
215
216Define the prefix of external functions, prepended to the function
217names used within your program, when looking for the entries in the
218DLL.
219
220=head2 Example
221
222		$dll = load OS2::REXX "RexxBase";
223		$dll->prefix("RexxBase_");
224		$dll->Init();
225
226is the same as
227
228		$dll = load OS2::REXX "RexxBase";
229		$dll->RexxBase_Init();
230
231=head2 Define queue:
232
233	$dll->queue(NAME);
234
235Define the name of the REXX queue passed to all external
236functions of this module. Defaults to "SESSION".
237
238Check for functions (optional):
239
240	BOOL = $dll->find(NAME [, NAME [, ...]]);
241
242Returns true if all functions are available.
243
244=head2 Call external REXX function:
245
246	$dll->function(arguments);
247
248Returns the return string if the return code is 0, else undef.
249Dies with error message if the function is not available.
250
251=head1 Accessing REXX-runtime
252
253While calling functions with REXX signature does not require the presence
254of the system REXX DLL, there are some actions which require REXX-runtime
255present. Among them is the access to REXX variables by name.
256
257One enables REXX runtime by bracketing your code by
258
259	REXX_call BLOCK;
260
261(trailing semicolon required!) or
262
263	REXX_call \&subroutine_name;
264
265Inside such a call one has access to REXX variables (see below).
266
267An alternative way to execute code inside a REXX compartment is
268
269	REXX_eval EXPR;
270	REXX_eval_with EXPR,
271		subroutine_name_in_REXX => \&Perl_subroutine
272
273Here C<EXPR> is a REXX code to run; to execute Perl code one needs to put
274it inside Perl_subroutine(), and call this subroutine from REXX, as in
275
276	REXX_eval_with <<EOE, foo => sub { 123 * shift };
277	  say foo(2)
278	EOE
279
280If one needs more Perl subroutines available, one can "import" them into
281REXX from inside Perl_subroutine(); since REXX is not case-sensitive,
282the names should be uppercased.
283
284	use OS2::REXX 'register';
285
286	sub BAR { 123 + shift}
287	sub BAZ { 789 }
288	sub importer { register qw(BAR BAZ) }
289
290	REXX_eval_with <<'EOE', importer => \&importer;
291	  call importer
292	  say bar(34)
293	  say baz()
294	EOE
295
296=head2 Bind scalar variable to REXX variable:
297
298	tie $var, OS2::REXX, "NAME";
299
300=head2 Bind array variable to REXX stem variable:
301
302	tie @var, OS2::REXX, "NAME.";
303
304Only scalar operations work so far. No array assignments, no array
305operations, ... FORGET IT.
306
307=head2 Bind hash array variable to REXX stem variable:
308
309	tie %var, OS2::REXX, "NAME.";
310
311To access all visible REXX variables via hash array, bind to "";
312
313No array assignments. No array operations, other than hash array
314operations. Just like the *dbm based implementations.
315
316For the usual REXX stem variables, append a "." to the name,
317as shown above. If the hash key is part of the stem name, for
318example if you bind to "", you cannot use lower case in the stem
319part of the key and it is subject to character set restrictions.
320
321=head2 Erase individual REXX variables (bound or not):
322
323	OS2::REXX::drop("NAME" [, "NAME" [, ...]]);
324
325=head2 Erase REXX variables with given stem (bound or not):
326
327	OS2::REXX::dropall("STEM" [, "STEM" [, ...]]);
328
329=head2 Make Perl functions available in REXX:
330
331	OS2::REXX::register("NAME" [, "NAME" [, ...]]);
332
333Since REXX is not case-sensitive, the names should be uppercase.
334
335=head1 Subcommand handlers
336
337By default, the executed REXX code runs without any default subcommand
338handler present.  A subcommand handler named C<PERLEVAL> is defined, but
339not made a default.  Use C<ADDRESS PERLEVAL> REXX command to make it a default
340handler; alternatively, use C<ADDRESS Handler WhatToDo> to direct a command
341to the handler you like.
342
343Experiments show that the handler C<CMD> is also available; probably it is
344provided by the REXX runtime.
345
346=head1 Interfacing from REXX to Perl
347
348This module provides an interface from Perl to REXX, and from REXX-inside-Perl
349back to Perl.  There is an alternative scenario which allows usage of Perl
350from inside REXX.
351
352A DLL F<PerlRexx> provides an API to Perl as REXX functions
353
354  PERL
355  PERLTERM
356  PERLINIT
357  PERLEXIT
358  PERLEVAL
359  PERLLASTERROR
360  PERLEXPORTALL
361  PERLDROPALL
362  PERLDROPALLEXIT
363
364A subcommand handler C<PERLEVALSUBCOMMAND> can also be registered.  Calling
365the function PERLEXPORTALL() exports all these functions, as well as
366exports this subcommand handler under the name C<EVALPERL>.  PERLDROPALL()
367inverts this action (and unloads PERLEXPORTALL() as well).  In particular
368
369  rc = RxFuncAdd("PerlExportAll", 'PerlRexx', "PERLEXPORTALL")
370  rc = PerlExportAll()
371  res = PERLEVAL(perlarg)
372  ADDRESS EVALPERL perlarg1
373  rc = PerlDropAllExit()
374
375loads all the functions above, evals the Perl code in the REXX variable
376C<perlarg>, putting the result into the REXX variable C<res>,
377then evals the Perl code in the REXX variable C<perlarg1>, and, finally,
378drops the loaded functions and the subcommand handler, deinitializes
379the Perl interpreter, and exits the Perl's C runtime library.
380
381PERLEXIT() or PERLDROPALLEXIT() should be called as the last command of
382the REXX program.  (This is considered as a bug.)  Their purpose is to flush
383all the output buffers of the Perl's C runtime library.
384
385C<PERLLASTERROR> gives the reason for the failure of the last PERLEVAL().
386It is useful inside C<signal on syntax> handler.  PERLINIT() and PERLTERM()
387initialize and deinitialize the Perl interpreter.
388
389C<PERLEVAL(string)> initializes the Perl interpreter (if needed), and
390evaluates C<string> as Perl code.  The result is returned to REXX stringified,
391undefined result is considered as failure.
392
393C<PERL(string)> does the same as C<PERLEVAL(string)> wrapped by calls to
394PERLINIT() and PERLEXIT().
395
396=head1 NOTES
397
398Note that while function and variable names are case insensitive in the
399REXX language, function names exported by a DLL and the REXX variables
400(as seen by Perl through the chosen API) are all case sensitive!
401
402Most REXX DLLs export function names all upper case, but there are a
403few which export mixed case names (such as RxExtras). When trying to
404find the entry point, both exact case and all upper case are searched.
405If the DLL exports "RxNap", you have to specify the exact case, if it
406exports "RXOPEN", you can use any case.
407
408To avoid interfering with subroutine names defined by Perl (DESTROY)
409or used within the REXX module (prefix, find), it is best to use mixed
410case and to avoid lowercase only or uppercase only names when calling
411REXX functions. Be consistent. The same function written in different
412ways results in different Perl stubs.
413
414There is no REXX interpolation on variable names, so the REXX variable
415name TEST.ONE is not affected by some other REXX variable ONE. And it
416is not the same variable as TEST.one!
417
418You cannot call REXX functions which are not exported by the DLL.
419While most DLLs export all their functions, some, like RxFTP, export
420only "...LoadFuncs", which registers the functions within REXX only.
421
422You cannot call 16-bit DLLs. The few interesting ones I found
423(FTP,NETB,APPC) do not export their functions.
424
425I do not know whether the REXX API is reentrant with respect to
426exceptions (signals) when the REXX top-level exception handler is
427overridden. So unless you know better than I do, do not access REXX
428variables (probably tied to Perl variables) or call REXX functions
429which access REXX queues or REXX variables in signal handlers.
430
431See C<t/rx*.t> and the next section for examples.
432
433=head1 EXAMPLE
434
435 use OS2::REXX;
436
437 sub Ender::DESTROY { $vrexx->VExit; print "Exiting...\n" }
438
439 $vrexx = OS2::REXX->load('VREXX');
440 REXX_call {			# VOpenWindow takes a stem
441   local $SIG{TERM} = sub {die}; # enable Ender::DESTROY
442   local $SIG{INT} = sub {die};	# enable Ender::DESTROY
443
444   $code = $vrexx->VInit;
445   print "Init code = `$code'\n";
446   die "error initializing VREXX" if $code eq 'ERROR';
447
448   my $ender = bless [], 'Ender'; # Call Ender::DESTROY on exit
449
450   print "VREXX Version ", $vrexx->VGetVersion, "\n";
451
452   tie %pos, 'OS2::REXX', 'POS.' or die;
453   %pos = ( LEFT   => 0, RIGHT  => 7, TOP    => 5, BOTTOM => 0 );
454
455   $id = $vrexx->VOpenWindow('To disconnect:', 'WHITE', 'POS');
456   $vrexx->VForeColor($id, 'BLACK');
457   $vrexx->VSetFont($id, 'TIME', '30');
458   $tlim = time + 60;
459   while ( ($r = $tlim - time) >= 0 ) {
460     $vrexx->VClearWindow($id);
461     $vrexx->VSay($id, 100, 50, (sprintf "%02i:%02i", int($r/60),
462                                                              $r % 60));
463     sleep 1;
464   }
465   print "Close code = `$res'\n" if $res = $vrexx->VCloseWindow($id);
466 };
467
468
469
470=head1 ENVIRONMENT
471
472If C<PERL_REXX_DEBUG> is set, prints trace info on calls to REXX runtime
473environment.
474
475=head1 AUTHOR
476
477Andreas Kaiser ak@ananke.s.bawue.de, with additions by Ilya Zakharevich
478ilya@math.ohio-state.edu.
479
480=head1 SEE ALSO
481
482L<OS2::DLL>.
483
484=cut
485