Reverting revisions 1.37, 1.38, 1.40 and 1.41.
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolTable.cs
1 //
2 // System.Diagnostics.SymbolStore/MonoSymbolTable.cs
3 //
4 // Author:
5 //   Martin Baulig (martin@gnome.org)
6 //
7 // (C) 2002 Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Collections;
14 using System.Text;
15 using System.IO;
16         
17 namespace Mono.CSharp.Debugger
18 {
19         public struct OffsetTable
20         {
21                 public const int  Version = 35;
22                 public const long Magic   = 0x45e82623fd7fa614;
23
24                 public int TotalFileSize;
25                 public int DataSectionOffset;
26                 public int DataSectionSize;
27                 public int SourceCount;
28                 public int SourceTableOffset;
29                 public int SourceTableSize;
30                 public int MethodCount;
31                 public int MethodTableOffset;
32                 public int MethodTableSize;
33                 public int TypeCount;
34
35                 internal OffsetTable (BinaryReader reader)
36                 {
37                         TotalFileSize = reader.ReadInt32 ();
38                         DataSectionOffset = reader.ReadInt32 ();
39                         DataSectionSize = reader.ReadInt32 ();
40                         SourceCount = reader.ReadInt32 ();
41                         SourceTableOffset = reader.ReadInt32 ();
42                         SourceTableSize = reader.ReadInt32 ();
43                         MethodCount = reader.ReadInt32 ();
44                         MethodTableOffset = reader.ReadInt32 ();
45                         MethodTableSize = reader.ReadInt32 ();
46                         TypeCount = reader.ReadInt32 ();
47                 }
48
49                 internal void Write (BinaryWriter bw)
50                 {
51                         bw.Write (TotalFileSize);
52                         bw.Write (DataSectionOffset);
53                         bw.Write (DataSectionSize);
54                         bw.Write (SourceCount);
55                         bw.Write (SourceTableOffset);
56                         bw.Write (SourceTableSize);
57                         bw.Write (MethodCount);
58                         bw.Write (MethodTableOffset);
59                         bw.Write (MethodTableSize);
60                         bw.Write (TypeCount);
61                 }
62
63                 public override string ToString ()
64                 {
65                         return String.Format (
66                                 "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]",
67                                 TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount,
68                                 SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset,
69                                 MethodTableSize, TypeCount);
70                 }
71         }
72
73         public struct LineNumberEntry
74         {
75                 public readonly int Row;
76                 public readonly int Offset;
77
78                 public LineNumberEntry (int row, int offset)
79                 {
80                         this.Row = row;
81                         this.Offset = offset;
82                 }
83
84                 public static LineNumberEntry Null = new LineNumberEntry (0, 0);
85
86                 internal LineNumberEntry (BinaryReader reader)
87                 {
88                         Row = reader.ReadInt32 ();
89                         Offset = reader.ReadInt32 ();
90                 }
91
92                 internal void Write (BinaryWriter bw)
93                 {
94                         bw.Write (Row);
95                         bw.Write (Offset);
96                 }
97
98                 private class OffsetComparerClass : IComparer
99                 {
100                         public int Compare (object a, object b)
101                         {
102                                 LineNumberEntry l1 = (LineNumberEntry) a;
103                                 LineNumberEntry l2 = (LineNumberEntry) b;
104
105                                 if (l1.Offset < l2.Offset)
106                                         return -1;
107                                 else if (l1.Offset > l2.Offset)
108                                         return 1;
109                                 else
110                                         return 0;
111                         }
112                 }
113
114                 private class RowComparerClass : IComparer
115                 {
116                         public int Compare (object a, object b)
117                         {
118                                 LineNumberEntry l1 = (LineNumberEntry) a;
119                                 LineNumberEntry l2 = (LineNumberEntry) b;
120
121                                 if (l1.Row < l2.Row)
122                                         return -1;
123                                 else if (l1.Row > l2.Row)
124                                         return 1;
125                                 else
126                                         return 0;
127                         }
128                 }
129
130                 public static readonly IComparer OffsetComparer = new OffsetComparerClass ();
131                 public static readonly IComparer RowComparer = new RowComparerClass ();
132
133                 public override string ToString ()
134                 {
135                         return String.Format ("[Line {0}:{1}]", Row, Offset);
136                 }
137         }
138
139         public class LexicalBlockEntry
140         {
141                 public int Index;
142                 public int StartOffset;
143                 public int EndOffset;
144
145                 public LexicalBlockEntry (int index, int start_offset)
146                 {
147                         this.Index = index;
148                         this.StartOffset = start_offset;
149                 }
150
151                 internal LexicalBlockEntry (int index, BinaryReader reader)
152                 {
153                         this.Index = index;
154                         this.StartOffset = reader.ReadInt32 ();
155                         this.EndOffset = reader.ReadInt32 ();
156                 }
157
158                 public void Close (int end_offset)
159                 {
160                         this.EndOffset = end_offset;
161                 }
162
163                 internal void Write (BinaryWriter bw)
164                 {
165                         bw.Write (StartOffset);
166                         bw.Write (EndOffset);
167                 }
168
169                 public override string ToString ()
170                 {
171                         return String.Format ("[LexicalBlock {0}:{1}]", StartOffset, EndOffset);
172                 }
173         }
174
175         public struct LocalVariableEntry
176         {
177                 public readonly string Name;
178                 public readonly FieldAttributes Attributes;
179                 public readonly byte[] Signature;
180                 public readonly int BlockIndex;
181
182                 public LocalVariableEntry (string Name, FieldAttributes Attributes, byte[] Signature,
183                                            int BlockIndex)
184                 {
185                         this.Name = Name;
186                         this.Attributes = Attributes;
187                         this.Signature = Signature;
188                         this.BlockIndex = BlockIndex;
189                 }
190
191                 internal LocalVariableEntry (BinaryReader reader)
192                 {
193                         int name_length = reader.ReadInt32 ();
194                         byte[] name = reader.ReadBytes (name_length);
195                         Name = Encoding.UTF8.GetString (name);
196                         Attributes = (FieldAttributes) reader.ReadInt32 ();
197                         int sig_length = reader.ReadInt32 ();
198                         Signature = reader.ReadBytes (sig_length);
199                         BlockIndex = reader.ReadInt32 ();
200                 }
201
202                 internal void Write (MonoSymbolFile file, BinaryWriter bw)
203                 {
204                         file.WriteString (bw, Name);
205                         bw.Write ((int) Attributes);
206                         bw.Write ((int) Signature.Length);
207                         bw.Write (Signature);
208                         bw.Write (BlockIndex);
209                 }
210
211                 public override string ToString ()
212                 {
213                         return String.Format ("[LocalVariable {0}:{1}]", Name, Attributes);
214                 }
215         }
216
217         public class SourceFileEntry
218         {
219                 MonoSymbolFile file;
220                 string file_name;
221                 ArrayList methods;
222                 ArrayList namespaces;
223                 int index, count, name_offset, method_offset;
224                 int namespace_count, nstable_offset;
225                 bool creating;
226
227                 public static int Size {
228                         get { return 24; }
229                 }
230
231                 internal SourceFileEntry (MonoSymbolFile file, string file_name)
232                 {
233                         this.file = file;
234                         this.file_name = file_name;
235                         this.index = file.AddSource (this);
236
237                         creating = true;
238                         methods = new ArrayList ();
239                         namespaces = new ArrayList ();
240                 }
241
242                 public void DefineMethod (MethodBase method, int token, LocalVariableEntry[] locals,
243                                           LineNumberEntry[] lines, LexicalBlockEntry[] blocks,
244                                           int start, int end, int namespace_id)
245                 {
246                         if (!creating)
247                                 throw new InvalidOperationException ();
248
249                         MethodEntry entry = new MethodEntry (
250                                 file, this, method, token, locals, lines, blocks, start, end, namespace_id);
251
252                         methods.Add (entry);
253                         file.AddMethod (entry);
254                 }
255
256                 public int DefineNamespace (string name, string[] using_clauses, int parent)
257                 {
258                         if (!creating)
259                                 throw new InvalidOperationException ();
260
261                         int index = file.GetNextNamespaceIndex ();
262                         NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
263                         namespaces.Add (ns);
264                         return index;
265                 }
266
267                 internal void WriteData (BinaryWriter bw)
268                 {
269                         name_offset = (int) bw.BaseStream.Position;
270                         file.WriteString (bw, file_name);
271
272                         ArrayList list = new ArrayList ();
273                         foreach (MethodEntry entry in methods)
274                                 list.Add (entry.Write (file, bw));
275                         list.Sort ();
276                         count = list.Count;
277
278                         method_offset = (int) bw.BaseStream.Position;
279                         foreach (MethodSourceEntry method in list)
280                                 method.Write (bw);
281
282                         namespace_count = namespaces.Count;
283                         nstable_offset = (int) bw.BaseStream.Position;
284                         foreach (NamespaceEntry ns in namespaces)
285                                 ns.Write (file, bw);
286                 }
287
288                 internal void Write (BinaryWriter bw)
289                 {
290                         bw.Write (index);
291                         bw.Write (count);
292                         bw.Write (namespace_count);
293                         bw.Write (name_offset);
294                         bw.Write (method_offset);
295                         bw.Write (nstable_offset);
296                 }
297
298                 internal SourceFileEntry (MonoSymbolFile file, BinaryReader reader)
299                 {
300                         this.file = file;
301
302                         index = reader.ReadInt32 ();
303                         count = reader.ReadInt32 ();
304                         namespace_count = reader.ReadInt32 ();
305                         name_offset = reader.ReadInt32 ();
306                         method_offset = reader.ReadInt32 ();
307                         nstable_offset = reader.ReadInt32 ();
308
309                         file_name = file.ReadString (name_offset);
310                 }
311
312                 public int Index {
313                         get { return index; }
314                 }
315
316                 public string FileName {
317                         get { return file_name; }
318                 }
319
320                 public MethodSourceEntry[] Methods {
321                         get {
322                                 if (creating)
323                                         throw new InvalidOperationException ();
324
325                                 BinaryReader reader = file.BinaryReader;
326                                 int old_pos = (int) reader.BaseStream.Position;
327
328                                 reader.BaseStream.Position = method_offset;
329                                 ArrayList list = new ArrayList ();
330                                 for (int i = 0; i < count; i ++)
331                                         list.Add (new MethodSourceEntry (reader));
332                                 reader.BaseStream.Position = old_pos;
333
334                                 MethodSourceEntry[] retval = new MethodSourceEntry [count];
335                                 list.CopyTo (retval, 0);
336                                 return retval;
337                         }
338                 }
339
340                 public override string ToString ()
341                 {
342                         return String.Format ("SourceFileEntry ({0}:{1}:{2})", index, file_name, count);
343                 }
344         }
345
346         public struct MethodSourceEntry : IComparable
347         {
348                 public readonly int Index;
349                 public readonly int FileOffset;
350                 public readonly int StartRow;
351                 public readonly int EndRow;
352
353                 public MethodSourceEntry (int index, int file_offset, int start, int end)
354                 {
355                         this.Index = index;
356                         this.FileOffset = file_offset;
357                         this.StartRow = start;
358                         this.EndRow = end;
359                 }
360
361                 internal MethodSourceEntry (BinaryReader reader)
362                 {
363                         Index = reader.ReadInt32 ();
364                         FileOffset = reader.ReadInt32 ();
365                         StartRow = reader.ReadInt32 ();
366                         EndRow = reader.ReadInt32 ();
367                 }
368
369                 public static int Size {
370                         get { return 16; }
371                 }
372
373                 internal void Write (BinaryWriter bw)
374                 {
375                         bw.Write (Index);
376                         bw.Write (FileOffset);
377                         bw.Write (StartRow);
378                         bw.Write (EndRow);
379                 }
380
381                 public int CompareTo (object obj)
382                 {
383                         MethodSourceEntry method = (MethodSourceEntry) obj;
384
385                         if (method.StartRow < StartRow)
386                                 return -1;
387                         else if (method.StartRow > StartRow)
388                                 return 1;
389                         else
390                                 return 0;
391                 }
392
393                 public override string ToString ()
394                 {
395                         return String.Format ("MethodSourceEntry ({0}:{1}:{2}:{3})",
396                                               Index, FileOffset, StartRow, EndRow);
397                 }
398         }
399
400         public struct MethodIndexEntry
401         {
402                 public readonly int FileOffset;
403                 public readonly int FullNameOffset;
404                 public readonly int Token;
405
406                 public static int Size {
407                         get { return 12; }
408                 }
409
410                 public MethodIndexEntry (int offset, int name_offset, int token)
411                 {
412                         this.FileOffset = offset;
413                         this.FullNameOffset = name_offset;
414                         this.Token = token;
415                 }
416
417                 internal MethodIndexEntry (BinaryReader reader)
418                 {
419                         FileOffset = reader.ReadInt32 ();
420                         FullNameOffset = reader.ReadInt32 ();
421                         Token = reader.ReadInt32 ();
422                 }
423
424                 internal void Write (BinaryWriter bw)
425                 {
426                         bw.Write (FileOffset);
427                         bw.Write (FullNameOffset);
428                         bw.Write (Token);
429                 }
430
431                 public override string ToString ()
432                 {
433                         return String.Format ("MethodIndexEntry ({0}:{1}:{2:x})",
434                                               FileOffset, FullNameOffset, Token);
435                 }
436         }
437
438         public class MethodEntry
439         {
440                 #region This is actually written to the symbol file
441                 public readonly int SourceFileIndex;
442                 public readonly int Token;
443                 public readonly int StartRow;
444                 public readonly int EndRow;
445                 public readonly int ClassTypeIndex;
446                 public readonly int NumParameters;
447                 public readonly int NumLocals;
448                 public readonly int NumLineNumbers;
449                 public readonly int NamespaceID;
450                 public readonly bool LocalNamesAmbiguous;
451
452                 int NameOffset;
453                 int FullNameOffset;
454                 int TypeIndexTableOffset;
455                 int LocalVariableTableOffset;
456                 int LineNumberTableOffset;
457                 int NumLexicalBlocks;
458                 int LexicalBlockTableOffset;
459                 #endregion
460
461                 int file_offset;
462                 string name;
463                 string full_name;
464
465                 public readonly int Index;
466                 public readonly SourceFileEntry SourceFile;
467                 public readonly LineNumberEntry[] LineNumbers;
468                 public readonly int[] ParamTypeIndices;
469                 public readonly int[] LocalTypeIndices;
470                 public readonly LocalVariableEntry[] Locals;
471                 public readonly Type[] LocalTypes;
472                 public readonly LexicalBlockEntry[] LexicalBlocks;
473
474                 public readonly MonoSymbolFile SymbolFile;
475
476                 public static int Size {
477                         get { return 52; }
478                 }
479
480                 public string Name {
481                         get { return name; }
482                 }
483
484                 public string FullName {
485                         get { return full_name; }
486                 }
487
488                 public MethodBase MethodBase {
489                         get { return SymbolFile.Assembly.MonoDebugger_GetMethod (Token); }
490                 }
491
492                 internal MethodEntry (MonoSymbolFile file, BinaryReader reader, int index)
493                 {
494                         this.SymbolFile = file;
495                         this.Index = index;
496                         SourceFileIndex = reader.ReadInt32 ();
497                         Token = reader.ReadInt32 ();
498                         StartRow = reader.ReadInt32 ();
499                         EndRow = reader.ReadInt32 ();
500                         ClassTypeIndex = reader.ReadInt32 ();
501                         NumParameters = reader.ReadInt32 ();
502                         NumLocals = reader.ReadInt32 ();
503                         NumLineNumbers = reader.ReadInt32 ();
504                         NameOffset = reader.ReadInt32 ();
505                         FullNameOffset = reader.ReadInt32 ();
506                         TypeIndexTableOffset = reader.ReadInt32 ();
507                         LocalVariableTableOffset = reader.ReadInt32 ();
508                         LineNumberTableOffset = reader.ReadInt32 ();
509                         NumLexicalBlocks = reader.ReadInt32 ();
510                         LexicalBlockTableOffset = reader.ReadInt32 ();
511                         NamespaceID = reader.ReadInt32 ();
512                         LocalNamesAmbiguous = reader.ReadInt32 () != 0;
513
514                         name = file.ReadString (NameOffset);
515                         full_name = file.ReadString (FullNameOffset);
516
517                         SourceFile = file.GetSourceFile (SourceFileIndex);
518
519                         if (LineNumberTableOffset != 0) {
520                                 long old_pos = reader.BaseStream.Position;
521                                 reader.BaseStream.Position = LineNumberTableOffset;
522
523                                 LineNumbers = new LineNumberEntry [NumLineNumbers];
524
525                                 for (int i = 0; i < NumLineNumbers; i++)
526                                         LineNumbers [i] = new LineNumberEntry (reader);
527
528                                 reader.BaseStream.Position = old_pos;
529                         }
530
531                         if (LocalVariableTableOffset != 0) {
532                                 long old_pos = reader.BaseStream.Position;
533                                 reader.BaseStream.Position = LocalVariableTableOffset;
534
535                                 Locals = new LocalVariableEntry [NumLocals];
536                                 LocalTypes = new Type [NumLocals];
537
538                                 Assembly ass = file.Assembly;
539
540                                 for (int i = 0; i < NumLocals; i++) {
541                                         Locals [i] = new LocalVariableEntry (reader);
542                                         LocalTypes [i] = ass.MonoDebugger_GetLocalTypeFromSignature (
543                                                 Locals [i].Signature);
544                                 }
545
546                                 reader.BaseStream.Position = old_pos;
547                         }
548
549                         if (TypeIndexTableOffset != 0) {
550                                 long old_pos = reader.BaseStream.Position;
551                                 reader.BaseStream.Position = TypeIndexTableOffset;
552
553                                 ParamTypeIndices = new int [NumParameters];
554                                 LocalTypeIndices = new int [NumLocals];
555
556                                 for (int i = 0; i < NumParameters; i++)
557                                         ParamTypeIndices [i] = reader.ReadInt32 ();
558                                 for (int i = 0; i < NumLocals; i++)
559                                         LocalTypeIndices [i] = reader.ReadInt32 ();
560
561                                 reader.BaseStream.Position = old_pos;
562                         }
563
564                         if (LexicalBlockTableOffset != 0) {
565                                 long old_pos = reader.BaseStream.Position;
566                                 reader.BaseStream.Position = LexicalBlockTableOffset;
567
568                                 LexicalBlocks = new LexicalBlockEntry [NumLexicalBlocks];
569                                 for (int i = 0; i < NumLexicalBlocks; i++)
570                                         LexicalBlocks [i] = new LexicalBlockEntry (i, reader);
571
572                                 reader.BaseStream.Position = old_pos;
573                         }
574                 }
575
576                 internal MethodEntry (MonoSymbolFile file, SourceFileEntry source, MethodBase method,
577                                       int token, LocalVariableEntry[] locals, LineNumberEntry[] lines,
578                                       LexicalBlockEntry[] blocks, int start_row, int end_row,
579                                       int namespace_id)
580                 {
581                         this.SymbolFile = file;
582                         Index = file.GetNextMethodIndex ();
583
584                         Token = token;
585                         SourceFileIndex = source.Index;
586                         SourceFile = source;
587                         StartRow = start_row;
588                         EndRow = end_row;
589                         NamespaceID = namespace_id;
590                         LexicalBlocks = blocks;
591                         NumLexicalBlocks = LexicalBlocks.Length;
592
593                         LineNumbers = BuildLineNumberTable (lines);
594                         NumLineNumbers = LineNumbers.Length;
595
596                         ParameterInfo[] parameters = method.GetParameters ();
597                         if (parameters == null)
598                                 parameters = new ParameterInfo [0];
599                         
600                         if (parameters.Length == 0)
601                                 full_name = method.DeclaringType.FullName + "." + method.Name + "()";
602                         else if (parameters.Length == 1)
603                                 full_name = method.DeclaringType.FullName + "." + method.Name + "(" + parameters [0].ParameterType.FullName +  ")";
604                         else if (parameters.Length == 2)
605                                 full_name = method.DeclaringType.FullName + "." + method.Name + "(" + parameters [0].ParameterType.FullName + "," + parameters [1].ParameterType.FullName + ")";
606                         else {
607                                 StringBuilder sb = new StringBuilder ();
608                                 sb.Append (method.DeclaringType.FullName);
609                                 sb.Append (".");
610                                 sb.Append (method.Name);
611                                 sb.Append ("(");
612                                 for (int i = 0; i < parameters.Length; i++) {
613                                         if (i > 0)
614                                                 sb.Append (",");
615                                         sb.Append (parameters [i].ParameterType.FullName);
616                                 }
617                                 sb.Append (")");
618                                 full_name = sb.ToString ();
619                         }
620
621                         name = method.Name;
622                         
623                         NumParameters = parameters.Length;
624                         ParamTypeIndices = new int [NumParameters];
625                         for (int i = 0; i < NumParameters; i++)
626                                 ParamTypeIndices [i] = file.DefineType (parameters [i].ParameterType);
627
628                         NumLocals = locals.Length;
629                         Locals = locals;
630
631                         if (NumLocals <= 32) {
632                                 // Most of the time, the O(n^2) factor is actually
633                                 // less than the cost of allocating the hash table,
634                                 // 32 is a rough number obtained through some testing.
635                                 
636                                 for (int i = 0; i < NumLocals; i ++) {
637                                         string nm = locals [i].Name;
638                                         
639                                         for (int j = i + 1; j < NumLocals; j ++) {
640                                                 if (locals [j].Name == nm) {
641                                                         LocalNamesAmbiguous = true;
642                                                         goto locals_check_done;
643                                                 }
644                                         }
645                                 }
646                         locals_check_done :
647                                 ;
648                         } else {
649                                 Hashtable local_names = new Hashtable ();
650                                 foreach (LocalVariableEntry local in locals) {
651                                         if (local_names.Contains (local.Name)) {
652                                                 LocalNamesAmbiguous = true;
653                                                 break;
654                                         }
655                                         local_names.Add (local.Name, local);
656                                 }
657                         }
658
659                         LocalTypeIndices = new int [NumLocals];
660                         for (int i = 0; i < NumLocals; i++)
661                                 LocalTypeIndices [i] = file.GetNextTypeIndex ();
662
663                         ClassTypeIndex = file.DefineType (method.ReflectedType);
664                 }
665
666                 LineNumberEntry[] BuildLineNumberTable (LineNumberEntry[] line_numbers)
667                 {
668                         ArrayList list = new ArrayList ();
669                         int last_offset = -1;
670                         int last_row = -1;
671
672                         for (int i = 0; i < line_numbers.Length; i++) {
673                                 LineNumberEntry line = (LineNumberEntry) line_numbers [i];
674
675                                 if (line.Offset > last_offset) {
676                                         if (last_row >= 0)
677                                                 list.Add (new LineNumberEntry (last_row, last_offset));
678                                         last_row = line.Row;
679                                         last_offset = line.Offset;
680                                 } else if (line.Row > last_row) {
681                                         last_row = line.Row;
682                                 }
683                         }
684
685                         if (last_row >= 0)
686                                 list.Add (new LineNumberEntry (last_row, last_offset));
687
688                         LineNumberEntry[] retval = new LineNumberEntry [list.Count];
689                         list.CopyTo (retval, 0);
690                         return retval;
691                 }
692
693                 internal MethodSourceEntry Write (MonoSymbolFile file, BinaryWriter bw)
694                 {
695                         NameOffset = (int) bw.BaseStream.Position;
696                         file.WriteString (bw, name);
697
698                         FullNameOffset = (int) bw.BaseStream.Position;
699                         file.WriteString (bw, full_name);
700
701                         TypeIndexTableOffset = (int) bw.BaseStream.Position;
702
703                         for (int i = 0; i < NumParameters; i++)
704                                 bw.Write (ParamTypeIndices [i]);
705                         for (int i = 0; i < NumLocals; i++)
706                                 bw.Write (LocalTypeIndices [i]);
707
708                         LocalVariableTableOffset = (int) bw.BaseStream.Position;
709                         for (int i = 0; i < NumLocals; i++)
710                                 Locals [i].Write (file, bw);
711                         file.LocalCount += NumLocals;
712
713                         LineNumberTableOffset = (int) bw.BaseStream.Position;
714                         for (int i = 0; i < NumLineNumbers; i++)
715                                 LineNumbers [i].Write (bw);
716                         file.LineNumberCount += NumLineNumbers;
717
718                         LexicalBlockTableOffset = (int) bw.BaseStream.Position;
719                         for (int i = 0; i < NumLexicalBlocks; i++)
720                                 LexicalBlocks [i].Write (bw);
721                         file_offset = (int) bw.BaseStream.Position;
722
723                         bw.Write (SourceFileIndex);
724                         bw.Write (Token);
725                         bw.Write (StartRow);
726                         bw.Write (EndRow);
727                         bw.Write (ClassTypeIndex);
728                         bw.Write (NumParameters);
729                         bw.Write (NumLocals);
730                         bw.Write (NumLineNumbers);
731                         bw.Write (NameOffset);
732                         bw.Write (FullNameOffset);
733                         bw.Write (TypeIndexTableOffset);
734                         bw.Write (LocalVariableTableOffset);
735                         bw.Write (LineNumberTableOffset);
736                         bw.Write (NumLexicalBlocks);
737                         bw.Write (LexicalBlockTableOffset);
738                         bw.Write (NamespaceID);
739                         bw.Write (LocalNamesAmbiguous ? 1 : 0);
740
741                         return new MethodSourceEntry (Index, file_offset, StartRow, EndRow);
742                 }
743
744                 internal void WriteIndex (BinaryWriter bw)
745                 {
746                         new MethodIndexEntry (file_offset, FullNameOffset, Token).Write (bw);
747                 }
748
749                 public override string ToString ()
750                 {
751                         return String.Format ("[Method {0}:{1}:{2}:{3}:{4} - {7}:{8}:{9}:{10} - {5} - {6}]",
752                                               Index, Token, SourceFileIndex, StartRow, EndRow,
753                                               SourceFile, FullName, ClassTypeIndex, NumParameters,
754                                               NumLocals, NumLineNumbers);
755                 }
756         }
757
758         public struct NamespaceEntry
759         {
760                 public readonly string Name;
761                 public readonly int Index;
762                 public readonly int Parent;
763                 public readonly string[] UsingClauses;
764
765                 public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
766                 {
767                         this.Name = name;
768                         this.Index = index;
769                         this.Parent = parent;
770                         this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
771                 }
772
773                 internal void Write (MonoSymbolFile file, BinaryWriter bw)
774                 {
775                         file.WriteString (bw, Name);
776                         bw.Write (Index);
777                         bw.Write (Parent);
778                         bw.Write (UsingClauses.Length);
779                         foreach (string uc in UsingClauses)
780                                 file.WriteString (bw, uc);
781                 }
782
783                 public override string ToString ()
784                 {
785                         return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);
786                 }
787         }
788 }