Previously, the functions registered with atexit() would be called with data bank corresponding to the blank segment, which is correct in the small memory model but not necessarily in the large memory model. This could cause memory corruption or misbehavior for certain operations accessing global variables.
This is used by the new ORCA/C debugging option to check for illegal use of null pointers. It is similar to an existing routine in PasLib used by ORCA/Pascal's similar checks.
This ensures use of the Time Tool is fully under the control of the programmer, rather than potentially being affected by other things that may load it (like the Time Zone CDev). It also avoids calls to tiStatus in the default non-Time Tool code paths, and thereby allows them to work under Golden Gate.
The new CDev root code generated by ORCA/C will now branch to this code after each CDev call, giving it an opportunity to clean up if necessary. Specifically, it will dispose of the user ID allocated for the CDev if it is going away after this call. There are several cases where this occurs, which need to be detected based on the message code passed to the CDev and in some cases other factors.
This differs from the existing ~UMul2 in SysLib in that it gives the low-order 16 bits of the true result in the event of overflow. The C standards require this behavior for computations on unsigned types.
This affects code where multiple structs or unions are assigned by successive = operators in one expression, e.g. "s1=s2=s3". The middle struct assignment(s) would use the ~Move2 or ~LongMove2 helper functions (for <64k or >=64k moves, respectively). These functions are supposed to leave the destination pointer on the stack so it can be used as the source of a subsequent move, but they both had bugs where they could modify dest and leave that modified value on the stack, which would cause subsequent moves to use the wrong source location. In the case of ~Move2, this only happened if the size was odd.
Here is a program that demonstrated the problems with both functions:
#pragma memorymodel 1
#include <stdio.h>
struct S1 {
char s[80000];
} a,b,c;
int main(void) {
struct S2 {
int x,y;
char z;
} d,e,f;
c.s[66000] = 123;
f.y = 5678;
a = b = c;
d = e = f;
printf("%i %i %i\n", a.s[66000], b.s[66000], c.s[66000]);
printf("%i %i %i\n", d.y, e.y, f.y);
}
Tabs have been expanded to spaces in several files that use mainly spaces for indentation.
The files ctype.asm, stdio.asm, and string.asm consistently use tabs for indentation. The tabs in these files have been left alone, except that a few tabs between sentences in comments were changed to spaces. One space-indented line in stdio.asm was changed to use a tab.