[net.lang.c] problems with the C parser

brisco@topaz.RUTGERS.EDU (T.p.) (05/30/86)

	I've been trying to translate a program written in Vax
Pascal to C on our Suns.
	My problem arose when I was trying to translate a pascal
variant record structure into a C union structure. The structure type
(in pascal) looked as follows: (keep in mind - both were for 32 bit machines)

	newtype = record case selector of
		0:(int: unsigned);
		1:(bool: packed array [0..31] of boolean);
		end


	Which I had translated into C as:

	typedef union {
		int intfield;   /* change the record name - keyword */
		struct bool{unsigned x[32]:1};
		} newtype;


	The C parser barfed all over this. I tried every combination
of unsigned x:1[32], ..... that I could think of.  Out of frustration
I looked up the syntax of the declarations in K&R and found that the
initial guess had been correct!
	I wanted an integer that I could index into by bit, so I could
avoid using masks (which weren't going to be easily used due to the
methodology of the original program).
	Am I going crazy or is our C parser brain-damaged?  Can anyone
else compile the above structure declaration?


			"Wah!"
			"No, no. It's 'Wah!'"
			"Wah!"
			"That's better!"

				tp.

chris@umcp-cs.UUCP (Chris Torek) (05/30/86)

In article <5072@topaz.RUTGERS.EDU>, brisco@topaz.RUTGERS.EDU (T.p.),
wanting to translate a Pascal packed array [0..31] of boolean
writes:
>	... I [tried]:
>
>	typedef union {
>		int intfield;   /* change the record name - keyword */
>		struct bool{unsigned x[32]:1};
>		} newtype;
>
>	The C parser barfed all over this. I tried every combination
>of unsigned x:1[32], ..... that I could think of.  Out of frustration
>I looked up the syntax of the declarations in K&R and found that the
>initial guess had been correct!

Hrum.  Where in K&R did you find something that implies the above
is in any way correct?  Try instead chapter 6, page 138:

	Other restrictions to bear in mind: fields are unsigned; they
	may be stored only in int's (or, equivalently, unsigned's);
	THEY ARE NOT ARRAYS; [emphasis mine] they do not have addresses,
	so the & operator cannot be applied to them.

Arrays must be addressible; bit fields are not addressible; and
therefore there are no arrays of bit fields, nor are there bit
fields of arrays.

As for solving the original problem---obtaining the equivalent
of `packed array [0..31] of boolean'---you will probably have to
make do with macros, e.g.:

	#define	BIT(name, index) ((name) & (1 << (index)))
	#define BIS(name, index) ((name) |= 1 << (index))
	#define BIC(name, index) ((name) &= ~(1 << (index)))

You can, at this point, dispense with the union:

	typedef long newtype;

is probably the best way to go: it is even portable to 16-bitters.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

ark@alice.UucP (Andrew Koenig) (05/30/86)

>	I wanted an integer that I could index into by bit, so I could
> avoid using masks (which weren't going to be easily used due to the
> methodology of the original program).

C does not offer any kind of bit indexing.

garys@bunker.UUCP (Gary M. Samuelson) (05/30/86)

In article <5072@topaz.RUTGERS.EDU> brisco@topaz.UUCP writes:

>	typedef union {
>		int intfield;   /* change the record name - keyword */
>		struct bool{unsigned x[32]:1};
>		} newtype;

>	Can anyone else compile the above structure declaration?

No.  You didn't read far enough:
	"In all implementations, there are no arrays of fields"
	K&R, p. 197

I tried
	typedef union {
		int intfield;
		struct bool {int x:1; }bit[32];
		} newtype;

But each bit takes up an entire unsigned, so the size of the above
is 32 * sizeof (unsigned).

I think you will have to choose from masks, or making each bit a
separate field:
	typedef union {
		int intfield;
		struct	bool {
			unsigned
			x0:1,  x1:1,  x2:1,  x3:1,  x4:1,  x5:1,  x6:1,  x7:1,
			x8:1,  x9:1,  x10:1, x11:1, x12:1, x13:1, x14:1, x15:1,
			x16:1, x17:1, x18:1, x19:1, x20:1, x21:1, x22:1, x23:1,
			x24:1, x25:1, x26:1, x27:1, x28:1, x29:1, x30:1, x31:1;
		}
	} newtype;

Gary Samuelson

guy@sun.uucp (Guy Harris) (05/30/86)

> 	typedef union {
> 		int intfield;   /* change the record name - keyword */
> 		struct bool{unsigned x[32]:1};
> 		} newtype;
> 
> 
> 	The C parser barfed all over this.

Well, actually, the parser had no trouble with it whatsoever.  Some routines
that do semantic checking on declarations complained about it.  There are
plenty of constructs in C which are syntactically valid but not legal C.

> 	I wanted an integer that I could index into by bit...

You can't.  Read K&R again, only look at more than just the syntax
specifications.  At the top of page 197:

	...In all implementations, there are no arrays of fields...

Like it or not, that's the case.  It may not be easy to convert your program
to use masks, but if you want to convert it to C you have no choice.  There
*is* a Pascal on Suns, although I don't know if your program uses features
specific to VAX(/VMS, I presume) Pascal, which the Berkeley Pascal which Sun
offers probably doesn't have.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.arpa

greg@utcsri.UUCP (Gregory Smith) (05/31/86)

In article <5072@topaz.RUTGERS.EDU> brisco@topaz.RUTGERS.EDU (T.p.) writes:
>	Which I had translated into C as:
>
>	typedef union {
>		int intfield;   /* change the record name - keyword */
>		struct bool{unsigned x[32]:1};
>		} newtype;
>
>
>	The C parser barfed all over this. I tried every combination

'illegal field type', which is what I get, is not an example of
parser-vomit by any stretch of the imagination. You did forget the ';'
after the 1 in the above, though - which might cause the first '}' to be
lost - instant upchuck.
And you didn't name the second member of the union - that's not
a syntax error, though.

>of unsigned x:1[32], ..... that I could think of.  Out of frustration
>I looked up the syntax of the declarations in K&R and found that the
>initial guess had been correct!
>	Am I going crazy or is our C parser brain-damaged?  Can anyone
>else compile the above structure declaration?

Well, K&R says that the kinds of things that can put in a bitfield is
implementation-defined - thus `declarator : constant_expression'.
I think it would be rare, though, to find anything but unsigned ints and
ints to be implemented. If an array was allowed, it would be declared as
`unsigned x[32]:32', since the width applies to the whole declarator.
As it stands, I think you are out of luck. Write 'unsigned bits32'
and then use shifts and masks to get at them:

#define boolread( rval, bitnum ) ( ((rval)>>(bitnum)) &1)
#define boolset( lval,bitnum )	( (lval) |= 1<<(bitnum))
#define boolclr( lval,bitnum )  ( (lval) &= ~(1<<(bitnum))
#define boolasg( lval,bitnum, new )( new? boolset( lval,bitnum):boolclr(lval\
,bitnum)

-- 
"We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg

throopw@dg_rtp.UUCP (Wayne Throop) (06/01/86)

> brisco@topaz.UUCP

>         typedef union {
>                 int intfield;   /* change the record name - keyword */
>                 struct bool{unsigned x[32]:1};
>
>         The C parser barfed all over this. I tried every combination
> of unsigned x:1[32], ..... that I could think of.  Out of frustration
> I looked up the syntax of the declarations in K&R and found that the
> initial guess had been correct!
>         I wanted an integer that I could index into by bit, so I could
> avoid using masks (which weren't going to be easily used due to the
> methodology of the original program).
> 	Am I going crazy or is our C parser brain-damaged?  Can anyone
> else compile the above structure declaration?

Well.  Correcting things to avoid some minor errors, we find

        typedef union {
                int intfield;
                struct {unsigned x[32]:1;} bool;
                } newtype;

which our compiler seems to think means that you want to fit an array of
32 unsigneds into a single bit.  It does not approve.

Naturally, trying variations of parenthesis around the "x" and the
"[32]" doesn't help much, since the :1 is only syntactically legal at
the top level of a structure.  Which leads to the point.

The ":n" bitfield notation is only applicable to integer types, and only
when they occur in a structure.  It cannot be applied to array members,
since array/pointer equivalence insists that each member of an array has
an address, and bitfields may not have an address.  Similar in notion to
trying to declare an array of register variables.... just doesn't work
(though most compilers might just overlook that one).

Ok, now that we know you can't do what you said you wanted in C, just
what *can* be done?  Well, you want an array-like construct, so that you
can select the bits based on an integer known at run-time.
Mask-and-shift can do what you want.  Consider the following macros:

    #define pm(m,p) ((m)<<(p))  /* position mask */
    #define mm(w) ((1<<(w))-1)  /* make a mask */
    #define slice(v,w,p) (((v)&pm(mm(w),(p)))>>(p))

One can now use the "slice" macro to grab an arbitrarily positioned and
sized bit field out of an integer typed variable.  Bits are counted from
the least significant to the most significant, and these macros assume
that you've got two's complement arithmetic.  They may also not work in
full generality on machines that use arithmetic shifts rather than
logical shifts.  Note that the "position" argument is expanded twice,
and thus should be side-effect-free.  If you are only interested in
single bits, rather than arbitrarily sized bit fields, you can use this
macro:

    #define bit(v,p) (((v)&(1<<(p)))>>(p))

which our compiler seems to choke down effectively.

I've left the assign_to_slice and assign_to_bit macros as exersizes for
the interested readers.

Have fun.

--
"Are we having fun yet?"
                        --- from "The Four Seasons"
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw