diff options
Diffstat (limited to 'prism/options.c')
| -rw-r--r-- | prism/options.c | 282 |
1 files changed, 227 insertions, 55 deletions
diff --git a/prism/options.c b/prism/options.c index cd575357aa..b589865a2a 100644 --- a/prism/options.c +++ b/prism/options.c @@ -1,9 +1,78 @@ -#include "prism/options.h" +#include "prism/internal/options.h" + +#include "prism/compiler/inline.h" + +#include "prism/internal/allocator.h" +#include "prism/internal/char.h" +#include "prism/internal/stringy.h" + +#include <stdlib.h> +#include <string.h> + +/** + * Allocate a new options struct. If the options struct cannot be allocated, + * this function aborts the process. + */ +pm_options_t * +pm_options_new(void) { + pm_options_t *options = xcalloc(1, sizeof(pm_options_t)); + if (options == NULL) abort(); + return options; +} + +/** + * Free the internal memory associated with the options. + */ +void +pm_options_cleanup(pm_options_t *options) { + pm_string_cleanup(&options->filepath); + pm_string_cleanup(&options->encoding); + + for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { + pm_options_scope_t *scope = &options->scopes[scope_index]; + + for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { + pm_string_cleanup(&scope->locals[local_index]); + } + + xfree_sized(scope->locals, scope->locals_count * sizeof(pm_string_t)); + } + + xfree_sized(options->scopes, options->scopes_count * sizeof(pm_options_scope_t)); +} + +/** + * Free both the held memory of the given options struct and the struct itself. + * + * @param options The options struct to free. + */ +void +pm_options_free(pm_options_t *options) { + pm_options_cleanup(options); + xfree_sized(options, sizeof(pm_options_t)); +} + +/** + * Set the shebang callback option on the given options struct. + */ +void +pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) { + options->shebang_callback = shebang_callback; + options->shebang_callback_data = shebang_callback_data; +} + +/** + * Get the filepath option on the given options struct. + */ +const pm_string_t * +pm_options_filepath(const pm_options_t *options) { + return &options->filepath; +} /** * Set the filepath option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_filepath_set(pm_options_t *options, const char *filepath) { pm_string_constant_init(&options->filepath, filepath, strlen(filepath)); } @@ -11,31 +80,31 @@ pm_options_filepath_set(pm_options_t *options, const char *filepath) { /** * Set the encoding option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_encoding_set(pm_options_t *options, const char *encoding) { pm_string_constant_init(&options->encoding, encoding, strlen(encoding)); } /** - * Set the line option on the given options struct. + * Set the encoding_locked option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void -pm_options_line_set(pm_options_t *options, int32_t line) { - options->line = line; +void +pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) { + options->encoding_locked = encoding_locked; } /** - * Set the offset option on the given options struct. + * Set the line option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void -pm_options_offset_set(pm_options_t *options, uint32_t offset) { - options->offset = offset; +void +pm_options_line_set(pm_options_t *options, int32_t line) { + options->line = line; } /** * Set the frozen string literal option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) { options->frozen_string_literal = frozen_string_literal ? PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED : PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED; } @@ -43,43 +112,137 @@ pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_l /** * Sets the command line option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_command_line_set(pm_options_t *options, uint8_t command_line) { options->command_line = command_line; } /** + * Checks if the given slice represents a number. + */ +static PRISM_INLINE bool +is_number(const char *string, size_t length) { + return pm_strspn_decimal_digit((const uint8_t *) string, (ptrdiff_t) length) == length; +} + +/** * Set the version option on the given options struct by parsing the given * string. If the string contains an invalid option, this returns false. * Otherwise, it returns true. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_options_version_set(pm_options_t *options, const char *version, size_t length) { - if (version == NULL && length == 0) { + if (version == NULL) { options->version = PM_OPTIONS_VERSION_LATEST; return true; } - if (length == 5) { - if (strncmp(version, "3.3.0", length) == 0) { - options->version = PM_OPTIONS_VERSION_CRUBY_3_3_0; + if (length == 3) { + if (strncmp(version, "3.3", 3) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; return true; } - if (strncmp(version, "3.4.0", length) == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; + if (strncmp(version, "3.4", 3) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_4; + return true; + } + + if (strncmp(version, "3.5", 3) == 0 || strncmp(version, "4.0", 3) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_4_0; + return true; + } + + if (strncmp(version, "4.1", 3) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_4_1; return true; } + + return false; } - if (length == 6 && strncmp(version, "latest", length) == 0) { - options->version = PM_OPTIONS_VERSION_LATEST; - return true; + if (length >= 4 && is_number(version + 4, length - 4)) { + if (strncmp(version, "3.3.", 4) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; + return true; + } + + if (strncmp(version, "3.4.", 4) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_4; + return true; + } + + if (strncmp(version, "3.5.", 4) == 0 || strncmp(version, "4.0.", 4) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_4_0; + return true; + } + + if (strncmp(version, "4.1.", 4) == 0) { + options->version = PM_OPTIONS_VERSION_CRUBY_4_1; + return true; + } + } + + if (length == 6) { + if (strncmp(version, "latest", 6) == 0) { + options->version = PM_OPTIONS_VERSION_LATEST; + return true; + } } return false; } +/** + * Set the version option on the given options struct to the lowest version of + * Ruby that prism supports. + */ +void +pm_options_version_set_lowest(pm_options_t *options) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; +} + +/** + * Set the version option on the given options struct to the highest version of + * Ruby that prism supports. + */ +void +pm_options_version_set_highest(pm_options_t *options) { + options->version = PM_OPTIONS_VERSION_LATEST; +} + +/** + * Set the main script option on the given options struct. + */ +void +pm_options_main_script_set(pm_options_t *options, bool main_script) { + options->main_script = main_script; +} + +/** + * Set the partial script option on the given options struct. + */ +void +pm_options_partial_script_set(pm_options_t *options, bool partial_script) { + options->partial_script = partial_script; +} + +/** + * Get the freeze option on the given options struct. + */ +bool +pm_options_freeze(const pm_options_t *options) { + return options->freeze; +} + +/** + * Set the freeze option on the given options struct. + */ +void +pm_options_freeze_set(pm_options_t *options, bool freeze) { + options->freeze = freeze; +} + // For some reason, GCC analyzer thinks we're leaking allocated scopes and // locals here, even though we definitely aren't. This is a false positive. // Ideally we wouldn't need to suppress this. @@ -91,7 +254,7 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length /** * Allocate and zero out the scopes array on the given options struct. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count) { options->scopes_count = scopes_count; options->scopes = xcalloc(scopes_count, sizeof(pm_options_scope_t)); @@ -99,10 +262,20 @@ pm_options_scopes_init(pm_options_t *options, size_t scopes_count) { } /** - * Return a pointer to the scope at the given index within the given options. + * Return a constant pointer to the scope at the given index within the given + * options. */ -PRISM_EXPORTED_FUNCTION const pm_options_scope_t * -pm_options_scope_get(const pm_options_t *options, size_t index) { +const pm_options_scope_t * +pm_options_scope(const pm_options_t *options, size_t index) { + return &options->scopes[index]; +} + +/** + * Return a mutable pointer to the scope at the given index within the given + * options. + */ +pm_options_scope_t * +pm_options_scope_mut(pm_options_t *options, size_t index) { return &options->scopes[index]; } @@ -110,40 +283,38 @@ pm_options_scope_get(const pm_options_t *options, size_t index) { * Create a new options scope struct. This will hold a set of locals that are in * scope surrounding the code that is being parsed. */ -PRISM_EXPORTED_FUNCTION bool +void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) { scope->locals_count = locals_count; scope->locals = xcalloc(locals_count, sizeof(pm_string_t)); - return scope->locals != NULL; + scope->forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE; + if (scope->locals == NULL) abort(); } /** - * Return a pointer to the local at the given index within the given scope. + * Return a constant pointer to the local at the given index within the given + * scope. */ -PRISM_EXPORTED_FUNCTION const pm_string_t * -pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { +const pm_string_t * +pm_options_scope_local(const pm_options_scope_t *scope, size_t index) { return &scope->locals[index]; } /** - * Free the internal memory associated with the options. + * Return a mutable pointer to the local at the given index within the given + * scope. */ -PRISM_EXPORTED_FUNCTION void -pm_options_free(pm_options_t *options) { - pm_string_free(&options->filepath); - pm_string_free(&options->encoding); - - for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { - pm_options_scope_t *scope = &options->scopes[scope_index]; - - for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { - pm_string_free(&scope->locals[local_index]); - } - - xfree(scope->locals); - } +pm_string_t * +pm_options_scope_local_mut(pm_options_scope_t *scope, size_t index) { + return &scope->locals[index]; +} - xfree(options->scopes); +/** + * Set the forwarding option on the given scope struct. + */ +void +pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { + scope->forwarding = forwarding; } /** @@ -201,9 +372,6 @@ pm_options_read(pm_options_t *options, const char *data) { options->line = pm_options_read_s32(data); data += 4; - options->offset = pm_options_read_u32(data); - data += 4; - uint32_t encoding_length = pm_options_read_u32(data); data += 4; @@ -215,6 +383,10 @@ pm_options_read(pm_options_t *options, const char *data) { options->frozen_string_literal = (int8_t) *data++; options->command_line = (uint8_t) *data++; options->version = (pm_options_version_t) *data++; + options->encoding_locked = ((uint8_t) *data++) > 0; + options->main_script = ((uint8_t) *data++) > 0; + options->partial_script = ((uint8_t) *data++) > 0; + options->freeze = ((uint8_t) *data++) > 0; uint32_t scopes_count = pm_options_read_u32(data); data += 4; @@ -227,10 +399,10 @@ pm_options_read(pm_options_t *options, const char *data) { data += 4; pm_options_scope_t *scope = &options->scopes[scope_index]; - if (!pm_options_scope_init(scope, locals_count)) { - pm_options_free(options); - return; - } + pm_options_scope_init(scope, locals_count); + + uint8_t forwarding = (uint8_t) *data++; + pm_options_scope_forwarding_set(&options->scopes[scope_index], forwarding); for (size_t local_index = 0; local_index < locals_count; local_index++) { uint32_t local_length = pm_options_read_u32(data); |
