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
.metadata
.DeclarationScope
;
29 import org
.eclipse
.linuxtools
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
30 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDeclaration
;
31 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Encoding
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDeclaration
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDeclaration
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
36 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDeclaration
;
37 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
38 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
39 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
40 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.Stream
;
41 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
42 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.Activator
;
45 * Asserts throughout this class denote the assumptions we can make because of
46 * the way the grammar generates the AST.
48 * There is also an assert at the beginning of each function that receives a
49 * tree node to make sure that the node is indeed of the type the function is
53 * Suppress unchecked warnings for things like List<CommonTree> children =
54 * root.getChildren(), because ANTLR doesn't know what generics are.
57 * <b><u>IOStructGen</u></b>
59 @SuppressWarnings("unchecked")
60 public class IOStructGen
{
62 // ------------------------------------------------------------------------
64 // ------------------------------------------------------------------------
66 static private final boolean DEBUG_
= false;
71 private final CTFTrace trace
;
72 private final CommonTree tree
;
75 * The current declaration scope.
77 private DeclarationScope scope
= null;
79 // ------------------------------------------------------------------------
81 // ------------------------------------------------------------------------
83 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
88 public void generate() throws ParseException
{
92 // ------------------------------------------------------------------------
94 // ------------------------------------------------------------------------
97 * Parse the root node.
101 * @throws ParseException
103 private void parseRoot(CommonTree root
) throws ParseException
{
104 assert (root
.getType() == CTFParser
.ROOT
);
106 List
<CommonTree
> children
= root
.getChildren();
107 assert (children
!= null);
108 java
.io
.FileOutputStream fos
= null;
109 java
.io
.OutputStreamWriter out
= null;
112 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
113 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
114 } catch (FileNotFoundException e
) {
117 } catch (UnsupportedEncodingException e
) {
123 CommonTree traceNode
= null;
124 List
<CommonTree
> streams
= new ArrayList
<CommonTree
>();
125 List
<CommonTree
> events
= new ArrayList
<CommonTree
>();
126 List
<CommonTree
> declarations
= new ArrayList
<CommonTree
>();
127 List
<CommonTree
> environments
= new ArrayList
<CommonTree
>();
128 List
<CommonTree
> clocks
= new ArrayList
<CommonTree
>();
129 /* Create a new declaration scope with no parent. */
133 for (CommonTree child
: children
) {
135 out
.write(child
.toString()
136 + " -> " + child
.getType() + '\n'); //$NON-NLS-1$
138 switch (child
.getType()) {
139 case CTFParser
.DECLARATION
:
140 declarations
.add(child
);
142 case CTFParser
.TRACE
:
143 if (traceNode
!= null) {
144 throw new ParseException(
145 "Only one trace block is allowed"); //$NON-NLS-1$
149 case CTFParser
.STREAM
:
152 case CTFParser
.EVENT
:
155 case CTFParser
.CLOCK
:
159 environments
.add(child
);
162 childTypeError(child
);
167 out
.write("Environments\n"); //$NON-NLS-1$
169 for (CommonTree environment
: environments
) {
170 parseEnvironment(environment
);
173 out
.write("Clocks\n"); //$NON-NLS-1$
175 for (CommonTree clock
: clocks
) {
179 out
.write("Declarations\n"); //$NON-NLS-1$
181 for (CommonTree decl
: declarations
) {
183 out
.write(decl
.toString() + '\n');
185 parseRootDeclaration(decl
);
188 if (traceNode
== null) {
189 throw new ParseException("Missing trace block"); //$NON-NLS-1$
192 parseTrace(traceNode
);
195 out
.write("Streams\n"); //$NON-NLS-1$
197 if (streams
.size() > 0) {
198 for (CommonTree stream
: streams
) {
201 out
.write(stream
.toString() + '\n');
202 } catch (IOException e
) {
209 /* Add an empty stream that will have a null id */
210 trace
.addStream(new Stream(trace
));
214 out
.write("Events\n"); //$NON-NLS-1$
216 for (CommonTree event
: events
) {
218 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1)
219 .getChild(0).getChild(0);
221 out
.write("Name = " + name
); //$NON-NLS-1$
223 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1)
224 .getChild(0).getChild(0);
226 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
234 } catch (IOException e
) {
240 private void parseEnvironment(CommonTree environment
) {
241 List
<CommonTree
> children
= environment
.getChildren();
242 for (CommonTree child
: children
) {
245 left
= child
.getChild(0).getChild(0).getChild(0).getText();
246 right
= child
.getChild(1).getChild(0).getChild(0).getText();
247 trace
.addEnvironmentVar(left
, right
);
251 private void parseClock(CommonTree clock
) {
252 List
<CommonTree
> children
= clock
.getChildren();
253 CTFClock ctfClock
= new CTFClock();
254 for (CommonTree child
: children
) {
255 final String key
= child
.getChild(0).getChild(0).getChild(0)
257 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
258 final int type
= value
.getType();
260 case CTFParser
.INTEGER
:
261 case CTFParser
.DECIMAL_LITERAL
:
263 * Not a pretty hack, this is to make sure that there is no number
264 * overflow due to 63 bit integers. The offset should only really
265 * be an issue in the year 2262. the tracer in C/ASM can write an offset in
266 * an unsigned 64 bit long. In java, the last bit, being set to 1 will
267 * be read as a negative number, but since it is too big a positive it will
268 * throw an exception. this will happen in 2^63 ns from 1970.
269 * Therefore 293 years from 1970
273 numValue
= Long
.parseLong(value
.getText());
277 numValue
= 1330938566783103277L;
279 ctfClock
.addAttribute(key
, numValue
);
282 ctfClock
.addAttribute(key
, value
.getText());
286 String NameValue
= ctfClock
.getName();
287 trace
.addClock(NameValue
, ctfClock
);
290 private void parseTrace(CommonTree traceNode
) throws ParseException
{
291 assert (traceNode
.getType() == CTFParser
.TRACE
);
293 List
<CommonTree
> children
= traceNode
.getChildren();
294 if (children
== null) {
295 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
300 for (CommonTree child
: children
) {
301 switch (child
.getType()) {
302 case CTFParser
.TYPEALIAS
:
303 parseTypealias(child
);
305 case CTFParser
.TYPEDEF
:
308 case CTFParser
.CTF_EXPRESSION_TYPE
:
309 case CTFParser
.CTF_EXPRESSION_VAL
:
310 parseTraceDeclaration(child
);
313 childTypeError(child
);
319 * If trace byte order was not specified and not using packet based
322 if (trace
.getByteOrder() == null) {
323 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
329 private void parseTraceDeclaration(CommonTree traceDecl
)
330 throws ParseException
{
331 assert ((traceDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (traceDecl
332 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
334 /* There should be a left and right */
335 assert (traceDecl
.getChildCount() == 2);
337 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
338 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
339 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
340 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
342 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
343 assert (leftStrings
!= null);
345 if (!isUnaryString(leftStrings
.get(0))) {
346 throw new ParseException(
347 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
350 String left
= concatenateUnaryStrings(leftStrings
);
352 if (left
.equals("major")) { //$NON-NLS-1$
353 if (trace
.majortIsSet()) {
354 throw new ParseException("major is already set"); //$NON-NLS-1$
357 trace
.setMajor(getMajorOrMinor(rightNode
));
358 } else if (left
.equals("minor")) { //$NON-NLS-1$
359 if (trace
.minorIsSet()) {
360 throw new ParseException("minor is already set"); //$NON-NLS-1$
363 trace
.setMinor(getMajorOrMinor(rightNode
));
364 } else if (left
.equals("uuid")) { //$NON-NLS-1$
365 UUID uuid
= getUUID(rightNode
);
368 * If uuid was already set by a metadata packet, compare it to see
371 if (trace
.UUIDIsSet()) {
372 if (trace
.getUUID().compareTo(uuid
) != 0) {
373 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
374 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
380 } else if (left
.equals("byte_order")) { //$NON-NLS-1$
381 ByteOrder byteOrder
= getByteOrder(rightNode
);
384 * If byte order was already set by a metadata packet, compare it to
387 if (trace
.getByteOrder() != null) {
388 if (trace
.getByteOrder() != byteOrder
) {
389 throw new ParseException(
390 "Endianness mismatch. Magic number says " //$NON-NLS-1$
391 + trace
.getByteOrder()
392 + " but metadata says " + byteOrder
); //$NON-NLS-1$
395 trace
.setByteOrder(byteOrder
);
397 } else if (left
.equals("packet.header")) { //$NON-NLS-1$
398 if (trace
.packetHeaderIsSet()) {
399 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
402 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
404 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
405 throw new ParseException(
406 "packet.header expects a type specifier"); //$NON-NLS-1$
409 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
410 typeSpecifier
, null);
412 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
413 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
416 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
418 throw new ParseException("Unknown trace attribute : " + left
); //$NON-NLS-1$
422 private void parseStream(CommonTree streamNode
) throws ParseException
{
423 assert (streamNode
.getType() == CTFParser
.STREAM
);
425 Stream stream
= new Stream(trace
);
427 List
<CommonTree
> children
= streamNode
.getChildren();
428 if (children
== null) {
429 throw new ParseException("Empty stream block"); //$NON-NLS-1$
434 for (CommonTree child
: children
) {
435 switch (child
.getType()) {
436 case CTFParser
.TYPEALIAS
:
437 parseTypealias(child
);
439 case CTFParser
.TYPEDEF
:
442 case CTFParser
.CTF_EXPRESSION_TYPE
:
443 case CTFParser
.CTF_EXPRESSION_VAL
:
444 parseStreamDeclaration(child
, stream
);
447 childTypeError(child
);
452 if (stream
.idIsSet()) {
453 if (!trace
.packetHeaderIsSet()
454 || !trace
.getPacketHeader().hasField("stream_id")) { //$NON-NLS-1$
455 throw new ParseException(
456 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
460 trace
.addStream(stream
);
465 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
466 throws ParseException
{
467 assert ((streamDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (streamDecl
468 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
470 /* There should be a left and right */
471 assert (streamDecl
.getChildCount() == 2);
473 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
474 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
475 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
476 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
478 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
479 assert (leftStrings
!= null);
481 if (!isUnaryString(leftStrings
.get(0))) {
482 throw new ParseException(
483 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
486 String left
= concatenateUnaryStrings(leftStrings
);
488 if (left
.equals("id")) { //$NON-NLS-1$
489 if (stream
.idIsSet()) {
490 throw new ParseException("stream id already defined"); //$NON-NLS-1$
493 long streamID
= getStreamID(rightNode
);
495 stream
.setId(streamID
);
496 } else if (left
.equals("event.header")) { //$NON-NLS-1$
497 if (stream
.eventHeaderIsSet()) {
498 throw new ParseException("event.header already defined"); //$NON-NLS-1$
501 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
503 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
504 throw new ParseException(
505 "event.header expects a type specifier"); //$NON-NLS-1$
508 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
509 typeSpecifier
, null);
511 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
512 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
515 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
516 } else if (left
.equals("event.context")) { //$NON-NLS-1$
517 if (stream
.eventContextIsSet()) {
518 throw new ParseException("event.context already defined"); //$NON-NLS-1$
521 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
523 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
524 throw new ParseException(
525 "event.context expects a type specifier"); //$NON-NLS-1$
528 IDeclaration eventContextDecl
= parseTypeSpecifierList(
529 typeSpecifier
, null);
531 if (!(eventContextDecl
instanceof StructDeclaration
)) {
532 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
535 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
536 } else if (left
.equals("packet.context")) { //$NON-NLS-1$
537 if (stream
.packetContextIsSet()) {
538 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
541 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
543 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
544 throw new ParseException(
545 "packet.context expects a type specifier"); //$NON-NLS-1$
548 IDeclaration packetContextDecl
= parseTypeSpecifierList(
549 typeSpecifier
, null);
551 if (!(packetContextDecl
instanceof StructDeclaration
)) {
552 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
555 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
557 throw new ParseException("Unknown stream attribute : " + left
); //$NON-NLS-1$
561 private void parseEvent(CommonTree eventNode
) throws ParseException
{
562 assert (eventNode
.getType() == CTFParser
.EVENT
);
564 List
<CommonTree
> children
= eventNode
.getChildren();
565 if (children
== null) {
566 throw new ParseException("Empty event block"); //$NON-NLS-1$
569 EventDeclaration event
= new EventDeclaration();
573 for (CommonTree child
: children
) {
574 switch (child
.getType()) {
575 case CTFParser
.TYPEALIAS
:
576 parseTypealias(child
);
578 case CTFParser
.TYPEDEF
:
581 case CTFParser
.CTF_EXPRESSION_TYPE
:
582 case CTFParser
.CTF_EXPRESSION_VAL
:
583 parseEventDeclaration(child
, event
);
586 childTypeError(child
);
591 if (!event
.nameIsSet()) {
592 throw new ParseException("Event name not set"); //$NON-NLS-1$
596 * If the event did not specify a stream, then the trace must be single
599 if (!event
.streamIsSet()) {
600 if (trace
.nbStreams() > 1) {
601 throw new ParseException(
602 "Event without stream_id with more than one stream"); //$NON-NLS-1$
606 * If the event did not specify a stream, the only existing stream
607 * must not have an id. Note: That behavior could be changed, it
608 * could be possible to just get the only existing stream, whatever
611 Stream stream
= trace
.getStream(null);
613 if (stream
!= null) {
614 event
.setStream(stream
);
616 throw new ParseException(
617 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
622 * Add the event to the stream.
624 event
.getStream().addEvent(event
);
629 private void parseEventDeclaration(CommonTree eventDecl
,
630 EventDeclaration event
) throws ParseException
{
631 assert ((eventDecl
.getType() == CTFParser
.CTF_EXPRESSION_TYPE
) || (eventDecl
632 .getType() == CTFParser
.CTF_EXPRESSION_VAL
));
634 /* There should be a left and right */
635 assert (eventDecl
.getChildCount() == 2);
637 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
638 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
639 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
640 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
642 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
643 assert (leftStrings
!= null);
645 if (!isUnaryString(leftStrings
.get(0))) {
646 throw new ParseException(
647 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
650 String left
= concatenateUnaryStrings(leftStrings
);
652 if (left
.equals("name")) { //$NON-NLS-1$
653 if (event
.nameIsSet()) {
654 throw new ParseException("name already defined"); //$NON-NLS-1$
657 String name
= getEventName(rightNode
);
660 } else if (left
.equals("id")) { //$NON-NLS-1$
661 if (event
.idIsSet()) {
662 throw new ParseException("id already defined"); //$NON-NLS-1$
665 long id
= getEventID(rightNode
);
668 } else if (left
.equals("stream_id")) { //$NON-NLS-1$
669 if (event
.streamIsSet()) {
670 throw new ParseException("stream id already defined"); //$NON-NLS-1$
673 long streamId
= getStreamID(rightNode
);
675 Stream stream
= trace
.getStream(streamId
);
677 if (stream
== null) {
678 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
681 event
.setStream(stream
);
682 } else if (left
.equals("context")) { //$NON-NLS-1$
683 if (event
.contextIsSet()) {
684 throw new ParseException("context already defined"); //$NON-NLS-1$
687 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
689 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
690 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
693 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
696 if (!(contextDecl
instanceof StructDeclaration
)) {
697 throw new ParseException("context expects a struct"); //$NON-NLS-1$
700 event
.setContext((StructDeclaration
) contextDecl
);
701 } else if (left
.equals("fields")) { //$NON-NLS-1$
702 if (event
.fieldsIsSet()) {
703 throw new ParseException("fields already defined"); //$NON-NLS-1$
706 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
708 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
709 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
712 IDeclaration fieldsDecl
;
713 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
715 if (!(fieldsDecl
instanceof StructDeclaration
)) {
716 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
719 * The underscores in the event names.
720 * These underscores were added by the LTTng tracer.
722 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
723 event
.setFields(fields
);
726 throw new ParseException("Unknown event attribute : " + left
); //$NON-NLS-1$
731 * Parses a declaration at the root level.
734 * The declaration subtree.
735 * @throws ParseException
737 private void parseRootDeclaration(CommonTree declaration
)
738 throws ParseException
{
739 assert (declaration
.getType() == CTFParser
.DECLARATION
);
741 List
<CommonTree
> children
= declaration
.getChildren();
742 assert (children
!= null);
744 for (CommonTree child
: children
) {
745 switch (child
.getType()) {
746 case CTFParser
.TYPEDEF
:
749 case CTFParser
.TYPEALIAS
:
750 parseTypealias(child
);
752 case CTFParser
.TYPE_SPECIFIER_LIST
:
753 parseTypeSpecifierList(child
, null);
756 childTypeError(child
);
762 * Parses a typealias node. It parses the target, the alias, and registers
763 * the type in the current scope.
767 * @throws ParseException
769 private void parseTypealias(CommonTree typealias
) throws ParseException
{
770 assert (typealias
.getType() == CTFParser
.TYPEALIAS
);
772 List
<CommonTree
> children
= typealias
.getChildren();
773 assert (children
!= null);
775 CommonTree target
= null;
776 CommonTree alias
= null;
778 for (CommonTree child
: children
) {
779 switch (child
.getType()) {
780 case CTFParser
.TYPEALIAS_TARGET
:
781 assert (target
== null);
784 case CTFParser
.TYPEALIAS_ALIAS
:
785 assert (alias
== null);
789 childTypeError(child
);
794 assert (target
!= null);
795 assert (alias
!= null);
797 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
799 if (targetDeclaration
instanceof VariantDeclaration
) {
800 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
801 throw new ParseException(
802 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
806 String aliasString
= parseTypealiasAlias(alias
);
808 getCurrentScope().registerType(aliasString
, targetDeclaration
);
812 * Parses the target part of a typealias and gets the corresponding
816 * A TYPEALIAS_TARGET node.
817 * @return The corresponding declaration.
818 * @throws ParseException
820 private IDeclaration
parseTypealiasTarget(CommonTree target
)
821 throws ParseException
{
822 assert (target
.getType() == CTFParser
.TYPEALIAS_TARGET
);
824 List
<CommonTree
> children
= target
.getChildren();
825 assert (children
!= null);
827 CommonTree typeSpecifierList
= null;
828 CommonTree typeDeclaratorList
= null;
829 CommonTree typeDeclarator
= null;
830 StringBuilder identifierSB
= new StringBuilder();
832 for (CommonTree child
: children
) {
833 switch (child
.getType()) {
834 case CTFParser
.TYPE_SPECIFIER_LIST
:
835 assert (typeSpecifierList
== null);
836 typeSpecifierList
= child
;
838 case CTFParser
.TYPE_DECLARATOR_LIST
:
839 assert (typeDeclaratorList
== null);
840 typeDeclaratorList
= child
;
843 childTypeError(child
);
848 assert (typeSpecifierList
!= null);
850 if (typeDeclaratorList
!= null) {
852 * Only allow one declarator
854 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
855 * otherwise the new type puint8_t would maps to two different
858 if (typeDeclaratorList
.getChildCount() != 1) {
859 throw new ParseException(
860 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
863 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
866 /* Parse the target type and get the declaration */
867 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
868 typeSpecifierList
, identifierSB
);
871 * We don't allow identifier in the target
873 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
876 if (identifierSB
.length() > 0) {
877 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
878 + ") not expected in the typealias target"); //$NON-NLS-1$
881 return targetDeclaration
;
885 * Parses the alias part of a typealias. It parses the underlying specifier
886 * list and declarator and creates the string representation that will be
887 * used to register the type.
890 * A TYPEALIAS_ALIAS node.
891 * @return The string representation of the alias.
892 * @throws ParseException
894 private static String
parseTypealiasAlias(CommonTree alias
)
895 throws ParseException
{
896 assert (alias
.getType() == CTFParser
.TYPEALIAS_ALIAS
);
898 List
<CommonTree
> children
= alias
.getChildren();
899 assert (children
!= null);
901 CommonTree typeSpecifierList
= null;
902 CommonTree typeDeclaratorList
= null;
903 CommonTree typeDeclarator
= null;
904 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
906 for (CommonTree child
: children
) {
907 switch (child
.getType()) {
908 case CTFParser
.TYPE_SPECIFIER_LIST
:
909 assert (typeSpecifierList
== null);
910 typeSpecifierList
= child
;
912 case CTFParser
.TYPE_DECLARATOR_LIST
:
913 assert (typeDeclaratorList
== null);
914 typeDeclaratorList
= child
;
917 childTypeError(child
);
922 /* If there is a type declarator list, extract the pointers */
923 if (typeDeclaratorList
!= null) {
925 * Only allow one declarator
927 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
929 if (typeDeclaratorList
.getChildCount() != 1) {
930 throw new ParseException(
931 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
934 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
936 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
938 assert (typeDeclaratorChildren
!= null);
940 for (CommonTree child
: typeDeclaratorChildren
) {
941 switch (child
.getType()) {
942 case CTFParser
.POINTER
:
945 case CTFParser
.IDENTIFIER
:
946 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
947 + ") not expected in the typealias target"); //$NON-NLS-1$
950 childTypeError(child
);
956 return createTypeDeclarationString(typeSpecifierList
, pointers
);
960 * Parses a typedef node. This creates and registers a new declaration for
961 * each declarator found in the typedef.
965 * @throws ParseException
966 * If there is an error creating the declaration.
968 private void parseTypedef(CommonTree typedef
) throws ParseException
{
969 assert (typedef
.getType() == CTFParser
.TYPEDEF
);
971 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
972 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
973 assert (typeDeclaratorListNode
!= null);
975 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
976 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
977 assert (typeSpecifierListNode
!= null);
979 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
981 assert (typeDeclaratorList
!= null);
983 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
984 StringBuilder identifierSB
= new StringBuilder();
986 IDeclaration type_declaration
= parseTypeDeclarator(
987 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
989 if (type_declaration
instanceof VariantDeclaration
) {
990 if (((VariantDeclaration
) type_declaration
).isTagged()) {
991 throw new ParseException(
992 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
996 getCurrentScope().registerType(identifierSB
.toString(),
1002 * Parses a pair type declarator / type specifier list and returns the
1003 * corresponding declaration. If it is present, it also writes the
1004 * identifier of the declarator in the given {@link StringBuilder}.
1006 * @param typeDeclarator
1007 * A TYPE_DECLARATOR node.
1008 * @param typeSpecifierList
1009 * A TYPE_SPECIFIER_LIST node.
1010 * @param identifierSB
1011 * A StringBuilder that will receive the identifier found in the
1013 * @return The corresponding declaration.
1014 * @throws ParseException
1015 * If there is an error finding or creating the declaration.
1017 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1018 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1019 throws ParseException
{
1020 if (typeDeclarator
!= null) {
1021 assert (typeDeclarator
.getType() == CTFParser
.TYPE_DECLARATOR
);
1023 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1025 IDeclaration declaration
= null;
1026 List
<CommonTree
> children
= null;
1027 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1028 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1029 CommonTree identifier
= null;
1031 /* Separate the tokens by type */
1032 if (typeDeclarator
!= null) {
1033 children
= typeDeclarator
.getChildren();
1034 assert (children
!= null);
1035 for (CommonTree child
: children
) {
1037 switch (child
.getType()) {
1038 case CTFParser
.POINTER
:
1039 pointers
.add(child
);
1041 case CTFParser
.IDENTIFIER
:
1042 assert (identifier
== null);
1045 case CTFParser
.LENGTH
:
1049 childTypeError(child
);
1057 * Parse the type specifier list, which is the "base" type. For example,
1058 * it would be int in int a[3][len].
1060 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1063 * Each length subscript means that we must create a nested array or
1064 * sequence. For example, int a[3][len] means that we have an array of 3
1065 * (sequences of length 'len' of (int)).
1067 if (lengths
.size() > 0 ) {
1068 /* We begin at the end */
1069 Collections
.reverse(lengths
);
1071 for (CommonTree length
: lengths
) {
1073 * By looking at the first expression, we can determine whether
1074 * it is an array or a sequence.
1076 List
<CommonTree
> lengthChildren
= length
.getChildren();
1077 assert (lengthChildren
!= null);
1079 CommonTree first
= lengthChildren
.get(0);
1080 if (isUnaryInteger(first
)) {
1082 int arrayLength
= (int) parseUnaryInteger(first
);
1084 if (arrayLength
< 1) {
1085 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1088 /* Create the array declaration. */
1089 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1090 } else if (isUnaryString(first
)) {
1092 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1094 /* Create the sequence declaration. */
1095 declaration
= new SequenceDeclaration(lengthName
,
1098 childTypeError(first
);
1103 if (identifier
!= null) {
1104 identifierSB
.append(identifier
.getText());
1111 * Parses a type specifier list and returns the corresponding declaration.
1113 * @param typeSpecifierList
1114 * A TYPE_SPECIFIER_LIST node.
1115 * @param pointerList
1116 * A list of POINTER nodes that apply to the specified type.
1117 * @return The corresponding declaration.
1118 * @throws ParseException
1119 * If the type has not been defined or if there is an error
1120 * creating the declaration.
1122 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1123 List
<CommonTree
> pointerList
) throws ParseException
{
1124 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
1125 IDeclaration declaration
= null;
1128 * By looking at the first element of the type specifier list, we can
1129 * determine which type it belongs to.
1131 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1132 assert (firstChild
!= null); /* grammar */
1134 switch (firstChild
.getType()) {
1135 case CTFParser
.FLOATING_POINT
:
1138 .log("parseTypeSpecifierList: floating_point not implemented yet"); //$NON-NLS-1$
1140 case CTFParser
.INTEGER
:
1141 declaration
= parseInteger(firstChild
);
1143 case CTFParser
.STRING
:
1144 declaration
= parseString(firstChild
);
1146 case CTFParser
.STRUCT
:
1147 declaration
= parseStruct(firstChild
);
1149 case CTFParser
.VARIANT
:
1150 declaration
= parseVariant(firstChild
);
1152 case CTFParser
.ENUM
:
1153 declaration
= parseEnum(firstChild
);
1155 case CTFParser
.IDENTIFIER
:
1156 case CTFParser
.FLOATTOK
:
1157 case CTFParser
.INTTOK
:
1158 case CTFParser
.LONGTOK
:
1159 case CTFParser
.SHORTTOK
:
1160 case CTFParser
.SIGNEDTOK
:
1161 case CTFParser
.UNSIGNEDTOK
:
1162 case CTFParser
.CHARTOK
:
1163 case CTFParser
.DOUBLETOK
:
1164 case CTFParser
.VOIDTOK
:
1165 case CTFParser
.BOOLTOK
:
1166 case CTFParser
.COMPLEXTOK
:
1167 case CTFParser
.IMAGINARYTOK
:
1168 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1171 childTypeError(firstChild
);
1174 assert (declaration
!= null);
1179 * Parses a type specifier list as a user-declared type.
1181 * @param typeSpecifierList
1182 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1183 * @param pointerList
1184 * A list of POINTER nodes that apply to the type specified in
1185 * typeSpecifierList.
1186 * @return The corresponding declaration.
1187 * @throws ParseException
1188 * If the type does not exist (has not been found).
1190 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1191 List
<CommonTree
> pointerList
) throws ParseException
{
1192 /* Create the string representation of the type declaration */
1193 String typeStringRepresentation
= createTypeDeclarationString(
1194 typeSpecifierList
, pointerList
);
1196 /* Use the string representation to search the type in the current scope */
1197 IDeclaration decl
= getCurrentScope().rlookupType(
1198 typeStringRepresentation
);
1201 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1202 + " has not been defined."); //$NON-NLS-1$
1209 * Parses an integer declaration node.
1213 * @return The corresponding integer declaration.
1214 * @throws ParseException
1216 private IntegerDeclaration
parseInteger(CommonTree integer
)
1217 throws ParseException
{
1218 assert (integer
.getType() == CTFParser
.INTEGER
);
1220 List
<CommonTree
> children
= integer
.getChildren();
1223 * If the integer has no attributes, then it is missing the size
1224 * attribute which is required
1226 if (children
== null) {
1227 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1230 /* The return value */
1231 IntegerDeclaration integerDeclaration
= null;
1232 boolean signed
= false;
1233 ByteOrder byteOrder
= trace
.getByteOrder();
1237 String clock
= null;
1239 Encoding encoding
= Encoding
.NONE
;
1241 /* Iterate on all integer children */
1242 for (CommonTree child
: children
) {
1243 switch (child
.getType()) {
1244 case CTFParser
.CTF_EXPRESSION_VAL
:
1246 * An assignment expression must have 2 children, left and right
1248 assert (child
.getChildCount() == 2);
1250 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1251 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1252 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1253 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1255 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1256 assert (leftStrings
!= null);
1258 if (!isUnaryString(leftStrings
.get(0))) {
1259 throw new ParseException(
1260 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1262 String left
= concatenateUnaryStrings(leftStrings
);
1264 if (left
.equals("signed")) { //$NON-NLS-1$
1265 signed
= getSigned(rightNode
);
1266 } else if (left
.equals("byte_order")) { //$NON-NLS-1$
1267 byteOrder
= getByteOrder(rightNode
);
1268 } else if (left
.equals("size")) { //$NON-NLS-1$
1269 size
= getSize(rightNode
);
1270 } else if (left
.equals("align")) { //$NON-NLS-1$
1271 alignment
= getAlignment(rightNode
);
1272 } else if (left
.equals("base")) { //$NON-NLS-1$
1273 base
= getBase(rightNode
);
1274 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1275 encoding
= getEncoding(rightNode
);
1276 } else if (left
.equals("map")) { //$NON-NLS-1$
1277 clock
= getClock(rightNode
);
1279 throw new ParseException("Integer: unknown attribute " + left
); //$NON-NLS-1$
1284 childTypeError(child
);
1290 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1293 if (alignment
== 0) {
1294 if ((size
% 8) == 0) {
1301 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1302 byteOrder
, encoding
, clock
);
1304 assert (integerDeclaration
!= null);
1305 return integerDeclaration
;
1308 private static String
getClock(CommonTree rightNode
) {
1309 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1312 private static StringDeclaration
parseString(CommonTree string
)
1313 throws ParseException
{
1314 assert (string
.getType() == CTFParser
.STRING
);
1316 List
<CommonTree
> children
= string
.getChildren();
1317 StringDeclaration stringDeclaration
= null;
1319 if (children
== null) {
1320 stringDeclaration
= new StringDeclaration();
1322 Encoding encoding
= Encoding
.UTF8
;
1323 for (CommonTree child
: children
) {
1324 switch (child
.getType()) {
1325 case CTFParser
.CTF_EXPRESSION_VAL
:
1327 * An assignment expression must have 2 children, left and
1330 assert (child
.getChildCount() == 2);
1332 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1333 assert (leftNode
.getType() == CTFParser
.CTF_LEFT
);
1334 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1335 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
1337 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1338 assert (leftStrings
!= null);
1340 if (!isUnaryString(leftStrings
.get(0))) {
1341 throw new ParseException(
1342 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1344 String left
= concatenateUnaryStrings(leftStrings
);
1346 if (left
.equals("encoding")) { //$NON-NLS-1$
1347 encoding
= getEncoding(rightNode
);
1349 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1355 childTypeError(child
);
1360 stringDeclaration
= new StringDeclaration(encoding
);
1363 return stringDeclaration
;
1367 * Parses a struct declaration and returns the corresponding declaration.
1371 * @return The corresponding struct declaration.
1372 * @throws ParseException
1374 private StructDeclaration
parseStruct(CommonTree struct
)
1375 throws ParseException
{
1376 assert (struct
.getType() == CTFParser
.STRUCT
);
1378 List
<CommonTree
> children
= struct
.getChildren();
1379 assert (children
!= null);
1381 /* The return value */
1382 StructDeclaration structDeclaration
= null;
1385 String structName
= null;
1386 boolean hasName
= false;
1389 CommonTree structBody
= null;
1390 boolean hasBody
= false;
1393 long structAlign
= 0;
1395 /* Loop on all children and identify what we have to work with. */
1396 for (CommonTree child
: children
) {
1397 switch (child
.getType()) {
1398 case CTFParser
.STRUCT_NAME
: {
1401 assert (child
.getChildCount() == 1);
1402 CommonTree structNameIdentifier
= (CommonTree
) child
1405 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1406 structName
= structNameIdentifier
.getText();
1410 case CTFParser
.STRUCT_BODY
: {
1417 case CTFParser
.ALIGN
: {
1418 assert (child
.getChildCount() == 1);
1419 CommonTree structAlignExpression
= (CommonTree
) child
1422 structAlign
= getAlignment(structAlignExpression
);
1427 childTypeError(child
);
1434 * If a struct has just a body and no name (just like the song,
1435 * "A Struct With No Name" by America (sorry for that...)), it's a
1436 * definition of a new type, so we create the type declaration and
1437 * return it. We can't add it to the declaration scope since there is no
1438 * name, but that's what we want because it won't be possible to use it
1439 * again to declare another field.
1441 * If it has just a name, we look it up in the declaration scope and
1442 * return the associated declaration. If it is not found in the
1443 * declaration scope, it means that a struct with that name has not been
1444 * declared, which is an error.
1446 * If it has both, then we create the type declaration and register it
1447 * to the current scope.
1449 * If it has none, then what are we doing here ?
1453 * If struct has a name, check if already defined in the current
1456 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1457 throw new ParseException("struct " + structName
//$NON-NLS-1$
1458 + " already defined."); //$NON-NLS-1$
1461 /* Create the declaration */
1462 structDeclaration
= new StructDeclaration(structAlign
);
1464 /* Parse the body */
1465 parseStructBody(structBody
, structDeclaration
);
1467 /* If struct has name, add it to the current scope. */
1469 getCurrentScope().registerStruct(structName
, structDeclaration
);
1471 } else /* !hasBody */{
1473 /* Name and !body */
1475 /* Lookup the name in the current scope. */
1476 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1479 * If not found, it means that a struct with such name has not
1482 if (structDeclaration
== null) {
1483 throw new ParseException("struct " + structName
//$NON-NLS-1$
1484 + " is not defined"); //$NON-NLS-1$
1487 /* !Name and !body */
1489 /* We can't do anything with that. */
1490 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1494 assert (structDeclaration
!= null);
1495 return structDeclaration
;
1499 * Parses a struct body, adding the fields to specified structure
1503 * A STRUCT_BODY node.
1504 * @param structDeclaration
1505 * The struct declaration.
1506 * @throws ParseException
1508 private void parseStructBody(CommonTree structBody
,
1509 StructDeclaration structDeclaration
) throws ParseException
{
1510 assert (structBody
.getType() == CTFParser
.STRUCT_BODY
);
1512 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1515 * If structDeclaration is null, structBody has no children and the
1516 * struct body is empty.
1518 if (structDeclarations
!= null) {
1521 for (CommonTree declarationNode
: structDeclarations
) {
1522 switch (declarationNode
.getType()) {
1523 case CTFParser
.TYPEALIAS
:
1524 parseTypealias(declarationNode
);
1526 case CTFParser
.TYPEDEF
:
1527 parseTypedef(declarationNode
);
1529 case CTFParser
.SV_DECLARATION
:
1530 parseStructDeclaration(declarationNode
, structDeclaration
);
1533 childTypeError(declarationNode
);
1542 * Parses a declaration found in a struct.
1544 * @param declaration
1545 * A SV_DECLARATION node.
1547 * A struct declaration. (I know, little name clash here...)
1548 * @throws ParseException
1550 private void parseStructDeclaration(CommonTree declaration
,
1551 StructDeclaration struct
) throws ParseException
{
1552 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
1554 List
<CommonTree
> children
= declaration
.getChildren();
1555 assert (children
!= null);
1557 /* Get the type specifier list node */
1558 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
1559 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1560 assert (typeSpecifierListNode
!= null);
1562 /* Get the type declarator list node */
1563 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
1564 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1565 assert (typeDeclaratorListNode
!= null);
1567 /* Get the type declarator list */
1568 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
1570 assert (typeDeclaratorList
!= null);
1573 * For each type declarator, parse the declaration and add a field to
1576 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1577 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
1579 StringBuilder identifierSB
= new StringBuilder();
1581 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1582 typeSpecifierListNode
, identifierSB
);
1583 String fieldName
= identifierSB
.toString();
1585 if (struct
.hasField(fieldName
)) {
1586 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1590 struct
.addField(fieldName
, decl
);
1596 * Parses an enum declaration and returns the corresponding declaration.
1600 * @return The corresponding enum declaration.
1601 * @throws ParseException
1603 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1604 assert (_enum
.getType() == CTFParser
.ENUM
);
1606 List
<CommonTree
> children
= _enum
.getChildren();
1607 assert (children
!= null);
1609 /* The return value */
1610 EnumDeclaration enumDeclaration
= null;
1613 String enumName
= null;
1616 CommonTree enumBody
= null;
1618 /* Container type */
1619 IntegerDeclaration containerTypeDeclaration
= null;
1621 /* Loop on all children and identify what we have to work with. */
1622 for (CommonTree child
: children
) {
1623 switch (child
.getType()) {
1624 case CTFParser
.ENUM_NAME
: {
1625 assert (enumName
== null);
1627 assert (child
.getChildCount() == 1);
1628 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1630 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1631 enumName
= enumNameIdentifier
.getText();
1635 case CTFParser
.ENUM_BODY
: {
1636 assert (enumBody
== null);
1642 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1643 assert (containerTypeDeclaration
== null);
1645 containerTypeDeclaration
= parseEnumContainerType(child
);
1650 childTypeError(child
);
1656 * If the container type has not been defined explicitly, we assume it
1659 if (containerTypeDeclaration
== null) {
1660 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1663 throw new ParseException(
1664 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1665 } else if (!(decl
instanceof IntegerDeclaration
)) {
1666 throw new ParseException(
1667 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1670 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1674 * If it has a body, it's a new declaration, otherwise it's a reference
1675 * to an existing declaration. Same logic as struct.
1677 if (enumBody
!= null) {
1679 * If enum has a name, check if already defined in the current
1682 if ((enumName
!= null)
1683 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1684 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1685 + " already defined"); //$NON-NLS-1$
1688 /* Create the declaration */
1689 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1691 /* Parse the body */
1692 parseEnumBody(enumBody
, enumDeclaration
);
1694 /* If the enum has name, add it to the current scope. */
1695 if (enumName
!= null) {
1696 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1699 if (enumName
!= null) {
1700 /* Name and !body */
1702 /* Lookup the name in the current scope. */
1703 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1706 * If not found, it means that an enum with such name has not
1709 if (enumDeclaration
== null) {
1710 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1711 + " is not defined"); //$NON-NLS-1$
1714 /* !Name and !body */
1715 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1719 return enumDeclaration
;
1724 * Parses an enum body, adding the enumerators to the specified enum
1728 * An ENUM_BODY node.
1729 * @param enumDeclaration
1730 * The enum declaration.
1731 * @throws ParseException
1733 private void parseEnumBody(CommonTree enumBody
,
1734 EnumDeclaration enumDeclaration
) throws ParseException
{
1735 assert (enumBody
.getType() == CTFParser
.ENUM_BODY
);
1737 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1738 /* enum body can't be empty (unlike struct). */
1739 assert (enumerators
!= null);
1744 * Start at -1, so that if the first enumrator has no explicit value, it
1749 for (CommonTree enumerator
: enumerators
) {
1750 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1759 * Parses an enumerator node and adds an enumerator declaration to an
1760 * enumeration declaration.
1762 * The high value of the range of the last enumerator is needed in case the
1763 * current enumerator does not specify its value.
1766 * An ENUM_ENUMERATOR node.
1767 * @param enumDeclaration
1768 * en enumeration declaration to which will be added the
1771 * The high value of the range of the last enumerator
1772 * @return The high value of the value range of the current enumerator.
1773 * @throws ParseException
1775 private static long parseEnumEnumerator(CommonTree enumerator
,
1776 EnumDeclaration enumDeclaration
, long lastHigh
)
1777 throws ParseException
{
1778 assert (enumerator
.getType() == CTFParser
.ENUM_ENUMERATOR
);
1780 List
<CommonTree
> children
= enumerator
.getChildren();
1781 assert (children
!= null);
1783 long low
= 0, high
= 0;
1784 boolean valueSpecified
= false;
1785 String label
= null;
1787 for (CommonTree child
: children
) {
1788 if (isUnaryString(child
)) {
1789 label
= parseUnaryString(child
);
1790 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1791 assert (child
.getChildCount() == 1);
1792 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1794 valueSpecified
= true;
1796 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1798 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1799 assert (child
.getChildCount() == 2);
1800 assert (isUnaryInteger((CommonTree
) child
.getChild(0)));
1801 assert (isUnaryInteger((CommonTree
) child
.getChild(1)));
1803 valueSpecified
= true;
1805 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1806 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1808 childTypeError(child
);
1812 assert (label
!= null);
1814 if (!valueSpecified
) {
1820 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1823 if (!enumDeclaration
.add(low
, high
, label
)) {
1824 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1831 * Parses an enum container type node and returns the corresponding integer
1834 * @param enumContainerType
1835 * An ENUM_CONTAINER_TYPE node.
1836 * @return An integer declaration corresponding to the container type.
1837 * @throws ParseException
1838 * If the type does not parse correctly or if it is not an
1841 private IntegerDeclaration
parseEnumContainerType(
1842 CommonTree enumContainerType
) throws ParseException
{
1843 assert (enumContainerType
.getType() == CTFParser
.ENUM_CONTAINER_TYPE
);
1845 /* Get the child, which should be a type specifier list */
1846 assert (enumContainerType
.getChildCount() == 1);
1847 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
1850 /* Parse it and get the corresponding declaration */
1851 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1853 /* If is is an integer, return it, else throw an error */
1854 if (decl
instanceof IntegerDeclaration
) {
1855 return (IntegerDeclaration
) decl
;
1857 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1860 private VariantDeclaration
parseVariant(CommonTree variant
)
1861 throws ParseException
{
1862 assert (variant
.getType() == CTFParser
.VARIANT
);
1864 List
<CommonTree
> children
= variant
.getChildren();
1865 VariantDeclaration variantDeclaration
= null;
1867 boolean hasName
= false;
1868 String variantName
= null;
1870 boolean hasBody
= false;
1871 CommonTree variantBody
= null;
1873 boolean hasTag
= false;
1874 String variantTag
= null;
1876 for (CommonTree child
: children
) {
1877 switch (child
.getType()) {
1878 case CTFParser
.VARIANT_NAME
:
1879 assert (variantName
== null);
1883 assert (child
.getChildCount() == 1);
1884 CommonTree variantNameIdentifier
= (CommonTree
) child
1887 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1888 variantName
= variantNameIdentifier
.getText();
1891 case CTFParser
.VARIANT_TAG
:
1892 assert (variantTag
== null);
1896 assert (child
.getChildCount() == 1);
1897 CommonTree variantTagIdentifier
= (CommonTree
) child
1900 assert (variantTagIdentifier
.getType() == CTFParser
.IDENTIFIER
);
1901 variantTag
= variantTagIdentifier
.getText();
1904 case CTFParser
.VARIANT_BODY
:
1905 assert (variantBody
== null);
1909 variantBody
= child
;
1913 childTypeError(child
);
1920 * If variant has a name, check if already defined in the current
1924 && (getCurrentScope().lookupVariant(variantName
) != null)) {
1925 throw new ParseException("variant " + variantName
//$NON-NLS-1$
1926 + " already defined."); //$NON-NLS-1$
1929 /* Create the declaration */
1930 variantDeclaration
= new VariantDeclaration();
1932 /* Parse the body */
1933 parseVariantBody(variantBody
, variantDeclaration
);
1935 /* If variant has name, add it to the current scope. */
1937 getCurrentScope().registerVariant(variantName
,
1938 variantDeclaration
);
1940 } else /* !hasBody */{
1942 /* Name and !body */
1944 /* Lookup the name in the current scope. */
1945 variantDeclaration
= getCurrentScope().rlookupVariant(
1949 * If not found, it means that a struct with such name has not
1952 if (variantDeclaration
== null) {
1953 throw new ParseException("variant " + variantName
//$NON-NLS-1$
1954 + " is not defined"); //$NON-NLS-1$
1957 /* !Name and !body */
1959 /* We can't do anything with that. */
1960 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
1965 variantDeclaration
.setTag(variantTag
);
1968 assert (variantDeclaration
!= null);
1969 return variantDeclaration
;
1972 private void parseVariantBody(CommonTree variantBody
,
1973 VariantDeclaration variantDeclaration
) throws ParseException
{
1974 assert (variantBody
.getType() == CTFParser
.VARIANT_BODY
);
1976 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
1977 assert (variantDeclarations
!= null);
1981 for (CommonTree declarationNode
: variantDeclarations
) {
1982 switch (declarationNode
.getType()) {
1983 case CTFParser
.TYPEALIAS
:
1984 parseTypealias(declarationNode
);
1986 case CTFParser
.TYPEDEF
:
1987 parseTypedef(declarationNode
);
1989 case CTFParser
.SV_DECLARATION
:
1990 parseVariantDeclaration(declarationNode
, variantDeclaration
);
1993 childTypeError(declarationNode
);
2001 private void parseVariantDeclaration(CommonTree declaration
,
2002 VariantDeclaration variant
) throws ParseException
{
2003 assert (declaration
.getType() == CTFParser
.SV_DECLARATION
);
2005 List
<CommonTree
> children
= declaration
.getChildren();
2006 assert (children
!= null);
2008 /* Get the type specifier list node */
2009 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
2010 .getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2011 assert (typeSpecifierListNode
!= null);
2013 /* Get the type declarator list node */
2014 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
2015 .getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2016 assert (typeDeclaratorListNode
!= null);
2018 /* Get the type declarator list */
2019 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
2021 assert (typeDeclaratorList
!= null);
2024 * For each type declarator, parse the declaration and add a field to
2027 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2028 assert (typeDeclaratorNode
.getType() == CTFParser
.TYPE_DECLARATOR
);
2030 StringBuilder identifierSB
= new StringBuilder();
2032 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2033 typeSpecifierListNode
, identifierSB
);
2035 if (variant
.hasField(identifierSB
.toString())) {
2036 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2037 + identifierSB
.toString());
2040 variant
.addField(identifierSB
.toString(), decl
);
2045 * Creates the string representation of a type declaration (type specifier
2048 * @param typeSpecifierList
2049 * A TYPE_SPECIFIER_LIST node.
2051 * A list of POINTER nodes.
2052 * @return The string representation.
2053 * @throws ParseException
2055 private static String
createTypeDeclarationString(
2056 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2057 throws ParseException
{
2058 StringBuilder sb
= new StringBuilder();
2060 createTypeSpecifierListString(typeSpecifierList
, sb
);
2061 createPointerListString(pointers
, sb
);
2063 return sb
.toString();
2067 * Creates the string representation of a list of type specifiers.
2069 * @param typeSpecifierList
2070 * A TYPE_SPECIFIER_LIST node.
2072 * A StringBuilder to which will be appended the string.
2073 * @throws ParseException
2075 private static void createTypeSpecifierListString(
2076 CommonTree typeSpecifierList
, StringBuilder sb
)
2077 throws ParseException
{
2078 assert (typeSpecifierList
.getType() == CTFParser
.TYPE_SPECIFIER_LIST
);
2080 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2081 assert (children
!= null);
2083 boolean firstItem
= true;
2085 for (CommonTree child
: children
) {
2093 /* Append the string that represents this type specifier. */
2094 createTypeSpecifierString(child
, sb
);
2099 * Creates the string representation of a type specifier.
2101 * @param typeSpecifier
2102 * A TYPE_SPECIFIER node.
2104 * A StringBuilder to which will be appended the string.
2105 * @throws ParseException
2107 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2108 StringBuilder sb
) throws ParseException
{
2109 switch (typeSpecifier
.getType()) {
2110 case CTFParser
.FLOATTOK
:
2111 case CTFParser
.INTTOK
:
2112 case CTFParser
.LONGTOK
:
2113 case CTFParser
.SHORTTOK
:
2114 case CTFParser
.SIGNEDTOK
:
2115 case CTFParser
.UNSIGNEDTOK
:
2116 case CTFParser
.CHARTOK
:
2117 case CTFParser
.DOUBLETOK
:
2118 case CTFParser
.VOIDTOK
:
2119 case CTFParser
.BOOLTOK
:
2120 case CTFParser
.COMPLEXTOK
:
2121 case CTFParser
.IMAGINARYTOK
:
2122 case CTFParser
.CONSTTOK
:
2123 case CTFParser
.IDENTIFIER
:
2124 sb
.append(typeSpecifier
.getText());
2126 case CTFParser
.STRUCT
: {
2127 CommonTree structName
= (CommonTree
) typeSpecifier
2128 .getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2129 if (structName
== null) {
2130 throw new ParseException(
2131 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2133 assert (structName
.getChildCount() == 1);
2135 CommonTree structNameIdentifier
= (CommonTree
) structName
2137 assert (structNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2139 sb
.append(structNameIdentifier
.getText());
2142 case CTFParser
.VARIANT
: {
2143 CommonTree variantName
= (CommonTree
) typeSpecifier
2144 .getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2145 if (variantName
== null) {
2146 throw new ParseException(
2147 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2149 assert (variantName
.getChildCount() == 1);
2151 CommonTree variantNameIdentifier
= (CommonTree
) variantName
2153 assert (variantNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2155 sb
.append(variantNameIdentifier
.getText());
2158 case CTFParser
.ENUM
: {
2159 CommonTree enumName
= (CommonTree
) typeSpecifier
2160 .getFirstChildWithType(CTFParser
.ENUM_NAME
);
2161 if (enumName
== null) {
2162 throw new ParseException(
2163 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2165 assert (enumName
.getChildCount() == 1);
2167 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2168 assert (enumNameIdentifier
.getType() == CTFParser
.IDENTIFIER
);
2170 sb
.append(enumNameIdentifier
.getText());
2173 case CTFParser
.FLOATING_POINT
:
2174 case CTFParser
.INTEGER
:
2175 case CTFParser
.STRING
:
2176 throw new ParseException(
2177 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2180 childTypeError(typeSpecifier
);
2186 * Creates the string representation of a list of pointers.
2188 * @param pointerList
2189 * A list of pointer nodes. If pointerList is null, this function
2192 * A stringbuilder to which will be appended the string.
2194 private static void createPointerListString(List
<CommonTree
> pointerList
,
2196 if (pointerList
== null) {
2200 for (CommonTree pointer
: pointerList
) {
2201 assert (pointer
.getType() == CTFParser
.POINTER
);
2203 sb
.append(" *"); //$NON-NLS-1$
2204 if (pointer
.getChildCount() > 0) {
2205 assert (pointer
.getChildCount() == 1);
2206 CommonTree constQualifier
= (CommonTree
) pointer
.getChild(0);
2207 assert (constQualifier
.getType() == CTFParser
.CONSTTOK
);
2209 sb
.append(" const"); //$NON-NLS-1$
2216 * The node to check.
2217 * @return True if the given node is an unary string or unary integer.
2219 private static boolean isUnaryExpression(CommonTree node
) {
2220 return isUnaryInteger(node
) || isUnaryString(node
);
2225 * The node to check.
2226 * @return True if the given node is an unary string.
2228 private static boolean isUnaryString(CommonTree node
) {
2229 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (node
2230 .getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2235 * The node to check.
2236 * @return True if the given node is an unary integer.
2238 private static boolean isUnaryInteger(CommonTree node
) {
2239 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
)
2240 || (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) || (node
2241 .getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2245 * Parses a unary string node and return the string value.
2247 * @param unaryString
2248 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2249 * or UNARY_EXPRESSION_STRING_QUOTES).
2250 * @return The string value.
2253 * It would be really nice to remove the quotes earlier, such as in the
2256 private static String
parseUnaryString(CommonTree unaryString
) {
2257 assert (isUnaryString(unaryString
));
2259 assert (unaryString
.getChildCount() == 1);
2260 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2261 assert (value
!= null);
2262 String strval
= value
.getText();
2265 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2266 strval
= strval
.substring(1, strval
.length() - 1);
2273 * Parses an unary integer (dec, hex or oct).
2275 * @param unaryInteger
2276 * An unary integer node.
2277 * @return The integer value.
2279 private static long parseUnaryInteger(CommonTree unaryInteger
) {
2280 assert (isUnaryInteger(unaryInteger
));
2282 assert (unaryInteger
.getChildCount() >= 1);
2284 List
<CommonTree
> children
= unaryInteger
.getChildren();
2285 CommonTree value
= children
.get(0);
2286 String strval
= value
.getText();
2290 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2291 intval
= Long
.parseLong(strval
, 10);
2292 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2293 intval
= Long
.parseLong(strval
, 0x10);
2294 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2295 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2298 /* The rest of children are sign */
2299 if ((children
.size() % 2) == 0) {
2305 private static long getMajorOrMinor(CommonTree rightNode
)
2306 throws ParseException
{
2307 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2308 assert (rightNode
.getChildCount() > 0);
2310 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2312 if (isUnaryInteger(firstChild
)) {
2313 if (rightNode
.getChildCount() > 1) {
2314 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2317 long m
= parseUnaryInteger(firstChild
);
2320 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2325 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2328 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2329 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2330 assert (rightNode
.getChildCount() > 0);
2332 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2334 if (isUnaryString(firstChild
)) {
2335 if (rightNode
.getChildCount() > 1) {
2336 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2339 String uuidstr
= parseUnaryString(firstChild
);
2342 UUID uuid
= UUID
.fromString(uuidstr
);
2344 } catch (IllegalArgumentException e
) {
2345 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2348 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2352 * Gets the value of a "signed" integer attribute.
2356 * @return The "signed" value as a boolean.
2357 * @throws ParseException
2359 private static boolean getSigned(CommonTree rightNode
)
2360 throws ParseException
{
2361 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2362 assert (rightNode
.getChildCount() > 0);
2364 boolean ret
= false;
2365 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2367 if (isUnaryString(firstChild
)) {
2368 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2370 if (strval
.equals("true") || strval
.equals("TRUE")) { //$NON-NLS-1$ //$NON-NLS-2$
2372 } else if (strval
.equals("false") || strval
.equals("FALSE")) { //$NON-NLS-1$ //$NON-NLS-2$
2375 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2376 + firstChild
.getChild(0).getText());
2378 } else if (isUnaryInteger(firstChild
)) {
2379 /* Happens if the value is something like "1234.hello" */
2380 if (rightNode
.getChildCount() > 1) {
2381 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2384 long intval
= parseUnaryInteger(firstChild
);
2388 } else if (intval
== 0) {
2391 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2392 + firstChild
.getChild(0).getText());
2395 throw new ParseException();
2402 * Gets the value of a "byte_order" integer attribute.
2406 * @return The "byte_order" value.
2407 * @throws ParseException
2409 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2410 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2411 assert (rightNode
.getChildCount() > 0);
2413 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2415 if (isUnaryString(firstChild
)) {
2416 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2418 if (strval
.equals("le")) { //$NON-NLS-1$
2419 return ByteOrder
.LITTLE_ENDIAN
;
2420 } else if (strval
.equals("be") || strval
.equals("network")) { //$NON-NLS-1$ //$NON-NLS-2$
2421 return ByteOrder
.BIG_ENDIAN
;
2422 } else if (strval
.equals("native")) { //$NON-NLS-1$
2423 return trace
.getByteOrder();
2425 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2428 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2432 * Determines if the given value is a valid alignment value.
2435 * The value to check.
2436 * @return True if it is valid.
2438 private static boolean isValidAlignment(long alignment
) {
2439 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2443 * Gets the value of a "size" integer attribute.
2447 * @return The "size" value.
2448 * @throws ParseException
2450 private static long getSize(CommonTree rightNode
) throws ParseException
{
2451 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2452 assert (rightNode
.getChildCount() > 0);
2454 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2456 if (isUnaryInteger(firstChild
)) {
2457 if (rightNode
.getChildCount() > 1) {
2458 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2461 long size
= parseUnaryInteger(firstChild
);
2464 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2469 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2473 * Gets the value of a "align" integer or struct attribute.
2476 * A CTF_RIGHT node or directly an unary integer.
2477 * @return The align value.
2478 * @throws ParseException
2480 private static long getAlignment(CommonTree node
) throws ParseException
{
2481 assert (isUnaryExpression(node
) || (node
.getType() == CTFParser
.CTF_RIGHT
));
2484 * If a CTF_RIGHT node was passed, call getAlignment with the first
2487 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2488 if (node
.getChildCount() > 1) {
2489 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2492 return getAlignment((CommonTree
) node
.getChild(0));
2493 } else if (isUnaryInteger(node
)) {
2494 long alignment
= parseUnaryInteger(node
);
2496 if (!isValidAlignment(alignment
)) {
2497 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2503 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2507 * Gets the value of a "base" integer attribute.
2510 * An CTF_RIGHT node.
2511 * @return The "base" value.
2512 * @throws ParseException
2514 private static int getBase(CommonTree rightNode
) throws ParseException
{
2515 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2516 assert (rightNode
.getChildCount() > 0);
2518 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2520 if (isUnaryInteger(firstChild
)) {
2521 if (rightNode
.getChildCount() > 1) {
2522 throw new ParseException("invalid base value"); //$NON-NLS-1$
2525 long intval
= parseUnaryInteger(firstChild
);
2526 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2527 || (intval
== 16)) {
2528 return (int) intval
;
2530 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2531 } else if (isUnaryString(firstChild
)) {
2532 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2534 if (strval
.equals("decimal") || strval
.equals("dec") //$NON-NLS-1$ //$NON-NLS-2$
2535 || strval
.equals("d") || strval
.equals("i") //$NON-NLS-1$ //$NON-NLS-2$
2536 || strval
.equals("u")) { //$NON-NLS-1$
2538 } else if (strval
.equals("hexadecimal") || strval
.equals("hex") //$NON-NLS-1$ //$NON-NLS-2$
2539 || strval
.equals("x") || strval
.equals("X") //$NON-NLS-1$ //$NON-NLS-2$
2540 || strval
.equals("p")) { //$NON-NLS-1$
2542 } else if (strval
.equals("octal") || strval
.equals("oct") //$NON-NLS-1$ //$NON-NLS-2$
2543 || strval
.equals("o")) { //$NON-NLS-1$
2545 } else if (strval
.equals("binary") || strval
.equals("b")) { //$NON-NLS-1$ //$NON-NLS-2$
2548 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2551 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2556 * Gets the value of an "encoding" integer attribute.
2560 * @return The "encoding" value.
2561 * @throws ParseException
2563 private static Encoding
getEncoding(CommonTree rightNode
)
2564 throws ParseException
{
2565 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2567 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2569 if (isUnaryString(firstChild
)) {
2570 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2572 if (strval
.equals("UTF8")) { //$NON-NLS-1$
2573 return Encoding
.UTF8
;
2574 } else if (strval
.equals("ASCII")) { //$NON-NLS-1$
2575 return Encoding
.ASCII
;
2576 } else if (strval
.equals("none")) { //$NON-NLS-1$
2577 return Encoding
.NONE
;
2579 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2582 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2585 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2586 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2587 assert (rightNode
.getChildCount() > 0);
2589 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2591 if (isUnaryInteger(firstChild
)) {
2592 if (rightNode
.getChildCount() > 1) {
2593 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2596 long intval
= parseUnaryInteger(firstChild
);
2600 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2603 private static String
getEventName(CommonTree rightNode
)
2604 throws ParseException
{
2605 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2606 assert (rightNode
.getChildCount() > 0);
2608 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2610 if (isUnaryString(firstChild
)) {
2611 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2615 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2618 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2619 assert (rightNode
.getType() == CTFParser
.CTF_RIGHT
);
2620 assert (rightNode
.getChildCount() > 0);
2622 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2624 if (isUnaryInteger(firstChild
)) {
2625 if (rightNode
.getChildCount() > 1) {
2626 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2629 long intval
= parseUnaryInteger(firstChild
);
2633 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2637 * Concatenates a list of unary strings separated by arrows (->) or dots.
2640 * A list, first element being an unary string, subsequent
2641 * elements being ARROW or DOT nodes with unary strings as child.
2642 * @return The string representation of the unary string chain.
2644 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2645 assert ((strings
!= null) && (strings
.size() > 0));
2647 StringBuilder sb
= new StringBuilder();
2649 CommonTree first
= strings
.get(0);
2650 sb
.append(parseUnaryString(first
));
2652 boolean isFirst
= true;
2654 for (CommonTree ref
: strings
) {
2660 assert ((ref
.getType() == CTFParser
.ARROW
) || (ref
.getType() == CTFParser
.DOT
));
2661 assert (ref
.getChildCount() == 1);
2663 CommonTree id
= (CommonTree
) ref
.getChild(0);
2665 if (ref
.getType() == CTFParser
.ARROW
) {
2666 sb
.append("->"); //$NON-NLS-1$
2671 sb
.append(parseUnaryString(id
));
2674 return sb
.toString();
2678 * Throws a ParseException stating that the parent-child relation between
2679 * the given node and its parent is not valid. It means that the shape of
2680 * the AST is unexpected.
2683 * The invalid child node.
2684 * @throws ParseException
2686 private static void childTypeError(CommonTree child
) throws ParseException
{
2687 CommonTree parent
= (CommonTree
) child
.getParent();
2688 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2689 + " can't have a child of type " //$NON-NLS-1$
2690 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2692 throw new ParseException(error
);
2695 // ------------------------------------------------------------------------
2697 // ------------------------------------------------------------------------
2700 * Adds a new declaration scope on the top of the scope stack.
2702 private void pushScope() {
2703 scope
= new DeclarationScope(scope
);
2707 * Removes the top declaration scope from the scope stack.
2709 private void popScope() {
2710 assert (scope
!= null);
2711 scope
= scope
.getParentScope();
2715 * Returns the current declaration scope.
2717 * @return The current declaration scope.
2719 private DeclarationScope
getCurrentScope() {
2720 assert (scope
!= null);