[comp.lang.lisp.x] xlftab.c:funtab[] & other questions

jsp@glia.biostr.washington.edu (Jeff Prothero) (11/20/90)

Why are the xlftab.c:funtab[] entries so carefully numbered?

What is going to break if the numbering is changed?  Primarily the
image save/restore stuff?  

Why can't/shouldn't those things which will break key off the function
names instead of the table offsets?

Why are extra slots reserved at the end of funtab[]?

What's the point of image save/restore?  Should saved images be
portable between machines or versions?

Would it be hard/pointless to write code to convert the xlisp
state into initialized C header files, so that the xlisp state
could be portably compiled into an application?

{...YOYOYOY...:-}

--
     jsp@glia.biostr.washington.edu (Jeff Prothero)
     jsp@u.washington.edu (If above bounces.)
     Biological Structure Graphics Lab, U Washington

toma@tekgvs.LABS.TEK.COM (Tom Almy) (11/21/90)

In article <JSP.90Nov19154628@glia.biostr.washington.edu> jsp@glia.biostr.washington.edu (Jeff Prothero) writes:
>Why are the xlftab.c:funtab[] entries so carefully numbered?
Beats me. I was careful to maintain the numbering until I ran out of slots.
Now I just append to the end! The table is only actually scanned once (during
initialization), and the scan is terminated by the null entry at the end.

>What is going to break if the numbering is changed?  Primarily the
>image save/restore stuff?  
>Why can't/shouldn't those things which will break key off the function
>names instead of the table offsets?
The first entries, for the read macros and the intrinsic message selectors,
are referenced by offset for initialization (probably due to laziness, but
I am not sure). As long as you leave these alone, nothing else breaks. 
(but see below)

>Why are extra slots reserved at the end of funtab[]?
You can delete them.

>What's the point of image save/restore?  Should saved images be
>portable between machines or versions?

You can save your workspace, and go back to it at a later time, like in
Smalltalk or APL. You can use it as a snapshot, and later go back in time.
It is the only way to do a vector/string memory defragmentation (except
for people who use my files dldmem and dlimage, in which case the 
defragmentation is automatic).

Saved images are not portable between machines because these are binary
files and the representations can change (big vs little endian, wordsize, etc).
They are also not portable if funtab changes.

>Would it be hard/pointless to write code to convert the xlisp
>state into initialized C header files, so that the xlisp state
>could be portably compiled into an application?

The state is mainly a large initialized linked list which can not be
statically declared in C (you need to execute code to set the links).
IMHO it would also be pointless since applications should be distributed
as xlisp source rather than C files (what if the user doesn't have a C
compiler?).

Tom Almy
toma@tekgvs.labs.tek.com
Standard Disclaimers Apply

jsp@glia.biostr.washington.edu. (Jeff Prothero) (11/21/90)

In article <8457@tekgvs.LABS.TEK.COM> toma@tekgvs.LABS.TEK.COM (Tom Almy) writes:

   In article <JSP.90Nov19154628@glia.biostr.washington.edu> jsp@glia.biostr.washington.edu (Jeff Prothero) writes:

>>What's the point of image save/restore?  Should saved images be
>>portable between machines or versions?

>Saved images are not portable between machines because these are binary
>files and the representations can change (big vs little endian, wordsize, etc).
>They are also not portable if funtab changes.

Yeah... notice, my question was *should* saved images be portable.
Do people save images only for an afternoon, or do they habitually
archive them and come back a year later...?

>>Would it be hard/pointless to write code to convert the xlisp
>>state into initialized C header files, so that the xlisp state
>>could be portably compiled into an application?

>The state is mainly a large initialized linked list which can not be
>statically declared in C (you need to execute code to set the links).

Is this obviously true?  You can initialize an array of pointers to
functions in C.  (Remember funtab[]? :-) As far as I know, you can
initialize pointers to anything in C.  Is it nonportable in practice
to initialize an array of pointers with the pointers pointing various
places into the array...?  I don't think my compiler would have any
problems with this...

>IMHO it would also be pointless since applications should be distributed
>as xlisp source rather than C files (what if the user doesn't have a C
>compiler?).

I'm sensitive to this.  But loading a lot of source text in can slow
things down.  Loading an imagefile is one way to speed things up.
Having the lisp image precompiled in would be another...

>Tom Almy
>toma@tekgvs.labs.tek.com
>Standard Disclaimers Apply
--
jsp@glia.biostr.washington.edu (Jeff Prothero)
jsp@u.washington.edu (If above bounces.)
Biological Structure Graphics Lab, U Washington

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (11/21/90)

In article <JSP.90Nov19154628@glia.biostr.washington.edu> jsp@glia.biostr.washington.edu (Jeff Prothero) writes:
>Why are the xlftab.c:funtab[] entries so carefully numbered?

For function calls, the funtab index is necessary, but there are other ways
of doing it -- xlisp/xlinit.c:initwks() just calls:

|     /* install the built-in functions and special forms */
|     for (i = 0, p = funtab; p->fd_subr != NULL; ++i, ++p)
| 	if (p->fd_name)
| 	    xlsubr(p->fd_name,p->fd_type,p->fd_subr,i);
| 

which sets up a subr node, with a name, FSUBR/SUBR kind, function pointer,
and offset (index into funtab) for each entry in funtab. A brief peruse of
the code shows that xlisp/xlprin.c:putsubr() and
xlisp/xlimage.c:xlirestore() are the only things that access the index into
funtab. The former is used to get the name of the function, and the latter
is used to retrieve the C function pointer assocd w/ a subr node from
funtab...

#ifdef ADVERTIZING_MODE_ON
   FYI, for perusing XLISP/WINTERP/MOTIF sources, I strongly encourage the
   use of powerful static analysis tools. AT&T's software toolchest has
   something called CSCOPE, and HP has a whizzy X11/Motif-Look-And-Feel
   programming environment (for C C++, Common Lisp, etc) called SOFTBENCH
   with a very nice static analysis tool... Much more useful than grep
   for answering questions like "list every use of this identifier", "show
   me the definition of this identifier", etc. Ask your friendly HP Sales
   rep for details.
#endif

Getting back to the point... Methods are added via xladdmsg(), which
requires the index into the function table rather than a function pointer
or somesuch.

Example: in xlisp/xlobj.c:
|     xladdmsg(class,":NEW",FT_CLNEW);
|     xladdmsg(class,":ISNEW",FT_CLISNEW);
|     xladdmsg(class,":ANSWER",FT_CLANSWER);
|     xladdmsg(object,":ISNEW",FT_OBISNEW);
|     xladdmsg(object,":CLASS",FT_OBCLASS);
|     xladdmsg(object,":SHOW",FT_OBSHOW);

Where FT_* are defined in xlisp/xlisp.h:
| /* function table offsets for the initialization functions */
| #define FT_RMHASH	0
| #define FT_RMQUOTE	1
| #define FT_RMDQUOTE	2
| #define FT_RMBQUOTE	3
| #define FT_RMCOMMA	4
| #define FT_RMLPAR	5
| #define FT_RMRPAR	6
| #define FT_RMSEMI	7
| /* #define xxxxxx       8 */
| /* #define yyyyyy       9 */
| #define FT_CLNEW	10
| #define FT_CLISNEW	11
| #define FT_CLANSWER	12
| #define FT_OBISNEW	13
| #define FT_OBCLASS	14
| #define FT_OBSHOW	15


And xlisp/xlftab.c contains corresponding:
|     xladdmsg(class,":NEW",FT_CLNEW);
|     xladdmsg(class,":ISNEW",FT_CLISNEW);
|     xladdmsg(class,":ANSWER",FT_CLANSWER);
| 
|     /* finish initializing 'object' */
|     setivar(object,SUPERCLASS,NIL);
|     xladdmsg(object,":ISNEW",FT_OBISNEW);
|     xladdmsg(object,":CLASS",FT_OBCLASS);
|     xladdmsg(object,":SHOW",FT_OBSHOW);


>What is going to break if the numbering is changed?  Primarily the
>image save/restore stuff?  

The main reason is because you have to make sure that the number of an
entry into funtab[] corresponds to the number in the #define FT_* in
xlisp.h. If these get out of sync, then you end up calling the wrong method
associated with a message, which isn't Good.

If you restore into a system in which funtab[]'s entries are differently
numbered, you'll pick up the wrong C function call...

Since I added HUNDREDS of methods to implement WINTERP, I had to worry
about funtab numbering alot. I didn't want to change XLISP extensively,
because then it wouldn't be the same old standard xlisp that we're all used
to (and patching it for updates would become harder).  To avoid explicitly
renumbering things, I did the ugly hack visible in src-server/w_funtab.c
src-server/w_funtab.h (do not look at these after eating lest you want to
lose your lunch). This hack/technique is also known as "C preprocessor
abuse"....

>
>Why can't/shouldn't those things which will break key off the function
>names instead of the table offsets?
>

Note that 'union ninfo' is a 2 element union. If you wanted to put the
name, C fn ptr, SUBR/FSUBR info into the union, all value nodes would take
up an extra 4 bytes. By keeping the static information in a table to be
looked up when needed, and only keeping the C fn ptr and index in the value
node, value nodes are kept small, and yet function calls don't require
extra indirection.

Your solution of keying off the function names sounds like it would require
extra indirection, even with hashing.

Other solutions and tradeoffs are obviously possible. The one we're
discussing happens to be the way David Betz decided to do it.

>Why are extra slots reserved at the end of funtab[]?
>

So you can add more functions easily.

>What's the point of image save/restore? 

Faster startup times.

>Should saved images be
>portable between machines or versions?

I don't think that's possible if different machines/versions have different
primitives. You could define indexes 0 thru N to be common/shared
functions, and have restore retrieve xnotdef() for all others.

>
>Would it be hard/pointless to write code to convert the xlisp
>state into initialized C header files, so that the xlisp state
>could be portably compiled into an application?

???

Perhaps you'd be better off looking at what gnuemacs and (I think) KCL do
w/r/t dumping (akin to core dumping) an executable image and then
"undumping" it to restore the executable and memory image created by
loading and initializing files.

Undumping is very nice when it works, but can create massive headaches when
it doesn't. In the case of gnuemacs, these undumped images cannot be
debugged with the manufacturer's supplied debugging tools. You could
compile with gcc and debug with gdb. However, for HPUX HP's product
compilers supposedly produce better/faster code.

>{...YOYOYOY...:-}

Indeed!

-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *