summaryrefslogtreecommitdiff
path: root/cpp/src/Slice/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Slice/Parser.cpp')
-rw-r--r--cpp/src/Slice/Parser.cpp148
1 files changed, 121 insertions, 27 deletions
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index 7f79e2bf54c..e2bea935547 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -9,12 +9,19 @@
#include <IceUtil/Functional.h>
#include <IceUtil/InputUtil.h>
+#include <IceUtil/StringUtil.h>
+#include <IceUtil/Unicode.h>
#include <Slice/Parser.h>
#include <Slice/GrammarUtil.h>
+#include <Slice/Util.h>
#ifdef __BCPLUSPLUS__
# include <iterator>
#endif
+#ifdef _WIN32
+# include <io.h>
+#endif
+
using namespace std;
using namespace Slice;
@@ -4987,6 +4994,88 @@ Slice::Unit::nextLine()
_currentLine++;
}
+#ifdef _WIN32
+//
+// On Windows mcpp output does not maintain filename capitalization
+// so we have to manually fix it up.
+//
+string
+fixCapitalization(const string& path)
+{
+ if(!isAbsolute(path))
+ {
+ return path;
+ }
+
+ vector<string> result;
+ IceUtilInternal::splitString(path, "/", result);
+ string currentPath = result[0];
+ for(unsigned int i = 1; i < result.size(); ++i)
+ {
+ const wstring fs = IceUtil::stringToWstring(currentPath + "/*");
+
+#ifdef __BCPLUSPLUS__
+ struct _wffblk data;
+ int h = _wfindfirst(fs.c_str(), &data, FA_DIREC);
+ if(h == -1)
+ {
+ return path;
+ }
+
+ while(true)
+ {
+ string name = IceUtil::wstringToString(data.ff_name);
+ assert(!name.empty());
+
+ if(_stricmp(name.c_str(), result[i].c_str()) == 0)
+ {
+ currentPath += "/" + name;
+ _wfindclose(&data);
+ break;
+ }
+
+ if(_wfindnext(&data) == -1)
+ {
+ _wfindclose(&data);
+ return path;
+ }
+ }
+#else
+ struct _wfinddata_t data;
+# if defined(_MSC_VER) && (_MSC_VER < 1300)
+ long h = _wfindfirst(fs.c_str(), &data);
+# else
+ intptr_t h = _wfindfirst(fs.c_str(), &data);
+# endif
+ if(h == -1)
+ {
+ return path;
+ }
+
+ while(true)
+ {
+ string name = IceUtil::wstringToString(data.name);
+ assert(!name.empty());
+
+ if(_stricmp(name.c_str(), result[i].c_str()) == 0)
+ {
+ currentPath += "/" + name;
+ _findclose(h);
+ break;
+ }
+
+ if(_wfindnext(h, &data) == -1)
+ {
+ _findclose(h);
+ return path;
+ }
+ }
+#endif
+ }
+ return currentPath;
+}
+#endif
+
void
Slice::Unit::scanPosition(const char* s)
{
@@ -5011,32 +5100,6 @@ Slice::Unit::scanPosition(const char* s)
}
eraseWhiteSpace(line);
- //
- // If the string ends in <whitespace>1 or <whitespace>2, it is a push or pop directive.
- //
- enum LineType { File, Push, Pop };
-
- LineType type = File;
-
- idx = line.find_last_of(" \t\r");
- if(idx != string::npos)
- {
- ++idx;
- if(line.substr(idx) == "1")
- {
- type = Push;
- line.erase(idx);
- eraseWhiteSpace(line);
-
- }
- else if(line.substr(idx) == "2")
- {
- type = Pop;
- line.erase(idx);
- eraseWhiteSpace(line);
- }
- }
-
string currentFile;
if(!line.empty())
{
@@ -5054,6 +5117,35 @@ Slice::Unit::scanPosition(const char* s)
}
}
+#ifdef _WIN32
+ currentFile = fixCapitalization(currentFile);
+#endif
+ currentFile = normalizePath(currentFile, false);
+
+ enum LineType { File, Push, Pop };
+
+ LineType type = File;
+
+ if(_currentLine == 0)
+ {
+ if(currentFile != _topLevelFile)
+ {
+ type = Push;
+ line.erase(idx);
+ eraseWhiteSpace(line);
+ }
+ }
+ else
+ {
+ DefinitionContextPtr dc = currentDefinitionContext();
+ if(dc != 0 && !dc->filename().empty() && dc->filename() != currentFile)
+ {
+ type = Pop;
+ line.erase(idx);
+ eraseWhiteSpace(line);
+ }
+ }
+
switch(type)
{
case Push:
@@ -5417,7 +5509,7 @@ Slice::Unit::includeFiles() const
}
int
-Slice::Unit::parse(FILE* file, bool debug, Slice::FeatureProfile profile)
+Slice::Unit::parse(const string& filename, FILE* file, bool debug, Slice::FeatureProfile profile)
{
slice_debug = debug ? 1 : 0;
@@ -5428,6 +5520,7 @@ Slice::Unit::parse(FILE* file, bool debug, Slice::FeatureProfile profile)
_currentLine = 1;
_currentIncludeLevel = 0;
_featureProfile = profile;
+ _topLevelFile = normalizePath(filename);
pushContainer(this);
pushDefinitionContext();
@@ -5502,6 +5595,7 @@ Slice::Unit::Unit(bool ignRedefs, bool all, bool allowIcePrefix, bool caseSensit
_caseSensitive(caseSensitive),
_defaultGlobalMetadata(defaultGlobalMetadata),
_errors(0)
+
{
_unit = this;
}