summaryrefslogtreecommitdiff
path: root/libfsm/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'libfsm/common.h')
-rw-r--r--libfsm/common.h504
1 files changed, 504 insertions, 0 deletions
diff --git a/libfsm/common.h b/libfsm/common.h
new file mode 100644
index 00000000..142eb735
--- /dev/null
+++ b/libfsm/common.h
@@ -0,0 +1,504 @@
+/*
+ * Copyright 2001-2018 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include <iostream>
+#include <fstream>
+#include <climits>
+#include "dlist.h"
+
+struct colm_location;
+
+struct InputData;
+struct CodeGenData;
+struct HostLang;
+struct CodeGenArgs;
+
+enum RagelBackend
+{
+ Direct,
+ Translated
+};
+
+enum BackendFeature
+{
+ GotoFeature,
+ BreakFeature,
+ VarFeature
+};
+
+#define S8BIT_MIN -128
+#define S8BIT_MAX 127
+
+#define U8BIT_MIN 0
+#define U8BIT_MAX 255
+
+#define S16BIT_MIN -32768
+#define S16BIT_MAX 32767
+
+#define U16BIT_MIN 0
+#define U16BIT_MAX 65535
+
+#define S31BIT_MIN -1073741824l
+#define S31BIT_MAX 1073741823l
+
+#define S32BIT_MIN -2147483648l
+#define S32BIT_MAX 2147483647l
+
+#define U32BIT_MIN 0
+#define U32BIT_MAX 4294967295l
+
+#define S64BIT_MIN (-9223372036854775807LL - 1LL)
+#define S64BIT_MAX 9223372036854775807LL
+
+#define U64BIT_MIN 0
+#define U64BIT_MAX 18446744073709551615ULL
+
+struct ParserLoc
+{
+ const char *fileName;
+ int line;
+ int col;
+};
+
+/* Location in an input file. */
+struct InputLoc
+{
+ InputLoc( colm_location *pcloc );
+
+ InputLoc() : fileName(0), line(-1), col(-1) {}
+
+ InputLoc( const ParserLoc loc )
+ {
+ fileName = loc.fileName;
+ line = loc.line;
+ col = loc.col;
+
+ if ( fileName == 0 )
+ fileName = "-";
+ if ( line == 0 )
+ line = 1;
+ }
+
+ InputLoc( const InputLoc &loc )
+ {
+ fileName = loc.fileName;
+ line = loc.line;
+ col = loc.col;
+
+ if ( fileName == 0 )
+ fileName = "-";
+ if ( line == 0 )
+ line = 1;
+ }
+
+ InputLoc( const char *fileName, int line, int col )
+ : fileName(fileName), line(line), col(col) {}
+
+ const char *fileName;
+ int line;
+ int col;
+};
+
+extern InputLoc internal;
+
+typedef unsigned long long Size;
+
+struct Key
+{
+private:
+ long key;
+
+public:
+ 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; };
+
+ 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' ) ); }
+};
+
+struct CondKey
+{
+private:
+ long key;
+
+public:
+ friend inline bool operator<( const CondKey key1, const CondKey key2 );
+ friend inline bool operator>( const CondKey key1, const CondKey key2 );
+ friend inline bool operator==( const CondKey key1, const CondKey key2 );
+ friend inline CondKey operator+( const CondKey key1, const CondKey key2 );
+ friend inline CondKey operator-( const CondKey key1, const CondKey key2 );
+
+ friend struct KeyOps;
+
+ CondKey( ) {}
+ CondKey( const CondKey &key ) : key(key.key) {}
+ CondKey( 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; };
+
+ 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 );
+ }
+
+ CondKey toUpper() const
+ { return CondKey( 'A' + ( key - 'a' ) ); }
+ CondKey toLower() const
+ { return CondKey( 'a' + ( key - 'A' ) ); }
+
+ /* Decrement. Needed only for ranges. */
+ inline void decrement();
+ inline void increment();
+};
+
+inline CondKey operator+(const CondKey key1, const CondKey key2)
+{
+ return CondKey( key1.key + key2.key );
+}
+
+inline CondKey operator-(const CondKey key1, const CondKey key2)
+{
+ return CondKey( key1.key - key2.key );
+}
+
+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;
+};
+
+typedef void (*GenLineDirectiveT)( std::ostream &out, bool nld, int line, const char *file );
+typedef const char *(*DefaultOutFnT)( const char *inputFileName );
+typedef CodeGenData *(*MakeCodeGenT)( const HostLang *hostLang, const CodeGenArgs &args );
+
+struct HostLang
+{
+ HostType *hostTypes;
+ int numHostTypes;
+ int defaultAlphType;
+ bool explicitUnsigned;
+ bool loopLabels;
+
+ RagelBackend backend;
+ BackendFeature feature;
+
+ MakeCodeGenT makeCodeGen;
+ DefaultOutFnT defaultOutFn;
+ GenLineDirectiveT genLineDirective;
+};
+
+void genLineDirectiveC( std::ostream &out, bool nld, int line, const char *file );
+void genLineDirectiveAsm( std::ostream &out, bool nld, int line, const char *file );
+void genLineDirectiveTrans( std::ostream &out, bool nld, int line, const char *file );
+
+extern const HostLang hostLangC;
+extern const HostLang hostLangAsm;
+
+HostType *findAlphType( const HostLang *hostLang, const char *s1 );
+HostType *findAlphType( const HostLang *hostLang, const char *s1, const char *s2 );
+HostType *findAlphTypeInternal( const HostLang *hostLang, const char *s1 );
+
+const char *defaultOutFnC( const char *inputFileName );
+extern HostType hostTypesC[];
+
+/* An abstraction of the key operators that manages key operations such as
+ * comparison and increment according the signedness of the key. */
+struct KeyOps
+{
+ /* Defaults to C "char" type: Signed 8 bit. */
+ KeyOps()
+ :
+ isSigned(true),
+ explicitUnsigned(true),
+ minKey(CHAR_MIN),
+ maxKey(CHAR_MAX)
+ {}
+
+ bool isSigned;
+ bool explicitUnsigned;
+ Key minKey, maxKey;
+
+ void setAlphType( const HostLang *hostLang, const HostType *alphType )
+ {
+ isSigned = alphType->isSigned;
+ explicitUnsigned = hostLang->explicitUnsigned;
+
+ if ( isSigned ) {
+ minKey = (long) alphType->sMinVal;
+ maxKey = (long) alphType->sMaxVal;
+ }
+ else {
+ minKey = (long) alphType->uMinVal;
+ maxKey = (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 ); }
+
+ inline bool lt( const Key key1, const Key key2 )
+ {
+ return this->isSigned ? key1.key < key2.key :
+ (unsigned long)key1.key < (unsigned long)key2.key;
+ }
+
+ inline bool le( const Key key1, const Key key2 )
+ {
+ return this->isSigned ? key1.key <= key2.key :
+ (unsigned long)key1.key <= (unsigned long)key2.key;
+ }
+
+ inline bool gt( const Key key1, const Key key2 )
+ {
+ return this->isSigned ? key1.key > key2.key :
+ (unsigned long)key1.key > (unsigned long)key2.key;
+ }
+
+ inline bool ge( const Key key1, const Key key2 )
+ {
+ return this->isSigned ? key1.key >= key2.key :
+ (unsigned long)key1.key >= (unsigned long)key2.key;
+ }
+
+ inline bool eq( const Key key1, const Key key2 )
+ {
+ return key1.key == key2.key;
+ }
+
+ inline bool ne( const Key key1, const Key key2 )
+ {
+ return key1.key != key2.key;
+ }
+
+ inline Key add(const Key key1, const Key key2)
+ {
+ /* FIXME: must be made aware of isSigned. */
+ return Key( key1.key + key2.key );
+ }
+
+ inline Key sub(const Key key1, const Key key2)
+ {
+ /* FIXME: must be made aware of isSigned. */
+ return Key( key1.key - key2.key );
+ }
+
+ /* Decrement. Needed only for ranges. */
+ inline void decrement( Key &key )
+ {
+ key.key = this->isSigned ? key.key - 1 : ((unsigned long)key.key)-1;
+ }
+
+ /* Increment. Needed only for ranges. */
+ inline void increment( Key &key )
+ {
+ key.key = this->isSigned ? key.key+1 : ((unsigned long)key.key)+1;
+ }
+
+ /* Returns the key casted to a long long. This form of the key does not
+ * require any signedness interpretation. */
+ inline long long getLongLong( const Key &key )
+ {
+ return this->isSigned ? (long long)key.key : (long long)(unsigned long)key.key;
+ }
+};
+
+/* CondKey */
+
+inline bool operator<( const CondKey key1, const CondKey key2 )
+{
+ return key1.key < key2.key;
+}
+
+inline bool operator>( const CondKey key1, const CondKey key2 )
+{
+ return key1.key > key2.key;
+}
+
+inline bool operator==( const CondKey key1, const CondKey key2 )
+{
+ return key1.key == key2.key;
+}
+
+/* Increment. Needed only for ranges. */
+inline void CondKey::increment()
+{
+ key = key + 1;
+}
+
+
+/* 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),
+ level(0),
+ indent(false),
+ singleIndent(false)
+ {}
+
+ virtual int sync();
+ virtual std::streamsize xsputn( const char* s, std::streamsize n );
+
+ std::streamsize countAndWrite( const char* s, std::streamsize n );
+
+ const char *fileName;
+ int line;
+ int level;
+ bool indent;
+ bool singleIndent;
+};
+
+class nullbuf
+:
+ public std::streambuf
+{
+public:
+ virtual std::streamsize xsputn( const char * s, std::streamsize n )
+ { return n; }
+
+ virtual int overflow( int c )
+ { return 1; }
+};
+
+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( std::string name, Key key )
+ : name(name), key(key) {}
+
+ std::string name;
+ Key key;
+
+ Export *prev, *next;
+};
+
+typedef DList<Export> ExportList;
+
+struct exit_object { };
+extern exit_object endp;
+void operator<<( std::ostream &out, exit_object & );
+
+enum RagelFrontend
+{
+ KelbtBased,
+ ReduceBased
+};
+
+CodeGenData *makeCodeGen( const HostLang *hostLang, const CodeGenArgs &args );
+CodeGenData *makeCodeGenAsm( const HostLang *hostLang, const CodeGenArgs &args );
+
+#endif