123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // Copyright 2015 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
-
- // +build ignore
-
- // This is a program that works like the GNU c++filt program.
- // It's here for testing purposes and as an example.
-
- package main
-
- import (
- "bufio"
- "flag"
- "fmt"
- "io"
- "os"
- "strings"
- "unicode"
-
- "github.com/ianlancetaylor/demangle"
- )
-
- func flagUsage() {
- usage(os.Stderr, 2)
- }
-
- func usage(w io.Writer, status int) {
- fmt.Fprintf(w, "Usage: %s [options] [mangled names]\n", os.Args[0])
- flag.CommandLine.SetOutput(w)
- flag.PrintDefaults()
- fmt.Fprintln(w, `Demangled names are displayed to stdout
- If a name cannot be demangled it is just echoed to stdout.
- If no names are provided on the command line, stdin is read.`)
- os.Exit(status)
- }
-
- var stripUnderscore = flag.Bool("_", false, "Ignore first leading underscore")
- var noParams = flag.Bool("p", false, "Do not display function argument types")
- var noVerbose = flag.Bool("i", false, "Do not show implementation details (if any)")
- var help = flag.Bool("h", false, "Display help information")
- var debug = flag.Bool("d", false, "Display debugging information for strings on command line")
-
- // Unimplemented c++filt flags:
- // -n (opposite of -_)
- // -t (demangle types)
- // -s (set demangling style)
- // -V (print version information)
-
- // Characters considered to be part of a symbol.
- const symbolChars = "_$."
-
- func main() {
- flag.Usage = func() { usage(os.Stderr, 1) }
- flag.Parse()
-
- if *help {
- usage(os.Stdout, 0)
- }
-
- out := bufio.NewWriter(os.Stdout)
-
- if flag.NArg() > 0 {
- for _, f := range flag.Args() {
- if *debug {
- a, err := demangle.ToAST(f, options()...)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %v\n", f, err)
- } else {
- fmt.Fprintf(out, "%#v\n", a)
- }
- } else {
- doDemangle(out, f)
- }
- out.WriteByte('\n')
- }
- if err := out.Flush(); err != nil {
- fmt.Fprintln(os.Stderr, err)
- os.Exit(2)
- }
- return
- }
-
- scanner := bufio.NewScanner(bufio.NewReader(os.Stdin))
- for scanner.Scan() {
- line := scanner.Text()
- start := -1
- for i, c := range line {
- if unicode.IsLetter(c) || unicode.IsNumber(c) || strings.ContainsRune(symbolChars, c) {
- if start < 0 {
- start = i
- }
- } else {
- if start >= 0 {
- doDemangle(out, line[start:i])
- }
- out.WriteRune(c)
- start = -1
- }
- }
- if start >= 0 {
- doDemangle(out, line[start:])
- start = -1
- }
- out.WriteByte('\n')
- if err := out.Flush(); err != nil {
- fmt.Fprintln(os.Stderr, err)
- os.Exit(2)
- }
- }
- }
-
- // Demangle a string just as the GNU c++filt program does.
- func doDemangle(out *bufio.Writer, name string) {
- skip := 0
- if name[0] == '.' || name[0] == '$' {
- skip++
- }
- if *stripUnderscore && name[skip] == '_' {
- skip++
- }
- result := demangle.Filter(name[skip:], options()...)
- if result == name[skip:] {
- out.WriteString(name)
- } else {
- if name[0] == '.' {
- out.WriteByte('.')
- }
- out.WriteString(result)
- }
- }
-
- // options returns the demangling options to use based on the command
- // line flags.
- func options() []demangle.Option {
- var options []demangle.Option
- if *noParams {
- options = append(options, demangle.NoParams)
- }
- if !*noVerbose {
- options = append(options, demangle.Verbose)
- }
- return options
- }
|