[comp.sources.misc] v06i073: fdecs - generate pANS prototypes from K&R C code

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (03/22/89)

Posting-number: Volume 6, Issue 73
Submitted-by: mnc@m10ux.UUCP (52171.3-Michael Condict-- MHx5911 (MH0000)M999)
Archive-name: fdecs

[My, there's a lot of this kind of thing floating around recently.  ++bsa]

This shell script (fdecs) extracts ANSI-C function prototype declarations,
suitable for use in a .h file, from C source files that contain old-style
function definitions.  See the comment at the top of fdecs for more info.

The only option is "-Idir", which causes the C source to be run through the
C preprocessor before the prototype extraction is done.

Mike Condict

---------------------------- cut here --------------------------------------
#!/bin/sh
# This is a shar archive.
# The rest of this file is a shell script which will extract:
#
# fdecs fdecs1.sed fdecs2.sed fdecs3.sed
#
# To extract the files from this shell archive file simply
# create a directory for this file, move the archive file
# to it and enter the command
#
#	sh filename
# 
# The files will be extracted automatically.
# Note: Do not use csh.
#
# Archive created: Tue Mar 14 10:29:50 EST 1989
#
echo x - fdecs
sed 's/^X//' > fdecs << '@FUNKY STUFF@'

# This script, given C source files, finds all the function definitions
# of the form "type_decl f(a,b,...) type_decl a; type_decl b; ... { body }",
# and outputs a file of extern function declarations suitable for a .h file.
# There need not be a type_decl for each argument (defaults to int) and the
# type_decl's can be in a different order from the arg list.  Multiple args
# can be declared in the standard abbreviated fashion: "int a, *b;".
#
# The only restriction is that the type_decl's must be no more complicated
# than what can be formed with type words, names, "*" and "[]".  That is the
# type_decl's may not contain "struct ... {...}" or "float (*x)()" although,
# e.g., "struct A" is allowed.
#
# The output is one line of the form 
#
#	type_decl f(type_decl a, type_decl b, . . . );
#
# for each function f defined in the source files, i.e. a legal ANSI-C
# function prototype.

SEDDIR=~mnc/src/fdecs

Iflag=""
while [ "$#" -gt 0 ]; do
	case "$1" in
	-I*)	Iflag="$Iflag $1"; shift
		;;
	-*)	echo "Usage: $0 [ -Iincl_dir ] ... file ..."
		echo "       (use -I only if C preprocessor is wanted)"
		exit 1
		;;
	*)	break ;;
	esac
done

if [ "$#" -eq 0 ] ; then
	sed -f $SEDDIR/fdecs1.sed |
	sed -f $SEDDIR/fdecs2.sed | sed -f $SEDDIR/fdecs3.sed
elif [ "X$Iflag" != X ] ; then
	# User wants to run the C files through the preprocessor, with
	# the specified -I flag.  We delete the contents of the
	# .h files from the preprocessor's output.  We also need to
	# delete any occurrences of '^$filename:', which some versions
	# of cc -E put out at the beginning of every file:
	cc -E $Iflag "$@" | \
		sed -e '#n No automatic printing

			# Delete contents of included .h files:
			: chkhdr
			/^# [1-9][0-9]* ".*\.h"/{
				: delhdr
					n
				/^#/!b delhdr
				b chkhdr
			}
			# Delete "filename:" inserted by "cc -E":
			/^[^ 	]*\.[ch]:[ 	]*$/d
			' \
		    -f $SEDDIR/fdecs1.sed \
		    -e 'p' |
		sed -f $SEDDIR/fdecs2.sed | sed -f $SEDDIR/fdecs3.sed
else
	sed -f $SEDDIR/fdecs1.sed "$@" |
		sed -f $SEDDIR/fdecs2.sed | sed -f $SEDDIR/fdecs3.sed
fi
@FUNKY STUFF@
ls -l fdecs
echo x - fdecs1.sed
sed 's/^X//' > fdecs1.sed << '@FUNKY STUFF@'

: morebs
/\\$/ {
	N
	s/\\\n//
	b morebs
}

/^[ 	]*$/d

: delcom
/\/\*/{
	s/@/ /g
	s:/\*:@:

	: morecm
	/\*\//!{
		s/@.*/@/
		N
		b morecm
	}

	s/\$/ /g

	s:\*/:$:
	s/@[^$]*\$/ /

	b delcom
}

/^#/d

s/\\"/ /g
s/"[^"]*"/0/g
s/\\'/ /g
s/'[^']*'/0/g

/^[ 	]*$/d
@FUNKY STUFF@
ls -l fdecs1.sed
echo x - fdecs2.sed
sed 's/^X//' > fdecs2.sed << '@FUNKY STUFF@'
: delcbrc
/{/{
	s/{[^{}]*/{/g
	: getcbrc
	/}/!{
		N
		s/{[^{}]*/{/g
		b getcbrc
	}
	s/{[^{}]*}/#/g
	b delcbrc
}
s/#/{}/g
@FUNKY STUFF@
ls -l fdecs2.sed
echo x - fdecs3.sed
sed 's/^X//' > fdecs3.sed << '@FUNKY STUFF@'


: doline


: getsbr
/[;{]/!{
	N
	b getsbr
}

s/\n/ /g
s/[ 	][ 	]*/ /g


/;/{
	/^[^;]*) *[a-zA-Z_{]/!{
		s/^[^;]*;//
		/^ *$/d
		b doline
	}
}


/[;)] *{}/!{
	N
	b doline
}

s/^  *//
s/( */(/g
s/ *)/)/g
s/ *, */, /g
s/ *; */; /g
s/ *\*/ \*/g
s/\*  */\*/g



/() *{/b no_arg
	s/, /, %/g
	s/(/(, %/

	t more_t
	: more_t
		s/, %\([A-Za-z_][A-Za-z0-9_]*\)\(.*[);] *\)\([A-Za-z_][A-Za-z0-9_{} ]*\)\( *\)\(\**\1[][]*\)\([,;]\)/, \3 \5\2\3\4@\6/
		s/, %\([A-Za-z_][A-Za-z0-9_]*\)\(.*[);] *\)\([A-Za-z_][A-Za-z0-9_{} ]*\)\( [^;]*, %\)\(\**\1[][]*\)\([,;]\)/, \3 \5\2\3\4@\6/
	t more_t
	
	s/(, /(/
	
	s/%/int /g

	s?(\([^)]*\)).*?(\1);?

	/ register/{
		s/\([A-Za-z_0-9]\) register\([^A-Za-z0-9_]\)/\1\2/g
		s/ register\([^A-Za-z0-9_][^A-Za-z0-9_]*[A-Za-z_][A-Za-z0-9_]*\),/ int\1,/g
		s/ register\([^A-Za-z0-9_]\)/ \1/g
	}

	s/   */ /g

	b done_a
: no_arg
	s/).*/void);/
: done_a
@FUNKY STUFF@
ls -l fdecs3.sed
# The following exit is to ensure that extra garbage 
# after the end of the shar file will be ignored.
exit 0