2 * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
5 /* This file is part of Ragel.
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.
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.
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
29 /* Location in an input file. */
38 typedef unsigned long long Size;
46 friend inline Key operator+(const Key key1, const Key key2);
47 friend inline Key operator-(const Key key1, const Key key2);
48 friend inline Key operator/(const Key key1, const Key key2);
49 friend inline long operator&(const Key key1, const Key key2);
51 friend inline bool operator<( const Key key1, const Key key2 );
52 friend inline bool operator<=( const Key key1, const Key key2 );
53 friend inline bool operator>( const Key key1, const Key key2 );
54 friend inline bool operator>=( const Key key1, const Key key2 );
55 friend inline bool operator==( const Key key1, const Key key2 );
56 friend inline bool operator!=( const Key key1, const Key key2 );
61 Key( const Key &key ) : key(key.key) {}
62 Key( long key ) : key(key) {}
64 /* Returns the value used to represent the key. This value must be
65 * interpreted based on signedness. */
66 long getVal() const { return key; };
68 /* Returns the key casted to a long long. This form of the key does not
69 * require any signedness interpretation. */
70 long long getLongLong() const;
72 /* Returns the distance from the key value to the maximum value that the
73 * key implementation can hold. */
74 Size availableSpace() const;
76 bool isUpper() const { return ( 'A' <= key && key <= 'Z' ); }
77 bool isLower() const { return ( 'a' <= key && key <= 'z' ); }
78 bool isPrintable() const
80 return ( 7 <= key && key <= 13 ) || ( 32 <= key && key < 127 );
84 { return Key( 'A' + ( key - 'a' ) ); }
86 { return Key( 'a' + ( key - 'A' ) ); }
88 void operator+=( const Key other )
90 /* FIXME: must be made aware of isSigned. */
94 void operator-=( const Key other )
96 /* FIXME: must be made aware of isSigned. */
100 void operator|=( const Key other )
102 /* FIXME: must be made aware of isSigned. */
106 /* Decrement. Needed only for ranges. */
107 inline void decrement();
108 inline void increment();
115 const char *internalName;
124 /* Target language. */
127 C, D, Java, Ruby, CSharp
133 HostType *defaultAlphType;
134 bool explicitUnsigned;
137 extern HostLang *hostLang;
139 extern HostLang hostLangC;
140 extern HostLang hostLangD;
141 extern HostLang hostLangJava;
142 extern HostLang hostLangRuby;
143 extern HostLang hostLangCSharp;
145 HostType *findAlphType( const char *s1 );
146 HostType *findAlphType( const char *s1, const char *s2 );
147 HostType *findAlphTypeInternal( const char *s1 );
149 /* An abstraction of the key operators that manages key operations such as
150 * comparison and increment according the signedness of the key. */
153 /* Default to signed alphabet. */
159 /* Default to signed alphabet. */
160 KeyOps( bool isSigned )
161 :isSigned(isSigned) {}
167 void setAlphType( HostType *alphType )
169 this->alphType = alphType;
170 isSigned = alphType->isSigned;
172 minKey = (long) alphType->minVal;
173 maxKey = (long) alphType->maxVal;
176 minKey = (long) (unsigned long) alphType->minVal;
177 maxKey = (long) (unsigned long) alphType->maxVal;
181 /* Compute the distance between two keys. */
182 Size span( Key key1, Key key2 )
185 (unsigned long long)(
186 (long long)key2.key -
187 (long long)key1.key + 1) :
188 (unsigned long long)(
189 (unsigned long)key2.key) -
190 (unsigned long long)((unsigned long)key1.key) + 1;
194 { return span( minKey, maxKey ); }
196 HostType *typeSubsumes( long long maxVal )
198 for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
199 if ( maxVal <= hostLang->hostTypes[i].maxVal )
200 return hostLang->hostTypes + i;
205 HostType *typeSubsumes( bool isSigned, long long maxVal )
207 for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
208 if ( ( ( isSigned && hostLang->hostTypes[i].isSigned ) || !isSigned ) &&
209 maxVal <= hostLang->hostTypes[i].maxVal )
210 return hostLang->hostTypes + i;
216 extern KeyOps *keyOps;
218 inline bool operator<( const Key key1, const Key key2 )
220 return keyOps->isSigned ? key1.key < key2.key :
221 (unsigned long)key1.key < (unsigned long)key2.key;
224 inline bool operator<=( const Key key1, const Key key2 )
226 return keyOps->isSigned ? key1.key <= key2.key :
227 (unsigned long)key1.key <= (unsigned long)key2.key;
230 inline bool operator>( const Key key1, const Key key2 )
232 return keyOps->isSigned ? key1.key > key2.key :
233 (unsigned long)key1.key > (unsigned long)key2.key;
236 inline bool operator>=( const Key key1, const Key key2 )
238 return keyOps->isSigned ? key1.key >= key2.key :
239 (unsigned long)key1.key >= (unsigned long)key2.key;
242 inline bool operator==( const Key key1, const Key key2 )
244 return key1.key == key2.key;
247 inline bool operator!=( const Key key1, const Key key2 )
249 return key1.key != key2.key;
252 /* Decrement. Needed only for ranges. */
253 inline void Key::decrement()
255 key = keyOps->isSigned ? key - 1 : ((unsigned long)key)-1;
258 /* Increment. Needed only for ranges. */
259 inline void Key::increment()
261 key = keyOps->isSigned ? key+1 : ((unsigned long)key)+1;
264 inline long long Key::getLongLong() const
266 return keyOps->isSigned ? (long long)key : (long long)(unsigned long)key;
269 inline Size Key::availableSpace() const
271 if ( keyOps->isSigned )
272 return (long long)LONG_MAX - (long long)key;
274 return (unsigned long long)ULONG_MAX - (unsigned long long)(unsigned long)key;
277 inline Key operator+(const Key key1, const Key key2)
279 /* FIXME: must be made aware of isSigned. */
280 return Key( key1.key + key2.key );
283 inline Key operator-(const Key key1, const Key key2)
285 /* FIXME: must be made aware of isSigned. */
286 return Key( key1.key - key2.key );
289 inline long operator&(const Key key1, const Key key2)
291 /* FIXME: must be made aware of isSigned. */
292 return key1.key & key2.key;
295 inline Key operator/(const Key key1, const Key key2)
297 /* FIXME: must be made aware of isSigned. */
298 return key1.key / key2.key;
301 /* Filter on the output stream that keeps track of the number of lines
303 class output_filter : public std::filebuf
306 output_filter( const char *fileName ) : fileName(fileName), line(1) { }
309 virtual std::streamsize xsputn(const char* s, std::streamsize n);
311 const char *fileName;
315 class cfilebuf : public std::streambuf
318 cfilebuf( char *fileName, FILE* file ) : fileName(fileName), file(file) { }
328 int overflow( int c )
335 std::streamsize xsputn( const char* s, std::streamsize n )
337 std::streamsize written = fwrite( s, 1, n, file );
342 class costream : public std::ostream
345 costream( cfilebuf *b ) :
346 std::ostream(b), b(b) {}
352 { ::fclose( b->file ); }
358 const char *findFileExtension( const char *stemFile );
359 const char *fileNameFromStem( const char *stemFile, const char *suffix );
363 Export( const char *name, Key key )
364 : name(name), key(key) {}
372 typedef DList<Export> ExportList;
374 struct exit_object { };
375 extern exit_object endp;
376 void operator<<( std::ostream &out, exit_object & );