1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9 package org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.struct
;
11 import static org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.TsdlUtils
.childTypeError
;
13 import java
.util
.List
;
15 import org
.antlr
.runtime
.tree
.CommonTree
;
16 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
17 import org
.eclipse
.jdt
.annotation
.Nullable
;
18 import org
.eclipse
.tracecompass
.ctf
.core
.event
.metadata
.DeclarationScope
;
19 import org
.eclipse
.tracecompass
.ctf
.core
.event
.types
.StructDeclaration
;
20 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFTrace
;
21 import org
.eclipse
.tracecompass
.ctf
.parser
.CTFParser
;
22 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.AbstractScopedCommonTreeParser
;
23 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.ParseException
;
24 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.AlignmentParser
;
25 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.types
.StructDeclarationFlattener
;
29 * Structures are aligned on the largest alignment required by basic types
30 * contained within the structure. (This follows the ISO/C standard for
32 * TSDL metadata representation of a named structure:
36 field_type field_name;
37 field_type field_name;
46 integer { // nameless type
51 uint64_t second_field_name; // named type declared in the metadata
55 * The fields are placed in a sequence next to each other. They each possess a
56 * field name, which is a unique identifier within the structure. The identifier
57 * is not allowed to use any [reserved keyword](#specC.1.2). Replacing reserved
58 * keywords with underscore-prefixed field names is <strong>recommended</strong>
59 * . Fields starting with an underscore should have their leading underscore
60 * removed by the CTF trace readers. <br>
61 * A nameless structure can be declared as a field type or as part of a
71 * Alignment for a structure compound type can be forced to a minimum value by
72 * adding an `align` specifier after the declaration of a structure body. This
73 * attribute is read as: `align(value)`. The value is specified in bits. The
74 * structure will be aligned on the maximum value between this attribute and the
75 * alignment required by the basic types contained within the structure. e.g.
84 * @author Matthew Khouzam
85 * @author Efficios - Javadoc preamble
87 public final class StructParser
extends AbstractScopedCommonTreeParser
{
92 * @author Matthew Khouzam
96 public static final class Param
implements ICommonTreeParserParameter
{
97 private final DeclarationScope fDeclarationScope
;
98 private final @Nullable CommonTree fIdentifier
;
99 private final CTFTrace fTrace
;
111 public Param(CTFTrace trace
, @Nullable CommonTree identifier
, DeclarationScope scope
) {
113 fIdentifier
= identifier
;
114 fDeclarationScope
= scope
;
121 public final static StructParser INSTANCE
= new StructParser();
123 private StructParser() {
127 * Parse the struct AST node, So everything in "struct a {...};"
130 * the struct AST node
132 * the parameter object of {@link Param} type.
133 * @return a {@link StructDeclaration} that is fully populated
134 * @throws ParseException
135 * the AST is malformed
138 public StructDeclaration
parse(CommonTree struct
, ICommonTreeParserParameter param
) throws ParseException
{
139 if (!(param
instanceof Param
)) {
140 throw new IllegalArgumentException("Param must be a " + Param
.class.getCanonicalName()); //$NON-NLS-1$
142 final DeclarationScope scope
= ((Param
) param
).fDeclarationScope
;
143 CommonTree identifier
= ((Param
) param
).fIdentifier
;
145 List
<CommonTree
> children
= struct
.getChildren();
147 /* The return value */
148 StructDeclaration structDeclaration
= null;
151 String structName
= null;
152 boolean hasName
= false;
155 CommonTree structBody
= null;
156 boolean hasBody
= false;
159 long structAlign
= 0;
161 /* Loop on all children and identify what we have to work with. */
162 for (CommonTree child
: children
) {
163 switch (child
.getType()) {
164 case CTFParser
.STRUCT_NAME
: {
166 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
167 structName
= structNameIdentifier
.getText();
170 case CTFParser
.STRUCT_BODY
: {
176 case CTFParser
.ALIGN
: {
177 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
179 structAlign
= AlignmentParser
.INSTANCE
.parse(structAlignExpression
, null);
183 throw childTypeError(child
);
187 if (!hasName
&& identifier
!= null) {
188 structName
= identifier
.getText();
193 * If a struct has just a body and no name (just like the song,
194 * "A Struct With No Name" by America (sorry for that...)), it's a
195 * definition of a new type, so we create the type declaration and
196 * return it. We can't add it to the declaration scope since there is no
197 * name, but that's what we want because it won't be possible to use it
198 * again to declare another field.
200 * If it has just a name, we look it up in the declaration scope and
201 * return the associated declaration. If it is not found in the
202 * declaration scope, it means that a struct with that name has not been
203 * declared, which is an error.
205 * If it has both, then we create the type declaration and register it
206 * to the current scope.
208 * If it has none, then what are we doing here ?
212 * If struct has a name, check if already defined in the current
215 if (hasName
&& (scope
.lookupStruct(structName
) != null)) {
216 throw new ParseException("struct " + structName
//$NON-NLS-1$
217 + " already defined."); //$NON-NLS-1$
219 /* Create the declaration */
220 structDeclaration
= new StructDeclaration(structAlign
);
222 CTFTrace trace
= ((Param
) param
).fTrace
;
224 StructBodyParser
.INSTANCE
.parse(structBody
, new StructBodyParser
.Param(structDeclaration
, trace
, structName
, scope
));
225 /* If struct has name, add it to the current scope. */
227 scope
.registerStruct(structName
, structDeclaration
);
229 } else /* !hasBody */ {
233 /* Lookup the name in the current scope. */
234 structDeclaration
= scope
.lookupStructRecursive(structName
);
237 * If not found, it means that a struct with such name has not
240 if (structDeclaration
== null) {
241 throw new ParseException("struct " + structName
//$NON-NLS-1$
242 + " is not defined"); //$NON-NLS-1$
245 /* !Name and !body */
247 /* We can't do anything with that. */
248 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
251 return StructDeclarationFlattener
.tryFlattenStruct(structDeclaration
);