Commit Graph

207 Commits

Author SHA1 Message Date
Stephen Heumann c025bba177 Implement nearbyint and fdim. 2021-11-22 19:25:25 -06:00
Stephen Heumann 2334443437 Implement scalbln.
This differs from scalbn in that the exponent has type long. When scaling an extended value, exponents slightly outside the range of int can actually be used meaningfully. We address this by doing multiple SCALBX calls (at most 2) in a loop.
2021-11-21 20:10:36 -06: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 3ec8a8797f Implement some of the math functions added in C99.
The functions implemented so far are largely the ones that map (nearly) directly to SANE calls.

Note that C99 specifies separate float/double/long double versions of each of these functions, but under ORCA/C they generally use the same code.
2021-11-20 19:24:51 -06:00
Stephen Heumann fb5683a14d Add a function to implement the FP comparison macros in <math.h>.
These macros differ from the normal comparison operators in that they will not signal invalid due to the operands being unordered. However, this implementation will still signal invalid for SNaNs. That is clearly OK according to the wording in draft C23. C17 and earlier do not mention that possibility, but they do not really specify the behavior of SNaNs in general.
2021-11-02 21:56:30 -05: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 e3c9bc96bc Add implementation of the <uchar.h> functions. 2021-10-03 16:02:30 -05:00
Stephen Heumann ae504c6e4f Add support for EILSEQ errno value.
EILSEQ is required by C95 and later.
2021-10-02 14:34:35 -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 3a847d245e Add strcoll and strxfrm functions.
This is currently a minimalistic implementation in which strcoll always sorts strings the same way as strcmp.
2021-09-30 18:37:54 -05:00
Stephen Heumann 512fadeff0 Add an implementation of the <locale.h> functions.
This is currently a minimalistic implementation, which only supports the C locale.
2021-09-30 18:34:54 -05:00
Stephen Heumann 5ad86f4a0b Implement strftime.
This is intended to be a complete implementation of strftime as specified in C17, although it lacks meaningful support for time zones or non-C locales.
2021-09-26 20:31:15 -05:00
Stephen Heumann 379f2f93ad Fix bug causing data corruption when assigning to multiple structs.
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);
}
2021-09-17 18:25:32 -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 869f8726a6 Add __assert2 function to include the function name when reporting assertion failures.
This is required by C99 and later.

The old __assert function is retained for compatibility with existing object code.
2021-08-24 18:21:39 -05:00
Stephen Heumann 690ee7137f Add a function to get the proper value of CLOCKS_PER_SEC.
This may be either 50 or 60, depending on the system's video frequency setting (50Hz PAL or 60Hz NTSC). The video setting can be determined by inspecting bit 4 of the LANGSEL soft switch, documented in Appendix E of the Apple IIGS Firmware Reference.
2021-08-23 19:00:09 -05:00
Stephen Heumann 79201198a1 Fix a bug in memset.
If the upper byte of the int argument was nonzero, it could write the wrong value (the OR of the upper and lower bytes). It should convert the value to unsigned char, i.e. just use the lower byte.
2021-03-10 20:08:36 -06:00
Stephen Heumann 9e727697d3 Add a helper function to get the sign bit. 2021-03-09 00:24:26 -06:00
Stephen Heumann 98cfd4e831 Add floating-point number classification functions.
These are the internal routines used by the fpclassify() macro.
2021-03-08 23:44:44 -06:00
Stephen Heumann 07959d32eb Add new routines to reduce the precision of floating-point numbers.
These will now be used to implement explicit floating-point casts.
2021-03-06 22:21:52 -06:00
Stephen Heumann 0685ce71ca Add an implementation of <fenv.h> to ORCALib. 2021-03-06 16:29:02 -06: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 9af245933c Change long long printing routine to a new technique not using division.
The core loop uses the 65816's decimal mode to create a BCD representation of the number, then we convert that to ASCII to print it. The idea is based on some code from Kent Dickey, with adjustments to fit this codebase. This technique should be faster, and also should typically result in smaller code, since the long long division routine will not need to be linked into every program that uses printf.
2021-02-21 18:33:04 -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 f9d7017687 Add real to long long conversion routines.
For conversion to signed long long, we can almost just use SANE's FX2C call to convert it to comp. But LLONG_MIN corresponds to the bit pattern of the comp NaN, so it has to be treated specially. (You might think SANE would return the comp NaN when converting out-of-range values, which would give the value we want, but somewhat strangely it does not.)

For conversion to unsigned long long, we check if the value is greater than LLONG_MAX (which is also the max comp value). If so, we subtract LLONG_MAX+1 from the floating-point value before conversion and add it back in to the integer afterward.
2021-02-16 18:44:38 -06:00
Stephen Heumann 81e152f863 Add a comparison routine for signed 64-bit numbers.
This is almost the same as ~CMP8 in SysLib, except that it does not use a static location to save the DP. This makes it slightly smaller/faster, and also makes it thread/interrupt safe.
2021-02-15 18:06: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 91f0dcbdb9 Optimize 64-bit unsigned shifts.
They now try to shift 16 bits at a time and only go bit-by-bit for the last 15 or fewer bit positions.
2021-02-12 15:58:27 -06:00
Stephen Heumann 7ad54827a3 Add 64-bit shift routines. 2021-02-12 15:05:23 -06:00
Stephen Heumann a5d0172d82 Add signed/unsigned long long to SANE extended conversion routines.
SANE does not have built in operations for this, but all the values are exactly representable in the SANE extended format, so we just do the conversion ourselves based on the definition of the extended format.
2021-02-11 12:41:36 -06:00
Stephen Heumann c185face85 Add long long support for printf d/i/u conversions.
At this point, the long long support for the printf and scanf families of functions is complete.
2021-02-10 17:51:23 -06:00
Stephen Heumann 4f9b41938a Implement vscanf/vfscanf/vsscanf (from C99).
These are equivalent to the existing scanf calls, except that they use variable arguments from a va_list.
2021-02-09 22:09:00 -06:00
Stephen Heumann cfc3fd3468 scanf: if %c gets some characters but < field width, it's a matching failure.
EOF should not be returned in this case.

I think it shouldn't actually write anything to the destination in this case, but it currently does. That problem remains unfixed for the moment; addressing it would require us to have our own internal buffer.
2021-02-09 16:03:19 -06:00
Stephen Heumann 6626aad7f0 scanf: report EOF for 's' conversions, is appropriate.
They should be treated as input failures if they got EOF before finding a non-whitespace character.
2021-02-09 15:44:39 -06:00
Stephen Heumann bc21593507 scanf: 's' and '[' conversions should "put back" EOF if it is encountered.
This ensures that a subsequent %n conversion reports the right number of characters actually read (not including EOF).
2021-02-09 15:31:19 -06:00
Stephen Heumann 375d664ae1 Recognize 'L' as a length modifier for scanf.
Conversions using it will not actually work right yet (unless assignment is suppressed), because the necessary changes have not been made in SysFloat, but the infrastructure is now in place to allow for those changes.
2021-02-09 14:32:37 -06:00
Stephen Heumann 2f68708b47 scanf: Report EOF for o/u/x conversions, if appropriate.
This was not being reported unless assignment was suppressed, because the "sta ~eofFound" instruction was too late.

(Found based on test cases by Rich Felker.)
2021-02-09 13:14:24 -06:00
Stephen Heumann 66e1835175 scanf could trash a word of the caller's stack if it did not perform all possible assignments.
Code in ~scanf would call ~RemoveWord to remove the extra parameters, but ~RemoveWord is designed to be called from one of the ~Scan_... subroutines, which is (in effect) called by JSR and thus has an extra word on the stack for its return address. This stack misalignment caused ~RemoveWord to overwrite a word of the caller's stack when called from the code to remove extra parameters.

This could cause a crash in the following program:

#include <stdio.h>
void f(void) {
    int a,b;
    sscanf("Z", "%i%i", &a, &b);
}
int main(void) {
    f();
}
2021-02-09 13:09:04 -06:00
Stephen Heumann 61bfc70b9b scanf: for 'i' or 'd' specifiers, count a leading sign toward the field width. 2021-02-09 00:40:24 -06:00
Stephen Heumann de9f830c0c scanf: when an ordinary character cannot match due to EOF, flag an input failure.
This may cause scanf to return EOF, if no conversions have been done.

This seems to be the intent of the C standards, although the wording could be clearer. It is also consistent with all the other implementations I tested.
2021-02-08 00:19:23 -06:00
Stephen Heumann 23a27bd434 scanf: accept leading whitespace in a %% conversion.
The C standards say this should be accepted.
2021-02-08 00:08:45 -06:00
Stephen Heumann 539707344a scanf: a sign and/or 0x prefix with no following digits should be a matching failure.
This applies to + or - signs for 'd' or 'i' conversions, and to '0x' or '0X' prefixes for 'i' and 'x' conversions. (The new support for signs on u/o/x conversions did not have the problem.)

These cases were treated as if they successfully matched a number, but now they are correctly treated as a failure, causing no assignment to be done and causing the function to return without processing any further directives.

(Incidentally, the handling of '0x' without following digits is something that differs in modern C libraries: macOS libc, glibc, and musl are all different. Our new behavior should match that of musl, which I believe is what is correct under the C standards.)
2021-02-07 21:57:53 -06:00
Stephen Heumann 3ef9687b7e scanf: allow u/o/x conversions to match numbers with a leading sign.
The C standards say this should be allowed.
2021-02-07 18:45:52 -06:00
Stephen Heumann aa1351f84d Add support for long long in scanf.
The 'll' length modifier is now fully supported for the d, i, o, u, x, and X conversion specifiers. The 'n' conversion specifier can also store to a long long, but the value is still limited to 64k. The 'j' length modifier (for intmax_t) is also now treated as specifying a 64-bit value.
2021-02-07 08:35:18 -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 d1d0358e4b Add 64-bit division routines.
The ~CDIV8 routine is the same as ~DIV8 in SysLib, except that it negates the remainder if the numerator is negative. This complies with the definition of the % operator in C, which gives negative (or 0) remainders if the numerator is negative, such that (a/b)*b + a%b equals a.

The ~UDIV8 routine is an unsigned version, using the same core division loop but without the sign handling.
2021-02-05 12:42:22 -06:00
Stephen Heumann 2bb5361c24 Add a new file for 64-bit integer routines, initially with an unsigned multiply.
This file will be expanded with more support routines as needed.

The unsigned multiply routine uses the core multiplication loop from the 64-bit signed multiply routine in SysLib, with new entry/exit code for the unsigned version.
2021-02-04 23:58:54 -06:00