49#include    <snapdev/poison.h> 
  120    f_paths.push_back(path);
 
 
  131    f_parents.push_back(parent);
 
 
  136    f_parents.pop_back();
 
 
  141    return f_parents.empty();
 
 
  146    if(f_parents.size() < 2)
 
  148        throw csspp_exception_logic(
"compiler.cpp:compiler::compiler_state_t::get_current_parent(): no previous parents available."); 
 
  152    return f_parents[f_parents.size() - 2];
 
 
  160    std::string 
const variable_name(name->get_string());
 
  167        size_t pos(f_parents.size());
 
  175                s->set_variable(variable_name, v);
 
  182    f_root->set_variable(variable_name, v);
 
 
  189        size_t pos(f_parents.size());
 
  194            switch(s->get_type())
 
  214    return f_root->get_variable(variable_name);
 
 
  230    || value->size() != 2)
 
  232        throw csspp_exception_logic(
"compiler.cpp:compiler::compiler_state_t::execute_user_function(): all functions must be two sub-values in a LIST, the first item being the variable."); 
 
  252        throw csspp_exception_logic(
"compiler.cpp:compiler::compiler_state_t::execute_user_function(): @mixin function is not defined inside a {}-block."); 
 
  256    root->copy_variable(f_root);
 
  258    size_t max_val_children(val->size());
 
  259    for(
size_t j(0); j < max_val_children; ++j)
 
  261        root->add_child(val->get_child(j)->clone());
 
  264    size_t const max_children(var->size());
 
  265    size_t const max_input(func->size());
 
  266    for(
size_t i(0); i < max_children; ++i)
 
  272            throw csspp_exception_logic(
"compiler.cpp:compiler::compiler_state_t::execute_user_function(): FUNCTION children are not all ARG nodes."); 
 
  276            throw csspp_exception_logic(
"compiler.cpp:compiler::compiler_state_t::execute_user_function(): ARG is empty."); 
 
  297                default_param->remove_child(0);  
 
  298                if(default_param->size() == 1)
 
  300                    default_param = default_param->get_child(0);
 
  305                    value_list->take_over_children_of(default_param);
 
  306                    default_param = value_list;
 
  309                param_value->add_child(arg_name);
 
  310                param_value->add_child(default_param);
 
  311                root->set_variable(arg_name->get_string(), param_value);
 
  317                        << 
"missing function variable named \"" 
  318                        << arg_name->get_string()
 
  319                        << 
"\" when calling " 
  320                        << func->get_string()
 
  332                throw csspp_exception_logic(
"compiler.cpp:compiler::replace_variable(): user parameter is not an ARG."); 
 
  334            if(user_param->size() == 1)
 
  336                user_param = user_param->get_child(0);
 
  343                list->take_over_children_of(user_param);
 
  347            param_value->add_child(arg_name);
 
  348            param_value->add_child(user_param->clone());
 
  349            root->set_variable(arg_name->get_string(), param_value);
 
 
  365    f_empty_on_undefined_variable = empty_on_undefined_variable;
 
 
  370    return f_empty_on_undefined_variable;
 
 
  376    if(script_name.empty())
 
  378        return std::string();
 
  382    if(script_name[0] == 
'/')
 
  384        if(access(script_name.c_str(), R_OK) == 0)
 
  389        return std::string();
 
  396        f_paths.push_back(
"/usr/lib/csspp/scripts");
 
  400    for(
auto it : f_paths)
 
  402        std::string 
const name(it == 
"" ? script_name : it + 
"/" + script_name);
 
  403        if(access(name.c_str(), R_OK) == 0)
 
  410    return std::string();
 
 
  440        throw csspp_exception_logic(
"compiler.cpp: compiler::set_date_time_variables(): function called too soon, root not set yet.");
 
  447    strftime(buf, 
sizeof(buf), 
"%m/%d/%Y%T", &t);
 
  453    var->set_string(
"_csspp_usdate");
 
  455    arg->set_string(std::string(buf, 10));
 
  460    var->set_string(
"_csspp_month");
 
  462    arg->set_string(std::string(buf, 2));
 
  467    var->set_string(
"_csspp_day");
 
  469    arg->set_string(std::string(buf + 3, 2));
 
  474    var->set_string(
"_csspp_year");
 
  476    arg->set_string(std::string(buf + 6, 4));
 
  481    var->set_string(
"_csspp_time");
 
  483    arg->set_string(std::string(buf + 10, 8));
 
  488    var->set_string(
"_csspp_hour");
 
  490    arg->set_string(std::string(buf + 10, 2));
 
  495    var->set_string(
"_csspp_minute");
 
  497    arg->set_string(std::string(buf + 13, 2));
 
  502    var->set_string(
"_csspp_second");
 
  504    arg->set_string(std::string(buf + 16, 2));
 
 
  532        throw csspp_exception_logic(
"compiler.cpp: compiler::compile(): compile() called without a root node pointer, call set_root() first."); 
 
  552        throw csspp_exception_logic(
"compiler.cpp: the stack of parents must always be empty before mark_selectors() returns."); 
 
  558        throw csspp_exception_logic(
"compiler.cpp: the stack of parents must always be empty before replace_variables() returns."); 
 
  564        throw csspp_exception_logic(
"compiler.cpp: the stack of parents must always be empty before compile() returns"); 
 
  570        throw csspp_exception_logic(
"compiler.cpp: the stack of parents must always be empty before remove_empty_rules() returns"); 
 
  576        throw csspp_exception_logic(
"compiler.cpp: the stack of parents must always be empty before expand_nested_components() returns"); 
 
 
  587        header->set_string(
"import");
 
  589        header_string->set_string(
"system/init.scss");
 
  590        header->add_child(header_string);
 
  599        footer->set_string(
"import");
 
  601        footer_string->set_string(
"system/close.scss");
 
  602        footer->add_child(footer_string);
 
  611        no_logo->set_string(
"_csspp_no_logo");
 
 
  622    switch(n->get_type())
 
  637                && n->get_child(idx) == child)
 
  669            std::stringstream ss;
 
  670            ss << 
"unexpected token (type: " << n->get_type() << 
") in compile().";
 
 
  722        size_t pos(parent->child_position(n));
 
  723        parent->remove_child(pos);
 
  724        parent->insert_child(pos, n->get_child(0));
 
  734        throw csspp_exception_logic(
"compiler.cpp: found an ARG as the first child of COMPONENT_VALUE, compile_component_value() called twice on the same object?"); 
 
  737    size_t const max_children(n->size());
 
  739    for(
size_t idx(0); idx < max_children; ++idx)
 
  747    if(count_cv == max_children)
 
  755        size_t pos(parent->child_position(n));
 
  756        parent->remove_child(pos);
 
  757        for(
size_t idx(0); idx < max_children; ++idx, ++pos)
 
  759            parent->insert_child(pos, n->get_child(idx));
 
  765    else if(count_cv != 0)
 
  767        std::cerr << 
"Invalid node:\n" << *n;                                                           
 
  791        throw csspp_exception_logic(
"compiler.cpp: somehow a variable definition was found while compiling (1)."); 
 
  813        throw csspp_exception_logic(
"compiler.cpp: somehow a variable definition was found while compiling (1)."); 
 
 
  830                << 
"a qualified rule without selectors is not valid." 
  845    if(brackets->empty())
 
  858    for(
size_t b(0); b < brackets->size();)
 
  864            for(
size_t idx(0); idx < child->size();)
 
  869                if(idx < child->size()
 
  870                && item == child->get_child(idx))
 
  880        if(b < brackets->size()
 
  881        && child == brackets->get_child(b))
 
 
  906                << 
"somehow a declaration list is missing a field name or ':'." 
  925            identifier = n->get_child(0);
 
  927                    << 
"the '[*|.|!]<field-name>: ...' syntax is not allowed in csspp, we offer other ways to control field names per browser and do not allow such tricks." 
  939                    << 
"the '#<field-name>: ...' syntax is not allowed in csspp, we offer other ways to control field names per browser and do not allow such tricks." 
  945                    << 
"expected an identifier to start a declaration value; got a: " << identifier->get_type() << 
" instead." 
  956        next = n->get_child(1);
 
  963                << 
"expected a ':' after the identifier of this declaration value; got a: " << n->get_type() << 
" instead." 
  972                << 
"somehow a declaration list is missing fields, this happens if you used an invalid variable." 
  988                << 
"somehow a declaration list is missing fields, this happens if you used an invalid variable." 
  995    declaration->set_string(identifier->get_string());
 
  999    size_t const max_children(n->size());
 
 1000    for(
size_t i(1); i < max_children; ++i)
 
 1004        declaration->add_child(n->get_child(1));
 
 1017        throw csspp_exception_logic(
"compiler.cpp: got a node which was not of type COMPONENT_VALUE to replace with the DECLARATION."); 
 
 1026    if(compile_declaration_items)
 
 1028        for(
size_t i(0); i < declaration->size(); ++i)
 
 1031            switch(item->get_type())
 
 1038                compile_declaration_items = 
false;
 
 1048    if(compile_declaration_items
 
 1049    && !declaration->empty())
 
 1055                && (child->get_string() == 
"alpha" || child->get_string() == 
"chroma" || child->get_string() == 
"gray" || child->get_string() == 
"opacity")
 
 1056                && (declaration->get_string() == 
"filter" || declaration->get_string() == 
"-filter"))
 
 1059                && child->get_string() == 
"progid" 
 1060                && (declaration->get_string() == 
"filter" || declaration->get_string() == 
"-filter"))
 
 1074                    << 
"the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers." 
 1083            declaration_name->set_string(declaration->get_string());
 
 1100            args_expr.set_variable_handler(&
f_state);
 
 1101            args_expr.compile_args(divide_font_metrics);
 
 
 1111    for(
size_t i(0); i < declaration->size(); ++i)
 
 1115        switch(item->get_type())
 
 1126            for(
size_t j(0); j < item->size();)
 
 1145                    std::stringstream errmsg;                               
 
 1146                    errmsg << 
"compiler.cpp: found unexpected node type "    
 1147                           << component->get_type()                         
 
 1148                           << 
", expected a LIST.";                         
 
 1152                && component == item->get_child(j))
 
 
 1175    std::string 
const at(n->get_string());
 
 1182        parent->remove_child(n);
 
 1185                << (expr ? expr->to_string(0) : std::string(
"@error reached"))
 
 1192        parent->remove_child(n);
 
 1195                << (expr ? expr->to_string(0) : std::string(
"@warning reached"))
 
 1203        parent->remove_child(n);
 
 1206                << (expr ? expr->to_string(0) : std::string(
"@message reached"))
 
 1213        parent->remove_child(n);
 
 1216                << (expr ? expr->to_string(0) : std::string(
"@debug reached"))
 
 1226        parent->remove_child(n);
 
 1232                    << 
"the @charset is expected to be followed by exactly one string." 
 1237        std::string charset(n->get_child(0)->get_string());
 
 1238        while(!charset.empty() && std::isspace(charset[0]))
 
 1240            charset.erase(charset.begin(), charset.begin() + 1);
 
 1242        while(!charset.empty() && std::isspace(charset.back()))
 
 1244            charset.erase(charset.end() - 1, charset.end());
 
 1246        for(
auto & c : charset)
 
 1248            c = std::tolower(c);
 
 1250        if(charset != 
"utf-8")
 
 1253                    << 
"we only support @charset \"utf-8\";, any other encoding is refused." 
 1265    || at == 
"supports")
 
 1277                for(
size_t idx(0); idx < last->size();)
 
 1293                    if(idx < last->size()
 
 1294                    && child == last->get_child(idx))
 
 1304    if(at == 
"font-face" 
 1307    || at == 
"-ms-viewport")
 
 1314                if(last->size() > 0)
 
 1319                        list = last->get_child(0);
 
 1324                    for(
size_t idx(0); idx < list->size();)
 
 1332                            if(idx < list->size()
 
 1333                            && child == list->get_child(idx))
 
 1354                    << 
"@return must be followed by a valid expression." 
 1377    if(at == 
"keyframes" 
 1378    || at == 
"-o-keyframes" 
 1379    || at == 
"-webkit-keyframes")
 
 1468                    << 
"@keyframes must be followed by an identifier and '{' ... '}'." 
 1480                    << 
"@keyframes must first be followed by an identifier." 
 1490                    << 
"@keyframes must be followed by an identifier and '{' ... '}'." 
 1499        size_t const max_positions(positions->size());
 
 1500        for(
size_t idx(0); idx < max_positions; ++idx)
 
 1507                        << 
"@keyframes is only expecting component values as child entries." 
 1511            if(component_value->size() != 2)
 
 1515                        << 
"@keyframes is expected to be followed by an identifier or a percent number and a '{'." 
 1524                        << 
"@keyframes is expected to be followed by an identifier or a percent number and a '{'." 
 1528            if(components->size() != 1)
 
 1532                        << 
"@keyframes is expected to be followed by an identifier or a percent number and a '{'." 
 1542                sub_list->add_child(component_list);
 
 1543                component_list = sub_list;
 
 1549                        << 
"@keyframes is expected to be followed by an identifier or a percent number and a list of component values '{' ... '}'." 
 1559                std::string 
const l(
position->get_string());
 
 1572                            << 
"@keyframes position can be \"from\" or \"to\", other identifiers are not supported." 
 1579                p = 
position->get_decimal_number();
 
 1580                if(p < 0.0 || p > 1.0)
 
 1584                            << 
"@keyframes position must be a percentage between 0% and 100%." 
 1593                        << 
"@keyframes positions must either be \"from\" or \"to\" or a percent number between 0% and 100%." 
 1603            frame->set_decimal_number(p);
 
 1604            frame->take_over_children_of(component_list);
 
 1606            list->add_child(frame);
 
 1617        n->take_over_children_of(list);
 
 1621        n->insert_child(0, identifier);
 
 
 1631    static_cast<void>(
import);
 
 1656        std::string script_name(expr->get_string());
 
 1661            if(script_name.substr(0, 7) == 
"file://")
 
 1663                script_name = script_name.substr(7);
 
 1664                if(script_name.empty()
 
 1665                || script_name[0] != 
'/')
 
 1667                    script_name = 
"/" + script_name;
 
 1680            std::string::size_type pos(script_name.find(
':'));
 
 1681            if(pos != std::string::npos
 
 1682            && script_name.substr(pos, 3) == 
"://")
 
 1684                std::string 
const protocol(script_name.substr(0, pos));
 
 1685                auto s(protocol.c_str());
 
 1686                for(; *s != 
'\0'; ++s)
 
 1688                    if((*s < 
'a' || *s > 
'z')
 
 1689                    && (*s < 
'A' || *s > 
'Z'))
 
 1696                    if(protocol != 
"file")
 
 1701                    script_name = script_name.substr(7);
 
 1702                    if(script_name.empty()
 
 1703                    || script_name[0] != 
'/')
 
 1705                        script_name = 
"/" + script_name;
 
 1714        std::string filename(
find_file(script_name));
 
 1715        if(filename.empty() && script_name.length() > 5)
 
 1717            if(script_name.substr(script_name.size() - 5) != 
".scss")
 
 1720                filename = 
find_file(script_name + 
".scss");
 
 1725        if(!filename.empty())
 
 1732            parent->remove_child(idx);
 
 1747                        << 
"validation script \""            
 1749                        << 
"\" could not be opened."         
 1767                    size_t const max_results(list->size());
 
 1768                    for(
size_t i(0), j(idx); i < max_results; ++i, ++j)
 
 1770                        parent->insert_child(j, list->get_child(i));
 
 1778        else if(script_name.empty())
 
 1781                    << 
"@import \"\"; and @import url(); are not valid." 
 1789                    << 
"); left alone by the CSS Preprocessor, no matching file found." 
 1797                    << 
"\"; left alone by the CSS Preprocessor, no matching file found." 
 
 1810                << 
"a @mixin definition expects exactly two parameters: an identifier or function and a {}-block." 
 1819                << 
"a @mixin definition expects a {}-block as its second parameter." 
 1832                << 
"a @mixin must use an IDENTIFIER or FUNCTION and no a VARIABLE or VARIABLE_FUNCTION." 
 1862                << 
"a @mixin expects either an IDENTIFIER or a FUNCTION as its first parameter." 
 
 1871    switch(n->get_type())
 
 1895                n->get_last_child()->set_boolean(
true); 
 
 1899            for(
size_t idx(0); idx < n->size(); ++idx)
 
 
 1919    switch(n->get_type())
 
 1924        && n->get_last_child()->empty())
 
 1940        for(
size_t idx(0); idx < n->size();)
 
 1948            && child == n->get_child(idx))
 
 
 1966    switch(n->get_type())
 
 1975#if __cplusplus >= 201700 
 1994            size_t idx(is_variable_set
 
 1999            while(idx < n->size())
 
 2004                    n->remove_child(idx);
 
 2016                    n->remove_child(idx);
 
 2026                    switch(child->get_type())
 
 2041                        && child == n->get_child(idx))
 
 
 2084    std::string 
const & variable_name(n->get_string());
 
 2094                    << 
"variable named \"" 
 2104    || value->size() != 2)
 
 2106        throw csspp_exception_logic(
"compiler.cpp:compiler::replace_variable(): all variable values must be two sub-values in a LIST, the first item being the variable."); 
 
 2119                    << 
"variable named \"" 
 2121                    << 
"\" is not a function and it cannot be referenced as such." 
 2129        root->add_child(val->clone());
 
 2130        size_t const max_children(var->size());
 
 2131        size_t const max_input(n->size());
 
 2132        for(
size_t i(0); i < max_children; ++i)
 
 2138                throw csspp_exception_logic(
"compiler.cpp:compiler::replace_variable(): VARIABLE_FUNCTION children are not all ARG nodes."); 
 
 2163                    default_param->remove_child(0);  
 
 2164                    if(default_param->size() == 1)
 
 2166                        default_param = default_param->get_child(0);
 
 2171                        value_list->take_over_children_of(default_param);
 
 2172                        default_param = value_list;
 
 2175                    param_value->add_child(arg_name);
 
 2176                    param_value->add_child(default_param);
 
 2177                    root->set_variable(arg_name->get_string(), param_value);
 
 2183                            << 
"missing function variable named \"" 
 2184                            << arg_name->get_string()
 
 2185                            << 
"\" when calling " 
 2187                            << 
"() or using @include " 
 2200                    throw csspp_exception_logic(
"compiler.cpp:compiler::replace_variable(): user parameter is not an ARG."); 
 
 2202                if(user_param->size() == 1)
 
 2204                    user_param = user_param->get_child(0);
 
 2211                    list->take_over_children_of(user_param);
 
 2215                param_value->add_child(arg_name);
 
 2216                param_value->add_child(user_param->clone());
 
 2217                root->set_variable(arg_name->get_string(), param_value);
 
 2235            val = val->get_child(0);
 
 2244                    << 
"variable named \"" 
 2246                    << 
"\" is a function and it can only be referenced with a function ($" 
 2248                    << 
"() or @include " 
 2256    switch(val->get_type())
 
 2274            size_t const max_children(val->get_child(0)->size());
 
 2275            for(
size_t j(0), i(idx); j < max_children; ++j, ++i)
 
 2278                parent->insert_child(i, child->clone());
 
 2339#if __cplusplus >= 201700 
 2347            size_t const max_children(val->size());
 
 2348            for(
size_t j(0), i(idx); j < max_children; ++j, ++i)
 
 2350                parent->insert_child(i, val->get_child(j)->clone());
 
 2364        parent->insert_child(idx, val->clone());
 
 
 2392        throw csspp_exception_logic(
"compiler.cpp: somehow a variable set is not exactly IDENTIFIER WHITESPACE* ':'."); 
 
 2408    bool set_if_unset(
false);
 
 2409    std::string not_at_the_end;
 
 2410    size_t pos(n->size());
 
 2417            if(child->get_string() == 
"global")
 
 2420                n->remove_child(pos);
 
 2421                if(not_at_the_end.empty()
 
 2422                && pos != n->size())
 
 2424                    not_at_the_end = child->get_string();
 
 2427            else if(child->get_string() == 
"default")
 
 2429                set_if_unset = 
true;
 
 2430                n->remove_child(pos);
 
 2431                if(not_at_the_end.empty()
 
 2432                && pos != n->size())
 
 2434                    not_at_the_end = child->get_string();
 
 2439    if(!not_at_the_end.empty())
 
 2442                << 
"A special flag, !" 
 2444                << 
" in this case, must only appear at the end of a declaration." 
 2463        list = n->get_child(0);
 
 2468        list->take_over_children_of(n);
 
 2473    && list->get_string() == 
"null")
 
 
 2500    bool optional(
false);
 
 2501    size_t const max_children(var->size());
 
 2502    for(
size_t i(0); i < max_children; ++i)
 
 2507            throw csspp_exception_logic(
"compiler.cpp:compiler::set_variable(): an argument is not an ARG node."); 
 
 2516            size_t const arg_size(arg->size());
 
 2521                    arg->remove_child(1);
 
 2527                    arg->remove_child(1);
 
 2531                        arg->remove_child(1);
 
 2538                            << 
"function declarations expect variable with optional parameters to use a ':' after the variable name and before the optional value." 
 2548                            << 
"function declarations with optional parameters must make all parameters optional from the first one that is given an optional value up to the end of the list of arguments." 
 2556                    << 
"function declarations expect variables for each of their arguments, not a " 
 2557                    << param_var->get_type()
 
 
 2583    std::string 
const at(n->get_string());
 
 2602        parent->remove_child(idx);
 
 2612        parent->remove_child(idx);
 
 2620        parent->remove_child(idx);
 
 2629        parent->remove_child(idx);
 
 2637                    << 
"@include is expected to be followed by an IDENTIFIER or a FUNCTION naming the variable/mixin to include."    
 2647                    << 
"@include is expected to be followed by an IDENTIFIER or a FUNCTION naming the variable/mixin to include." 
 
 2690    if(idx < parent->size())
 
 2694        next = parent->get_child(idx);
 
 2696        && next->get_string() == 
"else")
 
 2699            next->set_integer(g_if_or_else_executed);
 
 2706    if(n->size() != 2 || !expr)
 
 2709                << 
"@if is expected to have exactly 2 parameters: an expression and a block. This @if has " 
 2710                << 
static_cast<int>(n->size())
 
 2723        size_t const max_children(block->size());
 
 2724        for(
size_t j(0); j < max_children; ++j, ++idx)
 
 2726            parent->insert_child(idx, block->get_child(j));
 
 2732        next->set_integer(g_if_or_else_false_so_far);
 
 
 2744    if(idx < parent->size())
 
 2746        next = parent->get_child(idx);
 
 2748        && next->get_string() == 
"else")
 
 2753                        << 
"'@else { ... }' cannot follow another '@else { ... }'. Maybe you are missing an 'if expr'?" 
 2762            next->set_integer(g_if_or_else_executed);
 
 2772                    && n->get_child(0)->get_string() == 
"if");
 
 2794                    << 
"'@else if ...' is missing an expression or a block." 
 2804    int status(n->get_integer());
 
 2805    if(status == g_if_or_else_undefined)
 
 2808                << 
"a standalone @else is not legal, it has to be preceeded by an @if ... or @else if ..." 
 2818    bool r(status == g_if_or_else_false_so_far);
 
 2821        if(n->size() != 2 || !expr)
 
 2824                    << 
"'@else { ... }' is expected to have 1 parameter, '@else if ... { ... }' is expected to have 2 parameters. This @else has " 
 2825                    << 
static_cast<int>(n->size())
 
 2845        status = g_if_or_else_executed;
 
 2851        size_t const max_children(block->size());
 
 2852        for(
size_t j(0); j < max_children; ++j, ++idx)
 
 2854            parent->insert_child(idx, block->get_child(j));
 
 2860        next->set_integer(status);
 
 
 2866    std::string comment(n->get_string());
 
 2868    std::string::size_type pos(comment.find(
'{')); 
 
 2869    while(pos != std::string::npos)
 
 2871        if(pos + 2 < comment.length()
 
 2872        && comment[pos + 1] == 
'$')
 
 2874            std::string::size_type start_var(pos);
 
 2875            std::string::size_type start_name(start_var + 2);
 
 2878            && comment[start_var - 1] == 
'#')
 
 2883            std::string::size_type end_var(comment.find(
'}', start_var + 2));
 
 2884            if(end_var != std::string::npos)
 
 2887                std::string 
const full_name(comment.substr(start_name, end_var - start_name));
 
 2890                bool is_function(
false);
 
 2891                std::string variable_name(full_name);
 
 2892                std::string::size_type func_pos(full_name.find(
'('));
 
 2893                if(func_pos != std::string::npos)
 
 2896                    variable_name = full_name.substr(0, func_pos);
 
 2905                    || var_content->size() != 2)
 
 2907                        throw csspp_exception_logic(
"compiler.cpp:compiler::replace_variables_in_comment(): all variable values must be two sub-values in a LIST, the first item being the variable."); 
 
 2916                                << 
"variable named \"" 
 2918                                << 
"\", is a function which is not supported in a comment." 
 2926                                    << 
"variable named \"" 
 2928                                    << 
"\", is not a function, yet you referenced it as such (and functions are not yet supported in comments)." 
 2934                        comment.erase(start_var, end_var + 1 - start_var);
 
 2936                        std::string 
const value(val->to_string(0));
 
 2938                        comment.insert(start_var, value);
 
 2943                        pos = start_var + value.length() - 1;
 
 2951                                << 
"variable named \"" 
 2953                                << 
"\", used in a comment, is not set." 
 2960        pos = comment.find(
'{', pos + 1); 
 
 2963    n->set_string(comment);
 
 
 2977            n->remove_child(term);          
 
 2978            if(pos >= n->size())            
 
 2982            term = n->get_child(pos);       
 
 2988                    << 
"an attribute selector expects to first find an identifier." 
 2994        if(pos >= n->size())
 
 3001        term = n->get_child(pos);
 
 3004            n->remove_child(pos);
 
 3005            if(pos >= n->size())
 
 3013            term = n->get_child(pos);
 
 3025                    << 
"expected attribute operator missing, supported operators are '=', '!=', '~=', '^=', '$=', '*=', and '|='." 
 3032        if(pos >= n->size())
 
 3037        term = n->get_child(pos);
 
 3040            n->remove_child(pos);
 
 3041            if(pos >= n->size())
 
 3048            term = n->get_child(pos);
 
 3057                    << 
"attribute selector value must be an identifier, a string, an integer, or a decimal number, a " 
 3058                    << term->get_type() << 
" is not acceptable." 
 3067                    << 
"attribute selector cannot be followed by more than one value, found " 
 3068                    << n->get_child(pos)->get_type() << 
" after the value, missing quotes?" 
 3080            parent->remove_child(parent_pos);
 
 3084            parent->insert_child(parent_pos, colon);
 
 3089            not_func->set_string(
"not");
 
 3090            parent->insert_child(parent_pos, not_func);
 
 3093            not_func->add_child(n);
 
 3100            n->insert_child(1, equal);
 
 3109            << 
"the attribute selector is expected to be an IDENTIFIER optionally followed by an operator and a value." 
 
 3116    if(pos >= n->size())
 
 3118        throw csspp_exception_logic(
"compiler.cpp:compiler::selector_term(): selector_simple_term() called when not enough selectors are available."); 
 
 3122    switch(term->get_type())
 
 3136        if(pos + 1 < n->size())
 
 3140                if(pos + 2 >= n->size())
 
 3143                            << 
"the scope operator (|) requires a right hand side identifier or '*'." 
 3148                term = n->get_child(pos);
 
 3153                            << 
"the right hand side of a scope operator (|) must be an identifier or '*'." 
 3163                n->remove_child(term);
 
 3171        if(pos >= n->size())
 
 3174                    << 
"a scope selector (|) must be followed by an identifier or '*'." 
 3178        term = n->get_child(pos);
 
 3183                    << 
"the right hand side of a scope operator (|) must be an identifier or '*'." 
 3191        if(pos >= n->size())
 
 3196                    << 
"a selector list cannot end with a standalone ':'." 
 3200        term = n->get_child(pos);
 
 3201        switch(term->get_type())
 
 3209                str->set_string(term->get_string());
 
 3225                function_name->set_string(term->get_string());
 
 3232                    size_t const max_children(term->size());
 
 3234                    for(
size_t idx(0); idx < max_children; ++idx)
 
 3244                        an_b_node->set_integer(nc.
get_nth());
 
 3246                        term->add_child(an_b_node);
 
 3266                    if(term->get_string() == 
"not")
 
 3270                                << 
"the :not() selector does not accept an inner :not()." 
 3274                    else if(term->get_string() == 
"lang")
 
 3277                        if(term->size() != 1)
 
 3280                                    << 
"a lang() function selector must have exactly one identifier as its parameter." 
 3284                        term = term->get_child(0);
 
 3287                            std::string lang(term->get_string());
 
 3288                            std::string country;
 
 3289                            std::string::size_type char_pos(lang.find(
'-'));
 
 3290                            if(char_pos != std::string::npos)
 
 3292                                country = lang.substr(char_pos + 1);
 
 3293                                lang = lang.substr(0, char_pos);
 
 3294                                char_pos = country.find(
'-');
 
 3295                                if(char_pos != std::string::npos)
 
 3299                                    country = country.substr(0, char_pos);
 
 3304                            language_name->set_string(lang);
 
 3311                            if(!country.empty())
 
 3315                                country_name->set_string(country);
 
 3327                                    << 
"a lang() function selector expects an identifier as its parameter." 
 3339                    << 
"a ':' selector must be followed by an identifier or a function, a " << n->get_type() << 
" was found instead." 
 3349        if(pos >= n->size())
 
 3352                    << 
"a selector list cannot end with a standalone '.'." 
 3356        term = n->get_child(pos);
 
 3360                    << 
"a class selector (after a period: '.') must be an identifier." 
 3374                << 
"found token " << term->get_type() << 
", which cannot be used to start a selector expression." 
 3380                << 
"found function \"" << term->get_string() << 
"()\", which may be a valid selector token but only if immediately preceeded by one ':' (simple term)." 
 3386                << 
"found token " << term->get_type() << 
", which is not a valid selector token (simple term)." 
 
 3400    if(pos >= n->size())
 
 3402        throw csspp_exception_logic(
"compiler.cpp:compiler::selector_term(): selector_term() called when not enough selectors are available."); 
 
 3406    switch(term->get_type())
 
 3417                    << 
"a selector reference (&) can only appear as the very first item in a list of selectors." 
 3428        if(pos >= n->size())
 
 3431                    << 
"a selector list cannot end with a standalone ':'." 
 3435        term = n->get_child(pos);
 
 3436        switch(term->get_type())
 
 3444            if(term->get_string() == 
"not")
 
 3457                if(sub_pos < term->size())
 
 3463                            << 
"the :not() function accepts at most one simple term." 
 3479                if(pos >= n->size())
 
 3482                            << 
"a selector list cannot end with a '::' without an identifier after it." 
 3486                term = n->get_child(pos);
 
 3490                            << 
"a pseudo element name (defined after a '::' in a list of selectors) must be defined using an identifier." 
 3496                pseudo_element->set_string(term->get_string());
 
 3503                if(pos + 1 < n->size())
 
 3506                            << 
"a pseudo element name (defined after a '::' in a list of selectors) must be defined as the last element in the list of selectors." 
 3516                    << 
"a ':' selector must be followed by an identifier or a function, a " << term->get_type() << 
" was found instead." 
 3535                << 
"found token " << term->get_type() << 
", which cannot be used to start a selector expression." 
 3543                << 
"found function \"" << term->get_string() << 
"()\", which may be a valid selector token but only if immediately preceeded by one ':' (term)." 
 3549                << 
"found token " << term->get_type() << 
", which is not a valid selector token (term)." 
 
 3571        if(pos >= n->size())
 
 3584            if(pos >= n->size())
 
 3588                throw csspp_exception_logic(
"compiler.cpp: a component value has a WHITESPACE token before the OPEN_CURLYBRACKET."); 
 
 3590            term = n->get_child(pos);
 
 3601                n->remove_child(pos - 1);
 
 3611            if(pos >= n->size())
 
 3614                        << 
"found token " << term->get_type() << 
", which is expected to be followed by another selector term." 
 3620            term = n->get_child(pos);
 
 3624                n->remove_child(term);
 
 3627                if(pos >= n->size())
 
 3631                    throw csspp_exception_logic(
"compiler.cpp: a component value has a WHITESPACE token before the OPEN_CURLYBRACKET."); 
 
 
 3650    size_t const max_children(n->size());
 
 3651    for(
size_t idx(0); idx < max_children; ++idx)
 
 3661            throw csspp_exception_logic(
"compiler.cpp: parse_selector() just called argify() and yet a child is not an ARG."); 
 
 3673        std::map<std::string, bool> hash;
 
 3674        for(
size_t j(0); j < arg->size(); ++j)
 
 3679                if(hash.find(child->get_string()) != hash.end())
 
 3683                            << child->get_string()
 
 3684                            << 
" twice in selector: \"" 
 3685                            << arg->to_string(0)
 
 3692                    hash[child->get_string()] = 
true;
 
 3701                        << 
"found multiple #id entries, note that in most cases, assuming your HTML is proper (identifiers are not repeated) then only the last #id is necessary." 
 
 3732    std::string filename(
find_file(script_name));
 
 3733    if(filename.empty())
 
 3735        if(script_name.substr(script_name.size() - 5) != 
".scss")
 
 3738            filename = 
find_file(script_name + 
".scss");
 
 3742    if(filename.empty())
 
 3747                << 
"validation script \"" 
 3749                << 
"\" was not found." 
 3775                    << 
"validation script \""                
 3777                    << 
"\" could not be opened."             
 3799    script->clear_variables();
 
 
 3806        throw csspp_exception_logic(
"compiler.cpp: somehow add_validation_variable() was called without a current validation script set."); 
 
 3810    var->set_string(variable_name);
 
 3813    v->add_child(value);
 
 
 3823        throw csspp_exception_logic(
"compiler.cpp:compiler::run_validation(): already validating, cannot validate from within a validation script."); 
 
 3840        std::stringstream ignore;
 
 
 3865    switch(n->get_type())
 
 3870            for(
size_t idx(0); idx < n->size();)
 
 3875                && child == n->get_child(idx))
 
 3890        for(
size_t idx(0); idx < n->size();)
 
 3896            && child == n->get_child(idx))
 
 3910        for(
size_t idx(0); idx < n->size();)
 
 3915            && child == n->get_child(idx))
 
 
 3933    switch(n->get_type())
 
 3962            size_t pos(parent->child_position(last));
 
 3963            parent->insert_child(pos + 1, n);
 
 3977                list->add_child(child);
 
 3979            for(
size_t idx(0); idx < root->size(); ++idx)
 
 3988                for(
size_t l(0); l < list->size(); ++l)
 
 3992                    for(
size_t a(0); a < arg->size(); ++a)
 
 4000                                clone->add_child(whitespace);
 
 4002                            clone->add_child(item->clone());
 
 4006                n->insert_child(idx, clone);
 
 4011            for(
size_t idx(0); idx < n->size();)
 
 4017                && child == n->get_child(idx))
 
 4026        for(
size_t idx(0); idx < n->size();)
 
 4032            && child == n->get_child(idx))
 
 4044        for(
size_t idx(0); idx < n->size();)
 
 4049            && child == n->get_child(idx))
 
 4058        for(
size_t idx(0); idx < n->size();)
 
 4063            && child == n->get_child(idx))
 
 
 4081    switch(n->get_type())
 
 4103            std::string 
const sub_name((name == 
"-csspp-null" ? 
"" : name + 
"-") + n->get_string());
 
 4107            size_t pos(parent->child_position(root));
 
 4108            parent->insert_child(pos + 1, n);
 
 4109            n->set_string(sub_name);
 
 4112            for(
size_t idx(0); idx < n->size();)
 
 4117                && child == n->get_child(idx))
 
 4134        throw csspp_exception_logic(
"compiler.cpp:compiler::expand_nested_declarations(): @-keyword cannot appear within a declaration."); 
 
 4149        for(
size_t idx(0); idx < n->size();)
 
 4154            && child == n->get_child(idx))
 
 4167                << 
"a nested declaration cannot include a rule." 
 
void set_root(node::pointer_t root)
void push_parent(node::pointer_t parent)
bool f_empty_on_undefined_variable
bool get_empty_on_undefined_variable() const
virtual node::pointer_t execute_user_function(node::pointer_t func)
virtual node::pointer_t get_variable(std::string const &variable_name, bool global_only=false) const
void add_path(std::string const &path)
void set_variable(node::pointer_t variable, node::pointer_t value, bool global) const
void set_paths(compiler_state_t const &state)
bool empty_parents() const
void set_empty_on_undefined_variable(bool const empty_on_undefined_variable)
node::pointer_t get_root() const
node::pointer_t get_previous_parent() const
std::string find_file(std::string const &script_name)
void replace_else(node::pointer_t parent, node::pointer_t n, size_t idx)
void set_no_logo(bool no_logo=true)
void replace_if(node::pointer_t parent, node::pointer_t n, size_t idx)
bool selector_term(node::pointer_t n, size_t &pos)
void handle_mixin(node::pointer_t n)
void compile_component_value(node::pointer_t n)
void expand_nested_rules(node::pointer_t parent, node::pointer_t root, node::pointer_t &last, node::pointer_t n)
void replace_variables_in_comment(node::pointer_t n)
bool parse_selector(node::pointer_t n)
void compile_declaration(node::pointer_t n)
void replace_variables(node::pointer_t n)
compiler(bool validating=false)
void add_header_and_footer()
void replace_variable(node::pointer_t parent, node::pointer_t n, size_t &idx)
void add_path(std::string const &path)
node::pointer_t get_result() const
void expand_nested_declarations(std::string const &name, node::pointer_t parent, node::pointer_t &root, node::pointer_t n)
void set_root(node::pointer_t root)
void prepare_function_arguments(node::pointer_t var)
node::pointer_t at_keyword_expression(node::pointer_t n)
node::pointer_t f_return_result
void compile_declaration_values(node::pointer_t declaration)
std::string find_file(std::string const &script_name)
void compile_at_keyword(node::pointer_t n)
void replace_at_keyword(node::pointer_t parent, node::pointer_t n, size_t &idx)
void set_validation_script(std::string const &script_name)
bool selector_simple_term(node::pointer_t n, size_t &pos)
void set_empty_on_undefined_variable(bool const empty_on_undefined_variable)
bool f_compiler_validating
void replace_import(node::pointer_t parent, node::pointer_t import, size_t &idx)
void expand_nested_components(node::pointer_t n)
node::pointer_t f_current_validation_script
bool run_validation(bool check_only)
bool selector_list(node::pointer_t n, size_t &pos)
node::pointer_t get_root() const
void mark_selectors(node::pointer_t n)
void set_date_time_variables(time_t now)
void compile_qualified_rule(node::pointer_t n)
void add_validation_variable(std::string const &variable_name, node::pointer_t value)
bool selector_attribute_check(node::pointer_t parent, size_t &parent_pos, node::pointer_t n)
void set_variable(node::pointer_t n)
void remove_empty_rules(node::pointer_t n)
bool error_happened() const
static error & instance()
node::pointer_t compile()
void set_variable_handler(expression_variables_interface *handler)
static bool boolean(node::pointer_t n)
Check whether a node represents true or false.
std::shared_ptr< lexer > pointer_t
static int const g_to_string_flag_show_quotes
std::shared_ptr< node > pointer_t
std::string get_error() const
integer_t get_nth() const
bool parse(std::string const &an_plus_b)
node::pointer_t stylesheet()
static bool argify(node::pointer_t n, node_type_t const separator=node_type_t::COMMA)
static bool is_nested_declaration(node::pointer_t n)
static bool is_variable_set(node::pointer_t n, bool with_block)
compiler::compiler_state_t & f_state
safe_compiler_state_t(compiler::compiler_state_t &state)
compiler::compiler_state_t f_state_copy
safe_parents_t(compiler::compiler_state_t &state, node::pointer_t n)
compiler::compiler_state_t & f_state
integer_t const g_if_or_else_undefined
integer_t const g_if_or_else_executed
integer_t const g_if_or_else_false_so_far
The namespace of all the classes in the CSS Preprocessor.