github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/transpiler/offset.go (about) 1 package transpiler 2 3 import ( 4 "bytes" 5 "fmt" 6 goast "go/ast" 7 8 "github.com/Konstantin8105/c4go/ast" 9 "github.com/Konstantin8105/c4go/program" 10 "github.com/Konstantin8105/c4go/util" 11 ) 12 13 func transpileOffsetOfExpr(n *ast.OffsetOfExpr, p *program.Program) ( 14 expr goast.Expr, exprType string, err error) { 15 // clang ast haven`t enough information about OffsetOfExpr 16 defer func() { 17 if err != nil { 18 err = fmt.Errorf("cannot transpile OffsetOfExpr. %v", err) 19 } 20 }() 21 22 var buffer []byte 23 pos := n.Position() 24 buffer, err = p.PreprocessorFile.GetSnippet(pos.File, 25 pos.Line, pos.LineEnd, 26 pos.Column, pos.ColumnEnd) 27 if err != nil { 28 err = fmt.Errorf("cannot found snippet position is %v. %v", 29 n.Position(), err) 30 return 31 } 32 33 if len(buffer) == 0 { 34 err = fmt.Errorf("buffer is empty") 35 return 36 } 37 38 if !bytes.HasPrefix(buffer, []byte("__builtin_offsetof(")) { 39 err = fmt.Errorf("haven`t prefix `__builtin_offsetof(` in buffer `%v`", 40 string(buffer)) 41 return 42 } 43 44 buffer = buffer[len("__builtin_offsetof(") : len(buffer)-1] 45 46 // separate by `,` 47 arguments := bytes.Split(buffer, []byte(",")) 48 if len(arguments) != 2 { 49 err = fmt.Errorf("not correct amount of arguments in `%v` found %v", 50 string(buffer), len(arguments)) 51 return 52 } 53 54 for i := range arguments { 55 arguments[i] = bytes.TrimSpace(arguments[i]) 56 } 57 58 // preparing name of struct 59 if bytes.HasPrefix(arguments[0], []byte("struct ")) { 60 arguments[0] = arguments[0][len("struct "):] 61 } 62 63 p.AddImport("unsafe") 64 expr = util.NewCallExpr("unsafe.Offsetof", 65 &goast.SelectorExpr{ 66 X: &goast.CompositeLit{ 67 Type: goast.NewIdent(string(arguments[0])), 68 Lbrace: 1, 69 }, 70 Sel: goast.NewIdent(string(arguments[1])), 71 }) 72 73 exprType = n.Type 74 return 75 }