-//
-// location.cs: Keeps track of the location of source code entity
-//
-// Author:
-// Miguel de Icaza
-//
-// (C) 2001 Ximian, Inc.
-//
-
-using System;
-using System.IO;
-using System.Collections;
-using System.Diagnostics.SymbolStore;
-
-namespace Mono.MonoBASIC {
-
- /// <summary>
- /// Keeps track of the location in the program
- /// </summary>
- ///
- /// <remarks>
- /// This uses a compact representation and a couple of auxiliary
- /// structures to keep track of tokens to (file,line) mappings.
- ///
- /// We could probably also keep track of columns by storing those
- /// in 8 bits (and say, map anything after char 255 to be `255+').
- /// </remarks>
- public struct Location {
- public int token;
-
- static Hashtable map;
- static Hashtable sym_docs;
- static ArrayList list;
- static int global_count;
- static int module_base;
-
- public readonly static Location Null;
-
- static Location ()
- {
- map = new Hashtable ();
- list = new ArrayList ();
- sym_docs = new Hashtable ();
- global_count = 0;
- module_base = 0;
- Null.token = -1;
- }
-
- static public void Push (string name)
- {
- map.Remove (global_count);
- map.Add (global_count, name);
- list.Add (global_count);
- module_base = global_count;
- }
-
- public Location (int row, int col)
- {
- if (row < 0 || col < 0)
- token = -1;
- else {
- if (col > 255)
- col = 255;
- token = module_base + (row << 8) + col;
- if (global_count < token)
- global_count = token;
- }
- }
-
- public override string ToString ()
- {
- return Name + ": (" + Row + ")";
- }
-
- /// <summary>
- /// Whether the Location is Null
- /// </summary>
- static public bool IsNull (Location l)
- {
- return l.token == -1;
- }
-
- public string Name {
- get {
- int best = 0;
-
- if (token < 0)
- return "Internal";
-
- foreach (int b in list){
- if (token > b)
- best = b;
- }
- return (string) map [best];
- }
- }
-
- public int Row {
- get {
- int best = 0;
-
- if (token < 0)
- return 1;
-
- foreach (int b in list){
- if (token > b)
- best = b;
- }
- return (token - best) >> 8;
- }
- }
-
- public int Col {
- get {
- int best = 0;
-
- if (token < 0)
- return 1;
-
- foreach (int b in list){
- if (token > b)
- best = b;
- }
- return (token - best) & 0xFF;
- }
- }
-
- // The ISymbolDocumentWriter interface is used by the symbol writer to
- // describe a single source file - for each source file there's exactly
- // one corresponding ISymbolDocumentWriter instance.
- //
- // This class has an internal hash table mapping source document names
- // to such ISymbolDocumentWriter instances - so there's exactly one
- // instance per document.
- //
- // This property returns the ISymbolDocumentWriter instance which belongs
- // to the location's source file.
- //
- // If we don't have a symbol writer, this property is always null.
- public ISymbolDocumentWriter SymbolDocument {
- get {
- ISymbolWriter sw = CodeGen.SymbolWriter;
- ISymbolDocumentWriter doc;
-
- if (token < 0)
- return null;
-
- // If we don't have a symbol writer, return null.
- if (sw == null)
- return null;
-
- string path = Path.GetFullPath (Name);
-
- if (sym_docs.Contains (path))
- // If we already created an ISymbolDocumentWriter
- // instance for this document, return it.
- doc = (ISymbolDocumentWriter) sym_docs [path];
- else {
- // Create a new ISymbolDocumentWriter instance and
- // store it in the hash table.
- doc = sw.DefineDocument (path, SymLanguageType.Basic,
- SymLanguageVendor.Microsoft,
- SymDocumentType.Text);
-
- sym_docs.Add (path, doc);
- }
-
- return doc;
- }
- }
- }
-}
+//\r
+// location.cs: Keeps track of the location of source code entity\r
+//\r
+// Author:\r
+// Miguel de Icaza\r
+//\r
+// (C) 2001 Ximian, Inc.\r
+//\r
+\r
+using System;\r
+using System.IO;\r
+using System.Collections;\r
+using System.Diagnostics.SymbolStore;\r
+\r
+namespace Mono.MonoBASIC {\r
+\r
+ /// <summary>\r
+ /// Keeps track of the location in the program\r
+ /// </summary>\r
+ ///\r
+ /// <remarks>\r
+ /// This uses a compact representation and a couple of auxiliary\r
+ /// structures to keep track of tokens to (line, col, file) mappings.\r
+ ///\r
+ public struct Location {\r
+ const int NUM_ROW_BITS = 16;\r
+ const int NUM_COL_BITS = 8;\r
+ const int NUM_FILE_BITS = (32-NUM_ROW_BITS-NUM_COL_BITS);\r
+ \r
+ const int NUM_FILE_SHIFTS = 0;\r
+ const int NUM_ROW_SHIFTS = NUM_FILE_BITS;\r
+ const int NUM_COL_SHIFTS = NUM_ROW_BITS+NUM_FILE_BITS;\r
+\r
+ const int FILE_MASK = (1<<NUM_FILE_BITS)-1;\r
+ const int ROW_MASK = ((1<<NUM_ROW_BITS)-1)<<NUM_FILE_BITS;\r
+ const int COL_MASK = ((1<<NUM_COL_BITS)-1)<<(NUM_ROW_BITS+NUM_FILE_BITS);\r
+ \r
+ public int token; // ordered triplet: (Row, Col, File Index)\r
+\r
+ static ArrayList source_list;\r
+ static Hashtable source_files;\r
+ static int source_count;\r
+ static int current_source;\r
+ static Hashtable sym_docs;\r
+\r
+ public readonly static Location Null;\r
+ \r
+ static Location ()\r
+ {\r
+ source_files = new Hashtable ();\r
+ source_list = new ArrayList ();\r
+ current_source = 0;\r
+ sym_docs = new Hashtable ();\r
+ Null.token = 0;\r
+ }\r
+\r
+ static public void SetCurrentSource(string name)\r
+ {\r
+ int index;\r
+ \r
+ if (!source_files.Contains (name)) {\r
+ index = ++source_count;\r
+ source_files.Add (name, index);\r
+ source_list.Add (name);\r
+ }\r
+ else {\r
+ index = (int)source_files[name];\r
+ }\r
+\r
+ current_source = index;\r
+ }\r
+ \r
+ public Location (int row, int col)\r
+ {\r
+ if (row < 0 || col < 0)\r
+ token = 0;\r
+ else {\r
+ if (col > 255)\r
+ col = 255;\r
+ token = (current_source<<NUM_FILE_SHIFTS) + (row<<NUM_ROW_SHIFTS) + (col<<NUM_COL_SHIFTS);\r
+ }\r
+ }\r
+\r
+ public override string ToString ()\r
+ {\r
+ return Name + ": (" + Row + ")";\r
+ }\r
+ \r
+ static public bool IsNull (Location l)\r
+ {\r
+ return l.token == 0;\r
+ }\r
+\r
+ public string Name {\r
+ get {\r
+ if(token == 0)\r
+ return "Internal";\r
+\r
+ int index = (token & FILE_MASK)>>NUM_FILE_SHIFTS;\r
+ string file = (string) source_list [index - 1];\r
+ return file;\r
+ }\r
+ }\r
+\r
+ public int Row {\r
+ get {\r
+ if (token == 0)\r
+ return 1;\r
+\r
+ return (token & ROW_MASK)>>NUM_ROW_SHIFTS;\r
+ }\r
+ }\r
+\r
+ public int Col {\r
+ get {\r
+ if (token == 0)\r
+ return 1;\r
+ \r
+ return (token & COL_MASK)>>NUM_COL_SHIFTS;\r
+ }\r
+ }\r
+\r
+ // The ISymbolDocumentWriter interface is used by the symbol writer to\r
+ // describe a single source file - for each source file there's exactly\r
+ // one corresponding ISymbolDocumentWriter instance.\r
+ //\r
+ // This class has an internal hash table mapping source document names\r
+ // to such ISymbolDocumentWriter instances - so there's exactly one\r
+ // instance per document.\r
+ //\r
+ // This property returns the ISymbolDocumentWriter instance which belongs\r
+ // to the location's source file.\r
+ //\r
+ // If we don't have a symbol writer, this property is always null.\r
+ public ISymbolDocumentWriter SymbolDocument {\r
+ get {\r
+ ISymbolWriter sw = CodeGen.SymbolWriter;\r
+ ISymbolDocumentWriter doc;\r
+\r
+ if (token < 0)\r
+ return null;\r
+\r
+ // If we don't have a symbol writer, return null.\r
+ if (sw == null)\r
+ return null;\r
+\r
+ string path = Path.GetFullPath (Name);\r
+\r
+ if (sym_docs.Contains (path))\r
+ // If we already created an ISymbolDocumentWriter\r
+ // instance for this document, return it.\r
+ doc = (ISymbolDocumentWriter) sym_docs [path];\r
+ else {\r
+ // Create a new ISymbolDocumentWriter instance and\r
+ // store it in the hash table.\r
+ doc = sw.DefineDocument (path, SymLanguageType.Basic,\r
+ SymLanguageVendor.Microsoft,\r
+ SymDocumentType.Text);\r
+\r
+ sym_docs.Add (path, doc);\r
+ }\r
+\r
+ return doc;\r
+ }\r
+ }\r
+ }\r
+}\r