#105270 - sgeos - Sat Oct 07, 2006 5:27 am
Input:
Code: |
#include "macro.h"
#define PATH ../
#define FILE dummy.file
MACRO_LINK(PATH,FILE) |
Desired output:
Unacceptable output:
macro.h
Code: |
#ifndef MACRO_H
#define MACRO_H
#define MACRO_FORWARD(MACRO_string) MACRO_string
#define MACRO_SQUOTE(MACRO_string) #MACRO_string
#define MACRO_QUOTE(MACRO_string) MACRO_SQUOTE(MACRO_string)
#define MACRO_LINK(MACRO_path,MACRO_link) MACRO_QUOTE(MACRO_FORWARD(MACRO_path)MACRO_FORWARD(MACRO_link))
#endif // MACRO_H |
This works. Is it portable?
-Brendan
#105272 - poslundc - Sat Oct 07, 2006 5:34 am
sgeos wrote: |
This works. Is it portable? |
Better question: are you insane? O_o
Dan.
#105286 - sgeos - Sat Oct 07, 2006 10:56 am
poslundc wrote: |
Better question: are you insane? O_o |
The problem domain is atypical. The C preprocessor's stringize and token paste features necessarily require dummy macros to use. This makes them confusing to work with.
Is there a better way to meet the above specification using the C preprocessor? I'd really like to know. The interface is MACRO_LINK(A,B).
MACRO_LINK(a,b) gives me
"ab"
MACRO_FORWARD(a)MACRO_FORWARD(b) gives
a b
note the space. The space can be removed using token paste instead.
I'm not fond of this solution, but it works. Here and now at least.
-Brendan
#105309 - gmiller - Sat Oct 07, 2006 4:22 pm
The features you are using are part of the standard and should be portable. There are a number of things that work in C that are understandable but not always obvious.
two quoted strings one after the other will be concatenated by the compiler to a singe quoted string in the preprocessor. I use this:
#define VERSION_NUMBER_STRING "1.0.4.2"
char version[] = "program name "VERSION_NUMBER_STRING
Using the macro expansion stuff I have debug that is:
#define printDebug(a) cout <<#a" = "<<a
The extra space is not something I have seen but I generally have not used it in the fashion you are. I have a number of different compilers so I will check to see how they react.
#105319 - poslundc - Sat Oct 07, 2006 6:02 pm
sgeos wrote: |
The problem domain is atypical. The C preprocessor's stringize and token paste features necessarily require dummy macros to use. This makes them confusing to work with.
Is there a better way to meet the above specification using the C preprocessor? I'd really like to know. The interface is MACRO_LINK(A,B).
MACRO_LINK(a,b) gives me
"ab"
MACRO_FORWARD(a)MACRO_FORWARD(b) gives
a b
note the space. The space can be removed using token paste instead.
I'm not fond of this solution, but it works. Here and now at least. |
I don't know that I could easily create an alternative solution... I've used some of the fancier macro token features before but never anything that convoluted.
Could what you're ultimately trying to accomplish perhaps be better achieved through configuration through makefile options?
Dan.
#105357 - sgeos - Sun Oct 08, 2006 3:01 am
gmiller wrote: |
two quoted strings one after the other will be concatenated by the compiler to a singe quoted string in the preprocessor. |
The output from the preprocessor never gets to meet the compiler. It gets to meet web browsers, printers and yet more conversion tools instead.
gmiller wrote: |
The features you are using are part of the standard and should be portable. |
Excellent. So long as extra spaces don't pop up, I'm happy.
gmiller wrote: |
The extra space is not something I have seen but I generally have not used it in the fashion you are. I have a number of different compilers so I will check to see how they react. |
That would be fantastic.
poslundc wrote: |
Could what you're ultimately trying to accomplish perhaps be better achieved through configuration through makefile options? |
I doubt it. If I'm going to bother externalizing anything, if possible, I'd rather put that information a spreadsheet that in the makefile. Some information is already being supplied by the makefile.
I'm converting template XHTML pages to real XHTML pages. In this case, one of the templates is used to generate many (regularly formatted) pages. This could probably be better accomplished with a different tool. I don't know what that tool is- nor do I have time to learn how to use it right now. This solution does work, afterall. Next project... =) If anyone knows, I'd still love to know what the tool for the job is. Maybe PHP? Right now I'm using C, the C preprocessor, make and perl.
This is basically what I'm doing:
Code: |
// macro.h - macro library
#define MACRO_FORWARD(MACRO_string) MACRO_string
#define MACRO_SQUOTE(MACRO_string) #MACRO_string
#define MACRO_QUOTE(MACRO_string) MACRO_SQUOTE(MACRO_string)
#define MACRO_SCAT(MACRO_a,MACRO_b) MACRO_a##MACRO_b
#define MACRO_CAT(MACRO_a,MACRO_b) MACRO_SCAT(MACRO_a,MACRO_b)
#define MACRO_LINK5(a,b,c,d,e) \
MACRO_QUOTE(MACRO_FORWARD(a)MACRO_FORWARD(b)MACRO_FORWARD(c)MACRO_FORWARD(d)MACRO_FORWARD(e))
// def.h - strings autogenerated from a spreadsheet (English Build)
#define TXT_TITLE Bunch O'Links |
Code: |
<h1>TXT_TITLE</h1>
<ul>
<li><a href=MACRO_LINK5(../../../folder/subfolder/,TXT_BASE,suffix/prefix,TXT_CARDBASE,00.file)>MACRO_CAT(TXT_BASE,00)</a></li>
<li><a href=MACRO_LINK5(../../../folder/subfolder/,TXT_BASE,suffix/prefix,TXT_CARDBASE,01.file)>MACRO_CAT(TXT_BASE,01)</a></li>
<li><a href=MACRO_LINK5(../../../folder/subfolder/,TXT_BASE,suffix/prefix,TXT_CARDBASE,02.file)>MACRO_CAT(TXT_BASE,02)</a></li>
...
<li><a href=MACRO_LINK5(../../../folder/subfolder/,TXT_BASE,suffix/prefix,TXT_CARDBASE,09.file)>MACRO_CAT(TXT_BASE,09)</a></li>
</ul>
...
<ul>
<li><a href=MACRO_LINK5(../../../folder/subfolder/,TXT_BASE,suffix/prefix,TXT_CARDBASE,90.file)>MACRO_CAT(TXT_BASE,90)</a></li>
...
<li><a href=MACRO_LINK5(../../../folder/subfolder/,TXT_BASE,suffix/prefix,TXT_CARDBASE,99.file)>MACRO_CAT(TXT_BASE,99)</a></li>
</ul> |
And the output is:
gcc -E -x c -P -C -DTXT_BASE=00 template.html > output/00suffix.html
Code: |
<h1>Bunch O'Links</h1>
<ul>
<li><a href="../../../folder/subfolder/00suffix/prefix0000.file">0000</a></li>
<li><a href="../../../folder/subfolder/00suffix/prefix0001.file">0001</a></li>
<li><a href="../../../folder/subfolder/00suffix/prefix0002.file">0002</a></li>
... |
gcc -E -x c -P -C -DTXT_BASE=27 template.html > output/27suffix.html
Code: |
<h1>Bunch O'Links</h1>
<ul>
<li><a href="../../../folder/subfolder/27suffix/prefix2700.file">2700</a></li>
... |
-Brendan
#105371 - poslundc - Sun Oct 08, 2006 6:44 am
I would definitely consider using a scripting language in the future rather than shoehorning the preprocessor into doing this kind of thing for you. If I understand it correctly (which I'm far from certain of) all you're looking to do is automate a search-and-replace on certain dictionary tokens in the file, with multiple sets of values you want to instantiate in.
I used to do most of my utilitarian scripting in PHP, which I like because of its huge libraries, easy documentation, and that it runs in a web browser (making interface elements easy to add via forms).
Lately I've switched more to using Python, which doesn't have as many libraries as PHP and isn't innately a web-oriented scripting language, but is far, far more elegant and makes it easier for me to both read my own code and reuse it down the road (part of the reason I'm not fond of PERL).
Both languages have incredibly poweful set-types, PHP with its associative arrays, and Python with its lists and dictionaries. And they both have really convenient string-manipulation functions. Once you start working with those kinds of things you'll wonder how you ever got by without them. Doing something like what you describe above, iterating over multiple sets of data, instantiating them into the template, and writing the results out to separate files, would be a cinch in either one using those tools.
Dan.
#107803 - gmiller - Thu Nov 02, 2006 4:36 am
I checked the VS 2005/2003 compiler and the Sun compiler and saw no issues in the basic testing. Of course the GCC compilers seemed to be happy as well on a number of platforms. I also tried some older obsolete version and got some strange results (tubo C++, for example) that seemed to work but not all of the results were exact. I was just using the posted examples so it was not a very extensive test.
#107821 - sgeos - Thu Nov 02, 2006 10:45 am
Thanks for doing the tests.
This approach appears to be "basically" portable. If I ever end up using a strange compiler that breaks things, I'll figure out a workaround then.
-Brendan
#107838 - Dwedit - Thu Nov 02, 2006 2:32 pm
I thought most compilers would combine strings, so "../" "foo" would be identical to "../foo".
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#107858 - tepples - Thu Nov 02, 2006 5:14 pm
Dwedit wrote: |
I thought most compilers would combine strings, so "../" "foo" would be identical to "../foo". |
Right, but then it's the C compiler combining the strings, not the preprocessor.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.