aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/com
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-04-01 15:51:04 +0200
committerSven Gothel <[email protected]>2015-04-01 15:51:04 +0200
commitc6d5ee30e023d030697f14ae2c444ce7a5542e94 (patch)
tree0013fef29a228522b6791630385932d38a36a399 /src/java/com
parentc156343fec33ceea7f238b9766a9f4985fb92687 (diff)
Bug 1153 - GlueGen: Support [const] [native] expressions and conversion to java space, incl. [native] numbers
Rewrite ConstantDefinition: Add sub-class CNumber: - containing integer/float values and their original qualifiers [long, double, unsigned] - conversion to java number ConstantDefinition: - holds native expression - optionally holds CNumber representing native expression, if [only] a number - can compute equivalent java expression with result type (JavaExpr) Add static native number reg-expression for number detection and parsing. Add static native number to CNumber conversion methods. +++ Retrieve full LISP tree and convert to serialized expression to be utilized for expressions used in enumerates. Parse enumerates, allowing const native expressions: - Utilize ConstantDefinition either for definite CNumber or expression - Simply add "+1" for new default values, if previous is an expression
Diffstat (limited to 'src/java/com')
-rw-r--r--src/java/com/jogamp/gluegen/ConstantDefinition.java831
-rw-r--r--src/java/com/jogamp/gluegen/DebugEmitter.java2
-rw-r--r--src/java/com/jogamp/gluegen/GlueGen.java11
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java279
-rw-r--r--src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java2
-rw-r--r--src/java/com/jogamp/gluegen/cgram/TNode.java83
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/EnumType.java76
7 files changed, 942 insertions, 342 deletions
diff --git a/src/java/com/jogamp/gluegen/ConstantDefinition.java b/src/java/com/jogamp/gluegen/ConstantDefinition.java
index f8f4973..675c6d7 100644
--- a/src/java/com/jogamp/gluegen/ConstantDefinition.java
+++ b/src/java/com/jogamp/gluegen/ConstantDefinition.java
@@ -1,38 +1,35 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+/**
+ * Copyright 2015 JogAmp Community. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
*
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
*
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
*
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
-
package com.jogamp.gluegen;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
@@ -40,55 +37,351 @@ import com.jogamp.gluegen.cgram.types.AliasedSymbol.AliasedSymbolImpl;
import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
-/** Represents the definition of a constant which was provided either
- via a #define statement or through an enum definition. */
+/**
+ * Represents a [native] constant expression,
+ * comprises the [native] expression, see {@link #getNativeExpr()}
+ * and the optional {@link CNumber} representation, see {@link #getNumber()}.
+ * <p>
+ * The representation of the equivalent java expression including
+ * the result type is covered by {@link JavaExpr},
+ * which can be computed via {@link #computeJavaExpr(Map)}.
+ * </p>
+ * <p>
+ * This class and its sub-classes define and convert all native expressions
+ * to Java space.
+ * </p>
+ */
public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSemanticSymbol, ASTLocusTagProvider {
+ public static final long UNSIGNED_INT_MAX_VALUE = 0xffffffffL;
+ public static final BigInteger UNSIGNED_LONG_MAX_VALUE = new BigInteger("ffffffffffffffff", 16);
+
+ /**
+ * A Number, either integer, optionally [long, unsigned],
+ * or floating point, optionally [double].
+ */
+ public static class CNumber {
+ /**
+ * {@code true} if number is integer and value stored in {@link #i},
+ * otherwise {@code false} for floating point and value stored in {@link #f}.
+ */
+ public final boolean isInteger;
+ /** {@code true} if number is a {@code long} {@link #isInteger}. */
+ public final boolean isLong;
+ /** {@code true} if number is an {@code unsigned} {@link #isInteger}. */
+ public final boolean isUnsigned;
+ /** The value if {@link #isInteger} */
+ public final long i;
+
+ /** {@code true} if number is a {@code double precision} {@code floating point}, i.e. !{@link #isInteger}. */
+ public final boolean isDouble;
+ /** The value if !{@link #isInteger} */
+ public final double f;
+
+ /** ctor for integer number */
+ public CNumber(final boolean isLong, final boolean isUnsigned, final long value) {
+ this.isInteger = true;
+ this.isLong = isLong;
+ this.isUnsigned = isUnsigned;
+ this.i = value;
+ this.isDouble = false;
+ this.f = 0.0;
+ }
+ /** ctor for floating point number */
+ public CNumber(final boolean isDouble, final double value) {
+ this.isInteger = false;
+ this.isLong = false;
+ this.isUnsigned = false;
+ this.i = 0;
+ this.isDouble = isDouble;
+ this.f = value;
+ }
+ @Override
+ public int hashCode() {
+ return isInteger ? Long.valueOf(i).hashCode() : Double.valueOf(f).hashCode();
+ }
+ @Override
+ public boolean equals(final Object arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof CNumber) ) {
+ return false;
+ }
+ final CNumber t = (CNumber) arg;
+ return isInteger == t.isInteger &&
+ ( isInteger ? i == t.i : f == t.f );
+ }
+ public final String toJavaString() {
+ if( isInteger ) {
+ if( i >= 0 || isUnsigned ) {
+ if( isLong ) {
+ return "0x"+Long.toHexString(i)+"L";
+ } else {
+ return "0x"+Integer.toHexString((int)i);
+ }
+ } else {
+ if( isLong ) {
+ return String.valueOf(i)+"L";
+ } else {
+ return String.valueOf((int)i);
+ }
+ }
+ } else {
+ return String.valueOf(f) + ( !isDouble ? "f" : "");
+ }
+ }
+ public final String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ if( isInteger ) {
+ if( isUnsigned ) {
+ sb.append("unsigned ");
+ }
+ if( isLong) {
+ sb.append("long: ");
+ } else {
+ sb.append("int: ");
+ }
+ sb.append(i);
+ } else {
+ if( isDouble ) {
+ sb.append("double: ");
+ } else {
+ sb.append("float: ");
+ }
+ sb.append(f);
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+ /**
+ * A valid java expression, including its result type,
+ * usually generated from a native [C] expression,
+ * see {@link JavaExpr#create(ConstantDefinition)}.
+ */
+ public static class JavaExpr {
+ public final String javaExpression;
+ public final CNumber resultType;
+ public final Number resultJavaType;
+ public final String resultJavaTypeName;
+ public JavaExpr(final String javaExpression, final CNumber resultType) {
+ this.javaExpression = javaExpression;
+ this.resultType = resultType;
+ if( resultType.isDouble ) {
+ resultJavaTypeName = "double";
+ resultJavaType = Double.valueOf(resultType.f);
+ } else if( !resultType.isInteger ) {
+ resultJavaTypeName = "float";
+ resultJavaType = Double.valueOf(resultType.f).floatValue();
+ } else if( resultType.isLong ) {
+ resultJavaTypeName = "long";
+ resultJavaType = Long.valueOf(resultType.i);
+ } else /* if( resultType.isInteger ) */ {
+ resultJavaTypeName = "int";
+ resultJavaType = Long.valueOf(resultType.i).intValue();
+ }
+ }
+ /**
+ * Computes a valid {@link JavaExpr java expression} based on the given {@link ConstantDefinition},
+ * which may either be a single {@link CNumber}, see {@link ConstantDefinition#getNumber()},
+ * or represents a native expression, see {@link ConstantDefinition#getExpr()}.
+ */
+ public static JavaExpr compute(final ConstantDefinition constDef,
+ final Map<String, ConstantDefinition.JavaExpr> constMap) {
+ final boolean debug = GlueGen.debug();
+ if( debug ) {
+ System.err.println("ConstJavaExpr.create: "+constDef);
+ }
+ if( constDef.hasNumber() ) {
+ // Already parsed as CNumber completely!
+ if( debug ) {
+ System.err.printf("V %s (isCNumber)%n", constDef);
+ }
+ return new JavaExpr(constDef.getNumber().toJavaString(), constDef.getNumber());
+ }
+ final StringBuilder javaExpr = new StringBuilder();
+ final String nativeExpr = constDef.getNativeExpr();
+
+ // "calculates" the result type of a simple expression
+ // example: (2+3)-(2.0f-3.0) -> Double
+ // example: (1 << 2) -> Integer
+ CNumber resultType = null;
+ final Matcher matcher = patternCPPOperand.matcher(nativeExpr);
+ int preStartIdx = 0;
+ int opEndIdx = 0;
+ while ( matcher.find() ) {
+ final int opStartIdx = matcher.start();
+ if( opStartIdx > preStartIdx ) {
+ final String sValue = nativeExpr.substring(preStartIdx, opStartIdx).trim();
+ if( sValue.length() > 0 ) {
+ if( debug ) {
+ System.err.printf("V %03d-%03d: %s%n", preStartIdx, opStartIdx, sValue);
+ }
+ resultType = processValue(constDef, sValue, constMap, resultType, javaExpr);
+ javaExpr.append(" ");
+ }
+ }
+ opEndIdx = matcher.end();
+ final String op = nativeExpr.substring(opStartIdx, opEndIdx);
+ if( debug ) {
+ System.err.printf("O %03d-%03d: %s%n", opStartIdx, opEndIdx, op);
+ }
+ javaExpr.append(op).append(" ");
+ preStartIdx = opEndIdx;
+ }
+ if( opEndIdx < nativeExpr.length() ) {
+ // tail ..
+ final String sValue = nativeExpr.substring(opEndIdx).trim();
+ if( sValue.length() > 0 ) {
+ if( debug ) {
+ System.err.printf("V %03d %03d-%03d: %s (tail)%n", preStartIdx, opEndIdx, nativeExpr.length(), sValue);
+ }
+ resultType = processValue(constDef, sValue, constMap, resultType, javaExpr);
+ }
+ }
+ final String javaExprS = javaExpr.toString().trim();
+ if( null == resultType ) {
+ throw new GlueGenException("Cannot emit const \""+constDef.getName()+"\": value \""+nativeExpr+
+ "\", parsed \""+javaExprS+"\" does not contain a constant number", constDef.getASTLocusTag());
+ }
+ return new JavaExpr(javaExprS, resultType);
+ }
+ private static CNumber processValue(final ConstantDefinition constDef,
+ final String sValue,
+ final Map<String, ConstantDefinition.JavaExpr> constMap,
+ CNumber resultType,
+ final StringBuilder javaExpr) {
+ final CNumber nValue = getANumber(constDef, sValue);
+ if( null != nValue ) {
+ resultType = evalType(resultType , nValue);
+ javaExpr.append(nValue.toJavaString());
+ } else {
+ // Lookup CNumber type in const-map, to evaluate this result type
+ final JavaExpr cje = constMap.get(sValue);
+ if( null != cje ) {
+ resultType = evalType(resultType , cje.resultType);
+ }
+ javaExpr.append(sValue);
+ }
+ return resultType;
+ }
+ private static CNumber getANumber(final ConstantDefinition constDef, final String value) {
+ try {
+ final CNumber number = decodeANumber(value);
+ if( null != number ) {
+ return number;
+ }
+ } catch( final Throwable _t ) {
+ final String msg = "Cannot emit const \""+constDef.getName()+"\": value \""+value+
+ "\" cannot be assigned to a int, long, float, or double";
+ throw new GlueGenException(msg, constDef.getASTLocusTag(), _t);
+ }
+ return null;
+ }
+ private static CNumber evalType(final CNumber resultType, final CNumber type) {
+ //fast path
+ if( type.isDouble ) {
+ return type;
+ }
+ if( null != resultType ) {
+ if( resultType.isInteger ) {
+ if( resultType.isLong ) {
+ /* resultType is Long */
+ if( !type.isInteger ) {
+ /* resultType: Long -> [ Float || Double ] */
+ return type;
+ }
+ } else if( type.isLong || !type.isInteger ) {
+ /* resultType: Integer -> [ Long || Float || Double ] */
+ return type;
+ }
+ } else if( !resultType.isInteger && !resultType.isDouble ) {
+ if( type.isDouble ) {
+ /* resultType: Float -> Double */
+ return type;
+ }
+ }
+ } else {
+ return type;
+ }
+ return resultType;
+ }
+ }
+
private final boolean relaxedEqSem;
- private final String sValue;
- private final long iValue;
- private final boolean hasIntValue;
+ private final String nativeExpr;
+ private final CNumber number;
private final boolean isEnum;
private final String enumName;
private final ASTLocusTag astLocus;
- /** Covering enums */
+ /**
+ * Constructor for plain const-values, non-enumerates.
+ * @param name unique name of this constant expression
+ * @param nativeExpr original [native] expression
+ * @param number optional {@link CNumber} representing this constant.
+ * If {@code null}, implementation attempts to derive a {@link CNumber}
+ * of the given {@code nativeExpr}.
+ * @param astLocus AST location of the represented constant.
+ */
public ConstantDefinition(final String name,
- final long value,
- final String enumName,
+ final String nativeExpr,
+ final CNumber number,
final ASTLocusTag astLocus) {
- super(name);
- this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
- this.sValue = String.valueOf(value);
- this.iValue = value;
- this.hasIntValue = true;
- this.isEnum = true;
- this.enumName = enumName;
- this.astLocus = astLocus;
+ this(name, nativeExpr, number, false, null, astLocus);
}
-
- /** Covering defines */
+ /**
+ * Constructor for enumerates
+ * @param name unique name of this constant expression
+ * @param nativeExpr original [native] expression
+ * @param number optional {@link CNumber} representing this constant.
+ * If {@code null}, implementation attempts to derive a {@link CNumber}
+ * of the given {@code nativeExpr}.
+ * @param enumName optional name of the represented enumeration
+ * @param astLocus AST location of the represented constant.
+ */
public ConstantDefinition(final String name,
- final String value,
- final ASTLocusTag astLocus) {
+ final String nativeExpr,
+ final CNumber number,
+ final String enumName, final ASTLocusTag astLocus) {
+ this(name, nativeExpr, number, true, enumName, astLocus);
+ }
+ /**
+ * @param name unique name of this constant expression
+ * @param nativeExpr original [native] expression
+ * @param number optional {@link CNumber} representing this constant.
+ * If {@code null}, implementation attempts to derive a {@link CNumber}
+ * of the given {@code nativeExpr}.
+ * @param isEnum {@code true} if this constant is an enumerate, otherwise {@code false}.
+ * @param enumName optional name of the represented enumeration
+ * @param astLocus AST location of the represented constant.
+ */
+ private ConstantDefinition(final String name,
+ final String nativeExpr,
+ final CNumber number,
+ final boolean isEnum, final String enumName, final ASTLocusTag astLocus) {
super(name);
+ this.nativeExpr = nativeExpr;
this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
- this.sValue = value;
- {
+ if( null != number ) {
+ this.number = number;
+ } else {
// Attempt to parse define string as number
- long v;
- boolean b;
- try {
- v = Long.decode(value).longValue();
- b = true;
- } catch (final NumberFormatException e) {
- v = 0;
- b = false;
+ final CNumber iNum = decodeIntegerNumber(nativeExpr);
+ if( null != iNum ) {
+ this.number = iNum;
+ } else {
+ final CNumber fNum = decodeDecimalNumber(nativeExpr);
+ if( null != fNum ) {
+ this.number = fNum;
+ } else {
+ this.number = null;
+ }
}
- this.iValue = v;
- this.hasIntValue = b;
}
- this.isEnum = false;
- this.enumName = null;
+ this.isEnum = isEnum;
+ this.enumName = enumName;
this.astLocus = astLocus;
}
@@ -122,8 +415,10 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema
public final int hashCodeSemantics() {
// 31 * x == (x << 5) - x
int hash = 31 + ( null != getName() ? getName().hashCode() : 0 );
- hash = ((hash << 5) - hash) + ( null != sValue ? sValue.hashCode() : 0 );
- return ((hash << 5) - hash) + ( null != enumName ? enumName.hashCode() : 0 );
+ hash = ((hash << 5) - hash) + ( isEnum ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( null != enumName ? enumName.hashCode() : 0 );
+ hash = ((hash << 5) - hash) + ( null != number ? number.hashCode() : 0 );
+ return ((hash << 5) - hash) + ( !relaxedEqSem && null != nativeExpr ? nativeExpr.hashCode() : 0 );
}
@Override
@@ -135,30 +430,49 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema
} else {
final ConstantDefinition t = (ConstantDefinition) arg;
if( !equals(getName(), t.getName()) ||
+ isEnum != t.isEnum ||
!equals(enumName, t.enumName) ) {
return false;
}
- if( hasIntValue ) {
- return iValue == t.iValue;
+ if( null != number ) {
+ if( number.isInteger ) {
+ return number.i == t.number.i;
+ } else {
+ return number.f == t.number.f;
+ }
} else {
// define's string value may be semantical equal .. but formatted differently!
- return relaxedEqSem || equals(sValue, t.sValue);
+ return relaxedEqSem || equals(nativeExpr, t.nativeExpr);
}
}
}
- public String getValue() { return sValue; }
- /** Returns null if this definition was not part of an
- enumeration, or if the enum was anonymous. */
+ /** Returns the original [native] expression. */
+ public String getNativeExpr() { return nativeExpr; }
+ /**
+ * Returns the parsed {@link CNumber} of the {@link #getNativeExpr() native expression},
+ * or {@code null} if the latter does not comprise a single number,
+ * i.e. is a complex expression.
+ */
+ public CNumber getNumber() { return number; }
+ /**
+ * Returns {@code true} if this instance represents has a {@link #getNumber() number},
+ * otherwise {@code false}.
+ */
+ public boolean hasNumber() { return null != number; }
+
+ /** Returns {@code null} if this definition was not part of an
+ enumeration, or if the enumeration is anonymous. */
public String getEnumName() { return enumName; }
public boolean isEnum() { return isEnum; }
@Override
public String toString() {
- return "ConstantDefinition [name " + getName()
- + ", value " + sValue + " (isInt " + hasIntValue
- + "), enumName " + enumName + ", isEnum " + isEnum + "]";
+ return "ConstantDefinition [name \"" + getName()
+ + "\", expression \"" + nativeExpr
+ + "\", number "+number
+ + "], enum[is " + isEnum + ", name \"" + enumName + "\"]]";
}
private static boolean equals(final String s1, final String s2) {
@@ -172,6 +486,18 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema
return s1.equals(s2);
}
+ /**
+ * Computes the {@link JavaExpr java expression} based on this instance,
+ * see {@link JavaExpr#create(ConstantDefinition)}.
+ */
+ public final JavaExpr computeJavaExpr(final Map<String, ConstantDefinition.JavaExpr> constMap) {
+ return JavaExpr.compute(this, constMap);
+ }
+
+ //
+ // Static utility functions for type detection
+ //
+
public static boolean isConstantExpression(final String value) {
if( null != value && value.length() > 0 ) {
// Single numeric value
@@ -222,32 +548,260 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema
return identifier;
}
+ /**
+ * Returns either {@link #decodeIntegerNumber(String)},
+ * {@link #decodeDecimalNumber(String)} or {@code null}.
+ * @param v
+ */
+ public static CNumber decodeANumber(final String v) {
+ final CNumber iNumber = ConstantDefinition.decodeIntegerNumber(v);
+ if( null != iNumber ) {
+ return iNumber;
+ }
+ return ConstantDefinition.decodeDecimalNumber(v);
+ }
+
+ /**
+ * If the given string {@link #isIntegerNumber(String)},
+ * return the decoded integer value, represented as a {@code ANumber},
+ * otherwise returns {@code null}.
+ * <p>
+ * Method strips off sign prefix {@code +}
+ * and integer modifier suffixes {@code [uUlL]}
+ * before utilizing {@link Long#decode(String)}.
+ * </p>
+ * @param v
+ */
+ public static CNumber decodeIntegerNumber(final String v) {
+ if( null == v || !isIntegerNumber(v) ) {
+ return null;
+ }
+ String s0 = v.trim();
+ if( 0 == s0.length() ) {
+ return null;
+ }
+ if (s0.startsWith("+")) {
+ s0 = s0.substring(1, s0.length()).trim();
+ if( 0 == s0.length() ) {
+ return null;
+ }
+ }
+ final boolean neg;
+ if (s0.startsWith("-")) {
+ s0 = s0.substring(1, s0.length()).trim();
+ if( 0 == s0.length() ) {
+ return null;
+ }
+ neg = true;
+ } else {
+ neg = false;
+ }
+
+ // Test last two chars for [lL] and [uU] modifiers!
+ boolean isUnsigned = false;
+ boolean isLong = false;
+ final int j = s0.length() - 2;
+ for(int i = s0.length() - 1; i >= 0 && i >= j; i--) {
+ final char lastChar = s0.charAt(s0.length()-1);
+ if( lastChar == 'u' || lastChar == 'U' ) {
+ s0 = s0.substring(0, s0.length()-1);
+ isUnsigned = true;
+ } else if( lastChar == 'l' || lastChar == 'L' ) {
+ s0 = s0.substring(0, s0.length()-1);
+ isLong = true;
+ } else {
+ // early out, no modifier match!
+ break;
+ }
+ }
+ if( 0 == s0.length() ) {
+ return null;
+ }
+ final long res;
+ if( isLong && isUnsigned ) {
+ res = decodeULong(s0, neg);
+ } else {
+ if( neg ) {
+ s0 = "-" + s0;
+ }
+ res = Long.decode(s0).longValue();
+ }
+ final boolean isLong2 = isLong ||
+ ( !isUnsigned && ( Integer.MIN_VALUE > res || res > Integer.MAX_VALUE ) ) ||
+ ( isUnsigned && res > UNSIGNED_INT_MAX_VALUE );
+ return new CNumber(isLong2, isUnsigned, res);
+ }
+ private static long decodeULong(final String v, final boolean neg) throws NumberFormatException {
+ final int radix;
+ final int idx;
+ if (v.startsWith("0x") || v.startsWith("0X")) {
+ idx = 2;
+ radix = 16;
+ } else if (v.startsWith("#")) {
+ idx = 1;
+ radix = 16;
+ } else if (v.startsWith("0") && v.length() > 1) {
+ idx = 1;
+ radix = 8;
+ } else {
+ idx = 0;
+ radix = 10;
+ }
+ final String s0 = ( neg ? "-" : "" ) + v.substring(idx);
+ final BigInteger res = new BigInteger(s0, radix);
+ if( res.compareTo(UNSIGNED_LONG_MAX_VALUE) > 0 ) {
+ throw new NumberFormatException("Value \""+v+"\" is > UNSIGNED_LONG_MAX");
+ }
+ return res.longValue();
+ }
+
+ /**
+ * If the given string {@link #isDecimalNumber(String)},
+ * return the decoded floating-point value, represented as a {@code ANumber} object,
+ * otherwise returns {@code null}.
+ * <p>
+ * Method utilizes {@link Double#valueOf(String)}.
+ * </p>
+ * @param v
+ * @param isDouble return value for {@code double} flag
+ */
+ public static CNumber decodeDecimalNumber(final String v) {
+ if( null == v || !isDecimalNumber(v) ) {
+ return null;
+ }
+ final String s0 = v.trim();
+ if( 0 == s0.length() ) {
+ return null;
+ }
+ boolean _isDouble = false;
+ final char lastChar = s0.charAt(s0.length()-1);
+ if( lastChar == 'd' || lastChar == 'D' ) {
+ _isDouble = true;
+ }
+ final double res = Double.valueOf(s0).doubleValue();
+ final double ares = Math.abs(res);
+ return new CNumber(_isDouble || Float.MIN_VALUE > ares || ares > Float.MAX_VALUE, res);
+ }
+
+ /**
+ * Matches {@link #isHexNumber(String)} or {@link #isDecimalOrIntNumber(String)}.
+ */
public static boolean isNumber(final String s) {
if( isHexNumber(s) ) {
return true;
} else {
- return isDecimalNumber(s);
+ return isDecimalOrIntNumber(s);
+ }
+ }
+
+ /**
+ * Matches {@link #isHexNumber(String)} or {@link #patternIntegerNumber}.
+ */
+ public static boolean isIntegerNumber(final String s) {
+ if( isHexNumber(s) ) {
+ return true;
+ } else {
+ return patternIntegerNumber.matcher(s).matches();
}
}
+
+ /**
+ * Matches {@link #patternHexNumber}.
+ */
public static boolean isHexNumber(final String s) {
return patternHexNumber.matcher(s).matches();
}
- public static Pattern patternHexNumber = Pattern.compile("0[xX][0-9a-fA-F]+[lLfFuU]?");
+
+ /**
+ * Matches pattern for <code>floating point</code> number,
+ * compatible and described in {@link Double#valueOf(String)}.
+ */
+ public static boolean isDecimalNumber(final String s) {
+ return patternDecimalNumber.matcher(s).matches();
+ }
+
+ /**
+ * Complete pattern for <code>floating point</code> <i>and</i> <code>integer</code> number,
+ * covering {@link #patternDecimalNumber} <i>and</i> {@link #patternIntegerNumber}.
+ */
+ public static boolean isDecimalOrIntNumber(final String s) {
+ return patternDecimalOrIntNumber.matcher(s).matches();
+ }
+
+ /**
+ * Matches pattern for valid CPP operands, see {@link #patternCPPOperand}.
+ */
+ public static boolean isCPPOperand(final String s) {
+ return patternCPPOperand.matcher(s).matches();
+ }
+
+ /**
+ * Complete pattern for <code>hexadecimal</code> number,
+ * including an optional sign {@code [+-]} and optional suffixes {@code [uUlL]}.
+ */
+ public static Pattern patternHexNumber;
/**
* Complete pattern for <code>floating point</code> number,
* compatible and described in {@link Double#valueOf(String)}.
*/
- public static Pattern patternDecimalNumber;
- private static String fpRegex;
+ public final static Pattern patternDecimalNumber;
+
+ /**
+ * Complete pattern for <code>floating point</code> <i>and</i> <code>integer</code> number,
+ * covering {@link #patternDecimalNumber} <i>and</i> {@link #patternIntegerNumber}.
+ */
+ public final static Pattern patternDecimalOrIntNumber;
+
+ /**
+ * Complete pattern for <code>integer</code> number,
+ * including an optional sign {@code [+-]} and optional suffixes {@code [uUlL]}.
+ */
+ public final static Pattern patternIntegerNumber;
+
+ /**
+ * One of: {@code +} {@code -} {@code *} {@code /} {@code |} {@code &} {@code (} {@code )} {@code <<} {@code >>}
+ * <p>
+ * Expression excludes {@link #patternDecimalOrIntNumber}.
+ * </p>
+ */
+ public static Pattern patternCPPOperand;
+
static {
+ final String WhiteSpace = "[\\x00-\\x20]*";
final String Digits = "(\\p{Digit}+)";
final String HexDigits = "(\\p{XDigit}+)";
+ final String IntTypeSuffix =
+ "(" +
+ "[uU]|" +
+ "([uU][lL])|" +
+ "[lL]|" +
+ "([lL][uU])" +
+ ")";
+
+ final String hexRegex =
+ WhiteSpace + // Optional leading "whitespace"
+ "[+-]?" + // Optional sign character
+ // HexDigits IntTypeSuffix_opt
+ "0[xX]" + HexDigits + IntTypeSuffix + "?" +
+ WhiteSpace // Optional trailing "whitespace"
+ ;
+ patternHexNumber = Pattern.compile(hexRegex);
+
+ final String intRegex =
+ WhiteSpace + // Optional leading "whitespace"
+ "[+-]?" + // Optional sign character
+ // Digits IntTypeSuffix_opt
+ Digits + IntTypeSuffix + "?" +
+ WhiteSpace // Optional trailing "whitespace"
+ ;
+ patternIntegerNumber = Pattern.compile(intRegex);
+
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
final String Exp = "[eE][+-]?"+Digits;
- fpRegex =
- ("[\\x00-\\x20]*"+ // Optional leading "whitespace"
+ final String fpRegex =
+ WhiteSpace + // Optional leading "whitespace"
"[+-]?" + // Optional sign character
"("+
"NaN|" + // "NaN" string
@@ -289,23 +843,112 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema
"[fFdD]?"+
")"+
")" +
- "[\\x00-\\x20]*"// Optional trailing "whitespace"
- );
+ WhiteSpace // Optional trailing "whitespace"
+ ;
patternDecimalNumber = Pattern.compile(fpRegex);
- }
- public static boolean isDecimalNumber(final String s) {
- return patternDecimalNumber.matcher(s).matches();
- }
- public static boolean isCPPOperand(final String s) {
- return patternCPPOperand.matcher(s).matches();
- }
- /**
- * One of: {@code +} {@code -} {@code *} {@code /} {@code |} {@code &} {@code (} {@code )} {@code <<} {@code >>}
- * <p>
- * Expression excludes {@link #patternDecimalNumber}.
- * </p>
- */
- public static Pattern patternCPPOperand = Pattern.compile("(?!"+fpRegex+")[\\+\\-\\*\\/\\|\\&\\(\\)]|(\\<\\<)|(\\>\\>)");
+ final String fpOrIntRegex =
+ WhiteSpace + // Optional leading "whitespace"
+ "[+-]?" + // Optional sign character
+ "("+
+ "NaN|" + // "NaN" string
+ "Infinity|" + // "Infinity" string
+
+ // Matching integers w/ IntTypeSuffix,
+ // which are otherwise not matched by the below floating point matcher!
+ // Digits IntTypeSuffix
+ "(" + Digits + IntTypeSuffix +")|" +
+
+ // A decimal floating-point string representing a finite positive
+ // number without a leading sign has at most five basic pieces:
+ // Digits . Digits ExponentPart FloatTypeSuffix
+ //
+ // Since this method allows integer-only strings as input
+ // in addition to strings of floating-point literals, the
+ // two sub-patterns below are simplifications of the grammar
+ // productions from the Java Language Specification, 2nd
+ // edition, section 3.10.2.
+
+ "("+
+ "("+
+ // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
+ "(" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|" +
+ // . Digits ExponentPart_opt FloatTypeSuffix_opt
+ "(\\.(" + Digits + ")(" + Exp + ")?)|" +
+
+ // Hexadecimal w/ binary exponent
+ "(" +
+ "(" +
+ // Hexadecimal strings
+ // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
+ "(0[xX]" + HexDigits + "(\\.)?)|" +
+
+ // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
+ "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
+ ")" +
+
+ // binary exponent
+ "[pP][+-]?" + Digits +
+ ")" +
+ ")" +
+ "[fFdD]?"+
+ ")"+
+ ")" +
+ WhiteSpace // Optional trailing "whitespace"
+ ;
+ patternDecimalOrIntNumber = Pattern.compile(fpOrIntRegex);
+
+ final String fpOrIntRegex2 =
+ WhiteSpace + // Optional leading "whitespace"
+ // "[+-]?" + // Optional sign character
+ "("+
+ "NaN|" + // "NaN" string
+ "Infinity|" + // "Infinity" string
+
+ // Matching integers w/ IntTypeSuffix,
+ // which are otherwise not matched by the below floating point matcher!
+ // Digits IntTypeSuffix
+ "(" + Digits + IntTypeSuffix +")|" +
+
+ // A decimal floating-point string representing a finite positive
+ // number without a leading sign has at most five basic pieces:
+ // Digits . Digits ExponentPart FloatTypeSuffix
+ //
+ // Since this method allows integer-only strings as input
+ // in addition to strings of floating-point literals, the
+ // two sub-patterns below are simplifications of the grammar
+ // productions from the Java Language Specification, 2nd
+ // edition, section 3.10.2.
+
+ "("+
+ "("+
+ // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
+ "(" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|" +
+
+ // . Digits ExponentPart_opt FloatTypeSuffix_opt
+ "(\\.(" + Digits + ")(" + Exp + ")?)|" +
+
+ // Hexadecimal w/ binary exponent
+ "(" +
+ "(" +
+ // Hexadecimal strings
+ // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
+ "(0[xX]" + HexDigits + "(\\.)?)|" +
+
+ // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
+ "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
+ ")" +
+
+ // binary exponent
+ "[pP][+-]?" + Digits +
+ ")" +
+ ")" +
+ "[fFdD]?"+
+ ")"+
+ ")" +
+ WhiteSpace // Optional trailing "whitespace"
+ ;
+ patternCPPOperand = Pattern.compile("(?!"+fpOrIntRegex2+")[\\+\\-\\*\\/\\|\\&\\(\\)]|(\\<\\<)|(\\>\\>)");
+ }
}
diff --git a/src/java/com/jogamp/gluegen/DebugEmitter.java b/src/java/com/jogamp/gluegen/DebugEmitter.java
index 582a1d7..046c2b6 100644
--- a/src/java/com/jogamp/gluegen/DebugEmitter.java
+++ b/src/java/com/jogamp/gluegen/DebugEmitter.java
@@ -74,7 +74,7 @@ public class DebugEmitter implements GlueEmitter {
@Override
public void emitDefine(final ConstantDefinition def, final String optionalComment) {
final String name = def.getName();
- final String value = def.getValue();
+ final String value = def.getNativeExpr();
System.out.println("#define " + name + " " + value +
(optionalComment != null ? ("// " + optionalComment) : ""));
}
diff --git a/src/java/com/jogamp/gluegen/GlueGen.java b/src/java/com/jogamp/gluegen/GlueGen.java
index d0ce9ed..6dee6f0 100644
--- a/src/java/com/jogamp/gluegen/GlueGen.java
+++ b/src/java/com/jogamp/gluegen/GlueGen.java
@@ -217,14 +217,17 @@ public class GlueGen implements GlueEmitterControls {
}
// iterate over all values in the enumeration
for (int i = 0; i < enumeration.getNumEnumerates(); ++i) {
- final String enumElementName = enumeration.getEnumName(i);
- allConstants.add(new ConstantDefinition(enumElementName, enumeration.getEnumValue(i),
- enumName, enumeration.getASTLocusTag()));
+ final EnumType.Enumerator enumerate = enumeration.getEnum(i);
+ final ConstantDefinition def =
+ new ConstantDefinition(enumerate.getName(), enumerate.getExpr(),
+ enumerate.getNumber(),
+ enumName, enumeration.getASTLocusTag());
+ allConstants.add(def);
}
}
for (final Object elem : lexer.getDefines()) {
final Define def = (Define) elem;
- allConstants.add(new ConstantDefinition(def.getName(), def.getValue(), def.getASTLocusTag()));
+ allConstants.add(new ConstantDefinition(def.getName(), def.getValue(), null, def.getASTLocusTag()));
}
allConstants.addAll(preprocessor.getConstantDefinitions());
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index 15dc401..60cd3f4 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -40,24 +40,56 @@
package com.jogamp.gluegen;
+import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PACKAGE_PRIVATE;
+import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PRIVATE;
+import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PROTECTED;
+import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PUBLIC;
+import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PUBLIC_ABSTRACT;
+import static java.util.logging.Level.FINE;
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.Buffer;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jogamp.common.os.MachineDataInfoRuntime;
+
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.common.os.MachineDataInfo;
-
-import java.io.*;
-import java.util.*;
-import java.text.MessageFormat;
-
+import com.jogamp.common.util.ArrayHashMap;
import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
import com.jogamp.gluegen.Logging.LoggerIf;
-import com.jogamp.gluegen.cgram.types.*;
+import com.jogamp.gluegen.cgram.types.AliasedSymbol;
+import com.jogamp.gluegen.cgram.types.ArrayType;
+import com.jogamp.gluegen.cgram.types.CVAttributes;
+import com.jogamp.gluegen.cgram.types.CompoundType;
+import com.jogamp.gluegen.cgram.types.Field;
+import com.jogamp.gluegen.cgram.types.FunctionSymbol;
+import com.jogamp.gluegen.cgram.types.FunctionType;
+import com.jogamp.gluegen.cgram.types.IntType;
+import com.jogamp.gluegen.cgram.types.PointerType;
+import com.jogamp.gluegen.cgram.types.SizeThunk;
+import com.jogamp.gluegen.cgram.types.StructLayout;
+import com.jogamp.gluegen.cgram.types.Type;
import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
-
-import java.nio.Buffer;
-
-import jogamp.common.os.MachineDataInfoRuntime;
-import static java.util.logging.Level.*;
-import static com.jogamp.gluegen.JavaEmitter.MethodAccess.*;
+import com.jogamp.gluegen.cgram.types.TypeDictionary;
// PROBLEMS:
// - what if something returns 'const int *'? Could we
@@ -134,9 +166,12 @@ public class JavaEmitter implements GlueEmitter {
return functions;
}
- private <T extends AliasedSemanticSymbol> List<T> filterSymbolsInt(final List<T> inList, final List<T> outList) {
+ private <T extends AliasedSemanticSymbol> List<T> filterSymbolsInt(final List<T> inList,
+ final boolean preserveOrder,
+ final List<T> outList) {
final JavaConfiguration cfg = getConfig();
- final HashMap<String, T> symMap = new HashMap<String, T>(100);
+ final ArrayHashMap<String, T> symMap =
+ new ArrayHashMap<String, T>(false, 100, ArrayHashMap.DEFAULT_LOAD_FACTOR);
for (final T sym : inList) {
final String origName = sym.getName();
final String newName = cfg.getJavaSymbolRename(origName);
@@ -195,21 +230,23 @@ public class JavaEmitter implements GlueEmitter {
}
}
}
- outList.addAll(symMap.values());
- // sort constants to make them easier to find in native code
- Collections.sort(outList, new Comparator<T>() {
- @Override
- public int compare(final T o1, final T o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
+ outList.addAll(symMap.getData());
+ if( !preserveOrder ) {
+ // sort constants to make them easier to find in native code
+ Collections.sort(outList, new Comparator<T>() {
+ @Override
+ public int compare(final T o1, final T o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ }
return outList;
}
@Override
public void filterSymbols(final List<ConstantDefinition> inConstList, final List<FunctionSymbol> inFuncList) {
- constants = filterSymbolsInt(inConstList, new ArrayList<ConstantDefinition>(100));
- functions = filterSymbolsInt(inFuncList, new ArrayList<FunctionSymbol>(100));
+ constants = filterSymbolsInt(inConstList, true, new ArrayList<ConstantDefinition>(100));
+ functions = filterSymbolsInt(inFuncList, true, new ArrayList<FunctionSymbol>(100));
}
}
@@ -253,171 +290,6 @@ public class JavaEmitter implements GlueEmitter {
}
}
- protected static int getJavaRadix(final String name, final String value) {
- // FIXME: need to handle when type specifier is in last char (e.g.,
- // "1.0d or 2759L", because parseXXX() methods don't allow the type
- // specifier character in the string.
- //
- //char lastChar = value.charAt(value.length()-1);
-
- try {
- // see if it's a long or int
- int radix;
- String parseValue;
- // FIXME: are you allowed to specify hex/octal constants with
- // negation, e.g. "-0xFF" or "-056"? If so, need to modify the
- // following "if(..)" checks and parseValue computation
- if (value.startsWith("0x") || value.startsWith("0X")) {
- radix = 16;
- parseValue = value.substring(2);
- }
- else if (value.startsWith("0") && value.length() > 1) {
- // TODO: is "0" the prefix in C to indicate octal???
- radix = 8;
- parseValue = value.substring(1);
- }
- else {
- radix = 10;
- parseValue = value;
- }
- //System.err.println("parsing " + value + " as long w/ radix " + radix);
- Long.parseLong(parseValue, radix);
- return radix;
- } catch (final NumberFormatException e) {
- try {
- // see if it's a double or float
- Double.parseDouble(value);
- return 10;
- } catch (final NumberFormatException e2) {
- throw new RuntimeException(
- "Cannot emit define \""+name+"\": value \""+value+
- "\" cannot be assigned to a int, long, float, or double", e2);
- }
- }
- }
-
- protected static Object getJavaValue(final String name, final String value) {
-
- // "calculates" the result type of a simple expression
- // example: (2+3)-(2.0f-3.0) -> Double
- // example: (1 << 2) -> Integer
- final Scanner scanner = new Scanner(value).useDelimiter(ConstantDefinition.patternCPPOperand);
-
- Object resultType = null;
-
- while (scanner.hasNext()) {
-
- final String t = scanner.next().trim();
-
- if(0<t.length()) {
- final Object type = getJavaValue2(name, t);
-
- //fast path
- if(type instanceof Double)
- return type;
-
- if(resultType != null) {
-
- if(resultType instanceof Integer) {
- if(type instanceof Long || type instanceof Float || type instanceof Double)
- resultType = type;
- }else if(resultType instanceof Long) {
- if(type instanceof Float || type instanceof Double)
- resultType = type;
- }else if(resultType instanceof Float) {
- if(type instanceof Float)
- resultType = type;
- }
- }else{
- resultType = type;
- }
-
- //fast path
- if(resultType instanceof Double)
- return type;
- }
- }
-
- return resultType;
- }
-
- private static Object getJavaValue2(final String name, final String value) {
- // FIXME: need to handle when type specifier is in last char (e.g.,
- // "1.0d or 2759L", because parseXXX() methods don't allow the type
- // specifier character in the string.
- //
- final char lastChar = value.charAt(value.length()-1);
-
- try {
- // see if it's a long or int
- int radix;
- String parseValue;
- // FIXME: are you allowed to specify hex/octal constants with
- // negation, e.g. "-0xFF" or "-056"? If so, need to modify the
- // following "if(..)" checks and parseValue computation
- if (value.startsWith("0x") || value.startsWith("0X")) {
- radix = 16;
- parseValue = value.substring(2);
- } else if (value.startsWith("0") && value.length() > 1) {
- // TODO: is "0" the prefix in C to indicate octal???
- radix = 8;
- parseValue = value.substring(1);
- } else {
- radix = 10;
- parseValue = value;
- }
- if(lastChar == 'u' || lastChar == 'U') {
- parseValue = parseValue.substring(0, parseValue.length()-1);
- }
-
- //System.err.println("parsing " + value + " as long w/ radix " + radix);
- final long longVal = Long.parseLong(parseValue, radix);
- // if constant is small enough, store it as an int instead of a long
- if (longVal > Integer.MIN_VALUE && longVal < Integer.MAX_VALUE) {
- return (int)longVal;
- }
- return longVal;
-
- } catch (final NumberFormatException e) {
- try {
- // see if it's a double or float
- final double dVal = Double.parseDouble(value);
- final double absVal = Math.abs(dVal);
- // if constant is small enough, store it as a float instead of a double
- if (absVal < Float.MIN_VALUE || absVal > Float.MAX_VALUE || lastChar == 'd' || lastChar == 'D' ) {
- return new Double(dVal);
- }
- return new Float((float) dVal);
- } catch (final NumberFormatException e2) {
- throw new RuntimeException(
- "Cannot emit define \""+name+"\": value \""+value+
- "\" cannot be assigned to a int, long, float, or double", e2);
- }
- }
- }
-
-
- protected static String getJavaType(final String name, final String value) {
- final Object oval = getJavaValue(name, value);
- return getJavaType(name, oval);
- }
-
- protected static String getJavaType(final String name, final Object oval) {
- if(oval instanceof Integer) {
- return "int";
- } else if(oval instanceof Long) {
- return "long";
- } else if(oval instanceof Float) {
- return "float";
- } else if(oval instanceof Double) {
- return "double";
- }
-
- throw new RuntimeException(
- "Cannot emit define (2) \""+name+"\": value \""+oval+
- "\" cannot be assigned to a int, long, float, or double");
- }
-
/** Mangle a class, package or function name for JNI usage, i.e. replace all '.' w/ '_' */
protected static String jniMangle(final String name) {
return name.replaceAll("_", "_1").replace('.', '_');
@@ -427,6 +299,9 @@ public class JavaEmitter implements GlueEmitter {
return "Java_"+jniMangle(javaPackageName)+"_"+jniMangle(javaClassName);
}
+ private final Map<String, ConstantDefinition.JavaExpr> constMap =
+ new HashMap<String, ConstantDefinition.JavaExpr>();
+
@Override
public void emitDefine(final ConstantDefinition def, final String optionalComment) throws Exception {
if ( ( cfg.allStatic() || cfg.emitInterface() ) && !cfg.structsOnly() ) {
@@ -439,24 +314,22 @@ public class JavaEmitter implements GlueEmitter {
// currently only emits only numeric defines -- if it handled #define'd
// objects it would make a bigger difference.
- final String name = def.getName();
- String value = def.getValue();
-
if ( !cfg.shouldIgnoreInInterface(def) ) {
- final String type = getJavaType(name, value);
+ final ConstantDefinition.JavaExpr constExpr = def.computeJavaExpr(constMap);
+ constMap.put(def.getName(), constExpr);
+ javaWriter().print(" /** ");
if (optionalComment != null && optionalComment.length() != 0) {
- javaWriter().println(" /** " + optionalComment + " */");
+ javaWriter().print(optionalComment);
+ javaWriter().print(" - ");
}
- String suffix = "";
- final char lastChar = value.charAt(value.length()-1);
- if( lastChar != ')' ) {
- if (type.equals("float") && lastChar != 'f' && lastChar != 'F' ) {
- suffix = "f";
- }else if( lastChar == 'u' || lastChar == 'U' ) {
- value = value.substring(0, value.length()-1);
- }
+ javaWriter().print("CType: ");
+ if( constExpr.resultType.isUnsigned ) {
+ javaWriter().print("unsigned ");
}
- javaWriter().println(" public static final " + type + " " + name + " = " + value + suffix + ";");
+ javaWriter().print(constExpr.resultJavaTypeName);
+ javaWriter().println(" */");
+ javaWriter().println(" public static final " + constExpr.resultJavaTypeName +
+ " " + def.getName() + " = " + constExpr.javaExpression + ";");
}
}
}
diff --git a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java
index c145ff5..d3fca14 100644
--- a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java
@@ -894,7 +894,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
writer.print(" valid values are: <code>");
for (int j = 0; j < enumType.getNumEnumerates(); ++j) {
if (j>0) writer.print(", ");
- writer.print(enumType.getEnumName(j));
+ writer.print(enumType.getEnum(j).getName());
}
writer.println("</code>");
} else if (javaType.isNIOBuffer()) {
diff --git a/src/java/com/jogamp/gluegen/cgram/TNode.java b/src/java/com/jogamp/gluegen/cgram/TNode.java
index 70dc2c4..5a36945 100644
--- a/src/java/com/jogamp/gluegen/cgram/TNode.java
+++ b/src/java/com/jogamp/gluegen/cgram/TNode.java
@@ -10,6 +10,7 @@ import java.util.Enumeration;
import com.jogamp.gluegen.ASTLocusTag;
import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
+import com.jogamp.gluegen.GlueGen;
/**
Class TNode is an implementation of the AST interface
@@ -179,15 +180,87 @@ public void initialize(final AST tr) {
text = text_;
}
- /** Returns the text for this node and all children */
- public String getAllChildrenText() {
+ static class DebugASTVisitor {
+ protected int level;
+ private String tabs(final StringBuilder sb) {
+ sb.setLength(0);
+ for (int i = 0; i < level; i++) {
+ sb.append(" ");
+ }
+ return sb.toString();
+ }
+ DebugASTVisitor(final int level) {
+ this.level = level;
+ }
+ void visit(final AST node) {
+ final StringBuilder sb = new StringBuilder();
+ AST node2;
+ for (node2 = node; node2 != null; node2 = node2.getNextSibling()) {
+ if (node2.getText() == null) {
+ System.err.printf("%03d: %snil [%d]%n", level, tabs(sb), node2.getType());
+ } else {
+ System.err.printf("%03d: %s%s [%d]%n", level, tabs(sb), node2.getText(), node2.getType());
+ }
+ if (node2.getFirstChild() != null) {
+ level++;
+ visit(node2.getFirstChild());
+ level--;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the text for this node, its children and siblings.
+ * <p>
+ * Implementation converts the AST LISP notation to serialized form.
+ * </p>
+ */
+ public String getAllChildrenText(final String name) {
+ if( GlueGen.debug() ) {
+ System.err.println("TNode.XXX: "+name);
+ new DebugASTVisitor(1).visit(getFirstChild());
+ }
final StringBuilder buf = new StringBuilder();
- buf.append(getText());
- for (TNode node = (TNode) getFirstChild(); node != null; node = (TNode) node.getNextSibling()) {
- buf.append(node.getText());
+ final TNode down = (TNode) this.getFirstChild();
+ if( null == down ) {
+ buf.append(this.getText());
+ } else {
+ getAllChildrenText(buf, this, down);
}
return buf.toString();
}
+ private static void getAllChildrenText(final StringBuilder buf,
+ final TNode upNode, TNode thisNode) {
+ boolean first = true;
+ while( null != thisNode ) {
+ final boolean isClosing = HeaderParserTokenTypes.RPAREN == thisNode.getType();
+ final boolean isGroupStart = HeaderParserTokenTypes.NExpressionGroup == thisNode.getType();
+
+ final TNode nextNode = (TNode) thisNode.getNextSibling();
+ final TNode downNode = (TNode) thisNode.getFirstChild();
+ if( !isClosing &&
+ ( null == downNode && null == nextNode || // unary
+ !first // binary
+ )
+ ) {
+ buf.append(" ").append(upNode.getText());
+ }
+ if( null != downNode ) {
+ if( !isGroupStart ) {
+ buf.append(" (");
+ }
+ getAllChildrenText(buf, thisNode, downNode);
+ if( !isGroupStart ) {
+ buf.append(" )");
+ }
+ } else if( !isClosing ) {
+ buf.append(" ").append(thisNode.getText());
+ }
+ thisNode = nextNode;
+ first = false;
+ }
+ }
/** return the last child of this node, or null if there is none */
public TNode getLastChild() {
diff --git a/src/java/com/jogamp/gluegen/cgram/types/EnumType.java b/src/java/com/jogamp/gluegen/cgram/types/EnumType.java
index f49c2ec..7c2fa73 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/EnumType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/EnumType.java
@@ -43,6 +43,9 @@ import java.util.ArrayList;
import java.util.NoSuchElementException;
import com.jogamp.gluegen.ASTLocusTag;
+import com.jogamp.gluegen.ConstantDefinition;
+import com.jogamp.gluegen.ConstantDefinition.CNumber;
+import com.jogamp.gluegen.GlueGenException;
import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
@@ -50,40 +53,49 @@ import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
they have a set of named values. */
public class EnumType extends IntType implements Cloneable {
- private static class Enum implements TypeComparator.SemanticEqualityOp {
- final String name;
- final long value;
+ public static class Enumerator implements TypeComparator.SemanticEqualityOp {
+ private final String name;
+ private final String expr;
+ private final CNumber number;
- Enum(final String name, final long value) {
+ public Enumerator(final String name, final long value) {
this.name = name;
- this.value = value;
+ this.number = new CNumber(false, false, value);
+ this.expr = this.number.toJavaString();
}
-
- String getName() {
- return name;
+ public Enumerator(final String name, final CNumber number) {
+ this.name = name;
+ this.number = number;
+ this.expr = this.number.toJavaString();
}
-
- long getValue() {
- return value;
+ public Enumerator(final String name, final String value) {
+ this.name = name;
+ this.expr = value;
+ this.number = ConstantDefinition.decodeIntegerNumber(value);
}
+ public String getName() { return name; }
+ public String getExpr() { return expr; }
+ public CNumber getNumber() { return number; }
+ public boolean hasNumber() { return null != number; }
+
@Override
public int hashCode() {
// 31 * x == (x << 5) - x
final int hash = name.hashCode();
- return ((hash << 5) - hash) + (int)(value ^ (value >>> 32));
+ return ((hash << 5) - hash) + expr.hashCode();
}
@Override
public boolean equals(final Object arg) {
if (arg == this) {
return true;
- } else if ( !(arg instanceof Enum) ) {
+ } else if ( !(arg instanceof Enumerator) ) {
return false;
}
- final Enum t = (Enum) arg;
+ final Enumerator t = (Enumerator) arg;
return name.equals(t.name) &&
- value == t.value;
+ expr.equals(t.expr);
}
@Override
@@ -96,11 +108,12 @@ public class EnumType extends IntType implements Cloneable {
return equals(arg);
}
- public String toString() { return name+" = "+value; }
+ @Override
+ public String toString() { return "["+name+" = ["+expr+", "+number+"]"; }
}
private final IntType underlyingType;
- private ArrayList<Enum> enums;
+ private ArrayList<Enumerator> enums;
public EnumType(final String name) {
super(name, SizeThunk.LONG, false, CVAttributes.CONST);
@@ -116,7 +129,7 @@ public class EnumType extends IntType implements Cloneable {
super(o, cvAttributes, astLocus);
underlyingType = o.underlyingType;
if(null != o.enums) {
- enums = new ArrayList<Enum>(o.enums);
+ enums = new ArrayList<Enumerator>(o.enums);
}
}
@@ -164,11 +177,11 @@ public class EnumType extends IntType implements Cloneable {
public Type getUnderlyingType() { return this.underlyingType; }
- public void addEnum(final String name, final long val) {
+ public void addEnum(final String name, final Enumerator newEnum) {
if (enums == null) {
- enums = new ArrayList<Enum>();
+ enums = new ArrayList<Enumerator>();
}
- enums.add(new Enum(name, val));
+ enums.add(newEnum);
clearCache();
}
@@ -177,22 +190,17 @@ public class EnumType extends IntType implements Cloneable {
return enums.size();
}
- /** Fetch <i>i</i>th (0..getNumEnumerates() - 1) name */
- public String getEnumName(final int i) {
- return (enums.get(i)).getName();
- }
-
- /** Fetch <i>i</i>th (0..getNumEnumerates() - 1) value */
- public long getEnumValue(final int i) {
- return (enums.get(i)).getValue();
+ /** Fetch <i>i</i>th (0..getNumEnumerates() - 1) {@link Enumerator} */
+ public Enumerator getEnum(final int i) {
+ return enums.get(i);
}
- /** Fetch the value of the enumerate with the given name. */
- public long getEnumValue(final String name) {
+ /** Fetch the enumerate with the given name. */
+ public Enumerator getEnum(final String name) {
for (int i = 0; i < enums.size(); ++i) {
- final Enum n = (enums.get(i));
+ final Enumerator n = (enums.get(i));
if (n.getName().equals(name)) {
- return n.getValue();
+ return n;
}
}
throw new NoSuchElementException(
@@ -215,7 +223,7 @@ public class EnumType extends IntType implements Cloneable {
*/
public boolean removeEnumerate(final String name) {
for (int i = 0; i < enums.size(); ++i) {
- final Enum e = enums.get(i);
+ final Enumerator e = enums.get(i);
if (e.getName().equals(name)) {
enums.remove(e);
clearCache();