//
// 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 {
///
/// Keeps track of the location in the program
///
///
///
/// 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+').
///
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 + ")";
}
///
/// Whether the Location is Null
///
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;
}
}
}
}