0001: /*
0002: * xtc - The eXTensible Compiler
0003: * Copyright (C) 2004-2007 Robert Grimm
0004: *
0005: * This program is free software; you can redistribute it and/or
0006: * modify it under the terms of the GNU General Public License
0007: * version 2 as published by the Free Software Foundation.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
0017: * USA.
0018: */
0019: package xtc.lang;
0020:
0021: import java.util.Iterator;
0022:
0023: import xtc.tree.LineMarker;
0024: import xtc.tree.Node;
0025: import xtc.tree.GNode;
0026: import xtc.tree.Pragma;
0027: import xtc.tree.Printer;
0028: import xtc.tree.SourceIdentity;
0029: import xtc.tree.Token;
0030: import xtc.tree.Visitor;
0031:
0032: /**
0033: * A pretty printer for C.
0034: *
0035: * <p />A note on operator precedence: This printer uses precedence
0036: * levels to control when to print parentheses around expressions.
0037: * The actual precedence values are the standard C precedence levels
0038: * multiplied by ten.
0039: *
0040: * @author Robert Grimm
0041: * @version $Revision: 1.74 $
0042: */
0043: public class CPrinter extends Visitor {
0044:
0045: /**
0046: * The flag for printing additional parentheses to avoid gcc
0047: * warnings.
0048: */
0049: public static final boolean EXTRA_PARENTHESES = true;
0050:
0051: /**
0052: * The base precedence level. This level corresponds to the
0053: * expression nonterminal.
0054: */
0055: public static final int PREC_BASE = 0;
0056:
0057: /**
0058: * The list precedence level. This level corresponds to the
0059: * assignment expression nonterminal.
0060: */
0061: public static final int PREC_LIST = 11;
0062:
0063: /**
0064: * The constant precedence level. This level corresponds to the
0065: * conditional expression nonterminal.
0066: */
0067: public static final int PREC_CONSTANT = 21;
0068:
0069: /** The flag for any statement besides an if or if-else statement. */
0070: public static final int STMT_ANY = 0;
0071:
0072: /** The flag for an if statement. */
0073: public static final int STMT_IF = 1;
0074:
0075: /** The flag for an if-else statement. */
0076: public static final int STMT_IF_ELSE = 2;
0077:
0078: /** The printer for this C printer. */
0079: protected final Printer printer;
0080:
0081: /**
0082: * The flag for whether to line up declarations and statements with
0083: * their source locations.
0084: */
0085: protected final boolean lineUp;
0086:
0087: /** The flag for whether to use GNU coding guidelines. */
0088: protected final boolean gnuify;
0089:
0090: /** The flag for whether we just printed a declaration. */
0091: protected boolean isDeclaration;
0092:
0093: /**
0094: * The flag for whether we just printed a declaration spanning
0095: * several lines.
0096: */
0097: protected boolean isLongDecl;
0098:
0099: /** The flag for whether we just printed a statement. */
0100: protected boolean isStatement;
0101:
0102: /** The flag for whether the last statement ended with an open line. */
0103: protected boolean isOpenLine;
0104:
0105: /**
0106: * The flag for whether the current statement requires nesting or
0107: * for whether the current declaration is nested within a for
0108: * statement.
0109: */
0110: protected boolean isNested;
0111:
0112: /**
0113: * The flag for whether this statement is the else clause of an
0114: * if-else statement.
0115: */
0116: protected boolean isIfElse;
0117:
0118: /**
0119: * The flag for whether this compound statement is an expression (as
0120: * in the GCC extension).
0121: */
0122: protected boolean isStmtAsExpr;
0123:
0124: /**
0125: * The flag for whether this declarator is a function definition.
0126: */
0127: protected boolean isFunctionDef;
0128:
0129: /** The operator precedence level for the current expression. */
0130: protected int precedence;
0131:
0132: /**
0133: * Create a new C printer.
0134: *
0135: * @param printer The printer.
0136: */
0137: public CPrinter(Printer printer) {
0138: this (printer, false, false);
0139: }
0140:
0141: /**
0142: * Create a new C printer.
0143: *
0144: * @param printer The printer.
0145: * @param lineUp The flag for whether to line up declaratons and
0146: * statements with their source locations.
0147: * @param gnuify The flag for whether to use GNU code formatting
0148: * conventions.
0149: */
0150: public CPrinter(Printer printer, boolean lineUp, boolean gnuify) {
0151: this .printer = printer;
0152: this .lineUp = lineUp;
0153: this .gnuify = gnuify;
0154: printer.register(this );
0155: }
0156:
0157: /**
0158: * Determine whether the specified generic node contains a long type
0159: * definition. A long type definition requires multiple lines for
0160: * readability. Examples include enumeration, structure, and union
0161: * type definitions.
0162: *
0163: * @param specs The generic node, representing a list of specifiers.
0164: * @return <code>true</code> if the specifiers contain a long
0165: * type specifier.
0166: */
0167: protected boolean containsLongType(GNode specs) {
0168: for (Object o : specs) {
0169: GNode node = GNode.cast(o);
0170: if (node.hasName("EnumerationTypeDefinition")
0171: || node.hasName("StructureTypeDefinition")
0172: || node.hasName("UnionTypeDefinition")) {
0173: return true;
0174: }
0175: }
0176:
0177: return false;
0178: }
0179:
0180: /**
0181: * Determine whether the specified declaration is long. A long
0182: * declaration requires multiple lines for readability. Examples
0183: * include declarations containing enumeration, structure, and union
0184: * type definitions.
0185: *
0186: * @param decl The declaration.
0187: * @return <code>true</code> if the specified declaration is long.
0188: */
0189: protected boolean isLongDeclaration(GNode decl) {
0190: // Make sure the specified generic node actually is a declaration.
0191: if (!decl.hasName("Declaration"))
0192: return false;
0193:
0194: // Check the declaration specifiers for enumeration, structure,
0195: // and union definitions (but not declarations).
0196: if (containsLongType(decl.getGeneric(1)))
0197: return true;
0198:
0199: // Check the initialized declarator list for initializer lists.
0200: GNode n = decl.getGeneric(2);
0201: if (null != n) {
0202: for (Object o : n) {
0203: GNode elem = GNode.cast(o).getGeneric(3);
0204: if ((null != elem) && elem.hasName("InitializerList")) {
0205: return true;
0206: }
0207: }
0208: }
0209:
0210: // Done.
0211: return false;
0212: }
0213:
0214: /**
0215: * Print an expression as a truth value. This method prints the
0216: * specified node. If that node represents an assignment expression
0217: * and {@link #EXTRA_PARENTHESES} is <code>true</code>, this method
0218: * adds an extra set of parentheses around the expression to avoid
0219: * gcc warnings.
0220: *
0221: * @param n The node to print.
0222: */
0223: protected void formatAsTruthValue(Node n) {
0224: if (GNode.cast(n).hasName("AssignmentExpression")) {
0225: printer.p('(').p(n).p(')');
0226: } else {
0227: printer.p(n);
0228: }
0229: }
0230:
0231: /**
0232: * Start a new statement. This method and the corresponding {@link
0233: * #prepareNested()} and {@link #endStatement(boolean)} methods
0234: * provide a reasonable default for newlines and indentation when
0235: * printing statements. They manage the {@link #isDeclaration},
0236: * {@link #isStatement}, {@link #isOpenLine}, {@link #isNested}, and
0237: * {@link #isIfElse} flags.
0238: *
0239: * @param kind The kind of statement, which must be one of the
0240: * three statement flags defined by this class.
0241: * @param node The statement's node.
0242: * @return The flag for whether the current statement is nested.
0243: */
0244: protected boolean startStatement(int kind, Node node) {
0245: if (isIfElse && ((STMT_IF == kind) || (STMT_IF_ELSE == kind))) {
0246: isNested = false;
0247: } else {
0248: if (lineUp) {
0249: if (isOpenLine)
0250: printer.pln();
0251: printer.lineUp(node);
0252: } else {
0253: if (isDeclaration || isOpenLine) {
0254: printer.pln();
0255: }
0256: }
0257: if (isNested) {
0258: printer.incr();
0259: }
0260: }
0261:
0262: isOpenLine = false;
0263: boolean nested = isNested;
0264: isNested = false;
0265:
0266: return nested;
0267: }
0268:
0269: /**
0270: * Prepare for a nested statement.
0271: *
0272: * @see #startStatement
0273: */
0274: protected void prepareNested() {
0275: isDeclaration = false;
0276: isStatement = false;
0277: isOpenLine = true;
0278: isNested = true;
0279: }
0280:
0281: /**
0282: * End a statement.
0283: *
0284: * @see #startStatement
0285: *
0286: * @param nested The flag for whether the current statement is nested.
0287: */
0288: protected void endStatement(boolean nested) {
0289: if (nested) {
0290: printer.decr();
0291: }
0292: isDeclaration = false;
0293: isStatement = true;
0294: }
0295:
0296: /**
0297: * Enter an expression context. The new context has the specified
0298: * precedence level.
0299: *
0300: * @see #exitContext(int)
0301: *
0302: * @param prec The precedence level for the expression context.
0303: * @return The previous precedence level.
0304: */
0305: protected int enterContext(int prec) {
0306: int old = precedence;
0307: precedence = prec;
0308: return old;
0309: }
0310:
0311: /**
0312: * Enter an expression context. The new context is appropriate for
0313: * an operand opposite the associativity of the current operator.
0314: * For example, when printing an additive expression, this method
0315: * should be called before printing the second operand, as additive
0316: * operators associate left-to-right.
0317: *
0318: * @see #exitContext(int)
0319: *
0320: * @return The previous precedence level.
0321: */
0322: protected int enterContext() {
0323: int old = precedence;
0324: precedence += 1;
0325: return old;
0326: }
0327:
0328: /**
0329: * Exit an expression context.
0330: *
0331: * @see #enterContext(int)
0332: * @see #enterContext()
0333: *
0334: * @param prec The previous precedence level.
0335: */
0336: protected void exitContext(int prec) {
0337: precedence = prec;
0338: }
0339:
0340: /**
0341: * Start printing an expression at the specified operator precedence
0342: * level.
0343: *
0344: * @see #endExpression(int)
0345: *
0346: * @param prec The expression's precedence level.
0347: * @return The previous precedence level.
0348: */
0349: protected int startExpression(int prec) {
0350: if (prec < precedence) {
0351: printer.p('(');
0352: }
0353:
0354: int old = precedence;
0355: precedence = prec;
0356: return old;
0357: }
0358:
0359: /**
0360: * Stop printing an expression.
0361: *
0362: * @see #startExpression(int)
0363: *
0364: * @param prec The previous precedence level.
0365: */
0366: protected void endExpression(int prec) {
0367: if (precedence < prec) {
0368: printer.p(')');
0369: }
0370: precedence = prec;
0371: }
0372:
0373: /** Visit the specified translation unit node. */
0374: public void visitTranslationUnit(GNode n) {
0375: // Reset the state.
0376: isDeclaration = false;
0377: isLongDecl = false;
0378: isStatement = false;
0379: isOpenLine = false;
0380: isNested = false;
0381: isIfElse = false;
0382: isStmtAsExpr = false;
0383: isFunctionDef = false;
0384: precedence = PREC_BASE;
0385:
0386: if (lineUp)
0387: printer.line(1);
0388:
0389: for (Object o : n) {
0390: printer.p((Node) o);
0391: }
0392: }
0393:
0394: /** Visit the specified function definition node. */
0395: public void visitFunctionDefinition(GNode n) {
0396: if (lineUp) {
0397: if (isOpenLine)
0398: printer.pln();
0399: printer.lineUp(n);
0400: } else if (isStatement || isDeclaration || isLongDecl) {
0401: if (isOpenLine)
0402: printer.pln();
0403: printer.pln();
0404: }
0405:
0406: isDeclaration = false;
0407: isLongDecl = false;
0408: isStatement = false;
0409: isOpenLine = false;
0410: isNested = false;
0411: isIfElse = false;
0412:
0413: // Print extension and return type.
0414: printer.indent();
0415: if ((null != n.get(0)) || (null != n.get(1))) {
0416: if (null != n.get(0)) {
0417: printer.p("__extension__ ");
0418: }
0419: printer.p(n.getNode(1));
0420: }
0421:
0422: // Print function name and parameters.
0423: Node declor = n.getNode(2);
0424: if (gnuify) {
0425: GNode g = GNode.cast(declor);
0426: if (g.hasName("PointerDeclarator")) {
0427: isFunctionDef = true;
0428: printer.p(' ').p(declor);
0429: declor = g.getNode(1);
0430: }
0431: printer.pln().indent();
0432: } else if (null != n.get(1)) {
0433: printer.p(' ');
0434: }
0435: printer.p(declor);
0436: if (null != n.get(3)) {
0437: printer.pln().incr().p(n.getNode(3)).decr();
0438: } else if (gnuify) {
0439: printer.pln();
0440: isOpenLine = false;
0441: } else {
0442: isOpenLine = true;
0443: }
0444:
0445: isDeclaration = false;
0446: isLongDecl = false;
0447: isStatement = false;
0448: isNested = false;
0449: isIfElse = false;
0450:
0451: printer.p(n.getNode(4)).pln();
0452:
0453: isDeclaration = true;
0454: isLongDecl = true;
0455: isStatement = false;
0456: isOpenLine = false;
0457: isNested = false;
0458: isIfElse = false;
0459: }
0460:
0461: /** Visit the specified empty definition. */
0462: public void visitEmptyDefinition(GNode n) {
0463: /* We are not printing anything. */
0464: }
0465:
0466: /** Visit the specified declaration list node. */
0467: public void visitDeclarationList(GNode n) {
0468: for (Object o : n)
0469: printer.p((Node) o);
0470: }
0471:
0472: /** Visit the specified declaration node. */
0473: public void visitDeclaration(GNode n) {
0474: boolean nested = isNested;
0475: if (!nested) {
0476: if (lineUp) {
0477: if (isOpenLine)
0478: printer.pln();
0479: printer.lineUp(n);
0480: } else if (isStatement || isLongDecl) {
0481: if (isOpenLine)
0482: printer.pln();
0483: printer.pln();
0484: } else if (isLongDeclaration(n)) {
0485: printer.pln();
0486: }
0487: printer.indent();
0488: }
0489:
0490: isDeclaration = false;
0491: isLongDecl = false;
0492: isStatement = false;
0493: isOpenLine = false;
0494: isNested = false;
0495: isIfElse = false;
0496:
0497: if (null != n.get(0)) {
0498: printer.p("__extension__ ");
0499: }
0500: printer.p(n.getNode(1));
0501: if (null != n.get(2)) {
0502: printer.p(' ').p(n.getNode(2));
0503: }
0504: if (!nested) {
0505: printer.p(';').fitMore().pln();
0506: }
0507:
0508: isDeclaration = true;
0509: isStatement = false;
0510: isOpenLine = false;
0511: isNested = false;
0512: isIfElse = false;
0513: }
0514:
0515: /** Visit the specified declaration specifiers node. */
0516: public void visitDeclarationSpecifiers(GNode n) {
0517: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0518: printer.p((Node) iter.next());
0519: if (iter.hasNext()) {
0520: printer.p(' ');
0521: }
0522: }
0523: }
0524:
0525: /** Visit the specified auto storage class specifier node. */
0526: public void visitAutoSpecifier(GNode n) {
0527: printer.p("auto");
0528: }
0529:
0530: /** Visit the specified extern storage class specifier node. */
0531: public void visitExternSpecifier(GNode n) {
0532: printer.p("extern");
0533: }
0534:
0535: /** Visit the specified register storage class specifier node. */
0536: public void visitRegisterSpecifier(GNode n) {
0537: printer.p("register");
0538: }
0539:
0540: /** Visit the specified static storage class specifier node. */
0541: public void visitStaticSpecifier(GNode n) {
0542: printer.p("static");
0543: }
0544:
0545: /** Visit the specified typedef storage class specifier node. */
0546: public void visitTypedefSpecifier(GNode n) {
0547: printer.p("typedef");
0548: }
0549:
0550: /** Visit the specified volatile qualifier node. */
0551: public void visitVolatileQualifier(GNode n) {
0552: printer.p(n.getString(0));
0553: }
0554:
0555: /** Visit the specified constant qualifier node. */
0556: public void visitConstantQualifier(GNode n) {
0557: printer.p(n.getString(0));
0558: }
0559:
0560: /** Visit the specified restrict qualifier node. */
0561: public void visitRestrictQualifier(GNode n) {
0562: printer.p(n.getString(0));
0563: }
0564:
0565: /** Visit the specified function specifier node. */
0566: public void visitFunctionSpecifier(GNode n) {
0567: printer.p(n.getString(0));
0568: }
0569:
0570: /** Visit the specified enumeration type definition. */
0571: public void visitEnumerationTypeDefinition(GNode n) {
0572: printer.p("enum ");
0573: if (null != n.get(0)) {
0574: printer.p(n.getNode(0)).p(' ');
0575: }
0576: if (null != n.get(1)) {
0577: printer.p(n.getString(1)).p(' ');
0578: }
0579: printer.pln('{').incr().p(n.getNode(2)).decr().indent().p('}');
0580: if (null != n.get(3)) {
0581: printer.p(' ').p(n.getNode(3));
0582: }
0583: isLongDecl = true;
0584: }
0585:
0586: /** Visit the specified enumerator list node. */
0587: public void visitEnumeratorList(GNode n) {
0588: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0589: printer.indent().p((Node) iter.next());
0590: if (iter.hasNext()) {
0591: printer.p(',');
0592: }
0593: printer.pln();
0594: }
0595: }
0596:
0597: /** Visit the specified enumerator node. */
0598: public void visitEnumerator(GNode n) {
0599: printer.p(n.getString(0));
0600: if (null != n.get(1)) {
0601: int prec = enterContext(PREC_CONSTANT);
0602: printer.p(" = ").p(n.getNode(1));
0603: exitContext(prec);
0604: }
0605: }
0606:
0607: /** Visit the specified enumeration type reference node. */
0608: public void visitEnumerationTypeReference(GNode n) {
0609: printer.p("enum ");
0610: if (null != n.get(0)) {
0611: printer.p(n.getNode(0)).p(' ');
0612: }
0613: printer.p(n.getString(1));
0614: }
0615:
0616: /** Visit the specified structure type definition. */
0617: public void visitStructureTypeDefinition(GNode n) {
0618: printer.p("struct ");
0619: if (null != n.get(0)) {
0620: printer.p(n.getNode(0)).p(' ');
0621: }
0622: if (null != n.get(1)) {
0623: printer.p(n.getString(1)).p(' ');
0624: }
0625: printer.pln('{').incr().p(n.getNode(2)).decr().indent().p('}');
0626: if (null != n.get(3)) {
0627: printer.p(' ').p(n.getNode(3));
0628: }
0629: isLongDecl = true;
0630: }
0631:
0632: /** Visit the specified structure type reference. */
0633: public void visitStructureTypeReference(GNode n) {
0634: printer.p("struct ");
0635: if (null != n.get(0)) {
0636: printer.p(n.getNode(0)).p(' ');
0637: }
0638: printer.p(n.getString(1));
0639: }
0640:
0641: /** Visit the specified union type definition. */
0642: public void visitUnionTypeDefinition(GNode n) {
0643: printer.p("union ");
0644: if (null != n.get(0)) {
0645: printer.p(n.getNode(0)).p(' ');
0646: }
0647: if (null != n.get(1)) {
0648: printer.p(n.getString(1)).p(' ');
0649: }
0650: printer.pln('{').incr().p(n.getNode(2)).decr().indent().p('}');
0651: if (null != n.get(3)) {
0652: printer.p(' ').p(n.getNode(3));
0653: }
0654: isLongDecl = true;
0655: }
0656:
0657: /** Visit the specified union type reference. */
0658: public void visitUnionTypeReference(GNode n) {
0659: printer.p("union ");
0660: if (null != n.get(0)) {
0661: printer.p(n.getNode(0)).p(' ');
0662: }
0663: printer.p(n.getString(1));
0664: }
0665:
0666: /** Visit the specified structure declaration list node. */
0667: public void visitStructureDeclarationList(GNode n) {
0668: boolean wasLong = false;
0669: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0670: Node node = (Node) iter.next();
0671:
0672: if (!iter.hasNext()) {
0673: // Do nothing for last child representing annotations.
0674: } else if (containsLongType(GNode.cast(node).getGeneric(1))) {
0675: printer.pln();
0676: wasLong = true;
0677: } else if (wasLong) {
0678: printer.pln();
0679: wasLong = false;
0680: }
0681: printer.p(node);
0682: }
0683: }
0684:
0685: /** Visit the specified structure declaration node. */
0686: public void visitStructureDeclaration(GNode n) {
0687: printer.indent();
0688: if (null != n.get(0)) {
0689: printer.p("__extension__ ");
0690: }
0691: printer.p(n.getNode(1));
0692: if (null != n.get(2)) {
0693: printer.p(' ').p(n.getNode(2));
0694: }
0695: printer.pln(';');
0696: }
0697:
0698: /** Visit the specified specifier qualifier list node. */
0699: public void visitSpecifierQualifierList(GNode n) {
0700: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0701: printer.p((Node) iter.next());
0702: if (iter.hasNext())
0703: printer.p(' ');
0704: }
0705: }
0706:
0707: /** Visit the specified structure declarator list node. */
0708: public void visitStructureDeclaratorList(GNode n) {
0709: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0710: printer.p((Node) iter.next());
0711: if (iter.hasNext()) {
0712: printer.p(", ");
0713: }
0714: }
0715: }
0716:
0717: /** Visit the specified bit field node. */
0718: public void visitBitField(GNode n) {
0719: if (null != n.get(0)) {
0720: printer.p(n.getNode(0)).p(' ');
0721: }
0722: printer.p(n.getNode(1)).p(':');
0723:
0724: int prec = enterContext(PREC_CONSTANT);
0725: printer.p(n.getNode(2));
0726: exitContext(prec);
0727:
0728: if (null != n.get(3)) {
0729: printer.p(' ').p(n.getNode(3));
0730: }
0731: }
0732:
0733: /** Visit the specified attributed declarator node. */
0734: public void visitAttributedDeclarator(GNode n) {
0735: if (null != n.get(0)) {
0736: printer.p(n.getNode(0)).p(' ');
0737: }
0738: printer.p(n.getNode(1));
0739: if (null != n.get(2)) {
0740: printer.p(' ').p(n.getNode(2));
0741: }
0742: }
0743:
0744: /** Visit the specified pointer declarator node. */
0745: public void visitPointerDeclarator(GNode n) {
0746: printer.p(n.getNode(0));
0747: if (isFunctionDef) {
0748: isFunctionDef = false;
0749: return;
0750: }
0751: printer.p(n.getNode(1));
0752: }
0753:
0754: /** Visit the specified pointer node. */
0755: public void visitPointer(GNode n) {
0756: printer.p('*').p(n.getNode(0)).p(n.getNode(1));
0757: }
0758:
0759: /** Visit the specified type qualifier list node. */
0760: public void visitTypeQualifierList(GNode n) {
0761: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0762: printer.p(' ').p((Node) iter.next());
0763: if (!iter.hasNext()) {
0764: printer.p(' ');
0765: }
0766: }
0767: }
0768:
0769: /** Visit the specified simple declarator node. */
0770: public void visitSimpleDeclarator(GNode n) {
0771: printer.p(n.getString(0));
0772: }
0773:
0774: /** Visit the specified function declarator node. */
0775: public void visitFunctionDeclarator(GNode n) {
0776: if (n.getGeneric(0).hasName("SimpleDeclarator")) {
0777: printer.p(n.getNode(0));
0778: } else {
0779: printer.p('(').p(n.getNode(0)).p(')');
0780: }
0781: printer.p('(').p(n.getNode(1)).p(')');
0782: }
0783:
0784: /** Visit the specified parameter type list node. */
0785: public void visitParameterTypeList(GNode n) {
0786: printer.p(n.getNode(0));
0787: if (null != n.get(1)) {
0788: printer.p(", ...");
0789: }
0790: }
0791:
0792: /** Visit the specified parameter list node. */
0793: public void visitParameterList(GNode n) {
0794: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0795: printer.p((Node) iter.next());
0796: if (iter.hasNext()) {
0797: printer.p(", ");
0798: }
0799: }
0800: }
0801:
0802: /** Visit the specified parameter declaration node. */
0803: public void visitParameterDeclaration(GNode n) {
0804: printer.p(n.getNode(0));
0805: if (null != n.get(1)) {
0806: printer.p(' ').p(n.getNode(1));
0807: }
0808: if (null != n.get(2)) {
0809: printer.p(' ').p(n.getNode(2));
0810: }
0811: }
0812:
0813: /** Visit the specified attributed abstract declarator node. */
0814: public void visitAttributedAbstractDeclarator(GNode n) {
0815: if (null != n.get(0)) {
0816: printer.p(n.getNode(0)).p(' ');
0817: }
0818: printer.p(n.getNode(1));
0819: }
0820:
0821: /** Visit the specified abstract declarator node. */
0822: public void visitAbstractDeclarator(GNode n) {
0823: printer.p(n.getNode(0)).p(n.getNode(1));
0824: }
0825:
0826: /** Visit the specified direct abstract declarator node. */
0827: public void visitDirectAbstractDeclarator(GNode n) {
0828: if (null != n.get(0)) {
0829: printer.p('(').p(n.getNode(0)).p(')');
0830: }
0831: if ("[".equals(n.get(1))) {
0832: printer.p('[');
0833:
0834: if (null != n.get(2)) {
0835: int prec = enterContext(PREC_LIST);
0836: printer.p(n.getNode(2));
0837: exitContext(prec);
0838: }
0839:
0840: printer.p(']');
0841:
0842: } else {
0843: printer.p('(').p(n.getNode(2)).p(')');
0844: }
0845: }
0846:
0847: /** Visit the specified identifier list node. */
0848: public void visitIdentifierList(GNode n) {
0849: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0850: printer.p(Token.cast(iter.next()));
0851: if (iter.hasNext()) {
0852: printer.p(", ");
0853: }
0854: }
0855: }
0856:
0857: /** Visit the specified array declarator node. */
0858: public void visitArrayDeclarator(GNode n) {
0859: if (n.getGeneric(0).hasName("SimpleDeclarator")) {
0860: printer.p(n.getNode(0));
0861: } else {
0862: printer.p('(').p(n.getNode(0)).p(')');
0863: }
0864:
0865: printer.p('[');
0866: int column = printer.column();
0867: printer.p(n.getNode(1));
0868:
0869: if (null != n.get(2)) {
0870: if (printer.column() != column)
0871: printer.p(' ');
0872: int prec = enterContext(PREC_LIST);
0873: printer.p(n.getNode(2));
0874: exitContext(prec);
0875: }
0876: printer.p(']');
0877: }
0878:
0879: /** Visit the specified variable length node. */
0880: public void visitVariableLength(GNode n) {
0881: printer.p('*');
0882: }
0883:
0884: /** Visit the specified array qualifier list node. */
0885: public void visitArrayQualifierList(GNode n) {
0886: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0887: printer.p((Node) iter.next());
0888: if (iter.hasNext()) {
0889: printer.p(' ');
0890: }
0891: }
0892: }
0893:
0894: /** Visit the specified complex node. */
0895: public void visitComplex(GNode n) {
0896: printer.p(n.getString(0));
0897: }
0898:
0899: /** Visit the specified double node. */
0900: public void visitDouble(GNode n) {
0901: printer.p("double");
0902: }
0903:
0904: /** Visit the specified float node. */
0905: public void visitFloat(GNode n) {
0906: printer.p("float");
0907: }
0908:
0909: /** Visit the specified long node. */
0910: public void visitLong(GNode n) {
0911: printer.p("long");
0912: }
0913:
0914: /** Visit the specified int node. */
0915: public void visitInt(GNode n) {
0916: printer.p("int");
0917: }
0918:
0919: /** Visit the specified short node. */
0920: public void visitShort(GNode n) {
0921: printer.p("short");
0922: }
0923:
0924: /** Visit the specified char node. */
0925: public void visitChar(GNode n) {
0926: printer.p("char");
0927: }
0928:
0929: /** Visit the specified bool node. */
0930: public void visitBool(GNode n) {
0931: printer.p("_Bool");
0932: }
0933:
0934: /** Visit the specified unsigned node. */
0935: public void visitUnsigned(GNode n) {
0936: printer.p("unsigned");
0937: }
0938:
0939: /** Visit the specified signed node. */
0940: public void visitSigned(GNode n) {
0941: printer.p(n.getString(0));
0942: }
0943:
0944: /** Visit the specified typedef name node. */
0945: public void visitTypedefName(GNode n) {
0946: printer.p(n.getString(0));
0947: }
0948:
0949: /** Visit the specified typeof specifier node. */
0950: public void visitTypeofSpecifier(GNode n) {
0951: int prec = enterContext(PREC_BASE);
0952: printer.p("typeof(").p(n.getNode(0)).p(')');
0953: exitContext(prec);
0954: }
0955:
0956: /** Visit the specified void type specifier node. */
0957: public void visitVoidTypeSpecifier(GNode n) {
0958: printer.p("void");
0959: }
0960:
0961: /** Visit the specified variable argument list specifier node. */
0962: public void visitVarArgListSpecifier(GNode n) {
0963: printer.p("__builtin_va_list");
0964: }
0965:
0966: /** Visit the specified initialized declarator list node. */
0967: public void visitInitializedDeclaratorList(GNode n) {
0968: boolean first = true;
0969: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
0970: if (first) {
0971: first = false;
0972: } else {
0973: printer.buffer();
0974: }
0975: printer.p((Node) iter.next());
0976: if (iter.hasNext()) {
0977: printer.p(", ").fitMore();
0978: }
0979: }
0980: }
0981:
0982: /** Visit the specified initialized declarator node. */
0983: public void visitInitializedDeclarator(GNode n) {
0984: if (null != n.get(0)) {
0985: printer.p(n.getNode(0)).p(' ');
0986: }
0987: printer.p(n.getNode(1));
0988: if (null != n.get(2)) {
0989: printer.p(' ').p(n.getNode(2));
0990: }
0991: if (null != n.get(3)) {
0992: printer.p(' ').p(n.getNode(3));
0993: }
0994: if (null != n.get(4)) {
0995: printer.p(" = ");
0996: int prec = enterContext(PREC_LIST);
0997: printer.p(n.getNode(4));
0998: exitContext(prec);
0999: }
1000: }
1001:
1002: /** Visit the specified initializer list node. */
1003: public void visitInitializerList(GNode n) {
1004: if (!n.isEmpty()) {
1005: printer.pln('{').incr().indent();
1006: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1007: printer.buffer().p((Node) iter.next());
1008: if (iter.hasNext()) {
1009: printer.p(", ");
1010: }
1011: printer.fit();
1012: }
1013: printer.pln().decr().indent().p('}');
1014: isLongDecl = true;
1015: } else {
1016: printer.p("{ }");
1017: }
1018: }
1019:
1020: /** Visit the specified initializer list entry node. */
1021: public void visitInitializerListEntry(GNode n) {
1022: printer.p(n.getNode(0));
1023: int prec = enterContext(PREC_LIST);
1024: printer.p(n.getNode(1));
1025: exitContext(prec);
1026: }
1027:
1028: /** Visit the specified designation node. */
1029: public void visitDesignation(GNode n) {
1030: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1031: printer.p((Node) iter.next());
1032: if (iter.hasNext()) {
1033: printer.p(' ');
1034: }
1035: }
1036: printer.p(" = ");
1037: }
1038:
1039: /** Visit the specified obsolete array designation node. */
1040: public void visitObsoleteArrayDesignation(GNode n) {
1041: // Print the obsolete array designation as a standard array
1042: // designation.
1043: int prec = enterContext(PREC_CONSTANT);
1044: printer.p('[').p(n.getNode(1));
1045: if (3 == n.size() && null != n.getGeneric(2)) {
1046: printer.p(" ... ").p(n.getNode(2));
1047: }
1048: printer.p(']');
1049: exitContext(prec);
1050: printer.p(" = ");
1051: }
1052:
1053: /** Visit the specified obsolete field designation node. */
1054: public void visitObsoleteFieldDesignation(GNode n) {
1055: // Print the obsolete field designation as a standard field
1056: // designation.
1057: printer.p('.').p(n.getString(0)).p(" = ");
1058: }
1059:
1060: /** Visit the specified designator entry node. */
1061: public void visitDesignator(GNode n) {
1062: if ("[".equals(n.get(0))) {
1063: int prec = enterContext(PREC_CONSTANT);
1064: printer.p('[').p(n.getNode(1));
1065: if (3 == n.size()) {
1066: printer.p(" ... ").p(n.getNode(2));
1067: }
1068: printer.p(']');
1069: exitContext(prec);
1070: } else {
1071: printer.p('.').p(n.getNode(1));
1072: }
1073: }
1074:
1075: /** Visit the specified type name node. */
1076: public void visitTypeName(GNode n) {
1077: printer.p(n.getNode(0));
1078: if (null != n.get(1)) {
1079: printer.p(' ').p(n.getNode(1));
1080: }
1081: }
1082:
1083: /** Visit the specified attribute specifier list node. */
1084: public void visitAttributeSpecifierList(GNode n) {
1085: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1086: printer.p((Node) iter.next());
1087: if (iter.hasNext()) {
1088: printer.p(' ');
1089: }
1090: }
1091: }
1092:
1093: /** Visit the specified attribute specifier node. */
1094: public void visitAttributeSpecifier(GNode n) {
1095: printer.p("__attribute__((").p(n.getNode(0)).p("))");
1096: }
1097:
1098: /** Visit the specified attribute list node. */
1099: public void visitAttributeList(GNode n) {
1100: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1101: printer.p((Node) iter.next());
1102: if (iter.hasNext()) {
1103: printer.p(", ");
1104: }
1105: }
1106: }
1107:
1108: /** Visit the specified attribute list entry node. */
1109: public void visitAttributeListEntry(GNode n) {
1110: printer.p(n.getString(0));
1111: if (null != n.get(1)) {
1112: printer.p('(').p(n.getNode(1)).p(')');
1113: }
1114: }
1115:
1116: /** Visit the specified labeled statement node. */
1117: public void visitLabeledStatement(GNode n) {
1118: boolean nested = startStatement(STMT_ANY, n);
1119: printer.indentLess().p(n.getNode(0)).pln();
1120: isDeclaration = false;
1121: isStatement = true;
1122: printer.p(n.getNode(1));
1123: endStatement(nested);
1124: }
1125:
1126: /** Visit the specified named label node. */
1127: public void visitNamedLabel(GNode n) {
1128: printer.p(n.getString(0));
1129: if (null == n.get(1)) {
1130: printer.p(':');
1131: } else {
1132: printer.p(": ").p(n.getNode(1));
1133: }
1134: }
1135:
1136: /** Visit the specified case label node. */
1137: public void visitCaseLabel(GNode n) {
1138: int prec = enterContext(PREC_CONSTANT);
1139: printer.p("case ").p(n.getNode(0));
1140: if (2 == n.size()) {
1141: printer.p(" ... ").p(n.getNode(1));
1142: }
1143: printer.p(':');
1144: exitContext(prec);
1145: }
1146:
1147: /** Visit the specified default label node. */
1148: public void visitDefaultLabel(GNode n) {
1149: printer.p("default:");
1150: }
1151:
1152: /** Visit the specified compound statement node. */
1153: public void visitCompoundStatement(GNode n) {
1154: boolean stmtAsExpr = isStmtAsExpr;
1155: isStmtAsExpr = false;
1156: boolean nested = isNested;
1157:
1158: if (stmtAsExpr) {
1159: printer.pln(" ({").incr();
1160: } else if (nested && gnuify) {
1161: printer.pln().incr().indent().pln('{').incr();
1162: } else if (isOpenLine) {
1163: printer.pln(" {").incr();
1164: } else {
1165: printer.indent().pln('{').incr();
1166: }
1167:
1168: isOpenLine = false;
1169: isNested = false;
1170: isIfElse = false;
1171: for (Object o : n)
1172: printer.p((Node) o);
1173:
1174: if (isOpenLine) {
1175: printer.pln();
1176: }
1177: if (stmtAsExpr) {
1178: printer.decr().indent().p("})");
1179: isOpenLine = true;
1180: } else if (nested && gnuify) {
1181: printer.decr().indent().pln('}').decr();
1182: isOpenLine = false;
1183: } else {
1184: printer.decr().indent().p('}');
1185: isOpenLine = true;
1186: }
1187: isNested = false;
1188: isIfElse = false;
1189: isStmtAsExpr = stmtAsExpr;
1190: }
1191:
1192: /** Visit the specified label declaration node. */
1193: public void visitLocalLabelDeclaration(GNode n) {
1194: if (!isNested) {
1195: if (lineUp) {
1196: if (isOpenLine)
1197: printer.pln();
1198: printer.lineUp(n);
1199: } else if (isStatement || isLongDecl) {
1200: if (isOpenLine)
1201: printer.pln();
1202: printer.pln();
1203: } else if (isLongDeclaration(n)) {
1204: printer.pln();
1205: }
1206: printer.indent();
1207: }
1208:
1209: printer.p("__label__ ");
1210:
1211: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1212: printer.p(Token.cast(iter.next()));
1213: if (iter.hasNext()) {
1214: printer.p(", ");
1215: }
1216: }
1217:
1218: printer.pln(';');
1219:
1220: isDeclaration = true;
1221: isStatement = false;
1222: isOpenLine = false;
1223: isNested = false;
1224: isIfElse = false;
1225: }
1226:
1227: /** Visit the specified if else statement node. */
1228: public void visitIfElseStatement(GNode n) {
1229: boolean nested = startStatement(STMT_IF_ELSE, n);
1230: if (isIfElse) {
1231: printer.p(' ');
1232: } else {
1233: printer.indent();
1234: }
1235: printer.p("if (");
1236: formatAsTruthValue(n.getNode(0));
1237: printer.p(')');
1238: prepareNested();
1239: printer.p(n.getNode(1));
1240: if (isOpenLine) {
1241: printer.p(" else");
1242: } else {
1243: printer.indent().p("else");
1244: }
1245: prepareNested();
1246: boolean ifElse = isIfElse;
1247: isIfElse = true;
1248: printer.p(n.getNode(2));
1249: isIfElse = ifElse;
1250: endStatement(nested);
1251: }
1252:
1253: /** Visit the specified if statement node. */
1254: public void visitIfStatement(GNode n) {
1255: boolean nested = startStatement(STMT_IF, n);
1256: if (isIfElse) {
1257: printer.p(' ');
1258: } else {
1259: printer.indent();
1260: }
1261: printer.p("if (");
1262: formatAsTruthValue(n.getNode(0));
1263: printer.p(')');
1264: prepareNested();
1265: printer.p(n.getNode(1));
1266: endStatement(nested);
1267: }
1268:
1269: /** Visit the specified while statement node. */
1270: public void visitWhileStatement(GNode n) {
1271: boolean nested = startStatement(STMT_ANY, n);
1272: printer.indent().p("while (");
1273: formatAsTruthValue(n.getNode(0));
1274: printer.p(')');
1275: prepareNested();
1276: printer.p(n.getNode(1));
1277: endStatement(nested);
1278: }
1279:
1280: /** Visit the specified do statement node. */
1281: public void visitDoStatement(GNode n) {
1282: boolean nested = startStatement(STMT_ANY, n);
1283: printer.indent().p("do");
1284: prepareNested();
1285: printer.p(n.getNode(0));
1286: if (isOpenLine) {
1287: printer.p(' ');
1288: } else {
1289: printer.indent();
1290: }
1291: printer.p("while (");
1292: formatAsTruthValue(n.getNode(1));
1293: printer.pln(");");
1294: endStatement(nested);
1295: }
1296:
1297: /** Visit the specified for statement node. */
1298: public void visitForStatement(GNode n) {
1299: boolean nested = startStatement(STMT_ANY, n);
1300:
1301: printer.indent().p("for (");
1302: if (null != n.get(0)) {
1303: int prec = enterContext(PREC_BASE);
1304: printer.p(n.getNode(0));
1305: exitContext(prec);
1306: }
1307: printer.p(';');
1308:
1309: if (null != n.get(1)) {
1310: int prec = enterContext(PREC_BASE);
1311: printer.p(' ');
1312: formatAsTruthValue(n.getNode(1));
1313: exitContext(prec);
1314: }
1315:
1316: printer.p(';');
1317: if (null != n.get(2)) {
1318: int prec = enterContext(PREC_BASE);
1319: printer.p(' ').p(n.getNode(2));
1320: exitContext(prec);
1321: }
1322: printer.p(')');
1323:
1324: prepareNested();
1325: printer.p(n.getNode(3));
1326:
1327: endStatement(nested);
1328: }
1329:
1330: /** Visit the specified switch statement node. */
1331: public void visitSwitchStatement(GNode n) {
1332: boolean nested = startStatement(STMT_ANY, n);
1333: printer.indent().p("switch (").p(n.getNode(0)).p(')');
1334: prepareNested();
1335: printer.p(n.getNode(1));
1336: endStatement(nested);
1337: }
1338:
1339: /** Visit the specified break statement node. */
1340: public void visitBreakStatement(GNode n) {
1341: boolean nested = startStatement(STMT_ANY, n);
1342: printer.indent().pln("break;");
1343: endStatement(nested);
1344: }
1345:
1346: /** Visit the specified continue statement node. */
1347: public void visitContinueStatement(GNode n) {
1348: boolean nested = startStatement(STMT_ANY, n);
1349: printer.indent().pln("continue;");
1350: endStatement(nested);
1351: }
1352:
1353: /** Visit the specified return statement node. */
1354: public void visitReturnStatement(GNode n) {
1355: boolean nested = startStatement(STMT_ANY, n);
1356: printer.indent().p("return");
1357: if (null != n.getNode(0)) {
1358: printer.p(' ').p(n.getNode(0));
1359: }
1360: printer.pln(';');
1361: endStatement(nested);
1362: }
1363:
1364: /** Visit the specified goto statement node. */
1365: public void visitGotoStatement(GNode n) {
1366: boolean nested = startStatement(STMT_ANY, n);
1367: printer.indent().p("goto ");
1368: if (null == n.get(0)) {
1369: printer.p(n.getNode(1));
1370: } else {
1371: printer.p('*');
1372: int prec = enterContext(150);
1373: printer.p(n.getNode(1));
1374: exitContext(prec);
1375: }
1376: printer.pln(';');
1377: endStatement(nested);
1378: }
1379:
1380: /** Visit the specified expression statement node. */
1381: public void visitExpressionStatement(GNode n) {
1382: boolean nested = startStatement(STMT_ANY, n);
1383: printer.indent().p(n.getNode(0)).pln(';');
1384: endStatement(nested);
1385: }
1386:
1387: /** Visit the specified empty statement node. */
1388: public void visitEmptyStatement(GNode n) {
1389: boolean nested = startStatement(STMT_ANY, n);
1390: printer.indent().pln(';');
1391: endStatement(nested);
1392: }
1393:
1394: /** Visit the specified comma expression node. */
1395: public void visitCommaExpression(GNode n) {
1396: int prec1 = startExpression(10);
1397: printer.p(n.getNode(0)).p(", ");
1398:
1399: int prec2 = enterContext();
1400: printer.p(n.getNode(1));
1401: exitContext(prec2);
1402:
1403: endExpression(prec1);
1404: }
1405:
1406: /** Visit the specified assignment expression node. */
1407: public void visitAssignmentExpression(GNode n) {
1408: int prec1 = startExpression(20);
1409: int prec2 = enterContext();
1410: printer.p(n.getNode(0));
1411: exitContext(prec2);
1412:
1413: printer.p(' ').p(n.getString(1)).p(' ').p(n.getNode(2));
1414: endExpression(prec1);
1415: }
1416:
1417: /** Visit the specified conditional expression node. */
1418: public void visitConditionalExpression(GNode n) {
1419: int prec1 = startExpression(30);
1420:
1421: int prec2 = enterContext();
1422: printer.p(n.getNode(0)).p(" ? ");
1423: exitContext(prec2);
1424:
1425: prec2 = enterContext();
1426: if (null != n.get(1)) {
1427: printer.p(n.getNode(1)).p(" : ");
1428: } else {
1429: printer.p(" /* Empty */ : ");
1430: }
1431: exitContext(prec2);
1432:
1433: printer.p(n.getNode(2));
1434: endExpression(prec1);
1435: }
1436:
1437: /** Visit the specified logical or expression node. */
1438: public void visitLogicalOrExpression(GNode n) {
1439: int prec1 = startExpression(40);
1440: boolean paren1 = n.getGeneric(0)
1441: .hasName("LogicalAndExpression");
1442: boolean paren2 = n.getGeneric(1)
1443: .hasName("LogicalAndExpression");
1444:
1445: if (EXTRA_PARENTHESES && paren1) {
1446: // Force parentheses to make gcc happy.
1447: printer.p('(').p(n.getNode(0)).p(')');
1448: } else {
1449: printer.p(n.getNode(0));
1450: }
1451:
1452: printer.p(" || ");
1453:
1454: if (EXTRA_PARENTHESES && paren2) {
1455: // Force parentheses to make gcc happy.
1456: printer.p('(').p(n.getNode(1)).p(')');
1457: } else {
1458: int prec2 = enterContext();
1459: printer.p(n.getNode(1));
1460: exitContext(prec2);
1461: }
1462:
1463: endExpression(prec1);
1464: }
1465:
1466: /** Visit the specified logical and expression node. */
1467: public void visitLogicalAndExpression(GNode n) {
1468: int prec1 = startExpression(50);
1469: printer.p(n.getNode(0)).p(" && ");
1470:
1471: int prec2 = enterContext();
1472: printer.p(n.getNode(1));
1473: exitContext(prec2);
1474:
1475: endExpression(prec1);
1476: }
1477:
1478: /** Visit the specified bitwise or expression node. */
1479: public void visitBitwiseOrExpression(GNode n) {
1480: int prec1 = startExpression(60);
1481: GNode op1 = n.getGeneric(0);
1482: boolean paren1 = (op1.hasName("AdditiveExpression")
1483: || op1.hasName("BitwiseAndExpression")
1484: || op1.hasName("BitwiseXorExpression")
1485: || op1.hasName("RelationalExpression") || op1
1486: .hasName("EqualityExpression"));
1487: GNode op2 = n.getGeneric(1);
1488: boolean paren2 = (op2.hasName("AdditiveExpression")
1489: || op2.hasName("BitwiseAndExpression")
1490: || op2.hasName("BitwiseXorExpression")
1491: || op2.hasName("RelationalExpression") || op2
1492: .hasName("EqualityExpression"));
1493:
1494: if (EXTRA_PARENTHESES && paren1) {
1495: // Force parentheses to make gcc happy.
1496: printer.p('(').p(n.getNode(0)).p(')');
1497: } else {
1498: printer.p(n.getNode(0));
1499: }
1500:
1501: printer.p(" | ");
1502:
1503: if (EXTRA_PARENTHESES && paren2) {
1504: // Force parentheses to make gcc happy.
1505: printer.p('(').p(n.getNode(1)).p(')');
1506: } else {
1507: int prec2 = enterContext();
1508: printer.p(n.getNode(1));
1509: exitContext(prec2);
1510: }
1511:
1512: endExpression(prec1);
1513: }
1514:
1515: /** Visit the specified bitwise xor expression node. */
1516: public void visitBitwiseXorExpression(GNode n) {
1517: int prec1 = startExpression(70);
1518: GNode op1 = n.getGeneric(0);
1519: boolean paren1 = (op1.hasName("AdditiveExpression")
1520: || op1.hasName("BitwiseAndExpression")
1521: || op1.hasName("RelationalExpression") || op1
1522: .hasName("EqualityExpression"));
1523: GNode op2 = n.getGeneric(1);
1524: boolean paren2 = (op2.hasName("AdditiveExpression")
1525: || op2.hasName("BitwiseAndExpression")
1526: || op2.hasName("RelationalExpression") || op2
1527: .hasName("EqualityExpression"));
1528:
1529: if (EXTRA_PARENTHESES && paren1) {
1530: // Force parentheses to make gcc happy.
1531: printer.p('(').p(n.getNode(0)).p(')');
1532: } else {
1533: printer.p(n.getNode(0));
1534: }
1535:
1536: printer.p(" ^ ");
1537:
1538: if (EXTRA_PARENTHESES && paren2) {
1539: // Force parentheses to make gcc happy.
1540: printer.p('(').p(n.getNode(1)).p(')');
1541: } else {
1542: int prec2 = enterContext();
1543: printer.p(n.getNode(1));
1544: exitContext(prec2);
1545: }
1546:
1547: endExpression(prec1);
1548: }
1549:
1550: /** Visit the specified bitwise and expression node. */
1551: public void visitBitwiseAndExpression(GNode n) {
1552: int prec1 = startExpression(80);
1553: GNode op1 = n.getGeneric(0);
1554: boolean paren1 = (op1.hasName("AdditiveExpression")
1555: || op1.hasName("RelationalExpression") || op1
1556: .hasName("EqualityExpression"));
1557: GNode op2 = n.getGeneric(1);
1558: boolean paren2 = (op2.hasName("AdditiveExpression")
1559: || op2.hasName("RelationalExpression") || op2
1560: .hasName("EqualityExpression"));
1561:
1562: if (EXTRA_PARENTHESES && paren1) {
1563: // Force parentheses to make gcc happy.
1564: printer.p('(').p(n.getNode(0)).p(')');
1565: } else {
1566: printer.p(n.getNode(0));
1567: }
1568:
1569: printer.p(" & ");
1570:
1571: if (EXTRA_PARENTHESES && paren2) {
1572: // Force parentheses to make gcc happy.
1573: printer.p('(').p(n.getNode(1)).p(')');
1574: } else {
1575: int prec2 = enterContext();
1576: printer.p(n.getNode(1));
1577: exitContext(prec2);
1578: }
1579:
1580: endExpression(prec1);
1581: }
1582:
1583: /** Visit the specified equality expression node. */
1584: public void visitEqualityExpression(GNode n) {
1585: int prec1 = startExpression(90);
1586: GNode op1 = n.getGeneric(0);
1587: boolean paren1 = (op1.hasName("RelationalExpression") || op1
1588: .hasName("EqualityExpression"));
1589: GNode op2 = n.getGeneric(2);
1590: boolean paren2 = (op2.hasName("RelationalExpression") || op2
1591: .hasName("EqualityExpression"));
1592:
1593: if (EXTRA_PARENTHESES && paren1) {
1594: // Force parentheses to make gcc happy.
1595: printer.p('(').p(n.getNode(0)).p(')');
1596: } else {
1597: printer.p(n.getNode(0));
1598: }
1599:
1600: printer.p(' ').p(n.getString(1)).p(' ');
1601:
1602: if (EXTRA_PARENTHESES && paren2) {
1603: // Force parentheses to make gcc happy.
1604: printer.p('(').p(n.getNode(2)).p(')');
1605: } else {
1606: int prec2 = enterContext();
1607: printer.p(n.getNode(2));
1608: exitContext(prec2);
1609: }
1610:
1611: endExpression(prec1);
1612: }
1613:
1614: /** Visit the specified relational expression node. */
1615: public void visitRelationalExpression(GNode n) {
1616: int prec1 = startExpression(100);
1617: GNode op1 = n.getGeneric(0);
1618: boolean paren1 = (op1.hasName("RelationalExpression") || op1
1619: .hasName("EqualityExpression"));
1620: GNode op2 = n.getGeneric(2);
1621: boolean paren2 = (op2.hasName("RelationalExpression") || op2
1622: .hasName("EqualityExpression"));
1623:
1624: if (EXTRA_PARENTHESES && paren1) {
1625: // Force parentheses to make gcc happy.
1626: printer.p('(').p(n.getNode(0)).p(')');
1627: } else {
1628: printer.p(n.getNode(0));
1629: }
1630:
1631: printer.p(' ').p(n.getString(1)).p(' ');
1632:
1633: if (EXTRA_PARENTHESES && paren2) {
1634: // Force parentheses to make gcc happy.
1635: printer.p('(').p(n.getNode(2)).p(')');
1636: } else {
1637: int prec2 = enterContext();
1638: printer.p(n.getNode(2));
1639: exitContext(prec2);
1640: }
1641:
1642: endExpression(prec1);
1643: }
1644:
1645: /** Visit the specified shift expression node. */
1646: public void visitShiftExpression(GNode n) {
1647: int prec1 = startExpression(110);
1648: boolean paren1 = n.getGeneric(0).hasName("AdditiveExpression");
1649: boolean paren2 = n.getGeneric(2).hasName("AdditiveExpression");
1650:
1651: if (EXTRA_PARENTHESES && paren1) {
1652: // Force parentheses to make gcc happy.
1653: printer.p('(').p(n.getNode(0)).p(')');
1654: } else {
1655: printer.p(n.getNode(0));
1656: }
1657:
1658: printer.p(' ').p(n.getString(1)).p(' ');
1659:
1660: if (EXTRA_PARENTHESES && paren2) {
1661: // Force parentheses to make gcc happy.
1662: printer.p('(').p(n.getNode(2)).p(')');
1663: } else {
1664: int prec2 = enterContext();
1665: printer.p(n.getNode(2));
1666: exitContext(prec2);
1667: }
1668:
1669: endExpression(prec1);
1670: }
1671:
1672: /** Visit the specified additive expression node. */
1673: public void visitAdditiveExpression(GNode n) {
1674: int prec1 = startExpression(120);
1675: printer.p(n.getNode(0)).p(' ').p(n.getString(1)).p(' ');
1676:
1677: int prec2 = enterContext();
1678: printer.p(n.getNode(2));
1679: exitContext(prec2);
1680:
1681: endExpression(prec1);
1682: }
1683:
1684: /** Visit the specified multiplicative expression node. */
1685: public void visitMultiplicativeExpression(GNode n) {
1686: int prec1 = startExpression(130);
1687: printer.p(n.getNode(0)).p(' ').p(n.getString(1)).p(' ');
1688:
1689: int prec2 = enterContext();
1690: printer.p(n.getNode(2));
1691: exitContext(prec2);
1692:
1693: endExpression(prec1);
1694: }
1695:
1696: /** Visit the specified cast expression node. */
1697: public void visitCastExpression(GNode n) {
1698: int prec = startExpression(140);
1699: printer.p('(').p(n.getNode(0)).p(')').p(n.getNode(1));
1700: endExpression(prec);
1701: }
1702:
1703: /** Visit the specified sizeof expression node. */
1704: public void visitSizeofExpression(GNode n) {
1705: int prec = startExpression(150);
1706: int prec2 = enterContext(PREC_BASE);
1707: printer.p("sizeof(").p(n.getNode(0)).p(')');
1708: exitContext(prec2);
1709: endExpression(prec);
1710: }
1711:
1712: /** Visit the specified alignof expression node. */
1713: public void visitAlignofExpression(GNode n) {
1714: int prec = startExpression(150);
1715: int prec2 = enterContext(PREC_BASE);
1716: printer.p("__alignof__(").p(n.getNode(0)).p(')');
1717: exitContext(prec2);
1718: endExpression(prec);
1719: }
1720:
1721: /** Visit the specified offsetof expression node. */
1722: public void visitOffsetofExpression(GNode n) {
1723: int prec = startExpression(160);
1724: printer.p("__builtin_offsetof(").p(n.getNode(0)).p(", ").p(
1725: n.getNode(1)).p(')');
1726: endExpression(prec);
1727: }
1728:
1729: /** Visit the specified type compatability expression. */
1730: public void visitTypeCompatibilityExpression(GNode n) {
1731: int prec = startExpression(150);
1732: printer.p("__builtin_types_compatible_p(");
1733: int prec2 = enterContext(PREC_BASE);
1734: printer.p(n.getNode(0));
1735: exitContext(prec2);
1736: prec2 = enterContext(PREC_BASE);
1737: printer.p(", ").p(n.getNode(1)).p(')');
1738: exitContext(prec2);
1739: endExpression(prec);
1740: }
1741:
1742: /** Visit the specified unary minus expression node. */
1743: public void visitUnaryMinusExpression(GNode n) {
1744: int prec = startExpression(150);
1745: GNode e = n.getGeneric(0);
1746: if (e.hasName("UnaryMinusExpression")
1747: || e.hasName("PredecrementExpression")) {
1748: printer.p("-(").p(n.getNode(0)).p(')');
1749: } else {
1750: printer.p('-').p(n.getNode(0));
1751: }
1752: endExpression(prec);
1753: }
1754:
1755: /** Visit the specified unary plus expression node. */
1756: public void visitUnaryPlusExpression(GNode n) {
1757: int prec = startExpression(150);
1758: GNode e = n.getGeneric(0);
1759: if (e.hasName("UnaryPlusExpression")
1760: || e.hasName("PreincrementExpression")) {
1761: printer.p("+(").p(n.getNode(0)).p(')');
1762: } else {
1763: printer.p('+').p(n.getNode(0));
1764: }
1765: endExpression(prec);
1766: }
1767:
1768: /** Visit the specified logical negation expression node. */
1769: public void visitLogicalNegationExpression(GNode n) {
1770: int prec = startExpression(150);
1771: printer.p('!').p(n.getNode(0));
1772: endExpression(prec);
1773: }
1774:
1775: /** Visit the specified bitwise negation expression node. */
1776: public void visitBitwiseNegationExpression(GNode n) {
1777: int prec = startExpression(150);
1778: printer.p('~').p(n.getNode(0));
1779: endExpression(prec);
1780: }
1781:
1782: /** Visit the specified address expression node. */
1783: public void visitAddressExpression(GNode n) {
1784: int prec = startExpression(150);
1785: GNode e = n.getGeneric(0);
1786: if (e.hasName("AddressExpression")
1787: || e.hasName("LabelAddressExpression")) {
1788: printer.p("&(").p(n.getNode(0)).p(')');
1789: } else {
1790: printer.p('&').p(n.getNode(0));
1791: }
1792: endExpression(prec);
1793: }
1794:
1795: /** Visit the specified label address expression node. */
1796: public void visitLabelAddressExpression(GNode n) {
1797: int prec = startExpression(150);
1798: printer.p("&&").p(n.getString(0));
1799: endExpression(prec);
1800: }
1801:
1802: /** Visit the specified indirection expression node. */
1803: public void visitIndirectionExpression(GNode n) {
1804: int prec = startExpression(150);
1805: printer.p('*').p(n.getNode(0));
1806: endExpression(prec);
1807: }
1808:
1809: /** Visit the specified preincrement expression node. */
1810: public void visitPreincrementExpression(GNode n) {
1811: int prec = startExpression(150);
1812: printer.p("++").p(n.getNode(0));
1813: endExpression(prec);
1814: }
1815:
1816: /** Visit the specified predecrement expression node. */
1817: public void visitPredecrementExpression(GNode n) {
1818: int prec = startExpression(150);
1819: printer.p("--").p(n.getNode(0));
1820: endExpression(prec);
1821: }
1822:
1823: /** Visit the extension expression node. */
1824: public void visitExtensionExpression(GNode n) {
1825: int prec = startExpression(150);
1826: printer.p("__extension__ ").p(n.getNode(0));
1827: endExpression(prec);
1828: }
1829:
1830: /** Visit the specified subscript expression node. */
1831: public void visitSubscriptExpression(GNode n) {
1832: int prec1 = startExpression(160);
1833: printer.p(n.getNode(0));
1834: int prec2 = enterContext(PREC_BASE);
1835: printer.p('[').p(n.getNode(1)).p(']');
1836: exitContext(prec2);
1837: endExpression(prec1);
1838: }
1839:
1840: /** Visit the specified direct component selection node. */
1841: public void visitDirectComponentSelection(GNode n) {
1842: int prec = startExpression(160);
1843: printer.p(n.getNode(0)).p('.').p(n.getString(1));
1844: endExpression(prec);
1845: }
1846:
1847: /** Visit the specified indirect component selection node. */
1848: public void visitIndirectComponentSelection(GNode n) {
1849: int prec = startExpression(160);
1850: printer.p(n.getNode(0)).p("->").p(n.getString(1));
1851: endExpression(prec);
1852: }
1853:
1854: /** Visit the specified function call node. */
1855: public void visitFunctionCall(GNode n) {
1856: int prec = startExpression(160);
1857: printer.p(n.getNode(0)).p('(').p(n.getNode(1)).p(')');
1858: endExpression(prec);
1859: }
1860:
1861: /** Visit the specified expression list node. */
1862: public void visitExpressionList(GNode n) {
1863: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1864: int prec = enterContext(PREC_LIST);
1865: printer.p((Node) iter.next());
1866: exitContext(prec);
1867: if (iter.hasNext()) {
1868: printer.p(", ");
1869: }
1870: }
1871: }
1872:
1873: /** Visit the specified postincrement expression node. */
1874: public void visitPostincrementExpression(GNode n) {
1875: int prec = startExpression(160);
1876: printer.p(n.getNode(0)).p("++");
1877: endExpression(prec);
1878: }
1879:
1880: /** Visit the specified postdecrement expression node. */
1881: public void visitPostdecrementExpression(GNode n) {
1882: int prec = startExpression(160);
1883: printer.p(n.getNode(0)).p("--");
1884: endExpression(prec);
1885: }
1886:
1887: /** Visit the specified compound literal node. */
1888: public void visitCompoundLiteral(GNode n) {
1889: int prec = startExpression(160);
1890: printer.p('(').p(n.getNode(0)).p(") ").p(n.getNode(1));
1891: endExpression(prec);
1892: }
1893:
1894: /** Visit the specified primary identifier node. */
1895: public void visitPrimaryIdentifier(GNode n) {
1896: int prec = startExpression(160);
1897: printer.p(n.getString(0));
1898: endExpression(prec);
1899: }
1900:
1901: /** Visit the specified statement as exprression node. */
1902: public void visitStatementAsExpression(GNode n) {
1903: int prec = enterContext(PREC_BASE);
1904: boolean stmtAsExpr = isStmtAsExpr;
1905: isStmtAsExpr = true;
1906: prepareNested();
1907: printer.p(n.getNode(0));
1908: isStmtAsExpr = stmtAsExpr;
1909: exitContext(prec);
1910: }
1911:
1912: /** Visit the specified variable argument access node. */
1913: public void visitVariableArgumentAccess(GNode n) {
1914: int prec = startExpression(160);
1915: printer.p("__builtin_va_arg(");
1916: int prec2 = enterContext(PREC_LIST);
1917: printer.p(n.getNode(0));
1918: exitContext(prec2);
1919: printer.p(", ").p(n.getNode(1)).p(')');
1920: endExpression(prec);
1921: }
1922:
1923: /** Visit the specified assembly definition node. */
1924: public void visitAssemblyDefinition(GNode n) {
1925: if (lineUp) {
1926: if (isOpenLine)
1927: printer.pln();
1928: printer.lineUp(n);
1929: } else if (isStatement || isDeclaration || isLongDecl) {
1930: if (isOpenLine)
1931: printer.pln();
1932: printer.pln();
1933: }
1934:
1935: printer.p(n.getNode(0)).pln(';');
1936:
1937: isDeclaration = false;
1938: isLongDecl = false;
1939: isStatement = false;
1940: isOpenLine = false;
1941: isNested = false;
1942: isIfElse = false;
1943: }
1944:
1945: /** Visit the specified simple assembly expression node. */
1946: public void visitSimpleAssemblyExpression(GNode n) {
1947: int prec = enterContext(PREC_BASE);
1948: printer.p("asm(").p(n.getNode(0)).p(')');
1949: exitContext(prec);
1950: }
1951:
1952: /** Visit the specified assembly statement node. */
1953: public void visitAssemblyStatement(GNode n) {
1954: boolean nested = startStatement(STMT_ANY, n);
1955: printer.indent().p("asm ");
1956: if (null != n.getNode(0)) {
1957: printer.p(n.getNode(0)).p(' ');
1958: }
1959: printer.p('(').p(n.getNode(1)).pln(");");
1960: endStatement(nested);
1961: }
1962:
1963: /** Visit the specified assembly argument node. */
1964: public void visitAssemblyArgument(GNode n) {
1965: final int prec = enterContext(PREC_BASE);
1966: final int number = n.size();
1967: final int align = printer.column();
1968: printer.p(n.getNode(0));
1969: if (number >= 2) {
1970: if (null == n.get(1)) {
1971: printer.pln().align(align).p(
1972: ": /* No output operands */");
1973: } else {
1974: printer.pln().align(align).p(": ").p(n.getNode(1));
1975: }
1976:
1977: if (number >= 3) {
1978: if (null == n.get(2)) {
1979: printer.pln().align(align).p(
1980: ": /* No input operands */");
1981: } else {
1982: printer.pln().align(align).p(": ").p(n.getNode(2));
1983: }
1984:
1985: if (number == 4) {
1986: printer.pln().align(align).p(": ").p(n.getNode(3));
1987: }
1988: }
1989: }
1990: exitContext(prec);
1991: }
1992:
1993: /** Visit the specified assembly operands node. */
1994: public void visitAssemblyOperands(GNode n) {
1995: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
1996: printer.p((Node) iter.next());
1997: if (iter.hasNext()) {
1998: printer.p(", ");
1999: }
2000: }
2001: }
2002:
2003: /** Visit the specified assembly operand node. */
2004: public void visitAssemblyOperand(GNode n) {
2005: if (null != n.get(0)) {
2006: printer.p('[').p(n.getString(0)).p("] ");
2007: }
2008: printer.p(n.getNode(1)).p(" (").p(n.getNode(2)).p(')');
2009: }
2010:
2011: /** Visit the specified assembly clobbers node. */
2012: public void visitAssemblyClobbers(GNode n) {
2013: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
2014: printer.p((Node) iter.next());
2015: if (iter.hasNext()) {
2016: printer.p(", ");
2017: }
2018: }
2019: }
2020:
2021: /** Visit the specified floating constant node. */
2022: public void visitFloatingConstant(GNode n) {
2023: int prec = startExpression(160);
2024: printer.p(n.getString(0));
2025: endExpression(prec);
2026: }
2027:
2028: /** Visit the specified integer constant node. */
2029: public void visitIntegerConstant(GNode n) {
2030: int prec = startExpression(160);
2031: printer.p(n.getString(0));
2032: endExpression(prec);
2033: }
2034:
2035: /** Visit the specified character constant node. */
2036: public void visitCharacterConstant(GNode n) {
2037: int prec = startExpression(160);
2038: printer.p(n.getString(0));
2039: endExpression(prec);
2040: }
2041:
2042: /** Visit the specified string constant node. */
2043: public void visitStringConstant(GNode n) {
2044: int prec = startExpression(160);
2045:
2046: if (1 == n.size()) {
2047: printer.p(n.getString(0));
2048:
2049: } else {
2050: int align = printer.column();
2051: for (Iterator<?> iter = n.iterator(); iter.hasNext();) {
2052: printer.p(Token.cast(iter.next()));
2053: if (iter.hasNext()) {
2054: printer.pln().align(align);
2055: }
2056: }
2057: }
2058:
2059: endExpression(prec);
2060: }
2061:
2062: /** Visit the specified line marker. */
2063: public void visit(LineMarker mark) {
2064: if (isOpenLine) {
2065: isOpenLine = false;
2066: printer.pln();
2067: }
2068: if (lineUp)
2069: printer.lineUp(mark);
2070:
2071: printer.p("# ").p(mark.line).p(" \"").p(mark.file).p('\"');
2072: if (0 != (mark.flags & LineMarker.FLAG_START_FILE)) {
2073: printer.p(" 1");
2074: }
2075: if (0 != (mark.flags & LineMarker.FLAG_RETURN_TO_FILE)) {
2076: printer.p(" 2");
2077: }
2078: if (0 != (mark.flags & LineMarker.FLAG_SYSTEM_HEADER)) {
2079: printer.p(" 3");
2080: }
2081: if (0 != (mark.flags & LineMarker.FLAG_EXTERN_C)) {
2082: printer.p(" 4");
2083: }
2084: printer.pln().p(mark.getNode());
2085: }
2086:
2087: /** Visit the specified pragma. */
2088: public void visit(Pragma p) {
2089: if (isOpenLine) {
2090: isOpenLine = false;
2091: printer.pln();
2092: }
2093: if (lineUp)
2094: printer.lineUp(p);
2095:
2096: printer.p("#pragma ").pln(p.directive).p(p.getNode());
2097: }
2098:
2099: /** Visit the specified source identity marker. */
2100: public void visit(SourceIdentity ident) {
2101: if (isOpenLine) {
2102: isOpenLine = false;
2103: printer.pln();
2104: }
2105: if (lineUp)
2106: printer.lineUp(ident);
2107:
2108: printer.p("#ident \"").p(ident.ident).pln('"').p(
2109: ident.getNode());
2110: }
2111:
2112: }
|