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