raiguard/odin-wayland
git clone https://git.raiguard.me/raiguard/odin-wayland
f425641
trunk
1package codegen 2 3import "core:encoding/xml" 4import "core:flags" 5import "core:fmt" 6import "core:io" 7import "core:os" 8import "core:strings" 9 10// This program functions as a "script" and does not run for very long. Therefore we do not free any memory, ever! 11// Don't run ASAN on this program! :) 12// TODO: We really ought to manage our memory a bit. 13 14main :: proc () { 15f : struct { 16source : string `args:"pos=0,required" usage:"Path to directory containing wayland XML specifications."` , 17dest : string `args:"pos=1,required" usage:"Path to directory in which to place generated code."` , 18} 19flags . parse_or_exit ( & f , os . args ) 20 21if ! os . exists ( f . source ) { 22fmt . eprintfln ( "Source directory '{}' does not exist." , f . source ) 23os . exit ( 1 ) 24} 25 26source_walker := os . walker_create ( f . source ) 27defer os . walker_destroy ( & source_walker ) 28 29protocols : map [ string ] Protocol // Keyed by Protocol.name 30num_interfaces : int 31max_num_events : int 32 33for info in os . walker_walk ( & source_walker ) { 34if info . type == . Directory || os . ext ( info . fullpath ) != ".xml" { 35continue 36} 37 38fmt . println ( info . fullpath ) 39 40doc , doc_err := xml . load_from_file ( info . fullpath ) 41if doc_err != nil { 42// No need to print because the XML library does that for us. 43continue 44} 45 46p := parser_make ( doc ) 47protocol , parse_err := parse_protocol ( & p ) 48if parse_err != nil { 49fmt . eprintfln ( "Error parsing '{}': {}" , info . name , parse_err ) 50continue 51} 52protocol . file_name = strings . clone ( info . name ) 53protocols [ protocol . name ] = protocol 54 55num_interfaces += len ( protocol . interfaces ) 56for interface in protocol . interfaces { 57max_num_events = max ( max_num_events , len ( interface . events )) 58} 59// fmt.printfln("%#v", protocol) 60} 61fmt . println ( num_interfaces , "interfaces" ) 62fmt . println ( max_num_events , "max events" ) 63 64if ! os . exists ( f . dest ) { 65os . make_directory ( f . dest ) 66} 67 68// Iterate over each protocol again and generate a file from it. 69for protocol_name , protocol in protocols { 70// Don't care about allocator errors. 71file_path , _ := os . join_path ({ f . dest , fmt . tprint ( "protocol_" , protocol_name , ".gen.odin" , sep = "" )}, context . allocator ) 72file , file_err := os . create ( file_path ) 73if file_err != nil { 74fmt . eprintfln ( "Error creating '{}': {}" , file_path , file_err ) 75continue 76} 77 78gen_header ( file , protocol ) 79gen_imports ( file , protocol ) 80 81for interface in protocol . interfaces { 82gen_interface ( file , protocol , interface ) 83} 84 85os . close ( file ) 86} 87}