[comp.lang.c] Pointers to functions on Xenix

stever@Octopus.COM (Steve Resnick ) (09/08/89)

I have a shell I am writing for MS DOS which  will extend the batch language
and add some UNIX style enhancements (aliasing, history, and getting rid of
that damn backslash). As I write this I want to port it to UNIX/Xenix as well.
my problem is that the Xenix C compiler bitches at using pointers to
functions. For example, consider the follow fragment...

int echo(int, char **);		/* The protos allow the forward refernce to */
int setenv(int, char **);	/* the functions */

struct ci 				/* This is the command table */
{		
	char * name;			/* The shell uses this name to compare
					   against the entered command */
	int (* fptr)(int, char **);	/* and here is the function pointer */
}  Cmds[] =
"ECHO",echo,
"SET",setenv,
} ;
.
.	/* Main and other stuff here */
.
.
/* When I get to the point where I execute an internal function, I call the
   routine here..
*/
	(Cmds[idx].fptr)(c,v);	/* Here is where I call  the function */

This is what the compiler doesn't like. The error message is something like

Term does not evaluate to a function.

This seems to be legitimate C in the MS DOS world...
Help! Please!

karl@haddock.ima.isc.com (Karl Heuer) (09/09/89)

In article <1989Sep8.021802.29203@Octopus.COM> stever@octopus.UUCP (Steve Resnick ) writes:
>When I get to the point where I execute an internal function...
>	(Cmds[idx].fptr)(c,v);	/* Here is where I call  the function */
>This is what the compiler doesn't like.

The ability to invoke a function via a pointer without an explicit dereference
is new to ANSI C, and is not supported by all pre-ANSI compilers.  The more
portable syntax is
	(*Cmds[idx].fptr)(c,v);

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

scjones@sdrc.UUCP (Larry Jones) (09/09/89)

In article <1989Sep8.021802.29203@Octopus.COM>, stever@Octopus.COM (Steve Resnick ) writes:
> my problem is that the Xenix C compiler bitches at using pointers to
> functions. For example, consider the follow fragment...
> 	(Cmds[idx].fptr)(c,v);	/* Here is where I call  the function */
> 
> This is what the compiler doesn't like. The error message is something like
> 
> Term does not evaluate to a function.

The error message says it all -- (Cmds[idx].fptr) is not a
function, it's a POINTER to a function.  You need to use
(*Cmds[idx].fptr) for many existing implementations, although
ANSI C allows as few or as many asterisks as you like.

Once again, let's all repeat in unison:
In C, the use of a variable and it's declaration should look the
same.
----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@SDRC.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"I have plenty of good sense.  I just choose to ignore it."
-Calvin

schaut@madnix.UUCP (Rick Schaut) (09/10/89)

In article <1989Sep8.021802.29203@Octopus.COM> stever@octopus.UUCP (Steve Resnick ) writes:
[Defines an array of structures where one element of the structure is
a pointer to a function returning an int.]
| /* When I get to the point where I execute an internal function, I call the
|    routine here..
| */
| 	(Cmds[idx].fptr)(c,v);	/* Here is where I call  the function */
| 
| This is what the compiler doesn't like. The error message is something like
| 
| Term does not evaluate to a function.

Exactly, the term evaluates to a pointer.  You need to go through a level
of indirection to get to the function that the pointer points to.  The
correct expression is:

	(*Cmds[idx].fptr)(c,v);

See K&R 5.11 (p. 118, 2nd Ed.).  See, also, operator precedence on p. 52.


-- 
   Richard Schaut
ArpaNet: madnix!schaut@cs.wisc.edu
UseNet: ...uwvax!astroatc!nicmad!madnix!schaut
             {decvax!att}!

perry@ccssrv.UUCP (Perry Hutchison) (09/13/89)

In article <1989Sep8.021802.29203@Octopus.COM> stever@octopus.UUCP
(Steve Resnick) writes:

> int echo(int, char **);		/* The protos allow the forward refernce to */
> int setenv(int, char **);	/* the functions */
> 
> struct ci 				/* This is the command table */
> {		
> 	char * name;			/* The shell uses this name to compare
> 					   against the entered command */
> 	int (* fptr)(int, char **);	/* and here is the function pointer */
> }  Cmds[] =
> "ECHO",echo,
         ^^^^
> "SET",setenv,
        ^^^^^^
> } ;

 ...

> 	(Cmds[idx].fptr)(c,v);	/* Here is where I call  the function */
> 
> The error message is something like
> 
> Term does not evaluate to a function.

The type of member fptr is "pointer to a function", but the initial
values given are "functions".  Try preceding them with "&" thus

  "ECHO", &echo,
          ^
  "SET", &setenv,
         ^

I would call it a bug that the compiler complained only about the call.
It should have at least given a warning on the initialization.

Also, in the call, you need to dereference the "pointer to function" in
order to obtain a "function" which you can call, thus

  	(* Cmds[idx].fptr)(c,v);	/* Here is where I call  the function */
     ^

stever@Octopus.COM (Steve Resnick ) (09/15/89)

I  appreciate the help everyone has given me. It seems that I've  grown quite
used  to my ANSI compiler on the DOS machine. The lack of the indirection was
the problem. I could live with better error messages than Microsoft C  but
alas that is the Xenix C compiler. Ah well....

Thanx to all who've helped. 


----------------------------------------------------------------------------
| Confusing and counfounding a hopelessley defenseless department who was  |
| unfortunate to ask for the informationin the first place.                |
|--------------------------------------------------------------------------|
| Steve Resnick | ...!sun!vsi1!octopus!psisj!steve                         |
|---------------| or ...!sun!vsi1!octopus!stever                           |
|--------------------------------------------------------------------------|