Skip to content

Commit

Permalink
Some more improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed May 1, 2021
1 parent a34cd4b commit a653f76
Show file tree
Hide file tree
Showing 33 changed files with 252 additions and 206 deletions.
17 changes: 9 additions & 8 deletions docs/api-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,35 @@ compilers should catch the case when arguments mismatch on the C-API side.

### List of anonymous structures

These structs have no real implementation are only passed around as pointers.
Internally in LibSass those pointers represent mostly different c++ objects.
These structs have no real implementation and are only passed around as pointers.
Internally in LibSass these pointers represent mostly different c++ objects.

- struct SassError - An error object to get further information
- struct SassTrace - An single stack-trace object to get further information
- struct SassError - An error object holding further information
- struct SassTrace - An single stack-trace object holding further information
- struct SassSource - Imported source with associated import and resolved path.
- struct SassSrcSpan - Parser state for column, line and source information.
- struct SassCompiler - Main object to hold state for whole compilation phase.
- struct SassFunction - Custom function object holding callback and cookie.
- struct SassImport - Single import for entry point or returned by custom importer.
- struct SassImporter - Custom importer function to be hooked into our loading.
- struct SassImportList - Custom importers can return a list of imports.
- struct SassImportList - Custom importers can return a SassImport list.
- struct SassMapIterator - Object to support iteration API over map objects.

## Why using c++11 (or gcc4.4 compatibility)

Since LibSass 3.0 we started to use more and more c++11 features. Some just
creeped in, others were utilized deliberately. With LibSass 4.0 I took the
crept in, others were utilized deliberately. With LibSass 4.0 I took the
decision to fully utilize whatever c++11 could offer. The main reason to
fully embrace c++11 is the move semantics it brings. Earlier we also tried
to support compilers that only had partial c++11 support (e.g. gnu++0x).
With LibSass 4.0 we don't really support this target anymore, as any compiler
not older than 5 years should support the c++11 syntax we use.

Note: currently the LibSass 4.0 release is on going and the final
target compiler is gcc 4.8, as it should fully support c++11.
target compiler is gcc 4.8, as it should fully support c++11.
More testing and tuning needs to be done after a 4.0 release!

## Binary distributions in linkage issues
## Binary distributions and linkage issues

LibSass itself does not have any official binary distribution. The main reason for
this is because it is nearly impossible to do so reliably for each and every
Expand Down
132 changes: 93 additions & 39 deletions docs/api-compiler-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

```C:data.c
#include <stdio.h>
#include <sass/context.h>
#include <sass.h>

int main( int argc, const char* argv[] )
int main(int argc, const char* argv[])
{

// LibSass will take control of data you pass in
Expand All @@ -15,22 +15,47 @@ int main( int argc, const char* argv[] )
// then fill it with data you load from disk or somewhere else.

// create the data context and get all related structs
struct Sass_Data_Context* data_ctx = sass_make_data_context(text);
struct Sass_Context* ctx = sass_data_context_get_context(data_ctx);
struct Sass_Options* ctx_opt = sass_context_get_options(ctx);

// configure some options ...
sass_option_set_precision(ctx_opt, 10);

// context is set up, call the compile step now
int status = sass_compile_data_context(data_ctx);

// print the result or the error to the stdout
if (status == 0) puts(sass_context_get_output_string(ctx));
else puts(sass_context_get_error_message(ctx));

// release allocated memory
sass_delete_data_context(data_ctx);
struct SassCompiler* compiler = sass_make_compiler();
struct SassImport* data = sass_make_content_import(text, "styles");
sass_compiler_set_entry_point(compiler, data);
// everything you make you must delete
sass_delete_import(data); // passed away

// Execute all three phases
sass_compiler_parse(compiler);
sass_compiler_compile(compiler);
sass_compiler_render(compiler);

// Print any warning to console
if (sass_compiler_get_warn_string(compiler)) {
sass_print_stderr(sass_compiler_get_warn_string(compiler));
}

// Print error message if we have an error
if (sass_compiler_get_status(compiler) != 0) {
const struct SassError* error = sass_compiler_get_error(compiler);
sass_print_stderr(sass_error_get_string(error));
}

// Get result code after all compilation steps
int status = sass_compiler_get_status(compiler);

// Write to output if no errors occurred
if (status == 0) {

// Paths where to write stuff to (might be `stream://stdout`)
const char* outfile = sass_compiler_get_output_path(compiler);
const char* mapfile = sass_compiler_get_srcmap_path(compiler);
// Get the parts to be added to the output file (or stdout)
const char* content = sass_compiler_get_output_string(compiler);
const char* footer = sass_compiler_get_footer_string(compiler);
const char* srcmap = sass_compiler_get_srcmap_string(compiler);

// Output all results
if (content) puts(content);
if (footer) puts(footer);

}

// exit status
return status;
Expand All @@ -51,31 +76,60 @@ echo "foo { margin: 21px * 2; }" > foo.scss

```C:file.c
#include <stdio.h>
#include "sass/context.h"
#include <sass.h>

int main( int argc, const char* argv[] )
int main(int argc, const char* argv[])
{

// get the input file from first argument or use default
const char* input = argc > 1 ? argv[1] : "styles.scss";

// create the file context and get all related structs
struct Sass_File_Context* file_ctx = sass_make_file_context(input);
struct Sass_Context* ctx = sass_file_context_get_context(file_ctx);
struct Sass_Options* ctx_opt = sass_context_get_options(ctx);

// configure some options ...
sass_option_set_precision(ctx_opt, 10);

// context is set up, call the compile step now
int status = sass_compile_file_context(file_ctx);

// print the result or the error to the stdout
if (status == 0) puts(sass_context_get_output_string(ctx));
else puts(sass_context_get_error_message(ctx));
// LibSass will take control of data you pass in
// Therefore we need to make a copy of static data
char* text = sass_copy_c_string("a{b:c;}");
// Normally you'll load data into a buffer from i.e. the disk.
// Use `sass_alloc_memory` to get a buffer to pass to LibSass
// then fill it with data you load from disk or somewhere else.

// release allocated memory
sass_delete_file_context(file_ctx);
// create the data context and get all related structs
struct SassCompiler* compiler = sass_make_compiler();
struct SassImport* data = sass_make_file_import("foo.scss");
sass_compiler_set_entry_point(compiler, data);
// everything you make you must delete
sass_delete_import(data); // passed away

// Execute all three phases
sass_compiler_parse(compiler);
sass_compiler_compile(compiler);
sass_compiler_render(compiler);

// Print any warning to console
if (sass_compiler_get_warn_string(compiler)) {
sass_print_stderr(sass_compiler_get_warn_string(compiler));
}

// Print error message if we have an error
if (sass_compiler_get_status(compiler) != 0) {
const struct SassError* error = sass_compiler_get_error(compiler);
sass_print_stderr(sass_error_get_string(error));
}

// Get result code after all compilation steps
int status = sass_compiler_get_status(compiler);

// Write to output if no errors occurred
if (status == 0) {

// Paths where to write stuff to (might be `stream://stdout`)
const char* outfile = sass_compiler_get_output_path(compiler);
const char* mapfile = sass_compiler_get_srcmap_path(compiler);
// Get the parts to be added to the output file (or stdout)
const char* content = sass_compiler_get_output_string(compiler);
const char* footer = sass_compiler_get_footer_string(compiler);
const char* srcmap = sass_compiler_get_srcmap_string(compiler);

// Output all results
if (content) puts(content);
if (footer) puts(footer);

}

// exit status
return status;
Expand Down
112 changes: 55 additions & 57 deletions docs/api-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ First you will need to include the header file!
This will automatically load all other headers too!

```C
#include "sass/context.h"
#include <sass.h>
```

## Basic C Example

```C
#include <stdio.h>
#include "sass/context.h"
#include <sass.h>

int main() {
puts(libsass_version());
Expand All @@ -54,61 +54,59 @@ gcc -Wall version.c -lsass -o version && ./version

## Compiling your code

The most important is your sass file (or string of sass code). With this, you
will want to start a LibSass compiler. Here is some pseudocode describing the
process. The compiler has two different modes: direct input as a string with
`Sass_Data_Context` or LibSass will do file reading for you by using
`Sass_File_Context`. See the code for a list of options available
[Sass_Options](https://github.com/sass/libsass/blob/36feef0/include/sass/interface.h#L18)

The general rule is if the API takes `const char*` it will make a copy,
but where the API is `char*` it will take over memory ownership, so make sure to pass
in memory that is allocated via `sass_copy_c_string` or `sass_alloc_memory`.

**Building a file compiler**

context = sass_make_file_context("file.scss")
options = sass_file_context_get_options(context)
sass_option_set_precision(options, 1)
sass_option_set_source_comments(options, true)

sass_file_context_set_options(context, options)

compiler = sass_make_file_compiler(sass_context)
sass_compiler_parse(compiler)
sass_compiler_execute(compiler)

output = sass_context_get_output_string(context)
// Retrieve errors during compilation
error_status = sass_context_get_error_status(context)
json_error = sass_context_get_error_json(context)
// Release memory dedicated to the C compiler
sass_delete_compiler(compiler)

**Building a data compiler**

// LibSass takes over memory owenership, make sure to allocate
// a buffer via `sass_alloc_memory` or `sass_copy_c_string`.
buffer = sass_copy_c_string("div { a { color: blue; } }")

context = sass_make_data_context(buffer)
options = sass_data_context_get_options(context)
sass_option_set_precision(options, 1)
sass_option_set_source_comments(options, true)

sass_data_context_set_options(context, options)

compiler = sass_make_data_compiler(context)
sass_compiler_parse(compiler)
sass_compiler_execute(compiler)

output = sass_context_get_output_string(context)
// div a { color: blue; }
// Retrieve errors during compilation
error_status = sass_context_get_error_status(context)
json_error = sass_context_get_error_json(context)
// Release memory dedicated to the C compiler
sass_delete_compiler(compiler)
LibSass parsing starts with some entry point, which can either be a
file or some code you provide directly. Further relative includes are
resolved against CWD. In order to tell LibSass the entry point, there
are two main ways, either defining the content directly or let LibSass
load a file.

`struct SassImport* data = sass_make_content_import(text, "styles.scss");`
`struct SassImport* data = sass_make_file_import("styles.scss");`

**Building a compiler**

sass_compiler_set_entry_point(compiler, entrypoint);
// everything you make you must delete
sass_delete_import(data); // passed away

// Execute all three phases
sass_compiler_parse(compiler);
sass_compiler_compile(compiler);
sass_compiler_render(compiler);

// Print any warning to console
if (sass_compiler_get_warn_string(compiler)) {
sass_print_stderr(sass_compiler_get_warn_string(compiler));
}

// Print error message if we have an error
if (sass_compiler_get_status(compiler) != 0) {
const struct SassError* error = sass_compiler_get_error(compiler);
sass_print_stderr(sass_error_get_string(error));
}

// Get result code after all compilation steps
int status = sass_compiler_get_status(compiler);

// Write to output if no errors occurred
if (status == 0) {

// Paths where to write stuff to (might be `stream://stdout`)
const char* outfile = sass_compiler_get_output_path(compiler);
const char* mapfile = sass_compiler_get_srcmap_path(compiler);
// Get the parts to be added to the output file (or stdout)
const char* content = sass_compiler_get_output_string(compiler);
const char* footer = sass_compiler_get_footer_string(compiler);
const char* srcmap = sass_compiler_get_srcmap_string(compiler);

// Output all results
if (content) puts(content);
if (footer) puts(footer);

}

// exit status
return status;

## Sass Context Internals

Expand Down
2 changes: 1 addition & 1 deletion docs/api-import.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

Imports on the C-API side can either be compilation entry points or imports
returned from custom importers. Overall they behave very similarly, but entry
points are a bit more strict, as we know better what to expect. Import from
points are a bit more strict, as we know better what to expect. Imports from
custom importers can be more versatile. An import can either have a path,
some loaded content or both. Custom importer can return imports in either
of that state, while with entry points we know what to expect.
Expand Down
10 changes: 6 additions & 4 deletions include/sass/variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,18 @@ extern "C" {
ADDAPI struct SassValue* ADDCALL sass_env_get_lexical (struct SassCompiler*, const char*);

// Setter for lexical variable (lexical to scope where function is called).
// Returns true if variable was set or false if it does not exist (we can't create it)
// Note: C-API function can only access existing variables and not create new ones!
ADDAPI void ADDCALL sass_env_set_lexical(struct SassCompiler*, const char*, struct SassValue*);
ADDAPI bool ADDCALL sass_env_set_lexical(struct SassCompiler*, const char*, struct SassValue*);

// Getter for local variable (local only to scope where function is called).
// Getter for global variable (only variables on the root scope are considered).
// Note: C-API function can only access existing variables and not create new ones!
ADDAPI struct SassValue* ADDCALL sass_env_get_global (struct SassCompiler*, const char*);

// Setter for local variable (local only to scope where function is called).
// Setter for global variable (only variables on the root scope are considered).
// Returns true if variable was set or false if it does not exist (we can't create it)
// Note: C-API function can only access existing variables and not create new ones!
ADDAPI void ADDCALL sass_env_set_global(struct SassCompiler*, const char*, struct SassValue*);
ADDAPI bool ADDCALL sass_env_set_global(struct SassCompiler*, const char*, struct SassValue*);

/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
Expand Down
6 changes: 3 additions & 3 deletions src/ast_callables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Sass {
const EnvKey& envkey,
ArgumentDeclaration* parameters,
const SassFnSig& callback) :
Callable(SourceSpan::tmp("[BUILTIN]")),
Callable(SourceSpan::internal("[BUILTIN]")),
envkey_(envkey),
// Create a single entry in overloaded function
function_(SassFnPair{ parameters, callback })
Expand Down Expand Up @@ -54,7 +54,7 @@ namespace Sass {
BuiltInCallables::BuiltInCallables(
const EnvKey& envkey,
const SassFnPairs& overloads) :
Callable(SourceSpan::tmp("[BUILTINS]")),
Callable(SourceSpan::internal("[BUILTINS]")),
envkey_(envkey),
overloads_(overloads)
{
Expand Down Expand Up @@ -121,7 +121,7 @@ namespace Sass {
const EnvKey& fname,
ArgumentDeclaration* parameters,
SassFunctionLambda lambda) :
Callable(SourceSpan::tmp("[EXTERNAL]")),
Callable(SourceSpan::internal("[EXTERNAL]")),
envkey_(fname),
declaration_(parameters),
lambda_(lambda)
Expand Down
Loading

0 comments on commit a653f76

Please sign in to comment.