[comp.lang.c] Using vars to access structures/functions

asst-jos@yetti.UUCP (Jonathan) (07/19/89)

	Is it possible to place the name of a field in a variable, and
then use that variable to reference the field?  For a contrived
example, if I have a structure that has a large number of fields,
and I want to reference a field, by querying the user for the
field name rather than do the following:
	getfieldname(var);
	if ( strcmp(var, "fieldname1") == 0)
		do whatever to field1
	else if (strcmp( var, "fieldname2) == 0)
		do whatever to field2
	else ....

In effect, this is to come up with a general solution to the problem rather
than re-write the code for each situation like this that arises.

	This would apply to pointers to functions as well.  Is it
possible to use the name of a function (read in from the terminal, for
example) to execute the function (assuming that it exists) without creating
a cross reference table first? I have tried this and have been unable to do 
this.  This does not seem possible, but you never know!!! Any and all 
help (flames included :-) ) accepted.  e-mail is welcome.
-------------------------------------------------------------------------
Jeffrey Klein
York University, Toronto     UUCP: Uunet!utai!utcsri!yunexus!yuyetti!asst-jos

Standard Disclaimer: 
This is MY opinion, not York University's!!!

gwyn@smoke.BRL.MIL (Doug Gwyn) (07/21/89)

In article <329@yetti.UUCP> asst-jos@yetti.UUCP (Jeffrey Klein) writes:
>	Is it possible to place the name of a field in a variable, and
>then use that variable to reference the field?

Not as such, since source code identifiers vanish before run time.
(Except for possible debugging or interpreter environments, but the
identifiers are still not supposed to be available to the program.)

You need to design some other solution.  For function tables, you
might set up something like:
	extern void func1(), func2();
	struct func_pair {
		char *func_name;
		void *func_entry();
	} funct_table[] = {
		{ "func1", func1 },
		{ "func2", func2 },
	};
and search the table for a matching func_name member, then use the
struct func_pair pointer that matched to invoke the function via the
corresponding funct_entry member.  Selecting different members of a
struct by name is a harder proposition, and it would be best to find
some other way of accomplishing the desired effect in such a case.

poser@csli.Stanford.EDU (Bill Poser) (07/21/89)

If the members of the structure that you want to access are of the
same type, you can create an array of pointers to the various members
in which you are interested and a function that returns the index
into this array given the name of the member (which can be the
name you use in your source code but doesn't have to be.)
You also write a function that you call at initialization
time that assigns the addresses of the structure members to the
array. When you want to access a member by name, you call the
function that translates from the name to the array index and index
into the array to get the address of the structure member.

This is kind of elaborate, but there are circumstances in which
it is useful.

I have used this in a programmable time series editor (sort of like
EMACS, only not for text) in which various attributes of a window are
stored both in user-variables and in internal data structures. The
user-variables are trapped so that I can do things like make sure that
a color specification is valid as well as updating the internal data
structure when the user-variable is assigned to.  Rather than having a
distinct trap function for each attribute, I have a single trap
function SetColorAttribute which is called with a pointer to the
variable as its argument. It checks the validity of the color
specification, and then does the right thing to the internal data
structure.

Each window is represented by a structure that contains (along with
lots of other things) both the color attribute information and an
array of pointers to the color attributes. Here is an excerpt from the
function that initializes the array:

void
InitAttAddresses(w)
WINDOW_PTR w;
{

   if(w == NULL_WINDOW) return;

   w->ColorAttributes[0] = &(w->AnchorLineColor);

...
}

And here is the function SetColorAttribute:

void
SetColorAttribute(vptr)
VAR_PTR vptr;
{
   int cstatus;
   Color *c;

   c = vptr->list->binder.window->ColorAttributes[GetColorAttIndex(vptr->name)];

   cstatus = XParseColor(vptr->value,c);
   if(cstatus == 0){
      mwprintf(
	 "Could not parse color specification %s%s%s.\n%s defaulting to %s.\n",
	 sostr,vptr->value,usostr,vptr->name,defcolor);
      sprintf(vptr->value,defcolor);
      XParseColor(vptr->value,c);
   }
   XGetHardwareColor(c);
   return;
}

(Note that each variable contains a pointer to the list that contains
it and that each variable list contains a pointer to the object
with which the variable list is associated, if any, so that it
is possible to determine which window the variable is an attribute
of. That is the value of vptr->list->binder.window.)

This gets a bit complex, but it works quite nicely, and there are cases
like this in which it seems to be the right thing to do.


						Bill

 

maart@cs.vu.nl (Maarten Litmaath) (07/22/89)

gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
\...	extern void func1(), func2();
\	struct func_pair {
\		char *func_name;
\		void *func_entry();

Ahum: void (*func_entry)();

\	} funct_table[] = {
\		{ "func1", func1 },
\		{ "func2", func2 },
\	};
\...
-- 
"Mom! Eric Newton broke the day! In 24   |Maarten Litmaath @ VU Amsterdam:
  parts!" (Mike Schmitt in misc.misc)    |maart@cs.vu.nl, mcvax!botter!maart