What does the preprocessor do with "# <number> <filename>"? - c

I've just encountered a C file which contains both preprocessor directives and lines that look like this:
# 9 "filename"
I have never seen such lines before. What do they mean? I'm guessing these are preprocessor directives, but what does the preprocessor do with them?
Also, for some of the lines the string doesn't even represent an existing filename...

I believe it's another way of using the #line preprocessor directive.
For example you could write:
// you could write #line 7 "filename" or
// # 7 "filename" or
// # 7 or
#line 7
int main(void)
{
printf("%d\n", __LINE__);
And all of them would give you (in this case) 10 on stdout.
And a note about the "filename" part it's optional and unverified (that's why it can be anything, even a file that doesn't exist). Its use is explained in the link I provided -
If you specify a file name, the compiler views the next line as part of the specified file. If you do not specify a file name, the compiler views the next line as part of the current source file.

Related

Does C preprocessed file contain source file line number information?

Here is the problem:
I have a C source file main.c and the corresponding preprocessed file main.i. Given a line in main.i, how can I get the corresponding line number in main.c?
The C standard does not specify this. GCC and Clang emit lines starting with # followed by a space, a line number, a file name, and other information.. You can determine the line number in main.c:
Read the preprocessed file, main.i. After any line with # followed by a space, a number, and a file name that is not “main.c”, read and ignore further lines until there is a # followed by a space, a number, and “main.c”. Remember that number as the current line number.
Subsequent lines until another # line in this form are lines from main.c (after preprocessing) with consecutive line numbers continuing from the line number remembered above.
When used as a separate phase to produce a text file, the C preprocessor usually inserts #line directives, sometimes appearing as bare # directives providing the original line number, file name and other contextual information. #line directives have this form:
# line pp-tokens new-line
which after macro substitution should become:
# line digit-sequence new-line
or
# line digit-sequence " s-char-sequenceopt " new-line
Where digit-sequence is the line number of the next list in the source stream and the s-char-sequenceopt is the name of the file to use for diagnostics and as a replacement for the __FILE__ macro. Subsequent newlines increment the line number thus defined.
#line directives are produced by external programs that generate C code files to make compiler diagnostics point to the original source file.
C Compilers such as gcc and clang produce similar information in their preprocessing output in the form:
# number filename other-information new-line
This syntax is not defined by the C Standard but very common in preprocessing output produced by C compilers. The C standard does not define this output, used mostly for debugging purposes.

C extra # lines after preprocessing part [duplicate]

I was inspecting the preprocessed output generated by GCC, and I see a lot of these in the .i file that I generated using the -save-temps flag:
# 8 "/usr/include/i386-linux-gnu/gnu/stubs.h" 2 3 4
What do the numbers before and after the absolute path of stubs.h mean? It seems to be some kind of debugging information that is inserted by the preprocessor and allows the compiler to issue error messages referring to this information. These lines do not affect the program itself, but what specifically is each number for?
Based on the documentation the number before the filename is the line number. The numbers after the file name are a flag and mean the following:
1 indicates the start of a new file.
2 indicates returning to a file (after having included another file).
3 indicates that the following text comes from a system header file, so certain warnings should be suppressed.
4 indicates that the following text should be treated as being wrapped in an implicit extern "C" block.

#line keyword in C

I am trying to understand some code and I've come across a keyword that I've never seen before. I tried to google it, but haven't found anything regarding it as well.
char *valtext;
#line 1 "Values.l"
#define INITIAL 0
#line 2 "Values.l"
int reserve(char *s);
#line 388 "lex.val.c"
I've included the entire block hoping that perhaps someone can help me understand this chunk of code. I can't find any files on my system named "Values.l" and this chunk of code is located in the "lex.val.c" file.
Thanks in advance.
A #line directive sets the compiler's setting for the current file name and line number. This affects the __FILE__ and __LINE__ symbols, the output generated by a failing assert(), and diagnostic messages (errors and warnings). It's typically used by the preprocessor so that error and warning messages can refer to the original source code, not to the output of the preprocessor (which is typically discarded by the time you see any messages).
It's also used by other tools that generate C source code, such as lex/flex and yacc/bison, so that error messages can refer to the input file rather than the (temporary) generated C code.
The definitive reference is the C standard (pdf), section 6.10.4.
A line of the form
#line number
sets the current line number. A line of the form
#line number "file-name"
sets both the line number and the file name. You can also generate one of these two forms via macro expansion; for example:
#define LINE 42
#define FILE "foo.c"
#line LINE FILE
The #line directive is for the use of preprocessors, so that the original line number of the source can be communicated to the C compiler. It makes it so that error messages from the compiler properly refer to line numbers the user will understand.
For example, line 12 of your mycode.c may go through a preprocessor, and now be line 183 of mycode.tmp.cc. If the C compiler finds an error on that line, you don't want to be told the error is on line 183 of mycode.tmp.cc. So the C compiler needs to be given "original coordinates" of each line. The #line directive does this, telling the compiler the current line number and filename to use in error messages.
The line directive:
http://msdn.microsoft.com/en-US/library/b5w2czay%28v=VS.80%29.aspx
That code has gone through the pre-processor and as such is marked up by one stage of a compiler, intended to be consumed by another stage of the same compiler. The features that it uses aren't intended for your use.
The files that it references may be temporary files created by the compiler as it runs.
This is done so that the line number changes.
This is done in order to show the line numbers of the Lex input file, for example, in error messages and warnings. Because Lex generates C code, without #line directives compile errors and warnings wouldn't be of any value.

Precedence of -D MACRO and #define MACRO

If I have a C file foo.c and while I have given -DMACRO=1 as command line option for compilation. However, if within the header file also I have
#define MACRO 2
Which of these will get precedence?
I'm making an assumption of what you're doing, but if you'd like to supply from the command-line a non-default value for that macro, try this for the macro definition:
#ifndef MACRO
#define MACRO 2
#endif
That way if the MACRO has already been defined (via command-line parameter) it will neither be redefined nor result in an error.
The command line options apply ahead of any line read from a file. The file contents apply in the order written. In general, you will get at least a warning if any macro is redefined, regardless of whether the command line is involved. The warning may be silenced if the redefinition doesn't matter, perhaps because both definitions are identical.
The right way to answer a question like this is to build a small test case and try it. For example, in q3965956.c put the following:
#define AAA 2
AAA
and run it through the C preprocessor, perhaps with gcc -E:
C:>gcc -DAAA=42 -E q3965956.c
# 1 "q3965956.c"
# 1 ""
# 1 ""
# 1 "q3965956.c"
q3965956.c:1:1: warning: "AAA" redefined
:1:1: warning: this is the location of the previous definition
2
C:>
You can see from the output that the macro expanded to the value given by the #define in the file. Furthermore, you can see from the sequence of # directives that built-in definitions and the command line were both processed before any content of line 1 of q3965956.c.
Defines are stored in order the compiler sees them, and when the compiler encounters a new macro with the same name, it overwrites the previous macro with the new one (at least this is the case in gcc). GCC will also give you a warning when this happens.
You'll get an error for macro redefinition. Obviously -D gets defined first (before the source file is parsed rather than after) or it would have no use. The #define is then a redefinition.
manual says: first all -D and -U are evaluated in order and then all -includes (under section -D)
best way: try it out.

Is there any way to "undo" the effect of #line in C?

I am generating C code based on information provided by another file (an XML file). Certain chunks of C are included in this XML file and should be included verbatim in my generated C file. I wish to use the #line directive, so that if these chunks contain an error, the user will see the line number in the XML file that the chunk came from. For example, I wish to generate code like:
int main() {
#line 35 "file.xml"
....
#line
}
I wish to somehow "close" the #line section, I mean I think if there is an error e.g. with the closing } and that is generated by my program, the user should not see "error on line 36 of file.xml", that will be meaningless to them and confuse them.
For example, I could imagine a #line directive on its own (as in my example) would do something like that. But it doesn't work, and there is no such mention of any such facility in the gcc docs on #line.
Is there any such facility I'm missing? Or am I just asking for something that doesn't exist? How would you go about such a problem?
You need to issue another #line directive "resetting" to the line and filename of your original file.

Resources