1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
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
10 * Matthew Khouzam - Initial Design and Grammar
11 * Francis Giraldeau - Initial API and implementation
12 * Simon Marchi - Initial API and implementation
13 *******************************************************************************/
15 package org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
;
17 import java
.io
.FileNotFoundException
;
18 import java
.io
.IOException
;
19 import java
.io
.UnsupportedEncodingException
;
20 import java
.math
.BigInteger
;
21 import java
.nio
.ByteOrder
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Collections
;
24 import java
.util
.HashSet
;
25 import java
.util
.LinkedList
;
26 import java
.util
.List
;
28 import java
.util
.UUID
;
30 import org
.antlr
.runtime
.tree
.CommonTree
;
31 import org
.eclipse
.core
.runtime
.IStatus
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.CTFClock
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDeclaration
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Encoding
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDeclaration
;
36 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.FloatDeclaration
;
37 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDeclaration
;
38 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
39 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
40 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDeclaration
;
41 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
42 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
43 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
44 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.Stream
;
45 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
46 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.Activator
;
47 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.EventDeclaration
;
48 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
53 public class IOStructGen
{
55 // ------------------------------------------------------------------------
57 // ------------------------------------------------------------------------
59 private static final boolean DEBUG
= false;
64 private final CTFTrace fTrace
;
65 private CommonTree fTree
;
68 * The current declaration scope.
70 private DeclarationScope fScope
= null;
73 * Data helpers needed for streaming
76 private boolean fHasBeenParsed
= false;
78 // ------------------------------------------------------------------------
80 // ------------------------------------------------------------------------
86 * the tree (ANTLR generated) with the parsed TSDL data.
88 * the trace containing the places to put all the read metadata
90 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
97 * Parse the tree and populate the trace defined in the constructor.
99 * @throws ParseException
100 * If there was a problem parsing the metadata
102 public void generate() throws ParseException
{
107 * Parse a partial tree and populate the trace defined in the constructor.
108 * Does not check for a "trace" block as there is only one in the trace and
111 * @throws ParseException
112 * If there was a problem parsing the metadata
114 public void generateFragment() throws ParseException
{
115 parseIncompleteRoot(fTree
);
118 // ------------------------------------------------------------------------
120 // ------------------------------------------------------------------------
123 * Sets a new tree to parse
126 * the new tree to parse
128 public void setTree(CommonTree newTree
) {
133 * Parse the root node.
137 * @throws ParseException
139 private void parseRoot(CommonTree root
) throws ParseException
{
141 List
<CommonTree
> children
= root
.getChildren();
142 java
.io
.FileOutputStream fos
= null;
143 java
.io
.OutputStreamWriter out
= null;
146 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
147 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
148 } catch (FileNotFoundException e
) {
151 } catch (UnsupportedEncodingException e
) {
157 CommonTree traceNode
= null;
158 List
<CommonTree
> streams
= new ArrayList
<>();
159 List
<CommonTree
> events
= new ArrayList
<>();
160 List
<CommonTree
> declarations
= new ArrayList
<>();
161 List
<CommonTree
> environments
= new ArrayList
<>();
162 List
<CommonTree
> clocks
= new ArrayList
<>();
163 List
<CommonTree
> callsites
= new ArrayList
<>();
165 /* Create a new declaration scope with no parent. */
169 for (CommonTree child
: children
) {
170 final int type
= child
.getType();
172 out
.write(child
.toString()
173 + " -> " + type
+ '\n'); //$NON-NLS-1$
176 case CTFParser
.DECLARATION
:
177 declarations
.add(child
);
179 case CTFParser
.TRACE
:
180 if (traceNode
!= null) {
181 throw new ParseException("Only one trace block is allowed"); //$NON-NLS-1$
185 case CTFParser
.STREAM
:
188 case CTFParser
.EVENT
:
191 case CTFParser
.CLOCK
:
195 environments
.add(child
);
197 case CTFParser
.CALLSITE
:
198 callsites
.add(child
);
201 childTypeError(child
);
205 out
.write("Declarations\n"); //$NON-NLS-1$
207 for (CommonTree decl
: declarations
) {
209 out
.write(decl
.toString() + '\n');
211 parseRootDeclaration(decl
);
213 if (traceNode
== null) {
214 throw new ParseException("Missing trace block"); //$NON-NLS-1$
217 parseTrace(traceNode
);
220 out
.write("Environments\n"); //$NON-NLS-1$
222 for (CommonTree environment
: environments
) {
223 parseEnvironment(environment
);
226 out
.write("Clocks\n"); //$NON-NLS-1$
228 for (CommonTree clock
: clocks
) {
232 out
.write("Callsites\n"); //$NON-NLS-1$
234 for (CommonTree callsite
: callsites
) {
235 parseCallsite(callsite
);
239 out
.write("Streams\n"); //$NON-NLS-1$
241 if (streams
.size() > 0) {
242 for (CommonTree stream
: streams
) {
245 out
.write(stream
.toString() + '\n');
246 } catch (IOException e
) {
253 /* Add an empty stream that will have a null id */
254 fTrace
.addStream(new Stream(fTrace
));
258 out
.write("Events\n"); //$NON-NLS-1$
260 for (CommonTree event
: events
) {
263 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
264 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
265 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
273 } catch (IOException e
) {
277 fHasBeenParsed
= true;
280 private void parseIncompleteRoot(CommonTree root
) throws ParseException
{
281 List
<CommonTree
> children
= root
.getChildren();
283 if (fHasBeenParsed
== false) {
284 throw new ParseException("You need to run generate first"); //$NON-NLS-1$
286 List
<CommonTree
> streams
= new ArrayList
<>();
287 List
<CommonTree
> events
= new ArrayList
<>();
288 List
<CommonTree
> declarations
= new ArrayList
<>();
289 List
<CommonTree
> environments
= new ArrayList
<>();
290 List
<CommonTree
> clocks
= new ArrayList
<>();
291 List
<CommonTree
> callsites
= new ArrayList
<>();
292 /* Create a new declaration scope with no parent. */
295 for (CommonTree child
: children
) {
296 final int type
= child
.getType();
298 case CTFParser
.DECLARATION
:
299 declarations
.add(child
);
301 case CTFParser
.TRACE
:
302 throw new ParseException("Trace block defined here, please use generate and not generateFragment to parse this fragment"); //$NON-NLS-1$
303 case CTFParser
.STREAM
:
306 case CTFParser
.EVENT
:
309 case CTFParser
.CLOCK
:
313 environments
.add(child
);
315 case CTFParser
.CALLSITE
:
316 callsites
.add(child
);
319 childTypeError(child
);
322 for (CommonTree decl
: declarations
) {
323 parseRootDeclaration(decl
);
326 for (CommonTree environment
: environments
) {
327 parseEnvironment(environment
);
329 for (CommonTree clock
: clocks
) {
332 for (CommonTree callsite
: callsites
) {
333 parseCallsite(callsite
);
336 for (CommonTree stream
: streams
) {
340 for (CommonTree event
: events
) {
346 private void parseCallsite(CommonTree callsite
) {
348 List
<CommonTree
> children
= callsite
.getChildren();
350 String funcName
= null;
351 long lineNumber
= -1;
353 String fileName
= null;
355 for (CommonTree child
: children
) {
357 /* this is a regex to find the leading and trailing quotes */
358 final String regex
= "^\"|\"$"; //$NON-NLS-1$
360 * this is to replace the previous quotes with nothing...
361 * effectively deleting them
363 final String nullString
= ""; //$NON-NLS-1$
364 left
= child
.getChild(0).getChild(0).getChild(0).getText();
365 if (left
.equals("name")) { //$NON-NLS-1$
366 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
367 } else if (left
.equals("func")) { //$NON-NLS-1$
368 funcName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
369 } else if (left
.equals("ip")) { //$NON-NLS-1$
370 ip
= Long
.decode(child
.getChild(1).getChild(0).getChild(0).getText());
371 } else if (left
.equals("file")) { //$NON-NLS-1$
372 fileName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
373 } else if (left
.equals("line")) { //$NON-NLS-1$
374 lineNumber
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
377 fTrace
.addCallsite(name
, funcName
, ip
, fileName
, lineNumber
);
380 private void parseEnvironment(CommonTree environment
) {
381 List
<CommonTree
> children
= environment
.getChildren();
382 for (CommonTree child
: children
) {
385 left
= child
.getChild(0).getChild(0).getChild(0).getText();
386 right
= child
.getChild(1).getChild(0).getChild(0).getText();
387 fTrace
.addEnvironmentVar(left
, right
);
391 private void parseClock(CommonTree clock
) {
392 List
<CommonTree
> children
= clock
.getChildren();
393 CTFClock ctfClock
= new CTFClock();
394 for (CommonTree child
: children
) {
395 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
396 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
397 final int type
= value
.getType();
399 case CTFParser
.INTEGER
:
400 case CTFParser
.DECIMAL_LITERAL
:
402 * Not a pretty hack, this is to make sure that there is no
403 * number overflow due to 63 bit integers. The offset should
404 * only really be an issue in the year 2262. the tracer in C/ASM
405 * can write an offset in an unsigned 64 bit long. In java, the
406 * last bit, being set to 1 will be read as a negative number,
407 * but since it is too big a positive it will throw an
408 * exception. this will happen in 2^63 ns from 1970. Therefore
409 * 293 years from 1970
413 numValue
= Long
.parseLong(value
.getText());
414 } catch (Exception e
) {
415 numValue
= 1330938566783103277L;
417 ctfClock
.addAttribute(key
, numValue
);
420 ctfClock
.addAttribute(key
, value
.getText());
424 String nameValue
= ctfClock
.getName();
425 fTrace
.addClock(nameValue
, ctfClock
);
428 private void parseTrace(CommonTree traceNode
) throws ParseException
{
430 List
<CommonTree
> children
= traceNode
.getChildren();
431 if (children
== null) {
432 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
437 for (CommonTree child
: children
) {
438 switch (child
.getType()) {
439 case CTFParser
.TYPEALIAS
:
440 parseTypealias(child
);
442 case CTFParser
.TYPEDEF
:
445 case CTFParser
.CTF_EXPRESSION_TYPE
:
446 case CTFParser
.CTF_EXPRESSION_VAL
:
447 parseTraceDeclaration(child
);
450 childTypeError(child
);
456 * If trace byte order was not specified and not using packet based
459 if (fTrace
.getByteOrder() == null) {
460 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
466 private void parseTraceDeclaration(CommonTree traceDecl
)
467 throws ParseException
{
469 /* There should be a left and right */
471 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
472 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
474 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
476 if (!isAnyUnaryString(leftStrings
.get(0))) {
477 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
480 String left
= concatenateUnaryStrings(leftStrings
);
482 if (left
.equals(MetadataStrings
.MAJOR
)) {
483 if (fTrace
.majorIsSet()) {
484 throw new ParseException("major is already set"); //$NON-NLS-1$
487 fTrace
.setMajor(getMajorOrMinor(rightNode
));
488 } else if (left
.equals(MetadataStrings
.MINOR
)) {
489 if (fTrace
.minorIsSet()) {
490 throw new ParseException("minor is already set"); //$NON-NLS-1$
493 fTrace
.setMinor(getMajorOrMinor(rightNode
));
494 } else if (left
.equals(MetadataStrings
.UUID_STRING
)) {
495 UUID uuid
= getUUID(rightNode
);
498 * If uuid was already set by a metadata packet, compare it to see
501 if (fTrace
.uuidIsSet()) {
502 if (fTrace
.getUUID().compareTo(uuid
) != 0) {
503 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
504 + fTrace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
507 fTrace
.setUUID(uuid
);
510 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
511 ByteOrder byteOrder
= getByteOrder(rightNode
);
514 * If byte order was already set by a metadata packet, compare it to
517 if (fTrace
.getByteOrder() != null) {
518 if (fTrace
.getByteOrder() != byteOrder
) {
519 throw new ParseException(
520 "Endianness mismatch. Magic number says " //$NON-NLS-1$
521 + fTrace
.getByteOrder()
522 + " but metadata says " + byteOrder
); //$NON-NLS-1$
525 fTrace
.setByteOrder(byteOrder
);
526 final DeclarationScope parentScope
= fScope
.getParentScope();
528 for (String type
: parentScope
.getTypeNames()) {
529 IDeclaration d
= parentScope
.lookupType(type
);
530 if (d
instanceof IntegerDeclaration
) {
531 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
532 } else if (d
instanceof StructDeclaration
) {
533 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
537 } else if (left
.equals(MetadataStrings
.PACKET_HEADER
)) {
538 if (fTrace
.packetHeaderIsSet()) {
539 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
542 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
544 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
545 throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
548 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
549 typeSpecifier
, null);
551 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
552 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
555 fTrace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
557 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownTraceAttributeWarning
+ " " + left
); //$NON-NLS-1$
561 private static void addByteOrder(ByteOrder byteOrder
,
562 final DeclarationScope parentScope
, String name
,
563 IntegerDeclaration decl
) throws ParseException
{
565 if (decl
.getByteOrder() == null) {
566 IntegerDeclaration newI
;
567 newI
= new IntegerDeclaration(decl
.getLength(), decl
.isSigned(),
568 decl
.getBase(), byteOrder
, decl
.getEncoding(),
569 decl
.getClock(), decl
.getAlignment());
570 parentScope
.replaceType(name
, newI
);
574 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
575 ByteOrder byteOrder
) throws ParseException
{
577 for (String s
: sd
.getFieldsList()) {
578 IDeclaration d
= sd
.getFields().get(s
);
580 if (d
instanceof StructDeclaration
) {
581 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
583 } else if (d
instanceof VariantDeclaration
) {
584 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
586 } else if (d
instanceof IntegerDeclaration
) {
587 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
588 if (decl
.getByteOrder() == null) {
589 IntegerDeclaration newI
;
590 newI
= new IntegerDeclaration(decl
.getLength(),
591 decl
.isSigned(), decl
.getBase(), byteOrder
,
592 decl
.getEncoding(), decl
.getClock(),
593 decl
.getAlignment());
594 sd
.getFields().put(s
, newI
);
600 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
601 ByteOrder byteOrder
) throws ParseException
{
603 for (String s
: vd
.getFields().keySet()) {
604 IDeclaration d
= vd
.getFields().get(s
);
606 if (d
instanceof StructDeclaration
) {
607 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
609 } else if (d
instanceof IntegerDeclaration
) {
610 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
611 IntegerDeclaration newI
;
612 newI
= new IntegerDeclaration(decl
.getLength(),
613 decl
.isSigned(), decl
.getBase(), byteOrder
,
614 decl
.getEncoding(), decl
.getClock(),
615 decl
.getAlignment());
616 vd
.getFields().put(s
, newI
);
621 private void parseStream(CommonTree streamNode
) throws ParseException
{
623 Stream stream
= new Stream(fTrace
);
625 List
<CommonTree
> children
= streamNode
.getChildren();
626 if (children
== null) {
627 throw new ParseException("Empty stream block"); //$NON-NLS-1$
632 for (CommonTree child
: children
) {
633 switch (child
.getType()) {
634 case CTFParser
.TYPEALIAS
:
635 parseTypealias(child
);
637 case CTFParser
.TYPEDEF
:
640 case CTFParser
.CTF_EXPRESSION_TYPE
:
641 case CTFParser
.CTF_EXPRESSION_VAL
:
642 parseStreamDeclaration(child
, stream
);
645 childTypeError(child
);
650 if (stream
.isIdSet()) {
651 if (!fTrace
.packetHeaderIsSet()
652 || !fTrace
.getPacketHeader().hasField(MetadataStrings
.STREAM_ID
)) {
653 throw new ParseException("Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
657 fTrace
.addStream(stream
);
662 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
663 throws ParseException
{
665 /* There should be a left and right */
667 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
668 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
670 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
672 if (!isAnyUnaryString(leftStrings
.get(0))) {
673 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
676 String left
= concatenateUnaryStrings(leftStrings
);
678 if (left
.equals(MetadataStrings
.ID
)) {
679 if (stream
.isIdSet()) {
680 throw new ParseException("stream id already defined"); //$NON-NLS-1$
683 long streamID
= getStreamID(rightNode
);
685 stream
.setId(streamID
);
686 } else if (left
.equals(MetadataStrings
.EVENT_HEADER
)) {
687 if (stream
.isEventHeaderSet()) {
688 throw new ParseException("event.header already defined"); //$NON-NLS-1$
691 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
693 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
694 throw new ParseException("event.header expects a type specifier"); //$NON-NLS-1$
697 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
698 typeSpecifier
, null);
700 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
701 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
704 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
705 } else if (left
.equals(MetadataStrings
.EVENT_CONTEXT
)) {
706 if (stream
.isEventContextSet()) {
707 throw new ParseException("event.context already defined"); //$NON-NLS-1$
710 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
712 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
713 throw new ParseException("event.context expects a type specifier"); //$NON-NLS-1$
716 IDeclaration eventContextDecl
= parseTypeSpecifierList(
717 typeSpecifier
, null);
719 if (!(eventContextDecl
instanceof StructDeclaration
)) {
720 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
723 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
724 } else if (left
.equals(MetadataStrings
.PACKET_CONTEXT
)) {
725 if (stream
.isPacketContextSet()) {
726 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
729 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
731 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
732 throw new ParseException("packet.context expects a type specifier"); //$NON-NLS-1$
735 IDeclaration packetContextDecl
= parseTypeSpecifierList(
736 typeSpecifier
, null);
738 if (!(packetContextDecl
instanceof StructDeclaration
)) {
739 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
742 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
744 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownStreamAttributeWarning
+ " " + left
); //$NON-NLS-1$
748 private void parseEvent(CommonTree eventNode
) throws ParseException
{
750 List
<CommonTree
> children
= eventNode
.getChildren();
751 if (children
== null) {
752 throw new ParseException("Empty event block"); //$NON-NLS-1$
755 EventDeclaration event
= new EventDeclaration();
759 for (CommonTree child
: children
) {
760 switch (child
.getType()) {
761 case CTFParser
.TYPEALIAS
:
762 parseTypealias(child
);
764 case CTFParser
.TYPEDEF
:
767 case CTFParser
.CTF_EXPRESSION_TYPE
:
768 case CTFParser
.CTF_EXPRESSION_VAL
:
769 parseEventDeclaration(child
, event
);
772 childTypeError(child
);
777 if (!event
.nameIsSet()) {
778 throw new ParseException("Event name not set"); //$NON-NLS-1$
782 * If the event did not specify a stream, then the trace must be single
785 if (!event
.streamIsSet()) {
786 if (fTrace
.nbStreams() > 1) {
787 throw new ParseException("Event without stream_id with more than one stream"); //$NON-NLS-1$
791 * If the event did not specify a stream, the only existing stream
792 * must not have an id. Note: That behavior could be changed, it
793 * could be possible to just get the only existing stream, whatever
796 Stream stream
= fTrace
.getStream(null);
798 if (stream
!= null) {
799 event
.setStream(stream
);
801 throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
806 * Add the event to the stream.
808 event
.getStream().addEvent(event
);
813 private void parseEventDeclaration(CommonTree eventDecl
,
814 EventDeclaration event
) throws ParseException
{
816 /* There should be a left and right */
818 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
819 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
821 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
823 if (!isAnyUnaryString(leftStrings
.get(0))) {
824 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
827 String left
= concatenateUnaryStrings(leftStrings
);
829 if (left
.equals(MetadataStrings
.NAME2
)) {
830 if (event
.nameIsSet()) {
831 throw new ParseException("name already defined"); //$NON-NLS-1$
834 String name
= getEventName(rightNode
);
837 } else if (left
.equals(MetadataStrings
.ID
)) {
838 if (event
.idIsSet()) {
839 throw new ParseException("id already defined"); //$NON-NLS-1$
842 long id
= getEventID(rightNode
);
845 } else if (left
.equals(MetadataStrings
.STREAM_ID
)) {
846 if (event
.streamIsSet()) {
847 throw new ParseException("stream id already defined"); //$NON-NLS-1$
850 long streamId
= getStreamID(rightNode
);
852 Stream stream
= fTrace
.getStream(streamId
);
854 if (stream
== null) {
855 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
858 event
.setStream(stream
);
859 } else if (left
.equals(MetadataStrings
.CONTEXT
)) {
860 if (event
.contextIsSet()) {
861 throw new ParseException("context already defined"); //$NON-NLS-1$
864 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
866 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
867 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
870 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
873 if (!(contextDecl
instanceof StructDeclaration
)) {
874 throw new ParseException("context expects a struct"); //$NON-NLS-1$
877 event
.setContext((StructDeclaration
) contextDecl
);
878 } else if (left
.equals(MetadataStrings
.FIELDS_STRING
)) {
879 if (event
.fieldsIsSet()) {
880 throw new ParseException("fields already defined"); //$NON-NLS-1$
883 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
885 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
886 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
889 IDeclaration fieldsDecl
;
890 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
892 if (!(fieldsDecl
instanceof StructDeclaration
)) {
893 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
896 * The underscores in the event names. These underscores were added
897 * by the LTTng tracer.
899 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
900 event
.setFields(fields
);
901 } else if (left
.equals(MetadataStrings
.LOGLEVEL2
)) {
902 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
903 event
.setLogLevel(logLevel
);
905 /* Custom event attribute, we'll add it to the attributes map */
906 String right
= parseUnaryString((CommonTree
) rightNode
.getChild(0));
907 event
.setCustomAttribute(left
, right
);
912 * Parses a declaration at the root level.
915 * The declaration subtree.
916 * @throws ParseException
918 private void parseRootDeclaration(CommonTree declaration
)
919 throws ParseException
{
921 List
<CommonTree
> children
= declaration
.getChildren();
923 for (CommonTree child
: children
) {
924 switch (child
.getType()) {
925 case CTFParser
.TYPEDEF
:
928 case CTFParser
.TYPEALIAS
:
929 parseTypealias(child
);
931 case CTFParser
.TYPE_SPECIFIER_LIST
:
932 parseTypeSpecifierList(child
, null);
935 childTypeError(child
);
941 * Parses a typealias node. It parses the target, the alias, and registers
942 * the type in the current scope.
946 * @throws ParseException
948 private void parseTypealias(CommonTree typealias
) throws ParseException
{
950 List
<CommonTree
> children
= typealias
.getChildren();
952 CommonTree target
= null;
953 CommonTree alias
= null;
955 for (CommonTree child
: children
) {
956 switch (child
.getType()) {
957 case CTFParser
.TYPEALIAS_TARGET
:
960 case CTFParser
.TYPEALIAS_ALIAS
:
964 childTypeError(child
);
969 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
971 if ((targetDeclaration
instanceof VariantDeclaration
)
972 && ((VariantDeclaration
) targetDeclaration
).isTagged()) {
973 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
976 String aliasString
= parseTypealiasAlias(alias
);
978 getCurrentScope().registerType(aliasString
, targetDeclaration
);
982 * Parses the target part of a typealias and gets the corresponding
986 * A TYPEALIAS_TARGET node.
987 * @return The corresponding declaration.
988 * @throws ParseException
990 private IDeclaration
parseTypealiasTarget(CommonTree target
)
991 throws ParseException
{
993 List
<CommonTree
> children
= target
.getChildren();
995 CommonTree typeSpecifierList
= null;
996 CommonTree typeDeclaratorList
= null;
997 CommonTree typeDeclarator
= null;
998 StringBuilder identifierSB
= new StringBuilder();
1000 for (CommonTree child
: children
) {
1001 switch (child
.getType()) {
1002 case CTFParser
.TYPE_SPECIFIER_LIST
:
1003 typeSpecifierList
= child
;
1005 case CTFParser
.TYPE_DECLARATOR_LIST
:
1006 typeDeclaratorList
= child
;
1009 childTypeError(child
);
1014 if (typeDeclaratorList
!= null) {
1016 * Only allow one declarator
1018 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
1019 * otherwise the new type puint8_t would maps to two different
1022 if (typeDeclaratorList
.getChildCount() != 1) {
1023 throw new ParseException("Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
1026 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1029 /* Parse the target type and get the declaration */
1030 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
1031 typeSpecifierList
, identifierSB
);
1034 * We don't allow identifier in the target
1036 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
1039 if (identifierSB
.length() > 0) {
1040 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
1041 + ") not expected in the typealias target"); //$NON-NLS-1$
1044 return targetDeclaration
;
1048 * Parses the alias part of a typealias. It parses the underlying specifier
1049 * list and declarator and creates the string representation that will be
1050 * used to register the type.
1053 * A TYPEALIAS_ALIAS node.
1054 * @return The string representation of the alias.
1055 * @throws ParseException
1057 private static String
parseTypealiasAlias(CommonTree alias
)
1058 throws ParseException
{
1060 List
<CommonTree
> children
= alias
.getChildren();
1062 CommonTree typeSpecifierList
= null;
1063 CommonTree typeDeclaratorList
= null;
1064 CommonTree typeDeclarator
= null;
1065 List
<CommonTree
> pointers
= new LinkedList
<>();
1067 for (CommonTree child
: children
) {
1068 switch (child
.getType()) {
1069 case CTFParser
.TYPE_SPECIFIER_LIST
:
1070 typeSpecifierList
= child
;
1072 case CTFParser
.TYPE_DECLARATOR_LIST
:
1073 typeDeclaratorList
= child
;
1076 childTypeError(child
);
1081 /* If there is a type declarator list, extract the pointers */
1082 if (typeDeclaratorList
!= null) {
1084 * Only allow one declarator
1086 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
1088 if (typeDeclaratorList
.getChildCount() != 1) {
1089 throw new ParseException("Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1092 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1094 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
1096 for (CommonTree child
: typeDeclaratorChildren
) {
1097 switch (child
.getType()) {
1098 case CTFParser
.POINTER
:
1099 pointers
.add(child
);
1101 case CTFParser
.IDENTIFIER
:
1102 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1103 + ") not expected in the typealias target"); //$NON-NLS-1$
1105 childTypeError(child
);
1111 return createTypeDeclarationString(typeSpecifierList
, pointers
);
1115 * Parses a typedef node. This creates and registers a new declaration for
1116 * each declarator found in the typedef.
1120 * @throws ParseException
1121 * If there is an error creating the declaration.
1123 private void parseTypedef(CommonTree typedef
) throws ParseException
{
1125 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1127 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1129 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1131 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1132 StringBuilder identifierSB
= new StringBuilder();
1134 IDeclaration typeDeclaration
= parseTypeDeclarator(
1135 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1137 if ((typeDeclaration
instanceof VariantDeclaration
)
1138 && ((VariantDeclaration
) typeDeclaration
).isTagged()) {
1139 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1142 getCurrentScope().registerType(identifierSB
.toString(),
1148 * Parses a pair type declarator / type specifier list and returns the
1149 * corresponding declaration. If it is present, it also writes the
1150 * identifier of the declarator in the given {@link StringBuilder}.
1152 * @param typeDeclarator
1153 * A TYPE_DECLARATOR node.
1154 * @param typeSpecifierList
1155 * A TYPE_SPECIFIER_LIST node.
1156 * @param identifierSB
1157 * A StringBuilder that will receive the identifier found in the
1159 * @return The corresponding declaration.
1160 * @throws ParseException
1161 * If there is an error finding or creating the declaration.
1163 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1164 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1165 throws ParseException
{
1167 IDeclaration declaration
= null;
1168 List
<CommonTree
> children
= null;
1169 List
<CommonTree
> pointers
= new LinkedList
<>();
1170 List
<CommonTree
> lengths
= new LinkedList
<>();
1171 CommonTree identifier
= null;
1173 /* Separate the tokens by type */
1174 if (typeDeclarator
!= null) {
1175 children
= typeDeclarator
.getChildren();
1176 for (CommonTree child
: children
) {
1178 switch (child
.getType()) {
1179 case CTFParser
.POINTER
:
1180 pointers
.add(child
);
1182 case CTFParser
.IDENTIFIER
:
1185 case CTFParser
.LENGTH
:
1189 childTypeError(child
);
1197 * Parse the type specifier list, which is the "base" type. For example,
1198 * it would be int in int a[3][len].
1200 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1203 * Each length subscript means that we must create a nested array or
1204 * sequence. For example, int a[3][len] means that we have an array of 3
1205 * (sequences of length 'len' of (int)).
1207 if (lengths
.size() > 0) {
1208 /* We begin at the end */
1209 Collections
.reverse(lengths
);
1211 for (CommonTree length
: lengths
) {
1213 * By looking at the first expression, we can determine whether
1214 * it is an array or a sequence.
1216 List
<CommonTree
> lengthChildren
= length
.getChildren();
1218 CommonTree first
= lengthChildren
.get(0);
1219 if (isUnaryInteger(first
)) {
1221 int arrayLength
= (int) parseUnaryInteger(first
);
1223 if (arrayLength
< 1) {
1224 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1227 /* Create the array declaration. */
1228 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1229 } else if (isAnyUnaryString(first
)) {
1231 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1233 /* check that lengthName was declared */
1234 if (isSignedIntegerField(lengthName
)) {
1235 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
1237 /* Create the sequence declaration. */
1238 declaration
= new SequenceDeclaration(lengthName
,
1241 childTypeError(first
);
1246 if (identifier
!= null) {
1247 identifierSB
.append(identifier
.getText());
1253 private boolean isSignedIntegerField(String lengthName
) throws ParseException
{
1254 IDeclaration decl
= getCurrentScope().lookupIdentifierRecursive(lengthName
);
1255 if (decl
instanceof IntegerDeclaration
) {
1256 return ((IntegerDeclaration
) decl
).isSigned();
1258 throw new ParseException("Is not an integer: " + lengthName
); //$NON-NLS-1$
1263 * Parses a type specifier list and returns the corresponding declaration.
1265 * @param typeSpecifierList
1266 * A TYPE_SPECIFIER_LIST node.
1267 * @param pointerList
1268 * A list of POINTER nodes that apply to the specified type.
1269 * @return The corresponding declaration.
1270 * @throws ParseException
1271 * If the type has not been defined or if there is an error
1272 * creating the declaration.
1274 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1275 List
<CommonTree
> pointerList
) throws ParseException
{
1276 IDeclaration declaration
= null;
1279 * By looking at the first element of the type specifier list, we can
1280 * determine which type it belongs to.
1282 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1284 switch (firstChild
.getType()) {
1285 case CTFParser
.FLOATING_POINT
:
1286 declaration
= parseFloat(firstChild
);
1288 case CTFParser
.INTEGER
:
1289 declaration
= parseInteger(firstChild
);
1291 case CTFParser
.STRING
:
1292 declaration
= parseString(firstChild
);
1294 case CTFParser
.STRUCT
:
1295 declaration
= parseStruct(firstChild
);
1297 case CTFParser
.VARIANT
:
1298 declaration
= parseVariant(firstChild
);
1300 case CTFParser
.ENUM
:
1301 declaration
= parseEnum(firstChild
);
1303 case CTFParser
.IDENTIFIER
:
1304 case CTFParser
.FLOATTOK
:
1305 case CTFParser
.INTTOK
:
1306 case CTFParser
.LONGTOK
:
1307 case CTFParser
.SHORTTOK
:
1308 case CTFParser
.SIGNEDTOK
:
1309 case CTFParser
.UNSIGNEDTOK
:
1310 case CTFParser
.CHARTOK
:
1311 case CTFParser
.DOUBLETOK
:
1312 case CTFParser
.VOIDTOK
:
1313 case CTFParser
.BOOLTOK
:
1314 case CTFParser
.COMPLEXTOK
:
1315 case CTFParser
.IMAGINARYTOK
:
1316 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1319 childTypeError(firstChild
);
1325 private IDeclaration
parseFloat(CommonTree floatingPoint
)
1326 throws ParseException
{
1328 List
<CommonTree
> children
= floatingPoint
.getChildren();
1331 * If the integer has no attributes, then it is missing the size
1332 * attribute which is required
1334 if (children
== null) {
1335 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1338 /* The return value */
1339 FloatDeclaration floatDeclaration
= null;
1340 ByteOrder byteOrder
= fTrace
.getByteOrder();
1345 /* Iterate on all integer children */
1346 for (CommonTree child
: children
) {
1347 switch (child
.getType()) {
1348 case CTFParser
.CTF_EXPRESSION_VAL
:
1350 * An assignment expression must have 2 children, left and right
1353 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1354 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1356 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1358 if (!isAnyUnaryString(leftStrings
.get(0))) {
1359 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1361 String left
= concatenateUnaryStrings(leftStrings
);
1363 if (left
.equals(MetadataStrings
.EXP_DIG
)) {
1364 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1365 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1366 byteOrder
= getByteOrder(rightNode
);
1367 } else if (left
.equals(MetadataStrings
.MANT_DIG
)) {
1368 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1369 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1370 alignment
= getAlignment(rightNode
);
1372 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1377 childTypeError(child
);
1381 int size
= mantissa
+ exponent
;
1383 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1386 if (alignment
== 0) {
1387 if ((size
% 8) == 0) {
1394 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1396 return floatDeclaration
;
1401 * Parses a type specifier list as a user-declared type.
1403 * @param typeSpecifierList
1404 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1405 * @param pointerList
1406 * A list of POINTER nodes that apply to the type specified in
1407 * typeSpecifierList.
1408 * @return The corresponding declaration.
1409 * @throws ParseException
1410 * If the type does not exist (has not been found).
1412 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1413 List
<CommonTree
> pointerList
) throws ParseException
{
1414 /* Create the string representation of the type declaration */
1415 String typeStringRepresentation
= createTypeDeclarationString(
1416 typeSpecifierList
, pointerList
);
1418 /* Use the string representation to search the type in the current scope */
1419 IDeclaration decl
= getCurrentScope().lookupTypeRecursive(
1420 typeStringRepresentation
);
1423 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1424 + " has not been defined."); //$NON-NLS-1$
1431 * Parses an integer declaration node.
1435 * @return The corresponding integer declaration.
1436 * @throws ParseException
1438 private IntegerDeclaration
parseInteger(CommonTree integer
)
1439 throws ParseException
{
1441 List
<CommonTree
> children
= integer
.getChildren();
1444 * If the integer has no attributes, then it is missing the size
1445 * attribute which is required
1447 if (children
== null) {
1448 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1451 /* The return value */
1452 IntegerDeclaration integerDeclaration
= null;
1453 boolean signed
= false;
1454 ByteOrder byteOrder
= fTrace
.getByteOrder();
1458 String clock
= null;
1460 Encoding encoding
= Encoding
.NONE
;
1462 /* Iterate on all integer children */
1463 for (CommonTree child
: children
) {
1464 switch (child
.getType()) {
1465 case CTFParser
.CTF_EXPRESSION_VAL
:
1467 * An assignment expression must have 2 children, left and right
1470 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1471 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1473 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1475 if (!isAnyUnaryString(leftStrings
.get(0))) {
1476 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1478 String left
= concatenateUnaryStrings(leftStrings
);
1480 if (left
.equals("signed")) { //$NON-NLS-1$
1481 signed
= getSigned(rightNode
);
1482 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1483 byteOrder
= getByteOrder(rightNode
);
1484 } else if (left
.equals("size")) { //$NON-NLS-1$
1485 size
= getSize(rightNode
);
1486 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1487 alignment
= getAlignment(rightNode
);
1488 } else if (left
.equals("base")) { //$NON-NLS-1$
1489 base
= getBase(rightNode
);
1490 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1491 encoding
= getEncoding(rightNode
);
1492 } else if (left
.equals("map")) { //$NON-NLS-1$
1493 clock
= getClock(rightNode
);
1495 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownIntegerAttributeWarning
+ " " + left
); //$NON-NLS-1$
1500 childTypeError(child
);
1506 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1509 if (alignment
== 0) {
1510 if ((size
% 8) == 0) {
1517 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1518 byteOrder
, encoding
, clock
, alignment
);
1520 return integerDeclaration
;
1523 private static String
getClock(CommonTree rightNode
) {
1524 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1527 private static StringDeclaration
parseString(CommonTree string
)
1528 throws ParseException
{
1530 List
<CommonTree
> children
= string
.getChildren();
1531 StringDeclaration stringDeclaration
= null;
1533 if (children
== null) {
1534 stringDeclaration
= new StringDeclaration();
1536 Encoding encoding
= Encoding
.UTF8
;
1537 for (CommonTree child
: children
) {
1538 switch (child
.getType()) {
1539 case CTFParser
.CTF_EXPRESSION_VAL
:
1541 * An assignment expression must have 2 children, left and
1545 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1546 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1548 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1550 if (!isAnyUnaryString(leftStrings
.get(0))) {
1551 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1553 String left
= concatenateUnaryStrings(leftStrings
);
1555 if (left
.equals("encoding")) { //$NON-NLS-1$
1556 encoding
= getEncoding(rightNode
);
1558 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1564 childTypeError(child
);
1569 stringDeclaration
= new StringDeclaration(encoding
);
1572 return stringDeclaration
;
1576 * Parses a struct declaration and returns the corresponding declaration.
1580 * @return The corresponding struct declaration.
1581 * @throws ParseException
1583 private StructDeclaration
parseStruct(CommonTree struct
)
1584 throws ParseException
{
1586 List
<CommonTree
> children
= struct
.getChildren();
1588 /* The return value */
1589 StructDeclaration structDeclaration
= null;
1592 String structName
= null;
1593 boolean hasName
= false;
1596 CommonTree structBody
= null;
1597 boolean hasBody
= false;
1600 long structAlign
= 0;
1602 /* Loop on all children and identify what we have to work with. */
1603 for (CommonTree child
: children
) {
1604 switch (child
.getType()) {
1605 case CTFParser
.STRUCT_NAME
: {
1608 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1610 structName
= structNameIdentifier
.getText();
1614 case CTFParser
.STRUCT_BODY
: {
1621 case CTFParser
.ALIGN
: {
1622 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1624 structAlign
= getAlignment(structAlignExpression
);
1629 childTypeError(child
);
1636 * If a struct has just a body and no name (just like the song,
1637 * "A Struct With No Name" by America (sorry for that...)), it's a
1638 * definition of a new type, so we create the type declaration and
1639 * return it. We can't add it to the declaration scope since there is no
1640 * name, but that's what we want because it won't be possible to use it
1641 * again to declare another field.
1643 * If it has just a name, we look it up in the declaration scope and
1644 * return the associated declaration. If it is not found in the
1645 * declaration scope, it means that a struct with that name has not been
1646 * declared, which is an error.
1648 * If it has both, then we create the type declaration and register it
1649 * to the current scope.
1651 * If it has none, then what are we doing here ?
1655 * If struct has a name, check if already defined in the current
1658 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1659 throw new ParseException("struct " + structName
//$NON-NLS-1$
1660 + " already defined."); //$NON-NLS-1$
1662 /* Create the declaration */
1663 structDeclaration
= new StructDeclaration(structAlign
);
1665 /* Parse the body */
1666 parseStructBody(structBody
, structDeclaration
);
1668 /* If struct has name, add it to the current scope. */
1670 getCurrentScope().registerStruct(structName
, structDeclaration
);
1672 } else /* !hasBody */{
1674 /* Name and !body */
1676 /* Lookup the name in the current scope. */
1677 structDeclaration
= getCurrentScope().lookupStructRecursive(structName
);
1680 * If not found, it means that a struct with such name has not
1683 if (structDeclaration
== null) {
1684 throw new ParseException("struct " + structName
//$NON-NLS-1$
1685 + " is not defined"); //$NON-NLS-1$
1688 /* !Name and !body */
1690 /* We can't do anything with that. */
1691 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1695 return structDeclaration
;
1699 * Parses a struct body, adding the fields to specified structure
1703 * A STRUCT_BODY node.
1704 * @param structDeclaration
1705 * The struct declaration.
1706 * @throws ParseException
1708 private void parseStructBody(CommonTree structBody
,
1709 StructDeclaration structDeclaration
) throws ParseException
{
1711 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1714 * If structDeclaration is null, structBody has no children and the
1715 * struct body is empty.
1717 if (structDeclarations
!= null) {
1720 for (CommonTree declarationNode
: structDeclarations
) {
1721 switch (declarationNode
.getType()) {
1722 case CTFParser
.TYPEALIAS
:
1723 parseTypealias(declarationNode
);
1725 case CTFParser
.TYPEDEF
:
1726 parseTypedef(declarationNode
);
1728 case CTFParser
.SV_DECLARATION
:
1729 parseStructDeclaration(declarationNode
, structDeclaration
);
1732 childTypeError(declarationNode
);
1741 * Parses a declaration found in a struct.
1743 * @param declaration
1744 * A SV_DECLARATION node.
1746 * A struct declaration. (I know, little name clash here...)
1747 * @throws ParseException
1749 private void parseStructDeclaration(CommonTree declaration
,
1750 StructDeclaration struct
) throws ParseException
{
1752 /* Get the type specifier list node */
1753 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1755 /* Get the type declarator list node */
1756 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1758 /* Get the type declarator list */
1759 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1762 * For each type declarator, parse the declaration and add a field to
1765 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1767 StringBuilder identifierSB
= new StringBuilder();
1769 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1770 typeSpecifierListNode
, identifierSB
);
1771 String fieldName
= identifierSB
.toString();
1772 getCurrentScope().registerIdentifier(fieldName
, decl
);
1774 if (struct
.hasField(fieldName
)) {
1775 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1779 struct
.addField(fieldName
, decl
);
1785 * Parses an enum declaration and returns the corresponding declaration.
1789 * @return The corresponding enum declaration.
1790 * @throws ParseException
1792 private EnumDeclaration
parseEnum(CommonTree theEnum
) throws ParseException
{
1794 List
<CommonTree
> children
= theEnum
.getChildren();
1796 /* The return value */
1797 EnumDeclaration enumDeclaration
= null;
1800 String enumName
= null;
1803 CommonTree enumBody
= null;
1805 /* Container type */
1806 IntegerDeclaration containerTypeDeclaration
= null;
1808 /* Loop on all children and identify what we have to work with. */
1809 for (CommonTree child
: children
) {
1810 switch (child
.getType()) {
1811 case CTFParser
.ENUM_NAME
: {
1812 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1813 enumName
= enumNameIdentifier
.getText();
1816 case CTFParser
.ENUM_BODY
: {
1820 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1821 containerTypeDeclaration
= parseEnumContainerType(child
);
1825 childTypeError(child
);
1831 * If the container type has not been defined explicitly, we assume it
1834 if (containerTypeDeclaration
== null) {
1835 IDeclaration enumDecl
;
1837 * it could be because the enum was already declared.
1839 if (enumName
!= null) {
1840 enumDecl
= getCurrentScope().lookupEnumRecursive(enumName
);
1841 if (enumDecl
!= null) {
1842 return (EnumDeclaration
) enumDecl
;
1846 IDeclaration decl
= getCurrentScope().lookupTypeRecursive("int"); //$NON-NLS-1$
1849 throw new ParseException("enum container type implicit and type int not defined"); //$NON-NLS-1$
1850 } else if (!(decl
instanceof IntegerDeclaration
)) {
1851 throw new ParseException("enum container type implicit and type int not an integer"); //$NON-NLS-1$
1854 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1858 * If it has a body, it's a new declaration, otherwise it's a reference
1859 * to an existing declaration. Same logic as struct.
1861 if (enumBody
!= null) {
1863 * If enum has a name, check if already defined in the current
1866 if ((enumName
!= null)
1867 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1868 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1869 + " already defined"); //$NON-NLS-1$
1872 /* Create the declaration */
1873 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1875 /* Parse the body */
1876 parseEnumBody(enumBody
, enumDeclaration
);
1878 /* If the enum has name, add it to the current scope. */
1879 if (enumName
!= null) {
1880 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1883 if (enumName
!= null) {
1884 /* Name and !body */
1886 /* Lookup the name in the current scope. */
1887 enumDeclaration
= getCurrentScope().lookupEnumRecursive(enumName
);
1890 * If not found, it means that an enum with such name has not
1893 if (enumDeclaration
== null) {
1894 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1895 + " is not defined"); //$NON-NLS-1$
1898 /* !Name and !body */
1899 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1903 return enumDeclaration
;
1908 * Parses an enum body, adding the enumerators to the specified enum
1912 * An ENUM_BODY node.
1913 * @param enumDeclaration
1914 * The enum declaration.
1915 * @throws ParseException
1917 private void parseEnumBody(CommonTree enumBody
,
1918 EnumDeclaration enumDeclaration
) throws ParseException
{
1920 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1921 /* enum body can't be empty (unlike struct). */
1926 * Start at -1, so that if the first enumrator has no explicit value, it
1931 for (CommonTree enumerator
: enumerators
) {
1932 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1941 * Parses an enumerator node and adds an enumerator declaration to an
1942 * enumeration declaration.
1944 * The high value of the range of the last enumerator is needed in case the
1945 * current enumerator does not specify its value.
1948 * An ENUM_ENUMERATOR node.
1949 * @param enumDeclaration
1950 * en enumeration declaration to which will be added the
1953 * The high value of the range of the last enumerator
1954 * @return The high value of the value range of the current enumerator.
1955 * @throws ParseException
1957 private static long parseEnumEnumerator(CommonTree enumerator
,
1958 EnumDeclaration enumDeclaration
, long lastHigh
)
1959 throws ParseException
{
1961 List
<CommonTree
> children
= enumerator
.getChildren();
1963 long low
= 0, high
= 0;
1964 boolean valueSpecified
= false;
1965 String label
= null;
1967 for (CommonTree child
: children
) {
1968 if (isAnyUnaryString(child
)) {
1969 label
= parseUnaryString(child
);
1970 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1972 valueSpecified
= true;
1974 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1976 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1978 valueSpecified
= true;
1980 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1981 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1983 childTypeError(child
);
1987 if (!valueSpecified
) {
1993 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1996 if (!enumDeclaration
.add(low
, high
, label
)) {
1997 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
2000 if (valueSpecified
&& (BigInteger
.valueOf(low
).compareTo(enumDeclaration
.getContainerType().getMinValue()) == -1 ||
2001 BigInteger
.valueOf(high
).compareTo(enumDeclaration
.getContainerType().getMaxValue()) == 1)) {
2002 throw new ParseException("enum value is not in range"); //$NON-NLS-1$
2009 * Parses an enum container type node and returns the corresponding integer
2012 * @param enumContainerType
2013 * An ENUM_CONTAINER_TYPE node.
2014 * @return An integer declaration corresponding to the container type.
2015 * @throws ParseException
2016 * If the type does not parse correctly or if it is not an
2019 private IntegerDeclaration
parseEnumContainerType(
2020 CommonTree enumContainerType
) throws ParseException
{
2022 /* Get the child, which should be a type specifier list */
2023 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
.getChild(0);
2025 /* Parse it and get the corresponding declaration */
2026 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
2028 /* If is is an integer, return it, else throw an error */
2029 if (decl
instanceof IntegerDeclaration
) {
2030 return (IntegerDeclaration
) decl
;
2032 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
2035 private VariantDeclaration
parseVariant(CommonTree variant
)
2036 throws ParseException
{
2038 List
<CommonTree
> children
= variant
.getChildren();
2039 VariantDeclaration variantDeclaration
= null;
2041 boolean hasName
= false;
2042 String variantName
= null;
2044 boolean hasBody
= false;
2045 CommonTree variantBody
= null;
2047 boolean hasTag
= false;
2048 String variantTag
= null;
2050 for (CommonTree child
: children
) {
2051 switch (child
.getType()) {
2052 case CTFParser
.VARIANT_NAME
:
2056 CommonTree variantNameIdentifier
= (CommonTree
) child
.getChild(0);
2058 variantName
= variantNameIdentifier
.getText();
2061 case CTFParser
.VARIANT_TAG
:
2065 CommonTree variantTagIdentifier
= (CommonTree
) child
.getChild(0);
2067 variantTag
= variantTagIdentifier
.getText();
2070 case CTFParser
.VARIANT_BODY
:
2074 variantBody
= child
;
2078 childTypeError(child
);
2085 * If variant has a name, check if already defined in the current
2089 && (getCurrentScope().lookupVariant(variantName
) != null)) {
2090 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2091 + " already defined."); //$NON-NLS-1$
2094 /* Create the declaration */
2095 variantDeclaration
= new VariantDeclaration();
2097 /* Parse the body */
2098 parseVariantBody(variantBody
, variantDeclaration
);
2100 /* If variant has name, add it to the current scope. */
2102 getCurrentScope().registerVariant(variantName
,
2103 variantDeclaration
);
2105 } else /* !hasBody */{
2107 /* Name and !body */
2109 /* Lookup the name in the current scope. */
2110 variantDeclaration
= getCurrentScope().lookupVariantRecursive(
2114 * If not found, it means that a struct with such name has not
2117 if (variantDeclaration
== null) {
2118 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2119 + " is not defined"); //$NON-NLS-1$
2122 /* !Name and !body */
2124 /* We can't do anything with that. */
2125 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2130 variantDeclaration
.setTag(variantTag
);
2132 IDeclaration decl
= getCurrentScope().lookupIdentifierRecursive(variantTag
);
2134 throw new ParseException("Variant tag not found: " + variantTag
); //$NON-NLS-1$
2136 if (!(decl
instanceof EnumDeclaration
)) {
2137 throw new ParseException("Variant tag must be an enum: " + variantTag
); //$NON-NLS-1$
2139 EnumDeclaration tagDecl
= (EnumDeclaration
) decl
;
2140 Set
<String
> intersection
= new HashSet
<>(tagDecl
.getLabels());
2141 intersection
.retainAll(variantDeclaration
.getFields().keySet());
2142 if (intersection
.isEmpty()) {
2143 throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName
); //$NON-NLS-1$
2147 return variantDeclaration
;
2150 private void parseVariantBody(CommonTree variantBody
,
2151 VariantDeclaration variantDeclaration
) throws ParseException
{
2153 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2157 for (CommonTree declarationNode
: variantDeclarations
) {
2158 switch (declarationNode
.getType()) {
2159 case CTFParser
.TYPEALIAS
:
2160 parseTypealias(declarationNode
);
2162 case CTFParser
.TYPEDEF
:
2163 parseTypedef(declarationNode
);
2165 case CTFParser
.SV_DECLARATION
:
2166 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2169 childTypeError(declarationNode
);
2177 private void parseVariantDeclaration(CommonTree declaration
,
2178 VariantDeclaration variant
) throws ParseException
{
2180 /* Get the type specifier list node */
2181 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2183 /* Get the type declarator list node */
2184 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2186 /* Get the type declarator list */
2187 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
2190 * For each type declarator, parse the declaration and add a field to
2193 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2195 StringBuilder identifierSB
= new StringBuilder();
2197 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2198 typeSpecifierListNode
, identifierSB
);
2200 String name
= identifierSB
.toString();
2202 if (variant
.hasField(name
)) {
2203 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2207 getCurrentScope().registerIdentifier(name
, decl
);
2209 variant
.addField(name
, decl
);
2214 * Creates the string representation of a type declaration (type specifier
2217 * @param typeSpecifierList
2218 * A TYPE_SPECIFIER_LIST node.
2220 * A list of POINTER nodes.
2221 * @return The string representation.
2222 * @throws ParseException
2224 private static String
createTypeDeclarationString(
2225 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2226 throws ParseException
{
2227 StringBuilder sb
= new StringBuilder();
2229 createTypeSpecifierListString(typeSpecifierList
, sb
);
2230 createPointerListString(pointers
, sb
);
2232 return sb
.toString();
2236 * Creates the string representation of a list of type specifiers.
2238 * @param typeSpecifierList
2239 * A TYPE_SPECIFIER_LIST node.
2241 * A StringBuilder to which will be appended the string.
2242 * @throws ParseException
2244 private static void createTypeSpecifierListString(
2245 CommonTree typeSpecifierList
, StringBuilder sb
)
2246 throws ParseException
{
2248 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2250 boolean firstItem
= true;
2252 for (CommonTree child
: children
) {
2260 /* Append the string that represents this type specifier. */
2261 createTypeSpecifierString(child
, sb
);
2266 * Creates the string representation of a type specifier.
2268 * @param typeSpecifier
2269 * A TYPE_SPECIFIER node.
2271 * A StringBuilder to which will be appended the string.
2272 * @throws ParseException
2274 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2275 StringBuilder sb
) throws ParseException
{
2276 switch (typeSpecifier
.getType()) {
2277 case CTFParser
.FLOATTOK
:
2278 case CTFParser
.INTTOK
:
2279 case CTFParser
.LONGTOK
:
2280 case CTFParser
.SHORTTOK
:
2281 case CTFParser
.SIGNEDTOK
:
2282 case CTFParser
.UNSIGNEDTOK
:
2283 case CTFParser
.CHARTOK
:
2284 case CTFParser
.DOUBLETOK
:
2285 case CTFParser
.VOIDTOK
:
2286 case CTFParser
.BOOLTOK
:
2287 case CTFParser
.COMPLEXTOK
:
2288 case CTFParser
.IMAGINARYTOK
:
2289 case CTFParser
.CONSTTOK
:
2290 case CTFParser
.IDENTIFIER
:
2291 sb
.append(typeSpecifier
.getText());
2293 case CTFParser
.STRUCT
: {
2294 CommonTree structName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2295 if (structName
== null) {
2296 throw new ParseException("nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2299 CommonTree structNameIdentifier
= (CommonTree
) structName
.getChild(0);
2301 sb
.append(structNameIdentifier
.getText());
2304 case CTFParser
.VARIANT
: {
2305 CommonTree variantName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2306 if (variantName
== null) {
2307 throw new ParseException("nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2310 CommonTree variantNameIdentifier
= (CommonTree
) variantName
.getChild(0);
2312 sb
.append(variantNameIdentifier
.getText());
2315 case CTFParser
.ENUM
: {
2316 CommonTree enumName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.ENUM_NAME
);
2317 if (enumName
== null) {
2318 throw new ParseException("nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2321 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2323 sb
.append(enumNameIdentifier
.getText());
2326 case CTFParser
.FLOATING_POINT
:
2327 case CTFParser
.INTEGER
:
2328 case CTFParser
.STRING
:
2329 throw new ParseException("CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2331 childTypeError(typeSpecifier
);
2337 * Creates the string representation of a list of pointers.
2339 * @param pointerList
2340 * A list of pointer nodes. If pointerList is null, this function
2343 * A stringbuilder to which will be appended the string.
2345 private static void createPointerListString(List
<CommonTree
> pointerList
,
2347 if (pointerList
== null) {
2351 for (CommonTree pointer
: pointerList
) {
2353 sb
.append(" *"); //$NON-NLS-1$
2354 if (pointer
.getChildCount() > 0) {
2356 sb
.append(" const"); //$NON-NLS-1$
2363 * The node to check.
2364 * @return True if the given node is an unary string.
2366 private static boolean isUnaryString(CommonTree node
) {
2367 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
));
2372 * The node to check.
2373 * @return True if the given node is any type of unary string (no quotes,
2376 private static boolean isAnyUnaryString(CommonTree node
) {
2377 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2382 * The node to check.
2383 * @return True if the given node is an unary integer.
2385 private static boolean isUnaryInteger(CommonTree node
) {
2386 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) ||
2387 (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) || (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2391 * Parses a unary string node and return the string value.
2393 * @param unaryString
2394 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2395 * or UNARY_EXPRESSION_STRING_QUOTES).
2396 * @return The string value.
2399 * It would be really nice to remove the quotes earlier, such as in the
2402 private static String
parseUnaryString(CommonTree unaryString
) {
2404 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2405 String strval
= value
.getText();
2408 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2409 strval
= strval
.substring(1, strval
.length() - 1);
2416 * Parses an unary integer (dec, hex or oct).
2418 * @param unaryInteger
2419 * An unary integer node.
2420 * @return The integer value.
2421 * @throws ParseException
2422 * on an invalid integer format ("bob" for example)
2424 private static long parseUnaryInteger(CommonTree unaryInteger
) throws ParseException
{
2426 List
<CommonTree
> children
= unaryInteger
.getChildren();
2427 CommonTree value
= children
.get(0);
2428 String strval
= value
.getText();
2432 intval
= Long
.decode(strval
);
2433 } catch (NumberFormatException e
) {
2434 throw new ParseException("Invalid integer format: " + strval
); //$NON-NLS-1$
2437 /* The rest of children are sign */
2438 if ((children
.size() % 2) == 0) {
2444 private static long getMajorOrMinor(CommonTree rightNode
)
2445 throws ParseException
{
2447 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2449 if (isUnaryInteger(firstChild
)) {
2450 if (rightNode
.getChildCount() > 1) {
2451 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2454 long m
= parseUnaryInteger(firstChild
);
2457 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2462 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2465 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2467 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2469 if (isAnyUnaryString(firstChild
)) {
2470 if (rightNode
.getChildCount() > 1) {
2471 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2474 String uuidstr
= parseUnaryString(firstChild
);
2477 return UUID
.fromString(uuidstr
);
2478 } catch (IllegalArgumentException e
) {
2479 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2482 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2486 * Gets the value of a "signed" integer attribute.
2490 * @return The "signed" value as a boolean.
2491 * @throws ParseException
2493 private static boolean getSigned(CommonTree rightNode
)
2494 throws ParseException
{
2496 boolean ret
= false;
2497 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2499 if (isUnaryString(firstChild
)) {
2500 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2502 if (strval
.equals(MetadataStrings
.TRUE
)
2503 || strval
.equals(MetadataStrings
.TRUE2
)) {
2505 } else if (strval
.equals(MetadataStrings
.FALSE
)
2506 || strval
.equals(MetadataStrings
.FALSE2
)) {
2509 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2510 + firstChild
.getChild(0).getText());
2512 } else if (isUnaryInteger(firstChild
)) {
2513 /* Happens if the value is something like "1234.hello" */
2514 if (rightNode
.getChildCount() > 1) {
2515 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2518 long intval
= parseUnaryInteger(firstChild
);
2522 } else if (intval
== 0) {
2525 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2526 + firstChild
.getChild(0).getText());
2529 throw new ParseException();
2536 * Gets the value of a "byte_order" integer attribute.
2540 * @return The "byte_order" value.
2541 * @throws ParseException
2543 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2545 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2547 if (isUnaryString(firstChild
)) {
2548 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2550 if (strval
.equals(MetadataStrings
.LE
)) {
2551 return ByteOrder
.LITTLE_ENDIAN
;
2552 } else if (strval
.equals(MetadataStrings
.BE
)
2553 || strval
.equals(MetadataStrings
.NETWORK
)) {
2554 return ByteOrder
.BIG_ENDIAN
;
2555 } else if (strval
.equals(MetadataStrings
.NATIVE
)) {
2556 return fTrace
.getByteOrder();
2558 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2561 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2565 * Determines if the given value is a valid alignment value.
2568 * The value to check.
2569 * @return True if it is valid.
2571 private static boolean isValidAlignment(long alignment
) {
2572 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2576 * Gets the value of a "size" integer attribute.
2580 * @return The "size" value.
2581 * @throws ParseException
2583 private static long getSize(CommonTree rightNode
) throws ParseException
{
2585 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2587 if (isUnaryInteger(firstChild
)) {
2588 if (rightNode
.getChildCount() > 1) {
2589 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2592 long size
= parseUnaryInteger(firstChild
);
2595 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2600 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2604 * Gets the value of a "align" integer or struct attribute.
2607 * A CTF_RIGHT node or directly an unary integer.
2608 * @return The align value.
2609 * @throws ParseException
2611 private static long getAlignment(CommonTree node
) throws ParseException
{
2614 * If a CTF_RIGHT node was passed, call getAlignment with the first
2617 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2618 if (node
.getChildCount() > 1) {
2619 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2622 return getAlignment((CommonTree
) node
.getChild(0));
2623 } else if (isUnaryInteger(node
)) {
2624 long alignment
= parseUnaryInteger(node
);
2626 if (!isValidAlignment(alignment
)) {
2627 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2633 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2637 * Gets the value of a "base" integer attribute.
2640 * An CTF_RIGHT node.
2641 * @return The "base" value.
2642 * @throws ParseException
2644 private static int getBase(CommonTree rightNode
) throws ParseException
{
2646 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2648 if (isUnaryInteger(firstChild
)) {
2649 if (rightNode
.getChildCount() > 1) {
2650 throw new ParseException("invalid base value"); //$NON-NLS-1$
2653 long intval
= parseUnaryInteger(firstChild
);
2654 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2655 || (intval
== 16)) {
2656 return (int) intval
;
2658 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2659 } else if (isUnaryString(firstChild
)) {
2660 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2662 if (strval
.equals(MetadataStrings
.DECIMAL
)
2663 || strval
.equals(MetadataStrings
.DEC
)
2664 || strval
.equals(MetadataStrings
.DEC_CTE
)
2665 || strval
.equals(MetadataStrings
.INT_MOD
)
2666 || strval
.equals(MetadataStrings
.UNSIGNED_CTE
)) {
2668 } else if (strval
.equals(MetadataStrings
.HEXADECIMAL
)
2669 || strval
.equals(MetadataStrings
.HEX
)
2670 || strval
.equals(MetadataStrings
.X
)
2671 || strval
.equals(MetadataStrings
.X2
)
2672 || strval
.equals(MetadataStrings
.POINTER
)) {
2674 } else if (strval
.equals(MetadataStrings
.OCTAL
)
2675 || strval
.equals(MetadataStrings
.OCT
)
2676 || strval
.equals(MetadataStrings
.OCTAL_CTE
)) {
2678 } else if (strval
.equals(MetadataStrings
.BINARY
)
2679 || strval
.equals(MetadataStrings
.BIN
)) {
2682 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2685 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2690 * Gets the value of an "encoding" integer attribute.
2694 * @return The "encoding" value.
2695 * @throws ParseException
2697 private static Encoding
getEncoding(CommonTree rightNode
)
2698 throws ParseException
{
2700 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2702 if (isUnaryString(firstChild
)) {
2703 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2705 if (strval
.equals(MetadataStrings
.UTF8
)) {
2706 return Encoding
.UTF8
;
2707 } else if (strval
.equals(MetadataStrings
.ASCII
)) {
2708 return Encoding
.ASCII
;
2709 } else if (strval
.equals(MetadataStrings
.NONE
)) {
2710 return Encoding
.NONE
;
2712 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2715 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2718 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2720 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2722 if (isUnaryInteger(firstChild
)) {
2723 if (rightNode
.getChildCount() > 1) {
2724 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2727 long intval
= parseUnaryInteger(firstChild
);
2731 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2734 private static String
getEventName(CommonTree rightNode
)
2735 throws ParseException
{
2737 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2739 if (isAnyUnaryString(firstChild
)) {
2740 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2744 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2747 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2749 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2751 if (isUnaryInteger(firstChild
)) {
2752 if (rightNode
.getChildCount() > 1) {
2753 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2756 long intval
= parseUnaryInteger(firstChild
);
2760 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2764 * Concatenates a list of unary strings separated by arrows (->) or dots.
2767 * A list, first element being an unary string, subsequent
2768 * elements being ARROW or DOT nodes with unary strings as child.
2769 * @return The string representation of the unary string chain.
2771 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2773 StringBuilder sb
= new StringBuilder();
2775 CommonTree first
= strings
.get(0);
2776 sb
.append(parseUnaryString(first
));
2778 boolean isFirst
= true;
2780 for (CommonTree ref
: strings
) {
2786 CommonTree id
= (CommonTree
) ref
.getChild(0);
2788 if (ref
.getType() == CTFParser
.ARROW
) {
2789 sb
.append("->"); //$NON-NLS-1$
2794 sb
.append(parseUnaryString(id
));
2797 return sb
.toString();
2801 * Throws a ParseException stating that the parent-child relation between
2802 * the given node and its parent is not valid. It means that the shape of
2803 * the AST is unexpected.
2806 * The invalid child node.
2807 * @throws ParseException
2809 private static void childTypeError(CommonTree child
) throws ParseException
{
2810 CommonTree parent
= (CommonTree
) child
.getParent();
2811 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2812 + " can't have a child of type " //$NON-NLS-1$
2813 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2815 throw new ParseException(error
);
2818 // ------------------------------------------------------------------------
2820 // ------------------------------------------------------------------------
2823 * Adds a new declaration scope on the top of the scope stack.
2825 private void pushScope() {
2826 fScope
= new DeclarationScope(fScope
);
2830 * Removes the top declaration scope from the scope stack.
2832 private void popScope() {
2833 fScope
= fScope
.getParentScope();
2837 * Returns the current declaration scope.
2839 * @return The current declaration scope.
2841 private DeclarationScope
getCurrentScope() {