Path: utzoo!utgpu!water!watmath!clyde!att-cb!osu-cis!tut.cis.ohio-state.edu!uwmcsd1!ig!agate!ucbvax!NRL-CSS.ARPA!cornwell From: cornwell@NRL-CSS.ARPA (Mark Cornwell) Newsgroups: comp.lang.modula2 Subject: Re: union types Message-ID: <8803252349.AA00158@nrl-iws6.ARPA> Date: 25 Mar 88 23:49:15 GMT Sender: usenet@ucbvax.BERKELEY.EDU Reply-To: Info-Modula2 Distribution List Organization: The Internet Lines: 80 Richard, Thanks for your interest. I'm afraid our project won't be of as much interest to you as it may have appeared. We will be writing a secure message system on top of a variant of the UNIX operating system. The system will be written mostly in Modula-2. It is important that the application call the UNIX interface directly. Our modula-2 compiler did not come with an interface to UNIX, just a set of libraries for I/O, files, etc. I spent the last few days, writing a module of `glue' routines that handle the difference between the calling conventions of the Modula-2 compiler and the C-libraries so that I can write stubs in Modula to call the C-functions. These stubs have to push parameters on the run-time stacks, stash return values in registers and things like that. That is what the procedures do. In addition the interface needs a set of type declarations that coorespond to the types one would find in the header files of the UNIX system interface. It was the writing of these header files that prompted my question. In the end I found a pretty solution to the grubby coding part. I wrote some m4 macros that take a one line description of the function and its parameters and generate the linkage code, computing the proper calling sequence from the sizes of the parameters, the type of the functions, etc. It's like a mini version of a code generator as you might find in a compiler. I'm pretty proud of it. It shrinks to two pages of code what would have taken me 40 or 50 to write if I'd taken the brute-force approach. E.g., it lets me write: cgen(chown,INTEGER,path,StringPtr,owner,INTEGER,group,INTEGER) And the cgen macro will expand to: PROCEDURE chown ( path: StringPtr; owner: INTEGER; group: INTEGER ) : INTEGER; VAR adr:ADDRESS; BEGIN (* Push one word parameter: group *) SETREG(AX,group); (* ax <- amode *) CODE(50H); (* push ax *) (* Push one word parameter: owner *) SETREG(AX,owner); (* ax <- amode *) CODE(50H); (* push ax *) (* Push two word parameter: path *) adr := path SETREG(AX,adr.SEGMENT); CODE(50H); (* push ax *) SETREC(AX,adr.OFFSET); CODE(50H); (* push ax *) (* Call C-library routine: chown *) SetCLibDS; (* set DS to correct value *) EXTCALL("_chown"); (* call "_chown" *) (* Pop the 4 words pushed off the stack *) CODE(83H,C4H,08H); (* add sp,8 *) (* Move the one word function result from AX to BX *) CODE(89H,D8H); (* BX <- AX *) END chown; The macro has to be clever enough to know the sizes of the arguments and whether the function returns a value and well as the size of the return value. The calling conventions vary with respect to all of these. My implementation module contains about a hundred or so lines that are just calls to cgen. Unfortunately, all of this is just incidental to the project. It was an enjoyable distraction for the last few days and is pretty much finished now. If you are still interested, I can send you the code. --Mark