[Tmf][Ctf] Add descriptive fail to import messages.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / internal / ctf / core / event / metadata / IOStructGen.java
CommitLineData
866e5b51 1/*******************************************************************************
8e964be1 2 * Copyright (c) 2011-2013 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
3 *
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
8 *
9 * Contributors: Matthew Khouzam - Initial Design and Grammar
10 * Contributors: Francis Giraldeau - Initial API and implementation
8e964be1 11 * Contributors: Simon Marchi - Initial API and implementation
866e5b51
FC
12 *******************************************************************************/
13
ce2388e0 14package org.eclipse.linuxtools.internal.ctf.core.event.metadata;
866e5b51
FC
15
16import java.io.FileNotFoundException;
17import java.io.IOException;
18import java.io.UnsupportedEncodingException;
19import java.nio.ByteOrder;
20import java.util.ArrayList;
21import java.util.Collections;
866e5b51
FC
22import java.util.LinkedList;
23import java.util.List;
866e5b51
FC
24import java.util.UUID;
25
26import org.antlr.runtime.tree.CommonTree;
866e5b51 27import org.eclipse.linuxtools.ctf.core.event.CTFClock;
866e5b51
FC
28import org.eclipse.linuxtools.ctf.core.event.types.ArrayDeclaration;
29import org.eclipse.linuxtools.ctf.core.event.types.Encoding;
30import org.eclipse.linuxtools.ctf.core.event.types.EnumDeclaration;
53047a66 31import org.eclipse.linuxtools.ctf.core.event.types.FloatDeclaration;
866e5b51
FC
32import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration;
33import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
34import org.eclipse.linuxtools.ctf.core.event.types.SequenceDeclaration;
35import org.eclipse.linuxtools.ctf.core.event.types.StringDeclaration;
36import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
37import org.eclipse.linuxtools.ctf.core.event.types.VariantDeclaration;
a94410d9 38import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
866e5b51 39import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
486efb2e 40import org.eclipse.linuxtools.ctf.core.trace.Stream;
866e5b51 41import org.eclipse.linuxtools.ctf.parser.CTFParser;
8e964be1 42import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
ce2388e0 43import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException;
866e5b51 44
866e5b51 45/**
251274dd 46 * IOStructGen
866e5b51 47 */
866e5b51
FC
48public class IOStructGen {
49
50 // ------------------------------------------------------------------------
51 // Attributes
52 // ------------------------------------------------------------------------
53
54 static private final boolean DEBUG_ = false;
55
56 /**
57 * The trace
58 */
59 private final CTFTrace trace;
60 private final CommonTree tree;
61
62 /**
63 * The current declaration scope.
64 */
65 private DeclarationScope scope = null;
66
67 // ------------------------------------------------------------------------
68 // Constructor
69 // ------------------------------------------------------------------------
70
9ac2eb62
MK
71 /**
72 * Constuctor
be6df2d8
AM
73 *
74 * @param tree
75 * the tree (ANTLR generated) with the parsed TSDL data.
76 * @param trace
77 * the trace containing the places to put all the read metadata
9ac2eb62 78 */
866e5b51
FC
79 public IOStructGen(CommonTree tree, CTFTrace trace) {
80 this.trace = trace;
81 this.tree = tree;
82 }
83
9ac2eb62
MK
84 /**
85 * Parse the tree and populate the trace defined in the constructor.
be6df2d8 86 *
9ac2eb62 87 * @throws ParseException
be6df2d8 88 * If there was a problem parsing the metadata
9ac2eb62 89 */
866e5b51
FC
90 public void generate() throws ParseException {
91 parseRoot(tree);
92 }
93
94 // ------------------------------------------------------------------------
95 // Operations
96 // ------------------------------------------------------------------------
97
98 /**
99 * Parse the root node.
100 *
101 * @param root
102 * A ROOT node.
103 * @throws ParseException
104 */
105 private void parseRoot(CommonTree root) throws ParseException {
866e5b51
FC
106
107 List<CommonTree> children = root.getChildren();
866e5b51
FC
108 java.io.FileOutputStream fos = null;
109 java.io.OutputStreamWriter out = null;
110 if (DEBUG_) {
111 try {
112 fos = new java.io.FileOutputStream("/tmp/astInfo.txt"); //$NON-NLS-1$
113 out = new java.io.OutputStreamWriter(fos, "UTF-8"); //$NON-NLS-1$
114 } catch (FileNotFoundException e) {
115 e.printStackTrace();
116 return;
117 } catch (UnsupportedEncodingException e) {
118 e.printStackTrace();
119 return;
120 }
121 }
122
123 CommonTree traceNode = null;
124 List<CommonTree> streams = new ArrayList<CommonTree>();
125 List<CommonTree> events = new ArrayList<CommonTree>();
126 List<CommonTree> declarations = new ArrayList<CommonTree>();
127 List<CommonTree> environments = new ArrayList<CommonTree>();
128 List<CommonTree> clocks = new ArrayList<CommonTree>();
4c9d2941 129 List<CommonTree> callsites = new ArrayList<CommonTree>();
866e5b51
FC
130 /* Create a new declaration scope with no parent. */
131 pushScope();
132
133 try {
134 for (CommonTree child : children) {
4c9d2941 135 final int type = child.getType();
866e5b51
FC
136 if (DEBUG_) {
137 out.write(child.toString()
4c9d2941 138 + " -> " + type + '\n'); //$NON-NLS-1$
866e5b51 139 }
4c9d2941 140 switch (type) {
866e5b51
FC
141 case CTFParser.DECLARATION:
142 declarations.add(child);
143 break;
144 case CTFParser.TRACE:
145 if (traceNode != null) {
146 throw new ParseException(
147 "Only one trace block is allowed"); //$NON-NLS-1$
148 }
149 traceNode = child;
150 break;
151 case CTFParser.STREAM:
152 streams.add(child);
153 break;
154 case CTFParser.EVENT:
155 events.add(child);
156 break;
157 case CTFParser.CLOCK:
158 clocks.add(child);
159 break;
160 case CTFParser.ENV:
161 environments.add(child);
162 break;
4c9d2941
MK
163 case CTFParser.CALLSITE:
164 callsites.add(child);
165 break;
866e5b51
FC
166 default:
167 childTypeError(child);
168 }
169 }
866e5b51
FC
170 if (DEBUG_) {
171 out.write("Declarations\n"); //$NON-NLS-1$
172 }
173 for (CommonTree decl : declarations) {
174 if (DEBUG_) {
175 out.write(decl.toString() + '\n');
176 }
177 parseRootDeclaration(decl);
178 }
866e5b51
FC
179 if (traceNode == null) {
180 throw new ParseException("Missing trace block"); //$NON-NLS-1$
181 }
182
183 parseTrace(traceNode);
184
72dbc4ac
MK
185 if (DEBUG_) {
186 out.write("Environments\n"); //$NON-NLS-1$
187 }
188 for (CommonTree environment : environments) {
189 parseEnvironment(environment);
190 }
191 if (DEBUG_) {
192 out.write("Clocks\n"); //$NON-NLS-1$
193 }
194 for (CommonTree clock : clocks) {
195 parseClock(clock);
196 }
4c9d2941
MK
197 if (DEBUG_) {
198 out.write("Callsites\n"); //$NON-NLS-1$
199 }
200 for (CommonTree callsite : callsites) {
201 parseCallsite(callsite);
202 }
72dbc4ac 203
866e5b51
FC
204 if (DEBUG_) {
205 out.write("Streams\n"); //$NON-NLS-1$
206 }
207 if (streams.size() > 0) {
208 for (CommonTree stream : streams) {
209 if (DEBUG_) {
210 try {
211 out.write(stream.toString() + '\n');
212 } catch (IOException e) {
213 e.printStackTrace();
214 }
215 }
216 parseStream(stream);
217 }
218 } else {
219 /* Add an empty stream that will have a null id */
220 trace.addStream(new Stream(trace));
221 }
222
223 if (DEBUG_) {
224 out.write("Events\n"); //$NON-NLS-1$
225 }
226 for (CommonTree event : events) {
227 parseEvent(event);
866e5b51 228 if (DEBUG_) {
32ede2ec
MK
229 CommonTree name = (CommonTree) event.getChild(0).getChild(1).getChild(0).getChild(0);
230 CommonTree id = (CommonTree) event.getChild(1).getChild(1).getChild(0).getChild(0);
866e5b51
FC
231 out.write("Name = " + name + " Id = " + id + '\n'); //$NON-NLS-1$ //$NON-NLS-2$
232 }
233 }
234
235 if (DEBUG_) {
236 out.close();
237 fos.close();
238 }
239 } catch (IOException e) {
240 e.printStackTrace();
241 }
242 popScope();
243 }
244
4c9d2941
MK
245 private void parseCallsite(CommonTree callsite) {
246
247 List<CommonTree> children = callsite.getChildren();
248 String name = null;
249 String func_name = null;
250 long line_number = -1;
251 long ip = -1;
252 String file_name = null;
253
254 for (CommonTree child : children) {
255 String left;
256 /* this is a regex to find the leading and trailing quotes*/
257 final String regex = "^\"|\"$"; //$NON-NLS-1$
258 /* this is to replace the previous quotes with nothing... effectively deleting them */
259 final String nullString = ""; //$NON-NLS-1$
260 left = child.getChild(0).getChild(0).getChild(0).getText();
261 if (left.equals("name")) { //$NON-NLS-1$
262 name = child.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex, nullString);
263 } else if (left.equals("func")) { //$NON-NLS-1$
264 func_name = child.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex, nullString);
265 } else if (left.equals("ip")) { //$NON-NLS-1$
266 ip = Long.parseLong(child.getChild(1).getChild(0).getChild(0).getText().substring(2),16); // trim the 0x
267 } else if (left.equals("file")) { //$NON-NLS-1$
268 file_name = child.getChild(1).getChild(0).getChild(0).getText().replaceAll(regex, nullString);
269 } else if (left.equals("line")) { //$NON-NLS-1$
270 line_number = Long.parseLong(child.getChild(1).getChild(0).getChild(0).getText());
271 }
272 }
273 trace.addCallsite(name, func_name, ip,file_name, line_number);
274 }
275
866e5b51
FC
276 private void parseEnvironment(CommonTree environment) {
277 List<CommonTree> children = environment.getChildren();
278 for (CommonTree child : children) {
279 String left;
280 String right;
281 left = child.getChild(0).getChild(0).getChild(0).getText();
282 right = child.getChild(1).getChild(0).getChild(0).getText();
283 trace.addEnvironmentVar(left, right);
284 }
285 }
286
287 private void parseClock(CommonTree clock) {
288 List<CommonTree> children = clock.getChildren();
289 CTFClock ctfClock = new CTFClock();
290 for (CommonTree child : children) {
72dbc4ac 291 final String key = child.getChild(0).getChild(0).getChild(0).getText();
866e5b51
FC
292 final CommonTree value = (CommonTree) child.getChild(1).getChild(0).getChild(0);
293 final int type = value.getType();
294 switch (type) {
295 case CTFParser.INTEGER:
296 case CTFParser.DECIMAL_LITERAL:
284fdee8 297 /*
32ede2ec
MK
298 * Not a pretty hack, this is to make sure that there is no
299 * number overflow due to 63 bit integers. The offset should
300 * only really be an issue in the year 2262. the tracer in C/ASM
301 * can write an offset in an unsigned 64 bit long. In java, the
302 * last bit, being set to 1 will be read as a negative number,
303 * but since it is too big a positive it will throw an
304 * exception. this will happen in 2^63 ns from 1970. Therefore
305 * 293 years from 1970
284fdee8 306 */
866e5b51 307 Long numValue;
32ede2ec 308 try {
866e5b51 309 numValue = Long.parseLong(value.getText());
32ede2ec 310 } catch (Exception e) {
866e5b51
FC
311 numValue = 1330938566783103277L;
312 }
313 ctfClock.addAttribute(key, numValue);
314 break;
315 default:
316 ctfClock.addAttribute(key, value.getText());
317 }
318
319 }
320 String NameValue = ctfClock.getName();
321 trace.addClock(NameValue, ctfClock);
322 }
323
324 private void parseTrace(CommonTree traceNode) throws ParseException {
866e5b51
FC
325
326 List<CommonTree> children = traceNode.getChildren();
327 if (children == null) {
328 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
329 }
330
331 pushScope();
332
333 for (CommonTree child : children) {
334 switch (child.getType()) {
335 case CTFParser.TYPEALIAS:
336 parseTypealias(child);
337 break;
338 case CTFParser.TYPEDEF:
339 parseTypedef(child);
340 break;
341 case CTFParser.CTF_EXPRESSION_TYPE:
342 case CTFParser.CTF_EXPRESSION_VAL:
343 parseTraceDeclaration(child);
344 break;
345 default:
346 childTypeError(child);
347 break;
348 }
349 }
350
351 /*
352 * If trace byte order was not specified and not using packet based
353 * metadata
354 */
355 if (trace.getByteOrder() == null) {
356 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
357 }
358
359 popScope();
360 }
361
362 private void parseTraceDeclaration(CommonTree traceDecl)
363 throws ParseException {
866e5b51
FC
364
365 /* There should be a left and right */
866e5b51
FC
366
367 CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
866e5b51 368 CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
866e5b51
FC
369
370 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51
FC
371
372 if (!isUnaryString(leftStrings.get(0))) {
373 throw new ParseException(
374 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
375 }
376
377 String left = concatenateUnaryStrings(leftStrings);
378
07002e0a 379 if (left.equals(CTFStrings.MAJOR)) {
866e5b51
FC
380 if (trace.majortIsSet()) {
381 throw new ParseException("major is already set"); //$NON-NLS-1$
382 }
383
384 trace.setMajor(getMajorOrMinor(rightNode));
07002e0a 385 } else if (left.equals(CTFStrings.MINOR)) {
866e5b51
FC
386 if (trace.minorIsSet()) {
387 throw new ParseException("minor is already set"); //$NON-NLS-1$
388 }
389
390 trace.setMinor(getMajorOrMinor(rightNode));
07002e0a 391 } else if (left.equals(CTFStrings.UUID_STRING)) {
866e5b51
FC
392 UUID uuid = getUUID(rightNode);
393
394 /*
395 * If uuid was already set by a metadata packet, compare it to see
396 * if it matches
397 */
398 if (trace.UUIDIsSet()) {
399 if (trace.getUUID().compareTo(uuid) != 0) {
400 throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
401 + trace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
402 }
403 } else {
404 trace.setUUID(uuid);
405 }
406
07002e0a 407 } else if (left.equals(CTFStrings.BYTE_ORDER)) {
866e5b51
FC
408 ByteOrder byteOrder = getByteOrder(rightNode);
409
410 /*
411 * If byte order was already set by a metadata packet, compare it to
412 * see if it matches
413 */
414 if (trace.getByteOrder() != null) {
415 if (trace.getByteOrder() != byteOrder) {
416 throw new ParseException(
417 "Endianness mismatch. Magic number says " //$NON-NLS-1$
418 + trace.getByteOrder()
419 + " but metadata says " + byteOrder); //$NON-NLS-1$
420 }
421 } else {
422 trace.setByteOrder(byteOrder);
72dbc4ac
MK
423 final DeclarationScope parentScope = scope.getParentScope();
424 String types[] = parentScope.getTypeNames();
425
426 for (String type : types) {
427 IDeclaration d = parentScope.lookupType(type);
428 if (d instanceof IntegerDeclaration) {
429 addByteOrder(byteOrder, parentScope, type, (IntegerDeclaration) d);
430 } else if (d instanceof StructDeclaration) {
431 setAlign(parentScope, (StructDeclaration) d, byteOrder);
432 }
433 }
866e5b51 434 }
07002e0a 435 } else if (left.equals(CTFStrings.PACKET_HEADER)) {
866e5b51
FC
436 if (trace.packetHeaderIsSet()) {
437 throw new ParseException("packet.header already defined"); //$NON-NLS-1$
438 }
439
440 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
441
442 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
443 throw new ParseException(
444 "packet.header expects a type specifier"); //$NON-NLS-1$
445 }
446
447 IDeclaration packetHeaderDecl = parseTypeSpecifierList(
448 typeSpecifier, null);
449
450 if (!(packetHeaderDecl instanceof StructDeclaration)) {
451 throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
452 }
453
454 trace.setPacketHeader((StructDeclaration) packetHeaderDecl);
455 } else {
456 throw new ParseException("Unknown trace attribute : " + left); //$NON-NLS-1$
457 }
458 }
459
72dbc4ac
MK
460 private static void addByteOrder(ByteOrder byteOrder,
461 final DeclarationScope parentScope, String name,
462 IntegerDeclaration decl) throws ParseException {
463
464 if (decl.getByteOrder() == null) {
465 IntegerDeclaration newI;
466 newI = new IntegerDeclaration(decl.getLength(), decl.isSigned(),
467 decl.getBase(), byteOrder, decl.getEncoding(),
468 decl.getClock(), decl.getAlignment());
469 parentScope.replaceType(name, newI);
470 }
471 }
472
473 private void setAlign(DeclarationScope parentScope, StructDeclaration sd,
474 ByteOrder byteOrder) throws ParseException {
475
476 for (String s : sd.getFieldsList()) {
477 IDeclaration d = sd.getFields().get(s);
478
479 if (d instanceof StructDeclaration) {
480 setAlign(parentScope, (StructDeclaration) d, byteOrder);
481
482 } else if (d instanceof VariantDeclaration) {
483 setAlign(parentScope, (VariantDeclaration) d, byteOrder);
484
485 } else if (d instanceof IntegerDeclaration) {
486 IntegerDeclaration decl = (IntegerDeclaration) d;
487 if (decl.getByteOrder() == null) {
488 IntegerDeclaration newI;
489 newI = new IntegerDeclaration(decl.getLength(),
490 decl.isSigned(), decl.getBase(), byteOrder,
491 decl.getEncoding(), decl.getClock(),
492 decl.getAlignment());
493 sd.getFields().put(s, newI);
494 }
495 }
496 }
497 }
498
499 private void setAlign(DeclarationScope parentScope, VariantDeclaration vd,
500 ByteOrder byteOrder) throws ParseException {
501
502 for (String s : vd.getFields().keySet()) {
503 IDeclaration d = vd.getFields().get(s);
504
505 if (d instanceof StructDeclaration) {
506 setAlign(parentScope, (StructDeclaration) d, byteOrder);
507
508 } else if (d instanceof IntegerDeclaration) {
509 IntegerDeclaration decl = (IntegerDeclaration) d;
510 IntegerDeclaration newI;
511 newI = new IntegerDeclaration(decl.getLength(),
512 decl.isSigned(), decl.getBase(), byteOrder,
513 decl.getEncoding(), decl.getClock(),
514 decl.getAlignment());
515 vd.getFields().put(s, newI);
516 }
517 }
518 }
519
866e5b51 520 private void parseStream(CommonTree streamNode) throws ParseException {
866e5b51
FC
521
522 Stream stream = new Stream(trace);
523
524 List<CommonTree> children = streamNode.getChildren();
525 if (children == null) {
526 throw new ParseException("Empty stream block"); //$NON-NLS-1$
527 }
528
529 pushScope();
530
531 for (CommonTree child : children) {
532 switch (child.getType()) {
533 case CTFParser.TYPEALIAS:
534 parseTypealias(child);
535 break;
536 case CTFParser.TYPEDEF:
537 parseTypedef(child);
538 break;
539 case CTFParser.CTF_EXPRESSION_TYPE:
540 case CTFParser.CTF_EXPRESSION_VAL:
541 parseStreamDeclaration(child, stream);
542 break;
543 default:
544 childTypeError(child);
545 break;
546 }
547 }
548
9ac2eb62 549 if (stream.isIdSet()) {
866e5b51 550 if (!trace.packetHeaderIsSet()
07002e0a 551 || !trace.getPacketHeader().hasField(CTFStrings.STREAM_ID)) {
866e5b51
FC
552 throw new ParseException(
553 "Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
554 }
555 }
556
557 trace.addStream(stream);
558
559 popScope();
560 }
561
562 private void parseStreamDeclaration(CommonTree streamDecl, Stream stream)
563 throws ParseException {
866e5b51
FC
564
565 /* There should be a left and right */
866e5b51
FC
566
567 CommonTree leftNode = (CommonTree) streamDecl.getChild(0);
866e5b51 568 CommonTree rightNode = (CommonTree) streamDecl.getChild(1);
866e5b51
FC
569
570 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51
FC
571
572 if (!isUnaryString(leftStrings.get(0))) {
573 throw new ParseException(
574 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
575 }
576
577 String left = concatenateUnaryStrings(leftStrings);
578
07002e0a 579 if (left.equals(CTFStrings.ID)) {
9ac2eb62 580 if (stream.isIdSet()) {
866e5b51
FC
581 throw new ParseException("stream id already defined"); //$NON-NLS-1$
582 }
583
584 long streamID = getStreamID(rightNode);
585
586 stream.setId(streamID);
07002e0a 587 } else if (left.equals(CTFStrings.EVENT_HEADER)) {
9ac2eb62 588 if (stream.isEventHeaderSet()) {
866e5b51
FC
589 throw new ParseException("event.header already defined"); //$NON-NLS-1$
590 }
591
592 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
593
594 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
595 throw new ParseException(
596 "event.header expects a type specifier"); //$NON-NLS-1$
597 }
598
599 IDeclaration eventHeaderDecl = parseTypeSpecifierList(
600 typeSpecifier, null);
601
602 if (!(eventHeaderDecl instanceof StructDeclaration)) {
603 throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
604 }
605
606 stream.setEventHeader((StructDeclaration) eventHeaderDecl);
07002e0a 607 } else if (left.equals(CTFStrings.EVENT_CONTEXT)) {
9ac2eb62 608 if (stream.isEventContextSet()) {
866e5b51
FC
609 throw new ParseException("event.context already defined"); //$NON-NLS-1$
610 }
611
612 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
613
614 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
615 throw new ParseException(
616 "event.context expects a type specifier"); //$NON-NLS-1$
617 }
618
619 IDeclaration eventContextDecl = parseTypeSpecifierList(
620 typeSpecifier, null);
621
622 if (!(eventContextDecl instanceof StructDeclaration)) {
623 throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
624 }
625
626 stream.setEventContext((StructDeclaration) eventContextDecl);
07002e0a 627 } else if (left.equals(CTFStrings.PACKET_CONTEXT)) {
9ac2eb62 628 if (stream.isPacketContextSet()) {
866e5b51
FC
629 throw new ParseException("packet.context already defined"); //$NON-NLS-1$
630 }
631
632 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
633
634 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
635 throw new ParseException(
636 "packet.context expects a type specifier"); //$NON-NLS-1$
637 }
638
639 IDeclaration packetContextDecl = parseTypeSpecifierList(
640 typeSpecifier, null);
641
642 if (!(packetContextDecl instanceof StructDeclaration)) {
643 throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
644 }
645
646 stream.setPacketContext((StructDeclaration) packetContextDecl);
647 } else {
648 throw new ParseException("Unknown stream attribute : " + left); //$NON-NLS-1$
649 }
650 }
651
652 private void parseEvent(CommonTree eventNode) throws ParseException {
866e5b51
FC
653
654 List<CommonTree> children = eventNode.getChildren();
655 if (children == null) {
656 throw new ParseException("Empty event block"); //$NON-NLS-1$
657 }
658
659 EventDeclaration event = new EventDeclaration();
660
661 pushScope();
662
663 for (CommonTree child : children) {
664 switch (child.getType()) {
665 case CTFParser.TYPEALIAS:
666 parseTypealias(child);
667 break;
668 case CTFParser.TYPEDEF:
669 parseTypedef(child);
670 break;
671 case CTFParser.CTF_EXPRESSION_TYPE:
672 case CTFParser.CTF_EXPRESSION_VAL:
673 parseEventDeclaration(child, event);
674 break;
675 default:
676 childTypeError(child);
677 break;
678 }
679 }
680
681 if (!event.nameIsSet()) {
682 throw new ParseException("Event name not set"); //$NON-NLS-1$
683 }
684
685 /*
686 * If the event did not specify a stream, then the trace must be single
687 * stream
688 */
689 if (!event.streamIsSet()) {
690 if (trace.nbStreams() > 1) {
691 throw new ParseException(
692 "Event without stream_id with more than one stream"); //$NON-NLS-1$
693 }
694
695 /*
696 * If the event did not specify a stream, the only existing stream
697 * must not have an id. Note: That behavior could be changed, it
698 * could be possible to just get the only existing stream, whatever
699 * is its id.
700 */
701 Stream stream = trace.getStream(null);
702
703 if (stream != null) {
704 event.setStream(stream);
705 } else {
706 throw new ParseException(
707 "Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
708 }
709 }
710
711 /*
712 * Add the event to the stream.
713 */
714 event.getStream().addEvent(event);
715
716 popScope();
717 }
718
719 private void parseEventDeclaration(CommonTree eventDecl,
720 EventDeclaration event) throws ParseException {
866e5b51
FC
721
722 /* There should be a left and right */
866e5b51
FC
723
724 CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
866e5b51 725 CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
866e5b51
FC
726
727 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51
FC
728
729 if (!isUnaryString(leftStrings.get(0))) {
730 throw new ParseException(
731 "Left side of CTF assignment must be a string"); //$NON-NLS-1$
732 }
733
734 String left = concatenateUnaryStrings(leftStrings);
735
07002e0a 736 if (left.equals(CTFStrings.NAME2)) {
866e5b51
FC
737 if (event.nameIsSet()) {
738 throw new ParseException("name already defined"); //$NON-NLS-1$
739 }
740
741 String name = getEventName(rightNode);
742
743 event.setName(name);
07002e0a 744 } else if (left.equals(CTFStrings.ID)) {
866e5b51
FC
745 if (event.idIsSet()) {
746 throw new ParseException("id already defined"); //$NON-NLS-1$
747 }
748
749 long id = getEventID(rightNode);
750
751 event.setId(id);
07002e0a 752 } else if (left.equals(CTFStrings.STREAM_ID)) {
866e5b51
FC
753 if (event.streamIsSet()) {
754 throw new ParseException("stream id already defined"); //$NON-NLS-1$
755 }
756
757 long streamId = getStreamID(rightNode);
758
759 Stream stream = trace.getStream(streamId);
760
761 if (stream == null) {
762 throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
763 }
764
765 event.setStream(stream);
07002e0a 766 } else if (left.equals(CTFStrings.CONTEXT)) {
866e5b51
FC
767 if (event.contextIsSet()) {
768 throw new ParseException("context already defined"); //$NON-NLS-1$
769 }
770
771 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
772
773 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
774 throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
775 }
776
777 IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier,
778 null);
779
780 if (!(contextDecl instanceof StructDeclaration)) {
781 throw new ParseException("context expects a struct"); //$NON-NLS-1$
782 }
783
784 event.setContext((StructDeclaration) contextDecl);
07002e0a 785 } else if (left.equals(CTFStrings.FIELDS_STRING)) {
866e5b51
FC
786 if (event.fieldsIsSet()) {
787 throw new ParseException("fields already defined"); //$NON-NLS-1$
788 }
789
790 CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
791
792 if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
793 throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
794 }
795
13be1a8f
AM
796 IDeclaration fieldsDecl;
797 fieldsDecl = parseTypeSpecifierList(typeSpecifier, null);
866e5b51
FC
798
799 if (!(fieldsDecl instanceof StructDeclaration)) {
800 throw new ParseException("fields expects a struct"); //$NON-NLS-1$
801 }
802 /*
32ede2ec
MK
803 * The underscores in the event names. These underscores were added
804 * by the LTTng tracer.
866e5b51 805 */
91847dfc 806 final StructDeclaration fields = (StructDeclaration) fieldsDecl;
866e5b51 807 event.setFields(fields);
32ede2ec
MK
808 } else if (left.equals(CTFStrings.LOGLEVEL2)) {
809 long logLevel = parseUnaryInteger((CommonTree) rightNode.getChild(0));
53047a66 810 event.setLogLevel(logLevel);
866e5b51 811 } else {
8e964be1
MK
812 /* Custom event attribute, we'll add it to the attributes map */
813 String right = parseUnaryString((CommonTree) rightNode.getChild(0));
814 event.setCustomAttribute(left, right);
866e5b51
FC
815 }
816 }
817
818 /**
819 * Parses a declaration at the root level.
820 *
821 * @param declaration
822 * The declaration subtree.
823 * @throws ParseException
824 */
825 private void parseRootDeclaration(CommonTree declaration)
826 throws ParseException {
866e5b51
FC
827
828 List<CommonTree> children = declaration.getChildren();
866e5b51
FC
829
830 for (CommonTree child : children) {
831 switch (child.getType()) {
832 case CTFParser.TYPEDEF:
833 parseTypedef(child);
834 break;
835 case CTFParser.TYPEALIAS:
836 parseTypealias(child);
837 break;
838 case CTFParser.TYPE_SPECIFIER_LIST:
839 parseTypeSpecifierList(child, null);
840 break;
841 default:
842 childTypeError(child);
843 }
844 }
845 }
846
847 /**
848 * Parses a typealias node. It parses the target, the alias, and registers
849 * the type in the current scope.
850 *
851 * @param typealias
852 * A TYPEALIAS node.
853 * @throws ParseException
854 */
855 private void parseTypealias(CommonTree typealias) throws ParseException {
866e5b51
FC
856
857 List<CommonTree> children = typealias.getChildren();
866e5b51
FC
858
859 CommonTree target = null;
860 CommonTree alias = null;
861
862 for (CommonTree child : children) {
863 switch (child.getType()) {
864 case CTFParser.TYPEALIAS_TARGET:
866e5b51
FC
865 target = child;
866 break;
867 case CTFParser.TYPEALIAS_ALIAS:
866e5b51
FC
868 alias = child;
869 break;
870 default:
871 childTypeError(child);
872 break;
873 }
874 }
875
866e5b51
FC
876
877 IDeclaration targetDeclaration = parseTypealiasTarget(target);
878
879 if (targetDeclaration instanceof VariantDeclaration) {
880 if (((VariantDeclaration) targetDeclaration).isTagged()) {
881 throw new ParseException(
882 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
883 }
884 }
885
886 String aliasString = parseTypealiasAlias(alias);
887
888 getCurrentScope().registerType(aliasString, targetDeclaration);
889 }
890
891 /**
892 * Parses the target part of a typealias and gets the corresponding
893 * declaration.
894 *
895 * @param target
896 * A TYPEALIAS_TARGET node.
897 * @return The corresponding declaration.
898 * @throws ParseException
899 */
900 private IDeclaration parseTypealiasTarget(CommonTree target)
901 throws ParseException {
866e5b51
FC
902
903 List<CommonTree> children = target.getChildren();
866e5b51
FC
904
905 CommonTree typeSpecifierList = null;
906 CommonTree typeDeclaratorList = null;
907 CommonTree typeDeclarator = null;
908 StringBuilder identifierSB = new StringBuilder();
909
910 for (CommonTree child : children) {
911 switch (child.getType()) {
912 case CTFParser.TYPE_SPECIFIER_LIST:
866e5b51
FC
913 typeSpecifierList = child;
914 break;
915 case CTFParser.TYPE_DECLARATOR_LIST:
866e5b51
FC
916 typeDeclaratorList = child;
917 break;
918 default:
919 childTypeError(child);
920 break;
921 }
922 }
923
866e5b51
FC
924
925 if (typeDeclaratorList != null) {
926 /*
927 * Only allow one declarator
928 *
929 * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
930 * otherwise the new type puint8_t would maps to two different
931 * types.
932 */
933 if (typeDeclaratorList.getChildCount() != 1) {
934 throw new ParseException(
935 "Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
936 }
937
938 typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
939 }
940
941 /* Parse the target type and get the declaration */
942 IDeclaration targetDeclaration = parseTypeDeclarator(typeDeclarator,
943 typeSpecifierList, identifierSB);
944
945 /*
946 * We don't allow identifier in the target
947 *
948 * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
949 * permitted
950 */
951 if (identifierSB.length() > 0) {
952 throw new ParseException("Identifier (" + identifierSB.toString() //$NON-NLS-1$
953 + ") not expected in the typealias target"); //$NON-NLS-1$
954 }
955
956 return targetDeclaration;
957 }
958
959 /**
960 * Parses the alias part of a typealias. It parses the underlying specifier
961 * list and declarator and creates the string representation that will be
962 * used to register the type.
963 *
964 * @param alias
965 * A TYPEALIAS_ALIAS node.
966 * @return The string representation of the alias.
967 * @throws ParseException
968 */
969 private static String parseTypealiasAlias(CommonTree alias)
970 throws ParseException {
866e5b51
FC
971
972 List<CommonTree> children = alias.getChildren();
866e5b51
FC
973
974 CommonTree typeSpecifierList = null;
975 CommonTree typeDeclaratorList = null;
976 CommonTree typeDeclarator = null;
977 List<CommonTree> pointers = new LinkedList<CommonTree>();
978
979 for (CommonTree child : children) {
980 switch (child.getType()) {
981 case CTFParser.TYPE_SPECIFIER_LIST:
866e5b51
FC
982 typeSpecifierList = child;
983 break;
984 case CTFParser.TYPE_DECLARATOR_LIST:
866e5b51
FC
985 typeDeclaratorList = child;
986 break;
987 default:
988 childTypeError(child);
989 break;
990 }
991 }
992
993 /* If there is a type declarator list, extract the pointers */
994 if (typeDeclaratorList != null) {
995 /*
996 * Only allow one declarator
997 *
998 * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
999 */
1000 if (typeDeclaratorList.getChildCount() != 1) {
1001 throw new ParseException(
1002 "Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
1003 }
1004
1005 typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
1006
72dbc4ac 1007 List<CommonTree> typeDeclaratorChildren = typeDeclarator.getChildren();
866e5b51
FC
1008
1009 for (CommonTree child : typeDeclaratorChildren) {
1010 switch (child.getType()) {
1011 case CTFParser.POINTER:
1012 pointers.add(child);
1013 break;
1014 case CTFParser.IDENTIFIER:
1015 throw new ParseException("Identifier (" + child.getText() //$NON-NLS-1$
1016 + ") not expected in the typealias target"); //$NON-NLS-1$
1017 /* break; */
1018 default:
1019 childTypeError(child);
1020 break;
1021 }
1022 }
1023 }
1024
1025 return createTypeDeclarationString(typeSpecifierList, pointers);
1026 }
1027
1028 /**
1029 * Parses a typedef node. This creates and registers a new declaration for
1030 * each declarator found in the typedef.
1031 *
1032 * @param typedef
1033 * A TYPEDEF node.
1034 * @throws ParseException
1035 * If there is an error creating the declaration.
1036 */
1037 private void parseTypedef(CommonTree typedef) throws ParseException {
866e5b51 1038
72dbc4ac 1039 CommonTree typeDeclaratorListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
866e5b51 1040
72dbc4ac 1041 CommonTree typeSpecifierListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
866e5b51 1042
72dbc4ac 1043 List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
866e5b51
FC
1044
1045 for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
1046 StringBuilder identifierSB = new StringBuilder();
1047
1048 IDeclaration type_declaration = parseTypeDeclarator(
1049 typeDeclaratorNode, typeSpecifierListNode, identifierSB);
1050
1051 if (type_declaration instanceof VariantDeclaration) {
1052 if (((VariantDeclaration) type_declaration).isTagged()) {
1053 throw new ParseException(
1054 "Typealias of untagged variant is not permitted"); //$NON-NLS-1$
1055 }
1056 }
1057
1058 getCurrentScope().registerType(identifierSB.toString(),
1059 type_declaration);
1060 }
1061 }
1062
1063 /**
1064 * Parses a pair type declarator / type specifier list and returns the
1065 * corresponding declaration. If it is present, it also writes the
1066 * identifier of the declarator in the given {@link StringBuilder}.
1067 *
1068 * @param typeDeclarator
1069 * A TYPE_DECLARATOR node.
1070 * @param typeSpecifierList
1071 * A TYPE_SPECIFIER_LIST node.
1072 * @param identifierSB
1073 * A StringBuilder that will receive the identifier found in the
1074 * declarator.
1075 * @return The corresponding declaration.
1076 * @throws ParseException
1077 * If there is an error finding or creating the declaration.
1078 */
1079 private IDeclaration parseTypeDeclarator(CommonTree typeDeclarator,
1080 CommonTree typeSpecifierList, StringBuilder identifierSB)
1081 throws ParseException {
866e5b51
FC
1082
1083 IDeclaration declaration = null;
1084 List<CommonTree> children = null;
1085 List<CommonTree> pointers = new LinkedList<CommonTree>();
1086 List<CommonTree> lengths = new LinkedList<CommonTree>();
1087 CommonTree identifier = null;
1088
1089 /* Separate the tokens by type */
1090 if (typeDeclarator != null) {
1091 children = typeDeclarator.getChildren();
866e5b51
FC
1092 for (CommonTree child : children) {
1093
1094 switch (child.getType()) {
1095 case CTFParser.POINTER:
1096 pointers.add(child);
1097 break;
1098 case CTFParser.IDENTIFIER:
866e5b51
FC
1099 identifier = child;
1100 break;
1101 case CTFParser.LENGTH:
1102 lengths.add(child);
1103 break;
1104 default:
1105 childTypeError(child);
1106 break;
1107 }
1108 }
1109
1110 }
1111
1112 /*
1113 * Parse the type specifier list, which is the "base" type. For example,
1114 * it would be int in int a[3][len].
1115 */
1116 declaration = parseTypeSpecifierList(typeSpecifierList, pointers);
1117
1118 /*
1119 * Each length subscript means that we must create a nested array or
1120 * sequence. For example, int a[3][len] means that we have an array of 3
1121 * (sequences of length 'len' of (int)).
1122 */
32ede2ec 1123 if (lengths.size() > 0) {
866e5b51
FC
1124 /* We begin at the end */
1125 Collections.reverse(lengths);
1126
1127 for (CommonTree length : lengths) {
1128 /*
1129 * By looking at the first expression, we can determine whether
1130 * it is an array or a sequence.
1131 */
1132 List<CommonTree> lengthChildren = length.getChildren();
866e5b51
FC
1133
1134 CommonTree first = lengthChildren.get(0);
1135 if (isUnaryInteger(first)) {
1136 /* Array */
1137 int arrayLength = (int) parseUnaryInteger(first);
1138
1139 if (arrayLength < 1) {
1140 throw new ParseException("Array length is negative"); //$NON-NLS-1$
1141 }
1142
1143 /* Create the array declaration. */
1144 declaration = new ArrayDeclaration(arrayLength, declaration);
1145 } else if (isUnaryString(first)) {
1146 /* Sequence */
1147 String lengthName = concatenateUnaryStrings(lengthChildren);
1148
1149 /* Create the sequence declaration. */
1150 declaration = new SequenceDeclaration(lengthName,
1151 declaration);
1152 } else {
1153 childTypeError(first);
1154 }
1155 }
1156 }
1157
1158 if (identifier != null) {
1159 identifierSB.append(identifier.getText());
1160 }
1161
1162 return declaration;
1163 }
1164
1165 /**
1166 * Parses a type specifier list and returns the corresponding declaration.
1167 *
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.
1176 */
1177 private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList,
1178 List<CommonTree> pointerList) throws ParseException {
866e5b51
FC
1179 IDeclaration declaration = null;
1180
1181 /*
1182 * By looking at the first element of the type specifier list, we can
1183 * determine which type it belongs to.
1184 */
1185 CommonTree firstChild = (CommonTree) typeSpecifierList.getChild(0);
866e5b51
FC
1186
1187 switch (firstChild.getType()) {
1188 case CTFParser.FLOATING_POINT:
53047a66 1189 declaration = parseFloat(firstChild);
866e5b51
FC
1190 break;
1191 case CTFParser.INTEGER:
1192 declaration = parseInteger(firstChild);
1193 break;
1194 case CTFParser.STRING:
1195 declaration = parseString(firstChild);
1196 break;
1197 case CTFParser.STRUCT:
1198 declaration = parseStruct(firstChild);
1199 break;
1200 case CTFParser.VARIANT:
1201 declaration = parseVariant(firstChild);
1202 break;
1203 case CTFParser.ENUM:
1204 declaration = parseEnum(firstChild);
1205 break;
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);
1220 break;
1221 default:
1222 childTypeError(firstChild);
1223 }
1224
866e5b51
FC
1225 return declaration;
1226 }
1227
32ede2ec
MK
1228 private IDeclaration parseFloat(CommonTree floatingPoint)
1229 throws ParseException {
53047a66
MK
1230
1231 List<CommonTree> children = floatingPoint.getChildren();
1232
1233 /*
1234 * If the integer has no attributes, then it is missing the size
1235 * attribute which is required
1236 */
1237 if (children == null) {
1238 throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
1239 }
1240
1241 /* The return value */
1242 FloatDeclaration floatDeclaration = null;
1243 ByteOrder byteOrder = trace.getByteOrder();
1244 long alignment = 0;
53047a66
MK
1245 int exponent = 8;
1246 int mantissa = 24;
1247
53047a66
MK
1248 /* Iterate on all integer children */
1249 for (CommonTree child : children) {
1250 switch (child.getType()) {
1251 case CTFParser.CTF_EXPRESSION_VAL:
1252 /*
1253 * An assignment expression must have 2 children, left and right
1254 */
53047a66
MK
1255
1256 CommonTree leftNode = (CommonTree) child.getChild(0);
53047a66 1257 CommonTree rightNode = (CommonTree) child.getChild(1);
53047a66
MK
1258
1259 List<CommonTree> leftStrings = leftNode.getChildren();
53047a66
MK
1260
1261 if (!isUnaryString(leftStrings.get(0))) {
1262 throw new ParseException(
1263 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1264 }
1265 String left = concatenateUnaryStrings(leftStrings);
1266
07002e0a 1267 if (left.equals(CTFStrings.EXP_DIG)) {
53047a66 1268 exponent = (int) parseUnaryInteger((CommonTree) rightNode.getChild(0));
07002e0a 1269 } else if (left.equals(CTFStrings.BYTE_ORDER)) {
53047a66 1270 byteOrder = getByteOrder(rightNode);
07002e0a 1271 } else if (left.equals(CTFStrings.MANT_DIG)) {
53047a66 1272 mantissa = (int) parseUnaryInteger((CommonTree) rightNode.getChild(0));
07002e0a 1273 } else if (left.equals(CTFStrings.ALIGN)) {
53047a66
MK
1274 alignment = getAlignment(rightNode);
1275 } else {
1276 throw new ParseException("Float: unknown attribute " + left); //$NON-NLS-1$
1277 }
1278
1279 break;
1280 default:
1281 childTypeError(child);
1282 break;
1283 }
1284 }
1285 int size = mantissa + exponent;
1286 if (size == 0) {
1287 throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
1288 }
1289
1290 if (alignment == 0) {
1291 if ((size % 8) == 0) {
1292 alignment = 1;
1293 } else {
1294 alignment = 8;
1295 }
1296 }
1297
07002e0a 1298 floatDeclaration = new FloatDeclaration(exponent, mantissa, byteOrder, alignment);
53047a66 1299
53047a66
MK
1300 return floatDeclaration;
1301
1302 }
1303
866e5b51
FC
1304 /**
1305 * Parses a type specifier list as a user-declared type.
1306 *
1307 * @param typeSpecifierList
1308 * A TYPE_SPECIFIER_LIST node containing a user-declared type.
1309 * @param pointerList
1310 * A list of POINTER nodes that apply to the type specified in
1311 * typeSpecifierList.
1312 * @return The corresponding declaration.
1313 * @throws ParseException
1314 * If the type does not exist (has not been found).
1315 */
1316 private IDeclaration parseTypeDeclaration(CommonTree typeSpecifierList,
1317 List<CommonTree> pointerList) throws ParseException {
1318 /* Create the string representation of the type declaration */
1319 String typeStringRepresentation = createTypeDeclarationString(
1320 typeSpecifierList, pointerList);
1321
1322 /* Use the string representation to search the type in the current scope */
1323 IDeclaration decl = getCurrentScope().rlookupType(
1324 typeStringRepresentation);
1325
1326 if (decl == null) {
1327 throw new ParseException("Type " + typeStringRepresentation //$NON-NLS-1$
1328 + " has not been defined."); //$NON-NLS-1$
1329 }
1330
1331 return decl;
1332 }
1333
1334 /**
1335 * Parses an integer declaration node.
1336 *
1337 * @param integer
1338 * An INTEGER node.
1339 * @return The corresponding integer declaration.
1340 * @throws ParseException
1341 */
1342 private IntegerDeclaration parseInteger(CommonTree integer)
1343 throws ParseException {
866e5b51
FC
1344
1345 List<CommonTree> children = integer.getChildren();
1346
1347 /*
1348 * If the integer has no attributes, then it is missing the size
1349 * attribute which is required
1350 */
1351 if (children == null) {
1352 throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
1353 }
1354
1355 /* The return value */
1356 IntegerDeclaration integerDeclaration = null;
1357 boolean signed = false;
1358 ByteOrder byteOrder = trace.getByteOrder();
1359 long size = 0;
1360 long alignment = 0;
1361 int base = 10;
284fdee8 1362 String clock = null;
866e5b51
FC
1363
1364 Encoding encoding = Encoding.NONE;
1365
1366 /* Iterate on all integer children */
1367 for (CommonTree child : children) {
1368 switch (child.getType()) {
1369 case CTFParser.CTF_EXPRESSION_VAL:
1370 /*
1371 * An assignment expression must have 2 children, left and right
1372 */
866e5b51
FC
1373
1374 CommonTree leftNode = (CommonTree) child.getChild(0);
866e5b51 1375 CommonTree rightNode = (CommonTree) child.getChild(1);
866e5b51
FC
1376
1377 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51
FC
1378
1379 if (!isUnaryString(leftStrings.get(0))) {
1380 throw new ParseException(
1381 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1382 }
1383 String left = concatenateUnaryStrings(leftStrings);
1384
1385 if (left.equals("signed")) { //$NON-NLS-1$
1386 signed = getSigned(rightNode);
07002e0a 1387 } else if (left.equals(CTFStrings.BYTE_ORDER)) {
866e5b51
FC
1388 byteOrder = getByteOrder(rightNode);
1389 } else if (left.equals("size")) { //$NON-NLS-1$
1390 size = getSize(rightNode);
07002e0a 1391 } else if (left.equals(CTFStrings.ALIGN)) {
866e5b51
FC
1392 alignment = getAlignment(rightNode);
1393 } else if (left.equals("base")) { //$NON-NLS-1$
1394 base = getBase(rightNode);
1395 } else if (left.equals("encoding")) { //$NON-NLS-1$
1396 encoding = getEncoding(rightNode);
1397 } else if (left.equals("map")) { //$NON-NLS-1$
1398 clock = getClock(rightNode);
1399 } else {
32ede2ec
MK
1400 throw new ParseException(
1401 "Integer: unknown attribute " + left); //$NON-NLS-1$
866e5b51
FC
1402 }
1403
1404 break;
1405 default:
1406 childTypeError(child);
1407 break;
1408 }
1409 }
1410
1411 if (size == 0) {
1412 throw new ParseException("Integer missing size attribute"); //$NON-NLS-1$
1413 }
1414
1415 if (alignment == 0) {
1416 if ((size % 8) == 0) {
1417 alignment = 1;
1418 } else {
1419 alignment = 8;
1420 }
1421 }
1422
1423 integerDeclaration = new IntegerDeclaration((int) size, signed, base,
fd74e6c1 1424 byteOrder, encoding, clock, alignment);
866e5b51 1425
866e5b51
FC
1426 return integerDeclaration;
1427 }
1428
284fdee8 1429 private static String getClock(CommonTree rightNode) {
866e5b51
FC
1430 return rightNode.getChild(1).getChild(0).getChild(0).getText();
1431 }
1432
1433 private static StringDeclaration parseString(CommonTree string)
1434 throws ParseException {
866e5b51
FC
1435
1436 List<CommonTree> children = string.getChildren();
1437 StringDeclaration stringDeclaration = null;
1438
1439 if (children == null) {
1440 stringDeclaration = new StringDeclaration();
1441 } else {
1442 Encoding encoding = Encoding.UTF8;
1443 for (CommonTree child : children) {
1444 switch (child.getType()) {
1445 case CTFParser.CTF_EXPRESSION_VAL:
1446 /*
1447 * An assignment expression must have 2 children, left and
1448 * right
1449 */
866e5b51
FC
1450
1451 CommonTree leftNode = (CommonTree) child.getChild(0);
866e5b51 1452 CommonTree rightNode = (CommonTree) child.getChild(1);
866e5b51
FC
1453
1454 List<CommonTree> leftStrings = leftNode.getChildren();
866e5b51
FC
1455
1456 if (!isUnaryString(leftStrings.get(0))) {
1457 throw new ParseException(
1458 "Left side of ctf expression must be a string"); //$NON-NLS-1$
1459 }
1460 String left = concatenateUnaryStrings(leftStrings);
1461
1462 if (left.equals("encoding")) { //$NON-NLS-1$
1463 encoding = getEncoding(rightNode);
1464 } else {
1465 throw new ParseException("String: unknown attribute " //$NON-NLS-1$
1466 + left);
1467 }
1468
1469 break;
1470 default:
1471 childTypeError(child);
1472 break;
1473 }
1474 }
1475
1476 stringDeclaration = new StringDeclaration(encoding);
1477 }
1478
1479 return stringDeclaration;
1480 }
1481
1482 /**
1483 * Parses a struct declaration and returns the corresponding declaration.
1484 *
1485 * @param struct
1486 * An STRUCT node.
1487 * @return The corresponding struct declaration.
1488 * @throws ParseException
1489 */
1490 private StructDeclaration parseStruct(CommonTree struct)
1491 throws ParseException {
866e5b51
FC
1492
1493 List<CommonTree> children = struct.getChildren();
866e5b51
FC
1494
1495 /* The return value */
1496 StructDeclaration structDeclaration = null;
1497
1498 /* Name */
1499 String structName = null;
1500 boolean hasName = false;
1501
1502 /* Body */
1503 CommonTree structBody = null;
1504 boolean hasBody = false;
1505
1506 /* Align */
1507 long structAlign = 0;
1508
1509 /* Loop on all children and identify what we have to work with. */
1510 for (CommonTree child : children) {
1511 switch (child.getType()) {
1512 case CTFParser.STRUCT_NAME: {
1513 hasName = true;
1514
72dbc4ac 1515 CommonTree structNameIdentifier = (CommonTree) child.getChild(0);
866e5b51 1516
866e5b51
FC
1517 structName = structNameIdentifier.getText();
1518
1519 break;
1520 }
1521 case CTFParser.STRUCT_BODY: {
1522 hasBody = true;
1523
1524 structBody = child;
1525
1526 break;
1527 }
1528 case CTFParser.ALIGN: {
72dbc4ac 1529 CommonTree structAlignExpression = (CommonTree) child.getChild(0);
866e5b51
FC
1530
1531 structAlign = getAlignment(structAlignExpression);
1532
1533 break;
1534 }
1535 default:
1536 childTypeError(child);
1537
1538 break;
1539 }
1540 }
1541
1542 /*
1543 * If a struct has just a body and no name (just like the song,
1544 * "A Struct With No Name" by America (sorry for that...)), it's a
1545 * definition of a new type, so we create the type declaration and
1546 * return it. We can't add it to the declaration scope since there is no
1547 * name, but that's what we want because it won't be possible to use it
1548 * again to declare another field.
1549 *
1550 * If it has just a name, we look it up in the declaration scope and
1551 * return the associated declaration. If it is not found in the
1552 * declaration scope, it means that a struct with that name has not been
1553 * declared, which is an error.
1554 *
1555 * If it has both, then we create the type declaration and register it
1556 * to the current scope.
1557 *
1558 * If it has none, then what are we doing here ?
1559 */
1560 if (hasBody) {
1561 /*
1562 * If struct has a name, check if already defined in the current
1563 * scope.
1564 */
1565 if (hasName && (getCurrentScope().lookupStruct(structName) != null)) {
1566 throw new ParseException("struct " + structName //$NON-NLS-1$
1567 + " already defined."); //$NON-NLS-1$
1568 }
866e5b51
FC
1569 /* Create the declaration */
1570 structDeclaration = new StructDeclaration(structAlign);
1571
1572 /* Parse the body */
1573 parseStructBody(structBody, structDeclaration);
1574
1575 /* If struct has name, add it to the current scope. */
1576 if (hasName) {
1577 getCurrentScope().registerStruct(structName, structDeclaration);
1578 }
1579 } else /* !hasBody */{
1580 if (hasName) {
1581 /* Name and !body */
1582
1583 /* Lookup the name in the current scope. */
1584 structDeclaration = getCurrentScope().rlookupStruct(structName);
1585
1586 /*
1587 * If not found, it means that a struct with such name has not
1588 * been defined
1589 */
1590 if (structDeclaration == null) {
1591 throw new ParseException("struct " + structName //$NON-NLS-1$
1592 + " is not defined"); //$NON-NLS-1$
1593 }
1594 } else {
1595 /* !Name and !body */
1596
1597 /* We can't do anything with that. */
1598 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
1599 }
1600 }
1601
866e5b51
FC
1602 return structDeclaration;
1603 }
1604
1605 /**
1606 * Parses a struct body, adding the fields to specified structure
1607 * declaration.
1608 *
1609 * @param structBody
1610 * A STRUCT_BODY node.
1611 * @param structDeclaration
1612 * The struct declaration.
1613 * @throws ParseException
1614 */
1615 private void parseStructBody(CommonTree structBody,
1616 StructDeclaration structDeclaration) throws ParseException {
866e5b51
FC
1617
1618 List<CommonTree> structDeclarations = structBody.getChildren();
1619
1620 /*
1621 * If structDeclaration is null, structBody has no children and the
1622 * struct body is empty.
1623 */
1624 if (structDeclarations != null) {
1625 pushScope();
1626
1627 for (CommonTree declarationNode : structDeclarations) {
1628 switch (declarationNode.getType()) {
1629 case CTFParser.TYPEALIAS:
1630 parseTypealias(declarationNode);
1631 break;
1632 case CTFParser.TYPEDEF:
1633 parseTypedef(declarationNode);
1634 break;
1635 case CTFParser.SV_DECLARATION:
1636 parseStructDeclaration(declarationNode, structDeclaration);
1637 break;
1638 default:
1639 childTypeError(declarationNode);
1640 break;
1641 }
1642 }
1643 popScope();
1644 }
1645 }
1646
1647 /**
1648 * Parses a declaration found in a struct.
1649 *
1650 * @param declaration
1651 * A SV_DECLARATION node.
1652 * @param struct
1653 * A struct declaration. (I know, little name clash here...)
1654 * @throws ParseException
1655 */
1656 private void parseStructDeclaration(CommonTree declaration,
1657 StructDeclaration struct) throws ParseException {
866e5b51 1658
866e5b51
FC
1659
1660 /* Get the type specifier list node */
72dbc4ac 1661 CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
866e5b51
FC
1662
1663 /* Get the type declarator list node */
72dbc4ac 1664 CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
866e5b51
FC
1665
1666 /* Get the type declarator list */
72dbc4ac 1667 List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
866e5b51
FC
1668
1669 /*
1670 * For each type declarator, parse the declaration and add a field to
1671 * the struct
1672 */
1673 for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
866e5b51
FC
1674
1675 StringBuilder identifierSB = new StringBuilder();
1676
1677 IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
1678 typeSpecifierListNode, identifierSB);
1679 String fieldName = identifierSB.toString();
866e5b51
FC
1680
1681 if (struct.hasField(fieldName)) {
1682 throw new ParseException("struct: duplicate field " //$NON-NLS-1$
1683 + fieldName);
1684 }
1685
1686 struct.addField(fieldName, decl);
1687
1688 }
1689 }
1690
1691 /**
1692 * Parses an enum declaration and returns the corresponding declaration.
1693 *
1694 * @param _enum
1695 * An ENUM node.
1696 * @return The corresponding enum declaration.
1697 * @throws ParseException
1698 */
1699 private EnumDeclaration parseEnum(CommonTree _enum) throws ParseException {
866e5b51
FC
1700
1701 List<CommonTree> children = _enum.getChildren();
866e5b51
FC
1702
1703 /* The return value */
1704 EnumDeclaration enumDeclaration = null;
1705
1706 /* Name */
1707 String enumName = null;
1708
1709 /* Body */
1710 CommonTree enumBody = null;
1711
1712 /* Container type */
1713 IntegerDeclaration containerTypeDeclaration = null;
1714
1715 /* Loop on all children and identify what we have to work with. */
1716 for (CommonTree child : children) {
1717 switch (child.getType()) {
1718 case CTFParser.ENUM_NAME: {
866e5b51
FC
1719 CommonTree enumNameIdentifier = (CommonTree) child.getChild(0);
1720
866e5b51
FC
1721 enumName = enumNameIdentifier.getText();
1722
1723 break;
1724 }
1725 case CTFParser.ENUM_BODY: {
866e5b51
FC
1726
1727 enumBody = child;
1728
1729 break;
1730 }
1731 case CTFParser.ENUM_CONTAINER_TYPE: {
866e5b51
FC
1732
1733 containerTypeDeclaration = parseEnumContainerType(child);
1734
1735 break;
1736 }
1737 default:
1738 childTypeError(child);
1739 break;
1740 }
1741 }
1742
1743 /*
1744 * If the container type has not been defined explicitly, we assume it
1745 * is "int".
1746 */
1747 if (containerTypeDeclaration == null) {
32ede2ec
MK
1748 IDeclaration enumDecl;
1749 /*
1750 * it could be because the enum was already declared.
1751 */
1752 if (enumName != null) {
1753 enumDecl = getCurrentScope().rlookupEnum(enumName);
1754 if (enumDecl != null) {
1755 return (EnumDeclaration) enumDecl;
1756 }
1757 }
1758
866e5b51
FC
1759 IDeclaration decl = getCurrentScope().rlookupType("int"); //$NON-NLS-1$
1760
1761 if (decl == null) {
1762 throw new ParseException(
1763 "enum container type implicit and type int not defined"); //$NON-NLS-1$
1764 } else if (!(decl instanceof IntegerDeclaration)) {
1765 throw new ParseException(
1766 "enum container type implicit and type int not an integer"); //$NON-NLS-1$
1767 }
1768
1769 containerTypeDeclaration = (IntegerDeclaration) decl;
1770 }
1771
1772 /*
1773 * If it has a body, it's a new declaration, otherwise it's a reference
1774 * to an existing declaration. Same logic as struct.
1775 */
1776 if (enumBody != null) {
1777 /*
1778 * If enum has a name, check if already defined in the current
1779 * scope.
1780 */
1781 if ((enumName != null)
1782 && (getCurrentScope().lookupEnum(enumName) != null)) {
1783 throw new ParseException("enum " + enumName //$NON-NLS-1$
1784 + " already defined"); //$NON-NLS-1$
1785 }
1786
1787 /* Create the declaration */
1788 enumDeclaration = new EnumDeclaration(containerTypeDeclaration);
1789
1790 /* Parse the body */
1791 parseEnumBody(enumBody, enumDeclaration);
1792
1793 /* If the enum has name, add it to the current scope. */
1794 if (enumName != null) {
1795 getCurrentScope().registerEnum(enumName, enumDeclaration);
1796 }
1797 } else {
1798 if (enumName != null) {
1799 /* Name and !body */
1800
1801 /* Lookup the name in the current scope. */
1802 enumDeclaration = getCurrentScope().rlookupEnum(enumName);
1803
1804 /*
1805 * If not found, it means that an enum with such name has not
1806 * been defined
1807 */
1808 if (enumDeclaration == null) {
1809 throw new ParseException("enum " + enumName //$NON-NLS-1$
1810 + " is not defined"); //$NON-NLS-1$
1811 }
1812 } else {
1813 /* !Name and !body */
1814 throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
1815 }
1816 }
1817
1818 return enumDeclaration;
1819
1820 }
1821
1822 /**
1823 * Parses an enum body, adding the enumerators to the specified enum
1824 * declaration.
1825 *
1826 * @param enumBody
1827 * An ENUM_BODY node.
1828 * @param enumDeclaration
1829 * The enum declaration.
1830 * @throws ParseException
1831 */
1832 private void parseEnumBody(CommonTree enumBody,
1833 EnumDeclaration enumDeclaration) throws ParseException {
866e5b51
FC
1834
1835 List<CommonTree> enumerators = enumBody.getChildren();
1836 /* enum body can't be empty (unlike struct). */
866e5b51
FC
1837
1838 pushScope();
1839
1840 /*
1841 * Start at -1, so that if the first enumrator has no explicit value, it
1842 * will choose 0
1843 */
1844 long lastHigh = -1;
1845
1846 for (CommonTree enumerator : enumerators) {
1847 lastHigh = parseEnumEnumerator(enumerator, enumDeclaration,
1848 lastHigh);
1849 }
1850
1851 popScope();
1852
1853 }
1854
1855 /**
1856 * Parses an enumerator node and adds an enumerator declaration to an
1857 * enumeration declaration.
1858 *
1859 * The high value of the range of the last enumerator is needed in case the
1860 * current enumerator does not specify its value.
1861 *
1862 * @param enumerator
1863 * An ENUM_ENUMERATOR node.
1864 * @param enumDeclaration
1865 * en enumeration declaration to which will be added the
1866 * enumerator.
1867 * @param lastHigh
1868 * The high value of the range of the last enumerator
1869 * @return The high value of the value range of the current enumerator.
1870 * @throws ParseException
1871 */
1872 private static long parseEnumEnumerator(CommonTree enumerator,
1873 EnumDeclaration enumDeclaration, long lastHigh)
1874 throws ParseException {
866e5b51
FC
1875
1876 List<CommonTree> children = enumerator.getChildren();
866e5b51
FC
1877
1878 long low = 0, high = 0;
1879 boolean valueSpecified = false;
1880 String label = null;
1881
1882 for (CommonTree child : children) {
1883 if (isUnaryString(child)) {
1884 label = parseUnaryString(child);
1885 } else if (child.getType() == CTFParser.ENUM_VALUE) {
866e5b51
FC
1886
1887 valueSpecified = true;
1888
1889 low = parseUnaryInteger((CommonTree) child.getChild(0));
1890 high = low;
1891 } else if (child.getType() == CTFParser.ENUM_VALUE_RANGE) {
866e5b51
FC
1892
1893 valueSpecified = true;
1894
1895 low = parseUnaryInteger((CommonTree) child.getChild(0));
1896 high = parseUnaryInteger((CommonTree) child.getChild(1));
1897 } else {
1898 childTypeError(child);
1899 }
1900 }
1901
866e5b51
FC
1902 if (!valueSpecified) {
1903 low = lastHigh + 1;
1904 high = low;
1905 }
1906
1907 if (low > high) {
1908 throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
1909 }
1910
1911 if (!enumDeclaration.add(low, high, label)) {
1912 throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
1913 }
1914
1915 return high;
1916 }
1917
1918 /**
1919 * Parses an enum container type node and returns the corresponding integer
1920 * type.
1921 *
1922 * @param enumContainerType
1923 * An ENUM_CONTAINER_TYPE node.
1924 * @return An integer declaration corresponding to the container type.
1925 * @throws ParseException
1926 * If the type does not parse correctly or if it is not an
1927 * integer type.
1928 */
1929 private IntegerDeclaration parseEnumContainerType(
1930 CommonTree enumContainerType) throws ParseException {
866e5b51
FC
1931
1932 /* Get the child, which should be a type specifier list */
72dbc4ac 1933 CommonTree typeSpecifierList = (CommonTree) enumContainerType.getChild(0);
866e5b51
FC
1934
1935 /* Parse it and get the corresponding declaration */
1936 IDeclaration decl = parseTypeSpecifierList(typeSpecifierList, null);
1937
1938 /* If is is an integer, return it, else throw an error */
1939 if (decl instanceof IntegerDeclaration) {
1940 return (IntegerDeclaration) decl;
1941 }
1942 throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
1943 }
1944
1945 private VariantDeclaration parseVariant(CommonTree variant)
1946 throws ParseException {
866e5b51
FC
1947
1948 List<CommonTree> children = variant.getChildren();
1949 VariantDeclaration variantDeclaration = null;
1950
1951 boolean hasName = false;
1952 String variantName = null;
1953
1954 boolean hasBody = false;
1955 CommonTree variantBody = null;
1956
1957 boolean hasTag = false;
1958 String variantTag = null;
1959
1960 for (CommonTree child : children) {
1961 switch (child.getType()) {
1962 case CTFParser.VARIANT_NAME:
866e5b51
FC
1963
1964 hasName = true;
1965
72dbc4ac 1966 CommonTree variantNameIdentifier = (CommonTree) child.getChild(0);
866e5b51 1967
866e5b51
FC
1968 variantName = variantNameIdentifier.getText();
1969
1970 break;
1971 case CTFParser.VARIANT_TAG:
866e5b51
FC
1972
1973 hasTag = true;
1974
72dbc4ac 1975 CommonTree variantTagIdentifier = (CommonTree) child.getChild(0);
866e5b51 1976
866e5b51
FC
1977 variantTag = variantTagIdentifier.getText();
1978
1979 break;
1980 case CTFParser.VARIANT_BODY:
866e5b51
FC
1981
1982 hasBody = true;
1983
1984 variantBody = child;
1985
1986 break;
1987 default:
1988 childTypeError(child);
1989 break;
1990 }
1991 }
1992
1993 if (hasBody) {
1994 /*
1995 * If variant has a name, check if already defined in the current
1996 * scope.
1997 */
1998 if (hasName
1999 && (getCurrentScope().lookupVariant(variantName) != null)) {
2000 throw new ParseException("variant " + variantName //$NON-NLS-1$
2001 + " already defined."); //$NON-NLS-1$
2002 }
2003
2004 /* Create the declaration */
2005 variantDeclaration = new VariantDeclaration();
2006
2007 /* Parse the body */
2008 parseVariantBody(variantBody, variantDeclaration);
2009
2010 /* If variant has name, add it to the current scope. */
2011 if (hasName) {
2012 getCurrentScope().registerVariant(variantName,
2013 variantDeclaration);
2014 }
2015 } else /* !hasBody */{
2016 if (hasName) {
2017 /* Name and !body */
2018
2019 /* Lookup the name in the current scope. */
2020 variantDeclaration = getCurrentScope().rlookupVariant(
2021 variantName);
2022
2023 /*
2024 * If not found, it means that a struct with such name has not
2025 * been defined
2026 */
2027 if (variantDeclaration == null) {
2028 throw new ParseException("variant " + variantName //$NON-NLS-1$
2029 + " is not defined"); //$NON-NLS-1$
2030 }
2031 } else {
2032 /* !Name and !body */
2033
2034 /* We can't do anything with that. */
2035 throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
2036 }
2037 }
2038
2039 if (hasTag) {
2040 variantDeclaration.setTag(variantTag);
2041 }
2042
866e5b51
FC
2043 return variantDeclaration;
2044 }
2045
2046 private void parseVariantBody(CommonTree variantBody,
2047 VariantDeclaration variantDeclaration) throws ParseException {
866e5b51
FC
2048
2049 List<CommonTree> variantDeclarations = variantBody.getChildren();
866e5b51
FC
2050
2051 pushScope();
2052
2053 for (CommonTree declarationNode : variantDeclarations) {
2054 switch (declarationNode.getType()) {
2055 case CTFParser.TYPEALIAS:
2056 parseTypealias(declarationNode);
2057 break;
2058 case CTFParser.TYPEDEF:
2059 parseTypedef(declarationNode);
2060 break;
2061 case CTFParser.SV_DECLARATION:
2062 parseVariantDeclaration(declarationNode, variantDeclaration);
2063 break;
2064 default:
2065 childTypeError(declarationNode);
2066 break;
2067 }
2068 }
2069
2070 popScope();
2071 }
2072
2073 private void parseVariantDeclaration(CommonTree declaration,
2074 VariantDeclaration variant) throws ParseException {
866e5b51 2075
866e5b51
FC
2076
2077 /* Get the type specifier list node */
72dbc4ac 2078 CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
866e5b51
FC
2079
2080 /* Get the type declarator list node */
72dbc4ac 2081 CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
866e5b51
FC
2082
2083 /* Get the type declarator list */
72dbc4ac 2084 List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
866e5b51
FC
2085
2086 /*
2087 * For each type declarator, parse the declaration and add a field to
2088 * the variant
2089 */
2090 for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
866e5b51
FC
2091
2092 StringBuilder identifierSB = new StringBuilder();
2093
2094 IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
2095 typeSpecifierListNode, identifierSB);
2096
2097 if (variant.hasField(identifierSB.toString())) {
2098 throw new ParseException("variant: duplicate field " //$NON-NLS-1$
2099 + identifierSB.toString());
2100 }
2101
2102 variant.addField(identifierSB.toString(), decl);
2103 }
2104 }
2105
2106 /**
2107 * Creates the string representation of a type declaration (type specifier
2108 * list + pointers).
2109 *
2110 * @param typeSpecifierList
2111 * A TYPE_SPECIFIER_LIST node.
2112 * @param pointers
2113 * A list of POINTER nodes.
2114 * @return The string representation.
2115 * @throws ParseException
2116 */
2117 private static String createTypeDeclarationString(
2118 CommonTree typeSpecifierList, List<CommonTree> pointers)
2119 throws ParseException {
2120 StringBuilder sb = new StringBuilder();
2121
2122 createTypeSpecifierListString(typeSpecifierList, sb);
2123 createPointerListString(pointers, sb);
2124
2125 return sb.toString();
2126 }
2127
2128 /**
2129 * Creates the string representation of a list of type specifiers.
2130 *
2131 * @param typeSpecifierList
2132 * A TYPE_SPECIFIER_LIST node.
2133 * @param sb
2134 * A StringBuilder to which will be appended the string.
2135 * @throws ParseException
2136 */
2137 private static void createTypeSpecifierListString(
2138 CommonTree typeSpecifierList, StringBuilder sb)
2139 throws ParseException {
866e5b51
FC
2140
2141 List<CommonTree> children = typeSpecifierList.getChildren();
866e5b51
FC
2142
2143 boolean firstItem = true;
2144
2145 for (CommonTree child : children) {
2146 if (!firstItem) {
2147 sb.append(' ');
2148
2149 }
2150
2151 firstItem = false;
2152
2153 /* Append the string that represents this type specifier. */
2154 createTypeSpecifierString(child, sb);
2155 }
2156 }
2157
2158 /**
2159 * Creates the string representation of a type specifier.
2160 *
2161 * @param typeSpecifier
2162 * A TYPE_SPECIFIER node.
2163 * @param sb
2164 * A StringBuilder to which will be appended the string.
2165 * @throws ParseException
2166 */
2167 private static void createTypeSpecifierString(CommonTree typeSpecifier,
2168 StringBuilder sb) throws ParseException {
2169 switch (typeSpecifier.getType()) {
2170 case CTFParser.FLOATTOK:
2171 case CTFParser.INTTOK:
2172 case CTFParser.LONGTOK:
2173 case CTFParser.SHORTTOK:
2174 case CTFParser.SIGNEDTOK:
2175 case CTFParser.UNSIGNEDTOK:
2176 case CTFParser.CHARTOK:
2177 case CTFParser.DOUBLETOK:
2178 case CTFParser.VOIDTOK:
2179 case CTFParser.BOOLTOK:
2180 case CTFParser.COMPLEXTOK:
2181 case CTFParser.IMAGINARYTOK:
2182 case CTFParser.CONSTTOK:
2183 case CTFParser.IDENTIFIER:
2184 sb.append(typeSpecifier.getText());
2185 break;
2186 case CTFParser.STRUCT: {
72dbc4ac 2187 CommonTree structName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.STRUCT_NAME);
866e5b51
FC
2188 if (structName == null) {
2189 throw new ParseException(
2190 "nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
2191 }
866e5b51 2192
72dbc4ac 2193 CommonTree structNameIdentifier = (CommonTree) structName.getChild(0);
866e5b51
FC
2194
2195 sb.append(structNameIdentifier.getText());
2196 break;
2197 }
2198 case CTFParser.VARIANT: {
72dbc4ac 2199 CommonTree variantName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.VARIANT_NAME);
866e5b51
FC
2200 if (variantName == null) {
2201 throw new ParseException(
2202 "nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
2203 }
866e5b51 2204
72dbc4ac 2205 CommonTree variantNameIdentifier = (CommonTree) variantName.getChild(0);
866e5b51
FC
2206
2207 sb.append(variantNameIdentifier.getText());
2208 break;
2209 }
2210 case CTFParser.ENUM: {
72dbc4ac 2211 CommonTree enumName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.ENUM_NAME);
866e5b51
FC
2212 if (enumName == null) {
2213 throw new ParseException(
2214 "nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
2215 }
866e5b51
FC
2216
2217 CommonTree enumNameIdentifier = (CommonTree) enumName.getChild(0);
866e5b51
FC
2218
2219 sb.append(enumNameIdentifier.getText());
2220 break;
2221 }
2222 case CTFParser.FLOATING_POINT:
2223 case CTFParser.INTEGER:
2224 case CTFParser.STRING:
2225 throw new ParseException(
2226 "CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
2227 /* break; */
2228 default:
2229 childTypeError(typeSpecifier);
2230 break;
2231 }
2232 }
2233
2234 /**
2235 * Creates the string representation of a list of pointers.
2236 *
2237 * @param pointerList
2238 * A list of pointer nodes. If pointerList is null, this function
2239 * does nothing.
2240 * @param sb
2241 * A stringbuilder to which will be appended the string.
2242 */
2243 private static void createPointerListString(List<CommonTree> pointerList,
2244 StringBuilder sb) {
2245 if (pointerList == null) {
2246 return;
2247 }
2248
2249 for (CommonTree pointer : pointerList) {
866e5b51
FC
2250
2251 sb.append(" *"); //$NON-NLS-1$
2252 if (pointer.getChildCount() > 0) {
866e5b51
FC
2253
2254 sb.append(" const"); //$NON-NLS-1$
2255 }
2256 }
2257 }
2258
866e5b51
FC
2259 /**
2260 * @param node
2261 * The node to check.
2262 * @return True if the given node is an unary string.
2263 */
2264 private static boolean isUnaryString(CommonTree node) {
72dbc4ac
MK
2265 return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING) ||
2266 (node.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES));
866e5b51
FC
2267 }
2268
2269 /**
2270 * @param node
2271 * The node to check.
2272 * @return True if the given node is an unary integer.
2273 */
2274 private static boolean isUnaryInteger(CommonTree node) {
72dbc4ac
MK
2275 return ((node.getType() == CTFParser.UNARY_EXPRESSION_DEC) ||
2276 (node.getType() == CTFParser.UNARY_EXPRESSION_HEX) ||
2277 (node.getType() == CTFParser.UNARY_EXPRESSION_OCT));
866e5b51
FC
2278 }
2279
2280 /**
2281 * Parses a unary string node and return the string value.
2282 *
2283 * @param unaryString
2284 * The unary string node to parse (type UNARY_EXPRESSION_STRING
2285 * or UNARY_EXPRESSION_STRING_QUOTES).
2286 * @return The string value.
2287 */
2288 /*
2289 * It would be really nice to remove the quotes earlier, such as in the
2290 * parser.
2291 */
2292 private static String parseUnaryString(CommonTree unaryString) {
866e5b51 2293
866e5b51 2294 CommonTree value = (CommonTree) unaryString.getChild(0);
866e5b51
FC
2295 String strval = value.getText();
2296
2297 /* Remove quotes */
2298 if (unaryString.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES) {
2299 strval = strval.substring(1, strval.length() - 1);
2300 }
2301
2302 return strval;
2303 }
2304
2305 /**
2306 * Parses an unary integer (dec, hex or oct).
2307 *
2308 * @param unaryInteger
2309 * An unary integer node.
2310 * @return The integer value.
a94410d9 2311 * @throws CTFReaderException
866e5b51 2312 */
a94410d9 2313 private static long parseUnaryInteger(CommonTree unaryInteger) throws ParseException {
866e5b51
FC
2314
2315 List<CommonTree> children = unaryInteger.getChildren();
2316 CommonTree value = children.get(0);
2317 String strval = value.getText();
2318
2319 long intval;
a94410d9
MK
2320 try {
2321 if (unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_DEC) {
2322 intval = Long.parseLong(strval, 10);
2323 } else if (unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_HEX) {
2324 intval = Long.parseLong(strval, 0x10);
2325 } else { /* unaryInteger.getType() == CTFParser.UNARY_EXPRESSION_OCT */
2326 intval = Long.parseLong(strval, 010); // 010 == 0x08 == 8
2327 }
2328 } catch (NumberFormatException e) {
2329 throw new ParseException(e);
866e5b51 2330 }
866e5b51
FC
2331 /* The rest of children are sign */
2332 if ((children.size() % 2) == 0) {
2333 return -intval;
2334 }
2335 return intval;
2336 }
2337
2338 private static long getMajorOrMinor(CommonTree rightNode)
2339 throws ParseException {
866e5b51
FC
2340
2341 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2342
2343 if (isUnaryInteger(firstChild)) {
2344 if (rightNode.getChildCount() > 1) {
2345 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2346 }
2347
2348 long m = parseUnaryInteger(firstChild);
2349
2350 if (m < 0) {
2351 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2352 }
2353
2354 return m;
2355 }
2356 throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
2357 }
2358
2359 private static UUID getUUID(CommonTree rightNode) throws ParseException {
866e5b51
FC
2360
2361 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2362
2363 if (isUnaryString(firstChild)) {
2364 if (rightNode.getChildCount() > 1) {
2365 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2366 }
2367
2368 String uuidstr = parseUnaryString(firstChild);
2369
2370 try {
2371 UUID uuid = UUID.fromString(uuidstr);
2372 return uuid;
2373 } catch (IllegalArgumentException e) {
2374 throw new ParseException("Invalid format for UUID"); //$NON-NLS-1$
2375 }
2376 }
2377 throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
2378 }
2379
2380 /**
2381 * Gets the value of a "signed" integer attribute.
2382 *
2383 * @param rightNode
2384 * A CTF_RIGHT node.
2385 * @return The "signed" value as a boolean.
2386 * @throws ParseException
2387 */
2388 private static boolean getSigned(CommonTree rightNode)
2389 throws ParseException {
866e5b51
FC
2390
2391 boolean ret = false;
2392 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2393
2394 if (isUnaryString(firstChild)) {
2395 String strval = concatenateUnaryStrings(rightNode.getChildren());
2396
32ede2ec
MK
2397 if (strval.equals(CTFStrings.TRUE)
2398 || strval.equals(CTFStrings.TRUE2)) {
866e5b51 2399 ret = true;
32ede2ec
MK
2400 } else if (strval.equals(CTFStrings.FALSE)
2401 || strval.equals(CTFStrings.FALSE2)) {
866e5b51
FC
2402 ret = false;
2403 } else {
2404 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2405 + firstChild.getChild(0).getText());
2406 }
2407 } else if (isUnaryInteger(firstChild)) {
2408 /* Happens if the value is something like "1234.hello" */
2409 if (rightNode.getChildCount() > 1) {
2410 throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
2411 }
2412
2413 long intval = parseUnaryInteger(firstChild);
2414
2415 if (intval == 1) {
2416 ret = true;
2417 } else if (intval == 0) {
2418 ret = false;
2419 } else {
2420 throw new ParseException("Invalid boolean value " //$NON-NLS-1$
2421 + firstChild.getChild(0).getText());
2422 }
2423 } else {
2424 throw new ParseException();
2425 }
2426
2427 return ret;
2428 }
2429
2430 /**
2431 * Gets the value of a "byte_order" integer attribute.
2432 *
2433 * @param rightNode
2434 * A CTF_RIGHT node.
2435 * @return The "byte_order" value.
2436 * @throws ParseException
2437 */
2438 private ByteOrder getByteOrder(CommonTree rightNode) throws ParseException {
866e5b51
FC
2439
2440 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2441
2442 if (isUnaryString(firstChild)) {
2443 String strval = concatenateUnaryStrings(rightNode.getChildren());
2444
07002e0a 2445 if (strval.equals(CTFStrings.LE)) {
866e5b51 2446 return ByteOrder.LITTLE_ENDIAN;
32ede2ec
MK
2447 } else if (strval.equals(CTFStrings.BE)
2448 || strval.equals(CTFStrings.NETWORK)) {
866e5b51 2449 return ByteOrder.BIG_ENDIAN;
07002e0a 2450 } else if (strval.equals(CTFStrings.NATIVE)) {
866e5b51
FC
2451 return trace.getByteOrder();
2452 } else {
2453 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2454 }
2455 }
2456 throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
2457 }
2458
2459 /**
2460 * Determines if the given value is a valid alignment value.
2461 *
2462 * @param alignment
2463 * The value to check.
2464 * @return True if it is valid.
2465 */
2466 private static boolean isValidAlignment(long alignment) {
2467 return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
2468 }
2469
2470 /**
2471 * Gets the value of a "size" integer attribute.
2472 *
2473 * @param rightNode
2474 * A CTF_RIGHT node.
2475 * @return The "size" value.
2476 * @throws ParseException
2477 */
2478 private static long getSize(CommonTree rightNode) throws ParseException {
866e5b51
FC
2479
2480 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2481
2482 if (isUnaryInteger(firstChild)) {
2483 if (rightNode.getChildCount() > 1) {
2484 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2485 }
2486
2487 long size = parseUnaryInteger(firstChild);
2488
2489 if (size < 1) {
2490 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2491 }
2492
2493 return size;
2494 }
2495 throw new ParseException("Invalid value for size"); //$NON-NLS-1$
2496 }
2497
2498 /**
2499 * Gets the value of a "align" integer or struct attribute.
2500 *
2501 * @param node
2502 * A CTF_RIGHT node or directly an unary integer.
2503 * @return The align value.
2504 * @throws ParseException
2505 */
2506 private static long getAlignment(CommonTree node) throws ParseException {
866e5b51
FC
2507
2508 /*
2509 * If a CTF_RIGHT node was passed, call getAlignment with the first
2510 * child
2511 */
2512 if (node.getType() == CTFParser.CTF_RIGHT) {
2513 if (node.getChildCount() > 1) {
2514 throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
2515 }
2516
2517 return getAlignment((CommonTree) node.getChild(0));
2518 } else if (isUnaryInteger(node)) {
2519 long alignment = parseUnaryInteger(node);
2520
2521 if (!isValidAlignment(alignment)) {
2522 throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
2523 + alignment);
2524 }
2525
2526 return alignment;
2527 }
2528 throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
2529 }
2530
2531 /**
2532 * Gets the value of a "base" integer attribute.
2533 *
2534 * @param rightNode
2535 * An CTF_RIGHT node.
2536 * @return The "base" value.
2537 * @throws ParseException
2538 */
2539 private static int getBase(CommonTree rightNode) throws ParseException {
866e5b51
FC
2540
2541 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2542
2543 if (isUnaryInteger(firstChild)) {
2544 if (rightNode.getChildCount() > 1) {
2545 throw new ParseException("invalid base value"); //$NON-NLS-1$
2546 }
2547
2548 long intval = parseUnaryInteger(firstChild);
2549 if ((intval == 2) || (intval == 8) || (intval == 10)
2550 || (intval == 16)) {
2551 return (int) intval;
2552 }
2553 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2554 } else if (isUnaryString(firstChild)) {
2555 String strval = concatenateUnaryStrings(rightNode.getChildren());
2556
32ede2ec
MK
2557 if (strval.equals(CTFStrings.DECIMAL)
2558 || strval.equals(CTFStrings.DEC)
2559 || strval.equals(CTFStrings.DEC_CTE)
2560 || strval.equals(CTFStrings.INT_MOD)
07002e0a 2561 || strval.equals(CTFStrings.UNSIGNED_CTE)) {
866e5b51 2562 return 10;
32ede2ec
MK
2563 } else if (strval.equals(CTFStrings.HEXADECIMAL)
2564 || strval.equals(CTFStrings.HEX)
2565 || strval.equals(CTFStrings.X)
2566 || strval.equals(CTFStrings.X2)
07002e0a 2567 || strval.equals(CTFStrings.POINTER)) {
866e5b51 2568 return 16;
32ede2ec
MK
2569 } else if (strval.equals(CTFStrings.OCTAL)
2570 || strval.equals(CTFStrings.OCT)
07002e0a 2571 || strval.equals(CTFStrings.OCTAL_CTE)) {
866e5b51 2572 return 8;
32ede2ec
MK
2573 } else if (strval.equals(CTFStrings.BINARY)
2574 || strval.equals(CTFStrings.BIN)) {
866e5b51
FC
2575 return 2;
2576 } else {
2577 throw new ParseException("Invalid value for base"); //$NON-NLS-1$
2578 }
2579 } else {
2580 throw new ParseException("invalid value for base"); //$NON-NLS-1$
2581 }
2582 }
2583
2584 /**
2585 * Gets the value of an "encoding" integer attribute.
2586 *
2587 * @param rightNode
2588 * A CTF_RIGHT node.
2589 * @return The "encoding" value.
2590 * @throws ParseException
2591 */
2592 private static Encoding getEncoding(CommonTree rightNode)
2593 throws ParseException {
866e5b51
FC
2594
2595 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2596
2597 if (isUnaryString(firstChild)) {
2598 String strval = concatenateUnaryStrings(rightNode.getChildren());
2599
07002e0a 2600 if (strval.equals(CTFStrings.UTF8)) {
866e5b51 2601 return Encoding.UTF8;
07002e0a 2602 } else if (strval.equals(CTFStrings.ASCII)) {
866e5b51 2603 return Encoding.ASCII;
07002e0a 2604 } else if (strval.equals(CTFStrings.NONE)) {
866e5b51
FC
2605 return Encoding.NONE;
2606 } else {
2607 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2608 }
2609 }
2610 throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
2611 }
2612
2613 private static long getStreamID(CommonTree rightNode) throws ParseException {
866e5b51
FC
2614
2615 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2616
2617 if (isUnaryInteger(firstChild)) {
2618 if (rightNode.getChildCount() > 1) {
2619 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2620 }
2621
2622 long intval = parseUnaryInteger(firstChild);
2623
2624 return intval;
2625 }
2626 throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
2627 }
2628
2629 private static String getEventName(CommonTree rightNode)
2630 throws ParseException {
866e5b51
FC
2631
2632 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2633
2634 if (isUnaryString(firstChild)) {
2635 String str = concatenateUnaryStrings(rightNode.getChildren());
2636
2637 return str;
2638 }
2639 throw new ParseException("invalid value for event name"); //$NON-NLS-1$
2640 }
2641
2642 private static long getEventID(CommonTree rightNode) throws ParseException {
866e5b51
FC
2643
2644 CommonTree firstChild = (CommonTree) rightNode.getChild(0);
2645
2646 if (isUnaryInteger(firstChild)) {
2647 if (rightNode.getChildCount() > 1) {
2648 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2649 }
2650
2651 long intval = parseUnaryInteger(firstChild);
2652
2653 return intval;
2654 }
2655 throw new ParseException("invalid value for event id"); //$NON-NLS-1$
2656 }
2657
2658 /**
2659 * Concatenates a list of unary strings separated by arrows (->) or dots.
2660 *
2661 * @param strings
2662 * A list, first element being an unary string, subsequent
2663 * elements being ARROW or DOT nodes with unary strings as child.
2664 * @return The string representation of the unary string chain.
2665 */
2666 private static String concatenateUnaryStrings(List<CommonTree> strings) {
866e5b51
FC
2667
2668 StringBuilder sb = new StringBuilder();
2669
2670 CommonTree first = strings.get(0);
2671 sb.append(parseUnaryString(first));
2672
2673 boolean isFirst = true;
2674
2675 for (CommonTree ref : strings) {
2676 if (isFirst) {
2677 isFirst = false;
2678 continue;
2679 }
2680
866e5b51
FC
2681
2682 CommonTree id = (CommonTree) ref.getChild(0);
2683
2684 if (ref.getType() == CTFParser.ARROW) {
2685 sb.append("->"); //$NON-NLS-1$
2686 } else { /* DOT */
2687 sb.append('.');
2688 }
2689
2690 sb.append(parseUnaryString(id));
2691 }
2692
2693 return sb.toString();
2694 }
2695
2696 /**
2697 * Throws a ParseException stating that the parent-child relation between
2698 * the given node and its parent is not valid. It means that the shape of
2699 * the AST is unexpected.
2700 *
2701 * @param child
2702 * The invalid child node.
2703 * @throws ParseException
2704 */
2705 private static void childTypeError(CommonTree child) throws ParseException {
2706 CommonTree parent = (CommonTree) child.getParent();
2707 String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
2708 + " can't have a child of type " //$NON-NLS-1$
2709 + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
2710
2711 throw new ParseException(error);
2712 }
2713
2714 // ------------------------------------------------------------------------
2715 // Scope management
2716 // ------------------------------------------------------------------------
2717
2718 /**
2719 * Adds a new declaration scope on the top of the scope stack.
2720 */
2721 private void pushScope() {
2722 scope = new DeclarationScope(scope);
2723 }
2724
2725 /**
2726 * Removes the top declaration scope from the scope stack.
2727 */
2728 private void popScope() {
866e5b51
FC
2729 scope = scope.getParentScope();
2730 }
2731
2732 /**
2733 * Returns the current declaration scope.
2734 *
2735 * @return The current declaration scope.
2736 */
2737 private DeclarationScope getCurrentScope() {
866e5b51
FC
2738 return scope;
2739 }
2740
2741}
This page took 0.151862 seconds and 5 git commands to generate.