package codegen import "core:encoding/xml" import "core:flags" import "core:fmt" import "core:io" import "core:os" import "core:strings" // This program functions as a "script" and does not run for very long. Therefore we do not free any memory, ever! // Don't run ASAN on this program! :) // TODO: We really ought to manage our memory a bit. main :: proc() { f: struct { source: string `args:"pos=0,required" usage:"Path to directory containing wayland XML specifications."`, dest: string `args:"pos=1,required" usage:"Path to directory in which to place generated code."`, } flags.parse_or_exit(&f, os.args) if !os.exists(f.source) { fmt.eprintfln("Source directory '{}' does not exist.", f.source) os.exit(1) } source_walker := os.walker_create(f.source) defer os.walker_destroy(&source_walker) protocols: map[string]Protocol // Keyed by Protocol.name num_interfaces: int max_num_events: int for info in os.walker_walk(&source_walker) { if info.type == .Directory || os.ext(info.fullpath) != ".xml" { continue } fmt.println(info.fullpath) doc, doc_err := xml.load_from_file(info.fullpath) if doc_err != nil { // No need to print because the XML library does that for us. continue } p := parser_make(doc) protocol, parse_err := parse_protocol(&p) if parse_err != nil { fmt.eprintfln("Error parsing '{}': {}", info.name, parse_err) continue } protocol.file_name = strings.clone(info.name) protocols[protocol.name] = protocol num_interfaces += len(protocol.interfaces) for interface in protocol.interfaces { max_num_events = max(max_num_events, len(interface.events)) } // fmt.printfln("%#v", protocol) } fmt.println(num_interfaces, "interfaces") fmt.println(max_num_events, "max events") if !os.exists(f.dest) { os.make_directory(f.dest) } // Iterate over each protocol again and generate a file from it. for protocol_name, protocol in protocols { // Don't care about allocator errors. file_path, _ := os.join_path({f.dest, fmt.tprint("protocol_", protocol_name, ".gen.odin", sep="")}, context.allocator) file, file_err := os.create(file_path) if file_err != nil { fmt.eprintfln("Error creating '{}': {}", file_path, file_err) continue } gen_header(file, protocol) gen_imports(file, protocol) for interface in protocol.interfaces { gen_interface(file, protocol, interface) } os.close(file) } }