github.com/gotranspile/cxgo@v0.3.7/macros.go (about) 1 package cxgo 2 3 import ( 4 "fmt" 5 "github.com/gotranspile/cxgo/types" 6 "sort" 7 "strconv" 8 "strings" 9 10 "modernc.org/cc/v3" 11 ) 12 13 func (g *translator) convertValue(v cc.Value) Expr { 14 switch v := v.(type) { 15 case cc.Int64Value: 16 return cIntLit(int64(v)) 17 case cc.Uint64Value: 18 return cUintLit(uint64(v)) 19 case cc.Float32Value: 20 return FloatLit{val: float64(v)} 21 case cc.Float64Value: 22 return FloatLit{val: float64(v)} 23 case cc.StringValue: 24 e, err := g.parseCStringLit(string(v)) 25 if err != nil { 26 panic(err) 27 } 28 return e 29 default: 30 panic(fmt.Errorf("unsupported value type: %T", v)) 31 } 32 } 33 34 func (g *translator) convertMacros(ast *cc.AST) []CDecl { 35 type macro struct { 36 name string 37 m *cc.Macro 38 } 39 var arr []macro 40 for name, mc := range ast.Macros { 41 if !g.inCurFile(mc) { 42 continue 43 } 44 if mc.IsFnLike() { 45 continue // we don't support function macros yet 46 } 47 if len(mc.ReplacementTokens()) == 0 { 48 continue // no value 49 } 50 arr = append(arr, macro{name.String(), mc}) 51 } 52 sort.Slice(arr, func(i, j int) bool { 53 return arr[i].m.Position().Offset < arr[j].m.Position().Offset 54 }) 55 var decls []CDecl 56 for _, mc := range arr { 57 if val := g.evalMacro(mc.m, ast); val != nil { 58 typ := val.CType(nil) 59 id := types.NewIdent(mc.name, typ) 60 decls = append(decls, &CVarDecl{Const: true, CVarSpec: CVarSpec{ 61 g: g, Type: typ, 62 Names: []*types.Ident{id}, 63 Inits: []Expr{val}, 64 }}) 65 } 66 } 67 return decls 68 } 69 70 func (g *translator) evalMacro(m *cc.Macro, ast *cc.AST) Expr { 71 toks := m.ReplacementTokens() 72 if len(toks) != 1 { 73 return evalMacro2(m, ast) 74 } 75 76 src := strings.TrimSpace(toks[0].Src.String()) 77 if len(src) == 0 { 78 return nil 79 } 80 81 if src[0] == '"' { 82 if s, err := strconv.Unquote(src); err == nil { 83 if l, err := g.parseCStringLit(s); err == nil { 84 return l 85 } 86 } 87 } else { 88 if l, err := parseCIntLit(src); err == nil { 89 return l 90 } 91 if l, err := parseCFloatLit(src); err == nil { 92 return l 93 } 94 } 95 96 return evalMacro2(m, ast) 97 } 98 99 func evalMacro2(m *cc.Macro, ast *cc.AST) Expr { 100 op, err := ast.Eval(m) 101 if err != nil { 102 return nil 103 } 104 105 switch x := op.Value().(type) { 106 case cc.Int64Value: 107 return cIntLit(int64(x)) 108 case cc.Uint64Value: 109 return cUintLit(uint64(x)) 110 default: 111 return nil 112 } 113 }