GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
JavaConfiguration.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2023 JogAmp Community. All rights reserved.
3 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * - Redistribution of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistribution in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of Sun Microsystems, Inc. or the names of
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use
34 * in the design, construction, operation or maintenance of any nuclear
35 * facility.
36 *
37 * Sun gratefully acknowledges that this software was originally authored
38 * and developed by Kenneth Bradley Russell and Christopher John Kline.
39 */
40
41package com.jogamp.gluegen;
42
43import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
44import com.jogamp.gluegen.JavaEmitter.EmissionStyle;
45import com.jogamp.gluegen.JavaEmitter.MethodAccess;
46import com.jogamp.gluegen.Logging.LoggerIf;
47
48import java.io.*;
49import java.lang.reflect.Array;
50import java.util.*;
51import java.util.regex.*;
52
53import com.jogamp.gluegen.jgram.*;
54import com.jogamp.gluegen.cgram.types.*;
55
56import static java.util.logging.Level.*;
57import static com.jogamp.gluegen.JavaEmitter.MethodAccess.*;
58import static com.jogamp.gluegen.JavaEmitter.EmissionStyle.*;
59
60/** Parses and provides access to the contents of .cfg files for the
61 JavaEmitter. */
62
63public class JavaConfiguration {
64 private int nestedReads;
65 private String libraryOnLoadName;
66 private String packageName;
67 private String implPackageName;
68 private String className;
69 private String implClassName;
70
71 protected final LoggerIf LOG;
72
73 public static String NEWLINE = System.getProperty("line.separator");
74
75 /**
76 * Root directory for the hierarchy of generated java classes. Default is
77 * working directory.
78 */
79 private String javaOutputDir = ".";
80
81 /**
82 * Top output root directory for all generated files. Default is null, ie not to use it.
83 */
84 private String outputRootDir = null;
85
86 /**
87 * Directory into which generated native JNI code will be written. Default
88 * is current working directory.
89 */
90 private String nativeOutputDir = ".";
91
92 /**
93 * If true, then each native *.c and *.h file will be generated in the
94 * directory nativeOutputDir/packageAsPath(packageName). Default is false.
95 */
96 private boolean nativeOutputUsesJavaHierarchy;
97
98 /**
99 * If true, then the comment of a native method binding will include a @native tag
100 * to allow taglets to augment the javadoc with additional information regarding
101 * the mapped C function. Defaults to false.
102 */
103 private boolean tagNativeBinding;
104
105 /**
106 * If true, {@link TypeConfig.SemanticEqualityOp#equalSemantics(TypeConfig.SemanticEqualityOp)}
107 * will attempt to perform a relaxed semantic equality test, e.g. skip the {@code const} and {@code volatile} qualifiers.
108 * Otherwise a full semantic equality test will be performed.
109 */
110 private boolean relaxedEqualSemanticsTest;
111
112 /**
113 * Style of code emission. Can emit everything into one class
114 * (AllStatic), separate interface and implementing classes
115 * (InterfaceAndImpl), only the interface (InterfaceOnly), or only
116 * the implementation (ImplOnly).
117 */
118 private EmissionStyle emissionStyle = AllStatic;
119
120 /**
121 * List of imports to emit at the head of the output files.
122 */
123 private final List<String> imports = new ArrayList<String>();
124
125 /**
126 * The package in which the generated glue code expects to find its
127 * run-time helper classes (Buffers, Platform,
128 * StructAccessor). Defaults to "com.jogamp.gluegen.runtime".
129 */
130 private String gluegenRuntimePackage = "com.jogamp.gluegen.runtime";
131
132 /**
133 * The kind of exception raised by the generated code if run-time
134 * checks fail. Defaults to RuntimeException.
135 */
136 private String runtimeExceptionType = "RuntimeException";
137 private String unsupportedExceptionType = "UnsupportedOperationException";
138
139 private final Map<String, MethodAccess> accessControl = new HashMap<String, MethodAccess>();
140 private final Map<String, TypeInfo> typeInfoMap = new HashMap<String, TypeInfo>();
141 private final Set<String> returnsString = new HashSet<String>();
142 private final Set<String> returnsStringOnly = new HashSet<String>();
143 private final Map<String, JavaType> returnsOpaqueJType = new HashMap<String, JavaType>();
144 private final Map<String, String> returnedArrayLengths = new HashMap<String, String>();
145 private final Set<String> maxOneElement = new HashSet<String>();
146
147 /**
148 * Key is function that has some byte[] or short[] arguments that should be
149 * converted to String args; value is List of Integer argument indices
150 */
151 private final Map<String, List<Integer>> argumentsAreString = new HashMap<String, List<Integer>>();
152
153 /**
154 * Key is function that has a pascal string, i.e. length and some byte[] or short[] arguments that should be
155 * converted to String args; value is a list of PascalStringArg
156 */
157 private final Map<String, List<JavaType.PascalStringElem>> argumentsArePascalString = new HashMap<String, List<JavaType.PascalStringElem>>();
158
159 /** JavaCallback configuration definition (static) */
160 public static class JavaCallbackDef {
161 final String cbFuncTypeName;
162 final int cbFuncUserParamIdx;
163 final String setFuncName;
164 final int setFuncUserParamIdx; // optional
165 final List<Integer> cbFuncKeyIndices = new ArrayList<Integer>();
166 final String userParamClassName; // optional
167 final String customKeyClassName; // optional
168 final List<Integer> setFuncKeyIndices = new ArrayList<Integer>();
169 JavaCallbackDef(final String cbFuncTypeName, final int cbFuncUserParamIdx, final String setFuncName, final int setFuncUserParamIdx,
170 final String userParamClassName, final String customKeyClassName) {
171 this.cbFuncTypeName = cbFuncTypeName;
172 this.cbFuncUserParamIdx = cbFuncUserParamIdx;
173 this.setFuncName = setFuncName;
174 this.setFuncUserParamIdx = setFuncUserParamIdx;
175 this.userParamClassName = userParamClassName;
176 this.customKeyClassName = customKeyClassName;
177 }
178 @Override
179 public String toString() {
180 return String.format("JavaCallbackDef[cbFunc[type %s, userParamIdx %d, keys %s], set[%s, keys %s, userParamIdx %d], Class[UserParam %s, Key %s]]",
181 cbFuncTypeName, cbFuncUserParamIdx, cbFuncKeyIndices.toString(), setFuncName, setFuncKeyIndices.toString(), setFuncUserParamIdx,
182 userParamClassName, customKeyClassName);
183 }
184 }
185 private final List<JavaCallbackDef> javaCallbackList = new ArrayList<JavaCallbackDef>();
186 private final Map<String, JavaCallbackDef> javaCallbackSetFuncToDef = new HashMap<String, JavaCallbackDef>();
187
188 private final Set<String> extendedIntfSymbolsIgnore = new HashSet<String>();
189 private final Set<String> extendedIntfSymbolsOnly = new HashSet<String>();
190 private final Set<String> extendedImplSymbolsIgnore = new HashSet<String>();
191 private final Set<String> extendedImplSymbolsOnly = new HashSet<String>();
192 private final Set<Pattern> ignores = new HashSet<Pattern>();
193 private final Map<String, Pattern> ignoreMap = new HashMap<String, Pattern>();
194 private final Set<Pattern> ignoreNots = new HashSet<Pattern>();
195 private final Set<Pattern> unignores = new HashSet<Pattern>();
196 private final Set<Pattern> unimplemented = new HashSet<Pattern>();
197 private boolean forceUseNIOOnly4All = false;
198 private final Set<String> useNIOOnly = new HashSet<String>();
199 private boolean forceUseNIODirectOnly4All = false;
200 private final Set<String> useNIODirectOnly = new HashSet<String>();
201 private final Set<String> immutableAccessSymbols = new HashSet<String>();
202 private final Set<String> manuallyImplement = new HashSet<String>();
203 private final Map<String, String> delegatedImplementation = new HashMap<String, String>();
204 private final Map<String, List<String>> customJavaCode = new HashMap<String, List<String>>();
205 private final Map<String, List<String>> customJNICode = new HashMap<String, List<String>>();
206 private final Map<String, List<String>> classJavadoc = new HashMap<String, List<String>>();
207 private final Map<String, List<String>> methodJavadoc = new HashMap<String, List<String>>();
208 private final Map<String, String> structPackages = new HashMap<String, String>();
209 private final List<String> customCCode = new ArrayList<String>();
210 private final List<String> forcedStructs = new ArrayList<String>();
211 private final Map<String, String> structMachineDataInfoIndex = new HashMap<String, String>();
212 private final Map<String, String> returnValueCapacities = new HashMap<String, String>();
213 private final Map<String, String> returnValueLengths = new HashMap<String, String>();
214 private final Map<String, List<String>> temporaryCVariableDeclarations = new HashMap<String, List<String>>();
215 private final Map<String, List<String>> temporaryCVariableAssignments = new HashMap<String, List<String>>();
216 private final Map<String, List<String>> extendedInterfaces = new HashMap<String, List<String>>();
217 private final Map<String, List<String>> implementedInterfaces = new HashMap<String, List<String>>();
218 private final Map<String, String> parentClass = new HashMap<String, String>();
219 private final Map<String, String> javaTypeRenames = new HashMap<String, String>();
220 private final Map<String, String> javaSymbolRenames = new HashMap<String, String>();
221 private final Map<String, Set<String>> javaRenamedSymbols = new HashMap<String, Set<String>>();
222 private final Map<String, List<String>> javaPrologues = new HashMap<String, List<String>>();
223 private final Map<String, List<String>> javaEpilogues = new HashMap<String, List<String>>();
224
226 LOG = Logging.getLogger(JavaConfiguration.class.getPackage().getName(), JavaConfiguration.class.getSimpleName());
227 }
228
229 /** Reads the configuration file.
230 @param filename path to file that should be read
231 */
232 public final void read(final String filename) throws IOException {
233 read(filename, null);
234 }
235
236 /** Reads the specified file, treating each line as if it started with the
237 specified string.
238 @param filename path to file that should be read
239 @param linePrefix if not null, treat each line read as if it were
240 prefixed with the specified string.
241 */
242 protected final void read(final String filename, final String linePrefix) throws IOException {
243 final File file = new File(filename);
244 BufferedReader reader = null;
245 try {
246 reader = new BufferedReader(new FileReader(file));
247 }
248 catch (final FileNotFoundException fnfe) {
249 throw new RuntimeException("Could not read file \"" + file + "\"", fnfe);
250 }
251 int lineNo = 0;
252 String line = null;
253 final boolean hasPrefix = linePrefix != null && linePrefix.length() > 0;
254 try {
255 ++nestedReads;
256 while ((line = reader.readLine()) != null) {
257 ++lineNo;
258 if (hasPrefix) {
259 line = linePrefix + " " + line;
260 }
261
262 if (line.trim().startsWith("#")) {
263 // comment line
264 continue;
265 }
266
267 final StringTokenizer tok = new StringTokenizer(line);
268 if (tok.hasMoreTokens()) {
269 // always reset delimiters in case of CustomJavaCode, etc.
270 final String cmd = tok.nextToken(" \t\n\r\f");
271
272 dispatch(cmd, tok, file, filename, lineNo);
273 }
274 }
275 reader.close();
276 } finally {
277 --nestedReads;
278 }
279
280 if (nestedReads == 0) {
281 if (allStatic() && implClassName != null) {
282 throw new IllegalStateException("Error in configuration file \"" + filename + "\": Cannot use " +
283 "directive \"ImplJavaClass\" in conjunction with " +
284 "\"Style AllStatic\"");
285 }
286
287 if (className == null && (emissionStyle() != ImplOnly)) {
288// throw new RuntimeException("Output class name was not specified in configuration file \"" + filename + "\"");
289 }
290 if (packageName == null && (emissionStyle() != ImplOnly)) {
291 throw new RuntimeException("Output package name was not specified in configuration file \"" + filename + "\"");
292 }
293
294 if (allStatic()) {
295 implClassName = className;
296 // If we're using the "Style AllStatic" directive, then the
297 // implPackageName is the same as the regular package name
298 implPackageName = packageName;
299 } else {
300 if (implClassName == null) {
301 // implClassName defaults to "<className>Impl" if ImplJavaClass
302 // directive is not used
303 if (className == null) {
304 throw new RuntimeException("If ImplJavaClass is not specified, must specify JavaClass");
305 }
306 implClassName = className + "Impl";
307 }
308 if (implPackageName == null) {
309 // implPackageName defaults to "<packageName>.impl" if ImplPackage
310 // directive is not used
311 if (packageName == null) {
312 throw new RuntimeException("If ImplPackageName is not specified, must specify PackageName");
313 }
314 implPackageName = packageName + ".impl";
315 }
316 }
317 }
318 }
319
320 public void setOutputRootDir(final String s) { outputRootDir=s; }
321
322 /** Returns the library basename used to {@link CCodeUnit#emitJNIOnLoadJNIEnvCode(String)}. */
323 public String libraryOnLoadName() {
324 return libraryOnLoadName;
325 }
326
327 /** Returns the package name parsed from the configuration file. */
328 public String packageName() {
329 return packageName;
330 }
331
332 /** Returns the implementation package name parsed from the configuration file. */
333 public String implPackageName() {
334 return implPackageName;
335 }
336
337 /** Returns the class name parsed from the configuration file. */
338 public String className() {
339 return className;
340 }
341
342 /** Returns the implementation class name parsed from the configuration file. */
343 public String implClassName() {
344 return implClassName;
345 }
346
347 public boolean structsOnly() {
348 return className == null && implClassName == null;
349 }
350
351 /** Returns the Java code output directory parsed from the configuration file. */
352 public String javaOutputDir() {
353 return (null != outputRootDir) ? (outputRootDir + "/" + javaOutputDir) : javaOutputDir;
354 }
355
356 /** Returns the native code output directory parsed from the configuration file. */
357 public String nativeOutputDir() {
358 return (null != outputRootDir) ? (outputRootDir + "/" + nativeOutputDir) : nativeOutputDir;
359 }
360
361 /** Returns whether the native code directory structure mirrors the Java hierarchy. */
363 return nativeOutputUsesJavaHierarchy;
364 }
365
366 /** Returns whether the comment of a native method binding should include a @native tag. */
367 public boolean tagNativeBinding() {
368 return tagNativeBinding;
369 }
370
371 /**
372 * Returns whether {@link TypeConfig.SemanticEqualityOp#equalSemantics(TypeConfig.SemanticEqualityOp)}
373 * shall attempt to perform a relaxed semantic equality test, e.g. skip the {@code const} and {@code volatile} qualifier
374 * - or not.
375 */
376 public boolean relaxedEqualSemanticsTest() {
377 return relaxedEqualSemanticsTest;
378 }
379
380 /** Returns the code emission style (constants in JavaEmitter) parsed from the configuration file. */
382 return emissionStyle;
383 }
384
385 /**
386 * Returns the access control for the given method-name
387 * or fully qualified class-name.
388 */
389 public MethodAccess accessControl(final String name) {
390 final MethodAccess ret = accessControl.get(name);
391 if (ret != null) {
392 return ret;
393 }
394 // Default access control is public
395 return PUBLIC;
396 }
397
398 /** Returns the package in which the generated glue code expects to
399 find its run-time helper classes (Buffers, Platform,
400 StructAccessor). Defaults to "com.jogamp.gluegen.runtime". */
401 public String gluegenRuntimePackage() {
402 return gluegenRuntimePackage;
403 }
404
405 /** Returns the kind of exception to raise if run-time checks fail in the generated code. */
406 public String runtimeExceptionType() {
407 return runtimeExceptionType;
408 }
409
410 /** Returns the kind of exception to raise if run-time checks fail in the generated code. */
411 public String unsupportedExceptionType() {
412 return unsupportedExceptionType;
413 }
414
415 /** Returns the list of imports that should be emitted at the top of each .java file. */
416 public List<String> imports() {
417 return imports;
418 }
419
420 private static final boolean DEBUG_TYPE_INFO = false;
421
422 /**
423 * If the given {@code canonicalName} should be considered opaque,
424 * returns the TypeInfo describing the replacement type.
425 * <p>
426 * Returns null if this type should not be considered opaque.
427 * </p>
428 * <p>
429 * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)},
430 * it describes field's array-length or element-count referenced by a pointer.
431 * </p>
432 */
433 public TypeInfo canonicalNameOpaque(final String canonicalName) {
434 return typeInfoMap.get(canonicalName);
435 }
436
437 /** If this type should be considered opaque, returns the TypeInfo
438 describing the replacement type. Returns null if this type
439 should not be considered opaque. */
440 public TypeInfo typeInfo(Type type) {
441 // Because typedefs of pointer types can show up at any point,
442 // walk the pointer chain looking for a typedef name that is in
443 // the TypeInfo map.
444 if (DEBUG_TYPE_INFO)
445 System.err.println("Incoming type = " + type + ", " + type.getDebugString());
446 final int pointerDepth = type.pointerDepth();
447 for (int i = 0; i <= pointerDepth; i++) {
448 String name = type.getName();
449 if (DEBUG_TYPE_INFO) {
450 System.err.printf(" [%2d] Name = %s%n", i, name);
451 System.err.printf(" [%2d] Type = %s, pointerDepth %d, %s%n", i, type, type.pointerDepth(), type.getDebugString());
452 }
453 if (name != null) {
454 final TypeInfo info = closestTypeInfo(name, i + type.pointerDepth());
455 if (info != null) {
456 final TypeInfo res = promoteTypeInfo(info, i);
457 if (DEBUG_TYPE_INFO) {
458 System.err.printf(" [A][%2d] name %s%n", i, name);
459 System.err.printf(" [A][%2d] info %s%n", i, info.toString());
460 System.err.printf(" [A][%2d] res %s%n", i, res.toString());
461 }
462 return res;
463 }
464 }
465
466 if (type.isCompound()) {
467 // Try struct name as well
468 name = type.asCompound().getStructName();
469 if (name != null) {
470 final TypeInfo info = closestTypeInfo(name, i + type.pointerDepth());
471 if (info != null) {
472 final TypeInfo res = promoteTypeInfo(info, i);
473 if (DEBUG_TYPE_INFO) {
474 System.err.printf(" [A][%2d] name %s%n", i, name);
475 System.err.printf(" [A][%2d] info %s%n", i, info.toString());
476 System.err.printf(" [A][%2d] res %s%n", i, res.toString());
477 }
478 return res;
479 }
480 }
481 }
482
483 if (type.isPointer()) {
484 type = type.asPointer().getTargetType();
485 }
486 }
487 if (DEBUG_TYPE_INFO) {
488 System.err.println(" [X] NULL");
489 }
490 return null;
491 }
492
493 // Helper functions for above
494 private TypeInfo closestTypeInfo(final String name, final int pointerDepth) {
495 TypeInfo info = typeInfoMap.get(name);
496 TypeInfo closest = null;
497 while (info != null) {
498 if (DEBUG_TYPE_INFO) {
499 System.err.println(" Checking TypeInfo for " + name + " at pointerDepth " + pointerDepth);
500 }
501 if (info.pointerDepth() <= pointerDepth && (closest == null || info.pointerDepth() > closest.pointerDepth())) {
502 if (DEBUG_TYPE_INFO) {
503 System.err.println(" Accepted");
504 }
505 closest = info;
506 }
507 info = info.next();
508 }
509 return closest;
510 }
511
512 // Promotes a TypeInfo to a higher pointer type (if necessary)
513 private TypeInfo promoteTypeInfo(final TypeInfo info, final int numPointersStripped) {
514 final int pd = info.pointerDepth();
515 int diff = numPointersStripped - pd;
516 if (diff == 0) {
517 return info;
518 }
519
520 if (diff < 0) {
521 throw new RuntimeException("TypeInfo for " + info.name() + " and pointerDepth " +
522 info.pointerDepth() + " should not have matched for depth " +
523 numPointersStripped);
524 }
525
526 Class<?> c = info.javaType().getJavaClass();
527
528 // Handle single-pointer stripping for types compatible with C
529 // integral and floating-point types specially so we end up
530 // generating NIO variants for these
531 if (diff == 1) {
532 JavaType jt = null;
533 if (c == Boolean.TYPE) jt = JavaType.createForCCharPointer();
534 else if (c == Byte.TYPE) jt = JavaType.createForCCharPointer();
535 else if (c == Short.TYPE) jt = JavaType.createForCShortPointer();
536 else if (c == Integer.TYPE) jt = JavaType.createForCInt32Pointer();
537 else if (c == Long.TYPE) jt = JavaType.createForCInt64Pointer();
538 else if (c == Float.TYPE) jt = JavaType.createForCFloatPointer();
539 else if (c == Double.TYPE) jt = JavaType.createForCDoublePointer();
540
541 if (jt != null)
542 return new TypeInfo(info.name(), numPointersStripped, jt);
543 }
544
545 while (diff > 0) {
546 c = Array.newInstance(c, 0).getClass();
547 --diff;
548 }
549
550 return new TypeInfo(info.name(),
551 numPointersStripped,
552 JavaType.createForClass(c));
553 }
554
555 /** Indicates whether the given function (which returns a
556 <code>char*</code> in C) should be translated as returning a
557 <code>java.lang.String</code>. */
558 public boolean returnsString(final String functionName) {
559 return returnsString.contains(functionName);
560 }
561 /** Indicates whether the given function (which returns a
562 <code>char*</code> in C) should be translated as returning a
563 <code>java.lang.String</code>. */
564 public boolean returnsString(final AliasedSymbol symbol) {
565 return returnsString.contains( symbol.getName() ) ||
566 oneInSet(returnsString, symbol.getAliasedNames());
567 }
568
569 /** Indicates whether the given function (which returns a
570 <code>char*</code> in C) should be translated as returning a
571 <code>java.lang.String</code> only. Excluding other variants for struct field access. */
572 public boolean returnsStringOnly(final String functionName) {
573 return returnsStringOnly.contains(functionName);
574 }
575
576 /** Returns the list of all configured JavaCallback definitions. */
577 public List<JavaCallbackDef> getJavaCallbackList() {
578 return javaCallbackList;
579 }
580
581 /** Returns the configured JavaCallback definition mapped to the JavaCallback-Set-Function name. */
583 final String name = symbol.getName();
584 final Set<String> aliases = symbol.getAliasedNames();
585
586 JavaCallbackDef res = javaCallbackSetFuncToDef.get(name);
587 if( null == res ) {
588 res = oneInMap(javaCallbackSetFuncToDef, aliases);
589 }
590 return res;
591 }
592
593 /**
594 * Returns a MessageFormat string of the Java expression calculating
595 * the number of elements in the returned array from the specified function
596 * name or struct-field array-size. The literal <code>1</code> indicates a constant single object.
597 * <p>
598 * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)},
599 * it describes field's array-length or element-count referenced by a pointer.
600 * </p>
601 * <p>
602 * In case of struct fields, this array length will also be used
603 * for the native C function, i.e. multiplied w/ <code>sizeof(C-Type)</code>
604 * and passed down to native code, <b>if</b> not overriden by
605 * either {@link #returnValueCapacity(String)} or {@link #returnValueLength(String)}!
606 * </p>
607 */
608 public String returnedArrayLength(final String symbol) {
609 return returnedArrayLengths.get(symbol);
610 }
611
612 /**
613 * Indicates whether the given symbol covers no or one single object.
614 * This is useful for struct-field pointer, indicating a null value
615 * holding no object or at most referincing memory for one single object.
616 */
617 public boolean maxOneElement(final String symbol) {
618 return maxOneElement.contains(symbol);
619 }
620
621 /** Returns a list of <code>Integer</code>s which are the indices of <code>const char*</code>
622 arguments that should be converted to <code>String</code>s. Returns null if there are no
623 such hints for the given function alias symbol. */
624 public List<Integer> stringArguments(final AliasedSymbol symbol) {
625 final String name = symbol.getName();
626 final Set<String> aliases = symbol.getAliasedNames();
627
628 List<Integer> res = argumentsAreString.get(name);
629 if( null == res ) {
630 res = oneInMap(argumentsAreString, aliases);
631 if( null == res ) {
632 return null;
633 }
634 }
635 LOG.log(INFO, getASTLocusTag(symbol), "ArgumentsAreString: {0} -> {1}", symbol, res);
636 return res;
637 }
638
639 /** Returns a list of PascalStringIdx which are tuples of indices of <code>int len, const char*</code>
640 arguments that should be converted to <code>String</code>s. Returns null if there are no
641 such hints for the given function alias symbol. */
643 final String name = symbol.getName();
644 final Set<String> aliases = symbol.getAliasedNames();
645
646 List<JavaType.PascalStringElem> res = argumentsArePascalString.get(name);
647 if( null == res ) {
648 res = oneInMap(argumentsArePascalString, aliases);
649 if( null == res ) {
650 return null;
651 }
652 }
653 LOG.log(INFO, getASTLocusTag(symbol), "ArgumentIsPascalString: {0} -> {1}", symbol, res);
654 return res;
655 }
656
657 public boolean isForceUsingNIOOnly4All() { return forceUseNIOOnly4All; }
658
659 public void addUseNIOOnly(final String fname ) {
660 useNIOOnly.add(fname);
661 }
662 /** Returns true if the given function should only create a java.nio
663 variant, and no array variants, for <code>void*</code> and other
664 C primitive pointers. NIO only still allows usage of array backed not direct Buffers. */
665 public boolean useNIOOnly(final String functionName) {
666 return useNIODirectOnly(functionName) || forceUseNIOOnly4All || useNIOOnly.contains(functionName);
667 }
668
669 public void addUseNIODirectOnly(final String fname ) {
670 useNIODirectOnly.add(fname);
671 }
672 /** Returns true if the given function should only create a java.nio
673 variant, and no array variants, for <code>void*</code> and other
674 C primitive pointers. NIO direct only does only allow direct Buffers.
675 Implies useNIOOnly !
676 */
677 public boolean useNIODirectOnly(final String functionName) {
678 return forceUseNIODirectOnly4All || useNIODirectOnly.contains(functionName);
679 }
680
681 /** Returns a list of Strings containing user-implemented code for
682 the given Java type name (not fully-qualified, only the class
683 name); returns either null or an empty list if there is no
684 custom code for the class. */
685 public List<String> customJavaCodeForClass(final String className) {
686 List<String> res = customJavaCode.get(className);
687 if (res == null) {
688 res = new ArrayList<String>();
689 customJavaCode.put(className, res);
690 }
691 return res;
692 }
693
694 /** Returns a list of Strings containing user-implemented JNI code for
695 the given Java type name (not fully-qualified, only the class
696 name); returns either null or an empty list if there is no
697 custom code for the class. */
698 public List<String> customJNICodeForClass(final String className) {
699 List<String> res = customJNICode.get(className);
700 if (res == null) {
701 res = new ArrayList<String>();
702 customJNICode.put(className, res);
703 }
704 return res;
705 }
706
707 public List<String> javadocForMethod(final String methodName) {
708 List<String> res = methodJavadoc.get(methodName);
709 if (res == null) {
710 res = new ArrayList<String>();
711 methodJavadoc.put(methodName, res);
712 }
713 return res;
714 }
715
716 /** Returns a list of Strings containing Javadoc documentation for
717 the given Java type name (not fully-qualified, only the class
718 name); returns either null or an empty list if there is no
719 Javadoc documentation for the class. */
720 public List<String> javadocForClass(final String className) {
721 List<String> res = classJavadoc.get(className);
722 if (res == null) {
723 res = new ArrayList<String>();
724 classJavadoc.put(className, res);
725 }
726 return res;
727 }
728
729 /** Returns the package into which to place the glue code for
730 accessing the specified struct. Defaults to emitting into the
731 regular package (i.e., the result of {@link #packageName}). */
732 public String packageForStruct(final String structName) {
733 String res = structPackages.get(structName);
734 if (res == null) {
735 res = packageName;
736 }
737 return res;
738 }
739
740 /** Returns, as a List of Strings, the custom C code to be emitted
741 along with the glue code for the main class. */
742 public List<String> customCCode() {
743 return customCCode;
744 }
745
746 /** Returns, as a List of Strings, the structs for which glue code
747 emission should be forced. */
748 public List<String> forcedStructs() {
749 return forcedStructs;
750 }
751
752 /**
753 * Returns a MessageFormat string of the Java code defining {@code mdIdx},
754 * i.e. the index of the static MachineDescriptor index for structs.
755 * <p>
756 * If undefined, code generation uses the default expression:
757 * <pre>
758 * private static final int mdIdx = MachineDataInfoRuntime.getStatic().ordinal();
759 * </pre>
760 * </p>
761 */
762 public String returnStructMachineDataInfoIndex(final String structName) {
763 return structMachineDataInfoIndex.get(structName);
764 }
765
766 /**
767 * Returns a MessageFormat string of the C expression calculating
768 * the capacity of the java.nio.ByteBuffer being returned from a
769 * native method, or null if no expression has been specified.
770 * <p>
771 * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)},
772 * it describes field's array-length or element-count referenced by a pointer.
773 * </p>
774 */
775 public String returnValueCapacity(final String functionName) {
776 return returnValueCapacities.get(functionName);
777 }
778
779 /**
780 * Returns a MessageFormat string of the C expression calculating
781 * the length of the array being returned from a native method.
782 * <p>
783 * If symbol references a struct fields, see {@link #canonicalStructFieldSymbol(String, String)},
784 * it describes field's array-length or element-count referenced by a pointer.
785 * </p>
786 */
787 public String returnValueLength(final String symbol) {
788 return returnValueLengths.get(symbol);
789 }
790
791 /** Returns a List of Strings of expressions declaring temporary C
792 variables in the glue code for the specified function. */
793 public List<String> temporaryCVariableDeclarations(final String functionName) {
794 return temporaryCVariableDeclarations.get(functionName);
795 }
796
797 /** Returns a List of Strings of expressions containing assignments
798 to temporary C variables in the glue code for the specified
799 function. */
800 public List<String> temporaryCVariableAssignments(final String functionName) {
801 return temporaryCVariableAssignments.get(functionName);
802 }
803
804 /** Returns a List of Strings indicating the interfaces the passed
805 interface should declare it extends. May return null or a list
806 of zero length if there are none. */
807 public List<String> extendedInterfaces(final String interfaceName) {
808 List<String> res = extendedInterfaces.get(interfaceName);
809 if (res == null) {
810 res = new ArrayList<String>();
811 extendedInterfaces.put(interfaceName, res);
812 }
813 return res;
814 }
815
816 /** Returns a List of Strings indicating the interfaces the passed
817 class should declare it implements. May return null or a list
818 of zero length if there are none. */
819 public List<String> implementedInterfaces(final String className) {
820 List<String> res = implementedInterfaces.get(className);
821 if (res == null) {
822 res = new ArrayList<String>();
823 implementedInterfaces.put(className, res);
824 }
825 return res;
826 }
827
828 /** Returns a List of Strings indicating the interfaces the passed
829 class should declare it implements. May return null or a list
830 of zero length if there are none. */
831 public String extendedParentClass(final String className) {
832 return parentClass.get(className);
833 }
834
835 public void logIgnoresOnce() {
836 if(!loggedIgnores) {
837 loggedIgnores = true;
838 logIgnores();
839 }
840 }
841 private static boolean loggedIgnores = false;
842
843 public void logIgnores() {
844 LOG.log(INFO, "Extended Intf: {0}", extendedIntfSymbolsIgnore.size());
845 for (final String str : extendedIntfSymbolsIgnore) {
846 LOG.log(INFO, "\t{0}", str);
847 }
848 LOG.log(INFO, "Extended Impl: {0}", extendedImplSymbolsIgnore.size());
849 for (final String str : extendedImplSymbolsIgnore) {
850 LOG.log(INFO, "\t{0}", str);
851 }
852 LOG.log(INFO, "Ignores (All): {0}", ignores.size());
853 for (final Pattern pattern : ignores) {
854 LOG.log(INFO, "\t{0}", pattern);
855 }
856 }
857
858 public void logRenamesOnce() {
859 if(!loggedRenames) {
860 loggedRenames = true;
861 logRenames();
862 }
863 }
864 private static boolean loggedRenames = false;
865
866 public void logRenames() {
867 LOG.log(INFO, "Symbol Renames: {0}", javaSymbolRenames.size());
868 for (final String key : javaSymbolRenames.keySet()) {
869 LOG.log(INFO, "\t{0} -> {1}", key, javaSymbolRenames.get(key));
870 }
871
872 LOG.log(INFO, "Symbol Aliasing (through renaming): {0}", javaSymbolRenames.size());
873 for(final String newName : javaSymbolRenames.values()) {
874 final Set<String> origNames = javaRenamedSymbols.get(newName);
875 if(null!=origNames) {
876 LOG.log(INFO, "\t{0} <- {1}", newName, origNames);
877 }
878 }
879 }
880
881 public static <K,V> V oneInMap(final Map<K, V> map, final Set<K> symbols) {
882 if( null != map && map.size() > 0 &&
883 null != symbols && symbols.size() > 0 ) {
884 for(final K sym : symbols) {
885 final V v = map.get(sym);
886 if( null != v ) {
887 return v;
888 }
889 }
890 }
891 return null;
892 }
893 public static <K> boolean oneInSet(final Set<K> set1, final Set<K> set2) {
894 if( null != set1 && set1.size() > 0 &&
895 null != set2 && set2.size() > 0 ) {
896 for(final K sym : set2) {
897 if( set1.contains( sym ) ) {
898 return true;
899 }
900 }
901 }
902 return false;
903 }
904 private static boolean onePatternMatch(final Pattern ignoreRegexp, final Set<String> set) {
905 if( null != ignoreRegexp && null != set && set.size() > 0 ) {
906 for(final String sym : set) {
907 final Matcher matcher = ignoreRegexp.matcher(sym);
908 if (matcher.matches()) {
909 return true;
910 }
911 }
912 }
913 return false;
914 }
915 protected static ASTLocusTag getASTLocusTag(final AliasedSymbol s) {
916 if( s instanceof ASTLocusTagProvider ) {
917 return ((ASTLocusTagProvider)s).getASTLocusTag();
918 } else {
919 return null;
920 }
921 }
922
923 /**
924 * Returns the canonical configuration name for a struct field name,
925 * i.e. 'struct-name'.'field-name'
926 */
927 public static String canonicalStructFieldSymbol(final String structName, final String fieldName) {
928 return structName+"."+fieldName;
929 }
930
931 /**
932 * Returns true if the glue code for the given aliased symbol
933 * shall produce code for immutable access only.
934 * <p>
935 * This is implemented for whole struct-type symbols or struct-field names,
936 * where no setter methods will be produced if marked immutable.
937 * </p>
938 */
939 public final boolean immutableAccess(final AliasedSymbol symbol) {
940 final String name = symbol.getName();
941 final Set<String> aliases = symbol.getAliasedNames();
942
943 if ( immutableAccessSymbols.contains( name ) ||
944 oneInSet(immutableAccessSymbols, aliases)
945 )
946 {
947 LOG.log(INFO, getASTLocusTag(symbol), "Immutable access: {0}", symbol);
948 return true;
949 }
950 return false;
951 }
952 /**
953 * Returns true if the glue code for the given symbol
954 * shall produce code for immutable access only.
955 * <p>
956 * This is implemented for whole struct-type symbols or struct-field names,
957 * where no setter methods will be produced if marked immutable.
958 * </p>
959 */
960 public final boolean immutableAccess(final String symbol) {
961 if ( immutableAccessSymbols.contains( symbol ) ) {
962 LOG.log(INFO, "Immutable access: {0}", symbol);
963 return true;
964 }
965 return false;
966 }
967
968 /**
969 * Variant of {@link #manuallyImplement(AliasedSymbol)},
970 * where this method only considers the {@link AliasedSymbol#getName() current-name}
971 * of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
972 */
973 public boolean manuallyImplement(final String functionName) {
974 if( manuallyImplement.contains(functionName) ) {
975 LOG.log(INFO, "ManuallyImplement: \"{0}\"", functionName);
976 return true;
977 } else {
978 return false;
979 }
980 }
981
982 /**
983 * Returns true if the glue code for the given aliased function will be
984 * manually implemented by the end user.
985 * <p>
986 * Both, the {@link AliasedSymbol#getName() current-name}
987 * and all {@link AliasedSymbol#getAliasedNames() aliases} shall be considered.
988 * </p>
989 * <p>
990 * If symbol references a struct field or method, see {@link #canonicalStructFieldSymbol(String, String)},
991 * it describes field's array-length or element-count referenced by a pointer.
992 * </p>
993 * @see #manuallyImplement(String)
994 */
995 public boolean manuallyImplement(final AliasedSymbol symbol) {
996 final String name = symbol.getName();
997 final Set<String> aliases = symbol.getAliasedNames();
998
999 if ( manuallyImplement.contains( name ) ||
1000 oneInSet(manuallyImplement, aliases)
1001 )
1002 {
1003 LOG.log(INFO, getASTLocusTag(symbol), "ManuallyImplement: {0}", symbol);
1004 return true;
1005 } else {
1006 return false;
1007 }
1008 }
1009
1010 /**
1011 * Variant of {@link #getDelegatedImplementation(AliasedSymbol)},
1012 * where this method only considers the {@link AliasedSymbol#getName() current-name}
1013 * of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
1014 */
1015 public String getDelegatedImplementation(final String functionName) {
1016 final String res = delegatedImplementation.get(functionName);
1017 if( null == res ) {
1018 return null;
1019 }
1020 LOG.log(INFO, "DelegatedImplementation: {0} -> {1}", functionName, res);
1021 return res;
1022 }
1023
1024 /**
1025 * Returns the {@code RENAMED-IMPL-SYMBOL} if the implementation of the glue code
1026 * of the given function shall be manually delegated by the end user.
1027 * <p>
1028 * {@code DelegateImplementation <ORIG-SYMBOL> <RENAMED-IMPL-SYMBOL>}
1029 * </p>
1030 * <p>
1031 * The interface is emitted unchanged.
1032 * </p>
1033 * <p>
1034 * The Java and native-code implementation is renamed to {@code RENAMED-IMPL-SYMBOL}.
1035 * The user's manual implementation of {@code ORIG-SYMBOL}
1036 * may delegate to {@code RENAMED-IMPL-SYMBOL}.
1037 * </p>
1038 * <p>
1039 * If symbol references a struct field or method, see {@link #canonicalStructFieldSymbol(String, String)},
1040 * it describes field's array-length or element-count referenced by a pointer.
1041 * </p>
1042 */
1043 public String getDelegatedImplementation(final AliasedSymbol symbol) {
1044 final String name = symbol.getName();
1045 final Set<String> aliases = symbol.getAliasedNames();
1046
1047 String res = delegatedImplementation.get(name);
1048 if( null == res ) {
1049 res = oneInMap(delegatedImplementation, aliases);
1050 if( null == res ) {
1051 return null;
1052 }
1053 }
1054 LOG.log(INFO, getASTLocusTag(symbol), "DelegatedImplementation: {0} -> {1}", symbol, res);
1055 return res;
1056 }
1057
1058 /**
1059 * Variant of {@link #getOpaqueReturnType(AliasedSymbol)},
1060 * where this method only considers the {@link AliasedSymbol#getName() current-name}
1061 * of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
1062 */
1063 public JavaType getOpaqueReturnType(final String functionName) {
1064 final JavaType res = returnsOpaqueJType.get(functionName);
1065 if( null == res ) {
1066 return null;
1067 }
1068 LOG.log(INFO, "ReturnsOpaque: {0} -> {1}", functionName, res);
1069 return res;
1070 }
1071
1072 /**
1073 * Returns the opaque {@link JavaType} for the given function {@link AliasedSymbol}
1074 * or {@code null} if not opaque.
1075 * <p>
1076 * {@code ReturnsOpaque <Primitive Java Type> <Function Name>}
1077 * </p>
1078 */
1080 final String name = symbol.getName();
1081 final Set<String> aliases = symbol.getAliasedNames();
1082 JavaType res = returnsOpaqueJType.get(name);
1083 if( null == res ) {
1084 res = oneInMap(returnsOpaqueJType, aliases);
1085 if( null == res ) {
1086 return null;
1087 }
1088 }
1089 LOG.log(INFO, getASTLocusTag(symbol), "ReturnsOpaque: {0} -> {1}", symbol, res);
1090 return res;
1091 }
1092
1093 /**
1094 * Variant of {@link #shouldIgnoreInInterface(AliasedSymbol)},
1095 * where this method only considers the {@link AliasedSymbol#getName() current-name}
1096 * of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
1097 */
1098 public final boolean shouldIgnoreInInterface(final String symbol) {
1100 }
1101 /**
1102 * Returns true if this aliased symbol should be ignored
1103 * during glue code generation of interfaces and implementation.
1104 * <p>
1105 * Both, the {@link AliasedSymbol#getName() current-name}
1106 * and all {@link AliasedSymbol#getAliasedNames() aliases} shall be considered.
1107 * </p>
1108 * <p>
1109 * Implementation calls {@link #shouldIgnoreInInterface_Int(AliasedSymbol)}
1110 * and overriding implementations shall ensure its being called as well!
1111 * </p>
1112 * @param symbol the symbolic aliased name to check for exclusion
1113 */
1114 public boolean shouldIgnoreInInterface(final AliasedSymbol symbol) {
1115 return shouldIgnoreInInterface_Int(symbol);
1116 }
1117
1118 protected final boolean shouldIgnoreInInterface_Int(final AliasedSymbol symbol) {
1119 if( GlueGen.debug() ) {
1121 }
1122 final String name = symbol.getName();
1123 final Set<String> aliases = symbol.getAliasedNames();
1124
1125 // Simple case-1; the symbol (orig or renamed) is in the interface ignore table
1126 if ( extendedIntfSymbolsIgnore.contains( name ) ||
1127 oneInSet(extendedIntfSymbolsIgnore, aliases)
1128 )
1129 {
1130 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Intf ignore (one): {0}", symbol);
1131 return true;
1132 }
1133 // Simple case-2; the entire symbol (orig and renamed) is _not_ in the not-empty interface only table
1134 if ( !extendedIntfSymbolsOnly.isEmpty() &&
1135 !extendedIntfSymbolsOnly.contains( name ) &&
1136 !oneInSet(extendedIntfSymbolsOnly, aliases) ) {
1137 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Intf !extended (all): {0}", symbol);
1138 return true;
1139 }
1140 return shouldIgnoreInImpl_Int(symbol);
1141 }
1142
1143 /**
1144 * Returns true if this aliased symbol should be ignored
1145 * during glue code generation of implementation only.
1146 * <p>
1147 * Both, the {@link AliasedSymbol#getName() current-name}
1148 * and all {@link AliasedSymbol#getAliasedNames() aliases} shall be considered.
1149 * </p>
1150 * <p>
1151 * Implementation calls {@link #shouldIgnoreInImpl_Int(AliasedSymbol)}
1152 * and overriding implementations shall ensure its being called as well!
1153 * </p>
1154 * @param symbol the symbolic aliased name to check for exclusion
1155 */
1156 public boolean shouldIgnoreInImpl(final AliasedSymbol symbol) {
1157 return shouldIgnoreInImpl_Int(symbol);
1158 }
1159
1160 protected final boolean shouldIgnoreInImpl_Int(final AliasedSymbol symbol) {
1161 final String name = symbol.getName();
1162 final Set<String> aliases = symbol.getAliasedNames();
1163
1164 // Simple case-1; the symbol (orig or renamed) is in the interface ignore table
1165 if ( extendedImplSymbolsIgnore.contains( name ) ||
1166 oneInSet(extendedImplSymbolsIgnore, aliases)
1167 )
1168 {
1169 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Impl ignore (one): {0}", symbol);
1170 return true;
1171 }
1172 // Simple case-2; the entire symbol (orig and renamed) is _not_ in the not-empty interface only table
1173 if ( !extendedImplSymbolsOnly.isEmpty() &&
1174 !extendedImplSymbolsOnly.contains( name ) &&
1175 !oneInSet(extendedImplSymbolsOnly, aliases) ) {
1176 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Impl !extended (all): {0}", symbol);
1177 return true;
1178 }
1179
1180 // Ok, the slow case. We need to check the entire table, in case the table
1181 // contains an regular expression that matches the symbol.
1182 for (final Pattern ignoreRegexp : ignores) {
1183 final Matcher matcher = ignoreRegexp.matcher(name);
1184 if ( matcher.matches() || onePatternMatch(ignoreRegexp, aliases) ) {
1185 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Impl RegEx: {0}", symbol);
1186 return true;
1187 }
1188 }
1189
1190 // Check negated ignore table if not empty
1191 if (ignoreNots.size() > 0) {
1192 // Ok, the slow case. We need to check the entire table, in case the table
1193 // contains an regular expression that matches the symbol.
1194 for (final Pattern ignoreNotRegexp : ignoreNots) {
1195 final Matcher matcher = ignoreNotRegexp.matcher(name);
1196 if ( !matcher.matches() && !onePatternMatch(ignoreNotRegexp, aliases) ) {
1197 // Special case as this is most often likely to be the case.
1198 // Unignores are not used very often.
1199 if(unignores.isEmpty()) {
1200 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Impl unignores==0: {0} -> {1}", symbol, name);
1201 return true;
1202 }
1203 boolean unignoreFound = false;
1204 for (final Pattern unignoreRegexp : unignores) {
1205 final Matcher unignoreMatcher = unignoreRegexp.matcher(name);
1206 if ( unignoreMatcher.matches() || onePatternMatch(unignoreRegexp, aliases) ) {
1207 unignoreFound = true;
1208 break;
1209 }
1210 }
1211
1212 if (!unignoreFound) {
1213 LOG.log(INFO, getASTLocusTag(symbol), "Ignore Impl !unignore: {0} -> {1}", symbol, name);
1214 return true;
1215 }
1216 }
1217 }
1218 }
1219 return false;
1220 }
1221
1222 /** Returns true if this function should be given a body which
1223 throws a run-time exception with an "unimplemented" message
1224 during glue code generation. */
1225 public boolean isUnimplemented(final AliasedSymbol symbol) {
1226 // Ok, the slow case. We need to check the entire table, in case the table
1227 // contains an regular expression that matches the symbol.
1228 for (final Pattern unimplRegexp : unimplemented) {
1229 final Matcher matcher = unimplRegexp.matcher(symbol.getName());
1230 if ( matcher.matches() || onePatternMatch(unimplRegexp, symbol.getAliasedNames()) ) {
1231 return true;
1232 }
1233 }
1234 return false;
1235 }
1236
1237
1238 /**
1239 * Return a set of aliased-name for comment in docs.
1240 * <p>
1241 * This is usually {@link AliasedSymbol#addAliasedName(String)},
1242 * however an implementation may choose otherwise.
1243 * </p>
1244 * @param symbol the aliased symbol to retrieve the aliases
1245 * @return set of aliased-names or {@code null}.
1246 */
1247 public Set<String> getAliasedDocNames(final AliasedSymbol symbol) {
1248 return symbol.getAliasedNames();
1249 }
1250
1251 /** Returns a replacement name for this type, which should be the
1252 name of a Java wrapper class for a C struct, or the name
1253 unchanged if no RenameJavaType directive was specified for this
1254 type. */
1255 public String renameJavaType(final String javaTypeName) {
1256 final String rename = javaTypeRenames.get(javaTypeName);
1257 if (rename != null) {
1258 return rename;
1259 }
1260 return javaTypeName;
1261 }
1262
1263 /** Returns a replacement name for this function or definition which
1264 should be used as the Java name for the bound method or
1265 constant. If a function, it still calls the originally-named C
1266 function under the hood. Returns null if this symbol has not
1267 been explicitly renamed. */
1268 public String getJavaSymbolRename(final String origName) {
1269 if( LOG.isLoggable(INFO) ) {
1271 }
1272 return javaSymbolRenames.get(origName);
1273 }
1274
1275 /** Returns a set of replaced names to the given <code>aliasedName</code>. */
1276 public Set<String> getRenamedJavaSymbols(final String aliasedName) {
1277 return javaRenamedSymbols.get(aliasedName);
1278 }
1279
1280 /** Programmatically adds a rename directive for the given symbol. */
1281 public void addJavaSymbolRename(final String origName, final String newName) {
1282 LOG.log(INFO, "\tRename {0} -> {1}", origName, newName);
1283 final String prevValue = javaSymbolRenames.put(origName, newName);
1284 if(null != prevValue && !prevValue.equals(newName)) {
1285 throw new RuntimeException("Rename-Override Attampt: "+origName+" -> "+newName+
1286 ", but "+origName+" -> "+prevValue+" already exist. Run in 'debug' mode to analyze!");
1287 }
1288 Set<String> origNames = javaRenamedSymbols.get(newName);
1289 if(null == origNames) {
1290 origNames = new HashSet<String>();
1291 javaRenamedSymbols.put(newName, origNames);
1292 }
1293 origNames.add(origName);
1294 }
1295
1296 /** Programmatically adds a delegate implementation directive for the given symbol. */
1297 public void addDelegateImplementation(final String origName, final String renamedImpl) {
1298 LOG.log(INFO, "\tDelegateImplementation {0} -> {1}", origName, renamedImpl);
1299 final String prevValue = delegatedImplementation.put(origName, renamedImpl);
1300 if(null != prevValue && !prevValue.equals(renamedImpl)) {
1301 throw new RuntimeException("Rename-Override Attampt: "+origName+" -> "+renamedImpl+
1302 ", but "+origName+" -> "+prevValue+" already exist. Run in 'debug' mode to analyze!");
1303 }
1304 }
1305
1306 /** Returns true if the emission style is AllStatic. */
1307 public boolean allStatic() {
1308 return emissionStyle == AllStatic;
1309 }
1310
1311 /** Returns true if an interface should be emitted during glue code generation. */
1312 public boolean emitInterface() {
1313 return emissionStyle() == InterfaceAndImpl || emissionStyle() == InterfaceOnly;
1314 }
1315
1316 /** Returns true if an implementing class should be emitted during glue code generation. */
1317 public boolean emitImpl() {
1318 return emissionStyle() == AllStatic || emissionStyle() == InterfaceAndImpl || emissionStyle() == ImplOnly;
1319 }
1320
1321 /** Returns a list of Strings which should be emitted as a prologue
1322 to the body for the Java-side glue code for the given method.
1323 Returns null if no prologue was specified. */
1324 public List<String> javaPrologueForMethod(final MethodBinding binding,
1325 final boolean forImplementingMethodCall,
1326 final boolean eraseBufferAndArrayTypes) {
1327 List<String> res = javaPrologues.get(binding.getName());
1328 if (res == null) {
1329 // Try again with method name and descriptor
1330 res = javaPrologues.get(binding.getName() + binding.getDescriptor(forImplementingMethodCall, eraseBufferAndArrayTypes));
1331 }
1332 return res;
1333 }
1334
1335 /** Returns a list of Strings which should be emitted as an epilogue
1336 to the body for the Java-side glue code for the given method.
1337 Returns null if no epilogue was specified. */
1338 public List<String> javaEpilogueForMethod(final MethodBinding binding,
1339 final boolean forImplementingMethodCall,
1340 final boolean eraseBufferAndArrayTypes) {
1341 List<String> res = javaEpilogues.get(binding.getName());
1342 if (res == null) {
1343 // Try again with method name and descriptor
1344 res = javaEpilogues.get(binding.getName() + binding.getDescriptor(forImplementingMethodCall, eraseBufferAndArrayTypes));
1345 }
1346 return res;
1347 }
1348
1349 //----------------------------------------------------------------------
1350 // Internals only below this point
1351 //
1352
1353 protected void dispatch(final String cmd, final StringTokenizer tok, final File file, final String filename, final int lineNo) throws IOException {
1354 //System.err.println("read cmd = [" + cmd + "]");
1355 if (cmd.equalsIgnoreCase("LibraryOnLoad")) {
1356 libraryOnLoadName = readString("LibraryOnLoad", tok, filename, lineNo);
1357 } else if (cmd.equalsIgnoreCase("Package")) {
1358 packageName = readString("Package", tok, filename, lineNo);
1359 } else if (cmd.equalsIgnoreCase("GlueGenRuntimePackage")) {
1360 gluegenRuntimePackage = readString("GlueGenRuntimePackage", tok, filename, lineNo);
1361 } else if (cmd.equalsIgnoreCase("ImplPackage")) {
1362 implPackageName = readString("ImplPackage", tok, filename, lineNo);
1363 } else if (cmd.equalsIgnoreCase("JavaClass")) {
1364 className = readString("JavaClass", tok, filename, lineNo);
1365 } else if (cmd.equalsIgnoreCase("ImplJavaClass")) {
1366 implClassName = readString("ImplJavaClass", tok, filename, lineNo);
1367 } else if (cmd.equalsIgnoreCase("JavaOutputDir")) {
1368 javaOutputDir = readString("JavaOutputDir", tok, filename, lineNo);
1369 } else if (cmd.equalsIgnoreCase("NativeOutputDir")) {
1370 nativeOutputDir = readString("NativeOutputDir", tok, filename, lineNo);
1371 } else if (cmd.equalsIgnoreCase("HierarchicalNativeOutput")) {
1372 final String tmp = readString("HierarchicalNativeOutput", tok, filename, lineNo);
1373 nativeOutputUsesJavaHierarchy = Boolean.valueOf(tmp).booleanValue();
1374 } else if (cmd.equalsIgnoreCase("TagNativeBinding")) {
1375 tagNativeBinding = readBoolean("TagNativeBinding", tok, filename, lineNo).booleanValue();
1376 } else if (cmd.equalsIgnoreCase("RelaxedEqualSemanticsTest")) {
1377 relaxedEqualSemanticsTest = readBoolean("RelaxedEqualSemanticsTest", tok, filename, lineNo).booleanValue();
1378 TypeConfig.setRelaxedEqualSemanticsTest(relaxedEqualSemanticsTest); // propagate ..
1379 } else if (cmd.equalsIgnoreCase("Style")) {
1380 try{
1381 emissionStyle = EmissionStyle.valueOf(readString("Style", tok, filename, lineNo));
1382 }catch(final IllegalArgumentException ex) {
1383 LOG.log(WARNING, "Error parsing \"style\" command at line {0} in file \"{1}\"", lineNo, filename);
1384 }
1385 } else if (cmd.equalsIgnoreCase("AccessControl")) {
1386 readAccessControl(tok, filename, lineNo);
1387 } else if (cmd.equalsIgnoreCase("Import")) {
1388 imports.add(readString("Import", tok, filename, lineNo));
1389 } else if (cmd.equalsIgnoreCase("Opaque")) {
1390 readOpaque(tok, filename, lineNo);
1391 } else if (cmd.equalsIgnoreCase("ReturnsString")) {
1392 readReturnsString(tok, filename, lineNo);
1393 } else if (cmd.equalsIgnoreCase("ReturnsStringOnly")) {
1394 readReturnsStringOnly(tok, filename, lineNo);
1395 } else if (cmd.equalsIgnoreCase("ReturnsOpaque")) {
1396 readReturnsOpaque(tok, filename, lineNo);
1397 } else if (cmd.equalsIgnoreCase("ReturnedArrayLength")) {
1398 readReturnedArrayLength(tok, filename, lineNo);
1399 // Warning: make sure delimiters are reset at the top of this loop
1400 // because ReturnedArrayLength changes them.
1401 } else if (cmd.equalsIgnoreCase("MaxOneElement")) {
1402 readMaxOneElement(tok, filename, lineNo);
1403 } else if (cmd.equalsIgnoreCase("ArgumentIsString")) {
1404 readArgumentIsString(tok, filename, lineNo);
1405 } else if (cmd.equalsIgnoreCase("ArgumentIsPascalString")) {
1406 readArgumentIsPascalString(tok, filename, lineNo);
1407 } else if (cmd.equalsIgnoreCase("JavaCallbackDef")) {
1408 readJavaCallbackDef(tok, filename, lineNo);
1409 } else if (cmd.equalsIgnoreCase("JavaCallbackKey")) {
1410 readJavaCallbackKey(tok, filename, lineNo);
1411 } else if (cmd.equalsIgnoreCase("ExtendedInterfaceSymbolsIgnore")) {
1412 readExtendedIntfImplSymbols(tok, filename, lineNo, true, false, false);
1413 } else if (cmd.equalsIgnoreCase("ExtendedInterfaceSymbolsOnly")) {
1414 readExtendedIntfImplSymbols(tok, filename, lineNo, true, false, true);
1415 } else if (cmd.equalsIgnoreCase("ExtendedImplementationSymbolsIgnore")) {
1416 readExtendedIntfImplSymbols(tok, filename, lineNo, false, true, false);
1417 } else if (cmd.equalsIgnoreCase("ExtendedImplementationSymbolsOnly")) {
1418 readExtendedIntfImplSymbols(tok, filename, lineNo, false, true, true);
1419 } else if (cmd.equalsIgnoreCase("ExtendedIntfAndImplSymbolsIgnore")) {
1420 readExtendedIntfImplSymbols(tok, filename, lineNo, true, true, false);
1421 } else if (cmd.equalsIgnoreCase("ExtendedIntfAndImplSymbolsOnly")) {
1422 readExtendedIntfImplSymbols(tok, filename, lineNo, true, true, true);
1423 } else if (cmd.equalsIgnoreCase("Ignore")) {
1424 readIgnore(tok, filename, lineNo);
1425 } else if (cmd.equalsIgnoreCase("Unignore")) {
1426 readUnignore(tok, filename, lineNo);
1427 } else if (cmd.equalsIgnoreCase("IgnoreNot")) {
1428 readIgnoreNot(tok, filename, lineNo);
1429 } else if (cmd.equalsIgnoreCase("Unimplemented")) {
1430 readUnimplemented(tok, filename, lineNo);
1431 } else if (cmd.equalsIgnoreCase("IgnoreField")) {
1432 readIgnoreField(tok, filename, lineNo);
1433 } else if (cmd.equalsIgnoreCase("ImmutableAccess")) {
1434 readImmutableAccess(tok, filename, lineNo);
1435 } else if (cmd.equalsIgnoreCase("ManuallyImplement")) {
1436 readManuallyImplement(tok, filename, lineNo);
1437 } else if (cmd.equalsIgnoreCase("CustomJavaCode")) {
1438 readCustomJavaCode(tok, filename, lineNo);
1439 // Warning: make sure delimiters are reset at the top of this loop
1440 // because readCustomJavaCode changes them.
1441 } else if (cmd.equalsIgnoreCase("CustomCCode")) {
1442 readCustomCCode(tok, filename, lineNo);
1443 // Warning: make sure delimiters are reset at the top of this loop
1444 // because readCustomJNICode changes them.
1445 } else if (cmd.equalsIgnoreCase("CustomJNICode")) {
1446 readCustomJNICode(tok, filename, lineNo);
1447 // Warning: make sure delimiters are reset at the top of this loop
1448 // because readCustomCCode changes them.
1449 } else if (cmd.equalsIgnoreCase("MethodJavadoc")) {
1450 readMethodJavadoc(tok, filename, lineNo);
1451 // Warning: make sure delimiters are reset at the top of this loop
1452 // because readMethodJavadoc changes them.
1453 } else if (cmd.equalsIgnoreCase("ClassJavadoc")) {
1454 readClassJavadoc(tok, filename, lineNo);
1455 // Warning: make sure delimiters are reset at the top of this loop
1456 // because readClassJavadoc changes them.
1457 } else if (cmd.equalsIgnoreCase("NIOOnly")) {
1458 final String funcName = readString("NIOOnly", tok, filename, lineNo);
1459 if(funcName.equals("__ALL__")) {
1460 forceUseNIOOnly4All=true;
1461 } else {
1462 addUseNIOOnly( funcName );
1463 }
1464 } else if (cmd.equalsIgnoreCase("NIODirectOnly")) {
1465 final String funcName = readString("NIODirectOnly", tok, filename, lineNo);
1466 if(funcName.equals("__ALL__")) {
1467 forceUseNIODirectOnly4All=true;
1468 } else {
1469 addUseNIODirectOnly( funcName );
1470 }
1471 } else if (cmd.equalsIgnoreCase("EmitStruct")) {
1472 forcedStructs.add(readString("EmitStruct", tok, filename, lineNo));
1473 } else if (cmd.equalsIgnoreCase("StructPackage")) {
1474 readStructPackage(tok, filename, lineNo);
1475 } else if (cmd.equalsIgnoreCase("TemporaryCVariableDeclaration")) {
1476 readTemporaryCVariableDeclaration(tok, filename, lineNo);
1477 // Warning: make sure delimiters are reset at the top of this loop
1478 // because TemporaryCVariableDeclaration changes them.
1479 } else if (cmd.equalsIgnoreCase("TemporaryCVariableAssignment")) {
1480 readTemporaryCVariableAssignment(tok, filename, lineNo);
1481 // Warning: make sure delimiters are reset at the top of this loop
1482 // because TemporaryCVariableAssignment changes them.
1483 } else if (cmd.equalsIgnoreCase("StructMachineDataInfoIndex")) {
1484 readStructMachineDataInfoIndex(tok, filename, lineNo);
1485 // Warning: make sure delimiters are reset at the top of this loop
1486 // because StructMachineDescriptorIndex changes them.
1487 } else if (cmd.equalsIgnoreCase("ReturnValueCapacity")) {
1488 readReturnValueCapacity(tok, filename, lineNo);
1489 // Warning: make sure delimiters are reset at the top of this loop
1490 // because ReturnValueCapacity changes them.
1491 } else if (cmd.equalsIgnoreCase("ReturnValueLength")) {
1492 readReturnValueLength(tok, filename, lineNo);
1493 // Warning: make sure delimiters are reset at the top of this loop
1494 // because ReturnValueLength changes them.
1495 } else if (cmd.equalsIgnoreCase("Include")) {
1496 doInclude(tok, file, filename, lineNo);
1497 } else if (cmd.equalsIgnoreCase("IncludeAs")) {
1498 doIncludeAs(tok, file, filename, lineNo);
1499 } else if (cmd.equalsIgnoreCase("Extends")) {
1500 readExtend(tok, filename, lineNo);
1501 } else if (cmd.equalsIgnoreCase("Implements")) {
1502 readImplements(tok, filename, lineNo);
1503 } else if (cmd.equalsIgnoreCase("ParentClass")) {
1504 readParentClass(tok, filename, lineNo);
1505 } else if (cmd.equalsIgnoreCase("RenameJavaType")) {
1506 readRenameJavaType(tok, filename, lineNo);
1507 } else if (cmd.equalsIgnoreCase("RenameJavaSymbol")) {
1508 readRenameJavaSymbol(tok, filename, lineNo);
1509 } else if (cmd.equalsIgnoreCase("DelegateImplementation")) {
1510 readDelegateImplementation(tok, filename, lineNo);
1511 } else if (cmd.equalsIgnoreCase("RuntimeExceptionType")) {
1512 runtimeExceptionType = readString("RuntimeExceptionType", tok, filename, lineNo);
1513 } else if (cmd.equalsIgnoreCase("UnsupportedExceptionType")) {
1514 unsupportedExceptionType = readString("UnsupportedExceptionType", tok, filename, lineNo);
1515 } else if (cmd.equalsIgnoreCase("JavaPrologue")) {
1516 readJavaPrologueOrEpilogue(tok, filename, lineNo, true);
1517 // Warning: make sure delimiters are reset at the top of this loop
1518 // because readJavaPrologueOrEpilogue changes them.
1519 } else if (cmd.equalsIgnoreCase("JavaEpilogue")) {
1520 readJavaPrologueOrEpilogue(tok, filename, lineNo, false);
1521 // Warning: make sure delimiters are reset at the top of this loop
1522 // because readJavaPrologueOrEpilogue changes them.
1523 } else if (cmd.equalsIgnoreCase("RangeCheck")) {
1524 readRangeCheck(tok, filename, lineNo, false);
1525 // Warning: make sure delimiters are reset at the top of this loop
1526 // because RangeCheck changes them.
1527 } else if (cmd.equalsIgnoreCase("RangeCheckBytes")) {
1528 readRangeCheck(tok, filename, lineNo, true);
1529 // Warning: make sure delimiters are reset at the top of this loop
1530 // because RangeCheckBytes changes them.
1531 } else {
1532 throw new RuntimeException("Unknown command \"" + cmd +
1533 "\" in command file " + filename +
1534 " at line number " + lineNo);
1535 }
1536 }
1537
1538 protected String readString(final String cmd, final StringTokenizer tok, final String filename, final int lineNo) {
1539 try {
1540 return tok.nextToken();
1541 } catch (final NoSuchElementException e) {
1542 throw new RuntimeException("Error parsing \"" + cmd + "\" command at line " + lineNo +
1543 " in file \"" + filename + "\": missing expected parameter", e);
1544 }
1545 }
1546
1547 protected Boolean readBoolean(final String cmd, final StringTokenizer tok, final String filename, final int lineNo) {
1548 try {
1549 return Boolean.valueOf(tok.nextToken());
1550 } catch (final NoSuchElementException e) {
1551 throw new RuntimeException("Error parsing \"" + cmd + "\" command at line " + lineNo +
1552 " in file \"" + filename + "\": missing expected boolean value", e);
1553 }
1554 }
1555
1556 protected Class<?> stringToPrimitiveType(final String type) throws ClassNotFoundException {
1557 if (type.equals("boolean")) return Boolean.TYPE;
1558 if (type.equals("byte")) return Byte.TYPE;
1559 if (type.equals("char")) return Character.TYPE;
1560 if (type.equals("short")) return Short.TYPE;
1561 if (type.equals("int")) return Integer.TYPE;
1562 if (type.equals("long")) return Long.TYPE;
1563 if (type.equals("float")) return Float.TYPE;
1564 if (type.equals("double")) return Double.TYPE;
1565 throw new RuntimeException("Only primitive types are supported here");
1566 }
1567
1568 protected void readAccessControl(final StringTokenizer tok, final String filename, final int lineNo) {
1569 try {
1570 final String methodName = tok.nextToken();
1571 final String style = tok.nextToken();
1572 final MethodAccess access = MethodAccess.valueOf(style.toUpperCase());
1573 accessControl.put(methodName, access);
1574 } catch (final Exception e) {
1575 throw new RuntimeException("Error parsing \"AccessControl\" command at line " + lineNo
1576 + " in file \"" + filename + "\"", e);
1577 }
1578 }
1579
1580 protected void readOpaque(final StringTokenizer tok, final String filename, final int lineNo) {
1581 try {
1582 final JavaType javaType = JavaType.createForOpaqueClass(stringToPrimitiveType(tok.nextToken()));
1583 String cType = null;
1584 while (tok.hasMoreTokens()) {
1585 if (cType == null) {
1586 cType = tok.nextToken();
1587 } else {
1588 cType = cType + " " + tok.nextToken();
1589 }
1590 }
1591 if (cType == null) {
1592 throw new RuntimeException("No C type for \"Opaque\" command at line " + lineNo +
1593 " in file \"" + filename + "\"");
1594 }
1595 final TypeInfo info = parseTypeInfo(cType, javaType);
1596 addTypeInfo(info);
1597 } catch (final Exception e) {
1598 throw new RuntimeException("Error parsing \"Opaque\" command at line " + lineNo +
1599 " in file \"" + filename + "\"", e);
1600 }
1601 }
1602
1603 protected void readReturnsOpaque(final StringTokenizer tok, final String filename, final int lineNo) {
1604 try {
1605 final JavaType javaType = JavaType.createForOpaqueClass(stringToPrimitiveType(tok.nextToken()));
1606 final String funcName = tok.nextToken();
1607 returnsOpaqueJType.put(funcName, javaType);
1608 } catch (final Exception e) {
1609 throw new RuntimeException("Error parsing \"ReturnsOpaque\" command at line " + lineNo +
1610 " in file \"" + filename + "\"", e);
1611 }
1612 }
1613
1614 protected void readReturnsString(final StringTokenizer tok, final String filename, final int lineNo) {
1615 try {
1616 final String name = tok.nextToken();
1617 returnsString.add(name);
1618 } catch (final NoSuchElementException e) {
1619 throw new RuntimeException("Error parsing \"ReturnsString\" command at line " + lineNo +
1620 " in file \"" + filename + "\"", e);
1621 }
1622 }
1623
1624 protected void readReturnsStringOnly(final StringTokenizer tok, final String filename, final int lineNo) {
1625 try {
1626 final String name = tok.nextToken();
1627 returnsStringOnly.add(name);
1628 } catch (final NoSuchElementException e) {
1629 throw new RuntimeException("Error parsing \"ReturnsStringOnly\" command at line " + lineNo +
1630 " in file \"" + filename + "\"", e);
1631 }
1632 }
1633
1634 protected void readReturnedArrayLength(final StringTokenizer tok, final String filename, final int lineNo) {
1635 try {
1636 final String functionName = tok.nextToken();
1637 String restOfLine = tok.nextToken("\n\r\f");
1638 restOfLine = restOfLine.trim();
1639 returnedArrayLengths.put(functionName, restOfLine);
1640 } catch (final NoSuchElementException e) {
1641 throw new RuntimeException("Error parsing \"ReturnedArrayLength\" command at line " + lineNo +
1642 " in file \"" + filename + "\"", e);
1643 }
1644 }
1645
1646 protected void readMaxOneElement(final StringTokenizer tok, final String filename, final int lineNo) {
1647 try {
1648 final String name = tok.nextToken();
1649 maxOneElement.add(name);
1650 } catch (final NoSuchElementException e) {
1651 throw new RuntimeException("Error parsing \"MaxOneElement\" command at line " + lineNo +
1652 " in file \"" + filename + "\"", e);
1653 }
1654 }
1655
1656 protected void readJavaCallbackDef(final StringTokenizer tok, final String filename, final int lineNo) {
1657 try {
1658 final String setFuncName = tok.nextToken();
1659 final int setFuncUserParamIdx = Integer.parseInt(tok.nextToken());
1660 final String cbFuncTypeName = tok.nextToken();
1661 final int cbFuncUserParamIdx = Integer.parseInt(tok.nextToken());
1662 final String userParamClassName;
1663 final String customKeyClassName;
1664 if( tok.hasMoreTokens() ) {
1665 final String s = tok.nextToken();
1666 if( s.length() == 0 || s.equals("null") ) {
1667 userParamClassName = null;
1668 } else {
1669 userParamClassName = s;
1670 }
1671 if( tok.hasMoreTokens() ) {
1672 customKeyClassName = tok.nextToken();
1673 } else {
1674 customKeyClassName = null;
1675 }
1676 } else {
1677 userParamClassName = null;
1678 customKeyClassName = null;
1679 }
1680 final JavaCallbackDef jcd = new JavaCallbackDef(cbFuncTypeName, cbFuncUserParamIdx, setFuncName, setFuncUserParamIdx,
1681 userParamClassName, customKeyClassName);
1682 javaCallbackList.add(jcd);
1683 javaCallbackSetFuncToDef.put(setFuncName, jcd);
1684 } catch (final NoSuchElementException e) {
1685 throw new RuntimeException("Error parsing \"JavaCallbackDef\" command at line " + lineNo +
1686 " in file \"" + filename + "\"", e);
1687 }
1688 }
1689
1690 protected void readJavaCallbackKey(final StringTokenizer tok, final String filename, final int lineNo) {
1691 try {
1692 final String setFuncName = tok.nextToken();
1693 final JavaCallbackDef jcd = javaCallbackSetFuncToDef.get(setFuncName);
1694 if( null == jcd ) {
1695 throw new IllegalArgumentException("JavaCallbackDef '"+setFuncName+"\' not (yet) defined.");
1696 }
1697
1698 // Collect setFuncKeyIndices
1699 String stok = null;
1700 while( tok.hasMoreTokens() ) {
1701 stok = tok.nextToken();
1702 if( !isInteger(stok) ) {
1703 break;
1704 }
1705 final int idx = Integer.parseInt(stok);
1706 if( 0 > idx ) {
1707 throw new IllegalArgumentException("JavaCallbackKey '"+setFuncName+"\' SetCallback-ParamIndex "+idx+" not in range [0..n].");
1708 }
1709 jcd.setFuncKeyIndices.add( idx );
1710 }
1711
1712 // Validate proper CallbackFuncType
1713 if( null == stok ) {
1714 throw new IllegalArgumentException("JavaCallbackKey '"+setFuncName+"\': CallbackFuncType missing.");
1715 }
1716 if( !stok.equals(jcd.cbFuncTypeName) ) {
1717 throw new IllegalArgumentException("JavaCallbackKey '"+setFuncName+"\': CallbackFuncType '"+stok+"' not matching JavaCallbackDef: "+jcd);
1718 }
1719
1720 // Collect cbFuncKeyIndices
1721 while( tok.hasMoreTokens() ) {
1722 final int idx = Integer.parseInt(tok.nextToken());
1723 if( 0 > idx ) {
1724 throw new IllegalArgumentException("JavaCallbackKey '"+setFuncName+"\' CallbackFunc-ParamIndex "+idx+" not in range [0..n].");
1725 }
1726 jcd.cbFuncKeyIndices.add( idx );
1727 }
1728 if( jcd.setFuncKeyIndices.size() != jcd.cbFuncKeyIndices.size() ) {
1729 throw new IllegalArgumentException("JavaCallbackKey '"+setFuncName+"\' SetCallback-ParamIndex list count "+jcd.setFuncKeyIndices.toString()+
1730 " != CallbackFunc-ParamIndex count "+jcd.cbFuncKeyIndices.toString());
1731 }
1732 } catch (final NoSuchElementException e) {
1733 throw new RuntimeException("Error parsing \"JavaCallbackKey\" command at line " + lineNo +
1734 " in file \"" + filename + "\"", e);
1735 }
1736 }
1737 private static boolean isInteger(final String s) {
1738 try {
1739 Integer.parseInt(s);
1740 return true;
1741 } catch(final Exception e) {
1742 return false;
1743 }
1744 }
1745
1746 protected void readExtendedIntfImplSymbols(final StringTokenizer tok, final String filename, final int lineNo, final boolean forInterface, final boolean forImplementation, final boolean onlyList) {
1747 File javaFile;
1748 BufferedReader javaReader;
1749 try {
1750 javaFile = new File(tok.nextToken());
1751 javaReader = new BufferedReader(new FileReader(javaFile));
1752 } catch (final FileNotFoundException e) {
1753 throw new RuntimeException(e);
1754 }
1755
1756 final JavaLexer lexer = new JavaLexer(javaReader);
1757 lexer.setFilename(javaFile.getName());
1758
1759 final JavaParser parser = new JavaParser(lexer);
1760 parser.setFilename(javaFile.getName());
1761
1762 try {
1763 parser.compilationUnit();
1764 } catch (final Exception e) {
1765 throw new RuntimeException(e);
1766 }
1767
1768 final Set<String> parsedEnumNames = parser.getParsedEnumNames();
1769 final Set<String> parsedFuncNames = parser.getParsedFunctionNames();
1770 final Set<String> parsedInnerInterfaces = parser.getParsedInnerInterfacesNames();
1771 final Set<String> parsedInnerClasses = parser.getParsedInnerClassesNames();
1772
1773 if(forInterface) {
1774 if(onlyList) {
1775 extendedIntfSymbolsOnly.addAll(parsedEnumNames);
1776 extendedIntfSymbolsOnly.addAll(parsedFuncNames);
1777 extendedIntfSymbolsOnly.addAll(parsedInnerInterfaces);
1778 extendedIntfSymbolsOnly.addAll(parsedInnerClasses);
1779 } else {
1780 extendedIntfSymbolsIgnore.addAll(parsedEnumNames);
1781 extendedIntfSymbolsIgnore.addAll(parsedFuncNames);
1782 extendedIntfSymbolsIgnore.addAll(parsedInnerInterfaces);
1783 extendedIntfSymbolsIgnore.addAll(parsedInnerClasses);
1784 }
1785 }
1786 if(forImplementation) {
1787 if(onlyList) {
1788 extendedImplSymbolsOnly.addAll(parsedEnumNames);
1789 extendedImplSymbolsOnly.addAll(parsedFuncNames);
1790 extendedImplSymbolsOnly.addAll(parsedInnerInterfaces);
1791 extendedImplSymbolsOnly.addAll(parsedInnerClasses);
1792 } else {
1793 extendedImplSymbolsIgnore.addAll(parsedEnumNames);
1794 extendedImplSymbolsIgnore.addAll(parsedFuncNames);
1795 extendedImplSymbolsIgnore.addAll(parsedInnerInterfaces);
1796 extendedImplSymbolsIgnore.addAll(parsedInnerClasses);
1797 }
1798 }
1799 }
1800
1801 protected void readIgnore(final StringTokenizer tok, final String filename, final int lineNo) {
1802 try {
1803 final String regex = tok.nextToken();
1804 final Pattern pattern = Pattern.compile(regex);
1805 ignores.add(pattern);
1806 ignoreMap.put(regex, pattern);
1807 //System.err.println("IGNORING " + regex + " / " + ignores.get(regex));
1808 } catch (final NoSuchElementException e) {
1809 throw new RuntimeException("Error parsing \"Ignore\" command at line " + lineNo +
1810 " in file \"" + filename + "\"", e);
1811 }
1812 }
1813
1814 protected void readUnignore(final StringTokenizer tok, final String filename, final int lineNo) {
1815 try {
1816 final String regex = tok.nextToken();
1817 Pattern pattern = ignoreMap.get(regex);
1818 ignoreMap.remove(regex);
1819 ignores.remove(pattern);
1820
1821 // If the pattern wasn't registered before, then make sure we have a
1822 // valid pattern instance to put into the unignores set.
1823 if(pattern == null)
1824 pattern = Pattern.compile(regex);
1825 unignores.add(pattern);
1826
1827 //System.err.println("UN-IGNORING " + regex + " / " + ignores.get(regex));
1828 } catch (final NoSuchElementException e) {
1829 throw new RuntimeException("Error parsing \"Unignore\" command at line " + lineNo +
1830 " in file \"" + filename + "\"", e);
1831 }
1832 }
1833
1834 protected void readIgnoreNot(final StringTokenizer tok, final String filename, final int lineNo) {
1835 try {
1836 final String regex = tok.nextToken();
1837 ignoreNots.add(Pattern.compile(regex));
1838 //System.err.println("IGNORING NEGATION OF " + regex + " / " + ignores.get(regex));
1839 } catch (final NoSuchElementException e) {
1840 throw new RuntimeException("Error parsing \"IgnoreNot\" command at line " + lineNo +
1841 " in file \"" + filename + "\"", e);
1842 }
1843 }
1844
1845 protected void readUnimplemented(final StringTokenizer tok, final String filename, final int lineNo) {
1846 try {
1847 final String regex = tok.nextToken();
1848 unimplemented.add(Pattern.compile(regex));
1849 } catch (final NoSuchElementException e) {
1850 throw new RuntimeException("Error parsing \"Unimplemented\" command at line " + lineNo +
1851 " in file \"" + filename + "\"", e);
1852 }
1853 }
1854
1855 protected void readIgnoreField(final StringTokenizer tok, final String filename, final int lineNo) {
1856 try {
1857 final String containingStruct = tok.nextToken();
1858 final String name = tok.nextToken();
1859 ignores.add(Pattern.compile(containingStruct + "\\." + name));
1860 } catch (final NoSuchElementException e) {
1861 throw new RuntimeException("Error parsing \"IgnoreField\" command at line " + lineNo +
1862 " in file \"" + filename + "\"", e);
1863 }
1864 }
1865
1866 protected void readImmutableAccess(final StringTokenizer tok, final String filename, final int lineNo) {
1867 try {
1868 final String name = tok.nextToken();
1869 immutableAccessSymbols.add(name);
1870 } catch (final NoSuchElementException e) {
1871 throw new RuntimeException("Error parsing \"ImmutableAccess\" command at line " + lineNo +
1872 " in file \"" + filename + "\"", e);
1873 }
1874 }
1875
1876 protected void readManuallyImplement(final StringTokenizer tok, final String filename, final int lineNo) {
1877 try {
1878 final String name = tok.nextToken();
1879 manuallyImplement.add(name);
1880 } catch (final NoSuchElementException e) {
1881 throw new RuntimeException("Error parsing \"ManuallyImplement\" command at line " + lineNo +
1882 " in file \"" + filename + "\"", e);
1883 }
1884 }
1885
1886 protected void readCustomJavaCode(final StringTokenizer tok, final String filename, final int lineNo) {
1887 try {
1888 final String tokenClassName = tok.nextToken();
1889 try {
1890 final String restOfLine = tok.nextToken("\n\r\f");
1891 addCustomJavaCode(tokenClassName, restOfLine);
1892 } catch (final NoSuchElementException e) {
1893 addCustomJavaCode(tokenClassName, "");
1894 }
1895 } catch (final NoSuchElementException e) {
1896 throw new RuntimeException("Error parsing \"CustomJavaCode\" command at line " + lineNo +
1897 " in file \"" + filename + "\"", e);
1898 }
1899 }
1900
1901 protected void addCustomJavaCode(final String className, final String code) {
1902 final List<String> codeList = customJavaCodeForClass(className);
1903 codeList.add(code);
1904 }
1905
1906 protected void readCustomCCode(final StringTokenizer tok, final String filename, final int lineNo) {
1907 try {
1908 final String restOfLine = tok.nextToken("\n\r\f");
1909 customCCode.add(restOfLine);
1910 } catch (final NoSuchElementException e) {
1911 customCCode.add("");
1912 }
1913 }
1914
1915 protected void readCustomJNICode(final StringTokenizer tok, final String filename, final int lineNo) {
1916 try {
1917 final String tokenClassName = tok.nextToken();
1918 try {
1919 final String restOfLine = tok.nextToken("\n\r\f");
1920 addCustomJNICode(tokenClassName, restOfLine);
1921 } catch (final NoSuchElementException e) {
1922 addCustomJNICode(tokenClassName, "");
1923 }
1924 } catch (final NoSuchElementException e) {
1925 throw new RuntimeException("Error parsing \"CustomJNICode\" command at line " + lineNo +
1926 " in file \"" + filename + "\"", e);
1927 }
1928 }
1929
1930 protected void addCustomJNICode(final String className, final String code) {
1931 final List<String> codeList = customJNICodeForClass(className);
1932 codeList.add(code);
1933 }
1934
1935 protected void readMethodJavadoc(final StringTokenizer tok, final String filename, final int lineNo) {
1936 try {
1937 final String tokenClassName = tok.nextToken();
1938 final String restOfLine = tok.nextToken("\n\r\f");
1939 addMethodJavadoc(tokenClassName, restOfLine);
1940 } catch (final NoSuchElementException e) {
1941 throw new RuntimeException("Error parsing \"MethodJavadoc\" command at line " + lineNo +
1942 " in file \"" + filename + "\"", e);
1943 }
1944 }
1945 protected void addMethodJavadoc(final String methodName, final String code) {
1946 final List<String> codeList = javadocForMethod(methodName);
1947 codeList.add(code);
1948 }
1949
1950 protected void readClassJavadoc(final StringTokenizer tok, final String filename, final int lineNo) {
1951 try {
1952 final String tokenClassName = tok.nextToken();
1953 final String restOfLine = tok.nextToken("\n\r\f");
1954 addClassJavadoc(tokenClassName, restOfLine);
1955 } catch (final NoSuchElementException e) {
1956 throw new RuntimeException("Error parsing \"ClassJavadoc\" command at line " + lineNo +
1957 " in file \"" + filename + "\"", e);
1958 }
1959 }
1960
1961 protected void addClassJavadoc(final String className, final String code) {
1962 final List<String> codeList = javadocForClass(className);
1963 codeList.add(code);
1964 }
1965
1966 /**
1967 * When const char* arguments in the C function prototypes are encountered,
1968 * the emitter will normally convert them to <code>byte[]</code>
1969 * arguments. This directive lets you specify which of those arguments
1970 * should be converted to <code>String</code> arguments instead of <code>
1971 * byte[] </code>. <p>
1972 *
1973 * For example, given the C prototype:
1974 * <pre>
1975 * void FuncName(const char* ugh, int bar, const char *foo, const char* goop);
1976 * </pre>
1977 *
1978 * The emitter will normally emit:
1979 * <pre>
1980 * public abstract void FuncName(byte[] ugh, int bar, byte[] foo, byte[] goop);
1981 * </pre>
1982 *
1983 * However, if you supplied the following directive:
1984 *
1985 * <pre>
1986 * ArgumentIsString FuncName 0 2
1987 * </pre>
1988 *
1989 * The emitter will instead emit:
1990 * <pre>
1991 * public abstract void FuncName(String ugh, int bar, String foo, byte[] goop);
1992 * </pre>
1993 *
1994 */
1995 protected void readArgumentIsString(final StringTokenizer tok, final String filename, final int lineNo) {
1996 try {
1997 final String methodName = tok.nextToken();
1998 final ArrayList<Integer> argIndices = new ArrayList<Integer>(2);
1999 while (tok.hasMoreTokens()) {
2000 final Integer idx = Integer.valueOf(tok.nextToken());
2001 argIndices.add(idx);
2002 }
2003
2004 if (argIndices.size() > 0) {
2005 argumentsAreString.put(methodName, argIndices);
2006 } else {
2007 throw new RuntimeException("ERROR: Error parsing \"ArgumentIsString\" command at line " + lineNo +
2008 " in file \"" + filename + "\": directive requires specification of at least 1 index");
2009 }
2010 } catch (final NoSuchElementException e) {
2011 throw new RuntimeException(
2012 "Error parsing \"ArgumentIsString\" command at line " + lineNo +
2013 " in file \"" + filename + "\"", e);
2014 }
2015 }
2016
2017 protected void readArgumentIsPascalString(final StringTokenizer tok, final String filename, final int lineNo) {
2018 try {
2019 final String methodName = tok.nextToken();
2020 final List<JavaType.PascalStringElem> pascalTuples = new ArrayList<JavaType.PascalStringElem>(2);
2021 while (tok.countTokens() >= 2) {
2022 final int lenIdx = Integer.valueOf(tok.nextToken()).intValue();
2023 final int valIdx = Integer.valueOf(tok.nextToken()).intValue();
2024 pascalTuples.add(new JavaType.PascalStringElem(lenIdx, valIdx));
2025 }
2026 if( pascalTuples.size() > 0 ) {
2027 argumentsArePascalString.put(methodName, pascalTuples);
2028 }
2029 } catch (final NoSuchElementException e) {
2030 throw new RuntimeException(
2031 "Error parsing \"ArgumentIsPascalString\" command at line " + lineNo +
2032 " in file \"" + filename + "\"", e);
2033 }
2034 }
2035
2036 protected void readStructPackage(final StringTokenizer tok, final String filename, final int lineNo) {
2037 try {
2038 final String struct = tok.nextToken();
2039 final String pkg = tok.nextToken();
2040 structPackages.put(struct, pkg);
2041 } catch (final NoSuchElementException e) {
2042 throw new RuntimeException("Error parsing \"StructPackage\" command at line " + lineNo +
2043 " in file \"" + filename + "\"", e);
2044 }
2045 }
2046
2047 protected void readStructMachineDataInfoIndex(final StringTokenizer tok, final String filename, final int lineNo) {
2048 try {
2049 final String structName = tok.nextToken();
2050 String restOfLine = tok.nextToken("\n\r\f");
2051 restOfLine = restOfLine.trim();
2052 structMachineDataInfoIndex.put(structName, restOfLine);
2053 } catch (final NoSuchElementException e) {
2054 throw new RuntimeException("Error parsing \"StructMachineDataInfoIndex\" command at line " + lineNo +
2055 " in file \"" + filename + "\"", e);
2056 }
2057 }
2058
2059 protected void readReturnValueCapacity(final StringTokenizer tok, final String filename, final int lineNo) {
2060 try {
2061 final String functionName = tok.nextToken();
2062 String restOfLine = tok.nextToken("\n\r\f");
2063 restOfLine = restOfLine.trim();
2064 returnValueCapacities.put(functionName, restOfLine);
2065 } catch (final NoSuchElementException e) {
2066 throw new RuntimeException("Error parsing \"ReturnValueCapacity\" command at line " + lineNo +
2067 " in file \"" + filename + "\"", e);
2068 }
2069 }
2070
2071 protected void readReturnValueLength(final StringTokenizer tok, final String filename, final int lineNo) {
2072 try {
2073 final String functionName = tok.nextToken();
2074 String restOfLine = tok.nextToken("\n\r\f");
2075 restOfLine = restOfLine.trim();
2076 returnValueLengths.put(functionName, restOfLine);
2077 } catch (final NoSuchElementException e) {
2078 throw new RuntimeException("Error parsing \"ReturnValueLength\" command at line " + lineNo +
2079 " in file \"" + filename + "\"", e);
2080 }
2081 }
2082
2083 protected void readTemporaryCVariableDeclaration(final StringTokenizer tok, final String filename, final int lineNo) {
2084 try {
2085 final String functionName = tok.nextToken();
2086 String restOfLine = tok.nextToken("\n\r\f");
2087 restOfLine = restOfLine.trim();
2088 List<String> list = temporaryCVariableDeclarations.get(functionName);
2089 if (list == null) {
2090 list = new ArrayList<String>();
2091 temporaryCVariableDeclarations.put(functionName, list);
2092 }
2093 list.add(restOfLine);
2094 } catch (final NoSuchElementException e) {
2095 throw new RuntimeException("Error parsing \"TemporaryCVariableDeclaration\" command at line " + lineNo +
2096 " in file \"" + filename + "\"", e);
2097 }
2098 }
2099
2100 protected void readTemporaryCVariableAssignment(final StringTokenizer tok, final String filename, final int lineNo) {
2101 try {
2102 final String functionName = tok.nextToken();
2103 String restOfLine = tok.nextToken("\n\r\f");
2104 restOfLine = restOfLine.trim();
2105 List<String> list = temporaryCVariableAssignments.get(functionName);
2106 if (list == null) {
2107 list = new ArrayList<String>();
2108 temporaryCVariableAssignments.put(functionName, list);
2109 }
2110 list.add(restOfLine);
2111 } catch (final NoSuchElementException e) {
2112 throw new RuntimeException("Error parsing \"TemporaryCVariableAssignment\" command at line " + lineNo +
2113 " in file \"" + filename + "\"", e);
2114 }
2115 }
2116
2117 protected void doInclude(final StringTokenizer tok, final File file, final String filename, final int lineNo) throws IOException {
2118 try {
2119 final String includedFilename = tok.nextToken();
2120 File includedFile = new File(includedFilename);
2121 if (!includedFile.isAbsolute()) {
2122 includedFile = new File(file.getParentFile(), includedFilename);
2123 }
2124 read(includedFile.getAbsolutePath());
2125 } catch (final NoSuchElementException e) {
2126 throw new RuntimeException("Error parsing \"Include\" command at line " + lineNo +
2127 " in file \"" + filename + "\"", e);
2128 }
2129 }
2130
2131 protected void doIncludeAs(final StringTokenizer tok, final File file, final String filename, final int lineNo) throws IOException {
2132 try {
2133 final StringBuilder linePrefix = new StringBuilder(128);
2134 while (tok.countTokens() > 1)
2135 {
2136 linePrefix.append(tok.nextToken());
2137 linePrefix.append(" ");
2138 }
2139 // last token is filename
2140 final String includedFilename = tok.nextToken();
2141 File includedFile = new File(includedFilename);
2142 if (!includedFile.isAbsolute()) {
2143 includedFile = new File(file.getParentFile(), includedFilename);
2144 }
2145 read(includedFile.getAbsolutePath(), linePrefix.toString());
2146 } catch (final NoSuchElementException e) {
2147 throw new RuntimeException("Error parsing \"IncludeAs\" command at line " + lineNo +
2148 " in file \"" + filename + "\"", e);
2149 }
2150 }
2151
2152 protected void readExtend(final StringTokenizer tok, final String filename, final int lineNo) {
2153 try {
2154 final String interfaceName = tok.nextToken();
2155 final List<String> intfs = extendedInterfaces(interfaceName);
2156 intfs.add(tok.nextToken());
2157 } catch (final NoSuchElementException e) {
2158 throw new RuntimeException("Error parsing \"Extends\" command at line " + lineNo +
2159 " in file \"" + filename + "\": missing expected parameter", e);
2160 }
2161 }
2162
2163 protected void readImplements(final StringTokenizer tok, final String filename, final int lineNo) {
2164 try {
2165 final String tokenClassName = tok.nextToken();
2166 final List<String> intfs = implementedInterfaces(tokenClassName);
2167 intfs.add(tok.nextToken());
2168 } catch (final NoSuchElementException e) {
2169 throw new RuntimeException("Error parsing \"Implements\" command at line " + lineNo +
2170 " in file \"" + filename + "\": missing expected parameter", e);
2171 }
2172 }
2173
2174 protected void readParentClass(final StringTokenizer tok, final String filename, final int lineNo) {
2175 try {
2176 final String tokenClassName = tok.nextToken();
2177 parentClass.put(tokenClassName, tok.nextToken());
2178 } catch (final NoSuchElementException e) {
2179 throw new RuntimeException("Error parsing \"ParentClass\" command at line " + lineNo +
2180 " in file \"" + filename + "\": missing expected parameter", e);
2181 }
2182 }
2183
2184 protected void readRenameJavaType(final StringTokenizer tok, final String filename, final int lineNo) {
2185 try {
2186 final String fromName = tok.nextToken();
2187 final String toName = tok.nextToken();
2188 javaTypeRenames.put(fromName, toName);
2189 } catch (final NoSuchElementException e) {
2190 throw new RuntimeException("Error parsing \"RenameJavaType\" command at line " + lineNo +
2191 " in file \"" + filename + "\": missing expected parameter", e);
2192 }
2193 }
2194
2195 protected void readRenameJavaSymbol(final StringTokenizer tok, final String filename, final int lineNo) {
2196 try {
2197 final String fromName = tok.nextToken();
2198 final String toName = tok.nextToken();
2199 addJavaSymbolRename(fromName, toName);
2200 } catch (final NoSuchElementException e) {
2201 throw new RuntimeException("Error parsing \"RenameJavaSymbol\" command at line " + lineNo +
2202 " in file \"" + filename + "\": missing expected parameter", e);
2203 }
2204 }
2205
2206 public void readDelegateImplementation(final StringTokenizer tok, final String filename, final int lineNo) {
2207 try {
2208 final String fromName = tok.nextToken();
2209 final String toName = tok.nextToken();
2210 addDelegateImplementation(fromName, toName);
2211 } catch (final NoSuchElementException e) {
2212 throw new RuntimeException("Error parsing \"DelegateImplementation\" command at line " + lineNo +
2213 " in file \"" + filename + "\": missing expected parameter", e);
2214 }
2215 }
2216
2217 protected void readJavaPrologueOrEpilogue(final StringTokenizer tok, final String filename, final int lineNo, final boolean prologue) {
2218 try {
2219 String methodName = tok.nextToken();
2220 String restOfLine = tok.nextToken("\n\r\f");
2221 restOfLine = restOfLine.trim();
2222 if (startsWithDescriptor(restOfLine)) {
2223 // Assume it starts with signature for disambiguation
2224 final int spaceIdx = restOfLine.indexOf(' ');
2225 if (spaceIdx > 0) {
2226 final String descriptor = restOfLine.substring(0, spaceIdx);
2227 restOfLine = restOfLine.substring(spaceIdx + 1, restOfLine.length());
2228 methodName = methodName + descriptor;
2229 }
2230 }
2231 addJavaPrologueOrEpilogue(methodName, restOfLine, prologue);
2232 } catch (final NoSuchElementException e) {
2233 throw new RuntimeException("Error parsing \"" +
2234 (prologue ? "JavaPrologue" : "JavaEpilogue") +
2235 "\" command at line " + lineNo +
2236 " in file \"" + filename + "\"", e);
2237 }
2238 }
2239
2240 protected void addJavaPrologueOrEpilogue(final String methodName, final String code, final boolean prologue) {
2241 final Map<String, List<String>> codes = (prologue ? javaPrologues : javaEpilogues);
2242 List<String> data = codes.get(methodName);
2243 if (data == null) {
2244 data = new ArrayList<String>();
2245 codes.put(methodName, data);
2246 }
2247 data.add(code);
2248 }
2249
2250 protected void readRangeCheck(final StringTokenizer tok, final String filename, final int lineNo, final boolean inBytes) {
2251 try {
2252 final String functionName = tok.nextToken();
2253 final int argNum = Integer.parseInt(tok.nextToken());
2254 String restOfLine = tok.nextToken("\n\r\f");
2255 restOfLine = restOfLine.trim();
2256 // Construct a JavaPrologue for this
2257 addJavaPrologueOrEpilogue(functionName,
2258 "Buffers.rangeCheck" +
2259 (inBytes ? "Bytes" : "") +
2260 "({" + argNum + "}, " + restOfLine + ");",
2261 true);
2262 } catch (final Exception e) {
2263 throw new RuntimeException("Error parsing \"RangeCheck" + (inBytes ? "Bytes" : "") + "\" command at line " + lineNo +
2264 " in file \"" + filename + "\"", e);
2265 }
2266 }
2267
2268 protected static TypeInfo parseTypeInfo(final String cType, final JavaType javaType) {
2269 String typeName = null;
2270 int pointerDepth = 0;
2271 int idx = 0;
2272 while (idx < cType.length() &&
2273 (cType.charAt(idx) != ' ') &&
2274 (cType.charAt(idx) != '*')) {
2275 ++idx;
2276 }
2277 typeName = cType.substring(0, idx);
2278 // Count pointer depth
2279 while (idx < cType.length()) {
2280 if (cType.charAt(idx) == '*') {
2281 ++pointerDepth;
2282 }
2283 ++idx;
2284 }
2285 return new TypeInfo(typeName, pointerDepth, javaType);
2286 }
2287
2288 public TypeInfo addTypeInfo(final String alias, final Type superType) {
2289 final TypeInfo superInfo = typeInfo(superType);
2290 if( null != superInfo ) {
2291 final TypeInfo res = new TypeInfo(alias, superInfo.pointerDepth(), superInfo.javaType());
2292 addTypeInfo(res);
2293 return res;
2294 } else {
2295 return null;
2296 }
2297 }
2298 protected void addTypeInfo(final TypeInfo info) {
2299 TypeInfo tmp = typeInfoMap.get(info.name());
2300 if (tmp == null) {
2301 typeInfoMap.put(info.name(), info);
2302 return;
2303 }
2304 while (tmp.next() != null) {
2305 tmp = tmp.next();
2306 }
2307 tmp.setNext(info);
2308 }
2309
2310 private static int nextIndexAfterType(final String s, int idx) {
2311 final int len = s.length();
2312 while (idx < len) {
2313 final char c = s.charAt(idx);
2314
2315 if (Character.isJavaIdentifierStart(c) ||
2316 Character.isJavaIdentifierPart(c) ||
2317 (c == '/')) {
2318 idx++;
2319 } else if (c == ';') {
2320 return (idx + 1);
2321 } else {
2322 return -1;
2323 }
2324 }
2325 return -1;
2326 }
2327
2328 private static int nextIndexAfterDescriptor(final String s, final int idx) {
2329 final char c = s.charAt(idx);
2330 switch (c) {
2331 case 'B':
2332 case 'C':
2333 case 'D':
2334 case 'F':
2335 case 'I':
2336 case 'J':
2337 case 'S':
2338 case 'Z':
2339 case 'V': return (1 + idx);
2340 case 'L': return nextIndexAfterType(s, idx + 1);
2341 case ')': return idx;
2342 default: break;
2343 }
2344 return -1;
2345 }
2346
2347 protected static boolean startsWithDescriptor(final String s) {
2348 // Try to see whether the String s starts with a valid Java
2349 // descriptor.
2350
2351 int idx = 0;
2352 final int len = s.length();
2353 while ((idx < len) && s.charAt(idx) == ' ') {
2354 ++idx;
2355 }
2356
2357 if (idx >= len) return false;
2358 if (s.charAt(idx++) != '(') return false;
2359 while (idx < len) {
2360 final int nextIdx = nextIndexAfterDescriptor(s, idx);
2361 if (nextIdx < 0) {
2362 return false;
2363 }
2364 if (nextIdx == idx) {
2365 // ')'
2366 break;
2367 }
2368 idx = nextIdx;
2369 }
2370 final int nextIdx = nextIndexAfterDescriptor(s, idx + 1);
2371 if (nextIdx < 0) {
2372 return false;
2373 }
2374 return true;
2375 }
2376
2377 /**
2378 * JavaCallback compile time information, produced by {@link JavaEmitter#beginFunctions(TypeDictionary, TypeDictionary, Map)}
2379 * from {@link Type#isFunctionPointer() function-pointer} {@link Type}s mapped to {@link JavaConfiguration#getJavaCallbackList()} names via {@link TypeDictionary} (typedef).
2380 * @see JavaConfiguration#funcPtrTypeToJavaCallbackMap
2381 * @see JavaConfiguration#setFuncToJavaCallbackMap
2382 */
2383 public static class JavaCallbackInfo {
2384 final String cbFuncTypeName;
2385 final String cbSimpleClazzName;
2386 final String cbFQClazzName;
2387 final String staticCBMethodSignature;
2388 final FunctionType cbFuncType;
2389 final MethodBinding cbFuncBinding;
2390 final List<Integer> cbFuncKeyIndices;
2391 final int cbFuncUserParamIdx;
2392 final String cbFuncUserParamName;
2393 final Type cbFuncUserParamType;
2394
2395 final boolean cbUserParamIsDefined;
2396
2397 final String setFuncName;
2398 final List<Integer> setFuncKeyIndices;
2399 final int setFuncUserParamIdx;
2400 final String userParamClassName; // optional
2401 final String customKeyClassName; // optional
2402 boolean setFuncProcessed;
2403 int setFuncCBParamIdx;
2404 boolean keyClassEmitted;
2405
2406 public JavaCallbackInfo(final String cbFuncTypeName, final String cbSimpleClazzName, final String cbFQClazzName, final String staticCBMethodSignature,
2407 final FunctionType cbFuncType, final MethodBinding cbFuncBinding, final int cbFuncUserParamIdx, final List<Integer> cbFuncKeyIndices,
2408 final String setFuncName, final int setFuncUserParamIdx, final List<Integer> setFuncKeyIndices,
2409 final String userParamClassName, final String customKeyClassName) {
2410 this.cbFuncTypeName = cbFuncTypeName;
2411 this.cbSimpleClazzName = cbSimpleClazzName;
2412 this.cbFQClazzName = cbFQClazzName;
2413 this.staticCBMethodSignature = staticCBMethodSignature;
2414 this.cbFuncType = cbFuncType;
2415 this.cbFuncBinding = cbFuncBinding;
2416 this.cbUserParamIsDefined = setFuncUserParamIdx >= 0;
2417 if( cbUserParamIsDefined ) {
2418 int paramIdx = -2;
2419 Type paramType = null;
2420 String paramName = null;
2421 if( 0 <= cbFuncUserParamIdx && cbFuncUserParamIdx < cbFuncType.getNumArguments() ) {
2422 final Type t = cbFuncType.getArgumentType(cbFuncUserParamIdx);
2423 if( null != t && t.isPointer() ) {
2424 // OK '<something>*'
2425 paramIdx = cbFuncUserParamIdx;
2426 paramName = cbFuncType.getArgumentName(cbFuncUserParamIdx);
2427 paramType = t.getTargetType();
2428 }
2429 }
2430 this.cbFuncUserParamIdx = paramIdx;
2431 this.cbFuncUserParamName = paramName;
2432 this.cbFuncUserParamType = paramType;
2433 } else {
2434 this.cbFuncUserParamIdx = -1;
2435 this.cbFuncUserParamName = null;
2436 this.cbFuncUserParamType = null;
2437 }
2438 this.cbFuncKeyIndices = cbFuncKeyIndices;
2439 this.setFuncName = setFuncName;
2440 this.setFuncKeyIndices = setFuncKeyIndices;
2441 this.setFuncUserParamIdx = setFuncUserParamIdx;
2442 this.userParamClassName = userParamClassName;
2443 this.customKeyClassName = customKeyClassName;
2444 this.setFuncProcessed = false;
2445 this.setFuncCBParamIdx = -1;
2446 this.keyClassEmitted = false;
2447 }
2448 private void validateKeyIndices(final FunctionType setFuncType) {
2449 if( this.cbFuncKeyIndices.size() != this.setFuncKeyIndices.size() ) {
2450 throw new IllegalArgumentException("JavaCallback "+setFuncName+": Key count mismatch: setFunc "+setFuncKeyIndices.toString()+
2451 " != cbFunc "+cbFuncKeyIndices.toString());
2452 }
2453 for(int i=0; i< this.cbFuncKeyIndices.size(); ++i) {
2454 final int cbFuncIdx = this.cbFuncKeyIndices.get(i);
2455 final Type t1 = this.cbFuncType.getArgumentType(cbFuncIdx);
2456 final int setFuncIdx = this.setFuncKeyIndices.get(i);
2457 final Type t2 = setFuncType.getArgumentType(setFuncIdx);
2458 if( !t1.equals(t2) ) {
2459 throw new IllegalArgumentException("JavaCallback "+setFuncName+": Key Type mismatch: setFunc#"+setFuncIdx+" with "+t2.toString()+", cbFunc#"+cbFuncIdx+" with "+t1.toString());
2460 }
2461 }
2462 }
2463
2464 public void setFuncProcessed(final FunctionType setFuncType, final int cbParamIdx) {
2465 if( !setFuncProcessed ) {
2466 if( 0 <= cbParamIdx ) {
2467 setFuncProcessed = true;
2468 setFuncCBParamIdx = cbParamIdx;
2469 validateKeyIndices(setFuncType);
2470 } else {
2471 setFuncCBParamIdx = -1;
2472 }
2473 }
2474 }
2475
2476 @Override
2477 public String toString() {
2478 return String.format("JavaCallbackInfo[cbFunc[%s%s, userParam[defined %b, idx %d, '%s', %s, keys %s], set[%s(ok %b, cbIdx %d, upIdx %d, keys %s], Class[UserParam '%s', Key '%s'], %s]",
2479 cbFuncTypeName, staticCBMethodSignature,
2480 cbUserParamIsDefined, cbFuncUserParamIdx, cbFuncUserParamName, cbUserParamIsDefined ? cbFuncUserParamType.getSignature(null).toString() : null, cbFuncKeyIndices.toString(),
2481 setFuncName, setFuncProcessed, setFuncCBParamIdx, setFuncUserParamIdx,
2482 setFuncKeyIndices.toString(), userParamClassName, customKeyClassName,
2483 cbFuncType.toString(cbFuncTypeName, false, true));
2484 }
2485 }
2486 /** Mapped binding name to {@link JavaCallbackInfo} */
2487 /* pp */ final Map<String, JavaCallbackInfo> setFuncToJavaCallbackMap = new HashMap<String, JavaCallbackInfo>();
2488 final Set<String> emittedJavaCallbackUserParamClasses = new HashSet<String>();
2489
2490 /** Returns true if a method binding requires specific java callback code */
2491 final boolean requiresJavaCallbackCode(final String bindingName) {
2492 final JavaCallbackInfo jcbi = setFuncToJavaCallbackMap.get(bindingName);
2493 return null != jcbi;
2494 }
2495
2496}
Glue code generator for C functions and data structures.
Definition: GlueGen.java:59
JavaCallback configuration definition (static)
JavaCallback compile time information, produced by JavaEmitter#beginFunctions(TypeDictionary,...
void setFuncProcessed(final FunctionType setFuncType, final int cbParamIdx)
JavaCallbackInfo(final String cbFuncTypeName, final String cbSimpleClazzName, final String cbFQClazzName, final String staticCBMethodSignature, final FunctionType cbFuncType, final MethodBinding cbFuncBinding, final int cbFuncUserParamIdx, final List< Integer > cbFuncKeyIndices, final String setFuncName, final int setFuncUserParamIdx, final List< Integer > setFuncKeyIndices, final String userParamClassName, final String customKeyClassName)
Parses and provides access to the contents of .cfg files for the JavaEmitter.
void readReturnValueLength(final StringTokenizer tok, final String filename, final int lineNo)
List< Integer > stringArguments(final AliasedSymbol symbol)
Returns a list of Integers which are the indices of const char* arguments that should be converted to...
void readCustomJavaCode(final StringTokenizer tok, final String filename, final int lineNo)
String extendedParentClass(final String className)
Returns a List of Strings indicating the interfaces the passed class should declare it implements.
void readOpaque(final StringTokenizer tok, final String filename, final int lineNo)
String implClassName()
Returns the implementation class name parsed from the configuration file.
List< String > customJavaCodeForClass(final String className)
Returns a list of Strings containing user-implemented code for the given Java type name (not fully-qu...
static ASTLocusTag getASTLocusTag(final AliasedSymbol s)
void readUnignore(final StringTokenizer tok, final String filename, final int lineNo)
void readJavaPrologueOrEpilogue(final StringTokenizer tok, final String filename, final int lineNo, final boolean prologue)
List< JavaType.PascalStringElem > pascalStringArgument(final AliasedSymbol symbol)
Returns a list of PascalStringIdx which are tuples of indices of int len, const char* arguments that ...
void readIgnoreField(final StringTokenizer tok, final String filename, final int lineNo)
List< String > temporaryCVariableAssignments(final String functionName)
Returns a List of Strings of expressions containing assignments to temporary C variables in the glue ...
boolean allStatic()
Returns true if the emission style is AllStatic.
final boolean shouldIgnoreInImpl_Int(final AliasedSymbol symbol)
void readExtendedIntfImplSymbols(final StringTokenizer tok, final String filename, final int lineNo, final boolean forInterface, final boolean forImplementation, final boolean onlyList)
final void read(final String filename)
Reads the configuration file.
void readStructMachineDataInfoIndex(final StringTokenizer tok, final String filename, final int lineNo)
JavaCallbackDef javaCallbackSetFuncToDef(final AliasedSymbol symbol)
Returns the configured JavaCallback definition mapped to the JavaCallback-Set-Function name.
void readReturnValueCapacity(final StringTokenizer tok, final String filename, final int lineNo)
boolean useNIOOnly(final String functionName)
Returns true if the given function should only create a java.nio variant, and no array variants,...
void readManuallyImplement(final StringTokenizer tok, final String filename, final int lineNo)
boolean returnsString(final AliasedSymbol symbol)
Indicates whether the given function (which returns a char* in C) should be translated as returning a...
List< String > forcedStructs()
Returns, as a List of Strings, the structs for which glue code emission should be forced.
final boolean immutableAccess(final String symbol)
Returns true if the glue code for the given symbol shall produce code for immutable access only.
void readMaxOneElement(final StringTokenizer tok, final String filename, final int lineNo)
void readReturnsOpaque(final StringTokenizer tok, final String filename, final int lineNo)
String nativeOutputDir()
Returns the native code output directory parsed from the configuration file.
List< String > imports()
Returns the list of imports that should be emitted at the top of each .java file.
boolean shouldIgnoreInInterface(final AliasedSymbol symbol)
Returns true if this aliased symbol should be ignored during glue code generation of interfaces and i...
boolean tagNativeBinding()
Returns whether the comment of a native method binding should include a @native tag.
void addJavaSymbolRename(final String origName, final String newName)
Programmatically adds a rename directive for the given symbol.
TypeInfo canonicalNameOpaque(final String canonicalName)
If the given canonicalName should be considered opaque, returns the TypeInfo describing the replaceme...
void readStructPackage(final StringTokenizer tok, final String filename, final int lineNo)
void readImplements(final StringTokenizer tok, final String filename, final int lineNo)
void readDelegateImplementation(final StringTokenizer tok, final String filename, final int lineNo)
void readTemporaryCVariableAssignment(final StringTokenizer tok, final String filename, final int lineNo)
boolean shouldIgnoreInImpl(final AliasedSymbol symbol)
Returns true if this aliased symbol should be ignored during glue code generation of implementation o...
void readJavaCallbackKey(final StringTokenizer tok, final String filename, final int lineNo)
String returnValueLength(final String symbol)
Returns a MessageFormat string of the C expression calculating the length of the array being returned...
String returnedArrayLength(final String symbol)
Returns a MessageFormat string of the Java expression calculating the number of elements in the retur...
String getDelegatedImplementation(final AliasedSymbol symbol)
Returns the RENAMED-IMPL-SYMBOL if the implementation of the glue code of the given function shall be...
void readArgumentIsString(final StringTokenizer tok, final String filename, final int lineNo)
When const char* arguments in the C function prototypes are encountered, the emitter will normally co...
boolean returnsStringOnly(final String functionName)
Indicates whether the given function (which returns a char* in C) should be translated as returning a...
boolean emitInterface()
Returns true if an interface should be emitted during glue code generation.
String className()
Returns the class name parsed from the configuration file.
void dispatch(final String cmd, final StringTokenizer tok, final File file, final String filename, final int lineNo)
static TypeInfo parseTypeInfo(final String cType, final JavaType javaType)
boolean emitImpl()
Returns true if an implementing class should be emitted during glue code generation.
String gluegenRuntimePackage()
Returns the package in which the generated glue code expects to find its run-time helper classes (Buf...
boolean manuallyImplement(final String functionName)
Variant of manuallyImplement(AliasedSymbol), where this method only considers the current-name of the...
boolean maxOneElement(final String symbol)
Indicates whether the given symbol covers no or one single object.
void readReturnsStringOnly(final StringTokenizer tok, final String filename, final int lineNo)
boolean isUnimplemented(final AliasedSymbol symbol)
Returns true if this function should be given a body which throws a run-time exception with an "unimp...
void readClassJavadoc(final StringTokenizer tok, final String filename, final int lineNo)
TypeInfo addTypeInfo(final String alias, final Type superType)
static String canonicalStructFieldSymbol(final String structName, final String fieldName)
Returns the canonical configuration name for a struct field name, i.e.
final boolean shouldIgnoreInInterface_Int(final AliasedSymbol symbol)
String runtimeExceptionType()
Returns the kind of exception to raise if run-time checks fail in the generated code.
void readJavaCallbackDef(final StringTokenizer tok, final String filename, final int lineNo)
List< String > customCCode()
Returns, as a List of Strings, the custom C code to be emitted along with the glue code for the main ...
String returnStructMachineDataInfoIndex(final String structName)
Returns a MessageFormat string of the Java code defining mdIdx, i.e.
EmissionStyle emissionStyle()
Returns the code emission style (constants in JavaEmitter) parsed from the configuration file.
void readParentClass(final StringTokenizer tok, final String filename, final int lineNo)
static< K, V > V oneInMap(final Map< K, V > map, final Set< K > symbols)
static< K > boolean oneInSet(final Set< K > set1, final Set< K > set2)
void readExtend(final StringTokenizer tok, final String filename, final int lineNo)
List< JavaCallbackDef > getJavaCallbackList()
Returns the list of all configured JavaCallback definitions.
void readMethodJavadoc(final StringTokenizer tok, final String filename, final int lineNo)
String implPackageName()
Returns the implementation package name parsed from the configuration file.
void addJavaPrologueOrEpilogue(final String methodName, final String code, final boolean prologue)
void doInclude(final StringTokenizer tok, final File file, final String filename, final int lineNo)
Set< String > getAliasedDocNames(final AliasedSymbol symbol)
Return a set of aliased-name for comment in docs.
MethodAccess accessControl(final String name)
Returns the access control for the given method-name or fully qualified class-name.
List< String > javaPrologueForMethod(final MethodBinding binding, final boolean forImplementingMethodCall, final boolean eraseBufferAndArrayTypes)
Returns a list of Strings which should be emitted as a prologue to the body for the Java-side glue co...
void addUseNIODirectOnly(final String fname)
String readString(final String cmd, final StringTokenizer tok, final String filename, final int lineNo)
final boolean immutableAccess(final AliasedSymbol symbol)
Returns true if the glue code for the given aliased symbol shall produce code for immutable access on...
void doIncludeAs(final StringTokenizer tok, final File file, final String filename, final int lineNo)
JavaType getOpaqueReturnType(final AliasedSymbol symbol)
Returns the opaque JavaType for the given function AliasedSymbol or null if not opaque.
JavaType getOpaqueReturnType(final String functionName)
Variant of getOpaqueReturnType(AliasedSymbol), where this method only considers the current-name of t...
Set< String > getRenamedJavaSymbols(final String aliasedName)
Returns a set of replaced names to the given aliasedName.
String javaOutputDir()
Returns the Java code output directory parsed from the configuration file.
String libraryOnLoadName()
Returns the library basename used to CCodeUnit#emitJNIOnLoadJNIEnvCode(String).
String packageForStruct(final String structName)
Returns the package into which to place the glue code for accessing the specified struct.
List< String > implementedInterfaces(final String className)
Returns a List of Strings indicating the interfaces the passed class should declare it implements.
boolean returnsString(final String functionName)
Indicates whether the given function (which returns a char* in C) should be translated as returning a...
void readUnimplemented(final StringTokenizer tok, final String filename, final int lineNo)
void readTemporaryCVariableDeclaration(final StringTokenizer tok, final String filename, final int lineNo)
void readCustomCCode(final StringTokenizer tok, final String filename, final int lineNo)
Class<?> stringToPrimitiveType(final String type)
void readReturnedArrayLength(final StringTokenizer tok, final String filename, final int lineNo)
void readImmutableAccess(final StringTokenizer tok, final String filename, final int lineNo)
void addMethodJavadoc(final String methodName, final String code)
boolean relaxedEqualSemanticsTest()
Returns whether TypeConfig.SemanticEqualityOp#equalSemantics(TypeConfig.SemanticEqualityOp) shall att...
String unsupportedExceptionType()
Returns the kind of exception to raise if run-time checks fail in the generated code.
String getJavaSymbolRename(final String origName)
Returns a replacement name for this function or definition which should be used as the Java name for ...
void addCustomJNICode(final String className, final String code)
List< String > javaEpilogueForMethod(final MethodBinding binding, final boolean forImplementingMethodCall, final boolean eraseBufferAndArrayTypes)
Returns a list of Strings which should be emitted as an epilogue to the body for the Java-side glue c...
List< String > javadocForMethod(final String methodName)
void addDelegateImplementation(final String origName, final String renamedImpl)
Programmatically adds a delegate implementation directive for the given symbol.
String packageName()
Returns the package name parsed from the configuration file.
String returnValueCapacity(final String functionName)
Returns a MessageFormat string of the C expression calculating the capacity of the java....
String getDelegatedImplementation(final String functionName)
Variant of getDelegatedImplementation(AliasedSymbol), where this method only considers the current-na...
String renameJavaType(final String javaTypeName)
Returns a replacement name for this type, which should be the name of a Java wrapper class for a C st...
void readCustomJNICode(final StringTokenizer tok, final String filename, final int lineNo)
void readRenameJavaSymbol(final StringTokenizer tok, final String filename, final int lineNo)
void readRenameJavaType(final StringTokenizer tok, final String filename, final int lineNo)
List< String > temporaryCVariableDeclarations(final String functionName)
Returns a List of Strings of expressions declaring temporary C variables in the glue code for the spe...
void readIgnore(final StringTokenizer tok, final String filename, final int lineNo)
void readIgnoreNot(final StringTokenizer tok, final String filename, final int lineNo)
TypeInfo typeInfo(Type type)
If this type should be considered opaque, returns the TypeInfo describing the replacement type.
boolean nativeOutputUsesJavaHierarchy()
Returns whether the native code directory structure mirrors the Java hierarchy.
void readReturnsString(final StringTokenizer tok, final String filename, final int lineNo)
static boolean startsWithDescriptor(final String s)
void readRangeCheck(final StringTokenizer tok, final String filename, final int lineNo, final boolean inBytes)
void addClassJavadoc(final String className, final String code)
List< String > customJNICodeForClass(final String className)
Returns a list of Strings containing user-implemented JNI code for the given Java type name (not full...
boolean manuallyImplement(final AliasedSymbol symbol)
Returns true if the glue code for the given aliased function will be manually implemented by the end ...
void addCustomJavaCode(final String className, final String code)
Boolean readBoolean(final String cmd, final StringTokenizer tok, final String filename, final int lineNo)
boolean useNIODirectOnly(final String functionName)
Returns true if the given function should only create a java.nio variant, and no array variants,...
final boolean shouldIgnoreInInterface(final String symbol)
Variant of shouldIgnoreInInterface(AliasedSymbol), where this method only considers the current-name ...
void readArgumentIsPascalString(final StringTokenizer tok, final String filename, final int lineNo)
List< String > javadocForClass(final String className)
Returns a list of Strings containing Javadoc documentation for the given Java type name (not fully-qu...
void readAccessControl(final StringTokenizer tok, final String filename, final int lineNo)
List< String > extendedInterfaces(final String interfaceName)
Returns a List of Strings indicating the interfaces the passed interface should declare it extends.
final void read(final String filename, final String linePrefix)
Reads the specified file, treating each line as if it started with the specified string.
Pascal string argument index tuple for length and value.
Definition: JavaType.java:65
Describes a java-side representation of a type that is used to represent the same data on both the Ja...
Definition: JavaType.java:54
static JavaType createForOpaqueClass(final Class<?> clazz)
Creates a JavaType corresponding to the given opaque Java type.
Definition: JavaType.java:189
static LoggerIf getLogger()
Returns the root package logger.
Definition: Logging.java:355
Represents the binding of a C function to a Java method.
String getDescriptor(final boolean forImplementingMethodCall, final boolean eraseBufferAndArrayTypes)
Returns a String containing the descriptor (signature in internal format) of this MethodBinding as it...
String getName()
Returns the FunctionSymbol's current aliased API name.
Static Type config helper binding JavaConfiguration#relaxedEqualSemanticsTest() system wide.
Definition: TypeConfig.java:37
Utility class for handling Opaque directives for JavaEmitter.
Definition: TypeInfo.java:45
void setNext(final TypeInfo info)
Definition: TypeInfo.java:60
String getStructName()
Returns the struct name of this CompoundType, i.e.
Describes a function type, used to model both function declarations and (via PointerType) function po...
String getArgumentName(final int i)
Returns the name of the ith argument.
String toString()
Returns a string representation of this type.
Type getArgumentType(final int i)
Returns the type of the ith argument.
final Type getTargetType()
Helper method to returns the target type of this type, in case another type is being referenced,...
final StringBuilder getSignature(StringBuilder sb)
Definition: Type.java:173
PointerType asPointer()
Casts this to a PointerType or returns null if not a PointerType.
Definition: Type.java:386
final String getName()
Returns the name of this type.
Definition: Type.java:142
int pointerDepth()
Helper method for determining how many pointer indirections this type represents (i....
Definition: Type.java:564
String toString()
Returns a string representation of this type.
Definition: Type.java:161
Type getTargetType()
Helper method to returns the target type of this type, in case another type is being referenced,...
Definition: Type.java:605
final boolean equals(final Object arg)
Equality test for Types inclusive its given name.
Definition: Type.java:468
final boolean isPointer()
Indicates whether this is a PointerType.
Definition: Type.java:407
CompoundType asCompound()
Casts this to a CompoundType or returns null if not a CompoundType.
Definition: Type.java:390
final boolean isCompound()
Indicates whether this is a CompoundType.
Definition: Type.java:411
Set< String > getParsedEnumNames()
Returns the EnumTypes this HeaderParser processed.
Definition: JavaParser.java:36
Set< String > getParsedFunctionNames()
Returns the list of FunctionSymbols this HeaderParser has parsed.
Definition: JavaParser.java:48
Set< String > getParsedInnerClassesNames()
Returns the list of inner classes this HeaderParser has parsed.
Definition: JavaParser.java:72
Set< String > getParsedInnerInterfacesNames()
Returns the list of inner interfaces this HeaderParser has parsed.
Definition: JavaParser.java:60
Access control for emitted Java methods.
Interface tag for ASTLocusTag provider.
An interface for Logger.
Definition: Logging.java:59
boolean isLoggable(Level level)
See Logger#isLoggable(Level).
void log(final Level level, final String msg)
See Logger#log(Level, String).
Set< String > getAliasedNames()
Return all aliases for this symbol, i.e.
String getName()
Return the current-name, which is the last renamed-name if issued, or the original-name.