473,386 Members | 2,042 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

how to do two-stage preprocessing of one file

What I'm trying to do is have the preprocessor parse one file twice.
The file has three parts, and each is dependent on the previous.
Example (file name is foo.c):
#ifndef ONCE /* first part */
#define D #define
#define ONCE
#include "foo.c"
#endif
#ifdef ONCE /* second part */
D x int
#ifndef TWICE
#define TWICE
#include "foo.c"
#endif
#endif
#ifdef TWICE /* third part */
x y;
#endif

The problem is that the preprocessor just adds the third part to the
second part, but doesn't preprocess the third part in the process.
How do I make my #includes and #ifedefs so that the third part will be
preprocessed?

Nov 12 '07 #1
11 2319
In article <11*********************@k79g2000hse.googlegroups. com>,
andreyvul <an********@gmail.comwrote:
>What I'm trying to do is have the preprocessor parse one file twice.
You cannot do that using the facilities defined by the C preprocessor.

Your particular implementation -probably- offers a way to
preprocess files. For example, on the system I am using at the
moment, the sequence would look something like,

cc -P myfile.c
mv myfile.i myfile_preprocessed.c
cc -o outputfile myfile_preprocessed.c

But it would also not be uncommon on a Unix system for the sequence
to look something closer to

cc -E myfile.c | egrep -v '^#line' myfile_preprocessed.c
cc -o outfile myfile_preprocessed.c

Many unix C compilers offer some option as in the second example,
to preprocess and send the result to standard output; it may
or may not be necessary in your toolchain to remove #line directives
from the preprocessed output before you can push the file back
through the C parseer.

If you are using one of the Windows compilers... there is probably
some similar option, but probably not named -P or -E .
--
"Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us." -- Ecclesiastes
Nov 13 '07 #2
On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,

andreyvul <andrey....@gmail.comwrote:
What I'm trying to do is have the preprocessor parse one file twice.

You cannot do that using the facilities defined by the C preprocessor.
Oh, I meant _recursively_ preprocess the file twice.
That's why I was asking about proper #include/#ifdef structure, so
that it preprocesses like this:

#block 1
|->#block 2 (via recursive include)
|->#block 3 (via recursive include)

however, it doesn't get to |->#block 3

Nov 13 '07 #3
andreyvul wrote:
On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
>In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,

andreyvul <andrey....@gmail.comwrote:
>>What I'm trying to do is have the preprocessor parse one file twice.
You cannot do that using the facilities defined by the C preprocessor.
Oh, I meant _recursively_ preprocess the file twice.
That's why I was asking about proper #include/#ifdef structure, so
that it preprocesses like this:

#block 1
|->#block 2 (via recursive include)
|->#block 3 (via recursive include)

however, it doesn't get to |->#block 3
I didn't try it but something along these lines might do it:

#ifndef REC_COUNT
#define REC_COUNT 2
#elif REC_COUNT == 2
#undef REC_COUNT
#define REC_COUNT 1
#elif REC_COUNT == 1
#undef REC_COUNT
#define REC_COUNT 0
#endif
/* Here is the meat */
#if REC_COUNT == 2
/* first iteration */
#elif REC_COUNT == 1
/* second iteration */
#else
/* third and last iteration */
#if REC_COUNT != 0
#include __FILE__
#endif

--
Ark
Nov 13 '07 #4
In article <11**********************@d55g2000hsg.googlegroups .com>,
andreyvul <an********@gmail.comwrote:
>On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
>In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,
>andreyvul <andrey....@gmail.comwrote:
>What I'm trying to do is have the preprocessor parse one file twice.
>You cannot do that using the facilities defined by the C preprocessor.
>Oh, I meant _recursively_ preprocess the file twice.
Oh, in that case, let me correct my statement:

The facilities of the C preprocessor are defined in such a way that
you are not guaranteed to be able to do this; if you were able to
get it to work at all, it would be due to implementation-dependant
behaviour.
--
"History is a pile of debris" -- Laurie Anderson
Nov 13 '07 #5
On Nov 12, 7:58 pm, Ark Khasin <akha...@macroexpressions.comwrote:
andreyvul wrote:
On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,
andreyvul <andrey....@gmail.comwrote:
What I'm trying to do is have the preprocessor parse one file twice.
You cannot do that using the facilities defined by the C preprocessor.
Oh, I meant _recursively_ preprocess the file twice.
That's why I was asking about proper #include/#ifdef structure, so
that it preprocesses like this:
#block 1
|->#block 2 (via recursive include)
|->#block 3 (via recursive include)
however, it doesn't get to |->#block 3

I didn't try it but something along these lines might do it:

#ifndef REC_COUNT
#define REC_COUNT 2
#elif REC_COUNT == 2
#undef REC_COUNT
#define REC_COUNT 1
#elif REC_COUNT == 1
#undef REC_COUNT
#define REC_COUNT 0
#endif
/* Here is the meat */
#if REC_COUNT == 2
/* first iteration */
#elif REC_COUNT == 1
/* second iteration */
#else
/* third and last iteration */
#if REC_COUNT != 0
#include __FILE__
#endif

--
Ark
Nope, doesn't work.

Great, I have now figured out it is impossible to recursively
preprocess more than one level. Is this supposed to happen per ANSI
specs, or should I go to the cpp newsgroup?

Nov 13 '07 #6
And I got it to work now:
cc foo.c -E | sed -re '/#[^di]/D' -e /^$/D' | head -7 | cc -x c - -o
foo
Kind of impossible on windows without GnuWin32, msys, or cygwin.

Nov 13 '07 #7
andreyvul wrote:
On Nov 12, 7:58 pm, Ark Khasin <akha...@macroexpressions.comwrote:
>andreyvul wrote:
>>On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,
andreyvul <andrey....@gmail.comwrote:
What I'm trying to do is have the preprocessor parse one file twice.
You cannot do that using the facilities defined by the C preprocessor.
Oh, I meant _recursively_ preprocess the file twice.
That's why I was asking about proper #include/#ifdef structure, so
that it preprocesses like this:
#block 1
|->#block 2 (via recursive include)
|->#block 3 (via recursive include)
however, it doesn't get to |->#block 3
I didn't try it but something along these lines might do it:

#ifndef REC_COUNT
#define REC_COUNT 2
#elif REC_COUNT == 2
#undef REC_COUNT
#define REC_COUNT 1
#elif REC_COUNT == 1
#undef REC_COUNT
#define REC_COUNT 0
#endif
/* Here is the meat */
#if REC_COUNT == 2
/* first iteration */
#elif REC_COUNT == 1
/* second iteration */
#else
/* third and last iteration */
#if REC_COUNT != 0
#include __FILE__
#endif

--
Ark

Nope, doesn't work.

Great, I have now figured out it is impossible to recursively
preprocess more than one level. Is this supposed to happen per ANSI
specs, or should I go to the cpp newsgroup?
You didn't try hard enough :). The text I posted was not #balanced.
Here's a working example:
------------- iter.c -------------
#include <stdio.h>
int main()
{
#include "iter.h"
return 0;
}
------------- iter.h -------------
#ifndef REC_COUNT
# define REC_COUNT 2
/* first iteration */
puts("first iteration");
#elif REC_COUNT == 2
# undef REC_COUNT
# define REC_COUNT 1
/* second iteration */
puts("second iteration");
#elif REC_COUNT == 1
# undef REC_COUNT
# define REC_COUNT 0
/* third and last iteration */
puts("third and last iteration");
#endif
#if REC_COUNT != 0
# include __FILE__
#endif
------------ output --------------------
first iteration
second iteration
third and last iteration

.... which also disproves a claim of a nearby post that it's impossible.
In fact, you can do recursion of any fixed depth this way.
Unless of course I misunderstood what you were trying to achieve.

--
Ark
Nov 13 '07 #8
On Nov 12, 9:54 pm, Ark Khasin <akha...@macroexpressions.comwrote:
andreyvul wrote:
On Nov 12, 7:58 pm, Ark Khasin <akha...@macroexpressions.comwrote:
andreyvul wrote:
On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,
andreyvul <andrey....@gmail.comwrote:
What I'm trying to do is have the preprocessor parse one file twice.
You cannot do that using the facilities defined by the C preprocessor.
Oh, I meant _recursively_ preprocess the file twice.
That's why I was asking about proper #include/#ifdef structure, so
that it preprocesses like this:
#block 1
|->#block 2 (via recursive include)
|->#block 3 (via recursive include)
however, it doesn't get to |->#block 3
I didn't try it but something along these lines might do it:
#ifndef REC_COUNT
#define REC_COUNT 2
#elif REC_COUNT == 2
#undef REC_COUNT
#define REC_COUNT 1
#elif REC_COUNT == 1
#undef REC_COUNT
#define REC_COUNT 0
#endif
/* Here is the meat */
#if REC_COUNT == 2
/* first iteration */
#elif REC_COUNT == 1
/* second iteration */
#else
/* third and last iteration */
#if REC_COUNT != 0
#include __FILE__
#endif
--
Ark
Nope, doesn't work.
Great, I have now figured out it is impossible to recursively
preprocess more than one level. Is this supposed to happen per ANSI
specs, or should I go to the cpp newsgroup?

You didn't try hard enough :). The text I posted was not #balanced.
Here's a working example:
------------- iter.c -------------
#include <stdio.h>
int main()
{
#include "iter.h"
return 0;}

------------- iter.h -------------
#ifndef REC_COUNT
# define REC_COUNT 2
/* first iteration */
puts("first iteration");
#elif REC_COUNT == 2
# undef REC_COUNT
# define REC_COUNT 1
/* second iteration */
puts("second iteration");
#elif REC_COUNT == 1
# undef REC_COUNT
# define REC_COUNT 0
/* third and last iteration */
puts("third and last iteration");
#endif
#if REC_COUNT != 0
# include __FILE__
#endif
------------ output --------------------
first iteration
second iteration
third and last iteration

... which also disproves a claim of a nearby post that it's impossible.
In fact, you can do recursion of any fixed depth this way.
Unless of course I misunderstood what you were trying to achieve.

--
Ark
What if you had a macro in the third iteration that was to be expanded
by the previous iterations?

Nov 13 '07 #9
On Nov 12, 9:54 pm, Ark Khasin <akha...@macroexpressions.comwrote:
andreyvul wrote:
On Nov 12, 7:58 pm, Ark Khasin <akha...@macroexpressions.comwrote:
andreyvul wrote:
On Nov 12, 7:11 pm, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson)
wrote:
In article <1194910305.752743.81...@k79g2000hse.googlegroups. com>,
andreyvul <andrey....@gmail.comwrote:
What I'm trying to do is have the preprocessor parse one file twice.
You cannot do that using the facilities defined by the C preprocessor.
Oh, I meant _recursively_ preprocess the file twice.
That's why I was asking about proper #include/#ifdef structure, so
that it preprocesses like this:
#block 1
|->#block 2 (via recursive include)
|->#block 3 (via recursive include)
however, it doesn't get to |->#block 3
I didn't try it but something along these lines might do it:
#ifndef REC_COUNT
#define REC_COUNT 2
#elif REC_COUNT == 2
#undef REC_COUNT
#define REC_COUNT 1
#elif REC_COUNT == 1
#undef REC_COUNT
#define REC_COUNT 0
#endif
/* Here is the meat */
#if REC_COUNT == 2
/* first iteration */
#elif REC_COUNT == 1
/* second iteration */
#else
/* third and last iteration */
#if REC_COUNT != 0
#include __FILE__
#endif
--
Ark
Nope, doesn't work.
Great, I have now figured out it is impossible to recursively
preprocess more than one level. Is this supposed to happen per ANSI
specs, or should I go to the cpp newsgroup?

You didn't try hard enough :). The text I posted was not #balanced.
Here's a working example:
------------- iter.c -------------
#include <stdio.h>
int main()
{
#include "iter.h"
return 0;}

------------- iter.h -------------
#ifndef REC_COUNT
# define REC_COUNT 2
/* first iteration */
puts("first iteration");
#elif REC_COUNT == 2
# undef REC_COUNT
# define REC_COUNT 1
/* second iteration */
puts("second iteration");
#elif REC_COUNT == 1
# undef REC_COUNT
# define REC_COUNT 0
/* third and last iteration */
puts("third and last iteration");
#endif
#if REC_COUNT != 0
# include __FILE__
#endif
------------ output --------------------
first iteration
second iteration
third and last iteration

... which also disproves a claim of a nearby post that it's impossible.
In fact, you can do recursion of any fixed depth this way.
Unless of course I misunderstood what you were trying to achieve.

--
Ark
What if you have a macro in the third iteration that needs expanding
in the second iteration, which needs expanding in the first iteration?
*That* was what I was trying to do.

Nov 13 '07 #10
Here's an example of what I mean:
#ifndef REC
#define REC 2
#define d #define
#define i include
#elif REC == 2
#undef REC
#define REC 1
i <stdio.h>
d p(a) puts(a)
d q(a) int a
d Q main
d r(a) char**a
#elif REC == 1
#undef REC
#define REC 0
q(Q)(q(c), r(v)){p("Hello, World!\n");return 0;}
#endif
#if REC != 0
#include __FILE__
#endif

Should produce:
[stdio.h]
int main(int c, char**v){puts("Hello, World!\n"); return 0;}

Nov 13 '07 #11
andreyvul wrote:
Here's an example of what I mean:
#ifndef REC
#define REC 2
#define d #define
#define i include
#elif REC == 2
#undef REC
#define REC 1
i <stdio.h>
d p(a) puts(a)
d q(a) int a
d Q main
d r(a) char**a
#elif REC == 1
#undef REC
#define REC 0
q(Q)(q(c), r(v)){p("Hello, World!\n");return 0;}
#endif
#if REC != 0
#include __FILE__
#endif

Should produce:
[stdio.h]
int main(int c, char**v){puts("Hello, World!\n"); return 0;}
THAT you should not even attempt to do. It's a tad late to find quotes
from the standard, but basically:
- # in a context of macro definition means STRINGIZE when applied to a
macro argument; I doubt other uses are meaningful or valid
- you cannot (re)define preprocessor directives
So it is not valid C.

This is what you are doing:
- You deliberately take a bad (i.e. invalid) C-like source,
- You massage it to automatically produce a valid C source and run with it.
If that's what you want, you can use an arbitrary pair of source
language style and a corresponding preprocessor utility; that has
nothing to do with C.

YOU CAN, however, process your file in every which way you like, as you
demonstrated in this thread. Attempting to coerce a C compiler to do
preprocessing is not a terribly good idea. I'd suggest to use a
standalone PP that gives you some guarantees of what it outputs. (Google
them C preprocessors.) Or use a specific compiler you know suits your needs.
Keep in mind that:
- the compiler is under no obligation to produce preprocessor output.
- if the compiler does produce PP output, it may turn bad source into a
perfectly good source; I used to have a vivid example of that around
#define SLASH /
something /SLASH alleged comment
but I lost it. Basically, PP found a token /, then a token SLASH which
it expanded to / and output //. It compiles as start of comment (a
single token //) but in the original source they were, effectively, two
/ tokens. One might argue that PP should have produced / / but then
again, the compiler owes me nothing in that department.

If my hunch is correct and all you are trying to do is to obfuscate your
code, there are better ways of doing so.

--
Ark

Nov 13 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: SimonC | last post by:
I'm looking to do something similar to a feature found on Ticketmaster.com, where you select your seats at a venue, and then you have two minutes in which to take or leave them. QUESTION 1a....
8
by: John Grenier | last post by:
Hi, I have to determine the "standing" (WIN - TIE - LOSS) from confrontations between two teams on a contest. The table matchResults has fields cont_id, team_id and contest_result (int). ...
6
by: Willem | last post by:
Hi, I have a newbie question: is it possible to make a search form in asp that searches in two different databases (access)? Willem
6
by: Matt K. | last post by:
Hi there, I have a form in an Access project that contains a subform which displays the results of a query of the style "select * from where = #a certain date#". In the main part of the form...
7
by: Prabhudhas Peter | last post by:
I have two object instances of a same class... and i assigned values in both object instances (or the values can be taken from databse and assigned to the members of the objects)... Now i want to...
0
by: clintonG | last post by:
I applied aspnet_regsql to SQL2K which was working fine throughout Beta 2 development. After installing Visual Studio and SQL Express RTM my application has blown up. Logging in to the application...
9
by: Steven | last post by:
Hello, I have a question about strcmp(). I have four words, who need to be compared if it were two strings. I tried adding the comparison values like '(strcmp(w1, w2) + strcmp(w3, w4))', where...
272
by: Peter Olcott | last post by:
http://groups.google.com/group/comp.lang.c++/msg/a9092f0f6c9bf13a I think that the operator() member function does not work correctly, does anyone else know how to make a template for making two...
13
by: paul.joseph.davis | last post by:
Hi, I've just had my first encounter with two-phase lookup and I'm scratching my head a bit. The idea behind two phase look up is pretty easy to understand, but I have a case that fails to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.