Commit f4064312 authored by Robert Bradshaw's avatar Robert Bradshaw

Option to emit #line directives, ticket #53

parent 112e74e4
...@@ -36,7 +36,7 @@ Options: ...@@ -36,7 +36,7 @@ Options:
-D, --no-docstrings Remove docstrings. -D, --no-docstrings Remove docstrings.
-a, --annotate Produce a colorized HTML version of the source. -a, --annotate Produce a colorized HTML version of the source.
--convert-range Convert for loops using range() function to for...from loops. --line-directives Produce #line directives pointing to the .pyx source
--cplus Output a c++ rather than c file. --cplus Output a c++ rather than c file.
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive -X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
""" """
...@@ -114,6 +114,8 @@ def parse_command_line(args): ...@@ -114,6 +114,8 @@ def parse_command_line(args):
Options.annotate = True Options.annotate = True
elif option == "--convert-range": elif option == "--convert-range":
Options.convert_range = True Options.convert_range = True
elif option == "--line-directives":
options.emit_linenums = True
elif option in ("-X", "--directive"): elif option in ("-X", "--directive"):
try: try:
options.pragma_overrides = Options.parse_option_list(pop_arg()) options.pragma_overrides = Options.parse_option_list(pop_arg())
......
...@@ -161,13 +161,14 @@ class GlobalState(object): ...@@ -161,13 +161,14 @@ class GlobalState(object):
# interned_nums # interned_nums
# cached_builtins # cached_builtins
def __init__(self, rootwriter): def __init__(self, rootwriter, emit_linenums=False):
self.filename_table = {} self.filename_table = {}
self.filename_list = [] self.filename_list = []
self.input_file_contents = {} self.input_file_contents = {}
self.used_utility_code = set() self.used_utility_code = set()
self.declared_cnames = {} self.declared_cnames = {}
self.pystring_table_needed = False self.pystring_table_needed = False
self.emit_linenums = emit_linenums
def initwriters(self, rootwriter): def initwriters(self, rootwriter):
self.utilprotowriter = rootwriter.new_writer() self.utilprotowriter = rootwriter.new_writer()
...@@ -378,6 +379,8 @@ class GlobalState(object): ...@@ -378,6 +379,8 @@ class GlobalState(object):
writer.insert(self.utilprotowriter) writer.insert(self.utilprotowriter)
def put_utility_code_defs(self, writer): def put_utility_code_defs(self, writer):
if self.emit_linenums:
writer.write('\n#line 1 "cython_utility"\n')
writer.insert(self.utildefwriter) writer.insert(self.utildefwriter)
...@@ -403,7 +406,7 @@ class CCodeWriter(object): ...@@ -403,7 +406,7 @@ class CCodeWriter(object):
- marker: Not copied to insertion point - marker: Not copied to insertion point
- filename_table, filename_list, input_file_contents: All codewriters - filename_table, filename_list, input_file_contents: All codewriters
coming from the same root share the same instances simultaneously. coming from the same root share the same instances simultaneously.
""" """
# f file output file # f file output file
# buffer StringIOTree # buffer StringIOTree
...@@ -415,19 +418,21 @@ class CCodeWriter(object): ...@@ -415,19 +418,21 @@ class CCodeWriter(object):
# generation (labels and temps state etc.) # generation (labels and temps state etc.)
# globalstate GlobalState contains state global for a C file (input file info, # globalstate GlobalState contains state global for a C file (input file info,
# utility code, declared constants etc.) # utility code, declared constants etc.)
# emit_linenums boolean whether or not to write #line pragmas
def __init__(self, create_from=None, buffer=None, copy_formatting=False): def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None):
if buffer is None: buffer = StringIOTree() if buffer is None: buffer = StringIOTree()
self.buffer = buffer self.buffer = buffer
self.marker = None self.marker = None
self.last_marker_line = 0 self.last_marker_line = 0
self.source_desc = ""
self.funcstate = None self.funcstate = None
self.level = 0 self.level = 0
self.bol = 1 self.bol = 1
if create_from is None: if create_from is None:
# Root CCodeWriter # Root CCodeWriter
self.globalstate = GlobalState(self) self.globalstate = GlobalState(self, emit_linenums=emit_linenums)
self.globalstate.initwriters(self) self.globalstate.initwriters(self)
# ^^^ need seperate step because this will reference self.globalstate # ^^^ need seperate step because this will reference self.globalstate
else: else:
...@@ -437,6 +442,10 @@ class CCodeWriter(object): ...@@ -437,6 +442,10 @@ class CCodeWriter(object):
if copy_formatting: if copy_formatting:
self.level = create_from.level self.level = create_from.level
self.bol = create_from.bol self.bol = create_from.bol
if emit_linenums is None:
self.emit_linenums = self.globalstate.emit_linenums
else:
self.emit_linenums = emit_linenums
def create_new(self, create_from, buffer, copy_formatting): def create_new(self, create_from, buffer, copy_formatting):
# polymorphic constructor -- very slightly more versatile # polymorphic constructor -- very slightly more versatile
...@@ -504,6 +513,8 @@ class CCodeWriter(object): ...@@ -504,6 +513,8 @@ class CCodeWriter(object):
def putln(self, code = ""): def putln(self, code = ""):
if self.marker and self.bol: if self.marker and self.bol:
self.emit_marker() self.emit_marker()
if self.emit_linenums and self.last_marker_line != 0:
self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
if code: if code:
self.put(code) self.put(code)
self.write("\n"); self.write("\n");
...@@ -580,7 +591,8 @@ class CCodeWriter(object): ...@@ -580,7 +591,8 @@ class CCodeWriter(object):
marker = u'"%s":%d\n%s\n' % ( marker = u'"%s":%d\n%s\n' % (
source_desc.get_escaped_description(), line, u'\n'.join(lines)) source_desc.get_escaped_description(), line, u'\n'.join(lines))
self.marker = (line, marker) self.marker = (line, marker)
if self.emit_linenums:
self.source_desc = source_desc.get_escaped_description()
def put_label(self, lbl): def put_label(self, lbl):
if lbl in self.funcstate.labels_used: if lbl in self.funcstate.labels_used:
......
...@@ -727,7 +727,8 @@ default_options = dict( ...@@ -727,7 +727,8 @@ default_options = dict(
timestamps = None, timestamps = None,
verbose = 0, verbose = 0,
quiet = 0, quiet = 0,
pragma_overrides = {} pragma_overrides = {},
emit_linenums = False,
) )
if sys.platform == "mac": if sys.platform == "mac":
from Cython.Mac.MacSystem import c_compile, c_link, CCompilerError from Cython.Mac.MacSystem import c_compile, c_link, CCompilerError
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
# #
import os, time import os, time
from cStringIO import StringIO
from PyrexTypes import CPtrType from PyrexTypes import CPtrType
import Future import Future
...@@ -240,7 +239,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -240,7 +239,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if Options.annotate or options.annotate: if Options.annotate or options.annotate:
code = Annotate.AnnotationCCodeWriter() code = Annotate.AnnotationCCodeWriter()
else: else:
code = Code.CCodeWriter() code = Code.CCodeWriter(emit_linenums=options.emit_linenums)
h_code = code.insertion_point() h_code = code.insertion_point()
self.generate_module_preamble(env, modules, h_code) self.generate_module_preamble(env, modules, h_code)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment