github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/transpiler/vaarg.go (about) 1 package transpiler 2 3 import ( 4 "fmt" 5 goast "go/ast" 6 "go/token" 7 "strings" 8 9 "github.com/Konstantin8105/c4go/ast" 10 "github.com/Konstantin8105/c4go/program" 11 "github.com/Konstantin8105/c4go/types" 12 "github.com/Konstantin8105/c4go/util" 13 ) 14 15 func transpileVAArgExpr(n *ast.VAArgExpr, p *program.Program) ( 16 expr goast.Expr, 17 exprType string, 18 preStmts []goast.Stmt, 19 postStmts []goast.Stmt, 20 err error) { 21 defer func() { 22 if err != nil { 23 err = fmt.Errorf("cannot transpileVAArgExpr. %v", err) 24 } 25 }() 26 // -VAArgExpr 'int' 27 // `-ImplicitCastExpr 'struct __va_list_tag *' <ArrayToPointerDecay> 28 // `-DeclRefExpr 'va_list':'...' lvalue Var 'ap' 'va_list':'...' 29 30 p.IsHaveVaList = true 31 32 expr, exprType, preStmts, postStmts, err = atomicOperation(n.Children()[0], p) 33 if err != nil { 34 return expr, exprType, preStmts, postStmts, err 35 } 36 37 goType, err := types.ResolveType(p, n.Type) 38 if err != nil { 39 return expr, exprType, preStmts, postStmts, err 40 } 41 42 expr = &goast.TypeAssertExpr{ 43 X: util.NewCallExpr(va_arg, expr), 44 Lparen: 1, 45 Type: goast.NewIdent(goType), 46 } 47 exprType = n.Type 48 return 49 } 50 51 func getVaListStruct() string { 52 return ` 53 54 // va_list is C4GO implementation of va_list from "stdarg.h" 55 type va_list struct{ 56 position int 57 Slice []interface{} 58 } 59 60 func create_va_list(list []interface{}) * va_list{ 61 return &va_list{ 62 position: 0, 63 Slice : list, 64 } 65 } 66 67 func va_start(v * va_list, count interface{}) { 68 v.position = 0 69 } 70 71 func va_end(v * va_list) { 72 // do nothing 73 } 74 75 func va_arg(v * va_list) interface{} { 76 defer func(){ 77 v.position++ 78 }() 79 value := v.Slice[v.position] 80 switch value.(type) { 81 case int: 82 return int32(value.(int)) 83 default: 84 return value 85 } 86 } 87 88 ` 89 } 90 91 const ( 92 create_va_list string = "create_va_list" 93 va_arg = "va_arg" 94 va_start = "va_start" 95 va_end = "va_end" 96 ) 97 98 func VaListInit(p *program.Program, name string) []goast.Decl { 99 // variable for va_list. see "variadic function" 100 // header : <stdarg.h> 101 // Example : 102 // DeclStmt 0x2fd87e0 <line:442:2, col:14> 103 // `-VarDecl 0x2fd8780 <col:2, col:10> col:10 used args 'va_list':'struct __va_list_tag [1]' 104 // Result: 105 // ... - convert to - c4goArgs ...interface{} 106 // var args = c4goArgs 107 108 p.IsHaveVaList = true 109 110 return []goast.Decl{&goast.GenDecl{ 111 Tok: token.VAR, 112 Specs: []goast.Spec{ 113 &goast.ValueSpec{ 114 Names: []*goast.Ident{util.NewIdent(name)}, 115 Values: []goast.Expr{ 116 util.NewCallExpr(create_va_list, util.NewIdent("c4goArgs")), 117 }, 118 }, 119 }, 120 }} 121 } 122 123 func changeVaListFuncs(functionName *string) { 124 switch *functionName { 125 case "__builtin_va_start": 126 mod := va_start 127 *functionName = mod 128 case "__builtin_va_end": 129 mod := va_end 130 *functionName = mod 131 } 132 return 133 } 134 135 func ignoreVaListTypedef(name string) bool { 136 if strings.Contains(name, "va_list") { 137 return true 138 } 139 return false 140 }