ORCA/C 2.2.0 B1 Copyright 1997, Byte Works Inc. -- Change List -------------------------------------------------------------- 2.2.0 B1 1. Bugs squashed. See bug notes, below. 2. New language features added (mainly features from C99). See "Compiler changes introduced in C 2.2.0." 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." 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. The loop invariant removal optimization pass can create infinite loops or otherwise generate bad code in some cases. 2. The % operator will generally not work correctly when either operand is negative. It may produce an incorrect result, or in certain scenarios it may give a compile-time or run-time error. 3. Not all orderings of storage class specifiers, type qualifiers, and type specifiers are supported in declarations and type names. 4. 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 0 if it handled the action and 1 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. 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. 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 numeric escape sequence until no more hexadecimal characters are found. The result is then anded with 0x00FF to yield a single character. (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 discussion concerning floating-point constants is misleading. While constants are indeed handled as extended values in the executable program, the compiler itself uses double values for the constants internally, so you need to adhere to the valid exponent range for double values, and you should expect to see accuracy in constants that is in line with double values. p. 241 ORCA/C now supports // comments. See "// Comments," 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. 258 The #pragma ignore directive supports two new bits. Bit 1 affects the interpretation of multi-character character constants. See "Multi-Character Character Constants," 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. 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. 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. 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. 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. 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. The assertion has the form Assertion failed: file :hd:foo.cc, line 47; assertion: bar==1 The documentation states assert() writes to stdout. Beginning with ORCA/C 2.1, it writes to stderr. p. 353 The discussion of _exit() should note that the _exit() function is an extension to ANSI C. 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() 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 language standard. 1. (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.) 2. (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. 3. (C99) Enumeration specifiers may contain a trailing comma, e.g. enum color {black, purple, green, white,} pencolor; (Kelvin Sherlock) 4. (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. 5. 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) 6. 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.) 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) 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 not harmful to enable both types of debugging information at the same time. (Kelvin Sherlock) New Headers ----------- ORCA/C now includes three new headers specified by recent C standards. 1. 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. It complies with the C95, C99, and C11 standards. 2. The header defines various integer types with certain sizes and properties, as well as macros related to integer types. It largely complies with the C99 and C11 standards, but is missing 64-bit integer types because ORCA/C does not currently support them. For the same reason, intmax_t and uintmax_t are 32-bit types, even though C99 and C11 require them to be 64-bit or larger types. 3. 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. The macros provided generally conform to the C99 and C11 standards, but certain macros specified by the standards are not available due to ORCA/C limitations. The functions that the standards specify should be declared in this header are also not available. -- 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 restruction 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 presense 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 oter 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 undesireable 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 long and unsigned long types, as required by the ANSI C89 standard. 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.) -- 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.