Add preview of 1984-2019

The 2020 winners are hinted it, but the source code is not there,
nor are the hints. Someone could look into the HTML and
see what was commented out, but that is not a problem because
WHO won is known and the name of their AWARD is known already.
Moreover a number of the winners have talked about what their
entirs do, so the commented out spoiler text is not a bit problem.

One will find HTML commented out with:

    <!-- XXX remove when 2020 is ready
    2020 links here
    XXX remove when 2020 is ready -->

The "XXX remove when 2020 is ready" string is found at the
start and end comment blocks.  Again, soneone could read
what was commented out, but that is OK since most of that
information is known or can be known.  The following files
have such HTML comment blocks in them.

    ./winners.html
    ./years-spoiler.html
    ./years.html

In addition, ./all/summary.txt was modified to not
include the 2020 entries for the momemt.

The 2020 winner code AND write-ups are NOT part of this set.

p.s. The all/all.tar.bz2 does not contain the 2020 source code (yet?).
This commit is contained in:
Landon Curt Noll committed 2020-12-30 16:57:03 -08:00
1 parent 28efc67f5d
commit c0663537cb
1683 files changed
+220064

No files matched your search

+254
View File
@@ -0,0 +1,254 @@
#!/usr/bin/env make
#
# 2015 makefile
#
# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis
# is licensed under:
#
# Creative Commons Attribution-ShareAlike 3.0 Unported License.
#
# See: http://creativecommons.org/licenses/by-sa/3.0/
################
# tool locations
################
#
#SHELL= /bin/bash
CP= cp
CPP= cpp
GUNZIP= gunzip
BUNZIP2= bunzip2
LD= ld
MAKE= make
RM= rm
SED= sed
TAR= tar
TRUE= true
MKDIR= mkdir
MV= mv
TR= tr
GREP= grep
SORT= sort
UNIQ= uniq
# Set X11_LIBDIR to the directory where the X11 library resides
#
#X11_LIBDIR= /usr/X11R6/lib
#X11_LIBDIR= /usr/X11/lib
X11_LIBDIR= /opt/X11/lib
# Set X11_INCLUDEDIR to the directory where the X11 include files reside
#
#X11_INCDIR= /usr/X11R6/include
#X11_INCDIR= /usr/X11/include
X11_INCDIR= /opt/X11/include
# Compiler warnings
#
#CWARN=
#CWARN= -Wall
#CWARN= -Wall -Wextra
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
#CWARN= -Wall -Wextra -Weverything
#CWARN= -Wall -Wextra -Weverything -pedantic
#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE}
# Silence warnings that ${CWARN} would normally complain about
#
CSILENCE=
# compiler standard
#
#CSTD=
#CSTD= -ansi
CSTD= -std=c11
#CSTD= -std=c99
# compiler bit architecture
#
# Some entries require 32-bitness:
# ARCH= -m32
#
# Some entries require 64-bitess:
# ARCH= -m64
#
# By default we assume nothing:
#
ARCH=
# defines that are needed to compile
#
#CDEFINE=
CDEFINE= -Dtyp=uint64_t
# include files that are needed to compile
#
CINCLUDE=
# optimization
#
# Most compiles will safely use -O2. Some can use only -O1 or -O.
# A few compilers have broken optimizers or this entry make break
# under those buggy optimizers and thus you may not want anything.
# Reasonable compilers will allow for -O3.
#
#OPT=
#OPT= -O
#OPT= -O1
#OPT= -O2
OPT= -O3
# default flags for ANSI C compilation
#
CFLAGS= ${CWARN} ${CSTD} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT}
# Libraries needed to build
#
LIBS=
# ANSI compiler
#
# Set CC to the name of your ANSI compiler.
#
# Some entries seem to need gcc. If you have gcc, set
# both CC and MAY_NEED_GCC to gcc.
#
# If you do not have gcc, set CC to the name of your ANSI compiler, and
# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just :
# to disable such programs.
#
CC= cc
#CC=clang
MAY_NEED_GCC= gcc
##############################
# Special flags for this entry
##############################
#
ENTRY= prog
CSRC= ${ENTRY}.c
OBJ= ${ENTRY}.o
DATA=
ALT_OBJ=
ALT_ENTRY=
TARGET= ${ENTRY}
#################
# build the entry
#################
#
all: ${TARGET} ${DATA}
@${TRUE}
${ENTRY}: ${CSRC}
${CC} ${CFLAGS} $< -o $@ ${LIBS}
# alternative executable
#
alt: ${ALT_ENTRY}
@${TRUE}
# data files
#
data: ${DATA}
@${TRUE}
###############
# utility rules
###############
#
everything: all alt
clean:
${RM} -f ${OBJ} ${ALT_OBJ}
clobber: clean
${RM} -f ${TARGET} ${ALT_ENTRY}
nuke: clobber
@${TRUE}
dist_clean: nuke
@${TRUE}
install:
@echo "Surely we are joking Dr. May!"
@${TRUE}
# backwards compatibility
#
build: all
@${TRUE}
##################
# 133t hacker rulz
##################
#
love:
@echo 'not war?'
@${TRUE}
haste:
$(MAKE) waste
@${TRUE}
waste:
@echo 'haste'
@${TRUE}
make:
@echo 'Attend a maker faire'
@${TRUE}
easter_egg:
@echo you expected to sometimes mis-understand this $${RANDOM} magic
@echo chongo '<was here>' "/\\oo/\\"
@echo Readers shall not be disallowed from not failing to be unable to not partly misunderstand this particular final echo.
# Understand the history of the Homebrew Computer Club
# as well as the West Coast Computer Faire and
# you might be confused different. :-)
#
supernova: nuke
@-if [ -r .code_anal ]; then \
${RM} -f .code_anal_v5; \
else \
echo "planet deniers, like the IAU, are amusing"; \
fi
@echo A $@ helps ${MAKE} the elements that help form planets
@${TRUE}
deep_magic:
@-if [ -r .code_anal ]; then \
ccode_analysis --deep_magic 2ed3582ec5c094a093fea2a6bcb9f19439892873c9cc45ed1ceaafe08b7d52e1b2c7cd524be3b0b2 --FNV1a_hash_512_bit "${ENTRY}"; \
else \
echo "You are holding it wrong!"; \
fi
@${TRUE}
magic: deep_magic
@-if [ -r .code_anal ]; then \
ccode_analysis --mode 216091 --level 216193 --FNV1a_hash_512_bit "${ENTRY}"; \
else \
echo "These aren't the primes you're looking for Pauline!"; \
fi
@${TRUE}
# The IOCCC resident astronomer states
#
charon: supernova
@echo $@ is a dwarf planet
@echo dwarf is a type of planet
@echo $@ is a planet
pluto: supernova
${MAKE} charon
@echo $@ is a dwarf planet
@echo dwarf is a type of planet
@echo $@ is a planet
@echo get used to having lots of planets because a $< can ${MAKE} a lot of them
+813
View File
@@ -0,0 +1,813 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Best Documented</title>
</head>
<body>
<h1>Best Documented</h1>
<p>Jens Schweikhardt<br>
<a href="http://www.schweikhardt.net">http://www.schweikhardt.net</a></p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./prog n
where n is a base 16 number of any size
</code></pre>
<h3>Try:</h3>
<pre><code>./prog 19
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>This code is clean. When you compile with all warnings enabled,
such as with clang:</p>
<p> cc -Weverything -pedantic -std=c11 -Dtyp=uint64_t -O3 prog.c -o prog</p>
<p>The code compiles without warnings on the systems that we tested!</p>
<p>Even more, the code was 100% clean when we ran it against various
static source checkers.</p>
<p>This tool references a problem that David I. Bell once described
as having one of the largest &ldquo;yummo quotients&rdquo; in number theory:</p>
<pre><code> complexity of the solution
yummo quotient = -----------------------------------
complexity of the problem statement
</code></pre>
<p>Erdős privately told one of the IOCCC judges:</p>
<p>&ldquo;Solving the <a href="https://en.wikipedia.org/wiki/Generalized_Riemann_hypothesis#Extended_Riemann_hypothesis_.28ERH.29">Generalized Riemann hypothesis</a>
would be a good warmup exercise for someone to get ready
to begin to work on the <a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Collatz conjecture</a>.&rdquo;</p>
<p>You may explore this famous conjecture using this entry:</p>
<pre><code>./prog 2410
./prog abfff
./prog 27f8cebf
./prog 246f8fddf
./prog 2e95ab51ffea9de
./prog e6a5c22fd7bde9f
./prog 1b7dd73a937485bf
./prog 7d3237680d190a77e53751b
./prog 302ab3d052fb87c06228d249581be0e4
</code></pre>
<p>When you first look at the source, the code looks fairly straightforward.
But look again. Like the Collatz conjecture, simplicity is deceptive!
Oh, and the variable names? They are not simple single letter variables,
they are names of various <a href="https://en.wikipedia.org/wiki/Proteinogenic_amino_acid">Proteinogenic amino
acid</a>:
which is yet another simple building block that can be used to
build some very complex structures. :-)</p>
<p>p.s. We appreciated that apart from a few powers of 2, the source
code is magic number free.</p>
<h2>Author&rsquo;s comments:</h2>
<h2>The TL;DR version</h2>
<p>This is the cleanest program ever submitted. If for some input it enters
a non-terminating loop or runs out of memory you will be insta-famous.
It&rsquo;s a bit like a lottery without the need to buy a ticket and you can
play as often as you like. One notable historic person has even offered
some prize money.</p>
<p>The program illustrates the bloat caused by adherence to too many rules,
each of which may sound sane in isolation, but in their entirety lead to
an obfuscated, hard to read and understand monster.</p>
<h2>What this program does.</h2>
<p>The program tests whether a given natural number satisfies the
<a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Collatz Conjecture</a>:</p>
<p>Take any natural number <em>n</em>. If <em>n</em> is even, divide it by 2 to get <em>n</em>/2.
If <em>n</em> is odd, multiply it by 3 and add 1 to obtain 3<em>n</em> + 1.
Repeat the process indefinitely.
The conjecture is that no matter what number you start with,
you eventually reach 1.</p>
<p>Paul Erdős said about the Collatz conjecture:
&ldquo;Mathematics may not be ready for such problems.&rdquo;
He also offered $500 for its solution.</p>
<p>For example, the sequence of numbers for <em>n</em> = 6 is</p>
<blockquote><p> 6, 3, 10, 5, 16, 8, 4, 2, 1.</p></blockquote>
<p>Continuing past one leads to the <em>cycle</em> 1, 4, 2, 1, 4, 2, 1, &hellip;
Interesting factoid: if you allow <em>negative</em> start values, there are
a few more cycles, each of different length:</p>
<blockquote><p> −1, −2, −1</p>
<p> −5, −14, −7, −20, −10, −5</p>
<p> −17, −50, −25, −74, −37, −110, −55, −164, −82, −41, −122, −61, −182, −91, −272, −136, −68, −34, −17</p></blockquote>
<p>The program computes the sequence for a given positive natural number
and stops at 1. The number <em>n</em> is specified in hexadecimal (without 0x
prefix) as the first argument. The program prints the given number in
zero-padded hex and each iteration along with a line count in decimal.
The example above looks like this (compiled with 64 bit word size):</p>
<pre><code>$ ./prog 6
0000000000000006
0000000000000003 1
000000000000000A 2
0000000000000005 3
0000000000000010 4
0000000000000008 5
0000000000000004 6
0000000000000002 7
0000000000000001 8
</code></pre>
<p>The size of <em>n</em> is only limited by the argument size limit of your
shell/OS (the program implements arbitrary size bignums).
To query this on your POSIX system, run</p>
<pre><code>$ getconf ARG_MAX
262144
</code></pre>
<p>which reports the limit in bytes, here 256KB. This allows to test
whether a <a href="https://en.wikipedia.org/wiki/Googol">Googol</a>, which is
10<sup>100</sup>, satisfies the conjecture. But what is a googol in hex?
Fear not,
<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html">bc(1)</a>
to the rescue:</p>
<pre><code>$ printf 'obase=16;10^100\n' | bc
1249AD2594C37CEB0B2784C4CE0BF38ACE408E211A7CAAB24308A82E8F1000000000\
0000000000000000
$ ./prog 1249AD2594C37CEB0B2784C4CE0BF38ACE408E211A7CAAB24308A82E8F10000000000000000000000000 \
| less
[...]
</code></pre>
<p>Observe how the first 100 iterations melt the zeros to the right. Can you explain
why?</p>
<p>For a given <em>n</em> the program behavior is one of the following 3:</p>
<ol>
<li>The sequence stops at 1. No fame. No money. Thanks for playing. Computational
mathematicians have tested all <em>n</em> &lt; 4FFDD776055A0000 (~10<sup>18</sup>)
so don&rsquo;t try anything less than that.</li>
<li>The chosen <em>n</em> leads to a sequence with ever bigger numbers,
so that eventually the bignum cannot be stored in memory. If this happens,
the program outputs <code>laugh</code> (more likely) or <code>throw up</code> (less likely) and
stops. You <em>might</em> have found
a number for which the sequence <em>diverges</em>. If confirmed, this disproves the
conjecture.</li>
<li>The chosen <em>n</em> leads to a cycle not including 1 (i.e. runs forever,
repeating the same sequence over and over). You have disproved the
conjecture and should certainly submit a paper to the nearest
mathematical journal.</li>
</ol>
<h2>Design objectives</h2>
<p>I gave myself the following objectives. Like in real world programming,
not all of them can be met 100%. Think of them as a multidimensional
continuum, where trade-offs have to be made.</p>
<ol>
<li>No arbitrary limits on the input number. 64 bits might be enough
for everybody, but is not enough for exploring new Collatz-territory.
Thus bignums are required.</li>
<li>Ultra-portable. Must run on C89 systems and self-adapt to C99 and C11
features like exact width types.</li>
<li>Super-efficient. Must be able to run with the widest type as the
base of the bignums. Make the user select the widest type supported
by the implementation and then crunch away. If a non-standard
128bit type is available, it should be usable.</li>
<li>Pentagon level lint cleanliness and MISRA compliance.</li>
<li>Easy to understand, self-documenting clear code. A joy for maintenance
programmers. The epitome of best practice demonstration for all
future textbooks on C.</li>
</ol>
<h1>Program Obfuscation</h1>
<p>In the following I address all the <em>tests</em> as specified by your honors in the
<em>guidelines</em>.</p>
<ul>
<li>look at the original source</li>
<li>convert ANSI tri-graphs to ASCII</li>
<li>C pre-process the source ignoring <code>#include</code> lines</li>
<li>C pre-process the source ignoring <code>#define</code> and <code>#include</code> lines</li>
<li>run it through a C beautifier</li>
<li>examine the algorithm</li>
<li>compile it (with flags to enable all warnings)</li>
<li>execute it</li>
</ul>
<h2>Look at the original source</h2>
<p>Using one letter identifiers is quite old. I decided to use TLI (three
letter identifiers). Not the random kind, rather with a connection to
the meaning of life, the universe and the rest. Enter amino acids! Among
the myriad of possible amino acids there are 23 from which proteins are
built. In biochemistry, each is assigned a TLI (see <a href="https://en.wikipedia.org/wiki/Proteinogenic_amino_acid">Proteinogenic amino
acid</a>):</p>
<pre><code>ala Alanine
cys Cysteine
asp Aspartic acid
glu Glutamic acid
phe Phenylalanine
gly Glycine
his Histidine
ile Isoleucine
lys Lysine
leu Leucine
met Methionine
asn Asparagine
pyl Pyrrolysine
pro Proline
gln Glutamine
arg Arginine
ser Serine
thr Threonine
sec Selenocysteine
val Valine
trp Tryptophan
tyr Tyrosine
asx Asparagine or Aspartic acid
glx Glutamic acid or Glutamine
xle Leucine or Isoleucine
unk Unknown
</code></pre>
<p>My own research results complete this list (not yet in Wikipedia due to
the rule &ldquo;<a href="https://en.wikipedia.org/wiki/Wikipedia:No_original_research">No original
research</a>&rdquo;):</p>
<pre><code>and Androgynine
xor Xenoricine
not Notanamine
tla Triletramine
</code></pre>
<p>Interestingly, the TLI are the perfect mnemonics for C language source.
For example, <code>met</code> is &ldquo;Main&rsquo;s Exit Type&rdquo; (<code>int</code>), <code>ala</code> is &ldquo;A Large
Algebraic&rdquo; (bignum), <code>ile</code> an &ldquo;Incremented Local Entity&rdquo; (index
counter), <code>gly</code> means &ldquo;Grow Larger memorY&rdquo;, <code>gln</code> is &ldquo;Grown Larger Now&rdquo;
(after realloc), <code>not</code> is a &ldquo;Not Overflowing Type&rdquo; (recursive!), <code>unk</code>
is the &ldquo;UNit (Known as 1)&rdquo;, <code>trp</code> is the &ldquo;Tabula Rasa Product&rdquo; (zero),
<code>phe</code> is &ldquo;Print HEx&rdquo; and so on.</p>
<h2>Convert ANSI tri-graphs to ASCII</h2>
<p>Huh??!</p>
<h2>C pre-process the source ignoring &lsquo;#include&rsquo; lines</h2>
<p>Wow, an identity operation (except for the <code>&lt;stdint.h&gt;</code> and <code>EOF + __STDC__</code>
trivialities). Did you gain any insight through this?</p>
<h2>C pre-process the source ignoring &lsquo;#define&rsquo; and &lsquo;#include&rsquo; lines</h2>
<p><code>#define</code>? Which <code>#define</code> directives? How many 4K source files do you
see that neither use a single <code>#define</code> directive <em>nor</em> abuse the build
file? Even though the &ldquo;no <code>#define</code>&rdquo; rule I submitted myself to made it
hard, I could use <code>__LINE__</code> and stdio macros <code>EOF</code>, <code>L_tmpnam</code>,
<code>BUFSIZ</code>, <code>FILENAME_MAX</code>, <code>TMP_MAX</code> to obfuscate at least something.</p>
<h2>Run it through a C beautifier</h2>
<p>Another identity operation. I&rsquo;ve done it for you already. Use this
<code>.indent.pro</code> with FreeBSD indent:</p>
<pre><code>$ cat .indent.pro
-bad /* blank line after decls */
-bap /* blank line after functions */
-br /* braces on if line */
-i8 /* indent */
-l999 /* line length */
-npcs /* no space after function call names */
-npsl /* don't break procedure type */
-ut /* use tabs */
-ce /* cuddle else */
-nip /* no parameter indentation */
-di1 /* declaration indent */
-Tand
-Tmet
-Tthr
-Tpro
-Tser
-Tala
</code></pre>
<p>It looks like a perfect program should:</p>
<ul>
<li> two and a half <code>#includes</code> of unsuspicious standard headers</li>
<li> followed by self protection against goofy implementations</li>
<li> followed by a handful of <code>typedef</code>s</li>
<li> and a pair of file scope objects by necessity</li>
<li> prototypes! With parameter names! <code>static</code> for internal linkage even! This <strong>must</strong> be a first in IOCCC history.</li>
<li> function definitions, <code>main</code> last</li>
<li> everything is fully const-poisoned: automatics, statics, arguments, even <code>main</code></li>
<li> everything is fully curly braced, even single statements</li>
<li> plenty of meaningful TLC (Three Letter Comments)</li>
</ul>
<p>The program contains not a single <em>magic number</em> (only 0 and powers of
2, each power from 1 to 512) which are obvious to competent software
engineers). How many programs have <em>that</em> property? The check for
<code>__STDC_VERSION__</code> was a bit tough to arrive at, since 199901L has too
many bits set. But I realized that I only needed a number larger than
199409 and less than 199901. 199680 has only 4 bits set and writing it
as (256 + 128 + 4 + 2) * 512 minimizes the character count. That&rsquo;s what
judges get when they don&rsquo;t like programs that are longer than they need
to be.</p>
<h2>Examine the algorithm</h2>
<p>Spoilers ahead. Duh!</p>
<p>Pseudocode, with comments matching those in the C source:</p>
<pre><code>/* run */
if (non-NULL and nonempty argv[1]) {
n = convert(argv[1])
print n /* 2hx */
while (n != 1) { /* one */
if (n is odd) { /* odd */
m = deep copy of n /* cpy */
n &lt;&lt;= 1 /* shl */
n += m /* add */
increment n /* inc */
} else { /* eve */
n &gt;&gt;= 1 /* shr */
}
print n /* 2hx */
}
}
</code></pre>
<p>Bignums are represented as the two member structs</p>
<pre><code>typedef struct {
size_t places; /* number of places in base 2&lt;sup&gt;8*sizeof(type)&lt;/sup&gt; */
type *number; /* dynamically allocated memory for number */
} bignum
</code></pre>
<h2>Compile it (with flags to enable all warnings)</h2>
<p>Here&rsquo;s where the program shines brighter than a <a href="https://en.wikipedia.org/wiki/Gamma-ray_burst">gamma-ray
burst</a>!</p>
<p>I challenge you to throw all kinds of compilers, lints, checkers and
analyzers at my program and make it find the slightest of issues.</p>
<p>Is <code>clang -Wall -Wextra -Weverything -Dtyp=uint32_t prog.c</code> all you can
do? Clang has implemented a new warning? Bring it on!</p>
<h2>Execute it</h2>
<p>May you win the jackpot!</p>
<p>For least surprising results, the execution character set should be
ASCII. The program computes four bits from every character in <code>argv[1]</code> and
interprets them as a hex digit. On ASCII the characters a-f, A-F and 0-9
are converted as expected.</p>
<p>This means however, that the program accepts <strong>any string</strong>, turns it
into a starting number (which is output as the first line), and starts
crunching. Nothing stops you from executing</p>
<pre><code>$ ./prog "$(cat prog.c)" # Kind of quine?
$ ./prog "$(cat rules guidelines)" # A jackpot? Maybe next year...
$ ./prog "$(cat /bin/ls)" # Number cut short at first NUL byte.
</code></pre>
<p>In a certain way, the program is character set and encoding agnostic.</p>
<h2>Assumptions made</h2>
<ul>
<li>The <code>EOF</code> macro from <code>&lt;stdio.h&gt;</code> must expand to negative one since it is used
to decrement a pointer and do some other math.
None of the tools catches this one. The program self-protects against unusual
systems with <code>#if EOF + __STDC__</code> followed by <code>#error goofy!</code>. In the rare event
your system is goofy, replace all <code>EOF</code> tokens with <code>(-1)</code> and remove the
<code>#error</code> directive.</li>
</ul>
<p>While the program works best when bytes/characters are octets and the
number of bits in a type is <code>sizeof(typ) &lt;&lt; 3</code>, it will work correctly
on 24bit or 36bit systems with 9 bits/byte, or systems where
<code>sizeof(typ)</code> is 1 even for <code>int</code> and so on. On such systems, it will only
use 8 * <code>sizeof(typ)</code> bits per place. It does not work when <code>CHAR_BIT &lt;= 7</code>.</p>
<h2>Results of various checkers</h2>
<h3>cppcheck</h3>
<p>The open source static checker <a href="http://cppcheck.sourceforge.net/">cppcheck</a>
checks various problems with respect to style, performance, portability
and general fishiness. To enable all checks, run</p>
<pre><code>$ cppcheck --enable=all --force -I/usr/include -Dtyp=uint32_t prog.c
</code></pre>
<p>No issues found.</p>
<h3>flawfinder</h3>
<p>The open source static checker <a href="http://www.dwheeler.com/flawfinder/">flawfinder</a>
checks various problems with respect to security like buffer overflows,
function arguments to known troublemaker functions and more. It doesn&rsquo;t need to
pre-process code, so can be run without the <code>typ</code> macro being defined:</p>
<pre><code>$ flawfinder prog.c
Flawfinder version 1.31, (C) 2001-2014 David A. Wheeler.
Number of rules (primarily dangerous function names) in C/C++ ruleset: 169
Examining prog.c
FINAL RESULTS:
ANALYSIS SUMMARY:
No hits found.
$
</code></pre>
<h3>valgrind</h3>
<p>The open source dynamic checker <a href="http://valgrind.org/">valgrind</a>
runs an executable and verifies all memory accesses and (de)allocations for
proper bounds and memory leaks.
Since the program frees all memory in all possible execution paths, even when
it must bail out,
valgrind should be happy. An early version of my program however reported this:</p>
<pre><code>$ valgrind --leak-check=full --show-leak-kinds=all ./prog 6
[...]
==14615== HEAP SUMMARY:
==14615== in use at exit: 4,096 bytes in 1 blocks
==14615== total heap usage: 4 allocs, 3 frees, 4,108 bytes allocated
==14615==
==14615== 4,096 bytes in 1 blocks are still reachable in loss record 1 of 1
==14615== at 0x4C236C0: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==14615== by 0x4F62175: ??? (in /lib/libc.so.7)
==14615== by 0x4F62073: ??? (in /lib/libc.so.7)
==14615== by 0x4F514EE: ??? (in /lib/libc.so.7)
==14615== by 0x4F51265: vfprintf_l (in /lib/libc.so.7)
==14615== by 0x4F3E001: printf (in /lib/libc.so.7)
==14615== by 0x40101E: phe (in ./prog)
==14615== by 0x400A9F: main (in ./prog)
==14615==
==14615== LEAK SUMMARY:
==14615== definitely lost: 0 bytes in 0 blocks
==14615== indirectly lost: 0 bytes in 0 blocks
==14615== possibly lost: 0 bytes in 0 blocks
==14615== still reachable: 4,096 bytes in 1 blocks
==14615== suppressed: 0 bytes in 0 blocks
==14615==
==14615== For counts of detected and suppressed errors, rerun with: -v
==14615== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
</code></pre>
<p>From which I concluded that <code>printf</code> allocated a single 4K block for
which no matching free existed. But how to free memory allocated deep
down in the guts of the Standard I/O library? After some serious head
scratching it hit me. The only chance I have is telling the system I no
longer want to do I/O, maybe then it would free that buffer. A reading
of C99 7.19.5.1, &ldquo;The fclose function&rdquo;, was encouraging:</p>
<blockquote><p> Whether or not the call succeeds, the stream is disassociated from the file
and any buffer set by the <code>setbuf</code> or <code>setvbuf</code> function is disassociated from the stream
(and deallocated if it was automatically allocated).</p></blockquote>
<p>So I <code>fclose(stdout)</code> before returning and now:</p>
<pre><code>$ valgrind --leak-check=full --show-leak-kinds=all ./prog 6
==14571== Memcheck, a memory error detector
==14571== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14571== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==14571== Command: ./prog 6
==14571==
0000000000000006
0000000000000003 1
000000000000000A 2
0000000000000005 3
0000000000000010 4
0000000000000008 5
0000000000000004 6
0000000000000002 7
0000000000000001 8
==14571==
==14571== HEAP SUMMARY:
==14571== in use at exit: 0 bytes in 0 blocks
==14571== total heap usage: 4 allocs, 4 frees, 4,120 bytes allocated
==14571==
==14571== All heap blocks were freed -- no leaks are possible
==14571==
==14571== For counts of detected and suppressed errors, rerun with: -v
==14571== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
</code></pre>
<p>A squeaky clean valgrind result!</p>
<h3>FlexeLint</h3>
<p>FlexeLint is a commercial lint tool by <a href="http://www.gimpel.com/html/index.htm">Gimpel
Software</a>. It supports nearly a
thousand checks, broadly categorized into 4 levels,</p>
<ol>
<li> Syntax errors only (messages 1 to 399)</li>
<li> Warnings (messages 400 to 699)</li>
<li> Informational messages (700 to 899)</li>
<li> Elective notes (900 to 1000 and > 9000)</li>
</ol>
<p>There is an <a href="http://www.gimpel-online.com/OnlineTesting.html">on-line
demonstrator</a> you can
use for checking your C programs and I highly recommend trying it. For a start,
paste the well know first program in the form and press &ldquo;Analyze Code&rdquo;. Note
the FlexeLint configuration options in comments (no space between <code>/*</code> and <code>lint</code>).</p>
<pre><code>/*lint -w4 turn on everything */
/*lint +esym(534,*) no demonstrator defaults */
/*lint -e966 indirectly included header file not used */
/*lint -esym(9058,_*) tag not used outside typedef */
/*lint -misra(2) */
#include &lt;stdio.h&gt;
int main(void)
{
printf("hello, world\n");
return 0;
}
</code></pre>
<p>Possible checks include those for MISRA 2004 compliance verification.
The <a href="https://en.wikipedia.org/wiki/Motor_Industry_Software_Reliability_Association">Motor Industry Software Reliability
Association</a>
has produced a <a href="http://doc.hcc-embedded.com/display/CODING/MISRA+Rules">list of 121 required and 20 advisory
rules</a> for C
programming. I am proud to report that my program fulfills <em>almost all</em>
rules. To assess the few exceptions, one has to understand that MISRA
rules are geared towards embedded systems used in the automotive
industry. That&rsquo;s why features like <code>malloc</code> and <code>printf</code> are right out.
But that&rsquo;s too restrictive for an IOCCC hosted application, so I ignored
these:</p>
<ul>
<li>17.1 Pointer arithmetic shall only be applied to pointers that address an array or array element.</li>
<li>17.4 Array indexing shall be the only allowed form of pointer arithmetic.</li>
<li>20.4 Dynamic heap memory allocation shall not be used.</li>
<li>20.9 The input/output library stdio.h shall not be used in production code.</li>
<li>20.11 The functions abort, exit, getenv, and system from the library stdlib.h shall not be used.</li>
</ul>
<p>I started out with enabling <em>all</em> messages using FlexeLint&rsquo;s <code>-w4</code>
option and disabling all noise from system headers. Then I dealt with
the remaining messages by addressing them or suppressing them in such a way
that the set of suppressions was minimal. At the end of the day, this is
what remained:</p>
<pre><code>// === Tested with FlexeLint 9.00L on FreeBSD 11 ===
// Compiler:
// "4.2.1 Compatible FreeBSD Clang 3.6.1 (tags/RELEASE_361/final 237755)"
-w4 // Enable maximum pickiness
-passes(6) // Recommended in FlexeLint manual for torture testing
+fsc // Make string literals have type const char*
+fnr // ptr-returning functions may return NULL
-strong(AJX,and,pro,ser,ala) // strong types
-strong(AcJcm,thr) // thr is strong, but most arithmetic is okay
-strong(AarJemorX,met) // met is strong, but some use is okay
+libclass(angle) // All &lt;headers&gt; are system headers
-wlib(1) // Only errors for system headers
-i/usr/include // System headers
-i/usr/local/lib/supp/ansi // Comes with FlexeLint
-d__GNUC__=4 // Pretend...
-d__GNUC_MINOR__=2 // I'm...
-d__GNUC_PATCHLEVEL__=1 // someone else.
-d__builtin_va_list=char* // Fake this compiler extension
-d__inline= // Delete this compiler extension
-d__attribute__(x)= // Delete this compiler extension
+e900 // Announce number of messages produced
// MISRA 2004 checking
/usr/local/lib/supp/lnt/au-misra2.lnt // Enable all MISRA checking
-elib(960) // Don't check FreeBSD system headers for required rules
-elib(961) // Don't check FreeBSD system headers for advisory rules
-e829 // stdio.h used
-e522 // MISRA 14.2 Highest operation, lacks side-effects
-esym(960,17.4) // pointer arithmetic other than array indexing used
-e971 // char without signed/unsigned
-e974 // stack usage report
// Use verboten functions, Req. Rules 20.4 malloc() et al., 20.11, exit()
-esym(586,malloc,realloc,calloc,free,exit)
-e911 // implicit promotion of smaller than int to int
-e921 // cast from integral to integral
-e925 // cast from pointer to pointer
-e958 // padding required in struct
+e9??? // Enable all 9xxx informational messages, except:
-e9079 // conversion from pointer to void to pointer to other type
-e9087 // cast performed between a pointer to object type and a
// pointer to a different object type
-e9141 // global declaration of symbol
// Messages due to code in FreeBSD headers.
//
-dlint // The "lint" macro is tested in x86/_types.h
-elib(537) // Repeated include file
-e793 // external identifiers &gt; 6 chars
-e935 // (unsigned) int within struct (actually the size_t)
-estring(960,_*) // Could be defined at block scope
-e964 // Header file not directly used
-e966 // Indirectly included header file not used
-elib(970) // int outside typedef
-esym(9003,_*) // could be defined at block scope
-elib(9047) // FILE pointer dereferenced
-esym(9058,__*) // tag not used outside typedef
-e9092 // NULL does not expand to a pointer (but plain 0)
</code></pre>
<h2>Compulsory obfuscations</h2>
<p>Which of the rules cause which obfuscation?</p>
<p>MISRA 6.1, &ldquo;The plain char type shall be used only for the storage and
use of character values.&rdquo; This forbids using character constants in
expressions other than assignments to <code>char</code> objects. A consequence is
that printing digits with <code>'0' + digit</code> is not allowed (even though
<code>'0'</code> is technically an <code>int</code>!) so I am forced to output hex digits with</p>
<pre><code>printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2))));
</code></pre>
<p>because of the &ldquo;no magic numbers other than powers of two&rdquo; rule. How is this
an improvement over <code>printf("%c", '0' + tyr + 7 * (tyr / 10)</code>, MISRA?</p>
<p>MISRA 6.3 &ldquo;typedefs that indicate size and signedness should be used in
place of the basic types.&rdquo; Well, if you can&rsquo;t infer the size and
signedness from <code>typedef int met</code>, you&rsquo;re not a real C programmer.</p>
<p>MISRA 10.5, &ldquo;If the bitwise operators <code>~</code> and <code>&lt;&lt;</code> are applied to an
operand of underlying type <code>unsigned char</code> or <code>unsigned short</code>, the
result shall be immediately cast to the underlying type of the operand.&rdquo;
Because the program must work for any unsigned type chosen for the <code>typ</code>
macro, including the narrow types enumerated in the rule, a lot of
redundant casting ensues. It gets worse with the next rule&hellip;</p>
<p>MISRA 12.1, &ldquo;Limited dependence should be placed on the C operator
precedence rules in expressions.&rdquo; This requires parentheses for almost
all expressions involving more than one operator, especially those for which
a cast is required, leading to hard to understand expressions such as</p>
<pre><code>const ser glx = (ser)((asx &gt; (ser)64u) ? (ser)((ser)asx + (ser)8u + (ser)1u) : (ser)asx);
not.not[leu] = (and)((and)not.not[leu] | (and)(((and)glx % (and)16u) &lt;&lt; (and)lys));
</code></pre>
<p>MISRA 14.7, &ldquo;A function shall have a single point of exit at the end of
the function.&rdquo; Sigh. Since I must use eloquent prototypes (8.1, 16.3,
16.4) and static functions (8.10, 8.11), I can only use a few functions.
Everything usually written with an early <code>return</code> now cause <em>another
useless indent level</em>. The first three <code>if</code> statements in <code>main</code> cause a
silly 24 character indent. The maximum indent is forced to 8, which is way
too high for a sane function.</p>
<p>MISRA 16.10, &ldquo;If a function returns error information, then that error
information shall be tested.&rdquo; A cast to void would draw a lint warning, so
I use the <code>printf</code> result in expressions,</p>
<pre><code>lys -= 4 * printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2))));
val += printf("\n") / ((__LINE__ * L_tmpnam) + TMP_MAX);
val -= (printf(" %d\n", val) &gt; BUFSIZ) ? FILENAME_MAX : EOF;
</code></pre>
<p>which are, in the absence of errors, equivalent to</p>
<pre><code>lys -= 4;
/*nop*/
++val;
</code></pre>
<p>MISRA 13.1, &ldquo;Assignment operators shall not be used in expressions that
yield a Boolean value.&rdquo; Forbids the idiomatic <code>if ((p = malloc(n)) ==
NULL)</code> and requires separate statements, in other words, bloat.</p>
<p>MISRA 16.7, &ldquo;A pointer parameter in a function prototype should be
declared as pointer to const if the pointer is not used to modify the
addressed object.&rdquo; in conjunction with lint&rsquo;s &ldquo;Note 952: Parameter could
be declared const&rdquo; causes const-poisoning for all functions,</p>
<pre><code>static void phe(const ala not);
static void gly(ala *const not, const and his);
met main(met val, const pro *const his[]);
</code></pre>
<p>and quite a number of automatic variables.</p>
<h3>Why the &ldquo;laugh&rdquo; and &ldquo;throw up&rdquo; messages?</h3>
<p>The guidelines state &ldquo;We like programs that: make us laugh and/or throw
up :-) (humor really helps!)&rdquo;</p>
<h3>If you have a 128 bit type</h3>
<p>If your compiler supports a 128 bit wide type (e.g. clang, gcc) then
you can use it via the <code>typ</code> macro:</p>
<pre><code>clang -Dtyp=__uint128_t -o prog prog.c
</code></pre>
<p>Indeed, the program can use (and lints clean for) all of</p>
<pre><code>clang -Dtyp=uint8_t -o prog8 prog.c
clang -Dtyp=uint16_t -o prog16 prog.c
clang -Dtyp=uint32_t -o prog32 prog.c
clang -Dtyp=uint64_t -o prog64 prog.c
clang -std=c89 -Dtyp="unsigned long" -o prog89 prog.c
</code></pre>
<p>This works because the program has no need for corresponding <code>SCN</code> or
<code>PRI</code> macros to do the scanning and printing of variables of these
types. With a 128 bit type the program can represent numbers up to
340282366920938463463374607431768211457 (3.4 * 10<sup>39</sup>) as a
single &ldquo;place&rdquo;, enough to explore yet untested numbers for the rest of
your life.</p>
<h3>How big a number can I test with 4 GB of RAM?</h3>
<p>The number of hex digits in the start number is limited by <code>ARG_MAX</code>,
probably minus some overhead for the environment variables (use
<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html"><code>env</code>(1)</a>
to trim your environment). In bits this leaves you with 2<sup>4 *
ARG_MAX</sup>.</p>
<p>The algorithm requires two bignums in memory for addition.
If you hit a divergent number, this will cause out-of-memory (&ldquo;laugh&rdquo;)
somewhere near 2<sup>16,000,000,000</sup> (4GB/2 * 8bits/byte).
Sadly, I don&rsquo;t have a test case :-)</p>
<p>How long would it take to overflow the <em>Not Overflowing Type</em>? Lets
assume we&rsquo;re processing 2GB numbers. The program copies, shifts by one,
adds and increments 2GB long bit strings, each time completely thrashing
the data cache &ndash; at <em>all</em> levels. We have a fast machine that can do an
iteration in one second, on average. To make things easy, we round up
3<em>n</em> + 1 to 4<em>n</em>, and assume we never need to divide by two (which is
quite optimistic). Then each iteration shifts left by 2. This would take
8 billion seconds, or about 250 years. If you want to get famous, you
better <em>remove</em> some of the RAM, use an ancient box, or reduce available
memory resources with the ulimit(1) built-in of your shell.</p>
<p>For all intents and purposes, the <em>Not Overflowing Type</em> keeps the promise!</p>
<hr />
<!--
(c) Copyright 1984-2016, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved
This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc].
[judges]: http://www.ioccc.org/judges.html
[cc]: http://creativecommons.org/licenses/by-sa/3.0/
-->
<TABLE><TR>
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2016,
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
- All rights reserved<BR>
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
+771
View File
@@ -0,0 +1,771 @@
# Best Documented
Jens Schweikhardt
<http://www.schweikhardt.net>
## Judges' comments:
### To use:
make
./prog n
where n is a base 16 number of any size
### Try:
./prog 19
### Selected Judges Remarks:
This code is clean. When you compile with all warnings enabled,
such as with clang:
cc -Weverything -pedantic -std=c11 -Dtyp=uint64\_t -O3 prog.c -o prog
The code compiles without warnings on the systems that we tested!
Even more, the code was 100% clean when we ran it against various
static source checkers.
This tool references a problem that David I. Bell once described
as having one of the largest "yummo quotients" in number theory:
complexity of the solution
yummo quotient = -----------------------------------
complexity of the problem statement
Erdős privately told one of the IOCCC judges:
"Solving the [Generalized Riemann hypothesis](https://en.wikipedia.org/wiki/Generalized_Riemann_hypothesis#Extended_Riemann_hypothesis_.28ERH.29)
would be a good warmup exercise for someone to get ready
to begin to work on the [Collatz conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture)."
You may explore this famous conjecture using this entry:
./prog 2410
./prog abfff
./prog 27f8cebf
./prog 246f8fddf
./prog 2e95ab51ffea9de
./prog e6a5c22fd7bde9f
./prog 1b7dd73a937485bf
./prog 7d3237680d190a77e53751b
./prog 302ab3d052fb87c06228d249581be0e4
When you first look at the source, the code looks fairly straightforward.
But look again. Like the Collatz conjecture, simplicity is deceptive!
Oh, and the variable names? They are not simple single letter variables,
they are names of various [Proteinogenic amino
acid](https://en.wikipedia.org/wiki/Proteinogenic_amino_acid):
which is yet another simple building block that can be used to
build some very complex structures. :-)
p.s. We appreciated that apart from a few powers of 2, the source
code is magic number free.
## Author's comments:
The TL;DR version
-----------------
This is the cleanest program ever submitted. If for some input it enters
a non-terminating loop or runs out of memory you will be insta-famous.
It's a bit like a lottery without the need to buy a ticket and you can
play as often as you like. One notable historic person has even offered
some prize money.
The program illustrates the bloat caused by adherence to too many rules,
each of which may sound sane in isolation, but in their entirety lead to
an obfuscated, hard to read and understand monster.
What this program does.
-----------------------
The program tests whether a given natural number satisfies the
[Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture):
Take any natural number *n*. If *n* is even, divide it by 2 to get *n*/2.
If *n* is odd, multiply it by 3 and add 1 to obtain 3*n* + 1.
Repeat the process indefinitely.
The conjecture is that no matter what number you start with,
you eventually reach 1.
Paul Erdős said about the Collatz conjecture:
"Mathematics may not be ready for such problems."
He also offered $500 for its solution.
For example, the sequence of numbers for *n* = 6 is
> 6, 3, 10, 5, 16, 8, 4, 2, 1.
Continuing past one leads to the *cycle* 1, 4, 2, 1, 4, 2, 1, ...
Interesting factoid: if you allow *negative* start values, there are
a few more cycles, each of different length:
> −1, −2, −1
>
> −5, −14, −7, −20, −10, −5
>
> −17, −50, −25, −74, −37, −110, −55, −164, −82, −41, −122, −61, −182, −91, −272, −136, −68, −34, −17
The program computes the sequence for a given positive natural number
and stops at 1. The number *n* is specified in hexadecimal (without 0x
prefix) as the first argument. The program prints the given number in
zero-padded hex and each iteration along with a line count in decimal.
The example above looks like this (compiled with 64 bit word size):
$ ./prog 6
0000000000000006
0000000000000003 1
000000000000000A 2
0000000000000005 3
0000000000000010 4
0000000000000008 5
0000000000000004 6
0000000000000002 7
0000000000000001 8
The size of *n* is only limited by the argument size limit of your
shell/OS (the program implements arbitrary size bignums).
To query this on your POSIX system, run
$ getconf ARG_MAX
262144
which reports the limit in bytes, here 256KB. This allows to test
whether a [Googol](https://en.wikipedia.org/wiki/Googol), which is
10<sup>100</sup>, satisfies the conjecture. But what is a googol in hex?
Fear not,
[bc(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html)
to the rescue:
$ printf 'obase=16;10^100\n' | bc
1249AD2594C37CEB0B2784C4CE0BF38ACE408E211A7CAAB24308A82E8F1000000000\
0000000000000000
$ ./prog 1249AD2594C37CEB0B2784C4CE0BF38ACE408E211A7CAAB24308A82E8F10000000000000000000000000 \
| less
[...]
Observe how the first 100 iterations melt the zeros to the right. Can you explain
why?
For a given *n* the program behavior is one of the following 3:
1. The sequence stops at 1. No fame. No money. Thanks for playing. Computational
mathematicians have tested all *n* < 4FFDD776055A0000 (~10<sup>18</sup>)
so don't try anything less than that.
2. The chosen *n* leads to a sequence with ever bigger numbers,
so that eventually the bignum cannot be stored in memory. If this happens,
the program outputs `laugh` (more likely) or `throw up` (less likely) and
stops. You *might* have found
a number for which the sequence *diverges*. If confirmed, this disproves the
conjecture.
3. The chosen *n* leads to a cycle not including 1 (i.e. runs forever,
repeating the same sequence over and over). You have disproved the
conjecture and should certainly submit a paper to the nearest
mathematical journal.
Design objectives
-----------------
I gave myself the following objectives. Like in real world programming,
not all of them can be met 100%. Think of them as a multidimensional
continuum, where trade-offs have to be made.
1. No arbitrary limits on the input number. 64 bits might be enough
for everybody, but is not enough for exploring new Collatz-territory.
Thus bignums are required.
2. Ultra-portable. Must run on C89 systems and self-adapt to C99 and C11
features like exact width types.
3. Super-efficient. Must be able to run with the widest type as the
base of the bignums. Make the user select the widest type supported
by the implementation and then crunch away. If a non-standard
128bit type is available, it should be usable.
4. Pentagon level lint cleanliness and MISRA compliance.
5. Easy to understand, self-documenting clear code. A joy for maintenance
programmers. The epitome of best practice demonstration for all
future textbooks on C.
Program Obfuscation
===================
In the following I address all the *tests* as specified by your honors in the
*guidelines*.
* look at the original source
* convert ANSI tri-graphs to ASCII
* C pre-process the source ignoring `#include` lines
* C pre-process the source ignoring `#define` and `#include` lines
* run it through a C beautifier
* examine the algorithm
* compile it (with flags to enable all warnings)
* execute it
Look at the original source
---------------------------
Using one letter identifiers is quite old. I decided to use TLI (three
letter identifiers). Not the random kind, rather with a connection to
the meaning of life, the universe and the rest. Enter amino acids! Among
the myriad of possible amino acids there are 23 from which proteins are
built. In biochemistry, each is assigned a TLI (see [Proteinogenic amino
acid](https://en.wikipedia.org/wiki/Proteinogenic_amino_acid)):
ala Alanine
cys Cysteine
asp Aspartic acid
glu Glutamic acid
phe Phenylalanine
gly Glycine
his Histidine
ile Isoleucine
lys Lysine
leu Leucine
met Methionine
asn Asparagine
pyl Pyrrolysine
pro Proline
gln Glutamine
arg Arginine
ser Serine
thr Threonine
sec Selenocysteine
val Valine
trp Tryptophan
tyr Tyrosine
asx Asparagine or Aspartic acid
glx Glutamic acid or Glutamine
xle Leucine or Isoleucine
unk Unknown
My own research results complete this list (not yet in Wikipedia due to
the rule "[No original
research](https://en.wikipedia.org/wiki/Wikipedia:No_original_research)"):
and Androgynine
xor Xenoricine
not Notanamine
tla Triletramine
Interestingly, the TLI are the perfect mnemonics for C language source.
For example, `met` is "Main's Exit Type" (`int`), `ala` is "A Large
Algebraic" (bignum), `ile` an "Incremented Local Entity" (index
counter), `gly` means "Grow Larger memorY", `gln` is "Grown Larger Now"
(after realloc), `not` is a "Not Overflowing Type" (recursive!), `unk`
is the "UNit (Known as 1)", `trp` is the "Tabula Rasa Product" (zero),
`phe` is "Print HEx" and so on.
Convert ANSI tri-graphs to ASCII
--------------------------------
Huh??!
C pre-process the source ignoring '#include' lines
--------------------------------------------------
Wow, an identity operation (except for the `<stdint.h>` and `EOF + __STDC__`
trivialities). Did you gain any insight through this?
C pre-process the source ignoring '#define' and '#include' lines
----------------------------------------------------------------
`#define`? Which `#define` directives? How many 4K source files do you
see that neither use a single `#define` directive *nor* abuse the build
file? Even though the "no `#define`" rule I submitted myself to made it
hard, I could use `__LINE__` and stdio macros `EOF`, `L_tmpnam`,
`BUFSIZ`, `FILENAME_MAX`, `TMP_MAX` to obfuscate at least something.
Run it through a C beautifier
-----------------------------
Another identity operation. I've done it for you already. Use this
`.indent.pro` with FreeBSD indent:
$ cat .indent.pro
-bad /* blank line after decls */
-bap /* blank line after functions */
-br /* braces on if line */
-i8 /* indent */
-l999 /* line length */
-npcs /* no space after function call names */
-npsl /* don't break procedure type */
-ut /* use tabs */
-ce /* cuddle else */
-nip /* no parameter indentation */
-di1 /* declaration indent */
-Tand
-Tmet
-Tthr
-Tpro
-Tser
-Tala
It looks like a perfect program should:
* two and a half `#includes` of unsuspicious standard headers
* followed by self protection against goofy implementations
* followed by a handful of `typedef`s
* and a pair of file scope objects by necessity
* prototypes! With parameter names! `static` for internal linkage even! This __must__ be a first in IOCCC history.
* function definitions, `main` last
* everything is fully const-poisoned: automatics, statics, arguments, even `main`
* everything is fully curly braced, even single statements
* plenty of meaningful TLC (Three Letter Comments)
The program contains not a single *magic number* (only 0 and powers of
2, each power from 1 to 512) which are obvious to competent software
engineers). How many programs have *that* property? The check for
`__STDC_VERSION__` was a bit tough to arrive at, since 199901L has too
many bits set. But I realized that I only needed a number larger than
199409 and less than 199901. 199680 has only 4 bits set and writing it
as (256 + 128 + 4 + 2) * 512 minimizes the character count. That's what
judges get when they don't like programs that are longer than they need
to be.
Examine the algorithm
---------------------
Spoilers ahead. Duh!
Pseudocode, with comments matching those in the C source:
/* run */
if (non-NULL and nonempty argv[1]) {
n = convert(argv[1])
print n /* 2hx */
while (n != 1) { /* one */
if (n is odd) { /* odd */
m = deep copy of n /* cpy */
n <<= 1 /* shl */
n += m /* add */
increment n /* inc */
} else { /* eve */
n >>= 1 /* shr */
}
print n /* 2hx */
}
}
Bignums are represented as the two member structs
typedef struct {
size_t places; /* number of places in base 2<sup>8*sizeof(type)</sup> */
type *number; /* dynamically allocated memory for number */
} bignum
Compile it (with flags to enable all warnings)
----------------------------------------------
Here's where the program shines brighter than a [gamma-ray
burst](https://en.wikipedia.org/wiki/Gamma-ray_burst)!
I challenge you to throw all kinds of compilers, lints, checkers and
analyzers at my program and make it find the slightest of issues.
Is `clang -Wall -Wextra -Weverything -Dtyp=uint32_t prog.c` all you can
do? Clang has implemented a new warning? Bring it on!
Execute it
----------
May you win the jackpot!
For least surprising results, the execution character set should be
ASCII. The program computes four bits from every character in `argv[1]` and
interprets them as a hex digit. On ASCII the characters a-f, A-F and 0-9
are converted as expected.
This means however, that the program accepts __any string__, turns it
into a starting number (which is output as the first line), and starts
crunching. Nothing stops you from executing
$ ./prog "$(cat prog.c)" # Kind of quine?
$ ./prog "$(cat rules guidelines)" # A jackpot? Maybe next year...
$ ./prog "$(cat /bin/ls)" # Number cut short at first NUL byte.
In a certain way, the program is character set and encoding agnostic.
Assumptions made
----------------
* The `EOF` macro from `<stdio.h>` must expand to negative one since it is used
to decrement a pointer and do some other math.
None of the tools catches this one. The program self-protects against unusual
systems with `#if EOF + __STDC__` followed by `#error goofy!`. In the rare event
your system is goofy, replace all `EOF` tokens with `(-1)` and remove the
`#error` directive.
While the program works best when bytes/characters are octets and the
number of bits in a type is `sizeof(typ) << 3`, it will work correctly
on 24bit or 36bit systems with 9 bits/byte, or systems where
`sizeof(typ)` is 1 even for `int` and so on. On such systems, it will only
use 8 * `sizeof(typ)` bits per place. It does not work when `CHAR_BIT <= 7`.
Results of various checkers
---------------------------
### cppcheck
The open source static checker [cppcheck](http://cppcheck.sourceforge.net/)
checks various problems with respect to style, performance, portability
and general fishiness. To enable all checks, run
$ cppcheck --enable=all --force -I/usr/include -Dtyp=uint32_t prog.c
No issues found.
### flawfinder
The open source static checker [flawfinder](http://www.dwheeler.com/flawfinder/)
checks various problems with respect to security like buffer overflows,
function arguments to known troublemaker functions and more. It doesn't need to
pre-process code, so can be run without the `typ` macro being defined:
$ flawfinder prog.c
Flawfinder version 1.31, (C) 2001-2014 David A. Wheeler.
Number of rules (primarily dangerous function names) in C/C++ ruleset: 169
Examining prog.c
FINAL RESULTS:
ANALYSIS SUMMARY:
No hits found.
$
### valgrind
The open source dynamic checker [valgrind](http://valgrind.org/)
runs an executable and verifies all memory accesses and (de)allocations for
proper bounds and memory leaks.
Since the program frees all memory in all possible execution paths, even when
it must bail out,
valgrind should be happy. An early version of my program however reported this:
$ valgrind --leak-check=full --show-leak-kinds=all ./prog 6
[...]
==14615== HEAP SUMMARY:
==14615== in use at exit: 4,096 bytes in 1 blocks
==14615== total heap usage: 4 allocs, 3 frees, 4,108 bytes allocated
==14615==
==14615== 4,096 bytes in 1 blocks are still reachable in loss record 1 of 1
==14615== at 0x4C236C0: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==14615== by 0x4F62175: ??? (in /lib/libc.so.7)
==14615== by 0x4F62073: ??? (in /lib/libc.so.7)
==14615== by 0x4F514EE: ??? (in /lib/libc.so.7)
==14615== by 0x4F51265: vfprintf_l (in /lib/libc.so.7)
==14615== by 0x4F3E001: printf (in /lib/libc.so.7)
==14615== by 0x40101E: phe (in ./prog)
==14615== by 0x400A9F: main (in ./prog)
==14615==
==14615== LEAK SUMMARY:
==14615== definitely lost: 0 bytes in 0 blocks
==14615== indirectly lost: 0 bytes in 0 blocks
==14615== possibly lost: 0 bytes in 0 blocks
==14615== still reachable: 4,096 bytes in 1 blocks
==14615== suppressed: 0 bytes in 0 blocks
==14615==
==14615== For counts of detected and suppressed errors, rerun with: -v
==14615== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
From which I concluded that `printf` allocated a single 4K block for
which no matching free existed. But how to free memory allocated deep
down in the guts of the Standard I/O library? After some serious head
scratching it hit me. The only chance I have is telling the system I no
longer want to do I/O, maybe then it would free that buffer. A reading
of C99 7.19.5.1, "The fclose function", was encouraging:
> Whether or not the call succeeds, the stream is disassociated from the file
> and any buffer set by the `setbuf` or `setvbuf` function is disassociated from the stream
> (and deallocated if it was automatically allocated).
So I `fclose(stdout)` before returning and now:
$ valgrind --leak-check=full --show-leak-kinds=all ./prog 6
==14571== Memcheck, a memory error detector
==14571== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14571== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==14571== Command: ./prog 6
==14571==
0000000000000006
0000000000000003 1
000000000000000A 2
0000000000000005 3
0000000000000010 4
0000000000000008 5
0000000000000004 6
0000000000000002 7
0000000000000001 8
==14571==
==14571== HEAP SUMMARY:
==14571== in use at exit: 0 bytes in 0 blocks
==14571== total heap usage: 4 allocs, 4 frees, 4,120 bytes allocated
==14571==
==14571== All heap blocks were freed -- no leaks are possible
==14571==
==14571== For counts of detected and suppressed errors, rerun with: -v
==14571== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
A squeaky clean valgrind result!
### FlexeLint
FlexeLint is a commercial lint tool by [Gimpel
Software](http://www.gimpel.com/html/index.htm). It supports nearly a
thousand checks, broadly categorized into 4 levels,
1. Syntax errors only (messages 1 to 399)
2. Warnings (messages 400 to 699)
3. Informational messages (700 to 899)
4. Elective notes (900 to 1000 and > 9000)
There is an [on-line
demonstrator](http://www.gimpel-online.com/OnlineTesting.html) you can
use for checking your C programs and I highly recommend trying it. For a start,
paste the well know first program in the form and press "Analyze Code". Note
the FlexeLint configuration options in comments (no space between `/*` and `lint`).
/*lint -w4 turn on everything */
/*lint +esym(534,*) no demonstrator defaults */
/*lint -e966 indirectly included header file not used */
/*lint -esym(9058,_*) tag not used outside typedef */
/*lint -misra(2) */
#include <stdio.h>
int main(void)
{
printf("hello, world\n");
return 0;
}
Possible checks include those for MISRA 2004 compliance verification.
The [Motor Industry Software Reliability
Association](https://en.wikipedia.org/wiki/Motor_Industry_Software_Reliability_Association)
has produced a [list of 121 required and 20 advisory
rules](http://doc.hcc-embedded.com/display/CODING/MISRA+Rules) for C
programming. I am proud to report that my program fulfills *almost all*
rules. To assess the few exceptions, one has to understand that MISRA
rules are geared towards embedded systems used in the automotive
industry. That's why features like `malloc` and `printf` are right out.
But that's too restrictive for an IOCCC hosted application, so I ignored
these:
* 17.1 Pointer arithmetic shall only be applied to pointers that address an array or array element.
* 17.4 Array indexing shall be the only allowed form of pointer arithmetic.
* 20.4 Dynamic heap memory allocation shall not be used.
* 20.9 The input/output library stdio.h shall not be used in production code.
* 20.11 The functions abort, exit, getenv, and system from the library stdlib.h shall not be used.
I started out with enabling *all* messages using FlexeLint's `-w4`
option and disabling all noise from system headers. Then I dealt with
the remaining messages by addressing them or suppressing them in such a way
that the set of suppressions was minimal. At the end of the day, this is
what remained:
// === Tested with FlexeLint 9.00L on FreeBSD 11 ===
// Compiler:
// "4.2.1 Compatible FreeBSD Clang 3.6.1 (tags/RELEASE_361/final 237755)"
-w4 // Enable maximum pickiness
-passes(6) // Recommended in FlexeLint manual for torture testing
+fsc // Make string literals have type const char*
+fnr // ptr-returning functions may return NULL
-strong(AJX,and,pro,ser,ala) // strong types
-strong(AcJcm,thr) // thr is strong, but most arithmetic is okay
-strong(AarJemorX,met) // met is strong, but some use is okay
+libclass(angle) // All <headers> are system headers
-wlib(1) // Only errors for system headers
-i/usr/include // System headers
-i/usr/local/lib/supp/ansi // Comes with FlexeLint
-d__GNUC__=4 // Pretend...
-d__GNUC_MINOR__=2 // I'm...
-d__GNUC_PATCHLEVEL__=1 // someone else.
-d__builtin_va_list=char* // Fake this compiler extension
-d__inline= // Delete this compiler extension
-d__attribute__(x)= // Delete this compiler extension
+e900 // Announce number of messages produced
// MISRA 2004 checking
/usr/local/lib/supp/lnt/au-misra2.lnt // Enable all MISRA checking
-elib(960) // Don't check FreeBSD system headers for required rules
-elib(961) // Don't check FreeBSD system headers for advisory rules
-e829 // stdio.h used
-e522 // MISRA 14.2 Highest operation, lacks side-effects
-esym(960,17.4) // pointer arithmetic other than array indexing used
-e971 // char without signed/unsigned
-e974 // stack usage report
// Use verboten functions, Req. Rules 20.4 malloc() et al., 20.11, exit()
-esym(586,malloc,realloc,calloc,free,exit)
-e911 // implicit promotion of smaller than int to int
-e921 // cast from integral to integral
-e925 // cast from pointer to pointer
-e958 // padding required in struct
+e9??? // Enable all 9xxx informational messages, except:
-e9079 // conversion from pointer to void to pointer to other type
-e9087 // cast performed between a pointer to object type and a
// pointer to a different object type
-e9141 // global declaration of symbol
// Messages due to code in FreeBSD headers.
//
-dlint // The "lint" macro is tested in x86/_types.h
-elib(537) // Repeated include file
-e793 // external identifiers > 6 chars
-e935 // (unsigned) int within struct (actually the size_t)
-estring(960,_*) // Could be defined at block scope
-e964 // Header file not directly used
-e966 // Indirectly included header file not used
-elib(970) // int outside typedef
-esym(9003,_*) // could be defined at block scope
-elib(9047) // FILE pointer dereferenced
-esym(9058,__*) // tag not used outside typedef
-e9092 // NULL does not expand to a pointer (but plain 0)
Compulsory obfuscations
-----------------------
Which of the rules cause which obfuscation?
MISRA 6.1, "The plain char type shall be used only for the storage and
use of character values." This forbids using character constants in
expressions other than assignments to `char` objects. A consequence is
that printing digits with `'0' + digit` is not allowed (even though
`'0'` is technically an `int`!) so I am forced to output hex digits with
printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2))));
because of the "no magic numbers other than powers of two" rule. How is this
an improvement over `printf("%c", '0' + tyr + 7 * (tyr / 10)`, MISRA?
MISRA 6.3 "typedefs that indicate size and signedness should be used in
place of the basic types." Well, if you can't infer the size and
signedness from `typedef int met`, you're not a real C programmer.
MISRA 10.5, "If the bitwise operators `~` and `<<` are applied to an
operand of underlying type `unsigned char` or `unsigned short`, the
result shall be immediately cast to the underlying type of the operand."
Because the program must work for any unsigned type chosen for the `typ`
macro, including the narrow types enumerated in the rule, a lot of
redundant casting ensues. It gets worse with the next rule...
MISRA 12.1, "Limited dependence should be placed on the C operator
precedence rules in expressions." This requires parentheses for almost
all expressions involving more than one operator, especially those for which
a cast is required, leading to hard to understand expressions such as
const ser glx = (ser)((asx > (ser)64u) ? (ser)((ser)asx + (ser)8u + (ser)1u) : (ser)asx);
not.not[leu] = (and)((and)not.not[leu] | (and)(((and)glx % (and)16u) << (and)lys));
MISRA 14.7, "A function shall have a single point of exit at the end of
the function." Sigh. Since I must use eloquent prototypes (8.1, 16.3,
16.4) and static functions (8.10, 8.11), I can only use a few functions.
Everything usually written with an early `return` now cause *another
useless indent level*. The first three `if` statements in `main` cause a
silly 24 character indent. The maximum indent is forced to 8, which is way
too high for a sane function.
MISRA 16.10, "If a function returns error information, then that error
information shall be tested." A cast to void would draw a lint warning, so
I use the `printf` result in expressions,
lys -= 4 * printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2))));
val += printf("\n") / ((__LINE__ * L_tmpnam) + TMP_MAX);
val -= (printf(" %d\n", val) > BUFSIZ) ? FILENAME_MAX : EOF;
which are, in the absence of errors, equivalent to
lys -= 4;
/*nop*/
++val;
MISRA 13.1, "Assignment operators shall not be used in expressions that
yield a Boolean value." Forbids the idiomatic `if ((p = malloc(n)) ==
NULL)` and requires separate statements, in other words, bloat.
MISRA 16.7, "A pointer parameter in a function prototype should be
declared as pointer to const if the pointer is not used to modify the
addressed object." in conjunction with lint's "Note 952: Parameter could
be declared const" causes const-poisoning for all functions,
static void phe(const ala not);
static void gly(ala *const not, const and his);
met main(met val, const pro *const his[]);
and quite a number of automatic variables.
### Why the "laugh" and "throw up" messages?
The guidelines state "We like programs that: make us laugh and/or throw
up :-) (humor really helps!)"
### If you have a 128 bit type
If your compiler supports a 128 bit wide type (e.g. clang, gcc) then
you can use it via the `typ` macro:
clang -Dtyp=__uint128_t -o prog prog.c
Indeed, the program can use (and lints clean for) all of
clang -Dtyp=uint8_t -o prog8 prog.c
clang -Dtyp=uint16_t -o prog16 prog.c
clang -Dtyp=uint32_t -o prog32 prog.c
clang -Dtyp=uint64_t -o prog64 prog.c
clang -std=c89 -Dtyp="unsigned long" -o prog89 prog.c
This works because the program has no need for corresponding `SCN` or
`PRI` macros to do the scanning and printing of variables of these
types. With a 128 bit type the program can represent numbers up to
340282366920938463463374607431768211457 (3.4 * 10<sup>39</sup>) as a
single "place", enough to explore yet untested numbers for the rest of
your life.
### How big a number can I test with 4 GB of RAM?
The number of hex digits in the start number is limited by `ARG_MAX`,
probably minus some overhead for the environment variables (use
[`env`(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html)
to trim your environment). In bits this leaves you with 2<sup>4 *
ARG_MAX</sup>.
The algorithm requires two bignums in memory for addition.
If you hit a divergent number, this will cause out-of-memory ("laugh")
somewhere near 2<sup>16,000,000,000</sup> (4GB/2 * 8bits/byte).
Sadly, I don't have a test case :-)
How long would it take to overflow the *Not Overflowing Type*? Lets
assume we're processing 2GB numbers. The program copies, shifts by one,
adds and increments 2GB long bit strings, each time completely thrashing
the data cache -- at *all* levels. We have a fast machine that can do an
iteration in one second, on average. To make things easy, we round up
3*n* + 1 to 4*n*, and assume we never need to divide by two (which is
quite optimistic). Then each iteration shifts left by 2. This would take
8 billion seconds, or about 250 years. If you want to get famous, you
better *remove* some of the RAM, use an ancient box, or reduce available
memory resources with the ulimit(1) built-in of your shell.
For all intents and purposes, the *Not Overflowing Type* keeps the promise!
--------------------------------------------------------------------------------
<!--
(c) Copyright 1984-2016, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved
This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc].
[judges]: http://www.ioccc.org/judges.html
[cc]: http://creativecommons.org/licenses/by-sa/3.0/
-->
+179
View File
@@ -0,0 +1,179 @@
#include <stdio.h>
#include <stdlib.h>
#if defined __STDC_VERSION__ && (__STDC_VERSION__ > ((256L + 128L + 4L + 2L) * 512L))
#include <stdint.h>
#endif
#if EOF + __STDC__
#error goofy!
#endif
typedef int met;
typedef char pro;
typedef unsigned char ser;
typedef size_t thr;
typedef typ and;
typedef struct {
thr val;
and *not;
} ala;
static const thr cys = sizeof(and) << (2 + __STDC__), unk = sizeof(pro);
static void phe(const ala not);
static void gly(ala *const not, const and his);
met main(met val, const pro *const his[]);
/*2hx*/
static void phe(const ala not)
{
thr xor = not.val;
do {
met lys = (met)(cys - 4u);
--xor;
while (lys >= 0) {
const and tyr = (and)(((and)(not.not[xor] >> lys)) % (and)16u);
lys -= 4 * printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2))));
}
} while (xor);
}
/*ext*/
static void gly(ala *const not, const and his)
{
and *const gln = realloc((void *)not->not, (not->val + unk) * sizeof his);
if (gln == NULL) {
free(not->not);
exit(puts("throw up"));
}
not->not = gln;
not->not[not->val] = his;
++not->val;
}
/*run*/
met main(met val, const pro *const his[])
{
--val;
if (val == -EOF) {
const pro *tyr = his[val];
const thr trp = 0u;
thr ile = trp;
while (*tyr) {
tyr = &tyr[-EOF];
++ile;
}
if (ile != trp) {
ala not;
not.val = (ile + ((cys >> 2) - unk)) / (cys >> 2);
not.not = calloc(not.val, sizeof(and));
if (not.not != NULL) {
thr leu = trp, lys = trp;
while (ile--) {
const ser asx = (ser)tyr[EOF];
const ser glx = (ser)((asx > (ser)64u) ? (ser)((ser)asx + (ser)8u + (ser)1u) : (ser)asx);
tyr = &tyr[EOF];
not.not[leu] = (and)((and)not.not[leu] | (and)(((and)glx % (and)16u) << (and)lys)); /*lint !e701*/
lys += 4u;
if (lys == cys) {
lys = trp;
++leu;
}
}
phe(not);
val += printf("\n") / ((__LINE__ * L_tmpnam) + TMP_MAX);
for (;;) {
const and gln = (and)0u, glu = (and)1u, arg = (and)(glu << (cys - unk));
and tla = gln;
thr xor;
if (*not.not > glu) {
++tla;
} else {
for (xor = unk; xor < not.val; ++xor) {
if (not.not[xor] != gln) {
++tla;
break;
}
}
}
if (tla == gln) { /*one*/
break;
}
if (*not.not & glu) { /*odd*/
and sec = gln;
ala asn;
asn.val = not.val; /*cpy*/
asn.not = malloc(asn.val * sizeof sec);
if (asn.not == NULL) {
free(not.not);
exit(puts("laugh"));
}
for (xor = trp; xor < asn.val; ++xor) {
asn.not[xor] = not.not[xor];
}
if (not.not[not.val - unk] & arg) { /*shl*/
gly(&not, gln);
}
for (xor = trp; xor < not.val; ++xor) {
const and xle = ((not.not[xor] & arg) == arg) ? glu : gln;
not.not[xor] = (and)((and)(not.not[xor] << unk) + (and)sec);
sec = xle;
}
sec = gln;
while (asn.val < not.val) { /*add*/
gly(&asn, gln);
}
for (xor = trp; xor < not.val; ++xor) {
const and asp = (and)~gln;
if (sec) {
const and pyl = (not.not[xor] >= (asp - asn.not[xor])) ? glu : gln;
++not.not[xor];
sec = pyl;
} else {
sec = (not.not[xor] > (asp - asn.not[xor])) ? glu : gln;
}
not.not[xor] = (and)(not.not[xor] + asn.not[xor]);
}
if (sec) {
gly(&not, glu);
}
for (xor = trp; xor < not.val; ++xor) { /*inc*/
++not.not[xor];
if (not.not[xor] != gln) {
break;
}
}
if (xor == not.val) {
gly(&not, glu);
}
free(asn.not);
} else { /*eve,shr*/
*not.not = (and)(*not.not >> unk);
for (xor = unk; xor < not.val; ++xor) {
if (not.not[xor] & glu) {
not.not[xor - unk] = (and)(not.not[xor - unk] | arg);
}
not.not[xor] = (and)(not.not[xor] >> unk);
}
}
phe(not);
val -= (printf(" %d\n", val) > BUFSIZ) ? FILENAME_MAX : EOF;
}
free(not.not);
}
}
}
return fclose(stdout);
}