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
.CTFReaderException
;
39 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
40 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.Stream
;
41 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
42 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.EventDeclaration
;
43 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
48 public class IOStructGen
{
50 // ------------------------------------------------------------------------
52 // ------------------------------------------------------------------------
54 static private final boolean DEBUG_
= false;
59 private final CTFTrace trace
;
60 private final CommonTree tree
;
63 * The current declaration scope.
65 private DeclarationScope scope
= null;
67 // ------------------------------------------------------------------------
69 // ------------------------------------------------------------------------
75 * the tree (ANTLR generated) with the parsed TSDL data.
77 * the trace containing the places to put all the read metadata
79 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
85 * Parse the tree and populate the trace defined in the constructor.
87 * @throws ParseException
88 * If there was a problem parsing the metadata
90 public void generate() throws ParseException
{
94 // ------------------------------------------------------------------------
96 // ------------------------------------------------------------------------
99 * Parse the root node.
103 * @throws ParseException
105 private void parseRoot(CommonTree root
) throws ParseException
{
107 List
<CommonTree
> children
= root
.getChildren();
108 java
.io
.FileOutputStream fos
= null;
109 java
.io
.OutputStreamWriter out
= null;
112 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
113 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
114 } catch (FileNotFoundException e
) {
117 } catch (UnsupportedEncodingException e
) {
123 CommonTree traceNode
= null;
124 List
<CommonTree
> streams
= new ArrayList
<CommonTree
>();
125 List
<CommonTree
> events
= new ArrayList
<CommonTree
>();
126 List
<CommonTree
> declarations
= new ArrayList
<CommonTree
>();
127 List
<CommonTree
> environments
= new ArrayList
<CommonTree
>();
128 List
<CommonTree
> clocks
= new ArrayList
<CommonTree
>();
129 List
<CommonTree
> callsites
= new ArrayList
<CommonTree
>();
130 /* Create a new declaration scope with no parent. */
134 for (CommonTree child
: children
) {
135 final int type
= child
.getType();
137 out
.write(child
.toString()
138 + " -> " + type
+ '\n'); //$NON-NLS-1$
141 case CTFParser
.DECLARATION
:
142 declarations
.add(child
);
144 case CTFParser
.TRACE
:
145 if (traceNode
!= null) {
146 throw new ParseException(
147 "Only one trace block is allowed"); //$NON-NLS-1$
151 case CTFParser
.STREAM
:
154 case CTFParser
.EVENT
:
157 case CTFParser
.CLOCK
:
161 environments
.add(child
);
163 case CTFParser
.CALLSITE
:
164 callsites
.add(child
);
167 childTypeError(child
);
171 out
.write("Declarations\n"); //$NON-NLS-1$
173 for (CommonTree decl
: declarations
) {
175 out
.write(decl
.toString() + '\n');
177 parseRootDeclaration(decl
);
179 if (traceNode
== null) {
180 throw new ParseException("Missing trace block"); //$NON-NLS-1$
183 parseTrace(traceNode
);
186 out
.write("Environments\n"); //$NON-NLS-1$
188 for (CommonTree environment
: environments
) {
189 parseEnvironment(environment
);
192 out
.write("Clocks\n"); //$NON-NLS-1$
194 for (CommonTree clock
: clocks
) {
198 out
.write("Callsites\n"); //$NON-NLS-1$
200 for (CommonTree callsite
: callsites
) {
201 parseCallsite(callsite
);
205 out
.write("Streams\n"); //$NON-NLS-1$
207 if (streams
.size() > 0) {
208 for (CommonTree stream
: streams
) {
211 out
.write(stream
.toString() + '\n');
212 } catch (IOException e
) {
219 /* Add an empty stream that will have a null id */
220 trace
.addStream(new Stream(trace
));
224 out
.write("Events\n"); //$NON-NLS-1$
226 for (CommonTree event
: events
) {
229 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
230 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
231 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
239 } catch (IOException e
) {
245 private void parseCallsite(CommonTree callsite
) {
247 List
<CommonTree
> children
= callsite
.getChildren();
249 String func_name
= null;
250 long line_number
= -1;
252 String file_name
= null;
254 for (CommonTree child
: children
) {
256 /* this is a regex to find the leading and trailing quotes*/
257 final String regex
= "^\"|\"$"; //$NON-NLS-1$
258 /* this is to replace the previous quotes with nothing... effectively deleting them */
259 final String nullString
= ""; //$NON-NLS-1$
260 left
= child
.getChild(0).getChild(0).getChild(0).getText();
261 if (left
.equals("name")) { //$NON-NLS-1$
262 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
263 } else if (left
.equals("func")) { //$NON-NLS-1$
264 func_name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
265 } else if (left
.equals("ip")) { //$NON-NLS-1$
266 ip
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText().substring(2),16); // trim the 0x
267 } else if (left
.equals("file")) { //$NON-NLS-1$
268 file_name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
269 } else if (left
.equals("line")) { //$NON-NLS-1$
270 line_number
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
273 trace
.addCallsite(name
, func_name
, ip
,file_name
, line_number
);
276 private void parseEnvironment(CommonTree environment
) {
277 List
<CommonTree
> children
= environment
.getChildren();
278 for (CommonTree child
: children
) {
281 left
= child
.getChild(0).getChild(0).getChild(0).getText();
282 right
= child
.getChild(1).getChild(0).getChild(0).getText();
283 trace
.addEnvironmentVar(left
, right
);
287 private void parseClock(CommonTree clock
) {
288 List
<CommonTree
> children
= clock
.getChildren();
289 CTFClock ctfClock
= new CTFClock();
290 for (CommonTree child
: children
) {
291 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
292 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
293 final int type
= value
.getType();
295 case CTFParser
.INTEGER
:
296 case CTFParser
.DECIMAL_LITERAL
:
298 * Not a pretty hack, this is to make sure that there is no
299 * number overflow due to 63 bit integers. The offset should
300 * only really be an issue in the year 2262. the tracer in C/ASM
301 * can write an offset in an unsigned 64 bit long. In java, the
302 * last bit, being set to 1 will be read as a negative number,
303 * but since it is too big a positive it will throw an
304 * exception. this will happen in 2^63 ns from 1970. Therefore
305 * 293 years from 1970
309 numValue
= Long
.parseLong(value
.getText());
310 } catch (Exception e
) {
311 numValue
= 1330938566783103277L;
313 ctfClock
.addAttribute(key
, numValue
);
316 ctfClock
.addAttribute(key
, value
.getText());
320 String NameValue
= ctfClock
.getName();
321 trace
.addClock(NameValue
, ctfClock
);
324 private void parseTrace(CommonTree traceNode
) throws ParseException
{
326 List
<CommonTree
> children
= traceNode
.getChildren();
327 if (children
== null) {
328 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
333 for (CommonTree child
: children
) {
334 switch (child
.getType()) {
335 case CTFParser
.TYPEALIAS
:
336 parseTypealias(child
);
338 case CTFParser
.TYPEDEF
:
341 case CTFParser
.CTF_EXPRESSION_TYPE
:
342 case CTFParser
.CTF_EXPRESSION_VAL
:
343 parseTraceDeclaration(child
);
346 childTypeError(child
);
352 * If trace byte order was not specified and not using packet based
355 if (trace
.getByteOrder() == null) {
356 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
362 private void parseTraceDeclaration(CommonTree traceDecl
)
363 throws ParseException
{
365 /* There should be a left and right */
367 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
368 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
370 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
372 if (!isUnaryString(leftStrings
.get(0))) {
373 throw new ParseException(
374 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
377 String left
= concatenateUnaryStrings(leftStrings
);
379 if (left
.equals(CTFStrings
.MAJOR
)) {
380 if (trace
.majortIsSet()) {
381 throw new ParseException("major is already set"); //$NON-NLS-1$
384 trace
.setMajor(getMajorOrMinor(rightNode
));
385 } else if (left
.equals(CTFStrings
.MINOR
)) {
386 if (trace
.minorIsSet()) {
387 throw new ParseException("minor is already set"); //$NON-NLS-1$
390 trace
.setMinor(getMajorOrMinor(rightNode
));
391 } else if (left
.equals(CTFStrings
.UUID_STRING
)) {
392 UUID uuid
= getUUID(rightNode
);
395 * If uuid was already set by a metadata packet, compare it to see
398 if (trace
.UUIDIsSet()) {
399 if (trace
.getUUID().compareTo(uuid
) != 0) {
400 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
401 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
407 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
408 ByteOrder byteOrder
= getByteOrder(rightNode
);
411 * If byte order was already set by a metadata packet, compare it to
414 if (trace
.getByteOrder() != null) {
415 if (trace
.getByteOrder() != byteOrder
) {
416 throw new ParseException(
417 "Endianness mismatch. Magic number says " //$NON-NLS-1$
418 + trace
.getByteOrder()
419 + " but metadata says " + byteOrder
); //$NON-NLS-1$
422 trace
.setByteOrder(byteOrder
);
423 final DeclarationScope parentScope
= scope
.getParentScope();
424 String types
[] = parentScope
.getTypeNames();
426 for (String type
: types
) {
427 IDeclaration d
= parentScope
.lookupType(type
);
428 if (d
instanceof IntegerDeclaration
) {
429 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
430 } else if (d
instanceof StructDeclaration
) {
431 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
435 } else if (left
.equals(CTFStrings
.PACKET_HEADER
)) {
436 if (trace
.packetHeaderIsSet()) {
437 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
440 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
442 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
443 throw new ParseException(
444 "packet.header expects a type specifier"); //$NON-NLS-1$
447 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
448 typeSpecifier
, null);
450 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
451 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
454 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
456 throw new ParseException("Unknown trace attribute : " + left
); //$NON-NLS-1$
460 private static void addByteOrder(ByteOrder byteOrder
,
461 final DeclarationScope parentScope
, String name
,
462 IntegerDeclaration decl
) throws ParseException
{
464 if (decl
.getByteOrder() == null) {
465 IntegerDeclaration newI
;
466 newI
= new IntegerDeclaration(decl
.getLength(), decl
.isSigned(),
467 decl
.getBase(), byteOrder
, decl
.getEncoding(),
468 decl
.getClock(), decl
.getAlignment());
469 parentScope
.replaceType(name
, newI
);
473 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
474 ByteOrder byteOrder
) throws ParseException
{
476 for (String s
: sd
.getFieldsList()) {
477 IDeclaration d
= sd
.getFields().get(s
);
479 if (d
instanceof StructDeclaration
) {
480 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
482 } else if (d
instanceof VariantDeclaration
) {
483 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
485 } else if (d
instanceof IntegerDeclaration
) {
486 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
487 if (decl
.getByteOrder() == null) {
488 IntegerDeclaration newI
;
489 newI
= new IntegerDeclaration(decl
.getLength(),
490 decl
.isSigned(), decl
.getBase(), byteOrder
,
491 decl
.getEncoding(), decl
.getClock(),
492 decl
.getAlignment());
493 sd
.getFields().put(s
, newI
);
499 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
500 ByteOrder byteOrder
) throws ParseException
{
502 for (String s
: vd
.getFields().keySet()) {
503 IDeclaration d
= vd
.getFields().get(s
);
505 if (d
instanceof StructDeclaration
) {
506 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
508 } else if (d
instanceof IntegerDeclaration
) {
509 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
510 IntegerDeclaration newI
;
511 newI
= new IntegerDeclaration(decl
.getLength(),
512 decl
.isSigned(), decl
.getBase(), byteOrder
,
513 decl
.getEncoding(), decl
.getClock(),
514 decl
.getAlignment());
515 vd
.getFields().put(s
, newI
);
520 private void parseStream(CommonTree streamNode
) throws ParseException
{
522 Stream stream
= new Stream(trace
);
524 List
<CommonTree
> children
= streamNode
.getChildren();
525 if (children
== null) {
526 throw new ParseException("Empty stream block"); //$NON-NLS-1$
531 for (CommonTree child
: children
) {
532 switch (child
.getType()) {
533 case CTFParser
.TYPEALIAS
:
534 parseTypealias(child
);
536 case CTFParser
.TYPEDEF
:
539 case CTFParser
.CTF_EXPRESSION_TYPE
:
540 case CTFParser
.CTF_EXPRESSION_VAL
:
541 parseStreamDeclaration(child
, stream
);
544 childTypeError(child
);
549 if (stream
.isIdSet()) {
550 if (!trace
.packetHeaderIsSet()
551 || !trace
.getPacketHeader().hasField(CTFStrings
.STREAM_ID
)) {
552 throw new ParseException(
553 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
557 trace
.addStream(stream
);
562 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
563 throws ParseException
{
565 /* There should be a left and right */
567 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
568 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
570 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
572 if (!isUnaryString(leftStrings
.get(0))) {
573 throw new ParseException(
574 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
577 String left
= concatenateUnaryStrings(leftStrings
);
579 if (left
.equals(CTFStrings
.ID
)) {
580 if (stream
.isIdSet()) {
581 throw new ParseException("stream id already defined"); //$NON-NLS-1$
584 long streamID
= getStreamID(rightNode
);
586 stream
.setId(streamID
);
587 } else if (left
.equals(CTFStrings
.EVENT_HEADER
)) {
588 if (stream
.isEventHeaderSet()) {
589 throw new ParseException("event.header already defined"); //$NON-NLS-1$
592 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
594 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
595 throw new ParseException(
596 "event.header expects a type specifier"); //$NON-NLS-1$
599 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
600 typeSpecifier
, null);
602 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
603 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
606 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
607 } else if (left
.equals(CTFStrings
.EVENT_CONTEXT
)) {
608 if (stream
.isEventContextSet()) {
609 throw new ParseException("event.context already defined"); //$NON-NLS-1$
612 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
614 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
615 throw new ParseException(
616 "event.context expects a type specifier"); //$NON-NLS-1$
619 IDeclaration eventContextDecl
= parseTypeSpecifierList(
620 typeSpecifier
, null);
622 if (!(eventContextDecl
instanceof StructDeclaration
)) {
623 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
626 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
627 } else if (left
.equals(CTFStrings
.PACKET_CONTEXT
)) {
628 if (stream
.isPacketContextSet()) {
629 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
632 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
634 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
635 throw new ParseException(
636 "packet.context expects a type specifier"); //$NON-NLS-1$
639 IDeclaration packetContextDecl
= parseTypeSpecifierList(
640 typeSpecifier
, null);
642 if (!(packetContextDecl
instanceof StructDeclaration
)) {
643 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
646 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
648 throw new ParseException("Unknown stream attribute : " + left
); //$NON-NLS-1$
652 private void parseEvent(CommonTree eventNode
) throws ParseException
{
654 List
<CommonTree
> children
= eventNode
.getChildren();
655 if (children
== null) {
656 throw new ParseException("Empty event block"); //$NON-NLS-1$
659 EventDeclaration event
= new EventDeclaration();
663 for (CommonTree child
: children
) {
664 switch (child
.getType()) {
665 case CTFParser
.TYPEALIAS
:
666 parseTypealias(child
);
668 case CTFParser
.TYPEDEF
:
671 case CTFParser
.CTF_EXPRESSION_TYPE
:
672 case CTFParser
.CTF_EXPRESSION_VAL
:
673 parseEventDeclaration(child
, event
);
676 childTypeError(child
);
681 if (!event
.nameIsSet()) {
682 throw new ParseException("Event name not set"); //$NON-NLS-1$
686 * If the event did not specify a stream, then the trace must be single
689 if (!event
.streamIsSet()) {
690 if (trace
.nbStreams() > 1) {
691 throw new ParseException(
692 "Event without stream_id with more than one stream"); //$NON-NLS-1$
696 * If the event did not specify a stream, the only existing stream
697 * must not have an id. Note: That behavior could be changed, it
698 * could be possible to just get the only existing stream, whatever
701 Stream stream
= trace
.getStream(null);
703 if (stream
!= null) {
704 event
.setStream(stream
);
706 throw new ParseException(
707 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
712 * Add the event to the stream.
714 event
.getStream().addEvent(event
);
719 private void parseEventDeclaration(CommonTree eventDecl
,
720 EventDeclaration event
) throws ParseException
{
722 /* There should be a left and right */
724 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
725 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
727 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
729 if (!isUnaryString(leftStrings
.get(0))) {
730 throw new ParseException(
731 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
734 String left
= concatenateUnaryStrings(leftStrings
);
736 if (left
.equals(CTFStrings
.NAME2
)) {
737 if (event
.nameIsSet()) {
738 throw new ParseException("name already defined"); //$NON-NLS-1$
741 String name
= getEventName(rightNode
);
744 } else if (left
.equals(CTFStrings
.ID
)) {
745 if (event
.idIsSet()) {
746 throw new ParseException("id already defined"); //$NON-NLS-1$
749 long id
= getEventID(rightNode
);
752 } else if (left
.equals(CTFStrings
.STREAM_ID
)) {
753 if (event
.streamIsSet()) {
754 throw new ParseException("stream id already defined"); //$NON-NLS-1$
757 long streamId
= getStreamID(rightNode
);
759 Stream stream
= trace
.getStream(streamId
);
761 if (stream
== null) {
762 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
765 event
.setStream(stream
);
766 } else if (left
.equals(CTFStrings
.CONTEXT
)) {
767 if (event
.contextIsSet()) {
768 throw new ParseException("context already defined"); //$NON-NLS-1$
771 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
773 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
774 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
777 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
780 if (!(contextDecl
instanceof StructDeclaration
)) {
781 throw new ParseException("context expects a struct"); //$NON-NLS-1$
784 event
.setContext((StructDeclaration
) contextDecl
);
785 } else if (left
.equals(CTFStrings
.FIELDS_STRING
)) {
786 if (event
.fieldsIsSet()) {
787 throw new ParseException("fields already defined"); //$NON-NLS-1$
790 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
792 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
793 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
796 IDeclaration fieldsDecl
;
797 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
799 if (!(fieldsDecl
instanceof StructDeclaration
)) {
800 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
803 * The underscores in the event names. These underscores were added
804 * by the LTTng tracer.
806 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
807 event
.setFields(fields
);
808 } else if (left
.equals(CTFStrings
.LOGLEVEL2
)) {
809 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
810 event
.setLogLevel(logLevel
);
812 /* Custom event attribute, we'll add it to the attributes map */
813 String right
= parseUnaryString((CommonTree
) rightNode
.getChild(0));
814 event
.setCustomAttribute(left
, right
);
819 * Parses a declaration at the root level.
822 * The declaration subtree.
823 * @throws ParseException
825 private void parseRootDeclaration(CommonTree declaration
)
826 throws ParseException
{
828 List
<CommonTree
> children
= declaration
.getChildren();
830 for (CommonTree child
: children
) {
831 switch (child
.getType()) {
832 case CTFParser
.TYPEDEF
:
835 case CTFParser
.TYPEALIAS
:
836 parseTypealias(child
);
838 case CTFParser
.TYPE_SPECIFIER_LIST
:
839 parseTypeSpecifierList(child
, null);
842 childTypeError(child
);
848 * Parses a typealias node. It parses the target, the alias, and registers
849 * the type in the current scope.
853 * @throws ParseException
855 private void parseTypealias(CommonTree typealias
) throws ParseException
{
857 List
<CommonTree
> children
= typealias
.getChildren();
859 CommonTree target
= null;
860 CommonTree alias
= null;
862 for (CommonTree child
: children
) {
863 switch (child
.getType()) {
864 case CTFParser
.TYPEALIAS_TARGET
:
867 case CTFParser
.TYPEALIAS_ALIAS
:
871 childTypeError(child
);
877 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
879 if (targetDeclaration
instanceof VariantDeclaration
) {
880 if (((VariantDeclaration
) targetDeclaration
).isTagged()) {
881 throw new ParseException(
882 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
886 String aliasString
= parseTypealiasAlias(alias
);
888 getCurrentScope().registerType(aliasString
, targetDeclaration
);
892 * Parses the target part of a typealias and gets the corresponding
896 * A TYPEALIAS_TARGET node.
897 * @return The corresponding declaration.
898 * @throws ParseException
900 private IDeclaration
parseTypealiasTarget(CommonTree target
)
901 throws ParseException
{
903 List
<CommonTree
> children
= target
.getChildren();
905 CommonTree typeSpecifierList
= null;
906 CommonTree typeDeclaratorList
= null;
907 CommonTree typeDeclarator
= null;
908 StringBuilder identifierSB
= new StringBuilder();
910 for (CommonTree child
: children
) {
911 switch (child
.getType()) {
912 case CTFParser
.TYPE_SPECIFIER_LIST
:
913 typeSpecifierList
= child
;
915 case CTFParser
.TYPE_DECLARATOR_LIST
:
916 typeDeclaratorList
= child
;
919 childTypeError(child
);
925 if (typeDeclaratorList
!= null) {
927 * Only allow one declarator
929 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
930 * otherwise the new type puint8_t would maps to two different
933 if (typeDeclaratorList
.getChildCount() != 1) {
934 throw new ParseException(
935 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
938 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
941 /* Parse the target type and get the declaration */
942 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
943 typeSpecifierList
, identifierSB
);
946 * We don't allow identifier in the target
948 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
951 if (identifierSB
.length() > 0) {
952 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
953 + ") not expected in the typealias target"); //$NON-NLS-1$
956 return targetDeclaration
;
960 * Parses the alias part of a typealias. It parses the underlying specifier
961 * list and declarator and creates the string representation that will be
962 * used to register the type.
965 * A TYPEALIAS_ALIAS node.
966 * @return The string representation of the alias.
967 * @throws ParseException
969 private static String
parseTypealiasAlias(CommonTree alias
)
970 throws ParseException
{
972 List
<CommonTree
> children
= alias
.getChildren();
974 CommonTree typeSpecifierList
= null;
975 CommonTree typeDeclaratorList
= null;
976 CommonTree typeDeclarator
= null;
977 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
979 for (CommonTree child
: children
) {
980 switch (child
.getType()) {
981 case CTFParser
.TYPE_SPECIFIER_LIST
:
982 typeSpecifierList
= child
;
984 case CTFParser
.TYPE_DECLARATOR_LIST
:
985 typeDeclaratorList
= child
;
988 childTypeError(child
);
993 /* If there is a type declarator list, extract the pointers */
994 if (typeDeclaratorList
!= null) {
996 * Only allow one declarator
998 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
1000 if (typeDeclaratorList
.getChildCount() != 1) {
1001 throw new ParseException(
1002 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1005 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1007 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
1009 for (CommonTree child
: typeDeclaratorChildren
) {
1010 switch (child
.getType()) {
1011 case CTFParser
.POINTER
:
1012 pointers
.add(child
);
1014 case CTFParser
.IDENTIFIER
:
1015 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1016 + ") not expected in the typealias target"); //$NON-NLS-1$
1019 childTypeError(child
);
1025 return createTypeDeclarationString(typeSpecifierList
, pointers
);
1029 * Parses a typedef node. This creates and registers a new declaration for
1030 * each declarator found in the typedef.
1034 * @throws ParseException
1035 * If there is an error creating the declaration.
1037 private void parseTypedef(CommonTree typedef
) throws ParseException
{
1039 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1041 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1043 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1045 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1046 StringBuilder identifierSB
= new StringBuilder();
1048 IDeclaration type_declaration
= parseTypeDeclarator(
1049 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1051 if (type_declaration
instanceof VariantDeclaration
) {
1052 if (((VariantDeclaration
) type_declaration
).isTagged()) {
1053 throw new ParseException(
1054 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1058 getCurrentScope().registerType(identifierSB
.toString(),
1064 * Parses a pair type declarator / type specifier list and returns the
1065 * corresponding declaration. If it is present, it also writes the
1066 * identifier of the declarator in the given {@link StringBuilder}.
1068 * @param typeDeclarator
1069 * A TYPE_DECLARATOR node.
1070 * @param typeSpecifierList
1071 * A TYPE_SPECIFIER_LIST node.
1072 * @param identifierSB
1073 * A StringBuilder that will receive the identifier found in the
1075 * @return The corresponding declaration.
1076 * @throws ParseException
1077 * If there is an error finding or creating the declaration.
1079 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1080 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1081 throws ParseException
{
1083 IDeclaration declaration
= null;
1084 List
<CommonTree
> children
= null;
1085 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1086 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1087 CommonTree identifier
= null;
1089 /* Separate the tokens by type */
1090 if (typeDeclarator
!= null) {
1091 children
= typeDeclarator
.getChildren();
1092 for (CommonTree child
: children
) {
1094 switch (child
.getType()) {
1095 case CTFParser
.POINTER
:
1096 pointers
.add(child
);
1098 case CTFParser
.IDENTIFIER
:
1101 case CTFParser
.LENGTH
:
1105 childTypeError(child
);
1113 * Parse the type specifier list, which is the "base" type. For example,
1114 * it would be int in int a[3][len].
1116 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1119 * Each length subscript means that we must create a nested array or
1120 * sequence. For example, int a[3][len] means that we have an array of 3
1121 * (sequences of length 'len' of (int)).
1123 if (lengths
.size() > 0) {
1124 /* We begin at the end */
1125 Collections
.reverse(lengths
);
1127 for (CommonTree length
: lengths
) {
1129 * By looking at the first expression, we can determine whether
1130 * it is an array or a sequence.
1132 List
<CommonTree
> lengthChildren
= length
.getChildren();
1134 CommonTree first
= lengthChildren
.get(0);
1135 if (isUnaryInteger(first
)) {
1137 int arrayLength
= (int) parseUnaryInteger(first
);
1139 if (arrayLength
< 1) {
1140 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1143 /* Create the array declaration. */
1144 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1145 } else if (isUnaryString(first
)) {
1147 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1149 /* Create the sequence declaration. */
1150 declaration
= new SequenceDeclaration(lengthName
,
1153 childTypeError(first
);
1158 if (identifier
!= null) {
1159 identifierSB
.append(identifier
.getText());
1166 * Parses a type specifier list and returns the corresponding declaration.
1168 * @param typeSpecifierList
1169 * A TYPE_SPECIFIER_LIST node.
1170 * @param pointerList
1171 * A list of POINTER nodes that apply to the specified type.
1172 * @return The corresponding declaration.
1173 * @throws ParseException
1174 * If the type has not been defined or if there is an error
1175 * creating the declaration.
1177 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1178 List
<CommonTree
> pointerList
) throws ParseException
{
1179 IDeclaration declaration
= null;
1182 * By looking at the first element of the type specifier list, we can
1183 * determine which type it belongs to.
1185 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1187 switch (firstChild
.getType()) {
1188 case CTFParser
.FLOATING_POINT
:
1189 declaration
= parseFloat(firstChild
);
1191 case CTFParser
.INTEGER
:
1192 declaration
= parseInteger(firstChild
);
1194 case CTFParser
.STRING
:
1195 declaration
= parseString(firstChild
);
1197 case CTFParser
.STRUCT
:
1198 declaration
= parseStruct(firstChild
);
1200 case CTFParser
.VARIANT
:
1201 declaration
= parseVariant(firstChild
);
1203 case CTFParser
.ENUM
:
1204 declaration
= parseEnum(firstChild
);
1206 case CTFParser
.IDENTIFIER
:
1207 case CTFParser
.FLOATTOK
:
1208 case CTFParser
.INTTOK
:
1209 case CTFParser
.LONGTOK
:
1210 case CTFParser
.SHORTTOK
:
1211 case CTFParser
.SIGNEDTOK
:
1212 case CTFParser
.UNSIGNEDTOK
:
1213 case CTFParser
.CHARTOK
:
1214 case CTFParser
.DOUBLETOK
:
1215 case CTFParser
.VOIDTOK
:
1216 case CTFParser
.BOOLTOK
:
1217 case CTFParser
.COMPLEXTOK
:
1218 case CTFParser
.IMAGINARYTOK
:
1219 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1222 childTypeError(firstChild
);
1228 private IDeclaration
parseFloat(CommonTree floatingPoint
)
1229 throws ParseException
{
1231 List
<CommonTree
> children
= floatingPoint
.getChildren();
1234 * If the integer has no attributes, then it is missing the size
1235 * attribute which is required
1237 if (children
== null) {
1238 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1241 /* The return value */
1242 FloatDeclaration floatDeclaration
= null;
1243 ByteOrder byteOrder
= trace
.getByteOrder();
1248 /* Iterate on all integer children */
1249 for (CommonTree child
: children
) {
1250 switch (child
.getType()) {
1251 case CTFParser
.CTF_EXPRESSION_VAL
:
1253 * An assignment expression must have 2 children, left and right
1256 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1257 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1259 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1261 if (!isUnaryString(leftStrings
.get(0))) {
1262 throw new ParseException(
1263 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1265 String left
= concatenateUnaryStrings(leftStrings
);
1267 if (left
.equals(CTFStrings
.EXP_DIG
)) {
1268 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1269 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1270 byteOrder
= getByteOrder(rightNode
);
1271 } else if (left
.equals(CTFStrings
.MANT_DIG
)) {
1272 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1273 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1274 alignment
= getAlignment(rightNode
);
1276 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1281 childTypeError(child
);
1285 int size
= mantissa
+ exponent
;
1287 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1290 if (alignment
== 0) {
1291 if ((size
% 8) == 0) {
1298 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1300 return floatDeclaration
;
1305 * Parses a type specifier list as a user-declared type.
1307 * @param typeSpecifierList
1308 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1309 * @param pointerList
1310 * A list of POINTER nodes that apply to the type specified in
1311 * typeSpecifierList.
1312 * @return The corresponding declaration.
1313 * @throws ParseException
1314 * If the type does not exist (has not been found).
1316 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1317 List
<CommonTree
> pointerList
) throws ParseException
{
1318 /* Create the string representation of the type declaration */
1319 String typeStringRepresentation
= createTypeDeclarationString(
1320 typeSpecifierList
, pointerList
);
1322 /* Use the string representation to search the type in the current scope */
1323 IDeclaration decl
= getCurrentScope().rlookupType(
1324 typeStringRepresentation
);
1327 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1328 + " has not been defined."); //$NON-NLS-1$
1335 * Parses an integer declaration node.
1339 * @return The corresponding integer declaration.
1340 * @throws ParseException
1342 private IntegerDeclaration
parseInteger(CommonTree integer
)
1343 throws ParseException
{
1345 List
<CommonTree
> children
= integer
.getChildren();
1348 * If the integer has no attributes, then it is missing the size
1349 * attribute which is required
1351 if (children
== null) {
1352 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1355 /* The return value */
1356 IntegerDeclaration integerDeclaration
= null;
1357 boolean signed
= false;
1358 ByteOrder byteOrder
= trace
.getByteOrder();
1362 String clock
= null;
1364 Encoding encoding
= Encoding
.NONE
;
1366 /* Iterate on all integer children */
1367 for (CommonTree child
: children
) {
1368 switch (child
.getType()) {
1369 case CTFParser
.CTF_EXPRESSION_VAL
:
1371 * An assignment expression must have 2 children, left and right
1374 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1375 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1377 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1379 if (!isUnaryString(leftStrings
.get(0))) {
1380 throw new ParseException(
1381 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1383 String left
= concatenateUnaryStrings(leftStrings
);
1385 if (left
.equals("signed")) { //$NON-NLS-1$
1386 signed
= getSigned(rightNode
);
1387 } else if (left
.equals(CTFStrings
.BYTE_ORDER
)) {
1388 byteOrder
= getByteOrder(rightNode
);
1389 } else if (left
.equals("size")) { //$NON-NLS-1$
1390 size
= getSize(rightNode
);
1391 } else if (left
.equals(CTFStrings
.ALIGN
)) {
1392 alignment
= getAlignment(rightNode
);
1393 } else if (left
.equals("base")) { //$NON-NLS-1$
1394 base
= getBase(rightNode
);
1395 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1396 encoding
= getEncoding(rightNode
);
1397 } else if (left
.equals("map")) { //$NON-NLS-1$
1398 clock
= getClock(rightNode
);
1400 throw new ParseException(
1401 "Integer: unknown attribute " + left
); //$NON-NLS-1$
1406 childTypeError(child
);
1412 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1415 if (alignment
== 0) {
1416 if ((size
% 8) == 0) {
1423 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1424 byteOrder
, encoding
, clock
, alignment
);
1426 return integerDeclaration
;
1429 private static String
getClock(CommonTree rightNode
) {
1430 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1433 private static StringDeclaration
parseString(CommonTree string
)
1434 throws ParseException
{
1436 List
<CommonTree
> children
= string
.getChildren();
1437 StringDeclaration stringDeclaration
= null;
1439 if (children
== null) {
1440 stringDeclaration
= new StringDeclaration();
1442 Encoding encoding
= Encoding
.UTF8
;
1443 for (CommonTree child
: children
) {
1444 switch (child
.getType()) {
1445 case CTFParser
.CTF_EXPRESSION_VAL
:
1447 * An assignment expression must have 2 children, left and
1451 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1452 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1454 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1456 if (!isUnaryString(leftStrings
.get(0))) {
1457 throw new ParseException(
1458 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1460 String left
= concatenateUnaryStrings(leftStrings
);
1462 if (left
.equals("encoding")) { //$NON-NLS-1$
1463 encoding
= getEncoding(rightNode
);
1465 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1471 childTypeError(child
);
1476 stringDeclaration
= new StringDeclaration(encoding
);
1479 return stringDeclaration
;
1483 * Parses a struct declaration and returns the corresponding declaration.
1487 * @return The corresponding struct declaration.
1488 * @throws ParseException
1490 private StructDeclaration
parseStruct(CommonTree struct
)
1491 throws ParseException
{
1493 List
<CommonTree
> children
= struct
.getChildren();
1495 /* The return value */
1496 StructDeclaration structDeclaration
= null;
1499 String structName
= null;
1500 boolean hasName
= false;
1503 CommonTree structBody
= null;
1504 boolean hasBody
= false;
1507 long structAlign
= 0;
1509 /* Loop on all children and identify what we have to work with. */
1510 for (CommonTree child
: children
) {
1511 switch (child
.getType()) {
1512 case CTFParser
.STRUCT_NAME
: {
1515 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1517 structName
= structNameIdentifier
.getText();
1521 case CTFParser
.STRUCT_BODY
: {
1528 case CTFParser
.ALIGN
: {
1529 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1531 structAlign
= getAlignment(structAlignExpression
);
1536 childTypeError(child
);
1543 * If a struct has just a body and no name (just like the song,
1544 * "A Struct With No Name" by America (sorry for that...)), it's a
1545 * definition of a new type, so we create the type declaration and
1546 * return it. We can't add it to the declaration scope since there is no
1547 * name, but that's what we want because it won't be possible to use it
1548 * again to declare another field.
1550 * If it has just a name, we look it up in the declaration scope and
1551 * return the associated declaration. If it is not found in the
1552 * declaration scope, it means that a struct with that name has not been
1553 * declared, which is an error.
1555 * If it has both, then we create the type declaration and register it
1556 * to the current scope.
1558 * If it has none, then what are we doing here ?
1562 * If struct has a name, check if already defined in the current
1565 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1566 throw new ParseException("struct " + structName
//$NON-NLS-1$
1567 + " already defined."); //$NON-NLS-1$
1569 /* Create the declaration */
1570 structDeclaration
= new StructDeclaration(structAlign
);
1572 /* Parse the body */
1573 parseStructBody(structBody
, structDeclaration
);
1575 /* If struct has name, add it to the current scope. */
1577 getCurrentScope().registerStruct(structName
, structDeclaration
);
1579 } else /* !hasBody */{
1581 /* Name and !body */
1583 /* Lookup the name in the current scope. */
1584 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1587 * If not found, it means that a struct with such name has not
1590 if (structDeclaration
== null) {
1591 throw new ParseException("struct " + structName
//$NON-NLS-1$
1592 + " is not defined"); //$NON-NLS-1$
1595 /* !Name and !body */
1597 /* We can't do anything with that. */
1598 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1602 return structDeclaration
;
1606 * Parses a struct body, adding the fields to specified structure
1610 * A STRUCT_BODY node.
1611 * @param structDeclaration
1612 * The struct declaration.
1613 * @throws ParseException
1615 private void parseStructBody(CommonTree structBody
,
1616 StructDeclaration structDeclaration
) throws ParseException
{
1618 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1621 * If structDeclaration is null, structBody has no children and the
1622 * struct body is empty.
1624 if (structDeclarations
!= null) {
1627 for (CommonTree declarationNode
: structDeclarations
) {
1628 switch (declarationNode
.getType()) {
1629 case CTFParser
.TYPEALIAS
:
1630 parseTypealias(declarationNode
);
1632 case CTFParser
.TYPEDEF
:
1633 parseTypedef(declarationNode
);
1635 case CTFParser
.SV_DECLARATION
:
1636 parseStructDeclaration(declarationNode
, structDeclaration
);
1639 childTypeError(declarationNode
);
1648 * Parses a declaration found in a struct.
1650 * @param declaration
1651 * A SV_DECLARATION node.
1653 * A struct declaration. (I know, little name clash here...)
1654 * @throws ParseException
1656 private void parseStructDeclaration(CommonTree declaration
,
1657 StructDeclaration struct
) throws ParseException
{
1660 /* Get the type specifier list node */
1661 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1663 /* Get the type declarator list node */
1664 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1666 /* Get the type declarator list */
1667 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1670 * For each type declarator, parse the declaration and add a field to
1673 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1675 StringBuilder identifierSB
= new StringBuilder();
1677 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1678 typeSpecifierListNode
, identifierSB
);
1679 String fieldName
= identifierSB
.toString();
1681 if (struct
.hasField(fieldName
)) {
1682 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1686 struct
.addField(fieldName
, decl
);
1692 * Parses an enum declaration and returns the corresponding declaration.
1696 * @return The corresponding enum declaration.
1697 * @throws ParseException
1699 private EnumDeclaration
parseEnum(CommonTree _enum
) throws ParseException
{
1701 List
<CommonTree
> children
= _enum
.getChildren();
1703 /* The return value */
1704 EnumDeclaration enumDeclaration
= null;
1707 String enumName
= null;
1710 CommonTree enumBody
= null;
1712 /* Container type */
1713 IntegerDeclaration containerTypeDeclaration
= null;
1715 /* Loop on all children and identify what we have to work with. */
1716 for (CommonTree child
: children
) {
1717 switch (child
.getType()) {
1718 case CTFParser
.ENUM_NAME
: {
1719 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1721 enumName
= enumNameIdentifier
.getText();
1725 case CTFParser
.ENUM_BODY
: {
1731 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1733 containerTypeDeclaration
= parseEnumContainerType(child
);
1738 childTypeError(child
);
1744 * If the container type has not been defined explicitly, we assume it
1747 if (containerTypeDeclaration
== null) {
1748 IDeclaration enumDecl
;
1750 * it could be because the enum was already declared.
1752 if (enumName
!= null) {
1753 enumDecl
= getCurrentScope().rlookupEnum(enumName
);
1754 if (enumDecl
!= null) {
1755 return (EnumDeclaration
) enumDecl
;
1759 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1762 throw new ParseException(
1763 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1764 } else if (!(decl
instanceof IntegerDeclaration
)) {
1765 throw new ParseException(
1766 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1769 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1773 * If it has a body, it's a new declaration, otherwise it's a reference
1774 * to an existing declaration. Same logic as struct.
1776 if (enumBody
!= null) {
1778 * If enum has a name, check if already defined in the current
1781 if ((enumName
!= null)
1782 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1783 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1784 + " already defined"); //$NON-NLS-1$
1787 /* Create the declaration */
1788 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1790 /* Parse the body */
1791 parseEnumBody(enumBody
, enumDeclaration
);
1793 /* If the enum has name, add it to the current scope. */
1794 if (enumName
!= null) {
1795 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1798 if (enumName
!= null) {
1799 /* Name and !body */
1801 /* Lookup the name in the current scope. */
1802 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1805 * If not found, it means that an enum with such name has not
1808 if (enumDeclaration
== null) {
1809 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1810 + " is not defined"); //$NON-NLS-1$
1813 /* !Name and !body */
1814 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1818 return enumDeclaration
;
1823 * Parses an enum body, adding the enumerators to the specified enum
1827 * An ENUM_BODY node.
1828 * @param enumDeclaration
1829 * The enum declaration.
1830 * @throws ParseException
1832 private void parseEnumBody(CommonTree enumBody
,
1833 EnumDeclaration enumDeclaration
) throws ParseException
{
1835 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1836 /* enum body can't be empty (unlike struct). */
1841 * Start at -1, so that if the first enumrator has no explicit value, it
1846 for (CommonTree enumerator
: enumerators
) {
1847 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1856 * Parses an enumerator node and adds an enumerator declaration to an
1857 * enumeration declaration.
1859 * The high value of the range of the last enumerator is needed in case the
1860 * current enumerator does not specify its value.
1863 * An ENUM_ENUMERATOR node.
1864 * @param enumDeclaration
1865 * en enumeration declaration to which will be added the
1868 * The high value of the range of the last enumerator
1869 * @return The high value of the value range of the current enumerator.
1870 * @throws ParseException
1872 private static long parseEnumEnumerator(CommonTree enumerator
,
1873 EnumDeclaration enumDeclaration
, long lastHigh
)
1874 throws ParseException
{
1876 List
<CommonTree
> children
= enumerator
.getChildren();
1878 long low
= 0, high
= 0;
1879 boolean valueSpecified
= false;
1880 String label
= null;
1882 for (CommonTree child
: children
) {
1883 if (isUnaryString(child
)) {
1884 label
= parseUnaryString(child
);
1885 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1887 valueSpecified
= true;
1889 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1891 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1893 valueSpecified
= true;
1895 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1896 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1898 childTypeError(child
);
1902 if (!valueSpecified
) {
1908 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1911 if (!enumDeclaration
.add(low
, high
, label
)) {
1912 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1919 * Parses an enum container type node and returns the corresponding integer
1922 * @param enumContainerType
1923 * An ENUM_CONTAINER_TYPE node.
1924 * @return An integer declaration corresponding to the container type.
1925 * @throws ParseException
1926 * If the type does not parse correctly or if it is not an
1929 private IntegerDeclaration
parseEnumContainerType(
1930 CommonTree enumContainerType
) throws ParseException
{
1932 /* Get the child, which should be a type specifier list */
1933 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
.getChild(0);
1935 /* Parse it and get the corresponding declaration */
1936 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1938 /* If is is an integer, return it, else throw an error */
1939 if (decl
instanceof IntegerDeclaration
) {
1940 return (IntegerDeclaration
) decl
;
1942 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1945 private VariantDeclaration
parseVariant(CommonTree variant
)
1946 throws ParseException
{
1948 List
<CommonTree
> children
= variant
.getChildren();
1949 VariantDeclaration variantDeclaration
= null;
1951 boolean hasName
= false;
1952 String variantName
= null;
1954 boolean hasBody
= false;
1955 CommonTree variantBody
= null;
1957 boolean hasTag
= false;
1958 String variantTag
= null;
1960 for (CommonTree child
: children
) {
1961 switch (child
.getType()) {
1962 case CTFParser
.VARIANT_NAME
:
1966 CommonTree variantNameIdentifier
= (CommonTree
) child
.getChild(0);
1968 variantName
= variantNameIdentifier
.getText();
1971 case CTFParser
.VARIANT_TAG
:
1975 CommonTree variantTagIdentifier
= (CommonTree
) child
.getChild(0);
1977 variantTag
= variantTagIdentifier
.getText();
1980 case CTFParser
.VARIANT_BODY
:
1984 variantBody
= child
;
1988 childTypeError(child
);
1995 * If variant has a name, check if already defined in the current
1999 && (getCurrentScope().lookupVariant(variantName
) != null)) {
2000 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2001 + " already defined."); //$NON-NLS-1$
2004 /* Create the declaration */
2005 variantDeclaration
= new VariantDeclaration();
2007 /* Parse the body */
2008 parseVariantBody(variantBody
, variantDeclaration
);
2010 /* If variant has name, add it to the current scope. */
2012 getCurrentScope().registerVariant(variantName
,
2013 variantDeclaration
);
2015 } else /* !hasBody */{
2017 /* Name and !body */
2019 /* Lookup the name in the current scope. */
2020 variantDeclaration
= getCurrentScope().rlookupVariant(
2024 * If not found, it means that a struct with such name has not
2027 if (variantDeclaration
== null) {
2028 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2029 + " is not defined"); //$NON-NLS-1$
2032 /* !Name and !body */
2034 /* We can't do anything with that. */
2035 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2040 variantDeclaration
.setTag(variantTag
);
2043 return variantDeclaration
;
2046 private void parseVariantBody(CommonTree variantBody
,
2047 VariantDeclaration variantDeclaration
) throws ParseException
{
2049 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2053 for (CommonTree declarationNode
: variantDeclarations
) {
2054 switch (declarationNode
.getType()) {
2055 case CTFParser
.TYPEALIAS
:
2056 parseTypealias(declarationNode
);
2058 case CTFParser
.TYPEDEF
:
2059 parseTypedef(declarationNode
);
2061 case CTFParser
.SV_DECLARATION
:
2062 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2065 childTypeError(declarationNode
);
2073 private void parseVariantDeclaration(CommonTree declaration
,
2074 VariantDeclaration variant
) throws ParseException
{
2077 /* Get the type specifier list node */
2078 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2080 /* Get the type declarator list node */
2081 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2083 /* Get the type declarator list */
2084 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
2087 * For each type declarator, parse the declaration and add a field to
2090 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2092 StringBuilder identifierSB
= new StringBuilder();
2094 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2095 typeSpecifierListNode
, identifierSB
);
2097 if (variant
.hasField(identifierSB
.toString())) {
2098 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2099 + identifierSB
.toString());
2102 variant
.addField(identifierSB
.toString(), decl
);
2107 * Creates the string representation of a type declaration (type specifier
2110 * @param typeSpecifierList
2111 * A TYPE_SPECIFIER_LIST node.
2113 * A list of POINTER nodes.
2114 * @return The string representation.
2115 * @throws ParseException
2117 private static String
createTypeDeclarationString(
2118 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2119 throws ParseException
{
2120 StringBuilder sb
= new StringBuilder();
2122 createTypeSpecifierListString(typeSpecifierList
, sb
);
2123 createPointerListString(pointers
, sb
);
2125 return sb
.toString();
2129 * Creates the string representation of a list of type specifiers.
2131 * @param typeSpecifierList
2132 * A TYPE_SPECIFIER_LIST node.
2134 * A StringBuilder to which will be appended the string.
2135 * @throws ParseException
2137 private static void createTypeSpecifierListString(
2138 CommonTree typeSpecifierList
, StringBuilder sb
)
2139 throws ParseException
{
2141 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2143 boolean firstItem
= true;
2145 for (CommonTree child
: children
) {
2153 /* Append the string that represents this type specifier. */
2154 createTypeSpecifierString(child
, sb
);
2159 * Creates the string representation of a type specifier.
2161 * @param typeSpecifier
2162 * A TYPE_SPECIFIER node.
2164 * A StringBuilder to which will be appended the string.
2165 * @throws ParseException
2167 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2168 StringBuilder sb
) throws ParseException
{
2169 switch (typeSpecifier
.getType()) {
2170 case CTFParser
.FLOATTOK
:
2171 case CTFParser
.INTTOK
:
2172 case CTFParser
.LONGTOK
:
2173 case CTFParser
.SHORTTOK
:
2174 case CTFParser
.SIGNEDTOK
:
2175 case CTFParser
.UNSIGNEDTOK
:
2176 case CTFParser
.CHARTOK
:
2177 case CTFParser
.DOUBLETOK
:
2178 case CTFParser
.VOIDTOK
:
2179 case CTFParser
.BOOLTOK
:
2180 case CTFParser
.COMPLEXTOK
:
2181 case CTFParser
.IMAGINARYTOK
:
2182 case CTFParser
.CONSTTOK
:
2183 case CTFParser
.IDENTIFIER
:
2184 sb
.append(typeSpecifier
.getText());
2186 case CTFParser
.STRUCT
: {
2187 CommonTree structName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2188 if (structName
== null) {
2189 throw new ParseException(
2190 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2193 CommonTree structNameIdentifier
= (CommonTree
) structName
.getChild(0);
2195 sb
.append(structNameIdentifier
.getText());
2198 case CTFParser
.VARIANT
: {
2199 CommonTree variantName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2200 if (variantName
== null) {
2201 throw new ParseException(
2202 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2205 CommonTree variantNameIdentifier
= (CommonTree
) variantName
.getChild(0);
2207 sb
.append(variantNameIdentifier
.getText());
2210 case CTFParser
.ENUM
: {
2211 CommonTree enumName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.ENUM_NAME
);
2212 if (enumName
== null) {
2213 throw new ParseException(
2214 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2217 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2219 sb
.append(enumNameIdentifier
.getText());
2222 case CTFParser
.FLOATING_POINT
:
2223 case CTFParser
.INTEGER
:
2224 case CTFParser
.STRING
:
2225 throw new ParseException(
2226 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2229 childTypeError(typeSpecifier
);
2235 * Creates the string representation of a list of pointers.
2237 * @param pointerList
2238 * A list of pointer nodes. If pointerList is null, this function
2241 * A stringbuilder to which will be appended the string.
2243 private static void createPointerListString(List
<CommonTree
> pointerList
,
2245 if (pointerList
== null) {
2249 for (CommonTree pointer
: pointerList
) {
2251 sb
.append(" *"); //$NON-NLS-1$
2252 if (pointer
.getChildCount() > 0) {
2254 sb
.append(" const"); //$NON-NLS-1$
2261 * The node to check.
2262 * @return True if the given node is an unary string.
2264 private static boolean isUnaryString(CommonTree node
) {
2265 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) ||
2266 (node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2271 * The node to check.
2272 * @return True if the given node is an unary integer.
2274 private static boolean isUnaryInteger(CommonTree node
) {
2275 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) ||
2276 (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) ||
2277 (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2281 * Parses a unary string node and return the string value.
2283 * @param unaryString
2284 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2285 * or UNARY_EXPRESSION_STRING_QUOTES).
2286 * @return The string value.
2289 * It would be really nice to remove the quotes earlier, such as in the
2292 private static String
parseUnaryString(CommonTree unaryString
) {
2294 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2295 String strval
= value
.getText();
2298 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2299 strval
= strval
.substring(1, strval
.length() - 1);
2306 * Parses an unary integer (dec, hex or oct).
2308 * @param unaryInteger
2309 * An unary integer node.
2310 * @return The integer value.
2311 * @throws CTFReaderException
2313 private static long parseUnaryInteger(CommonTree unaryInteger
) throws ParseException
{
2315 List
<CommonTree
> children
= unaryInteger
.getChildren();
2316 CommonTree value
= children
.get(0);
2317 String strval
= value
.getText();
2321 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2322 intval
= Long
.parseLong(strval
, 10);
2323 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2324 intval
= Long
.parseLong(strval
, 0x10);
2325 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2326 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2328 } catch (NumberFormatException e
) {
2329 throw new ParseException(e
);
2331 /* The rest of children are sign */
2332 if ((children
.size() % 2) == 0) {
2338 private static long getMajorOrMinor(CommonTree rightNode
)
2339 throws ParseException
{
2341 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2343 if (isUnaryInteger(firstChild
)) {
2344 if (rightNode
.getChildCount() > 1) {
2345 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2348 long m
= parseUnaryInteger(firstChild
);
2351 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2356 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2359 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2361 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2363 if (isUnaryString(firstChild
)) {
2364 if (rightNode
.getChildCount() > 1) {
2365 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2368 String uuidstr
= parseUnaryString(firstChild
);
2371 UUID uuid
= UUID
.fromString(uuidstr
);
2373 } catch (IllegalArgumentException e
) {
2374 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2377 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2381 * Gets the value of a "signed" integer attribute.
2385 * @return The "signed" value as a boolean.
2386 * @throws ParseException
2388 private static boolean getSigned(CommonTree rightNode
)
2389 throws ParseException
{
2391 boolean ret
= false;
2392 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2394 if (isUnaryString(firstChild
)) {
2395 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2397 if (strval
.equals(CTFStrings
.TRUE
)
2398 || strval
.equals(CTFStrings
.TRUE2
)) {
2400 } else if (strval
.equals(CTFStrings
.FALSE
)
2401 || strval
.equals(CTFStrings
.FALSE2
)) {
2404 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2405 + firstChild
.getChild(0).getText());
2407 } else if (isUnaryInteger(firstChild
)) {
2408 /* Happens if the value is something like "1234.hello" */
2409 if (rightNode
.getChildCount() > 1) {
2410 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2413 long intval
= parseUnaryInteger(firstChild
);
2417 } else if (intval
== 0) {
2420 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2421 + firstChild
.getChild(0).getText());
2424 throw new ParseException();
2431 * Gets the value of a "byte_order" integer attribute.
2435 * @return The "byte_order" value.
2436 * @throws ParseException
2438 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2440 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2442 if (isUnaryString(firstChild
)) {
2443 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2445 if (strval
.equals(CTFStrings
.LE
)) {
2446 return ByteOrder
.LITTLE_ENDIAN
;
2447 } else if (strval
.equals(CTFStrings
.BE
)
2448 || strval
.equals(CTFStrings
.NETWORK
)) {
2449 return ByteOrder
.BIG_ENDIAN
;
2450 } else if (strval
.equals(CTFStrings
.NATIVE
)) {
2451 return trace
.getByteOrder();
2453 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2456 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2460 * Determines if the given value is a valid alignment value.
2463 * The value to check.
2464 * @return True if it is valid.
2466 private static boolean isValidAlignment(long alignment
) {
2467 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2471 * Gets the value of a "size" integer attribute.
2475 * @return The "size" value.
2476 * @throws ParseException
2478 private static long getSize(CommonTree rightNode
) throws ParseException
{
2480 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2482 if (isUnaryInteger(firstChild
)) {
2483 if (rightNode
.getChildCount() > 1) {
2484 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2487 long size
= parseUnaryInteger(firstChild
);
2490 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2495 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2499 * Gets the value of a "align" integer or struct attribute.
2502 * A CTF_RIGHT node or directly an unary integer.
2503 * @return The align value.
2504 * @throws ParseException
2506 private static long getAlignment(CommonTree node
) throws ParseException
{
2509 * If a CTF_RIGHT node was passed, call getAlignment with the first
2512 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2513 if (node
.getChildCount() > 1) {
2514 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2517 return getAlignment((CommonTree
) node
.getChild(0));
2518 } else if (isUnaryInteger(node
)) {
2519 long alignment
= parseUnaryInteger(node
);
2521 if (!isValidAlignment(alignment
)) {
2522 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2528 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2532 * Gets the value of a "base" integer attribute.
2535 * An CTF_RIGHT node.
2536 * @return The "base" value.
2537 * @throws ParseException
2539 private static int getBase(CommonTree rightNode
) throws ParseException
{
2541 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2543 if (isUnaryInteger(firstChild
)) {
2544 if (rightNode
.getChildCount() > 1) {
2545 throw new ParseException("invalid base value"); //$NON-NLS-1$
2548 long intval
= parseUnaryInteger(firstChild
);
2549 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2550 || (intval
== 16)) {
2551 return (int) intval
;
2553 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2554 } else if (isUnaryString(firstChild
)) {
2555 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2557 if (strval
.equals(CTFStrings
.DECIMAL
)
2558 || strval
.equals(CTFStrings
.DEC
)
2559 || strval
.equals(CTFStrings
.DEC_CTE
)
2560 || strval
.equals(CTFStrings
.INT_MOD
)
2561 || strval
.equals(CTFStrings
.UNSIGNED_CTE
)) {
2563 } else if (strval
.equals(CTFStrings
.HEXADECIMAL
)
2564 || strval
.equals(CTFStrings
.HEX
)
2565 || strval
.equals(CTFStrings
.X
)
2566 || strval
.equals(CTFStrings
.X2
)
2567 || strval
.equals(CTFStrings
.POINTER
)) {
2569 } else if (strval
.equals(CTFStrings
.OCTAL
)
2570 || strval
.equals(CTFStrings
.OCT
)
2571 || strval
.equals(CTFStrings
.OCTAL_CTE
)) {
2573 } else if (strval
.equals(CTFStrings
.BINARY
)
2574 || strval
.equals(CTFStrings
.BIN
)) {
2577 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2580 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2585 * Gets the value of an "encoding" integer attribute.
2589 * @return The "encoding" value.
2590 * @throws ParseException
2592 private static Encoding
getEncoding(CommonTree rightNode
)
2593 throws ParseException
{
2595 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2597 if (isUnaryString(firstChild
)) {
2598 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2600 if (strval
.equals(CTFStrings
.UTF8
)) {
2601 return Encoding
.UTF8
;
2602 } else if (strval
.equals(CTFStrings
.ASCII
)) {
2603 return Encoding
.ASCII
;
2604 } else if (strval
.equals(CTFStrings
.NONE
)) {
2605 return Encoding
.NONE
;
2607 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2610 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2613 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2615 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2617 if (isUnaryInteger(firstChild
)) {
2618 if (rightNode
.getChildCount() > 1) {
2619 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2622 long intval
= parseUnaryInteger(firstChild
);
2626 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2629 private static String
getEventName(CommonTree rightNode
)
2630 throws ParseException
{
2632 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2634 if (isUnaryString(firstChild
)) {
2635 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2639 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2642 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2644 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2646 if (isUnaryInteger(firstChild
)) {
2647 if (rightNode
.getChildCount() > 1) {
2648 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2651 long intval
= parseUnaryInteger(firstChild
);
2655 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2659 * Concatenates a list of unary strings separated by arrows (->) or dots.
2662 * A list, first element being an unary string, subsequent
2663 * elements being ARROW or DOT nodes with unary strings as child.
2664 * @return The string representation of the unary string chain.
2666 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2668 StringBuilder sb
= new StringBuilder();
2670 CommonTree first
= strings
.get(0);
2671 sb
.append(parseUnaryString(first
));
2673 boolean isFirst
= true;
2675 for (CommonTree ref
: strings
) {
2682 CommonTree id
= (CommonTree
) ref
.getChild(0);
2684 if (ref
.getType() == CTFParser
.ARROW
) {
2685 sb
.append("->"); //$NON-NLS-1$
2690 sb
.append(parseUnaryString(id
));
2693 return sb
.toString();
2697 * Throws a ParseException stating that the parent-child relation between
2698 * the given node and its parent is not valid. It means that the shape of
2699 * the AST is unexpected.
2702 * The invalid child node.
2703 * @throws ParseException
2705 private static void childTypeError(CommonTree child
) throws ParseException
{
2706 CommonTree parent
= (CommonTree
) child
.getParent();
2707 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2708 + " can't have a child of type " //$NON-NLS-1$
2709 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2711 throw new ParseException(error
);
2714 // ------------------------------------------------------------------------
2716 // ------------------------------------------------------------------------
2719 * Adds a new declaration scope on the top of the scope stack.
2721 private void pushScope() {
2722 scope
= new DeclarationScope(scope
);
2726 * Removes the top declaration scope from the scope stack.
2728 private void popScope() {
2729 scope
= scope
.getParentScope();
2733 * Returns the current declaration scope.
2735 * @return The current declaration scope.
2737 private DeclarationScope
getCurrentScope() {