Code:
/* testgen.cpp - Generates a test ZPAQ config file.
(C) 2011, Dell Inc. Written by Matt Mahoney.
Licensed under GPL v3. http://www.gnu.org/licenses/gpl.html
To use:
g++ testgen.cpp -o testgen (compile testgen)
testgen > test.cfg (create config file test.cfg)
zpaq prtest nul: testdata (creates a 3754 byte test file)
zpaq ctest testdata (compresses to testdata.zpaq)
zpaq x testdata.zpaq out1 (out1 should match testdata)
zpaq ox testdata.zpaq out2 (out2 should match testdata)
pzpaq -dkvc testdata.zpaq > out3 (out3 should match testdata)
unzpaq x testdata.zpaq out4 (out4 should match testdata)
test.cfg creates a ZPAQ configuration file describing an indirect
order 0 model and a postprocessor that ignores the decoded data
except for EOF, and then generates output using 16603 mostly random
bytes of ZPAQL code. It can only be used to compress testdata as
created above by using zpaq to run the postprocessor in standalone
mode. Once created, it can be compressed with zpaq and then
decompressed with any zpaq compatible decompressor.
The generated code is "mostly" random with the following exceptions.
- No illegal instructions.
- No ERROR instructions.
- No backward jumps.
- No jumps into the middle of a 2 or 3 byte instruction.
- One out of 8 instructions is conditionally skipped using one of
the 4 constructs JT, JF, JT 3 LJ, JF 3 LJ
- All instructions that modify the A register are followed by OUT.
- HALT only once at the end.
- The beginning of the program checks for EOF before doing the rest.
- JMP is not tested.
*/
#include <stdio.h>
#include <stdlib.h>
// Opcodes from zpaq.cpp
static const char* op[256]={
"error","a++", "a--", "a!", "a=0", "", "", "a=r",
"b<>a", "b++", "b--", "b!", "b=0", "", "", "b=r",
"c<>a", "c++", "c--", "c!", "c=0", "", "", "c=r",
"d<>a", "d++", "d--", "d!", "d=0", "", "", "d=r",
"*b<>a","*b++", "*b--", "*b!", "*b=0", "", "", "jt",
"*c<>a","*c++", "*c--", "*c!", "*c=0", "", "", "jf",
"*d<>a","*d++", "*d--", "*d!", "*d=0", "", "", "r=a",
"halt", "out", "", "hash", "hashd","", "", "jmp",
"a=a", "a=b", "a=c", "a=d", "a=*b", "a=*c", "a=*d", "a=",
"b=a", "b=b", "b=c", "b=d", "b=*b", "b=*c", "b=*d", "b=",
"c=a", "c=b", "c=c", "c=d", "c=*b", "c=*c", "c=*d", "c=",
"d=a", "d=b", "d=c", "d=d", "d=*b", "d=*c", "d=*d", "d=",
"*b=a", "*b=b", "*b=c", "*b=d", "*b=*b","*b=*c","*b=*d","*b=",
"*c=a", "*c=b", "*c=c", "*c=d", "*c=*b","*c=*c","*c=*d","*c=",
"*d=a", "*d=b", "*d=c", "*d=d", "*d=*b","*d=*c","*d=*d","*d=",
"", "", "", "", "", "", "", "",
"a+=a", "a+=b", "a+=c", "a+=d", "a+=*b","a+=*c","a+=*d","a+=",
"a-=a", "a-=b", "a-=c", "a-=d", "a-=*b","a-=*c","a-=*d","a-=",
"a*=a", "a*=b", "a*=c", "a*=d", "a*=*b","a*=*c","a*=*d","a*=",
"a/=a", "a/=b", "a/=c", "a/=d", "a/=*b","a/=*c","a/=*d","a/=",
"a%=a", "a%=b", "a%=c", "a%=d", "a%=*b","a%=*c","a%=*d","a%=",
"a&=a", "a&=b", "a&=c", "a&=d", "a&=*b","a&=*c","a&=*d","a&=",
"a&~a", "a&~b", "a&~c", "a&~d", "a&~*b","a&~*c","a&~*d","a&~",
"a|=a", "a|=b", "a|=c", "a|=d", "a|=*b","a|=*c","a|=*d","a|=",
"a^=a", "a^=b", "a^=c", "a^=d", "a^=*b","a^=*c","a^=*d","a^=",
"a<<=a","a<<=b","a<<=c","a<<=d","a<<=*b","a<<=*c","a<<=*d","a<<=",
"a>>=a","a>>=b","a>>=c","a>>=d","a>>=*b","a>>=*c","a>>=*d","a>>=",
"a==a", "a==b", "a==c", "a==d", "a==*b","a==*c","a==*d","a==",
"a<a", "a<b", "a<c", "a<d", "a<*b", "a<*c", "a<*d", "a<",
"a>a", "a>b", "a>c", "a>d", "a>*b", "a>*c", "a>*d", "a>",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "lj"};
static const char* cond[4]={"if", "ifnot", "ifl", "ifnotl"};
// Random byte based on RC4 with no key
int rnd() {
static int t=-1;
static unsigned char i=0, j=0, s[256];
if (t<0) do s[i]=i; while (++i);
j+=s[++i];
t=s[i];
s[i]=s[j];
s[j]=t;
return s[(s[i]+t)&255];
}
// Create test.cfg
int main() {
printf(
"(test.cfg)\n"
"comp 8 8 9 10 1\n"
" 0 icm 5\n"
"hcomp\n"
" halt\n"
"pcomp copy ;\n"
" a> 255 ifnot halt endif\n");
for (int i=0; i<10000; ++i) {
int r=rnd();
int cr=rnd()&31;
if (op[r][0] && r!=0 && op[r][0]!='j' && r!=56 && r!=255) {
if (cr<4) printf(" %s", cond[cr]);
printf(" %s", op[r]);
if (r%8==7) printf(" %d", rnd());
if (r<=4 || r==59 || r>=64 && r<=71 || r>=128 && r<=215)
printf(" out");
if (cr<4) printf(" endif");
printf("\n");
}
}
printf(" halt\n"
"end\n");
return 0;
}
Under Linux, change nul: to /dev/null and change copy to cp in the .cfg file.