Arcane C hacks?
herndon at umn-cs.UUCP
herndon at umn-cs.UUCP
Sun Feb 23 15:39:00 AEST 1986
[Here, bugs, bugs, bugs! Here, bu
Hmmm. Apparently my original posting wasn't too clear.
Many responses were sent telling me that I should just use
a switch statement, or an array of pointers to functions.
Somebody else mailed me a note telling me I should not
put code into an array, but should use an assembler.
My original note explicitly mentioned the possibilities
of using both switch statements and pointers to functions,
and I've had to make do with these options. Sigh.
Let me restate my problem. Suppose I have an interpreter,
which accepts input from a user. Something like a BASIC
(Ugh!) or Lisp interpreter/compiler. I wish to convert a
statement that the user enters into machine code, and be
able to execute that machine code, RIGHT THEN(!). (I
certainly don't wish to have to call an assembler and a
loader.) This is perhaps a iffy operation, since some
machines will not allow the execution of data.
Now, it is certainly not too difficult to generate my
machine code and stick it into an array somewhere. If I
could simply jump to it, I'd be very happy. This I can
do by creating an assembly language procedure of one
argument which jumps to the address given as the argument.
1) Can I do this without the assembly language help?
As a second alternative, I can put my machine code into
an array, place the address of that array into a union as
an integer, and CALL (not jump to!) the array by pulling
the address out of the union as a pointer to a function.
This is somewhat ugly, since I don't know what size a
code address is, and C will NOT let me type cast an address
into a pointer to a function. Therefore this CODE construct
is not portable. (As I noted in my original article, I
can generate code from machine-dependent DATA tables by
using ifdefs and includes, but I'd like machine independent
CODE.) Further, many machines (for instance, the VAX)
insist on particular prologues and epilogues for procedures
which I have no interest in and do not wish to generate
code for.
2) Is there a machine independent way to coerce non-pointer-
to-function values to pointer-to-function values?
As a third alternative, definitely the least desirable
from my particular perspective, is to do the whole thing
a "proper way". I should generate nice intermediate code,
stuff it into an array, and then write a routine to interpret
the intermediate code. Presumably then I can use the switch
statement everyone recommends to generate the jump-tables to
get to the code to interpret my intermediate code. Slow.
And I can't add new intermediate-opcodes without recompiling.
The fourth alternative (another "proper way") is to generate
arrays of pointers to functions for code, where the pointers
point to real, live C functions. Then, by stepping through
the arrays and calling each function pointed to, I can
indirectly interpret my code. (Something like a forth
interpreter.) Again, I can't add new intermediate-opcodes
without recompiling. Sigh.
Oh, well, it was a hack anyhow. It was something that
used to be possible and had occasional application, and then
was rudely snatched away by "improvements" to C. I think it
predates the existence of K&R's book.
Robert Herndon
More information about the Comp.lang.c
mailing list