1 // sass.hpp must go before all system headers to get the
2 // __EXTENSIONS__ fix on Solaris.
3 #include "sass.hpp"
4 
5 #include <cstring>
6 #include "util.hpp"
7 #include "context.hpp"
8 #include "values.hpp"
9 #include "sass/functions.h"
10 #include "sass_functions.hpp"
11 
12 extern "C" {
13   using namespace Sass;
14 
sass_make_function_list(size_t length)15   Sass_Function_List ADDCALL sass_make_function_list(size_t length)
16   {
17     return (Sass_Function_List) calloc(length + 1, sizeof(Sass_Function_Entry));
18   }
19 
sass_make_function(const char * signature,Sass_Function_Fn function,void * cookie)20   Sass_Function_Entry ADDCALL sass_make_function(const char* signature, Sass_Function_Fn function, void* cookie)
21   {
22     Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function));
23     if (cb == 0) return 0;
24     cb->signature = sass_copy_c_string(signature);
25     cb->function = function;
26     cb->cookie = cookie;
27     return cb;
28   }
29 
sass_delete_function(Sass_Function_Entry entry)30   void ADDCALL sass_delete_function(Sass_Function_Entry entry)
31   {
32     free(entry->signature);
33     free(entry);
34   }
35 
36   // Deallocator for the allocated memory
sass_delete_function_list(Sass_Function_List list)37   void ADDCALL sass_delete_function_list(Sass_Function_List list)
38   {
39     Sass_Function_List it = list;
40     if (list == 0) return;
41     while(*list) {
42       sass_delete_function(*list);
43       ++list;
44     }
45     free(it);
46   }
47 
48   // Setters and getters for callbacks on function lists
sass_function_get_list_entry(Sass_Function_List list,size_t pos)49   Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; }
sass_function_set_list_entry(Sass_Function_List list,size_t pos,Sass_Function_Entry cb)50   void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; }
51 
sass_function_get_signature(Sass_Function_Entry cb)52   const char* ADDCALL sass_function_get_signature(Sass_Function_Entry cb) { return cb->signature; }
sass_function_get_function(Sass_Function_Entry cb)53   Sass_Function_Fn ADDCALL sass_function_get_function(Sass_Function_Entry cb) { return cb->function; }
sass_function_get_cookie(Sass_Function_Entry cb)54   void* ADDCALL sass_function_get_cookie(Sass_Function_Entry cb) { return cb->cookie; }
55 
sass_make_importer(Sass_Importer_Fn importer,double priority,void * cookie)56   Sass_Importer_Entry ADDCALL sass_make_importer(Sass_Importer_Fn importer, double priority, void* cookie)
57   {
58     Sass_Importer_Entry cb = (Sass_Importer_Entry) calloc(1, sizeof(Sass_Importer));
59     if (cb == 0) return 0;
60     cb->importer = importer;
61     cb->priority = priority;
62     cb->cookie = cookie;
63     return cb;
64   }
65 
sass_importer_get_function(Sass_Importer_Entry cb)66   Sass_Importer_Fn ADDCALL sass_importer_get_function(Sass_Importer_Entry cb) { return cb->importer; }
sass_importer_get_priority(Sass_Importer_Entry cb)67   double ADDCALL sass_importer_get_priority (Sass_Importer_Entry cb) { return cb->priority; }
sass_importer_get_cookie(Sass_Importer_Entry cb)68   void* ADDCALL sass_importer_get_cookie(Sass_Importer_Entry cb) { return cb->cookie; }
69 
70   // Just in case we have some stray import structs
sass_delete_importer(Sass_Importer_Entry cb)71   void ADDCALL sass_delete_importer (Sass_Importer_Entry cb)
72   {
73     free(cb);
74   }
75 
76   // Creator for sass custom importer function list
sass_make_importer_list(size_t length)77   Sass_Importer_List ADDCALL sass_make_importer_list(size_t length)
78   {
79     return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry));
80   }
81 
82   // Deallocator for the allocated memory
sass_delete_importer_list(Sass_Importer_List list)83   void ADDCALL sass_delete_importer_list(Sass_Importer_List list)
84   {
85     Sass_Importer_List it = list;
86     if (list == 0) return;
87     while(*list) {
88       sass_delete_importer(*list);
89       ++list;
90     }
91     free(it);
92   }
93 
sass_importer_get_list_entry(Sass_Importer_List list,size_t idx)94   Sass_Importer_Entry ADDCALL sass_importer_get_list_entry(Sass_Importer_List list, size_t idx) { return list[idx]; }
sass_importer_set_list_entry(Sass_Importer_List list,size_t idx,Sass_Importer_Entry cb)95   void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) { list[idx] = cb; }
96 
97   // Creator for sass custom importer return argument list
sass_make_import_list(size_t length)98   Sass_Import_List ADDCALL sass_make_import_list(size_t length)
99   {
100     return (Sass_Import**) calloc(length + 1, sizeof(Sass_Import*));
101   }
102 
103   // Creator for a single import entry returned by the custom importer inside the list
104   // We take ownership of the memory for source and srcmap (freed when context is destroyed)
sass_make_import(const char * imp_path,const char * abs_path,char * source,char * srcmap)105   Sass_Import_Entry ADDCALL sass_make_import(const char* imp_path, const char* abs_path, char* source, char* srcmap)
106   {
107     Sass_Import* v = (Sass_Import*) calloc(1, sizeof(Sass_Import));
108     if (v == 0) return 0;
109     v->imp_path = imp_path ? sass_copy_c_string(imp_path) : 0;
110     v->abs_path = abs_path ? sass_copy_c_string(abs_path) : 0;
111     v->source = source;
112     v->srcmap = srcmap;
113     v->error = 0;
114     v->line = -1;
115     v->column = -1;
116     return v;
117   }
118 
119   // Older style, but somehow still valid - keep around or deprecate?
sass_make_import_entry(const char * path,char * source,char * srcmap)120   Sass_Import_Entry ADDCALL sass_make_import_entry(const char* path, char* source, char* srcmap)
121   {
122     return sass_make_import(path, path, source, srcmap);
123   }
124 
125   // Upgrade a normal import entry to throw an error (original path can be re-used by error reporting)
sass_import_set_error(Sass_Import_Entry import,const char * error,size_t line,size_t col)126   Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import, const char* error, size_t line, size_t col)
127   {
128     if (import == 0) return 0;
129     if (import->error) free(import->error);
130     import->error = error ? sass_copy_c_string(error) : 0;
131     import->line = line ? line : -1;
132     import->column = col ? col : -1;
133     return import;
134   }
135 
136   // Setters and getters for entries on the import list
sass_import_set_list_entry(Sass_Import_List list,size_t idx,Sass_Import_Entry entry)137   void ADDCALL sass_import_set_list_entry(Sass_Import_List list, size_t idx, Sass_Import_Entry entry) { list[idx] = entry; }
sass_import_get_list_entry(Sass_Import_List list,size_t idx)138   Sass_Import_Entry ADDCALL sass_import_get_list_entry(Sass_Import_List list, size_t idx) { return list[idx]; }
139 
140   // Deallocator for the allocated memory
sass_delete_import_list(Sass_Import_List list)141   void ADDCALL sass_delete_import_list(Sass_Import_List list)
142   {
143     Sass_Import_List it = list;
144     if (list == 0) return;
145     while(*list) {
146       sass_delete_import(*list);
147       ++list;
148     }
149     free(it);
150   }
151 
152   // Just in case we have some stray import structs
sass_delete_import(Sass_Import_Entry import)153   void ADDCALL sass_delete_import(Sass_Import_Entry import)
154   {
155     free(import->imp_path);
156     free(import->abs_path);
157     free(import->source);
158     free(import->srcmap);
159     free(import->error);
160     free(import);
161   }
162 
163   // Getter for callee entry
sass_callee_get_name(Sass_Callee_Entry entry)164   const char* ADDCALL sass_callee_get_name(Sass_Callee_Entry entry) { return entry->name; }
sass_callee_get_path(Sass_Callee_Entry entry)165   const char* ADDCALL sass_callee_get_path(Sass_Callee_Entry entry) { return entry->path; }
sass_callee_get_line(Sass_Callee_Entry entry)166   size_t ADDCALL sass_callee_get_line(Sass_Callee_Entry entry) { return entry->line; }
sass_callee_get_column(Sass_Callee_Entry entry)167   size_t ADDCALL sass_callee_get_column(Sass_Callee_Entry entry) { return entry->column; }
sass_callee_get_type(Sass_Callee_Entry entry)168   enum Sass_Callee_Type ADDCALL sass_callee_get_type(Sass_Callee_Entry entry) { return entry->type; }
sass_callee_get_env(Sass_Callee_Entry entry)169   Sass_Env_Frame ADDCALL sass_callee_get_env (Sass_Callee_Entry entry) { return &entry->env; }
170 
171   // Getters and Setters for environments (lexical, local and global)
sass_env_get_lexical(Sass_Env_Frame env,const char * name)172   union Sass_Value* ADDCALL sass_env_get_lexical (Sass_Env_Frame env, const char* name) {
173     Expression* ex = Cast<Expression>((*env->frame)[name]);
174     return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
175   }
sass_env_set_lexical(Sass_Env_Frame env,const char * name,union Sass_Value * val)176   void ADDCALL sass_env_set_lexical (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
177     (*env->frame)[name] = sass_value_to_ast_node(val);
178   }
sass_env_get_local(Sass_Env_Frame env,const char * name)179   union Sass_Value* ADDCALL sass_env_get_local (Sass_Env_Frame env, const char* name) {
180     Expression* ex = Cast<Expression>(env->frame->get_local(name));
181     return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
182   }
sass_env_set_local(Sass_Env_Frame env,const char * name,union Sass_Value * val)183   void ADDCALL sass_env_set_local (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
184     env->frame->set_local(name, sass_value_to_ast_node(val));
185   }
sass_env_get_global(Sass_Env_Frame env,const char * name)186   union Sass_Value* ADDCALL sass_env_get_global (Sass_Env_Frame env, const char* name) {
187     Expression* ex = Cast<Expression>(env->frame->get_global(name));
188     return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
189   }
sass_env_set_global(Sass_Env_Frame env,const char * name,union Sass_Value * val)190   void ADDCALL sass_env_set_global (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
191     env->frame->set_global(name, sass_value_to_ast_node(val));
192   }
193 
194   // Getter for import entry
sass_import_get_imp_path(Sass_Import_Entry entry)195   const char* ADDCALL sass_import_get_imp_path(Sass_Import_Entry entry) { return entry->imp_path; }
sass_import_get_abs_path(Sass_Import_Entry entry)196   const char* ADDCALL sass_import_get_abs_path(Sass_Import_Entry entry) { return entry->abs_path; }
sass_import_get_source(Sass_Import_Entry entry)197   const char* ADDCALL sass_import_get_source(Sass_Import_Entry entry) { return entry->source; }
sass_import_get_srcmap(Sass_Import_Entry entry)198   const char* ADDCALL sass_import_get_srcmap(Sass_Import_Entry entry) { return entry->srcmap; }
199 
200   // Getter for import error entry
sass_import_get_error_line(Sass_Import_Entry entry)201   size_t ADDCALL sass_import_get_error_line(Sass_Import_Entry entry) { return entry->line; }
sass_import_get_error_column(Sass_Import_Entry entry)202   size_t ADDCALL sass_import_get_error_column(Sass_Import_Entry entry) { return entry->column; }
sass_import_get_error_message(Sass_Import_Entry entry)203   const char* ADDCALL sass_import_get_error_message(Sass_Import_Entry entry) { return entry->error; }
204 
205   // Explicit functions to take ownership of the memory
206   // Resets our own property since we do not know if it is still alive
sass_import_take_source(Sass_Import_Entry entry)207   char* ADDCALL sass_import_take_source(Sass_Import_Entry entry) { char* ptr = entry->source; entry->source = 0; return ptr; }
sass_import_take_srcmap(Sass_Import_Entry entry)208   char* ADDCALL sass_import_take_srcmap(Sass_Import_Entry entry) { char* ptr = entry->srcmap; entry->srcmap = 0; return ptr; }
209 
210 }
211