#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/12/1991 18:27 UTC by tmo@leia.cs.hut.fi
# Source directory /usr/users/tmo
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   5597 -rw-r--r-- indenter.c
#
# ============= indenter.c ==============
if test -f 'indenter.c' -a X"$1" != X"-c"; then
	echo 'x - skipping indenter.c (File already exists)'
else
echo 'x - extracting indenter.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'indenter.c' &&
/*
X
XFrom dak@sq.sq.com Fri Jun 15 10:02:48 1990
XFrom: dak@sq.sq.com (David A Keldsen)
Newsgroups: comp.lang.scheme
Subject: Re: SUMMARY--reindentation and pretty-printing for Scheme
Keywords: emacs, vi, read-table, stand-alone
Date: 11 Jun 90 18:17:10 GMT
Distribution: comp
Organization: SoftQuad Inc.
X
And here's the promised stand-alone indenter (in C).
----------------------------------------------------------------------
XFrom:	wri!henry@uunet.uu.net
Received: by WRI.com (3.2/SMI-3.0DEV3)
X	id AA28825; Fri, 8 Jun 90 18:19:25 CDT
Message-Id: <9006082319.AA28825@WRI.com>
Date:	Fri, 8 Jun 90 19:19:24 EDT
To:	dak@sq.com
X
Here is a very simple indenter that I use all the  time.   Note,  it  doesn't
pretty print, just indent.  I find that that is exactly what I want.
X
*/
/*
X * Indent a lisp (scheme) program.
X * The only transformations performed are:
X *	Leading white space is replaced with 4 n spaces where n is the
X *		nesting level.
X *	Open and close square brackets (``['' and ``]'') are paired together
X *		and the latter are replaced with the correct number of close
X *		parens (``)'').
X */
#include <stdio.h>
#include <assert.h>
X
X
X
/*
X * The following definitions make C more amenable to a purist.
X */
#define	bool	char			/* boolean type */
#define	uint	unsigned int		/* short names for unsigned types */
#define	ulong	unsigned long
#define	uchar	unsigned char
#define	ushort	unsigned short int
#define	not	!			/* logical negation operator */
#define	and	&&			/* logical conjunction */
#define	or	||			/* logical disjunction */
#define	TRUE	(0 == 0)
#define	FALSE	(not TRUE)
#define	loop	while (TRUE)		/* loop until break */
#define	EOS	'\0'			/* end-of-string char */
#define	NULL	0			/* invalid pointer */
X
#define	cardof(a)	(sizeof(a) / sizeof(*(a)))
#define	endof(a)	((a) + cardof(a))
#define	bitsof(a)	(sizeof(a) * 8)
X
X
/*
X * Function declarations that should be in stdio.h.
X */
extern char	*malloc(),
X		*realloc();
X
X
#define	ISPACE	4			/* distance to indent for each level */
#define	TAB	8			/* distance between tab stops */
#define	MAXSQ	32			/* maximum nesting of ``['' and ``]'' */
X
X
/*
X * Note, an entry in sqs records the level BEFORE the cooresponding ``[''
X * was seen.
X */
static int	level,			/* current ``('' level */
X		sqs[MAXSQ],		/* stack of un-matched ``['' */
X		*sqtop	= sqs - 1;	/* top of sqs stack */
X
X
extern int	main();
static void	die(),
X		scan(),
X		doline(),
X		docomment(),
X		dostring();
static int	doocto();
static void	uplevel(),
X		downlevel();
static int	skipws();
static void	putws();
X
X
int
main()
{
X	scan();
X	return (0);
}
X
X
static void
die(fmt, arg)
char	*fmt;
int	arg;
{
X	fflush(stdout);
X	fprintf(stderr, fmt, arg);
X	fprintf(stderr, "\n");
X	exit(1);
}
X
X
static void
scan()
{
X	int	ch;
X
X	loop
X		switch (ch = skipws()) {
X		case '\n':
X			putchar('\n');
X			continue;
X		case EOF:
X			if (level != 0)
X				die("%d missing ``)''.", level);
X			return;
X		default:
X			putws(ISPACE * level);
X			doline(ch);
X			putchar('\n');
X		}
}
X
X
static void
doline(ch)
int	ch;
{
X	loop {
X		switch (ch) {
X		case '(':
X			uplevel(ch);
X			break;
X		case ')':
X			downlevel(ch);
X			break;
X		case '[':
X			uplevel(ch);
X			ch = '(';
X			break;
X		case ']':
X			downlevel(ch);
X			ch = ')';
X			break;
X		case ';':
X			docomment(ch);
X			return;
X		case '"':
X			dostring(ch);
X			ch = getchar();
X			continue;
X		case '#':
X			ch = doocto(ch);
X			continue;
X		case '\n':
X		case EOF:
X			return;
X		}
X		putchar(ch);
X		ch = getchar();
X	}
}
X
X
static void
docomment(ch)
int	ch;
{
X	assert(ch == ';');
X	do {
X		putchar(ch);
X		ch = getchar();
X	} while (ch != '\n' && ch != EOF);
}
X
X
static void
dostring(ch)
int	ch;
{
X	static bool	warned	= FALSE;
X
X	assert(ch == '\"');
X	loop {
X		putchar(ch);
X		ch = getchar();
X		switch (ch) {
X		case EOF:
X			putchar('\n');
X			die("Unterminated string");
X		case '\n':
X			if (not warned) {
X				warned = TRUE;
X				fprintf(stderr,
X					"Warning: new-line in string\n");
X			}
X			break;
X		case '"':
X			putchar(ch);
X			return;
X		case '\\':
X			putchar(ch);
X			ch = getchar();
X			if (ch == EOF) {
X				putchar('\n');
X				die("Unterminted string");
X			}
X			break;
X		}
X	}
}
X
X
static int
doocto(ch)
int	ch;
{
X	assert(ch == '#');
X	putchar(ch);
X	ch = getchar();
X	switch (ch) {
X	case '\\':
X		putchar(ch);
X		ch = getchar();
X		if (ch == EOF) {
X			putchar('\n');
X			die("Unterminated character constant");
X		}
X		putchar(ch);
X		return (getchar());
X	default:
X		return (ch);
X	}
}
X
X
static void
uplevel(ch)
int	ch;
{
X	switch (ch) {
X	case '(':
X		++level;
X		break;
X	case '[':
X		if (++sqtop == endof(sqs)) {
X			putchar('\n');
X			die("[ ... ] too deeply nested");
X		}
X		*sqtop = level++;
X		break;
X	default:
X		assert(FALSE);
X	}
}
X
X
static void
downlevel(ch)
int	ch;
{
X	switch (ch) {
X	case ')':
X		--level;
X		if ((sqtop >= sqs)
X		and (level <= *sqtop)) {
X			putchar('\n');
X			die("Unmatched ``[''.");
X		}
X		if (level < 0) {
X			putchar('\n');
X			die("Too many ``)''.");
X		}
X		break;
X	case ']':
X		if (sqtop < sqs) {
X			putchar('\n');
X			die("Too many ``]''.");
X		}
X		assert(*sqtop >= 0);
X		if (--level != *sqtop) {
X			assert(level >= *sqtop);
X			putchar('\n');
X			die("``]'' seen but need %d ``)'' first",
X				level - *sqtop);
X		}
X		--sqtop;
X		break;
X	default:
X		assert(FALSE);
X	}
}
X
X
static int
skipws()
{
X	int	ch;
X
X	loop
X		switch (ch = getchar()) {
X		case ' ':
X		case '\t':
X			break;
X		default:
X			return (ch);
X		}
}
X
X
static void
putws(len)
int	len;
{
X	assert(len >= 0);
X	for (; len >= TAB; len -= TAB)
X		putchar('\t');
X	for (; len != 0; --len)
X		putchar(' ');
}
/*
-- 
// David A. 'Dak' Keldsen:  dak@sq.com or utai[.toronto.edu]!sq!dak
// "I have heard the mermaids singing, each to each."  -- T.S.Eliot
*/
SHAR_EOF
chmod 0644 indenter.c ||
echo 'restore of indenter.c failed'
Wc_c="`wc -c < 'indenter.c'`"
test 5597 -eq "$Wc_c" ||
	echo 'indenter.c: original size 5597, current size' "$Wc_c"
fi
exit 0
