Improve my fixes to 1998/schweikh1

To make this slightly more portable still I have removed the hard-coding
of gcc to make it just be cc. In modern systems this should be fine.
This involved updating the magic numbers by subtracting one from each,
making them (in the primary version 43 and 45 and 94 and 96 in the
alternate code for macOS) but since one of the purposes of the fixes of
code include making them work in more systems I have made it use cc as
it should work (gcc is most likely in all systems anyway but it seemed
like a better idea for 2023).

I previously noted in the thanks-for-fixes.md that the mode in fopen()
could remain 44+__FILE__ (though as noted above it's now 43) but that I
had changed it to "r". This was a mistake and it is now restored though
again it is now 43 not 44.

The FILE * which was renamed to G has been changed back to H. Observe
how there is a macro with the same name. There was actually no need to
change it.

I have restored some of the control codes in the C preprocessor
directives. Unfortunately that is only prior to the #define because some
systems will give an annoying warning otherwise. For instance fedora
linux shows:

    schweikh1.c:6:8: warning: form feed in preprocessing directive
	6 | #define
		   x
		    )
		     ==
		       0
			?__LINE__:0){O
				      =__LINE__;break;}
						       }
	  |

and possibly vertical tab too.

So although it would be ideal to have them closer to the original I deem
that preventing warnings that cannot be, for whatever reason, disabled.

The thanks-for-fixes.md was updated for these changes and now includes
more details on the fixes to match the rest of the other entries (though
some might also be lacking in details).
This commit is contained in:
Cody Boone Ferguson committed 2023-10-15 05:39:49 -07:00
1 parent ec2c1b577e
commit 1b65c59cd4
5 files changed
+152 -68

No files matched your search

+1
View File
@@ -128,6 +128,7 @@ all: data ${TARGET}
${PROG}: ${PROG}.c ${PROG}: ${PROG}.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
@echo "NOTE: for macOS use the alternate code through make alt. See README.md for details."
# alternative executable # alternative executable
# #
+73 -30
View File
@@ -14,8 +14,9 @@ Germany
make all make all
``` ```
An alternate version for this entry works with macOS. See the Alternate code There is an alternate version of this entry that will work with macOS. See the
section below for more details. [Alternate code](#alternate-code) section below for details on how it works and
how to use it.
## To run: ## To run:
@@ -24,60 +25,100 @@ section below for more details.
./schweikh1 ./schweikh1
``` ```
NOTE: a limitation with the entry was that it required `gcc` but this limitation
has been removed to make it more portable, requiring only `cc`.
### Alternate code: ### Alternate code:
As noted above the alternate version works with macOS but there are some As noted above this entry will not work as it stands for macOS and there are
important notes as well as a description of how it works (spoilers for the some important notes as well as a description of how the fixed version works
original version as well). (the details of which are relevant to the original entry that no longer works as
well as the fixed version but are described in the context of the macOS
adjustments).
With a MacBook Pro Max with the M1 chip some header files report an #### macOS changes:
unsupported architecture and unsupported compiler (error, warning).
However the defines are still found okay.
For this alternate version you will need the command line tools which you can As an aside: if you have a Mac with the Apple chip, some of the header files
install like: will report an unsupported architecture and unsupported compiler (error,
warning). This will not make the program abort, however, but even with an Intel
CPU though, the original entry will not work in macOS as it stands because
`/usr/include` is hard-coded in the code and macOS does not have it.
Nevertheless, although some of it would not work in other systems where
`/usr/include` exists, the `#define`s would still be found okay, at least until
a file was not found (this limitation was removed in both versions, see
[thanks-for-fixes.md](/thanks-for-fixes.md) for details).
However, as noted, macOS does **not** have `/usr/include` so this would not ever
work for macOS without some changes, described next. For macOS you will need the
command line tools installed which can be done like:
```sh ```sh
sudo xcode-select --install sudo xcode-select --install
``` ```
Finally as far as how this works if you look at line 55 you see a funny command. An important point is that the original version hard-coded `gcc` but just like
This goes for both versions. Now the key are two magic numbers, one on a the entry, the alternate version has also removed this limitation despite `gcc`
different line shortly below the string. In the original the numbers are, existing (though it's `clang`) in macOS.
respectively, 44 and 46. But how does this work? Well the string is:
Now as far as how this works if you look at the code of
[schweikh1.c](schweikh1.c), on line 55 you'll see a funny command (this goes for
the alternate version as well but a bit different).
Now the key is two magic numbers, one (two of this exist) on a different line shortly below the
string and the other a couple lines further below.
In the original the numbers are, respectively, 44 and 46, but with the gcc
limitation removed the numbers now are 43 and 45. But how does this work? Well
the command 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 which has been changed to be:
second number is the same starting point but up through the `\0` which is why
it's +2. But what happens if only the first number is updated? Most of the
output will be just `#define` by itself; in the cases where there was text after
that it was macros that certainly were not defined. There might have been other
errors as well.
This allows for opening the right files. The problem with the macOS is ```
`/usr/include` does not exist: instead it's "0cc -ansi -E -dM -undef %s /usr/include/%s>r\0 ("
```
Shortly below that you will see, as noted above, the numbers:
```c
if ((H = fopen (__FILE__+43, 43+__FILE__)))
while ((fgets (L, (int)sizeof L, H)) != 0) {
I[strcspn (I, 45+__FILE__)] = O = 0;
```
The first number in the above C 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 it's `+2`. But what happens if only the first number is updated (from the
original)? Most of the output will be just `#define` by itself; in the cases
where there was text after that it was macros that certainly were not defined.
There might have been other errors as well.
Changing this for macOS allows for opening the right files; the problem with the
macOS is `/usr/include` does not exist: instead it's
`/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include` which is why `/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include` which is why
the different command line and the different numbers. the different command line and the different numbers. The change of the numbers
can be found in the alternate code and the explanation is the same.
To use this version use: To use this version use:
```sh ```sh
make alt make alt
``` ```
Use `schweikh1.alt` as you would `schweikh1` above. Use `schweikh1.alt` as you would `schweikh1` above.
Bonus exercise: modify the code to provide a different compiler.
## 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
with words after them. Curiously, if you look at the list of words with words after them. Curiously, if you look at the list of words
defined in a given standard header, they are never printed directly defined in a given standard header, they are never printed directly
after that header's name. Ah-hah! It's a conformance test for the after that header's name. Aha! It's a conformance test for the
standard headers. 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
@@ -90,15 +131,17 @@ Do not read them if you want to figure this out yourself. "Amendment
One" refers to "NA1", the add-on to C89 which added some fairly One" refers to "NA1", the add-on to C89 which added some fairly
crufty internationalization support. crufty internationalization support.
NOTE: Some non-gcc compilers that are not fully ANSI standard do not #### Historical note:
compile this entry correctly. Using cc by default is not helpful
most of the time on this entry, because the program has a hardcoded Some non-gcc compilers that were not fully ANSI standard did not
compile this entry correctly. Using cc by default was not helpful
most of the time on this entry, because the program had 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 one should have used gcc.
## Author's remarks ## Author's remarks:
Important! This program, if it compiles at all, is mis-compiled by many Important! This program, if it compiles at all, is mis-compiled by many
compilers due to compiler bugs. It could be the "least likely compilers due to compiler bugs. It could be the "least likely
+10 -10
View File
@@ -3,9 +3,9 @@
/*#include H(dlib)*/ /*#include H(dlib)*/
/*#include H(ring)*/ /*#include H(ring)*/
#define x ) == 0 ?__LINE__:0){O =__LINE__;break;} } #define x ) == 0 ?__LINE__:0){O =__LINE__;break;} }
#define X(x) __LINE__ x __LINE__ #define X(x) __LINE__ x __LINE__
#define t(a)\ #define t(a)\
for (c = 0; c <n##a; ++c) { \ for (c = 0; c <n##a; ++c) { \
if (strchr (a[c], 0[__FILE__])) { if (*a[c] == 0[__FILE__]) { \ if (strchr (a[c], 0[__FILE__])) { if (*a[c] == 0[__FILE__]) { \
if (strcmp (a[c]+__LINE__, I + strlen (I) + __LINE__ - strlen (a[c]) x else { \ if (strcmp (a[c]+__LINE__, I + strlen (I) + __LINE__ - strlen (a[c]) x else { \
@@ -16,11 +16,11 @@ for (c = 0; c <n##a; ++c) { \
int int
main (int C, char **V) main (int C, char **V)
{ {
FILE *G; FILE *H;
int c, ne, nn, S = C < 2 ? 060 : *V[1]; int c, ne, nn, S = C < 2 ? 060 : *V[1];
char f[__LINE__][X(*)], K[(X(*))*4], L[4*X(<<)], char f[__LINE__][X(*)], K[(X(*))*4], L[4*X(<<)],
e[X(<<)][3*__LINE__], n[X(<<)][3*__LINE__], F[__LINE__]; e[X(<<)][3*__LINE__], n[X(<<)][4*__LINE__], F[__LINE__];
if (freopen (__FILE__, "r", stdin) == 0) return __LINE__-13; if (freopen (__FILE__, "r", stdin) == 0) return __LINE__-13;
for (c = 0;;) { for (c = 0;;) {
@@ -52,17 +52,17 @@ O:
#line 8 "<%s>:\n" #line 8 "<%s>:\n"
char *I = L + __LINE__; char *I = L + __LINE__;
int O = printf (__FILE__, n[nn]) + int O = printf (__FILE__, n[nn]) +
#line 2 "0gcc -ansi -E -dM -undef %s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/%s>r\0 (" #line 2 "0cc -ansi -E -dM -undef %s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/%s>r\0 ("
sprintf (K, 1+__FILE__, f[S-*__FILE__] + __LINE__, n[nn]); sprintf (K, 1+__FILE__, f[S-*__FILE__] + __LINE__, n[nn]);
O += system (K); O += system (K);
if ((G = fopen (__FILE__+95, "r"))) if ((H = fopen (__FILE__+94, __FILE__+94)))
while ((fgets (L, (int)sizeof L, G)) != 0) { while ((fgets (L, (int)sizeof L, H)) != 0) {
I[strcspn (I, 97+__FILE__)] = O = 0; I[strcspn (I, 96+__FILE__)] = O = 0;
#line 1 "*r" #line 1 "*r"
t (n) t (e) t (n) t (e)
if (0 == O) O = puts (L); if (0 == O) O = puts (L);
} }
if (G != NULL) nn = fclose (G); if (H != NULL) nn = fclose (H);
} }
} }
} }
+9 -9
View File
@@ -3,9 +3,9 @@
/*#include H(dlib)*/ /*#include H(dlib)*/
/*#include H(ring)*/ /*#include H(ring)*/
#define x ) == 0 ?__LINE__:0){O =__LINE__;break;} } #define x ) == 0 ?__LINE__:0){O =__LINE__;break;} }
#define X(x) __LINE__ x __LINE__ #define X(x) __LINE__ x __LINE__
#define t(a)\ #define t(a)\
for (c = 0; c <n##a; ++c) { \ for (c = 0; c <n##a; ++c) { \
if (strchr (a[c], 0[__FILE__])) { if (*a[c] == 0[__FILE__]) { \ if (strchr (a[c], 0[__FILE__])) { if (*a[c] == 0[__FILE__]) { \
if (strcmp (a[c]+__LINE__, I + strlen (I) + __LINE__ - strlen (a[c]) x else { \ if (strcmp (a[c]+__LINE__, I + strlen (I) + __LINE__ - strlen (a[c]) x else { \
@@ -16,7 +16,7 @@ for (c = 0; c <n##a; ++c) { \
int int
main (int C, char **V) main (int C, char **V)
{ {
FILE *G; FILE *H;
int c, ne, nn, S = C < 2 ? 060 : *V[1]; int c, ne, nn, S = C < 2 ? 060 : *V[1];
char f[__LINE__][X(*)], K[(X(*))*4], L[4*X(<<)], char f[__LINE__][X(*)], K[(X(*))*4], L[4*X(<<)],
@@ -52,17 +52,17 @@ O:
#line 8 "<%s>:\n" #line 8 "<%s>:\n"
char *I = L + __LINE__; char *I = L + __LINE__;
int O = printf (__FILE__, n[nn]) + int O = printf (__FILE__, n[nn]) +
#line 2 "0gcc -ansi -E -dM -undef %s /usr/include/%s>r\0 (" #line 2 "0cc -ansi -E -dM -undef %s /usr/include/%s>r\0 ("
sprintf (K, 1+__FILE__, f[S-*__FILE__] + __LINE__, n[nn]); sprintf (K, 1+__FILE__, f[S-*__FILE__] + __LINE__, n[nn]);
O += system (K); O += system (K);
if ((G = fopen (__FILE__+44, "r"))) if ((H = fopen (__FILE__+43, 43+__FILE__)))
while ((fgets (L, (int)sizeof L, G)) != 0) { while ((fgets (L, (int)sizeof L, H)) != 0) {
I[strcspn (I, 46+__FILE__)] = O = 0; I[strcspn (I, 45+__FILE__)] = O = 0;
#line 1 "*r" #line 1 "*r"
t (n) t (e) t (n) t (e)
if (0 == O) O = puts (L); if (0 == O) O = puts (L);
} }
if (G != NULL) nn = fclose (G); if (H != NULL) nn = fclose (H);
} }
} }
} }
+59 -19
View File
@@ -17,13 +17,13 @@ bug fixes** such as [2001/anonymous](2001/anonymous/README.md) and
compile with clang, fixing entries to work with macOS (some of which are **very compile with clang, fixing entries to work with macOS (some of which are **very
complicated** such as [1998/schweikh1](1998/schweikh1/README.md)), fixing code complicated** such as [1998/schweikh1](1998/schweikh1/README.md)), fixing code
to work with both 32-bit and 64-bit (such as to work with both 32-bit and 64-bit (such as
[2001/herrmann2](2001/herrmann2/README.md)) which can be **quite complicated** [2001/herrmann2](2001/herrmann2/README.md)) which *can be* **quite complicated
(though not always even if it seems it), providing alternate code where useful too** (though not always even if it seems it), providing alternate code where
or necessary, fixing where possible dead links and otherwise removing them, typo useful or necessary, fixing where possible dead links and otherwise removing
and consistency fixes, improving **ALL _Makefiles_** and writing the [sgit them, typo and consistency fixes, improving **ALL _Makefiles_** and writing the
tool](https://github.com/xexyl/sgit) that we installed locally and have used to [sgit tool](https://github.com/xexyl/sgit) that we installed locally and have
easily run `sed` on files in the repository to help build the website. Thank used to easily run `sed` on files in the repository to help build the website.
you **very much** for your extensive efforts in helping improve the IOCCC Thank you **very much** for your extensive efforts in helping improve the IOCCC
presentation of past IOCCC winners and making many many past entries work with presentation of past IOCCC winners and making many many past entries work with
modern systems! modern systems!
@@ -921,20 +921,60 @@ segfault fixes should be made because the program is so beautiful.
## [1998/schweikh1](1998/schweikh1/schweikh1.c) ([README.md](1998/schweikh1/README.md])) ## [1998/schweikh1](1998/schweikh1/schweikh1.c) ([README.md](1998/schweikh1/README.md]))
Cody fixed this for modern systems (it did not work at all). He also made it so Cody fixed this for modern systems (it did not work at all) and added an
that if a file fails to open it does not return but rather skips the reading of alternate version that works with macOS. Cody also made it ever so slightly more
the file. Without this fix the entry did not work. portable by removing the hard-coding of `gcc`, instead hard-coding it `cc`. Doing
this not only lets it work with systems without `gcc` (though in macOS it does
exist but is actually `clang`) as `cc` always should.
What was wrong? The call to `freopen()` was incorrect with the second arg (the Getting this entry to work was quite complicated but is also very interesting.
mode) being instead `5+__FILE__`. It now is `"r"`. There was also a call to To see how the macOS fixes works, see the README.md but do note that this
`fopen()` that was wrong where the mode was instead `44+__FILE__`. Interestingly includes spoilers for both versions! The fixes to get it to work at all are
enough though this did not seem to be an issue though I cannot explain why. He described next.
notes that it works fine with `clang` as well as `gcc` (which is what is used
but in macOS - see below for alternate code - `gcc` is clang).
Additionally Cody provided an alternate version for macOS. The fix is So what was wrong with the original?
rather complicated but very interesting. See the README.md file for details on
how it works and how to use it. The call to `freopen()` was incorrect with the second arg (the mode) being
`5+__FILE__`; it is now `"r"`. (Observe that the mode to the `fopen()`
call is: `44+__FILE__`. This might seem incorrect and indeed it can be changed
to `"r"` as well but this was not actually necessary so once this was noticed it
was changed back to the original.)
Another important change is that the files are only closed if the `FILE *H` is
`!= NULL`. Without this check, because it's almost certain that some files will
not exist, it would dereference a NULL pointer and very likely crash or halt and
catch fire :-), preventing the entry from working. Notice how `H` is a funny
macro defined as:
```c
%:define H(x) <st%:%:x##.h>
```
and yet the `FILE *` can be called `H`! This might or might not make sense to
you but if it doesn't can you figure out why?
Another fix is that previously the program would `return 1` if a file failed to
open but for the same reason as above, it being very likely some files will not
exist, the return was removed so that if the statement of the `if` is true the
`while` loop run, rather than having the loop by itself. It was done this way to
make it as close to the original as possible and to maintain the obfuscation as
close as possible as well.
Also crucial, and the final fixes to make it work, is that the arrays `K` and
`L` had to be increased in size. They were originally (somewhat bewildering at
first glance) defined as `K[X(*)], L[X(<<)]` but they were changed to
`K[(X(*))*4], L[4*X(<<)]` though it is no longer clear just how necessary this
might be.
As noted, a limitation of `gcc` existing was removed by Cody to make it so that
`gcc` is not required as `cc` should exist in every system with a C compiler and
as the author stated: as long as the options `-E -dM` of the compiler prints out
the macros in the form of `gcc -dM` i.e. the lines are in the form `#define
MACRO value` it will work, assuming that compiler can run, of course.
As for the version for macOS, the even more complicated details are described in
the [Alternate code](1998/schweikh1/README#alternate-code) section of the
README.md file as these changes pertain to the described version therein.
## [1998/schweikh2](1998/schweikh2/schweikh2.c) ([README.md](1998/schweikh2/README.md])) ## [1998/schweikh2](1998/schweikh2/schweikh2.c) ([README.md](1998/schweikh2/README.md]))