blob: e1339f4c4fded391ec9ad6df6156cf507e09df4b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.floatingpoint;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
import java.nio.ByteOrder;
import java.util.List;
import org.antlr.runtime.tree.CommonTree;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.ctf.parser.CTFParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.AlignmentParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.ByteOrderParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
/**
*
* The floating point values byte ordering is defined in the TSDL metadata.
* <p>
* Floating point values follow the IEEE 754-2008 standard interchange formats.
* Description of the floating point values include the exponent and mantissa
* size in bits. Some requirements are imposed on the floating point values:
* <ul>
* <li>FLT_RADIX must be 2.</li>
* <li>mant_dig is the number of digits represented in the mantissa. It is
* specified by the ISO C99 standard, section 5.2.4, as FLT_MANT_DIG,
* DBL_MANT_DIG and LDBL_MANT_DIG as defined by <float.h>.</li>
* <li>exp_dig is the number of digits represented in the exponent. Given that
* mant_dig is one bit more than its actual size in bits (leading 1 is not
* needed) and also given that the sign bit always takes one bit, exp_dig can be
* specified as:</li>
* <ul>
* <li>sizeof(float) * CHAR_BIT - FLT_MANT_DIG</li>
* <li>sizeof(double) * CHAR_BIT - DBL_MANT_DIG</li>
* <li>sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG</li>
* <li>
* </ul>
* </ul>
*
* @author Matthew Khouzam - initial API and implementation
* @auttor Efficios - Description
*
*/
public final class FloatDeclarationParser implements ICommonTreeParser {
private static final String FLOAT_UNKNOWN_ATTRIBUTE = "Float: unknown attribute "; //$NON-NLS-1$
private static final String FLOAT_MISSING_SIZE_ATTRIBUTE = "Float: missing size attribute"; //$NON-NLS-1$
private static final String IDENTIFIER_MUST_BE_A_STRING = "Left side of ctf expression must be a string"; //$NON-NLS-1$
/**
* Parameter object with only a trace in it
*
* @author Matthew Khouzam
*
*/
@NonNullByDefault
public static final class Param implements ICommonTreeParserParameter {
private final CTFTrace fTrace;
/**
* Constructor
*
* @param trace
* the trace
*/
public Param(CTFTrace trace) {
fTrace = trace;
}
}
/**
* Instance
*/
public static final FloatDeclarationParser INSTANCE = new FloatDeclarationParser();
private static final int DEFAULT_FLOAT_EXPONENT = 8;
private static final int DEFAULT_FLOAT_MANTISSA = 24;
private FloatDeclarationParser() {
}
/**
* Parses a float node and returns a floating point declaration of the
* type @link {@link FloatDeclaration}.
*
* @param floatingPoint
* AST node of type FLOAT
* @param param
* parameter containing the trace
* @return the float declaration
* @throws ParseException
* if a float AST is malformed
*/
@Override
public FloatDeclaration parse(CommonTree floatingPoint, ICommonTreeParserParameter param) throws ParseException {
if (!(param instanceof Param)) {
throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
}
CTFTrace trace = ((Param) param).fTrace;
List<CommonTree> children = floatingPoint.getChildren();
/*
* If the integer has no attributes, then it is missing the size
* attribute which is required
*/
if (children == null) {
throw new ParseException(FLOAT_MISSING_SIZE_ATTRIBUTE);
}
/* The return value */
ByteOrder byteOrder = trace.getByteOrder();
long alignment = 0;
int exponent = DEFAULT_FLOAT_EXPONENT;
int mantissa = DEFAULT_FLOAT_MANTISSA;
/* Iterate on all integer children */
for (CommonTree child : children) {
switch (child.getType()) {
case CTFParser.CTF_EXPRESSION_VAL:
/*
* An assignment expression must have 2 children, left and right
*/
CommonTree leftNode = (CommonTree) child.getChild(0);
CommonTree rightNode = (CommonTree) child.getChild(1);
List<CommonTree> leftStrings = leftNode.getChildren();
if (!isAnyUnaryString(leftStrings.get(0))) {
throw new ParseException(IDENTIFIER_MUST_BE_A_STRING);
}
String left = concatenateUnaryStrings(leftStrings);
if (left.equals(MetadataStrings.EXP_DIG)) {
exponent = UnaryIntegerParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null).intValue();
} else if (left.equals(MetadataStrings.BYTE_ORDER)) {
byteOrder = ByteOrderParser.INSTANCE.parse(rightNode, new ByteOrderParser.Param(trace));
} else if (left.equals(MetadataStrings.MANT_DIG)) {
mantissa = UnaryIntegerParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null).intValue();
} else if (left.equals(MetadataStrings.ALIGN)) {
alignment = AlignmentParser.INSTANCE.parse(rightNode, null);
} else {
throw new ParseException(FLOAT_UNKNOWN_ATTRIBUTE + left);
}
break;
default:
throw childTypeError(child);
}
}
int size = mantissa + exponent;
if (size == 0) {
throw new ParseException(FLOAT_MISSING_SIZE_ATTRIBUTE);
}
if (alignment == 0) {
alignment = 1;
}
return new FloatDeclaration(exponent, mantissa, byteOrder, alignment);
}
}