// This is similar to alloca in C.
from_stack :: macro (size: u32) -> rawptr {
+ // This should do something about the alignment...
+ // Everything so far has assume that the stack is aligned to 16 bytes.
defer __stack_top = ~~(cast(^u8) __stack_top + size);
return __stack_top;
}
--- /dev/null
+package core.arg_parse
+
+use package core
+
+arg_parse :: (c_args: [] cstr, output: any) -> bool {
+ arg_iter := iter.as_iterator(c_args)
+ |> iter.map((x) => string.from_cstr(*x));
+ defer arg_iter.close(arg_iter.data);
+
+ use type_info;
+
+ ptr_type := cast(^Type_Info_Pointer) get_type_info(output.type);
+ if ptr_type.kind != .Pointer do return false;
+
+ arg_type := cast(^Type_Info_Struct) get_type_info(ptr_type.to);
+ if arg_type.kind != .Struct do return false;
+
+ data_base := *cast(^rawptr) output.data;
+
+ for #no_close arg: arg_iter {
+ for ^member: arg_type.members {
+ for ^tag: member.tags {
+ if tag.type != str do continue;
+
+ to_match := *cast(^str) tag.data;
+ if arg != to_match do continue;
+
+ switch member.type {
+ case bool {
+ *(cast(^bool) (cast(^u8) data_base + member.offset)) = !*(cast(^bool) (cast(^u8) data_base + member.offset));
+ }
+
+ case i32 {
+ value_str, success := iter.take_one(arg_iter, no_close=true);
+ if !success do return false;
+
+ value := conv.str_to_i64(value_str);
+ *(cast(^i32) (cast(^u8) data_base + member.offset)) = ~~value;
+ }
+
+ case str {
+ value, success := iter.take_one(arg_iter, no_close=true);
+ if !success do return false;
+
+ *(cast(^str) (cast(^u8) data_base + member.offset)) = value;
+ }
+
+ case #default {
+ printf("Unsupported argument type, {}.\n", output.type);
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
\ No newline at end of file
#load "./type_info/helper"
+#load "./arg_parse"
+
#local runtime :: package runtime
#if runtime.runtime == .Wasi || runtime.runtime == .Onyx {
#load "./os/file"
compile_only := false;
}
-args_parse :: (c_args: [] cstr, output: ^Settings) -> bool {
- arg_iter := iter.as_iterator(c_args)
- |> iter.map((x) => string.from_cstr(*x));
-
- use type_info;
-
- arg_type := cast(^Type_Info_Struct) get_type_info(typeof *output);
- if arg_type.kind != .Struct do return false;
-
- for #no_close arg: arg_iter {
- for ^member: arg_type.members {
- for ^tag: member.tags {
- if tag.type != str do continue;
-
- to_match := *cast(^str) tag.data;
- if arg != to_match do continue;
-
- switch member.type {
- case bool {
- // Should there be a way to specify a variable to be false?
- *(cast(^bool) (cast(^u8) output + member.offset)) = true;
- }
-
- case i32 {
- value_str, success := iter.take_one(arg_iter);
- if !success do return false;
-
- value := conv.str_to_i64(value_str);
- *(cast(^i32) (cast(^u8) output + member.offset)) = ~~value;
- }
-
- case str {
- value, success := iter.take_one(arg_iter);
- if !success do return false;
-
- *(cast(^str) (cast(^u8) output + member.offset)) = value;
- }
-
- case #default {
- println("Unsupported argument type.");
- return false;
- }
- }
- }
- }
- }
-
- // This has to be done explicitly beacuse the iter.take_one function
- // can close the iterator if it runs out during the taking.
- arg_iter.close(arg_iter.data);
- return true;
-}
-
main :: (args) => {
- args_parse(args, ^settings);
+ arg_parse.arg_parse(args, ^settings);
printf("Using {p*}\n", ^settings);
Execution_Context :: struct {