C99 portability challenge

N

new to c

Ben said:
One typo. Presumably you are grateful for that typo since the
corrected version gives 12 compile errors with lcc-win32.

Does lcc-win32 compile the VLA example I posted in reply to your
suggestion that C99 is portable? Personally, I think C99 is
reasonably portable for some application domains provided one avoids
lcc-win32, at least for the moment. The problems with designated
initialisers, compound literals, VLAs, variable macro argument lists
and non-constant initialisations make it too fragile.

Why lcc-win32 is sometimes on-topic and is sometimes off-topic here?

I ask question about C and lcc-win32 and Keith Thompson and Santosh say I troll.

You ask question about lcc-win32 and people not say you troll.

Why is difference?
 
B

Ben Bacarisse

new to c said:
Why lcc-win32 is sometimes on-topic and is sometimes off-topic here?

I ask question about C and lcc-win32 and Keith Thompson and Santosh
say I troll.

You ask question about lcc-win32 and people not say you troll.

Why is difference?

If there is a difference, it is probably that I was replying to a
message that was already either on- or off-topic depending on your
view.

Personally, I think questions about, and discussion of, compiler
conformance are on topic here, but other may well disagree. No doubt
they will tell me so.
 
I

Ian Collins

new said:
Why lcc-win32 is sometimes on-topic and is sometimes off-topic here?
It's on topic if it's being bashed.
It's off topic if it's being advertised.

:)
 
B

Ben Bacarisse

Richard Heathfield said:
Ben Bacarisse said:
I'm a little puzzled by "new to c"'s question, since I can only find one
question of his about lcc-win32 in the "Google Groups" archives.

I think "new to c" may post under various names, but I don't really
know. There were a few seemingly similar questions a while back that
caused the last such poster -- "new to c" -- to be accused of trying
to stir things up.
In fact,
I only found one post at all by "new to c" in those archives (I guess his
latest article hasn't hit their server yet as I write this.) It asked two
questions, one of which was about portability and one of which was about
the -A -A flag combination in lcc-win32, and I don't see any sign of
either question being criticised as being off-topic.

He/she said (s)he was accused of being a troll and that is exactly what
happened.

If I am brutally honest, I suspect my posting about lcc-win32's
conformance to C99 was essentially unhelpful. It may have been
prompted by exasperation at Jacob Navia promoting the use of a
language standard that his compiler has only limited support for but,
as such, it was as much a "troll" as many posts here since it was
short on information (what works and what does not) and high on
rhetoric (irony is a favourite rhetorical device).
 
J

jacob navia

Ben said:
If I am brutally honest, I suspect my posting about lcc-win32's
conformance to C99 was essentially unhelpful. It may have been
prompted by exasperation at Jacob Navia promoting the use of a
language standard that his compiler has only limited support for but,
as such, it was as much a "troll" as many posts here since it was
short on information (what works and what does not) and high on
rhetoric (irony is a favourite rhetorical device).

Everywhere I have said that I do not support designated initializers as
yet. Heathfield (and you) know this, that is why you put those there.

I am working since several weeks in doing that, and several attempts
have failed, because the complexity of the initialization rules in C99.

My first attempt was to build an image of the structure in memory, so
that you can "jump" from one field to the next in any order. This is
OK of course for simple structures, but will fail when your structure
definition contains references to other symbols that need a relocation.

For instance

struct M { int a;char *b;};
struct M ss = {6,"string"};

The reference to a char pointer means I have to put into the
structure the address of the character string, i.e. I have to first
generate the character string, assign it an automatic symbol, and then
put the reference to that symbol into the structure that is being built.

This was done before and immediately written to the assembler file, but
now I can't write anything, and must build structures in memory
where I can jump around according to the tags.

Obviously all structures are recursive, and I have to do this
recursively for arrays and structures since both now allow jumping
around.

I must work in my day time job and can't do this every day. I must
do it in week ends, or at night. Excellent working conditions surely.

You have the easy part Becarisse. Just complain, ironically say that
lcc-win is a pile of shit, etc.
 
J

jacob navia

Richard said:
jacob navia said:



Then you don't have a C99 compiler as yet.

And gcc doesn't have a C++ compiler, nor does Microsoft. They do not
implement *fully* the huge C++ standard.

Yes, I do not have a FULL C99 implementation as yet.
 
B

Bartc

Everywhere I have said that I do not support designated initializers as
yet. Heathfield (and you) know this, that is why you put those there.

I am working since several weeks in doing that, and several attempts
have failed, because the complexity of the initialization rules in C99.

My first attempt was to build an image of the structure in memory, so
that you can "jump" from one field to the next in any order. This is
OK of course for simple structures, but will fail when your structure
definition contains references to other symbols that need a relocation.

For instance

struct M { int a;char *b;};
struct M ss = {6,"string"};

The reference to a char pointer means I have to put into the
structure the address of the character string, i.e. I have to first
generate the character string, assign it an automatic symbol, and then
put the reference to that symbol into the structure that is being built.

This was done before and immediately written to the assembler file, but
now I can't write anything, and must build structures in memory
where I can jump around according to the tags.

Your example seems an ordinary non-designated initialiser. You mean the
difficulty comes with:

struct M ss = {.b "string"}; ?

Assuming a more interesting struct like:

struct M { int a,b,c; struct N {int p,q,r;} d; int e;};

And the initialiser is:

struct M ss = {.d {.q 200} .c 30 };

Couldn't this just be treated as though the user had written:

struct M ss = { X, X, 30, {X, 200,X}, X};

where X is the default value of the uninitialised fields?

Alternatively, does the standard prohibit startup code that just does:

struct M ss;

ss.c = 30;
ss.d.q = 200; ?
 
J

jacob navia

Bartc said:
Your example seems an ordinary non-designated initialiser. You mean the
difficulty comes with:

struct M ss = {.b "string"}; ?

yes, of course

Assuming a more interesting struct like:

struct M { int a,b,c; struct N {int p,q,r;} d; int e;};

And the initialiser is:

struct M ss = {.d {.q 200} .c 30 };

Couldn't this just be treated as though the user had written:

struct M ss = { X, X, 30, {X, 200,X}, X};

where X is the default value of the uninitialised fields?

Yes, but I have to put it in the right order. And you can
jump backwards, etc.
Alternatively, does the standard prohibit startup code that just does:

struct M ss;

ss.c = 30;
ss.d.q = 200; ?

That would be terribly inefficient!
 
O

Old Wolf

Several people in this group argue that standard C
is not portable since there are no compilers for it, etc.

I have already successfully compiled this program under

(1): windows using lcc-win.

You acknowledged later in this thread that
lcc-win does not support standard C (i.e. C99).

So what is the point of this thread again?
 
R

Richard Bos

Old Wolf said:
You acknowledged later in this thread that
lcc-win does not support standard C (i.e. C99).

So what is the point of this thread again?

Satisfaction. At any cost.

Richard
 
J

jacob navia

Andrew said:
Isn't that what you have to write explicitly in C90 anyway?

No.

struct s { int a,b,c;};

struct s example = { 1,2,3};

The assignments are done at compile time, not at run time.
The compiler prepares an image of the bits of the
structure and writes that image to the object file.
When loaded, the program finds at the address of "example"
the three integers in the right sequence.
 
A

Andrew Poelstra

No.

struct s { int a,b,c;};

struct s example = { 1,2,3};

Oh, of course. For stylistic reasons, I've only ever initialized
structs that way with {0} - otherwise I prefer to see explicitly
which members are being assigned what.
 
B

Bartc

jacob navia said:
No.

struct s { int a,b,c;};

struct s example = { 1,2,3};

The assignments are done at compile time, not at run time.
The compiler prepares an image of the bits of the
structure and writes that image to the object file.
When loaded, the program finds at the address of "example"
the three integers in the right sequence.

I think he meant how would a user code C99's designated initialisers using
C90:

struct M {int f1,f2,..... f1000;};

struct M ss {.f456 51};

In C90 this would best be coded as...? One way is to just do:

ss.f456 = 51;

which was my suggestion. (You might also save 4000 bytes of initialised --
but mostly zerod -- data in the executable, which brings up another problem
of initialising large but sparse structs and arrays.)
 
J

jameskuyper

jacob said:
No.

struct s { int a,b,c;};

struct s example = { 1,2,3};

The assignments are done at compile time, not at run time.
The compiler prepares an image of the bits of the
structure and writes that image to the object file.
When loaded, the program finds at the address of "example"
the three integers in the right sequence.

That's not the typical use case for designated initializers. The more
typical case is to have a struct with a large number of members, only
a few of which will be explicitly initialized to non-zero values.
Unless those few are near the beginning of the structure, the
corresponding C90 code would indeed usually look something like this:

struct big_complicated this_one = {0};
this_one.some_field = initial_value;
 
F

Flash Gordon

jacob navia wrote, On 27/08/08 23:10:
See the thread "Another C99 challenge" for my answer.

Why start another thread instead of replying? After all, is was still
relevant to the subject of this thread. Perhaps it was to hide the fact
that you did NOT answer my questions in your other thread. You changed
the code in a way that affects the results on my implementation at least.
 
J

jacob navia

Flash said:
jacob navia wrote, On 27/08/08 23:10:

Why start another thread instead of replying? After all, is was still
relevant to the subject of this thread. Perhaps it was to hide the fact
that you did NOT answer my questions in your other thread. You changed
the code in a way that affects the results on my implementation at least.

Yes, and I reported that to the comp.std.c group.

No C99 compiler apparently implements the standard floating point
pragmas within a compound statement. This is a bug in the C99
definition since it implies a full rewrite of any compiler.

The problem is that it is VERY difficult to keep scope semantics
after all the code rearranging that is done by all optimizing compilers.

Keeping weird floating point semantics and restoring them after
a block scope is too much. I proposed that the standard requirement
is lessened to just having those semantics
at global scope, i.e. outside a function. In that case the compiler
would still be able to rearrange code at will within the function
assuming that 3.8*76.5 would be folded at compile time.
 
K

Keith Thompson

jacob navia said:
Yes, and I reported that to the comp.std.c group.

No C99 compiler apparently implements the standard floating point
pragmas within a compound statement. This is a bug in the C99
definition since it implies a full rewrite of any compiler.

The problem is that it is VERY difficult to keep scope semantics
after all the code rearranging that is done by all optimizing compilers.

Keeping weird floating point semantics and restoring them after
a block scope is too much. I proposed that the standard requirement
is lessened to just having those semantics
at global scope, i.e. outside a function. In that case the compiler
would still be able to rearrange code at will within the function
assuming that 3.8*76.5 would be folded at compile time.

I'm skeptical that it's as difficult as you say it is.

It seems to me that when the FP_CONTRACT pragma applies to a region of
code, the compiler can just avoid moving any code across the
boundaries of that region. You'd need to enhance the information that
can be stored internally and/or in some intermediate form, but that's
hardly a "full rewrite". (Possibly you could fake it by treating the
region of code as a separate function in some manner, but the need to
be able to access things declared in enclosing scopes adds some
complexity to that approach.)

Even allowing it only outside any functions doesn't solve all the
problems. For example, it could apply to a single inline function;
you'd still need to be careful about moving code across the boundaries
of an inlined call to that function.

#pragma STDC FP_CONTRACT OFF
inline void foo(void) {
/* a bunch of calculations */
}
#pragma STDC FP_CONTRACT ON

void another_function(void)
{
/* some calculations */
foo();
/* some more calculations */
}
 
F

Flash Gordon

jacob navia wrote, On 29/08/08 20:05:
Yes, and I reported that to the comp.std.c group.

So how about actually ANSWERING the question?
No C99 compiler apparently implements the standard floating point
pragmas within a compound statement.

Have you actually tested any of the ones that claim to conform to C99? I
don't means ones like lcc-win32 which you admit doesn't yet conform or
ones like gcc where the maintainers state that things are broken, but
the few compilers that actually claim to conform. If not, you are in no
position to claim that.
This is a bug in the C99
definition since it implies a full rewrite of any compiler.

The problem is that it is VERY difficult to keep scope semantics
after all the code rearranging that is done by all optimizing compilers.

Actually the gcc failure I reported (and the warnings) are *not*
dependant on the pragmas being at block scope. So take them out of block
scope. So take them out of block scope and test again.
Keeping weird floating point semantics and restoring them after
a block scope is too much. I proposed that the standard requirement
is lessened to just having those semantics
at global scope, i.e. outside a function. In that case the compiler
would still be able to rearrange code at will within the function
assuming that 3.8*76.5 would be folded at compile time.

I'm not clear that constant folding in a way that does not follow the
dynamically selected rounding method is allowed. I'm pretty sure that it
is not allowed if crontracting expressions has been disabled.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
ScottChare

Latest Threads

Top