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  }