Created
January 26, 2018 23:43
-
-
Save josharian/2e8e8ba23a99317820291b30b47a64fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"flag" | |
"fmt" | |
"os" | |
"strings" | |
"github.com/go-clang/v3.9/clang" | |
) | |
var fname = flag.String("fname", "", "the file to analyze") | |
func main() { | |
flag.Parse() | |
if *fname == "" { | |
flag.Usage() | |
fmt.Printf("please provide a file name to analyze\n") | |
os.Exit(1) | |
} | |
idx := clang.NewIndex(0, 1) | |
defer idx.Dispose() | |
tu := idx.ParseTranslationUnit(*fname, []string{"-DDOCURIUM=1"}, nil, 0) | |
defer tu.Dispose() | |
diagnostics := tu.Diagnostics() | |
for _, d := range diagnostics { | |
fmt.Println("PROBLEM:", d.Spelling()) | |
} | |
if len(diagnostics) > 0 { | |
os.Exit(1) | |
} | |
cursor := tu.TranslationUnitCursor() | |
var enums []string | |
var comments [][]string | |
cursor.Visit(func(cursor, parent clang.Cursor) clang.ChildVisitResult { | |
if cursor.IsNull() { | |
return clang.ChildVisit_Continue | |
} | |
file, _, _, _ := cursor.Location().FileLocation() | |
if file.Name() != *fname { | |
return clang.ChildVisit_Continue | |
} | |
switch cursor.Kind() { | |
case clang.Cursor_EnumDecl: | |
cursor.Visit(func(innercursor, innerparent clang.Cursor) clang.ChildVisitResult { | |
if innercursor.Kind() != clang.Cursor_EnumConstantDecl { | |
return clang.ChildVisit_Continue | |
} | |
enums = append(enums, innercursor.Spelling()) | |
pc := innercursor.ParsedComment() | |
var lines []string | |
for i := uint32(0); i < pc.NumChildren(); i++ { | |
c := pc.Child(i) | |
if c.Kind() != clang.Comment_Paragraph { | |
panic("unexpected comment kind") | |
} | |
for j := uint32(0); j < c.NumChildren(); j++ { | |
line := c.Child(j) | |
if line.Kind() != clang.Comment_Text { | |
panic(fmt.Sprintf("unexpected inner comment kind %v", line.Kind().Spelling())) | |
} | |
lines = append(lines, line.TextComment_getText()) | |
} | |
lines = append(lines, "\n") | |
} | |
if len(lines) > 0 && lines[len(lines)-1] == "\n" { | |
lines = lines[:len(lines)-1] | |
} | |
comments = append(comments, lines) | |
return clang.ChildVisit_Recurse | |
}) | |
case clang.Cursor_TypedefDecl: | |
if len(enums) > 0 { | |
ctyp := cursor.Spelling() | |
special, isspecial := ctype2go[ctyp] // handle exceptions | |
var typ string | |
if isspecial { | |
typ = special.gotype | |
} else { | |
typ = ctyp | |
typ = strings.TrimPrefix(typ, "git_") | |
typ = strings.TrimSuffix(typ, "_t") | |
typ = toCamel(typ) | |
} | |
fmt.Printf("const (\n") | |
for i := range enums { | |
for _, line := range comments[i] { | |
fmt.Printf("\t//%s\n", line) | |
} | |
enum := toCamel(strings.TrimPrefix(enums[i], "GIT_")) | |
if isspecial { | |
enum = special.addPrefix + strings.TrimPrefix(enum, special.stripPrefix) | |
} | |
fmt.Printf("\t%s %s = C.%s\n", enum, typ, enums[i]) | |
if i != len(enums)-1 { | |
fmt.Println() | |
} | |
} | |
fmt.Printf(")\n\n\n") | |
} | |
enums = nil | |
comments = nil | |
} | |
return clang.ChildVisit_Continue | |
}) | |
if len(diagnostics) > 0 { | |
fmt.Println("NOTE: There were problems while analyzing the given file") | |
os.Exit(1) | |
} | |
} | |
var ctype2go = map[string]struct { | |
gotype string | |
stripPrefix string | |
addPrefix string | |
}{ | |
"git_merge_flag_t": {"MergeTreeFlag", "Merge", "MergeTree"}, | |
} | |
func toCamel(s string) string { | |
words := strings.Split(s, "_") | |
var camel [][]byte | |
for _, word := range words { | |
if len(word) == 0 { | |
camel = append(camel, []byte("")) | |
} | |
w := []byte(word) | |
w = bytes.ToLower(w) | |
w[0] = bytes.ToUpper(w[:1])[0] | |
camel = append(camel, w) | |
} | |
return string(bytes.Join(camel, nil)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment