1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.ochafik.lang.jnaerator;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22
23 import java.util.List;
24
25 import com.ochafik.lang.jnaerator.TypeConversion.JavaPrim;
26 import com.ochafik.lang.jnaerator.TypeConversion.TypeConversionMode;
27 import com.ochafik.lang.jnaerator.parser.Arg;
28 import com.ochafik.lang.jnaerator.parser.DeclarationsHolder;
29 import com.ochafik.lang.jnaerator.parser.Declarator;
30 import com.ochafik.lang.jnaerator.parser.Expression;
31 import com.ochafik.lang.jnaerator.parser.Function;
32 import com.ochafik.lang.jnaerator.parser.Identifier;
33 import com.ochafik.lang.jnaerator.parser.Modifier;
34 import com.ochafik.lang.jnaerator.parser.Statement;
35 import com.ochafik.lang.jnaerator.parser.Struct;
36 import com.ochafik.lang.jnaerator.parser.TypeRef;
37 import com.ochafik.lang.jnaerator.parser.VariablesDeclaration;
38 import com.ochafik.lang.jnaerator.parser.Declarator.PointerStyle;
39 import com.ochafik.lang.jnaerator.parser.Expression.MemberRefStyle;
40 import com.ochafik.lang.jnaerator.parser.Expression.VariableRef;
41 import com.ochafik.lang.jnaerator.runtime.globals.GlobalCallback;
42 import com.ochafik.lang.jnaerator.runtime.globals.GlobalPointer;
43 import com.ochafik.lang.jnaerator.runtime.globals.GlobalPointerType;
44 import com.ochafik.lang.jnaerator.runtime.globals.GlobalStruct;
45 import com.sun.jna.Pointer;
46 import com.sun.jna.Structure;
47 import com.sun.jna.ptr.ByReference;
48
49 import static com.ochafik.lang.jnaerator.parser.ElementsHelper.*;
50 public class GlobalsGenerator {
51 public GlobalsGenerator(Result result) {
52 this.result = result;
53 }
54
55 final Result result;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @SuppressWarnings("unchecked")
73 public void convertGlobals(VariablesDeclaration globals, Signatures signatures, DeclarationsHolder out, Expression nativeLibFieldExpr, Identifier callerLibraryName, String callerLibrary) throws UnsupportedConversionException {
74 for (Declarator d : globals.getDeclarators()) {
75 try {
76 Identifier name = result.typeConverter.getValidJavaArgumentName(ident(d.resolveName()));
77 TypeRef type = (TypeRef)d.mutateType(globals.getValueType());
78 if (type == null)
79 continue;
80
81 boolean isCallback = result.callbacksByName.containsKey(ident(type.toString()));
82 List<Modifier> modifiers = new ArrayList<Modifier>(type.getModifiers());
83 modifiers.addAll(globals.getModifiers());
84
85 type.setModifiers(Collections.EMPTY_LIST);
86
87 if ( !isCallback &&
88 !(Modifier.Extern.isContainedBy(modifiers) || Modifier.Dllexport.isContainedBy(modifiers) || Modifier.Dllimport.isContainedBy(modifiers))
89
90 ) {
91
92 continue;
93 }
94
95
96 if (true) {
97 if (!signatures.variablesSignatures.add(name.toString()))
98 continue;
99
100 boolean isPointer = type instanceof com.ochafik.lang.jnaerator.parser.TypeRef.Pointer;
101 JavaPrim prim = result.typeConverter.getPrimitive(isPointer ? ((com.ochafik.lang.jnaerator.parser.TypeRef.Pointer)type).getTarget() : type, callerLibraryName);
102 type.setMarkedAsResolved(false);
103 TypeRef convertedType = result.typeConverter.convertTypeToJNA(type, TypeConversionMode.NativeParameter, callerLibraryName);
104 String convTypStr = convertedType.toString();
105 if (convTypStr.endsWith(".ByValue"))
106 convTypStr = convTypStr.substring(0, convTypStr.length() - ".ByValue".length());
107 boolean isStruct = result.structsFullNames.contains(ident(convTypStr));
108 boolean isUnion = result.unionsFullNames.contains(ident(convTypStr));
109
110
111 if (prim != null || isCallback || isStruct || isUnion) {
112 TypeRef globalType = null;
113 Expression extraArg = null;
114
115 if (isUnion || isStruct) {
116 globalType = typeRef(ident(GlobalStruct.class, expr(convertedType.clone())));
117 extraArg = memberRef(expr(convertedType.clone()), MemberRefStyle.Dot, "class");
118 } else if (isCallback) {
119 globalType = typeRef(ident(GlobalCallback.class, expr(type.clone())));
120 extraArg = memberRef(expr(type.clone()), MemberRefStyle.Dot, "class");
121 } else if (isPointer) {
122 Class<? extends ByReference> brt = TypeConversion.primToByReference.get(prim);
123 if (brt != null) {
124 globalType = typeRef(ident(GlobalPointerType.class, expr(typeRef(ident(brt)))));
125 extraArg = classLiteral(brt);
126 } else if (prim == JavaPrim.Void) {
127 globalType = typeRef(GlobalPointer.class);
128 }
129 } else {
130 Class<?> globalClass = TypeConversion.primToGlobal.get(prim);
131 if (globalClass != null)
132 globalType = typeRef(globalClass);
133 }
134 if (globalType != null) {
135 List<Expression> constructorArgs = new ArrayList<Expression>();
136 constructorArgs.add(nativeLibFieldExpr.clone());
137 if (extraArg != null) {
138 constructorArgs.add(extraArg);
139 }
140 constructorArgs.add(expr(name.toString()));
141 VariablesDeclaration vd = new VariablesDeclaration(
142 globalType,
143 new Declarator.DirectDeclarator(
144 name.toString(),
145 new Expression.New(
146 globalType.clone(),
147 constructorArgs.toArray(new Expression[constructorArgs.size()])
148 )
149 )
150 );
151
152 vd.addModifiers(Modifier.Public, Modifier.Static, Modifier.Final);
153 vd.importDetails(globals, false);
154 vd.moveAllCommentsBefore();
155
156 out.addDeclaration(vd);
157 continue;
158 }
159 }
160 }
161
162 if (!signatures.classSignatures.add(name))
163 continue;
164
165
166
167 Struct struct = result.declarationsConverter.publicStaticClass(name, null, Struct.Type.JavaClass, null);
168 struct.addModifiers(Modifier.Final);
169 struct.importDetails(globals, false);
170 struct.moveAllCommentsBefore();
171
172 TypeRef pointerType = new TypeRef.Pointer(type, PointerStyle.Pointer);
173
174 TypeRef convPointerType = result.typeConverter.convertTypeToJNA(pointerType, TypeConversionMode.FieldType, callerLibraryName);
175 TypeRef instType;
176 boolean hasOffset, isPtr = false, isByRef = false;
177 String convPointerTypeStr = convPointerType.toString();
178 if (convPointerTypeStr.equals(Pointer.class.getName())) {
179 isPtr = true;
180 instType = convPointerType;
181 hasOffset = false;
182 } else if (TypeConversion.byReferenceClassesNames.contains(convPointerTypeStr)) {
183 isByRef = true;
184 instType = convPointerType;
185 hasOffset = false;
186 } else if (convPointerTypeStr.endsWith(".ByReference") && result.structsByName.get(convPointerTypeStr.substring(0, convPointerTypeStr.length() - ".ByReference".length())) != null) {
187 instType = result.typeConverter.convertTypeToJNA(type, TypeConversionMode.PointedValue, callerLibraryName);
188 hasOffset = true;
189 } else {
190 Identifier instTypeName = ident(name + "_holder");
191 Struct holderStruct = result.declarationsConverter.publicStaticClass(instTypeName, ident(Structure.class), Struct.Type.JavaClass, null);
192 holderStruct.addModifiers(Modifier.Final);
193 VariablesDeclaration vd = result.declarationsConverter.convertVariablesDeclaration("value", type, new int[1], callerLibraryName);
194 if (vd.getValueType().toString().equals(Pointer.class.getName())) {
195 isByRef = true;
196 instType = convPointerType;
197 hasOffset = false;
198 } else {
199 holderStruct.addDeclaration(vd);
200 Function pointerConstructor = new Function(Function.Type.JavaMethod, instTypeName, null,
201 new Arg("pointer", new TypeRef.SimpleTypeRef(Pointer.class.getName()))
202 );
203 hasOffset = false;
204 pointerConstructor.setBody(new Statement.Block(
205 new Statement.ExpressionStatement(methodCall("super")),
206 new Statement.ExpressionStatement(methodCall("useMemory", varRef("pointer"), expr(0))),
207 new Statement.ExpressionStatement(methodCall("read"))
208 ));
209 holderStruct.addDeclaration(pointerConstructor);
210
211
212 instType = new TypeRef.SimpleTypeRef(instTypeName);
213 struct.addDeclaration(decl(holderStruct));
214 }
215 }
216 Identifier instName = name;
217 struct.addDeclaration(new VariablesDeclaration(instType, new Declarator.DirectDeclarator(instName.toString())).addModifiers(Modifier.Private, Modifier.Static));
218 VariableRef instRef = new VariableRef(instName);
219 Expression ptrExpr = methodCall(
220 nativeLibFieldExpr.clone(),
221 MemberRefStyle.Dot,
222 "getGlobalVariableAddress",
223 expr(name.toString())
224 );
225 List<Statement> initStats = new ArrayList<Statement>();
226 initStats.add(new Statement.ExpressionStatement(
227 expr(
228 instRef.clone(),
229 Expression.AssignmentOperator.Equal,
230 isPtr ? ptrExpr :
231 isByRef ? new Expression.New(instType) :
232 new Expression.New(instType, new Expression.FunctionCall(null, ptrExpr, hasOffset ? expr(0) : null))
233 )
234 ));
235 if (isByRef)
236 initStats.add(new Statement.ExpressionStatement(methodCall(instRef, MemberRefStyle.Dot, "setPointer", ptrExpr)));
237
238 struct.addDeclaration(new Function(Function.Type.JavaMethod, ident("get"), instType).setBody(new Statement.Block(
239 new Statement.If(
240 expr(instRef, Expression.BinaryOperator.IsEqual, nullExpr()),
241 initStats.size() == 1 ? initStats.get(0) : new Statement.Block(initStats),
242 null
243 ),
244 new Statement.Return(instRef.clone())
245 )).addModifiers(Modifier.Public, Modifier.Static, Modifier.Synchronized));
246 out.addDeclaration(decl(struct));
247 } catch (Throwable t) {
248 out.addDeclaration(result.declarationsConverter.skipDeclaration(d, t.toString()));
249 }
250 }
251 }
252
253 public void convertGlobals(List<VariablesDeclaration> list, Signatures signatures, DeclarationsHolder out, Expression nativeLibFieldExpr, Identifier libraryNameExpression, String library) {
254 if (list == null)
255 return;
256
257 for (VariablesDeclaration v : list) {
258 try {
259 convertGlobals(v, signatures, out, nativeLibFieldExpr, libraryNameExpression, library);
260 } catch (UnsupportedConversionException ex) {
261 out.addDeclaration(result.declarationsConverter.skipDeclaration(v, ex.toString()));
262 }
263 }
264 }
265 }