Add 2020 source files for real

This commit is contained in:
Landon Curt Noll committed 2020-12-31 18:34:17 -08:00
1 parent a3c1748648
commit 9d61fc0fb4
147 files changed
+32101

No files matched your search

+588
View File
@@ -0,0 +1,588 @@
#!/usr/bin/env make
#
# 2020 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/
#############################
# shell used by this Makefile
#############################
#
SHELL= /bin/bash
#######################
# common tool locations
#######################
#
A2P= a2p
AR= ar
ASA= asa
AT= at
ATQ= atq
ATRM= atrm
AWK= awk
BANNER= banner
BASE64= base64
BASENAME= basename
BATCH= batch
BC= bc
BINHEX= binhex
BISON= bison
BUNZIP2= bunzip2
BZCAT= bzcat
BZCMP= bzcmp
BZDIFF= bzdiff
BZEGREP= bzegrep
BZFGREP= bzfgrep
BZGREP= bzgrep
BZIP2= bzip2
BZLESS= bzless
BZMORE= bzmore
C2PH= c2ph
C89= c89
C99= c99
CAL= cal
CALC= calc
CAT= cat
CD= cd
CHFLAGS= chflags
CHGRP= chgrp
CHMOD= chmod
CKSUM= cksum
CLANG= clang
CLANG_PLUSPLUS= clang++
CLEAR= clear
CMP= cmp
COL= col
COLLDEF= colldef
COLRM= colrm
COLUMN= column
COMPRESS= compress
CP= cp
CPIO= cpio
CPP= cpp
CRC32= crc32
CSH= csh
CSPLIT= csplit
CURL= curl
CUT= cut
C_PLUSPLUS= c++
C_PLUSPLUS_FILT= c++filt
DATE= date
DC= dc
DD= dd
DF= df
DIFF3= diff3
DIFF= diff
DIG= dig
DIRNAME= dirname
ECHO= echo
ED= ed
EGREP= egrep
ENV= env
EQN= eqn
ETAGS= etags
EXPECT= expect
EXPR= expr
FALSE= false
FGREP= fgrep
FILE= file
FIND2PERL= find2perl
FIND= find
FLEX= flex
FLEX_PLUSPLUS= flex++
FMT= fmt
FOLD= fold
FS_USAGE= fs_usage
FUNZIP= funzip
FUSER= fuser
GCC= gcc
GDIFFMK= gdiffmk
GENCAT= gencat
GENSTRINGS= genstrings
GETOPT= getopt
GETOPTS= getopts
GINDENT= gindent
GNUMAKE= gnumake
GREP= grep
GROFF= groff
GROFFER= groffer
GROG= grog
GROPS= grops
GROTTY= grotty
GUNZIP= gunzip
GVIM= gvim
GZCAT= gzcat
GZEXE= gzexe
GZIP_PROG= gzip
G_PLUSPLUS= g++
H2PH= h2ph
H2XS= h2xs
HASH= hash
HEAD= head
HOSTNAME_PROG= hostname
ICONV= iconv
ID= id
INDENT= indent
INFO= info
JOT= jot
KILL= kill
KSH= ksh
LAST= last
LD= ld
LESSECHO= lessecho
LEX= len
LINK= link
LN= ln
LS= ls
M4= m4
MAKE= make
MAN= man
MKDIR= mkdir
MKFIFo= mkfifo
MKTEMP= mktemp
MV= mv
NANO= nano
NASM= nasm
NEQN= neqn
NICE= nice
NL= nl
NM= nm
NOHUP= nohup
NROFF= nroff
NSLOOKUP= nslookup
OD= od
OPENSSL= openssl
PASTE= paste
PATCH= patch
PATHCHK= pathchk
PAX= pax
PERL= perl
PICO= pico
PR= pr
PRINTENV= printenv
PS= ps
PTAR= ptar
PTARDIFF= ptardiff
PTARGREP= ptargrep
PWD= pwd
PYDOC= pydoc
PYTHON= python
PYTHONW= pythonw
READLINK= readlink
RENICE= renice
RESET= reset
REV= rev
RI= ri
RM= rm
RMDIR= rmdir
RSYNC= rsync
RUBY= ruby
RVIM= rvim
SAY= say
SCP= scp
SCREEN= screen
SCRIPT= script
SDIFF= sdiff
SED= sed
SEQ= seq
SFTP= sftp
SH= sh
SHA1= sha1
SHA= sha
SHAR= shar
SHASUM5_18= shasum5.18
SHASUM= shasum
SIZE= size
SLEEP= sleep
SORT= sort
SSH= ssh
STAT= stat
STRIP= strip
STTY= stty
SUM= sum
SYNC= sync
TABS= tabs
TAIL= tail
TAR= tar
TEE= tee
TEST= test
TFTP= tftp
TIDY= tidy
TIME= time
TOP= top
TOUCH= touch
TPUT= tout
TPUT= tput
TR= tr
TROFF= troff
TRUE= true
TSET= tset
TSORT= tsort
UL= ul
UNAME= uname
UNCOMPRESS= uncompress
UNEXPAND= unexpand
UNIFDEF= unifdef
UNIFDEFALL= unifdefall
UNIQ= uniq
UNITS= units
UNLINK= unlink
UNZIP= unzip
UNZIPSFX= unzipsfx
UPTIME= uptime
UUDECODE= uudecode
UUENCODE= uuencode
UUIDGEN= uuidgen
VI= vi
VIEW= view
VIM= vim
VIMDIFF= vimdiff
W= w
WAIT4PATH= wait4path
WAIT= wait
WC= wc
WHAT= what
WHATIS= whatis
WHICH= which
WHO= who
WHOAMI= whoami
WHOIS= whois
WRTIE= write
XAR= xar
XARGS= xargs
XATTR= xattr
XXD= xxd
YACC= yacc
YES= yes
ZCAT= zcat
ZCMP= zcmp
ZDIFF= zdiff
ZEGREP= zegrep
ZFGREP= zfgrep
ZFORCE= zforce
ZGREP= zgrep
ZIP= zip
ZIPCLOAK= zipcloak
ZIPGREp= zipgrep
ZIPINFo= zipinfo
ZIPNOTE= zipnote
ZIPSPLIT= zipsplit
ZLESS= zless
ZMORE= zmore
ZNEW= znew
ZPRINT= zprint
ZSH= zsh
# 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
# CWARN - Silence warnings that ${CWARN} would normally complain about
# CSILENCE -Compiler warnings
#
ifeq ($(CC),clang)
# clang CSILENCE and CWARN
#
#CSILENCE=
#CSILENCE= -Wno-implicit-int
CSILENCE= -Wno-implicit-int-conversion -Wno-missing-prototypes -Wno-missing-variable-declarations \
-Wno-shorten-64-to-32 -Wno-sign-conversion -Wno-unreachable-code-return -Wno-conversion \
-Wno-unknown-warning-option
#
#CWARN= $CSILENCE}
#CWARN= -Wall $CSILENCE}
#CWARN= -Wall -Wextra $CSILENCE}
#CWARN= -Wall -Wextra -pedantic ${CSILENCE}
#CWARN= -Wall -Wextra -Weverything $CSILENCE}
CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE}
else
ifeq ($(CC),gcc)
# gcc CSILENCE and CWARN
#
CSILENCE=
#CSILENCE= -Wno-implicit-int
#
#CWARN= $CSILENCE}
#CWARN= -Wall $CSILENCE}
#CWARN= -Wall -Wextra $CSILENCE}
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
else
# default CSILENCE and WARN
#
CSILENCE=
#CSILENCE= -Wno-implicit-int
#
#CWARN= $CSILENCE}
#CWARN= -Wall $CSILENCE}
#CWARN= -Wall -Wextra $CSILENCE}
CWARN= -Wall -Wextra -pedantic ${CSILENCE}
#CWARN= -Wall -Wextra -Weverything $CSILENCE}
#CWARN= -Wall -Wextra -Weverything -pedantic ${CSILENCE}
endif
endif
# 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-bitness:
# ARCH= -m64
#
# By default we assume nothing:
#
ARCH=
# defines that are needed to compile
#
CDEFINE=
#CDEFINE= -DIOCCC
# include files that are needed to compile
#
CINCLUDE=
#CINCLUDE= -include stdlib.h
#CINCLUDE= -include stdio.h
#CINCLUDE= -include stdlib.h -include stdio.h
#CINCLUDE= -I ${X11_INCDIR}
# 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= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT}
# Libraries needed to build
#
LIBS=
#LIBS= -L ${X11_LIBDIR}
# 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
##############################
#
OBJ= prog.o
DATA=
TARGET= prog
#
ALT_OBJ=
ALT_TARGET=
#################
# build the entry
#################
#
all: ${TARGET} ${DATA}
@${TRUE}
prog: prog.c
${CC} ${CFLAGS} $< -o $@ ${LIBS}
# alternative executable
#
alt: ${ALT_TARGET}
@${TRUE}
# data files
#
data: ${DATA}
@${TRUE}
###############
# utility rules
###############
#
everything: all alt
clean:
${RM} -f ${OBJ} ${ALT_OBJ}
@-if [ -f indent.c ]; then \
${ECHO} ${RM} -f indent.c; \
${RM} -f indent.c; \
fi
clobber: clean
${RM} -f ${TARGET} ${ALT_TARGET}
@-if [ -e sandwich ]; then \
${RM} -f sandwich; \
${ECHO} 'ate sandwich'; \
fi
nuke: clobber
@${TRUE}
dist_clean: nuke
@${TRUE}
install:
@${ECHO} "Surely you are performing, Dr. Science!"
@${TRUE}
# backwards compatibility
#
build: all
@${TRUE}
# you may be able to mis-understand the source by reading indent.c
#
indent.c: prog.c
@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 prog found, ident $< yourself, sorry"; \
${ECHO} "exit 1"; \
exit 1; \
fi
##################
# 133t hacker rulz
##################
#
love:
@${ECHO} 'not war?'
@${TRUE}
haste:
$(MAKE) waste
@${TRUE}
waste:
@${ECHO} 'haste'
@${TRUE}
make:
@${ECHO} 'We encourage you to attend a maker faire'
@${TRUE}
easter_egg:
@${ECHO} you expected to often mis-understand this $${RANDOM} magic
@${ECHO} chongo '<was here>' "/\\oo/\\"
@${ECHO} Eggy and Kitty
fabricate fashion form frame manufacture produce: make
@${TRUE}
sandwich:
@if [ `id -u` -eq 0 ]; then \
${ECHO} 'Okay.'; \
${ECHO} $${RANDOM}`date +%s`$${RANDOM} | \
${SHASUM} -a 512256 | \
${SED} -e 's/ .*//' > $@; \
else \
${ECHO} 'Reall?!? Make it yourself.'; \
exit 1; \
fi
# 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_v6; \
else \
${ECHO} "planet deniers, like a few silly IAU members, are so cute when they try to defend their logic"; \
fi
@${ECHO} A $@ helps ${MAKE} the elements that help form planets
@${TRUE}
deep_magic:
@-if [ -r .code_anal ]; then \
ccode_analysis --deep_magic 253d8c80830e2df66c018820004b3d4939821bbd7d781fc50d9e633797e44f65d1d62c707bb7e5a82c328a37bbf9ecb4c46fb56aa3f08641fcf45d10ba3c6081 --FNV1a_hash_512_bit "prog"; \
else \
${ECHO} "Wrong! Do it again!"; \
sleep 1; \
${ECHO} "Wrong! Do it again!"; \
sleep 1; \
${ECHO} "Wrong! Do it again!"; \
fi
@${TRUE}
magic: deep_magic
@-if [ -r .code_anal ]; then \
ccode_analysis --level 391581 --mode 216193 --state Riesel --FNV1a_hash_512_bit "prog"; \
else \
${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?!"; \
${ECHO} "p.s. Be cafeful with that axe, Eugene."; \
fi
@${TRUE}
# The IOCCC resident astronomer states
#
charon: supernova
@${ECHO} $@ is a dwarf planet
@${ECHO} dwarf is a type of planet
@${ECHO} therefore we continue to tell the IAU that $@ is a planet
pluto: supernova
${MAKE} charon
@${ECHO} $@ is a dwarf planet
@${ECHO} dwarf is a type of planet
@${ECHO} therefore, $@ is a planet
@${ECHO} having lots of planets is good feature because $< can help ${MAKE} a lot of them
+153
View File
@@ -0,0 +1,153 @@
# Most percussive
Nathan Otterness
<https://github.com/yalue>
The code for this entry can be found in prog.c
## Judges' comments:
### To use:
make
./prog < input.mid > output.mid
### Try:
wget -O cvikl.mid 'http://www.kunstderfuge.com/-/midi.asp?file=beethoven/symphony_6_1_(c)cvikl.mid'
./prog < cvikl.mid > output.mid
# Play output.mid with your favorite player
wget -O entertainer.mid https://www.midiworld.com/download/3857
./prog < entertainer.mid > output2.mid
# Play output.mid with your favorite player
### Selected Judges Remarks:
In an entry that boasts not using literals, one would expect to see straightforward ways to produce
small integers like `!(x^x)<<!(x^x)`, etc. but this entry is trickier than that. Deciphering what it does,
apart from reading stdin and writing to stdout, would take a while.
While doing that, you can be audially *entertained* by a sample of its output.
## Author's comments:
### MIDI "boots and cats"
This program seeks to automatically "improve" standard MIDI files (.mid) by
adding an extra track that provides a driving drum beat to bring some
excitement into boring video-game music rips or classical music sequences that
otherwise only see the light of day when modern musicians import them into FL
Studio to copy a few chords.
#### Prerequisites
If you're not using Windows Media Player or already familiar with MIDI files,
you may need to install some additional software to be able to listen to them.
For example, on Ubuntu, I was able to play them in VLC after installing
`vlc-plugin-fluidsynth` and `fluid-soundfont-gm`.
You can obtain MIDIs in many places, but I mostly tested the program using
files I found [here](http://www.kunstderfuge.com/beethoven/variae.htm#Symphonies).
However, as discussed under the Limitations heading below, not all of them
work correctly. I will admit to having used
`http://www.kunstderfuge.com/-/midi.asp?file=beethoven/symphony_6_1_(c)cvikl.mid`
for most of my testing.
#### Usage
Compile the program using the following command (I tested this using both
`clang` and `gcc`):
```
$CC -pedantic -Wall -Werror -Wextra -O3 -o prog prog.c
```
The program expects a MIDI on stdin, and writes a modified MIDI to stdout:
```
./prog <input.mid >output.mid
```
If the program encounters an error, no output will generally be produced, and
it will exit with a specific status code. Meanings of the various status codes
are listed below, under the "Program error codes" heading. On success, the
program exits with a code of 0.
#### Limitations
1. The program does not support MIDI files over 4 MB (specifically, it will
not take input files larger than 2^22 - 1 bytes). This is unlikely to be a
big limitation in practice, since even lengthy MIDIs are rarely over a
couple hundred KB.
2. Not all MIDIs set (or *correctly* set) their timing information, which will
lead to the tempo of the drum beat not matching the track. This will be
especially true for "live performance" .mid files.
3. There may be some types of MIDI messages that the program is unable to
correctly parse, but I have rarely seen this in practice. The largest
cause of program failures, in my experience, has been Limitation 2.
#### Obfuscation notes
I had one primary goal when writing this program: include no C literals
whatsoever. The final C file includes no numerical, string, or character
literals. Instead, all literals have been replaced with a handful of global
variables, which are occasionally modified throughout the file to prevent
simple uses of find-and-replace.
So, in a sense, this obfuscation is simply an intentional use of global
variables' classic problem: absolute spaghetti code. The absence of any sort
of literals has the added benefit of forcing any would-be reader to trace the
contents of many variables starting from `main`, since, without literals, very
little of the code gives any inherent visual cues as to its purpose.
I already took the liberty of running `prog.c` through `clang-format`, since it
still fits in the size limit and the formatting of the code was never intended
to be an obfuscation technique here.
#### Other remarks
MIDI files are generally divided up into one or more "tracks" that play
concurrently. While it is easy to find the positions of each of these tracks
in the file, figuring out the amount of time each track is supposed to play is
more difficult, and requires parsing every track in its entirety. This means
that generating a drum beat that covers the entire piece of music requires
parsing every track (the entire file) in order to determine the longest track.
Once the program has determined the longest track in the file, it generates a
new track, containing the simple 4-note percussion sequence, to match the
length (in beats) of the longest-running track. It appends the new track onto
the end of the file, taking care to update the file header, as well.
### Program error codes
If the program encounters an error, it will exit with a nonzero code. The error
codes can be interpreted as follows:
- `1`: Encountered an invalid MIDI variable-length integer in the input.
- `2`: Attempted to write an invalid MIDI variable-length integer to output.
(This would be an internal error).
- `3`: Encountered an unsupported MIDI event in the input.
- `4`: Encountered a bad MIDI track header in the input.
- `5`: The input MIDI file uses SMPTE time division, which isn't supported.
- `6`: Failed allocating a temporary buffer to hold a single copy of our "beat"
messages.
- `7`: Failed allocating a buffer to hold the new track data.
- `8`: Failed allocating a buffer to hold the input file.
- `9`: The input file was too large.
- `10`: The input file's MIDI header was incorrect (but this isn't checked
very thoroughly).
-----------------------------------------------------------------------------------------------------
(c) Copyright 1984-2020, [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/
-----------------------------------------------------------------------------------------------------
+185
View File
@@ -0,0 +1,185 @@
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional //EN">
<html>
<head>
<meta name="GENERATOR" content="mkd2html 2.2.2">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css" />
<title></title>
<title>Most percussive</title>
</head>
<body>
<CENTER>
<IMG SRC="/png/ioccc.png" ALT="IOCCC" height=78 width=267>
<P><FONT size="6"><I>The International Obfuscated C Code Contest</I></FONT></P>
<div id="bar">
<ul>
<li><a href="../index.html">About the 27th IOCCC</a></li>
<li><a href="../whowon.html">27th IOCCC Winners</a></li>
<li><a href="/index.html">IOCCC home</a></li>
<li><a href="/winners.html">List of All Winners</a></li>
<li><a href="/judges.html">The Judges</a></li>
</ul>
</div>
<P><FONT size="6"><B>A 27<sup>th</sup> IOCCC Winner</B></FONT></P>
</CENTER>
<h1>Most percussive</h1>
<p>Nathan Otterness<br/>
<a href="https://github.com/yalue">https://github.com/yalue</a></p>
<p>The code for this entry can be found in <a href="prog.c">prog.c</a></p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./prog &lt; input.mid &gt; output.mid
</code></pre>
<h3>Try:</h3>
<pre><code>wget -O cvikl.mid 'http://www.kunstderfuge.com/-/midi.asp?file=beethoven/symphony_6_1_(c)cvikl.mid'
./prog &lt; cvikl.mid &gt; output.mid
# Play output.mid with your favorite player
wget -O entertainer.mid https://www.midiworld.com/download/3857
./prog &lt; entertainer.mid &gt; output2.mid
# Play output.mid with your favorite player
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>In an entry that boasts not using literals, one would expect to see straightforward ways to produce
small integers like <code>!(x^x)&lt;&lt;!(x^x)</code>, etc. but this entry is trickier than that. Deciphering what it does,
apart from reading stdin and writing to stdout, would take a while.</p>
<p>While doing that, you can be audially <em>entertained</em> by a sample of its output.</p>
<h2>Author&rsquo;s comments:</h2>
<h3>MIDI &ldquo;boots and cats&rdquo;</h3>
<p>This program seeks to automatically &ldquo;improve&rdquo; standard MIDI files (.mid) by
adding an extra track that provides a driving drum beat to bring some
excitement into boring video-game music rips or classical music sequences that
otherwise only see the light of day when modern musicians import them into FL
Studio to copy a few chords.</p>
<h4>Prerequisites</h4>
<p>If you&rsquo;re not using Windows Media Player or already familiar with MIDI files,
you may need to install some additional software to be able to listen to them.
For example, on Ubuntu, I was able to play them in VLC after installing
<code>vlc-plugin-fluidsynth</code> and <code>fluid-soundfont-gm</code>.</p>
<p>You can obtain MIDIs in many places, but I mostly tested the program using
files I found <a href="http://www.kunstderfuge.com/beethoven/variae.htm#Symphonies">here</a>.
However, as discussed under the Limitations heading below, not all of them
work correctly. I will admit to having used
<code>http://www.kunstderfuge.com/-/midi.asp?file=beethoven/symphony_6_1_(c)cvikl.mid</code>
for most of my testing.</p>
<h4>Usage</h4>
<p>Compile the program using the following command (I tested this using both
<code>clang</code> and <code>gcc</code>):
<code>
$CC -pedantic -Wall -Werror -Wextra -O3 -o prog prog.c
</code></p>
<p>The program expects a MIDI on stdin, and writes a modified MIDI to stdout:
<code>
./prog &lt;input.mid &gt;output.mid
</code></p>
<p>If the program encounters an error, no output will generally be produced, and
it will exit with a specific status code. Meanings of the various status codes
are listed below, under the &ldquo;Program error codes&rdquo; heading. On success, the
program exits with a code of 0.</p>
<h4>Limitations</h4>
<ol>
<li><p>The program does not support MIDI files over 4 MB (specifically, it will
not take input files larger than 2<sup>22</sup> - 1 bytes). This is unlikely to be a
big limitation in practice, since even lengthy MIDIs are rarely over a
couple hundred KB.</p></li>
<li><p>Not all MIDIs set (or <em>correctly</em> set) their timing information, which will
lead to the tempo of the drum beat not matching the track. This will be
especially true for &ldquo;live performance&rdquo; .mid files.</p></li>
<li><p>There may be some types of MIDI messages that the program is unable to
correctly parse, but I have rarely seen this in practice. The largest
cause of program failures, in my experience, has been Limitation 2.</p></li>
</ol>
<h4>Obfuscation notes</h4>
<p>I had one primary goal when writing this program: include no C literals
whatsoever. The final C file includes no numerical, string, or character
literals. Instead, all literals have been replaced with a handful of global
variables, which are occasionally modified throughout the file to prevent
simple uses of find-and-replace.</p>
<p>So, in a sense, this obfuscation is simply an intentional use of global
variables' classic problem: absolute spaghetti code. The absence of any sort
of literals has the added benefit of forcing any would-be reader to trace the
contents of many variables starting from <code>main</code>, since, without literals, very
little of the code gives any inherent visual cues as to its purpose.</p>
<p>I already took the liberty of running <code>prog.c</code> through <code>clang-format</code>, since it
still fits in the size limit and the formatting of the code was never intended
to be an obfuscation technique here.</p>
<h4>Other remarks</h4>
<p>MIDI files are generally divided up into one or more &ldquo;tracks&rdquo; that play
concurrently. While it is easy to find the positions of each of these tracks
in the file, figuring out the amount of time each track is supposed to play is
more difficult, and requires parsing every track in its entirety. This means
that generating a drum beat that covers the entire piece of music requires
parsing every track (the entire file) in order to determine the longest track.</p>
<p>Once the program has determined the longest track in the file, it generates a
new track, containing the simple 4-note percussion sequence, to match the
length (in beats) of the longest-running track. It appends the new track onto
the end of the file, taking care to update the file header, as well.</p>
<h3>Program error codes</h3>
<p>If the program encounters an error, it will exit with a nonzero code. The error
codes can be interpreted as follows:</p>
<ul>
<li><code>1</code>: Encountered an invalid MIDI variable-length integer in the input.</li>
<li><code>2</code>: Attempted to write an invalid MIDI variable-length integer to output.
(This would be an internal error).</li>
<li><code>3</code>: Encountered an unsupported MIDI event in the input.</li>
<li><code>4</code>: Encountered a bad MIDI track header in the input.</li>
<li><code>5</code>: The input MIDI file uses SMPTE time division, which isn&rsquo;t supported.</li>
<li><code>6</code>: Failed allocating a temporary buffer to hold a single copy of our &ldquo;beat&rdquo;
messages.</li>
<li><code>7</code>: Failed allocating a buffer to hold the new track data.</li>
<li><code>8</code>: Failed allocating a buffer to hold the input file.</li>
<li><code>9</code>: The input file was too large.</li>
<li><code>10</code>: The input file&rsquo;s MIDI header was incorrect (but this isn&rsquo;t checked
very thoroughly).</li>
</ul>
<BR>
<HR>
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2020,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
+226
View File
@@ -0,0 +1,226 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define P(a, b) fwrite(a, b, !!a, stdout)
typedef uint8_t u1;
typedef uint16_t u2;
typedef uint32_t u4;
u4 k, l, n;
u1 m, o, p, q, r, s, *t, *u;
u2 A(u1 *c) { return *(c + !!c) | (u2)(*c) << l; }
void B(u1 *c, u2 a) {
*c++ = a >> l;
*c = a;
}
int C(u1 *c, u4 *a) {
u1 b, d = k;
s = l--;
*a = k++;
for (; d<s>> k; d++) {
b = d[c];
*a |= b & p;
if (!(b >> l)) {
d += k--;
l = s;
return d;
}
*a = *a << l;
}
exit(!k);
return p;
}
u1 D(u4 a) {
u1 b = k++;
u1 c = l - k;
if (a) {
b = k;
while (a >>= k) b++;
}
k = k ? !k : k;
return b / c + !!(b % c);
}
int F(u4 a, u1 *c) {
u1 b = D(a);
*c = s - l--;
r = q / n;
if (!a) return b;
if (b > r) exit(o);
c += b;
c--;
while (a) {
*c = a & p;
a = a >> l;
c--;
}
l = s;
return b;
}
u1 *G(u1 *c, u1 *a) {
u4 d;
u1 b, e;
m = m < p ? p << q : m;
q = q < n + o ? p >> q : q;
e = *c;
if (e == m || e == m + q) {
*a = k;
c++;
c += C(c, &d);
return c + d;
}
if (e == (m | p)) {
*a = k;
c++;
c++;
c += C(c, &d);
return c + d;
}
l /= o;
if (e >> q) {
b = *c;
c++;
*a = b;
} else {
b = *a;
}
e = b >> l;
if (e < s || e > l + s) exit(n);
if (e != l + s && e != l + o) c++;
c++;
l = s;
return c;
}
u1 *H(u1 *c, u4 *a) {
u4 b, e, h = q, i = m;
u1 *d, f = k;
*a = k;
q = q / n;
m = p - m + p / m;
if (n[c] != m) exit(q);
b = (u4)A(c + q) << q * q | A(c + (m >> q));
c += l;
d = c + b;
while (c < d) {
c += C(c, &e);
*a += e;
c = G(c, &f);
}
q = h;
m = i;
return c;
}
u4 I(u1 *c, u4 a) {
u4 e, b, d = k;
for (e = k; e < a; e++) {
c = H(c, &b);
if (b > d) d = b;
}
return d;
}
u1 *J(u1 *c, u4 a, u4 b) {
u1 d, e;
if (l > o) {
o = (--s - o) << r;
l = p % (s + o);
r = o / l;
n = l / r;
m = o / n;
}
d = l + r;
e = o;
if (!(a % m)) {
d = l - m;
e = o + l;
} else if ((a % m) == r) {
d = l;
e = n + o;
}
k[t] = d;
r[t] = e;
*u = d;
memcpy(c, t, b);
return c + b;
}
void K(u1 *c, u4 a) {
u1 *b, *d;
u2 e, f;
u4 g, h, i, j;
o = n ^ k;
m = l;
l = o << o;
f = A(c + l + o);
e = A(c + l + o + o) >> k--;
p = ~k++;
p >>= k--;
q = p >> n;
if (e >> q--) exit(n + o);
g = I(c + q--, f) / e;
i = n + o + D(e);
if (!(t = malloc(i))) exit(n * o);
j = g * i + q;
b = malloc(j);
r = --l;
l++;
if (!b) exit(r);
*b = l << n | q;
*(!k + b) = *b + r;
n[b] = (*b << n) + n;
o[b] = n[b] + r--;
B(b + n * o, j - l);
B(b + o * o, (j - l) >> o * l);
d = t;
*d++ = k;
*d++ = r * r;
m = p / (n + o);
*d++ = p - m - o;
d += F(e, d);
u = d;
*d++ = r * r;
*d = k;
d = b + l;
*d++ = k++;
*d++ = p + q + q;
memcpy(d, t + k, i - k);
d += i - k;
for (h = k; h < g; h++) d = J(d, h, i);
l = (o + m) / s - m;
o = r;
*d++ = --k;
*d++ = ~k;
*d++ = p / o - o * l;
*d = k++;
*(l + p + c) = k;
B(c + l + o, f + k);
P(c, a);
P(b, j);
}
int main() {
u4 a, b;
u1 *c;
k = !!stdin;
n = k + k + k;
l = k << n;
m = l;
l = (l | l >> (k + k)) << k;
b = k << l;
c = malloc(b);
if (!c) exit(m);
a = fread(c, k, b, stdin);
l = (m << k) + m + k;
if (a >= b) exit(l / n + k);
if ((n[c] != l << (k + k)) || ((m - k)[c] != n + n))
exit((m << k) - (n << k));
K(c, a);
return !b;
}