2 // Mono.CSharp.Debugger/MonoSymbolWriter.cs
5 // Martin Baulig (martin@ximian.com)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Runtime.CompilerServices;
36 using System.Collections;
39 namespace Mono.CompilerServices.SymbolWriter
41 public interface ISourceFile
43 SourceFileEntry Entry {
48 public interface ISourceMethod
63 public class MonoSymbolWriter
65 protected ArrayList locals = null;
66 protected ArrayList methods = null;
67 protected ArrayList sources = null;
68 protected readonly MonoSymbolFile file;
69 private string filename = null;
71 LineNumberEntry [] current_method_lines;
72 int current_method_lines_pos = 0;
74 internal ISourceFile[] Sources {
76 ISourceFile[] retval = new ISourceFile [sources.Count];
77 sources.CopyTo (retval, 0);
82 private SourceMethod current_method = null;
84 public MonoSymbolWriter (string filename)
86 this.methods = new ArrayList ();
87 this.sources = new ArrayList ();
88 this.locals = new ArrayList ();
89 this.file = new MonoSymbolFile ();
91 this.filename = filename + ".mdb";
93 this.current_method_lines = new LineNumberEntry [50];
96 public void CloseNamespace ()
99 public void DefineLocalVariable (int index, string name, byte[] signature)
101 if (current_method == null)
104 current_method.AddLocal (index, name, signature);
107 public void MarkSequencePoint (int offset, int line, int column)
109 if (current_method == null)
112 if (current_method_lines_pos == current_method_lines.Length) {
113 LineNumberEntry [] tmp = current_method_lines;
114 current_method_lines = new LineNumberEntry [current_method_lines.Length * 2];
115 Array.Copy (tmp, current_method_lines, current_method_lines_pos);
118 current_method_lines [current_method_lines_pos++] = new LineNumberEntry (line, offset);
121 public void OpenMethod (ISourceFile file, ISourceMethod method,
122 int startRow, int startColumn,
123 int endRow, int endColumn)
125 SourceMethod source = new SourceMethod (
126 file, method, startRow, startColumn, endRow, endColumn);
128 current_method = source;
129 methods.Add (current_method);
132 public void CloseMethod ()
134 current_method.SetLineNumbers (
135 current_method_lines, current_method_lines_pos);
136 current_method_lines_pos = 0;
138 current_method = null;
141 public SourceFileEntry DefineDocument (string url)
143 SourceFileEntry entry = new SourceFileEntry (file, url);
148 public int DefineNamespace (string name, SourceFileEntry source,
149 string[] using_clauses, int parent)
151 if ((source == null) || (using_clauses == null))
152 throw new NullReferenceException ();
154 return source.DefineNamespace (name, using_clauses, parent);
157 public int OpenScope (int startOffset)
159 if (current_method == null)
162 current_method.StartBlock (startOffset);
166 public void CloseScope (int endOffset)
168 if (current_method == null)
171 current_method.EndBlock (endOffset);
174 public void WriteSymbolFile (Guid guid)
176 foreach (SourceMethod method in methods) {
177 method.SourceFile.Entry.DefineMethod (
178 method.Method.Name, method.Method.Token,
179 method.Locals, method.Lines, method.Blocks,
180 method.Start.Row, method.End.Row,
181 method.Method.NamespaceID);
184 using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
185 file.CreateSymbolFile (guid, fs);
189 protected class SourceMethod
191 LineNumberEntry [] lines;
192 private ArrayList _locals;
193 private ArrayList _blocks;
194 private Stack _block_stack;
195 private int next_block_id = 0;
196 private ISourceMethod _method;
197 private ISourceFile _file;
198 private LineNumberEntry _start, _end;
200 private LexicalBlockEntry _implicit_block;
202 public SourceMethod (ISourceFile file, ISourceMethod method,
203 int startLine, int startColumn,
204 int endLine, int endColumn)
207 this._method = method;
209 this._start = new LineNumberEntry (startLine, 0);
210 this._end = new LineNumberEntry (endLine, 0);
212 this._implicit_block = new LexicalBlockEntry (0, 0);
215 public void StartBlock (int startOffset)
217 LexicalBlockEntry block = new LexicalBlockEntry (
218 ++next_block_id, startOffset);
219 if (_block_stack == null)
220 _block_stack = new Stack ();
221 _block_stack.Push (block);
223 _blocks = new ArrayList ();
227 public void EndBlock (int endOffset)
229 LexicalBlockEntry block =
230 (LexicalBlockEntry) _block_stack.Pop ();
232 block.Close (endOffset);
235 public LexicalBlockEntry[] Blocks {
238 return new LexicalBlockEntry [0];
240 LexicalBlockEntry[] retval =
241 new LexicalBlockEntry [_blocks.Count];
242 _blocks.CopyTo (retval, 0);
248 public LexicalBlockEntry CurrentBlock {
250 if ((_block_stack != null) && (_block_stack.Count > 0))
251 return (LexicalBlockEntry) _block_stack.Peek ();
253 return _implicit_block;
257 public LineNumberEntry[] Lines {
263 public LocalVariableEntry[] Locals {
266 return new LocalVariableEntry [0];
268 LocalVariableEntry[] retval =
269 new LocalVariableEntry [_locals.Count];
270 _locals.CopyTo (retval, 0);
276 public void AddLocal (int index, string name, byte[] signature)
279 _locals = new ArrayList ();
280 _locals.Add (new LocalVariableEntry (
281 index, name, signature, CurrentBlock.Index));
284 public ISourceFile SourceFile {
285 get { return _file; }
288 public ISourceMethod Method {
289 get { return _method; }
292 public LineNumberEntry Start {
293 get { return _start; }
296 public LineNumberEntry End {
301 // Passes on the lines from the MonoSymbolWriter. This method is
302 // free to mutate the lns array, and it does.
304 internal void SetLineNumbers (LineNumberEntry [] lns, int count)
308 int last_offset = -1;
310 for (int i = 0; i < count; i++) {
311 LineNumberEntry line = lns [i];
313 if (line.Offset > last_offset) {
315 lns [pos++] = new LineNumberEntry (
316 last_row, last_offset);
319 last_offset = line.Offset;
320 } else if (line.Row > last_row) {
325 lines = new LineNumberEntry [count + ((last_row >= 0) ? 1 : 0)];
326 Array.Copy (lns, lines, pos);
328 lines [pos] = new LineNumberEntry (
329 last_row, last_offset);