8

I'm using a proprietary development environment that compiles code written in C, as well as the IEC 61131 languages. For the C compilation, it uses GCC 4.1.2 with these build options:

-fPIC -O0 -g -nostartfiles -Wall -trigraphs -fno-asm

The compilation is done by a program running on windows utilizing Cygwin.

My issue is, IEC language preprocessor is not that useful (doesn't support #define at all) and I want to use macros! I don't see why the GCC preprocessor would really care what language it is processing (my target language is Structured Text), so I'm looking to see if anyone might know a way to get it to process files of different file types that then are not compiled further (I'm just looking for macro expansion before the file is run through the IEC compiler). I'm very ignorant of compiler options and environments since I've never had to deal with them, I just write C code and it magically compiles and transfers to my target system to run.

The only things I can really do are add build options and execute a batch file before anything is executed. I think my best hope lies in using a batch file to process all files of a certain extension, but I don't even know what executable in the gnuinst folder to use, let alone what flags to use to run through the files.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
CapinWinky
  • 748
  • 7
  • 8
  • 1
    possible duplicate of [GCC preprocessor](http://stackoverflow.com/questions/3917316/gcc-preprocessor) - talks about C but that's mostly irrelevant. Just use the `-E` flag on whatever source text you want. – Mat Aug 27 '13 at 18:40
  • 1
    I've tried `gcc -E TestIn.txt -o TestOut.txt` and got the message: linker input file unused because linking not done. The contents of TestIn.txt is: `#define ADDTHEM(x,y) ((x)+(y)) Test= ADDTHEM(2,3);`. I'm trying to get an output file that contains: `Test= ((2)+(3));` – CapinWinky Aug 27 '13 at 18:49
  • GCC has funny heuristics to determine what sort of file you're feeding it based on extension, and apparently `.txt` are linker directives... Just tell it it's C: `gcc -xc -E TestIn.txt`. – Mat Aug 27 '13 at 18:52
  • Well, that gives `_spawnvp: no such file or directory`, but I gather that is because I'm doing this from a Windows command prompt and the compiler isn't in my PATH. – CapinWinky Aug 27 '13 at 19:01
  • @Mat: Or `gcc -E - < TestOut.txt` – Keith Thompson Aug 27 '13 at 19:01

1 Answers1

9

Just about any C preprocessor, including gcc's cpp, is going to assume that its input is valid C code. It has to tokenize the input following C (or C++, or Objective-C) rules, because it had to resolve its input into tokens (more precisely preprocessing tokens). Constructs above the token level shouldn't be an issue.

You certainly can use cpp or gcc -E to preprocess text that isn't C source code, but some input constructs will cause problems.

Taking an example from the comments:

$ cat foo.txt
#define ADDTHEM(x, y) ((x) + (y))
ADDTHEM(2, 3)
$ gcc -E - < foo.txt
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"

((2) + (3))

Note that I had to use gcc -E - < foo.txt rather than gcc -E foo.txt, because gcc treats a .txt file as a linker input file by default.

But if you add some content to foo.txt that doesn't consist of valid C preprocessor tokens, you can have problems:

$ cat foo.txt 
#define ADDTHEM(x, y) ((x) + (y))
ADDTHEM(2, 3)
ADDTHEM('c, "s)
$ gcc -E - < foo.txt
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"

((2) + (3))
<stdin>:3:9: warning: missing terminating ' character [enabled by default]
<stdin>:3:0: error: unterminated argument list invoking macro "ADDTHEM"
ADDTHEM

(Attempts to feed Ada source code to a C preprocessor have run into this kind of problem, since Ada uses isolated apostrophe ' characters for its attribute syntax.)

So you can do it if the input language doesn't use things that aren't valid C preprocessor tokens.

See the N1570 draft of the C standard, section 6.4, for more information about preprocessing tokens.

I actually wrote the above before I checked the GNU cpp manual, which says:

The C preprocessor is intended to be used only with C, C++, and Objective-C source code. In the past, it has been abused as a general text processor. It will choke on input which does not obey C's lexical rules. For example, apostrophes will be interpreted as the beginning of character constants, and cause errors. Also, you cannot rely on it preserving characteristics of the input which are not significant to C-family languages. If a Makefile is preprocessed, all the hard tabs will be removed, and the Makefile will not work.

Having said that, you can often get away with using cpp on things which are not C. Other Algol-ish programming languages are often safe (Pascal, Ada, etc.) So is assembly, with caution. `-traditional-cpp' mode preserves more white space, and is otherwise more permissive. Many of the problems can be avoided by writing C or C++ style comments instead of native language comments, and keeping macros simple.

Wherever possible, you should use a preprocessor geared to the language you are writing in. Modern versions of the GNU assembler have macro facilities. Most high level programming languages have their own conditional compilation and inclusion mechanism. If all else fails, try a true general text processor, such as GNU M4.

(The authors of that manual apparently missed the problem with Ada's attribute syntax.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • What would you recommend as an alternative to cpp? I could use PHP, but it seems overkill. – Janus Troelsen Feb 28 '15 at 14:04
  • 1
    is there a option to have the preprocessor NOT add those lines in the beginning starting with `#`? – Benny Jobigan Jul 26 '19 at 14:51
  • @BennyJobigan: I don't believe so. It's easy enough to filter them out yourself. – Keith Thompson Jul 26 '19 at 19:32
  • 3
    @KeithThompson actually I found out about a flag to do it. `-P Inhibit generation of linemarkers in the output from the preprocessor. This might be useful when running the preprocessor on something that is not C code, and will be sent to a program which might be confused by the linemarkers.` – Benny Jobigan Jul 28 '19 at 21:06
  • 1
    Instead of passing the input file through stdin, you should be able to use the `-xc` flag. This way, `__FILE__` macros will work. It seems to work great with Lua using gcc and tcc. – ABabin Dec 22 '22 at 06:01