% This is a file written using noweb
%
% $Id: asciioutput.nw,v 1.1 1996/03/13 11:30:06 gaertner Exp $
%

\documentclass{article}
\usepackage{a4,pretzeldoc,version,noweb}
\begin{document}

\includeversion{bigspecs}
\includeversion{impls}
%\excludeversion{bigspecs}% without elaborate specification
%\excludeversion{impls}% without implementation



\title{[[Ascii_terminal_output]]\thanks{This file is based on a
    template for a subclass of the [[Output]] class written by Felix
    G\"artner.} \\ An [[Output]] Subclass for Screen or Line Printer}

\author{Felix G\"artner}            % put your own name here

\maketitle


\begin{abstract}
  % fill in the abstract at the places marked XXX or write your own

  This file contains a subclass of the [[Output]] class called
  [[Ascii_terminal_output]]. It can be used to create a prettyprinter
  for a normal terminal screen. It belongs to a framework supplied by the
  ``pretzel'' prettyprinter generator.

\end{abstract}


\tableofcontents


% Fill in the places marked XXX or write your own text.

\section{Introduction}

This text describes the specification \begin{impls}and
  implementation\end{impls} for a new subclass of the \CPP\ [[Output]]
class. It specializes on a simple ASCII terminal or line printer
output device. It is a contribution to the ``pretzel'' system, a
prettyprinter generator written by Felix G\"artner
(\verb+theedge@rbg.informatik.th-darmstadt.de+).

For more examples of this kind of thing consult the files {\tt
  output.nw} and {\tt blankoutput.nw} included in the pretzel
distribution.

@ Here's the frame of the header for the new subclass.

<<header>>=
#ifndef ASCIIOUTPUT_H
#define ASCIIOUTPUT_H

#include "output.h"          /* base class defined in here */

<<Macro definitions in the specification>>

<<Declaration of the new subclass>>

#endif
@

\begin{impls}

Here's the framework of the implementation.

<<implementation>>=
#include "asciioutput.h"
<<Header files to include in the implementation>>

<<Macro definitions in the implementation>>

<<Static variables in the implementation>>

<<Implementation of the new subclass>>

@

\end{impls}

In the following section of this document we will explain the purpose
of this subclass and the results obtained when using it together with
pretzel. This is the interface of the class. \begin{impls}In the
  following section we will focus on the details of the implementation
  of the new subclass.\end{impls}

First of all, this is what the name of the subclass will look like in
the program:

<<Macro definitions in the specification>>=
#define Ascii_terminal_output_SUBCLASS_NAME Ascii_terminal_output
@


\section{Interface and Use}

A terminal or simple line printer is pretty dumb and naturally cannot
compete with such advanced typesetting systems like \TeX. But
sometimes prettyprinted output to a screen or an ASCII line printer is
required. This class implements this kind of stuff.

To actually build a prettyprinter of this kind you'll have to extract
a header and implementation file from this text, include it in the
prettyprinter specification and specify this subclass as argument to
the actual prettyprinter object.

[Example missing]

@ The actual declaration of the new subclass is pretty simple, once
we've defined the name.

<<Declaration of the new subclass>>=
class Ascii_terminal_output_SUBCLASS_NAME : public Output {
public:
    Ascii_terminal_output_SUBCLASS_NAME(ostream& ostr) : Output(ostr) {};
    ~Ascii_terminal_output_SUBCLASS_NAME() { flush_output(); };
private:
    void flush_output();
};

@ Yes, it`s as simple as that. The only thing needed to do now is
think about the actions that have to be done when interpreting format
commands and implement them within the [[flush_output]] routine, which
is a pure virtual function inside the [[Output]] base class. The main
parts of this routine are always identical. The only differences are
the different things done when format commands are interpreted.


\subsection{Aspects of ASCII Terminal Output}

We'll keep the ideas implemented here simple. The format commands that
will be implemented will be
 %
\begin{itemize}
\item [[indent]], [[outdent]]
\item [[force]], [[big_force]]
\end{itemize}
 %
This means that no line breaking mechanism is implemented at the
moment (although this would be possible) and the special commands
[[backup]] and [[no_indent]] will not come out correctly.

@ The amount of indentation is defined here (two blanks at present).

<<Macro definitions in the implementation>>=
#define Ascii_terminal_output_INDENTATION_STRING "  "
@


\begin{impls}

\section{Implementation}


  As part of the implementation, here's an explanation how the
  typesetter dependent parts of the new subclass work.
  Essentially this is an explanation of an example implementation of
  the virtual [[flush_output]] routine.

@ A lot of things can be defined here using the macro definitions
here. Here we specify the strings output to the internal output steam
when the corresponding format commands are interpreted.

<<Macro definitions in the specification>>=
#define Ascii_terminal_output_NULL_OUTPUT_STRING         ""
#define Ascii_terminal_output_INDENT_OUTPUT_STRING       ""
#define Ascii_terminal_output_OUTDENT_OUTPUT_STRING      ""
#define Ascii_terminal_output_OPT0_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT1_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT2_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT3_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT4_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT5_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT6_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT7_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT8_OUTPUT_STRING         ""
#define Ascii_terminal_output_OPT9_OUTPUT_STRING         ""
#define Ascii_terminal_output_BACKUP_OUTPUT_STRING       ""
#define Ascii_terminal_output_BREAKSPACE_OUTPUT_STRING   ""
#define Ascii_terminal_output_FORCE_OUTPUT_STRING        "\n"
#define Ascii_terminal_output_BIGFORCE_OUTPUT_STRING     "\n\n"
#define Ascii_terminal_output_NOINDENT_OUTPUT_STRING     ""
#define Ascii_terminal_output_CANCEL_OUTPUT_STRING       ""
@

Here`s the frame of [[flush_output]]. It will always be called when the
lookahead needs to be cleared. If the lookahead is empty, we don`t
need to do anything.

<<Implementation of the new subclass>>=
void Ascii_terminal_output_SUBCLASS_NAME::flush_output()
{
        if (next_output_type==empty)
                return;
        /* otherwise: */
        <<Interpret the format command in [[next_output]] and write the interpretation to [[os]]>>
        next_output_type=empty;
}

@ Ok, so now let's turn to the part, where format commands are
actually interpreted. Suppose the next format command to be
interpreted is stored in [[next_output]]; the only thing to do now is to
have a giant switch inspecting [[next_output]]. Every case in this
switch outputs the corresponding code for this case to the [[ostream
os]] that is connected to our output class object.

<<Interpret the format command in [[next_output]] and write the interpretation to [[os]]>>=
<<Print the name of the format command if debugging>>
switch (next_output)
{
    <<Cases of the interpretation switch in [[do_output]]>>
    default: <<An unknown format command!>> break;
};

@

<<Print the name of the format command if debugging>>=
if (debug_mode==yes) {
    os  << begin_string << Format_command_str[next_output]
        << end_string;
}
@

This shouldn't (can't) happen.

<<An unknown format command!>>=
cerr << endl
    << "Unknown format command detected! Something's wrong here." << endl
    << endl;
exit(EXIT_FAILURE);

@ To use [[exit]], we have to include this:

<<Header files to include in the implementation>>=
#include<stdlib.h>
@

And since some (really old) operating systems don't have the
common [[EXIT_FAILURE]] and [[EXIT_SUCCESS]] macros defined
(in [[stdlib.h]]), we'll define them here.

<<Header files to include in the implementation>>=
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
@

Now we will start to scan the cases in the big switch. The actions
performed are essentially the output of a special string defined in
the interface above. However, as an ASCII terminal is quite dumb, we
need to explicitly code some parts (like managing indentation).




\subsection{Implementing [[indent]] and [[outdent]]}

We need an internal counter to hold the current amount of indentation.
Here's a static variable for this purpose.

<<Static variables in the implementation>>=
static int ind = 0;
@

<<Cases of the interpretation switch in [[do_output]]>>=
case indent: os << Ascii_terminal_output_INDENT_OUTPUT_STRING ;
    ind++; break;
case outdent: os << Ascii_terminal_output_OUTDENT_OUTPUT_STRING ;
    ind--; break;
@

The [[force]] and [[big_force]] commands break the line and add
as much whitespace as required by [[ind]].

<<Cases of the interpretation switch in [[do_output]]>>=
case force: os << Ascii_terminal_output_FORCE_OUTPUT_STRING ;
  {
    for (int i=0; i< ind; i++) {
        os << Ascii_terminal_output_INDENTATION_STRING ;
    }
  }
  break;
case big_force: os << Ascii_terminal_output_BIGFORCE_OUTPUT_STRING ;
  {
    for (int i=0; i< ind; i++) {
        os << Ascii_terminal_output_INDENTATION_STRING ;
    }
  }
  break;
@


\subsection{Line Breaking}

The format commands concering line breaking are not implemented.

<<Cases of the interpretation switch in [[do_output]]>>=
case opt0: os << Ascii_terminal_output_OPT0_OUTPUT_STRING ; break;
case opt1: os << Ascii_terminal_output_OPT1_OUTPUT_STRING ; break;
case opt2: os << Ascii_terminal_output_OPT2_OUTPUT_STRING ; break;
case opt3: os << Ascii_terminal_output_OPT3_OUTPUT_STRING ; break;
case opt4: os << Ascii_terminal_output_OPT4_OUTPUT_STRING ; break;
case opt5: os << Ascii_terminal_output_OPT5_OUTPUT_STRING ; break;
case opt6: os << Ascii_terminal_output_OPT6_OUTPUT_STRING ; break;
case opt7: os << Ascii_terminal_output_OPT7_OUTPUT_STRING ; break;
case opt8: os << Ascii_terminal_output_OPT8_OUTPUT_STRING ; break;
case opt9: os << Ascii_terminal_output_OPT9_OUTPUT_STRING ; break;
case break_space: os << Ascii_terminal_output_BREAKSPACE_OUTPUT_STRING ; break;
@

\subsection{Going Back}

The [[backup]] and [[no_indent]] are also not implemented.

<<Cases of the interpretation switch in [[do_output]]>>=
case backup: os << Ascii_terminal_output_BACKUP_OUTPUT_STRING ; break;
case no_indent: os << Ascii_terminal_output_NOINDENT_OUTPUT_STRING ; break;
@

\subsection{The [[null]] and [[cancel]] commands}

<<Cases of the interpretation switch in [[do_output]]>>=
case null: os << Ascii_terminal_output_NULL_OUTPUT_STRING ; break;
case cancel: os << Ascii_terminal_output_CANCEL_OUTPUT_STRING ; break;
@

\end{impls}

\end{document}


%
% $Log: asciioutput.nw,v $
% Revision 1.1  1996/03/13  11:30:06  gaertner
% Initial revision
%
%


