2004-10-20 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolWriter.cs
index 07af791664ac4a9b9ba6c6ddda6db3a5b724c965..10fc8ce88af4dc540bc18f96b2e457de9dbe26b5 100755 (executable)
@@ -1,8 +1,8 @@
 //
-// System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
+// Mono.CSharp.Debugger/MonoSymbolWriter.cs
 //
 // Author:
-//   Martin Baulig (martin@gnome.org)
+//   Martin Baulig (martin@ximian.com)
 //
 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
 // interface.
 // (C) 2002 Ximian, Inc.  http://www.ximian.com
 //
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
-using System.Reflection;
-using System.Reflection.Emit;
 using System.Runtime.CompilerServices;
-using System.Diagnostics.SymbolStore;
 using System.Collections;
 using System.IO;
        
-namespace Mono.CSharp.Debugger
+namespace Mono.CompilerServices.SymbolWriter
 {
-       internal class SourceFile
+       public interface ISourceFile
        {
-               private ArrayList _methods = new ArrayList ();
-               private string _file_name;
-
-               public SourceFile (string filename)
-               {
-                       this._file_name = filename;
-               }
-
-               public override string ToString ()
-               {
-                       return _file_name;
-               }
-
-               public string FileName {
-                       get {
-                               return _file_name;
-                       }
-               }
-
-               public SourceMethod[] Methods {
-                       get {
-                               SourceMethod[] retval = new SourceMethod [_methods.Count];
-                               _methods.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddMethod (SourceMethod method)
-               {
-                       _methods.Add (method);
+               SourceFileEntry Entry {
+                       get;
                }
        }
 
-       internal class SourceBlock
+       public interface ISourceMethod
        {
-               static private int next_index;
-               private readonly int _index;
-
-               public SourceBlock (SourceMethod method, LineNumberEntry start, LineNumberEntry end)
-               {
-                       this._method = method;
-                       this._start = start;
-                       this._end = end;
-                       this._index = ++next_index;
-               }
-
-               internal SourceBlock (SourceMethod method, int startOffset)
-               {
-                       this._method = method;
-                       this._start_offset = startOffset;
-                       this._index = ++next_index;
-               }
-
-               public override string ToString ()
-               {
-                       return "SourceBlock #" + ID + " (" + Start + " - " + End + ")";
-               }
-
-               private readonly SourceMethod _method;
-               private ArrayList _blocks = new ArrayList ();
-               internal LineNumberEntry _start = LineNumberEntry.Null;
-               internal LineNumberEntry _end = LineNumberEntry.Null;
-               internal int _start_offset, _end_offset;
-               bool _has_source;
-
-               internal void SetSourceRange (int startLine, int endLine)
-               {
-                       _start = new LineNumberEntry (startLine, _start_offset);
-                       _end = new LineNumberEntry (endLine, _end_offset);
-                       _has_source = true;
-               }
-
-               private ArrayList _locals = new ArrayList ();
-
-               public SourceMethod SourceMethod {
-                       get {
-                               return _method;
-                       }
-               }
-
-               public SourceBlock[] Blocks {
-                       get {
-                               SourceBlock[] retval = new SourceBlock [_blocks.Count];
-                               _blocks.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddBlock (SourceBlock block)
-               {
-                       _blocks.Add (block);
+               string Name {
+                       get;
                }
 
-               public bool HasSource {
-                       get {
-                               return _has_source;
-                       }
-               }
-
-               public LineNumberEntry Start {
-                       get {
-                               return _start;
-                       }
-               }
-
-               public LineNumberEntry End {
-                       get {
-                               return _end;
-                       }
-               }
-
-               public int ID {
-                       get {
-                               return _index;
-                       }
-               }
-
-               public LocalVariableEntry[] Locals {
-                       get {
-                               LocalVariableEntry[] retval = new LocalVariableEntry [_locals.Count];
-                               _locals.CopyTo (retval);
-                               return retval;
-                       }
+               int NamespaceID {
+                       get;
                }
 
-               public void AddLocal (LocalVariableEntry local)
-               {
-                       _locals.Add (local);
+               int Token {
+                       get;
                }
        }
 
-       internal class SourceMethod
+       public class MonoSymbolWriter
        {
-               private ArrayList _lines = new ArrayList ();
-               private ArrayList _blocks = new ArrayList ();
-               private Hashtable _block_hash = new Hashtable ();
-               private Stack _block_stack = new Stack ();
-
-               internal readonly MethodBase _method_base;
-               internal SourceFile _source_file;
-               internal int _token;
-
-               private SourceBlock _implicit_block;
-
-               public SourceMethod (MethodBase method_base, SourceFile source_file)
-                       : this (method_base)
-               {
-                       this._source_file = source_file;
-               }
-
-               internal SourceMethod (MethodBase method_base)
-               {
-                       this._method_base = method_base;
-
-                       this._implicit_block = new SourceBlock (this, 0);
-               }
-
-               public void SetSourceRange (SourceFile sourceFile,
-                                           int startLine, int startColumn,
-                                           int endLine, int endColumn)
-               {
-                       _source_file = sourceFile;
-                       _implicit_block.SetSourceRange (startLine, endLine);
-               }
-
-               public void StartBlock (SourceBlock block)
-               {
-                       _block_stack.Push (block);
-               }
-
-               public void EndBlock (int endOffset) {
-                       SourceBlock block = (SourceBlock) _block_stack.Pop ();
-
-                       block._end_offset = endOffset;
-
-                       if (_block_stack.Count > 0) {
-                               SourceBlock parent = (SourceBlock) _block_stack.Peek ();
-
-                               parent.AddBlock (block);
-                       } else
-                               _blocks.Add (block);
-
-                       _block_hash.Add (block.ID, block);
-               }
-
-               public void SetBlockRange (int BlockID, int startOffset, int endOffset)
-               {
-                       SourceBlock block = (SourceBlock) _block_hash [BlockID];
-                       block._start_offset = startOffset;
-                       block._end_offset = endOffset;
-               }
-
-               public SourceBlock CurrentBlock {
-                       get {
-                               if (_block_stack.Count > 0)
-                                       return (SourceBlock) _block_stack.Peek ();
-                               else
-                                       return _implicit_block;
-                       }
-               }
-
-               public LineNumberEntry[] Lines {
-                       get {
-                               LineNumberEntry[] retval = new LineNumberEntry [_lines.Count];
-                               _lines.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddLine (LineNumberEntry line)
-               {
-                       _lines.Add (line);
-               }
-
-               public SourceBlock[] Blocks {
-                       get {
-                               SourceBlock[] retval = new SourceBlock [_blocks.Count];
-                               _blocks.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public LocalVariableEntry[] Locals {
-                       get {
-                               return _implicit_block.Locals;
-                       }
-               }
-
-               public void AddLocal (LocalVariableEntry local)
-               {
-                       _implicit_block.AddLocal (local);
-               }
-
-               public MethodBase MethodBase {
-                       get {
-                               return _method_base;
-                       }
-               }
-
-               public string FullName {
-                       get {
-                               return _method_base.DeclaringType.FullName + "." + _method_base.Name;
-                       }
-               }
-
-               public Type ReturnType {
-                       get {
-                               if (_method_base is MethodInfo)
-                                       return ((MethodInfo)_method_base).ReturnType;
-                               else if (_method_base is ConstructorInfo)
-                                       return _method_base.DeclaringType;
-                               else
-                                       throw new NotSupportedException ();
-                       }
-               }
-
-               public ParameterInfo[] Parameters {
-                       get {
-                               if (_method_base == null)
-                                       return new ParameterInfo [0];
-
-                               ParameterInfo [] retval = _method_base.GetParameters ();
-                               if (retval == null)
-                                       return new ParameterInfo [0];
-                               else
-                                       return retval;
-                       }
-               }
-
-               public SourceFile SourceFile {
-                       get {
-                               return _source_file;
-                       }
-               }
-
-               public int Token {
-                       get {
-                               if (_token != 0)
-                                       return _token;
-                               else
-                                       throw new NotSupportedException ();
-                       }
-               }
-
-               public bool HasSource {
-                       get {
-                               return _implicit_block.HasSource && (_source_file != null);
-                       }
-               }
-
-               public LineNumberEntry Start {
-                       get {
-                               return _implicit_block.Start;
-                       }
-               }
-
-               public LineNumberEntry End {
-                       get {
-                               return _implicit_block.End;
-                       }
-               }
-       }
-
-       public class MonoSymbolWriter : IMonoSymbolWriter
-       {
-               protected ModuleBuilder module_builder;
                protected ArrayList locals = null;
-               protected ArrayList orphant_methods = null;
                protected ArrayList methods = null;
-               protected Hashtable sources = null;
-               private ArrayList mbuilder_array = null;
-
-               internal SourceMethod[] Methods {
-                       get {
-                               SourceMethod[] retval = new SourceMethod [methods.Count];
-                               methods.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               internal SourceFile[] Sources {
+               protected ArrayList sources = null;
+               protected readonly MonoSymbolFile file;
+               private string filename = null;
+               
+               LineNumberEntry [] current_method_lines;
+               int current_method_lines_pos = 0;
+
+               internal ISourceFile[] Sources {
                        get {
-                               SourceFile[] retval = new SourceFile [sources.Count];
-                               sources.Values.CopyTo (retval, 0);
+                               ISourceFile[] retval = new ISourceFile [sources.Count];
+                               sources.CopyTo (retval, 0);
                                return retval;
                        }
                }
@@ -356,170 +85,77 @@ namespace Mono.CSharp.Debugger
                // Interface IMonoSymbolWriter
                //
 
-               public MonoSymbolWriter (ModuleBuilder mb, ArrayList mbuilder_array)
+               public MonoSymbolWriter (string filename)
                {
-                       this.module_builder = mb;
                        this.methods = new ArrayList ();
-                       this.sources = new Hashtable ();
-                       this.orphant_methods = new ArrayList ();
+                       this.sources = new ArrayList ();
                        this.locals = new ArrayList ();
-                       this.mbuilder_array = mbuilder_array;
-               }
-
-               public void Close ()
-               {
-                       throw new InvalidOperationException ();
-               }
+                       this.file = new MonoSymbolFile ();
 
-               public byte[] CreateSymbolFile (AssemblyBuilder assembly_builder)
-               {
-                       DoFixups (assembly_builder);
-
-                       return CreateOutput (assembly_builder);
-               }
-
-               public void CloseNamespace () {
+                       this.filename = filename + ".mdb";
+                       
+                       this.current_method_lines = new LineNumberEntry [50];
                }
 
-               // Create and return a new IMonoSymbolDocumentWriter.
-               public ISymbolDocumentWriter DefineDocument (string url,
-                                                            Guid language,
-                                                            Guid languageVendor,
-                                                            Guid documentType)
-               {
-                       return new MonoSymbolDocumentWriter (url);
-               }
+               public void CloseNamespace ()
+               { }
 
-               public void DefineField (
-                       SymbolToken parent,
-                       string name,
-                       FieldAttributes attributes,
-                       byte[] signature,
-                       SymAddressKind addrKind,
-                       int addr1,
-                       int addr2,
-                       int addr3)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public void DefineGlobalVariable (
-                       string name,
-                       FieldAttributes attributes,
-                       byte[] signature,
-                       SymAddressKind addrKind,
-                       int addr1,
-                       int addr2,
-                       int addr3)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public void DefineLocalVariable (string name,
-                                                FieldAttributes attributes,
-                                                byte[] signature,
-                                                SymAddressKind addrKind,
-                                                int addr1,
-                                                int addr2,
-                                                int addr3,
-                                                int startOffset,
-                                                int endOffset)
+               public void DefineLocalVariable (string name, byte[] signature)
                {
                        if (current_method == null)
                                return;
 
-                       current_method.AddLocal (new LocalVariableEntry (name, attributes, signature));
+                       current_method.AddLocal (name, signature);
                }
 
-               public void DefineParameter (string name,
-                                            ParameterAttributes attributes,
-                                            int sequence,
-                                            SymAddressKind addrKind,
-                                            int addr1,
-                                            int addr2,
-                                            int addr3)
-               {
-                       throw new NotSupportedException ();
-               }
-
-               public void DefineSequencePoints (ISymbolDocumentWriter document,
-                                                 int[] offsets,
-                                                 int[] lines,
-                                                 int[] columns,
-                                                 int[] endLines,
-                                                 int[] endColumns)
+               public void MarkSequencePoint (int offset, int line, int column)
                {
                        if (current_method == null)
                                return;
 
-                       LineNumberEntry source_line = new LineNumberEntry (lines [0], offsets [0]);
-
-                       if (current_method != null)
-                               current_method.AddLine (source_line);
-               }
-
-               public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
-               {
-                       throw new NotSupportedException ();
+                       if (current_method_lines_pos == current_method_lines.Length) {
+                               LineNumberEntry [] tmp = current_method_lines;
+                               current_method_lines = new LineNumberEntry [current_method_lines.Length * 2];
+                               Array.Copy (tmp, current_method_lines, current_method_lines_pos);
+                       }
+                       
+                       current_method_lines [current_method_lines_pos++] = new LineNumberEntry (line, offset);
                }
 
-               public void OpenMethod (SymbolToken symbol_token)
+               public void OpenMethod (ISourceFile file, ISourceMethod method,
+                                       int startRow, int startColumn,
+                                       int endRow, int endColumn)
                {
-                       int token = symbol_token.GetToken ();
-
-                       if ((token & 0xff000000) != 0x06000000)
-                               throw new ArgumentException ();
-
-                       int index = (token & 0xffffff) - 1;
-
-                       MethodBase mb = (MethodBase) mbuilder_array [index];
-
-                       current_method = new SourceMethod (mb);
+                       SourceMethod source = new SourceMethod (
+                               file, method, startRow, startColumn, endRow, endColumn);
 
+                       current_method = source;
                        methods.Add (current_method);
                }
 
-               public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
-                                                 int startLine, int startColumn,
-                                                 ISymbolDocumentWriter endDoc,
-                                                 int endLine, int endColumn)
+               public void CloseMethod ()
                {
-                       if (current_method == null)
-                               return;
-
-                       if ((startDoc == null) || (endDoc == null))
-                               throw new NullReferenceException ();
-
-                       if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
-                               throw new NotSupportedException ("both startDoc and endDoc must be of type "
-                                                                + "MonoSymbolDocumentWriter");
-
-                       if (!startDoc.Equals (endDoc))
-                               throw new NotSupportedException ("startDoc and endDoc must be the same");
-
-                       string source_file = ((MonoSymbolDocumentWriter) startDoc).FileName;
-                       SourceFile source_info;
-
-                       if (sources.ContainsKey (source_file))
-                               source_info = (SourceFile) sources [source_file];
-                       else {
-                               source_info = new SourceFile (source_file);
-                               sources.Add (source_file, source_info);
-                       }
-
-                       current_method.SetSourceRange (source_info, startLine, startColumn,
-                                                      endLine, endColumn);
-
-                       source_info.AddMethod (current_method);
+                       current_method.SetLineNumbers (
+                               current_method_lines, current_method_lines_pos);
+                       current_method_lines_pos = 0;
+                       
+                       current_method = null;
                }
 
-               public void CloseMethod () {
-                       current_method = null;
+               public SourceFileEntry DefineDocument (string url)
+               {
+                       SourceFileEntry entry = new SourceFileEntry (file, url);
+                       sources.Add (entry);
+                       return entry;
                }
 
-               public void OpenNamespace (string name)
+               public int DefineNamespace (string name, SourceFileEntry source,
+                                           string[] using_clauses, int parent)
                {
-                       throw new NotSupportedException ();
+                       if ((source == null) || (using_clauses == null))
+                               throw new NullReferenceException ();
+
+                       return source.DefineNamespace (name, using_clauses, parent);
                }
 
                public int OpenScope (int startOffset)
@@ -527,85 +163,182 @@ namespace Mono.CSharp.Debugger
                        if (current_method == null)
                                return 0;
 
-                       SourceBlock block = new SourceBlock (current_method, startOffset);
-                       current_method.StartBlock (block);
-
-                       return block.ID;
+                       current_method.StartBlock (startOffset);
+                       return 0;
                }
 
-               public void CloseScope (int endOffset) {
+               public void CloseScope (int endOffset)
+               {
                        if (current_method == null)
                                return;
 
                        current_method.EndBlock (endOffset);
                }
 
-               public void SetScopeRange (int scopeID, int startOffset, int endOffset)
+               protected byte[] CreateOutput (Guid guid)
                {
-                       if (current_method == null)
-                               return;
+                       foreach (SourceMethod method in methods) {
+                               method.SourceFile.Entry.DefineMethod (
+                                       method.Method.Name, method.Method.Token,
+                                       method.Locals, method.Lines, method.Blocks,
+                                       method.Start.Row, method.End.Row,
+                                       method.Method.NamespaceID);
+                       }
 
-                       current_method.SetBlockRange (scopeID, startOffset, endOffset);
+                       return file.CreateSymbolFile (guid);
                }
 
-               public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
+               public void WriteSymbolFile (Guid guid)
                {
-                       throw new NotSupportedException ();
+                       using (FileStream stream = new FileStream (
+                                      filename, FileMode.Create, FileAccess.Write)) {
+                               byte[] data = CreateOutput (guid);
+                               stream.Write (data, 0, data.Length);
+                       }
                }
 
-               public void SetUnderlyingWriter (IntPtr underlyingWriter)
+               protected class SourceMethod
                {
-                       throw new NotSupportedException ();
-               }
+                       LineNumberEntry [] lines;
+                       private ArrayList _locals;
+                       private ArrayList _blocks;
+                       private Stack _block_stack;
+                       private int next_block_id = 0;
+                       private ISourceMethod _method;
+                       private ISourceFile _file;
+                       private LineNumberEntry _start, _end;
 
-               public void SetUserEntryPoint (SymbolToken entryMethod)
-               {
-                       throw new NotSupportedException ();
-               }
+                       private LexicalBlockEntry _implicit_block;
 
-               public void UsingNamespace (string fullName)
-               {
-                       throw new NotSupportedException ();
-               }
+                       public SourceMethod (ISourceFile file, ISourceMethod method,
+                                            int startLine, int startColumn,
+                                            int endLine, int endColumn)
+                       {
+                               this._file = file;
+                               this._method = method;
 
-               //
-               // MonoSymbolWriter implementation
-               //
-               protected void DoFixups (Assembly assembly)
-               {
-                       foreach (SourceMethod method in methods) {
-                               if (method._method_base is MethodBuilder) {
-                                       MethodBuilder mb = (MethodBuilder) method._method_base;
-                                       method._token = mb.GetToken ().Token;
-                               } else if (method._method_base is ConstructorBuilder) {
-                                       ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
-                                       method._token = cb.GetToken ().Token;
-                               } else
-                                       throw new NotSupportedException ();
-
-                               if (method.SourceFile == null)
-                                       orphant_methods.Add (method);
+                               this._start = new LineNumberEntry (startLine, 0);
+                               this._end = new LineNumberEntry (endLine, 0);
+
+                               this._implicit_block = new LexicalBlockEntry (0, 0);
                        }
-               }
 
-               protected byte[] CreateOutput (Assembly assembly)
-               {
-                       MonoSymbolFile file = new MonoSymbolFile ();
+                       public void StartBlock (int startOffset)
+                       {
+                               LexicalBlockEntry block = new LexicalBlockEntry (
+                                       ++next_block_id, startOffset);
+                               if (_block_stack == null)
+                                       _block_stack = new Stack ();
+                               _block_stack.Push (block);
+                               if (_blocks == null)
+                                       _blocks = new ArrayList ();
+                               _blocks.Add (block);
+                       }
+
+                       public void EndBlock (int endOffset)
+                       {
+                               LexicalBlockEntry block =
+                                       (LexicalBlockEntry) _block_stack.Pop ();
+
+                               block.Close (endOffset);
+                       }
+
+                       public LexicalBlockEntry[] Blocks {
+                               get {
+                                       if (_blocks == null)
+                                               return new LexicalBlockEntry [0];
+                                       else {
+                                               LexicalBlockEntry[] retval =
+                                                       new LexicalBlockEntry [_blocks.Count];
+                                               _blocks.CopyTo (retval, 0);
+                                               return retval;
+                                       }
+                               }
+                       }
+
+                       public LexicalBlockEntry CurrentBlock {
+                               get {
+                                       if ((_block_stack != null) && (_block_stack.Count > 0))
+                                               return (LexicalBlockEntry) _block_stack.Peek ();
+                                       else
+                                               return _implicit_block;
+                               }
+                       }
+
+                       public LineNumberEntry[] Lines {
+                               get {
+                                       return lines;
+                               }
+                       }
 
-                       foreach (SourceMethod method in Methods) {
-                               if (!method.HasSource) {
-                                       Console.WriteLine ("INGORING METHOD: {0}", method);
-                                       continue;
+                       public LocalVariableEntry[] Locals {
+                               get {
+                                       if (_locals == null)
+                                               return new LocalVariableEntry [0];
+                                       else {
+                                               LocalVariableEntry[] retval =
+                                                       new LocalVariableEntry [_locals.Count];
+                                               _locals.CopyTo (retval, 0);
+                                               return retval;
+                                       }
                                }
+                       }
+
+                       public void AddLocal (string name, byte[] signature)
+                       {
+                               if (_locals == null)
+                                       _locals = new ArrayList ();
+                               _locals.Add (new LocalVariableEntry (
+                                                    name, signature, CurrentBlock.Index));
+                       }
 
-                               SourceFileEntry source = file.DefineSource (method.SourceFile.FileName);
+                       public ISourceFile SourceFile {
+                               get { return _file; }
+                       }
 
-                               source.DefineMethod (method.MethodBase, method.Token, method.Locals,
-                                                    method.Lines, method.Start.Row, method.End.Row);
+                       public ISourceMethod Method {
+                               get { return _method; }
                        }
 
-                       return file.CreateSymbolFile ();
+                       public LineNumberEntry Start {
+                               get { return _start; }
+                       }
+
+                       public LineNumberEntry End {
+                               get { return _end; }
+                       }
+
+                       //
+                       // Passes on the lines from the MonoSymbolWriter. This method is
+                       // free to mutate the lns array, and it does.
+                       //
+                       internal void SetLineNumbers (LineNumberEntry [] lns, int count)
+                       {
+                               int pos = 0;
+
+                               int last_offset = -1;
+                               int last_row = -1;
+                               for (int i = 0; i < count; i++) {
+                                       LineNumberEntry line = lns [i];
+
+                                       if (line.Offset > last_offset) {
+                                               if (last_row >= 0)
+                                                       lns [pos++] = new LineNumberEntry (
+                                                               last_row, last_offset);
+
+                                               last_row = line.Row;
+                                               last_offset = line.Offset;
+                                       } else if (line.Row > last_row) {
+                                               last_row = line.Row;
+                                       }
+                               }
+                       
+                               lines = new LineNumberEntry [count + ((last_row >= 0) ? 1 : 0)];
+                               Array.Copy (lns, lines, pos);
+                               if (last_row >= 0)
+                                       lines [pos] = new LineNumberEntry (
+                                               last_row, last_offset);
+                       }
                }
        }
 }
-