diff --git a/src/Makefile.dep b/src/Makefile.dep index 9908373..75fa86b 100755 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,7 +1,7 @@ # DO NOT DELETE -edanticitem.o: item.h -edanticpattern.o: pattern.h item.h stringconv.h utf8.h +edanticitem.o: item.h funinfo.h +edanticpattern.o: pattern.h item.h funinfo.h functions.h stringconv.h utf8.h edanticpattern.o: /home/tomek/roboczy/winix/core/log.h edanticpattern.o: /home/tomek/roboczy/winix/core/textstream.h edanticpattern.o: /home/tomek/roboczy/winix/core/misc.h diff --git a/src/functions.h b/src/functions.h index dcbcbba..452a4f4 100755 --- a/src/functions.h +++ b/src/functions.h @@ -40,7 +40,7 @@ #include #include "funinfo.h" - +#include "stringconv.h" namespace Ezc @@ -87,8 +87,7 @@ public: bool Find(const std::string & key, Function ** fun); bool Find(const std::wstring & key, Function ** fun); void Clear(); - size_t Size(); - + size_t Size() const; private: typedef std::map FunctionsTable; @@ -99,9 +98,6 @@ private: - - - template Functions::Function::Function() { @@ -246,13 +242,15 @@ void Functions::Clear() } + template -size_t Functions::Size() +size_t Functions::Size() const { return functions_tab.size(); } + } // namespace Ezc diff --git a/src/generator.h b/src/generator.h index 1e42eed..665651d 100755 --- a/src/generator.h +++ b/src/generator.h @@ -48,8 +48,7 @@ namespace Ezc { /* StreamType - we use method write where the content should not be escaped (html escaping) - we use operator<< where the content can be escaped (such as error messages) + we use only method write(const wchar_t * str, size_t len) from the stream */ template class Generator @@ -57,12 +56,7 @@ class Generator public: Generator(); - Generator(StreamType & o, Pattern & p, Functions & f); - void Set(StreamType & o, Pattern & p, Functions & f); - void Set(StreamType & o); - void Set(Pattern & p); - void Set(Functions & f); void SetMax(int max_items_, int max_for_items_); // recognizing some special characters in text patterns (item_text in Patterns) @@ -86,8 +80,12 @@ public: // default: false void SkipNewLine(bool skip); - // the main method for generating - void Generate(); + // the main methods for generating + void Generate(StreamType & o, Pattern & p, Functions & f); + + // this method is used only if the pattern has cached functions + void Generate(StreamType & o, Pattern & p); + private: @@ -111,11 +109,10 @@ private: const std::wstring empty; - bool Find(const std::wstring & key, typename Functions::Function ** function); + bool Find(const Item::Function & item_fun, typename Functions::Function ** function); void Call(typename Functions::Function * function, FunInfo & info); - bool Call(const std::wstring & name, FunInfo & info, typename Functions::Function ** pfun = 0); - bool Call(typename Item::Function & function, bool * info_res = 0, typename Functions::Function ** pfun = 0); + bool Call(Item::Function & function, bool * info_res = 0, typename Functions::Function ** pfun = 0); void CallUserFunction(typename Functions::Function * function, FunInfo & info); void CallVariable(typename Functions::Function * function, FunInfo & info); @@ -128,9 +125,10 @@ private: void SkipWhite(const wchar_t *& str); int StrToInt(const wchar_t * str, const wchar_t ** str_end); - void CreateMsg(StreamType & o, const wchar_t * type, const wchar_t * arg = 0); - void CreateMsg(StreamType & o, const std::wstring & type, const std::wstring & arg); - void CreateMsg(StreamType & o, const std::wstring & type); + void CreateMsg(const wchar_t * type, const wchar_t * arg = 0); + void CreateMsg(const std::wstring & type, const std::wstring & arg); + void CreateMsg(const std::wstring & type); + void CreateUnknownMsg(const std::wstring & fun); void MakeTextIf_go(Item & item, bool result); bool MakeTextIfindexnumber(Item & item, typename Functions::Function * function, bool & result); @@ -173,49 +171,6 @@ Generator::Generator() } -template -Generator::Generator(StreamType & o, Pattern & p, Functions & f) -{ - output_stream = &o; - pattern = &p; - functions = &f; - - max_items = 50000; - max_for_items = 5000; - special_chars = false; - trim_white = false; - skip_new_line = false; -} - - -template -void Generator::Set(StreamType & o, Pattern & p, Functions & f) -{ - output_stream = &o; - pattern = &p; - functions = &f; -} - - -template -void Generator::Set(StreamType & o) -{ - output_stream = &o; -} - - -template -void Generator::Set(Pattern & p) -{ - pattern = &p; -} - - -template -void Generator::Set(Functions & f) -{ - functions = &f; -} template @@ -248,10 +203,25 @@ void Generator::SkipNewLine(bool skip) template -void Generator::Generate() +void Generator::Generate(StreamType & o, Pattern & p, Functions & f) { - if( !output_stream || !pattern || !functions ) - return; + output_stream = &o; + pattern = &p; + functions = &f; + + break_generating = false; + current_item = 0; + + MakeText( pattern->item_root ); +} + + +template +void Generator::Generate(StreamType & o, Pattern & p) +{ + output_stream = &o; + pattern = &p; + functions = 0; break_generating = false; current_item = 0; @@ -263,12 +233,27 @@ void Generator::Generate() + template -bool Generator::Find(const std::wstring & key, typename Functions::Function ** function) +bool Generator::Find(const Item::Function & item_fun, typename Functions::Function ** function) { - if( !functions->Find(key, function) ) + if( !functions ) { - CreateMsg(*output_stream, L"can't find", key.c_str() ); + if( item_fun.fun_cache ) + { + *function = reinterpret_cast::Function*>(item_fun.fun_cache); + return true; + } + else + { + CreateUnknownMsg(item_fun.name); + return false; + } + } + + if( !functions->Find(item_fun.name, function) ) + { + CreateUnknownMsg(item_fun.name); return false; } @@ -276,14 +261,13 @@ return true; } - template void Generator::CallUserFunction(typename Functions::Function * function, FunInfo & info) { if( function->is_running ) { // recurrences are not allowed - CreateMsg(*output_stream, L"the function is being executed"); + CreateMsg(L"the function is being executed"); return; } @@ -315,53 +299,52 @@ void Generator::Call(typename Functions::Function * func } -// return: true if a function or variable was found and called -template -bool Generator::Call(const std::wstring & name, FunInfo & info, typename Functions::Function ** pfun) -{ -typename Functions::Function * function; - - if( Find(name, &function) ) - { - Call(function, info); - - if( pfun ) - *pfun = function; - - return true; - } - -return false; -} // return: true if a function or variable was found and called template -bool Generator::Call(typename Item::Function & function, bool * info_res, typename Functions::Function ** pfun) +bool Generator::Call(Item::Function & item_fun, bool * info_res, typename Functions::Function ** pfun) { -bool called; +typename Functions::Function * fun; +bool called = false; - if( function.params.empty() ) + if( item_fun.params.empty() ) { - FunInfo info(*output_stream, function.params, empty); - called = Call(function.name, info, pfun); + FunInfo info(*output_stream, item_fun.params, empty); + + if( Find(item_fun, &fun) ) + { + Call(fun, info); + called = true; + } if( info_res ) *info_res = info.res; } else { - FunInfo info(*output_stream, function.params, function.params[0]); - called = Call(function.name, info, pfun); + FunInfo info(*output_stream, item_fun.params, item_fun.params[0]); + + if( Find(item_fun, &fun) ) + { + Call(fun, info); + called = true; + } if( info_res ) *info_res = info.res; } + if( called && pfun ) + *pfun = fun; + return called; } + + + template wchar_t Generator::CreateSpecialChar(wchar_t c) { @@ -520,30 +503,35 @@ return res; template -void Generator::CreateMsg(StreamType & o, const wchar_t * type, const wchar_t * arg) +void Generator::CreateMsg(const wchar_t * type, const wchar_t * arg) { pattern->CreateMsg(temp_msg, type, arg); - o << temp_msg; - temp_msg.clear(); + output_stream->write(temp_msg.c_str(), temp_msg.size()); } template -void Generator::CreateMsg(StreamType & o, const std::wstring & type, const std::wstring & arg) +void Generator::CreateMsg(const std::wstring & type, const std::wstring & arg) { - CreateMsg(o, type.c_str(), arg.c_str()); + CreateMsg(type.c_str(), arg.c_str()); } template -void Generator::CreateMsg(StreamType & o, const std::wstring & type) +void Generator::CreateMsg(const std::wstring & type) { - CreateMsg(o, type.c_str()); + CreateMsg(type.c_str()); } +template +void Generator::CreateUnknownMsg(const std::wstring & fun) +{ + CreateMsg(L"unknown function", fun.c_str()); +} + @@ -770,7 +758,7 @@ bool Generator::MakeTextIfindexnumber(Item & item, typename Function if( *last_char != '\0' ) { - CreateMsg(*output_stream, L"if-index: syntax error"); + CreateMsg(L"if-index: syntax error"); return false; } @@ -792,7 +780,7 @@ void Generator::MakeTextIfindex(Item & item) typename Functions::Function * function; - if( !Find(item.functions[0].name, &function) ) + if( !Find(item.functions[0], &function) ) return; bool result = false; @@ -832,7 +820,7 @@ bool info_res; { if( function->iter >= max_for_items ) { - CreateMsg(*output_stream, item.functions[0].name.c_str(), + CreateMsg(item.functions[0].name.c_str(), L"function exceeded a limit for a [for] statement"); break; } @@ -856,12 +844,12 @@ void Generator::MakeTextFor(Item & item) typename Functions::Function * function; - if( !Find(item.functions[0].name, &function) ) + if( !Find(item.functions[0], &function) ) return; if( function->is_for ) { - CreateMsg(*output_stream, item.functions[0].name.c_str(), + CreateMsg(item.functions[0].name.c_str(), L"this function is already used in a [for] statement"); return; } @@ -880,6 +868,12 @@ void Generator::MakeTextFor(Item & item) template void Generator::MakeTextDefine(Item & item) { + if( !functions ) + { + CreateMsg(L"def statement is not available when used without functions set"); + return; + } + if( item.functions.size() == 1 ) { // inserting a new variable @@ -891,7 +885,7 @@ void Generator::MakeTextDefine(Item & item) { typename Functions::Function * function; - if( Find(item.functions[1].name, &function) ) + if( Find(item.functions[1], &function) ) { if( function->type == Functions::function ) { @@ -919,7 +913,7 @@ void Generator::MakeText(Item & item) if( ++current_item > max_items ) { break_generating = true; - CreateMsg(*output_stream, L"Generator exceeded allowed number of elements"); + CreateMsg(L"Generator exceeded allowed number of elements"); return; } @@ -938,7 +932,7 @@ void Generator::MakeText(Item & item) else if( item.type == Item::item_for ) MakeTextFor(item); else if( item.type == Item::item_def ) MakeTextDefine(item); else if( item.type == Item::item_err ) - CreateMsg(*output_stream, L"a wrong directive"); + CreateMsg(L"a wrong directive"); } diff --git a/src/item.h b/src/item.h index 1c531d5..e577b3f 100755 --- a/src/item.h +++ b/src/item.h @@ -41,6 +41,7 @@ #include #include +#include "funinfo.h" namespace Ezc @@ -61,6 +62,12 @@ struct Item { std::wstring name; // function name std::vector params; // function parameters + void * fun_cache; + + Function() + { + fun_cache = 0; + } }; Type type; diff --git a/src/pattern.cpp b/src/pattern.cpp index 441b8eb..2176378 100755 --- a/src/pattern.cpp +++ b/src/pattern.cpp @@ -38,9 +38,6 @@ #include "pattern.h" -#ifdef EZC_USE_WINIX_LOGGER -#include "core/log.h" -#endif namespace Ezc @@ -70,6 +67,22 @@ void Pattern::Clear() } +void Pattern::ClearCache() +{ + ClearCache(item_root); +} + + +void Pattern::ClearCache(Item & item) +{ + for(size_t f = 0; f < item.functions.size() ; ++f) + item.functions[f].fun_cache = 0; + + for(size_t i = 0; i < item.item_tab.size() ; ++i) + ClearCache(*item.item_tab[i]); +} + + void Pattern::Directory(const char * dir, const char * dir2) { @@ -77,17 +90,17 @@ void Pattern::Directory(const char * dir, const char * dir2) directory2.clear(); if( dir ) - AssignString(dir, directory); + UTF8ToWide(dir, directory); if( dir2 ) - AssignString(dir2, directory2); + UTF8ToWide(dir2, directory2); } void Pattern::Directory(const std::string & dir) { - AssignString(dir, directory); + UTF8ToWide(dir, directory); directory2.clear(); } @@ -95,8 +108,8 @@ void Pattern::Directory(const std::string & dir) void Pattern::Directory(const std::string & dir, const std::string & dir2) { - AssignString(dir, directory); - AssignString(dir2, directory2); + UTF8ToWide(dir, directory); + UTF8ToWide(dir2, directory2); } @@ -141,7 +154,7 @@ void Pattern::ParseFile(const std::string & file_name) void Pattern::ParseFile(const char * file_name) { - AssignString(file_name, item_root.file_name); + UTF8ToWide(file_name, item_root.file_name); include_level = 0; CreateTreeReadIncludeSkipAllowFlag(item_root); } @@ -169,7 +182,11 @@ void Pattern::ParseFile(const wchar_t * file_name) void Pattern::ParseString(const char * str) { - AssignString(str, string_content); + if( input_as_utf8 ) + UTF8ToWide(str, string_content); + else + AssignString(str, string_content); + ParseString(string_content.c_str()); string_content.clear(); } @@ -243,16 +260,16 @@ void Pattern::UTF8(bool utf8) void Pattern::SetCommentary(const char * com_start, const char * com_stop) { - AssignString(com_start, commentary_start); - AssignString(com_stop, commentary_stop); + UTF8ToWide(com_start, commentary_start); + UTF8ToWide(com_stop, commentary_stop); } void Pattern::SetCommentary(const std::string & com_start, const std::string & com_stop) { - AssignString(com_start, commentary_start); - AssignString(com_stop, commentary_stop); + UTF8ToWide(com_start, commentary_start); + UTF8ToWide(com_stop, commentary_stop); } @@ -275,23 +292,6 @@ void Pattern::SetCommentary(const std::wstring & com_start, const std::wstring & - -void Pattern::CreateMsg(std::wstring & out, const char * type, const char * arg) -{ - out = commentary_start; - out += L"Ezc: "; - AssignString(type, out, false); - - if( arg ) - { - out += ' '; - AssignString(arg, out, false); - } - - out += commentary_stop; -} - - void Pattern::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg) { out = commentary_start; @@ -409,12 +409,15 @@ bool Pattern::ReadFileFromDir(const std::wstring & dir, const wchar_t * name, st return false; } - ReadFile(file, result); - #ifdef EZC_USE_WINIX_LOGGER - log << log3 << "Ezc: read pattern: " << afile_name << logend; + if( include_level <= 1 ) + log << log3 << "Ezc: reading pattern: " << afile_name << logend; + else + log << log3 << " including pattern: " << afile_name << logend; #endif + ReadFile(file, result); + file_name.clear(); afile_name.clear(); diff --git a/src/pattern.h b/src/pattern.h index 82e7c24..4109f13 100755 --- a/src/pattern.h +++ b/src/pattern.h @@ -41,9 +41,13 @@ #include #include "item.h" +#include "functions.h" #include "stringconv.h" #include "utf8.h" +#ifdef EZC_USE_WINIX_LOGGER +#include "core/log.h" +#endif namespace Ezc @@ -98,14 +102,18 @@ public: void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop); void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop); - void CreateMsg(std::wstring & out, const char * type, const char * arg = 0); void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0); static bool IsWhite(wchar_t c); - - Item item_root; + template + void CacheFunctions(Functions & fun) + { + CacheFunctions(item_root, fun); + } + + void ClearCache(); private: @@ -203,6 +211,39 @@ private: void CreateTreeReadInclude(Item & item); void CreateTreeReadIncludeSkipAllowFlag(Item & item); + + template + void CacheFunctions(Item & item, Functions & fun) + { + typename Functions::Function * ezc_fun; + + for(size_t f = 0; f < item.functions.size() ; ++f) + { + if( fun.Find(item.functions[f].name, &ezc_fun) ) + { + item.functions[f].fun_cache = ezc_fun; + } + else + { + item.functions[f].fun_cache = 0; + + #ifdef EZC_USE_WINIX_LOGGER + log << log1 << "Ezc: unknown function: " << item.functions[f].name << logend; + #endif + } + + // one exception (if_index is putting its argument on the functions stack) + if( item.type == Item::item_ifindex ) + break; + } + + for(size_t i = 0; i < item.item_tab.size() ; ++i) + CacheFunctions(*item.item_tab[i], fun); + } + + + void ClearCache(Item & item); + }; // class Pattern