From 005615331eb8b03a965534158bda088cf6494ca5 Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Fri, 3 Jun 2011 12:01:50 +0000
Subject: [PATCH] new Initfile parser

---
 AMDiS/AMDiSConfig.cmake.in |   7 +-
 AMDiS/CMakeLists.txt       |  25 ++-
 AMDiS/src/Initfile.cc      | 142 ++++++++++++++
 AMDiS/src/Initfile.h       | 378 +++++++++++++++++++++++++++++++++++++
 AMDiS/src/Parameters.cc    |  70 +++----
 5 files changed, 580 insertions(+), 42 deletions(-)
 create mode 100644 AMDiS/src/Initfile.cc
 create mode 100644 AMDiS/src/Initfile.h

diff --git a/AMDiS/AMDiSConfig.cmake.in b/AMDiS/AMDiSConfig.cmake.in
index 113c0b97..c711d0fa 100644
--- a/AMDiS/AMDiSConfig.cmake.in
+++ b/AMDiS/AMDiSConfig.cmake.in
@@ -68,7 +68,7 @@ set(AMDIS_MINOR_VERSION @AMDIS_MINOR@)
 if(AMDiS_NEED_UMFPACK)
 	#look for umfpack, we need the headers only
 	find_file(UMFPACK_H umfpack.h
-			HINTS /usr/include /usr/include/suitesparse 
+			HINTS /usr/include /usr/include/suitesparse /usr/include/ufsparse
 			DOC "headerfile umfpack.h for UMFPACK")
 	if( UMFPACK_H )
 		#construct the include path
@@ -125,6 +125,11 @@ if(AMDiS_NEED_UMFPACK)
 	list(APPEND AMDIS_LIBRARY_DIRS ${BLAS_LIBRARY_DIR})
 endif(AMDiS_NEED_UMFPACK)
 
+
+#add directories for reinit
+list(APPEND AMDIS_INCLUDE_DIRS ${AMDIS_INCLUDE_DIR}/reinit)
+list(APPEND AMDIS_INCLUDE_DIRS ${AMDIS_INCLUDE_DIR}/compositeFEM)
+
 if(${AMDIS_FIND_COMPONENTS} MATCHES umfpack )
 	if( NOT AMDiS_NEED_UMFPACK )
 	  set( AMDiS_umfpack_FOUND FALSE)
diff --git a/AMDiS/CMakeLists.txt b/AMDiS/CMakeLists.txt
index bbf3e5f1..4427d078 100644
--- a/AMDiS/CMakeLists.txt
+++ b/AMDiS/CMakeLists.txt
@@ -100,6 +100,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
 	      ${SOURCE_DIR}/Global.cc
 	      ${SOURCE_DIR}/GlobalDOFNumbering.cc
 	      ${SOURCE_DIR}/GlobalElementNumbering.cc
+              ${SOURCE_DIR}/Initfile.cc
 	      ${SOURCE_DIR}/Lagrange.cc
 	      ${SOURCE_DIR}/LeafData.cc
 	      ${SOURCE_DIR}/Line.cc
@@ -288,7 +289,7 @@ if(ENABLE_UMFPACK)
 
 	#look for umfpack, we need the headers only
 	find_file(UMFPACK_H umfpack.h
-			HINTS /usr/include /usr/include/suitesparse 
+			HINTS /usr/include /usr/include/suitesparse /usr/include/ufsparse
 			DOC "headerfile umfpack.h for UMFPACK")
 	if( UMFPACK_H )
 		#construct the include path
@@ -345,8 +346,9 @@ include_directories(${AMDiS_INCLUDE_DIRS})
 
 add_library(amdis SHARED ${AMDIS_SRC} ${PARALLEL_DOMAIN_AMDIS_SRC})
 add_library(compositeFEM SHARED ${COMPOSITE_FEM_SRC})
-add_library(reinit STATIC ${REINIT_SRC})
-target_link_libraries(compositeFEM amdis)
+add_library(reinit SHARED ${REINIT_SRC})
+#target_link_libraries(compositeFEM amdis)
+#target_link_libraries(reinit amdis)
 list(APPEND AMDiS_LIBS amdis ${Boost_LIBRARIES})
 
 if(WIN32)
@@ -361,9 +363,6 @@ if(ENABLE_MARMOT)
 endif(ENABLE_MARMOT)
 
 #dont change this destination. the GUI depends on it to guess the buildsystem
-list(APPEND deb_add_dirs "lib/amdis")
-install(TARGETS amdis compositeFEM 
-	LIBRARY DESTINATION lib/amdis/ )
 
 FILE(GLOB HEADERS "${SOURCE_DIR}/*.h")
 INSTALL(FILES ${HEADERS} 
@@ -398,6 +397,20 @@ FILE(GLOB HEADERS "${SOURCE_DIR}/io/*.hh")
 INSTALL(FILES ${HEADERS}
 	DESTINATION include/amdis/io)
 
+FILE(GLOB HEADERS "${REINIT_SOURCE_DIR}/*.h")
+INSTALL(FILES ${HEADERS}
+	DESTINATION include/amdis/reinit)
+list(APPEND deb_add_dirs "include/amdis/reinit")
+
+FILE(GLOB HEADERS "${COMPOSITE_SOURCE_DIR}/*.h")
+INSTALL(FILES ${HEADERS}
+	DESTINATION include/amdis/compositeFEM)
+list(APPEND deb_add_dirs "include/amdis/compositeFEM")
+
+list(APPEND deb_add_dirs "lib/amdis")
+install(TARGETS amdis compositeFEM reinit 
+	LIBRARY DESTINATION lib/amdis/ )
+
 configure_file(${AMDiS_SOURCE_DIR}/AMDiSConfig.cmake.in
 		${AMDiS_BINARY_DIR}/AMDISConfig.cmake
 		@ONLY
diff --git a/AMDiS/src/Initfile.cc b/AMDiS/src/Initfile.cc
new file mode 100644
index 00000000..e22348b7
--- /dev/null
+++ b/AMDiS/src/Initfile.cc
@@ -0,0 +1,142 @@
+#include "Initfile.h"
+
+#include <string>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+using namespace std;
+
+/// the small parser for the initfile. see description of read(Initfile&, istream&)
+struct Parser {
+	Parser(const string& line) {
+		size_t pos= line.find(':');
+		if (pos == string::npos)
+			throw runtime_error("cannot find the delimiter ':' in line '"+line+"'");
+		name= line.substr(0, pos);
+		value= line.substr(pos+1, line.length() - (pos + 1));
+		// remove everything after the %
+		pos= value.find('%');
+		if (pos != string::npos) {
+			value= value.substr(0, pos);
+		}
+	}
+	string name;
+	string value;
+};
+
+Initfile* Initfile::singlett= NULL;
+std::set< std::string > Initfile::fn_include_list;
+
+/// initialize singleton object an global parameters
+void Initfile::init(std::string in) {
+	initIntern();
+	singlett->clear();
+	fn_include_list.clear();
+	singlett->read(in);
+	
+	singlett->getInternalParameters();
+	
+	// initialize global strcutures using parameters
+	Global::init();
+};
+
+/// Fill an initfile from a file with filename fn
+void Initfile::read(std::string fn) {
+// read file if its not parsed already
+	if (fn_include_list.find(fn)==fn_include_list.end()) {
+		std::ifstream inputFile;
+		inputFile.open(fn.c_str(), std::ios::in);
+		if (!inputFile.is_open())
+			throw runtime_error("init-file cannot be opened for reading");
+		
+		fn_include_list.insert(fn);
+		read(inputFile);
+	}
+};
+
+/// Fill an initfile from an input stream
+void Initfile::read(istream& in) {
+	unsigned line_length= 256;
+	char swap[line_length];
+	in.getline(swap, line_length);
+	while (in.good()) {
+		std::string whitespaces= " \t\r\f";
+		std::string sw(swap);
+		size_t pos0= sw.find_first_not_of(whitespaces);
+		
+		if (pos0!=std::string::npos && sw[pos0]!='%' && sw[pos0]!='#' && sw[pos0]!=0) {
+		// parse line and extract map: tag->value
+			Parser parser(sw);
+			operator[](parser.name)= parser.value;
+		} else if (sw[pos0]=='#' && static_cast<size_t>(sw.find("#include"))==pos0) {
+		// include file by '#include "filename"' or '#include <filename>'
+			size_t pos= sw.find_first_not_of(whitespaces,std::string("#include").size()+1);
+			size_t epos= 0;
+			std::string fn= "";
+			std::stringstream errorMsg;
+			switch (char c= swap[pos++]) {
+			case '<':
+				c= '>';
+			case '\"':
+				whitespaces+= c;
+				epos= sw.find_first_of(whitespaces, pos);
+				fn= sw.substr(pos,epos-pos);
+			
+				if (sw[epos]!=c) {
+					errorMsg << "filename in #include not terminated by " << c;
+					throw std::runtime_error(errorMsg.str());
+				}
+				break;
+			default:
+				throw std::runtime_error("no filename given for #include");
+			}
+			read(fn);
+		}
+		in.getline(swap, line_length);
+	}
+};
+
+/// read standard values for output and information of parameter-values
+void Initfile::getInternalParameters() 
+{
+	int val= 10;
+	get("level of information", val, 0);
+	msgInfo= val;
+	
+	val= 1;
+	get("WAIT", val, 0);
+	msgWait= val;
+	
+	val= 1;
+	get("parameter information", val, 0);
+	paramInfo= val;
+	
+	if (msgInfo==0)
+		paramInfo= 0;
+};
+
+/// print all parameters to std::cout
+void Initfile::printParameters() {
+	initIntern();
+	Initfile::iterator it;
+	for (it= singlett->begin(); it!=singlett->end(); it++)
+		std::cout << (*it).first << " => " << (*it).second << std::endl;
+};
+
+/// Write data-map to initfile
+void Initfile::write(ostream& out) {
+	Initfile::iterator it;
+	for (it= begin() ; it!=end(); it++)
+		out << (*it).first << ": " << (*it).second << std::endl;
+	
+};
+
+/// Write data-map to initfile
+void Initfile::write(std::string fn) {
+	std::ofstream outFile;
+	outFile.open(fn.c_str(), std::ios::out);
+	if (!outFile.is_open())
+		throw runtime_error("init-file cannot be opened for writing");
+	
+	write(outFile);
+};
diff --git a/AMDiS/src/Initfile.h b/AMDiS/src/Initfile.h
new file mode 100644
index 00000000..5f815214
--- /dev/null
+++ b/AMDiS/src/Initfile.h
@@ -0,0 +1,378 @@
+#ifndef INITFILE_H
+#define INITFILE_H
+
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <map>
+#include <list>
+#include <set>
+#include <vector>
+#include <stdexcept>
+#include <iostream>
+#include <typeinfo>
+#include "FixVec.h"
+
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/lexical_cast.hpp>
+
+using namespace AMDiS;
+
+namespace InitfileInternal {
+	/// Exceptions
+    struct WrongVectorSize : std::runtime_error {
+		WrongVectorSize(std::string m):std::runtime_error(m) {}
+	};
+    struct NoDelim : std::runtime_error {
+		NoDelim(std::string m):std::runtime_error(m) {}
+	};
+    struct WrongVectorFormat : std::runtime_error {
+		WrongVectorFormat(std::string m):std::runtime_error(m) {}
+	};
+	template< typename T >
+    struct WrongValueFormat : std::runtime_error {
+		static std::string name(int ) { return "int"; }
+		static std::string name(bool ) { return "bool"; }
+		static std::string name(double ) { return "double"; }
+		static std::string name(unsigned int ) { return "unsigned int"; }
+		template< typename G >
+		static std::string name(G ) { return std::string(typeid(G).name()); }
+		
+		WrongValueFormat(std::string value): std::runtime_error(std::string("cannot convert '") + value + std::string("' into <")+ name(T())+">" ) 
+		{}
+
+	};
+	
+	/// trim std::string
+	inline std::string trim(const std::string& oldStr) {
+		std::string swap(oldStr);
+		boost::algorithm::trim(swap);
+		return swap;
+	}
+	/// return the delimiter or throw an exception if there is no known delimiter in value
+	size_t checkDelim(const std::string& value, const std::string& delims) {
+		size_t pos(std::string::npos);
+		for (unsigned i= 0; i<delims.length(); ++i) {
+			pos= value.find(delims[i]);
+			if (pos!=std::string::npos)
+				return i;
+		}
+		throw NoDelim("cannot detect the delimiter in " + value);
+		return 0; 
+	}
+
+
+	/** parse an container from tag tag. The Container must have the properties:
+	 * 	- type value_type
+	 * 	- member function push_back
+	 */
+	template< typename Container >
+	inline void getContainer(const std::string val_, Container& c) {
+		
+		// accepted brackets and delimiters for vector input
+		std::string begBrackets= "{[(";
+		std::string endBrackets= "}])";
+		std::string delims= ",;";
+
+		c.clear();
+		std::string val= trim(val_); 
+		size_t pos= begBrackets.find(val[0]);
+		if( pos == std::string::npos )
+			throw WrongVectorFormat("cannot convert '" + val + "' into a list. No leading bracket found!");
+		if( val[val.length() - 1] != endBrackets[pos] )
+			throw WrongVectorFormat("begin and end bracket are different in value '" + val + "'");
+		size_t oldPos= 1;
+		size_t curDelim= 0;
+		typedef typename Container::value_type ValueType;
+		ValueType swap;
+		try {
+			curDelim= checkDelim(val, delims);
+			pos= val.find(delims[curDelim], oldPos);
+			while( pos != std::string::npos ) {
+				std::string curWord= val.substr(oldPos, pos - 1);
+				oldPos= pos + 1;
+				convert(curWord, swap);
+				c.push_back(swap);
+				pos= val.find(delims[curDelim], oldPos);
+			}
+			//last entry
+			std::string curWord= val.substr(oldPos, val.length() - oldPos-1);
+			convert(curWord, swap);
+			c.push_back(swap);
+		} catch (NoDelim nd) {
+			std::string curWord= val.substr(1, val.length()-2);
+			curWord = trim(curWord);
+			if(curWord.length()>0) {
+			// container with one entry
+				convert(curWord, swap);
+				c.push_back(swap);
+			}
+		}
+	}
+
+	/// convert string to string
+	inline void convert(const std::string valStr, std::string& value) {
+		value= trim(valStr);
+	}
+
+	/// convert string to intrinsic type
+	template< typename T >
+	inline void convert(const std::string valStr, T& value) {
+		using boost::lexical_cast;
+		try {
+			value = lexical_cast< T >(trim(valStr));
+		}catch(boost::bad_lexical_cast e) {
+			throw WrongValueFormat< T >(valStr);
+		}
+	}
+	/// convert string to WorldVector
+	template< typename T >
+	inline void convert(const std::string valStr, WorldVector<T>& c) {
+		std::vector<T> temp_vec;
+		getContainer(valStr, temp_vec);
+		if (static_cast<int>(temp_vec.size())!=c.getSize())
+			throw WrongVectorSize("wrong number of entries for WorldVector");
+		
+		for (unsigned i= 0; i<temp_vec.size(); ++i)
+			c[i]= temp_vec[i];
+	}
+
+	/// convert string to std::list using begBrackets, endBrackets and delims
+	template< typename T >
+	inline void convert(const std::string valStr, std::list< T >& value) {
+		getContainer(valStr, value);
+	}
+
+	/// convert string to std::vector using begBrackets, endBrackets and delims
+	template< typename T >
+	inline void convert(const std::string valStr, std::vector< T >& value) {
+		getContainer(valStr, value);
+	}
+
+	/// convert value of arbitrary type to string using stringstream and operator<< for type
+	template< typename T >
+	inline void convert(const T value, std::string& valStr) {
+		std::stringstream ss;
+		ss << value;
+		valStr= ss.str();
+	}
+	/// convert WorldVector to string
+	template< typename T >
+	inline void convert(const WorldVector<T>& c, std::string& valStr) {
+		std::vector<T> temp_vec(c.getSize());
+		for (unsigned i= 0; i<temp_vec.size(); ++i)
+			temp_vec[i]= c[i];
+		convert(temp_vec, valStr);
+	}
+} // end namespace InitfileInternal
+
+/** The entry in an initfile. This helper class was constructed to allow calls like
+ *  val = data.get(tag)
+ *  for arbitrary types of val. At current stage, only double and bool is supported
+ */
+
+struct InitEntry {
+	///the value as string
+	std::string valStr;
+
+	/// initialize with value as string
+	InitEntry(std::string v= ""):
+		valStr(v) {}
+
+	/// cast string to type T
+	template< typename T >
+	operator T() const { T t; convert(valStr, t); return t;}
+};
+
+/// output-stream for std::list
+template< typename T >
+std::ostream& operator<<(std::ostream& o, const std::list< T >& l) {
+	typename std::list< T >::const_iterator it= l.begin();
+	o << "[";
+	for(unsigned i= 0; it!=l.end() && i<l.size(); ++i) {
+		o << *it << (i<l.size()-1?", ":"");
+		++it;
+	}
+	o << "]";
+	return o;
+}
+/// output-stream for std::vector
+template< typename T >
+std::ostream& operator<<(std::ostream& o, const std::vector< T >& l) {
+	typename std::vector< T >::const_iterator it= l.begin();
+	o << "[";
+	for(unsigned i= 0; it!=l.end() && i<l.size(); ++i) {
+		o << *it << (i<l.size()-1?", ":"");
+		++it;
+	}
+	o << "]";
+	return o;
+}
+
+/** Basis data container as a map of tag on a value as strings. The container throws an exception, if the tag was not found.
+ */
+struct Initfile : public std::map< std::string, std::string > {
+	typedef std::map< std::string, std::string > super;
+
+	/// Exceptions
+    struct TagNotFound : std::invalid_argument {
+		TagNotFound(std::string m):std::invalid_argument(m) {}
+	};
+		
+	/** initialize init-file from file with filename in, read data and save it to singleton-map
+	 * @param in: filename string
+	 */
+	static void init(std::string in);
+	
+	/** Static get routine for getting parameter-values from init-file initialized in init()-method.
+	 * Cast the value to the desired type using std::stringstream.
+	 * @param tag: The tag to look for
+	 * @param value: The result.
+	 * @param debug_info: msgInfo for current parameter. (0..no printing, 1..print missing parameter info, 2..print parameter value) [optional]
+	 */
+	template< typename T >
+	static void get(const std::string tag, T& value, int debug_info= -1) {
+	using namespace InitfileInternal;
+		initIntern();
+		if (debug_info==-1)
+			debug_info= singlett->getMsgInfo();
+		
+		try {
+			std::string valStr(singlett->checkedGet(tag));
+			valStr= trim(valStr);
+			convert(valStr, value);
+			if (debug_info==2)
+				std::cout << "Parameter '" << tag << "' initialized with: " << value << std::endl;
+		} catch (TagNotFound ia) {
+			if (debug_info>=1)
+				std::cout << ia.what() << std::endl;
+		}
+	}
+	/// return InitEntry object for tag tag
+	static InitEntry get(const std::string tag) {
+	using namespace InitfileInternal;
+		int debug_info= singlett->getMsgInfo();
+		InitEntry result;
+		try {
+			std::string valStr(singlett->checkedGet(tag));
+			valStr= trim(valStr);
+			result= InitEntry(valStr);
+		} catch (TagNotFound ia) {
+			if (debug_info>=1)
+				std::cout << ia.what() << std::endl;
+		}
+		return result;
+	}
+	
+	/// update map tag->value_old to tag->value in singleton
+	template< typename T >
+	static void set(const std::string tag, T& value, int debug_info= -1) {
+	using namespace InitfileInternal;
+		initIntern();
+		if (debug_info==-1)
+			debug_info= singlett->getMsgInfo();
+		
+		std::string swap= "";
+		convert(value, swap);
+		(*singlett)[trim(tag)]= swap;
+		// update msg parameters msgInfo, msgWait, paramInfo
+		singlett->getInternalParameters();
+		if (debug_info==2)
+			std::cout << "Parameter '" << tag << "' set to: " << value << std::endl;
+	}
+	
+	/// add map tag->value to data in singleton
+	template< typename T >
+	static void add(const std::string tag, T& value, int debug_info= -1) {
+		set(tag, value, debug_info);
+	}
+
+	/// Returns specified info level
+	static int getMsgInfo() 
+	{ 
+		return (singlett!=NULL) ? singlett->msgInfo : 0; 
+	}
+
+	/// Returns specified wait value
+	static int getMsgWait() 
+	{ 
+		return (singlett!=NULL) ? singlett->msgWait : 0; 
+	}
+	
+	/// Checks whether parameters are initialized. if not, call init()
+	static bool initialized() 
+	{ 
+		return (singlett!=NULL); 
+	}
+
+	/// return pointer to singleton
+	static Initfile *getSingleton() 
+	{ 
+		return singlett; 
+	}
+	
+	/// print all data in singleton to std::cout
+	static void printParameters();
+
+	/// clear data in singleton
+	static void clearData()
+	{
+		initIntern();
+		singlett->clear();
+	}
+	
+	/// save singlett-data to file with filename fn
+	static void save(std::string fn)
+	{
+		initIntern();
+		singlett->write(fn);
+	}
+	
+protected:	
+	Initfile() : msgInfo(10), msgWait(1), paramInfo(1) {}
+	
+	static void initIntern() {
+		if (singlett == NULL)
+			singlett= new Initfile;
+	}
+
+	/// list of processed files
+	static std::set< std::string > fn_include_list;
+
+	/// pointer to the singleton that contains the data
+	static Initfile* singlett;
+	
+	/// return the value of the given tag or throws an exception if the tag does not exist
+	std::string checkedGet(const std::string& tag) const {
+		super::const_iterator it= find(tag);
+		if (it==end())
+			throw TagNotFound("there is no tag '"+ tag + "'");
+		return it->second;
+	}
+
+	/** Fill the initfile from an input stream.
+	* @param in: the stream to fill the data from.
+	* Current dataformat: tag:value
+	* Comment char: percent '%'
+	* Include files: #include "filename" or #include <filename>
+	*/
+	void read(std::istream& in);
+
+	/// Fill the initfile from a file with filename fn
+	void read(std::string fn);
+	
+	/** Write data-map to initfile
+	* @param out: the stream to fill the data in.
+	*/
+	void write(std::ostream& out);
+
+	/// Write data-map to initfile with filename fn
+	void write(std::string fn);
+	
+	/// read parameters for msgInfo, msgWait, paramInfo
+	void getInternalParameters();
+	
+	int msgInfo, msgWait, paramInfo;
+	
+};
+#endif
diff --git a/AMDiS/src/Parameters.cc b/AMDiS/src/Parameters.cc
index 2d887ebb..dc003fa0 100644
--- a/AMDiS/src/Parameters.cc
+++ b/AMDiS/src/Parameters.cc
@@ -340,41 +340,41 @@ namespace AMDiS {
       return(key);
 
     if (s[pos] == '#') {
-      if (static_cast<int>(s.find("#include")) == pos) {
-	/****************************************************************************/
-	/*  another init file has to be included                                    */
-	/****************************************************************************/
-
-	pos += strlen("#include");
-	pos = s.find_first_not_of(" \t\f\r");
-
-	i = 0;
-	switch (c = s[pos++]) {
-	case '<':
-	  c = '>';
-	case '\"':
-	  h += c;
-	  epos = s.find_first_not_of(h, pos);
-	  fn = s.substr(pos,epos-1);
-       
-	  if (s[epos] != c) {
-	    ERROR("aFilename of include not terminated by %c\n", c);
-	    ERROR("skipping line %d of file %s\n", nLine, aFilename.c_str());
-	    return("");
-	  }
-	  break;
-	default:
-	  ERROR("no aFilename of include file found\n");
-	  ERROR("skipping line %d of file %s\n", nLine, aFilename.c_str());
-	  return("");
-	}
-
-	read(fn);
-	return("");
-      } else {
-	ERROR("# must not be the first character on a line; except #include\n");
-	return("");
-      }
+//       if (static_cast<int>(s.find("#include")) == pos) {
+// 	/****************************************************************************/
+// 	/*  another init file has to be included                                    */
+// 	/****************************************************************************/
+// 
+// 	pos += strlen("#include");
+// 	pos = s.find_first_not_of(" \t\f\r");
+// 
+// 	i = 0;
+// 	switch (c = s[pos++]) {
+// 	case '<':
+// 	  c = '>';
+// 	case '\"':
+// 	  h += c;
+// 	  epos = s.find_first_not_of(h, pos);
+// 	  fn = s.substr(pos,epos-1);
+//        
+// 	  if (s[epos] != c) {
+// 	    ERROR("aFilename of include not terminated by %c\n", c);
+// 	    ERROR("skipping line %d of file %s\n", nLine, aFilename.c_str());
+// 	    return("");
+// 	  }
+// 	  break;
+// 	default:
+// 	  ERROR("no aFilename of include file found\n");
+// 	  ERROR("skipping line %d of file %s\n", nLine, aFilename.c_str());
+// 	  return("");
+// 	}
+// 
+// 	read(fn);
+// 	return("");
+//       } else {
+// 	ERROR("# must not be the first character on a line; except #include\n");
+// 	return("");
+//       }
     }
 
     /****************************************************************************/
-- 
GitLab