Get ragel working again while the direct-to-backend code is being written.
[external/ragel.git] / common / common.h
1 /*
2  *  Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
3  */
4
5 /*  This file is part of Ragel.
6  *
7  *  Ragel 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  *  Ragel 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 Ragel; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20  */
21
22 #ifndef _COMMON_H
23 #define _COMMON_H
24
25 #include <fstream>
26 #include <climits>
27 #include "dlist.h"
28
29 typedef unsigned long long Size;
30
31 struct Key
32 {
33 private:
34         long key;
35
36 public:
37         friend inline Key operator+(const Key key1, const Key key2);
38         friend inline Key operator-(const Key key1, const Key key2);
39         friend inline Key operator/(const Key key1, const Key key2);
40         friend inline long operator&(const Key key1, const Key key2);
41
42         friend inline bool operator<( const Key key1, const Key key2 );
43         friend inline bool operator<=( const Key key1, const Key key2 );
44         friend inline bool operator>( const Key key1, const Key key2 );
45         friend inline bool operator>=( const Key key1, const Key key2 );
46         friend inline bool operator==( const Key key1, const Key key2 );
47         friend inline bool operator!=( const Key key1, const Key key2 );
48
49         friend struct KeyOps;
50         
51         Key( ) {}
52         Key( const Key &key ) : key(key.key) {}
53         Key( long key ) : key(key) {}
54
55         /* Returns the value used to represent the key. This value must be
56          * interpreted based on signedness. */
57         long getVal() const { return key; };
58
59         /* Returns the key casted to a long long. This form of the key does not
60          * require any signedness interpretation. */
61         long long getLongLong() const;
62
63         /* Returns the distance from the key value to the maximum value that the
64          * key implementation can hold. */
65         Size availableSpace() const;
66
67         bool isUpper() const { return ( 'A' <= key && key <= 'Z' ); }
68         bool isLower() const { return ( 'a' <= key && key <= 'z' ); }
69         bool isPrintable() const
70         {
71             return ( 7 <= key && key <= 13 ) || ( 32 <= key && key < 127 );
72         }
73
74         Key toUpper() const
75                 { return Key( 'A' + ( key - 'a' ) ); }
76         Key toLower() const
77                 { return Key( 'a' + ( key - 'A' ) ); }
78
79         void operator+=( const Key other )
80         {
81                 /* FIXME: must be made aware of isSigned. */
82                 key += other.key;
83         }
84
85         void operator-=( const Key other )
86         {
87                 /* FIXME: must be made aware of isSigned. */
88                 key -= other.key;
89         }
90
91         void operator|=( const Key other )
92         {
93                 /* FIXME: must be made aware of isSigned. */
94                 key |= other.key;
95         }
96
97         /* Decrement. Needed only for ranges. */
98         inline void decrement();
99         inline void increment();
100 };
101
102 struct HostType
103 {
104         const char *data1;
105         const char *data2;
106         const char *internalName;
107         bool isSigned;
108         long long minVal;
109         long long maxVal;
110         unsigned int size;
111 };
112
113 struct HostLang
114 {
115         /* Target language. */
116         enum Lang
117         {
118                 C, D, Java, Ruby, CSharp
119         };
120
121         Lang lang;
122         HostType *hostTypes;
123         int numHostTypes;
124         HostType *defaultAlphType;
125         bool explicitUnsigned;
126 };
127
128 extern HostLang *hostLang;
129
130 extern HostLang hostLangC;
131 extern HostLang hostLangD;
132 extern HostLang hostLangJava;
133 extern HostLang hostLangRuby;
134 extern HostLang hostLangCSharp;
135
136 HostType *findAlphType( const char *s1 );
137 HostType *findAlphType( const char *s1, const char *s2 );
138 HostType *findAlphTypeInternal( const char *s1 );
139
140 /* An abstraction of the key operators that manages key operations such as
141  * comparison and increment according the signedness of the key. */
142 struct KeyOps
143 {
144         /* Default to signed alphabet. */
145         KeyOps() :
146                 isSigned(true),
147                 alphType(0)
148         {}
149
150         /* Default to signed alphabet. */
151         KeyOps( bool isSigned ) 
152                 :isSigned(isSigned) {}
153
154         bool isSigned;
155         Key minKey, maxKey;
156         HostType *alphType;
157
158         void setAlphType( HostType *alphType )
159         {
160                 this->alphType = alphType;
161                 isSigned = alphType->isSigned;
162                 if ( isSigned ) {
163                         minKey = (long) alphType->minVal;
164                         maxKey = (long) alphType->maxVal;
165                 }
166                 else {
167                         minKey = (long) (unsigned long) alphType->minVal; 
168                         maxKey = (long) (unsigned long) alphType->maxVal;
169                 }
170         }
171
172         /* Compute the distance between two keys. */
173         Size span( Key key1, Key key2 )
174         {
175                 return isSigned ? 
176                         (unsigned long long)(
177                                 (long long)key2.key - 
178                                 (long long)key1.key + 1) : 
179                         (unsigned long long)(
180                                 (unsigned long)key2.key) - 
181                                 (unsigned long long)((unsigned long)key1.key) + 1;
182         }
183
184         Size alphSize()
185                 { return span( minKey, maxKey ); }
186
187         HostType *typeSubsumes( long long maxVal )
188         {
189                 for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
190                         if ( maxVal <= hostLang->hostTypes[i].maxVal )
191                                 return hostLang->hostTypes + i;
192                 }
193                 return 0;
194         }
195
196         HostType *typeSubsumes( bool isSigned, long long maxVal )
197         {
198                 for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
199                         if ( ( ( isSigned && hostLang->hostTypes[i].isSigned ) || !isSigned ) &&
200                                         maxVal <= hostLang->hostTypes[i].maxVal )
201                                 return hostLang->hostTypes + i;
202                 }
203                 return 0;
204         }
205 };
206
207 extern KeyOps *keyOps;
208
209 inline bool operator<( const Key key1, const Key key2 )
210 {
211         return keyOps->isSigned ? key1.key < key2.key : 
212                 (unsigned long)key1.key < (unsigned long)key2.key;
213 }
214
215 inline bool operator<=( const Key key1, const Key key2 )
216 {
217         return keyOps->isSigned ?  key1.key <= key2.key : 
218                 (unsigned long)key1.key <= (unsigned long)key2.key;
219 }
220
221 inline bool operator>( const Key key1, const Key key2 )
222 {
223         return keyOps->isSigned ? key1.key > key2.key : 
224                 (unsigned long)key1.key > (unsigned long)key2.key;
225 }
226
227 inline bool operator>=( const Key key1, const Key key2 )
228 {
229         return keyOps->isSigned ? key1.key >= key2.key : 
230                 (unsigned long)key1.key >= (unsigned long)key2.key;
231 }
232
233 inline bool operator==( const Key key1, const Key key2 )
234 {
235         return key1.key == key2.key;
236 }
237
238 inline bool operator!=( const Key key1, const Key key2 )
239 {
240         return key1.key != key2.key;
241 }
242
243 /* Decrement. Needed only for ranges. */
244 inline void Key::decrement()
245 {
246         key = keyOps->isSigned ? key - 1 : ((unsigned long)key)-1;
247 }
248
249 /* Increment. Needed only for ranges. */
250 inline void Key::increment()
251 {
252         key = keyOps->isSigned ? key+1 : ((unsigned long)key)+1;
253 }
254
255 inline long long Key::getLongLong() const
256 {
257         return keyOps->isSigned ? (long long)key : (long long)(unsigned long)key;
258 }
259
260 inline Size Key::availableSpace() const
261 {
262         if ( keyOps->isSigned ) 
263                 return (long long)LONG_MAX - (long long)key;
264         else
265                 return (unsigned long long)ULONG_MAX - (unsigned long long)(unsigned long)key;
266 }
267         
268 inline Key operator+(const Key key1, const Key key2)
269 {
270         /* FIXME: must be made aware of isSigned. */
271         return Key( key1.key + key2.key );
272 }
273
274 inline Key operator-(const Key key1, const Key key2)
275 {
276         /* FIXME: must be made aware of isSigned. */
277         return Key( key1.key - key2.key );
278 }
279
280 inline long operator&(const Key key1, const Key key2)
281 {
282         /* FIXME: must be made aware of isSigned. */
283         return key1.key & key2.key;
284 }
285
286 inline Key operator/(const Key key1, const Key key2)
287 {
288         /* FIXME: must be made aware of isSigned. */
289         return key1.key / key2.key;
290 }
291
292 /* Filter on the output stream that keeps track of the number of lines
293  * output. */
294 class output_filter : public std::filebuf
295 {
296 public:
297         output_filter( const char *fileName ) : fileName(fileName), line(1) { }
298
299         virtual int sync();
300         virtual std::streamsize xsputn(const char* s, std::streamsize n);
301
302         const char *fileName;
303         int line;
304 };
305
306 class cfilebuf : public std::streambuf
307 {
308 public:
309         cfilebuf( char *fileName, FILE* file ) : fileName(fileName), file(file) { }
310         char *fileName;
311         FILE *file;
312
313         int sync()
314         {
315                 fflush( file );
316                 return 0;
317         }
318
319         int overflow( int c )
320         {
321                 if ( c != EOF )
322                         fputc( c, file );
323                 return 0;
324         }
325
326         std::streamsize xsputn( const char* s, std::streamsize n )
327         {
328                 std::streamsize written = fwrite( s, 1, n, file );
329                 return written;
330         }
331 };
332
333 class costream : public std::ostream
334 {
335 public:
336         costream( cfilebuf *b ) : 
337                 std::ostream(b), b(b) {}
338         
339         ~costream()
340                 { delete b; }
341
342         void fclose()
343                 { ::fclose( b->file ); }
344
345         cfilebuf *b;
346 };
347
348
349 const char *findFileExtension( const char *stemFile );
350 const char *fileNameFromStem( const char *stemFile, const char *suffix );
351
352 struct Export
353 {
354         Export( const char *name, Key key )
355                 : name(name), key(key) {}
356
357         const char *name;
358         Key key;
359
360         Export *prev, *next;
361 };
362
363 typedef DList<Export> ExportList;
364
365 struct exit_object { };
366 extern exit_object endp;
367 void operator<<( std::ostream &out, exit_object & );
368
369 /* Target output style. */
370 enum CodeStyleEnum
371 {
372         GenTables,
373         GenFTables,
374         GenFlat,
375         GenFFlat,
376         GenGoto,
377         GenFGoto,
378         GenIpGoto,
379         GenSplit
380 };
381
382 /* Target implementation */
383 enum RubyImplEnum
384 {
385         MRI,
386         Rubinius
387 };
388
389 #endif /* _COMMON_H */