/* * xtc - The eXTensible Compiler * Copyright (C) 2004-2008 Robert Grimm * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package xtc.lang; import java.util.Iterator; import xtc.tree.LineMarker; import xtc.tree.Node; import xtc.tree.GNode; import xtc.tree.Pragma; import xtc.tree.Printer; import xtc.tree.SourceIdentity; import xtc.tree.Token; import xtc.tree.Visitor; /** * A pretty printer for C. * * <p />A note on operator precedence: This printer uses precedence * levels to control when to print parentheses around expressions. * The actual precedence values are the standard C precedence levels * multiplied by ten. * * @author Robert Grimm * @version $Revision: 1.75 $ */ public class CPrinter extends Visitor { /** * The flag for printing additional parentheses to avoid gcc * warnings. */ public static final boolean EXTRA_PARENTHESES = true; /** * The base precedence level. This level corresponds to the * expression nonterminal. */ public static final int PREC_BASE = 0; /** * The list precedence level. This level corresponds to the * assignment expression nonterminal. */ public static final int PREC_LIST = 11; /** * The constant precedence level. This level corresponds to the * conditional expression nonterminal. */ public static final int PREC_CONSTANT = 21; /** The flag for any statement besides an if or if-else statement. */ public static final int STMT_ANY = 0; /** The flag for an if statement. */ public static final int STMT_IF = 1; /** The flag for an if-else statement. */ public static final int STMT_IF_ELSE = 2; /** The printer for this C printer. */ protected final Printer printer; /** * The flag for whether to line up declarations and statements with * their source locations. */ protected final boolean lineUp; /** The flag for whether to use GNU coding guidelines. */ protected final boolean gnuify; /** The flag for whether we just printed a declaration. */ protected boolean isDeclaration; /** * The flag for whether we just printed a declaration spanning * several lines. */ protected boolean isLongDecl; /** The flag for whether we just printed a statement. */ protected boolean isStatement; /** The flag for whether the last statement ended with an open line. */ protected boolean isOpenLine; /** * The flag for whether the current statement requires nesting or * for whether the current declaration is nested within a for * statement. */ protected boolean isNested; /** * The flag for whether this statement is the else clause of an * if-else statement. */ protected boolean isIfElse; /** * The flag for whether this compound statement is an expression (as * in the GCC extension). */ protected boolean isStmtAsExpr; /** * The flag for whether this declarator is a function definition. */ protected boolean isFunctionDef; /** The operator precedence level for the current expression. */ protected int precedence; /** * Create a new C printer. * * @param printer The printer. */ public CPrinter(Printer printer) { this(printer, false, false); } /** * Create a new C printer. * * @param printer The printer. * @param lineUp The flag for whether to line up declaratons and * statements with their source locations. * @param gnuify The flag for whether to use GNU code formatting * conventions. */ public CPrinter(Printer printer, boolean lineUp, boolean gnuify) { this.printer = printer; this.lineUp = lineUp; this.gnuify = gnuify; printer.register(this); } /** * Determine whether the specified generic node contains a long type * definition. A long type definition requires multiple lines for * readability. Examples include enumeration, structure, and union * type definitions. * * @param specs The generic node, representing a list of specifiers. * @return <code>true</code> if the specifiers contain a long * type specifier. */ protected boolean containsLongType(GNode specs) { for (Object o : specs) { GNode node = GNode.cast(o); if (node.hasName("EnumerationTypeDefinition") || node.hasName("StructureTypeDefinition") || node.hasName("UnionTypeDefinition")) { return true; } } return false; } /** * Determine whether the specified declaration is long. A long * declaration requires multiple lines for readability. Examples * include declarations containing enumeration, structure, and union * type definitions. * * @param decl The declaration. * @return <code>true</code> if the specified declaration is long. */ protected boolean isLongDeclaration(GNode decl) { // Make sure the specified generic node actually is a declaration. if (! decl.hasName("Declaration")) return false; // Check the declaration specifiers for enumeration, structure, // and union definitions (but not declarations). if (containsLongType(decl.getGeneric(1))) return true; // Check the initialized declarator list for initializer lists. GNode n = decl.getGeneric(2); if (null != n) { for (Object o : n) { GNode elem = GNode.cast(o).getGeneric(3); if ((null != elem) && elem.hasName("InitializerList")) { return true; } } } // Done. return false; } /** * Print an expression as a truth value. This method prints the * specified node. If that node represents an assignment expression * and {@link #EXTRA_PARENTHESES} is <code>true</code>, this method * adds an extra set of parentheses around the expression to avoid * gcc warnings. * * @param n The node to print. */ protected void formatAsTruthValue(Node n) { if (GNode.cast(n).hasName("AssignmentExpression")) { printer.p('(').p(n).p(')'); } else { printer.p(n); } } /** * Start a new statement. This method and the corresponding {@link * #prepareNested()} and {@link #endStatement(boolean)} methods * provide a reasonable default for newlines and indentation when * printing statements. They manage the {@link #isDeclaration}, * {@link #isStatement}, {@link #isOpenLine}, {@link #isNested}, and * {@link #isIfElse} flags. * * @param kind The kind of statement, which must be one of the * three statement flags defined by this class. * @param node The statement's node. * @return The flag for whether the current statement is nested. */ protected boolean startStatement(int kind, Node node) { if (isIfElse && ((STMT_IF == kind) || (STMT_IF_ELSE == kind))) { isNested = false; } else { if (lineUp) { if (isOpenLine) printer.pln(); printer.lineUp(node); } else { if (isDeclaration || isOpenLine) { printer.pln(); } } if (isNested) { printer.incr(); } } isOpenLine = false; boolean nested = isNested; isNested = false; return nested; } /** * Prepare for a nested statement. * * @see #startStatement */ protected void prepareNested() { isDeclaration = false; isStatement = false; isOpenLine = true; isNested = true; } /** * End a statement. * * @see #startStatement * * @param nested The flag for whether the current statement is nested. */ protected void endStatement(boolean nested) { if (nested) { printer.decr(); } isDeclaration = false; isStatement = true; } /** * Enter an expression context. The new context has the specified * precedence level. * * @see #exitContext(int) * * @param prec The precedence level for the expression context. * @return The previous precedence level. */ protected int enterContext(int prec) { int old = precedence; precedence = prec; return old; } /** * Enter an expression context. The new context is appropriate for * an operand opposite the associativity of the current operator. * For example, when printing an additive expression, this method * should be called before printing the second operand, as additive * operators associate left-to-right. * * @see #exitContext(int) * * @return The previous precedence level. */ protected int enterContext() { int old = precedence; precedence += 1; return old; } /** * Exit an expression context. * * @see #enterContext(int) * @see #enterContext() * * @param prec The previous precedence level. */ protected void exitContext(int prec) { precedence = prec; } /** * Start printing an expression at the specified operator precedence * level. * * @see #endExpression(int) * * @param prec The expression's precedence level. * @return The previous precedence level. */ protected int startExpression(int prec) { if (prec < precedence) { printer.p('('); } int old = precedence; precedence = prec; return old; } /** * Stop printing an expression. * * @see #startExpression(int) * * @param prec The previous precedence level. */ protected void endExpression(int prec) { if (precedence < prec) { printer.p(')'); } precedence = prec; } /** Visit the specified translation unit node. */ public void visitTranslationUnit(GNode n) { // Reset the state. isDeclaration = false; isLongDecl = false; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; isStmtAsExpr = false; isFunctionDef = false; precedence = PREC_BASE; if (lineUp) printer.line(1); for (Object o : n) { printer.p((Node)o); } } /** Visit the specified function definition node. */ public void visitFunctionDefinition(GNode n) { if (lineUp) { if (isOpenLine) printer.pln(); printer.lineUp(n); } else if (isStatement || isDeclaration || isLongDecl) { if (isOpenLine) printer.pln(); printer.pln(); } isDeclaration = false; isLongDecl = false; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; // Print extension and return type. printer.indent(); if ((null != n.get(0)) || (null != n.get(1))) { if (null != n.get(0)) { printer.p("__extension__ "); } printer.p(n.getNode(1)); } // Print function name and parameters. Node declor = n.getNode(2); if (gnuify) { GNode g = GNode.cast(declor); if (g.hasName("PointerDeclarator")) { isFunctionDef = true; printer.p(' ').p(declor); declor = g.getNode(1); } printer.pln().indent(); } else if (null != n.get(1)) { printer.p(' '); } printer.p(declor); if (null != n.get(3)) { printer.pln().incr().p(n.getNode(3)).decr(); } else if (gnuify) { printer.pln(); isOpenLine = false; } else { isOpenLine = true; } isDeclaration = false; isLongDecl = false; isStatement = false; isNested = false; isIfElse = false; printer.p(n.getNode(4)).pln(); isDeclaration = true; isLongDecl = true; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; } /** Visit the specified empty definition. */ public void visitEmptyDefinition(GNode n) { /* We are not printing anything. */ } /** Visit the specified declaration list node. */ public void visitDeclarationList(GNode n) { for (Object o : n) printer.p((Node)o); } /** Visit the specified declaration node. */ public void visitDeclaration(GNode n) { boolean nested = isNested; if (! nested) { if (lineUp) { if (isOpenLine) printer.pln(); printer.lineUp(n); } else if (isStatement || isLongDecl) { if (isOpenLine) printer.pln(); printer.pln(); } else if (isLongDeclaration(n)) { printer.pln(); } printer.indent(); } isDeclaration = false; isLongDecl = false; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; if (null != n.get(0)) { printer.p("__extension__ "); } printer.p(n.getNode(1)); if (null != n.get(2)) { printer.p(' ').p(n.getNode(2)); } if (! nested) { printer.p(';').fitMore().pln(); } isDeclaration = true; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; } /** Visit the specified declaration specifiers node. */ public void visitDeclarationSpecifiers(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(' '); } } } /** Visit the specified auto storage class specifier node. */ public void visitAutoSpecifier(GNode n) { printer.p("auto"); } /** Visit the specified extern storage class specifier node. */ public void visitExternSpecifier(GNode n) { printer.p("extern"); } /** Visit the specified register storage class specifier node. */ public void visitRegisterSpecifier(GNode n) { printer.p("register"); } /** Visit the specified static storage class specifier node. */ public void visitStaticSpecifier(GNode n) { printer.p("static"); } /** Visit the specified thread storage class specifier node. */ public void visitThreadSpecifier(GNode n) { printer.p("__thread"); } /** Visit the specified typedef storage class specifier node. */ public void visitTypedefSpecifier(GNode n) { printer.p("typedef"); } /** Visit the specified volatile qualifier node. */ public void visitVolatileQualifier(GNode n) { printer.p(n.getString(0)); } /** Visit the specified constant qualifier node. */ public void visitConstantQualifier(GNode n) { printer.p(n.getString(0)); } /** Visit the specified restrict qualifier node. */ public void visitRestrictQualifier(GNode n) { printer.p(n.getString(0)); } /** Visit the specified function specifier node. */ public void visitFunctionSpecifier(GNode n) { printer.p(n.getString(0)); } /** Visit the specified enumeration type definition. */ public void visitEnumerationTypeDefinition(GNode n) { printer.p("enum "); if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } if (null != n.get(1)) { printer.p(n.getString(1)).p(' '); } printer.pln('{').incr().p(n.getNode(2)).decr().indent().p('}'); if (null != n.get(3)) { printer.p(' ').p(n.getNode(3)); } isLongDecl = true; } /** Visit the specified enumerator list node. */ public void visitEnumeratorList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.indent().p((Node)iter.next()); if (iter.hasNext()) { printer.p(','); } printer.pln(); } } /** Visit the specified enumerator node. */ public void visitEnumerator(GNode n) { printer.p(n.getString(0)); if (null != n.get(1)) { int prec = enterContext(PREC_CONSTANT); printer.p(" = ").p(n.getNode(1)); exitContext(prec); } } /** Visit the specified enumeration type reference node. */ public void visitEnumerationTypeReference(GNode n) { printer.p("enum "); if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getString(1)); } /** Visit the specified structure type definition. */ public void visitStructureTypeDefinition(GNode n) { printer.p("struct "); if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } if (null != n.get(1)) { printer.p(n.getString(1)).p(' '); } printer.pln('{').incr().p(n.getNode(2)).decr().indent().p('}'); if (null != n.get(3)) { printer.p(' ').p(n.getNode(3)); } isLongDecl = true; } /** Visit the specified structure type reference. */ public void visitStructureTypeReference(GNode n) { printer.p("struct "); if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getString(1)); } /** Visit the specified union type definition. */ public void visitUnionTypeDefinition(GNode n) { printer.p("union "); if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } if (null != n.get(1)) { printer.p(n.getString(1)).p(' '); } printer.pln('{').incr().p(n.getNode(2)).decr().indent().p('}'); if (null != n.get(3)) { printer.p(' ').p(n.getNode(3)); } isLongDecl = true; } /** Visit the specified union type reference. */ public void visitUnionTypeReference(GNode n) { printer.p("union "); if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getString(1)); } /** Visit the specified structure declaration list node. */ public void visitStructureDeclarationList(GNode n) { boolean wasLong = false; for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { Node node = (Node)iter.next(); if (! iter.hasNext()) { // Do nothing for last child representing annotations. } else if (containsLongType(GNode.cast(node).getGeneric(1))) { printer.pln(); wasLong = true; } else if (wasLong) { printer.pln(); wasLong = false; } printer.p(node); } } /** Visit the specified structure declaration node. */ public void visitStructureDeclaration(GNode n) { printer.indent(); if (null != n.get(0)) { printer.p("__extension__ "); } printer.p(n.getNode(1)); if (null != n.get(2)) { printer.p(' ').p(n.getNode(2)); } printer.pln(';'); } /** Visit the specified specifier qualifier list node. */ public void visitSpecifierQualifierList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) printer.p(' '); } } /** Visit the specified structure declarator list node. */ public void visitStructureDeclaratorList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified bit field node. */ public void visitBitField(GNode n) { if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getNode(1)).p(':'); int prec = enterContext(PREC_CONSTANT); printer.p(n.getNode(2)); exitContext(prec); if (null != n.get(3)) { printer.p(' ').p(n.getNode(3)); } } /** Visit the specified attributed declarator node. */ public void visitAttributedDeclarator(GNode n) { if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getNode(1)); if (null != n.get(2)) { printer.p(' ').p(n.getNode(2)); } } /** Visit the specified pointer declarator node. */ public void visitPointerDeclarator(GNode n) { printer.p(n.getNode(0)); if (isFunctionDef) { isFunctionDef = false; return; } printer.p(n.getNode(1)); } /** Visit the specified pointer node. */ public void visitPointer(GNode n) { printer.p('*').p(n.getNode(0)).p(n.getNode(1)); } /** Visit the specified type qualifier list node. */ public void visitTypeQualifierList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p(' ').p((Node)iter.next()); if (! iter.hasNext()) { printer.p(' '); } } } /** Visit the specified simple declarator node. */ public void visitSimpleDeclarator(GNode n) { printer.p(n.getString(0)); } /** Visit the specified function declarator node. */ public void visitFunctionDeclarator(GNode n) { if (n.getGeneric(0).hasName("SimpleDeclarator")) { printer.p(n.getNode(0)); } else { printer.p('(').p(n.getNode(0)).p(')'); } printer.p('(').p(n.getNode(1)).p(')'); } /** Visit the specified parameter type list node. */ public void visitParameterTypeList(GNode n) { printer.p(n.getNode(0)); if (null != n.get(1)) { printer.p(", ..."); } } /** Visit the specified parameter list node. */ public void visitParameterList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified parameter declaration node. */ public void visitParameterDeclaration(GNode n) { printer.p(n.getNode(0)); if (null != n.get(1)) { printer.p(' ').p(n.getNode(1)); } if (null != n.get(2)) { printer.p(' ').p(n.getNode(2)); } } /** Visit the specified attributed abstract declarator node. */ public void visitAttributedAbstractDeclarator(GNode n) { if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getNode(1)); } /** Visit the specified abstract declarator node. */ public void visitAbstractDeclarator(GNode n) { printer.p(n.getNode(0)).p(n.getNode(1)); } /** Visit the specified direct abstract declarator node. */ public void visitDirectAbstractDeclarator(GNode n) { if (null != n.get(0)) { printer.p('(').p(n.getNode(0)).p(')'); } if ("[".equals(n.get(1))) { printer.p('['); if (null != n.get(2)) { int prec = enterContext(PREC_LIST); printer.p(n.getNode(2)); exitContext(prec); } printer.p(']'); } else { printer.p('(').p(n.getNode(2)).p(')'); } } /** Visit the specified identifier list node. */ public void visitIdentifierList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p(Token.cast(iter.next())); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified array declarator node. */ public void visitArrayDeclarator(GNode n) { if (n.getGeneric(0).hasName("SimpleDeclarator")) { printer.p(n.getNode(0)); } else { printer.p('(').p(n.getNode(0)).p(')'); } printer.p('['); int column = printer.column(); printer.p(n.getNode(1)); if (null != n.get(2)) { if (printer.column() != column) printer.p(' '); int prec = enterContext(PREC_LIST); printer.p(n.getNode(2)); exitContext(prec); } printer.p(']'); } /** Visit the specified variable length node. */ public void visitVariableLength(GNode n) { printer.p('*'); } /** Visit the specified array qualifier list node. */ public void visitArrayQualifierList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(' '); } } } /** Visit the specified complex node. */ public void visitComplex(GNode n) { printer.p(n.getString(0)); } /** Visit the specified double node. */ public void visitDouble(GNode n) { printer.p("double"); } /** Visit the specified float node. */ public void visitFloat(GNode n) { printer.p("float"); } /** Visit the specified long node. */ public void visitLong(GNode n) { printer.p("long"); } /** Visit the specified int node. */ public void visitInt(GNode n) { printer.p("int"); } /** Visit the specified short node. */ public void visitShort(GNode n) { printer.p("short"); } /** Visit the specified char node. */ public void visitChar(GNode n) { printer.p("char"); } /** Visit the specified bool node. */ public void visitBool(GNode n) { printer.p("_Bool"); } /** Visit the specified unsigned node. */ public void visitUnsigned(GNode n) { printer.p("unsigned"); } /** Visit the specified signed node. */ public void visitSigned(GNode n) { printer.p(n.getString(0)); } /** Visit the specified typedef name node. */ public void visitTypedefName(GNode n) { printer.p(n.getString(0)); } /** Visit the specified typeof specifier node. */ public void visitTypeofSpecifier(GNode n) { int prec = enterContext(PREC_BASE); printer.p("typeof(").p(n.getNode(0)).p(')'); exitContext(prec); } /** Visit the specified void type specifier node. */ public void visitVoidTypeSpecifier(GNode n) { printer.p("void"); } /** Visit the specified variable argument list specifier node. */ public void visitVarArgListSpecifier(GNode n) { printer.p("__builtin_va_list"); } /** Visit the specified initialized declarator list node. */ public void visitInitializedDeclaratorList(GNode n) { boolean first = true; for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { if (first) { first = false; } else { printer.buffer(); } printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(", ").fitMore(); } } } /** Visit the specified initialized declarator node. */ public void visitInitializedDeclarator(GNode n) { if (null != n.get(0)) { printer.p(n.getNode(0)).p(' '); } printer.p(n.getNode(1)); if (null != n.get(2)) { printer.p(' ').p(n.getNode(2)); } if (null != n.get(3)) { printer.p(' ').p(n.getNode(3)); } if (null != n.get(4)) { printer.p(" = "); int prec = enterContext(PREC_LIST); printer.p(n.getNode(4)); exitContext(prec); } } /** Visit the specified initializer list node. */ public void visitInitializerList(GNode n) { if (! n.isEmpty()) { printer.pln('{').incr().indent(); for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.buffer().p((Node)iter.next()); if (iter.hasNext()) { printer.p(", "); } printer.fit(); } printer.pln().decr().indent().p('}'); isLongDecl = true; } else { printer.p("{ }"); } } /** Visit the specified initializer list entry node. */ public void visitInitializerListEntry(GNode n) { printer.p(n.getNode(0)); int prec = enterContext(PREC_LIST); printer.p(n.getNode(1)); exitContext(prec); } /** Visit the specified designation node. */ public void visitDesignation(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(' '); } } printer.p(" = "); } /** Visit the specified obsolete array designation node. */ public void visitObsoleteArrayDesignation(GNode n) { // Print the obsolete array designation as a standard array // designation. int prec = enterContext(PREC_CONSTANT); printer.p('[').p(n.getNode(1)); if (3 == n.size() && null != n.getGeneric(2)) { printer.p(" ... ").p(n.getNode(2)); } printer.p(']'); exitContext(prec); printer.p(" = "); } /** Visit the specified obsolete field designation node. */ public void visitObsoleteFieldDesignation(GNode n) { // Print the obsolete field designation as a standard field // designation. printer.p('.').p(n.getString(0)).p(" = "); } /** Visit the specified designator entry node. */ public void visitDesignator(GNode n) { if ("[".equals(n.get(0))) { int prec = enterContext(PREC_CONSTANT); printer.p('[').p(n.getNode(1)); if (3 == n.size()) { printer.p(" ... ").p(n.getNode(2)); } printer.p(']'); exitContext(prec); } else { printer.p('.').p(n.getNode(1)); } } /** Visit the specified type name node. */ public void visitTypeName(GNode n) { printer.p(n.getNode(0)); if (null != n.get(1)) { printer.p(' ').p(n.getNode(1)); } } /** Visit the specified attribute specifier list node. */ public void visitAttributeSpecifierList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(' '); } } } /** Visit the specified attribute specifier node. */ public void visitAttributeSpecifier(GNode n) { printer.p("__attribute__((").p(n.getNode(0)).p("))"); } /** Visit the specified attribute list node. */ public void visitAttributeList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified attribute list entry node. */ public void visitAttributeListEntry(GNode n) { printer.p(n.getString(0)); if (null != n.get(1)) { printer.p('(').p(n.getNode(1)).p(')'); } } /** Visit the specified labeled statement node. */ public void visitLabeledStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indentLess().p(n.getNode(0)).pln(); isDeclaration = false; isStatement = true; printer.p(n.getNode(1)); endStatement(nested); } /** Visit the specified named label node. */ public void visitNamedLabel(GNode n) { printer.p(n.getString(0)); if (null == n.get(1)) { printer.p(':'); } else { printer.p(": ").p(n.getNode(1)); } } /** Visit the specified case label node. */ public void visitCaseLabel(GNode n) { int prec = enterContext(PREC_CONSTANT); printer.p("case ").p(n.getNode(0)); if (2 == n.size()) { printer.p(" ... ").p(n.getNode(1)); } printer.p(':'); exitContext(prec); } /** Visit the specified default label node. */ public void visitDefaultLabel(GNode n) { printer.p("default:"); } /** Visit the specified compound statement node. */ public void visitCompoundStatement(GNode n) { boolean stmtAsExpr = isStmtAsExpr; isStmtAsExpr = false; boolean nested = isNested; if (stmtAsExpr) { printer.pln(" ({").incr(); } else if (nested && gnuify) { printer.pln().incr().indent().pln('{').incr(); } else if (isOpenLine) { printer.pln(" {").incr(); } else { printer.indent().pln('{').incr(); } isOpenLine = false; isNested = false; isIfElse = false; for (Object o : n) printer.p((Node)o); if (isOpenLine) { printer.pln(); } if (stmtAsExpr) { printer.decr().indent().p("})"); isOpenLine = true; } else if (nested && gnuify) { printer.decr().indent().pln('}').decr(); isOpenLine = false; } else { printer.decr().indent().p('}'); isOpenLine = true; } isNested = false; isIfElse = false; isStmtAsExpr = stmtAsExpr; } /** Visit the specified label declaration node. */ public void visitLocalLabelDeclaration(GNode n) { if (! isNested) { if (lineUp) { if (isOpenLine) printer.pln(); printer.lineUp(n); } else if (isStatement || isLongDecl) { if (isOpenLine) printer.pln(); printer.pln(); } else if (isLongDeclaration(n)) { printer.pln(); } printer.indent(); } printer.p("__label__ "); for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p(Token.cast(iter.next())); if (iter.hasNext()) { printer.p(", "); } } printer.pln(';'); isDeclaration = true; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; } /** Visit the specified if else statement node. */ public void visitIfElseStatement(GNode n) { boolean nested = startStatement(STMT_IF_ELSE, n); if (isIfElse) { printer.p(' '); } else { printer.indent(); } printer.p("if ("); formatAsTruthValue(n.getNode(0)); printer.p(')'); prepareNested(); printer.p(n.getNode(1)); if (isOpenLine) { printer.p(" else"); } else { printer.indent().p("else"); } prepareNested(); boolean ifElse = isIfElse; isIfElse = true; printer.p(n.getNode(2)); isIfElse = ifElse; endStatement(nested); } /** Visit the specified if statement node. */ public void visitIfStatement(GNode n) { boolean nested = startStatement(STMT_IF, n); if (isIfElse) { printer.p(' '); } else { printer.indent(); } printer.p("if ("); formatAsTruthValue(n.getNode(0)); printer.p(')'); prepareNested(); printer.p(n.getNode(1)); endStatement(nested); } /** Visit the specified while statement node. */ public void visitWhileStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("while ("); formatAsTruthValue(n.getNode(0)); printer.p(')'); prepareNested(); printer.p(n.getNode(1)); endStatement(nested); } /** Visit the specified do statement node. */ public void visitDoStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("do"); prepareNested(); printer.p(n.getNode(0)); if (isOpenLine) { printer.p(' '); } else { printer.indent(); } printer.p("while ("); formatAsTruthValue(n.getNode(1)); printer.pln(");"); endStatement(nested); } /** Visit the specified for statement node. */ public void visitForStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("for ("); if (null != n.get(0)) { int prec = enterContext(PREC_BASE); printer.p(n.getNode(0)); exitContext(prec); } printer.p(';'); if (null != n.get(1)) { int prec = enterContext(PREC_BASE); printer.p(' '); formatAsTruthValue(n.getNode(1)); exitContext(prec); } printer.p(';'); if (null != n.get(2)) { int prec = enterContext(PREC_BASE); printer.p(' ').p(n.getNode(2)); exitContext(prec); } printer.p(')'); prepareNested(); printer.p(n.getNode(3)); endStatement(nested); } /** Visit the specified switch statement node. */ public void visitSwitchStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("switch (").p(n.getNode(0)).p(')'); prepareNested(); printer.p(n.getNode(1)); endStatement(nested); } /** Visit the specified break statement node. */ public void visitBreakStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().pln("break;"); endStatement(nested); } /** Visit the specified continue statement node. */ public void visitContinueStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().pln("continue;"); endStatement(nested); } /** Visit the specified return statement node. */ public void visitReturnStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("return"); if (null != n.getNode(0)) { printer.p(' ').p(n.getNode(0)); } printer.pln(';'); endStatement(nested); } /** Visit the specified goto statement node. */ public void visitGotoStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("goto "); if (null == n.get(0)) { printer.p(n.getNode(1)); } else { printer.p('*'); int prec = enterContext(150); printer.p(n.getNode(1)); exitContext(prec); } printer.pln(';'); endStatement(nested); } /** Visit the specified expression statement node. */ public void visitExpressionStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p(n.getNode(0)).pln(';'); endStatement(nested); } /** Visit the specified empty statement node. */ public void visitEmptyStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().pln(';'); endStatement(nested); } /** Visit the specified comma expression node. */ public void visitCommaExpression(GNode n) { int prec1 = startExpression(10); printer.p(n.getNode(0)).p(", "); int prec2 = enterContext(); printer.p(n.getNode(1)); exitContext(prec2); endExpression(prec1); } /** Visit the specified assignment expression node. */ public void visitAssignmentExpression(GNode n) { int prec1 = startExpression(20); int prec2 = enterContext(); printer.p(n.getNode(0)); exitContext(prec2); printer.p(' ').p(n.getString(1)).p(' ').p(n.getNode(2)); endExpression(prec1); } /** Visit the specified conditional expression node. */ public void visitConditionalExpression(GNode n) { int prec1 = startExpression(30); int prec2 = enterContext(); printer.p(n.getNode(0)).p(" ? "); exitContext(prec2); prec2 = enterContext(); if (null != n.get(1)) { printer.p(n.getNode(1)).p(" : "); } else { printer.p(" /* Empty */ : "); } exitContext(prec2); printer.p(n.getNode(2)); endExpression(prec1); } /** Visit the specified logical or expression node. */ public void visitLogicalOrExpression(GNode n) { int prec1 = startExpression(40); boolean paren1 = n.getGeneric(0).hasName("LogicalAndExpression"); boolean paren2 = n.getGeneric(1).hasName("LogicalAndExpression"); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(" || "); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(1)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(1)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified logical and expression node. */ public void visitLogicalAndExpression(GNode n) { int prec1 = startExpression(50); printer.p(n.getNode(0)).p(" && "); int prec2 = enterContext(); printer.p(n.getNode(1)); exitContext(prec2); endExpression(prec1); } /** Visit the specified bitwise or expression node. */ public void visitBitwiseOrExpression(GNode n) { int prec1 = startExpression(60); GNode op1 = n.getGeneric(0); boolean paren1 = (op1.hasName("AdditiveExpression") || op1.hasName("BitwiseAndExpression") || op1.hasName("BitwiseXorExpression") || op1.hasName("RelationalExpression") || op1.hasName("EqualityExpression")); GNode op2 = n.getGeneric(1); boolean paren2 = (op2.hasName("AdditiveExpression") || op2.hasName("BitwiseAndExpression") || op2.hasName("BitwiseXorExpression") || op2.hasName("RelationalExpression") || op2.hasName("EqualityExpression")); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(" | "); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(1)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(1)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified bitwise xor expression node. */ public void visitBitwiseXorExpression(GNode n) { int prec1 = startExpression(70); GNode op1 = n.getGeneric(0); boolean paren1 = (op1.hasName("AdditiveExpression") || op1.hasName("BitwiseAndExpression") || op1.hasName("RelationalExpression") || op1.hasName("EqualityExpression")); GNode op2 = n.getGeneric(1); boolean paren2 = (op2.hasName("AdditiveExpression") || op2.hasName("BitwiseAndExpression") || op2.hasName("RelationalExpression") || op2.hasName("EqualityExpression")); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(" ^ "); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(1)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(1)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified bitwise and expression node. */ public void visitBitwiseAndExpression(GNode n) { int prec1 = startExpression(80); GNode op1 = n.getGeneric(0); boolean paren1 = (op1.hasName("AdditiveExpression") || op1.hasName("RelationalExpression") || op1.hasName("EqualityExpression")); GNode op2 = n.getGeneric(1); boolean paren2 = (op2.hasName("AdditiveExpression") || op2.hasName("RelationalExpression") || op2.hasName("EqualityExpression")); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(" & "); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(1)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(1)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified equality expression node. */ public void visitEqualityExpression(GNode n) { int prec1 = startExpression(90); GNode op1 = n.getGeneric(0); boolean paren1 = (op1.hasName("RelationalExpression") || op1.hasName("EqualityExpression")); GNode op2 = n.getGeneric(2); boolean paren2 = (op2.hasName("RelationalExpression") || op2.hasName("EqualityExpression")); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(' ').p(n.getString(1)).p(' '); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(2)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(2)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified relational expression node. */ public void visitRelationalExpression(GNode n) { int prec1 = startExpression(100); GNode op1 = n.getGeneric(0); boolean paren1 = (op1.hasName("RelationalExpression") || op1.hasName("EqualityExpression")); GNode op2 = n.getGeneric(2); boolean paren2 = (op2.hasName("RelationalExpression") || op2.hasName("EqualityExpression")); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(' ').p(n.getString(1)).p(' '); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(2)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(2)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified shift expression node. */ public void visitShiftExpression(GNode n) { int prec1 = startExpression(110); boolean paren1 = n.getGeneric(0).hasName("AdditiveExpression"); boolean paren2 = n.getGeneric(2).hasName("AdditiveExpression"); if (EXTRA_PARENTHESES && paren1) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(0)).p(')'); } else { printer.p(n.getNode(0)); } printer.p(' ').p(n.getString(1)).p(' '); if (EXTRA_PARENTHESES && paren2) { // Force parentheses to make gcc happy. printer.p('(').p(n.getNode(2)).p(')'); } else { int prec2 = enterContext(); printer.p(n.getNode(2)); exitContext(prec2); } endExpression(prec1); } /** Visit the specified additive expression node. */ public void visitAdditiveExpression(GNode n) { int prec1 = startExpression(120); printer.p(n.getNode(0)).p(' ').p(n.getString(1)).p(' '); int prec2 = enterContext(); printer.p(n.getNode(2)); exitContext(prec2); endExpression(prec1); } /** Visit the specified multiplicative expression node. */ public void visitMultiplicativeExpression(GNode n) { int prec1 = startExpression(130); printer.p(n.getNode(0)).p(' ').p(n.getString(1)).p(' '); int prec2 = enterContext(); printer.p(n.getNode(2)); exitContext(prec2); endExpression(prec1); } /** Visit the specified cast expression node. */ public void visitCastExpression(GNode n) { int prec = startExpression(140); printer.p('(').p(n.getNode(0)).p(')').p(n.getNode(1)); endExpression(prec); } /** Visit the specified sizeof expression node. */ public void visitSizeofExpression(GNode n) { int prec = startExpression(150); int prec2 = enterContext(PREC_BASE); printer.p("sizeof(").p(n.getNode(0)).p(')'); exitContext(prec2); endExpression(prec); } /** Visit the specified alignof expression node. */ public void visitAlignofExpression(GNode n) { int prec = startExpression(150); int prec2 = enterContext(PREC_BASE); printer.p("__alignof__(").p(n.getNode(0)).p(')'); exitContext(prec2); endExpression(prec); } /** Visit the specified offsetof expression node. */ public void visitOffsetofExpression(GNode n) { int prec = startExpression(160); printer.p("__builtin_offsetof(").p(n.getNode(0)).p(", ").p(n.getNode(1)). p(')'); endExpression(prec); } /** Visit the specified type compatability expression. */ public void visitTypeCompatibilityExpression(GNode n) { int prec = startExpression(150); printer.p("__builtin_types_compatible_p("); int prec2 = enterContext(PREC_BASE); printer.p(n.getNode(0)); exitContext(prec2); prec2 = enterContext(PREC_BASE); printer.p(", ").p(n.getNode(1)).p(')'); exitContext(prec2); endExpression(prec); } /** Visit the specified unary minus expression node. */ public void visitUnaryMinusExpression(GNode n) { int prec = startExpression(150); GNode e = n.getGeneric(0); if (e.hasName("UnaryMinusExpression") || e.hasName("PredecrementExpression")) { printer.p("-(").p(n.getNode(0)).p(')'); } else { printer.p('-').p(n.getNode(0)); } endExpression(prec); } /** Visit the specified unary plus expression node. */ public void visitUnaryPlusExpression(GNode n) { int prec = startExpression(150); GNode e = n.getGeneric(0); if (e.hasName("UnaryPlusExpression") || e.hasName("PreincrementExpression")) { printer.p("+(").p(n.getNode(0)).p(')'); } else { printer.p('+').p(n.getNode(0)); } endExpression(prec); } /** Visit the specified logical negation expression node. */ public void visitLogicalNegationExpression(GNode n) { int prec = startExpression(150); printer.p('!').p(n.getNode(0)); endExpression(prec); } /** Visit the specified bitwise negation expression node. */ public void visitBitwiseNegationExpression(GNode n) { int prec = startExpression(150); printer.p('~').p(n.getNode(0)); endExpression(prec); } /** Visit the specified address expression node. */ public void visitAddressExpression(GNode n) { int prec = startExpression(150); GNode e = n.getGeneric(0); if (e.hasName("AddressExpression") || e.hasName("LabelAddressExpression")) { printer.p("&(").p(n.getNode(0)).p(')'); } else { printer.p('&').p(n.getNode(0)); } endExpression(prec); } /** Visit the specified label address expression node. */ public void visitLabelAddressExpression(GNode n) { int prec = startExpression(150); printer.p("&&").p(n.getString(0)); endExpression(prec); } /** Visit the specified indirection expression node. */ public void visitIndirectionExpression(GNode n) { int prec = startExpression(150); printer.p('*').p(n.getNode(0)); endExpression(prec); } /** Visit the specified preincrement expression node. */ public void visitPreincrementExpression(GNode n) { int prec = startExpression(150); printer.p("++").p(n.getNode(0)); endExpression(prec); } /** Visit the specified predecrement expression node. */ public void visitPredecrementExpression(GNode n) { int prec = startExpression(150); printer.p("--").p(n.getNode(0)); endExpression(prec); } /** Visit the extension expression node. */ public void visitExtensionExpression(GNode n) { int prec = startExpression(150); printer.p("__extension__ ").p(n.getNode(0)); endExpression(prec); } /** Visit the specified subscript expression node. */ public void visitSubscriptExpression(GNode n) { int prec1 = startExpression(160); printer.p(n.getNode(0)); int prec2 = enterContext(PREC_BASE); printer.p('[').p(n.getNode(1)).p(']'); exitContext(prec2); endExpression(prec1); } /** Visit the specified direct component selection node. */ public void visitDirectComponentSelection(GNode n) { int prec = startExpression(160); printer.p(n.getNode(0)).p('.').p(n.getString(1)); endExpression(prec); } /** Visit the specified indirect component selection node. */ public void visitIndirectComponentSelection(GNode n) { int prec = startExpression(160); printer.p(n.getNode(0)).p("->").p(n.getString(1)); endExpression(prec); } /** Visit the specified function call node. */ public void visitFunctionCall(GNode n) { int prec = startExpression(160); printer.p(n.getNode(0)).p('(').p(n.getNode(1)).p(')'); endExpression(prec); } /** Visit the specified expression list node. */ public void visitExpressionList(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { int prec = enterContext(PREC_LIST); printer.p((Node)iter.next()); exitContext(prec); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified postincrement expression node. */ public void visitPostincrementExpression(GNode n) { int prec = startExpression(160); printer.p(n.getNode(0)).p("++"); endExpression(prec); } /** Visit the specified postdecrement expression node. */ public void visitPostdecrementExpression(GNode n) { int prec = startExpression(160); printer.p(n.getNode(0)).p("--"); endExpression(prec); } /** Visit the specified compound literal node. */ public void visitCompoundLiteral(GNode n) { int prec = startExpression(160); printer.p('(').p(n.getNode(0)).p(") ").p(n.getNode(1)); endExpression(prec); } /** Visit the specified primary identifier node. */ public void visitPrimaryIdentifier(GNode n) { int prec = startExpression(160); printer.p(n.getString(0)); endExpression(prec); } /** Visit the specified statement as exprression node. */ public void visitStatementAsExpression(GNode n) { int prec = enterContext(PREC_BASE); boolean stmtAsExpr = isStmtAsExpr; isStmtAsExpr = true; prepareNested(); printer.p(n.getNode(0)); isStmtAsExpr = stmtAsExpr; exitContext(prec); } /** Visit the specified variable argument access node. */ public void visitVariableArgumentAccess(GNode n) { int prec = startExpression(160); printer.p("__builtin_va_arg("); int prec2 = enterContext(PREC_LIST); printer.p(n.getNode(0)); exitContext(prec2); printer.p(", ").p(n.getNode(1)).p(')'); endExpression(prec); } /** Visit the specified assembly definition node. */ public void visitAssemblyDefinition(GNode n) { if (lineUp) { if (isOpenLine) printer.pln(); printer.lineUp(n); } else if (isStatement || isDeclaration || isLongDecl) { if (isOpenLine) printer.pln(); printer.pln(); } printer.p(n.getNode(0)).pln(';'); isDeclaration = false; isLongDecl = false; isStatement = false; isOpenLine = false; isNested = false; isIfElse = false; } /** Visit the specified simple assembly expression node. */ public void visitSimpleAssemblyExpression(GNode n) { int prec = enterContext(PREC_BASE); printer.p("asm(").p(n.getNode(0)).p(')'); exitContext(prec); } /** Visit the specified assembly statement node. */ public void visitAssemblyStatement(GNode n) { boolean nested = startStatement(STMT_ANY, n); printer.indent().p("asm "); if (null != n.getNode(0)) { printer.p(n.getNode(0)).p(' '); } printer.p('(').p(n.getNode(1)).pln(");"); endStatement(nested); } /** Visit the specified assembly argument node. */ public void visitAssemblyArgument(GNode n) { final int prec = enterContext(PREC_BASE); final int number = n.size(); final int align = printer.column(); printer.p(n.getNode(0)); if (number >= 2) { if (null == n.get(1)) { printer.pln().align(align).p(": /* No output operands */"); } else { printer.pln().align(align).p(": ").p(n.getNode(1)); } if (number >= 3) { if (null == n.get(2)) { printer.pln().align(align).p(": /* No input operands */"); } else { printer.pln().align(align).p(": ").p(n.getNode(2)); } if (number == 4) { printer.pln().align(align).p(": ").p(n.getNode(3)); } } } exitContext(prec); } /** Visit the specified assembly operands node. */ public void visitAssemblyOperands(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified assembly operand node. */ public void visitAssemblyOperand(GNode n) { if (null != n.get(0)) { printer.p('[').p(n.getString(0)).p("] "); } printer.p(n.getNode(1)).p(" (").p(n.getNode(2)).p(')'); } /** Visit the specified assembly clobbers node. */ public void visitAssemblyClobbers(GNode n) { for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p((Node)iter.next()); if (iter.hasNext()) { printer.p(", "); } } } /** Visit the specified floating constant node. */ public void visitFloatingConstant(GNode n) { int prec = startExpression(160); printer.p(n.getString(0)); endExpression(prec); } /** Visit the specified integer constant node. */ public void visitIntegerConstant(GNode n) { int prec = startExpression(160); printer.p(n.getString(0)); endExpression(prec); } /** Visit the specified character constant node. */ public void visitCharacterConstant(GNode n) { int prec = startExpression(160); printer.p(n.getString(0)); endExpression(prec); } /** Visit the specified string constant node. */ public void visitStringConstant(GNode n) { int prec = startExpression(160); if (1 == n.size()) { printer.p(n.getString(0)); } else { int align = printer.column(); for (Iterator<?> iter = n.iterator(); iter.hasNext(); ) { printer.p(Token.cast(iter.next())); if (iter.hasNext()) { printer.pln().align(align); } } } endExpression(prec); } /** Visit the specified line marker. */ public void visit(LineMarker mark) { if (isOpenLine) { isOpenLine = false; printer.pln(); } if (lineUp) printer.lineUp(mark); printer.p("# ").p(mark.line).p(" \"").p(mark.file).p('\"'); if (0 != (mark.flags & LineMarker.FLAG_START_FILE)) { printer.p(" 1"); } if (0 != (mark.flags & LineMarker.FLAG_RETURN_TO_FILE)) { printer.p(" 2"); } if (0 != (mark.flags & LineMarker.FLAG_SYSTEM_HEADER)) { printer.p(" 3"); } if (0 != (mark.flags & LineMarker.FLAG_EXTERN_C)) { printer.p(" 4"); } printer.pln().p(mark.getNode()); } /** Visit the specified pragma. */ public void visit(Pragma p) { if (isOpenLine) { isOpenLine = false; printer.pln(); } if (lineUp) printer.lineUp(p); printer.p("#pragma ").pln(p.directive).p(p.getNode()); } /** Visit the specified source identity marker. */ public void visit(SourceIdentity ident) { if (isOpenLine) { isOpenLine = false; printer.pln(); } if (lineUp) printer.lineUp(ident); printer.p("#ident \"").p(ident.ident).pln('"').p(ident.getNode()); } }