Skip to content

Commit

Permalink
parser: Different way of storing enums
Browse files Browse the repository at this point in the history
Also started work on removing duplicate types.
  • Loading branch information
mefistotelis committed Mar 13, 2022
1 parent 0f2999f commit 95ab108
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 36 deletions.
14 changes: 8 additions & 6 deletions cmd/sym_dump/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func main() {
}
p.ParseTypes(f.Syms)
p.ParseDecls(f.Syms)
p.RemoveDuplicateTypes()
p.MakeNamesUnique()
// Output once for each files if not in merge mode.
if !merge {
Expand Down Expand Up @@ -148,7 +149,6 @@ func pruneDuplicates(ps []*csym.Parser, skipAddrDiff, skipLineDiff bool, opts *s
}

// Sort types by tag.
natsort.Strings(dst.EnumTags)
less := func(i, j int) bool {
ti := dst.Typedefs[i].(*c.VarDecl)
tj := dst.Typedefs[j].(*c.VarDecl)
Expand Down Expand Up @@ -301,8 +301,9 @@ func addUniqueUnions(dst *csym.Parser, p *csym.Parser, pnum int, fakeCount *int,

// addUniqueEnums adds unique Enums to destination parser.
func addUniqueEnums(dst *csym.Parser, p *csym.Parser, pnum int, fakeCount *int, isPresent *map[string]bool, opts *sym.Options) {
for _, tag := range p.EnumTags {
t := p.Enums[tag]
for tag, enums := range p.EnumTags {
for i := 0; i < len(enums); i++ {
t := enums[i]
fake := strings.Contains(t.Tag, "fake")
if fake {
t.Tag = placeholder
Expand All @@ -315,16 +316,17 @@ func addUniqueEnums(dst *csym.Parser, p *csym.Parser, pnum int, fakeCount *int,
}
if !(*isPresent)[s] {
if !fake {
if _, ok := dst.Enums[tag]; ok {
if _, ok := dst.EnumTags[tag]; ok {
tag = fmt.Sprintf("%s_dup_%d", tag, pnum)
t.Tag = tag
}
}
dst.Enums[tag] = t
dst.EnumTags = append(dst.EnumTags, tag)
dst.EnumTags[tag] = append(dst.EnumTags[tag], t)
dst.Enums = append(dst.Enums, t)
}
(*isPresent)[s] = true
}
}
}

// dump dumps the declarations of the parser to the given output directory, in
Expand Down
3 changes: 1 addition & 2 deletions cmd/sym_dump/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ func dumpTypes(p *csym.Parser, outputDir string) error {
}
}
// Print enums.
for _, tag := range p.EnumTags {
t := p.Enums[tag]
for _, t := range p.Enums {
if _, err := fmt.Fprintf(f, "%s;\n\n", t.Def()); err != nil {
return errors.WithStack(err)
}
Expand Down
12 changes: 6 additions & 6 deletions csym/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ type Parser struct {

// Struct maps from struct tag to struct types.
StructTags map[string][]*c.StructType
// unions maps from union tag to union type.
// Unions maps from union tag to union types.
UnionTags map[string][]*c.UnionType
// enums maps from enum tag to enum type.
Enums map[string]*c.EnumType
// Enums maps from enum tag to enum types.
EnumTags map[string][]*c.EnumType
// types maps from type name to underlying type definition.
Types map[string]c.Type
// Structs in order of occurrence in SYM file.
Structs []*c.StructType
// Unions in order of occurrence in SYM file.
Unions []*c.UnionType
// Enum tags in order of occurrence in SYM file.
EnumTags []string
// Enums in order of occurrence in SYM file.
Enums []*c.EnumType
// Type definitions in order of occurrence in SYM file.
Typedefs []c.Type
// Tracks unique enum member names.
Expand Down Expand Up @@ -53,7 +53,7 @@ func NewParser(opts *sym.Options) *Parser {
return &Parser{
StructTags: make(map[string][]*c.StructType),
UnionTags: make(map[string][]*c.UnionType),
Enums: make(map[string]*c.EnumType),
EnumTags: make(map[string][]*c.EnumType),
Types: make(map[string]c.Type),
enumMembers: make(map[string]bool),
Overlay: overlay,
Expand Down
65 changes: 61 additions & 4 deletions csym/parse_fixups.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,41 @@ package csym

import (
"fmt"
"reflect"

"github.com/mefistotelis/psx_mnd_sym/csym/c"
)

//TODO make unique names of types
//TODO remove duplicate items
// RemoveDuplicateTypes goes through parsed types and marks exact duplicates.
func (p *Parser) RemoveDuplicateTypes() {
if p.opts.Verbose { fmt.Printf("Remove duplicate types...\n") }
p.removeStructsDuplicates()
}

// removeStructsDuplicates goes through parsed symbols and marks exact duplicates.
func (p *Parser) removeStructsDuplicates() {
n := 0
for tag, structs := range p.StructTags {
for i := 0; i < len(structs); i++ {
t1 := structs[i]
for k := i+1; k < len(structs); k++ {
t2 := structs[k]
if !reflect.DeepEqual(t2, t1) { continue }
structs = structsRemoveIndex(structs, k)
k--
n++
}
}
p.StructTags[tag] = structs;
}
if p.opts.Verbose { fmt.Printf("Removed structs: %d\n", n) }
}

// MakeNamesUnique goes through parsed symbols and renames duplicate ones.
func structsRemoveIndex(s []*c.StructType, index int) []*c.StructType {
return append(s[:index], s[index+1:]...)
}

// MakeNamesUnique goes through parsed symbols and renames duplicate names.
func (p *Parser) MakeNamesUnique() {
if p.opts.Verbose { fmt.Printf("Making names unique...\n") }
p.makeStructsUnique()
Expand Down Expand Up @@ -60,7 +87,6 @@ func (p *Parser) makeFuncNamesUniqueInOverlay(overlay *Overlay) {
// makeStructsUnique goes through parsed symbols and renames duplicate ones.
func (p *Parser) makeStructsUnique() {
for _, structs := range p.StructTags {
// Do not rename extern declarations
real_len := len(structs)
if real_len < 2 { continue }
for i := 0; i < len(structs); i++ {
Expand All @@ -72,10 +98,26 @@ func (p *Parser) makeStructsUnique() {

// makeUnionsUnique goes through parsed symbols and renames duplicate ones.
func (p *Parser) makeUnionsUnique() {
for _, unions := range p.UnionTags {
real_len := len(unions)
if real_len < 2 { continue }
for i := 0; i < len(unions); i++ {
t := unions[i]
t.Tag = UniqueUnionTag(p.UnionTags, t)
}
}
}

// makeEnumsUnique goes through parsed symbols and renames duplicate ones.
func (p *Parser) makeEnumsUnique() {
for _, enums := range p.EnumTags {
real_len := len(enums)
if real_len < 2 { continue }
for i := 0; i < len(enums); i++ {
t := enums[i]
t.Tag = UniqueEnumTag(p.EnumTags, t)
}
}
}

// UniqueName returns a unique name based on the given name and address.
Expand Down Expand Up @@ -141,3 +183,18 @@ func UniqueUnionTag(unionTags map[string][]*c.UnionType, t *c.UnionType) string
}
return newTag
}

// UniqueEnumTag returns a unique enum tag based on the given enum
// and set of present enums mapped by tags.
func UniqueEnumTag(EnumTags map[string][]*c.EnumType, t *c.EnumType) string {
newTag := t.Tag
for {
enums, ok := EnumTags[newTag]
if !ok { break } // the tag is unique - done
k := SliceIndex(len(enums), func(i int) bool { return enums[i] == t })
if k < 0 { k = len(enums) }
newTag = UniqueTag(newTag, k)
}
return newTag
}

45 changes: 27 additions & 18 deletions csym/parse_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ func (p *Parser) emptyEnum(tag string) *c.EnumType {
t := &c.EnumType{
Tag: tag,
}
p.Enums[tag] = t
p.EnumTags = append(p.EnumTags, tag)
p.EnumTags[tag] = append(p.EnumTags[tag], t)
p.Enums = append(p.Enums, t)
return t
}

Expand All @@ -92,9 +92,6 @@ func (p *Parser) initTaggedTypes(syms []*sym.Symbol) {
// Add scaffolding types for structs, unions and enums, so they may be
// referrenced before defined.
p.emptyStruct("__vtbl_ptr_type", 0)
var (
enumTags = make(map[string]bool)
)
for _, s := range syms {
switch body := s.Body.(type) {
case *sym.Def:
Expand All @@ -105,7 +102,6 @@ func (p *Parser) initTaggedTypes(syms []*sym.Symbol) {
case sym.ClassUNTAG:
p.emptyUnion(tag, body.Size)
case sym.ClassENTAG:
tag = uniqueTag(tag, enumTags)
p.emptyEnum(tag)
}
}
Expand Down Expand Up @@ -384,10 +380,21 @@ func findEmptyUnion(p *Parser, tag string, size uint32) *c.UnionType {

// findEnum returns the enumeration with the given tag.
func (p *Parser) findEnum(tag string) *c.EnumType {
t, ok := p.Enums[tag]
// Ignore size - we currently support only one type with specific tag
if !ok {
var t *c.EnumType = nil
nameExists := false
enums, ok := p.EnumTags[tag]
if ok {
nameExists = len(enums) > 0
for i := 0; i < len(enums); i++ {
tt := enums[i]
t = tt
}
}
if t == nil {
t = p.emptyEnum(tag)
if nameExists {
t.Tag = UniqueEnumTag(p.EnumTags, t)
}
log.Printf("unable to locate enum %q, created empty", tag)
}
return t
Expand All @@ -397,17 +404,19 @@ func (p *Parser) findEnum(tag string) *c.EnumType {
// It selects the enum which has no members defined yet, and
// asserts that the type exists.
func findEmptyEnum(p *Parser, tag string) *c.EnumType {
newTag := tag
for i := 0; ; i++ {
t, ok := p.Enums[newTag]
if !ok {
panic(fmt.Errorf("unable to locate enum %q", tag))
}
if len(t.Members) == 0 {
return t
var t *c.EnumType = nil
enums, ok := p.EnumTags[tag]
if ok {
for i := 0; i < len(enums); i++ {
tt := enums[i]
if len(tt.Members) != 0 { continue }
t = tt
}
newTag = fmt.Sprintf(duplicateTagFormat, tag, i)
}
if t == nil {
panic(fmt.Errorf("unable to locate enum %q", tag))
}
return t
}

// parseType parses the SYM type into the equivalent C type.
Expand Down

0 comments on commit 95ab108

Please sign in to comment.