Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / loglan96 / loglan93 / objects.cc
1 #include <stdlib.h>
2 #include <String.h>
3 #include "Objects.h"
4
5 #define LINE_WIDTH 256 // set the line width to anything you want.
6                        // The Only assumption is that a column number
7                        // is lesser than LINE_WIDTH
8
9 #define POSITION(line,column) ( (line) * LINE_WIDTH + (column) )
10
11 //**************************************
12 //* Class Location :                   *
13 //*  Class used for storing location   *
14 //*  of an object                      *
15 //**************************************
16
17 // Constructor with two arguments : the markers are set equal each other
18 // Start mark = End mark.
19
20 Location::Location( void )
21 {
22   LineStart   = LineEnd   = 1;
23   ColumnStart = ColumnEnd = 1;
24 }
25
26 Location::Location( int Line, int Column = 1 )
27 {
28   if (Line < 0 || Column < 0 || Column > LINE_WIDTH)
29     error("Incoherent values for initialisation of Location object.");
30   LineStart   = LineEnd   = Line;
31   ColumnStart = ColumnEnd = Column;
32 }
33
34 // Constructor with four arguments : the two first are for Start mark
35 // and the two last are for the End mark.
36
37 Location::Location( int First_Line, int First_Column,
38                int Last_Line, int Last_Column )
39 {
40   if ((First_Line <= 0) || (First_Column <= 0) ||
41       (Last_Line  <= 0) || (Last_Column  <= 0) ||
42       (First_Column > LINE_WIDTH) || (Last_Column > LINE_WIDTH))
43     error("Incoherent values for initialisation of Location object.");
44
45   if ( POSITION(First_Line,First_Column) < POSITION(Last_Line,Last_Column) )
46   {
47     LineStart   = First_Line;
48     LineEnd     = Last_Line;
49     ColumnStart = First_Column;
50     ColumnEnd   = Last_Column;
51   }
52   else
53   {
54     LineStart   = Last_Line;
55     LineEnd     = First_Line;
56     ColumnStart = Last_Column;
57     ColumnEnd   = First_Column;
58   }
59 }
60
61 Location::Location( const Location& TheLoc )
62 {
63   LineStart   = TheLoc.LineStart;
64   LineEnd     = TheLoc.LineEnd;
65   ColumnStart = TheLoc.ColumnStart;
66   ColumnEnd   = TheLoc.ColumnEnd;
67 }
68
69 // SetEnd method : Set the End mark to line number Line
70 //                 and column number Column.
71
72 void Location::SetEnd( int Line, int Column )
73 {
74
75   if ( Line <= 0 || Column <= 0 || Column > LINE_WIDTH)
76     error("Incoherent values for initialisation of Location object.");
77
78   if ( POSITION(Line,Column) > POSITION(LineStart,ColumnStart) )
79 // The new End Mark is after the Start Mark so we just adjust the End Mark.
80   {
81     LineEnd     = Line;
82     ColumnEnd   = Column;
83   }
84   else
85   {
86 // The new End Mark is before the Start Mark so we have two swap the two marks.
87     LineEnd     = LineStart;
88     ColumnEnd   = ColumnStart;
89     LineStart   = Line;
90     ColumnStart = Column;
91   }
92 }
93
94 // This function sets the beginning of the Location Object at
95 // the line Line and the column Column
96
97 void Location::Move( int Line , int Column )
98 {
99   LineStart   = Line;
100   ColumnStart = Column;
101   if ( POSITION(LineStart,ColumnStart) > POSITION(LineEnd,ColumnEnd) )
102   {
103     ColumnEnd = ColumnStart;
104     LineEnd   = LineStart;
105   }
106 }
107
108 // This function simply advance the start position by 'distance' columns.
109 void Location::Tab( int distance )
110 {
111   ColumnStart += distance;
112   if (ColumnStart > LINE_WIDTH)
113   {
114     LineStart++;
115     ColumnStart = ((ColumnStart - 1) % LINE_WIDTH) + 1;
116   }
117   if (POSITION(LineStart,ColumnStart) > POSITION(LineEnd,ColumnEnd) )
118   {
119     LineEnd   = LineStart;
120     ColumnEnd = ColumnStart;
121   }
122 }
123
124 // This function return the start position to the first column of the next line.
125 void Location::Cr( void )
126 {
127   LineStart++;
128   ColumnStart = 1;
129   if ( POSITION(LineStart,ColumnStart) > POSITION(LineEnd,ColumnEnd) )
130   {
131     LineEnd = LineStart;
132     ColumnEnd = ColumnStart;
133   }
134 }
135
136 void Location::Select( int length )
137 {
138   LineStart   = LineEnd;
139   ColumnStart = ColumnEnd;
140   ColumnEnd  += length - 1;
141   if ( ColumnEnd >= LINE_WIDTH )
142   {
143     LineEnd++;
144     ColumnEnd = (ColumnEnd - 1 ) % LINE_WIDTH + 1;
145   }
146 }
147
148 void Location::Advance( void )
149 {
150   LineStart = LineEnd;
151   ColumnStart = ++ColumnEnd;
152   if (ColumnStart == LINE_WIDTH)
153   {
154     ColumnStart = ColumnEnd = 1;
155     LineStart = ++LineEnd;
156   }
157 }
158
159 void Location::CrSelect( void )
160 {
161   LineEnd++;
162   ColumnEnd = 1;
163 }
164
165 // Checking the properties of a location Object :
166 // Line numbers and Column numbers must be greater than 0 and
167 // Start Mark must be come before the End Mark.
168
169 int Location::OK( void )
170 {
171   if (  (LineStart   < 0) || (LineEnd   < 0) ||
172         (ColumnStart < 0) || (ColumnEnd < 0) ||
173 // here we compute the number of characters from the begining
174 // assuming the line is LINE_WIDTH characters wide .
175         ( POSITION( LineStart,ColumnStart ) > POSITION( LineEnd,ColumnEnd ) )
176      )
177   {
178     error(" This Location object is not in a coherent state.");
179     return -1;
180   }
181   else
182     return 0;
183 }
184
185 //  Overloading semantic of + operator.
186 //  this return a Location Object that include both objects Location.
187 Location operator + ( const Location& FirstLocation  ,
188                       const Location& SecondLocation )
189 {
190   if (POSITION( FirstLocation .LineStart,FirstLocation .ColumnStart ) <
191       POSITION( SecondLocation.LineEnd  ,SecondLocation.ColumnEnd   ) )
192   {
193     return Location( FirstLocation .LineStart  ,
194                      FirstLocation .ColumnStart,
195                      SecondLocation.LineEnd,
196                      SecondLocation.ColumnEnd );
197   }
198   else
199   {
200     return Location( SecondLocation.LineStart  ,
201                      SecondLocation.ColumnStart,
202                      FirstLocation.LineEnd,
203                      FirstLocation.ColumnEnd );
204   }
205 }
206
207 // Well, this print out the contents of a Location object.
208
209 ostream& operator << ( ostream& cout, Location there )
210 {
211   cout << '(' << there.LineStart << ':' << there.ColumnStart << ',';
212   return cout << there.LineEnd << ':' << there.ColumnEnd << ')';
213 }
214
215 // General fonction that force the program to abort.
216 void error( char * TheString )
217 {
218   cout << TheString;
219   exit(-1);
220 }