\chapter{Aprepro Library Interface}

The previous chapters have described the standalone version of
\aprepro{}.  The functionality provided in the standalone version can
also be provided to other programs through the \aprepro{} library
C++ interface. The \aprepro{} library provides a \cmd{SEAMS::Aprepro}
class which has three methods for parsing the input:
\begin{enumerate}
\item Read from stdin, echo data to stdout. At end of input, the
parsed output is available in the \cmd{Aprepro::parsing\_results()}
stream.
\item Read and parse a file. The entire file will be parsed with no
output.  After the file is parsed, the parsed output is available in
the \cmd{Aprepro::parsing\_results()} stream.
\item Read and parse a string containing the \aprepro{} input. The
results from parsing the string are returned in the \cmd{Aprepro::parsing\_results()}
stream. Note that when using this method, you cannot use loops, if
blocks, verbatim, and echo.
\end{enumerate}

\section{Adding basic \aprepro{} parsing to your application}
The \aprepro{} capability is provided as a set of C++ classes. The
main \cmd{SEAMS::Aprepro} class defined in the \file{aprepro.h}
include file is the main interface used by external programs.

The basic method for using the \cmd{SEAMS::Aprepro} class is:
\begin{itemize}
\item create a \cmd{SEAMS::Aprepro} object
\item parse the data
\item retrieve the parsed data.
\end{itemize}
An example of this is shown below:
\lstset{language=C++, basicstyle=\small, numbers=left, stepnumber=1,
numbersep=5pt, numberstyle=\tiny, morekeywords={[2]aprepro},keywordstyle={[2]\color{blue}}}
\begin{lstlisting}
#include <aprepro.h>
int main(int argc, char *argv[])
{
  SEAMS::Aprepro aprepro;
  bool result = aprepro.parse_stream(infile, argv[argc-1]);
  if (result) {
     std::cout << "PARSING RESULTS: " << aprepro.parsing_results().str();
  }
}
\end{lstlisting}

\section{Additional \aprepro{} parsing capabilities}
In addition to the basic parsing shown above, additional capabilities
are available including predefining variables, adding additional
functions, and modifying the aprepro options.

\subsection{Adding new variables}
The \cmd{add\_variable()} member function is used to define new
variables that will be available during the aprepro parsing. The
function signatures are:
\begin{source}
    void add\_variable(const std::string &name, const std::string &value, bool is\_immutable=false);
    void add\_variable(const std::string &name, double value, bool is\_immutable=false);
\end{source}
Where \cmd{name} is the name of the variable to be defined,
\cmd{value} is the value of the variable (either a double or a
string).  To create the variable as immutable, pass \var{true} as the
third option.

\subsection{Adding new functions}
Additional functions can be made available during parsing as shown in
the example below.
\begin{source}
  // This function is used below in the example showing how an
  // application can add its own functions to an aprepro instance.
  double succ(double i) \{
    return ++i;
  \}
  // EXAMPLE: Add a function to aprepro...
  SEAMS::symrec *ptr = aprepro.putsym("succ", SEAMS::Aprepro::FUNCTION, 0);
  ptr->value.fnctptr\_d = succ;
  ptr->info = "Return the successor to d";
  ptr->syntax = "succ(d)";
\end{source}
Following this, the user can use the \cmd{succ(d)} command in the same
way as any of the other \aprepro{} functions.  This can be used to
provide functions that access data internal to your program. The
function will also appear in the \cmd{DUMP\_FUNC()} function list.

\subsection{Modifying \aprepro{} Execution Settings}
The standalone \aprepro{} can be executed with several command line
options which change the behavior of \aprepro{} as defined in
Chapter~\ref{ch:execution}. Similar behavior modifications are
available in the \aprepro{} library via the \cmd{set\_option()}
command. The syntax is:
\begin{source}
    void set\_option(const std::string &option);
\end{source}
Where \cmd{option} is one of:
\begin{longtable}{lp{5.0in}}
\cmd{--debug} &  Dump all variables, debug loops/if/endif \\
\cmd{--dumpvars} & Dump all variables at end of run \\
\cmd{--dumpvars\_json} & Dump all variables at end of run in json format \\
\cmd{--version} &  Print version number to stderr.\\
\cmd{--immutable} & All variables are immutable -- cannot be modified \\
\cmd{--errors\_fatal} & Exit program with nonzero status if errors are encountered \\
\cmd{--errors\_and\_warnings\_fatal} & Exit program with nonzero status if warnings are encountered \\
\cmd{--require\_defined} & Treat undefined variable warnings as fatal \\
\cmd{--one\_based\_index} & Array indexing is one-based (default = zero-based) \\
\cmd{--interactive} & Interactive use, no buffering \\
\cmd{--message} & Print INFO messages \\
\cmd{--info=file} & Output INFO messages (e.g. DUMP() output) to file. \\
\cmd{--nowarning} &  Do not print warning messages.\\
\cmd{--copyright} &  Print copyright message to stderr.\\
\cmd{--message} &  Print INFO messages.\\
\cmd{--trace} &  Trace program execution. Primarily for aprepro developer.\\
\cmd{--interactive} &  Interactive use; do not buffer output.\\
\cmd{--exit\_on} &  End with Exit or EXIT or exit or Quit or QUIT or
quit encountered in parsing stream.\\
\cmd{--include=}\var{file\_or\_path} &  If a path is
specified, then optionally prepend it to all included filenames; if a
file is specified, the process the contents of the file before
processing input files.\\
\cmd{--help} &  Output the following text:\\
\end{longtable}
\begin{apout}
APREPRO PREPROCESSOR OPTIONS:
  --debug or -d: Dump all variables, debug loops/if/endif and keep temporary files
       --dumpvars or -D: Dump all variables at end of run
  --dumpvars_json or -J: Dump all variables at end of run in json format
        --version or -v: Print version number to stderr
      --immutable or -X: All variables are immutable--cannot be modified
   --errors\_fatal or -f: Exit program with nonzero status if errors are encountered
 --errors\_and\_warnings_fatal or -F: Exit program with nonzero status if warnings are encountered
--require\_defined or -R: Treat undefined variable warnings as fatal
--one\_based\_index or -1: Array indexing is one-based (default = zero-based)
    --interactive or -i: Interactive use, no buffering
    --include=P or -I=P: Include file or include path
                       : If P is path, then optionally prepended to all include filenames
                       : If P is file, then processed before processing input file
                       : variables defined in P will be immutable.
       --exit\_on or -e: End when 'Exit|EXIT|exit' entered
           --help or -h: Print this list
        --message or -M: Print INFO messages
            --info=file: Output INFO messages (e.g. DUMP() output) to file.
      --nowarning or -W: Do not print WARN messages
--comment=char or -c=char: Change comment character to 'char'
      --copyright or -C: Print copyright message
  --keep\_history or -k: Keep a history of aprepro substitutions.
                         (not for general interactive use)
          --quiet or -q: Do not print the header output line
                var=val: Assign value 'val' to variable 'var'
                         Use var=\"sval\" for a string variable

	Units Systems: si, cgs, cgs-ev, shock, swap, ft-lbf-s, ft-lbm-s, in-lbf-s
	Enter {DUMP()} for list of user-defined variables
	Enter {DUMP_FUNC()} for list of functions recognized by aprepro
	Enter {DUMP_PREVAR()} for list of predefined variables in aprepro

	->->-> Send email to gdsjaar@sandia.gov for aprepro support.
\end{apout}

For additional functions that are rarely used, see the
\file{aprepro.h} include file.

\section{Aprepro Library Test/Example Program}
A test program is provided with the \aprepro{} library which provides
examples of the three parsing methods, defining variables, and
defining functions.  This is defined in the \file{apr\_test.cc} file in
the \aprepro{} library distribution. The contents of this file are
shown below:



\lstset{language=C++, basicstyle=\small, numbers=left, stepnumber=1,
numbersep=5pt, numberstyle=\tiny, morekeywords={[2]aprepro},keywordstyle={[2]\color{blue}}}
\begin{lstlisting}
#include <iostream>
#include <fstream>

#include "aprepro.h"

// This function is used below in the example showing how an
// application can add its own functions to an aprepro instance.
double succ(double i) {
  return ++i;
}

int main(int argc, char *argv[])
{
  bool readfile = false;

  SEAMS::Aprepro aprepro;

  // EXAMPLE: Add a function to aprepro...
  SEAMS::symrec *ptr = aprepro.putsym("succ", SEAMS::Aprepro::FUNCTION, 0);
  ptr->value.fnctptr_d = succ;
  ptr->info = "Return the successor to d";
  ptr->syntax = "succ(d)";

  // EXAMPLE: Add a couple variables...
  aprepro.add_variable("Greg", "Is the author of this code", true);  // Make it immutable
  aprepro.add_variable("BirthYear", 1958);

  for(int ai = 1; ai < argc; ++ai) {
    std::string arg = argv[ai];
    if (arg == "-i") {
      // Read from cin and echo each line to cout All results will
      // also be stored in Aprepro::parsing_results() stream if needed
      // at end of file.
      aprepro.ap_options.interactive = true;
      bool result = aprepro.parse_stream(std::cin, "standard input");
      if (result) {
	std::cout << "PARSING RESULTS: " << aprepro.parsing_results().str();
      }
    }
    else if (arg[0] == '-') {
      aprepro.set_option(argv[ai]);
    }
    else {
      // Read and parse a file.  The entire file will be parsed and
      // then the output can be obtained in an std::ostringstream via
      // Aprepro::parsing_results()
      std::fstream infile(argv[ai]);
      if (!infile.good()) {
	std::cerr << "APREPRO: Could not open file: " << argv[ai] << '\n';
	return 0;
      }

      bool result = aprepro.parse_stream(infile, argv[ai]);
      if (result) {
	std::cout << "PARSING RESULTS: " << aprepro.parsing_results().str();
      }

      readfile = true;
    }
  }

  if (readfile) return 0;

  // Read and parse a string's worth of data at a time.
  // Cannot use looping/ifs/... with this method.
  std::string line;
  while( std::cout << "\nexpession: " &&
	 std::getline(std::cin, line) &&
	 !line.empty() ) {
    if (line[0] != '{')
      line = "{" + line + "}\n";
    else
      line += "\n";

    bool result = aprepro.parse_string(line, "input");
    if (result) {
      std::cout << "         : " << aprepro.parsing_results().str();
      aprepro.clear_results();
    }
  }
}
\end{lstlisting}
