fix Makefile and README.md for 2015/schweikhardt

This commit is contained in:
Landon Curt Noll committed 2023-03-24 21:20:25 -07:00
1 parent 48f690f089
commit d4654f7e94
2 files changed
+242 -151

No files matched your search

+171 -99
View File
@@ -1,36 +1,52 @@
#!/usr/bin/env make #!/usr/bin/env make
# #
# 2015 makefile # IOCCC 2015 winning entry - schweikhardt
################################################################################
# #
# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis # Regarding individual entries:
# is licensed under: #
# IOCCC winning entry code may not work on your system. Even with standards,
# conditions and build environments change, especially when it comes to more
# extreme code such you might find in an IOCCC winner. Moreover, what was
# allowed and liked in one IOCCC contest may no longer be liked/allowed in
# later IOCCC years.
#
# Corrections on winning author and fixing typos in remarks are VERY WELCOME.
#
# GitHub pull requests are welcome:
#
# If you have a patch that might make running an entry work in modern Unix-like
# environments, please create a GitHub pull request for the IOCCC judges to
# consider.
#
# Suggestions and corrections regarding Makefiles, winning author information,
# fixing typos in remarks, and code patches are welcome via opening a GitHub
# issue or better yet, by creating a GitHub pull request for the IOCCC judges
# to consider. To form a GitHub issue or GitHub pull, please visit:
#
# https://github.com/ioccc-src/winner
#
################################################################################
# This work by Landon Curt Noll and Leonid A. Broukhis is licensed under:
# #
# Creative Commons Attribution-ShareAlike 3.0 Unported License. # Creative Commons Attribution-ShareAlike 3.0 Unported License.
# #
# See: http://creativecommons.org/licenses/by-sa/3.0/ # See: http://creativecommons.org/licenses/by-sa/3.0/
################ #############################
# tool locations # shell used by this Makefile
################ #############################
# #
#SHELL= bash SHELL= bash
CP= cp
CPP= cpp #######################
GUNZIP= gunzip # common tool locations
BUNZIP2= bunzip2 #######################
LD= ld #
MAKE= make include ../../var.mk
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 # Set X11_LIBDIR to the directory where the X11 library resides
# #
@@ -44,49 +60,51 @@ X11_LIBDIR= /opt/X11/lib
#X11_INCDIR= /usr/X11/include #X11_INCDIR= /usr/X11/include
X11_INCDIR= /opt/X11/include X11_INCDIR= /opt/X11/include
# Compiler warnings # Common C compiler warnings to silence
#
#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= CSILENCE=
#CSILENCE= -Wno-implicit-int
# compiler standard # Common C compiler warning flags
#
#CWARN= ${CSILENCE}
#CWARN= -Wall ${CSILENCE}
#CWARN= -Wall -Wextra ${CSILENCE}
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
# Compiler standard
# #
#CSTD= #CSTD=
#CSTD= -ansi #CSTD= -ansi
CSTD= -std=c11 CSTD= -std=gnu11
#CSTD= -std=c99
# compiler bit architecture # Compiler bit architecture
# #
# Some entries require 32-bitness: # Some entries require 32-bitness:
# ARCH= -m32 # ARCH= -m32
# #
# Some entries require 64-bitess: # Some entries require 64-bitness:
# ARCH= -m64 # ARCH= -m64
# #
# By default we assume nothing: # By default we assume nothing:
# #
ARCH= ARCH=
# defines that are needed to compile # Defines that are needed to compile
# #
#CDEFINE= #CDEFINE=
CDEFINE= -Dtyp=uint64_t CDEFINE= -Dtyp=uint64_t
# include files that are needed to compile # Include files that are needed to compile
# #
CINCLUDE= CINCLUDE=
#CINCLUDE= -include stdlib.h
#CINCLUDE= -include stdio.h
#CINCLUDE= -include stdlib.h -include stdio.h
#CINCLUDE= -I ${X11_INCDIR} -I ${X11_INCDIR}/X11
#CINCLUDE= `${SDL2_CONFIG} --cflags`
# optimization # Optimization
# #
# Most compiles will safely use -O2. Some can use only -O1 or -O. # Most compiles will safely use -O2. Some can use only -O1 or -O.
# A few compilers have broken optimizers or this entry make break # A few compilers have broken optimizers or this entry make break
@@ -99,56 +117,77 @@ CINCLUDE=
#OPT= -O2 #OPT= -O2
OPT= -O3 OPT= -O3
# default flags for ANSI C compilation # Default flags for ANSI C compilation
# #
CFLAGS= ${CWARN} ${CSTD} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT}
# Libraries needed to build # Libraries needed to build
# #
LIBS= LIBS=
#LIBS= -lm
#LIBS= -L ${X11_LIBDIR} -lX11
#LIBS= `${SDL2_CONFIG} --libs`
# ANSI compiler # C compiler to use
#
# 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= cc
#CC=clang #CC=clang
MAY_NEED_GCC= gcc #CC=gcc
# Compiler add-ons or replacements for clang only
#
ifeq ($(CC),clang)
#
CSILENCE+= -Wno-poison-system-directories
#
CWARN+= -Weverything
#
endif
# Specific add-ons or replacements for gcc only
#
ifeq ($(CC),gcc)
#
#CSILENCE+=
#
#CWARN+=
#
endif
############################## ##############################
# Special flags for this entry # Special flags for this entry
############################## ##############################
# #
ENTRY= prog ENTRY= schweikhardt
CSRC= ${ENTRY}.c PROG= prog
OBJ= ${ENTRY}.o #
OBJ= ${PROG}.o
CSRC= ${PROG}.o
DATA= DATA=
TARGET= ${PROG}
#
ALT_OBJ= ALT_OBJ=
ALT_ENTRY= ALT_TARGET=
TARGET= ${ENTRY}
################# #################
# build the entry # build the entry
################# #################
# #
all: ${TARGET} ${DATA} all: data ${TARGET}
@${TRUE} @${TRUE}
${ENTRY}: ${CSRC} .PHONY: all alt data everything clean clobber install \
love haste waste maker easter_egg sandwich \
supernova deep_magic magic charon pluto
${PROG}: ${PROG}.c
${CC} ${CFLAGS} $< -o $@ ${LIBS} ${CC} ${CFLAGS} $< -o $@ ${LIBS}
# alternative executable # alternative executable
# #
alt: ${ALT_ENTRY} alt: data ${ALT_TARGET}
@${TRUE} @${TRUE}
# data files # data files
@@ -156,33 +195,51 @@ alt: ${ALT_ENTRY}
data: ${DATA} data: ${DATA}
@${TRUE} @${TRUE}
# both all and alt
#
everything: all alt
############### ###############
# utility rules # utility rules
############### ###############
# #
everything: all alt
clean: clean:
${RM} -f ${OBJ} ${ALT_OBJ} ${RM} -f ${OBJ} ${ALT_OBJ}
@-if [ -f indent.c ]; then \
echo ${RM} -f indent.c; \
${RM} -f indent.c; \
fi
clobber: clean clobber: clean
${RM} -f ${TARGET} ${ALT_ENTRY} ${RM} -f ${TARGET} ${ALT_TARGET}
@-if [ -e sandwich ]; then \
nuke: clobber ${RM} -f sandwich; \
@${TRUE} echo 'ate sandwich'; \
fi
dist_clean: nuke
@${TRUE}
install: install:
@echo "Surely we are joking Dr. May!" @echo "Dr. Spock says that is not logical!"
@${TRUE} @${TRUE}
# backwards compatibility # you may be able to misunderstand the source by reading indent.c
# #
build: all indent.c: ${PROG}.c
@${TRUE} @if which "${GINDENT}" >/dev/null 2>&1; then \
echo ${RM} -f $@; \
${RM} -f $@; \
echo "${GINDENT} < $< > $@"; \
${GINDENT} < $< > $@; \
elif which "${INDENT}" >/dev/null 2>&1; then \
echo ${RM} -f $@; \
${RM} -f $@; \
echo "${INDENT} < $< > $@"; \
${INDENT} < $< > $@; \
else \
echo "no intent tool found, ident $< yourself, sorry"; \
echo "exit 1"; \
exit 1; \
fi
################## ##################
@@ -201,54 +258,69 @@ waste:
@echo 'haste' @echo 'haste'
@${TRUE} @${TRUE}
make: maker:
@echo 'Attend a maker faire' @echo 'Participate in a maker faire'
@${TRUE} @${TRUE}
easter_egg: easter_egg:
@echo you expected to sometimes mis-understand this $${RANDOM} magic @echo "you expected to often misunderstand this $${RANDOM} magic"
@echo chongo '<was here>' "/\\oo/\\" @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. @echo "Eggy"
sandwich: easter_egg
@if [ `id -u` -eq 0 ]; then \
echo 'Okay.'; \
echo "$${RANDOM}`date +%s`$${RANDOM}" > $@; \
else \
echo 'What? Make it yourself.'; \
exit 1; \
fi
# Understand the history of the Homebrew Computer Club # Understand the history of the Homebrew Computer Club
# as well as the West Coast Computer Faire and # as well as the West Coast Computer Faire and
# you might be confused different. :-) # you might be confused different. :-)
# #
supernova: nuke supernova: sandwich
@-if [ -r .code_anal ]; then \ @-if [ -r .code_anal ]; then \
${RM} -f .code_anal_v5; \ ${RM} -f .code_anal_v6; \
else \ else \
echo "planet deniers, like the IAU, are amusing"; \ echo "planet deniers, like some members of the IAU, are so cute when they try to defend their logic"; \
fi fi
@echo A $@ helps ${MAKE} the elements that help form planets @echo "A $@ helps ${MAKE} the elements that help form planets"
@${TRUE} @${TRUE}
deep_magic: deep_magic: supernova
@-if [ -r .code_anal ]; then \ @-if [ -r .code_anal ]; then \
ccode_analysis --deep_magic 2ed3582ec5c094a093fea2a6bcb9f19439892873c9cc45ed1ceaafe08b7d52e1b2c7cd524be3b0b2 --FNV1a_hash_512_bit "${ENTRY}"; \ ccode_analysis --deep_magic 7889066cdbdf09b0408021754586e895be641cc9be29e7eafd3ca65359541f17 \
--FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
else \ else \
echo "You are holding it wrong!"; \ echo "Wrong! Do it again!"; \
sleep 2; \
echo "Wrong! Do it again!"; \
sleep 2; \
echo "Wrong! Do it again!"; \
fi fi
@${TRUE} @${TRUE}
magic: deep_magic magic: deep_magic
@-if [ -r .code_anal ]; then \ @-if [ -r .code_anal ]; then \
ccode_analysis --mode 216091 --level 216193 --FNV1a_hash_512_bit "${ENTRY}"; \ ccode_analysis --level 20003 --mode 5717175 --FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
else \ else \
echo "These aren't the primes you're looking for Pauline!"; \ echo "If you don't eat yer meat, you can't have any pudding!"; \
echo "How can you have any pudding if you don't eat yer meat?!"; \
fi fi
@${TRUE} @${TRUE}
# The IOCCC resident astronomer states # The IOCCC resident astronomer states
# #
charon: supernova charon: magic
@echo $@ is a dwarf planet @echo "$@ is a dwarf planet"
@echo dwarf is a type of planet @echo "dwarf is a type of planet"
@echo $@ is a planet @echo "therefore IAU, $@ is a planet"
pluto: supernova pluto: charon
${MAKE} charon ${MAKE} charon
@echo $@ is a dwarf planet @echo "$@ is a dwarf planet"
@echo dwarf is a type of planet @echo "dwarf is a type of planet"
@echo $@ is a planet @echo "therefore, $@ is a planet"
@echo get used to having lots of planets becasue supernovae can ${MAKE} a lot of them @echo "having lots of planets is good feature because supernovae can help ${MAKE} a lot of them"
+71 -52
View File
@@ -3,27 +3,34 @@
Jens Schweikhardt Jens Schweikhardt
<http://www.schweikhardt.net> <http://www.schweikhardt.net>
# To build:
## Judges' comments: ```sh
### To use:
make make
```
### To run:
```sh
./prog n ./prog n
```
where n is a base 16 number of any size where n is a base 16 number of any size.
### Try: ### Try:
```sh
./prog 19 ./prog 19
```
## Judges' comments:
### Selected Judges Remarks:
This code is clean. When you compile with all warnings enabled, This code is clean. When you compile with all warnings enabled,
such as with clang: such as with clang:
```sh
cc -Weverything -pedantic -std=c11 -Dtyp=uint64\_t -O3 prog.c -o prog cc -Weverything -pedantic -std=c11 -Dtyp=uint64\_t -O3 prog.c -o prog
```
The code compiles without warnings on the systems that we tested! The code compiles without warnings on the systems that we tested!
@@ -33,9 +40,11 @@ static source checkers.
This tool references a problem that David I. Bell once described This tool references a problem that David I. Bell once described
as having one of the largest "yummo quotients" in number theory: as having one of the largest "yummo quotients" in number theory:
```
complexity of the solution complexity of the solution
yummo quotient = ----------------------------------- yummo quotient = -----------------------------------
complexity of the problem statement complexity of the problem statement
```
Erdős privately told one of the IOCCC judges: Erdős privately told one of the IOCCC judges:
@@ -45,6 +54,7 @@ to begin to work on the [Collatz conjecture](https://en.wikipedia.org/wiki/Colla
You may explore this famous conjecture using this entry: You may explore this famous conjecture using this entry:
```sh
./prog 2410 ./prog 2410
./prog abfff ./prog abfff
./prog 27f8cebf ./prog 27f8cebf
@@ -54,6 +64,7 @@ You may explore this famous conjecture using this entry:
./prog 1b7dd73a937485bf ./prog 1b7dd73a937485bf
./prog 7d3237680d190a77e53751b ./prog 7d3237680d190a77e53751b
./prog 302ab3d052fb87c06228d249581be0e4 ./prog 302ab3d052fb87c06228d249581be0e4
```
When you first look at the source, the code looks fairly straightforward. When you first look at the source, the code looks fairly straightforward.
But look again. Like the Collatz conjecture, simplicity is deceptive! But look again. Like the Collatz conjecture, simplicity is deceptive!
@@ -67,8 +78,8 @@ p.s. We appreciated that apart from a few powers of 2, the source
code is magic number free. code is magic number free.
## Author's comments: ## Author's comments:
The TL;DR version
----------------- ### The TL;DR version
This is the cleanest program ever submitted. If for some input it enters 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. a non-terminating loop or runs out of memory you will be insta-famous.
@@ -80,8 +91,7 @@ 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 each of which may sound sane in isolation, but in their entirety lead to
an obfuscated, hard to read and understand monster. an obfuscated, hard to read and understand monster.
What this program does. ### What this program does.
-----------------------
The program tests whether a given natural number satisfies the The program tests whether a given natural number satisfies the
[Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture): [Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture):
@@ -116,6 +126,7 @@ 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. 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): The example above looks like this (compiled with 64 bit word size):
```sh
$ ./prog 6 $ ./prog 6
0000000000000006 0000000000000006
0000000000000003 1 0000000000000003 1
@@ -126,13 +137,16 @@ The example above looks like this (compiled with 64 bit word size):
0000000000000004 6 0000000000000004 6
0000000000000002 7 0000000000000002 7
0000000000000001 8 0000000000000001 8
## Judges' comments:
The size of *n* is only limited by the argument size limit of your The size of *n* is only limited by the argument size limit of your
shell/OS (the program implements arbitrary size bignums). shell/OS (the program implements arbitrary size bignums).
To query this on your POSIX system, run To query this on your POSIX system, run
```sh
$ getconf ARG_MAX $ getconf ARG_MAX
262144 262144
```
which reports the limit in bytes, here 256KB. This allows to test which reports the limit in bytes, here 256KB. This allows to test
whether a [Googol](https://en.wikipedia.org/wiki/Googol), which is whether a [Googol](https://en.wikipedia.org/wiki/Googol), which is
@@ -167,9 +181,7 @@ For a given *n* the program behavior is one of the following 3:
conjecture and should certainly submit a paper to the nearest conjecture and should certainly submit a paper to the nearest
mathematical journal. mathematical journal.
### Design objectives
Design objectives
-----------------
I gave myself the following objectives. Like in real world programming, 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 not all of them can be met 100%. Think of them as a multidimensional
@@ -189,8 +201,7 @@ continuum, where trade-offs have to be made.
programmers. The epitome of best practice demonstration for all programmers. The epitome of best practice demonstration for all
future textbooks on C. future textbooks on C.
Program Obfuscation ### Program Obfuscation
===================
In the following I address all the *tests* as specified by your honors in the In the following I address all the *tests* as specified by your honors in the
*guidelines*. *guidelines*.
@@ -204,8 +215,7 @@ In the following I address all the *tests* as specified by your honors in the
* compile it (with flags to enable all warnings) * compile it (with flags to enable all warnings)
* execute it * execute it
Look at the original source ### Look at the original source
---------------------------
Using one letter identifiers is quite old. I decided to use TLI (three Using one letter identifiers is quite old. I decided to use TLI (three
letter identifiers). Not the random kind, rather with a connection to letter identifiers). Not the random kind, rather with a connection to
@@ -258,19 +268,16 @@ counter), `gly` means "Grow Larger memorY", `gln` is "Grown Larger Now"
is the "UNit (Known as 1)", `trp` is the "Tabula Rasa Product" (zero), is the "UNit (Known as 1)", `trp` is the "Tabula Rasa Product" (zero),
`phe` is "Print HEx" and so on. `phe` is "Print HEx" and so on.
Convert ANSI tri-graphs to ASCII ### Convert ANSI tri-graphs to ASCII
--------------------------------
Huh??! Huh??!
C pre-process the source ignoring '#include' lines ### C pre-process the source ignoring '#include' lines
--------------------------------------------------
Wow, an identity operation (except for the `<stdint.h>` and `EOF + __STDC__` Wow, an identity operation (except for the `<stdint.h>` and `EOF + __STDC__`
trivialities). Did you gain any insight through this? trivialities). Did you gain any insight through this?
C pre-process the source ignoring '#define' and '#include' lines ### C pre-process the source ignoring '#define' and '#include' lines
----------------------------------------------------------------
`#define`? Which `#define` directives? How many 4K source files do you `#define`? Which `#define` directives? How many 4K source files do you
see that neither use a single `#define` directive *nor* abuse the build see that neither use a single `#define` directive *nor* abuse the build
@@ -278,12 +285,12 @@ file? Even though the "no `#define`" rule I submitted myself to made it
hard, I could use `__LINE__` and stdio macros `EOF`, `L_tmpnam`, hard, I could use `__LINE__` and stdio macros `EOF`, `L_tmpnam`,
`BUFSIZ`, `FILENAME_MAX`, `TMP_MAX` to obfuscate at least something. `BUFSIZ`, `FILENAME_MAX`, `TMP_MAX` to obfuscate at least something.
Run it through a C beautifier ### Run it through a C beautifier
-----------------------------
Another identity operation. I've done it for you already. Use this Another identity operation. I've done it for you already. Use this
`.indent.pro` with FreeBSD indent: `.indent.pro` with FreeBSD indent:
```sh
$ cat .indent.pro $ cat .indent.pro
-bad /* blank line after decls */ -bad /* blank line after decls */
-bap /* blank line after functions */ -bap /* blank line after functions */
@@ -302,6 +309,7 @@ Another identity operation. I've done it for you already. Use this
-Tpro -Tpro
-Tser -Tser
-Tala -Tala
```
It looks like a perfect program should: It looks like a perfect program should:
@@ -325,13 +333,13 @@ 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 judges get when they don't like programs that are longer than they need
to be. to be.
Examine the algorithm ### Examine the algorithm
---------------------
Spoilers ahead. Duh! Spoilers ahead. Duh!
Pseudocode, with comments matching those in the C source: Pseudocode, with comments matching those in the C source:
```c
/* run */ /* run */
if (non-NULL and nonempty argv[1]) { if (non-NULL and nonempty argv[1]) {
n = convert(argv[1]) n = convert(argv[1])
@@ -348,16 +356,18 @@ Pseudocode, with comments matching those in the C source:
print n /* 2hx */ print n /* 2hx */
} }
} }
```
Bignums are represented as the two member structs Bignums are represented as the two member structs
```c
typedef struct { typedef struct {
size_t places; /* number of places in base 2<sup>8*sizeof(type)</sup> */ size_t places; /* number of places in base 2<sup>8*sizeof(type)</sup> */
type *number; /* dynamically allocated memory for number */ type *number; /* dynamically allocated memory for number */
} bignum } bignum
```
Compile it (with flags to enable all warnings) ### Compile it (with flags to enable all warnings)
----------------------------------------------
Here's where the program shines brighter than a [gamma-ray Here's where the program shines brighter than a [gamma-ray
burst](https://en.wikipedia.org/wiki/Gamma-ray_burst)! burst](https://en.wikipedia.org/wiki/Gamma-ray_burst)!
@@ -368,9 +378,7 @@ 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 Is `clang -Wall -Wextra -Weverything -Dtyp=uint32_t prog.c` all you can
do? Clang has implemented a new warning? Bring it on! do? Clang has implemented a new warning? Bring it on!
### Execute it
Execute it
----------
May you win the jackpot! May you win the jackpot!
@@ -383,14 +391,15 @@ This means however, that the program accepts __any string__, turns it
into a starting number (which is output as the first line), and starts into a starting number (which is output as the first line), and starts
crunching. Nothing stops you from executing crunching. Nothing stops you from executing
$ ./prog "$(cat prog.c)" # Kind of quine? ```sh
$ ./prog "$(cat rules guidelines)" # A jackpot? Maybe next year... ./prog "$(cat prog.c)" # Kind of quine?
$ ./prog "$(cat /bin/ls)" # Number cut short at first NUL byte. ./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. In a certain way, the program is character set and encoding agnostic.
Assumptions made ### Assumptions made
----------------
* The `EOF` macro from `<stdio.h>` must expand to negative one since it is used * The `EOF` macro from `<stdio.h>` must expand to negative one since it is used
to decrement a pointer and do some other math. to decrement a pointer and do some other math.
@@ -406,9 +415,7 @@ 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 `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`. use 8 * `sizeof(typ)` bits per place. It does not work when `CHAR_BIT <= 7`.
### Results of various checkers
Results of various checkers
---------------------------
### cppcheck ### cppcheck
@@ -416,7 +423,9 @@ The open source static checker [cppcheck](http://cppcheck.sourceforge.net/)
checks various problems with respect to style, performance, portability checks various problems with respect to style, performance, portability
and general fishiness. To enable all checks, run and general fishiness. To enable all checks, run
$ cppcheck --enable=all --force -I/usr/include -Dtyp=uint32_t prog.c ```sh
cppcheck --enable=all --force -I/usr/include -Dtyp=uint32_t prog.c
```
No issues found. No issues found.
@@ -427,6 +436,7 @@ checks various problems with respect to security like buffer overflows,
function arguments to known troublemaker functions and more. It doesn't need to 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: pre-process code, so can be run without the `typ` macro being defined:
```sh
$ flawfinder prog.c $ flawfinder prog.c
Flawfinder version 1.31, (C) 2001-2014 David A. Wheeler. Flawfinder version 1.31, (C) 2001-2014 David A. Wheeler.
Number of rules (primarily dangerous function names) in C/C++ ruleset: 169 Number of rules (primarily dangerous function names) in C/C++ ruleset: 169
@@ -434,9 +444,9 @@ pre-process code, so can be run without the `typ` macro being defined:
FINAL RESULTS: FINAL RESULTS:
ANALYSIS SUMMARY: ANALYSIS SUMMARY:
No hits found. No hits found.
$ ```
### valgrind #### valgrind
The open source dynamic checker [valgrind](http://valgrind.org/) The open source dynamic checker [valgrind](http://valgrind.org/)
runs an executable and verifies all memory accesses and (de)allocations for runs an executable and verifies all memory accesses and (de)allocations for
@@ -511,7 +521,7 @@ So I `fclose(stdout)` before returning and now:
A squeaky clean valgrind result! A squeaky clean valgrind result!
### FlexeLint #### FlexeLint
FlexeLint is a commercial lint tool by [Gimpel FlexeLint is a commercial lint tool by [Gimpel
Software](http://www.gimpel.com/html/index.htm). It supports nearly a Software](http://www.gimpel.com/html/index.htm). It supports nearly a
@@ -629,9 +639,7 @@ what remained:
-esym(9058,__*) // tag not used outside typedef -esym(9058,__*) // tag not used outside typedef
-e9092 // NULL does not expand to a pointer (but plain 0) -e9092 // NULL does not expand to a pointer (but plain 0)
### Compulsory obfuscations
Compulsory obfuscations
-----------------------
Which of the rules cause which obfuscation? Which of the rules cause which obfuscation?
@@ -641,7 +649,9 @@ expressions other than assignments to `char` objects. A consequence is
that printing digits with `'0' + digit` is not allowed (even though 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 `'0'` is technically an `int`!) so I am forced to output hex digits with
```c
printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2)))); 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 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? an improvement over `printf("%c", '0' + tyr + 7 * (tyr / 10)`, MISRA?
@@ -664,9 +674,10 @@ precedence rules in expressions." This requires parentheses for almost
all expressions involving more than one operator, especially those for which all expressions involving more than one operator, especially those for which
a cast is required, leading to hard to understand expressions such as a cast is required, leading to hard to understand expressions such as
```c
const ser glx = (ser)((asx > (ser)64u) ? (ser)((ser)asx + (ser)8u + (ser)1u) : (ser)asx); 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)); 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 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, the function." Sigh. Since I must use eloquent prototypes (8.1, 16.3,
@@ -676,20 +687,23 @@ 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 silly 24 character indent. The maximum indent is forced to 8, which is way
too high for a sane function. too high for a sane function.
MISRA 16.10, "If a function returns error information, then that error 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 information shall be tested." A cast to void would draw a lint warning, so
I use the `printf` result in expressions, I use the `printf` result in expressions,
```c
lys -= 4 * printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2)))); lys -= 4 * printf("%c", (met)tyr + 32 + 16 + ((8 + EOF) * ((met)tyr / (8 + 2))));
val += printf("\n") / ((__LINE__ * L_tmpnam) + TMP_MAX); val += printf("\n") / ((__LINE__ * L_tmpnam) + TMP_MAX);
val -= (printf(" %d\n", val) > BUFSIZ) ? FILENAME_MAX : EOF; val -= (printf(" %d\n", val) > BUFSIZ) ? FILENAME_MAX : EOF;
```
which are, in the absence of errors, equivalent to which are, in the absence of errors, equivalent to
```c
lys -= 4; lys -= 4;
/*nop*/ /*nop*/
++val; ++val;
```
MISRA 13.1, "Assignment operators shall not be used in expressions that MISRA 13.1, "Assignment operators shall not be used in expressions that
@@ -702,9 +716,11 @@ 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 addressed object." in conjunction with lint's "Note 952: Parameter could
be declared const" causes const-poisoning for all functions, be declared const" causes const-poisoning for all functions,
```c
static void phe(const ala not); static void phe(const ala not);
static void gly(ala *const not, const and his); static void gly(ala *const not, const and his);
met main(met val, const pro *const his[]); met main(met val, const pro *const his[]);
```
and quite a number of automatic variables. and quite a number of automatic variables.
@@ -718,15 +734,19 @@ up :-) (humor really helps!)"
If your compiler supports a 128 bit wide type (e.g. clang, gcc) then If your compiler supports a 128 bit wide type (e.g. clang, gcc) then
you can use it via the `typ` macro: you can use it via the `typ` macro:
```sh
clang -Dtyp=__uint128_t -o prog prog.c clang -Dtyp=__uint128_t -o prog prog.c
```
Indeed, the program can use (and lints clean for) all of Indeed, the program can use (and lints clean for) all of
```sh
clang -Dtyp=uint8_t -o prog8 prog.c clang -Dtyp=uint8_t -o prog8 prog.c
clang -Dtyp=uint16_t -o prog16 prog.c clang -Dtyp=uint16_t -o prog16 prog.c
clang -Dtyp=uint32_t -o prog32 prog.c clang -Dtyp=uint32_t -o prog32 prog.c
clang -Dtyp=uint64_t -o prog64 prog.c clang -Dtyp=uint64_t -o prog64 prog.c
clang -std=c89 -Dtyp="unsigned long" -o prog89 prog.c clang -std=c89 -Dtyp="unsigned long" -o prog89 prog.c
```
This works because the program has no need for corresponding `SCN` or This works because the program has no need for corresponding `SCN` or
`PRI` macros to do the scanning and printing of variables of these `PRI` macros to do the scanning and printing of variables of these
@@ -761,11 +781,10 @@ memory resources with the ulimit(1) built-in of your shell.
For all intents and purposes, the *Not Overflowing Type* keeps the promise! For all intents and purposes, the *Not Overflowing Type* keeps the promise!
-------------------------------------------------------------------------------- ## Copyright:
<!--
(c) Copyright 1984-2016, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved (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]. This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc].
[judges]: http://www.ioccc.org/judges.html [judges]: http://www.ioccc.org/judges.html
[cc]: http://creativecommons.org/licenses/by-sa/3.0/ [cc]: http://creativecommons.org/licenses/by-sa/3.0/
-->