/* * Copyright 2001-2006 Adrian Thurston */ /* This file is part of Ragel. * * Ragel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Ragel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Ragel; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _COMMON_H #define _COMMON_H #include #include #include "dlist.h" /* Location in an input file. */ struct InputLoc { const char *fileName; long line; long col; }; typedef unsigned long long Size; struct Key { private: long key; public: friend inline Key operator+(const Key key1, const Key key2); friend inline Key operator-(const Key key1, const Key key2); friend inline Key operator/(const Key key1, const Key key2); friend inline long operator&(const Key key1, const Key key2); friend inline bool operator<( const Key key1, const Key key2 ); friend inline bool operator<=( const Key key1, const Key key2 ); friend inline bool operator>( const Key key1, const Key key2 ); friend inline bool operator>=( const Key key1, const Key key2 ); friend inline bool operator==( const Key key1, const Key key2 ); friend inline bool operator!=( const Key key1, const Key key2 ); friend struct KeyOps; Key( ) {} Key( const Key &key ) : key(key.key) {} Key( long key ) : key(key) {} /* Returns the value used to represent the key. This value must be * interpreted based on signedness. */ long getVal() const { return key; }; /* Returns the key casted to a long long. This form of the key does not * require any signedness interpretation. */ long long getLongLong() const; /* Returns the distance from the key value to the maximum value that the * key implementation can hold. */ Size availableSpace() const; bool isUpper() const { return ( 'A' <= key && key <= 'Z' ); } bool isLower() const { return ( 'a' <= key && key <= 'z' ); } bool isPrintable() const { return ( 7 <= key && key <= 13 ) || ( 32 <= key && key < 127 ); } Key toUpper() const { return Key( 'A' + ( key - 'a' ) ); } Key toLower() const { return Key( 'a' + ( key - 'A' ) ); } void operator+=( const Key other ) { /* FIXME: must be made aware of isSigned. */ key += other.key; } void operator-=( const Key other ) { /* FIXME: must be made aware of isSigned. */ key -= other.key; } void operator|=( const Key other ) { /* FIXME: must be made aware of isSigned. */ key |= other.key; } /* Decrement. Needed only for ranges. */ inline void decrement(); inline void increment(); }; struct HostType { const char *data1; const char *data2; const char *internalName; bool isSigned; bool isOrd; bool isChar; long long sMinVal; long long sMaxVal; unsigned long long uMinVal; unsigned long long uMaxVal; unsigned int size; }; struct HostLang { /* Target language. */ enum Lang { C, D, D2, Go, Java, Ruby, CSharp, OCaml }; Lang lang; HostType *hostTypes; int numHostTypes; HostType *defaultAlphType; bool explicitUnsigned; }; extern HostLang *hostLang; extern HostLang hostLangC; extern HostLang hostLangD; extern HostLang hostLangD2; extern HostLang hostLangGo; extern HostLang hostLangJava; extern HostLang hostLangRuby; extern HostLang hostLangCSharp; extern HostLang hostLangOCaml; HostType *findAlphType( const char *s1 ); HostType *findAlphType( const char *s1, const char *s2 ); HostType *findAlphTypeInternal( const char *s1 ); /* An abstraction of the key operators that manages key operations such as * comparison and increment according the signedness of the key. */ struct KeyOps { /* Default to signed alphabet. */ KeyOps() : isSigned(true), alphType(0) {} /* Default to signed alphabet. */ KeyOps( bool isSigned ) :isSigned(isSigned) {} bool isSigned; Key minKey, maxKey; HostType *alphType; void setAlphType( HostType *alphType ) { this->alphType = alphType; isSigned = alphType->isSigned; if ( isSigned ) { minKey = (long) alphType->sMinVal; maxKey = (long) alphType->sMaxVal; } else { minKey = (long) (unsigned long) alphType->uMinVal; maxKey = (long) (unsigned long) alphType->uMaxVal; } } /* Compute the distance between two keys. */ Size span( Key key1, Key key2 ) { return isSigned ? (unsigned long long)( (long long)key2.key - (long long)key1.key + 1) : (unsigned long long)( (unsigned long)key2.key) - (unsigned long long)((unsigned long)key1.key) + 1; } Size alphSize() { return span( minKey, maxKey ); } HostType *typeSubsumes( long long maxVal ) { HostType *hostTypes = hostLang->hostTypes; for ( int i = 0; i < hostLang->numHostTypes; i++ ) { long long typeMaxVal = hostTypes[i].isSigned ? hostTypes[i].sMaxVal : hostTypes[i].uMaxVal; if ( maxVal <= typeMaxVal ) return &hostLang->hostTypes[i]; } return 0; } HostType *typeSubsumes( bool isSigned, long long maxVal ) { HostType *hostTypes = hostLang->hostTypes; for ( int i = 0; i < hostLang->numHostTypes; i++ ) { long long typeMaxVal = hostTypes[i].isSigned ? hostTypes[i].sMaxVal : hostTypes[i].uMaxVal; if ( ( ( isSigned && hostTypes[i].isSigned ) || !isSigned ) && maxVal <= typeMaxVal ) return hostLang->hostTypes + i; } return 0; } }; extern KeyOps *keyOps; inline bool operator<( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key < key2.key : (unsigned long)key1.key < (unsigned long)key2.key; } inline bool operator<=( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key <= key2.key : (unsigned long)key1.key <= (unsigned long)key2.key; } inline bool operator>( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key > key2.key : (unsigned long)key1.key > (unsigned long)key2.key; } inline bool operator>=( const Key key1, const Key key2 ) { return keyOps->isSigned ? key1.key >= key2.key : (unsigned long)key1.key >= (unsigned long)key2.key; } inline bool operator==( const Key key1, const Key key2 ) { return key1.key == key2.key; } inline bool operator!=( const Key key1, const Key key2 ) { return key1.key != key2.key; } /* Decrement. Needed only for ranges. */ inline void Key::decrement() { key = keyOps->isSigned ? key - 1 : ((unsigned long)key)-1; } /* Increment. Needed only for ranges. */ inline void Key::increment() { key = keyOps->isSigned ? key+1 : ((unsigned long)key)+1; } inline long long Key::getLongLong() const { return keyOps->isSigned ? (long long)key : (long long)(unsigned long)key; } inline Size Key::availableSpace() const { if ( keyOps->isSigned ) return (long long)LONG_MAX - (long long)key; else return (unsigned long long)ULONG_MAX - (unsigned long long)(unsigned long)key; } inline Key operator+(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return Key( key1.key + key2.key ); } inline Key operator-(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return Key( key1.key - key2.key ); } inline long operator&(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return key1.key & key2.key; } inline Key operator/(const Key key1, const Key key2) { /* FIXME: must be made aware of isSigned. */ return key1.key / key2.key; } /* Filter on the output stream that keeps track of the number of lines * output. */ class output_filter : public std::filebuf { public: output_filter( const char *fileName ) : fileName(fileName), line(1) { } virtual int sync(); virtual std::streamsize xsputn(const char* s, std::streamsize n); const char *fileName; int line; }; class cfilebuf : public std::streambuf { public: cfilebuf( char *fileName, FILE* file ) : fileName(fileName), file(file) { } char *fileName; FILE *file; int sync() { fflush( file ); return 0; } int overflow( int c ) { if ( c != EOF ) fputc( c, file ); return 0; } std::streamsize xsputn( const char* s, std::streamsize n ) { std::streamsize written = fwrite( s, 1, n, file ); return written; } }; class costream : public std::ostream { public: costream( cfilebuf *b ) : std::ostream(b), b(b) {} ~costream() { delete b; } void fclose() { ::fclose( b->file ); } cfilebuf *b; }; const char *findFileExtension( const char *stemFile ); const char *fileNameFromStem( const char *stemFile, const char *suffix ); struct Export { Export( const char *name, Key key ) : name(name), key(key) {} const char *name; Key key; Export *prev, *next; }; typedef DList ExportList; struct exit_object { }; extern exit_object endp; void operator<<( std::ostream &out, exit_object & ); #endif