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
10 * Matthew Khouzam - Initial Design and Grammar
11 * Francis Giraldeau - Initial API and implementation
12 * Simon Marchi - Initial API and implementation
13 *******************************************************************************/
15 package org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
;
17 import java
.io
.FileNotFoundException
;
18 import java
.io
.IOException
;
19 import java
.io
.UnsupportedEncodingException
;
20 import java
.math
.BigInteger
;
21 import java
.nio
.ByteOrder
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Collections
;
24 import java
.util
.LinkedList
;
25 import java
.util
.List
;
26 import java
.util
.UUID
;
28 import org
.antlr
.runtime
.tree
.CommonTree
;
29 import org
.eclipse
.core
.runtime
.IStatus
;
30 import org
.eclipse
.linuxtools
.ctf
.core
.event
.CTFClock
;
31 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.ArrayDeclaration
;
32 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Encoding
;
33 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDeclaration
;
34 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.FloatDeclaration
;
35 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDeclaration
;
36 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDeclaration
;
37 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.SequenceDeclaration
;
38 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StringDeclaration
;
39 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
40 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDeclaration
;
41 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.CTFTrace
;
42 import org
.eclipse
.linuxtools
.ctf
.core
.trace
.Stream
;
43 import org
.eclipse
.linuxtools
.ctf
.parser
.CTFParser
;
44 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.Activator
;
45 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.EventDeclaration
;
46 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.metadata
.exceptions
.ParseException
;
51 public class IOStructGen
{
53 // ------------------------------------------------------------------------
55 // ------------------------------------------------------------------------
57 private static final boolean DEBUG
= false;
62 private final CTFTrace trace
;
63 private final CommonTree tree
;
66 * The current declaration scope.
68 private DeclarationScope scope
= null;
70 // ------------------------------------------------------------------------
72 // ------------------------------------------------------------------------
78 * the tree (ANTLR generated) with the parsed TSDL data.
80 * the trace containing the places to put all the read metadata
82 public IOStructGen(CommonTree tree
, CTFTrace trace
) {
88 * Parse the tree and populate the trace defined in the constructor.
90 * @throws ParseException
91 * If there was a problem parsing the metadata
93 public void generate() throws ParseException
{
97 // ------------------------------------------------------------------------
99 // ------------------------------------------------------------------------
102 * Parse the root node.
106 * @throws ParseException
108 private void parseRoot(CommonTree root
) throws ParseException
{
110 List
<CommonTree
> children
= root
.getChildren();
111 java
.io
.FileOutputStream fos
= null;
112 java
.io
.OutputStreamWriter out
= null;
115 fos
= new java
.io
.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
116 out
= new java
.io
.OutputStreamWriter(fos
, "UTF-8"); //$NON-NLS-1$
117 } catch (FileNotFoundException e
) {
120 } catch (UnsupportedEncodingException e
) {
126 CommonTree traceNode
= null;
127 List
<CommonTree
> streams
= new ArrayList
<CommonTree
>();
128 List
<CommonTree
> events
= new ArrayList
<CommonTree
>();
129 List
<CommonTree
> declarations
= new ArrayList
<CommonTree
>();
130 List
<CommonTree
> environments
= new ArrayList
<CommonTree
>();
131 List
<CommonTree
> clocks
= new ArrayList
<CommonTree
>();
132 List
<CommonTree
> callsites
= new ArrayList
<CommonTree
>();
133 /* Create a new declaration scope with no parent. */
137 for (CommonTree child
: children
) {
138 final int type
= child
.getType();
140 out
.write(child
.toString()
141 + " -> " + type
+ '\n'); //$NON-NLS-1$
144 case CTFParser
.DECLARATION
:
145 declarations
.add(child
);
147 case CTFParser
.TRACE
:
148 if (traceNode
!= null) {
149 throw new ParseException(
150 "Only one trace block is allowed"); //$NON-NLS-1$
154 case CTFParser
.STREAM
:
157 case CTFParser
.EVENT
:
160 case CTFParser
.CLOCK
:
164 environments
.add(child
);
166 case CTFParser
.CALLSITE
:
167 callsites
.add(child
);
170 childTypeError(child
);
174 out
.write("Declarations\n"); //$NON-NLS-1$
176 for (CommonTree decl
: declarations
) {
178 out
.write(decl
.toString() + '\n');
180 parseRootDeclaration(decl
);
182 if (traceNode
== null) {
183 throw new ParseException("Missing trace block"); //$NON-NLS-1$
186 parseTrace(traceNode
);
189 out
.write("Environments\n"); //$NON-NLS-1$
191 for (CommonTree environment
: environments
) {
192 parseEnvironment(environment
);
195 out
.write("Clocks\n"); //$NON-NLS-1$
197 for (CommonTree clock
: clocks
) {
201 out
.write("Callsites\n"); //$NON-NLS-1$
203 for (CommonTree callsite
: callsites
) {
204 parseCallsite(callsite
);
208 out
.write("Streams\n"); //$NON-NLS-1$
210 if (streams
.size() > 0) {
211 for (CommonTree stream
: streams
) {
214 out
.write(stream
.toString() + '\n');
215 } catch (IOException e
) {
222 /* Add an empty stream that will have a null id */
223 trace
.addStream(new Stream(trace
));
227 out
.write("Events\n"); //$NON-NLS-1$
229 for (CommonTree event
: events
) {
232 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
233 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
234 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
242 } catch (IOException e
) {
248 private void parseCallsite(CommonTree callsite
) {
250 List
<CommonTree
> children
= callsite
.getChildren();
252 String funcName
= null;
253 long lineNumber
= -1;
255 String fileName
= null;
257 for (CommonTree child
: children
) {
259 /* this is a regex to find the leading and trailing quotes */
260 final String regex
= "^\"|\"$"; //$NON-NLS-1$
261 /* this is to replace the previous quotes with nothing... effectively deleting them */
262 final String nullString
= ""; //$NON-NLS-1$
263 left
= child
.getChild(0).getChild(0).getChild(0).getText();
264 if (left
.equals("name")) { //$NON-NLS-1$
265 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
266 } else if (left
.equals("func")) { //$NON-NLS-1$
267 funcName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
268 } else if (left
.equals("ip")) { //$NON-NLS-1$
269 ip
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText().substring(2), 16); // trim the 0x
270 } else if (left
.equals("file")) { //$NON-NLS-1$
271 fileName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
272 } else if (left
.equals("line")) { //$NON-NLS-1$
273 lineNumber
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
276 trace
.addCallsite(name
, funcName
, ip
,fileName
, lineNumber
);
279 private void parseEnvironment(CommonTree environment
) {
280 List
<CommonTree
> children
= environment
.getChildren();
281 for (CommonTree child
: children
) {
284 left
= child
.getChild(0).getChild(0).getChild(0).getText();
285 right
= child
.getChild(1).getChild(0).getChild(0).getText();
286 trace
.addEnvironmentVar(left
, right
);
290 private void parseClock(CommonTree clock
) {
291 List
<CommonTree
> children
= clock
.getChildren();
292 CTFClock ctfClock
= new CTFClock();
293 for (CommonTree child
: children
) {
294 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
295 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
296 final int type
= value
.getType();
298 case CTFParser
.INTEGER
:
299 case CTFParser
.DECIMAL_LITERAL
:
301 * Not a pretty hack, this is to make sure that there is no
302 * number overflow due to 63 bit integers. The offset should
303 * only really be an issue in the year 2262. the tracer in C/ASM
304 * can write an offset in an unsigned 64 bit long. In java, the
305 * last bit, being set to 1 will be read as a negative number,
306 * but since it is too big a positive it will throw an
307 * exception. this will happen in 2^63 ns from 1970. Therefore
308 * 293 years from 1970
312 numValue
= Long
.parseLong(value
.getText());
313 } catch (Exception e
) {
314 numValue
= 1330938566783103277L;
316 ctfClock
.addAttribute(key
, numValue
);
319 ctfClock
.addAttribute(key
, value
.getText());
323 String nameValue
= ctfClock
.getName();
324 trace
.addClock(nameValue
, ctfClock
);
327 private void parseTrace(CommonTree traceNode
) throws ParseException
{
329 List
<CommonTree
> children
= traceNode
.getChildren();
330 if (children
== null) {
331 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
336 for (CommonTree child
: children
) {
337 switch (child
.getType()) {
338 case CTFParser
.TYPEALIAS
:
339 parseTypealias(child
);
341 case CTFParser
.TYPEDEF
:
344 case CTFParser
.CTF_EXPRESSION_TYPE
:
345 case CTFParser
.CTF_EXPRESSION_VAL
:
346 parseTraceDeclaration(child
);
349 childTypeError(child
);
355 * If trace byte order was not specified and not using packet based
358 if (trace
.getByteOrder() == null) {
359 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
365 private void parseTraceDeclaration(CommonTree traceDecl
)
366 throws ParseException
{
368 /* There should be a left and right */
370 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
371 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
373 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
375 if (!isAnyUnaryString(leftStrings
.get(0))) {
376 throw new ParseException(
377 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
380 String left
= concatenateUnaryStrings(leftStrings
);
382 if (left
.equals(MetadataStrings
.MAJOR
)) {
383 if (trace
.majortIsSet()) {
384 throw new ParseException("major is already set"); //$NON-NLS-1$
387 trace
.setMajor(getMajorOrMinor(rightNode
));
388 } else if (left
.equals(MetadataStrings
.MINOR
)) {
389 if (trace
.minorIsSet()) {
390 throw new ParseException("minor is already set"); //$NON-NLS-1$
393 trace
.setMinor(getMajorOrMinor(rightNode
));
394 } else if (left
.equals(MetadataStrings
.UUID_STRING
)) {
395 UUID uuid
= getUUID(rightNode
);
398 * If uuid was already set by a metadata packet, compare it to see
401 if (trace
.uuidIsSet()) {
402 if (trace
.getUUID().compareTo(uuid
) != 0) {
403 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
404 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
410 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
411 ByteOrder byteOrder
= getByteOrder(rightNode
);
414 * If byte order was already set by a metadata packet, compare it to
417 if (trace
.getByteOrder() != null) {
418 if (trace
.getByteOrder() != byteOrder
) {
419 throw new ParseException(
420 "Endianness mismatch. Magic number says " //$NON-NLS-1$
421 + trace
.getByteOrder()
422 + " but metadata says " + byteOrder
); //$NON-NLS-1$
425 trace
.setByteOrder(byteOrder
);
426 final DeclarationScope parentScope
= scope
.getParentScope();
427 String types
[] = parentScope
.getTypeNames();
429 for (String type
: types
) {
430 IDeclaration d
= parentScope
.lookupType(type
);
431 if (d
instanceof IntegerDeclaration
) {
432 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
433 } else if (d
instanceof StructDeclaration
) {
434 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
438 } else if (left
.equals(MetadataStrings
.PACKET_HEADER
)) {
439 if (trace
.packetHeaderIsSet()) {
440 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
443 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
445 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
446 throw new ParseException(
447 "packet.header expects a type specifier"); //$NON-NLS-1$
450 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
451 typeSpecifier
, null);
453 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
454 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
457 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
459 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownTraceAttributeWarning
+ " " + left
); //$NON-NLS-1$
463 private static void addByteOrder(ByteOrder byteOrder
,
464 final DeclarationScope parentScope
, String name
,
465 IntegerDeclaration decl
) throws ParseException
{
467 if (decl
.getByteOrder() == null) {
468 IntegerDeclaration newI
;
469 newI
= new IntegerDeclaration(decl
.getLength(), decl
.isSigned(),
470 decl
.getBase(), byteOrder
, decl
.getEncoding(),
471 decl
.getClock(), decl
.getAlignment());
472 parentScope
.replaceType(name
, newI
);
476 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
477 ByteOrder byteOrder
) throws ParseException
{
479 for (String s
: sd
.getFieldsList()) {
480 IDeclaration d
= sd
.getFields().get(s
);
482 if (d
instanceof StructDeclaration
) {
483 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
485 } else if (d
instanceof VariantDeclaration
) {
486 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
488 } else if (d
instanceof IntegerDeclaration
) {
489 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
490 if (decl
.getByteOrder() == null) {
491 IntegerDeclaration newI
;
492 newI
= new IntegerDeclaration(decl
.getLength(),
493 decl
.isSigned(), decl
.getBase(), byteOrder
,
494 decl
.getEncoding(), decl
.getClock(),
495 decl
.getAlignment());
496 sd
.getFields().put(s
, newI
);
502 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
503 ByteOrder byteOrder
) throws ParseException
{
505 for (String s
: vd
.getFields().keySet()) {
506 IDeclaration d
= vd
.getFields().get(s
);
508 if (d
instanceof StructDeclaration
) {
509 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
511 } else if (d
instanceof IntegerDeclaration
) {
512 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
513 IntegerDeclaration newI
;
514 newI
= new IntegerDeclaration(decl
.getLength(),
515 decl
.isSigned(), decl
.getBase(), byteOrder
,
516 decl
.getEncoding(), decl
.getClock(),
517 decl
.getAlignment());
518 vd
.getFields().put(s
, newI
);
523 private void parseStream(CommonTree streamNode
) throws ParseException
{
525 Stream stream
= new Stream(trace
);
527 List
<CommonTree
> children
= streamNode
.getChildren();
528 if (children
== null) {
529 throw new ParseException("Empty stream block"); //$NON-NLS-1$
534 for (CommonTree child
: children
) {
535 switch (child
.getType()) {
536 case CTFParser
.TYPEALIAS
:
537 parseTypealias(child
);
539 case CTFParser
.TYPEDEF
:
542 case CTFParser
.CTF_EXPRESSION_TYPE
:
543 case CTFParser
.CTF_EXPRESSION_VAL
:
544 parseStreamDeclaration(child
, stream
);
547 childTypeError(child
);
552 if (stream
.isIdSet()) {
553 if (!trace
.packetHeaderIsSet()
554 || !trace
.getPacketHeader().hasField(MetadataStrings
.STREAM_ID
)) {
555 throw new ParseException(
556 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
560 trace
.addStream(stream
);
565 private void parseStreamDeclaration(CommonTree streamDecl
, Stream stream
)
566 throws ParseException
{
568 /* There should be a left and right */
570 CommonTree leftNode
= (CommonTree
) streamDecl
.getChild(0);
571 CommonTree rightNode
= (CommonTree
) streamDecl
.getChild(1);
573 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
575 if (!isAnyUnaryString(leftStrings
.get(0))) {
576 throw new ParseException(
577 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
580 String left
= concatenateUnaryStrings(leftStrings
);
582 if (left
.equals(MetadataStrings
.ID
)) {
583 if (stream
.isIdSet()) {
584 throw new ParseException("stream id already defined"); //$NON-NLS-1$
587 long streamID
= getStreamID(rightNode
);
589 stream
.setId(streamID
);
590 } else if (left
.equals(MetadataStrings
.EVENT_HEADER
)) {
591 if (stream
.isEventHeaderSet()) {
592 throw new ParseException("event.header already defined"); //$NON-NLS-1$
595 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
597 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
598 throw new ParseException(
599 "event.header expects a type specifier"); //$NON-NLS-1$
602 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
603 typeSpecifier
, null);
605 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
606 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
609 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
610 } else if (left
.equals(MetadataStrings
.EVENT_CONTEXT
)) {
611 if (stream
.isEventContextSet()) {
612 throw new ParseException("event.context already defined"); //$NON-NLS-1$
615 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
617 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
618 throw new ParseException(
619 "event.context expects a type specifier"); //$NON-NLS-1$
622 IDeclaration eventContextDecl
= parseTypeSpecifierList(
623 typeSpecifier
, null);
625 if (!(eventContextDecl
instanceof StructDeclaration
)) {
626 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
629 stream
.setEventContext((StructDeclaration
) eventContextDecl
);
630 } else if (left
.equals(MetadataStrings
.PACKET_CONTEXT
)) {
631 if (stream
.isPacketContextSet()) {
632 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
635 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
637 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
638 throw new ParseException(
639 "packet.context expects a type specifier"); //$NON-NLS-1$
642 IDeclaration packetContextDecl
= parseTypeSpecifierList(
643 typeSpecifier
, null);
645 if (!(packetContextDecl
instanceof StructDeclaration
)) {
646 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
649 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
651 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownStreamAttributeWarning
+ " " + left
); //$NON-NLS-1$
655 private void parseEvent(CommonTree eventNode
) throws ParseException
{
657 List
<CommonTree
> children
= eventNode
.getChildren();
658 if (children
== null) {
659 throw new ParseException("Empty event block"); //$NON-NLS-1$
662 EventDeclaration event
= new EventDeclaration();
666 for (CommonTree child
: children
) {
667 switch (child
.getType()) {
668 case CTFParser
.TYPEALIAS
:
669 parseTypealias(child
);
671 case CTFParser
.TYPEDEF
:
674 case CTFParser
.CTF_EXPRESSION_TYPE
:
675 case CTFParser
.CTF_EXPRESSION_VAL
:
676 parseEventDeclaration(child
, event
);
679 childTypeError(child
);
684 if (!event
.nameIsSet()) {
685 throw new ParseException("Event name not set"); //$NON-NLS-1$
689 * If the event did not specify a stream, then the trace must be single
692 if (!event
.streamIsSet()) {
693 if (trace
.nbStreams() > 1) {
694 throw new ParseException(
695 "Event without stream_id with more than one stream"); //$NON-NLS-1$
699 * If the event did not specify a stream, the only existing stream
700 * must not have an id. Note: That behavior could be changed, it
701 * could be possible to just get the only existing stream, whatever
704 Stream stream
= trace
.getStream(null);
706 if (stream
!= null) {
707 event
.setStream(stream
);
709 throw new ParseException(
710 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
715 * Add the event to the stream.
717 event
.getStream().addEvent(event
);
722 private void parseEventDeclaration(CommonTree eventDecl
,
723 EventDeclaration event
) throws ParseException
{
725 /* There should be a left and right */
727 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
728 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
730 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
732 if (!isAnyUnaryString(leftStrings
.get(0))) {
733 throw new ParseException(
734 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
737 String left
= concatenateUnaryStrings(leftStrings
);
739 if (left
.equals(MetadataStrings
.NAME2
)) {
740 if (event
.nameIsSet()) {
741 throw new ParseException("name already defined"); //$NON-NLS-1$
744 String name
= getEventName(rightNode
);
747 } else if (left
.equals(MetadataStrings
.ID
)) {
748 if (event
.idIsSet()) {
749 throw new ParseException("id already defined"); //$NON-NLS-1$
752 long id
= getEventID(rightNode
);
755 } else if (left
.equals(MetadataStrings
.STREAM_ID
)) {
756 if (event
.streamIsSet()) {
757 throw new ParseException("stream id already defined"); //$NON-NLS-1$
760 long streamId
= getStreamID(rightNode
);
762 Stream stream
= trace
.getStream(streamId
);
764 if (stream
== null) {
765 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
768 event
.setStream(stream
);
769 } else if (left
.equals(MetadataStrings
.CONTEXT
)) {
770 if (event
.contextIsSet()) {
771 throw new ParseException("context already defined"); //$NON-NLS-1$
774 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
776 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
777 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
780 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
783 if (!(contextDecl
instanceof StructDeclaration
)) {
784 throw new ParseException("context expects a struct"); //$NON-NLS-1$
787 event
.setContext((StructDeclaration
) contextDecl
);
788 } else if (left
.equals(MetadataStrings
.FIELDS_STRING
)) {
789 if (event
.fieldsIsSet()) {
790 throw new ParseException("fields already defined"); //$NON-NLS-1$
793 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
795 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
796 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
799 IDeclaration fieldsDecl
;
800 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
802 if (!(fieldsDecl
instanceof StructDeclaration
)) {
803 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
806 * The underscores in the event names. These underscores were added
807 * by the LTTng tracer.
809 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
810 event
.setFields(fields
);
811 } else if (left
.equals(MetadataStrings
.LOGLEVEL2
)) {
812 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
813 event
.setLogLevel(logLevel
);
815 /* Custom event attribute, we'll add it to the attributes map */
816 String right
= parseUnaryString((CommonTree
) rightNode
.getChild(0));
817 event
.setCustomAttribute(left
, right
);
822 * Parses a declaration at the root level.
825 * The declaration subtree.
826 * @throws ParseException
828 private void parseRootDeclaration(CommonTree declaration
)
829 throws ParseException
{
831 List
<CommonTree
> children
= declaration
.getChildren();
833 for (CommonTree child
: children
) {
834 switch (child
.getType()) {
835 case CTFParser
.TYPEDEF
:
838 case CTFParser
.TYPEALIAS
:
839 parseTypealias(child
);
841 case CTFParser
.TYPE_SPECIFIER_LIST
:
842 parseTypeSpecifierList(child
, null);
845 childTypeError(child
);
851 * Parses a typealias node. It parses the target, the alias, and registers
852 * the type in the current scope.
856 * @throws ParseException
858 private void parseTypealias(CommonTree typealias
) throws ParseException
{
860 List
<CommonTree
> children
= typealias
.getChildren();
862 CommonTree target
= null;
863 CommonTree alias
= null;
865 for (CommonTree child
: children
) {
866 switch (child
.getType()) {
867 case CTFParser
.TYPEALIAS_TARGET
:
870 case CTFParser
.TYPEALIAS_ALIAS
:
874 childTypeError(child
);
880 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
882 if ((targetDeclaration
instanceof VariantDeclaration
)
883 && ((VariantDeclaration
) targetDeclaration
).isTagged()) {
884 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
887 String aliasString
= parseTypealiasAlias(alias
);
889 getCurrentScope().registerType(aliasString
, targetDeclaration
);
893 * Parses the target part of a typealias and gets the corresponding
897 * A TYPEALIAS_TARGET node.
898 * @return The corresponding declaration.
899 * @throws ParseException
901 private IDeclaration
parseTypealiasTarget(CommonTree target
)
902 throws ParseException
{
904 List
<CommonTree
> children
= target
.getChildren();
906 CommonTree typeSpecifierList
= null;
907 CommonTree typeDeclaratorList
= null;
908 CommonTree typeDeclarator
= null;
909 StringBuilder identifierSB
= new StringBuilder();
911 for (CommonTree child
: children
) {
912 switch (child
.getType()) {
913 case CTFParser
.TYPE_SPECIFIER_LIST
:
914 typeSpecifierList
= child
;
916 case CTFParser
.TYPE_DECLARATOR_LIST
:
917 typeDeclaratorList
= child
;
920 childTypeError(child
);
926 if (typeDeclaratorList
!= null) {
928 * Only allow one declarator
930 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
931 * otherwise the new type puint8_t would maps to two different
934 if (typeDeclaratorList
.getChildCount() != 1) {
935 throw new ParseException(
936 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
939 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
942 /* Parse the target type and get the declaration */
943 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
944 typeSpecifierList
, identifierSB
);
947 * We don't allow identifier in the target
949 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
952 if (identifierSB
.length() > 0) {
953 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
954 + ") not expected in the typealias target"); //$NON-NLS-1$
957 return targetDeclaration
;
961 * Parses the alias part of a typealias. It parses the underlying specifier
962 * list and declarator and creates the string representation that will be
963 * used to register the type.
966 * A TYPEALIAS_ALIAS node.
967 * @return The string representation of the alias.
968 * @throws ParseException
970 private static String
parseTypealiasAlias(CommonTree alias
)
971 throws ParseException
{
973 List
<CommonTree
> children
= alias
.getChildren();
975 CommonTree typeSpecifierList
= null;
976 CommonTree typeDeclaratorList
= null;
977 CommonTree typeDeclarator
= null;
978 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
980 for (CommonTree child
: children
) {
981 switch (child
.getType()) {
982 case CTFParser
.TYPE_SPECIFIER_LIST
:
983 typeSpecifierList
= child
;
985 case CTFParser
.TYPE_DECLARATOR_LIST
:
986 typeDeclaratorList
= child
;
989 childTypeError(child
);
994 /* If there is a type declarator list, extract the pointers */
995 if (typeDeclaratorList
!= null) {
997 * Only allow one declarator
999 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
1001 if (typeDeclaratorList
.getChildCount() != 1) {
1002 throw new ParseException(
1003 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1006 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
1008 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
1010 for (CommonTree child
: typeDeclaratorChildren
) {
1011 switch (child
.getType()) {
1012 case CTFParser
.POINTER
:
1013 pointers
.add(child
);
1015 case CTFParser
.IDENTIFIER
:
1016 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1017 + ") 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 typeDeclaration
= parseTypeDeclarator(
1049 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1051 if ((typeDeclaration
instanceof VariantDeclaration
)
1052 && ((VariantDeclaration
) typeDeclaration
).isTagged()) {
1053 throw new ParseException(
1054 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1057 getCurrentScope().registerType(identifierSB
.toString(),
1063 * Parses a pair type declarator / type specifier list and returns the
1064 * corresponding declaration. If it is present, it also writes the
1065 * identifier of the declarator in the given {@link StringBuilder}.
1067 * @param typeDeclarator
1068 * A TYPE_DECLARATOR node.
1069 * @param typeSpecifierList
1070 * A TYPE_SPECIFIER_LIST node.
1071 * @param identifierSB
1072 * A StringBuilder that will receive the identifier found in the
1074 * @return The corresponding declaration.
1075 * @throws ParseException
1076 * If there is an error finding or creating the declaration.
1078 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1079 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1080 throws ParseException
{
1082 IDeclaration declaration
= null;
1083 List
<CommonTree
> children
= null;
1084 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1085 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1086 CommonTree identifier
= null;
1088 /* Separate the tokens by type */
1089 if (typeDeclarator
!= null) {
1090 children
= typeDeclarator
.getChildren();
1091 for (CommonTree child
: children
) {
1093 switch (child
.getType()) {
1094 case CTFParser
.POINTER
:
1095 pointers
.add(child
);
1097 case CTFParser
.IDENTIFIER
:
1100 case CTFParser
.LENGTH
:
1104 childTypeError(child
);
1112 * Parse the type specifier list, which is the "base" type. For example,
1113 * it would be int in int a[3][len].
1115 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1118 * Each length subscript means that we must create a nested array or
1119 * sequence. For example, int a[3][len] means that we have an array of 3
1120 * (sequences of length 'len' of (int)).
1122 if (lengths
.size() > 0) {
1123 /* We begin at the end */
1124 Collections
.reverse(lengths
);
1126 for (CommonTree length
: lengths
) {
1128 * By looking at the first expression, we can determine whether
1129 * it is an array or a sequence.
1131 List
<CommonTree
> lengthChildren
= length
.getChildren();
1133 CommonTree first
= lengthChildren
.get(0);
1134 if (isUnaryInteger(first
)) {
1136 int arrayLength
= (int) parseUnaryInteger(first
);
1138 if (arrayLength
< 1) {
1139 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1142 /* Create the array declaration. */
1143 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1144 } else if (isAnyUnaryString(first
)) {
1146 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1148 /* Create the sequence declaration. */
1149 declaration
= new SequenceDeclaration(lengthName
,
1152 childTypeError(first
);
1157 if (identifier
!= null) {
1158 identifierSB
.append(identifier
.getText());
1165 * Parses a type specifier list and returns the corresponding declaration.
1167 * @param typeSpecifierList
1168 * A TYPE_SPECIFIER_LIST node.
1169 * @param pointerList
1170 * A list of POINTER nodes that apply to the specified type.
1171 * @return The corresponding declaration.
1172 * @throws ParseException
1173 * If the type has not been defined or if there is an error
1174 * creating the declaration.
1176 private IDeclaration
parseTypeSpecifierList(CommonTree typeSpecifierList
,
1177 List
<CommonTree
> pointerList
) throws ParseException
{
1178 IDeclaration declaration
= null;
1181 * By looking at the first element of the type specifier list, we can
1182 * determine which type it belongs to.
1184 CommonTree firstChild
= (CommonTree
) typeSpecifierList
.getChild(0);
1186 switch (firstChild
.getType()) {
1187 case CTFParser
.FLOATING_POINT
:
1188 declaration
= parseFloat(firstChild
);
1190 case CTFParser
.INTEGER
:
1191 declaration
= parseInteger(firstChild
);
1193 case CTFParser
.STRING
:
1194 declaration
= parseString(firstChild
);
1196 case CTFParser
.STRUCT
:
1197 declaration
= parseStruct(firstChild
);
1199 case CTFParser
.VARIANT
:
1200 declaration
= parseVariant(firstChild
);
1202 case CTFParser
.ENUM
:
1203 declaration
= parseEnum(firstChild
);
1205 case CTFParser
.IDENTIFIER
:
1206 case CTFParser
.FLOATTOK
:
1207 case CTFParser
.INTTOK
:
1208 case CTFParser
.LONGTOK
:
1209 case CTFParser
.SHORTTOK
:
1210 case CTFParser
.SIGNEDTOK
:
1211 case CTFParser
.UNSIGNEDTOK
:
1212 case CTFParser
.CHARTOK
:
1213 case CTFParser
.DOUBLETOK
:
1214 case CTFParser
.VOIDTOK
:
1215 case CTFParser
.BOOLTOK
:
1216 case CTFParser
.COMPLEXTOK
:
1217 case CTFParser
.IMAGINARYTOK
:
1218 declaration
= parseTypeDeclaration(typeSpecifierList
, pointerList
);
1221 childTypeError(firstChild
);
1227 private IDeclaration
parseFloat(CommonTree floatingPoint
)
1228 throws ParseException
{
1230 List
<CommonTree
> children
= floatingPoint
.getChildren();
1233 * If the integer has no attributes, then it is missing the size
1234 * attribute which is required
1236 if (children
== null) {
1237 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1240 /* The return value */
1241 FloatDeclaration floatDeclaration
= null;
1242 ByteOrder byteOrder
= trace
.getByteOrder();
1247 /* Iterate on all integer children */
1248 for (CommonTree child
: children
) {
1249 switch (child
.getType()) {
1250 case CTFParser
.CTF_EXPRESSION_VAL
:
1252 * An assignment expression must have 2 children, left and right
1255 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1256 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1258 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1260 if (!isAnyUnaryString(leftStrings
.get(0))) {
1261 throw new ParseException(
1262 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1264 String left
= concatenateUnaryStrings(leftStrings
);
1266 if (left
.equals(MetadataStrings
.EXP_DIG
)) {
1267 exponent
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1268 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1269 byteOrder
= getByteOrder(rightNode
);
1270 } else if (left
.equals(MetadataStrings
.MANT_DIG
)) {
1271 mantissa
= (int) parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
1272 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1273 alignment
= getAlignment(rightNode
);
1275 throw new ParseException("Float: unknown attribute " + left
); //$NON-NLS-1$
1280 childTypeError(child
);
1284 int size
= mantissa
+ exponent
;
1286 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1289 if (alignment
== 0) {
1290 if ((size
% 8) == 0) {
1297 floatDeclaration
= new FloatDeclaration(exponent
, mantissa
, byteOrder
, alignment
);
1299 return floatDeclaration
;
1304 * Parses a type specifier list as a user-declared type.
1306 * @param typeSpecifierList
1307 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1308 * @param pointerList
1309 * A list of POINTER nodes that apply to the type specified in
1310 * typeSpecifierList.
1311 * @return The corresponding declaration.
1312 * @throws ParseException
1313 * If the type does not exist (has not been found).
1315 private IDeclaration
parseTypeDeclaration(CommonTree typeSpecifierList
,
1316 List
<CommonTree
> pointerList
) throws ParseException
{
1317 /* Create the string representation of the type declaration */
1318 String typeStringRepresentation
= createTypeDeclarationString(
1319 typeSpecifierList
, pointerList
);
1321 /* Use the string representation to search the type in the current scope */
1322 IDeclaration decl
= getCurrentScope().rlookupType(
1323 typeStringRepresentation
);
1326 throw new ParseException("Type " + typeStringRepresentation
//$NON-NLS-1$
1327 + " has not been defined."); //$NON-NLS-1$
1334 * Parses an integer declaration node.
1338 * @return The corresponding integer declaration.
1339 * @throws ParseException
1341 private IntegerDeclaration
parseInteger(CommonTree integer
)
1342 throws ParseException
{
1344 List
<CommonTree
> children
= integer
.getChildren();
1347 * If the integer has no attributes, then it is missing the size
1348 * attribute which is required
1350 if (children
== null) {
1351 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1354 /* The return value */
1355 IntegerDeclaration integerDeclaration
= null;
1356 boolean signed
= false;
1357 ByteOrder byteOrder
= trace
.getByteOrder();
1361 String clock
= null;
1363 Encoding encoding
= Encoding
.NONE
;
1365 /* Iterate on all integer children */
1366 for (CommonTree child
: children
) {
1367 switch (child
.getType()) {
1368 case CTFParser
.CTF_EXPRESSION_VAL
:
1370 * An assignment expression must have 2 children, left and right
1373 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1374 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1376 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1378 if (!isAnyUnaryString(leftStrings
.get(0))) {
1379 throw new ParseException(
1380 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1382 String left
= concatenateUnaryStrings(leftStrings
);
1384 if (left
.equals("signed")) { //$NON-NLS-1$
1385 signed
= getSigned(rightNode
);
1386 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1387 byteOrder
= getByteOrder(rightNode
);
1388 } else if (left
.equals("size")) { //$NON-NLS-1$
1389 size
= getSize(rightNode
);
1390 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1391 alignment
= getAlignment(rightNode
);
1392 } else if (left
.equals("base")) { //$NON-NLS-1$
1393 base
= getBase(rightNode
);
1394 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1395 encoding
= getEncoding(rightNode
);
1396 } else if (left
.equals("map")) { //$NON-NLS-1$
1397 clock
= getClock(rightNode
);
1399 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownIntegerAttributeWarning
+ " " + left
); //$NON-NLS-1$
1404 childTypeError(child
);
1410 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1413 if (alignment
== 0) {
1414 if ((size
% 8) == 0) {
1421 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1422 byteOrder
, encoding
, clock
, alignment
);
1424 return integerDeclaration
;
1427 private static String
getClock(CommonTree rightNode
) {
1428 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1431 private static StringDeclaration
parseString(CommonTree string
)
1432 throws ParseException
{
1434 List
<CommonTree
> children
= string
.getChildren();
1435 StringDeclaration stringDeclaration
= null;
1437 if (children
== null) {
1438 stringDeclaration
= new StringDeclaration();
1440 Encoding encoding
= Encoding
.UTF8
;
1441 for (CommonTree child
: children
) {
1442 switch (child
.getType()) {
1443 case CTFParser
.CTF_EXPRESSION_VAL
:
1445 * An assignment expression must have 2 children, left and
1449 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1450 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1452 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1454 if (!isAnyUnaryString(leftStrings
.get(0))) {
1455 throw new ParseException(
1456 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1458 String left
= concatenateUnaryStrings(leftStrings
);
1460 if (left
.equals("encoding")) { //$NON-NLS-1$
1461 encoding
= getEncoding(rightNode
);
1463 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1469 childTypeError(child
);
1474 stringDeclaration
= new StringDeclaration(encoding
);
1477 return stringDeclaration
;
1481 * Parses a struct declaration and returns the corresponding declaration.
1485 * @return The corresponding struct declaration.
1486 * @throws ParseException
1488 private StructDeclaration
parseStruct(CommonTree struct
)
1489 throws ParseException
{
1491 List
<CommonTree
> children
= struct
.getChildren();
1493 /* The return value */
1494 StructDeclaration structDeclaration
= null;
1497 String structName
= null;
1498 boolean hasName
= false;
1501 CommonTree structBody
= null;
1502 boolean hasBody
= false;
1505 long structAlign
= 0;
1507 /* Loop on all children and identify what we have to work with. */
1508 for (CommonTree child
: children
) {
1509 switch (child
.getType()) {
1510 case CTFParser
.STRUCT_NAME
: {
1513 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1515 structName
= structNameIdentifier
.getText();
1519 case CTFParser
.STRUCT_BODY
: {
1526 case CTFParser
.ALIGN
: {
1527 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1529 structAlign
= getAlignment(structAlignExpression
);
1534 childTypeError(child
);
1541 * If a struct has just a body and no name (just like the song,
1542 * "A Struct With No Name" by America (sorry for that...)), it's a
1543 * definition of a new type, so we create the type declaration and
1544 * return it. We can't add it to the declaration scope since there is no
1545 * name, but that's what we want because it won't be possible to use it
1546 * again to declare another field.
1548 * If it has just a name, we look it up in the declaration scope and
1549 * return the associated declaration. If it is not found in the
1550 * declaration scope, it means that a struct with that name has not been
1551 * declared, which is an error.
1553 * If it has both, then we create the type declaration and register it
1554 * to the current scope.
1556 * If it has none, then what are we doing here ?
1560 * If struct has a name, check if already defined in the current
1563 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1564 throw new ParseException("struct " + structName
//$NON-NLS-1$
1565 + " already defined."); //$NON-NLS-1$
1567 /* Create the declaration */
1568 structDeclaration
= new StructDeclaration(structAlign
);
1570 /* Parse the body */
1571 parseStructBody(structBody
, structDeclaration
);
1573 /* If struct has name, add it to the current scope. */
1575 getCurrentScope().registerStruct(structName
, structDeclaration
);
1577 } else /* !hasBody */{
1579 /* Name and !body */
1581 /* Lookup the name in the current scope. */
1582 structDeclaration
= getCurrentScope().rlookupStruct(structName
);
1585 * If not found, it means that a struct with such name has not
1588 if (structDeclaration
== null) {
1589 throw new ParseException("struct " + structName
//$NON-NLS-1$
1590 + " is not defined"); //$NON-NLS-1$
1593 /* !Name and !body */
1595 /* We can't do anything with that. */
1596 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1600 return structDeclaration
;
1604 * Parses a struct body, adding the fields to specified structure
1608 * A STRUCT_BODY node.
1609 * @param structDeclaration
1610 * The struct declaration.
1611 * @throws ParseException
1613 private void parseStructBody(CommonTree structBody
,
1614 StructDeclaration structDeclaration
) throws ParseException
{
1616 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1619 * If structDeclaration is null, structBody has no children and the
1620 * struct body is empty.
1622 if (structDeclarations
!= null) {
1625 for (CommonTree declarationNode
: structDeclarations
) {
1626 switch (declarationNode
.getType()) {
1627 case CTFParser
.TYPEALIAS
:
1628 parseTypealias(declarationNode
);
1630 case CTFParser
.TYPEDEF
:
1631 parseTypedef(declarationNode
);
1633 case CTFParser
.SV_DECLARATION
:
1634 parseStructDeclaration(declarationNode
, structDeclaration
);
1637 childTypeError(declarationNode
);
1646 * Parses a declaration found in a struct.
1648 * @param declaration
1649 * A SV_DECLARATION node.
1651 * A struct declaration. (I know, little name clash here...)
1652 * @throws ParseException
1654 private void parseStructDeclaration(CommonTree declaration
,
1655 StructDeclaration struct
) throws ParseException
{
1658 /* Get the type specifier list node */
1659 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1661 /* Get the type declarator list node */
1662 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1664 /* Get the type declarator list */
1665 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1668 * For each type declarator, parse the declaration and add a field to
1671 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1673 StringBuilder identifierSB
= new StringBuilder();
1675 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1676 typeSpecifierListNode
, identifierSB
);
1677 String fieldName
= identifierSB
.toString();
1679 if (struct
.hasField(fieldName
)) {
1680 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1684 struct
.addField(fieldName
, decl
);
1690 * Parses an enum declaration and returns the corresponding declaration.
1694 * @return The corresponding enum declaration.
1695 * @throws ParseException
1697 private EnumDeclaration
parseEnum(CommonTree theEnum
) throws ParseException
{
1699 List
<CommonTree
> children
= theEnum
.getChildren();
1701 /* The return value */
1702 EnumDeclaration enumDeclaration
= null;
1705 String enumName
= null;
1708 CommonTree enumBody
= null;
1710 /* Container type */
1711 IntegerDeclaration containerTypeDeclaration
= null;
1713 /* Loop on all children and identify what we have to work with. */
1714 for (CommonTree child
: children
) {
1715 switch (child
.getType()) {
1716 case CTFParser
.ENUM_NAME
: {
1717 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1718 enumName
= enumNameIdentifier
.getText();
1721 case CTFParser
.ENUM_BODY
: {
1725 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1726 containerTypeDeclaration
= parseEnumContainerType(child
);
1730 childTypeError(child
);
1736 * If the container type has not been defined explicitly, we assume it
1739 if (containerTypeDeclaration
== null) {
1740 IDeclaration enumDecl
;
1742 * it could be because the enum was already declared.
1744 if (enumName
!= null) {
1745 enumDecl
= getCurrentScope().rlookupEnum(enumName
);
1746 if (enumDecl
!= null) {
1747 return (EnumDeclaration
) enumDecl
;
1751 IDeclaration decl
= getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1754 throw new ParseException(
1755 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1756 } else if (!(decl
instanceof IntegerDeclaration
)) {
1757 throw new ParseException(
1758 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1761 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1765 * If it has a body, it's a new declaration, otherwise it's a reference
1766 * to an existing declaration. Same logic as struct.
1768 if (enumBody
!= null) {
1770 * If enum has a name, check if already defined in the current
1773 if ((enumName
!= null)
1774 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1775 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1776 + " already defined"); //$NON-NLS-1$
1779 /* Create the declaration */
1780 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1782 /* Parse the body */
1783 parseEnumBody(enumBody
, enumDeclaration
);
1785 /* If the enum has name, add it to the current scope. */
1786 if (enumName
!= null) {
1787 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1790 if (enumName
!= null) {
1791 /* Name and !body */
1793 /* Lookup the name in the current scope. */
1794 enumDeclaration
= getCurrentScope().rlookupEnum(enumName
);
1797 * If not found, it means that an enum with such name has not
1800 if (enumDeclaration
== null) {
1801 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1802 + " is not defined"); //$NON-NLS-1$
1805 /* !Name and !body */
1806 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1810 return enumDeclaration
;
1815 * Parses an enum body, adding the enumerators to the specified enum
1819 * An ENUM_BODY node.
1820 * @param enumDeclaration
1821 * The enum declaration.
1822 * @throws ParseException
1824 private void parseEnumBody(CommonTree enumBody
,
1825 EnumDeclaration enumDeclaration
) throws ParseException
{
1827 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1828 /* enum body can't be empty (unlike struct). */
1833 * Start at -1, so that if the first enumrator has no explicit value, it
1838 for (CommonTree enumerator
: enumerators
) {
1839 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1848 * Parses an enumerator node and adds an enumerator declaration to an
1849 * enumeration declaration.
1851 * The high value of the range of the last enumerator is needed in case the
1852 * current enumerator does not specify its value.
1855 * An ENUM_ENUMERATOR node.
1856 * @param enumDeclaration
1857 * en enumeration declaration to which will be added the
1860 * The high value of the range of the last enumerator
1861 * @return The high value of the value range of the current enumerator.
1862 * @throws ParseException
1864 private static long parseEnumEnumerator(CommonTree enumerator
,
1865 EnumDeclaration enumDeclaration
, long lastHigh
)
1866 throws ParseException
{
1868 List
<CommonTree
> children
= enumerator
.getChildren();
1870 long low
= 0, high
= 0;
1871 boolean valueSpecified
= false;
1872 String label
= null;
1874 for (CommonTree child
: children
) {
1875 if (isAnyUnaryString(child
)) {
1876 label
= parseUnaryString(child
);
1877 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1879 valueSpecified
= true;
1881 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1883 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1885 valueSpecified
= true;
1887 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1888 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1890 childTypeError(child
);
1894 if (!valueSpecified
) {
1900 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1903 if (!enumDeclaration
.add(low
, high
, label
)) {
1904 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1907 if (valueSpecified
&& (BigInteger
.valueOf(low
).compareTo(enumDeclaration
.getContainerType().getMinValue()) == -1 ||
1908 BigInteger
.valueOf(high
).compareTo(enumDeclaration
.getContainerType().getMaxValue()) == 1)) {
1909 throw new ParseException("enum value is not in range"); //$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$
2225 childTypeError(typeSpecifier
);
2231 * Creates the string representation of a list of pointers.
2233 * @param pointerList
2234 * A list of pointer nodes. If pointerList is null, this function
2237 * A stringbuilder to which will be appended the string.
2239 private static void createPointerListString(List
<CommonTree
> pointerList
,
2241 if (pointerList
== null) {
2245 for (CommonTree pointer
: pointerList
) {
2247 sb
.append(" *"); //$NON-NLS-1$
2248 if (pointer
.getChildCount() > 0) {
2250 sb
.append(" const"); //$NON-NLS-1$
2257 * The node to check.
2258 * @return True if the given node is an unary string.
2260 private static boolean isUnaryString(CommonTree node
) {
2261 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
));
2266 * The node to check.
2267 * @return True if the given node is any type of unary string (no quotes, quotes, etc).
2269 private static boolean isAnyUnaryString(CommonTree node
) {
2270 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) ||
2271 (node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
));
2276 * The node to check.
2277 * @return True if the given node is an unary integer.
2279 private static boolean isUnaryInteger(CommonTree node
) {
2280 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) ||
2281 (node
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) ||
2282 (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2286 * Parses a unary string node and return the string value.
2288 * @param unaryString
2289 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2290 * or UNARY_EXPRESSION_STRING_QUOTES).
2291 * @return The string value.
2294 * It would be really nice to remove the quotes earlier, such as in the
2297 private static String
parseUnaryString(CommonTree unaryString
) {
2299 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2300 String strval
= value
.getText();
2303 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2304 strval
= strval
.substring(1, strval
.length() - 1);
2311 * Parses an unary integer (dec, hex or oct).
2313 * @param unaryInteger
2314 * An unary integer node.
2315 * @return The integer value.
2316 * @throws CTFReaderException
2318 private static long parseUnaryInteger(CommonTree unaryInteger
) throws ParseException
{
2320 List
<CommonTree
> children
= unaryInteger
.getChildren();
2321 CommonTree value
= children
.get(0);
2322 String strval
= value
.getText();
2326 if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_DEC
) {
2327 intval
= Long
.parseLong(strval
, 10);
2328 } else if (unaryInteger
.getType() == CTFParser
.UNARY_EXPRESSION_HEX
) {
2329 intval
= Long
.parseLong(strval
, 0x10);
2330 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2331 intval
= Long
.parseLong(strval
, 010); // 010 == 0x08 == 8
2333 } catch (NumberFormatException e
) {
2334 throw new ParseException("Invalid integer format: " + strval
); //$NON-NLS-1$
2337 /* The rest of children are sign */
2338 if ((children
.size() % 2) == 0) {
2344 private static long getMajorOrMinor(CommonTree rightNode
)
2345 throws ParseException
{
2347 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2349 if (isUnaryInteger(firstChild
)) {
2350 if (rightNode
.getChildCount() > 1) {
2351 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2354 long m
= parseUnaryInteger(firstChild
);
2357 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2362 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2365 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2367 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2369 if (isAnyUnaryString(firstChild
)) {
2370 if (rightNode
.getChildCount() > 1) {
2371 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2374 String uuidstr
= parseUnaryString(firstChild
);
2377 return UUID
.fromString(uuidstr
);
2378 } catch (IllegalArgumentException e
) {
2379 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2382 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2386 * Gets the value of a "signed" integer attribute.
2390 * @return The "signed" value as a boolean.
2391 * @throws ParseException
2393 private static boolean getSigned(CommonTree rightNode
)
2394 throws ParseException
{
2396 boolean ret
= false;
2397 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2399 if (isUnaryString(firstChild
)) {
2400 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2402 if (strval
.equals(MetadataStrings
.TRUE
)
2403 || strval
.equals(MetadataStrings
.TRUE2
)) {
2405 } else if (strval
.equals(MetadataStrings
.FALSE
)
2406 || strval
.equals(MetadataStrings
.FALSE2
)) {
2409 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2410 + firstChild
.getChild(0).getText());
2412 } else if (isUnaryInteger(firstChild
)) {
2413 /* Happens if the value is something like "1234.hello" */
2414 if (rightNode
.getChildCount() > 1) {
2415 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2418 long intval
= parseUnaryInteger(firstChild
);
2422 } else if (intval
== 0) {
2425 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2426 + firstChild
.getChild(0).getText());
2429 throw new ParseException();
2436 * Gets the value of a "byte_order" integer attribute.
2440 * @return The "byte_order" value.
2441 * @throws ParseException
2443 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2445 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2447 if (isUnaryString(firstChild
)) {
2448 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2450 if (strval
.equals(MetadataStrings
.LE
)) {
2451 return ByteOrder
.LITTLE_ENDIAN
;
2452 } else if (strval
.equals(MetadataStrings
.BE
)
2453 || strval
.equals(MetadataStrings
.NETWORK
)) {
2454 return ByteOrder
.BIG_ENDIAN
;
2455 } else if (strval
.equals(MetadataStrings
.NATIVE
)) {
2456 return trace
.getByteOrder();
2458 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2461 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2465 * Determines if the given value is a valid alignment value.
2468 * The value to check.
2469 * @return True if it is valid.
2471 private static boolean isValidAlignment(long alignment
) {
2472 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2476 * Gets the value of a "size" integer attribute.
2480 * @return The "size" value.
2481 * @throws ParseException
2483 private static long getSize(CommonTree rightNode
) throws ParseException
{
2485 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2487 if (isUnaryInteger(firstChild
)) {
2488 if (rightNode
.getChildCount() > 1) {
2489 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2492 long size
= parseUnaryInteger(firstChild
);
2495 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2500 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2504 * Gets the value of a "align" integer or struct attribute.
2507 * A CTF_RIGHT node or directly an unary integer.
2508 * @return The align value.
2509 * @throws ParseException
2511 private static long getAlignment(CommonTree node
) throws ParseException
{
2514 * If a CTF_RIGHT node was passed, call getAlignment with the first
2517 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2518 if (node
.getChildCount() > 1) {
2519 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2522 return getAlignment((CommonTree
) node
.getChild(0));
2523 } else if (isUnaryInteger(node
)) {
2524 long alignment
= parseUnaryInteger(node
);
2526 if (!isValidAlignment(alignment
)) {
2527 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2533 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2537 * Gets the value of a "base" integer attribute.
2540 * An CTF_RIGHT node.
2541 * @return The "base" value.
2542 * @throws ParseException
2544 private static int getBase(CommonTree rightNode
) throws ParseException
{
2546 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2548 if (isUnaryInteger(firstChild
)) {
2549 if (rightNode
.getChildCount() > 1) {
2550 throw new ParseException("invalid base value"); //$NON-NLS-1$
2553 long intval
= parseUnaryInteger(firstChild
);
2554 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2555 || (intval
== 16)) {
2556 return (int) intval
;
2558 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2559 } else if (isUnaryString(firstChild
)) {
2560 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2562 if (strval
.equals(MetadataStrings
.DECIMAL
)
2563 || strval
.equals(MetadataStrings
.DEC
)
2564 || strval
.equals(MetadataStrings
.DEC_CTE
)
2565 || strval
.equals(MetadataStrings
.INT_MOD
)
2566 || strval
.equals(MetadataStrings
.UNSIGNED_CTE
)) {
2568 } else if (strval
.equals(MetadataStrings
.HEXADECIMAL
)
2569 || strval
.equals(MetadataStrings
.HEX
)
2570 || strval
.equals(MetadataStrings
.X
)
2571 || strval
.equals(MetadataStrings
.X2
)
2572 || strval
.equals(MetadataStrings
.POINTER
)) {
2574 } else if (strval
.equals(MetadataStrings
.OCTAL
)
2575 || strval
.equals(MetadataStrings
.OCT
)
2576 || strval
.equals(MetadataStrings
.OCTAL_CTE
)) {
2578 } else if (strval
.equals(MetadataStrings
.BINARY
)
2579 || strval
.equals(MetadataStrings
.BIN
)) {
2582 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2585 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2590 * Gets the value of an "encoding" integer attribute.
2594 * @return The "encoding" value.
2595 * @throws ParseException
2597 private static Encoding
getEncoding(CommonTree rightNode
)
2598 throws ParseException
{
2600 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2602 if (isUnaryString(firstChild
)) {
2603 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2605 if (strval
.equals(MetadataStrings
.UTF8
)) {
2606 return Encoding
.UTF8
;
2607 } else if (strval
.equals(MetadataStrings
.ASCII
)) {
2608 return Encoding
.ASCII
;
2609 } else if (strval
.equals(MetadataStrings
.NONE
)) {
2610 return Encoding
.NONE
;
2612 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2615 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2618 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2620 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2622 if (isUnaryInteger(firstChild
)) {
2623 if (rightNode
.getChildCount() > 1) {
2624 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2627 long intval
= parseUnaryInteger(firstChild
);
2631 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2634 private static String
getEventName(CommonTree rightNode
)
2635 throws ParseException
{
2637 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2639 if (isAnyUnaryString(firstChild
)) {
2640 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2644 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2647 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2649 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2651 if (isUnaryInteger(firstChild
)) {
2652 if (rightNode
.getChildCount() > 1) {
2653 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2656 long intval
= parseUnaryInteger(firstChild
);
2660 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2664 * Concatenates a list of unary strings separated by arrows (->) or dots.
2667 * A list, first element being an unary string, subsequent
2668 * elements being ARROW or DOT nodes with unary strings as child.
2669 * @return The string representation of the unary string chain.
2671 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2673 StringBuilder sb
= new StringBuilder();
2675 CommonTree first
= strings
.get(0);
2676 sb
.append(parseUnaryString(first
));
2678 boolean isFirst
= true;
2680 for (CommonTree ref
: strings
) {
2687 CommonTree id
= (CommonTree
) ref
.getChild(0);
2689 if (ref
.getType() == CTFParser
.ARROW
) {
2690 sb
.append("->"); //$NON-NLS-1$
2695 sb
.append(parseUnaryString(id
));
2698 return sb
.toString();
2702 * Throws a ParseException stating that the parent-child relation between
2703 * the given node and its parent is not valid. It means that the shape of
2704 * the AST is unexpected.
2707 * The invalid child node.
2708 * @throws ParseException
2710 private static void childTypeError(CommonTree child
) throws ParseException
{
2711 CommonTree parent
= (CommonTree
) child
.getParent();
2712 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2713 + " can't have a child of type " //$NON-NLS-1$
2714 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2716 throw new ParseException(error
);
2719 // ------------------------------------------------------------------------
2721 // ------------------------------------------------------------------------
2724 * Adds a new declaration scope on the top of the scope stack.
2726 private void pushScope() {
2727 scope
= new DeclarationScope(scope
);
2731 * Removes the top declaration scope from the scope stack.
2733 private void popScope() {
2734 scope
= scope
.getParentScope();
2738 * Returns the current declaration scope.
2740 * @return The current declaration scope.
2742 private DeclarationScope
getCurrentScope() {