func AbsFile(dir, file, rewrites string) string {
	abs := file
	if dir != "" && !filepath.IsAbs(file) {
		abs = filepath.Join(dir, file)
	}
	start := 0
	for i := 0; i <= len(rewrites); i++ {
		if i == len(rewrites) || rewrites[i] == ';' {
			if new, ok := applyRewrite(abs, rewrites[start:i]); ok {
				abs = new
				goto Rewritten
			}
			start = i + 1
		}
	}
	if hasPathPrefix(abs, GOROOT) {
		abs = "$GOROOT" + abs[len(GOROOT):]
	}
Rewritten:
	if abs == "" {
		abs = "??"
	}
	return abs
}
AbsFile returns the absolute filename for file in the given directory,
as rewritten by the rewrites argument.
For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT".
If the resulting path is the empty string, the result is "??".

The rewrites argument is a ;-separated list of rewrites.
Each rewrite is of the form "prefix" or "prefix=>replace",
where prefix must match a leading sequence of path elements
and is either removed entirely or replaced by the replacement.
package objabi
import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
)
const (
	A_AUTO = 1 + iota
	A_PARAM
	A_DELETED_AUTO
)
func Flagcount(name, usage string, val *int) {
	flag.Var((*count)(val), name, usage)
}
func Flagfn1(name, usage string, f func(string)) {
	flag.Var(fn1(f), name, usage)
}
func Flagprint(w io.Writer) {
	flag.CommandLine.SetOutput(w)
	flag.PrintDefaults()
}
func Flagparse(usage func()) {
	flag.Usage = usage
	os.Args = expandArgs(os.Args)
	flag.Parse()
}
func expandArgs(in []string) (out []string) {
	for i, s := range in {
		if strings.HasPrefix(s, "@") {
			if out == nil {
				out = make([]string, 0, len(in)*2)
				out = append(out, in[:i]...)
			}
			slurp, err := ioutil.ReadFile(s[1:])
			if err != nil {
				log.Fatal(err)
			}
			args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n")
			out = append(out, expandArgs(args)...)
		} else if out != nil {
			out = append(out, s)
		}
	}
	if out == nil {
		return in
	}
	return
}
func AddVersionFlag() {
	flag.Var(versionFlag{}, "V", "print version and exit")
}
var buildID string  
type versionFlag struct{}
func (versionFlag) IsBoolFlag() bool { return true }
func (versionFlag) Get() interface{} { return nil }
func (versionFlag) String() string { return "" }
func (versionFlag) Set(s string) error {
	name := os.Args[0]
	name = name[strings.LastIndex(name, `/`)+1:]
	name = name[strings.LastIndex(name, `\`)+1:]
	name = strings.TrimSuffix(name, ".exe")
	p := Expstring()
	if p == DefaultExpstring() {
		p = ""
	}
	sep := ""
	if p != "" {
		sep = " "
	}
	if s == "full" {
		if strings.HasPrefix(Version, "devel") {
			p += " buildID=" + buildID
		}
	}
	fmt.Printf("%s version %s%s%s\n", name, Version, sep, p)
	os.Exit(0)
	return nil
}
type count int
func (c *count) String() string {
	return fmt.Sprint(int(*c))
}
func (c *count) Set(s string) error {
	switch s {
	case "true":
		*c++
	case "false":
		*c = 0
	default:
		n, err := strconv.Atoi(s)
		if err != nil {
			return fmt.Errorf("invalid count %q", s)
		}
		*c = count(n)
	}
	return nil
}
func (c *count) Get() interface{} {
	return int(*c)
}
func (c *count) IsBoolFlag() bool {
	return true
}
func (c *count) IsCountFlag() bool {
	return true
}
type fn1 func(string)
func (f fn1) Set(s string) error {
	f(s)
	return nil
}
func (f fn1) String() string { return "" }
const (
	PCDATA_RegMapIndex   = 0  
	PCDATA_UnsafePoint   = 0  
	PCDATA_StackMapIndex = 1
	PCDATA_InlTreeIndex  = 2
	FUNCDATA_ArgsPointerMaps    = 0
	FUNCDATA_LocalsPointerMaps  = 1
	FUNCDATA_RegPointerMaps     = 2  
	FUNCDATA_StackObjects       = 3
	FUNCDATA_InlTree            = 4
	FUNCDATA_OpenCodedDeferInfo = 5
	ArgsSizeUnknown = -0x80000000
)
const (
	PCDATA_RegMapUnsafe = -2  
	PCDATA_UnsafePointSafe   = -1  
	PCDATA_UnsafePointUnsafe = -2  
	PCDATA_Restart1 = -3
	PCDATA_Restart2 = -4
	PCDATA_RestartAtEntry = -5
)
type FuncID uint8
const (
	FuncID_normal FuncID = iota  
	FuncID_runtime_main
	FuncID_goexit
	FuncID_jmpdefer
	FuncID_mcall
	FuncID_morestack
	FuncID_mstart
	FuncID_rt0_go
	FuncID_asmcgocall
	FuncID_sigpanic
	FuncID_runfinq
	FuncID_gcBgMarkWorker
	FuncID_systemstack_switch
	FuncID_systemstack
	FuncID_cgocallback_gofunc
	FuncID_gogo
	FuncID_externalthreadhandler
	FuncID_debugCallV1
	FuncID_gopanic
	FuncID_panicwrap
	FuncID_handleAsyncEvent
	FuncID_asyncPreempt
	FuncID_wrapper  
)
func GetFuncID(name, file string) FuncID {
	switch name {
	case "runtime.main":
		return FuncID_runtime_main
	case "runtime.goexit":
		return FuncID_goexit
	case "runtime.jmpdefer":
		return FuncID_jmpdefer
	case "runtime.mcall":
		return FuncID_mcall
	case "runtime.morestack":
		return FuncID_morestack
	case "runtime.mstart":
		return FuncID_mstart
	case "runtime.rt0_go":
		return FuncID_rt0_go
	case "runtime.asmcgocall":
		return FuncID_asmcgocall
	case "runtime.sigpanic":
		return FuncID_sigpanic
	case "runtime.runfinq":
		return FuncID_runfinq
	case "runtime.gcBgMarkWorker":
		return FuncID_gcBgMarkWorker
	case "runtime.systemstack_switch":
		return FuncID_systemstack_switch
	case "runtime.systemstack":
		return FuncID_systemstack
	case "runtime.cgocallback_gofunc":
		return FuncID_cgocallback_gofunc
	case "runtime.gogo":
		return FuncID_gogo
	case "runtime.externalthreadhandler":
		return FuncID_externalthreadhandler
	case "runtime.debugCallV1":
		return FuncID_debugCallV1
	case "runtime.gopanic":
		return FuncID_gopanic
	case "runtime.panicwrap":
		return FuncID_panicwrap
	case "runtime.handleAsyncEvent":
		return FuncID_handleAsyncEvent
	case "runtime.asyncPreempt":
		return FuncID_asyncPreempt
	case "runtime.deferreturn":
		return FuncID_wrapper
	case "runtime.runOpenDeferFrame":
		return FuncID_wrapper
	case "runtime.reflectcallSave":
		return FuncID_wrapper
	}
	if file == "<autogenerated>" {
		return FuncID_wrapper
	}
	if strings.HasPrefix(name, "runtime.call") {
		if _, err := strconv.Atoi(name[12:]); err == nil {
			return FuncID_wrapper
		}
	}
	if strings.HasSuffix(name, "-fm") {
		return FuncID_wrapper
	}
	return FuncID_normal
}
type HeadType uint8
const (
	Hunknown HeadType = iota
	Hdarwin
	Hdragonfly
	Hfreebsd
	Hjs
	Hlinux
	Hnetbsd
	Hopenbsd
	Hplan9
	Hsolaris
	Hwindows
	Haix
)
func (h *HeadType) Set(s string) error {
	switch s {
	case "aix":
		*h = Haix
	case "darwin":
		*h = Hdarwin
	case "dragonfly":
		*h = Hdragonfly
	case "freebsd":
		*h = Hfreebsd
	case "js":
		*h = Hjs
	case "linux", "android":
		*h = Hlinux
	case "netbsd":
		*h = Hnetbsd
	case "openbsd":
		*h = Hopenbsd
	case "plan9":
		*h = Hplan9
	case "illumos", "solaris":
		*h = Hsolaris
	case "windows":
		*h = Hwindows
	default:
		return fmt.Errorf("invalid headtype: %q", s)
	}
	return nil
}
func (h *HeadType) String() string {
	switch *h {
	case Haix:
		return "aix"
	case Hdarwin:
		return "darwin"
	case Hdragonfly:
		return "dragonfly"
	case Hfreebsd:
		return "freebsd"
	case Hjs:
		return "js"
	case Hlinux:
		return "linux"
	case Hnetbsd:
		return "netbsd"
	case Hopenbsd:
		return "openbsd"
	case Hplan9:
		return "plan9"
	case Hsolaris:
		return "solaris"
	case Hwindows:
		return "windows"
	}
	return fmt.Sprintf("HeadType(%d)", *h)
}
func WorkingDir() string {
	var path string
	path, _ = os.Getwd()
	if path == "" {
		path = "/???"
	}
	return filepath.ToSlash(path)
}