tmf: Switch tmf.core to Java 7 + fix warnings
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / internal / ctf / core / event / metadata / IOStructGen.java
CommitLineData
866e5b51 1/*******************************************************************************
4311ac8b 2 * Copyright (c) 2011, 2013 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
4311ac8b
MAL
9 * Contributors:
10 * Matthew Khouzam - Initial Design and Grammar
11 * Francis Giraldeau - Initial API and implementation
12 * Simon Marchi - Initial API and implementation
866e5b51
FC
13 *******************************************************************************/
14
ce2388e0 15package org.eclipse.linuxtools.internal.ctf.core.event.metadata;
866e5b51
FC
16
17import java.io.FileNotFoundException;
18import java.io.IOException;
19import java.io.UnsupportedEncodingException;
4311ac8b 20import java.math.BigInteger;
866e5b51
FC
21import java.nio.ByteOrder;
22import java.util.ArrayList;
23import java.util.Collections;
816fde81 24import java.util.HashSet;
866e5b51
FC
25import java.util.LinkedList;
26import java.util.List;
816fde81 27import java.util.Set;
866e5b51
FC
28import java.util.UUID;
29
30import org.antlr.runtime.tree.CommonTree;
4311ac8b 31import org.eclipse.core.runtime.IStatus;
866e5b51 32import org.eclipse.linuxtools.ctf.core.event.CTFClock;
866e5b51
FC
33import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
34import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
35import org.eclipse.linuxtools.ctf.core.event.types.EnumDeclaration;
53047a66 36import org.eclipse.linuxtools.ctf.core.event.types.FloatDeclaration;
866e5b51
FC
37import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration;
38import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
39import org.eclipse.linuxtools.ctf.core.event.types.SequenceDeclaration;
40import org.eclipse.linuxtools.ctf.core.event.types.StringDeclaration;
41import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
42import org.eclipse.linuxtools.ctf.core.event.types.VariantDeclaration;
43import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
486efb2e 44import org.eclipse.linuxtools.ctf.core.trace.Stream;
866e5b51 45import org.eclipse.linuxtools.ctf.parser.CTFParser;
4311ac8b 46import org.eclipse.linuxtools.internal.ctf.core.Activator;
8e964be1 47import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
ce2388e0 48import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
866e5b51 49
866e5b51 50/**
251274dd 51 * IOStructGen
866e5b51 52 */
866e5b51
FC
53public class IOStructGen {
54
55 // ------------------------------------------------------------------------
56 // Attributes
57 // ------------------------------------------------------------------------
58
0594c61c 59 private static final boolean DEBUG = false;
866e5b51
FC
60
61 /**
62 * The trace
63 */
64 private final CTFTrace trace;
65 private final CommonTree tree;
66
67 /**
68 * The current declaration scope.
69 */
70 private DeclarationScope scope = null;
71
72 // ------------------------------------------------------------------------
73 // Constructor
74 // ------------------------------------------------------------------------
75
9ac2eb62 76 /**
ecb12461 77 * Constructor
be6df2d8
AM
78 *
79 * @param tree
80 * the tree (ANTLR generated) with the parsed TSDL data.
81 * @param trace
82 * the trace containing the places to put all the read metadata
9ac2eb62 83 */
866e5b51
FC
84 public IOStructGen(CommonTree tree, CTFTrace trace) {
85 this.trace = trace;
86 this.tree = tree;
87 }
88
9ac2eb62
MK
89 /**
90 * Parse the tree and populate the trace defined in the constructor.
be6df2d8 91 *
9ac2eb62 92 * @throws ParseException
be6df2d8 93 * If there was a problem parsing the metadata
9ac2eb62 94 */
866e5b51
FC
95 public void generate() throws ParseException {
96 parseRoot(tree);
97 }
98
99 // ------------------------------------------------------------------------
100 // Operations
101 // ------------------------------------------------------------------------
102
103 /**
104 * Parse the root node.
105 *
106 * @param root
107 * A ROOT node.
108 * @throws ParseException
109 */
110 private void parseRoot(CommonTree root) throws ParseException {
866e5b51
FC
111
112 List<CommonTree> children = root.getChildren();
866e5b51
FC
113 java.io.FileOutputStream fos = null;
114 java.io.OutputStreamWriter out = null;
0594c61c 115 if (DEBUG) {
866e5b51
FC
116 try {
117 fos = new java.io.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
118 out = new java.io.OutputStreamWriter(fos, "UTF-8"); //$NON-NLS-1$
119 } catch (FileNotFoundException e) {
120 e.printStackTrace();
121 return;
122 } catch (UnsupportedEncodingException e) {
123 e.printStackTrace();
124 return;
125 }
126 }
127
128 CommonTree traceNode = null;
129 List<CommonTree> streams = new ArrayList<CommonTree>();
130 List<CommonTree> events = new ArrayList<CommonTree>();
131 List<CommonTree> declarations = new ArrayList<CommonTree>();
132 List<CommonTree> environments = new ArrayList<CommonTree>();
133 List<CommonTree> clocks = new ArrayList<CommonTree>();
4c9d2941 134 List<CommonTree> callsites = new ArrayList<CommonTree>();
866e5b51
FC
135 /* Create a new declaration scope with no parent. */
136 pushScope();
137
138 try {
139 for (CommonTree child : children) {
4c9d2941 140 final int type = child.getType();
0594c61c 141 if (DEBUG) {
866e5b51 142 out.write(child.toString()
4c9d2941 143 + " -> " + type + '\n'); //$NON-NLS-1$
866e5b51 144 }
4c9d2941 145 switch (type) {
866e5b51
FC
146 case CTFParser.DECLARATION:
147 declarations.add(child);
148 break;
149 case CTFParser.TRACE:
150 if (traceNode != null) {
2c053b6e 151 throw new ParseException("Only one trace block is allowed"); //$NON-NLS-1$
866e5b51
FC
152 }
153 traceNode = child;
154 break;
155 case CTFParser.STREAM:
156 streams.add(child);
157 break;
158 case CTFParser.EVENT:
159 events.add(child);
160 break;
161 case CTFParser.CLOCK:
162 clocks.add(child);
163 break;
164 case CTFParser.ENV:
165 environments.add(child);
166 break;
4c9d2941
MK
167 case CTFParser.CALLSITE:
168 callsites.add(child);
169 break;
866e5b51
FC
170 default:
171 childTypeError(child);
172 }
173 }
0594c61c 174 if (DEBUG) {
866e5b51
FC
175 out.write("Declarations\n"); //$NON-NLS-1$
176 }
177 for (CommonTree decl : declarations) {
0594c61c 178 if (DEBUG) {
866e5b51
FC
179 out.write(decl.toString() + '\n');
180 }
181 parseRootDeclaration(decl);
182 }
866e5b51
FC
183 if (traceNode == null) {
184 throw new ParseException("Missing trace block"); //$NON-NLS-1$
185 }
186
187 parseTrace(traceNode);
188
0594c61c 189 if (DEBUG) {
72dbc4ac
MK
190 out.write("Environments\n"); //$NON-NLS-1$
191 }
192 for (CommonTree environment : environments) {
193 parseEnvironment(environment);
194 }
0594c61c 195 if (DEBUG) {
72dbc4ac
MK
196 out.write("Clocks\n"); //$NON-NLS-1$
197 }
198 for (CommonTree clock : clocks) {
199 parseClock(clock);
200 }
0594c61c 201 if (DEBUG) {
4c9d2941
MK
202 out.write("Callsites\n"); //$NON-NLS-1$
203 }
204 for (CommonTree callsite : callsites) {
205 parseCallsite(callsite);
206 }
72dbc4ac 207
0594c61c 208 if (DEBUG) {
866e5b51
FC
209 out.write("Streams\n"); //$NON-NLS-1$
210 }
211 if (streams.size() > 0) {
212 for (CommonTree stream : streams) {
0594c61c 213 if (DEBUG) {
866e5b51
FC
214 try {
215 out.write(stream.toString() + '\n');
216 } catch (IOException e) {
217 e.printStackTrace();
218 }
219 }
220 parseStream(stream);
221 }
222 } else {
223 /* Add an empty stream that will have a null id */
224 trace.addStream(new Stream(trace));
225 }
226
0594c61c 227 if (DEBUG) {
866e5b51
FC
228 out.write("Events\n"); //$NON-NLS-1$
229 }
230 for (CommonTree event : events) {
231 parseEvent(event);
0594c61c 232 if (DEBUG) {
32ede2ec
MK
233 CommonTree name = (CommonTree) event.getChild(0).getChild(1).getChild(0).getChild(0);
234 CommonTree id = (CommonTree) event.getChild(1).getChild(1).getChild(0).getChild(0);
866e5b51
FC
235 out.write("Name = " + name + " Id = " + id + '\n'); //$NON-NLS-1$ //$NON-NLS-2$
236 }
237 }
238
0594c61c 239 if (DEBUG) {
866e5b51
FC
240 out.close();
241 fos.close();
242 }
243 } catch (IOException e) {
244 e.printStackTrace();
245 }
246 popScope();
247 }
248
4c9d2941
MK
249 private void parseCallsite(CommonTree callsite) {
250
251 List<CommonTree> children = callsite.getChildren();
252 String name = null;
0594c61c
AM
253 String funcName = null;
254 long lineNumber = -1;
4c9d2941 255 long ip = -1;
0594c61c 256 String fileName = null;
4c9d2941
MK
257
258 for (CommonTree child : children) {
259 String left;
ecb12461 260 /* this is a regex to find the leading and trailing quotes */
4c9d2941 261 final String regex = "^\"|\"$"; //$NON-NLS-1$
2c053b6e
MK
262 /*
263 * this is to replace the previous quotes with nothing...
264 * effectively deleting them
265 */
4c9d2941
MK
266 final String nullString = ""; //$NON-NLS-1$
267 left = child.getChild(0).getChild(0).getChild(0).getText();
268 if (left.equals("name")) { //$NON-NLS-1$
269 name = child.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex, nullString);
270 } else if (left.equals("func")) { //$NON-NLS-1$
0594c61c 271 funcName = child.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex, nullString);
4c9d2941 272 } else if (left.equals("ip")) { //$NON-NLS-1$
2c053b6e
MK
273 /* trim the 0x */
274 ip = Long.parseLong(child.getChild(1).getChild(0).getChild(0).getText().substring(2), 16);
4c9d2941 275 } else if (left.equals("file")) { //$NON-NLS-1$
0594c61c 276 fileName = child.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex, nullString);
4c9d2941 277 } else if (left.equals("line")) { //$NON-NLS-1$
0594c61c 278 lineNumber = Long.parseLong(child.getChild(1).getChild(0).getChild(0).getText());
4c9d2941
MK
279 }
280 }
2c053b6e 281 trace.addCallsite(name, funcName, ip, fileName, lineNumber);
4c9d2941
MK
282 }
283
866e5b51
FC
284 private void parseEnvironment(CommonTree environment) {
285 List<CommonTree> children = environment.getChildren();
286 for (CommonTree child : children) {
287 String left;
288 String right;
289 left = child.getChild(0).getChild(0).getChild(0).getText();
290 right = child.getChild(1).getChild(0).getChild(0).getText();
291 trace.addEnvironmentVar(left, right);
292 }
293 }
294
295 private void parseClock(CommonTree clock) {
296 List<CommonTree> children = clock.getChildren();
297 CTFClock ctfClock = new CTFClock();
298 for (CommonTree child : children) {
72dbc4ac 299 final String key = child.getChild(0).getChild(0).getChild(0).getText();
866e5b51
FC
300 final CommonTree value = (CommonTree) child.getChild(1).getChild(0).getChild(0);
301 final int type = value.getType();
302 switch (type) {
303 case CTFParser.INTEGER:
304 case CTFParser.DECIMAL_LITERAL:
284fdee8 305 /*
32ede2ec
MK
306 * Not a pretty hack, this is to make sure that there is no
307 * number overflow due to 63 bit integers. The offset should
308 * only really be an issue in the year 2262. the tracer in C/ASM
309 * can write an offset in an unsigned 64 bit long. In java, the
310 * last bit, being set to 1 will be read as a negative number,
311 * but since it is too big a positive it will throw an
312 * exception. this will happen in 2^63 ns from 1970. Therefore
313 * 293 years from 1970
284fdee8 314 */
866e5b51 315 Long numValue;
32ede2ec 316 try {
866e5b51 317 numValue = Long.parseLong(value.getText());
32ede2ec 318 } catch (Exception e) {
866e5b51
FC
319 numValue = 1330938566783103277L;
320 }
321 ctfClock.addAttribute(key, numValue);
322 break;
323 default:
324 ctfClock.addAttribute(key, value.getText());
325 }
326
327 }
0594c61c
AM
328 String nameValue = ctfClock.getName();
329 trace.addClock(nameValue, ctfClock);
866e5b51
FC
330 }
331
332 private void parseTrace(CommonTree traceNode) throws ParseException {
866e5b51
FC
333
334 List<CommonTree> children = traceNode.getChildren();
335 if (children == null) {
336 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
337 }
338
339 pushScope();
340
341 for (CommonTree child : children) {
342 switch (child.getType()) {
343 case CTFParser.TYPEALIAS:
344 parseTypealias(child);
345 break;
346 case CTFParser.TYPEDEF:
347 parseTypedef(child);
348 break;
349 case CTFParser.CTF_EXPRESSION_TYPE:
350 case CTFParser.CTF_EXPRESSION_VAL:
351 parseTraceDeclaration(child);
352 break;
353 default:
354 childTypeError(child);
355 break;
356 }
357 }
358
359 /*
360 * If trace byte order was not specified and not using packet based
361 * metadata
362 */
363 if (trace.getByteOrder() == null) {
364 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
365 }
366
367 popScope();
368 }
369
370 private void parseTraceDeclaration(CommonTree traceDecl)
371 throws ParseException {
866e5b51
FC
372
373 /* There should be a left and right */
866e5b51
FC
374
375 CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
866e5b51 376 CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
866e5b51
FC
377
378 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51 379
4311ac8b 380 if (!isAnyUnaryString(leftStrings.get(0))) {
2c053b6e 381 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
866e5b51
FC
382 }
383
384 String left = concatenateUnaryStrings(leftStrings);
385
fafc36a7 386 if (left.equals(MetadataStrings.MAJOR)) {
07804639 387 if (trace.majorIsSet()) {
866e5b51
FC
388 throw new ParseException("major is already set"); //$NON-NLS-1$
389 }
390
391 trace.setMajor(getMajorOrMinor(rightNode));
fafc36a7 392 } else if (left.equals(MetadataStrings.MINOR)) {
866e5b51
FC
393 if (trace.minorIsSet()) {
394 throw new ParseException("minor is already set"); //$NON-NLS-1$
395 }
396
397 trace.setMinor(getMajorOrMinor(rightNode));
fafc36a7 398 } else if (left.equals(MetadataStrings.UUID_STRING)) {
866e5b51
FC
399 UUID uuid = getUUID(rightNode);
400
401 /*
402 * If uuid was already set by a metadata packet, compare it to see
403 * if it matches
404 */
0594c61c 405 if (trace.uuidIsSet()) {
866e5b51
FC
406 if (trace.getUUID().compareTo(uuid) != 0) {
407 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
408 + trace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
409 }
410 } else {
411 trace.setUUID(uuid);
412 }
413
fafc36a7 414 } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
866e5b51
FC
415 ByteOrder byteOrder = getByteOrder(rightNode);
416
417 /*
418 * If byte order was already set by a metadata packet, compare it to
419 * see if it matches
420 */
421 if (trace.getByteOrder() != null) {
422 if (trace.getByteOrder() != byteOrder) {
423 throw new ParseException(
424 "Endianness mismatch. Magic number says " //$NON-NLS-1$
425 + trace.getByteOrder()
426 + " but metadata says " + byteOrder); //$NON-NLS-1$
427 }
428 } else {
429 trace.setByteOrder(byteOrder);
72dbc4ac 430 final DeclarationScope parentScope = scope.getParentScope();
72dbc4ac 431
108f70b8 432 for (String type : parentScope.getTypeNames()) {
72dbc4ac
MK
433 IDeclaration d = parentScope.lookupType(type);
434 if (d instanceof IntegerDeclaration) {
435 addByteOrder(byteOrder, parentScope, type, (IntegerDeclaration) d);
436 } else if (d instanceof StructDeclaration) {
437 setAlign(parentScope, (StructDeclaration) d, byteOrder);
438 }
439 }
866e5b51 440 }
fafc36a7 441 } else if (left.equals(MetadataStrings.PACKET_HEADER)) {
866e5b51
FC
442 if (trace.packetHeaderIsSet()) {
443 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
444 }
445
446 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
447
448 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
2c053b6e 449 throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
866e5b51
FC
450 }
451
452 IDeclaration packetHeaderDecl = parseTypeSpecifierList(
453 typeSpecifier, null);
454
455 if (!(packetHeaderDecl instanceof StructDeclaration)) {
456 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
457 }
458
459 trace.setPacketHeader((StructDeclaration) packetHeaderDecl);
460 } else {
4311ac8b 461 Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownTraceAttributeWarning + " " + left); //$NON-NLS-1$
866e5b51
FC
462 }
463 }
464
72dbc4ac
MK
465 private static void addByteOrder(ByteOrder byteOrder,
466 final DeclarationScope parentScope, String name,
467 IntegerDeclaration decl) throws ParseException {
468
469 if (decl.getByteOrder() == null) {
470 IntegerDeclaration newI;
471 newI = new IntegerDeclaration(decl.getLength(), decl.isSigned(),
472 decl.getBase(), byteOrder, decl.getEncoding(),
473 decl.getClock(), decl.getAlignment());
474 parentScope.replaceType(name, newI);
475 }
476 }
477
478 private void setAlign(DeclarationScope parentScope, StructDeclaration sd,
479 ByteOrder byteOrder) throws ParseException {
480
481 for (String s : sd.getFieldsList()) {
482 IDeclaration d = sd.getFields().get(s);
483
484 if (d instanceof StructDeclaration) {
485 setAlign(parentScope, (StructDeclaration) d, byteOrder);
486
487 } else if (d instanceof VariantDeclaration) {
488 setAlign(parentScope, (VariantDeclaration) d, byteOrder);
489
490 } else if (d instanceof IntegerDeclaration) {
491 IntegerDeclaration decl = (IntegerDeclaration) d;
492 if (decl.getByteOrder() == null) {
493 IntegerDeclaration newI;
494 newI = new IntegerDeclaration(decl.getLength(),
495 decl.isSigned(), decl.getBase(), byteOrder,
496 decl.getEncoding(), decl.getClock(),
497 decl.getAlignment());
498 sd.getFields().put(s, newI);
499 }
500 }
501 }
502 }
503
504 private void setAlign(DeclarationScope parentScope, VariantDeclaration vd,
505 ByteOrder byteOrder) throws ParseException {
506
507 for (String s : vd.getFields().keySet()) {
508 IDeclaration d = vd.getFields().get(s);
509
510 if (d instanceof StructDeclaration) {
511 setAlign(parentScope, (StructDeclaration) d, byteOrder);
512
513 } else if (d instanceof IntegerDeclaration) {
514 IntegerDeclaration decl = (IntegerDeclaration) d;
515 IntegerDeclaration newI;
516 newI = new IntegerDeclaration(decl.getLength(),
517 decl.isSigned(), decl.getBase(), byteOrder,
518 decl.getEncoding(), decl.getClock(),
519 decl.getAlignment());
520 vd.getFields().put(s, newI);
521 }
522 }
523 }
524
866e5b51 525 private void parseStream(CommonTree streamNode) throws ParseException {
866e5b51
FC
526
527 Stream stream = new Stream(trace);
528
529 List<CommonTree> children = streamNode.getChildren();
530 if (children == null) {
531 throw new ParseException("Empty stream block"); //$NON-NLS-1$
532 }
533
534 pushScope();
535
536 for (CommonTree child : children) {
537 switch (child.getType()) {
538 case CTFParser.TYPEALIAS:
539 parseTypealias(child);
540 break;
541 case CTFParser.TYPEDEF:
542 parseTypedef(child);
543 break;
544 case CTFParser.CTF_EXPRESSION_TYPE:
545 case CTFParser.CTF_EXPRESSION_VAL:
546 parseStreamDeclaration(child, stream);
547 break;
548 default:
549 childTypeError(child);
550 break;
551 }
552 }
553
9ac2eb62 554 if (stream.isIdSet()) {
866e5b51 555 if (!trace.packetHeaderIsSet()
fafc36a7 556 || !trace.getPacketHeader().hasField(MetadataStrings.STREAM_ID)) {
2c053b6e 557 throw new ParseException("Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
866e5b51
FC
558 }
559 }
560
561 trace.addStream(stream);
562
563 popScope();
564 }
565
566 private void parseStreamDeclaration(CommonTree streamDecl, Stream stream)
567 throws ParseException {
866e5b51
FC
568
569 /* There should be a left and right */
866e5b51
FC
570
571 CommonTree leftNode = (CommonTree) streamDecl.getChild(0);
866e5b51 572 CommonTree rightNode = (CommonTree) streamDecl.getChild(1);
866e5b51
FC
573
574 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51 575
4311ac8b 576 if (!isAnyUnaryString(leftStrings.get(0))) {
2c053b6e 577 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
866e5b51
FC
578 }
579
580 String left = concatenateUnaryStrings(leftStrings);
581
fafc36a7 582 if (left.equals(MetadataStrings.ID)) {
9ac2eb62 583 if (stream.isIdSet()) {
866e5b51
FC
584 throw new ParseException("stream id already defined"); //$NON-NLS-1$
585 }
586
587 long streamID = getStreamID(rightNode);
588
589 stream.setId(streamID);
fafc36a7 590 } else if (left.equals(MetadataStrings.EVENT_HEADER)) {
9ac2eb62 591 if (stream.isEventHeaderSet()) {
866e5b51
FC
592 throw new ParseException("event.header already defined"); //$NON-NLS-1$
593 }
594
595 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
596
597 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
2c053b6e 598 throw new ParseException("event.header expects a type specifier"); //$NON-NLS-1$
866e5b51
FC
599 }
600
601 IDeclaration eventHeaderDecl = parseTypeSpecifierList(
602 typeSpecifier, null);
603
604 if (!(eventHeaderDecl instanceof StructDeclaration)) {
605 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
606 }
607
608 stream.setEventHeader((StructDeclaration) eventHeaderDecl);
fafc36a7 609 } else if (left.equals(MetadataStrings.EVENT_CONTEXT)) {
9ac2eb62 610 if (stream.isEventContextSet()) {
866e5b51
FC
611 throw new ParseException("event.context already defined"); //$NON-NLS-1$
612 }
613
614 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
615
616 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
2c053b6e 617 throw new ParseException("event.context expects a type specifier"); //$NON-NLS-1$
866e5b51
FC
618 }
619
620 IDeclaration eventContextDecl = parseTypeSpecifierList(
621 typeSpecifier, null);
622
623 if (!(eventContextDecl instanceof StructDeclaration)) {
624 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
625 }
626
627 stream.setEventContext((StructDeclaration) eventContextDecl);
fafc36a7 628 } else if (left.equals(MetadataStrings.PACKET_CONTEXT)) {
9ac2eb62 629 if (stream.isPacketContextSet()) {
866e5b51
FC
630 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
631 }
632
633 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
634
635 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
2c053b6e 636 throw new ParseException("packet.context expects a type specifier"); //$NON-NLS-1$
866e5b51
FC
637 }
638
639 IDeclaration packetContextDecl = parseTypeSpecifierList(
640 typeSpecifier, null);
641
642 if (!(packetContextDecl instanceof StructDeclaration)) {
643 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
644 }
645
646 stream.setPacketContext((StructDeclaration) packetContextDecl);
647 } else {
4311ac8b 648 Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownStreamAttributeWarning + " " + left); //$NON-NLS-1$
866e5b51
FC
649 }
650 }
651
652 private void parseEvent(CommonTree eventNode) throws ParseException {
866e5b51
FC
653
654 List<CommonTree> children = eventNode.getChildren();
655 if (children == null) {
656 throw new ParseException("Empty event block"); //$NON-NLS-1$
657 }
658
659 EventDeclaration event = new EventDeclaration();
660
661 pushScope();
662
663 for (CommonTree child : children) {
664 switch (child.getType()) {
665 case CTFParser.TYPEALIAS:
666 parseTypealias(child);
667 break;
668 case CTFParser.TYPEDEF:
669 parseTypedef(child);
670 break;
671 case CTFParser.CTF_EXPRESSION_TYPE:
672 case CTFParser.CTF_EXPRESSION_VAL:
673 parseEventDeclaration(child, event);
674 break;
675 default:
676 childTypeError(child);
677 break;
678 }
679 }
680
681 if (!event.nameIsSet()) {
682 throw new ParseException("Event name not set"); //$NON-NLS-1$
683 }
684
685 /*
686 * If the event did not specify a stream, then the trace must be single
687 * stream
688 */
689 if (!event.streamIsSet()) {
690 if (trace.nbStreams() > 1) {
2c053b6e 691 throw new ParseException("Event without stream_id with more than one stream"); //$NON-NLS-1$
866e5b51
FC
692 }
693
694 /*
695 * If the event did not specify a stream, the only existing stream
696 * must not have an id. Note: That behavior could be changed, it
697 * could be possible to just get the only existing stream, whatever
698 * is its id.
699 */
700 Stream stream = trace.getStream(null);
701
702 if (stream != null) {
703 event.setStream(stream);
704 } else {
2c053b6e 705 throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
866e5b51
FC
706 }
707 }
708
709 /*
710 * Add the event to the stream.
711 */
712 event.getStream().addEvent(event);
713
714 popScope();
715 }
716
717 private void parseEventDeclaration(CommonTree eventDecl,
718 EventDeclaration event) throws ParseException {
866e5b51
FC
719
720 /* There should be a left and right */
866e5b51
FC
721
722 CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
866e5b51 723 CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
866e5b51
FC
724
725 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51 726
4311ac8b 727 if (!isAnyUnaryString(leftStrings.get(0))) {
2c053b6e 728 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
866e5b51
FC
729 }
730
731 String left = concatenateUnaryStrings(leftStrings);
732
fafc36a7 733 if (left.equals(MetadataStrings.NAME2)) {
866e5b51
FC
734 if (event.nameIsSet()) {
735 throw new ParseException("name already defined"); //$NON-NLS-1$
736 }
737
738 String name = getEventName(rightNode);
739
740 event.setName(name);
fafc36a7 741 } else if (left.equals(MetadataStrings.ID)) {
866e5b51
FC
742 if (event.idIsSet()) {
743 throw new ParseException("id already defined"); //$NON-NLS-1$
744 }
745
746 long id = getEventID(rightNode);
747
748 event.setId(id);
fafc36a7 749 } else if (left.equals(MetadataStrings.STREAM_ID)) {
866e5b51
FC
750 if (event.streamIsSet()) {
751 throw new ParseException("stream id already defined"); //$NON-NLS-1$
752 }
753
754 long streamId = getStreamID(rightNode);
755
756 Stream stream = trace.getStream(streamId);
757
758 if (stream == null) {
759 throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
760 }
761
762 event.setStream(stream);
fafc36a7 763 } else if (left.equals(MetadataStrings.CONTEXT)) {
866e5b51
FC
764 if (event.contextIsSet()) {
765 throw new ParseException("context already defined"); //$NON-NLS-1$
766 }
767
768 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
769
770 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
771 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
772 }
773
774 IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier,
775 null);
776
777 if (!(contextDecl instanceof StructDeclaration)) {
778 throw new ParseException("context expects a struct"); //$NON-NLS-1$
779 }
780
781 event.setContext((StructDeclaration) contextDecl);
fafc36a7 782 } else if (left.equals(MetadataStrings.FIELDS_STRING)) {
866e5b51
FC
783 if (event.fieldsIsSet()) {
784 throw new ParseException("fields already defined"); //$NON-NLS-1$
785 }
786
787 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
788
789 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
790 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
791 }
792
13be1a8f
AM
793 IDeclaration fieldsDecl;
794 fieldsDecl = parseTypeSpecifierList(typeSpecifier, null);
866e5b51
FC
795
796 if (!(fieldsDecl instanceof StructDeclaration)) {
797 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
798 }
799 /*
32ede2ec
MK
800 * The underscores in the event names. These underscores were added
801 * by the LTTng tracer.
866e5b51 802 */
91847dfc 803 final StructDeclaration fields = (StructDeclaration) fieldsDecl;
866e5b51 804 event.setFields(fields);
fafc36a7 805 } else if (left.equals(MetadataStrings.LOGLEVEL2)) {
32ede2ec 806 long logLevel = parseUnaryInteger((CommonTree) rightNode.getChild(0));
53047a66 807 event.setLogLevel(logLevel);
866e5b51 808 } else {
8e964be1
MK
809 /* Custom event attribute, we'll add it to the attributes map */
810 String right = parseUnaryString((CommonTree) rightNode.getChild(0));
811 event.setCustomAttribute(left, right);
866e5b51
FC
812 }
813 }
814
815 /**
816 * Parses a declaration at the root level.
817 *
818 * @param declaration
819 * The declaration subtree.
820 * @throws ParseException
821 */
822 private void parseRootDeclaration(CommonTree declaration)
823 throws ParseException {
866e5b51
FC
824
825 List<CommonTree> children = declaration.getChildren();
866e5b51
FC
826
827 for (CommonTree child : children) {
828 switch (child.getType()) {
829 case CTFParser.TYPEDEF:
830 parseTypedef(child);
831 break;
832 case CTFParser.TYPEALIAS:
833 parseTypealias(child);
834 break;
835 case CTFParser.TYPE_SPECIFIER_LIST:
836 parseTypeSpecifierList(child, null);
837 break;
838 default:
839 childTypeError(child);
840 }
841 }
842 }
843
844 /**
845 * Parses a typealias node. It parses the target, the alias, and registers
846 * the type in the current scope.
847 *
848 * @param typealias
849 * A TYPEALIAS node.
850 * @throws ParseException
851 */
852 private void parseTypealias(CommonTree typealias) throws ParseException {
866e5b51
FC
853
854 List<CommonTree> children = typealias.getChildren();
866e5b51
FC
855
856 CommonTree target = null;
857 CommonTree alias = null;
858
859 for (CommonTree child : children) {
860 switch (child.getType()) {
861 case CTFParser.TYPEALIAS_TARGET:
866e5b51
FC
862 target = child;
863 break;
864 case CTFParser.TYPEALIAS_ALIAS:
866e5b51
FC
865 alias = child;
866 break;
867 default:
868 childTypeError(child);
869 break;
870 }
871 }
872
866e5b51
FC
873 IDeclaration targetDeclaration = parseTypealiasTarget(target);
874
0594c61c
AM
875 if ((targetDeclaration instanceof VariantDeclaration)
876 && ((VariantDeclaration) targetDeclaration).isTagged()) {
877 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
866e5b51
FC
878 }
879
880 String aliasString = parseTypealiasAlias(alias);
881
882 getCurrentScope().registerType(aliasString, targetDeclaration);
883 }
884
885 /**
886 * Parses the target part of a typealias and gets the corresponding
887 * declaration.
888 *
889 * @param target
890 * A TYPEALIAS_TARGET node.
891 * @return The corresponding declaration.
892 * @throws ParseException
893 */
894 private IDeclaration parseTypealiasTarget(CommonTree target)
895 throws ParseException {
866e5b51
FC
896
897 List<CommonTree> children = target.getChildren();
866e5b51
FC
898
899 CommonTree typeSpecifierList = null;
900 CommonTree typeDeclaratorList = null;
901 CommonTree typeDeclarator = null;
902 StringBuilder identifierSB = new StringBuilder();
903
904 for (CommonTree child : children) {
905 switch (child.getType()) {
906 case CTFParser.TYPE_SPECIFIER_LIST:
866e5b51
FC
907 typeSpecifierList = child;
908 break;
909 case CTFParser.TYPE_DECLARATOR_LIST:
866e5b51
FC
910 typeDeclaratorList = child;
911 break;
912 default:
913 childTypeError(child);
914 break;
915 }
916 }
917
866e5b51
FC
918 if (typeDeclaratorList != null) {
919 /*
920 * Only allow one declarator
921 *
922 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
923 * otherwise the new type puint8_t would maps to two different
924 * types.
925 */
926 if (typeDeclaratorList.getChildCount() != 1) {
2c053b6e 927 throw new ParseException("Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
866e5b51
FC
928 }
929
930 typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
931 }
932
933 /* Parse the target type and get the declaration */
934 IDeclaration targetDeclaration = parseTypeDeclarator(typeDeclarator,
935 typeSpecifierList, identifierSB);
936
937 /*
938 * We don't allow identifier in the target
939 *
940 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
941 * permitted
942 */
943 if (identifierSB.length() > 0) {
944 throw new ParseException("Identifier (" + identifierSB.toString() //$NON-NLS-1$
945 + ") not expected in the typealias target"); //$NON-NLS-1$
946 }
947
948 return targetDeclaration;
949 }
950
951 /**
952 * Parses the alias part of a typealias. It parses the underlying specifier
953 * list and declarator and creates the string representation that will be
954 * used to register the type.
955 *
956 * @param alias
957 * A TYPEALIAS_ALIAS node.
958 * @return The string representation of the alias.
959 * @throws ParseException
960 */
961 private static String parseTypealiasAlias(CommonTree alias)
962 throws ParseException {
866e5b51
FC
963
964 List<CommonTree> children = alias.getChildren();
866e5b51
FC
965
966 CommonTree typeSpecifierList = null;
967 CommonTree typeDeclaratorList = null;
968 CommonTree typeDeclarator = null;
969 List<CommonTree> pointers = new LinkedList<CommonTree>();
970
971 for (CommonTree child : children) {
972 switch (child.getType()) {
973 case CTFParser.TYPE_SPECIFIER_LIST:
866e5b51
FC
974 typeSpecifierList = child;
975 break;
976 case CTFParser.TYPE_DECLARATOR_LIST:
866e5b51
FC
977 typeDeclaratorList = child;
978 break;
979 default:
980 childTypeError(child);
981 break;
982 }
983 }
984
985 /* If there is a type declarator list, extract the pointers */
986 if (typeDeclaratorList != null) {
987 /*
988 * Only allow one declarator
989 *
990 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
991 */
992 if (typeDeclaratorList.getChildCount() != 1) {
2c053b6e 993 throw new ParseException("Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
866e5b51
FC
994 }
995
996 typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
997
72dbc4ac 998 List<CommonTree> typeDeclaratorChildren = typeDeclarator.getChildren();
866e5b51
FC
999
1000 for (CommonTree child : typeDeclaratorChildren) {
1001 switch (child.getType()) {
1002 case CTFParser.POINTER:
1003 pointers.add(child);
1004 break;
1005 case CTFParser.IDENTIFIER:
1006 throw new ParseException("Identifier (" + child.getText() //$NON-NLS-1$
1007 + ") not expected in the typealias target"); //$NON-NLS-1$
866e5b51
FC
1008 default:
1009 childTypeError(child);
1010 break;
1011 }
1012 }
1013 }
1014
1015 return createTypeDeclarationString(typeSpecifierList, pointers);
1016 }
1017
1018 /**
1019 * Parses a typedef node. This creates and registers a new declaration for
1020 * each declarator found in the typedef.
1021 *
1022 * @param typedef
1023 * A TYPEDEF node.
1024 * @throws ParseException
1025 * If there is an error creating the declaration.
1026 */
1027 private void parseTypedef(CommonTree typedef) throws ParseException {
866e5b51 1028
72dbc4ac 1029 CommonTree typeDeclaratorListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
866e5b51 1030
72dbc4ac 1031 CommonTree typeSpecifierListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
866e5b51 1032
72dbc4ac 1033 List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
866e5b51
FC
1034
1035 for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
1036 StringBuilder identifierSB = new StringBuilder();
1037
0594c61c 1038 IDeclaration typeDeclaration = parseTypeDeclarator(
866e5b51
FC
1039 typeDeclaratorNode, typeSpecifierListNode, identifierSB);
1040
0594c61c 1041 if ((typeDeclaration instanceof VariantDeclaration)
2c053b6e
MK
1042 && ((VariantDeclaration) typeDeclaration).isTagged()) {
1043 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
866e5b51
FC
1044 }
1045
1046 getCurrentScope().registerType(identifierSB.toString(),
0594c61c 1047 typeDeclaration);
866e5b51
FC
1048 }
1049 }
1050
1051 /**
1052 * Parses a pair type declarator / type specifier list and returns the
1053 * corresponding declaration. If it is present, it also writes the
1054 * identifier of the declarator in the given {@link StringBuilder}.
1055 *
1056 * @param typeDeclarator
1057 * A TYPE_DECLARATOR node.
1058 * @param typeSpecifierList
1059 * A TYPE_SPECIFIER_LIST node.
1060 * @param identifierSB
1061 * A StringBuilder that will receive the identifier found in the
1062 * declarator.
1063 * @return The corresponding declaration.
1064 * @throws ParseException
1065 * If there is an error finding or creating the declaration.
1066 */
1067 private IDeclaration parseTypeDeclarator(CommonTree typeDeclarator,
1068 CommonTree typeSpecifierList, StringBuilder identifierSB)
1069 throws ParseException {
866e5b51
FC
1070
1071 IDeclaration declaration = null;
1072 List<CommonTree> children = null;
1073 List<CommonTree> pointers = new LinkedList<CommonTree>();
1074 List<CommonTree> lengths = new LinkedList<CommonTree>();
1075 CommonTree identifier = null;
1076
1077 /* Separate the tokens by type */
1078 if (typeDeclarator != null) {
1079 children = typeDeclarator.getChildren();
866e5b51
FC
1080 for (CommonTree child : children) {
1081
1082 switch (child.getType()) {
1083 case CTFParser.POINTER:
1084 pointers.add(child);
1085 break;
1086 case CTFParser.IDENTIFIER:
866e5b51
FC
1087 identifier = child;
1088 break;
1089 case CTFParser.LENGTH:
1090 lengths.add(child);
1091 break;
1092 default:
1093 childTypeError(child);
1094 break;
1095 }
1096 }
1097
1098 }
1099
1100 /*
1101 * Parse the type specifier list, which is the "base" type. For example,
1102 * it would be int in int a[3][len].
1103 */
1104 declaration = parseTypeSpecifierList(typeSpecifierList, pointers);
1105
1106 /*
1107 * Each length subscript means that we must create a nested array or
1108 * sequence. For example, int a[3][len] means that we have an array of 3
1109 * (sequences of length 'len' of (int)).
1110 */
32ede2ec 1111 if (lengths.size() > 0) {
866e5b51
FC
1112 /* We begin at the end */
1113 Collections.reverse(lengths);
1114
1115 for (CommonTree length : lengths) {
1116 /*
1117 * By looking at the first expression, we can determine whether
1118 * it is an array or a sequence.
1119 */
1120 List<CommonTree> lengthChildren = length.getChildren();
866e5b51
FC
1121
1122 CommonTree first = lengthChildren.get(0);
1123 if (isUnaryInteger(first)) {
1124 /* Array */
1125 int arrayLength = (int) parseUnaryInteger(first);
1126
1127 if (arrayLength < 1) {
1128 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1129 }
1130
1131 /* Create the array declaration. */
1132 declaration = new ArrayDeclaration(arrayLength, declaration);
4311ac8b 1133 } else if (isAnyUnaryString(first)) {
866e5b51
FC
1134 /* Sequence */
1135 String lengthName = concatenateUnaryStrings(lengthChildren);
1136
2c053b6e
MK
1137 /* check that lengthName was declared */
1138 if (isSignedIntegerField(lengthName)) {
1139 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
1140 }
866e5b51
FC
1141 /* Create the sequence declaration. */
1142 declaration = new SequenceDeclaration(lengthName,
1143 declaration);
1144 } else {
1145 childTypeError(first);
1146 }
1147 }
1148 }
1149
1150 if (identifier != null) {
1151 identifierSB.append(identifier.getText());
1152 }
1153
1154 return declaration;
1155 }
1156
2c053b6e
MK
1157 private boolean isSignedIntegerField(String lengthName) throws ParseException {
1158 IDeclaration decl = getCurrentScope().lookupIdentifierRecursive(lengthName);
1159 if (decl instanceof IntegerDeclaration) {
1160 return ((IntegerDeclaration) decl).isSigned();
1161 }
1162 throw new ParseException("Is not an integer: " + lengthName); //$NON-NLS-1$
1163
1164 }
1165
866e5b51
FC
1166 /**
1167 * Parses a type specifier list and returns the corresponding declaration.
1168 *
1169 * @param typeSpecifierList
1170 * A TYPE_SPECIFIER_LIST node.
1171 * @param pointerList
1172 * A list of POINTER nodes that apply to the specified type.
1173 * @return The corresponding declaration.
1174 * @throws ParseException
1175 * If the type has not been defined or if there is an error
1176 * creating the declaration.
1177 */
1178 private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList,
1179 List<CommonTree> pointerList) throws ParseException {
866e5b51
FC
1180 IDeclaration declaration = null;
1181
1182 /*
1183 * By looking at the first element of the type specifier list, we can
1184 * determine which type it belongs to.
1185 */
1186 CommonTree firstChild = (CommonTree) typeSpecifierList.getChild(0);
866e5b51
FC
1187
1188 switch (firstChild.getType()) {
1189 case CTFParser.FLOATING_POINT:
53047a66 1190 declaration = parseFloat(firstChild);
866e5b51
FC
1191 break;
1192 case CTFParser.INTEGER:
1193 declaration = parseInteger(firstChild);
1194 break;
1195 case CTFParser.STRING:
1196 declaration = parseString(firstChild);
1197 break;
1198 case CTFParser.STRUCT:
1199 declaration = parseStruct(firstChild);
1200 break;
1201 case CTFParser.VARIANT:
1202 declaration = parseVariant(firstChild);
1203 break;
1204 case CTFParser.ENUM:
1205 declaration = parseEnum(firstChild);
1206 break;
1207 case CTFParser.IDENTIFIER:
1208 case CTFParser.FLOATTOK:
1209 case CTFParser.INTTOK:
1210 case CTFParser.LONGTOK:
1211 case CTFParser.SHORTTOK:
1212 case CTFParser.SIGNEDTOK:
1213 case CTFParser.UNSIGNEDTOK:
1214 case CTFParser.CHARTOK:
1215 case CTFParser.DOUBLETOK:
1216 case CTFParser.VOIDTOK:
1217 case CTFParser.BOOLTOK:
1218 case CTFParser.COMPLEXTOK:
1219 case CTFParser.IMAGINARYTOK:
1220 declaration = parseTypeDeclaration(typeSpecifierList, pointerList);
1221 break;
1222 default:
1223 childTypeError(firstChild);
1224 }
1225
866e5b51
FC
1226 return declaration;
1227 }
1228
32ede2ec
MK
1229 private IDeclaration parseFloat(CommonTree floatingPoint)
1230 throws ParseException {
53047a66
MK
1231
1232 List<CommonTree> children = floatingPoint.getChildren();
1233
1234 /*
1235 * If the integer has no attributes, then it is missing the size
1236 * attribute which is required
1237 */
1238 if (children == null) {
1239 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1240 }
1241
1242 /* The return value */
1243 FloatDeclaration floatDeclaration = null;
1244 ByteOrder byteOrder = trace.getByteOrder();
1245 long alignment = 0;
53047a66
MK
1246 int exponent = 8;
1247 int mantissa = 24;
1248
53047a66
MK
1249 /* Iterate on all integer children */
1250 for (CommonTree child : children) {
1251 switch (child.getType()) {
1252 case CTFParser.CTF_EXPRESSION_VAL:
1253 /*
1254 * An assignment expression must have 2 children, left and right
1255 */
53047a66
MK
1256
1257 CommonTree leftNode = (CommonTree) child.getChild(0);
53047a66 1258 CommonTree rightNode = (CommonTree) child.getChild(1);
53047a66
MK
1259
1260 List<CommonTree> leftStrings = leftNode.getChildren();
53047a66 1261
4311ac8b 1262 if (!isAnyUnaryString(leftStrings.get(0))) {
2c053b6e 1263 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
53047a66
MK
1264 }
1265 String left = concatenateUnaryStrings(leftStrings);
1266
fafc36a7 1267 if (left.equals(MetadataStrings.EXP_DIG)) {
53047a66 1268 exponent = (int) parseUnaryInteger((CommonTree) rightNode.getChild(0));
fafc36a7 1269 } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
53047a66 1270 byteOrder = getByteOrder(rightNode);
fafc36a7 1271 } else if (left.equals(MetadataStrings.MANT_DIG)) {
53047a66 1272 mantissa = (int) parseUnaryInteger((CommonTree) rightNode.getChild(0));
fafc36a7 1273 } else if (left.equals(MetadataStrings.ALIGN)) {
53047a66
MK
1274 alignment = getAlignment(rightNode);
1275 } else {
1276 throw new ParseException("Float: unknown attribute " + left); //$NON-NLS-1$
1277 }
1278
1279 break;
1280 default:
1281 childTypeError(child);
1282 break;
1283 }
1284 }
1285 int size = mantissa + exponent;
1286 if (size == 0) {
1287 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1288 }
1289
1290 if (alignment == 0) {
1291 if ((size % 8) == 0) {
1292 alignment = 1;
1293 } else {
1294 alignment = 8;
1295 }
1296 }
1297
07002e0a 1298 floatDeclaration = new FloatDeclaration(exponent, mantissa, byteOrder, alignment);
53047a66 1299
53047a66
MK
1300 return floatDeclaration;
1301
1302 }
1303
866e5b51
FC
1304 /**
1305 * Parses a type specifier list as a user-declared type.
1306 *
1307 * @param typeSpecifierList
1308 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1309 * @param pointerList
1310 * A list of POINTER nodes that apply to the type specified in
1311 * typeSpecifierList.
1312 * @return The corresponding declaration.
1313 * @throws ParseException
1314 * If the type does not exist (has not been found).
1315 */
1316 private IDeclaration parseTypeDeclaration(CommonTree typeSpecifierList,
1317 List<CommonTree> pointerList) throws ParseException {
1318 /* Create the string representation of the type declaration */
1319 String typeStringRepresentation = createTypeDeclarationString(
1320 typeSpecifierList, pointerList);
1321
1322 /* Use the string representation to search the type in the current scope */
2c053b6e 1323 IDeclaration decl = getCurrentScope().lookupTypeRecursive(
866e5b51
FC
1324 typeStringRepresentation);
1325
1326 if (decl == null) {
1327 throw new ParseException("Type " + typeStringRepresentation //$NON-NLS-1$
1328 + " has not been defined."); //$NON-NLS-1$
1329 }
1330
1331 return decl;
1332 }
1333
1334 /**
1335 * Parses an integer declaration node.
1336 *
1337 * @param integer
1338 * An INTEGER node.
1339 * @return The corresponding integer declaration.
1340 * @throws ParseException
1341 */
1342 private IntegerDeclaration parseInteger(CommonTree integer)
1343 throws ParseException {
866e5b51
FC
1344
1345 List<CommonTree> children = integer.getChildren();
1346
1347 /*
1348 * If the integer has no attributes, then it is missing the size
1349 * attribute which is required
1350 */
1351 if (children == null) {
1352 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1353 }
1354
1355 /* The return value */
1356 IntegerDeclaration integerDeclaration = null;
1357 boolean signed = false;
1358 ByteOrder byteOrder = trace.getByteOrder();
1359 long size = 0;
1360 long alignment = 0;
1361 int base = 10;
284fdee8 1362 String clock = null;
866e5b51
FC
1363
1364 Encoding encoding = Encoding.NONE;
1365
1366 /* Iterate on all integer children */
1367 for (CommonTree child : children) {
1368 switch (child.getType()) {
1369 case CTFParser.CTF_EXPRESSION_VAL:
1370 /*
1371 * An assignment expression must have 2 children, left and right
1372 */
866e5b51
FC
1373
1374 CommonTree leftNode = (CommonTree) child.getChild(0);
866e5b51 1375 CommonTree rightNode = (CommonTree) child.getChild(1);
866e5b51
FC
1376
1377 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51 1378
4311ac8b 1379 if (!isAnyUnaryString(leftStrings.get(0))) {
2c053b6e 1380 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
866e5b51
FC
1381 }
1382 String left = concatenateUnaryStrings(leftStrings);
1383
1384 if (left.equals("signed")) { //$NON-NLS-1$
1385 signed = getSigned(rightNode);
fafc36a7 1386 } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
866e5b51
FC
1387 byteOrder = getByteOrder(rightNode);
1388 } else if (left.equals("size")) { //$NON-NLS-1$
1389 size = getSize(rightNode);
fafc36a7 1390 } else if (left.equals(MetadataStrings.ALIGN)) {
866e5b51
FC
1391 alignment = getAlignment(rightNode);
1392 } else if (left.equals("base")) { //$NON-NLS-1$
1393 base = getBase(rightNode);
1394 } else if (left.equals("encoding")) { //$NON-NLS-1$
1395 encoding = getEncoding(rightNode);
1396 } else if (left.equals("map")) { //$NON-NLS-1$
1397 clock = getClock(rightNode);
1398 } else {
4311ac8b 1399 Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownIntegerAttributeWarning + " " + left); //$NON-NLS-1$
866e5b51
FC
1400 }
1401
1402 break;
1403 default:
1404 childTypeError(child);
1405 break;
1406 }
1407 }
1408
1409 if (size == 0) {
1410 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1411 }
1412
1413 if (alignment == 0) {
1414 if ((size % 8) == 0) {
1415 alignment = 1;
1416 } else {
1417 alignment = 8;
1418 }
1419 }
1420
1421 integerDeclaration = new IntegerDeclaration((int) size, signed, base,
fd74e6c1 1422 byteOrder, encoding, clock, alignment);
866e5b51 1423
866e5b51
FC
1424 return integerDeclaration;
1425 }
1426
284fdee8 1427 private static String getClock(CommonTree rightNode) {
866e5b51
FC
1428 return rightNode.getChild(1).getChild(0).getChild(0).getText();
1429 }
1430
1431 private static StringDeclaration parseString(CommonTree string)
1432 throws ParseException {
866e5b51
FC
1433
1434 List<CommonTree> children = string.getChildren();
1435 StringDeclaration stringDeclaration = null;
1436
1437 if (children == null) {
1438 stringDeclaration = new StringDeclaration();
1439 } else {
1440 Encoding encoding = Encoding.UTF8;
1441 for (CommonTree child : children) {
1442 switch (child.getType()) {
1443 case CTFParser.CTF_EXPRESSION_VAL:
1444 /*
1445 * An assignment expression must have 2 children, left and
1446 * right
1447 */
866e5b51
FC
1448
1449 CommonTree leftNode = (CommonTree) child.getChild(0);
866e5b51 1450 CommonTree rightNode = (CommonTree) child.getChild(1);
866e5b51
FC
1451
1452 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51 1453
4311ac8b 1454 if (!isAnyUnaryString(leftStrings.get(0))) {
2c053b6e 1455 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
866e5b51
FC
1456 }
1457 String left = concatenateUnaryStrings(leftStrings);
1458
1459 if (left.equals("encoding")) { //$NON-NLS-1$
1460 encoding = getEncoding(rightNode);
1461 } else {
1462 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1463 + left);
1464 }
1465
1466 break;
1467 default:
1468 childTypeError(child);
1469 break;
1470 }
1471 }
1472
1473 stringDeclaration = new StringDeclaration(encoding);
1474 }
1475
1476 return stringDeclaration;
1477 }
1478
1479 /**
1480 * Parses a struct declaration and returns the corresponding declaration.
1481 *
1482 * @param struct
1483 * An STRUCT node.
1484 * @return The corresponding struct declaration.
1485 * @throws ParseException
1486 */
1487 private StructDeclaration parseStruct(CommonTree struct)
1488 throws ParseException {
866e5b51
FC
1489
1490 List<CommonTree> children = struct.getChildren();
866e5b51
FC
1491
1492 /* The return value */
1493 StructDeclaration structDeclaration = null;
1494
1495 /* Name */
1496 String structName = null;
1497 boolean hasName = false;
1498
1499 /* Body */
1500 CommonTree structBody = null;
1501 boolean hasBody = false;
1502
1503 /* Align */
1504 long structAlign = 0;
1505
1506 /* Loop on all children and identify what we have to work with. */
1507 for (CommonTree child : children) {
1508 switch (child.getType()) {
1509 case CTFParser.STRUCT_NAME: {
1510 hasName = true;
1511
72dbc4ac 1512 CommonTree structNameIdentifier = (CommonTree) child.getChild(0);
866e5b51 1513
866e5b51
FC
1514 structName = structNameIdentifier.getText();
1515
1516 break;
1517 }
1518 case CTFParser.STRUCT_BODY: {
1519 hasBody = true;
1520
1521 structBody = child;
1522
1523 break;
1524 }
1525 case CTFParser.ALIGN: {
72dbc4ac 1526 CommonTree structAlignExpression = (CommonTree) child.getChild(0);
866e5b51
FC
1527
1528 structAlign = getAlignment(structAlignExpression);
1529
1530 break;
1531 }
1532 default:
1533 childTypeError(child);
1534
1535 break;
1536 }
1537 }
1538
1539 /*
1540 * If a struct has just a body and no name (just like the song,
1541 * "A Struct With No Name" by America (sorry for that...)), it's a
1542 * definition of a new type, so we create the type declaration and
1543 * return it. We can't add it to the declaration scope since there is no
1544 * name, but that's what we want because it won't be possible to use it
1545 * again to declare another field.
1546 *
1547 * If it has just a name, we look it up in the declaration scope and
1548 * return the associated declaration. If it is not found in the
1549 * declaration scope, it means that a struct with that name has not been
1550 * declared, which is an error.
1551 *
1552 * If it has both, then we create the type declaration and register it
1553 * to the current scope.
1554 *
1555 * If it has none, then what are we doing here ?
1556 */
1557 if (hasBody) {
1558 /*
1559 * If struct has a name, check if already defined in the current
1560 * scope.
1561 */
1562 if (hasName && (getCurrentScope().lookupStruct(structName) != null)) {
1563 throw new ParseException("struct " + structName //$NON-NLS-1$
1564 + " already defined."); //$NON-NLS-1$
1565 }
866e5b51
FC
1566 /* Create the declaration */
1567 structDeclaration = new StructDeclaration(structAlign);
1568
1569 /* Parse the body */
1570 parseStructBody(structBody, structDeclaration);
1571
1572 /* If struct has name, add it to the current scope. */
1573 if (hasName) {
1574 getCurrentScope().registerStruct(structName, structDeclaration);
1575 }
1576 } else /* !hasBody */{
1577 if (hasName) {
1578 /* Name and !body */
1579
1580 /* Lookup the name in the current scope. */
2c053b6e 1581 structDeclaration = getCurrentScope().lookupStructRecursive(structName);
866e5b51
FC
1582
1583 /*
1584 * If not found, it means that a struct with such name has not
1585 * been defined
1586 */
1587 if (structDeclaration == null) {
1588 throw new ParseException("struct " + structName //$NON-NLS-1$
1589 + " is not defined"); //$NON-NLS-1$
1590 }
1591 } else {
1592 /* !Name and !body */
1593
1594 /* We can't do anything with that. */
1595 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1596 }
1597 }
1598
866e5b51
FC
1599 return structDeclaration;
1600 }
1601
1602 /**
1603 * Parses a struct body, adding the fields to specified structure
1604 * declaration.
1605 *
1606 * @param structBody
1607 * A STRUCT_BODY node.
1608 * @param structDeclaration
1609 * The struct declaration.
1610 * @throws ParseException
1611 */
1612 private void parseStructBody(CommonTree structBody,
1613 StructDeclaration structDeclaration) throws ParseException {
866e5b51
FC
1614
1615 List<CommonTree> structDeclarations = structBody.getChildren();
1616
1617 /*
1618 * If structDeclaration is null, structBody has no children and the
1619 * struct body is empty.
1620 */
1621 if (structDeclarations != null) {
1622 pushScope();
1623
1624 for (CommonTree declarationNode : structDeclarations) {
1625 switch (declarationNode.getType()) {
1626 case CTFParser.TYPEALIAS:
1627 parseTypealias(declarationNode);
1628 break;
1629 case CTFParser.TYPEDEF:
1630 parseTypedef(declarationNode);
1631 break;
1632 case CTFParser.SV_DECLARATION:
1633 parseStructDeclaration(declarationNode, structDeclaration);
1634 break;
1635 default:
1636 childTypeError(declarationNode);
1637 break;
1638 }
1639 }
1640 popScope();
1641 }
1642 }
1643
1644 /**
1645 * Parses a declaration found in a struct.
1646 *
1647 * @param declaration
1648 * A SV_DECLARATION node.
1649 * @param struct
1650 * A struct declaration. (I know, little name clash here...)
1651 * @throws ParseException
1652 */
1653 private void parseStructDeclaration(CommonTree declaration,
1654 StructDeclaration struct) throws ParseException {
866e5b51 1655
866e5b51 1656 /* Get the type specifier list node */
72dbc4ac 1657 CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
866e5b51
FC
1658
1659 /* Get the type declarator list node */
72dbc4ac 1660 CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
866e5b51
FC
1661
1662 /* Get the type declarator list */
72dbc4ac 1663 List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
866e5b51
FC
1664
1665 /*
1666 * For each type declarator, parse the declaration and add a field to
1667 * the struct
1668 */
1669 for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
866e5b51
FC
1670
1671 StringBuilder identifierSB = new StringBuilder();
1672
1673 IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
1674 typeSpecifierListNode, identifierSB);
1675 String fieldName = identifierSB.toString();
2c053b6e 1676 getCurrentScope().registerIdentifier(fieldName, decl);
866e5b51
FC
1677
1678 if (struct.hasField(fieldName)) {
1679 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1680 + fieldName);
1681 }
1682
1683 struct.addField(fieldName, decl);
1684
1685 }
1686 }
1687
1688 /**
1689 * Parses an enum declaration and returns the corresponding declaration.
1690 *
0594c61c 1691 * @param theEnum
866e5b51
FC
1692 * An ENUM node.
1693 * @return The corresponding enum declaration.
1694 * @throws ParseException
1695 */
0594c61c 1696 private EnumDeclaration parseEnum(CommonTree theEnum) throws ParseException {
866e5b51 1697
0594c61c 1698 List<CommonTree> children = theEnum.getChildren();
866e5b51
FC
1699
1700 /* The return value */
1701 EnumDeclaration enumDeclaration = null;
1702
1703 /* Name */
1704 String enumName = null;
1705
1706 /* Body */
1707 CommonTree enumBody = null;
1708
1709 /* Container type */
1710 IntegerDeclaration containerTypeDeclaration = null;
1711
1712 /* Loop on all children and identify what we have to work with. */
1713 for (CommonTree child : children) {
1714 switch (child.getType()) {
1715 case CTFParser.ENUM_NAME: {
866e5b51 1716 CommonTree enumNameIdentifier = (CommonTree) child.getChild(0);
866e5b51 1717 enumName = enumNameIdentifier.getText();
866e5b51
FC
1718 break;
1719 }
1720 case CTFParser.ENUM_BODY: {
866e5b51 1721 enumBody = child;
866e5b51
FC
1722 break;
1723 }
1724 case CTFParser.ENUM_CONTAINER_TYPE: {
866e5b51 1725 containerTypeDeclaration = parseEnumContainerType(child);
866e5b51
FC
1726 break;
1727 }
1728 default:
1729 childTypeError(child);
1730 break;
1731 }
1732 }
1733
1734 /*
1735 * If the container type has not been defined explicitly, we assume it
1736 * is "int".
1737 */
1738 if (containerTypeDeclaration == null) {
32ede2ec
MK
1739 IDeclaration enumDecl;
1740 /*
1741 * it could be because the enum was already declared.
1742 */
1743 if (enumName != null) {
2c053b6e 1744 enumDecl = getCurrentScope().lookupEnumRecursive(enumName);
32ede2ec
MK
1745 if (enumDecl != null) {
1746 return (EnumDeclaration) enumDecl;
1747 }
1748 }
1749
2c053b6e 1750 IDeclaration decl = getCurrentScope().lookupTypeRecursive("int"); //$NON-NLS-1$
866e5b51
FC
1751
1752 if (decl == null) {
2c053b6e 1753 throw new ParseException("enum container type implicit and type int not defined"); //$NON-NLS-1$
866e5b51 1754 } else if (!(decl instanceof IntegerDeclaration)) {
2c053b6e 1755 throw new ParseException("enum container type implicit and type int not an integer"); //$NON-NLS-1$
866e5b51
FC
1756 }
1757
1758 containerTypeDeclaration = (IntegerDeclaration) decl;
1759 }
1760
1761 /*
1762 * If it has a body, it's a new declaration, otherwise it's a reference
1763 * to an existing declaration. Same logic as struct.
1764 */
1765 if (enumBody != null) {
1766 /*
1767 * If enum has a name, check if already defined in the current
1768 * scope.
1769 */
1770 if ((enumName != null)
1771 && (getCurrentScope().lookupEnum(enumName) != null)) {
1772 throw new ParseException("enum " + enumName //$NON-NLS-1$
1773 + " already defined"); //$NON-NLS-1$
1774 }
1775
1776 /* Create the declaration */
1777 enumDeclaration = new EnumDeclaration(containerTypeDeclaration);
1778
1779 /* Parse the body */
1780 parseEnumBody(enumBody, enumDeclaration);
1781
1782 /* If the enum has name, add it to the current scope. */
1783 if (enumName != null) {
1784 getCurrentScope().registerEnum(enumName, enumDeclaration);
1785 }
1786 } else {
1787 if (enumName != null) {
1788 /* Name and !body */
1789
1790 /* Lookup the name in the current scope. */
2c053b6e 1791 enumDeclaration = getCurrentScope().lookupEnumRecursive(enumName);
866e5b51
FC
1792
1793 /*
1794 * If not found, it means that an enum with such name has not
1795 * been defined
1796 */
1797 if (enumDeclaration == null) {
1798 throw new ParseException("enum " + enumName //$NON-NLS-1$
1799 + " is not defined"); //$NON-NLS-1$
1800 }
1801 } else {
1802 /* !Name and !body */
1803 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1804 }
1805 }
1806
1807 return enumDeclaration;
1808
1809 }
1810
1811 /**
1812 * Parses an enum body, adding the enumerators to the specified enum
1813 * declaration.
1814 *
1815 * @param enumBody
1816 * An ENUM_BODY node.
1817 * @param enumDeclaration
1818 * The enum declaration.
1819 * @throws ParseException
1820 */
1821 private void parseEnumBody(CommonTree enumBody,
1822 EnumDeclaration enumDeclaration) throws ParseException {
866e5b51
FC
1823
1824 List<CommonTree> enumerators = enumBody.getChildren();
1825 /* enum body can't be empty (unlike struct). */
866e5b51
FC
1826
1827 pushScope();
1828
1829 /*
1830 * Start at -1, so that if the first enumrator has no explicit value, it
1831 * will choose 0
1832 */
1833 long lastHigh = -1;
1834
1835 for (CommonTree enumerator : enumerators) {
1836 lastHigh = parseEnumEnumerator(enumerator, enumDeclaration,
1837 lastHigh);
1838 }
1839
1840 popScope();
1841
1842 }
1843
1844 /**
1845 * Parses an enumerator node and adds an enumerator declaration to an
1846 * enumeration declaration.
1847 *
1848 * The high value of the range of the last enumerator is needed in case the
1849 * current enumerator does not specify its value.
1850 *
1851 * @param enumerator
1852 * An ENUM_ENUMERATOR node.
1853 * @param enumDeclaration
1854 * en enumeration declaration to which will be added the
1855 * enumerator.
1856 * @param lastHigh
1857 * The high value of the range of the last enumerator
1858 * @return The high value of the value range of the current enumerator.
1859 * @throws ParseException
1860 */
1861 private static long parseEnumEnumerator(CommonTree enumerator,
1862 EnumDeclaration enumDeclaration, long lastHigh)
1863 throws ParseException {
866e5b51
FC
1864
1865 List<CommonTree> children = enumerator.getChildren();
866e5b51
FC
1866
1867 long low = 0, high = 0;
1868 boolean valueSpecified = false;
1869 String label = null;
1870
1871 for (CommonTree child : children) {
4311ac8b 1872 if (isAnyUnaryString(child)) {
866e5b51
FC
1873 label = parseUnaryString(child);
1874 } else if (child.getType() == CTFParser.ENUM_VALUE) {
866e5b51
FC
1875
1876 valueSpecified = true;
1877
1878 low = parseUnaryInteger((CommonTree) child.getChild(0));
1879 high = low;
1880 } else if (child.getType() == CTFParser.ENUM_VALUE_RANGE) {
866e5b51
FC
1881
1882 valueSpecified = true;
1883
1884 low = parseUnaryInteger((CommonTree) child.getChild(0));
1885 high = parseUnaryInteger((CommonTree) child.getChild(1));
1886 } else {
1887 childTypeError(child);
1888 }
1889 }
1890
866e5b51
FC
1891 if (!valueSpecified) {
1892 low = lastHigh + 1;
1893 high = low;
1894 }
1895
1896 if (low > high) {
1897 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1898 }
1899
1900 if (!enumDeclaration.add(low, high, label)) {
1901 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1902 }
1903
4311ac8b
MAL
1904 if (valueSpecified && (BigInteger.valueOf(low).compareTo(enumDeclaration.getContainerType().getMinValue()) == -1 ||
1905 BigInteger.valueOf(high).compareTo(enumDeclaration.getContainerType().getMaxValue()) == 1)) {
1906 throw new ParseException("enum value is not in range"); //$NON-NLS-1$
1907 }
1908
866e5b51
FC
1909 return high;
1910 }
1911
1912 /**
1913 * Parses an enum container type node and returns the corresponding integer
1914 * type.
1915 *
1916 * @param enumContainerType
1917 * An ENUM_CONTAINER_TYPE node.
1918 * @return An integer declaration corresponding to the container type.
1919 * @throws ParseException
1920 * If the type does not parse correctly or if it is not an
1921 * integer type.
1922 */
1923 private IntegerDeclaration parseEnumContainerType(
1924 CommonTree enumContainerType) throws ParseException {
866e5b51
FC
1925
1926 /* Get the child, which should be a type specifier list */
72dbc4ac 1927 CommonTree typeSpecifierList = (CommonTree) enumContainerType.getChild(0);
866e5b51
FC
1928
1929 /* Parse it and get the corresponding declaration */
1930 IDeclaration decl = parseTypeSpecifierList(typeSpecifierList, null);
1931
1932 /* If is is an integer, return it, else throw an error */
1933 if (decl instanceof IntegerDeclaration) {
1934 return (IntegerDeclaration) decl;
1935 }
1936 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1937 }
1938
1939 private VariantDeclaration parseVariant(CommonTree variant)
1940 throws ParseException {
866e5b51
FC
1941
1942 List<CommonTree> children = variant.getChildren();
1943 VariantDeclaration variantDeclaration = null;
1944
1945 boolean hasName = false;
1946 String variantName = null;
1947
1948 boolean hasBody = false;
1949 CommonTree variantBody = null;
1950
1951 boolean hasTag = false;
1952 String variantTag = null;
1953
1954 for (CommonTree child : children) {
1955 switch (child.getType()) {
1956 case CTFParser.VARIANT_NAME:
866e5b51
FC
1957
1958 hasName = true;
1959
72dbc4ac 1960 CommonTree variantNameIdentifier = (CommonTree) child.getChild(0);
866e5b51 1961
866e5b51
FC
1962 variantName = variantNameIdentifier.getText();
1963
1964 break;
1965 case CTFParser.VARIANT_TAG:
866e5b51
FC
1966
1967 hasTag = true;
1968
72dbc4ac 1969 CommonTree variantTagIdentifier = (CommonTree) child.getChild(0);
866e5b51 1970
866e5b51
FC
1971 variantTag = variantTagIdentifier.getText();
1972
1973 break;
1974 case CTFParser.VARIANT_BODY:
866e5b51
FC
1975
1976 hasBody = true;
1977
1978 variantBody = child;
1979
1980 break;
1981 default:
1982 childTypeError(child);
1983 break;
1984 }
1985 }
1986
1987 if (hasBody) {
1988 /*
1989 * If variant has a name, check if already defined in the current
1990 * scope.
1991 */
1992 if (hasName
1993 && (getCurrentScope().lookupVariant(variantName) != null)) {
1994 throw new ParseException("variant " + variantName //$NON-NLS-1$
1995 + " already defined."); //$NON-NLS-1$
1996 }
1997
1998 /* Create the declaration */
1999 variantDeclaration = new VariantDeclaration();
2000
2001 /* Parse the body */
2002 parseVariantBody(variantBody, variantDeclaration);
2003
2004 /* If variant has name, add it to the current scope. */
2005 if (hasName) {
2006 getCurrentScope().registerVariant(variantName,
2007 variantDeclaration);
2008 }
2009 } else /* !hasBody */{
2010 if (hasName) {
2011 /* Name and !body */
2012
2013 /* Lookup the name in the current scope. */
2c053b6e 2014 variantDeclaration = getCurrentScope().lookupVariantRecursive(
866e5b51
FC
2015 variantName);
2016
2017 /*
2018 * If not found, it means that a struct with such name has not
2019 * been defined
2020 */
2021 if (variantDeclaration == null) {
2022 throw new ParseException("variant " + variantName //$NON-NLS-1$
2023 + " is not defined"); //$NON-NLS-1$
2024 }
2025 } else {
2026 /* !Name and !body */
2027
2028 /* We can't do anything with that. */
2029 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2030 }
2031 }
2032
2033 if (hasTag) {
2034 variantDeclaration.setTag(variantTag);
816fde81
MK
2035
2036 IDeclaration decl = getCurrentScope().lookupIdentifierRecursive(variantTag);
2037 if (decl == null) {
2038 throw new ParseException("Variant tag not found: " + variantTag); //$NON-NLS-1$
2039 }
2040 if (!(decl instanceof EnumDeclaration)) {
2041 throw new ParseException("Variant tag must be an enum: " + variantTag); //$NON-NLS-1$
2042 }
2043 EnumDeclaration tagDecl = (EnumDeclaration) decl;
2044 Set<String> intersection = new HashSet<String>(tagDecl.getLabels());
2045 intersection.retainAll(variantDeclaration.getFields().keySet());
2046 if (intersection.isEmpty()) {
2047 throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$
2048 }
866e5b51
FC
2049 }
2050
866e5b51
FC
2051 return variantDeclaration;
2052 }
2053
2054 private void parseVariantBody(CommonTree variantBody,
2055 VariantDeclaration variantDeclaration) throws ParseException {
866e5b51
FC
2056
2057 List<CommonTree> variantDeclarations = variantBody.getChildren();
866e5b51
FC
2058
2059 pushScope();
2060
2061 for (CommonTree declarationNode : variantDeclarations) {
2062 switch (declarationNode.getType()) {
2063 case CTFParser.TYPEALIAS:
2064 parseTypealias(declarationNode);
2065 break;
2066 case CTFParser.TYPEDEF:
2067 parseTypedef(declarationNode);
2068 break;
2069 case CTFParser.SV_DECLARATION:
2070 parseVariantDeclaration(declarationNode, variantDeclaration);
2071 break;
2072 default:
2073 childTypeError(declarationNode);
2074 break;
2075 }
2076 }
2077
2078 popScope();
2079 }
2080
2081 private void parseVariantDeclaration(CommonTree declaration,
2082 VariantDeclaration variant) throws ParseException {
866e5b51 2083
866e5b51 2084 /* Get the type specifier list node */
72dbc4ac 2085 CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
866e5b51
FC
2086
2087 /* Get the type declarator list node */
72dbc4ac 2088 CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
866e5b51
FC
2089
2090 /* Get the type declarator list */
72dbc4ac 2091 List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
866e5b51
FC
2092
2093 /*
2094 * For each type declarator, parse the declaration and add a field to
2095 * the variant
2096 */
2097 for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
866e5b51
FC
2098
2099 StringBuilder identifierSB = new StringBuilder();
2100
2101 IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
2102 typeSpecifierListNode, identifierSB);
2103
2c053b6e
MK
2104 String name = identifierSB.toString();
2105
2106 if (variant.hasField(name)) {
866e5b51 2107 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2c053b6e 2108 + name);
866e5b51
FC
2109 }
2110
2c053b6e
MK
2111 getCurrentScope().registerIdentifier(name, decl);
2112
2113 variant.addField(name, decl);
866e5b51
FC
2114 }
2115 }
2116
2117 /**
2118 * Creates the string representation of a type declaration (type specifier
2119 * list + pointers).
2120 *
2121 * @param typeSpecifierList
2122 * A TYPE_SPECIFIER_LIST node.
2123 * @param pointers
2124 * A list of POINTER nodes.
2125 * @return The string representation.
2126 * @throws ParseException
2127 */
2128 private static String createTypeDeclarationString(
2129 CommonTree typeSpecifierList, List<CommonTree> pointers)
2130 throws ParseException {
2131 StringBuilder sb = new StringBuilder();
2132
2133 createTypeSpecifierListString(typeSpecifierList, sb);
2134 createPointerListString(pointers, sb);
2135
2136 return sb.toString();
2137 }
2138
2139 /**
2140 * Creates the string representation of a list of type specifiers.
2141 *
2142 * @param typeSpecifierList
2143 * A TYPE_SPECIFIER_LIST node.
2144 * @param sb
2145 * A StringBuilder to which will be appended the string.
2146 * @throws ParseException
2147 */
2148 private static void createTypeSpecifierListString(
2149 CommonTree typeSpecifierList, StringBuilder sb)
2150 throws ParseException {
866e5b51
FC
2151
2152 List<CommonTree> children = typeSpecifierList.getChildren();
866e5b51
FC
2153
2154 boolean firstItem = true;
2155
2156 for (CommonTree child : children) {
2157 if (!firstItem) {
2158 sb.append(' ');
2159
2160 }
2161
2162 firstItem = false;
2163
2164 /* Append the string that represents this type specifier. */
2165 createTypeSpecifierString(child, sb);
2166 }
2167 }
2168
2169 /**
2170 * Creates the string representation of a type specifier.
2171 *
2172 * @param typeSpecifier
2173 * A TYPE_SPECIFIER node.
2174 * @param sb
2175 * A StringBuilder to which will be appended the string.
2176 * @throws ParseException
2177 */
2178 private static void createTypeSpecifierString(CommonTree typeSpecifier,
2179 StringBuilder sb) throws ParseException {
2180 switch (typeSpecifier.getType()) {
2181 case CTFParser.FLOATTOK:
2182 case CTFParser.INTTOK:
2183 case CTFParser.LONGTOK:
2184 case CTFParser.SHORTTOK:
2185 case CTFParser.SIGNEDTOK:
2186 case CTFParser.UNSIGNEDTOK:
2187 case CTFParser.CHARTOK:
2188 case CTFParser.DOUBLETOK:
2189 case CTFParser.VOIDTOK:
2190 case CTFParser.BOOLTOK:
2191 case CTFParser.COMPLEXTOK:
2192 case CTFParser.IMAGINARYTOK:
2193 case CTFParser.CONSTTOK:
2194 case CTFParser.IDENTIFIER:
2195 sb.append(typeSpecifier.getText());
2196 break;
2197 case CTFParser.STRUCT: {
72dbc4ac 2198 CommonTree structName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.STRUCT_NAME);
866e5b51 2199 if (structName == null) {
2c053b6e 2200 throw new ParseException("nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
866e5b51 2201 }
866e5b51 2202
72dbc4ac 2203 CommonTree structNameIdentifier = (CommonTree) structName.getChild(0);
866e5b51
FC
2204
2205 sb.append(structNameIdentifier.getText());
2206 break;
2207 }
2208 case CTFParser.VARIANT: {
72dbc4ac 2209 CommonTree variantName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.VARIANT_NAME);
866e5b51 2210 if (variantName == null) {
2c053b6e 2211 throw new ParseException("nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
866e5b51 2212 }
866e5b51 2213
72dbc4ac 2214 CommonTree variantNameIdentifier = (CommonTree) variantName.getChild(0);
866e5b51
FC
2215
2216 sb.append(variantNameIdentifier.getText());
2217 break;
2218 }
2219 case CTFParser.ENUM: {
72dbc4ac 2220 CommonTree enumName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.ENUM_NAME);
866e5b51 2221 if (enumName == null) {
2c053b6e 2222 throw new ParseException("nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
866e5b51 2223 }
866e5b51
FC
2224
2225 CommonTree enumNameIdentifier = (CommonTree) enumName.getChild(0);
866e5b51
FC
2226
2227 sb.append(enumNameIdentifier.getText());
2228 break;
2229 }
2230 case CTFParser.FLOATING_POINT:
2231 case CTFParser.INTEGER:
2232 case CTFParser.STRING:
2c053b6e 2233 throw new ParseException("CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
866e5b51
FC
2234 default:
2235 childTypeError(typeSpecifier);
2236 break;
2237 }
2238 }
2239
2240 /**
2241 * Creates the string representation of a list of pointers.
2242 *
2243 * @param pointerList
2244 * A list of pointer nodes. If pointerList is null, this function
2245 * does nothing.
2246 * @param sb
2247 * A stringbuilder to which will be appended the string.
2248 */
2249 private static void createPointerListString(List<CommonTree> pointerList,
2250 StringBuilder sb) {
2251 if (pointerList == null) {
2252 return;
2253 }
2254
2255 for (CommonTree pointer : pointerList) {
866e5b51
FC
2256
2257 sb.append(" *"); //$NON-NLS-1$
2258 if (pointer.getChildCount() > 0) {
866e5b51
FC
2259
2260 sb.append(" const"); //$NON-NLS-1$
2261 }
2262 }
2263 }
2264
866e5b51
FC
2265 /**
2266 * @param node
2267 * The node to check.
2268 * @return True if the given node is an unary string.
2269 */
2270 private static boolean isUnaryString(CommonTree node) {
4311ac8b
MAL
2271 return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING));
2272 }
2273
2274 /**
2275 * @param node
2276 * The node to check.
2c053b6e
MK
2277 * @return True if the given node is any type of unary string (no quotes,
2278 * quotes, etc).
4311ac8b
MAL
2279 */
2280 private static boolean isAnyUnaryString(CommonTree node) {
2c053b6e 2281 return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING) || (node.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES));
866e5b51
FC
2282 }
2283
2284 /**
2285 * @param node
2286 * The node to check.
2287 * @return True if the given node is an unary integer.
2288 */
2289 private static boolean isUnaryInteger(CommonTree node) {
72dbc4ac 2290 return ((node.getType() == CTFParser.UNARY_EXPRESSION_DEC) ||
2c053b6e 2291 (node.getType() == CTFParser.UNARY_EXPRESSION_HEX) || (node.getType() == CTFParser.UNARY_EXPRESSION_OCT));
866e5b51
FC
2292 }
2293
2294 /**
2295 * Parses a unary string node and return the string value.
2296 *
2297 * @param unaryString
2298 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2299 * or UNARY_EXPRESSION_STRING_QUOTES).
2300 * @return The string value.
2301 */
2302 /*
2303 * It would be really nice to remove the quotes earlier, such as in the
2304 * parser.
2305 */
2306 private static String parseUnaryString(CommonTree unaryString) {
866e5b51 2307
866e5b51 2308 CommonTree value = (CommonTree) unaryString.getChild(0);
866e5b51
FC
2309 String strval = value.getText();
2310
2311 /* Remove quotes */
2312 if (unaryString.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES) {
2313 strval = strval.substring(1, strval.length() - 1);
2314 }
2315
2316 return strval;
2317 }
2318
2319 /**
2320 * Parses an unary integer (dec, hex or oct).
2321 *
2322 * @param unaryInteger
2323 * An unary integer node.
2324 * @return The integer value.
816fde81 2325 * @throws ParseException on an invalid integer format ("bob" for example)
866e5b51 2326 */
a94410d9 2327 private static long parseUnaryInteger(CommonTree unaryInteger) throws ParseException {
866e5b51
FC
2328
2329 List<CommonTree> children = unaryInteger.getChildren();
2330 CommonTree value = children.get(0);
2331 String strval = value.getText();
2332
2333 long intval;
a94410d9 2334 try {
ab98db9a 2335 intval = Long.decode(strval);
a94410d9 2336 } catch (NumberFormatException e) {
4311ac8b 2337 throw new ParseException("Invalid integer format: " + strval); //$NON-NLS-1$
866e5b51 2338 }
4311ac8b 2339
866e5b51
FC
2340 /* The rest of children are sign */
2341 if ((children.size() % 2) == 0) {
2342 return -intval;
2343 }
2344 return intval;
2345 }
2346
2347 private static long getMajorOrMinor(CommonTree rightNode)
2348 throws ParseException {
866e5b51
FC
2349
2350 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2351
2352 if (isUnaryInteger(firstChild)) {
2353 if (rightNode.getChildCount() > 1) {
2354 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2355 }
2356
2357 long m = parseUnaryInteger(firstChild);
2358
2359 if (m < 0) {
2360 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2361 }
2362
2363 return m;
2364 }
2365 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2366 }
2367
2368 private static UUID getUUID(CommonTree rightNode) throws ParseException {
866e5b51
FC
2369
2370 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2371
4311ac8b 2372 if (isAnyUnaryString(firstChild)) {
866e5b51
FC
2373 if (rightNode.getChildCount() > 1) {
2374 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2375 }
2376
2377 String uuidstr = parseUnaryString(firstChild);
2378
2379 try {
0594c61c 2380 return UUID.fromString(uuidstr);
866e5b51
FC
2381 } catch (IllegalArgumentException e) {
2382 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2383 }
2384 }
2385 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2386 }
2387
2388 /**
2389 * Gets the value of a "signed" integer attribute.
2390 *
2391 * @param rightNode
2392 * A CTF_RIGHT node.
2393 * @return The "signed" value as a boolean.
2394 * @throws ParseException
2395 */
2396 private static boolean getSigned(CommonTree rightNode)
2397 throws ParseException {
866e5b51
FC
2398
2399 boolean ret = false;
2400 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2401
2402 if (isUnaryString(firstChild)) {
2403 String strval = concatenateUnaryStrings(rightNode.getChildren());
2404
fafc36a7
AM
2405 if (strval.equals(MetadataStrings.TRUE)
2406 || strval.equals(MetadataStrings.TRUE2)) {
866e5b51 2407 ret = true;
fafc36a7
AM
2408 } else if (strval.equals(MetadataStrings.FALSE)
2409 || strval.equals(MetadataStrings.FALSE2)) {
866e5b51
FC
2410 ret = false;
2411 } else {
2412 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2413 + firstChild.getChild(0).getText());
2414 }
2415 } else if (isUnaryInteger(firstChild)) {
2416 /* Happens if the value is something like "1234.hello" */
2417 if (rightNode.getChildCount() > 1) {
2418 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2419 }
2420
2421 long intval = parseUnaryInteger(firstChild);
2422
2423 if (intval == 1) {
2424 ret = true;
2425 } else if (intval == 0) {
2426 ret = false;
2427 } else {
2428 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2429 + firstChild.getChild(0).getText());
2430 }
2431 } else {
2432 throw new ParseException();
2433 }
2434
2435 return ret;
2436 }
2437
2438 /**
2439 * Gets the value of a "byte_order" integer attribute.
2440 *
2441 * @param rightNode
2442 * A CTF_RIGHT node.
2443 * @return The "byte_order" value.
2444 * @throws ParseException
2445 */
2446 private ByteOrder getByteOrder(CommonTree rightNode) throws ParseException {
866e5b51
FC
2447
2448 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2449
2450 if (isUnaryString(firstChild)) {
2451 String strval = concatenateUnaryStrings(rightNode.getChildren());
2452
fafc36a7 2453 if (strval.equals(MetadataStrings.LE)) {
866e5b51 2454 return ByteOrder.LITTLE_ENDIAN;
fafc36a7
AM
2455 } else if (strval.equals(MetadataStrings.BE)
2456 || strval.equals(MetadataStrings.NETWORK)) {
866e5b51 2457 return ByteOrder.BIG_ENDIAN;
fafc36a7 2458 } else if (strval.equals(MetadataStrings.NATIVE)) {
866e5b51
FC
2459 return trace.getByteOrder();
2460 } else {
2461 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2462 }
2463 }
2464 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2465 }
2466
2467 /**
2468 * Determines if the given value is a valid alignment value.
2469 *
2470 * @param alignment
2471 * The value to check.
2472 * @return True if it is valid.
2473 */
2474 private static boolean isValidAlignment(long alignment) {
2475 return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
2476 }
2477
2478 /**
2479 * Gets the value of a "size" integer attribute.
2480 *
2481 * @param rightNode
2482 * A CTF_RIGHT node.
2483 * @return The "size" value.
2484 * @throws ParseException
2485 */
2486 private static long getSize(CommonTree rightNode) throws ParseException {
866e5b51
FC
2487
2488 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2489
2490 if (isUnaryInteger(firstChild)) {
2491 if (rightNode.getChildCount() > 1) {
2492 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2493 }
2494
2495 long size = parseUnaryInteger(firstChild);
2496
2497 if (size < 1) {
2498 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2499 }
2500
2501 return size;
2502 }
2503 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2504 }
2505
2506 /**
2507 * Gets the value of a "align" integer or struct attribute.
2508 *
2509 * @param node
2510 * A CTF_RIGHT node or directly an unary integer.
2511 * @return The align value.
2512 * @throws ParseException
2513 */
2514 private static long getAlignment(CommonTree node) throws ParseException {
866e5b51
FC
2515
2516 /*
2517 * If a CTF_RIGHT node was passed, call getAlignment with the first
2518 * child
2519 */
2520 if (node.getType() == CTFParser.CTF_RIGHT) {
2521 if (node.getChildCount() > 1) {
2522 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2523 }
2524
2525 return getAlignment((CommonTree) node.getChild(0));
2526 } else if (isUnaryInteger(node)) {
2527 long alignment = parseUnaryInteger(node);
2528
2529 if (!isValidAlignment(alignment)) {
2530 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2531 + alignment);
2532 }
2533
2534 return alignment;
2535 }
2536 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2537 }
2538
2539 /**
2540 * Gets the value of a "base" integer attribute.
2541 *
2542 * @param rightNode
2543 * An CTF_RIGHT node.
2544 * @return The "base" value.
2545 * @throws ParseException
2546 */
2547 private static int getBase(CommonTree rightNode) throws ParseException {
866e5b51
FC
2548
2549 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2550
2551 if (isUnaryInteger(firstChild)) {
2552 if (rightNode.getChildCount() > 1) {
2553 throw new ParseException("invalid base value"); //$NON-NLS-1$
2554 }
2555
2556 long intval = parseUnaryInteger(firstChild);
2557 if ((intval == 2) || (intval == 8) || (intval == 10)
2558 || (intval == 16)) {
2559 return (int) intval;
2560 }
2561 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2562 } else if (isUnaryString(firstChild)) {
2563 String strval = concatenateUnaryStrings(rightNode.getChildren());
2564
fafc36a7
AM
2565 if (strval.equals(MetadataStrings.DECIMAL)
2566 || strval.equals(MetadataStrings.DEC)
2567 || strval.equals(MetadataStrings.DEC_CTE)
2568 || strval.equals(MetadataStrings.INT_MOD)
2569 || strval.equals(MetadataStrings.UNSIGNED_CTE)) {
866e5b51 2570 return 10;
fafc36a7
AM
2571 } else if (strval.equals(MetadataStrings.HEXADECIMAL)
2572 || strval.equals(MetadataStrings.HEX)
2573 || strval.equals(MetadataStrings.X)
2574 || strval.equals(MetadataStrings.X2)
2575 || strval.equals(MetadataStrings.POINTER)) {
866e5b51 2576 return 16;
fafc36a7
AM
2577 } else if (strval.equals(MetadataStrings.OCTAL)
2578 || strval.equals(MetadataStrings.OCT)
2579 || strval.equals(MetadataStrings.OCTAL_CTE)) {
866e5b51 2580 return 8;
fafc36a7
AM
2581 } else if (strval.equals(MetadataStrings.BINARY)
2582 || strval.equals(MetadataStrings.BIN)) {
866e5b51
FC
2583 return 2;
2584 } else {
2585 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2586 }
2587 } else {
2588 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2589 }
2590 }
2591
2592 /**
2593 * Gets the value of an "encoding" integer attribute.
2594 *
2595 * @param rightNode
2596 * A CTF_RIGHT node.
2597 * @return The "encoding" value.
2598 * @throws ParseException
2599 */
2600 private static Encoding getEncoding(CommonTree rightNode)
2601 throws ParseException {
866e5b51
FC
2602
2603 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2604
2605 if (isUnaryString(firstChild)) {
2606 String strval = concatenateUnaryStrings(rightNode.getChildren());
2607
fafc36a7 2608 if (strval.equals(MetadataStrings.UTF8)) {
866e5b51 2609 return Encoding.UTF8;
fafc36a7 2610 } else if (strval.equals(MetadataStrings.ASCII)) {
866e5b51 2611 return Encoding.ASCII;
fafc36a7 2612 } else if (strval.equals(MetadataStrings.NONE)) {
866e5b51
FC
2613 return Encoding.NONE;
2614 } else {
2615 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2616 }
2617 }
2618 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2619 }
2620
2621 private static long getStreamID(CommonTree rightNode) throws ParseException {
866e5b51
FC
2622
2623 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2624
2625 if (isUnaryInteger(firstChild)) {
2626 if (rightNode.getChildCount() > 1) {
2627 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2628 }
2629
2630 long intval = parseUnaryInteger(firstChild);
2631
2632 return intval;
2633 }
2634 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2635 }
2636
2637 private static String getEventName(CommonTree rightNode)
2638 throws ParseException {
866e5b51
FC
2639
2640 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2641
4311ac8b 2642 if (isAnyUnaryString(firstChild)) {
866e5b51
FC
2643 String str = concatenateUnaryStrings(rightNode.getChildren());
2644
2645 return str;
2646 }
2647 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2648 }
2649
2650 private static long getEventID(CommonTree rightNode) throws ParseException {
866e5b51
FC
2651
2652 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2653
2654 if (isUnaryInteger(firstChild)) {
2655 if (rightNode.getChildCount() > 1) {
2656 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2657 }
2658
2659 long intval = parseUnaryInteger(firstChild);
2660
2661 return intval;
2662 }
2663 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2664 }
2665
2666 /**
2667 * Concatenates a list of unary strings separated by arrows (->) or dots.
2668 *
2669 * @param strings
2670 * A list, first element being an unary string, subsequent
2671 * elements being ARROW or DOT nodes with unary strings as child.
2672 * @return The string representation of the unary string chain.
2673 */
2674 private static String concatenateUnaryStrings(List<CommonTree> strings) {
866e5b51
FC
2675
2676 StringBuilder sb = new StringBuilder();
2677
2678 CommonTree first = strings.get(0);
2679 sb.append(parseUnaryString(first));
2680
2681 boolean isFirst = true;
2682
2683 for (CommonTree ref : strings) {
2684 if (isFirst) {
2685 isFirst = false;
2686 continue;
2687 }
2688
866e5b51
FC
2689 CommonTree id = (CommonTree) ref.getChild(0);
2690
2691 if (ref.getType() == CTFParser.ARROW) {
2692 sb.append("->"); //$NON-NLS-1$
2693 } else { /* DOT */
2694 sb.append('.');
2695 }
2696
2697 sb.append(parseUnaryString(id));
2698 }
2699
2700 return sb.toString();
2701 }
2702
2703 /**
2704 * Throws a ParseException stating that the parent-child relation between
2705 * the given node and its parent is not valid. It means that the shape of
2706 * the AST is unexpected.
2707 *
2708 * @param child
2709 * The invalid child node.
2710 * @throws ParseException
2711 */
2712 private static void childTypeError(CommonTree child) throws ParseException {
2713 CommonTree parent = (CommonTree) child.getParent();
2714 String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
2715 + " can't have a child of type " //$NON-NLS-1$
2716 + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
2717
2718 throw new ParseException(error);
2719 }
2720
2721 // ------------------------------------------------------------------------
2722 // Scope management
2723 // ------------------------------------------------------------------------
2724
2725 /**
2726 * Adds a new declaration scope on the top of the scope stack.
2727 */
2728 private void pushScope() {
2729 scope = new DeclarationScope(scope);
2730 }
2731
2732 /**
2733 * Removes the top declaration scope from the scope stack.
2734 */
2735 private void popScope() {
866e5b51
FC
2736 scope = scope.getParentScope();
2737 }
2738
2739 /**
2740 * Returns the current declaration scope.
2741 *
2742 * @return The current declaration scope.
2743 */
2744 private DeclarationScope getCurrentScope() {
866e5b51
FC
2745 return scope;
2746 }
2747
2748}
This page took 0.163246 seconds and 5 git commands to generate.