#line - goals?

Unfortunately, I did a little archeology of the code today (refactoring some old dangerous code) and found a little fossil:

# line 7 "foo.y" 

I was completely stunned to find such an archaic treasure there. I read about it on a C programming website. However, he did not explain why anyone would want to use it. I was left for myself, so I assumed that the programmer set it up solely for the sheer joy of lying to the compiler.

Note: (Keep in mind that the fossil was actually on line 3 of the cpp file) (Oh, and the file did point to a .y file that was almost identical to this file.

Can anyone think why such a directive is needed? Or that it can be used?

+7
c
source share
5 answers

It is usually used by automatic code generation tools (such as yacc or bison ) to set the line number to the line value in the actual source file, and not in the C source file.

Thus, when you get the error message:

 a += xyz; ^ No such identifier 'xyz' on line 15 of foo.y 

you can see line 15 of the actual source file to see the problem.

Otherwise, it says something ridiculous, like No such identifier 'xyz' on line 1723 of foo.c , and you need to manually match this line in your auto-generated C file with the equivalent in your real file. Believe me, if you do not want to deeply engage yourself in the internal aspects of lexical and semantic analysis (or you want a brain hemorrhage), you do not want to go through the code generated by yacc ( bison can generate more pleasant code, I don’t know, but I don’t like it because I'm writing a higher level code).

It has two forms in accordance with the C99 standard:

 #line 12345 #line 12345 "foo.y" 

The first sets only the line number of the message, the second also changes the name of the registered file, so you may get an error in line 27 foo.y instead of foo.c


As for the "programmer, he put it solely for the sheer joy of lying to the compiler," no. We can be bent and twisted, but we are usually not malicious :-) This line was placed there by yacc or bison itself to do you a favor.

+17
source share

The only place I saw this functionality as useful was the generated code. If you use a tool that generates a C file from a source defined in another form in a separate file (that is, a β€œ.y” file), using #line can help the user find out where the β€œreal” problem is and where they should go to fix this (.y file where they put the source code).

+5
source share

The purpose of the #line directive is mainly used by tools - code generators can use it so that debuggers (for example) can maintain a context of where things are in the user's code, or thus error messages can refer to the user's location in the source file.

I have never seen this directive used by a programmer manually inserting it - and I'm not sure how useful this would be.

+2
source share

It has a deeper purpose. The original C preprocessor was a separate program from the compiler. After he combined several .h files into a .c file, people still wanted to know that the error message came from line 42 of stdio.h or line 17 of main.c. Without any means of communication, the compiler would otherwise have no way of knowing which source file originally contained a line of code violation.

It also affects the tables that any source level debugger needs to translate between the generated code and the source file and line number.

Of course, in this case you are looking at a file that was written by a tool (probably called yacc or bison), which is used to create parsers from the description of their grammar. This file is not a source file. It was created from real source text.

If your archeology leads you to a problem with the parser, then you will need to determine which parser is actually used, and pay a little attention to the parsers in general, so that you understand why it does everything. Documentation for yacc, bison, or any other tool is likely to be useful as well.

+2
source share

I used #line and #error to create a temporary * .c file that you are compiling, and let your ID environment give you a list of available errors of some third-party tools.

For example, I transferred the output file from PC-LINT to a perl script that converted human readable errors to lines #line and #error. Then compiled this output, and my IDE allows me to go through every error using F4. It is much faster to manually open each file and go to a specific line.

+1
source share

All Articles