Commit 4b86ac98 by Dean Mao

Merge branch 'master' of git://github.com/hcatlin/libsass

parents ba80ff04 b3e8d772
#define SASS_COLOR_NAMES_INCLUDED
namespace Sass {
const char* color_names[] =
{
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"azure",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgrey",
"darkgreen",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkslategrey",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dimgrey",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"grey",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgrey",
"lightgreen",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightslategrey",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"slategrey",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen",
// sentinel value
0
};
const double color_values[] =
{
0xf0, 0xf8, 0xff,
0xfa, 0xeb, 0xd7,
0x00, 0xff, 0xff,
0x7f, 0xff, 0xd4,
0xf0, 0xff, 0xff,
0xf5, 0xf5, 0xdc,
0xff, 0xe4, 0xc4,
0x00, 0x00, 0x00,
0xff, 0xeb, 0xcd,
0x00, 0x00, 0xff,
0x8a, 0x2b, 0xe2,
0xa5, 0x2a, 0x2a,
0xde, 0xb8, 0x87,
0x5f, 0x9e, 0xa0,
0x7f, 0xff, 0x00,
0xd2, 0x69, 0x1e,
0xff, 0x7f, 0x50,
0x64, 0x95, 0xed,
0xff, 0xf8, 0xdc,
0xdc, 0x14, 0x3c,
0x00, 0xff, 0xff,
0x00, 0x00, 0x8b,
0x00, 0x8b, 0x8b,
0xb8, 0x86, 0x0b,
0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9,
0x00, 0x64, 0x00,
0xbd, 0xb7, 0x6b,
0x8b, 0x00, 0x8b,
0x55, 0x6b, 0x2f,
0xff, 0x8c, 0x00,
0x99, 0x32, 0xcc,
0x8b, 0x00, 0x00,
0xe9, 0x96, 0x7a,
0x8f, 0xbc, 0x8f,
0x48, 0x3d, 0x8b,
0x2f, 0x4f, 0x4f,
0x2f, 0x4f, 0x4f,
0x00, 0xce, 0xd1,
0x94, 0x00, 0xd3,
0xff, 0x14, 0x93,
0x00, 0xbf, 0xff,
0x69, 0x69, 0x69,
0x69, 0x69, 0x69,
0x1e, 0x90, 0xff,
0xb2, 0x22, 0x22,
0xff, 0xfa, 0xf0,
0x22, 0x8b, 0x22,
0xff, 0x00, 0xff,
0xdc, 0xdc, 0xdc,
0xf8, 0xf8, 0xff,
0xff, 0xd7, 0x00,
0xda, 0xa5, 0x20,
0x80, 0x80, 0x80,
0x80, 0x80, 0x80,
0x00, 0x80, 0x00,
0xad, 0xff, 0x2f,
0xf0, 0xff, 0xf0,
0xff, 0x69, 0xb4,
0xcd, 0x5c, 0x5c,
0x4b, 0x00, 0x82,
0xff, 0xff, 0xf0,
0xf0, 0xe6, 0x8c,
0xe6, 0xe6, 0xfa,
0xff, 0xf0, 0xf5,
0x7c, 0xfc, 0x00,
0xff, 0xfa, 0xcd,
0xad, 0xd8, 0xe6,
0xf0, 0x80, 0x80,
0xe0, 0xff, 0xff,
0xfa, 0xfa, 0xd2,
0xd3, 0xd3, 0xd3,
0xd3, 0xd3, 0xd3,
0x90, 0xee, 0x90,
0xff, 0xb6, 0xc1,
0xff, 0xa0, 0x7a,
0x20, 0xb2, 0xaa,
0x87, 0xce, 0xfa,
0x77, 0x88, 0x99,
0x77, 0x88, 0x99,
0xb0, 0xc4, 0xde,
0xff, 0xff, 0xe0,
0x00, 0xff, 0x00,
0x32, 0xcd, 0x32,
0xfa, 0xf0, 0xe6,
0xff, 0x00, 0xff,
0x80, 0x00, 0x00,
0x66, 0xcd, 0xaa,
0x00, 0x00, 0xcd,
0xba, 0x55, 0xd3,
0x93, 0x70, 0xd8,
0x3c, 0xb3, 0x71,
0x7b, 0x68, 0xee,
0x00, 0xfa, 0x9a,
0x48, 0xd1, 0xcc,
0xc7, 0x15, 0x85,
0x19, 0x19, 0x70,
0xf5, 0xff, 0xfa,
0xff, 0xe4, 0xe1,
0xff, 0xe4, 0xb5,
0xff, 0xde, 0xad,
0x00, 0x00, 0x80,
0xfd, 0xf5, 0xe6,
0x80, 0x80, 0x00,
0x6b, 0x8e, 0x23,
0xff, 0xa5, 0x00,
0xff, 0x45, 0x00,
0xda, 0x70, 0xd6,
0xee, 0xe8, 0xaa,
0x98, 0xfb, 0x98,
0xaf, 0xee, 0xee,
0xd8, 0x70, 0x93,
0xff, 0xef, 0xd5,
0xff, 0xda, 0xb9,
0xcd, 0x85, 0x3f,
0xff, 0xc0, 0xcb,
0xdd, 0xa0, 0xdd,
0xb0, 0xe0, 0xe6,
0x80, 0x00, 0x80,
0xff, 0x00, 0x00,
0xbc, 0x8f, 0x8f,
0x41, 0x69, 0xe1,
0x8b, 0x45, 0x13,
0xfa, 0x80, 0x72,
0xf4, 0xa4, 0x60,
0x2e, 0x8b, 0x57,
0xff, 0xf5, 0xee,
0xa0, 0x52, 0x2d,
0xc0, 0xc0, 0xc0,
0x87, 0xce, 0xeb,
0x6a, 0x5a, 0xcd,
0x70, 0x80, 0x90,
0x70, 0x80, 0x90,
0xff, 0xfa, 0xfa,
0x00, 0xff, 0x7f,
0x46, 0x82, 0xb4,
0xd2, 0xb4, 0x8c,
0x00, 0x80, 0x80,
0xd8, 0xbf, 0xd8,
0xff, 0x63, 0x47,
0x40, 0xe0, 0xd0,
0xee, 0x82, 0xee,
0xf5, 0xde, 0xb3,
0xff, 0xff, 0xff,
0xf5, 0xf5, 0xf5,
0xff, 0xff, 0x00,
0x9a, 0xcd, 0x32,
// sentinel value
0xfff
};
}
\ No newline at end of file
#include "context.hpp" #include "context.hpp"
#include <cstring>
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
#include "prelexer.hpp" #include "prelexer.hpp"
#include "color_names.hpp"
using std::cerr; using std::endl; using std::cerr; using std::endl;
namespace Sass { namespace Sass {
...@@ -40,19 +42,28 @@ namespace Sass { ...@@ -40,19 +42,28 @@ namespace Sass {
// } // }
} }
Context::Context(const char* paths_str) Context::Context(const char* paths_str, const char* img_path_str)
: global_env(Environment()), : global_env(Environment()),
function_env(map<pair<string, size_t>, Function>()), function_env(map<string, Function>()),
extensions(multimap<Node, Node>()), extensions(multimap<Node, Node>()),
pending_extensions(vector<pair<Node, Node> >()), pending_extensions(vector<pair<Node, Node> >()),
source_refs(vector<char*>()), source_refs(vector<char*>()),
include_paths(vector<string>()), include_paths(vector<string>()),
color_names_to_values(map<string, Node>()),
color_values_to_names(map<Node, string>()),
new_Node(Node_Factory()), new_Node(Node_Factory()),
image_path(0),
ref_count(0), ref_count(0),
has_extensions(false) has_extensions(false)
{ {
register_functions(); register_functions();
collect_include_paths(paths_str); collect_include_paths(paths_str);
setup_color_map();
string path_string(img_path_str);
path_string = "'" + path_string + "/'";
image_path = new char[path_string.length() + 1];
std::strcpy(image_path, path_string.c_str());
} }
Context::~Context() Context::~Context()
...@@ -60,21 +71,28 @@ namespace Sass { ...@@ -60,21 +71,28 @@ namespace Sass {
for (size_t i = 0; i < source_refs.size(); ++i) { for (size_t i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i]; delete[] source_refs[i];
} }
delete[] image_path;
new_Node.free(); new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl; // cerr << "Deallocated " << i << " source string(s)." << endl;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip) inline void Context::register_function(Function_Descriptor d, Primitive ip)
{ {
Function f(d, ip); Function f(d, ip, new_Node);
function_env[pair<string, size_t>(f.name, f.parameters.size())] = f; // function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
function_env[f.name] = f;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity) inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity)
{ {
Function f(d, ip); Function f(d, ip, new_Node);
function_env[pair<string, size_t>(f.name, arity)] = f; // function_env[pair<string, size_t>(f.name, arity)] = f;
function_env[f.name] = f;
}
inline void Context::register_overload_stub(string name)
{
function_env[name] = Function(name, true);
} }
void Context::register_functions() void Context::register_functions()
...@@ -82,11 +100,13 @@ namespace Sass { ...@@ -82,11 +100,13 @@ namespace Sass {
using namespace Functions; using namespace Functions;
// RGB Functions // RGB Functions
register_function(rgb_descriptor, rgb); register_function(rgb_descriptor, rgb);
register_overload_stub("rgba");
register_function(rgba_4_descriptor, rgba_4); register_function(rgba_4_descriptor, rgba_4);
register_function(rgba_2_descriptor, rgba_2); register_function(rgba_2_descriptor, rgba_2);
register_function(red_descriptor, red); register_function(red_descriptor, red);
register_function(green_descriptor, green); register_function(green_descriptor, green);
register_function(blue_descriptor, blue); register_function(blue_descriptor, blue);
register_overload_stub("mix");
register_function(mix_2_descriptor, mix_2); register_function(mix_2_descriptor, mix_2);
register_function(mix_3_descriptor, mix_3); register_function(mix_3_descriptor, mix_3);
// HSL Functions // HSL Functions
...@@ -112,10 +132,13 @@ namespace Sass { ...@@ -112,10 +132,13 @@ namespace Sass {
// List Functions // List Functions
register_function(length_descriptor, length); register_function(length_descriptor, length);
register_function(nth_descriptor, nth); register_function(nth_descriptor, nth);
register_overload_stub("join");
register_function(join_2_descriptor, join_2); register_function(join_2_descriptor, join_2);
register_function(join_3_descriptor, join_3); register_function(join_3_descriptor, join_3);
register_overload_stub("append");
register_function(append_2_descriptor, append_2); register_function(append_2_descriptor, append_2);
register_function(append_3_descriptor, append_3); register_function(append_3_descriptor, append_3);
register_overload_stub("compact");
register_function(compact_1_descriptor, compact); register_function(compact_1_descriptor, compact);
register_function(compact_2_descriptor, compact); register_function(compact_2_descriptor, compact);
register_function(compact_3_descriptor, compact); register_function(compact_3_descriptor, compact);
...@@ -126,6 +149,8 @@ namespace Sass { ...@@ -126,6 +149,8 @@ namespace Sass {
register_function(compact_8_descriptor, compact); register_function(compact_8_descriptor, compact);
register_function(compact_9_descriptor, compact); register_function(compact_9_descriptor, compact);
register_function(compact_10_descriptor, compact); register_function(compact_10_descriptor, compact);
register_function(compact_11_descriptor, compact);
register_function(compact_12_descriptor, compact);
// Introspection Functions // Introspection Functions
register_function(type_of_descriptor, type_of); register_function(type_of_descriptor, type_of);
register_function(unit_descriptor, unit); register_function(unit_descriptor, unit);
...@@ -134,5 +159,21 @@ namespace Sass { ...@@ -134,5 +159,21 @@ namespace Sass {
// Boolean Functions // Boolean Functions
register_function(not_descriptor, not_impl); register_function(not_descriptor, not_impl);
} }
void Context::setup_color_map()
{
size_t i = 0;
while (color_names[i]) {
string name(color_names[i]);
Node value(new_Node("[COLOR TABLE]", 0,
color_values[i*3],
color_values[i*3+1],
color_values[i*3+2],
1));
color_names_to_values[name] = value;
color_values_to_names[value] = name;
++i;
}
}
} }
...@@ -42,24 +42,29 @@ namespace Sass { ...@@ -42,24 +42,29 @@ namespace Sass {
struct Context { struct Context {
Environment global_env; Environment global_env;
map<pair<string, size_t>, Function> function_env; map<string, Function> function_env;
multimap<Node, Node> extensions; multimap<Node, Node> extensions;
vector<pair<Node, Node> > pending_extensions; vector<pair<Node, Node> > pending_extensions;
vector<char*> source_refs; // all the source c-strings vector<char*> source_refs; // all the source c-strings
vector<string> include_paths; vector<string> include_paths;
map<string, Node> color_names_to_values;
map<Node, string> color_values_to_names;
Node_Factory new_Node; Node_Factory new_Node;
char* image_path;
size_t ref_count; size_t ref_count;
string sass_path; // string sass_path;
string css_path; // string css_path;
bool has_extensions; bool has_extensions;
void collect_include_paths(const char* paths_str); void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0); Context(const char* paths_str = 0, const char* img_path_str = 0);
~Context(); ~Context();
void register_function(Function_Descriptor d, Primitive ip); void register_function(Function_Descriptor d, Primitive ip);
void register_function(Function_Descriptor d, Primitive ip, size_t arity); void register_function(Function_Descriptor d, Primitive ip, size_t arity);
void register_overload_stub(string name);
void register_functions(); void register_functions();
void setup_color_map();
}; };
} }
AliceBlue #F0F8FF
AntiqueWhite #FAEBD7
Aqua #00FFFF
Aquamarine #7FFFD4
Azure #F0FFFF
Beige #F5F5DC
Bisque #FFE4C4
Black #000000
BlanchedAlmond #FFEBCD
Blue #0000FF
BlueViolet #8A2BE2
Brown #A52A2A
BurlyWood #DEB887
CadetBlue #5F9EA0
Chartreuse #7FFF00
Chocolate #D2691E
Coral #FF7F50
CornflowerBlue #6495ED
Cornsilk #FFF8DC
Crimson #DC143C
Cyan #00FFFF
DarkBlue #00008B
DarkCyan #008B8B
DarkGoldenRod #B8860B
DarkGray #A9A9A9
DarkGrey #A9A9A9
DarkGreen #006400
DarkKhaki #BDB76B
DarkMagenta #8B008B
DarkOliveGreen #556B2F
Darkorange #FF8C00
DarkOrchid #9932CC
DarkRed #8B0000
DarkSalmon #E9967A
DarkSeaGreen #8FBC8F
DarkSlateBlue #483D8B
DarkSlateGray #2F4F4F
DarkSlateGrey #2F4F4F
DarkTurquoise #00CED1
DarkViolet #9400D3
DeepPink #FF1493
DeepSkyBlue #00BFFF
DimGray #696969
DimGrey #696969
DodgerBlue #1E90FF
FireBrick #B22222
FloralWhite #FFFAF0
ForestGreen #228B22
Fuchsia #FF00FF
Gainsboro #DCDCDC
GhostWhite #F8F8FF
Gold #FFD700
GoldenRod #DAA520
Gray #808080
Grey #808080
Green #008000
GreenYellow #ADFF2F
HoneyDew #F0FFF0
HotPink #FF69B4
IndianRed #CD5C5C
Indigo #4B0082
Ivory #FFFFF0
Khaki #F0E68C
Lavender #E6E6FA
LavenderBlush #FFF0F5
LawnGreen #7CFC00
LemonChiffon #FFFACD
LightBlue #ADD8E6
LightCoral #F08080
LightCyan #E0FFFF
LightGoldenRodYellow #FAFAD2
LightGray #D3D3D3
LightGrey #D3D3D3
LightGreen #90EE90
LightPink #FFB6C1
LightSalmon #FFA07A
LightSeaGreen #20B2AA
LightSkyBlue #87CEFA
LightSlateGray #778899
LightSlateGrey #778899
LightSteelBlue #B0C4DE
LightYellow #FFFFE0
Lime #00FF00
LimeGreen #32CD32
Linen #FAF0E6
Magenta #FF00FF
Maroon #800000
MediumAquaMarine #66CDAA
MediumBlue #0000CD
MediumOrchid #BA55D3
MediumPurple #9370D8
MediumSeaGreen #3CB371
MediumSlateBlue #7B68EE
MediumSpringGreen #00FA9A
MediumTurquoise #48D1CC
MediumVioletRed #C71585
MidnightBlue #191970
MintCream #F5FFFA
MistyRose #FFE4E1
Moccasin #FFE4B5
NavajoWhite #FFDEAD
Navy #000080
OldLace #FDF5E6
Olive #808000
OliveDrab #6B8E23
Orange #FFA500
OrangeRed #FF4500
Orchid #DA70D6
PaleGoldenRod #EEE8AA
PaleGreen #98FB98
PaleTurquoise #AFEEEE
PaleVioletRed #D87093
PapayaWhip #FFEFD5
PeachPuff #FFDAB9
Peru #CD853F
Pink #FFC0CB
Plum #DDA0DD
PowderBlue #B0E0E6
Purple #800080
Red #FF0000
RosyBrown #BC8F8F
RoyalBlue #4169E1
SaddleBrown #8B4513
Salmon #FA8072
SandyBrown #F4A460
SeaGreen #2E8B57
SeaShell #FFF5EE
Sienna #A0522D
Silver #C0C0C0
SkyBlue #87CEEB
SlateBlue #6A5ACD
SlateGray #708090
SlateGrey #708090
Snow #FFFAFA
SpringGreen #00FF7F
SteelBlue #4682B4
Tan #D2B48C
Teal #008080
Thistle #D8BFD8
Tomato #FF6347
Turquoise #40E0D0
Violet #EE82EE
Wheat #F5DEB3
White #FFFFFF
WhiteSmoke #F5F5F5
Yellow #FFFF00
YellowGreen #9ACD32
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "error.hpp" #include "error.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <sys/stat.h>
namespace Sass { namespace Sass {
...@@ -30,28 +31,28 @@ namespace Sass { ...@@ -30,28 +31,28 @@ namespace Sass {
{ {
std::FILE *f; std::FILE *f;
const char* path_str = path.c_str(); const char* path_str = path.c_str();
f = std::fopen(path_str, "rb"); struct stat st;
if (!f) { string tmp;
string path_with_extension(path + ".scss"); if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
f = std::fopen(path_with_extension.c_str(), "rb"); tmp = path + ".scss";
if (!f) { path_str = tmp.c_str();
const char* file_name_str = Prelexer::folders(path_str); if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
string path_with_underscore(Token::make(path_str, file_name_str).to_string() + const char *full_path_str = path.c_str();
"_" + const char *file_name_str = Prelexer::folders(full_path_str);
Token::make(file_name_str).to_string()); tmp = Token::make(full_path_str, file_name_str).to_string() +
f = std::fopen(path_with_underscore.c_str(), "rb"); "_" +
if (!f) { string(file_name_str);
string path_with_underscore_and_extension(path_with_underscore + ".scss"); path_str = tmp.c_str();
f = std::fopen(path_with_underscore_and_extension.c_str(), "rb"); if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
if (!f) throw path; tmp = tmp + ".scss";
path_str = tmp.c_str();
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode))
throw path;
}
} }
}
} }
if (std::fseek(f, 0, SEEK_END)) throw path; f = std::fopen(path_str, "rb");
int status = std::ftell(f); size_t len = st.st_size;
if (status < 0) throw path;
size_t len = status;
std::rewind(f);
char* source = new char[len + 1]; char* source = new char[len + 1];
size_t bytes_read = std::fread(source, sizeof(char), len, f); size_t bytes_read = std::fread(source, sizeof(char), len, f);
if (bytes_read != len) { if (bytes_read != len) {
...@@ -61,6 +62,8 @@ namespace Sass { ...@@ -61,6 +62,8 @@ namespace Sass {
source[len] = '\0'; source[len] = '\0';
char* end = source + len; char* end = source + len;
if (std::fclose(f)) throw path; if (std::fclose(f)) throw path;
const char *file_name_str = Prelexer::folders(path_str);
string include_path(path_str, file_name_str - path_str);
Document doc(ctx); Document doc(ctx);
doc.path = path; doc.path = path;
...@@ -72,6 +75,9 @@ namespace Sass { ...@@ -72,6 +75,9 @@ namespace Sass {
doc.end = end; doc.end = end;
doc.position = source; doc.position = source;
doc.context.source_refs.push_back(source); doc.context.source_refs.push_back(source);
if (!include_path.empty()) {
doc.context.include_paths.push_back(include_path);
}
return doc; return doc;
} }
...@@ -136,7 +142,8 @@ namespace Sass { ...@@ -136,7 +142,8 @@ namespace Sass {
// trim trailing whitespace // trim trailing whitespace
if (!retval.empty()) { if (!retval.empty()) {
size_t newlines = 0; size_t newlines = 0;
for (size_t i = retval.length() - 1; i >= 0; --i) { size_t i = retval.length();
while (i--) {
if (retval[i] == '\n') { if (retval[i] == '\n') {
++newlines; ++newlines;
continue; continue;
......
...@@ -101,17 +101,16 @@ namespace Sass { ...@@ -101,17 +101,16 @@ namespace Sass {
if (!lex< string_constant >()) throw_syntax_error("@import directive requires a url or quoted path"); if (!lex< string_constant >()) throw_syntax_error("@import directive requires a url or quoted path");
// TO DO: BETTER PATH HANDLING // TO DO: BETTER PATH HANDLING
string import_path(lexed.unquote()); string import_path(lexed.unquote());
const char* curr_path_start = path.c_str(); for (vector<string>::iterator path = context.include_paths.begin(); path < context.include_paths.end(); ++path) {
const char* curr_path_end = folders(curr_path_start); try {
string current_path(curr_path_start, curr_path_end - curr_path_start); Document importee(Document::make_from_file(context, *path + import_path));
try { importee.parse_scss();
Document importee(Document::make_from_file(context, current_path + import_path)); return importee.root;
importee.parse_scss(); }
return importee.root; catch (string& path) {
} }
catch (string& path) {
throw_read_error("error reading file \"" + path + "\"");
} }
throw_read_error("error reading file \"" + import_path + "\"");
// unreached statement // unreached statement
return Node(); return Node();
} }
...@@ -523,6 +522,7 @@ namespace Sass { ...@@ -523,6 +522,7 @@ namespace Sass {
else if (lex < return_directive >()) { else if (lex < return_directive >()) {
Node ret_expr(context.new_Node(Node::return_directive, path, line, 1)); Node ret_expr(context.new_Node(Node::return_directive, path, line, 1));
ret_expr << parse_list(); ret_expr << parse_list();
ret_expr.should_eval() = true;
block << ret_expr; block << ret_expr;
semicolon = true; semicolon = true;
} }
...@@ -813,14 +813,26 @@ namespace Sass { ...@@ -813,14 +813,26 @@ namespace Sass {
const char* value = position; const char* value = position;
const char* rparen = find_first< exactly<')'> >(position); const char* rparen = find_first< exactly<')'> >(position);
if (!rparen) throw_syntax_error("URI is missing ')'"); if (!rparen) throw_syntax_error("URI is missing ')'");
Token contents(Token::make(value, rparen)); Token content_tok(Token::make(value, rparen));
Node content_node(context.new_Node(Node::string_constant, path, line, content_tok));
// lex< string_constant >(); // lex< string_constant >();
Node result(context.new_Node(Node::uri, path, line, contents)); Node result(context.new_Node(Node::uri, path, line, 1));
result << content_node;
position = rparen; position = rparen;
lex< exactly<')'> >(); lex< exactly<')'> >();
return result; return result;
} }
if (lex< image_url_prefix >())
{
Node url(parse_value());
if (!lex< exactly<')'> >()) throw_syntax_error("call to image-url is missing ')'");
Node the_call(context.new_Node(Node::image_url, path, line, 1));
the_call << url;
the_call.should_eval() = true;
return the_call;
}
if (peek< functional >()) if (peek< functional >())
{ return parse_function_call(); } { return parse_function_call(); }
...@@ -1196,4 +1208,4 @@ namespace Sass { ...@@ -1196,4 +1208,4 @@ namespace Sass {
return result; return result;
} }
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "eval_apply.hpp" #include "eval_apply.hpp"
#include "document.hpp" #include "document.hpp"
#include "error.hpp" #include "error.hpp"
#include <cctype>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <cstdlib> #include <cstdlib>
...@@ -19,7 +20,7 @@ namespace Sass { ...@@ -19,7 +20,7 @@ namespace Sass {
// Evaluate the parse tree in-place (mostly). Most nodes will be left alone. // Evaluate the parse tree in-place (mostly). Most nodes will be left alone.
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx) Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name)
{ {
switch (expr.type()) switch (expr.type())
{ {
...@@ -29,7 +30,7 @@ namespace Sass { ...@@ -29,7 +30,7 @@ namespace Sass {
} break; } break;
case Node::function: { case Node::function: {
f_env[pair<string, size_t>(expr[0].to_string(), expr[1].size())] = Function(expr); f_env[expr[0].to_string()] = Function(expr);
return expr; return expr;
} break; } break;
...@@ -287,13 +288,25 @@ namespace Sass { ...@@ -287,13 +288,25 @@ namespace Sass {
if (!env.query(expr.token())) throw_eval_error("reference to unbound variable " + expr.token().to_string(), expr.path(), expr.line()); if (!env.query(expr.token())) throw_eval_error("reference to unbound variable " + expr.token().to_string(), expr.path(), expr.line());
return env[expr.token()]; return env[expr.token()];
} break; } break;
case Node::image_url: {
Node base(eval(expr[0], prefix, env, f_env, new_Node, ctx));
Node prefix(new_Node(Node::identifier, base.path(), base.line(), Token::make(ctx.image_path)));
Node fullpath(new_Node(Node::concatenation, base.path(), base.line(), 2));
Node url(new_Node(Node::uri, base.path(), base.line(), 1));
fullpath << prefix << base;
url << fullpath;
return url;
} break;
case Node::function_call: { case Node::function_call: {
// TO DO: default-constructed Function should be a generic callback (maybe) // TO DO: default-constructed Function should be a generic callback (maybe)
// eval the function name in case it's interpolated // eval the function name in case it's interpolated
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx); expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx, true);
pair<string, size_t> sig(expr[0].to_string(), expr[1].size()); string name(expr[0].to_string());
if (!f_env.count(sig)) { if (!f_env.count(name)) {
// no definition available; just pass it through (with evaluated args)
Node args(expr[1]); Node args(expr[1]);
for (size_t i = 0, S = args.size(); i < S; ++i) { for (size_t i = 0, S = args.size(); i < S; ++i) {
args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx); args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
...@@ -301,7 +314,16 @@ namespace Sass { ...@@ -301,7 +314,16 @@ namespace Sass {
return expr; return expr;
} }
else { else {
return apply_function(f_env[sig], expr[1], prefix, env, f_env, new_Node, ctx); // check to see if the function is primitive/built-in
Function f(f_env[name]);
if (f.overloaded) {
stringstream s;
s << name << " " << expr[1].size();
string resolved_name(s.str());
if (!f_env.count(resolved_name)) throw_eval_error("wrong number of arguments to " + name, expr.path(), expr.line());
f = f_env[resolved_name];
}
return apply_function(f, expr[1], prefix, env, f_env, new_Node, ctx);
} }
} break; } break;
...@@ -326,6 +348,17 @@ namespace Sass { ...@@ -326,6 +348,17 @@ namespace Sass {
return expr; return expr;
} }
} break; } break;
case Node::identifier: {
string id_str(expr.to_string());
to_lowercase(id_str);
if (!function_name && ctx.color_names_to_values.count(id_str)) {
return ctx.color_names_to_values[id_str];
}
else {
return expr;
}
} break;
case Node::string_schema: case Node::string_schema:
case Node::value_schema: case Node::value_schema:
...@@ -582,7 +615,7 @@ namespace Sass { ...@@ -582,7 +615,7 @@ namespace Sass {
// environment to the current one, then copy the body and eval in the new // environment to the current one, then copy the body and eval in the new
// environment. // environment.
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope) Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope)
{ {
Node params(mixin[1]); Node params(mixin[1]);
Node body(new_Node(mixin[2])); // clone the body Node body(new_Node(mixin[2])); // clone the body
...@@ -650,7 +683,7 @@ namespace Sass { ...@@ -650,7 +683,7 @@ namespace Sass {
// Apply a function -- bind the arguments and pass them to the underlying // Apply a function -- bind the arguments and pass them to the underlying
// primitive function implementation, then return its value. // primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx) Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{ {
if (f.primitive) { if (f.primitive) {
map<Token, Node> bindings; map<Token, Node> bindings;
...@@ -663,7 +696,7 @@ namespace Sass { ...@@ -663,7 +696,7 @@ namespace Sass {
} }
else { else {
// TO DO: ensure (j < f.parameters.size()) // TO DO: ensure (j < f.parameters.size())
bindings[f.parameters[j]] = eval(args[i], prefix, env, f_env, new_Node, ctx); bindings[f.parameters[j].token()] = eval(args[i], prefix, env, f_env, new_Node, ctx);
++j; ++j;
} }
} }
...@@ -827,7 +860,13 @@ namespace Sass { ...@@ -827,7 +860,13 @@ namespace Sass {
} break; } break;
case Node::return_directive: { case Node::return_directive: {
return eval(stm[0], Node(), bindings, ctx.function_env, new_Node, ctx); Node retval(eval(stm[0], Node(), bindings, ctx.function_env, new_Node, ctx));
if (retval.type() == Node::comma_list || retval.type() == Node::space_list) {
for (size_t i = 0, S = retval.size(); i < S; ++i) {
retval[i] = eval(retval[i], Node(), bindings, ctx.function_env, new_Node, ctx);
}
}
return retval;
} break; } break;
default: { default: {
...@@ -1177,11 +1216,9 @@ namespace Sass { ...@@ -1177,11 +1216,9 @@ namespace Sass {
default: { default: {
// something // something
cerr << "pux!" << endl;
} break; } break;
} }
} }
cerr << "blux!" << endl;
return Node(); return Node();
} }
...@@ -1243,4 +1280,7 @@ namespace Sass { ...@@ -1243,4 +1280,7 @@ namespace Sass {
Node selector_butlast(Node sel, Node_Factory& new_Node) Node selector_butlast(Node sel, Node_Factory& new_Node)
{ return selector_but(sel, new_Node, 0, 1); } { return selector_but(sel, new_Node, 0, 1); }
void to_lowercase(string& s)
{ for (size_t i = 0, L = s.length(); i < L; ++i) s[i] = tolower(s[i]); }
} }
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx); Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false);
Node function_eval(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false); Node function_eval(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false);
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node); Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs); double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false); Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx); Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx);
Node expand_selector(Node sel, Node pre, Node_Factory& new_Node); Node expand_selector(Node sel, Node pre, Node_Factory& new_Node);
Node expand_backref(Node sel, Node pre); Node expand_backref(Node sel, Node pre);
void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&); void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&);
...@@ -29,4 +29,5 @@ namespace Sass { ...@@ -29,4 +29,5 @@ namespace Sass {
Node selector_butfirst(Node sel, Node_Factory& new_Node); Node selector_butfirst(Node sel, Node_Factory& new_Node);
Node selector_butlast(Node sel, Node_Factory& new_Node); Node selector_butlast(Node sel, Node_Factory& new_Node);
void to_lowercase(string& s);
} }
\ No newline at end of file
...@@ -128,6 +128,7 @@ namespace Sass { ...@@ -128,6 +128,7 @@ namespace Sass {
value, value,
identifier, identifier,
uri, uri,
image_url,
textual_percentage, textual_percentage,
textual_dimension, textual_dimension,
textual_number, textual_number,
......
...@@ -268,7 +268,8 @@ namespace Sass { ...@@ -268,7 +268,8 @@ namespace Sass {
case uri: { case uri: {
string result("url("); string result("url(");
result += token().to_string(); // result += token().to_string();
result += at(0).to_string();
result += ")"; result += ")";
return result; return result;
} break; } break;
......
...@@ -278,6 +278,11 @@ namespace Sass { ...@@ -278,6 +278,11 @@ namespace Sass {
optional<spaces>, optional<spaces>,
exactly<')'> >(src); exactly<')'> >(src);
} }
// Match SCSS image-url function
extern const char image_url_kwd[] = "image-url(";
const char* image_url_prefix(const char* src) {
return exactly<image_url_kwd>(src);
}
// Match CSS "!important" keyword. // Match CSS "!important" keyword.
extern const char important_kwd[] = "important"; extern const char important_kwd[] = "important";
const char* important(const char* src) { const char* important(const char* src) {
......
...@@ -354,6 +354,8 @@ namespace Sass { ...@@ -354,6 +354,8 @@ namespace Sass {
// Match CSS uri specifiers. // Match CSS uri specifiers.
const char* uri_prefix(const char* src); const char* uri_prefix(const char* src);
const char* uri(const char* src); const char* uri(const char* src);
// Match SCSS image-url function.
const char* image_url_prefix(const char* src);
// Match CSS "!important" keyword. // Match CSS "!important" keyword.
const char* important(const char* src); const char* important(const char* src);
// Match Sass "!default" keyword. // Match Sass "!default" keyword.
......
...@@ -13,7 +13,7 @@ extern "C" { ...@@ -13,7 +13,7 @@ extern "C" {
using namespace std; using namespace std;
sass_context* sass_new_context() sass_context* sass_new_context()
{ return (sass_context*) calloc(1, sizeof(sass_context)); } { return (sass_context*) calloc(1, sizeof(sass_context)); }
void sass_free_context(sass_context* ctx) void sass_free_context(sass_context* ctx)
{ {
...@@ -24,7 +24,7 @@ extern "C" { ...@@ -24,7 +24,7 @@ extern "C" {
} }
sass_file_context* sass_new_file_context() sass_file_context* sass_new_file_context()
{ return (sass_file_context*) calloc(1, sizeof(sass_file_context)); } { return (sass_file_context*) calloc(1, sizeof(sass_file_context)); }
void sass_free_file_context(sass_file_context* ctx) void sass_free_file_context(sass_file_context* ctx)
{ {
...@@ -58,7 +58,8 @@ extern "C" { ...@@ -58,7 +58,8 @@ extern "C" {
{ {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// cpp_ctx.image_path = c_ctx->options.image_path;
// Document doc(0, c_ctx->input_string, cpp_ctx); // Document doc(0, c_ctx->input_string, cpp_ctx);
Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string)); Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string));
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
...@@ -93,8 +94,11 @@ extern "C" { ...@@ -93,8 +94,11 @@ extern "C" {
{ {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// Document doc(c_ctx->input_path, 0, cpp_ctx); // Document doc(c_ctx->input_path, 0, cpp_ctx);
// string path_string(c_ctx->options.image_path);
// path_string = "'" + path_string + "/";
// cpp_ctx.image_path = c_ctx->options.image_path;
Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path))); Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path)));
// cerr << "MADE A DOC AND CONTEXT OBJ" << endl; // cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
// cerr << "REGISTRY: " << doc.context.registry.size() << endl; // cerr << "REGISTRY: " << doc.context.registry.size() << endl;
......
...@@ -12,6 +12,7 @@ extern "C" { ...@@ -12,6 +12,7 @@ extern "C" {
struct sass_options { struct sass_options {
int output_style; int output_style;
char* include_paths; char* include_paths;
char* image_path;
}; };
struct sass_context { struct sass_context {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment