Lines 36-44
Link Here
|
36 |
# include <sys/param.h> |
36 |
# include <sys/param.h> |
37 |
#endif |
37 |
#endif |
38 |
|
38 |
|
39 |
#include <boost/filesystem/path.hpp> |
39 |
#include <filesystem> |
40 |
#include <boost/filesystem/operations.hpp> |
40 |
#include <fstream> |
41 |
#include "boost_string_file.hpp" |
|
|
42 |
|
41 |
|
43 |
#include "PyrParseNode.h" |
42 |
#include "PyrParseNode.h" |
44 |
#include "Bison/lang11d_tab.h" |
43 |
#include "Bison/lang11d_tab.h" |
Lines 84-95
int gNumCompiledFiles;
Link Here
|
84 |
thisProcess.interpreter.executeFile("Macintosh HD:score").size.postln; |
83 |
thisProcess.interpreter.executeFile("Macintosh HD:score").size.postln; |
85 |
*/ |
84 |
*/ |
86 |
|
85 |
|
87 |
namespace bfs = boost::filesystem; |
86 |
namespace fs = std::filesystem; |
88 |
using DirName = SC_Filesystem::DirName; |
87 |
using DirName = SC_Filesystem::DirName; |
89 |
|
88 |
|
90 |
PyrSymbol* gCompilingFileSym = nullptr; |
89 |
PyrSymbol* gCompilingFileSym = nullptr; |
91 |
VMGlobals* gCompilingVMGlobals = nullptr; |
90 |
VMGlobals* gCompilingVMGlobals = nullptr; |
92 |
static bfs::path gCompileDir; |
91 |
static fs::path gCompileDir; |
93 |
|
92 |
|
94 |
//#define DEBUGLEX 1 |
93 |
//#define DEBUGLEX 1 |
95 |
bool gDebugLexer = false; |
94 |
bool gDebugLexer = false; |
Lines 102-108
int lastClosedFuncCharNo = 0;
Link Here
|
102 |
|
101 |
|
103 |
const char* binopchars = "!@%&*-+=|<>?/"; |
102 |
const char* binopchars = "!@%&*-+=|<>?/"; |
104 |
char yytext[MAXYYLEN]; |
103 |
char yytext[MAXYYLEN]; |
105 |
bfs::path currfilename; |
104 |
fs::path currfilename; |
106 |
std::string printingCurrfilename; // for error reporting |
105 |
std::string printingCurrfilename; // for error reporting |
107 |
|
106 |
|
108 |
int yylen; |
107 |
int yylen; |
Lines 122-128
int textpos;
Link Here
|
122 |
int errLineOffset, errCharPosOffset; |
121 |
int errLineOffset, errCharPosOffset; |
123 |
int parseFailed = 0; |
122 |
int parseFailed = 0; |
124 |
bool compiledOK = false; |
123 |
bool compiledOK = false; |
125 |
std::set<bfs::path> compiledDirectories; |
124 |
std::set<fs::path> compiledDirectories; |
126 |
|
125 |
|
127 |
/* so the text editor's dumb paren matching will work */ |
126 |
/* so the text editor's dumb paren matching will work */ |
128 |
#define OPENPAREN '(' |
127 |
#define OPENPAREN '(' |
Lines 170-187
double sc_strtof(const char* str, int n, int base) {
Link Here
|
170 |
return z; |
169 |
return z; |
171 |
} |
170 |
} |
172 |
|
171 |
|
173 |
bool startLexer(PyrSymbol* fileSym, const bfs::path& p, int startPos, int endPos, int lineOffset); |
172 |
bool startLexer(PyrSymbol* fileSym, const fs::path& p, int startPos, int endPos, int lineOffset); |
174 |
bool startLexer(PyrSymbol* fileSym, const bfs::path& p, int startPos, int endPos, int lineOffset) { |
173 |
bool startLexer(PyrSymbol* fileSym, const fs::path& p, int startPos, int endPos, int lineOffset) { |
175 |
const char* filename = fileSym->name; |
174 |
const char* filename = fileSym->name; |
176 |
|
175 |
|
177 |
textlen = -1; |
176 |
textlen = -1; |
178 |
|
177 |
|
179 |
if (!fileSym->u.source) { |
178 |
if (!fileSym->u.source) { |
180 |
try { |
179 |
try { |
181 |
bfs::ifstream file; |
180 |
std::ifstream file; |
182 |
file.exceptions(std::ifstream::failbit | std::ifstream::badbit); |
181 |
file.exceptions(std::ifstream::failbit | std::ifstream::badbit); |
183 |
file.open(p, std::ios_base::binary); |
182 |
file.open(p, std::ios_base::binary); |
184 |
size_t sz = bfs::file_size(p); |
183 |
size_t sz = fs::file_size(p); |
185 |
|
184 |
|
186 |
text = (char*)pyr_pool_compile->Alloc((sz + 1) * sizeof(char)); |
185 |
text = (char*)pyr_pool_compile->Alloc((sz + 1) * sizeof(char)); |
187 |
MEMFAIL(text); |
186 |
MEMFAIL(text); |
Lines 225-231
bool startLexer(PyrSymbol* fileSym, const bfs::path& p, int startPos, int endPos
Link Here
|
225 |
zzval = 0; |
224 |
zzval = 0; |
226 |
parseFailed = 0; |
225 |
parseFailed = 0; |
227 |
lexCmdLine = 0; |
226 |
lexCmdLine = 0; |
228 |
currfilename = bfs::path(filename); |
227 |
currfilename = fs::path(filename); |
229 |
printingCurrfilename = "file '" + SC_Codecvt::path_to_utf8_str(currfilename) + "'"; |
228 |
printingCurrfilename = "file '" + SC_Codecvt::path_to_utf8_str(currfilename) + "'"; |
230 |
maxlinestarts = 1000; |
229 |
maxlinestarts = 1000; |
231 |
linestarts = (int*)pyr_pool_compile->Alloc(maxlinestarts * sizeof(int*)); |
230 |
linestarts = (int*)pyr_pool_compile->Alloc(maxlinestarts * sizeof(int*)); |
Lines 261-267
void startLexerCmdLine(char* textbuf, int textbuflen) {
Link Here
|
261 |
zzval = 0; |
260 |
zzval = 0; |
262 |
parseFailed = 0; |
261 |
parseFailed = 0; |
263 |
lexCmdLine = 1; |
262 |
lexCmdLine = 1; |
264 |
currfilename = bfs::path("interpreted text"); |
263 |
currfilename = fs::path("interpreted text"); |
265 |
printingCurrfilename = currfilename.string(); |
264 |
printingCurrfilename = currfilename.string(); |
266 |
maxlinestarts = 1000; |
265 |
maxlinestarts = 1000; |
267 |
linestarts = (int*)pyr_pool_compile->Alloc(maxlinestarts * sizeof(int*)); |
266 |
linestarts = (int*)pyr_pool_compile->Alloc(maxlinestarts * sizeof(int*)); |
Lines 1721-1727
void compileClass(PyrSymbol* fileSym, int startPos, int endPos, int lineOffset)
Link Here
|
1721 |
gCompilingVMGlobals = nullptr; |
1720 |
gCompilingVMGlobals = nullptr; |
1722 |
gRootParseNode = nullptr; |
1721 |
gRootParseNode = nullptr; |
1723 |
initParserPool(); |
1722 |
initParserPool(); |
1724 |
if (startLexer(fileSym, bfs::path(), startPos, endPos, lineOffset)) { |
1723 |
if (startLexer(fileSym, fs::path(), startPos, endPos, lineOffset)) { |
1725 |
// postfl("->Parsing %s\n", fileSym->name); fflush(stdout); |
1724 |
// postfl("->Parsing %s\n", fileSym->name); fflush(stdout); |
1726 |
parseFailed = yyparse(); |
1725 |
parseFailed = yyparse(); |
1727 |
// postfl("<-Parsing %s %d\n", fileSym->name, parseFailed); fflush(stdout); |
1726 |
// postfl("<-Parsing %s %d\n", fileSym->name, parseFailed); fflush(stdout); |
Lines 1733-1739
void compileClass(PyrSymbol* fileSym, int startPos, int endPos, int lineOffset)
Link Here
|
1733 |
// postfl("done compiling\n");fflush(stdout); |
1732 |
// postfl("done compiling\n");fflush(stdout); |
1734 |
} else { |
1733 |
} else { |
1735 |
compileErrors++; |
1734 |
compileErrors++; |
1736 |
bfs::path pathname(fileSym->name); |
1735 |
fs::path pathname(fileSym->name); |
1737 |
error("file '%s' parse failed\n", SC_Codecvt::path_to_utf8_str(pathname).c_str()); |
1736 |
error("file '%s' parse failed\n", SC_Codecvt::path_to_utf8_str(pathname).c_str()); |
1738 |
postfl("error parsing\n"); |
1737 |
postfl("error parsing\n"); |
1739 |
} |
1738 |
} |
Lines 1942-1948
void finiPassOne() {
Link Here
|
1942 |
/** |
1941 |
/** |
1943 |
* \brief \c true if \c dir is one of the language config's default classlib directories |
1942 |
* \brief \c true if \c dir is one of the language config's default classlib directories |
1944 |
*/ |
1943 |
*/ |
1945 |
static bool isDefaultClassLibraryDirectory(const bfs::path& dir) { |
1944 |
static bool isDefaultClassLibraryDirectory(const fs::path& dir) { |
1946 |
auto const& defaultDirs = gLanguageConfig->defaultClassLibraryDirectories(); |
1945 |
auto const& defaultDirs = gLanguageConfig->defaultClassLibraryDirectories(); |
1947 |
auto const iter = std::find(defaultDirs.begin(), defaultDirs.end(), dir); |
1946 |
auto const iter = std::find(defaultDirs.begin(), defaultDirs.end(), dir); |
1948 |
return iter != defaultDirs.end(); |
1947 |
return iter != defaultDirs.end(); |
Lines 1955-1964
static bool isDefaultClassLibraryDirectory(const bfs::path& dir) {
Link Here
|
1955 |
* try to create it, silently ignoring failure (most likely from permissions failure). |
1954 |
* try to create it, silently ignoring failure (most likely from permissions failure). |
1956 |
* Otherwise, warn the user to help catch mistyped/missing directory names. See #3468. |
1955 |
* Otherwise, warn the user to help catch mistyped/missing directory names. See #3468. |
1957 |
*/ |
1956 |
*/ |
1958 |
static void passOne_HandleMissingDirectory(const bfs::path& dir) { |
1957 |
static void passOne_HandleMissingDirectory(const fs::path& dir) { |
1959 |
if (isDefaultClassLibraryDirectory(dir)) { |
1958 |
if (isDefaultClassLibraryDirectory(dir)) { |
1960 |
boost::system::error_code ec {}; |
1959 |
std::error_code ec {}; |
1961 |
bfs::create_directories(dir, ec); |
1960 |
fs::create_directories(dir, ec); |
1962 |
} else { |
1961 |
} else { |
1963 |
post("WARNING: Could not open directory: '%s'\n" |
1962 |
post("WARNING: Could not open directory: '%s'\n" |
1964 |
"\tTo resolve this, either create the directory or remove it from your compilation paths.\n\n", |
1963 |
"\tTo resolve this, either create the directory or remove it from your compilation paths.\n\n", |
Lines 1966-1972
static void passOne_HandleMissingDirectory(const bfs::path& dir) {
Link Here
|
1966 |
} |
1965 |
} |
1967 |
} |
1966 |
} |
1968 |
|
1967 |
|
1969 |
bfs::path relativeToCompileDir(const bfs::path& p) { return bfs::relative(p, gCompileDir); } |
1968 |
fs::path relativeToCompileDir(const fs::path& p) { return fs::relative(p, gCompileDir); } |
1970 |
|
1969 |
|
1971 |
/** \brief Determines whether the directory should be skipped during compilation. |
1970 |
/** \brief Determines whether the directory should be skipped during compilation. |
1972 |
* |
1971 |
* |
Lines 1976-1982
bfs::path relativeToCompileDir(const bfs::path& p) { return bfs::relative(p, gCo
Link Here
|
1976 |
* - the language configuration says this path is excluded |
1975 |
* - the language configuration says this path is excluded |
1977 |
* - SC_Filesystem::shouldNotCompileDirectory(dir) returns `true` |
1976 |
* - SC_Filesystem::shouldNotCompileDirectory(dir) returns `true` |
1978 |
*/ |
1977 |
*/ |
1979 |
static bool passOne_ShouldSkipDirectory(const bfs::path& dir) { |
1978 |
static bool passOne_ShouldSkipDirectory(const fs::path& dir) { |
1980 |
return (compiledDirectories.find(dir) != compiledDirectories.end()) |
1979 |
return (compiledDirectories.find(dir) != compiledDirectories.end()) |
1981 |
|| (gLanguageConfig && gLanguageConfig->pathIsExcluded(dir)) |
1980 |
|| (gLanguageConfig && gLanguageConfig->pathIsExcluded(dir)) |
1982 |
|| (SC_Filesystem::instance().shouldNotCompileDirectory(dir)); |
1981 |
|| (SC_Filesystem::instance().shouldNotCompileDirectory(dir)); |
Lines 2003-2026
static bool passOne_ShouldSkipDirectory(const bfs::path& dir) {
Link Here
|
2003 |
* \returns `true` if processing was successful, `false` if it failed. |
2002 |
* \returns `true` if processing was successful, `false` if it failed. |
2004 |
* See above for what constitutes success and failure conditions. |
2003 |
* See above for what constitutes success and failure conditions. |
2005 |
*/ |
2004 |
*/ |
2006 |
static bool passOne_ProcessDir(const bfs::path& dir) { |
2005 |
static bool passOne_ProcessDir(const fs::path& dir) { |
2007 |
// Prefer non-throwing versions of filesystem functions, since they are actually not unexpected |
2006 |
// Prefer non-throwing versions of filesystem functions, since they are actually not unexpected |
2008 |
// and because it's faster to use error codes. |
2007 |
// and because it's faster to use error codes. |
2009 |
boost::system::error_code ec; |
2008 |
std::error_code ec; |
2010 |
|
2009 |
|
2011 |
// Perform tilde expansion on incoming dir. |
2010 |
// Perform tilde expansion on incoming dir. |
2012 |
const bfs::path expdir = SC_Filesystem::instance().expandTilde(dir); |
2011 |
const fs::path expdir = SC_Filesystem::instance().expandTilde(dir); |
2013 |
|
2012 |
|
2014 |
// Using a recursive_directory_iterator is much faster than actually calling this function |
2013 |
// Using a recursive_directory_iterator is much faster than actually calling this function |
2015 |
// recursively. Speedup from the switch was about 1.5x. _Do_ recurse on symlinks. |
2014 |
// recursively. Speedup from the switch was about 1.5x. _Do_ recurse on symlinks. |
2016 |
bfs::recursive_directory_iterator rditer(expdir, bfs::symlink_option::recurse, ec); |
2015 |
fs::recursive_directory_iterator rditer(expdir, fs::directory_options::follow_directory_symlink, ec); |
2017 |
|
2016 |
|
2018 |
// Check preconditions: are we able to access the file, and should we compile it according to |
2017 |
// Check preconditions: are we able to access the file, and should we compile it according to |
2019 |
// the language configuration? |
2018 |
// the language configuration? |
2020 |
if (ec) { |
2019 |
if (ec) { |
2021 |
// If we got an error, post a warning if it was because the target wasn't found, and return success. |
2020 |
// If we got an error, post a warning if it was because the target wasn't found, and return success. |
2022 |
// Otherwise, post the error and fail. |
2021 |
// Otherwise, post the error and fail. |
2023 |
if (ec.default_error_condition().value() == boost::system::errc::no_such_file_or_directory) { |
2022 |
if (ec.default_error_condition() == std::errc::no_such_file_or_directory) { |
2024 |
passOne_HandleMissingDirectory(expdir); |
2023 |
passOne_HandleMissingDirectory(expdir); |
2025 |
return true; |
2024 |
return true; |
2026 |
} else { |
2025 |
} else { |
Lines 2042-2055
static bool passOne_ProcessDir(const bfs::path& dir) {
Link Here
|
2042 |
|
2041 |
|
2043 |
// Invariant: we have processed (or begun to process) every directory or file already |
2042 |
// Invariant: we have processed (or begun to process) every directory or file already |
2044 |
// touched by the iterator. |
2043 |
// touched by the iterator. |
2045 |
while (rditer != bfs::end(rditer)) { |
2044 |
while (rditer != fs::end(rditer)) { |
2046 |
const bfs::path path = *rditer; |
2045 |
const fs::path path = *rditer; |
2047 |
|
2046 |
|
2048 |
// If the file is a directory, perform the same checks as above to see if we should |
2047 |
// If the file is a directory, perform the same checks as above to see if we should |
2049 |
// skip compilation on it. |
2048 |
// skip compilation on it. |
2050 |
if (bfs::is_directory(path)) { |
2049 |
if (fs::is_directory(path)) { |
2051 |
if (passOne_ShouldSkipDirectory(path)) { |
2050 |
if (passOne_ShouldSkipDirectory(path)) { |
2052 |
rditer.no_push(); // don't "push" into the next level of the hierarchy |
2051 |
rditer.disable_recursion_pending(); // don't "push" into the next level of the hierarchy |
2053 |
} else { |
2052 |
} else { |
2054 |
// Mark this directory as compiled. |
2053 |
// Mark this directory as compiled. |
2055 |
// By not calling no_push(), we allow the iterator to enter the directory |
2054 |
// By not calling no_push(), we allow the iterator to enter the directory |
Lines 2062-2069
static bool passOne_ProcessDir(const bfs::path& dir) {
Link Here
|
2062 |
// - resolution failed: returns empty path: let the user know |
2061 |
// - resolution failed: returns empty path: let the user know |
2063 |
// - it was not an alias, or was an alias that wasn't a directory: try to process it as a source file |
2062 |
// - it was not an alias, or was an alias that wasn't a directory: try to process it as a source file |
2064 |
bool isAlias = false; |
2063 |
bool isAlias = false; |
2065 |
const bfs::path& respath = SC_Filesystem::resolveIfAlias(path, isAlias); |
2064 |
const fs::path& respath = SC_Filesystem::resolveIfAlias(path, isAlias); |
2066 |
if (isAlias && bfs::is_directory(respath)) { |
2065 |
if (isAlias && fs::is_directory(respath)) { |
2067 |
// If the resolved alias is a directory, recurse on it. |
2066 |
// If the resolved alias is a directory, recurse on it. |
2068 |
if (!passOne_ProcessDir(respath)) { |
2067 |
if (!passOne_ProcessDir(respath)) { |
2069 |
return false; |
2068 |
return false; |
Lines 2095-2102
bool passOne() {
Link Here
|
2095 |
} |
2094 |
} |
2096 |
|
2095 |
|
2097 |
/// True if file doesn't begin with '.', and ends with either '.sc' or '.rtf' |
2096 |
/// True if file doesn't begin with '.', and ends with either '.sc' or '.rtf' |
2098 |
bool isValidSourceFileName(const bfs::path& path) { |
2097 |
bool isValidSourceFileName(const fs::path& path) { |
2099 |
const bfs::path& ext = path.extension(); |
2098 |
const fs::path& ext = path.extension(); |
2100 |
return path.filename().c_str()[0] != '.' && // must not be hidden file |
2099 |
return path.filename().c_str()[0] != '.' && // must not be hidden file |
2101 |
((ext == ".sc") || (ext == ".rtf" && path.stem().extension() == ".sc")); |
2100 |
((ext == ".sc") || (ext == ".rtf" && path.stem().extension() == ".sc")); |
2102 |
} |
2101 |
} |
Lines 2110-2116
bool isValidSourceFileName(const bfs::path& path) {
Link Here
|
2110 |
* \returns Whether parsing was successful. The only failure condition occurs |
2109 |
* \returns Whether parsing was successful. The only failure condition occurs |
2111 |
* when the file can't be opened. |
2110 |
* when the file can't be opened. |
2112 |
*/ |
2111 |
*/ |
2113 |
bool passOne_ProcessOneFile(const bfs::path& path) { |
2112 |
bool passOne_ProcessOneFile(const fs::path& path) { |
2114 |
bool success = true; |
2113 |
bool success = true; |
2115 |
|
2114 |
|
2116 |
const std::string path_str = SC_Codecvt::path_to_utf8_str(path); |
2115 |
const std::string path_str = SC_Codecvt::path_to_utf8_str(path); |