1 /*******************************************************************************
2 * Copyright (c) 2011-2012 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
9 * Contributors: Matthew Khouzam - Initial Design and Grammar
10 * Contributors: Francis Giraldeau - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
;
15 import java
.io
.FileNotFoundException
;
16 import java
.io
.IOException
;
17 import java
.io
.UnsupportedEncodingException
;
18 import java
.nio
.ByteOrder
;
19 import java
.util
.ArrayList
;
20 import java
.util
.Collections
;
21 import java
.util
.LinkedList
;
22 import java
.util
.List
;
23 import java
.util
.UUID
;
25 import org
.antlr
.runtime
.tree
.CommonTree
;
26 import org
.eclipse
.linuxtools
.ctf
.core
.event
.CTFClock
;
27 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDeclaration
;
28 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDeclaration
;
29 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Encoding
;
30 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDeclaration
;
31 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.FloatDeclaration
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDeclaration
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDeclaration
;
36 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
37 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
38 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
39 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
40 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
41 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.Stream
;
44 * Asserts throughout this class denote the assumptions we can make because of
45 * the way the grammar generates the AST.
47 * There is also an assert at the beginning of each function that receives a
48 * tree node to make sure that the node is indeed of the type the function is
52 * Suppress unchecked warnings for things like List<CommonTree> children =
53 * root.getChildren(), because ANTLR doesn't know what generics are.
56 * <b><u>IOStructGen</u></b>
58 @SuppressWarnings("unchecked")
59 public class IOStructGen
{
61 // ------------------------------------------------------------------------
63 // ------------------------------------------------------------------------
65 static private final boolean DEBUG_
= false;
70 private final CTFTrace trace
;
71 private final CommonTree tree
;
74 * The current declaration scope.
76 private DeclarationScope scope
= null;
78 // ------------------------------------------------------------------------
80 // ------------------------------------------------------------------------
82 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
87 public void generate() throws ParseException
{
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
96 * Parse the root node.
100 * @throws ParseException
102 private void parseRoot(CommonTree root
) throws ParseException
{
103 assert (root
.getType() == CTFParser
.ROOT
);
105 List
<CommonTree
> children
= root
.getChildren();
106 assert (children
!= null);
107 java
.io
.FileOutputStream fos
= null;
108 java
.io
.OutputStreamWriter out
= null;
111 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
112 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
113 } catch (FileNotFoundException e
) {
116 } catch (UnsupportedEncodingException e
) {
122 CommonTree traceNode
= null;
123 List
<CommonTree
> streams
= new ArrayList
<CommonTree
>();
124 List
<CommonTree
> events
= new ArrayList
<CommonTree
>();
125 List
<CommonTree
> declarations
= new ArrayList
<CommonTree
>();
126 List
<CommonTree
> environments
= new ArrayList
<CommonTree
>();
127 List
<CommonTree
> clocks
= new ArrayList
<CommonTree
>();
128 /* Create a new declaration scope with no parent. */
132 for (CommonTree child
: children
) {
134 out
.write(child
.toString()
135 + " -> " + child
.getType() + '\n'); //$NON-NLS-1$
137 switch (child
.getType()) {
138 case CTFParser
.DECLARATION
:
139 declarations
.add(child
);
141 case CTFParser
.TRACE
:
142 if (traceNode
!= null) {
143 throw new ParseException(
144 "Only one trace block is allowed"); //$NON-NLS-1$
148 case CTFParser
.STREAM
:
151 case CTFParser
.EVENT
:
154 case CTFParser
.CLOCK
:
158 environments
.add(child
);
161 childTypeError(child
);
166 out
.write("Environments\n"); //$NON-NLS-1$
168 for (CommonTree environment
: environments
) {
169 parseEnvironment(environment
);
172 out
.write("Clocks\n"); //$NON-NLS-1$
174 for (CommonTree clock
: clocks
) {
178 out
.write("Declarations\n"); //$NON-NLS-1$
180 for (CommonTree decl
: declarations
) {
182 out
.write(decl
.toString() + '\n');
184 parseRootDeclaration(decl
);
187 if (traceNode
== null) {
188 throw new ParseException("Missing trace block"); //$NON-NLS-1$
191 parseTrace(traceNode
);
194 out
.write("Streams\n"); //$NON-NLS-1$
196 if (streams
.size() > 0) {
197 for (CommonTree stream
: streams
) {
200 out
.write(stream
.toString() + '\n');
201 } catch (IOException e
) {
208 /* Add an empty stream that will have a null id */
209 trace
.addStream(new Stream(trace
));
213 out
.write("Events\n"); //$NON-NLS-1$
215 for (CommonTree event
: events
) {
218 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1)
219 .getChild(0).getChild(0);
220 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1)
221 .getChild(0).getChild(0);
222 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
230 } catch (IOException e
) {
236 private void parseEnvironment(CommonTree environment
) {
237 List
<CommonTree
> children
= environment
.getChildren();
238 for (CommonTree child
: children
) {
241 left
= child
.getChild(0).getChild(0).getChild(0).getText();
242 right
= child
.getChild(1).getChild(0).getChild(0).getText();
243 trace
.addEnvironmentVar(left
, right
);
247 private void parseClock(CommonTree clock
) {
248 List
<CommonTree
> children
= clock
.getChildren();
249 CTFClock ctfClock
= new CTFClock();
250 for (CommonTree child
: children
) {
251 final String key
= child
.getChild(0).getChild(0).getChild(0)
253 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
254 final int type
= value
.getType();
256 case CTFParser
.INTEGER
:
257 case CTFParser
.DECIMAL_LITERAL
:
259 * Not a pretty hack, this is to make sure that there is no number
260 * overflow due to 63 bit integers. The offset should only really
261 * be an issue in the year 2262. the tracer in C/ASM can write an offset in
262 * an unsigned 64 bit long. In java, the last bit, being set to 1 will
263 * be read as a negative number, but since it is too big a positive it will
264 * throw an exception. this will happen in 2^63 ns from 1970.
265 * Therefore 293 years from 1970
269 numValue
= Long
.parseLong(value
.getText());
273 numValue
= 1330938566783103277L;
275 ctfClock
.addAttribute(key
, numValue
);
278 ctfClock
.addAttribute(key
, value
.getText());
282 String NameValue
= ctfClock
.getName();
283 trace
.addClock(NameValue
, ctfClock
);
286 private void parseTrace(CommonTree traceNode
) throws ParseException
{
287 assert (traceNode
.getType() == CTFParser
.TRACE
);
289 List
<CommonTree
> children
= traceNode
.getChildren();
290 if (children
== null) {
291 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
296 for (CommonTree child
: children
) {
297 switch (child
.getType()) {
298 case CTFParser
.TYPEALIAS
:
299 parseTypealias(child
);
301 case CTFParser
.TYPEDEF
:
304 case CTFParser
.CTF_EXPRESSION_TYPE
:
305 case CTFParser
.CTF_EXPRESSION_VAL
:
306 parseTraceDeclaration(child
);
309 childTypeError(child
);
315 * If trace byte order was not specified and not using packet based
318 if (trace
.getByteOrder() == null) {
319 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
325 private void parseTraceDeclaration(CommonTree traceDecl
)
326 throws ParseException
{
327 assert ((traceDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (traceDecl
328 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
330 /* There should be a left and right */
331 assert (traceDecl
.getChildCount() == 2);
333 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
334 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
335 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
336 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
338 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
339 assert (leftStrings
!= null);
341 if (!isUnaryString(leftStrings
.get(0))) {
342 throw new ParseException(
343 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
346 String left
= concatenateUnaryStrings(leftStrings
);
348 if (left
.equals(CTFStrings
.MAJOR
)) {
349 if (trace
.majortIsSet()) {
350 throw new ParseException("major is already set"); //$NON-NLS-1$
353 trace
.setMajor(getMajorOrMinor(rightNode
));
354 } else if (left
.equals(CTFStrings
.MINOR
)) {
355 if (trace
.minorIsSet()) {
356 throw new ParseException("minor is already set"); //$NON-NLS-1$
359 trace
.setMinor(getMajorOrMinor(rightNode
));
360 } else if (left
.equals(CTFStrings
.UUID_STRING
)) {
361 UUID uuid
= getUUID(rightNode
);
364 * If uuid was already set by a metadata packet, compare it to see
367 if (trace
.UUIDIsSet()) {
368 if (trace
.getUUID().compareTo(uuid
) != 0) {
369 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
370 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
376 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
377 ByteOrder byteOrder
= getByteOrder(rightNode
);
380 * If byte order was already set by a metadata packet, compare it to
383 if (trace
.getByteOrder() != null) {
384 if (trace
.getByteOrder() != byteOrder
) {
385 throw new ParseException(
386 "Endianness mismatch. Magic number says " //$NON-NLS-1$
387 + trace
.getByteOrder()
388 + " but metadata says " + byteOrder
); //$NON-NLS-1$
391 trace
.setByteOrder(byteOrder
);
393 } else if (left
.equals(CTFStrings
.PACKET_HEADER
)) {
394 if (trace
.packetHeaderIsSet()) {
395 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
398 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
400 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
401 throw new ParseException(
402 "packet.header expects a type specifier"); //$NON-NLS-1$
405 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
406 typeSpecifier
, null);
408 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
409 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
412 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
414 throw new ParseException("Unknown trace attribute : " + left
); //$NON-NLS-1$
418 private void parseStream(CommonTree streamNode
) throws ParseException
{
419 assert (streamNode
.getType() == CTFParser
.STREAM
);
421 Stream stream
= new Stream(trace
);
423 List
<CommonTree
> children
= streamNode
.getChildren();
424 if (children
== null) {
425 throw new ParseException("Empty stream block"); //$NON-NLS-1$
430 for (CommonTree child
: children
) {
431 switch (child
.getType()) {
432 case CTFParser
.TYPEALIAS
:
433 parseTypealias(child
);
435 case CTFParser
.TYPEDEF
:
438 case CTFParser
.CTF_EXPRESSION_TYPE
:
439 case CTFParser
.CTF_EXPRESSION_VAL
:
440 parseStreamDeclaration(child
, stream
);
443 childTypeError(child
);
448 if (stream
.idIsSet()) {
449 if (!trace
.packetHeaderIsSet()
450 || !trace
.getPacketHeader().hasField(CTFStrings
.STREAM_ID
)) {
451 throw new ParseException(
452 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
456 trace
.addStream(stream
);
461 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
462 throws ParseException
{
463 assert ((streamDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (streamDecl
464 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
466 /* There should be a left and right */
467 assert (streamDecl
.getChildCount() == 2);
469 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
470 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
471 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
472 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
474 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
475 assert (leftStrings
!= null);
477 if (!isUnaryString(leftStrings
.get(0))) {
478 throw new ParseException(
479 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
482 String left
= concatenateUnaryStrings(leftStrings
);
484 if (left
.equals(CTFStrings
.ID
)) {
485 if (stream
.idIsSet()) {
486 throw new ParseException("stream id already defined"); //$NON-NLS-1$
489 long streamID
= getStreamID(rightNode
);
491 stream
.setId(streamID
);
492 } else if (left
.equals(CTFStrings
.EVENT_HEADER
)) {
493 if (stream
.eventHeaderIsSet()) {
494 throw new ParseException("event.header already defined"); //$NON-NLS-1$
497 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
499 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
500 throw new ParseException(
501 "event.header expects a type specifier"); //$NON-NLS-1$
504 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
505 typeSpecifier
, null);
507 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
508 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
511 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
512 } else if (left
.equals(CTFStrings
.EVENT_CONTEXT
)) {
513 if (stream
.eventContextIsSet()) {
514 throw new ParseException("event.context already defined"); //$NON-NLS-1$
517 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
519 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
520 throw new ParseException(
521 "event.context expects a type specifier"); //$NON-NLS-1$
524 IDeclaration eventContextDecl
= parseTypeSpecifierList(
525 typeSpecifier
, null);
527 if (!(eventContextDecl
instanceof StructDeclaration
)) {
528 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
531 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
532 } else if (left
.equals(CTFStrings
.PACKET_CONTEXT
)) {
533 if (stream
.packetContextIsSet()) {
534 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
537 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
539 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
540 throw new ParseException(
541 "packet.context expects a type specifier"); //$NON-NLS-1$
544 IDeclaration packetContextDecl
= parseTypeSpecifierList(
545 typeSpecifier
, null);
547 if (!(packetContextDecl
instanceof StructDeclaration
)) {
548 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
551 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
553 throw new ParseException("Unknown stream attribute : " + left
); //$NON-NLS-1$
557 private void parseEvent(CommonTree eventNode
) throws ParseException
{
558 assert (eventNode
.getType() == CTFParser
.EVENT
);
560 List
<CommonTree
> children
= eventNode
.getChildren();
561 if (children
== null) {
562 throw new ParseException("Empty event block"); //$NON-NLS-1$
565 EventDeclaration event
= new EventDeclaration();
569 for (CommonTree child
: children
) {
570 switch (child
.getType()) {
571 case CTFParser
.TYPEALIAS
:
572 parseTypealias(child
);
574 case CTFParser
.TYPEDEF
:
577 case CTFParser
.CTF_EXPRESSION_TYPE
:
578 case CTFParser
.CTF_EXPRESSION_VAL
:
579 parseEventDeclaration(child
, event
);
582 childTypeError(child
);
587 if (!event
.nameIsSet()) {
588 throw new ParseException("Event name not set"); //$NON-NLS-1$
592 * If the event did not specify a stream, then the trace must be single
595 if (!event
.streamIsSet()) {
596 if (trace
.nbStreams() > 1) {
597 throw new ParseException(
598 "Event without stream_id with more than one stream"); //$NON-NLS-1$
602 * If the event did not specify a stream, the only existing stream
603 * must not have an id. Note: That behavior could be changed, it
604 * could be possible to just get the only existing stream, whatever
607 Stream stream
= trace
.getStream(null);
609 if (stream
!= null) {
610 event
.setStream(stream
);
612 throw new ParseException(
613 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
618 * Add the event to the stream.
620 event
.getStream().addEvent(event
);
625 private void parseEventDeclaration(CommonTree eventDecl
,
626 EventDeclaration event
) throws ParseException
{
627 assert ((eventDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (eventDecl
628 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
630 /* There should be a left and right */
631 assert (eventDecl
.getChildCount() == 2);
633 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
634 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
635 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
636 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
638 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
639 assert (leftStrings
!= null);
641 if (!isUnaryString(leftStrings
.get(0))) {
642 throw new ParseException(
643 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
646 String left
= concatenateUnaryStrings(leftStrings
);
648 if (left
.equals(CTFStrings
.NAME2
)) {
649 if (event
.nameIsSet()) {
650 throw new ParseException("name already defined"); //$NON-NLS-1$
653 String name
= getEventName(rightNode
);
656 } else if (left
.equals(CTFStrings
.ID
)) {
657 if (event
.idIsSet()) {
658 throw new ParseException("id already defined"); //$NON-NLS-1$
661 long id
= getEventID(rightNode
);
664 } else if (left
.equals(CTFStrings
.STREAM_ID
)) {
665 if (event
.streamIsSet()) {
666 throw new ParseException("stream id already defined"); //$NON-NLS-1$
669 long streamId
= getStreamID(rightNode
);
671 Stream stream
= trace
.getStream(streamId
);
673 if (stream
== null) {
674 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
677 event
.setStream(stream
);
678 } else if (left
.equals(CTFStrings
.CONTEXT
)) {
679 if (event
.contextIsSet()) {
680 throw new ParseException("context already defined"); //$NON-NLS-1$
683 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
685 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
686 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
689 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
692 if (!(contextDecl
instanceof StructDeclaration
)) {
693 throw new ParseException("context expects a struct"); //$NON-NLS-1$
696 event
.setContext((StructDeclaration
) contextDecl
);
697 } else if (left
.equals(CTFStrings
.FIELDS_STRING
)) {
698 if (event
.fieldsIsSet()) {
699 throw new ParseException("fields already defined"); //$NON-NLS-1$
702 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
704 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
705 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
708 IDeclaration fieldsDecl
;
709 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
711 if (!(fieldsDecl
instanceof StructDeclaration
)) {
712 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
715 * The underscores in the event names.
716 * These underscores were added by the LTTng tracer.
718 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
719 event
.setFields(fields
);
721 else if (left
.equals(CTFStrings
.LOGLEVEL2
)){
723 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0)) ;
724 event
.setLogLevel(logLevel
);
726 throw new ParseException("Unknown event attribute : " + left
); //$NON-NLS-1$
731 * Parses a declaration at the root level.
734 * The declaration subtree.
735 * @throws ParseException
737 private void parseRootDeclaration(CommonTree declaration
)
738 throws ParseException
{
739 assert (declaration
.getType() == CTFParser
.DECLARATION
);
741 List
<CommonTree
> children
= declaration
.getChildren();
742 assert (children
!= null);
744 for (CommonTree child
: children
) {
745 switch (child
.getType()) {
746 case CTFParser
.TYPEDEF
:
749 case CTFParser
.TYPEALIAS
:
750 parseTypealias(child
);
752 case CTFParser
.TYPE_SPECIFIER_LIST
:
753 parseTypeSpecifierList(child
, null);
756 childTypeError(child
);
762 * Parses a typealias node. It parses the target, the alias, and registers
763 * the type in the current scope.
767 * @throws ParseException
769 private void parseTypealias(CommonTree typealias
) throws ParseException
{
770 assert (typealias
.getType() == CTFParser
.TYPEALIAS
);
772 List
<CommonTree
> children
= typealias
.getChildren();
773 assert (children
!= null);
775 CommonTree target
= null;
776 CommonTree alias
= null;
778 for (CommonTree child
: children
) {
779 switch (child
.getType()) {
780 case CTFParser
.TYPEALIAS_TARGET
:
781 assert (target
== null);
784 case CTFParser
.TYPEALIAS_ALIAS
:
785 assert (alias
== null);
789 childTypeError(child
);
794 assert (target
!= null);
795 assert (alias
!= null);
797 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
799 if (targetDeclaration
instanceof VariantDeclaration
) {
800 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
801 throw new ParseException(
802 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
806 String aliasString
= parseTypealiasAlias(alias
);
808 getCurrentScope().registerType(aliasString
, targetDeclaration
);
812 * Parses the target part of a typealias and gets the corresponding
816 * A TYPEALIAS_TARGET node.
817 * @return The corresponding declaration.
818 * @throws ParseException
820 private IDeclaration
parseTypealiasTarget(CommonTree target
)
821 throws ParseException
{
822 assert (target
.getType() == CTFParser
.TYPEALIAS_TARGET
);
824 List
<CommonTree
> children
= target
.getChildren();
825 assert (children
!= null);
827 CommonTree typeSpecifierList
= null;
828 CommonTree typeDeclaratorList
= null;
829 CommonTree typeDeclarator
= null;
830 StringBuilder identifierSB
= new StringBuilder();
832 for (CommonTree child
: children
) {
833 switch (child
.getType()) {
834 case CTFParser
.TYPE_SPECIFIER_LIST
:
835 assert (typeSpecifierList
== null);
836 typeSpecifierList
= child
;
838 case CTFParser
.TYPE_DECLARATOR_LIST
:
839 assert (typeDeclaratorList
== null);
840 typeDeclaratorList
= child
;
843 childTypeError(child
);
848 assert (typeSpecifierList
!= null);
850 if (typeDeclaratorList
!= null) {
852 * Only allow one declarator
854 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
855 * otherwise the new type puint8_t would maps to two different
858 if (typeDeclaratorList
.getChildCount() != 1) {
859 throw new ParseException(
860 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
863 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
866 /* Parse the target type and get the declaration */
867 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
868 typeSpecifierList
, identifierSB
);
871 * We don't allow identifier in the target
873 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
876 if (identifierSB
.length() > 0) {
877 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
878 + ") not expected in the typealias target"); //$NON-NLS-1$
881 return targetDeclaration
;
885 * Parses the alias part of a typealias. It parses the underlying specifier
886 * list and declarator and creates the string representation that will be
887 * used to register the type.
890 * A TYPEALIAS_ALIAS node.
891 * @return The string representation of the alias.
892 * @throws ParseException
894 private static String
parseTypealiasAlias(CommonTree alias
)
895 throws ParseException
{
896 assert (alias
.getType() == CTFParser
.TYPEALIAS_ALIAS
);
898 List
<CommonTree
> children
= alias
.getChildren();
899 assert (children
!= null);
901 CommonTree typeSpecifierList
= null;
902 CommonTree typeDeclaratorList
= null;
903 CommonTree typeDeclarator
= null;
904 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
906 for (CommonTree child
: children
) {
907 switch (child
.getType()) {
908 case CTFParser
.TYPE_SPECIFIER_LIST
:
909 assert (typeSpecifierList
== null);
910 typeSpecifierList
= child
;
912 case CTFParser
.TYPE_DECLARATOR_LIST
:
913 assert (typeDeclaratorList
== null);
914 typeDeclaratorList
= child
;
917 childTypeError(child
);
922 /* If there is a type declarator list, extract the pointers */
923 if (typeDeclaratorList
!= null) {
925 * Only allow one declarator
927 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
929 if (typeDeclaratorList
.getChildCount() != 1) {
930 throw new ParseException(
931 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
934 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
936 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
938 assert (typeDeclaratorChildren
!= null);
940 for (CommonTree child
: typeDeclaratorChildren
) {
941 switch (child
.getType()) {
942 case CTFParser
.POINTER
:
945 case CTFParser
.IDENTIFIER
:
946 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
947 + ") not expected in the typealias target"); //$NON-NLS-1$
950 childTypeError(child
);
956 return createTypeDeclarationString(typeSpecifierList
, pointers
);
960 * Parses a typedef node. This creates and registers a new declaration for
961 * each declarator found in the typedef.
965 * @throws ParseException
966 * If there is an error creating the declaration.
968 private void parseTypedef(CommonTree typedef
) throws ParseException
{
969 assert (typedef
.getType() == CTFParser
.TYPEDEF
);
971 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
972 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
973 assert (typeDeclaratorListNode
!= null);
975 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
976 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
977 assert (typeSpecifierListNode
!= null);
979 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
981 assert (typeDeclaratorList
!= null);
983 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
984 StringBuilder identifierSB
= new StringBuilder();
986 IDeclaration type_declaration
= parseTypeDeclarator(
987 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
989 if (type_declaration
instanceof VariantDeclaration
) {
990 if (((VariantDeclaration
) type_declaration
).isTagged()) {
991 throw new ParseException(
992 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
996 getCurrentScope().registerType(identifierSB
.toString(),
1002 * Parses a pair type declarator / type specifier list and returns the
1003 * corresponding declaration. If it is present, it also writes the
1004 * identifier of the declarator in the given {@link StringBuilder}.
1006 * @param typeDeclarator
1007 * A TYPE_DECLARATOR node.
1008 * @param typeSpecifierList
1009 * A TYPE_SPECIFIER_LIST node.
1010 * @param identifierSB
1011 * A StringBuilder that will receive the identifier found in the
1013 * @return The corresponding declaration.
1014 * @throws ParseException
1015 * If there is an error finding or creating the declaration.
1017 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1018 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1019 throws ParseException
{
1020 if (typeDeclarator
!= null) {
1021 assert (typeDeclarator
.getType() == CTFParser
.TYPE_DECLARATOR
);
1023 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1025 IDeclaration declaration
= null;
1026 List
<CommonTree
> children
= null;
1027 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1028 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1029 CommonTree identifier
= null;
1031 /* Separate the tokens by type */
1032 if (typeDeclarator
!= null) {
1033 children
= typeDeclarator
.getChildren();
1034 assert (children
!= null);
1035 for (CommonTree child
: children
) {
1037 switch (child
.getType()) {
1038 case CTFParser
.POINTER
:
1039 pointers
.add(child
);
1041 case CTFParser
.IDENTIFIER
:
1042 assert (identifier
== null);
1045 case CTFParser
.LENGTH
:
1049 childTypeError(child
);
1057 * Parse the type specifier list, which is the "base" type. For example,
1058 * it would be int in int a[3][len].
1060 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1063 * Each length subscript means that we must create a nested array or
1064 * sequence. For example, int a[3][len] means that we have an array of 3
1065 * (sequences of length 'len' of (int)).
1067 if (lengths
.size() > 0 ) {
1068 /* We begin at the end */
1069 Collections
.reverse(lengths
);
1071 for (CommonTree length
: lengths
) {
1073 * By looking at the first expression, we can determine whether
1074 * it is an array or a sequence.
1076 List
<CommonTree
> lengthChildren
= length
.getChildren();
1077 assert (lengthChildren
!= null);
1079 CommonTree first
= lengthChildren
.get(0);
1080 if (isUnaryInteger(first
)) {
1082 int arrayLength
= (int) parseUnaryInteger(first
);
1084 if (arrayLength
< 1) {
1085 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1088 /* Create the array declaration. */
1089 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1090 } else if (isUnaryString(first
)) {
1092 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1094 /* Create the sequence declaration. */
1095 declaration
= new SequenceDeclaration(lengthName
,
1098 childTypeError(first
);
1103 if (identifier
!= null) {
1104 identifierSB
.append(identifier
.getText());
1111 * Parses a type specifier list and returns the corresponding declaration.
1113 * @param typeSpecifierList
1114 * A TYPE_SPECIFIER_LIST node.
1115 * @param pointerList
1116 * A list of POINTER nodes that apply to the specified type.
1117 * @return The corresponding declaration.
1118 * @throws ParseException
1119 * If the type has not been defined or if there is an error
1120 * creating the declaration.
1122 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1123 List
<CommonTree
> pointerList
) throws ParseException
{
1124 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1125 IDeclaration declaration
= null;
1128 * By looking at the first element of the type specifier list, we can
1129 * determine which type it belongs to.
1131 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1132 assert (firstChild
!= null); /* grammar */
1134 switch (firstChild
.getType()) {
1135 case CTFParser
.FLOATING_POINT
:
1138 // .log("parseTypeSpecifierList: floating_point not implemented yet"); //$NON-NLS-1$
1139 declaration
= parseFloat(firstChild
);
1141 case CTFParser
.INTEGER
:
1142 declaration
= parseInteger(firstChild
);
1144 case CTFParser
.STRING
:
1145 declaration
= parseString(firstChild
);
1147 case CTFParser
.STRUCT
:
1148 declaration
= parseStruct(firstChild
);
1150 case CTFParser
.VARIANT
:
1151 declaration
= parseVariant(firstChild
);
1153 case CTFParser
.ENUM
:
1154 declaration
= parseEnum(firstChild
);
1156 case CTFParser
.IDENTIFIER
:
1157 case CTFParser
.FLOATTOK
:
1158 case CTFParser
.INTTOK
:
1159 case CTFParser
.LONGTOK
:
1160 case CTFParser
.SHORTTOK
:
1161 case CTFParser
.SIGNEDTOK
:
1162 case CTFParser
.UNSIGNEDTOK
:
1163 case CTFParser
.CHARTOK
:
1164 case CTFParser
.DOUBLETOK
:
1165 case CTFParser
.VOIDTOK
:
1166 case CTFParser
.BOOLTOK
:
1167 case CTFParser
.COMPLEXTOK
:
1168 case CTFParser
.IMAGINARYTOK
:
1169 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1172 childTypeError(firstChild
);
1175 assert (declaration
!= null);
1179 private IDeclaration
parseFloat(CommonTree floatingPoint
) throws ParseException
{
1180 assert (floatingPoint
.getType() == CTFParser
.INTEGER
);
1182 List
<CommonTree
> children
= floatingPoint
.getChildren();
1185 * If the integer has no attributes, then it is missing the size
1186 * attribute which is required
1188 if (children
== null) {
1189 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1192 /* The return value */
1193 FloatDeclaration floatDeclaration
= null;
1194 ByteOrder byteOrder
= trace
.getByteOrder();
1199 /* Iterate on all integer children */
1200 for (CommonTree child
: children
) {
1201 switch (child
.getType()) {
1202 case CTFParser
.CTF_EXPRESSION_VAL
:
1204 * An assignment expression must have 2 children, left and right
1206 assert (child
.getChildCount() == 2);
1208 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1209 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1210 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1211 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1213 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1214 assert (leftStrings
!= null);
1216 if (!isUnaryString(leftStrings
.get(0))) {
1217 throw new ParseException(
1218 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1220 String left
= concatenateUnaryStrings(leftStrings
);
1222 if (left
.equals(CTFStrings
.EXP_DIG
)) {
1223 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1224 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1225 byteOrder
= getByteOrder(rightNode
);
1226 } else if (left
.equals(CTFStrings
.MANT_DIG
)) {
1227 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1228 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1229 alignment
= getAlignment(rightNode
);
1231 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1236 childTypeError(child
);
1240 int size
= mantissa
+ exponent
;
1242 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1245 if (alignment
== 0) {
1246 if ((size
% 8) == 0) {
1253 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1255 assert (floatDeclaration
!= null);
1256 return floatDeclaration
;
1261 * Parses a type specifier list as a user-declared type.
1263 * @param typeSpecifierList
1264 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1265 * @param pointerList
1266 * A list of POINTER nodes that apply to the type specified in
1267 * typeSpecifierList.
1268 * @return The corresponding declaration.
1269 * @throws ParseException
1270 * If the type does not exist (has not been found).
1272 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1273 List
<CommonTree
> pointerList
) throws ParseException
{
1274 /* Create the string representation of the type declaration */
1275 String typeStringRepresentation
= createTypeDeclarationString(
1276 typeSpecifierList
, pointerList
);
1278 /* Use the string representation to search the type in the current scope */
1279 IDeclaration decl
= getCurrentScope().rlookupType(
1280 typeStringRepresentation
);
1283 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1284 + " has not been defined."); //$NON-NLS-1$
1291 * Parses an integer declaration node.
1295 * @return The corresponding integer declaration.
1296 * @throws ParseException
1298 private IntegerDeclaration
parseInteger(CommonTree integer
)
1299 throws ParseException
{
1300 assert (integer
.getType() == CTFParser
.INTEGER
);
1302 List
<CommonTree
> children
= integer
.getChildren();
1305 * If the integer has no attributes, then it is missing the size
1306 * attribute which is required
1308 if (children
== null) {
1309 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1312 /* The return value */
1313 IntegerDeclaration integerDeclaration
= null;
1314 boolean signed
= false;
1315 ByteOrder byteOrder
= trace
.getByteOrder();
1319 String clock
= null;
1321 Encoding encoding
= Encoding
.NONE
;
1323 /* Iterate on all integer children */
1324 for (CommonTree child
: children
) {
1325 switch (child
.getType()) {
1326 case CTFParser
.CTF_EXPRESSION_VAL
:
1328 * An assignment expression must have 2 children, left and right
1330 assert (child
.getChildCount() == 2);
1332 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1333 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1334 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1335 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1337 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1338 assert (leftStrings
!= null);
1340 if (!isUnaryString(leftStrings
.get(0))) {
1341 throw new ParseException(
1342 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1344 String left
= concatenateUnaryStrings(leftStrings
);
1346 if (left
.equals("signed")) { //$NON-NLS-1$
1347 signed
= getSigned(rightNode
);
1348 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1349 byteOrder
= getByteOrder(rightNode
);
1350 } else if (left
.equals("size")) { //$NON-NLS-1$
1351 size
= getSize(rightNode
);
1352 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1353 alignment
= getAlignment(rightNode
);
1354 } else if (left
.equals("base")) { //$NON-NLS-1$
1355 base
= getBase(rightNode
);
1356 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1357 encoding
= getEncoding(rightNode
);
1358 } else if (left
.equals("map")) { //$NON-NLS-1$
1359 clock
= getClock(rightNode
);
1361 throw new ParseException("Integer: unknown attribute " + left
); //$NON-NLS-1$
1366 childTypeError(child
);
1372 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1375 if (alignment
== 0) {
1376 if ((size
% 8) == 0) {
1383 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1384 byteOrder
, encoding
, clock
, alignment
);
1386 assert (integerDeclaration
!= null);
1387 return integerDeclaration
;
1390 private static String
getClock(CommonTree rightNode
) {
1391 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1394 private static StringDeclaration
parseString(CommonTree string
)
1395 throws ParseException
{
1396 assert (string
.getType() == CTFParser
.STRING
);
1398 List
<CommonTree
> children
= string
.getChildren();
1399 StringDeclaration stringDeclaration
= null;
1401 if (children
== null) {
1402 stringDeclaration
= new StringDeclaration();
1404 Encoding encoding
= Encoding
.UTF8
;
1405 for (CommonTree child
: children
) {
1406 switch (child
.getType()) {
1407 case CTFParser
.CTF_EXPRESSION_VAL
:
1409 * An assignment expression must have 2 children, left and
1412 assert (child
.getChildCount() == 2);
1414 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1415 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1416 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1417 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1419 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1420 assert (leftStrings
!= null);
1422 if (!isUnaryString(leftStrings
.get(0))) {
1423 throw new ParseException(
1424 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1426 String left
= concatenateUnaryStrings(leftStrings
);
1428 if (left
.equals("encoding")) { //$NON-NLS-1$
1429 encoding
= getEncoding(rightNode
);
1431 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1437 childTypeError(child
);
1442 stringDeclaration
= new StringDeclaration(encoding
);
1445 return stringDeclaration
;
1449 * Parses a struct declaration and returns the corresponding declaration.
1453 * @return The corresponding struct declaration.
1454 * @throws ParseException
1456 private StructDeclaration
parseStruct(CommonTree struct
)
1457 throws ParseException
{
1458 assert (struct
.getType() == CTFParser
.STRUCT
);
1460 List
<CommonTree
> children
= struct
.getChildren();
1461 assert (children
!= null);
1463 /* The return value */
1464 StructDeclaration structDeclaration
= null;
1467 String structName
= null;
1468 boolean hasName
= false;
1471 CommonTree structBody
= null;
1472 boolean hasBody
= false;
1475 long structAlign
= 0;
1477 /* Loop on all children and identify what we have to work with. */
1478 for (CommonTree child
: children
) {
1479 switch (child
.getType()) {
1480 case CTFParser
.STRUCT_NAME
: {
1483 assert (child
.getChildCount() == 1);
1484 CommonTree structNameIdentifier
= (CommonTree
) child
1487 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1488 structName
= structNameIdentifier
.getText();
1492 case CTFParser
.STRUCT_BODY
: {
1499 case CTFParser
.ALIGN
: {
1500 assert (child
.getChildCount() == 1);
1501 CommonTree structAlignExpression
= (CommonTree
) child
1504 structAlign
= getAlignment(structAlignExpression
);
1509 childTypeError(child
);
1516 * If a struct has just a body and no name (just like the song,
1517 * "A Struct With No Name" by America (sorry for that...)), it's a
1518 * definition of a new type, so we create the type declaration and
1519 * return it. We can't add it to the declaration scope since there is no
1520 * name, but that's what we want because it won't be possible to use it
1521 * again to declare another field.
1523 * If it has just a name, we look it up in the declaration scope and
1524 * return the associated declaration. If it is not found in the
1525 * declaration scope, it means that a struct with that name has not been
1526 * declared, which is an error.
1528 * If it has both, then we create the type declaration and register it
1529 * to the current scope.
1531 * If it has none, then what are we doing here ?
1535 * If struct has a name, check if already defined in the current
1538 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1539 throw new ParseException("struct " + structName
//$NON-NLS-1$
1540 + " already defined."); //$NON-NLS-1$
1542 /* Create the declaration */
1543 structDeclaration
= new StructDeclaration(structAlign
);
1545 /* Parse the body */
1546 parseStructBody(structBody
, structDeclaration
);
1548 /* If struct has name, add it to the current scope. */
1550 getCurrentScope().registerStruct(structName
, structDeclaration
);
1552 } else /* !hasBody */{
1554 /* Name and !body */
1556 /* Lookup the name in the current scope. */
1557 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1560 * If not found, it means that a struct with such name has not
1563 if (structDeclaration
== null) {
1564 throw new ParseException("struct " + structName
//$NON-NLS-1$
1565 + " is not defined"); //$NON-NLS-1$
1568 /* !Name and !body */
1570 /* We can't do anything with that. */
1571 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1575 assert (structDeclaration
!= null);
1576 return structDeclaration
;
1580 * Parses a struct body, adding the fields to specified structure
1584 * A STRUCT_BODY node.
1585 * @param structDeclaration
1586 * The struct declaration.
1587 * @throws ParseException
1589 private void parseStructBody(CommonTree structBody
,
1590 StructDeclaration structDeclaration
) throws ParseException
{
1591 assert (structBody
.getType() == CTFParser
.STRUCT_BODY
);
1593 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1596 * If structDeclaration is null, structBody has no children and the
1597 * struct body is empty.
1599 if (structDeclarations
!= null) {
1602 for (CommonTree declarationNode
: structDeclarations
) {
1603 switch (declarationNode
.getType()) {
1604 case CTFParser
.TYPEALIAS
:
1605 parseTypealias(declarationNode
);
1607 case CTFParser
.TYPEDEF
:
1608 parseTypedef(declarationNode
);
1610 case CTFParser
.SV_DECLARATION
:
1611 parseStructDeclaration(declarationNode
, structDeclaration
);
1614 childTypeError(declarationNode
);
1623 * Parses a declaration found in a struct.
1625 * @param declaration
1626 * A SV_DECLARATION node.
1628 * A struct declaration. (I know, little name clash here...)
1629 * @throws ParseException
1631 private void parseStructDeclaration(CommonTree declaration
,
1632 StructDeclaration struct
) throws ParseException
{
1633 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
1635 List
<CommonTree
> children
= declaration
.getChildren();
1636 assert (children
!= null);
1638 /* Get the type specifier list node */
1639 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
1640 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1641 assert (typeSpecifierListNode
!= null);
1643 /* Get the type declarator list node */
1644 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
1645 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1646 assert (typeDeclaratorListNode
!= null);
1648 /* Get the type declarator list */
1649 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
1651 assert (typeDeclaratorList
!= null);
1654 * For each type declarator, parse the declaration and add a field to
1657 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1658 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
1660 StringBuilder identifierSB
= new StringBuilder();
1662 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1663 typeSpecifierListNode
, identifierSB
);
1664 String fieldName
= identifierSB
.toString();
1666 if (struct
.hasField(fieldName
)) {
1667 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1671 struct
.addField(fieldName
, decl
);
1677 * Parses an enum declaration and returns the corresponding declaration.
1681 * @return The corresponding enum declaration.
1682 * @throws ParseException
1684 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1685 assert (_enum
.getType() == CTFParser
.ENUM
);
1687 List
<CommonTree
> children
= _enum
.getChildren();
1688 assert (children
!= null);
1690 /* The return value */
1691 EnumDeclaration enumDeclaration
= null;
1694 String enumName
= null;
1697 CommonTree enumBody
= null;
1699 /* Container type */
1700 IntegerDeclaration containerTypeDeclaration
= null;
1702 /* Loop on all children and identify what we have to work with. */
1703 for (CommonTree child
: children
) {
1704 switch (child
.getType()) {
1705 case CTFParser
.ENUM_NAME
: {
1706 assert (enumName
== null);
1708 assert (child
.getChildCount() == 1);
1709 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1711 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1712 enumName
= enumNameIdentifier
.getText();
1716 case CTFParser
.ENUM_BODY
: {
1717 assert (enumBody
== null);
1723 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1724 assert (containerTypeDeclaration
== null);
1726 containerTypeDeclaration
= parseEnumContainerType(child
);
1731 childTypeError(child
);
1737 * If the container type has not been defined explicitly, we assume it
1740 if (containerTypeDeclaration
== null) {
1741 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1744 throw new ParseException(
1745 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1746 } else if (!(decl
instanceof IntegerDeclaration
)) {
1747 throw new ParseException(
1748 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1751 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1755 * If it has a body, it's a new declaration, otherwise it's a reference
1756 * to an existing declaration. Same logic as struct.
1758 if (enumBody
!= null) {
1760 * If enum has a name, check if already defined in the current
1763 if ((enumName
!= null)
1764 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1765 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1766 + " already defined"); //$NON-NLS-1$
1769 /* Create the declaration */
1770 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1772 /* Parse the body */
1773 parseEnumBody(enumBody
, enumDeclaration
);
1775 /* If the enum has name, add it to the current scope. */
1776 if (enumName
!= null) {
1777 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1780 if (enumName
!= null) {
1781 /* Name and !body */
1783 /* Lookup the name in the current scope. */
1784 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1787 * If not found, it means that an enum with such name has not
1790 if (enumDeclaration
== null) {
1791 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1792 + " is not defined"); //$NON-NLS-1$
1795 /* !Name and !body */
1796 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1800 return enumDeclaration
;
1805 * Parses an enum body, adding the enumerators to the specified enum
1809 * An ENUM_BODY node.
1810 * @param enumDeclaration
1811 * The enum declaration.
1812 * @throws ParseException
1814 private void parseEnumBody(CommonTree enumBody
,
1815 EnumDeclaration enumDeclaration
) throws ParseException
{
1816 assert (enumBody
.getType() == CTFParser
.ENUM_BODY
);
1818 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1819 /* enum body can't be empty (unlike struct). */
1820 assert (enumerators
!= null);
1825 * Start at -1, so that if the first enumrator has no explicit value, it
1830 for (CommonTree enumerator
: enumerators
) {
1831 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1840 * Parses an enumerator node and adds an enumerator declaration to an
1841 * enumeration declaration.
1843 * The high value of the range of the last enumerator is needed in case the
1844 * current enumerator does not specify its value.
1847 * An ENUM_ENUMERATOR node.
1848 * @param enumDeclaration
1849 * en enumeration declaration to which will be added the
1852 * The high value of the range of the last enumerator
1853 * @return The high value of the value range of the current enumerator.
1854 * @throws ParseException
1856 private static long parseEnumEnumerator(CommonTree enumerator
,
1857 EnumDeclaration enumDeclaration
, long lastHigh
)
1858 throws ParseException
{
1859 assert (enumerator
.getType() == CTFParser
.ENUM_ENUMERATOR
);
1861 List
<CommonTree
> children
= enumerator
.getChildren();
1862 assert (children
!= null);
1864 long low
= 0, high
= 0;
1865 boolean valueSpecified
= false;
1866 String label
= null;
1868 for (CommonTree child
: children
) {
1869 if (isUnaryString(child
)) {
1870 label
= parseUnaryString(child
);
1871 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1872 assert (child
.getChildCount() == 1);
1873 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1875 valueSpecified
= true;
1877 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1879 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1880 assert (child
.getChildCount() == 2);
1881 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1882 assert (isUnaryInteger((CommonTree
) child
.getChild(1)));
1884 valueSpecified
= true;
1886 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1887 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1889 childTypeError(child
);
1893 assert (label
!= null);
1895 if (!valueSpecified
) {
1901 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1904 if (!enumDeclaration
.add(low
, high
, label
)) {
1905 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1912 * Parses an enum container type node and returns the corresponding integer
1915 * @param enumContainerType
1916 * An ENUM_CONTAINER_TYPE node.
1917 * @return An integer declaration corresponding to the container type.
1918 * @throws ParseException
1919 * If the type does not parse correctly or if it is not an
1922 private IntegerDeclaration
parseEnumContainerType(
1923 CommonTree enumContainerType
) throws ParseException
{
1924 assert (enumContainerType
.getType() == CTFParser
.ENUM_CONTAINER_TYPE
);
1926 /* Get the child, which should be a type specifier list */
1927 assert (enumContainerType
.getChildCount() == 1);
1928 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
1931 /* Parse it and get the corresponding declaration */
1932 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1934 /* If is is an integer, return it, else throw an error */
1935 if (decl
instanceof IntegerDeclaration
) {
1936 return (IntegerDeclaration
) decl
;
1938 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1941 private VariantDeclaration
parseVariant(CommonTree variant
)
1942 throws ParseException
{
1943 assert (variant
.getType() == CTFParser
.VARIANT
);
1945 List
<CommonTree
> children
= variant
.getChildren();
1946 VariantDeclaration variantDeclaration
= null;
1948 boolean hasName
= false;
1949 String variantName
= null;
1951 boolean hasBody
= false;
1952 CommonTree variantBody
= null;
1954 boolean hasTag
= false;
1955 String variantTag
= null;
1957 for (CommonTree child
: children
) {
1958 switch (child
.getType()) {
1959 case CTFParser
.VARIANT_NAME
:
1960 assert (variantName
== null);
1964 assert (child
.getChildCount() == 1);
1965 CommonTree variantNameIdentifier
= (CommonTree
) child
1968 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1969 variantName
= variantNameIdentifier
.getText();
1972 case CTFParser
.VARIANT_TAG
:
1973 assert (variantTag
== null);
1977 assert (child
.getChildCount() == 1);
1978 CommonTree variantTagIdentifier
= (CommonTree
) child
1981 assert (variantTagIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1982 variantTag
= variantTagIdentifier
.getText();
1985 case CTFParser
.VARIANT_BODY
:
1986 assert (variantBody
== null);
1990 variantBody
= child
;
1994 childTypeError(child
);
2001 * If variant has a name, check if already defined in the current
2005 && (getCurrentScope().lookupVariant(variantName
) != null)) {
2006 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2007 + " already defined."); //$NON-NLS-1$
2010 /* Create the declaration */
2011 variantDeclaration
= new VariantDeclaration();
2013 /* Parse the body */
2014 parseVariantBody(variantBody
, variantDeclaration
);
2016 /* If variant has name, add it to the current scope. */
2018 getCurrentScope().registerVariant(variantName
,
2019 variantDeclaration
);
2021 } else /* !hasBody */{
2023 /* Name and !body */
2025 /* Lookup the name in the current scope. */
2026 variantDeclaration
= getCurrentScope().rlookupVariant(
2030 * If not found, it means that a struct with such name has not
2033 if (variantDeclaration
== null) {
2034 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2035 + " is not defined"); //$NON-NLS-1$
2038 /* !Name and !body */
2040 /* We can't do anything with that. */
2041 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2046 variantDeclaration
.setTag(variantTag
);
2049 assert (variantDeclaration
!= null);
2050 return variantDeclaration
;
2053 private void parseVariantBody(CommonTree variantBody
,
2054 VariantDeclaration variantDeclaration
) throws ParseException
{
2055 assert (variantBody
.getType() == CTFParser
.VARIANT_BODY
);
2057 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2058 assert (variantDeclarations
!= null);
2062 for (CommonTree declarationNode
: variantDeclarations
) {
2063 switch (declarationNode
.getType()) {
2064 case CTFParser
.TYPEALIAS
:
2065 parseTypealias(declarationNode
);
2067 case CTFParser
.TYPEDEF
:
2068 parseTypedef(declarationNode
);
2070 case CTFParser
.SV_DECLARATION
:
2071 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2074 childTypeError(declarationNode
);
2082 private void parseVariantDeclaration(CommonTree declaration
,
2083 VariantDeclaration variant
) throws ParseException
{
2084 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
2086 List
<CommonTree
> children
= declaration
.getChildren();
2087 assert (children
!= null);
2089 /* Get the type specifier list node */
2090 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
2091 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2092 assert (typeSpecifierListNode
!= null);
2094 /* Get the type declarator list node */
2095 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
2096 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2097 assert (typeDeclaratorListNode
!= null);
2099 /* Get the type declarator list */
2100 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
2102 assert (typeDeclaratorList
!= null);
2105 * For each type declarator, parse the declaration and add a field to
2108 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2109 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
2111 StringBuilder identifierSB
= new StringBuilder();
2113 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2114 typeSpecifierListNode
, identifierSB
);
2116 if (variant
.hasField(identifierSB
.toString())) {
2117 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2118 + identifierSB
.toString());
2121 variant
.addField(identifierSB
.toString(), decl
);
2126 * Creates the string representation of a type declaration (type specifier
2129 * @param typeSpecifierList
2130 * A TYPE_SPECIFIER_LIST node.
2132 * A list of POINTER nodes.
2133 * @return The string representation.
2134 * @throws ParseException
2136 private static String
createTypeDeclarationString(
2137 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2138 throws ParseException
{
2139 StringBuilder sb
= new StringBuilder();
2141 createTypeSpecifierListString(typeSpecifierList
, sb
);
2142 createPointerListString(pointers
, sb
);
2144 return sb
.toString();
2148 * Creates the string representation of a list of type specifiers.
2150 * @param typeSpecifierList
2151 * A TYPE_SPECIFIER_LIST node.
2153 * A StringBuilder to which will be appended the string.
2154 * @throws ParseException
2156 private static void createTypeSpecifierListString(
2157 CommonTree typeSpecifierList
, StringBuilder sb
)
2158 throws ParseException
{
2159 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
2161 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2162 assert (children
!= null);
2164 boolean firstItem
= true;
2166 for (CommonTree child
: children
) {
2174 /* Append the string that represents this type specifier. */
2175 createTypeSpecifierString(child
, sb
);
2180 * Creates the string representation of a type specifier.
2182 * @param typeSpecifier
2183 * A TYPE_SPECIFIER node.
2185 * A StringBuilder to which will be appended the string.
2186 * @throws ParseException
2188 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2189 StringBuilder sb
) throws ParseException
{
2190 switch (typeSpecifier
.getType()) {
2191 case CTFParser
.FLOATTOK
:
2192 case CTFParser
.INTTOK
:
2193 case CTFParser
.LONGTOK
:
2194 case CTFParser
.SHORTTOK
:
2195 case CTFParser
.SIGNEDTOK
:
2196 case CTFParser
.UNSIGNEDTOK
:
2197 case CTFParser
.CHARTOK
:
2198 case CTFParser
.DOUBLETOK
:
2199 case CTFParser
.VOIDTOK
:
2200 case CTFParser
.BOOLTOK
:
2201 case CTFParser
.COMPLEXTOK
:
2202 case CTFParser
.IMAGINARYTOK
:
2203 case CTFParser
.CONSTTOK
:
2204 case CTFParser
.IDENTIFIER
:
2205 sb
.append(typeSpecifier
.getText());
2207 case CTFParser
.STRUCT
: {
2208 CommonTree structName
= (CommonTree
) typeSpecifier
2209 .getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2210 if (structName
== null) {
2211 throw new ParseException(
2212 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2214 assert (structName
.getChildCount() == 1);
2216 CommonTree structNameIdentifier
= (CommonTree
) structName
2218 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2220 sb
.append(structNameIdentifier
.getText());
2223 case CTFParser
.VARIANT
: {
2224 CommonTree variantName
= (CommonTree
) typeSpecifier
2225 .getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2226 if (variantName
== null) {
2227 throw new ParseException(
2228 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2230 assert (variantName
.getChildCount() == 1);
2232 CommonTree variantNameIdentifier
= (CommonTree
) variantName
2234 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2236 sb
.append(variantNameIdentifier
.getText());
2239 case CTFParser
.ENUM
: {
2240 CommonTree enumName
= (CommonTree
) typeSpecifier
2241 .getFirstChildWithType(CTFParser
.ENUM_NAME
);
2242 if (enumName
== null) {
2243 throw new ParseException(
2244 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2246 assert (enumName
.getChildCount() == 1);
2248 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2249 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2251 sb
.append(enumNameIdentifier
.getText());
2254 case CTFParser
.FLOATING_POINT
:
2255 case CTFParser
.INTEGER
:
2256 case CTFParser
.STRING
:
2257 throw new ParseException(
2258 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2261 childTypeError(typeSpecifier
);
2267 * Creates the string representation of a list of pointers.
2269 * @param pointerList
2270 * A list of pointer nodes. If pointerList is null, this function
2273 * A stringbuilder to which will be appended the string.
2275 private static void createPointerListString(List
<CommonTree
> pointerList
,
2277 if (pointerList
== null) {
2281 for (CommonTree pointer
: pointerList
) {
2282 assert (pointer
.getType() == CTFParser
.POINTER
);
2284 sb
.append(" *"); //$NON-NLS-1$
2285 if (pointer
.getChildCount() > 0) {
2286 assert (pointer
.getChildCount() == 1);
2287 CommonTree constQualifier
= (CommonTree
) pointer
.getChild(0);
2288 assert (constQualifier
.getType() == CTFParser
.CONSTTOK
);
2290 sb
.append(" const"); //$NON-NLS-1$
2297 * The node to check.
2298 * @return True if the given node is an unary string or unary integer.
2300 private static boolean isUnaryExpression(CommonTree node
) {
2301 return isUnaryInteger(node
) || isUnaryString(node
);
2306 * The node to check.
2307 * @return True if the given node is an unary string.
2309 private static boolean isUnaryString(CommonTree node
) {
2310 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (node
2311 .getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2316 * The node to check.
2317 * @return True if the given node is an unary integer.
2319 private static boolean isUnaryInteger(CommonTree node
) {
2320 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
)
2321 || (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) || (node
2322 .getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2326 * Parses a unary string node and return the string value.
2328 * @param unaryString
2329 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2330 * or UNARY_EXPRESSION_STRING_QUOTES).
2331 * @return The string value.
2334 * It would be really nice to remove the quotes earlier, such as in the
2337 private static String
parseUnaryString(CommonTree unaryString
) {
2338 assert (isUnaryString(unaryString
));
2340 assert (unaryString
.getChildCount() == 1);
2341 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2342 assert (value
!= null);
2343 String strval
= value
.getText();
2346 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2347 strval
= strval
.substring(1, strval
.length() - 1);
2354 * Parses an unary integer (dec, hex or oct).
2356 * @param unaryInteger
2357 * An unary integer node.
2358 * @return The integer value.
2360 private static long parseUnaryInteger(CommonTree unaryInteger
) {
2361 assert (isUnaryInteger(unaryInteger
));
2363 assert (unaryInteger
.getChildCount() >= 1);
2365 List
<CommonTree
> children
= unaryInteger
.getChildren();
2366 CommonTree value
= children
.get(0);
2367 String strval
= value
.getText();
2371 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2372 intval
= Long
.parseLong(strval
, 10);
2373 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2374 intval
= Long
.parseLong(strval
, 0x10);
2375 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2376 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2379 /* The rest of children are sign */
2380 if ((children
.size() % 2) == 0) {
2386 private static long getMajorOrMinor(CommonTree rightNode
)
2387 throws ParseException
{
2388 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2389 assert (rightNode
.getChildCount() > 0);
2391 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2393 if (isUnaryInteger(firstChild
)) {
2394 if (rightNode
.getChildCount() > 1) {
2395 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2398 long m
= parseUnaryInteger(firstChild
);
2401 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2406 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2409 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2410 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2411 assert (rightNode
.getChildCount() > 0);
2413 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2415 if (isUnaryString(firstChild
)) {
2416 if (rightNode
.getChildCount() > 1) {
2417 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2420 String uuidstr
= parseUnaryString(firstChild
);
2423 UUID uuid
= UUID
.fromString(uuidstr
);
2425 } catch (IllegalArgumentException e
) {
2426 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2429 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2433 * Gets the value of a "signed" integer attribute.
2437 * @return The "signed" value as a boolean.
2438 * @throws ParseException
2440 private static boolean getSigned(CommonTree rightNode
)
2441 throws ParseException
{
2442 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2443 assert (rightNode
.getChildCount() > 0);
2445 boolean ret
= false;
2446 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2448 if (isUnaryString(firstChild
)) {
2449 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2451 if (strval
.equals(CTFStrings
.TRUE
) || strval
.equals(CTFStrings
.TRUE2
)) {
2453 } else if (strval
.equals(CTFStrings
.FALSE
) || strval
.equals(CTFStrings
.FALSE2
)) {
2456 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2457 + firstChild
.getChild(0).getText());
2459 } else if (isUnaryInteger(firstChild
)) {
2460 /* Happens if the value is something like "1234.hello" */
2461 if (rightNode
.getChildCount() > 1) {
2462 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2465 long intval
= parseUnaryInteger(firstChild
);
2469 } else if (intval
== 0) {
2472 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2473 + firstChild
.getChild(0).getText());
2476 throw new ParseException();
2483 * Gets the value of a "byte_order" integer attribute.
2487 * @return The "byte_order" value.
2488 * @throws ParseException
2490 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2491 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2492 assert (rightNode
.getChildCount() > 0);
2494 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2496 if (isUnaryString(firstChild
)) {
2497 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2499 if (strval
.equals(CTFStrings
.LE
)) {
2500 return ByteOrder
.LITTLE_ENDIAN
;
2501 } else if (strval
.equals(CTFStrings
.BE
) || strval
.equals(CTFStrings
.NETWORK
)) {
2502 return ByteOrder
.BIG_ENDIAN
;
2503 } else if (strval
.equals(CTFStrings
.NATIVE
)) {
2504 return trace
.getByteOrder();
2506 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2509 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2513 * Determines if the given value is a valid alignment value.
2516 * The value to check.
2517 * @return True if it is valid.
2519 private static boolean isValidAlignment(long alignment
) {
2520 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2524 * Gets the value of a "size" integer attribute.
2528 * @return The "size" value.
2529 * @throws ParseException
2531 private static long getSize(CommonTree rightNode
) throws ParseException
{
2532 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2533 assert (rightNode
.getChildCount() > 0);
2535 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2537 if (isUnaryInteger(firstChild
)) {
2538 if (rightNode
.getChildCount() > 1) {
2539 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2542 long size
= parseUnaryInteger(firstChild
);
2545 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2550 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2554 * Gets the value of a "align" integer or struct attribute.
2557 * A CTF_RIGHT node or directly an unary integer.
2558 * @return The align value.
2559 * @throws ParseException
2561 private static long getAlignment(CommonTree node
) throws ParseException
{
2562 assert (isUnaryExpression(node
) || (node
.getType() == CTFParser
.CTF_RIGHT
));
2565 * If a CTF_RIGHT node was passed, call getAlignment with the first
2568 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2569 if (node
.getChildCount() > 1) {
2570 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2573 return getAlignment((CommonTree
) node
.getChild(0));
2574 } else if (isUnaryInteger(node
)) {
2575 long alignment
= parseUnaryInteger(node
);
2577 if (!isValidAlignment(alignment
)) {
2578 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2584 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2588 * Gets the value of a "base" integer attribute.
2591 * An CTF_RIGHT node.
2592 * @return The "base" value.
2593 * @throws ParseException
2595 private static int getBase(CommonTree rightNode
) throws ParseException
{
2596 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2597 assert (rightNode
.getChildCount() > 0);
2599 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2601 if (isUnaryInteger(firstChild
)) {
2602 if (rightNode
.getChildCount() > 1) {
2603 throw new ParseException("invalid base value"); //$NON-NLS-1$
2606 long intval
= parseUnaryInteger(firstChild
);
2607 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2608 || (intval
== 16)) {
2609 return (int) intval
;
2611 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2612 } else if (isUnaryString(firstChild
)) {
2613 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2615 if (strval
.equals(CTFStrings
.DECIMAL
) || strval
.equals(CTFStrings
.DEC
)
2616 || strval
.equals(CTFStrings
.DEC_CTE
) || strval
.equals(CTFStrings
.INT_MOD
)
2617 || strval
.equals(CTFStrings
.UNSIGNED_CTE
)) {
2619 } else if (strval
.equals(CTFStrings
.HEXADECIMAL
) || strval
.equals(CTFStrings
.HEX
)
2620 || strval
.equals(CTFStrings
.X
) || strval
.equals(CTFStrings
.X2
)
2621 || strval
.equals(CTFStrings
.POINTER
)) {
2623 } else if (strval
.equals(CTFStrings
.OCTAL
) || strval
.equals(CTFStrings
.OCT
)
2624 || strval
.equals(CTFStrings
.OCTAL_CTE
)) {
2626 } else if (strval
.equals(CTFStrings
.BINARY
) || strval
.equals(CTFStrings
.BIN
)) {
2629 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2632 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2637 * Gets the value of an "encoding" integer attribute.
2641 * @return The "encoding" value.
2642 * @throws ParseException
2644 private static Encoding
getEncoding(CommonTree rightNode
)
2645 throws ParseException
{
2646 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2648 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2650 if (isUnaryString(firstChild
)) {
2651 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2653 if (strval
.equals(CTFStrings
.UTF8
)) {
2654 return Encoding
.UTF8
;
2655 } else if (strval
.equals(CTFStrings
.ASCII
)) {
2656 return Encoding
.ASCII
;
2657 } else if (strval
.equals(CTFStrings
.NONE
)) {
2658 return Encoding
.NONE
;
2660 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2663 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2666 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2667 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2668 assert (rightNode
.getChildCount() > 0);
2670 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2672 if (isUnaryInteger(firstChild
)) {
2673 if (rightNode
.getChildCount() > 1) {
2674 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2677 long intval
= parseUnaryInteger(firstChild
);
2681 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2684 private static String
getEventName(CommonTree rightNode
)
2685 throws ParseException
{
2686 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2687 assert (rightNode
.getChildCount() > 0);
2689 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2691 if (isUnaryString(firstChild
)) {
2692 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2696 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2699 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2700 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2701 assert (rightNode
.getChildCount() > 0);
2703 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2705 if (isUnaryInteger(firstChild
)) {
2706 if (rightNode
.getChildCount() > 1) {
2707 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2710 long intval
= parseUnaryInteger(firstChild
);
2714 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2718 * Concatenates a list of unary strings separated by arrows (->) or dots.
2721 * A list, first element being an unary string, subsequent
2722 * elements being ARROW or DOT nodes with unary strings as child.
2723 * @return The string representation of the unary string chain.
2725 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2726 assert ((strings
!= null) && (strings
.size() > 0));
2728 StringBuilder sb
= new StringBuilder();
2730 CommonTree first
= strings
.get(0);
2731 sb
.append(parseUnaryString(first
));
2733 boolean isFirst
= true;
2735 for (CommonTree ref
: strings
) {
2741 assert ((ref
.getType() == CTFParser
.ARROW
) || (ref
.getType() == CTFParser
.DOT
));
2742 assert (ref
.getChildCount() == 1);
2744 CommonTree id
= (CommonTree
) ref
.getChild(0);
2746 if (ref
.getType() == CTFParser
.ARROW
) {
2747 sb
.append("->"); //$NON-NLS-1$
2752 sb
.append(parseUnaryString(id
));
2755 return sb
.toString();
2759 * Throws a ParseException stating that the parent-child relation between
2760 * the given node and its parent is not valid. It means that the shape of
2761 * the AST is unexpected.
2764 * The invalid child node.
2765 * @throws ParseException
2767 private static void childTypeError(CommonTree child
) throws ParseException
{
2768 CommonTree parent
= (CommonTree
) child
.getParent();
2769 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2770 + " can't have a child of type " //$NON-NLS-1$
2771 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2773 throw new ParseException(error
);
2776 // ------------------------------------------------------------------------
2778 // ------------------------------------------------------------------------
2781 * Adds a new declaration scope on the top of the scope stack.
2783 private void pushScope() {
2784 scope
= new DeclarationScope(scope
);
2788 * Removes the top declaration scope from the scope stack.
2790 private void popScope() {
2791 assert (scope
!= null);
2792 scope
= scope
.getParentScope();
2796 * Returns the current declaration scope.
2798 * @return The current declaration scope.
2800 private DeclarationScope
getCurrentScope() {
2801 assert (scope
!= null);