ctf: make all parser implementations final classes
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / internal / ctf / core / event / metadata / tsdl / trace / TraceDeclarationParser.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
3 *
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
10 package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace;
11
12 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
13 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
14
15 import java.nio.ByteOrder;
16 import java.util.List;
17 import java.util.Map.Entry;
18 import java.util.UUID;
19
20 import org.antlr.runtime.tree.CommonTree;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
24 import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
25 import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration.Pair;
26 import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
27 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
28 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
29 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
30 import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
31 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
32 import org.eclipse.tracecompass.ctf.parser.CTFParser;
33 import org.eclipse.tracecompass.internal.ctf.core.Activator;
34 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
35 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.Messages;
36 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
37 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
38 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.ByteOrderParser;
39 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
40
41 /**
42 *
43 * A <em>trace<em> is divided into multiple event streams. Each event stream
44 * contains a subset of the trace event types. <br>
45 * The final output of the trace, after its generation and optional transport
46 * over the network, is expected to be either on permanent or temporary storage
47 * in a virtual file system. Because each event stream is appended to while a
48 * trace is being recorded, each is associated with a distinct set of files for
49 * output. Therefore, a stored trace can be represented as a directory
50 * containing zero, one or more files per stream. <br>
51 * Metadata description associated with the trace contains information on trace
52 * event types expressed in the _Trace Stream Description Language_ (TSDL). This
53 * language describes: <br>
54 * <ul>
55 * <li>Trace version</li>
56 * <li>Types available</li>
57 * <li>Per-trace event header description</li>
58 * <li>Per-stream event header description</li>
59 * <li>Per-stream event context description</li>
60 * <li>Per-event
61 * <ul>
62 * <li>Event type to stream mapping</li>
63 * <li>Event type to name mapping</li>
64 * <li>Event type to ID mapping</li>
65 * <li>Event context description</li>
66 * <li>Event fields description</li>
67 * </ul>
68 * </ul>
69 *
70 * @author Matthew Khouzam
71 *
72 */
73 public final class TraceDeclarationParser extends AbstractScopedCommonTreeParser {
74
75 /**
76 * Parameter object
77 *
78 * @author Matthew Khouzam
79 *
80 */
81 @NonNullByDefault
82 public static final class Param implements ICommonTreeParserParameter {
83
84 private final DeclarationScope fCurrentScope;
85 private final CTFTrace fTrace;
86
87 /**
88 * Parameter Object
89 *
90 * @param trace
91 * the trace
92 * @param currentScope
93 * the current scope
94 */
95 public Param(CTFTrace trace, DeclarationScope currentScope) {
96 fTrace = trace;
97 fCurrentScope = currentScope;
98 }
99
100 }
101
102 /**
103 * Parser instance
104 */
105 public static final TraceDeclarationParser INSTANCE = new TraceDeclarationParser();
106
107 private TraceDeclarationParser() {
108 }
109
110 /**
111 * Parse a trace AST node
112 *
113 * @param traceDecl
114 * trace AST node
115 * @param param
116 * A parameter object of the type {@link Param}
117 * @return a {@link CTFTrace} that is populated
118 * @throws ParseException
119 * if the AST is malformed
120 */
121 @Override
122 public CTFTrace parse(CommonTree traceDecl, ICommonTreeParserParameter param) throws ParseException {
123 if (!(param instanceof Param)) {
124 throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
125 }
126 CTFTrace trace = ((Param) param).fTrace;
127 DeclarationScope scope = ((Param) param).fCurrentScope;
128
129 /* There should be a left and right */
130 CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
131 CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
132
133 List<CommonTree> leftStrings = leftNode.getChildren();
134
135 if (!isAnyUnaryString(leftStrings.get(0))) {
136 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
137 }
138
139 String left = concatenateUnaryStrings(leftStrings);
140
141 if (left.equals(MetadataStrings.MAJOR)) {
142 if (trace.majorIsSet()) {
143 throw new ParseException("major is already set"); //$NON-NLS-1$
144 }
145
146 trace.setMajor(VersionNumberParser.INSTANCE.parse(rightNode, null));
147 } else if (left.equals(MetadataStrings.MINOR)) {
148 if (trace.minorIsSet()) {
149 throw new ParseException("minor is already set"); //$NON-NLS-1$
150 }
151
152 trace.setMinor(VersionNumberParser.INSTANCE.parse(rightNode, null));
153 } else if (left.equals(MetadataStrings.UUID_STRING)) {
154 UUID uuid = UUIDParser.INSTANCE.parse(rightNode, null);
155
156 /*
157 * If uuid was already set by a metadata packet, compare it to see
158 * if it matches
159 */
160 if (trace.uuidIsSet()) {
161 if (trace.getUUID().compareTo(uuid) != 0) {
162 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
163 + trace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
164 }
165 } else {
166 trace.setUUID(uuid);
167 }
168
169 } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
170 ByteOrder byteOrder = ByteOrderParser.INSTANCE.parse(rightNode, new ByteOrderParser.Param(trace));
171
172 /*
173 * If byte order was already set by a metadata packet, compare it to
174 * see if it matches
175 */
176 if (trace.getByteOrder() != null) {
177 if (trace.getByteOrder() != byteOrder) {
178 throw new ParseException(
179 "Endianness mismatch. Magic number says " //$NON-NLS-1$
180 + trace.getByteOrder()
181 + " but metadata says " + byteOrder); //$NON-NLS-1$
182 }
183 } else {
184 trace.setByteOrder(byteOrder);
185
186 final DeclarationScope currentScope = scope;
187 for (String type : currentScope.getTypeNames()) {
188 IDeclaration d = currentScope.lookupType(type);
189 if (d instanceof IntegerDeclaration) {
190 addByteOrder(byteOrder, currentScope, type, (IntegerDeclaration) d);
191 } else if (d instanceof FloatDeclaration) {
192 addByteOrder(byteOrder, currentScope, type, (FloatDeclaration) d);
193 } else if (d instanceof EnumDeclaration) {
194 addByteOrder(byteOrder, currentScope, type, (EnumDeclaration) d);
195 } else if (d instanceof StructDeclaration) {
196 setAlign(currentScope, (StructDeclaration) d, byteOrder);
197 }
198 }
199 }
200 } else if (left.equals(MetadataStrings.PACKET_HEADER)) {
201 if (trace.packetHeaderIsSet()) {
202 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
203 }
204
205 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
206
207 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
208 throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
209 }
210
211 IDeclaration packetHeaderDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(trace, null, null, scope));
212
213 if (!(packetHeaderDecl instanceof StructDeclaration)) {
214 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
215 }
216
217 trace.setPacketHeader((StructDeclaration) packetHeaderDecl);
218 } else {
219 Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownTraceAttributeWarning + " " + left); //$NON-NLS-1$
220 }
221 return trace;
222 }
223
224 private static void addByteOrder(ByteOrder byteOrder,
225 final DeclarationScope parentScope, String name,
226 IntegerDeclaration decl) throws ParseException {
227
228 if (!decl.isByteOrderSet()) {
229 IntegerDeclaration newI;
230 newI = IntegerDeclaration.createDeclaration(decl.getLength(), decl.isSigned(),
231 decl.getBase(), byteOrder, decl.getEncoding(),
232 decl.getClock(), decl.getAlignment());
233 parentScope.replaceType(name, newI);
234 }
235 }
236
237 private static void addByteOrder(ByteOrder byteOrder, DeclarationScope parentScope, String name, EnumDeclaration decl) throws ParseException {
238 if (!decl.isByteOrderSet()) {
239 final IntegerDeclaration containerType = decl.getContainerType();
240 EnumDeclaration newEnum = new EnumDeclaration(IntegerDeclaration.createDeclaration(containerType.getLength(), containerType.isSigned(),
241 containerType.getBase(), byteOrder, containerType.getEncoding(),
242 containerType.getClock(), containerType.getAlignment()));
243 for (Entry<String, Pair> entry : decl.getEnumTable().entrySet()) {
244 newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
245 }
246
247 parentScope.replaceType(name, newEnum);
248 }
249 }
250
251 private static void addByteOrder(ByteOrder byteOrder, DeclarationScope parentScope, String name, FloatDeclaration decl) throws ParseException {
252 if (!decl.isByteOrderSet()) {
253 FloatDeclaration newFloat = new FloatDeclaration(decl.getExponent(), decl.getMantissa(), byteOrder, decl.getAlignment());
254 parentScope.replaceType(name, newFloat);
255 }
256 }
257
258 private void setAlign(DeclarationScope parentScope, StructDeclaration sd,
259 ByteOrder byteOrder) throws ParseException {
260
261 for (String s : sd.getFieldsList()) {
262 IDeclaration d = sd.getField(s);
263
264 if (d instanceof StructDeclaration) {
265 setAlign(parentScope, (StructDeclaration) d, byteOrder);
266
267 } else if (d instanceof VariantDeclaration) {
268 setAlign(parentScope, (VariantDeclaration) d, byteOrder);
269 } else if (d instanceof IntegerDeclaration) {
270 IntegerDeclaration decl = (IntegerDeclaration) d;
271 if (decl.getByteOrder() != byteOrder) {
272 IntegerDeclaration newI;
273 newI = IntegerDeclaration.createDeclaration(decl.getLength(),
274 decl.isSigned(), decl.getBase(), byteOrder,
275 decl.getEncoding(), decl.getClock(),
276 decl.getAlignment());
277 sd.getFields().put(s, newI);
278 }
279 }
280 }
281 }
282
283 private void setAlign(DeclarationScope parentScope, VariantDeclaration vd,
284 ByteOrder byteOrder) throws ParseException {
285
286 for (String s : vd.getFields().keySet()) {
287 IDeclaration d = vd.getFields().get(s);
288
289 if (d instanceof StructDeclaration) {
290 setAlign(parentScope, (StructDeclaration) d, byteOrder);
291
292 } else if (d instanceof IntegerDeclaration) {
293 IntegerDeclaration decl = (IntegerDeclaration) d;
294 IntegerDeclaration newI;
295 newI = IntegerDeclaration.createDeclaration(decl.getLength(),
296 decl.isSigned(), decl.getBase(), byteOrder,
297 decl.getEncoding(), decl.getClock(),
298 decl.getAlignment());
299 vd.getFields().put(s, newI);
300 }
301 }
302 }
303 }
This page took 0.080246 seconds and 5 git commands to generate.