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