Ruby: prism/options.c Source File

Ruby 3.4.7p58 (2025-10-08 revision 7a5688e2a27668e48f8d6ff4af5b2208b98a2f5e)

options.c
1#include "prism/options.h"
2
6 PRISM_EXPORTED_FUNCTION void
7pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) {
8 options->shebang_callback = shebang_callback;
9 options->shebang_callback_data = shebang_callback_data;
10}
11
15 PRISM_EXPORTED_FUNCTION void
16pm_options_filepath_set(pm_options_t *options, const char *filepath) {
17 pm_string_constant_init(&options->filepath, filepath, strlen(filepath));
18}
19
23 PRISM_EXPORTED_FUNCTION void
24pm_options_encoding_set(pm_options_t *options, const char *encoding) {
25 pm_string_constant_init(&options->encoding, encoding, strlen(encoding));
26}
27
31 PRISM_EXPORTED_FUNCTION void
32pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) {
33 options->encoding_locked = encoding_locked;
34}
35
39 PRISM_EXPORTED_FUNCTION void
40pm_options_line_set(pm_options_t *options, int32_t line) {
41 options->line = line;
42}
43
47 PRISM_EXPORTED_FUNCTION void
48pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) {
49 options->frozen_string_literal = frozen_string_literal ? PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED : PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED;
50}
51
55 PRISM_EXPORTED_FUNCTION void
56pm_options_command_line_set(pm_options_t *options, uint8_t command_line) {
57 options->command_line = command_line;
58}
59
63static inline bool
64is_number(const char *string, size_t length) {
65 return pm_strspn_decimal_digit((const uint8_t *) string, (ptrdiff_t) length) == length;
66}
67
73 PRISM_EXPORTED_FUNCTION bool
74pm_options_version_set(pm_options_t *options, const char *version, size_t length) {
75 if (version == NULL) {
76 options->version = PM_OPTIONS_VERSION_LATEST;
77 return true;
78 }
79
80 if (length == 3) {
81 if (strncmp(version, "3.3", 3) == 0) {
82 options->version = PM_OPTIONS_VERSION_CRUBY_3_3;
83 return true;
84 }
85
86 if (strncmp(version, "3.4", 3) == 0) {
87 options->version = PM_OPTIONS_VERSION_CRUBY_3_4;
88 return true;
89 }
90
91 if (strncmp(version, "3.5", 3) == 0) {
92 options->version = PM_OPTIONS_VERSION_CRUBY_3_5;
93 return true;
94 }
95
96 return false;
97 }
98
99 if (length >= 4) {
100 if (strncmp(version, "3.3.", 4) == 0 && is_number(version + 4, length - 4)) {
101 options->version = PM_OPTIONS_VERSION_CRUBY_3_3;
102 return true;
103 }
104
105 if (strncmp(version, "3.4.", 4) == 0 && is_number(version + 4, length - 4)) {
106 options->version = PM_OPTIONS_VERSION_CRUBY_3_4;
107 return true;
108 }
109
110 if (strncmp(version, "3.5.", 4) == 0 && is_number(version + 4, length - 4)) {
111 options->version = PM_OPTIONS_VERSION_CRUBY_3_5;
112 return true;
113 }
114 }
115
116 if (length >= 6) {
117 if (strncmp(version, "latest", 7) == 0) { // 7 to compare the \0 as well
118 options->version = PM_OPTIONS_VERSION_LATEST;
119 return true;
120 }
121 }
122
123 return false;
124}
125
129 PRISM_EXPORTED_FUNCTION void
130pm_options_main_script_set(pm_options_t *options, bool main_script) {
131 options->main_script = main_script;
132}
133
137 PRISM_EXPORTED_FUNCTION void
138pm_options_partial_script_set(pm_options_t *options, bool partial_script) {
139 options->partial_script = partial_script;
140}
141
145 PRISM_EXPORTED_FUNCTION void
146pm_options_freeze_set(pm_options_t *options, bool freeze) {
147 options->freeze = freeze;
148}
149
150// For some reason, GCC analyzer thinks we're leaking allocated scopes and
151// locals here, even though we definitely aren't. This is a false positive.
152// Ideally we wouldn't need to suppress this.
153#if defined(__GNUC__) && (__GNUC__ >= 10)
154#pragma GCC diagnostic push
155#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
156#endif
157
161 PRISM_EXPORTED_FUNCTION bool
162pm_options_scopes_init(pm_options_t *options, size_t scopes_count) {
163 options->scopes_count = scopes_count;
164 options->scopes = xcalloc(scopes_count, sizeof(pm_options_scope_t));
165 return options->scopes != NULL;
166}
167
171 PRISM_EXPORTED_FUNCTION const pm_options_scope_t *
172pm_options_scope_get(const pm_options_t *options, size_t index) {
173 return &options->scopes[index];
174}
175
180 PRISM_EXPORTED_FUNCTION bool
181pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) {
182 scope->locals_count = locals_count;
183 scope->locals = xcalloc(locals_count, sizeof(pm_string_t));
184 scope->forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE;
185 return scope->locals != NULL;
186}
187
191 PRISM_EXPORTED_FUNCTION const pm_string_t *
192pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) {
193 return &scope->locals[index];
194}
195
199 PRISM_EXPORTED_FUNCTION void
200pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) {
201 scope->forwarding = forwarding;
202}
203
207 PRISM_EXPORTED_FUNCTION void
208pm_options_free(pm_options_t *options) {
209 pm_string_free(&options->filepath);
210 pm_string_free(&options->encoding);
211
212 for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) {
213 pm_options_scope_t *scope = &options->scopes[scope_index];
214
215 for (size_t local_index = 0; local_index < scope->locals_count; local_index++) {
216 pm_string_free(&scope->locals[local_index]);
217 }
218
219 xfree(scope->locals);
220 }
221
222 xfree(options->scopes);
223}
224
230static uint32_t
231pm_options_read_u32(const char *data) {
232 if (((uintptr_t) data) % sizeof(uint32_t) == 0) {
233 return *((uint32_t *) data);
234 } else {
235 uint32_t value;
236 memcpy(&value, data, sizeof(uint32_t));
237 return value;
238 }
239}
240
246static int32_t
247pm_options_read_s32(const char *data) {
248 if (((uintptr_t) data) % sizeof(int32_t) == 0) {
249 return *((int32_t *) data);
250 } else {
251 int32_t value;
252 memcpy(&value, data, sizeof(int32_t));
253 return value;
254 }
255}
256
264void
265pm_options_read(pm_options_t *options, const char *data) {
266 options->line = 1; // default
267 if (data == NULL) return;
268
269 uint32_t filepath_length = pm_options_read_u32(data);
270 data += 4;
271
272 if (filepath_length > 0) {
273 pm_string_constant_init(&options->filepath, data, filepath_length);
274 data += filepath_length;
275 }
276
277 options->line = pm_options_read_s32(data);
278 data += 4;
279
280 uint32_t encoding_length = pm_options_read_u32(data);
281 data += 4;
282
283 if (encoding_length > 0) {
284 pm_string_constant_init(&options->encoding, data, encoding_length);
285 data += encoding_length;
286 }
287
288 options->frozen_string_literal = (int8_t) *data++;
289 options->command_line = (uint8_t) *data++;
290 options->version = (pm_options_version_t) *data++;
291 options->encoding_locked = ((uint8_t) *data++) > 0;
292 options->main_script = ((uint8_t) *data++) > 0;
293 options->partial_script = ((uint8_t) *data++) > 0;
294 options->freeze = ((uint8_t) *data++) > 0;
295
296 uint32_t scopes_count = pm_options_read_u32(data);
297 data += 4;
298
299 if (scopes_count > 0) {
300 if (!pm_options_scopes_init(options, scopes_count)) return;
301
302 for (size_t scope_index = 0; scope_index < scopes_count; scope_index++) {
303 uint32_t locals_count = pm_options_read_u32(data);
304 data += 4;
305
306 pm_options_scope_t *scope = &options->scopes[scope_index];
307 if (!pm_options_scope_init(scope, locals_count)) {
308 pm_options_free(options);
309 return;
310 }
311
312 uint8_t forwarding = (uint8_t) *data++;
313 pm_options_scope_forwarding_set(&options->scopes[scope_index], forwarding);
314
315 for (size_t local_index = 0; local_index < locals_count; local_index++) {
316 uint32_t local_length = pm_options_read_u32(data);
317 data += 4;
318
319 pm_string_constant_init(&scope->locals[local_index], data, local_length);
320 data += local_length;
321 }
322 }
323 }
324}
325
326#if defined(__GNUC__) && (__GNUC__ >= 10)
327#pragma GCC diagnostic pop
328#endif
xfree
#define xfree
Old name of ruby_xfree.
Definition xmalloc.h:58
xcalloc
#define xcalloc
Old name of ruby_xcalloc.
Definition xmalloc.h:55
options.h
The options that can be passed to parsing.
pm_options_scope_t
struct pm_options_scope pm_options_scope_t
A scope of locals surrounding the code that is being parsed.
pm_options_t
struct pm_options pm_options_t
The options that can be passed to the parser.
pm_options_shebang_callback_t
void(* pm_options_shebang_callback_t)(struct pm_options *options, const uint8_t *source, size_t length, void *shebang_callback_data)
The callback called when additional switches are found in a shebang comment that need to be processed...
Definition options.h:77
PM_OPTIONS_SCOPE_FORWARDING_NONE
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_NONE
The default value for parameters.
Definition options.h:48
PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED
#define PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED
String literals should be made frozen.
Definition options.h:20
PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED
#define PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED
String literals should be made mutable.
Definition options.h:31
pm_options_version_t
pm_options_version_t
The version of Ruby syntax that we should be parsing with.
Definition options.h:84
PM_OPTIONS_VERSION_CRUBY_3_3
@ PM_OPTIONS_VERSION_CRUBY_3_3
The vendored version of prism in CRuby 3.3.x.
Definition options.h:89
PM_OPTIONS_VERSION_LATEST
@ PM_OPTIONS_VERSION_LATEST
The current version of prism.
Definition options.h:98
PM_OPTIONS_VERSION_CRUBY_3_4
@ PM_OPTIONS_VERSION_CRUBY_3_4
The vendored version of prism in CRuby 3.4.x.
Definition options.h:92
PM_OPTIONS_VERSION_CRUBY_3_5
@ PM_OPTIONS_VERSION_CRUBY_3_5
The vendored version of prism in CRuby 3.5.x.
Definition options.h:95
PRISM_EXPORTED_FUNCTION
#define PRISM_EXPORTED_FUNCTION
By default, we compile with -fvisibility=hidden.
Definition defines.h:53
pm_options_scope::locals_count
size_t locals_count
The number of locals in the scope.
Definition options.h:38
pm_options_scope::forwarding
uint8_t forwarding
Flags for the set of forwarding parameters in this scope.
Definition options.h:44
pm_options_scope::locals
pm_string_t * locals
The names of the locals in the scope.
Definition options.h:41
pm_options::pm_options_shebang_callback_set
PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data)
Set the shebang callback option on the given options struct.
Definition options.c:7
pm_options::pm_options_encoding_set
PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding)
Set the encoding option on the given options struct.
Definition options.c:24
pm_options::pm_options_free
PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options)
Free the internal memory associated with the options.
Definition options.c:208
pm_options::freeze
bool freeze
Whether or not the parser should freeze the nodes that it creates.
Definition options.h:193
pm_options::pm_options_partial_script_set
PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script)
Set the partial script option on the given options struct.
Definition options.c:138
pm_options::command_line
uint8_t command_line
A bitset of the various options that were set on the command line.
Definition options.h:153
pm_options::pm_options_main_script_set
PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script)
Set the main script option on the given options struct.
Definition options.c:130
pm_options::shebang_callback_data
void * shebang_callback_data
Any additional data that should be passed along to the shebang callback if one was set.
Definition options.h:115
pm_options::encoding_locked
bool encoding_locked
Whether or not the encoding magic comments should be respected.
Definition options.h:169
pm_options::scopes
pm_options_scope_t * scopes
The scopes surrounding the code that is being parsed.
Definition options.h:143
pm_options::pm_options_scope_local_get
PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index)
Return a pointer to the local at the given index within the given scope.
Definition options.c:192
pm_options::main_script
bool main_script
When the file being parsed is the main script, the shebang will be considered for command-line flags ...
Definition options.h:176
pm_options::encoding
pm_string_t encoding
The name of the encoding that the source file is in.
Definition options.h:130
pm_options::line
int32_t line
The line within the file that the parse starts on.
Definition options.h:124
pm_options::shebang_callback
pm_options_shebang_callback_t shebang_callback
The callback to call when additional switches are found in a shebang comment.
Definition options.h:109
pm_options::pm_options_version_set
PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length)
Set the version option on the given options struct by parsing the given string.
Definition options.c:74
pm_options::pm_options_scope_init
PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count)
Create a new options scope struct.
Definition options.c:181
pm_options::pm_options_line_set
PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line)
Set the line option on the given options struct.
Definition options.c:40
pm_options::pm_options_scope_get
PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index)
Return a pointer to the scope at the given index within the given options.
Definition options.c:172
pm_options::pm_options_freeze_set
PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze)
Set the freeze option on the given options struct.
Definition options.c:146
pm_options::pm_options_encoding_locked_set
PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked)
Set the encoding_locked option on the given options struct.
Definition options.c:32
pm_options::frozen_string_literal
int8_t frozen_string_literal
Whether or not the frozen string literal option has been set.
Definition options.h:162
pm_options::pm_options_frozen_string_literal_set
PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal)
Set the frozen string literal option on the given options struct.
Definition options.c:48
pm_options::partial_script
bool partial_script
When the file being parsed is considered a "partial" script, jumps will not be marked as errors if th...
Definition options.h:186
pm_options::scopes_count
size_t scopes_count
The number of scopes surrounding the code that is being parsed.
Definition options.h:135
pm_options::filepath
pm_string_t filepath
The name of the file that is currently being parsed.
Definition options.h:118
pm_options::pm_options_command_line_set
PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line)
Sets the command line option on the given options struct.
Definition options.c:56
pm_options::pm_options_filepath_set
PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath)
Set the filepath option on the given options struct.
Definition options.c:16
pm_options::version
pm_options_version_t version
The version of prism that we should be parsing with.
Definition options.h:150
pm_options::pm_options_scopes_init
PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count)
Allocate and zero out the scopes array on the given options struct.
Definition options.c:162
pm_options::pm_options_scope_forwarding_set
PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding)
Set the forwarding option on the given scope struct.
Definition options.c:200
pm_string_t
A generic string type that can have various ownership semantics.
Definition pm_string.h:33