1 /*******************************************************************************
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
9 * Contributors: Matthew Khouzam - Initial Design and Grammar
10 * Contributors: Francis Giraldeau - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
;
15 import java
.io
.FileNotFoundException
;
16 import java
.io
.IOException
;
17 import java
.io
.UnsupportedEncodingException
;
18 import java
.nio
.ByteOrder
;
19 import java
.util
.ArrayList
;
20 import java
.util
.Collections
;
21 import java
.util
.LinkedList
;
22 import java
.util
.List
;
23 import java
.util
.UUID
;
25 import org
.antlr
.runtime
.tree
.CommonTree
;
26 import org
.eclipse
.linuxtools
.ctf
.core
.event
.CTFClock
;
27 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDeclaration
;
28 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDeclaration
;
29 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Encoding
;
30 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDeclaration
;
31 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.FloatDeclaration
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDeclaration
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDeclaration
;
36 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
37 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
38 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
39 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
40 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
41 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.Stream
;
46 public class IOStructGen
{
48 // ------------------------------------------------------------------------
50 // ------------------------------------------------------------------------
52 static private final boolean DEBUG_
= false;
57 private final CTFTrace trace
;
58 private final CommonTree tree
;
61 * The current declaration scope.
63 private DeclarationScope scope
= null;
65 // ------------------------------------------------------------------------
67 // ------------------------------------------------------------------------
73 * the tree (ANTLR generated) with the parsed TSDL data.
75 * the trace containing the places to put all the read metadata
77 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
83 * Parse the tree and populate the trace defined in the constructor.
85 * @throws ParseException
86 * If there was a problem parsing the metadata
88 public void generate() throws ParseException
{
92 // ------------------------------------------------------------------------
94 // ------------------------------------------------------------------------
97 * Parse the root node.
101 * @throws ParseException
103 private void parseRoot(CommonTree root
) throws ParseException
{
105 List
<CommonTree
> children
= root
.getChildren();
106 java
.io
.FileOutputStream fos
= null;
107 java
.io
.OutputStreamWriter out
= null;
110 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
111 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
112 } catch (FileNotFoundException e
) {
115 } catch (UnsupportedEncodingException e
) {
121 CommonTree traceNode
= null;
122 List
<CommonTree
> streams
= new ArrayList
<CommonTree
>();
123 List
<CommonTree
> events
= new ArrayList
<CommonTree
>();
124 List
<CommonTree
> declarations
= new ArrayList
<CommonTree
>();
125 List
<CommonTree
> environments
= new ArrayList
<CommonTree
>();
126 List
<CommonTree
> clocks
= new ArrayList
<CommonTree
>();
127 List
<CommonTree
> callsites
= new ArrayList
<CommonTree
>();
128 /* Create a new declaration scope with no parent. */
132 for (CommonTree child
: children
) {
133 final int type
= child
.getType();
135 out
.write(child
.toString()
136 + " -> " + type
+ '\n'); //$NON-NLS-1$
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
);
161 case CTFParser
.CALLSITE
:
162 callsites
.add(child
);
165 childTypeError(child
);
169 out
.write("Declarations\n"); //$NON-NLS-1$
171 for (CommonTree decl
: declarations
) {
173 out
.write(decl
.toString() + '\n');
175 parseRootDeclaration(decl
);
177 if (traceNode
== null) {
178 throw new ParseException("Missing trace block"); //$NON-NLS-1$
181 parseTrace(traceNode
);
184 out
.write("Environments\n"); //$NON-NLS-1$
186 for (CommonTree environment
: environments
) {
187 parseEnvironment(environment
);
190 out
.write("Clocks\n"); //$NON-NLS-1$
192 for (CommonTree clock
: clocks
) {
196 out
.write("Callsites\n"); //$NON-NLS-1$
198 for (CommonTree callsite
: callsites
) {
199 parseCallsite(callsite
);
203 out
.write("Streams\n"); //$NON-NLS-1$
205 if (streams
.size() > 0) {
206 for (CommonTree stream
: streams
) {
209 out
.write(stream
.toString() + '\n');
210 } catch (IOException e
) {
217 /* Add an empty stream that will have a null id */
218 trace
.addStream(new Stream(trace
));
222 out
.write("Events\n"); //$NON-NLS-1$
224 for (CommonTree event
: events
) {
227 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
228 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
229 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
237 } catch (IOException e
) {
243 private void parseCallsite(CommonTree callsite
) {
245 List
<CommonTree
> children
= callsite
.getChildren();
247 String func_name
= null;
248 long line_number
= -1;
250 String file_name
= null;
252 for (CommonTree child
: children
) {
254 /* this is a regex to find the leading and trailing quotes*/
255 final String regex
= "^\"|\"$"; //$NON-NLS-1$
256 /* this is to replace the previous quotes with nothing... effectively deleting them */
257 final String nullString
= ""; //$NON-NLS-1$
258 left
= child
.getChild(0).getChild(0).getChild(0).getText();
259 if (left
.equals("name")) { //$NON-NLS-1$
260 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
261 } else if (left
.equals("func")) { //$NON-NLS-1$
262 func_name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
263 } else if (left
.equals("ip")) { //$NON-NLS-1$
264 ip
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText().substring(2),16); // trim the 0x
265 } else if (left
.equals("file")) { //$NON-NLS-1$
266 file_name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
267 } else if (left
.equals("line")) { //$NON-NLS-1$
268 line_number
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
271 trace
.addCallsite(name
, func_name
, ip
,file_name
, line_number
);
274 private void parseEnvironment(CommonTree environment
) {
275 List
<CommonTree
> children
= environment
.getChildren();
276 for (CommonTree child
: children
) {
279 left
= child
.getChild(0).getChild(0).getChild(0).getText();
280 right
= child
.getChild(1).getChild(0).getChild(0).getText();
281 trace
.addEnvironmentVar(left
, right
);
285 private void parseClock(CommonTree clock
) {
286 List
<CommonTree
> children
= clock
.getChildren();
287 CTFClock ctfClock
= new CTFClock();
288 for (CommonTree child
: children
) {
289 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
290 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
291 final int type
= value
.getType();
293 case CTFParser
.INTEGER
:
294 case CTFParser
.DECIMAL_LITERAL
:
296 * Not a pretty hack, this is to make sure that there is no
297 * number overflow due to 63 bit integers. The offset should
298 * only really be an issue in the year 2262. the tracer in C/ASM
299 * can write an offset in an unsigned 64 bit long. In java, the
300 * last bit, being set to 1 will be read as a negative number,
301 * but since it is too big a positive it will throw an
302 * exception. this will happen in 2^63 ns from 1970. Therefore
303 * 293 years from 1970
307 numValue
= Long
.parseLong(value
.getText());
308 } catch (Exception e
) {
309 numValue
= 1330938566783103277L;
311 ctfClock
.addAttribute(key
, numValue
);
314 ctfClock
.addAttribute(key
, value
.getText());
318 String NameValue
= ctfClock
.getName();
319 trace
.addClock(NameValue
, ctfClock
);
322 private void parseTrace(CommonTree traceNode
) throws ParseException
{
324 List
<CommonTree
> children
= traceNode
.getChildren();
325 if (children
== null) {
326 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
331 for (CommonTree child
: children
) {
332 switch (child
.getType()) {
333 case CTFParser
.TYPEALIAS
:
334 parseTypealias(child
);
336 case CTFParser
.TYPEDEF
:
339 case CTFParser
.CTF_EXPRESSION_TYPE
:
340 case CTFParser
.CTF_EXPRESSION_VAL
:
341 parseTraceDeclaration(child
);
344 childTypeError(child
);
350 * If trace byte order was not specified and not using packet based
353 if (trace
.getByteOrder() == null) {
354 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
360 private void parseTraceDeclaration(CommonTree traceDecl
)
361 throws ParseException
{
363 /* There should be a left and right */
365 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
366 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
368 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
370 if (!isUnaryString(leftStrings
.get(0))) {
371 throw new ParseException(
372 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
375 String left
= concatenateUnaryStrings(leftStrings
);
377 if (left
.equals(CTFStrings
.MAJOR
)) {
378 if (trace
.majortIsSet()) {
379 throw new ParseException("major is already set"); //$NON-NLS-1$
382 trace
.setMajor(getMajorOrMinor(rightNode
));
383 } else if (left
.equals(CTFStrings
.MINOR
)) {
384 if (trace
.minorIsSet()) {
385 throw new ParseException("minor is already set"); //$NON-NLS-1$
388 trace
.setMinor(getMajorOrMinor(rightNode
));
389 } else if (left
.equals(CTFStrings
.UUID_STRING
)) {
390 UUID uuid
= getUUID(rightNode
);
393 * If uuid was already set by a metadata packet, compare it to see
396 if (trace
.UUIDIsSet()) {
397 if (trace
.getUUID().compareTo(uuid
) != 0) {
398 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
399 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
405 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
406 ByteOrder byteOrder
= getByteOrder(rightNode
);
409 * If byte order was already set by a metadata packet, compare it to
412 if (trace
.getByteOrder() != null) {
413 if (trace
.getByteOrder() != byteOrder
) {
414 throw new ParseException(
415 "Endianness mismatch. Magic number says " //$NON-NLS-1$
416 + trace
.getByteOrder()
417 + " but metadata says " + byteOrder
); //$NON-NLS-1$
420 trace
.setByteOrder(byteOrder
);
421 final DeclarationScope parentScope
= scope
.getParentScope();
422 String types
[] = parentScope
.getTypeNames();
424 for (String type
: types
) {
425 IDeclaration d
= parentScope
.lookupType(type
);
426 if (d
instanceof IntegerDeclaration
) {
427 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
428 } else if (d
instanceof StructDeclaration
) {
429 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
433 } else if (left
.equals(CTFStrings
.PACKET_HEADER
)) {
434 if (trace
.packetHeaderIsSet()) {
435 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
438 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
440 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
441 throw new ParseException(
442 "packet.header expects a type specifier"); //$NON-NLS-1$
445 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
446 typeSpecifier
, null);
448 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
449 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
452 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
454 throw new ParseException("Unknown trace attribute : " + left
); //$NON-NLS-1$
458 private static void addByteOrder(ByteOrder byteOrder
,
459 final DeclarationScope parentScope
, String name
,
460 IntegerDeclaration decl
) throws ParseException
{
462 if (decl
.getByteOrder() == null) {
463 IntegerDeclaration newI
;
464 newI
= new IntegerDeclaration(decl
.getLength(), decl
.isSigned(),
465 decl
.getBase(), byteOrder
, decl
.getEncoding(),
466 decl
.getClock(), decl
.getAlignment());
467 parentScope
.replaceType(name
, newI
);
471 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
472 ByteOrder byteOrder
) throws ParseException
{
474 for (String s
: sd
.getFieldsList()) {
475 IDeclaration d
= sd
.getFields().get(s
);
477 if (d
instanceof StructDeclaration
) {
478 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
480 } else if (d
instanceof VariantDeclaration
) {
481 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
483 } else if (d
instanceof IntegerDeclaration
) {
484 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
485 if (decl
.getByteOrder() == null) {
486 IntegerDeclaration newI
;
487 newI
= new IntegerDeclaration(decl
.getLength(),
488 decl
.isSigned(), decl
.getBase(), byteOrder
,
489 decl
.getEncoding(), decl
.getClock(),
490 decl
.getAlignment());
491 sd
.getFields().put(s
, newI
);
497 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
498 ByteOrder byteOrder
) throws ParseException
{
500 for (String s
: vd
.getFields().keySet()) {
501 IDeclaration d
= vd
.getFields().get(s
);
503 if (d
instanceof StructDeclaration
) {
504 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
506 } else if (d
instanceof IntegerDeclaration
) {
507 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
508 IntegerDeclaration newI
;
509 newI
= new IntegerDeclaration(decl
.getLength(),
510 decl
.isSigned(), decl
.getBase(), byteOrder
,
511 decl
.getEncoding(), decl
.getClock(),
512 decl
.getAlignment());
513 vd
.getFields().put(s
, newI
);
518 private void parseStream(CommonTree streamNode
) throws ParseException
{
520 Stream stream
= new Stream(trace
);
522 List
<CommonTree
> children
= streamNode
.getChildren();
523 if (children
== null) {
524 throw new ParseException("Empty stream block"); //$NON-NLS-1$
529 for (CommonTree child
: children
) {
530 switch (child
.getType()) {
531 case CTFParser
.TYPEALIAS
:
532 parseTypealias(child
);
534 case CTFParser
.TYPEDEF
:
537 case CTFParser
.CTF_EXPRESSION_TYPE
:
538 case CTFParser
.CTF_EXPRESSION_VAL
:
539 parseStreamDeclaration(child
, stream
);
542 childTypeError(child
);
547 if (stream
.isIdSet()) {
548 if (!trace
.packetHeaderIsSet()
549 || !trace
.getPacketHeader().hasField(CTFStrings
.STREAM_ID
)) {
550 throw new ParseException(
551 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
555 trace
.addStream(stream
);
560 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
561 throws ParseException
{
563 /* There should be a left and right */
565 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
566 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
568 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
570 if (!isUnaryString(leftStrings
.get(0))) {
571 throw new ParseException(
572 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
575 String left
= concatenateUnaryStrings(leftStrings
);
577 if (left
.equals(CTFStrings
.ID
)) {
578 if (stream
.isIdSet()) {
579 throw new ParseException("stream id already defined"); //$NON-NLS-1$
582 long streamID
= getStreamID(rightNode
);
584 stream
.setId(streamID
);
585 } else if (left
.equals(CTFStrings
.EVENT_HEADER
)) {
586 if (stream
.isEventHeaderSet()) {
587 throw new ParseException("event.header already defined"); //$NON-NLS-1$
590 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
592 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
593 throw new ParseException(
594 "event.header expects a type specifier"); //$NON-NLS-1$
597 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
598 typeSpecifier
, null);
600 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
601 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
604 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
605 } else if (left
.equals(CTFStrings
.EVENT_CONTEXT
)) {
606 if (stream
.isEventContextSet()) {
607 throw new ParseException("event.context already defined"); //$NON-NLS-1$
610 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
612 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
613 throw new ParseException(
614 "event.context expects a type specifier"); //$NON-NLS-1$
617 IDeclaration eventContextDecl
= parseTypeSpecifierList(
618 typeSpecifier
, null);
620 if (!(eventContextDecl
instanceof StructDeclaration
)) {
621 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
624 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
625 } else if (left
.equals(CTFStrings
.PACKET_CONTEXT
)) {
626 if (stream
.isPacketContextSet()) {
627 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
630 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
632 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
633 throw new ParseException(
634 "packet.context expects a type specifier"); //$NON-NLS-1$
637 IDeclaration packetContextDecl
= parseTypeSpecifierList(
638 typeSpecifier
, null);
640 if (!(packetContextDecl
instanceof StructDeclaration
)) {
641 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
644 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
646 throw new ParseException("Unknown stream attribute : " + left
); //$NON-NLS-1$
650 private void parseEvent(CommonTree eventNode
) throws ParseException
{
652 List
<CommonTree
> children
= eventNode
.getChildren();
653 if (children
== null) {
654 throw new ParseException("Empty event block"); //$NON-NLS-1$
657 EventDeclaration event
= new EventDeclaration();
661 for (CommonTree child
: children
) {
662 switch (child
.getType()) {
663 case CTFParser
.TYPEALIAS
:
664 parseTypealias(child
);
666 case CTFParser
.TYPEDEF
:
669 case CTFParser
.CTF_EXPRESSION_TYPE
:
670 case CTFParser
.CTF_EXPRESSION_VAL
:
671 parseEventDeclaration(child
, event
);
674 childTypeError(child
);
679 if (!event
.nameIsSet()) {
680 throw new ParseException("Event name not set"); //$NON-NLS-1$
684 * If the event did not specify a stream, then the trace must be single
687 if (!event
.streamIsSet()) {
688 if (trace
.nbStreams() > 1) {
689 throw new ParseException(
690 "Event without stream_id with more than one stream"); //$NON-NLS-1$
694 * If the event did not specify a stream, the only existing stream
695 * must not have an id. Note: That behavior could be changed, it
696 * could be possible to just get the only existing stream, whatever
699 Stream stream
= trace
.getStream(null);
701 if (stream
!= null) {
702 event
.setStream(stream
);
704 throw new ParseException(
705 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
710 * Add the event to the stream.
712 event
.getStream().addEvent(event
);
717 private void parseEventDeclaration(CommonTree eventDecl
,
718 EventDeclaration event
) throws ParseException
{
720 /* There should be a left and right */
722 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
723 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
725 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
727 if (!isUnaryString(leftStrings
.get(0))) {
728 throw new ParseException(
729 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
732 String left
= concatenateUnaryStrings(leftStrings
);
734 if (left
.equals(CTFStrings
.NAME2
)) {
735 if (event
.nameIsSet()) {
736 throw new ParseException("name already defined"); //$NON-NLS-1$
739 String name
= getEventName(rightNode
);
742 } else if (left
.equals(CTFStrings
.ID
)) {
743 if (event
.idIsSet()) {
744 throw new ParseException("id already defined"); //$NON-NLS-1$
747 long id
= getEventID(rightNode
);
750 } else if (left
.equals(CTFStrings
.STREAM_ID
)) {
751 if (event
.streamIsSet()) {
752 throw new ParseException("stream id already defined"); //$NON-NLS-1$
755 long streamId
= getStreamID(rightNode
);
757 Stream stream
= trace
.getStream(streamId
);
759 if (stream
== null) {
760 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
763 event
.setStream(stream
);
764 } else if (left
.equals(CTFStrings
.CONTEXT
)) {
765 if (event
.contextIsSet()) {
766 throw new ParseException("context already defined"); //$NON-NLS-1$
769 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
771 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
772 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
775 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
778 if (!(contextDecl
instanceof StructDeclaration
)) {
779 throw new ParseException("context expects a struct"); //$NON-NLS-1$
782 event
.setContext((StructDeclaration
) contextDecl
);
783 } else if (left
.equals(CTFStrings
.FIELDS_STRING
)) {
784 if (event
.fieldsIsSet()) {
785 throw new ParseException("fields already defined"); //$NON-NLS-1$
788 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
790 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
791 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
794 IDeclaration fieldsDecl
;
795 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
797 if (!(fieldsDecl
instanceof StructDeclaration
)) {
798 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
801 * The underscores in the event names. These underscores were added
802 * by the LTTng tracer.
804 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
805 event
.setFields(fields
);
806 } else if (left
.equals(CTFStrings
.LOGLEVEL2
)) {
807 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
808 event
.setLogLevel(logLevel
);
810 /* Unknown event attribute, we'll simply ignore it */
816 * Parses a declaration at the root level.
819 * The declaration subtree.
820 * @throws ParseException
822 private void parseRootDeclaration(CommonTree declaration
)
823 throws ParseException
{
825 List
<CommonTree
> children
= declaration
.getChildren();
827 for (CommonTree child
: children
) {
828 switch (child
.getType()) {
829 case CTFParser
.TYPEDEF
:
832 case CTFParser
.TYPEALIAS
:
833 parseTypealias(child
);
835 case CTFParser
.TYPE_SPECIFIER_LIST
:
836 parseTypeSpecifierList(child
, null);
839 childTypeError(child
);
845 * Parses a typealias node. It parses the target, the alias, and registers
846 * the type in the current scope.
850 * @throws ParseException
852 private void parseTypealias(CommonTree typealias
) throws ParseException
{
854 List
<CommonTree
> children
= typealias
.getChildren();
856 CommonTree target
= null;
857 CommonTree alias
= null;
859 for (CommonTree child
: children
) {
860 switch (child
.getType()) {
861 case CTFParser
.TYPEALIAS_TARGET
:
864 case CTFParser
.TYPEALIAS_ALIAS
:
868 childTypeError(child
);
874 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
876 if (targetDeclaration
instanceof VariantDeclaration
) {
877 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
878 throw new ParseException(
879 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
883 String aliasString
= parseTypealiasAlias(alias
);
885 getCurrentScope().registerType(aliasString
, targetDeclaration
);
889 * Parses the target part of a typealias and gets the corresponding
893 * A TYPEALIAS_TARGET node.
894 * @return The corresponding declaration.
895 * @throws ParseException
897 private IDeclaration
parseTypealiasTarget(CommonTree target
)
898 throws ParseException
{
900 List
<CommonTree
> children
= target
.getChildren();
902 CommonTree typeSpecifierList
= null;
903 CommonTree typeDeclaratorList
= null;
904 CommonTree typeDeclarator
= null;
905 StringBuilder identifierSB
= new StringBuilder();
907 for (CommonTree child
: children
) {
908 switch (child
.getType()) {
909 case CTFParser
.TYPE_SPECIFIER_LIST
:
910 typeSpecifierList
= child
;
912 case CTFParser
.TYPE_DECLARATOR_LIST
:
913 typeDeclaratorList
= child
;
916 childTypeError(child
);
922 if (typeDeclaratorList
!= null) {
924 * Only allow one declarator
926 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
927 * otherwise the new type puint8_t would maps to two different
930 if (typeDeclaratorList
.getChildCount() != 1) {
931 throw new ParseException(
932 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
935 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
938 /* Parse the target type and get the declaration */
939 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
940 typeSpecifierList
, identifierSB
);
943 * We don't allow identifier in the target
945 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
948 if (identifierSB
.length() > 0) {
949 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
950 + ") not expected in the typealias target"); //$NON-NLS-1$
953 return targetDeclaration
;
957 * Parses the alias part of a typealias. It parses the underlying specifier
958 * list and declarator and creates the string representation that will be
959 * used to register the type.
962 * A TYPEALIAS_ALIAS node.
963 * @return The string representation of the alias.
964 * @throws ParseException
966 private static String
parseTypealiasAlias(CommonTree alias
)
967 throws ParseException
{
969 List
<CommonTree
> children
= alias
.getChildren();
971 CommonTree typeSpecifierList
= null;
972 CommonTree typeDeclaratorList
= null;
973 CommonTree typeDeclarator
= null;
974 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
976 for (CommonTree child
: children
) {
977 switch (child
.getType()) {
978 case CTFParser
.TYPE_SPECIFIER_LIST
:
979 typeSpecifierList
= child
;
981 case CTFParser
.TYPE_DECLARATOR_LIST
:
982 typeDeclaratorList
= child
;
985 childTypeError(child
);
990 /* If there is a type declarator list, extract the pointers */
991 if (typeDeclaratorList
!= null) {
993 * Only allow one declarator
995 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
997 if (typeDeclaratorList
.getChildCount() != 1) {
998 throw new ParseException(
999 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1002 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1004 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
1006 for (CommonTree child
: typeDeclaratorChildren
) {
1007 switch (child
.getType()) {
1008 case CTFParser
.POINTER
:
1009 pointers
.add(child
);
1011 case CTFParser
.IDENTIFIER
:
1012 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1013 + ") not expected in the typealias target"); //$NON-NLS-1$
1016 childTypeError(child
);
1022 return createTypeDeclarationString(typeSpecifierList
, pointers
);
1026 * Parses a typedef node. This creates and registers a new declaration for
1027 * each declarator found in the typedef.
1031 * @throws ParseException
1032 * If there is an error creating the declaration.
1034 private void parseTypedef(CommonTree typedef
) throws ParseException
{
1036 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1038 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1040 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1042 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1043 StringBuilder identifierSB
= new StringBuilder();
1045 IDeclaration type_declaration
= parseTypeDeclarator(
1046 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1048 if (type_declaration
instanceof VariantDeclaration
) {
1049 if (((VariantDeclaration
) type_declaration
).isTagged()) {
1050 throw new ParseException(
1051 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1055 getCurrentScope().registerType(identifierSB
.toString(),
1061 * Parses a pair type declarator / type specifier list and returns the
1062 * corresponding declaration. If it is present, it also writes the
1063 * identifier of the declarator in the given {@link StringBuilder}.
1065 * @param typeDeclarator
1066 * A TYPE_DECLARATOR node.
1067 * @param typeSpecifierList
1068 * A TYPE_SPECIFIER_LIST node.
1069 * @param identifierSB
1070 * A StringBuilder that will receive the identifier found in the
1072 * @return The corresponding declaration.
1073 * @throws ParseException
1074 * If there is an error finding or creating the declaration.
1076 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1077 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1078 throws ParseException
{
1080 IDeclaration declaration
= null;
1081 List
<CommonTree
> children
= null;
1082 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1083 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1084 CommonTree identifier
= null;
1086 /* Separate the tokens by type */
1087 if (typeDeclarator
!= null) {
1088 children
= typeDeclarator
.getChildren();
1089 for (CommonTree child
: children
) {
1091 switch (child
.getType()) {
1092 case CTFParser
.POINTER
:
1093 pointers
.add(child
);
1095 case CTFParser
.IDENTIFIER
:
1098 case CTFParser
.LENGTH
:
1102 childTypeError(child
);
1110 * Parse the type specifier list, which is the "base" type. For example,
1111 * it would be int in int a[3][len].
1113 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1116 * Each length subscript means that we must create a nested array or
1117 * sequence. For example, int a[3][len] means that we have an array of 3
1118 * (sequences of length 'len' of (int)).
1120 if (lengths
.size() > 0) {
1121 /* We begin at the end */
1122 Collections
.reverse(lengths
);
1124 for (CommonTree length
: lengths
) {
1126 * By looking at the first expression, we can determine whether
1127 * it is an array or a sequence.
1129 List
<CommonTree
> lengthChildren
= length
.getChildren();
1131 CommonTree first
= lengthChildren
.get(0);
1132 if (isUnaryInteger(first
)) {
1134 int arrayLength
= (int) parseUnaryInteger(first
);
1136 if (arrayLength
< 1) {
1137 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1140 /* Create the array declaration. */
1141 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1142 } else if (isUnaryString(first
)) {
1144 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1146 /* Create the sequence declaration. */
1147 declaration
= new SequenceDeclaration(lengthName
,
1150 childTypeError(first
);
1155 if (identifier
!= null) {
1156 identifierSB
.append(identifier
.getText());
1163 * Parses a type specifier list and returns the corresponding declaration.
1165 * @param typeSpecifierList
1166 * A TYPE_SPECIFIER_LIST node.
1167 * @param pointerList
1168 * A list of POINTER nodes that apply to the specified type.
1169 * @return The corresponding declaration.
1170 * @throws ParseException
1171 * If the type has not been defined or if there is an error
1172 * creating the declaration.
1174 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1175 List
<CommonTree
> pointerList
) throws ParseException
{
1176 IDeclaration declaration
= null;
1179 * By looking at the first element of the type specifier list, we can
1180 * determine which type it belongs to.
1182 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1184 switch (firstChild
.getType()) {
1185 case CTFParser
.FLOATING_POINT
:
1186 declaration
= parseFloat(firstChild
);
1188 case CTFParser
.INTEGER
:
1189 declaration
= parseInteger(firstChild
);
1191 case CTFParser
.STRING
:
1192 declaration
= parseString(firstChild
);
1194 case CTFParser
.STRUCT
:
1195 declaration
= parseStruct(firstChild
);
1197 case CTFParser
.VARIANT
:
1198 declaration
= parseVariant(firstChild
);
1200 case CTFParser
.ENUM
:
1201 declaration
= parseEnum(firstChild
);
1203 case CTFParser
.IDENTIFIER
:
1204 case CTFParser
.FLOATTOK
:
1205 case CTFParser
.INTTOK
:
1206 case CTFParser
.LONGTOK
:
1207 case CTFParser
.SHORTTOK
:
1208 case CTFParser
.SIGNEDTOK
:
1209 case CTFParser
.UNSIGNEDTOK
:
1210 case CTFParser
.CHARTOK
:
1211 case CTFParser
.DOUBLETOK
:
1212 case CTFParser
.VOIDTOK
:
1213 case CTFParser
.BOOLTOK
:
1214 case CTFParser
.COMPLEXTOK
:
1215 case CTFParser
.IMAGINARYTOK
:
1216 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1219 childTypeError(firstChild
);
1225 private IDeclaration
parseFloat(CommonTree floatingPoint
)
1226 throws ParseException
{
1228 List
<CommonTree
> children
= floatingPoint
.getChildren();
1231 * If the integer has no attributes, then it is missing the size
1232 * attribute which is required
1234 if (children
== null) {
1235 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1238 /* The return value */
1239 FloatDeclaration floatDeclaration
= null;
1240 ByteOrder byteOrder
= trace
.getByteOrder();
1245 /* Iterate on all integer children */
1246 for (CommonTree child
: children
) {
1247 switch (child
.getType()) {
1248 case CTFParser
.CTF_EXPRESSION_VAL
:
1250 * An assignment expression must have 2 children, left and right
1253 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1254 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1256 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
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(CTFStrings
.EXP_DIG
)) {
1265 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1266 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1267 byteOrder
= getByteOrder(rightNode
);
1268 } else if (left
.equals(CTFStrings
.MANT_DIG
)) {
1269 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1270 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1271 alignment
= getAlignment(rightNode
);
1273 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1278 childTypeError(child
);
1282 int size
= mantissa
+ exponent
;
1284 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1287 if (alignment
== 0) {
1288 if ((size
% 8) == 0) {
1295 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1297 return floatDeclaration
;
1302 * Parses a type specifier list as a user-declared type.
1304 * @param typeSpecifierList
1305 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1306 * @param pointerList
1307 * A list of POINTER nodes that apply to the type specified in
1308 * typeSpecifierList.
1309 * @return The corresponding declaration.
1310 * @throws ParseException
1311 * If the type does not exist (has not been found).
1313 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1314 List
<CommonTree
> pointerList
) throws ParseException
{
1315 /* Create the string representation of the type declaration */
1316 String typeStringRepresentation
= createTypeDeclarationString(
1317 typeSpecifierList
, pointerList
);
1319 /* Use the string representation to search the type in the current scope */
1320 IDeclaration decl
= getCurrentScope().rlookupType(
1321 typeStringRepresentation
);
1324 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1325 + " has not been defined."); //$NON-NLS-1$
1332 * Parses an integer declaration node.
1336 * @return The corresponding integer declaration.
1337 * @throws ParseException
1339 private IntegerDeclaration
parseInteger(CommonTree integer
)
1340 throws ParseException
{
1342 List
<CommonTree
> children
= integer
.getChildren();
1345 * If the integer has no attributes, then it is missing the size
1346 * attribute which is required
1348 if (children
== null) {
1349 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1352 /* The return value */
1353 IntegerDeclaration integerDeclaration
= null;
1354 boolean signed
= false;
1355 ByteOrder byteOrder
= trace
.getByteOrder();
1359 String clock
= null;
1361 Encoding encoding
= Encoding
.NONE
;
1363 /* Iterate on all integer children */
1364 for (CommonTree child
: children
) {
1365 switch (child
.getType()) {
1366 case CTFParser
.CTF_EXPRESSION_VAL
:
1368 * An assignment expression must have 2 children, left and right
1371 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1372 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1374 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1376 if (!isUnaryString(leftStrings
.get(0))) {
1377 throw new ParseException(
1378 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1380 String left
= concatenateUnaryStrings(leftStrings
);
1382 if (left
.equals("signed")) { //$NON-NLS-1$
1383 signed
= getSigned(rightNode
);
1384 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1385 byteOrder
= getByteOrder(rightNode
);
1386 } else if (left
.equals("size")) { //$NON-NLS-1$
1387 size
= getSize(rightNode
);
1388 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1389 alignment
= getAlignment(rightNode
);
1390 } else if (left
.equals("base")) { //$NON-NLS-1$
1391 base
= getBase(rightNode
);
1392 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1393 encoding
= getEncoding(rightNode
);
1394 } else if (left
.equals("map")) { //$NON-NLS-1$
1395 clock
= getClock(rightNode
);
1397 throw new ParseException(
1398 "Integer: unknown attribute " + left
); //$NON-NLS-1$
1403 childTypeError(child
);
1409 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1412 if (alignment
== 0) {
1413 if ((size
% 8) == 0) {
1420 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1421 byteOrder
, encoding
, clock
, alignment
);
1423 return integerDeclaration
;
1426 private static String
getClock(CommonTree rightNode
) {
1427 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1430 private static StringDeclaration
parseString(CommonTree string
)
1431 throws ParseException
{
1433 List
<CommonTree
> children
= string
.getChildren();
1434 StringDeclaration stringDeclaration
= null;
1436 if (children
== null) {
1437 stringDeclaration
= new StringDeclaration();
1439 Encoding encoding
= Encoding
.UTF8
;
1440 for (CommonTree child
: children
) {
1441 switch (child
.getType()) {
1442 case CTFParser
.CTF_EXPRESSION_VAL
:
1444 * An assignment expression must have 2 children, left and
1448 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1449 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1451 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1453 if (!isUnaryString(leftStrings
.get(0))) {
1454 throw new ParseException(
1455 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1457 String left
= concatenateUnaryStrings(leftStrings
);
1459 if (left
.equals("encoding")) { //$NON-NLS-1$
1460 encoding
= getEncoding(rightNode
);
1462 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1468 childTypeError(child
);
1473 stringDeclaration
= new StringDeclaration(encoding
);
1476 return stringDeclaration
;
1480 * Parses a struct declaration and returns the corresponding declaration.
1484 * @return The corresponding struct declaration.
1485 * @throws ParseException
1487 private StructDeclaration
parseStruct(CommonTree struct
)
1488 throws ParseException
{
1490 List
<CommonTree
> children
= struct
.getChildren();
1492 /* The return value */
1493 StructDeclaration structDeclaration
= null;
1496 String structName
= null;
1497 boolean hasName
= false;
1500 CommonTree structBody
= null;
1501 boolean hasBody
= false;
1504 long structAlign
= 0;
1506 /* Loop on all children and identify what we have to work with. */
1507 for (CommonTree child
: children
) {
1508 switch (child
.getType()) {
1509 case CTFParser
.STRUCT_NAME
: {
1512 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1514 structName
= structNameIdentifier
.getText();
1518 case CTFParser
.STRUCT_BODY
: {
1525 case CTFParser
.ALIGN
: {
1526 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1528 structAlign
= getAlignment(structAlignExpression
);
1533 childTypeError(child
);
1540 * If a struct has just a body and no name (just like the song,
1541 * "A Struct With No Name" by America (sorry for that...)), it's a
1542 * definition of a new type, so we create the type declaration and
1543 * return it. We can't add it to the declaration scope since there is no
1544 * name, but that's what we want because it won't be possible to use it
1545 * again to declare another field.
1547 * If it has just a name, we look it up in the declaration scope and
1548 * return the associated declaration. If it is not found in the
1549 * declaration scope, it means that a struct with that name has not been
1550 * declared, which is an error.
1552 * If it has both, then we create the type declaration and register it
1553 * to the current scope.
1555 * If it has none, then what are we doing here ?
1559 * If struct has a name, check if already defined in the current
1562 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1563 throw new ParseException("struct " + structName
//$NON-NLS-1$
1564 + " already defined."); //$NON-NLS-1$
1566 /* Create the declaration */
1567 structDeclaration
= new StructDeclaration(structAlign
);
1569 /* Parse the body */
1570 parseStructBody(structBody
, structDeclaration
);
1572 /* If struct has name, add it to the current scope. */
1574 getCurrentScope().registerStruct(structName
, structDeclaration
);
1576 } else /* !hasBody */{
1578 /* Name and !body */
1580 /* Lookup the name in the current scope. */
1581 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1584 * If not found, it means that a struct with such name has not
1587 if (structDeclaration
== null) {
1588 throw new ParseException("struct " + structName
//$NON-NLS-1$
1589 + " is not defined"); //$NON-NLS-1$
1592 /* !Name and !body */
1594 /* We can't do anything with that. */
1595 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1599 return structDeclaration
;
1603 * Parses a struct body, adding the fields to specified structure
1607 * A STRUCT_BODY node.
1608 * @param structDeclaration
1609 * The struct declaration.
1610 * @throws ParseException
1612 private void parseStructBody(CommonTree structBody
,
1613 StructDeclaration structDeclaration
) throws ParseException
{
1615 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1618 * If structDeclaration is null, structBody has no children and the
1619 * struct body is empty.
1621 if (structDeclarations
!= null) {
1624 for (CommonTree declarationNode
: structDeclarations
) {
1625 switch (declarationNode
.getType()) {
1626 case CTFParser
.TYPEALIAS
:
1627 parseTypealias(declarationNode
);
1629 case CTFParser
.TYPEDEF
:
1630 parseTypedef(declarationNode
);
1632 case CTFParser
.SV_DECLARATION
:
1633 parseStructDeclaration(declarationNode
, structDeclaration
);
1636 childTypeError(declarationNode
);
1645 * Parses a declaration found in a struct.
1647 * @param declaration
1648 * A SV_DECLARATION node.
1650 * A struct declaration. (I know, little name clash here...)
1651 * @throws ParseException
1653 private void parseStructDeclaration(CommonTree declaration
,
1654 StructDeclaration struct
) throws ParseException
{
1657 /* Get the type specifier list node */
1658 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1660 /* Get the type declarator list node */
1661 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1663 /* Get the type declarator list */
1664 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1667 * For each type declarator, parse the declaration and add a field to
1670 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1672 StringBuilder identifierSB
= new StringBuilder();
1674 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1675 typeSpecifierListNode
, identifierSB
);
1676 String fieldName
= identifierSB
.toString();
1678 if (struct
.hasField(fieldName
)) {
1679 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1683 struct
.addField(fieldName
, decl
);
1689 * Parses an enum declaration and returns the corresponding declaration.
1693 * @return The corresponding enum declaration.
1694 * @throws ParseException
1696 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1698 List
<CommonTree
> children
= _enum
.getChildren();
1700 /* The return value */
1701 EnumDeclaration enumDeclaration
= null;
1704 String enumName
= null;
1707 CommonTree enumBody
= null;
1709 /* Container type */
1710 IntegerDeclaration containerTypeDeclaration
= null;
1712 /* Loop on all children and identify what we have to work with. */
1713 for (CommonTree child
: children
) {
1714 switch (child
.getType()) {
1715 case CTFParser
.ENUM_NAME
: {
1716 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1718 enumName
= enumNameIdentifier
.getText();
1722 case CTFParser
.ENUM_BODY
: {
1728 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1730 containerTypeDeclaration
= parseEnumContainerType(child
);
1735 childTypeError(child
);
1741 * If the container type has not been defined explicitly, we assume it
1744 if (containerTypeDeclaration
== null) {
1745 IDeclaration enumDecl
;
1747 * it could be because the enum was already declared.
1749 if (enumName
!= null) {
1750 enumDecl
= getCurrentScope().rlookupEnum(enumName
);
1751 if (enumDecl
!= null) {
1752 return (EnumDeclaration
) enumDecl
;
1756 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1759 throw new ParseException(
1760 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1761 } else if (!(decl
instanceof IntegerDeclaration
)) {
1762 throw new ParseException(
1763 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1766 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1770 * If it has a body, it's a new declaration, otherwise it's a reference
1771 * to an existing declaration. Same logic as struct.
1773 if (enumBody
!= null) {
1775 * If enum has a name, check if already defined in the current
1778 if ((enumName
!= null)
1779 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1780 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1781 + " already defined"); //$NON-NLS-1$
1784 /* Create the declaration */
1785 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1787 /* Parse the body */
1788 parseEnumBody(enumBody
, enumDeclaration
);
1790 /* If the enum has name, add it to the current scope. */
1791 if (enumName
!= null) {
1792 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1795 if (enumName
!= null) {
1796 /* Name and !body */
1798 /* Lookup the name in the current scope. */
1799 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1802 * If not found, it means that an enum with such name has not
1805 if (enumDeclaration
== null) {
1806 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1807 + " is not defined"); //$NON-NLS-1$
1810 /* !Name and !body */
1811 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1815 return enumDeclaration
;
1820 * Parses an enum body, adding the enumerators to the specified enum
1824 * An ENUM_BODY node.
1825 * @param enumDeclaration
1826 * The enum declaration.
1827 * @throws ParseException
1829 private void parseEnumBody(CommonTree enumBody
,
1830 EnumDeclaration enumDeclaration
) throws ParseException
{
1832 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1833 /* enum body can't be empty (unlike struct). */
1838 * Start at -1, so that if the first enumrator has no explicit value, it
1843 for (CommonTree enumerator
: enumerators
) {
1844 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1853 * Parses an enumerator node and adds an enumerator declaration to an
1854 * enumeration declaration.
1856 * The high value of the range of the last enumerator is needed in case the
1857 * current enumerator does not specify its value.
1860 * An ENUM_ENUMERATOR node.
1861 * @param enumDeclaration
1862 * en enumeration declaration to which will be added the
1865 * The high value of the range of the last enumerator
1866 * @return The high value of the value range of the current enumerator.
1867 * @throws ParseException
1869 private static long parseEnumEnumerator(CommonTree enumerator
,
1870 EnumDeclaration enumDeclaration
, long lastHigh
)
1871 throws ParseException
{
1873 List
<CommonTree
> children
= enumerator
.getChildren();
1875 long low
= 0, high
= 0;
1876 boolean valueSpecified
= false;
1877 String label
= null;
1879 for (CommonTree child
: children
) {
1880 if (isUnaryString(child
)) {
1881 label
= parseUnaryString(child
);
1882 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1884 valueSpecified
= true;
1886 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1888 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1890 valueSpecified
= true;
1892 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1893 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1895 childTypeError(child
);
1899 if (!valueSpecified
) {
1905 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1908 if (!enumDeclaration
.add(low
, high
, label
)) {
1909 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1916 * Parses an enum container type node and returns the corresponding integer
1919 * @param enumContainerType
1920 * An ENUM_CONTAINER_TYPE node.
1921 * @return An integer declaration corresponding to the container type.
1922 * @throws ParseException
1923 * If the type does not parse correctly or if it is not an
1926 private IntegerDeclaration
parseEnumContainerType(
1927 CommonTree enumContainerType
) throws ParseException
{
1929 /* Get the child, which should be a type specifier list */
1930 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
.getChild(0);
1932 /* Parse it and get the corresponding declaration */
1933 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1935 /* If is is an integer, return it, else throw an error */
1936 if (decl
instanceof IntegerDeclaration
) {
1937 return (IntegerDeclaration
) decl
;
1939 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1942 private VariantDeclaration
parseVariant(CommonTree variant
)
1943 throws ParseException
{
1945 List
<CommonTree
> children
= variant
.getChildren();
1946 VariantDeclaration variantDeclaration
= null;
1948 boolean hasName
= false;
1949 String variantName
= null;
1951 boolean hasBody
= false;
1952 CommonTree variantBody
= null;
1954 boolean hasTag
= false;
1955 String variantTag
= null;
1957 for (CommonTree child
: children
) {
1958 switch (child
.getType()) {
1959 case CTFParser
.VARIANT_NAME
:
1963 CommonTree variantNameIdentifier
= (CommonTree
) child
.getChild(0);
1965 variantName
= variantNameIdentifier
.getText();
1968 case CTFParser
.VARIANT_TAG
:
1972 CommonTree variantTagIdentifier
= (CommonTree
) child
.getChild(0);
1974 variantTag
= variantTagIdentifier
.getText();
1977 case CTFParser
.VARIANT_BODY
:
1981 variantBody
= child
;
1985 childTypeError(child
);
1992 * If variant has a name, check if already defined in the current
1996 && (getCurrentScope().lookupVariant(variantName
) != null)) {
1997 throw new ParseException("variant " + variantName
//$NON-NLS-1$
1998 + " already defined."); //$NON-NLS-1$
2001 /* Create the declaration */
2002 variantDeclaration
= new VariantDeclaration();
2004 /* Parse the body */
2005 parseVariantBody(variantBody
, variantDeclaration
);
2007 /* If variant has name, add it to the current scope. */
2009 getCurrentScope().registerVariant(variantName
,
2010 variantDeclaration
);
2012 } else /* !hasBody */{
2014 /* Name and !body */
2016 /* Lookup the name in the current scope. */
2017 variantDeclaration
= getCurrentScope().rlookupVariant(
2021 * If not found, it means that a struct with such name has not
2024 if (variantDeclaration
== null) {
2025 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2026 + " is not defined"); //$NON-NLS-1$
2029 /* !Name and !body */
2031 /* We can't do anything with that. */
2032 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2037 variantDeclaration
.setTag(variantTag
);
2040 return variantDeclaration
;
2043 private void parseVariantBody(CommonTree variantBody
,
2044 VariantDeclaration variantDeclaration
) throws ParseException
{
2046 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2050 for (CommonTree declarationNode
: variantDeclarations
) {
2051 switch (declarationNode
.getType()) {
2052 case CTFParser
.TYPEALIAS
:
2053 parseTypealias(declarationNode
);
2055 case CTFParser
.TYPEDEF
:
2056 parseTypedef(declarationNode
);
2058 case CTFParser
.SV_DECLARATION
:
2059 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2062 childTypeError(declarationNode
);
2070 private void parseVariantDeclaration(CommonTree declaration
,
2071 VariantDeclaration variant
) throws ParseException
{
2074 /* Get the type specifier list node */
2075 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2077 /* Get the type declarator list node */
2078 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2080 /* Get the type declarator list */
2081 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
2084 * For each type declarator, parse the declaration and add a field to
2087 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2089 StringBuilder identifierSB
= new StringBuilder();
2091 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2092 typeSpecifierListNode
, identifierSB
);
2094 if (variant
.hasField(identifierSB
.toString())) {
2095 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2096 + identifierSB
.toString());
2099 variant
.addField(identifierSB
.toString(), decl
);
2104 * Creates the string representation of a type declaration (type specifier
2107 * @param typeSpecifierList
2108 * A TYPE_SPECIFIER_LIST node.
2110 * A list of POINTER nodes.
2111 * @return The string representation.
2112 * @throws ParseException
2114 private static String
createTypeDeclarationString(
2115 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2116 throws ParseException
{
2117 StringBuilder sb
= new StringBuilder();
2119 createTypeSpecifierListString(typeSpecifierList
, sb
);
2120 createPointerListString(pointers
, sb
);
2122 return sb
.toString();
2126 * Creates the string representation of a list of type specifiers.
2128 * @param typeSpecifierList
2129 * A TYPE_SPECIFIER_LIST node.
2131 * A StringBuilder to which will be appended the string.
2132 * @throws ParseException
2134 private static void createTypeSpecifierListString(
2135 CommonTree typeSpecifierList
, StringBuilder sb
)
2136 throws ParseException
{
2138 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2140 boolean firstItem
= true;
2142 for (CommonTree child
: children
) {
2150 /* Append the string that represents this type specifier. */
2151 createTypeSpecifierString(child
, sb
);
2156 * Creates the string representation of a type specifier.
2158 * @param typeSpecifier
2159 * A TYPE_SPECIFIER node.
2161 * A StringBuilder to which will be appended the string.
2162 * @throws ParseException
2164 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2165 StringBuilder sb
) throws ParseException
{
2166 switch (typeSpecifier
.getType()) {
2167 case CTFParser
.FLOATTOK
:
2168 case CTFParser
.INTTOK
:
2169 case CTFParser
.LONGTOK
:
2170 case CTFParser
.SHORTTOK
:
2171 case CTFParser
.SIGNEDTOK
:
2172 case CTFParser
.UNSIGNEDTOK
:
2173 case CTFParser
.CHARTOK
:
2174 case CTFParser
.DOUBLETOK
:
2175 case CTFParser
.VOIDTOK
:
2176 case CTFParser
.BOOLTOK
:
2177 case CTFParser
.COMPLEXTOK
:
2178 case CTFParser
.IMAGINARYTOK
:
2179 case CTFParser
.CONSTTOK
:
2180 case CTFParser
.IDENTIFIER
:
2181 sb
.append(typeSpecifier
.getText());
2183 case CTFParser
.STRUCT
: {
2184 CommonTree structName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2185 if (structName
== null) {
2186 throw new ParseException(
2187 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2190 CommonTree structNameIdentifier
= (CommonTree
) structName
.getChild(0);
2192 sb
.append(structNameIdentifier
.getText());
2195 case CTFParser
.VARIANT
: {
2196 CommonTree variantName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2197 if (variantName
== null) {
2198 throw new ParseException(
2199 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2202 CommonTree variantNameIdentifier
= (CommonTree
) variantName
.getChild(0);
2204 sb
.append(variantNameIdentifier
.getText());
2207 case CTFParser
.ENUM
: {
2208 CommonTree enumName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.ENUM_NAME
);
2209 if (enumName
== null) {
2210 throw new ParseException(
2211 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2214 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2216 sb
.append(enumNameIdentifier
.getText());
2219 case CTFParser
.FLOATING_POINT
:
2220 case CTFParser
.INTEGER
:
2221 case CTFParser
.STRING
:
2222 throw new ParseException(
2223 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2226 childTypeError(typeSpecifier
);
2232 * Creates the string representation of a list of pointers.
2234 * @param pointerList
2235 * A list of pointer nodes. If pointerList is null, this function
2238 * A stringbuilder to which will be appended the string.
2240 private static void createPointerListString(List
<CommonTree
> pointerList
,
2242 if (pointerList
== null) {
2246 for (CommonTree pointer
: pointerList
) {
2248 sb
.append(" *"); //$NON-NLS-1$
2249 if (pointer
.getChildCount() > 0) {
2251 sb
.append(" const"); //$NON-NLS-1$
2258 * The node to check.
2259 * @return True if the given node is an unary string.
2261 private static boolean isUnaryString(CommonTree node
) {
2262 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) ||
2263 (node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2268 * The node to check.
2269 * @return True if the given node is an unary integer.
2271 private static boolean isUnaryInteger(CommonTree node
) {
2272 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) ||
2273 (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) ||
2274 (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2278 * Parses a unary string node and return the string value.
2280 * @param unaryString
2281 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2282 * or UNARY_EXPRESSION_STRING_QUOTES).
2283 * @return The string value.
2286 * It would be really nice to remove the quotes earlier, such as in the
2289 private static String
parseUnaryString(CommonTree unaryString
) {
2291 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2292 String strval
= value
.getText();
2295 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2296 strval
= strval
.substring(1, strval
.length() - 1);
2303 * Parses an unary integer (dec, hex or oct).
2305 * @param unaryInteger
2306 * An unary integer node.
2307 * @return The integer value.
2309 private static long parseUnaryInteger(CommonTree unaryInteger
) {
2311 List
<CommonTree
> children
= unaryInteger
.getChildren();
2312 CommonTree value
= children
.get(0);
2313 String strval
= value
.getText();
2317 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2318 intval
= Long
.parseLong(strval
, 10);
2319 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2320 intval
= Long
.parseLong(strval
, 0x10);
2321 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2322 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2325 /* The rest of children are sign */
2326 if ((children
.size() % 2) == 0) {
2332 private static long getMajorOrMinor(CommonTree rightNode
)
2333 throws ParseException
{
2335 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2337 if (isUnaryInteger(firstChild
)) {
2338 if (rightNode
.getChildCount() > 1) {
2339 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2342 long m
= parseUnaryInteger(firstChild
);
2345 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2350 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2353 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2355 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2357 if (isUnaryString(firstChild
)) {
2358 if (rightNode
.getChildCount() > 1) {
2359 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2362 String uuidstr
= parseUnaryString(firstChild
);
2365 UUID uuid
= UUID
.fromString(uuidstr
);
2367 } catch (IllegalArgumentException e
) {
2368 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2371 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2375 * Gets the value of a "signed" integer attribute.
2379 * @return The "signed" value as a boolean.
2380 * @throws ParseException
2382 private static boolean getSigned(CommonTree rightNode
)
2383 throws ParseException
{
2385 boolean ret
= false;
2386 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2388 if (isUnaryString(firstChild
)) {
2389 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2391 if (strval
.equals(CTFStrings
.TRUE
)
2392 || strval
.equals(CTFStrings
.TRUE2
)) {
2394 } else if (strval
.equals(CTFStrings
.FALSE
)
2395 || strval
.equals(CTFStrings
.FALSE2
)) {
2398 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2399 + firstChild
.getChild(0).getText());
2401 } else if (isUnaryInteger(firstChild
)) {
2402 /* Happens if the value is something like "1234.hello" */
2403 if (rightNode
.getChildCount() > 1) {
2404 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2407 long intval
= parseUnaryInteger(firstChild
);
2411 } else if (intval
== 0) {
2414 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2415 + firstChild
.getChild(0).getText());
2418 throw new ParseException();
2425 * Gets the value of a "byte_order" integer attribute.
2429 * @return The "byte_order" value.
2430 * @throws ParseException
2432 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2434 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2436 if (isUnaryString(firstChild
)) {
2437 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2439 if (strval
.equals(CTFStrings
.LE
)) {
2440 return ByteOrder
.LITTLE_ENDIAN
;
2441 } else if (strval
.equals(CTFStrings
.BE
)
2442 || strval
.equals(CTFStrings
.NETWORK
)) {
2443 return ByteOrder
.BIG_ENDIAN
;
2444 } else if (strval
.equals(CTFStrings
.NATIVE
)) {
2445 return trace
.getByteOrder();
2447 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2450 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2454 * Determines if the given value is a valid alignment value.
2457 * The value to check.
2458 * @return True if it is valid.
2460 private static boolean isValidAlignment(long alignment
) {
2461 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2465 * Gets the value of a "size" integer attribute.
2469 * @return The "size" value.
2470 * @throws ParseException
2472 private static long getSize(CommonTree rightNode
) throws ParseException
{
2474 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2476 if (isUnaryInteger(firstChild
)) {
2477 if (rightNode
.getChildCount() > 1) {
2478 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2481 long size
= parseUnaryInteger(firstChild
);
2484 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2489 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2493 * Gets the value of a "align" integer or struct attribute.
2496 * A CTF_RIGHT node or directly an unary integer.
2497 * @return The align value.
2498 * @throws ParseException
2500 private static long getAlignment(CommonTree node
) throws ParseException
{
2503 * If a CTF_RIGHT node was passed, call getAlignment with the first
2506 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2507 if (node
.getChildCount() > 1) {
2508 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2511 return getAlignment((CommonTree
) node
.getChild(0));
2512 } else if (isUnaryInteger(node
)) {
2513 long alignment
= parseUnaryInteger(node
);
2515 if (!isValidAlignment(alignment
)) {
2516 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2522 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2526 * Gets the value of a "base" integer attribute.
2529 * An CTF_RIGHT node.
2530 * @return The "base" value.
2531 * @throws ParseException
2533 private static int getBase(CommonTree rightNode
) throws ParseException
{
2535 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2537 if (isUnaryInteger(firstChild
)) {
2538 if (rightNode
.getChildCount() > 1) {
2539 throw new ParseException("invalid base value"); //$NON-NLS-1$
2542 long intval
= parseUnaryInteger(firstChild
);
2543 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2544 || (intval
== 16)) {
2545 return (int) intval
;
2547 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2548 } else if (isUnaryString(firstChild
)) {
2549 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2551 if (strval
.equals(CTFStrings
.DECIMAL
)
2552 || strval
.equals(CTFStrings
.DEC
)
2553 || strval
.equals(CTFStrings
.DEC_CTE
)
2554 || strval
.equals(CTFStrings
.INT_MOD
)
2555 || strval
.equals(CTFStrings
.UNSIGNED_CTE
)) {
2557 } else if (strval
.equals(CTFStrings
.HEXADECIMAL
)
2558 || strval
.equals(CTFStrings
.HEX
)
2559 || strval
.equals(CTFStrings
.X
)
2560 || strval
.equals(CTFStrings
.X2
)
2561 || strval
.equals(CTFStrings
.POINTER
)) {
2563 } else if (strval
.equals(CTFStrings
.OCTAL
)
2564 || strval
.equals(CTFStrings
.OCT
)
2565 || strval
.equals(CTFStrings
.OCTAL_CTE
)) {
2567 } else if (strval
.equals(CTFStrings
.BINARY
)
2568 || strval
.equals(CTFStrings
.BIN
)) {
2571 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2574 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2579 * Gets the value of an "encoding" integer attribute.
2583 * @return The "encoding" value.
2584 * @throws ParseException
2586 private static Encoding
getEncoding(CommonTree rightNode
)
2587 throws ParseException
{
2589 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2591 if (isUnaryString(firstChild
)) {
2592 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2594 if (strval
.equals(CTFStrings
.UTF8
)) {
2595 return Encoding
.UTF8
;
2596 } else if (strval
.equals(CTFStrings
.ASCII
)) {
2597 return Encoding
.ASCII
;
2598 } else if (strval
.equals(CTFStrings
.NONE
)) {
2599 return Encoding
.NONE
;
2601 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2604 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2607 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2609 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2611 if (isUnaryInteger(firstChild
)) {
2612 if (rightNode
.getChildCount() > 1) {
2613 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2616 long intval
= parseUnaryInteger(firstChild
);
2620 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2623 private static String
getEventName(CommonTree rightNode
)
2624 throws ParseException
{
2626 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2628 if (isUnaryString(firstChild
)) {
2629 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2633 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2636 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2638 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2640 if (isUnaryInteger(firstChild
)) {
2641 if (rightNode
.getChildCount() > 1) {
2642 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2645 long intval
= parseUnaryInteger(firstChild
);
2649 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2653 * Concatenates a list of unary strings separated by arrows (->) or dots.
2656 * A list, first element being an unary string, subsequent
2657 * elements being ARROW or DOT nodes with unary strings as child.
2658 * @return The string representation of the unary string chain.
2660 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2662 StringBuilder sb
= new StringBuilder();
2664 CommonTree first
= strings
.get(0);
2665 sb
.append(parseUnaryString(first
));
2667 boolean isFirst
= true;
2669 for (CommonTree ref
: strings
) {
2676 CommonTree id
= (CommonTree
) ref
.getChild(0);
2678 if (ref
.getType() == CTFParser
.ARROW
) {
2679 sb
.append("->"); //$NON-NLS-1$
2684 sb
.append(parseUnaryString(id
));
2687 return sb
.toString();
2691 * Throws a ParseException stating that the parent-child relation between
2692 * the given node and its parent is not valid. It means that the shape of
2693 * the AST is unexpected.
2696 * The invalid child node.
2697 * @throws ParseException
2699 private static void childTypeError(CommonTree child
) throws ParseException
{
2700 CommonTree parent
= (CommonTree
) child
.getParent();
2701 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2702 + " can't have a child of type " //$NON-NLS-1$
2703 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2705 throw new ParseException(error
);
2708 // ------------------------------------------------------------------------
2710 // ------------------------------------------------------------------------
2713 * Adds a new declaration scope on the top of the scope stack.
2715 private void pushScope() {
2716 scope
= new DeclarationScope(scope
);
2720 * Removes the top declaration scope from the scope stack.
2722 private void popScope() {
2723 scope
= scope
.getParentScope();
2727 * Returns the current declaration scope.
2729 * @return The current declaration scope.
2731 private DeclarationScope
getCurrentScope() {