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  }