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("Only one trace block is allowed"); //$NON-NLS-1$
153 case CTFParser
.STREAM
:
156 case CTFParser
.EVENT
:
159 case CTFParser
.CLOCK
:
163 environments
.add(child
);
165 case CTFParser
.CALLSITE
:
166 callsites
.add(child
);
169 childTypeError(child
);
173 out
.write("Declarations\n"); //$NON-NLS-1$
175 for (CommonTree decl
: declarations
) {
177 out
.write(decl
.toString() + '\n');
179 parseRootDeclaration(decl
);
181 if (traceNode
== null) {
182 throw new ParseException("Missing trace block"); //$NON-NLS-1$
185 parseTrace(traceNode
);
188 out
.write("Environments\n"); //$NON-NLS-1$
190 for (CommonTree environment
: environments
) {
191 parseEnvironment(environment
);
194 out
.write("Clocks\n"); //$NON-NLS-1$
196 for (CommonTree clock
: clocks
) {
200 out
.write("Callsites\n"); //$NON-NLS-1$
202 for (CommonTree callsite
: callsites
) {
203 parseCallsite(callsite
);
207 out
.write("Streams\n"); //$NON-NLS-1$
209 if (streams
.size() > 0) {
210 for (CommonTree stream
: streams
) {
213 out
.write(stream
.toString() + '\n');
214 } catch (IOException e
) {
221 /* Add an empty stream that will have a null id */
222 trace
.addStream(new Stream(trace
));
226 out
.write("Events\n"); //$NON-NLS-1$
228 for (CommonTree event
: events
) {
231 CommonTree name
= (CommonTree
) event
.getChild(0).getChild(1).getChild(0).getChild(0);
232 CommonTree id
= (CommonTree
) event
.getChild(1).getChild(1).getChild(0).getChild(0);
233 out
.write("Name = " + name
+ " Id = " + id
+ '\n'); //$NON-NLS-1$ //$NON-NLS-2$
241 } catch (IOException e
) {
247 private void parseCallsite(CommonTree callsite
) {
249 List
<CommonTree
> children
= callsite
.getChildren();
251 String funcName
= null;
252 long lineNumber
= -1;
254 String fileName
= null;
256 for (CommonTree child
: children
) {
258 /* this is a regex to find the leading and trailing quotes */
259 final String regex
= "^\"|\"$"; //$NON-NLS-1$
261 * this is to replace the previous quotes with nothing...
262 * effectively deleting them
264 final String nullString
= ""; //$NON-NLS-1$
265 left
= child
.getChild(0).getChild(0).getChild(0).getText();
266 if (left
.equals("name")) { //$NON-NLS-1$
267 name
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
268 } else if (left
.equals("func")) { //$NON-NLS-1$
269 funcName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
270 } else if (left
.equals("ip")) { //$NON-NLS-1$
272 ip
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText().substring(2), 16);
273 } else if (left
.equals("file")) { //$NON-NLS-1$
274 fileName
= child
.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex
, nullString
);
275 } else if (left
.equals("line")) { //$NON-NLS-1$
276 lineNumber
= Long
.parseLong(child
.getChild(1).getChild(0).getChild(0).getText());
279 trace
.addCallsite(name
, funcName
, ip
, fileName
, lineNumber
);
282 private void parseEnvironment(CommonTree environment
) {
283 List
<CommonTree
> children
= environment
.getChildren();
284 for (CommonTree child
: children
) {
287 left
= child
.getChild(0).getChild(0).getChild(0).getText();
288 right
= child
.getChild(1).getChild(0).getChild(0).getText();
289 trace
.addEnvironmentVar(left
, right
);
293 private void parseClock(CommonTree clock
) {
294 List
<CommonTree
> children
= clock
.getChildren();
295 CTFClock ctfClock
= new CTFClock();
296 for (CommonTree child
: children
) {
297 final String key
= child
.getChild(0).getChild(0).getChild(0).getText();
298 final CommonTree value
= (CommonTree
) child
.getChild(1).getChild(0).getChild(0);
299 final int type
= value
.getType();
301 case CTFParser
.INTEGER
:
302 case CTFParser
.DECIMAL_LITERAL
:
304 * Not a pretty hack, this is to make sure that there is no
305 * number overflow due to 63 bit integers. The offset should
306 * only really be an issue in the year 2262. the tracer in C/ASM
307 * can write an offset in an unsigned 64 bit long. In java, the
308 * last bit, being set to 1 will be read as a negative number,
309 * but since it is too big a positive it will throw an
310 * exception. this will happen in 2^63 ns from 1970. Therefore
311 * 293 years from 1970
315 numValue
= Long
.parseLong(value
.getText());
316 } catch (Exception e
) {
317 numValue
= 1330938566783103277L;
319 ctfClock
.addAttribute(key
, numValue
);
322 ctfClock
.addAttribute(key
, value
.getText());
326 String nameValue
= ctfClock
.getName();
327 trace
.addClock(nameValue
, ctfClock
);
330 private void parseTrace(CommonTree traceNode
) throws ParseException
{
332 List
<CommonTree
> children
= traceNode
.getChildren();
333 if (children
== null) {
334 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
339 for (CommonTree child
: children
) {
340 switch (child
.getType()) {
341 case CTFParser
.TYPEALIAS
:
342 parseTypealias(child
);
344 case CTFParser
.TYPEDEF
:
347 case CTFParser
.CTF_EXPRESSION_TYPE
:
348 case CTFParser
.CTF_EXPRESSION_VAL
:
349 parseTraceDeclaration(child
);
352 childTypeError(child
);
358 * If trace byte order was not specified and not using packet based
361 if (trace
.getByteOrder() == null) {
362 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
368 private void parseTraceDeclaration(CommonTree traceDecl
)
369 throws ParseException
{
371 /* There should be a left and right */
373 CommonTree leftNode
= (CommonTree
) traceDecl
.getChild(0);
374 CommonTree rightNode
= (CommonTree
) traceDecl
.getChild(1);
376 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
378 if (!isAnyUnaryString(leftStrings
.get(0))) {
379 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
382 String left
= concatenateUnaryStrings(leftStrings
);
384 if (left
.equals(MetadataStrings
.MAJOR
)) {
385 if (trace
.majorIsSet()) {
386 throw new ParseException("major is already set"); //$NON-NLS-1$
389 trace
.setMajor(getMajorOrMinor(rightNode
));
390 } else if (left
.equals(MetadataStrings
.MINOR
)) {
391 if (trace
.minorIsSet()) {
392 throw new ParseException("minor is already set"); //$NON-NLS-1$
395 trace
.setMinor(getMajorOrMinor(rightNode
));
396 } else if (left
.equals(MetadataStrings
.UUID_STRING
)) {
397 UUID uuid
= getUUID(rightNode
);
400 * If uuid was already set by a metadata packet, compare it to see
403 if (trace
.uuidIsSet()) {
404 if (trace
.getUUID().compareTo(uuid
) != 0) {
405 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
406 + trace
.getUUID() + " but metadata says " + uuid
); //$NON-NLS-1$
412 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
413 ByteOrder byteOrder
= getByteOrder(rightNode
);
416 * If byte order was already set by a metadata packet, compare it to
419 if (trace
.getByteOrder() != null) {
420 if (trace
.getByteOrder() != byteOrder
) {
421 throw new ParseException(
422 "Endianness mismatch. Magic number says " //$NON-NLS-1$
423 + trace
.getByteOrder()
424 + " but metadata says " + byteOrder
); //$NON-NLS-1$
427 trace
.setByteOrder(byteOrder
);
428 final DeclarationScope parentScope
= scope
.getParentScope();
429 String types
[] = parentScope
.getTypeNames();
431 for (String type
: types
) {
432 IDeclaration d
= parentScope
.lookupType(type
);
433 if (d
instanceof IntegerDeclaration
) {
434 addByteOrder(byteOrder
, parentScope
, type
, (IntegerDeclaration
) d
);
435 } else if (d
instanceof StructDeclaration
) {
436 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
440 } else if (left
.equals(MetadataStrings
.PACKET_HEADER
)) {
441 if (trace
.packetHeaderIsSet()) {
442 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
445 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
447 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
448 throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
451 IDeclaration packetHeaderDecl
= parseTypeSpecifierList(
452 typeSpecifier
, null);
454 if (!(packetHeaderDecl
instanceof StructDeclaration
)) {
455 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
458 trace
.setPacketHeader((StructDeclaration
) packetHeaderDecl
);
460 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownTraceAttributeWarning
+ " " + left
); //$NON-NLS-1$
464 private static void addByteOrder(ByteOrder byteOrder
,
465 final DeclarationScope parentScope
, String name
,
466 IntegerDeclaration decl
) throws ParseException
{
468 if (decl
.getByteOrder() == null) {
469 IntegerDeclaration newI
;
470 newI
= new IntegerDeclaration(decl
.getLength(), decl
.isSigned(),
471 decl
.getBase(), byteOrder
, decl
.getEncoding(),
472 decl
.getClock(), decl
.getAlignment());
473 parentScope
.replaceType(name
, newI
);
477 private void setAlign(DeclarationScope parentScope
, StructDeclaration sd
,
478 ByteOrder byteOrder
) throws ParseException
{
480 for (String s
: sd
.getFieldsList()) {
481 IDeclaration d
= sd
.getFields().get(s
);
483 if (d
instanceof StructDeclaration
) {
484 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
486 } else if (d
instanceof VariantDeclaration
) {
487 setAlign(parentScope
, (VariantDeclaration
) d
, byteOrder
);
489 } else if (d
instanceof IntegerDeclaration
) {
490 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
491 if (decl
.getByteOrder() == null) {
492 IntegerDeclaration newI
;
493 newI
= new IntegerDeclaration(decl
.getLength(),
494 decl
.isSigned(), decl
.getBase(), byteOrder
,
495 decl
.getEncoding(), decl
.getClock(),
496 decl
.getAlignment());
497 sd
.getFields().put(s
, newI
);
503 private void setAlign(DeclarationScope parentScope
, VariantDeclaration vd
,
504 ByteOrder byteOrder
) throws ParseException
{
506 for (String s
: vd
.getFields().keySet()) {
507 IDeclaration d
= vd
.getFields().get(s
);
509 if (d
instanceof StructDeclaration
) {
510 setAlign(parentScope
, (StructDeclaration
) d
, byteOrder
);
512 } else if (d
instanceof IntegerDeclaration
) {
513 IntegerDeclaration decl
= (IntegerDeclaration
) d
;
514 IntegerDeclaration newI
;
515 newI
= new IntegerDeclaration(decl
.getLength(),
516 decl
.isSigned(), decl
.getBase(), byteOrder
,
517 decl
.getEncoding(), decl
.getClock(),
518 decl
.getAlignment());
519 vd
.getFields().put(s
, newI
);
524 private void parseStream(CommonTree streamNode
) throws ParseException
{
526 Stream stream
= new Stream(trace
);
528 List
<CommonTree
> children
= streamNode
.getChildren();
529 if (children
== null) {
530 throw new ParseException("Empty stream block"); //$NON-NLS-1$
535 for (CommonTree child
: children
) {
536 switch (child
.getType()) {
537 case CTFParser
.TYPEALIAS
:
538 parseTypealias(child
);
540 case CTFParser
.TYPEDEF
:
543 case CTFParser
.CTF_EXPRESSION_TYPE
:
544 case CTFParser
.CTF_EXPRESSION_VAL
:
545 parseStreamDeclaration(child
, stream
);
548 childTypeError(child
);
553 if (stream
.isIdSet()) {
554 if (!trace
.packetHeaderIsSet()
555 || !trace
.getPacketHeader().hasField(MetadataStrings
.STREAM_ID
)) {
556 throw new ParseException("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("Left side of CTF assignment must be a string"); //$NON-NLS-1$
579 String left
= concatenateUnaryStrings(leftStrings
);
581 if (left
.equals(MetadataStrings
.ID
)) {
582 if (stream
.isIdSet()) {
583 throw new ParseException("stream id already defined"); //$NON-NLS-1$
586 long streamID
= getStreamID(rightNode
);
588 stream
.setId(streamID
);
589 } else if (left
.equals(MetadataStrings
.EVENT_HEADER
)) {
590 if (stream
.isEventHeaderSet()) {
591 throw new ParseException("event.header already defined"); //$NON-NLS-1$
594 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
596 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
597 throw new ParseException("event.header expects a type specifier"); //$NON-NLS-1$
600 IDeclaration eventHeaderDecl
= parseTypeSpecifierList(
601 typeSpecifier
, null);
603 if (!(eventHeaderDecl
instanceof StructDeclaration
)) {
604 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
607 stream
.setEventHeader((StructDeclaration
) eventHeaderDecl
);
608 } else if (left
.equals(MetadataStrings
.EVENT_CONTEXT
)) {
609 if (stream
.isEventContextSet()) {
610 throw new ParseException("event.context already defined"); //$NON-NLS-1$
613 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
615 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
616 throw new ParseException("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(MetadataStrings
.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("packet.context expects a type specifier"); //$NON-NLS-1$
638 IDeclaration packetContextDecl
= parseTypeSpecifierList(
639 typeSpecifier
, null);
641 if (!(packetContextDecl
instanceof StructDeclaration
)) {
642 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
645 stream
.setPacketContext((StructDeclaration
) packetContextDecl
);
647 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownStreamAttributeWarning
+ " " + left
); //$NON-NLS-1$
651 private void parseEvent(CommonTree eventNode
) throws ParseException
{
653 List
<CommonTree
> children
= eventNode
.getChildren();
654 if (children
== null) {
655 throw new ParseException("Empty event block"); //$NON-NLS-1$
658 EventDeclaration event
= new EventDeclaration();
662 for (CommonTree child
: children
) {
663 switch (child
.getType()) {
664 case CTFParser
.TYPEALIAS
:
665 parseTypealias(child
);
667 case CTFParser
.TYPEDEF
:
670 case CTFParser
.CTF_EXPRESSION_TYPE
:
671 case CTFParser
.CTF_EXPRESSION_VAL
:
672 parseEventDeclaration(child
, event
);
675 childTypeError(child
);
680 if (!event
.nameIsSet()) {
681 throw new ParseException("Event name not set"); //$NON-NLS-1$
685 * If the event did not specify a stream, then the trace must be single
688 if (!event
.streamIsSet()) {
689 if (trace
.nbStreams() > 1) {
690 throw new ParseException("Event without stream_id with more than one stream"); //$NON-NLS-1$
694 * If the event did not specify a stream, the only existing stream
695 * must not have an id. Note: That behavior could be changed, it
696 * could be possible to just get the only existing stream, whatever
699 Stream stream
= trace
.getStream(null);
701 if (stream
!= null) {
702 event
.setStream(stream
);
704 throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
709 * Add the event to the stream.
711 event
.getStream().addEvent(event
);
716 private void parseEventDeclaration(CommonTree eventDecl
,
717 EventDeclaration event
) throws ParseException
{
719 /* There should be a left and right */
721 CommonTree leftNode
= (CommonTree
) eventDecl
.getChild(0);
722 CommonTree rightNode
= (CommonTree
) eventDecl
.getChild(1);
724 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
726 if (!isAnyUnaryString(leftStrings
.get(0))) {
727 throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
730 String left
= concatenateUnaryStrings(leftStrings
);
732 if (left
.equals(MetadataStrings
.NAME2
)) {
733 if (event
.nameIsSet()) {
734 throw new ParseException("name already defined"); //$NON-NLS-1$
737 String name
= getEventName(rightNode
);
740 } else if (left
.equals(MetadataStrings
.ID
)) {
741 if (event
.idIsSet()) {
742 throw new ParseException("id already defined"); //$NON-NLS-1$
745 long id
= getEventID(rightNode
);
748 } else if (left
.equals(MetadataStrings
.STREAM_ID
)) {
749 if (event
.streamIsSet()) {
750 throw new ParseException("stream id already defined"); //$NON-NLS-1$
753 long streamId
= getStreamID(rightNode
);
755 Stream stream
= trace
.getStream(streamId
);
757 if (stream
== null) {
758 throw new ParseException("Stream " + streamId
+ " not found"); //$NON-NLS-1$ //$NON-NLS-2$
761 event
.setStream(stream
);
762 } else if (left
.equals(MetadataStrings
.CONTEXT
)) {
763 if (event
.contextIsSet()) {
764 throw new ParseException("context already defined"); //$NON-NLS-1$
767 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
769 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
770 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
773 IDeclaration contextDecl
= parseTypeSpecifierList(typeSpecifier
,
776 if (!(contextDecl
instanceof StructDeclaration
)) {
777 throw new ParseException("context expects a struct"); //$NON-NLS-1$
780 event
.setContext((StructDeclaration
) contextDecl
);
781 } else if (left
.equals(MetadataStrings
.FIELDS_STRING
)) {
782 if (event
.fieldsIsSet()) {
783 throw new ParseException("fields already defined"); //$NON-NLS-1$
786 CommonTree typeSpecifier
= (CommonTree
) rightNode
.getChild(0);
788 if (typeSpecifier
.getType() != CTFParser
.TYPE_SPECIFIER_LIST
) {
789 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
792 IDeclaration fieldsDecl
;
793 fieldsDecl
= parseTypeSpecifierList(typeSpecifier
, null);
795 if (!(fieldsDecl
instanceof StructDeclaration
)) {
796 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
799 * The underscores in the event names. These underscores were added
800 * by the LTTng tracer.
802 final StructDeclaration fields
= (StructDeclaration
) fieldsDecl
;
803 event
.setFields(fields
);
804 } else if (left
.equals(MetadataStrings
.LOGLEVEL2
)) {
805 long logLevel
= parseUnaryInteger((CommonTree
) rightNode
.getChild(0));
806 event
.setLogLevel(logLevel
);
808 /* Custom event attribute, we'll add it to the attributes map */
809 String right
= parseUnaryString((CommonTree
) rightNode
.getChild(0));
810 event
.setCustomAttribute(left
, right
);
815 * Parses a declaration at the root level.
818 * The declaration subtree.
819 * @throws ParseException
821 private void parseRootDeclaration(CommonTree declaration
)
822 throws ParseException
{
824 List
<CommonTree
> children
= declaration
.getChildren();
826 for (CommonTree child
: children
) {
827 switch (child
.getType()) {
828 case CTFParser
.TYPEDEF
:
831 case CTFParser
.TYPEALIAS
:
832 parseTypealias(child
);
834 case CTFParser
.TYPE_SPECIFIER_LIST
:
835 parseTypeSpecifierList(child
, null);
838 childTypeError(child
);
844 * Parses a typealias node. It parses the target, the alias, and registers
845 * the type in the current scope.
849 * @throws ParseException
851 private void parseTypealias(CommonTree typealias
) throws ParseException
{
853 List
<CommonTree
> children
= typealias
.getChildren();
855 CommonTree target
= null;
856 CommonTree alias
= null;
858 for (CommonTree child
: children
) {
859 switch (child
.getType()) {
860 case CTFParser
.TYPEALIAS_TARGET
:
863 case CTFParser
.TYPEALIAS_ALIAS
:
867 childTypeError(child
);
872 IDeclaration targetDeclaration
= parseTypealiasTarget(target
);
874 if ((targetDeclaration
instanceof VariantDeclaration
)
875 && ((VariantDeclaration
) targetDeclaration
).isTagged()) {
876 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
879 String aliasString
= parseTypealiasAlias(alias
);
881 getCurrentScope().registerType(aliasString
, targetDeclaration
);
885 * Parses the target part of a typealias and gets the corresponding
889 * A TYPEALIAS_TARGET node.
890 * @return The corresponding declaration.
891 * @throws ParseException
893 private IDeclaration
parseTypealiasTarget(CommonTree target
)
894 throws ParseException
{
896 List
<CommonTree
> children
= target
.getChildren();
898 CommonTree typeSpecifierList
= null;
899 CommonTree typeDeclaratorList
= null;
900 CommonTree typeDeclarator
= null;
901 StringBuilder identifierSB
= new StringBuilder();
903 for (CommonTree child
: children
) {
904 switch (child
.getType()) {
905 case CTFParser
.TYPE_SPECIFIER_LIST
:
906 typeSpecifierList
= child
;
908 case CTFParser
.TYPE_DECLARATOR_LIST
:
909 typeDeclaratorList
= child
;
912 childTypeError(child
);
917 if (typeDeclaratorList
!= null) {
919 * Only allow one declarator
921 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
922 * otherwise the new type puint8_t would maps to two different
925 if (typeDeclaratorList
.getChildCount() != 1) {
926 throw new ParseException("Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
929 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
932 /* Parse the target type and get the declaration */
933 IDeclaration targetDeclaration
= parseTypeDeclarator(typeDeclarator
,
934 typeSpecifierList
, identifierSB
);
937 * We don't allow identifier in the target
939 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
942 if (identifierSB
.length() > 0) {
943 throw new ParseException("Identifier (" + identifierSB
.toString() //$NON-NLS-1$
944 + ") not expected in the typealias target"); //$NON-NLS-1$
947 return targetDeclaration
;
951 * Parses the alias part of a typealias. It parses the underlying specifier
952 * list and declarator and creates the string representation that will be
953 * used to register the type.
956 * A TYPEALIAS_ALIAS node.
957 * @return The string representation of the alias.
958 * @throws ParseException
960 private static String
parseTypealiasAlias(CommonTree alias
)
961 throws ParseException
{
963 List
<CommonTree
> children
= alias
.getChildren();
965 CommonTree typeSpecifierList
= null;
966 CommonTree typeDeclaratorList
= null;
967 CommonTree typeDeclarator
= null;
968 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
970 for (CommonTree child
: children
) {
971 switch (child
.getType()) {
972 case CTFParser
.TYPE_SPECIFIER_LIST
:
973 typeSpecifierList
= child
;
975 case CTFParser
.TYPE_DECLARATOR_LIST
:
976 typeDeclaratorList
= child
;
979 childTypeError(child
);
984 /* If there is a type declarator list, extract the pointers */
985 if (typeDeclaratorList
!= null) {
987 * Only allow one declarator
989 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
991 if (typeDeclaratorList
.getChildCount() != 1) {
992 throw new ParseException("Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
995 typeDeclarator
= (CommonTree
) typeDeclaratorList
.getChild(0);
997 List
<CommonTree
> typeDeclaratorChildren
= typeDeclarator
.getChildren();
999 for (CommonTree child
: typeDeclaratorChildren
) {
1000 switch (child
.getType()) {
1001 case CTFParser
.POINTER
:
1002 pointers
.add(child
);
1004 case CTFParser
.IDENTIFIER
:
1005 throw new ParseException("Identifier (" + child
.getText() //$NON-NLS-1$
1006 + ") not expected in the typealias target"); //$NON-NLS-1$
1008 childTypeError(child
);
1014 return createTypeDeclarationString(typeSpecifierList
, pointers
);
1018 * Parses a typedef node. This creates and registers a new declaration for
1019 * each declarator found in the typedef.
1023 * @throws ParseException
1024 * If there is an error creating the declaration.
1026 private void parseTypedef(CommonTree typedef
) throws ParseException
{
1028 CommonTree typeDeclaratorListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1030 CommonTree typeSpecifierListNode
= (CommonTree
) typedef
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1032 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1034 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1035 StringBuilder identifierSB
= new StringBuilder();
1037 IDeclaration typeDeclaration
= parseTypeDeclarator(
1038 typeDeclaratorNode
, typeSpecifierListNode
, identifierSB
);
1040 if ((typeDeclaration
instanceof VariantDeclaration
)
1041 && ((VariantDeclaration
) typeDeclaration
).isTagged()) {
1042 throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1045 getCurrentScope().registerType(identifierSB
.toString(),
1051 * Parses a pair type declarator / type specifier list and returns the
1052 * corresponding declaration. If it is present, it also writes the
1053 * identifier of the declarator in the given {@link StringBuilder}.
1055 * @param typeDeclarator
1056 * A TYPE_DECLARATOR node.
1057 * @param typeSpecifierList
1058 * A TYPE_SPECIFIER_LIST node.
1059 * @param identifierSB
1060 * A StringBuilder that will receive the identifier found in the
1062 * @return The corresponding declaration.
1063 * @throws ParseException
1064 * If there is an error finding or creating the declaration.
1066 private IDeclaration
parseTypeDeclarator(CommonTree typeDeclarator
,
1067 CommonTree typeSpecifierList
, StringBuilder identifierSB
)
1068 throws ParseException
{
1070 IDeclaration declaration
= null;
1071 List
<CommonTree
> children
= null;
1072 List
<CommonTree
> pointers
= new LinkedList
<CommonTree
>();
1073 List
<CommonTree
> lengths
= new LinkedList
<CommonTree
>();
1074 CommonTree identifier
= null;
1076 /* Separate the tokens by type */
1077 if (typeDeclarator
!= null) {
1078 children
= typeDeclarator
.getChildren();
1079 for (CommonTree child
: children
) {
1081 switch (child
.getType()) {
1082 case CTFParser
.POINTER
:
1083 pointers
.add(child
);
1085 case CTFParser
.IDENTIFIER
:
1088 case CTFParser
.LENGTH
:
1092 childTypeError(child
);
1100 * Parse the type specifier list, which is the "base" type. For example,
1101 * it would be int in int a[3][len].
1103 declaration
= parseTypeSpecifierList(typeSpecifierList
, pointers
);
1106 * Each length subscript means that we must create a nested array or
1107 * sequence. For example, int a[3][len] means that we have an array of 3
1108 * (sequences of length 'len' of (int)).
1110 if (lengths
.size() > 0) {
1111 /* We begin at the end */
1112 Collections
.reverse(lengths
);
1114 for (CommonTree length
: lengths
) {
1116 * By looking at the first expression, we can determine whether
1117 * it is an array or a sequence.
1119 List
<CommonTree
> lengthChildren
= length
.getChildren();
1121 CommonTree first
= lengthChildren
.get(0);
1122 if (isUnaryInteger(first
)) {
1124 int arrayLength
= (int) parseUnaryInteger(first
);
1126 if (arrayLength
< 1) {
1127 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1130 /* Create the array declaration. */
1131 declaration
= new ArrayDeclaration(arrayLength
, declaration
);
1132 } else if (isAnyUnaryString(first
)) {
1134 String lengthName
= concatenateUnaryStrings(lengthChildren
);
1136 /* check that lengthName was declared */
1137 if (isSignedIntegerField(lengthName
)) {
1138 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
1140 /* Create the sequence declaration. */
1141 declaration
= new SequenceDeclaration(lengthName
,
1144 childTypeError(first
);
1149 if (identifier
!= null) {
1150 identifierSB
.append(identifier
.getText());
1156 private boolean isSignedIntegerField(String lengthName
) throws ParseException
{
1157 IDeclaration decl
= getCurrentScope().lookupIdentifierRecursive(lengthName
);
1158 if (decl
instanceof IntegerDeclaration
) {
1159 return ((IntegerDeclaration
) decl
).isSigned();
1161 throw new ParseException("Is not an integer: " + lengthName
); //$NON-NLS-1$
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 (!isAnyUnaryString(leftStrings
.get(0))) {
1262 throw new ParseException("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().lookupTypeRecursive(
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("Left side of ctf expression must be a string"); //$NON-NLS-1$
1381 String left
= concatenateUnaryStrings(leftStrings
);
1383 if (left
.equals("signed")) { //$NON-NLS-1$
1384 signed
= getSigned(rightNode
);
1385 } else if (left
.equals(MetadataStrings
.BYTE_ORDER
)) {
1386 byteOrder
= getByteOrder(rightNode
);
1387 } else if (left
.equals("size")) { //$NON-NLS-1$
1388 size
= getSize(rightNode
);
1389 } else if (left
.equals(MetadataStrings
.ALIGN
)) {
1390 alignment
= getAlignment(rightNode
);
1391 } else if (left
.equals("base")) { //$NON-NLS-1$
1392 base
= getBase(rightNode
);
1393 } else if (left
.equals("encoding")) { //$NON-NLS-1$
1394 encoding
= getEncoding(rightNode
);
1395 } else if (left
.equals("map")) { //$NON-NLS-1$
1396 clock
= getClock(rightNode
);
1398 Activator
.log(IStatus
.WARNING
, Messages
.IOStructGen_UnknownIntegerAttributeWarning
+ " " + left
); //$NON-NLS-1$
1403 childTypeError(child
);
1409 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1412 if (alignment
== 0) {
1413 if ((size
% 8) == 0) {
1420 integerDeclaration
= new IntegerDeclaration((int) size
, signed
, base
,
1421 byteOrder
, encoding
, clock
, alignment
);
1423 return integerDeclaration
;
1426 private static String
getClock(CommonTree rightNode
) {
1427 return rightNode
.getChild(1).getChild(0).getChild(0).getText();
1430 private static StringDeclaration
parseString(CommonTree string
)
1431 throws ParseException
{
1433 List
<CommonTree
> children
= string
.getChildren();
1434 StringDeclaration stringDeclaration
= null;
1436 if (children
== null) {
1437 stringDeclaration
= new StringDeclaration();
1439 Encoding encoding
= Encoding
.UTF8
;
1440 for (CommonTree child
: children
) {
1441 switch (child
.getType()) {
1442 case CTFParser
.CTF_EXPRESSION_VAL
:
1444 * An assignment expression must have 2 children, left and
1448 CommonTree leftNode
= (CommonTree
) child
.getChild(0);
1449 CommonTree rightNode
= (CommonTree
) child
.getChild(1);
1451 List
<CommonTree
> leftStrings
= leftNode
.getChildren();
1453 if (!isAnyUnaryString(leftStrings
.get(0))) {
1454 throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
1456 String left
= concatenateUnaryStrings(leftStrings
);
1458 if (left
.equals("encoding")) { //$NON-NLS-1$
1459 encoding
= getEncoding(rightNode
);
1461 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1467 childTypeError(child
);
1472 stringDeclaration
= new StringDeclaration(encoding
);
1475 return stringDeclaration
;
1479 * Parses a struct declaration and returns the corresponding declaration.
1483 * @return The corresponding struct declaration.
1484 * @throws ParseException
1486 private StructDeclaration
parseStruct(CommonTree struct
)
1487 throws ParseException
{
1489 List
<CommonTree
> children
= struct
.getChildren();
1491 /* The return value */
1492 StructDeclaration structDeclaration
= null;
1495 String structName
= null;
1496 boolean hasName
= false;
1499 CommonTree structBody
= null;
1500 boolean hasBody
= false;
1503 long structAlign
= 0;
1505 /* Loop on all children and identify what we have to work with. */
1506 for (CommonTree child
: children
) {
1507 switch (child
.getType()) {
1508 case CTFParser
.STRUCT_NAME
: {
1511 CommonTree structNameIdentifier
= (CommonTree
) child
.getChild(0);
1513 structName
= structNameIdentifier
.getText();
1517 case CTFParser
.STRUCT_BODY
: {
1524 case CTFParser
.ALIGN
: {
1525 CommonTree structAlignExpression
= (CommonTree
) child
.getChild(0);
1527 structAlign
= getAlignment(structAlignExpression
);
1532 childTypeError(child
);
1539 * If a struct has just a body and no name (just like the song,
1540 * "A Struct With No Name" by America (sorry for that...)), it's a
1541 * definition of a new type, so we create the type declaration and
1542 * return it. We can't add it to the declaration scope since there is no
1543 * name, but that's what we want because it won't be possible to use it
1544 * again to declare another field.
1546 * If it has just a name, we look it up in the declaration scope and
1547 * return the associated declaration. If it is not found in the
1548 * declaration scope, it means that a struct with that name has not been
1549 * declared, which is an error.
1551 * If it has both, then we create the type declaration and register it
1552 * to the current scope.
1554 * If it has none, then what are we doing here ?
1558 * If struct has a name, check if already defined in the current
1561 if (hasName
&& (getCurrentScope().lookupStruct(structName
) != null)) {
1562 throw new ParseException("struct " + structName
//$NON-NLS-1$
1563 + " already defined."); //$NON-NLS-1$
1565 /* Create the declaration */
1566 structDeclaration
= new StructDeclaration(structAlign
);
1568 /* Parse the body */
1569 parseStructBody(structBody
, structDeclaration
);
1571 /* If struct has name, add it to the current scope. */
1573 getCurrentScope().registerStruct(structName
, structDeclaration
);
1575 } else /* !hasBody */{
1577 /* Name and !body */
1579 /* Lookup the name in the current scope. */
1580 structDeclaration
= getCurrentScope().lookupStructRecursive(structName
);
1583 * If not found, it means that a struct with such name has not
1586 if (structDeclaration
== null) {
1587 throw new ParseException("struct " + structName
//$NON-NLS-1$
1588 + " is not defined"); //$NON-NLS-1$
1591 /* !Name and !body */
1593 /* We can't do anything with that. */
1594 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1598 return structDeclaration
;
1602 * Parses a struct body, adding the fields to specified structure
1606 * A STRUCT_BODY node.
1607 * @param structDeclaration
1608 * The struct declaration.
1609 * @throws ParseException
1611 private void parseStructBody(CommonTree structBody
,
1612 StructDeclaration structDeclaration
) throws ParseException
{
1614 List
<CommonTree
> structDeclarations
= structBody
.getChildren();
1617 * If structDeclaration is null, structBody has no children and the
1618 * struct body is empty.
1620 if (structDeclarations
!= null) {
1623 for (CommonTree declarationNode
: structDeclarations
) {
1624 switch (declarationNode
.getType()) {
1625 case CTFParser
.TYPEALIAS
:
1626 parseTypealias(declarationNode
);
1628 case CTFParser
.TYPEDEF
:
1629 parseTypedef(declarationNode
);
1631 case CTFParser
.SV_DECLARATION
:
1632 parseStructDeclaration(declarationNode
, structDeclaration
);
1635 childTypeError(declarationNode
);
1644 * Parses a declaration found in a struct.
1646 * @param declaration
1647 * A SV_DECLARATION node.
1649 * A struct declaration. (I know, little name clash here...)
1650 * @throws ParseException
1652 private void parseStructDeclaration(CommonTree declaration
,
1653 StructDeclaration struct
) throws ParseException
{
1655 /* Get the type specifier list node */
1656 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
1658 /* Get the type declarator list node */
1659 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
1661 /* Get the type declarator list */
1662 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
1665 * For each type declarator, parse the declaration and add a field to
1668 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
1670 StringBuilder identifierSB
= new StringBuilder();
1672 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
1673 typeSpecifierListNode
, identifierSB
);
1674 String fieldName
= identifierSB
.toString();
1675 getCurrentScope().registerIdentifier(fieldName
, decl
);
1677 if (struct
.hasField(fieldName
)) {
1678 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1682 struct
.addField(fieldName
, decl
);
1688 * Parses an enum declaration and returns the corresponding declaration.
1692 * @return The corresponding enum declaration.
1693 * @throws ParseException
1695 private EnumDeclaration
parseEnum(CommonTree theEnum
) throws ParseException
{
1697 List
<CommonTree
> children
= theEnum
.getChildren();
1699 /* The return value */
1700 EnumDeclaration enumDeclaration
= null;
1703 String enumName
= null;
1706 CommonTree enumBody
= null;
1708 /* Container type */
1709 IntegerDeclaration containerTypeDeclaration
= null;
1711 /* Loop on all children and identify what we have to work with. */
1712 for (CommonTree child
: children
) {
1713 switch (child
.getType()) {
1714 case CTFParser
.ENUM_NAME
: {
1715 CommonTree enumNameIdentifier
= (CommonTree
) child
.getChild(0);
1716 enumName
= enumNameIdentifier
.getText();
1719 case CTFParser
.ENUM_BODY
: {
1723 case CTFParser
.ENUM_CONTAINER_TYPE
: {
1724 containerTypeDeclaration
= parseEnumContainerType(child
);
1728 childTypeError(child
);
1734 * If the container type has not been defined explicitly, we assume it
1737 if (containerTypeDeclaration
== null) {
1738 IDeclaration enumDecl
;
1740 * it could be because the enum was already declared.
1742 if (enumName
!= null) {
1743 enumDecl
= getCurrentScope().lookupEnumRecursive(enumName
);
1744 if (enumDecl
!= null) {
1745 return (EnumDeclaration
) enumDecl
;
1749 IDeclaration decl
= getCurrentScope().lookupTypeRecursive("int"); //$NON-NLS-1$
1752 throw new ParseException("enum container type implicit and type int not defined"); //$NON-NLS-1$
1753 } else if (!(decl
instanceof IntegerDeclaration
)) {
1754 throw new ParseException("enum container type implicit and type int not an integer"); //$NON-NLS-1$
1757 containerTypeDeclaration
= (IntegerDeclaration
) decl
;
1761 * If it has a body, it's a new declaration, otherwise it's a reference
1762 * to an existing declaration. Same logic as struct.
1764 if (enumBody
!= null) {
1766 * If enum has a name, check if already defined in the current
1769 if ((enumName
!= null)
1770 && (getCurrentScope().lookupEnum(enumName
) != null)) {
1771 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1772 + " already defined"); //$NON-NLS-1$
1775 /* Create the declaration */
1776 enumDeclaration
= new EnumDeclaration(containerTypeDeclaration
);
1778 /* Parse the body */
1779 parseEnumBody(enumBody
, enumDeclaration
);
1781 /* If the enum has name, add it to the current scope. */
1782 if (enumName
!= null) {
1783 getCurrentScope().registerEnum(enumName
, enumDeclaration
);
1786 if (enumName
!= null) {
1787 /* Name and !body */
1789 /* Lookup the name in the current scope. */
1790 enumDeclaration
= getCurrentScope().lookupEnumRecursive(enumName
);
1793 * If not found, it means that an enum with such name has not
1796 if (enumDeclaration
== null) {
1797 throw new ParseException("enum " + enumName
//$NON-NLS-1$
1798 + " is not defined"); //$NON-NLS-1$
1801 /* !Name and !body */
1802 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1806 return enumDeclaration
;
1811 * Parses an enum body, adding the enumerators to the specified enum
1815 * An ENUM_BODY node.
1816 * @param enumDeclaration
1817 * The enum declaration.
1818 * @throws ParseException
1820 private void parseEnumBody(CommonTree enumBody
,
1821 EnumDeclaration enumDeclaration
) throws ParseException
{
1823 List
<CommonTree
> enumerators
= enumBody
.getChildren();
1824 /* enum body can't be empty (unlike struct). */
1829 * Start at -1, so that if the first enumrator has no explicit value, it
1834 for (CommonTree enumerator
: enumerators
) {
1835 lastHigh
= parseEnumEnumerator(enumerator
, enumDeclaration
,
1844 * Parses an enumerator node and adds an enumerator declaration to an
1845 * enumeration declaration.
1847 * The high value of the range of the last enumerator is needed in case the
1848 * current enumerator does not specify its value.
1851 * An ENUM_ENUMERATOR node.
1852 * @param enumDeclaration
1853 * en enumeration declaration to which will be added the
1856 * The high value of the range of the last enumerator
1857 * @return The high value of the value range of the current enumerator.
1858 * @throws ParseException
1860 private static long parseEnumEnumerator(CommonTree enumerator
,
1861 EnumDeclaration enumDeclaration
, long lastHigh
)
1862 throws ParseException
{
1864 List
<CommonTree
> children
= enumerator
.getChildren();
1866 long low
= 0, high
= 0;
1867 boolean valueSpecified
= false;
1868 String label
= null;
1870 for (CommonTree child
: children
) {
1871 if (isAnyUnaryString(child
)) {
1872 label
= parseUnaryString(child
);
1873 } else if (child
.getType() == CTFParser
.ENUM_VALUE
) {
1875 valueSpecified
= true;
1877 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1879 } else if (child
.getType() == CTFParser
.ENUM_VALUE_RANGE
) {
1881 valueSpecified
= true;
1883 low
= parseUnaryInteger((CommonTree
) child
.getChild(0));
1884 high
= parseUnaryInteger((CommonTree
) child
.getChild(1));
1886 childTypeError(child
);
1890 if (!valueSpecified
) {
1896 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1899 if (!enumDeclaration
.add(low
, high
, label
)) {
1900 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1903 if (valueSpecified
&& (BigInteger
.valueOf(low
).compareTo(enumDeclaration
.getContainerType().getMinValue()) == -1 ||
1904 BigInteger
.valueOf(high
).compareTo(enumDeclaration
.getContainerType().getMaxValue()) == 1)) {
1905 throw new ParseException("enum value is not in range"); //$NON-NLS-1$
1912 * Parses an enum container type node and returns the corresponding integer
1915 * @param enumContainerType
1916 * An ENUM_CONTAINER_TYPE node.
1917 * @return An integer declaration corresponding to the container type.
1918 * @throws ParseException
1919 * If the type does not parse correctly or if it is not an
1922 private IntegerDeclaration
parseEnumContainerType(
1923 CommonTree enumContainerType
) throws ParseException
{
1925 /* Get the child, which should be a type specifier list */
1926 CommonTree typeSpecifierList
= (CommonTree
) enumContainerType
.getChild(0);
1928 /* Parse it and get the corresponding declaration */
1929 IDeclaration decl
= parseTypeSpecifierList(typeSpecifierList
, null);
1931 /* If is is an integer, return it, else throw an error */
1932 if (decl
instanceof IntegerDeclaration
) {
1933 return (IntegerDeclaration
) decl
;
1935 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1938 private VariantDeclaration
parseVariant(CommonTree variant
)
1939 throws ParseException
{
1941 List
<CommonTree
> children
= variant
.getChildren();
1942 VariantDeclaration variantDeclaration
= null;
1944 boolean hasName
= false;
1945 String variantName
= null;
1947 boolean hasBody
= false;
1948 CommonTree variantBody
= null;
1950 boolean hasTag
= false;
1951 String variantTag
= null;
1953 for (CommonTree child
: children
) {
1954 switch (child
.getType()) {
1955 case CTFParser
.VARIANT_NAME
:
1959 CommonTree variantNameIdentifier
= (CommonTree
) child
.getChild(0);
1961 variantName
= variantNameIdentifier
.getText();
1964 case CTFParser
.VARIANT_TAG
:
1968 CommonTree variantTagIdentifier
= (CommonTree
) child
.getChild(0);
1970 variantTag
= variantTagIdentifier
.getText();
1973 case CTFParser
.VARIANT_BODY
:
1977 variantBody
= child
;
1981 childTypeError(child
);
1988 * If variant has a name, check if already defined in the current
1992 && (getCurrentScope().lookupVariant(variantName
) != null)) {
1993 throw new ParseException("variant " + variantName
//$NON-NLS-1$
1994 + " already defined."); //$NON-NLS-1$
1997 /* Create the declaration */
1998 variantDeclaration
= new VariantDeclaration();
2000 /* Parse the body */
2001 parseVariantBody(variantBody
, variantDeclaration
);
2003 /* If variant has name, add it to the current scope. */
2005 getCurrentScope().registerVariant(variantName
,
2006 variantDeclaration
);
2008 } else /* !hasBody */{
2010 /* Name and !body */
2012 /* Lookup the name in the current scope. */
2013 variantDeclaration
= getCurrentScope().lookupVariantRecursive(
2017 * If not found, it means that a struct with such name has not
2020 if (variantDeclaration
== null) {
2021 throw new ParseException("variant " + variantName
//$NON-NLS-1$
2022 + " is not defined"); //$NON-NLS-1$
2025 /* !Name and !body */
2027 /* We can't do anything with that. */
2028 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2033 variantDeclaration
.setTag(variantTag
);
2036 return variantDeclaration
;
2039 private void parseVariantBody(CommonTree variantBody
,
2040 VariantDeclaration variantDeclaration
) throws ParseException
{
2042 List
<CommonTree
> variantDeclarations
= variantBody
.getChildren();
2046 for (CommonTree declarationNode
: variantDeclarations
) {
2047 switch (declarationNode
.getType()) {
2048 case CTFParser
.TYPEALIAS
:
2049 parseTypealias(declarationNode
);
2051 case CTFParser
.TYPEDEF
:
2052 parseTypedef(declarationNode
);
2054 case CTFParser
.SV_DECLARATION
:
2055 parseVariantDeclaration(declarationNode
, variantDeclaration
);
2058 childTypeError(declarationNode
);
2066 private void parseVariantDeclaration(CommonTree declaration
,
2067 VariantDeclaration variant
) throws ParseException
{
2069 /* Get the type specifier list node */
2070 CommonTree typeSpecifierListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_SPECIFIER_LIST
);
2072 /* Get the type declarator list node */
2073 CommonTree typeDeclaratorListNode
= (CommonTree
) declaration
.getFirstChildWithType(CTFParser
.TYPE_DECLARATOR_LIST
);
2075 /* Get the type declarator list */
2076 List
<CommonTree
> typeDeclaratorList
= typeDeclaratorListNode
.getChildren();
2079 * For each type declarator, parse the declaration and add a field to
2082 for (CommonTree typeDeclaratorNode
: typeDeclaratorList
) {
2084 StringBuilder identifierSB
= new StringBuilder();
2086 IDeclaration decl
= parseTypeDeclarator(typeDeclaratorNode
,
2087 typeSpecifierListNode
, identifierSB
);
2089 String name
= identifierSB
.toString();
2091 if (variant
.hasField(name
)) {
2092 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2096 getCurrentScope().registerIdentifier(name
, decl
);
2098 variant
.addField(name
, decl
);
2103 * Creates the string representation of a type declaration (type specifier
2106 * @param typeSpecifierList
2107 * A TYPE_SPECIFIER_LIST node.
2109 * A list of POINTER nodes.
2110 * @return The string representation.
2111 * @throws ParseException
2113 private static String
createTypeDeclarationString(
2114 CommonTree typeSpecifierList
, List
<CommonTree
> pointers
)
2115 throws ParseException
{
2116 StringBuilder sb
= new StringBuilder();
2118 createTypeSpecifierListString(typeSpecifierList
, sb
);
2119 createPointerListString(pointers
, sb
);
2121 return sb
.toString();
2125 * Creates the string representation of a list of type specifiers.
2127 * @param typeSpecifierList
2128 * A TYPE_SPECIFIER_LIST node.
2130 * A StringBuilder to which will be appended the string.
2131 * @throws ParseException
2133 private static void createTypeSpecifierListString(
2134 CommonTree typeSpecifierList
, StringBuilder sb
)
2135 throws ParseException
{
2137 List
<CommonTree
> children
= typeSpecifierList
.getChildren();
2139 boolean firstItem
= true;
2141 for (CommonTree child
: children
) {
2149 /* Append the string that represents this type specifier. */
2150 createTypeSpecifierString(child
, sb
);
2155 * Creates the string representation of a type specifier.
2157 * @param typeSpecifier
2158 * A TYPE_SPECIFIER node.
2160 * A StringBuilder to which will be appended the string.
2161 * @throws ParseException
2163 private static void createTypeSpecifierString(CommonTree typeSpecifier
,
2164 StringBuilder sb
) throws ParseException
{
2165 switch (typeSpecifier
.getType()) {
2166 case CTFParser
.FLOATTOK
:
2167 case CTFParser
.INTTOK
:
2168 case CTFParser
.LONGTOK
:
2169 case CTFParser
.SHORTTOK
:
2170 case CTFParser
.SIGNEDTOK
:
2171 case CTFParser
.UNSIGNEDTOK
:
2172 case CTFParser
.CHARTOK
:
2173 case CTFParser
.DOUBLETOK
:
2174 case CTFParser
.VOIDTOK
:
2175 case CTFParser
.BOOLTOK
:
2176 case CTFParser
.COMPLEXTOK
:
2177 case CTFParser
.IMAGINARYTOK
:
2178 case CTFParser
.CONSTTOK
:
2179 case CTFParser
.IDENTIFIER
:
2180 sb
.append(typeSpecifier
.getText());
2182 case CTFParser
.STRUCT
: {
2183 CommonTree structName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.STRUCT_NAME
);
2184 if (structName
== null) {
2185 throw new ParseException("nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2188 CommonTree structNameIdentifier
= (CommonTree
) structName
.getChild(0);
2190 sb
.append(structNameIdentifier
.getText());
2193 case CTFParser
.VARIANT
: {
2194 CommonTree variantName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.VARIANT_NAME
);
2195 if (variantName
== null) {
2196 throw new ParseException("nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2199 CommonTree variantNameIdentifier
= (CommonTree
) variantName
.getChild(0);
2201 sb
.append(variantNameIdentifier
.getText());
2204 case CTFParser
.ENUM
: {
2205 CommonTree enumName
= (CommonTree
) typeSpecifier
.getFirstChildWithType(CTFParser
.ENUM_NAME
);
2206 if (enumName
== null) {
2207 throw new ParseException("nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2210 CommonTree enumNameIdentifier
= (CommonTree
) enumName
.getChild(0);
2212 sb
.append(enumNameIdentifier
.getText());
2215 case CTFParser
.FLOATING_POINT
:
2216 case CTFParser
.INTEGER
:
2217 case CTFParser
.STRING
:
2218 throw new ParseException("CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2220 childTypeError(typeSpecifier
);
2226 * Creates the string representation of a list of pointers.
2228 * @param pointerList
2229 * A list of pointer nodes. If pointerList is null, this function
2232 * A stringbuilder to which will be appended the string.
2234 private static void createPointerListString(List
<CommonTree
> pointerList
,
2236 if (pointerList
== null) {
2240 for (CommonTree pointer
: pointerList
) {
2242 sb
.append(" *"); //$NON-NLS-1$
2243 if (pointer
.getChildCount() > 0) {
2245 sb
.append(" const"); //$NON-NLS-1$
2252 * The node to check.
2253 * @return True if the given node is an unary string.
2255 private static boolean isUnaryString(CommonTree node
) {
2256 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
));
2261 * The node to check.
2262 * @return True if the given node is any type of unary string (no quotes,
2265 private static boolean isAnyUnaryString(CommonTree node
) {
2266 return ((node
.getType() == CTFParser
.UNARY_EXPRESSION_STRING
) || (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
) || (node
.getType() == CTFParser
.UNARY_EXPRESSION_OCT
));
2280 * Parses a unary string node and return the string value.
2282 * @param unaryString
2283 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2284 * or UNARY_EXPRESSION_STRING_QUOTES).
2285 * @return The string value.
2288 * It would be really nice to remove the quotes earlier, such as in the
2291 private static String
parseUnaryString(CommonTree unaryString
) {
2293 CommonTree value
= (CommonTree
) unaryString
.getChild(0);
2294 String strval
= value
.getText();
2297 if (unaryString
.getType() == CTFParser
.UNARY_EXPRESSION_STRING_QUOTES
) {
2298 strval
= strval
.substring(1, strval
.length() - 1);
2305 * Parses an unary integer (dec, hex or oct).
2307 * @param unaryInteger
2308 * An unary integer node.
2309 * @return The integer value.
2310 * @throws CTFReaderException
2312 private static long parseUnaryInteger(CommonTree unaryInteger
) throws ParseException
{
2314 List
<CommonTree
> children
= unaryInteger
.getChildren();
2315 CommonTree value
= children
.get(0);
2316 String strval
= value
.getText();
2320 intval
= Long
.decode(strval
);
2321 } catch (NumberFormatException e
) {
2322 throw new ParseException("Invalid integer format: " + strval
); //$NON-NLS-1$
2325 /* The rest of children are sign */
2326 if ((children
.size() % 2) == 0) {
2332 private static long getMajorOrMinor(CommonTree rightNode
)
2333 throws ParseException
{
2335 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2337 if (isUnaryInteger(firstChild
)) {
2338 if (rightNode
.getChildCount() > 1) {
2339 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2342 long m
= parseUnaryInteger(firstChild
);
2345 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2350 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2353 private static UUID
getUUID(CommonTree rightNode
) throws ParseException
{
2355 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2357 if (isAnyUnaryString(firstChild
)) {
2358 if (rightNode
.getChildCount() > 1) {
2359 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2362 String uuidstr
= parseUnaryString(firstChild
);
2365 return UUID
.fromString(uuidstr
);
2366 } catch (IllegalArgumentException e
) {
2367 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2370 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2374 * Gets the value of a "signed" integer attribute.
2378 * @return The "signed" value as a boolean.
2379 * @throws ParseException
2381 private static boolean getSigned(CommonTree rightNode
)
2382 throws ParseException
{
2384 boolean ret
= false;
2385 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2387 if (isUnaryString(firstChild
)) {
2388 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2390 if (strval
.equals(MetadataStrings
.TRUE
)
2391 || strval
.equals(MetadataStrings
.TRUE2
)) {
2393 } else if (strval
.equals(MetadataStrings
.FALSE
)
2394 || strval
.equals(MetadataStrings
.FALSE2
)) {
2397 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2398 + firstChild
.getChild(0).getText());
2400 } else if (isUnaryInteger(firstChild
)) {
2401 /* Happens if the value is something like "1234.hello" */
2402 if (rightNode
.getChildCount() > 1) {
2403 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2406 long intval
= parseUnaryInteger(firstChild
);
2410 } else if (intval
== 0) {
2413 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2414 + firstChild
.getChild(0).getText());
2417 throw new ParseException();
2424 * Gets the value of a "byte_order" integer attribute.
2428 * @return The "byte_order" value.
2429 * @throws ParseException
2431 private ByteOrder
getByteOrder(CommonTree rightNode
) throws ParseException
{
2433 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2435 if (isUnaryString(firstChild
)) {
2436 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2438 if (strval
.equals(MetadataStrings
.LE
)) {
2439 return ByteOrder
.LITTLE_ENDIAN
;
2440 } else if (strval
.equals(MetadataStrings
.BE
)
2441 || strval
.equals(MetadataStrings
.NETWORK
)) {
2442 return ByteOrder
.BIG_ENDIAN
;
2443 } else if (strval
.equals(MetadataStrings
.NATIVE
)) {
2444 return trace
.getByteOrder();
2446 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2449 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2453 * Determines if the given value is a valid alignment value.
2456 * The value to check.
2457 * @return True if it is valid.
2459 private static boolean isValidAlignment(long alignment
) {
2460 return !((alignment
<= 0) || ((alignment
& (alignment
- 1)) != 0));
2464 * Gets the value of a "size" integer attribute.
2468 * @return The "size" value.
2469 * @throws ParseException
2471 private static long getSize(CommonTree rightNode
) throws ParseException
{
2473 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2475 if (isUnaryInteger(firstChild
)) {
2476 if (rightNode
.getChildCount() > 1) {
2477 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2480 long size
= parseUnaryInteger(firstChild
);
2483 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2488 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2492 * Gets the value of a "align" integer or struct attribute.
2495 * A CTF_RIGHT node or directly an unary integer.
2496 * @return The align value.
2497 * @throws ParseException
2499 private static long getAlignment(CommonTree node
) throws ParseException
{
2502 * If a CTF_RIGHT node was passed, call getAlignment with the first
2505 if (node
.getType() == CTFParser
.CTF_RIGHT
) {
2506 if (node
.getChildCount() > 1) {
2507 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2510 return getAlignment((CommonTree
) node
.getChild(0));
2511 } else if (isUnaryInteger(node
)) {
2512 long alignment
= parseUnaryInteger(node
);
2514 if (!isValidAlignment(alignment
)) {
2515 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2521 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2525 * Gets the value of a "base" integer attribute.
2528 * An CTF_RIGHT node.
2529 * @return The "base" value.
2530 * @throws ParseException
2532 private static int getBase(CommonTree rightNode
) throws ParseException
{
2534 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2536 if (isUnaryInteger(firstChild
)) {
2537 if (rightNode
.getChildCount() > 1) {
2538 throw new ParseException("invalid base value"); //$NON-NLS-1$
2541 long intval
= parseUnaryInteger(firstChild
);
2542 if ((intval
== 2) || (intval
== 8) || (intval
== 10)
2543 || (intval
== 16)) {
2544 return (int) intval
;
2546 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2547 } else if (isUnaryString(firstChild
)) {
2548 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2550 if (strval
.equals(MetadataStrings
.DECIMAL
)
2551 || strval
.equals(MetadataStrings
.DEC
)
2552 || strval
.equals(MetadataStrings
.DEC_CTE
)
2553 || strval
.equals(MetadataStrings
.INT_MOD
)
2554 || strval
.equals(MetadataStrings
.UNSIGNED_CTE
)) {
2556 } else if (strval
.equals(MetadataStrings
.HEXADECIMAL
)
2557 || strval
.equals(MetadataStrings
.HEX
)
2558 || strval
.equals(MetadataStrings
.X
)
2559 || strval
.equals(MetadataStrings
.X2
)
2560 || strval
.equals(MetadataStrings
.POINTER
)) {
2562 } else if (strval
.equals(MetadataStrings
.OCTAL
)
2563 || strval
.equals(MetadataStrings
.OCT
)
2564 || strval
.equals(MetadataStrings
.OCTAL_CTE
)) {
2566 } else if (strval
.equals(MetadataStrings
.BINARY
)
2567 || strval
.equals(MetadataStrings
.BIN
)) {
2570 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2573 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2578 * Gets the value of an "encoding" integer attribute.
2582 * @return The "encoding" value.
2583 * @throws ParseException
2585 private static Encoding
getEncoding(CommonTree rightNode
)
2586 throws ParseException
{
2588 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2590 if (isUnaryString(firstChild
)) {
2591 String strval
= concatenateUnaryStrings(rightNode
.getChildren());
2593 if (strval
.equals(MetadataStrings
.UTF8
)) {
2594 return Encoding
.UTF8
;
2595 } else if (strval
.equals(MetadataStrings
.ASCII
)) {
2596 return Encoding
.ASCII
;
2597 } else if (strval
.equals(MetadataStrings
.NONE
)) {
2598 return Encoding
.NONE
;
2600 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2603 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2606 private static long getStreamID(CommonTree rightNode
) throws ParseException
{
2608 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2610 if (isUnaryInteger(firstChild
)) {
2611 if (rightNode
.getChildCount() > 1) {
2612 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2615 long intval
= parseUnaryInteger(firstChild
);
2619 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2622 private static String
getEventName(CommonTree rightNode
)
2623 throws ParseException
{
2625 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2627 if (isAnyUnaryString(firstChild
)) {
2628 String str
= concatenateUnaryStrings(rightNode
.getChildren());
2632 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2635 private static long getEventID(CommonTree rightNode
) throws ParseException
{
2637 CommonTree firstChild
= (CommonTree
) rightNode
.getChild(0);
2639 if (isUnaryInteger(firstChild
)) {
2640 if (rightNode
.getChildCount() > 1) {
2641 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2644 long intval
= parseUnaryInteger(firstChild
);
2648 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2652 * Concatenates a list of unary strings separated by arrows (->) or dots.
2655 * A list, first element being an unary string, subsequent
2656 * elements being ARROW or DOT nodes with unary strings as child.
2657 * @return The string representation of the unary string chain.
2659 private static String
concatenateUnaryStrings(List
<CommonTree
> strings
) {
2661 StringBuilder sb
= new StringBuilder();
2663 CommonTree first
= strings
.get(0);
2664 sb
.append(parseUnaryString(first
));
2666 boolean isFirst
= true;
2668 for (CommonTree ref
: strings
) {
2674 CommonTree id
= (CommonTree
) ref
.getChild(0);
2676 if (ref
.getType() == CTFParser
.ARROW
) {
2677 sb
.append("->"); //$NON-NLS-1$
2682 sb
.append(parseUnaryString(id
));
2685 return sb
.toString();
2689 * Throws a ParseException stating that the parent-child relation between
2690 * the given node and its parent is not valid. It means that the shape of
2691 * the AST is unexpected.
2694 * The invalid child node.
2695 * @throws ParseException
2697 private static void childTypeError(CommonTree child
) throws ParseException
{
2698 CommonTree parent
= (CommonTree
) child
.getParent();
2699 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
2700 + " can't have a child of type " //$NON-NLS-1$
2701 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
2703 throw new ParseException(error
);
2706 // ------------------------------------------------------------------------
2708 // ------------------------------------------------------------------------
2711 * Adds a new declaration scope on the top of the scope stack.
2713 private void pushScope() {
2714 scope
= new DeclarationScope(scope
);
2718 * Removes the top declaration scope from the scope stack.
2720 private void popScope() {
2721 scope
= scope
.getParentScope();
2725 * Returns the current declaration scope.
2727 * @return The current declaration scope.
2729 private DeclarationScope
getCurrentScope() {