将C预处理器用于C以外的语言

时间:2022-08-24 15:54:12

The Wikipedia entry for the C Preprocessor states:

C预处理器的*条目指出:

The language of preprocessor directives is agnostic to the grammar of C, so the C preprocessor can also be used independently to process other types of files.

预处理程序指令的语言与C的语法无关,因此C预处理程序也可以独立用于处理其他类型的文件。

How can this be done? Any examples or techniques?

如何才能做到这一点?任何例子或技巧?

EDIT: Yes, I'm mostly interested in macro processing. Even though it's probably not advisable or maintainable it would still be useful to know what's possible.

编辑:是的,我最感兴趣的是宏观处理。即使它可能不可取或不可维护,但知道什么是可能的仍然是有用的。

12 个解决方案

#1


You can call CPP directly:

您可以直接致电CPP:

cpp <file>

Rather than calling it through gcc:

而不是通过gcc调用它:

gcc -E filename

Do note however that, as mentioned in the same Wikipedia article, C preprocessor's language is not really equipped for general-purpose use:

请注意,正如同一篇*文章中所提到的,C预处理器的语言并不是真正适用于通用目的:

However, since the C preprocessor does not have features of some other preprocessors, such as recursive macros, selective expansion according to quoting, string evaluation in conditionals, and Turing completeness, it is very limited in comparison to a more general macro processor such as m4.

但是,由于C预处理器不具备某些其他预处理器的功能,例如递归宏,根据引用的选择性扩展,条件中的字符串评估以及图灵完整性,与更通用的宏处理器(如m4)相比,它非常有限。

Have you considered dabbling with a more flexible macro processing language, like the aforementioned m4 for instance?

您是否考虑过使用更灵活的宏处理语言,例如前面提到的m4?

#2


For example, Assembler. While many assemblers have their own way to #include headers and #define macros, it can be useful to use the C preprocessor for this. GNU make, for example, has implicit rules for turning *.S files into *.s files by running the preprocessor ('cpp'), before feeding the *.s file to the GNU assembler ('as').

例如,汇编程序。虽然许多汇编器都有自己的#include头和#define宏的方法,但为此使用C预处理器会很有用。例如,GNU make具有隐式规则,用于在将* .s文件提供给GNU汇编器('as')之前,通过运行预处理器('cpp')将* .S文件转换为* .s文件。

#3


Yes, it can be done by parsing your own language through the gcc preprocessor (e.g. 'gcc -E').

是的,可以通过gcc预处理器(例如'gcc -E')解析自己的语言来完成。

We have done this on my job with our our, specific language. It has quite some advantages:

我们用我们特定的语言完成了这项工作。它有一些优点:

  • You can use C's include statements (#include) which is very powerful
  • 您可以使用C的include语句(#include),它非常强大

  • You can use your #ifdef constructions
  • 您可以使用#ifdef结构

  • You can define Constants (#define MAGIC_NUMBER 42) or macro functions (#define min(x,y) ( (x( < (y) ? (x) : (y))
  • 您可以定义常量(#define MAGIC_NUMBER 42)或宏函数(#define min(x,y)((x(<(y)?(x):( y))

... and the other things in the c processor.

...以及c处理器中的其他内容。

HOWEVER, you also inherit the unsafe C constructions, and having a preprocessor not integrated with your main language is the cause of it. Think about the minimum macro and doing something like :

但是,您还继承了不安全的C结构,并且没有与主语言集成的预处理器是它的原因。想想最小的宏并做一些像:

a = 2;
b = 3;

c = min(a--, b--);

Just think what value a and b will have after the min function?

想想min函数后a和b的值是多少?

Same is true about the non-typed constants that you introduce

关于您引入的非类型常量也是如此

See the Safer C book for details.

有关详细信息,请参阅Safer C书。

#4


Many C compilers have a flag that tells them to only preprocess. With gcc it's the -E flag. eg:

许多C编译器都有一个标志,告诉他们只进行预处理。使用gcc,它是-E标志。例如:

$ gcc -E -                 
#define FOO foo
bar FOO baz

will output:

# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "<stdin>"

bar foo baz

With other C compilers you'll have to check the manuals to see how to swithc to preprocess-only mode.

对于其他C编译器,您必须查看手册以了解如何切换到仅预处理模式。

#5


Usually you can invoke the C compiler with an option to preprocess only (and ignore any #line statements). Take this as a simple example:

通常,您可以使用仅预处理的选项调用C编译器(并忽略任何#line语句)。以此为例,简单说明:

<?php
function foo()
{
#ifdef DEBUG
    echo "Some debug info.";
#endif
    echo "Foo!";
}

foo();

We define a PHP source file with preprocess statements. We can then preprocess it (gcc can do this, too):

我们使用预处理语句定义PHP源文件。然后我们可以预处理它(gcc也可以这样做):

cl -nologo -EP foo.php > foo2.php

Since DEBUG is not the defined the first echo is stripped. Plus here is that lines beginning with # are comments in PHP so you don't have to preprocess them for a "debug" build.

由于DEBUG未定义,因此第一个回声被剥离。另外,以#开头的行是PHP中的注释,因此您不必为“调试”构建预处理它们。

Edit: Since you asked about macros. This works fine too and could be used to generate boilerplate code etc.

编辑:因为你问过宏。这也很好用,可以用来生成样板代码等。

#6


Using Microsoft's compiler, I think (I just looked it up, haven't tested it) that it's the /P compiler option.

使用微软的编译器,我认为(我只是查了一下,还没有测试过它)它是/ P编译器选项。

Other compilers presumably have similar options (or, for some compilers the preprocessor might actually be a different executable, which is usually run implicitly by the compiler but which you can also run explicitly separately).

其他编译器可能有类似的选项(或者,对于某些编译器,预处理器实际上可能是不同的可执行文件,它通常由编译器隐式运行,但您也可以单独显式运行)。

#7


Assuming you're using GCC, You can take any plain old text file, regardless of its contents, and run:

假设您正在使用GCC,您可以使用任何普通的旧文本文件,无论其内容如何,​​并运行:

gcc -E filename

Any preprocessor directives in the file will be processed by the preprocessor and GCC will then exit.

预处理器将处理文件中的任何预处理程序指令,然后GCC将退出。

The point is that it doesn't matter what the actual content of the text file is, since all the preprocessor cares about is its own directives.

关键是文本文件的实际内容并不重要,因为所有预处理器都关心的是它自己的指令。

#8


I have heard of people using the C pre-processor on Ada code. Ada has no preprocessor, so you have to do something like that if you want to preprocess your code.

我听说有人在Ada代码上使用C预处理器。 Ada没有预处理器,所以如果你想预处理代码,你必须做类似的事情。

However, it was a concious design decision not to give it one, so doing this is very un-Ada. I wouldn't suggest anyone do this.

然而,这是一个有意识的设计决定,不给它一个,所以做这个非常非Ada。我不建议任何人这样做。

#9


A while ago I did some work on a project that used imake for makefile generation. As I recall, it was basically the c preprocessor syntax to generate the make files.

前段时间我在一个使用imake生成makefile的项目上做了一些工作。我记得,它基本上是生成make文件的c预处理器语法。

#10


The C preprocessor can also be invoked by the Glasgow Haskell Compiler (GHC) prior to compiling Haskell code, by passing the -cpp flag.

在编译Haskell代码之前,通过传递-cpp标志,Glasgow Haskell编译器(GHC)也可以调用C预处理器。

#11


You could implement the C preprocessor in the compiler for another language.

您可以在编译器中为另一种语言实现C预处理器。

You could use it to preprocess any sort of text file, but there's much better things for that purpose.

您可以使用它来预处理任何类型的文本文件,但为此目的有更好的事情。

#12


Basically what it's saying is that preprocessors have nothing to do with C syntax. They are basically simple parsers that follow a set of rules. So you could use preprocessors kind of like you'd use sed or awk for some silly tasks. Don't ask me why you'd ever want to do it though.

基本上它说的是预处理器与C语法无关。它们基本上是遵循一组规则的简单解析器。因此,您可以使用预处理器,就像您使用sed或awk进行一些愚蠢的任务一样。不要问我为什么你想要这样做。

For example, on a text file:

例如,在文本文件上:

#define pi 3.141

pi is not an irrational number.

Then you run the preprocessor & you'd get.

然后你运行预处理器,你会得到。

3.141 is not an irrational number.

3.141不是一个无理数。

#1


You can call CPP directly:

您可以直接致电CPP:

cpp <file>

Rather than calling it through gcc:

而不是通过gcc调用它:

gcc -E filename

Do note however that, as mentioned in the same Wikipedia article, C preprocessor's language is not really equipped for general-purpose use:

请注意,正如同一篇*文章中所提到的,C预处理器的语言并不是真正适用于通用目的:

However, since the C preprocessor does not have features of some other preprocessors, such as recursive macros, selective expansion according to quoting, string evaluation in conditionals, and Turing completeness, it is very limited in comparison to a more general macro processor such as m4.

但是,由于C预处理器不具备某些其他预处理器的功能,例如递归宏,根据引用的选择性扩展,条件中的字符串评估以及图灵完整性,与更通用的宏处理器(如m4)相比,它非常有限。

Have you considered dabbling with a more flexible macro processing language, like the aforementioned m4 for instance?

您是否考虑过使用更灵活的宏处理语言,例如前面提到的m4?

#2


For example, Assembler. While many assemblers have their own way to #include headers and #define macros, it can be useful to use the C preprocessor for this. GNU make, for example, has implicit rules for turning *.S files into *.s files by running the preprocessor ('cpp'), before feeding the *.s file to the GNU assembler ('as').

例如,汇编程序。虽然许多汇编器都有自己的#include头和#define宏的方法,但为此使用C预处理器会很有用。例如,GNU make具有隐式规则,用于在将* .s文件提供给GNU汇编器('as')之前,通过运行预处理器('cpp')将* .S文件转换为* .s文件。

#3


Yes, it can be done by parsing your own language through the gcc preprocessor (e.g. 'gcc -E').

是的,可以通过gcc预处理器(例如'gcc -E')解析自己的语言来完成。

We have done this on my job with our our, specific language. It has quite some advantages:

我们用我们特定的语言完成了这项工作。它有一些优点:

  • You can use C's include statements (#include) which is very powerful
  • 您可以使用C的include语句(#include),它非常强大

  • You can use your #ifdef constructions
  • 您可以使用#ifdef结构

  • You can define Constants (#define MAGIC_NUMBER 42) or macro functions (#define min(x,y) ( (x( < (y) ? (x) : (y))
  • 您可以定义常量(#define MAGIC_NUMBER 42)或宏函数(#define min(x,y)((x(<(y)?(x):( y))

... and the other things in the c processor.

...以及c处理器中的其他内容。

HOWEVER, you also inherit the unsafe C constructions, and having a preprocessor not integrated with your main language is the cause of it. Think about the minimum macro and doing something like :

但是,您还继承了不安全的C结构,并且没有与主语言集成的预处理器是它的原因。想想最小的宏并做一些像:

a = 2;
b = 3;

c = min(a--, b--);

Just think what value a and b will have after the min function?

想想min函数后a和b的值是多少?

Same is true about the non-typed constants that you introduce

关于您引入的非类型常量也是如此

See the Safer C book for details.

有关详细信息,请参阅Safer C书。

#4


Many C compilers have a flag that tells them to only preprocess. With gcc it's the -E flag. eg:

许多C编译器都有一个标志,告诉他们只进行预处理。使用gcc,它是-E标志。例如:

$ gcc -E -                 
#define FOO foo
bar FOO baz

will output:

# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "<stdin>"

bar foo baz

With other C compilers you'll have to check the manuals to see how to swithc to preprocess-only mode.

对于其他C编译器,您必须查看手册以了解如何切换到仅预处理模式。

#5


Usually you can invoke the C compiler with an option to preprocess only (and ignore any #line statements). Take this as a simple example:

通常,您可以使用仅预处理的选项调用C编译器(并忽略任何#line语句)。以此为例,简单说明:

<?php
function foo()
{
#ifdef DEBUG
    echo "Some debug info.";
#endif
    echo "Foo!";
}

foo();

We define a PHP source file with preprocess statements. We can then preprocess it (gcc can do this, too):

我们使用预处理语句定义PHP源文件。然后我们可以预处理它(gcc也可以这样做):

cl -nologo -EP foo.php > foo2.php

Since DEBUG is not the defined the first echo is stripped. Plus here is that lines beginning with # are comments in PHP so you don't have to preprocess them for a "debug" build.

由于DEBUG未定义,因此第一个回声被剥离。另外,以#开头的行是PHP中的注释,因此您不必为“调试”构建预处理它们。

Edit: Since you asked about macros. This works fine too and could be used to generate boilerplate code etc.

编辑:因为你问过宏。这也很好用,可以用来生成样板代码等。

#6


Using Microsoft's compiler, I think (I just looked it up, haven't tested it) that it's the /P compiler option.

使用微软的编译器,我认为(我只是查了一下,还没有测试过它)它是/ P编译器选项。

Other compilers presumably have similar options (or, for some compilers the preprocessor might actually be a different executable, which is usually run implicitly by the compiler but which you can also run explicitly separately).

其他编译器可能有类似的选项(或者,对于某些编译器,预处理器实际上可能是不同的可执行文件,它通常由编译器隐式运行,但您也可以单独显式运行)。

#7


Assuming you're using GCC, You can take any plain old text file, regardless of its contents, and run:

假设您正在使用GCC,您可以使用任何普通的旧文本文件,无论其内容如何,​​并运行:

gcc -E filename

Any preprocessor directives in the file will be processed by the preprocessor and GCC will then exit.

预处理器将处理文件中的任何预处理程序指令,然后GCC将退出。

The point is that it doesn't matter what the actual content of the text file is, since all the preprocessor cares about is its own directives.

关键是文本文件的实际内容并不重要,因为所有预处理器都关心的是它自己的指令。

#8


I have heard of people using the C pre-processor on Ada code. Ada has no preprocessor, so you have to do something like that if you want to preprocess your code.

我听说有人在Ada代码上使用C预处理器。 Ada没有预处理器,所以如果你想预处理代码,你必须做类似的事情。

However, it was a concious design decision not to give it one, so doing this is very un-Ada. I wouldn't suggest anyone do this.

然而,这是一个有意识的设计决定,不给它一个,所以做这个非常非Ada。我不建议任何人这样做。

#9


A while ago I did some work on a project that used imake for makefile generation. As I recall, it was basically the c preprocessor syntax to generate the make files.

前段时间我在一个使用imake生成makefile的项目上做了一些工作。我记得,它基本上是生成make文件的c预处理器语法。

#10


The C preprocessor can also be invoked by the Glasgow Haskell Compiler (GHC) prior to compiling Haskell code, by passing the -cpp flag.

在编译Haskell代码之前,通过传递-cpp标志,Glasgow Haskell编译器(GHC)也可以调用C预处理器。

#11


You could implement the C preprocessor in the compiler for another language.

您可以在编译器中为另一种语言实现C预处理器。

You could use it to preprocess any sort of text file, but there's much better things for that purpose.

您可以使用它来预处理任何类型的文本文件,但为此目的有更好的事情。

#12


Basically what it's saying is that preprocessors have nothing to do with C syntax. They are basically simple parsers that follow a set of rules. So you could use preprocessors kind of like you'd use sed or awk for some silly tasks. Don't ask me why you'd ever want to do it though.

基本上它说的是预处理器与C语法无关。它们基本上是遵循一组规则的简单解析器。因此,您可以使用预处理器,就像您使用sed或awk进行一些愚蠢的任务一样。不要问我为什么你想要这样做。

For example, on a text file:

例如,在文本文件上:

#define pi 3.141

pi is not an irrational number.

Then you run the preprocessor & you'd get.

然后你运行预处理器,你会得到。

3.141 is not an irrational number.

3.141不是一个无理数。