Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site fortune.UUCP Path: utzoo!linus!philabs!seismo!hao!hplabs!hpda!fortune!rpw3 From: rpw3@fortune.UUCP Newsgroups: net.unix Subject: Re: functions returning pionters to func - (nf) Message-ID: <2035@fortune.UUCP> Date: Sat, 17-Dec-83 04:05:44 EST Article-I.D.: fortune.2035 Posted: Sat Dec 17 04:05:44 1983 Date-Received: Sun, 18-Dec-83 09:07:32 EST Sender: notes@fortune.UUCP Organization: Fortune Systems, Redwood City, CA Lines: 110 #R:azure:-243000:fortune:26900005:000:2673 fortune!rpw3 Dec 17 00:16:00 1983 Lo, I too have fought the mighty type-check and been victorious! (Enough ancient grammer...) The following code was the result of trying to declare a VARIABLE (as opposed to the original submitter's ROUTINE) named "state", said variable to hold the address of an array of routines, each of which returns a value of the same type as "state" (i.e., a pointer to an array of routines which...). In case you haven't guessed, this is to build FAST state machines for which the state and an input value maps directly to an action routine. The application was, well, never mind... Each interrupt would process all of the state transitions needed until no more work could be done. After I had stumbled through all of the hassles mentioned previously, I finally solved it using typedefs, but wasn't happy, since there seemed something inelegant about that. The following program does it WITHOUT typedefs (although the typedef version is easier to read, and was what was used in production). Read carefully! The line that starts "struct..." is actually declaring "state". (Ignore the missing initialization of "state") Rob Warnock UUCP: {sri-unix,amd70,hpda,harpo,ihnp4,allegra}!fortune!rpw3 DDD: (415)595-8444 USPS: Fortune Systems Corp, 101 Twin Dolphins Drive, Redwood City, CA 94065 ----------- sm.c -------------- extern char DR_flags; /* argument to each state handler */ struct foo { struct foo (*(*dummy)())[]; } (*state)[]; /* called on each interrupt */ smachine() { state = FIRSTSTATE; /* defining FIRSTSTATE is hard, too */ while (state) state = (*((*state)[DR_flags].dummy))(); /* turn the crank */ } --------------------------------- Here is the compiled code for a couple of machines. The typedef version gives the same code, but the dummy struct member is avoided. ----------- smpdp10.mac ------------- (compiled from the original BLISS) state:: block 1 _smachine:: skipne 1,state popj 17, add 1,DR_flags## pushj 17,@(1) movem 1,state jrst _smachine ----------- smvax.s ------------- .data .comm _state,4 .text LL0:.align 1 .globl _smachine .set L14,0x0 .data .text _smachine:.word L14 jbr L18 L2000001:cvtbl _DR_flags,r0 ashl $2,r0,r0 addl2 _state,r0 movl (r0),r0 calls $0,(r0) movl r0,_state L18:tstl _state jneq L2000001 ret ----------- sm68.s -------------- .data .comm state,4 .text .globl smachine smachine: |.proc link %a6,#-.F1 movl %a2,%sp@ movl #state,%a2 jra .L15 .L20001: movb DR_flags,%d0 extw %d0 extl %d0 asll #2,%d0 addl %a2@,%d0 movl %d0,%a0 movl %a0@,%a0 jsr %a0@ movl %d0,%a2@ .L15: tstl %a2@ jne .L20001 movl %a6@(-.F1),%a2 unlk %a6 rts .F1 = 4 .S1 = 1024 .data ----------end--------------------