2 // location.cs: Keeps track of the location of source code entity
7 // (C) 2001 Ximian, Inc.
12 using System.Collections;
13 using System.Diagnostics.SymbolStore;
15 namespace Mono.CSharp {
17 /// This is one single source file.
20 /// This is intentionally a class and not a struct since we need
21 /// to pass this by reference.
23 public sealed class SourceFile {
24 public readonly string Name;
25 public readonly string Path;
26 public readonly int Index;
27 public ISymbolDocumentWriter SymbolDocument;
29 public SourceFile (string name, string path, int index)
38 /// Keeps track of the location in the program
42 /// This uses a compact representation and a couple of auxiliary
43 /// structures to keep track of tokens to (file,line) mappings.
45 /// We could probably also keep track of columns by storing those
46 /// in 8 bits (and say, map anything after char 255 to be `255+').
48 public struct Location {
51 static ArrayList source_list;
52 static Hashtable source_files;
53 static int source_bits;
54 static int source_mask;
55 static int source_count;
56 static int module_base;
57 static int current_source;
59 public readonly static Location Null;
63 source_files = new Hashtable ();
64 source_list = new ArrayList ();
71 // This must be called before parsing/tokenizing any files.
73 static public void AddFile (string name)
75 string path = Path.GetFullPath (name);
77 if (source_files.Contains (path)){
80 "Source file `" + name + "' specified multiple times");
84 source_files.Add (path, ++source_count);
85 source_list.Add (new SourceFile (name, path, source_count));
88 static public SourceFile[] SourceFiles {
90 SourceFile[] retval = new SourceFile [source_list.Count];
91 source_list.CopyTo (retval, 0);
96 static int log2 (int number)
108 // After adding all source files we want to compile with AddFile(), this method
109 // must be called to `reserve' an appropriate number of bits in the token for the
110 // source file. We reserve some extra space for files we encounter via #line
111 // directives while parsing.
113 static public void Initialize ()
115 source_bits = log2 (source_list.Count) + 2;
116 source_mask = (1 << source_bits) - 1;
120 // This is used when we encounter a #line preprocessing directive.
122 static public SourceFile LookupFile (string name)
124 string path = Path.GetFullPath (name);
126 if (!source_files.Contains (path)) {
127 if (source_count >= (1 << source_bits))
128 return new SourceFile (name, path, 0);
130 source_files.Add (path, ++source_count);
131 SourceFile retval = new SourceFile (name, path, source_count);
132 source_list.Add (retval);
136 int index = (int) source_files [path];
137 return (SourceFile) source_list [index - 1];
140 static public void Push (SourceFile file)
142 current_source = file.Index;
143 module_base = current_source << source_bits;
147 // If we're compiling with debugging support, this is called between parsing and
148 // code generation to register all the source files with the symbol writer. //
150 static public void DefineSymbolDocuments (SymbolWriter symwriter)
152 foreach (SourceFile file in source_list)
153 file.SymbolDocument = symwriter.DefineDocument (file.Path);
156 public Location (int row)
161 token = current_source + (row << source_bits);
164 public override string ToString ()
166 return Name + ": (" + Row + ")";
170 /// Whether the Location is Null
172 static public bool IsNull (Location l)
179 int index = token & source_mask;
180 if ((token == 0) || (index == 0))
183 SourceFile file = (SourceFile) source_list [index - 1];
193 return token >> source_bits;
199 return token & source_mask;
203 // The ISymbolDocumentWriter interface is used by the symbol writer to
204 // describe a single source file - for each source file there's exactly
205 // one corresponding ISymbolDocumentWriter instance.
207 // This class has an internal hash table mapping source document names
208 // to such ISymbolDocumentWriter instances - so there's exactly one
209 // instance per document.
211 // This property returns the ISymbolDocumentWriter instance which belongs
212 // to the location's source file.
214 // If we don't have a symbol writer, this property is always null.
215 public ISymbolDocumentWriter SymbolDocument {
217 int index = token & source_mask;
220 SourceFile file = (SourceFile) source_list [index - 1];
221 return file.SymbolDocument;