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
.jdt
.annotation
.NonNull
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.CTFClock
;
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
.StringDeclaration
;
40 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
41 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
42 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFStream
;
43 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
44 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
45 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.Activator
;
46 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.EventDeclaration
;
47 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
48 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.types
.ArrayDeclaration
;
49 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.types
.SequenceDeclaration
;
54 public class IOStructGen
{
56 // ------------------------------------------------------------------------
58 // ------------------------------------------------------------------------
60 private static final boolean DEBUG
= false;
65 private final CTFTrace fTrace
;
66 private CommonTree fTree
;
69 * The current declaration scope.
71 private DeclarationScope fScope
= null;
74 * Data helpers needed for streaming
77 private boolean fHasBeenParsed
= false;
79 // ------------------------------------------------------------------------
81 // ------------------------------------------------------------------------
87 * the tree (ANTLR generated) with the parsed TSDL data.
89 * the trace containing the places to put all the read metadata
91 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
98 * Parse the tree and populate the trace defined in the constructor.
100 * @throws ParseException
101 * If there was a problem parsing the metadata
103 public void generate() throws ParseException
{
108 * Parse a partial tree and populate the trace defined in the constructor.
109 * Does not check for a "trace" block as there is only one in the trace and
112 * @throws ParseException
113 * If there was a problem parsing the metadata
115 public void generateFragment() throws ParseException
{
116 parseIncompleteRoot(fTree
);
119 // ------------------------------------------------------------------------
121 // ------------------------------------------------------------------------
124 * Sets a new tree to parse
127 * the new tree to parse
129 public void setTree(CommonTree newTree
) {
134 * Parse the root node.
138 * @throws ParseException
140 private void parseRoot(CommonTree root
) throws ParseException
{
142 List
<CommonTree
> children
= root
.getChildren();
143 java
.io
.FileOutputStream fos
= null;
144 java
.io
.OutputStreamWriter out
= null;
147 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
148 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
149 } catch (FileNotFoundException e
) {
152 } catch (UnsupportedEncodingException e
) {
158 CommonTree traceNode
= null;
159 List
<CommonTree
> streams
= new ArrayList
<>();
160 List
<CommonTree
> events
= new ArrayList
<>();
161 List
<CommonTree
> declarations
= new ArrayList
<>();
162 List
<CommonTree
> environments
= new ArrayList
<>();
163 List
<CommonTree
> clocks
= new ArrayList
<>();
164 List
<CommonTree
> callsites
= new ArrayList
<>();
166 /* Create a new declaration scope with no parent. */
170 for (CommonTree child
: children
) {
171 final int type
= child
.getType();
173 out
.write(child
.toString()
174 + " -> " + type
+ '\n'); //$NON-NLS-1$
177 case CTFParser
.DECLARATION
:
178 declarations
.add(child
);
180 case CTFParser
.TRACE
:
181 if (traceNode
!= null) {
182 throw new ParseException("Only one trace block is allowed"); //$NON-NLS-1$
186 case CTFParser
.STREAM
:
189 case CTFParser
.EVENT
:
192 case CTFParser
.CLOCK
:
196 environments
.add(child
);
198 case CTFParser
.CALLSITE
:
199 callsites
.add(child
);
202 childTypeError(child
);
206 out
.write("Declarations\n"); //$NON-NLS-1$
208 for (CommonTree decl
: declarations
) {
210 out
.write(decl
.toString() + '\n');
212 parseRootDeclaration(decl
);
214 if (traceNode
== null) {
215 throw new ParseException("Missing trace block"); //$NON-NLS-1$
218 parseTrace(traceNode
);
221 out
.write("Environments\n"); //$NON-NLS-1$
223 for (CommonTree environment
: environments
) {
224 parseEnvironment(environment
);
227 out
.write("Clocks\n"); //$NON-NLS-1$
229 for (CommonTree clock
: clocks
) {
233 out
.write("Callsites\n"); //$NON-NLS-1$
235 for (CommonTree callsite
: callsites
) {
236 parseCallsite(callsite
);
240 out
.write("Streams\n"); //$NON-NLS-1$
242 if (streams
.size() > 0) {
243 for (CommonTree stream
: streams
) {
246 out
.write(stream
.toString() + '\n');
247 } catch (IOException e
) {
254 /* Add an empty stream that will have a null id */
255 fTrace
.addStream(new CTFStream(fTrace
));
259 out
.write("Events\n"); //$NON-NLS-1$
261 for (CommonTree event
: events
) {
264 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
265 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
266 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
274 } catch (IOException e
) {
278 fHasBeenParsed
= true;
281 private void parseIncompleteRoot(CommonTree root
) throws ParseException
{
282 List
<CommonTree
> children
= root
.getChildren();
284 if (fHasBeenParsed
== false) {
285 throw new ParseException("You need to run generate first"); //$NON-NLS-1$
287 List
<CommonTree
> streams
= new ArrayList
<>();
288 List
<CommonTree
> events
= new ArrayList
<>();
289 List
<CommonTree
> declarations
= new ArrayList
<>();
290 List
<CommonTree
> environments
= new ArrayList
<>();
291 List
<CommonTree
> clocks
= new ArrayList
<>();
292 List
<CommonTree
> callsites
= new ArrayList
<>();
293 /* Create a new declaration scope with no parent. */
296 for (CommonTree child
: children
) {
297 final int type
= child
.getType();
299 case CTFParser
.DECLARATION
:
300 declarations
.add(child
);
302 case CTFParser
.TRACE
:
303 throw new ParseException("Trace block defined here, please use generate and not generateFragment to parse this fragment"); //$NON-NLS-1$
304 case CTFParser
.STREAM
:
307 case CTFParser
.EVENT
:
310 case CTFParser
.CLOCK
:
314 environments
.add(child
);
316 case CTFParser
.CALLSITE
:
317 callsites
.add(child
);
320 childTypeError(child
);
323 for (CommonTree decl
: declarations
) {
324 parseRootDeclaration(decl
);
327 for (CommonTree environment
: environments
) {
328 parseEnvironment(environment
);
330 for (CommonTree clock
: clocks
) {
333 for (CommonTree callsite
: callsites
) {
334 parseCallsite(callsite
);
337 for (CommonTree stream
: streams
) {
341 for (CommonTree event
: events
) {
347 private void parseCallsite(CommonTree callsite
) {
349 List
<CommonTree
> children
= callsite
.getChildren();
351 String funcName
= null;
352 long lineNumber
= -1;
354 String fileName
= null;
356 for (CommonTree child
: children
) {
358 /* this is a regex to find the leading and trailing quotes */
359 final String regex
= "^\"|\"$"; //$NON-NLS-1$
361 * this is to replace the previous quotes with nothing...
362 * effectively deleting them
364 final String nullString
= ""; //$NON-NLS-1$
365 left
= child
.getChild(0).getChild(0).getChild(0).getText();
366 if (left
.equals("name")) { //$NON-NLS-1$
367 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
368 } else if (left
.equals("func")) { //$NON-NLS-1$
369 funcName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
370 } else if (left
.equals("ip")) { //$NON-NLS-1$
371 ip
= Long
.decode(child
.getChild(1).getChild(0).getChild(0).getText());
372 } else if (left
.equals("file")) { //$NON-NLS-1$
373 fileName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
374 } else if (left
.equals("line")) { //$NON-NLS-1$
375 lineNumber
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
378 fTrace
.addCallsite(name
, funcName
, ip
, fileName
, lineNumber
);
381 private void parseEnvironment(CommonTree environment
) {
382 List
<CommonTree
> children
= environment
.getChildren();
383 for (CommonTree child
: children
) {
386 left
= child
.getChild(0).getChild(0).getChild(0).getText();
387 right
= child
.getChild(1).getChild(0).getChild(0).getText();
388 fTrace
.addEnvironmentVar(left
, right
);
392 private void parseClock(CommonTree clock
) {
393 List
<CommonTree
> children
= clock
.getChildren();
394 CTFClock ctfClock
= new CTFClock();
395 for (CommonTree child
: children
) {
396 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
397 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
398 final int type
= value
.getType();
400 case CTFParser
.INTEGER
:
401 case CTFParser
.DECIMAL_LITERAL
:
403 * Not a pretty hack, this is to make sure that there is no
404 * number overflow due to 63 bit integers. The offset should
405 * only really be an issue in the year 2262. the tracer in C/ASM
406 * can write an offset in an unsigned 64 bit long. In java, the
407 * last bit, being set to 1 will be read as a negative number,
408 * but since it is too big a positive it will throw an
409 * exception. this will happen in 2^63 ns from 1970. Therefore
410 * 293 years from 1970
414 numValue
= Long
.parseLong(value
.getText());
415 } catch (Exception e
) {
416 numValue
= 1330938566783103277L;
418 ctfClock
.addAttribute(key
, numValue
);
421 ctfClock
.addAttribute(key
, value
.getText());
425 String nameValue
= ctfClock
.getName();
426 fTrace
.addClock(nameValue
, ctfClock
);
429 private void parseTrace(CommonTree traceNode
) throws ParseException
{
431 List
<CommonTree
> children
= traceNode
.getChildren();
432 if (children
== null) {
433 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
438 for (CommonTree child
: children
) {
439 switch (child
.getType()) {
440 case CTFParser
.TYPEALIAS
:
441 parseTypealias(child
);
443 case CTFParser
.TYPEDEF
:
446 case CTFParser
.CTF_EXPRESSION_TYPE
:
447 case CTFParser
.CTF_EXPRESSION_VAL
:
448 parseTraceDeclaration(child
);
451 childTypeError(child
);
457 * If trace byte order was not specified and not using packet based
460 if (fTrace
.getByteOrder() == null) {
461 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
467 private void parseTraceDeclaration(CommonTree traceDecl
)
468 throws ParseException
{
470 /* There should be a left and right */
472 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
473 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
475 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
477 if (!isAnyUnaryString(leftStrings
.get(0))) {
478 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
481 String left
= concatenateUnaryStrings(leftStrings
);
483 if (left
.equals(MetadataStrings
.MAJOR
)) {
484 if (fTrace
.majorIsSet()) {
485 throw new ParseException("major is already set"); //$NON-NLS-1$
488 fTrace
.setMajor(getMajorOrMinor(rightNode
));
489 } else if (left
.equals(MetadataStrings
.MINOR
)) {
490 if (fTrace
.minorIsSet()) {
491 throw new ParseException("minor is already set"); //$NON-NLS-1$
494 fTrace
.setMinor(getMajorOrMinor(rightNode
));
495 } else if (left
.equals(MetadataStrings
.UUID_STRING
)) {
496 UUID uuid
= getUUID(rightNode
);
499 * If uuid was already set by a metadata packet, compare it to see
502 if (fTrace
.uuidIsSet()) {
503 if (fTrace
.getUUID().compareTo(uuid
) != 0) {
504 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
505 + fTrace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
508 fTrace
.setUUID(uuid
);
511 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
512 ByteOrder byteOrder
= getByteOrder(rightNode
);
515 * If byte order was already set by a metadata packet, compare it to
518 if (fTrace
.getByteOrder() != null) {
519 if (fTrace
.getByteOrder() != byteOrder
) {
520 throw new ParseException(
521 "Endianness mismatch. Magic number says " //$NON-NLS-1$
522 + fTrace
.getByteOrder()
523 + " but metadata says " + byteOrder
); //$NON-NLS-1$
526 fTrace
.setByteOrder(byteOrder
);
527 final DeclarationScope parentScope
= fScope
.getParentScope();
529 for (String type
: parentScope
.getTypeNames()) {
530 IDeclaration d
= parentScope
.lookupType(type
);
531 if (d
instanceof IntegerDeclaration
) {
532 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
533 } else if (d
instanceof StructDeclaration
) {
534 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
538 } else if (left
.equals(MetadataStrings
.PACKET_HEADER
)) {
539 if (fTrace
.packetHeaderIsSet()) {
540 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
543 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
545 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
546 throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
549 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
550 typeSpecifier
, null);
552 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
553 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
556 fTrace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
558 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownTraceAttributeWarning
+ " " + left
); //$NON-NLS-1$
562 private static void addByteOrder(ByteOrder byteOrder
,
563 final DeclarationScope parentScope
, String name
,
564 IntegerDeclaration decl
) throws ParseException
{
566 if (decl
.getByteOrder() != byteOrder
) {
567 IntegerDeclaration newI
;
568 newI
= IntegerDeclaration
.createDeclaration(decl
.getLength(), decl
.isSigned(),
569 decl
.getBase(), byteOrder
, decl
.getEncoding(),
570 decl
.getClock(), decl
.getAlignment());
571 parentScope
.replaceType(name
, newI
);
575 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
576 ByteOrder byteOrder
) throws ParseException
{
578 for (String s
: sd
.getFieldsList()) {
579 IDeclaration d
= sd
.getFields().get(s
);
581 if (d
instanceof StructDeclaration
) {
582 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
584 } else if (d
instanceof VariantDeclaration
) {
585 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
587 } else if (d
instanceof IntegerDeclaration
) {
588 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
589 if (decl
.getByteOrder() != byteOrder
) {
590 IntegerDeclaration newI
;
591 newI
= IntegerDeclaration
.createDeclaration(decl
.getLength(),
592 decl
.isSigned(), decl
.getBase(), byteOrder
,
593 decl
.getEncoding(), decl
.getClock(),
594 decl
.getAlignment());
595 sd
.getFields().put(s
, newI
);
601 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
602 ByteOrder byteOrder
) throws ParseException
{
604 for (String s
: vd
.getFields().keySet()) {
605 IDeclaration d
= vd
.getFields().get(s
);
607 if (d
instanceof StructDeclaration
) {
608 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
610 } else if (d
instanceof IntegerDeclaration
) {
611 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
612 IntegerDeclaration newI
;
613 newI
= IntegerDeclaration
.createDeclaration(decl
.getLength(),
614 decl
.isSigned(), decl
.getBase(), byteOrder
,
615 decl
.getEncoding(), decl
.getClock(),
616 decl
.getAlignment());
617 vd
.getFields().put(s
, newI
);
622 private void parseStream(CommonTree streamNode
) throws ParseException
{
624 CTFStream stream
= new CTFStream(fTrace
);
626 List
<CommonTree
> children
= streamNode
.getChildren();
627 if (children
== null) {
628 throw new ParseException("Empty stream block"); //$NON-NLS-1$
633 for (CommonTree child
: children
) {
634 switch (child
.getType()) {
635 case CTFParser
.TYPEALIAS
:
636 parseTypealias(child
);
638 case CTFParser
.TYPEDEF
:
641 case CTFParser
.CTF_EXPRESSION_TYPE
:
642 case CTFParser
.CTF_EXPRESSION_VAL
:
643 parseStreamDeclaration(child
, stream
);
646 childTypeError(child
);
651 if (stream
.isIdSet()) {
652 if (!fTrace
.packetHeaderIsSet()
653 || !fTrace
.getPacketHeader().hasField(MetadataStrings
.STREAM_ID
)) {
654 throw new ParseException("Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
658 fTrace
.addStream(stream
);
663 private void parseStreamDeclaration(CommonTree streamDecl
, CTFStream stream
)
664 throws ParseException
{
666 /* There should be a left and right */
668 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
669 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
671 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
673 if (!isAnyUnaryString(leftStrings
.get(0))) {
674 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
677 String left
= concatenateUnaryStrings(leftStrings
);
679 if (left
.equals(MetadataStrings
.ID
)) {
680 if (stream
.isIdSet()) {
681 throw new ParseException("stream id already defined"); //$NON-NLS-1$
684 long streamID
= getStreamID(rightNode
);
686 stream
.setId(streamID
);
687 } else if (left
.equals(MetadataStrings
.EVENT_HEADER
)) {
688 if (stream
.isEventHeaderSet()) {
689 throw new ParseException("event.header already defined"); //$NON-NLS-1$
692 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
694 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
695 throw new ParseException("event.header expects a type specifier"); //$NON-NLS-1$
698 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
699 typeSpecifier
, null);
701 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
702 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
705 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
706 } else if (left
.equals(MetadataStrings
.EVENT_CONTEXT
)) {
707 if (stream
.isEventContextSet()) {
708 throw new ParseException("event.context already defined"); //$NON-NLS-1$
711 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
713 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
714 throw new ParseException("event.context expects a type specifier"); //$NON-NLS-1$
717 IDeclaration eventContextDecl
= parseTypeSpecifierList(
718 typeSpecifier
, null);
720 if (!(eventContextDecl
instanceof StructDeclaration
)) {
721 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
724 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
725 } else if (left
.equals(MetadataStrings
.PACKET_CONTEXT
)) {
726 if (stream
.isPacketContextSet()) {
727 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
730 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
732 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
733 throw new ParseException("packet.context expects a type specifier"); //$NON-NLS-1$
736 IDeclaration packetContextDecl
= parseTypeSpecifierList(
737 typeSpecifier
, null);
739 if (!(packetContextDecl
instanceof StructDeclaration
)) {
740 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
743 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
745 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownStreamAttributeWarning
+ " " + left
); //$NON-NLS-1$
749 private void parseEvent(CommonTree eventNode
) throws ParseException
{
751 List
<CommonTree
> children
= eventNode
.getChildren();
752 if (children
== null) {
753 throw new ParseException("Empty event block"); //$NON-NLS-1$
756 EventDeclaration event
= new EventDeclaration();
760 for (CommonTree child
: children
) {
761 switch (child
.getType()) {
762 case CTFParser
.TYPEALIAS
:
763 parseTypealias(child
);
765 case CTFParser
.TYPEDEF
:
768 case CTFParser
.CTF_EXPRESSION_TYPE
:
769 case CTFParser
.CTF_EXPRESSION_VAL
:
770 parseEventDeclaration(child
, event
);
773 childTypeError(child
);
778 if (!event
.nameIsSet()) {
779 throw new ParseException("Event name not set"); //$NON-NLS-1$
783 * If the event did not specify a stream, then the trace must be single
786 if (!event
.streamIsSet()) {
787 if (fTrace
.nbStreams() > 1) {
788 throw new ParseException("Event without stream_id with more than one stream"); //$NON-NLS-1$
792 * If the event did not specify a stream, the only existing stream
793 * must not have an id. Note: That behavior could be changed, it
794 * could be possible to just get the only existing stream, whatever
797 CTFStream stream
= fTrace
.getStream(null);
799 if (stream
!= null) {
800 event
.setStream(stream
);
802 throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
807 * Add the event to the stream.
809 event
.getStream().addEvent(event
);
814 private void parseEventDeclaration(CommonTree eventDecl
,
815 EventDeclaration event
) throws ParseException
{
817 /* There should be a left and right */
819 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
820 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
822 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
824 if (!isAnyUnaryString(leftStrings
.get(0))) {
825 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
828 String left
= concatenateUnaryStrings(leftStrings
);
830 if (left
.equals(MetadataStrings
.NAME2
)) {
831 if (event
.nameIsSet()) {
832 throw new ParseException("name already defined"); //$NON-NLS-1$
835 String name
= getEventName(rightNode
);
838 } else if (left
.equals(MetadataStrings
.ID
)) {
839 if (event
.idIsSet()) {
840 throw new ParseException("id already defined"); //$NON-NLS-1$
843 long id
= getEventID(rightNode
);
846 } else if (left
.equals(MetadataStrings
.STREAM_ID
)) {
847 if (event
.streamIsSet()) {
848 throw new ParseException("stream id already defined"); //$NON-NLS-1$
851 long streamId
= getStreamID(rightNode
);
853 CTFStream stream
= fTrace
.getStream(streamId
);
855 if (stream
== null) {
856 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
859 event
.setStream(stream
);
860 } else if (left
.equals(MetadataStrings
.CONTEXT
)) {
861 if (event
.contextIsSet()) {
862 throw new ParseException("context already defined"); //$NON-NLS-1$
865 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
867 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
868 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
871 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
874 if (!(contextDecl
instanceof StructDeclaration
)) {
875 throw new ParseException("context expects a struct"); //$NON-NLS-1$
878 event
.setContext((StructDeclaration
) contextDecl
);
879 } else if (left
.equals(MetadataStrings
.FIELDS_STRING
)) {
880 if (event
.fieldsIsSet()) {
881 throw new ParseException("fields already defined"); //$NON-NLS-1$
884 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
886 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
887 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
890 IDeclaration fieldsDecl
;
891 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
893 if (!(fieldsDecl
instanceof StructDeclaration
)) {
894 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
897 * The underscores in the event names. These underscores were added
898 * by the LTTng tracer.
900 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
901 event
.setFields(fields
);
902 } else if (left
.equals(MetadataStrings
.LOGLEVEL2
)) {
903 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
904 event
.setLogLevel(logLevel
);
906 /* Custom event attribute, we'll add it to the attributes map */
907 String right
= parseUnaryString((CommonTree
) rightNode
.getChild(0));
908 event
.setCustomAttribute(left
, right
);
913 * Parses a declaration at the root level.
916 * The declaration subtree.
917 * @throws ParseException
919 private void parseRootDeclaration(CommonTree declaration
)
920 throws ParseException
{
922 List
<CommonTree
> children
= declaration
.getChildren();
924 for (CommonTree child
: children
) {
925 switch (child
.getType()) {
926 case CTFParser
.TYPEDEF
:
929 case CTFParser
.TYPEALIAS
:
930 parseTypealias(child
);
932 case CTFParser
.TYPE_SPECIFIER_LIST
:
933 parseTypeSpecifierList(child
, null);
936 childTypeError(child
);
942 * Parses a typealias node. It parses the target, the alias, and registers
943 * the type in the current scope.
947 * @throws ParseException
949 private void parseTypealias(CommonTree typealias
) throws ParseException
{
951 List
<CommonTree
> children
= typealias
.getChildren();
953 CommonTree target
= null;
954 CommonTree alias
= null;
956 for (CommonTree child
: children
) {
957 switch (child
.getType()) {
958 case CTFParser
.TYPEALIAS_TARGET
:
961 case CTFParser
.TYPEALIAS_ALIAS
:
965 childTypeError(child
);
970 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
972 if ((targetDeclaration
instanceof VariantDeclaration
)
973 && ((VariantDeclaration
) targetDeclaration
).isTagged()) {
974 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
977 String aliasString
= parseTypealiasAlias(alias
);
979 getCurrentScope().registerType(aliasString
, targetDeclaration
);
983 * Parses the target part of a typealias and gets the corresponding
987 * A TYPEALIAS_TARGET node.
988 * @return The corresponding declaration.
989 * @throws ParseException
991 private IDeclaration
parseTypealiasTarget(CommonTree target
)
992 throws ParseException
{
994 List
<CommonTree
> children
= target
.getChildren();
996 CommonTree typeSpecifierList
= null;
997 CommonTree typeDeclaratorList
= null;
998 CommonTree typeDeclarator
= null;
999 StringBuilder identifierSB
= new StringBuilder();
1001 for (CommonTree child
: children
) {
1002 switch (child
.getType()) {
1003 case CTFParser
.TYPE_SPECIFIER_LIST
:
1004 typeSpecifierList
= child
;
1006 case CTFParser
.TYPE_DECLARATOR_LIST
:
1007 typeDeclaratorList
= child
;
1010 childTypeError(child
);
1015 if (typeDeclaratorList
!= null) {
1017 * Only allow one declarator
1019 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
1020 * otherwise the new type puint8_t would maps to two different
1023 if (typeDeclaratorList
.getChildCount() != 1) {
1024 throw new ParseException("Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
1027 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1030 /* Parse the target type and get the declaration */
1031 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
1032 typeSpecifierList
, identifierSB
);
1035 * We don't allow identifier in the target
1037 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
1040 if (identifierSB
.length() > 0) {
1041 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
1042 + ") not expected in the typealias target"); //$NON-NLS-1$
1045 return targetDeclaration
;
1049 * Parses the alias part of a typealias. It parses the underlying specifier
1050 * list and declarator and creates the string representation that will be
1051 * used to register the type.
1054 * A TYPEALIAS_ALIAS node.
1055 * @return The string representation of the alias.
1056 * @throws ParseException
1058 private static String
parseTypealiasAlias(CommonTree alias
)
1059 throws ParseException
{
1061 List
<CommonTree
> children
= alias
.getChildren();
1063 CommonTree typeSpecifierList
= null;
1064 CommonTree typeDeclaratorList
= null;
1065 CommonTree typeDeclarator
= null;
1066 List
<CommonTree
> pointers
= new LinkedList
<>();
1068 for (CommonTree child
: children
) {
1069 switch (child
.getType()) {
1070 case CTFParser
.TYPE_SPECIFIER_LIST
:
1071 typeSpecifierList
= child
;
1073 case CTFParser
.TYPE_DECLARATOR_LIST
:
1074 typeDeclaratorList
= child
;
1077 childTypeError(child
);
1082 /* If there is a type declarator list, extract the pointers */
1083 if (typeDeclaratorList
!= null) {
1085 * Only allow one declarator
1087 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
1089 if (typeDeclaratorList
.getChildCount() != 1) {
1090 throw new ParseException("Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1093 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1095 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
1097 for (CommonTree child
: typeDeclaratorChildren
) {
1098 switch (child
.getType()) {
1099 case CTFParser
.POINTER
:
1100 pointers
.add(child
);
1102 case CTFParser
.IDENTIFIER
:
1103 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1104 + ") not expected in the typealias target"); //$NON-NLS-1$
1106 childTypeError(child
);
1112 return createTypeDeclarationString(typeSpecifierList
, pointers
);
1116 * Parses a typedef node. This creates and registers a new declaration for
1117 * each declarator found in the typedef.
1121 * @throws ParseException
1122 * If there is an error creating the declaration.
1124 private void parseTypedef(CommonTree typedef
) throws ParseException
{
1126 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1128 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1130 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1132 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1133 StringBuilder identifierSB
= new StringBuilder();
1135 IDeclaration typeDeclaration
= parseTypeDeclarator(
1136 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1138 if ((typeDeclaration
instanceof VariantDeclaration
)
1139 && ((VariantDeclaration
) typeDeclaration
).isTagged()) {
1140 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1143 getCurrentScope().registerType(identifierSB
.toString(),
1149 * Parses a pair type declarator / type specifier list and returns the
1150 * corresponding declaration. If it is present, it also writes the
1151 * identifier of the declarator in the given {@link StringBuilder}.
1153 * @param typeDeclarator
1154 * A TYPE_DECLARATOR node.
1155 * @param typeSpecifierList
1156 * A TYPE_SPECIFIER_LIST node.
1157 * @param identifierSB
1158 * A StringBuilder that will receive the identifier found in the
1160 * @return The corresponding declaration.
1161 * @throws ParseException
1162 * If there is an error finding or creating the declaration.
1164 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1165 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1166 throws ParseException
{
1168 IDeclaration declaration
= null;
1169 List
<CommonTree
> children
= null;
1170 List
<CommonTree
> pointers
= new LinkedList
<>();
1171 List
<CommonTree
> lengths
= new LinkedList
<>();
1172 CommonTree identifier
= null;
1174 /* Separate the tokens by type */
1175 if (typeDeclarator
!= null) {
1176 children
= typeDeclarator
.getChildren();
1177 for (CommonTree child
: children
) {
1179 switch (child
.getType()) {
1180 case CTFParser
.POINTER
:
1181 pointers
.add(child
);
1183 case CTFParser
.IDENTIFIER
:
1186 case CTFParser
.LENGTH
:
1190 childTypeError(child
);
1198 * Parse the type specifier list, which is the "base" type. For example,
1199 * it would be int in int a[3][len].
1201 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1204 * Each length subscript means that we must create a nested array or
1205 * sequence. For example, int a[3][len] means that we have an array of 3
1206 * (sequences of length 'len' of (int)).
1208 if (lengths
.size() > 0) {
1209 /* We begin at the end */
1210 Collections
.reverse(lengths
);
1212 for (CommonTree length
: lengths
) {
1214 * By looking at the first expression, we can determine whether
1215 * it is an array or a sequence.
1217 List
<CommonTree
> lengthChildren
= length
.getChildren();
1219 CommonTree first
= lengthChildren
.get(0);
1220 if (isUnaryInteger(first
)) {
1222 int arrayLength
= (int) parseUnaryInteger(first
);
1224 if (arrayLength
< 1) {
1225 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1228 /* Create the array declaration. */
1229 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1230 } else if (isAnyUnaryString(first
)) {
1232 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1234 /* check that lengthName was declared */
1235 if (isSignedIntegerField(lengthName
)) {
1236 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
1238 /* Create the sequence declaration. */
1239 declaration
= new SequenceDeclaration(lengthName
,
1242 childTypeError(first
);
1247 if (identifier
!= null) {
1248 identifierSB
.append(identifier
.getText());
1254 private boolean isSignedIntegerField(String lengthName
) throws ParseException
{
1255 IDeclaration decl
= getCurrentScope().lookupIdentifierRecursive(lengthName
);
1256 if (decl
instanceof IntegerDeclaration
) {
1257 return ((IntegerDeclaration
) decl
).isSigned();
1259 throw new ParseException("Is not an integer: " + lengthName
); //$NON-NLS-1$
1264 * Parses a type specifier list and returns the corresponding declaration.
1266 * @param typeSpecifierList
1267 * A TYPE_SPECIFIER_LIST node.
1268 * @param pointerList
1269 * A list of POINTER nodes that apply to the specified type.
1270 * @return The corresponding declaration.
1271 * @throws ParseException
1272 * If the type has not been defined or if there is an error
1273 * creating the declaration.
1275 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1276 List
<CommonTree
> pointerList
) throws ParseException
{
1277 IDeclaration declaration
= null;
1280 * By looking at the first element of the type specifier list, we can
1281 * determine which type it belongs to.
1283 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1285 switch (firstChild
.getType()) {
1286 case CTFParser
.FLOATING_POINT
:
1287 declaration
= parseFloat(firstChild
);
1289 case CTFParser
.INTEGER
:
1290 declaration
= parseInteger(firstChild
);
1292 case CTFParser
.STRING
:
1293 declaration
= parseString(firstChild
);
1295 case CTFParser
.STRUCT
:
1296 declaration
= parseStruct(firstChild
);
1298 case CTFParser
.VARIANT
:
1299 declaration
= parseVariant(firstChild
);
1301 case CTFParser
.ENUM
:
1302 declaration
= parseEnum(firstChild
);
1304 case CTFParser
.IDENTIFIER
:
1305 case CTFParser
.FLOATTOK
:
1306 case CTFParser
.INTTOK
:
1307 case CTFParser
.LONGTOK
:
1308 case CTFParser
.SHORTTOK
:
1309 case CTFParser
.SIGNEDTOK
:
1310 case CTFParser
.UNSIGNEDTOK
:
1311 case CTFParser
.CHARTOK
:
1312 case CTFParser
.DOUBLETOK
:
1313 case CTFParser
.VOIDTOK
:
1314 case CTFParser
.BOOLTOK
:
1315 case CTFParser
.COMPLEXTOK
:
1316 case CTFParser
.IMAGINARYTOK
:
1317 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1320 childTypeError(firstChild
);
1326 private IDeclaration
parseFloat(CommonTree floatingPoint
)
1327 throws ParseException
{
1329 List
<CommonTree
> children
= floatingPoint
.getChildren();
1332 * If the integer has no attributes, then it is missing the size
1333 * attribute which is required
1335 if (children
== null) {
1336 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1339 /* The return value */
1340 FloatDeclaration floatDeclaration
= null;
1341 ByteOrder byteOrder
= fTrace
.getByteOrder();
1346 /* Iterate on all integer children */
1347 for (CommonTree child
: children
) {
1348 switch (child
.getType()) {
1349 case CTFParser
.CTF_EXPRESSION_VAL
:
1351 * An assignment expression must have 2 children, left and right
1354 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1355 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1357 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1359 if (!isAnyUnaryString(leftStrings
.get(0))) {
1360 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1362 String left
= concatenateUnaryStrings(leftStrings
);
1364 if (left
.equals(MetadataStrings
.EXP_DIG
)) {
1365 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1366 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1367 byteOrder
= getByteOrder(rightNode
);
1368 } else if (left
.equals(MetadataStrings
.MANT_DIG
)) {
1369 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1370 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1371 alignment
= getAlignment(rightNode
);
1373 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1378 childTypeError(child
);
1382 int size
= mantissa
+ exponent
;
1384 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1387 if (alignment
== 0) {
1388 if ((size
% 8) == 0) {
1395 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1397 return floatDeclaration
;
1402 * Parses a type specifier list as a user-declared type.
1404 * @param typeSpecifierList
1405 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1406 * @param pointerList
1407 * A list of POINTER nodes that apply to the type specified in
1408 * typeSpecifierList.
1409 * @return The corresponding declaration.
1410 * @throws ParseException
1411 * If the type does not exist (has not been found).
1413 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1414 List
<CommonTree
> pointerList
) throws ParseException
{
1415 /* Create the string representation of the type declaration */
1416 String typeStringRepresentation
= createTypeDeclarationString(
1417 typeSpecifierList
, pointerList
);
1419 /* Use the string representation to search the type in the current scope */
1420 IDeclaration decl
= getCurrentScope().lookupTypeRecursive(
1421 typeStringRepresentation
);
1424 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1425 + " has not been defined."); //$NON-NLS-1$
1432 * Parses an integer declaration node.
1436 * @return The corresponding integer declaration.
1437 * @throws ParseException
1439 private IntegerDeclaration
parseInteger(CommonTree integer
)
1440 throws ParseException
{
1442 List
<CommonTree
> children
= integer
.getChildren();
1445 * If the integer has no attributes, then it is missing the size
1446 * attribute which is required
1448 if (children
== null) {
1449 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1452 /* The return value */
1453 IntegerDeclaration integerDeclaration
= null;
1454 boolean signed
= false;
1455 ByteOrder byteOrder
= fTrace
.getByteOrder();
1460 String clock
= ""; //$NON-NLS-1$
1462 Encoding encoding
= Encoding
.NONE
;
1464 /* Iterate on all integer children */
1465 for (CommonTree child
: children
) {
1466 switch (child
.getType()) {
1467 case CTFParser
.CTF_EXPRESSION_VAL
:
1469 * An assignment expression must have 2 children, left and right
1472 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1473 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1475 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1477 if (!isAnyUnaryString(leftStrings
.get(0))) {
1478 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1480 String left
= concatenateUnaryStrings(leftStrings
);
1482 if (left
.equals("signed")) { //$NON-NLS-1$
1483 signed
= getSigned(rightNode
);
1484 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1485 byteOrder
= getByteOrder(rightNode
);
1486 } else if (left
.equals("size")) { //$NON-NLS-1$
1487 size
= getSize(rightNode
);
1488 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1489 alignment
= getAlignment(rightNode
);
1490 } else if (left
.equals("base")) { //$NON-NLS-1$
1491 base
= getBase(rightNode
);
1492 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1493 encoding
= getEncoding(rightNode
);
1494 } else if (left
.equals("map")) { //$NON-NLS-1$
1495 clock
= getClock(rightNode
);
1497 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownIntegerAttributeWarning
+ " " + left
); //$NON-NLS-1$
1502 childTypeError(child
);
1508 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1511 if (alignment
== 0) {
1512 if ((size
% 8) == 0) {
1519 integerDeclaration
= IntegerDeclaration
.createDeclaration((int) size
, signed
, base
,
1520 byteOrder
, encoding
, clock
, alignment
);
1522 return integerDeclaration
;
1526 private static String
getClock(CommonTree rightNode
) {
1527 String clock
= rightNode
.getChild(1).getChild(0).getChild(0).getText();
1528 return clock
== null ?
"" : clock
; //$NON-NLS-1$
1531 private static StringDeclaration
parseString(CommonTree string
)
1532 throws ParseException
{
1534 List
<CommonTree
> children
= string
.getChildren();
1535 StringDeclaration stringDeclaration
= null;
1537 if (children
== null) {
1538 stringDeclaration
= new StringDeclaration();
1540 Encoding encoding
= Encoding
.UTF8
;
1541 for (CommonTree child
: children
) {
1542 switch (child
.getType()) {
1543 case CTFParser
.CTF_EXPRESSION_VAL
:
1545 * An assignment expression must have 2 children, left and
1549 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1550 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1552 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1554 if (!isAnyUnaryString(leftStrings
.get(0))) {
1555 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1557 String left
= concatenateUnaryStrings(leftStrings
);
1559 if (left
.equals("encoding")) { //$NON-NLS-1$
1560 encoding
= getEncoding(rightNode
);
1562 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1568 childTypeError(child
);
1573 stringDeclaration
= new StringDeclaration(encoding
);
1576 return stringDeclaration
;
1580 * Parses a struct declaration and returns the corresponding declaration.
1584 * @return The corresponding struct declaration.
1585 * @throws ParseException
1587 private StructDeclaration
parseStruct(CommonTree struct
)
1588 throws ParseException
{
1590 List
<CommonTree
> children
= struct
.getChildren();
1592 /* The return value */
1593 StructDeclaration structDeclaration
= null;
1596 String structName
= null;
1597 boolean hasName
= false;
1600 CommonTree structBody
= null;
1601 boolean hasBody
= false;
1604 long structAlign
= 0;
1606 /* Loop on all children and identify what we have to work with. */
1607 for (CommonTree child
: children
) {
1608 switch (child
.getType()) {
1609 case CTFParser
.STRUCT_NAME
: {
1612 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1614 structName
= structNameIdentifier
.getText();
1618 case CTFParser
.STRUCT_BODY
: {
1625 case CTFParser
.ALIGN
: {
1626 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1628 structAlign
= getAlignment(structAlignExpression
);
1633 childTypeError(child
);
1640 * If a struct has just a body and no name (just like the song,
1641 * "A Struct With No Name" by America (sorry for that...)), it's a
1642 * definition of a new type, so we create the type declaration and
1643 * return it. We can't add it to the declaration scope since there is no
1644 * name, but that's what we want because it won't be possible to use it
1645 * again to declare another field.
1647 * If it has just a name, we look it up in the declaration scope and
1648 * return the associated declaration. If it is not found in the
1649 * declaration scope, it means that a struct with that name has not been
1650 * declared, which is an error.
1652 * If it has both, then we create the type declaration and register it
1653 * to the current scope.
1655 * If it has none, then what are we doing here ?
1659 * If struct has a name, check if already defined in the current
1662 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1663 throw new ParseException("struct " + structName
//$NON-NLS-1$
1664 + " already defined."); //$NON-NLS-1$
1666 /* Create the declaration */
1667 structDeclaration
= new StructDeclaration(structAlign
);
1669 /* Parse the body */
1670 parseStructBody(structBody
, structDeclaration
);
1672 /* If struct has name, add it to the current scope. */
1674 getCurrentScope().registerStruct(structName
, structDeclaration
);
1676 } else /* !hasBody */{
1678 /* Name and !body */
1680 /* Lookup the name in the current scope. */
1681 structDeclaration
= getCurrentScope().lookupStructRecursive(structName
);
1684 * If not found, it means that a struct with such name has not
1687 if (structDeclaration
== null) {
1688 throw new ParseException("struct " + structName
//$NON-NLS-1$
1689 + " is not defined"); //$NON-NLS-1$
1692 /* !Name and !body */
1694 /* We can't do anything with that. */
1695 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1699 return structDeclaration
;
1703 * Parses a struct body, adding the fields to specified structure
1707 * A STRUCT_BODY node.
1708 * @param structDeclaration
1709 * The struct declaration.
1710 * @throws ParseException
1712 private void parseStructBody(CommonTree structBody
,
1713 StructDeclaration structDeclaration
) throws ParseException
{
1715 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1718 * If structDeclaration is null, structBody has no children and the
1719 * struct body is empty.
1721 if (structDeclarations
!= null) {
1724 for (CommonTree declarationNode
: structDeclarations
) {
1725 switch (declarationNode
.getType()) {
1726 case CTFParser
.TYPEALIAS
:
1727 parseTypealias(declarationNode
);
1729 case CTFParser
.TYPEDEF
:
1730 parseTypedef(declarationNode
);
1732 case CTFParser
.SV_DECLARATION
:
1733 parseStructDeclaration(declarationNode
, structDeclaration
);
1736 childTypeError(declarationNode
);
1745 * Parses a declaration found in a struct.
1747 * @param declaration
1748 * A SV_DECLARATION node.
1750 * A struct declaration. (I know, little name clash here...)
1751 * @throws ParseException
1753 private void parseStructDeclaration(CommonTree declaration
,
1754 StructDeclaration struct
) throws ParseException
{
1756 /* Get the type specifier list node */
1757 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1759 /* Get the type declarator list node */
1760 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1762 /* Get the type declarator list */
1763 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1766 * For each type declarator, parse the declaration and add a field to
1769 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1771 StringBuilder identifierSB
= new StringBuilder();
1773 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1774 typeSpecifierListNode
, identifierSB
);
1775 String fieldName
= identifierSB
.toString();
1776 getCurrentScope().registerIdentifier(fieldName
, decl
);
1778 if (struct
.hasField(fieldName
)) {
1779 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1783 struct
.addField(fieldName
, decl
);
1789 * Parses an enum declaration and returns the corresponding declaration.
1793 * @return The corresponding enum declaration.
1794 * @throws ParseException
1796 private EnumDeclaration
parseEnum(CommonTree theEnum
) throws ParseException
{
1798 List
<CommonTree
> children
= theEnum
.getChildren();
1800 /* The return value */
1801 EnumDeclaration enumDeclaration
= null;
1804 String enumName
= null;
1807 CommonTree enumBody
= null;
1809 /* Container type */
1810 IntegerDeclaration containerTypeDeclaration
= null;
1812 /* Loop on all children and identify what we have to work with. */
1813 for (CommonTree child
: children
) {
1814 switch (child
.getType()) {
1815 case CTFParser
.ENUM_NAME
: {
1816 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1817 enumName
= enumNameIdentifier
.getText();
1820 case CTFParser
.ENUM_BODY
: {
1824 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1825 containerTypeDeclaration
= parseEnumContainerType(child
);
1829 childTypeError(child
);
1835 * If the container type has not been defined explicitly, we assume it
1838 if (containerTypeDeclaration
== null) {
1839 IDeclaration enumDecl
;
1841 * it could be because the enum was already declared.
1843 if (enumName
!= null) {
1844 enumDecl
= getCurrentScope().lookupEnumRecursive(enumName
);
1845 if (enumDecl
!= null) {
1846 return (EnumDeclaration
) enumDecl
;
1850 IDeclaration decl
= getCurrentScope().lookupTypeRecursive("int"); //$NON-NLS-1$
1853 throw new ParseException("enum container type implicit and type int not defined"); //$NON-NLS-1$
1854 } else if (!(decl
instanceof IntegerDeclaration
)) {
1855 throw new ParseException("enum container type implicit and type int not an integer"); //$NON-NLS-1$
1858 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1862 * If it has a body, it's a new declaration, otherwise it's a reference
1863 * to an existing declaration. Same logic as struct.
1865 if (enumBody
!= null) {
1867 * If enum has a name, check if already defined in the current
1870 if ((enumName
!= null)
1871 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1872 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1873 + " already defined"); //$NON-NLS-1$
1876 /* Create the declaration */
1877 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1879 /* Parse the body */
1880 parseEnumBody(enumBody
, enumDeclaration
);
1882 /* If the enum has name, add it to the current scope. */
1883 if (enumName
!= null) {
1884 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1887 if (enumName
!= null) {
1888 /* Name and !body */
1890 /* Lookup the name in the current scope. */
1891 enumDeclaration
= getCurrentScope().lookupEnumRecursive(enumName
);
1894 * If not found, it means that an enum with such name has not
1897 if (enumDeclaration
== null) {
1898 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1899 + " is not defined"); //$NON-NLS-1$
1902 /* !Name and !body */
1903 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1907 return enumDeclaration
;
1912 * Parses an enum body, adding the enumerators to the specified enum
1916 * An ENUM_BODY node.
1917 * @param enumDeclaration
1918 * The enum declaration.
1919 * @throws ParseException
1921 private void parseEnumBody(CommonTree enumBody
,
1922 EnumDeclaration enumDeclaration
) throws ParseException
{
1924 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1925 /* enum body can't be empty (unlike struct). */
1930 * Start at -1, so that if the first enumrator has no explicit value, it
1935 for (CommonTree enumerator
: enumerators
) {
1936 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1945 * Parses an enumerator node and adds an enumerator declaration to an
1946 * enumeration declaration.
1948 * The high value of the range of the last enumerator is needed in case the
1949 * current enumerator does not specify its value.
1952 * An ENUM_ENUMERATOR node.
1953 * @param enumDeclaration
1954 * en enumeration declaration to which will be added the
1957 * The high value of the range of the last enumerator
1958 * @return The high value of the value range of the current enumerator.
1959 * @throws ParseException
1961 private static long parseEnumEnumerator(CommonTree enumerator
,
1962 EnumDeclaration enumDeclaration
, long lastHigh
)
1963 throws ParseException
{
1965 List
<CommonTree
> children
= enumerator
.getChildren();
1967 long low
= 0, high
= 0;
1968 boolean valueSpecified
= false;
1969 String label
= null;
1971 for (CommonTree child
: children
) {
1972 if (isAnyUnaryString(child
)) {
1973 label
= parseUnaryString(child
);
1974 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1976 valueSpecified
= true;
1978 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1980 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1982 valueSpecified
= true;
1984 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1985 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1987 childTypeError(child
);
1991 if (!valueSpecified
) {
1997 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
2000 if (!enumDeclaration
.add(low
, high
, label
)) {
2001 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
2004 if (valueSpecified
&& (BigInteger
.valueOf(low
).compareTo(enumDeclaration
.getContainerType().getMinValue()) == -1 ||
2005 BigInteger
.valueOf(high
).compareTo(enumDeclaration
.getContainerType().getMaxValue()) == 1)) {
2006 throw new ParseException("enum value is not in range"); //$NON-NLS-1$
2013 * Parses an enum container type node and returns the corresponding integer
2016 * @param enumContainerType
2017 * An ENUM_CONTAINER_TYPE node.
2018 * @return An integer declaration corresponding to the container type.
2019 * @throws ParseException
2020 * If the type does not parse correctly or if it is not an
2023 private IntegerDeclaration
parseEnumContainerType(
2024 CommonTree enumContainerType
) throws ParseException
{
2026 /* Get the child, which should be a type specifier list */
2027 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
.getChild(0);
2029 /* Parse it and get the corresponding declaration */
2030 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
2032 /* If is is an integer, return it, else throw an error */
2033 if (decl
instanceof IntegerDeclaration
) {
2034 return (IntegerDeclaration
) decl
;
2036 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
2039 private VariantDeclaration
parseVariant(CommonTree variant
)
2040 throws ParseException
{
2042 List
<CommonTree
> children
= variant
.getChildren();
2043 VariantDeclaration variantDeclaration
= null;
2045 boolean hasName
= false;
2046 String variantName
= null;
2048 boolean hasBody
= false;
2049 CommonTree variantBody
= null;
2051 boolean hasTag
= false;
2052 String variantTag
= null;
2054 for (CommonTree child
: children
) {
2055 switch (child
.getType()) {
2056 case CTFParser
.VARIANT_NAME
:
2060 CommonTree variantNameIdentifier
= (CommonTree
) child
.getChild(0);
2062 variantName
= variantNameIdentifier
.getText();
2065 case CTFParser
.VARIANT_TAG
:
2069 CommonTree variantTagIdentifier
= (CommonTree
) child
.getChild(0);
2071 variantTag
= variantTagIdentifier
.getText();
2074 case CTFParser
.VARIANT_BODY
:
2078 variantBody
= child
;
2082 childTypeError(child
);
2089 * If variant has a name, check if already defined in the current
2093 && (getCurrentScope().lookupVariant(variantName
) != null)) {
2094 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2095 + " already defined."); //$NON-NLS-1$
2098 /* Create the declaration */
2099 variantDeclaration
= new VariantDeclaration();
2101 /* Parse the body */
2102 parseVariantBody(variantBody
, variantDeclaration
);
2104 /* If variant has name, add it to the current scope. */
2106 getCurrentScope().registerVariant(variantName
,
2107 variantDeclaration
);
2109 } else /* !hasBody */{
2111 /* Name and !body */
2113 /* Lookup the name in the current scope. */
2114 variantDeclaration
= getCurrentScope().lookupVariantRecursive(
2118 * If not found, it means that a struct with such name has not
2121 if (variantDeclaration
== null) {
2122 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2123 + " is not defined"); //$NON-NLS-1$
2126 /* !Name and !body */
2128 /* We can't do anything with that. */
2129 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2134 variantDeclaration
.setTag(variantTag
);
2136 IDeclaration decl
= getCurrentScope().lookupIdentifierRecursive(variantTag
);
2138 throw new ParseException("Variant tag not found: " + variantTag
); //$NON-NLS-1$
2140 if (!(decl
instanceof EnumDeclaration
)) {
2141 throw new ParseException("Variant tag must be an enum: " + variantTag
); //$NON-NLS-1$
2143 EnumDeclaration tagDecl
= (EnumDeclaration
) decl
;
2144 Set
<String
> intersection
= new HashSet
<>(tagDecl
.getLabels());
2145 intersection
.retainAll(variantDeclaration
.getFields().keySet());
2146 if (intersection
.isEmpty()) {
2147 throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName
); //$NON-NLS-1$
2151 return variantDeclaration
;
2154 private void parseVariantBody(CommonTree variantBody
,
2155 VariantDeclaration variantDeclaration
) throws ParseException
{
2157 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2161 for (CommonTree declarationNode
: variantDeclarations
) {
2162 switch (declarationNode
.getType()) {
2163 case CTFParser
.TYPEALIAS
:
2164 parseTypealias(declarationNode
);
2166 case CTFParser
.TYPEDEF
:
2167 parseTypedef(declarationNode
);
2169 case CTFParser
.SV_DECLARATION
:
2170 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2173 childTypeError(declarationNode
);
2181 private void parseVariantDeclaration(CommonTree declaration
,
2182 VariantDeclaration variant
) throws ParseException
{
2184 /* Get the type specifier list node */
2185 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2187 /* Get the type declarator list node */
2188 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2190 /* Get the type declarator list */
2191 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
2194 * For each type declarator, parse the declaration and add a field to
2197 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2199 StringBuilder identifierSB
= new StringBuilder();
2201 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2202 typeSpecifierListNode
, identifierSB
);
2204 String name
= identifierSB
.toString();
2206 if (variant
.hasField(name
)) {
2207 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2211 getCurrentScope().registerIdentifier(name
, decl
);
2213 variant
.addField(name
, decl
);
2218 * Creates the string representation of a type declaration (type specifier
2221 * @param typeSpecifierList
2222 * A TYPE_SPECIFIER_LIST node.
2224 * A list of POINTER nodes.
2225 * @return The string representation.
2226 * @throws ParseException
2228 private static String
createTypeDeclarationString(
2229 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2230 throws ParseException
{
2231 StringBuilder sb
= new StringBuilder();
2233 createTypeSpecifierListString(typeSpecifierList
, sb
);
2234 createPointerListString(pointers
, sb
);
2236 return sb
.toString();
2240 * Creates the string representation of a list of type specifiers.
2242 * @param typeSpecifierList
2243 * A TYPE_SPECIFIER_LIST node.
2245 * A StringBuilder to which will be appended the string.
2246 * @throws ParseException
2248 private static void createTypeSpecifierListString(
2249 CommonTree typeSpecifierList
, StringBuilder sb
)
2250 throws ParseException
{
2252 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2254 boolean firstItem
= true;
2256 for (CommonTree child
: children
) {
2264 /* Append the string that represents this type specifier. */
2265 createTypeSpecifierString(child
, sb
);
2270 * Creates the string representation of a type specifier.
2272 * @param typeSpecifier
2273 * A TYPE_SPECIFIER node.
2275 * A StringBuilder to which will be appended the string.
2276 * @throws ParseException
2278 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2279 StringBuilder sb
) throws ParseException
{
2280 switch (typeSpecifier
.getType()) {
2281 case CTFParser
.FLOATTOK
:
2282 case CTFParser
.INTTOK
:
2283 case CTFParser
.LONGTOK
:
2284 case CTFParser
.SHORTTOK
:
2285 case CTFParser
.SIGNEDTOK
:
2286 case CTFParser
.UNSIGNEDTOK
:
2287 case CTFParser
.CHARTOK
:
2288 case CTFParser
.DOUBLETOK
:
2289 case CTFParser
.VOIDTOK
:
2290 case CTFParser
.BOOLTOK
:
2291 case CTFParser
.COMPLEXTOK
:
2292 case CTFParser
.IMAGINARYTOK
:
2293 case CTFParser
.CONSTTOK
:
2294 case CTFParser
.IDENTIFIER
:
2295 sb
.append(typeSpecifier
.getText());
2297 case CTFParser
.STRUCT
: {
2298 CommonTree structName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2299 if (structName
== null) {
2300 throw new ParseException("nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2303 CommonTree structNameIdentifier
= (CommonTree
) structName
.getChild(0);
2305 sb
.append(structNameIdentifier
.getText());
2308 case CTFParser
.VARIANT
: {
2309 CommonTree variantName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2310 if (variantName
== null) {
2311 throw new ParseException("nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2314 CommonTree variantNameIdentifier
= (CommonTree
) variantName
.getChild(0);
2316 sb
.append(variantNameIdentifier
.getText());
2319 case CTFParser
.ENUM
: {
2320 CommonTree enumName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.ENUM_NAME
);
2321 if (enumName
== null) {
2322 throw new ParseException("nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2325 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2327 sb
.append(enumNameIdentifier
.getText());
2330 case CTFParser
.FLOATING_POINT
:
2331 case CTFParser
.INTEGER
:
2332 case CTFParser
.STRING
:
2333 throw new ParseException("CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2335 childTypeError(typeSpecifier
);
2341 * Creates the string representation of a list of pointers.
2343 * @param pointerList
2344 * A list of pointer nodes. If pointerList is null, this function
2347 * A stringbuilder to which will be appended the string.
2349 private static void createPointerListString(List
<CommonTree
> pointerList
,
2351 if (pointerList
== null) {
2355 for (CommonTree pointer
: pointerList
) {
2357 sb
.append(" *"); //$NON-NLS-1$
2358 if (pointer
.getChildCount() > 0) {
2360 sb
.append(" const"); //$NON-NLS-1$
2367 * The node to check.
2368 * @return True if the given node is an unary string.
2370 private static boolean isUnaryString(CommonTree node
) {
2371 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
));
2376 * The node to check.
2377 * @return True if the given node is any type of unary string (no quotes,
2380 private static boolean isAnyUnaryString(CommonTree node
) {
2381 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2386 * The node to check.
2387 * @return True if the given node is an unary integer.
2389 private static boolean isUnaryInteger(CommonTree node
) {
2390 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) ||
2391 (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) || (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2395 * Parses a unary string node and return the string value.
2397 * @param unaryString
2398 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2399 * or UNARY_EXPRESSION_STRING_QUOTES).
2400 * @return The string value.
2403 * It would be really nice to remove the quotes earlier, such as in the
2406 private static String
parseUnaryString(CommonTree unaryString
) {
2408 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2409 String strval
= value
.getText();
2412 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2413 strval
= strval
.substring(1, strval
.length() - 1);
2420 * Parses an unary integer (dec, hex or oct).
2422 * @param unaryInteger
2423 * An unary integer node.
2424 * @return The integer value.
2425 * @throws ParseException
2426 * on an invalid integer format ("bob" for example)
2428 private static long parseUnaryInteger(CommonTree unaryInteger
) throws ParseException
{
2430 List
<CommonTree
> children
= unaryInteger
.getChildren();
2431 CommonTree value
= children
.get(0);
2432 String strval
= value
.getText();
2436 intval
= Long
.decode(strval
);
2437 } catch (NumberFormatException e
) {
2438 throw new ParseException("Invalid integer format: " + strval
); //$NON-NLS-1$
2441 /* The rest of children are sign */
2442 if ((children
.size() % 2) == 0) {
2448 private static long getMajorOrMinor(CommonTree rightNode
)
2449 throws ParseException
{
2451 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2453 if (isUnaryInteger(firstChild
)) {
2454 if (rightNode
.getChildCount() > 1) {
2455 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2458 long m
= parseUnaryInteger(firstChild
);
2461 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2466 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2469 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2471 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2473 if (isAnyUnaryString(firstChild
)) {
2474 if (rightNode
.getChildCount() > 1) {
2475 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2478 String uuidstr
= parseUnaryString(firstChild
);
2481 return UUID
.fromString(uuidstr
);
2482 } catch (IllegalArgumentException e
) {
2483 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2486 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2490 * Gets the value of a "signed" integer attribute.
2494 * @return The "signed" value as a boolean.
2495 * @throws ParseException
2497 private static boolean getSigned(CommonTree rightNode
)
2498 throws ParseException
{
2500 boolean ret
= false;
2501 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2503 if (isUnaryString(firstChild
)) {
2504 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2506 if (strval
.equals(MetadataStrings
.TRUE
)
2507 || strval
.equals(MetadataStrings
.TRUE2
)) {
2509 } else if (strval
.equals(MetadataStrings
.FALSE
)
2510 || strval
.equals(MetadataStrings
.FALSE2
)) {
2513 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2514 + firstChild
.getChild(0).getText());
2516 } else if (isUnaryInteger(firstChild
)) {
2517 /* Happens if the value is something like "1234.hello" */
2518 if (rightNode
.getChildCount() > 1) {
2519 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2522 long intval
= parseUnaryInteger(firstChild
);
2526 } else if (intval
== 0) {
2529 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2530 + firstChild
.getChild(0).getText());
2533 throw new ParseException();
2540 * Gets the value of a "byte_order" integer attribute.
2544 * @return The "byte_order" value.
2545 * @throws ParseException
2547 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2549 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2551 if (isUnaryString(firstChild
)) {
2552 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2554 if (strval
.equals(MetadataStrings
.LE
)) {
2555 return ByteOrder
.LITTLE_ENDIAN
;
2556 } else if (strval
.equals(MetadataStrings
.BE
)
2557 || strval
.equals(MetadataStrings
.NETWORK
)) {
2558 return ByteOrder
.BIG_ENDIAN
;
2559 } else if (strval
.equals(MetadataStrings
.NATIVE
)) {
2560 return fTrace
.getByteOrder();
2562 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2565 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2569 * Determines if the given value is a valid alignment value.
2572 * The value to check.
2573 * @return True if it is valid.
2575 private static boolean isValidAlignment(long alignment
) {
2576 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2580 * Gets the value of a "size" integer attribute.
2584 * @return The "size" value.
2585 * @throws ParseException
2587 private static long getSize(CommonTree rightNode
) throws ParseException
{
2589 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2591 if (isUnaryInteger(firstChild
)) {
2592 if (rightNode
.getChildCount() > 1) {
2593 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2596 long size
= parseUnaryInteger(firstChild
);
2599 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2604 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2608 * Gets the value of a "align" integer or struct attribute.
2611 * A CTF_RIGHT node or directly an unary integer.
2612 * @return The align value.
2613 * @throws ParseException
2615 private static long getAlignment(CommonTree node
) throws ParseException
{
2618 * If a CTF_RIGHT node was passed, call getAlignment with the first
2621 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2622 if (node
.getChildCount() > 1) {
2623 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2626 return getAlignment((CommonTree
) node
.getChild(0));
2627 } else if (isUnaryInteger(node
)) {
2628 long alignment
= parseUnaryInteger(node
);
2630 if (!isValidAlignment(alignment
)) {
2631 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2637 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2641 * Gets the value of a "base" integer attribute.
2644 * An CTF_RIGHT node.
2645 * @return The "base" value.
2646 * @throws ParseException
2648 private static int getBase(CommonTree rightNode
) throws ParseException
{
2650 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2652 if (isUnaryInteger(firstChild
)) {
2653 if (rightNode
.getChildCount() > 1) {
2654 throw new ParseException("invalid base value"); //$NON-NLS-1$
2657 long intval
= parseUnaryInteger(firstChild
);
2658 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2659 || (intval
== 16)) {
2660 return (int) intval
;
2662 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2663 } else if (isUnaryString(firstChild
)) {
2664 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2666 if (strval
.equals(MetadataStrings
.DECIMAL
)
2667 || strval
.equals(MetadataStrings
.DEC
)
2668 || strval
.equals(MetadataStrings
.DEC_CTE
)
2669 || strval
.equals(MetadataStrings
.INT_MOD
)
2670 || strval
.equals(MetadataStrings
.UNSIGNED_CTE
)) {
2672 } else if (strval
.equals(MetadataStrings
.HEXADECIMAL
)
2673 || strval
.equals(MetadataStrings
.HEX
)
2674 || strval
.equals(MetadataStrings
.X
)
2675 || strval
.equals(MetadataStrings
.X2
)
2676 || strval
.equals(MetadataStrings
.POINTER
)) {
2678 } else if (strval
.equals(MetadataStrings
.OCTAL
)
2679 || strval
.equals(MetadataStrings
.OCT
)
2680 || strval
.equals(MetadataStrings
.OCTAL_CTE
)) {
2682 } else if (strval
.equals(MetadataStrings
.BINARY
)
2683 || strval
.equals(MetadataStrings
.BIN
)) {
2686 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2689 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2694 * Gets the value of an "encoding" integer attribute.
2698 * @return The "encoding" value.
2699 * @throws ParseException
2702 private static Encoding
getEncoding(CommonTree rightNode
)
2703 throws ParseException
{
2705 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2707 if (isUnaryString(firstChild
)) {
2708 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2710 if (strval
.equals(MetadataStrings
.UTF8
)) {
2711 return Encoding
.UTF8
;
2712 } else if (strval
.equals(MetadataStrings
.ASCII
)) {
2713 return Encoding
.ASCII
;
2714 } else if (strval
.equals(MetadataStrings
.NONE
)) {
2715 return Encoding
.NONE
;
2717 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2720 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2723 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2725 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2727 if (isUnaryInteger(firstChild
)) {
2728 if (rightNode
.getChildCount() > 1) {
2729 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2732 long intval
= parseUnaryInteger(firstChild
);
2736 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2739 private static String
getEventName(CommonTree rightNode
)
2740 throws ParseException
{
2742 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2744 if (isAnyUnaryString(firstChild
)) {
2745 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2749 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2752 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2754 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2756 if (isUnaryInteger(firstChild
)) {
2757 if (rightNode
.getChildCount() > 1) {
2758 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2761 long intval
= parseUnaryInteger(firstChild
);
2765 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2769 * Concatenates a list of unary strings separated by arrows (->) or dots.
2772 * A list, first element being an unary string, subsequent
2773 * elements being ARROW or DOT nodes with unary strings as child.
2774 * @return The string representation of the unary string chain.
2776 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2778 StringBuilder sb
= new StringBuilder();
2780 CommonTree first
= strings
.get(0);
2781 sb
.append(parseUnaryString(first
));
2783 boolean isFirst
= true;
2785 for (CommonTree ref
: strings
) {
2791 CommonTree id
= (CommonTree
) ref
.getChild(0);
2793 if (ref
.getType() == CTFParser
.ARROW
) {
2794 sb
.append("->"); //$NON-NLS-1$
2799 sb
.append(parseUnaryString(id
));
2802 return sb
.toString();
2806 * Throws a ParseException stating that the parent-child relation between
2807 * the given node and its parent is not valid. It means that the shape of
2808 * the AST is unexpected.
2811 * The invalid child node.
2812 * @throws ParseException
2814 private static void childTypeError(CommonTree child
) throws ParseException
{
2815 CommonTree parent
= (CommonTree
) child
.getParent();
2816 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2817 + " can't have a child of type " //$NON-NLS-1$
2818 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2820 throw new ParseException(error
);
2823 // ------------------------------------------------------------------------
2825 // ------------------------------------------------------------------------
2828 * Adds a new declaration scope on the top of the scope stack.
2830 private void pushScope() {
2831 fScope
= new DeclarationScope(fScope
);
2835 * Removes the top declaration scope from the scope stack.
2837 private void popScope() {
2838 fScope
= fScope
.getParentScope();
2842 * Returns the current declaration scope.
2844 * @return The current declaration scope.
2846 private DeclarationScope
getCurrentScope() {