This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / mbas / location.cs
1 //
2 // location.cs: Keeps track of the location of source code entity
3 //
4 // Author:
5 //   Miguel de Icaza
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9
10 using System;
11 using System.IO;
12 using System.Collections;
13 using System.Diagnostics.SymbolStore;
14
15 namespace Mono.MonoBASIC {
16
17         /// <summary>
18         ///   Keeps track of the location in the program
19         /// </summary>
20         ///
21         /// <remarks>
22         ///   This uses a compact representation and a couple of auxiliary
23         ///   structures to keep track of tokens to (file,line) mappings.
24         ///
25         ///   We could probably also keep track of columns by storing those
26         ///   in 8 bits (and say, map anything after char 255 to be `255+').
27         /// </remarks>
28         public struct Location {
29                 public int token; 
30
31                 static Hashtable map;
32                 static Hashtable sym_docs;
33                 static ArrayList list;
34                 static int global_count;
35                 static int module_base;
36
37                 public readonly static Location Null;
38                 
39                 static Location ()
40                 {
41                         map = new Hashtable ();
42                         list = new ArrayList ();
43                         sym_docs = new Hashtable ();
44                         global_count = 0;
45                         module_base = 0;
46                         Null.token = -1;
47                 }
48
49                 static public void Push (string name)
50                 {
51                         map.Remove (global_count);
52                         map.Add (global_count, name);
53                         list.Add (global_count);
54                         module_base = global_count;
55                 }
56                 
57                 public Location (int row, int col)
58                 {
59                         if (row < 0 || col <  0)
60                                 token = -1;
61                         else {
62                                 if (col > 255)
63                                         col = 255;
64                                 token = module_base + (row << 8) + col;
65                                 if (global_count < token)
66                                         global_count = token;
67                         }
68                 }
69
70                 public override string ToString ()
71                 {
72                         return Name + ": (" + Row + ")";
73                 }
74                 
75                 /// <summary>
76                 ///   Whether the Location is Null
77                 /// </summary>
78                 static public bool IsNull (Location l)
79                 {
80                         return l.token == -1;
81                 }
82
83                 public string Name {
84                         get {
85                                 int best = 0;
86                                 
87                                 if (token < 0)
88                                         return "Internal";
89
90                                 foreach (int b in list){
91                                         if (token > b)
92                                                 best = b;
93                                 }
94                                 return (string) map [best];
95                         }
96                 }
97
98                 public int Row {
99                         get {
100                                 int best = 0;
101                                 
102                                 if (token < 0)
103                                         return 1;
104                                 
105                                 foreach (int b in list){
106                                         if (token > b)
107                                                 best = b;
108                                 }
109                                 return (token - best) >> 8;
110                         }
111                 }
112
113                 public int Col {
114                         get {
115                                 int best = 0;
116                                 
117                                 if (token < 0)
118                                         return 1;
119                                 
120                                 foreach (int b in list){
121                                         if (token > b)
122                                                 best = b;
123                                 }
124                                 return (token - best) & 0xFF;
125                         }
126                 }
127
128                 // The ISymbolDocumentWriter interface is used by the symbol writer to
129                 // describe a single source file - for each source file there's exactly
130                 // one corresponding ISymbolDocumentWriter instance.
131                 //
132                 // This class has an internal hash table mapping source document names
133                 // to such ISymbolDocumentWriter instances - so there's exactly one
134                 // instance per document.
135                 //
136                 // This property returns the ISymbolDocumentWriter instance which belongs
137                 // to the location's source file.
138                 //
139                 // If we don't have a symbol writer, this property is always null.
140                 public ISymbolDocumentWriter SymbolDocument {
141                         get {
142                                 ISymbolWriter sw = CodeGen.SymbolWriter;
143                                 ISymbolDocumentWriter doc;
144
145                                 if (token < 0)
146                                         return null;
147
148                                 // If we don't have a symbol writer, return null.
149                                 if (sw == null)
150                                         return null;
151
152                                 string path = Path.GetFullPath (Name);
153
154                                 if (sym_docs.Contains (path))
155                                         // If we already created an ISymbolDocumentWriter
156                                         // instance for this document, return it.
157                                         doc = (ISymbolDocumentWriter) sym_docs [path];
158                                 else {
159                                         // Create a new ISymbolDocumentWriter instance and
160                                         // store it in the hash table.
161                                         doc = sw.DefineDocument (path, SymLanguageType.Basic,
162                                                                  SymLanguageVendor.Microsoft,
163                                                                  SymDocumentType.Text);
164
165                                         sym_docs.Add (path, doc);
166                                 }
167
168                                 return doc;
169                         }
170                 }
171         }
172 }