×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Why can't I invoke this external routine?

Why can't I invoke this external routine?

Why can't I invoke this external routine?

(OP)
I have the following subroutine (ooREXX on Windows):
                                       /* REXX external subroutine   */
/* ----------------------------------------------------------------- */
SQRT:                                  /*@                           */
	arg nbr .
	parse var nbr whole "." frac
	if \Datatype(whole,"W") then whole = 0
	if \Datatype(frac ,"W") then frac  = 0; else frac = "."frac
	if Length(whole)//2 = 0 then parse var whole base 3 tail
				else parse var whole base 2 tail
	root = (base/2) * (10**(Length(tail)%2)) + frac
	numeric digits 12
	lastdiff = 0
	do forever
	   diff = nbr - root**2
	   if diff = 0 then leave
	   if diff = lastdiff then leave
	   lastdiff = diff
	   root  =  root + ((diff/2) /root)
	end
	numeric digits 11
	root = root + 0
	root 	=	Strip( root , "T" , '0' )
	root 	=	Strip( root , "T" , '.' )
return root                            /*@ SQRT                      */   
 

It lives in the same directory as its caller and is called as
area = SQRT( s *(s-a )*( s-b )*( s-c ) )
That statement blows up with "routine not found". When I make SQRT an internal routine, everything works as designed. What am I doing wrong?

Frank Clarke
--America's source for adverse opinions since 1943.

RE: Why can't I invoke this external routine?

Hi, it works for me:

I stored your subroutine SQRT in a file with the same name, i.e.:
sqrt.rex

CODE

SQRT:
  say "* Subroutine SQRT by rexxhead"
  arg nbr .
  parse var nbr whole "." frac
  if \Datatype(whole,"W") then whole = 0
  if \Datatype(frac ,"W") then frac  = 0; else frac = "."frac
  if Length(whole)//2 = 0 then parse var whole base 3 tail
                          else parse var whole base 2 tail
  root = (base/2) * (10**(Length(tail)%2)) + frac
  numeric digits 12
  lastdiff = 0
  do forever
    diff = nbr - root**2
    if diff = 0 then leave
    if diff = lastdiff then leave
    lastdiff = diff
    root  =  root + ((diff/2) /root)
  end
  numeric digits 11
  root = root + 0
  root = Strip( root , "T" , '0' )
  root = Strip( root , "T" , '.' )
return root 

then I created in the same directory the second source file:
caller_01.rex

CODE

-- test the function
x = 1000
y = sqrt(x)
say "x =" x
say "sqrt("||x||") =" y 
exit 

calling it delivers result

CODE

c:\00_mikrom\Work\REXX>rexx caller_01.rex
* Subroutine SQRT by rexxhead
x = 1000
sqrt(1000) = 31.622776602 

RE: Why can't I invoke this external routine?

(OP)
Does it work if you eliminate the 'rexx' and the '.rex'?

c:\00_mikrom\Work\REXX>caller_01 
?

That's how I'm calling it:

F:\REXX\ooREXXcode>hero 13 14 15
A triangle with sides   13     14     15    has an area of 84 

Frank Clarke
--America's source for adverse opinions since 1943.

RE: Why can't I invoke this external routine?

Quote (rexxhead)


Does it work if you eliminate the 'rexx' and the '.rex'?

yes it works:

CODE

c:\00_mikrom\Work\REXX>caller_01.rex
x = 1000
* Subroutine SQRT by rexxhead
sqrt(1000) = 31.622776602


c:\00_mikrom\Work\REXX>caller_01
x = 1000
* Subroutine SQRT by rexxhead
sqrt(1000) = 31.622776602 

RE: Why can't I invoke this external routine?

(OP)
Maybe at 78 I'm just starting to show signs of dementia.

I copied yours just to prove it works in my environment. It worked.

I copied my original, excised the internal SQRT code, and moved the complex multiplication outside the call and just did "area = SQRT(x)". It worked.

I modified the original to just excise the internal SQRT code. It worked.

I have no idea why it works now and didn't work then.

Thank you for your patience.

Frank Clarke
--America's source for adverse opinions since 1943.

RE: Why can't I invoke this external routine?

Probably you got the error, because the name of your source file where the code of the function SQRT is stored was not exactly sqrt.rex or sqrt

First I named my source file with SQRT functions.rex, thinking that I could have in one source file more functions, but then I got the error like you.

RE: Why can't I invoke this external routine?

I'm not sure if it's possible in standard REXX to have multiple external routines stored in one file.
But in ooREXX we can do that with the built-in ::routine and ::requires commands.
Here is the example:

I have this source file which contains two functions tagged with ::routine and public

functions.rex

CODE

::routine sqrt public
  say "* Function: SQRT by rexxhead"
  arg nbr .
  parse var nbr whole "." frac
  if \Datatype(whole,"W") then whole = 0
  if \Datatype(frac ,"W") then frac  = 0; else frac = "."frac
  if Length(whole)//2 = 0 then parse var whole base 3 tail
                          else parse var whole base 2 tail
  root = (base/2) * (10**(Length(tail)%2)) + frac
  numeric digits 12
  lastdiff = 0
  do forever
    diff = nbr - root**2
    if diff = 0 then leave
    if diff = lastdiff then leave
    lastdiff = diff
    root  =  root + ((diff/2) /root)
  end
  numeric digits 11
  root = root + 0
  root = Strip( root , "T" , '0' )
  root = Strip( root , "T" , '.' )
return root

::routine integer_of_sqrt public
  say "* Function: Integer Part of Square Root"
  n = arg(1)
  r = 0
  do while (r*r <= n)
    r = r + 1
  end
  r = r - 1
return r 

Then I have this source file with the main program which ::requires "functions.rex" and call the external routines

caller_02.rex

CODE

-- test functions
x = 1000
say "x =" x
say

y = sqrt(x)
say "sqrt("||x||") =" y 
say

y = integer_of_sqrt(x)
say "integer_of_sqrt("||x||") =" y
say 
exit

::requires "functions.rex" 

Note, that ::requires statement should be placed at the end of the source file.

Now, running caller_02 delivers the following results:

CODE

c:\00_mikrom\Work\REXX>caller_02
x = 1000

* Function: SQRT by rexxhead
sqrt(1000) = 31.622776602

* Function: Integer Part of Square Root
integer_of_sqrt(1000) = 31 

RE: Why can't I invoke this external routine?

(OP)
No, standard REXX doesn't include the notion of a library of external routines, dammit, nor does it allow (as PL/I and COBOL) to INCLUDE blocks of external text. The latter, in fact, would practically eliminate the need for the former.

Oh, how I would love to be able to

/* REXX Routine */
%INCLUDE stdfront
call a_init
call b_prolog
call m_main_processing
call z_epilog
%INCLUDE stdback
 

Instead, I copy in my canonical boilerplate code and then insert code to do whatever the instant function calls for.

Frank Clarke
--America's source for adverse opinions since 1943.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close