Commit Graph

196 Commits

Author SHA1 Message Date
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
508d0266a0 Update README.GNO file. 2021-02-26 22:21:58 -06:00
Stephen Heumann
d92183ad41 Update version number in rVersion resource. 2021-02-26 21:25:52 -06:00
Stephen Heumann
14c7a1186c Update GNO version makefile to include int64.asm. 2021-02-26 21:22:53 -06:00
Stephen Heumann
fffeef1206 Merge branch 'master' into gno-version 2021-02-26 21:20:39 -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
Stephen Heumann
80dbf0c34c printf/scanf: Add 'P' conversion specifier as a synonym for 'b'.
The 'b' conversion specifier is an ORCA extension to support p-strings, but lower case letters are reserved for use in future C standards, and in fact C23 is likely to use 'b' for integers in binary notation. For the time being, 'b' is still supported with its existing meaning, but it is considered deprecated. It may be removed in the future if we want to support the C23 behavior. Upper-case letters are available to use for extensions, so 'P' should remain available for our use.
2021-01-30 19:53:50 -06:00
Stephen Heumann
bd1e822a43 printf: In d/i/o/u/x/X conversions with a precision specified, the 0 flag should be ignored.
For example, the output of the following should have only two leading zeros (and the rest of the field width padded with spaces):

#include <stdio.h>

int main(void) {
        printf("%016.5i\n", 123);
}
2021-01-30 17:51:55 -06:00
Stephen Heumann
7c4141f03d printf: properly handle negative field width or precision arguments.
If the field width is given by an argument (when * is used in the format specification) and the value given is negative, it should be treated like a positive field width with the - flag. If a negative argument is given for the precision, it should be treated as if the precision was not specified.

The following is an example of code that behaved incorrectly:

#include <stdio.h>
int main(void) {
        printf("%*iXX\n", -50, 123);
}
2021-01-30 16:55:27 -06:00
Stephen Heumann
71a25f0fef printf: %#x or %#X conversions should not print the 0x/0X prefix if the value is 0.
This is the behavior specified in all versions of the C standards.
2021-01-30 16:04:18 -06:00
Stephen Heumann
37c38a7077 Add partial support for 64-bit 'long long' types in printf.
Currently, it works as follows:
*The 'll' length modifier is recognized. 'j' (for intmax_t) is also now treated as denoting a 64-bit type.
*The 'x', 'X', and 'o' format specifiers have full support for 64-bit types.
*The 'n' format specifier can write a 64-bit integer, but only actually supports values up to 64k.
*The 'd', 'i', and 'u' format specifiers can consume a 64-bit value, but they only print it correctly if it is within the range of 32-bit long/unsigned long.
2021-01-30 14:41:07 -06:00
Stephen Heumann
7566fffb6c Add readme describing GNO version of ORCALib. 2020-02-19 12:49:29 -06:00
Stephen Heumann
f906cac5f9 Update the version in the resource fork.
This is now an ORCA/C version number, rather than a GNO version number.
2020-02-19 12:47:16 -06:00
Stephen Heumann
3145f4b023 Merge branch 'master' into gno-version.
The includes all the changes through the version in ORCA/C 2.2.0 B4, plus a small POSIX conformance tweak in strtol/strtoul.

# Conflicts:
#	assert.asm
#	cc.asm
#	ctype.asm
#	string.asm
#	vars.asm
2020-02-19 12:43:57 -06:00
Stephen Heumann
97c3ecad73 ORCALib changes for GNO.
This is a reconstruction of the ORCALib source changes for the version of ORCALib distributed with GNO 2.0.6. The library built with this code should be identical to the original GNO one, apart from insignificant junk bytes at the ends of segments and the build date in the resource fork.
2020-02-19 12:19:41 -06:00
Stephen Heumann
e9de42d6c4 fopen: do not require read access when opening a file for append only.
This can cause an error if the file's permissions deny read access.
2020-02-17 19:49:18 -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
573bc6efa9 Use consistent indentation within files.
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.
2020-02-16 13:28:18 -06:00
Stephen Heumann
44dfc1d1d6 Prevent localtime() from potentially giving incorrect tm_isdst values.
This could happen when it was called for a time other than the present, because it set tm_isdst based on the current value of the DST flag in BRAM, which is valid only for the current time.

Now it works as follows: If localtime() is passed the time_t value that was produced by the most recent call to time(), it gives the DST setting in effect at the time of that call.  Otherwise, it sets tm_isdst to -1, indicating that the correct value is unknown.

This is about the best we can do without having a full timezone library/database. It should give the right tm_isdst value in probably the most common case, and avoids giving an incorrect value in any case (assuming the system's DST flag is right).

This fixes #18.
2020-02-02 12:52:42 -06:00
Stephen Heumann
9af1c093cb Ensure tmpfile() doesn't access a file created by someone else.
This could happen due to a race condition, which shouldn't generally be an issue on the GS but is at least theoretically possible under GNO or Golden Gate.
2020-01-31 12:47:34 -06:00