views:

140

answers:

4

I am using the Perl Template Toolkit to generate C files. I dearly want to be able to include #line directives in my C code so that error messages from the C compiler send me to the right place (the template file) rather than the wrong place (the template output). However, I don't know how to do this. The only result I got from Google was an unanswered message on the Template Toolkit mailing list.

I can imagine a tortured solution like reading the template file myself and adding line numbers, but does anyone have a trick or even a sensible method of getting the line numbers of the original file in Template Toolkit?

+3  A: 

Looks to me like Template::Parser's location method returns a suitable #line directive, but there isn't any built in function I see to include that in the output. You'd have to extend Template Toolkit to make it do so.

ysth
I'll accept that there is no way to do it, and just use the brute force method of adding a line directive everywhere via a preprocessor.
Kinopiko
A: 

Since number and "filename" are totally made up (whatever you want) in the #line directive, I suggest putting #line directives in the template using a slightly different context.

Rather than counting lines in the template yourself, which you could do, even using a template pre-processor. I would 'invent' file names for the different sections of the template and number thos lines with small numbers that you can count.

Then an error message might say "... in line 2 of div id='topleft'"

Don
+1  A: 

It doesn't look like Template::Toolkit natively supports this. One thing that you could do is make your program also write a mapping of generated lines to their lines in the appropriate template, so that you can look the errors up the errors with a simple script.

James Thompson
I want to do `C-x \``
Kinopiko
Let C-x ` jump to your error in the generated code, and map another key to call a script that looks up the corresponding entry in your line. You could even make a special entry in Emacs that does both things for you.
James Thompson
A: 

A brute-force solution:

#!/usr/local/bin/perl
use warnings;
use strict;
my $file = "something.c";
open my $input, "<", $file or die $!;
while (<$input>) {
    print "#line $. \"$file\"\n";
    print;
}
close $input or die $!;

Even better, test for [% on the line and only print #lines where necessary.

Kinopiko