1 /*******************************************************************************
2 * Copyright (c) 2011-2013 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 * Contributors: Simon Marchi - Initial API and implementation
12 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
;
16 import java
.io
.FileNotFoundException
;
17 import java
.io
.IOException
;
18 import java
.io
.UnsupportedEncodingException
;
19 import java
.nio
.ByteOrder
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Collections
;
22 import java
.util
.LinkedList
;
23 import java
.util
.List
;
24 import java
.util
.UUID
;
26 import org
.antlr
.runtime
.tree
.CommonTree
;
27 import org
.eclipse
.linuxtools
.ctf
.core
.event
.CTFClock
;
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
.core
.trace
.Stream
;
40 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
41 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.EventDeclaration
;
42 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
47 public class IOStructGen
{
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
53 static private final boolean DEBUG_
= false;
58 private final CTFTrace trace
;
59 private final CommonTree tree
;
62 * The current declaration scope.
64 private DeclarationScope scope
= null;
66 // ------------------------------------------------------------------------
68 // ------------------------------------------------------------------------
74 * the tree (ANTLR generated) with the parsed TSDL data.
76 * the trace containing the places to put all the read metadata
78 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
84 * Parse the tree and populate the trace defined in the constructor.
86 * @throws ParseException
87 * If there was a problem parsing the metadata
89 public void generate() throws ParseException
{
93 // ------------------------------------------------------------------------
95 // ------------------------------------------------------------------------
98 * Parse the root node.
102 * @throws ParseException
104 private void parseRoot(CommonTree root
) throws ParseException
{
106 List
<CommonTree
> children
= root
.getChildren();
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 List
<CommonTree
> callsites
= new ArrayList
<CommonTree
>();
129 /* Create a new declaration scope with no parent. */
133 for (CommonTree child
: children
) {
134 final int type
= child
.getType();
136 out
.write(child
.toString()
137 + " -> " + type
+ '\n'); //$NON-NLS-1$
140 case CTFParser
.DECLARATION
:
141 declarations
.add(child
);
143 case CTFParser
.TRACE
:
144 if (traceNode
!= null) {
145 throw new ParseException(
146 "Only one trace block is allowed"); //$NON-NLS-1$
150 case CTFParser
.STREAM
:
153 case CTFParser
.EVENT
:
156 case CTFParser
.CLOCK
:
160 environments
.add(child
);
162 case CTFParser
.CALLSITE
:
163 callsites
.add(child
);
166 childTypeError(child
);
170 out
.write("Declarations\n"); //$NON-NLS-1$
172 for (CommonTree decl
: declarations
) {
174 out
.write(decl
.toString() + '\n');
176 parseRootDeclaration(decl
);
178 if (traceNode
== null) {
179 throw new ParseException("Missing trace block"); //$NON-NLS-1$
182 parseTrace(traceNode
);
185 out
.write("Environments\n"); //$NON-NLS-1$
187 for (CommonTree environment
: environments
) {
188 parseEnvironment(environment
);
191 out
.write("Clocks\n"); //$NON-NLS-1$
193 for (CommonTree clock
: clocks
) {
197 out
.write("Callsites\n"); //$NON-NLS-1$
199 for (CommonTree callsite
: callsites
) {
200 parseCallsite(callsite
);
204 out
.write("Streams\n"); //$NON-NLS-1$
206 if (streams
.size() > 0) {
207 for (CommonTree stream
: streams
) {
210 out
.write(stream
.toString() + '\n');
211 } catch (IOException e
) {
218 /* Add an empty stream that will have a null id */
219 trace
.addStream(new Stream(trace
));
223 out
.write("Events\n"); //$NON-NLS-1$
225 for (CommonTree event
: events
) {
228 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
229 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
230 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
238 } catch (IOException e
) {
244 private void parseCallsite(CommonTree callsite
) {
246 List
<CommonTree
> children
= callsite
.getChildren();
248 String func_name
= null;
249 long line_number
= -1;
251 String file_name
= null;
253 for (CommonTree child
: children
) {
255 /* this is a regex to find the leading and trailing quotes*/
256 final String regex
= "^\"|\"$"; //$NON-NLS-1$
257 /* this is to replace the previous quotes with nothing... effectively deleting them */
258 final String nullString
= ""; //$NON-NLS-1$
259 left
= child
.getChild(0).getChild(0).getChild(0).getText();
260 if (left
.equals("name")) { //$NON-NLS-1$
261 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
262 } else if (left
.equals("func")) { //$NON-NLS-1$
263 func_name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
264 } else if (left
.equals("ip")) { //$NON-NLS-1$
265 ip
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText().substring(2),16); // trim the 0x
266 } else if (left
.equals("file")) { //$NON-NLS-1$
267 file_name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
268 } else if (left
.equals("line")) { //$NON-NLS-1$
269 line_number
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
272 trace
.addCallsite(name
, func_name
, ip
,file_name
, line_number
);
275 private void parseEnvironment(CommonTree environment
) {
276 List
<CommonTree
> children
= environment
.getChildren();
277 for (CommonTree child
: children
) {
280 left
= child
.getChild(0).getChild(0).getChild(0).getText();
281 right
= child
.getChild(1).getChild(0).getChild(0).getText();
282 trace
.addEnvironmentVar(left
, right
);
286 private void parseClock(CommonTree clock
) {
287 List
<CommonTree
> children
= clock
.getChildren();
288 CTFClock ctfClock
= new CTFClock();
289 for (CommonTree child
: children
) {
290 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
291 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
292 final int type
= value
.getType();
294 case CTFParser
.INTEGER
:
295 case CTFParser
.DECIMAL_LITERAL
:
297 * Not a pretty hack, this is to make sure that there is no
298 * number overflow due to 63 bit integers. The offset should
299 * only really be an issue in the year 2262. the tracer in C/ASM
300 * can write an offset in an unsigned 64 bit long. In java, the
301 * last bit, being set to 1 will be read as a negative number,
302 * but since it is too big a positive it will throw an
303 * exception. this will happen in 2^63 ns from 1970. Therefore
304 * 293 years from 1970
308 numValue
= Long
.parseLong(value
.getText());
309 } catch (Exception e
) {
310 numValue
= 1330938566783103277L;
312 ctfClock
.addAttribute(key
, numValue
);
315 ctfClock
.addAttribute(key
, value
.getText());
319 String NameValue
= ctfClock
.getName();
320 trace
.addClock(NameValue
, ctfClock
);
323 private void parseTrace(CommonTree traceNode
) throws ParseException
{
325 List
<CommonTree
> children
= traceNode
.getChildren();
326 if (children
== null) {
327 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
332 for (CommonTree child
: children
) {
333 switch (child
.getType()) {
334 case CTFParser
.TYPEALIAS
:
335 parseTypealias(child
);
337 case CTFParser
.TYPEDEF
:
340 case CTFParser
.CTF_EXPRESSION_TYPE
:
341 case CTFParser
.CTF_EXPRESSION_VAL
:
342 parseTraceDeclaration(child
);
345 childTypeError(child
);
351 * If trace byte order was not specified and not using packet based
354 if (trace
.getByteOrder() == null) {
355 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
361 private void parseTraceDeclaration(CommonTree traceDecl
)
362 throws ParseException
{
364 /* There should be a left and right */
366 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
367 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
369 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
371 if (!isUnaryString(leftStrings
.get(0))) {
372 throw new ParseException(
373 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
376 String left
= concatenateUnaryStrings(leftStrings
);
378 if (left
.equals(CTFStrings
.MAJOR
)) {
379 if (trace
.majortIsSet()) {
380 throw new ParseException("major is already set"); //$NON-NLS-1$
383 trace
.setMajor(getMajorOrMinor(rightNode
));
384 } else if (left
.equals(CTFStrings
.MINOR
)) {
385 if (trace
.minorIsSet()) {
386 throw new ParseException("minor is already set"); //$NON-NLS-1$
389 trace
.setMinor(getMajorOrMinor(rightNode
));
390 } else if (left
.equals(CTFStrings
.UUID_STRING
)) {
391 UUID uuid
= getUUID(rightNode
);
394 * If uuid was already set by a metadata packet, compare it to see
397 if (trace
.UUIDIsSet()) {
398 if (trace
.getUUID().compareTo(uuid
) != 0) {
399 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
400 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
406 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
407 ByteOrder byteOrder
= getByteOrder(rightNode
);
410 * If byte order was already set by a metadata packet, compare it to
413 if (trace
.getByteOrder() != null) {
414 if (trace
.getByteOrder() != byteOrder
) {
415 throw new ParseException(
416 "Endianness mismatch. Magic number says " //$NON-NLS-1$
417 + trace
.getByteOrder()
418 + " but metadata says " + byteOrder
); //$NON-NLS-1$
421 trace
.setByteOrder(byteOrder
);
422 final DeclarationScope parentScope
= scope
.getParentScope();
423 String types
[] = parentScope
.getTypeNames();
425 for (String type
: types
) {
426 IDeclaration d
= parentScope
.lookupType(type
);
427 if (d
instanceof IntegerDeclaration
) {
428 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
429 } else if (d
instanceof StructDeclaration
) {
430 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
434 } else if (left
.equals(CTFStrings
.PACKET_HEADER
)) {
435 if (trace
.packetHeaderIsSet()) {
436 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
439 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
441 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
442 throw new ParseException(
443 "packet.header expects a type specifier"); //$NON-NLS-1$
446 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
447 typeSpecifier
, null);
449 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
450 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
453 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
455 throw new ParseException("Unknown trace attribute : " + left
); //$NON-NLS-1$
459 private static void addByteOrder(ByteOrder byteOrder
,
460 final DeclarationScope parentScope
, String name
,
461 IntegerDeclaration decl
) throws ParseException
{
463 if (decl
.getByteOrder() == null) {
464 IntegerDeclaration newI
;
465 newI
= new IntegerDeclaration(decl
.getLength(), decl
.isSigned(),
466 decl
.getBase(), byteOrder
, decl
.getEncoding(),
467 decl
.getClock(), decl
.getAlignment());
468 parentScope
.replaceType(name
, newI
);
472 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
473 ByteOrder byteOrder
) throws ParseException
{
475 for (String s
: sd
.getFieldsList()) {
476 IDeclaration d
= sd
.getFields().get(s
);
478 if (d
instanceof StructDeclaration
) {
479 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
481 } else if (d
instanceof VariantDeclaration
) {
482 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
484 } else if (d
instanceof IntegerDeclaration
) {
485 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
486 if (decl
.getByteOrder() == null) {
487 IntegerDeclaration newI
;
488 newI
= new IntegerDeclaration(decl
.getLength(),
489 decl
.isSigned(), decl
.getBase(), byteOrder
,
490 decl
.getEncoding(), decl
.getClock(),
491 decl
.getAlignment());
492 sd
.getFields().put(s
, newI
);
498 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
499 ByteOrder byteOrder
) throws ParseException
{
501 for (String s
: vd
.getFields().keySet()) {
502 IDeclaration d
= vd
.getFields().get(s
);
504 if (d
instanceof StructDeclaration
) {
505 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
507 } else if (d
instanceof IntegerDeclaration
) {
508 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
509 IntegerDeclaration newI
;
510 newI
= new IntegerDeclaration(decl
.getLength(),
511 decl
.isSigned(), decl
.getBase(), byteOrder
,
512 decl
.getEncoding(), decl
.getClock(),
513 decl
.getAlignment());
514 vd
.getFields().put(s
, newI
);
519 private void parseStream(CommonTree streamNode
) throws ParseException
{
521 Stream stream
= new Stream(trace
);
523 List
<CommonTree
> children
= streamNode
.getChildren();
524 if (children
== null) {
525 throw new ParseException("Empty stream block"); //$NON-NLS-1$
530 for (CommonTree child
: children
) {
531 switch (child
.getType()) {
532 case CTFParser
.TYPEALIAS
:
533 parseTypealias(child
);
535 case CTFParser
.TYPEDEF
:
538 case CTFParser
.CTF_EXPRESSION_TYPE
:
539 case CTFParser
.CTF_EXPRESSION_VAL
:
540 parseStreamDeclaration(child
, stream
);
543 childTypeError(child
);
548 if (stream
.isIdSet()) {
549 if (!trace
.packetHeaderIsSet()
550 || !trace
.getPacketHeader().hasField(CTFStrings
.STREAM_ID
)) {
551 throw new ParseException(
552 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
556 trace
.addStream(stream
);
561 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
562 throws ParseException
{
564 /* There should be a left and right */
566 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
567 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
569 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
571 if (!isUnaryString(leftStrings
.get(0))) {
572 throw new ParseException(
573 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
576 String left
= concatenateUnaryStrings(leftStrings
);
578 if (left
.equals(CTFStrings
.ID
)) {
579 if (stream
.isIdSet()) {
580 throw new ParseException("stream id already defined"); //$NON-NLS-1$
583 long streamID
= getStreamID(rightNode
);
585 stream
.setId(streamID
);
586 } else if (left
.equals(CTFStrings
.EVENT_HEADER
)) {
587 if (stream
.isEventHeaderSet()) {
588 throw new ParseException("event.header already defined"); //$NON-NLS-1$
591 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
593 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
594 throw new ParseException(
595 "event.header expects a type specifier"); //$NON-NLS-1$
598 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
599 typeSpecifier
, null);
601 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
602 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
605 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
606 } else if (left
.equals(CTFStrings
.EVENT_CONTEXT
)) {
607 if (stream
.isEventContextSet()) {
608 throw new ParseException("event.context already defined"); //$NON-NLS-1$
611 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
613 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
614 throw new ParseException(
615 "event.context expects a type specifier"); //$NON-NLS-1$
618 IDeclaration eventContextDecl
= parseTypeSpecifierList(
619 typeSpecifier
, null);
621 if (!(eventContextDecl
instanceof StructDeclaration
)) {
622 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
625 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
626 } else if (left
.equals(CTFStrings
.PACKET_CONTEXT
)) {
627 if (stream
.isPacketContextSet()) {
628 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
631 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
633 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
634 throw new ParseException(
635 "packet.context expects a type specifier"); //$NON-NLS-1$
638 IDeclaration packetContextDecl
= parseTypeSpecifierList(
639 typeSpecifier
, null);
641 if (!(packetContextDecl
instanceof StructDeclaration
)) {
642 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
645 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
647 throw new ParseException("Unknown stream attribute : " + left
); //$NON-NLS-1$
651 private void parseEvent(CommonTree eventNode
) throws ParseException
{
653 List
<CommonTree
> children
= eventNode
.getChildren();
654 if (children
== null) {
655 throw new ParseException("Empty event block"); //$NON-NLS-1$
658 EventDeclaration event
= new EventDeclaration();
662 for (CommonTree child
: children
) {
663 switch (child
.getType()) {
664 case CTFParser
.TYPEALIAS
:
665 parseTypealias(child
);
667 case CTFParser
.TYPEDEF
:
670 case CTFParser
.CTF_EXPRESSION_TYPE
:
671 case CTFParser
.CTF_EXPRESSION_VAL
:
672 parseEventDeclaration(child
, event
);
675 childTypeError(child
);
680 if (!event
.nameIsSet()) {
681 throw new ParseException("Event name not set"); //$NON-NLS-1$
685 * If the event did not specify a stream, then the trace must be single
688 if (!event
.streamIsSet()) {
689 if (trace
.nbStreams() > 1) {
690 throw new ParseException(
691 "Event without stream_id with more than one stream"); //$NON-NLS-1$
695 * If the event did not specify a stream, the only existing stream
696 * must not have an id. Note: That behavior could be changed, it
697 * could be possible to just get the only existing stream, whatever
700 Stream stream
= trace
.getStream(null);
702 if (stream
!= null) {
703 event
.setStream(stream
);
705 throw new ParseException(
706 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
711 * Add the event to the stream.
713 event
.getStream().addEvent(event
);
718 private void parseEventDeclaration(CommonTree eventDecl
,
719 EventDeclaration event
) throws ParseException
{
721 /* There should be a left and right */
723 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
724 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
726 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
728 if (!isUnaryString(leftStrings
.get(0))) {
729 throw new ParseException(
730 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
733 String left
= concatenateUnaryStrings(leftStrings
);
735 if (left
.equals(CTFStrings
.NAME2
)) {
736 if (event
.nameIsSet()) {
737 throw new ParseException("name already defined"); //$NON-NLS-1$
740 String name
= getEventName(rightNode
);
743 } else if (left
.equals(CTFStrings
.ID
)) {
744 if (event
.idIsSet()) {
745 throw new ParseException("id already defined"); //$NON-NLS-1$
748 long id
= getEventID(rightNode
);
751 } else if (left
.equals(CTFStrings
.STREAM_ID
)) {
752 if (event
.streamIsSet()) {
753 throw new ParseException("stream id already defined"); //$NON-NLS-1$
756 long streamId
= getStreamID(rightNode
);
758 Stream stream
= trace
.getStream(streamId
);
760 if (stream
== null) {
761 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
764 event
.setStream(stream
);
765 } else if (left
.equals(CTFStrings
.CONTEXT
)) {
766 if (event
.contextIsSet()) {
767 throw new ParseException("context already defined"); //$NON-NLS-1$
770 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
772 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
773 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
776 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
779 if (!(contextDecl
instanceof StructDeclaration
)) {
780 throw new ParseException("context expects a struct"); //$NON-NLS-1$
783 event
.setContext((StructDeclaration
) contextDecl
);
784 } else if (left
.equals(CTFStrings
.FIELDS_STRING
)) {
785 if (event
.fieldsIsSet()) {
786 throw new ParseException("fields already defined"); //$NON-NLS-1$
789 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
791 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
792 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
795 IDeclaration fieldsDecl
;
796 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
798 if (!(fieldsDecl
instanceof StructDeclaration
)) {
799 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
802 * The underscores in the event names. These underscores were added
803 * by the LTTng tracer.
805 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
806 event
.setFields(fields
);
807 } else if (left
.equals(CTFStrings
.LOGLEVEL2
)) {
808 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
809 event
.setLogLevel(logLevel
);
811 /* Custom event attribute, we'll add it to the attributes map */
812 String right
= parseUnaryString((CommonTree
) rightNode
.getChild(0));
813 event
.setCustomAttribute(left
, right
);
818 * Parses a declaration at the root level.
821 * The declaration subtree.
822 * @throws ParseException
824 private void parseRootDeclaration(CommonTree declaration
)
825 throws ParseException
{
827 List
<CommonTree
> children
= declaration
.getChildren();
829 for (CommonTree child
: children
) {
830 switch (child
.getType()) {
831 case CTFParser
.TYPEDEF
:
834 case CTFParser
.TYPEALIAS
:
835 parseTypealias(child
);
837 case CTFParser
.TYPE_SPECIFIER_LIST
:
838 parseTypeSpecifierList(child
, null);
841 childTypeError(child
);
847 * Parses a typealias node. It parses the target, the alias, and registers
848 * the type in the current scope.
852 * @throws ParseException
854 private void parseTypealias(CommonTree typealias
) throws ParseException
{
856 List
<CommonTree
> children
= typealias
.getChildren();
858 CommonTree target
= null;
859 CommonTree alias
= null;
861 for (CommonTree child
: children
) {
862 switch (child
.getType()) {
863 case CTFParser
.TYPEALIAS_TARGET
:
866 case CTFParser
.TYPEALIAS_ALIAS
:
870 childTypeError(child
);
876 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
878 if (targetDeclaration
instanceof VariantDeclaration
) {
879 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
880 throw new ParseException(
881 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
885 String aliasString
= parseTypealiasAlias(alias
);
887 getCurrentScope().registerType(aliasString
, targetDeclaration
);
891 * Parses the target part of a typealias and gets the corresponding
895 * A TYPEALIAS_TARGET node.
896 * @return The corresponding declaration.
897 * @throws ParseException
899 private IDeclaration
parseTypealiasTarget(CommonTree target
)
900 throws ParseException
{
902 List
<CommonTree
> children
= target
.getChildren();
904 CommonTree typeSpecifierList
= null;
905 CommonTree typeDeclaratorList
= null;
906 CommonTree typeDeclarator
= null;
907 StringBuilder identifierSB
= new StringBuilder();
909 for (CommonTree child
: children
) {
910 switch (child
.getType()) {
911 case CTFParser
.TYPE_SPECIFIER_LIST
:
912 typeSpecifierList
= child
;
914 case CTFParser
.TYPE_DECLARATOR_LIST
:
915 typeDeclaratorList
= child
;
918 childTypeError(child
);
924 if (typeDeclaratorList
!= null) {
926 * Only allow one declarator
928 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
929 * otherwise the new type puint8_t would maps to two different
932 if (typeDeclaratorList
.getChildCount() != 1) {
933 throw new ParseException(
934 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
937 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
940 /* Parse the target type and get the declaration */
941 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
942 typeSpecifierList
, identifierSB
);
945 * We don't allow identifier in the target
947 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
950 if (identifierSB
.length() > 0) {
951 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
952 + ") not expected in the typealias target"); //$NON-NLS-1$
955 return targetDeclaration
;
959 * Parses the alias part of a typealias. It parses the underlying specifier
960 * list and declarator and creates the string representation that will be
961 * used to register the type.
964 * A TYPEALIAS_ALIAS node.
965 * @return The string representation of the alias.
966 * @throws ParseException
968 private static String
parseTypealiasAlias(CommonTree alias
)
969 throws ParseException
{
971 List
<CommonTree
> children
= alias
.getChildren();
973 CommonTree typeSpecifierList
= null;
974 CommonTree typeDeclaratorList
= null;
975 CommonTree typeDeclarator
= null;
976 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
978 for (CommonTree child
: children
) {
979 switch (child
.getType()) {
980 case CTFParser
.TYPE_SPECIFIER_LIST
:
981 typeSpecifierList
= child
;
983 case CTFParser
.TYPE_DECLARATOR_LIST
:
984 typeDeclaratorList
= child
;
987 childTypeError(child
);
992 /* If there is a type declarator list, extract the pointers */
993 if (typeDeclaratorList
!= null) {
995 * Only allow one declarator
997 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
999 if (typeDeclaratorList
.getChildCount() != 1) {
1000 throw new ParseException(
1001 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1004 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1006 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
1008 for (CommonTree child
: typeDeclaratorChildren
) {
1009 switch (child
.getType()) {
1010 case CTFParser
.POINTER
:
1011 pointers
.add(child
);
1013 case CTFParser
.IDENTIFIER
:
1014 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1015 + ") not expected in the typealias target"); //$NON-NLS-1$
1018 childTypeError(child
);
1024 return createTypeDeclarationString(typeSpecifierList
, pointers
);
1028 * Parses a typedef node. This creates and registers a new declaration for
1029 * each declarator found in the typedef.
1033 * @throws ParseException
1034 * If there is an error creating the declaration.
1036 private void parseTypedef(CommonTree typedef
) throws ParseException
{
1038 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1040 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1042 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1044 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1045 StringBuilder identifierSB
= new StringBuilder();
1047 IDeclaration type_declaration
= parseTypeDeclarator(
1048 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1050 if (type_declaration
instanceof VariantDeclaration
) {
1051 if (((VariantDeclaration
) type_declaration
).isTagged()) {
1052 throw new ParseException(
1053 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1057 getCurrentScope().registerType(identifierSB
.toString(),
1063 * Parses a pair type declarator / type specifier list and returns the
1064 * corresponding declaration. If it is present, it also writes the
1065 * identifier of the declarator in the given {@link StringBuilder}.
1067 * @param typeDeclarator
1068 * A TYPE_DECLARATOR node.
1069 * @param typeSpecifierList
1070 * A TYPE_SPECIFIER_LIST node.
1071 * @param identifierSB
1072 * A StringBuilder that will receive the identifier found in the
1074 * @return The corresponding declaration.
1075 * @throws ParseException
1076 * If there is an error finding or creating the declaration.
1078 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1079 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1080 throws ParseException
{
1082 IDeclaration declaration
= null;
1083 List
<CommonTree
> children
= null;
1084 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1085 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1086 CommonTree identifier
= null;
1088 /* Separate the tokens by type */
1089 if (typeDeclarator
!= null) {
1090 children
= typeDeclarator
.getChildren();
1091 for (CommonTree child
: children
) {
1093 switch (child
.getType()) {
1094 case CTFParser
.POINTER
:
1095 pointers
.add(child
);
1097 case CTFParser
.IDENTIFIER
:
1100 case CTFParser
.LENGTH
:
1104 childTypeError(child
);
1112 * Parse the type specifier list, which is the "base" type. For example,
1113 * it would be int in int a[3][len].
1115 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1118 * Each length subscript means that we must create a nested array or
1119 * sequence. For example, int a[3][len] means that we have an array of 3
1120 * (sequences of length 'len' of (int)).
1122 if (lengths
.size() > 0) {
1123 /* We begin at the end */
1124 Collections
.reverse(lengths
);
1126 for (CommonTree length
: lengths
) {
1128 * By looking at the first expression, we can determine whether
1129 * it is an array or a sequence.
1131 List
<CommonTree
> lengthChildren
= length
.getChildren();
1133 CommonTree first
= lengthChildren
.get(0);
1134 if (isUnaryInteger(first
)) {
1136 int arrayLength
= (int) parseUnaryInteger(first
);
1138 if (arrayLength
< 1) {
1139 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1142 /* Create the array declaration. */
1143 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1144 } else if (isUnaryString(first
)) {
1146 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1148 /* Create the sequence declaration. */
1149 declaration
= new SequenceDeclaration(lengthName
,
1152 childTypeError(first
);
1157 if (identifier
!= null) {
1158 identifierSB
.append(identifier
.getText());
1165 * Parses a type specifier list and returns the corresponding declaration.
1167 * @param typeSpecifierList
1168 * A TYPE_SPECIFIER_LIST node.
1169 * @param pointerList
1170 * A list of POINTER nodes that apply to the specified type.
1171 * @return The corresponding declaration.
1172 * @throws ParseException
1173 * If the type has not been defined or if there is an error
1174 * creating the declaration.
1176 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1177 List
<CommonTree
> pointerList
) throws ParseException
{
1178 IDeclaration declaration
= null;
1181 * By looking at the first element of the type specifier list, we can
1182 * determine which type it belongs to.
1184 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1186 switch (firstChild
.getType()) {
1187 case CTFParser
.FLOATING_POINT
:
1188 declaration
= parseFloat(firstChild
);
1190 case CTFParser
.INTEGER
:
1191 declaration
= parseInteger(firstChild
);
1193 case CTFParser
.STRING
:
1194 declaration
= parseString(firstChild
);
1196 case CTFParser
.STRUCT
:
1197 declaration
= parseStruct(firstChild
);
1199 case CTFParser
.VARIANT
:
1200 declaration
= parseVariant(firstChild
);
1202 case CTFParser
.ENUM
:
1203 declaration
= parseEnum(firstChild
);
1205 case CTFParser
.IDENTIFIER
:
1206 case CTFParser
.FLOATTOK
:
1207 case CTFParser
.INTTOK
:
1208 case CTFParser
.LONGTOK
:
1209 case CTFParser
.SHORTTOK
:
1210 case CTFParser
.SIGNEDTOK
:
1211 case CTFParser
.UNSIGNEDTOK
:
1212 case CTFParser
.CHARTOK
:
1213 case CTFParser
.DOUBLETOK
:
1214 case CTFParser
.VOIDTOK
:
1215 case CTFParser
.BOOLTOK
:
1216 case CTFParser
.COMPLEXTOK
:
1217 case CTFParser
.IMAGINARYTOK
:
1218 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1221 childTypeError(firstChild
);
1227 private IDeclaration
parseFloat(CommonTree floatingPoint
)
1228 throws ParseException
{
1230 List
<CommonTree
> children
= floatingPoint
.getChildren();
1233 * If the integer has no attributes, then it is missing the size
1234 * attribute which is required
1236 if (children
== null) {
1237 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1240 /* The return value */
1241 FloatDeclaration floatDeclaration
= null;
1242 ByteOrder byteOrder
= trace
.getByteOrder();
1247 /* Iterate on all integer children */
1248 for (CommonTree child
: children
) {
1249 switch (child
.getType()) {
1250 case CTFParser
.CTF_EXPRESSION_VAL
:
1252 * An assignment expression must have 2 children, left and right
1255 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1256 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1258 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1260 if (!isUnaryString(leftStrings
.get(0))) {
1261 throw new ParseException(
1262 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1264 String left
= concatenateUnaryStrings(leftStrings
);
1266 if (left
.equals(CTFStrings
.EXP_DIG
)) {
1267 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1268 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1269 byteOrder
= getByteOrder(rightNode
);
1270 } else if (left
.equals(CTFStrings
.MANT_DIG
)) {
1271 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1272 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1273 alignment
= getAlignment(rightNode
);
1275 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1280 childTypeError(child
);
1284 int size
= mantissa
+ exponent
;
1286 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1289 if (alignment
== 0) {
1290 if ((size
% 8) == 0) {
1297 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1299 return floatDeclaration
;
1304 * Parses a type specifier list as a user-declared type.
1306 * @param typeSpecifierList
1307 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1308 * @param pointerList
1309 * A list of POINTER nodes that apply to the type specified in
1310 * typeSpecifierList.
1311 * @return The corresponding declaration.
1312 * @throws ParseException
1313 * If the type does not exist (has not been found).
1315 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1316 List
<CommonTree
> pointerList
) throws ParseException
{
1317 /* Create the string representation of the type declaration */
1318 String typeStringRepresentation
= createTypeDeclarationString(
1319 typeSpecifierList
, pointerList
);
1321 /* Use the string representation to search the type in the current scope */
1322 IDeclaration decl
= getCurrentScope().rlookupType(
1323 typeStringRepresentation
);
1326 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1327 + " has not been defined."); //$NON-NLS-1$
1334 * Parses an integer declaration node.
1338 * @return The corresponding integer declaration.
1339 * @throws ParseException
1341 private IntegerDeclaration
parseInteger(CommonTree integer
)
1342 throws ParseException
{
1344 List
<CommonTree
> children
= integer
.getChildren();
1347 * If the integer has no attributes, then it is missing the size
1348 * attribute which is required
1350 if (children
== null) {
1351 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1354 /* The return value */
1355 IntegerDeclaration integerDeclaration
= null;
1356 boolean signed
= false;
1357 ByteOrder byteOrder
= trace
.getByteOrder();
1361 String clock
= null;
1363 Encoding encoding
= Encoding
.NONE
;
1365 /* Iterate on all integer children */
1366 for (CommonTree child
: children
) {
1367 switch (child
.getType()) {
1368 case CTFParser
.CTF_EXPRESSION_VAL
:
1370 * An assignment expression must have 2 children, left and right
1373 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1374 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1376 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1378 if (!isUnaryString(leftStrings
.get(0))) {
1379 throw new ParseException(
1380 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1382 String left
= concatenateUnaryStrings(leftStrings
);
1384 if (left
.equals("signed")) { //$NON-NLS-1$
1385 signed
= getSigned(rightNode
);
1386 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1387 byteOrder
= getByteOrder(rightNode
);
1388 } else if (left
.equals("size")) { //$NON-NLS-1$
1389 size
= getSize(rightNode
);
1390 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1391 alignment
= getAlignment(rightNode
);
1392 } else if (left
.equals("base")) { //$NON-NLS-1$
1393 base
= getBase(rightNode
);
1394 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1395 encoding
= getEncoding(rightNode
);
1396 } else if (left
.equals("map")) { //$NON-NLS-1$
1397 clock
= getClock(rightNode
);
1399 throw new ParseException(
1400 "Integer: unknown attribute " + left
); //$NON-NLS-1$
1405 childTypeError(child
);
1411 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1414 if (alignment
== 0) {
1415 if ((size
% 8) == 0) {
1422 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1423 byteOrder
, encoding
, clock
, alignment
);
1425 return integerDeclaration
;
1428 private static String
getClock(CommonTree rightNode
) {
1429 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1432 private static StringDeclaration
parseString(CommonTree string
)
1433 throws ParseException
{
1435 List
<CommonTree
> children
= string
.getChildren();
1436 StringDeclaration stringDeclaration
= null;
1438 if (children
== null) {
1439 stringDeclaration
= new StringDeclaration();
1441 Encoding encoding
= Encoding
.UTF8
;
1442 for (CommonTree child
: children
) {
1443 switch (child
.getType()) {
1444 case CTFParser
.CTF_EXPRESSION_VAL
:
1446 * An assignment expression must have 2 children, left and
1450 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1451 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1453 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1455 if (!isUnaryString(leftStrings
.get(0))) {
1456 throw new ParseException(
1457 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1459 String left
= concatenateUnaryStrings(leftStrings
);
1461 if (left
.equals("encoding")) { //$NON-NLS-1$
1462 encoding
= getEncoding(rightNode
);
1464 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1470 childTypeError(child
);
1475 stringDeclaration
= new StringDeclaration(encoding
);
1478 return stringDeclaration
;
1482 * Parses a struct declaration and returns the corresponding declaration.
1486 * @return The corresponding struct declaration.
1487 * @throws ParseException
1489 private StructDeclaration
parseStruct(CommonTree struct
)
1490 throws ParseException
{
1492 List
<CommonTree
> children
= struct
.getChildren();
1494 /* The return value */
1495 StructDeclaration structDeclaration
= null;
1498 String structName
= null;
1499 boolean hasName
= false;
1502 CommonTree structBody
= null;
1503 boolean hasBody
= false;
1506 long structAlign
= 0;
1508 /* Loop on all children and identify what we have to work with. */
1509 for (CommonTree child
: children
) {
1510 switch (child
.getType()) {
1511 case CTFParser
.STRUCT_NAME
: {
1514 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1516 structName
= structNameIdentifier
.getText();
1520 case CTFParser
.STRUCT_BODY
: {
1527 case CTFParser
.ALIGN
: {
1528 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1530 structAlign
= getAlignment(structAlignExpression
);
1535 childTypeError(child
);
1542 * If a struct has just a body and no name (just like the song,
1543 * "A Struct With No Name" by America (sorry for that...)), it's a
1544 * definition of a new type, so we create the type declaration and
1545 * return it. We can't add it to the declaration scope since there is no
1546 * name, but that's what we want because it won't be possible to use it
1547 * again to declare another field.
1549 * If it has just a name, we look it up in the declaration scope and
1550 * return the associated declaration. If it is not found in the
1551 * declaration scope, it means that a struct with that name has not been
1552 * declared, which is an error.
1554 * If it has both, then we create the type declaration and register it
1555 * to the current scope.
1557 * If it has none, then what are we doing here ?
1561 * If struct has a name, check if already defined in the current
1564 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1565 throw new ParseException("struct " + structName
//$NON-NLS-1$
1566 + " already defined."); //$NON-NLS-1$
1568 /* Create the declaration */
1569 structDeclaration
= new StructDeclaration(structAlign
);
1571 /* Parse the body */
1572 parseStructBody(structBody
, structDeclaration
);
1574 /* If struct has name, add it to the current scope. */
1576 getCurrentScope().registerStruct(structName
, structDeclaration
);
1578 } else /* !hasBody */{
1580 /* Name and !body */
1582 /* Lookup the name in the current scope. */
1583 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1586 * If not found, it means that a struct with such name has not
1589 if (structDeclaration
== null) {
1590 throw new ParseException("struct " + structName
//$NON-NLS-1$
1591 + " is not defined"); //$NON-NLS-1$
1594 /* !Name and !body */
1596 /* We can't do anything with that. */
1597 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1601 return structDeclaration
;
1605 * Parses a struct body, adding the fields to specified structure
1609 * A STRUCT_BODY node.
1610 * @param structDeclaration
1611 * The struct declaration.
1612 * @throws ParseException
1614 private void parseStructBody(CommonTree structBody
,
1615 StructDeclaration structDeclaration
) throws ParseException
{
1617 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1620 * If structDeclaration is null, structBody has no children and the
1621 * struct body is empty.
1623 if (structDeclarations
!= null) {
1626 for (CommonTree declarationNode
: structDeclarations
) {
1627 switch (declarationNode
.getType()) {
1628 case CTFParser
.TYPEALIAS
:
1629 parseTypealias(declarationNode
);
1631 case CTFParser
.TYPEDEF
:
1632 parseTypedef(declarationNode
);
1634 case CTFParser
.SV_DECLARATION
:
1635 parseStructDeclaration(declarationNode
, structDeclaration
);
1638 childTypeError(declarationNode
);
1647 * Parses a declaration found in a struct.
1649 * @param declaration
1650 * A SV_DECLARATION node.
1652 * A struct declaration. (I know, little name clash here...)
1653 * @throws ParseException
1655 private void parseStructDeclaration(CommonTree declaration
,
1656 StructDeclaration struct
) throws ParseException
{
1659 /* Get the type specifier list node */
1660 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1662 /* Get the type declarator list node */
1663 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1665 /* Get the type declarator list */
1666 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1669 * For each type declarator, parse the declaration and add a field to
1672 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1674 StringBuilder identifierSB
= new StringBuilder();
1676 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1677 typeSpecifierListNode
, identifierSB
);
1678 String fieldName
= identifierSB
.toString();
1680 if (struct
.hasField(fieldName
)) {
1681 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1685 struct
.addField(fieldName
, decl
);
1691 * Parses an enum declaration and returns the corresponding declaration.
1695 * @return The corresponding enum declaration.
1696 * @throws ParseException
1698 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1700 List
<CommonTree
> children
= _enum
.getChildren();
1702 /* The return value */
1703 EnumDeclaration enumDeclaration
= null;
1706 String enumName
= null;
1709 CommonTree enumBody
= null;
1711 /* Container type */
1712 IntegerDeclaration containerTypeDeclaration
= null;
1714 /* Loop on all children and identify what we have to work with. */
1715 for (CommonTree child
: children
) {
1716 switch (child
.getType()) {
1717 case CTFParser
.ENUM_NAME
: {
1718 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1720 enumName
= enumNameIdentifier
.getText();
1724 case CTFParser
.ENUM_BODY
: {
1730 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1732 containerTypeDeclaration
= parseEnumContainerType(child
);
1737 childTypeError(child
);
1743 * If the container type has not been defined explicitly, we assume it
1746 if (containerTypeDeclaration
== null) {
1747 IDeclaration enumDecl
;
1749 * it could be because the enum was already declared.
1751 if (enumName
!= null) {
1752 enumDecl
= getCurrentScope().rlookupEnum(enumName
);
1753 if (enumDecl
!= null) {
1754 return (EnumDeclaration
) enumDecl
;
1758 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1761 throw new ParseException(
1762 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1763 } else if (!(decl
instanceof IntegerDeclaration
)) {
1764 throw new ParseException(
1765 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1768 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1772 * If it has a body, it's a new declaration, otherwise it's a reference
1773 * to an existing declaration. Same logic as struct.
1775 if (enumBody
!= null) {
1777 * If enum has a name, check if already defined in the current
1780 if ((enumName
!= null)
1781 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1782 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1783 + " already defined"); //$NON-NLS-1$
1786 /* Create the declaration */
1787 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1789 /* Parse the body */
1790 parseEnumBody(enumBody
, enumDeclaration
);
1792 /* If the enum has name, add it to the current scope. */
1793 if (enumName
!= null) {
1794 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1797 if (enumName
!= null) {
1798 /* Name and !body */
1800 /* Lookup the name in the current scope. */
1801 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1804 * If not found, it means that an enum with such name has not
1807 if (enumDeclaration
== null) {
1808 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1809 + " is not defined"); //$NON-NLS-1$
1812 /* !Name and !body */
1813 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1817 return enumDeclaration
;
1822 * Parses an enum body, adding the enumerators to the specified enum
1826 * An ENUM_BODY node.
1827 * @param enumDeclaration
1828 * The enum declaration.
1829 * @throws ParseException
1831 private void parseEnumBody(CommonTree enumBody
,
1832 EnumDeclaration enumDeclaration
) throws ParseException
{
1834 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1835 /* enum body can't be empty (unlike struct). */
1840 * Start at -1, so that if the first enumrator has no explicit value, it
1845 for (CommonTree enumerator
: enumerators
) {
1846 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1855 * Parses an enumerator node and adds an enumerator declaration to an
1856 * enumeration declaration.
1858 * The high value of the range of the last enumerator is needed in case the
1859 * current enumerator does not specify its value.
1862 * An ENUM_ENUMERATOR node.
1863 * @param enumDeclaration
1864 * en enumeration declaration to which will be added the
1867 * The high value of the range of the last enumerator
1868 * @return The high value of the value range of the current enumerator.
1869 * @throws ParseException
1871 private static long parseEnumEnumerator(CommonTree enumerator
,
1872 EnumDeclaration enumDeclaration
, long lastHigh
)
1873 throws ParseException
{
1875 List
<CommonTree
> children
= enumerator
.getChildren();
1877 long low
= 0, high
= 0;
1878 boolean valueSpecified
= false;
1879 String label
= null;
1881 for (CommonTree child
: children
) {
1882 if (isUnaryString(child
)) {
1883 label
= parseUnaryString(child
);
1884 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1886 valueSpecified
= true;
1888 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1890 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1892 valueSpecified
= true;
1894 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1895 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1897 childTypeError(child
);
1901 if (!valueSpecified
) {
1907 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1910 if (!enumDeclaration
.add(low
, high
, label
)) {
1911 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1918 * Parses an enum container type node and returns the corresponding integer
1921 * @param enumContainerType
1922 * An ENUM_CONTAINER_TYPE node.
1923 * @return An integer declaration corresponding to the container type.
1924 * @throws ParseException
1925 * If the type does not parse correctly or if it is not an
1928 private IntegerDeclaration
parseEnumContainerType(
1929 CommonTree enumContainerType
) throws ParseException
{
1931 /* Get the child, which should be a type specifier list */
1932 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
.getChild(0);
1934 /* Parse it and get the corresponding declaration */
1935 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1937 /* If is is an integer, return it, else throw an error */
1938 if (decl
instanceof IntegerDeclaration
) {
1939 return (IntegerDeclaration
) decl
;
1941 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1944 private VariantDeclaration
parseVariant(CommonTree variant
)
1945 throws ParseException
{
1947 List
<CommonTree
> children
= variant
.getChildren();
1948 VariantDeclaration variantDeclaration
= null;
1950 boolean hasName
= false;
1951 String variantName
= null;
1953 boolean hasBody
= false;
1954 CommonTree variantBody
= null;
1956 boolean hasTag
= false;
1957 String variantTag
= null;
1959 for (CommonTree child
: children
) {
1960 switch (child
.getType()) {
1961 case CTFParser
.VARIANT_NAME
:
1965 CommonTree variantNameIdentifier
= (CommonTree
) child
.getChild(0);
1967 variantName
= variantNameIdentifier
.getText();
1970 case CTFParser
.VARIANT_TAG
:
1974 CommonTree variantTagIdentifier
= (CommonTree
) child
.getChild(0);
1976 variantTag
= variantTagIdentifier
.getText();
1979 case CTFParser
.VARIANT_BODY
:
1983 variantBody
= child
;
1987 childTypeError(child
);
1994 * If variant has a name, check if already defined in the current
1998 && (getCurrentScope().lookupVariant(variantName
) != null)) {
1999 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2000 + " already defined."); //$NON-NLS-1$
2003 /* Create the declaration */
2004 variantDeclaration
= new VariantDeclaration();
2006 /* Parse the body */
2007 parseVariantBody(variantBody
, variantDeclaration
);
2009 /* If variant has name, add it to the current scope. */
2011 getCurrentScope().registerVariant(variantName
,
2012 variantDeclaration
);
2014 } else /* !hasBody */{
2016 /* Name and !body */
2018 /* Lookup the name in the current scope. */
2019 variantDeclaration
= getCurrentScope().rlookupVariant(
2023 * If not found, it means that a struct with such name has not
2026 if (variantDeclaration
== null) {
2027 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2028 + " is not defined"); //$NON-NLS-1$
2031 /* !Name and !body */
2033 /* We can't do anything with that. */
2034 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2039 variantDeclaration
.setTag(variantTag
);
2042 return variantDeclaration
;
2045 private void parseVariantBody(CommonTree variantBody
,
2046 VariantDeclaration variantDeclaration
) throws ParseException
{
2048 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2052 for (CommonTree declarationNode
: variantDeclarations
) {
2053 switch (declarationNode
.getType()) {
2054 case CTFParser
.TYPEALIAS
:
2055 parseTypealias(declarationNode
);
2057 case CTFParser
.TYPEDEF
:
2058 parseTypedef(declarationNode
);
2060 case CTFParser
.SV_DECLARATION
:
2061 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2064 childTypeError(declarationNode
);
2072 private void parseVariantDeclaration(CommonTree declaration
,
2073 VariantDeclaration variant
) throws ParseException
{
2076 /* Get the type specifier list node */
2077 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2079 /* Get the type declarator list node */
2080 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2082 /* Get the type declarator list */
2083 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
2086 * For each type declarator, parse the declaration and add a field to
2089 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2091 StringBuilder identifierSB
= new StringBuilder();
2093 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2094 typeSpecifierListNode
, identifierSB
);
2096 if (variant
.hasField(identifierSB
.toString())) {
2097 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2098 + identifierSB
.toString());
2101 variant
.addField(identifierSB
.toString(), decl
);
2106 * Creates the string representation of a type declaration (type specifier
2109 * @param typeSpecifierList
2110 * A TYPE_SPECIFIER_LIST node.
2112 * A list of POINTER nodes.
2113 * @return The string representation.
2114 * @throws ParseException
2116 private static String
createTypeDeclarationString(
2117 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2118 throws ParseException
{
2119 StringBuilder sb
= new StringBuilder();
2121 createTypeSpecifierListString(typeSpecifierList
, sb
);
2122 createPointerListString(pointers
, sb
);
2124 return sb
.toString();
2128 * Creates the string representation of a list of type specifiers.
2130 * @param typeSpecifierList
2131 * A TYPE_SPECIFIER_LIST node.
2133 * A StringBuilder to which will be appended the string.
2134 * @throws ParseException
2136 private static void createTypeSpecifierListString(
2137 CommonTree typeSpecifierList
, StringBuilder sb
)
2138 throws ParseException
{
2140 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2142 boolean firstItem
= true;
2144 for (CommonTree child
: children
) {
2152 /* Append the string that represents this type specifier. */
2153 createTypeSpecifierString(child
, sb
);
2158 * Creates the string representation of a type specifier.
2160 * @param typeSpecifier
2161 * A TYPE_SPECIFIER node.
2163 * A StringBuilder to which will be appended the string.
2164 * @throws ParseException
2166 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2167 StringBuilder sb
) throws ParseException
{
2168 switch (typeSpecifier
.getType()) {
2169 case CTFParser
.FLOATTOK
:
2170 case CTFParser
.INTTOK
:
2171 case CTFParser
.LONGTOK
:
2172 case CTFParser
.SHORTTOK
:
2173 case CTFParser
.SIGNEDTOK
:
2174 case CTFParser
.UNSIGNEDTOK
:
2175 case CTFParser
.CHARTOK
:
2176 case CTFParser
.DOUBLETOK
:
2177 case CTFParser
.VOIDTOK
:
2178 case CTFParser
.BOOLTOK
:
2179 case CTFParser
.COMPLEXTOK
:
2180 case CTFParser
.IMAGINARYTOK
:
2181 case CTFParser
.CONSTTOK
:
2182 case CTFParser
.IDENTIFIER
:
2183 sb
.append(typeSpecifier
.getText());
2185 case CTFParser
.STRUCT
: {
2186 CommonTree structName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2187 if (structName
== null) {
2188 throw new ParseException(
2189 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2192 CommonTree structNameIdentifier
= (CommonTree
) structName
.getChild(0);
2194 sb
.append(structNameIdentifier
.getText());
2197 case CTFParser
.VARIANT
: {
2198 CommonTree variantName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2199 if (variantName
== null) {
2200 throw new ParseException(
2201 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2204 CommonTree variantNameIdentifier
= (CommonTree
) variantName
.getChild(0);
2206 sb
.append(variantNameIdentifier
.getText());
2209 case CTFParser
.ENUM
: {
2210 CommonTree enumName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.ENUM_NAME
);
2211 if (enumName
== null) {
2212 throw new ParseException(
2213 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2216 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2218 sb
.append(enumNameIdentifier
.getText());
2221 case CTFParser
.FLOATING_POINT
:
2222 case CTFParser
.INTEGER
:
2223 case CTFParser
.STRING
:
2224 throw new ParseException(
2225 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2228 childTypeError(typeSpecifier
);
2234 * Creates the string representation of a list of pointers.
2236 * @param pointerList
2237 * A list of pointer nodes. If pointerList is null, this function
2240 * A stringbuilder to which will be appended the string.
2242 private static void createPointerListString(List
<CommonTree
> pointerList
,
2244 if (pointerList
== null) {
2248 for (CommonTree pointer
: pointerList
) {
2250 sb
.append(" *"); //$NON-NLS-1$
2251 if (pointer
.getChildCount() > 0) {
2253 sb
.append(" const"); //$NON-NLS-1$
2260 * The node to check.
2261 * @return True if the given node is an unary string.
2263 private static boolean isUnaryString(CommonTree node
) {
2264 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) ||
2265 (node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2270 * The node to check.
2271 * @return True if the given node is an unary integer.
2273 private static boolean isUnaryInteger(CommonTree node
) {
2274 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) ||
2275 (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) ||
2276 (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2280 * Parses a unary string node and return the string value.
2282 * @param unaryString
2283 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2284 * or UNARY_EXPRESSION_STRING_QUOTES).
2285 * @return The string value.
2288 * It would be really nice to remove the quotes earlier, such as in the
2291 private static String
parseUnaryString(CommonTree unaryString
) {
2293 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2294 String strval
= value
.getText();
2297 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2298 strval
= strval
.substring(1, strval
.length() - 1);
2305 * Parses an unary integer (dec, hex or oct).
2307 * @param unaryInteger
2308 * An unary integer node.
2309 * @return The integer value.
2311 private static long parseUnaryInteger(CommonTree unaryInteger
) {
2313 List
<CommonTree
> children
= unaryInteger
.getChildren();
2314 CommonTree value
= children
.get(0);
2315 String strval
= value
.getText();
2319 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2320 intval
= Long
.parseLong(strval
, 10);
2321 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2322 intval
= Long
.parseLong(strval
, 0x10);
2323 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2324 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2327 /* The rest of children are sign */
2328 if ((children
.size() % 2) == 0) {
2334 private static long getMajorOrMinor(CommonTree rightNode
)
2335 throws ParseException
{
2337 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2339 if (isUnaryInteger(firstChild
)) {
2340 if (rightNode
.getChildCount() > 1) {
2341 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2344 long m
= parseUnaryInteger(firstChild
);
2347 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2352 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2355 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2357 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2359 if (isUnaryString(firstChild
)) {
2360 if (rightNode
.getChildCount() > 1) {
2361 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2364 String uuidstr
= parseUnaryString(firstChild
);
2367 UUID uuid
= UUID
.fromString(uuidstr
);
2369 } catch (IllegalArgumentException e
) {
2370 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2373 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2377 * Gets the value of a "signed" integer attribute.
2381 * @return The "signed" value as a boolean.
2382 * @throws ParseException
2384 private static boolean getSigned(CommonTree rightNode
)
2385 throws ParseException
{
2387 boolean ret
= false;
2388 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2390 if (isUnaryString(firstChild
)) {
2391 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2393 if (strval
.equals(CTFStrings
.TRUE
)
2394 || strval
.equals(CTFStrings
.TRUE2
)) {
2396 } else if (strval
.equals(CTFStrings
.FALSE
)
2397 || strval
.equals(CTFStrings
.FALSE2
)) {
2400 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2401 + firstChild
.getChild(0).getText());
2403 } else if (isUnaryInteger(firstChild
)) {
2404 /* Happens if the value is something like "1234.hello" */
2405 if (rightNode
.getChildCount() > 1) {
2406 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2409 long intval
= parseUnaryInteger(firstChild
);
2413 } else if (intval
== 0) {
2416 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2417 + firstChild
.getChild(0).getText());
2420 throw new ParseException();
2427 * Gets the value of a "byte_order" integer attribute.
2431 * @return The "byte_order" value.
2432 * @throws ParseException
2434 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2436 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2438 if (isUnaryString(firstChild
)) {
2439 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2441 if (strval
.equals(CTFStrings
.LE
)) {
2442 return ByteOrder
.LITTLE_ENDIAN
;
2443 } else if (strval
.equals(CTFStrings
.BE
)
2444 || strval
.equals(CTFStrings
.NETWORK
)) {
2445 return ByteOrder
.BIG_ENDIAN
;
2446 } else if (strval
.equals(CTFStrings
.NATIVE
)) {
2447 return trace
.getByteOrder();
2449 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2452 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2456 * Determines if the given value is a valid alignment value.
2459 * The value to check.
2460 * @return True if it is valid.
2462 private static boolean isValidAlignment(long alignment
) {
2463 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2467 * Gets the value of a "size" integer attribute.
2471 * @return The "size" value.
2472 * @throws ParseException
2474 private static long getSize(CommonTree rightNode
) throws ParseException
{
2476 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2478 if (isUnaryInteger(firstChild
)) {
2479 if (rightNode
.getChildCount() > 1) {
2480 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2483 long size
= parseUnaryInteger(firstChild
);
2486 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2491 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2495 * Gets the value of a "align" integer or struct attribute.
2498 * A CTF_RIGHT node or directly an unary integer.
2499 * @return The align value.
2500 * @throws ParseException
2502 private static long getAlignment(CommonTree node
) throws ParseException
{
2505 * If a CTF_RIGHT node was passed, call getAlignment with the first
2508 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2509 if (node
.getChildCount() > 1) {
2510 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2513 return getAlignment((CommonTree
) node
.getChild(0));
2514 } else if (isUnaryInteger(node
)) {
2515 long alignment
= parseUnaryInteger(node
);
2517 if (!isValidAlignment(alignment
)) {
2518 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2524 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2528 * Gets the value of a "base" integer attribute.
2531 * An CTF_RIGHT node.
2532 * @return The "base" value.
2533 * @throws ParseException
2535 private static int getBase(CommonTree rightNode
) throws ParseException
{
2537 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2539 if (isUnaryInteger(firstChild
)) {
2540 if (rightNode
.getChildCount() > 1) {
2541 throw new ParseException("invalid base value"); //$NON-NLS-1$
2544 long intval
= parseUnaryInteger(firstChild
);
2545 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2546 || (intval
== 16)) {
2547 return (int) intval
;
2549 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2550 } else if (isUnaryString(firstChild
)) {
2551 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2553 if (strval
.equals(CTFStrings
.DECIMAL
)
2554 || strval
.equals(CTFStrings
.DEC
)
2555 || strval
.equals(CTFStrings
.DEC_CTE
)
2556 || strval
.equals(CTFStrings
.INT_MOD
)
2557 || strval
.equals(CTFStrings
.UNSIGNED_CTE
)) {
2559 } else if (strval
.equals(CTFStrings
.HEXADECIMAL
)
2560 || strval
.equals(CTFStrings
.HEX
)
2561 || strval
.equals(CTFStrings
.X
)
2562 || strval
.equals(CTFStrings
.X2
)
2563 || strval
.equals(CTFStrings
.POINTER
)) {
2565 } else if (strval
.equals(CTFStrings
.OCTAL
)
2566 || strval
.equals(CTFStrings
.OCT
)
2567 || strval
.equals(CTFStrings
.OCTAL_CTE
)) {
2569 } else if (strval
.equals(CTFStrings
.BINARY
)
2570 || strval
.equals(CTFStrings
.BIN
)) {
2573 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2576 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2581 * Gets the value of an "encoding" integer attribute.
2585 * @return The "encoding" value.
2586 * @throws ParseException
2588 private static Encoding
getEncoding(CommonTree rightNode
)
2589 throws ParseException
{
2591 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2593 if (isUnaryString(firstChild
)) {
2594 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2596 if (strval
.equals(CTFStrings
.UTF8
)) {
2597 return Encoding
.UTF8
;
2598 } else if (strval
.equals(CTFStrings
.ASCII
)) {
2599 return Encoding
.ASCII
;
2600 } else if (strval
.equals(CTFStrings
.NONE
)) {
2601 return Encoding
.NONE
;
2603 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2606 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2609 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2611 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2613 if (isUnaryInteger(firstChild
)) {
2614 if (rightNode
.getChildCount() > 1) {
2615 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2618 long intval
= parseUnaryInteger(firstChild
);
2622 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2625 private static String
getEventName(CommonTree rightNode
)
2626 throws ParseException
{
2628 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2630 if (isUnaryString(firstChild
)) {
2631 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2635 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2638 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2640 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2642 if (isUnaryInteger(firstChild
)) {
2643 if (rightNode
.getChildCount() > 1) {
2644 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2647 long intval
= parseUnaryInteger(firstChild
);
2651 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2655 * Concatenates a list of unary strings separated by arrows (->) or dots.
2658 * A list, first element being an unary string, subsequent
2659 * elements being ARROW or DOT nodes with unary strings as child.
2660 * @return The string representation of the unary string chain.
2662 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2664 StringBuilder sb
= new StringBuilder();
2666 CommonTree first
= strings
.get(0);
2667 sb
.append(parseUnaryString(first
));
2669 boolean isFirst
= true;
2671 for (CommonTree ref
: strings
) {
2678 CommonTree id
= (CommonTree
) ref
.getChild(0);
2680 if (ref
.getType() == CTFParser
.ARROW
) {
2681 sb
.append("->"); //$NON-NLS-1$
2686 sb
.append(parseUnaryString(id
));
2689 return sb
.toString();
2693 * Throws a ParseException stating that the parent-child relation between
2694 * the given node and its parent is not valid. It means that the shape of
2695 * the AST is unexpected.
2698 * The invalid child node.
2699 * @throws ParseException
2701 private static void childTypeError(CommonTree child
) throws ParseException
{
2702 CommonTree parent
= (CommonTree
) child
.getParent();
2703 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2704 + " can't have a child of type " //$NON-NLS-1$
2705 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2707 throw new ParseException(error
);
2710 // ------------------------------------------------------------------------
2712 // ------------------------------------------------------------------------
2715 * Adds a new declaration scope on the top of the scope stack.
2717 private void pushScope() {
2718 scope
= new DeclarationScope(scope
);
2722 * Removes the top declaration scope from the scope stack.
2724 private void popScope() {
2725 scope
= scope
.getParentScope();
2729 * Returns the current declaration scope.
2731 * @return The current declaration scope.
2733 private DeclarationScope
getCurrentScope() {