#!/bin/sh

# ccformat - convert C code to standard format

# @(#) ccformat.sh 1.3 11/5/89 14:39:29

# how to supress newlines in echo

case `echo -n` in
"") n=-n; c=;;
 *) n=; c='\c';;
esac

# initialize

TMPF=/tmp/ccformat.$$
ERROR=
TROFF=
BCK=
FLAGS="-st -di8 -npsl -bap -bad -bbb -nbc -i4 -d0 -nip -nfc1 -cd41 -c49"

trap 'rm -f .ind.$$ $TMPF; exit 1' 1 2 3 15

# parse command options

while :
do
	case $1 in
	-t) TROFF=-troff;;
	-b) case $# in
	    1) ERROR="-b option requires backup argument"; break;;
	    *) BCK=$2; shift;;
	    esac;;
	-T) case $# in
	    1) ERROR="-T option requires typename argument"; break;;
	    *) FLAGS="$FLAGS -T$2"; shift;;
	    esac;;
	-*) ERROR="invalid option: $1"; break;;
	 *) break;;
	esac
	shift
done

# check for invalid commands

test -z "$ERROR" || {
	echo "$0: $ERROR" 1>&2
	echo "usage: $0 [-b backup] [-t] [-T typename] [file(s)]" 1>&2
	exit 1; }

# format the files

case $# in 
 0) indent $TROFF $FLAGS;;
 *) case "$TROFF" in
-troff) for i in $*
	do
	    indent $TROFF $FLAGS $i
	done;;
     *) for i in $*
	do 
	    echo $n $i... $c 
	    test -z "$BCK" || cp $i $i"$BCK" || { echo backup FAILED; exit 1; } 
	    { # some versions of indent return garbage exit status -- gack!
	    (indent $FLAGS <$i 2>.ind.$$ >$TMPF || test ! -s .ind.$$) >$TMPF &&
	    # try a device full check
	    # echo >>$TMPF && 
	    (
		# ignore interrupts while we overwrite the original file
		trap '' 1 2 3 15; cp $TMPF $i 
	    ) && echo replaced; } || { echo replacement FAILED; exit 1; }
	done;;
    esac;;
esac

rm -f $TMPF .ind.$$

exit

#++
# NAME
#	ccformat 1
# SUMMARY
#	convert C source text to standard format
# PROJECT
#	sdetools
# SYNOPSIS
#	ccformat [-b backup] [-t] [-T typename] [file(s)]
# DESCRIPTION
#	The \fIccformat\fR command adjusts the layout of C program text 
#	such that it approximates the Kernighan and Ritchie coding style.
#
#	If no file names are specified, \fIccformat\fR reads 
#	from standard input and writes the result to standard output. 
#	This is convenient for source formatting from within a text
#	editor program.
#
#	Otherwise, the named files are overwritten with their 
#	formatted equivalent. The \fI-b\fR option (see below) provides 
#	a way to create backup copies of the original files.
#
#	Alternatively, the command can be used as a preprocessor for
#	pretty-printing with the \fInroff\fR or \fItroff\fR commands
#	(see the -t option below). In this case, output is always written 
#	to standard output and no change is made to source files.
#
#	The following options are recognized:
# .TP
# -b backup
#	Requests that a copy of the original files be saved. The backup
#	file name is constructed by appending the specified \fIbackup\fR 
#	string to the original file name. 
#	This option is ignored when the \fI-t\fR
#	option is specifid.
# .TP
# -t
#	Makes the program act as a preprocessor
#	for pretty-printing with \fInroff\fR or \fItroff\fR.
#	For example, in order to produce a pretty-printed
#	version on the line printer, use
#
	ccformat -t file(s) | nroff -mindent | col | lp
# .TP
# -T typename
#	Adds \fItypename\fR to the list of type keywords.
#	Names accumulate: -T can be specified more
#	than once. You need to specify all the
#	typenames that appear in your program that
#	are defined by typedefs - nothing will be
#	harmed if you miss a few, but the program
#	won't be formatted as nicely as it should.
# PROGRAM LAYOUT
# .fi
# .ad
#	The following program layout is produced:
# .TP 
# comments
#	Comments starting in the first column are left untouched.
#	These are often carefully laid out by the programmer.
# .sp
#	Comments that appear in-between statements are lined up with 
#	the surrounding program text, and are adjusted to accomodate 
#	as many words on a line as possible. 
#	However, a blank line in the middle of a comment is respected.
# .sp
#	Trailing comments after declarations begin at column 41 
#	(5 tab stops). 
#	Trailing comments after executable statements start at 
#	column 49 (6 tab stops). 
# .TP
# indentation
#	Statements are indented by multiples of four columns. 
#	There is only one statement per line. A control statement
#	is always placed on a separate line.
# .TP
# braces
#	If an opening brace is preceded by a control statement (\fCif,
#	else, do, for\fR or \fCswitch\fR), it is placed on the same line 
#	as the control statement.
# .sp
#	A closing brace is placed at the same level of indentation as the 
#	program text that precedes the corresponding opening brace.
#	If a closing brace is followed by a control statement (\fCelse\fR
#	or \fCwhile\fR), that control statement is placed on the same line 
#	as the closing brace.
# .sp
#	In practice, brace placement is as
#	exemplified by the books on C by B.W. Kernighan and D.M. Ritchie.
# .TP
# blanks
#	Blanks are placed around assignment and arithmetic operators.
#	Commas in declarations or parameter lists are followed by one blank. 
# .sp
#	In the following cases a 
#	blank line is inserted if it is not already present in the text:
#	1) in front of a block comment, 2) between local declarations and 
#	executable statements 3) after each function body. 
# .TP
# declarations
#	In the output, each variable declaration appears on
#	a separate line.
# COMMANDS
#	indent(1)
# FILES
#	/tmp/ccformat.*	intermediate files
# SEE ALSO
#	indent(1)
# DIAGNOSTICS
#	Indent may complain in case of syntax errors. These show
#	up as comments in the resulting program text.
# BUGS
#	The programs seems to beave even when fed ANSI C or even C++
#	code; this has not been tested thoroughly, however.
#
#	Will produce useless files when fed with anything that is
#	not C program text. This does not imply a judgment about
#	C programs in general.
# AUTHOR(S)
#	W.Z. Venema
#	Eindhoven University of Technology
#	Department of Mathematics and Computer Science
#	Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
# CREATION DATE
#	Fri May  6 14:07:04 MET DST 1988
# STATUS
#	ccformat.sh 1.3 11/5/89 14:39:29 (draft)
#--
