diff --git a/applications/test/dictionary/Allwmake b/applications/test/dictionary/Allwmake deleted file mode 100755 index fcf297dc892423ab70d3b8238f4a2713b6797ca6..0000000000000000000000000000000000000000 --- a/applications/test/dictionary/Allwmake +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -cd ${0%/*} || exit 1 # run from this directory - -# this will have to do until we have a makefile rule - -if type Coco > /dev/null 2>&1 -then - Coco \ - -frames $WM_THIRD_PARTY_DIR/coco-r \ - calcEntry/calcEntry.atg -else - echo "Coco not installed" -fi - -wmake diff --git a/applications/test/dictionary/Make/files b/applications/test/dictionary/Make/files index 148f5fb1c94c8ff332eed2edec36e2771eb65e02..b9363efb23b13e6012274d16c0a250cdf9d2ca39 100644 --- a/applications/test/dictionary/Make/files +++ b/applications/test/dictionary/Make/files @@ -1,7 +1,3 @@ dictionaryTest.C -calcEntry/calcEntry.C -calcEntry/calcEntryParser.cpp -calcEntry/calcEntryScanner.cpp - EXE = $(FOAM_USER_APPBIN)/dictionaryTest diff --git a/applications/test/dictionary/Make/options b/applications/test/dictionary/Make/options index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..41306609f208806f0c6f42a2426867d3e10d4897 100644 --- a/applications/test/dictionary/Make/options +++ b/applications/test/dictionary/Make/options @@ -0,0 +1 @@ +EXE_INC = diff --git a/applications/test/dictionary/calcEntry/calcEntry.atg b/applications/test/dictionary/calcEntry/calcEntry.atg deleted file mode 100644 index 90c0861143681adc74fd7a4a59fb7ea793c3e1f6..0000000000000000000000000000000000000000 --- a/applications/test/dictionary/calcEntry/calcEntry.atg +++ /dev/null @@ -1,252 +0,0 @@ -/*------------------------------------------------------------------------- - compile with: - Coco \ - -frames $WM_THIRD_PARTY_DIR/coco-r \ - calcEntry.atg --------------------------------------------------------------------------*/ - -#include "dictionary.H" -#include "scalar.H" -#include "error.H" -#include "wchar.H" - - -COMPILER calcEntry -$prefix=calcEntry -$namespace=Foam::functionEntries::calcEntryInternal -$eof=true // grammar handles eof itself - - // Simple four function calculator for OpenFOAM dictionaries - - //! with debug - static const int debug = 0; - - //! The parent dictionary - mutable dictionary* dict_; - - //! Track that parent dictionary was set - bool hasDict_; - - //! The calculation result - scalar val; - - - //! token -> scalar - scalar getScalar() const - { - return coco_string_toDouble(t->val); - } - - //! token -> string - std::string getString() const - { - char* str = coco_string_create_char(t->val); - std::string s(str); - coco_string_delete(str); - return s; - } - - //! attach a dictionary - void dict(const dictionary& dict) - { - dict_ = const_cast<dictionary*>(&dict); - hasDict_ = true; - } - - - //! lookup dictionary entry - scalar getDictLookup() const - { - scalar dictValue = 0; - - if (!hasDict_) - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "No dictionary attached!" - << exit(FatalError); - - return 0; - } - - char* chars = coco_string_create_char - ( - t->val, - 1, - (coco_string_length(t->val) - 1) - ); - word keyword(chars); - coco_string_delete(chars); - - if (debug) - { - Info<<"lookup: " << keyword << nl; - } - - entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); - if (entryPtr && !entryPtr->isDict()) - { - if (entryPtr->stream().size() != 1) - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "keyword " << keyword << " has " - << entryPtr->stream().size() << " values in dictionary " - << exit(FatalError); - } - entryPtr->stream() >> dictValue; - } - else - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "keyword " << keyword << " is undefined in dictionary " - << exit(FatalError); - } - - - return dictValue; - } - - scalar Result() const - { - return val; - } - - -/*---------------------------------------------------------------------------*/ - -CHARACTERS - letter = 'A'..'Z' + 'a'..'z'. - qualifier = '_' + ':'. - dollar = '$'. - digit = "0123456789". - sign = '+' + '-'. - cr = '\r'. - lf = '\n'. - tab = '\t'. - stringCh = ANY - '"' - '\\' - cr - lf. - printable = '\u0020' .. '\u007e'. - - -// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * // - -TOKENS - -// identifier -ident = - letter { letter | digit | qualifier }. - -// string -string = - '"' { stringCh | '\\' printable } '"'. - -// dictionary lookup identifier -// starts with '$' and otherwise limited to a normal indentifier -variable = - dollar letter { letter | digit | qualifier }. - -// floating point and integer numbers -number = - [sign] ('.' digit { digit } ) | ( digit { digit } [ '.' { digit } ]) - [ ('E' | 'e') [sign] digit { digit } ]. - - -// * * * * * * * * * * * PRAGMAS / COMMENTS / IGNORE * * * * * * * * * * * // - -COMMENTS FROM "/*" TO "*/" NESTED -COMMENTS FROM "//" TO lf - -IGNORE cr + lf + tab - - -// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * // - -PRODUCTIONS - -calcEntry (. val = 0; - if (debug){Info<<"start val pos:"<< t->pos << nl;} - .) -= - '{' Expr<val> '}' (. - if (debug){ - Info<<"end {} at pos:"<< t->pos - <<" val:"<< t->val - <<" len:"<< coco_string_length(t->val) - <<" la pos:"<< la->pos << nl; - } - // reposition to immediately after the closing '}' - scanner->buffer->SetPos - ( - t->pos + coco_string_length(t->val) - ); - .) - | ( Expr<val> EOF ) -. - - -/*---------------------------------------------------------------------------*/ - -Expr<scalar& val> (. scalar val2 = 0; - if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;} - .) -= - Term<val> - { - "+" Term<val2> (. if (debug) {Info<<"+Term:"<<val2 << " pos:"<< t->pos << nl;} - val += val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) - | "-" Term<val2> (. if (debug) {Info<<"-Term:"<<val2<< " pos:"<< t->pos << nl;} - val -= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) - } -. - - -/*---------------------------------------------------------------------------*/ - -Term<scalar& val> (. scalar val2 = 0; - if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;} - .) -= - Factor<val> - { - "*" Factor<val2> (. if (debug) {Info<<"*Factor:"<<val2<< " pos:"<< t->pos << nl;} - val *= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) - | "/" Factor<val2> (. if (debug) {Info<<"/Factor:"<<val2<< " pos:"<< t->pos << nl;} - val /= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - .) - } -. - - -/*---------------------------------------------------------------------------*/ -Factor<scalar& val> -= - variable (. val = getDictLookup(); - if (debug) {Info<<"lookup:"<<val<< " pos:"<< t->pos << nl;} - .) - | number (. val = getScalar(); - if (debug) {Info<<"got num:"<<val<< " pos:"<< t->pos << nl;} - .) - | '-' '(' Expr<val> ')' (. val = -val; - if (debug) {Info<<"inv:"<<val<< " pos:"<< t->pos << nl;} - .) - | '(' Expr<val> ')' (. if (debug){Info<<"got Expr:"<<val<< " pos:"<< t->pos << nl;} - .) -. - - -/*---------------------------------------------------------------------------*/ - -END calcEntry. - -// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.cpp b/applications/test/dictionary/calcEntry/calcEntryParser.cpp deleted file mode 100644 index 1ff95b8ac96b1080dca11b1cb82fe4bc55a6dfab..0000000000000000000000000000000000000000 --- a/applications/test/dictionary/calcEntry/calcEntryParser.cpp +++ /dev/null @@ -1,339 +0,0 @@ - - -#include <wchar.h> -#include "calcEntryParser.h" - - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - -// ---------------------------------------------------------------------------- -// Parser Implementation -// ---------------------------------------------------------------------------- - -void Parser::SynErr(int n) { - if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n); - errDist = 0; -} - - -void Parser::SemErr(const wchar_t* msg) { - if (errDist >= minErrDist) errors->Error(t->line, t->col, msg); - errDist = 0; -} - - -void Parser::Get() { - for (;;) { - t = la; - la = scanner->Scan(); - if (la->kind <= maxT) { - ++errDist; - break; - } - - if (dummyToken != t) { - dummyToken->kind = t->kind; - dummyToken->pos = t->pos; - dummyToken->col = t->col; - dummyToken->line = t->line; - dummyToken->next = NULL; - coco_string_delete(dummyToken->val); - dummyToken->val = coco_string_create(t->val); - t = dummyToken; - } - la = t; - } -} - - -void Parser::Expect(int n) { - if (la->kind == n) { - Get(); - } - else { - SynErr(n); - } -} - - -void Parser::ExpectWeak(int n, int follow) { - if (la->kind == n) { - Get(); - } - else { - SynErr(n); - while (!StartOf(follow)) { - Get(); - } - } -} - - -bool Parser::WeakSeparator(int n, int syFol, int repFol) { - if (la->kind == n) { - Get(); - return true; - } - else if (StartOf(repFol)) { - return false; - } - else { - SynErr(n); - while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) { - Get(); - } - return StartOf(syFol); - } -} - - -void Parser::calcEntry() { - val = 0; - if (debug){Info<<"start val pos:"<< t->pos << nl;} - - if (la->kind == 5) { - Get(); - Expr(val); - Expect(6); - if (debug){ - Info<<"end {} at pos:"<< t->pos - <<" val:"<< t->val - <<" len:"<< coco_string_length(t->val) - <<" la pos:"<< la->pos << nl; - } - // reposition to immediately after the closing '}' - scanner->buffer->SetPos - ( - t->pos + coco_string_length(t->val) - ); - - } else if (StartOf(1)) { - Expr(val); - Expect(0); - } else SynErr(14); -} - -void Parser::Expr(scalar& val) { - scalar val2 = 0; - if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;} - - Term(val); - while (la->kind == 7 || la->kind == 8) { - if (la->kind == 7) { - Get(); - Term(val2); - if (debug) {Info<<"+Term:"<<val2 << " pos:"<< t->pos << nl;} - val += val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - - } else { - Get(); - Term(val2); - if (debug) {Info<<"-Term:"<<val2<< " pos:"<< t->pos << nl;} - val -= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - - } - } -} - -void Parser::Term(scalar& val) { - scalar val2 = 0; - if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;} - - Factor(val); - while (la->kind == 9 || la->kind == 10) { - if (la->kind == 9) { - Get(); - Factor(val2); - if (debug) {Info<<"*Factor:"<<val2<< " pos:"<< t->pos << nl;} - val *= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - - } else { - Get(); - Factor(val2); - if (debug) {Info<<"/Factor:"<<val2<< " pos:"<< t->pos << nl;} - val /= val2; - if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;} - - } - } -} - -void Parser::Factor(scalar& val) { - if (la->kind == 3) { - Get(); - val = getDictLookup(); - if (debug) {Info<<"lookup:"<<val<< " pos:"<< t->pos << nl;} - - } else if (la->kind == 4) { - Get(); - val = getScalar(); - if (debug) {Info<<"got num:"<<val<< " pos:"<< t->pos << nl;} - - } else if (la->kind == 8) { - Get(); - Expect(11); - Expr(val); - Expect(12); - val = -val; - if (debug) {Info<<"inv:"<<val<< " pos:"<< t->pos << nl;} - - } else if (la->kind == 11) { - Get(); - Expr(val); - Expect(12); - if (debug){Info<<"got Expr:"<<val<< " pos:"<< t->pos << nl;} - - } else SynErr(15); -} - - - -void Parser::Parse() { - t = NULL; - if (dummyToken) { // safety: someone might call Parse() twice - delete dummyToken; - } - la = dummyToken = new Token(); - la->val = coco_string_create(L"Dummy Token"); - Get(); - calcEntry(); - // let grammar deal with end-of-file expectations - -} - - -Parser::Parser(Scanner* scan, Errors* err) -: - dummyToken(NULL), - deleteErrorsDestruct_(!err), - errDist(minErrDist), - scanner(scan), - errors(err), - t(NULL), - la(NULL) -{ - - if (!errors) { // add in default error handling - errors = new Errors(); - } -} - - -bool Parser::StartOf(int s) { - const bool T = true; - const bool x = false; - - static bool set[2][15] = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,x,x,T, T,x,x,x, T,x,x,T, x,x,x} - }; - - - - return set[s][la->kind]; -} - - -Parser::~Parser() { - if (deleteErrorsDestruct_) { // delete default error handling - delete errors; - } - delete dummyToken; -} - - -// ---------------------------------------------------------------------------- -// Errors Implementation -// ---------------------------------------------------------------------------- - -Errors::Errors() -: - count(0) -{} - - -Errors::~Errors() -{} - - -void Errors::clear() { - count = 0; -} - - -wchar_t* Errors::strerror(int n) -{ - wchar_t* s; - switch (n) { - case 0: s = coco_string_create(L"EOF expected"); break; - case 1: s = coco_string_create(L"ident expected"); break; - case 2: s = coco_string_create(L"string expected"); break; - case 3: s = coco_string_create(L"variable expected"); break; - case 4: s = coco_string_create(L"number expected"); break; - case 5: s = coco_string_create(L"\"{\" expected"); break; - case 6: s = coco_string_create(L"\"}\" expected"); break; - case 7: s = coco_string_create(L"\"+\" expected"); break; - case 8: s = coco_string_create(L"\"-\" expected"); break; - case 9: s = coco_string_create(L"\"*\" expected"); break; - case 10: s = coco_string_create(L"\"/\" expected"); break; - case 11: s = coco_string_create(L"\"(\" expected"); break; - case 12: s = coco_string_create(L"\")\" expected"); break; - case 13: s = coco_string_create(L"??? expected"); break; - case 14: s = coco_string_create(L"invalid calcEntry"); break; - case 15: s = coco_string_create(L"invalid Factor"); break; - - default: - { - wchar_t format[20]; - coco_swprintf(format, 20, L"error %d", n); - s = coco_string_create(format); - } - break; - } - return s; -} - - -void Errors::Warning(const wchar_t* msg) { - wprintf(L"%ls\n", msg); -} - - -void Errors::Warning(int line, int col, const wchar_t* msg) { - wprintf(L"-- line %d col %d: %ls\n", line, col, msg); -} - - -void Errors::Error(int line, int col, const wchar_t* msg) { - wprintf(L"-- line %d col %d: %ls\n", line, col, msg); - count++; -} - - -void Errors::SynErr(int line, int col, int n) { - wchar_t* msg = this->strerror(n); - this->Error(line, col, msg); - coco_string_delete(msg); -} - - -void Errors::Exception(const wchar_t* msg) { - wprintf(L"%ls", msg); - ::exit(1); -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // namespace -} // namespace -} // namespace - - -// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.h b/applications/test/dictionary/calcEntry/calcEntryParser.h deleted file mode 100644 index de12a3961ea6eebe69671ac65f5bb1121769b019..0000000000000000000000000000000000000000 --- a/applications/test/dictionary/calcEntry/calcEntryParser.h +++ /dev/null @@ -1,206 +0,0 @@ - - -#ifndef COCO_calcEntryPARSER_H__ -#define COCO_calcEntryPARSER_H__ - -#include "dictionary.H" -#include "scalar.H" -#include "error.H" -#include "wchar.H" - - -#include "calcEntryScanner.h" - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - -//! Parser error handing -class Errors { -public: - int count; //!< The number of errors detected - - //! Allocate and return a string describing the given error code. - /** It is the responsibility of the caller to free this string, - * eg, with coco_string_delete() - */ - static wchar_t* strerror(int n); - - Errors(); //!< Construct null - start with no errors - virtual ~Errors(); //!< Destructor - virtual void clear(); //!< Clear the error count - - //! Handle a general warning 'msg' - virtual void Warning(const wchar_t* msg); - //! Handle a general warning 'msg' - virtual void Warning(int line, int col, const wchar_t* msg); - //! Handle general error 'msg' (eg, a semantic error) - virtual void Error(int line, int col, const wchar_t* msg); - //! Handle syntax error 'n', uses strerror for the message, calls Error() - virtual void SynErr(int line, int col, int n); - //! Handle a general exception 'msg' - virtual void Exception(const wchar_t* msg); - -}; // Errors - - -//! A Coco/R Parser -class Parser { -private: - enum { - _EOF=0, - _ident=1, - _string=2, - _variable=3, - _number=4, - }; - static const int maxT = 13; - - static const int minErrDist = 2; //!< min. distance before reporting errors - - Token *dummyToken; - bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor - int errDist; - - void SynErr(int n); //!< Handle syntax error 'n' - void Get(); - void Expect(int n); - bool StartOf(int s); - void ExpectWeak(int n, int follow); - bool WeakSeparator(int n, int syFol, int repFol); - -public: - Scanner *scanner; - Errors *errors; - - Token *t; //!< last recognized token - Token *la; //!< lookahead token - -static const int debug = 0; - - //! The parent dictionary - mutable dictionary* dict_; - - //! Track that parent dictionary was set - bool hasDict_; - - //! The calculation result - scalar val; - - - //! token -> scalar - scalar getScalar() const - { - return coco_string_toDouble(t->val); - } - - //! token -> string - std::string getString() const - { - char* str = coco_string_create_char(t->val); - std::string s(str); - coco_string_delete(str); - return s; - } - - //! attach a dictionary - void dict(const dictionary& dict) - { - dict_ = const_cast<dictionary*>(&dict); - hasDict_ = true; - } - - - //! lookup dictionary entry - scalar getDictLookup() const - { - scalar dictValue = 0; - - if (!hasDict_) - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "No dictionary attached!" - << exit(FatalError); - - return 0; - } - - char* chars = coco_string_create_char - ( - t->val, - 1, - (coco_string_length(t->val) - 1) - ); - word keyword(chars); - coco_string_delete(chars); - - if (debug) - { - Info<<"lookup: " << keyword << nl; - } - - entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); - if (entryPtr && !entryPtr->isDict()) - { - if (entryPtr->stream().size() != 1) - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "keyword " << keyword << " has " - << entryPtr->stream().size() << " values in dictionary " - << exit(FatalError); - } - entryPtr->stream() >> dictValue; - } - else - { - FatalErrorIn - ( - "calcEntry::getDictEntry() const" - ) << "keyword " << keyword << " is undefined in dictionary " - << exit(FatalError); - } - - - return dictValue; - } - - scalar Result() const - { - return val; - } - - -/*---------------------------------------------------------------------------*/ - - - - //! Construct for the specified scanner - /** - * Use the default error handling, or optionally provide an error - * handler, which will not be deleted upon destruction. - */ - Parser(Scanner* scan, Errors* err = 0); - ~Parser(); //!< Destructor - cleanup errors and dummyToken - void SemErr(const wchar_t* msg); //!< Handle semantic error - - void calcEntry(); - void Expr(scalar& val); - void Term(scalar& val); - void Factor(scalar& val); - - void Parse(); //!< Execute the parse operation - -}; // end Parser - -} // namespace -} // namespace -} // namespace - - -#endif // COCO_calcEntryPARSER_H__ - diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp b/applications/test/dictionary/calcEntry/calcEntryScanner.cpp deleted file mode 100644 index b070bcf3f35c7c402c7115da70fdefe40bb433b9..0000000000000000000000000000000000000000 --- a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp +++ /dev/null @@ -1,932 +0,0 @@ - - -#include <sstream> - -#include "calcEntryScanner.h" - -// values for the file stream buffering -#define MIN_BUFFER_LENGTH 1024 // 1KB -#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH) // 64KB -// value for the heap management -#define HEAP_BLOCK_SIZE (64*1024) // 64KB - - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - -// * * * * * * * * * * Wide Character String Routines * * * * * * * * * * * // - -// string handling, wide character - -wchar_t* coco_string_create(const wchar_t* str) { - int len = coco_string_length(str); - wchar_t* dest = new wchar_t[len + 1]; - if (len) { - wcsncpy(dest, str, len); - } - dest[len] = 0; - return dest; -} - -wchar_t* coco_string_create(const wchar_t* str, int index, int length) { - int len = coco_string_length(str); - if (len) { - len = length; - } - wchar_t* dest = new wchar_t[len + 1]; - if (len) { - wcsncpy(dest, &(str[index]), len); - } - dest[len] = 0; - return dest; -} - - -wchar_t* coco_string_create_lower(const wchar_t* str) { - if (!str) { return NULL; } - return coco_string_create_lower(str, 0, wcslen(str)); -} - - -wchar_t* coco_string_create_lower(const wchar_t* str, int index, int len) { - if (!str) { return NULL; } - wchar_t* dest = new wchar_t[len + 1]; - - for (int i = 0; i < len; i++) { - const wchar_t ch = str[index + i]; - if ((L'A' <= ch) && (ch <= L'Z')) { - dest[i] = ch - (L'A' - L'a'); - } - else { - dest[i] = ch; - } - } - dest[len] = L'\0'; - return dest; -} - - -wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2) { - int str1Len = coco_string_length(str1); - int str2Len = coco_string_length(str2); - - wchar_t* dest = new wchar_t[str1Len + str2Len + 1]; - - if (str1Len) { wcscpy(dest, str1); } - if (str2Len) { wcscpy(dest + str1Len, str2); } - - dest[str1Len + str2Len] = 0; - return dest; -} - -wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t ch) { - int len = coco_string_length(str1); - wchar_t* dest = new wchar_t[len + 2]; - wcsncpy(dest, str1, len); // or use if (len) { wcscpy(dest, str1); } - dest[len] = ch; - dest[len + 1] = 0; - return dest; -} - -void coco_string_delete(wchar_t* &str) { - delete [] str; - str = NULL; -} - -int coco_string_length(const wchar_t* str) { - return str ? wcslen(str) : 0; -} - -bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr) { - int strLen = wcslen(str); - int endLen = wcslen(endstr); - return (endLen <= strLen) && (wcscmp(str + strLen - endLen, endstr) == 0); -} - -int coco_string_indexof(const wchar_t* str, const wchar_t ch) { - const wchar_t* fnd = wcschr(str, ch); - return fnd ? (fnd - str) : -1; -} - -int coco_string_lastindexof(const wchar_t* str, const wchar_t ch) { - const wchar_t* fnd = wcsrchr(str, ch); - return fnd ? (fnd - str) : -1; -} - -void coco_string_merge(wchar_t* &dest, const wchar_t* str) { - if (!str) { return; } - wchar_t* newstr = coco_string_create_append(dest, str); - delete [] dest; - dest = newstr; -} - -bool coco_string_equal(const wchar_t* str1, const wchar_t* str2) { - return wcscmp(str1, str2) == 0; -} - -int coco_string_compareto(const wchar_t* str1, const wchar_t* str2) { - return wcscmp(str1, str2); -} - -int coco_string_hash(const wchar_t* str) { - int h = 0; - if (!str) { return 0; } - while (*str != 0) { - h = (h * 7) ^ *str; - ++str; - } - if (h < 0) { h = -h; } - return h; -} - - -double coco_string_toDouble(const wchar_t* str) -{ - return str ? wcstod(str, NULL) : 0; -} - -float coco_string_toFloat(const wchar_t* str) -{ - return str ? wcstof(str, NULL) : 0; -} - - - -// -// string handling, byte character -// - -wchar_t* coco_string_create(const char* str) { - int len = str ? strlen(str) : 0; - wchar_t* dest = new wchar_t[len + 1]; - for (int i = 0; i < len; ++i) { - dest[i] = wchar_t(str[i]); - } - dest[len] = 0; - return dest; -} - -wchar_t* coco_string_create(const char* str, int index, int length) { - int len = str ? length : 0; - wchar_t* dest = new wchar_t[len + 1]; - for (int i = 0; i < len; ++i) { - dest[i] = wchar_t(str[index + i]); - } - dest[len] = 0; - return dest; -} - - -char* coco_string_create_char(const wchar_t* str) { - int len = coco_string_length(str); - char *dest = new char[len + 1]; - for (int i = 0; i < len; ++i) - { - dest[i] = char(str[i]); - } - dest[len] = 0; - return dest; -} - -char* coco_string_create_char(const wchar_t* str, int index, int length) { - int len = coco_string_length(str); - if (len) { - len = length; - } - char *dest = new char[len + 1]; - for (int i = 0; i < len; ++i) { - dest[i] = char(str[index + i]); - } - dest[len] = 0; - return dest; -} - - -void coco_string_delete(char* &str) { - delete [] str; - str = NULL; -} - - -double coco_string_toDouble(const char* str) -{ - return str ? strtod(str, NULL) : 0; -} - -float coco_string_toFloat(const char* str) -{ - return str ? strtof(str, NULL) : 0; -} - - -// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * // - - -Token::Token() -: - kind(0), - pos(0), - col(0), - line(0), - val(NULL), - next(NULL) -{} - - -// Note: this delete may not be correct if the token was actually -// allocated by the internal heap mechanism -Token::~Token() { - coco_string_delete(val); -} - - -// ---------------------------------------------------------------------------- -// Buffer Implementation -// ---------------------------------------------------------------------------- - -Buffer::Buffer(Buffer* b) -: - buf(b->buf), - bufCapacity(b->bufCapacity), - bufLen(b->bufLen), - bufPos(b->bufPos), - bufStart(b->bufStart), - fileLen(b->fileLen), - cStream(b->cStream), - stdStream(b->stdStream), - isUserStream_(b->isUserStream_) -{ - // avoid accidental deletion on any of these members - b->buf = NULL; - b->cStream = NULL; - b->stdStream = NULL; -} - - -Buffer::Buffer(FILE* istr, bool isUserStream) -: - buf(NULL), - bufCapacity(0), - bufLen(0), - bufPos(0), - bufStart(0), - fileLen(0), - cStream(istr), - stdStream(NULL), - isUserStream_(isUserStream) -{ -// ensure binary read on windows -#if _MSC_VER >= 1300 - _setmode(_fileno(cStream), _O_BINARY); -#endif - - if (CanSeek()) { - fseek(cStream, 0, SEEK_END); - fileLen = ftell(cStream); - fseek(cStream, 0, SEEK_SET); - bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH; - bufStart = INT_MAX; // nothing in the buffer so far - } - - bufCapacity = (bufLen > 0) ? bufLen : MIN_BUFFER_LENGTH; - buf = new unsigned char[bufCapacity]; - if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start) - else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid - if (bufLen == fileLen && CanSeek()) Close(); -} - - -Buffer::Buffer(std::istream* istr, bool isUserStream) -: - buf(NULL), - bufCapacity(0), - bufLen(0), - bufPos(0), - bufStart(0), - fileLen(0), - cStream(NULL), - stdStream(istr), - isUserStream_(isUserStream) -{ - // ensure binary read on windows -#if _MSC_VER >= 1300 - // TODO -#endif -} - - -Buffer::Buffer(std::string& str) -: - buf(NULL), - bufCapacity(0), - bufLen(0), - bufPos(0), - bufStart(0), - fileLen(0), - cStream(NULL), - stdStream(new std::istringstream(str)), - isUserStream_(false) -{} - - -Buffer::Buffer(const unsigned char* chars, int len) -: - buf(new unsigned char[len]), - bufCapacity(len), - bufLen(len), - bufPos(0), - bufStart(0), - fileLen(len), - cStream(NULL), - stdStream(NULL), - isUserStream_(false) -{ - memcpy(this->buf, chars, len*sizeof(char)); -} - - -Buffer::Buffer(const char* chars, int len) -: - buf(new unsigned char[len]), - bufCapacity(len), - bufLen(len), - bufPos(0), - bufStart(0), - fileLen(len), - cStream(NULL), - stdStream(NULL), - isUserStream_(false) -{ - memcpy(this->buf, chars, len*sizeof(char)); -} - - -Buffer::~Buffer() { - Close(); - if (buf) { - delete [] buf; - buf = NULL; - } -} - - -void Buffer::Close() { - if (!isUserStream_) { - if (cStream) { - fclose(cStream); - cStream = NULL; - } - else if (stdStream) { - delete stdStream; - stdStream = 0; - } - } -} - - -int Buffer::Read() { - if (stdStream) - { - int ch = stdStream->get(); - if (stdStream->eof()) - { - return EoF; - } - return ch; - } - - if (bufPos < bufLen) { - return buf[bufPos++]; - } else if (GetPos() < fileLen) { - SetPos(GetPos()); // shift buffer start to Pos - return buf[bufPos++]; - } else if (cStream && !CanSeek() && (ReadNextStreamChunk() > 0)) { - return buf[bufPos++]; - } else { - return EoF; - } -} - - -int UTF8Buffer::Read() { - int ch; - do { - ch = Buffer::Read(); - // until we find a utf8 start (0xxxxxxx or 11xxxxxx) - } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EoF)); - if (ch < 128 || ch == EoF) { - // nothing to do, first 127 chars are the same in ascii and utf8 - // 0xxxxxxx or end of file character - } else if ((ch & 0xF0) == 0xF0) { - // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - int c1 = ch & 0x07; ch = Buffer::Read(); - int c2 = ch & 0x3F; ch = Buffer::Read(); - int c3 = ch & 0x3F; ch = Buffer::Read(); - int c4 = ch & 0x3F; - ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; - } else if ((ch & 0xE0) == 0xE0) { - // 1110xxxx 10xxxxxx 10xxxxxx - int c1 = ch & 0x0F; ch = Buffer::Read(); - int c2 = ch & 0x3F; ch = Buffer::Read(); - int c3 = ch & 0x3F; - ch = (((c1 << 6) | c2) << 6) | c3; - } else if ((ch & 0xC0) == 0xC0) { - // 110xxxxx 10xxxxxx - int c1 = ch & 0x1F; ch = Buffer::Read(); - int c2 = ch & 0x3F; - ch = (c1 << 6) | c2; - } - return ch; -} - - -int Buffer::Peek() { - int curPos = GetPos(); - int ch = Read(); - SetPos(curPos); - return ch; -} - - -int Buffer::GetPos() const { - if (stdStream) - { - return stdStream->tellg(); - } - - return bufPos + bufStart; -} - - -void Buffer::SetPos(int value) { - if (stdStream) - { - stdStream->seekg(value, std::ios::beg); - return; - } - - if ((value >= fileLen) && cStream && !CanSeek()) { - // Wanted position is after buffer and the stream - // is not seek-able e.g. network or console, - // thus we have to read the stream manually till - // the wanted position is in sight. - while ((value >= fileLen) && (ReadNextStreamChunk() > 0)) - {} - } - - if ((value < 0) || (value > fileLen)) { - wprintf(L"--- buffer out of bounds access, position: %d\n", value); - ::exit(1); - } - - if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer - bufPos = value - bufStart; - } else if (cStream) { // must be swapped in - fseek(cStream, value, SEEK_SET); - bufLen = fread(buf, sizeof(char), bufCapacity, cStream); - bufStart = value; bufPos = 0; - } else { - bufPos = fileLen - bufStart; // make Pos return fileLen - } -} - - -// Read the next chunk of bytes from the stream, increases the buffer -// if needed and updates the fields fileLen and bufLen. -// Returns the number of bytes read. -int Buffer::ReadNextStreamChunk() { - int freeLen = bufCapacity - bufLen; - if (freeLen == 0) { - // in the case of a growing input stream - // we can neither seek in the stream, nor can we - // foresee the maximum length, thus we must adapt - // the buffer size on demand. - bufCapacity = bufLen * 2; - unsigned char *newBuf = new unsigned char[bufCapacity]; - memcpy(newBuf, buf, bufLen*sizeof(char)); - delete [] buf; - buf = newBuf; - freeLen = bufLen; - } - int read = fread(buf + bufLen, sizeof(char), freeLen, cStream); - if (read > 0) { - fileLen = bufLen = (bufLen + read); - return read; - } - // end of stream reached - return 0; -} - - -bool Buffer::CanSeek() const { - return cStream && (ftell(cStream) != -1); -} - - -// ---------------------------------------------------------------------------- -// Scanner Implementation -// ---------------------------------------------------------------------------- - -Scanner::Scanner(FILE* istr) -: - buffer(new Buffer(istr, true)) -{ - Init(); -} - - -Scanner::Scanner(std::istream& istr) -: - buffer(new Buffer(&istr, true)) -{ - Init(); -} - - -Scanner::Scanner(const wchar_t* fileName) { - char *chFileName = coco_string_create_char(fileName); - FILE* istr; - if ((istr = fopen(chFileName, "rb")) == NULL) { - wprintf(L"--- Cannot open file %ls\n", fileName); - ::exit(1); - } - coco_string_delete(chFileName); - buffer = new Buffer(istr, false); - Init(); -} - - -Scanner::Scanner(const unsigned char* buf, int len) -: - buffer(new Buffer(buf, len)) -{ - Init(); -} - - -Scanner::Scanner(const char* buf, int len) -: - buffer(new Buffer(buf, len)) -{ - Init(); -} - - -Scanner::~Scanner() { - char* cur = reinterpret_cast<char*>(firstHeap); - - while (cur) { - cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE)); - free(firstHeap); - firstHeap = cur; - } - delete [] tval; - delete buffer; -} - - -void Scanner::Init() { - for (int i = 65; i <= 90; ++i) start.set(i, 1); - for (int i = 97; i <= 122; ++i) start.set(i, 1); - for (int i = 36; i <= 36; ++i) start.set(i, 5); - start.set(45, 20); - for (int i = 48; i <= 57; ++i) start.set(i, 9); - start.set(34, 2); - start.set(46, 7); - start.set(123, 14); - start.set(125, 15); - start.set(43, 21); - start.set(42, 16); - start.set(47, 17); - start.set(40, 18); - start.set(41, 19); - start.set(Buffer::EoF, -1); - - - - tvalLength = 128; - tval = new wchar_t[tvalLength]; // text of current token - - // HEAP_BLOCK_SIZE byte heap + pointer to next heap block - heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); - firstHeap = heap; - heapEnd = - reinterpret_cast<void**> - (reinterpret_cast<char*>(heap) + HEAP_BLOCK_SIZE); - *heapEnd = 0; - heapTop = heap; - if (sizeof(Token) > HEAP_BLOCK_SIZE) { - wprintf(L"--- Too small HEAP_BLOCK_SIZE\n"); - ::exit(1); - } - - pos = -1; line = 1; col = 0; - oldEols = 0; - NextCh(); - if (ch == 0xEF) { // check optional byte order mark for UTF-8 - NextCh(); int ch1 = ch; - NextCh(); int ch2 = ch; - if (ch1 != 0xBB || ch2 != 0xBF) { - wprintf(L"Illegal byte order mark at start of file"); - ::exit(1); - } - Buffer *oldBuf = buffer; - buffer = new UTF8Buffer(buffer); col = 0; - delete oldBuf; oldBuf = NULL; - NextCh(); - } - - - pt = tokens = CreateToken(); // first token is a dummy -} - - -void Scanner::NextCh() { - if (oldEols > 0) { - ch = EOL; - oldEols--; - } - else { - pos = buffer->GetPos(); - ch = buffer->Read(); col++; - // replace isolated '\r' by '\n' in order to make - // eol handling uniform across Windows, Unix and Mac - if (ch == L'\r' && buffer->Peek() != L'\n') ch = EOL; - if (ch == EOL) { line++; col = 0; } - } - -} - - -void Scanner::AddCh() { - if (tlen >= tvalLength) { - tvalLength *= 2; - wchar_t *newBuf = new wchar_t[tvalLength]; - memcpy(newBuf, tval, tlen*sizeof(wchar_t)); - delete [] tval; - tval = newBuf; - } - if (ch != Buffer::EoF) { - tval[tlen++] = ch; - NextCh(); - } -} - - - -bool Scanner::Comment0() { - int level = 1, pos0 = pos, line0 = line, col0 = col; - NextCh(); - if (ch == L'/') { - NextCh(); - for(;;) { - if (ch == 10) { - level--; - if (level == 0) { oldEols = line - line0; NextCh(); return true; } - NextCh(); - } else if (ch == buffer->EoF) return false; - else NextCh(); - } - } else { - buffer->SetPos(pos0); NextCh(); line = line0; col = col0; - } - return false; -} - -bool Scanner::Comment1() { - int level = 1, pos0 = pos, line0 = line, col0 = col; - NextCh(); - if (ch == L'*') { - NextCh(); - for(;;) { - if (ch == L'*') { - NextCh(); - if (ch == L'/') { - level--; - if (level == 0) { oldEols = line - line0; NextCh(); return true; } - NextCh(); - } - } else if (ch == L'/') { - NextCh(); - if (ch == L'*') { - level++; NextCh(); - } - } else if (ch == buffer->EoF) return false; - else NextCh(); - } - } else { - buffer->SetPos(pos0); NextCh(); line = line0; col = col0; - } - return false; -} - - -void Scanner::CreateHeapBlock() { - char* cur = reinterpret_cast<char*>(firstHeap); - - // release unused blocks - while - ( - (reinterpret_cast<char*>(tokens) < cur) - || (reinterpret_cast<char*>(tokens) > (cur + HEAP_BLOCK_SIZE)) - ) { - cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE)); - free(firstHeap); - firstHeap = cur; - } - - // HEAP_BLOCK_SIZE byte heap + pointer to next heap block - void* newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); - *heapEnd = newHeap; - heapEnd = - reinterpret_cast<void**> - (reinterpret_cast<char*>(newHeap) + HEAP_BLOCK_SIZE); - *heapEnd = 0; - heap = newHeap; - heapTop = heap; -} - - -Token* Scanner::CreateToken() { - const int reqMem = sizeof(Token); - if - ( - (reinterpret_cast<char*>(heapTop) + reqMem) - >= reinterpret_cast<char*>(heapEnd) - ) { - CreateHeapBlock(); - } - // token 'occupies' heap starting at heapTop - Token* tok = reinterpret_cast<Token*>(heapTop); - // increment past this part of the heap, which is now used - heapTop = - reinterpret_cast<void*> - (reinterpret_cast<char*>(heapTop) + reqMem); - tok->val = NULL; - tok->next = NULL; - return tok; -} - - -void Scanner::AppendVal(Token* tok) { - const int reqMem = (tlen + 1) * sizeof(wchar_t); - if - ( - (reinterpret_cast<char*>(heapTop) + reqMem) - >= reinterpret_cast<char*>(heapEnd) - ) { - if (reqMem > HEAP_BLOCK_SIZE) { - wprintf(L"--- Too long token value\n"); - ::exit(1); - } - CreateHeapBlock(); - } - - // add text value from heap - tok->val = reinterpret_cast<wchar_t*>(heapTop); - - // increment past this part of the heap, which is now used - heapTop = - reinterpret_cast<void*> - (reinterpret_cast<char*>(heapTop) + reqMem); - - // copy the currently parsed tval into the token - wcsncpy(tok->val, tval, tlen); - tok->val[tlen] = L'\0'; -} - - -Token* Scanner::NextToken() { - while (ch == ' ' || - (ch >= 9 && ch <= 10) || ch == 13 - ) NextCh(); - if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken(); - t = CreateToken(); - t->pos = pos; t->col = col; t->line = line; - int state = start.state(ch); - tlen = 0; AddCh(); - - switch (state) { - case -1: { t->kind = eofSym; break; } // NextCh already done - case 0: { t->kind = noSym; break; } // NextCh already done - case 1: - case_1: - if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;} - else {t->kind = 1; break;} - case 2: - case_2: - if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= L'!') || (ch >= L'#' && ch <= L'[') || (ch >= L']' && ch <= 65535)) {AddCh(); goto case_2;} - else if (ch == L'"') {AddCh(); goto case_4;} - else if (ch == 92) {AddCh(); goto case_3;} - else {t->kind = noSym; break;} - case 3: - case_3: - if ((ch >= L' ' && ch <= L'~')) {AddCh(); goto case_2;} - else {t->kind = noSym; break;} - case 4: - case_4: - {t->kind = 2; break;} - case 5: - if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} - else {t->kind = noSym; break;} - case 6: - case_6: - if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;} - else {t->kind = 3; break;} - case 7: - case_7: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;} - else {t->kind = noSym; break;} - case 8: - case_8: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;} - else {t->kind = 4; break;} - case 9: - case_9: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_9;} - else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;} - else if (ch == L'.') {AddCh(); goto case_13;} - else {t->kind = 4; break;} - case 10: - case_10: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;} - else if (ch == L'+' || ch == L'-') {AddCh(); goto case_11;} - else {t->kind = noSym; break;} - case 11: - case_11: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;} - else {t->kind = noSym; break;} - case 12: - case_12: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;} - else {t->kind = 4; break;} - case 13: - case_13: - if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_13;} - else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;} - else {t->kind = 4; break;} - case 14: - {t->kind = 5; break;} - case 15: - {t->kind = 6; break;} - case 16: - {t->kind = 9; break;} - case 17: - {t->kind = 10; break;} - case 18: - {t->kind = 11; break;} - case 19: - {t->kind = 12; break;} - case 20: - if (ch == L'.') {AddCh(); goto case_7;} - else {t->kind = 8; break;} - case 21: - if (ch == L'.') {AddCh(); goto case_7;} - else {t->kind = 7; break;} - - } - AppendVal(t); - return t; -} - - -// get the next token (possibly a token already seen during peeking) -Token* Scanner::Scan() { - if (tokens->next == NULL) { - return pt = tokens = NextToken(); - } else { - pt = tokens = tokens->next; - return tokens; - } -} - - -// peek for the next token, ignore pragmas -Token* Scanner::Peek() { - do { - if (pt->next == NULL) { - pt->next = NextToken(); - } - pt = pt->next; - } while (pt->kind > maxT); // skip pragmas - - return pt; -} - - -// make sure that peeking starts at the current scan position -void Scanner::ResetPeek() { - pt = tokens; -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // namespace -} // namespace -} // namespace - - -// ************************************************************************* // diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.h b/applications/test/dictionary/calcEntry/calcEntryScanner.h deleted file mode 100644 index fdebddeebed9f6792bf2a1922373a86379559282..0000000000000000000000000000000000000000 --- a/applications/test/dictionary/calcEntry/calcEntryScanner.h +++ /dev/null @@ -1,398 +0,0 @@ - - -#ifndef COCO_calcEntrySCANNER_H__ -#define COCO_calcEntrySCANNER_H__ - -#include <climits> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <cwchar> -#include <string> -#include <fstream> -#include <iostream> - -// io.h and fcntl are used to ensure binary read from streams on windows -#if _MSC_VER >= 1300 -#include <io.h> -#include <fcntl.h> -#endif - -#if _MSC_VER >= 1400 -#define coco_swprintf swprintf_s -#elif _MSC_VER >= 1300 -#define coco_swprintf _snwprintf -#else -// assume every other compiler knows swprintf -#define coco_swprintf swprintf -#endif - - -#define COCO_WCHAR_MAX 65535 - - -namespace Foam { -namespace functionEntries { -namespace calcEntryInternal { - - - -// * * * * * * * * * * Wide Character String Routines * * * * * * * * * * * // - -// -// string handling, wide character -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -//! Create by copying str -wchar_t* coco_string_create(const wchar_t* str); - -//! Create a substring of str starting at index and length characters long -wchar_t* coco_string_create(const wchar_t* str, int index, int length); - -//! Create a lowercase string from str -wchar_t* coco_string_create_lower(const wchar_t* str); - -//! Create a lowercase substring from str starting at index and length characters long -wchar_t* coco_string_create_lower(const wchar_t* str, int index, int length); - -//! Create a string by concatenating str1 and str2 -wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2); - -//! Create a string by concatenating a character to the end of str -wchar_t* coco_string_create_append(const wchar_t* str, const wchar_t ch); - -//! Free storage and nullify the argument -void coco_string_delete(wchar_t* &str); - -//! The length of the str, or 0 if the str is NULL -int coco_string_length(const wchar_t* str); - -//! Return true if the str ends with the endstr -bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr); - -//! Return the index of the first occurrence of ch. -// Return -1 if nothing is found. -int coco_string_indexof(const wchar_t* str, const wchar_t ch); - -//! Return the index of the last occurrence of ch. -// Return -1 if nothing is found. -int coco_string_lastindexof(const wchar_t* str, const wchar_t ch); - -//! Append str to dest -void coco_string_merge(wchar_t* &dest, const wchar_t* str); - -//! Compare strings, return true if they are equal -bool coco_string_equal(const wchar_t* str1, const wchar_t* str2); - -//! Compare strings, return 0 if they are equal -int coco_string_compareto(const wchar_t* str1, const wchar_t* str2); - -//! Simple string hashing function -int coco_string_hash(const wchar_t* str); - -// -// String conversions -// ~~~~~~~~~~~~~~~~~~ - -//! Convert wide string to double -double coco_string_toDouble(const wchar_t* str); - -//! Convert wide string to float -float coco_string_toFloat(const wchar_t* str); - -// -// String handling, byte character -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -//! Create by copying byte str -wchar_t* coco_string_create(const char* str); - -//! Create a substring of byte str starting at index and length characters long -wchar_t* coco_string_create(const char* str, int index, int length); - -//! Create a byte string by copying str -char* coco_string_create_char(const wchar_t* str); - -//! Create a byte substring of str starting at index and length characters long -char* coco_string_create_char(const wchar_t* str, int index, int length); - -//! Free storage and nullify the argument -void coco_string_delete(char* &str); - - -// -// String conversions, byte character -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -//! Convert byte string to double -double coco_string_toDouble(const char* str); - -//! Convert byte string to float -float coco_string_toFloat(const char* str); - -// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * // - - -//! Scanner Token -class Token -{ -public: - int kind; //!< token kind - int pos; //!< token position in the source text (starting at 0) - int col; //!< token column (starting at 1) - int line; //!< token line (starting at 1) - wchar_t* val; //!< token value - Token *next; //!< Peek tokens are kept in linked list - - Token(); //!< Construct null - ~Token(); //!< Destructor - cleanup allocated val?? -}; - - -//! Scanner Buffer -// -//! This Buffer supports the following cases: -//! -# seekable stream (file) -//! -# whole stream in buffer -//! -# part of stream in buffer -//! -# non seekable stream (network, console) -class Buffer { -private: - unsigned char *buf; //!< input buffer - int bufCapacity; //!< capacity of buf - int bufLen; //!< length of buffer - int bufPos; //!< current position in buffer - int bufStart; //!< position of first byte in buffer relative to input stream - int fileLen; //!< length of input stream (may change if the stream is no file) - FILE* cStream; //!< input stdio stream (normally seekable) - std::istream* stdStream; //!< STL std stream (seekable) - bool isUserStream_; //!< was the stream opened by the user? - - int ReadNextStreamChunk(); - bool CanSeek() const; //!< true if stream can be seeked otherwise false - -protected: - Buffer(Buffer*); //!< for the UTF8Buffer - -public: - static const int EoF = COCO_WCHAR_MAX + 1; - - //! Attach buffer to a stdio stream. - //! User streams are not closed in the destructor - Buffer(FILE*, bool isUserStream = true); - - //! Attach buffer to an STL std stream - //! User streams are not closed in the destructor - explicit Buffer(std::istream*, bool isUserStream = true); - - //! Copy buffer contents from constant string - //! Handled internally as an istringstream - explicit Buffer(std::string&); - - //! Copy buffer contents from constant character string - Buffer(const unsigned char* chars, int len); - //! Copy buffer contents from constant character string - Buffer(const char* chars, int len); - - //! Close stream (but not user streams) and free buf (if any) - virtual ~Buffer(); - - virtual void Close(); //!< Close stream (but not user streams) - virtual int Read(); //!< Get character from stream or buffer - virtual int Peek(); //!< Peek character from stream or buffer - - virtual int GetPos() const; - virtual void SetPos(int value); -}; - - -//! A Scanner buffer that handles UTF-8 characters -class UTF8Buffer : public Buffer { -public: - UTF8Buffer(Buffer* b) : Buffer(b) {} - virtual int Read(); -}; - - -//------------------------------------------------------------------------------ -// StartStates -//------------------------------------------------------------------------------ -//! maps characters (integers) to start states of tokens -class StartStates { -private: - class Elem { - public: - int key, val; - Elem *next; - Elem(int k, int v) : - key(k), val(v), next(0) - {} - }; - - Elem **tab; - -public: - StartStates() : - tab(new Elem*[128]) - { - memset(tab, 0, 128 * sizeof(Elem*)); - } - - virtual ~StartStates() { - for (int i = 0; i < 128; ++i) { - Elem *e = tab[i]; - while (e) { - Elem *next = e->next; - delete e; - e = next; - } - } - delete [] tab; - } - - void set(int key, int val) { - Elem *e = new Elem(key, val); - int k = unsigned(key) % 128; - e->next = tab[k]; - tab[k] = e; - } - - int state(int key) { - Elem *e = tab[unsigned(key) % 128]; - while (e && e->key != key) e = e->next; - return e ? e->val : 0; - } -}; - - -//------------------------------------------------------------------------------ -// KeywordMap -//------------------------------------------------------------------------------ -//! maps strings to integers (identifiers to keyword kinds) -class KeywordMap { -private: - class Elem { - public: - wchar_t *key; - int val; - Elem *next; - Elem(const wchar_t *k, int v) : - key(coco_string_create(k)), val(v), next(0) - {} - virtual ~Elem() { - coco_string_delete(key); - } - }; - - Elem **tab; - -public: - KeywordMap() : - tab(new Elem*[128]) - { - memset(tab, 0, 128 * sizeof(Elem*)); - } - - virtual ~KeywordMap() { - for (int i = 0; i < 128; ++i) { - Elem *e = tab[i]; - while (e) { - Elem *next = e->next; - delete e; - e = next; - } - } - delete [] tab; - } - - void set(const wchar_t *key, int val) { - Elem *e = new Elem(key, val); - const int k = coco_string_hash(key) % 128; - e->next = tab[k]; - tab[k] = e; - } - - int get(const wchar_t *key, int defaultVal) { - Elem *e = tab[coco_string_hash(key) % 128]; - while (e && !coco_string_equal(e->key, key)) e = e->next; - return e ? e->val : defaultVal; - } -}; - - -//! A Coco/R Scanner -class Scanner { -private: - static const int maxT = 13; - static const int noSym = 13; - - static const int eofSym = 0; //!< end-of-file token id - static const char EOL = '\n'; //!< end-of-line character - - void *firstHeap; //!< the start of the heap management - void *heap; //!< the currently active block - void *heapTop; //!< the top of the heap - void **heapEnd; //!< the end of the last heap block - - StartStates start; //!< A map of start states for particular characters - KeywordMap keywords; //!< A hash of keyword literals to token kind - - Token *t; //!< current token - wchar_t *tval; //!< text of current token - int tvalLength; //!< maximum capacity (length) for tval - int tlen; //!< length of tval - - Token *tokens; //!< list of tokens already peeked (first token is a dummy) - Token *pt; //!< current peek token - - int ch; //!< current input character - - int pos; //!< byte position of current character - int line; //!< line number of current character - int col; //!< column number of current character - int oldEols; //!< the number of EOLs that appeared in a comment - - void CreateHeapBlock(); //!< add a heap block, freeing unused ones - Token* CreateToken(); //!< fit token on the heap - void AppendVal(Token* tok); //!< adjust tok->val to point to the heap and copy tval into it - - void Init(); //!< complete the initialization for the constructors - void NextCh(); //!< get the next input character into ch - void AddCh(); //!< append the character ch to tval - bool Comment0(); - bool Comment1(); - - Token* NextToken(); //!< get the next token - -public: - //! The scanner buffer - Buffer *buffer; - - //! Using an existing open file handle for the scanner - Scanner(FILE*); - - //! Using an existing open STL std stream - explicit Scanner(std::istream&); - - //! Open a file for reading and attach scanner - explicit Scanner(const wchar_t* fileName); - - //! Attach scanner to an existing character buffer - Scanner(const unsigned char* chars, int len); - //! Attach scanner to an existing character buffer - Scanner(const char* chars, int len); - - ~Scanner(); //!< free heap and allocated memory - Token* Scan(); //!< get the next token (possibly a token already seen during peeking) - Token* Peek(); //!< peek for the next token, ignore pragmas - void ResetPeek(); //!< ensure that peeking starts at the current scan position - -}; // end Scanner - -} // namespace -} // namespace -} // namespace - - -#endif // COCO_calcEntrySCANNER_H__ - diff --git a/applications/test/dictionary/testDictCalc b/applications/test/dictionary/testDictCalc index f1d67650e855526718e33e461fa254079990eac9..577cbf112d96c38a3c443cfb190961a4720892d6 100644 --- a/applications/test/dictionary/testDictCalc +++ b/applications/test/dictionary/testDictCalc @@ -10,7 +10,7 @@ FoamFile version 2.0; format ascii; class dictionary; - object testDictTest; + object testDictCalc; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -19,28 +19,13 @@ flowRatePerHour 720; x 10; y 20; z t s v; -// z #test{ // this -// 123 - 456 -// // comments // are -// /* stripped -// * 10 -// * {} -// */ -// + 1 /*100 */ 10 -// }; - -p this calculation #calc{ - 1 + 2 + 10 * 15 + - $x - $y - // $x + $y -} -is done inplace; +p #calc{ 1 + 2 + 10 * 15 + $x - $y }; +// this calculation is in-place, but does not work inside a string: +flowRate "The flow rate " #calc{ $flowRatePerHour / 3600 } "kg/s"; -flowRate #calc{ $flowRatePerHour / 3600}; +// this is also okay +x #calc{ $x * 1E-3 }; -xxx yyy; -foo 30; -bar 15; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/applications/test/dictionary/testDictCalcError b/applications/test/dictionary/testDictCalcError new file mode 100644 index 0000000000000000000000000000000000000000..95b90ce8e8186a01ee01164bd2969f5cbe2d2027 --- /dev/null +++ b/applications/test/dictionary/testDictCalcError @@ -0,0 +1,46 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: Any | +| \\ / A nd | Web: www.OpenFOAM.org | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object testDictCalcError; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +flowRatePerHour 720; + +x 10; +y 20; +z t s v; +// z #test{ // this +// 123 - 456 +// // comments // are +// /* stripped +// * 10 +// * {} +// */ +// + 1 /*100 */ 10 +// }; + +p this calculation #calc{ + 1xxx1 + 2 + 10 * 15 + + $x - $y + // $x + $y +} +is done inplace; + + +flowRate #calc{ $flowRatePerHour / 3600}; + +xxx yyy; +foo 30; +bar 15; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 9c18e7255554a2f30fdde1980d8b2b24cff66dbe..d8634de6dfdc75f0852cab846fd032ff45c8da8b 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -142,6 +142,12 @@ $(functionEntries)/includeIfPresentEntry/includeIfPresentEntry.C $(functionEntries)/inputModeEntry/inputModeEntry.C $(functionEntries)/removeEntry/removeEntry.C +calcEntry = $(functionEntries)/calcEntry +$(calcEntry)/calcEntryParser.atg +$(calcEntry)/calcEntryInternal.C +$(calcEntry)/calcEntry.C + + IOdictionary = db/IOobjects/IOdictionary $(IOdictionary)/IOdictionary.C $(IOdictionary)/IOdictionaryIO.C diff --git a/src/OpenFOAM/Make/options b/src/OpenFOAM/Make/options index 4eba86ae56d914aed88f7c06eb8d50c24b6f492b..b1cc1a2d10a16d24ecee7fd9ac347019fa4ed786 100644 --- a/src/OpenFOAM/Make/options +++ b/src/OpenFOAM/Make/options @@ -1,4 +1,4 @@ -EXE_INC = +EXE_INC = -I$(OBJECTS_DIR) LIB_LIBS = \ $(FOAM_LIBBIN)/libOSspecific.o \ diff --git a/applications/test/dictionary/calcEntry/calcEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.C similarity index 87% rename from applications/test/dictionary/calcEntry/calcEntry.C rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.C index 98108123083a6d58dc8f2a5d6f664b783ec77225..0f0bfbbdc84bf333bc1ca3a5f92db1c8401003d4 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -68,17 +68,23 @@ bool Foam::functionEntries::calcEntry::execute myErrorHandler("calcEntryInternal::Parser"); calcEntryInternal::Scanner scanner(iss); + + // set the starting line + scanner.Line(is.lineNumber()); + calcEntryInternal::Parser parser(&scanner, &myErrorHandler); // Attach dictionary context parser.dict(parentDict); - // Attach scalar functions - // parser.functions(parentDict); - parser.Parse(); - // make a small input list to contain the answer + // mostly have an extra newline in the lookahead token + // so subtract 1 to keep things vaguely in sync + // (this is still far from perfect) + is.lineNumber() = scanner.Line() - 1; + + // a small input list to contain the answer tokenList tokens(2); tokens[0] = parser.Result(); tokens[1] = token::END_STATEMENT; diff --git a/applications/test/dictionary/calcEntry/calcEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H similarity index 97% rename from applications/test/dictionary/calcEntry/calcEntry.H rename to src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H index 027c4b510b74258ade09325a34b4d70601e47c02..3db7562161c7ff4db4e7b9a38442a5899462cfc8 100644 --- a/applications/test/dictionary/calcEntry/calcEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntry.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2009-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License diff --git a/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.C b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.C new file mode 100644 index 0000000000000000000000000000000000000000..086238d9a3b5665f23bdae47d6ec7672c946d41c --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.C @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +\*---------------------------------------------------------------------------*/ + +#include "calcEntryInternal.H" +#include "addToGlobalFunctionSelectionTable.H" +#include "unitConversion.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ +namespace calcEntryInternal +{ + +defineGlobalFunctionSelectionTable(dispatch,ParamList); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#define globalConstant0(Name, Constant)\ +scalar Name##_0(const UList<scalar>& param) \ +{ \ + return Constant; \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0) + + +#define globalFunction0(Name, Function)\ +scalar Name##_0(const UList<scalar>& param) \ +{ \ + return Function(); \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0) + + +#define globalFunction1(Name, Function)\ +scalar Name##_1(const UList<scalar>& param) \ +{ \ + return Function(param[0]); \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_1,&Name##_1) + + +#define globalFunction2(Name, Function)\ +scalar Name##_2(const UList<scalar>& param) \ +{ \ + return Function(param[0], param[1]); \ +} \ +addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_2,&Name##_2) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +globalConstant0(pi, constant::mathematical::pi); + +globalFunction1(degToRad, degToRad); +globalFunction1(radToDeg, radToDeg); +globalFunction1(asin, Foam::asin); +globalFunction1(acos, Foam::acos); +globalFunction1(atan, Foam::atan); +globalFunction1(sin, Foam::sin); +globalFunction1(cos, Foam::cos); +globalFunction1(tan, Foam::tan); +globalFunction1(log, Foam::log); +globalFunction1(log10, Foam::log10); +globalFunction1(mag, Foam::mag); + +globalFunction2(atan2, Foam::atan2); +globalFunction2(pow, Foam::pow); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +scalar dispatch(const word& name, const UList<scalar>& param) +{ + // create lookup name with parameter count + const word lookupName = name + '_' + Foam::name(param.size()); + + dispatchParamListMemberFunctionTable::iterator mfIter = + dispatchParamListMemberFunctionTablePtr_->find(lookupName); + + if (mfIter == dispatchParamListMemberFunctionTablePtr_->end()) + { + FatalErrorIn + ( + "calcEntryInternal::scalarFunctions::dispatch" + "(const word&, const UList<scalar>&) : " + ) << "Unknown function " << name << nl << nl + << "Valid types are :" << endl + << dispatchParamListMemberFunctionTablePtr_->sortedToc() + << exit(FatalError); + } + + return mfIter()(param); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace calcEntryInternal +} // End namespace functionEntries +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.H b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.H new file mode 100644 index 0000000000000000000000000000000000000000..2dd3a0305682064df767e60ac6929f4e31844110 --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryInternal.H @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Namespace + Foam::functionEntries::calcEntryInternal + +Description + Contains global functions and classes for the calcEntry. + +SourceFiles + calcEntryInternal.C + +\*---------------------------------------------------------------------------*/ + +#ifndef calcEntryInternal_H +#define calcEntryInternal_H + +#include "error.H" +#include "scalar.H" +#include "DynamicList.H" +#include "globalFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionEntries +{ +namespace calcEntryInternal +{ + + // Global Function Selectors + + declareGlobalFunctionSelectionTable + ( + scalar, + dispatch, + ParamList, + ( + const UList<scalar>& param + ), + (param) + ); + + + //- Dispatch calculation to the named function + scalar dispatch(const word&, const UList<scalar>&); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace calcEntryInternal +} // End namespace functionEntries +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryParser.atg b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryParser.atg new file mode 100644 index 0000000000000000000000000000000000000000..755f539d98398a20060c0625de835882096cb3ae --- /dev/null +++ b/src/OpenFOAM/db/dictionary/functionEntries/calcEntry/calcEntryParser.atg @@ -0,0 +1,258 @@ +/*---------------------------------------------------------------------------*\ + Attributed Grammar for Coco/R (-*- C++ -*- version) + compile with: + coco-cpp calcEntryParser.atg +\*---------------------------------------------------------------------------*/ +[copy] +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file calcEntryParser.atg + +Description + An attributed Coco/R grammar to parse simple arithmetic expressions + + Includes support for dictionary $variables and some scalar functions + (eg, sin, pow, ...) + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +[/copy] +#include "dictionary.H" +#include "wchar.H" +#include "calcEntryInternal.H" + + +COMPILER calcEntry + // grammar pragmas: + $prefix=calcEntry + $namespace=Foam::functionEntries::calcEntryInternal + $define=EXPLICIT_EOF // grammar handles eof itself + $define=STREAMS_ONLY // only use STL streams + $define=NO_UTF8 // disable UTF8 on input + +private: + //- The parent dictionary + dictionary* dict_; + + //- The calculation result + scalar val; + + //- lookup dictionary entry + scalar getDictLookup(const word&) const; + +public: + + //- attach a dictionary + void dict(const dictionary& dict) + { + dict_ = const_cast<dictionary*>(&dict); + } + + //- Return the calculated result + scalar Result() const + { + return val; + } + + +/*---------------------------------------------------------------------------*/ + +[initialize] // add to Parser constructor + dict_ = 0; + val = 0; +[/initialize] + +/*---------------------------------------------------------------------------*/ +[code] +Foam::scalar Parser::getDictLookup(const word& keyword) const +{ + if (!dict_) + { + FatalErrorIn + ( + "calcEntry::getDictEntry(const word&) const" + ) << "No dictionary attached!" + << exit(FatalError); + + return 0; + } + + scalar dictValue = 0; + + entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false); + if (entryPtr && !entryPtr->isDict()) + { + if (entryPtr->stream().size() != 1) + { + FatalErrorIn + ( + "calcEntry::getDictEntry(const word&) const" + ) << "keyword " << keyword << " has " + << entryPtr->stream().size() << " values in dictionary " + << exit(FatalError); + } + entryPtr->stream() >> dictValue; + } + else + { + FatalErrorIn + ( + "calcEntry::getDictEntry(const word&) const" + ) << "keyword " << keyword << " is undefined in dictionary " + << exit(FatalError); + } + + return dictValue; +} +[/code] + +/*---------------------------------------------------------------------------*/ + +CHARACTERS + letter = 'A'..'Z' + 'a'..'z' + '_'. + digit = "0123456789". + alphanum = letter + digit. + sign = '+' + '-'. + cr = '\r'. + lf = '\n'. + tab = '\t'. + stringCh = ANY - '"' - '\\' - cr - lf. + printable = '\u0020' .. '\u007e'. + + +// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * // + +TOKENS + +// identifier +ident = + letter { alphanum }. + +// string +string = + '"' { stringCh | '\\' printable } '"'. + +// dictionary lookup identifier +// starts with '$' and otherwise limited to a normal identifier +variable = + '$' letter { alphanum }. + +// floating point and integer numbers +number = + [sign] ('.' digit { digit } ) | ( digit { digit } [ '.' { digit } ]) + [ ('E' | 'e') [sign] digit { digit } ]. + + +// * * * * * * * * * * * PRAGMAS / COMMENTS / IGNORE * * * * * * * * * * * // + +COMMENTS FROM "/*" TO "*/" NESTED +COMMENTS FROM "//" TO lf + +IGNORE cr + lf + tab + + +// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * // + +PRODUCTIONS + +calcEntry (. val = 0; .) += + '{' Expr<val> '}' (. // reposition to immediately after the closing '}' + scanner->buffer->SetPos(t->pos + 1); + .) + | ( Expr<val> EOF ) +. + + +/*---------------------------------------------------------------------------*/ + +Expr<scalar& val> (. scalar val2 = 0; .) += + Term<val> + { + '+' Term<val2> (. val += val2; .) + | '-' Term<val2> (. val -= val2; .) + } +. + + +/*---------------------------------------------------------------------------*/ + +Term<scalar& val> (. scalar val2 = 0; .) += + Factor<val> + { + '*' Factor<val2> (. val *= val2; .) + | '/' Factor<val2> (. val /= val2; .) + } +. + + +/*---------------------------------------------------------------------------*/ + +// Note the treatment of the leading signs is fairly generous +// eg, "10 + - 10" is treated like "10 + -10" +// +Factor<scalar& val> (. bool negative = false; .) += + ['+' | '-' (. negative = true; .) + ] + ( + Func<val> | '(' Expr<val> ')' + | variable (. + // skip leading '$' for the keyword + val = getDictLookup(t->toString(1, t->length()-1)); + .) + | number (. val = coco_string_toDouble(t->val); .) + ) (. if (negative) { val = -val; } .) +. + + +/*---------------------------------------------------------------------------*/ + +// functions like sin(x) or pow(x, y) etc. +Func<scalar& val> += + ident (. + word funcName(t->toString()); + DynamicList<scalar> stack(4); + .) + '(' + [ (. scalar x; .) + Expr<x> (. stack.append(x); .) + { ',' Expr<x> (. stack.append(x); .) + } + ] + ')' (. val = dispatch(funcName, stack); .) +. + + +/*---------------------------------------------------------------------------*/ + +END calcEntry. + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/error/CocoParserErrors.H b/src/OpenFOAM/db/error/CocoParserErrors.H index 21f574592dbec36011d24f18eb8b6aad1e33555d..97d503204f1b38ccf5abfaffb4990a5eb4af4621 100644 --- a/src/OpenFOAM/db/error/CocoParserErrors.H +++ b/src/OpenFOAM/db/error/CocoParserErrors.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -45,7 +45,7 @@ namespace Foam Class CocoParserErrors Declaration \*---------------------------------------------------------------------------*/ -template<class BaseClass> +template<class BaseClass, class StringClass=std::wstring> class CocoParserErrors : public BaseClass @@ -90,14 +90,14 @@ public: // Error Handling //- Handle a general warning 'msg' - virtual void Warning(const wchar_t* msg) + virtual void Warning(const StringClass& msg) { WarningIn(name_) << msg << endl; } //- Handle a general warning 'msg' - virtual void Warning(int line, int col, const wchar_t* msg) + virtual void Warning(int line, int col, const StringClass& msg) { WarningIn(name_) <<"line " << line << " col " << col << ": " @@ -105,7 +105,7 @@ public: } //- Handle general error 'msg' (eg, a semantic error) - virtual void Error(int line, int col, const wchar_t* msg) + virtual void Error(int line, int col, const StringClass& msg) { FatalErrorIn(name_) << "line " << line << " col " << col <<": " << msg << endl @@ -113,7 +113,7 @@ public: } //- Handle general error 'msg' (eg, a semantic error) - virtual void Error(const wchar_t* msg) + virtual void Error(const StringClass& msg) { FatalErrorIn(name_) << msg << endl @@ -121,7 +121,7 @@ public: } //- Handle a general exception 'msg' - virtual void Exception(const wchar_t* msg) + virtual void Exception(const StringClass& msg) { this->Error(msg); } diff --git a/src/OpenFOAM/db/runTimeSelection/addToRunTimeSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/construction/addToRunTimeSelectionTable.H similarity index 100% rename from src/OpenFOAM/db/runTimeSelection/addToRunTimeSelectionTable.H rename to src/OpenFOAM/db/runTimeSelection/construction/addToRunTimeSelectionTable.H diff --git a/src/OpenFOAM/db/runTimeSelection/runTimeSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/construction/runTimeSelectionTables.H similarity index 100% rename from src/OpenFOAM/db/runTimeSelection/runTimeSelectionTables.H rename to src/OpenFOAM/db/runTimeSelection/construction/runTimeSelectionTables.H diff --git a/src/OpenFOAM/db/runTimeSelection/globalFunctions/addToGlobalFunctionSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/globalFunctions/addToGlobalFunctionSelectionTable.H new file mode 100644 index 0000000000000000000000000000000000000000..d6eadfdd74c0e2541d3b79130e9b840bb057a931 --- /dev/null +++ b/src/OpenFOAM/db/runTimeSelection/globalFunctions/addToGlobalFunctionSelectionTable.H @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::addToGlobalFunctionSelectionTable + +Description + Macros for easy insertion into global function selection tables + +\*---------------------------------------------------------------------------*/ + +#ifndef addToGlobalFunctionSelectionTable_H +#define addToGlobalFunctionSelectionTable_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// add to hash-table of functions with 'lookup' as the key +#define addNamedToGlobalFunctionSelectionTable\ +(memberFunction,argNames,lookup,functionPtr) \ + \ + /* Add to the table, find by lookup name */ \ + add##memberFunction##argNames##GlobalMemberFunctionToTable \ + add_##lookup##_##memberFunction##argNames##GlobalMemberFunctionTo##Table_\ + (#lookup, functionPtr) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/runTimeSelection/globalFunctions/globalFunctionSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/globalFunctions/globalFunctionSelectionTables.H new file mode 100644 index 0000000000000000000000000000000000000000..4a7dfb4ac4b5c8f27a5625ae40830eac9d5c2937 --- /dev/null +++ b/src/OpenFOAM/db/runTimeSelection/globalFunctions/globalFunctionSelectionTables.H @@ -0,0 +1,145 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::globalFunctionSelectionTables + +Description + Macros to enable the easy declaration of global function selection tables. + +\*---------------------------------------------------------------------------*/ + +#ifndef globalMemberFunctionSelectionTables_H +#define globalMemberFunctionSelectionTables_H + +#include "memberFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// external use: +// ~~~~~~~~~~~~~ +// declare a run-time selection: +#define declareGlobalFunctionSelectionTable\ +(returnType,memberFunction,argNames,argList,parList) \ + \ + /* Construct from argList function pointer type */ \ + typedef returnType (*memberFunction##argNames##MemberFunctionPtr)argList; \ + \ + /* Construct from argList function table type */ \ + typedef HashTable \ + <memberFunction##argNames##MemberFunctionPtr, word, string::hash> \ + memberFunction##argNames##MemberFunctionTable; \ + \ + /* Construct from argList function pointer table pointer */ \ + extern memberFunction##argNames##MemberFunctionTable* \ + memberFunction##argNames##MemberFunctionTablePtr_; \ + \ + /* Table memberFunction called from the table add function */ \ + void construct##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Table destructor called from the table add function destructor */ \ + void destroy##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Class to add constructor from argList to table */ \ + class add##memberFunction##argNames##GlobalMemberFunctionToTable \ + { \ + public: \ + \ + add##memberFunction##argNames##GlobalMemberFunctionToTable \ + ( \ + const word& lookup, \ + memberFunction##argNames##MemberFunctionPtr function \ + ) \ + { \ + construct##memberFunction##argNames##MemberFunctionTables(); \ + memberFunction##argNames##MemberFunctionTablePtr_->insert \ + ( \ + lookup, \ + function \ + ); \ + } \ + \ + ~add##memberFunction##argNames##GlobalMemberFunctionToTable() \ + { \ + destroy##memberFunction##argNames##MemberFunctionTables(); \ + } \ + } + +// internal use: +// constructor/destructor aid +#define defineGlobalFunctionSelectionTableConstructDestruct\ +(memberFunction,argNames) \ + \ + /* Table constructor called from the table add function */ \ + void construct##memberFunction##argNames##MemberFunctionTables()\ + { \ + static bool constructed = false; \ + if (!constructed) \ + { \ + constructed = true; \ + memberFunction##argNames##MemberFunctionTablePtr_ \ + = new memberFunction##argNames##MemberFunctionTable; \ + } \ + } \ + \ + /* Table destructor called from the table add function destructor */ \ + void destroy##memberFunction##argNames##MemberFunctionTables()\ + { \ + if (memberFunction##argNames##MemberFunctionTablePtr_) \ + { \ + delete memberFunction##argNames##MemberFunctionTablePtr_; \ + memberFunction##argNames##MemberFunctionTablePtr_ = NULL; \ + } \ + } + + +// internal use: +// create pointer to hash-table of functions +#define defineGlobalFunctionSelectionTablePtr\ +(memberFunction,argNames) \ + \ + /* Define the memberFunction table */ \ + memberFunction##argNames##MemberFunctionTable* \ + memberFunction##argNames##MemberFunctionTablePtr_ = NULL + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// external use: +// ~~~~~~~~~~~~~ +// define run-time selection table +#define defineGlobalFunctionSelectionTable\ +(memberFunction,argNames) \ + \ + defineGlobalFunctionSelectionTablePtr \ + (memberFunction,argNames); \ + defineGlobalFunctionSelectionTableConstructDestruct \ + (memberFunction,argNames) + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/memberFunctionSelection/addToMemberFunctionSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/memberFunctions/addToMemberFunctionSelectionTable.H similarity index 100% rename from src/OpenFOAM/db/memberFunctionSelection/addToMemberFunctionSelectionTable.H rename to src/OpenFOAM/db/runTimeSelection/memberFunctions/addToMemberFunctionSelectionTable.H diff --git a/src/OpenFOAM/db/memberFunctionSelection/memberFunctionSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/memberFunctions/memberFunctionSelectionTables.H similarity index 100% rename from src/OpenFOAM/db/memberFunctionSelection/memberFunctionSelectionTables.H rename to src/OpenFOAM/db/runTimeSelection/memberFunctions/memberFunctionSelectionTables.H diff --git a/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/addToStaticMemberFunctionSelectionTable.H b/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/addToStaticMemberFunctionSelectionTable.H new file mode 100644 index 0000000000000000000000000000000000000000..572f93ae23e426310ba74a711604c63b7351bed9 --- /dev/null +++ b/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/addToStaticMemberFunctionSelectionTable.H @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::addToStaticMemberFunctionSelectionTable + +Description + Macros for easy insertion into member function selection tables + +\*---------------------------------------------------------------------------*/ + +#ifndef addToStaticMemberFunctionSelectionTable_H +#define addToStaticMemberFunctionSelectionTable_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// add to hash-table of functions with 'lookup' as the key +#define addNamedToStaticMemberFunctionSelectionTable\ +(baseType,thisType,memberFunction,argNames,lookup,functionPtr) \ + \ + /* Add the thisType memberFunction to the table, find by lookup name */ \ + baseType::add##memberFunction##argNames##StaticMemberFunctionToTable<thisType> \ + add_##lookup##_##thisType##memberFunction##argNames##StaticMemberFunctionTo##baseType##Table_\ + (#lookup, functionPtr) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/staticMemberFunctionSelectionTables.H b/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/staticMemberFunctionSelectionTables.H new file mode 100644 index 0000000000000000000000000000000000000000..3febd71e8a0684a0680ecbfe1a0cc9802afe606b --- /dev/null +++ b/src/OpenFOAM/db/runTimeSelection/staticMemberFunctions/staticMemberFunctionSelectionTables.H @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file Foam::staticMemberFunctionSelectionTables + +Description + Macros to enable the easy declaration of member function selection tables. + +\*---------------------------------------------------------------------------*/ + +#ifndef staticMemberFunctionSelectionTables_H +#define staticMemberFunctionSelectionTables_H + +#include "memberFunctionSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +// external use: +// ~~~~~~~~~~~~~ +// declare a run-time selection: +#define declareStaticMemberFunctionSelectionTable\ +(returnType,baseType,memberFunction,argNames,argList,parList) \ + \ + /* Construct from argList function pointer type */ \ + typedef returnType (*memberFunction##argNames##MemberFunctionPtr)argList; \ + \ + /* Construct from argList function table type */ \ + typedef HashTable \ + <memberFunction##argNames##MemberFunctionPtr, word, string::hash> \ + memberFunction##argNames##MemberFunctionTable; \ + \ + /* Construct from argList function pointer table pointer */ \ + static memberFunction##argNames##MemberFunctionTable* \ + memberFunction##argNames##MemberFunctionTablePtr_; \ + \ + /* Table memberFunction called from the table add function */ \ + static void construct##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Table destructor called from the table add function destructor */ \ + static void destroy##memberFunction##argNames##MemberFunctionTables(); \ + \ + /* Class to add constructor from argList to table */ \ + template<class baseType##Type> \ + class add##memberFunction##argNames##StaticMemberFunctionToTable \ + { \ + public: \ + \ + add##memberFunction##argNames##StaticMemberFunctionToTable \ + ( \ + const word& lookup, \ + memberFunction##argNames##MemberFunctionPtr function \ + ) \ + { \ + construct##memberFunction##argNames##MemberFunctionTables(); \ + memberFunction##argNames##MemberFunctionTablePtr_->insert \ + ( \ + lookup, \ + function \ + ); \ + } \ + \ + ~add##memberFunction##argNames##StaticMemberFunctionToTable() \ + { \ + destroy##memberFunction##argNames##MemberFunctionTables(); \ + } \ + } + + +// internal use: +// constructor/destructor aid +#define defineStaticMemberFunctionSelectionTableConstructDestruct\ +(baseType,memberFunction,argNames) \ + \ + /* Table constructor called from the table add function constructor */ \ + void baseType::construct##memberFunction##argNames##MemberFunctionTables()\ + { \ + static bool constructed = false; \ + if (!constructed) \ + { \ + constructed = true; \ + baseType::memberFunction##argNames##MemberFunctionTablePtr_ \ + = new baseType::memberFunction##argNames##MemberFunctionTable;\ + } \ + }; \ + \ + /* Table destructor called from the table add function destructor */ \ + void baseType::destroy##memberFunction##argNames##MemberFunctionTables() \ + { \ + if (baseType::memberFunction##argNames##MemberFunctionTablePtr_) \ + { \ + delete baseType::memberFunction##argNames##MemberFunctionTablePtr_;\ + baseType::memberFunction##argNames##MemberFunctionTablePtr_ = NULL;\ + } \ + } + + +// internal use: +// create pointer to hash-table of functions +#define defineStaticMemberFunctionSelectionTablePtr\ +(baseType,memberFunction,argNames) \ + \ + /* Define the memberFunction table */ \ + baseType::memberFunction##argNames##MemberFunctionTable* \ + baseType::memberFunction##argNames##MemberFunctionTablePtr_ = NULL + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// external use: +// ~~~~~~~~~~~~~ +// define run-time selection table +#define defineStaticMemberFunctionSelectionTable\ +(baseType,memberFunction,argNames) \ + \ + defineStaticMemberFunctionSelectionTablePtr \ + (baseType,memberFunction,argNames); \ + defineStaticMemberFunctionSelectionTableConstructDestruct \ + (baseType,memberFunction,argNames) \ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/chars/wchar/wchar.H b/src/OpenFOAM/primitives/chars/wchar/wchar.H index 61519a51d345032b8e96e262035b7009d8eba642..d4df7a61eaac704c77d8a39cc3e5ef465148f474 100644 --- a/src/OpenFOAM/primitives/chars/wchar/wchar.H +++ b/src/OpenFOAM/primitives/chars/wchar/wchar.H @@ -41,6 +41,7 @@ SeeAlso #define wchar_H #include <cwchar> +#include <string> // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -58,6 +59,9 @@ Ostream& operator<<(Ostream&, const wchar_t); //- Output wide character (Unicode) string as UTF-8 Ostream& operator<<(Ostream&, const wchar_t*); +//- Output wide character (Unicode) string as UTF-8 +Ostream& operator<<(Ostream&, const std::wstring&); + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/primitives/chars/wchar/wcharIO.C b/src/OpenFOAM/primitives/chars/wchar/wcharIO.C index 9796d4b6eb9658eb4f8f68c8ff6fe8e3683a9f38..37f81321efd0e5fa6112bfb8cf33b3a59713efd6 100644 --- a/src/OpenFOAM/primitives/chars/wchar/wcharIO.C +++ b/src/OpenFOAM/primitives/chars/wchar/wcharIO.C @@ -101,13 +101,13 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t wc) } -Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws) +Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* wstr) { - if (ws) + if (wstr) { - for (const wchar_t* p = ws; *p; ++p) + for (const wchar_t* iter = wstr; *iter; ++iter) { - os << *p; + os << *iter; } } @@ -115,4 +115,20 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const wchar_t* ws) } +Foam::Ostream& Foam::operator<<(Ostream& os, const std::wstring& wstr) +{ + for + ( + std::wstring::const_iterator iter = wstr.begin(); + iter != wstr.end(); + ++iter + ) + { + os << *iter; + } + + return os; +} + + // ************************************************************************* // diff --git a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/0/U b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/0/U index b2ed1ea6d74f3d52badf34a348c389941adbacb2..39d9711c4080366f8db54efaeefbe1c0551951d0 100644 --- a/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/0/U +++ b/tutorials/lagrangian/porousExplicitSourceReactingParcelFoam/verticalChannel/0/U @@ -33,13 +33,13 @@ boundaryField { type flowRateInletVelocity; flowRate 0.00379; - value uniform (-0 10.82857143 -0); + value uniform (0 10.82857143 0); } inletSides { type flowRateInletVelocity; flowRate 0.00832; - value uniform (-0 11.88571429 -0); + value uniform (0 11.88571429 0); } outlet { diff --git a/wmake/rules/General/coco b/wmake/rules/General/coco new file mode 100644 index 0000000000000000000000000000000000000000..7f7bd2ff29b58e6d8b869fa567b2aa00cf2b1bd4 --- /dev/null +++ b/wmake/rules/General/coco @@ -0,0 +1,13 @@ +# handie Coco/R attributed grammars + +.SUFFIXES: .atg + +atgtoo = \ + $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/$(WM_ARCH)$(WM_COMPILER)/bin/coco-cpp \ + -single \ + -frames $(WM_THIRD_PARTY_DIR)/coco-cpp/platforms/share/coco-cpp \ + $$SOURCE -o $(OBJECTS_DIR) && \ + $(CC) $(c++FLAGS) -c $*.cpp -o $@ + +.atg.dep: + $(MAKE_DEP) diff --git a/wmake/rules/General/standard b/wmake/rules/General/standard index 809f9353a2d6f179ebc3329b5c8ce67142b01af2..3188ac4413f749392e8e11bd094bd767fc5cf7b7 100644 --- a/wmake/rules/General/standard +++ b/wmake/rules/General/standard @@ -4,6 +4,7 @@ include $(GENERAL_RULES)/sourceToDep include $(GENERAL_RULES)/flex include $(GENERAL_RULES)/flex++ +include $(GENERAL_RULES)/coco ## include $(GENERAL_RULES)/byacc ## include $(GENERAL_RULES)/btyacc++ include $(GENERAL_RULES)/bison diff --git a/wmake/src/Makefile b/wmake/src/Makefile index a74c250f8815ba0020d9cef77f587551c725e2ad..cac2a639a5238b358d2abb78977435f8148ae417 100644 --- a/wmake/src/Makefile +++ b/wmake/src/Makefile @@ -2,7 +2,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. +# \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -60,16 +60,17 @@ include $(RULES)/$(WM_LINK_LANGUAGE) # targets #------------------------------------------------------------------------------ -all: $(BIN)/dirToString $(BIN)/wmkdep +all: $(BIN)/dirToString $(BIN)/wmkdep $(BIN)/wmkdepend clean: - rm -f $(BIN)/dirToString $(BIN)/wmkdep 2>/dev/null + rm -f $(BIN)/dirToString $(BIN)/wmkdep $(BIN)/wmkdepend 2>/dev/null $(BIN)/dirToString: dirToString.c @mkdir -p $(BIN) $(cc) $(cFLAGS) dirToString.c -o $(BIN)/dirToString + $(BIN)/wmkdep: wmkdep.l @mkdir -p $(BIN) flex wmkdep.l @@ -77,4 +78,13 @@ $(BIN)/wmkdep: wmkdep.l @rm -f lex.yy.c 2>/dev/null +# for bootstrapping - use generated files directly (instead of from .atg file) +$(BIN)/wmkdepend: wmkdepend.cpp \ + wmkdependParser.cpp wmkdependScanner.cpp \ + wmkdependParser.h wmkdependScanner.h + @mkdir -p $(BIN) + $(CC) $(c++FLAGS) \ + wmkdepend.cpp wmkdependParser.cpp wmkdependScanner.cpp \ + -o $(BIN)/wmkdepend + #------------------------------------------------------------------------------ diff --git a/wmake/src/wmkdepend.cpp b/wmake/src/wmkdepend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..159fb3849b9046fbf4716922492b084bb736ac27 --- /dev/null +++ b/wmake/src/wmkdepend.cpp @@ -0,0 +1,164 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------ +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Application + wmkdepend + +Description + A fast dependency list generator that emulates the behaviour and + output of cpp -M. However, the output contains no duplications and + is ~40% faster than cpp. + + The algorithm uses flex to scan for includes and searches the files + found. Each file is entered into a hash table so that files are scanned + only once. This is why this program is faster than cpp. + +Usage + wmkdep [ -Idirectory ... -Idirectory ] filename + +\*---------------------------------------------------------------------------*/ + +#include <cstdio> +#include <stdlib.h> +#include <cstring> + +#include "wmkdependParser.h" + +// Note: since we use the Coco/R default error messages, we must use +// wide streams for stderr. + +void printUsage(const char* message = NULL) +{ + if (message) + { + fwprintf(stderr, L"\nError: %s\n\n", message); + } + + fwprintf + ( + stderr, + L"Usage: wmkdepend [ -Idirectory ... -Idirectory ] filename\n" + ); +} + + +int main(int argc, char* argv[]) +{ + if (argc == 1) + { + printUsage("Error: input file not supplied"); + ::exit(1); + } + + for (int i=1; i < argc; i++) + { + if (strncmp(argv[i], "-I", 2) == 0 && strlen(argv[i]) > 2) + { + std::string dirName(argv[i] + 2); + + // add trailing slash if required + if (dirName.rfind('/') != dirName.size()-1) + { + dirName += '/'; + } + + wmake::Parser::includeDirs.push_back(dirName); + } + } + + std::string sourceFile(argv[argc-1]); + + fwprintf + ( + stderr, + L"Making dependency list for source file %s\n", + sourceFile.c_str() + ); + + std::string::size_type basePos = sourceFile.rfind('/'); + if (basePos == std::string::npos) + { + basePos = 0; + } + else + { + basePos++; + } + + std::string::size_type dotPos = sourceFile.rfind('.'); + if + ( + dotPos == std::string::npos + || dotPos == sourceFile.size()-1 + || dotPos <= basePos + ) + { + fwprintf + ( + stderr, + L"Cannot find extension in source file name %s\n", + sourceFile.c_str() + ); + ::exit(1); + } + + std::string depFile = sourceFile.substr(0, dotPos); + depFile += ".dep"; + + const std::string sourceExt = sourceFile.substr(dotPos); + if (sourceExt == ".java") + { + // import directories to ignore + wmake::Parser::ignoreDir("java.*"); + wmake::Parser::ignoreDir("org.*"); + wmake::Parser::ignoreDir("com.*"); + wmake::Parser::ignoreDir("sunw.*"); + wmake::Parser::ignoreDir("sun.*"); + wmake::Parser::ignoreDir("launcher.*"); + + std::cout + << "$(CLASSES_DIR)/" + << sourceFile.substr(basePos, dotPos - basePos) << ".class: " + << depFile << "\n"; + } + else + { + std::cout + << "$(OBJECTS_DIR)/" + << sourceFile.substr(basePos, dotPos - basePos) << ".o: " + << depFile << "\n"; + } + + + wmake::Parser::sourceFile = sourceFile; + wmake::Parser::depFile = depFile; + + wmake::Parser::includeFile(sourceFile); + + return 0; +} + + + +/*****************************************************************************/ diff --git a/wmake/src/wmkdependParser.atg b/wmake/src/wmkdependParser.atg new file mode 100644 index 0000000000000000000000000000000000000000..2da6ebd31333d55539958a446f00affb782332e0 --- /dev/null +++ b/wmake/src/wmkdependParser.atg @@ -0,0 +1,497 @@ +/*---------------------------------------------------------------------------*\ + Attributed Grammar for Coco/R (-*- C++ -*- version) + compile with: + coco-cpp wmkdependParser.atg +\*---------------------------------------------------------------------------*/ +[copy] +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file wmkdependParser.atg + +Description + An attributed Coco/R grammar to parse C/C++, Fortran and Java files + for include and import statements. + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +[/copy] +#include <iostream> +#include <string> +#include <list> + +//! @brief A simple HashTable implementation +/** + * @note This hash table is only vaguely STL-like. In accordance with + * its present purpose, this hash table only supports a constIterator + * and no deletions. For simplicity, the constIterator increment is + * simply via a next() method. Instead of comparing to an end value, + * the constIterator valid() method is used. + * For example, + * @code + * for + * ( + * HashTable<foo>::constIterator iter = myHash.begin(); + * iter.valid(); + * iter.next() + * ) + * { + * std::cerr<< "key: " << iter.key() << "\n"; + * } + * @endcode + * + */ +class StringHashSet +{ + //! An entry within the HashTable + struct hashedEntry + { + const std::string key_; //<! The lookup key + hashedEntry *next_; //<! Pointer to next hashedEntry in sub-list + + hashedEntry(const std::string& key, hashedEntry *next=0) + : + key_(key), next_(next) + {} + }; + + const int size_; //<! fixed HashTable size + hashedEntry** table_; + +public: + + //! Construct with a default size + StringHashSet(int size = 500) + : + size_(size), + table_(new hashedEntry*[size_]) + { + memset(table_, 0, size_ * sizeof(hashedEntry*)); + } + + //! Destructor + ~StringHashSet() + { + for (int hashIdx = 0; hashIdx < size_; ++hashIdx) + { + hashedEntry* ep = table_[hashIdx]; + while (ep) + { + hashedEntry* del = ep; + ep = ep->next_; + delete del; + } + } + delete[] table_; + table_ = 0; + } + + //! Return hash index for lookup name in hash table + bool hashKeyIndex(const std::string& name) const + { + int hashIdx = 0; + + // calculate hash index + for + ( + std::string::const_iterator iter = name.begin(); + iter != name.end(); + ++iter + ) + { + hashIdx = hashIdx << 1 ^ *iter; + } + + if (hashIdx < 0) + { + hashIdx = -hashIdx; + } + + return hashIdx % size_; + } + + + //! Return true if name is found in hash table + bool found(const std::string& name) const + { + const int hashIdx = hashKeyIndex(name); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (name == ep->key_) + { + // found + return true; + } + } + + // entry not found + return false; + } + + + //! Return true if name is found in hash table, insert if not found + bool foundOrInsert(const std::string& name) + { + const int hashIdx = hashKeyIndex(name); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (name == ep->key_) + { + // found - return true + return true; + } + } + + // not found - insert it + table_[hashIdx] = new hashedEntry(name, table_[hashIdx]); + + // entry not found (but was added) - return false + return false; + } + +}; + + +/*---------------------------------------------------------------------------*/ + +COMPILER wmkdepend + // grammar pragmas: + $namespace=wmake + $prefix=wmkdepend + $define=FORCE_UTF8 + +/*---------------------------------------------------------------------------*/ +private: + + //! Hash of files already visited + static StringHashSet visitedFiles_; + + //! Hash of (java) directories already visited + static StringHashSet visitedDirs_; + + //! Replace all '.' with '/' + static void dotToSlash(std::string& name); + + //! Import (java) directories + static void importDir(const std::string& dirName); + + //! Import (java) file + static void importFile(const std::string& name); + +public: + //! Include directories to search + static std::list<std::string> includeDirs; + + //! The name of the top-level source file + static std::string sourceFile; + + //! The name of the top-level dep file + static std::string depFile; + + //! Add directory to list of visited dirs, thus effectively ignoring it + static void ignoreDir(const std::string& name); + + //! Include file + static void includeFile(const std::string& name); + +/*---------------------------------------------------------------------------*/ +[code] +#include <sys/types.h> +#include <dirent.h> + +StringHashSet Parser::visitedFiles_; +StringHashSet Parser::visitedDirs_; + +std::list<std::string> Parser::includeDirs; +std::string Parser::sourceFile; +std::string Parser::depFile; + + +void Parser::dotToSlash(std::string& name) +{ + std::string::size_type start = 0; + + while ((start = name.find('.', start)) != std::string::npos) + { + name.replace(start, 1, 1, '/'); + start++; + } +} + + +void Parser::ignoreDir(const std::string& name) +{ + visitedDirs_.foundOrInsert(name); +} + + +void Parser::includeFile(const std::string& name) +{ + if (visitedFiles_.foundOrInsert(name)) + { + return; + } + + // use stdio and buffering within Coco/R -- (faster) + FILE *fh = fopen(name.c_str(), "r"); + if (fh) + { + std::cout << depFile << ": " << name << "\n"; + } + else + { + for + ( + std::list<std::string>::const_iterator iter = includeDirs.begin(); + iter != includeDirs.end(); + ++iter + ) + { + const std::string pathName = *iter + name; + + fh = fopen(pathName.c_str(), "r"); + if (fh) + { + std::cout << depFile << ": " << pathName << "\n"; + break; + } + } + } + + if (fh) + { + Scanner scanner(fh); + Parser parser(&scanner); + + parser.Parse(); + fclose(fh); + } + else + { + fwprintf + ( + stderr, + L"could not open file %s for source file %s\n", + name.c_str(), sourceFile.c_str() + ); + } +} + + +void Parser::importFile(const std::string& name) +{ + // check if a globbed form was already visited + std::string::size_type dotPos = name.find('.'); + if (dotPos != std::string::npos) + { + std::string dirGlob = name.substr(0, dotPos); + dirGlob += ".*"; + + if (visitedDirs_.found(dirGlob)) + { + return; + } + } + + std::string javaFileName = name; + + dotToSlash(javaFileName); + javaFileName += ".java"; + + includeFile(javaFileName); +} + + +void Parser::importDir(const std::string& name) +{ + if (visitedDirs_.foundOrInsert(name)) + { + return; + } + + std::string dirName = name; + dotToSlash(dirName); + + DIR *source = opendir(dirName.c_str()); + + if (source) + { + struct dirent *list; + + // Read and parse all the entries in the directory + while ((list = readdir(source)) != NULL) + { + const char* ext = strstr(list->d_name, ".java"); + + // avoid matching on something like '.java~' + if (ext && strlen(ext) == 5) + { + std::string pathName = dirName + list->d_name; + includeFile(pathName); + } + } + + closedir(source); + } + else + { + fwprintf + ( + stderr, + L"could not open directory %s\n", + dirName.c_str() + ); + return; + } +} + +[/code] + + +/*---------------------------------------------------------------------------*/ + +CHARACTERS + letter = 'A'..'Z' + 'a'..'z' + '_'. + digit = "0123456789". + cr = '\r'. + lf = '\n'. + tab = '\t'. + stringCh = ANY - '"' - '\\' - cr - lf. + printable = '\u0020' .. '\u007e'. + java_letter = letter + '$'. + +// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * // + +TOKENS + +// string +string = + '"' { stringCh | '\\' printable } '"'. + +// single-quoted string (eg, Fortran) +sqstring = + '\'' { stringCh | '\\' printable } '\''. + +// for java import +package_name = + java_letter { java_letter | digit } + { '.' java_letter { java_letter | digit } } . + +// for java import +package_dir = + java_letter { java_letter | digit } + { '.' java_letter { java_letter | digit } } ".*" . + + +// * * * * * * * * * * * PRAGMAS / COMMENTS / IGNORE * * * * * * * * * * * // + +COMMENTS FROM "/*" TO "*/" NESTED +COMMENTS FROM "//" TO lf + +IGNORE tab + +// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * // + +PRODUCTIONS + +wmkdepend += +{ + // C/C++-style includes + '#' + [ + "include" + [ + string (. + if (isUTF8()) + { + includeFile(t->toStringUTF8(1, t->length()-2)); + } + else + { + includeFile(t->toString(1, t->length()-2)); + } + .) + ] + ] + [ ANY { ANY } ] '\n' // skip trailing junk + + // Fortran-style includes + | "include" + [ + sqstring (. + if (isUTF8()) + { + includeFile(t->toStringUTF8(1, t->length()-2)); + } + else + { + includeFile(t->toString(1, t->length()-2)); + } + .) + ] + [ ANY { ANY } ] '\n' // skip trailing junk + + // Java imports + | "import" + ( + package_dir (. + if (isUTF8()) + { + importDir(t->toStringUTF8()); + } + else + { + importDir(t->toString()); + } + .) + | package_name (. + if (isUTF8()) + { + importFile(t->toStringUTF8()); + } + else + { + importFile(t->toString()); + } + .) + ) + ';' + [ ANY { ANY } ] '\n' // skip trailing junk + + | [ ANY { ANY } ] '\n' // skip any other lines + +} +. + + +/*---------------------------------------------------------------------------*/ + +END wmkdepend. + +// ************************************************************************* // diff --git a/wmake/src/wmkdependParser.cpp b/wmake/src/wmkdependParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6d5e4e71a11114a14ee50bcc579ea249a807684 --- /dev/null +++ b/wmake/src/wmkdependParser.cpp @@ -0,0 +1,575 @@ +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file wmkdependParser.atg + +Description + An attributed Coco/R grammar to parse C/C++, Fortran and Java files + for include and import statements. + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +// This file was generated with Coco/R C++ (7 Feb 2010) +// http://www.ssw.uni-linz.ac.at/coco/ +// with these defines: +// - FORCE_UTF8 + + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cwchar> +#include <sstream> + +#include "wmkdependParser.h" + +namespace wmake { + + +#include <sys/types.h> +#include <dirent.h> + +StringHashSet Parser::visitedFiles_; +StringHashSet Parser::visitedDirs_; + +std::list<std::string> Parser::includeDirs; +std::string Parser::sourceFile; +std::string Parser::depFile; + + +void Parser::dotToSlash(std::string& name) +{ + std::string::size_type start = 0; + + while ((start = name.find('.', start)) != std::string::npos) + { + name.replace(start, 1, 1, '/'); + start++; + } +} + + +void Parser::ignoreDir(const std::string& name) +{ + visitedDirs_.foundOrInsert(name); +} + + +void Parser::includeFile(const std::string& name) +{ + if (visitedFiles_.foundOrInsert(name)) + { + return; + } + + // use stdio and buffering within Coco/R -- (faster) + FILE *fh = fopen(name.c_str(), "r"); + if (fh) + { + std::cout << depFile << ": " << name << "\n"; + } + else + { + for + ( + std::list<std::string>::const_iterator iter = includeDirs.begin(); + iter != includeDirs.end(); + ++iter + ) + { + const std::string pathName = *iter + name; + + fh = fopen(pathName.c_str(), "r"); + if (fh) + { + std::cout << depFile << ": " << pathName << "\n"; + break; + } + } + } + + if (fh) + { + Scanner scanner(fh); + Parser parser(&scanner); + + parser.Parse(); + fclose(fh); + } + else + { + fwprintf + ( + stderr, + L"could not open file %s for source file %s\n", + name.c_str(), sourceFile.c_str() + ); + } +} + + +void Parser::importFile(const std::string& name) +{ + // check if a globbed form was already visited + std::string::size_type dotPos = name.find('.'); + if (dotPos != std::string::npos) + { + std::string dirGlob = name.substr(0, dotPos); + dirGlob += ".*"; + + if (visitedDirs_.found(dirGlob)) + { + return; + } + } + + std::string javaFileName = name; + + dotToSlash(javaFileName); + javaFileName += ".java"; + + includeFile(javaFileName); +} + + +void Parser::importDir(const std::string& name) +{ + if (visitedDirs_.foundOrInsert(name)) + { + return; + } + + std::string dirName = name; + dotToSlash(dirName); + + DIR *source = opendir(dirName.c_str()); + + if (source) + { + struct dirent *list; + + // Read and parse all the entries in the directory + while ((list = readdir(source)) != NULL) + { + const char* ext = strstr(list->d_name, ".java"); + + // avoid matching on something like '.java~' + if (ext && strlen(ext) == 5) + { + std::string pathName = dirName + list->d_name; + includeFile(pathName); + } + } + + closedir(source); + } + else + { + fwprintf + ( + stderr, + L"could not open directory %s\n", + dirName.c_str() + ); + return; + } +} + + + + +//! @cond fileScope +// + +// +// Create by copying str - only used locally +inline static wchar_t* coco_string_create(const wchar_t* str) +{ + const int len = wcslen(str); + wchar_t* dst = new wchar_t[len + 1]; + wcsncpy(dst, str, len); + dst[len] = 0; + return dst; +} + + +// Free storage and nullify the argument +inline static void coco_string_delete(wchar_t* &str) +{ + delete[] str; + str = NULL; +} +// +//! @endcond fileScope + + +// ---------------------------------------------------------------------------- +// Parser Implementation +// ---------------------------------------------------------------------------- + +void Parser::SynErr(int n) +{ + if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n); + errDist = 0; +} + + +void Parser::SemErr(const std::wstring& msg) +{ + if (errDist >= minErrDist) errors->Error(t->line, t->col, msg); + errDist = 0; +} + + +bool Parser::isUTF8() const +{ + return scanner && scanner->buffer && scanner->buffer->isUTF8(); +} + + +void Parser::Get() +{ + for (;;) + { + t = la; + la = scanner->Scan(); + if (la->kind <= maxT) + { + ++errDist; + break; + } + if (dummyToken != t) + { + dummyToken->kind = t->kind; + dummyToken->pos = t->pos; + dummyToken->col = t->col; + dummyToken->line = t->line; + dummyToken->next = NULL; + coco_string_delete(dummyToken->val); + dummyToken->val = coco_string_create(t->val); + t = dummyToken; + } + la = t; + } +} + + +void Parser::Expect(int n) +{ + if (la->kind == n) + { + Get(); + } + else + { + SynErr(n); + } +} + + +void Parser::ExpectWeak(int n, int follow) +{ + if (la->kind == n) + { + Get(); + } + else + { + SynErr(n); + while (!StartOf(follow)) + { + Get(); + } + } +} + + +bool Parser::WeakSeparator(int n, int syFol, int repFol) +{ + if (la->kind == n) + { + Get(); + return true; + } + else if (StartOf(repFol)) + { + return false; + } + else + { + SynErr(n); + while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) + { + Get(); + } + return StartOf(syFol); + } +} + + +void Parser::wmkdepend() +{ + while (StartOf(1)) { + if (la->kind == 5) { + Get(); + if (la->kind == 6) { + Get(); + if (la->kind == 1) { + Get(); + if (isUTF8()) + { + includeFile(t->toStringUTF8(1, t->length()-2)); + } + else + { + includeFile(t->toString(1, t->length()-2)); + } + + } + } + if (StartOf(2)) { + Get(); + while (StartOf(3)) { + Get(); + } + } + Expect(7); + } else if (la->kind == 6) { + Get(); + if (la->kind == 2) { + Get(); + if (isUTF8()) + { + includeFile(t->toStringUTF8(1, t->length()-2)); + } + else + { + includeFile(t->toString(1, t->length()-2)); + } + + } + if (StartOf(4)) { + Get(); + while (StartOf(3)) { + Get(); + } + } + Expect(7); + } else if (la->kind == 8) { + Get(); + if (la->kind == 4) { + Get(); + if (isUTF8()) + { + importDir(t->toStringUTF8()); + } + else + { + importDir(t->toString()); + } + + } else if (la->kind == 3) { + Get(); + if (isUTF8()) + { + importFile(t->toStringUTF8()); + } + else + { + importFile(t->toString()); + } + + } else SynErr(11); + Expect(9); + if (StartOf(3)) { + Get(); + while (StartOf(3)) { + Get(); + } + } + Expect(7); + } else { + if (StartOf(5)) { + Get(); + while (StartOf(3)) { + Get(); + } + } + Expect(7); + } + } +} + + + +void Parser::Parse() +{ + t = NULL; + // might call Parse() twice + if (dummyToken) { + coco_string_delete(dummyToken->val); + delete dummyToken; + } + dummyToken = new Token(coco_string_create(L"Dummy Token")); + la = dummyToken; + Get(); + wmkdepend(); + Expect(0); // expect end-of-file automatically added +} + + +Parser::Parser(Scanner* scan, Errors* err) +: + dummyToken(NULL), + deleteErrorsDestruct_(!err), + errDist(minErrDist), + scanner(scan), + errors(err), + t(NULL), + la(NULL) +{ + if (!errors) // add in default error handling + { + errors = new Errors(); + } + // user-defined initializations: +} + + +bool Parser::StartOf(int s) +{ + const bool T = true; + const bool x = false; + + static const bool set[6][12] = + { + {T,x,x,x, x,x,x,x, x,x,x,x}, + {x,T,T,T, T,T,T,T, T,T,T,x}, + {x,x,T,T, T,T,x,x, T,T,T,x}, + {x,T,T,T, T,T,T,x, T,T,T,x}, + {x,T,x,T, T,T,T,x, T,T,T,x}, + {x,T,T,T, T,x,x,x, x,T,T,x} + }; + + return set[s][la->kind]; +} + + +Parser::~Parser() +{ + if (deleteErrorsDestruct_) { delete errors; } // delete default error handling + if (dummyToken) { + coco_string_delete(dummyToken->val); + delete dummyToken; + } + // user-defined destruction: +} + + +// ---------------------------------------------------------------------------- +// Errors Implementation +// ---------------------------------------------------------------------------- + +Errors::Errors() +: + count(0) +{} + + +Errors::~Errors() +{} + + +void Errors::clear() +{ + count = 0; +} + + +std::wstring Errors::strerror(int n) +{ + switch (n) { + case 0: return L"EOF expected"; break; + case 1: return L"string expected"; break; + case 2: return L"sqstring expected"; break; + case 3: return L"package_name expected"; break; + case 4: return L"package_dir expected"; break; + case 5: return L"\"#\" expected"; break; + case 6: return L"\"include\" expected"; break; + case 7: return L"\"\\n\" expected"; break; + case 8: return L"\"import\" expected"; break; + case 9: return L"\";\" expected"; break; + case 10: return L"??? expected"; break; + case 11: return L"invalid wmkdepend"; break; + default: + { + // std::wostringstream buf; (this typedef might be missing) + std::basic_ostringstream<wchar_t> buf; + buf << "error " << n; + return buf.str(); + } + break; + } +} + + +void Errors::Warning(const std::wstring& msg) +{ + fwprintf(stderr, L"%ls\n", msg.c_str()); +} + + +void Errors::Warning(int line, int col, const std::wstring& msg) +{ + fwprintf(stderr, L"-- line %d col %d: %ls\n", line, col, msg.c_str()); +} + + +void Errors::Error(int line, int col, const std::wstring& msg) +{ + fwprintf(stderr, L"-- line %d col %d: %ls\n", line, col, msg.c_str()); + count++; +} + + +void Errors::SynErr(int line, int col, int n) +{ + this->Error(line, col, this->strerror(n)); +} + + +void Errors::Exception(const std::wstring& msg) +{ + fwprintf(stderr, L"%ls", msg.c_str()); + ::exit(1); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace + +// ************************************************************************* // diff --git a/wmake/src/wmkdependParser.h b/wmake/src/wmkdependParser.h new file mode 100644 index 0000000000000000000000000000000000000000..8c7703adbd6a2eece7c06394cdff879d21e89cb1 --- /dev/null +++ b/wmake/src/wmkdependParser.h @@ -0,0 +1,310 @@ +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file wmkdependParser.atg + +Description + An attributed Coco/R grammar to parse C/C++, Fortran and Java files + for include and import statements. + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +// This file was generated with Coco/R C++ (7 Feb 2010) +// http://www.ssw.uni-linz.ac.at/coco/ +// with these defines: +// - FORCE_UTF8 + + +#ifndef COCO_wmkdependPARSER_H__ +#define COCO_wmkdependPARSER_H__ + +#include <iostream> +#include <string> +#include <list> + +//! @brief A simple HashTable implementation +/** + * @note This hash table is only vaguely STL-like. In accordance with + * its present purpose, this hash table only supports a constIterator + * and no deletions. For simplicity, the constIterator increment is + * simply via a next() method. Instead of comparing to an end value, + * the constIterator valid() method is used. + * For example, + * @code + * for + * ( + * HashTable<foo>::constIterator iter = myHash.begin(); + * iter.valid(); + * iter.next() + * ) + * { + * std::cerr<< "key: " << iter.key() << "\n"; + * } + * @endcode + * + */ +class StringHashSet +{ + //! An entry within the HashTable + struct hashedEntry + { + const std::string key_; //<! The lookup key + hashedEntry *next_; //<! Pointer to next hashedEntry in sub-list + + hashedEntry(const std::string& key, hashedEntry *next=0) + : + key_(key), next_(next) + {} + }; + + const int size_; //<! fixed HashTable size + hashedEntry** table_; + +public: + + //! Construct with a default size + StringHashSet(int size = 500) + : + size_(size), + table_(new hashedEntry*[size_]) + { + memset(table_, 0, size_ * sizeof(hashedEntry*)); + } + + //! Destructor + ~StringHashSet() + { + for (int hashIdx = 0; hashIdx < size_; ++hashIdx) + { + hashedEntry* ep = table_[hashIdx]; + while (ep) + { + hashedEntry* del = ep; + ep = ep->next_; + delete del; + } + } + delete[] table_; + table_ = 0; + } + + //! Return hash index for lookup name in hash table + bool hashKeyIndex(const std::string& name) const + { + int hashIdx = 0; + + // calculate hash index + for + ( + std::string::const_iterator iter = name.begin(); + iter != name.end(); + ++iter + ) + { + hashIdx = hashIdx << 1 ^ *iter; + } + + if (hashIdx < 0) + { + hashIdx = -hashIdx; + } + + return hashIdx % size_; + } + + + //! Return true if name is found in hash table + bool found(const std::string& name) const + { + const int hashIdx = hashKeyIndex(name); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (name == ep->key_) + { + // found + return true; + } + } + + // entry not found + return false; + } + + + //! Return true if name is found in hash table, insert if not found + bool foundOrInsert(const std::string& name) + { + const int hashIdx = hashKeyIndex(name); + + for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_) + { + if (name == ep->key_) + { + // found - return true + return true; + } + } + + // not found - insert it + table_[hashIdx] = new hashedEntry(name, table_[hashIdx]); + + // entry not found (but was added) - return false + return false; + } + +}; + + +/*---------------------------------------------------------------------------*/ + + + +#include "wmkdependScanner.h" + +namespace wmake { + + +/*---------------------------------------------------------------------------*\ + Class Errors Declaration +\*---------------------------------------------------------------------------*/ +//! Parser error handing +class Errors +{ +public: + int count; //!< The number of errors detected + + //! Return a string describing the given error code. + static std::wstring strerror(int n); + + Errors(); //!< Construct null - start with no errors + virtual ~Errors(); //!< Destructor + virtual void clear(); //!< Clear the error count + + //! Handle a general warning 'msg' + virtual void Warning(const std::wstring& msg); + //! Handle a general warning 'msg' + virtual void Warning(int line, int col, const std::wstring& msg); + //! Handle general error 'msg' (eg, a semantic error) + virtual void Error(int line, int col, const std::wstring& msg); + //! Handle syntax error 'n', uses strerror for the message, calls Error() + virtual void SynErr(int line, int col, int n); + //! Handle a general exception 'msg' + virtual void Exception(const std::wstring& msg); + +}; // Errors + + + +/*---------------------------------------------------------------------------*\ + Class Parser Declaration +\*---------------------------------------------------------------------------*/ +//! A Coco/R Parser +class Parser +{ + enum { + _EOF=0, + _string=1, + _sqstring=2, + _package_name=3, + _package_dir=4, + maxT = 10 //<! max term (w/o pragmas) + }; + static const int minErrDist = 2; //!< min. distance before reporting errors + + Token *dummyToken; + bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor + int errDist; + + void SynErr(int n); //!< Handle syntax error 'n' + void Get(); + void Expect(int n); + bool StartOf(int s); + void ExpectWeak(int n, int follow); + bool WeakSeparator(int n, int syFol, int repFol); + +public: + Scanner *scanner; + Errors *errors; + + Token *t; //!< last recognized token + Token *la; //!< lookahead token + +private: + + //! Hash of files already visited + static StringHashSet visitedFiles_; + + //! Hash of (java) directories already visited + static StringHashSet visitedDirs_; + + //! Replace all '.' with '/' + static void dotToSlash(std::string& name); + + //! Import (java) directories + static void importDir(const std::string& dirName); + + //! Import (java) file + static void importFile(const std::string& name); + +public: + //! Include directories to search + static std::list<std::string> includeDirs; + + //! The name of the top-level source file + static std::string sourceFile; + + //! The name of the top-level dep file + static std::string depFile; + + //! Add directory to list of visited dirs, thus effectively ignoring it + static void ignoreDir(const std::string& name); + + //! Include file + static void includeFile(const std::string& name); + +/*---------------------------------------------------------------------------*/ + + //! Construct for the specified scanner + /*! + * Use the default error handling, or optionally provide an error + * handler, which will not be deleted upon destruction. + */ + Parser(Scanner* scan, Errors* err = 0); + ~Parser(); + void Parse(); //!< Execute the parse operation + void SemErr(const std::wstring& msg); //!< Handle semantic error + bool isUTF8() const; //!< Return true if scanner buffer is UTF8 + + void wmkdepend(); + +}; // end Parser + +} // End namespace + +#endif // COCO_wmkdependPARSER_H__ + +// ************************************************************************* // diff --git a/wmake/src/wmkdependScanner.cpp b/wmake/src/wmkdependScanner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72f082f7886bbb2c3a256240763222f4700ecfaf --- /dev/null +++ b/wmake/src/wmkdependScanner.cpp @@ -0,0 +1,1022 @@ +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file wmkdependParser.atg + +Description + An attributed Coco/R grammar to parse C/C++, Fortran and Java files + for include and import statements. + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +// This file was generated with Coco/R C++ (7 Feb 2010) +// http://www.ssw.uni-linz.ac.at/coco/ +// with these defines: +// - FORCE_UTF8 + + +#include <sstream> + +// io.h and fcntl are used to ensure binary read from streams on windows +#ifdef _WIN32 +# include <io.h> +# include <fcntl.h> +#endif + +#include <climits> + +#include "wmkdependScanner.h" + +// values for the file stream buffering +#define MIN_BUFFER_LENGTH 1024 // 1KB +#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH) // 64KB +// value for the heap management +#define HEAP_BLOCK_SIZE (64*1024) // 64KB + + +namespace wmake { + +// * * * * * * * * * * * Miscellaneous String Routines * * * * * * * * * * * // + +// +// string handling, byte character +// + +std::string coco_stdString(const wchar_t* str) +{ + return str ? coco_stdString(str, 0, wcslen(str)) : std::string(); +} + + +std::string coco_stdString(const wchar_t* str, unsigned length) +{ + return coco_stdString(str, 0, length); +} + + +std::string coco_stdString(const wchar_t* str, unsigned index, unsigned length) +{ + const unsigned len = (str && *str) ? length : 0; + std::string dst; + dst.reserve(len); + + for (unsigned i = 0; i < len; ++i) + { + dst += char(str[index+i] & 0xFF); + } + + return dst; +} + + +std::string coco_stdStringUTF8(const wchar_t* str) +{ + return str ? coco_stdStringUTF8(str, 0, wcslen(str)) : std::string(); +} + + +std::string coco_stdStringUTF8(const wchar_t* str, unsigned length) +{ + return coco_stdStringUTF8(str, 0, length); +} + + +std::string coco_stdStringUTF8(const wchar_t* str, unsigned index, unsigned length) +{ + const unsigned len = (str && *str) ? length : 0; + std::string dst; + dst.reserve(len); + + for (unsigned i = 0; i < len; ++i) + { + wchar_t wc = str[index+i]; + + if (!(wc & ~0x0000007F)) + { + // 0x00000000 - 0x0000007F [min. 8bit storage, 1-byte encoding) + // 0aaaaaaa + dst += char(wc); + } + else if (!(wc & ~0x000007FF)) + { + // 0x00000080 - 0x000007FF [min. 16bit storage, 2-byte encoding] + // 110bbbaa 10aaaaaa + dst += char(0xC0 | ((wc >> 6) & 0x1F)); + dst += char(0x80 | ((wc) & 0x3F)); + } + else if (!(wc & ~0x0000FFFF)) + { + // 0x00000800 - 0x0000FFFF [min. 16bit storage, 3-byte encoding] + // 1110bbbb 10bbbbaa 10aaaaaa + dst += char(0xE0 | ((wc >> 12) & 0x0F)); + dst += char(0x80 | ((wc >> 6) & 0x3F)); + dst += char(0x80 | ((wc) & 0x3F)); + } + else if (!(wc & ~0x001FFFFF)) + { + // 0x00010000 - 0x001FFFFF [min. 24bit storage, 4-byte encoding] + // 11110ccc 10ccbbbb 10bbbbaa 10aaaaaa + dst += char(0xF0 | ((wc >> 18) & 0x07)); + dst += char(0x80 | ((wc >> 12) & 0x3F)); + dst += char(0x80 | ((wc >> 6) & 0x3F)); + dst += char(0x80 | ((wc) & 0x3F)); + } +// +// Not (yet) used - wchar_t storage is limited to 16bit on windows +// This also corresponds to the unicode BMP (Basic Multilingual Plane) +// +// else if (!(wc & ~0x03FFFFFF)) +// { +// // 0x00200000 - 0x03FFFFFF [min. 32bit storage, 5-byte encoding] +// // 111110dd 10cccccc 10ccbbbb 10bbbbaa 10aaaaaa +// dst += char(0xF8 | ((wc >> 24) & 0x03)); +// dst += char(0x80 | ((wc >> 18) & 0x3F)); +// dst += char(0x80 | ((wc >> 12) & 0x3F)); +// dst += char(0x80 | ((wc >> 6) & 0x3F)); +// dst += char(0x80 | ((wc) & 0x3F)); +// } +// else if (!(wc & ~0x7FFFFFFF)) +// { +// // 0x04000000 - 0x7FFFFFFF [min. 32bit storage, 6-byte encoding] +// // 1111110d 10dddddd 10cccccc 10ccbbbb 10bbbbaa 10aaaaaa +// dst += char(0xFC | ((wc >> 30) & 0x01)); +// dst += char(0x80 | ((wc >> 24) & 0x3F)); +// dst += char(0x80 | ((wc >> 18) & 0x3F)); +// dst += char(0x80 | ((wc >> 12) & 0x3F)); +// dst += char(0x80 | ((wc >> 6) & 0x3F)); +// dst += char(0x80 | ((wc) & 0x3F)); +// } +// + else + { + // report anything unknown/invalid as replacement character U+FFFD + dst += char(0xEF); + dst += char(0xBF); + dst += char(0xBD); + } + } + + return dst; +} + + +// * * * * * * * * * * * * End of String Routines * * * * * * * * * * * * * // + + +Token::Token(wchar_t* value) +: + kind(0), + pos(0), + col(0), + line(0), + val(value), + next(NULL) +{} + + +Token::~Token() +{} + + +int Token::length() const +{ + return val ? wcslen(val) : 0; +} + + +// ---------------------------------------------------------------------------- +// Buffer Implementation +// ---------------------------------------------------------------------------- + +Buffer::Buffer(Buffer* b) +: + buf(b->buf), + bufCapacity(b->bufCapacity), + bufLen(b->bufLen), + bufPos(b->bufPos), + bufStart(b->bufStart), + fileLen(b->fileLen), + cStream(b->cStream), + stdStream(b->stdStream), + isUserStream_(b->isUserStream_) +{ + // avoid accidental deletion on any of these members + b->buf = NULL; + b->cStream = NULL; + b->stdStream = NULL; +} + + +Buffer::Buffer(const char* chars, int len) +: + buf(new unsigned char[len]), + bufCapacity(len), + bufLen(len), + bufPos(0), + bufStart(0), + fileLen(len), + cStream(NULL), + stdStream(NULL), + isUserStream_(false) +{ + memcpy(this->buf, chars, len*sizeof(char)); +} + + +Buffer::Buffer(const unsigned char* chars, int len) +: + buf(new unsigned char[len]), + bufCapacity(len), + bufLen(len), + bufPos(0), + bufStart(0), + fileLen(len), + cStream(NULL), + stdStream(NULL), + isUserStream_(false) +{ + memcpy(this->buf, chars, len*sizeof(char)); +} + + +Buffer::Buffer(FILE* ifh, bool isUserStream) +: + buf(NULL), + bufCapacity(0), + bufLen(0), + bufPos(0), + bufStart(0), + fileLen(0), + cStream(ifh), + stdStream(NULL), + isUserStream_(isUserStream) +{ +// ensure binary read on windows +#ifdef _WIN32 + _setmode(_fileno(cStream), _O_BINARY); +#endif + + if (CanSeek()) + { + fseek(cStream, 0, SEEK_END); + fileLen = ftell(cStream); + fseek(cStream, 0, SEEK_SET); + bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH; + bufStart = INT_MAX; // nothing in the buffer so far + } + + bufCapacity = (bufLen > 0) ? bufLen : MIN_BUFFER_LENGTH; + buf = new unsigned char[bufCapacity]; + if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start) + else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid + if (bufLen == fileLen && CanSeek()) Close(); +} + + +Buffer::Buffer(std::istream* istr, bool isUserStream) +: + buf(NULL), + bufCapacity(0), + bufLen(0), + bufPos(0), + bufStart(0), + fileLen(0), + cStream(NULL), + stdStream(istr), + isUserStream_(isUserStream) +{ +#if _WIN32 + // TODO: ensure binary read on windows? +#endif +} + + +Buffer::~Buffer() +{ + Close(); + if (buf) + { + delete[] buf; + buf = NULL; + } +} + + +void Buffer::Close() +{ + if (!isUserStream_) + { + if (cStream) + { + fclose(cStream); + cStream = NULL; + } + if (stdStream) + { + delete stdStream; + stdStream = 0; + } + } +} + + +int Buffer::Read() +{ + if (stdStream) + { + int ch = stdStream->get(); + if (stdStream->eof()) + { + return EoF; + } + return ch; + } + + if (bufPos < bufLen) { + return buf[bufPos++]; + } + else if (GetPos() < fileLen) { + SetPos(GetPos()); // shift buffer start to Pos + return buf[bufPos++]; + } + else if (cStream && !CanSeek() && (ReadNextStreamChunk() > 0)) { + return buf[bufPos++]; + } + + return EoF; +} + +bool Buffer::isUTF8() const +{ + return false; +} + +int UTF8Buffer::Read() +{ + int ch; + do { + ch = Buffer::Read(); + // until we find a utf8 start (0xxxxxxx or 11xxxxxx) + } while (ch != EoF && ch >= 128 && ((ch & 0xC0) != 0xC0)); + if (ch < 128 || ch == EoF) { + // nothing to do, first 127 chars are identical in ASCII and UTF8 + // 0xxxxxxx or end of file character + } + else if ((ch & 0xF0) == 0xF0) { + // 0x00010000 - 0x001FFFFF [min. 24bit storage, 4-byte encoding] + // 11110ccc 10ccbbbb 10bbbbaa 10aaaaaa + // CAUTION: this should probably be disallowed since it overflows + // wchar_t on windows and overflows the max (0xFFFF) used here + int c1 = ch & 0x07; ch = Buffer::Read(); + int c2 = ch & 0x3F; ch = Buffer::Read(); + int c3 = ch & 0x3F; ch = Buffer::Read(); + int c4 = ch & 0x3F; + ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4; + } + else if ((ch & 0xE0) == 0xE0) { + // 0x00000800 - 0x0000FFFF [min. 16bit storage, 3-byte encoding] + // 1110bbbb 10bbbbaa 10aaaaaa + int c1 = ch & 0x0F; ch = Buffer::Read(); + int c2 = ch & 0x3F; ch = Buffer::Read(); + int c3 = ch & 0x3F; + ch = (((c1 << 6) | c2) << 6) | c3; + } + else if ((ch & 0xC0) == 0xC0) { + // 0x00000080 - 0x000007FF [min. 16bit storage, 2-byte encoding] + // 110bbbaa 10aaaaaa + int c1 = ch & 0x1F; ch = Buffer::Read(); + int c2 = ch & 0x3F; + ch = (c1 << 6) | c2; + } + return ch; +} + + +bool UTF8Buffer::isUTF8() const +{ + return true; +} + + +int Buffer::Peek() +{ + int curPos = GetPos(); + int ch = Read(); + SetPos(curPos); + return ch; +} + + +int Buffer::GetPos() const +{ + if (stdStream) + { + return stdStream->tellg(); + } + + return bufPos + bufStart; +} + + +void Buffer::SetPos(int value) +{ + if (stdStream) + { + stdStream->seekg(value, std::ios::beg); + return; + } + + if ((value >= fileLen) && cStream && !CanSeek()) + { + // Wanted position is after buffer and the stream + // is not seek-able e.g. network or console, + // thus we have to read the stream manually till + // the wanted position is in sight. + while ((value >= fileLen) && (ReadNextStreamChunk() > 0)) + {} + } + + if ((value < 0) || (value > fileLen)) + { + fwprintf(stderr, L"--- buffer out of bounds access, position: %d\n", value); + ::exit(1); + } + + if ((value >= bufStart) && (value < (bufStart + bufLen))) // already in buffer + { + bufPos = value - bufStart; + } + else if (cStream) // must be swapped in + { + fseek(cStream, value, SEEK_SET); + bufLen = fread(buf, sizeof(char), bufCapacity, cStream); + bufStart = value; bufPos = 0; + } + else + { + bufPos = fileLen - bufStart; // make Pos return fileLen + } +} + + +// +// Read the next chunk of bytes from the stream, increases the buffer +// if needed and updates the fields fileLen and bufLen. +// Returns the number of bytes read. +// +int Buffer::ReadNextStreamChunk() +{ + int freeLen = bufCapacity - bufLen; + if (freeLen == 0) + { + // in the case of a growing input stream + // we can neither seek in the stream, nor can we + // foresee the maximum length, thus we must adapt + // the buffer size on demand. + bufCapacity = bufLen * 2; + unsigned char *newBuf = new unsigned char[bufCapacity]; + memcpy(newBuf, buf, bufLen*sizeof(char)); + delete[] buf; + buf = newBuf; + freeLen = bufLen; + } + int read = fread(buf + bufLen, sizeof(char), freeLen, cStream); + if (read > 0) + { + fileLen = bufLen = (bufLen + read); + return read; + } + // end of stream reached + return 0; +} + + +bool Buffer::CanSeek() const +{ + return cStream && (ftell(cStream) != -1); +} + +// ---------------------------------------------------------------------------- +// Scanner Implementation +// ---------------------------------------------------------------------------- + +Scanner::Scanner(const char* buf, int len) +: + buffer(new Buffer(buf, len)) +{ + Init(); +} + + +Scanner::Scanner(const unsigned char* buf, int len) +: + buffer(new Buffer(buf, len)) +{ + Init(); +} + + +Scanner::Scanner(FILE* ifh) +: + buffer(new Buffer(ifh, true)) +{ + Init(); +} + + +#ifdef _WIN32 +Scanner::Scanner(const std::wstring& fileName) +{ + FILE* ifh; + + if ((ifh = _wfopen(fileName.c_str(), L"rb")) == NULL) + { + fwprintf(stderr, L"--- Cannot open file %ls\n", fileName.c_str()); + ::exit(1); + } + buffer = new Buffer(ifh, false); + Init(); +} +#endif + + +Scanner::Scanner(const std::string& fileName) +{ + FILE* ifh; + if ((ifh = fopen(fileName.c_str(), "rb")) == NULL) + { + fwprintf(stderr, L"--- Cannot open file %s\n", fileName.c_str()); + ::exit(1); + } + buffer = new Buffer(ifh, false); + Init(); +} + + +Scanner::Scanner(std::istream& istr) +: + buffer(new Buffer(&istr, true)) +{ + Init(); +} + + +Scanner::~Scanner() +{ + char* cur = reinterpret_cast<char*>(firstHeap); + +#ifdef COCO_DEBUG_HEAP + fwprintf(stderr, L"~Scanner:\n"); +#endif + + while (cur) + { + cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE)); + free(firstHeap); +#ifdef COCO_DEBUG_HEAP + fwprintf + ( + stderr, L" free %p -> %p\n", + firstHeap, + reinterpret_cast<char*>(firstHeap) + HEAP_BLOCK_SIZE + ); +#endif + firstHeap = cur; + } + delete[] tval; + delete buffer; +} + + +void Scanner::Init() +{ + for (int i = 36; i <= 36; ++i) start.set(i, 7); + for (int i = 65; i <= 90; ++i) start.set(i, 7); + for (int i = 95; i <= 95; ++i) start.set(i, 7); + for (int i = 97; i <= 122; ++i) start.set(i, 7); + start.set(34, 1); + start.set(39, 4); + start.set(35, 11); + start.set(10, 12); + start.set(59, 13); + start.set(Buffer::EoF, -1); + + keywords.set(L"include", 6); + keywords.set(L"import", 8); + + tvalLength = 128; + tval = new wchar_t[tvalLength]; // text of current token + tlen = 0; + tval[tlen] = 0; + + // HEAP_BLOCK_SIZE byte heap + pointer to next heap block + heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); + firstHeap = heap; + heapEnd = + reinterpret_cast<void**> + (reinterpret_cast<char*>(heap) + HEAP_BLOCK_SIZE); + *heapEnd = 0; + heapTop = heap; + if (sizeof(Token) > HEAP_BLOCK_SIZE) + { + fwprintf(stderr, L"--- Too small HEAP_BLOCK_SIZE\n"); + ::exit(1); + } +#ifdef COCO_DEBUG_HEAP + fwprintf + ( + stderr, L"Scanner::init: firstHeap %p -> %p\n", + firstHeap, + reinterpret_cast<char*>(firstHeap) + HEAP_BLOCK_SIZE + ); +#endif + + pos = -1; line = 1; col = 0; + oldEols = 0; + NextCh(); + if (ch == 0xEF) // check optional byte order mark for UTF-8 + { // Windows-specific magic + NextCh(); int ch1 = ch; + NextCh(); int ch2 = ch; + if (ch1 != 0xBB || ch2 != 0xBF) + { + fwprintf(stderr, L"Illegal byte order mark at start of file"); + ::exit(1); + } + Buffer *oldBuf = buffer; + buffer = new UTF8Buffer(oldBuf); col = 0; + delete oldBuf; oldBuf = NULL; + NextCh(); + } + else + { + // FORCE_UTF8 was defined + // use UTF8Buffer without relying on a byte order mark. + Buffer *oldBuf = buffer; + buffer = new UTF8Buffer(oldBuf); col = 0; + delete oldBuf; oldBuf = NULL; + } + + pt = tokens = CreateToken(); // first token is a dummy +} + + +void Scanner::NextCh() +{ + if (oldEols > 0) + { + ch = EOL; + oldEols--; + } + else + { + pos = buffer->GetPos(); + ch = buffer->Read(); col++; + // replace isolated '\r' by '\n' in order to make + // eol handling uniform across Windows, Unix and Mac + if (ch == '\r' && buffer->Peek() != '\n') ch = EOL; + if (ch == EOL) { line++; col = 0; } + } +} + + +void Scanner::AddCh() +{ + if (tlen >= tvalLength) + { + tvalLength *= 2; + wchar_t *newBuf = new wchar_t[tvalLength]; + memcpy(newBuf, tval, tlen*sizeof(wchar_t)); + delete[] tval; + tval = newBuf; + } + if (ch != Buffer::EoF) + { + tval[tlen++] = ch; + NextCh(); + } +} + + + +bool Scanner::Comment0() { + int level = 1, pos0 = pos, line0 = line, col0 = col; + NextCh(); + if (ch == '/') { + NextCh(); + while (true) { + if (ch == 10) { + level--; + if (level == 0) { oldEols = line - line0; NextCh(); return true; } + NextCh(); + } else if (ch == buffer->EoF) return false; + else NextCh(); + } + } else { + buffer->SetPos(pos0); NextCh(); line = line0; col = col0; + } + return false; +} + +bool Scanner::Comment1() { + int level = 1, pos0 = pos, line0 = line, col0 = col; + NextCh(); + if (ch == '*') { + NextCh(); + while (true) { + if (ch == '*') { + NextCh(); + if (ch == '/') { + level--; + if (level == 0) { oldEols = line - line0; NextCh(); return true; } + NextCh(); + } + } else if (ch == '/') { + NextCh(); + if (ch == '*') { + level++; NextCh(); + } + } else if (ch == buffer->EoF) return false; + else NextCh(); + } + } else { + buffer->SetPos(pos0); NextCh(); line = line0; col = col0; + } + return false; +} + +void Scanner::CreateHeapBlock() +{ + char* cur = reinterpret_cast<char*>(firstHeap); + +#ifdef COCO_DEBUG_HEAP + fwprintf(stderr, L"CreateHeapBlock: tokens %p\n", tokens); +#endif + + // release unused blocks + while + ( + (reinterpret_cast<char*>(tokens) < cur) + || (reinterpret_cast<char*>(tokens) > (cur + HEAP_BLOCK_SIZE)) + ) + { + cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE)); +#ifdef COCO_DEBUG_HEAP + fwprintf + ( + stderr, L" free %p -> %p\n", + firstHeap, + reinterpret_cast<char*>(firstHeap) + HEAP_BLOCK_SIZE + ); +#endif + free(firstHeap); + firstHeap = cur; + } + + // HEAP_BLOCK_SIZE byte heap + pointer to next heap block + void* newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*)); + *heapEnd = newHeap; + heapEnd = + reinterpret_cast<void**> + (reinterpret_cast<char*>(newHeap) + HEAP_BLOCK_SIZE); + *heapEnd = 0; + heap = newHeap; + heapTop = heap; +#ifdef COCO_DEBUG_HEAP + fwprintf + ( + stderr, L" malloc %p -> %p\n", + newHeap, + reinterpret_cast<char*>(newHeap) + HEAP_BLOCK_SIZE + ); +#endif +} + + +Token* Scanner::CreateToken() +{ + const int reqMem = sizeof(Token); + if + ( + (reinterpret_cast<char*>(heapTop) + reqMem) + >= reinterpret_cast<char*>(heapEnd) + ) + { + CreateHeapBlock(); + } + // token 'occupies' heap starting at heapTop + Token* tok = reinterpret_cast<Token*>(heapTop); + // increment past this part of the heap, which is now used + heapTop = + reinterpret_cast<void*> + (reinterpret_cast<char*>(heapTop) + reqMem); + tok->val = NULL; + tok->next = NULL; + return tok; +} + + +void Scanner::AppendVal(Token* tok) +{ + const int reqMem = (tlen + 1) * sizeof(wchar_t); + if + ( + (reinterpret_cast<char*>(heapTop) + reqMem) + >= reinterpret_cast<char*>(heapEnd) + ) + { + if (reqMem > HEAP_BLOCK_SIZE) + { + fwprintf(stderr, L"--- Too long token value\n"); + ::exit(1); + } + CreateHeapBlock(); + } + + // add text value from heap + tok->val = reinterpret_cast<wchar_t*>(heapTop); + + // increment past this part of the heap, which is now used + heapTop = + reinterpret_cast<void*> + (reinterpret_cast<char*>(heapTop) + reqMem); + + // copy the currently parsed tval into the token + wcsncpy(tok->val, tval, tlen); + tok->val[tlen] = '\0'; +} + + +Token* Scanner::NextToken() +{ + while + ( + ch == ' ' + || ch == 9 + ) NextCh(); + if ((ch == '/' && Comment0()) || (ch == '/' && Comment1())) return NextToken(); + int recKind = noSym; + int recEnd = pos; + t = CreateToken(); + t->pos = pos; t->col = col; t->line = line; + int state = start.state(ch); + tlen = 0; AddCh(); + + switch (state) + { + case -1: { t->kind = eofSym; break; } // NextCh already done + case 0: { + case_0: + if (recKind != noSym) { + tlen = recEnd - t->pos; + SetScannerBehindT(); + } + t->kind = recKind; break; + } // NextCh already done + case 1: + case_1: + if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= '!') || (ch >= '#' && ch <= '[') || (ch >= ']' && ch <= 65535)) {AddCh(); goto case_1;} + else if (ch == '"') {AddCh(); goto case_3;} + else if (ch == 92) {AddCh(); goto case_2;} + else {goto case_0;} + case 2: + case_2: + if ((ch >= ' ' && ch <= '~')) {AddCh(); goto case_1;} + else {goto case_0;} + case 3: + case_3: + {t->kind = 1; break;} + case 4: + case_4: + if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= '!') || (ch >= '#' && ch <= '&') || (ch >= '(' && ch <= '[') || (ch >= ']' && ch <= 65535)) {AddCh(); goto case_4;} + else if (ch == 39) {AddCh(); goto case_8;} + else if (ch == 92) {AddCh(); goto case_5;} + else {goto case_0;} + case 5: + case_5: + if ((ch >= ' ' && ch <= '~')) {AddCh(); goto case_4;} + else {goto case_0;} + case 6: + case_6: + {t->kind = 4; break;} + case 7: + case_7: + recEnd = pos; recKind = 3; + if (ch == '$' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= 'a' && ch <= 'z')) {AddCh(); goto case_7;} + else if (ch == '.') {AddCh(); goto case_9;} + else {t->kind = 3; std::wstring literal(tval, tlen); t->kind = keywords.get(literal, t->kind); break;} + case 8: + case_8: + recEnd = pos; recKind = 2; + if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= '!') || (ch >= '#' && ch <= '&') || (ch >= '(' && ch <= '[') || (ch >= ']' && ch <= 65535)) {AddCh(); goto case_4;} + else if (ch == 39) {AddCh(); goto case_8;} + else if (ch == 92) {AddCh(); goto case_5;} + else {t->kind = 2; break;} + case 9: + case_9: + if (ch == '$' || (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= 'a' && ch <= 'z')) {AddCh(); goto case_10;} + else if (ch == '*') {AddCh(); goto case_6;} + else {goto case_0;} + case 10: + case_10: + recEnd = pos; recKind = 3; + if (ch == '$' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= 'a' && ch <= 'z')) {AddCh(); goto case_10;} + else if (ch == '.') {AddCh(); goto case_9;} + else {t->kind = 3; std::wstring literal(tval, tlen); t->kind = keywords.get(literal, t->kind); break;} + case 11: + {t->kind = 5; break;} + case 12: + {t->kind = 7; break;} + case 13: + {t->kind = 9; break;} + } + AppendVal(t); + return t; +} + + +void Scanner::SetScannerBehindT() +{ + buffer->SetPos(t->pos); + NextCh(); + line = t->line; col = t->col; + for (int i = 0; i < tlen; i++) NextCh(); +} + + +// get the next token (possibly a token already seen during peeking) +Token* Scanner::Scan() +{ + if (tokens->next == NULL) { + pt = tokens = NextToken(); + } + else { + pt = tokens = tokens->next; + } + return tokens; +} + + +// peek for the next token, ignore pragmas +Token* Scanner::Peek() +{ + do + { + if (pt->next == NULL) + { + pt->next = NextToken(); + } + pt = pt->next; + } while (pt->kind > maxT); // skip pragmas + + return pt; +} + + +// make sure that peeking starts at the current scan position +void Scanner::ResetPeek() +{ + pt = tokens; +} + + +int Scanner::Line() const +{ + return line; +} + + +void Scanner::Line(int lineNo) +{ + line = lineNo; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace + +// ************************************************************************* // diff --git a/wmake/src/wmkdependScanner.h b/wmake/src/wmkdependScanner.h new file mode 100644 index 0000000000000000000000000000000000000000..a72bf4b9684c2b8cd847484213e681981c09acab --- /dev/null +++ b/wmake/src/wmkdependScanner.h @@ -0,0 +1,477 @@ +/*---------------------------------*- C++ -*---------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +@file wmkdependParser.atg + +Description + An attributed Coco/R grammar to parse C/C++, Fortran and Java files + for include and import statements. + +SourceFiles + generated + +\*---------------------------------------------------------------------------*/ +// This file was generated with Coco/R C++ (7 Feb 2010) +// http://www.ssw.uni-linz.ac.at/coco/ +// with these defines: +// - FORCE_UTF8 + + +#ifndef COCO_wmkdependSCANNER_H__ +#define COCO_wmkdependSCANNER_H__ + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cwchar> +#include <string> +#include <fstream> +#include <iostream> + +namespace wmake { + +// * * * * * * * * * * * Miscellaneous String Routines * * * * * * * * * * * // + +//! Simple lower-case string transformation +template<class StringT> +inline void coco_string_toLower(StringT& str) +{ + for + ( + typename StringT::iterator iter = str.begin(); + iter != str.end(); + ++iter + ) + { + if (*iter >= 'A' && *iter <= 'Z') + { + *iter += ('a' - 'A'); // lower-case + } + } +} + + +//! Simple string hashing function +template<class StringT> +inline int coco_string_hash(const StringT& str) +{ + int h = 0; + for + ( + typename StringT::const_iterator iter = str.begin(); + iter != str.end(); + ++iter + ) + { + h = (h * 7) ^ *iter; + } + return h < 0 ? -h : h; +} + + +// +// String conversions +// ~~~~~~~~~~~~~~~~~~ + +//! Convert wide string to double +inline double coco_string_toDouble(const wchar_t* str) +{ + return str ? wcstod(str, NULL) : 0; +} + + +//! Convert wide string to long +inline long coco_string_toLong(const wchar_t* str) +{ + return str ? wcstol(str, NULL, 10) : 0; +} + + +//! A byte string (restricted to 8bit values) by copying str +std::string coco_stdString(const wchar_t* str); + +//! A byte string (restricted to 8bit values) by copying str, +//! up to length characters long +std::string coco_stdString(const wchar_t* str, unsigned length); + +//! A byte substring (restricted to 8bit values) of str, +//! starting at index and length characters long +std::string coco_stdString(const wchar_t* str, unsigned index, unsigned length); + +//! A UTF8 byte string by copying str +std::string coco_stdStringUTF8(const wchar_t* str); + +//! A UTF8 byte string by copying str, up to length characters long +std::string coco_stdStringUTF8(const wchar_t* str, unsigned length); + +//! A UTF8 byte substring, starting at index and length characters long +std::string coco_stdStringUTF8(const wchar_t* str, unsigned index, unsigned length); + +// * * * * * * * * * * * * End of String Routines * * * * * * * * * * * * * // + + + +/*---------------------------------------------------------------------------*\ + Class Token Declaration +\*---------------------------------------------------------------------------*/ +/*! + * @brief Scanner Token + * + * @note since each Token is allocated by the internal heap mechanism, + * the destructor does not clean up the val member. + */ +class Token +{ +public: + int kind; //!< token kind + int pos; //!< token position in the source text (starting at 0) + int col; //!< token column (starting at 1) + int line; //!< token line (starting at 1) + wchar_t* val; //!< token value (normally allocated from the internal heap) + Token *next; //!< Peek tokens are kept in linked list + + int length() const; //!< The length of val, or 0 if val is NULL + + //! Construct null Token, optionally with pointer to a string value + Token(wchar_t* value = 0); + ~Token(); //!< Destructor - does not cleanup val member + + //! Token val as byte string (restricted to 8bit values) + inline std::string toString() const + { + return coco_stdString(val); + } + + //! Token val as byte string (restricted to 8bit values), up to length characters long + inline std::string toString(unsigned length) const + { + return coco_stdString(val, length); + } + + //! Token val as byte string (restricted to 8bit values), starting at index and length characters long + inline std::string toString(unsigned index, unsigned length) const + { + return coco_stdString(val, index, length); + } + + //! Token val as UTF8 byte string + inline std::string toStringUTF8() const + { + return coco_stdStringUTF8(val); + } + + //! Token val as UTF8 byte string, up to length characters long + inline std::string toStringUTF8(unsigned length) const + { + return coco_stdStringUTF8(val, length); + } + + //! Token val as UTF8 byte substring, starting at index and length characters long + inline std::string toStringUTF8(unsigned index, unsigned length) const + { + return coco_stdStringUTF8(this->val, index, length); + } + +}; + + +/*---------------------------------------------------------------------------*\ + Class Buffer Declaration +\*---------------------------------------------------------------------------*/ +/*! + * @brief Scanner Buffer Token + * + * This Buffer supports the following cases: + * -# seekable stream (file) + * -# whole stream in buffer + * -# part of stream in buffer + * -# non seekable stream (network, console) + */ +class Buffer +{ + unsigned char *buf; //!< input buffer + int bufCapacity; //!< capacity of buf + int bufLen; //!< length of buffer + int bufPos; //!< current position in buffer + int bufStart; //!< position of first byte in buffer relative to input stream + int fileLen; //!< length of input stream (may change if the stream is no file) + FILE* cStream; //!< input stdio stream (normally seekable) + std::istream* stdStream; //!< STL std stream (seekable) + bool isUserStream_; //!< was the stream opened by the user? + + int ReadNextStreamChunk(); + bool CanSeek() const; //!< true if stream can be seeked otherwise false + +protected: + Buffer(Buffer*); //!< for the UTF8Buffer + +public: + //! max unicode characters is 0xFFFF (16bit storage) + static const int MaxChar = 65535; + static const int EoF = MaxChar + 1; + + //! Copy buffer contents from constant character string + Buffer(const char* chars, int len); + + //! Copy buffer contents from constant character string + Buffer(const unsigned char* chars, int len); + + //! @brief Attach buffer to a stdio stream. + //! User streams are not closed in the destructor + Buffer(FILE*, bool isUserStream = true); + + //! @brief Attach buffer to an STL standard stream + //! User streams are not closed in the destructor + explicit Buffer(std::istream*, bool isUserStream = true); + + //! Close stream (but not user streams) and free buf (if any) + virtual ~Buffer(); + + virtual void Close(); //!< Close stream (but not user streams) + virtual int Read(); //!< Get character from stream or buffer + virtual int Peek(); //!< Peek character from stream or buffer + + virtual int GetPos() const; + virtual void SetPos(int value); + virtual bool isUTF8() const; //!< Return false - buffer is not UTF8 +}; + + +/*---------------------------------------------------------------------------*\ + Class UTF8Buffer Declaration +\*---------------------------------------------------------------------------*/ +//! A Scanner Buffer variant that decodes UTF-8 characters into 16bit unicode +class UTF8Buffer : public Buffer +{ +public: + UTF8Buffer(Buffer* b) : Buffer(b) {} + virtual int Read(); + virtual bool isUTF8() const; //!< Return true - buffer is UTF8 +}; + + +/*---------------------------------------------------------------------------*\ + Class StartStates Declaration +\*---------------------------------------------------------------------------*/ +//! maps characters (integers) to start states of tokens as a HashTable +class StartStates +{ + //! HashTable entry + struct Entry + { + int key; //<! The lookup key + int val; //<! The data + Entry *next; //<! Pointer next Entry in sub-list + + Entry(int k, int v, Entry *n=0) + : + key(k), val(v), next(n) + {} + }; + + static const int size_ = 128; //<! fixed HashTable size + Entry **table_; + +public: + StartStates() + : + table_(new Entry*[size_]) + { + memset(table_, 0, size_*sizeof(Entry*)); + } + + virtual ~StartStates() + { + for (int i = 0; i < size_; ++i) + { + Entry *e = table_[i]; + while (e) + { + Entry *next = e->next; + delete e; + e = next; + } + } + delete[] table_; + } + + void set(int key, int val) + { + const int hashIndex = unsigned(key) % size_; + table_[hashIndex] = new Entry(key, val, table_[hashIndex]); + } + + int state(int key) + { + Entry *e = table_[unsigned(key) % size_]; + while (e && e->key != key) e = e->next; + return e ? e->val : 0; + } +}; + + +/*---------------------------------------------------------------------------*\ + Class KeywordMap Declaration +\*---------------------------------------------------------------------------*/ +//! maps strings to integers (identifiers to keyword kinds) as a HashTable +class KeywordMap +{ + //! HashTable entry + struct Entry + { + const std::wstring key; //<! The lookup key + int val; //<! The data + Entry *next; //<! Pointer next Entry in sub-list + + Entry(const std::wstring& k, int v, Entry *n=0) + : + key(k), val(v), next(n) + {} + }; + + static const int size_ = 128; //<! fixed HashTable size + Entry **table_; + +public: + KeywordMap() + : + table_(new Entry*[size_]) + { + memset(table_, 0, size_*sizeof(Entry*)); + } + + virtual ~KeywordMap() + { + for (int i = 0; i < size_; ++i) + { + Entry *e = table_[i]; + while (e) + { + Entry *next = e->next; + delete e; + e = next; + } + } + delete[] table_; + } + + void set(const std::wstring& key, int val) + { + const int hashIndex = coco_string_hash(key) % size_; + table_[hashIndex] = new Entry(key, val, table_[hashIndex]); + } + + int get(const std::wstring& key, int defaultVal) + { + Entry *e = table_[coco_string_hash(key) % size_]; + while (e && e->key != key) e = e->next; + return e ? e->val : defaultVal; + } +}; + + +/*---------------------------------------------------------------------------*\ + Class Scanner Declaration +\*---------------------------------------------------------------------------*/ +//! A Coco/R Scanner +class Scanner +{ + static const int maxT = 10; + static const int noSym = 10; + static const int eofSym = 0; //!< end-of-file token id + static const char EOL = '\n'; //!< end-of-line character + + void *firstHeap; //!< the start of the heap management + void *heap; //!< the currently active block + void *heapTop; //!< the top of the heap + void **heapEnd; //!< the end of the last heap block + + StartStates start; //!< A map of start states for particular characters + KeywordMap keywords; //!< A hash of keyword literals to token kind + + Token *t; //!< current token + wchar_t *tval; //!< text of current token + int tvalLength; //!< maximum capacity (length) for tval + int tlen; //!< length of tval + + Token *tokens; //!< list of tokens already peeked (first token is a dummy) + Token *pt; //!< current peek token + + int ch; //!< current input character + int pos; //!< byte position of current character + int line; //!< line number of current character + int col; //!< column number of current character + int oldEols; //!< the number of EOLs that appeared in a comment + + void CreateHeapBlock(); //!< add a heap block, freeing unused ones + Token* CreateToken(); //!< fit token on the heap + void AppendVal(Token* tok); //!< adjust tok->val to point to the heap and copy tval into it + void SetScannerBehindT(); + + void Init(); //!< complete the initialization for the constructors + void NextCh(); //!< get the next input character into ch + void AddCh(); //!< append the character ch to tval + bool Comment0(); + bool Comment1(); + Token* NextToken(); //!< get the next token + +public: + //! The scanner buffer + Buffer *buffer; + + //! Attach scanner to an existing character buffer + Scanner(const char* chars, int len); + + //! Attach scanner to an existing character buffer + Scanner(const unsigned char* chars, int len); + + //! Attach scanner to an existing open file handle + Scanner(FILE*); + +#ifdef _WIN32 + //! Open a file for reading and attach scanner - Windows only + explicit Scanner(const std::wstring& fileName); +#endif + + //! Open a file for reading and attach scanner + explicit Scanner(const std::string& fileName); + + //! Attach scanner to an existing open STL standard stream + explicit Scanner(std::istream&); + + ~Scanner(); //!< free heap and allocated memory + Token* Scan(); //!< get the next token (possibly a token already seen during peeking) + Token* Peek(); //!< peek for the next token, ignore pragmas + void ResetPeek(); //!< ensure that peeking starts at the current scan position + + int Line() const; //!< Return the current line + void Line(int lineNo); //!< Define the starting line for reporting errors + +}; // end Scanner + +} // End namespace + +#endif // COCO_wmkdependSCANNER_H__ + +// ************************************************************************* //