2
0
Daniel Gavin 4 жил өмнө
parent
commit
b18e8898d8
2 өөрчлөгдсөн 346 нэмэгдсэн , 380 устгасан
  1. 219 232
      tools/odinfmt/flag/flag.odin
  2. 127 148
      tools/odinfmt/main.odin

+ 219 - 232
tools/odinfmt/flag/flag.odin

@@ -1,232 +1,219 @@
-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 true {
-
-        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 := true;
-            mem.copy(flag.data, &tmp, flag.type.size);
-            flag.parsed = true;
-            continue;
-        }
-
-        //must be in the next argument
-        else if value == "" {
-
-            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 && union_type.maybe && 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";
-}
+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 true {
+
+		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 := true;
+			mem.copy(flag.data, &tmp, flag.type.size);
+			flag.parsed = true;
+			continue;
+		} else
+
+		//must be in the next argument
+		if value == "" {
+
+			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 && union_type.maybe && 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";
+}

+ 127 - 148
tools/odinfmt/main.odin

@@ -1,148 +1,127 @@
-package odinfmt
-
-import "core:os"
-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() {
-
-}
-
-print_arg_error :: proc(error: flag.Flag_Error) {
-    fmt.println(error);
-}
-
-format_file :: proc(filepath: string) -> ([] u8, bool) {
-
-    if data, ok := os.read_entire_file(filepath); ok {
-        return format.format(data, format.default_style);
-    }
-
-    else {
-        return {}, false;
-    }
-
-}
-
-files: [dynamic] string;
-
-walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (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.megabytes(100));
-
-    args: Args;
-
-    if len(os.args) < 2 {
-        print_help();
-        os.exit(1);
-    }
-
-    if res := flag.parse(args, os.args[1:len(os.args)-1]); res != .None {
-        print_arg_error(res);
-        os.exit(1);
-    }
-
-    path := os.args[len(os.args)-1];
-
-    tick_time := time.tick_now();
-
-    if os.is_file(path) {
-
-        if _, ok := args.write.(bool); ok {
-
-            backup_path := strings.concatenate({path, "_bk"}, context.temp_allocator);
-
-            if data, ok := format_file(path); ok {
-
-                 os.rename(path, backup_path);
-
-                if os.write_entire_file(path, data) {
-                    os.remove(backup_path);
-                }
-
-            }
-
-            else {
-                fmt.eprintf("failed to write %v", path);
-            }
-
-        }
-
-        else {
-
-            if data, ok := format_file(path); ok {
-                fmt.println(transmute(string)data);
-            }
-
-        }
-
-    }
-
-    else if os.is_dir(path) {
-
-        filepath.walk(path, walk_files);
-
-        for file in files {
-
-            fmt.println(file);
-
-            backup_path := strings.concatenate({file, "_bk"}, context.temp_allocator);
-
-            if data, ok := format_file(file); ok {
-
-                if _, ok := args.write.(bool); ok {
-                    os.rename(file, backup_path);
-
-                    if os.write_entire_file(file, data) {
-                        os.remove(backup_path);
-                    }
-                }
-
-                else {
-                    fmt.println(transmute(string)data);
-                }
-
-
-            } else {
-                fmt.eprintf("failed to format %v", file);
-            }
-
-            free_all(context.temp_allocator);
-        }
-
-        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(0);
-}
+package odinfmt
+
+import "core:os"
+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() {
+}
+
+print_arg_error :: proc(error: flag.Flag_Error) {
+	fmt.println(error);
+}
+ 
+format_file :: proc(filepath: string) -> ([]u8, bool) {
+
+	if data, ok := os.read_entire_file(filepath); ok {
+		return format.format(data, format.default_style);
+	} else {
+		return {}, false;
+	}
+}
+
+files: [dynamic]string;
+
+walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (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.megabytes(100));
+
+	args: Args;
+
+	if len(os.args) < 2 {
+		print_help();
+		os.exit(1);
+	}
+
+	if res := flag.parse(args, os.args[1:len(os.args) - 1]); res != .None {
+		print_arg_error(res);
+		os.exit(1);
+	}
+
+	path := os.args[len(os.args) - 1];
+
+	tick_time := time.tick_now();
+
+	if os.is_file(path) {
+
+		if _, ok := args.write.(bool); ok {
+
+			backup_path := strings.concatenate({path, "_bk"}, context.temp_allocator);
+
+			if data, ok := format_file(path); ok {
+
+				os.rename(path, backup_path);
+
+				if os.write_entire_file(path, data) {
+					os.remove(backup_path);
+				}
+			} else {
+				fmt.eprintf("failed to write %v", path);
+			}
+		} else {
+
+			if data, ok := format_file(path); ok {
+				fmt.println(transmute(string)data);
+			}
+		}
+	} else if os.is_dir(path) {
+
+		filepath.walk(path, walk_files);
+
+		for file in files {
+
+			fmt.println(file);
+
+			backup_path := strings.concatenate({file, "_bk"}, context.temp_allocator);
+
+			if data, ok := format_file(file); ok {
+
+				if _, ok := args.write.(bool); ok {
+					os.rename(file, backup_path);
+
+					if os.write_entire_file(file, data) {
+						os.remove(backup_path);
+					}
+				} else {
+					fmt.println(transmute(string)data);
+				}
+			} else {
+				fmt.eprintf("failed to format %v", file);
+			}
+
+			free_all(context.temp_allocator);
+		}
+
+		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(0);
+}