diff --git a/uppdev/cpp2/cpp.cpp b/uppdev/cpp2/cpp.cpp index 73aa84184..798f02ef0 100644 --- a/uppdev/cpp2/cpp.cpp +++ b/uppdev/cpp2/cpp.cpp @@ -83,43 +83,12 @@ String CppMacro::Expand(const Vector& p) const return r; } -String Cpp::Define(const char *s) +void Cpp::Define(const char *s) { - CParser p(s); - String id; - String r; - try { - if(!p.IsId()) - return Null; - id = p.ReadId(); - r << "#define " << id; - CppMacro& m = macro.GetAdd(id); - m.param.Clear(); - if(p.Char('(')) { - r << '('; - bool next = false; - while(p.IsId()) { - String pid = p.ReadId(); - if(next) - r << ", "; - r << pid; - m.param.Add(p.ReadId()); - p.Char(','); - next = true; - } - if(p.Char3('.', '.', '.')) { - m.variadic = true; - if(next) - r << ", "; - r << "..."; - } - p.Char(')'); - r << ')'; - } - m.body = p.GetPtr(); - } - catch(CParser::Error) {} - return r; + CppMacro m; + String id = m.Define(s); + if(id.GetCount()) + macro.GetAdd(id) = pick(m); } const char *Cpp::SkipString(const char *s) @@ -157,6 +126,12 @@ void Cpp::ParamAdd(Vector& param, const char *s, const char *e) } String Cpp::Expand(const char *s) +{ + Index notmacro; + return Expand(s, notmacro); +} + +String Cpp::Expand(const char *s, Index& notmacro) { StringBuffer r; while(*s) { @@ -177,12 +152,7 @@ String Cpp::Expand(const char *s) s++; String id(b, s); if(notmacro.Find(id) < 0) { - const CppMacro *m = NULL; - const Cpp *p = this; - while(!m && p) { - m = p->macro.FindPtr(id); - p = p->parent; - } + const CppMacro *m = macro.FindPtr(id); if(m && !id.StartsWith("__$allowed_on_")) { Vector param; const char *s0 = s; @@ -229,8 +199,6 @@ String Cpp::Expand(const char *s) id = '\x1a' + Expand(m->Expand(param)); notmacro.Trim(ti); } - else - notmacro.Add(id); } r.Cat(id); } @@ -251,37 +219,64 @@ String Cpp::Expand(const char *s) return r; } - -void Cpp::DoCpp(Stream& in, Index& header) +bool Cpp::Preprocess(const String& sourcefile, Stream& in, const String& currentfile) { + macro.Clear(); Vector ignorelist = Split("__declspec;__cdecl;" - "__out;__in;__inout;__deref_in;__deref_inout;__deref_out;" - "__AuToQuOtE;__xin;__xout;" - "$drv_group;$allowed_on_parameter", - ';'); + "__out;__in;__inout;__deref_in;__deref_inout;__deref_out;" + "__AuToQuOtE;__xin;__xout;" + "$drv_group;$allowed_on_parameter", + ';'); for(int i = 0; i < ignorelist.GetCount(); i++) macro.GetAdd(ignorelist[i]).variadic = true; - Do(in, header); + done = false; + incomment = false; + Index visited; + Do(NormalizePath(sourcefile), in, NormalizePath(currentfile), visited); + return done; } -void Cpp::Parse(StringBuffer& result) -{ - DDUMP(result.GetCount()); - String r = result; - _DBG_ SaveFile("c:/xxx/cpp/" + GetFileTitle(path) + ".hpp", r); - DDUMP(result.GetCount()); - StringStream ss(r); - DDUMP(result.GetCount()); - Upp::Parse(ss, Vector(), base, path, THISBACK(AddError)); -} - -void Cpp::Do(Stream& in, Index& header) +void Cpp::Do(const String& sourcefile, Stream& in, const String& currentfile, Index& visited) { + DDUMP(currentfile); + if(visited.Find(currentfile) >= 0 || visited.GetCount() > 20000) + return; + visited.Add(currentfile); + String current_folder = GetFileFolder(currentfile); + if(sourcefile != currentfile) { + const PPFile& pp = GetPPFile(currentfile); + pp.Dump(); + for(int i = 0; i < pp.item.GetCount() && !done; i++) { + const PPItem& m = pp.item[i]; + if(m.type == PP_DEFINE) { + if(m.macro.body.GetCount()) + macro.GetAdd(m.id) = clone(m.macro); + } + else + if(m.type == PP_INCLUDE) { + String s = GetIncludePath(m.id, current_folder, include_path); + if(s.GetCount()) + Do(sourcefile, in, s, visited); + } + else + if(m.type == PP_NAMESPACE) + namespace_stack.Add(m.id); + else + if(m.type == PP_NAMESPACE_END && namespace_stack.GetCount()) + namespace_stack.Drop(); + else + if(m.type == PP_USING) + namespace_using.FindAdd(m.id); + } + return; + } + incomment = false; StringBuffer result; result.Clear(); result.Reserve(16384); int lineno = 0; + bool incomment = false; while(!in.IsEof()) { String l = in.GetLine(); lineno++; @@ -291,46 +286,20 @@ void Cpp::Do(Stream& in, Index& header) l.Trim(l.GetLength() - 1); l.Cat(in.GetLine()); } - const char *s = l; - while(*s == ' ') - s++; - if(*s == '#') { - if(strncmp(s + 1, "define", 6) == 0) - result << Define(s + 7) << "\n"; + RemoveComments(l, incomment); + CParser p(l); + if(p.Char('#')) { + if(p.Id("define")) { + result.Cat(l + "\n"); + Define(p.GetPtr()); + } else { - result.Cat("\n"); - if(strncmp(s + 1, "include", 7) == 0) { - String hdr = Expand(s + 8); - String header_path = GetIncludePath(hdr); - if(path.GetCount() == 0) DLOG("Include file " << String(s + 8) << " not found"); - String include = String().Cat() << path << ':' << lineno << ':' << header_path; - if(path.GetCount() && header.Find(include) < 0) { - DLOG(">>> " << l << " -> " << header_path << LOG_BEGIN); - Parse(result); - header.Add(include); - Cpp cpp; - cpp.WhenError = Proxy(WhenError); - cpp.path = header_path; - cpp.filedir = GetFileFolder(header_path); - cpp.include_path = include_path; - cpp.parent = this; - DDUMP(cpp.macro.GetCount()); - FileIn in(header_path); - cpp.Do(in, header); - DLOG(path << ": " << cpp.macro); - DLOG("USED: " << cpp.usedmacro); - // TODO: caching, this is the place to retrieve used macro values - { RTIMING("Mixing macros"); - for(int i = 0; i < cpp.macro.GetCount(); i++) - macro.GetAdd(cpp.macro.GetKey(i)) = pick(cpp.macro[i]); - } - DDUMP(macro.GetCount()); - RTIMING("Mixing bases"); - for(int i = 0; i < cpp.base.GetCount(); i++) - base.GetAdd(cpp.base.GetKey(i)).AppendPick(cpp.base[i]); - DLOG("---" << LOG_END); - } - notmacro.Clear(); + result.Cat('\n'); + if(p.Id("include")) { + String hdr = Expand(p.GetPtr()); + String header_path = GetIncludePath(hdr, current_folder, include_path); + if(header_path.GetCount()) + Do(Null, NilStream(), header_path, visited); } } } @@ -340,29 +309,6 @@ void Cpp::Do(Stream& in, Index& header) while(el--) result.Cat("\n"); } - Parse(result); -} - -String Cpp::GetIncludePath(const char *s) -{ - while(IsSpace(*s)) - s++; - int type = *s; - if(type == '<' || type == '\"' || type == '?') { - s++; - String name; - if(type == '<') type = '>'; - while(*s != '\r' && *s != '\n') { - if(*s == type) { - if(type == '\"') { - String fn = NormalizePath(name, filedir); - if(FileExists(fn)) - return fn; - } - return GetFileOnPath(name, include_path, false); - } - name.Cat(*s++); - } - } - return Null; + done = true; + output = result; } diff --git a/uppdev/cpp2/cpp.h b/uppdev/cpp2/cpp.h index 454dd9a58..4e40a318f 100644 --- a/uppdev/cpp2/cpp.h +++ b/uppdev/cpp2/cpp.h @@ -7,6 +7,8 @@ using namespace Upp; +void RemoveComments(String& l, bool& incomment); + struct CppMacro : Moveable, DeepCopyOption { String body; Index param; @@ -37,7 +39,7 @@ struct PPItem { CppMacro macro; }; -struct PPFile { +struct PPFile { // contains "macro extract" of file, only info about macros defined and namespaces FileTime filetime; Array item; Index includes; @@ -54,52 +56,32 @@ const PPFile& GetPPFile(const char *path); String GetIncludePath(const String& s, const String& filedir, const String& include_path); -bool IncludesFile(const String& include, const String& path, const String& include_path); +bool IncludesFile(const String& parent_path, const String& header_path, const String& include_path); struct Cpp { bool incomment; + bool done; - String path; - String filedir; String include_path; - Index header; VectorMap macro; + + String output; Index usedmacro; - Index notmacro; + Index namespace_using; + Vector namespace_stack; - CppBase base; - - Cpp *parent; - - void SyncSet(); - - String Define(const char *s); + void Define(const char *s); static const char *SkipString(const char *s); - void ParamAdd(Vector& param, const char *b, const char *e); - + void ParamAdd(Vector& param, const char *b, const char *e); + String Expand(const char *s, Index& notmacro); String Expand(const char *s); - void Include(const char *s); - String GetIncludePath(const char *s); - - void Parse(StringBuffer& result); + void Do(const String& sourcefile, Stream& in, const String& currentfile, Index& visited); - void Do(Stream& in, Index& header); - void DoCpp(Stream& in, Index& header); - - Callback3 WhenError; - - void AddError(int ln, const String& s) { WhenError(path, ln, s); } - - Cpp() { parent = NULL; } + bool Preprocess(const String& sourcefile, Stream& in, const String& currentfile); typedef Cpp CLASSNAME; }; -String Preprocess(const String& filename, const String& include_path); - -String Preprocess(const String& sourcefile, Stream& in, const String& surrogatefile, - const String& include_path); - #endif diff --git a/uppdev/cpp2/cpp.txt b/uppdev/cpp2/cpp.txt index 30d1625e9..501a6bbaf 100644 --- a/uppdev/cpp2/cpp.txt +++ b/uppdev/cpp2/cpp.txt @@ -1,16 +1 @@ -%'\1'%"\2"% -%1 +1%3% -%"1" "2" ","%','% -"a" -"a x y" -"\"A\"" -a3 -3a -a# -a"X" -"Y""X" -x -haha -haha ble -alfa xy.r #hahaha \ No newline at end of file diff --git a/uppdev/cpp2/cpp2.upp b/uppdev/cpp2/cpp2.upp index c2f81fd36..cfbb160b5 100644 --- a/uppdev/cpp2/cpp2.upp +++ b/uppdev/cpp2/cpp2.upp @@ -4,7 +4,6 @@ uses file cpp.h, - expand.cpp, ppfile.cpp, cpp.cpp, main.cpp, diff --git a/uppdev/cpp2/expand.cpp b/uppdev/cpp2/expand.cpp deleted file mode 100644 index 25633d86a..000000000 --- a/uppdev/cpp2/expand.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "cpp.h" - -#if 0 -String MacroExpand(const char *s, ArrayMap& macro, Index& notmacro, - bool& incomment) -{ - StringBuffer r; - while(*s) { - if(incomment) { - if(s[0] == '*' && s[1] == '/') { - incomment = false; - s += 2; - r.Cat("*/"); - } - else - r.Cat(*s++); - } - else - if(iscib2(*s)) { - const char *b = s; - s++; - while(iscid2(*s)) - s++; - String id(b, s); - if(notmacro.Find(id) < 0) { - const CppMacro *m = macro.FindPtr(id); - if(m && !id.StartsWith("__$allowed_on_")) { - Vector param; - const char *s0 = s; - while(*s && (byte)*s <= ' ') - s++; - if(*s == '(') { - s++; - const char *b = s; - int level = 0; - for(;;) - if(*s == ',' && level == 0) { - ParamAdd(param, b, s); - s++; - b = s; - } - else - if(*s == ')') { - s++; - if(level == 0) { - ParamAdd(param, b, s - 1); - break; - } - level--; - } - else - if(*s == '(') { - s++; - level++; - } - else - if(*s == '\0') - break; - else - if(*s == '\"' || *s == '\'') - s = SkipString(s); - else - s++; - } - else - s = s0; // otherwise we eat spaces after parameterless macro - usedmacro.FindAdd(id); - int ti = notmacro.GetCount(); - notmacro.Add(id); - id = '\x1a' + Expand(m->Expand(param)); - notmacro.Trim(ti); - } - else - notmacro.Add(id); - } - r.Cat(id); - } - else - if(s[0] == '/' && s[1] == '*') { - incomment = true; - s += 2; - r.Cat("/*"); - } - else - if(s[0] == '/' && s[1] == '/') { - r.Cat(s); - break; - } - else - r.Cat(*s++); - } - return r; -} -#endif \ No newline at end of file diff --git a/uppdev/cpp2/main.cpp b/uppdev/cpp2/main.cpp index 7ad747ac7..036106f01 100644 --- a/uppdev/cpp2/main.cpp +++ b/uppdev/cpp2/main.cpp @@ -12,42 +12,18 @@ String include_path = "C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\Vc\\Include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Include;C:\\u\\OpenSSL-Win32\\include;C:\\u\\pgsql\\include;C:\\Program Files (x86)\\MySQL\\MySQL Connector C 6.1\\include;" ";c:/u/upp.src/uppsrc"; -void Test(const char *path) +void Test(const char *sourcefile, const char *currentfile) { - DDUMP(sizeof(CppItem)); + DDUMP(sourcefile); + DDUMP(currentfile); Cpp cpp; - cpp.WhenError = callback(AddError); - cpp.path = path; - cpp.filedir = GetFileFolder(path); -// cpp.include_path = cpp.filedir;//"C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include;C:\\OpenSSL-Win32\\include;C:\\u\\pgsql\\include;C:\\u\\OpenSSL-Win32\\include"; - cpp.include_path << "C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include;C:\\OpenSSL-Win32\\include;C:\\u\\pgsql\\include;C:\\u\\OpenSSL-Win32\\include;"; - cpp.include_path << "C:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\Vc\\Include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Include;C:\\u\\OpenSSL-Win32\\include;C:\\u\\pgsql\\include;C:\\Program Files (x86)\\MySQL\\MySQL Connector C 6.1\\include;"; - cpp.include_path << ";c:/u/upp.src/uppsrc"; - FileIn in(path); - Index inc; - cpp.DoCpp(in, inc); -// StringStream ss(pp); -// Parse(ss, Vector() << "__cdecl", base, path, callback(AddError)); - DLOG("======================="); - DUMPC(cpp.macro.GetKeys()); - DLOG("======================="); - DUMPC(inc); - DLOG("======================="); - DUMPC(errs); - DLOG("======================="); - Qualify(cpp.base); - String out; - for(int i = 0; i < cpp.base.GetCount(); i++) { - out << Nvl(cpp.base.GetKey(i), "") << " {\n"; - const Array& ma = cpp.base[i]; - for(int j = 0; j < ma.GetCount(); j++) { - const CppItem& m = ma[j]; - out << '\t' << CppItemKindAsString(m.kind) << ' ' << m.qitem << ' ' << m.line << "\n"; - // DDUMP(StoreAsString(const_cast(m)).GetCount()); - } - out << "}\n"; - } - LOG(out); + cpp.include_path = include_path; + FileIn in(sourcefile); + DDUMP(cpp.Preprocess(sourcefile, in, currentfile)); + DDUMP(cpp.namespace_stack); + DDUMP(cpp.output); + DDUMP(cpp.usedmacro); + DLOG("================================="); } void RecursePP(const char *path, const char *include_path, Index& visited) @@ -66,6 +42,20 @@ void RecursePP(const char *path, const char *include_path, Index& visite p.Dump(); } +void TestC(const char *ln) +{ + for(int q = 0; q < 2; q++) { + bool incomment = q; + String l = ln; + DDUMP(incomment); + LOG(l); + RemoveComments(l, incomment); + LOG(l); + LOG(incomment); + LOG("-----------------------"); + } +} + CONSOLE_APP_MAIN { StdLogSetup(LOG_FILE, NULL, 150000000); @@ -78,6 +68,25 @@ CONSOLE_APP_MAIN // f.Parse(in); // f.Dump(); + +// Test("c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp", "c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp"); +#if 0 + TestC("test"); + TestC("*/ test /*c2*/ /* comment"); + TestC(" */ test /*c2*/ a /* comment */"); + TestC(" */ test /*c2*/ a /*/* comment */"); + return; +#endif + { + RTIMING("Pass1"); + Test("C:\\u\\upp.src\\uppsrc\\Core\\Profile.h", "C:\\u\\upp.src\\uppsrc\\Core\\Format.cpp"); + } + if(0) { + RTIMING("Pass2"); + Test("C:\\u\\upp.src\\uppsrc\\Core\\Format.h", "C:\\u\\upp.src\\uppsrc\\Core\\Format.cpp"); + } + +#if 0 { RTIMING("Pass1"); Index visited; @@ -85,6 +94,7 @@ CONSOLE_APP_MAIN } DDUMP(IncludesFile("c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp", "c:/u/upp.src/uppsrc/Core/Core.h", include_path)); + DDUMP(IncludesFile("c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp", "c:/u/upp.src/uppsrc/Core/Core2.h", include_path)); for(int i = 0; i < 1000; i++) { RTIMING("IncludesFile true"); @@ -95,7 +105,7 @@ CONSOLE_APP_MAIN RTIMING("IncludesFile false"); IncludesFile("c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp", "c:/u/upp.src/uppsrc/Core/Core1.h", include_path); } - +#endif // GetPPFile(GetDataFile("test.h")).Dump(); return; } diff --git a/uppdev/cpp2/ppfile.cpp b/uppdev/cpp2/ppfile.cpp index 5d32a9b0b..1c2fbb3d1 100644 --- a/uppdev/cpp2/ppfile.cpp +++ b/uppdev/cpp2/ppfile.cpp @@ -1,5 +1,37 @@ #include "cpp.h" +void SetSpaces(String& l, int pos, int count) +{ + StringBuffer s = l; + memset(~s + pos, ' ', count); + l = s; +} + +void RemoveComments(String& l, bool& incomment) +{ + int q = -1; + int w = -1; + if(incomment) + q = w = 0; + else { + q = l.Find("/*"); + if(q >= 0) + w = q + 2; + } + while(q >= 0) { + int eq = l.Find("*/", w); + if(eq < 0) { + incomment = true; + SetSpaces(l, q, l.GetCount() - q); + return; + } + SetSpaces(l, q, eq + 2 - q); + incomment = false; + q = l.Find("/*"); + w = q + 2; + } +} + String CppMacro::Define(const char *s) { CParser p(s); @@ -42,13 +74,15 @@ void PPFile::Parse(Stream& in) bool was_using = false; bool was_namespace = false; int level = 0; + bool incomment = false; Vector namespace_block; - while(!in.IsEof()) { // TODO: Do comments... + while(!in.IsEof()) { String l = in.GetLine(); while(*l.Last() == '\\' && !in.IsEof()) { l.Trim(l.GetLength() - 1); l.Cat(in.GetLine()); } + RemoveComments(l, incomment); try { CParser p(l); if(p.Char('#')) {