gawk: Assert Function

 
 10.2.2 Assertions
 -----------------
 
 When writing large programs, it is often useful to know that a condition
 or set of conditions is true.  Before proceeding with a particular
 computation, you make a statement about what you believe to be the case.
 Such a statement is known as an "assertion".  The C language provides an
 '<assert.h>' header file and corresponding 'assert()' macro that a
 programmer can use to make assertions.  If an assertion fails, the
 'assert()' macro arranges to print a diagnostic message describing the
 condition that should have been true but was not, and then it kills the
 program.  In C, using 'assert()' looks this:
 
      #include <assert.h>
 
      int myfunc(int a, double b)
      {
           assert(a <= 5 && b >= 17.1);
           ...
      }
 
    If the assertion fails, the program prints a message similar to this:
 
      prog.c:5: assertion failed: a <= 5 && b >= 17.1
 
    The C language makes it possible to turn the condition into a string
 for use in printing the diagnostic message.  This is not possible in
 'awk', so this 'assert()' function also requires a string version of the
 condition that is being tested.  Following is the function:
 
      # assert --- assert that a condition is true. Otherwise, exit.
 
      function assert(condition, string)
      {
          if (! condition) {
              printf("%s:%d: assertion failed: %s\n",
                  FILENAME, FNR, string) > "/dev/stderr"
              _assert_exit = 1
              exit 1
          }
      }
 
      END {
          if (_assert_exit)
              exit 1
      }
 
    The 'assert()' function tests the 'condition' parameter.  If it is
 false, it prints a message to standard error, using the 'string'
 parameter to describe the failed condition.  It then sets the variable
 '_assert_exit' to one and executes the 'exit' statement.  The 'exit'
 statement jumps to the 'END' rule.  If the 'END' rule finds
 '_assert_exit' to be true, it exits immediately.
 
    The purpose of the test in the 'END' rule is to keep any other 'END'
 rules from running.  When an assertion fails, the program should exit
 immediately.  If no assertions fail, then '_assert_exit' is still false
 when the 'END' rule is run normally, and the rest of the program's 'END'
 rules execute.  For all of this to work correctly, 'assert.awk' must be
 the first source file read by 'awk'.  The function can be used in a
 program in the following way:
 
      function myfunc(a, b)
      {
           assert(a <= 5 && b >= 17.1, "a <= 5 && b >= 17.1")
           ...
      }
 
 If the assertion fails, you see a message similar to the following:
 
      mydata:1357: assertion failed: a <= 5 && b >= 17.1
 
    There is a small problem with this version of 'assert()'.  An 'END'
 rule is automatically added to the program calling 'assert()'.
 Normally, if a program consists of just a 'BEGIN' rule, the input files
 and/or standard input are not read.  However, now that the program has
 an 'END' rule, 'awk' attempts to read the input data files or standard
 input (SeeUsing BEGIN/END), most likely causing the program to hang
 as it waits for input.
 
    There is a simple workaround to this: make sure that such a 'BEGIN'
 rule always ends with an 'exit' statement.