Use llvm::sys::Path to implement "mkdir -p".
Change-Id: I3bb36e1a8050bbd9744fd02935b6186d2f285015
diff --git a/Android.mk b/Android.mk
index be5ce9a..177ba91 100644
--- a/Android.mk
+++ b/Android.mk
@@ -132,6 +132,7 @@
LOCAL_SRC_FILES := \
slang_driver.cpp \
slang.cpp \
+ slang_utils.cpp \
slang_backend.cpp \
slang_pragma_recorder.cpp \
slang_diagnostic_buffer.cpp \
diff --git a/slang.cpp b/slang.cpp
index cffe2cf..770d37b 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -4,6 +4,8 @@
#include "llvm/Target/TargetSelect.h"
+#include "llvm/System/Path.h"
+
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ErrorHandling.h"
@@ -31,6 +33,7 @@
#include "clang/Parse/ParseAST.h"
+#include "slang_utils.h"
#include "slang_backend.h"
using namespace slang;
@@ -251,42 +254,19 @@
return true;
}
-static void _mkdir_given_a_file(const char *file) {
- char buf[256];
- char *tmp, *p = NULL;
- size_t len = strlen(file);
-
- if (len + 1 <= sizeof(buf))
- tmp = buf;
- else
- tmp = new char[len + 1];
-
- strcpy(tmp, file);
-
- if (tmp[len - 1] == '/')
- tmp[len - 1] = 0;
-
- for (p = tmp + 1; *p; p++) {
- if (*p == '/') {
- *p = 0;
- mkdir(tmp, S_IRWXU);
- *p = '/';
- }
- }
-
- if (tmp != buf)
- delete[] tmp;
-}
-
bool Slang::setOutput(const char *OutputFile) {
+ llvm::sys::Path OutputFilePath(OutputFile);
std::string Error;
switch (mOT) {
case OT_Dependency:
case OT_Assembly:
case OT_LLVMAssembly: {
- _mkdir_given_a_file(OutputFile);
- mOS.reset(new llvm::raw_fd_ostream(OutputFile, Error, 0));
+ if (!SlangUtils::CreateDirectoryWithParents(OutputFilePath.getDirname(),
+ &Error))
+ mDiagnostics->Report(clang::diag::err_fe_error_opening) << OutputFile
+ << Error;
+ mOS.reset(new llvm::tool_output_file(OutputFile, Error, 0));
break;
}
case OT_Nothing: {
@@ -295,15 +275,18 @@
}
case OT_Object:
case OT_Bitcode: {
- _mkdir_given_a_file(OutputFile);
- mOS.reset(new llvm::raw_fd_ostream(OutputFile,
- Error,
- llvm::raw_fd_ostream::F_Binary));
+ if (!SlangUtils::CreateDirectoryWithParents(OutputFilePath.getDirname(),
+ &Error))
+ mDiagnostics->Report(clang::diag::err_fe_error_opening) << OutputFile
+ << Error;
+ mOS.reset(new llvm::tool_output_file(OutputFile,
+ Error,
+ llvm::raw_fd_ostream::F_Binary));
break;
}
- default:
+ default: {
llvm_unreachable("Unknown compiler output type");
- break;
+ }
}
if (!Error.empty()) {
@@ -319,8 +302,13 @@
}
bool Slang::setDepOutput(const char *OutputFile) {
+ llvm::sys::Path OutputFilePath(OutputFile);
std::string Error;
- _mkdir_given_a_file(OutputFile);
+
+ if (!SlangUtils::CreateDirectoryWithParents(OutputFilePath.getDirname(),
+ &Error))
+ mDiagnostics->Report(clang::diag::err_fe_error_opening) << OutputFile
+ << Error;
mDOS.reset(new llvm::raw_fd_ostream(OutputFile, Error, 0));
if (!Error.empty()) {
diff --git a/slang_diagnostic_buffer.h b/slang_diagnostic_buffer.h
index 3ed48be..b6f223e 100644
--- a/slang_diagnostic_buffer.h
+++ b/slang_diagnostic_buffer.h
@@ -1,5 +1,5 @@
-#ifndef _SLANG_DIAGNOSTIC_BUFFER_H
-#define _SLANG_DIAGNOSTIC_BUFFER_H
+#ifndef _SLANG_COMPILER_DIAGNOSTIC_BUFFER_H
+#define _SLANG_COMPILER_DIAGNOSTIC_BUFFER_H
#include "llvm/Support/raw_ostream.h"
diff --git a/slang_rs_reflect_utils.cpp b/slang_rs_reflect_utils.cpp
index 75db21a..94fb8b0 100644
--- a/slang_rs_reflect_utils.cpp
+++ b/slang_rs_reflect_utils.cpp
@@ -1,11 +1,11 @@
#include "slang_rs_reflect_utils.h"
-#include <cstdlib>
#include <cstdio>
#include <cstring>
-#include <sys/stat.h>
-#include <sys/types.h>
+#include "llvm/ADT/StringRef.h"
+
+#include "slang_utils.h"
namespace slang {
@@ -85,36 +85,6 @@
return InternalFileNameConvert(rsFileName, true);
}
-bool RSSlangReflectUtils::mkdir_p(const char *path) {
- char buf[256];
- char *tmp, *p = NULL;
- size_t len = strlen(path);
-
- if (len + 1 <= sizeof(buf))
- tmp = buf;
- else
- tmp = new char[len + 1];
-
- strcpy(tmp, path);
-
- if (tmp[len - 1] == '/')
- tmp[len - 1] = 0;
-
- for (p = tmp + 1; *p; p++) {
- if (*p == '/') {
- *p = 0;
- mkdir(tmp, S_IRWXU);
- *p = '/';
- }
- }
- mkdir(tmp, S_IRWXU);
-
- if (tmp != buf)
- delete[] tmp;
-
- return true;
-}
-
static bool GenerateAccessorHeader(
const RSSlangReflectUtils::BitCodeAccessorContext &context, FILE *pfout) {
fprintf(pfout, "/*\n");
@@ -249,7 +219,8 @@
const BitCodeAccessorContext &context) {
string output_path = ComputePackagedPath(context.reflectPath,
context.packageName);
- if (!mkdir_p(output_path.c_str())) {
+ if (!SlangUtils::CreateDirectoryWithParents(llvm::StringRef(output_path),
+ NULL)) {
fprintf(stderr, "Error: could not create dir %s\n",
output_path.c_str());
return false;
diff --git a/slang_rs_reflect_utils.h b/slang_rs_reflect_utils.h
index d4124f2..d1b8328 100644
--- a/slang_rs_reflect_utils.h
+++ b/slang_rs_reflect_utils.h
@@ -59,10 +59,6 @@
// rsFileName: the input .rs file name (with or without path).
static std::string BCFileNameFromRSFileName(const char *rsFileName);
- // "mkdir -p"
- static bool mkdir_p(const char *path);
-
-
// Generate the bit code accessor Java source file.
static bool GenerateBitCodeAccessor(const BitCodeAccessorContext &context);
};
diff --git a/slang_rs_reflection.cpp b/slang_rs_reflection.cpp
index d667058..8cdb78e 100644
--- a/slang_rs_reflection.cpp
+++ b/slang_rs_reflection.cpp
@@ -7,6 +7,7 @@
#include "llvm/ADT/APFloat.h"
+#include "slang_utils.h"
#include "slang_rs_context.h"
#include "slang_rs_export_var.h"
#include "slang_rs_export_func.h"
@@ -460,36 +461,10 @@
return NULL;
}
-bool RSReflection::openScriptFile(Context &C,
- const std::string &ClassName,
- std::string &ErrorMsg) {
- if (!C.mUseStdout) {
- C.mOF.clear();
- std::string _path = RSSlangReflectUtils::ComputePackagedPath(
- mRSContext->getReflectJavaPathName().c_str(),
- C.getPackageName().c_str());
-
- RSSlangReflectUtils::mkdir_p(_path.c_str());
- C.mOF.open((_path + "/" + ClassName + ".java").c_str());
- if (!C.mOF.good()) {
- ErrorMsg = "failed to open file '" + _path + "/" + ClassName
- + ".java' for write";
-
- return false;
- }
- }
- return true;
-}
-
/********************** Methods to generate script class **********************/
bool RSReflection::genScriptClass(Context &C,
const std::string &ClassName,
std::string &ErrorMsg) {
- // Open the file
- if (!openScriptFile(C, ClassName, ErrorMsg)) {
- return false;
- }
-
if (!C.startClass(Context::AM_Public,
false,
ClassName,
@@ -1220,11 +1195,6 @@
std::string &ErrorMsg) {
std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
- // Open the file
- if (!openScriptFile(C, ClassName, ErrorMsg)) {
- return false;
- }
-
if (!C.startClass(Context::AM_Public,
false,
ClassName,
@@ -1694,9 +1664,11 @@
if ((OutputPackageName == NULL) ||
(*OutputPackageName == '\0') ||
strcmp(OutputPackageName, "-") == 0)
- C = new Context(InputFileName, "<Package Name>", ResourceId, true);
+ C = new Context(mRSContext->getReflectJavaPathName(), InputFileName,
+ "<Package Name>", ResourceId, true);
else
- C = new Context(InputFileName, OutputPackageName, ResourceId, false);
+ C = new Context(mRSContext->getReflectJavaPathName(), InputFileName,
+ OutputPackageName, ResourceId, false);
if (C != NULL) {
std::string ErrorMsg, ScriptClassName;
@@ -1772,6 +1744,28 @@
"android.util.Log",
};
+bool RSReflection::Context::openClassFile(const std::string &ClassName,
+ std::string &ErrorMsg) {
+ if (!mUseStdout) {
+ mOF.clear();
+ std::string Path =
+ RSSlangReflectUtils::ComputePackagedPath(mOutputPath.c_str(),
+ mPackageName.c_str());
+
+ if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg))
+ return false;
+
+ std::string ClassFile = Path + "/" + ClassName + ".java";
+
+ mOF.open(ClassFile.c_str());
+ if (!mOF.good()) {
+ ErrorMsg = "failed to open file '" + ClassFile + "' for write";
+ return false;
+ }
+ }
+ return true;
+}
+
const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) {
switch (AM) {
case AM_Public: return "public"; break;
@@ -1789,6 +1783,10 @@
if (mVerbose)
std::cout << "Generating " << ClassName << ".java ..." << std::endl;
+ // Open file for class
+ if (!openClassFile(ClassName, ErrorMsg))
+ return false;
+
// License
out() << mLicenseNote;
diff --git a/slang_rs_reflection.h b/slang_rs_reflection.h
index b072790..c4750dc 100644
--- a/slang_rs_reflection.h
+++ b/slang_rs_reflection.h
@@ -33,6 +33,8 @@
bool mVerbose;
+ std::string mOutputPath;
+
std::string mInputRSFile;
std::string mPackageName;
@@ -65,6 +67,9 @@
return;
}
+ bool openClassFile(const std::string &ClassName,
+ std::string &ErrorMsg);
+
public:
typedef enum {
AM_Public,
@@ -77,11 +82,13 @@
static const char *AccessModifierStr(AccessModifier AM);
- Context(const std::string &InputRSFile,
+ Context(const std::string &OutputPath,
+ const std::string &InputRSFile,
const std::string &PackageName,
const std::string &ResourceId,
bool UseStdout)
: mVerbose(true),
+ mOutputPath(OutputPath),
mInputRSFile(InputRSFile),
mPackageName(PackageName),
mResourceId(ResourceId),
@@ -179,9 +186,6 @@
inline void clearFieldIndexMap() { mFieldIndexMap.clear(); }
};
- bool openScriptFile(Context &C,
- const std::string &ClassName,
- std::string &ErrorMsg);
bool genScriptClass(Context &C,
const std::string &ClassName,
std::string &ErrorMsg);
diff --git a/slang_utils.cpp b/slang_utils.cpp
new file mode 100644
index 0000000..d1955df
--- /dev/null
+++ b/slang_utils.cpp
@@ -0,0 +1,11 @@
+#include "slang_utils.h"
+
+#include "llvm/System/Path.h"
+
+using namespace slang;
+
+bool SlangUtils::CreateDirectoryWithParents(llvm::StringRef Dir,
+ std::string* Error) {
+ return !llvm::sys::Path(Dir).createDirectoryOnDisk(/* create_parents = */true,
+ Error);
+}
diff --git a/slang_utils.h b/slang_utils.h
new file mode 100644
index 0000000..7fe5aac
--- /dev/null
+++ b/slang_utils.h
@@ -0,0 +1,22 @@
+#ifndef _SLANG_COMPILER_UTILS_H
+#define _SLANG_COMPILER_UTILS_H
+
+#include <string>
+
+namespace llvm {
+ class StringRef;
+}
+
+namespace slang {
+
+class SlangUtils {
+ private:
+ SlangUtils() {}
+
+ public:
+ static bool CreateDirectoryWithParents(llvm::StringRef Dir,
+ std::string* Error);
+};
+}
+
+#endif // _SLANG_COMPILER_UTILS_H