/***************************************************************************\
             Now.h - Will Mengarini - Version 1.00 - Mo 23 Jan 95

When we code assert( <condition> ), we're saying that <condition> is true
now, at this point in the control flow. This module implements a more
powerful assert() that is targeted at industrial-strength software
engineering environments, where automated regression testing is an expected
part of a delivered system, & a system is typically developed by a multi-
person project team whose members develop modules independently, test them
(this is called "unit testing"), then integrate them with the rest of the
system & regression test to ensure that the improvements haven't broken
anything else (this is part of what's called "system testing"). Integration
can be surprisingly traumatic, so engineers who have lived thru it have
learned that it's best done frequently; it has become customary for large
systems to attempt a complete link & system test every night so all modules
that were improved during the day are checked for continued compatibility
with the rest of this system (this is called "the nightly build").

Assert-replacement macros in this API have the form now#(), where # is 0-9.
The # is a measure of the importance of the assertion; the greater the #,
the more important the assertion is, & the greater the importance, the later
in system development it stops being tested. Standard assert() is
executed only #ifndef NDEBUG, so it doesn't get into ship code. However,
sometimes assert()s are so important that they do need to ship, & the
desire for a ship_assert() was the first of two needs that started the
development of this module. The name "ship_assert" is too long, however;
if it's too ponderous to type, there will be fewer assertions in the code,
which is Bad. Here, a now8() is a ship_assert(). A now6() gets as far as
system testing (the nightly build), a now4() only reaches unit testing, &
a now2() is used while debugging local regions of code.

The manifest constants UNIT_TEST, SYSTEM_TEST, & SHIP are used to determine
behavior of now[468](); exactly one of them must be 1. (Un#defined constants
are evaluated as 0 in conditional preprocessor directives; that's a POSIX
standard.) UNIT_TEST is intended to be 1 only within the module being unit-
tested, *not* within subordinate modules used by the module being unit-
tested. For example, the Now module contains conditional compilation based on
UNIT_TEST that causes now.cpp to to contain a main(){} that tests Now.
Obviously, this is impermissible when Now is used as part of the unit-testing
of other modules, as is intended to be possible.

I suggest that most now#()s should be now6()s, which is analogous to the
standard assert(); when the nightly build becomes too slow, selected now6()s
in mature code can start being reduced to now4()s. The gaps in the # sequence
can be given whatever definitions individual project teams need. For example,
now5() could be defined to test its condition in the same circumstances in
which now6() tests it, but to not compile the diagnostic output. This could
substantially reduce the size of the nightly build while maintaining the full
rigor (but also the increased run time) of the system test.

As a notational convenience now() is defined here as synonymous with now6(),
but this can easily be changed by project teams that need something else.

A now2() is used for debugging local regions of code & must be enabled by
setting REGION_NOW_LEVEL = 2 (which can be done using a debugger, since
REGION_NOW_LEVEL is a volatile int). There are an analogous now1() & now3().
These macros are independent of UNIT_TEST, SYSTEM_TEST, & SHIP, so if it's
necessary to run a debugger on ship code (which has no debugging
information), it'll at least be possible to use now[123]() for data output.

Note that it's commonplace to temporarily instrument code for debugging,
then to remove all the instrumentation when the bug is found, partly because
it's ugly, & partly because it's inefficient. A now2() avoids that. A now2()
is useful just as documentation, describing the programmer's intentions; but
it can be activated when those intentions are suspected of being unmet.

The standard assert() just displays the text & location of the failed
assertion. In a now8(), however, it's essential, & elsewhere it's often
desirable, to be able to display an explanatory message as well. An arg
that's just a char* wouldn't be powerful enough, since what's really wanted
here is the full power of stream-object output. The other major motivation
for the development of this module (the first was the need for a
ship_assert()) was the need to be able to associate formatted parameterized
type-safe error explanations with assert()s, often as afterthoughts when
assert() failures that were "impossible" started happening with sufficient
frequency to require detailed diagnostic output from each instance.

Another very frustrating attribute of the standard assert() is that it always
abends the program, making automated unit-testing of error-handling pathways
impossible. What's really needed to fix this is exceptions, which are
unavailable in the C++ for which this is being developed. The only way
around that is to unwind the stack by hand, & now#() is intended for use
in a development environment in which functions that would, in a full
C++, return void, instead return an error code that's checked by their
callers, &, if unanticipated, propagated up the stack. This would allow
    now8( !do_something_cool(),, ); //the ",," will be explained later
as a possible invocation of such a function. This is part of why macros
instead of functions are being used for now#(); there needs to be a return
statement in the now#() code. All non-test code therefore must check the
return value from void-like functions it calls, & abend if the return code is
nonzero; however, self-testing code can call such functions with deliberately
erroneous arguments or environments, & check without abending the unit test
that they correctly catch the error.

I considered using a global error code instead (the more common approach
to this kind of problem). That has several difficulties. For one thing, it's
not reentrant. For another, the syntax actually ends up worse, typically
    do_something_cool(); now8( !global_error_code );
It's even easier to forget the obligatory now6()s using the global_error_code
strategy than using the returned-error-code strategy. Reentrancy could be
achieved by making the error code a data member of some task object rather
than a global value, but the syntax remains prone to omission of the check.

Note that because returns are being used to simulate exceptions, now()s
can't be used inside constructors or destructors. To deal with this, put
all the nontrivial processing of a ctor or dtor inside a method.

There is a problem here. Although
    now8( !do_something_cool(),, );
does work, it has a serious disadvantage from a standpoint of software
engineering rigor. One of the more unfortunate gotchas with assert()s is
that, because they disappear in ship code, so do any side effects they may
have; so proper assert()s must never have side effects. The whole point of
    now8( !do_something_cool(),, );
is the side effect of running do_something_cool(), however, & the only
reason this works is that it's a now8(), which persists into ship code.
The problem is that a major goal of now#() is to allow tweaking the
digits more or less at whim to get the desired balance of failsafing
and efficiency; & this use of now8() doesn't fit that pattern, because
its purpose is to have a side effect.

This problem will go away when C++ compilers support exceptions, since
    now8( !do_something_cool(),, );
is only a way of implementing dtor-calling exceptions by hand; but still,
it leads to the dangerous habit of coding now#()s with side effects, which
should always be eschewed. Therefore, this specific use of now8(), as an
exception substitute, is implemented here with a differently-named macro
that's internally almost identical to now8(), but is intended to look
different enough that it won't engender confusion about side-effects
in assert()s & assert()-substitutes. What we want to say is that we're
requiring the called method to succeed (which it indicates by returning 0),
& if it doesn't we want to propagate the exception up the stack;
    succeed( do_something_cool(),, ); //the ",," will be explained later
seems to express that well enough, conveniently also eliminating the
potentially-confusing "!".

As this is being developed, most C++ preprocessors don't support optional
args for macros, & advocacy of a more powerful preprocessor is politically
incorrect. However, a very important aspect of now6() is its ability to
start out as the equivalent of assert(), be enhanced with diagnostic output
when its importance is discovered, &, if appropriate, be converted to a
ship_assert(), all without needing to recode the syntactic scaffolding
that surrounds the condition. However, altho args may not be omitted,
they may be empty; so
    three_arg_macro( warga, blegga, pizza )
&
    three_arg_macro( foo, spoo, )
are both syntactically acceptable to the preprocessor.

The now#() macros take 3 args, of which the last 2 are optional: they may
be omitted, altho their commas may not. The first arg is the condition;
the second arg is an error code of type int (an enum is acceptable using the
Borland C++ option "treat enums as ints"); & the third arg is diagnostic
output. It's OK to omit the second arg but include the third.

Parameterized diagnostic output was implemented in C with printf(), but this
wasn't type-safe, motivating the development of stream objects. This
    now( i > 0,, "Invalid i: " << i << " (it must be positive)" )
is an example of what now() can do. Note that the output stream isn't
specified in the third arg; that arg is actually just an expression fragment,
to which the implementation will prepend an equivalent of "cerr <<".
Such an assertion will typically begin life as
    now( i > 0,, );
if that were an assert(), it'd have to be replaced by an if() statement,
possibly wrapped inside an #if directive, just to display the value of i.
Also note that if complex user-defined objects are given stream-object output
methods, it becomes just as syntactically convenient to display the entire
relevant state of the program as it is to display an int.

The diagnostic output doesn't actually need to go to cerr (standard error).
Because now8() is a ship_assert(), it's mandatory to enable diagnostics
that would be comprehensible to a product user. __LINE__ & __FILE__ shouldn't
be in such output. Two identifiers of type <extern ostream &> are defined,
userLog & debugLog; in ship code, debugLog can be directed to a log file,
while userLog goes to some video output window. During development, it's
usually satisfactory to include the line
    ostream &userLog = cerr, &debugLog = cerr;
in one of the .cpp files. In ship code, __LINE__ & __FILE__ go to debugLog,
along with a time stamp, so they're accessible to telephone tech support
staff while not confusing users. The third arg to now8() goes to userLog.

Because ship code assertion failures generally require far more boilerplate
of the "phone this # for help" variety, a facility is provided for defining
that boilerplate in one place. Two char arrays, shipCodeNowFailureHeader &
shipCodeNowFailureFooter, must be defined by Now users. Because you don't
want to discover that you forgot these definitions only when you're ready
to ship, they're actually required to be defined in test code as well,
but are not output. In ship code they surround the third arg to now8(). If
you want newlines at the ends of those boilerplate segments (you might not
if they're going into a an error box) you need to insert them yourself.

The second arg to the now#() macros is an error code used in unwinding the
stack to simulate throwing an exception. (Just abending doesn't run object
destructors, which matters not only for resource recovery (eg avoiding
memory leaks) in caught exceptions, but also for cleanup of the system
state even when an abend is to occur, such as releasing database locks.)
The now#() macros expect to be called from inside functions that return
success/failure ints, where 0 denotes success. If a now#() macro's condition
is false, it displays its own diagnostic output as well as arg 3, then
executes a return statement with a nonzero value. (You could easily change
this, either to throw an exception if you have them, or to call exit()
(which, nota bene, calls the at_exit() registrations, whereas _exit() does
not) if that's sufficient for your resource recovery.) The nonzero value
defaults to a manifest constant named defaultErrorCode; it is returned if
there is no 2nd arg, else the 2nd arg is returned. You can give a value to
defaultErrorCode using any of the standard methods (a -D directive, a
#define, etc); if you do none of these, this .h gives it a value of 5000.

In summary, this is what you must do to use the Now module:
  --Either design your code so each function that uses the now#() macros
    returns a success/failure int, or hack the NOW() macro below (an internal
    macro used in implementing each of the now#() macros) to use your own
    failure protocol, such as calling exit() or throwing an exception.
    Note that functions that return non-success/failure values can easily
    be redefined to take reference args into which they store those values.
  --Include the line
      ostream &userLog = cerr, &debugLog = cerr;
    (or something more complicated) in one of your .cpp modules.
    Watch those ampersands; if you have a typedef convention, use it instead.
  --Define lines like
      char shipCodeNowFailureHeader[] = "Don't worry, but I have bad news:";
      char shipCodeNowFailureFooter[] = "Everything will be all right.";
    in one of your .cpp files. There needn't be a corresponding declaration
    in any of your .h files.
  --Ensure that in every compilation, exactly one of the manifest constants
    UNIT_TEST, SYSTEM_TEST, & SHIP will be 1.
  --Begin by just replacing the form
      assert( condition );
    with the form
      now( condition,, );
    you can later add diagnostic output & error codes as needed.
    Always call functions that participate in stack-unwinding with
      succeed( function,, );
    rather than
      now8( !function,, );
    even tho they're equivalent; now#()s should never have side effects.

That completes the specification of the Now module API.  It should be all
you need to read if you want to use the code without hacking it.
If you want to make improvements, you can't start by reading the rest of
this file; you must start with a header, "WM-Root.h", that I #include in all
my code. It contains #defines & typedefs without understanding which my code
is unreadable, & also has some explanation of my programming style.
\***************************************************************************/

#ifndef NOW_H
#define NOW_H

//You should not be reading this unless you've already read "WM-Root.h".
//If you haven't, stop now & read it.

#include "WM-Root.h"

//You can redefine the following constant if necessary for your own
//error-handling protocol. The #ifndef allows this to be done on the
//compiler's command line by users who don't want to hack the source.

#ifndef defaultErrorCode
  #define defaultErrorCode 5000
#endif

//The user must run all compilations with exactly one of the following
//constants defined as 1.

#if (UNIT_TEST + SYSTEM_TEST + SHIP) != 1
  #error
#endif

//Verify consistency with the manifest constant used to control
//the built-in assert() macro (see the system include file assert.h).

#if NDEBUG != SHIP
  #error
#endif

//All the now#() macros will be implemented in terms of NOW(), an internal
//macro used to factor out the importance-level-independent code.
//NOW() always expands to generate debugging code; the now#()s decide whether
//to expand to NOW() or not.

//The implementations of now[123]() & now[468]() are fundamentally different
//in that now[123]() decide whether to call NOW() using an if() statement,
//whereas now[468]() use an #if directive. This is because the decision for
//now[468]() is based entirely on values known at preprocessing time,
//whereas the decision for now[123]() is based on a value that might not
//be known until run time.

//First comes the implementation of now[123](), which are expanded based
//on the value of REGION_NOW_LEVEL. REGION_NOW_LEVEL is declared here as
//a volatile int; the volatility ensures that code optimization won't
//prevent you from modifying REGION_NOW_LEVEL in the debugger to enable
//now[123]() in a region. However, for exactly this reason, the debugging
//code for now[123]() is always generated even if the now() is not enabled;
//it's just not executed if it's not enabled. In the event that you want to
//leave now[123]()s in place while causing them to generate no code, you
//can do it by #defining REGION_NOW_LEVEL as 0 in optimized code; that will
//cause the if()'s condition to be based entirely on literals, to always be
//false, & to therefore generate no code. This #define is checked for
//before the declaration here.

#ifndef REGION_NOW_LEVEL
  extern volatile I REGION_NOW_LEVEL; // = 0 in Now.cpp
#endif

#define now1( condition, errorCode, errorMsg )\
  if( REGION_NOW_LEVEL >= 1 ) NOW( condition, errorCode, errorMsg );

#define now2( condition, errorCode, errorMsg )\
  if( REGION_NOW_LEVEL >= 2 ) NOW( condition, errorCode, errorMsg );

#define now3( condition, errorCode, errorMsg )\
  if( REGION_NOW_LEVEL >= 3 ) NOW( condition, errorCode, errorMsg );

//REGION_NOW_LEVEL is volatile so it can be changed in the debugger, but
//if source is being frequently recompiled during debugging, it may be
//preferable to change REGION_NOW_LEVEL in source. This at least can be
//made a bit more convenient by obviating the need to remember to change it
//back at the end of the code being scrutinized. Calling blockNowLevel(2)
//sets REGION_NOW_LEVEL to 2 for the duration of the {} block, then sets
//it back to its previous level when the block is exited.

//Since that whole concept is invalid if REGION_NOW_LEVEL is #defined,
//a wrapper checking for that must protect blockNowLevel()'s implementation.

#ifndef REGION_NOW_LEVEL

  #define blockNowLevel(i) BlockLevel objectOfClassBlockLevel = (i)

  class BlockLevel {
    I oldLevel;
  public:
    BlockLevel( K I newLevel ){
      oldLevel = REGION_NOW_LEVEL;
      REGION_NOW_LEVEL = newLevel;
    }
    ~BlockLevel(){
      REGION_NOW_LEVEL = oldLevel;
    }
  };

#endif //#ifndef REGION_NOW_LEVEL

//As a notational convenience, now() is defined as whichever of now[468]()
//the project team most customarily uses. That's expected to be now6().

#define now( condition, errorCode, errorMsg )\
  now6( condition, errorCode, errorMsg )

//If now[468]() are enabled by the current #defines, they expand to NOW()
//calls; else they expand to nothing.

#if UNIT_TEST
  #define now4( condition, errorCode, errorMsg )\
    NOW( condition, errorCode, errorMsg )
#else
  #define now4( condition, errorCode, errorMsg )
#endif

#if UNIT_TEST || SYSTEM_TEST
  #define now6( condition, errorCode, errorMsg )\
    NOW( condition, errorCode, errorMsg )
#else
  #define now6( condition, errorCode, errorMsg )
#endif

#if UNIT_TEST || SYSTEM_TEST || SHIP
  #define now8( condition, errorCode, errorMsg )\
    NOW( condition, errorCode, errorMsg )
#else
  #define now8( condition, errorCode, errorMsg )
#endif

//When succeed() is used to simulate exceptions, it typically produces
//a cascade of Now violations at successively higher invocation levels.
//This cascade is confusing unless flagged as such, which requires
//a global variable to remember that it happened, & a global function
//to clear it if the exception is caught before an abend.

extern I cascadeOfNowsInProgress;//initialized to 0 in now.cpp
V clearNow();

//It also helps to clarify that the failing "assertion" is just
//an "assertion" that an action was successful:

#define successful(action) !(action)

#define succeed( action, errorCode, errorMsg )\
  NOW( successful( action ), errorCode, errorMsg )

//In NOW(), either errorCode or errorMsg may be omitted from the invocation,
//as long as their commas are present; but condition, unlike errorCode or
//errorMsg, is guaranteed to be nonempty. (An empty condition wouldn't make
//sense in terms of what the API is implementing, & so NOW() is coded to
//generate a C++ syntax error if condition is empty.)

//In NOW(), error logging is handled by an object rather than a function so
//it can preserve a data state during syntactic shenanigans that are needed
//to cope with the possibly-empty args. A class ErrorLog is defined for this,
//& the non-empty data it will need, __FILE__, __LINE__, & the stringized
//condition, are just passed as args to its constructor. Its destructor will
//be run implicitly when the return statement in NOW() is executed, & those
//two methods--constructor & destructor--take care of whatever output needs
//to surround the user's output in the errorMsg arg.

//The central shenanigan for dealing with empty args is to exploit the
//ambiguous arity of "+": a possibly-empty arg can precede it without
//rendering the resulting C++ invalid if the C++ makes sense whether the
//"+" is unary or binary, & the emptiness of the arg can be tested by code
//that does different things depending on that arity.

//This is easiest with errorCode, which is either emptiness or a nonzero #;
//the expression "errorCode + defaultErrorCode != defaultErrorCode" is true
//if the user specified an errorCode, & the expression "errorCode + 0" is
//a syntactically-safe way of referring to errorCode whether empty or not.

//The problem with errorMsg is much more complex, because even a nonempty
//errorMsg needn't be a valid C++ expression; it's an expression /fragment/,
//to which an ostream insertion like "cerr <<" must be prepended. WM-Root.h
//(#included at the top of now.h) defines an object named "nul" that comes
//in useful in situations like this. It's basically a placeholder. To cope
//with errorMsg, we can define the expression "errorMsg + nul" to always be
//wellformed & meaningful by providing suitable overloadings of "+".

//Note that errorCode & errorMsg can't be parenthesized the way macro args
//usually are, because they might be empty, & because errorMsg might contain
//ostream::operator <<(); "cerr << (string1 << string2)" parses wrong. (It
//can actually be /wellformed/ under Borland 3.1; a literal string is a
//pointer, which is implicitly convertible to an int, so "spoo" << "oops"
//left-shifts the address of "spoo" by the integer value modulo 32 of the
//address of "oops". This pointer is then output instead of the error msg.)

#define NOW( condition, errorCode, errorMsg )\
  if( !(condition) ){\
    ErrorLog el( __FILE__, __LINE__, #condition );\
    userLog << errorMsg + nul;\
;   return errorCode + defaultErrorCode != defaultErrorCode ? \
      errorCode + 0 : defaultErrorCode;\
  }

//The ErrorLog destructor will need to know whether errorMsg was empty, since
//I think it's unhackworthy for a module like this to require programmers to
//explicitly code newlines at the end of args like errorMsg; they all require
//one, so the module should provide it, but of course it must only be
//provided if there /was/ an errorMsg, since it's also unhackworthy to just
//output a spurious blank line. (The same argument doesn't apply to the
//shipCodeNowFailure{Header,Footer} boilerplate since the programmer only
//needs to code that once.) A global can keep track of whether errorMsg was
//empty, & its value can be set by the "+" overloadings.

extern I errorMsgNonemptyInCallOfNOW; //defined in now.cpp

//In the event that errorMsg is empty, "userLog << errorMsg + nul" becomes
//"userLog << + nul", which must be a wellformed NOP. Inserting "" into
//an ostream is always a NOP, so "+ nul" can return "" & set the boolean.
//(Note that nul is an object (the only object) of class Nul.)

C *operator + ( Nul );//defined in now.cpp
  //This is the definition:
  //  C *operator + ( Nul ){
  //    errorMsgNonemptyInCallOfNOW = 0;
  //    return "";
  //  }
  //It needs to go in now.cpp since putting it here would generate a
  //separate copy of the code in each .cpp in which now.h was #included.

//In the event that errorMsg is nonempty, "userLog << errorMsg + nul" must
//become equivalent to "userLog << errorMsg". This can be achieved by
//defining the expression fragment "+ nul" as a postfix identity function
//defined on all data types. Like the unary "+" above, it must set the
//boolean as a side effect.

template< class T > T operator + ( T t, Nul ){
  errorMsgNonemptyInCallOfNOW = 1;
  return t;
}
  //Unlike ordinary function code, template code needs to go in a header
  //so each .cpp can decide how to instantiate it.

//(I considered another approach to dealing with errorMsg: whether it's
//empty or not can be used to overload a function of void. For example,
//  class EmptinessTester {
//    I itWasEmpty;
//  public:
//    EmptinessTester ()     { itWasEmpty = 1; }
//    EmptinessTester ( C * ){ itWasEmpty = 0; }
//    operator I () { return itWasEmpty; }
//  };
//would enable code like
//  if( EmptinessTester(#errorMsg) ) [...]
//The problem is that because errorMsg is an expression fragment,
//it must be stringized to produce a value that can overload a ctor;
//& the necessary attribute of the stringize operator--that stringizing
//an empty arg produces emptiness, not ""--is undocumented either in the
//Borland C++ v3.1 Programmer's Guide p164 or Stroustrup 91 r.16.3.1,
//& without it, the whole concept breaks. The template/Nul hack always works.
//(Just as an aside, note that this definition of the stringize operator is
//strictly more powerful than one that returns ""; if you want the latter
//effect, you can get it with code like
//  #someArg ""
//which, in the event that someArg is nonempty, will generate
//  "valueOfSomeArg" ""
//which the preprocessor (Stroustrup 91 r.16.1) then concatenates.))

//The declarations for userLog & debugLog must have been seen by the time
//class ErrorLog is declared.

extern ostream &userLog, &debugLog; //user must define these

//The constructor & destructor write a header & footer preceding & following
//the user's errorMsg. Methods for doing that need to be separately compiled
//(so they're in now.cpp rather than now.h) because they generate a lot of
//code, so all the class definition here does is declare & call them.

class ErrorLog {
  K C *errorFile, *condition;
  K I errorLine;
public:
  ErrorLog ( K C *errorFile, K I errorLine, K C *condition )
  : errorFile(errorFile)
  , errorLine(errorLine)
  , condition(condition)
  {
    writeLogHeader( errorFile, errorLine, condition );
  }
  ~ErrorLog (){
    writeLogFooterAndFlagCascade( errorFile, errorLine, condition );
  }
private:
  V writeLogHeader (
    K C *errorFile, K I errorLine, K C *condition
  ) K;
  V writeLogFooterAndFlagCascade (
    K C *errorFile, K I errorLine, K C *condition
  ) K;
};

#endif //NOW_H

