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.SymbolWriterOld
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);
185
// We mmap the file, so unlink the previous version since it may be in use
186
File.Delete (filename);
188
// We can safely ignore
190
using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
191
file.CreateSymbolFile (guid, fs);
195
protected class SourceMethod
197
LineNumberEntry [] lines;
198
private ArrayList _locals;
199
private ArrayList _blocks;
200
private Stack _block_stack;
201
private int next_block_id = 0;
202
private ISourceMethod _method;
203
private ISourceFile _file;
204
private LineNumberEntry _start, _end;
206
private LexicalBlockEntry _implicit_block;
208
public SourceMethod (ISourceFile file, ISourceMethod method,
209
int startLine, int startColumn,
210
int endLine, int endColumn)
213
this._method = method;
215
this._start = new LineNumberEntry (startLine, 0);
216
this._end = new LineNumberEntry (endLine, 0);
218
this._implicit_block = new LexicalBlockEntry (0, 0);
221
public void StartBlock (int startOffset)
223
LexicalBlockEntry block = new LexicalBlockEntry (
224
++next_block_id, startOffset);
225
if (_block_stack == null)
226
_block_stack = new Stack ();
227
_block_stack.Push (block);
229
_blocks = new ArrayList ();
233
public void EndBlock (int endOffset)
235
LexicalBlockEntry block =
236
(LexicalBlockEntry) _block_stack.Pop ();
238
block.Close (endOffset);
241
public LexicalBlockEntry[] Blocks {
244
return new LexicalBlockEntry [0];
246
LexicalBlockEntry[] retval =
247
new LexicalBlockEntry [_blocks.Count];
248
_blocks.CopyTo (retval, 0);
254
public LexicalBlockEntry CurrentBlock {
256
if ((_block_stack != null) && (_block_stack.Count > 0))
257
return (LexicalBlockEntry) _block_stack.Peek ();
259
return _implicit_block;
263
public LineNumberEntry[] Lines {
269
public LocalVariableEntry[] Locals {
272
return new LocalVariableEntry [0];
274
LocalVariableEntry[] retval =
275
new LocalVariableEntry [_locals.Count];
276
_locals.CopyTo (retval, 0);
282
public void AddLocal (int index, string name, byte[] signature)
285
_locals = new ArrayList ();
286
_locals.Add (new LocalVariableEntry (
287
index, name, signature, CurrentBlock.Index));
290
public ISourceFile SourceFile {
291
get { return _file; }
294
public ISourceMethod Method {
295
get { return _method; }
298
public LineNumberEntry Start {
299
get { return _start; }
302
public LineNumberEntry End {
307
// Passes on the lines from the MonoSymbolWriter. This method is
308
// free to mutate the lns array, and it does.
310
internal void SetLineNumbers (LineNumberEntry [] lns, int count)
314
int last_offset = -1;
316
for (int i = 0; i < count; i++) {
317
LineNumberEntry line = lns [i];
319
if (line.Offset > last_offset) {
321
lns [pos++] = new LineNumberEntry (
322
last_row, last_offset);
325
last_offset = line.Offset;
326
} else if (line.Row > last_row) {
331
lines = new LineNumberEntry [count + ((last_row >= 0) ? 1 : 0)];
332
Array.Copy (lns, lines, pos);
334
lines [pos] = new LineNumberEntry (
335
last_row, last_offset);