Message ID | mcrocc35v51.fsf@google.com |
---|---|
State | New |
Headers | show |
On Sat, 11 Sep 2010 23:32:58 -0700 Ian Lance Taylor <iant@google.com> wrote: > By convention, a Go comment of the form //line FILE:LINENO is the > equivalent of a C #line comment. This patch implements that for gccgo. > Committed to gccgo branch. I don't use Go yet (even if I liked reading its specification & documentation) but, as someone who did wrote significant source code generators (notably the GCC MELT branch and plugin see http://gcc.gnu.org/wiki/MELT for more) I would suggest an advice. There are lots of code generators which generate several lines of generated code per line of their input code. So it would help these to be able to say that a given chunk of lines of code is orginated from the same position. So an hypothetical code generator would not have to generate //line "ab.cd":3 x23 = 2 + z; //line "ab.cd":3 x34 = 3 * y; //line "ab.cd":3 y = x23 + x34; //line "ab.cd":3 if (y < 0) y=0; //line "ab.cd":3 if (z > x34) z=x34; I assume above is correct Go syntax. If it is generated C it would be #line "ab.cd" 3 x23 = 2 + z; #line "ab.cd" 3 x32 = 3 * y; #line "ab.cd" 3 y = x23 + x34; #line "ab.cd" 3 if (y < 0) y = 0; #line "ab.cd" 3 if (z > x34) z=x34; I am suggesting to accept in Go two new magical comments //startsamelines & //endsamelines and generate //startsamelines "ab.cd":3 x23 = 2 + z; x34 = 3 * y; y = x23 + x33; if (y < 0) y = 0; if (z > x34) z=x34; //endsamelines this in addition of your //line proposal. Within GCC, the suggestions could be to have pragmas #pragma GCC startsamelines "ab.cd":3 x23 = 2 + z; x34 = 3 * y; y = x23 + x33; if (y < 0) y = 0; if (z > x34) z=x34; #pragma GCC endsamelines And these chunks of code will have the same effect as the previous with only //line for Go & #line for C. The proposed trick avoid the generator to have to emit the same //line comment in Go or #line directive in C for every line generated for the same source position. Regards.
Basile Starynkevitch <basile@starynkevitch.net> writes: > I am suggesting to accept in Go two new magical > comments //startsamelines & //endsamelines and generate > //startsamelines "ab.cd":3 > x23 = 2 + z; > x34 = 3 * y; > y = x23 + x33; > if (y < 0) y = 0; > if (z > x34) z=x34; > //endsamelines > this in addition of your //line proposal. Thanks for the suggestion, but I don't think the benefit is worth adding the feature. It should be easy enough for the code generator to simply put all the generated lines on the same line of the generated source file--it should be as simple as generating a semicolon instead of a newline. After all, generated code is rarely read, and the compiler doesn't care. In that cases where that is impossible for some reason, I don't think it is much of a hardship for the code generator to generate multiple //line comments. Ian
diff -r 54b04d338c19 go/lex.cc --- a/go/lex.cc Fri Sep 10 16:18:13 2010 -0700 +++ b/go/lex.cc Sat Sep 11 23:29:35 2010 -0700 @@ -448,7 +448,6 @@ Lex::~Lex() { delete[] this->linebuf_; - linemap_add(line_table, LC_LEAVE, 0, NULL, 0); } // Read a new line from the file. @@ -1579,6 +1578,44 @@ { const char* p = this->linebuf_ + this->lineoff_; const char* pend = this->linebuf_ + this->linesize_; + + // By convention, a C++ comment at the start of the line of the form + // //line FILE:LINENO + // is interpreted as setting the file name and line number of the + // next source line. + + if (this->lineoff_ == 2 + && pend - p > 5 + && memcmp(p, "line ", 5) == 0) + { + p += 5; + while (p < pend && *p == ' ') + ++p; + const char* pcolon = static_cast<const char*>(memchr(p, ':', pend - p)); + if (pcolon != NULL + && pcolon[1] >= '0' + && pcolon[1] <= '9') + { + char* plend; + long lineno = strtol(pcolon + 1, &plend, 10); + if (plend > pcolon + 1 + && (plend == pend + || *plend < '0' + || *plend > '9')) + { + unsigned int filelen = pcolon - p; + char* file = new char[filelen + 1]; + memcpy(file, p, filelen); + file[filelen] = '\0'; + + linemap_add(line_table, LC_ENTER, 0, file, lineno); + this->lineno_ = lineno - 1; + + p = plend; + } + } + } + while (p < pend) { this->lineoff_ = p - this->linebuf_;