diff options
author | Adrian Thurston <thurston@colm.net> | 2020-03-16 08:54:20 +0200 |
---|---|---|
committer | Adrian Thurston <thurston@colm.net> | 2020-03-16 08:54:20 +0200 |
commit | 0f227e5db320e7b2ec9a69ea19269ec9060091c2 (patch) | |
tree | 0af24234cf16185f1021fc26a109b6e124dc1c2a | |
parent | b38131d491567d436516fdababc006074230c034 (diff) | |
download | colm-0f227e5db320e7b2ec9a69ea19269ec9060091c2.tar.gz |
removal of some files only belonging in ragel, install libfsm to include/libfsm
-rw-r--r-- | aapl/Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 15 | ||||
-rw-r--r-- | libfsm/Makefile.am | 4 | ||||
-rw-r--r-- | libfsm/buffer.h | 56 | ||||
-rw-r--r-- | libfsm/common.cc | 130 | ||||
-rw-r--r-- | libfsm/inputdata.cc | 1150 | ||||
-rw-r--r-- | libfsm/libragel.h | 32 | ||||
-rw-r--r-- | libfsm/load.h | 37 | ||||
-rw-r--r-- | libfsm/pcheck.h | 49 | ||||
-rw-r--r-- | libfsm/reducer.cc | 230 | ||||
-rw-r--r-- | libfsm/reducer.h | 120 | ||||
-rw-r--r-- | libfsm/rlscan.h | 136 | ||||
-rw-r--r-- | libfsm/xmlparse.kh | 211 | ||||
-rw-r--r-- | libfsm/xmlparse.kl | 1006 | ||||
-rw-r--r-- | libfsm/xmlscan.rl | 315 | ||||
-rw-r--r-- | libfsm/xmltags.gperf | 95 |
16 files changed, 16 insertions, 3572 deletions
diff --git a/aapl/Makefile.am b/aapl/Makefile.am index 00cffba9..b3cd0c94 100644 --- a/aapl/Makefile.am +++ b/aapl/Makefile.am @@ -1,5 +1,3 @@ -aaplincludedir = $(includedir)/aapl - aaplinclude_HEADERS = \ avlbasic.h avlimel.h avlmap.h bstcommon.h compare.h insertsort.h \ sbstset.h avlcommon.h avlimelkey.h avlmel.h bstmap.h dlcommon.h \ diff --git a/configure.ac b/configure.ac index 03c429f2..a5de89d5 100644 --- a/configure.ac +++ b/configure.ac @@ -50,7 +50,6 @@ AC_PROG_CXX AC_CHECK_TOOL(AR, ar) AC_PROG_RANLIB AC_PROG_LIBTOOL - SED_SUBST=["\ -e 's|@CXX@|${CXX}|g' \ -e 's|@CC@|${CC}|g' \ @@ -59,6 +58,20 @@ SED_SUBST=["\ dnl Set test on c++ compiler. AC_LANG_CPLUSPLUS +dnl +dnl libfsmincludedir +dnl +libfsmincludedir='${includedir}/libfsm/' +AC_SUBST(libfsmincludedir) +SED_SUBST="$SED_SUBST -e 's|[@]libfsmincludedir[@]|$libfsmincludedir|g'" + +dnl +dnl aaplincludedir +dnl +aaplincludedir='${includedir}/aapl/' +AC_SUBST(aaplincludedir) +SED_SUBST="$SED_SUBST -e 's|[@]aaplincludedir[@]|$aaplincludedir|g'" + dnl Check for definition of MAKE. AC_PROG_MAKE_SET diff --git a/libfsm/Makefile.am b/libfsm/Makefile.am index 5a3761e9..261aa0a4 100644 --- a/libfsm/Makefile.am +++ b/libfsm/Makefile.am @@ -4,9 +4,9 @@ # to the ragel language. lib_LTLIBRARIES = libfsm.la -pkginclude_HEADERS = \ +libfsminclude_HEADERS = \ action.h fsmgraph.h common.h \ - gendata.h redfsm.h dot.h + gendata.h redfsm.h dot.h asm.h ragel.h # nodist_pkginclude_HEADERS = config.h diff --git a/libfsm/buffer.h b/libfsm/buffer.h deleted file mode 100644 index 72bcd5f9..00000000 --- a/libfsm/buffer.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2003-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 _BUFFER_H -#define _BUFFER_H - -#define BUFFER_INITIAL_SIZE 4096 - -/* An automatically grown buffer for collecting tokens. Always reuses space; - * never down resizes. */ -struct Buffer -{ - Buffer() - { - data = (char*) malloc( BUFFER_INITIAL_SIZE ); - allocated = BUFFER_INITIAL_SIZE; - length = 0; - } - ~Buffer() { free(data); } - - void append( char p ) - { - if ( length == allocated ) { - allocated *= 2; - data = (char*) realloc( data, allocated ); - } - data[length++] = p; - } - - void clear() { length = 0; } - - char *data; - int allocated; - int length; -}; - -#endif diff --git a/libfsm/common.cc b/libfsm/common.cc index 6e0f5c0c..9ebbd905 100644 --- a/libfsm/common.cc +++ b/libfsm/common.cc @@ -20,7 +20,6 @@ * SOFTWARE. */ -#include "pcheck.h" #include "common.h" #include "stdlib.h" #include <string.h> @@ -139,135 +138,6 @@ HostType *findAlphTypeInternal( const HostLang *hostLang, const char *s1 ) return 0; } -/* Construct a new parameter checker with for paramSpec. */ -ParamCheck::ParamCheck( const char *paramSpec, int argc, const char **argv ) -: - state(noparam), - argOffset(0), - curArg(0), - iCurArg(1), - paramSpec(paramSpec), - argc(argc), - argv(argv) -{ -} - -/* Check a single option. Returns the index of the next parameter. Sets p to - * the arg character if valid, 0 otherwise. Sets parg to the parameter arg if - * there is one, NULL otherwise. */ -bool ParamCheck::check() -{ - bool requiresParam; - - if ( iCurArg >= argc ) { /* Off the end of the arg list. */ - state = noparam; - return false; - } - - if ( argOffset != 0 && *argOffset == 0 ) { - /* We are at the end of an arg string. */ - iCurArg += 1; - if ( iCurArg >= argc ) { - state = noparam; - return false; - } - argOffset = 0; - } - - if ( argOffset == 0 ) { - /* Set the current arg. */ - curArg = argv[iCurArg]; - - /* We are at the beginning of an arg string. */ - if ( argv[iCurArg] == 0 || /* Argv[iCurArg] is null. */ - argv[iCurArg][0] != '-' || /* Not a param. */ - argv[iCurArg][1] == 0 ) { /* Only a dash. */ - parameter = 0; - paramArg = 0; - - iCurArg += 1; - state = noparam; - return true; - } - argOffset = argv[iCurArg] + 1; - } - - /* Get the arg char. */ - char argChar = *argOffset; - - /* Loop over all the parms and look for a match. */ - const char *pSpec = paramSpec; - while ( *pSpec != 0 ) { - char pSpecChar = *pSpec; - - /* If there is a ':' following the char then - * it requires a parm. If a parm is required - * then move ahead two in the parmspec. Otherwise - * move ahead one in the parm spec. */ - if ( pSpec[1] == ':' ) { - requiresParam = true; - pSpec += 2; - } - else { - requiresParam = false; - pSpec += 1; - } - - /* Do we have a match. */ - if ( argChar == pSpecChar ) { - if ( requiresParam ) { - if ( argOffset[1] == 0 ) { - /* The param must follow. */ - if ( iCurArg + 1 == argc ) { - /* We are the last arg so there - * cannot be a parameter to it. */ - parameter = argChar; - paramArg = 0; - iCurArg += 1; - argOffset = 0; - state = invalid; - return true; - } - else { - /* the parameter to the arg is the next arg. */ - parameter = pSpecChar; - paramArg = argv[iCurArg + 1]; - iCurArg += 2; - argOffset = 0; - state = match; - return true; - } - } - else { - /* The param for the arg is built in. */ - parameter = pSpecChar; - paramArg = argOffset + 1; - iCurArg += 1; - argOffset = 0; - state = match; - return true; - } - } - else { - /* Good, we matched the parm and no - * arg is required. */ - parameter = pSpecChar; - paramArg = 0; - argOffset += 1; - state = match; - return true; - } - } - } - - /* We did not find a match. Bad Argument. */ - parameter = argChar; - paramArg = 0; - argOffset += 1; - state = invalid; - return true; -} - std::streamsize output_filter::countAndWrite( const char *s, std::streamsize n ) { for ( int i = 0; i < n; i++ ) { diff --git a/libfsm/inputdata.cc b/libfsm/inputdata.cc deleted file mode 100644 index 66ec4afb..00000000 --- a/libfsm/inputdata.cc +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * Copyright 2008-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. - */ - -#include "ragel.h" -#include "common.h" -#include "inputdata.h" -#include "parsedata.h" -#include "load.h" -#include "rlscan.h" -#include "reducer.h" -#include "version.h" -#include "pcheck.h" -#include <colm/colm.h> - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <iostream> -#include <iomanip> -#include <fstream> -#include <unistd.h> -#include <sstream> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#if defined(HAVE_SYS_WAIT_H) -#include <sys/wait.h> -#endif - -#ifdef _WIN32 -#include <windows.h> -#include <psapi.h> -#include <time.h> -#include <io.h> -#include <process.h> - -#if _MSC_VER -#define S_IRUSR _S_IREAD -#define S_IWUSR _S_IWRITE -#endif -#endif - -using std::istream; -using std::ifstream; -using std::ofstream; -using std::stringstream; -using std::ostream; -using std::endl; -using std::ios; - -InputData::~InputData() -{ - inputItems.empty(); - parseDataList.empty(); - sectionList.empty(); - - for ( Vector<const char**>::Iter fns = streamFileNames; fns.lte(); fns++ ) { - const char **ptr = *fns; - while ( *ptr != 0 ) { - ::free( (void*)*ptr ); - ptr += 1; - } - free( (void*) *fns ); - } - - if ( outputFileName != 0 ) - delete[] outputFileName; - - if ( histogramFn != 0 ) - ::free( (void*)histogramFn ); - - if ( histogram != 0 ) - delete[] histogram; - - for ( ArgsVector::Iter bl = breadthLabels; bl.lte(); bl++ ) - free( (void*) *bl ); -} - -void InputData::makeDefaultFileName() -{ - if ( outputFileName == 0 ) - outputFileName = (hostLang->defaultOutFn)( inputFileName ); -} - -bool InputData::isBreadthLabel( const string &label ) -{ - for ( ArgsVector::Iter bl = breadthLabels; bl.lte(); bl++ ) { - if ( label == *bl ) - return true; - } - return false; -} - -void InputData::createOutputStream() -{ - /* Make sure we are not writing to the same file as the input file. */ - if ( outputFileName != 0 ) { - if ( strcmp( inputFileName, outputFileName ) == 0 ) { - error() << "output file \"" << outputFileName << - "\" is the same as the input file" << endl; - } - - /* Create the filter on the output and open it. */ - outFilter = new output_filter( outputFileName ); - - /* Open the output stream, attaching it to the filter. */ - outStream = new ostream( outFilter ); - } - else { - /* Writing out to std out. */ - outStream = &std::cout; - } -} - -void InputData::openOutput() -{ - if ( outFilter != 0 ) { - outFilter->open( outputFileName, ios::out|ios::trunc ); - if ( !outFilter->is_open() ) { - error() << "error opening " << outputFileName << " for writing" << endl; - abortCompile( 1 ); - } - } -} - -void InputData::prepareSingleMachine() -{ - ParseData *pd = 0; - GraphDictEl *gdEl = 0; - - /* Locate a machine spec to generate dot output for. We can only emit. - * Dot takes one graph at a time. */ - if ( machineSpec != 0 ) { - /* Machine specified. */ - ParseDataDictEl *pdEl = parseDataDict.find( machineSpec ); - if ( pdEl == 0 ) - error() << "could not locate machine specified with -S and/or -M" << endp; - pd = pdEl->value; - } - else { - /* No machine spec given, generate the first one. */ - if ( parseDataList.length() == 0 ) - error() << "no machine specification to generate graphviz output" << endp; - - pd = parseDataList.head; - } - - if ( machineName != 0 ) { - gdEl = pd->graphDict.find( machineName ); - if ( gdEl == 0 ) - error() << "machine definition/instantiation not found" << endp; - } - else { - /* We are using the whole machine spec. Need to make sure there - * are instances in the spec. */ - if ( pd->instanceList.length() == 0 ) - error() << "no machine instantiations to generate graphviz output" << endp; - } - - pd->prepareMachineGen( gdEl, hostLang ); - dotGenPd = pd; -} - -void InputData::prepareAllMachines() -{ - for ( ParseDataDict::Iter pdel = parseDataDict; pdel.lte(); pdel++ ) { - ParseData *pd = pdel->value; - if ( pd->instanceList.length() > 0 ) { - pd->prepareMachineGen( 0, hostLang ); - - pd->makeExports(); - } - - } -} - -void InputData::generateReduced() -{ - for ( ParseDataDict::Iter pdel = parseDataDict; pdel.lte(); pdel++ ) { - ParseData *pd = pdel->value; - if ( pd->instanceList.length() > 0 ) - pd->generateReduced( inputFileName, codeStyle, *outStream, hostLang ); - } -} - -void InputData::verifyWriteHasData( InputItem *ii ) -{ - if ( ii->type == InputItem::Write ) { - if ( ii->pd->cgd == 0 ) - error( ii->loc ) << ii->pd->sectionName << ": no machine instantiations to write" << endl; - } -} - -void InputData::verifyWritesHaveData() -{ - for ( InputItemList::Iter ii = inputItems; ii.lte(); ii++ ) - verifyWriteHasData( ii ); -} - -void InputData::writeOutput( InputItem *ii ) -{ - /* If it is the first input item then check if we need to write the BOM. */ - if ( ii->prev == 0 && utf8BomPresent ) - *outStream << (uchar)0xEF << (uchar)0xBB << (uchar) 0xBF; - - switch ( ii->type ) { - case InputItem::Write: { - CodeGenData *cgd = ii->pd->cgd; - cgd->writeStatement( ii->loc, ii->writeArgs.size(), - ii->writeArgs, generateDot, hostLang ); - break; - } - case InputItem::HostData: { - switch ( hostLang->backend ) { - case Direct: - if ( ii->loc.fileName != 0 ) { - if ( ii->prev != 0 ) - *outStream << "\n"; - (*hostLang->genLineDirective)( *outStream, !noLineDirectives, ii->loc.line, ii->loc.fileName ); - } - - *outStream << ii->data.str(); - break; - case Translated: - openHostBlock( '@', this, *outStream, inputFileName, ii->loc.line ); - translatedHostData( *outStream, ii->data.str() ); - *outStream << "}@"; - break; - } - break; - } - case InputItem::EndSection: { - break; - } - } -} - -void InputData::closeOutput() -{ - /* If writing to a file, delete the ostream, causing it to flush. - * Standard out is flushed automatically. */ - if ( outputFileName != 0 ) { - delete outStream; - delete outFilter; - } -} - -void InputData::processDot() -{ - /* Compiles the DOT machines. */ - prepareSingleMachine(); - - if ( errorCount > 0 ) - abortCompile( 1 ); - - createOutputStream(); - - if ( errorCount > 0 ) - abortCompile( 1 ); - - /* - * From this point on we should not be reporting any errors. - */ - - openOutput(); - writeDot( *outStream ); - closeOutput(); -} - -bool InputData::checkLastRef( InputItem *ii ) -{ - if ( generateDot ) - return true; - - if ( errorCount > 0 ) - return false; - - /* - * 1. Go forward to next last reference. - * 2. Fully process that machine, mark as processed. - * 3. Move forward through input items until no longer - */ - if ( ii->section != 0 && ii->section->lastReference == ii ) { - /* Fully Process. */ - ParseData *pd = ii->pd; - - if ( pd->instanceList.length() > 0 ) { -#ifdef WITH_RAGEL_KELBT - if ( ii->parser != 0 ) - ii->parser->terminateParser(); -#endif - - FsmRes res = pd->prepareMachineGen( 0, hostLang ); - - /* Compute exports from the export definitions. */ - pd->makeExports(); - - if ( !res.success() ) - return false; - - if ( errorCount > 0 ) - return false; - - pd->generateReduced( inputFileName, codeStyle, *outStream, hostLang ); - - if ( errorCount > 0 ) - return false; - } - - /* Mark all input items referencing the machine as processed. */ - InputItem *toMark = lastFlush; - while ( true ) { - toMark->processed = true; - - if ( toMark == ii ) - break; - - toMark = toMark->next; - } - - /* Move forward, flushing input items until we get to an unprocessed - * input item. */ - while ( lastFlush != 0 && lastFlush->processed ) { - verifyWriteHasData( lastFlush ); - - if ( errorCount > 0 ) - return false; - - /* Flush out. */ - writeOutput( lastFlush ); - - lastFlush = lastFlush->next; - } - } - return true; -} - -void InputData::makeFirstInputItem() -{ - /* Make the first input item. */ - InputItem *firstInputItem = new InputItem; - firstInputItem->type = InputItem::HostData; - firstInputItem->loc.fileName = inputFileName; - firstInputItem->loc.line = 1; - firstInputItem->loc.col = 1; - inputItems.append( firstInputItem ); -} - -/* Send eof to all parsers. */ -void InputData::terminateAllParsers( ) -{ -#ifdef WITH_RAGEL_KELBT - for ( ParserDict::Iter pdel = parserDict; pdel.lte(); pdel++ ) - pdel->value->terminateParser(); -#endif -} - -void InputData::flushRemaining() -{ - InputItem *item = inputItems.head; - - while ( item != 0 ) { - checkLastRef( item ); - item = item->next; - } - - /* Flush remaining items. */ - while ( lastFlush != 0 ) { - /* Flush out. */ - writeOutput( lastFlush ); - - lastFlush = lastFlush->next; - } -} - -void InputData::makeTranslateOutputFileName() -{ - origOutputFileName = outputFileName; - outputFileName = fileNameFromStem( outputFileName, ".ri" ); - genOutputFileName = outputFileName; -} - -#ifdef WITH_RAGEL_KELBT -void InputData::parseKelbt() -{ - /* - * Ragel Parser from ragel 6. - */ - ifstream *inFileStream; - istream *inStream; - - /* Open the input file for reading. */ - assert( inputFileName != 0 ); - inFileStream = new ifstream( inputFileName ); - if ( ! inFileStream->is_open() ) - error() << "could not open " << inputFileName << " for reading" << endp; - inStream = inFileStream; - - makeFirstInputItem(); - - Scanner scanner( this, inputFileName, *inStream, 0, 0, 0, false ); - - scanner.sectionPass = true; - scanner.do_scan(); - - inStream->clear(); - inStream->seekg( 0, std::ios::beg ); - curItem = inputItems.head; - lastFlush = inputItems.head; - - scanner.sectionPass = false; - scanner.do_scan(); - - /* Finished, final check for errors.. */ - if ( errorCount > 0 ) - abortCompile( 1 ); - - /* Bail on above error. */ - if ( errorCount > 0 ) - abortCompile( 1 ); - - delete inFileStream; -} - -void InputData::processKelbt() -{ - /* With the kelbt version we implement two parse passes. The first is used - * to identify the last time that any given machine is referenced by a - * ragel section. In the second pass we parse, compile, and emit as far - * forward as possible when we encounter the last reference to a machine. - * */ - - if ( generateDot ) { - parseKelbt(); - terminateAllParsers(); - processDot(); - } - else { - createOutputStream(); - openOutput(); - parseKelbt(); - flushRemaining(); - closeOutput(); - } - - assert( errorCount == 0 ); -} -#endif - -bool InputData::parseReduce() -{ - /* - * Colm-based reduction parser introduced in ragel 7. - */ - - TopLevel *topLevel = new TopLevel( frontendSections, this, hostLang, - minimizeLevel, minimizeOpt ); - - /* Check input file. File is actually opened by colm code. We don't - * need to perform the check if in libragel since it comes in via a - * string. */ - if ( input == 0 ) { - ifstream *inFile = new ifstream( inputFileName ); - if ( ! inFile->is_open() ) - error() << "could not open " << inputFileName << " for reading" << endp; - delete inFile; - } - - if ( errorCount ) - return false; - - makeFirstInputItem(); - - curItem = inputItems.head; - lastFlush = inputItems.head; - - - topLevel->reduceFile( "rlparse", inputFileName ); - - if ( errorCount ) - return false; - - bool success = topLevel->success; - - delete topLevel; - return success; -} - -bool InputData::processReduce() -{ - if ( generateDot ) { - parseReduce(); - processDot(); - return true; - } - else { - createOutputStream(); - openOutput(); - - bool success = parseReduce(); - if ( success ) - flushRemaining(); - - closeOutput(); - - if ( !success && outputFileName != 0 ) - unlink( outputFileName ); - - return success; - } -} - -bool InputData::process() -{ - switch ( frontend ) { - case KelbtBased: { -#ifdef WITH_RAGEL_KELBT - processKelbt(); -#endif - return true; - } - case ReduceBased: { - return processReduce(); - } - } - return false; -} - -/* Print a summary of the options. */ -void InputData::usage() -{ - info() << -"usage: ragel [options] file\n" -"general:\n" -" -h, -H, -?, --help Print this usage and exit\n" -" -v, --version Print version information and exit\n" -" -o <file> Write output to <file>\n" -" -s Print some statistics and compilation info to stderr\n" -" -d Do not remove duplicates from action lists\n" -" -I <dir> Add <dir> to the list of directories to search\n" -" for included an imported files\n" -" --rlhc Show the rlhc command used to compile\n" -" --save-temps Do not delete intermediate file during compilation\n" -" --no-intermediate Disable call to rlhc, leave behind intermediate\n" -"error reporting format:\n" -" --error-format=gnu file:line:column: message (default)\n" -" --error-format=msvc file(line,column): message\n" -"fsm minimization:\n" -" -n Do not perform minimization\n" -" -m Minimize at the end of the compilation\n" -" -l Minimize after most operations (default)\n" -" -e Minimize after every operation\n" -"visualization:\n" -" -V Generate a dot file for Graphviz\n" -" -p Display printable characters on labels\n" -" -S <spec> FSM specification to output (for graphviz output)\n" -" -M <machine> Machine definition/instantiation to output (for\n" -" graphviz output)\n" -"host language:\n" -" -C C, C++, Obj-C or Obj-C++ (default)\n" -" All code styles supported.\n" -" --asm --gas-x86-64-sys-v\n" -" GNU AS, x86_64, System V ABI.\n" -" Generated in a code style equivalent to -G2\n" -" -D D All code styles supported\n" -" -Z Go All code styles supported\n" -" -A C# -T0 -T1 -F0 -F1 -G0 -G1\n" -" -J Java -T0 -T1 -F0 -F1\n" -" -R Ruby -T0 -T1 -F0 -F1\n" -" -O OCaml -T0 -T1 -F0 -F1\n" -" -U Rust -T0 -T1 -F0 -F1\n" -" -Y Julia -T0 -T1 -F0 -F1\n" -" -K Crack -T0 -T1 -F0 -F1\n" -" -P JavaScript -T0 -T1 -F0 -F1\n" -"line directives:\n" -" -L Inhibit writing of #line directives\n" -"code style:\n" -" -T0 Binary search (default)\n" -" -T1 Binary search with expanded actions \n" -" -F0 Flat table\n" -" -F1 Flat table with expanded actions\n" -" -G0 Switch-driven\n" -" -G1 Switch-driven with expanded actions\n" -" -G2 Goto-driven with expanded actions\n" -"large machines:\n" -" --integral-tables Use integers for table data (default)\n" -" --string-tables Encode table data into strings for faster host lang\n" -" compilation\n" -"analysis:\n" -" --prior-interaction Search for condition-based general repetitions\n" -" that will not function properly due to state mod\n" -" overlap and must be NFA reps. \n" -" --conds-depth=D Search for high-cost conditions inside a prefix\n" -" of the machine (depth D from start state).\n" -" --state-limit=L Report fail if number of states exceeds this\n" -" during compilation.\n" -" --breadth-check=E1,E2,.. Report breadth cost of named entry points and\n" -" the start state.\n" -" --input-histogram=FN Input char histogram for breadth check. If\n" -" unspecified a flat histogram is used.\n" -"testing:\n" -" --kelbt-frontend Compile using original ragel + kelbt frontend\n" -" Requires ragel be built with ragel + kelbt support\n" -" --colm-frontend Compile using a colm-based recursive descent\n" -" frontend\n" -" --reduce-frontend Compile using a colm-based reducer (default)\n" -" --var-backend Use the variable-based backend even if the host lang\n" -" supports goto-based\n" -" --supported-host-langs Show supported host languages by command line arg\n" -" --supported-frontends Show supported frontends\n" -" --supported-backends Show supported backends\n" -" --force-libragel Cause mainline to behave like libragel\n" - ; - - abortCompile( 0 ); -} - -/* Print version information and exit. */ -void InputData::version() -{ - info() << "Ragel State Machine Compiler version " RAGEL_VERSION << " " RAGEL_PUBDATE << endl << - "Copyright (c) 2001-2019 by Adrian Thurston et al." << endl; - abortCompile( 0 ); -} - -void InputData::showFrontends() -{ - ostream &out = info(); - out << "--colm-frontend"; - out << " --reduce-frontend"; -#ifdef WITH_RAGEL_KELBT - out << " --kelbt-frontend"; -#endif - out << endl; - abortCompile( 0 ); -} - -void InputData::showBackends() -{ - info() << - "--direct-backend --colm-backend" << endl; - abortCompile( 0 ); -} - -InputLoc makeInputLoc( const char *fileName, int line, int col ) -{ - InputLoc loc( fileName, line, col ); - return loc; -} - -void escapeLineDirectivePath( std::ostream &out, char *path ) -{ - for ( char *pc = path; *pc != 0; pc++ ) { - if ( *pc == '\\' ) - out << "\\\\"; - else - out << *pc; - } -} - -void InputData::parseArgs( int argc, const char **argv ) -{ - ParamCheck pc( "o:dnmleabjkS:M:I:vHh?-:sT:F:W:G:LpV", argc, argv ); - - /* Decide if we were invoked using a path variable, or with an explicit path. */ - const char *lastSlash = strrchr( argv[0], '/' ); - if ( lastSlash == 0 ) { - /* Defualt to the the binary install location. */ - dirName = BINDIR; - } - else { - /* Compute dirName from argv0. */ - dirName = string( argv[0], lastSlash - argv[0] ); - } - - /* FIXME: Need to check code styles VS langauge. */ - - while ( pc.check() ) { - switch ( pc.state ) { - case ParamCheck::match: - switch ( pc.parameter ) { - case 'V': - generateDot = true; - break; - - /* Output. */ - case 'o': - if ( *pc.paramArg == 0 ) - error() << "a zero length output file name was given" << endl; - else if ( outputFileName != 0 ) - error() << "more than one output file name was given" << endl; - else { - /* Ok, remember the output file name. */ - outputFileName = new char[strlen(pc.paramArg)+1]; - strcpy( (char*)outputFileName, pc.paramArg ); - } - break; - - /* Flag for turning off duplicate action removal. */ - case 'd': - wantDupsRemoved = false; - break; - - /* Minimization, mostly hidden options. */ - case 'n': - minimizeOpt = MinimizeNone; - break; - case 'm': - minimizeOpt = MinimizeEnd; - break; - case 'l': - minimizeOpt = MinimizeMostOps; - break; - case 'e': - minimizeOpt = MinimizeEveryOp; - break; - case 'a': - #ifdef TO_UPGRADE_CONDS - minimizeLevel = MinimizeApprox; - #else - error() << "minimize approx (-a) unsupported in this version" << endp; - #endif - break; - case 'b': - #ifdef TO_UPGRADE_CONDS - minimizeLevel = MinimizeStable; - #else - error() << "minimize stable (-b) unsupported in this version" << endp; - #endif - break; - case 'j': - minimizeLevel = MinimizePartition1; - break; - case 'k': - minimizeLevel = MinimizePartition2; - break; - - /* Machine spec. */ - case 'S': - if ( *pc.paramArg == 0 ) - error() << "please specify an argument to -S" << endl; - else if ( machineSpec != 0 ) - error() << "more than one -S argument was given" << endl; - else { - /* Ok, remember the path to the machine to generate. */ - machineSpec = pc.paramArg; - } - break; - - /* Machine path. */ - case 'M': - if ( *pc.paramArg == 0 ) - error() << "please specify an argument to -M" << endl; - else if ( machineName != 0 ) - error() << "more than one -M argument was given" << endl; - else { - /* Ok, remember the machine name to generate. */ - machineName = pc.paramArg; - } - break; - - case 'I': - if ( *pc.paramArg == 0 ) - error() << "please specify an argument to -I" << endl; - else { - includePaths.append( pc.paramArg ); - } - break; - - /* Version and help. */ - case 'v': - version(); - break; - case 'H': case 'h': case '?': - usage(); - break; - case 's': - printStatistics = true; - break; - case '-': { - char *arg = strdup( pc.paramArg ); - char *eq = strchr( arg, '=' ); - - if ( eq != 0 ) - *eq++ = 0; - - if ( strcmp( arg, "help" ) == 0 ) - usage(); - else if ( strcmp( arg, "version" ) == 0 ) - version(); - else if ( strcmp( arg, "error-format" ) == 0 ) { - if ( eq == 0 ) - error() << "expecting '=value' for error-format" << endl; - else if ( strcmp( eq, "gnu" ) == 0 ) - errorFormat = ErrorFormatGNU; - else if ( strcmp( eq, "msvc" ) == 0 ) - errorFormat = ErrorFormatMSVC; - else - error() << "invalid value for error-format" << endl; - } - else if ( strcmp( arg, "rlhc" ) == 0 ) - rlhc = true; - else if ( strcmp( arg, "no-intermediate" ) == 0 ) - noIntermediate = true; -#ifdef WITH_RAGEL_KELBT - else if ( strcmp( arg, "kelbt-frontend" ) == 0 ) { - frontend = KelbtBased; - frontendSpecified = true; - } -#else - else if ( strcmp( arg, "kelbt-frontend" ) == 0 ) { - error() << "--kelbt-frontend specified but, " - "ragel not built with ragel+kelbt support" << endp; - } -#endif - else if ( strcmp( arg, "reduce-frontend" ) == 0 ) { - frontend = ReduceBased; - frontendSpecified = true; - } - else if ( strcmp( arg, "string-tables" ) == 0 ) - stringTables = true; - else if ( strcmp( arg, "integral-tables" ) == 0 ) - stringTables = false; - else if ( strcmp( arg, "supported-frontends" ) == 0 ) - showFrontends(); - else if ( strcmp( arg, "supported-backends" ) == 0 ) - showBackends(); - else if ( strcmp( arg, "save-temps" ) == 0 ) - saveTemps = true; - - else if ( strcmp( arg, "prior-interaction" ) == 0 ) - checkPriorInteraction = true; - else if ( strcmp( arg, "conds-depth" ) == 0 ) - condsCheckDepth = strtol( eq, 0, 10 ); - else if ( strcmp( arg, "state-limit" ) == 0 ) - stateLimit = strtol( eq, 0, 10 ); - - else if ( strcmp( arg, "breadth-check" ) == 0 ) { - char *ptr = 0; - while ( true ) { - char *label = strtok_r( eq, ",", &ptr ); - eq = NULL; - if ( label == NULL ) - break; - breadthLabels.append( strdup( label ) ); - } - checkBreadth = true; - } - else if ( strcmp( arg, "input-histogram" ) == 0 ) - histogramFn = strdup(eq); - else if ( strcmp( arg, "var-backend" ) == 0 ) - forceVar = true; - else if ( strcmp( arg, "no-fork" ) == 0 ) - noFork = true; - else { - error() << "--" << pc.paramArg << - " is an invalid argument" << endl; - } - free( arg ); - break; - } - - /* Passthrough args. */ - case 'T': - if ( pc.paramArg[0] == '0' ) - codeStyle = GenBinaryLoop; - else if ( pc.paramArg[0] == '1' ) - codeStyle = GenBinaryExp; - else { - error() << "-T" << pc.paramArg[0] << - " is an invalid argument" << endl; - abortCompile( 1 ); - } - break; - case 'F': - if ( pc.paramArg[0] == '0' ) - codeStyle = GenFlatLoop; - else if ( pc.paramArg[0] == '1' ) - codeStyle = GenFlatExp; - else { - error() << "-F" << pc.paramArg[0] << - " is an invalid argument" << endl; - abortCompile( 1 ); - } - break; - case 'G': - if ( pc.paramArg[0] == '0' ) - codeStyle = GenGotoLoop; - else if ( pc.paramArg[0] == '1' ) - codeStyle = GenGotoExp; - else if ( pc.paramArg[0] == '2' ) - codeStyle = GenIpGoto; - else if ( pc.paramArg[0] == 'T' && pc.paramArg[1] == '2' ) { - codeStyle = GenIpGoto; - maxTransitions = 32; - } else { - error() << "-G" << pc.paramArg[0] << - " is an invalid argument" << endl; - abortCompile( 1 ); - } - break; - case 'W': - if ( pc.paramArg[0] == '0' ) - codeStyle = GenSwitchLoop; - else if ( pc.paramArg[0] == '1' ) - codeStyle = GenSwitchExp; - else { - error() << "-G" << pc.paramArg[0] << - " is an invalid argument" << endl; - abortCompile( 1 ); - } - break; - - case 'p': - displayPrintables = true; - break; - - case 'L': - noLineDirectives = true; - break; - } - break; - - case ParamCheck::invalid: - error() << "-" << pc.parameter << " is an invalid argument" << endl; - break; - - case ParamCheck::noparam: - /* It is interpreted as an input file. */ - if ( *pc.curArg == 0 ) - error() << "a zero length input file name was given" << endl; - else if ( inputFileName != 0 ) - error() << "more than one input file name was given" << endl; - else { - /* OK, Remember the filename. */ - inputFileName = pc.curArg; - } - break; - } - } -} - -void InputData::loadHistogram() -{ - const int alphsize = 256; - - /* Init a default. */ - histogram = new double[alphsize]; - ifstream h( histogramFn ); - if ( !h.is_open() ) - error() << "histogram read: failed to open file: " << histogramFn << endp; - - int i = 0; - double value; - while ( true ) { - if ( h >> value ) { - if ( i >= alphsize ) { - /* Too many items. */ - error() << "histogram read: too many histogram values," - " expecting " << alphsize << " (for char alphabet)" << endp; - } - histogram[i] = value; - i++; - } - else { - /* Read failure. */ - if ( h.eof() ) { - if ( i < alphsize ) { - error() << "histogram read: fell short of " << - alphsize << " items" << endp; - } - break; - } - else { - error() << "histogram read: error at item " << i << endp; - } - } - } -} - -void InputData::defaultHistogram() -{ - /* Flat histogram. */ - const int alphsize = 256; - histogram = new double[alphsize]; - for ( int i = 0; i < alphsize; i++ ) { - histogram[i] = 1.0 / (double)alphsize; - } -} - -void InputData::checkArgs() -{ - /* Require an input file. If we use standard in then we won't have a file - * name on which to base the output. */ - if ( inputFileName == 0 ) - error() << "no input file given" << endl; - - /* Bail on argument processing errors. */ - if ( errorCount > 0 ) - abortCompile( 1 ); - - /* Make sure we are not writing to the same file as the input file. */ - if ( inputFileName != 0 && outputFileName != 0 && - strcmp( inputFileName, outputFileName ) == 0 ) - { - error() << "output file \"" << outputFileName << - "\" is the same as the input file" << endp; - } - - if ( !frontendSpecified ) - frontend = ReduceBased; - - if ( checkBreadth ) { - if ( histogramFn != 0 ) - loadHistogram(); - else - defaultHistogram(); - } -} - -char *InputData::readInput( const char *inputFileName ) -{ - struct stat st; - int res = stat( inputFileName, &st ); - if ( res != 0 ) { - error() << inputFileName << ": stat failed: " << strerror(errno) << endl; - return 0; - } - - std::ifstream in( inputFileName ); - if ( !in.is_open() ) { - error() << inputFileName << ": could not open in force-libragel mode"; - return 0; - } - - char *input = new char[st.st_size+1]; - in.read( input, st.st_size ); - if ( in.gcount() != st.st_size ) { - error() << inputFileName << ": could not read in force-libragel mode"; - delete[] input; - return 0; - } - input[st.st_size] = 0; - - return input; -} - -int InputData::main( int argc, const char **argv ) -{ - int code = 0; - try { - parseArgs( argc, argv ); - checkArgs(); - if ( !generateDot ) - makeDefaultFileName(); - - if ( !process() ) - abortCompile( 1 ); - } - catch ( const AbortCompile &ac ) { - code = ac.code; - } - - return code; -} - -int InputData::runFrontend( int argc, const char **argv ) -{ - if ( !process() ) - return -1; - return 0; -} - -int InputData::runRlhc( int argc, const char **argv ) -{ - struct colm_program *prg; - int exit_status; - - prg = colm_new_program( rlhcSections ); - colm_set_debug( prg, 0 ); - colm_run_program( prg, argc, argv ); - exit_status = colm_delete_program( prg ); - return exit_status; -} - -/* Run a job (frontend or backend). If we want forks then we return the result - * via the process's exit code. otherwise it comes back on the stack. */ -int InputData::runJob( const char *what, IdProcess idProcess, int argc, const char **argv ) -{ -#if defined(HAVE_SYS_WAIT_H) - if ( !noFork ) { - pid_t pid = fork(); - - if ( pid == 0 ) { - int es = (this->*idProcess)( argc, argv ); - exit( es ); - } - - int status = 0; - waitpid( pid, &status, 0 ); - if ( WIFSIGNALED(status) ) { - error() << what << " stopped by signal: " << WTERMSIG(status) << std::endl; - return -1; - } - - return WEXITSTATUS( status ); - } -#endif - return (this->*idProcess)( argc, argv ); -} - -int InputData::rlhcMain( int argc, const char **argv ) -{ - parseArgs( argc, argv ); - checkArgs(); - makeDefaultFileName(); - makeTranslateOutputFileName(); - - int es = runJob( "frontend", &InputData::runFrontend, 0, 0 ); - - if ( es != 0 ) - return es; - - /* rlhc <input> <output> */ - const char *_argv[] = { "rlhc", - genOutputFileName.c_str(), - origOutputFileName.c_str(), 0 }; - - return runJob( "rlhc", &InputData::runRlhc, 3, _argv ); -} diff --git a/libfsm/libragel.h b/libfsm/libragel.h deleted file mode 100644 index ad328e86..00000000 --- a/libfsm/libragel.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016-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 _LIBRAGEL_H -#define _LIBRAGEL_H - -#ifdef __cplusplus -#define EXTERN_C extern "C" -#else -#define EXTERN_C -#endif - -#endif diff --git a/libfsm/load.h b/libfsm/load.h deleted file mode 100644 index 6ef7d57c..00000000 --- a/libfsm/load.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013-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 _LOAD_H -#define _LOAD_H - -#include "ragel.h" - -struct LoadRagel; -struct InputData; -struct HostLang; - -LoadRagel *newLoadRagel( InputData &id, const HostLang *hostLang, - MinimizeLevel minimizeLevel, MinimizeOpt minimizeOpt ); -void loadRagel( LoadRagel *lr, const char *inputFileName ); -void deleteLoadRagel( LoadRagel * ); - -#endif diff --git a/libfsm/pcheck.h b/libfsm/pcheck.h deleted file mode 100644 index adc011b3..00000000 --- a/libfsm/pcheck.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 _PCHECK_H -#define _PCHECK_H - -class ParamCheck -{ -public: - ParamCheck( const char *paramSpec, int argc, const char **argv); - - bool check(); - - const char *paramArg; /* The argument to the parameter. */ - char parameter; /* The parameter matched. */ - enum { match, invalid, noparam } state; - - const char *argOffset; /* If we are reading params inside an - * arg this points to the offset. */ - - const char *curArg; /* Pointer to the current arg. */ - int iCurArg; /* Index to the current arg. */ - -private: - const char *paramSpec; /* Parameter spec supplied by the coder. */ - int argc; /* Arguement data from the command line. */ - const char **argv; -}; - -#endif diff --git a/libfsm/reducer.cc b/libfsm/reducer.cc deleted file mode 100644 index 592dcfe1..00000000 --- a/libfsm/reducer.cc +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2015-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. - */ - -#include "reducer.h" - -#include <colm/colm.h> -#include <colm/tree.h> - -#include <errno.h> - -using std::endl; -using std::ifstream; - -void TopLevel::loadMachineName( string data ) -{ - /* Make/get the priority key. The name may have already been referenced - * and therefore exist. */ - PriorDictEl *priorDictEl; - if ( pd->priorDict.insert( data, pd->fsmCtx->nextPriorKey, &priorDictEl ) ) - pd->fsmCtx->nextPriorKey += 1; - pd->curDefPriorKey = priorDictEl->value; - - /* Make/get the local error key. */ - LocalErrDictEl *localErrDictEl; - if ( pd->localErrDict.insert( data, pd->nextLocalErrKey, &localErrDictEl ) ) - pd->nextLocalErrKey += 1; - pd->curDefLocalErrKey = localErrDictEl->value; -} - -void TopLevel::tryMachineDef( const InputLoc &loc, std::string name, - MachineDef *machineDef, bool isInstance ) -{ - GraphDictEl *newEl = pd->graphDict.insert( name ); - if ( newEl != 0 ) { - /* New element in the dict, all good. */ - newEl->value = new VarDef( name, machineDef ); - newEl->isInstance = isInstance; - newEl->loc = loc; - newEl->value->isExport = exportContext[exportContext.length()-1]; - - /* It it is an instance, put on the instance list. */ - if ( isInstance ) - pd->instanceList.append( newEl ); - } - else { - // Recover by ignoring the duplicate. - pd->id->error(loc) << "fsm \"" << name << "\" previously defined" << endl; - } -} - -long TopLevel::tryLongScan( const InputLoc &loc, const char *data ) -{ - /* Convert the priority number to a long. Check for overflow. */ - long priorityNum; - errno = 0; - - long aug = strtol( data, 0, 10 ); - if ( errno == ERANGE && aug == LONG_MAX ) { - /* Priority number too large. Recover by setting the priority to 0. */ - pd->id->error(loc) << "priority number " << data << - " overflows" << endl; - priorityNum = 0; - } - else if ( errno == ERANGE && aug == LONG_MIN ) { - /* Priority number too large in the neg. Recover by using 0. */ - pd->id->error(loc) << "priority number " << data << - " underflows" << endl; - priorityNum = 0; - } - else { - /* No overflow or underflow. */ - priorityNum = aug; - } - - return priorityNum; -} - -void TopLevel::include( const InputLoc &incLoc, bool fileSpecified, string fileName, string machine ) -{ - /* Stash the current section name and pd. */ - string sectionName = pd->sectionName; - ParseData *pd0 = pd; - - const char **includeChecks = 0; - long found = 0; - - const char *inclSectionName = machine.c_str(); - - /* Default the section name to the current section name. */ - if ( inclSectionName == 0 ) - inclSectionName = sectionName.c_str(); - - /* Build the include checks. */ - if ( fileSpecified ) - includeChecks = pd->id->makeIncludePathChecks( curFileName, fileName.c_str() ); - else { - char *test = new char[strlen(curFileName)+1]; - strcpy( test, curFileName ); - - includeChecks = new const char*[2]; - - includeChecks[0] = test; - includeChecks[1] = 0; - } - - /* Try to find the file. */ - ifstream *inFile = pd->id->tryOpenInclude( includeChecks, found ); - if ( inFile == 0 ) { - id->error(incLoc) << "include: failed to locate file" << endl; - const char **tried = includeChecks; - while ( *tried != 0 ) - id->error(incLoc) << "include: attempted: \"" << *tried++ << '\"' << endl; - - return; - } - - delete inFile; - -// /* Don't include anything that's already been included. */ -// if ( !pd->duplicateInclude( includeChecks[found], inclSectionName ) ) { -// pd->includeHistory.push_back( IncludeHistoryItem( -// includeChecks[found], inclSectionName ) ); -// -// /* Either we are not in the lib, or a file was specifed, use the -// * file-based include pass. */ -// includePass.reduceFile( includeChecks[found], id->hostLang ); -// } - - const char *targetMachine0 = targetMachine; - const char *searchMachine0 = searchMachine; - - includeDepth += 1; - pd = 0; - - targetMachine = sectionName.c_str(); - searchMachine = machine.c_str(); - - // reduceFile( includeChecks[found] ); - -// if ( includePass.incItems.length() == 0 ) { -// pd->id->error(incLoc) << "could not find machine " << machine << -// " in " << fileName << endp; -// } -// else { -// /* Load the data into include el. Save in the dict. */ -// loadIncludeData( el, includePass, includeChecks[found] ); -// id->includeDict.insert( el ); -// includePass.incItems.empty(); -// } - - pd = pd0; - includeDepth -= 1; - - targetMachine = targetMachine0; - searchMachine = searchMachine0; -} - -void TopLevel::import( const InputLoc &loc, std::string name, Literal *literal ) -{ - MachineDef *machineDef = new MachineDef( - new Join( - new Expression( - new Term( - new FactorWithAug( - new FactorWithRep( - new FactorWithNeg( new Factor( literal ) ) - ) - ) - ) - ) - ) - ); - - /* Generic creation of machine for instantiation and assignment. */ - tryMachineDef( loc, name, machineDef, false ); - machineDef->join->loc = loc; -} - -void TopLevel::reduceFile( const char *cmd, const char *inputFileName ) -{ - const int baseN = 2; - const char **argv = new const char*[baseN + id->includePaths.length() + 1]; - argv[0] = cmd; - argv[1] = inputFileName; - for ( int i = 0; i < id->includePaths.length(); i++ ) - argv[baseN + i] = id->includePaths.data[i]; - argv[baseN + id->includePaths.length()] = 0; - - const char *prevCurFileName = curFileName; - curFileName = inputFileName; - - colm_program *program = colm_new_program( frontendSections ); - colm_set_debug( program, 0 ); - colm_set_reduce_clean( program, 0 ); - colm_set_reduce_ctx( program, this ); - colm_run_program( program, baseN + id->includePaths.length(), argv ); - id->streamFileNames.append( colm_extract_fns( program ) ); - - int length = 0; - const char *err = colm_error( program, &length ); - if ( err != 0 ) { - // std::cout << "error" << std::endl; - id->error_plain() << string( err, length ) << std::endl; - } - - colm_delete_program( program ); - - curFileName = prevCurFileName; - - delete[] argv; -} diff --git a/libfsm/reducer.h b/libfsm/reducer.h deleted file mode 100644 index 0d0f1af1..00000000 --- a/libfsm/reducer.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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. - */ - -#include <colm/pdarun.h> -#include <colm/bytecode.h> -#include <colm/defs.h> -#include <colm/input.h> -#include <colm/tree.h> -#include <colm/program.h> -#include <colm/colm.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include <iostream> -#include <vector> -#include <string> - -#include "vector.h" -#include "inputdata.h" -#include "parsedata.h" - -#ifndef _REDUCER_H -#define _REDUCER_H - -char *unescape( const char *s, int slen ); -char *unescape( const char *s ); - -struct SectionPass; - -struct TopLevel -{ - TopLevel( struct colm_sections *frontendSections, InputData *id, const HostLang *hostLang, - MinimizeLevel minimizeLevel, MinimizeOpt minimizeOpt ) - : - frontendSections(frontendSections), - id(id), - section(0), - pd(0), - machineSpec(0), - machineName(0), - includeDepth(0), - hostLang(hostLang), - minimizeLevel(minimizeLevel), - minimizeOpt(minimizeOpt), - - /* Should be passed into the load, somehow. */ - targetMachine(0), - searchMachine(0), - paramList(0), - success(true), - isImport(false) - { - exportContext.append( false ); - } - - struct colm_sections *frontendSections; - InputData *id; - Section *section; - SectionPass *sectionPass; - ParseData *pd; - char *machineSpec; - char *machineName; - int includeDepth; - const HostLang *hostLang; - MinimizeLevel minimizeLevel; - MinimizeOpt minimizeOpt; - std::vector<std::string> writeArgs; - - /* Should this go in the parse data? Probably. */ - Vector<bool> exportContext; - - const char *curFileName; - - const char *targetMachine; - const char *searchMachine; - - ActionParamList *paramList; - bool success; - - /* Generated and called by colm. */ - void commit_reduce_forward( program_t *prg, tree_t **root, - struct pda_run *pda_run, parse_tree_t *pt ); - void read_reduce_forward( program_t *prg, FILE *file ); - - void loadMachineName( string data ); - void tryMachineDef( const InputLoc &loc, std::string name, - MachineDef *machineDef, bool isInstance ); - long tryLongScan( const InputLoc &loc, const char *data ); - void include( const InputLoc &incLoc, bool fileSpecified, string fileName, string machine ); - void reduceFile( const char *cmd, const char *inputFileName ); - - void import( const InputLoc &loc, std::string name, Literal *literal ); - void importFile( std::string fileName ); - - bool isImport; -}; - -#endif diff --git a/libfsm/rlscan.h b/libfsm/rlscan.h deleted file mode 100644 index e8b4047d..00000000 --- a/libfsm/rlscan.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2007-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 _RLSCAN_H -#define _RLSCAN_H - -#include <iostream> -#include "rlscan.h" -#include "vector.h" -#ifdef WITH_RAGEL_KELBT -#include "rlparse.h" -#endif -#include "parsedata.h" -#include "avltree.h" -#include "vector.h" - -using std::istream; -using std::ostream; - -extern char *Parser6_lelNames[]; -struct Section; - -struct Scanner -{ - Scanner( InputData *id, const char *fileName, istream &input, - Parser6 *inclToParser, char *inclSectionTarg, - int includeDepth, bool importMachines ) - : - id(id), fileName(fileName), - input(input), - inclToParser(inclToParser), - inclSectionTarg(inclSectionTarg), - includeDepth(includeDepth), - importMachines(importMachines), - cur_token(0), - line(1), column(1), lastnl(0), - parser(0), ignoreSection(false), - parserExistsError(false), - whitespaceOn(true), - lastToken(0), - section(0), - sectionPass(false) - {} - - void handleMachine(); - void handleInclude(); - void handleImport(); - - void init(); - void token( int type, char *start, char *end ); - void token( int type, char c ); - void token( int type ); - void processToken( int type, char *tokdata, int toklen ); - void directToParser( Parser6 *toParser, const char *tokFileName, int tokLine, - int tokColumn, int type, char *tokdata, int toklen ); - void flushImport( ); - void importToken( int type, char *start, char *end ); - void pass( int token, char *start, char *end ); - void pass(); - void updateCol(); - void startSection(); - void endSection(); - void do_scan(); - bool active(); - InputLoc scan_loc(); - - InputData *id; - const char *fileName; - istream &input; - Parser6 *inclToParser; - char *inclSectionTarg; - int includeDepth; - bool importMachines; - - /* For import parsing. */ - int tok_cs, tok_act; - int *tok_ts, *tok_te; - int cur_token; - static const int max_tokens = 32; - int token_data[max_tokens]; - char *token_strings[max_tokens]; - int token_lens[max_tokens]; - - /* For section processing. */ - int cs; - char *word, *lit; - int word_len, lit_len; - - /* For character scanning. */ - int line; - InputLoc sectionLoc; - char *ts, *te; - int column; - char *lastnl; - - /* Set by machine statements, these persist from section to section - * allowing for unnamed sections. */ - Parser6 *parser; - bool ignoreSection; - - /* This is set if ragel has already emitted an error stating that - * no section name has been seen and thus no parser exists. */ - bool parserExistsError; - - /* This is for inline code. By default it is on. It goes off for - * statements and values in inline blocks which are parsed. */ - bool whitespaceOn; - - /* Keeps a record of the previous token sent to the section parser. */ - int lastToken; - - Section *section; - bool sectionPass; - -}; - -#endif diff --git a/libfsm/xmlparse.kh b/libfsm/xmlparse.kh deleted file mode 100644 index 1b0b30ad..00000000 --- a/libfsm/xmlparse.kh +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2001-2007 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 _XMLPARSE_H -#define _XMLPARSE_H - -#include "vector.h" -#include "gendata.h" -#include "buffer.h" -#include <iostream> - -using std::istream; -using std::ostream; - -#define XML_BUFSIZE 4096 - -struct AttrMarker -{ - char *id; - int idLen; - char *value; - int valueLen; -}; - -struct Attribute -{ - char *id; - char *value; -}; - -typedef Vector<AttrMarker> AttrMkList; -typedef Vector<Attribute> AttrList; -struct XMLTagHashPair; - -struct XMLTag -{ - enum TagType { Open, Close }; - - XMLTag( XMLTagHashPair *tagId, TagType type ) : - tagId(tagId), type(type), - content(0), attrList(0) {} - - Attribute *findAttr( const char *id ) - { - if ( attrList != 0 ) { - for ( AttrList::Iter attr = *attrList; attr.lte(); attr++ ) { - if ( strcmp( id, attr->id ) == 0 ) - return attr; - } - } - return 0; - } - - XMLTagHashPair *tagId; - TagType type; - - /* Content is associtated with closing tags. */ - char *content; - - /* Attribute lists are associated with opening tags. */ - AttrList *attrList; -}; - - -struct XMLTagHashPair -{ - const char *name; - int id; -}; - -struct Token; - -struct GenInlineItem; -struct GenInlineList; - -struct LmSwitchVect; -struct LmSwitchAction; - -struct XmlScanner -{ - XmlScanner( const char *fileName, istream &input ); - - int scan(); - void adjustAttrPointers( int distance ); - std::ostream &error(); - - const char *fileName; - istream &input; - - /* Scanner State. */ - int cs, act, have, curline, curcol; - char *ts, *te; - char *p, *pe; - int done; - - /* Token data */ - char *data; - int data_len; - int value; - AttrMkList attrMkList; - Buffer buffer; - char *tag_id_start; - int tag_id_len; - int token_col, token_line; - - char buf[XML_BUFSIZE]; -}; - - -struct XmlParser -{ - %%{ - parser XmlParser; - - token TAG_unknown, TAG_ragel, TAG_ragel_def, TAG_host, TAG_state_list, - TAG_state, TAG_trans_list, TAG_t, TAG_machine, TAG_start_state, - TAG_error_state, TAG_action_list, TAG_action_table_list, - TAG_action, TAG_action_table, TAG_alphtype, TAG_element, - TAG_getkey, TAG_state_actions, TAG_entry_points, TAG_sub_action, - TAG_cond_space_list, TAG_cond_space, TAG_cond_list, TAG_c, - TAG_exports, TAG_ex; - - # Inline block tokens. - token TAG_text, TAG_goto, TAG_call, TAG_next, TAG_goto_expr, - TAG_call_expr, TAG_next_expr, TAG_ret, TAG_pchar, TAG_char, - TAG_hold, TAG_exec, TAG_curs, TAG_targs, TAG_entry, TAG_data, - TAG_lm_switch, TAG_init_act, TAG_set_act, TAG_set_tokend, - TAG_get_tokend, TAG_init_tokstart, TAG_set_tokstart; - - token TAG_write, TAG_access, TAG_break, TAG_arg, TAG_cs_expr; - - token TAG_p_expr, TAG_pe_expr, TAG_eof_expr, TAG_cs_expr, TAG_top_expr, - TAG_stack_expr, TAG_act_expr, TAG_tokstart_expr, TAG_tokend_expr, - TAG_data_expr, TAG_prepush, TAG_postpop, TAG_eof_t; - }%% - - %% write instance_data; - - void init(); - int parseLangEl( int type, const Token *token ); - - XmlParser( const char *sourceFileName, const char *xmlFileName, bool outputActive, bool wantComplete ) : - sourceFileName(sourceFileName), - fileName(xmlFileName), - outStream(0), - outputActive(outputActive), - wantComplete(wantComplete), - cgd(0) { } - - int token( int tokenId, Token &token ); - int token( int tokenId, int col, int line ); - int token( XMLTag *tag, int col, int line ); - - void openOutput(); - - /* Report an error encountered by the parser. */ - ostream &warning( const InputLoc &loc ); - ostream &error(); - ostream &error( const InputLoc &loc ); - ostream &parser_error( int tokId, Token &token ); - ostream &source_error( const InputLoc &loc ); - - /* The name of the root section, this does not change during an include. */ - const char *sourceFileName; - const char *fileName; - ostream *outStream; - bool outputActive; - bool wantComplete; - - /* Collected during parsing. */ - char *attrKey; - char *attrValue; - int curAction; - int curActionTable; - int curTrans; - int curState; - int curCondSpace; - int curStateCond; - - CodeGenData *cgd; - CodeGenMap codeGenMap; - - Vector <char*> writeOptions; -}; - -%% write token_defs; - -int xml_parse( std::istream &input, const char *fileName, - bool outputActive, bool wantComplete, - XmlScanner &scanner, XmlParser &parser ); - -#endif diff --git a/libfsm/xmlparse.kl b/libfsm/xmlparse.kl deleted file mode 100644 index 04d95b83..00000000 --- a/libfsm/xmlparse.kl +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Copyright 2001-2007 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. - */ - -#include "xmlparse.h" -#include "common.h" -#include "gendata.h" -#include "version.h" -#include <iostream> -#include <stdlib.h> - -using std::ostream; -using std::istream; -using std::cerr; -using std::endl; - -Key readKey( char *td, char **end ); -long readOffsetPtr( char *td, char **end ); -unsigned long readLength( char *td ); - -struct Token -{ - XMLTag *tag; - InputLoc loc; -}; - -%%{ - -parser XmlParser; - -include "xmlparse.kh"; - -start: tag_ragel; -start: - final { - /* If we get no input the assumption is that the frontend died and - * emitted an error. This forces the backend to return a non-zero - * exit status, but does not print an error. */ - gblErrorCount += 1; - }; - -tag_ragel: tag_ragel_head ragel_def_list host_or_write_list '/' TAG_ragel; - -tag_ragel_head: TAG_ragel - final { - /* Check version used to generated the intermediate file. */ - Attribute *versionAttr = $1->tag->findAttr( "version" ); - if ( versionAttr == 0 ) - error($1->loc) << "tag <ragel> requires a version attribute" << endp; - if ( strcmp( versionAttr->value, VERSION ) != 0 ) - error($1->loc) << "version mismatch between frontend and backend" << endp; - - /* Check for file name attribute. */ - Attribute *fileNameAttr = $1->tag->findAttr( "filename" ); - if ( fileNameAttr == 0 ) - error($1->loc) << "tag <ragel> requires a filename attribute" << endp; - sourceFileName = fileNameAttr->value; - - /* Check for language attribute. */ - Attribute *langAttr = $1->tag->findAttr( "lang" ); - if ( langAttr == 0 ) - error($1->loc) << "tag <ragel> requires a lang attribute" << endp; - - if ( generateDot ) - outStream = dotOpenOutput( sourceFileName ); - else if ( strcmp( langAttr->value, "C" ) == 0 ) { - hostLang = &hostLangC; - outStream = cdOpenOutput( sourceFileName ); - } - else if ( strcmp( langAttr->value, "D" ) == 0 ) { - hostLang = &hostLangD; - outStream = cdOpenOutput( sourceFileName ); - } - else if ( strcmp( langAttr->value, "Java" ) == 0 ) { - hostLang = &hostLangJava; - outStream = javaOpenOutput( sourceFileName ); - } - else if ( strcmp( langAttr->value, "Ruby" ) == 0 ) { - hostLang = &hostLangRuby; - outStream = rubyOpenOutput( sourceFileName ); - } - else if ( strcmp( langAttr->value, "C#" ) == 0 ) { - hostLang = &hostLangCSharp; - outStream = csharpOpenOutput( sourceFileName ); - } - else { - error($1->loc) << "expecting lang attribute to be " - "one of C, D, Java, Ruby or C#" << endp; - } - }; - -ragel_def_list: ragel_def_list ragel_def; -ragel_def_list: ; - -host_or_write_list: host_or_write_list host_or_write; -host_or_write_list: ; - -host_or_write: tag_host; -host_or_write: tag_write; - -tag_host: - TAG_host '/' TAG_host - final { - Attribute *lineAttr = $1->tag->findAttr( "line" ); - if ( lineAttr == 0 ) - error($1->loc) << "tag <host> requires a line attribute" << endp; - else { - int line = atoi( lineAttr->value ); - if ( outputActive ) - lineDirective( *outStream, sourceFileName, line ); - } - - if ( outputActive ) - *outStream << $3->tag->content; - }; - -ragel_def: - tag_ragel_def_head ragel_def_item_list '/' TAG_ragel_def - final { - /* Do this before distributing transitions out to singles and defaults - * makes life easier. */ - cgd->redFsm->maxKey = cgd->findMaxKey(); - - cgd->redFsm->assignActionLocs(); - - /* Find the first final state (The final state with the lowest id). */ - cgd->redFsm->findFirstFinState(); - - /* Call the user's callback. */ - cgd->finishRagelDef(); - }; - -tag_ragel_def_head: TAG_ragel_def - final { - char *fsmName = 0; - Attribute *nameAttr = $1->tag->findAttr( "name" ); - if ( nameAttr != 0 ) { - fsmName = nameAttr->value; - - CodeGenMapEl *mapEl = codeGenMap.find( fsmName ); - if ( mapEl != 0 ) - cgd = mapEl->value; - else { - cgd = makeCodeGen( sourceFileName, fsmName, *outStream, wantComplete ); - codeGenMap.insert( fsmName, cgd ); - } - } - else { - cgd = makeCodeGen( sourceFileName, fsmName, - *outStream, wantComplete ); - } - - ::keyOps = &cgd->thisKeyOps; - }; - -ragel_def_item_list: ragel_def_item_list ragel_def_item; -ragel_def_item_list: ; - -ragel_def_item: tag_alph_type; -ragel_def_item: tag_getkey_expr; -ragel_def_item: tag_access_expr; -ragel_def_item: tag_prepush_expr; -ragel_def_item: tag_postpop_expr; -ragel_def_item: tag_export_list; -ragel_def_item: tag_machine; -ragel_def_item: tag_p_expr; -ragel_def_item: tag_pe_expr; -ragel_def_item: tag_eof_expr; -ragel_def_item: tag_cs_expr; -ragel_def_item: tag_top_expr; -ragel_def_item: tag_stack_expr; -ragel_def_item: tag_act_expr; -ragel_def_item: tag_tokstart_expr; -ragel_def_item: tag_tokend_expr; -ragel_def_item: tag_data_expr; - -tag_export_list: TAG_exports export_list '/' TAG_exports; - -export_list: export_list tag_export; -export_list: ; - -tag_export: TAG_ex '/' TAG_ex - final { - Attribute *nameAttr = $1->tag->findAttr( "name" ); - if ( nameAttr == 0 ) - error($1->loc) << "tag <ex> requires a name attribute" << endp; - else { - char *td = $3->tag->content; - Key exportKey = readKey( td, &td ); - cgd->exportList.append( new Export( nameAttr->value, exportKey ) ); - } - }; - -tag_alph_type: TAG_alphtype '/' TAG_alphtype - final { - if ( ! cgd->setAlphType( $3->tag->content ) ) - error($1->loc) << "tag <alphtype> specifies unknown alphabet type" << endp; - }; - -tag_getkey_expr: TAG_getkey inline_list '/' TAG_getkey - final { - cgd->getKeyExpr = $2->inlineList; - }; - -tag_access_expr: TAG_access inline_list '/' TAG_access - final { - cgd->accessExpr = $2->inlineList; - }; - -tag_prepush_expr: TAG_prepush inline_list '/' TAG_prepush - final { - cgd->prePushExpr = $2->inlineList; - }; - -tag_postpop_expr: TAG_postpop inline_list '/' TAG_postpop - final { - cgd->postPopExpr = $2->inlineList; - }; - -tag_p_expr: TAG_p_expr inline_list '/' TAG_p_expr - final { cgd->pExpr = $2->inlineList; }; -tag_pe_expr: TAG_pe_expr inline_list '/' TAG_pe_expr - final { cgd->peExpr = $2->inlineList; }; -tag_eof_expr: TAG_eof_expr inline_list '/' TAG_eof_expr - final { cgd->eofExpr = $2->inlineList; }; -tag_cs_expr: TAG_cs_expr inline_list '/' TAG_cs_expr - final { cgd->csExpr = $2->inlineList; }; -tag_top_expr: TAG_top_expr inline_list '/' TAG_top_expr - final { cgd->topExpr = $2->inlineList; }; -tag_stack_expr: TAG_stack_expr inline_list '/' TAG_stack_expr - final { cgd->stackExpr = $2->inlineList; }; -tag_act_expr: TAG_act_expr inline_list '/' TAG_act_expr - final { cgd->actExpr = $2->inlineList; }; -tag_tokstart_expr: TAG_tokstart_expr inline_list '/' TAG_tokstart_expr - final { cgd->tokstartExpr = $2->inlineList; }; -tag_tokend_expr: TAG_tokend_expr inline_list '/' TAG_tokend_expr - final { cgd->tokendExpr = $2->inlineList; }; -tag_data_expr: TAG_data_expr inline_list '/' TAG_data_expr - final { cgd->dataExpr = $2->inlineList; }; - - -tag_write: tag_write_head write_option_list '/' TAG_write - final { - /* Terminate the options list and call the write statement handler. */ - writeOptions.append(0); - cgd->writeStatement( $1->loc, writeOptions.length()-1, writeOptions.data ); - - /* Clear the options in prep for the next write statement. */ - writeOptions.empty(); - }; - -nonterm tag_write_head -{ - InputLoc loc; -}; - -tag_write_head: TAG_write - final { - Attribute *nameAttr = $1->tag->findAttr( "def_name" ); - Attribute *lineAttr = $1->tag->findAttr( "line" ); - Attribute *colAttr = $1->tag->findAttr( "col" ); - - if ( nameAttr == 0 ) - error($1->loc) << "tag <write> requires a def_name attribute" << endp; - if ( lineAttr == 0 ) - error($1->loc) << "tag <write> requires a line attribute" << endp; - if ( colAttr == 0 ) - error($1->loc) << "tag <write> requires a col attribute" << endp; - - if ( nameAttr != 0 && lineAttr != 0 && colAttr != 0 ) { - $$->loc.line = atoi(lineAttr->value); - $$->loc.col = atoi(colAttr->value); - - CodeGenMapEl *mapEl = codeGenMap.find( nameAttr->value ); - if ( mapEl == 0 ) { - source_error($$->loc) << "write statement given " - "but there are no machine instantiations" << endp; - } - else { - cgd = mapEl->value; - ::keyOps = &cgd->thisKeyOps; - } - } - }; - - -write_option_list: write_option_list tag_arg; -write_option_list: ; - -nonterm tag_arg -{ - char *option; -}; - -tag_arg: TAG_arg '/' TAG_arg - final { - writeOptions.append( $3->tag->content ); - }; - -tag_machine: tag_machine_head machine_item_list '/' TAG_machine - final { - cgd->closeMachine(); - }; - -tag_machine_head: TAG_machine - final { - cgd->createMachine(); - }; - -machine_item_list: machine_item_list machine_item; -machine_item_list: ; - -machine_item: tag_start_state; -machine_item: tag_error_state; -machine_item: tag_entry_points; -machine_item: tag_state_list; -machine_item: tag_action_list; -machine_item: tag_action_table_list; -machine_item: tag_cond_space_list; - -# -# States. -# - -tag_start_state: TAG_start_state '/' TAG_start_state - final { - unsigned long startState = strtoul( $3->tag->content, 0, 10 ); - cgd->setStartState( startState ); - }; - -tag_error_state: TAG_error_state '/' TAG_error_state - final { - unsigned long errorState = strtoul( $3->tag->content, 0, 10 ); - cgd->setErrorState( errorState ); - }; - -tag_entry_points: TAG_entry_points entry_point_list '/' TAG_entry_points - final { - Attribute *errorAttr = $1->tag->findAttr( "error" ); - if ( errorAttr != 0 ) - cgd->setForcedErrorState(); - }; - -entry_point_list: entry_point_list tag_entry; -entry_point_list: ; - -tag_entry: TAG_entry '/' TAG_entry - final { - Attribute *nameAttr = $1->tag->findAttr( "name" ); - if ( nameAttr == 0 ) { - error($1->loc) << "tag <entry_points>::<entry> " - "requires a name attribute" << endp; - } - else { - char *data = $3->tag->content; - unsigned long entry = strtoul( data, &data, 10 ); - cgd->addEntryPoint( nameAttr->value, entry ); - } - }; - -tag_state_list: tag_state_list_head state_list '/' TAG_state_list; - -tag_state_list_head: TAG_state_list - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) - error($1->loc) << "tag <state_list> requires a length attribute" << endp; - else { - unsigned long length = strtoul( lengthAttr->value, 0, 10 ); - cgd->initStateList( length ); - curState = 0; - } - }; - -state_list: state_list tag_state; -state_list: ; - -tag_state: TAG_state state_item_list '/' TAG_state - final { - Attribute *idAttr = $1->tag->findAttr( "id" ); - if ( idAttr == 0 ) - error($1->loc) << "tag <state> requires an id attribute" << endp; - else { - int id = atoi( idAttr->value ); - cgd->setId( curState, id ); - } - - Attribute *lengthAttr = $1->tag->findAttr( "final" ); - if ( lengthAttr != 0 ) - cgd->setFinal( curState ); - curState += 1; - }; - -state_item_list: state_item_list state_item; -state_item_list: ; - -state_item: tag_state_actions; -state_item: tag_eof_t; -state_item: tag_state_cond_list; -state_item: tag_trans_list; - -tag_state_actions: TAG_state_actions '/' TAG_state_actions - final { - char *ad = $3->tag->content; - - long toStateAction = readOffsetPtr( ad, &ad ); - long fromStateAction = readOffsetPtr( ad, &ad ); - long eofAction = readOffsetPtr( ad, &ad ); - - cgd->setStateActions( curState, toStateAction, - fromStateAction, eofAction ); - }; - -tag_eof_t: TAG_eof_t '/' TAG_eof_t - final { - char *et = $3->tag->content; - long targ = readOffsetPtr( et, &et ); - long eofAction = readOffsetPtr( et, &et ); - - cgd->setEofTrans( curState, targ, eofAction ); - }; - -tag_state_cond_list: tag_state_cond_list_head state_cond_list '/' TAG_cond_list; - -tag_state_cond_list_head: TAG_cond_list - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) - error($1->loc) << "tag <cond_list> requires a length attribute" << endp; - else { - ulong length = readLength( lengthAttr->value ); - cgd->initStateCondList( curState, length ); - curStateCond = 0; - } - }; - -state_cond_list: state_cond_list state_cond; -state_cond_list: ; - -state_cond: TAG_c '/' TAG_c - final { - char *td = $3->tag->content; - Key lowKey = readKey( td, &td ); - Key highKey = readKey( td, &td ); - long condId = readOffsetPtr( td, &td ); - cgd->addStateCond( curState, lowKey, highKey, condId ); - }; - -tag_trans_list: tag_trans_list_head trans_list '/' TAG_trans_list - final { - cgd->finishTransList( curState ); - }; - -tag_trans_list_head: TAG_trans_list - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) - error($1->loc) << "tag <trans_list> requires a length attribute" << endp; - else { - unsigned long length = strtoul( lengthAttr->value, 0, 10 ); - cgd->initTransList( curState, length ); - curTrans = 0; - } - }; - -trans_list: trans_list tag_trans; -trans_list: ; - -tag_trans: TAG_t '/' TAG_t - final { - char *td = $3->tag->content; - Key lowKey = readKey( td, &td ); - Key highKey = readKey( td, &td ); - long targ = readOffsetPtr( td, &td ); - long action = readOffsetPtr( td, &td ); - - cgd->newTrans( curState, curTrans++, lowKey, highKey, targ, action ); - }; - -# -# Action Lists. -# - -tag_action_list: tag_action_list_head action_list '/' TAG_action_list; - -tag_action_list_head: TAG_action_list - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) - error($1->loc) << "tag <action_list> requires a length attribute" << endp; - else { - unsigned long length = strtoul( lengthAttr->value, 0, 10 ); - cgd->initActionList( length ); - curAction = 0; - } - }; - -action_list: action_list tag_action; -action_list: ; - -# -# Actions. -# - -tag_action: TAG_action inline_list '/' TAG_action - final { - Attribute *lineAttr = $1->tag->findAttr( "line" ); - Attribute *colAttr = $1->tag->findAttr( "col" ); - Attribute *nameAttr = $1->tag->findAttr( "name" ); - if ( lineAttr == 0 || colAttr == 0) - error($1->loc) << "tag <action> requires a line and col attributes" << endp; - else { - unsigned long line = strtoul( lineAttr->value, 0, 10 ); - unsigned long col = strtoul( colAttr->value, 0, 10 ); - - char *name = 0; - if ( nameAttr != 0 ) - name = nameAttr->value; - - cgd->newAction( curAction++, name, line, col, $2->inlineList ); - } - }; - -nonterm inline_list -{ - GenInlineList *inlineList; -}; - - -inline_list: inline_list inline_item - final { - /* Append the item to the list, return the list. */ - $1->inlineList->append( $2->inlineItem ); - $$->inlineList = $1->inlineList; - }; - -inline_list: - final { - /* Start with empty list. */ - $$->inlineList = new GenInlineList; - }; - -nonterm inline_item_type -{ - GenInlineItem *inlineItem; -}; - -nonterm inline_item uses inline_item_type; - -inline_item: tag_text final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_goto final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_call final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_next final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_goto_expr final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_call_expr final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_next_expr final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_ret final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_break final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_pchar final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_char final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_hold final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_exec final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_curs final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_targs final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_il_entry final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_init_tokstart final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_init_act final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_get_tokend final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_set_tokstart final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_set_tokend final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_set_act final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_sub_action final { $$->inlineItem = $1->inlineItem; }; -inline_item: tag_lm_switch final { $$->inlineItem = $1->inlineItem; }; - -nonterm tag_text uses inline_item_type; -nonterm tag_goto uses inline_item_type; -nonterm tag_call uses inline_item_type; -nonterm tag_next uses inline_item_type; -nonterm tag_goto_expr uses inline_item_type; -nonterm tag_call_expr uses inline_item_type; -nonterm tag_next_expr uses inline_item_type; -nonterm tag_ret uses inline_item_type; -nonterm tag_break uses inline_item_type; -nonterm tag_pchar uses inline_item_type; -nonterm tag_char uses inline_item_type; -nonterm tag_hold uses inline_item_type; -nonterm tag_exec uses inline_item_type; -nonterm tag_curs uses inline_item_type; -nonterm tag_targs uses inline_item_type; -nonterm tag_il_entry uses inline_item_type; -nonterm tag_init_tokstart uses inline_item_type; -nonterm tag_init_act uses inline_item_type; -nonterm tag_get_tokend uses inline_item_type; -nonterm tag_set_tokstart uses inline_item_type; -nonterm tag_set_tokend uses inline_item_type; -nonterm tag_set_act uses inline_item_type; -nonterm tag_sub_action uses inline_item_type; -nonterm tag_lm_switch uses inline_item_type; - -tag_text: TAG_text '/' TAG_text - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Text ); - $$->inlineItem->data = $3->tag->content; - }; - -tag_goto: TAG_goto '/' TAG_goto - final { - int targ = strtol( $3->tag->content, 0, 10 ); - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Goto ); - $$->inlineItem->targId = targ; - }; - -tag_call: TAG_call '/' TAG_call - final { - int targ = strtol( $3->tag->content, 0, 10 ); - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Call ); - $$->inlineItem->targId = targ; - }; - -tag_next: TAG_next '/' TAG_next - final { - int targ = strtol( $3->tag->content, 0, 10 ); - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Next ); - $$->inlineItem->targId = targ; - }; - -tag_goto_expr: TAG_goto_expr inline_list '/' TAG_goto_expr - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::GotoExpr ); - $$->inlineItem->children = $2->inlineList; - }; - -tag_call_expr: TAG_call_expr inline_list '/' TAG_call_expr - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::CallExpr ); - $$->inlineItem->children = $2->inlineList; - }; - -tag_next_expr: TAG_next_expr inline_list '/' TAG_next_expr - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::NextExpr ); - $$->inlineItem->children = $2->inlineList; - }; - -tag_ret: TAG_ret '/' TAG_ret - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Ret ); - }; - -tag_break: TAG_break '/' TAG_break - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Break ); - }; - -tag_pchar: TAG_pchar '/' TAG_pchar - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::PChar ); - }; - -tag_char: TAG_char '/' TAG_char - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Char ); - }; - -tag_hold: TAG_hold '/' TAG_hold - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Hold ); - }; - -tag_exec: TAG_exec inline_list '/' TAG_exec - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Exec ); - $$->inlineItem->children = $2->inlineList; - }; - -tag_curs: TAG_curs '/' TAG_curs - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Curs ); - }; - -tag_targs: TAG_targs '/' TAG_targs - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Targs ); - }; - -tag_il_entry: TAG_entry '/' TAG_entry - final { - int targ = strtol( $3->tag->content, 0, 10 ); - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::Entry ); - $$->inlineItem->targId = targ; - }; - -tag_init_tokstart: TAG_init_tokstart '/' TAG_init_tokstart - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmInitTokStart ); - }; - -tag_init_act: TAG_init_act '/' TAG_init_act - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmInitAct ); - }; - -tag_get_tokend: TAG_get_tokend '/' TAG_get_tokend - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmGetTokEnd ); - }; - -tag_set_tokstart: TAG_set_tokstart '/' TAG_set_tokstart - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokStart ); - cgd->hasLongestMatch = true; - }; - -tag_set_tokend: TAG_set_tokend '/' TAG_set_tokend - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetTokEnd ); - $$->inlineItem->offset = strtol( $3->tag->content, 0, 10 ); - }; - -tag_set_act: TAG_set_act '/' TAG_set_act - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSetActId ); - $$->inlineItem->lmId = strtol( $3->tag->content, 0, 10 ); - }; - -tag_sub_action: TAG_sub_action inline_list '/' TAG_sub_action - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::SubAction ); - $$->inlineItem->children = $2->inlineList; - }; - -# Action switches. -tag_lm_switch: TAG_lm_switch lm_action_list '/' TAG_lm_switch - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::LmSwitch ); - $$->inlineItem->children = $2->inlineList; - }; - -nonterm lm_action_list -{ - GenInlineList *inlineList; -}; - -lm_action_list: lm_action_list tag_inline_action - final { - $$->inlineList = $1->inlineList; - $$->inlineList->append( $2->inlineItem ); - }; -lm_action_list: - final { - $$->inlineList = new GenInlineList; - }; - -nonterm tag_inline_action uses inline_item_type; - -tag_inline_action: TAG_sub_action inline_list '/' TAG_sub_action - final { - $$->inlineItem = new GenInlineItem( InputLoc(), GenInlineItem::SubAction ); - $$->inlineItem->children = $2->inlineList; - - Attribute *idAttr = $1->tag->findAttr( "id" ); - if ( idAttr != 0 ) { - unsigned long id = strtoul( idAttr->value, 0, 10 ); - $$->inlineItem->lmId = id; - } - }; - -# -# Lists of Actions. -# - -tag_action_table_list: - tag_action_table_list_head action_table_list '/' TAG_action_table_list; - -tag_action_table_list_head: TAG_action_table_list - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) { - error($1->loc) << "tag <action_table_list> requires " - "a length attribute" << endp; - } - else { - unsigned long length = strtoul( lengthAttr->value, 0, 10 ); - cgd->initActionTableList( length ); - curActionTable = 0; - } - }; - -action_table_list: action_table_list tag_action_table; -action_table_list: ; - -tag_action_table: TAG_action_table '/' TAG_action_table - final { - /* Find the length of the action table. */ - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) - error($1->loc) << "tag <at> requires a length attribute" << endp; - else { - unsigned long length = strtoul( lengthAttr->value, 0, 10 ); - - /* Collect the action table. */ - RedAction *redAct = cgd->allActionTables + curActionTable; - redAct->actListId = curActionTable; - redAct->key.setAsNew( length ); - char *ptr = $3->tag->content; - int pos = 0; - while ( *ptr != 0 ) { - unsigned long actionId = strtoul( ptr, &ptr, 10 ); - redAct->key[pos].key = 0; - redAct->key[pos].value = cgd->allActions+actionId; - pos += 1; - } - - /* Insert into the action table map. */ - cgd->redFsm->actionMap.insert( redAct ); - } - - curActionTable += 1; - }; - -# -# Conditions. -# - -tag_cond_space_list: tag_cond_space_list_head cond_space_list '/' TAG_cond_space_list; - -tag_cond_space_list_head: TAG_cond_space_list - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - if ( lengthAttr == 0 ) { - error($1->loc) << "tag <cond_space_list> " - "requires a length attribute" << endp; - } - else { - ulong length = readLength( lengthAttr->value ); - cgd->initCondSpaceList( length ); - curCondSpace = 0; - } - }; - -cond_space_list: cond_space_list tag_cond_space; -cond_space_list: tag_cond_space; - -tag_cond_space: TAG_cond_space '/' TAG_cond_space - final { - Attribute *lengthAttr = $1->tag->findAttr( "length" ); - Attribute *idAttr = $1->tag->findAttr( "id" ); - if ( lengthAttr == 0 ) - error($1->loc) << "tag <cond_space> requires a length attribute" << endp; - else { - if ( lengthAttr == 0 ) - error($1->loc) << "tag <cond_space> requires an id attribute" << endp; - else { - unsigned long condSpaceId = strtoul( idAttr->value, 0, 10 ); - ulong length = readLength( lengthAttr->value ); - - char *td = $3->tag->content; - Key baseKey = readKey( td, &td ); - - cgd->newCondSpace( curCondSpace, condSpaceId, baseKey ); - for ( ulong a = 0; a < length; a++ ) { - long actionOffset = readOffsetPtr( td, &td ); - cgd->condSpaceItem( curCondSpace, actionOffset ); - } - curCondSpace += 1; - } - } - }; - -}%% - -%%{ - write types; - write data; -}%% - -void XmlParser::init() -{ - %% write init; -} - -int XmlParser::parseLangEl( int type, const Token *token ) -{ - %% write exec; - return errCount == 0 ? 0 : -1; -} - - -unsigned long readLength( char *td ) -{ - return strtoul( td, 0, 10 ); -} - -Key readKey( char *td, char **end ) -{ - if ( keyOps->isSigned ) - return Key( strtol( td, end, 10 ) ); - else - return Key( strtoul( td, end, 10 ) ); -} - -long readOffsetPtr( char *td, char **end ) -{ - while ( *td == ' ' || *td == '\t' ) - td++; - - if ( *td == 'x' ) { - if ( end != 0 ) - *end = td + 1; - return -1; - } - - return strtol( td, end, 10 ); -} - -ostream &XmlParser::warning( const InputLoc &loc ) -{ - cerr << fileName << ":" << loc.line << ":" << loc.col << ": warning: "; - return cerr; -} - -ostream &XmlParser::error( const InputLoc &loc ) -{ - gblErrorCount += 1; - assert( fileName != 0 ); - cerr << fileName << ":" << loc.line << ":" << loc.col << ": "; - return cerr; -} - - -ostream &XmlParser::parser_error( int tokId, Token &token ) -{ - gblErrorCount += 1; - assert( fileName != 0 ); - cerr << fileName << ":" << token.loc.line << ":" << token.loc.col; - if ( token.tag != 0 ) { - if ( token.tag->tagId == 0 ) - cerr << ": at unknown tag"; - else - cerr << ": at tag <" << token.tag->tagId->name << ">"; - } - cerr << ": "; - - return cerr; -} - -ostream &XmlParser::source_error( const InputLoc &loc ) -{ - gblErrorCount += 1; - assert( sourceFileName != 0 ); - cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": "; - return cerr; -} - - -int XmlParser::token( int tokenId, Token &tok ) -{ - int res = parseLangEl( tokenId, &tok ); - if ( res < 0 ) - parser_error( tokenId, tok ) << "parse error" << endp; - return res; -} - -int XmlParser::token( int tokenId, int col, int line ) -{ - Token tok; - tok.loc.col = col; - tok.loc.line = line; - tok.tag = 0; - return token( tokenId, tok ); -} - -int XmlParser::token( XMLTag *tag, int col, int line ) -{ - Token tok; - tok.loc.col = col; - tok.loc.line = line; - tok.tag = tag; - - if ( tag->type == XMLTag::Close ) { - int res = token( '/', tok ); - if ( res < 0 ) - return res; - } - - tok.tag = tag; - return token( tag->tagId != 0 ? tag->tagId->id : TAG_unknown, tok ); -} diff --git a/libfsm/xmlscan.rl b/libfsm/xmlscan.rl deleted file mode 100644 index 4e9ee4e2..00000000 --- a/libfsm/xmlscan.rl +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright 2001-2007 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. - */ - -#include <iostream> -#include <string.h> -#include "vector.h" -#include "xmlparse.h" - -using std::istream; -using std::cout; -using std::cerr; -using std::endl; - -%%{ - machine XmlScanner; - write data; -}%% - -class Perfect_Hash -{ -private: - static inline unsigned int hash (const char *str, unsigned int len); - -public: - static struct XMLTagHashPair *in_word_set (const char *str, unsigned int len); -}; - -XmlScanner::XmlScanner( const char *fileName, istream &input ) : - fileName(fileName), - input(input), - curline(1), - curcol(1), - p(0), pe(0), - done(false), - data(0), data_len(0), - value(0) -{ - %%{ - machine XmlScanner; - write init; - }%% -} - -#define TK_NO_TOKEN (-1) -#define TK_ERR 1 -#define TK_SPACE 2 -#define TK_EOF 3 -#define TK_OpenTag 4 -#define TK_CloseTag 5 - -#define ret_tok( _tok ) token = (_tok); data = ts - -void XmlScanner::adjustAttrPointers( int distance ) -{ - for ( AttrMkList::Iter attr = attrMkList; attr.lte(); attr++ ) { - attr->id -= distance; - attr->value -= distance; - } -} - -/* There is no claim that this is a proper XML parser, but it is good - * enough for our purposes. */ -%%{ - machine XmlScanner; - - action colup { curcol++; } - action start_tok { token_col = curcol; token_line = curline; } - NL = '\n' @{ curcol = 0; curline++; }; - - WS = [\r\t ] | NL; - id = [_a-zA-Z][_a-zA-Z0-9]*; - literal = '"' ( [^"] | NL )* '"'; - - # Attribute identifiers. - action start_attr_id { attr_id_start = p; } - action leave_attr_id { attr_id_len = p - attr_id_start; } - - attr_id = id >start_attr_id %leave_attr_id; - - # Attribute values - action start_attr_value { attr_value_start = p; } - action leave_attr_value - { - attr_value_len = p - attr_value_start; - - AttrMarker newAttr; - newAttr.id = attr_id_start; - newAttr.idLen = attr_id_len; - newAttr.value = attr_value_start; - newAttr.valueLen = attr_value_len; - attrMkList.append( newAttr ); - } - - attr_value = literal >start_attr_value %leave_attr_value; - - # Attribute list. - attribute = attr_id WS* '=' WS* attr_value WS*; - - # Tag identifiers. - action tag_id_start { tag_id_start = p; } - action leave_tag_id { tag_id_len = p - tag_id_start; } - - tag_id = id >tag_id_start %leave_tag_id; - - main := |* - # Tags - ( '<' WS* tag_id ( WS+ attribute* )? '>' ) >start_tok $colup - => { ret_tok( TK_OpenTag ); fbreak; }; - - ( '<' WS* '/' WS* tag_id WS* '>' ) >start_tok $colup - => { ret_tok( TK_CloseTag ); fbreak; }; - - # Data in between tags. - ( [^<&\0] | NL ) $colup - => { buffer.append( *p ); }; - - # Specials. - "&" $colup - => { buffer.append( '&' ); }; - "<" $colup - => { buffer.append( '<' ); }; - ">" $colup - => { buffer.append( '>' ); }; - - # EOF - 0 >start_tok => { ret_tok( TK_EOF ); fbreak; }; - - *|; -}%% - -int XmlScanner::scan( ) -{ - int token = TK_NO_TOKEN; - int space = 0, readlen = 0; - char *attr_id_start = 0; - char *attr_value_start = 0; - int attr_id_len = 0; - int attr_value_len = 0; - - attrMkList.empty(); - buffer.clear(); - - while ( 1 ) { - if ( p == pe ) { - //printf("scanner: need more data\n"); - - if ( ts == 0 ) - have = 0; - else { - /* There is data that needs to be shifted over. */ - //printf("scanner: buffer broken mid token\n"); - have = pe - ts; - memmove( buf, ts, have ); - - int distance = ts - buf; - te -= distance; - tag_id_start -= distance; - attr_id_start -= distance; - attr_value_start -= distance; - adjustAttrPointers( distance ); - ts = buf; - } - - p = buf + have; - space = XML_BUFSIZE - have; - - if ( space == 0 ) { - /* We filled up the buffer trying to scan a token. */ - return TK_SPACE; - } - - if ( done ) { - //printf("scanner: end of file\n"); - p[0] = 0; - readlen = 1; - } - else { - input.read( p, space ); - readlen = input.gcount(); - if ( input.eof() ) { - //printf("scanner: setting done flag\n"); - done = 1; - } - } - - pe = p + readlen; - } - - %% write exec; - - if ( cs == XmlScanner_error ) - return TK_ERR; - - if ( token != TK_NO_TOKEN ) { - data_len = p - data; - return token; - } - } -} - -int xml_parse( std::istream &input, const char *fileName, - bool outputActive, bool wantComplete, - XmlScanner &scanner, XmlParser &parser ) -{ - while ( 1 ) { - int token = scanner.scan(); - if ( token == TK_NO_TOKEN ) { - cerr << "xmlscan: interal error: scanner returned NO_TOKEN" << endl; - exit(1); - } - else if ( token == TK_EOF ) { - parser.token( XmlParser_tk_eof, scanner.token_col, scanner.token_line ); - break; - } - else if ( token == TK_ERR ) { - scanner.error() << "scanner error" << endl; - break; - } - else if ( token == TK_SPACE ) { - scanner.error() << "scanner is out of buffer space" << endl; - break; - } - else { - /* All other tokens are either open or close tags. */ - XMLTagHashPair *tagId = Perfect_Hash::in_word_set( - scanner.tag_id_start, scanner.tag_id_len ); - - XMLTag *tag = new XMLTag( tagId, token == TK_OpenTag ? - XMLTag::Open : XMLTag::Close ); - - if ( tagId != 0 ) { - /* Get attributes for open tags. */ - if ( token == TK_OpenTag && scanner.attrMkList.length() > 0 ) { - tag->attrList = new AttrList; - for ( AttrMkList::Iter attr = scanner.attrMkList; - attr.lte(); attr++ ) - { - Attribute newAttr; - newAttr.id = new char[attr->idLen+1]; - memcpy( newAttr.id, attr->id, attr->idLen ); - newAttr.id[attr->idLen] = 0; - - /* Exclude the surrounding quotes. */ - newAttr.value = new char[attr->valueLen-1]; - memcpy( newAttr.value, attr->value+1, attr->valueLen-2 ); - newAttr.value[attr->valueLen-2] = 0; - - tag->attrList->append( newAttr ); - } - } - - /* Get content for closing tags. */ - if ( token == TK_CloseTag ) { - switch ( tagId->id ) { - case TAG_host: case TAG_arg: - case TAG_t: case TAG_alphtype: - case TAG_text: case TAG_goto: - case TAG_call: case TAG_next: - case TAG_entry: case TAG_set_tokend: - case TAG_set_act: case TAG_start_state: - case TAG_error_state: case TAG_state_actions: - case TAG_action_table: case TAG_cond_space: - case TAG_c: case TAG_ex: case TAG_eof_t: - tag->content = new char[scanner.buffer.length+1]; - memcpy( tag->content, scanner.buffer.data, - scanner.buffer.length ); - tag->content[scanner.buffer.length] = 0; - break; - } - } - } - - #if 0 - cerr << "parser_driver: " << (tag->type == XMLTag::Open ? "open" : "close") << - ": " << (tag->tagId != 0 ? tag->tagId->name : "<unknown>") << endl; - if ( tag->attrList != 0 ) { - for ( AttrList::Iter attr = *tag->attrList; attr.lte(); attr++ ) - cerr << " " << attr->id << ": " << attr->value << endl; - } - if ( tag->content != 0 ) - cerr << " content: " << tag->content << endl; - #endif - - parser.token( tag, scanner.token_col, scanner.token_line ); - } - } - - return 0; -} - -std::ostream &XmlScanner::error() -{ - gblErrorCount += 1; - cerr << fileName << ":" << curline << ":" << curcol << ": "; - return cerr; -} diff --git a/libfsm/xmltags.gperf b/libfsm/xmltags.gperf deleted file mode 100644 index 1ca544f7..00000000 --- a/libfsm/xmltags.gperf +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2005 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. - */ - - -%{ -#include <string.h> -#include "xmlparse.h" -%} -%compare-strncmp -struct XMLTagHashPair; -%% -ragel, TAG_ragel -ragel_def, TAG_ragel_def -host, TAG_host -state_list, TAG_state_list -state, TAG_state -trans_list, TAG_trans_list -t, TAG_t -machine, TAG_machine -start_state, TAG_start_state -error_state, TAG_error_state -action_list, TAG_action_list -action, TAG_action -action_table_list, TAG_action_table_list -action_table, TAG_action_table -alphtype, TAG_alphtype -getkey, TAG_getkey -state_actions, TAG_state_actions -entry_points, TAG_entry_points -text, TAG_text -goto, TAG_goto -call, TAG_call -next, TAG_next -goto_expr, TAG_goto_expr -call_expr, TAG_call_expr -next_expr, TAG_next_expr -ret, TAG_ret -pchar, TAG_pchar -char, TAG_char -hold, TAG_hold -exec, TAG_exec -curs, TAG_curs -targs, TAG_targs -entry, TAG_entry -data, TAG_data -lm_switch, TAG_lm_switch -sub_action, TAG_sub_action -init_act, TAG_init_act -set_act, TAG_set_act -get_tokend, TAG_get_tokend -set_tokend, TAG_set_tokend -init_tokstart, TAG_init_tokstart -set_tokstart, TAG_set_tokstart -write, TAG_write -access, TAG_access -break, TAG_break -arg, TAG_arg -cond_space_list, TAG_cond_space_list -cond_space, TAG_cond_space -cond_list, TAG_cond_list -c, TAG_c -exports, TAG_exports -ex, TAG_ex -p_expr, TAG_p_expr -pe_expr, TAG_pe_expr -eof_expr, TAG_eof_expr -cs_expr, TAG_cs_expr -top_expr, TAG_top_expr -stack_expr, TAG_stack_expr -act_expr, TAG_act_expr -tokstart_expr, TAG_tokstart_expr -tokend_expr, TAG_tokend_expr -data_expr, TAG_data_expr -prepush, TAG_prepush -postpop, TAG_postpop -eof_t, TAG_eof_t |