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  }