Translating from C with extensions to standard C

S

Spiros Bousbouras

There are several compilers which accept various
extensions to the C language and produce native
code. But I wonder if there are any which offer the
option to translate from C with some extensions
to standard C.
 
C

Cong Wang

Spiros said:
There are several compilers which accept various
extensions to the C language and produce native
code. But I wonder if there are any which offer the
option to translate from C with some extensions
to standard C.

I am afraid not. The reason why they extend C is mainly that standard C
can't do the things that they want. Standard C is aimed at portability
while extended C is aimed at optimizing for low level operations or for
certain architecture.
Maybe few extensions can be translated, but most not.
 
S

Spiros Bousbouras

Cong said:
I am afraid not. The reason why they extend C is mainly that standard C
can't do the things that they want. Standard C is aimed at portability
while extended C is aimed at optimizing for low level operations or for
certain architecture.
Maybe few extensions can be translated, but most not.

Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?
 
C

Cong Wang

Spiros said:
Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?

Of course. The following code is from Linux kernel and is written with
GCC extensions:

#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})

It can hardly be translated into standard C.
And another obvious extension of GCC that can't be translated is inline
asm, of course.
 
R

Richard Heathfield

Spiros Bousbouras said:
There are several compilers which accept various
extensions to the C language and produce native
code. But I wonder if there are any which offer the
option to translate from C with some extensions
to standard C.

The reason that programmers sometimes use extensions is that the standard
language doesn't provide a way to do what they need to do. In other words,
the answer is no, there are no compilers which genuinely offer this option
in the general case.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
I

Ian Collins

Spiros said:
Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?
Packed data structures and special interrupt function types spring to mind.
 
C

CBFalconer

Spiros said:
Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?

You don't even have to go to extensions. Both offsetof() and
getc() are not translatable. That's why they are part of the
standard library.
 
K

Keith Thompson

Cong Wang said:
Spiros Bousbouras wrote: [...]
Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?

Of course. The following code is from Linux kernel and is written with
GCC extensions:

#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})

It can hardly be translated into standard C.
And another obvious extension of GCC that can't be translated is inline
asm, of course.

That specific construct can't be expressed in standard C, but any
program that uses it can be translated into an equivalent standard C
program. The extended-C to C translator would just have to replace
"typeof(x)" with the actual type of x.

There's precedent for this kind of thing; see cfront.
And another obvious extension of GCC that can't be translated is inline
asm, of course.

That's a better example. (I suppose a translator could emit standard
C code for a CPU emulator, but that's probably cheating.)
 
C

Cong Wang

CBFalconer said:
You don't even have to go to extensions. Both offsetof() and
getc() are not translatable. That's why they are part of the
standard library.

Is offsetof() not translatable?

#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif
 
K

Kenny McCormack

Spiros Bousbouras said:


The reason that programmers sometimes use extensions is that the standard
language doesn't provide a way to do what they need to do. In other words,
the answer is no, there are no compilers which genuinely offer this option
in the general case.

If there were (i.e., if it [the 'it' that is the subject of this thread]
was possible), this ng would be a lot more interesting.

Everytime somebody posted something off-topic (say, something Linux-y or
Windows-y), we could give him the Standard C version of it, and
everybody would live happily everafter.
 
K

Keith Thompson

Cong Wang said:
Is offsetof() not translatable?

Yes and no (or, since it was a negative question, perhaps I should say
no and yes).
#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif

That definition is not strictly portable, which is exactly why
offsetof() is part of the standard library. It can be implemented, by
"magic" if necessary, in any implementation, but no one definition can
be portable.

But it's not a good example. An invocation of offsetof() or getc() is
*already* standard C; it doesn't need to be translated. And even if
offsetof() weren't part of the standard library, a hypothetical
translator (actually a compiler that produces standard C as its
output) could easily replace an offsetof() invocation with the
constant value of the actual offset. The requirement was to to
generate standard C, not portable or maintainable C; the translator
would have to know how the backend C compiler does structure layout.
 
G

Gordon Burditt

I am afraid not. The reason why they extend C is mainly that standard C
Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?

There are a lot of things standard C can't do in terms of external
interfaces, so unless you can do these with a non-standard external
command called from system(), or it can be done by something starting
the program (e.g. connecting stdin to a network connection), they
can't be done.

- Reading the list of files in a directory. (POSIX opendir() and readdir()
are not standard C, and system("ls > list.tmp"), then opening up list.tmp
and reading it is not guaranteed to do what might be expected).
- Displaying graphics. (It is probably possible to transform graphics
files portably, given the application-specific format of, say, a .jpeg
file, and something else to handle the display of the file after the
program has run).
- Coin Return. Some systems don't even have a coin slot, and there are
a variety of ways to return deposited coins.
- Networking. You might be able to do limited networking by passing a
user-supplied string to fopen() to access remote files, or connect a
pipe to stdin, stdout, or stderr, before the program starts but things
like BSD bind(), connect(), creating sockets, listen(), etc. are
not standard C.
- Launching missiles, although fflush(stdin) may do this, but it's not
standard C, and there's the problem of targetting.
- Anything to do with reading or changing the ownership, permissions,
color, colour, timestamps, or postage on a file. POSIX stat() is
not standard C, and files may not have some or all of these attributes.
- Creation of a directory, folder, foulder, named pipe, socket, wormhole,
special device file, stargate, or warp field. system("mkdir foo")
is not guaranteed to create a directory, folder, or foulder, nor is it
guaranteed which will be created if one is at all.
 
I

Ira Baxter

Keith Thompson said:
Cong Wang said:
Spiros Bousbouras wrote: [...]
Can you give me an example of an extension which
cannot be translated into (efficient) standard C ?

Of course. The following code is from Linux kernel and is written with
GCC extensions:

#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})

It can hardly be translated into standard C.
And another obvious extension of GCC that can't be translated is inline
asm, of course.

Semantic Designs offers a program transformation system which
can transform C (and other languages, including C++). We have
in fact implemented extensions of C++ and transformed them down
to standard C++; this is much harder than doing extensions for C :-}
We have also implemented transforms of GNU-type
extensions of C (the typeof construct in particular, as in the above
example)
into standard C.

Inline assembler could be translated to C if the assembler instructions
affect the visible machine state in ways representable in C. Machine
instructions that only affect the hardware would likely be untranslatable.
However, it isn't clear that the OP was really interested in this case.

See http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html
 
S

Stephen Sprunk

Gordon Burditt said:
There are a lot of things standard C can't do in terms of external
interfaces, so unless you can do these with a non-standard external
command called from system(), or it can be done by something starting
the program (e.g. connecting stdin to a network connection), they
can't be done.

- Reading the list of files in a directory. (POSIX opendir() and
readdir()
are not standard C, and system("ls > list.tmp"), then opening up
list.tmp
and reading it is not guaranteed to do what might be expected).
- Displaying graphics. (It is probably possible to transform graphics
files portably, given the application-specific format of, say, a
.jpeg
file, and something else to handle the display of the file after the
program has run).
- Coin Return. Some systems don't even have a coin slot, and there
are
a variety of ways to return deposited coins.
- Networking. You might be able to do limited networking by passing a
user-supplied string to fopen() to access remote files, or connect a
pipe to stdin, stdout, or stderr, before the program starts but
things
like BSD bind(), connect(), creating sockets, listen(), etc. are
not standard C.
- Launching missiles, although fflush(stdin) may do this, but it's not
standard C, and there's the problem of targetting.
- Anything to do with reading or changing the ownership, permissions,
color, colour, timestamps, or postage on a file. POSIX stat() is
not standard C, and files may not have some or all of these
attributes.
- Creation of a directory, folder, foulder, named pipe, socket,
wormhole,
special device file, stargate, or warp field. system("mkdir foo")
is not guaranteed to create a directory, folder, or foulder, nor is
it
guaranteed which will be created if one is at all.

All of those are examples of non-portable libraries that may be
available, not actual language extensions.

Extensions would be something like the ability to change the calling
convention for a function, specify attributes for variables or functions
(e.g. the number of bits in an int, or that a function is "const" or
"pure"), integral thread-local storage, nested functions, etc. Most of
those types of things cannot be translated into standard C because
standard C doesn't provide any way to do those things -- or even
acknowledge those things exist.

S
 
G

Giorgos Keramidas

Can you give me an example of an extension which cannot be translated
into (efficient) standard C ?

FWIW,

One example, which I can remember from a recent FreeBSD discussion,
includes the packing and alignment extensions of GCC for struct objects:

__attribute ((__packed__))
__attribute ((aligned (X))) /* X = alignment size in bytes */

The standard does not specify the *precise* memory layout of 'struct'
objects. This is done for a reason, since there cannot be One True
Way(TM) of arranging the members of a struct object in memory, which can
satisfy any sort of requirement for alignment restrictions on *any*
system and still perform as fast as possible.

You can annotate sources using these two extensions with as many
comments and other meta-information you want, but there is *no* portable
way to do the same thing in strictly conforming ANSI C programs.

- Giorgos
 
K

Keith Thompson

Giorgos Keramidas said:
FWIW,

One example, which I can remember from a recent FreeBSD discussion,
includes the packing and alignment extensions of GCC for struct objects:

__attribute ((__packed__))
__attribute ((aligned (X))) /* X = alignment size in bytes */

The standard does not specify the *precise* memory layout of 'struct'
objects. This is done for a reason, since there cannot be One True
Way(TM) of arranging the members of a struct object in memory, which can
satisfy any sort of requirement for alignment restrictions on *any*
system and still perform as fast as possible.

You can annotate sources using these two extensions with as many
comments and other meta-information you want, but there is *no* portable
way to do the same thing in strictly conforming ANSI C programs.

For __packed__, the translator (think of it as a compiler that emits
standard C as its output) could lay out the structure with no gaps,
then use memcpy() or equivalent to extract or store any members that
might not be aligned as they would be in standard C (probably any but
the first).

The translator could use heap allocation for anything with an
"aligned" attribute, as long as the specified alignment doesn't exceed
the alignment guaranteed by malloc(). Larger alignments would require
system-specific support.

You might not *want* to do this kind of translation, and the resulting
standard C code wouldn't be maintainable, but that wasn't a
requirement.

It's common to use C as an intermediate language for compilers; cfront
is an example.
 
I

Ian Collins

Keith said:
Giorgos Keramidas said:
[...]
Can you give me an example of an extension which cannot be translated
into (efficient) standard C ?

FWIW,

One example, which I can remember from a recent FreeBSD discussion,
includes the packing and alignment extensions of GCC for struct objects:

__attribute ((__packed__))
__attribute ((aligned (X))) /* X = alignment size in bytes */

The standard does not specify the *precise* memory layout of 'struct'
objects. This is done for a reason, since there cannot be One True
Way(TM) of arranging the members of a struct object in memory, which can
satisfy any sort of requirement for alignment restrictions on *any*
system and still perform as fast as possible.

You can annotate sources using these two extensions with as many
comments and other meta-information you want, but there is *no* portable
way to do the same thing in strictly conforming ANSI C programs.


For __packed__, the translator (think of it as a compiler that emits
standard C as its output) could lay out the structure with no gaps,
then use memcpy() or equivalent to extract or store any members that
might not be aligned as they would be in standard C (probably any but
the first).

The translator could use heap allocation for anything with an
"aligned" attribute, as long as the specified alignment doesn't exceed
the alignment guaranteed by malloc(). Larger alignments would require
system-specific support.

You might not *want* to do this kind of translation, and the resulting
standard C code wouldn't be maintainable, but that wasn't a
requirement.
I had to do this a while back, the secret to keeping the code
maintainable was to treat the packed structures as opaque types and
generating getter/setter functions to access the members.
 

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,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top