Per Simon's suggestions in the original Contributions thread [7ac18850], here's an updated version of the
Note: the attached patch deletes trailing whitespace from the cobc and libcob changelogs.
For the last few weeks, I've been slowly trying to get my head round the GNU COBOL source code, and to help me understand I've been working on adding a new statement to GNU COBOL:
ASSERT. Okay, it's another non-standard extension, but I think it will be useful.
There aren't any docs on it because this is just an extension I made up. I just liked C's
assert macro and thought it would be neat to implement a COBOL version. I don't expect this to be integrated into GNU COBOL.
ASSERT tests a condition; if it is false,
EC-IMP-FAILED-ASSERT is raised, the location of the failed assertion is displayed on
stderr and the program terminates. The
ASSERT syntax diagram is:
literal-1 is a string. The
MESSAGE clause is used to define a message which will be displayed with the
ASSERT location and the
DEBUGGING clause specifies that the
ASSERT will only be active if the compiler switch
‑fdebug‑assert is present. If
-fsource-location is used,
FUNCTION EXCEPTION-LOCATION is used to show the location of a failed
ASSERT. If not, the displayed location is just the file and line number. Using
-debug implicity sets
There is one known bug: if only the
MESSAGE clause is used and the program is compiled without
-fsource-location, the assertion's location will be one line further down than it should be.
Why would I want to use
Standard COBOL programming style favours large programs which are difficult to test, which makes modifying them difficult.
ASSERT documents assumptions that you make when writing code—things you always expect to be true. Such things might be "a month has 31 days at most", "the name field will not be blank" or "the year will not be greater than 2000". Assertions help when modifying code as it allows you to say with confidence "This change has not broken this module." If you change something and an assertion fails, you then know that you have broken the code and (hopefully) how you have done it. And, when you find a bug, you can use
ASSERTs to make sure it never happens again and/or to find the source of the bad data causing it.
An equivalent, standard-conforming copybook
But what if you like assertions, but not non-standard extensions? In that case,
COPY comes to the rescue:
IF NOT ( cond ) RAISE EXCEPTION EC-USER-FAILED-ASSERT DISPLAY FUNCTION EXCEPTION-LOCATION " " message UPON STDERR STOP RUN RETURNING 1 END-IF
Using the above copybook provides the same functionality, while remaining standard-conforming. Here's how it's used:
COPY assert REPLACING ==cond== BY ==year-num < 2000== ==message== BY =="Help! Year >= 2000!"==
For assertions which should only be used for debugging, use the following copybook and
>>DEFINE debug-assert to activate:
>>IF debug-assert IS DEFINED IF NOT ( cond ) RAISE EXCEPTION EC-USER-FAILED-ASSERT DISPLAY FUNCTION EXCEPTION-LOCATION " " message UPON STDERR STOP RUN RETURNING 1 END-IF >>END-IF