ORCA/C 2.2.0 B5 Copyright 1997, Byte Works Inc. Updated by Stephen Heumann and Kelvin Sherlock, 2017-2021 -- Change List -------------------------------------------------------------- 2.2.0 B5 1. Bugs squashed. See bug notes, below. 2. New language features added (mainly features from C99 and C11). See "New Language Features," below. 3. Some optimization passes have small improvements. 4. Some internal size limits were raised, allowing compilation of larger functions. 5. Certain errors that were previously ignored are now detected. 6. New option added to generate inline function names for use with assembly-level debugging tools. See "Inline Function Names." 7. Some new headers specified by recent C standards are added. See "New Headers." 8. Several new #pragma ignore bits are defined. See "Additions to #pragma ignore." 9. Several new #pragma lint bits are defined. Also, messages from #pragma lint can now optionally be treated as warnings rather than errors. See "Enhancements to #pragma lint." 10. Stack repair code is now more efficient. 11. Some new library functions and features from C99 and C11 have been added. See "Library Updates." 12. Floating-point constant expressions now use extended precision. See "Evaluation of Floating-Point Expressions and Constants." 2.1.1 B3 1. Bugs squashed. See bug notes, below. 2.1.0 1. Bugs squashed. See bug notes, below. 2. New bit added for vararg stack repair removal. See #pragma optimize, below. 3. There have been several changes to assert(). See the Manual Errata for page 343 for details. 4. C supports the extended character set. See "Extended Characters." 5. You can create defaults that are used in all of your C programs using the new defaults.h file. See "The Default .h File." 6. ORCA/C supports // comments. See "// Comments." 2.0.3 1. Bugs squashed. See bug notes, below. 2.0.2 1. Bugs squashed. See bug notes, below. 2.0.1 1. Bugs squashed. See bug notes, below. -- Known Issues ------------------------------------------------------------- 1. ORCA/C fails to detect various error conditions for which the C standards require a diagnostic message to be issued. -- Manual Errata ------------------------------------------------------------ p. 40 The description of the action function says it takes a single integer parameter. Actually, it takes two parameters, as shown in the example on page 41. Both the description and the sample on page 41 indicate that the action procedure for an NDA should return void. Actually, the action routine should return int, returning 1 if it handled the action and 0 if it did not. The correct function looks like this: int Action (long param, int code) { int handledEvent = 0; <<>> return handledEvent; } The description of the init function doesn't point out some important limitations. When this call is made at shutdown time, your NDA has already been placed in a dormant state, and all RAM has been deallocated. (This happened when the close function was called.) If you need dynamic memory for any purpose, be sure you obtain a valid user ID, and that you dispose of the memory after you are finished with it. Do not rely on C memory management functions at shutdown time. Static variables are safe, though, and can be used to pass information to the init function for use at shutdown time. p. 67 Delete the paragraph starting "One important point is that you should never reinitialize the Text Tool Set. ..." ORCA/C no longer uses the Text Tool Set for routine input and output, and definitely does not use it for I/O redirection. p. 100 The text does not mention the sixth default character. It is not used by PRIZM, though. For details on the 6th default character (as well as the 5th) see page 193, where their use by the text based editor is described. p. 101 The sample SYSTABS line at the top of the page should start 8 100110 p. 107 The table shows the language number for C as 7. It should be 8. p. 233 Identifiers may now contain universal character names, a type of escape sequence that can denote a Unicode character. See "New Language Features," below. Several new reserved words (keywords) added in the C99 or C11 standards are now supported. For information on what these are and how they are used, see "New Language Features," below. Certain alternate reserved symbols known as digraphs are now supported. See "New Language Features," below. p. 237 ORCA/C now supports character constants containing multiple characters. See "Multi-Character Character Constants," below. p. 238 The limit on the total length of string constants in a single function has been raised to 12500 characters. p. 239 String and character constants may now contain universal character names, a type of escape sequence that can denote a Unicode character. See "New Language Features," below. p. 240 The discussion of escape sequences states that hexadecimal numeric escape sequences can contain from one to three digits. This was true until ORCA/C 2.1, when the compiler was changed to respect the ANSI C standard. The compiler will now scan a hexadecimal escape sequence until no more hexadecimal characters are found. (ORCA/C 2.1 would also scan an octal escape sequence until no more octal characters were found, but this has been changed back to limit octal escape sequences to at most three octal digits, as required by the C standards.) The value of an octal or hexadecimal escape sequence must be within the range of representable character values (0-255). Also, \ may not be followed by a character other than one of the ones described as forming an escape sequence. ORCA/C now gives an error in these cases. Accordingly, the examples of "\410" and '\g' mentioned in the manual are now treated as errors. p. 241 The 'f', 'F', 'l', or 'L' suffixes on floating-point constants do now affect the semantic type of those constants, although they do not change the constant's precision or range (which are always those of the SANE extended format). ORCA/C now supports // comments. See "// Comments," below. p. 247 The predefined macros __STDC__ and __ORCAC__ expand to the integer constant 1, not -1. ORCA/C now supports several new predefined macros. See "New Language Features," below. p. 250 Several things are listed that will cause a .sym file to stop or not be built at all. Add to this list a #append, which does not work like a #include. It's worth keeping in mind that #append in included in ORCA/C solely for the purpose of appending files of a different language. There are several advantages to using #append to tack assembly language source to the end of a C source file, but there is no other place in ORCA/C where a #append is more useful than a #include. p. 254 The #error directive may be followed by any sequence of preprocessing tokens, not just a string constant. p. 256 The #pragma debug directive supports a new bit. If bit 15 is set, ORCA/C generates inline function names for use with assembly-level debugging tools. See "Inline Function Names," below. p. 257 The #pragma expand directive has been changed to use three-digit octal escape sequences (rather than hexadecimal ones) in strings it outputs. (This ensures that subsequent characters in the string cannot be interpreted as part of the escape sequence.) p. 258 The #pragma ignore directive supports several new bits. Bit 1 affects the interpretation of multi-character character constants. See "Multi-Character Character Constants," below. Bit 2 controls whether spurious tokens are allowed after an #endif directive. See "Additions to #pragma ignore," below. Bit 3 controls whether // comments are allowed. If bit 3 is set, as in #pragma ignore 0x0008 ORCA/C supports // comments. If bit 3 is clear, ORCA/C does not support // comments, which are not actually allowed in ANSI C89 programs. See "// Comments," below, for a complete description of // comments. Bit 4 controls whether C99-style scope rules are followed and whether mixed statements and declarations are allowed in blocks. See "New Language Features," below. Bit 5 controls whether type compatibility checks should strictly follow the C standards, or whether looser rules should be used in certain cases. See "Additions to #pragma ignore," below. p. 259 The #pragma lint directive can now optionally treat messages from lint checks as warnings rather than errors. In addition, several new types of lint checks are now available. For details, see "Enhancements to #pragma lint," below. p. 263 1. The discussion of NDAs is on page 40, not page 58. 2. There is a new optimization bit for #pragma optimize. See #pragma optimize, below. p. 269 The 64-bit integer types long long and unsigned long long are now supported. So is the type _Bool, a boolean type that can hold the values 0 or 1. See "New Language Features," below. p. 275 Several new declaration specifiers from C99 and C11 are now supported. For details, see "New Language Features," below. p. 277 The type "long double" now specifies a number in the SANE extended format. p. 289 Unions can be initialized by a brace-enclosed expression giving the initializer value for the first element of the union, or by an expression of the appropriate union type. The non-standard construct of initializing the first element of a union with a non-brace-enclosed initializer is no longer supported. The supported alternative is simply to enclose the initializer in braces, e.g. union nums {float f; int i;} x = {0.0}; p. 311 If integer overflow occurs during signed integer multiplication, the resulting value is not predictable. Contrary to what the description in the manual implies, it will not necessarily be the low-order bits from the true product of the operands. p. 321 The unary conversion rules have been modified to convert values of type char or unsigned char to int (rather than unsigned int), as required by the C standards. Also, they do not change the semantic type of float or double values. In the binary conversions, if either operand has a floating-point type, the semantic type is the largest floating-point type of either operand. However, floating-point operations are always evaluated with the range and precision of the SANE extended format. p. 337 The ORCA/C compiler is intended as a faithful implementation of ANSI C with some extensions, but there have always been some library functions from ANSI C that were missing in ORCA/C. Chapter 19 should start with a summary of these omissions. They are: locale.h This header file is missing completely, along with all of its functions. stdlib.h The functions mblen(), mbstowcs(), mbtowc(), wcstombs() and wctomb() are missing. These are related to locale.h. string.h strcoll() and strxfrm() are missing. These are related to locale.h. time.h The function strftime() is missing. p. 342 Several new standard library functions from C99 and C11 are now provided. See "Library Updates," below. All the functions in that are specified as having argument or return types of extended actually use the type double. However, the values passed to and returned from them still have the range and precision of the extended type. p. 343 The documentation states that assert() uses exit(-1) to exit a program. Actually, it uses abort(). Beginning with ORCA/C 2.1, assert() prints a string that includes the assertion itself, not just the line number and file name. Beginning with ORCA/C 2.2.0 B5, it also includes the name of the enclosing function. The assertion has the form Assertion failed: file :hd:foo.cc, line 47, function fn; assertion: bar==1 The documentation states assert() writes to stdout. Beginning with ORCA/C 2.1, it writes to stderr. p. 344 The atexit() function actually returns zero if the function is registered successfully, and a non-zero value if there is not enough memory to satisfy the request (the reverse of what the manual says). p. 348 The discussion of clock() should mention the standard macro CLOCKS_PER_SEC, which gives the number of clock ticks per second. The CLK_TCK macro also gives the same value, but it is non-standard and should be considered deprecated. Also, CLOCKS_PER_SEC and CLK_TCK may be either 50 or 60, depending on the system's video frequency setting; they now expand to code that will detect the setting and give the appropriate value. p. 353 The discussion of _exit() should note that the _exit() function is an extension to ANSI C. p. 354 The discussion of abort() should note that it will call raise(SIGABRT) before exiting. Accordingly, if a SIGABRT handler was previously registered via a call to signal(), it will be executed. p. 356 The fprintf() family of functions has been updated to support several new features specified by C99. Also, the snprintf() and vsnprintf() functions have been added. See "Library Updates," below. p. 367 The fscanf() family of functions has been updated to support several new features specified by C99. Also, the vscanf() family of functions have been added. See "Library Updates," below. p. 375 The discussion of isascii() should note that isascii() is an extension to ANSI C. p. 376 The discussions of iscsym() and iscsymf() should note that these functions are extensions to ANSI C. p. 377 The discussion of isodigit() should note that isodigit() is an extension to ANSI C. p. 396 The discussion of strpos() and strrpos() should note that the these functions are an extension to ANSI C. p. 398 The discussion of strrpbrk() should note that the strrpbrk() function is an extension to ANSI C. p. 404 The discussions of toascii(), toint(), and _tolower should note that they are extensions to ANSI C. p. 405 The discussion of _toupper should note that _toupper is an extension to ANSI C. p. 444,445 The control codes to turn the cursor on and off are no longer used in the .CONSOLE driver, which is what the current version of ORCA/C uses for all text output. In the .CONSOLE driver, the cursor is always off unless it is waiting for a character. -- Compiler changes introduced in C 2.2.0 ----------------------------------- New Language Features --------------------- ORCA/C 2.2.0 adds support for several new C language features. Most are features that were added in the C99 or C11 language standards. 1. (C99 and C11) ORCA/C now recognizes the new keywords added in C99 and C11. These are: _Alignas _Alignof _Atomic _Bool _Complex _Generic _Imaginary _Noreturn _Static_assert _Thread_local restrict inline (already treated as a keyword by ORCA/C) Of these, _Atomic, _Complex, _Imaginary, and _Thread_local are recognized as keywords, but the corresponding language features are not yet supported, so any attempt to use them will produce an error message. The other new keywords are supported, as described below. 2. (C99) Statements and declarations may now be mixed within a block; declarations are no longer required to come before statements. The first clause of a for loop statement may also be a declaration (with auto or register storage class only). Variables may only be referred to by name in code syntactically after their declaration, but their lifetime continues as long as control remains in the enclosing block scope, even if it returns to a point before the declaration. Initializers for variables with automatic storage duration are evaluated whenever execution reaches the point where they appear in the code. In addition, the scope rules are changed so that each while, do, for, if, or switch statement introduces a new block scope corresponding to the statement, separate from the enclosing scope and ending at the end of the statement. Each substatement of these statements also introduces its own new block scope corresponding to that substatement, separate from the enclosing scope associated with the while, do, for, if, or switch statement itself. These rules ensure that a variable declared in the first clause of a for loop is local to that loop, but they can also affect other code by restricting the scope where an identifier is visible. In certain unusual cases, this can change the semantics of a program that was valid under C89, potentially producing a compile error or causing unexpected behavior when it executes. These new rules for declaration placement and scopes are enabled by default, but they can be controlled by a new flag bit in the #pragma ignore directive. Setting bit 4 (a value of 16) enables these new C99 features; clearing it disables them and returns to the older C89 rules. 3. (C99) ORCA/C now supports flexible array members, in which the last member of a struct may be declared with an incomplete array type, e.g. struct S { int a; int b[]; }; The flexible array member does not contribute to the size of the struct as reported by sizeof, but if such a struct is allocated in the heap, extra space may be allocated for the flexible array member, and elements of it up to the limit of the size allocated may be accessed. (This feature was actually permitted "by accident" in previous versions of ORCA/C, but it is now a supported feature, and errors related to it are now detected.) 4. (C99) The value 0 will always be returned if execution reaches the end of the main function without encountering a return statement, provided main is declared as returning a value of type int. 5. (C99) Enumeration specifiers may contain a trailing comma, e.g. enum color {black, purple, green, white,} pencolor; (Kelvin Sherlock) 6. (C99) Functions may be declared as "static inline". These have the same semantics as other static functions. The "inline" specifier suggests (but does not require) that calls to the function should be inlined or otherwise optimized. ORCA/C currently does not inline these functions or apply any other special optimizations, but future versions might introduce such features. Note that non-static inline functions are not currently supported. 7. Integer constants may be written in binary, with a "0b" or "0B" prefix followed by binary digits. The type of these constants is determined by the same rules as for octal and hexadecimal constants. (This is a non-standard feature, but compatible with other common compilers such as GCC and Clang.) (Kelvin Sherlock) 8. The "#warning" preprocessor directive is now supported. This behaves similarly to #error in that it causes any following tokens to be printed as a diagnostic message, but (unlike #error) it does not abort compilation. (This is a non-standard feature, but compatible with other common compilers such as GCC and Clang.) 9. (C11) The _Alignof operator and _Alignas declaration specifier are now supported. An expression "_Alignof(type-name)" gives the alignment of the specified type. In a declaration, an alignment specifier "_Alignas(type-name)" or "_Alignas(constant-expression)" specifies the required alignment for the object being declared. In ORCA/C, the alignment of all object types is 1, and that is the only alignment value supported. (As such, these features are not particularly useful in ORCA/C-specific code, but they may be used to control alignment in portable programs.) 10. (C11) The _Noreturn function specifier may be used in function declarations. It indicates that the function does not return to its caller. This serves as documentation to the user. It could potentially also enable optimizations, although ORCA/C does not currently perform any optimizations based on it. 11. (C11) Static assertions are now supported. These have the form _Static_assert ( constant-expression , string-literal ) ; and may appear wherever a declaration can (including inside and outside functions). They serve as assertions evaluated at compilation time, which will fail and abort compilation if the constant expression evaluates to 0. The string literal can contain an error message describing the problem. 12. (C99) The "restrict" type qualifier is now supported. This qualifier on object pointer types requires that all accesses to the pointed-to object must directly or indirectly use the value of that particular pointer. For example, if a function takes two pointer parameters that are both restrict-qualified, this asserts that during any execution of the function, if an object is accessed through one of those pointer parameters, it is not also accessed through the other; the values passed at call sites must be such that this will be the case. Using "restrict" could potentially enable greater optimization possibilities, but ORCA/C does not currently perform any optimizations based on it. 13. (C95) Digraphs are now supported. These are alternative tokens that are equivalent to certain tokens that may be difficult to type or display in some situations (e.g. on the IIgs text screen with certain language settings). Specifically, the following six tokens are now supported: <: :> <% %> %: %:%: These behave the same as the existing tokens [, ], {, }, #, and ## (respectively), apart from their spelling. 14. (C99) Universal character names are now supported in string literals, character constants, and identifiers. These are sequences of the form \unnnn or \Unnnnnnnn, where the nnnn or nnnnnnnn is a hexadecimal representation of a Unicode code point. These may be used to represent characters in a way that is independent of the source and execution character sets. In a string literal or character constant, only characters that can be mapped to the execution character set may be represented. There are also certain other restrictions on what characters can be used; see the C standards for details. For ORCA/C the source and execution character sets are both considered to be Mac OS Roman, the character set used in the IIGS desktop environment. 15. (C99) Function-like macros may take a variable number of arguments. To specify such a macro, include "..." as the last (or only) member of its parameter list. When the macro is used, one or more corresponding arguments may be provided. To access these arguments within the macro, use the special identifier __VA_ARGS__. This functions similarly to a normal macro parameter, but its expansion includes the tokens from all the corresponding arguments that were provided, including any commas separating arguments. 16. (C99) Any or all of the arguments to a function-like macro can now be empty. (This happened to work previously in some cases but not others.) 17. (C99 and C11) Several new predefined macros have been added: __STDC_HOSTED__ normally expands to the integer constant 1, indicating that ORCA/C is a hosted implementation of the C language (where the full standard library is available and the program starts by executing the main function). However, it will expand to 0 if one of the pragmas for special types of programs with different entry points has been used. __STDC_NO_ATOMICS__, __STDC_NO_COMPLEX__, __STDC_NO_THREADS__, and __STDC_NO_VLA__ all expand to the integer constant 1. These indicate that ORCA/C does not implement certain C language features that are optional under the C11 and later standards (atomics, complex numbers, threads, and variable length arrays). 18. (C99) The _Bool type is now supported. This is a boolean type that can hold the values 0 or 1. When a value of another type is converted to _Bool, the result is 0 if the value compares equal to 0, or 1 otherwise. 19. (C99) The types "long long" and "unsigned long long" are now supported. In ORCA/C, these are 64-bit integer types, capable of representing a larger range of values than the existing smaller integer types. All operations that can be done on other integer types can now be done on these types as well. Several new library functions in support operations on these types, and the fprintf() and fscanf() function families have been updated to support them. Also, several new functions defined in operate on intmax_t and uintmax_t, which are now typedefs for long long and unsigned long long. For details on these new and updated functions, see "Library Updates," below. The predefined macro __ORCAC_HAS_LONG_LONG__ is now defined, and expands to the integer constant 1. This indicates that these long long types are supported. 20. (C99) The predefined identifier __func__ is now supported, providing a way for code within a function to get the function's name. Specifically, it behaves as if the following declaration appeared at the beginning of each function body (where function-name is the name of the function): static const char __func__[] = "function-name"; 21. (C99) ORCA/C now supports the following standard pragmas: #pragma STDC FENV_ACCESS [ ON | OFF | DEFAULT ] #pragma STDC FP_CONTRACT [ ON | OFF | DEFAULT ] #pragma STDC CX_LIMITED_RANGE [ ON | OFF | DEFAULT ] These pragmas can be used either outside any external declarations or just after the opening brace of a compound statement. In the former case, they remain in effect until the end of the translation unit, or until another instance of the same pragma is encountered. In the latter case, they remain in effect until the end of the compound statement, and then revert to their previous setting. The FENV_ACCESS pragma should be set to ON if the code may access the floating-point environment (via functions in ) or run under non-default floating-point control modes. Under ORCA/C, it is not strictly necessary to use this pragma when accessing the floating-point environment, but if it is not used then certain operations may not affect or be affected by the floating-point environment in the expected way. Under ORCA/C, the default setting for FENV_ACCESS is OFF. Note that setting it to ON will disable some optimizations. The FP_CONTRACT pragma controls whether the compiler may "contract" certain floating-point expressions, evaluating multiple operations together and rounding only at the end. ORCA/C never does this. Accordingly, the FP_CONTRACT pragma is accepted, but its setting has no effect. The CX_LIMITED_RANGE pragma relates to complex arithmetic, which ORCA/C does not support, so it is also accepted but has no effect. 22. (C11) ORCA/C now supports generic selection expressions, which can select which of several expressions they should evaluate to based on the type of one expression. They have the following syntax: generic-selection: _Generic '(' assignment-expression ',' generic-assoc-list ')' generic-assoc-list: generic-association | generic-assoc-list ',' generic-association generic-association: type-name ':' assignment-expression | default ':' assignment-expression The generic-assoc-list provides a list of associations of types with expressions (and optionally a default association). If the type of the the initial expression is compatible with one of those in the generic-assoc-list, the generic selection expression evaluates to the expression specified in that association. If there is no compatible type but there is a default association, the expression specified there is used. It is an error if there is no suitable association. Only the expression from the selected association is evaluated and becomes the value of the overall generic selection expression; the initial expression and all those in other associations are not evaluated. As an example, this expression evaluates to 2 because the type of 1+2 is int: _Generic(1+2, double: 1.0, int: 2, char*: 3, default: 4) Generic selection expressions are primarily useful within macros, which can give different behavior based on the types of the arguments passed to them. Multi-Character Character Constants ----------------------------------- Character constants containing multiple characters are now supported, as required by the C standards. The value of such constants is implementation-defined. In ORCA/C, the value is initially set to the ordinal value of the first character, as in a single-character constant. For each subsequent character encountered, the existing value is shifted left by eight bit positions, and the ordinal value of the new character is placed in the lower eight bits. (This is similar to the behavior of GCC and Clang.) A new bit is also introduced in #pragma ignore that affects the interpretation of such constants. Setting #pragma ignore bit 1 (a value of 2) causes character constants with three or more characters to be treated as having type long, rather than type int. This non-standard feature effectively allows a character constant to contain the values of up to four characters, rather than only two. Note that MPW IIGS ORCA/C also supports multi-character constants and #pragma ignore bit 1, but it calculates the value of such constants differently. (In general, the bytes of a multi-character constant will be in the opposite order.) Also, MPW IIGS ORCA/C treats #pragma ignore bit 1 as being set by default, but in this version it is unset by default, providing standard-compliant semantics. (Mike Westerfield, Kelvin Sherlock, Stephen Heumann) Evaluation of Floating-Point Expressions and Constants ------------------------------------------------------ There have been some changes to the way ORCA/C evaluates floating-point expressions and constants. ORCA/C has always used the SANE extended format (which is the format of long double) to evaluate floating-point expressions at run time, even if their semantic type in the standard C language was float or double. However, it previously used the double format to evaluate constant expressions that could be computed at compile time. Now, it uses the extended format for those computations too, producing consistent results for a computation regardless of whether it is done at compile time or run time. ORCA/C also historically used the double format internally to hold the values of all floating-point constants, even those with an 'L' suffix indicating they were of type long double. It now uses the extended format for all floating-point constants. This allows long double constants to be represented with the full range and precision that they should have. It also provides extra range and precision for constants of type float or double, beyond what would be provided if they were simply represented using their semantic type. Using the extended format provides greater precision and range than the float or double formats, and can lead to more accurate results. However, using it for expressions or constants with shorter semantic types can cause behavior that may be surprising. For example, a variable of type double that has had a constant of type double assigned to it may not compare equal to that same constant. This behavior is allowed under the C standards (the new behavior is designed to be consistent with a FLT_EVAL_METHOD value of 2, as defined in the C99 and later standards), but it is different from that of some C compilers on other systems. If you want to get a value strictly in a certain type with no extra range or precision, you can store it in a variable of that type or explicitly cast it to that type. (In older versions of ORCA/C, floating-point casts did not remove extra range or precision, but now they do, as required by the C standards.) Additions to #pragma ignore --------------------------- Several additional #pragma ignore bits are now supported. Bit 1 (a value of 2) affects the interpretation of multi-character character constants. It is described under "Multi-Character Character Constants," above. Bit 2 (a value of 4) controls whether spurious tokens are allowed after an #endif directive. If it is set, the tokens are treated as a comment, and have no effect on the program. If this bit is clear, tokens after #endif are treated as an error. (This feature was introduced in MPW IIgs ORCA/C and is compatible with it, but in this version the bit is unset by default, providing standard-compliant semantics.) Bit 4 (a value of 16) controls whether ORCA/C follows C99-style rules for declaration placement and block scopes. See "New Language Features," above. Bit 5 (a value of 32) controls whether type compatibility checks should strictly follow the C standards, or whether looser rules should be used in certain cases. If this bit is set, the looser rules will be followed, matching ORCA/C's historical behavior. Bit 5 is currently set by default, but new code should avoid relying on this. There are three specific situations where bit 5 currently has an effect: First, setting bit 5 causes pointer assignments that discard type qualifiers to be allowed. For example, this affects an assignment from an expression of type "const int *" to a variable of type "int *", because it discards the "const" qualifier from the type pointed to. These assignments are prohibited by the C standards, but ORCA/C historically allowed them. If bit 5 is set it will still allow them, but if bit 5 is clear it will give an error. Second, setting bit 5 causes type compatibility checks involving function pointers to ignore the prototyped parameter types. If bit 5 is clear, the prototyped parameter types (if available) must be compatible. Third, setting bit 5 causes the types "char" and "unsigned char" to be treated as compatible with each other for most purposes. These types have the same representation in ORCA/C, but the C standards specify that they are nonetheless two distinct types and are not mutually compatible. Therefore, any standard-conforming C compiler should produce a diagnostic message if these two types or types derived from them are used in a situation where the types are required to be compatible, as in the following example: unsigned char uc; char *p = &uc; /* &uc has type unsigned char *, incompatible with char *. */ ORCA/C historically permitted code like the above, and when bit 5 is set it will still do so. If bit 5 is clear, it will give a "type conflict" error. (Mike Westerfield, Kelvin Sherlock, Stephen Heumann) Inline Function Names --------------------- ORCA/C now supports recording the names of functions using the inline name format documented in Apple IIGS Technical Note #103. This allows assembly-level debugging tools such as GSBug and Nifty List to display the names of functions in an ORCA/C program while debugging it. To enable generation of inline function names, set #pragma debug bit 15 (a value of 0x8000). Note that inline function names are unrelated to the other types of debug code that ORCA/C can generate. In particular, inline function names are not needed for source-level debugging using the desktop development environment or other compatible source-level debuggers, although it is possible to enable both types of debugging information at the same time. (Kelvin Sherlock) Enhancements to #pragma lint ---------------------------- The #pragma lint directive has several new features. First, the directive can now optionally be configured to perform its checks but treat any messages produced as warnings rather than errors, so that they do not cause compilation to fail. To make it work this way, add ";0" after the integer value indicating the checks to perform. For example, you can use #pragma lint -1;0 to perform all lint checks but treat them as warnings rather than errors. In addition, several new kinds of lint checks can now be performed. They are controlled by new bits in the #pragma lint operand, as described below. * Format checking: There is a new #pragma lint bit to enable checking of the format strings passed to the fprintf() and fscanf() families of functions. If #pragma lint bit 4 (a value of 16) is set, the compiler will check if the format strings passed to those functions are valid, and if the number and types of arguments passed to them match what the format strings call for. If these lint checks detect any errors, they will produce the error message "lint: invalid format string or arguments," followed by more detailed information about the problem(s) found. (Kelvin Sherlock) * Checking for undefined behavior in computations: There is a new #pragma lint bit to enable checking for several situations in arithmetic computations or bit manipulation that give rise to undefined behavior according to the C standards. These are generally indicative of bugs, or (in code ported from other platforms) of assumptions that types have larger ranges than they do in ORCA/C. These checks are enabled if #pragma lint bit 5 (a value of 32) is set. They currently check for the following conditions: - Integer overflow from arithmetic in constant expressions of type int - Integer division by the constant zero (or remainder from such division) - Invalid constant shift counts (negative, or >= the width of the type) * Checking for syntax disallowed by C99: ORCA/C can now detect several elements of C syntax that were allowed in C89 but are not allowed in C99 or later. These checks are performed if #pragma lint bit 6 (a value of 64) is set. This currently checks for the following situations: - Calls to undeclared functions (also detected by #pragma lint bit 0) - K&R-style function definitions without explicit declarations for parameters - return statements with no value in functions that have non-void return types (also detected by #pragma lint bit 7, described below) - Declarations or type names with no type specifiers (using 'implicit int') (This includes but is broader than what is checked by #pragma lint bit 1.) * Checking for functions not returning a value or returning inappropriately: If #pragma lint bit 7 (a value of 128) is set, ORCA/C detects some situations where a function with a non-void return type may return an unpredictable value, either by executing a return statement with no value or by executing to the end of the function with no return statement. (The former case is also detected by #pragma lint bit 6.) It also detects some situations where a _Noreturn function could return. Note that these checks only detect some cases of these problems, not all of them. Also, they may report a potential problem in some situations where the code at the end of a function is not actually reachable. New Headers ----------- ORCA/C now includes several new headers specified by recent C standards. 1. (C95) The header contains macros giving alternative spellings for certain operators. It may be useful in contexts where the characters in those operators cannot easily be typed or displayed. 2. (C99) The header defines various integer types with certain sizes and properties, as well as macros related to integer types. 3. (C99) The header defines macros that can be used for format specifiers when values of the types defined in are used with the fprintf or fscanf family of functions. It also provides several functions operating on the types intmax_t or uintmax_t. 4. (C11) The header defines the macros "alignas" for _Alignas and "alignof" for _Alignof. 5. (C11) The header defines the macro "noreturn" for _Noreturn. 6. (C99) The header defines the macro "bool" for _Bool, and the macros "true" and "false" for the boolean values 1 and 0. 7. (C99) The header provides functions to access the floating-point environment, plus types and macros used by those functions and the macro FE_DFL_ENV representing the default floating-point environment. Library Updates --------------- ORCA/C now includes some new library functions and features specified by the C99 and C11 standards: 1. (C99) The isblank() function and macro have been added: #include int isblank(int c); isblank returns non-zero if the argument is a standard blank character, and zero if it is not. The argument must lie in the range -1 to 255, or the result is not valid. The standard blank characters are space and horizontal tab. 2. (C99) The snprintf() and vsnprintf() functions have been added: #include int snprintf(char * restrict s, size_t n, const char * restrict format, ...); #include #include int vsnprintf(char * restrict s, size_t n, const char * restrict format, va_list arg); These are equivalent to sprintf and vsprintf, except that they take an additional argument giving the maximum number of characters to be written. If n is 0, no characters are written. Otherwise, at most n-1 characters are written based on the format string, followed by a terminating null character. They return the number of characters (not including the terminating null character) that would have been written if there was no size limit. 3. (C99) The vscanf(), vfscanf(), anf vsscanf() functions have been added: #include #include int vscanf(const char * restrict format, va_list arg); int vfscanf(FILE * restrict stream, const char * restrict format, va_list arg); int vsscanf(const char * restrict s, const char * restrict format, va_list arg); These functions are equivalent to scanf, fscanf, and sscanf, except that the variable portion of the arguments is instead supplied by arg, a variable argument list that should have been initialized by va_start. 4. (C99) The fprintf() and fscanf() families of functions have been updated to support some additional length modifiers and conversion specifiers: The length modifiers 'z', 't', 'j', 'hh', and 'll' are now allowed in the format strings for the fprintf and fscanf families of functions. They may be used with the 'd', 'i', 'o', 'u', 'x', 'X', or 'n' conversion specifiers. These each correspond to integer types, as follows: 'z' to size_t or the corresponding signed integer type, 't' to ptrdiff_t or the corresponding unsigned integer type, 'j' to intmax_t or uintmax_t, 'hh' to signed char or unsigned char, and 'll' to long long or unsigned long long. The corresponding argument must be an integer of an appropriate type, or a pointer to such an integer, as appropriate for the function and conversion specifier. The conversion specifiers 'F', 'a', and 'A' are now allowed in the format strings for the fscanf family of functions. These are all equivalent to 'f' (but none of them accept numbers in the hexadecimal format allowed by C99). The 'F' conversion specifier is also now allowed in the format strings for the fprintf family of functions. It is equivalent to 'f', except that "INF" and "NAN" are guaranteed to be printed in upper case. The conversion specifiers 'a' and 'A' (both also used with floating-point numbers) are also recognized in the format strings for the fprintf family of functions, but they do not currently print the numbers in the hexadecimal format required by the C99 standard. The ORCA/C-specific conversion specifier 'P' is now allowed in the format strings for the fprintf and fscanf families of functions. This works exactly the same as the existing 'b' conversion specifier, printing or reading input to a string with a leading length byte (a p-string). This new specifier was introduced because the 'b' specifier may be used for a different purpose in future C standards. For the time being, the 'b' specifier is still available with its existing meaning, but it is considered deprecated. Code should be migrated to use the 'P' conversion specifier instead. 5. (C99 and C11) The _Exit(), quick_exit(), and at_quick_exit() functions have been added: #include _Noreturn void _Exit(int status); _Noreturn void quick_exit(int status); int at_quick_exit(void (*func)(void)); _Exit() exits the program without calling functions registered with atexit() and possibly without doing other clean-up operations. In ORCA/C, it is functionally identical to _exit(). quick_exit() calls any functions registered with at_quick_exit(), then exits the program in the same way as _Exit(). at_quick_exit() registers a function to be called by quick_exit(). It works similarly to atexit(), except that it maintains a separate list of functions that are called only if the program exits via quick_exit(). It returns zero if the function is registered successfully, and a non-zero value if there is not enough memory to satisfy the request. 6. (C11) The aligned_alloc function has beed added: #include void *aligned_alloc(size_t alignment, size_t size); This is equivalent to malloc, except that it specifies an alignment for the block of memory to be allocated. In ORCA/C, the only supported alignment value is 1 (which is the alignment of all object types). 7. (C11) If the second argument to fopen() or freopen() starts with "w", it can optionally have an "x" at the end (e.g. "wbx"). This is equivalent to the corresponding form without an "x", except that the operation will only succeed if the file does not already exist (so that it can be newly created). If the file already exists, the operation will fail: it will leave the file alone, set errno to EEXIST, and return NULL. 8. (C99) Several functions operating on long long types have been added: #include typedef struct {long long quot,rem;} lldiv_t; long long atoll(const char *str); long long llabs(long long x); lldiv_t lldiv(long long numer, long long denom); long long strtoll(const char * restrict str, char ** restrict ptr, int base); unsigned long long strtoull(const char * restrict str, char ** restrict ptr, int base); The atoll(), strtoll(), and strtoull() functions convert a string to a long long or unsigned long long number. llabs() computes the absolute value of a long long value. lldiv() divides one long long value by another, returning a structure with both the quotient and the remainder. Except for the types used and the range of numbers that can be represented, these functions behave the same as atol(), strtol(), strtoul(), labs(), and ldiv(), respectively. There are also several functions operating on the type intmax_t or uintmax_t: #include typedef struct {intmax_t quot,rem;} imaxdiv_t; intmax_t imaxabs(intmax_t); imaxdiv_t imaxdiv(intmax_t, intmax_t); intmax_t strtoimax(const char * restrict, char ** restrict, int); uintmax_t strtoumax(const char * restrict, char ** restrict, int); Under ORCA/C, intmax_t is long long and uintmax_t is unsigned long long, so these functions behave the same as the ones above. 9. (C99) Several functions for accessing the floating-point environment have been added: #include int feclearexcept(int excepts); int fegetexceptflag(fexcept_t *flagp, int excepts); int feraiseexcept(int excepts); int fesetexceptflag(const fexcept_t *flagp, int excepts); int fetestexcept(int excepts); int fegetround(void); int fesetround(int round); int fegetenv(fenv_t *envp); int feholdexcept(fenv_t *envp); int fesetenv(const fenv_t *envp); int feupdateenv(const fenv_t *envp); For all the functions taking an argument called excepts, it is a bitwise OR of floating-point exception macros defined in . feclearexcept() clears the specified exceptions. fegetexceptflag() saves a representation of the current state of the specified exceptions to *flagp. feraiseexcept() raises the specified exceptions. fesetexceptflag() sets the exception flags for the specified exceptions to the states saved in *flagp, but does not raise them. fetestexcept() tests whether the specified exceptions are set, returning the bitwise OR of the specified exceptions that are set. fegetround() gets the current rounding direction. fesetround() sets the rounding direction. fegetenv() saves a representation of the current floating-point environment to *envp. feholdexcept() saves a representation of the current environment, then clears all exception flags and disables halts for all floating-point exceptions. fesetenv() sets the floating-point environment, but does not raise any exceptions. feupdateenv() temporarily saves the currently raised floating-point exceptions, installs the specified floating-point environment, and then raises the saved exceptions. Except for fetestexcept() and fegetround(), these calls return 0 if they successfully carried out the operation, or non-zero otherwise. Under ORCA/C, they always succeed if given valid arguments. To ensure that these functions interact properly with floating-point operations in the program, #pragma STDC FENV_ACCESS ON should be in effect when they are called; see "New Language Features," above. Under ORCA/C, these functions all correspond to operations on the SANE environment; see the Apple Numerics Manual for details on its behavior. Note that these functions may not behave as expected when using an FPE or compatible floating-point card. 10. (C99) Several new function-like macros for classification of floating-point numbers have been added: #include int fpclassify(real-floating x); int isfinite(real-floating x); int isinf(real-floating x); int isnan(real-floating x); int isnormal(real-floating x); int signbit(real-floating x); These macros accept an argument of any real floating type, i.e. float, double, or long double. They behave as if the argument is converted strictly to its semantic type before classifying it, removing any extra range and precision. fpclassify() returns one of the macro values FP_INFINITE, FP_NAN, FP_NORMAL, FP_SUBNORMAL, or FP_ZERO, indicating the classification of its argument. isfinite() returns a non-zero value if its argument is normal, subnormal, or zero (not infinite or NAN). isinf(), isnan(), and isnormal() return a non-zero value if their arguments are infinite, NAN, or normal, respectively. signbit() returns zero if the argument has a positive sign, and non-zero if it has a negative sign (this applies to all floating-point values, even zeros and NANs). -- Compiler changes introduced in C 2.1.0 ----------------------------------- The Default .h File ------------------- The default .h file is a new way for you to set up compiler options that you want to use on every C source file you compile. Here's how it works: When ORCA/C starts, it begins by processing any command line parameters. Next, it looks for a file called defaults.h in the library folder. Finally, it compiles your source file. When ORCA/C looks for the defaults.h file, it behaves almost as if your program had started with the line #include The only differences are that the file doesn't have to exist (and if it doesn't no error is generated), the line is never shown in your source file, and the line number counter is not incremented. You can put absolutely anything you like in this file. The intent is to use it for pragmas or other preprocessor directives that you would like to become defaults for all of your programs, but there is no restriction that prevents you from putting other things in the file. WARNING: If you add a defaults.h file, be sure and delete all .sym files. .sym files are created by the compiler to make recompiling programs faster. They need to be recreated with the new information from the defaults.h file, but the compiler will not notice the presence of the defaults.h file if it is compiling a .sym file created with a previous version of the compiler. // Comments ----------- ORCA/C supports // comments. These comments begin with the characters //, and continue to the end of the physical line. // comments are a flagrant violation of the ANSI C89 standard, although they are supported by the C99 and later standards. This is legal ANSI C89, and it should print 4: a = 8//* yep, this is legal */ 2 ; printf("All ANSI C compilers should now print 4! %d\n", a); To restore ANSI C89 conformance, use the #pragma ignore directive. Setting bit 3 (a value of 8) tells ORCA/C to allow // comments. This is the default. Clearing bit 3 tells ORCA/C not to look for // comments. To restore ANSI C89 conformance for all programs, use this directive in the defaults.h file. (see "The Default .h File," above.) Extended Characters ------------------- Bear with me. This is an ASCII file, and it describes non-ASCII material. Beginning with version 2.1, the PRIZM desktop editor supports the full Apple extended character set. A file called FontTest on the samples disk shows the complete character set, and also contains a table that shows how to type each character from a U.S. English keyboard. C supports the use of extended characters in strings, comments, identifiers, and for a few mathematical operations. Any character you can type from PRIZM (or for that matter, any character with an ordinal value in [1..12, 14..255]) can appear in a string or comment. The ordinal value of the character matches the values shown in FontTest, as well as several official Apple publications. Keep in mind that many output devices, including Apple's text console driver, do not support all of these characters. ORCA/C will properly send extended characters to whatever output device you choose, but what happens when the output device tries to handle the character varies from device to device. Many of the characters in the extended character set are used in languages other than English, and are now allowed in identifiers. There are two ways to think about which characters will work in an identifier. The simple way is to remember that all characters that look like a graphically modified ASCII alphabetic character or a Greek alphabetic character are allowed in identifiers. For example, an a with two dots above it is now legal in an identifier. The more exact, and naturally more complicated way to think about which characters are allowed in an identifier is to list all of them. Since this is an ASCII file, I'll list the ordinal values--you can cross reference the values in FontTest. The ordinal values of the extended characters that are allowed in identifiers are [$80..$9F, $A7, $AE, $AF, $B4..$B9, $BB..$BF, $C4, $C6, $CB..$CF, $D8, $DE, $DF]. In addition, ORCA/C supports several extended characters as shortcuts for multi-character mathematical operations. These are: ordinal value description substitutes for ------------- ----------- --------------- $C7 two < << $C8 two > >> $AD not equal != $B2 less than or equal <= $B3 greater than or equal >= $D6 division (- with dots) / Finally, the non-breaking space, sometimes called the sticky space (ordinal value $CA), is treated exactly like a standard space character. #pragma optimize ---------------- In brief, there is a new optimization bit. Setting bit 6 (a value of 64) turns off stack repair code around variable argument function calls. The rest of this section describes when the stack repair code is generated, why, and the side effects of using this optimization--or not using it. In variable argument functions (functions with ... as the last "parameter") it is illegal to pass fewer parameters than the function expects, or to pass parameters of a type different than the function expects. For example, both of these statements are illegal in ANSI C, even though few if any compilers can detect the error (and those that do are blocking some legal--albeit stupid--C code.): printf("%d %d", 4); printf("%d", 4.5); ORCA/C has always taken advantage of this fact to generate code that is more efficient and compatible with the other ORCA languages. With all optimizations on, programs containing the above statements will corrupt the stack, generally leading to a crash. On the other hand, ORCA/C did not allow this statement: printf("%d", 4, 5); Contrary to all common sense, the ANSI standard says this statement is legal IF THE APPROPRIATE HEADER FILE IS INCLUDED, even though the first two are not. Beginning with ORCA/C 2.1, this statement will work. Note that in keeping with the ANSI standard, this call and others like it only work if the function is properly defined with a prototyped variable argument parameter list. There are two undesirable side effects, though. First, all function calls to a variable argument function are surrounded by extra stack repair code, even if you set optimization bit 3. (This bit turns off stack repair code.) This increases code size and slows a program down. Sometimes these changes are noticeable, or even dramatic. Second, native code peephole optimization is always disabled when stack repair code is in use, so you loose another optimization if you do not use this one. Turning this optimization on means ORCA/C is no longer strictly in compliance with the ANSI standard. For strict compliance, you should leave stack repair code on for variable argument functions. You also need to disable stack repair code in any user-defined function that uses the va_arg() function, since this function is not compatible with stack repair code. For strict compliance, then, use at least #pragma optimize 0x0008 You can also add all of the other optimizations except removal of stack repair code around variable argument function calls and remain ANSI compliant, so this pragma will also work with all ANSI C programs: #pragma optimize 0x003F If you use #pragma debug 0x0010 to enable stack check debug code, the compiler will still flag variable argument functions that do not consume all arguments as a run-time error, even though ANSI C does allow them. -- Bugs from C 2.1.1 B3 that have been fixed in C 2.2.0 --------------------- 1. There were various bugs that could cause incorrect code to be generated in certain cases. Some of these were specific to certain optimization passes, alone or in combination. (Doug Gwyn, Norman Dodge, Dave Tribby, Michael Lutinsky, Todd Whitesel, et al.) 2. The integer promotion rules (usual unary conversions) would previously promote values of type char or unsigned char to unsigned int, rather than int. The C standards require these types to be promoted to int (not unsigned int) when the types involved have the ranges that they do in ORCA/C, and ORCA/C now behaves accordingly. (This is sometimes referred to as "value-preserving" behavior, rather than the previous "unsigned-preserving" behavior.) This can cause certain expressions to be evaluated differently, for example when char values are compared with negative integers. (Devin Reade) 3. Globals or static variables that used pointer arithmetic or the & operator in their initializers could sometimes get the wrong values. (Devin Reade) 4. Preprocessing directives could be mis-evaluated if they occurred immediately after a use of a function-like macro. 5. Arrays could not be used as operands of && and ||, or as the first operand of the ? : operator. Now they can (they are implicitly converted to pointers). (Derek Taubert) 6. Dereferencing pointers to const struct or const union types gave spurious errors. (Derek Taubert) 7. When a bit-field is used within an lvalue expression but isn't what's being assigned to, the bit-field could erroneously be assigned to instead. (Michael Guitton) 8. When arrays are declared using a typedef'd incomplete array type, the size for all arrays of that type would erroneously be fixed based on the initializer of the first array using it. (Devin Reade) 9. The += and -= operators could not be used on function parameters declared using array syntax (which are adjusted to have pointer type). (Doug Gwyn, Norman Dodge) 10. String and floating-point constants may now appear within the operands of sizeof in a constant expression. (Devin Reade) 11. Code for narrowing conversions or casts was sometimes not properly generated. 12. Case labels in switch statements may now be out of range of the type being switched on. They are converted to the promoted type of the expression being switched on, as if by a cast. Code requiring this is dubious, but it's allowed under the C standards. 13. Unsigned constants in the range 0x8000-0xFFFF were erroneously being treated like negative signed values in some contexts. 14. Unions can now be initialized by assignment from expressions of the appropriate union type. 15. If a defaults.h file is present, the value of the __LINE__ macro would be off by one. (Steve Reeves) 16. Zero-initializing a one-byte array could crash the system. 17. The 'extern' storage-class specifier may now be used in function definitions. 18. Certain integer constant expressions, including sizeof expressions, were treated as having type signed long when they should have type unsigned long. 19. Spurious error messages were produced when #error was used with tokens other than a string constant. It now properly accepts any sequence of pp-tokens. (Soenke Behrens) 20. The types of shift expressions depended on the types of both their operands. They now correctly depend only on the (promoted) type of the left operand. 21. The __DATE__ macro did not properly report dates in the year 2000 or later, and used a slightly non-standard date format in some cases. (Dave Tribby) 22. When using common subexpression elimination, ORCA/C could crash or corrupt memory due to stack overflow in certain cases involving large switch statements or long sequences of code without control flow statements. 23. Comparing 32-bit values in static arrays or structs against 0 could sometimes give the wrong result when using the large memory model. 24. Pointer types with type qualifiers (const or volatile) were not allowed in casts and sizeof expressions. (Doug Gwyn) 25. Spurious errors were given when calling functions with const-qualified parameter types or returning from functions with const-qualified return type. (Norman Dodge) 26. Statically-evaluated conversions from floating-point values to integers could give wrong values because they were rounded rather than truncated in certain cases. 27. If a macro's name appeared inside the macro, it would be expanded repeatedly, leading to a crash. (Bug in ORCA/C 2.1.1 betas only.) 28. Statically-evaluated division and remainder computations on unsigned 32-bit values could give incorrect results because of bugs in the math routines. 29. Unsigned long values greater than 2^31 could not be used as the second operand to % in constant expressions. 30. In constant binary expressions involving unsigned int and signed long operands, the operands would be converted to unsigned long and the expression evaluated using that type. They are now correctly evaluated using the type long, rather than unsigned long. 31. Statically-evaluated signed comparisons evaluated to -1 if true. They now properly evaluate to 1. 32. Floating literals that are immediately cast to integer types were not allowed in integer constant expressions. Now they are, as required by the C standards. 33. Within preprocessor expressions, keywords and typedef names were sometimes processed based on their usual semantics rather than being treated as identifiers. They are now consistently treated as identifiers. 34. Preprocessor expressions were being evaluated using the normal type conversion rules (with many expressions evaluated as type int). All preprocessor expressions are now evaluated using the intmax_t and uintmax_t types, as required by the C standards. (As of ORCA/C 2.2.0 B5, these are the 64-bit types long long and unsigned long long.) 35. The unary ! operator could not be applied to floating constants. 36. In constant expressions, the result type of || and && expressions was based on the types of their operands. Now they always correctly yield type int. 37. Certain error conditions (use of #error or undefined labels in goto statements) would not cause an error status to be reported to the shell. This could cause a multi-step compilation process to continue when it should halt due to the error. Now a non-zero error level is always reported in these cases, so the compilation process will halt. (Michael Lutinsky) 38. An error was reported if there were unknown preprocessor directives or unexpected tokens following a preprocessing directive within a section of code that was skipped during preprocessing. Now these cases are not reported as errors. This allows certain nonstandard constructs used by other compilers to appear within conditionally-skipped code. 39. Errors would be reported when a number-like token was not a valid numeric constant, even if it was a valid preprocessing-number token used in a context where it did not need to be converted to a numeric constant (e.g. within conditionally-skipped code). Some such cases are now allowed. 40. Array types were not treated as compatible with corresponding pointer types in function prototypes. Now they are, so the following declarations, for example, are permitted to all be present in one translation unit: int foo(int*); int foo(int[]); int foo(int[42]); 41. Spurious errors could be reported due to improper handling of the symbol table when a pointer to a typedef'd function type was declared. 42. Global structs and unions with const-qualified types were not being generated in object files. 43. In programs that used the 'volatile' keyword, both accesses to volatile variables and certain other operations could be erroneously optimized out in some cases. 44. Character constants containing multiple characters were not allowed. Now they are, as required by the C standards. See above for information on their semantics. 45. Typedef'd versions of "void" could not be used in the prototyped parameter list of a function taking no arguments. 46. The declaration of PutScrap in was incorrect. (Kelvin Sherlock) 47. The declaration of LEClassifyKey in was incorrect. (Kelvin Sherlock) 48. The declaration of SetContentOrigin2 in was commented out, with a comment indicating it was not documented. It is actually a valid tool call documented in TBR2. A prototyped declaration for it is now provided. 49. In some cases, very large functions would appear to compile correctly, but actually generate corrupt OMF object files. These cases should now either work correctly (if they fit within the new, increased size limits) or give an error message. (Jawaid Bazyar) 50. There was a bug that might trash four bytes of memory in certain circumstances. (Kelvin Sherlock) 51. An unlimited number of octal digits could be processed as part of an octal escape sequence in a character constant or string. Octal escape sequences are now limited to a maximum of three octal digits, as required by the C standards. (This partially reverts a change in ORCA/C 2.1.0, which should only have applied to hexadecimal escape sequences.) (Bug fixes below here were added in ORCA/C 2.2.0 B2.) 52. Fixed several bugs that could cause invalid optimizations to be performed by the loop invariant removal optimization pass, and also one that affected common subexpression elimination. (Soenke Behrens, Michael Guitton, Dave Tribby) 53. Added prototypes for internal functions called by macros in , so they will not produce errors when certain #pragma lint options are used. (Robert Eckweiler) 54. Fixed several bugs that could cause invalid code to be generated for array indexing or pointer arithmetic in certain cases. (Kelvin Sherlock, Stephen Heumann) 55. Prototypes for the library functions also defined as macros are now provided. This ensures correct behavior when the macro is bypassed to access the library function. 56. The setbuf macro could evaluate its second argument twice, which could cause incorrect behavior. It has been removed in favor of just calling the library function. 57. Correct code was not being generated when producing profiling code but not source-level debug code (e.g. by using "#pragma debug 4"). This could result in incorrect profiling results or other strange behavior. (Kelvin Sherlock) 58. When a macro's own name was used within it, that token could be re-expanded later in some cases. That re-expansion is now blocked, consistent with the C standards. 59. When zero was consecutively stored to two global or static variables, the second store might be omitted if using the native code peephole optimizer. (This was a regression introduced in ORCA/C 2.2.0 B1.) (Bug fixes below here were added in ORCA/C 2.2.0 B3.) 60. If two consecutive operations stored zero to the same volatile variable, one of the stores might be omitted if using the native code peephole optimizer. (This was a regression introduced in ORCA/C 2.2.0 B1.) 61. Invalid debug code was generated in some cases involving structs or unions. (Kelvin Sherlock) 62. The definition of struct __file in did not match that actually used by the ORCALib library binary. This could cause problems with (non-portable) code that accesses the members of that structure. 63. Parameters in a function prototype with previously-undeclared structure types would be entered in the global symbol table, which could cause incorrect behavior or error messages if the same name was used later. (Kelvin Sherlock) 64. Tentative definitions of arrays (e.g. "int i[];" at file scope) are now allowed and handled as required by the C standards: such arrays will wind up having one element, initialized to 0, unless a subsequent non-tentative definition gives a size. 65. sys_nerr was 6; it should be 12. (Devin Reade) 66. The function (but not the macro) for iscntrl() was misnamed isctrl(). (Devin Reade) 67. toupper() and tolower() were not correctly handling inputs of EOF (-1). (Kelvin Sherlock) 68. The code to parse the command line into argv would mis-handle certain cases involving double-quoted arguments (such as double-quoted arguments containing only whitespace characters), which could lead to argv being corrupted. (Kelvin Sherlock) 69. When argc==0 (as for S16 programs and various other cases), argv should be a valid pointer and argv[0] should be NULL. 70. sprintf()/vsprintf() should write a terminating null character even if the string produced is empty. 71. asctime() should correctly print dates in the years 1000 through 9999. (Steve Reeves) 72. mktime() was treating the tm_yday field of struct tm as if it was indexed from 1 for January 1st. In fact, it is the number of days since January 1st. (Steve Reeves) 73. Calling system(NULL) should detect whether a command processor is present. (Philippe R Manet) 74. strtol()/strtoul() should return LONG_MIN/LONG_MAX/ULONG_MAX for out-of-range values. (Devin Reade) 75. Fixed some bugs in code generation and optimization of expressions using the comma operator. 76. Fixed some bugs that caused spurious errors when const-qualified struct or union types were used in certain ways. 77. Fixed several bugs in intermediate code optimization that could cause invalid code to be generated for certain unusual (and mostly useless) expressions. 78. Fixed several bugs that could cause invalid code to be generated in functions with 254 or more bytes of local variables. 79. Fixed some cases where decay of array types to pointer types was not handled correctly. (Bugs in items 75-79 were identified using Csmith.) 80. ORCA/C sometimes failed to initialize an error message being reported. (Kelvin Sherlock) 81. The #line directive was setting the number for the current line, rather than the following one. 82. Output from #pragma expand could contain string literals that were invalid or did not represent the same strings as those in the original program code. In order to fix this problem, #pragma expand has been changed to use three-digit octal escape sequences (rather than hexadecimal ones) in strings it outputs. (This ensures that subsequent characters in the string cannot be interpreted as part of the escape sequence.) 83. Constant expressions cast to char or unsigned char could be treated as if their type promoted to unsigned int rather than int. 84. If the compiler was set to enter the editor on errors, it could sometimes open the editor at the wrong position in the file. (Matt Ackeret) 85. Errors displayed for source lines indented with tabs would typically appear to be at the wrong position (depending on how the console in use displays tabs). 86. The LDBL_* values in were all wrong. They specified values for the double format, not the SANE extended format actually used for long double. As of ORCA/C 2.2.0 B5, all of them now have the correct values. 87. perror() should write only a single new-line. Also, it should not write the prefix string, colon and space if the prefix string pointer is NULL or if it points to an empty string. 88. The % operator would generally not work correctly if either operand was negative. It could produce an incorrect result, or in certain scenarios give a compile-time or run-time error. It now gives correct results as defined by the C standards, such that (a/b)*b + a%b equals a (provided that b is not 0 and a/b is representable in the type used for the operation). (Devin Reade) 89. The div() and ldiv() functions could also give incorrect remainders: in some cases where one or both of the arguments were negative, the remainder would have the wrong sign. This has been corrected; these functions now also generate correct remainder values, consistent with what the % operator now produces. 90. strtol() and strtoul() incorrectly considered it an error for the string to start with "0X" or "0x" if the base parameter was something other than 0 or 16. 91. Including system headers named via macros, as in the following example, did not work properly: #define STDIO_H #include STDIO_H 92. The ?: operator could sometimes evaluate the wrong branch when certain kinds of expressions were used as the condition. 93. Fixed several issues where initializers of structs or unions (or arrays containing structs or unions) might not be processed correctly. 94. const-qualified struct or union types were not being recorded properly in .sym files. This could lead to spurious errors or other problems when the .sym files were used. This bug has now been fixed, and .sym files created by older versions of ORCA/C will automatically be ignored and regenerated. (Bug fixes below here were added in ORCA/C 2.2.0 B4.) 95. const-qualified struct types were not being represented properly in debugger symbol tables. (Kelvin Sherlock) 96. Some operations on function parameters declared with array types could give spurious errors. (Kelvin Sherlock) 97. Floating point division by 0.0 is now consistently allowed. It can be used to generate infinities, consistent with the principles of IEEE/SANE arithmetic. (Kelvin Sherlock) 98. Some uses of enum constants in integer constant expressions could give spurious errors or generate bad code. 99. Common subexpression elimination could cause a crash or a spurious error in certain rare circumstances. 100. Fixed various cases where code in ORCA/C might dereference null pointers. Some of these could potentially lead to spurious errors, memory trashing, or possibly crashes. 101. Incrementing or decrementing pointers to types with a size of 64 KiB or larger would generally not work correctly (even with the large memory model). 102. Invalid sym files could be generated if an #include was encountered within the scope of an #if or #ifdef in the main source file, leading to spurious "type conflict" errors on subsequent compilations. 103. In certain very obscure circumstances, stale values of __DATE__ or __TIME__ could be stored in the sym file and used on subsequent compilations. 104. Initializing bitfields of type long could lead to a spurious "compiler error" (and memory trashing). 105. The WDM instruction is now supported in the mini-assembler. It is treated as taking a one-byte numeric operand. 107. Declaration specifiers (storage class specifiers, type specifiers, type qualifiers, function specifiers, and alignment specifiers) can now appear in any order within a declaration or type name. 108. Prototyped function parameter types can now begin with "volatile". 109. strtoul() should return 0 when given an empty string. It now does, and also sets errno to EINVAL in that case. (This was a regression introduced in ORCA/C 2.2.0 B3.) 110. strtok() might not always return NULL after having reached the end of the string. (This depended on the contents of memory location 0.) 111. The fscanf() family of functions might corrupt the stack if a scan error occurred and certain conversion specifiers containing the % character in a scanset (e.g. %4[%]) appeared as subsequent elements in the format string. (Kelvin Sherlock) 112. If #pragma rtl was used, the exit() family of functions would still try to exit the program via a GS/OS Quit call instead of an RTL. (Sheppy) 113. strtol(), atoi(), and atol() would accept numbers with extra white space and/or an additional plus sign after the initial sign, e.g. "- +53". 114. strtoul() will now accept numbers with a leading minus sign. This causes the value to be negated in the unsigned long type before being returned. 115. strtol() and strtoul() did not always set the end pointer to the right value in error cases. Now they do: 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 was passed in to them. 116. strtol() now accepts "-2147483648" or equivalent in other bases (i.e. LONG_MIN) as a valid input, and does not set errno in this case. 117. Register optimization could generate incorrect code in some cases. (Kelvin Sherlock) 118. Unnamed bit-fields with non-zero widths were treated as taking up no space. They now take up the same space as a named bit-field of the same width would. 119. The compiler allowed non-pointer types to be dereferenced when used as an l-value. (Kelvin Sherlock) 120. The # operator in macros, which makes a string literal from the tokens passed as an argument to the macro, now puts quotes around string literal tokens and inserts spaces corresponding to whitespace between tokens. 121. freopen() did not properly handle modes with 'b' before '+' (e.g. "rb+"). 122. If tmpnam() is called with a non-null pointer argument, it should return that same pointer, not a pointer to its internal static buffer. 123. When running under a multitasking environment, there was a theoretical possibility that a race condition could cause tmpfile() to open a file that had already been created by another program running concurrently. It will now return NULL in the very unlikely situation where this would occur. 124. localtime() would set tm_isdst based on the system's current DST setting even when given a time_t argument other than the current time, so the tm_isdst value might be incorrect. 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 (as configured in the Time CDev) in effect at the time of that call. Otherwise, it sets tm_isdst to -1, indicating that the correct value is unknown. (Steve Reeves) 125. Within character constants, /* or // should not start a comment. 126. In a proprocessor expression, any identifiers remaining after macro expansion should be replaced with the constant 0. This did not work correctly for declared variable or function names, nor for enumeration constants. (Bug fixes below here were added in ORCA/C 2.2.0 B5.) 127. ORCA/C internally treated types with the same representation (e.g. short and int) as essentially being the same type, and therefore did not report type conflicts between these types, including in some circumstances where the C standards require a diagnostic message to be produced. These type conflicts are now reported. However, char and unsigned char are still treated as compatible by default (controlled by a new bit in #pragma ignore, described above). 128. The ++ and -- operators often would not work correctly on bit-fields, or on floating-point values that were in a structure or were accessed via a pointer. 129. Certain invalid compound assignment expressions were erroneously permitted. 130. In the fprintf() family of functions, %#x or %#X conversions should not print the 0x or 0X prefix if the value is 0. 131. In the fprintf() family of functions, if the field width or precision in a conversion specification was * (indicating that it will be specified by an argument to the function) and the corresponding argument was negative, the behavior could be incorrect. It now behaves correctly, as follows: if a negative argument is given for the field width, it is treated like a positive field width with the - flag. If a negative argument is given for the precision, it is treated as if the precision was not specified. 132. In the fprintf() family of functions, if a d, i, o, u, x, or X conversion has a precision specified, the 0 flag should be ignored even if present. 133. In certain cases where a cast expression was used in a language construct that implicitly compares its value against 0 (such as an if statement), the comparison could be mis-evaluated, leading to execution of the wrong code path. 134. Negative values of type signed char could be handled incorrectly in several cases, making them behave as if they had a positive value outside the range representable by signed char. 135. Hexadecimal and octal constants in the range 0x80000000 to 0xFFFFFFFF should have the type unsigned long int, but they were being treated as having the type signed long int (with negative values) instead. 136. Numeric constants with duplicate suffixes (e.g. "123ulu") were incorrectly being accepted. 137. Trying to define a macro to + or - on the command line (with the -d option) would actually define it to 0 instead. Now this gives an error, indicating that the definition is unsupported. (Currently, macros can only be defined via the command line to an identifier, a numeric constant, or a string literal.) 138. In the fscanf() family of functions, the 'o', 'u', 'x', and 'X' conversions should accept an integer optionally preceded by a plus or minus sign. 139. In the fscanf() family of functions, if the input item for an integer conversion contains a sign and/or (if applicable) an '0x' or '0X' prefix but does not contain any digits of the number, it is not a matching sequence. This should be treated as a matching failure, causing no assignment to be done and causing the function to return without processing any further directives. 140. In the fscanf() family of functions, a %% conversion should be able to consume leading whitespace before the % character. 141. In the fscanf() family of functions, input failures on certain directives (before having performed any conversions) would not cause them to return EOF. 142. In the fscanf() family of functions, if a 'd' or 'i' conversion specification includes a maximum field width, a leading + or - sign in the number should count toward that field width. 143. In the fscanf() family of functions, if a directive fails and causes the function to return before it has done all the possible assignments, then it would trash a word on the stack, potentially causing a crash or other problems. 144. In the fscanf() family of functions, the number of characters reported as read by an 'n' conversion could be off by one if a previous 's' or '[' conversion read to the end of the available input and encountered EOF. 145. In expressions like "exp | -1" or "exp & 0", the intermediate code peephole optimizer could optimize away the evaluation of "exp" even though it had side effects (e.g. a function call or assignment). 146. In initializers for static data, expressions where an integer with unsigned type was added to an array address (e.g. "a + 1U") would not be accepted. 147. The and headers include several non-standard functions and macros. Their declarations and definitions should be omitted if __KeepNamespacePure__ is defined. 148. When an expression that the intermediate code peephole optimizer could reduce to a constant was cast to a character type, the resulting value could be outside the range of that type. 149. When qsort() was called with a count argument of 0 and certain values for the other arguments, it might behave incorrectly, possibly causing a crash. (Kelvin Sherlock) 150. Constants and constant expressions of type long double (aka extended) were only represented and evaluated with the range and precision of double, often producing less accurate results and potentially giving infinities for numbers that should have been within the range of finite long double values. Now, they are evaluated in the long double format, with its full range and precision. In fact, all floating-point expressions are now evaluated in the long double format. See "Evaluation of Floating-Point Expressions and Constants," above. 151. An explicit cast to a floating-point type should produce a value that is exactly representable in that type's format, with no extra range or precision. Similarly, the value of an assignment expression should be exactly the value stored, with no more range or precision than that of the location it was stored to. ORCA/C was not reducing the range and precision of floating-point values in these cases, but now it does. 152. sizeof did not give the right values for certain expressions of floating-point and character types, including expressions cast to those types. 153. The postfix ++ and -- operators might not give exactly the original value when applied to floating-point variables. 154. If the upper byte of the int argument to memset() was nonzero, it could set the memory locations to the wrong value. It now properly converts the int argument to unsigned char and uses that value (i.e. only the low-order byte). 155. Extra characters (detritus from the on-screen spinner) could be left in the compiler's output when #pragma expand 1 was used. 156. The second subexpression of a ? : expression may use the comma operator, even in a context where commas would otherwise separate items (such as arguments to a function). For example, abs(1 ? 2,-3 : 4) is a valid call that passes one argument. Code like this was causing spurious errors, but now it is accepted. 157. An error was not reported if code tried to define an enumeration constant with a value in the range 0xFFFF8000 to 0xFFFFFFFF. (Enumeration constants are limited to values representable as an int.) 158. An "illegal type cast" error would be reported when an illegal operator was used in a constant expression. An appropriate error message is now produced. 159. The CLOCKS_PER_SEC and CLK_TCK macros were hard-coded as 60, but they should actually be 50 if the system is in 50Hz video mode. This could throw off timing code that used these macros in conjunction with clock(). The macros now expand to code that will detect the video mode and give the appropriate value. 160. The volatile type qualifier was omitted from declarations recorded in a .sym file. This could lead to volatile accesses being optimized away. 161. The system() function might return the wrong value when using the large memory model. (This was a regression introduced in ORCA/C 2.2.0 B3.) 162. In certain cases, an assignment from a location with an 8-bit type to a location with a 16-bit type might store the wrong value. 163. When an argument of type double was passed to a function taking variable arguments, va_arg(ap,double) would not retrieve it correctly. (Devin Reade) 164. The fields of const-qualified structs and unions were not treated as being const-qualified. Neither were the members of arrays declared like "const T a", where T is a typedef'd array type. Now such fields and array members are treated as const-qualified, so assignments to them will give errors. -- Bugs from C 2.1.0 that have been fixed ----------------------------------- 1. In some situations, fread() reread the first 1K or so of the file. (Devin Reade) 2. Typedef names used as macro parameters were not treated properly. (Devin Reade) 3. In the error message "pascal qualifier is only allowed on functions", qualifier was spelled qualtifier. (Kelvin Sherlock) 4. strtod() and atof() did not handle errors correctly when the input string contained leading whitespace and no valid numeric characters, or when the input string was the NULL pointer. (Dave Tribby) -- Bugs from C 2.0.3 that have been fixed ----------------------------------- 1. Corrected a very rare bug that caused an unreliable value to be used in determining the type of an assignment statement. 2. Converting a value larger than 2147483647.0 from a real representation to an unsigned long integer representation did not generally work correctly. (Soenke Behrens) 3. Variables declared as "unsigned" were treated as "int" rather than "unsigned int". (Soenke Behrens, Philipp Vandry) 4. isgraph(' ') was true; it now correctly returns 0. (Soenke Behrens) 5. When asked to scan 65536 or more bytes, memchr actually scanned an extra 65536 bytes, often returning an incorrect result. (Soenke Behrens) 6. scanf("%d", &i) did not return EOF if it was used twice in succession, once with a numeric line followed by a return, and then pressing Control-@ o signal and end of file. (Sharon Barbaccia) 7. A switch statement with a default label but no case labels now generates the correct code to jump to the default label. (Animasia, Soenke Behrens, Michael Hackett) 8. In textedit.h, the last parameter to TEInsert was a Long; it has been changed to Handle. (Norm Dodge) 9. In time.h, NULL and size_t are now declared. (Soenke Behrens) 10. In time.h, string.h, stdio.h and stdlib.h, several functions that should have had const arguments do, now. (Soenke Behrens) 11. 0x8000 * 1 and 0x80000000 * 1 are now evaluated correctly. (Note: This actually showed up as a pointer offset bug, where *ptr = (char *)0x00C000; int offset = -32768; gave an incorrect result for ptr + offset). (Soenke Behrens, David Empson) 12. In expressions that could be evaluated at compile time, results that overflowed an integer frequently resulted in the constant being improperly promoted from an integer or unsigned to a long or unsigned long. Examples of expressions that would cause this kind of error are (65533U + 1U) / 2 and 0x8000|1. (Soenke Behrens, David Empson, Jay Krell) 13. In expressions that could be evaluated at compile time, binary operations involving an unsigned and integer were treated as an integer, when they should be treated as unsigned. This applies both to short and long operands. (Soenke Behrens, David Empson, Jay Krell) 14. The first and last parameter to FWEntry were reversed by the tool glue code. (Soenke Behrens, David Empson) 15. Storing multiple long values through a pointer stored in a global or static variable, as in a->b = a->c = 0L; where b and c are long and a is a global pointer, did not store the correct value in any but the rightmost operand. (Soenke Behrens, Derek Taubert) 16. Code generation has been improved for optimized code when a value is stored through a global or static pointer. 17. A linefeed between a macro name and the ( before the macro arguments caused a spurious compiler error. (Soenke Behrens, Jay Krell) 18. When skipping tokens due to a preprocessor command, ORCA/C was flagging # tokens from assembly language code as an error. Frankly, I can read the standard either way here. It's clear that skipped code must be tokenized. It is not clear whether # is allowed as a token in skipped code. Since I've gotten close to a bazilion complaints about this, though, I'm streatching things to allow # in skipped code, even without using the ignore pragma. (Soenke Behrens, Matt Ackeret) 19. In misctool.h, the fields in the HexTime struct were reversed, causing problems with the WriteTimeHex call. (Soenke Behrens, David Empson) 20. In stdio.h, fputc(), putchar() and ungetc() were declared with char parameters that should have been declared as int. In ctype.h, the same is true for tolower() and toupper(). (Soenke Behrens) 21. signal.h did not define sig_atomic_t; (Soenke Behrens) 22. Loads of double values were not performed correctly by the FPE version of the SysFloat library, resulting in a large loss of precision. (Soenke Behrens, Dirk Froehling, Frank Gizinski, Doug Gwyn) 23. Function parameters of type (const void *) generated an error when a pointer type was passed, rather than treating all pointer types as compatible. (Animasia) 24. There are several technical violations of the ANSI C namespace for header files. Basically, ANSI C says a compiler can't declare names in headers other than those documented in the standard unless they follow some very specific rules. Identifiers that start with an underscore and are followed by another underscore or an uppercase letter are reserved for use by the implementation. If you avoid these and all names explicitly defined by ANSI C, you should not have problems. Because ORCA/C defines some names other than those declared in the standard, and also because these names do not start with an underscore followed by an underscore or uppercase letter, there is the very slight potential that a program that should compile correctly won't. This bug can be corrected with the new libraries by defining a macro __KeepNamespacePure__ before including any header files. At some point I plan to define a header file that is always included, and you could define this macro there for 100% ANSI namespace compatibility. Until that time, though, the bug technically will continue to exist, but you have an easy workaround: just define the macro like this: #define __KeepNamespacePure__ 0 before the #include's in any file that should compile under ANSI C, but has namespace problems. (Soenke Behrens) 25. The various arguments and return types in math.h were declared as extended; they have been changed to double. (This actually doesn't make any difference, since all arguments and return types are promoted to extended anyway.) (Soenke Behrens) 26. The second parameter of the modf() function was of type (int *); this has been changed to (double *). (Soenke Behrens, Jay Krell) 27. In starg.h, va_end was declared as a function, when it must be a macro. It is now a macro. (Soenke Behrens) 28. localtime() now sets tm_isdst based on the BRAM setting. You can change the BRAM setting using the Clock CDev. (Soenke Behrens, Marlin Allred) 29. Mixing an integer 0 with a pointer in a conditional expression, as in void *p, *q = 0xdeadbeef; p = (1) ? 0 : q; generated incorrect code. (Soenke Behrens, Devin Reade) 30. If all of the following contitions are met, the 2.0.3 compiler crashes: a. Debug code is turned on (as in #pragma debug -1). b. A struct type is defined, and one of the elements of the struct type is a pointer back to the same struct type. (Think linked lists.) c. A function is defined containing a variable of this struct type, and that variable is the first variable processed when the compiler builds the debug symbol table. (Soenke Behrens) 31. Initlializers did not work for types defined like "static const struct foo bar[] = " Leaving out const worked fine. (Soenke Behrens) 32. Using const after a struct or union typedef name and before the variable name, as in struct charname { const char *symbol; const char *crypted; }; static struct charname const charname[3]; caused a spurious compiler error. (Soenke Behrens) 33. Casting an unsigned long value to double did not work correctly when the value being cast could not be evaluated until run-time, and when the value exceeded 0x7FFFFFFFul. (Soenke Behrens, Philipp Vandry) 34. Ignoring a long value returned by a tool call by casting the result to void, as in (void) ConvSeconds (TimeRec2ProDOS, 0L, (Pointer) &time); left the results on the stack, which generally resulted in a crash. The value is correctly removed, now. (Soenke Behrens, David Empson) 35. In some cases, nesting an increment or decriment operator around another increment or decrement operator, as in foo[*sp++]++ generated incorrect code. (Soenke Behrens) 36. Declaring a function using prototyped parameters, then defining it with K&R parameters, as in extern void foo (int *, int *); void foo (bar, gorp) int *bar, *gorp; {} generated incorrect code for accessing the parameters. (Soenke Behrens) 37. The compiler did not flag an error when an old-style struct parameter was used in a prototyped function declatation, as in: void foo (int x) struct bar = {1,2}; { return; } (Peter Watson, Soenke Behrens) 38. The predefined macros __LINE__, __STDC__ and __ORCAC__ did not work correctly when used with the ## operator. (Soenke Behrens, Jay Krell) 39. The __VERSION__ macro was not corrently updated in several earlier versions. It is now in lock-step with the version number printed when ORCA/C compiles a program, making it much more likely that it will stay correct. (Michael Hackett) 40. scanf() and its cousins incremented the number of items scanned when a %d or %i specifier encountered an input stream with no matching number. For example, sscanf("foo","%d",&bar) returned 1, when it should return 0, indicating that no number was found in the input stream. (Soenke Behrens) 41. When handling character set specifiers, scanf() and its cousins are supposed to allow ] as the first character in a set. For example, "%[]]" should scan ']', while "%[^]]" should scan all but ']'. This works correctly, now. (Jay Krell, Soenke Behrens) 42. With a file opened as "rb+", writing a single character and then closing the file did not always write the character to the output file. Multiple character writes would succeed. (Peter Watson, Soenke Behrens) 43. When a file is opened for reading and writing (as with "r+"), then a read is done, followed by an fflush(), the file should be available for output. In ORCA/C 2.0.3, it was not reset so output could occur. Note that this is generally no big deal, since the behavior of fflush() is undefined if the most recent operation on the file was input. In other words, the file position is not reliable. In general, you should use fseek(), fsetpos() or rewind() to change a file from input to output mode, not fflush(). (Soenke Behrens) 44. fflush(NULL) should flush all open streams. Starting with this version, it does. 45. With output redirected to a file and input comming from the keyboard, pressing the return key echoed the return that should have shown up on the screen to the output file. (Soenke Behrens, David Empson) 46. ORCA/C was allowing prototyped parameter lists with types but no identifier, as in foo (int, float) in both function declarations and function definitions. They should only be allowed in function declarations, and now cause an error if the identifier is missing in a function definition. (Soenke Behrens) 47. Variable argument functions that pass too many parameters are legal, and should not cause the compiler to behave in an unexpected way. ORCA/C now allows such function calls. See #pragma optimize for some details. (Soenke Behrens) 48. Assignments of structs or unions were sometimes removed from a loop by the loop invariant removal optimization when they should not have been removed. (Animasia) 49. A unary + operator was not allowed at the start of an expression. (Soenke Behrens) 50. When calling a pascal function from the C compiler's inline assembler, the compiler did not capitolize the identifier, resulting in link errors. (Jay Krell, Soenke Behrens) 51. ORCA/C 2.0.3 did not accept -1 as a value for period in #pragma nda, although documentation said it would. It now accepts a leading + or -. (Peter Watson, Soenke Behrens) 52. The compiler complained with "identifier expected" when doing something like: typedef char *ptr; typedef void *vptr; #define ptr vptr It should not care, since the preprocessor is a simple text substitution system. (Jay Krell, Soenke Behrens) 53. Multiple ## operators, as in #define cat(a,b,c) a##b##c were not handled correctly. (Soenke Behrens) 54. #append was not resetting the line counter used by the __LINE__ macro. It does, now. (Soenke Behrens) 55. When handling numeric escape sequences like '\x0077', ORCA/C has always limited the number of numeric characters actually scanned. In this specific example, the result would have been two characters, one with a value of 0x07 and another with the value '7'. According to the ANSI standard, all characters that can be included in a numeric sequence should be accepted. This, the above example should give a single character with a value of 0x77; it does now. (Dave Huang, Soenke Behrens) 56. printf("%#.0x", 0) should not print anything; it was printing 0x. (Soenke Behrens) 57. scanf with the '[' format specifier treated an input string with no matching characters as a valid match, returning a null string. It should have treated an input sequence with no matching characters as an error. (Soenke Behrens) 58. In several places, if output was suppressed and a scanf input failed, scanf returned one less than the correct number of inputs scanned. 59. Several functions were defined as macro overrides, and the macro overrides called other standard C functions. This could cause a problem in obscure cases where the function defined as a macro was used, but the user replaced the standar function it calls with one of their own. All of these cases have been corrected in some way so this cannot happen. The affected functions are: stdio.h: getc(), putc(), rewind(), setbuf() (Soenke Behrens) 60. Several functions were defined as macro overrides. This works fine unless the function is used form a program that does not include the header file. These functions have all been recreated as true library functions that will link into a program whether or not the header file is included. In cases where is more efficient to use the macro than to make a function call, the macro definition has been left in place. This is not a violation of the standard, but if if bothers you, you can eliminate the macro and replace it with the header file form shown in the ANSI standard or any correct C reference manual. If you do this, your program may end up a little larger or slower, but it will still work, since the functions do exist in ORCALib. The affected functions are: stdio.h: getc(), putc(), rewind(), setbuf() ctype.h: isalnum(), isalpha(), iscntrl(), isdigit(), isgraph(), islower(), isprint(), ispunct(), isspace(), isupper(), isxdigit() (Soenke Behrens) 61. Definitions like extern int foo = 0; are now legal. Once you wade through the technical language of the standard, it turns out that this declaration works exactly as if the extern is left off. Note that this definition is illegal in virtually all dialects of C except ANSI C. In particular, it is not legal in either K&R C or C++. Since there is no real reason to ever use it, I recomment you don't. (Soenke Behrens) 62. When the compiler found a single error, it ended with the message "1 errors found." It now ends with "1 error found." 63. ORCA/C now supports tenative definitions. Basically, this means that variables declared at the program level can be declared as many times as you like, with or without the extern qualifier. The only restrictions are: 1. The types must match on all of the declarations and definitions. 2. A variable can only get an initializer in one place, even if the same initializer is used in all places. That place does NOT have to be the last place the variable appears, though. 3. If a variable is declared without the static qualifier, it cannot be declared in any other source file without the static qualifier. This isn't really a change, but the restriction still applies. Note that you can use extern and an initializer at the same time, now. (See bug 61.) The result is a declaration, though, not a definition. In other words, if extern int foo = 4; appears in one source file, it is an error if int foo; appears in some other source file; you will get i duplicate symbol error in the linker. If the first instance is changed to extern int foo; then this is a definition, and references to the variable actually use the one declared in the other source file. (Soenke Behrens) 64. Making a function call though a variable that is declared but not a function, as in int foo; foo(4); did not generate an error, and caused various problems, like incorrect code generation or compile time hangs. This will now generate an error. (David Empson, Soenke Behrens) 65. If the last include in a source file was followed immediately by a #endif, the compiler generated a spurious error whenever a .sym file was available. (Jay Krell, Soenke Behrens, JoeV16@AOL.COM, Michael Hackett) 66. assert() now prints the argument as a string, in addition to the file and line number. (Soenke Behrens) 67. asert() now writes to stderr, not stdout. (Soenke Behrens) 68. In some situations where a number is referenced indirectly, and added to itself, and when intermediate code optimization was used, the compiler could fail with a terminal compiler error. One example that caused this problem is: #pragma optimize 1 ... x = ptr->field + 1 + (ptr->field + 1); (Guy Umbright, Michael Hackett) 69. The midiSynth tool call GetMSData needed a tool glue routine; it has one, now. (Dave Tribby, Michael Hackett) 70. String constants formed using the macro stringization operator (#) were always disposed of at the end of a subroutine. This caused problems if the resulting string was used to initialize a static variable, since ORCA/C creates the static variable strings long after the subroutine is complete. (Philippe Manet, Michael Hackett) 71. strstr("abc", "") took an excessive amount of time to return an incorrect result. It now returns "abc", as required when the search string is the null string. (Doug Gwyn, Michael Hackett) 72. fwrite() now returns a correct element count when a disk full error occurs during a write. (Todd Whitesel, Michael Hackett) 73. The Gamm.cc benchmark gave incorrect results. This was due to a coding error in the benchmark itself. It has been corrected on the latest samples disk. 74. Pointers to functions were not entered in the debug table properly, causing debuggers to have a variety of problems. Debuggers generally show what a pointer points to, and there's no realistic way to do that for a pointer to a function, so the compiler now enters pointers to functions in the debug symbol table as if they are pointers to integers. (Michael Hackett) -- Bugs from C 2.0.2 that have been fixed ----------------------------------- 1. Debug code was inadvertantly left in the 2.0.2 compiler release. This could cause crashes or entry into a debugger, as well as extraneous text output during a compile. (Joe Wankerl) 2. The comments in stdarg.h were ended too early, so stdarg.h did not compile. -- Bugs from C 2.0.1 that have been fixed ----------------------------------- 1. The #line directive does not set the source file in a way that causes the debugger to use a different source file. (Gary Desrochers) 2. The #line directive now allows a line number of 0. 3. The results of the #line directive are now saved in the .sym file, so file names and line numbers are preserved when the .sym file is read. 4. stdarg.h has been modified to work with the stricter error checking for type casts implemented in C 2.0.1. (Doug Gwynn) -- Bugs from C 2.0 that have been fixed ------------------------------------- 1. In desk.h, added CloseNDAbyWinPtr to match TBR #1. Apple's original spelling (CloseNDAByWinPtr) has been retained for compatibility with existing source. (Dave Tribby) 2. In locator.h, an extraneous ; has been removed. (Dave Tribby, John Mills) 3. In sane.h, the spellings DecForm and Decimal have been added so Apple's naming scheme in the remainder of the file will work. (Dave Tribby) 4. In MidiSynth.h, the following spelling corrections were made: from to ---- -- WavAddrB WaveAddrB FindTuneA TineTuneA (Dave Tribby) 5. In MidiSynth.h, added SetBasicChan to match TBR. Apple's original spelling (SetBasicChannel) has been retained for compatibility with existing source. (Dave Tribby) 6. With static or global integers, multiple assignments of zero (e.g. a=b=0) stored random values in all but the last value. (Doug Gwyn, D.Leffler, AFAAndyW, et. al.) 7. strtod() and related functions fail when the input is a single digit number. (James C.Smith) 8. SaveTextState() in Locator.h did not have an inline directive. (GSPlusDiz) 9. In some cases, successive stores of a long constant with common subexpression elimination turned on would damage the stack. (GNOTim2) 10. Assigning the same constant to both a single-byte value and a word, as in unsigned char foo; unsigned int bar; bar = foo = 1; did not correctly set the most significant byte of the word value. (GNOTim2) 11. In some conditional branches involcing comples integer expressions, the condition code was not properly evaluated. (GNOTim2) 12. Optimization of arithmetic shifts by a constant in the range 9..15 has been improved. (GNOTim2) 13. Closing carriage return added to ToolLib.h. (Doug Gwyn) 14. Some comparisons of pointers to pointers, such as *p1 == *p2, caused the code generator to generate a spurious error. (Soenke Behrens) 15. strtoul() would fail when a string address at the start of a bank was passed. (AFA AndyW) 16. fread() and fwrite() now return results of size_t. (John Joganic) 17. Text programs didn't work when launched from the Finder. (JamesG7858) 18. Run-time error checks for two-byte add and subtract operations flagged legal operations as illegal. Run-time error checks for two-byte adds and subtracts have been removed. (D.Tribby) 19. fclose() did not properly close temp files before trying to destroy them. (Jawaid Bazyar) 20. Decrementing a global or static long by 1 generated incorrect code. This was fixed in an earlier version, but I don't remember which one. (Jawaid Bazyar) 21. The type for ptrdiff_t in stddef.h should be a signed type, not unsigned long. (Doug Gwyn) 22. Using the large memory model, some two-byte load operations used absolute addressing when they should have used long absoule addressing. (AFAAndyW) 23. IBeamCursor() (in QDAux.h) is prototyped with a Word parameter; it should be void. (J.Mills11) 24. TEInsert() (in TextEdit.h) has one too few parameters prototyped. (J.Mills11) 25. Improperly set optionList parameters on GetFileInfo calls were causing compiler crashes, generally in a pseudo-random way, but most often while creating .sym files. (Walker Archer) 26. With optimize 1, adding 1 to a global long and saving the result to the same location generated incorrect code. (e.g. v := v+1 or ++v where v is a global 4-byte value.) 27. The purge call to remove an included file from memory was not working correctly. (Jawaid Bazyar) 28. Casting an l-value is not legal, but the compiler did not flag an error. (Marc Wolfgram, Doug Gwyn) 29. Macro stringization of a string produced a garbage result. (D.Kopper) 30. A conditional jump based on a load of a signed character could be evaluated incorrectly. 31. In several places, particularly in the .CONSOLE standard I/O routines, the libraries used absolute addressing when long addressing should have been used, or when the databank register should have been set to K. These problems could cause loads and stores or loss of character output with the large memory model. (Marsha J, John Joganic, et. al.) 32. The library routine that sets bank zero memory to zero trashes the data register. (GSPlusDiz) 33. gets() does not write a terminating null character if the return key is pressed right away. (Jawaid Bazyar) 34. C programs hang when input is read through standard in and standard in is redirected from a file using a shell command. (Jawaid Bazyar) 35. sys_nerr is 6; it should be 11. (Doug Gwynn, Joe Walters) 36. When a single code segment exceeds 32K, the compiler could loose track of the correct length for an object file. 37. In some cases, a conditional branch based on the result of a divide or add could fail.