Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: $Revision: 1.6.2.14 $; site umn-cs.UUCP Path: utzoo!watmath!clyde!cbosgd!ihnp4!stolaf!umn-cs!herndon From: herndon@umn-cs.UUCP Newsgroups: net.lang.c Subject: Re: Arcane C hacks? Message-ID: <1700004@umn-cs.UUCP> Date: Sun, 23-Feb-86 00:39:00 EST Article-I.D.: umn-cs.1700004 Posted: Sun Feb 23 00:39:00 1986 Date-Received: Fri, 28-Feb-86 22:19:32 EST References: <1700003@umn-cs.UUCP> Lines: 67 Nf-ID: #R:umn-cs:-170000300:umn-cs:1700004:000:3238 Nf-From: umn-cs!herndon Feb 22 23:39:00 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