diff --git a/uppdev/cpp/cpp.cpp b/uppdev/cpp/cpp.cpp index 81c473b70..d6a96addc 100644 --- a/uppdev/cpp/cpp.cpp +++ b/uppdev/cpp/cpp.cpp @@ -2,9 +2,7 @@ #include -#define LLOG(x) - -bool IsSpc(byte c) +inline bool IsSpc(byte c) { return c > 0 && c <= 32; } @@ -14,7 +12,7 @@ String CppMacro::ToString() const return String().Cat() << "(" << AsString(param) << ") " << body; } -String CppMacro::Expand(const Vector& p) +String CppMacro::Expand(const Vector& p) const { String r; const char *s = body; @@ -82,18 +80,18 @@ String CppMacro::Expand(const Vector& p) } r.Cat(*s++); } - LLOG("EXPAND: " << r); return r; } -void Cpp::Define(const char *s) +String Cpp::Define(const char *s) { CParser p(s); + String id; try { - String id; if(!p.IsId()) - return; - CppMacro& m = macro.GetAdd(p.ReadId()); + return Null; + id = p.ReadId(); + CppMacro& m = macro.GetAdd(id); m.param.Clear(); if(p.Char('(')) { while(p.IsId()) { @@ -107,6 +105,7 @@ void Cpp::Define(const char *s) m.body = p.GetPtr(); } catch(CParser::Error) {} + return "#define " + id; } const char *Cpp::SkipString(const char *s) @@ -140,7 +139,6 @@ void Cpp::ParamAdd(Vector& param, const char *s, const char *e) else h.Cat(*s++); } - LLOG("param: " << h); param.Add(h); } @@ -164,53 +162,59 @@ String Cpp::Expand(const char *s) while(IsAlNum(*s) || *s == '_') s++; String id(b, s); - int q = macro.Find(id); - if(q >= 0 && !macro[q].flag) { - LLOG("Expanding " << id); - 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; + if(notmacro.Find(id) < 0) { + const CppMacro *m = NULL; + for(int i = 0; i < macro_set.GetCount() && !m; i++) + m = macro_set[i]->FindPtr(id); + if(m) { + 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; } - level--; - } - else - if(*s == '(') { - s++; - level++; - } - else - if(*s == '\0') - break; - else - if(*s == '\"' || *s == '\'') - s = SkipString(s); - else - 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 + int ti = notmacro.GetCount(); + notmacro.Add(id); + usedmacro.FindAdd(id); + id = '\x1a' + Expand(m->Expand(param)); + notmacro.Trim(ti); } else - s = s0; // otherwise we eat spaces after parameterless macro - macro[q].flag = true; - r.Cat(Expand(macro[q].Expand(param))); - macro[q].flag = false; + notmacro.FindAdd(id); } - else - r.Cat(id); + r.Cat(id); } else if(s[0] == '/' && s[1] == '*') { @@ -229,8 +233,32 @@ String Cpp::Expand(const char *s) return r; } -String Cpp::Preprocess(Stream& in, bool needresult) +const VectorMap *GetFileMacros(const String& filepath) { + static ArrayMap cache; + Time last_write = FileGetTime(filepath); + CppMacroRecord& m = cache.GetAdd(filepath); + if(m.last_write != last_write) { + m.last_write = last_write; + Cpp cpp; + FileIn in(filepath); + m.includes.Clear(); + cpp.Do(in, m.includes); + m.macro = pick(cpp.macro); + } + return &m.macro; +} + +String Cpp::Do(Stream& in, Index& header) +{ + bool needresult = true; _DBG_ + + macro0.Add("__declspec").variadic = true; + macro0.Add("__cdecl").variadic = true; + macro_set.Add(¯o0); + + macro_set.Add(¯o); + incomment = false; StringBuffer result; result.Clear(); @@ -249,7 +277,7 @@ String Cpp::Preprocess(Stream& in, bool needresult) if(*s == '#') { result.Cat("\n"); if(strncmp(s + 1, "define", 6) == 0) - Define(s + 7); + result << Define(s + 7) << "\n"; else if(strncmp(s + 1, "undef", 5) == 0) { CParser p(s + 6); @@ -257,23 +285,25 @@ String Cpp::Preprocess(Stream& in, bool needresult) macro.UnlinkKey(p.ReadId()); } else - if(strncmp(s + 1, "include", 7) == 0 && level < 100) { + if(strncmp(s + 1, "include", 7) == 0) { String path = GetIncludePath(s + 8); - DDUMP(path); - if(path.GetCount()) { + if(path.GetCount() && header.Find(path) < 0) { + int lheader = header.GetCount(); + header.Add(path); Cpp inc; - inc.level = level + 1; - inc.filedir = filedir; + inc.filedir = GetFileFolder(path); inc.include_path = include_path; FileIn in(path); - inc.Preprocess(in, false); - inc.macro.Sweep(); - for(int i = 0; i < inc.macro.GetCount(); i++) - macro.GetAdd(inc.macro.GetKey(i)) = inc.macro[i]; + inc.Do(in, header); + macro_set.Drop(); + for(int i = lheader; i < header.GetCount(); i++) + macro_set.Add(GetFileMacros(header[i])); + macro_set.Add(¯o); + notmacro.Clear(); } } } - else + else { if(needresult) result.Cat(Expand(l) + "\n"); else { @@ -295,6 +325,7 @@ String Cpp::Preprocess(Stream& in, bool needresult) s++; } } + } if(needresult) while(el--) result.Cat("\n"); diff --git a/uppdev/cpp/cpp.h b/uppdev/cpp/cpp.h index 135e9e3fe..6846cfd44 100644 --- a/uppdev/cpp/cpp.h +++ b/uppdev/cpp/cpp.h @@ -3,30 +3,52 @@ #include +#include + using namespace Upp; struct CppMacro : Moveable { String body; Index param; bool variadic; - bool flag; // used when expanding macros to mark those use; MT incompatible (!) - String Expand(const Vector& p); + String Expand(const Vector& p) const; String ToString() const; - CppMacro() { flag = variadic = false; } + CppMacro() { variadic = false; } }; +struct CppMacroRecord { + Time last_write; + VectorMap macro; + Index includes; + + CppMacroRecord() { last_write = Time::Low(); } +}; + +const VectorMap *GetFileMacros(const String& filepath); + struct Cpp { bool incomment; - VectorMap macro; String filedir; String include_path; - int level; + + VectorMap used_macro; + Index not_macro; + + Index header; + VectorMap macro0; + VectorMap macro; + Index notmacro; + Index usedmacro; + + void SyncSet(); + + Vector *> macro_set; - void Define(const char *s); + String Define(const char *s); static const char *SkipString(const char *s); void ParamAdd(Vector& param, const char *b, const char *e); @@ -35,7 +57,10 @@ struct Cpp { void Include(const char *s); String GetIncludePath(const char *s); - String Preprocess(Stream& in, bool needresult = true); + String Do(Stream& in, Index& header); }; + +String Preprocess(const String& filename, const String& include_path); + #endif diff --git a/uppdev/cpp/cpp.upp b/uppdev/cpp/cpp.upp index e0acfcae7..a71214364 100644 --- a/uppdev/cpp/cpp.upp +++ b/uppdev/cpp/cpp.upp @@ -1,5 +1,6 @@ uses - Core; + Core, + CppBase; file cpp.h, diff --git a/uppdev/cpp/init b/uppdev/cpp/init index 7aecda6a6..a4d3d782e 100644 --- a/uppdev/cpp/init +++ b/uppdev/cpp/init @@ -1,4 +1,5 @@ #ifndef _cpp_icpp_init_stub #define _cpp_icpp_init_stub #include "Core/init" +#include "CppBase/init" #endif diff --git a/uppdev/cpp/main.cpp b/uppdev/cpp/main.cpp index 1e437598d..5ba489aaf 100644 --- a/uppdev/cpp/main.cpp +++ b/uppdev/cpp/main.cpp @@ -1,36 +1,43 @@ #include "cpp.h" -/* -#define TEST(x, y) %x%y% -#define TESTS(x) #x -#define TEST2(x, y) x ## y -#define TEST4 alfa x ## y.r #hahaha -#define TESTX x\ -//h +Vector errs; -#define TESTY haha // note\ -ble +void AddError(int ln, const String& s) +{ + errs.Add(AsString(ln) + ": " + s); +} -#define TESTZ haha \ -ble +void Test(const char *path) +{ + CppBase base; -//* -TEST('\1', "\2") -TEST( 1 +1 , 3 ) -TEST( "1" "2" ",", ',') -TESTS(a) -TESTS(a x y) -TESTS("A") -TEST2(a, 3) -TEST2(3, a) -TEST2(a, #) -TEST2(a, "X") -TEST2("Y", "X") -TESTX -TESTY -TESTZ -TEST4 -//*/ + Cpp cpp; + cpp.filedir = GetFileFolder(path); + 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"; + FileIn in(path); + Index inc; + String pp = cpp.Do(in, inc); + SaveFile(GetHomeDirFile(GetFileTitle(path) + ".pp"), pp); + StringStream ss(pp); + Parse(ss, Vector() << "__cdecl", base, path, callback(AddError)); + DLOG("======================="); + DUMPC(inc); + DLOG("======================="); + DUMPC(errs); + DLOG("======================="); + Qualify(base); + String out; + for(int i = 0; i < base.GetCount(); i++) { + out << Nvl(base.GetKey(i), "") << " {\n"; + const Array& ma = 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"; + } + out << "}\n"; + } + LOG(out); +} CONSOLE_APP_MAIN { @@ -54,17 +61,29 @@ CONSOLE_APP_MAIN DUMP(x.Expand("This is: TEST((1 , 2), 3)!")); DUMP(x.Expand("This is: TEST( \"1\" \"2\" \",\", ',')!")); */ +// Test("C:/OpenSSL-Win32/include/openssl/ssl.h"); + Test("C:/Program Files/Microsoft SDKs/Windows/v7.1/Include/WinBase.h"); +// Test("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include\\string.h"); + return; Cpp x; x.filedir = GetFileFolder(GetDataFile("x")); x.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"; - x.level = 0; // FileIn in0("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include\\crtdefs.h"); // x.Preprocess(in0); // FileIn in("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Vc\\Include\\string.h"); - FileIn in(GetDataFile("test.h")); - LOG(x.Preprocess(in)); +// FileIn in(GetDataFile("test.h")); + FileIn in("C:/OpenSSL-Win32/include/openssl/ssl.h"); +// FileIn in(); + Index inc; + LOG(x.Do(in, inc)); LOG("---------------------------"); DUMPM(x.macro); + LOG("---------------------------"); + DUMPC(x.usedmacro); + LOG("---------------------------"); + DUMPC(x.notmacro); + LOG("---------------------------"); + DUMPC(inc); } // TEST:a,b:|a|b|\n