Fixes in 1998/schweikh1/README.md

This includes the up to date URL. More commits will be made for this as
well.
This commit is contained in:
Cody Boone Ferguson committed 2023-04-18 08:42:44 -07:00
1 parent 2cd9f57a46
commit 7ee4f426d5
1 file changed
+87 -54
+87 -54
View File
@@ -5,12 +5,13 @@
Schlartaeckerweg 3 (Home address) Schlartaeckerweg 3 (Home address)
D-71384 Weinstadt D-71384 Weinstadt
Germany Germany
<http://www.schweikhardt.net>
http://www.shuttle.de/schweikh/
## To build: ## To build:
```sh
make all make all
```
[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for modern [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for modern
systems (it did not work at all). He also made it so that if a file fails to systems (it did not work at all). He also made it so that if a file fails to
@@ -27,6 +28,13 @@ but in macOS - see below for alternative code - `gcc` is clang).
Additionally Cody provided an alternative version for macOS. See below for the Additionally Cody provided an alternative version for macOS. See below for the
alternative version. Thank you Cody for your assistance! alternative version. Thank you Cody for your assistance!
## To run:
```sh
./schweikh1
```
### Alternative code: ### Alternative code:
As noted above [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) made an As noted above [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) made an
@@ -50,7 +58,9 @@ This goes for both versions. Now the key are two magic numbers, one on a
different line shortly below the string. In the original the numbers are, different line shortly below the string. In the original the numbers are,
respectively, 44 and 46. But how does this work? Well the string is: respectively, 44 and 46. But how does this work? Well the string is:
```
"0gcc -ansi -E -dM -undef %s /usr/include/%s>r\0 (" "0gcc -ansi -E -dM -undef %s /usr/include/%s>r\0 ("
```
The first number means: the length starting from 0 up through the `>`. The The first number means: the length starting from 0 up through the `>`. The
second number is the same starting point but up through the `\0` which is why second number is the same starting point but up through the `\0` which is why
@@ -68,10 +78,6 @@ the different command line and the different numbers.
To use this version use `schweikh1.alt` instead. To use this version use `schweikh1.alt` instead.
## To run:
./schweikh1
## Judges' remarks: ## Judges' remarks:
What does it do? It seems to print a list of system headers, perhaps What does it do? It seems to print a list of system headers, perhaps
@@ -82,7 +88,7 @@ standard headers.
This code is a wonder; it's a wonder that it compiles. I wonder This code is a wonder; it's a wonder that it compiles. I wonder
whether or not it should. The innovative realization that you can whether or not it should. The innovative realization that you can
use special characters, such as '\n', in #file directives alone use special characters, such as `'\n'`, in #file directives alone
merits some recognition. merits some recognition.
I've included most of the author's remarks; they're fairly thorough. I've included most of the author's remarks; they're fairly thorough.
@@ -95,7 +101,7 @@ compile this entry correctly. Using cc by default is not helpful
most of the time on this entry, because the program has a hardcoded most of the time on this entry, because the program has a hardcoded
gcc invocation anyway. Anyone who uses egcs and has no plain gcc gcc invocation anyway. Anyone who uses egcs and has no plain gcc
will need to frob the source anyway and can be expected to do the will need to frob the source anyway and can be expected to do the
right thing with ${CC}. So use gcc. right thing with `${CC}`. So use gcc.
## Author's remarks ## Author's remarks
@@ -107,7 +113,9 @@ When run, it is likely to uncover bugs in your system headers.
The program is run without arguments. If your compiler is buggy, The program is run without arguments. If your compiler is buggy,
the most likely result is no output and/or an exit status of 1. the most likely result is no output and/or an exit status of 1.
If Amendment One headers are missing you will see If Amendment One headers are missing you will see something like:
```
<iso646.h>: <iso646.h>:
gcc: /usr/include/iso646.h: No such file or directory gcc: /usr/include/iso646.h: No such file or directory
gcc: No input files specified gcc: No input files specified
@@ -117,28 +125,27 @@ the most likely result is no output and/or an exit status of 1.
<wchar.h>: <wchar.h>:
gcc: /usr/include/wchar.h: No such file or directory gcc: /usr/include/wchar.h: No such file or directory
gcc: No input files specified gcc: No input files specified
```
Bug your vendor for an upgrade. Bug your vendor for an upgrade.
The format of the info file is straightforward and described in the file The format of the info file is straightforward and described in the file
itself. Just load it in your favorite editor. itself. Just load it in your favorite editor.
Requirements ### Requirements
------------
`gcc` (the GNU C compiler) must be available at runtime. It is assumed that your
C implementation keeps headers as files in the /usr/include directory. The info
file must be readable and reside in the current working directory. The current
working directory must be writable in order to create a temporary file (which is
removed upon program termination). In case you don't have gcc at runtime, not
all is lost if your compiler or preprocessor can produce a list of defined
macros in the format output by `gcc -dM`, i.e. lines of the form `#define MACRO
value`.
Gcc (the GNU C compiler) must be available at runtime. It is assumed
that your C implementation keeps headers as files in the /usr/include
directory. The info file must be readable and reside in the current
working directory. The current working directory must be writable in
order to create a temporary file (which is removed upon program
termination). In case you don't have gcc at runtime, not all is lost
if your compiler or preprocessor can produce a list of defined macros
in the format output by gcc -dM, i.e. lines of the form
#define MACRO value
Edit the source at line 55 in this case. Edit the source at line 55 in this case.
Background ### Background
----------
ISO C has a very strict idea of visibility of identifiers. All possible ISO C has a very strict idea of visibility of identifiers. All possible
macros are explicitly enumerated. In a compliant implementation no other macros are explicitly enumerated. In a compliant implementation no other
@@ -146,6 +153,7 @@ macros can be defined, because you could write strictly conforming
programs that may fail to compile due to syntax errors: suppose programs that may fail to compile due to syntax errors: suppose
`<stdio.h>` defines `PIPE_BUF`, then the conforming `<stdio.h>` defines `PIPE_BUF`, then the conforming
```c
#include <assert.h> #include <assert.h>
#include <stdio.h> /* <- or where the bogus macro is defined */ #include <stdio.h> /* <- or where the bogus macro is defined */
#include <string.h> #include <string.h>
@@ -157,99 +165,122 @@ programs that may fail to compile due to syntax errors: suppose
assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0); assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0);
return 0; return 0;
} }
```
is expected to compile and meet the assertion. If it does not, your is expected to compile and meet the assertion. If it does not, your
compiler compiles some other language than ISO C. compiler compiles some other language than ISO C.
Why I think my program is obfuscated ### Why I think my program is obfuscated
------------------------------------
Not only is the program's purpose a thorough standard conformance Not only is the program's purpose a thorough standard conformance
test. The source itself is a beast and has uncovered bugs in many test, the source itself is a beast and has uncovered bugs in many
C compilers. C compilers.
1. The token sequence after #include can consist of pp-tokens and 1. The token sequence after `#include` can consist of pp-tokens and
"are processed just as in normal text." [ISO 6.8.2] The result "are processed just as in normal text." [ISO 6.8.2] The result
must resemble one of the canonical forms, "foo.h" or <bar.h>. must resemble one of the canonical forms, `"foo.h"` or `<bar.h>`.
This lets us write things like This lets us write things like
```c
#define HEADER "foo.h" #define HEADER "foo.h"
#include HEADER #include HEADER
```
I could not find a compiler rejecting this. However, if we're I could not find a compiler rejecting this. However, if we're
torturing the preprocessor a little more, by using token pasting, torturing the preprocessor a little more, by using token pasting,
at least one compiler falls over. at least one compiler falls over.
```c
#define H(x) <st##x##.h> #define H(x) <st##x##.h>
#include H(dio) /* expands to <stdio.h> */ #include H(dio) /* expands to <stdio.h> */
```
is rejected by tcc version 4.1.2, the TenDRA compiler: is rejected by tcc version 4.1.2, the TenDRA compiler:
```
"t.c", line 3: Error: "t.c", line 3: Error:
[ISO 6.8.3.3]: Invalid result for '##' operator in macro 'H'. [ISO 6.8.3.3]: Invalid result for '##' operator in macro 'H'.
```
To be honest, I don't know if the rules for pp-tokens and token To be honest, I don't know if the rules for pp-tokens and token
pasting don't forbid what I do (and tcc is correct in rejecting it). pasting don't forbid what I do (and tcc is correct in rejecting it).
In this case, all other compilers I tried are buggy, or the Standard In this case, all other compilers I tried are buggy, or the Standard
itself :-) itself :-)
2. The #line directive allows to set a line number, and optionally 2. The `#line` directive allows to set a line number, and optionally
a file name, i.e. modify __LINE__ and __FILE__. Strange things a file name, i.e. modify `__LINE__` and `__FILE__`. Strange things
happen if the file name contains a NUL byte -- which the Standard happen if the file name contains a NUL byte -- which the Standard
allows: in #line num "file" the "file" is an s-char-sequence per allows: in `#line num "file"` the `"file"` is an s-char-sequence per
ISO 6.8.4. ISO 6.1.4 defines string literals as s-char-sequences, ISO 6.8.4. ISO 6.1.4 defines string literals as s-char-sequences,
which may include octal escape sequences. Let's look at which may include octal escape sequences. Let's look at
```c
#include <stdio.h> #include <stdio.h>
#line 42 "foo\0bar" #line 42 "foo\0bar"
int main (void) { int main (void) {
printf ("%s %d\n", __FILE__, (int)sizeof __FILE__); printf ("%s %d\n", __FILE__, (int)sizeof __FILE__);
return 0; return 0;
} }
This is supposed to output 'foo 8'. Here's what happens in RL: ```
This is supposed to output `'foo 8'`. Here's what happens in RL:
```
foo 4 gcc 2.7.2.1, lcc foo 4 gcc 2.7.2.1, lcc
foo\0bar 9 tcc 4.1.2, Sunsoft cc turn "\0" into "\\0", ugh! foo\0bar 9 tcc 4.1.2, Sunsoft cc turn "\0" into "\\0", ugh!
```
(I have written a bug report for gcc. Newer versions and egcs are ok.) (I have written a bug report for gcc. Newer versions and egcs are ok.)
3. The %: and %:%: digraphs test for conformance to Amendment One. 3. The `%:` and `%:%:` digraphs test for conformance to Amendment One.
Ask your local guru if C allows the same case label in the same switch Ask your local guru if C allows the same case label in the same switch
statement to appear more than once. Ask him/her to think real hard. statement to appear more than once. Ask him/her to think real hard.
The answer will be "no". The true guru will cite a constraint in The answer will be "no". The true guru will cite a constraint in
ISO 6.6.4.2. Then make fun of the guru's answer by waving 'case __LINE__:' ISO 6.6.4.2. Then make fun of the guru's answer by waving `case __LINE__:`
under his/her nose. Easy money from a bet! Make sure your guru has under his/her nose. Easy money from a bet! Make sure your guru has
no chance to use Standardese weasel words as an escape: can I have no chance to use Standardese weasel words as an escape: can I have
```c
case <some_token>: case <some_token>:
case <some_token>: case <some_token>:
```
in the same switch? (Note that you need the [invisible] newline. You in the same switch? (Note that you need the [invisible] newline. You
can generously allow the additional constraint that no #undefs or can generously allow the additional constraint that no `#undef`s or
#defines are allowed between the two cases.) `#define`s are allowed between the two cases.)
Lots of integer constants and string literals come into the source Lots of integer constants and string literals come into the source
via __LINE__ and __FILE__ which are redefined at various places. via `__LINE__` and `__FILE__` which are redefined at various places.
Sometimes the __FILE__ contains \0 bytes; different strings or Sometimes the `__FILE__` contains `\0` bytes; different strings or
characters are then accessed with offsets, say 10+__FILE__ or characters are then accessed with offsets, say `10+__FILE__` or
__LINE__+__FILE__ or 2[__FILE__]. One integral constant in octal. `__LINE__+__FILE__` or `2[__FILE__]`. One integral constant in octal.
This makes the source and header input depend on ASCII. This makes the source and header input depend on ASCII.
A few old obfuscations, like one character identifiers, not too A few old obfuscations, like one character identifiers, not too
many macros, a goto O, "needless" assignments to satisfy lint many macros, a `goto O`, "needless" assignments to satisfy lint
with its "function value ignored" warnings. My lint has nothing with its "function value ignored" warnings. My lint has nothing
to complain. to complain.
There's more whitespace in the Standard than just space, tab and There's more whitespace in the Standard than just space, tab and newline. In
newline. In particular, there are vertical tab and formfeed that particular, there are vertical tab and form-feed that can be used in certain
can be used in certain places (outside of preprocessing directives, places (outside of preprocessing directives, i.e. they are not allowed from just
i.e. they are not allowed from just after the # up to the final after the `#` up to the final newline. See 6.8 for details.) On many
newline. See 6.8 for details.) implementations these appear as `^L` and `^K`. My source starts with an
On many implementations these appear as ^L and ^K. My source starts extremely uncommon 32bit word consisting of `^L`, `^K`, `%` and `:`. I have
with an extremely uncommon 32bit word consisting of ^L, ^K, % and :. grepped old winning entries for ^K, none of them contains one, so this is
I have grepped old winning entries for ^K, none of them contains one, something new -- after 14 years of IOCCC. Be sure to have enough paper in your
so this is something new -- after 14 years of IOCCC. Be sure to have printer when you make a hard copy of the source...
enough paper in your printer when you make a hardcopy of the source...
While I'm at it, the rules state that only space, tab and newline While I'm at it, the rules state that only space, tab and newline
are ignored for the count (plus '{', '}', ';' followed by are ignored for the count (plus '`{`', '`}`', '`;`' followed by
whitespace). The mkentry.c program, however, uses isspace() which whitespace). The mkentry.c program, however, uses `isspace()` which
returns nonzero for vtab and formfeed and other characters as well. returns nonzero for vtab and form-feed and other characters as well.
I could have used a lot more ^K and ^L probably undetected by your I could have used a lot more ^K and ^L probably undetected by your
counter but decided to err on the side of safety. I use a perl counter but decided to err on the side of safety. I use a perl
script to compute the character count according to the rules. script to compute the character count according to the rules.
The advantages of an independent clean room approach... The advantages of an independent clean room approach...
```perl
#!/usr/bin/perl -w #!/usr/bin/perl -w
$/ = "\0"; $/ = "\0";
$_ = <>; $_ = <>;
@@ -257,11 +288,13 @@ The advantages of an independent clean room approach...
s/[ \t\n]+//g; s/[ \t\n]+//g;
print length ($_),"\n"; print length ($_),"\n";
```
I have tried, as suggested in the guidelines, to let the code look I have tried, as suggested in the guidelines, to let the code look
like ordinary C code. Apart from a few long lines I think I left like ordinary C code. Apart from a few long lines I think I left
the indentation like I would in RL. You should however not try to the indentation like I would in RL. You should however not try to
use indent on the source. The code is extremely fragile because of the use indent on the source. The code is extremely fragile because of the
myriads of __LINE__ macros -- indenting is a sure way to break myriads of `__LINE__` macros -- indenting is a sure way to break
the program. Don't even think of maintaining that beast; I've the program. Don't even think of maintaining that beast; I've
had my share of core dumps during development :-) A test suite had my share of core dumps during development :-) A test suite
was used after every minor change to find out if the program still was used after every minor change to find out if the program still