[net.lang.c] c types problem

gostas@kuling.UUCP (G|sta Simil{/ml) (01/03/86)

I need to define a type for a program which can store any of the types
long, int, short and also the unsigned variants of them.
Some of the routines referencing this types will not use them directly
however, it will use the sys/types.h typedefs dev_t, time_t etc.
It will look something like this: "(*func)(&data)" there *func,
but not the calling routine knows what type is currently stored in "data".
The formal (but ugly) way to solve this would proparbly be to use a union
for all (about 10) types. But now I wonder if anyone have a simpler but
resonably portable solution?

	G|sta Simil{				gostas@kuling.UUCP

jsdy@hadron.UUCP (Joseph S. D. Yao) (01/05/86)

In article <870@kuling.UUCP> gostas@kuling.UUCP (G|sta Simil{/ml) writes:
>The formal (but ugly) way to solve this would proparbly be to use a union
>for all (about 10) types. But now I wonder if anyone have a simpler but
>resonably portable solution?

I really don't think you'll find any more portable solution than to
use a union, which really isn't all that ugly if you declare the union
elsewhere and use some good macros.  E.g.:
	union mix {
		int	mix_i;
		long int mix_li;
		dev_t	mix_d;	/* Be sure to include dev_t and */
		time_t	mix_t;	/* time_t et al: they may surprise */
				/* you. */
		...
	};
	union mix getval(int);
	#define getint(x)	(getval((x)).mix_i)
	#define getlong(x)	(getval((x)).mix_li)
	...
If you're worried about portability, you certainly won't have any
places where you don't know the type of the return value.  Oh: to
return a value, in the function you really should (e.g.):
	union mix getval(x)
	  int x;
	{
		union mix retval;
		...
			retval.mix_i = Xxx;
			return(retval);
		...
	}
which can be #define'd:
#define retmix(val,type)	retval.type = val; return(retval);
=>			retmix(Xxx, mix_i);
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (01/06/86)

> I need to define a type for a program which can store any of the types
> long, int, short and also the unsigned variants of them.
> Some of the routines referencing this types will not use them directly
> however, it will use the sys/types.h typedefs dev_t, time_t etc.
> It will look something like this: "(*func)(&data)" there *func,
> but not the calling routine knows what type is currently stored in "data".
> The formal (but ugly) way to solve this would proparbly be to use a union
> for all (about 10) types. But now I wonder if anyone have a simpler but
> resonably portable solution?

Since you're going to pass pointers, just coerce the actual data
address into a generic pointer ((void *) if you have it, otherwise
(char *)) and coerce it back inside the called function.

jsdy@hadron.UUCP (Joseph S. D. Yao) (01/06/86)

In article <168@hadron.UUCP> jsdy@hadron.UUCP (Joseph S. D. Yao) writes:
>In article <870@kuling.UUCP> gostas@kuling.UUCP (G|sta Simil{/ml) writes:
>>The formal (but ugly) way to solve this would proparbly be to use a union
>>for all (about 10) types. But now I wonder if anyone have a simpler but
>>resonably portable solution?
> ...

My original answer dealt with a union of outputs.  Re-reading the
message, it seems that you are talking about a union of inputs.
Oh, well, the principle remains the same.  I hope that you are
relying on a state variable somewhere (even if it  i s  extern) to
tell you what type the data is, rather than trusting the contents
to let you know.
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

franka@mmintl.UUCP (Frank Adams) (01/07/86)

In article <1261@brl-tgr.ARPA> gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) writes:
>> I need to define a type for a program which can store any of the types
>> long, int, short and also the unsigned variants of them.
>> Some of the routines referencing this types will not use them directly
>> however, it will use the sys/types.h typedefs dev_t, time_t etc.
>> It will look something like this: "(*func)(&data)" there *func,
>> but not the calling routine knows what type is currently stored in "data".
>> The formal (but ugly) way to solve this would proparbly be to use a union
>> for all (about 10) types. But now I wonder if anyone have a simpler but
>> resonably portable solution?
>
>Since you're going to pass pointers, just coerce the actual data
>address into a generic pointer ((void *) if you have it, otherwise
>(char *)) and coerce it back inside the called function.

I got the impression he wanted long, short, etc. in his union, as well as
pointers.  If so, I don't think (void *) is portable; a long is bigger than
any pointer on some machines.

Frank Adams                           ihpn4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

ken@gitpyr.UUCP (Ken Hall) (01/07/86)

May I ask a stupid question?  Would somebody post or send me a very short
C program that open a file, write something to it, then closes it?

Thankyou in advance.

Ken Hall

tribble_acn%uta.csnet@csnet-relay.arpa (David Tribble) (01/08/86)

In article <870@kuling.UUCP> gostas@kuling.UUCP writes:
>The formal (but ugly) way to solve this would probably be to use a union
>for all (about 10) types. But now I wonder if anyone has a simpler but
>reasonably portable solution?

The only way that is truly portable that comes to mind is to use a union.
However, the following way works on many (not all) machines and is somewhat
portable (meaning it is not truly portable):
	foo (typ, arg)
	int	typ;
	double	arg;
	{
	    char*	argp;
	    ...

	    argp = (char*) &arg;
	    switch (typ) {
	        case CHR:	c = *(char*)argp;
	        case INT:	i = *(int*)argp;
	        case FLT:	f = *(float*)argp;
	        case DBL:	d = *(double*)argp;
	        ...		...
	    }
	}
foo is the routine that is passed the arg or unknown type, and foo
knows what type arg is by the value of typ.
The idea is to pass the parm (declared as a type that will probably be aligned,
thus 'double'), take its address (which is usually on the stack), cast
the address (pointer) to the appropriate pointer type, then de-reference
the casted pointer. This is based on the assumption that parameters of
different types will reside at the same location (ie, their lower bytes
have the same alignment).

Yes, it's hokey, and yes, it will not work on machines that align function
arguments in funny ways.

-----
Another variant to this scheme is to call foo passing it the address of
the object, declaring foo-
	foo (typ, argp)
	int	typ;
	char*	argp;
This solves the alignment problem. However, since you can only
take the address of an lvalue, you cannot pass foo the address of an
expression. This scheme suffers from nonportability since casting
pointers to different types is wierd on some machines.

Given my choice, I would probably use the pointer-passing scheme, since
it is (mostly) portable and doesn't require macros (only an '&' operator)
or extra unused space for local unions.

[The usual disclaimers go here.]

	david r. tribble	univ. texas at arlington
				tribble_acn@uta

kanner@tymix.UUCP (Herb Kanner) (01/09/86)

In article <1237@gitpyr.UUCP> ken@gitpyr.UUCP (Ken Hall) writes:
>May I ask a stupid question?  Would somebody post or send me a very short
>C program that open a file, write something to it, then closes it?
>
>Thankyou in advance.

#include <stdio.h>

main()
{
	FILE *file;

	filex = fopen("THING", "w");  /* opens file named THING for writing */
	putc('a', filex);	/* puts char 'a' in file pointed to by 'filex' */
	fclose(filex);	/* not necessary; end of program closes file */
}

	

-- 
Herb Kanner
Tymnet, Inc.
...!hplabs!oliveb!tymix!kanner

gostas@kuling.UUCP (G|sta Simil{/ml) (01/11/86)

In article <175@hadron.UUCP> jsdy@hadron.UUCP (Joseph S. D. Yao) writes:
>In article <168@hadron.UUCP> jsdy@hadron.UUCP (Joseph S. D. Yao) writes:
>>In article <870@kuling.UUCP> gostas@kuling.UUCP (G|sta Simil{/ml) writes:
>>>The formal (but ugly) way to solve this would proparbly be to use a union
>>>for all (about 10) types. But now I wonder if anyone have a simpler but
>>>resonably portable solution?
>> ...
>
>My original answer dealt with a union of outputs.  Re-reading the
>message, it seems that you are talking about a union of inputs.
>Oh, well, the principle remains the same.

>	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

Yes, it's a union of inputs, no value will be returned and the calling program
will have no idea what type the called functions are using currently, the
code will look something like this:

/* calling routine: */
typemix *base;  /* malloc()'ed array, may change size during execution */

	current_data = base;
	for (current_data = base; (something); current_data++, p++)
		if ((*p->function)(current_data))  /* value changed? */
			(*p->action)();  /* really just a print routine */

/* called function: */

func(old_value)
typemix *old_value;
{
	some_type new_value = get_new_value();

	if (new_value == old_value->some_type)
		return(0);
	old_value->some_type = new_value;
	return(1);
}

The example will be used when updating a screen, to avoid printing a field
which have not changed value since the last update.

	G|sta Simil{				gostas@kuling.UUCP

gwyn@BRL.ARPA (VLD/VMB) (01/12/86)

A (long *) fits into a (void *) just fine.

zap@duvan.UUCP (Svante Lindahl) (01/14/86)

In article <1237@gitpyr.UUCP> ken@gitpyr.UUCP (Ken Hall) writes:
>May I ask a stupid question?  Would somebody post or send me a very short
>C program that open a file, write something to it, then closes it?

% cat > foo.c
#include <stdio.h>
main()
{
	FILE *fopen(), *fp;

	if ((fp = fopen("/dev/tty","w")) == NULL) {
		(void) fprintf(stderr, "Can't open /dev/tty\n");
		exit(1);
	}
	(void) fprintf(fp, "Go bye yourself a C-book!\n");
	(void) fclose(fp);
}
% cc foo.c
% a.out
Go bye yourself a C-book!
-- 
Svante Lindahl, NADA, KTH (Dept of Numerical Analysis and Computer Science 
			   at the Royal Institute of Technology)
UUCP:	{seismo,mcvax,cernvax,diku,ircam,prlb2,tut,ukc,unido}!enea!ttds!zap
ARPA:	enea!ttds!zap@seismo.ARPA
 or 	Svante_Lindahl_NADA%QZCOM.MAILNET@MIT-MULTICS.ARPA

zap@duvan.UUCP (Svante Lindahl) (01/14/86)

In article <1237@gitpyr.UUCP> ken@gitpyr.UUCP (Ken Hall) writes:
>May I ask a stupid question?  Would somebody post or send me a very short
>C program that open a file, write something to it, then closes it?

% cat > foo.c
#include <stdio.h>
main()
{
	FILE *fopen(), *fp;

	if ((fp = fopen("/dev/tty","w")) == NULL) {
		(void) fprintf(stderr, "Can't open /dev/tty\n");
		exit(1);
	}
	(void) fprintf(fp, "Go buy yourself a C-book!\n");
	(void) fclose(fp);
}
% cc foo.c
% a.out
Go buy yourself a C-book!