diff --git a/tools/odinfmt/flag/flag.odin b/tools/odinfmt/flag/flag.odin deleted file mode 100644 index 6b2525717..000000000 --- a/tools/odinfmt/flag/flag.odin +++ /dev/null @@ -1,211 +0,0 @@ -package flag - -import "core:runtime" -import "core:strings" -import "core:reflect" -import "core:fmt" -import "core:mem" -import "core:strconv" - -Flag_Error :: enum { - None, - No_Base_Struct, - Arg_Error, - Arg_Unsupported_Field_Type, - Arg_Not_Defined, - Arg_Non_Optional, - Value_Parse_Error, - Tag_Error, -} - -Flag :: struct { - optional: bool, - type: ^runtime.Type_Info, - data: rawptr, - tag_ptr: rawptr, - parsed: bool, -} - -Flag_Context :: struct { - seen_flags: map[string]Flag, -} - -parse_args :: proc(ctx: ^Flag_Context, args: []string) -> Flag_Error { - - using runtime; - - args := args; - - for { - if len(args) == 0 { - return .None; - } - - arg := args[0]; - - if len(arg) < 2 || arg[0] != '-' { - return .Arg_Error; - } - - minus_count := 1; - - if arg[1] == '-' { - minus_count += 1; - - if len(arg) == 2 { - return .Arg_Error; - } - } - - name := arg[minus_count:]; - - if len(name) == 0 { - return .Arg_Error; - } - - args = args[1:]; - - assign_index := strings.index(name, "="); - - value := ""; - - if assign_index > 0 { - value = name[assign_index + 1:]; - name = name[0:assign_index]; - } - - flag := &ctx.seen_flags[name]; - - if flag == nil { - return .Arg_Not_Defined; - } - - if reflect.is_boolean(flag.type) { - tmp: b64 = true; - mem.copy(flag.data, &tmp, flag.type.size); - flag.parsed = true; - continue; - } else if value == "" { // must be in the next argument - if len(args) == 0 { - return .Arg_Error; - } - - value = args[0]; - args = args[1:]; - } - - #partial switch _ in flag.type.variant { - case Type_Info_Integer: - if v, ok := strconv.parse_int(value); ok { - mem.copy(flag.data, &v, flag.type.size); - } else { - return .Value_Parse_Error; - } - case Type_Info_String: - raw_string := cast(^mem.Raw_String)flag.data; - raw_string.data = strings.ptr_from_string(value); - raw_string.len = len(value); - case Type_Info_Float: - switch flag.type.size { - case 32: - if v, ok := strconv.parse_f32(value); ok { - mem.copy(flag.data, &v, flag.type.size); - } else { - return .Value_Parse_Error; - } - case 64: - if v, ok := strconv.parse_f64(value); ok { - mem.copy(flag.data, &v, flag.type.size); - } else { - return .Value_Parse_Error; - } - } - } - - flag.parsed = true; - } - - return .None; -} - -reflect_args_structure :: proc(ctx: ^Flag_Context, v: any) -> Flag_Error { - using runtime; - - if !reflect.is_struct(type_info_of(v.id)) { - return .No_Base_Struct; - } - - names := reflect.struct_field_names(v.id); - types := reflect.struct_field_types(v.id); - offsets := reflect.struct_field_offsets(v.id); - tags := reflect.struct_field_tags(v.id); - - for name, i in names { - flag: Flag; - - type := types[i]; - - if named_type, ok := type.variant.(Type_Info_Named); ok { - if union_type, ok := named_type.base.variant.(Type_Info_Union); ok && len(union_type.variants) == 1 { - flag.optional = true; - flag.tag_ptr = rawptr(uintptr(union_type.tag_offset) + uintptr(v.data) + uintptr(offsets[i])); - type = union_type.variants[0]; - } else { - return .Arg_Unsupported_Field_Type; - } - } - - #partial switch _ in type.variant { - case Type_Info_Integer, Type_Info_String, Type_Info_Boolean, Type_Info_Float: - flag.type = type; - flag.data = rawptr(uintptr(v.data) + uintptr(offsets[i])); - case: - return .Arg_Unsupported_Field_Type; - } - - flag_name: string; - - if value, ok := reflect.struct_tag_lookup(tags[i], "flag"); ok { - flag_name = cast(string)value; - } else { - return .Tag_Error; - } - - ctx.seen_flags[flag_name] = flag; - } - - return .None; -} - -parse :: proc(v: any, args: []string) -> Flag_Error { - - if v == nil { - return .None; - } - - ctx: Flag_Context; - - if res := reflect_args_structure(&ctx, v); res != .None { - return res; - } - - if res := parse_args(&ctx, args); res != .None { - return res; - } - - //validate that the required flags were actually set - for k, v in ctx.seen_flags { - if v.optional && v.parsed { - tag_value: i32 = 1; - mem.copy(v.tag_ptr, &tag_value, 4); //4 constant is probably not portable, but it works for me currently - } else if !v.parsed && !v.optional { - return .Arg_Non_Optional; - } - } - - return .None; -} - -usage :: proc(v: any) -> string { - return "failed"; -} diff --git a/tools/odinfmt/main.odin b/tools/odinfmt/main.odin deleted file mode 100644 index 9b9cbac0b..000000000 --- a/tools/odinfmt/main.odin +++ /dev/null @@ -1,145 +0,0 @@ -package odinfmt - -import "core:os" -import "core:odin/tokenizer" -import "core:odin/format" -import "core:fmt" -import "core:strings" -import "core:path/filepath" -import "core:time" -import "core:mem" - -import "flag" - -Args :: struct { - write: Maybe(bool) `flag:"w" usage:"write the new format to file"`, -} - -print_help :: proc(args: []string) { - if len(args) == 0 { - fmt.eprint("odinfmt "); - } else { - fmt.eprintf("%s ", args[0]); - } - fmt.eprintln(); -} - -print_arg_error :: proc(args: []string, error: flag.Flag_Error) { - switch error { - case .None: - print_help(args); - case .No_Base_Struct: - fmt.eprintln(args[0], "no base struct"); - case .Arg_Error: - fmt.eprintln(args[0], "argument error"); - case .Arg_Unsupported_Field_Type: - fmt.eprintln(args[0], "argument: unsupported field type"); - case .Arg_Not_Defined: - fmt.eprintln(args[0], "argument: no defined"); - case .Arg_Non_Optional: - fmt.eprintln(args[0], "argument: non optional"); - case .Value_Parse_Error: - fmt.eprintln(args[0], "argument: value parse error"); - case .Tag_Error: - fmt.eprintln(args[0], "argument: tag error"); - } -} - -format_file :: proc(filepath: string) -> (string, bool) { - if data, ok := os.read_entire_file(filepath); ok { - return format.format(filepath, string(data), format.default_style); - } else { - return "", false; - } -} - -files: [dynamic]string; - -walk_files :: proc(info: os.File_Info, in_err: os.Errno, user_data: rawptr) -> (err: os.Errno, skip_dir: bool) { - if info.is_dir { - return 0, false; - } - - if filepath.ext(info.name) != ".odin" { - return 0, false; - } - - append(&files, strings.clone(info.fullpath)); - - return 0, false; -} - -main :: proc() { - init_global_temporary_allocator(mem.Megabyte * 100) - - args: Args; - - if len(os.args) < 2 { - print_help(os.args); - os.exit(1); - } - - if res := flag.parse(args, os.args[1:len(os.args) - 1]); res != .None { - print_arg_error(os.args, res); - os.exit(1); - } - - path := os.args[len(os.args) - 1]; - - tick_time := time.tick_now(); - - write_failure := false; - - if os.is_file(path) { - if _, ok := args.write.(bool); ok { - backup_path := strings.concatenate({path, "_bk"}); - defer delete(backup_path); - - if data, ok := format_file(path); ok { - os.rename(path, backup_path); - - if os.write_entire_file(path, transmute([]byte)data) { - os.remove(backup_path); - } - } else { - fmt.eprintf("failed to write %v", path); - write_failure = true; - } - } else { - if data, ok := format_file(path); ok { - fmt.println(data); - } - } - } else if os.is_dir(path) { - filepath.walk(path, walk_files, nil); - - for file in files { - - backup_path := strings.concatenate({file, "_bk"}); - defer delete(backup_path); - - if data, ok := format_file(file); ok { - - if _, ok := args.write.(bool); ok { - os.rename(file, backup_path); - - if os.write_entire_file(file, transmute([]byte)data) { - os.remove(backup_path); - } - } else { - fmt.println(data); - } - } else { - fmt.eprintf("failed to format %v", file); - write_failure = true; - } - } - - fmt.printf("formatted %v files in %vms", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time))); - } else { - fmt.eprintf("%v is neither a directory nor a file \n", path); - os.exit(1); - } - - os.exit(1 if write_failure else 0); -}