/*
- * Copyright 2006-2007 Adrian Thurston <thurston@cs.queensu.ca>
+ * Copyright 2006-2007 Adrian Thurston <thurston@complang.org>
*/
/* This file is part of Ragel.
#include "ragel.h"
#include "rlscan.h"
+#include "inputdata.h"
//#define LOG_TOKENS
SemiTerminated
};
-#ifdef WIN32
+#ifdef _WIN32
#define PATH_SEP '\\'
#else
#define PATH_SEP '/'
}
}
-void Scanner::directToParser( Parser *toParser, char *tokFileName, int tokLine,
+void Scanner::directToParser( Parser *toParser, const char *tokFileName, int tokLine,
int tokColumn, int type, char *tokdata, int toklen )
{
InputLoc loc;
/* If no errors and we are at the bottom of the include stack (the
* source file listed on the command line) then write out the data. */
if ( includeDepth == 0 && machineSpec == 0 && machineName == 0 )
- xmlEscapeHost( output, ts, te-ts );
+ id.inputItems.tail->data.write( ts, te-ts );
}
/*
{
/* Maintain the error count. */
gblErrorCount += 1;
- cerr << fileName << ":" << line << ":" << column << ": ";
+ cerr << makeInputLoc( fileName, line, column ) << ": ";
return cerr;
}
-bool Scanner::recursiveInclude( char *inclFileName, char *inclSectionName )
+/* An approximate check for duplicate includes. Due to aliasing of files it's
+ * possible for duplicates to creep in. */
+bool Scanner::duplicateInclude( char *inclFileName, char *inclSectionName )
{
- for ( IncludeStack::Iter si = includeStack; si.lte(); si++ ) {
- if ( strcmp( si->fileName, inclFileName ) == 0 &&
- strcmp( si->sectionName, inclSectionName ) == 0 )
+ for ( IncludeHistory::Iter hi = parser->includeHistory; hi.lte(); hi++ ) {
+ if ( strcmp( hi->fileName, inclFileName ) == 0 &&
+ strcmp( hi->sectionName, inclSectionName ) == 0 )
{
return true;
}
if ( !importMachines && inclSectionTarg == 0 ) {
ignoreSection = false;
- ParserDictEl *pdEl = parserDict.find( machine );
+ ParserDictEl *pdEl = id.parserDict.find( machine );
if ( pdEl == 0 ) {
pdEl = new ParserDictEl( machine );
pdEl->value = new Parser( fileName, machine, sectionLoc );
pdEl->value->init();
- parserDict.insert( pdEl );
+ id.parserDict.insert( pdEl );
+ id.parserList.append( pdEl->value );
}
parser = pdEl->value;
{
if ( active() ) {
char *inclSectionName = word;
- char **inclFileName = 0;
+ char **includeChecks = 0;
/* Implement defaults for the input file and section name. */
if ( inclSectionName == 0 )
inclSectionName = parser->sectionName;
if ( lit != 0 )
- inclFileName = makeIncludePathChecks( fileName, lit, lit_len );
+ includeChecks = makeIncludePathChecks( fileName, lit, lit_len );
else {
char *test = new char[strlen(fileName)+1];
strcpy( test, fileName );
- inclFileName = new char*[2];
+ includeChecks = new char*[2];
- inclFileName[0] = test;
- inclFileName[1] = 0;
+ includeChecks[0] = test;
+ includeChecks[1] = 0;
}
long found = 0;
- ifstream *inFile = tryOpenInclude( inclFileName, found );
- if ( inFile == 0 )
+ ifstream *inFile = tryOpenInclude( includeChecks, found );
+ if ( inFile == 0 ) {
scan_error() << "include: failed to locate file" << endl;
+ char **tried = includeChecks;
+ while ( *tried != 0 )
+ scan_error() << "include: attempted: \"" << *tried++ << '\"' << endl;
+ }
else {
- /* Check for a recursive include structure. Add the current file/section
- * name then check if what we are including is already in the stack. */
- includeStack.append( IncludeStackItem( fileName, parser->sectionName ) );
+ /* Don't include anything that's already been included. */
+ if ( !duplicateInclude( includeChecks[found], inclSectionName ) ) {
+ parser->includeHistory.append( IncludeHistoryItem(
+ includeChecks[found], inclSectionName ) );
- if ( recursiveInclude( inclFileName[found], inclSectionName ) )
- scan_error() << "include: this is a recursive include operation" << endl;
- else {
- Scanner scanner( inclFileName[found], *inFile, output, parser,
+ Scanner scanner( id, includeChecks[found], *inFile, parser,
inclSectionName, includeDepth+1, false );
scanner.do_scan( );
delete inFile;
}
-
- /* Remove the last element (len-1) */
- includeStack.remove( -1 );
}
}
}
void Scanner::handleImport()
{
if ( active() ) {
- char **importFileName = makeIncludePathChecks( fileName, lit, lit_len );
+ char **importChecks = makeIncludePathChecks( fileName, lit, lit_len );
/* Open the input file for reading. */
long found = 0;
- ifstream *inFile = tryOpenInclude( importFileName, found );
+ ifstream *inFile = tryOpenInclude( importChecks, found );
if ( inFile == 0 ) {
scan_error() << "import: could not open import file " <<
"for reading" << endl;
+ char **tried = importChecks;
+ while ( *tried != 0 )
+ scan_error() << "import: attempted: \"" << *tried++ << '\"' << endl;
}
- Scanner scanner( importFileName[found], *inFile, output, parser,
+ Scanner scanner( id, importChecks[found], *inFile, parser,
0, includeDepth+1, true );
scanner.do_scan( );
scanner.importToken( 0, 0, 0 );
action write_command
{
if ( active() && machineSpec == 0 && machineName == 0 ) {
- output << "<write"
- " def_name=\"" << parser->sectionName << "\""
- " line=\"" << line << "\""
- " col=\"" << column << "\""
- ">";
+ InputItem *inputItem = new InputItem;
+ inputItem->type = InputItem::Write;
+ inputItem->loc.line = line;
+ inputItem->loc.col = column;
+ inputItem->name = parser->sectionName;
+ inputItem->pd = parser->pd;
+ id.inputItems.append( inputItem );
}
}
action write_arg
{
if ( active() && machineSpec == 0 && machineName == 0 )
- output << "<arg>" << tokdata << "</arg>";
+ id.inputItems.tail->writeArgs.append( strdup(tokdata) );
}
action write_close
{
if ( active() && machineSpec == 0 && machineName == 0 )
- output << "</write>\n";
+ id.inputItems.tail->writeArgs.append( 0 );
}
write_stmt =
void Scanner::processToken( int type, char *tokdata, int toklen )
{
int *p, *pe, *eof;
-
if ( type < 0 )
p = pe = eof = 0;
{
parserExistsError = false;
- if ( includeDepth == 0 ) {
- if ( machineSpec == 0 && machineName == 0 )
- output << "</host>\n";
- }
-
sectionLoc.fileName = fileName;
sectionLoc.line = line;
- sectionLoc.col = 0;
+ sectionLoc.col = column;
}
void Scanner::endSection( )
InputLoc loc;
loc.fileName = fileName;
loc.line = line;
- loc.col = 0;
+ loc.col = column;
parser->token( loc, TK_EndSection, 0, 0 );
}
if ( machineSpec == 0 && machineName == 0 ) {
/* The end section may include a newline on the end, so
* we use the last line, which will count the newline. */
- output << "<host line=\"" << line << "\">";
+ InputItem *inputItem = new InputItem;
+ inputItem->type = InputItem::HostData;
+ inputItem->loc.line = line;
+ inputItem->loc.col = column;
+ id.inputItems.append( inputItem );
}
}
}
bool isAbsolutePath( const char *path )
{
-#ifdef WIN32
+#ifdef _WIN32
return isalpha( path[0] ) && path[1] == ':' && path[2] == '\\';
#else
return path[0] == '/';
#endif
}
-char **Scanner::makeIncludePathChecks( char *thisFileName, char *fileName, int fnlen )
+char **Scanner::makeIncludePathChecks( const char *thisFileName,
+ const char *fileName, int fnlen )
{
char **checks = new char*[2];
long nextCheck = 0;
}
/* Search from the include paths given on the command line. */
- for ( ArgsVector::Iter incp = includePaths; incp.lte(); incp++ ) {
+ for ( ArgsVector::Iter incp = id.includePaths; incp.lte(); incp++ ) {
long pathLen = strlen( *incp );
long checkLen = pathLen + 1 + length;
char *check = new char[checkLen+1];
# Parser definitions.
parser_def := |*
+ 'length_cond' => { token( KW_Length ); };
'machine' => { token( KW_Machine ); };
'include' => { token( KW_Include ); };
'import' => { token( KW_Import ); };