\section{C-Language Printing}

Class [[CPrinter]] is analogous to [[Printer]] (Section~\ref{sec:printer}),
but its role is to help generate C-language, rather than assembly-language,
output files.  The structure and many of the methods of [[CPrinter]] are
the same as those of [[Printer]].

\subsection{Class [[CPrinter]]}
\label{sec:c-printer}

\paragraph{Interface.}

Though [[CPrinter]] is abstract, it has fewer methods with no default
definition than class [[Printer]], since the output language is fixed.

<<class [[CPrinter]]>>=
class CPrinter {
  public:
    virtual ~CPrinter();

    void clear();
    FILE *get_file_ptr() { return out; }
    void set_file_ptr(FILE *the_file_ptr) { out = the_file_ptr; }

    bool get_omit_unwanted_notes() const { return !omit_unwanted_notes; }
    void set_omit_unwanted_notes(bool omit) { omit_unwanted_notes = omit; }

    virtual void print_notes(FileBlock*);
    virtual void print_notes(Instr*);

    virtual void print_instr(Instr *mi) = 0;
    virtual void print_opnd(Opnd o);
    virtual void print_type(TypeId t);

    virtual void print_sym(Sym *s);
    virtual void print_sym_decl(Sym *s);
    virtual void print_sym_decl(char *s, TypeId t);
    virtual void print_var_def(VarSym *v, bool no_init);

    virtual void print_global_decl(FileBlock *fb) = 0;
    virtual void print_proc_decl(ProcSym *p);
    virtual void print_proc_begin(ProcDef *pd);

<<[[CPrinter]] protected part>>
};
@

Notes on the public methods:

\begin{itemize}
\item [[get_file_ptr]] and [[set_file_ptr]] fetch and store the
      output stream ([[FILE*]]) for the C file being generated.
\item [[get_omit_unwanted_notes]] and [[set_omit_unwanted_notes]]  control
      whether annotation printing is selective.  Normally, annotations on
      instructions are printed as comments in the output C file, but those
      whose keys are in the set [[nonprinting_notes]] are skipped.  By
      calling [[set_omit_unwanted_notes]] with argument [[false]], 
      you turn off selective printing, so that all annotations appear.
\item [[print_notes]] prints the annotations on the object to which it it
      applied.
\item [[print_instr]] and [[print_opnd]] are called to print each
      instruction and each operand, respectively.
\item [[print_type]] prints a C type.  It keeps track of [[struct]],
      [[union]], and [[enum]] types that have already been printed and
      abbreviates them to avoid illegal duplication.
\item [[print_sym]] prints a symbol.
\item [[print_sym_decl]] prints the declarator for a symbol, which includes
      its name and type, but no terminating punctuation.  It is used for
      formal parameters as well as global and local declarations.
\item [[print_var_def]] prints the defining declaration of a variable
      symbol.  If the variable has an initializer and the second argument
      [[no_init]] is not true, the initializer is included in the printed
      definition.
\item [[print_global_decl]], like the corresponding method of class
      [[Printer]], is a hook for printing things at the start of the output
      file.  If the C output file needs a special [[#include]] directive,
      it can be printed by this method.
\item [[print_proc_decl]] prints the declaration of a procedure, including
      a terminating semi-colon and end-of-line string.
\item [[print_proc_begin]] prints the header of a procedure definition,
      including the opening brace of its body.
\end{itemize}


\paragraph{Specialization.}

Like a [[Printer]] object, an instance of [[CPrinter]] contains a dispatch
table that maps from an opcode to a virtual method for printing an
instruction that has the opcode.  This table, called [[print_instr_table]],
is initialized when the target-specific library creates an instance of its
own subclass of [[CPrinter]].  The methods [[print_instr_alm]],
[[print_instr_cti]], [[print_instr_dot]], [[print_instr_label]], and
[[print_instr_user_defd]] are used for C-language printing in a manner
that's analogous to assembly-language printing.  The main difference is
that [[print_instr_label]] has a definition, since label printing in C is
pretty standard.

The remaining protected methods are helpers that are exposed to the
target-library writer in case some aspect of the target requires special
treatment when translating to C.

\begin{itemize}
\item [[print_annote]] method prints a SUIF [[Annote]] object, which is
      expected to be a [[BrickAnnote]]. 
\item [[print_immed]] prints an immediate operand.
\item [[print_addr]] prints an address expression.  Its second argument, if
      non-zero, is the desired referent type; the method applies a cast if
      necessary to achieve it.  The third argument is a syntactic context
      indicator that helps to control parenthesization.
\item [[print_value_block]] is a recursive helper for [[print_var_def]]
      that prints the initializer part of a variable definition.
\item [[print_decl]] is a recursive helper for printing a declarator in C's
      distinctive syntax.  The structure of the declarator is described in
      the second argument, which may include a symbolic identifier or may
      leave it out, for printing types.
\item [[print_pointer_cast]] prints a cast to the pointer type that has the
      argument type as its referent.
\item [[print_type_ref]] prints an abbreviated compond type, on the
      assumption that the full definition of the type has already been seen
      by the C compiler.  The second argument is one of the keywords
      [[struct]], [[union]], or [[enum]].
\item [[print_group_def]] prints the full definition of a [[struct]] or
      [[union]] type.
\item [[print_enum_def]] prints the full definition of an [[enum]] type.
\item [[print_atomic_type]] prints a non-compound type.
\item [[print_string_literal]] prints a string literal suitably quoted and
      with interior escapes for input to a C compiler.
\end{itemize}

<<[[CPrinter]] protected part>>=
  protected:
    // table of instr printing functions -- filled in by derived class
    typedef void (CPrinter::*print_instr_f)(Instr*);
    print_instr_f *print_instr_table;

    // instr printing functions that populate the print_instr_table
    virtual void print_instr_alm(Instr*) = 0;
    virtual void print_instr_cti(Instr*) = 0;
    virtual void print_instr_dot(Instr*) = 0;
    virtual void print_instr_label(Instr*);

    virtual void print_instr_user_defd(Instr*) = 0;

    // helper methods

    virtual void print_annote(Annote*);

    virtual void print_immed(Opnd);
    virtual void print_addr(Opnd, TypeId goal = 0, int context = ANY);
    virtual void print_addr_disp(Opnd addr, Opnd disp, TypeId goal,
				 int context, char *op);

    virtual bool process_value_block(ValueBlock*, TypeId);

    virtual void print_decl(TypeId, const Declarator&);
    virtual void print_pointer_cast(TypeId referent);
    virtual bool print_type_ref(TypeId, const char *keyword);
    virtual void print_group_def(TypeId);
    virtual void print_enum_def (TypeId);
    virtual void print_atomic_type(TypeId);

    virtual void print_string_literal(IdString literal);

    CPrinter();

    FILE *out;
    bool omit_unwanted_notes;

    List<TypeId> noted_types;
    int next_type_tag;

    // syntactic contexts
    enum { ANY, ASSIGN, BINARY, UNARY, PRIMARY };
@

\paragraph{The [[CPrinter]] object for the current target.}

To access the [[CPrinter]] object in the prevailing context, call this
function:

<<function [[target_c_printer]]>>=
CPrinter* target_c_printer();
@


\subsection{Header file for module [[CPrinter.h]]}

The interface file has the following layout:

<<c\_printer.h>>=
/* file "machine/c_printer.h" */

<<Machine-SUIF copyright>>

#ifndef MACHINE_CPRINTER_H
#define MACHINE_CPRINTER_H

#include <machine/copyright.h>

#ifndef SUPPRESS_PRAGMA_INTERFACE
#pragma interface "machine/cprinter.h"
#endif

#include <machine/substrate.h>
#include <machine/machine_ir.h>

class Declarator;

<<class [[CPrinter]]>>

<<function [[target_c_printer]]>>

#endif /* MACHINE_CPRINTER_H */
@
