1 /*
2 
3     This file is part of the Maude 2 interpreter.
4 
5     Copyright 1997-2003 SRI International, Menlo Park, CA 94025, USA.
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20 
21 */
22 
23 //
24 //      Implementation for class FileTable.
25 //
26 
27 //      utility stuff
28 #include "macros.hh"
29 #include "vector.hh"
30 
31 #include "fileTable.hh"
32 
33 #ifdef EXPLICIT_TEMPLATES
34 template class Vector<FileTable::Entry>;
35 #endif
36 
FileTable()37 FileTable::FileTable()
38 {
39   firstSilent = NONE;
40 }
41 
42 void
openFile(int lineNumber,const char * name,bool silent)43 FileTable::openFile(int lineNumber, const char* name, bool silent)
44 {
45   if (silent && firstSilent == NONE)
46     firstSilent = fileStack.length();
47   if (firstSilent == NONE && fileStack.length() > 0)
48     cout << "Reading in file: \"" << name << "\"\n";
49   int nrFileChanges = fileChanges.length();
50   fileChanges.expandBy(1);
51   Entry& fc = fileChanges[nrFileChanges];
52   fc.absoluteLineNumber = lineNumber;
53   fc.fileNameIndex = fileNames.encode(name);
54   fc.relativeLineNumber = 1;
55   fileStack.append(nrFileChanges);
56 }
57 
58 void
closeFile(int lineNumber)59 FileTable::closeFile(int lineNumber)
60 {
61   int topOfStack = fileStack.length() - 1;
62   int matchingOpen = fileStack[topOfStack];
63   if (firstSilent == NONE && topOfStack > 0)
64     {
65       cout << "Done reading in file: \"" <<
66 	fileNames.name(fileChanges[matchingOpen].fileNameIndex) << "\"\n";
67     }
68   if (firstSilent == topOfStack)
69     firstSilent = NONE;
70   int prevFileNameIndex = NONE;
71   int prevLineNumberDiff = 0;
72   if (matchingOpen > 0)
73     {
74       Entry& fe = fileChanges[matchingOpen - 1];
75       prevFileNameIndex = fe.fileNameIndex;
76       prevLineNumberDiff = fe.absoluteLineNumber - fe.relativeLineNumber;
77     }
78   int nrFileChanges = fileChanges.length();
79   fileChanges.expandBy(1);
80   Entry& fc = fileChanges[nrFileChanges];
81   fc.absoluteLineNumber = lineNumber;
82   fc.fileNameIndex = prevFileNameIndex;
83   fc.relativeLineNumber = fileChanges[matchingOpen].absoluteLineNumber - prevLineNumberDiff;
84   fileStack.contractTo(topOfStack);
85 }
86 
87 void
beginModule(Token type,Token name)88 FileTable::beginModule(Token type, Token name)
89 {
90   int nrModuleChanges = moduleChanges.length();
91   moduleChanges.expandBy(1);
92   Entry& mc = moduleChanges[nrModuleChanges];
93   mc.absoluteLineNumber = type.lineNumber();
94   mc.moduleNameIndex = name.code();
95   mc.moduleTypeIndex = type.code();
96   moduleStack.append(nrModuleChanges);
97   if (outputLine())
98     cout << type << ' ' << name << '\n';
99 }
100 
101 bool
outputLine()102 FileTable::outputLine()
103 {
104   if (firstSilent == NONE && fileStack.length() > 0)
105     {
106       cout << "==========================================\n";
107       return true;
108     }
109   return false;
110 }
111 
112 void
endModule(int lineNumber)113 FileTable::endModule(int lineNumber)
114 {
115   int topOfStack = moduleStack.length() - 1;
116   int matchingOpen = moduleStack[topOfStack];
117   int nrModuleChanges = moduleChanges.length();
118   moduleChanges.expandBy(1);
119   Entry& mc = moduleChanges[nrModuleChanges];
120   mc.absoluteLineNumber = lineNumber;
121   if (matchingOpen > 0)
122     {
123       mc.moduleNameIndex = moduleChanges[matchingOpen - 1].moduleNameIndex;
124       mc.moduleTypeIndex = moduleChanges[matchingOpen - 1].moduleTypeIndex;
125     }
126   else
127     {
128       mc.moduleNameIndex = NONE;
129       mc.moduleTypeIndex = NONE;
130     }
131   moduleStack.contractTo(topOfStack);
132 }
133 
134 void
abortEverything(int lineNumber)135 FileTable::abortEverything(int lineNumber)
136 {
137   //
138   //	Revert to top level file.
139   //
140   if (fileStack.length() > 0)
141     {
142       int matchingOpen = fileStack[0];
143       int prevLineNumberDiff = 0;
144       if (matchingOpen > 0)
145 	{
146 	  Entry& fe = fileChanges[matchingOpen - 1];
147 	  prevLineNumberDiff = fe.absoluteLineNumber - fe.relativeLineNumber;
148 	}
149       int nrFileChanges = fileChanges.length();
150       fileChanges.expandBy(1);
151       Entry& fc = fileChanges[nrFileChanges];
152       fc.absoluteLineNumber = lineNumber;
153       fc.fileNameIndex = NONE;
154       fc.relativeLineNumber = fileChanges[matchingOpen].absoluteLineNumber - prevLineNumberDiff;
155       fileStack.contractTo(0);
156       firstSilent = NONE;
157     }
158   //
159   //	End all modules.
160   //
161   if (moduleStack.length() > 0)
162     {
163       int nrModuleChanges = moduleChanges.length();
164       moduleChanges.expandBy(1);
165       Entry& mc = moduleChanges[nrModuleChanges];
166       mc.absoluteLineNumber = lineNumber;
167       mc.moduleNameIndex = NONE;
168       mc.moduleTypeIndex = NONE;
169       moduleStack.contractTo(0);
170     }
171 }
172 
173 int
binarySearch(Vector<Entry> & table,int lineNumber)174 FileTable::binarySearch(Vector<Entry>& table, int lineNumber)
175 {
176   //
177   //	Find index of entry with largest absoluteLineNumber that is <= lineNumber.
178   //	Return -1 if no such entry exists.
179   //
180   int max = table.length() - 1;
181   int min = 0;
182   while (max >= min)
183     {
184       int probe = (max + min) / 2;
185       int n = table[probe].absoluteLineNumber;
186       if (n == lineNumber)
187 	return probe;
188       else if (n > lineNumber)
189 	max = probe - 1;
190       else
191 	min = probe + 1;
192     }
193   return min - 1;
194 }
195 
196 void
printLineNumber(ostream & s,int lineNumber)197 FileTable::printLineNumber(ostream& s, int lineNumber)
198 {
199   switch (lineNumber)
200     {
201     case SYSTEM_CREATED:
202       {
203 	s << "<automatic>";
204 	break;
205       }
206     case META_LEVEL_CREATED:
207       {
208 	s << "<metalevel>";
209 	break;
210       }
211     case COMMAND_LINE:
212       {
213 	s << "<command line>";
214 	break;
215       }
216     default:
217       {
218 	int fileEntry = binarySearch(fileChanges, lineNumber);
219 	if (fileEntry == -1)
220 	  s << "<standard input>, line " << lineNumber;
221 	else
222 	  {
223 	    Entry& fe = fileChanges[fileEntry];
224 	    if (fe.fileNameIndex == NONE)
225 	      s << "<standard input>";
226 	    else
227 	      s << '"' << fileNames.name(fe.fileNameIndex) << '"';
228 	    s << ", line " << fe.relativeLineNumber + (lineNumber - fe.absoluteLineNumber);
229 	  }
230 	int moduleEntry = binarySearch(moduleChanges, lineNumber);
231 	if (moduleEntry == -1 || moduleChanges[moduleEntry].moduleTypeIndex == NONE)
232 	  break;
233 	Entry& me = moduleChanges[moduleEntry];
234 	s << " (" << Token::name(me.moduleTypeIndex) <<
235 	  ' ' << Token::name(me.moduleNameIndex) << ')';
236       }
237     }
238 }
239