Commit Graph

36 Commits

Author SHA1 Message Date
Stephen Heumann bf3a4d7ceb Small optimizations in library code.
There should be no functional differences.
2024-02-18 17:35:21 -06: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 cd6131abab Small optimization of strto* functions. 2023-04-03 20:16:22 -05: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 84f471474a Use newer, more efficient ph2/ph4 macros throughout ORCALib.
These push DP values with pei, rather than lda+pha as in the old versions of the macros.
2022-06-30 19:01:47 -05:00
Stephen Heumann 268892b671 Add float and long double versions of functions in SysFloat.
Most of these actually just jump to the existing functions, since they really use extended precision anyway. The exception is the modf functions, which need a separate implementation for each type because they store a value through a pointer to that type.
2021-11-21 14:34:52 -06:00
Stephen Heumann b8605de33f Add a new helper function to record varargs info when va_end is called.
This will be used in conjunction with the new implementation of variable arguments, where they are not removed from the stack until the end of the function.
2021-10-23 21:08:30 -05:00
Stephen Heumann 09942026a8 Add mblen function.
The currently implementation assumes we do not actually support a multi-byte character set for char strings.
2021-09-30 18:38:57 -05:00
Stephen Heumann ee395c371b Update misleading comments that referred to stddef instead of stdlib. 2021-09-02 17:41:31 -05:00
Stephen Heumann 9937ef7003 In system(), avoid depending on the data bank value at entry.
The previous code relied on the data bank value at entry being the bank that contained the library code. This might not be the case when called from code using the large memory model, which could lead to the wrong value being returned.
2021-09-02 17:38:38 -05:00
Stephen Heumann 7e95f8b182 In qsort, make sure to do nothing if count is 0.
Previously, it could behave incorrectly in some cases where count was 0. This would happen if the address calculation &base[-1] wrapped around and produced a large number, either because base was NULL or because size was larger than the address of base.

This fixes #33.
2021-02-25 22:54:32 -06:00
Stephen Heumann 52c011ab48 Implement atoll() function.
This is just a small wrapper around strtoll().
2021-02-17 14:37:54 -06:00
Stephen Heumann 6bf27c6743 Use some improved macros for 64-bit operations in the libraries.
The new m16.int64 file contains a new "negate8" macro (for 64-bit negation), as well as an improved version of "ph8". These have been added to the individual *.macros files, but if those are regenerated, m16.int64 should be used as an input to macgen ahead of m16.ORCA (which contains the original version of ph8).
2021-02-12 20:24:37 -06:00
Stephen Heumann 506f9fa965 Implement strtoll and strtoull (aka strtoimax and strtoumax).
This is a fairly straightforward adaptation of the strtol/strtoul code. The multiplication routine is modified to return the next 16 bits in X so that strtoull can detect overflows.
2021-02-06 14:37:42 -06:00
Stephen Heumann 6635346ae8 Implement llabs and imaxabs functions.
These give the absolute value of 64-bit numbers.
2021-02-06 00:11:44 -06:00
Stephen Heumann b072f5d042 Implement lldiv and imaxdiv functions.
These do 64-bit division and return a struct with the quotient and remainder.
2021-02-05 18:11:37 -06:00
Stephen Heumann 717cf99071 Detect invalid base values in strtol and strtoul.
They will now return 0 and set errno to EINVAL if an invalid base value (anything other than 0 or 2..36) is detected.

This behavior is required by POSIX. It's not required by the C standards (which leave the behavior in this case undefined), but it seems reasonable to do.
2020-02-17 17:39:36 -06:00
Stephen Heumann e5360c9605 Spellcheck comments. 2020-02-16 13:29:53 -06:00
Stephen Heumann 8490da9d85 Allow -2147483648 (LONG_MIN) as valid input to strtol(), not setting errno.
This is what other implementations do and seems to be the intent of the standards, although the wording isn't entirely clear.
2020-01-24 12:25:01 -06:00
Stephen Heumann 14554fcdc7 Make strtol() and strtoul() set the right end pointer in error cases.
Previously, they often did not do this. Now they do, as follows:

If there was a sequence of the expected numeric form, then they fully parse that sequence and give a pointer past the end of it, even if the number was out of range.  If there was not a sequence of the expected form, they give the starting pointer that they were passed in.
2020-01-23 23:47:55 -06:00
Stephen Heumann ebbb5b73ed Allow strtoul to take numbers with a minus sign.
The effect of this is to negate the number in the unsigned long type before returning it.
2020-01-23 21:50:11 -06:00
Stephen Heumann 599c1e3c7b Fix problem where strtol would accept invalid strings like "- +53".
This stemmed from its calling strtoul internally, causing it to accept extra while space and/or + signs. The fix is to have an alternate entry point for strtoul that skips that processing.
2020-01-23 20:42:25 -06:00
Stephen Heumann ee1b7e606d Implement quick_exit() and at_quick_exit() from C11.
Also, make all the exit functions quit via RTL if #pragma rtl was used. This fixes #19.
2020-01-23 18:43:20 -06:00
Stephen Heumann 887d66d537 Implement aligned_alloc function (C11).
This allocates memory with a specified alignment. Currently, the only allowed alignment value is 1.
2020-01-12 18:54:07 -06:00
Stephen Heumann 571c601b66 strtoul: return 0 when given an empty string, as required by the C standards.
The issue was introduced in commit 6e9790667.

errno is now set to EINVAL in this case. (This is not required by the C standards, but is consistent with various other implementations.)

This fixes the cases in #23 related to strtol() and strtoul().
2019-06-16 20:26:13 -05:00
Stephen Heumann 7a20f5f71d strtoul: don't try to parse initial '0x' as hex prefix unless base is 0 or 16.
In other bases, the 'x' either ends parsing of the number string or (in base 34 and larger) is a digit.

Also, ensure only ASCII characters (with high bit clear) are accepted in all situations.
2018-09-13 18:28:02 -05:00
Stephen Heumann 27fc6836cc Fix div() and ldiv() to return properly-signed remainders.
They could previously give the wrong sign on the remainder in certain cases where one or both of the arguments were negative, because they were using the wrong condition to decide whether to negate it.
2018-09-10 17:09:28 -05:00
Stephen Heumann efab82784d Add _Exit() function from C99.
This exits the programs without calling atexit functions and possibly without doing other clean-up operations. In ORCA/C, it is functionally identical to _exit().
2018-09-09 23:23:19 -05:00
Stephen Heumann 6e97906678 Make strtol/strtoul return LONG_MIN/LONG_MAX/ULONG_MAX for out-of-range values.
This fixes #10.

There are still issues with the end pointer value generated in error cases.
2018-03-13 22:11:40 -05:00
Stephen Heumann 7abdfc9beb Make system(NULL) detect whether a command processor is available.
Previously, it just ran an Execute shell call with NULL as the command-line pointer.

The fix is to still call Execute, but with an empty string as the command line, and then check if the call gave an error. If running under plain GS/OS, this gives an error for an unknown system call, whereas both ORCA/APW and GNO shells will return with no error in this case. (Golden Gate doesn't implement the Execute shell call, so it also gives an error and will report no command processor available.)

This fixes issue #25.
2018-03-13 17:49:49 -05:00
Kelvin Sherlock 578bda8439 CR -> LF 2017-10-31 13:14:07 -04:00
mikew50 954c3a02b5 ORCA libraries, from the Opus ][ CD 2017-10-01 18:00:58 -06:00