[net.sources] Bizarre program

chris@umcp-cs.UUCP (Chris Torek) (07/09/85)

I don't know what net.bizarre is supposed to be for, but as long
as it's here, I might as well exercise it :-), so here's a truly
bizarre program.  (It actually has some useful code embedded in
it too.)
---------------------------------------------------------------
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Making directory "floop"'
mkdir floop
/bin/echo 'Extracting floop/Makefile'
sed 's/^X//' <<'//go.sysin dd *' >floop/Makefile
#
# Makefile for floop
#
# Copyright (c) 1985 University of Maryland Computer Science Department
# Author: Chris Torek

CFLAGS=	-O
LIBS=	-ltermlib

floop:	floop.o cm.o
	cc -o floop floop.o cm.o $(LIBS)

clean:
	rm -f floop floop.o cm.o

floop.o: cm.h
cm.o: cm.h
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 floop/Makefile
	/bin/echo -n '	'; /bin/ls -ld floop/Makefile
fi
/bin/echo 'Extracting floop/cm.c'
sed 's/^X//' <<'//go.sysin dd *' >floop/cm.c
X/*
 * cm -- Cursor Motion subroutines
 *
 * Copyright (c) 1985 University of Maryland Computer Science Department
 */

#include <stdio.h>
#include <sgtty.h>
#include "cm.h"

#define	BIG	2000

char	*malloc (), *tgoto (), *getenv (), *tgetstr ();

static int cost;		/* sums up costs */

static evalcost (c) char c; {
	cost++;
}

static put (c) char c; {
	putchar (c);
}

X/* NEXT TWO ARE DONE WITH MACROS */
#if 0
X/*
 * Assume the cursor is at row row, column col.  Normally used only after
 * clearing the screen, when the cursor is at (0, 0), but what the heck,
 * let's let the guy put it anywhere.
 */

static
at (row, col) {
	curY = row;
	curX = col;
}

X/*
 * Add n columns to the current cursor position.
 */

static
addcol (n) {
	curX += n;

	/*
	 * If cursor hit edge of screen, what happened?
	 * N.B.: DO NOT!! write past edge of screen.  If you do, you
	 * deserve what you get.  Furthermore, on terminals with
	 * autowrap (but not magicwrap), don't write in the last column
	 * of the last line.
	 */
	if (curX == Wcm.cm_cols) {
		/*
		 * Well, if magicwrap, still there, past the edge of the
		 * screen (!).  If autowrap, on the col 0 of the next line.
		 * Otherwise on last column.
		 */
		if (Wcm.cm_magicwrap)
			;	/* "limbo" */
		else if (Wcm.cm_autowrap) {
			curX = 0;
			curY++;	/* Beware end of screen! */
		}
		else
			curX--;
	}
}
#endif

X/*
 * (Re)Initialize the cost factors, given the output speed of the terminal
 * in the variable ospeed.  (Note: this holds B300, B9600, etc -- ie stuff
 * out of <sgtty.h>.)
 */
static
costinit () {
#define	COST(x)		(x ? (cost = 0, tputs (x, 1, evalcost), cost) : BIG)
	Wcm.cc_up =	COST (Wcm.cm_up);
	Wcm.cc_down =	COST (Wcm.cm_down);
	Wcm.cc_left =	COST (Wcm.cm_left);
	Wcm.cc_right =	COST (Wcm.cm_right);
	Wcm.cc_home =	COST (Wcm.cm_home);
	Wcm.cc_cr =	COST (Wcm.cm_cr);
	Wcm.cc_ll =	COST (Wcm.cm_ll);
	Wcm.cc_tab =	Wcm.cm_tabwidth ? COST (Wcm.cm_tab) : BIG;

	/*
	 * These last three are actually minimum costs.  When (if) they are
	 * candidates for the least-cost motion, the real cost is computed.
	 * (Note that "0" is the assumed to generate the minimum cost.
	 * While this is not necessarily true, I have yet to see a terminal
	 * for which is not; all the terminals that have variable-cost
	 * cursor motion seem to take straight numeric values.  --ACT)
	 */
#undef	COST
#define	COST(x)		(x ? (cost = 0, tputs (tgoto (x, 0, 0), 1, evalcost),\
				cost) : BIG)
	Wcm.cc_abs =	COST (Wcm.cm_abs);
	Wcm.cc_habs =	COST (Wcm.cm_habs);
	Wcm.cc_vabs =	COST (Wcm.cm_vabs);
#undef	COST
}

X/*
 * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
 * up and down, and left and right, motions, and tabs.  If doit is set
 * actually perform the motion.
 */
static
calccost (srcy, srcx, dsty, dstx, doit) {
	register int	deltay, deltax, c, totalcost;
	int		ntabs, n2tabs,
			tabx, tab2x,
			tabcost;
	register char  *p;

	totalcost = 0;
	if ((deltay = dsty - srcy) == 0)
		goto x;
	if (deltay < 0)
		p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay;
	else
		p = Wcm.cm_down, c = Wcm.cc_down;
	if (c == BIG) {		/* caint get thar from here */
		if (doit)
			printf ("OOPS");
		return c;
	}
	totalcost = c * deltay;
	if (doit)
		while (--deltay >= 0)
			tputs (p, 1, put);
x:
	if ((deltax = dstx - srcx) == 0)
		goto done;
	if (deltax < 0) {
		p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;
		goto dodelta;	/* skip all the tab junk */
	}
	/* Tabs (the toughie) */
	if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs)
		goto olddelta;	/* forget it! */

	/*
	 * ntabs is # tabs towards but not past dstx; n2tabs is one more
	 * (ie past dstx), but this is only valid if that is not past the
	 * right edge of the screen.  We can check that at the same time
	 * as we figure out where we would be if we use the tabs (which
	 * we will put into tabx (for ntabs) and tab2x (for n2tabs)).
	 */
	ntabs = deltax / Wcm.cm_tabwidth;
	n2tabs = ntabs + 1;
	tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth;
	tab2x = tabx + Wcm.cm_tabwidth;

	if (tab2x >= Wcm.cm_cols)/* too far (past edge) */
		n2tabs = 0;

	/*
	 * Now set tabcost to the cost for using ntabs, and c to the cost
	 * for using n2tabs, then pick the minimum.
	 */
			/* cost for ntabs     +    cost for right motion */
	tabcost = ntabs ? ntabs * Wcm.cc_tab  + (dstx - tabx) * Wcm.cc_right
			: BIG;

			/* cost for n2tabs    +    cost for left motion */
	c =	 n2tabs ? n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left
			: BIG;

	if (c < tabcost)	/* then cheaper to overshoot & back up */
		ntabs = n2tabs, tabcost = c, tabx = tab2x;

	if (tabcost >= BIG)	/* caint use tabs */
		goto newdelta;

	/*
	 * See if tabcost is less than just moving right
	 */
	if (tabcost < (deltax * Wcm.cc_right)) {
		totalcost += tabcost;/* use the tabs */
		if (doit)
			while (--ntabs >= 0)
				tputs (Wcm.cm_tab, 1, put);
		srcx = tabx;
	}

	/*
	 * Now might as well just recompute the delta.
	 */
newdelta:
	if ((deltax = dstx - srcx) == 0)
		goto done;
olddelta:
	if (deltax > 0)
		p = Wcm.cm_right, c = Wcm.cc_right;
	else
		p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax;

dodelta:
	if (c == BIG) {		/* caint get thar from here */
		if (doit)
			printf ("OOPS");
		return c;
	}
	totalcost += c * deltax;
	if (doit)
		while (--deltax >= 0)
			tputs (p, 1, put);
done:
	return totalcost;
}

#define	USEREL	0
#define	USEHOME	1
#define	USELL	2
#define	USECR	3

static
xgoto (row, col) {
	int homecost, crcost, llcost, relcost, directcost;
	int use;
	char *p, *dcm;

	/* First the degenerate case */
	if (row == curY && col == curX)/* already there */
		return;

	/*
	 * Pick least-cost motions
	 */
	relcost = calccost (curY, curX, row, col, 0);
	use = USEREL;
	if ((homecost = Wcm.cc_home) < BIG)
		homecost += calccost (0, 0, row, col, 0);
	if (homecost < relcost)
		relcost = homecost, use = USEHOME;
	if ((llcost = Wcm.cc_ll) < BIG)
		llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0);
	if (llcost < relcost)
		relcost = llcost, use = USELL;
	if ((crcost = Wcm.cc_cr) < BIG) {
		if (Wcm.cm_autolf)
			if (curY + 1 >= Wcm.cm_rows)
				crcost = BIG;
			else
				crcost += calccost (curY + 1, 0, row, col, 0);
		else
			crcost += calccost (curY, 0, row, col, 0);
	}
	if (crcost < relcost)
		relcost = crcost, use = USECR;
	directcost = Wcm.cc_abs, dcm = Wcm.cm_abs;
	if (row == curY && Wcm.cc_habs < BIG)
		directcost = Wcm.cc_habs, dcm = Wcm.cm_habs;
	else if (col == curX && Wcm.cc_vabs < BIG)
		directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs;

	/*
	 * In the following comparison, the = in <= is because when the costs
	 * are the same, it looks nicer (I think) to move directly there.
	 */
	if (directcost <= relcost) {
		/* compute REAL direct cost */
		cost = 0;
		p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) :
					 tgoto (dcm, col, row);
		tputs (p, 1, evalcost);
		if (cost <= relcost) {	/* really is cheaper */
			tputs (p, 1, put);
			curY = row, curX = col;
			return;
		}
	}
	switch (use) {
	case USEHOME:
		tputs (Wcm.cm_home, 1, put);
		curY = 0, curX = 0;
		break;
	case USELL:
		tputs (Wcm.cm_ll, 1, put);
		curY = Wcm.cm_rows - 1, curX = 0;
		break;
	case USECR:
		tputs (Wcm.cm_cr, 1, put);
		if (Wcm.cm_autolf)
			curY++;
		curX = 0;
		break;
	}
	calccost (curY, curX, row, col, 1);
	curY = row, curX = col;
}

X/*
 * Read the interesting things out of termcap
 * Return 0 if can do CM.
 */
Wcm_init (fill) char **fill; {
	char *p, *term;

	Wcm.cx_put = put;
	Wcm.cx_costinit = costinit;
	Wcm.cx_goto = xgoto;

	if (fill == 0)		/* assume Wcm stuff is already set up */
		goto done;

	/*
	 * If *fill == 0, he has not got the termcap stuff yet, so allocate a
	 * buffer and set *fill.  Otherwise assume he already set everything
	 * up and we merely have to suck in the capabilities.
	 */
	if (*fill == 0) {
		term = getenv ("TERM");
		if (!term)
			return -1;
		/*
		 * Magic constants, yucko!  Termcap should have #defines
		 * for these.
		 */
		p = malloc (2048);
		if (!p)
			return -1;
		if (tgetent (&p[1024], term) <= 0) {
			free (p);
			return -1;
		}
		*fill = p;
	}
	if (tgetflag ("bs"))
		Wcm.cm_left = "\b";
	else
		Wcm.cm_left =	tgetstr ("bc", fill);
	Wcm.cm_up =		tgetstr ("up", fill);
	Wcm.cm_down =		tgetstr ("nl", fill);
	Wcm.cm_right =		tgetstr ("nd", fill);
	Wcm.cm_home =		tgetstr ("ho", fill);
	Wcm.cm_cr =		tgetstr ("cr", fill);
	Wcm.cm_ll =		tgetstr ("ll", fill);
	Wcm.cm_abs =		tgetstr ("cm", fill);
	Wcm.cm_habs =		tgetstr ("ch", fill);
	Wcm.cm_vabs =		tgetstr ("cv", fill);
	Wcm.cm_tab =		tgetstr ("ta", fill);
	Wcm.cm_tabwidth =	tgetnum ("tw");
	if (Wcm.cm_tabwidth < 0)
		Wcm.cm_tabwidth = 8;
	Wcm.cm_cols =		tgetnum ("co");
	Wcm.cm_rows =		tgetnum ("li");
	Wcm.cm_autowrap =	tgetflag ("am");
	Wcm.cm_magicwrap =	tgetflag ("xn");
	Wcm.cm_autolf =		tgetflag ("rn");

#define	DEFAULT(x,y)	if (!x) x = y

	DEFAULT (Wcm.cm_down, "\n");
	DEFAULT (Wcm.cm_cr, "\r");
	DEFAULT (Wcm.cm_tab, "\t");

#undef	DEFAULT

	if (tgetflag ("nc"))
		Wcm.cm_cr = 0;
	if (tgetflag ("nn"))
		Wcm.cm_down = 0;
	if (tgetflag ("xt"))
		Wcm.cm_tab = 0;
	p = tgetstr ("pc", fill);
	if (p)
		PC = *p;

done:
	/* Check that we know the size of the screen.... */
	if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
		return -1;
	/* Require up and left, and, if no absolute, down and right */
	if (!Wcm.cm_up || !Wcm.cm_left)
		return -1;
	if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
		return -1;
	return 0;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 floop/cm.c
	/bin/echo -n '	'; /bin/ls -ld floop/cm.c
fi
/bin/echo 'Extracting floop/cm.h'
sed 's/^X//' <<'//go.sysin dd *' >floop/cm.h
X/* Copyright (c) 1985 University of Maryland Computer Science Department */

X/*
 * This structure holds everything needed to do cursor motion except the pad
 * character (PC) and the output speed of the terminal (ospeed), which
 * termcap wants in global variables.
 */
struct cm {
	/* Cursor position */
	int	cm_curY,	/* current row */
		cm_curX;	/* current column */
	/* Capabilities from termcap(5) (including extensions) */
	char	*cm_up,		/* up (up) */
		*cm_down,	/* down (do) */
		*cm_left,	/* left (bs) */
		*cm_right,	/* right (nd) */
		*cm_home,	/* home (ho) */
		*cm_cr,		/* carriage return (cr) */
		*cm_ll,		/* last line (ll) */
		*cm_abs,	/* absolute (cm) */
		*cm_habs,	/* horizontal absolute (ch) */
		*cm_vabs,	/* vertical absolute (cv) */
		*cm_tab;	/* tab (ta) */
	int	cm_tabwidth,	/* tab width (tw) */
		cm_cols,	/* Number of cols on screen (co) */
		cm_rows,	/* Number of rows on screen (li) */
		cm_autowrap:1,	/* autowrap flag (am) */
		cm_magicwrap:1,	/* vt100s: cursor stays in last col but
				   will wrap if next char is printing (xn) */
		cm_usetabs:1,	/* if set, use tabs */
		cm_autolf:1;	/* \r performs a \r\n (rn) */
	/* Costs */
	int	cc_up,		/* cost for up */
		cc_down,	/* etc */
		cc_left,
		cc_right,
		cc_home,
		cc_cr,
		cc_ll,
		cc_abs,		/* abs costs are actually min costs */
		cc_habs,
		cc_vabs,
		cc_tab;
	/* Functions */
	int	(*cx_costinit) (),/* initialize cost factors */
		(*cx_goto) (),	/* (*cx_goto) (row, col) moves cursor to
				   specified coordinates (0 origin!!) */
		(*cx_put) ();	/* points to putc function (for tputs) */
} Wcm;

char	PC;			/* Pad character */
short	ospeed;			/* Output speed (from sg_ospeed) */

X/* Shorthand */
#ifndef NoCMShortHand
#define	curY		Wcm.cm_curY
#define	curX		Wcm.cm_curX
#define	Up		Wcm.cm_up
#define	Down		Wcm.cm_down
#define	Left		Wcm.cm_left
#define	Right		Wcm.cm_right
#define	Home		Wcm.cm_home
#define	CR		Wcm.cm_cr
#define	LastLine	Wcm.cm_ll
#define	Tab		Wcm.cm_tab
#define	TabWidth	Wcm.cm_tabwidth
#define	AbsPosition	Wcm.cm_abs
#define	ColPosition	Wcm.cm_habs
#define	RowPosition	Wcm.cm_vabs
#define	AutoWrap	Wcm.cm_autowrap
#define	MagicWrap	Wcm.cm_magicwrap
#define	UseTabs		Wcm.cm_usetabs
#define	AutoLF		Wcm.cm_autolf
#define	ScreenRows	Wcm.cm_rows
#define	ScreenCols	Wcm.cm_cols

#define	cmcostinit()	(*Wcm.cx_costinit) ()
#define	cmgoto(row,col)	(*Wcm.cx_goto) (row, col)
#define	cmat(row,col)	(curY = (row), curX = (col))
#define	cmplus(n)	{if ((curX += (n)) >= ScreenCols && !MagicWrap)\
				if (AutoWrap) curX = 0, curY++; else curX--;}
#define	cmputc		Wcm.cx_put
#endif
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 floop/cm.h
	/bin/echo -n '	'; /bin/ls -ld floop/cm.h
fi
/bin/echo 'Extracting floop/floop.c'
sed 's/^X//' <<'//go.sysin dd *' >floop/floop.c
X/* Copyright (c) 1985 Computer Science Department University of Maryland */

X/*
 * floop
 */
#include <stdio.h>
#include <sgtty.h>
#include <signal.h>
#include "cm.h"

struct sgttyb old;
int in_fd;
char *tgetstr(), *malloc ();

intrup () {
	stty (in_fd, &old);
	exit (1);
}

main (argc, argv) char **argv; {
	register int i, j, line, n, c;
	register char *cp;
	register int r;
	char *p = 0, *cl, *ce, **buf2;
	int maxcol = 0, col = 0;
	long time (); /* no see */
	FILE *fp, *popen ();
	struct sgttyb sg2;

	if (gtty (in_fd = 0, &old))
		gtty (in_fd = 1, &old);
	if (Wcm_init (&p) || (cl = tgetstr ("cl", &p)) == 0) {
		fprintf (stderr, "terminal too dumb\n");
		exit (1);
	}
	ce = tgetstr ("ce", &p);
	if (makebuf (&buf2)) {
		fprintf (stderr, "out of memory!\n");
		exit (1);
	}
	fp = in_fd == 0 ? popen ("who", "r") : stdin;
	if (fp == NULL) {
		fprintf (stderr, "popen(\"who\") failed\n");
		exit (1);
	}
	cp = buf2[0];
	line = 0;
	r = ScreenRows - 1;
	while ((i = getc (fp)) != EOF) {
		if (line >= r || col >= ScreenCols)
			continue;
		if (i == '\n') {
			if (col > maxcol)
				maxcol = col;
			if (++line >= r)
				continue;
			cp = buf2[line];
			col = 0;
		}
		else if (i == '\t')
			col = (col & ~7) + 8;
		else
			cp[col++] = i;
	}
	if (col > maxcol)
		maxcol = col;
	if (maxcol > ScreenCols)
		maxcol = ScreenCols;
	if (fp != stdin)
		pclose (fp);
	ospeed = old.sg_ospeed;
	if ((old.sg_flags & TBDELAY) == TAB0)
		UseTabs = 1;
	sg2 = old;
	sg2.sg_flags &= ~CRMOD;
	signal (SIGINT, intrup);
	stty (in_fd, &sg2);
	cmcostinit ();
	tputs (cl, 1, cmputc);
	cmat (0, 0);
	srand (time ((long *) 0));
#define rnd() (rand()>>16)
	n = 3 * maxcol * line;
	while (--n >= 0) {
		i = rnd () % line;
		j = rnd () % maxcol;
		c = buf2[i][j];
		if (c == ' ' || c == 0)
			continue;
		cmgoto (i, j);
		putchar (c);
		buf2[i][j] = ' ';
		cmplus (1);
	}
	for (i = 0; i < line; i++) {
		for (j = 0; j < maxcol; j++) {
			c = buf2[i][j];
			if (c && c != ' ') {
				cmgoto (i, j);
				putchar (c);
				cmplus (1);
			}
		}
	}
	cmgoto (Wcm.cm_rows - 1, 0);
	if (ce)
		tputs (ce, 1, cmputc);
	stty (in_fd, &old);
	exit (0);
}

makebuf (bp) char ***bp; {
	register char **l, *s;
	register int i = ScreenRows - 1;

	if ((l = (char **) malloc ((unsigned) i * sizeof (char *))) == 0)
		return -1;
	*bp = l;
	while (--i >= 0) {
		if ((*l = malloc ((unsigned) ScreenCols)) == 0)
			return -1;
		bzero (*l++, (unsigned) ScreenCols);
	}
	return 0;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 floop/floop.c
	/bin/echo -n '	'; /bin/ls -ld floop/floop.c
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 floop
	/bin/echo -n '	'; /bin/ls -ld floop
fi
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland