Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #102319 > unrolled thread
| Started by | BartC <bc@freeuk.com> |
|---|---|
| First post | 2017-01-22 13:24 +0000 |
| Last post | 2017-01-30 05:30 -0800 |
| Articles | 20 on this page of 35 — 10 participants |
Back to article view | Back to comp.lang.c
Preprocessor expressions BartC <bc@freeuk.com> - 2017-01-22 13:24 +0000
Re: Preprocessor expressions jameskuyper@verizon.net - 2017-01-22 07:52 -0800
Re: Preprocessor expressions Ralf Damaschke <rwspam@gmx.de> - 2017-01-22 17:15 +0000
Re: Preprocessor expressions "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-22 13:32 -0500
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-01-22 17:38 +0000
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-01 03:12 -0800
Re: Preprocessor expressions Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-01 11:44 +0000
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-01 11:56 +0000
Re: Preprocessor expressions jameskuyper@verizon.net - 2017-02-01 08:35 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-02 09:23 -0800
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-02 18:14 +0000
Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-02 10:35 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-02 17:09 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-05 10:09 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-05 10:38 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-05 11:03 -0800
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-06 15:17 +0000
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-07 05:36 -0800
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-07 21:01 +0000
Re: Preprocessor expressions supercat@casperkitty.com - 2017-02-07 13:16 -0800
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-07 22:09 +0000
Re: Preprocessor expressions supercat@casperkitty.com - 2017-02-07 14:33 -0800
Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-07 14:52 -0800
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-08 00:13 +0000
Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-07 16:39 -0800
Re: Preprocessor expressions jameskuyper@verizon.net - 2017-02-07 16:47 -0800
Re: Preprocessor expressions David Brown <david.brown@hesbynett.no> - 2017-02-08 10:03 +0100
Re: Preprocessor expressions Keith Thompson <kst-u@mib.org> - 2017-02-08 09:19 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-08 12:35 -0800
Re: Preprocessor expressions Thiago Adams <thiago.adams@gmail.com> - 2017-02-09 05:25 -0800
Re: Preprocessor expressions supercat@casperkitty.com - 2017-02-09 07:37 -0800
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-02-09 15:52 +0000
Re: Preprocessor expressions BartC <bc@freeuk.com> - 2017-01-22 19:34 +0000
Re: Preprocessor expressions jameskuyper@verizon.net - 2017-01-22 13:01 -0800
Re: Preprocessor expressions Tim Rentsch <txr@alumni.caltech.edu> - 2017-01-30 05:30 -0800
Page 1 of 2 [1] 2 Next page →
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-01-22 13:24 +0000 |
| Subject | Preprocessor expressions |
| Message-ID | <o62bn5$kms$1@dont-email.me> |
These are the ones that occur after #if and #elif. The standard 6.10p1 says these are constant-expressions. But the latter (A.2.1) can apparently include casts, ++, sizeof, ., ->, [] and and all the rest. 6.6 says little about constant expressions except that it rules out ++ and -- (assignment and so on are ruled out by the grammar). Where are the restrictions for what are allowed in #if expressions? All I can see are numerous instances of 'constant expressions suitable for use in #if preprocessing directives', without it defining 'suitable'. I can guess what it means, but I would rather not guess. -- Bartc
[toc] | [next] | [standalone]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-01-22 07:52 -0800 |
| Message-ID | <d4b65b12-2c67-475e-9121-8d96874df453@googlegroups.com> |
| In reply to | #102319 |
On Sunday, January 22, 2017 at 8:24:30 AM UTC-5, Bart wrote: > These are the ones that occur after #if and #elif. > > The standard 6.10p1 says these are constant-expressions. But the latter > (A.2.1) can apparently include casts, ++, sizeof, ., ->, [] and and all > the rest. Keep in mind that, in an #if constant-expression, all of the following occur before the condition is interpreted as a constant-expression: 1. macros that are not the argument of the "defined" unary operator are expanded. 2. occurrences of the "defined" unary operator are replaced by either 0 or 1, depending upon whether or not it's argument matches the name of a defined macro. 3. All remaining identifiers are replaced with the pp-number 0. This occurs BEFORE conversion of pre-processing tokens into tokens (6.10.1p4). Keep in mind that keywords qualify only as tokens, and not as pre-processing tokens (6.4p1). At this point in the translation process, things that will later be identified as keywords are parsed only as identifiers - and the conversion described above applies to those identifiers. Therefore, (struct tm*) would be converted to (0 0*), and (int (*)(double)) would be converted to (0(*)(0), both of which are syntax errors. Offhand, I don't see any way for a #if condition to contain an actual cast. For both the prefix and postfix versions of the ++ and -- operators, there is a constraint that their argument be a modifiable lvalue. With all identifiers converted to 0, how could that constraint ever be satisfied? For both the "." and "->", the left operand is required to have a struct or union type. With all identifiers (including typedefs, struct and union tags, and all of the keywords used to specify types) replaced with 0, how could you form such an operand? With all identifiers converted to 0, the only way to form an array is using a string literal. "abcdef"[0] is therefore permitted in a #if. > 6.6 says little about constant expressions except that it rules out ++ > and -- (assignment and so on are ruled out by the grammar). > > Where are the restrictions for what are allowed in #if expressions? I don't think that there are any explicit restrictions other than those that apply to constant expressions in general. However, the fact that all identifiers are converted to 0 means that a great many possibilities that can occur in constant expressions in other contexts cannot meaningfully occur in a #if condition. Most of those possibilities become syntax errors after the conversion; most of the others change meaning as a result of the conversion. For instance, "array"[i] becomes "array"[0]. The only reason I can think of why anyone would write "array"[i] in an #if condition is if they were unaware of that conversion, and would therefore be surprised by the fact that it occurred. > All I can see are numerous instances of 'constant expressions suitable > for use in #if preprocessing directives', without it defining > 'suitable'. I can guess what it means, but I would rather not guess.
[toc] | [prev] | [next] | [standalone]
| From | Ralf Damaschke <rwspam@gmx.de> |
|---|---|
| Date | 2017-01-22 17:15 +0000 |
| Message-ID | <pan.2017.01.22.17.15.43@y2plugh.fqdn.th-h.de> |
| In reply to | #102331 |
jameskuyper wrote: > With all identifiers converted to 0, the only way to form an array is using a > string literal. "abcdef"[0] is therefore permitted in a #if. I don't think so. § 6.6p6 only allows some sorts of operands and implicitly rules out the operators that need at least an excluded one (such as "[]" and btw. also ".", "->", "++"): | An integer constant expression shall have integer type and shall only | have operands that are integer constants, enumeration constants, | character constants, sizeof expressions whose results are integer | constants, _Alignof expressions, and floating constants that are the | immediate operands of casts. FWIW, casts were explicitly excluded in C99 § 6.10.1p1 but this was probably discarded being redundant to the substitution mechanism you describe above.
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-01-22 13:32 -0500 |
| Message-ID | <f43f4d41-805e-2578-3d0c-83763e43cf4b@verizon.net> |
| In reply to | #102341 |
On 01/22/2017 12:15 PM, Ralf Damaschke wrote: > jameskuyper wrote: > >> With all identifiers converted to 0, the only way to form an array is using a >> string literal. "abcdef"[0] is therefore permitted in a #if. > > I don't think so. § 6.6p6 only allows some sorts of operands and > implicitly rules out the operators that need at least an excluded one > (such as "[]" and btw. also ".", "->", "++"): You're right - I was concentrating on the implications of 6.10.1p4, and forgot to be careful about the details of what 6.6 said. > | An integer constant expression shall have integer type and shall only > | have operands that are integer constants, enumeration constants, > | character constants, sizeof expressions whose results are integer > | constants, _Alignof expressions, and floating constants that are the > | immediate operands of casts. > > FWIW, casts were explicitly excluded in C99 § 6.10.1p1 but this was > probably discarded being redundant to the substitution mechanism > you describe above. I participated in discussions in 2001 <https://groups.google.com/d/msg/comp.std.c/KmkW8N3KgKM/AQXW5Iuc-R4J> about precisely this issue, which may have been part of the process that led to that change.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-01-22 17:38 +0000 |
| Message-ID | <o62qjg$ib0$1@dont-email.me> |
| In reply to | #102331 |
On 22/01/2017 15:52, jameskuyper@verizon.net wrote: > On Sunday, January 22, 2017 at 8:24:30 AM UTC-5, Bart wrote: >> These are the ones that occur after #if and #elif. >> >> The standard 6.10p1 says these are constant-expressions. But the latter >> (A.2.1) can apparently include casts, ++, sizeof, ., ->, [] and and all >> the rest. > > Keep in mind that, in an #if constant-expression, all of the following occur > before the condition is interpreted as a constant-expression: > 1. macros that are not the argument of the "defined" unary operator are > expanded. > 2. occurrences of the "defined" unary operator are replaced by either 0 or 1, > depending upon whether or not it's argument matches the name of a defined macro. > 3. All remaining identifiers are replaced with the pp-number 0. This occurs > BEFORE conversion of pre-processing tokens into tokens (6.10.1p4). > Keep in mind that keywords qualify only as tokens, and not as pre-processing > tokens (6.4p1). At this point in the translation process, things that will > later be identified as keywords are parsed only as identifiers - and the > conversion described above applies to those identifiers. > > Therefore, (struct tm*) would be converted to (0 0*), and (int (*)(double)) > would be converted to (0(*)(0), both of which are syntax errors. Offhand, I > don't see any way for a #if condition to contain an actual cast. > > For both the prefix and postfix versions of the ++ and -- operators, there is a > constraint that their argument be a modifiable lvalue. With all identifiers > converted to 0, how could that constraint ever be satisfied? > > For both the "." and "->", the left operand is required to have a struct or > union type. With all identifiers (including typedefs, struct and union tags, > and all of the keywords used to specify types) replaced with 0, how could you > form such an operand? OK, thanks. That's starting to make more sense (but a dedicated grammar for pp expressions I think would have been useful). > With all identifiers converted to 0, the only way to form an array is using a > string literal. "abcdef"[0] is therefore permitted in a #if. gcc (and most compilers I've tried) tells me that "abcdef" is not a valid pp token. And neither is "[", "->", ".", "++" and so on. (I've been using trial and error to figure these things out, to try and build a reduced syntax for these expressions.) -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-01 03:12 -0800 |
| Message-ID | <53636d82-e300-4745-9cf3-b4848b97d8b9@googlegroups.com> |
| In reply to | #102344 |
On Sunday, January 22, 2017 at 3:38:39 PM UTC-2, Bart wrote: [...] > (I've been using trial and error to figure these things out, to try and > build a reduced syntax for these expressions.) > For my C parser, I assume (I don't know if it is correct) that C compilers share the code for constant expressions between pre-processor and parser and the differences would be "natural" for instance, sizeof(X) would not work in pre-processor. Bart, can you pull tokens from your pre-processor or is it like recursive-descendent?
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-02-01 11:44 +0000 |
| Message-ID | <87poj2m8z8.fsf@bsb.me.uk> |
| In reply to | #102900 |
Thiago Adams <thiago.adams@gmail.com> writes: > On Sunday, January 22, 2017 at 3:38:39 PM UTC-2, Bart wrote: > [...] >> (I've been using trial and error to figure these things out, to try and >> build a reduced syntax for these expressions.) > > For my C parser, I assume (I don't know if it is correct) that C > compilers share the code for constant expressions between > pre-processor and parser and the differences would be "natural" > for instance, sizeof(X) would not work in pre-processor. The depends on what you include in the "natural" differences! Pre-processor expressions are evaluated in the widest integer type, for example. It's not just the replacement of un-expanded words by 0 that is different. <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-01 11:56 +0000 |
| Message-ID | <o6sia0$di6$1@dont-email.me> |
| In reply to | #102900 |
On 01/02/2017 11:12, Thiago Adams wrote: > On Sunday, January 22, 2017 at 3:38:39 PM UTC-2, Bart wrote: > [...] >> (I've been using trial and error to figure these things out, to try and >> build a reduced syntax for these expressions.) >> > > > For my C parser, I assume (I don't know if it is correct) that C > compilers share the code for constant expressions between > pre-processor and parser and the differences would be "natural" > for instance, sizeof(X) would not work in pre-processor. > Bart, can you pull tokens from your pre-processor or is it > like recursive-descendent? I'm not sure what this means. Other than #if expressions, my preprocessor doesn't not use recursion outside of macro expansions. For #if/#elif expressions, a recursive descent scheme is used, but that is completely separate from the one to be used when parsing the main language. The set of expressions is much more limited, but also /it evaluates the expression as it goes along/. The main expression will build an AST. The part of my preprocessor that deals with #if expressions is here (not in C): http://pastebin.com/cM51Km6k It follows the C grammar for constant-expression but leaves out anything not allowed in preprocessor expressions. (This propagates back signed/unsigned info but does not do anything with that at the minute; all ops are signed I think.) (For an auto-generated C version of the whole thing, see: https://github.com/bartg/langs/blob/master/clex/clex.c #if expression stuff is from line 5398.) -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | jameskuyper@verizon.net |
|---|---|
| Date | 2017-02-01 08:35 -0800 |
| Message-ID | <7a6cc8a1-6241-486e-bd87-43a0ccbe78b6@googlegroups.com> |
| In reply to | #102900 |
On Wednesday, February 1, 2017 at 6:12:54 AM UTC-5, Thiago Adams wrote: > On Sunday, January 22, 2017 at 3:38:39 PM UTC-2, Bart wrote: > [...] > > (I've been using trial and error to figure these things out, to try and > > build a reduced syntax for these expressions.) > > > > > For my C parser, I assume (I don't know if it is correct) that C > compilers share the code for constant expressions between > pre-processor and parser and the differences would be "natural" > for instance, sizeof(X) would not work in pre-processor. A C implementation could share code that way. However, the shared code should never see "sizeof(X)" - before passing the tokens to the constant-expression parser, the pre-processor should already have converted them to "0(0)". The shared code should know precisely what to do with such code (in this case, tag it as a syntax error). There's many things that the shared code would have to be prepared to deal with, that don't need to be dealt with during preprocessing. I suspect it might be worthwhile writing code specialized for that context. The specialized version would never have to deal with keywords or identifiers (since they will all have been converted to 0). It would therefore never have to deal with function names, variable names, type casts, generic selections, member selection operators, compound literals, sizeof, or _Alignof. > Bart, can you pull tokens from your pre-processor or is it > like recursive-descendent?
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-02 09:23 -0800 |
| Message-ID | <634d154c-9d22-4a83-8d3c-85ca4b89ae06@googlegroups.com> |
| In reply to | #102911 |
On Wednesday, February 1, 2017 at 2:35:39 PM UTC-2, james...@verizon.net wrote: > On Wednesday, February 1, 2017 at 6:12:54 AM UTC-5, Thiago Adams wrote: > > On Sunday, January 22, 2017 at 3:38:39 PM UTC-2, Bart wrote: > > [...] > > > (I've been using trial and error to figure these things out, to try and > > > build a reduced syntax for these expressions.) > > > > > > > > > For my C parser, I assume (I don't know if it is correct) that C > > compilers share the code for constant expressions between > > pre-processor and parser and the differences would be "natural" > > for instance, sizeof(X) would not work in pre-processor. Bart, I published my parser + pre-processor (without any fix) https://github.com/thradams/TurboLint/ I also have interest in C source to C source translation. Maybe add extensions to C and generate C. My preference would be friendly (multi files) generated code and also the big one translation unit option. The folder /TurboLint has the code for lint part plus source generation. The folder /Parser has the scanner (with pre-processor) and parser). The folder /Base is for strings, arrays, maps. The const expression is at Ast.c : 746 bool EvaluateConstantExpression(TExpression2 * _opt p, int *pResult) The input TExpression2 is the ast part that has only expressions.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-02 18:14 +0000 |
| Message-ID | <mGKkA.214862$3L.178811@fx26.am4> |
| In reply to | #102963 |
On 02/02/2017 17:23, Thiago Adams wrote:
> On Wednesday, February 1, 2017 at 2:35:39 PM UTC-2, james...@verizon.net wrote:
> Bart, I published my parser + pre-processor (without any fix)
>
> https://github.com/thradams/TurboLint/
(Is there any quick way of downloading all the files to a PC? Last time
I did it a file at time - click on a file, show raw, copy & paste to a
local file, save with the correct name - and it took ages.)
> I also have interest in C source to C source translation.
> Maybe add extensions to C and generate C. My preference would be
> friendly (multi files) generated code and also the
> big one translation unit option.
I've thought about that some more and it's not as straightforward as it
sounds.
For one thing, because my program would do preprocessing, any C output
would be a 'rendering' or 'snapshot' of a given C input and sets of
input macros and options. The output could be compiled as C, but you
couldn't use it for development; you'd have to go back to the original.
Example, input is:
#define OPTION 1
#if OPTION
A;
#else
B;
#endif
The output from this will be:
A;
In this new version, You can no longer change OPTION, and compile B
instead of A.
Also, code like this:
#define AGE 35
AGE;
will appear as just '35;'. There are many such issues.
To preserve the original includes, conditionals and macros will be a
different, more difficult project. Not impossible, as re-factoring
programs exist. But some of the things you may want to translate could
be hidden or affected by those includes, conditional code and macros.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-02 10:35 -0800 |
| Message-ID | <ln1svg7867.fsf@kst-u.example.com> |
| In reply to | #102967 |
BartC <bc@freeuk.com> writes:
> On 02/02/2017 17:23, Thiago Adams wrote:
>> On Wednesday, February 1, 2017 at 2:35:39 PM UTC-2, james...@verizon.net wrote:
>
>> Bart, I published my parser + pre-processor (without any fix)
>>
>> https://github.com/thradams/TurboLint/
>
> (Is there any quick way of downloading all the files to a PC? Last time
> I did it a file at time - click on a file, show raw, copy & paste to a
> local file, save with the correct name - and it took ages.)
[...]
Click "Clone or download" and select "Download ZIP".
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-02 17:09 -0800 |
| Message-ID | <e3c53979-10e8-44e4-b6c4-0cd5b65ae78f@googlegroups.com> |
| In reply to | #102967 |
On Thursday, February 2, 2017 at 4:14:54 PM UTC-2, Bart wrote:
> On 02/02/2017 17:23, Thiago Adams wrote:
> > On Wednesday, February 1, 2017 at 2:35:39 PM UTC-2, james...@verizon.net wrote:
>
> > Bart, I published my parser + pre-processor (without any fix)
> >
> > https://github.com/thradams/TurboLint/
>
> (Is there any quick way of downloading all the files to a PC? Last time
> I did it a file at time - click on a file, show raw, copy & paste to a
> local file, save with the correct name - and it took ages.)
>
> > I also have interest in C source to C source translation.
> > Maybe add extensions to C and generate C. My preference would be
> > friendly (multi files) generated code and also the
> > big one translation unit option.
>
> I've thought about that some more and it's not as straightforward as it
> sounds.
>
> For one thing, because my program would do preprocessing, any C output
> would be a 'rendering' or 'snapshot' of a given C input and sets of
> input macros and options. The output could be compiled as C, but you
> couldn't use it for development; you'd have to go back to the original.
>
> Example, input is:
>
> #define OPTION 1
>
> #if OPTION
> A;
> #else
> B;
> #endif
>
> The output from this will be:
>
> A;
>
> In this new version, You can no longer change OPTION, and compile B
> instead of A.
>
> Also, code like this:
>
> #define AGE 35
>
> AGE;
>
> will appear as just '35;'. There are many such issues.
>
> To preserve the original includes, conditionals and macros will be a
> different, more difficult project. Not impossible, as re-factoring
> programs exist. But some of the things you may want to translate could
> be hidden or affected by those includes, conditional code and macros.
>
>
I guess one good approach to generate code similar of input
source is not to recreate it but change it.
For instance, let's say I want to implement the
default initialization:
--file1.h--
struct X {
int i = 1;
int k = 2;
};
--file1.c--
int main()
{
X x = {};
}
I could have the input source as one big string.
The AST would have all tokens and positions from the
original input source. I also can understand if the token
is from one expanded macro and generate some error.
Then at AST I have the position of "= 1" and "= 2".
The generator would cut-paste from the input source.
cut "= 1" paste ""; cut " = 2" paste ""
The cut paste operation is always using the original position,
some correction needs to be applied.
Or I would just add /* before '=' and */ after '1'.
Small changes are better. Big changes, for instance,
replace all struct declaration could eat comments or macros.
This approach also doesn't work in all cases.
For instance:
--file1.h--
#ifdef XX
struct X {
int i = 1;
int k = 2;
};
#else
struct X {
int ii = 1;
int kk = 2;
};
#endif
The AST is built only for one situation, unless I could
have many ast's replacing the same input source. (maybe?)
Probably there are more difficult cases, but I think if
it works for common cases it's good enough.
Some code would be just "paste" or "cut" as well.
Final result:
--file1.h--
struct X {
int i /*= 1*/;
int k /*= 2*/;
};
#define X_INIT {1 , 2}
--file1.c--
int main()
{
X x = X_INIT;
}
-----
/* inserted before = 1
*/ inserted after = 1;
/* inserted before = 2
*/ inserted after = 2;
X_INIT was inserted after the token ; of struct declaration.
{} was replaced by X_INIT
Some feature I would like to have is function overload.
Then I would just replace "cut-paste" names with some
name mangling.
Some other mechanic tool without AST
could join these files to create the amalgamation file.
static functions also could be renamed in the previous stage
to avoid conflict for the mechanic tool.
--file1.c--
static void f() {}
f();
---generated---
static void file1_f() {}
file1_f();
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-05 10:09 -0800 |
| Message-ID | <f2b5c6b7-d029-48e6-84aa-2ff7b3ac38d2@googlegroups.com> |
| In reply to | #103000 |
On Thursday, February 2, 2017 at 11:09:23 PM UTC-2, Thiago Adams wrote:
[...]
> The cut paste operation is always using the original position,
> some correction needs to be applied.
I did an experiment how to replace parts from the original source.
With just one concept of "Change" is possible to add, delete
or replace parts from the original text.
The changed position must be sequential.
#include <stdio.h>
typedef struct
{
int Current;
const char* Source;
} Text;
#define TEXT_INIT {0, NULL}
void Flush(Text* text)
{
for (int i = text->Current; text->Source[i] != '\0'; i++)
{
printf("%c", text->Source[i]);
}
}
void Change(Text* text,
int position,
int sz,
const char* newStr)
{
for (int i = text->Current; i < position; i++)
{
printf("%c", text->Source[i]);
}
text->Current = position + sz;
if (newStr != NULL)
{
printf("%s", newStr);
}
}
int main()
{
Text text = TEXT_INIT;
//original text
text.Source = "0123456789";
//insert AAA before 2
Change(&text, 2, 0, "AAA");
//replace 56 by B
Change(&text, 5, 2, "B");
//delete 8
Change(&text, 8, 1, NULL);
Flush(&text);
return 0;
}
Result:
01AAA234B79
This kind of code modification also can be used to create
refactoring tools or some code generators.
Another case for code generation in C could be
lambdas (like C++)
void F(void (*PF)(int i));
int main()
{
F([](int i)
{
printf("hi");
});
}
The generated code would be:
-insert one static function before 'int main'
-replace [ ... } by &F_1
static void F_1(int i)
{
printf("hi %d", i);
}
int main()
{
F(&F_1);
}
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-05 10:38 -0800 |
| Message-ID | <4bb1dbcd-6e3c-40df-8319-eb33b8bfa685@googlegroups.com> |
| In reply to | #103000 |
On Thursday, February 2, 2017 at 11:09:23 PM UTC-2, Thiago Adams wrote: [...] > Some feature I would like to have is function overload. > Then I would just replace "cut-paste" names with some > name mangling. Later, I realized one problem for "pretty code" on function overload. Let's say I have: void Clear(X* x); void Clear(Y* y); If the Clear(X*) is the only function in all source, I don't want to decorate the name because the generated code would be unnecessarily decorated and difficult to read. But it's impossible to know (only with global analysis) if one more "Clear" exists.
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-05 11:03 -0800 |
| Message-ID | <030e3613-d745-46c4-8a46-d625eb276baa@googlegroups.com> |
| In reply to | #103226 |
On Sunday, February 5, 2017 at 4:38:15 PM UTC-2, Thiago Adams wrote: > On Thursday, February 2, 2017 at 11:09:23 PM UTC-2, Thiago Adams wrote: > [...] > > Some feature I would like to have is function overload. > > Then I would just replace "cut-paste" names with some > > name mangling. > > Later, I realized one problem for "pretty code" on function > overload. > Let's say I have: > > void Clear(X* x); > void Clear(Y* y); > > If the Clear(X*) is the only function in all source, > I don't want to decorate the name because the generated > code would be unnecessarily decorated and difficult to read. > > But it's impossible to know (only with global analysis) > if one more "Clear" exists. In a different approach where the source is not intended to be read (at least all the time) I think the best solution is to ignore pre-processor and generate code direct from AST. So, if you change #if macros you need to re-generate everything from the original source. Using this approach we also need to decide if the system includes will be added or not. System includes or "extern C" code could be the exception to the rule and they could be added at the top of the translation unit. //Begin external code includes #include <stdio.h> #include <some_c_lib.h> //End external code includes ..no more macros here...
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-06 15:17 +0000 |
| Message-ID | <o7a3u7$9u$1@dont-email.me> |
| In reply to | #103229 |
On 05/02/2017 19:03, Thiago Adams wrote:
> In a different approach where the source is not intended to
> be read (at least all the time) I think the best solution
> is to ignore pre-processor and generate code direct from AST.
> So, if you change #if macros you need to re-generate everything
> from the original source.
> Using this approach we also need to decide if the system includes
> will be added or not. System includes or "extern C" code could be
> the exception to the rule and they could be added at the top of the
> translation unit.
>
> //Begin external code includes
> #include <stdio.h>
> #include <some_c_lib.h>
> //End external code includes
With a translator with C output, the possibilities for dealing with
<stdio.h> for example are:
* Write #include <stdio.h> to the output too
* Write a preprocessed version of stdio.h
However that can result in user-code being dominated by preprocessed
versions of the standard headers. (It won't be the nearly 5000 lines
that are involved with stdio.h from gcc, but a few hundred as
conditional code is excluded, so still quite a bit.)
One idea I might try out, is to only output declarations from stdio.h
that are used in the program (either directly on indirectly). For
hello.c, that means declaring printf().
But the user program can still have this:
#if cond
printf("hello");
#endif
For my purposes, everything will need to be preprocessed anyway, so
printf will be included when cond is true. The output will be C code
that doesn't use any headers, not even system ones.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | Thiago Adams <thiago.adams@gmail.com> |
|---|---|
| Date | 2017-02-07 05:36 -0800 |
| Message-ID | <1e988be1-ec21-4335-8f79-e6d1e213f1c7@googlegroups.com> |
| In reply to | #103311 |
On Monday, February 6, 2017 at 1:17:14 PM UTC-2, Bart wrote:
> On 05/02/2017 19:03, Thiago Adams wrote:
>
> > In a different approach where the source is not intended to
> > be read (at least all the time) I think the best solution
> > is to ignore pre-processor and generate code direct from AST.
> > So, if you change #if macros you need to re-generate everything
> > from the original source.
> > Using this approach we also need to decide if the system includes
> > will be added or not. System includes or "extern C" code could be
> > the exception to the rule and they could be added at the top of the
> > translation unit.
> >
> > //Begin external code includes
> > #include <stdio.h>
> > #include <some_c_lib.h>
> > //End external code includes
>
> With a translator with C output, the possibilities for dealing with
> <stdio.h> for example are:
>
> * Write #include <stdio.h> to the output too
>
> * Write a preprocessed version of stdio.h
>
> However that can result in user-code being dominated by preprocessed
> versions of the standard headers. (It won't be the nearly 5000 lines
> that are involved with stdio.h from gcc, but a few hundred as
> conditional code is excluded, so still quite a bit.)
>
> One idea I might try out, is to only output declarations from stdio.h
> that are used in the program (either directly on indirectly). For
> hello.c, that means declaring printf().
>
> But the user program can still have this:
>
> #if cond
> printf("hello");
> #endif
>
> For my purposes, everything will need to be preprocessed anyway, so
> printf will be included when cond is true. The output will be C code
> that doesn't use any headers, not even system ones.
I guess, that you can increase the changes of avoiding "rebuild" in
different platforms if you keep the include of the system headers.
For instance, let's say you have a simple hello world.
#include <stdio.h>
int main()
{
printf("hello");
}
The generated code is the same. But if you include the declarations of
stdio.h you may be including a lot of stuffs from the previous platform.
I think the C standard also allow some functions to be implemented
optionally as a macro and this can differs between platforms.
If the "rebuild" is always used this is not a problem.
Bart, what kind of "input source" do you have in mind?
Language extensions for C? What kind?
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-07 21:01 +0000 |
| Message-ID | <o7dcfu$69q$1@dont-email.me> |
| In reply to | #103350 |
On 07/02/2017 13:36, Thiago Adams wrote:
> On Monday, February 6, 2017 at 1:17:14 PM UTC-2, Bart wrote:
>> One idea I might try out, is to only output declarations from stdio.h
>> that are used in the program (either directly on indirectly). For
>> hello.c, that means declaring printf().
>>
>> But the user program can still have this:
>>
>> #if cond
>> printf("hello");
>> #endif
>>
>> For my purposes, everything will need to be preprocessed anyway, so
>> printf will be included when cond is true. The output will be C code
>> that doesn't use any headers, not even system ones.
>
> I guess, that you can increase the changes of avoiding "rebuild" in
> different platforms if you keep the include of the system headers.
> For instance, let's say you have a simple hello world.
>
> #include <stdio.h>
>
> int main()
> {
> printf("hello");
> }
>
> The generated code is the same. But if you include the declarations of
> stdio.h you may be including a lot of stuffs from the previous platform.
Yes, quite a lot of stuff will be fixed in the output C source,
restricting how it can be used.
My experience at the moment (translating from a non-C language to C, in
a recent working project) is that things such as pointer sizes, and
struct-member offsets, will be fixed. That means that generated C
requires things like pack(1), and to be compiled for a particular
pointer size.
I'm not familiar with the details of the standard headers so I don't yet
know what other issues will arise. However, my current project counts as
a compiler, and a compiler is allowed to make these decisions as they
will usually have a particular target in mind.
It just means that if it optionally writes out the program code as C
source (rather than binary native code or ASM source, tied to some
processor and ABI), then it may be similarly restricted. I will have to
see how to works out.
Keeping the output C general is a much harder project.
> I think the C standard also allow some functions to be implemented
> optionally as a macro and this can differs between platforms.
> If the "rebuild" is always used this is not a problem.
>
> Bart, what kind of "input source" do you have in mind?
> Language extensions for C? What kind?
For the new project, input source will be standard C code. One of the
output options will be C, including single-file C. (Which may be
restricted to run on the same platform it was generated on.)
I'm not looking at any extensions at the minute (for one thing, because
I'm trying to make it fast, and any extensions are likely to slow to down!)
But later on, I'm likely to play around with some, although my ideas of
worthwhile extensions are going to be different from yours, gcc's, or
anyone else's.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-07 13:16 -0800 |
| Message-ID | <86f1f0c5-5f44-4bab-8cd2-074b407220e8@googlegroups.com> |
| In reply to | #103419 |
On Tuesday, February 7, 2017 at 3:01:36 PM UTC-6, Bart wrote: > My experience at the moment (translating from a non-C language to C, in > a recent working project) is that things such as pointer sizes, and > struct-member offsets, will be fixed. That means that generated C > requires things like pack(1), and to be compiled for a particular > pointer size. I would think it should be fairly straightforward to keep track of the required alignment for each type, and insert padding bytes in structure definitions as needed to maintain alignment. While the Standard allows implementations to use arbitrary padding rules, the vast majority use a simple rule which says that every object will be preceded by whatever amount of padding would be needed to reach the next multiple of its alignment, and every structure or union will have the same alignment requirement as its coarsest member. If your code knows the required alignment for each primitive, it should be able to add byte fields with dummy names so as to ensure that a compiler would never need to add any padding of its own unless it uses very weird structure layout rules.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web