[comp.lang.misc] Call by string

sommar@enea.se (Erland Sommarskog) (01/22/89)

Some while ago I asked the following:
>But to throw some new wood on the fire, consider the following: Assume
>you have routine you want to call but whose name you don't know until
>run-time, thus you have the name in a string. Now in which langauges
>can you easily do this? Interpreting langauges like Lisp and Basic,
>support this I guess. But compiled langauges?

Since then several people have answered in various waays.
  First, some posters have corrected me and pointed out that Lisp 
could be compiled too. Of course, there is no particular problem with
implementing this in a compiled langauge; the problem lies in that 
the compiler can't perform the validation we often expect it to. 
Whether parameter profiles will match or not it can't tell. (Well, 
if we are using some 3rd class language we are not expecting this 
validation anyway.) Just finding the procedure to call it's simply 
a matter of having suffcient symbol information around.
  Someone said that this was just like a CASE statement in language
in Ada or Pascal. Most emphatically: IT'S NOT! I'll present you later
with a problem which isn't solveable with a simple CASE.
  Someone told us about $entry in PRIMOS(?). And VMS has 
LIB$Find_image_symbol for finding the address to a name, and then 
LIB$CallG for calling it. Unix surely have something similar. Yes,
this seems like the way to go. Rely on what the OS gives you. Not 
very portable though.
  Peter da Silva (peter@ficc.uu.net) said:
>I do this all the time in 'C', for one reason or another. 
>...
>} funtab[] = {
>	"fname1", func1,
>	"fname2", func2,
>...
This is of course no better no solution than the CASE proposal. Maybe
a litlte more convenient, but still have one serious problem: the names
of the routines to call must be known at coding time.

The problem I talked of: A general reusable menu handler. When the 
end-user starts the program he gets the main menu. He types a code
which the menu handler looks up in the database. The code may refer 
to another menu which in this case is displayed. It may also refer
to a specific function. In this case the menu handler calls the 
routine whose *name* it found in the database.
  The menu handler here is a reusable module which you link into
your system, probably as the main program. This is where the CASE
solution is totally unsatisfactory. For every new function we add, 
we have to modify the menu handler. Not talking of the case of moving 
to another application with new names and function codes.
  But Peter's function tables? Could one not require that every
function loads a table entry at startup with itself? The global access
cannot be a problem. Unfortunately, there is a little obstacle.
To do the loading the module has to be activated. But by whom? The
menu handler does at this stage not know about it. So you have to
have some other code that knows about all functions in the system,
and this is exactly what we want to avoid.
  (The self-loading approach could maybe work in a language with 
parallell processes, but I fail to find something workable for Ada. 
And if there is something it is a big overkill anyway.)

So in what langauge can you implement the calling-part of this menu 
handler without calling some OS function? (It will be interesting to 
see what ideas that turn up this time.)
-- 
Erland Sommarskog
ENEA Data, Stockholm              This signature is not to be quoted.
sommar@enea.se

db@lfcs.ed.ac.uk (Dave Berry) (01/24/89)

In article <4261@enea.se> sommar@enea.se (Erland Sommarskog) writes:
>  But Peter's function tables? Could one not require that every
>function loads a table entry at startup with itself? The global access
>cannot be a problem. Unfortunately, there is a little obstacle.
>To do the loading the module has to be activated. But by whom? The
>menu handler does at this stage not know about it. So you have to
>have some other code that knows about all functions in the system,
>and this is exactly what we want to avoid.

I'm not sure I understand this example.  Couldn't one use a generic menu
handler that takes a list of names and a symbol table as a parameter?
I don't see why you need to avoid a piece of code that knows about
all the functions in scope in your system, provided that that code doesn't
constrain the men handler to dealing with a specific system.


Dave Berry,	Laboratory for Foundations of Computer Science, Edinburgh.
		db%lfcs.ed.ac.uk@nss.cs.ucl.ac.uk
		<Atlantic Ocean>!mcvax!ukc!lfcs!db

peter@ficc.uu.net (Peter da Silva) (01/24/89)

In article <4261@enea.se>, sommar@enea.se (Erland Sommarskog) writes:
>   But Peter's function tables? Could one not require that every
> function loads a table entry at startup with itself? The global access
> cannot be a problem. Unfortunately, there is a little obstacle.
> To do the loading the module has to be activated. But by whom? The
> menu handler does at this stage not know about it. So you have to
> have some other code that knows about all functions in the system,
> and this is exactly what we want to avoid.

Well, there are a number of objections to this argument.

First of all, not all functions are suitable for use in a menu... even
in a language like Forth. Lisp, where each routine effectively validates
all its arguments at run time might be able to get away with this, but
the overhead seems a little high. The programmer knows which functions
do make sense, and can stick them in the table.

Secondly, some languages (Modula, for example) do have an initialisation
section for each module. Stick them here.

Finally, have you never heard of a preprocessor? Put this in your code:

function(args) /* %id "name" */
...

Then run the following script from your makefile:

	sed -n '/%id/s/\(.*\)(.*%id \(".*"\).*/	\2, \1,/' *.c > functab.i

And finally:

functab.c:

struct {
	char *name;
	int (*func)();
} functab {
#include "functab.i"
}; ...

> So in what langauge can you implement the calling-part of this menu 
> handler without calling some OS function? (It will be interesting to 
> see what ideas that turn up this time.)

If you really want to be sick, you can do this:

call.h:
struct fentry { char tag[4], *name; int (*func)(); };

#include "call.h"

struct fentry foobar_entry = { "%id", "foobar", foobar };

And then do a linear search through memory for the unique tag string at
startup time.

Gross, wot? I got the inspiration for this from some guy's 'C' garbage
collection code.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.   `-_-'
Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.                 'U`
Opinions may not represent the policies of FICC or the Xenix Support group.

mcdonald@uxe.cso.uiuc.edu (01/27/89)

>Some while ago I asked the following:
>But to throw some new wood on the fire, consider the following: Assume
>you have routine you want to call but whose name you don't know until
>run-time, thus you have the name in a string. Now in which langauges
>can you easily do this? Interpreting langauges like Lisp and Basic,
>support this I guess. But compiled langauges?

I think that you are asking the wrong question, or maybe only a subset
of the full question. There are lots of languages (most?) where you
could find a way of getting to any routine known at original
compile-time. The real problem comes in getting at routines COMPILED
at run time. This often becomes an operating system question: it appears
that there are operating systems where it is impossible without
logging in from the operator's console. 

Doug McDonald

jefu@pawl.rpi.edu (Jeffrey Putnam) (01/29/89)

In article <51300013@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.edu writes:

>>Some while ago I asked the following:
>>But to throw some new wood on the fire, consider the following: Assume
>>you have routine you want to call but whose name you don't know until
>>run-time, thus you have the name in a string. Now in which langauges
>>can you easily do this? Interpreting langauges like Lisp and Basic,
>>support this I guess. But compiled langauges?

>I think that you are asking the wrong question, or maybe only a subset
>of the full question. There are lots of languages (most?) where you
>could find a way of getting to any routine known at original
>compile-time. The real problem comes in getting at routines COMPILED
>at run time. This often becomes an operating system question: it appears
>that there are operating systems where it is impossible without
>logging in from the operator's console. 

I have been following this discussion for a while and just realized this
morning that it is possible that everyone has been asking the wrong question.
(Parenthetically, i worked out a scheme whereby a C program compiled with
debugging stuff on could read its symbol table and then jump to the 
address of the appropriate subroutine.  Cute.)  

The question is, "why do you want to do this?"  Im sure that there
are valid reasons for wanting to do something like this, (i can think
of many) but in most cases, what is wanted is not to be able to jump
to just any subroutine, but only to some specific subset of the
subroutines.  In that case, there is no reason not to use a compiled table
of "name -> address" as has been previously suggested.  

(But, as mentioned above, this compiled table might be produced by the 
C compiler (ick!).)


jeff putnam        -- "Sometimes one must attempt the impossible if only to
jefu@pawl.rpi.edu  --  show it is merely inadvisable."

sommar@enea.se (Erland Sommarskog) (01/30/89)

It's possible I have missed some responses to my previous article,
news flow seems to have been incomplete last week, so there
is a risk someone has said what I wanted to hear. Anyway, this
article tells how the menu handler I talked of actually was
implemented.

Some replay for newcomers: In the discussion about Bondage &
Discipline langauges I said that a lanaguge like C was a B&D
language if I want to call a routine by its name which I have
in a string. As an example I gave a menu handler that should
be reusable, and with knowledge of the routines in the application
within its code, but in a user-loaded database. 

But before I give the final clues and reveal the answer some 
comments to other people comments. Beside the articles, I got
some mail too.

Obviously it would be trivial to implement the menu handler
(at least the calling part of it) in Lisp, Scheme and PS-Algol.
  Then there was a discussion of C. And, yes, in every practical
case, we can implement the handler in C. Either we could ship the 
menu handler with a program that reads the database and from that
generates the code that loads a function table. This generated
module would then be linked with the system and called at startup.
(Or be the startup program itself.) Another solution if you are on 
Unix if to use nlist(3) that someone pointed out to me. This may not 
be portable, though.
  So we can use C, yes, but with a lot of work and inconvenince.
Clearly a case of B&D it seems to me.
  In Modula which has initiation parts in the module we could require
that each menu-selection routine loads itself in the initiation part.
However, we run the risk theat the application programmer is messing
things up. (Typically one such routine is in a module of its, since
it more or less an independent program.) It works, but it's still B&D.

One language that hasn't been mentioned is MUMPS. In MUMPS you
have XECUTE, which simple executes its string argument. (This
is an interpreted langauge, so it's easy.) The string could of
course be a procedure call as anything else. I thought this
could be common in some BASICs too, that's why I originally
mentioned BASIC. As a whole such constructs are easy to implement
in interpreted langauges. Not so easy in compiled ones. (DEC
editor langauge VAXTPU is an example, though.)

But the manu handler I talked of is more than just a theoretical
idea. It exists. Not written by me, but by the people I currently
work with. What language did they use? 
Clue 1: It hasn't been mentioned in the call-by-string discussion so 
far, possibly in the previous B&D language, as an example of a B&D langauge.

Clue 2: It doesn't have a newsgroup of its own on the net.

Some obscure langauge that no one has heard of? Not really. In fact, 
Clue 3: There is an ANSI standard for it. Latest revision in 1985.

Clue 4: The previous ANSI standard is from 1974.

Clue 5: (Now it's getting easy.)
It's probably the world's most commonly used programming langauge.

Answer: COBOL.

It's very simple. The construct is:
    CALL Nisse USING Parameter1, Parameter2....
where Nisse is a string variable. (PIC X(32) or so.)
If Nisse is the name of a routine you want to call, you use quotes:
    CALL "Nisse" USING Parameter1, Parameter2...
Compare this with loading function tables and I don't know what in C!
  Then on the other hand, there are of course things that are simpler
to carry out in C. So that's the point: what's is B&D depends on what 
you want to do. Or in clear text: This talk of B&D is just rubbish.

It's interesting to the see in this company of bright people, no one
mentions Cobol. Reveales that the net community is maybe not
perfectly representable for the programmer community at large. But
don't feel ashamed. I didn't know this capability in Cobol a year ago.

Addendum on the menu handler: Since I have mentioned it, some more
details could be of interest to you. First, it is not written in 
Cobol, only the routine that calls the application routine is. The 
rest is in VAX-Pascal. And since our application also is in VAX-Pascal, 
every application routine needs a little link program in Cobol, since 
there is a restriction with the CALL identifier construct, saying that 
the called routine must be another Cobol routine.
  Actually, we are about to abandon the Cobol solution. The reason
is that with Cobol we must link all routines into one image and it 
gets large, 9000+ blocks. (A block = 512 bytes.) So we're aiming at 
shareable images instead, which would mean LIB$Find_image_symbol. 
What we hope to do, but don't know the performance penalty for it yet, 
is to have every application routine as a shareable image (there are 
around 200 of them currently), which would mean a fix in such a program 
can be delivered instantly. And not only the menu handler's code will 
be application independent, but also the its executeable will be. 
Talk about modular software! (And before someone ask: yes we will 
put common routines in shareable images a la run-time libraries as well.)

Ahum, if you follow up on this addendum, it's probably not a
langauge issue, so look for another newsgroup.
-- 
Erland Sommarskog
ENEA Data, Stockholm              This signature is not to be quoted.
sommar@enea.se

amanda@iesd.uucp (Per Abrahamsen) (01/31/89)

In article <4279@enea.se> sommar@enea.se (Erland Sommarskog) writes:
>  Then on the other hand, there are of course things that are simpler
>to carry out in C. So that's the point: what's is B&D depends on what 
>you want to do. Or in clear text: This talk of B&D is just rubbish.

Who said a language was "B&D" when it made something difficult to do?

The claim was that a language was B&D when the designer intentionally
made something difficult, in order to protect the programmer from
himself. C and Modula 2 don't have a "call string" because it would be
difficult and inefficient to implement in these languages, not because
Richie & Wirth thought it was wrong. 

-- 
Per Abrahamsen,  amanda@iesd.dk, {...}!mcvax!diku!iesd!amanda

djones@megatest.UUCP (Dave Jones) (01/31/89)

From article <403@rpi.edu>, by jefu@pawl.rpi.edu (Jeffrey Putnam):
... 
> I have been following this discussion for a while and just realized this
> morning that it is possible that everyone has been asking the wrong question.
> (Parenthetically, i worked out a scheme whereby a C program compiled with
> debugging stuff on could read its symbol table and then jump to the 
> address of the appropriate subroutine.  Cute.)  
> 


Under BSD4.2  and Sun3, it is not even necessary to compile with
debugging stuff.  Just don't strip out the symbol-table.


> The question is, "why do you want to do this?"

...


The reason might be that the procedure you want to jump to was
compiled after the main program was compiled, and was not, and could
not be, known to the main program at the time of its compilation.

I'll give you a real world example. Well, it's real world if you include
manufacturing and testing computer parts as "real world".

Let's suppose you have engineers all over the world who come up with
designs for ASIC parts. Each of these part-specifications generates
a procedure which tests the part. A program monitors loading chips
or wafers by robot, interacting with the operator, etc., and it keeps
timing calibration and other data concerning the tester itself. The
program has to be able to call any of these part-specific procedures
which had not even been written when the main program was written. But
putting each part-specific procedure in its own process would be 
prohibitively expensive without some mechanism for shared data: It would
take too long to initialize it with the calibration data, etc.,
and it would require too much memory, even with today's multimegabyte
rams.

So the program needs to read the part-specific procedure into memory,
and then branch to it.

djones@megatest.UUCP (Dave Jones) (01/31/89)

From article <4279@enea.se>, by sommar@enea.se (Erland Sommarskog):
...
> Some replay for newcomers: In the discussion about Bondage &
> Discipline langauges I said that a lanaguge like C was a B&D
> language if I want to call a routine by its name which I have
> in a string.

As I understand it, the originators of the term, "B&D language"
use it to refer to languages which prevent or make difficult
certain kinds of programming, not by simple omission, but because the
language designers deemed them Bad Things, and sought to prevent
them by decree.  C does not attempt to prevent you from writing 
a call-by-string routine. It just does not contain call-by-string
as a feature, presumably because the Founding Fathers did not need it
to write Unix.  I have written call-by-string in C for BSD4.2 and Sun3,
and it was not at all difficult.  The only problem was deciphering
the executable (dot-o) format.  The C part was easy. Machine-independence
is down the tubes, of course.  By making it part of the language,
you could move the porting problem from the application programmer
to the C-library programmer, which might be a win, if enough people
use the feature. But as it is, it's not B&D.

oster@dewey.soe.berkeley.edu (David Phillip Oster) (02/01/89)

Under the macintosh operatiing system, call by string is simply:

typedef long (*LFuncPtr)();	/* LFuncPtr is a pointer to a func
				returning a long */
LFuncPtr *byString;

	if(NULL != (byString = (LFuncPtr *) 
		GetNamedResource('XCMD',"\pYour Name Here"))){
		HLock((Handle) byString);
		(**byString)(arg1, arg2, arg3);	/* your args here */
		HUnlock((Handle byString);
	}

explanation:
On the mac, every program has a built-in archive of data called "the
resource fork". The system call GetResource() fetches data by 4-char type
and integer id number. The system call GetNamedResource() fetches data by
f-char type and string name. The "\p" generates a length byte, which is
the kind of string GetNamedResource takes.

It doesn't return a ptr to the data, but a ptr to ptr. The extra level of
indirection lets the system move the data, if it needs to change its size,
so long as I always double indirect when I access through the ptr to ptr.

HLock() tells the system not to move this piece of data for a while.
(Can't have the code moving out from under the program counter while it is
executing!

You could repackage all of the above (except the HUnlock()) as a function
called "CallByString", that takes one argument, a string. It would lock
anmd return a pointer to the code object, if it found it. Otherwise, it
would return a pointer to an error routine.
Then you could say:
	(*CallByString(stringVariable))(arg1, arg2, arg3)

You can't get much cleaner than that.  C hardly seems to be a B&D language
here: as I have proved by demonstrating, with the right library support,
call by string isn't difficult at all in C.

No, if you want B&D, try to call C printf from Pascal. Try to write printf
in pascal.

frode@m2cs.uu.no (Frode Odegard) (02/01/89)

In article <4279@enea.se>, sommar@enea.se (Erland Sommarskog) writes:
>   In Modula which has initiation parts in the module we could require
> that each menu-selection routine loads itself in the initiation part.
> However, we run the risk theat the application programmer is messing
> things up. (Typically one such routine is in a module of its, since
> it more or less an independent program.) It works, but it's still B&D.
> 

We're doing an environment for large Modula projects which includes
lots of Interlisp-D/Symbolics features. It is quite easy to write Modula
programs which write Modula programs and send them off to the interpreter
or the incremental compilation system. The interpreter is yet another
library module... [and this is not a toy, we're going to hit the embedded
systems market HARD in a few months..incremental compilation reduces turn-
around time a LOT].

				- Frode

-- 
| Frode L. Odegard         |"The world is coming to an end! Repent and|
| Modula-2 CASE Systems    |rm /bin/cc"                               |
| NORWAY (EUROPE)     	   |                                          |
| Email: frode@m2cs.uu.no  |                                          |

nick@aimed.UUCP (Nick Pemberton) (02/01/89)

Well, being the PICK hack I am, I couldn't help enjoying watching people
struggle with this one for a while. PICK's warped version of BASIC supports
this feature. If a variable contains a string representing the name of
a routine, one can do a call of the form:

CALL @variable(arg1, [arg2, ...])

there is no limit on the number of arguments; the routine can be any
cataloged routine (cataloged just means compiled and in a 'library').
We use it all the time for a generic window driver: It is a data driven
application that has field descritors within it that are capable of calling
any other BASIC routine. Very usefull. Indispensable, in fact. 
And yes, its possible because PICK BASIC is at least partially interpretted.

Nick.
-- 

Nick Pemberton                   UUCP: !{utzoo,utai}!lsuc!aimed!nick
AIM, Inc                          Bus: (416) 429-4913
                                 Home: (416) 690-0647

nevin1@ihlpb.ATT.COM (Liber) (02/03/89)

In article <4279@enea.se> sommar@enea.se (Erland Sommarskog) writes:
>In the discussion about Bondage &
>Discipline langauges I said that a lanaguge like C was a B&D
>language if I want to call a routine by its name which I have
>in a string.

To be technically correct, what you should have said is that you want
to call a routine by its name which you have in an array of char
terminated by a null byte, and you think that C is a B&D language
because it does not directly support any operations on arrays of char
terminated by a null byte.  "Strings" are NOT first class objects in C,
nor should they be!  No matter how you implement strings (special
terminator, fixed length, keep size separately, etc.), there are always
some applications where it is advantageous, and others where it is not.
One of the benefits of C is that you can implement them any way you
want; the language doesn't tie you down to one implementation.  To call
this B&D (besides not using the original poster's definition) is
ludicrious.
-- 
 _ __	NEVIN ":-)" LIBER  nevin1@ihlpb.ATT.COM  (312) 979-4751  IH 4F-410
' )  )			 "I will not be pushed, filed, stamped, indexed,
 /  / _ , __o  ____	  briefed, debriefed or numbered!  My life is my own!"
/  (_</_\/ <__/ / <_	As far as I know, these are NOT the opinions of AT&T.

frode@m2cs.uu.no (Frode Odegard) (02/05/89)

In article <1260@iesd.uucp>, amanda@iesd.uucp (Per Abrahamsen) writes:
> C and Modula 2 don't have a "call string" because it would be
> difficult and inefficient to implement in these languages, not because
> Richie & Wirth thought it was wrong. 
> 
> -- 
> Per Abrahamsen,  amanda@iesd.dk, {...}!mcvax!diku!iesd!amanda

Well, we're working on an Interlisp-D/Symbolics/Smalltalk -inspired Modula-2
environment on the Sun workstation. The system includes an interpreter and
an incremental compilation system. In our environment programs can build
data structures which are programs (or pieces of programs) and send them off
to the intepreter. The system is based on using a special data structure for
representing Modula-2 source code. This data structure can be manipulated using
library modules available to toolmakers. The editor is pretty "intelligent"
because it works on a higher level than text only. You can view module dependencies
and stuff like that, and it is easy to write new tools which manipulate/write
programs. We have built an o-o database server for managing all the data,
and the user interface is NeWS-based.

While not extending Modula-2 in itself, we're trying to provide a dynamic,
LISP-inspired environment for Moduleans. The first release will target the
embedded systems market, so the environment does support "Modula-2 -- the
fast systems language".

					- Frode

-- 
| Frode L. Odegard         |"The world is coming to an end! Repent and|
| Modula-2 CASE Systems    |rm /bin/cc"                               |
| NORWAY (EUROPE)     	   |                                          |
| Email: frode@m2cs.uu.no  |                                          |

daveb@geaclib.UUCP (David Collier-Brown) (02/07/89)

  On the off chance noone has mentioned it, the concept of calling a
name expressed in an external format (ie, a string), is a basic
mechanism in Multics, Unix's daddy.
  It wasn't a language feature, it was how you did linking.  If you
couldn't link by at least runtime, you got told about the problem and
asked for a compiled function (or a different name) to satisfy the
call request.  This was not only useful, it also allowed you to do cute
demonstrations of prototyping...
-- 
 David Collier-Brown.  | yunexus!lethe!dave
 Interleaf Canada Inc. |
 1550 Enterprise Rd.   | He's so smart he's dumb.
 Mississauga, Ontario  |       --Joyce C-B

ch@maths.tcd.ie (Charles Bryant) (02/09/89)

In article <1316@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>From article <403@rpi.edu>, by jefu@pawl.rpi.edu (Jeffrey Putnam):
>... 
>
>The reason might be that the procedure you want to jump to was
>compiled after the main program was compiled, and was not, and could
>not be, known to the main program at the time of its compilation.
>...

Well here's another solution (which will work in many languages):

write your C code with function definitions like this:

char *			/* or whatever */
/*CALLABLE*/
func_foo(a, b, c)
{
 ...

Then write a small program (awk/sed script or whatever you like) to read a file
and take the first word of all lines following /*CALLABLE*/ and produce:

struct calltable {
	void (*func)();		/* whatever type you want */
	char *name;
} my_call_table = {
	func_foo, "func_foo",
	.
	.
	.
	};

Now write a function which takes a string, looks it up in the table and calls
it. By declaring the table 'extern', the program can be compiled, and the table
can be generated and linked later. The parts of the program you don't need
to be able to call can even be linked if your linker can produce one linkable
object from several.
-- 

		Charles Bryant.
Working at Datacode Electronics Ltd.