Blame docs/custom-functions-internal.md

Packit Service 7770af
# Developer Documentation
Packit Service 7770af
Packit Service 7770af
Custom functions are internally represented by `struct Sass_C_Function_Descriptor`.
Packit Service 7770af
Packit Service 7770af
## Sass_C_Function_Descriptor
Packit Service 7770af
Packit Service 7770af
```C
Packit Service 7770af
struct Sass_C_Function_Descriptor {
Packit Service 7770af
  const char*      signature;
Packit Service 7770af
  Sass_C_Function  function;
Packit Service 7770af
  void*            cookie;
Packit Service 7770af
};
Packit Service 7770af
```
Packit Service 7770af
Packit Service 7770af
- `signature`: The function declaration, like `foo($bar, $baz:1)`
Packit Service 7770af
- `function`:  Reference to the C function callback
Packit Service 7770af
- `cookie`:    any pointer you want to attach
Packit Service 7770af
Packit Service 7770af
### signature
Packit Service 7770af
Packit Service 7770af
The signature defines how the function can be invoked. It also declares which arguments are required and which are optional.  Required arguments will be enforced by LibSass and a Sass error is thrown in the event a call as missing an argument. Optional arguments only need to be present when you want to overwrite the default value.
Packit Service 7770af
Packit Service 7770af
    foo($bar, $baz: 2)
Packit Service 7770af
Packit Service 7770af
In this example, `$bar` is required and will error if not passed. `$baz` is optional and the default value of it is 2. A call like `foo(10)` is therefore equal to `foo(10, 2)`, while `foo()` will produce an error.
Packit Service 7770af
Packit Service 7770af
### function
Packit Service 7770af
Packit Service 7770af
The callback function needs to be of the following form:
Packit Service 7770af
Packit Service 7770af
```C
Packit Service 7770af
union Sass_Value* call_sass_function(
Packit Service 7770af
    const union Sass_Value* s_args,
Packit Service 7770af
    void*                   cookie
Packit Service 7770af
) {
Packit Service 7770af
  return sass_clone_value(s_args);
Packit Service 7770af
}
Packit Service 7770af
```
Packit Service 7770af
Packit Service 7770af
### cookie
Packit Service 7770af
Packit Service 7770af
The cookie can hold any pointer you want. In the `perl-libsass` implementation it holds the structure with the reference of the actual registered callback into the perl interpreter. Before that call `perl-libsass` will convert all `Sass_Values` to corresponding perl data types (so they can be used natively inside the perl interpretor). The callback can also return a `Sass_Value`. In `perl-libsass` the actual function returns a perl value, which has to be converted before `libsass` can work with it again!
Packit Service 7770af
Packit Service 7770af
## Sass_Values
Packit Service 7770af
Packit Service 7770af
```C
Packit Service 7770af
// allocate memory (copies passed strings)
Packit Service 7770af
union Sass_Value* make_sass_boolean (int val);
Packit Service 7770af
union Sass_Value* make_sass_number  (double val, const char* unit);
Packit Service 7770af
union Sass_Value* make_sass_color   (double r, double g, double b, double a);
Packit Service 7770af
union Sass_Value* make_sass_string  (const char* val);
Packit Service 7770af
union Sass_Value* make_sass_list    (size_t len, enum Sass_Separator sep);
Packit Service 7770af
union Sass_Value* make_sass_map     (size_t len);
Packit Service 7770af
union Sass_Value* make_sass_null    ();
Packit Service 7770af
union Sass_Value* make_sass_error   (const char* msg);
Packit Service 7770af
Packit Service 7770af
// Make a deep cloned copy of the given sass value
Packit Service 7770af
union Sass_Value* sass_clone_value (const union Sass_Value* val);
Packit Service 7770af
Packit Service 7770af
// deallocate memory (incl. all copied memory)
Packit Service 7770af
void sass_delete_value (const union Sass_Value* val);
Packit Service 7770af
```
Packit Service 7770af
Packit Service 7770af
## Example main.c
Packit Service 7770af
Packit Service 7770af
```C
Packit Service 7770af
#include <stdio.h>
Packit Service 7770af
#include <stdint.h>
Packit Service 7770af
#include "sass/context.h"
Packit Service 7770af
Packit Service 7770af
union Sass_Value* call_fn_foo(const union Sass_Value* s_args, void* cookie)
Packit Service 7770af
{
Packit Service 7770af
  // we actually abuse the void* to store an "int"
Packit Service 7770af
  return sass_make_number((size_t)cookie, "px");
Packit Service 7770af
}
Packit Service 7770af
Packit Service 7770af
int main( int argc, const char* argv[] )
Packit Service 7770af
{
Packit Service 7770af
Packit Service 7770af
  // get the input file from first argument or use default
Packit Service 7770af
  const char* input = argc > 1 ? argv[1] : "styles.scss";
Packit Service 7770af
Packit Service 7770af
  // create the file context and get all related structs
Packit Service 7770af
  struct Sass_File_Context* file_ctx = sass_make_file_context(input);
Packit Service 7770af
  struct Sass_Context* ctx = sass_file_context_get_context(file_ctx);
Packit Service 7770af
  struct Sass_Options* ctx_opt = sass_context_get_options(ctx);
Packit Service 7770af
Packit Service 7770af
  // allocate a custom function caller
Packit Service 7770af
  Sass_C_Function_Callback fn_foo =
Packit Service 7770af
    sass_make_function("foo()", call_fn_foo, (void*)42);
Packit Service 7770af
Packit Service 7770af
  // create list of all custom functions
Packit Service 7770af
  Sass_C_Function_List fn_list = sass_make_function_list(1);
Packit Service 7770af
  sass_function_set_list_entry(fn_list, 0, fn_foo);
Packit Service 7770af
  sass_option_set_c_functions(ctx_opt, fn_list);
Packit Service 7770af
Packit Service 7770af
  // context is set up, call the compile step now
Packit Service 7770af
  int status = sass_compile_file_context(file_ctx);
Packit Service 7770af
Packit Service 7770af
  // print the result or the error to the stdout
Packit Service 7770af
  if (status == 0) puts(sass_context_get_output_string(ctx));
Packit Service 7770af
  else puts(sass_context_get_error_message(ctx));
Packit Service 7770af
Packit Service 7770af
  // release allocated memory
Packit Service 7770af
  sass_delete_file_context(file_ctx);
Packit Service 7770af
Packit Service 7770af
  // exit status
Packit Service 7770af
  return status;
Packit Service 7770af
Packit Service 7770af
}
Packit Service 7770af
```
Packit Service 7770af
Packit Service 7770af
## Compile main.c
Packit Service 7770af
Packit Service 7770af
```bash
Packit Service 7770af
gcc -c main.c -o main.o
Packit Service 7770af
gcc -o sample main.o -lsass
Packit Service 7770af
echo "foo { margin: foo(); }" > foo.scss
Packit Service 7770af
./sample foo.scss => "foo { margin: 42px }"
Packit Service 7770af
```