diff --git a/applications/test/codeStream/Make/files b/applications/test/codeStream/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..a5e2ef2d2f4ab72970c0449416b17016ced0df3a --- /dev/null +++ b/applications/test/codeStream/Make/files @@ -0,0 +1,3 @@ +Test-codeStream.C + +EXE = $(FOAM_USER_APPBIN)/Test-codeStream diff --git a/applications/test/codeStream/Make/options b/applications/test/codeStream/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..41306609f208806f0c6f42a2426867d3e10d4897 --- /dev/null +++ b/applications/test/codeStream/Make/options @@ -0,0 +1 @@ +EXE_INC = diff --git a/applications/test/codeStream/Test-codeStream.C b/applications/test/codeStream/Test-codeStream.C new file mode 100644 index 0000000000000000000000000000000000000000..f2fbf756378d9aecd31ec42b8554c3a77d307c8b --- /dev/null +++ b/applications/test/codeStream/Test-codeStream.C @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2011 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 3 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, see <http://www.gnu.org/licenses/>. + +Application + Test-codeStream + +Description + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "IOstreams.H" +#include "IOobject.H" +#include "IFstream.H" +#include "dictionary.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::validArgs.insert("dict .. dictN"); + argList args(argc, argv, false, true); + + Info<< nl + << "FOAM_CASE=" << getEnv("FOAM_CASE") << nl + << "FOAM_CASENAME=" << getEnv("FOAM_CASENAME") << nl + << endl; + + if (args.size() <= 1) + { + Info<<"specify dictionaries to test\n"; + } + else + { + IOobject::writeDivider(Info); + for (label argI=1; argI < args.size(); ++argI) + { + const string& dictFile = args[argI]; + IFstream is(dictFile); + + dictionary dict(is); + + Info<< dict << endl; + } + } + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/test/codeStream/codeStreamDict1 b/applications/test/codeStream/codeStreamDict1 new file mode 100644 index 0000000000000000000000000000000000000000..54fb3d0efe9497c15c83617324fc3ac81a8d42d3 --- /dev/null +++ b/applications/test/codeStream/codeStreamDict1 @@ -0,0 +1,43 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: Any | +| \\ / A nd | Web: www.OpenFOAM.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object testDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// #include "codeStreamDefaults" + +writeInterval #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude + #}; + + code + #{ + scalar start = 0; + scalar end = 100; + label nDumps = 5; + label interval = end - start; + Info<<"on-the-fly: " << ((interval)/nDumps) << endl; + os << ((interval)/nDumps); + #}; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/etc/codeTemplates/codeStream/codeStreamTemplate.C b/etc/codeTemplates/codeStream/codeStreamTemplate.C index af4f82ffc8a970a1c2a750b2b6be63ce6f951e1e..f6aa7501ccebe08a4e5ddbb928b82e7d1809fae1 100644 --- a/etc/codeTemplates/codeStream/codeStreamTemplate.C +++ b/etc/codeTemplates/codeStream/codeStreamTemplate.C @@ -21,9 +21,14 @@ License You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +Description + Template for use with codeStream. + \*---------------------------------------------------------------------------*/ +//{{{ begin codeInclude ${codeInclude} +//}}} end codeInclude using namespace Foam; @@ -39,7 +44,9 @@ void ${typeName} Ostream& os ) { +//{{{ begin code ${code}; +//}}} end code } } diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C index d91fcce979a2063e5a0e489784f92487a03d972e..5a2735541065443af08a4b50010e0b6a0d9c511f 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.C @@ -57,6 +57,16 @@ namespace functionEntries } +const Foam::word Foam::functionEntries::codeStream::codeTemplateName + = "codeStreamTemplate.C"; + +const Foam::word Foam::functionEntries::codeStream::codeTemplateEnvName + = "FOAM_CODESTREAM_TEMPLATES"; + +const Foam::fileName Foam::functionEntries::codeStream::codeTemplateDirName + = "codeTemplates/codeStream"; + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // bool Foam::functionEntries::codeStream::execute @@ -80,57 +90,52 @@ bool Foam::functionEntries::codeStream::execute } - // Read three sections of code. Remove any leading empty lines - // (necessary for compilation options, just visually pleasing for includes - // and body). + // Read three sections of code. + // Remove any leading whitespace - necessary for compilation options, + // convenience for includes and body. dictionary codeDict(is); - string codeInclude = ""; + // "codeInclude" is optional + string codeInclude; if (codeDict.found("codeInclude")) { codeInclude = stringOps::trimLeft(codeDict["codeInclude"]); } - string code = stringOps::trimLeft(codeDict["code"]); - string codeOptions = ""; + // "codeOptions" is optional + string codeOptions; if (codeDict.found("codeOptions")) { codeOptions = stringOps::trimLeft(codeDict["codeOptions"]); } + // "code" is mandatory + string code = stringOps::trimLeft(codeDict["code"]); // Create name from the contents SHA1Digest sha; { OSHA1stream os; - os << codeInclude << code << codeOptions; + os << codeInclude << codeOptions << code; sha = os.digest(); } - fileName name; - { - OStringStream str; - str << sha; - name = "codeStream" + str.str(); - } + // write code into _SHA1 subdirectory fileName dir; if (isA<IOdictionary>(parentDict)) { const IOdictionary& d = static_cast<const IOdictionary&>(parentDict); - dir = d.db().time().constantPath()/"codeStream"/name; + dir = d.db().time().constantPath()/"codeStream"/"_" + sha.str(); } else { - dir = "codeStream"/name; + dir = fileName("codeStream")/"_" + sha.str(); } - + fileName name = "codeStream_" + sha.str(); fileName libPath ( - Foam::getEnv("FOAM_USER_LIBBIN") - / "lib" - + name - + ".so" + Foam::getEnv("FOAM_USER_LIBBIN")/"lib" + name + ".so" ); void* lib = dlLibraryTable::findLibrary(libPath); @@ -143,39 +148,64 @@ bool Foam::functionEntries::codeStream::execute { Info<< "Creating new library in " << libPath << endl; - fileName templates + fileName srcFile; + + // try to get template from FOAM_CODESTREAM_TEMPLATES + fileName templateDir ( - Foam::getEnv("FOAM_CODESTREAM_TEMPLATE_DIR") + Foam::getEnv(codeTemplateEnvName) ); - if (!templates.size()) + + if (!templateDir.empty()) + { + srcFile = templateDir/codeTemplateName; + if (!isFile(srcFile, false)) + { + srcFile.clear(); + } + } + + // not found - fallback to ~OpenFOAM expansion + if (srcFile.empty()) + { + srcFile = findEtcFile + ( + codeTemplateDirName/codeTemplateName + ); + } + + if (srcFile.empty()) { FatalIOErrorIn ( "functionEntries::codeStream::execute(..)", parentDict - ) << "Please set environment variable" - " FOAM_CODESTREAM_TEMPLATE_DIR" - << " to point to the location of codeStreamTemplate.C" + ) << "Could not find the code template: " + << codeTemplateName << nl + << "Under the $FOAM_CODESTREAM_TEMPLATES directory" + << " via via the ~OpenFOAM/" / codeTemplateDirName + << " expansion" << exit(FatalIOError); } - List<fileAndVars> copyFiles(1); - copyFiles[0].first() = templates/"codeStreamTemplate.C"; - stringPairList bodyVars(2); - bodyVars[0] = Pair<string>("codeInclude", codeInclude); - bodyVars[1] = Pair<string>("code", code); - copyFiles[0].second() = bodyVars; - List<fileAndContent> filesContents(2); + List<codeStreamTools::fileAndVars> copyFiles(1); + copyFiles[0].file() = srcFile; + copyFiles[0].set("codeInclude", codeInclude); + copyFiles[0].set("code", code); + + List<codeStreamTools::fileAndContent> filesContents(2); + // Write Make/files filesContents[0].first() = "Make/files"; filesContents[0].second() = - "codeStreamTemplate.C \n\ - LIB = $(FOAM_USER_LIBBIN)/lib" + name; + codeTemplateName + "\n" + "LIB = $(FOAM_USER_LIBBIN)/lib" + name; + // Write Make/options filesContents[1].first() = "Make/options"; filesContents[1].second() = - "EXE_INC = -g\\\n" + codeOptions + "\n\nLIB_LIBS = "; + "EXE_INC = -g \\\n" + codeOptions + "\n\nLIB_LIBS ="; codeStreamTools writer(name, copyFiles, filesContents); if (!writer.copyFilesContents(dir)) @@ -199,7 +229,8 @@ bool Foam::functionEntries::codeStream::execute ( "functionEntries::codeStream::execute(..)", parentDict - ) << "Failed " << wmakeCmd << exit(FatalIOError); + ) << "Failed " << wmakeCmd + << exit(FatalIOError); } } @@ -209,7 +240,8 @@ bool Foam::functionEntries::codeStream::execute ( "functionEntries::codeStream::execute(..)", parentDict - ) << "Failed loading library " << libPath << exit(FatalIOError); + ) << "Failed loading library " << libPath + << exit(FatalIOError); } lib = dlLibraryTable::findLibrary(libPath); diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H index 6375d1329e4b7b8cc9c20783b4577a360f54827d..ea732167b5fd786d75a1587d18dc872db88c17ec 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStream.H @@ -29,11 +29,12 @@ Description generate the entry itself. So - codeStream reads three entries: 'code', 'codeInclude' (optional), 'codeOptions' (optional) - and uses those to generate library sources inside constant/codeStream/ + and uses those to generate library sources inside \f constant/codeStream/ - these get compiled using 'wmake libso' - the resulting library is loaded in executed with as arguments - const dictionary& dict, - Ostream& os + \code + (const dictionary& dict, Ostream& os) + \endcode where the dictionary is the current dictionary. - the code has to write into Ostream which is then used to construct the actual dictionary entry. @@ -41,6 +42,7 @@ Description E.g. to set the internal field of a field: + \verbatim internalField #codeStream { code @@ -56,19 +58,23 @@ Description #{ #include "fvCFD.H" #}; + + //- Optional: codeOptions #{ -I$(LIB_SRC)/finiteVolume/lnInclude #}; }; + \endverbatim - Note the #{ #} syntax which is just a way of inputting strings with embedded - newlines. + Note the \c \#{ ... \c \#} syntax is a 'verbatim' input mode that allows + inputting strings with embedded newlines. Limitations: - '~' symbol not allowed inside the code sections. - - probably some other limitations (uses string::expand which expands $, ~) + - probably some other limitations (uses string::expand which expands + \c \$ and \c ~ sequences) SourceFiles codeStream.C @@ -106,6 +112,20 @@ class codeStream public: + // Static data members + + //- Name of the code template to be used + const static word codeTemplateName; + + //- Name of the code template environment variable + // Used to located the codeTemplateName + const static word codeTemplateEnvName; + + //- Name of the code template sub-directory + // Used when locating the codeTemplateName via Foam::findEtcFile + const static fileName codeTemplateDirName; + + //- Runtime type information ClassName("codeStream"); diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.C b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.C index 337fc177e155fc5122c7960fa13423048e886a64..783f986a0e028ebbfa1f0b3afd29775a928de062 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.C @@ -25,6 +25,7 @@ License \*---------------------------------------------------------------------------*/ #include "codeStreamTools.H" +#include "stringOps.H" #include "IFstream.H" #include "OFstream.H" #include "OSspecific.H" @@ -43,38 +44,46 @@ int Foam::codeStreamTools::allowSystemOperations void Foam::codeStreamTools::copyAndExpand ( - ISstream& sourceStr, - OSstream& destStr + ISstream& is, + OSstream& os, + const HashTable<string>& mapping ) const { - if (!sourceStr.good()) + if (!is.good()) { FatalErrorIn ( "codeStreamTools::copyAndExpand()" " const" - ) << "Failed opening for reading " << sourceStr.name() + ) << "Failed opening for reading " << is.name() << exit(FatalError); } - if (!destStr.good()) + if (!os.good()) { FatalErrorIn ( "codeStreamTools::copyAndExpand()" " const" - ) << "Failed writing " << destStr.name() << exit(FatalError); + ) << "Failed writing " << os.name() + << exit(FatalError); } - // Copy file whilst rewriting environment vars + // Copy file while rewriting $VARS and ${VARS} string line; do { - sourceStr.getLine(line); - line.expand(true, true); // replace any envvars inside substitutions - destStr<< line.c_str() << nl; + is.getLine(line); + + // normal expansion according to mapping + stringOps::inplaceExpand(line, mapping); + + // expand according to env variables + stringOps::inplaceExpandEnv(line, true, true); + + os << line.c_str() << nl; } - while (sourceStr.good()); + while (is.good()); } @@ -109,11 +118,11 @@ Foam::codeStreamTools::codeStreamTools {} -Foam::codeStreamTools::codeStreamTools(const codeStreamTools& otf) +Foam::codeStreamTools::codeStreamTools(const codeStreamTools& tools) : - name_(otf.name_), - copyFiles_(otf.copyFiles_), - filesContents_(otf.filesContents_) + name_(tools.name_), + copyFiles_(tools.copyFiles_), + filesContents_(tools.filesContents_) {} @@ -127,21 +136,17 @@ bool Foam::codeStreamTools::copyFilesContents(const fileName& dir) const ( "codeStreamTools::copyFilesContents(const fileName&) const" ) << "Loading a shared library using case-supplied code is not" - << " enabled by default" << endl + << " enabled by default" << nl << "because of security issues. If you trust the code you can" - << " enable this" << endl + << " enable this" << nl << "facility be adding to the InfoSwitches setting in the system" - << " controlDict" << endl - << endl - << " allowSystemOperations 1" << endl - << endl - << "The system controlDict is either" << endl - << endl - << " ~/.OpenFOAM/$WM_PROJECT_VERSION/controlDict" << endl - << endl - << "or" << endl - << endl - << " $WM_PROJECT_DIR/etc/controlDict" << endl + << " controlDict" << nl + << nl + << " allowSystemOperations 1" << nl << nl + << "The system controlDict is either" << nl << nl + << " ~/.OpenFOAM/$WM_PROJECT_VERSION/controlDict" << nl << nl + << "or" << nl << nl + << " $WM_PROJECT_DIR/etc/controlDict" << nl << endl << exit(FatalError); } @@ -149,64 +154,64 @@ bool Foam::codeStreamTools::copyFilesContents(const fileName& dir) const // Create dir mkDir(dir); - //Info<< "Setting envvar typeName=" << name_ << endl; - setEnv("typeName", name_, true); + // Info<< "set mapping typeName=" << name_ << endl; // Copy any template files forAll(copyFiles_, i) { - const List<Pair<string> >& rules = copyFiles_[i].second(); - forAll(rules, j) - { - //Info<< "Setting envvar " << rules[j].first() << endl; - setEnv(rules[j].first(), rules[j].second(), true); - } + const fileName sourceFile(fileName(copyFiles_[i].file()).expand()); + const fileName destFile(dir/sourceFile.name()); - const fileName sourceFile = fileName(copyFiles_[i].first()).expand(); - const fileName destFile = dir/sourceFile.name(); - - IFstream sourceStr(sourceFile); - //Info<< "Reading from " << sourceStr.name() << endl; - if (!sourceStr.good()) + IFstream is(sourceFile); + //Info<< "Reading from " << is.name() << endl; + if (!is.good()) { FatalErrorIn ( - "codeStreamTools::copyFilesContents()" + "codeStreamTools::copyFilesContents(const fileName&)" " const" ) << "Failed opening " << sourceFile << exit(FatalError); } - OFstream destStr(destFile); + OFstream os(destFile); //Info<< "Writing to " << destFile.name() << endl; - if (!destStr.good()) + if (!os.good()) { FatalErrorIn ( - "codeStreamTools::copyFilesContents()" + "codeStreamTools::copyFilesContents(const fileName&)" " const" ) << "Failed writing " << destFile << exit(FatalError); } - copyAndExpand(sourceStr, destStr); + // variables mapping + HashTable<string> mapping(copyFiles_[i]); + mapping.set("typeName", name_); + copyAndExpand(is, os, mapping); } + // Files that are always written: forAll(filesContents_, i) { - fileName f = fileName(dir/filesContents_[i].first()).expand(); + const fileName dstFile + ( + fileName(dir/filesContents_[i].first()).expand() + ); - mkDir(f.path()); - OFstream str(f); + mkDir(dstFile.path()); + OFstream os(dstFile); //Info<< "Writing to " << filesContents_[i].first() << endl; - if (!str.good()) + if (!os.good()) { FatalErrorIn ( "codeStreamTools::copyFilesContents()" " const" - ) << "Failed writing " << f << exit(FatalError); + ) << "Failed writing " << dstFile << exit(FatalError); } - str << filesContents_[i].second().c_str() << endl; + os << filesContents_[i].second().c_str() << endl; } + return true; } @@ -217,16 +222,16 @@ bool Foam::codeStreamTools::writeDigest const SHA1Digest& sha1 ) { - OFstream str(dir/"SHA1Digest"); - str << sha1; - return str.good(); + OFstream os(dir/"SHA1Digest"); + os << sha1; + return os.good(); } Foam::SHA1Digest Foam::codeStreamTools::readDigest(const fileName& dir) { - IFstream str(dir/"SHA1Digest"); - return SHA1Digest(str); + IFstream is(dir/"SHA1Digest"); + return SHA1Digest(is); } diff --git a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.H b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.H index d04d2fad5db43c591b52559ac5e7654a261f072a..0e989eafd67d05fdf3534a582a70398329bc4a5f 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/codeStream/codeStreamTools.H @@ -39,20 +39,16 @@ SourceFiles #include "Tuple2.H" #include "Pair.H" #include "SHA1Digest.H" +#include "HashTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { - -typedef List<Pair<string> > stringPairList; -typedef Tuple2<fileName, List<Pair<string> > > fileAndVars; -typedef Tuple2<fileName, string> fileAndContent; - - -class OSstream; +// Forward declaration of classes class ISstream; +class OSstream; /*---------------------------------------------------------------------------*\ Class codeStreamTools Declaration @@ -60,20 +56,56 @@ class ISstream; class codeStreamTools { +public: + typedef Tuple2<fileName, string> fileAndContent; + + //- Helper class for managing file and variables + class fileAndVars + : + public HashTable<string> + { + // Private data + fileName file_; + + public: + //- Construct null + fileAndVars() + {} + + //- Return the file name + const fileName& file() const + { + return file_; + } + + //- Return the file name + fileName& file() + { + return file_; + } + }; + + +private: // Private data //- Name for underlying set word name_; //- Files to copy - List<fileAndVars> copyFiles_; + List<codeStreamTools::fileAndVars> copyFiles_; //- Direct contents for files List<fileAndContent> filesContents_; protected: - void copyAndExpand(ISstream&, OSstream&) const; + void copyAndExpand + ( + ISstream&, + OSstream&, + const HashTable<string>& mapping + ) const; public: @@ -96,24 +128,24 @@ public: ); //- Construct copy - codeStreamTools(const codeStreamTools& otf); + codeStreamTools(const codeStreamTools&); // Member functions - const List<Tuple2<fileName, List<Pair<string> > > >& copyFiles() const + const word& name() const { - return copyFiles_; + return name_; } - const List<Tuple2<fileName, string> >& filesContents() const + const List<fileAndVars>& copyFiles() const { - return filesContents_; + return copyFiles_; } - const word& name() const + const List<Tuple2<fileName, string> >& filesContents() const { - return name_; + return filesContents_; } bool copyFilesContents(const fileName& dir) const;