github.com/chenzhuoyu/iasm@v0.9.1/cmd/iasm/main.go (about) 1 package main 2 3 import ( 4 `os` 5 6 `github.com/chenzhuoyu/iasm/obj` 7 `github.com/chenzhuoyu/iasm/repl` 8 `github.com/chenzhuoyu/iasm/x86_64` 9 `nullprogram.com/x/optparse` 10 ) 11 12 type _FileFormat int 13 14 const ( 15 _F_bin _FileFormat = iota + 1 16 _F_macho 17 _F_elf 18 ) 19 20 var formatTab = map[string]_FileFormat { 21 "bin" : _F_bin, 22 "macho" : _F_macho, 23 "elf" : _F_elf, 24 } 25 26 func usage() { 27 println("usage: iasm [OPTIONS] <source>") 28 println(" iasm -h | --help") 29 println() 30 println("General Options:") 31 println(` -D DEF, --define=DEF Passing the defination to preprocessor`) 32 println(" -f FMT, --format=FMT Select output format") 33 println(" bin Flat raw binary (default)") 34 println(" macho Mach-O executable") 35 println(" elf ELF executable") 36 println() 37 println(" -h, --help This help message") 38 println(" -o FILE, --output=FILE Output file name") 39 println(" -s, --gas-compat GAS compatible mode") 40 println() 41 println("Environment Variables:") 42 println(" CPP The C Preprocessor") 43 println() 44 } 45 46 func compile() { 47 var err error 48 var src string 49 var rem []string 50 var asm x86_64.Assembler 51 var ret []optparse.Result 52 53 /* options list */ 54 opts := []optparse.Option { 55 { "help" , 'h', optparse.KindNone }, 56 { "define" , 'D', optparse.KindRequired }, 57 { "format" , 'f', optparse.KindRequired }, 58 { "output" , 'o', optparse.KindRequired }, 59 { "gas-compat" , 's', optparse.KindNone }, 60 } 61 62 /* parse the options */ 63 if ret, rem, err = optparse.Parse(opts, os.Args); err != nil { 64 println("iasm: error: " + err.Error()) 65 usage() 66 } 67 68 /* default values */ 69 help := false 70 mgas := false 71 ffmt := "bin" 72 fout := "a.out" 73 defs := []string(nil) 74 75 /* check the result */ 76 for _, vv := range ret { 77 switch vv.Short { 78 case 'h': help = true 79 case 's': mgas = true 80 case 'f': ffmt = vv.Optarg 81 case 'o': fout = vv.Optarg 82 case 'D': defs = append(defs, vv.Optarg) 83 } 84 } 85 86 /* check file format */ 87 if _, ok := formatTab[ffmt]; !ok { 88 println("iasm: error: unknown file format: " + ffmt) 89 os.Exit(1) 90 } 91 92 /* check for help */ 93 if help { 94 usage() 95 } 96 97 /* must have source files */ 98 if len(rem) == 0 { 99 println("iasm: error: missing input file.") 100 os.Exit(1) 101 } 102 103 /* must have exactly 1 source file */ 104 if len(rem) != 1 { 105 println("iasm: error: too many input files.") 106 os.Exit(1) 107 } 108 109 /* preprocess the source file */ 110 if src, err = preprocess(rem[0], defs); err != nil { 111 println("iasm: error: failed to run preprocessor: " + err.Error()) 112 os.Exit(1) 113 } 114 115 /* check for GAS compatible mode */ 116 if mgas { 117 asm.Options().InstructionAliasing = true 118 asm.Options().IgnoreUnknownDirectives = true 119 } 120 121 /* assemble the source */ 122 if err = asm.Assemble(src); err != nil { 123 println("iasm: error: " + err.Error()) 124 os.Exit(1) 125 } 126 127 /* check for format */ 128 switch formatTab[ffmt] { 129 case _F_bin : err = os.WriteFile(fout, asm.Code(), 0755) 130 case _F_elf : err = obj.ELF.Generate(fout, asm.Code(), uint64(asm.Base()), uint64(asm.Entry())) 131 case _F_macho : err = obj.MachO.Generate(fout, asm.Code(), uint64(asm.Base()), uint64(asm.Entry())) 132 default : panic("invalid format: " + ffmt) 133 } 134 135 /* check for errors */ 136 if err != nil { 137 println("iasm: error: " + err.Error()) 138 os.Exit(1) 139 } 140 } 141 142 func main() { 143 if len(os.Args) != 1 { 144 compile() 145 } else { 146 new(repl.IASM).Start() 147 } 148 }