2023-11-02 18:15:37 +03:00
|
|
|
/**
|
|
|
|
* @file options.h
|
|
|
|
*
|
|
|
|
* The options that can be passed to parsing.
|
|
|
|
*/
|
|
|
|
#ifndef PRISM_OPTIONS_H
|
|
|
|
#define PRISM_OPTIONS_H
|
|
|
|
|
|
|
|
#include "prism/defines.h"
|
|
|
|
#include "prism/util/pm_string.h"
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
2024-03-12 14:17:55 +03:00
|
|
|
/**
|
|
|
|
* String literals should be made frozen.
|
|
|
|
*/
|
|
|
|
#define PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED ((int8_t) -1)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* String literals may be frozen or mutable depending on the implementation
|
|
|
|
* default.
|
|
|
|
*/
|
|
|
|
#define PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET ((int8_t) 0)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* String literals should be made mutable.
|
|
|
|
*/
|
|
|
|
#define PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED ((int8_t) 1)
|
|
|
|
|
2023-11-02 18:15:37 +03:00
|
|
|
/**
|
|
|
|
* A scope of locals surrounding the code that is being parsed.
|
|
|
|
*/
|
|
|
|
typedef struct pm_options_scope {
|
|
|
|
/** The number of locals in the scope. */
|
|
|
|
size_t locals_count;
|
|
|
|
|
|
|
|
/** The names of the locals in the scope. */
|
|
|
|
pm_string_t *locals;
|
|
|
|
} pm_options_scope_t;
|
|
|
|
|
2024-01-02 19:18:29 +03:00
|
|
|
/**
|
2024-01-17 18:44:37 +03:00
|
|
|
* The version of Ruby syntax that we should be parsing with. This is used to
|
|
|
|
* allow consumers to specify which behavior they want in case they need to
|
|
|
|
* parse in the same way as a specific version of CRuby would have.
|
2024-01-02 19:18:29 +03:00
|
|
|
*/
|
|
|
|
typedef enum {
|
|
|
|
/** The current version of prism. */
|
|
|
|
PM_OPTIONS_VERSION_LATEST = 0,
|
|
|
|
|
2024-05-02 01:54:05 +03:00
|
|
|
/** The vendored version of prism in CRuby 3.3.x. */
|
|
|
|
PM_OPTIONS_VERSION_CRUBY_3_3 = 1
|
2024-01-02 19:18:29 +03:00
|
|
|
} pm_options_version_t;
|
|
|
|
|
2023-11-02 18:15:37 +03:00
|
|
|
/**
|
|
|
|
* The options that can be passed to the parser.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
/** The name of the file that is currently being parsed. */
|
2023-11-02 21:01:20 +03:00
|
|
|
pm_string_t filepath;
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The line within the file that the parse starts on. This value is
|
2024-01-31 15:07:00 +03:00
|
|
|
* 1-indexed.
|
2023-11-02 18:15:37 +03:00
|
|
|
*/
|
2023-11-29 13:46:33 +03:00
|
|
|
int32_t line;
|
2023-11-02 18:15:37 +03:00
|
|
|
|
2023-11-02 21:01:20 +03:00
|
|
|
/**
|
|
|
|
* The name of the encoding that the source file is in. Note that this must
|
|
|
|
* correspond to a name that can be found with Encoding.find in Ruby.
|
|
|
|
*/
|
|
|
|
pm_string_t encoding;
|
|
|
|
|
2023-11-02 18:15:37 +03:00
|
|
|
/**
|
|
|
|
* The number of scopes surrounding the code that is being parsed.
|
|
|
|
*/
|
|
|
|
size_t scopes_count;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The scopes surrounding the code that is being parsed. For most parses
|
|
|
|
* this will be NULL, but for evals it will be the locals that are in scope
|
2024-01-17 21:11:09 +03:00
|
|
|
* surrounding the eval. Scopes are ordered from the outermost scope to the
|
|
|
|
* innermost one.
|
2023-11-02 18:15:37 +03:00
|
|
|
*/
|
|
|
|
pm_options_scope_t *scopes;
|
|
|
|
|
2024-01-02 19:18:29 +03:00
|
|
|
/**
|
|
|
|
* The version of prism that we should be parsing with. This is used to
|
|
|
|
* allow consumers to specify which behavior they want in case they need to
|
|
|
|
* parse exactly as a specific version of CRuby.
|
|
|
|
*/
|
|
|
|
pm_options_version_t version;
|
|
|
|
|
2024-02-28 21:56:10 +03:00
|
|
|
/** A bitset of the various options that were set on the command line. */
|
|
|
|
uint8_t command_line;
|
|
|
|
|
2024-03-12 14:17:55 +03:00
|
|
|
/**
|
|
|
|
* Whether or not the frozen string literal option has been set.
|
|
|
|
* May be:
|
|
|
|
* - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED
|
|
|
|
* - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED
|
|
|
|
* - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET
|
|
|
|
*/
|
|
|
|
int8_t frozen_string_literal;
|
2024-02-28 21:56:10 +03:00
|
|
|
} pm_options_t;
|
2024-02-27 06:11:33 +03:00
|
|
|
|
2024-02-28 21:56:10 +03:00
|
|
|
/**
|
|
|
|
* A bit representing whether or not the command line -a option was set. -a
|
|
|
|
* splits the input line $_ into $F.
|
|
|
|
*/
|
|
|
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_A = 0x1;
|
2024-02-27 06:11:33 +03:00
|
|
|
|
2024-02-28 21:56:10 +03:00
|
|
|
/**
|
|
|
|
* A bit representing whether or not the command line -e option was set. -e
|
|
|
|
* allow the user to specify a script to be executed. This is necessary for
|
|
|
|
* prism to know because certain warnings are not generated when -e is used.
|
|
|
|
*/
|
|
|
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_E = 0x2;
|
2024-02-27 06:11:33 +03:00
|
|
|
|
2024-02-28 21:56:10 +03:00
|
|
|
/**
|
|
|
|
* A bit representing whether or not the command line -l option was set. -l
|
|
|
|
* chomps the input line by default.
|
|
|
|
*/
|
|
|
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_L = 0x4;
|
2024-02-27 06:11:33 +03:00
|
|
|
|
2024-02-28 21:56:10 +03:00
|
|
|
/**
|
|
|
|
* A bit representing whether or not the command line -n option was set. -n
|
|
|
|
* wraps the script in a while gets loop.
|
|
|
|
*/
|
|
|
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_N = 0x8;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A bit representing whether or not the command line -p option was set. -p
|
|
|
|
* prints the value of $_ at the end of each loop.
|
|
|
|
*/
|
|
|
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_P = 0x10;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A bit representing whether or not the command line -x option was set. -x
|
|
|
|
* searches the input file for a shebang that matches the current Ruby engine.
|
|
|
|
*/
|
|
|
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20;
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the filepath option on the given options struct.
|
|
|
|
*
|
|
|
|
* @param options The options struct to set the filepath on.
|
|
|
|
* @param filepath The filepath to set.
|
|
|
|
*/
|
2023-11-02 21:01:20 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
2023-11-02 21:01:20 +03:00
|
|
|
* Set the line option on the given options struct.
|
2023-11-02 18:15:37 +03:00
|
|
|
*
|
2023-11-02 21:01:20 +03:00
|
|
|
* @param options The options struct to set the line on.
|
|
|
|
* @param line The line to set.
|
2023-11-02 18:15:37 +03:00
|
|
|
*/
|
2023-11-29 13:46:33 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
2023-11-02 21:01:20 +03:00
|
|
|
* Set the encoding option on the given options struct.
|
2023-11-02 18:15:37 +03:00
|
|
|
*
|
2023-11-02 21:01:20 +03:00
|
|
|
* @param options The options struct to set the encoding on.
|
|
|
|
* @param encoding The encoding to set.
|
2023-11-02 18:15:37 +03:00
|
|
|
*/
|
2023-11-02 21:01:20 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the frozen string literal option on the given options struct.
|
|
|
|
*
|
|
|
|
* @param options The options struct to set the frozen string literal value on.
|
|
|
|
* @param frozen_string_literal The frozen string literal value to set.
|
|
|
|
*/
|
2023-11-02 21:01:20 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
2024-02-27 06:11:33 +03:00
|
|
|
/**
|
2024-02-28 21:56:10 +03:00
|
|
|
* Sets the command line option on the given options struct.
|
2024-02-27 06:11:33 +03:00
|
|
|
*
|
2024-02-28 21:56:10 +03:00
|
|
|
* @param options The options struct to set the command line option on.
|
|
|
|
* @param command_line The command_line value to set.
|
2024-02-27 06:11:33 +03:00
|
|
|
*/
|
2024-02-28 21:56:10 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line);
|
2024-02-27 06:11:33 +03:00
|
|
|
|
2024-01-02 19:18:29 +03:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* @param options The options struct to set the version on.
|
|
|
|
* @param version The version to set.
|
|
|
|
* @param length The length of the version string.
|
|
|
|
* @return Whether or not the version was parsed successfully.
|
|
|
|
*/
|
|
|
|
PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length);
|
|
|
|
|
2023-11-02 18:15:37 +03:00
|
|
|
/**
|
|
|
|
* Allocate and zero out the scopes array on the given options struct.
|
|
|
|
*
|
|
|
|
* @param options The options struct to initialize the scopes array on.
|
|
|
|
* @param scopes_count The number of scopes to allocate.
|
2024-02-17 23:51:39 +03:00
|
|
|
* @return Whether or not the scopes array was initialized successfully.
|
2023-11-02 18:15:37 +03:00
|
|
|
*/
|
2024-02-17 23:51:39 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a pointer to the scope at the given index within the given options.
|
|
|
|
*
|
|
|
|
* @param options The options struct to get the scope from.
|
|
|
|
* @param index The index of the scope to get.
|
|
|
|
* @return A pointer to the scope at the given index.
|
|
|
|
*/
|
2023-11-02 21:01:20 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new options scope struct. This will hold a set of locals that are in
|
|
|
|
* scope surrounding the code that is being parsed.
|
|
|
|
*
|
|
|
|
* @param scope The scope struct to initialize.
|
|
|
|
* @param locals_count The number of locals to allocate.
|
2024-02-17 23:51:39 +03:00
|
|
|
* @return Whether or not the scope was initialized successfully.
|
2023-11-02 18:15:37 +03:00
|
|
|
*/
|
2024-02-17 23:51:39 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a pointer to the local at the given index within the given scope.
|
|
|
|
*
|
|
|
|
* @param scope The scope struct to get the local from.
|
|
|
|
* @param index The index of the local to get.
|
|
|
|
* @return A pointer to the local at the given index.
|
|
|
|
*/
|
2023-11-02 21:01:20 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Free the internal memory associated with the options.
|
|
|
|
*
|
|
|
|
* @param options The options struct whose internal memory should be freed.
|
|
|
|
*/
|
2023-11-02 21:01:20 +03:00
|
|
|
PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deserialize an options struct from the given binary string. This is used to
|
|
|
|
* pass options to the parser from an FFI call so that consumers of the library
|
|
|
|
* from an FFI perspective don't have to worry about the structure of our
|
|
|
|
* options structs. Since the source of these calls will be from Ruby
|
|
|
|
* implementation internals we assume it is from a trusted source.
|
|
|
|
*
|
|
|
|
* `data` is assumed to be a valid pointer pointing to well-formed data. The
|
|
|
|
* layout of this data should be the same every time, and is described below:
|
|
|
|
*
|
|
|
|
* | # bytes | field |
|
|
|
|
* | ------- | -------------------------- |
|
2023-11-02 22:42:18 +03:00
|
|
|
* | `4` | the length of the filepath |
|
2023-11-02 21:01:20 +03:00
|
|
|
* | ... | the filepath bytes |
|
2023-11-02 22:42:18 +03:00
|
|
|
* | `4` | the line number |
|
|
|
|
* | `4` | the length the encoding |
|
2023-11-02 21:01:20 +03:00
|
|
|
* | ... | the encoding bytes |
|
2023-11-02 22:42:18 +03:00
|
|
|
* | `1` | frozen string literal |
|
2024-02-27 06:11:33 +03:00
|
|
|
* | `1` | -p command line option |
|
|
|
|
* | `1` | -n command line option |
|
|
|
|
* | `1` | -l command line option |
|
|
|
|
* | `1` | -a command line option |
|
2024-01-02 19:18:29 +03:00
|
|
|
* | `1` | the version |
|
2023-11-02 22:42:18 +03:00
|
|
|
* | `4` | the number of scopes |
|
2023-11-02 21:01:20 +03:00
|
|
|
* | ... | the scopes |
|
|
|
|
*
|
2024-01-02 19:18:29 +03:00
|
|
|
* The version field is an enum, so it should be one of the following values:
|
|
|
|
*
|
|
|
|
* | value | version |
|
|
|
|
* | ----- | ------------------------- |
|
|
|
|
* | `0` | use the latest version of prism |
|
|
|
|
* | `1` | use the version of prism that is vendored in CRuby 3.3.0 |
|
|
|
|
*
|
2024-03-24 14:06:35 +03:00
|
|
|
* Each scope is laid out as follows:
|
2023-11-03 01:12:57 +03:00
|
|
|
*
|
2023-11-02 21:01:20 +03:00
|
|
|
* | # bytes | field |
|
|
|
|
* | ------- | -------------------------- |
|
2023-11-02 22:42:18 +03:00
|
|
|
* | `4` | the number of locals |
|
2023-11-02 21:01:20 +03:00
|
|
|
* | ... | the locals |
|
|
|
|
*
|
2024-03-24 14:06:35 +03:00
|
|
|
* Each local is laid out as follows:
|
2023-11-02 21:01:20 +03:00
|
|
|
*
|
|
|
|
* | # bytes | field |
|
|
|
|
* | ------- | -------------------------- |
|
2023-11-02 22:42:18 +03:00
|
|
|
* | `4` | the length of the local |
|
2023-11-02 21:01:20 +03:00
|
|
|
* | ... | the local bytes |
|
|
|
|
*
|
|
|
|
* Some additional things to note about this layout:
|
|
|
|
*
|
|
|
|
* * The filepath can have a length of 0, in which case we'll consider it an
|
|
|
|
* empty string.
|
|
|
|
* * The line number should be 0-indexed.
|
|
|
|
* * The encoding can have a length of 0, in which case we'll use the default
|
|
|
|
* encoding (UTF-8). If it's not 0, it should correspond to a name of an
|
|
|
|
* encoding that can be passed to `Encoding.find` in Ruby.
|
|
|
|
* * The frozen string literal and suppress warnings fields are booleans, so
|
|
|
|
* their values should be either 0 or 1.
|
|
|
|
* * The number of scopes can be 0.
|
|
|
|
*
|
|
|
|
* @param options The options struct to deserialize into.
|
|
|
|
* @param data The binary string to deserialize from.
|
|
|
|
*/
|
|
|
|
void pm_options_read(pm_options_t *options, const char *data);
|
2023-11-02 18:15:37 +03:00
|
|
|
|
|
|
|
#endif
|