I have inherited some PCL (Patran Command Language) code that is preprocessed with a C preprocessor to enable use of macros etc. This code has a number of features that do not work for modern preprocessors such as cpp. Currently I'm using gcc -E
or cpp
with version 11.3.0.
For example, one issue is caused by `//' being the concatenate operator in PCL, but being recognised as a comment by cpp:
$ A.pcc
#define FUNC(X) ui_write(X)
string variable
FUNC("text "//variable//" more text")
The required result is
string variable
ui_write("text "//variable//" more text")
I can preprocess this successfully with the command
cpp -traditional A.pcc
where -traditional
says to use old style cpp which doesn't tokenize, so the comment symbol is not an issue. If not using this flag, the preprocessor fails to match the argument X
within FUNC(X)
and errors as it ends the token search at the comment.
In the same file (and many others) token concatenation / token pasting is also being used:
$ B.pcc
#define CAT(I,J) command ## I ## J ## s()
CAT(1,2)
The required result is
command12s()
However by using the -traditional
flag, token concatenation is turned off, so the result is
command ## 1 ## 2 ## s()
Which isn't valid PCL.
Any suggestions for appropriate flags? These two issues occur in the same files so I am unable to compile different files with different flags. My current best idea is to use sed to replace the comments with other characters, preprocess, then put them back in.
Edit: I've found a cpp only solution via this answer (multipass a source code to cpp), so the line for me would be
cpp -traditional file.pcc | cpp -C
where the -C
flag says to keep comments. I'll have to add a macro to each file so the token concatenation doesn't occur in the first pass
#define DEF_CAT #define CAT(I,J) command ## I ## J ## ()
DEF_CAT
Preprocess the //
to something cpp
ignores, and then preprocess it back. The following /tmp/mycpp
:
#!/bin/bash
uuid=06ae45e2-dd08-40db-abeb-1089e89e638f
sed "s@//@$uuid@g" "$@" | cpp -P -xc - | sed "s@$uuid@//@g"
The following shell transcript presents execution:
$ in='
#define FUNC(X) ui_write(X)
string variable
FUNC("text "//variable//" more text")
#define CAT(I,J) command ## I ## J()
CAT(1,2)
'
$ /tmp/mycpp <<<"$in"
string variable
ui_write("text "//variable//" more text")
command12()