annotate R/rdyncall/R/dynstruct.R @ 62:4a9f6c7c09c1 default tip

- fix inccorect overflow errors for int (and long on LLP64 systems)
author Tassilo Philipp
date Sat, 18 May 2024 15:33:54 +0200
parents 0cfcc391201f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
1 # Package: rdyncall
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
2 # File: R/dynstruct.R
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
3 # Description: Handling of aggregate (struct/union) C types
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
4
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
5 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
6 # dynport basetype sizes
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
7
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
8 .basetypeSizes <- c(
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
9 B=.Machine$sizeof.long,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
10 c=1,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
11 C=1,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
12 s=2,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
13 S=2,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
14 i=4,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
15 I=4,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
16 j=.Machine$sizeof.long,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
17 J=.Machine$sizeof.long,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
18 l=.Machine$sizeof.longlong,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
19 L=.Machine$sizeof.longlong,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
20 f=4,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
21 d=8,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
22 p=.Machine$sizeof.pointer,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
23 x=.Machine$sizeof.pointer,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
24 Z=.Machine$sizeof.pointer,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
25 v=0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
26 )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
27
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
28 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
29 # dynport type information
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
30 #
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
31
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
32 TypeInfo <- function(name, type = c("base","pointer","struct","union"), size = NA, align = NA, basetype = NA, fields = NA, signature = NA)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
33 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
34 type <- match.arg(type)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
35 x <- list(name = name, type = type, size = size, align = align, basetype = basetype, fields = fields, signature = signature)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
36 class(x) <- "typeinfo"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
37 return(x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
38 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
39
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
40 is.TypeInfo <- function(x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
41 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
42 inherits(x, "typeinfo")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
43 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
44
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
45 getTypeInfo <- function(name, envir=parent.frame())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
46 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
47 if (is.character(name)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
48 getTypeInfoByName(name, envir)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
49 } else if (is.TypeInfo(name)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
50 name
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
51 } else {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
52 stop("unknown type")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
53 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
54 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
55
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
56 getTypeInfoByName <- function(typeName, envir=parent.frame())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
57 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
58 char1 <- substr(typeName, 1, 1)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
59 switch(char1,
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
60 "*"=TypeInfo(name=typeName, type="pointer", size=.Machine$sizeof.pointer, align=.Machine$sizeof.pointer, basetype=substr(typeName,2,nchar(typeName)), signature=typeName),
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
61 "<"={
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
62 x <- getTypeInfo(substr(typeName, 2,nchar(typeName)-1), envir=envir)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
63 if (!is.null(x))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
64 return(x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
65 else
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
66 return(TypeInfo(name=typeName, type="struct"))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
67 },
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
68 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
69 # try as basetype
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
70 basetypeSize <- unname(.basetypeSizes[typeName])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
71 if ( !is.na(basetypeSize) ) return(TypeInfo(name=typeName,type="base", size=basetypeSize, align=basetypeSize, signature=typeName))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
72 # try lookup symbol
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
73 else if (exists(typeName,envir=envir) ) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
74 info <- get(typeName,envir=envir)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
75 if (!inherits(info, "typeinfo")) stop("not a type information symbol")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
76 return(info)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
77 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
78 # otherwise fail
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
79 else NULL
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
80 # else stop("unknown type info: ",typeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
81 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
82 )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
83 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
84
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
85 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
86 # align C offsets
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
87
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
88 align <- function(offset, alignment)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
89 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
90 as.integer( as.integer( (offset + alignment-1) / alignment ) * alignment )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
91 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
92
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
93 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
94 # field information (structures and unions)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
95
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
96 makeFieldInfo <- function(fieldNames, types, offsets)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
97 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
98 data.frame(type=I(types), offset=offsets, row.names=fieldNames)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
99 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
100
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
101 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
102 # parse structure signature
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
103
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
104 makeStructInfo <- function(name, signature, fieldNames, envir=parent.frame())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
105 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
106 # computations:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
107 types <- character()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
108 offsets <- integer()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
109 offset <- 0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
110 maxAlign <- 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
111 # scan variables:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
112 n <- nchar(signature)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
113 i <- 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
114 start <- i
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
115 while(i <= n)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
116 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
117 char <- substr(signature,i,i)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
118 if (char == "*") {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
119 i <- i + 1 ; next
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
120 } else if (char == "<") {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
121 i <- i + 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
122 while (i < n) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
123 if ( substr(signature,i,i) == ">" ) break
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
124 i <- i + 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
125 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
126 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
127 typeName <- substr(signature, start, i)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
128 types <- c(types, typeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
129 typeInfo <- getTypeInfo(typeName, envir=envir)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
130 alignment <- typeInfo$align
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
131 maxAlign <- max(maxAlign, alignment)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
132 offset <- align( offset, alignment )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
133 offsets <- c(offsets, offset)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
134
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
135 # increment offset by size
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
136 offset <- offset + typeInfo$size
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
137
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
138 # next token
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
139 i <- i + 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
140 start <- i
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
141 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
142 # align the structure size (compiler-specific?)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
143 size <- align(offset, maxAlign)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
144 # build field information
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
145 fields <- makeFieldInfo(fieldNames, types, offsets)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
146 TypeInfo(name=name,type="struct",size=size,align=maxAlign,fields=fields)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
147 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
148
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
149 parseStructInfos <- function(sigs, envir=parent.frame())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
150 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
151 # split functions at ';'
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
152 sigs <- unlist( strsplit(sigs, ";") )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
153 # split name/struct signature at '('
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
154 sigs <- strsplit(sigs, "[{]")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
155 infos <- list()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
156 for (i in seq(along=sigs))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
157 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
158 n <- length(sigs[[i]])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
159 if ( n == 2 ) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
160 # parse structure name
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
161 name <- sigs[[i]][[1]]
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
162 name <- gsub("[ \n\t]*","",name)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
163 # split struct signature and field names
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
164 tail <- unlist( strsplit(sigs[[i]][[2]], "[}]") )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
165 sig <- tail[[1]]
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
166 if (length(tail) == 2)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
167 fields <- unlist( strsplit( tail[[2]], "[ \n\t]+" ) )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
168 else
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
169 fields <- NULL
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
170 assign(name, makeStructInfo(name, sig, fields, envir=envir), envir=envir)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
171 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
172 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
173 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
174
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
175 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
176 # parse union signature
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
177
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
178 makeUnionInfo <- function(name, signature, fieldNames, envir=parent.frame())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
179 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
180 # computations:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
181 types <- character()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
182 maxSize <- 0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
183 maxAlign <- 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
184 # scan variables:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
185 i <- 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
186 start <- i
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
187 n <- nchar(signature)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
188 while(i <= n) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
189 char <- substr(signature,i,i)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
190 if (char == "*") {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
191 i <- i + 1 ; next
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
192 } else if (char == "<") {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
193 i <- i + 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
194 while (i < n) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
195 if ( substr(signature,i,i) == ">" ) break
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
196 i <- i + 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
197 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
198 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
199 typeName <- substr(signature,start,i)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
200 types <- c(types, typeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
201 typeInfo <- getTypeInfo(typeName, envir)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
202 maxSize <- max( maxSize, typeInfo$size )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
203 maxAlign <- max( maxAlign, typeInfo$align )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
204 # next token
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
205 i <- i + 1
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
206 start <- i
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
207 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
208 offsets <- rep(0, length(types) )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
209 fields <- makeFieldInfo(fieldNames, types, offsets)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
210 TypeInfo(name=name, type="union", fields=fields, size=maxSize, align=maxAlign)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
211 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
212
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
213 parseUnionInfos <- function(sigs, envir=parent.frame())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
214 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
215 # split functions at ';'
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
216 sigs <- unlist( strsplit(sigs, ";") )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
217 # split name/union signature at '|'
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
218 sigs <- strsplit(sigs, "[|]")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
219 infos <- list()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
220 for (i in seq(along=sigs))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
221 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
222 n <- length(sigs[[i]])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
223 if ( n == 2 ) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
224 # parse union name
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
225 name <- sigs[[i]][[1]]
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
226 name <- gsub("[ \n\t]*","",name)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
227 # split union signature and field names
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
228 tail <- unlist( strsplit(sigs[[i]][[2]], "[}]") )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
229 sig <- tail[[1]]
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
230 if (length(tail) == 2)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
231 fields <- unlist( strsplit( tail[[2]], "[ \n\t]+" ) )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
232 else
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
233 fields <- NULL
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
234 assign( name, makeUnionInfo(name, sig, fields, envir=envir), envir=envir )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
235 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
236 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
237 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
238
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
239
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
240 # ----------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
241 # raw backed struct's (S3 Class)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
242
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
243 as.struct <- function(x, type)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
244 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
245 if (is.TypeInfo(x)) structName <- type$name
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
246 attr(x, "struct") <- type
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
247 class(x) <- "struct"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
248 return(x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
249 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
250
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
251 new.struct <- function(type)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
252 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
253 if (is.character(type)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
254 name <- type
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
255 type <- getTypeInfo(type)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
256 } else if (is.TypeInfo(type)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
257 name <- type$name
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
258 } else {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
259 stop("type is not of class TypeInfo and no character string")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
260 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
261 if (! type$type %in% c("struct","union") ) stop("type must be C struct or union.")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
262 x <- raw( type$size )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
263 class(x) <- "struct"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
264 attr(x, "struct") <- type$name
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
265 return(x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
266 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
267
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
268 "$.struct" <-
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
269 unpack.struct <- function(x, index)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
270 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
271 structName <- attr(x, "struct")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
272 structInfo <- getTypeInfo(structName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
273 fieldInfos <- structInfo$fields
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
274 offset <- fieldInfos[index,"offset"]
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
275 if (is.na(offset)) stop("unknown field index '", index ,"'")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
276 fieldTypeName <- as.character(fieldInfos[[index,"type"]])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
277 fieldTypeInfo <- getTypeInfo(fieldTypeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
278 if (fieldTypeInfo$type %in% c("base","pointer")) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
279 .unpack(x, offset, fieldTypeInfo$signature)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
280 } else if ( !is.null(fieldTypeInfo$fields) ) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
281 if (is.raw(x)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
282 size <- fieldTypeInfo$size
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
283 as.struct( x[(offset+1):(offset+1+size-1)], fieldTypeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
284 } else if (is.externalptr(x)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
285 as.struct( offsetPtr(x, offset), fieldTypeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
286 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
287 } else {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
288 stop("invalid field type '", fieldTypeName,"' at field '", index )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
289 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
290 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
291
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
292 "$<-.struct" <-
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
293 pack.struct <- function( x, index, value )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
294 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
295 structName <- attr(x, "struct")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
296 structInfo <- getTypeInfo(structName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
297 fieldInfos <- structInfo$fields
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
298 offset <- fieldInfos[index,"offset"]
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
299 if (is.na(offset)) stop("unknown field index '", index ,"'")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
300 fieldTypeName <- as.character(fieldInfos[index,"type"])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
301 fieldTypeInfo <- getTypeInfo(fieldTypeName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
302 if ( fieldTypeInfo$type %in% c("base","pointer") ) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
303 .pack( x, offset, fieldTypeInfo$signature, value )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
304 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
305 else if ( !is.null(fieldTypeInfo$fields) ) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
306 # substructure
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
307 size <- fieldTypeInfo$size
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
308 x[(offset+1):(offset+1+size-1)] <- as.raw(value)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
309 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
310 else {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
311 stop("invalid field type '", fieldTypeName,"' at field '", index )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
312 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
313 return(x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
314 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
315
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
316 print.struct <- function(x, indent=0, ...)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
317 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
318 structName <- attr(x, "struct")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
319 structInfo <- getTypeInfo(structName)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
320 fieldInfos <- structInfo$fields
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
321 fieldNames <- rownames(fieldInfos)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
322
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
323 cat( "struct ", structName, " ")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
324 if (typeof(x) == "externalptr") {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
325 cat ("*")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
326 if (is.nullptr(x)) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
327 cat("=NULL\n")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
328 return()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
329 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
330 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
331 cat("{\n")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
332 # print data without last
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
333 for (i in seq(along=fieldNames))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
334 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
335 cat( rep(" ", indent+1), fieldNames[[i]] , ":" )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
336 val <- unpack.struct(x, fieldNames[[i]])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
337 if (typeof(val) == "externalptr") val <- "ptr" # .extptr2str(val)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
338 if (class(val) == "struct") { print.struct(val, indent=indent+1) }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
339 else cat( val, "\n" )
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
340 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
341 cat( rep(" ", indent), "}\n")
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
342 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
343