简体   繁体   English

重置C / C ++预处理器#line物理文件/行

[英]Reset the C/C++ preprocessor #line the physical file/line

I have a code generator that's going to take some user-written code and embed chunks of it in a larger generated file. 我有一个代码生成器,它将采用一些用户编写的代码并将其中的块嵌入更大的生成文件中。 I want the underlying compiler to provide good diagnostics when there are defects in the user's code, but I also don't want defects in the generated code to be misattributed to the source when they shouldn't be. 我希望底层编译器在用户代码中存在缺陷时提供良好的诊断,但我也不希望生成的代码中的缺陷在它们不应该被错误地分配给源时。

I intend to emit #line lineNum "sourceFile" directives at the beginning of each chunk of user-written code. 我打算在每个用户编写的代码块的开头发出#line lineNum "sourceFile"指令。 However, I can't find any documentation of the #line directive that mentions a technique for 'resetting' __LINE__ and __FILE__ back to the actual line in the generated file once I leave the user-provided code. 但是,在找到用户提供的代码后,我找不到#line指令的任何文档,它提到了一种“重置” __LINE____FILE__回到生成文件中的实际行。 The ideal solution would be analogous to the C# preprocessor's #line default directive. 理想的解决方案类似于C#预处理器的#line default指令。

Do I just need to keep track of how many lines I've written and manually reset that myself? 我只需要跟踪我写的行数并亲自手动重置吗? Or is there a better way, some sort of reset directive or sentinel value I can pass to #line to erase the association with the user's code? 或者有更好的方法,我可以传递给#line以删除与用户代码的关联的某种重置指令或标记值?

It looks like this may have been posed before , though there's no solid answer there. 看起来这可能是以前提出的 ,尽管那里没有可靠的答案。 To distinguish this from that, I'll additionally ask whether the lack of answer there has changed with C++11. 为了区别于此,我还要问一下C ++ 11中是否缺少答案。

A technique I've used before is to have my code generator output a # by itself on a line when it wants to reset the line directives, and then use a simple awk script to postprocess the file and change those to correct line directives: 我之前使用过的一种技术是让我的代码生成器在想要重置行指令时在一行上输出# ,然后使用一个简单的awk脚本对文件进行后处理并将其更改为正确的行指令:

#!/bin/awk -f
/^#$/ { printf "#line %d \"%s\"\n", NR+1, FILENAME; next; }
{ print; }

Yes, you need to keep track of the number of lines you've output, and you need to know the name of the file you're outputting into. 是的,您需要跟踪输出的行数,并且需要知道要输出的文件的名称。 Remember that the line number you specify is the line number of the next line. 请记住,您指定的行号是下一行的行号。 So if you've written 12 lines so far, you need to output #line 14 "filename" , since the #line directive will go on line 13, and so the next line is 14. 因此,如果到目前为止已经编写了12行,则需要输出#line 14 "filename" ,因为#line指令将在第13行,因此下一行是14。

There's no difference between the #line preprocessor directive in C and C++ . CC++#line预处理程序指令没有区别。

Suppose the input to the code generator, "user.code", contains the following: 假设代码生成器“user.code”的输入包含以下内容:

int foo () {
   return error1 ();
}

int bar () {
   return error2 ();
}

Suppose you want to augment this so it looks basically look like this: 假设你想要增加它,所以看起来基本上看起来像这样:

int foo () {
   return error1 ();
}

int generated_foo () {
   return generated_error1 ();
}

int bar () {
   return error2 ();
}

int generated_bar () {
   return generated_error2 ();
}

Except you don't want that. 除非你不想那样。 You want to add #line directives to the generated code so that the compiler messages indicate whether the errors / warnings are from the user code or the autogenerated code. 您希望将#line指令添加到生成的代码中,以便编译器消息指示错误/警告是来自用户代码还是自动生成的代码。 The #line directive indicates the source of the next line of code (rather than the line containing the #line directive). #line指令指示下一行代码的来源(而不是包含#line指令的行)。

#line 1 "user.code"
int foo () {
   return error1 ();
}

#line 7 "generated_code.cpp"  // NOTE: This is line #6 of generated_code.cpp
int generated_foo () {
   return generated_error1 ();
}

#line 5 "user.code"
int bar () {
   return error2 ();
}

#line 17 "generated_code.cpp" // NOTE: This is line #16 of generated_code.cpp
int generated_bar () {
   return generated_error2 ();
}

@Novelocrat, @Novelocrat,

I had asked this question here before, and no solid answers were posted, but I figured out that if line directives are inserted in the auto-generated code that points to the user code, then this makes the auto-generated code hard to relocate . 我之前在这里问过这个问题,并没有发布可靠的答案,但我发现如果在指向用户代码的自动生成的代码中插入行指令,那么这会使自动生成的代码难以重新定位 You have to keep the auto-generated and user code in the locations where the compiler can find them for reporting errors. 您必须将自动生成的和用户代码保留在编译器可以找到它们以报告错误的位置。 I thought it was better to simply insert the file name and line numbers of the user code in the generated code. 我认为最好只在生成的代码中插入用户代码的文件名和行号。 In good text editors it is a matter of a couple of keystrokes to jump to a line in a file by placing the cursor on the file name. 在优秀的文本编辑器中,通过将光标放在文件名上来跳转到文件中的一行就可以进行几次击键。

Eg: in vim placing the cursor on the file-name and pressing gf takes you to the file, and :42 takes you to the line 42 (say) that had the error. 例如:在vim中将光标放在文件名上并按gf将您带到文件,然后:42将您带到有错误的第42行(比如说)。

Just posting this bit here, so that someone else coming up with the same questions might consider this alternative too. 只是在这里发布这一点,以便其他人提出相同的问题也可以考虑这个替代方案。

Have you tried what __LINE__ and __FILE__ give you? 你试过__LINE____FILE__给你什么? I believe they are taken from your #line directives (what would be the point if not?). 我相信它们是从你的#line指令中取出的(如果不是,那会是什么意思?)。

(A quick test with gcc-4.7.2 and clang-3.1 confirms my hunch). (使用gcc-4.7.2和clang-3.1的快速测试证实了我的预感)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM