Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the value of '\n' under C compilers for old Mac OS?

Tags:

c++

c

mac-classic

The values of the character constants \r and \n was the exact same in Classic Mac OS environments as it was everywhere else: \r was CR was ASCII 13 (0x0d); \n was LF was ASCII 10 (0x0a). The only thing that was different on Classic Mac OS was that \r was used as the "standard" line ending in text editors, just like \n is used on UNIX systems, or \r\n on DOS and Windows systems.

Here's a screenshot of a simple test program running in Metrowerks CodeWarrior on Mac OS 9, for instance:

Example program running in CodeWarrior

Keep in mind that Classic Mac OS systems didn't have a system-wide standard C library! Functions like printf() were only present as part of compiler-specific libraries like SIOUX for CodeWarrior, which implemented C standard I/O by writing output to a window with a text field in it. As such, some implementations of standard file I/O may have performed some automatic translation between \r and \n, which may be what you're thinking of. (Many Windows systems do similar things for \r\n if you don't pass the "b" flag to fopen(), for instance.) There was certainly nothing like that in the Mac OS Toolbox, though.


I've done a search and found this page with an old discussion where especially the following can be found:

The Metrowerks MacOS implementation goes a step further by reversing the significance of CR and LF with regard to the '\r' and '\n' escapes in i/o involving a file, but not in any other context. This means that if you open a FILE or fstream in text mode, every '\r' will be output there as an LF as well as every '\n' being output as CR, and the same is true of input - the escape-to-ASCII-binary correspondences are reversed. They are not reversed however in memory, e.g. with sprintf() to a buffer or with a std::stringstream. I find this confusing and, if not non-standard, at least worse than other implementations.

It turns out there is a workaround with MSL - if you open the file in binary mode then '\n' always == LF and '\r' always == CR. This is what I wanted but in getting this information I also got a lot of justification from folks over there that this was the "standard" way to get what I wanted, when I feel like this is more like a workaround for a bug in their implementation. After all, CR and LF are 7-bit ASCII values and I'd expect to be able to use them in a standard way with a file opened in text mode.

(An answer makes clear that this is indeed not a violation of the standard.)

So obviously there was at least one implementation which used \n and \r with the usual ASCII values, but translated them in (non-binary) file output (by just exchanging them).


On older Mac compilers, the roles of \r and \n where reversed: We had '\n' == 13 and '\r' == 10, while today '\n' == 10 and '\r' == 13. Great fun during the transition phase. Write a '\n' to a file with an old compiler, read the file with a new compiler, and get a '\r' (of course, both times you actually had a number 13).


C-language specification:

5.2.2
...
2 Alphabetic escape sequences representing nongraphic characters in the execution character set are intended to produce actions on display devices as follows:
...
\n (new line) Moves the active position to the initial position of the next line.
\r (carriage return) Moves the active position to the initial position of the current line.

so \n represents the appropriate char in that character encoding... in ASCII is the LF char


I don't have an old Mac compiler to check if they follow this, but the numeric value of '\n' should be the same as the ASCII new line character (given that those compilers used ASCII compatible encoding as the execution encoding, which I believe they did). '\r' should have the same numeric value as the ASCII carriage return.

The library or OS functions that handle writing text mode files is responsible for converting the numeric value of '\n' to whatever the OS uses to terminate lines. The numeric values of these characters at runtime are determined entirely by the execution character set.

Thus, since we're still ASCII compatible execution encodings the numeric values should be the same as with classic Mac compilers.