import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import org.eclipse.linuxtools.ctf.core.trace.StreamInputPacketIndexEntry;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.StreamInputPacketIndex;
-import org.eclipse.linuxtools.ctf.core.trace.StreamInputPacketIndexEntry;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.Stream;
import org.eclipse.linuxtools.ctf.core.trace.StreamInput;
-import org.eclipse.linuxtools.ctf.core.trace.StreamInputPacketIndexEntry;
import org.eclipse.linuxtools.ctf.core.trace.StreamInputPacketReader;
import org.eclipse.linuxtools.ctf.core.trace.StreamInputReader;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.linuxtools.ctf.core.trace.Stream;
import org.eclipse.linuxtools.ctf.core.trace.StreamInput;
import org.eclipse.linuxtools.ctf.core.trace.StreamInputReader;
-import org.eclipse.linuxtools.ctf.core.trace.StreamInputReaderComparator;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputReaderComparator;
import org.junit.*;
/**
import java.nio.ByteOrder;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
import org.eclipse.linuxtools.ctf.core.event.types.EnumDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteOrder;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteOrder;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.event.types.StringDeclaration;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
import java.util.HashMap;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
import org.eclipse.linuxtools.ctf.core.trace.CTFTraceReader;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
import org.junit.After;
import org.junit.Before;
org.antlr.runtime;bundle-version="3.2.0",
org.eclipse.linuxtools.ctf.parser;bundle-version="0.1.0"
Export-Package: org.eclipse.linuxtools.ctf.core.event,
- org.eclipse.linuxtools.ctf.core.event.io,
org.eclipse.linuxtools.ctf.core.event.metadata,
org.eclipse.linuxtools.ctf.core.event.metadata.exceptions,
org.eclipse.linuxtools.ctf.core.event.types,
+++ /dev/null
-/*******************************************************************************.
- * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
- *
- * All rights reserved. This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Matthew Khouzam - Initial Design and implementation
- * Contributors: Francis Giraldeau - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.linuxtools.ctf.core.event.io;
-
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * <b><u>BitBuffer</u></b>
- * <p>
- * TODO Implement me. Please.
- */
-public class BitBuffer {
-
- // ------------------------------------------------------------------------
- // Constants
- // ------------------------------------------------------------------------
-
- /* default bit width */
- public static final int BIT_CHAR = 8;
- public static final int BIT_SHORT = 16;
- public static final int BIT_INT = 32;
- public static final int BIT_FLOAT = 32;
- public static final int BIT_LONG = 64;
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- private ByteBuffer buf;
- private int pos;
- private ByteOrder byteOrder;
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- public BitBuffer() {
- this(null, ByteOrder.BIG_ENDIAN);
- }
-
- public BitBuffer(ByteBuffer buf) {
- this(buf, ByteOrder.BIG_ENDIAN);
- }
-
- public BitBuffer(ByteBuffer buf, ByteOrder order) {
- setByteBuffer(buf);
- order(order);
- position(0);
- }
-
- // ------------------------------------------------------------------------
- // 'Get' operations on buffer
- // ------------------------------------------------------------------------
-
- /**
- * Relative <i>get</i> method for reading 32-bit integer.
- *
- * Reads next four bytes from the current bit position according to current
- * byte order.
- *
- * @return The int value read from the buffer
- */
- public int getInt() {
- int val = getInt(BIT_INT, true);
- pos += BIT_INT;
- return val;
- }
-
- /**
- * Relative <i>get</i> method for reading integer of <i>length</i> bits.
- *
- * Reads <i>length</i> bits starting at the current position. The result is
- * signed extended if <i>signed</i> is true. The current position is
- * increased of <i>length</i> bits.
- *
- * @param length
- * The length in bits of this integer
- * @param signed
- * The sign extended flag
- * @return The int value read from the buffer
- */
- public int getInt(int length, boolean signed) {
- int val;
- if (!canRead(pos, length)) {
- throw new BufferOverflowException();
- }
- if (length == 0) {
- val = 0;
- }
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- val = getIntLE(pos, length, signed);
- } else {
- val = getIntBE(pos, length, signed);
- }
- pos += length;
- return val;
- }
-
- /**
- * Absolute <i>get</i> method for reading integer of <i>length</i> bits.
- *
- * Reads <i>length</i> bits starting from position <i>index</i>. The result
- * is signed extended if <i>signed</i> is true. The current position is
- * increased of <i>length</i> bits.
- *
- * @param index
- * The start index in bits
- * @param length
- * The length in bits to read
- * @param signed
- * The sign extended flag
- * @return The int value read from the buffer
- */
- public int getInt(int index, int length, boolean signed) {
- if (!canRead(index, length)) {
- throw new BufferOverflowException();
- }
- if (length == 0) {
- return 0;
- }
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- return getIntLE(index, length, signed);
- }
- return getIntBE(index, length, signed);
- }
-
- private int getIntBE(int index, int length, boolean signed) {
- assert ((length > 0) && (length <= BIT_INT));
- int end = index + length;
- int startByte = index / BIT_CHAR;
- int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
- int currByte, lshift, cshift, mask, cmask, cache;
- int value = 0;
-
- currByte = startByte;
- cache = buf.get(currByte) & 0xFF;
- boolean isNeg = (cache & (1 << (BIT_CHAR - (index % BIT_CHAR) - 1))) != 0;
- if (signed && isNeg) {
- value = ~0;
- }
- if (startByte == (endByte - 1)) {
- cmask = cache >>> ((BIT_CHAR - (end % BIT_CHAR)) % BIT_CHAR);
- if (((length) % BIT_CHAR) > 0) {
- mask = ~((~0) << length);
- cmask &= mask;
- }
- value <<= length;
- value |= cmask;
- return value;
- }
- cshift = index % BIT_CHAR;
- if (cshift > 0) {
- mask = ~((~0) << (BIT_CHAR - cshift));
- cmask = cache & mask;
- lshift = BIT_CHAR - cshift;
- value <<= lshift;
- value |= cmask;
- // index += lshift;
- currByte++;
- }
- for (; currByte < (endByte - 1); currByte++) {
- value <<= BIT_CHAR;
- value |= buf.get(currByte) & 0xFF;
- }
- lshift = end % BIT_CHAR;
- if (lshift > 0) {
- mask = ~((~0) << lshift);
- cmask = buf.get(currByte) & 0xFF;
- cmask >>>= BIT_CHAR - lshift;
- cmask &= mask;
- value <<= lshift;
- value |= cmask;
- } else {
- value <<= BIT_CHAR;
- value |= buf.get(currByte) & 0xFF;
- }
- return value;
- }
-
- private int getIntLE(int index, int length, boolean signed) {
- assert ((length > 0) && (length <= BIT_INT));
- int end = index + length;
- int startByte = index / BIT_CHAR;
- int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
- int currByte, lshift, cshift, mask, cmask, cache, mod;
- int value = 0;
-
- currByte = endByte - 1;
- cache = buf.get(currByte) & 0xFF;
- mod = end % BIT_CHAR;
- lshift = (mod > 0) ? mod : BIT_CHAR;
- boolean isNeg = (cache & (1 << (lshift - 1))) != 0;
- if (signed && isNeg) {
- value = ~0;
- }
- if (startByte == (endByte - 1)) {
- cmask = cache >>> (index % BIT_CHAR);
- if (((length) % BIT_CHAR) > 0) {
- mask = ~((~0) << length);
- cmask &= mask;
- }
- value <<= length;
- value |= cmask;
- return value;
- }
- cshift = end % BIT_CHAR;
- if (cshift > 0) {
- mask = ~((~0) << cshift);
- cmask = cache & mask;
- value <<= cshift;
- value |= cmask;
- // end -= cshift;
- currByte--;
- }
- for (; currByte >= (startByte + 1); currByte--) {
- value <<= BIT_CHAR;
- value |= buf.get(currByte) & 0xFF;
- }
- lshift = index % BIT_CHAR;
- if (lshift > 0) {
- mask = ~((~0) << (BIT_CHAR - lshift));
- cmask = buf.get(currByte) & 0xFF;
- cmask >>>= lshift;
- cmask &= mask;
- value <<= (BIT_CHAR - lshift);
- value |= cmask;
- } else {
- value <<= BIT_CHAR;
- value |= buf.get(currByte) & 0xFF;
- }
- return value;
- }
-
- // ------------------------------------------------------------------------
- // 'Put' operations on buffer
- // ------------------------------------------------------------------------
-
- /**
- * Relative <i>put</i> method to write signed 32-bit integer.
- *
- * Write four bytes starting from current bit position in the buffer
- * according to the current byte order. The current position is increased of
- * <i>length</i> bits.
- *
- * @param value
- * The int value to write
- */
- public void putInt(int value) {
- putInt(BIT_INT, value);
- }
-
- /**
- * Relative <i>put</i> method to write <i>length</i> bits integer.
- *
- * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
- * starting from current bit position in the buffer. Sequential bytes are
- * written according to the current byte order. The sign bit is carried to
- * the MSB if signed is true. The sign bit is included in <i>length</i>. The
- * current position is increased of <i>length</i>.
- *
- * @param length
- * The number of bits to write
- * @param value
- * The value to write
- */
- public void putInt(int length, int value) {
- putInt(this.pos, length, value);
- }
-
- /**
- * Absolute <i>put</i> method to write <i>length</i> bits integer.
- *
- * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
- * starting from <i>index</i> position in the buffer. Sequential bytes are
- * written according to the current byte order. The sign bit is carried to
- * the MSB if signed is true. The sign bit is included in <i>length</i>. The
- * current position is increased of <i>length</i>.
- *
- * @param index
- * The start position to write the value
- * @param value
- * The value to write
- * @param length
- * The number of bits to write
- */
- public void putInt(int index, int length, int value) {
- if (!canRead(index, length)) {
- throw new BufferOverflowException();
- }
- if (length == 0) {
- return;
- }
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- putIntLE(index, length, value);
- } else {
- putIntBE(index, length, value);
- }
- }
-
- private void putIntBE(int index, int length, int value) {
- assert ((length > 0) && (length <= BIT_INT));
- int end = index + length;
- int startByte = index / BIT_CHAR;
- int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
- int currByte, lshift, cshift, mask, cmask;
- int correctedValue = value;
-
- /*
- * mask v high bits. Works for unsigned and two complement signed
- * numbers which value do not overflow on length bits.
- */
-
- if (length < BIT_INT) {
- correctedValue &= ~(~0 << length);
- }
-
- /* sub byte */
- if (startByte == (endByte - 1)) {
- lshift = (BIT_CHAR - (end % BIT_CHAR)) % BIT_CHAR;
- mask = ~((~0) << lshift);
- if ((index % BIT_CHAR) > 0) {
- mask |= (~(0)) << (BIT_CHAR - (index % BIT_CHAR));
- }
- cmask = correctedValue << lshift;
- /*
- * low bits are cleared because of lshift and high bits are already
- * cleared
- */
- cmask &= ~mask;
- int b = buf.get(startByte) & 0xFF;
- buf.put(startByte, (byte) ((b & mask) | cmask));
- return;
- }
-
- /* head byte contains MSB */
- currByte = endByte - 1;
- cshift = end % BIT_CHAR;
- if (cshift > 0) {
- lshift = BIT_CHAR - cshift;
- mask = ~((~0) << lshift);
- cmask = correctedValue << lshift;
- cmask &= ~mask;
- int b = buf.get(currByte) & 0xFF;
- buf.put(currByte, (byte) ((b & mask) | cmask));
- correctedValue >>>= cshift;
- // end -= cshift;
- currByte--;
- }
-
- /* middle byte(s) */
- for (; currByte >= (startByte + 1); currByte--) {
- buf.put(currByte, (byte) correctedValue);
- correctedValue >>>= BIT_CHAR;
- }
- /* end byte contains LSB */
- if ((index % BIT_CHAR) > 0) {
- mask = (~0) << (BIT_CHAR - (index % BIT_CHAR));
- cmask = correctedValue & ~mask;
- int b = buf.get(currByte) & 0xFF;
- buf.put(currByte, (byte) ((b & mask) | cmask));
- } else {
- buf.put(currByte, (byte) correctedValue);
- }
- }
-
- private void putIntLE(int index, int length, int value) {
- assert ((length > 0) && (length <= BIT_INT));
- int end = index + length;
- int startByte = index / BIT_CHAR;
- int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
- int currByte, lshift, cshift, mask, cmask;
- int correctedValue = value;
-
- /*
- * mask v high bits. Works for unsigned and two complement signed
- * numbers which value do not overflow on length bits.
- */
-
- if (length < BIT_INT) {
- correctedValue &= ~(~0 << length);
- }
-
- /* sub byte */
- if (startByte == (endByte - 1)) {
- lshift = index % BIT_CHAR;
- mask = ~((~0) << lshift);
- if ((end % BIT_CHAR) > 0) {
- mask |= (~(0)) << (end % BIT_CHAR);
- }
- cmask = correctedValue << lshift;
- /*
- * low bits are cleared because of lshift and high bits are already
- * cleared
- */
- cmask &= ~mask;
- int b = buf.get(startByte) & 0xFF;
- buf.put(startByte, (byte) ((b & mask) | cmask));
- return;
- }
-
- /* head byte */
- currByte = startByte;
- cshift = index % BIT_CHAR;
- if (cshift > 0) {
- mask = ~((~0) << cshift);
- cmask = correctedValue << cshift;
- cmask &= ~mask;
- int b = buf.get(currByte) & 0xFF;
- buf.put(currByte, (byte) ((b & mask) | cmask));
- correctedValue >>>= BIT_CHAR - cshift;
- // index += BIT_CHAR - cshift;
- currByte++;
- }
-
- /* middle byte(s) */
- for (; currByte < (endByte - 1); currByte++) {
- buf.put(currByte, (byte) correctedValue);
- correctedValue >>>= BIT_CHAR;
- }
- /* end byte */
- if ((end % BIT_CHAR) > 0) {
- mask = (~0) << (end % BIT_CHAR);
- cmask = correctedValue & ~mask;
- int b = buf.get(currByte) & 0xFF;
- buf.put(currByte, (byte) ((b & mask) | cmask));
- } else {
- buf.put(currByte, (byte) correctedValue);
- }
- }
-
- // ------------------------------------------------------------------------
- // Buffer attributes handling
- // ------------------------------------------------------------------------
-
- public boolean canRead(int length) {
- return canRead(pos, length);
- }
-
- public boolean canRead(int index, int length) {
- if (buf == null) {
- return false;
- }
-
- if ((index + length) > (buf.capacity() * BIT_CHAR)) {
- return false;
- }
- return true;
- }
-
- public void order(ByteOrder order) {
- this.byteOrder = order;
- if (buf != null) {
- buf.order(order);
- }
- }
-
- public ByteOrder order() {
- return byteOrder;
- }
-
- public void position(int newPosition) {
- this.pos = newPosition;
- }
-
- public int position() {
- return pos;
- }
-
- public void setByteBuffer(ByteBuffer buf) {
- this.buf = buf;
- if (buf != null) {
- this.buf.order(byteOrder);
- }
- clear();
- }
-
- public ByteBuffer getByteBuffer() {
- return buf;
- }
-
- public void setByteOrder(ByteOrder byteOrder) {
- this.byteOrder = byteOrder;
- }
-
- public ByteOrder getByteOrder() {
- return byteOrder;
- }
-
- public void clear() {
- position(0);
-
- if (buf == null) {
- return;
- }
- buf.clear();
- }
-
-}
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
- *
- * All rights reserved. This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Matthew Khouzam - Initial Design and Grammar
- * Contributors: Francis Giraldeau - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.linuxtools.ctf.core.event.metadata;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-
-import org.antlr.runtime.tree.CommonTree;
-import org.eclipse.linuxtools.ctf.core.event.CTFClock;
-import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.metadata.exceptions.ParseException;
-import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
-import org.eclipse.linuxtools.ctf.core.event.types.EnumDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.SequenceDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.StringDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
-import org.eclipse.linuxtools.ctf.core.event.types.VariantDeclaration;
-import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
-import org.eclipse.linuxtools.ctf.core.trace.Stream;
-import org.eclipse.linuxtools.ctf.parser.CTFParser;
-import org.eclipse.linuxtools.internal.ctf.core.Activator;
-
-/*
- * Asserts throughout this class denote the assumptions we can make because of
- * the way the grammar generates the AST.
- *
- * There is also an assert at the beginning of each function that receives a
- * tree node to make sure that the node is indeed of the type the function is
- * expecting.
- */
-/*
- * Suppress unchecked warnings for things like List<CommonTree> children =
- * root.getChildren(), because ANTLR doesn't know what generics are.
- */
-/**
- * <b><u>IOStructGen</u></b>
- */
-@SuppressWarnings("unchecked")
-public class IOStructGen {
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- static private final boolean DEBUG_ = false;
-
- /**
- * The trace
- */
- private final CTFTrace trace;
- private final CommonTree tree;
-
- /**
- * The current declaration scope.
- */
- private DeclarationScope scope = null;
-
- // ------------------------------------------------------------------------
- // Constructor
- // ------------------------------------------------------------------------
-
- public IOStructGen(CommonTree tree, CTFTrace trace) {
- this.trace = trace;
- this.tree = tree;
- }
-
- public void generate() throws ParseException {
- parseRoot(tree);
- }
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- /**
- * Parse the root node.
- *
- * @param root
- * A ROOT node.
- * @throws ParseException
- */
- private void parseRoot(CommonTree root) throws ParseException {
- assert (root.getType() == CTFParser.ROOT);
-
- List<CommonTree> children = root.getChildren();
- assert (children != null);
- java.io.FileOutputStream fos = null;
- java.io.OutputStreamWriter out = null;
- if (DEBUG_) {
- try {
- fos = new java.io.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
- out = new java.io.OutputStreamWriter(fos, "UTF-8"); //$NON-NLS-1$
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- return;
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- return;
- }
- }
-
- CommonTree traceNode = null;
- List<CommonTree> streams = new ArrayList<CommonTree>();
- List<CommonTree> events = new ArrayList<CommonTree>();
- List<CommonTree> declarations = new ArrayList<CommonTree>();
- List<CommonTree> environments = new ArrayList<CommonTree>();
- List<CommonTree> clocks = new ArrayList<CommonTree>();
- /* Create a new declaration scope with no parent. */
- pushScope();
-
- try {
- for (CommonTree child : children) {
- if (DEBUG_) {
- out.write(child.toString()
- + " -> " + child.getType() + '\n'); //$NON-NLS-1$
- }
- switch (child.getType()) {
- case CTFParser.DECLARATION:
- declarations.add(child);
- break;
- case CTFParser.TRACE:
- if (traceNode != null) {
- throw new ParseException(
- "Only one trace block is allowed"); //$NON-NLS-1$
- }
- traceNode = child;
- break;
- case CTFParser.STREAM:
- streams.add(child);
- break;
- case CTFParser.EVENT:
- events.add(child);
- break;
- case CTFParser.CLOCK:
- clocks.add(child);
- break;
- case CTFParser.ENV:
- environments.add(child);
- break;
- default:
- childTypeError(child);
- }
- }
-
- if (DEBUG_) {
- out.write("Environments\n"); //$NON-NLS-1$
- }
- for (CommonTree environment : environments) {
- parseEnvironment(environment);
- }
- if (DEBUG_) {
- out.write("Clocks\n"); //$NON-NLS-1$
- }
- for (CommonTree clock : clocks) {
- parseClock(clock);
- }
- if (DEBUG_) {
- out.write("Declarations\n"); //$NON-NLS-1$
- }
- for (CommonTree decl : declarations) {
- if (DEBUG_) {
- out.write(decl.toString() + '\n');
- }
- parseRootDeclaration(decl);
- }
-
- if (traceNode == null) {
- throw new ParseException("Missing trace block"); //$NON-NLS-1$
- }
-
- parseTrace(traceNode);
-
- if (DEBUG_) {
- out.write("Streams\n"); //$NON-NLS-1$
- }
- if (streams.size() > 0) {
- for (CommonTree stream : streams) {
- if (DEBUG_) {
- try {
- out.write(stream.toString() + '\n');
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- parseStream(stream);
- }
- } else {
- /* Add an empty stream that will have a null id */
- trace.addStream(new Stream(trace));
- }
-
- if (DEBUG_) {
- out.write("Events\n"); //$NON-NLS-1$
- }
- for (CommonTree event : events) {
- parseEvent(event);
- CommonTree name = (CommonTree) event.getChild(0).getChild(1)
- .getChild(0).getChild(0);
- if (DEBUG_) {
- out.write("Name = " + name); //$NON-NLS-1$
- }
- CommonTree id = (CommonTree) event.getChild(1).getChild(1)
- .getChild(0).getChild(0);
- if (DEBUG_) {
- out.write("Name = " + name + " Id = " + id + '\n'); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
- if (DEBUG_) {
- out.close();
- fos.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- popScope();
- }
-
- private void parseEnvironment(CommonTree environment) {
- List<CommonTree> children = environment.getChildren();
- for (CommonTree child : children) {
- String left;
- String right;
- left = child.getChild(0).getChild(0).getChild(0).getText();
- right = child.getChild(1).getChild(0).getChild(0).getText();
- trace.addEnvironmentVar(left, right);
- }
- }
-
- private void parseClock(CommonTree clock) {
- List<CommonTree> children = clock.getChildren();
- CTFClock ctfClock = new CTFClock();
- for (CommonTree child : children) {
- final String key = child.getChild(0).getChild(0).getChild(0)
- .getText();
- final CommonTree value = (CommonTree) child.getChild(1).getChild(0).getChild(0);
- final int type = value.getType();
- switch (type) {
- case CTFParser.INTEGER:
- case CTFParser.DECIMAL_LITERAL:
- /*
- * Not a pretty hack, this is to make sure that there is no number
- * overflow due to 63 bit integers. The offset should only really
- * be an issue in the year 2262. the tracer in C/ASM can write an offset in
- * an unsigned 64 bit long. In java, the last bit, being set to 1 will
- * be read as a negative number, but since it is too big a positive it will
- * throw an exception. this will happen in 2^63 ns from 1970.
- * Therefore 293 years from 1970
- */
- Long numValue;
- try{
- numValue = Long.parseLong(value.getText());
- }
- catch( Exception e)
- {
- numValue = 1330938566783103277L;
- }
- ctfClock.addAttribute(key, numValue);
- break;
- default:
- ctfClock.addAttribute(key, value.getText());
- }
-
- }
- String NameValue = ctfClock.getName();
- trace.addClock(NameValue, ctfClock);
- }
-
- private void parseTrace(CommonTree traceNode) throws ParseException {
- assert (traceNode.getType() == CTFParser.TRACE);
-
- List<CommonTree> children = traceNode.getChildren();
- if (children == null) {
- throw new ParseException("Trace block is empty"); //$NON-NLS-1$
- }
-
- pushScope();
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPEALIAS:
- parseTypealias(child);
- break;
- case CTFParser.TYPEDEF:
- parseTypedef(child);
- break;
- case CTFParser.CTF_EXPRESSION_TYPE:
- case CTFParser.CTF_EXPRESSION_VAL:
- parseTraceDeclaration(child);
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- /*
- * If trace byte order was not specified and not using packet based
- * metadata
- */
- if (trace.getByteOrder() == null) {
- throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
- }
-
- popScope();
- }
-
- private void parseTraceDeclaration(CommonTree traceDecl)
- throws ParseException {
- assert ((traceDecl.getType() == CTFParser.CTF_EXPRESSION_TYPE) || (traceDecl
- .getType() == CTFParser.CTF_EXPRESSION_VAL));
-
- /* There should be a left and right */
- assert (traceDecl.getChildCount() == 2);
-
- CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
- assert (leftNode.getType() == CTFParser.CTF_LEFT);
- CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
-
- List<CommonTree> leftStrings = leftNode.getChildren();
- assert (leftStrings != null);
-
- if (!isUnaryString(leftStrings.get(0))) {
- throw new ParseException(
- "Left side of CTF assignment must be a string"); //$NON-NLS-1$
- }
-
- String left = concatenateUnaryStrings(leftStrings);
-
- if (left.equals("major")) { //$NON-NLS-1$
- if (trace.majortIsSet()) {
- throw new ParseException("major is already set"); //$NON-NLS-1$
- }
-
- trace.setMajor(getMajorOrMinor(rightNode));
- } else if (left.equals("minor")) { //$NON-NLS-1$
- if (trace.minorIsSet()) {
- throw new ParseException("minor is already set"); //$NON-NLS-1$
- }
-
- trace.setMinor(getMajorOrMinor(rightNode));
- } else if (left.equals("uuid")) { //$NON-NLS-1$
- UUID uuid = getUUID(rightNode);
-
- /*
- * If uuid was already set by a metadata packet, compare it to see
- * if it matches
- */
- if (trace.UUIDIsSet()) {
- if (trace.getUUID().compareTo(uuid) != 0) {
- throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
- + trace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
- }
- } else {
- trace.setUUID(uuid);
- }
-
- } else if (left.equals("byte_order")) { //$NON-NLS-1$
- ByteOrder byteOrder = getByteOrder(rightNode);
-
- /*
- * If byte order was already set by a metadata packet, compare it to
- * see if it matches
- */
- if (trace.getByteOrder() != null) {
- if (trace.getByteOrder() != byteOrder) {
- throw new ParseException(
- "Endianness mismatch. Magic number says " //$NON-NLS-1$
- + trace.getByteOrder()
- + " but metadata says " + byteOrder); //$NON-NLS-1$
- }
- } else {
- trace.setByteOrder(byteOrder);
- }
- } else if (left.equals("packet.header")) { //$NON-NLS-1$
- if (trace.packetHeaderIsSet()) {
- throw new ParseException("packet.header already defined"); //$NON-NLS-1$
- }
-
- CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
- if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
- throw new ParseException(
- "packet.header expects a type specifier"); //$NON-NLS-1$
- }
-
- IDeclaration packetHeaderDecl = parseTypeSpecifierList(
- typeSpecifier, null);
-
- if (!(packetHeaderDecl instanceof StructDeclaration)) {
- throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
- }
-
- trace.setPacketHeader((StructDeclaration) packetHeaderDecl);
- } else {
- throw new ParseException("Unknown trace attribute : " + left); //$NON-NLS-1$
- }
- }
-
- private void parseStream(CommonTree streamNode) throws ParseException {
- assert (streamNode.getType() == CTFParser.STREAM);
-
- Stream stream = new Stream(trace);
-
- List<CommonTree> children = streamNode.getChildren();
- if (children == null) {
- throw new ParseException("Empty stream block"); //$NON-NLS-1$
- }
-
- pushScope();
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPEALIAS:
- parseTypealias(child);
- break;
- case CTFParser.TYPEDEF:
- parseTypedef(child);
- break;
- case CTFParser.CTF_EXPRESSION_TYPE:
- case CTFParser.CTF_EXPRESSION_VAL:
- parseStreamDeclaration(child, stream);
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- if (stream.idIsSet()) {
- if (!trace.packetHeaderIsSet()
- || !trace.getPacketHeader().hasField("stream_id")) { //$NON-NLS-1$
- throw new ParseException(
- "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
- }
- }
-
- trace.addStream(stream);
-
- popScope();
- }
-
- private void parseStreamDeclaration(CommonTree streamDecl, Stream stream)
- throws ParseException {
- assert ((streamDecl.getType() == CTFParser.CTF_EXPRESSION_TYPE) || (streamDecl
- .getType() == CTFParser.CTF_EXPRESSION_VAL));
-
- /* There should be a left and right */
- assert (streamDecl.getChildCount() == 2);
-
- CommonTree leftNode = (CommonTree) streamDecl.getChild(0);
- assert (leftNode.getType() == CTFParser.CTF_LEFT);
- CommonTree rightNode = (CommonTree) streamDecl.getChild(1);
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
-
- List<CommonTree> leftStrings = leftNode.getChildren();
- assert (leftStrings != null);
-
- if (!isUnaryString(leftStrings.get(0))) {
- throw new ParseException(
- "Left side of CTF assignment must be a string"); //$NON-NLS-1$
- }
-
- String left = concatenateUnaryStrings(leftStrings);
-
- if (left.equals("id")) { //$NON-NLS-1$
- if (stream.idIsSet()) {
- throw new ParseException("stream id already defined"); //$NON-NLS-1$
- }
-
- long streamID = getStreamID(rightNode);
-
- stream.setId(streamID);
- } else if (left.equals("event.header")) { //$NON-NLS-1$
- if (stream.eventHeaderIsSet()) {
- throw new ParseException("event.header already defined"); //$NON-NLS-1$
- }
-
- CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
- if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
- throw new ParseException(
- "event.header expects a type specifier"); //$NON-NLS-1$
- }
-
- IDeclaration eventHeaderDecl = parseTypeSpecifierList(
- typeSpecifier, null);
-
- if (!(eventHeaderDecl instanceof StructDeclaration)) {
- throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
- }
-
- stream.setEventHeader((StructDeclaration) eventHeaderDecl);
- } else if (left.equals("event.context")) { //$NON-NLS-1$
- if (stream.eventContextIsSet()) {
- throw new ParseException("event.context already defined"); //$NON-NLS-1$
- }
-
- CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
- if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
- throw new ParseException(
- "event.context expects a type specifier"); //$NON-NLS-1$
- }
-
- IDeclaration eventContextDecl = parseTypeSpecifierList(
- typeSpecifier, null);
-
- if (!(eventContextDecl instanceof StructDeclaration)) {
- throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
- }
-
- stream.setEventContext((StructDeclaration) eventContextDecl);
- } else if (left.equals("packet.context")) { //$NON-NLS-1$
- if (stream.packetContextIsSet()) {
- throw new ParseException("packet.context already defined"); //$NON-NLS-1$
- }
-
- CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
- if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
- throw new ParseException(
- "packet.context expects a type specifier"); //$NON-NLS-1$
- }
-
- IDeclaration packetContextDecl = parseTypeSpecifierList(
- typeSpecifier, null);
-
- if (!(packetContextDecl instanceof StructDeclaration)) {
- throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
- }
-
- stream.setPacketContext((StructDeclaration) packetContextDecl);
- } else {
- throw new ParseException("Unknown stream attribute : " + left); //$NON-NLS-1$
- }
- }
-
- private void parseEvent(CommonTree eventNode) throws ParseException {
- assert (eventNode.getType() == CTFParser.EVENT);
-
- List<CommonTree> children = eventNode.getChildren();
- if (children == null) {
- throw new ParseException("Empty event block"); //$NON-NLS-1$
- }
-
- EventDeclaration event = new EventDeclaration();
-
- pushScope();
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPEALIAS:
- parseTypealias(child);
- break;
- case CTFParser.TYPEDEF:
- parseTypedef(child);
- break;
- case CTFParser.CTF_EXPRESSION_TYPE:
- case CTFParser.CTF_EXPRESSION_VAL:
- parseEventDeclaration(child, event);
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- if (!event.nameIsSet()) {
- throw new ParseException("Event name not set"); //$NON-NLS-1$
- }
-
- /*
- * If the event did not specify a stream, then the trace must be single
- * stream
- */
- if (!event.streamIsSet()) {
- if (trace.nbStreams() > 1) {
- throw new ParseException(
- "Event without stream_id with more than one stream"); //$NON-NLS-1$
- }
-
- /*
- * If the event did not specify a stream, the only existing stream
- * must not have an id. Note: That behavior could be changed, it
- * could be possible to just get the only existing stream, whatever
- * is its id.
- */
- Stream stream = trace.getStream(null);
-
- if (stream != null) {
- event.setStream(stream);
- } else {
- throw new ParseException(
- "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
- }
- }
-
- /*
- * Add the event to the stream.
- */
- event.getStream().addEvent(event);
-
- popScope();
- }
-
- private void parseEventDeclaration(CommonTree eventDecl,
- EventDeclaration event) throws ParseException {
- assert ((eventDecl.getType() == CTFParser.CTF_EXPRESSION_TYPE) || (eventDecl
- .getType() == CTFParser.CTF_EXPRESSION_VAL));
-
- /* There should be a left and right */
- assert (eventDecl.getChildCount() == 2);
-
- CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
- assert (leftNode.getType() == CTFParser.CTF_LEFT);
- CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
-
- List<CommonTree> leftStrings = leftNode.getChildren();
- assert (leftStrings != null);
-
- if (!isUnaryString(leftStrings.get(0))) {
- throw new ParseException(
- "Left side of CTF assignment must be a string"); //$NON-NLS-1$
- }
-
- String left = concatenateUnaryStrings(leftStrings);
-
- if (left.equals("name")) { //$NON-NLS-1$
- if (event.nameIsSet()) {
- throw new ParseException("name already defined"); //$NON-NLS-1$
- }
-
- String name = getEventName(rightNode);
-
- event.setName(name);
- } else if (left.equals("id")) { //$NON-NLS-1$
- if (event.idIsSet()) {
- throw new ParseException("id already defined"); //$NON-NLS-1$
- }
-
- long id = getEventID(rightNode);
-
- event.setId(id);
- } else if (left.equals("stream_id")) { //$NON-NLS-1$
- if (event.streamIsSet()) {
- throw new ParseException("stream id already defined"); //$NON-NLS-1$
- }
-
- long streamId = getStreamID(rightNode);
-
- Stream stream = trace.getStream(streamId);
-
- if (stream == null) {
- throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- event.setStream(stream);
- } else if (left.equals("context")) { //$NON-NLS-1$
- if (event.contextIsSet()) {
- throw new ParseException("context already defined"); //$NON-NLS-1$
- }
-
- CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
- if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
- throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
- }
-
- IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier,
- null);
-
- if (!(contextDecl instanceof StructDeclaration)) {
- throw new ParseException("context expects a struct"); //$NON-NLS-1$
- }
-
- event.setContext((StructDeclaration) contextDecl);
- } else if (left.equals("fields")) { //$NON-NLS-1$
- if (event.fieldsIsSet()) {
- throw new ParseException("fields already defined"); //$NON-NLS-1$
- }
-
- CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
- if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
- throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
- }
-
- IDeclaration fieldsDecl;
- fieldsDecl = parseTypeSpecifierList(typeSpecifier, null);
-
- if (!(fieldsDecl instanceof StructDeclaration)) {
- throw new ParseException("fields expects a struct"); //$NON-NLS-1$
- }
- /*
- * The underscores in the event names.
- * These underscores were added by the LTTng tracer.
- */
- final StructDeclaration fields = (StructDeclaration) fieldsDecl;
- event.setFields(fields);
-
- } else {
- throw new ParseException("Unknown event attribute : " + left); //$NON-NLS-1$
- }
- }
-
- /**
- * Parses a declaration at the root level.
- *
- * @param declaration
- * The declaration subtree.
- * @throws ParseException
- */
- private void parseRootDeclaration(CommonTree declaration)
- throws ParseException {
- assert (declaration.getType() == CTFParser.DECLARATION);
-
- List<CommonTree> children = declaration.getChildren();
- assert (children != null);
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPEDEF:
- parseTypedef(child);
- break;
- case CTFParser.TYPEALIAS:
- parseTypealias(child);
- break;
- case CTFParser.TYPE_SPECIFIER_LIST:
- parseTypeSpecifierList(child, null);
- break;
- default:
- childTypeError(child);
- }
- }
- }
-
- /**
- * Parses a typealias node. It parses the target, the alias, and registers
- * the type in the current scope.
- *
- * @param typealias
- * A TYPEALIAS node.
- * @throws ParseException
- */
- private void parseTypealias(CommonTree typealias) throws ParseException {
- assert (typealias.getType() == CTFParser.TYPEALIAS);
-
- List<CommonTree> children = typealias.getChildren();
- assert (children != null);
-
- CommonTree target = null;
- CommonTree alias = null;
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPEALIAS_TARGET:
- assert (target == null);
- target = child;
- break;
- case CTFParser.TYPEALIAS_ALIAS:
- assert (alias == null);
- alias = child;
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- assert (target != null);
- assert (alias != null);
-
- IDeclaration targetDeclaration = parseTypealiasTarget(target);
-
- if (targetDeclaration instanceof VariantDeclaration) {
- if (((VariantDeclaration) targetDeclaration).isTagged()) {
- throw new ParseException(
- "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
- }
- }
-
- String aliasString = parseTypealiasAlias(alias);
-
- getCurrentScope().registerType(aliasString, targetDeclaration);
- }
-
- /**
- * Parses the target part of a typealias and gets the corresponding
- * declaration.
- *
- * @param target
- * A TYPEALIAS_TARGET node.
- * @return The corresponding declaration.
- * @throws ParseException
- */
- private IDeclaration parseTypealiasTarget(CommonTree target)
- throws ParseException {
- assert (target.getType() == CTFParser.TYPEALIAS_TARGET);
-
- List<CommonTree> children = target.getChildren();
- assert (children != null);
-
- CommonTree typeSpecifierList = null;
- CommonTree typeDeclaratorList = null;
- CommonTree typeDeclarator = null;
- StringBuilder identifierSB = new StringBuilder();
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPE_SPECIFIER_LIST:
- assert (typeSpecifierList == null);
- typeSpecifierList = child;
- break;
- case CTFParser.TYPE_DECLARATOR_LIST:
- assert (typeDeclaratorList == null);
- typeDeclaratorList = child;
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- assert (typeSpecifierList != null);
-
- if (typeDeclaratorList != null) {
- /*
- * Only allow one declarator
- *
- * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
- * otherwise the new type puint8_t would maps to two different
- * types.
- */
- if (typeDeclaratorList.getChildCount() != 1) {
- throw new ParseException(
- "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
- }
-
- typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
- }
-
- /* Parse the target type and get the declaration */
- IDeclaration targetDeclaration = parseTypeDeclarator(typeDeclarator,
- typeSpecifierList, identifierSB);
-
- /*
- * We don't allow identifier in the target
- *
- * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
- * permitted
- */
- if (identifierSB.length() > 0) {
- throw new ParseException("Identifier (" + identifierSB.toString() //$NON-NLS-1$
- + ") not expected in the typealias target"); //$NON-NLS-1$
- }
-
- return targetDeclaration;
- }
-
- /**
- * Parses the alias part of a typealias. It parses the underlying specifier
- * list and declarator and creates the string representation that will be
- * used to register the type.
- *
- * @param alias
- * A TYPEALIAS_ALIAS node.
- * @return The string representation of the alias.
- * @throws ParseException
- */
- private static String parseTypealiasAlias(CommonTree alias)
- throws ParseException {
- assert (alias.getType() == CTFParser.TYPEALIAS_ALIAS);
-
- List<CommonTree> children = alias.getChildren();
- assert (children != null);
-
- CommonTree typeSpecifierList = null;
- CommonTree typeDeclaratorList = null;
- CommonTree typeDeclarator = null;
- List<CommonTree> pointers = new LinkedList<CommonTree>();
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.TYPE_SPECIFIER_LIST:
- assert (typeSpecifierList == null);
- typeSpecifierList = child;
- break;
- case CTFParser.TYPE_DECLARATOR_LIST:
- assert (typeDeclaratorList == null);
- typeDeclaratorList = child;
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- /* If there is a type declarator list, extract the pointers */
- if (typeDeclaratorList != null) {
- /*
- * Only allow one declarator
- *
- * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
- */
- if (typeDeclaratorList.getChildCount() != 1) {
- throw new ParseException(
- "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
- }
-
- typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
-
- List<CommonTree> typeDeclaratorChildren = typeDeclarator
- .getChildren();
- assert (typeDeclaratorChildren != null);
-
- for (CommonTree child : typeDeclaratorChildren) {
- switch (child.getType()) {
- case CTFParser.POINTER:
- pointers.add(child);
- break;
- case CTFParser.IDENTIFIER:
- throw new ParseException("Identifier (" + child.getText() //$NON-NLS-1$
- + ") not expected in the typealias target"); //$NON-NLS-1$
- /* break; */
- default:
- childTypeError(child);
- break;
- }
- }
- }
-
- return createTypeDeclarationString(typeSpecifierList, pointers);
- }
-
- /**
- * Parses a typedef node. This creates and registers a new declaration for
- * each declarator found in the typedef.
- *
- * @param typedef
- * A TYPEDEF node.
- * @throws ParseException
- * If there is an error creating the declaration.
- */
- private void parseTypedef(CommonTree typedef) throws ParseException {
- assert (typedef.getType() == CTFParser.TYPEDEF);
-
- CommonTree typeDeclaratorListNode = (CommonTree) typedef
- .getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
- assert (typeDeclaratorListNode != null);
-
- CommonTree typeSpecifierListNode = (CommonTree) typedef
- .getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
- assert (typeSpecifierListNode != null);
-
- List<CommonTree> typeDeclaratorList = typeDeclaratorListNode
- .getChildren();
- assert (typeDeclaratorList != null);
-
- for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
- StringBuilder identifierSB = new StringBuilder();
-
- IDeclaration type_declaration = parseTypeDeclarator(
- typeDeclaratorNode, typeSpecifierListNode, identifierSB);
-
- if (type_declaration instanceof VariantDeclaration) {
- if (((VariantDeclaration) type_declaration).isTagged()) {
- throw new ParseException(
- "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
- }
- }
-
- getCurrentScope().registerType(identifierSB.toString(),
- type_declaration);
- }
- }
-
- /**
- * Parses a pair type declarator / type specifier list and returns the
- * corresponding declaration. If it is present, it also writes the
- * identifier of the declarator in the given {@link StringBuilder}.
- *
- * @param typeDeclarator
- * A TYPE_DECLARATOR node.
- * @param typeSpecifierList
- * A TYPE_SPECIFIER_LIST node.
- * @param identifierSB
- * A StringBuilder that will receive the identifier found in the
- * declarator.
- * @return The corresponding declaration.
- * @throws ParseException
- * If there is an error finding or creating the declaration.
- */
- private IDeclaration parseTypeDeclarator(CommonTree typeDeclarator,
- CommonTree typeSpecifierList, StringBuilder identifierSB)
- throws ParseException {
- if (typeDeclarator != null) {
- assert (typeDeclarator.getType() == CTFParser.TYPE_DECLARATOR);
- }
- assert (typeSpecifierList.getType() == CTFParser.TYPE_SPECIFIER_LIST);
-
- IDeclaration declaration = null;
- List<CommonTree> children = null;
- List<CommonTree> pointers = new LinkedList<CommonTree>();
- List<CommonTree> lengths = new LinkedList<CommonTree>();
- CommonTree identifier = null;
-
- /* Separate the tokens by type */
- if (typeDeclarator != null) {
- children = typeDeclarator.getChildren();
- assert (children != null);
- for (CommonTree child : children) {
-
- switch (child.getType()) {
- case CTFParser.POINTER:
- pointers.add(child);
- break;
- case CTFParser.IDENTIFIER:
- assert (identifier == null);
- identifier = child;
- break;
- case CTFParser.LENGTH:
- lengths.add(child);
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- }
-
- /*
- * Parse the type specifier list, which is the "base" type. For example,
- * it would be int in int a[3][len].
- */
- declaration = parseTypeSpecifierList(typeSpecifierList, pointers);
-
- /*
- * Each length subscript means that we must create a nested array or
- * sequence. For example, int a[3][len] means that we have an array of 3
- * (sequences of length 'len' of (int)).
- */
- if (lengths.size() > 0 ) {
- /* We begin at the end */
- Collections.reverse(lengths);
-
- for (CommonTree length : lengths) {
- /*
- * By looking at the first expression, we can determine whether
- * it is an array or a sequence.
- */
- List<CommonTree> lengthChildren = length.getChildren();
- assert (lengthChildren != null);
-
- CommonTree first = lengthChildren.get(0);
- if (isUnaryInteger(first)) {
- /* Array */
- int arrayLength = (int) parseUnaryInteger(first);
-
- if (arrayLength < 1) {
- throw new ParseException("Array length is negative"); //$NON-NLS-1$
- }
-
- /* Create the array declaration. */
- declaration = new ArrayDeclaration(arrayLength, declaration);
- } else if (isUnaryString(first)) {
- /* Sequence */
- String lengthName = concatenateUnaryStrings(lengthChildren);
-
- /* Create the sequence declaration. */
- declaration = new SequenceDeclaration(lengthName,
- declaration);
- } else {
- childTypeError(first);
- }
- }
- }
-
- if (identifier != null) {
- identifierSB.append(identifier.getText());
- }
-
- return declaration;
- }
-
- /**
- * Parses a type specifier list and returns the corresponding declaration.
- *
- * @param typeSpecifierList
- * A TYPE_SPECIFIER_LIST node.
- * @param pointerList
- * A list of POINTER nodes that apply to the specified type.
- * @return The corresponding declaration.
- * @throws ParseException
- * If the type has not been defined or if there is an error
- * creating the declaration.
- */
- private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList,
- List<CommonTree> pointerList) throws ParseException {
- assert (typeSpecifierList.getType() == CTFParser.TYPE_SPECIFIER_LIST);
- IDeclaration declaration = null;
-
- /*
- * By looking at the first element of the type specifier list, we can
- * determine which type it belongs to.
- */
- CommonTree firstChild = (CommonTree) typeSpecifierList.getChild(0);
- assert (firstChild != null); /* grammar */
-
- switch (firstChild.getType()) {
- case CTFParser.FLOATING_POINT:
- Activator
- .getDefault()
- .log("parseTypeSpecifierList: floating_point not implemented yet"); //$NON-NLS-1$
- break;
- case CTFParser.INTEGER:
- declaration = parseInteger(firstChild);
- break;
- case CTFParser.STRING:
- declaration = parseString(firstChild);
- break;
- case CTFParser.STRUCT:
- declaration = parseStruct(firstChild);
- break;
- case CTFParser.VARIANT:
- declaration = parseVariant(firstChild);
- break;
- case CTFParser.ENUM:
- declaration = parseEnum(firstChild);
- break;
- case CTFParser.IDENTIFIER:
- case CTFParser.FLOATTOK:
- case CTFParser.INTTOK:
- case CTFParser.LONGTOK:
- case CTFParser.SHORTTOK:
- case CTFParser.SIGNEDTOK:
- case CTFParser.UNSIGNEDTOK:
- case CTFParser.CHARTOK:
- case CTFParser.DOUBLETOK:
- case CTFParser.VOIDTOK:
- case CTFParser.BOOLTOK:
- case CTFParser.COMPLEXTOK:
- case CTFParser.IMAGINARYTOK:
- declaration = parseTypeDeclaration(typeSpecifierList, pointerList);
- break;
- default:
- childTypeError(firstChild);
- }
-
- assert (declaration != null);
- return declaration;
- }
-
- /**
- * Parses a type specifier list as a user-declared type.
- *
- * @param typeSpecifierList
- * A TYPE_SPECIFIER_LIST node containing a user-declared type.
- * @param pointerList
- * A list of POINTER nodes that apply to the type specified in
- * typeSpecifierList.
- * @return The corresponding declaration.
- * @throws ParseException
- * If the type does not exist (has not been found).
- */
- private IDeclaration parseTypeDeclaration(CommonTree typeSpecifierList,
- List<CommonTree> pointerList) throws ParseException {
- /* Create the string representation of the type declaration */
- String typeStringRepresentation = createTypeDeclarationString(
- typeSpecifierList, pointerList);
-
- /* Use the string representation to search the type in the current scope */
- IDeclaration decl = getCurrentScope().rlookupType(
- typeStringRepresentation);
-
- if (decl == null) {
- throw new ParseException("Type " + typeStringRepresentation //$NON-NLS-1$
- + " has not been defined."); //$NON-NLS-1$
- }
-
- return decl;
- }
-
- /**
- * Parses an integer declaration node.
- *
- * @param integer
- * An INTEGER node.
- * @return The corresponding integer declaration.
- * @throws ParseException
- */
- private IntegerDeclaration parseInteger(CommonTree integer)
- throws ParseException {
- assert (integer.getType() == CTFParser.INTEGER);
-
- List<CommonTree> children = integer.getChildren();
-
- /*
- * If the integer has no attributes, then it is missing the size
- * attribute which is required
- */
- if (children == null) {
- throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
- }
-
- /* The return value */
- IntegerDeclaration integerDeclaration = null;
- boolean signed = false;
- ByteOrder byteOrder = trace.getByteOrder();
- long size = 0;
- long alignment = 0;
- int base = 10;
- String clock = null;
-
- Encoding encoding = Encoding.NONE;
-
- /* 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
- */
- assert (child.getChildCount() == 2);
-
- CommonTree leftNode = (CommonTree) child.getChild(0);
- assert (leftNode.getType() == CTFParser.CTF_LEFT);
- CommonTree rightNode = (CommonTree) child.getChild(1);
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
-
- List<CommonTree> leftStrings = leftNode.getChildren();
- assert (leftStrings != null);
-
- if (!isUnaryString(leftStrings.get(0))) {
- throw new ParseException(
- "Left side of ctf expression must be a string"); //$NON-NLS-1$
- }
- String left = concatenateUnaryStrings(leftStrings);
-
- if (left.equals("signed")) { //$NON-NLS-1$
- signed = getSigned(rightNode);
- } else if (left.equals("byte_order")) { //$NON-NLS-1$
- byteOrder = getByteOrder(rightNode);
- } else if (left.equals("size")) { //$NON-NLS-1$
- size = getSize(rightNode);
- } else if (left.equals("align")) { //$NON-NLS-1$
- alignment = getAlignment(rightNode);
- } else if (left.equals("base")) { //$NON-NLS-1$
- base = getBase(rightNode);
- } else if (left.equals("encoding")) { //$NON-NLS-1$
- encoding = getEncoding(rightNode);
- } else if (left.equals("map")) { //$NON-NLS-1$
- clock = getClock(rightNode);
- } else {
- throw new ParseException("Integer: unknown attribute " + left); //$NON-NLS-1$
- }
-
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- if (size == 0) {
- throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
- }
-
- if (alignment == 0) {
- if ((size % 8) == 0) {
- alignment = 1;
- } else {
- alignment = 8;
- }
- }
-
- integerDeclaration = new IntegerDeclaration((int) size, signed, base,
- byteOrder, encoding, clock);
-
- assert (integerDeclaration != null);
- return integerDeclaration;
- }
-
- private static String getClock(CommonTree rightNode) {
- return rightNode.getChild(1).getChild(0).getChild(0).getText();
- }
-
- private static StringDeclaration parseString(CommonTree string)
- throws ParseException {
- assert (string.getType() == CTFParser.STRING);
-
- List<CommonTree> children = string.getChildren();
- StringDeclaration stringDeclaration = null;
-
- if (children == null) {
- stringDeclaration = new StringDeclaration();
- } else {
- Encoding encoding = Encoding.UTF8;
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.CTF_EXPRESSION_VAL:
- /*
- * An assignment expression must have 2 children, left and
- * right
- */
- assert (child.getChildCount() == 2);
-
- CommonTree leftNode = (CommonTree) child.getChild(0);
- assert (leftNode.getType() == CTFParser.CTF_LEFT);
- CommonTree rightNode = (CommonTree) child.getChild(1);
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
-
- List<CommonTree> leftStrings = leftNode.getChildren();
- assert (leftStrings != null);
-
- if (!isUnaryString(leftStrings.get(0))) {
- throw new ParseException(
- "Left side of ctf expression must be a string"); //$NON-NLS-1$
- }
- String left = concatenateUnaryStrings(leftStrings);
-
- if (left.equals("encoding")) { //$NON-NLS-1$
- encoding = getEncoding(rightNode);
- } else {
- throw new ParseException("String: unknown attribute " //$NON-NLS-1$
- + left);
- }
-
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- stringDeclaration = new StringDeclaration(encoding);
- }
-
- return stringDeclaration;
- }
-
- /**
- * Parses a struct declaration and returns the corresponding declaration.
- *
- * @param struct
- * An STRUCT node.
- * @return The corresponding struct declaration.
- * @throws ParseException
- */
- private StructDeclaration parseStruct(CommonTree struct)
- throws ParseException {
- assert (struct.getType() == CTFParser.STRUCT);
-
- List<CommonTree> children = struct.getChildren();
- assert (children != null);
-
- /* The return value */
- StructDeclaration structDeclaration = null;
-
- /* Name */
- String structName = null;
- boolean hasName = false;
-
- /* Body */
- CommonTree structBody = null;
- boolean hasBody = false;
-
- /* Align */
- long structAlign = 0;
-
- /* Loop on all children and identify what we have to work with. */
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.STRUCT_NAME: {
- hasName = true;
-
- assert (child.getChildCount() == 1);
- CommonTree structNameIdentifier = (CommonTree) child
- .getChild(0);
-
- assert (structNameIdentifier.getType() == CTFParser.IDENTIFIER);
- structName = structNameIdentifier.getText();
-
- break;
- }
- case CTFParser.STRUCT_BODY: {
- hasBody = true;
-
- structBody = child;
-
- break;
- }
- case CTFParser.ALIGN: {
- assert (child.getChildCount() == 1);
- CommonTree structAlignExpression = (CommonTree) child
- .getChild(0);
-
- structAlign = getAlignment(structAlignExpression);
-
- break;
- }
- default:
- childTypeError(child);
-
- break;
- }
- }
-
- /*
- * If a struct has just a body and no name (just like the song,
- * "A Struct With No Name" by America (sorry for that...)), it's a
- * definition of a new type, so we create the type declaration and
- * return it. We can't add it to the declaration scope since there is no
- * name, but that's what we want because it won't be possible to use it
- * again to declare another field.
- *
- * If it has just a name, we look it up in the declaration scope and
- * return the associated declaration. If it is not found in the
- * declaration scope, it means that a struct with that name has not been
- * declared, which is an error.
- *
- * If it has both, then we create the type declaration and register it
- * to the current scope.
- *
- * If it has none, then what are we doing here ?
- */
- if (hasBody) {
- /*
- * If struct has a name, check if already defined in the current
- * scope.
- */
- if (hasName && (getCurrentScope().lookupStruct(structName) != null)) {
- throw new ParseException("struct " + structName //$NON-NLS-1$
- + " already defined."); //$NON-NLS-1$
- }
-
- /* Create the declaration */
- structDeclaration = new StructDeclaration(structAlign);
-
- /* Parse the body */
- parseStructBody(structBody, structDeclaration);
-
- /* If struct has name, add it to the current scope. */
- if (hasName) {
- getCurrentScope().registerStruct(structName, structDeclaration);
- }
- } else /* !hasBody */{
- if (hasName) {
- /* Name and !body */
-
- /* Lookup the name in the current scope. */
- structDeclaration = getCurrentScope().rlookupStruct(structName);
-
- /*
- * If not found, it means that a struct with such name has not
- * been defined
- */
- if (structDeclaration == null) {
- throw new ParseException("struct " + structName //$NON-NLS-1$
- + " is not defined"); //$NON-NLS-1$
- }
- } else {
- /* !Name and !body */
-
- /* We can't do anything with that. */
- throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
- }
- }
-
- assert (structDeclaration != null);
- return structDeclaration;
- }
-
- /**
- * Parses a struct body, adding the fields to specified structure
- * declaration.
- *
- * @param structBody
- * A STRUCT_BODY node.
- * @param structDeclaration
- * The struct declaration.
- * @throws ParseException
- */
- private void parseStructBody(CommonTree structBody,
- StructDeclaration structDeclaration) throws ParseException {
- assert (structBody.getType() == CTFParser.STRUCT_BODY);
-
- List<CommonTree> structDeclarations = structBody.getChildren();
-
- /*
- * If structDeclaration is null, structBody has no children and the
- * struct body is empty.
- */
- if (structDeclarations != null) {
- pushScope();
-
- for (CommonTree declarationNode : structDeclarations) {
- switch (declarationNode.getType()) {
- case CTFParser.TYPEALIAS:
- parseTypealias(declarationNode);
- break;
- case CTFParser.TYPEDEF:
- parseTypedef(declarationNode);
- break;
- case CTFParser.SV_DECLARATION:
- parseStructDeclaration(declarationNode, structDeclaration);
- break;
- default:
- childTypeError(declarationNode);
- break;
- }
- }
- popScope();
- }
- }
-
- /**
- * Parses a declaration found in a struct.
- *
- * @param declaration
- * A SV_DECLARATION node.
- * @param struct
- * A struct declaration. (I know, little name clash here...)
- * @throws ParseException
- */
- private void parseStructDeclaration(CommonTree declaration,
- StructDeclaration struct) throws ParseException {
- assert (declaration.getType() == CTFParser.SV_DECLARATION);
-
- List<CommonTree> children = declaration.getChildren();
- assert (children != null);
-
- /* Get the type specifier list node */
- CommonTree typeSpecifierListNode = (CommonTree) declaration
- .getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
- assert (typeSpecifierListNode != null);
-
- /* Get the type declarator list node */
- CommonTree typeDeclaratorListNode = (CommonTree) declaration
- .getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
- assert (typeDeclaratorListNode != null);
-
- /* Get the type declarator list */
- List<CommonTree> typeDeclaratorList = typeDeclaratorListNode
- .getChildren();
- assert (typeDeclaratorList != null);
-
- /*
- * For each type declarator, parse the declaration and add a field to
- * the struct
- */
- for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
- assert (typeDeclaratorNode.getType() == CTFParser.TYPE_DECLARATOR);
-
- StringBuilder identifierSB = new StringBuilder();
-
- IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
- typeSpecifierListNode, identifierSB);
- String fieldName = identifierSB.toString();
-
- if (struct.hasField(fieldName)) {
- throw new ParseException("struct: duplicate field " //$NON-NLS-1$
- + fieldName);
- }
-
- struct.addField(fieldName, decl);
-
- }
- }
-
- /**
- * Parses an enum declaration and returns the corresponding declaration.
- *
- * @param _enum
- * An ENUM node.
- * @return The corresponding enum declaration.
- * @throws ParseException
- */
- private EnumDeclaration parseEnum(CommonTree _enum) throws ParseException {
- assert (_enum.getType() == CTFParser.ENUM);
-
- List<CommonTree> children = _enum.getChildren();
- assert (children != null);
-
- /* The return value */
- EnumDeclaration enumDeclaration = null;
-
- /* Name */
- String enumName = null;
-
- /* Body */
- CommonTree enumBody = null;
-
- /* Container type */
- IntegerDeclaration containerTypeDeclaration = null;
-
- /* Loop on all children and identify what we have to work with. */
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.ENUM_NAME: {
- assert (enumName == null);
-
- assert (child.getChildCount() == 1);
- CommonTree enumNameIdentifier = (CommonTree) child.getChild(0);
-
- assert (enumNameIdentifier.getType() == CTFParser.IDENTIFIER);
- enumName = enumNameIdentifier.getText();
-
- break;
- }
- case CTFParser.ENUM_BODY: {
- assert (enumBody == null);
-
- enumBody = child;
-
- break;
- }
- case CTFParser.ENUM_CONTAINER_TYPE: {
- assert (containerTypeDeclaration == null);
-
- containerTypeDeclaration = parseEnumContainerType(child);
-
- break;
- }
- default:
- childTypeError(child);
- break;
- }
- }
-
- /*
- * If the container type has not been defined explicitly, we assume it
- * is "int".
- */
- if (containerTypeDeclaration == null) {
- IDeclaration decl = getCurrentScope().rlookupType("int"); //$NON-NLS-1$
-
- if (decl == null) {
- throw new ParseException(
- "enum container type implicit and type int not defined"); //$NON-NLS-1$
- } else if (!(decl instanceof IntegerDeclaration)) {
- throw new ParseException(
- "enum container type implicit and type int not an integer"); //$NON-NLS-1$
- }
-
- containerTypeDeclaration = (IntegerDeclaration) decl;
- }
-
- /*
- * If it has a body, it's a new declaration, otherwise it's a reference
- * to an existing declaration. Same logic as struct.
- */
- if (enumBody != null) {
- /*
- * If enum has a name, check if already defined in the current
- * scope.
- */
- if ((enumName != null)
- && (getCurrentScope().lookupEnum(enumName) != null)) {
- throw new ParseException("enum " + enumName //$NON-NLS-1$
- + " already defined"); //$NON-NLS-1$
- }
-
- /* Create the declaration */
- enumDeclaration = new EnumDeclaration(containerTypeDeclaration);
-
- /* Parse the body */
- parseEnumBody(enumBody, enumDeclaration);
-
- /* If the enum has name, add it to the current scope. */
- if (enumName != null) {
- getCurrentScope().registerEnum(enumName, enumDeclaration);
- }
- } else {
- if (enumName != null) {
- /* Name and !body */
-
- /* Lookup the name in the current scope. */
- enumDeclaration = getCurrentScope().rlookupEnum(enumName);
-
- /*
- * If not found, it means that an enum with such name has not
- * been defined
- */
- if (enumDeclaration == null) {
- throw new ParseException("enum " + enumName //$NON-NLS-1$
- + " is not defined"); //$NON-NLS-1$
- }
- } else {
- /* !Name and !body */
- throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
- }
- }
-
- return enumDeclaration;
-
- }
-
- /**
- * Parses an enum body, adding the enumerators to the specified enum
- * declaration.
- *
- * @param enumBody
- * An ENUM_BODY node.
- * @param enumDeclaration
- * The enum declaration.
- * @throws ParseException
- */
- private void parseEnumBody(CommonTree enumBody,
- EnumDeclaration enumDeclaration) throws ParseException {
- assert (enumBody.getType() == CTFParser.ENUM_BODY);
-
- List<CommonTree> enumerators = enumBody.getChildren();
- /* enum body can't be empty (unlike struct). */
- assert (enumerators != null);
-
- pushScope();
-
- /*
- * Start at -1, so that if the first enumrator has no explicit value, it
- * will choose 0
- */
- long lastHigh = -1;
-
- for (CommonTree enumerator : enumerators) {
- lastHigh = parseEnumEnumerator(enumerator, enumDeclaration,
- lastHigh);
- }
-
- popScope();
-
- }
-
- /**
- * Parses an enumerator node and adds an enumerator declaration to an
- * enumeration declaration.
- *
- * The high value of the range of the last enumerator is needed in case the
- * current enumerator does not specify its value.
- *
- * @param enumerator
- * An ENUM_ENUMERATOR node.
- * @param enumDeclaration
- * en enumeration declaration to which will be added the
- * enumerator.
- * @param lastHigh
- * The high value of the range of the last enumerator
- * @return The high value of the value range of the current enumerator.
- * @throws ParseException
- */
- private static long parseEnumEnumerator(CommonTree enumerator,
- EnumDeclaration enumDeclaration, long lastHigh)
- throws ParseException {
- assert (enumerator.getType() == CTFParser.ENUM_ENUMERATOR);
-
- List<CommonTree> children = enumerator.getChildren();
- assert (children != null);
-
- long low = 0, high = 0;
- boolean valueSpecified = false;
- String label = null;
-
- for (CommonTree child : children) {
- if (isUnaryString(child)) {
- label = parseUnaryString(child);
- } else if (child.getType() == CTFParser.ENUM_VALUE) {
- assert (child.getChildCount() == 1);
- assert (isUnaryInteger((CommonTree) child.getChild(0)));
-
- valueSpecified = true;
-
- low = parseUnaryInteger((CommonTree) child.getChild(0));
- high = low;
- } else if (child.getType() == CTFParser.ENUM_VALUE_RANGE) {
- assert (child.getChildCount() == 2);
- assert (isUnaryInteger((CommonTree) child.getChild(0)));
- assert (isUnaryInteger((CommonTree) child.getChild(1)));
-
- valueSpecified = true;
-
- low = parseUnaryInteger((CommonTree) child.getChild(0));
- high = parseUnaryInteger((CommonTree) child.getChild(1));
- } else {
- childTypeError(child);
- }
- }
-
- assert (label != null);
-
- if (!valueSpecified) {
- low = lastHigh + 1;
- high = low;
- }
-
- if (low > high) {
- throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
- }
-
- if (!enumDeclaration.add(low, high, label)) {
- throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
- }
-
- return high;
- }
-
- /**
- * Parses an enum container type node and returns the corresponding integer
- * type.
- *
- * @param enumContainerType
- * An ENUM_CONTAINER_TYPE node.
- * @return An integer declaration corresponding to the container type.
- * @throws ParseException
- * If the type does not parse correctly or if it is not an
- * integer type.
- */
- private IntegerDeclaration parseEnumContainerType(
- CommonTree enumContainerType) throws ParseException {
- assert (enumContainerType.getType() == CTFParser.ENUM_CONTAINER_TYPE);
-
- /* Get the child, which should be a type specifier list */
- assert (enumContainerType.getChildCount() == 1);
- CommonTree typeSpecifierList = (CommonTree) enumContainerType
- .getChild(0);
-
- /* Parse it and get the corresponding declaration */
- IDeclaration decl = parseTypeSpecifierList(typeSpecifierList, null);
-
- /* If is is an integer, return it, else throw an error */
- if (decl instanceof IntegerDeclaration) {
- return (IntegerDeclaration) decl;
- }
- throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
- }
-
- private VariantDeclaration parseVariant(CommonTree variant)
- throws ParseException {
- assert (variant.getType() == CTFParser.VARIANT);
-
- List<CommonTree> children = variant.getChildren();
- VariantDeclaration variantDeclaration = null;
-
- boolean hasName = false;
- String variantName = null;
-
- boolean hasBody = false;
- CommonTree variantBody = null;
-
- boolean hasTag = false;
- String variantTag = null;
-
- for (CommonTree child : children) {
- switch (child.getType()) {
- case CTFParser.VARIANT_NAME:
- assert (variantName == null);
-
- hasName = true;
-
- assert (child.getChildCount() == 1);
- CommonTree variantNameIdentifier = (CommonTree) child
- .getChild(0);
-
- assert (variantNameIdentifier.getType() == CTFParser.IDENTIFIER);
- variantName = variantNameIdentifier.getText();
-
- break;
- case CTFParser.VARIANT_TAG:
- assert (variantTag == null);
-
- hasTag = true;
-
- assert (child.getChildCount() == 1);
- CommonTree variantTagIdentifier = (CommonTree) child
- .getChild(0);
-
- assert (variantTagIdentifier.getType() == CTFParser.IDENTIFIER);
- variantTag = variantTagIdentifier.getText();
-
- break;
- case CTFParser.VARIANT_BODY:
- assert (variantBody == null);
-
- hasBody = true;
-
- variantBody = child;
-
- break;
- default:
- childTypeError(child);
- break;
- }
- }
-
- if (hasBody) {
- /*
- * If variant has a name, check if already defined in the current
- * scope.
- */
- if (hasName
- && (getCurrentScope().lookupVariant(variantName) != null)) {
- throw new ParseException("variant " + variantName //$NON-NLS-1$
- + " already defined."); //$NON-NLS-1$
- }
-
- /* Create the declaration */
- variantDeclaration = new VariantDeclaration();
-
- /* Parse the body */
- parseVariantBody(variantBody, variantDeclaration);
-
- /* If variant has name, add it to the current scope. */
- if (hasName) {
- getCurrentScope().registerVariant(variantName,
- variantDeclaration);
- }
- } else /* !hasBody */{
- if (hasName) {
- /* Name and !body */
-
- /* Lookup the name in the current scope. */
- variantDeclaration = getCurrentScope().rlookupVariant(
- variantName);
-
- /*
- * If not found, it means that a struct with such name has not
- * been defined
- */
- if (variantDeclaration == null) {
- throw new ParseException("variant " + variantName //$NON-NLS-1$
- + " is not defined"); //$NON-NLS-1$
- }
- } else {
- /* !Name and !body */
-
- /* We can't do anything with that. */
- throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
- }
- }
-
- if (hasTag) {
- variantDeclaration.setTag(variantTag);
- }
-
- assert (variantDeclaration != null);
- return variantDeclaration;
- }
-
- private void parseVariantBody(CommonTree variantBody,
- VariantDeclaration variantDeclaration) throws ParseException {
- assert (variantBody.getType() == CTFParser.VARIANT_BODY);
-
- List<CommonTree> variantDeclarations = variantBody.getChildren();
- assert (variantDeclarations != null);
-
- pushScope();
-
- for (CommonTree declarationNode : variantDeclarations) {
- switch (declarationNode.getType()) {
- case CTFParser.TYPEALIAS:
- parseTypealias(declarationNode);
- break;
- case CTFParser.TYPEDEF:
- parseTypedef(declarationNode);
- break;
- case CTFParser.SV_DECLARATION:
- parseVariantDeclaration(declarationNode, variantDeclaration);
- break;
- default:
- childTypeError(declarationNode);
- break;
- }
- }
-
- popScope();
- }
-
- private void parseVariantDeclaration(CommonTree declaration,
- VariantDeclaration variant) throws ParseException {
- assert (declaration.getType() == CTFParser.SV_DECLARATION);
-
- List<CommonTree> children = declaration.getChildren();
- assert (children != null);
-
- /* Get the type specifier list node */
- CommonTree typeSpecifierListNode = (CommonTree) declaration
- .getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
- assert (typeSpecifierListNode != null);
-
- /* Get the type declarator list node */
- CommonTree typeDeclaratorListNode = (CommonTree) declaration
- .getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
- assert (typeDeclaratorListNode != null);
-
- /* Get the type declarator list */
- List<CommonTree> typeDeclaratorList = typeDeclaratorListNode
- .getChildren();
- assert (typeDeclaratorList != null);
-
- /*
- * For each type declarator, parse the declaration and add a field to
- * the variant
- */
- for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
- assert (typeDeclaratorNode.getType() == CTFParser.TYPE_DECLARATOR);
-
- StringBuilder identifierSB = new StringBuilder();
-
- IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
- typeSpecifierListNode, identifierSB);
-
- if (variant.hasField(identifierSB.toString())) {
- throw new ParseException("variant: duplicate field " //$NON-NLS-1$
- + identifierSB.toString());
- }
-
- variant.addField(identifierSB.toString(), decl);
- }
- }
-
- /**
- * Creates the string representation of a type declaration (type specifier
- * list + pointers).
- *
- * @param typeSpecifierList
- * A TYPE_SPECIFIER_LIST node.
- * @param pointers
- * A list of POINTER nodes.
- * @return The string representation.
- * @throws ParseException
- */
- private static String createTypeDeclarationString(
- CommonTree typeSpecifierList, List<CommonTree> pointers)
- throws ParseException {
- StringBuilder sb = new StringBuilder();
-
- createTypeSpecifierListString(typeSpecifierList, sb);
- createPointerListString(pointers, sb);
-
- return sb.toString();
- }
-
- /**
- * Creates the string representation of a list of type specifiers.
- *
- * @param typeSpecifierList
- * A TYPE_SPECIFIER_LIST node.
- * @param sb
- * A StringBuilder to which will be appended the string.
- * @throws ParseException
- */
- private static void createTypeSpecifierListString(
- CommonTree typeSpecifierList, StringBuilder sb)
- throws ParseException {
- assert (typeSpecifierList.getType() == CTFParser.TYPE_SPECIFIER_LIST);
-
- List<CommonTree> children = typeSpecifierList.getChildren();
- assert (children != null);
-
- boolean firstItem = true;
-
- for (CommonTree child : children) {
- if (!firstItem) {
- sb.append(' ');
-
- }
-
- firstItem = false;
-
- /* Append the string that represents this type specifier. */
- createTypeSpecifierString(child, sb);
- }
- }
-
- /**
- * Creates the string representation of a type specifier.
- *
- * @param typeSpecifier
- * A TYPE_SPECIFIER node.
- * @param sb
- * A StringBuilder to which will be appended the string.
- * @throws ParseException
- */
- private static void createTypeSpecifierString(CommonTree typeSpecifier,
- StringBuilder sb) throws ParseException {
- switch (typeSpecifier.getType()) {
- case CTFParser.FLOATTOK:
- case CTFParser.INTTOK:
- case CTFParser.LONGTOK:
- case CTFParser.SHORTTOK:
- case CTFParser.SIGNEDTOK:
- case CTFParser.UNSIGNEDTOK:
- case CTFParser.CHARTOK:
- case CTFParser.DOUBLETOK:
- case CTFParser.VOIDTOK:
- case CTFParser.BOOLTOK:
- case CTFParser.COMPLEXTOK:
- case CTFParser.IMAGINARYTOK:
- case CTFParser.CONSTTOK:
- case CTFParser.IDENTIFIER:
- sb.append(typeSpecifier.getText());
- break;
- case CTFParser.STRUCT: {
- CommonTree structName = (CommonTree) typeSpecifier
- .getFirstChildWithType(CTFParser.STRUCT_NAME);
- if (structName == null) {
- throw new ParseException(
- "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
- }
- assert (structName.getChildCount() == 1);
-
- CommonTree structNameIdentifier = (CommonTree) structName
- .getChild(0);
- assert (structNameIdentifier.getType() == CTFParser.IDENTIFIER);
-
- sb.append(structNameIdentifier.getText());
- break;
- }
- case CTFParser.VARIANT: {
- CommonTree variantName = (CommonTree) typeSpecifier
- .getFirstChildWithType(CTFParser.VARIANT_NAME);
- if (variantName == null) {
- throw new ParseException(
- "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
- }
- assert (variantName.getChildCount() == 1);
-
- CommonTree variantNameIdentifier = (CommonTree) variantName
- .getChild(0);
- assert (variantNameIdentifier.getType() == CTFParser.IDENTIFIER);
-
- sb.append(variantNameIdentifier.getText());
- break;
- }
- case CTFParser.ENUM: {
- CommonTree enumName = (CommonTree) typeSpecifier
- .getFirstChildWithType(CTFParser.ENUM_NAME);
- if (enumName == null) {
- throw new ParseException(
- "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
- }
- assert (enumName.getChildCount() == 1);
-
- CommonTree enumNameIdentifier = (CommonTree) enumName.getChild(0);
- assert (enumNameIdentifier.getType() == CTFParser.IDENTIFIER);
-
- sb.append(enumNameIdentifier.getText());
- break;
- }
- case CTFParser.FLOATING_POINT:
- case CTFParser.INTEGER:
- case CTFParser.STRING:
- throw new ParseException(
- "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
- /* break; */
- default:
- childTypeError(typeSpecifier);
- break;
- }
- }
-
- /**
- * Creates the string representation of a list of pointers.
- *
- * @param pointerList
- * A list of pointer nodes. If pointerList is null, this function
- * does nothing.
- * @param sb
- * A stringbuilder to which will be appended the string.
- */
- private static void createPointerListString(List<CommonTree> pointerList,
- StringBuilder sb) {
- if (pointerList == null) {
- return;
- }
-
- for (CommonTree pointer : pointerList) {
- assert (pointer.getType() == CTFParser.POINTER);
-
- sb.append(" *"); //$NON-NLS-1$
- if (pointer.getChildCount() > 0) {
- assert (pointer.getChildCount() == 1);
- CommonTree constQualifier = (CommonTree) pointer.getChild(0);
- assert (constQualifier.getType() == CTFParser.CONSTTOK);
-
- sb.append(" const"); //$NON-NLS-1$
- }
- }
- }
-
- /**
- * @param node
- * The node to check.
- * @return True if the given node is an unary string or unary integer.
- */
- private static boolean isUnaryExpression(CommonTree node) {
- return isUnaryInteger(node) || isUnaryString(node);
- }
-
- /**
- * @param node
- * The node to check.
- * @return True if the given node is an unary string.
- */
- private static boolean isUnaryString(CommonTree node) {
- return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING) || (node
- .getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES));
- }
-
- /**
- * @param node
- * The node to check.
- * @return True if the given node is an unary integer.
- */
- private static boolean isUnaryInteger(CommonTree node) {
- return ((node.getType() == CTFParser.UNARY_EXPRESSION_DEC)
- || (node.getType() == CTFParser.UNARY_EXPRESSION_HEX) || (node
- .getType() == CTFParser.UNARY_EXPRESSION_OCT));
- }
-
- /**
- * Parses a unary string node and return the string value.
- *
- * @param unaryString
- * The unary string node to parse (type UNARY_EXPRESSION_STRING
- * or UNARY_EXPRESSION_STRING_QUOTES).
- * @return The string value.
- */
- /*
- * It would be really nice to remove the quotes earlier, such as in the
- * parser.
- */
- private static String parseUnaryString(CommonTree unaryString) {
- assert (isUnaryString(unaryString));
-
- assert (unaryString.getChildCount() == 1);
- CommonTree value = (CommonTree) unaryString.getChild(0);
- assert (value != null);
- String strval = value.getText();
-
- /* Remove quotes */
- if (unaryString.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES) {
- strval = strval.substring(1, strval.length() - 1);
- }
-
- return strval;
- }
-
- /**
- * Parses an unary integer (dec, hex or oct).
- *
- * @param unaryInteger
- * An unary integer node.
- * @return The integer value.
- */
- private static long parseUnaryInteger(CommonTree unaryInteger) {
- assert (isUnaryInteger(unaryInteger));
-
- assert (unaryInteger.getChildCount() >= 1);
-
- List<CommonTree> children = unaryInteger.getChildren();
- CommonTree value = children.get(0);
- String strval = value.getText();
-
- long intval;
-
- if (unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_DEC) {
- intval = Long.parseLong(strval, 10);
- } else if (unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_HEX) {
- intval = Long.parseLong(strval, 0x10);
- } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
- intval = Long.parseLong(strval, 010); // 010 == 0x08 == 8
- }
-
- /* The rest of children are sign */
- if ((children.size() % 2) == 0) {
- return -intval;
- }
- return intval;
- }
-
- private static long getMajorOrMinor(CommonTree rightNode)
- throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryInteger(firstChild)) {
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
- }
-
- long m = parseUnaryInteger(firstChild);
-
- if (m < 0) {
- throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
- }
-
- return m;
- }
- throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
- }
-
- private static UUID getUUID(CommonTree rightNode) throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryString(firstChild)) {
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
- }
-
- String uuidstr = parseUnaryString(firstChild);
-
- try {
- UUID uuid = UUID.fromString(uuidstr);
- return uuid;
- } catch (IllegalArgumentException e) {
- throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
- }
- }
- throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
- }
-
- /**
- * Gets the value of a "signed" integer attribute.
- *
- * @param rightNode
- * A CTF_RIGHT node.
- * @return The "signed" value as a boolean.
- * @throws ParseException
- */
- private static boolean getSigned(CommonTree rightNode)
- throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- boolean ret = false;
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryString(firstChild)) {
- String strval = concatenateUnaryStrings(rightNode.getChildren());
-
- if (strval.equals("true") || strval.equals("TRUE")) { //$NON-NLS-1$ //$NON-NLS-2$
- ret = true;
- } else if (strval.equals("false") || strval.equals("FALSE")) { //$NON-NLS-1$ //$NON-NLS-2$
- ret = false;
- } else {
- throw new ParseException("Invalid boolean value " //$NON-NLS-1$
- + firstChild.getChild(0).getText());
- }
- } else if (isUnaryInteger(firstChild)) {
- /* Happens if the value is something like "1234.hello" */
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
- }
-
- long intval = parseUnaryInteger(firstChild);
-
- if (intval == 1) {
- ret = true;
- } else if (intval == 0) {
- ret = false;
- } else {
- throw new ParseException("Invalid boolean value " //$NON-NLS-1$
- + firstChild.getChild(0).getText());
- }
- } else {
- throw new ParseException();
- }
-
- return ret;
- }
-
- /**
- * Gets the value of a "byte_order" integer attribute.
- *
- * @param rightNode
- * A CTF_RIGHT node.
- * @return The "byte_order" value.
- * @throws ParseException
- */
- private ByteOrder getByteOrder(CommonTree rightNode) throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryString(firstChild)) {
- String strval = concatenateUnaryStrings(rightNode.getChildren());
-
- if (strval.equals("le")) { //$NON-NLS-1$
- return ByteOrder.LITTLE_ENDIAN;
- } else if (strval.equals("be") || strval.equals("network")) { //$NON-NLS-1$ //$NON-NLS-2$
- return ByteOrder.BIG_ENDIAN;
- } else if (strval.equals("native")) { //$NON-NLS-1$
- return trace.getByteOrder();
- } else {
- throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
- }
- }
- throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
- }
-
- /**
- * Determines if the given value is a valid alignment value.
- *
- * @param alignment
- * The value to check.
- * @return True if it is valid.
- */
- private static boolean isValidAlignment(long alignment) {
- return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
- }
-
- /**
- * Gets the value of a "size" integer attribute.
- *
- * @param rightNode
- * A CTF_RIGHT node.
- * @return The "size" value.
- * @throws ParseException
- */
- private static long getSize(CommonTree rightNode) throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryInteger(firstChild)) {
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("Invalid value for size"); //$NON-NLS-1$
- }
-
- long size = parseUnaryInteger(firstChild);
-
- if (size < 1) {
- throw new ParseException("Invalid value for size"); //$NON-NLS-1$
- }
-
- return size;
- }
- throw new ParseException("Invalid value for size"); //$NON-NLS-1$
- }
-
- /**
- * Gets the value of a "align" integer or struct attribute.
- *
- * @param node
- * A CTF_RIGHT node or directly an unary integer.
- * @return The align value.
- * @throws ParseException
- */
- private static long getAlignment(CommonTree node) throws ParseException {
- assert (isUnaryExpression(node) || (node.getType() == CTFParser.CTF_RIGHT));
-
- /*
- * If a CTF_RIGHT node was passed, call getAlignment with the first
- * child
- */
- if (node.getType() == CTFParser.CTF_RIGHT) {
- if (node.getChildCount() > 1) {
- throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
- }
-
- return getAlignment((CommonTree) node.getChild(0));
- } else if (isUnaryInteger(node)) {
- long alignment = parseUnaryInteger(node);
-
- if (!isValidAlignment(alignment)) {
- throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
- + alignment);
- }
-
- return alignment;
- }
- throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
- }
-
- /**
- * Gets the value of a "base" integer attribute.
- *
- * @param rightNode
- * An CTF_RIGHT node.
- * @return The "base" value.
- * @throws ParseException
- */
- private static int getBase(CommonTree rightNode) throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryInteger(firstChild)) {
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("invalid base value"); //$NON-NLS-1$
- }
-
- long intval = parseUnaryInteger(firstChild);
- if ((intval == 2) || (intval == 8) || (intval == 10)
- || (intval == 16)) {
- return (int) intval;
- }
- throw new ParseException("Invalid value for base"); //$NON-NLS-1$
- } else if (isUnaryString(firstChild)) {
- String strval = concatenateUnaryStrings(rightNode.getChildren());
-
- if (strval.equals("decimal") || strval.equals("dec") //$NON-NLS-1$ //$NON-NLS-2$
- || strval.equals("d") || strval.equals("i") //$NON-NLS-1$ //$NON-NLS-2$
- || strval.equals("u")) { //$NON-NLS-1$
- return 10;
- } else if (strval.equals("hexadecimal") || strval.equals("hex") //$NON-NLS-1$ //$NON-NLS-2$
- || strval.equals("x") || strval.equals("X") //$NON-NLS-1$ //$NON-NLS-2$
- || strval.equals("p")) { //$NON-NLS-1$
- return 16;
- } else if (strval.equals("octal") || strval.equals("oct") //$NON-NLS-1$ //$NON-NLS-2$
- || strval.equals("o")) { //$NON-NLS-1$
- return 8;
- } else if (strval.equals("binary") || strval.equals("b")) { //$NON-NLS-1$ //$NON-NLS-2$
- return 2;
- } else {
- throw new ParseException("Invalid value for base"); //$NON-NLS-1$
- }
- } else {
- throw new ParseException("invalid value for base"); //$NON-NLS-1$
- }
- }
-
- /**
- * Gets the value of an "encoding" integer attribute.
- *
- * @param rightNode
- * A CTF_RIGHT node.
- * @return The "encoding" value.
- * @throws ParseException
- */
- private static Encoding getEncoding(CommonTree rightNode)
- throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryString(firstChild)) {
- String strval = concatenateUnaryStrings(rightNode.getChildren());
-
- if (strval.equals("UTF8")) { //$NON-NLS-1$
- return Encoding.UTF8;
- } else if (strval.equals("ASCII")) { //$NON-NLS-1$
- return Encoding.ASCII;
- } else if (strval.equals("none")) { //$NON-NLS-1$
- return Encoding.NONE;
- } else {
- throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
- }
- }
- throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
- }
-
- private static long getStreamID(CommonTree rightNode) throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryInteger(firstChild)) {
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
- }
-
- long intval = parseUnaryInteger(firstChild);
-
- return intval;
- }
- throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
- }
-
- private static String getEventName(CommonTree rightNode)
- throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryString(firstChild)) {
- String str = concatenateUnaryStrings(rightNode.getChildren());
-
- return str;
- }
- throw new ParseException("invalid value for event name"); //$NON-NLS-1$
- }
-
- private static long getEventID(CommonTree rightNode) throws ParseException {
- assert (rightNode.getType() == CTFParser.CTF_RIGHT);
- assert (rightNode.getChildCount() > 0);
-
- CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
- if (isUnaryInteger(firstChild)) {
- if (rightNode.getChildCount() > 1) {
- throw new ParseException("invalid value for event id"); //$NON-NLS-1$
- }
-
- long intval = parseUnaryInteger(firstChild);
-
- return intval;
- }
- throw new ParseException("invalid value for event id"); //$NON-NLS-1$
- }
-
- /**
- * Concatenates a list of unary strings separated by arrows (->) or dots.
- *
- * @param strings
- * A list, first element being an unary string, subsequent
- * elements being ARROW or DOT nodes with unary strings as child.
- * @return The string representation of the unary string chain.
- */
- private static String concatenateUnaryStrings(List<CommonTree> strings) {
- assert ((strings != null) && (strings.size() > 0));
-
- StringBuilder sb = new StringBuilder();
-
- CommonTree first = strings.get(0);
- sb.append(parseUnaryString(first));
-
- boolean isFirst = true;
-
- for (CommonTree ref : strings) {
- if (isFirst) {
- isFirst = false;
- continue;
- }
-
- assert ((ref.getType() == CTFParser.ARROW) || (ref.getType() == CTFParser.DOT));
- assert (ref.getChildCount() == 1);
-
- CommonTree id = (CommonTree) ref.getChild(0);
-
- if (ref.getType() == CTFParser.ARROW) {
- sb.append("->"); //$NON-NLS-1$
- } else { /* DOT */
- sb.append('.');
- }
-
- sb.append(parseUnaryString(id));
- }
-
- return sb.toString();
- }
-
- /**
- * Throws a ParseException stating that the parent-child relation between
- * the given node and its parent is not valid. It means that the shape of
- * the AST is unexpected.
- *
- * @param child
- * The invalid child node.
- * @throws ParseException
- */
- private static void childTypeError(CommonTree child) throws ParseException {
- CommonTree parent = (CommonTree) child.getParent();
- String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
- + " can't have a child of type " //$NON-NLS-1$
- + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
-
- throw new ParseException(error);
- }
-
- // ------------------------------------------------------------------------
- // Scope management
- // ------------------------------------------------------------------------
-
- /**
- * Adds a new declaration scope on the top of the scope stack.
- */
- private void pushScope() {
- scope = new DeclarationScope(scope);
- }
-
- /**
- * Removes the top declaration scope from the scope stack.
- */
- private void popScope() {
- assert (scope != null);
- scope = scope.getParentScope();
- }
-
- /**
- * Returns the current declaration scope.
- *
- * @return The current declaration scope.
- */
- private DeclarationScope getCurrentScope() {
- assert (scope != null);
- return scope;
- }
-
-}
package org.eclipse.linuxtools.ctf.core.event.types;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>ArrayDefinition</u></b>
package org.eclipse.linuxtools.ctf.core.event.types;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>Definition</u></b>
package org.eclipse.linuxtools.ctf.core.event.types;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>EnumDefinition</u></b>
package org.eclipse.linuxtools.ctf.core.event.types;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>IntegerDefinition</u></b>
package org.eclipse.linuxtools.ctf.core.event.types;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>SequenceDefinition</u></b>
package org.eclipse.linuxtools.ctf.core.event.types;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>StringDefinition</u></b>
import java.util.HashMap;
import java.util.ListIterator;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>StructDefinition</u></b>
import java.util.HashMap;
import java.util.Map;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>VariantDefinition</u></b>
import java.util.UUID;
import org.eclipse.linuxtools.ctf.core.event.CTFClock;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.metadata.exceptions.ParseException;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
import org.eclipse.linuxtools.internal.ctf.core.Activator;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
/**
* <b><u>CTFTrace</u></b>
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
import org.eclipse.linuxtools.internal.ctf.core.Activator;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
/**
* Reads the events of a trace.
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTree;
-import org.eclipse.linuxtools.ctf.core.event.metadata.IOStructGen;
import org.eclipse.linuxtools.ctf.core.event.metadata.exceptions.ParseException;
import org.eclipse.linuxtools.ctf.parser.CTFLexer;
import org.eclipse.linuxtools.ctf.parser.CTFParser;
import org.eclipse.linuxtools.ctf.parser.CTFParser.parse_return;
+import org.eclipse.linuxtools.internal.ctf.core.event.metadata.IOStructGen;
/**
* <b><u>Metadata</u></b>
import java.nio.channels.FileChannel.MapMode;
import java.util.UUID;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
/**
* <b><u>StreamInput</u></b>
import java.util.ListIterator;
import java.util.Vector;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
+
/**
* <b><u>StreamInputPacketIndex</u></b>
* <p>
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
- *
- * All rights reserved. This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Matthew Khouzam - Initial API and implementation
- * Contributors: Simon Marchi - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.linuxtools.ctf.core.trace;
-
-/**
- * <b><u>StreamInputPacketIndexEntry</u></b>
- * <p>
- * Represents an entry in the index of event packets.
- */
-public class StreamInputPacketIndexEntry {
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
-
-
- /**
- * Offset of the packet in the file, in bytes
- */
- final private long offsetBytes;
-
- /**
- * Offset of the data in the packet, in bits
- */
- private int dataOffsetBits = 0;
-
- /**
- * Packet size, in bits
- */
- private int packetSizeBits = 0;
-
- /**
- * Content size, in bits
- */
- private int contentSizeBits = 0;
-
- /**
- * Begin timestamp
- */
- private long timestampBegin = 0;
-
- /**
- * End timestamp
- */
- private long timestampEnd = 0;
-
-
- private long indexBegin = Long.MAX_VALUE;
-
- private long indexEnd = Long.MAX_VALUE;
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructs an index entry.
- *
- * @param offset
- * The offset of the packet in the file, in bytes.
- */
-
- public StreamInputPacketIndexEntry(long offset) {
- this.offsetBytes = offset;
- }
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- /**
- * Returns whether the packet includes (inclusively) the given timestamp in
- * the begin-end timestamp range.
- *
- * @param ts
- * The timestamp to check.
- * @return True if the packet includes the timestamp.
- */
- boolean includes(long ts) {
- return (ts >= timestampBegin) && (ts <= timestampEnd);
- }
-
- boolean includesIndex(long index){
- return (index >= indexBegin) && (index <= indexEnd);
- }
- /* (non-Javadoc)
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return "StreamInputPacketIndexEntry [offsetBytes=" + offsetBytes //$NON-NLS-1$
- + ", timestampBegin=" + timestampBegin + ", timestampEnd=" //$NON-NLS-1$ //$NON-NLS-2$
- + timestampEnd + ", indexBegin=" + indexBegin + ", indexEnd=" //$NON-NLS-1$ //$NON-NLS-2$
- + indexEnd + "]"; //$NON-NLS-1$
- }
-
- // ------------------------------------------------------------------------
- // Getters and Setters
- // ------------------------------------------------------------------------
-
- /**
- * @return the offsetBytes
- */
- public long getOffsetBytes() {
- return offsetBytes;
- }
-
- /**
- * @return the dataOffsetBits
- */
- public int getDataOffsetBits() {
- return dataOffsetBits;
- }
-
- /**
- * @param dataOffsetBits the dataOffsetBits to set
- */
- public void setDataOffsetBits(int dataOffsetBits) {
- this.dataOffsetBits = dataOffsetBits;
- }
-
- /**
- * @return the packetSizeBits
- */
- public int getPacketSizeBits() {
- return packetSizeBits;
- }
-
- /**
- * @param packetSizeBits the packetSizeBits to set
- */
- public void setPacketSizeBits(int packetSizeBits) {
- this.packetSizeBits = packetSizeBits;
- }
-
- /**
- * @return the contentSizeBits
- */
- public int getContentSizeBits() {
- return contentSizeBits;
- }
-
- /**
- * @param contentSizeBits the contentSizeBits to set
- */
- public void setContentSizeBits(int contentSizeBits) {
- this.contentSizeBits = contentSizeBits;
- }
-
- /**
- * @return the timestampBegin
- */
- public long getTimestampBegin() {
- return timestampBegin;
- }
-
- /**
- * @param timestampBegin the timestampBegin to set
- */
- public void setTimestampBegin(long timestampBegin) {
- this.timestampBegin = timestampBegin;
- }
-
- /**
- * @return the timestampEnd
- */
- public long getTimestampEnd() {
- return timestampEnd;
- }
-
- /**
- * @param timestampEnd the timestampEnd to set
- */
- public void setTimestampEnd(long timestampEnd) {
- this.timestampEnd = timestampEnd;
- }
-
- /**
- * @return the indexBegin
- */
- public long getIndexBegin() {
- return indexBegin;
- }
-
- /**
- * @param indexBegin the indexBegin to set
- */
- public void setIndexBegin(long indexBegin) {
- this.indexBegin = indexBegin;
- }
-
- /**
- * @return the indexEnd
- */
- public long getIndexEnd() {
- return indexEnd;
- }
-
- /**
- * @param indexEnd the indexEnd to set
- */
- public void setIndexEnd(long indexEnd) {
- this.indexEnd = indexEnd;
- }
-}
import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
-import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
+import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
/**
* <b><u>StreamInputPacketReader</u></b>
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
/**
* <b><u>StreamInputReader</u></b>
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
- *
- * All rights reserved. This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Matthew Khouzam - Initial API and implementation
- * Contributors: Simon Marchi - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.linuxtools.ctf.core.trace;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * <b><u>StreamInputReaderComparator</u></b>
- * <p>
- * TODO Implement me. Please.
- */
-public class StreamInputReaderComparator implements
- Comparator<StreamInputReader>, Serializable {
-
- // ------------------------------------------------------------------------
- // Constants
- // ------------------------------------------------------------------------
-
- private static final long serialVersionUID = 7477206132343139753L;
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- @Override
- public int compare(StreamInputReader a, StreamInputReader b) {
- // TODO: use unsigned comparison to avoid sign errors if needed
- long ta = a.getCurrentEvent().timestamp;
- long tb = b.getCurrentEvent().timestamp;
-
- if (ta < tb) {
- return -1;
- } else if (ta > tb) {
- return 1;
- } else {
- return 0;
- }
- }
-
-}
--- /dev/null
+/*******************************************************************************.
+ * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Matthew Khouzam - Initial Design and implementation
+ * Contributors: Francis Giraldeau - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.ctf.core.event.io;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * <b><u>BitBuffer</u></b>
+ * <p>
+ * TODO Implement me. Please.
+ */
+public class BitBuffer {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ /* default bit width */
+ public static final int BIT_CHAR = 8;
+ public static final int BIT_SHORT = 16;
+ public static final int BIT_INT = 32;
+ public static final int BIT_FLOAT = 32;
+ public static final int BIT_LONG = 64;
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ private ByteBuffer buf;
+ private int pos;
+ private ByteOrder byteOrder;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public BitBuffer() {
+ this(null, ByteOrder.BIG_ENDIAN);
+ }
+
+ public BitBuffer(ByteBuffer buf) {
+ this(buf, ByteOrder.BIG_ENDIAN);
+ }
+
+ public BitBuffer(ByteBuffer buf, ByteOrder order) {
+ setByteBuffer(buf);
+ order(order);
+ position(0);
+ }
+
+ // ------------------------------------------------------------------------
+ // 'Get' operations on buffer
+ // ------------------------------------------------------------------------
+
+ /**
+ * Relative <i>get</i> method for reading 32-bit integer.
+ *
+ * Reads next four bytes from the current bit position according to current
+ * byte order.
+ *
+ * @return The int value read from the buffer
+ */
+ public int getInt() {
+ int val = getInt(BIT_INT, true);
+ pos += BIT_INT;
+ return val;
+ }
+
+ /**
+ * Relative <i>get</i> method for reading integer of <i>length</i> bits.
+ *
+ * Reads <i>length</i> bits starting at the current position. The result is
+ * signed extended if <i>signed</i> is true. The current position is
+ * increased of <i>length</i> bits.
+ *
+ * @param length
+ * The length in bits of this integer
+ * @param signed
+ * The sign extended flag
+ * @return The int value read from the buffer
+ */
+ public int getInt(int length, boolean signed) {
+ int val;
+ if (!canRead(pos, length)) {
+ throw new BufferOverflowException();
+ }
+ if (length == 0) {
+ val = 0;
+ }
+ if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
+ val = getIntLE(pos, length, signed);
+ } else {
+ val = getIntBE(pos, length, signed);
+ }
+ pos += length;
+ return val;
+ }
+
+ /**
+ * Absolute <i>get</i> method for reading integer of <i>length</i> bits.
+ *
+ * Reads <i>length</i> bits starting from position <i>index</i>. The result
+ * is signed extended if <i>signed</i> is true. The current position is
+ * increased of <i>length</i> bits.
+ *
+ * @param index
+ * The start index in bits
+ * @param length
+ * The length in bits to read
+ * @param signed
+ * The sign extended flag
+ * @return The int value read from the buffer
+ */
+ public int getInt(int index, int length, boolean signed) {
+ if (!canRead(index, length)) {
+ throw new BufferOverflowException();
+ }
+ if (length == 0) {
+ return 0;
+ }
+ if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
+ return getIntLE(index, length, signed);
+ }
+ return getIntBE(index, length, signed);
+ }
+
+ private int getIntBE(int index, int length, boolean signed) {
+ assert ((length > 0) && (length <= BIT_INT));
+ int end = index + length;
+ int startByte = index / BIT_CHAR;
+ int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
+ int currByte, lshift, cshift, mask, cmask, cache;
+ int value = 0;
+
+ currByte = startByte;
+ cache = buf.get(currByte) & 0xFF;
+ boolean isNeg = (cache & (1 << (BIT_CHAR - (index % BIT_CHAR) - 1))) != 0;
+ if (signed && isNeg) {
+ value = ~0;
+ }
+ if (startByte == (endByte - 1)) {
+ cmask = cache >>> ((BIT_CHAR - (end % BIT_CHAR)) % BIT_CHAR);
+ if (((length) % BIT_CHAR) > 0) {
+ mask = ~((~0) << length);
+ cmask &= mask;
+ }
+ value <<= length;
+ value |= cmask;
+ return value;
+ }
+ cshift = index % BIT_CHAR;
+ if (cshift > 0) {
+ mask = ~((~0) << (BIT_CHAR - cshift));
+ cmask = cache & mask;
+ lshift = BIT_CHAR - cshift;
+ value <<= lshift;
+ value |= cmask;
+ // index += lshift;
+ currByte++;
+ }
+ for (; currByte < (endByte - 1); currByte++) {
+ value <<= BIT_CHAR;
+ value |= buf.get(currByte) & 0xFF;
+ }
+ lshift = end % BIT_CHAR;
+ if (lshift > 0) {
+ mask = ~((~0) << lshift);
+ cmask = buf.get(currByte) & 0xFF;
+ cmask >>>= BIT_CHAR - lshift;
+ cmask &= mask;
+ value <<= lshift;
+ value |= cmask;
+ } else {
+ value <<= BIT_CHAR;
+ value |= buf.get(currByte) & 0xFF;
+ }
+ return value;
+ }
+
+ private int getIntLE(int index, int length, boolean signed) {
+ assert ((length > 0) && (length <= BIT_INT));
+ int end = index + length;
+ int startByte = index / BIT_CHAR;
+ int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
+ int currByte, lshift, cshift, mask, cmask, cache, mod;
+ int value = 0;
+
+ currByte = endByte - 1;
+ cache = buf.get(currByte) & 0xFF;
+ mod = end % BIT_CHAR;
+ lshift = (mod > 0) ? mod : BIT_CHAR;
+ boolean isNeg = (cache & (1 << (lshift - 1))) != 0;
+ if (signed && isNeg) {
+ value = ~0;
+ }
+ if (startByte == (endByte - 1)) {
+ cmask = cache >>> (index % BIT_CHAR);
+ if (((length) % BIT_CHAR) > 0) {
+ mask = ~((~0) << length);
+ cmask &= mask;
+ }
+ value <<= length;
+ value |= cmask;
+ return value;
+ }
+ cshift = end % BIT_CHAR;
+ if (cshift > 0) {
+ mask = ~((~0) << cshift);
+ cmask = cache & mask;
+ value <<= cshift;
+ value |= cmask;
+ // end -= cshift;
+ currByte--;
+ }
+ for (; currByte >= (startByte + 1); currByte--) {
+ value <<= BIT_CHAR;
+ value |= buf.get(currByte) & 0xFF;
+ }
+ lshift = index % BIT_CHAR;
+ if (lshift > 0) {
+ mask = ~((~0) << (BIT_CHAR - lshift));
+ cmask = buf.get(currByte) & 0xFF;
+ cmask >>>= lshift;
+ cmask &= mask;
+ value <<= (BIT_CHAR - lshift);
+ value |= cmask;
+ } else {
+ value <<= BIT_CHAR;
+ value |= buf.get(currByte) & 0xFF;
+ }
+ return value;
+ }
+
+ // ------------------------------------------------------------------------
+ // 'Put' operations on buffer
+ // ------------------------------------------------------------------------
+
+ /**
+ * Relative <i>put</i> method to write signed 32-bit integer.
+ *
+ * Write four bytes starting from current bit position in the buffer
+ * according to the current byte order. The current position is increased of
+ * <i>length</i> bits.
+ *
+ * @param value
+ * The int value to write
+ */
+ public void putInt(int value) {
+ putInt(BIT_INT, value);
+ }
+
+ /**
+ * Relative <i>put</i> method to write <i>length</i> bits integer.
+ *
+ * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
+ * starting from current bit position in the buffer. Sequential bytes are
+ * written according to the current byte order. The sign bit is carried to
+ * the MSB if signed is true. The sign bit is included in <i>length</i>. The
+ * current position is increased of <i>length</i>.
+ *
+ * @param length
+ * The number of bits to write
+ * @param value
+ * The value to write
+ */
+ public void putInt(int length, int value) {
+ putInt(this.pos, length, value);
+ }
+
+ /**
+ * Absolute <i>put</i> method to write <i>length</i> bits integer.
+ *
+ * Writes <i>length</i> lower-order bits from the provided <i>value</i>,
+ * starting from <i>index</i> position in the buffer. Sequential bytes are
+ * written according to the current byte order. The sign bit is carried to
+ * the MSB if signed is true. The sign bit is included in <i>length</i>. The
+ * current position is increased of <i>length</i>.
+ *
+ * @param index
+ * The start position to write the value
+ * @param value
+ * The value to write
+ * @param length
+ * The number of bits to write
+ */
+ public void putInt(int index, int length, int value) {
+ if (!canRead(index, length)) {
+ throw new BufferOverflowException();
+ }
+ if (length == 0) {
+ return;
+ }
+ if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
+ putIntLE(index, length, value);
+ } else {
+ putIntBE(index, length, value);
+ }
+ }
+
+ private void putIntBE(int index, int length, int value) {
+ assert ((length > 0) && (length <= BIT_INT));
+ int end = index + length;
+ int startByte = index / BIT_CHAR;
+ int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
+ int currByte, lshift, cshift, mask, cmask;
+ int correctedValue = value;
+
+ /*
+ * mask v high bits. Works for unsigned and two complement signed
+ * numbers which value do not overflow on length bits.
+ */
+
+ if (length < BIT_INT) {
+ correctedValue &= ~(~0 << length);
+ }
+
+ /* sub byte */
+ if (startByte == (endByte - 1)) {
+ lshift = (BIT_CHAR - (end % BIT_CHAR)) % BIT_CHAR;
+ mask = ~((~0) << lshift);
+ if ((index % BIT_CHAR) > 0) {
+ mask |= (~(0)) << (BIT_CHAR - (index % BIT_CHAR));
+ }
+ cmask = correctedValue << lshift;
+ /*
+ * low bits are cleared because of lshift and high bits are already
+ * cleared
+ */
+ cmask &= ~mask;
+ int b = buf.get(startByte) & 0xFF;
+ buf.put(startByte, (byte) ((b & mask) | cmask));
+ return;
+ }
+
+ /* head byte contains MSB */
+ currByte = endByte - 1;
+ cshift = end % BIT_CHAR;
+ if (cshift > 0) {
+ lshift = BIT_CHAR - cshift;
+ mask = ~((~0) << lshift);
+ cmask = correctedValue << lshift;
+ cmask &= ~mask;
+ int b = buf.get(currByte) & 0xFF;
+ buf.put(currByte, (byte) ((b & mask) | cmask));
+ correctedValue >>>= cshift;
+ // end -= cshift;
+ currByte--;
+ }
+
+ /* middle byte(s) */
+ for (; currByte >= (startByte + 1); currByte--) {
+ buf.put(currByte, (byte) correctedValue);
+ correctedValue >>>= BIT_CHAR;
+ }
+ /* end byte contains LSB */
+ if ((index % BIT_CHAR) > 0) {
+ mask = (~0) << (BIT_CHAR - (index % BIT_CHAR));
+ cmask = correctedValue & ~mask;
+ int b = buf.get(currByte) & 0xFF;
+ buf.put(currByte, (byte) ((b & mask) | cmask));
+ } else {
+ buf.put(currByte, (byte) correctedValue);
+ }
+ }
+
+ private void putIntLE(int index, int length, int value) {
+ assert ((length > 0) && (length <= BIT_INT));
+ int end = index + length;
+ int startByte = index / BIT_CHAR;
+ int endByte = (end + (BIT_CHAR - 1)) / BIT_CHAR;
+ int currByte, lshift, cshift, mask, cmask;
+ int correctedValue = value;
+
+ /*
+ * mask v high bits. Works for unsigned and two complement signed
+ * numbers which value do not overflow on length bits.
+ */
+
+ if (length < BIT_INT) {
+ correctedValue &= ~(~0 << length);
+ }
+
+ /* sub byte */
+ if (startByte == (endByte - 1)) {
+ lshift = index % BIT_CHAR;
+ mask = ~((~0) << lshift);
+ if ((end % BIT_CHAR) > 0) {
+ mask |= (~(0)) << (end % BIT_CHAR);
+ }
+ cmask = correctedValue << lshift;
+ /*
+ * low bits are cleared because of lshift and high bits are already
+ * cleared
+ */
+ cmask &= ~mask;
+ int b = buf.get(startByte) & 0xFF;
+ buf.put(startByte, (byte) ((b & mask) | cmask));
+ return;
+ }
+
+ /* head byte */
+ currByte = startByte;
+ cshift = index % BIT_CHAR;
+ if (cshift > 0) {
+ mask = ~((~0) << cshift);
+ cmask = correctedValue << cshift;
+ cmask &= ~mask;
+ int b = buf.get(currByte) & 0xFF;
+ buf.put(currByte, (byte) ((b & mask) | cmask));
+ correctedValue >>>= BIT_CHAR - cshift;
+ // index += BIT_CHAR - cshift;
+ currByte++;
+ }
+
+ /* middle byte(s) */
+ for (; currByte < (endByte - 1); currByte++) {
+ buf.put(currByte, (byte) correctedValue);
+ correctedValue >>>= BIT_CHAR;
+ }
+ /* end byte */
+ if ((end % BIT_CHAR) > 0) {
+ mask = (~0) << (end % BIT_CHAR);
+ cmask = correctedValue & ~mask;
+ int b = buf.get(currByte) & 0xFF;
+ buf.put(currByte, (byte) ((b & mask) | cmask));
+ } else {
+ buf.put(currByte, (byte) correctedValue);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Buffer attributes handling
+ // ------------------------------------------------------------------------
+
+ public boolean canRead(int length) {
+ return canRead(pos, length);
+ }
+
+ public boolean canRead(int index, int length) {
+ if (buf == null) {
+ return false;
+ }
+
+ if ((index + length) > (buf.capacity() * BIT_CHAR)) {
+ return false;
+ }
+ return true;
+ }
+
+ public void order(ByteOrder order) {
+ this.byteOrder = order;
+ if (buf != null) {
+ buf.order(order);
+ }
+ }
+
+ public ByteOrder order() {
+ return byteOrder;
+ }
+
+ public void position(int newPosition) {
+ this.pos = newPosition;
+ }
+
+ public int position() {
+ return pos;
+ }
+
+ public void setByteBuffer(ByteBuffer buf) {
+ this.buf = buf;
+ if (buf != null) {
+ this.buf.order(byteOrder);
+ }
+ clear();
+ }
+
+ public ByteBuffer getByteBuffer() {
+ return buf;
+ }
+
+ public void setByteOrder(ByteOrder byteOrder) {
+ this.byteOrder = byteOrder;
+ }
+
+ public ByteOrder getByteOrder() {
+ return byteOrder;
+ }
+
+ public void clear() {
+ position(0);
+
+ if (buf == null) {
+ return;
+ }
+ buf.clear();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Matthew Khouzam - Initial Design and Grammar
+ * Contributors: Francis Giraldeau - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.ctf.core.event.metadata;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.linuxtools.ctf.core.event.CTFClock;
+import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.linuxtools.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
+import org.eclipse.linuxtools.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.SequenceDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.StringDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
+import org.eclipse.linuxtools.ctf.core.trace.Stream;
+import org.eclipse.linuxtools.ctf.parser.CTFParser;
+import org.eclipse.linuxtools.internal.ctf.core.Activator;
+
+/*
+ * Asserts throughout this class denote the assumptions we can make because of
+ * the way the grammar generates the AST.
+ *
+ * There is also an assert at the beginning of each function that receives a
+ * tree node to make sure that the node is indeed of the type the function is
+ * expecting.
+ */
+/*
+ * Suppress unchecked warnings for things like List<CommonTree> children =
+ * root.getChildren(), because ANTLR doesn't know what generics are.
+ */
+/**
+ * <b><u>IOStructGen</u></b>
+ */
+@SuppressWarnings("unchecked")
+public class IOStructGen {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ static private final boolean DEBUG_ = false;
+
+ /**
+ * The trace
+ */
+ private final CTFTrace trace;
+ private final CommonTree tree;
+
+ /**
+ * The current declaration scope.
+ */
+ private DeclarationScope scope = null;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ public IOStructGen(CommonTree tree, CTFTrace trace) {
+ this.trace = trace;
+ this.tree = tree;
+ }
+
+ public void generate() throws ParseException {
+ parseRoot(tree);
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Parse the root node.
+ *
+ * @param root
+ * A ROOT node.
+ * @throws ParseException
+ */
+ private void parseRoot(CommonTree root) throws ParseException {
+ assert (root.getType() == CTFParser.ROOT);
+
+ List<CommonTree> children = root.getChildren();
+ assert (children != null);
+ java.io.FileOutputStream fos = null;
+ java.io.OutputStreamWriter out = null;
+ if (DEBUG_) {
+ try {
+ fos = new java.io.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
+ out = new java.io.OutputStreamWriter(fos, "UTF-8"); //$NON-NLS-1$
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return;
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ CommonTree traceNode = null;
+ List<CommonTree> streams = new ArrayList<CommonTree>();
+ List<CommonTree> events = new ArrayList<CommonTree>();
+ List<CommonTree> declarations = new ArrayList<CommonTree>();
+ List<CommonTree> environments = new ArrayList<CommonTree>();
+ List<CommonTree> clocks = new ArrayList<CommonTree>();
+ /* Create a new declaration scope with no parent. */
+ pushScope();
+
+ try {
+ for (CommonTree child : children) {
+ if (DEBUG_) {
+ out.write(child.toString()
+ + " -> " + child.getType() + '\n'); //$NON-NLS-1$
+ }
+ switch (child.getType()) {
+ case CTFParser.DECLARATION:
+ declarations.add(child);
+ break;
+ case CTFParser.TRACE:
+ if (traceNode != null) {
+ throw new ParseException(
+ "Only one trace block is allowed"); //$NON-NLS-1$
+ }
+ traceNode = child;
+ break;
+ case CTFParser.STREAM:
+ streams.add(child);
+ break;
+ case CTFParser.EVENT:
+ events.add(child);
+ break;
+ case CTFParser.CLOCK:
+ clocks.add(child);
+ break;
+ case CTFParser.ENV:
+ environments.add(child);
+ break;
+ default:
+ childTypeError(child);
+ }
+ }
+
+ if (DEBUG_) {
+ out.write("Environments\n"); //$NON-NLS-1$
+ }
+ for (CommonTree environment : environments) {
+ parseEnvironment(environment);
+ }
+ if (DEBUG_) {
+ out.write("Clocks\n"); //$NON-NLS-1$
+ }
+ for (CommonTree clock : clocks) {
+ parseClock(clock);
+ }
+ if (DEBUG_) {
+ out.write("Declarations\n"); //$NON-NLS-1$
+ }
+ for (CommonTree decl : declarations) {
+ if (DEBUG_) {
+ out.write(decl.toString() + '\n');
+ }
+ parseRootDeclaration(decl);
+ }
+
+ if (traceNode == null) {
+ throw new ParseException("Missing trace block"); //$NON-NLS-1$
+ }
+
+ parseTrace(traceNode);
+
+ if (DEBUG_) {
+ out.write("Streams\n"); //$NON-NLS-1$
+ }
+ if (streams.size() > 0) {
+ for (CommonTree stream : streams) {
+ if (DEBUG_) {
+ try {
+ out.write(stream.toString() + '\n');
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ parseStream(stream);
+ }
+ } else {
+ /* Add an empty stream that will have a null id */
+ trace.addStream(new Stream(trace));
+ }
+
+ if (DEBUG_) {
+ out.write("Events\n"); //$NON-NLS-1$
+ }
+ for (CommonTree event : events) {
+ parseEvent(event);
+ CommonTree name = (CommonTree) event.getChild(0).getChild(1)
+ .getChild(0).getChild(0);
+ if (DEBUG_) {
+ out.write("Name = " + name); //$NON-NLS-1$
+ }
+ CommonTree id = (CommonTree) event.getChild(1).getChild(1)
+ .getChild(0).getChild(0);
+ if (DEBUG_) {
+ out.write("Name = " + name + " Id = " + id + '\n'); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ if (DEBUG_) {
+ out.close();
+ fos.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ popScope();
+ }
+
+ private void parseEnvironment(CommonTree environment) {
+ List<CommonTree> children = environment.getChildren();
+ for (CommonTree child : children) {
+ String left;
+ String right;
+ left = child.getChild(0).getChild(0).getChild(0).getText();
+ right = child.getChild(1).getChild(0).getChild(0).getText();
+ trace.addEnvironmentVar(left, right);
+ }
+ }
+
+ private void parseClock(CommonTree clock) {
+ List<CommonTree> children = clock.getChildren();
+ CTFClock ctfClock = new CTFClock();
+ for (CommonTree child : children) {
+ final String key = child.getChild(0).getChild(0).getChild(0)
+ .getText();
+ final CommonTree value = (CommonTree) child.getChild(1).getChild(0).getChild(0);
+ final int type = value.getType();
+ switch (type) {
+ case CTFParser.INTEGER:
+ case CTFParser.DECIMAL_LITERAL:
+ /*
+ * Not a pretty hack, this is to make sure that there is no number
+ * overflow due to 63 bit integers. The offset should only really
+ * be an issue in the year 2262. the tracer in C/ASM can write an offset in
+ * an unsigned 64 bit long. In java, the last bit, being set to 1 will
+ * be read as a negative number, but since it is too big a positive it will
+ * throw an exception. this will happen in 2^63 ns from 1970.
+ * Therefore 293 years from 1970
+ */
+ Long numValue;
+ try{
+ numValue = Long.parseLong(value.getText());
+ }
+ catch( Exception e)
+ {
+ numValue = 1330938566783103277L;
+ }
+ ctfClock.addAttribute(key, numValue);
+ break;
+ default:
+ ctfClock.addAttribute(key, value.getText());
+ }
+
+ }
+ String NameValue = ctfClock.getName();
+ trace.addClock(NameValue, ctfClock);
+ }
+
+ private void parseTrace(CommonTree traceNode) throws ParseException {
+ assert (traceNode.getType() == CTFParser.TRACE);
+
+ List<CommonTree> children = traceNode.getChildren();
+ if (children == null) {
+ throw new ParseException("Trace block is empty"); //$NON-NLS-1$
+ }
+
+ pushScope();
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPEALIAS:
+ parseTypealias(child);
+ break;
+ case CTFParser.TYPEDEF:
+ parseTypedef(child);
+ break;
+ case CTFParser.CTF_EXPRESSION_TYPE:
+ case CTFParser.CTF_EXPRESSION_VAL:
+ parseTraceDeclaration(child);
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ /*
+ * If trace byte order was not specified and not using packet based
+ * metadata
+ */
+ if (trace.getByteOrder() == null) {
+ throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
+ }
+
+ popScope();
+ }
+
+ private void parseTraceDeclaration(CommonTree traceDecl)
+ throws ParseException {
+ assert ((traceDecl.getType() == CTFParser.CTF_EXPRESSION_TYPE) || (traceDecl
+ .getType() == CTFParser.CTF_EXPRESSION_VAL));
+
+ /* There should be a left and right */
+ assert (traceDecl.getChildCount() == 2);
+
+ CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
+ assert (leftNode.getType() == CTFParser.CTF_LEFT);
+ CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+
+ List<CommonTree> leftStrings = leftNode.getChildren();
+ assert (leftStrings != null);
+
+ if (!isUnaryString(leftStrings.get(0))) {
+ throw new ParseException(
+ "Left side of CTF assignment must be a string"); //$NON-NLS-1$
+ }
+
+ String left = concatenateUnaryStrings(leftStrings);
+
+ if (left.equals("major")) { //$NON-NLS-1$
+ if (trace.majortIsSet()) {
+ throw new ParseException("major is already set"); //$NON-NLS-1$
+ }
+
+ trace.setMajor(getMajorOrMinor(rightNode));
+ } else if (left.equals("minor")) { //$NON-NLS-1$
+ if (trace.minorIsSet()) {
+ throw new ParseException("minor is already set"); //$NON-NLS-1$
+ }
+
+ trace.setMinor(getMajorOrMinor(rightNode));
+ } else if (left.equals("uuid")) { //$NON-NLS-1$
+ UUID uuid = getUUID(rightNode);
+
+ /*
+ * If uuid was already set by a metadata packet, compare it to see
+ * if it matches
+ */
+ if (trace.UUIDIsSet()) {
+ if (trace.getUUID().compareTo(uuid) != 0) {
+ throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
+ + trace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
+ }
+ } else {
+ trace.setUUID(uuid);
+ }
+
+ } else if (left.equals("byte_order")) { //$NON-NLS-1$
+ ByteOrder byteOrder = getByteOrder(rightNode);
+
+ /*
+ * If byte order was already set by a metadata packet, compare it to
+ * see if it matches
+ */
+ if (trace.getByteOrder() != null) {
+ if (trace.getByteOrder() != byteOrder) {
+ throw new ParseException(
+ "Endianness mismatch. Magic number says " //$NON-NLS-1$
+ + trace.getByteOrder()
+ + " but metadata says " + byteOrder); //$NON-NLS-1$
+ }
+ } else {
+ trace.setByteOrder(byteOrder);
+ }
+ } else if (left.equals("packet.header")) { //$NON-NLS-1$
+ if (trace.packetHeaderIsSet()) {
+ throw new ParseException("packet.header already defined"); //$NON-NLS-1$
+ }
+
+ CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+ if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+ throw new ParseException(
+ "packet.header expects a type specifier"); //$NON-NLS-1$
+ }
+
+ IDeclaration packetHeaderDecl = parseTypeSpecifierList(
+ typeSpecifier, null);
+
+ if (!(packetHeaderDecl instanceof StructDeclaration)) {
+ throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
+ }
+
+ trace.setPacketHeader((StructDeclaration) packetHeaderDecl);
+ } else {
+ throw new ParseException("Unknown trace attribute : " + left); //$NON-NLS-1$
+ }
+ }
+
+ private void parseStream(CommonTree streamNode) throws ParseException {
+ assert (streamNode.getType() == CTFParser.STREAM);
+
+ Stream stream = new Stream(trace);
+
+ List<CommonTree> children = streamNode.getChildren();
+ if (children == null) {
+ throw new ParseException("Empty stream block"); //$NON-NLS-1$
+ }
+
+ pushScope();
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPEALIAS:
+ parseTypealias(child);
+ break;
+ case CTFParser.TYPEDEF:
+ parseTypedef(child);
+ break;
+ case CTFParser.CTF_EXPRESSION_TYPE:
+ case CTFParser.CTF_EXPRESSION_VAL:
+ parseStreamDeclaration(child, stream);
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ if (stream.idIsSet()) {
+ if (!trace.packetHeaderIsSet()
+ || !trace.getPacketHeader().hasField("stream_id")) { //$NON-NLS-1$
+ throw new ParseException(
+ "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
+ }
+ }
+
+ trace.addStream(stream);
+
+ popScope();
+ }
+
+ private void parseStreamDeclaration(CommonTree streamDecl, Stream stream)
+ throws ParseException {
+ assert ((streamDecl.getType() == CTFParser.CTF_EXPRESSION_TYPE) || (streamDecl
+ .getType() == CTFParser.CTF_EXPRESSION_VAL));
+
+ /* There should be a left and right */
+ assert (streamDecl.getChildCount() == 2);
+
+ CommonTree leftNode = (CommonTree) streamDecl.getChild(0);
+ assert (leftNode.getType() == CTFParser.CTF_LEFT);
+ CommonTree rightNode = (CommonTree) streamDecl.getChild(1);
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+
+ List<CommonTree> leftStrings = leftNode.getChildren();
+ assert (leftStrings != null);
+
+ if (!isUnaryString(leftStrings.get(0))) {
+ throw new ParseException(
+ "Left side of CTF assignment must be a string"); //$NON-NLS-1$
+ }
+
+ String left = concatenateUnaryStrings(leftStrings);
+
+ if (left.equals("id")) { //$NON-NLS-1$
+ if (stream.idIsSet()) {
+ throw new ParseException("stream id already defined"); //$NON-NLS-1$
+ }
+
+ long streamID = getStreamID(rightNode);
+
+ stream.setId(streamID);
+ } else if (left.equals("event.header")) { //$NON-NLS-1$
+ if (stream.eventHeaderIsSet()) {
+ throw new ParseException("event.header already defined"); //$NON-NLS-1$
+ }
+
+ CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+ if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+ throw new ParseException(
+ "event.header expects a type specifier"); //$NON-NLS-1$
+ }
+
+ IDeclaration eventHeaderDecl = parseTypeSpecifierList(
+ typeSpecifier, null);
+
+ if (!(eventHeaderDecl instanceof StructDeclaration)) {
+ throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
+ }
+
+ stream.setEventHeader((StructDeclaration) eventHeaderDecl);
+ } else if (left.equals("event.context")) { //$NON-NLS-1$
+ if (stream.eventContextIsSet()) {
+ throw new ParseException("event.context already defined"); //$NON-NLS-1$
+ }
+
+ CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+ if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+ throw new ParseException(
+ "event.context expects a type specifier"); //$NON-NLS-1$
+ }
+
+ IDeclaration eventContextDecl = parseTypeSpecifierList(
+ typeSpecifier, null);
+
+ if (!(eventContextDecl instanceof StructDeclaration)) {
+ throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
+ }
+
+ stream.setEventContext((StructDeclaration) eventContextDecl);
+ } else if (left.equals("packet.context")) { //$NON-NLS-1$
+ if (stream.packetContextIsSet()) {
+ throw new ParseException("packet.context already defined"); //$NON-NLS-1$
+ }
+
+ CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+ if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+ throw new ParseException(
+ "packet.context expects a type specifier"); //$NON-NLS-1$
+ }
+
+ IDeclaration packetContextDecl = parseTypeSpecifierList(
+ typeSpecifier, null);
+
+ if (!(packetContextDecl instanceof StructDeclaration)) {
+ throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
+ }
+
+ stream.setPacketContext((StructDeclaration) packetContextDecl);
+ } else {
+ throw new ParseException("Unknown stream attribute : " + left); //$NON-NLS-1$
+ }
+ }
+
+ private void parseEvent(CommonTree eventNode) throws ParseException {
+ assert (eventNode.getType() == CTFParser.EVENT);
+
+ List<CommonTree> children = eventNode.getChildren();
+ if (children == null) {
+ throw new ParseException("Empty event block"); //$NON-NLS-1$
+ }
+
+ EventDeclaration event = new EventDeclaration();
+
+ pushScope();
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPEALIAS:
+ parseTypealias(child);
+ break;
+ case CTFParser.TYPEDEF:
+ parseTypedef(child);
+ break;
+ case CTFParser.CTF_EXPRESSION_TYPE:
+ case CTFParser.CTF_EXPRESSION_VAL:
+ parseEventDeclaration(child, event);
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ if (!event.nameIsSet()) {
+ throw new ParseException("Event name not set"); //$NON-NLS-1$
+ }
+
+ /*
+ * If the event did not specify a stream, then the trace must be single
+ * stream
+ */
+ if (!event.streamIsSet()) {
+ if (trace.nbStreams() > 1) {
+ throw new ParseException(
+ "Event without stream_id with more than one stream"); //$NON-NLS-1$
+ }
+
+ /*
+ * If the event did not specify a stream, the only existing stream
+ * must not have an id. Note: That behavior could be changed, it
+ * could be possible to just get the only existing stream, whatever
+ * is its id.
+ */
+ Stream stream = trace.getStream(null);
+
+ if (stream != null) {
+ event.setStream(stream);
+ } else {
+ throw new ParseException(
+ "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * Add the event to the stream.
+ */
+ event.getStream().addEvent(event);
+
+ popScope();
+ }
+
+ private void parseEventDeclaration(CommonTree eventDecl,
+ EventDeclaration event) throws ParseException {
+ assert ((eventDecl.getType() == CTFParser.CTF_EXPRESSION_TYPE) || (eventDecl
+ .getType() == CTFParser.CTF_EXPRESSION_VAL));
+
+ /* There should be a left and right */
+ assert (eventDecl.getChildCount() == 2);
+
+ CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
+ assert (leftNode.getType() == CTFParser.CTF_LEFT);
+ CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+
+ List<CommonTree> leftStrings = leftNode.getChildren();
+ assert (leftStrings != null);
+
+ if (!isUnaryString(leftStrings.get(0))) {
+ throw new ParseException(
+ "Left side of CTF assignment must be a string"); //$NON-NLS-1$
+ }
+
+ String left = concatenateUnaryStrings(leftStrings);
+
+ if (left.equals("name")) { //$NON-NLS-1$
+ if (event.nameIsSet()) {
+ throw new ParseException("name already defined"); //$NON-NLS-1$
+ }
+
+ String name = getEventName(rightNode);
+
+ event.setName(name);
+ } else if (left.equals("id")) { //$NON-NLS-1$
+ if (event.idIsSet()) {
+ throw new ParseException("id already defined"); //$NON-NLS-1$
+ }
+
+ long id = getEventID(rightNode);
+
+ event.setId(id);
+ } else if (left.equals("stream_id")) { //$NON-NLS-1$
+ if (event.streamIsSet()) {
+ throw new ParseException("stream id already defined"); //$NON-NLS-1$
+ }
+
+ long streamId = getStreamID(rightNode);
+
+ Stream stream = trace.getStream(streamId);
+
+ if (stream == null) {
+ throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ event.setStream(stream);
+ } else if (left.equals("context")) { //$NON-NLS-1$
+ if (event.contextIsSet()) {
+ throw new ParseException("context already defined"); //$NON-NLS-1$
+ }
+
+ CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+ if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+ throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
+ }
+
+ IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier,
+ null);
+
+ if (!(contextDecl instanceof StructDeclaration)) {
+ throw new ParseException("context expects a struct"); //$NON-NLS-1$
+ }
+
+ event.setContext((StructDeclaration) contextDecl);
+ } else if (left.equals("fields")) { //$NON-NLS-1$
+ if (event.fieldsIsSet()) {
+ throw new ParseException("fields already defined"); //$NON-NLS-1$
+ }
+
+ CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+ if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+ throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
+ }
+
+ IDeclaration fieldsDecl;
+ fieldsDecl = parseTypeSpecifierList(typeSpecifier, null);
+
+ if (!(fieldsDecl instanceof StructDeclaration)) {
+ throw new ParseException("fields expects a struct"); //$NON-NLS-1$
+ }
+ /*
+ * The underscores in the event names.
+ * These underscores were added by the LTTng tracer.
+ */
+ final StructDeclaration fields = (StructDeclaration) fieldsDecl;
+ event.setFields(fields);
+
+ } else {
+ throw new ParseException("Unknown event attribute : " + left); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Parses a declaration at the root level.
+ *
+ * @param declaration
+ * The declaration subtree.
+ * @throws ParseException
+ */
+ private void parseRootDeclaration(CommonTree declaration)
+ throws ParseException {
+ assert (declaration.getType() == CTFParser.DECLARATION);
+
+ List<CommonTree> children = declaration.getChildren();
+ assert (children != null);
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPEDEF:
+ parseTypedef(child);
+ break;
+ case CTFParser.TYPEALIAS:
+ parseTypealias(child);
+ break;
+ case CTFParser.TYPE_SPECIFIER_LIST:
+ parseTypeSpecifierList(child, null);
+ break;
+ default:
+ childTypeError(child);
+ }
+ }
+ }
+
+ /**
+ * Parses a typealias node. It parses the target, the alias, and registers
+ * the type in the current scope.
+ *
+ * @param typealias
+ * A TYPEALIAS node.
+ * @throws ParseException
+ */
+ private void parseTypealias(CommonTree typealias) throws ParseException {
+ assert (typealias.getType() == CTFParser.TYPEALIAS);
+
+ List<CommonTree> children = typealias.getChildren();
+ assert (children != null);
+
+ CommonTree target = null;
+ CommonTree alias = null;
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPEALIAS_TARGET:
+ assert (target == null);
+ target = child;
+ break;
+ case CTFParser.TYPEALIAS_ALIAS:
+ assert (alias == null);
+ alias = child;
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ assert (target != null);
+ assert (alias != null);
+
+ IDeclaration targetDeclaration = parseTypealiasTarget(target);
+
+ if (targetDeclaration instanceof VariantDeclaration) {
+ if (((VariantDeclaration) targetDeclaration).isTagged()) {
+ throw new ParseException(
+ "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
+ }
+ }
+
+ String aliasString = parseTypealiasAlias(alias);
+
+ getCurrentScope().registerType(aliasString, targetDeclaration);
+ }
+
+ /**
+ * Parses the target part of a typealias and gets the corresponding
+ * declaration.
+ *
+ * @param target
+ * A TYPEALIAS_TARGET node.
+ * @return The corresponding declaration.
+ * @throws ParseException
+ */
+ private IDeclaration parseTypealiasTarget(CommonTree target)
+ throws ParseException {
+ assert (target.getType() == CTFParser.TYPEALIAS_TARGET);
+
+ List<CommonTree> children = target.getChildren();
+ assert (children != null);
+
+ CommonTree typeSpecifierList = null;
+ CommonTree typeDeclaratorList = null;
+ CommonTree typeDeclarator = null;
+ StringBuilder identifierSB = new StringBuilder();
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPE_SPECIFIER_LIST:
+ assert (typeSpecifierList == null);
+ typeSpecifierList = child;
+ break;
+ case CTFParser.TYPE_DECLARATOR_LIST:
+ assert (typeDeclaratorList == null);
+ typeDeclaratorList = child;
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ assert (typeSpecifierList != null);
+
+ if (typeDeclaratorList != null) {
+ /*
+ * Only allow one declarator
+ *
+ * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
+ * otherwise the new type puint8_t would maps to two different
+ * types.
+ */
+ if (typeDeclaratorList.getChildCount() != 1) {
+ throw new ParseException(
+ "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
+ }
+
+ typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
+ }
+
+ /* Parse the target type and get the declaration */
+ IDeclaration targetDeclaration = parseTypeDeclarator(typeDeclarator,
+ typeSpecifierList, identifierSB);
+
+ /*
+ * We don't allow identifier in the target
+ *
+ * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
+ * permitted
+ */
+ if (identifierSB.length() > 0) {
+ throw new ParseException("Identifier (" + identifierSB.toString() //$NON-NLS-1$
+ + ") not expected in the typealias target"); //$NON-NLS-1$
+ }
+
+ return targetDeclaration;
+ }
+
+ /**
+ * Parses the alias part of a typealias. It parses the underlying specifier
+ * list and declarator and creates the string representation that will be
+ * used to register the type.
+ *
+ * @param alias
+ * A TYPEALIAS_ALIAS node.
+ * @return The string representation of the alias.
+ * @throws ParseException
+ */
+ private static String parseTypealiasAlias(CommonTree alias)
+ throws ParseException {
+ assert (alias.getType() == CTFParser.TYPEALIAS_ALIAS);
+
+ List<CommonTree> children = alias.getChildren();
+ assert (children != null);
+
+ CommonTree typeSpecifierList = null;
+ CommonTree typeDeclaratorList = null;
+ CommonTree typeDeclarator = null;
+ List<CommonTree> pointers = new LinkedList<CommonTree>();
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.TYPE_SPECIFIER_LIST:
+ assert (typeSpecifierList == null);
+ typeSpecifierList = child;
+ break;
+ case CTFParser.TYPE_DECLARATOR_LIST:
+ assert (typeDeclaratorList == null);
+ typeDeclaratorList = child;
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ /* If there is a type declarator list, extract the pointers */
+ if (typeDeclaratorList != null) {
+ /*
+ * Only allow one declarator
+ *
+ * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
+ */
+ if (typeDeclaratorList.getChildCount() != 1) {
+ throw new ParseException(
+ "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
+ }
+
+ typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
+
+ List<CommonTree> typeDeclaratorChildren = typeDeclarator
+ .getChildren();
+ assert (typeDeclaratorChildren != null);
+
+ for (CommonTree child : typeDeclaratorChildren) {
+ switch (child.getType()) {
+ case CTFParser.POINTER:
+ pointers.add(child);
+ break;
+ case CTFParser.IDENTIFIER:
+ throw new ParseException("Identifier (" + child.getText() //$NON-NLS-1$
+ + ") not expected in the typealias target"); //$NON-NLS-1$
+ /* break; */
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+ }
+
+ return createTypeDeclarationString(typeSpecifierList, pointers);
+ }
+
+ /**
+ * Parses a typedef node. This creates and registers a new declaration for
+ * each declarator found in the typedef.
+ *
+ * @param typedef
+ * A TYPEDEF node.
+ * @throws ParseException
+ * If there is an error creating the declaration.
+ */
+ private void parseTypedef(CommonTree typedef) throws ParseException {
+ assert (typedef.getType() == CTFParser.TYPEDEF);
+
+ CommonTree typeDeclaratorListNode = (CommonTree) typedef
+ .getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
+ assert (typeDeclaratorListNode != null);
+
+ CommonTree typeSpecifierListNode = (CommonTree) typedef
+ .getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
+ assert (typeSpecifierListNode != null);
+
+ List<CommonTree> typeDeclaratorList = typeDeclaratorListNode
+ .getChildren();
+ assert (typeDeclaratorList != null);
+
+ for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
+ StringBuilder identifierSB = new StringBuilder();
+
+ IDeclaration type_declaration = parseTypeDeclarator(
+ typeDeclaratorNode, typeSpecifierListNode, identifierSB);
+
+ if (type_declaration instanceof VariantDeclaration) {
+ if (((VariantDeclaration) type_declaration).isTagged()) {
+ throw new ParseException(
+ "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
+ }
+ }
+
+ getCurrentScope().registerType(identifierSB.toString(),
+ type_declaration);
+ }
+ }
+
+ /**
+ * Parses a pair type declarator / type specifier list and returns the
+ * corresponding declaration. If it is present, it also writes the
+ * identifier of the declarator in the given {@link StringBuilder}.
+ *
+ * @param typeDeclarator
+ * A TYPE_DECLARATOR node.
+ * @param typeSpecifierList
+ * A TYPE_SPECIFIER_LIST node.
+ * @param identifierSB
+ * A StringBuilder that will receive the identifier found in the
+ * declarator.
+ * @return The corresponding declaration.
+ * @throws ParseException
+ * If there is an error finding or creating the declaration.
+ */
+ private IDeclaration parseTypeDeclarator(CommonTree typeDeclarator,
+ CommonTree typeSpecifierList, StringBuilder identifierSB)
+ throws ParseException {
+ if (typeDeclarator != null) {
+ assert (typeDeclarator.getType() == CTFParser.TYPE_DECLARATOR);
+ }
+ assert (typeSpecifierList.getType() == CTFParser.TYPE_SPECIFIER_LIST);
+
+ IDeclaration declaration = null;
+ List<CommonTree> children = null;
+ List<CommonTree> pointers = new LinkedList<CommonTree>();
+ List<CommonTree> lengths = new LinkedList<CommonTree>();
+ CommonTree identifier = null;
+
+ /* Separate the tokens by type */
+ if (typeDeclarator != null) {
+ children = typeDeclarator.getChildren();
+ assert (children != null);
+ for (CommonTree child : children) {
+
+ switch (child.getType()) {
+ case CTFParser.POINTER:
+ pointers.add(child);
+ break;
+ case CTFParser.IDENTIFIER:
+ assert (identifier == null);
+ identifier = child;
+ break;
+ case CTFParser.LENGTH:
+ lengths.add(child);
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ }
+
+ /*
+ * Parse the type specifier list, which is the "base" type. For example,
+ * it would be int in int a[3][len].
+ */
+ declaration = parseTypeSpecifierList(typeSpecifierList, pointers);
+
+ /*
+ * Each length subscript means that we must create a nested array or
+ * sequence. For example, int a[3][len] means that we have an array of 3
+ * (sequences of length 'len' of (int)).
+ */
+ if (lengths.size() > 0 ) {
+ /* We begin at the end */
+ Collections.reverse(lengths);
+
+ for (CommonTree length : lengths) {
+ /*
+ * By looking at the first expression, we can determine whether
+ * it is an array or a sequence.
+ */
+ List<CommonTree> lengthChildren = length.getChildren();
+ assert (lengthChildren != null);
+
+ CommonTree first = lengthChildren.get(0);
+ if (isUnaryInteger(first)) {
+ /* Array */
+ int arrayLength = (int) parseUnaryInteger(first);
+
+ if (arrayLength < 1) {
+ throw new ParseException("Array length is negative"); //$NON-NLS-1$
+ }
+
+ /* Create the array declaration. */
+ declaration = new ArrayDeclaration(arrayLength, declaration);
+ } else if (isUnaryString(first)) {
+ /* Sequence */
+ String lengthName = concatenateUnaryStrings(lengthChildren);
+
+ /* Create the sequence declaration. */
+ declaration = new SequenceDeclaration(lengthName,
+ declaration);
+ } else {
+ childTypeError(first);
+ }
+ }
+ }
+
+ if (identifier != null) {
+ identifierSB.append(identifier.getText());
+ }
+
+ return declaration;
+ }
+
+ /**
+ * Parses a type specifier list and returns the corresponding declaration.
+ *
+ * @param typeSpecifierList
+ * A TYPE_SPECIFIER_LIST node.
+ * @param pointerList
+ * A list of POINTER nodes that apply to the specified type.
+ * @return The corresponding declaration.
+ * @throws ParseException
+ * If the type has not been defined or if there is an error
+ * creating the declaration.
+ */
+ private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList,
+ List<CommonTree> pointerList) throws ParseException {
+ assert (typeSpecifierList.getType() == CTFParser.TYPE_SPECIFIER_LIST);
+ IDeclaration declaration = null;
+
+ /*
+ * By looking at the first element of the type specifier list, we can
+ * determine which type it belongs to.
+ */
+ CommonTree firstChild = (CommonTree) typeSpecifierList.getChild(0);
+ assert (firstChild != null); /* grammar */
+
+ switch (firstChild.getType()) {
+ case CTFParser.FLOATING_POINT:
+ Activator
+ .getDefault()
+ .log("parseTypeSpecifierList: floating_point not implemented yet"); //$NON-NLS-1$
+ break;
+ case CTFParser.INTEGER:
+ declaration = parseInteger(firstChild);
+ break;
+ case CTFParser.STRING:
+ declaration = parseString(firstChild);
+ break;
+ case CTFParser.STRUCT:
+ declaration = parseStruct(firstChild);
+ break;
+ case CTFParser.VARIANT:
+ declaration = parseVariant(firstChild);
+ break;
+ case CTFParser.ENUM:
+ declaration = parseEnum(firstChild);
+ break;
+ case CTFParser.IDENTIFIER:
+ case CTFParser.FLOATTOK:
+ case CTFParser.INTTOK:
+ case CTFParser.LONGTOK:
+ case CTFParser.SHORTTOK:
+ case CTFParser.SIGNEDTOK:
+ case CTFParser.UNSIGNEDTOK:
+ case CTFParser.CHARTOK:
+ case CTFParser.DOUBLETOK:
+ case CTFParser.VOIDTOK:
+ case CTFParser.BOOLTOK:
+ case CTFParser.COMPLEXTOK:
+ case CTFParser.IMAGINARYTOK:
+ declaration = parseTypeDeclaration(typeSpecifierList, pointerList);
+ break;
+ default:
+ childTypeError(firstChild);
+ }
+
+ assert (declaration != null);
+ return declaration;
+ }
+
+ /**
+ * Parses a type specifier list as a user-declared type.
+ *
+ * @param typeSpecifierList
+ * A TYPE_SPECIFIER_LIST node containing a user-declared type.
+ * @param pointerList
+ * A list of POINTER nodes that apply to the type specified in
+ * typeSpecifierList.
+ * @return The corresponding declaration.
+ * @throws ParseException
+ * If the type does not exist (has not been found).
+ */
+ private IDeclaration parseTypeDeclaration(CommonTree typeSpecifierList,
+ List<CommonTree> pointerList) throws ParseException {
+ /* Create the string representation of the type declaration */
+ String typeStringRepresentation = createTypeDeclarationString(
+ typeSpecifierList, pointerList);
+
+ /* Use the string representation to search the type in the current scope */
+ IDeclaration decl = getCurrentScope().rlookupType(
+ typeStringRepresentation);
+
+ if (decl == null) {
+ throw new ParseException("Type " + typeStringRepresentation //$NON-NLS-1$
+ + " has not been defined."); //$NON-NLS-1$
+ }
+
+ return decl;
+ }
+
+ /**
+ * Parses an integer declaration node.
+ *
+ * @param integer
+ * An INTEGER node.
+ * @return The corresponding integer declaration.
+ * @throws ParseException
+ */
+ private IntegerDeclaration parseInteger(CommonTree integer)
+ throws ParseException {
+ assert (integer.getType() == CTFParser.INTEGER);
+
+ List<CommonTree> children = integer.getChildren();
+
+ /*
+ * If the integer has no attributes, then it is missing the size
+ * attribute which is required
+ */
+ if (children == null) {
+ throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
+ }
+
+ /* The return value */
+ IntegerDeclaration integerDeclaration = null;
+ boolean signed = false;
+ ByteOrder byteOrder = trace.getByteOrder();
+ long size = 0;
+ long alignment = 0;
+ int base = 10;
+ String clock = null;
+
+ Encoding encoding = Encoding.NONE;
+
+ /* 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
+ */
+ assert (child.getChildCount() == 2);
+
+ CommonTree leftNode = (CommonTree) child.getChild(0);
+ assert (leftNode.getType() == CTFParser.CTF_LEFT);
+ CommonTree rightNode = (CommonTree) child.getChild(1);
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+
+ List<CommonTree> leftStrings = leftNode.getChildren();
+ assert (leftStrings != null);
+
+ if (!isUnaryString(leftStrings.get(0))) {
+ throw new ParseException(
+ "Left side of ctf expression must be a string"); //$NON-NLS-1$
+ }
+ String left = concatenateUnaryStrings(leftStrings);
+
+ if (left.equals("signed")) { //$NON-NLS-1$
+ signed = getSigned(rightNode);
+ } else if (left.equals("byte_order")) { //$NON-NLS-1$
+ byteOrder = getByteOrder(rightNode);
+ } else if (left.equals("size")) { //$NON-NLS-1$
+ size = getSize(rightNode);
+ } else if (left.equals("align")) { //$NON-NLS-1$
+ alignment = getAlignment(rightNode);
+ } else if (left.equals("base")) { //$NON-NLS-1$
+ base = getBase(rightNode);
+ } else if (left.equals("encoding")) { //$NON-NLS-1$
+ encoding = getEncoding(rightNode);
+ } else if (left.equals("map")) { //$NON-NLS-1$
+ clock = getClock(rightNode);
+ } else {
+ throw new ParseException("Integer: unknown attribute " + left); //$NON-NLS-1$
+ }
+
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ if (size == 0) {
+ throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
+ }
+
+ if (alignment == 0) {
+ if ((size % 8) == 0) {
+ alignment = 1;
+ } else {
+ alignment = 8;
+ }
+ }
+
+ integerDeclaration = new IntegerDeclaration((int) size, signed, base,
+ byteOrder, encoding, clock);
+
+ assert (integerDeclaration != null);
+ return integerDeclaration;
+ }
+
+ private static String getClock(CommonTree rightNode) {
+ return rightNode.getChild(1).getChild(0).getChild(0).getText();
+ }
+
+ private static StringDeclaration parseString(CommonTree string)
+ throws ParseException {
+ assert (string.getType() == CTFParser.STRING);
+
+ List<CommonTree> children = string.getChildren();
+ StringDeclaration stringDeclaration = null;
+
+ if (children == null) {
+ stringDeclaration = new StringDeclaration();
+ } else {
+ Encoding encoding = Encoding.UTF8;
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.CTF_EXPRESSION_VAL:
+ /*
+ * An assignment expression must have 2 children, left and
+ * right
+ */
+ assert (child.getChildCount() == 2);
+
+ CommonTree leftNode = (CommonTree) child.getChild(0);
+ assert (leftNode.getType() == CTFParser.CTF_LEFT);
+ CommonTree rightNode = (CommonTree) child.getChild(1);
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+
+ List<CommonTree> leftStrings = leftNode.getChildren();
+ assert (leftStrings != null);
+
+ if (!isUnaryString(leftStrings.get(0))) {
+ throw new ParseException(
+ "Left side of ctf expression must be a string"); //$NON-NLS-1$
+ }
+ String left = concatenateUnaryStrings(leftStrings);
+
+ if (left.equals("encoding")) { //$NON-NLS-1$
+ encoding = getEncoding(rightNode);
+ } else {
+ throw new ParseException("String: unknown attribute " //$NON-NLS-1$
+ + left);
+ }
+
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ stringDeclaration = new StringDeclaration(encoding);
+ }
+
+ return stringDeclaration;
+ }
+
+ /**
+ * Parses a struct declaration and returns the corresponding declaration.
+ *
+ * @param struct
+ * An STRUCT node.
+ * @return The corresponding struct declaration.
+ * @throws ParseException
+ */
+ private StructDeclaration parseStruct(CommonTree struct)
+ throws ParseException {
+ assert (struct.getType() == CTFParser.STRUCT);
+
+ List<CommonTree> children = struct.getChildren();
+ assert (children != null);
+
+ /* The return value */
+ StructDeclaration structDeclaration = null;
+
+ /* Name */
+ String structName = null;
+ boolean hasName = false;
+
+ /* Body */
+ CommonTree structBody = null;
+ boolean hasBody = false;
+
+ /* Align */
+ long structAlign = 0;
+
+ /* Loop on all children and identify what we have to work with. */
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.STRUCT_NAME: {
+ hasName = true;
+
+ assert (child.getChildCount() == 1);
+ CommonTree structNameIdentifier = (CommonTree) child
+ .getChild(0);
+
+ assert (structNameIdentifier.getType() == CTFParser.IDENTIFIER);
+ structName = structNameIdentifier.getText();
+
+ break;
+ }
+ case CTFParser.STRUCT_BODY: {
+ hasBody = true;
+
+ structBody = child;
+
+ break;
+ }
+ case CTFParser.ALIGN: {
+ assert (child.getChildCount() == 1);
+ CommonTree structAlignExpression = (CommonTree) child
+ .getChild(0);
+
+ structAlign = getAlignment(structAlignExpression);
+
+ break;
+ }
+ default:
+ childTypeError(child);
+
+ break;
+ }
+ }
+
+ /*
+ * If a struct has just a body and no name (just like the song,
+ * "A Struct With No Name" by America (sorry for that...)), it's a
+ * definition of a new type, so we create the type declaration and
+ * return it. We can't add it to the declaration scope since there is no
+ * name, but that's what we want because it won't be possible to use it
+ * again to declare another field.
+ *
+ * If it has just a name, we look it up in the declaration scope and
+ * return the associated declaration. If it is not found in the
+ * declaration scope, it means that a struct with that name has not been
+ * declared, which is an error.
+ *
+ * If it has both, then we create the type declaration and register it
+ * to the current scope.
+ *
+ * If it has none, then what are we doing here ?
+ */
+ if (hasBody) {
+ /*
+ * If struct has a name, check if already defined in the current
+ * scope.
+ */
+ if (hasName && (getCurrentScope().lookupStruct(structName) != null)) {
+ throw new ParseException("struct " + structName //$NON-NLS-1$
+ + " already defined."); //$NON-NLS-1$
+ }
+
+ /* Create the declaration */
+ structDeclaration = new StructDeclaration(structAlign);
+
+ /* Parse the body */
+ parseStructBody(structBody, structDeclaration);
+
+ /* If struct has name, add it to the current scope. */
+ if (hasName) {
+ getCurrentScope().registerStruct(structName, structDeclaration);
+ }
+ } else /* !hasBody */{
+ if (hasName) {
+ /* Name and !body */
+
+ /* Lookup the name in the current scope. */
+ structDeclaration = getCurrentScope().rlookupStruct(structName);
+
+ /*
+ * If not found, it means that a struct with such name has not
+ * been defined
+ */
+ if (structDeclaration == null) {
+ throw new ParseException("struct " + structName //$NON-NLS-1$
+ + " is not defined"); //$NON-NLS-1$
+ }
+ } else {
+ /* !Name and !body */
+
+ /* We can't do anything with that. */
+ throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
+ }
+ }
+
+ assert (structDeclaration != null);
+ return structDeclaration;
+ }
+
+ /**
+ * Parses a struct body, adding the fields to specified structure
+ * declaration.
+ *
+ * @param structBody
+ * A STRUCT_BODY node.
+ * @param structDeclaration
+ * The struct declaration.
+ * @throws ParseException
+ */
+ private void parseStructBody(CommonTree structBody,
+ StructDeclaration structDeclaration) throws ParseException {
+ assert (structBody.getType() == CTFParser.STRUCT_BODY);
+
+ List<CommonTree> structDeclarations = structBody.getChildren();
+
+ /*
+ * If structDeclaration is null, structBody has no children and the
+ * struct body is empty.
+ */
+ if (structDeclarations != null) {
+ pushScope();
+
+ for (CommonTree declarationNode : structDeclarations) {
+ switch (declarationNode.getType()) {
+ case CTFParser.TYPEALIAS:
+ parseTypealias(declarationNode);
+ break;
+ case CTFParser.TYPEDEF:
+ parseTypedef(declarationNode);
+ break;
+ case CTFParser.SV_DECLARATION:
+ parseStructDeclaration(declarationNode, structDeclaration);
+ break;
+ default:
+ childTypeError(declarationNode);
+ break;
+ }
+ }
+ popScope();
+ }
+ }
+
+ /**
+ * Parses a declaration found in a struct.
+ *
+ * @param declaration
+ * A SV_DECLARATION node.
+ * @param struct
+ * A struct declaration. (I know, little name clash here...)
+ * @throws ParseException
+ */
+ private void parseStructDeclaration(CommonTree declaration,
+ StructDeclaration struct) throws ParseException {
+ assert (declaration.getType() == CTFParser.SV_DECLARATION);
+
+ List<CommonTree> children = declaration.getChildren();
+ assert (children != null);
+
+ /* Get the type specifier list node */
+ CommonTree typeSpecifierListNode = (CommonTree) declaration
+ .getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
+ assert (typeSpecifierListNode != null);
+
+ /* Get the type declarator list node */
+ CommonTree typeDeclaratorListNode = (CommonTree) declaration
+ .getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
+ assert (typeDeclaratorListNode != null);
+
+ /* Get the type declarator list */
+ List<CommonTree> typeDeclaratorList = typeDeclaratorListNode
+ .getChildren();
+ assert (typeDeclaratorList != null);
+
+ /*
+ * For each type declarator, parse the declaration and add a field to
+ * the struct
+ */
+ for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
+ assert (typeDeclaratorNode.getType() == CTFParser.TYPE_DECLARATOR);
+
+ StringBuilder identifierSB = new StringBuilder();
+
+ IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
+ typeSpecifierListNode, identifierSB);
+ String fieldName = identifierSB.toString();
+
+ if (struct.hasField(fieldName)) {
+ throw new ParseException("struct: duplicate field " //$NON-NLS-1$
+ + fieldName);
+ }
+
+ struct.addField(fieldName, decl);
+
+ }
+ }
+
+ /**
+ * Parses an enum declaration and returns the corresponding declaration.
+ *
+ * @param _enum
+ * An ENUM node.
+ * @return The corresponding enum declaration.
+ * @throws ParseException
+ */
+ private EnumDeclaration parseEnum(CommonTree _enum) throws ParseException {
+ assert (_enum.getType() == CTFParser.ENUM);
+
+ List<CommonTree> children = _enum.getChildren();
+ assert (children != null);
+
+ /* The return value */
+ EnumDeclaration enumDeclaration = null;
+
+ /* Name */
+ String enumName = null;
+
+ /* Body */
+ CommonTree enumBody = null;
+
+ /* Container type */
+ IntegerDeclaration containerTypeDeclaration = null;
+
+ /* Loop on all children and identify what we have to work with. */
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.ENUM_NAME: {
+ assert (enumName == null);
+
+ assert (child.getChildCount() == 1);
+ CommonTree enumNameIdentifier = (CommonTree) child.getChild(0);
+
+ assert (enumNameIdentifier.getType() == CTFParser.IDENTIFIER);
+ enumName = enumNameIdentifier.getText();
+
+ break;
+ }
+ case CTFParser.ENUM_BODY: {
+ assert (enumBody == null);
+
+ enumBody = child;
+
+ break;
+ }
+ case CTFParser.ENUM_CONTAINER_TYPE: {
+ assert (containerTypeDeclaration == null);
+
+ containerTypeDeclaration = parseEnumContainerType(child);
+
+ break;
+ }
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ /*
+ * If the container type has not been defined explicitly, we assume it
+ * is "int".
+ */
+ if (containerTypeDeclaration == null) {
+ IDeclaration decl = getCurrentScope().rlookupType("int"); //$NON-NLS-1$
+
+ if (decl == null) {
+ throw new ParseException(
+ "enum container type implicit and type int not defined"); //$NON-NLS-1$
+ } else if (!(decl instanceof IntegerDeclaration)) {
+ throw new ParseException(
+ "enum container type implicit and type int not an integer"); //$NON-NLS-1$
+ }
+
+ containerTypeDeclaration = (IntegerDeclaration) decl;
+ }
+
+ /*
+ * If it has a body, it's a new declaration, otherwise it's a reference
+ * to an existing declaration. Same logic as struct.
+ */
+ if (enumBody != null) {
+ /*
+ * If enum has a name, check if already defined in the current
+ * scope.
+ */
+ if ((enumName != null)
+ && (getCurrentScope().lookupEnum(enumName) != null)) {
+ throw new ParseException("enum " + enumName //$NON-NLS-1$
+ + " already defined"); //$NON-NLS-1$
+ }
+
+ /* Create the declaration */
+ enumDeclaration = new EnumDeclaration(containerTypeDeclaration);
+
+ /* Parse the body */
+ parseEnumBody(enumBody, enumDeclaration);
+
+ /* If the enum has name, add it to the current scope. */
+ if (enumName != null) {
+ getCurrentScope().registerEnum(enumName, enumDeclaration);
+ }
+ } else {
+ if (enumName != null) {
+ /* Name and !body */
+
+ /* Lookup the name in the current scope. */
+ enumDeclaration = getCurrentScope().rlookupEnum(enumName);
+
+ /*
+ * If not found, it means that an enum with such name has not
+ * been defined
+ */
+ if (enumDeclaration == null) {
+ throw new ParseException("enum " + enumName //$NON-NLS-1$
+ + " is not defined"); //$NON-NLS-1$
+ }
+ } else {
+ /* !Name and !body */
+ throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
+ }
+ }
+
+ return enumDeclaration;
+
+ }
+
+ /**
+ * Parses an enum body, adding the enumerators to the specified enum
+ * declaration.
+ *
+ * @param enumBody
+ * An ENUM_BODY node.
+ * @param enumDeclaration
+ * The enum declaration.
+ * @throws ParseException
+ */
+ private void parseEnumBody(CommonTree enumBody,
+ EnumDeclaration enumDeclaration) throws ParseException {
+ assert (enumBody.getType() == CTFParser.ENUM_BODY);
+
+ List<CommonTree> enumerators = enumBody.getChildren();
+ /* enum body can't be empty (unlike struct). */
+ assert (enumerators != null);
+
+ pushScope();
+
+ /*
+ * Start at -1, so that if the first enumrator has no explicit value, it
+ * will choose 0
+ */
+ long lastHigh = -1;
+
+ for (CommonTree enumerator : enumerators) {
+ lastHigh = parseEnumEnumerator(enumerator, enumDeclaration,
+ lastHigh);
+ }
+
+ popScope();
+
+ }
+
+ /**
+ * Parses an enumerator node and adds an enumerator declaration to an
+ * enumeration declaration.
+ *
+ * The high value of the range of the last enumerator is needed in case the
+ * current enumerator does not specify its value.
+ *
+ * @param enumerator
+ * An ENUM_ENUMERATOR node.
+ * @param enumDeclaration
+ * en enumeration declaration to which will be added the
+ * enumerator.
+ * @param lastHigh
+ * The high value of the range of the last enumerator
+ * @return The high value of the value range of the current enumerator.
+ * @throws ParseException
+ */
+ private static long parseEnumEnumerator(CommonTree enumerator,
+ EnumDeclaration enumDeclaration, long lastHigh)
+ throws ParseException {
+ assert (enumerator.getType() == CTFParser.ENUM_ENUMERATOR);
+
+ List<CommonTree> children = enumerator.getChildren();
+ assert (children != null);
+
+ long low = 0, high = 0;
+ boolean valueSpecified = false;
+ String label = null;
+
+ for (CommonTree child : children) {
+ if (isUnaryString(child)) {
+ label = parseUnaryString(child);
+ } else if (child.getType() == CTFParser.ENUM_VALUE) {
+ assert (child.getChildCount() == 1);
+ assert (isUnaryInteger((CommonTree) child.getChild(0)));
+
+ valueSpecified = true;
+
+ low = parseUnaryInteger((CommonTree) child.getChild(0));
+ high = low;
+ } else if (child.getType() == CTFParser.ENUM_VALUE_RANGE) {
+ assert (child.getChildCount() == 2);
+ assert (isUnaryInteger((CommonTree) child.getChild(0)));
+ assert (isUnaryInteger((CommonTree) child.getChild(1)));
+
+ valueSpecified = true;
+
+ low = parseUnaryInteger((CommonTree) child.getChild(0));
+ high = parseUnaryInteger((CommonTree) child.getChild(1));
+ } else {
+ childTypeError(child);
+ }
+ }
+
+ assert (label != null);
+
+ if (!valueSpecified) {
+ low = lastHigh + 1;
+ high = low;
+ }
+
+ if (low > high) {
+ throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
+ }
+
+ if (!enumDeclaration.add(low, high, label)) {
+ throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
+ }
+
+ return high;
+ }
+
+ /**
+ * Parses an enum container type node and returns the corresponding integer
+ * type.
+ *
+ * @param enumContainerType
+ * An ENUM_CONTAINER_TYPE node.
+ * @return An integer declaration corresponding to the container type.
+ * @throws ParseException
+ * If the type does not parse correctly or if it is not an
+ * integer type.
+ */
+ private IntegerDeclaration parseEnumContainerType(
+ CommonTree enumContainerType) throws ParseException {
+ assert (enumContainerType.getType() == CTFParser.ENUM_CONTAINER_TYPE);
+
+ /* Get the child, which should be a type specifier list */
+ assert (enumContainerType.getChildCount() == 1);
+ CommonTree typeSpecifierList = (CommonTree) enumContainerType
+ .getChild(0);
+
+ /* Parse it and get the corresponding declaration */
+ IDeclaration decl = parseTypeSpecifierList(typeSpecifierList, null);
+
+ /* If is is an integer, return it, else throw an error */
+ if (decl instanceof IntegerDeclaration) {
+ return (IntegerDeclaration) decl;
+ }
+ throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
+ }
+
+ private VariantDeclaration parseVariant(CommonTree variant)
+ throws ParseException {
+ assert (variant.getType() == CTFParser.VARIANT);
+
+ List<CommonTree> children = variant.getChildren();
+ VariantDeclaration variantDeclaration = null;
+
+ boolean hasName = false;
+ String variantName = null;
+
+ boolean hasBody = false;
+ CommonTree variantBody = null;
+
+ boolean hasTag = false;
+ String variantTag = null;
+
+ for (CommonTree child : children) {
+ switch (child.getType()) {
+ case CTFParser.VARIANT_NAME:
+ assert (variantName == null);
+
+ hasName = true;
+
+ assert (child.getChildCount() == 1);
+ CommonTree variantNameIdentifier = (CommonTree) child
+ .getChild(0);
+
+ assert (variantNameIdentifier.getType() == CTFParser.IDENTIFIER);
+ variantName = variantNameIdentifier.getText();
+
+ break;
+ case CTFParser.VARIANT_TAG:
+ assert (variantTag == null);
+
+ hasTag = true;
+
+ assert (child.getChildCount() == 1);
+ CommonTree variantTagIdentifier = (CommonTree) child
+ .getChild(0);
+
+ assert (variantTagIdentifier.getType() == CTFParser.IDENTIFIER);
+ variantTag = variantTagIdentifier.getText();
+
+ break;
+ case CTFParser.VARIANT_BODY:
+ assert (variantBody == null);
+
+ hasBody = true;
+
+ variantBody = child;
+
+ break;
+ default:
+ childTypeError(child);
+ break;
+ }
+ }
+
+ if (hasBody) {
+ /*
+ * If variant has a name, check if already defined in the current
+ * scope.
+ */
+ if (hasName
+ && (getCurrentScope().lookupVariant(variantName) != null)) {
+ throw new ParseException("variant " + variantName //$NON-NLS-1$
+ + " already defined."); //$NON-NLS-1$
+ }
+
+ /* Create the declaration */
+ variantDeclaration = new VariantDeclaration();
+
+ /* Parse the body */
+ parseVariantBody(variantBody, variantDeclaration);
+
+ /* If variant has name, add it to the current scope. */
+ if (hasName) {
+ getCurrentScope().registerVariant(variantName,
+ variantDeclaration);
+ }
+ } else /* !hasBody */{
+ if (hasName) {
+ /* Name and !body */
+
+ /* Lookup the name in the current scope. */
+ variantDeclaration = getCurrentScope().rlookupVariant(
+ variantName);
+
+ /*
+ * If not found, it means that a struct with such name has not
+ * been defined
+ */
+ if (variantDeclaration == null) {
+ throw new ParseException("variant " + variantName //$NON-NLS-1$
+ + " is not defined"); //$NON-NLS-1$
+ }
+ } else {
+ /* !Name and !body */
+
+ /* We can't do anything with that. */
+ throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
+ }
+ }
+
+ if (hasTag) {
+ variantDeclaration.setTag(variantTag);
+ }
+
+ assert (variantDeclaration != null);
+ return variantDeclaration;
+ }
+
+ private void parseVariantBody(CommonTree variantBody,
+ VariantDeclaration variantDeclaration) throws ParseException {
+ assert (variantBody.getType() == CTFParser.VARIANT_BODY);
+
+ List<CommonTree> variantDeclarations = variantBody.getChildren();
+ assert (variantDeclarations != null);
+
+ pushScope();
+
+ for (CommonTree declarationNode : variantDeclarations) {
+ switch (declarationNode.getType()) {
+ case CTFParser.TYPEALIAS:
+ parseTypealias(declarationNode);
+ break;
+ case CTFParser.TYPEDEF:
+ parseTypedef(declarationNode);
+ break;
+ case CTFParser.SV_DECLARATION:
+ parseVariantDeclaration(declarationNode, variantDeclaration);
+ break;
+ default:
+ childTypeError(declarationNode);
+ break;
+ }
+ }
+
+ popScope();
+ }
+
+ private void parseVariantDeclaration(CommonTree declaration,
+ VariantDeclaration variant) throws ParseException {
+ assert (declaration.getType() == CTFParser.SV_DECLARATION);
+
+ List<CommonTree> children = declaration.getChildren();
+ assert (children != null);
+
+ /* Get the type specifier list node */
+ CommonTree typeSpecifierListNode = (CommonTree) declaration
+ .getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
+ assert (typeSpecifierListNode != null);
+
+ /* Get the type declarator list node */
+ CommonTree typeDeclaratorListNode = (CommonTree) declaration
+ .getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
+ assert (typeDeclaratorListNode != null);
+
+ /* Get the type declarator list */
+ List<CommonTree> typeDeclaratorList = typeDeclaratorListNode
+ .getChildren();
+ assert (typeDeclaratorList != null);
+
+ /*
+ * For each type declarator, parse the declaration and add a field to
+ * the variant
+ */
+ for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
+ assert (typeDeclaratorNode.getType() == CTFParser.TYPE_DECLARATOR);
+
+ StringBuilder identifierSB = new StringBuilder();
+
+ IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
+ typeSpecifierListNode, identifierSB);
+
+ if (variant.hasField(identifierSB.toString())) {
+ throw new ParseException("variant: duplicate field " //$NON-NLS-1$
+ + identifierSB.toString());
+ }
+
+ variant.addField(identifierSB.toString(), decl);
+ }
+ }
+
+ /**
+ * Creates the string representation of a type declaration (type specifier
+ * list + pointers).
+ *
+ * @param typeSpecifierList
+ * A TYPE_SPECIFIER_LIST node.
+ * @param pointers
+ * A list of POINTER nodes.
+ * @return The string representation.
+ * @throws ParseException
+ */
+ private static String createTypeDeclarationString(
+ CommonTree typeSpecifierList, List<CommonTree> pointers)
+ throws ParseException {
+ StringBuilder sb = new StringBuilder();
+
+ createTypeSpecifierListString(typeSpecifierList, sb);
+ createPointerListString(pointers, sb);
+
+ return sb.toString();
+ }
+
+ /**
+ * Creates the string representation of a list of type specifiers.
+ *
+ * @param typeSpecifierList
+ * A TYPE_SPECIFIER_LIST node.
+ * @param sb
+ * A StringBuilder to which will be appended the string.
+ * @throws ParseException
+ */
+ private static void createTypeSpecifierListString(
+ CommonTree typeSpecifierList, StringBuilder sb)
+ throws ParseException {
+ assert (typeSpecifierList.getType() == CTFParser.TYPE_SPECIFIER_LIST);
+
+ List<CommonTree> children = typeSpecifierList.getChildren();
+ assert (children != null);
+
+ boolean firstItem = true;
+
+ for (CommonTree child : children) {
+ if (!firstItem) {
+ sb.append(' ');
+
+ }
+
+ firstItem = false;
+
+ /* Append the string that represents this type specifier. */
+ createTypeSpecifierString(child, sb);
+ }
+ }
+
+ /**
+ * Creates the string representation of a type specifier.
+ *
+ * @param typeSpecifier
+ * A TYPE_SPECIFIER node.
+ * @param sb
+ * A StringBuilder to which will be appended the string.
+ * @throws ParseException
+ */
+ private static void createTypeSpecifierString(CommonTree typeSpecifier,
+ StringBuilder sb) throws ParseException {
+ switch (typeSpecifier.getType()) {
+ case CTFParser.FLOATTOK:
+ case CTFParser.INTTOK:
+ case CTFParser.LONGTOK:
+ case CTFParser.SHORTTOK:
+ case CTFParser.SIGNEDTOK:
+ case CTFParser.UNSIGNEDTOK:
+ case CTFParser.CHARTOK:
+ case CTFParser.DOUBLETOK:
+ case CTFParser.VOIDTOK:
+ case CTFParser.BOOLTOK:
+ case CTFParser.COMPLEXTOK:
+ case CTFParser.IMAGINARYTOK:
+ case CTFParser.CONSTTOK:
+ case CTFParser.IDENTIFIER:
+ sb.append(typeSpecifier.getText());
+ break;
+ case CTFParser.STRUCT: {
+ CommonTree structName = (CommonTree) typeSpecifier
+ .getFirstChildWithType(CTFParser.STRUCT_NAME);
+ if (structName == null) {
+ throw new ParseException(
+ "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
+ }
+ assert (structName.getChildCount() == 1);
+
+ CommonTree structNameIdentifier = (CommonTree) structName
+ .getChild(0);
+ assert (structNameIdentifier.getType() == CTFParser.IDENTIFIER);
+
+ sb.append(structNameIdentifier.getText());
+ break;
+ }
+ case CTFParser.VARIANT: {
+ CommonTree variantName = (CommonTree) typeSpecifier
+ .getFirstChildWithType(CTFParser.VARIANT_NAME);
+ if (variantName == null) {
+ throw new ParseException(
+ "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
+ }
+ assert (variantName.getChildCount() == 1);
+
+ CommonTree variantNameIdentifier = (CommonTree) variantName
+ .getChild(0);
+ assert (variantNameIdentifier.getType() == CTFParser.IDENTIFIER);
+
+ sb.append(variantNameIdentifier.getText());
+ break;
+ }
+ case CTFParser.ENUM: {
+ CommonTree enumName = (CommonTree) typeSpecifier
+ .getFirstChildWithType(CTFParser.ENUM_NAME);
+ if (enumName == null) {
+ throw new ParseException(
+ "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
+ }
+ assert (enumName.getChildCount() == 1);
+
+ CommonTree enumNameIdentifier = (CommonTree) enumName.getChild(0);
+ assert (enumNameIdentifier.getType() == CTFParser.IDENTIFIER);
+
+ sb.append(enumNameIdentifier.getText());
+ break;
+ }
+ case CTFParser.FLOATING_POINT:
+ case CTFParser.INTEGER:
+ case CTFParser.STRING:
+ throw new ParseException(
+ "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
+ /* break; */
+ default:
+ childTypeError(typeSpecifier);
+ break;
+ }
+ }
+
+ /**
+ * Creates the string representation of a list of pointers.
+ *
+ * @param pointerList
+ * A list of pointer nodes. If pointerList is null, this function
+ * does nothing.
+ * @param sb
+ * A stringbuilder to which will be appended the string.
+ */
+ private static void createPointerListString(List<CommonTree> pointerList,
+ StringBuilder sb) {
+ if (pointerList == null) {
+ return;
+ }
+
+ for (CommonTree pointer : pointerList) {
+ assert (pointer.getType() == CTFParser.POINTER);
+
+ sb.append(" *"); //$NON-NLS-1$
+ if (pointer.getChildCount() > 0) {
+ assert (pointer.getChildCount() == 1);
+ CommonTree constQualifier = (CommonTree) pointer.getChild(0);
+ assert (constQualifier.getType() == CTFParser.CONSTTOK);
+
+ sb.append(" const"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * @param node
+ * The node to check.
+ * @return True if the given node is an unary string or unary integer.
+ */
+ private static boolean isUnaryExpression(CommonTree node) {
+ return isUnaryInteger(node) || isUnaryString(node);
+ }
+
+ /**
+ * @param node
+ * The node to check.
+ * @return True if the given node is an unary string.
+ */
+ private static boolean isUnaryString(CommonTree node) {
+ return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING) || (node
+ .getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES));
+ }
+
+ /**
+ * @param node
+ * The node to check.
+ * @return True if the given node is an unary integer.
+ */
+ private static boolean isUnaryInteger(CommonTree node) {
+ return ((node.getType() == CTFParser.UNARY_EXPRESSION_DEC)
+ || (node.getType() == CTFParser.UNARY_EXPRESSION_HEX) || (node
+ .getType() == CTFParser.UNARY_EXPRESSION_OCT));
+ }
+
+ /**
+ * Parses a unary string node and return the string value.
+ *
+ * @param unaryString
+ * The unary string node to parse (type UNARY_EXPRESSION_STRING
+ * or UNARY_EXPRESSION_STRING_QUOTES).
+ * @return The string value.
+ */
+ /*
+ * It would be really nice to remove the quotes earlier, such as in the
+ * parser.
+ */
+ private static String parseUnaryString(CommonTree unaryString) {
+ assert (isUnaryString(unaryString));
+
+ assert (unaryString.getChildCount() == 1);
+ CommonTree value = (CommonTree) unaryString.getChild(0);
+ assert (value != null);
+ String strval = value.getText();
+
+ /* Remove quotes */
+ if (unaryString.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES) {
+ strval = strval.substring(1, strval.length() - 1);
+ }
+
+ return strval;
+ }
+
+ /**
+ * Parses an unary integer (dec, hex or oct).
+ *
+ * @param unaryInteger
+ * An unary integer node.
+ * @return The integer value.
+ */
+ private static long parseUnaryInteger(CommonTree unaryInteger) {
+ assert (isUnaryInteger(unaryInteger));
+
+ assert (unaryInteger.getChildCount() >= 1);
+
+ List<CommonTree> children = unaryInteger.getChildren();
+ CommonTree value = children.get(0);
+ String strval = value.getText();
+
+ long intval;
+
+ if (unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_DEC) {
+ intval = Long.parseLong(strval, 10);
+ } else if (unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_HEX) {
+ intval = Long.parseLong(strval, 0x10);
+ } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
+ intval = Long.parseLong(strval, 010); // 010 == 0x08 == 8
+ }
+
+ /* The rest of children are sign */
+ if ((children.size() % 2) == 0) {
+ return -intval;
+ }
+ return intval;
+ }
+
+ private static long getMajorOrMinor(CommonTree rightNode)
+ throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryInteger(firstChild)) {
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
+ }
+
+ long m = parseUnaryInteger(firstChild);
+
+ if (m < 0) {
+ throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
+ }
+
+ return m;
+ }
+ throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
+ }
+
+ private static UUID getUUID(CommonTree rightNode) throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryString(firstChild)) {
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
+ }
+
+ String uuidstr = parseUnaryString(firstChild);
+
+ try {
+ UUID uuid = UUID.fromString(uuidstr);
+ return uuid;
+ } catch (IllegalArgumentException e) {
+ throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
+ }
+ }
+ throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the value of a "signed" integer attribute.
+ *
+ * @param rightNode
+ * A CTF_RIGHT node.
+ * @return The "signed" value as a boolean.
+ * @throws ParseException
+ */
+ private static boolean getSigned(CommonTree rightNode)
+ throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ boolean ret = false;
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryString(firstChild)) {
+ String strval = concatenateUnaryStrings(rightNode.getChildren());
+
+ if (strval.equals("true") || strval.equals("TRUE")) { //$NON-NLS-1$ //$NON-NLS-2$
+ ret = true;
+ } else if (strval.equals("false") || strval.equals("FALSE")) { //$NON-NLS-1$ //$NON-NLS-2$
+ ret = false;
+ } else {
+ throw new ParseException("Invalid boolean value " //$NON-NLS-1$
+ + firstChild.getChild(0).getText());
+ }
+ } else if (isUnaryInteger(firstChild)) {
+ /* Happens if the value is something like "1234.hello" */
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
+ }
+
+ long intval = parseUnaryInteger(firstChild);
+
+ if (intval == 1) {
+ ret = true;
+ } else if (intval == 0) {
+ ret = false;
+ } else {
+ throw new ParseException("Invalid boolean value " //$NON-NLS-1$
+ + firstChild.getChild(0).getText());
+ }
+ } else {
+ throw new ParseException();
+ }
+
+ return ret;
+ }
+
+ /**
+ * Gets the value of a "byte_order" integer attribute.
+ *
+ * @param rightNode
+ * A CTF_RIGHT node.
+ * @return The "byte_order" value.
+ * @throws ParseException
+ */
+ private ByteOrder getByteOrder(CommonTree rightNode) throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryString(firstChild)) {
+ String strval = concatenateUnaryStrings(rightNode.getChildren());
+
+ if (strval.equals("le")) { //$NON-NLS-1$
+ return ByteOrder.LITTLE_ENDIAN;
+ } else if (strval.equals("be") || strval.equals("network")) { //$NON-NLS-1$ //$NON-NLS-2$
+ return ByteOrder.BIG_ENDIAN;
+ } else if (strval.equals("native")) { //$NON-NLS-1$
+ return trace.getByteOrder();
+ } else {
+ throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
+ }
+ }
+ throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
+ }
+
+ /**
+ * Determines if the given value is a valid alignment value.
+ *
+ * @param alignment
+ * The value to check.
+ * @return True if it is valid.
+ */
+ private static boolean isValidAlignment(long alignment) {
+ return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
+ }
+
+ /**
+ * Gets the value of a "size" integer attribute.
+ *
+ * @param rightNode
+ * A CTF_RIGHT node.
+ * @return The "size" value.
+ * @throws ParseException
+ */
+ private static long getSize(CommonTree rightNode) throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryInteger(firstChild)) {
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("Invalid value for size"); //$NON-NLS-1$
+ }
+
+ long size = parseUnaryInteger(firstChild);
+
+ if (size < 1) {
+ throw new ParseException("Invalid value for size"); //$NON-NLS-1$
+ }
+
+ return size;
+ }
+ throw new ParseException("Invalid value for size"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the value of a "align" integer or struct attribute.
+ *
+ * @param node
+ * A CTF_RIGHT node or directly an unary integer.
+ * @return The align value.
+ * @throws ParseException
+ */
+ private static long getAlignment(CommonTree node) throws ParseException {
+ assert (isUnaryExpression(node) || (node.getType() == CTFParser.CTF_RIGHT));
+
+ /*
+ * If a CTF_RIGHT node was passed, call getAlignment with the first
+ * child
+ */
+ if (node.getType() == CTFParser.CTF_RIGHT) {
+ if (node.getChildCount() > 1) {
+ throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
+ }
+
+ return getAlignment((CommonTree) node.getChild(0));
+ } else if (isUnaryInteger(node)) {
+ long alignment = parseUnaryInteger(node);
+
+ if (!isValidAlignment(alignment)) {
+ throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
+ + alignment);
+ }
+
+ return alignment;
+ }
+ throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets the value of a "base" integer attribute.
+ *
+ * @param rightNode
+ * An CTF_RIGHT node.
+ * @return The "base" value.
+ * @throws ParseException
+ */
+ private static int getBase(CommonTree rightNode) throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryInteger(firstChild)) {
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("invalid base value"); //$NON-NLS-1$
+ }
+
+ long intval = parseUnaryInteger(firstChild);
+ if ((intval == 2) || (intval == 8) || (intval == 10)
+ || (intval == 16)) {
+ return (int) intval;
+ }
+ throw new ParseException("Invalid value for base"); //$NON-NLS-1$
+ } else if (isUnaryString(firstChild)) {
+ String strval = concatenateUnaryStrings(rightNode.getChildren());
+
+ if (strval.equals("decimal") || strval.equals("dec") //$NON-NLS-1$ //$NON-NLS-2$
+ || strval.equals("d") || strval.equals("i") //$NON-NLS-1$ //$NON-NLS-2$
+ || strval.equals("u")) { //$NON-NLS-1$
+ return 10;
+ } else if (strval.equals("hexadecimal") || strval.equals("hex") //$NON-NLS-1$ //$NON-NLS-2$
+ || strval.equals("x") || strval.equals("X") //$NON-NLS-1$ //$NON-NLS-2$
+ || strval.equals("p")) { //$NON-NLS-1$
+ return 16;
+ } else if (strval.equals("octal") || strval.equals("oct") //$NON-NLS-1$ //$NON-NLS-2$
+ || strval.equals("o")) { //$NON-NLS-1$
+ return 8;
+ } else if (strval.equals("binary") || strval.equals("b")) { //$NON-NLS-1$ //$NON-NLS-2$
+ return 2;
+ } else {
+ throw new ParseException("Invalid value for base"); //$NON-NLS-1$
+ }
+ } else {
+ throw new ParseException("invalid value for base"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Gets the value of an "encoding" integer attribute.
+ *
+ * @param rightNode
+ * A CTF_RIGHT node.
+ * @return The "encoding" value.
+ * @throws ParseException
+ */
+ private static Encoding getEncoding(CommonTree rightNode)
+ throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryString(firstChild)) {
+ String strval = concatenateUnaryStrings(rightNode.getChildren());
+
+ if (strval.equals("UTF8")) { //$NON-NLS-1$
+ return Encoding.UTF8;
+ } else if (strval.equals("ASCII")) { //$NON-NLS-1$
+ return Encoding.ASCII;
+ } else if (strval.equals("none")) { //$NON-NLS-1$
+ return Encoding.NONE;
+ } else {
+ throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
+ }
+ }
+ throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
+ }
+
+ private static long getStreamID(CommonTree rightNode) throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryInteger(firstChild)) {
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
+ }
+
+ long intval = parseUnaryInteger(firstChild);
+
+ return intval;
+ }
+ throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
+ }
+
+ private static String getEventName(CommonTree rightNode)
+ throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryString(firstChild)) {
+ String str = concatenateUnaryStrings(rightNode.getChildren());
+
+ return str;
+ }
+ throw new ParseException("invalid value for event name"); //$NON-NLS-1$
+ }
+
+ private static long getEventID(CommonTree rightNode) throws ParseException {
+ assert (rightNode.getType() == CTFParser.CTF_RIGHT);
+ assert (rightNode.getChildCount() > 0);
+
+ CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+
+ if (isUnaryInteger(firstChild)) {
+ if (rightNode.getChildCount() > 1) {
+ throw new ParseException("invalid value for event id"); //$NON-NLS-1$
+ }
+
+ long intval = parseUnaryInteger(firstChild);
+
+ return intval;
+ }
+ throw new ParseException("invalid value for event id"); //$NON-NLS-1$
+ }
+
+ /**
+ * Concatenates a list of unary strings separated by arrows (->) or dots.
+ *
+ * @param strings
+ * A list, first element being an unary string, subsequent
+ * elements being ARROW or DOT nodes with unary strings as child.
+ * @return The string representation of the unary string chain.
+ */
+ private static String concatenateUnaryStrings(List<CommonTree> strings) {
+ assert ((strings != null) && (strings.size() > 0));
+
+ StringBuilder sb = new StringBuilder();
+
+ CommonTree first = strings.get(0);
+ sb.append(parseUnaryString(first));
+
+ boolean isFirst = true;
+
+ for (CommonTree ref : strings) {
+ if (isFirst) {
+ isFirst = false;
+ continue;
+ }
+
+ assert ((ref.getType() == CTFParser.ARROW) || (ref.getType() == CTFParser.DOT));
+ assert (ref.getChildCount() == 1);
+
+ CommonTree id = (CommonTree) ref.getChild(0);
+
+ if (ref.getType() == CTFParser.ARROW) {
+ sb.append("->"); //$NON-NLS-1$
+ } else { /* DOT */
+ sb.append('.');
+ }
+
+ sb.append(parseUnaryString(id));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Throws a ParseException stating that the parent-child relation between
+ * the given node and its parent is not valid. It means that the shape of
+ * the AST is unexpected.
+ *
+ * @param child
+ * The invalid child node.
+ * @throws ParseException
+ */
+ private static void childTypeError(CommonTree child) throws ParseException {
+ CommonTree parent = (CommonTree) child.getParent();
+ String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
+ + " can't have a child of type " //$NON-NLS-1$
+ + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
+
+ throw new ParseException(error);
+ }
+
+ // ------------------------------------------------------------------------
+ // Scope management
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds a new declaration scope on the top of the scope stack.
+ */
+ private void pushScope() {
+ scope = new DeclarationScope(scope);
+ }
+
+ /**
+ * Removes the top declaration scope from the scope stack.
+ */
+ private void popScope() {
+ assert (scope != null);
+ scope = scope.getParentScope();
+ }
+
+ /**
+ * Returns the current declaration scope.
+ *
+ * @return The current declaration scope.
+ */
+ private DeclarationScope getCurrentScope() {
+ assert (scope != null);
+ return scope;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.ctf.core.trace;
+
+/**
+ * <b><u>StreamInputPacketIndexEntry</u></b>
+ * <p>
+ * Represents an entry in the index of event packets.
+ */
+public class StreamInputPacketIndexEntry {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+
+
+ /**
+ * Offset of the packet in the file, in bytes
+ */
+ final private long offsetBytes;
+
+ /**
+ * Offset of the data in the packet, in bits
+ */
+ private int dataOffsetBits = 0;
+
+ /**
+ * Packet size, in bits
+ */
+ private int packetSizeBits = 0;
+
+ /**
+ * Content size, in bits
+ */
+ private int contentSizeBits = 0;
+
+ /**
+ * Begin timestamp
+ */
+ private long timestampBegin = 0;
+
+ /**
+ * End timestamp
+ */
+ private long timestampEnd = 0;
+
+
+ private long indexBegin = Long.MAX_VALUE;
+
+ private long indexEnd = Long.MAX_VALUE;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs an index entry.
+ *
+ * @param offset
+ * The offset of the packet in the file, in bytes.
+ */
+
+ public StreamInputPacketIndexEntry(long offset) {
+ this.offsetBytes = offset;
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns whether the packet includes (inclusively) the given timestamp in
+ * the begin-end timestamp range.
+ *
+ * @param ts
+ * The timestamp to check.
+ * @return True if the packet includes the timestamp.
+ */
+ boolean includes(long ts) {
+ return (ts >= timestampBegin) && (ts <= timestampEnd);
+ }
+
+ boolean includesIndex(long index){
+ return (index >= indexBegin) && (index <= indexEnd);
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "StreamInputPacketIndexEntry [offsetBytes=" + offsetBytes //$NON-NLS-1$
+ + ", timestampBegin=" + timestampBegin + ", timestampEnd=" //$NON-NLS-1$ //$NON-NLS-2$
+ + timestampEnd + ", indexBegin=" + indexBegin + ", indexEnd=" //$NON-NLS-1$ //$NON-NLS-2$
+ + indexEnd + "]"; //$NON-NLS-1$
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters and Setters
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return the offsetBytes
+ */
+ public long getOffsetBytes() {
+ return offsetBytes;
+ }
+
+ /**
+ * @return the dataOffsetBits
+ */
+ public int getDataOffsetBits() {
+ return dataOffsetBits;
+ }
+
+ /**
+ * @param dataOffsetBits the dataOffsetBits to set
+ */
+ public void setDataOffsetBits(int dataOffsetBits) {
+ this.dataOffsetBits = dataOffsetBits;
+ }
+
+ /**
+ * @return the packetSizeBits
+ */
+ public int getPacketSizeBits() {
+ return packetSizeBits;
+ }
+
+ /**
+ * @param packetSizeBits the packetSizeBits to set
+ */
+ public void setPacketSizeBits(int packetSizeBits) {
+ this.packetSizeBits = packetSizeBits;
+ }
+
+ /**
+ * @return the contentSizeBits
+ */
+ public int getContentSizeBits() {
+ return contentSizeBits;
+ }
+
+ /**
+ * @param contentSizeBits the contentSizeBits to set
+ */
+ public void setContentSizeBits(int contentSizeBits) {
+ this.contentSizeBits = contentSizeBits;
+ }
+
+ /**
+ * @return the timestampBegin
+ */
+ public long getTimestampBegin() {
+ return timestampBegin;
+ }
+
+ /**
+ * @param timestampBegin the timestampBegin to set
+ */
+ public void setTimestampBegin(long timestampBegin) {
+ this.timestampBegin = timestampBegin;
+ }
+
+ /**
+ * @return the timestampEnd
+ */
+ public long getTimestampEnd() {
+ return timestampEnd;
+ }
+
+ /**
+ * @param timestampEnd the timestampEnd to set
+ */
+ public void setTimestampEnd(long timestampEnd) {
+ this.timestampEnd = timestampEnd;
+ }
+
+ /**
+ * @return the indexBegin
+ */
+ public long getIndexBegin() {
+ return indexBegin;
+ }
+
+ /**
+ * @param indexBegin the indexBegin to set
+ */
+ public void setIndexBegin(long indexBegin) {
+ this.indexBegin = indexBegin;
+ }
+
+ /**
+ * @return the indexEnd
+ */
+ public long getIndexEnd() {
+ return indexEnd;
+ }
+
+ /**
+ * @param indexEnd the indexEnd to set
+ */
+ public void setIndexEnd(long indexEnd) {
+ this.indexEnd = indexEnd;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.ctf.core.trace;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.eclipse.linuxtools.ctf.core.trace.StreamInputReader;
+
+/**
+ * <b><u>StreamInputReaderComparator</u></b>
+ * <p>
+ * TODO Implement me. Please.
+ */
+public class StreamInputReaderComparator implements
+ Comparator<StreamInputReader>, Serializable {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final long serialVersionUID = 7477206132343139753L;
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public int compare(StreamInputReader a, StreamInputReader b) {
+ // TODO: use unsigned comparison to avoid sign errors if needed
+ long ta = a.getCurrentEvent().timestamp;
+ long tb = b.getCurrentEvent().timestamp;
+
+ if (ta < tb) {
+ return -1;
+ } else if (ta > tb) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+}