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
.IDeclaration
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDeclaration
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
36 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
37 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
38 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
39 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.Activator
;
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
) {
217 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1)
218 .getChild(0).getChild(0);
220 out
.write("Name = " + name
); //$NON-NLS-1$
222 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1)
223 .getChild(0).getChild(0);
225 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
233 } catch (IOException e
) {
239 private void parseEnvironment(CommonTree environment
) {
240 List
<CommonTree
> children
= environment
.getChildren();
241 for (CommonTree child
: children
) {
244 left
= child
.getChild(0).getChild(0).getChild(0).getText();
245 right
= child
.getChild(1).getChild(0).getChild(0).getText();
246 trace
.addEnvironmentVar(left
, right
);
250 private void parseClock(CommonTree clock
) {
251 List
<CommonTree
> children
= clock
.getChildren();
252 CTFClock ctfClock
= new CTFClock();
253 for (CommonTree child
: children
) {
254 final String key
= child
.getChild(0).getChild(0).getChild(0)
256 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
257 final int type
= value
.getType();
259 case CTFParser
.INTEGER
:
260 case CTFParser
.DECIMAL_LITERAL
:
262 * Not a pretty hack, this is to make sure that there is no number
263 * overflow due to 63 bit integers. The offset should only really
264 * be an issue in the year 2262. the tracer in C/ASM can write an offset in
265 * an unsigned 64 bit long. In java, the last bit, being set to 1 will
266 * be read as a negative number, but since it is too big a positive it will
267 * throw an exception. this will happen in 2^63 ns from 1970.
268 * Therefore 293 years from 1970
272 numValue
= Long
.parseLong(value
.getText());
276 numValue
= 1330938566783103277L;
278 ctfClock
.addAttribute(key
, numValue
);
281 ctfClock
.addAttribute(key
, value
.getText());
285 String NameValue
= ctfClock
.getName();
286 trace
.addClock(NameValue
, ctfClock
);
289 private void parseTrace(CommonTree traceNode
) throws ParseException
{
290 assert (traceNode
.getType() == CTFParser
.TRACE
);
292 List
<CommonTree
> children
= traceNode
.getChildren();
293 if (children
== null) {
294 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
299 for (CommonTree child
: children
) {
300 switch (child
.getType()) {
301 case CTFParser
.TYPEALIAS
:
302 parseTypealias(child
);
304 case CTFParser
.TYPEDEF
:
307 case CTFParser
.CTF_EXPRESSION_TYPE
:
308 case CTFParser
.CTF_EXPRESSION_VAL
:
309 parseTraceDeclaration(child
);
312 childTypeError(child
);
318 * If trace byte order was not specified and not using packet based
321 if (trace
.getByteOrder() == null) {
322 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
328 private void parseTraceDeclaration(CommonTree traceDecl
)
329 throws ParseException
{
330 assert ((traceDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (traceDecl
331 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
333 /* There should be a left and right */
334 assert (traceDecl
.getChildCount() == 2);
336 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
337 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
338 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
339 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
341 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
342 assert (leftStrings
!= null);
344 if (!isUnaryString(leftStrings
.get(0))) {
345 throw new ParseException(
346 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
349 String left
= concatenateUnaryStrings(leftStrings
);
351 if (left
.equals("major")) { //$NON-NLS-1$
352 if (trace
.majortIsSet()) {
353 throw new ParseException("major is already set"); //$NON-NLS-1$
356 trace
.setMajor(getMajorOrMinor(rightNode
));
357 } else if (left
.equals("minor")) { //$NON-NLS-1$
358 if (trace
.minorIsSet()) {
359 throw new ParseException("minor is already set"); //$NON-NLS-1$
362 trace
.setMinor(getMajorOrMinor(rightNode
));
363 } else if (left
.equals("uuid")) { //$NON-NLS-1$
364 UUID uuid
= getUUID(rightNode
);
367 * If uuid was already set by a metadata packet, compare it to see
370 if (trace
.UUIDIsSet()) {
371 if (trace
.getUUID().compareTo(uuid
) != 0) {
372 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
373 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
379 } else if (left
.equals("byte_order")) { //$NON-NLS-1$
380 ByteOrder byteOrder
= getByteOrder(rightNode
);
383 * If byte order was already set by a metadata packet, compare it to
386 if (trace
.getByteOrder() != null) {
387 if (trace
.getByteOrder() != byteOrder
) {
388 throw new ParseException(
389 "Endianness mismatch. Magic number says " //$NON-NLS-1$
390 + trace
.getByteOrder()
391 + " but metadata says " + byteOrder
); //$NON-NLS-1$
394 trace
.setByteOrder(byteOrder
);
396 } else if (left
.equals("packet.header")) { //$NON-NLS-1$
397 if (trace
.packetHeaderIsSet()) {
398 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
401 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
403 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
404 throw new ParseException(
405 "packet.header expects a type specifier"); //$NON-NLS-1$
408 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
409 typeSpecifier
, null);
411 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
412 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
415 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
417 throw new ParseException("Unknown trace attribute : " + left
); //$NON-NLS-1$
421 private void parseStream(CommonTree streamNode
) throws ParseException
{
422 assert (streamNode
.getType() == CTFParser
.STREAM
);
424 Stream stream
= new Stream(trace
);
426 List
<CommonTree
> children
= streamNode
.getChildren();
427 if (children
== null) {
428 throw new ParseException("Empty stream block"); //$NON-NLS-1$
433 for (CommonTree child
: children
) {
434 switch (child
.getType()) {
435 case CTFParser
.TYPEALIAS
:
436 parseTypealias(child
);
438 case CTFParser
.TYPEDEF
:
441 case CTFParser
.CTF_EXPRESSION_TYPE
:
442 case CTFParser
.CTF_EXPRESSION_VAL
:
443 parseStreamDeclaration(child
, stream
);
446 childTypeError(child
);
451 if (stream
.idIsSet()) {
452 if (!trace
.packetHeaderIsSet()
453 || !trace
.getPacketHeader().hasField("stream_id")) { //$NON-NLS-1$
454 throw new ParseException(
455 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
459 trace
.addStream(stream
);
464 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
465 throws ParseException
{
466 assert ((streamDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (streamDecl
467 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
469 /* There should be a left and right */
470 assert (streamDecl
.getChildCount() == 2);
472 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
473 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
474 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
475 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
477 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
478 assert (leftStrings
!= null);
480 if (!isUnaryString(leftStrings
.get(0))) {
481 throw new ParseException(
482 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
485 String left
= concatenateUnaryStrings(leftStrings
);
487 if (left
.equals("id")) { //$NON-NLS-1$
488 if (stream
.idIsSet()) {
489 throw new ParseException("stream id already defined"); //$NON-NLS-1$
492 long streamID
= getStreamID(rightNode
);
494 stream
.setId(streamID
);
495 } else if (left
.equals("event.header")) { //$NON-NLS-1$
496 if (stream
.eventHeaderIsSet()) {
497 throw new ParseException("event.header already defined"); //$NON-NLS-1$
500 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
502 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
503 throw new ParseException(
504 "event.header expects a type specifier"); //$NON-NLS-1$
507 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
508 typeSpecifier
, null);
510 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
511 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
514 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
515 } else if (left
.equals("event.context")) { //$NON-NLS-1$
516 if (stream
.eventContextIsSet()) {
517 throw new ParseException("event.context already defined"); //$NON-NLS-1$
520 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
522 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
523 throw new ParseException(
524 "event.context expects a type specifier"); //$NON-NLS-1$
527 IDeclaration eventContextDecl
= parseTypeSpecifierList(
528 typeSpecifier
, null);
530 if (!(eventContextDecl
instanceof StructDeclaration
)) {
531 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
534 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
535 } else if (left
.equals("packet.context")) { //$NON-NLS-1$
536 if (stream
.packetContextIsSet()) {
537 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
540 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
542 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
543 throw new ParseException(
544 "packet.context expects a type specifier"); //$NON-NLS-1$
547 IDeclaration packetContextDecl
= parseTypeSpecifierList(
548 typeSpecifier
, null);
550 if (!(packetContextDecl
instanceof StructDeclaration
)) {
551 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
554 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
556 throw new ParseException("Unknown stream attribute : " + left
); //$NON-NLS-1$
560 private void parseEvent(CommonTree eventNode
) throws ParseException
{
561 assert (eventNode
.getType() == CTFParser
.EVENT
);
563 List
<CommonTree
> children
= eventNode
.getChildren();
564 if (children
== null) {
565 throw new ParseException("Empty event block"); //$NON-NLS-1$
568 EventDeclaration event
= new EventDeclaration();
572 for (CommonTree child
: children
) {
573 switch (child
.getType()) {
574 case CTFParser
.TYPEALIAS
:
575 parseTypealias(child
);
577 case CTFParser
.TYPEDEF
:
580 case CTFParser
.CTF_EXPRESSION_TYPE
:
581 case CTFParser
.CTF_EXPRESSION_VAL
:
582 parseEventDeclaration(child
, event
);
585 childTypeError(child
);
590 if (!event
.nameIsSet()) {
591 throw new ParseException("Event name not set"); //$NON-NLS-1$
595 * If the event did not specify a stream, then the trace must be single
598 if (!event
.streamIsSet()) {
599 if (trace
.nbStreams() > 1) {
600 throw new ParseException(
601 "Event without stream_id with more than one stream"); //$NON-NLS-1$
605 * If the event did not specify a stream, the only existing stream
606 * must not have an id. Note: That behavior could be changed, it
607 * could be possible to just get the only existing stream, whatever
610 Stream stream
= trace
.getStream(null);
612 if (stream
!= null) {
613 event
.setStream(stream
);
615 throw new ParseException(
616 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
621 * Add the event to the stream.
623 event
.getStream().addEvent(event
);
628 private void parseEventDeclaration(CommonTree eventDecl
,
629 EventDeclaration event
) throws ParseException
{
630 assert ((eventDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (eventDecl
631 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
633 /* There should be a left and right */
634 assert (eventDecl
.getChildCount() == 2);
636 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
637 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
638 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
639 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
641 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
642 assert (leftStrings
!= null);
644 if (!isUnaryString(leftStrings
.get(0))) {
645 throw new ParseException(
646 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
649 String left
= concatenateUnaryStrings(leftStrings
);
651 if (left
.equals("name")) { //$NON-NLS-1$
652 if (event
.nameIsSet()) {
653 throw new ParseException("name already defined"); //$NON-NLS-1$
656 String name
= getEventName(rightNode
);
659 } else if (left
.equals("id")) { //$NON-NLS-1$
660 if (event
.idIsSet()) {
661 throw new ParseException("id already defined"); //$NON-NLS-1$
664 long id
= getEventID(rightNode
);
667 } else if (left
.equals("stream_id")) { //$NON-NLS-1$
668 if (event
.streamIsSet()) {
669 throw new ParseException("stream id already defined"); //$NON-NLS-1$
672 long streamId
= getStreamID(rightNode
);
674 Stream stream
= trace
.getStream(streamId
);
676 if (stream
== null) {
677 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
680 event
.setStream(stream
);
681 } else if (left
.equals("context")) { //$NON-NLS-1$
682 if (event
.contextIsSet()) {
683 throw new ParseException("context already defined"); //$NON-NLS-1$
686 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
688 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
689 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
692 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
695 if (!(contextDecl
instanceof StructDeclaration
)) {
696 throw new ParseException("context expects a struct"); //$NON-NLS-1$
699 event
.setContext((StructDeclaration
) contextDecl
);
700 } else if (left
.equals("fields")) { //$NON-NLS-1$
701 if (event
.fieldsIsSet()) {
702 throw new ParseException("fields already defined"); //$NON-NLS-1$
705 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
707 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
708 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
711 IDeclaration fieldsDecl
;
712 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
714 if (!(fieldsDecl
instanceof StructDeclaration
)) {
715 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
718 * The underscores in the event names.
719 * These underscores were added by the LTTng tracer.
721 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
722 event
.setFields(fields
);
725 throw new ParseException("Unknown event attribute : " + left
); //$NON-NLS-1$
730 * Parses a declaration at the root level.
733 * The declaration subtree.
734 * @throws ParseException
736 private void parseRootDeclaration(CommonTree declaration
)
737 throws ParseException
{
738 assert (declaration
.getType() == CTFParser
.DECLARATION
);
740 List
<CommonTree
> children
= declaration
.getChildren();
741 assert (children
!= null);
743 for (CommonTree child
: children
) {
744 switch (child
.getType()) {
745 case CTFParser
.TYPEDEF
:
748 case CTFParser
.TYPEALIAS
:
749 parseTypealias(child
);
751 case CTFParser
.TYPE_SPECIFIER_LIST
:
752 parseTypeSpecifierList(child
, null);
755 childTypeError(child
);
761 * Parses a typealias node. It parses the target, the alias, and registers
762 * the type in the current scope.
766 * @throws ParseException
768 private void parseTypealias(CommonTree typealias
) throws ParseException
{
769 assert (typealias
.getType() == CTFParser
.TYPEALIAS
);
771 List
<CommonTree
> children
= typealias
.getChildren();
772 assert (children
!= null);
774 CommonTree target
= null;
775 CommonTree alias
= null;
777 for (CommonTree child
: children
) {
778 switch (child
.getType()) {
779 case CTFParser
.TYPEALIAS_TARGET
:
780 assert (target
== null);
783 case CTFParser
.TYPEALIAS_ALIAS
:
784 assert (alias
== null);
788 childTypeError(child
);
793 assert (target
!= null);
794 assert (alias
!= null);
796 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
798 if (targetDeclaration
instanceof VariantDeclaration
) {
799 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
800 throw new ParseException(
801 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
805 String aliasString
= parseTypealiasAlias(alias
);
807 getCurrentScope().registerType(aliasString
, targetDeclaration
);
811 * Parses the target part of a typealias and gets the corresponding
815 * A TYPEALIAS_TARGET node.
816 * @return The corresponding declaration.
817 * @throws ParseException
819 private IDeclaration
parseTypealiasTarget(CommonTree target
)
820 throws ParseException
{
821 assert (target
.getType() == CTFParser
.TYPEALIAS_TARGET
);
823 List
<CommonTree
> children
= target
.getChildren();
824 assert (children
!= null);
826 CommonTree typeSpecifierList
= null;
827 CommonTree typeDeclaratorList
= null;
828 CommonTree typeDeclarator
= null;
829 StringBuilder identifierSB
= new StringBuilder();
831 for (CommonTree child
: children
) {
832 switch (child
.getType()) {
833 case CTFParser
.TYPE_SPECIFIER_LIST
:
834 assert (typeSpecifierList
== null);
835 typeSpecifierList
= child
;
837 case CTFParser
.TYPE_DECLARATOR_LIST
:
838 assert (typeDeclaratorList
== null);
839 typeDeclaratorList
= child
;
842 childTypeError(child
);
847 assert (typeSpecifierList
!= null);
849 if (typeDeclaratorList
!= null) {
851 * Only allow one declarator
853 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
854 * otherwise the new type puint8_t would maps to two different
857 if (typeDeclaratorList
.getChildCount() != 1) {
858 throw new ParseException(
859 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
862 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
865 /* Parse the target type and get the declaration */
866 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
867 typeSpecifierList
, identifierSB
);
870 * We don't allow identifier in the target
872 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
875 if (identifierSB
.length() > 0) {
876 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
877 + ") not expected in the typealias target"); //$NON-NLS-1$
880 return targetDeclaration
;
884 * Parses the alias part of a typealias. It parses the underlying specifier
885 * list and declarator and creates the string representation that will be
886 * used to register the type.
889 * A TYPEALIAS_ALIAS node.
890 * @return The string representation of the alias.
891 * @throws ParseException
893 private static String
parseTypealiasAlias(CommonTree alias
)
894 throws ParseException
{
895 assert (alias
.getType() == CTFParser
.TYPEALIAS_ALIAS
);
897 List
<CommonTree
> children
= alias
.getChildren();
898 assert (children
!= null);
900 CommonTree typeSpecifierList
= null;
901 CommonTree typeDeclaratorList
= null;
902 CommonTree typeDeclarator
= null;
903 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
905 for (CommonTree child
: children
) {
906 switch (child
.getType()) {
907 case CTFParser
.TYPE_SPECIFIER_LIST
:
908 assert (typeSpecifierList
== null);
909 typeSpecifierList
= child
;
911 case CTFParser
.TYPE_DECLARATOR_LIST
:
912 assert (typeDeclaratorList
== null);
913 typeDeclaratorList
= child
;
916 childTypeError(child
);
921 /* If there is a type declarator list, extract the pointers */
922 if (typeDeclaratorList
!= null) {
924 * Only allow one declarator
926 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
928 if (typeDeclaratorList
.getChildCount() != 1) {
929 throw new ParseException(
930 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
933 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
935 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
937 assert (typeDeclaratorChildren
!= null);
939 for (CommonTree child
: typeDeclaratorChildren
) {
940 switch (child
.getType()) {
941 case CTFParser
.POINTER
:
944 case CTFParser
.IDENTIFIER
:
945 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
946 + ") not expected in the typealias target"); //$NON-NLS-1$
949 childTypeError(child
);
955 return createTypeDeclarationString(typeSpecifierList
, pointers
);
959 * Parses a typedef node. This creates and registers a new declaration for
960 * each declarator found in the typedef.
964 * @throws ParseException
965 * If there is an error creating the declaration.
967 private void parseTypedef(CommonTree typedef
) throws ParseException
{
968 assert (typedef
.getType() == CTFParser
.TYPEDEF
);
970 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
971 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
972 assert (typeDeclaratorListNode
!= null);
974 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
975 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
976 assert (typeSpecifierListNode
!= null);
978 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
980 assert (typeDeclaratorList
!= null);
982 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
983 StringBuilder identifierSB
= new StringBuilder();
985 IDeclaration type_declaration
= parseTypeDeclarator(
986 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
988 if (type_declaration
instanceof VariantDeclaration
) {
989 if (((VariantDeclaration
) type_declaration
).isTagged()) {
990 throw new ParseException(
991 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
995 getCurrentScope().registerType(identifierSB
.toString(),
1001 * Parses a pair type declarator / type specifier list and returns the
1002 * corresponding declaration. If it is present, it also writes the
1003 * identifier of the declarator in the given {@link StringBuilder}.
1005 * @param typeDeclarator
1006 * A TYPE_DECLARATOR node.
1007 * @param typeSpecifierList
1008 * A TYPE_SPECIFIER_LIST node.
1009 * @param identifierSB
1010 * A StringBuilder that will receive the identifier found in the
1012 * @return The corresponding declaration.
1013 * @throws ParseException
1014 * If there is an error finding or creating the declaration.
1016 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1017 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1018 throws ParseException
{
1019 if (typeDeclarator
!= null) {
1020 assert (typeDeclarator
.getType() == CTFParser
.TYPE_DECLARATOR
);
1022 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1024 IDeclaration declaration
= null;
1025 List
<CommonTree
> children
= null;
1026 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1027 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1028 CommonTree identifier
= null;
1030 /* Separate the tokens by type */
1031 if (typeDeclarator
!= null) {
1032 children
= typeDeclarator
.getChildren();
1033 assert (children
!= null);
1034 for (CommonTree child
: children
) {
1036 switch (child
.getType()) {
1037 case CTFParser
.POINTER
:
1038 pointers
.add(child
);
1040 case CTFParser
.IDENTIFIER
:
1041 assert (identifier
== null);
1044 case CTFParser
.LENGTH
:
1048 childTypeError(child
);
1056 * Parse the type specifier list, which is the "base" type. For example,
1057 * it would be int in int a[3][len].
1059 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1062 * Each length subscript means that we must create a nested array or
1063 * sequence. For example, int a[3][len] means that we have an array of 3
1064 * (sequences of length 'len' of (int)).
1066 if (lengths
.size() > 0 ) {
1067 /* We begin at the end */
1068 Collections
.reverse(lengths
);
1070 for (CommonTree length
: lengths
) {
1072 * By looking at the first expression, we can determine whether
1073 * it is an array or a sequence.
1075 List
<CommonTree
> lengthChildren
= length
.getChildren();
1076 assert (lengthChildren
!= null);
1078 CommonTree first
= lengthChildren
.get(0);
1079 if (isUnaryInteger(first
)) {
1081 int arrayLength
= (int) parseUnaryInteger(first
);
1083 if (arrayLength
< 1) {
1084 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1087 /* Create the array declaration. */
1088 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1089 } else if (isUnaryString(first
)) {
1091 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1093 /* Create the sequence declaration. */
1094 declaration
= new SequenceDeclaration(lengthName
,
1097 childTypeError(first
);
1102 if (identifier
!= null) {
1103 identifierSB
.append(identifier
.getText());
1110 * Parses a type specifier list and returns the corresponding declaration.
1112 * @param typeSpecifierList
1113 * A TYPE_SPECIFIER_LIST node.
1114 * @param pointerList
1115 * A list of POINTER nodes that apply to the specified type.
1116 * @return The corresponding declaration.
1117 * @throws ParseException
1118 * If the type has not been defined or if there is an error
1119 * creating the declaration.
1121 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1122 List
<CommonTree
> pointerList
) throws ParseException
{
1123 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1124 IDeclaration declaration
= null;
1127 * By looking at the first element of the type specifier list, we can
1128 * determine which type it belongs to.
1130 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1131 assert (firstChild
!= null); /* grammar */
1133 switch (firstChild
.getType()) {
1134 case CTFParser
.FLOATING_POINT
:
1137 .log("parseTypeSpecifierList: floating_point not implemented yet"); //$NON-NLS-1$
1139 case CTFParser
.INTEGER
:
1140 declaration
= parseInteger(firstChild
);
1142 case CTFParser
.STRING
:
1143 declaration
= parseString(firstChild
);
1145 case CTFParser
.STRUCT
:
1146 declaration
= parseStruct(firstChild
);
1148 case CTFParser
.VARIANT
:
1149 declaration
= parseVariant(firstChild
);
1151 case CTFParser
.ENUM
:
1152 declaration
= parseEnum(firstChild
);
1154 case CTFParser
.IDENTIFIER
:
1155 case CTFParser
.FLOATTOK
:
1156 case CTFParser
.INTTOK
:
1157 case CTFParser
.LONGTOK
:
1158 case CTFParser
.SHORTTOK
:
1159 case CTFParser
.SIGNEDTOK
:
1160 case CTFParser
.UNSIGNEDTOK
:
1161 case CTFParser
.CHARTOK
:
1162 case CTFParser
.DOUBLETOK
:
1163 case CTFParser
.VOIDTOK
:
1164 case CTFParser
.BOOLTOK
:
1165 case CTFParser
.COMPLEXTOK
:
1166 case CTFParser
.IMAGINARYTOK
:
1167 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1170 childTypeError(firstChild
);
1173 assert (declaration
!= null);
1178 * Parses a type specifier list as a user-declared type.
1180 * @param typeSpecifierList
1181 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1182 * @param pointerList
1183 * A list of POINTER nodes that apply to the type specified in
1184 * typeSpecifierList.
1185 * @return The corresponding declaration.
1186 * @throws ParseException
1187 * If the type does not exist (has not been found).
1189 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1190 List
<CommonTree
> pointerList
) throws ParseException
{
1191 /* Create the string representation of the type declaration */
1192 String typeStringRepresentation
= createTypeDeclarationString(
1193 typeSpecifierList
, pointerList
);
1195 /* Use the string representation to search the type in the current scope */
1196 IDeclaration decl
= getCurrentScope().rlookupType(
1197 typeStringRepresentation
);
1200 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1201 + " has not been defined."); //$NON-NLS-1$
1208 * Parses an integer declaration node.
1212 * @return The corresponding integer declaration.
1213 * @throws ParseException
1215 private IntegerDeclaration
parseInteger(CommonTree integer
)
1216 throws ParseException
{
1217 assert (integer
.getType() == CTFParser
.INTEGER
);
1219 List
<CommonTree
> children
= integer
.getChildren();
1222 * If the integer has no attributes, then it is missing the size
1223 * attribute which is required
1225 if (children
== null) {
1226 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1229 /* The return value */
1230 IntegerDeclaration integerDeclaration
= null;
1231 boolean signed
= false;
1232 ByteOrder byteOrder
= trace
.getByteOrder();
1236 String clock
= null;
1238 Encoding encoding
= Encoding
.NONE
;
1240 /* Iterate on all integer children */
1241 for (CommonTree child
: children
) {
1242 switch (child
.getType()) {
1243 case CTFParser
.CTF_EXPRESSION_VAL
:
1245 * An assignment expression must have 2 children, left and right
1247 assert (child
.getChildCount() == 2);
1249 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1250 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1251 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1252 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1254 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1255 assert (leftStrings
!= null);
1257 if (!isUnaryString(leftStrings
.get(0))) {
1258 throw new ParseException(
1259 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1261 String left
= concatenateUnaryStrings(leftStrings
);
1263 if (left
.equals("signed")) { //$NON-NLS-1$
1264 signed
= getSigned(rightNode
);
1265 } else if (left
.equals("byte_order")) { //$NON-NLS-1$
1266 byteOrder
= getByteOrder(rightNode
);
1267 } else if (left
.equals("size")) { //$NON-NLS-1$
1268 size
= getSize(rightNode
);
1269 } else if (left
.equals("align")) { //$NON-NLS-1$
1270 alignment
= getAlignment(rightNode
);
1271 } else if (left
.equals("base")) { //$NON-NLS-1$
1272 base
= getBase(rightNode
);
1273 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1274 encoding
= getEncoding(rightNode
);
1275 } else if (left
.equals("map")) { //$NON-NLS-1$
1276 clock
= getClock(rightNode
);
1278 throw new ParseException("Integer: unknown attribute " + left
); //$NON-NLS-1$
1283 childTypeError(child
);
1289 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1292 if (alignment
== 0) {
1293 if ((size
% 8) == 0) {
1300 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1301 byteOrder
, encoding
, clock
);
1303 assert (integerDeclaration
!= null);
1304 return integerDeclaration
;
1307 private static String
getClock(CommonTree rightNode
) {
1308 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1311 private static StringDeclaration
parseString(CommonTree string
)
1312 throws ParseException
{
1313 assert (string
.getType() == CTFParser
.STRING
);
1315 List
<CommonTree
> children
= string
.getChildren();
1316 StringDeclaration stringDeclaration
= null;
1318 if (children
== null) {
1319 stringDeclaration
= new StringDeclaration();
1321 Encoding encoding
= Encoding
.UTF8
;
1322 for (CommonTree child
: children
) {
1323 switch (child
.getType()) {
1324 case CTFParser
.CTF_EXPRESSION_VAL
:
1326 * An assignment expression must have 2 children, left and
1329 assert (child
.getChildCount() == 2);
1331 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1332 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1333 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1334 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1336 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1337 assert (leftStrings
!= null);
1339 if (!isUnaryString(leftStrings
.get(0))) {
1340 throw new ParseException(
1341 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1343 String left
= concatenateUnaryStrings(leftStrings
);
1345 if (left
.equals("encoding")) { //$NON-NLS-1$
1346 encoding
= getEncoding(rightNode
);
1348 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1354 childTypeError(child
);
1359 stringDeclaration
= new StringDeclaration(encoding
);
1362 return stringDeclaration
;
1366 * Parses a struct declaration and returns the corresponding declaration.
1370 * @return The corresponding struct declaration.
1371 * @throws ParseException
1373 private StructDeclaration
parseStruct(CommonTree struct
)
1374 throws ParseException
{
1375 assert (struct
.getType() == CTFParser
.STRUCT
);
1377 List
<CommonTree
> children
= struct
.getChildren();
1378 assert (children
!= null);
1380 /* The return value */
1381 StructDeclaration structDeclaration
= null;
1384 String structName
= null;
1385 boolean hasName
= false;
1388 CommonTree structBody
= null;
1389 boolean hasBody
= false;
1392 long structAlign
= 0;
1394 /* Loop on all children and identify what we have to work with. */
1395 for (CommonTree child
: children
) {
1396 switch (child
.getType()) {
1397 case CTFParser
.STRUCT_NAME
: {
1400 assert (child
.getChildCount() == 1);
1401 CommonTree structNameIdentifier
= (CommonTree
) child
1404 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1405 structName
= structNameIdentifier
.getText();
1409 case CTFParser
.STRUCT_BODY
: {
1416 case CTFParser
.ALIGN
: {
1417 assert (child
.getChildCount() == 1);
1418 CommonTree structAlignExpression
= (CommonTree
) child
1421 structAlign
= getAlignment(structAlignExpression
);
1426 childTypeError(child
);
1433 * If a struct has just a body and no name (just like the song,
1434 * "A Struct With No Name" by America (sorry for that...)), it's a
1435 * definition of a new type, so we create the type declaration and
1436 * return it. We can't add it to the declaration scope since there is no
1437 * name, but that's what we want because it won't be possible to use it
1438 * again to declare another field.
1440 * If it has just a name, we look it up in the declaration scope and
1441 * return the associated declaration. If it is not found in the
1442 * declaration scope, it means that a struct with that name has not been
1443 * declared, which is an error.
1445 * If it has both, then we create the type declaration and register it
1446 * to the current scope.
1448 * If it has none, then what are we doing here ?
1452 * If struct has a name, check if already defined in the current
1455 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1456 throw new ParseException("struct " + structName
//$NON-NLS-1$
1457 + " already defined."); //$NON-NLS-1$
1460 /* Create the declaration */
1461 structDeclaration
= new StructDeclaration(structAlign
);
1463 /* Parse the body */
1464 parseStructBody(structBody
, structDeclaration
);
1466 /* If struct has name, add it to the current scope. */
1468 getCurrentScope().registerStruct(structName
, structDeclaration
);
1470 } else /* !hasBody */{
1472 /* Name and !body */
1474 /* Lookup the name in the current scope. */
1475 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1478 * If not found, it means that a struct with such name has not
1481 if (structDeclaration
== null) {
1482 throw new ParseException("struct " + structName
//$NON-NLS-1$
1483 + " is not defined"); //$NON-NLS-1$
1486 /* !Name and !body */
1488 /* We can't do anything with that. */
1489 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1493 assert (structDeclaration
!= null);
1494 return structDeclaration
;
1498 * Parses a struct body, adding the fields to specified structure
1502 * A STRUCT_BODY node.
1503 * @param structDeclaration
1504 * The struct declaration.
1505 * @throws ParseException
1507 private void parseStructBody(CommonTree structBody
,
1508 StructDeclaration structDeclaration
) throws ParseException
{
1509 assert (structBody
.getType() == CTFParser
.STRUCT_BODY
);
1511 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1514 * If structDeclaration is null, structBody has no children and the
1515 * struct body is empty.
1517 if (structDeclarations
!= null) {
1520 for (CommonTree declarationNode
: structDeclarations
) {
1521 switch (declarationNode
.getType()) {
1522 case CTFParser
.TYPEALIAS
:
1523 parseTypealias(declarationNode
);
1525 case CTFParser
.TYPEDEF
:
1526 parseTypedef(declarationNode
);
1528 case CTFParser
.SV_DECLARATION
:
1529 parseStructDeclaration(declarationNode
, structDeclaration
);
1532 childTypeError(declarationNode
);
1541 * Parses a declaration found in a struct.
1543 * @param declaration
1544 * A SV_DECLARATION node.
1546 * A struct declaration. (I know, little name clash here...)
1547 * @throws ParseException
1549 private void parseStructDeclaration(CommonTree declaration
,
1550 StructDeclaration struct
) throws ParseException
{
1551 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
1553 List
<CommonTree
> children
= declaration
.getChildren();
1554 assert (children
!= null);
1556 /* Get the type specifier list node */
1557 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
1558 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1559 assert (typeSpecifierListNode
!= null);
1561 /* Get the type declarator list node */
1562 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
1563 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1564 assert (typeDeclaratorListNode
!= null);
1566 /* Get the type declarator list */
1567 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
1569 assert (typeDeclaratorList
!= null);
1572 * For each type declarator, parse the declaration and add a field to
1575 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1576 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
1578 StringBuilder identifierSB
= new StringBuilder();
1580 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1581 typeSpecifierListNode
, identifierSB
);
1582 String fieldName
= identifierSB
.toString();
1584 if (struct
.hasField(fieldName
)) {
1585 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1589 struct
.addField(fieldName
, decl
);
1595 * Parses an enum declaration and returns the corresponding declaration.
1599 * @return The corresponding enum declaration.
1600 * @throws ParseException
1602 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1603 assert (_enum
.getType() == CTFParser
.ENUM
);
1605 List
<CommonTree
> children
= _enum
.getChildren();
1606 assert (children
!= null);
1608 /* The return value */
1609 EnumDeclaration enumDeclaration
= null;
1612 String enumName
= null;
1615 CommonTree enumBody
= null;
1617 /* Container type */
1618 IntegerDeclaration containerTypeDeclaration
= null;
1620 /* Loop on all children and identify what we have to work with. */
1621 for (CommonTree child
: children
) {
1622 switch (child
.getType()) {
1623 case CTFParser
.ENUM_NAME
: {
1624 assert (enumName
== null);
1626 assert (child
.getChildCount() == 1);
1627 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1629 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1630 enumName
= enumNameIdentifier
.getText();
1634 case CTFParser
.ENUM_BODY
: {
1635 assert (enumBody
== null);
1641 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1642 assert (containerTypeDeclaration
== null);
1644 containerTypeDeclaration
= parseEnumContainerType(child
);
1649 childTypeError(child
);
1655 * If the container type has not been defined explicitly, we assume it
1658 if (containerTypeDeclaration
== null) {
1659 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1662 throw new ParseException(
1663 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1664 } else if (!(decl
instanceof IntegerDeclaration
)) {
1665 throw new ParseException(
1666 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1669 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1673 * If it has a body, it's a new declaration, otherwise it's a reference
1674 * to an existing declaration. Same logic as struct.
1676 if (enumBody
!= null) {
1678 * If enum has a name, check if already defined in the current
1681 if ((enumName
!= null)
1682 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1683 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1684 + " already defined"); //$NON-NLS-1$
1687 /* Create the declaration */
1688 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1690 /* Parse the body */
1691 parseEnumBody(enumBody
, enumDeclaration
);
1693 /* If the enum has name, add it to the current scope. */
1694 if (enumName
!= null) {
1695 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1698 if (enumName
!= null) {
1699 /* Name and !body */
1701 /* Lookup the name in the current scope. */
1702 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1705 * If not found, it means that an enum with such name has not
1708 if (enumDeclaration
== null) {
1709 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1710 + " is not defined"); //$NON-NLS-1$
1713 /* !Name and !body */
1714 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1718 return enumDeclaration
;
1723 * Parses an enum body, adding the enumerators to the specified enum
1727 * An ENUM_BODY node.
1728 * @param enumDeclaration
1729 * The enum declaration.
1730 * @throws ParseException
1732 private void parseEnumBody(CommonTree enumBody
,
1733 EnumDeclaration enumDeclaration
) throws ParseException
{
1734 assert (enumBody
.getType() == CTFParser
.ENUM_BODY
);
1736 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1737 /* enum body can't be empty (unlike struct). */
1738 assert (enumerators
!= null);
1743 * Start at -1, so that if the first enumrator has no explicit value, it
1748 for (CommonTree enumerator
: enumerators
) {
1749 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1758 * Parses an enumerator node and adds an enumerator declaration to an
1759 * enumeration declaration.
1761 * The high value of the range of the last enumerator is needed in case the
1762 * current enumerator does not specify its value.
1765 * An ENUM_ENUMERATOR node.
1766 * @param enumDeclaration
1767 * en enumeration declaration to which will be added the
1770 * The high value of the range of the last enumerator
1771 * @return The high value of the value range of the current enumerator.
1772 * @throws ParseException
1774 private static long parseEnumEnumerator(CommonTree enumerator
,
1775 EnumDeclaration enumDeclaration
, long lastHigh
)
1776 throws ParseException
{
1777 assert (enumerator
.getType() == CTFParser
.ENUM_ENUMERATOR
);
1779 List
<CommonTree
> children
= enumerator
.getChildren();
1780 assert (children
!= null);
1782 long low
= 0, high
= 0;
1783 boolean valueSpecified
= false;
1784 String label
= null;
1786 for (CommonTree child
: children
) {
1787 if (isUnaryString(child
)) {
1788 label
= parseUnaryString(child
);
1789 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1790 assert (child
.getChildCount() == 1);
1791 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1793 valueSpecified
= true;
1795 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1797 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1798 assert (child
.getChildCount() == 2);
1799 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1800 assert (isUnaryInteger((CommonTree
) child
.getChild(1)));
1802 valueSpecified
= true;
1804 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1805 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1807 childTypeError(child
);
1811 assert (label
!= null);
1813 if (!valueSpecified
) {
1819 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1822 if (!enumDeclaration
.add(low
, high
, label
)) {
1823 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1830 * Parses an enum container type node and returns the corresponding integer
1833 * @param enumContainerType
1834 * An ENUM_CONTAINER_TYPE node.
1835 * @return An integer declaration corresponding to the container type.
1836 * @throws ParseException
1837 * If the type does not parse correctly or if it is not an
1840 private IntegerDeclaration
parseEnumContainerType(
1841 CommonTree enumContainerType
) throws ParseException
{
1842 assert (enumContainerType
.getType() == CTFParser
.ENUM_CONTAINER_TYPE
);
1844 /* Get the child, which should be a type specifier list */
1845 assert (enumContainerType
.getChildCount() == 1);
1846 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
1849 /* Parse it and get the corresponding declaration */
1850 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1852 /* If is is an integer, return it, else throw an error */
1853 if (decl
instanceof IntegerDeclaration
) {
1854 return (IntegerDeclaration
) decl
;
1856 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1859 private VariantDeclaration
parseVariant(CommonTree variant
)
1860 throws ParseException
{
1861 assert (variant
.getType() == CTFParser
.VARIANT
);
1863 List
<CommonTree
> children
= variant
.getChildren();
1864 VariantDeclaration variantDeclaration
= null;
1866 boolean hasName
= false;
1867 String variantName
= null;
1869 boolean hasBody
= false;
1870 CommonTree variantBody
= null;
1872 boolean hasTag
= false;
1873 String variantTag
= null;
1875 for (CommonTree child
: children
) {
1876 switch (child
.getType()) {
1877 case CTFParser
.VARIANT_NAME
:
1878 assert (variantName
== null);
1882 assert (child
.getChildCount() == 1);
1883 CommonTree variantNameIdentifier
= (CommonTree
) child
1886 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1887 variantName
= variantNameIdentifier
.getText();
1890 case CTFParser
.VARIANT_TAG
:
1891 assert (variantTag
== null);
1895 assert (child
.getChildCount() == 1);
1896 CommonTree variantTagIdentifier
= (CommonTree
) child
1899 assert (variantTagIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1900 variantTag
= variantTagIdentifier
.getText();
1903 case CTFParser
.VARIANT_BODY
:
1904 assert (variantBody
== null);
1908 variantBody
= child
;
1912 childTypeError(child
);
1919 * If variant has a name, check if already defined in the current
1923 && (getCurrentScope().lookupVariant(variantName
) != null)) {
1924 throw new ParseException("variant " + variantName
//$NON-NLS-1$
1925 + " already defined."); //$NON-NLS-1$
1928 /* Create the declaration */
1929 variantDeclaration
= new VariantDeclaration();
1931 /* Parse the body */
1932 parseVariantBody(variantBody
, variantDeclaration
);
1934 /* If variant has name, add it to the current scope. */
1936 getCurrentScope().registerVariant(variantName
,
1937 variantDeclaration
);
1939 } else /* !hasBody */{
1941 /* Name and !body */
1943 /* Lookup the name in the current scope. */
1944 variantDeclaration
= getCurrentScope().rlookupVariant(
1948 * If not found, it means that a struct with such name has not
1951 if (variantDeclaration
== null) {
1952 throw new ParseException("variant " + variantName
//$NON-NLS-1$
1953 + " is not defined"); //$NON-NLS-1$
1956 /* !Name and !body */
1958 /* We can't do anything with that. */
1959 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
1964 variantDeclaration
.setTag(variantTag
);
1967 assert (variantDeclaration
!= null);
1968 return variantDeclaration
;
1971 private void parseVariantBody(CommonTree variantBody
,
1972 VariantDeclaration variantDeclaration
) throws ParseException
{
1973 assert (variantBody
.getType() == CTFParser
.VARIANT_BODY
);
1975 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
1976 assert (variantDeclarations
!= null);
1980 for (CommonTree declarationNode
: variantDeclarations
) {
1981 switch (declarationNode
.getType()) {
1982 case CTFParser
.TYPEALIAS
:
1983 parseTypealias(declarationNode
);
1985 case CTFParser
.TYPEDEF
:
1986 parseTypedef(declarationNode
);
1988 case CTFParser
.SV_DECLARATION
:
1989 parseVariantDeclaration(declarationNode
, variantDeclaration
);
1992 childTypeError(declarationNode
);
2000 private void parseVariantDeclaration(CommonTree declaration
,
2001 VariantDeclaration variant
) throws ParseException
{
2002 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
2004 List
<CommonTree
> children
= declaration
.getChildren();
2005 assert (children
!= null);
2007 /* Get the type specifier list node */
2008 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
2009 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2010 assert (typeSpecifierListNode
!= null);
2012 /* Get the type declarator list node */
2013 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
2014 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2015 assert (typeDeclaratorListNode
!= null);
2017 /* Get the type declarator list */
2018 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
2020 assert (typeDeclaratorList
!= null);
2023 * For each type declarator, parse the declaration and add a field to
2026 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2027 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
2029 StringBuilder identifierSB
= new StringBuilder();
2031 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2032 typeSpecifierListNode
, identifierSB
);
2034 if (variant
.hasField(identifierSB
.toString())) {
2035 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2036 + identifierSB
.toString());
2039 variant
.addField(identifierSB
.toString(), decl
);
2044 * Creates the string representation of a type declaration (type specifier
2047 * @param typeSpecifierList
2048 * A TYPE_SPECIFIER_LIST node.
2050 * A list of POINTER nodes.
2051 * @return The string representation.
2052 * @throws ParseException
2054 private static String
createTypeDeclarationString(
2055 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2056 throws ParseException
{
2057 StringBuilder sb
= new StringBuilder();
2059 createTypeSpecifierListString(typeSpecifierList
, sb
);
2060 createPointerListString(pointers
, sb
);
2062 return sb
.toString();
2066 * Creates the string representation of a list of type specifiers.
2068 * @param typeSpecifierList
2069 * A TYPE_SPECIFIER_LIST node.
2071 * A StringBuilder to which will be appended the string.
2072 * @throws ParseException
2074 private static void createTypeSpecifierListString(
2075 CommonTree typeSpecifierList
, StringBuilder sb
)
2076 throws ParseException
{
2077 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
2079 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2080 assert (children
!= null);
2082 boolean firstItem
= true;
2084 for (CommonTree child
: children
) {
2092 /* Append the string that represents this type specifier. */
2093 createTypeSpecifierString(child
, sb
);
2098 * Creates the string representation of a type specifier.
2100 * @param typeSpecifier
2101 * A TYPE_SPECIFIER node.
2103 * A StringBuilder to which will be appended the string.
2104 * @throws ParseException
2106 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2107 StringBuilder sb
) throws ParseException
{
2108 switch (typeSpecifier
.getType()) {
2109 case CTFParser
.FLOATTOK
:
2110 case CTFParser
.INTTOK
:
2111 case CTFParser
.LONGTOK
:
2112 case CTFParser
.SHORTTOK
:
2113 case CTFParser
.SIGNEDTOK
:
2114 case CTFParser
.UNSIGNEDTOK
:
2115 case CTFParser
.CHARTOK
:
2116 case CTFParser
.DOUBLETOK
:
2117 case CTFParser
.VOIDTOK
:
2118 case CTFParser
.BOOLTOK
:
2119 case CTFParser
.COMPLEXTOK
:
2120 case CTFParser
.IMAGINARYTOK
:
2121 case CTFParser
.CONSTTOK
:
2122 case CTFParser
.IDENTIFIER
:
2123 sb
.append(typeSpecifier
.getText());
2125 case CTFParser
.STRUCT
: {
2126 CommonTree structName
= (CommonTree
) typeSpecifier
2127 .getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2128 if (structName
== null) {
2129 throw new ParseException(
2130 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2132 assert (structName
.getChildCount() == 1);
2134 CommonTree structNameIdentifier
= (CommonTree
) structName
2136 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2138 sb
.append(structNameIdentifier
.getText());
2141 case CTFParser
.VARIANT
: {
2142 CommonTree variantName
= (CommonTree
) typeSpecifier
2143 .getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2144 if (variantName
== null) {
2145 throw new ParseException(
2146 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2148 assert (variantName
.getChildCount() == 1);
2150 CommonTree variantNameIdentifier
= (CommonTree
) variantName
2152 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2154 sb
.append(variantNameIdentifier
.getText());
2157 case CTFParser
.ENUM
: {
2158 CommonTree enumName
= (CommonTree
) typeSpecifier
2159 .getFirstChildWithType(CTFParser
.ENUM_NAME
);
2160 if (enumName
== null) {
2161 throw new ParseException(
2162 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2164 assert (enumName
.getChildCount() == 1);
2166 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2167 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2169 sb
.append(enumNameIdentifier
.getText());
2172 case CTFParser
.FLOATING_POINT
:
2173 case CTFParser
.INTEGER
:
2174 case CTFParser
.STRING
:
2175 throw new ParseException(
2176 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2179 childTypeError(typeSpecifier
);
2185 * Creates the string representation of a list of pointers.
2187 * @param pointerList
2188 * A list of pointer nodes. If pointerList is null, this function
2191 * A stringbuilder to which will be appended the string.
2193 private static void createPointerListString(List
<CommonTree
> pointerList
,
2195 if (pointerList
== null) {
2199 for (CommonTree pointer
: pointerList
) {
2200 assert (pointer
.getType() == CTFParser
.POINTER
);
2202 sb
.append(" *"); //$NON-NLS-1$
2203 if (pointer
.getChildCount() > 0) {
2204 assert (pointer
.getChildCount() == 1);
2205 CommonTree constQualifier
= (CommonTree
) pointer
.getChild(0);
2206 assert (constQualifier
.getType() == CTFParser
.CONSTTOK
);
2208 sb
.append(" const"); //$NON-NLS-1$
2215 * The node to check.
2216 * @return True if the given node is an unary string or unary integer.
2218 private static boolean isUnaryExpression(CommonTree node
) {
2219 return isUnaryInteger(node
) || isUnaryString(node
);
2224 * The node to check.
2225 * @return True if the given node is an unary string.
2227 private static boolean isUnaryString(CommonTree node
) {
2228 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (node
2229 .getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2234 * The node to check.
2235 * @return True if the given node is an unary integer.
2237 private static boolean isUnaryInteger(CommonTree node
) {
2238 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
)
2239 || (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) || (node
2240 .getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2244 * Parses a unary string node and return the string value.
2246 * @param unaryString
2247 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2248 * or UNARY_EXPRESSION_STRING_QUOTES).
2249 * @return The string value.
2252 * It would be really nice to remove the quotes earlier, such as in the
2255 private static String
parseUnaryString(CommonTree unaryString
) {
2256 assert (isUnaryString(unaryString
));
2258 assert (unaryString
.getChildCount() == 1);
2259 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2260 assert (value
!= null);
2261 String strval
= value
.getText();
2264 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2265 strval
= strval
.substring(1, strval
.length() - 1);
2272 * Parses an unary integer (dec, hex or oct).
2274 * @param unaryInteger
2275 * An unary integer node.
2276 * @return The integer value.
2278 private static long parseUnaryInteger(CommonTree unaryInteger
) {
2279 assert (isUnaryInteger(unaryInteger
));
2281 assert (unaryInteger
.getChildCount() >= 1);
2283 List
<CommonTree
> children
= unaryInteger
.getChildren();
2284 CommonTree value
= children
.get(0);
2285 String strval
= value
.getText();
2289 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2290 intval
= Long
.parseLong(strval
, 10);
2291 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2292 intval
= Long
.parseLong(strval
, 0x10);
2293 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2294 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2297 /* The rest of children are sign */
2298 if ((children
.size() % 2) == 0) {
2304 private static long getMajorOrMinor(CommonTree rightNode
)
2305 throws ParseException
{
2306 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2307 assert (rightNode
.getChildCount() > 0);
2309 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2311 if (isUnaryInteger(firstChild
)) {
2312 if (rightNode
.getChildCount() > 1) {
2313 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2316 long m
= parseUnaryInteger(firstChild
);
2319 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2324 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2327 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2328 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2329 assert (rightNode
.getChildCount() > 0);
2331 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2333 if (isUnaryString(firstChild
)) {
2334 if (rightNode
.getChildCount() > 1) {
2335 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2338 String uuidstr
= parseUnaryString(firstChild
);
2341 UUID uuid
= UUID
.fromString(uuidstr
);
2343 } catch (IllegalArgumentException e
) {
2344 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2347 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2351 * Gets the value of a "signed" integer attribute.
2355 * @return The "signed" value as a boolean.
2356 * @throws ParseException
2358 private static boolean getSigned(CommonTree rightNode
)
2359 throws ParseException
{
2360 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2361 assert (rightNode
.getChildCount() > 0);
2363 boolean ret
= false;
2364 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2366 if (isUnaryString(firstChild
)) {
2367 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2369 if (strval
.equals("true") || strval
.equals("TRUE")) { //$NON-NLS-1$ //$NON-NLS-2$
2371 } else if (strval
.equals("false") || strval
.equals("FALSE")) { //$NON-NLS-1$ //$NON-NLS-2$
2374 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2375 + firstChild
.getChild(0).getText());
2377 } else if (isUnaryInteger(firstChild
)) {
2378 /* Happens if the value is something like "1234.hello" */
2379 if (rightNode
.getChildCount() > 1) {
2380 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2383 long intval
= parseUnaryInteger(firstChild
);
2387 } else if (intval
== 0) {
2390 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2391 + firstChild
.getChild(0).getText());
2394 throw new ParseException();
2401 * Gets the value of a "byte_order" integer attribute.
2405 * @return The "byte_order" value.
2406 * @throws ParseException
2408 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2409 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2410 assert (rightNode
.getChildCount() > 0);
2412 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2414 if (isUnaryString(firstChild
)) {
2415 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2417 if (strval
.equals("le")) { //$NON-NLS-1$
2418 return ByteOrder
.LITTLE_ENDIAN
;
2419 } else if (strval
.equals("be") || strval
.equals("network")) { //$NON-NLS-1$ //$NON-NLS-2$
2420 return ByteOrder
.BIG_ENDIAN
;
2421 } else if (strval
.equals("native")) { //$NON-NLS-1$
2422 return trace
.getByteOrder();
2424 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2427 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2431 * Determines if the given value is a valid alignment value.
2434 * The value to check.
2435 * @return True if it is valid.
2437 private static boolean isValidAlignment(long alignment
) {
2438 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2442 * Gets the value of a "size" integer attribute.
2446 * @return The "size" value.
2447 * @throws ParseException
2449 private static long getSize(CommonTree rightNode
) throws ParseException
{
2450 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2451 assert (rightNode
.getChildCount() > 0);
2453 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2455 if (isUnaryInteger(firstChild
)) {
2456 if (rightNode
.getChildCount() > 1) {
2457 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2460 long size
= parseUnaryInteger(firstChild
);
2463 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2468 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2472 * Gets the value of a "align" integer or struct attribute.
2475 * A CTF_RIGHT node or directly an unary integer.
2476 * @return The align value.
2477 * @throws ParseException
2479 private static long getAlignment(CommonTree node
) throws ParseException
{
2480 assert (isUnaryExpression(node
) || (node
.getType() == CTFParser
.CTF_RIGHT
));
2483 * If a CTF_RIGHT node was passed, call getAlignment with the first
2486 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2487 if (node
.getChildCount() > 1) {
2488 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2491 return getAlignment((CommonTree
) node
.getChild(0));
2492 } else if (isUnaryInteger(node
)) {
2493 long alignment
= parseUnaryInteger(node
);
2495 if (!isValidAlignment(alignment
)) {
2496 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2502 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2506 * Gets the value of a "base" integer attribute.
2509 * An CTF_RIGHT node.
2510 * @return The "base" value.
2511 * @throws ParseException
2513 private static int getBase(CommonTree rightNode
) throws ParseException
{
2514 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2515 assert (rightNode
.getChildCount() > 0);
2517 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2519 if (isUnaryInteger(firstChild
)) {
2520 if (rightNode
.getChildCount() > 1) {
2521 throw new ParseException("invalid base value"); //$NON-NLS-1$
2524 long intval
= parseUnaryInteger(firstChild
);
2525 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2526 || (intval
== 16)) {
2527 return (int) intval
;
2529 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2530 } else if (isUnaryString(firstChild
)) {
2531 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2533 if (strval
.equals("decimal") || strval
.equals("dec") //$NON-NLS-1$ //$NON-NLS-2$
2534 || strval
.equals("d") || strval
.equals("i") //$NON-NLS-1$ //$NON-NLS-2$
2535 || strval
.equals("u")) { //$NON-NLS-1$
2537 } else if (strval
.equals("hexadecimal") || strval
.equals("hex") //$NON-NLS-1$ //$NON-NLS-2$
2538 || strval
.equals("x") || strval
.equals("X") //$NON-NLS-1$ //$NON-NLS-2$
2539 || strval
.equals("p")) { //$NON-NLS-1$
2541 } else if (strval
.equals("octal") || strval
.equals("oct") //$NON-NLS-1$ //$NON-NLS-2$
2542 || strval
.equals("o")) { //$NON-NLS-1$
2544 } else if (strval
.equals("binary") || strval
.equals("b")) { //$NON-NLS-1$ //$NON-NLS-2$
2547 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2550 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2555 * Gets the value of an "encoding" integer attribute.
2559 * @return The "encoding" value.
2560 * @throws ParseException
2562 private static Encoding
getEncoding(CommonTree rightNode
)
2563 throws ParseException
{
2564 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2566 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2568 if (isUnaryString(firstChild
)) {
2569 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2571 if (strval
.equals("UTF8")) { //$NON-NLS-1$
2572 return Encoding
.UTF8
;
2573 } else if (strval
.equals("ASCII")) { //$NON-NLS-1$
2574 return Encoding
.ASCII
;
2575 } else if (strval
.equals("none")) { //$NON-NLS-1$
2576 return Encoding
.NONE
;
2578 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2581 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2584 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2585 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2586 assert (rightNode
.getChildCount() > 0);
2588 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2590 if (isUnaryInteger(firstChild
)) {
2591 if (rightNode
.getChildCount() > 1) {
2592 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2595 long intval
= parseUnaryInteger(firstChild
);
2599 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2602 private static String
getEventName(CommonTree rightNode
)
2603 throws ParseException
{
2604 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2605 assert (rightNode
.getChildCount() > 0);
2607 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2609 if (isUnaryString(firstChild
)) {
2610 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2614 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2617 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2618 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2619 assert (rightNode
.getChildCount() > 0);
2621 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2623 if (isUnaryInteger(firstChild
)) {
2624 if (rightNode
.getChildCount() > 1) {
2625 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2628 long intval
= parseUnaryInteger(firstChild
);
2632 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2636 * Concatenates a list of unary strings separated by arrows (->) or dots.
2639 * A list, first element being an unary string, subsequent
2640 * elements being ARROW or DOT nodes with unary strings as child.
2641 * @return The string representation of the unary string chain.
2643 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2644 assert ((strings
!= null) && (strings
.size() > 0));
2646 StringBuilder sb
= new StringBuilder();
2648 CommonTree first
= strings
.get(0);
2649 sb
.append(parseUnaryString(first
));
2651 boolean isFirst
= true;
2653 for (CommonTree ref
: strings
) {
2659 assert ((ref
.getType() == CTFParser
.ARROW
) || (ref
.getType() == CTFParser
.DOT
));
2660 assert (ref
.getChildCount() == 1);
2662 CommonTree id
= (CommonTree
) ref
.getChild(0);
2664 if (ref
.getType() == CTFParser
.ARROW
) {
2665 sb
.append("->"); //$NON-NLS-1$
2670 sb
.append(parseUnaryString(id
));
2673 return sb
.toString();
2677 * Throws a ParseException stating that the parent-child relation between
2678 * the given node and its parent is not valid. It means that the shape of
2679 * the AST is unexpected.
2682 * The invalid child node.
2683 * @throws ParseException
2685 private static void childTypeError(CommonTree child
) throws ParseException
{
2686 CommonTree parent
= (CommonTree
) child
.getParent();
2687 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2688 + " can't have a child of type " //$NON-NLS-1$
2689 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2691 throw new ParseException(error
);
2694 // ------------------------------------------------------------------------
2696 // ------------------------------------------------------------------------
2699 * Adds a new declaration scope on the top of the scope stack.
2701 private void pushScope() {
2702 scope
= new DeclarationScope(scope
);
2706 * Removes the top declaration scope from the scope stack.
2708 private void popScope() {
2709 assert (scope
!= null);
2710 scope
= scope
.getParentScope();
2714 * Returns the current declaration scope.
2716 * @return The current declaration scope.
2718 private DeclarationScope
getCurrentScope() {
2719 assert (scope
!= null);