If you need to download the code, you can do so from the app homepage listed in the PREFACE. At the download page you should find a file named alphaxy.zip, containing the APP/APPLIB version x.y distribution. This is a zip file that will unzip into a directory named alpha. You should first move aside your existing alpha directory if you have already downloaded a previous version. For Windows you can use winzip; for linux/unix use "unzip -a alphaxy.zip".
This software was initially developed on a W95 Intel platform with MS VC++ 5.0, and presently runs under both VC++ and g++ 2.91.66+ (cygwin/slackware 7 linux). The alpha directory when unzipped is set up for both VC++ and g++ environments. See first the README.txt file after unzipping. This file will tell you how to install for any of: VC++, linux/unix g++, cygwin g++, and dual VC++/cygwin g++ platforms.
For MS VC++, installation is simple. About all install.bat does is copy the pre-built executables, static library, and header files to the bin, lib, and include directories of your choice - it may also invoke app to fix #line's in _beta.h, depending on the INCLUDE variable setting.
For g++, installation is a little more involved, as there are no pre-built g++ executables or libraries. Basically everything has to be compiled first, after which installation proceeds pretty much as for VC++. This is all handled by a single script file (gboot.sh).
App is a command-line driven application. Type 'app -h' to get an idea of what the command line arguments look like, and 'app -v' to get current version related information.
General usage is 'app options f1 f2 ... fn'. App expects zero or more input files f1 f2 .. fn. In the zero case, input is taken from standard input, and output is by default to standard output. In the one case input is taken from f1, and output is by default to _f1. In the two or more cases, input is taken from the ordered catenation of f1 f2 .. fn, and output by default is to _fn; additionally a temporary file fn.tmp is generated that app uses to concatenate f1 f2 ... fn and is removed upon successful completion. Option 't=x' can be specified to indicate an extension .x rather than .tmp. You can in any case specify '-o=f' to override output defaults for filename f ("-" for f is taken as cout).
In the multiple file input case, f1 f2 .. fn-1 are taken as implicit include files. You can use option '-i=d' one or more times to tell app where to look for any of the f1 f2 .. fn-1 that can't be found otherwise, where 'd' is a directory name. The precedence order for '-i' is right to left so that e.g. 'app -i=d1 -i=d2 ...' implies that d2 is searched before d1.
Option '-ori' ('--only_read_includes') causes app to treat the argument files f1..fn-1 as implicit include files as usual but which are excluded from the generated code. By using explicit #include directives for _f1.._fn-1 in your code together with this option (assuming default _f1.._fn-1 app outputs), you can reduce the size of the generated code and also the number of redundant symbols. This is particularly effective for use with class browsers etc.
App accounts for #line directives in input, but doesn't do C++ preprocessing functions itself. As it can be operated in a mode that makes it appear as an extension to the C++ preprocessor, for the sake of modal consistency it just uses a simple command line facility for include handling rather than trying to deal with #includes in input or some kind of special #include-like keyword that only app would understand.
This can have implications when files included by the app command line facility themselves include other files; as app does not know about the other included files it may be necessary to compile the app generated result by specifying additional include directories as compiler parameters so as to account for the other files. If things are not set up properly and there are problems in a source file that the compiler wants to complain about, the compiler may get confused and refer to nonexistent or otherwise bogus files due for example to app generated #line directives that don't correspond with reality. In such cases option '-nolds' can be used to get app to not generate #line directives; the compiler will then at least be able to refer to an existing file. Option '-lfp=s' can also be used to get app to attach s as a filename prefix to all generated #line directives; this may prove useful in certain circumstances.
By default app deliberately generates "unpretty" code by removing redundant whitespace. An option '-p' ('--pretty') can be specified to (largely) preserve original whitespace, and not generate #line directives. The pretty option can be useful for certain illustrative purposes but can cause headaches because the pretty code looks almost exactly like the original, and even the synthesized code looks pretty, so it is easy to edit it by mistake instead of the original. Beware.
There are at least three ways that app can operate. First, it can be utilized as a standalone program, which is surely the easiest way, and it isn't that painful to deal with either. Second, it can be utilized as a frontend for the C++ preprocessor. Third, it can be utilized as a backend for the C++ preprocessor.
The standalone mode works pretty much as expected. You just run app like any other code generating program such as lex or yacc, then arrange to compile the output. If you have makefile capabilities it's just a one or two step process. I use the Cygnus cygwin free software, which provides for certain Unix-like utilities for Windows including 'make', so I just type 'make' in a shell, which runs app as needed, then switch to Visual Studio and hit F7, and that's about all there is to it.
By default app generates a '#define APP' directive as the first line of output. This is useful for IDEs that are sensitive to filename extensions. For example I like to use .cpp files for both app inputs and outputs because the MS Visual Studio editor highlights C/C++ keywords - but only for C/C++ files. By wrapping all app input code with #ifdef APP ... #endif directives the VC++ compiler won't complain about app constructs even though the app inputs are part of the same project as the outputs, because only app outputs get the requisite #define. Option '-noad' can be used to get app to not generate the #define, which might come in handy when app is utilized as a backend for the C++ preprocessor - when it's too late for #define's.
App can also operate as a C++ preprocessor frontend, that is, if you can get the C++ preprocesor to run independently of the compiler, or if the compiler can act like an independent preprocessor in case it also happens to implement the preprocessor. In this case though you probably want to use a makefile or some such to get things to work out. However if you can do all that it would probably be better to use app as a backend for the C++ preprocessor in order to better take advantage of its capabilities. Don't forget the '-noad' option.
The sample directory contains an assortment of simple examples illustrating the basic concepts of app and applib. There is just one program sample_main that links with the individual samples via sample_x() interface routines. Many of the sample_x.cpp files have a corresponding _sample_x.cpp file, the app generated version.
If you are using MS VC++ the sample directory is also a project, and you should be able to run the project in the usual manner. Note that as object files are not included in the distribution, when you run the project you will be told that there are missing files and asked if you would like to rebuild them; it doesn't matter how you answer.
If you are using g++ the gsample directory also contains a very simple hello world program (app-style) and associated makefile that you may wish to examine first.
You may also wish to examine the app source as substantial portions of it are written in itself. As for the sample code, each app input file f.h or f.cpp has a corresponding output file _f.h or _f.cpp. The various app makefiles also illustrate pretty well how to deal with moderately complex app related build environments using some of the more interesting GNU make features.
App uses flex to do input scanning, but the code is not particularly flex specific. Unfortunately flex appears to have a problem (at least on Windows) when the last line of input is not newline terminated. You should make sure all app input files have properly terminated last lines otherwise final input tokens may silently disappear.
As of g++ 2.95.2, there are certain limitations under g++: option '-ori' is
ineffectual, and #line directives that point back to the generated output file
are not generated (the app code specializes the filebuf and ofstream classes
and that appears to be a problem with g++ due to buggy iostream support).