/*******************************************************************************
* Copyright (c) 2015 Ericsson
*
* 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
*******************************************************************************/
package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
import java.util.List;
import org.antlr.runtime.tree.CommonTree;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
import org.eclipse.tracecompass.ctf.parser.CTFParser;
import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryStringParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream.StreamIdParser;
import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
/**
* The declaration of an event
*
* @author Matthew Khouzam - Initial API and implementation
*
*/
public final class EventDeclarationParser extends AbstractScopedCommonTreeParser {
/**
* Parameter object, contains a trace, an event and a scope
*
* @author Matthew Khouzam
*
*/
@NonNullByDefault
public static final class Param implements ICommonTreeParserParameter {
private final EventDeclaration fEvent;
private final CTFTrace fTrace;
private final DeclarationScope fDeclarationScope;
/**
* Constructor
*
* @param trace
* the trace
* @param event
* the event to populate
* @param scope
* the current scope
*/
public Param(CTFTrace trace, EventDeclaration event, DeclarationScope scope) {
fTrace = trace;
fEvent = event;
fDeclarationScope = scope;
}
}
/**
* Instance
*/
public static final EventDeclarationParser INSTANCE = new EventDeclarationParser();
private EventDeclarationParser() {
}
@Override
public EventDeclaration parse(CommonTree eventDecl, ICommonTreeParserParameter param) throws ParseException {
if (!(param instanceof Param)) {
throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
}
DeclarationScope scope = ((Param) param).fDeclarationScope;
EventDeclaration event = ((Param) param).fEvent;
CTFTrace fTrace = ((Param) param).fTrace;
/* There should be a left and right */
CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
List<CommonTree> leftStrings = leftNode.getChildren();
if (!isAnyUnaryString(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(MetadataStrings.NAME2)) {
if (event.nameIsSet()) {
throw new ParseException("name already defined"); //$NON-NLS-1$
}
String name = EventNameParser.INSTANCE.parse(rightNode, null);
event.setName(name);
} else if (left.equals(MetadataStrings.ID)) {
if (event.idIsSet()) {
throw new ParseException("id already defined"); //$NON-NLS-1$
}
long id = EventIDParser.INSTANCE.parse(rightNode, null);
if (id > Integer.MAX_VALUE) {
throw new ParseException("id is greater than int.maxvalue, unsupported. id : " + id); //$NON-NLS-1$
}
if (id < 0) {
throw new ParseException("negative id, unsupported. id : " + id); //$NON-NLS-1$
}
event.setId((int) id);
} else if (left.equals(MetadataStrings.STREAM_ID)) {
if (event.streamIsSet()) {
throw new ParseException("stream id already defined"); //$NON-NLS-1$
}
long streamId = StreamIdParser.INSTANCE.parse(rightNode, null);
/*
* If the event has a stream and it is defined, look up the stream,
* if it is the available, assign it. If not, the event is
* malformed.
*/
ICTFStream iStream = fTrace.getStream(streamId);
if (!(iStream instanceof CTFStream)) {
throw new ParseException("Event specified stream with ID " + streamId + ". But no stream with that ID was defined"); //$NON-NLS-1$ //$NON-NLS-2$
}
CTFStream ctfStream = (CTFStream) iStream;
event.setStream(ctfStream);
} else if (left.equals(MetadataStrings.CONTEXT)) {
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 = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
if (!(contextDecl instanceof StructDeclaration)) {
throw new ParseException("context expects a struct"); //$NON-NLS-1$
}
event.setContext((StructDeclaration) contextDecl);
} else if (left.equals(MetadataStrings.FIELDS_STRING)) {
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 = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
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 if (left.equals(MetadataStrings.LOGLEVEL2)) {
long logLevel = UnaryIntegerParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null);
event.setLogLevel(logLevel);
} else {
/* Custom event attribute, we'll add it to the attributes map */
String right = UnaryStringParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null);
event.setCustomAttribute(left, right);
}
return event;
}
}