[net.sources] yacpps - another C pre-processor simulator

simon@its63b.ed.ac.uk (ECSC68 S Brown CS) (10/07/86)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	yacpps.1
#	yacpps
# This archive created: Tue Oct  7 16:56:10 1986
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'yacpps.1'
then
	echo shar: "will not over-write existing file 'yacpps.1'"
else
cat << \SHAR_EOF > 'yacpps.1'

.TH YACPPS 1 "Edinburgh Univ, June 6 1986"
.SH NAME
yacpps - yet another C pre-processor simulator
.SH SYNOPSIS
.B yacpps [-i] [-Dlabel] ... [-Ulabel] ... [source]
.SH DESCRIPTION
.I Yacpps
simulates the C pre-processor in its action of
removing dependant code between
.I #ifdef/#ifndef
and
.I #endif
pairs.
Each pre-processor label it encounters is given one of the
values
.I Defined, Undefined or Unknown.
.PP
A
.I #ifdef
directive will be
.TP
.B 1.
Left complete, with the
.I #ifdef-#endif
labels removed, if the variable is
.I Defined.
.TP 
.B 2.
Removed entirely, with its #ifdef-#endif labels,
if it is
.I Undefined.
.TP
.B 3
Left alone, if it is
.I Unknown.
.PP
A
.I #ifndef
directive will be similar, with reversed effects
for
.I Defined
and 
.I Undefined
variables.
.PP
A
.I #if
directive is always treated as though its parameter were
.I unknown.
.PP
Options understood are
.TP
.B -i
This causes `implicit'
definition of variables;
if a
.I #define
of a previously
.I unknown
variable
occurs
in the scope of an
.I undefined
.I #ifdef
or
.I #ifndef,
or in comments within a
.I defined
.I #ifdef
or
.I #ifndef,
then it is set as being
.I undefined.
.br
This causes lots of junk to be removed, though its
safety is not totally guarenteed.
.TP
.B -Dlabel
This sets the variable
.I label
to be
.I defined.
.TP
.B -Ulabel
This sets the variable named to be
.I undefined.
.PP
If no source file is given on the command line,
then the standard input file is used instead.
.SH "STATUS RETURNS"
Return status is non-zero if anything went wrong,
otherwise 0.
.SH "SEE ALSO"
cpp(1).
.SH BUGS
It doesn't understand comments very well.
.br
Any Control-G's in the input are converted into
newlines on output.
.br
It fails to remove
.I unknown
#ifdef/#endif pairs with null bodies.
.br
It is implemented as a shell-script.
.SH AUTHOR
Simon Brown
SHAR_EOF
if test 1839 -ne "`wc -c < 'yacpps.1'`"
then
	echo shar: "error transmitting 'yacpps.1'" '(should have been 1839 characters)'
fi
fi
if test -f 'yacpps'
then
	echo shar: "will not over-write existing file 'yacpps'"
else
cat << \SHAR_EOF > 'yacpps'
#!/bin/sh
# yacpps: yet another C pre-processor simulator
#
#	Usage: yacpps [-i] [-D label] ... [-U label] ... [source]
#
#	where options are:
#		-i:	Implicit #define's.
#			  1. If a #define of an unknown label occurs in
#			     a comment, then it is set as being undefined.
#			  2. If a #define of an unknown label occurs in
#			     the scope of an undefined #ifdef, then it is
#			     set as being undefined.
#		-D label: Defines the label.
#		-U label: Undefines the label.
#
#	All labels which are not Defined or Undefined are treated as
#	unknown, and may appear under #ifdef and #unifdef scopes in the
#	output.
#
#	The labels "pdp11" and "vax" are treated specially, in that
#	their definition-states are computed automatically.
#
#	When removing #ifdefs from code which was written for many
#	different systems, it is necessary to explicitly Define the
#	system you are using and to Undefine all other possibilities.
#	For example,
#	    yacpps -D sysV -U BSD -U V7 -U sysIII -U ultrix -U eunice
#	Failure to do it like this will cause lots of dependant code
#	to be left in, which should have been removed.
#
#
# -----------------------------------------------------------------------
#
#		Author: Simon Brown
#			Department of Computer Science,
#			University of Edinburgh. 
#		Date:	Monday October 6th, 1986
#		
#	Written on the ERCC/ITS GEC-63/40 "its63b" for the SysV shell.
#	Not guarenteed to work under BSD (but it probably will).
#
#	THIS SOFTWARE MAY BE DISTRIBUTED TO ANYONE SO LONG AS THESE
#	LINES REMAIN UNDISTURBED.
#
#	Please mail any bugs to simon@its63b.ed.ac.uk
#
#		
# -----------------------------------------------------------------------
#
# KNOWN BUGS: 1. It doesn't understand comments properly.
#	      2. Any Control-G's in the input are converted into
#		 newlines.
#	      3. Sometimes it leaves pairs of #ifdef/#endif lines
#		 with no dependant lines between - it would be tidier
#		 if it just deleted the whole lot.
#			
# -----------------------------------------------------------------------
#

machines="pdp11 vax"	# add whatever you are using, too
implicit=false

set -- `getopt D:U:i $*`
if [ $? != 0 ]
then	echo "Usage: $0 [-i] [-Dlabel] ... [-Ulabel] ... [source]" 1>&2
	exit 1
fi
while [ $# -ge 1 ]
do
	case $1 in
	    -i)	implicit=true
		shift ;;
	    -D) eval _$2=true
		shift; shift ;;
	    -U) eval _$2=false
		shift; shift ;;
	    --) shift; break ;;
	     *) echo "wow.... a getopt error! ($1)" 1>&2;
		exit 1
	esac
done
if [ $# -ge 1 ]
then exec < $1
fi

#fast shell functions... (delete these if you don't have the System-V shell)
true(){ return 0; }
false(){ return 1; } 

def=true
state=true
for engine in $machines
do
	if $engine > /dev/null 2>&1
	then eval _$engine=true
	else eval _$engine=false
	fi
done

tr '\\' '\007'  |  while IFS= read line 
do
	IFS=" 	"
	case $line in
	    \#define*)
			set $line
			var=$2
			case $var in
			    *\(* ) normal=false ;;
			    *    ) normal=true
			esac
			case $state in
			    true) 
				  if $normal
				  then eval _$var=true
				  fi
				  echo "$line" ;;
			    neither)
				  if $normal
				  then eval : \${_$var:=neither};
				  fi
				  echo "$line" ;;
			    false)
				  if $implicit && $normal
				  then eval _$var=false
				  fi 
			esac
			;;
	    \#undef*)
			set $line
			var=$2
			case $state in
			    true) 
				  eval _$var=false
				  echo "$line" ;;
			    neither)
				  eval : \${_$var:=neither}
				  echo "$line" ;;
			esac 
			;;
	    /\*#define*)
			if $implicit
			then
				IFS=" 	/*"
				set $line
				var=$2
				case $state in
				    true)
					  eval _$var=false
					  echo "$line" ;;
				    neither)
					  eval : \${_$var:=neither}
					  echo "$line"
				esac 
				IFS=" 	"
			else	case $state in
			   	    true|neither)
					  echo "$line"
			     	esac
			fi
			;;
	    \#ifdef*)
			set $line
			var=$2
			case $state in
			    false) : ;;
			    neither) eval state=\${_$var:-neither}
				     case $state in
					true) state=neither 
				     esac ;;
			     * )     eval state=\${_$var:-neither}
			esac
			case $state in
			    true) def="true $def" ;;
			    false)def="false $def" ;;
			     *)   def="neither $def"
				  echo "$line"
			esac
			;;
	    \#ifndef*)
			set $line
			var=$2
			case $state in
			    false)   state=true ;;
			    neither) eval state=\${_$var:-neither}
				     case $state in
					true) state=neither ;;
					false) state=true
				     esac ;;
			      * )    eval state=\${_$var:-neither}
			esac
			case $state in
			    true) def="false $def"
				  state=false ;;
			    false)def="true $def"
				  state=true ;;
			     * )  def="neither $def"
				  echo "$line" 
			esac
			;;
	    \#else*)
			set $def
			state=$1
			shift
			case $state in
			    true) def="false $*"
				  state=false ;;
			    false)def="true $*" 
				  state=true ;;
			      *)  def="neither $*"
				  echo "$line"
			esac
			;;
	    \#endif*)
			case $state in
			    neither) echo "$line"
			esac
			set $def
			shift
			state=$1
			def=$*
			;;
	    \#if*)
			def="neither $def"
			state=neither
			echo "$line"
			;;
	        *)
			case $state in
			    true|neither)
					echo "$line"
			esac
	esac
done  | tr '\007' '\\'
				  

SHAR_EOF
if test 5200 -ne "`wc -c < 'yacpps'`"
then
	echo shar: "error transmitting 'yacpps'" '(should have been 5200 characters)'
fi
chmod +x 'yacpps'
fi
exit 0
#	End of shell archive