Commit Graph

212 Commits

Author SHA1 Message Date
Stephen Heumann cd1eabf60c Update version number and README for ORCA/C 2.2.0. 2023-07-16 17:34:54 -05:00
Stephen Heumann 2f79cf3f3a Merge branch 'master' into gno-version 2023-07-03 17:11:05 -05:00
Stephen Heumann 3f70daed7d Remove floating-point code from ORCALib.
It is being moved to SysFloat.
2023-06-23 15:52:46 -05:00
Stephen Heumann a81a9964c2 Change several JMP instructions to BRL.
This avoids the need for run-time relocation and makes executables smaller.
2023-06-19 18:05:46 -05:00
Stephen Heumann a5504be621 scanf: skip remaining directives after encountering EOF.
Encountering EOF is an input failure, which terminates scanf processing. Thus, remaining directives (even %n) should not be processed.
2023-06-11 16:07:19 -05:00
Stephen Heumann 6bc1c3741c scanf: Do not test for EOF at the beginning of scanf processing.
If the format string is empty or contains only %n conversions, then nothing should be read from the stream, so no error should be indicated even if it is at EOF. If a directive does read from the stream and encounter EOF, that will be handled when the directive is processed.

This could cause scanf to pause waiting for input from the console in cases where it should not.
2023-06-11 16:05:12 -05:00
Stephen Heumann 614af65c68 printf: print inf/nan rather than INF/NAN when using f and a formats.
This works in conjunction with SysFloat commit e409ecd4717, and at least that version of SysFloat is now required.
2023-06-01 20:10:12 -05:00
Stephen Heumann b21a51ba33 Optimize lgamma.
This includes adjustments that make it a little faster for most input values, but especially for |x| < 7. The impact on accuracy should be minimal.
2023-05-22 18:05:15 -05:00
Stephen Heumann 97a295522c Implement lgamma (C99).
This uses an approximation based on the Stirling series for most positive values, but uses separate rational approximations for greater accuracy near 1 and 2. A reflection formula is used for negative values.
2023-05-21 18:24:01 -05:00
Stephen Heumann afff478793 More small size optimizations for (f)printf. 2023-04-18 22:27:49 -05:00
Stephen Heumann 78a9e1d93b printf: Unify code for hex and octal formatting.
These are similar enough that they can use the same code with just a few conditionals, which saves space.

(This same code can also be used for binary when that is added.)
2023-04-17 21:52:26 -05:00
Stephen Heumann 67ae5f7b44 printf: optimize hex and octal printing code.
This also fixes a bug: printf("%#.0o\n", 0) should print "0", rather than nothing.
2023-04-17 19:36:45 -05:00
Stephen Heumann 80c0bbc32b Small size optimizations in printf code. 2023-04-16 22:14:15 -05:00
Stephen Heumann 34f78fb1f2 printf: add support for 'a'/'A' conversion specifiers (C99).
These print a floating-point number in a hexadecimal format, with several variations based on the conversion specification:

Upper or lower case letters (%A or %a)
Number of digits after decimal point (precision)
Use + sign for positive numbers? (+ flag)
Use leading space for positive numbers (space flag)
Include decimal point when there are no more digits? (# flag)
Pad with leading zeros after 0x? (0 flag)

If no precision is given, enough digits are printed to represent the value exactly. Otherwise, the value is correctly rounded based on the rounding mode.
2023-04-16 20:23:53 -05:00
Stephen Heumann 578e544174 Update comments about printf. 2023-04-16 15:41:00 -05:00
Stephen Heumann b7b4182cd2 printf: ignore '0' flag if '-' is also used.
This is what the standards require. Previously, the '0' flag would effectively override '-'.

Here is a program that demonstrates the problem:

#include <stdio.h>
int main(void) {
        printf("|%-020d|\n", 123);
        printf("|%0-20d|\n", 123);
        printf("|%0*d|\n", -20, 123);
}
2023-04-16 15:39:49 -05:00
Stephen Heumann b6bab6df80 Update ORCA/C version number to 2.2.0 B7. 2023-04-06 15:55:09 -05:00
Stephen Heumann 14121f55b6 Merge branch 'master' into gno-version 2023-04-06 15:54:40 -05:00
Stephen Heumann bdfed3628d Fix fma to support large memory model.
It was not using long addressing where needed, so it could store results in the wrong bank.
2023-04-06 14:34:40 -05:00
Stephen Heumann 2f2d3d2056 Save a few bytes in floating-to-long long conversion code. 2023-04-04 18:06:21 -05:00
Stephen Heumann cd6131abab Small optimization of strto* functions. 2023-04-03 20:16:22 -05:00
Stephen Heumann fca8c1ef85 Save a few bytes in printf and scanf. 2023-04-03 13:26:37 -05:00
Stephen Heumann de978dab48 Use more efficient code to return values from various math functions. 2023-04-02 16:33:24 -05:00
Stephen Heumann 68fc475721 Implement fma().
This tries to carefully follow the C and IEEE standards regarding rounding, exceptions, etc. Like the other ORCA/C <math.h> functions, there is really just one version that has extended precision, so double rounding is still possible if the result gets assigned to a float or double variable.

In addition to the tests I added to the ORCA/C test suite, I have also tested this against (somewhat modified versions of) the following:

*FreeBSD fma tests by David Schultz:
https://github.com/freebsd/freebsd-src/blob/release/9.3.0/tools/regression/lib/msun/test-fma.c

*Tests by Bruno Haible, in the Gnulib test suite and attached to this bug report:
https://sourceware.org/bugzilla/show_bug.cgi?id=13304
2023-04-02 16:30:29 -05:00
Stephen Heumann 3c1f357b0c Save a few bytes in the startup code. 2023-03-28 21:38:55 -05:00
Stephen Heumann a4ba2403fe Call atexit functions with correct data bank in large memory model
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.
2023-03-28 18:52:14 -05:00
Stephen Heumann 48371dc669 tmpnam: allow slightly longer temp directory name
ORCA/C's tmpnam() implementation is designed to use prefix 3 if it is defined and the path is sufficiently short. I think it was intended to allow up to a 15-character disk name to be specified, but it used a GS/OS result buffer size of 16, which only leaves 12 characters for the path, including initial and terminal : characters. As such, only up to a 10-character disk name could be used. This patch increases the specified buffer size to 21, allowing for a 17-character path that can encompass a 15-character disk name.
2023-03-08 18:59:10 -06:00
Stephen Heumann b03e462125 bsearch: return NULL without calling compare function if count==0.
This is explicitly required in C99 and later.
2023-02-17 20:31:55 -06:00
Stephen Heumann b3f028da2f Avoid address comparison error in qsort.
If the last element in the range being sorted has the smallest value, rsort can be called with last set to first-1, i.e. pointing to (what would be) the element before the first one. But with large enough element sizes and appropriate address values, this address computation can wrap around and produce a negative value for last. We need to treat such a value as being less than first, so it terminates that branch of the recursive computation. Previously, we were doing an unsigned comparison, so such a last value would be treated as greater than first and would lead to improper behavior including memory trashing.

Here is an example program that can show this (depending on memory layout):

#pragma memorymodel 1
#include <stdlib.h>
#include <stdio.h>

#define PADSIZE 2000000 /* may need to adjust based on memory size/layout */
#define N 2

struct big {
        int i;
        char pad[PADSIZE];
};

int cmp(const void *p1, const void *p2) {
        int a = ((struct big *)p1)->i;
        int b = ((struct big *)p2)->i;

        return (a < b) ? -1 : (a > b);
}

int main(void) {
        int j;
        struct big *p = malloc(sizeof(struct big) * N);
        if (!p)
                return 0;

        for (j = 0; j < N; j++) {
                p[j].i = N-j;
        }

        qsort(p, N, sizeof(struct big), cmp);

        for (j = 0; j < N; j++) {
                printf("%i\n", p[j].i);
        }
}
2023-02-16 18:45:03 -06:00
Stephen Heumann 2540b28ca3 Avoid excessively deep recursion in qsort.
It could have O(n) recursion depth for some inputs (e.g. if already sorted or reverse sorted), which could easily cause stack overflows.

Now, recursion is only used for the smaller of the two subarrays at each step, so the maximum recursion depth is bounded to log2(n).
2023-02-15 22:04:10 -06:00
Stephen Heumann 3417a98d10 Use proper data bank when calling comparison function in qsort.
When using the large memory model, the wrong data bank (that of the library code rather than the program's static data) would be in place when the comparison function was called, potentially leading to data corruption or other incorrect behavior.
2023-02-15 18:46:46 -06:00
Stephen Heumann 60d49c7dc3 Fix qsort code for swapping elements with a size of 64KiB or more.
This code did not previously work properly, because the X register value was overwritten within the loop. This could result in incorrect behavior such as hanging or data corruption when using qsort with element sizes >= 64KiB.
2023-02-14 18:43:40 -06:00
Stephen Heumann 74de206058 Add library function for null pointer checking.
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.
2023-02-12 18:57:56 -06:00
Stephen Heumann 3551644355 Fix stack handling in localtime.
This was broken by commit 882af9e075.
2023-01-05 20:00:44 -06:00
Stephen Heumann 506b070439 Rename CVars to ~CVars to avoid namespace pollution. 2023-01-02 18:41:45 -06:00
Stephen Heumann 69765a96ef Use a variable to control use of Time Tool.
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.
2023-01-02 18:01:28 -06:00
Stephen Heumann c4d485e960 Implement timespec_get (C11).
This follows gmtime in using the Time Tool to get UTC time if it is active, but otherwise just using local time.
2023-01-01 21:33:00 -06:00
Stephen Heumann 44c3078ab3 mktime: force struct tm components to their normal ranges.
This is done by calling ~gmlocaltime after computing the time_t value in mktime.
2022-12-31 22:06:25 -06:00
Stephen Heumann 7e4f067c35 Compute tm_yday and tm_wday directly in ~gmlocaltime.
This avoids calling mktime (future versions of which may call ~gmlocaltime), and also deals correctly with time zones.
2022-12-31 19:10:36 -06:00
Stephen Heumann 882af9e075 Make gmlocaltime take a parameter for the struct tm to use.
This will be needed for gmtime_r/localtime_r, but also is a step toward using this code to normalize the struct tm values for mktime.
2022-12-30 18:46:51 -06:00
Stephen Heumann 3b0c1c2149 Fix gmtime() handling of times very near the limits of time_t.
The UTC time may be several hours before or after local time, and therefore the UTC time/date may be slightly outside the limits of what can be represented as a local time/date. This is now handled correctly.

This also more generally fixes handling of negative seconds/minutes/hours, which is also applicable to mktime().
2022-12-30 17:28:16 -06:00
Stephen Heumann 32c5fd94a1 Handle out-of-range months in mktime() input. 2022-12-29 23:54:10 -06:00
Stephen Heumann f15caf8096 Make gmtime/localtime properly support times near the limits of the time_t range.
They did not properly handle times in 1969 or 2105 (for the latter, they would infinite-loop).
2022-12-29 23:18:48 -06:00
Stephen Heumann b302a85fd6 Switch time "factor" code over to 0-based month indexing.
This matches both struct tm and ReadTimeHex, so it avoids needing to increment the values.

Also, simplify the time() code a little bit.
2022-12-29 22:53:37 -06:00
Stephen Heumann 17faeda1de Rework time "factor" routine to work for the full 32-bit time range.
ORCA/C uses an unsigned 32-bit time_t which should give a range up to 2105, but calculations on it were being done with signed types, causing them not to work correctly beyond 2036-2038. Now the factor routine, mktime(), and time() should work up to 2105. (In the case of time(), this assumes ReadTimeHex reports the time correctly.)

The factor routine actually computes a 64-bit time value. Currently, the rest of the code only takes the bottom 32 bits of it, but this could be extended if we ever wanted to switch to 64-bit time_t.
2022-12-29 22:31:31 -06:00
Stephen Heumann d30ee1a2e5 Adjust comments in time.asm to reflect actual starting date of time_t.
It was clearly supposed to be 1 Jan 1970, but it's actually not, probably because the number of days from 1 Jan 1900 to 1 Jan 1970 was miscalculated. Changing it now could potentially cause compatibility issues (especially for GNO, which uses time_t in some kernel call interfaces and file formats), so for now it is left as is and just documented appropriately.

Nothing in the C standards requires the time_t epoch to be 1 Jan 1970, so this does not cause any standards-compliance problem for the C standards. (It is different from POSIX, though.)
2022-12-29 14:25:24 -06:00
Stephen Heumann e2de990f4d strftime: use Time Tool Set to get time zone offset.
This is used for the %z conversion specifier (giving the time zone offset in +-HHMM format). The %Z conversion specifier (giving the locale's time zone name or abbreviation) also prints the same thing for now.

As with gmtime, this will only use the Time Tool Set if it has already been started. Otherwise, these conversions simply produce no output.
2022-12-28 19:55:48 -06:00
Stephen Heumann 4019e9f370 gmtime: support time zone adjustment with Time Tool Set.
If the Time Tool Set (tool 56, by Geoff Weiss) is present and active, gmtime will use it (plus the DST flag) to determine the local time offset from UTC, allowing it to produce the correct UTC time. If not, it will still treat local time as being equal to UTC, like it did previously.

The library code will not try to load or start the Time Tool Set, so the program will have to do that before calling gmtime if it wants to use this functionality.
2022-12-28 19:46:49 -06:00
Stephen Heumann 89664d2921 Slightly improve tgamma calculation for x < 8.
Previously, 1-4 low-order bits of the input value were essentially ignored when calculating the numerator, but used to some degree when calculating the denominator. This would lead to the calculated tgamma values decreasing slightly over the range of several consecutive input values (when they should increase). Now, the low-order bits of the input value are effectively just rounded away. This should give slightly more accurate results, and greatly reduces the frequency of cases where consecutive output values go in the wrong direction.
2022-12-24 21:59:52 -06:00
Stephen Heumann 5985e7d774 Implement tgamma (c99).
This uses an approximation based on the Stirling series for large enough x (for which it is highly accurate). For smaller x, identities are used to express gamma(x) in terms of gamma(x+1) or gamma(1-x), ultimately letting the Stirling series approximation be used.
2022-12-24 20:20:40 -06:00