gawk: Assert Function

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