|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
# ifdef __MINGW32__
|
|
Packit Service |
7770af |
# ifndef off64_t
|
|
Packit Service |
7770af |
# define off64_t _off64_t /* Workaround for http://sourceforge.net/p/mingw/bugs/2024/ */
|
|
Packit Service |
7770af |
# endif
|
|
Packit Service |
7770af |
# endif
|
|
Packit Service |
7770af |
# include <direct.h>
|
|
Packit Service |
7770af |
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
|
Packit Service |
7770af |
#else
|
|
Packit Service |
7770af |
# include <unistd.h>
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
#include "sass.hpp"
|
|
Packit Service |
7770af |
#include <iostream>
|
|
Packit Service |
7770af |
#include <fstream>
|
|
Packit Service |
7770af |
#include <cctype>
|
|
Packit Service |
7770af |
#include <vector>
|
|
Packit Service |
7770af |
#include <algorithm>
|
|
Packit Service |
7770af |
#include <sys/stat.h>
|
|
Packit Service |
7770af |
#include "file.hpp"
|
|
Packit Service |
7770af |
#include "context.hpp"
|
|
Packit Service |
7770af |
#include "prelexer.hpp"
|
|
Packit Service |
7770af |
#include "utf8_string.hpp"
|
|
Packit Service |
7770af |
#include "sass_functions.hpp"
|
|
Packit Service |
7770af |
#include "sass2scss.h"
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
# include <windows.h>
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
# ifdef _MSC_VER
|
|
Packit Service |
7770af |
# include <codecvt>
|
|
Packit Service |
7770af |
inline static std::string wstring_to_string(const std::wstring& wstr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_converter;
|
|
Packit Service |
7770af |
return wchar_converter.to_bytes(wstr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
# else // mingw(/gcc) does not support C++11's codecvt yet.
|
|
Packit Service |
7770af |
inline static std::string wstring_to_string(const std::wstring &wstr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
|
|
Packit Service |
7770af |
std::string strTo(size_needed, 0);
|
|
Packit Service |
7770af |
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
|
|
Packit Service |
7770af |
return strTo;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
# endif
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
namespace Sass {
|
|
Packit Service |
7770af |
namespace File {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// return the current directory
|
|
Packit Service |
7770af |
// always with forward slashes
|
|
Packit Service |
7770af |
std::string get_cwd()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
const size_t wd_len = 1024;
|
|
Packit Service |
7770af |
#ifndef _WIN32
|
|
Packit Service |
7770af |
char wd[wd_len];
|
|
Packit Service |
7770af |
std::string cwd = getcwd(wd, wd_len);
|
|
Packit Service |
7770af |
#else
|
|
Packit Service |
7770af |
wchar_t wd[wd_len];
|
|
Packit Service |
7770af |
std::string cwd = wstring_to_string(_wgetcwd(wd, wd_len));
|
|
Packit Service |
7770af |
//convert backslashes to forward slashes
|
|
Packit Service |
7770af |
replace(cwd.begin(), cwd.end(), '\\', '/');
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
if (cwd[cwd.length() - 1] != '/') cwd += '/';
|
|
Packit Service |
7770af |
return cwd;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// test if path exists and is a file
|
|
Packit Service |
7770af |
bool file_exists(const std::string& path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
std::wstring wpath = UTF_8::convert_to_utf16(path);
|
|
Packit Service |
7770af |
DWORD dwAttrib = GetFileAttributesW(wpath.c_str());
|
|
Packit Service |
7770af |
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
|
Packit Service |
7770af |
(!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)));
|
|
Packit Service |
7770af |
#else
|
|
Packit Service |
7770af |
struct stat st_buf;
|
|
Packit Service |
7770af |
return (stat (path.c_str(), &st_buf) == 0) &&
|
|
Packit Service |
7770af |
(!S_ISDIR (st_buf.st_mode));
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// return if given path is absolute
|
|
Packit Service |
7770af |
// works with *nix and windows paths
|
|
Packit Service |
7770af |
bool is_absolute_path(const std::string& path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
if (path.length() >= 2 && isalpha(path[0]) && path[1] == ':') return true;
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
size_t i = 0;
|
|
Packit Service |
7770af |
// check if we have a protocol
|
|
Packit Service |
7770af |
if (path[i] && Prelexer::is_alpha(path[i])) {
|
|
Packit Service |
7770af |
// skip over all alphanumeric characters
|
|
Packit Service |
7770af |
while (path[i] && Prelexer::is_alnum(path[i])) ++i;
|
|
Packit Service |
7770af |
i = i && path[i] == ':' ? i + 1 : 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return path[i] == '/';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// helper function to find the last directory seperator
|
|
Packit Service |
7770af |
inline size_t find_last_folder_separator(const std::string& path, size_t limit = std::string::npos)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
size_t pos;
|
|
Packit Service |
7770af |
size_t pos_p = path.find_last_of('/', limit);
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
size_t pos_w = path.find_last_of('\\', limit);
|
|
Packit Service |
7770af |
#else
|
|
Packit Service |
7770af |
size_t pos_w = std::string::npos;
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
if (pos_p != std::string::npos && pos_w != std::string::npos) {
|
|
Packit Service |
7770af |
pos = std::max(pos_p, pos_w);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (pos_p != std::string::npos) {
|
|
Packit Service |
7770af |
pos = pos_p;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
pos = pos_w;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return pos;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// return only the directory part of path
|
|
Packit Service |
7770af |
std::string dir_name(const std::string& path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
size_t pos = find_last_folder_separator(path);
|
|
Packit Service |
7770af |
if (pos == std::string::npos) return "";
|
|
Packit Service |
7770af |
else return path.substr(0, pos+1);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// return only the filename part of path
|
|
Packit Service |
7770af |
std::string base_name(const std::string& path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
size_t pos = find_last_folder_separator(path);
|
|
Packit Service |
7770af |
if (pos == std::string::npos) return path;
|
|
Packit Service |
7770af |
else return path.substr(pos+1);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// do a logical clean up of the path
|
|
Packit Service |
7770af |
// no physical check on the filesystem
|
|
Packit Service |
7770af |
std::string make_canonical_path (std::string path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// declarations
|
|
Packit Service |
7770af |
size_t pos;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
//convert backslashes to forward slashes
|
|
Packit Service |
7770af |
replace(path.begin(), path.end(), '\\', '/');
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
pos = 0; // remove all self references inside the path string
|
|
Packit Service |
7770af |
while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// remove all leading and trailing self references
|
|
Packit Service |
7770af |
while(path.length() > 1 && path.substr(0, 2) == "./") path.erase(0, 2);
|
|
Packit Service |
7770af |
while((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") path.erase(pos - 2);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
size_t proto = 0;
|
|
Packit Service |
7770af |
// check if we have a protocol
|
|
Packit Service |
7770af |
if (path[proto] && Prelexer::is_alpha(path[proto])) {
|
|
Packit Service |
7770af |
// skip over all alphanumeric characters
|
|
Packit Service |
7770af |
while (path[proto] && Prelexer::is_alnum(path[proto++])) {}
|
|
Packit Service |
7770af |
// then skip over the mandatory colon
|
|
Packit Service |
7770af |
if (proto && path[proto] == ':') ++ proto;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// then skip over start slashes
|
|
Packit Service |
7770af |
while (path[proto++] == '/') {}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
pos = proto; // collapse multiple delimiters into a single one
|
|
Packit Service |
7770af |
while((pos = path.find("//", pos)) != std::string::npos) path.erase(pos, 1);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return path;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// join two path segments cleanly together
|
|
Packit Service |
7770af |
// but only if right side is not absolute yet
|
|
Packit Service |
7770af |
std::string join_paths(std::string l, std::string r)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
// convert Windows backslashes to URL forward slashes
|
|
Packit Service |
7770af |
replace(l.begin(), l.end(), '\\', '/');
|
|
Packit Service |
7770af |
replace(r.begin(), r.end(), '\\', '/');
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (l.empty()) return r;
|
|
Packit Service |
7770af |
if (r.empty()) return l;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (is_absolute_path(r)) return r;
|
|
Packit Service |
7770af |
if (l[l.length()-1] != '/') l += '/';
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) {
|
|
Packit Service |
7770af |
size_t L = l.length(), pos = find_last_folder_separator(l, L - 2);
|
|
Packit Service |
7770af |
bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\');
|
|
Packit Service |
7770af |
bool is_self = pos + 3 == L && (l[pos+1] == '.');
|
|
Packit Service |
7770af |
if (!is_self && !is_slash) r = r.substr(3);
|
|
Packit Service |
7770af |
else if (pos == std::string::npos) break;
|
|
Packit Service |
7770af |
l = l.substr(0, pos == std::string::npos ? pos : pos + 1);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return l + r;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string path_for_console(const std::string& rel_path, const std::string& abs_path, const std::string& orig_path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// magic algorith goes here!!
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// if the file is outside this directory show the absolute path
|
|
Packit Service |
7770af |
if (rel_path.substr(0, 3) == "../") {
|
|
Packit Service |
7770af |
return orig_path;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// this seems to work most of the time
|
|
Packit Service |
7770af |
return abs_path == orig_path ? abs_path : rel_path;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create an absolute path by resolving relative paths with cwd
|
|
Packit Service |
7770af |
std::string rel2abs(const std::string& path, const std::string& base, const std::string& cwd)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return make_canonical_path(join_paths(join_paths(cwd + "/", base + "/"), path));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create a path that is relative to the given base directory
|
|
Packit Service |
7770af |
// path and base will first be resolved against cwd to make them absolute
|
|
Packit Service |
7770af |
std::string abs2rel(const std::string& path, const std::string& base, const std::string& cwd)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string abs_path = rel2abs(path, cwd);
|
|
Packit Service |
7770af |
std::string abs_base = rel2abs(base, cwd);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
size_t proto = 0;
|
|
Packit Service |
7770af |
// check if we have a protocol
|
|
Packit Service |
7770af |
if (path[proto] && Prelexer::is_alpha(path[proto])) {
|
|
Packit Service |
7770af |
// skip over all alphanumeric characters
|
|
Packit Service |
7770af |
while (path[proto] && Prelexer::is_alnum(path[proto++])) {}
|
|
Packit Service |
7770af |
// then skip over the mandatory colon
|
|
Packit Service |
7770af |
if (proto && path[proto] == ':') ++ proto;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// distinguish between windows absolute paths and valid protocols
|
|
Packit Service |
7770af |
// we assume that protocols must at least have two chars to be valid
|
|
Packit Service |
7770af |
if (proto && path[proto++] == '/' && proto > 3) return path;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
// absolute link must have a drive letter, and we know that we
|
|
Packit Service |
7770af |
// can only create relative links if both are on the same drive
|
|
Packit Service |
7770af |
if (abs_base[0] != abs_path[0]) return abs_path;
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string stripped_uri = "";
|
|
Packit Service |
7770af |
std::string stripped_base = "";
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
size_t index = 0;
|
|
Packit Service |
7770af |
size_t minSize = std::min(abs_path.size(), abs_base.size());
|
|
Packit Service |
7770af |
for (size_t i = 0; i < minSize; ++i) {
|
|
Packit Service |
7770af |
#ifdef FS_CASE_SENSITIVE
|
|
Packit Service |
7770af |
if (abs_path[i] != abs_base[i]) break;
|
|
Packit Service |
7770af |
#else
|
|
Packit Service |
7770af |
// compare the charactes in a case insensitive manner
|
|
Packit Service |
7770af |
// windows fs is only case insensitive in ascii ranges
|
|
Packit Service |
7770af |
if (tolower(abs_path[i]) != tolower(abs_base[i])) break;
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
if (abs_path[i] == '/') index = i + 1;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
for (size_t i = index; i < abs_path.size(); ++i) {
|
|
Packit Service |
7770af |
stripped_uri += abs_path[i];
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
for (size_t i = index; i < abs_base.size(); ++i) {
|
|
Packit Service |
7770af |
stripped_base += abs_base[i];
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
size_t left = 0;
|
|
Packit Service |
7770af |
size_t directories = 0;
|
|
Packit Service |
7770af |
for (size_t right = 0; right < stripped_base.size(); ++right) {
|
|
Packit Service |
7770af |
if (stripped_base[right] == '/') {
|
|
Packit Service |
7770af |
if (stripped_base.substr(left, 2) != "..") {
|
|
Packit Service |
7770af |
++directories;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (directories > 1) {
|
|
Packit Service |
7770af |
--directories;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
directories = 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
left = right + 1;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string result = "";
|
|
Packit Service |
7770af |
for (size_t i = 0; i < directories; ++i) {
|
|
Packit Service |
7770af |
result += "../";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
result += stripped_uri;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return result;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Resolution order for ambiguous imports:
|
|
Packit Service |
7770af |
// (1) filename as given
|
|
Packit Service |
7770af |
// (2) underscore + given
|
|
Packit Service |
7770af |
// (3) underscore + given + extension
|
|
Packit Service |
7770af |
// (4) given + extension
|
|
Packit Service |
7770af |
std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::string filename = join_paths(root, file);
|
|
Packit Service |
7770af |
// split the filename
|
|
Packit Service |
7770af |
std::string base(dir_name(file));
|
|
Packit Service |
7770af |
std::string name(base_name(file));
|
|
Packit Service |
7770af |
std::vector<Include> includes;
|
|
Packit Service |
7770af |
// create full path (maybe relative)
|
|
Packit Service |
7770af |
std::string rel_path(join_paths(base, name));
|
|
Packit Service |
7770af |
std::string abs_path(join_paths(root, rel_path));
|
|
Packit Service |
7770af |
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
Packit Service |
7770af |
// next test variation with underscore
|
|
Packit Service |
7770af |
rel_path = join_paths(base, "_" + name);
|
|
Packit Service |
7770af |
abs_path = join_paths(root, rel_path);
|
|
Packit Service |
7770af |
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
Packit Service |
7770af |
// next test exts plus underscore
|
|
Packit Service |
7770af |
for(auto ext : exts) {
|
|
Packit Service |
7770af |
rel_path = join_paths(base, "_" + name + ext);
|
|
Packit Service |
7770af |
abs_path = join_paths(root, rel_path);
|
|
Packit Service |
7770af |
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// next test plain name with exts
|
|
Packit Service |
7770af |
for(auto ext : exts) {
|
|
Packit Service |
7770af |
rel_path = join_paths(base, name + ext);
|
|
Packit Service |
7770af |
abs_path = join_paths(root, rel_path);
|
|
Packit Service |
7770af |
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// nothing found
|
|
Packit Service |
7770af |
return includes;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::vector<std::string> includes;
|
|
Packit Service |
7770af |
for (std::string path : paths) {
|
|
Packit Service |
7770af |
std::string abs_path(join_paths(path, file));
|
|
Packit Service |
7770af |
if (file_exists(abs_path)) includes.push_back(abs_path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return includes;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// get the last import entry to get current base directory
|
|
Packit Service |
7770af |
// struct Sass_Options* options = sass_compiler_get_options(compiler);
|
|
Packit Service |
7770af |
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
|
|
Packit Service |
7770af |
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
|
|
Packit Service |
7770af |
// create the vector with paths to lookup
|
|
Packit Service |
7770af |
std::vector<std::string> paths(1 + incs.size());
|
|
Packit Service |
7770af |
paths.push_back(dir_name(import->abs_path));
|
|
Packit Service |
7770af |
paths.insert(paths.end(), incs.begin(), incs.end());
|
|
Packit Service |
7770af |
// dispatch to find files in paths
|
|
Packit Service |
7770af |
return find_files(file, paths);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// helper function to search one file in all include paths
|
|
Packit Service |
7770af |
// this is normally not used internally by libsass (C-API sugar)
|
|
Packit Service |
7770af |
std::string find_file(const std::string& file, const std::vector<std::string> paths)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (file.empty()) return file;
|
|
Packit Service |
7770af |
auto res = find_files(file, paths);
|
|
Packit Service |
7770af |
return res.empty() ? "" : res.front();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// helper function to resolve a filename
|
|
Packit Service |
7770af |
std::string find_include(const std::string& file, const std::vector<std::string> paths)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// search in every include path for a match
|
|
Packit Service |
7770af |
for (size_t i = 0, S = paths.size(); i < S; ++i)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::vector<Include> resolved(resolve_includes(paths[i], file));
|
|
Packit Service |
7770af |
if (resolved.size()) return resolved[0].abs_path;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// nothing found
|
|
Packit Service |
7770af |
return std::string("");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// try to load the given filename
|
|
Packit Service |
7770af |
// returned memory must be freed
|
|
Packit Service |
7770af |
// will auto convert .sass files
|
|
Packit Service |
7770af |
char* read_file(const std::string& path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
#ifdef _WIN32
|
|
Packit Service |
7770af |
BYTE* pBuffer;
|
|
Packit Service |
7770af |
DWORD dwBytes;
|
|
Packit Service |
7770af |
// windows unicode filepaths are encoded in utf16
|
|
Packit Service |
7770af |
std::wstring wpath = UTF_8::convert_to_utf16(path);
|
|
Packit Service |
7770af |
HANDLE hFile = CreateFileW(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
Packit Service |
7770af |
if (hFile == INVALID_HANDLE_VALUE) return 0;
|
|
Packit Service |
7770af |
DWORD dwFileLength = GetFileSize(hFile, NULL);
|
|
Packit Service |
7770af |
if (dwFileLength == INVALID_FILE_SIZE) return 0;
|
|
Packit Service |
7770af |
// allocate an extra byte for the null char
|
|
Packit Service |
7770af |
pBuffer = (BYTE*)malloc((dwFileLength+1)*sizeof(BYTE));
|
|
Packit Service |
7770af |
ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL);
|
|
Packit Service |
7770af |
pBuffer[dwFileLength] = '\0';
|
|
Packit Service |
7770af |
CloseHandle(hFile);
|
|
Packit Service |
7770af |
// just convert from unsigned char*
|
|
Packit Service |
7770af |
char* contents = (char*) pBuffer;
|
|
Packit Service |
7770af |
#else
|
|
Packit Service |
7770af |
struct stat st;
|
|
Packit Service |
7770af |
if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0;
|
|
Packit Service |
7770af |
std::ifstream file(path.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
Packit Service |
7770af |
char* contents = 0;
|
|
Packit Service |
7770af |
if (file.is_open()) {
|
|
Packit Service |
7770af |
size_t size = file.tellg();
|
|
Packit Service |
7770af |
// allocate an extra byte for the null char
|
|
Packit Service |
7770af |
contents = (char*) malloc((size+1)*sizeof(char));
|
|
Packit Service |
7770af |
file.seekg(0, std::ios::beg);
|
|
Packit Service |
7770af |
file.read(contents, size);
|
|
Packit Service |
7770af |
contents[size] = '\0';
|
|
Packit Service |
7770af |
file.close();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
std::string extension;
|
|
Packit Service |
7770af |
if (path.length() > 5) {
|
|
Packit Service |
7770af |
extension = path.substr(path.length() - 5, 5);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
for(size_t i=0; i
|
|
Packit Service |
7770af |
extension[i] = tolower(extension[i]);
|
|
Packit Service |
7770af |
if (extension == ".sass" && contents != 0) {
|
|
Packit Service |
7770af |
char * converted = sass2scss(contents, SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
|
|
Packit Service |
7770af |
free(contents); // free the indented contents
|
|
Packit Service |
7770af |
return converted; // should be freed by caller
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
return contents;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// split a path string delimited by semicolons or colons (OS dependent)
|
|
Packit Service |
7770af |
std::vector<std::string> split_path_list(const char* str)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::vector<std::string> paths;
|
|
Packit Service |
7770af |
if (str == NULL) return paths;
|
|
Packit Service |
7770af |
// find delimiter via prelexer (return zero at end)
|
|
Packit Service |
7770af |
const char* end = Prelexer::find_first<PATH_SEP>(str);
|
|
Packit Service |
7770af |
// search until null delimiter
|
|
Packit Service |
7770af |
while (end) {
|
|
Packit Service |
7770af |
// add path from current position to delimiter
|
|
Packit Service |
7770af |
paths.push_back(std::string(str, end - str));
|
|
Packit Service |
7770af |
str = end + 1; // skip delimiter
|
|
Packit Service |
7770af |
end = Prelexer::find_first<PATH_SEP>(str);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// add path from current position to end
|
|
Packit Service |
7770af |
paths.push_back(std::string(str));
|
|
Packit Service |
7770af |
// return back
|
|
Packit Service |
7770af |
return paths;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|