Merge pull request #1315 from xexyl/1992-adrian-fixes
This commit is contained in:
5 files changed
+197
-79
No files matched your search
@@ -43,7 +43,7 @@ CSILENCE= -Wno-bitwise-op-parentheses -Wno-comment -Wno-deprecated-declarations
|
|||||||
-Wno-logical-op-parentheses -Wno-macro-redefined -Wno-parentheses \
|
-Wno-logical-op-parentheses -Wno-macro-redefined -Wno-parentheses \
|
||||||
-Wno-return-type -Wno-uninitialized -Wno-unused-value -Wno-unused-variable \
|
-Wno-return-type -Wno-uninitialized -Wno-unused-value -Wno-unused-variable \
|
||||||
-Wno-unused-but-set-variable -Wno-unsequenced -Wno-unused-parameter \
|
-Wno-unused-but-set-variable -Wno-unsequenced -Wno-unused-parameter \
|
||||||
-Wno-empty-translation-unit
|
-Wno-empty-translation-unit -Wno-implicit-int
|
||||||
|
|
||||||
# Common C compiler warning flags
|
# Common C compiler warning flags
|
||||||
#
|
#
|
||||||
@@ -118,7 +118,7 @@ PROG= ${ENTRY}
|
|||||||
#
|
#
|
||||||
OBJ= ${PROG}.o
|
OBJ= ${PROG}.o
|
||||||
DATA=
|
DATA=
|
||||||
TARGET= ${PROG}
|
TARGET= ${PROG} adgrep
|
||||||
#
|
#
|
||||||
ALT_OBJ=
|
ALT_OBJ=
|
||||||
ALT_TARGET=
|
ALT_TARGET=
|
||||||
|
|||||||
+67
-49
@@ -4,6 +4,17 @@
|
|||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Bugs and (Mis)features:
|
||||||
|
|
||||||
|
The current status of this entry is:
|
||||||
|
|
||||||
|
```
|
||||||
|
STATUS: known bug - please help us fix
|
||||||
|
STATUS: INABIAF - please **DO NOT** fix
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information see [1992 adrian in bugs.md](/bugs.md#1992-adrian).
|
||||||
|
|
||||||
|
|
||||||
### Try:
|
### Try:
|
||||||
|
|
||||||
@@ -17,7 +28,8 @@ For the slow minded, try:
|
|||||||
./adsleep 32767
|
./adsleep 32767
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: if you do not specify an arg to the program it will segfault.
|
NOTE: if you do not specify an arg some of the programs such as `adsleep` it
|
||||||
|
will very likely segfault do something funny. This is supposed to happen.
|
||||||
|
|
||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
@@ -32,9 +44,9 @@ NOTE: Some compilers have had trouble optimizing this entry.
|
|||||||
|
|
||||||
### ADrian's GREP (adgrep)
|
### ADrian's GREP (adgrep)
|
||||||
|
|
||||||
For those confused by the complexity of full-blown egrep style regular
|
For those confused by the complexity of full-blown `egrep(1)` style regular
|
||||||
expressions, this program offers an alternative. It implements an
|
expressions, this program offers an alternative. It implements an equivalent
|
||||||
equivalent search, using a deterministic finite automaton.
|
search, using a deterministic finite automaton.
|
||||||
|
|
||||||
A deterministic finite automaton consists of a finite set of states,
|
A deterministic finite automaton consists of a finite set of states,
|
||||||
along with transition rules to move from one state to another, an initial
|
along with transition rules to move from one state to another, an initial
|
||||||
@@ -48,25 +60,30 @@ accepting states, then the string is accepted.
|
|||||||
The deterministic finite automaton is specified as a series of rules for
|
The deterministic finite automaton is specified as a series of rules for
|
||||||
each state:
|
each state:
|
||||||
|
|
||||||
<state> chars1 <dest1> chars2 <dest2> ...
|
```
|
||||||
|
<state> chars1 <dest1> chars2 <dest2> ...
|
||||||
|
```
|
||||||
|
|
||||||
`chars1` is a list of characters (only the first 8 are significant) which
|
`chars1` is a list of characters (_only the first 8_ are significant) which
|
||||||
should trigger a transition to `<dest1>`. `<dest1>` is another state which
|
should trigger a transition to `<dest1>`. `<dest1>` is another state which
|
||||||
should have a similar specification somewhere. A state is accepting if
|
should have a similar specification somewhere. A state is accepting if
|
||||||
it is specified in square brackets: `[final]`, and state strings are
|
it is specified in square brackets: `[final]`; state strings are
|
||||||
significant to only eight characters.
|
significant to only eight characters like `chars1`.
|
||||||
|
|
||||||
|
|
||||||
### Example 1: matches `^abc$`
|
### Example 1: matches `^abc$`
|
||||||
|
|
||||||
<q0> a <q1> The first state to appear is the start state
|
```
|
||||||
<q1> b <q2>
|
<q0> a <q1> The first state to appear is the start state
|
||||||
<q2> c [q3]
|
<q1> b <q2>
|
||||||
[q3]
|
<q2> c [q3]
|
||||||
|
[q3]
|
||||||
|
```
|
||||||
|
|
||||||
Technically, a deterministic finite automaton should have a rule for each
|
Technically, a deterministic finite automaton should have a rule for each
|
||||||
possible input character at each state. To simplify descriptions of the
|
possible input character at each state. To simplify descriptions of the
|
||||||
automata, if no rule is present, the string will not be accepted. Also,
|
automata, if no rule is present, the string will not be accepted. Also,
|
||||||
the `'.'` character matches any character if it occurs first in the
|
the `.` character matches any character if it occurs first in the
|
||||||
character list.
|
character list.
|
||||||
|
|
||||||
|
|
||||||
@@ -116,55 +133,55 @@ character list.
|
|||||||
[q5]
|
[q5]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
With the automaton specification in `filename`, invoke the program by
|
||||||
With the automaton specification in 'filename', invoke the program by
|
|
||||||
typing
|
typing
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./adgrep 'filename'
|
./adrian filename
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
It will read stdin and print out all the lines which the automaton
|
It will read the file and print out all the lines which the automaton
|
||||||
accepts. If the file cannot be opened, a system error message will
|
accepts. If the file cannot be opened, a system error message will
|
||||||
be printed. If the input contains errors, then an error message along
|
be printed. If the input contains errors, then an error message along
|
||||||
with the number of the offending line will be printed to stderr. The\
|
with the number of the offending line will be printed to stderr. The
|
||||||
number of rules for each state is limited to 17. If more than 17 rules\
|
number of rules for each state is limited to 17. If more than 17 rules
|
||||||
are present, you get the error `too_many_rules`, and the state that was\
|
are present, you get the error `too_many_rules`, and the state that was
|
||||||
being processed is printed. Error `no_destination` occurs if you specify a\
|
being processed is printed. Error `no_destination` occurs if you specify a
|
||||||
set of characters, but no destination state, and error `too_many_states`
|
set of characters, but no destination state, and error `too_many_states`
|
||||||
occurs if your automaton has more than 257 states.
|
occurs if your automaton has more than 257 states.
|
||||||
|
|
||||||
Running:
|
Running:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./adgrep from < your_mailbox
|
./adrian from < your_mailbox
|
||||||
```
|
```
|
||||||
|
|
||||||
will perform a function similar to that of the unix from command.
|
will perform a function similar to that of the unix `from` command.
|
||||||
|
|
||||||
If no filename is specified on the command line, then `"adgrep.c"` is used
|
If no filename is specified on the command line, then `__FILE__` is used
|
||||||
as the specification for the automaton. (This file has been renamed\
|
as the specification for the automaton. (Originally `"adgrep.c"` the file was renamed
|
||||||
to `adrian.c` by the judges.) In this case, the program will search for\
|
to `adrian.c` by the judges but for more portability the arg was changed to
|
||||||
|
`__FILE__`.) In this case, the program will search for
|
||||||
matches to the regular expression:
|
matches to the regular expression:
|
||||||
|
|
||||||
```
|
```
|
||||||
^.[^|C][^w[Q]*(Q|[w[]c).*|^.[C|]$
|
^.[^|C][^w[Q]*(Q|[w[]c).*|^.[C|]$
|
||||||
```
|
```
|
||||||
|
|
||||||
I suggest using `adgrep.c` as input, and storing the output in `adwc.c`:
|
I suggest using `adrian.c` as input, and storing the output in `adwc.c`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./adgrep < adgrep.c > adwc.c
|
./adrian < adrian.c > adwc.c
|
||||||
```
|
```
|
||||||
|
|
||||||
Compiling the new file, `mywc.c`, yields a clone of the unix wc command. It
|
Compiling the new file, `adwc.c`, yields a clone of the unix `wc` command. It
|
||||||
runs on one file (defaulting to `"adgrep.c"` if no file is given) and
|
runs on one file, defaulting to `"adrian.c"` if no file is given (again, this
|
||||||
displays the number of lines, words, and bytes in the input file.
|
was changed to be `__FILE__`) and displays the number of lines, words, and bytes
|
||||||
|
in the input file.
|
||||||
|
|
||||||
Another possibly interesting automaton can be created by slightly
|
Another possibly interesting automaton can be created by slightly
|
||||||
adjusting the `adgrep.c` file. Change the first line to read
|
adjusting the `adrian.c` file. Change the first line to read
|
||||||
|
|
||||||
```c
|
```c
|
||||||
/* . echo| . */
|
/* . echo| . */
|
||||||
@@ -173,7 +190,7 @@ adjusting the `adgrep.c` file. Change the first line to read
|
|||||||
and repeat the process above
|
and repeat the process above
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./adgrep <adgrep.c > adecho.c
|
./adrian <adrian.c > adecho.c
|
||||||
```
|
```
|
||||||
|
|
||||||
The new file now contains all lines which match
|
The new file now contains all lines which match
|
||||||
@@ -182,7 +199,7 @@ The new file now contains all lines which match
|
|||||||
^.[^5|m^]*[m^]([e=p,;]|[^e=+p,;].*)$
|
^.[^5|m^]*[m^]([e=p,;]|[^e=+p,;].*)$
|
||||||
```
|
```
|
||||||
|
|
||||||
Compile and run. This is an echo clone. Note the efficient algorithm
|
Compile and run. This is an `echo(1)` clone. Note the efficient algorithm
|
||||||
employed.
|
employed.
|
||||||
|
|
||||||
|
|
||||||
@@ -199,10 +216,10 @@ you can search for matches to
|
|||||||
^.[^W]*W..*$
|
^.[^W]*W..*$
|
||||||
```
|
```
|
||||||
|
|
||||||
By some freak happenstance, lines of adgrep.c which match this regular
|
By some freak happenstance, lines of `adrian.c` which match this regular
|
||||||
expression form a unix head command. It prints the first ten lines of
|
expression form a unix `head(1)` command. It prints the first ten lines of
|
||||||
the file specified on the command line (or adgrep.c if no file is
|
the file specified on the command line or adrian.c if no file is
|
||||||
specified).
|
specified (again this was changed to `__FILE__`).
|
||||||
|
|
||||||
By setting the first line to
|
By setting the first line to
|
||||||
|
|
||||||
@@ -210,14 +227,14 @@ By setting the first line to
|
|||||||
/* . basename . */
|
/* . basename . */
|
||||||
```
|
```
|
||||||
|
|
||||||
a clone of the unix basename command can be unearthed. The automaton will
|
a clone of the unix `basename(1)` command can be unearthed. The automaton will
|
||||||
search for
|
search for
|
||||||
|
|
||||||
```
|
```
|
||||||
^.[^j]*jr.*$
|
^.[^j]*jr.*$
|
||||||
```
|
```
|
||||||
|
|
||||||
on standard input. And the program which results by running adgrep.c
|
on standard input. And the program which results by running `adrian.c`
|
||||||
through this filter requires two parameters. The first is meant to be a
|
through this filter requires two parameters. The first is meant to be a
|
||||||
filename, and the second, an extension. All leading pathname components
|
filename, and the second, an extension. All leading pathname components
|
||||||
are removed from the filename, and the extension is removed if present.
|
are removed from the filename, and the extension is removed if present.
|
||||||
@@ -235,11 +252,11 @@ you can search for
|
|||||||
^.[^(~][^s]*sl.*$
|
^.[^(~][^s]*sl.*$
|
||||||
```
|
```
|
||||||
|
|
||||||
Filtering adgrep.c through this search yields a clone of the sleep
|
Filtering `adrian.c` through this search yields a clone of the `sleep(1)`
|
||||||
command. Invoke with a single integer parameter, and it will pause
|
command. Invoke with a single integer parameter, and it will pause for that
|
||||||
for that many seconds.
|
many seconds.
|
||||||
|
|
||||||
If either adbasename or adsleep is invoked with too few parameters,
|
If either `adbasename` or `adsleep` is invoked with too few parameters,
|
||||||
the program will print the error message:
|
the program will print the error message:
|
||||||
|
|
||||||
> Segmentation fault (core dumped)
|
> Segmentation fault (core dumped)
|
||||||
@@ -248,15 +265,16 @@ the program will print the error message:
|
|||||||
machine.) The four programs which read from stdin require lines
|
machine.) The four programs which read from stdin require lines
|
||||||
shorter than 999 characters.
|
shorter than 999 characters.
|
||||||
|
|
||||||
The other info files are adrian.grep.[1-6] which contain the six
|
The other info files are `adrian.grep.[1-6]` which contain the six
|
||||||
examples that appear above, and from, which is used to emulate the
|
examples that appear above, and from, which is used to emulate the
|
||||||
unix from command. For reasons of clarity, the name "from" should
|
unix `from` command. For reasons of clarity, the name `"from"` should
|
||||||
probably not be changed if possible. I wouldn't want to be accused of\
|
probably not be changed if possible. I wouldn't want to be accused of
|
||||||
confusing people by giving the input files weird names.
|
confusing people by giving the input files weird names.
|
||||||
|
|
||||||
If you want to change the default input filename (line 80) you must be
|
If you want to change the default input filename (line 80) you must be
|
||||||
careful to choose a name that doesn't match the wrong search patterns,
|
careful to choose a name that doesn't match the wrong search patterns,
|
||||||
introducing extra lines into one of the programs.
|
introducing extra lines into one of the programs (again, this was changed to be
|
||||||
|
`__FILE__`).
|
||||||
|
|
||||||
The program will produce at least one warning and possible several
|
The program will produce at least one warning and possible several
|
||||||
when compiled depending on the compiler.
|
when compiled depending on the compiler.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ int L=0,j= -28;
|
|||||||
void E(int i, int m,char*c)
|
void E(int i, int m,char*c)
|
||||||
{
|
{
|
||||||
for(; i<43; i+=3)
|
for(; i<43; i+=3)
|
||||||
putc("}|uutsrq`_^bji`[Zkediml[PO]a_M__]ISOYIRGTNR"[i]+i-9,stderr);
|
putc(i["}|uutsrq`_^bji`[Zkediml[PO]a_M__]ISOYIRGTNR"]+i-9,stderr);
|
||||||
fprintf(stderr,"(%d): %s\n" ,m,c);
|
fprintf(stderr,"(%d): %s\n" ,m,c);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ main(int sl,char *j[]){
|
|||||||
v(s = V[1]; if (*V=strrchr(s,'/'))s=*V+1; if(( !strncmp( s + (jr=strlen(s)) -
|
v(s = V[1]; if (*V=strrchr(s,'/'))s=*V+1; if(( !strncmp( s + (jr=strlen(s)) -
|
||||||
(q=strlen(V[2]) ),V[2],q))&&jr!=q) s[jr-q] = 0; puts(s); )
|
(q=strlen(V[2]) ),V[2],q))&&jr!=q) s[jr-q] = 0; puts(s); )
|
||||||
int e,p,C=0,Q ,basename;
|
int e,p,C=0,Q ,basename;
|
||||||
W= fopen(wc>= 2 ? V[1] : "adgrep.c","rt");
|
W= fopen(wc>= 2 ? V[1] : __FILE__,"rt");if(!W)exit(1);
|
||||||
echo| m^ e| 5| (int) .8| echo|
|
echo| m^ e| 5| (int) .8| echo|
|
||||||
wc |C ==o[o[C] .e] .
|
wc |C ==o[o[C] .e] .
|
||||||
e| e==+p,p; s[o[C] .e ]
|
e| e==+p,p; s[o[C] .e ]
|
||||||
|
|||||||
@@ -707,6 +707,59 @@ when you're cheating it ends up winning! Can you figure that out as well?
|
|||||||
|
|
||||||
# 1992
|
# 1992
|
||||||
|
|
||||||
|
## 1992 adrian
|
||||||
|
|
||||||
|
### STATUS: known bug - please help us fix
|
||||||
|
### Source code: [1992/adrian/westley.c](1992/westley/westley.c)
|
||||||
|
### Information: [1992/adrian/README.md](1992/westley/README.md)
|
||||||
|
|
||||||
|
The author states that:
|
||||||
|
|
||||||
|
```
|
||||||
|
If the input contains errors, then an error message along
|
||||||
|
with the number of the offending line will be printed to stderr. The
|
||||||
|
number of rules for each state is limited to 17. If more than 17 rules
|
||||||
|
are present, you get the error 'too_many_rules', and the state that was
|
||||||
|
being processed is printed. Error 'no_destination' occurs if you specify a
|
||||||
|
set of characters, but no destination state, and error 'too_many_states'
|
||||||
|
occurs if your automaton has more than 257 states.
|
||||||
|
```
|
||||||
|
|
||||||
|
but only `no_destination` appears to occur. It is possible that this is invalid
|
||||||
|
test cases but it's also possible it simply is a bug.
|
||||||
|
|
||||||
|
You are welcome to try and fix these problem(s).
|
||||||
|
|
||||||
|
|
||||||
|
### STATUS: INABIAF - please **DO NOT** fix
|
||||||
|
### Source code: [1992/adrian/westley.c](1992/westley/westley.c)
|
||||||
|
### Information: [1992/adrian/README.md](1992/westley/README.md)
|
||||||
|
|
||||||
|
The author stated that if the file cannot be opened then it will print a system
|
||||||
|
error but this is not the case unless it's showing a fault. However this was
|
||||||
|
instead fixed by Cody as part of another problem that was detected so that the
|
||||||
|
program just exits 1 if the file cannot be opened.
|
||||||
|
|
||||||
|
Also, if _some_ of the programs are not given an arg they will very likely crash
|
||||||
|
or do something funny. For instance `adsleep` and `adbasename`. This is very
|
||||||
|
simple to fix but the author explicitly noted that this will segfault and it is
|
||||||
|
that that is the error message.
|
||||||
|
|
||||||
|
Another thing is that the code:
|
||||||
|
|
||||||
|
```c
|
||||||
|
printf((W,Y));
|
||||||
|
```
|
||||||
|
|
||||||
|
appears to be wrong because `W` is a `FILE *` and `Y` is a `char[]` but if one
|
||||||
|
changes it to use `fprintf()` on the file (which, incidentally, is opened in
|
||||||
|
read only mode which is another reason) with the `%s` specifier it will make
|
||||||
|
`adhead` not work: it'll print nothing at all! So this code should not be
|
||||||
|
changed either even if it appears to be wrong. Notice too a curious thing: if
|
||||||
|
you did change it to fprintf, even if you have the right number of args, you'd
|
||||||
|
have to remove the outer `()` pair.
|
||||||
|
|
||||||
|
|
||||||
## 1992 gson
|
## 1992 gson
|
||||||
|
|
||||||
### STATUS: uses gets() - change to fgets() if possible
|
### STATUS: uses gets() - change to fgets() if possible
|
||||||
|
|||||||
+73
-26
@@ -12,22 +12,22 @@ contributed thousands, that we wish to thank.
|
|||||||
We call out the extensive contributions of [Cody Boone
|
We call out the extensive contributions of [Cody Boone
|
||||||
Ferguson](https://www.ioccc.org/winners.html#Cody_Boone_Ferguson) who is
|
Ferguson](https://www.ioccc.org/winners.html#Cody_Boone_Ferguson) who is
|
||||||
responsible for most of the improvements and fixes including many **EXTREMELY
|
responsible for most of the improvements and fixes including many **EXTREMELY
|
||||||
CHALLENGING bug fixes** like
|
HARD bug fixes** like
|
||||||
[1988/phillipps](/thanks-for-fixes.md#1988phillipps-readmemd),
|
[1988/phillipps](/thanks-for-fixes.md#1988phillipps-readmemd),
|
||||||
[2001/anonymous](/thanks-for-fixes.md#2001anonymous-readmemd) and
|
[2001/anonymous](/thanks-for-fixes.md#2001anonymous-readmemd) and
|
||||||
[2004/burley](/thanks-for-fixes.md#2004burley-readmemd), making entries like
|
[2004/burley](/thanks-for-fixes.md#2004burley-readmemd), making entries like
|
||||||
[1985/sicherman](/thanks-for-fixes.md#1985sicherman-readmemd) and
|
[1985/sicherman](/thanks-for-fixes.md#1985sicherman-readmemd) and
|
||||||
[1986/wall](/thanks-for-fixes.md#1986wall-readmemd) not need `-traditional-cpp`
|
[1986/wall](/thanks-for-fixes.md#1986wall-readmemd) not need `-traditional-cpp`
|
||||||
(all **EXTREMELY CHALLENGING**), fixing entries to work with clang (some being
|
(all **EXTREMELY HARD**), fixing entries to work with clang (some being
|
||||||
**EXTREMELY CHALLENGING** like
|
**EXTREMELY HARD** like
|
||||||
[1991/dds](/thanks-for-fixes.md#1991dds-readmemd)) or as much as possible (like
|
[1991/dds](/thanks-for-fixes.md#1991dds-readmemd)) or as much as possible (like
|
||||||
[1989/westley](/thanks-for-fixes.md#1989westley-readmemd), a true masterpiece
|
[1989/westley](/thanks-for-fixes.md#1989westley-readmemd), a true masterpiece
|
||||||
that is **INCREDIBLY HARD, _MUCH, MUCH MORE SO_ than any other fix!**), porting
|
that is **INCREDIBLY HARD, _MUCH, MUCH MORE SO_ than any other fix!**), porting
|
||||||
entries to macOS (some being **EXTREMELY CHALLENGING** like
|
entries to macOS (some being **EXTREMELY HARD** like
|
||||||
[1998/schweikh1](/thanks-for-fixes.md#1998schweikh1-readmemd)), fixing code like
|
[1998/schweikh1](/thanks-for-fixes.md#1998schweikh1-readmemd)), fixing code like
|
||||||
[2001/herrmann2](/thanks-for-fixes.md#2001herrmann2-readmemd) to work in both
|
[2001/herrmann2](/thanks-for-fixes.md#2001herrmann2-readmemd) to work in both
|
||||||
32-bit/64-bit which *can be* **EXTREMELY CHALLENGING**, providing alternate code
|
32-bit/64-bit which *can be* **EXTREMELY HARD**, providing alternate code
|
||||||
where useful/necessary, fixing where possible dead links or removing them,
|
where useful/necessary, fixing where possible/removing dead links,
|
||||||
typo/consistency fixes, improving **ALL _Makefiles_** and writing
|
typo/consistency fixes, improving **ALL _Makefiles_** and writing
|
||||||
[sgit](https://github.com/xexyl/sgit) that we installed locally to easily run
|
[sgit](https://github.com/xexyl/sgit) that we installed locally to easily run
|
||||||
`sed` on files in the repo to help build the website. **THANK YOU VERY MUCH**
|
`sed` on files in the repo to help build the website. **THANK YOU VERY MUCH**
|
||||||
@@ -122,9 +122,15 @@ $ warning: this program uses gets(), which is unsafe.
|
|||||||
whereas without the warning it's much easier to see that it's a prompt.
|
whereas without the warning it's much easier to see that it's a prompt.
|
||||||
|
|
||||||
In some entries this change is not possible, in one-liners it might make them
|
In some entries this change is not possible, in one-liners it might make them
|
||||||
too long and in some entries it's more complicated than others because of the
|
too long (though it's also been possible to do this in some cases) and in some
|
||||||
annoying fact that for '"compatibility" reasons' `fgets()` retains the newline
|
entries it's more complicated than others because of the annoying fact that for
|
||||||
and `gets()` does not. Nevertheless some of the entries have been updated this
|
'"compatibility" reasons' `fgets()` retains the newline and `gets()` does not.
|
||||||
|
Some entries like [1992/adrian](1992/adrian/README.md) are more complicated in
|
||||||
|
other ways due to the code generating other output; and because of how it works
|
||||||
|
it would generate code that could not be compiled, simply because of spaces
|
||||||
|
being added (a number of other fixes in that entry were also made)!
|
||||||
|
|
||||||
|
Nevertheless some of the entries have been updated this
|
||||||
way for the reasons described above and in the [FAQ](/faq.md).
|
way for the reasons described above and in the [FAQ](/faq.md).
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +149,7 @@ the second line starts with `o, world!\n"`.
|
|||||||
|
|
||||||
By request, the original code is provided as
|
By request, the original code is provided as
|
||||||
[anonymous.alt.c](1984/anonymous/anonymous.alt.c) so that one can look at it and
|
[anonymous.alt.c](1984/anonymous/anonymous.alt.c) so that one can look at it and
|
||||||
the famous tattoo:
|
the famous tattoo which we also include here:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -1299,27 +1305,68 @@ should have been removed.
|
|||||||
|
|
||||||
## [1992/adrian](1992/adrian/adrian.c) ([README.md](1992/adrian/README.md]))
|
## [1992/adrian](1992/adrian/adrian.c) ([README.md](1992/adrian/README.md]))
|
||||||
|
|
||||||
Cody changed the location that it used `gets()` to be `fgets()` instead to make
|
Cody fixed the code so that it will try opening the file the code was compiled
|
||||||
it safer and to prevent annoying warnings during compiling, linking or runtime
|
from (`__FILE__`), not `adgrep.c`, as
|
||||||
(interspersed with the program's output).
|
the latter does not exist: `adgrep` is simply a link to `adrian` as `adgrep` is
|
||||||
|
what the program was submitted as but the winner is `adrian`.
|
||||||
|
|
||||||
|
Not fixing this would cause the program to crash if no arg was specified as the
|
||||||
|
file did not exist. In doing this, at first the change to check for a NULL file
|
||||||
|
was added. Then it was noticed that the problem is that `adgrep.c` was an
|
||||||
|
incorrect reference that was never fixed in any of the files, not the code or
|
||||||
|
the documentation. A fun fact is that one can do:
|
||||||
|
|
||||||
|
```c
|
||||||
|
W= fopen(wc>= 2 ? V[1] : __FILE__,"rt");if(!W)exit(1);
|
||||||
|
```
|
||||||
|
|
||||||
|
but one _CANNOT_ do:
|
||||||
|
|
||||||
|
```c
|
||||||
|
W= fopen(wc>= 2 ? V[1] : __FILE__,"rt");if(!W)exit(1);
|
||||||
|
if (W==NULL)exit(1);
|
||||||
|
```
|
||||||
|
|
||||||
|
because `adwc.c` will be empty! The difference is it is on a newline, the check.
|
||||||
|
This is an example of how a simple change in code can break it and this is also
|
||||||
|
true of another change as further below.
|
||||||
|
|
||||||
|
Cody also restored a slightly more obscure line of code that had been changed:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- putc("}|uutsrq`_^bji`[Zkediml[PO]a_M__]ISOYIRGTNR"[i]+i-9,stderr);
|
||||||
|
+ putc(i["}|uutsrq`_^bji`[Zkediml[PO]a_M__]ISOYIRGTNR"]+i-9,stderr);
|
||||||
|
```
|
||||||
|
|
||||||
|
though it's questionable how much more (if at all) obscure that is.
|
||||||
|
|
||||||
|
Cody also changed the location that it used `gets()` to be `fgets()` instead to
|
||||||
|
make it safer and to prevent annoying warnings during compiling, linking or
|
||||||
|
runtime (interspersed with the program's output). This was complicated because
|
||||||
|
of how the other source files are generated, as noted above; simply changing the
|
||||||
|
code could cause invalid output in the program which made other files fail to
|
||||||
|
compile (for this example specifically, see below).
|
||||||
|
|
||||||
|
One might think that simply changing the `gets()` to `fgets()` (with `stdin`)
|
||||||
|
would work but it did not because `fgets()` stores the newline and `gets()` does
|
||||||
|
not. That is well known but this code was relying on not having this newline
|
||||||
|
(see also above).
|
||||||
|
|
||||||
|
With `fgets()` the code `if(A(Y)) puts(Y);` ended up printing an extra line
|
||||||
|
which made the generation of some files (like `adhead.c`) fail to compile. Why?
|
||||||
|
There was a blank line after a `\` at the end of the first line of a macro
|
||||||
|
definition! Thus the code now first trims off the last character of the buffer
|
||||||
|
read to get the same correct functionality but in a safe and non obnoxious way.
|
||||||
|
|
||||||
Later Cody improved the change to `fgets()` to make it slightly more like the
|
Later Cody improved the change to `fgets()` to make it slightly more like the
|
||||||
original. This still requires the additional stripping of the newline inside the
|
original. This still requires the additional stripping of the newline inside the
|
||||||
loop but now it uses what looks like before, just a call to `gets()`.
|
loop but now it uses what looks like before, just a call to `gets()`.
|
||||||
|
|
||||||
One might think that simply changing the `gets()` to `fgets()` (with `stdin`)
|
|
||||||
would work but it did not because `fgets()` stores the newline and `gets()` does
|
|
||||||
not. The code was relying on not having this newline. With `fgets()` the code
|
|
||||||
`if(A(Y)) puts(Y);` ended up printing an extra line which made the generation of
|
|
||||||
some files (like `adhead.c`) fail to compile. Why? There was a blank line after
|
|
||||||
a `\` at the end of the first line of a macro definition! Thus the code now
|
|
||||||
first trims off the last character of the buffer read to get the same correct
|
|
||||||
functionality but in a safe way and non obnoxious way.
|
|
||||||
|
|
||||||
But the improvement so that it uses `gets()` could not be changed to have the
|
But the improvement so that it uses `gets()` could not be changed to have the
|
||||||
macro do the removal of the extra line (as in with a comma operator or a `&&`)
|
macro do the removal of the extra line (as in with a comma operator or a `&&`)
|
||||||
as this caused compilation errors with another generated file (`adwc.c`). Thus
|
as this, as might be expected from the above, caused compilation errors with
|
||||||
after the `gets()` call in the line that looks like:
|
another generated file (`adwc.c`)! Thus after the `gets()` call in the line that
|
||||||
|
looks like:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
while( gets(Y) ){ Y[strlen(Y)-1]='\0'; if(A(Y)) puts(Y); }
|
while( gets(Y) ){ Y[strlen(Y)-1]='\0'; if(A(Y)) puts(Y); }
|
||||||
@@ -1327,8 +1374,8 @@ while( gets(Y) ){ Y[strlen(Y)-1]='\0'; if(A(Y)) puts(Y); }
|
|||||||
|
|
||||||
one must keep the `Y[strlen(Y)-1]='\0';` part and keep it there.
|
one must keep the `Y[strlen(Y)-1]='\0';` part and keep it there.
|
||||||
|
|
||||||
This is a complex change due to the way the program and Makefile generate
|
These fixes are complex changes due to the way the program and Makefile generate
|
||||||
additional tools.
|
the additional tools.
|
||||||
|
|
||||||
|
|
||||||
## [1992/albert](1992/albert/albert.c) ([README.md](1992/albert/README.md]))
|
## [1992/albert](1992/albert/albert.c) ([README.md](1992/albert/README.md]))
|
||||||
|
|||||||
Reference in new issue
Block a user