From 2484b2510b78bbccf59ae6632512caff773f61bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Str=C3=B6mb=C3=A4ck?= Date: Fri, 25 Oct 2013 15:48:29 +0200 Subject: [PATCH 1/2] Removed output --- mymake.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/mymake.cpp b/mymake.cpp index b6d0a93..db7c2c2 100644 --- a/mymake.cpp +++ b/mymake.cpp @@ -50,7 +50,6 @@ bool compileFiles(Files &files, Files &toLink) { File relative = file.makeRelative(srcPath); File output = File(settings.getBuildPath()) + relative; output.setType(settings.intermediateExt); - cout << "Output file: " << output << endl; bool needsCompilation = false; if (settings.forceRecompilation) { From ef47a33225fd2b4cd8e68405e50089769efbf826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Str=C3=B6mb=C3=A4ck?= Date: Mon, 28 Oct 2013 13:56:49 +0100 Subject: [PATCH 2/2] Fixed a bug with empty file extentions. Added support for storing executable files in another path. --- file.cpp | 305 +++++++++++++++++++++++++++++---------------------- file.h | 112 ++++++++++++------- mymake.cpp | 2 - path.cpp | 240 ---------------------------------------- path.h | 90 --------------- settings.cpp | 13 ++- settings.h | 2 + 7 files changed, 260 insertions(+), 504 deletions(-) delete mode 100644 path.cpp delete mode 100644 path.h diff --git a/file.cpp b/file.cpp index e720465..46af3f2 100644 --- a/file.cpp +++ b/file.cpp @@ -1,197 +1,244 @@ #include "file.h" #include "mkpath.h" +#include "unistd.h" #include "directory.h" #include "globals.h" -#include "unistd.h" +#include +#include + +typedef unsigned int nat; + +string join(const std::vector &data, const string &between) { + if (data.size() == 0) return ""; + + std::ostringstream oss; + oss << data[0]; + for (nat i = 1; i < data.size(); i++) { + oss << between << data[i]; + } + return oss.str(); +} -#if 0 -#include +File::File(const string &path) { + parseStr(path); + simplify(); +} -using namespace std; +File::File() : isDirectory(true) {} -File::File(const string &path, const string &title) { - initialize(path + title); -} +void File::parseStr(const string &str) { + nat numPaths = std::count(str.begin(), str.end(), '\\'); + numPaths += std::count(str.begin(), str.end(), '/'); + parts.reserve(numPaths + 1); -File::File(const string &f) { - initialize(f); -} + nat startAt = 0; + for (nat i = 0; i < str.size(); i++) { + if (str[i] == '\\' || str[i] == '/') { + if (i > startAt) { + parts.push_back(str.substr(startAt, i - startAt)); + } + startAt = i + 1; + } + } -void File::initialize(const string &f) { - string filename = fixDelimiters(f); - int lastPath = filename.rfind(PATH_DELIM); - if (lastPath < 0) { - this->directory = string(".") + PATH_DELIM; - this->title = filename; + if (str.size() > startAt) { + parts.push_back(str.substr(startAt)); + isDirectory = false; } else { - this->directory = trimPath(filename.substr(0, lastPath + 1)); - this->title = filename.substr(lastPath + 1); + isDirectory = true; + } +} + +void File::simplify() { + std::vector::iterator i = parts.begin(); + while (i != parts.end()) { + if (*i == ".") { + // Safely removed. + i = parts.erase(i); + } else if (*i == ".." && i != parts.begin() && *(i - 1) != "..") { + // Remove previous path. + i = parts.erase(--i); + i = parts.erase(i); + } else { + // Nothing to do, continue. + ++i; + } } +} + +string File::toString() const { + string result = join(parts, string(1, PATH_DELIM)); + if (isDirectory && parts.size() > 0) result += PATH_DELIM; + if (!isAbsolute()) result = string(".") + string(1, PATH_DELIM) + result; + return result; - if (stat((directory + title).c_str(), &status) < 0) valid = false; - else valid = true; } -File::File(const File &other) { - *this = other; - if (stat((directory + title).c_str(), &status) < 0) valid = false; - else valid = true; +std::ostream &operator <<(std::ostream &to, const File &path) { + cout << path.toString(); + return to; } -File::~File() {} -File &File::operator =(const File &other) { - this->status = other.status; - this->directory = other.directory; - this->title = other.title; +bool File::operator ==(const File &o) const { + if (isDirectory != o.isDirectory) return false; + if (parts.size() != o.parts.size()) return false; + for (nat i = 0; i < parts.size(); i++) { + if (parts[i] != o.parts[i]) return false; + } + return true; +} + +File File::operator +(const File &other) const { + File result(*this); + result += other; + return result; +} + +File &File::operator +=(const File &other) { + isDirectory = other.isDirectory; + parts.insert(parts.end(), other.parts.begin(), other.parts.end()); + simplify(); return *this; } -bool File::operator ==(const File &other) const { - return (directory == other.directory) && (title == other.title); +File File::operator +(const string &name) const { + File result(*this); + result += name; + return result; } -bool File::isDirectory() const { - return S_ISDIR(status.st_mode); +File &File::operator +=(const string &name) { + *this += File(name); + return *this; } -bool File::isPrevious() const { - if (title == "..") return true; - if (title == ".") return true; - return false; +File File::parent() const { + File result(*this); + result.parts.pop_back(); + result.isDirectory = true; + return result; } -bool File::isType(const std::string &type) const { - return (title.substr(title.size() - type.size()) == type); +string File::title() const { + return parts.back(); } -string File::getTitle() const { - return title; +string File::titleNoExt() const { + string t = title(); + nat last = t.rfind('.'); + return t.substr(0, last); } -string File::getFullPath() const { - return directory + title; +bool File::isDir() const { + return isDirectory; } -string File::getDirectory() const { - if (!isDirectory()) return directory; - else return directory + title; +bool File::isAbsolute() const { + if (parts.size() == 0) return false; + const string &first = parts.front(); +#ifdef _WIN32 + if (first.size() < 2) return false; + return first[1] == L':'; +#else + return (first == ""); +#endif } -void File::output(ostream &to) const { - if (settings.debugOutput) { - if (isDirectory()) { - to << "[" << directory << ", " << title << "]"; - } else { - to << directory << ", " << title; - } - } else { - if (isDirectory()) { - to << "[" << directory << title << "]"; - } else { - to << directory << title; - } - } +bool File::isEmpty() const { + return parts.size() == 0; } -ostream &operator <<(ostream &outputTo, const File &output) { - output.output(outputTo); +bool File::exists() const { + struct stat status; + if (stat(toString().c_str(), &status) < 0) return false; + return true; +} - return outputTo; +time_t File::getLastModified() const { + struct stat status; + if (stat(toString().c_str(), &status) < 0) return 0; + return status.st_mtime; } -ifstream *File::read() const { - return new ifstream(getFullPath().c_str(), ifstream::in); +bool File::verifyDir() const { + struct stat status; + if (stat(toString().c_str(), &status) < 0) return false; + return S_ISDIR(status.st_mode); } -string File::trimPath(string path) { - string dotSlash = string(".") + PATH_DELIM; - int pos = path.find(dotSlash.c_str()); - while (pos >= 0) { - if (pos == 0) { - path = path.substr(pos + 2); - } else if (path[pos - 1] != '.') { - path = path.substr(0, pos) + path.substr(pos + 2); - } - pos = path.find(dotSlash.c_str(), pos + 1); - } +File File::makeRelative(const File &to) const { + File result; + result.isDirectory = isDirectory; - string slashDotDot = PATH_DELIM + string(".."); - pos = path.find(slashDotDot); - while (pos >= 0) { - int last = path.rfind(PATH_DELIM, pos - 1); - if (last >= 0) { - path = path.substr(0, last) + path.substr(pos + 3); + bool equal = true; + nat consumed = 0; + + for (nat i = 0; i < to.parts.size(); i++) { + if (!equal) { + result.parts.push_back(".."); + } else if (i >= parts.size()) { + result.parts.push_back(".."); + equal = false; + } else if (to.parts[i] != parts[i]) { + result.parts.push_back(".."); + equal = false; } else { - path = path.substr(pos + 4); + consumed++; } + } - pos = path.find(slashDotDot, pos + 1); + for (nat i = consumed; i < parts.size(); i++) { + result.parts.push_back(parts[i]); } - return dotSlash + path; + return result; } - -time_t File::getLastModified() const { - return status.st_mtime; +File File::modifyRelative(const File &old, const File &n) const { + File rel = makeRelative(old); + return n + rel; } +bool File::deleteFile() const { + return (unlink(toString().c_str()) == 0); +} -File File::modifyType(const string &type) const { - string dottedType; - if (type.size() == 0) dottedType = ""; - else dottedType = "." + type; - - int lastDot = title.rfind('.'); - if (lastDot >= 0) { - return File(directory, title.substr(0, lastDot) + dottedType); +void File::setType(const string &type) { + if (type == "") { + parts.back() = titleNoExt(); } else { - return File(directory, title + dottedType); + parts.back() = titleNoExt() + "." + type; } } -File File::modifyRelative(const string &original, const string &newRelative) const { - return File(newRelative + directory.substr(trimPath(original).size()), title); +void File::ensurePathExists() const { + mkpath(parent().toString().c_str(), 0764); } +bool File::isType(const string &ext) const { + string last = parts.back(); + size_t dot = last.rfind('.'); + if (dot == string::npos) return false; -void File::ensurePathExists() const { - mkpath(directory.c_str(), 0764); + return (last.substr(dot + 1) == ext); +} + +bool File::isPrevious() const { + return title() == "." || title() == ".."; } -void File::update() { - if (stat((directory + title).c_str(), &status) < 0) valid = false; - else valid = true; +ifstream *File::read() const { + return new ifstream(toString().c_str()); } -bool File::remove() const { - if (isDirectory()) { - Directory dir(*this); - if (settings.debugOutput) cout << "Removing " << getFullPath().c_str() << endl; - bool ok = dir.remove(); - ok &= (rmdir(getFullPath().c_str()) == 0); - if (!ok) cout << "Failed to remove " << getFullPath().c_str() << endl; - return ok; +void File::output(ostream &to) const { + for (int i = 0; i < parts.size(); i++) to << ", " << parts[i]; + if (verifyDir()) { + to << "[" << *this << "]"; } else { - if (settings.debugOutput) cout << "Removing " << getFullPath().c_str() << endl; - bool ok = (unlink(getFullPath().c_str()) == 0); - if (!ok) cout << "Failed to remove " << getFullPath().c_str() << endl; - return ok; + to << *this; } } -string File::fixDelimiters(const string &path) { - string result = path; - for (int i = 0; i < result.size(); i++) { - if (result[i] == '/') { - result[i] = PATH_DELIM; - } else if (result[i] == '\\') { - result[i] = PATH_DELIM; - } - } - return result; -} - -#endif diff --git a/file.h b/file.h index d24103e..ad2d7d3 100644 --- a/file.h +++ b/file.h @@ -1,60 +1,92 @@ #pragma once +#pragma once + #include #include #include "dirent.h" #include - #include - -#if 0 +#include using namespace std; +// A class for managing path names. class File { - public: - File(const string &directory, const string &title); - File(const string &filename); - File(const File &file); - virtual ~File(); - - File &operator =(const File &other); - bool operator ==(const File &other) const; - friend ostream &operator <<(ostream &outputTo, const File &output); - - string getTitle() const; - string getFullPath() const; - string getDirectory() const; - bool isValid() const { return valid; }; - bool isDirectory() const; - bool isPrevious() const; - bool isType(const string &type) const; - virtual time_t getLastModified() const; - File modifyType(const string &type) const; - File modifyRelative(const string &original, const string &newRelative) const; + friend std::ostream &operator <<(std::ostream &to, const File &path); +public: + // Create an empty path. + File(); - void ensurePathExists() const; + // Create a path object from a string. + explicit File(const string &path); - bool remove() const; + // Comparison. + bool operator ==(const File &o) const; + inline bool operator !=(const File &o) const { return !(*this == o); } - void update(); - ifstream* read() const; - protected: - struct stat status; - bool valid; + // Concat this path with another path, the other path must be relative. + File operator +(const File &other) const; + File &operator +=(const File &other); - string directory; - string title; + // Add a string to go deeper into the hierarchy. If this object is not + // a directory already, it will be made into one. + File operator +(const string &file) const; + File &operator +=(const string &file); - void initialize(const string &filename); + // To string. + string toString() const; - virtual void output(ostream &to) const; - static string trimPath(string path); - static string fixDelimiters(const string &path); -}; + // Status about this path. + bool isDir() const; + bool isAbsolute() const; + bool isEmpty() const; + + // Make this obj a directory. + void makeDir() { isDirectory = true; } + + // Get parent directory. + File parent() const; + + // Get the title of this file or directory. + string title() const; + string titleNoExt() const; + + // Does the file exist? + bool exists() const; + // Delete the file. + bool deleteFile() const; -#endif + // Make this path relative to another path. Absolute-making is accomplished by + // using the + operator above. + File makeRelative(const File &to) const; -#include "path.h" -typedef Path File; + // Make this path relative another path. + File modifyRelative(const File &original, const File &newRel) const; + + void setType(const string &to); + time_t getLastModified() const; + + void ensurePathExists() const; + bool isType(const string &ext) const; + bool verifyDir() const; // Check in the fs if the path is a dir. + bool isPrevious() const; + ifstream *read() const; + + // Output formatted to "out". + void output(ostream &to) const; +private: + + // Internal representation is a list of strings, one for each part of the pathname. + std::vector parts; + + // Is this a directory? + bool isDirectory; + + // Parse a path string. + void parseStr(const string &str); + + // Simplify a path string, which means to remove any . and .. + void simplify(); +}; diff --git a/mymake.cpp b/mymake.cpp index db7c2c2..6c1b499 100644 --- a/mymake.cpp +++ b/mymake.cpp @@ -183,8 +183,6 @@ int main(int argc, char **argv) { return -1; } - list::iterator i = files.begin(); - int errorCode = 0; Files toLink; diff --git a/path.cpp b/path.cpp deleted file mode 100644 index 3fce233..0000000 --- a/path.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include "path.h" -#include "mkpath.h" -#include "unistd.h" -#include "directory.h" -#include "globals.h" -#include -#include - -typedef unsigned int nat; - -string join(const std::vector &data, const string &between) { - if (data.size() == 0) return ""; - - std::ostringstream oss; - oss << data[0]; - for (nat i = 1; i < data.size(); i++) { - oss << between << data[i]; - } - return oss.str(); -} - - -Path::Path(const string &path) { - parseStr(path); - simplify(); -} - -Path::Path() : isDirectory(true) {} - -void Path::parseStr(const string &str) { - nat numPaths = std::count(str.begin(), str.end(), '\\'); - numPaths += std::count(str.begin(), str.end(), '/'); - parts.reserve(numPaths + 1); - - nat startAt = 0; - for (nat i = 0; i < str.size(); i++) { - if (str[i] == '\\' || str[i] == '/') { - if (i > startAt) { - parts.push_back(str.substr(startAt, i - startAt)); - } - startAt = i + 1; - } - } - - if (str.size() > startAt) { - parts.push_back(str.substr(startAt)); - isDirectory = false; - } else { - isDirectory = true; - } -} - -void Path::simplify() { - std::vector::iterator i = parts.begin(); - while (i != parts.end()) { - if (*i == ".") { - // Safely removed. - i = parts.erase(i); - } else if (*i == ".." && i != parts.begin() && *(i - 1) != "..") { - // Remove previous path. - i = parts.erase(--i); - i = parts.erase(i); - } else { - // Nothing to do, continue. - ++i; - } - } -} - -string Path::toString() const { - string result = join(parts, string(1, PATH_DELIM)); - if (isDirectory && parts.size() > 0) result += PATH_DELIM; - if (!isAbsolute()) result = string(".") + string(1, PATH_DELIM) + result; - return result; - -} - -std::ostream &operator <<(std::ostream &to, const Path &path) { - cout << path.toString(); - return to; -} - - -bool Path::operator ==(const Path &o) const { - if (isDirectory != o.isDirectory) return false; - if (parts.size() != o.parts.size()) return false; - for (nat i = 0; i < parts.size(); i++) { - if (parts[i] != o.parts[i]) return false; - } - return true; -} - -Path Path::operator +(const Path &other) const { - Path result(*this); - result += other; - return result; -} - -Path &Path::operator +=(const Path &other) { - isDirectory = other.isDirectory; - parts.insert(parts.end(), other.parts.begin(), other.parts.end()); - simplify(); - return *this; -} - -Path Path::operator +(const string &name) const { - Path result(*this); - result += name; - return result; -} - -Path &Path::operator +=(const string &name) { - *this += Path(name); - return *this; -} - -Path Path::parent() const { - Path result(*this); - result.parts.pop_back(); - result.isDirectory = true; - return result; -} - -string Path::title() const { - return parts.back(); -} - -string Path::titleNoExt() const { - string t = title(); - nat last = t.rfind('.'); - return t.substr(0, last); -} - -bool Path::isDir() const { - return isDirectory; -} - -bool Path::isAbsolute() const { - if (parts.size() == 0) return false; - const string &first = parts.front(); -#ifdef _WIN32 - if (first.size() < 2) return false; - return first[1] == L':'; -#else - return (first == ""); -#endif -} - -bool Path::isEmpty() const { - return parts.size() == 0; -} - -bool Path::exists() const { - struct stat status; - if (stat(toString().c_str(), &status) < 0) return false; - return true; -} - -time_t Path::getLastModified() const { - struct stat status; - if (stat(toString().c_str(), &status) < 0) return 0; - return status.st_mtime; -} - -bool Path::verifyDir() const { - struct stat status; - if (stat(toString().c_str(), &status) < 0) return false; - return S_ISDIR(status.st_mode); -} - -Path Path::makeRelative(const Path &to) const { - Path result; - result.isDirectory = isDirectory; - - bool equal = true; - nat consumed = 0; - - for (nat i = 0; i < to.parts.size(); i++) { - if (!equal) { - result.parts.push_back(".."); - } else if (i >= parts.size()) { - result.parts.push_back(".."); - equal = false; - } else if (to.parts[i] != parts[i]) { - result.parts.push_back(".."); - equal = false; - } else { - consumed++; - } - } - - for (nat i = consumed; i < parts.size(); i++) { - result.parts.push_back(parts[i]); - } - - return result; -} - -Path Path::modifyRelative(const Path &old, const Path &n) const { - Path rel = makeRelative(old); - return n + rel; -} - -bool Path::deleteFile() const { - return (unlink(toString().c_str()) == 0); -} - -void Path::setType(const string &type) { - parts.back() = titleNoExt() + "." + type; -} - -void Path::ensurePathExists() const { - mkpath(parent().toString().c_str(), 0764); -} - -bool Path::isType(const string &ext) const { - string last = parts.back(); - size_t dot = last.rfind('.'); - if (dot == string::npos) return false; - - return (last.substr(dot + 1) == ext); -} - -bool Path::isPrevious() const { - return title() == "." || title() == ".."; -} - -ifstream *Path::read() const { - return new ifstream(toString().c_str()); -} - -void File::output(ostream &to) const { - for (int i = 0; i < parts.size(); i++) to << ", " << parts[i]; - if (verifyDir()) { - to << "[" << *this << "]"; - } else { - to << *this; - } -} - diff --git a/path.h b/path.h deleted file mode 100644 index 2398d66..0000000 --- a/path.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include -#include -#include "dirent.h" -#include -#include -#include - -using namespace std; - -// A class for managing path names. -class Path { - friend std::ostream &operator <<(std::ostream &to, const Path &path); -public: - // Create an empty path. - Path(); - - // Create a path object from a string. - explicit Path(const string &path); - - // Comparison. - bool operator ==(const Path &o) const; - inline bool operator !=(const Path &o) const { return !(*this == o); } - - // Concat this path with another path, the other path must be relative. - Path operator +(const Path &other) const; - Path &operator +=(const Path &other); - - // Add a string to go deeper into the hierarchy. If this object is not - // a directory already, it will be made into one. - Path operator +(const string &file) const; - Path &operator +=(const string &file); - - // To string. - string toString() const; - - // Status about this path. - bool isDir() const; - bool isAbsolute() const; - bool isEmpty() const; - - // Make this obj a directory. - void makeDir() { isDirectory = true; } - - // Get parent directory. - Path parent() const; - - // Get the title of this file or directory. - string title() const; - string titleNoExt() const; - - // Does the file exist? - bool exists() const; - - // Delete the file. - bool deleteFile() const; - - // Make this path relative to another path. Absolute-making is accomplished by - // using the + operator above. - Path makeRelative(const Path &to) const; - - // Make this path relative another path. - Path modifyRelative(const Path &original, const Path &newRel) const; - - void setType(const string &to); - time_t getLastModified() const; - - void ensurePathExists() const; - bool isType(const string &ext) const; - bool verifyDir() const; // Check in the fs if the path is a dir. - bool isPrevious() const; - ifstream *read() const; - - // Output formatted to "out". - void output(ostream &to) const; -private: - - // Internal representation is a list of strings, one for each part of the pathname. - std::vector parts; - - // Is this a directory? - bool isDirectory; - - // Parse a path string. - void parseStr(const string &str); - - // Simplify a path string, which means to remove any . and .. - void simplify(); -}; diff --git a/settings.cpp b/settings.cpp index 488477e..63222a4 100644 --- a/settings.cpp +++ b/settings.cpp @@ -100,6 +100,9 @@ void Settings::install() const { out << "#Output (defaults to the name of the first input file)" << endl; out << "#out=" << endl; out << "" << endl; + out << "#Set the output path for executable files." << endl; + out << "executablePath=./" << endl; + out << "" << endl; out << "#Command used to compile a single source file into a unlinked file." << endl; out << "# will be replaced by the input file and" << endl; out << "# will be replaced by the outputn file" << endl; @@ -259,6 +262,8 @@ void Settings::storeItem(const string &identifier, const string &value) { executableExt = value; } else if (identifier == "out") { active.outFile = value; + } else if (identifier == "executablePath") { + executablePath = File(value); } else if (identifier == "ignore") { ignoreFiles.push_back(value); } else if (identifier == "compile") { @@ -381,9 +386,11 @@ bool Settings::enoughForCompilation() { if (active.buildPath.size() == 0) return false; if (active.outFile.size() == 0) { - File firstInFile(inputFiles.front()); - firstInFile.setType(executableExt); - active.outFile = firstInFile.toString(); + File inFile(inputFiles.front()); + File outFile(executablePath); + outFile += inFile.title(); + outFile.setType(executableExt); + active.outFile = outFile.toString(); } return true; diff --git a/settings.h b/settings.h index 6dce1a0..995b706 100644 --- a/settings.h +++ b/settings.h @@ -5,6 +5,7 @@ #include "includecache.h" #include "wildcard.h" +#include "file.h" using namespace std; @@ -18,6 +19,7 @@ class Settings { string intermediateExt; string executableExt; string executable; + File executablePath; list inputFiles; list cppExtensions;