blob: 69c3443f9e4f49ac0deeef8e8c5d3f16e1ba3a83 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
import java.util.List;
import org.antlr.runtime.tree.CommonTree;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.tracecompass.ctf.parser.CTFParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
/**
* A local static scope consists in the scope generated by the declaration of
* fields within a compound type. A static scope is a local static scope
* augmented with the nested sub-static-scopes it contains.
* <p>
* A dynamic scope consists in the static scope augmented with the implicit
* event structure definition hierarchy.
* <p>
* Multiple declarations of the same field name within a local static scope is
* not valid. It is however valid to re-use the same field name in different
* local scopes.
* <p>
* Nested static and dynamic scopes form lookup paths. These are used for
* variant tag and sequence length references. They are used at the variant and
* sequence definition site to look up the location of the tag field associated
* with a variant, and to lookup up the location of the length field associated
* with a sequence.
* <p>
* Variants and sequences can refer to a tag field either using a relative path
* or an absolute path. The relative path is relative to the scope in which the
* variant or sequence performing the lookup is located. Relative paths are only
* allowed to lookup within the same static scope, which includes its nested
* static scopes. Lookups targeting parent static scopes need to be performed
* with an absolute path.
* <p>
* Absolute path lookups use the full path including the dynamic scope followed
* by a . and then the static scope. Therefore, variants (or sequences) in lower
* levels in the dynamic scope (e.g., event context) can refer to a tag (or
* length) field located in upper levels (e.g., in the event header) by
* specifying, in this case, the associated tag with
* <stream.event.header.field_name>. This allows, for instance, the event
* context to define a variant referring to the id field of the event header as
* selector.
* <p>
* The dynamic scope prefixes are thus:
* <ul>
* <li>Trace environment: <env. ></li>
* <li>Trace packet header: <trace.packet.header. ></li>
* <li>Stream packet context: <stream.packet.context. ></li>
* <li>Event header: <stream.event.header. ></li>
* <li>Stream event context: <stream.event.context. ></li>
* <li>Event context: <event.context. ></li>
* <li>Event payload: <event.fields. ></li>
* </ul>
* <p>
* The target dynamic scope must be specified explicitly when referring to a
* field outside of the static scope (absolute scope reference). No conflict can
* occur between relative and dynamic paths, because the keywords trace, stream,
* and event are reserved, and thus not permitted as field names. It is
* recommended that field names clashing with CTF and C99 reserved keywords use
* an underscore prefix to eliminate the risk of generating a description
* containing an invalid field name. Consequently, fields starting with an
* underscore should have their leading underscore removed by the CTF trace
* readers.
* <p>
* The information available in the dynamic scopes can be thought of as the
* current tracing context. At trace production, information about the current
* context is saved into the specified scope field levels. At trace consumption,
* for each event, the current trace context is therefore readable by accessing
* the upper dynamic scopes.
*
* @author Matthew Khouzam - Initial API and implementation
* @author Efficios - Description
*
*/
public final class EventScopeParser implements ICommonTreeParser {
/**
* Parameter object containing a list of common trees
*
* @author Matthew Khouzam
*
*/
@NonNullByDefault
public static final class Param implements ICommonTreeParserParameter {
private final List<CommonTree> fList;
/**
* Constructor
*
* @param list
* parameter list
*/
public Param(List<CommonTree> list) {
fList = list;
}
}
/**
* Instance
*/
public static final EventScopeParser INSTANCE = new EventScopeParser();
private EventScopeParser() {
}
/**
* Parses in a different way, the AST node is unused, and the event list
* contains data to read. This converts a scope from a set of strings to
* "event.subscope1.subscope2".
*
* @param unused
* unused AST node
* @param param
* a list of tree nodes that contain the scope description.
* @return a concatenated string of the scope
*/
@Override
public String parse(CommonTree unused, ICommonTreeParserParameter param) throws ParseException {
if (!(param instanceof Param)) {
throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
}
List<CommonTree> lengthChildren = ((Param) param).fList;
CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
String lengthName;
switch (nextElem.getType()) {
case CTFParser.UNARY_EXPRESSION_STRING:
case CTFParser.IDENTIFIER:
List<CommonTree> sublist = lengthChildren.subList(1, lengthChildren.size());
lengthName = MetadataStrings.EVENT + '.' + concatenateUnaryStrings(sublist);
break;
default:
throw new ParseException("Unsupported scope event." + nextElem); //$NON-NLS-1$
}
return lengthName;
}
}