Fix 1992/gson in macOS + format/typo checks
The fix is simply disabling the optimiser. This allows the specific
cases where it crashed on start in macOS to not happen. An example
command where it crashed:
./gson free software foundation < /usr/share/dict/words
The README.md file has been typo/format checked.
This commit is contained in:
1 parent
0a316e7046
commit
41d230e234
3 files changed
+37
-24
No files matched your search
+1
-1
@@ -69,7 +69,7 @@ CINCLUDE=
|
|||||||
|
|
||||||
# Optimization
|
# Optimization
|
||||||
#
|
#
|
||||||
OPT= -O3
|
OPT=
|
||||||
|
|
||||||
# Default flags for ANSI C compilation
|
# Default flags for ANSI C compilation
|
||||||
#
|
#
|
||||||
|
|||||||
+32
-22
@@ -4,6 +4,16 @@
|
|||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Bugs and (Mis)features:
|
||||||
|
|
||||||
|
The current status of this entry is:
|
||||||
|
|
||||||
|
```
|
||||||
|
STATUS: uses gets() - change to fgets() if possible
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information see [1992 gson in bugs.md](/bugs.md#1992-gson).
|
||||||
|
|
||||||
|
|
||||||
## To use:
|
## To use:
|
||||||
|
|
||||||
@@ -92,7 +102,7 @@ number of words in the anagrams is limited to 3 by default. This
|
|||||||
limit can be changed using a numeric command line option, as in
|
limit can be changed using a numeric command line option, as in
|
||||||
`./ag -4 international obfuscated c code contest </usr/dict/words`.
|
`./ag -4 international obfuscated c code contest </usr/dict/words`.
|
||||||
|
|
||||||
### Bugs
|
### Bugs and limitations
|
||||||
|
|
||||||
- There is no error checking.
|
- There is no error checking.
|
||||||
- Standard input must be seekable, so you can't pipe the dictionary into AG.
|
- Standard input must be seekable, so you can't pipe the dictionary into AG.
|
||||||
@@ -117,7 +127,7 @@ Instead, it tries to achieve both its speed and its obscurity through a
|
|||||||
careful choice of algorithms. Some of the finer points of those
|
careful choice of algorithms. Some of the finer points of those
|
||||||
algorithms are outlined in the spoiler below.
|
algorithms are outlined in the spoiler below.
|
||||||
|
|
||||||
### How it works: (ROT13 to read)
|
### How it works:
|
||||||
|
|
||||||
Here follows a description of some of the data structures and
|
Here follows a description of some of the data structures and
|
||||||
algorithms used by AG. It is by no means complete, but it may help
|
algorithms used by AG. It is by no means complete, but it may help
|
||||||
@@ -134,16 +144,16 @@ each because the same letter is unlikely to occur more than 15
|
|||||||
times in a practical anagram generation problem.
|
times in a practical anagram generation problem.
|
||||||
|
|
||||||
These `32*4`-bit arrays are actually stored in memory in a
|
These `32*4`-bit arrays are actually stored in memory in a
|
||||||
"bit-transposed" format, as arrays of four "long" values. It is
|
"bit-transposed" format, as arrays of four `long` values. It is
|
||||||
assumed that a "long" is at least 32 bits. The first 4-bit letter
|
assumed that a `long` is at least 32 bits. The first 4-bit letter
|
||||||
count is formed by the least significant (2^0) bit in each of the
|
count is formed by the least significant (`2^0`) bit in each of the
|
||||||
four longs, the next one is formed by the 2^1 bits, etc.
|
four `long`s, the next one is formed by the `2^1` bits, etc.
|
||||||
|
|
||||||
This storage format makes it possible to add or subtract two such
|
This storage format makes it possible to add or subtract two such
|
||||||
vectors of 32 4-bit values in parallel by simulating a set of 32
|
vectors of 32 4-bit values in parallel by simulating a set of 32
|
||||||
binary full adders in software using bitwise logical operations.
|
binary full adders in software using bitwise logical operations.
|
||||||
E.g., all the LSB:s of the result are formed in parallel by taking
|
E.g., all the LSBs of the result are formed in parallel by taking
|
||||||
the exclusive OR of the LSB:s in each summand, and 32 carry bits
|
the exclusive OR of the LSBs in each summand, and 32 carry bits
|
||||||
are formed in parallel in a similar way using a logical AND.
|
are formed in parallel in a similar way using a logical AND.
|
||||||
Thus, 32 independent 4-bit additions can be performed by just four
|
Thus, 32 independent 4-bit additions can be performed by just four
|
||||||
iterations of a loop containing some 32-bit bitwise logical
|
iterations of a loop containing some 32-bit bitwise logical
|
||||||
@@ -155,13 +165,13 @@ subtraction directly, handling addition by means of the identity
|
|||||||
`a+b = a-(0-b)`.
|
`a+b = a-(0-b)`.
|
||||||
|
|
||||||
In addition to this `32*4`-bit representation, AG also forms a so-called
|
In addition to this `32*4`-bit representation, AG also forms a so-called
|
||||||
"signature" that is the bitwise OR of the four longs, which is
|
"signature" that is the bitwise OR of the four `long`s, which is
|
||||||
equivalent to saying that the signature of a word contains a logical 1
|
equivalent to saying that the signature of a word contains a logical 1
|
||||||
in the bit positions corresponding to letters occurring at least once
|
in the bit positions corresponding to letters occurring at least once
|
||||||
in that word.
|
in that word.
|
||||||
|
|
||||||
The first thing AG does is to construct a lookup table of 256
|
The first thing AG does is to construct a lookup table of 256
|
||||||
longs, one for each 8-bit character value. The entry for a
|
`long`s, one for each 8-bit character value. The entry for a
|
||||||
character will be zero if that character doesn't appear in the
|
character will be zero if that character doesn't appear in the
|
||||||
sentence given on the command line, or it will have a single bit
|
sentence given on the command line, or it will have a single bit
|
||||||
set if the character does appear in the sentence. By adding
|
set if the character does appear in the sentence. By adding
|
||||||
@@ -175,15 +185,15 @@ Words containing the right letters but in excessive numbers are
|
|||||||
eliminated in a separate check involving the `32*4` bit array.
|
eliminated in a separate check involving the `32*4` bit array.
|
||||||
|
|
||||||
The remaining words, which will be referred to as "candidate words",
|
The remaining words, which will be referred to as "candidate words",
|
||||||
are stored in `32*4`-bit representation, together with their signatures\
|
are stored in `32*4`-bit representation, together with their signatures
|
||||||
and offsets into the dictionary file so that the plain-text version of
|
and offsets into the dictionary file so that the plain-text version of
|
||||||
a word can later be found for printing. This information is kept in a
|
a word can later be found for printing. This information is kept in a
|
||||||
local "struct" in the dictionary-reading function, and memory is
|
local `struct` in the dictionary-reading function, and memory is
|
||||||
allocated for each candidate word simply by making another recursive
|
allocated for each candidate word simply by making another recursive
|
||||||
call to that function.
|
call to that function.
|
||||||
|
|
||||||
Each struct so allocated is linked into a fixed-size hash table of
|
Each `struct` so allocated is linked into a fixed-size hash table of
|
||||||
4096 entries indexed by the 12 low bits of the word's signature.\
|
4096 entries indexed by the 12 low bits of the word's signature.
|
||||||
When the dictionary-reading function encounters end-of-file, all the
|
When the dictionary-reading function encounters end-of-file, all the
|
||||||
candidate words have been stored in nested activation records on the
|
candidate words have been stored in nested activation records on the
|
||||||
stack, accessible through the hash table.
|
stack, accessible through the hash table.
|
||||||
@@ -196,10 +206,10 @@ command line.
|
|||||||
The subtraction is performed in parallel on the 4-bit letter counts
|
The subtraction is performed in parallel on the 4-bit letter counts
|
||||||
as described above, and if all 32 results are zero, an anagram has
|
as described above, and if all 32 results are zero, an anagram has
|
||||||
been found. If the result is negative for one or more of the letters
|
been found. If the result is negative for one or more of the letters
|
||||||
(as indicated by one or more "1" in a vector of 32 borrow bits
|
(as indicated by one or more `1`s in a vector of 32 borrow bits
|
||||||
returned by the subtraction routine), the word did not match the
|
returned by the subtraction routine), the word did not match the
|
||||||
current sentence and is ignored. Finally, if the result contained
|
current sentence and is ignored. Finally, if the result contained
|
||||||
only non-negative letter counts, we have found a partial anagram:\
|
only non-negative letter counts, we have found a partial anagram:
|
||||||
a word containing some, but not all, of the letters in the current
|
a word containing some, but not all, of the letters in the current
|
||||||
sentence. In this case we recursively try to find an anagram of the
|
sentence. In this case we recursively try to find an anagram of the
|
||||||
remaining letters. The depth of the recursion is limited to the
|
remaining letters. The depth of the recursion is limited to the
|
||||||
@@ -218,14 +228,14 @@ not interested in hash buckets whose words contain any letters not
|
|||||||
in the current sentence; these buckets are exactly those whose index
|
in the current sentence; these buckets are exactly those whose index
|
||||||
has a logical one in a bit position where the signature of the current
|
has a logical one in a bit position where the signature of the current
|
||||||
sentence has a zero. Put another way, we want to loop through only
|
sentence has a zero. Put another way, we want to loop through only
|
||||||
those hash bucket indices "i" that contain zeroes in all the bit
|
those hash bucket indices `i` that contain zeroes in all the bit
|
||||||
positions where the signature "s" of the current sentence contains
|
positions where the signature `s` of the current sentence contains
|
||||||
a zero; this can be expressed in C as (i & ~s == 0).
|
a zero; this can be expressed in C as (`i & ~s == 0`).
|
||||||
|
|
||||||
It is possible to loop through all such numbers in an efficient way by
|
It is possible to loop through all such numbers in an efficient way by
|
||||||
taking advantage of certain properties of binary arithmetic: by
|
taking advantage of certain properties of binary arithmetic: by
|
||||||
forcing the bits corresponding to zeroes in "s" to ones, we can make
|
forcing the bits corresponding to zeroes in `s` to ones, we can make
|
||||||
the carries generated in incrementing "i" propagate straight across
|
the carries generated in incrementing `i` propagate straight across
|
||||||
those bits that should remain zero. For example, the following
|
those bits that should remain zero. For example, the following
|
||||||
program prints all those 16-bit integers that contain zeroes in all
|
program prints all those 16-bit integers that contain zeroes in all
|
||||||
even bit positions:
|
even bit positions:
|
||||||
@@ -241,7 +251,7 @@ to the hash table index when initiating a recursive search, using
|
|||||||
similar bit-twiddling techniques.
|
similar bit-twiddling techniques.
|
||||||
|
|
||||||
Whenever an anagram has been found, it is printed by traversing a
|
Whenever an anagram has been found, it is printed by traversing a
|
||||||
linked list formed by structs in the activation records of the
|
linked list formed by `struct`s in the activation records of the
|
||||||
recursive invocations of the search function, seeking to the beginning
|
recursive invocations of the search function, seeking to the beginning
|
||||||
of the word matched by that invocation, and copying the characters of
|
of the word matched by that invocation, and copying the characters of
|
||||||
the word directly from standard input to standard output.
|
the word directly from standard input to standard output.
|
||||||
|
|||||||
+4
-1
@@ -1417,7 +1417,10 @@ commands that we suggested and some additional ones that provide for some fun.
|
|||||||
|
|
||||||
## [1992/gson](1992/gson/gson.c) ([README.md](1992/gson/README.md]))
|
## [1992/gson](1992/gson/gson.c) ([README.md](1992/gson/README.md]))
|
||||||
|
|
||||||
Cody changed the buffer size in such a way that `gets()` should be safe
|
Cody fixed a crash that prevented this entry from working in some cases in some
|
||||||
|
systems (like macOS) by disabling the optimiser in the Makefile.
|
||||||
|
|
||||||
|
Cody also changed the buffer size in such a way that `gets()` should be safe
|
||||||
(theoretically) as it comes from the command line (though it can also read input
|
(theoretically) as it comes from the command line (though it can also read input
|
||||||
from stdin after starting the program). Ideally `fgets()` would be used but this
|
from stdin after starting the program). Ideally `fgets()` would be used but this
|
||||||
is a more problematic. Previously it had a buffer size of 256 which could
|
is a more problematic. Previously it had a buffer size of 256 which could
|
||||||
|
|||||||
Reference in new issue
Block a user