home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume8
/
travesty
/
part01
/
travesty.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-20
|
8KB
|
312 lines
/*
travesty.c: make a travesty of a file
*/
static char travestyauthor[] =
"travesty was written by Daniel J. Bernstein.\n\
Internet address: brnstnd@acf10.nyu.edu.\n";
static char travestyversion[] =
"travesty version 1.0, 12/17/89.\n\
Copyright (c) 1989, Daniel J. Bernstein.\n\
All rights reserved.\n";
static char travestycopyright[] =
"travesty version 1.0, 12/17/89.\n\
Copyright (c) 1989, Daniel J. Bernstein.\n\
All rights reserved.\n\
\n\
Until January 1, 1993, you are granted the following rights: A. To make\n\
copies of this work in original form, so long as (1) the copies are exact\n\
and complete; (2) the copies include the copyright notice, this paragraph,\n\
and the disclaimer of warranty in their entirety. B. To distribute this\n\
work, or copies made under the provisions above, so long as (1) this is\n\
the original work and not a derivative form; (2) you do not charge a fee\n\
for copying or for distribution; (3) you ensure that the distributed form\n\
includes the copyright notice, this paragraph, and the disclaimer of\n\
warranty in their entirety. These rights are temporary and revocable upon\n\
written, oral, or other notice by Daniel J. Bernstein. These rights are\n\
automatically revoked on January 1, 1993. This copyright notice shall be\n\
governed by the laws of the state of New York.\n\
\n\
If you have questions about travesty or about this copyright notice,\n\
or if you would like additional rights beyond those granted above,\n\
please feel free to contact the author at brnstnd@acf10.nyu.edu\n\
on the Internet.\n";
static char travestywarranty[] =
"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
all warranties, explicit or implied, including but not limited to the\n\
implied warranties of merchantability and fitness for a particular purpose.\n\
Daniel J. Bernstein is not and shall not be liable for any damages,\n\
incidental or consequential, arising from the use of this program, even\n\
if you inform him of the possibility of such damages. This disclaimer\n\
shall be governed by the laws of the state of New York.\n\
\n\
In other words, use this program at your own risk.\n\
\n\
If you have questions about travesty or about this disclaimer of warranty,\n\
please feel free to contact the author at brnstnd@acf10.nyu.edu\n\
on the Internet.\n";
static char travestyusage[] =
"Usage: travesty [ -oord ] [ -nnum ] [ -rrand ] [ -sS ] [ -ACHUVW ]\n\
Help: travesty -H\n";
static char travestyhelp[] =
"travesty makes a travesty of its input.\n\
\n\
travesty -A: print authorship notice\n\
travesty -C: print copyright notice\n\
travesty -H: print this notice\n\
travesty -U: print short usage summary\n\
travesty -V: print version number\n\
travesty -W: print disclaimer of warranty\n\
\n\
travesty [ -oord ] [ -nnum ] [ -rrand ] [ -sS ]: let the monkeys bang away\n\
-oord: use an order-ord Markov process (default 5, limit 20)\n\
-nnum: generate num output characters (default 0, meaning forever)\n\
-rrand: use rand as the random number generator seed (default based on time)\n\
-s: start output same as input\n\
-S: start output at a random spot in input (default)\n\
\n\
travesty will respond to an ALRM signal by printing its random seed on stderr.\n\
\n\
If you have questions about or suggestions for travesty, please feel free\n\
to contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu\n\
on the Internet.\n";
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
extern int getopt();
extern char *optarg; /* these should be in getopt.h! */
extern int optind;
extern char *malloc();
extern char *realloc();
long random();
#include "djberr.h"
#include "djbatoi.h"
/* The following macro had better make chars into ints from 0 thru 255. */
#define ctoi(x) ((unsigned int) (x))
#define copy(s,t,len) bcopy(s,t,len)
#define cmp(s,t,len) bcmp(s,t,len) /* had better return signed value! */
#define ran(n) (((random() % n) + n) % n) /* idiotic % can be negative */
#define MAXORD 20
int flagstart = 0;
int numout = 0;
int ord = 5;
int ord1;
int seed;
int s[MAXORD + 1][257];
char *c;
int curc;
int *p;
int *q;
int last;
int m;
int len;
initp()
{
register int i;
for (i = 0;i < len;i++)
p[i] = i;
}
rearrange()
{
register int i,j,k;
register char t[MAXORD + 1];
for (i = 0;i < len;i++)
if (i != p[i])
{
copy(c + (j = i) * ord1,t,ord1);
do
{
k = p[j];
copy(c + k * ord1,c + j * ord1,ord1);
p[j] = j;
j = k;
}
while (p[j] != i);
copy(t,c + j * ord1,ord1);
p[j] = j;
}
}
sort(l,u,m)
register int l,u; /* we are useless if l == u; we crash if l > u */
register int m;
{
register int i;
register int ch;
if (m > ord)
return;
for (ch = 0; ch < 256; ch++)
s[m][ch] = 0;
for (i = l; i <= u; i++)
s[m][ctoi(c[p[i] * ord1 + m])]++;
s[m][0] += l - 1;
for (ch = 1; ch < 256; ch++)
s[m][ch] += s[m][ch - 1];
for (i = u; i >= l; i--)
q[s[m][ctoi(c[p[i] * ord1 + m])]--] = p[i]; /* trust me. */
for (i = l; i <= u; i++)
p[i] = q[i];
s[m][256] = u;
for (ch = 0; ch < 256; ch++)
if (s[m][ch] + 1 < s[m][ch + 1]) /* anything to save a procedure call */
sort(s[m][ch] + 1,s[m][ch + 1],m + 1);
}
zeroq()
{
register int i;
for (i = 0; i < len; i++)
q[i] = 0;
}
sigalrm()
{
fprintf(stderr,"Seed: %d\n",seed);
fflush(stderr);
}
main(argc,argv,envp)
int argc;
char *argv[];
char *envp[];
{
register int opt;
register int l, u, i;
register int num;
register int ch;
struct timeval tv;
(void) gettimeofday(&tv,NULL); /* if it fails, oh well */
seed = tv.tv_sec + tv.tv_usec;
while ((opt = getopt(argc,argv,"ACHUVWsSr:n:o:")) != EOF)
switch(opt)
{
case 'A': (void) err(travestyauthor); exit(1);
case 'C': (void) err(travestycopyright); exit(1);
case 'H': (void) err(travestyhelp); exit(1);
case 'U': (void) err(travestyusage); exit(1);
case 'V': (void) err(travestyversion); exit(1);
case 'W': (void) err(travestywarranty); exit(1);
case '?': (void) err(travestyusage); exit(1);
case 's': flagstart = 1; break;
case 'S': flagstart = 0; break;
case 'r': seed = atoi(optarg); break;
case 'n': numout = atoi(optarg); break;
case 'o': ord = atoi(optarg); break;
}
argv += optind, argc -= optind;
if (ord < 1) ord = 1;
if (ord > MAXORD) ord = MAXORD;
ord1 = ord + 1;
srandom(seed);
(void) signal(SIGALRM,sigalrm);
/* read in characters */
curc = 1024;
if ((c = malloc(ord1 * curc)) == NULL)
{
errn("travesty: fatal: input too big");
exit(1);
}
for (len = 0;(ch = getchar()) != EOF;len++)
{
if (len >= curc)
{
curc += 1024;
if ((c = realloc(c,ord1 * curc)) == NULL)
{
errn("travesty: fatal: input too big");
exit(1);
}
}
c[len * ord1] = ch;
}
if (len == 0)
{
exit(0); /* the travesty of emptiness is emptiness... right? */
}
for (i = 0; i < len; i++)
for (m = 0; m < ord; m++)
c[((i + (m + 1) * (len - 1)) % len) * ord1 + m + 1] = c[i * ord1];
p = (int *) malloc(sizeof(int) * len);
q = (int *) malloc(sizeof(int) * len);
if ((p == NULL) || (q == NULL))
{
errn("travesty: fatal: input too big");
exit(1);
}
initp(); /* here p is pointer array for sorting c, q is temp p */
sort(0,len - 1,0);
rearrange();
zeroq(); /* from now on p and q are start and length from old searches */
if (flagstart)
last = 0;
else
last = ran(len);
if ((numout) && (numout <= ord))
ord = numout - 1; /* stupid but does the trick */
for (m = 0; m <= ord; m++)
putchar(c[last * ord1 + m]);
for (num = ord1; (!numout) || (num < numout); num++)
{
if (!q[last])
{
l = 0; u = len - 1;
while (u > l)
if (cmp(c + last * ord1 + 1,c + (i = (u + l)/2) * ord1,ord) > 0)
l = i + 1;
else
u = i;
p[last] = l;
u = len - 1;
while (u > l)
if (cmp(c + last * ord1 + 1,c + (i = (u + l + 1)/2) * ord1,ord) < 0)
u = i - 1;
else
l = i;
q[last] = u - p[last] + 1;
}
last = p[last] + ran(q[last]);
putchar(c[last * ord1 + ord]);
}
exit(0);
}