Asserts.mpas, details

Introduction

The reason for creating this unit can be found here: String variables that are too short (or contents of strings that are too long) are very difficult to find and make react the PIC software in very strange ways. Sometimes the erroneous software works and a minute later, after a minor change (not related to the overfilled string), it stops working.
The idea is, when a string variable is filled with characters, it should be possible at run time to do an assertion to check if the string variable is used within its size declaration. When the string if filled beyond that, a warning (here via Uart) is to be given to the user.

Additionaly the possibility is added to do also other assertions than on string length only.

Unit Interface

The unit's interface looks as follows:
// interface

// -------------- Public procedures --------------------

procedure Assert(Success: boolean; var Comment: string[50]);
// Generic Assert routine. Sends an Assert message when "Success" is false

procedure AssertStr(var S: string[4095]; Size: word; var Comment: string[50]);
// Specific for a string length Assert. Sends an Assert message when strlen(S) >= Size.

procedure Assert_Send_Message(var Message_: string[50]);
// simply sends the "message" to the assert output device


// -------------- External procedure, has to be defined in another unit (or main file) ---------

procedure SendAssertMessage(var S: string[50]); external;
// Sends a string to the assert message output device

Public procedures: The unit uses a procedure that has to be present in the one of the project's units (or main program): SendAssertMessage, see chapter "Assert Output".

See examples below.

Unit Usage

Before the unit can be used the output device that will be used for assert messages (e.g. Uart1) has to be initialised.
The routine AssertStr is to be called every time you want do do an assertion on a string.
The routine Assert is a more generic assert routine, and can of course also be used for stringlength assertion (it gives however not that detailed assert message as "AssertStr") and for any other assert activity.
The routine Assert_Send_Message is to be called whenever simply a text has to be sent to the assert output device.

Example:
{$DEFINE STRINGASSERT}     // switches on or off the StringAssert 

{$IFDEF STRINGASSERT}
uses Asserts;
{$ENDIF}

var Par: integer;
    Str: string[8];
    Str2: string[10];

{$IFDEF STRINGASSERT}
procedure Assert_Init;     // Initialises the device that will be used as output for assertion messages.
begin
  // Uart1 will be used as assert output device
  
{$IFDEF P24}  
  PPS_Mapping (7, _INPUT,  _U1RX);  // RP7 is uart1 input  pin 16
  PPS_Mapping (6, _OUTPUT, _U1TX);  // RP6 is uart1 output pin 15
{$ENDIF}

  Uart1_Init(115200);
  Delay_ms(250);
end;

procedure SendAssertMessage(var S: string[50]); // see chapter "Assert Output"
begin
  Uart1_Write_text(S);
end;
{$ENDIF}
...
  {$IFDEF STRINGASSERT}
  Assert_Init;          // only needed if the Uart is not already intialised
  {$ENDIF}
...
  Str2 := 'abc';
  Par := -32000;
  IntToStr(Par, Str);
  Str := 'Task2 ' + Str + #13 +#10 +#13 +#10;
  {$IFDEF STRINGASSERT}
  Assert_Send_Message('Started');
  AssertStr(Str, SizeOf(Str), 'Task2 AssertStr');    // do assert the string "Str" on overfilling, or
  Assert(StrLen(Str) < SizeOf(Str), 'Task2 Assert'); // do the same with the generic assert routine
  Assert_Send_Message('Done');
  {$ENDIF}
Since assertion on string assignments probably only will take place in the development period of the program, and not in the release version, a compiler directive defines whether string assertion will be done or not.

Assert Output

The assert output messages will be sent via the routine SendAssertMessage. This routine can be in any unit of the project (provided its declaration is in the interface part), or in the main project file. It has to be adapted (can be done for each project separately) if another output device has to be used by the project.

The implementation (which has to be changed if the project needs it) is very simple (example give for Uart1):
procedure SendAssertMessage(var S: string[50]);
begin
  Uart1_Write_text(S);
end;

-------------------------------------------