diff --git a/autotest/CppParser/CppParser.cpp b/autotest/CppParser/CppParser.cpp index 52a50c6f4..eb65e2191 100644 --- a/autotest/CppParser/CppParser.cpp +++ b/autotest/CppParser/CppParser.cpp @@ -18,8 +18,11 @@ void Test(const char *path) FileIn in(path); errs.Clear(); + Index hh; + Parser p; - p.Do(in, Vector(), base, path, callback(AddError)); + p.Do(in, base, 0, 0, "title", callback(AddError), + Vector(), Vector(), hh); if(errs.GetCount()) DUMPC(errs); @@ -32,14 +35,23 @@ void Test(const char *path) 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 << ", line " << m.line << "\n"; + out << '\t' << CppItemKindAsString(m.kind) << ", name: " << m.name << ", qitem: " << m.qitem + << ", qtype: " << m.qtype + << ", qptype: " << m.qptype + << ", natural: " << m.natural + << ", line " << m.line + << ", using " << m.using_namespaces; + if(m.isptr) + out << ", pointer"; + out << "\n"; } out << "}\n"; } p.dobody = true; in.Seek(0); - p.Do(in, Vector(), base, path, callback(AddError)); + p.Do(in, base, 0, 0, "title", callback(AddError), + Vector(), Vector(), hh); out << " {\n"; for(int i = 0; i < p.local.GetCount(); i++) { @@ -52,19 +64,21 @@ void Test(const char *path) LOG("===="); LOG(out); LOG("-------------------------------------------------------------------------------"); +#ifdef flagSAVE + SaveFile(ForceExt(path, ".out"), out); +#else String h = LoadFile(ForceExt(path, ".out")); h.Replace("\r", ""); ASSERT(out == h); +#endif } CONSOLE_APP_MAIN { StdLogSetup(LOG_COUT|LOG_FILE); + + SeedRandom(0); -#ifdef flagSINGLE - FindFile ff(GetDataFile("test5.in")); -#else FindFile ff(GetDataFile("*.in")); -#endif while(ff) { Test(ff.GetPath()); ff.Next(); diff --git a/autotest/CppParser/CppParser.upp b/autotest/CppParser/CppParser.upp index 8b12f9109..25db2ecfe 100644 --- a/autotest/CppParser/CppParser.upp +++ b/autotest/CppParser/CppParser.upp @@ -15,9 +15,41 @@ file test4.in, test4.out, test5.in, - test5.out; + test5.out, + test6.in, + test6.out, + test7.in, + test7.out, + test8.in, + test8.out, + test9.in, + test9.out, + test10.in, + test10.out, + test11.in, + test11.out, + test12.in, + test12.out, + test13.in, + test13.out, + test14.in, + test14.out, + test15.in, + test15.out, + test16.in, + test16.out, + test17.in, + test17.out, + test18.in, + test18.out, + test19.in, + test19.out, + test20.in, + test20.out, + test21.in, + test21.out; mainconfig "" = "", - "" = "SINGLE"; + "" = "SAVE"; diff --git a/autotest/CppParser/test0.out b/autotest/CppParser/test0.out index 50df159d0..acab381f4 100644 --- a/autotest/CppParser/test0.out +++ b/autotest/CppParser/test0.out @@ -1,19 +1,19 @@ -ERRORS: [63: Name expected] - { - VARIABLE , line 3 - VARIABLE , line 63 - VARIABLE , line 201 - FUNCTION Foo(int,const String&), line 65 - FUNCTION Foo(int,const String&), line 67 - FUNCTION GetCppFile(int), line 21 - FUNCTION GetCppFileIndex(const String&), line 13 - FUNCTION PreProcess(Stream&), line 69 - FUNCTION SLPos(SrcFile&), line 51 - VARIABLE cpp_file, line 11 - VARIABLE cpp_file_mutex, line 10 -} -SrcFile { - CONSTRUCTOR SrcFile(), line 56 -} - { +ERRORS: [63: Name expected] + { + VARIABLE, name: , qitem: , qtype: NAMESPACE_UPP, qptype: , natural: NAMESPACE_UPP, line 3, using + VARIABLE, name: cpp_file_mutex, qitem: cpp_file_mutex, qtype: StaticMutex, qptype: , natural: static StaticMutex cpp_file_mutex, line 10, using + VARIABLE, name: cpp_file, qitem: cpp_file, qtype: Index, qptype: , natural: static Index cpp_file, line 11, using + FUNCTION, name: GetCppFileIndex, qitem: GetCppFileIndex(const String&), qtype: , qptype: String, natural: int GetCppFileIndex(const String& path), line 13, using + FUNCTION, name: GetCppFile, qitem: GetCppFile(int), qtype: String, qptype: , natural: const String& GetCppFile(int i), line 21, using + FUNCTION, name: SLPos, qitem: SLPos(SrcFile&), qtype: , qptype: SrcFile, natural: void SLPos(SrcFile& res), line 51, using + VARIABLE, name: , qitem: , qtype: , qptype: , natural: void, line 63, using + FUNCTION, name: Foo, qitem: Foo(int,const String&), qtype: , qptype: ;String, natural: void Foo(int x, const String& y), line 65, using + FUNCTION, name: Foo, qitem: Foo(int,const String&), qtype: , qptype: ;String, natural: void Foo(int x, const String& y), line 67, using + FUNCTION, name: PreProcess, qitem: PreProcess(Stream&), qtype: SrcFile, qptype: Stream, natural: SrcFile PreProcess(Stream& in), line 69, using + VARIABLE, name: , qitem: , qtype: END_UPP_NAMESPACE, qptype: , natural: END_UPP_NAMESPACE, line 201, using +} +SrcFile { + CONSTRUCTOR, name: SrcFile, qitem: SrcFile(), qtype: , qptype: , natural: SrcFile(), line 56, using +} + { } \ No newline at end of file diff --git a/autotest/CppParser/test1.out b/autotest/CppParser/test1.out index 3fddef058..6560c0f97 100644 --- a/autotest/CppParser/test1.out +++ b/autotest/CppParser/test1.out @@ -1,22 +1,22 @@ - { - FUNCTION Test(), line 1 - FUNCTION foo(), line 15 - VARIABLE global, line 13 -} -Foo { - CONSTRUCTOR Foo(), line 4 - STRUCT class, line 3 -} -Point { - INSTANCEVARIABLE bar, line 10 - INSTANCEVARIABLE next, line 9 - STRUCT struct, line 7 - INSTANCEVARIABLE x, line 8 - INSTANCEVARIABLE y, line 8 -} - { -x , line: 17 -a Point, line: 18 -b Point, line: 18 -c Point pointer, line: 18 + { + FUNCTION, name: Test, qitem: Test(), qtype: , qptype: , natural: void Test(), line 1, using + VARIABLE, name: global, qitem: global, qtype: Point, qptype: , natural: Point global, line 13, using + FUNCTION, name: foo, qitem: foo(), qtype: , qptype: , natural: void foo(), line 15, using +} +Foo { + STRUCT, name: Foo, qitem: class, qtype: Foo, qptype: , natural: class Foo, line 3, using + CONSTRUCTOR, name: Foo, qitem: Foo(), qtype: , qptype: , natural: Foo(), line 4, using +} +Point { + STRUCT, name: Point, qitem: struct, qtype: Point, qptype: , natural: struct Point, line 7, using + INSTANCEVARIABLE, name: x, qitem: x, qtype: , qptype: , natural: int x, line 8, using + INSTANCEVARIABLE, name: y, qitem: y, qtype: , qptype: , natural: int y, line 8, using + INSTANCEVARIABLE, name: next, qitem: next, qtype: Point, qptype: , natural: Point *next, line 9, using , pointer + INSTANCEVARIABLE, name: bar, qitem: bar, qtype: Foo, qptype: , natural: Foo bar, line 10, using +} + { +x , line: 17 +a Point, line: 18 +b Point, line: 18 +c Point pointer, line: 18 } \ No newline at end of file diff --git a/autotest/CppParser/test10.in b/autotest/CppParser/test10.in new file mode 100644 index 000000000..3c6148bca --- /dev/null +++ b/autotest/CppParser/test10.in @@ -0,0 +1,5 @@ +template +class Moveable : public B +{ + int boo; +}; diff --git a/autotest/CppParser/test10.out b/autotest/CppParser/test10.out new file mode 100644 index 000000000..807694df9 --- /dev/null +++ b/autotest/CppParser/test10.out @@ -0,0 +1,6 @@ +Moveable { + STRUCTTEMPLATE, name: Moveable, qitem: class, qtype: Moveable, qptype: 1, natural: template class Moveable : public B, line 1, using + INSTANCEVARIABLE, name: boo, qitem: boo, qtype: , qptype: , natural: int boo, line 4, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test11.in b/autotest/CppParser/test11.in new file mode 100644 index 000000000..b49d3270c --- /dev/null +++ b/autotest/CppParser/test11.in @@ -0,0 +1,3 @@ +struct Foo { + friend class Bar; +}; diff --git a/autotest/CppParser/test11.out b/autotest/CppParser/test11.out new file mode 100644 index 000000000..f6ad943e8 --- /dev/null +++ b/autotest/CppParser/test11.out @@ -0,0 +1,5 @@ +Foo { + STRUCT, name: Foo, qitem: struct, qtype: Foo, qptype: , natural: struct Foo, line 1, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test12.in b/autotest/CppParser/test12.in new file mode 100644 index 000000000..d42d6aee6 --- /dev/null +++ b/autotest/CppParser/test12.in @@ -0,0 +1,11 @@ +enum Alpha { + FOO, BAR +}; + +typedef enum { + FOO, BAR +} Beta; + +typedef enum Gamma { + FOO, BAR +} Gamma; diff --git a/autotest/CppParser/test12.out b/autotest/CppParser/test12.out new file mode 100644 index 000000000..bc0262d0b --- /dev/null +++ b/autotest/CppParser/test12.out @@ -0,0 +1,10 @@ + { + ENUM, name: FOO, qitem: FOO, qtype: , qptype: , natural: enum Alpha FOO, line 2, using + ENUM, name: BAR, qitem: BAR, qtype: , qptype: , natural: enum Alpha BAR, line 2, using + ENUM, name: FOO, qitem: FOO, qtype: , qptype: , natural: enum FOO, line 6, using + ENUM, name: BAR, qitem: BAR, qtype: , qptype: , natural: enum BAR, line 6, using + ENUM, name: FOO, qitem: FOO, qtype: , qptype: , natural: enum Gamma FOO, line 10, using + ENUM, name: BAR, qitem: BAR, qtype: , qptype: , natural: enum Gamma BAR, line 10, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test13.in b/autotest/CppParser/test13.in new file mode 100644 index 000000000..adc8c28bf --- /dev/null +++ b/autotest/CppParser/test13.in @@ -0,0 +1,48 @@ +typedef struct _LARGE_INTEGER { + +typedef union _LARGE_INTEGER { + struct { + DWORD LowPart; + LONG HighPart; + } ; + struct { + DWORD LowPart; + LONG HighPart; + } u; + + LONGLONG QuadPart; +} LARGE_INTEGER; + +typedef LARGE_INTEGER *PLARGE_INTEGER; + + +typedef struct _ULARGE_INTEGER { + +typedef union _ULARGE_INTEGER { + struct { + DWORD LowPart; + DWORD HighPart; + } ; + struct { + DWORD LowPart; + DWORD HighPart; + } u; + + ULONGLONG QuadPart; +} ULARGE_INTEGER; + +typedef ULARGE_INTEGER *PULARGE_INTEGER; + +typedef struct _LUID { + DWORD LowPart; + LONG HighPart; +} LUID, *PLUID; + +#define _DWORDLONG_ +typedef ULONGLONG DWORDLONG; +typedef DWORDLONG *PDWORDLONG; + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY, * PRLIST_ENTRY; diff --git a/autotest/CppParser/test13.out b/autotest/CppParser/test13.out new file mode 100644 index 000000000..dc10538b1 --- /dev/null +++ b/autotest/CppParser/test13.out @@ -0,0 +1,80 @@ +_LARGE_INTEGER { + STRUCT, name: _LARGE_INTEGER, qitem: struct, qtype: _LARGE_INTEGER, qptype: , natural: , line 1, using + STRUCT, name: _LARGE_INTEGER, qitem: union, qtype: _LARGE_INTEGER, qptype: , natural: union _LARGE_INTEGER, line 3, using + INSTANCEVARIABLE, name: u, qitem: u, qtype: .u, qptype: , natural: struct { DWORD LowPart; LONG HighPart; } u, line 10, using + INSTANCEVARIABLE, name: QuadPart, qitem: QuadPart, qtype: LONGLONG, qptype: , natural: LONGLONG QuadPart, line 13, using +} +_LARGE_INTEGER::@rAp/jC+qxJd1pha3wMwh2A==/title { + STRUCT, name: @rAp/jC+qxJd1pha3wMwh2A==/title, qitem: struct, qtype: @rAp/jC+qxJd1pha3wMwh2A==/title, qptype: , natural: struct @rAp/jC+qxJd1pha3wMwh2A==/title, line 4, using + INSTANCEVARIABLE, name: LowPart, qitem: LowPart, qtype: DWORD, qptype: , natural: DWORD LowPart, line 5, using + INSTANCEVARIABLE, name: HighPart, qitem: HighPart, qtype: LONG, qptype: , natural: LONG HighPart, line 6, using +} +_LARGE_INTEGER::.u { + STRUCT, name: .u, qitem: struct, qtype: .u, qptype: , natural: struct .u, line 8, using + INSTANCEVARIABLE, name: LowPart, qitem: LowPart, qtype: DWORD, qptype: , natural: DWORD LowPart, line 9, using + INSTANCEVARIABLE, name: HighPart, qitem: HighPart, qtype: LONG, qptype: , natural: LONG HighPart, line 10, using +} +LARGE_INTEGER { + TYPEDEF, name: LARGE_INTEGER, qitem: typedef, qtype: _LARGE_INTEGER, qptype: , natural: typedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; } ; struct { DWORD LowPart; LONG HighPart; } u; LONGLONG QuadPart; } LARGE_INTEGER, line 13, using +} +PLARGE_INTEGER { + TYPEDEF, name: PLARGE_INTEGER, qitem: typedef, qtype: LARGE_INTEGER, qptype: , natural: typedef LARGE_INTEGER *PLARGE_INTEGER, line 16, using +} +_ULARGE_INTEGER { + STRUCT, name: _ULARGE_INTEGER, qitem: struct, qtype: _ULARGE_INTEGER, qptype: , natural: , line 19, using + STRUCT, name: _ULARGE_INTEGER, qitem: union, qtype: _ULARGE_INTEGER, qptype: , natural: union _ULARGE_INTEGER, line 21, using + INSTANCEVARIABLE, name: u, qitem: u, qtype: .u, qptype: , natural: struct { DWORD LowPart; DWORD HighPart; } u, line 28, using + INSTANCEVARIABLE, name: QuadPart, qitem: QuadPart, qtype: ULONGLONG, qptype: , natural: ULONGLONG QuadPart, line 31, using +} +_ULARGE_INTEGER::@Q7NOmvtSotvDdn2LZ33l2A==/title { + STRUCT, name: @Q7NOmvtSotvDdn2LZ33l2A==/title, qitem: struct, qtype: @Q7NOmvtSotvDdn2LZ33l2A==/title, qptype: , natural: struct @Q7NOmvtSotvDdn2LZ33l2A==/title, line 22, using + INSTANCEVARIABLE, name: LowPart, qitem: LowPart, qtype: DWORD, qptype: , natural: DWORD LowPart, line 23, using + INSTANCEVARIABLE, name: HighPart, qitem: HighPart, qtype: DWORD, qptype: , natural: DWORD HighPart, line 24, using +} +_ULARGE_INTEGER::.u { + STRUCT, name: .u, qitem: struct, qtype: .u, qptype: , natural: struct .u, line 26, using + INSTANCEVARIABLE, name: LowPart, qitem: LowPart, qtype: DWORD, qptype: , natural: DWORD LowPart, line 27, using + INSTANCEVARIABLE, name: HighPart, qitem: HighPart, qtype: DWORD, qptype: , natural: DWORD HighPart, line 28, using +} +ULARGE_INTEGER { + TYPEDEF, name: ULARGE_INTEGER, qitem: typedef, qtype: _ULARGE_INTEGER, qptype: , natural: typedef union _ULARGE_INTEGER { struct { DWORD LowPart; DWORD HighPart; } ; struct { DWORD LowPart; DWORD HighPart; } u; ULONGLONG QuadPart; } ULARGE_INTEGER, line 31, using +} +PULARGE_INTEGER { + TYPEDEF, name: PULARGE_INTEGER, qitem: typedef, qtype: ULARGE_INTEGER, qptype: , natural: typedef ULARGE_INTEGER *PULARGE_INTEGER, line 34, using +} +_LUID { + STRUCT, name: _LUID, qitem: struct, qtype: _LUID, qptype: , natural: struct _LUID, line 36, using + INSTANCEVARIABLE, name: LowPart, qitem: LowPart, qtype: DWORD, qptype: , natural: DWORD LowPart, line 37, using + INSTANCEVARIABLE, name: HighPart, qitem: HighPart, qtype: LONG, qptype: , natural: LONG HighPart, line 38, using +} +LUID { + TYPEDEF, name: LUID, qitem: typedef, qtype: _LUID, qptype: , natural: typedef struct _LUID { DWORD LowPart; LONG HighPart; } LUID, line 38, using +} +PLUID { + TYPEDEF, name: PLUID, qitem: typedef, qtype: _LUID, qptype: , natural: typedef struct _LUID { DWORD LowPart; LONG HighPart; } *PLUID, line 38, using +} + { + MACRO, name: _DWORDLONG_, qitem: _DWORDLONG_, qtype: , qptype: , natural: _DWORDLONG_, line 41, using +} +DWORDLONG { + TYPEDEF, name: DWORDLONG, qitem: typedef, qtype: ULONGLONG, qptype: , natural: typedef ULONGLONG DWORDLONG, line 42, using +} +PDWORDLONG { + TYPEDEF, name: PDWORDLONG, qitem: typedef, qtype: DWORDLONG, qptype: , natural: typedef DWORDLONG *PDWORDLONG, line 43, using +} +_LIST_ENTRY { + STRUCT, name: _LIST_ENTRY, qitem: struct, qtype: _LIST_ENTRY, qptype: , natural: struct _LIST_ENTRY, line 45, using + INSTANCEVARIABLE, name: Flink, qitem: Flink, qtype: _LIST_ENTRY, qptype: , natural: struct _LIST_ENTRY *Flink, line 46, using , pointer + INSTANCEVARIABLE, name: Blink, qitem: Blink, qtype: _LIST_ENTRY, qptype: , natural: struct _LIST_ENTRY *Blink, line 47, using , pointer +} +LIST_ENTRY { + TYPEDEF, name: LIST_ENTRY, qitem: typedef, qtype: _LIST_ENTRY, qptype: , natural: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, line 47, using +} +PLIST_ENTRY { + TYPEDEF, name: PLIST_ENTRY, qitem: typedef, qtype: _LIST_ENTRY, qptype: , natural: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } *PLIST_ENTRY, line 47, using +} +PRLIST_ENTRY { + TYPEDEF, name: PRLIST_ENTRY, qitem: typedef, qtype: _LIST_ENTRY, qptype: , natural: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } * PRLIST_ENTRY, line 47, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test14.in b/autotest/CppParser/test14.in new file mode 100644 index 000000000..53bec2b07 --- /dev/null +++ b/autotest/CppParser/test14.in @@ -0,0 +1,28 @@ +typedef struct { + int x; + struct Foo { + int a; + } y; + struct { + int bar; + }; + struct { + int foo; + } quack; +} name; + +namespace std { + struct string {}; +}; + +// void Foo(string a); + +using namespace std; + +struct Bar { + struct string {}; + + std::string Foo(string a); +}; + +void Foo(string a); diff --git a/autotest/CppParser/test14.out b/autotest/CppParser/test14.out new file mode 100644 index 000000000..3018dbed3 --- /dev/null +++ b/autotest/CppParser/test14.out @@ -0,0 +1,36 @@ +.name { + STRUCT, name: .name, qitem: struct, qtype: .name, qptype: , natural: struct .name, line 1, using + INSTANCEVARIABLE, name: x, qitem: x, qtype: , qptype: , natural: int x, line 2, using + INSTANCEVARIABLE, name: y, qitem: y, qtype: .name::Foo, qptype: , natural: struct Foo { int a; } y, line 4, using + INSTANCEVARIABLE, name: quack, qitem: quack, qtype: .quack, qptype: , natural: struct { int foo; } quack, line 10, using +} +.name::Foo { + STRUCT, name: Foo, qitem: struct, qtype: .name::Foo, qptype: , natural: struct Foo, line 3, using + INSTANCEVARIABLE, name: a, qitem: a, qtype: , qptype: , natural: int a, line 4, using +} +.name::@WJqy9ozNzEU6OSliwUJIeg==/title { + STRUCT, name: @WJqy9ozNzEU6OSliwUJIeg==/title, qitem: struct, qtype: @WJqy9ozNzEU6OSliwUJIeg==/title, qptype: , natural: struct @WJqy9ozNzEU6OSliwUJIeg==/title, line 6, using + INSTANCEVARIABLE, name: bar, qitem: bar, qtype: , qptype: , natural: int bar, line 7, using +} +.name::.quack { + STRUCT, name: .quack, qitem: struct, qtype: .quack, qptype: , natural: struct .quack, line 9, using + INSTANCEVARIABLE, name: foo, qitem: foo, qtype: , qptype: , natural: int foo, line 10, using +} +name { + TYPEDEF, name: name, qitem: typedef, qtype: .name, qptype: , natural: typedef struct { int x; struct Foo { int a; } y; struct { int bar; }; struct { int foo; } quack; } name, line 10, using +} +std::string { + STRUCT, name: string, qitem: struct, qtype: std::string, qptype: , natural: struct string, line 15, using +} +Bar { + STRUCT, name: Bar, qitem: struct, qtype: Bar, qptype: , natural: struct Bar, line 22, using std + INSTANCEFUNCTION, name: Foo, qitem: Foo(Bar::string), qtype: std::string, qptype: Bar::string, natural: std::string Foo(string a), line 25, using std +} +Bar::string { + STRUCT, name: string, qitem: struct, qtype: Bar::string, qptype: , natural: struct string, line 23, using std +} + { + FUNCTION, name: Foo, qitem: Foo(std::string), qtype: , qptype: std::string, natural: void Foo(string a), line 28, using std +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test15.in b/autotest/CppParser/test15.in new file mode 100644 index 000000000..b38f22f19 --- /dev/null +++ b/autotest/CppParser/test15.in @@ -0,0 +1,3 @@ + #define _THROW0() throw () + +void Test() _THROW0() diff --git a/autotest/CppParser/test15.out b/autotest/CppParser/test15.out new file mode 100644 index 000000000..aab5757c4 --- /dev/null +++ b/autotest/CppParser/test15.out @@ -0,0 +1,7 @@ + { + MACRO, name: _THROW0, qitem: _THROW0(), qtype: , qptype: , natural: _THROW0(), line 1, using + FUNCTION, name: Test, qitem: Test(), qtype: , qptype: , natural: void Test(), line 3, using + VARIABLE, name: , qitem: , qtype: _THROW0, qptype: , natural: _THROW0(), line 3, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test16.in b/autotest/CppParser/test16.in new file mode 100644 index 000000000..db644bf17 --- /dev/null +++ b/autotest/CppParser/test16.in @@ -0,0 +1,9 @@ +typedef enum _MANDATORY_LEVEL { + MandatoryLevelUntrusted = 0, + MandatoryLevelLow, + MandatoryLevelMedium, + MandatoryLevelHigh, + MandatoryLevelSystem, + MandatoryLevelSecureProcess, + MandatoryLevelCount +} MANDATORY_LEVEL, *PMANDATORY_LEVEL; diff --git a/autotest/CppParser/test16.out b/autotest/CppParser/test16.out new file mode 100644 index 000000000..778ae8e2f --- /dev/null +++ b/autotest/CppParser/test16.out @@ -0,0 +1,11 @@ + { + ENUM, name: MandatoryLevelUntrusted, qitem: MandatoryLevelUntrusted, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelUntrusted = 0, line 2, using + ENUM, name: MandatoryLevelLow, qitem: MandatoryLevelLow, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelLow, line 3, using + ENUM, name: MandatoryLevelMedium, qitem: MandatoryLevelMedium, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelMedium, line 4, using + ENUM, name: MandatoryLevelHigh, qitem: MandatoryLevelHigh, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelHigh, line 5, using + ENUM, name: MandatoryLevelSystem, qitem: MandatoryLevelSystem, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelSystem, line 6, using + ENUM, name: MandatoryLevelSecureProcess, qitem: MandatoryLevelSecureProcess, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelSecureProcess, line 7, using + ENUM, name: MandatoryLevelCount, qitem: MandatoryLevelCount, qtype: , qptype: , natural: enum _MANDATORY_LEVEL MandatoryLevelCount, line 8, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test17.in b/autotest/CppParser/test17.in new file mode 100644 index 000000000..1de062291 --- /dev/null +++ b/autotest/CppParser/test17.in @@ -0,0 +1,4 @@ +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY, * PRLIST_ENTRY; diff --git a/autotest/CppParser/test17.out b/autotest/CppParser/test17.out new file mode 100644 index 000000000..70611877b --- /dev/null +++ b/autotest/CppParser/test17.out @@ -0,0 +1,16 @@ +_LIST_ENTRY { + STRUCT, name: _LIST_ENTRY, qitem: struct, qtype: _LIST_ENTRY, qptype: , natural: struct _LIST_ENTRY, line 1, using + INSTANCEVARIABLE, name: Flink, qitem: Flink, qtype: _LIST_ENTRY, qptype: , natural: struct _LIST_ENTRY *Flink, line 2, using , pointer + INSTANCEVARIABLE, name: Blink, qitem: Blink, qtype: _LIST_ENTRY, qptype: , natural: struct _LIST_ENTRY *Blink, line 3, using , pointer +} +LIST_ENTRY { + TYPEDEF, name: LIST_ENTRY, qitem: typedef, qtype: _LIST_ENTRY, qptype: , natural: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, line 3, using +} +PLIST_ENTRY { + TYPEDEF, name: PLIST_ENTRY, qitem: typedef, qtype: _LIST_ENTRY, qptype: , natural: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } *PLIST_ENTRY, line 3, using +} +PRLIST_ENTRY { + TYPEDEF, name: PRLIST_ENTRY, qitem: typedef, qtype: _LIST_ENTRY, qptype: , natural: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } * PRLIST_ENTRY, line 3, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test18.in b/autotest/CppParser/test18.in new file mode 100644 index 000000000..e037045a6 --- /dev/null +++ b/autotest/CppParser/test18.in @@ -0,0 +1 @@ +String EncodeHtml(const String& x, const VectorMap& escape = VectorMap()); diff --git a/autotest/CppParser/test18.out b/autotest/CppParser/test18.out new file mode 100644 index 000000000..f31a47098 --- /dev/null +++ b/autotest/CppParser/test18.out @@ -0,0 +1,5 @@ + { + FUNCTION, name: EncodeHtml, qitem: EncodeHtml(const String&,const VectorMap&), qtype: String, qptype: String;VectorMap, natural: String EncodeHtml(const String& x, const VectorMap& escape = VectorMap()), line 1, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test19.in b/autotest/CppParser/test19.in new file mode 100644 index 000000000..a116047d5 --- /dev/null +++ b/autotest/CppParser/test19.in @@ -0,0 +1 @@ +[attr] [attr] int function([attr] [attr] string x[4], [attr] int y[4][5], [attr] const int& x, int (*f)[4]); diff --git a/autotest/CppParser/test19.out b/autotest/CppParser/test19.out new file mode 100644 index 000000000..b97dc4484 --- /dev/null +++ b/autotest/CppParser/test19.out @@ -0,0 +1,5 @@ + { + FUNCTION, name: function, qitem: function(string[4],int[4][5],const int&,int(*)[4]), qtype: , qptype: string;;;, natural: int function(string x[4], int y[4][5], const int& x, int (*f)[4]), line 1, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test2.out b/autotest/CppParser/test2.out index 6108603aa..0ea770674 100644 --- a/autotest/CppParser/test2.out +++ b/autotest/CppParser/test2.out @@ -1,8 +1,8 @@ -_CrtEnableIf { - STRUCTTEMPLATE struct, line 1 -} -_CrtEnableIf ::_Type { - TYPEDEF typedef, line 4 -} - { +_CrtEnableIf { + STRUCTTEMPLATE, name: _CrtEnableIf , qitem: struct, qtype: _CrtEnableIf, qptype: , natural: template struct _CrtEnableIf , line 1, using +} +_CrtEnableIf ::_Type { + TYPEDEF, name: _Type, qitem: typedef, qtype: 1, qptype: , natural: typedef _Ty _Type, line 4, using +} + { } \ No newline at end of file diff --git a/autotest/CppParser/test20.in b/autotest/CppParser/test20.in new file mode 100644 index 000000000..1c8a0e797 --- /dev/null +++ b/autotest/CppParser/test20.in @@ -0,0 +1 @@ +; \ No newline at end of file diff --git a/autotest/CppParser/test20.out b/autotest/CppParser/test20.out new file mode 100644 index 000000000..e9f34467b --- /dev/null +++ b/autotest/CppParser/test20.out @@ -0,0 +1,2 @@ + { +} \ No newline at end of file diff --git a/autotest/CppParser/test21.in b/autotest/CppParser/test21.in new file mode 100644 index 000000000..c58db0ff9 --- /dev/null +++ b/autotest/CppParser/test21.in @@ -0,0 +1,5 @@ +int static foo(); + +FOO + +static Bar bar; \ No newline at end of file diff --git a/autotest/CppParser/test21.out b/autotest/CppParser/test21.out new file mode 100644 index 000000000..9c5fbc062 --- /dev/null +++ b/autotest/CppParser/test21.out @@ -0,0 +1,7 @@ + { + FUNCTION, name: foo, qitem: foo(), qtype: , qptype: , natural: int foo(), line 1, using + VARIABLE, name: , qitem: , qtype: FOO, qptype: , natural: FOO, line 3, using + VARIABLE, name: bar, qitem: bar, qtype: Bar, qptype: , natural: static Bar bar, line 5, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test3.out b/autotest/CppParser/test3.out index e6b49576b..7e8c1e8df 100644 --- a/autotest/CppParser/test3.out +++ b/autotest/CppParser/test3.out @@ -1,5 +1,5 @@ - { - FUNCTIONTEMPLATE memcpy(_DstType(&)[_Size],const void*,size_t)throw(), line 3 -} - { + { + FUNCTIONTEMPLATE, name: memcpy, qitem: memcpy(_DstType(&)[_Size],const void*,size_t)throw(), qtype: _CrtEnableIf<(_Size>1),void*>, qptype: _DstType;;size_t, natural: template typename _CrtEnableIf<(_Size > 1), void *>::_Type memcpy(_DstType (&_Dst)[_Size], const void *_Src, size_t _SrcSize) throw(), line 3, using +} + { } \ No newline at end of file diff --git a/autotest/CppParser/test4.out b/autotest/CppParser/test4.out index 942558ba2..b8088cbf8 100644 --- a/autotest/CppParser/test4.out +++ b/autotest/CppParser/test4.out @@ -1,5 +1,5 @@ - { - FUNCTIONTEMPLATE Fn(), line 1 -} - { + { + FUNCTIONTEMPLATE, name: Fn, qitem: Fn(), qtype: , qptype: , natural: template void Fn(), line 1, using +} + { } \ No newline at end of file diff --git a/autotest/CppParser/test5.out b/autotest/CppParser/test5.out index 3deebdf2a..9d73a94a5 100644 --- a/autotest/CppParser/test5.out +++ b/autotest/CppParser/test5.out @@ -1,9 +1,9 @@ -Value { - STRUCT class, line 1 - INSTANCEFUNCTION operator<(const Value&)const, line 4 - INSTANCEFUNCTION operator<=(const Value&)const, line 2 - INSTANCEFUNCTION operator>(const Value&)const, line 5 - INSTANCEFUNCTION operator>=(const Value&)const, line 3 -} - { +Value { + STRUCT, name: Value, qitem: class, qtype: Value, qptype: , natural: class Value, line 1, using + INSTANCEFUNCTION, name: operator<=, qitem: operator<=(const Value&)const, qtype: , qptype: Value, natural: bool operator<=(const Value& x) const, line 2, using + INSTANCEFUNCTION, name: operator>=, qitem: operator>=(const Value&)const, qtype: , qptype: Value, natural: bool operator>=(const Value& x) const, line 3, using + INSTANCEFUNCTION, name: operator<, qitem: operator<(const Value&)const, qtype: , qptype: Value, natural: bool operator<(const Value& x) const, line 4, using + INSTANCEFUNCTION, name: operator>, qitem: operator>(const Value&)const, qtype: , qptype: Value, natural: bool operator>(const Value& x) const, line 5, using +} + { } \ No newline at end of file diff --git a/autotest/CppParser/test6.in b/autotest/CppParser/test6.in new file mode 100644 index 000000000..932137f0e --- /dev/null +++ b/autotest/CppParser/test6.in @@ -0,0 +1 @@ +[attribute] void test([attribute] const int a); diff --git a/autotest/CppParser/test6.out b/autotest/CppParser/test6.out new file mode 100644 index 000000000..b8f5b1d8e --- /dev/null +++ b/autotest/CppParser/test6.out @@ -0,0 +1,5 @@ + { + FUNCTION, name: test, qitem: test(const int), qtype: , qptype: , natural: void test(const int a), line 1, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test7.in b/autotest/CppParser/test7.in new file mode 100644 index 000000000..f133844df --- /dev/null +++ b/autotest/CppParser/test7.in @@ -0,0 +1,20 @@ +__inline +char * +__insecure__strlwr_l( +[SA_Pre( Null=SA_No, NullTerminated=SA_Yes)] +[SA_Pre(Deref=1, Valid=SA_Yes)] +[SA_Post( NullTerminated=SA_Yes)] +[SA_Post(Deref=1, Valid=SA_Yes)] +char *_String, +[SA_Pre( Null=SA_Maybe)] [SA_Pre(Deref=1, Valid=SA_Yes)] +[SA_Pre(Deref=1, Access=SA_Read)] +_locale_t _Locale) +{ + char * _strlwr_l([SA_Pre( Null=SA_No, NullTerminated=SA_Yes)] + [SA_Pre(Deref=1, Valid=SA_Yes)] + [SA_Post( NullTerminated=SA_Yes)] + [SA_Post(Deref=1, Valid=SA_Yes)] + char *_String, + [SA_Pre( Null=SA_Maybe)] [SA_Pre(Deref=1, Valid=SA_Yes)] + [SA_Pre(Deref=1, Access=SA_Read)] _locale_t _Locale); + return _strlwr_l(_String, _Locale); } diff --git a/autotest/CppParser/test7.out b/autotest/CppParser/test7.out new file mode 100644 index 000000000..f12b112b6 --- /dev/null +++ b/autotest/CppParser/test7.out @@ -0,0 +1,5 @@ + { + FUNCTION, name: __insecure__strlwr_l, qitem: __insecure__strlwr_l(char*,_locale_t), qtype: , qptype: ;_locale_t, natural: __inline char * __insecure__strlwr_l( char *_String, _locale_t _Locale), line 1, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test8.in b/autotest/CppParser/test8.in new file mode 100644 index 000000000..a88dff940 --- /dev/null +++ b/autotest/CppParser/test8.in @@ -0,0 +1,26 @@ +struct { + DWORD TimeCheck; + BYTE DemotePercent; + BYTE PromotePercent; + BYTE Spare[2]; +} vPROCESSOR_IDLESTATE_INFO, *vPPROCESSOR_IDLESTATE_INFO; + +typedef struct { + DWORD TimeCheck; + BYTE DemotePercent; + BYTE PromotePercent; + BYTE Spare[2]; +} PROCESSOR_IDLESTATE_INFO, *PPROCESSOR_IDLESTATE_INFO; + +struct Point { + int x, y; +} xxx, yyy; + +typedef struct PointT { + int x, y; +} PPP; + +template +struct TPoint { + T x, y; +}; diff --git a/autotest/CppParser/test8.out b/autotest/CppParser/test8.out new file mode 100644 index 000000000..3a0dfbcdf --- /dev/null +++ b/autotest/CppParser/test8.out @@ -0,0 +1,46 @@ +.vPROCESSOR_IDLESTATE_INFO { + STRUCT, name: .vPROCESSOR_IDLESTATE_INFO, qitem: struct, qtype: .vPROCESSOR_IDLESTATE_INFO, qptype: , natural: struct .vPROCESSOR_IDLESTATE_INFO, line 1, using + INSTANCEVARIABLE, name: TimeCheck, qitem: TimeCheck, qtype: DWORD, qptype: , natural: DWORD TimeCheck, line 2, using + INSTANCEVARIABLE, name: DemotePercent, qitem: DemotePercent, qtype: BYTE, qptype: , natural: BYTE DemotePercent, line 3, using + INSTANCEVARIABLE, name: PromotePercent, qitem: PromotePercent, qtype: BYTE, qptype: , natural: BYTE PromotePercent, line 4, using + INSTANCEVARIABLE, name: Spare, qitem: Spare, qtype: BYTE, qptype: , natural: BYTE Spare[2], line 5, using , pointer +} + { + VARIABLE, name: vPROCESSOR_IDLESTATE_INFO, qitem: vPROCESSOR_IDLESTATE_INFO, qtype: .vPROCESSOR_IDLESTATE_INFO, qptype: , natural: struct { DWORD TimeCheck; BYTE DemotePercent; BYTE PromotePercent; BYTE Spare[2]; } vPROCESSOR_IDLESTATE_INFO, line 5, using + VARIABLE, name: vPPROCESSOR_IDLESTATE_INFO, qitem: vPPROCESSOR_IDLESTATE_INFO, qtype: .vPROCESSOR_IDLESTATE_INFO, qptype: , natural: struct { DWORD TimeCheck; BYTE DemotePercent; BYTE PromotePercent; BYTE Spare[2]; } *vPPROCESSOR_IDLESTATE_INFO, line 5, using , pointer + VARIABLE, name: xxx, qitem: xxx, qtype: Point, qptype: , natural: struct Point { int x, y; } xxx, line 16, using + VARIABLE, name: yyy, qitem: yyy, qtype: Point, qptype: , natural: struct Point { int x, y; } yyy, line 16, using +} +.PROCESSOR_IDLESTATE_INFO { + STRUCT, name: .PROCESSOR_IDLESTATE_INFO, qitem: struct, qtype: .PROCESSOR_IDLESTATE_INFO, qptype: , natural: struct .PROCESSOR_IDLESTATE_INFO, line 8, using + INSTANCEVARIABLE, name: TimeCheck, qitem: TimeCheck, qtype: DWORD, qptype: , natural: DWORD TimeCheck, line 9, using + INSTANCEVARIABLE, name: DemotePercent, qitem: DemotePercent, qtype: BYTE, qptype: , natural: BYTE DemotePercent, line 10, using + INSTANCEVARIABLE, name: PromotePercent, qitem: PromotePercent, qtype: BYTE, qptype: , natural: BYTE PromotePercent, line 11, using + INSTANCEVARIABLE, name: Spare, qitem: Spare, qtype: BYTE, qptype: , natural: BYTE Spare[2], line 12, using , pointer +} +PROCESSOR_IDLESTATE_INFO { + TYPEDEF, name: PROCESSOR_IDLESTATE_INFO, qitem: typedef, qtype: .PROCESSOR_IDLESTATE_INFO, qptype: , natural: typedef struct { DWORD TimeCheck; BYTE DemotePercent; BYTE PromotePercent; BYTE Spare[2]; } PROCESSOR_IDLESTATE_INFO, line 12, using +} +PPROCESSOR_IDLESTATE_INFO { + TYPEDEF, name: PPROCESSOR_IDLESTATE_INFO, qitem: typedef, qtype: .PROCESSOR_IDLESTATE_INFO, qptype: , natural: typedef struct { DWORD TimeCheck; BYTE DemotePercent; BYTE PromotePercent; BYTE Spare[2]; } *PPROCESSOR_IDLESTATE_INFO, line 12, using +} +Point { + STRUCT, name: Point, qitem: struct, qtype: Point, qptype: , natural: struct Point, line 15, using + INSTANCEVARIABLE, name: x, qitem: x, qtype: , qptype: , natural: int x, line 16, using + INSTANCEVARIABLE, name: y, qitem: y, qtype: , qptype: , natural: int y, line 16, using +} +PointT { + STRUCT, name: PointT, qitem: struct, qtype: PointT, qptype: , natural: struct PointT, line 19, using + INSTANCEVARIABLE, name: x, qitem: x, qtype: , qptype: , natural: int x, line 20, using + INSTANCEVARIABLE, name: y, qitem: y, qtype: , qptype: , natural: int y, line 20, using +} +PPP { + TYPEDEF, name: PPP, qitem: typedef, qtype: PointT, qptype: , natural: typedef struct PointT { int x, y; } PPP, line 20, using +} +TPoint { + STRUCTTEMPLATE, name: TPoint, qitem: struct, qtype: TPoint, qptype: , natural: template struct TPoint, line 23, using + INSTANCEVARIABLE, name: x, qitem: x, qtype: 0, qptype: , natural: T x, line 25, using + INSTANCEVARIABLE, name: y, qitem: y, qtype: 0, qptype: , natural: T y, line 25, using +} + { +} \ No newline at end of file diff --git a/autotest/CppParser/test9.in b/autotest/CppParser/test9.in new file mode 100644 index 000000000..f40ab400d --- /dev/null +++ b/autotest/CppParser/test9.in @@ -0,0 +1,6 @@ +SHORT +_InterlockedCompareExchange16 ( + SHORT volatile *Destination, + SHORT ExChange, + SHORT Comperand + ); diff --git a/autotest/CppParser/test9.out b/autotest/CppParser/test9.out new file mode 100644 index 000000000..454ad0a62 --- /dev/null +++ b/autotest/CppParser/test9.out @@ -0,0 +1,5 @@ + { + FUNCTION, name: _InterlockedCompareExchange16, qitem: _InterlockedCompareExchange16(SHORT volatile*,SHORT,SHORT), qtype: SHORT, qptype: SHORT;SHORT;SHORT, natural: SHORT _InterlockedCompareExchange16 ( SHORT volatile *Destination, SHORT ExChange, SHORT Comperand ), line 1, using +} + { +} \ No newline at end of file diff --git a/autotest/PPTest/PPTest.cpp b/autotest/PPTest/PPTest.cpp new file mode 100644 index 000000000..b8016d5c7 --- /dev/null +++ b/autotest/PPTest/PPTest.cpp @@ -0,0 +1,27 @@ +#include +#include + +using namespace Upp; + +CONSOLE_APP_MAIN +{ + String path = GetDataFile("test.in"); + PPSync(GetFileFolder(path)); + + Cpp cpp; + FileIn in(path); + cpp.Preprocess(path, in, path); + + String s = cpp.output; + String opath = GetDataFile("test.out"); + + LOG("======================"); + LOG(cpp.output); + +#ifdef flagSAVE + SaveFile(opath, s); +#else + ASSERT(LoadFile(opath) == s); +#endif + LOG("===================== OK"); +} diff --git a/autotest/PPTest/PPTest.upp b/autotest/PPTest/PPTest.upp new file mode 100644 index 000000000..30b503cc7 --- /dev/null +++ b/autotest/PPTest/PPTest.upp @@ -0,0 +1,14 @@ +uses + Core, + CppBase; + +file + PPTest.cpp, + test.in, + test.out, + help.in; + +mainconfig + "" = "", + "" = "SAVE"; + diff --git a/autotest/PPTest/help.in b/autotest/PPTest/help.in new file mode 100644 index 000000000..84d35d650 --- /dev/null +++ b/autotest/PPTest/help.in @@ -0,0 +1,127 @@ +#define COMBINE__(a, b) a##b +#define COMBINE(a, b) COMBINE__(a, b) + +#define COMBINE3__(a, b, c) a##b##c +#define COMBINE3(a, b, c) COMBINE3__(a, b, c) + +#define COMBINE4__(a, b, c, d) a##b##c##d +#define COMBINE4(a, b, c, d) COMBINE4__(a, b, c, d) + +#define COMBINE5__(a, b, c, d, e) a##b##c##d##e +#define COMBINE5(a, b, c, d, e) COMBINE5__(a, b, c, d, e) + +#define _cm_ , + +#define __countof(a) int(sizeof(a) / sizeof(a[0])) + +#define __Expand1(x) x(1) +#define __Expand2(x) __Expand1(x) x(2) +#define __Expand3(x) __Expand2(x) x(3) +#define __Expand4(x) __Expand3(x) x(4) +#define __Expand5(x) __Expand4(x) x(5) + +#define __List1(x) x(1) +#define __List2(x) __List1(x), x(2) +#define __List3(x) __List2(x), x(3) +#define __List4(x) __List3(x), x(4) +#define __List5(x) __List4(x), x(5) + +#define E__p(I) p##I + +#define MK__s__(x) s__s##x +#define MK__s_(x) MK__s__(x) + +// #define MK__s MK__s_(__LINE__) + +#define MK__s MK__s_(COMBINE3(BLITZ_INDEX__, _, __LINE__)) + +#define INITBLOCK \ +static void COMBINE(MK__s, _fn)(); static UPP::Callinit MK__s(COMBINE(MK__s, _fn), __FILE__, __LINE__); \ +static void COMBINE(MK__s, _fn)() + + +//--------------------------------------------------- + +#define E__NFValue(I) const Value& COMBINE(p, I) +#define E__NFBody(I) \ +String Format(const char *fmt, __List##I(E__NFValue)); +__Expand5(E__NFBody) + +// ============= + +INITBLOCK { + Value::SvoRegister("Color"); +} + +// ============= + + + #define max (a, b) (a < b ? b : a) + +max(12, 23) + +max (A, B) + +#undef max + +#define max(a, b) (a < b ? b : a) + +max(12, 23) + +max (A, B) + +// ============= + +#define macro something // comment + +macro +something +//$- comment + +#define mm(a, b, c, d) (d) [c] {b} + +mm(1, 2, 3, 4) + +mm(1, 2, +3, 4) + +mm(1, +2, +3, +4 +) + +// ============= + +#define MACRO(x) 123+x + +MACRO( +x +) + +MACRO(x +) + +MACRO(x) + + MACRO(x) + + MACRO(x +) + +// ============= + +#undef _STCONS + + #define _STCONS(ty, name, val) static const ty name = (ty)(val) + + _STCONS(float_denorm_style, has_denorm, denorm_absent); + + + +#define InterlockedIncrement16 _InterlockedIncrement16 + +SHORT +InterlockedIncrement16 ( + SHORT volatile *Addend +); diff --git a/autotest/PPTest/init b/autotest/PPTest/init new file mode 100644 index 000000000..3b2d60dcc --- /dev/null +++ b/autotest/PPTest/init @@ -0,0 +1,5 @@ +#ifndef _PPTest_icpp_init_stub +#define _PPTest_icpp_init_stub +#include "Core/init" +#include "CppBase/init" +#endif diff --git a/autotest/PPTest/test.in b/autotest/PPTest/test.in new file mode 100644 index 000000000..84d35d650 --- /dev/null +++ b/autotest/PPTest/test.in @@ -0,0 +1,127 @@ +#define COMBINE__(a, b) a##b +#define COMBINE(a, b) COMBINE__(a, b) + +#define COMBINE3__(a, b, c) a##b##c +#define COMBINE3(a, b, c) COMBINE3__(a, b, c) + +#define COMBINE4__(a, b, c, d) a##b##c##d +#define COMBINE4(a, b, c, d) COMBINE4__(a, b, c, d) + +#define COMBINE5__(a, b, c, d, e) a##b##c##d##e +#define COMBINE5(a, b, c, d, e) COMBINE5__(a, b, c, d, e) + +#define _cm_ , + +#define __countof(a) int(sizeof(a) / sizeof(a[0])) + +#define __Expand1(x) x(1) +#define __Expand2(x) __Expand1(x) x(2) +#define __Expand3(x) __Expand2(x) x(3) +#define __Expand4(x) __Expand3(x) x(4) +#define __Expand5(x) __Expand4(x) x(5) + +#define __List1(x) x(1) +#define __List2(x) __List1(x), x(2) +#define __List3(x) __List2(x), x(3) +#define __List4(x) __List3(x), x(4) +#define __List5(x) __List4(x), x(5) + +#define E__p(I) p##I + +#define MK__s__(x) s__s##x +#define MK__s_(x) MK__s__(x) + +// #define MK__s MK__s_(__LINE__) + +#define MK__s MK__s_(COMBINE3(BLITZ_INDEX__, _, __LINE__)) + +#define INITBLOCK \ +static void COMBINE(MK__s, _fn)(); static UPP::Callinit MK__s(COMBINE(MK__s, _fn), __FILE__, __LINE__); \ +static void COMBINE(MK__s, _fn)() + + +//--------------------------------------------------- + +#define E__NFValue(I) const Value& COMBINE(p, I) +#define E__NFBody(I) \ +String Format(const char *fmt, __List##I(E__NFValue)); +__Expand5(E__NFBody) + +// ============= + +INITBLOCK { + Value::SvoRegister("Color"); +} + +// ============= + + + #define max (a, b) (a < b ? b : a) + +max(12, 23) + +max (A, B) + +#undef max + +#define max(a, b) (a < b ? b : a) + +max(12, 23) + +max (A, B) + +// ============= + +#define macro something // comment + +macro +something +//$- comment + +#define mm(a, b, c, d) (d) [c] {b} + +mm(1, 2, 3, 4) + +mm(1, 2, +3, 4) + +mm(1, +2, +3, +4 +) + +// ============= + +#define MACRO(x) 123+x + +MACRO( +x +) + +MACRO(x +) + +MACRO(x) + + MACRO(x) + + MACRO(x +) + +// ============= + +#undef _STCONS + + #define _STCONS(ty, name, val) static const ty name = (ty)(val) + + _STCONS(float_denorm_style, has_denorm, denorm_absent); + + + +#define InterlockedIncrement16 _InterlockedIncrement16 + +SHORT +InterlockedIncrement16 ( + SHORT volatile *Addend +); diff --git a/autotest/PPTest/test.out b/autotest/PPTest/test.out new file mode 100644 index 000000000..d5e4e1854 --- /dev/null +++ b/autotest/PPTest/test.out @@ -0,0 +1,127 @@ +#define COMBINE__(a, b) a##b +#define COMBINE(a, b) COMBINE__(a, b) + +#define COMBINE3__(a, b, c) a##b##c +#define COMBINE3(a, b, c) COMBINE3__(a, b, c) + +#define COMBINE4__(a, b, c, d) a##b##c##d +#define COMBINE4(a, b, c, d) COMBINE4__(a, b, c, d) + +#define COMBINE5__(a, b, c, d, e) a##b##c##d##e +#define COMBINE5(a, b, c, d, e) COMBINE5__(a, b, c, d, e) + +#define _cm_ , + +#define __countof(a) int(sizeof(a) / sizeof(a[0])) + +#define __Expand1(x) x(1) +#define __Expand2(x) __Expand1(x) x(2) +#define __Expand3(x) __Expand2(x) x(3) +#define __Expand4(x) __Expand3(x) x(4) +#define __Expand5(x) __Expand4(x) x(5) + +#define __List1(x) x(1) +#define __List2(x) __List1(x), x(2) +#define __List3(x) __List2(x), x(3) +#define __List4(x) __List3(x), x(4) +#define __List5(x) __List4(x), x(5) + +#define E__p(I) p##I + +#define MK__s__(x) s__s##x +#define MK__s_(x) MK__s__(x) + +// #define MK__s MK__s_(__LINE__) + +#define MK__s MK__s_(COMBINE3(BLITZ_INDEX__, _, __LINE__)) + +#define INITBLOCK static void COMBINE(MK__s, _fn)(); static UPP::Callinit MK__s(COMBINE(MK__s, _fn), __FILE__, __LINE__); static void COMBINE(MK__s, _fn)() + + + + +//--------------------------------------------------- + +#define E__NFValue(I) const Value& COMBINE(p, I) +#define E__NFBody(I) String Format(const char *fmt, __List##I(E__NFValue)); + +String Format(const char *fmt, const Value& p1); String Format(const char *fmt, const Value& p1, const Value& p2); String Format(const char *fmt, const Value& p1, const Value& p2, const Value& p3); String Format(const char *fmt, const Value& p1, const Value& p2, const Value& p3, const Value& p4); String Format(const char *fmt, const Value& p1, const Value& p2, const Value& p3, const Value& p4, const Value& p5); + +// ============= + + static void s__sBLITZ_INDEX_____LINE___fn(); static UPP::Callinit  s__sBLITZ_INDEX_____LINE__(s__sBLITZ_INDEX_____LINE___fn, __FILE__, __LINE__); static void s__sBLITZ_INDEX_____LINE___fn() { + Value::SvoRegister("Color"); +} + +// ============= + + + #define max (a, b) (a < b ? b : a) + + (a, b) (a < b ? b : a)(12, 23) + + (a, b) (a < b ? b : a) (A, B) + +#undef max + +#define max(a, b) (a < b ? b : a) + +(12 < 23 ? 23 : 12) + +(A < B ? B : A) + +// ============= + +#define macro something // comment + + something +something +//$- comment + +#define mm(a, b, c, d) (d) [c] {b} + +(4) [3] {2} <1> + + +(4) [3] {2} <1> + + + + + +(4) [3] {2} <1> + +// ============= + +#define MACRO(x) 123+x + + + +123+x + + +123+x + +123+x + + 123+x + + + 123+x + +// ============= + +#undef _STCONS + + #define _STCONS(ty, name, val) static const ty name = (ty)(val) + + static const float_denorm_style has_denorm = (float_denorm_style)(denorm_absent); + + + +#define InterlockedIncrement16 _InterlockedIncrement16 + +SHORT + _InterlockedIncrement16 ( + SHORT volatile *Addend +); diff --git a/uppdev/CppTest/CppTest.upp b/uppdev/CppTest/CppTest.upp new file mode 100644 index 000000000..931b7e7c6 --- /dev/null +++ b/uppdev/CppTest/CppTest.upp @@ -0,0 +1,8 @@ +file + file.cpp, + file2.h, + file1.h; + +mainconfig + "" = ""; + diff --git a/uppdev/CppTest/file.cpp b/uppdev/CppTest/file.cpp new file mode 100644 index 000000000..c07256e78 --- /dev/null +++ b/uppdev/CppTest/file.cpp @@ -0,0 +1,7 @@ +#include "file2.h" + +void Foo2() {} + +MACRO(printf("Hello!")); + +void Foo() {} \ No newline at end of file diff --git a/uppdev/CppTest/file1.h b/uppdev/CppTest/file1.h new file mode 100644 index 000000000..b46007d6f --- /dev/null +++ b/uppdev/CppTest/file1.h @@ -0,0 +1,5 @@ +#define MACRO3 + +#define MACRO_NEW test + +#include "file2.h" diff --git a/uppdev/CppTest/file2.h b/uppdev/CppTest/file2.h new file mode 100644 index 000000000..9fde705cf --- /dev/null +++ b/uppdev/CppTest/file2.h @@ -0,0 +1,3 @@ +#define MACRO(x) void main() { x; }x + +#define MACRO3 xxx2333 \ No newline at end of file diff --git a/uppdev/CppTest/init b/uppdev/CppTest/init new file mode 100644 index 000000000..89a4c07a1 --- /dev/null +++ b/uppdev/CppTest/init @@ -0,0 +1,3 @@ +#ifndef _CppTest_icpp_init_stub +#define _CppTest_icpp_init_stub +#endif diff --git a/uppdev/TestCppParser/CppParser.cpp b/uppdev/TestCppParser/CppParser.cpp new file mode 100644 index 000000000..8ae4325c6 --- /dev/null +++ b/uppdev/TestCppParser/CppParser.cpp @@ -0,0 +1,79 @@ +#include + +using namespace Upp; + +Vector errs; + +void AddError(int ln, const String& s) +{ + errs.Add(AsString(ln) + ": " + s); +} + +void Test(const char *path) +{ + CppBase base; + + LOG("**** " << GetFileName(path)); + + FileIn in(path); + errs.Clear(); + + Index hh; + hh.Add("test"); + + Parser p; +// p.Do(in, base, 0, 0, GetFileTitle(path), callback(AddError), Vector(), Vector(), Index()); + p.Do(in, base, 0, 0, GetFileTitle(path), callback(AddError), + Vector(), Vector(), hh); + + if(errs.GetCount()) + DUMPC(errs); + 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) << ", name: " << m.name << ", qitem: " << m.qitem + << ", qtype " << m.qtype << ", qptype: " << m.qptype << ", line " << m.line + << ", using " << m.using_namespaces + << ", item " << m.item + << ", natural " << m.natural + << "\n"; + } + out << "}\n"; + } + +// base.Dump(VppLog()); + + p.dobody = true; + in.Seek(0); + p.Do(in, base, 0, 0, GetFileTitle(path), callback(AddError), + Vector(), Vector(), hh); + + out << " {\n"; + for(int i = 0; i < p.local.GetCount(); i++) { + out << p.local.GetKey(i) << " " << p.local[i].type; + if(p.local[i].isptr) + out << " pointer"; + out << ", line: " << p.local[i].line << "\n"; + } + out << "}"; + LOG("===="); + LOG(out); + LOG("-------------------------------------------------------------------------------"); +} + +CONSOLE_APP_MAIN { + StdLogSetup(LOG_COUT|LOG_FILE); +// Test("C:/xxx/cpp/math"); + Test(GetDataFile("test1.in")); + /* + FindFile ff(GetDataFile("test1.in")); + while(ff) { + Test(ff.GetPath()); + ff.Next(); + } + */ +} diff --git a/uppdev/TestCppParser/TestCppParser.upp b/uppdev/TestCppParser/TestCppParser.upp new file mode 100644 index 000000000..840563d49 --- /dev/null +++ b/uppdev/TestCppParser/TestCppParser.upp @@ -0,0 +1,18 @@ +uses + Core, + CppBase; + +file + CppParser.cpp, + todo.txt, + test1.in, + test1.out, + test2.in, + test2.out, + test3.in, + todo.in, + totest.in; + +mainconfig + "" = "SSE2"; + diff --git a/uppdev/TestCppParser/init b/uppdev/TestCppParser/init new file mode 100644 index 000000000..15dd72215 --- /dev/null +++ b/uppdev/TestCppParser/init @@ -0,0 +1,5 @@ +#ifndef _TestCppParser_icpp_init_stub +#define _TestCppParser_icpp_init_stub +#include "Core/init" +#include "CppBase/init" +#endif diff --git a/uppdev/TestCppParser/test1.in b/uppdev/TestCppParser/test1.in new file mode 100644 index 000000000..a96cf32f8 --- /dev/null +++ b/uppdev/TestCppParser/test1.in @@ -0,0 +1 @@ +inline int static foo(); \ No newline at end of file diff --git a/upptst/CppParser/test1.out b/uppdev/TestCppParser/test1.out similarity index 100% rename from upptst/CppParser/test1.out rename to uppdev/TestCppParser/test1.out diff --git a/uppdev/TestCppParser/test2.in b/uppdev/TestCppParser/test2.in new file mode 100644 index 000000000..b119cebfa --- /dev/null +++ b/uppdev/TestCppParser/test2.in @@ -0,0 +1,29 @@ +typedef struct { + int x; + struct Foo { + int a; + } y; + struct { + int bar; + }; + struct { + int foo; + } quack; +} name; + +namespace std { + struct string {}; +}; + +// void Foo(string a); + +using namespace std; + +struct Bar { + struct string {}; + + std::string Foo(string a); +}; + +void Foo(string a); + diff --git a/upptst/CppParser/test3.in b/uppdev/TestCppParser/test3.in similarity index 100% rename from upptst/CppParser/test3.in rename to uppdev/TestCppParser/test3.in diff --git a/uppdev/TestCppParser/todo.in b/uppdev/TestCppParser/todo.in new file mode 100644 index 000000000..0122a9ae7 --- /dev/null +++ b/uppdev/TestCppParser/todo.in @@ -0,0 +1,31 @@ +============ +struct Foo { + struct Foo; + + Foo *x; +}; +============ + +String EncodeHtml(const RichText& text, Index& css, + const VectorMap& links, + const VectorMap& labels, + const String& path, const String& base = Null, Zoom z = Zoom(8, 40), + const VectorMap& escape = VectorMap(), + int imtolerance = 0); + +============ + _onexit_t onexit( [SA_Pre( Null=SA_Maybe)] [SA_Pre(Deref=1, Valid=SA_Yes)] [SA_Pre(Deref=1, Access=SA_Read)] _onexit_t _Func); +============ +typedef struct tagMONCONVSTRUCT { + UINT cb; + BOOL fConnect; + DWORD dwTime; + HANDLE hTask; + HSZ hszSvc; + HSZ hszTopic; + HCONV hConvClient; // Globally unique value != apps local hConv + HCONV hConvServer; // Globally unique value != apps local hConv +} MONCONVSTRUCT, *PMONCONVSTRUCT; +// ^^^^ have invalid line number +============= +typedef GUID *REFGUID; diff --git a/uppdev/TestCppParser/totest.in b/uppdev/TestCppParser/totest.in new file mode 100644 index 000000000..8fb1b8122 --- /dev/null +++ b/uppdev/TestCppParser/totest.in @@ -0,0 +1,5 @@ +======================== +[attr] [attr] int function([attr] [attr] string x[4], [attr] int y[4], [attr] const int& x); +============== +; +============== diff --git a/uppdev/cpp2/cpp.cpp b/uppdev/cpp2/cpp.cpp deleted file mode 100644 index 291a44e2c..000000000 --- a/uppdev/cpp2/cpp.cpp +++ /dev/null @@ -1,243 +0,0 @@ -#include "cpp.h" - -void Cpp::Define(const char *s) -{ - CppMacro m; - String id = m.Define(s); - if(id.GetCount()) - macro.GetAdd(id) = pick(m); -} - -const char *Cpp::SkipString(const char *s) -{ - CParser p(s); - p.ReadOneString(*s); - s = p.GetPtr(); - while((byte)*(s - 1) <= ' ') - s--; - return s; -} - -void Cpp::ParamAdd(Vector& param, const char *s, const char *e) -{ - while(s < e && (byte)*s <= ' ') s++; - while(e > s && (byte)*(e - 1) <= ' ') e--; - String h; - while(s < e) { - if((byte)*s <= ' ') { - h.Cat(' '); - s++; - while(s < e && (byte)*s <= ' ') - s++; - } - else - if(*s == '\"' || *s == '\'') { - const char *q = SkipString(s); - h.Cat(String(s, q)); - s = q; - } - else - h.Cat(*s++); - } - param.Add(h); -} - -String Cpp::Expand(const char *s) -{ - Index notmacro; - return Expand(s, notmacro); -} - -String Cpp::Expand(const char *s, Index& notmacro) -{ - StringBuffer r; - while(*s) { - if(incomment) { - if(s[0] == '*' && s[1] == '/') { - incomment = false; - s += 2; - r.Cat("*/"); - } - else - r.Cat(*s++); - } - else - if(iscib(*s)) { - const char *b = s; - s++; - while(iscid(*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); - } - } - 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; -} - -bool Cpp::Preprocess(const String& sourcefile, Stream& in, const String& currentfile, - const Index *get_macros) -{ - macro.Clear(); - Vector ignorelist = Split("__declspec;__cdecl;" - "__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]).param = "."; - done = false; - incomment = false; - Index visited; - if(get_macros) - DUMP(*get_macros); - Do(NormalizePath(sourcefile), in, NormalizePath(currentfile), visited, get_macros); - return done; -} - -void Cpp::Do(const String& sourcefile, Stream& in, const String& currentfile, - Index& visited, const Index *get_macros) -{ -// DUMP(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); - #ifdef _DEBUG - pp.Dump(); - #endif - for(int i = 0; i < pp.item.GetCount() && !done; i++) { - const PPItem& m = pp.item[i]; - if(m.type == PP_DEFINE) { -// RTIMING("macro Add"); - if(!get_macros || get_macros->Find(m.id) >= 0) - macro.GetAdd(m.id) = 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, get_macros); - } - 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; - } - - done = true; - if(get_macros) - return; - - RTIMING("Expand"); - incomment = false; - StringBuffer result; - result.Clear(); - result.Reserve(16384); - int lineno = 0; - bool incomment = false; - while(!in.IsEof()) { - String l = in.GetLine(); - lineno++; - int el = 0; - while(*l.Last() == '\\' && !in.IsEof()) { - el++; - l.Trim(l.GetLength() - 1); - l.Cat(in.GetLine()); - } - 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(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, get_macros); - } - } - } - else { - result.Cat(Expand(l) + "\n"); - } - while(el--) - result.Cat("\n"); - } - DUMP(macro.GetCount()); - output = result; -} diff --git a/uppdev/cpp2/cpp.h b/uppdev/cpp2/cpp.h index 3ddec8b27..e83bbf397 100644 --- a/uppdev/cpp2/cpp.h +++ b/uppdev/cpp2/cpp.h @@ -7,78 +7,4 @@ using namespace Upp; -void RemoveComments(String& l, bool& incomment); - -struct CppMacro : Moveable, DeepCopyOption { - String param; - String body; - - String Define(const char *s); - - String Expand(const Vector& p) const; - - String ToString() const; -}; - -enum PPItemType { - PP_DEFINE, - PP_INCLUDE, - PP_USING, - PP_NAMESPACE, - PP_NAMESPACE_END -}; - -struct PPItem { - int type; - String id; - CppMacro macro; -}; - -struct PPFile { // contains "macro extract" of file, only info about macros defined and namespaces - FileTime filetime; - Array item; - Index includes; - - void Parse(Stream& in); - - void Dump() const; - -private: - void CheckEndNamespace(Vector& namespace_block, int level); -}; - -const PPFile& GetPPFile(const char *path); - -String GetIncludePath(const String& s, const String& filedir, 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 include_path; - - VectorMap macro; - - String output; - Index usedmacro; - Index namespace_using; - Vector namespace_stack; - - void Define(const char *s); - - static const char *SkipString(const char *s); - void ParamAdd(Vector& param, const char *b, const char *e); - String Expand(const char *s, Index& notmacro); - String Expand(const char *s); - void Do(const String& sourcefile, Stream& in, const String& currentfile, - Index& visited, const Index *get_macros); - - bool Preprocess(const String& sourcefile, Stream& in, const String& currentfile, - const Index *get_macros = NULL); - - typedef Cpp CLASSNAME; -}; - #endif diff --git a/uppdev/cpp2/cpp.txt b/uppdev/cpp2/cpp.txt index 501a6bbaf..296888b89 100644 --- a/uppdev/cpp2/cpp.txt +++ b/uppdev/cpp2/cpp.txt @@ -1 +1,79 @@ - \ No newline at end of file +Gather files 0.375 +Checking files 0.031 +Removing files 0.000 +Parsing files 5.125 +TIMING PP_DEFINE : 0.00 ns - 0.00 ns (593.00 ms / 12471437 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 12471437 +TIMING Parse : 636.94 ms - 554.35 us (637.00 ms / 1149 ), min: 0.00 ns, max: 16.00 ms, nesting: 1 - 1149 +TIMING Expand : 424.95 ms - 376.39 us (425.00 ms / 1129 ), min: 0.00 ns, max: 38.00 ms, nesting: 1 - 1129 +TIMING macros : 500.95 ms - 443.71 us (501.00 ms / 1129 ), min: 0.00 ns, max: 2.00 ms, nesting: 1 - 1129 +TIMING Gather IDs : 208.95 ms - 185.07 us (209.00 ms / 1129 ), min: 0.00 ns, max: 9.00 ms, nesting: 1 - 1129 +TIMING GetMasterFile : 742.94 ms - 646.60 us (743.00 ms / 1149 ), min: 0.00 ns, max: 4.00 ms, nesting: 1 - 1149 +TIMING Preprocess : 3.25 s - 2.83 ms ( 3.25 s / 1149 ), min: 0.00 ns, max: 45.00 ms, nesting: 1 - 1149 +TIMING GetIncludePath : 190.24 ms - 420.12 ns (212.00 ms / 452817 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 452817 +TIMING sCppFile make : 999.95 us - 999.95 us ( 1.00 ms / 1 ), min: 1.00 ms, max: 1.00 ms, nesting: 1 - 1 + + +Gather files 0.375 +Checking files 0.016 +Removing files 0.000 +Parsing files 6.531 +TIMING PP_DEFINE : 1.67 s - 134.20 ns ( 2.30 s / 12471407 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 12471407 +TIMING Parse : 676.94 ms - 589.16 us (677.00 ms / 1149 ), min: 0.00 ns, max: 27.00 ms, nesting: 1 - 1149 +TIMING Expand : 523.94 ms - 464.08 us (524.00 ms / 1129 ), min: 0.00 ns, max: 39.00 ms, nesting: 1 - 1129 +TIMING GetMasterFile : 728.94 ms - 634.41 us (729.00 ms / 1149 ), min: 0.00 ns, max: 4.00 ms, nesting: 1 - 1149 +TIMING Preprocess : 4.41 s - 3.84 ms ( 4.41 s / 1149 ), min: 0.00 ns, max: 50.00 ms, nesting: 1 - 1149 +TIMING GetIncludePath : 189.15 ms - 417.72 ns (212.00 ms / 452817 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 452817 +TIMING sCppFile make : 999.95 us - 999.95 us ( 1.00 ms / 1 ), min: 1.00 ms, max: 1.00 ms, nesting: 1 - 1 + +* c:\upp\cppide.exe 29.03.2015 22:44:02, user: cxl + +Gather files 0.375 +Checking files 0.016 +Removing files 0.000 +Parsing files 5.109 +TIMING PP_DEFINE : 0.00 ns - 0.00 ns (609.00 ms / 12471437 ), min: 0.00 ns, max: 2.00 ms, nesting: 1 - 12471437 +TIMING Parse : 658.94 ms - 573.49 us (659.00 ms / 1149 ), min: 0.00 ns, max: 16.00 ms, nesting: 1 - 1149 +TIMING Expand : 408.94 ms - 362.22 us (409.00 ms / 1129 ), min: 0.00 ns, max: 38.00 ms, nesting: 1 - 1129 +TIMING macros : 487.94 ms - 432.19 us (488.00 ms / 1129 ), min: 0.00 ns, max: 2.00 ms, nesting: 1 - 1129 +TIMING add macro : 65.11 ms - 30.71 ns (169.00 ms / 2120492 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 2120492 +TIMING Gather IDs : 382.94 ms - 339.19 us (383.00 ms / 1129 ), min: 0.00 ns, max: 16.00 ms, nesting: 1 - 1129 +TIMING GetMasterFile : 705.94 ms - 614.40 us (706.00 ms / 1149 ), min: 0.00 ns, max: 5.00 ms, nesting: 1 - 1149 +TIMING Preprocess : 3.32 s - 2.89 ms ( 3.32 s / 1149 ), min: 0.00 ns, max: 45.00 ms, nesting: 1 - 1149 +TIMING GetIncludePath : 188.82 ms - 416.98 ns (211.00 ms / 452817 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 452817 +TIMING PP read : 302.94 ms - 263.43 us (303.00 ms / 1150 ), min: 0.00 ns, max: 10.00 ms, nesting: 1 - 1150 +TIMING sCppFile make : 999.95 us - 999.95 us ( 1.00 ms / 1 ), min: 1.00 ms, max: 1.00 ms, nesting: 1 - 1 + + +* c:\upp\cppide.exe 30.03.2015 22:21:31, user: cxl + +Gather files 0.687 +Checking files 0.032 +Removing files 0.000 +Parsing files 3.281 +TIMING PP_DEFINES : 0.00 ns - 0.00 ns ( 5.00 ms / 154902 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 154902 +TIMING Parse : 631.95 ms - 551.44 us (632.00 ms / 1146 ), min: 0.00 ns, max: 26.00 ms, nesting: 1 - 1146 +TIMING Expand include : 10.90 ms - 4.96 us (11.00 ms / 2199 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 2199 +TIMING Expand expand : 544.38 ms - 831.97 ns (574.00 ms / 654331 ), min: 0.00 ns, max: 16.00 ms, nesting: 1 - 654331 +TIMING Expand define : 13.69 ms - 268.12 ns (16.00 ms / 51057 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 51057 +TIMING Expand : 737.95 ms - 655.37 us (738.00 ms / 1126 ), min: 0.00 ns, max: 39.00 ms, nesting: 1 - 1126 +TIMING GetMasterFile : 695.95 ms - 607.28 us (696.00 ms / 1146 ), min: 0.00 ns, max: 4.00 ms, nesting: 1 - 1146 +TIMING Preprocess : 1.59 s - 1.38 ms ( 1.59 s / 1146 ), min: 0.00 ns, max: 41.00 ms, nesting: 1 - 1146 +TIMING GetIncludePath : 188.51 ms - 416.39 ns (209.00 ms / 452724 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 452724 +TIMING PP read : 492.95 ms - 429.77 us (493.00 ms / 1147 ), min: 0.00 ns, max: 11.00 ms, nesting: 1 - 1147 +TIMING sCppFile make : 999.95 us - 999.95 us ( 1.00 ms / 1 ), min: 1.00 ms, max: 1.00 ms, nesting: 1 - 1 + +Gather files 0.375 +Checking files 0.016 +Removing files 0.000 +Parsing files 3.297 +TIMING PP_DEFINES : 869.25 us - 5.61 ns ( 7.00 ms / 154902 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 154902 +TIMING Parse : 656.95 ms - 573.26 us (657.00 ms / 1146 ), min: 0.00 ns, max: 25.00 ms, nesting: 1 - 1146 +TIMING Expand include : 4.91 ms - 2.23 us ( 5.00 ms / 2199 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 2199 +TIMING Expand expand : 517.10 ms - 790.28 ns (543.00 ms / 654331 ), min: 0.00 ns, max: 16.00 ms, nesting: 1 - 654331 +TIMING Expand define : 19.98 ms - 391.31 ns (22.00 ms / 51057 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 51057 +TIMING Expand : 731.96 ms - 650.05 us (732.00 ms / 1126 ), min: 0.00 ns, max: 40.00 ms, nesting: 1 - 1126 +TIMING GetMasterFile : 699.95 ms - 610.78 us (700.00 ms / 1146 ), min: 0.00 ns, max: 4.00 ms, nesting: 1 - 1146 +TIMING Preprocess : 1.58 s - 1.38 ms ( 1.58 s / 1146 ), min: 0.00 ns, max: 41.00 ms, nesting: 1 - 1146 +TIMING GetIncludePath : 166.08 ms - 366.85 ns (184.00 ms / 452724 ), min: 0.00 ns, max: 1.00 ms, nesting: 1 - 452724 +TIMING PP read : 315.95 ms - 275.46 us (316.00 ms / 1147 ), min: 0.00 ns, max: 11.00 ms, nesting: 1 - 1147 +TIMING sCppFile make : 999.96 us - 999.96 us ( 1.00 ms / 1 ), min: 1.00 ms, max: 1.00 ms, nesting: 1 - 1 diff --git a/uppdev/cpp2/cpp2.upp b/uppdev/cpp2/cpp2.upp index e58afb04f..3a88705f2 100644 --- a/uppdev/cpp2/cpp2.upp +++ b/uppdev/cpp2/cpp2.upp @@ -4,9 +4,6 @@ uses file cpp.h, - macro.cpp, - ppfile.cpp, - cpp.cpp, main.cpp, test.h, testfile, diff --git a/uppdev/cpp2/main.cpp b/uppdev/cpp2/main.cpp index f977eb60b..84ad21346 100644 --- a/uppdev/cpp2/main.cpp +++ b/uppdev/cpp2/main.cpp @@ -22,11 +22,13 @@ void Test(const char *sourcefile, const char *currentfile) { RTIMING("Preprocess"); cpp.Preprocess(sourcefile, in, currentfile); DUMP(cpp.namespace_stack); -// DDUMP(cpp.output); DUMP(cpp.usedmacro); + DUMP(cpp.macro.GetCount()); } LOG("================================="); + LOG(cpp.output); +/* { Cpp cpp2; cpp2.include_path = include_path; @@ -40,6 +42,7 @@ void Test(const char *sourcefile, const char *currentfile) cpp2.include_path = include_path; cpp2.Preprocess(sourcefile, NilStream(), currentfile, &cpp.usedmacro); } +*/ } void TestC(const char *ln) @@ -68,45 +71,10 @@ CONSOLE_APP_MAIN // f.Parse(in); // f.Dump(); + GetPPFile("C:\\u\\upp.src\\uppsrc\\Core\\Core.h").Dump(); + DLOG("=============="); + Test("C:\\u\\upp.src\\uppsrc\\Core\\Format.h", "C:\\u\\upp.src\\uppsrc\\Core\\Format.cpp"); -// 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\\Format.h", "C:\\u\\upp.src\\uppsrc\\Core\\Format.cpp"); - } -#ifndef _DEBUG - for(int i = 0; i < 100; i++) { - Test("C:\\u\\upp.src\\uppsrc\\Core\\Format.h", "C:\\u\\upp.src\\uppsrc\\Core\\Format.cpp"); - } -#endif -#if 0 - { - RTIMING("Pass1"); - Index visited; -// RecursePP("c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp", include_path, visited); - } - - 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"); - IncludesFile("c:/u/upp.src/uppsrc/CtrlLib/EditField.cpp", "c:/u/upp.src/uppsrc/Core/Core.h", include_path); - } - - for(int i = 0; i < 1000; i++) { - 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 deleted file mode 100644 index f3c64211d..000000000 --- a/uppdev/cpp2/ppfile.cpp +++ /dev/null @@ -1,285 +0,0 @@ -#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; - } -} - -void PPFile::CheckEndNamespace(Vector& namespace_block, int level) -{ - if(namespace_block.GetCount() && namespace_block.Top() == level) { - namespace_block.Drop(); - item.Add().type = PP_NAMESPACE_END; - } -} - -void PPFile::Parse(Stream& in) -{ - item.Clear(); - includes.Clear(); - bool was_using = false; - bool was_namespace = false; - int level = 0; - bool incomment = false; - Vector namespace_block; - 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('#')) { - if(p.Id("define")) { - PPItem& m = item.Add(); - m.type = PP_DEFINE; - m.id = m.macro.Define(p.GetPtr()); - if(IsNull(m.id)) - item.Drop(); - } - else - if(p.Id("include")) { - PPItem& m = item.Add(); - m.type = PP_INCLUDE; - m.id = TrimBoth(p.GetPtr()); - if(IsNull(m.id)) - item.Drop(); - else - includes.FindAdd(m.id); - } - } - else { - while(!p.IsEof()) { - if(was_namespace) { - int type = was_using ? PP_USING : PP_NAMESPACE; - String id; - while(p.Char2(':', ':')) - id = "::"; - id << p.ReadId(); - while(p.Char2(':', ':')) - id << "::" << p.ReadId(); - if(!was_using) - namespace_block.Add(level); - PPItem& m = item.Add(); - m.type = type; - m.id = id; - was_namespace = was_using = false; - } - else - if(p.Id("using")) - was_using = true; - else - if(p.Id("namespace")) - was_namespace = true; - else { - was_using = was_namespace = false; - if(p.IsId()) { - static VectorMap namespace_macro; // TODO: Make this ugly trick dynamic - ONCELOCK { - namespace_macro.Add("_STD_BEGIN", "std"); - namespace_macro.Add("_C_STD_BEGIN", "std"); - namespace_macro.Add("_STDEXT_BEGIN", "stdext"); - namespace_macro.Add("NAMESPACE_UPP", "Upp"); - } - static Index namespace_end_macro; - ONCELOCK { - namespace_end_macro.Add("_STD_END"); - namespace_end_macro.Add("_STDEXT_END"); - namespace_end_macro.Add("_C_STD_END"); - namespace_end_macro.Add("END_UPP_NAMESPACE"); - } - - String id = p.ReadId(); - int q = namespace_macro.Find(id); - if(q > 0) { - PPItem& m = item.Add(); - m.type = PP_NAMESPACE; - m.id = namespace_macro[q]; - namespace_block.Add(level); - level++; - } - else { - q = namespace_end_macro.Find(id); - if(q >= 0) { - level--; - CheckEndNamespace(namespace_block, level); - } - } - } - else - if(p.Char('}')) { - if(level > 0) { - level--; - CheckEndNamespace(namespace_block, level); - } - } - else - if(p.Char('{')) - level++; - else - p.SkipTerm(); - } - } - } - } - catch(...) {} - } -} - -void PPFile::Dump() const -{ - for(int i = 0; i < item.GetCount(); i++) { - const PPItem& m = item[i]; - String ll; - ll << decode(m.type, PP_DEFINE, "#define", PP_INCLUDE, "#include", - PP_USING, "using namespace", PP_NAMESPACE, "namespace", - PP_NAMESPACE_END, "}", "") - << ' ' << m.id; - if(m.type == PP_DEFINE) - ll << m.macro; - if(m.type == PP_NAMESPACE) - ll << " {"; - LOG(ll); - } - LOG("----- includes:"); - DUMPC(includes); -} - -static ArrayMap sPathFileTime; -static VectorMap sIncludePath; -static VectorMap sIncludes; - -void PPSyncPath() -{ - sPathFileTime.Clear(); - sIncludePath.Clear(); - sIncludes.Clear(); -} - -String GetIncludePath0(const char *s, const char *filedir, const String& include_path) -{ - 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; -} - -FileTime GetFileTimeCached(const String& p) -{ - int q = sPathFileTime.Find(p); - if(q >= 0) - return sPathFileTime[q]; - FileTime m = GetFileTime(p); - sPathFileTime.Add(p, m); - return m; -} - -String GetIncludePath(const String& s, const String& filedir, const String& include_path) -{ - RTIMING("GetIncludePath"); - String key; - key << s << "#" << filedir << "#" << include_path; - int q = sIncludePath.Find(key); - if(q >= 0) - return sIncludePath[q]; - String p = GetIncludePath0(s, filedir, include_path); - sIncludePath.Add(key, p); - return p; -} - -const PPFile& GetPPFile(const char *path) -{ - static ArrayMap file; - FileTime tm = GetFileTimeCached(path); - PPFile& f = file.GetAdd(path); - if(f.filetime != tm) { - f.filetime = tm; - FileIn in(path); - f.Parse(in); - } - return f; -} - -bool IsSameFile(const String& f1, const String& f2) -{ - return NormalizePath(f1) == NormalizePath(f2); -} - -bool IncludesFile(const String& parent_path, const String& path, const String& include_path, Index& visited) -{ - if(visited.Find(parent_path) >= 0) - return false; - visited.Add(parent_path); - if(IsSameFile(parent_path, path)) - return true; - const PPFile& f = GetPPFile(parent_path); - for(int i = 0; i < f.includes.GetCount(); i++) { - String p = GetIncludePath(f.includes[i], GetFileFolder(parent_path), include_path); - if(p.GetCount()) { - String key = p + "#" + path; - int q = sIncludes.Find(key); - if(q >= 0) { - if(sIncludes[q]) - return true; - } - else { - bool b = IncludesFile(p, path, include_path, visited); - sIncludes.Add(key, b); - if(b) - return true; - } - } - } - return false; -} - -bool IncludesFile(const String& parent_path, const String& path, const String& include_path) -{ - Index visited; - return IncludesFile(parent_path, path, include_path, visited); -} diff --git a/uppsrc/CppBase/ScopeInfo.cpp b/uppsrc/CppBase/ScopeInfo.cpp new file mode 100644 index 000000000..1ba156371 --- /dev/null +++ b/uppsrc/CppBase/ScopeInfo.cpp @@ -0,0 +1,132 @@ +#include "CppBase.h" + +NAMESPACE_UPP + +#define LLOG(x) +#define LTIMING(x) // RTIMING(x) + +ScopeInfo::ScopeInfo(const CppBase& base, int scopei) + : scopei(scopei), base(base) +{ + LTIMING("ScopeInfo(const CppBase& base, int scopei)"); + Init(); +} + +ScopeInfo::ScopeInfo(int scopei, const CppBase& base) + : scopei(scopei), base(base) +{ + LTIMING("ScopeInfo(int scopei, const CppBase& base)"); + Init(); +} + +ScopeInfo::ScopeInfo(const CppBase& base, const String& scope) + : scopei(base.Find(scope)), base(base) +{ + LTIMING("ScopeInfo(const CppBase& base, const String& scope)"); + Init(); +} + +ScopeInfo::ScopeInfo(const ScopeInfo& f) + : base(f.base) +{ + LTIMING("ScopeInfo copy contructor"); + scopes <<= f.scopes; + bvalid = nvalid = false; + scopei = f.scopei; +} + +void ScopeInfo::Init() +{ + bvalid = nvalid = false; +} + +void ScopeInfo::Bases(int i, Vector& g) +{ // recursively retrieve all base classes + if(base.IsType(i)) { + const Array& n = base[i]; + for(int i = 0; i < n.GetCount(); i++) { + const CppItem& im = n[i]; + if(im.IsType()) { + const char *q = im.qptype; + const char *b = q; + for(;;) { + if(*q == ';' || *q == '\0') { + if(b < q) { + String h = String(b, q); + int q = h.Find('<'); + if(q >= 0) + h.Trim(q); + h = TrimBoth(h); + int nq = base.Find(h); + if(nq >= 0) + g.Add(nq); + } + if(*q == '\0') + return; + q++; + b = q; + } + else + q++; + } + } + } + } +} + +const Vector& ScopeInfo::GetBases() +{ + LTIMING("GetBases"); + if(!bvalid) { + bvalid = true; + baselist.Clear(); + if(scopei < 0) + return baselist; + Vector b; + Index bi; + Bases(scopei, b); + while(b.GetCount()) { + Vector bb; + for(int i = 0; i < b.GetCount(); i++) { + int q = b[i]; + if(bi.Find(q) < 0) { + bi.Add(q); + Bases(b[i], bb); + } + } + b = pick(bb); + } + for(int i = 0; i < bi.GetCount(); i++) + baselist.Add(base.GetKey(bi[i]) + "::"); + } + return baselist; +} + +const Vector& ScopeInfo::GetScopes(const String& usings_) +{ + LTIMING("GetScopes"); + if(!nvalid || usings != usings_) { + usings = usings_; + nvalid = true; + scopes.Clear(); + if(scopei < 0) + return scopes; + String nn = base.GetKey(scopei); + while(nn.GetCount()) { + if(nn[0] == ':' && nn.GetCount() == 2) { + scopes.Add(nn); + return scopes; + } + scopes.Add(nn + "::"); + int q = nn.ReverseFind(':'); + nn.Trim(max(0, q - 1)); + } + scopes.Add(""); + Vector h = Split(usings, ';'); + for(int i = 0; i < h.GetCount(); i++) + scopes.Add(h[i] + "::"); + } + return scopes; +} + +END_UPP_NAMESPACE diff --git a/uppsrc/CppBase/cpp.cpp b/uppsrc/CppBase/cpp.cpp new file mode 100644 index 000000000..65786bd38 --- /dev/null +++ b/uppsrc/CppBase/cpp.cpp @@ -0,0 +1,400 @@ +#include "CppBase.h" + +NAMESPACE_UPP + +#define LTIMING(x) RTIMING(x) +#define LLOG(x) // DLOG(x) + +const char *Cpp::SkipString(const char *s) +{ + CParser p(s); + try { + p.ReadOneString(*s); + } + catch(CParser::Error) {} + s = p.GetPtr(); + while((byte)*(s - 1) <= ' ') + s--; + return s; +} + +void Cpp::ParamAdd(Vector& param, const char *s, const char *e) +{ + while(s < e && (byte)*s <= ' ') s++; + while(e > s && (byte)*(e - 1) <= ' ') e--; + String h; + while(s < e) { + if((byte)*s <= ' ') { + h.Cat(' '); + s++; + while(s < e && (byte)*s <= ' ') + s++; + } + else + if(*s == '\"' || *s == '\'') { + const char *q = SkipString(s); + h.Cat(String(s, q)); + s = q; + } + else + h.Cat(*s++); + } + param.Add(h); +} + +String Cpp::Expand(const char *s) +{ + StringBuffer r; + const char *l0 = s; + while(*s) { + if(incomment) { + if(s[0] == '*' && s[1] == '/') { + incomment = false; + s += 2; + r.Cat("*/"); + } + else + r.Cat(*s++); + } + else + if(iscib(*s)) { + LTIMING("Expand ID"); + const char *bid = s; + s++; + while(iscid(*s)) + s++; + String id(bid, s); + LTIMING("Expand ID2"); + ids.FindAdd(id); + if(notmacro.Find(id) < 0) { + const PPMacro *pp = macro.FindLastPtr(id); + int segmenti = pp ? segment_id.Find(pp->segment_id) : -1; + const CppMacro *m = FindMacro(id, segment_id, segmenti); + if(!m && pp) + m = &pp->macro; + if(m && m->IsUndef()) + m = NULL; + if(m) { + LTIMING("Expand macro"); + Vector param; + bool function_like = false; + const char *s0 = s; + if(m->param.GetCount()) { + while(*s && (byte)*s <= ' ') + s++; + if(*s == '(') { + function_like = true; + 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') { // macro use spread into more lines + if(bid == l0) // begin of line + prefix_macro = bid; + else + prefix_macro = String(' ', 1) + bid; // do not want to emit grounding in body + return r; + } + else + if(*s == '\"' || *s == '\'') + s = SkipString(s); + else + s++; + } + } + if(!!m->param.GetCount() == function_like) { + int ti = notmacro.GetCount(); + Vector eparam; + eparam.SetCount(param.GetCount()); + for(int i = 0; i < param.GetCount(); i++) + eparam[i] = Expand(param[i]); + notmacro.Add(id); + id = '\x1f' + Expand(m->Expand(param, eparam)); // \x1f is info for Pre that there was a macro expansion + notmacro.Trim(ti); + } + else + s = s0; + } + else + notmacro.Add(id); + } + r.Cat(id); + } + else + if(*s == '\"') { + const char *e = SkipString(s); + r.Cat(s, e); + s = e; + } + 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; +} + +Index Cpp::kw; + +bool Cpp::Preprocess(const String& sourcefile, Stream& in, const String& currentfile, + bool get_macros) +{ + LLOG("===== Preprocess " << sourcefile << " <- " << currentfile); + LTIMING("Cpp::Preprocess"); + macro.Clear(); + macro.Reserve(1000); + segment_id.Clear(); + segment_id.Reserve(100); + + const Vector& ignorelist = GetIgnoreList(); + + for(int i = 0; i < ignorelist.GetCount(); i++) { + PPMacro h; + PPMacro& pp = macro.GetAdd(h.macro.Define(ignorelist[i])); + pp = h; + pp.segment_id = -999999999; + } + segment_id.Add(-999999999); + + std_macros = macro.GetCount(); + + ONCELOCK { + const char **h = CppKeyword(); + while(*h) { + kw.Add(*h); + h++; + } + } + notmacro = clone(kw); + + done = false; + incomment = false; + Index visited; + Do(NormalizePath(sourcefile), in, NormalizePath(currentfile), visited, get_macros); + return done; +} + +void Cpp::DoFlatInclude(const String& header_path) +{ + LLOG("Flat include " << header_path); + if(header_path.GetCount()) { + const PPFile& pp = GetFlatPPFile(header_path); + LLOG("DoFlatInclude " << header_path << ", " << pp.item.GetCount() << " items"); + for(int i = 0; i < pp.item.GetCount() && !done; i++) { + const PPItem& m = pp.item[i]; + if(m.type == PP_DEFINES) { + segment_id.FindAdd(m.segment_id); + // DDUMP(m.segment_id); + } + else + if(m.type == PP_USING) { + namespace_using.FindAdd(m.text); + usings << ";" << m.text; + } + else + if(m.type == PP_INCLUDE) // In flat PP, only marker + usings << ";[" << m.text << "]"; + } + } +} + +void Cpp::Do(const String& sourcefile, Stream& in, const String& currentfile, + Index& visited, bool get_macros) +{ + if(visited.Find(currentfile) >= 0 || visited.GetCount() > 20000) + return; + visited.Add(currentfile); + String current_folder = GetFileFolder(currentfile); + bool notthefile = sourcefile != currentfile; + if(notthefile || get_macros) { + const PPFile& pp = GetPPFile(currentfile); + for(int i = 0; i < pp.item.GetCount() && !done; i++) { + const PPItem& m = pp.item[i]; + if(m.type == PP_DEFINES) { + LTIMING("PP_DEFINES"); + if(notthefile) // if getting macros, we are interested in included macros only + segment_id.FindAdd(m.segment_id); + } + else + if(m.type == PP_INCLUDE) { + String s = GetIncludePath(m.text, current_folder); + if(s.GetCount()) { + if(notthefile && IncludesFile(s, sourcefile)) { + LLOG("Include IN " << s); + Do(sourcefile, in, s, visited, get_macros); + RHITCOUNT("Include IN"); + } + else { + LLOG("Include FLAT " << s); + RHITCOUNT("Include FLAT"); + DoFlatInclude(s); + } + } + } + else + if(m.type == PP_NAMESPACE) { + namespace_stack.Add(m.text); + LLOG("pp namespace " << m.text << " " << namespace_stack); + } + else + if(m.type == PP_NAMESPACE_END && namespace_stack.GetCount()) { + namespace_stack.Drop(); + LLOG("pp end namespace " << namespace_stack); + } + else + if(m.type == PP_USING) + namespace_using.FindAdd(m.text); + } + if(sourcefile != currentfile) + return; + } + + namespaces = Join(namespace_stack, ";"); + + if(!get_macros) { + LTIMING("Expand"); + incomment = false; + prefix_macro.Clear(); + StringBuffer result; + result.Clear(); + result.Reserve(16384); + int lineno = 0; + bool incomment = false; + int segment_serial = 0; + segment_id.Add(--segment_serial); + #ifdef IGNORE_ELSE + int ignore_else = 0; + #endif + while(!in.IsEof()) { + String l = prefix_macro + in.GetLine(); + prefix_macro.Clear(); + lineno++; + int el = 0; + while(*l.Last() == '\\' && !in.IsEof()) { + el++; + l.Trim(l.GetLength() - 1); + l.Cat(in.GetLine()); + } + RemoveComments(l, incomment); + CParser p(l); + if(p.Char('#')) { + if(p.Id("define")) { + result.Cat(l + "\n"); + CppMacro m; + String id = m.Define(p.GetPtr()); + if(id.GetCount()) { + PPMacro& pp = macro.Add(id); + pp.macro = m; + pp.segment_id = segment_serial; + notmacro.Trim(kw.GetCount()); + } + } + else + if(p.Id("undef")) { + result.Cat(l + "\n"); + if(p.IsId()) { + segment_id.Add(--segment_serial); + PPMacro& m = macro.Add(p.ReadId()); + m.segment_id = segment_serial; + m.macro.SetUndef(); + notmacro.Trim(kw.GetCount()); + segment_id.Add(--segment_serial); + } + } + else { + result.Cat('\n'); + #ifdef IGNORE_ELSE + if(ignore_else) { + if(p.Id("if") || p.Id("ifdef") || p.Id("ifndef")) + ignore_else++; + else + if(p.Id("endif")) + ignore_else--; + } + else { + if(p.Id("else") || p.Id("elif")) + ignore_else = 1; + } + #endif + if(p.Id("include")) { + LTIMING("Expand include"); + String s = GetIncludePath(p.GetPtr(), current_folder); + DoFlatInclude(s); + segment_id.Add(--segment_serial); + includes << ';' << s; + } + } + } + else { + LTIMING("Expand expand"); + #ifdef IGNORE_ELSE + if(ignore_else) + result.Cat('\n'); + else + #endif + result.Cat(Expand(l) + "\n"); + } + while(el--) + result.Cat("\n"); + } + output = result; + } + done = true; +} + +VectorMap Cpp::GetDefinedMacros() +{ + LTIMING("GetDefinedMacros"); + VectorMap r; + for(int i = std_macros; i < macro.GetCount(); i++) + r.GetAdd(macro.GetKey(i)) << macro[i].macro << "\n"; + LLOG("GetDefinedMacros " << r); + for(int i = 0; i < r.GetCount(); i++) + r[i] = MD5String(r[i]); + return r; +} + +String Cpp::GetIncludedMacroValues(const Vector& m) +{ + String r; + LTIMING("GetUsedMacroValues"); + r << "##namespace\n" << namespaces << "\n" + << "##usings\n" << usings << "\n"; + for(int i = 0; i < m.GetCount(); i++) { + String mm = GetAllMacros(m[i], segment_id); + if(mm.GetCount()) + r << '#' << m[i] << '\n' << mm << '\n'; + } + return MD5String(r); +} + +END_UPP_NAMESPACE diff --git a/uppdev/cpp2/macro.cpp b/uppsrc/CppBase/macro.cpp similarity index 60% rename from uppdev/cpp2/macro.cpp rename to uppsrc/CppBase/macro.cpp index bb514a7ab..6587c6310 100644 --- a/uppdev/cpp2/macro.cpp +++ b/uppsrc/CppBase/macro.cpp @@ -1,4 +1,6 @@ -#include "cpp.h" +#include "CppBase.h" + +NAMESPACE_UPP inline bool IsSpc(byte c) { @@ -12,9 +14,12 @@ String CppMacro::Define(const char *s) try { if(!p.IsId()) return Null; + p.NoSkipSpaces().NoSkipComments(); // '#define TEST(x)' is difference form '#define TEST (x)' - later is parameterless id = p.ReadId(); param.Clear(); if(p.Char('(')) { + p.SkipSpaces(); + p.Spaces(); while(p.IsId()) { if(param.GetCount()) param << ","; @@ -24,8 +29,13 @@ String CppMacro::Define(const char *s) if(p.Char3('.', '.', '.')) param << '.'; p.Char(')'); + if(param.GetCount() == 0) // #define foo() bar - need to 'eat' parenthesis, cheap way + param = "."; } - body = p.GetPtr(); + const char *b = p.GetPtr(); + while(!p.IsEof() && !p.IsChar2('/', '/')) + p.SkipTerm(); + body = String(b, p.GetPtr()); } catch(CParser::Error) { return Null; @@ -41,11 +51,14 @@ String CppMacro::ToString() const h.Replace(".", "..."); r << "(" << h << ")"; } - r << ' ' << body; + if(IsUndef()) + r << " #undef"; + else + r << ' ' << body; return r; } -String CppMacro::Expand(const Vector& p) const +String CppMacro::Expand(const Vector& p, const Vector& ep) const { String r; const char *s = body; @@ -56,6 +69,7 @@ String CppMacro::Expand(const Vector& p) const pp.Trim(pp.GetCount() - 1); } Index param(pick(Split(pp, ','))); + static String VA_ARGS("__VA_ARGS__"); // static - Speed optimization while(*s) { if(IsAlpha(*s) || *s == '_') { const char *b = s; @@ -63,21 +77,31 @@ String CppMacro::Expand(const Vector& p) const while(IsAlNum(*s) || *s == '_') s++; String id(b, s); - static String VA_ARGS("__VA_ARGS__"); // Speed optimization + const char *ss = b; + bool cat = false; + while(ss > ~body && ss[-1] == ' ') + ss--; + if(ss >= ~body + 2 && ss[-1] == '#' && ss[-2] == '#') + cat = true; + ss = s; + while(*ss && *ss == ' ') + ss++; + if(ss[0] == '#' && ss[1] == '#') + cat = true; if(id == VA_ARGS) { bool next = false; - for(int i = param.GetCount(); i < p.GetCount(); i++) { + for(int i = param.GetCount(); i < ep.GetCount(); i++) { if(next) r.Cat(", "); - r.Cat(p[i]); + r.Cat((cat ? p : ep)[i]); next = true; } } else { int q = param.Find(id); if(q >= 0) { - if(q < p.GetCount()) - r.Cat(p[q]); + if(q < ep.GetCount()) + r.Cat((cat ? p : ep)[q]); } else r.Cat(id); @@ -122,3 +146,5 @@ String CppMacro::Expand(const Vector& p) const } return r; } + +END_UPP_NAMESPACE diff --git a/uppsrc/CppBase/ppconfig.cpp b/uppsrc/CppBase/ppconfig.cpp new file mode 100644 index 000000000..42efce416 --- /dev/null +++ b/uppsrc/CppBase/ppconfig.cpp @@ -0,0 +1,84 @@ +#include "CppBase.h" + +namespace Upp { + +Value StringArray(const char *s) +{ + Vector h = Split(s, ';'); + ValueArray va; + for(int i = 0; i < h.GetCount(); i++) + va.Add(h[i]); + return va; +} + +String GetStdConfig() +{ + static const char ns[] = "_STD_BEGIN:std;_C_STD_BEGIN:std;_STDEXT_BEGIN:stdext;NAMESPACE_UPP:Upp"; + static const char endns[] = "_STD_END;_STDEXT_END;_C_STD_END;END_UPP_NAMESPACE"; + static const char ignore[] = "__declspec(...);__cdecl;__attribute__(...);__stdcall;__forceinline;" + "__out;__in;__inout;__deref_in;__deref_inout;__deref_out;" + "__pragma(...);__pascal;_far;_pascal;_cdecl;" + "__AuToQuOtE;__xin;__xout;__export;" + "__clrcall;__alignof(...)"; + ValueMap json; + ValueArray va; + Vector h = Split(ns, ';'); + for(int i = 0; i < h.GetCount(); i++) { + String id, n; + SplitTo(h[i], ':', id, n); + ValueMap m; + m.Add(id, n); + va.Add(m); + } + json.Add("namespace", va); + json.Add("end_namespace", StringArray(endns)); + json.Add("ignore", StringArray(ignore)); + return AsJSON(json); +} + +static VectorMap s_namespace_macro; +static Index s_namespace_end_macro; +static Vector s_ignorelist; + +void LoadPPConfig(const String& json) +{ + Value m = ParseJSON(json); + + try { + s_namespace_macro.Clear(); + ValueArray va = m["namespace"]; + for(int i = 0; i < va.GetCount(); i++) { + ValueMap m = va[i]; + if(m.GetCount()) + s_namespace_macro.Add(m.GetKey(0), m.GetValue(0)); + } + + s_namespace_end_macro.Clear(); + va = m["end_namespace"]; + for(int i = 0; i < va.GetCount(); i++) + s_namespace_end_macro.Add(va[i]); + + s_ignorelist.Clear(); + va = m["ignore"]; + for(int i = 0; i < va.GetCount(); i++) + s_ignorelist.Add(va[i]); + } + catch(ValueTypeError) {} +} + +const VectorMap& GetNamespaceMacros() +{ + return s_namespace_macro; +} + +const Index& GetNamespaceEndMacros() +{ + return s_namespace_end_macro; +} + +const Vector& GetIgnoreList() +{ + return s_ignorelist; +} + +}; \ No newline at end of file diff --git a/uppsrc/CppBase/ppfile.cpp b/uppsrc/CppBase/ppfile.cpp new file mode 100644 index 000000000..08a440ddc --- /dev/null +++ b/uppsrc/CppBase/ppfile.cpp @@ -0,0 +1,489 @@ +#include "CppBase.h" + +NAMESPACE_UPP + +#define LTIMING(x) RTIMING(x) +#define LLOG(x) // LOG(x) + +bool IsCPPFile(const String& path) +{ + return findarg(ToLower(GetFileExt(path)) , ".c", ".cpp", ".cc" , ".cxx", ".icpp") >= 0; +} + +bool IsHFile(const String& path) +{ + return findarg(ToLower(GetFileExt(path)) , ".h", ".hpp", ".hxx" , ".hh") >= 0; +} + +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; + } +} + +static VectorMap sAllMacros; +static ArrayMap sPPfile; +static int sPPserial; + +void SerializePPFiles(Stream& s) +{ + s % sAllMacros % sPPfile % sPPserial; +} + +void CleanPP() +{ + sAllMacros.Clear(); + sPPfile.Clear(); + sPPserial = 0; +} + +void SweepPPFiles(const Index& keep) +{ + for(int i = 0; i < sPPfile.GetCount(); i++) + if(keep.Find(sPPfile.GetKey(i)) < 0 && !sPPfile.IsUnlinked(i)) + sPPfile.Unlink(i); +} + +String GetSegmentFile(int segment_id) +{ + for(int i = 0; i < sPPfile.GetCount(); i++) { + const Array& m = sPPfile[i].item; + for(int j = 0; j < m.GetCount(); j++) + if(m[j].type == PP_DEFINES && m[j].segment_id == segment_id) + return sPPfile.GetKey(i); + } + return ""; +} + +PPMacro *FindPPMacro(const String& id, Index& segment_id, int& segmenti) +{ + Index undef; + PPMacro *r; + + for(int pass = 0; pass < 2; pass++) { + r = NULL; + int best = segmenti; + int line = -1; + int q = sAllMacros.Find(id); + while(q >= 0) { + PPMacro& m = sAllMacros[q]; + if(m.macro.IsUndef()) { + if(pass == 0 && segment_id.Find(m.segment_id) >= 0) { + undef.FindAdd(m.segment_id); + } + } + else + if(pass == 0 || undef.Find(m.undef_segment_id) < 0) { + int si = segment_id.Find(m.segment_id); + if(si > best || si >= 0 && si == best && m.line > line) { + best = si; + line = m.line; + r = &m; + } + } + q = sAllMacros.FindNext(q); + } + if(undef.GetCount() == 0) + break; + } + return r; +} + +const CppMacro *FindMacro(const String& id, Index& segment_id, int& segmenti) +{ + PPMacro *m = FindPPMacro(id, segment_id, segmenti); + return m ? &m->macro : NULL; +} + +String GetAllMacros(const String& id, Index& segment_id) +{ + String r; + int q = sAllMacros.Find(id); + while(q >= 0) { + const PPMacro& m = sAllMacros[q]; + if(segment_id.Find(m.segment_id) >= 0) + r << '\n' << m.macro; + q = sAllMacros.FindNext(q); + } + return r; +} + +void PPFile::CheckEndNamespace(Vector& namespace_block, int level) +{ + if(namespace_block.GetCount() && namespace_block.Top() == level) { + namespace_block.Drop(); + item.Add().type = PP_NAMESPACE_END; + } +} + +void PPFile::Parse(Stream& in) +{ + LTIMING("PPFile::Parse"); + for(int i = 0; i < ppmacro.GetCount(); i++) + sAllMacros.Unlink(ppmacro[i]); + ppmacro.Clear(); + item.Clear(); + includes.Clear(); + bool was_using = false; + bool was_namespace = false; + int level = 0; + bool incomment = false; + Vector namespace_block; + bool next_segment = true; + Index local_segments; + int linei = 0; + 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('#')) { + if(p.Id("define")) { + if(next_segment) { + PPItem& m = item.Add(); + m.type = PP_DEFINES; + m.segment_id = ++sPPserial; + next_segment = false; + local_segments.Add(sPPserial); + } + CppMacro def; + String id = def.Define(p.GetPtr()); + if(id.GetCount()) { + PPMacro m; + m.segment_id = sPPserial; + m.line = linei; + m.macro = def; + ppmacro.Add(sAllMacros.Put(id, m)); + } + } + else + if(p.Id("undef")) { + if(p.IsId()) { + String id = p.ReadId(); + int segmenti = -1; + PPMacro *um = FindPPMacro(id, local_segments, segmenti); + if(um) { // heuristic: only local undefs are allowed + PPItem& m = item.Add(); + m.type = PP_DEFINES; + m.segment_id = ++sPPserial; + um->undef_segment_id = m.segment_id; + next_segment = true; + local_segments.Add(sPPserial); + if(id.GetCount()) { + PPMacro m; + m.segment_id = sPPserial; + m.line = linei; + m.macro.SetUndef(); + ppmacro.Add(sAllMacros.Put(id, m)); + } + } + } + } + else + if(p.Id("include")) { + PPItem& m = item.Add(); + next_segment = true; + m.type = PP_INCLUDE; + m.text = TrimBoth(p.GetPtr()); + if(IsNull(m.text)) + item.Drop(); + else + includes.FindAdd(m.text); + } + } + else { + while(!p.IsEof()) { + if(was_namespace) { + int type = was_using ? PP_USING : PP_NAMESPACE; + String id; + while(p.Char2(':', ':')) + id = "::"; + id << p.ReadId(); + while(p.Char2(':', ':')) + id << "::" << p.ReadId(); + if(!was_using) + namespace_block.Add(level); + if(!was_using || level == 0) { + PPItem& m = item.Add(); + next_segment = true; + m.type = type; + m.text = id; + } + was_namespace = was_using = false; + } + else + if(p.Id("using")) + was_using = true; + else + if(p.Id("namespace")) + was_namespace = true; + else { + was_using = was_namespace = false; + if(p.IsId()) { + static const VectorMap& namespace_macro = GetNamespaceMacros(); + static const Index& namespace_end_macro = GetNamespaceEndMacros(); + + String id = p.ReadId(); + int q = namespace_macro.Find(id); + if(q > 0) { + PPItem& m = item.Add(); + next_segment = true; + m.type = PP_NAMESPACE; + m.text = namespace_macro[q]; + namespace_block.Add(level); + level++; + } + else { + q = namespace_end_macro.Find(id); + if(q >= 0) { + level--; + CheckEndNamespace(namespace_block, level); + } + } + } + else + if(p.Char('}')) { + if(level > 0) { + level--; + CheckEndNamespace(namespace_block, level); + } + } + else + if(p.Char('{')) + level++; + else + p.SkipTerm(); + } + } + } + } + catch(...) {} + linei++; + } +} + +void PPFile::Dump() const +{ + for(int i = 0; i < item.GetCount(); i++) { + const PPItem& m = item[i]; + String ll; + ll << decode(m.type, PP_DEFINES, "#defines ", PP_INCLUDE, "#include ", + PP_USING, "using namespace ", PP_NAMESPACE, "namespace ", + PP_NAMESPACE_END, "}", ""); + if(m.type == PP_DEFINES) + ll << m.segment_id; + else + ll << m.text; + if(m.type == PP_NAMESPACE) + ll << " {"; + LOG(ll); + } + LOG("----- includes:"); + DUMPC(includes); +} + +static VectorMap sPathFileTime; +static VectorMap sIncludePath; +static VectorMap sIncludes; +static ArrayMap sFlatPP; +static String sInclude_Path; + +void PPSync(const String& include_path) +{ + sPathFileTime.Clear(); + sIncludePath.Clear(); + sIncludes.Clear(); + sFlatPP.Clear(); + sInclude_Path = include_path; +} + +String GetIncludePath() +{ + return sInclude_Path; +} + +String GetIncludePath0(const char *s, const char *filedir) +{ + LTIMING("GetIncludePath0"); + 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, GetIncludePath(), false); + } + name.Cat(*s++); + } + } + return Null; +} + +Time GetFileTimeCached(const String& p) +{ + LTIMING("GetFileTimeCached"); + int q = sPathFileTime.Find(p); + if(q >= 0) + return sPathFileTime[q]; + Time m = FileGetTime(p); + sPathFileTime.Add(p, m); + return m; +} + +String GetIncludePath(const String& s, const String& filedir) +{ + LTIMING("GetIncludePath"); + String key; + key << s << "#" << filedir << "#" << GetIncludePath(); + int q = sIncludePath.Find(key); + if(q >= 0) + return sIncludePath[q]; + String p = GetIncludePath0(s, filedir); + sIncludePath.Add(key, p); + return p; +} + +const PPFile& GetPPFile(const char *path) +{ + Time tm = GetFileTimeCached(path); + PPFile& f = sPPfile.GetPut(path); + if(f.filetime != tm) { + f.filetime = tm; + LTIMING("PP read"); + FileIn in(path); + f.Parse(in); + } + return f; +} + +bool IsSameFile(const String& f1, const String& f2) +{ + return NormalizePath(f1) == NormalizePath(f2); +} + +bool IncludesFile(const String& parent_path, const String& path, Index& visited) +{ + HITCOUNT("IncludesFile0"); + if(visited.Find(parent_path) >= 0) + return false; + visited.Add(parent_path); + if(IsSameFile(parent_path, path)) + return true; + const PPFile& f = GetPPFile(parent_path); + for(int i = 0; i < f.includes.GetCount(); i++) { + String key = path + "#" + f.includes[i]; + int q = sIncludes.Find(key); + if(q >= 0) { + HITCOUNT("IncludesFile cached"); + if(sIncludes[q]) + return true; + } + else { + HITCOUNT("IncludesFile getpath"); + String p = GetIncludePath(f.includes[i], GetFileFolder(parent_path)); + bool b = p.GetCount() && IncludesFile(p, path, visited); + sIncludes.Add(key, b); + if(b) + return true; + } + } + return false; +} + +bool IncludesFile(const String& parent_path, const String& path) +{ + LTIMING("IncludesFile"); + Index visited; + return IncludesFile(parent_path, path, visited); +} + +void CreateFlatPP(PPFile& fp, const char *path, Index& visited) +{ + if(visited.Find(path) >= 0) + return; + visited.Add(path); + LLOG("CreateFlatPP " << path << LOG_BEGIN); + const PPFile& pp = GetPPFile(path); + for(int i = 0; i < pp.item.GetCount(); i++) { + const PPItem& m = pp.item[i]; + if(m.type == PP_INCLUDE) { + String s = GetIncludePath(m.text, GetFileFolder(path)); + if(s.GetCount()) + CreateFlatPP(fp, s, visited); + } + else + fp.item.Add(m); + } + LLOG(LOG_END); +} + +const PPFile& GetFlatPPFile(const char *path, Index& visited) +{ + LLOG("GetFlatPPFile " << path); + int q = sFlatPP.Find(path); + if(q >= 0) + return sFlatPP[q]; + PPFile& fp = sFlatPP.Add(path); + const PPFile& pp = GetPPFile(path); + for(int i = 0; i < pp.item.GetCount(); i++) { + const PPItem& m = pp.item[i]; + fp.item.Add(m); + if(m.type == PP_INCLUDE) { + String s = GetIncludePath(m.text, GetFileFolder(path)); + if(s.GetCount() && visited.Find(s) < 0) { + visited.Add(s); + const PPFile& pp = GetFlatPPFile(s, visited); + for(int i = 0; i < pp.item.GetCount(); i++) + fp.item.Add(pp.item[i]); + } + } + } + return fp; +} + +const PPFile& GetFlatPPFile(const char *path) +{ + Index visited; + visited.Add(path); + return GetFlatPPFile(path, visited); +} + +END_UPP_NAMESPACE diff --git a/uppsrc/ide/Core/src.tpp/Builder$en-us.tpp b/uppsrc/ide/Core/src.tpp/Builder$en-us.tpp new file mode 100644 index 000000000..9443e4dd7 --- /dev/null +++ b/uppsrc/ide/Core/src.tpp/Builder$en-us.tpp @@ -0,0 +1,31 @@ +topic ""; +[ $$0,0#00000000000000000000000000000000:Default] +[H6;0 $$1,0#05600065144404261032431302351956:begin] +[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem] +[l288;2 $$3,0#27521748481378242620020725143825:desc] +[0 $$4,0#96390100711032703541132217272105:end] +[{_}%EN-US +[s1;%- &] +[s2;:Builder`:`:BuildPackage`(const String`&`,Vector``&`,Vector``&`,String`&`,const Vector``&`,const Vector``&`,int`):%- [@(0.0.255) v +irtual] [@(0.0.255) bool]_[* BuildPackage]([@(0.0.255) const]_[_^String^ String][@(0.0.255) `& +]_[*@3 package], [_^Vector^ Vector]<[_^String^ String]>`&_[*@3 linkfile], +[_^Vector^ Vector]<[_^String^ String]>`&_[*@3 immfile], [_^String^ String][@(0.0.255) `&]_[*@3 l +inkoptions], [@(0.0.255) const]_[_^Vector^ Vector]<[_^String^ String]>`&_[*@3 all`_uses], + [@(0.0.255) const]_[_^Vector^ Vector]<[_^String^ String]>`&_[*@3 all`_libraries], +[@(0.0.255) int]_[*@3 optimize])&] +[s3; Called for each package during building.&] +[s3; [%-*@3 package] name of package.&] +[s3; [%-*@3 linkfile] builder puts here files to link, for Link method&] +[s3; [%-*@3 immfile] builder puts here all intermediate files (.a, +.o, .lib ...) so that theide knows them and can touch them (set +current time) as needed&] +[s3; [%-*@3 linkoptions] again, like linkfile, a place to gather link +options so that Link method recieves them&] +[s3; [%-*@3 all`_uses] all packages that package uses (including indirect). +important for .so builds only&] +[s3; [%-*@3 all`_libraries] all libraries that package uses (including +indirect). important for .so builds only&] +[s3; [%-*@3 optimize] global optimization setting `- R`_SPEED, R`_SIZE, +R`_OPTIMAL&] +[s4; &] +[s0; ]] \ No newline at end of file diff --git a/upptst/CppParser/CppParser.cpp b/upptst/CppParser/CppParser.cpp index 3c5efc737..2f8d6708d 100644 --- a/upptst/CppParser/CppParser.cpp +++ b/upptst/CppParser/CppParser.cpp @@ -19,7 +19,7 @@ void Test(const char *path) errs.Clear(); Parser p; - p.Do(in, Vector(), base, path, callback(AddError)); + p.Do(in, base, 0, 0, callback(AddError)); if(errs.GetCount()) DUMPC(errs); @@ -30,7 +30,10 @@ void Test(const char *path) const Array& ma = base[i]; for(int j = 0; j < ma.GetCount(); j++) { const CppItem& m = ma[j]; - out << '\t' << CppItemKindAsString(m.kind) << ", name: " << m.name << ", qitem: " << m.qitem << ", line " << m.line << "\n"; + out << '\t' << CppItemKindAsString(m.kind) << ", name: " << m.name << ", qitem: " << m.qitem << ", qtype: " << m.qtype << ", line " << m.line; + if(m.isptr) + out << ", pointer"; + out << "\n"; } out << "}\n"; } @@ -39,7 +42,7 @@ void Test(const char *path) p.dobody = true; in.Seek(0); - p.Do(in, Vector(), base, path, callback(AddError)); + p.Do(in, base, 0, 0, callback(AddError)); out << " {\n"; for(int i = 0; i < p.local.GetCount(); i++) { @@ -54,14 +57,8 @@ void Test(const char *path) LOG("-------------------------------------------------------------------------------"); } -CONSOLE_APP_MAIN { +CONSOLE_APP_MAIN +{ StdLogSetup(LOG_COUT|LOG_FILE); - Test(GetDataFile("test1.in")); - /* - FindFile ff(GetDataFile("test1.in")); - while(ff) { - Test(ff.GetPath()); - ff.Next(); - } - */ + Test(GetDataFile("test.in")); } diff --git a/upptst/CppParser/CppParser.upp b/upptst/CppParser/CppParser.upp index b90ba10a0..1a70770d8 100644 --- a/upptst/CppParser/CppParser.upp +++ b/upptst/CppParser/CppParser.upp @@ -4,11 +4,8 @@ uses file CppParser.cpp, - test1.in, - test1.out, - test2.in, - test2.out, - test3.in; + todo.txt, + test.in; mainconfig "" = "SSE2"; diff --git a/upptst/CppParser/test.in b/upptst/CppParser/test.in new file mode 100644 index 000000000..ed55dee60 --- /dev/null +++ b/upptst/CppParser/test.in @@ -0,0 +1 @@ +typedef HMODULE DLLHANDLE; diff --git a/upptst/CppParser/test1.in b/upptst/CppParser/test1.in deleted file mode 100644 index bae51faeb..000000000 --- a/upptst/CppParser/test1.in +++ /dev/null @@ -1,9 +0,0 @@ -extern "C++" -{ - template - inline - typename _CrtEnableIf<(_Size > 1), void *>::_Type memcpy(_DstType (&_Dst)[_Size], const void *_Src, size_t _SrcSize) throw() - { - return memcpy_s(_Dst, _Size * sizeof(_DstType), _Src, _SrcSize) == 0 ? _Dst : 0; - } -} diff --git a/upptst/CppParser/test2.in b/upptst/CppParser/test2.in deleted file mode 100644 index f1215bde4..000000000 --- a/upptst/CppParser/test2.in +++ /dev/null @@ -1,5 +0,0 @@ -template -struct _CrtEnableIf -{ - typedef _Ty _Type; -}; diff --git a/upptst/CppParser/todo.txt b/upptst/CppParser/todo.txt new file mode 100644 index 000000000..acb547fb8 --- /dev/null +++ b/upptst/CppParser/todo.txt @@ -0,0 +1,23 @@ +enum +{ + INVALID_SOCKET = -1, + TCP_NODELAY = 1, + SD_RECEIVE = 0, + SD_SEND = 1, + SD_BOTH = 2, +}; +-------------------------- +typedef HMODULE DLLHANDLE; +-------------------------- +void RichEdit::Pick(RichText t) +{ + Clear(); + text = pick(t); + if(text.GetPartCount() == 0) + text.Cat(RichPara()); + ReadStyles(); + EndSizeTracking(); + SetupLanguage(text.GetAllLanguages()); + Move(0); + Update(); +} \ No newline at end of file