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
) {
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
);
724 else if (left
.equals("loglevel")){ //$NON-NLS-1$
726 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0)) ;
727 event
.setLogLevel(logLevel
);
729 throw new ParseException("Unknown event attribute : " + left
); //$NON-NLS-1$
734 * Parses a declaration at the root level.
737 * The declaration subtree.
738 * @throws ParseException
740 private void parseRootDeclaration(CommonTree declaration
)
741 throws ParseException
{
742 assert (declaration
.getType() == CTFParser
.DECLARATION
);
744 List
<CommonTree
> children
= declaration
.getChildren();
745 assert (children
!= null);
747 for (CommonTree child
: children
) {
748 switch (child
.getType()) {
749 case CTFParser
.TYPEDEF
:
752 case CTFParser
.TYPEALIAS
:
753 parseTypealias(child
);
755 case CTFParser
.TYPE_SPECIFIER_LIST
:
756 parseTypeSpecifierList(child
, null);
759 childTypeError(child
);
765 * Parses a typealias node. It parses the target, the alias, and registers
766 * the type in the current scope.
770 * @throws ParseException
772 private void parseTypealias(CommonTree typealias
) throws ParseException
{
773 assert (typealias
.getType() == CTFParser
.TYPEALIAS
);
775 List
<CommonTree
> children
= typealias
.getChildren();
776 assert (children
!= null);
778 CommonTree target
= null;
779 CommonTree alias
= null;
781 for (CommonTree child
: children
) {
782 switch (child
.getType()) {
783 case CTFParser
.TYPEALIAS_TARGET
:
784 assert (target
== null);
787 case CTFParser
.TYPEALIAS_ALIAS
:
788 assert (alias
== null);
792 childTypeError(child
);
797 assert (target
!= null);
798 assert (alias
!= null);
800 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
802 if (targetDeclaration
instanceof VariantDeclaration
) {
803 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
804 throw new ParseException(
805 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
809 String aliasString
= parseTypealiasAlias(alias
);
811 getCurrentScope().registerType(aliasString
, targetDeclaration
);
815 * Parses the target part of a typealias and gets the corresponding
819 * A TYPEALIAS_TARGET node.
820 * @return The corresponding declaration.
821 * @throws ParseException
823 private IDeclaration
parseTypealiasTarget(CommonTree target
)
824 throws ParseException
{
825 assert (target
.getType() == CTFParser
.TYPEALIAS_TARGET
);
827 List
<CommonTree
> children
= target
.getChildren();
828 assert (children
!= null);
830 CommonTree typeSpecifierList
= null;
831 CommonTree typeDeclaratorList
= null;
832 CommonTree typeDeclarator
= null;
833 StringBuilder identifierSB
= new StringBuilder();
835 for (CommonTree child
: children
) {
836 switch (child
.getType()) {
837 case CTFParser
.TYPE_SPECIFIER_LIST
:
838 assert (typeSpecifierList
== null);
839 typeSpecifierList
= child
;
841 case CTFParser
.TYPE_DECLARATOR_LIST
:
842 assert (typeDeclaratorList
== null);
843 typeDeclaratorList
= child
;
846 childTypeError(child
);
851 assert (typeSpecifierList
!= null);
853 if (typeDeclaratorList
!= null) {
855 * Only allow one declarator
857 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
858 * otherwise the new type puint8_t would maps to two different
861 if (typeDeclaratorList
.getChildCount() != 1) {
862 throw new ParseException(
863 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
866 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
869 /* Parse the target type and get the declaration */
870 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
871 typeSpecifierList
, identifierSB
);
874 * We don't allow identifier in the target
876 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
879 if (identifierSB
.length() > 0) {
880 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
881 + ") not expected in the typealias target"); //$NON-NLS-1$
884 return targetDeclaration
;
888 * Parses the alias part of a typealias. It parses the underlying specifier
889 * list and declarator and creates the string representation that will be
890 * used to register the type.
893 * A TYPEALIAS_ALIAS node.
894 * @return The string representation of the alias.
895 * @throws ParseException
897 private static String
parseTypealiasAlias(CommonTree alias
)
898 throws ParseException
{
899 assert (alias
.getType() == CTFParser
.TYPEALIAS_ALIAS
);
901 List
<CommonTree
> children
= alias
.getChildren();
902 assert (children
!= null);
904 CommonTree typeSpecifierList
= null;
905 CommonTree typeDeclaratorList
= null;
906 CommonTree typeDeclarator
= null;
907 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
909 for (CommonTree child
: children
) {
910 switch (child
.getType()) {
911 case CTFParser
.TYPE_SPECIFIER_LIST
:
912 assert (typeSpecifierList
== null);
913 typeSpecifierList
= child
;
915 case CTFParser
.TYPE_DECLARATOR_LIST
:
916 assert (typeDeclaratorList
== null);
917 typeDeclaratorList
= child
;
920 childTypeError(child
);
925 /* If there is a type declarator list, extract the pointers */
926 if (typeDeclaratorList
!= null) {
928 * Only allow one declarator
930 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
932 if (typeDeclaratorList
.getChildCount() != 1) {
933 throw new ParseException(
934 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
937 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
939 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
941 assert (typeDeclaratorChildren
!= null);
943 for (CommonTree child
: typeDeclaratorChildren
) {
944 switch (child
.getType()) {
945 case CTFParser
.POINTER
:
948 case CTFParser
.IDENTIFIER
:
949 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
950 + ") not expected in the typealias target"); //$NON-NLS-1$
953 childTypeError(child
);
959 return createTypeDeclarationString(typeSpecifierList
, pointers
);
963 * Parses a typedef node. This creates and registers a new declaration for
964 * each declarator found in the typedef.
968 * @throws ParseException
969 * If there is an error creating the declaration.
971 private void parseTypedef(CommonTree typedef
) throws ParseException
{
972 assert (typedef
.getType() == CTFParser
.TYPEDEF
);
974 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
975 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
976 assert (typeDeclaratorListNode
!= null);
978 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
979 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
980 assert (typeSpecifierListNode
!= null);
982 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
984 assert (typeDeclaratorList
!= null);
986 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
987 StringBuilder identifierSB
= new StringBuilder();
989 IDeclaration type_declaration
= parseTypeDeclarator(
990 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
992 if (type_declaration
instanceof VariantDeclaration
) {
993 if (((VariantDeclaration
) type_declaration
).isTagged()) {
994 throw new ParseException(
995 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
999 getCurrentScope().registerType(identifierSB
.toString(),
1005 * Parses a pair type declarator / type specifier list and returns the
1006 * corresponding declaration. If it is present, it also writes the
1007 * identifier of the declarator in the given {@link StringBuilder}.
1009 * @param typeDeclarator
1010 * A TYPE_DECLARATOR node.
1011 * @param typeSpecifierList
1012 * A TYPE_SPECIFIER_LIST node.
1013 * @param identifierSB
1014 * A StringBuilder that will receive the identifier found in the
1016 * @return The corresponding declaration.
1017 * @throws ParseException
1018 * If there is an error finding or creating the declaration.
1020 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1021 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1022 throws ParseException
{
1023 if (typeDeclarator
!= null) {
1024 assert (typeDeclarator
.getType() == CTFParser
.TYPE_DECLARATOR
);
1026 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1028 IDeclaration declaration
= null;
1029 List
<CommonTree
> children
= null;
1030 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1031 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1032 CommonTree identifier
= null;
1034 /* Separate the tokens by type */
1035 if (typeDeclarator
!= null) {
1036 children
= typeDeclarator
.getChildren();
1037 assert (children
!= null);
1038 for (CommonTree child
: children
) {
1040 switch (child
.getType()) {
1041 case CTFParser
.POINTER
:
1042 pointers
.add(child
);
1044 case CTFParser
.IDENTIFIER
:
1045 assert (identifier
== null);
1048 case CTFParser
.LENGTH
:
1052 childTypeError(child
);
1060 * Parse the type specifier list, which is the "base" type. For example,
1061 * it would be int in int a[3][len].
1063 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1066 * Each length subscript means that we must create a nested array or
1067 * sequence. For example, int a[3][len] means that we have an array of 3
1068 * (sequences of length 'len' of (int)).
1070 if (lengths
.size() > 0 ) {
1071 /* We begin at the end */
1072 Collections
.reverse(lengths
);
1074 for (CommonTree length
: lengths
) {
1076 * By looking at the first expression, we can determine whether
1077 * it is an array or a sequence.
1079 List
<CommonTree
> lengthChildren
= length
.getChildren();
1080 assert (lengthChildren
!= null);
1082 CommonTree first
= lengthChildren
.get(0);
1083 if (isUnaryInteger(first
)) {
1085 int arrayLength
= (int) parseUnaryInteger(first
);
1087 if (arrayLength
< 1) {
1088 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1091 /* Create the array declaration. */
1092 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1093 } else if (isUnaryString(first
)) {
1095 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1097 /* Create the sequence declaration. */
1098 declaration
= new SequenceDeclaration(lengthName
,
1101 childTypeError(first
);
1106 if (identifier
!= null) {
1107 identifierSB
.append(identifier
.getText());
1114 * Parses a type specifier list and returns the corresponding declaration.
1116 * @param typeSpecifierList
1117 * A TYPE_SPECIFIER_LIST node.
1118 * @param pointerList
1119 * A list of POINTER nodes that apply to the specified type.
1120 * @return The corresponding declaration.
1121 * @throws ParseException
1122 * If the type has not been defined or if there is an error
1123 * creating the declaration.
1125 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1126 List
<CommonTree
> pointerList
) throws ParseException
{
1127 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1128 IDeclaration declaration
= null;
1131 * By looking at the first element of the type specifier list, we can
1132 * determine which type it belongs to.
1134 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1135 assert (firstChild
!= null); /* grammar */
1137 switch (firstChild
.getType()) {
1138 case CTFParser
.FLOATING_POINT
:
1141 // .log("parseTypeSpecifierList: floating_point not implemented yet"); //$NON-NLS-1$
1142 declaration
= parseFloat(firstChild
);
1144 case CTFParser
.INTEGER
:
1145 declaration
= parseInteger(firstChild
);
1147 case CTFParser
.STRING
:
1148 declaration
= parseString(firstChild
);
1150 case CTFParser
.STRUCT
:
1151 declaration
= parseStruct(firstChild
);
1153 case CTFParser
.VARIANT
:
1154 declaration
= parseVariant(firstChild
);
1156 case CTFParser
.ENUM
:
1157 declaration
= parseEnum(firstChild
);
1159 case CTFParser
.IDENTIFIER
:
1160 case CTFParser
.FLOATTOK
:
1161 case CTFParser
.INTTOK
:
1162 case CTFParser
.LONGTOK
:
1163 case CTFParser
.SHORTTOK
:
1164 case CTFParser
.SIGNEDTOK
:
1165 case CTFParser
.UNSIGNEDTOK
:
1166 case CTFParser
.CHARTOK
:
1167 case CTFParser
.DOUBLETOK
:
1168 case CTFParser
.VOIDTOK
:
1169 case CTFParser
.BOOLTOK
:
1170 case CTFParser
.COMPLEXTOK
:
1171 case CTFParser
.IMAGINARYTOK
:
1172 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1175 childTypeError(firstChild
);
1178 assert (declaration
!= null);
1182 private IDeclaration
parseFloat(CommonTree floatingPoint
) throws ParseException
{
1183 assert (floatingPoint
.getType() == CTFParser
.INTEGER
);
1185 List
<CommonTree
> children
= floatingPoint
.getChildren();
1188 * If the integer has no attributes, then it is missing the size
1189 * attribute which is required
1191 if (children
== null) {
1192 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1195 /* The return value */
1196 FloatDeclaration floatDeclaration
= null;
1197 ByteOrder byteOrder
= trace
.getByteOrder();
1203 Encoding encoding
= Encoding
.NONE
;
1205 /* Iterate on all integer children */
1206 for (CommonTree child
: children
) {
1207 switch (child
.getType()) {
1208 case CTFParser
.CTF_EXPRESSION_VAL
:
1210 * An assignment expression must have 2 children, left and right
1212 assert (child
.getChildCount() == 2);
1214 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1215 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1216 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1217 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1219 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1220 assert (leftStrings
!= null);
1222 if (!isUnaryString(leftStrings
.get(0))) {
1223 throw new ParseException(
1224 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1226 String left
= concatenateUnaryStrings(leftStrings
);
1228 if (left
.equals("exp_dig")) { //$NON-NLS-1$
1229 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1230 } else if (left
.equals("byte_order")) { //$NON-NLS-1$
1231 byteOrder
= getByteOrder(rightNode
);
1232 } else if (left
.equals("mant_dig")) { //$NON-NLS-1$
1233 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1234 } else if (left
.equals("align")) { //$NON-NLS-1$
1235 alignment
= getAlignment(rightNode
);
1237 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1242 childTypeError(child
);
1246 int size
= mantissa
+ exponent
;
1248 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1251 if (alignment
== 0) {
1252 if ((size
% 8) == 0) {
1259 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, encoding
);
1261 assert (floatDeclaration
!= null);
1262 return floatDeclaration
;
1267 * Parses a type specifier list as a user-declared type.
1269 * @param typeSpecifierList
1270 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1271 * @param pointerList
1272 * A list of POINTER nodes that apply to the type specified in
1273 * typeSpecifierList.
1274 * @return The corresponding declaration.
1275 * @throws ParseException
1276 * If the type does not exist (has not been found).
1278 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1279 List
<CommonTree
> pointerList
) throws ParseException
{
1280 /* Create the string representation of the type declaration */
1281 String typeStringRepresentation
= createTypeDeclarationString(
1282 typeSpecifierList
, pointerList
);
1284 /* Use the string representation to search the type in the current scope */
1285 IDeclaration decl
= getCurrentScope().rlookupType(
1286 typeStringRepresentation
);
1289 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1290 + " has not been defined."); //$NON-NLS-1$
1297 * Parses an integer declaration node.
1301 * @return The corresponding integer declaration.
1302 * @throws ParseException
1304 private IntegerDeclaration
parseInteger(CommonTree integer
)
1305 throws ParseException
{
1306 assert (integer
.getType() == CTFParser
.INTEGER
);
1308 List
<CommonTree
> children
= integer
.getChildren();
1311 * If the integer has no attributes, then it is missing the size
1312 * attribute which is required
1314 if (children
== null) {
1315 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1318 /* The return value */
1319 IntegerDeclaration integerDeclaration
= null;
1320 boolean signed
= false;
1321 ByteOrder byteOrder
= trace
.getByteOrder();
1325 String clock
= null;
1327 Encoding encoding
= Encoding
.NONE
;
1329 /* Iterate on all integer children */
1330 for (CommonTree child
: children
) {
1331 switch (child
.getType()) {
1332 case CTFParser
.CTF_EXPRESSION_VAL
:
1334 * An assignment expression must have 2 children, left and right
1336 assert (child
.getChildCount() == 2);
1338 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1339 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1340 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1341 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1343 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1344 assert (leftStrings
!= null);
1346 if (!isUnaryString(leftStrings
.get(0))) {
1347 throw new ParseException(
1348 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1350 String left
= concatenateUnaryStrings(leftStrings
);
1352 if (left
.equals("signed")) { //$NON-NLS-1$
1353 signed
= getSigned(rightNode
);
1354 } else if (left
.equals("byte_order")) { //$NON-NLS-1$
1355 byteOrder
= getByteOrder(rightNode
);
1356 } else if (left
.equals("size")) { //$NON-NLS-1$
1357 size
= getSize(rightNode
);
1358 } else if (left
.equals("align")) { //$NON-NLS-1$
1359 alignment
= getAlignment(rightNode
);
1360 } else if (left
.equals("base")) { //$NON-NLS-1$
1361 base
= getBase(rightNode
);
1362 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1363 encoding
= getEncoding(rightNode
);
1364 } else if (left
.equals("map")) { //$NON-NLS-1$
1365 clock
= getClock(rightNode
);
1367 throw new ParseException("Integer: unknown attribute " + left
); //$NON-NLS-1$
1372 childTypeError(child
);
1378 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1381 if (alignment
== 0) {
1382 if ((size
% 8) == 0) {
1389 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1390 byteOrder
, encoding
, clock
);
1392 assert (integerDeclaration
!= null);
1393 return integerDeclaration
;
1396 private static String
getClock(CommonTree rightNode
) {
1397 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1400 private static StringDeclaration
parseString(CommonTree string
)
1401 throws ParseException
{
1402 assert (string
.getType() == CTFParser
.STRING
);
1404 List
<CommonTree
> children
= string
.getChildren();
1405 StringDeclaration stringDeclaration
= null;
1407 if (children
== null) {
1408 stringDeclaration
= new StringDeclaration();
1410 Encoding encoding
= Encoding
.UTF8
;
1411 for (CommonTree child
: children
) {
1412 switch (child
.getType()) {
1413 case CTFParser
.CTF_EXPRESSION_VAL
:
1415 * An assignment expression must have 2 children, left and
1418 assert (child
.getChildCount() == 2);
1420 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1421 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1422 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1423 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1425 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1426 assert (leftStrings
!= null);
1428 if (!isUnaryString(leftStrings
.get(0))) {
1429 throw new ParseException(
1430 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1432 String left
= concatenateUnaryStrings(leftStrings
);
1434 if (left
.equals("encoding")) { //$NON-NLS-1$
1435 encoding
= getEncoding(rightNode
);
1437 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1443 childTypeError(child
);
1448 stringDeclaration
= new StringDeclaration(encoding
);
1451 return stringDeclaration
;
1455 * Parses a struct declaration and returns the corresponding declaration.
1459 * @return The corresponding struct declaration.
1460 * @throws ParseException
1462 private StructDeclaration
parseStruct(CommonTree struct
)
1463 throws ParseException
{
1464 assert (struct
.getType() == CTFParser
.STRUCT
);
1466 List
<CommonTree
> children
= struct
.getChildren();
1467 assert (children
!= null);
1469 /* The return value */
1470 StructDeclaration structDeclaration
= null;
1473 String structName
= null;
1474 boolean hasName
= false;
1477 CommonTree structBody
= null;
1478 boolean hasBody
= false;
1481 long structAlign
= 0;
1483 /* Loop on all children and identify what we have to work with. */
1484 for (CommonTree child
: children
) {
1485 switch (child
.getType()) {
1486 case CTFParser
.STRUCT_NAME
: {
1489 assert (child
.getChildCount() == 1);
1490 CommonTree structNameIdentifier
= (CommonTree
) child
1493 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1494 structName
= structNameIdentifier
.getText();
1498 case CTFParser
.STRUCT_BODY
: {
1505 case CTFParser
.ALIGN
: {
1506 assert (child
.getChildCount() == 1);
1507 CommonTree structAlignExpression
= (CommonTree
) child
1510 structAlign
= getAlignment(structAlignExpression
);
1515 childTypeError(child
);
1522 * If a struct has just a body and no name (just like the song,
1523 * "A Struct With No Name" by America (sorry for that...)), it's a
1524 * definition of a new type, so we create the type declaration and
1525 * return it. We can't add it to the declaration scope since there is no
1526 * name, but that's what we want because it won't be possible to use it
1527 * again to declare another field.
1529 * If it has just a name, we look it up in the declaration scope and
1530 * return the associated declaration. If it is not found in the
1531 * declaration scope, it means that a struct with that name has not been
1532 * declared, which is an error.
1534 * If it has both, then we create the type declaration and register it
1535 * to the current scope.
1537 * If it has none, then what are we doing here ?
1541 * If struct has a name, check if already defined in the current
1544 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1545 throw new ParseException("struct " + structName
//$NON-NLS-1$
1546 + " already defined."); //$NON-NLS-1$
1549 /* Create the declaration */
1550 structDeclaration
= new StructDeclaration(structAlign
);
1552 /* Parse the body */
1553 parseStructBody(structBody
, structDeclaration
);
1555 /* If struct has name, add it to the current scope. */
1557 getCurrentScope().registerStruct(structName
, structDeclaration
);
1559 } else /* !hasBody */{
1561 /* Name and !body */
1563 /* Lookup the name in the current scope. */
1564 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1567 * If not found, it means that a struct with such name has not
1570 if (structDeclaration
== null) {
1571 throw new ParseException("struct " + structName
//$NON-NLS-1$
1572 + " is not defined"); //$NON-NLS-1$
1575 /* !Name and !body */
1577 /* We can't do anything with that. */
1578 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1582 assert (structDeclaration
!= null);
1583 return structDeclaration
;
1587 * Parses a struct body, adding the fields to specified structure
1591 * A STRUCT_BODY node.
1592 * @param structDeclaration
1593 * The struct declaration.
1594 * @throws ParseException
1596 private void parseStructBody(CommonTree structBody
,
1597 StructDeclaration structDeclaration
) throws ParseException
{
1598 assert (structBody
.getType() == CTFParser
.STRUCT_BODY
);
1600 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1603 * If structDeclaration is null, structBody has no children and the
1604 * struct body is empty.
1606 if (structDeclarations
!= null) {
1609 for (CommonTree declarationNode
: structDeclarations
) {
1610 switch (declarationNode
.getType()) {
1611 case CTFParser
.TYPEALIAS
:
1612 parseTypealias(declarationNode
);
1614 case CTFParser
.TYPEDEF
:
1615 parseTypedef(declarationNode
);
1617 case CTFParser
.SV_DECLARATION
:
1618 parseStructDeclaration(declarationNode
, structDeclaration
);
1621 childTypeError(declarationNode
);
1630 * Parses a declaration found in a struct.
1632 * @param declaration
1633 * A SV_DECLARATION node.
1635 * A struct declaration. (I know, little name clash here...)
1636 * @throws ParseException
1638 private void parseStructDeclaration(CommonTree declaration
,
1639 StructDeclaration struct
) throws ParseException
{
1640 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
1642 List
<CommonTree
> children
= declaration
.getChildren();
1643 assert (children
!= null);
1645 /* Get the type specifier list node */
1646 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
1647 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1648 assert (typeSpecifierListNode
!= null);
1650 /* Get the type declarator list node */
1651 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
1652 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1653 assert (typeDeclaratorListNode
!= null);
1655 /* Get the type declarator list */
1656 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
1658 assert (typeDeclaratorList
!= null);
1661 * For each type declarator, parse the declaration and add a field to
1664 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1665 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
1667 StringBuilder identifierSB
= new StringBuilder();
1669 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1670 typeSpecifierListNode
, identifierSB
);
1671 String fieldName
= identifierSB
.toString();
1673 if (struct
.hasField(fieldName
)) {
1674 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1678 struct
.addField(fieldName
, decl
);
1684 * Parses an enum declaration and returns the corresponding declaration.
1688 * @return The corresponding enum declaration.
1689 * @throws ParseException
1691 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1692 assert (_enum
.getType() == CTFParser
.ENUM
);
1694 List
<CommonTree
> children
= _enum
.getChildren();
1695 assert (children
!= null);
1697 /* The return value */
1698 EnumDeclaration enumDeclaration
= null;
1701 String enumName
= null;
1704 CommonTree enumBody
= null;
1706 /* Container type */
1707 IntegerDeclaration containerTypeDeclaration
= null;
1709 /* Loop on all children and identify what we have to work with. */
1710 for (CommonTree child
: children
) {
1711 switch (child
.getType()) {
1712 case CTFParser
.ENUM_NAME
: {
1713 assert (enumName
== null);
1715 assert (child
.getChildCount() == 1);
1716 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1718 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1719 enumName
= enumNameIdentifier
.getText();
1723 case CTFParser
.ENUM_BODY
: {
1724 assert (enumBody
== null);
1730 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1731 assert (containerTypeDeclaration
== null);
1733 containerTypeDeclaration
= parseEnumContainerType(child
);
1738 childTypeError(child
);
1744 * If the container type has not been defined explicitly, we assume it
1747 if (containerTypeDeclaration
== null) {
1748 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1751 throw new ParseException(
1752 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1753 } else if (!(decl
instanceof IntegerDeclaration
)) {
1754 throw new ParseException(
1755 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1758 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1762 * If it has a body, it's a new declaration, otherwise it's a reference
1763 * to an existing declaration. Same logic as struct.
1765 if (enumBody
!= null) {
1767 * If enum has a name, check if already defined in the current
1770 if ((enumName
!= null)
1771 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1772 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1773 + " already defined"); //$NON-NLS-1$
1776 /* Create the declaration */
1777 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1779 /* Parse the body */
1780 parseEnumBody(enumBody
, enumDeclaration
);
1782 /* If the enum has name, add it to the current scope. */
1783 if (enumName
!= null) {
1784 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1787 if (enumName
!= null) {
1788 /* Name and !body */
1790 /* Lookup the name in the current scope. */
1791 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1794 * If not found, it means that an enum with such name has not
1797 if (enumDeclaration
== null) {
1798 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1799 + " is not defined"); //$NON-NLS-1$
1802 /* !Name and !body */
1803 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1807 return enumDeclaration
;
1812 * Parses an enum body, adding the enumerators to the specified enum
1816 * An ENUM_BODY node.
1817 * @param enumDeclaration
1818 * The enum declaration.
1819 * @throws ParseException
1821 private void parseEnumBody(CommonTree enumBody
,
1822 EnumDeclaration enumDeclaration
) throws ParseException
{
1823 assert (enumBody
.getType() == CTFParser
.ENUM_BODY
);
1825 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1826 /* enum body can't be empty (unlike struct). */
1827 assert (enumerators
!= null);
1832 * Start at -1, so that if the first enumrator has no explicit value, it
1837 for (CommonTree enumerator
: enumerators
) {
1838 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1847 * Parses an enumerator node and adds an enumerator declaration to an
1848 * enumeration declaration.
1850 * The high value of the range of the last enumerator is needed in case the
1851 * current enumerator does not specify its value.
1854 * An ENUM_ENUMERATOR node.
1855 * @param enumDeclaration
1856 * en enumeration declaration to which will be added the
1859 * The high value of the range of the last enumerator
1860 * @return The high value of the value range of the current enumerator.
1861 * @throws ParseException
1863 private static long parseEnumEnumerator(CommonTree enumerator
,
1864 EnumDeclaration enumDeclaration
, long lastHigh
)
1865 throws ParseException
{
1866 assert (enumerator
.getType() == CTFParser
.ENUM_ENUMERATOR
);
1868 List
<CommonTree
> children
= enumerator
.getChildren();
1869 assert (children
!= null);
1871 long low
= 0, high
= 0;
1872 boolean valueSpecified
= false;
1873 String label
= null;
1875 for (CommonTree child
: children
) {
1876 if (isUnaryString(child
)) {
1877 label
= parseUnaryString(child
);
1878 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1879 assert (child
.getChildCount() == 1);
1880 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1882 valueSpecified
= true;
1884 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1886 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1887 assert (child
.getChildCount() == 2);
1888 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1889 assert (isUnaryInteger((CommonTree
) child
.getChild(1)));
1891 valueSpecified
= true;
1893 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1894 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1896 childTypeError(child
);
1900 assert (label
!= null);
1902 if (!valueSpecified
) {
1908 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1911 if (!enumDeclaration
.add(low
, high
, label
)) {
1912 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1919 * Parses an enum container type node and returns the corresponding integer
1922 * @param enumContainerType
1923 * An ENUM_CONTAINER_TYPE node.
1924 * @return An integer declaration corresponding to the container type.
1925 * @throws ParseException
1926 * If the type does not parse correctly or if it is not an
1929 private IntegerDeclaration
parseEnumContainerType(
1930 CommonTree enumContainerType
) throws ParseException
{
1931 assert (enumContainerType
.getType() == CTFParser
.ENUM_CONTAINER_TYPE
);
1933 /* Get the child, which should be a type specifier list */
1934 assert (enumContainerType
.getChildCount() == 1);
1935 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
1938 /* Parse it and get the corresponding declaration */
1939 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1941 /* If is is an integer, return it, else throw an error */
1942 if (decl
instanceof IntegerDeclaration
) {
1943 return (IntegerDeclaration
) decl
;
1945 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1948 private VariantDeclaration
parseVariant(CommonTree variant
)
1949 throws ParseException
{
1950 assert (variant
.getType() == CTFParser
.VARIANT
);
1952 List
<CommonTree
> children
= variant
.getChildren();
1953 VariantDeclaration variantDeclaration
= null;
1955 boolean hasName
= false;
1956 String variantName
= null;
1958 boolean hasBody
= false;
1959 CommonTree variantBody
= null;
1961 boolean hasTag
= false;
1962 String variantTag
= null;
1964 for (CommonTree child
: children
) {
1965 switch (child
.getType()) {
1966 case CTFParser
.VARIANT_NAME
:
1967 assert (variantName
== null);
1971 assert (child
.getChildCount() == 1);
1972 CommonTree variantNameIdentifier
= (CommonTree
) child
1975 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1976 variantName
= variantNameIdentifier
.getText();
1979 case CTFParser
.VARIANT_TAG
:
1980 assert (variantTag
== null);
1984 assert (child
.getChildCount() == 1);
1985 CommonTree variantTagIdentifier
= (CommonTree
) child
1988 assert (variantTagIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1989 variantTag
= variantTagIdentifier
.getText();
1992 case CTFParser
.VARIANT_BODY
:
1993 assert (variantBody
== null);
1997 variantBody
= child
;
2001 childTypeError(child
);
2008 * If variant has a name, check if already defined in the current
2012 && (getCurrentScope().lookupVariant(variantName
) != null)) {
2013 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2014 + " already defined."); //$NON-NLS-1$
2017 /* Create the declaration */
2018 variantDeclaration
= new VariantDeclaration();
2020 /* Parse the body */
2021 parseVariantBody(variantBody
, variantDeclaration
);
2023 /* If variant has name, add it to the current scope. */
2025 getCurrentScope().registerVariant(variantName
,
2026 variantDeclaration
);
2028 } else /* !hasBody */{
2030 /* Name and !body */
2032 /* Lookup the name in the current scope. */
2033 variantDeclaration
= getCurrentScope().rlookupVariant(
2037 * If not found, it means that a struct with such name has not
2040 if (variantDeclaration
== null) {
2041 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2042 + " is not defined"); //$NON-NLS-1$
2045 /* !Name and !body */
2047 /* We can't do anything with that. */
2048 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2053 variantDeclaration
.setTag(variantTag
);
2056 assert (variantDeclaration
!= null);
2057 return variantDeclaration
;
2060 private void parseVariantBody(CommonTree variantBody
,
2061 VariantDeclaration variantDeclaration
) throws ParseException
{
2062 assert (variantBody
.getType() == CTFParser
.VARIANT_BODY
);
2064 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2065 assert (variantDeclarations
!= null);
2069 for (CommonTree declarationNode
: variantDeclarations
) {
2070 switch (declarationNode
.getType()) {
2071 case CTFParser
.TYPEALIAS
:
2072 parseTypealias(declarationNode
);
2074 case CTFParser
.TYPEDEF
:
2075 parseTypedef(declarationNode
);
2077 case CTFParser
.SV_DECLARATION
:
2078 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2081 childTypeError(declarationNode
);
2089 private void parseVariantDeclaration(CommonTree declaration
,
2090 VariantDeclaration variant
) throws ParseException
{
2091 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
2093 List
<CommonTree
> children
= declaration
.getChildren();
2094 assert (children
!= null);
2096 /* Get the type specifier list node */
2097 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
2098 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2099 assert (typeSpecifierListNode
!= null);
2101 /* Get the type declarator list node */
2102 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
2103 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2104 assert (typeDeclaratorListNode
!= null);
2106 /* Get the type declarator list */
2107 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
2109 assert (typeDeclaratorList
!= null);
2112 * For each type declarator, parse the declaration and add a field to
2115 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2116 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
2118 StringBuilder identifierSB
= new StringBuilder();
2120 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2121 typeSpecifierListNode
, identifierSB
);
2123 if (variant
.hasField(identifierSB
.toString())) {
2124 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2125 + identifierSB
.toString());
2128 variant
.addField(identifierSB
.toString(), decl
);
2133 * Creates the string representation of a type declaration (type specifier
2136 * @param typeSpecifierList
2137 * A TYPE_SPECIFIER_LIST node.
2139 * A list of POINTER nodes.
2140 * @return The string representation.
2141 * @throws ParseException
2143 private static String
createTypeDeclarationString(
2144 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2145 throws ParseException
{
2146 StringBuilder sb
= new StringBuilder();
2148 createTypeSpecifierListString(typeSpecifierList
, sb
);
2149 createPointerListString(pointers
, sb
);
2151 return sb
.toString();
2155 * Creates the string representation of a list of type specifiers.
2157 * @param typeSpecifierList
2158 * A TYPE_SPECIFIER_LIST node.
2160 * A StringBuilder to which will be appended the string.
2161 * @throws ParseException
2163 private static void createTypeSpecifierListString(
2164 CommonTree typeSpecifierList
, StringBuilder sb
)
2165 throws ParseException
{
2166 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
2168 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2169 assert (children
!= null);
2171 boolean firstItem
= true;
2173 for (CommonTree child
: children
) {
2181 /* Append the string that represents this type specifier. */
2182 createTypeSpecifierString(child
, sb
);
2187 * Creates the string representation of a type specifier.
2189 * @param typeSpecifier
2190 * A TYPE_SPECIFIER node.
2192 * A StringBuilder to which will be appended the string.
2193 * @throws ParseException
2195 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2196 StringBuilder sb
) throws ParseException
{
2197 switch (typeSpecifier
.getType()) {
2198 case CTFParser
.FLOATTOK
:
2199 case CTFParser
.INTTOK
:
2200 case CTFParser
.LONGTOK
:
2201 case CTFParser
.SHORTTOK
:
2202 case CTFParser
.SIGNEDTOK
:
2203 case CTFParser
.UNSIGNEDTOK
:
2204 case CTFParser
.CHARTOK
:
2205 case CTFParser
.DOUBLETOK
:
2206 case CTFParser
.VOIDTOK
:
2207 case CTFParser
.BOOLTOK
:
2208 case CTFParser
.COMPLEXTOK
:
2209 case CTFParser
.IMAGINARYTOK
:
2210 case CTFParser
.CONSTTOK
:
2211 case CTFParser
.IDENTIFIER
:
2212 sb
.append(typeSpecifier
.getText());
2214 case CTFParser
.STRUCT
: {
2215 CommonTree structName
= (CommonTree
) typeSpecifier
2216 .getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2217 if (structName
== null) {
2218 throw new ParseException(
2219 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2221 assert (structName
.getChildCount() == 1);
2223 CommonTree structNameIdentifier
= (CommonTree
) structName
2225 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2227 sb
.append(structNameIdentifier
.getText());
2230 case CTFParser
.VARIANT
: {
2231 CommonTree variantName
= (CommonTree
) typeSpecifier
2232 .getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2233 if (variantName
== null) {
2234 throw new ParseException(
2235 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2237 assert (variantName
.getChildCount() == 1);
2239 CommonTree variantNameIdentifier
= (CommonTree
) variantName
2241 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2243 sb
.append(variantNameIdentifier
.getText());
2246 case CTFParser
.ENUM
: {
2247 CommonTree enumName
= (CommonTree
) typeSpecifier
2248 .getFirstChildWithType(CTFParser
.ENUM_NAME
);
2249 if (enumName
== null) {
2250 throw new ParseException(
2251 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2253 assert (enumName
.getChildCount() == 1);
2255 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2256 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2258 sb
.append(enumNameIdentifier
.getText());
2261 case CTFParser
.FLOATING_POINT
:
2262 case CTFParser
.INTEGER
:
2263 case CTFParser
.STRING
:
2264 throw new ParseException(
2265 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2268 childTypeError(typeSpecifier
);
2274 * Creates the string representation of a list of pointers.
2276 * @param pointerList
2277 * A list of pointer nodes. If pointerList is null, this function
2280 * A stringbuilder to which will be appended the string.
2282 private static void createPointerListString(List
<CommonTree
> pointerList
,
2284 if (pointerList
== null) {
2288 for (CommonTree pointer
: pointerList
) {
2289 assert (pointer
.getType() == CTFParser
.POINTER
);
2291 sb
.append(" *"); //$NON-NLS-1$
2292 if (pointer
.getChildCount() > 0) {
2293 assert (pointer
.getChildCount() == 1);
2294 CommonTree constQualifier
= (CommonTree
) pointer
.getChild(0);
2295 assert (constQualifier
.getType() == CTFParser
.CONSTTOK
);
2297 sb
.append(" const"); //$NON-NLS-1$
2304 * The node to check.
2305 * @return True if the given node is an unary string or unary integer.
2307 private static boolean isUnaryExpression(CommonTree node
) {
2308 return isUnaryInteger(node
) || isUnaryString(node
);
2313 * The node to check.
2314 * @return True if the given node is an unary string.
2316 private static boolean isUnaryString(CommonTree node
) {
2317 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (node
2318 .getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2323 * The node to check.
2324 * @return True if the given node is an unary integer.
2326 private static boolean isUnaryInteger(CommonTree node
) {
2327 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
)
2328 || (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) || (node
2329 .getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2333 * Parses a unary string node and return the string value.
2335 * @param unaryString
2336 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2337 * or UNARY_EXPRESSION_STRING_QUOTES).
2338 * @return The string value.
2341 * It would be really nice to remove the quotes earlier, such as in the
2344 private static String
parseUnaryString(CommonTree unaryString
) {
2345 assert (isUnaryString(unaryString
));
2347 assert (unaryString
.getChildCount() == 1);
2348 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2349 assert (value
!= null);
2350 String strval
= value
.getText();
2353 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2354 strval
= strval
.substring(1, strval
.length() - 1);
2361 * Parses an unary integer (dec, hex or oct).
2363 * @param unaryInteger
2364 * An unary integer node.
2365 * @return The integer value.
2367 private static long parseUnaryInteger(CommonTree unaryInteger
) {
2368 assert (isUnaryInteger(unaryInteger
));
2370 assert (unaryInteger
.getChildCount() >= 1);
2372 List
<CommonTree
> children
= unaryInteger
.getChildren();
2373 CommonTree value
= children
.get(0);
2374 String strval
= value
.getText();
2378 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2379 intval
= Long
.parseLong(strval
, 10);
2380 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2381 intval
= Long
.parseLong(strval
, 0x10);
2382 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2383 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2386 /* The rest of children are sign */
2387 if ((children
.size() % 2) == 0) {
2393 private static long getMajorOrMinor(CommonTree rightNode
)
2394 throws ParseException
{
2395 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2396 assert (rightNode
.getChildCount() > 0);
2398 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2400 if (isUnaryInteger(firstChild
)) {
2401 if (rightNode
.getChildCount() > 1) {
2402 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2405 long m
= parseUnaryInteger(firstChild
);
2408 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2413 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2416 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2417 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2418 assert (rightNode
.getChildCount() > 0);
2420 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2422 if (isUnaryString(firstChild
)) {
2423 if (rightNode
.getChildCount() > 1) {
2424 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2427 String uuidstr
= parseUnaryString(firstChild
);
2430 UUID uuid
= UUID
.fromString(uuidstr
);
2432 } catch (IllegalArgumentException e
) {
2433 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2436 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2440 * Gets the value of a "signed" integer attribute.
2444 * @return The "signed" value as a boolean.
2445 * @throws ParseException
2447 private static boolean getSigned(CommonTree rightNode
)
2448 throws ParseException
{
2449 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2450 assert (rightNode
.getChildCount() > 0);
2452 boolean ret
= false;
2453 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2455 if (isUnaryString(firstChild
)) {
2456 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2458 if (strval
.equals("true") || strval
.equals("TRUE")) { //$NON-NLS-1$ //$NON-NLS-2$
2460 } else if (strval
.equals("false") || strval
.equals("FALSE")) { //$NON-NLS-1$ //$NON-NLS-2$
2463 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2464 + firstChild
.getChild(0).getText());
2466 } else if (isUnaryInteger(firstChild
)) {
2467 /* Happens if the value is something like "1234.hello" */
2468 if (rightNode
.getChildCount() > 1) {
2469 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2472 long intval
= parseUnaryInteger(firstChild
);
2476 } else if (intval
== 0) {
2479 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2480 + firstChild
.getChild(0).getText());
2483 throw new ParseException();
2490 * Gets the value of a "byte_order" integer attribute.
2494 * @return The "byte_order" value.
2495 * @throws ParseException
2497 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2498 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2499 assert (rightNode
.getChildCount() > 0);
2501 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2503 if (isUnaryString(firstChild
)) {
2504 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2506 if (strval
.equals("le")) { //$NON-NLS-1$
2507 return ByteOrder
.LITTLE_ENDIAN
;
2508 } else if (strval
.equals("be") || strval
.equals("network")) { //$NON-NLS-1$ //$NON-NLS-2$
2509 return ByteOrder
.BIG_ENDIAN
;
2510 } else if (strval
.equals("native")) { //$NON-NLS-1$
2511 return trace
.getByteOrder();
2513 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2516 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2520 * Determines if the given value is a valid alignment value.
2523 * The value to check.
2524 * @return True if it is valid.
2526 private static boolean isValidAlignment(long alignment
) {
2527 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2531 * Gets the value of a "size" integer attribute.
2535 * @return The "size" value.
2536 * @throws ParseException
2538 private static long getSize(CommonTree rightNode
) throws ParseException
{
2539 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2540 assert (rightNode
.getChildCount() > 0);
2542 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2544 if (isUnaryInteger(firstChild
)) {
2545 if (rightNode
.getChildCount() > 1) {
2546 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2549 long size
= parseUnaryInteger(firstChild
);
2552 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2557 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2561 * Gets the value of a "align" integer or struct attribute.
2564 * A CTF_RIGHT node or directly an unary integer.
2565 * @return The align value.
2566 * @throws ParseException
2568 private static long getAlignment(CommonTree node
) throws ParseException
{
2569 assert (isUnaryExpression(node
) || (node
.getType() == CTFParser
.CTF_RIGHT
));
2572 * If a CTF_RIGHT node was passed, call getAlignment with the first
2575 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2576 if (node
.getChildCount() > 1) {
2577 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2580 return getAlignment((CommonTree
) node
.getChild(0));
2581 } else if (isUnaryInteger(node
)) {
2582 long alignment
= parseUnaryInteger(node
);
2584 if (!isValidAlignment(alignment
)) {
2585 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2591 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2595 * Gets the value of a "base" integer attribute.
2598 * An CTF_RIGHT node.
2599 * @return The "base" value.
2600 * @throws ParseException
2602 private static int getBase(CommonTree rightNode
) throws ParseException
{
2603 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2604 assert (rightNode
.getChildCount() > 0);
2606 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2608 if (isUnaryInteger(firstChild
)) {
2609 if (rightNode
.getChildCount() > 1) {
2610 throw new ParseException("invalid base value"); //$NON-NLS-1$
2613 long intval
= parseUnaryInteger(firstChild
);
2614 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2615 || (intval
== 16)) {
2616 return (int) intval
;
2618 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2619 } else if (isUnaryString(firstChild
)) {
2620 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2622 if (strval
.equals("decimal") || strval
.equals("dec") //$NON-NLS-1$ //$NON-NLS-2$
2623 || strval
.equals("d") || strval
.equals("i") //$NON-NLS-1$ //$NON-NLS-2$
2624 || strval
.equals("u")) { //$NON-NLS-1$
2626 } else if (strval
.equals("hexadecimal") || strval
.equals("hex") //$NON-NLS-1$ //$NON-NLS-2$
2627 || strval
.equals("x") || strval
.equals("X") //$NON-NLS-1$ //$NON-NLS-2$
2628 || strval
.equals("p")) { //$NON-NLS-1$
2630 } else if (strval
.equals("octal") || strval
.equals("oct") //$NON-NLS-1$ //$NON-NLS-2$
2631 || strval
.equals("o")) { //$NON-NLS-1$
2633 } else if (strval
.equals("binary") || strval
.equals("b")) { //$NON-NLS-1$ //$NON-NLS-2$
2636 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2639 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2644 * Gets the value of an "encoding" integer attribute.
2648 * @return The "encoding" value.
2649 * @throws ParseException
2651 private static Encoding
getEncoding(CommonTree rightNode
)
2652 throws ParseException
{
2653 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2655 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2657 if (isUnaryString(firstChild
)) {
2658 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2660 if (strval
.equals("UTF8")) { //$NON-NLS-1$
2661 return Encoding
.UTF8
;
2662 } else if (strval
.equals("ASCII")) { //$NON-NLS-1$
2663 return Encoding
.ASCII
;
2664 } else if (strval
.equals("none")) { //$NON-NLS-1$
2665 return Encoding
.NONE
;
2667 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2670 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2673 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2674 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2675 assert (rightNode
.getChildCount() > 0);
2677 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2679 if (isUnaryInteger(firstChild
)) {
2680 if (rightNode
.getChildCount() > 1) {
2681 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2684 long intval
= parseUnaryInteger(firstChild
);
2688 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2691 private static String
getEventName(CommonTree rightNode
)
2692 throws ParseException
{
2693 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2694 assert (rightNode
.getChildCount() > 0);
2696 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2698 if (isUnaryString(firstChild
)) {
2699 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2703 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2706 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2707 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2708 assert (rightNode
.getChildCount() > 0);
2710 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2712 if (isUnaryInteger(firstChild
)) {
2713 if (rightNode
.getChildCount() > 1) {
2714 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2717 long intval
= parseUnaryInteger(firstChild
);
2721 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2725 * Concatenates a list of unary strings separated by arrows (->) or dots.
2728 * A list, first element being an unary string, subsequent
2729 * elements being ARROW or DOT nodes with unary strings as child.
2730 * @return The string representation of the unary string chain.
2732 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2733 assert ((strings
!= null) && (strings
.size() > 0));
2735 StringBuilder sb
= new StringBuilder();
2737 CommonTree first
= strings
.get(0);
2738 sb
.append(parseUnaryString(first
));
2740 boolean isFirst
= true;
2742 for (CommonTree ref
: strings
) {
2748 assert ((ref
.getType() == CTFParser
.ARROW
) || (ref
.getType() == CTFParser
.DOT
));
2749 assert (ref
.getChildCount() == 1);
2751 CommonTree id
= (CommonTree
) ref
.getChild(0);
2753 if (ref
.getType() == CTFParser
.ARROW
) {
2754 sb
.append("->"); //$NON-NLS-1$
2759 sb
.append(parseUnaryString(id
));
2762 return sb
.toString();
2766 * Throws a ParseException stating that the parent-child relation between
2767 * the given node and its parent is not valid. It means that the shape of
2768 * the AST is unexpected.
2771 * The invalid child node.
2772 * @throws ParseException
2774 private static void childTypeError(CommonTree child
) throws ParseException
{
2775 CommonTree parent
= (CommonTree
) child
.getParent();
2776 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2777 + " can't have a child of type " //$NON-NLS-1$
2778 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2780 throw new ParseException(error
);
2783 // ------------------------------------------------------------------------
2785 // ------------------------------------------------------------------------
2788 * Adds a new declaration scope on the top of the scope stack.
2790 private void pushScope() {
2791 scope
= new DeclarationScope(scope
);
2795 * Removes the top declaration scope from the scope stack.
2797 private void popScope() {
2798 assert (scope
!= null);
2799 scope
= scope
.getParentScope();
2803 * Returns the current declaration scope.
2805 * @return The current declaration scope.
2807 private DeclarationScope
getCurrentScope() {
2808 assert (scope
!= null);