[net.sources] rcsit -- A semi-intelligent program to add RCS headers to files

mikec@reed.UUCP (Michael Cooper) (05/01/85)

#!/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 the files:
#	README
#	Makefile
#	rcsit.c
#	rcsit.1l
# This archive created: Wed May  1 11:45:30 1985
# By:	Michael Cooper (Tabr Sietch - Portland, Oregon)
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
cat << \SHAR_EOF > 'README'
May 1, 1985		rcsit.c			Version 1.0

This group of files is for rcsit.  It is a program to prepare 
files for RCS by adding the $Header and $Log key words to the
files.  It is a semi-intelligent program in that it tries to 
guess the type of file (and thus the type of comment strings
to use) by looking and the suffix after the last ``.'' of the
file name and the whole file name.  See the manual (included)
for more specifics and the code for specific questions.

For you SCCS folks out there, it should not be to hard to adapt
rcsit.  I don't know to much about SCCS, but what I do know
leads me to believe it would be fairly easier to convert.

This program was written under Ultrix-32 (~4.2bsd) on a VAX 780.
Although, I haven't tried to port it to Sys V, it shouldn't be
to difficult.

If you discover bugs or make enhancements, please send them to me
and I will try to get the fixes out to the world.



					Michael Cooper

______________________________________________________________________________
{decvax, ucbvax, purdue, uw-beaver, masscomp, cbosg, aat, sdcrdcf,
 mit-ems, psu-cs, uoregon, orstcs, ihnp4, uf-cgrl, ssc-vax}!tektronix 
								\
						                 +--!reed!mikec 
{teneron, ogcvax, muddcs, cadic, oresoft, grpwre,     		/
 	  harvard, psu-cs, omen, isonvax, nsc-pdc}-------------+
SHAR_EOF
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
#
# Makefile for rcsit
#
# 4-29-85
#

DEFS=
FLAGS= -O -s

rcsit: rcsit.c
	$(CC) $(FLAGS) $(DEFS) rcsit.c -o rcsit

clean:
	/bin/rm rcsit

man: rcsit.1l
	nroff -man rcsit.1l > rcsit.man

shar: README Makefile rcsit.c rcsit.1l
	shar README Makefile rcsit.c rcsit.1l > rcsit.shar

all: rcsit man
SHAR_EOF
if test -f 'rcsit.c'
then
	echo shar: over-writing existing file "'rcsit.c'"
fi
cat << \SHAR_EOF > 'rcsit.c'
/*
 * rcsit.c - A semi-intelligent program for adding RCS headers to files.
 *
 *		This program will try and put the $Header and $Log RCS
 *		keywords at the beginning of the specified files.
 *
 *		If the user fails to identify the type of files (i.e. with -c, 
 *		-h, -m, -M, -s, etc.), rcsit will attempt to identify each
 *		file by looking at the `.' suffix (or the whole file name
 *		in the case of makefiles) and the trailing character or two.
 *
 *		Rcsit currently knows how to deal with regular C files
 *		(.c), include files (.h), shell scripts (.sh), makefiles
 *		(filename == makefile || filename == Makefile || .mk), and 
 *		manuals (.# --> where # is a digit).  The user may specify
 *		the comment string to use with the "-c string" option, where
 *		"string" is the comment string to use.
 *
 *
 *	Author: 		Michael Cooper
 *				tektronix!reed!mikec
 *
 *	Orignally written: 	April 30, 1985.
 *
 */

#include <stdio.h>
#include <ctype.h>

#define FALSE	0
#define TRUE	1

static char *progname;

int aflag = FALSE;			/* automatically guess file type */
int mflag = FALSE;			/* force manual type */
int Mflag = FALSE;			/* force Makefile type */
int sflag = FALSE;			/* force shell script type */
int iflag = FALSE;			/* force include type */
int cflag = FALSE;			/* use user specified string */
int qflag = FALSE;			/* be quiet about operations */

main(argc, argv)
char *argv[];
{
	char *tmpfile = "/tmp/rcsitXXXXXX";
	char *commentstr, *str, *file, *format;
	char *alloca(), *autoguess();
	FILE *fopen(), *ptmp, *fd;

	progname = argv[0];

	argc--, argv++;
	while (argc > 0 && argv[0][0] == '-') {
		switch(argv[0][1]) {
		case 'c':
			cflag = TRUE;
			argc--, argv++;
			str = *argv;
			break;
		case 'q':
			qflag = TRUE;
			break;
		case 'i':
			iflag = TRUE;
			break;
		case 's':
			sflag = TRUE;
			break;
		case 'm':
			mflag = TRUE;
			break;
		case 'M':
			Mflag = TRUE;
			break;
		default:
			usage();
		}
		argc--, argv++;
	}
	++argc, --argv;

	if(argc < 1)
		usage();

	mktemp(tmpfile);

	if(!sflag && !iflag && !mflag && !Mflag)
		aflag = TRUE;

	while(argc-- > 1) {
		file = *++argv;
		if(!access_ok(file)){
			fprintf(stderr, "%s: No write permission on %s.\n",
				progname, file);
			exit(1);
		}
		if((fd = fopen(file, "r")) == NULL){
			fprintf(stderr,
				"%s: Cannot open %s for reading.\n", 
				progname, file);
			exit(1);
		}
		if((ptmp = fopen(tmpfile, "w")) == NULL) {
			fprintf(stderr, "%s: Cannot open %s for write.\n", 
				progname, tmpfile);
			exit(1);
		}

		if(aflag) 		/* try to guess type of file */ 
			format = autoguess(file);

		if(iflag)
			format = "Include";
		else if(sflag)
			format = "Script";
		else if(Mflag)
			format = "Makefile";
		else if(cflag)
			format = "Alternate";
		else if(mflag)
			format = "Manual";

		if(cflag) {
			commentstr = alloca(128);
			sprintf(commentstr, "%s ", str);
		} else if(sflag || Mflag) 
			commentstr = "# ";
		else if(mflag)
			commentstr = "... ";
		else
			commentstr = " * ";

		if(!qflag)
			printf("Converting %s to %s style format...", 
				file, format);

		if(iflag)
			fprintf(ptmp, 
			"/*\n * $Header: %s,v $\n */\n\n/*\n", file);
		else if(cflag)
			fprintf(ptmp,
			"%s\n%s$Header: %s,v $\n%s\n", 
				commentstr, commentstr, file, commentstr);
		else if(sflag || mflag || Mflag)
			fprintf(ptmp,
			"%s\n%s$Header: %s,v $\n%s\n", 
				commentstr, commentstr, file, commentstr);
		else
			fprintf(ptmp, 
			"static char *RCSid = \"$Header: %s,v $\";\n\n/*\n",
				file);

		fprintf(ptmp, commentstr);
		fprintf(ptmp, "$Log: %s,v $\n", file);
		fprintf(ptmp, "%s\n", commentstr);

		if(cflag || Mflag || sflag || mflag)
			fprintf(ptmp, "%s\n\n", commentstr);
		else
			fprintf(ptmp, " */\n\n");

		addfile(fd, ptmp);

		fclose(fd);
		fclose(ptmp);

		renam(tmpfile, file);

		if(!qflag)
			printf("done\n");
	}
	if(unlink(tmpfile) != 0){
		fprintf(stderr, "%s: error unlinking %s.\n", 
			progname, tmpfile);
		exit(1);
	}
}

/*
 * addfile() -- append contents of "orig to "tofile".
 */

addfile(orig, tofile)
FILE *orig;
FILE *tofile;
{
	char *line;

	line = alloca(1024);
	while(fgets(line, sizeof(line), orig) != NULL)
		fputs(line, tofile);
}

/*
 * renam() -- rename "from" to "to".  Would be a lot easier if we could
 *	      just do a rename(), but you can't do that accross file systems!
 */

renam(from, to)
char *from;
char *to;
{
	FILE *fd, *fdf;
	char *line;

	if((fdf = fopen(from, "r")) == NULL) {
		fprintf(stderr,"%s: error reading %s for rename.\n",
			progname, from);
		exit(1);
	}
	if((fd = fopen(to, "w")) == NULL) {
		fprintf(stderr,"%s: error creating %s for rename.\n", 
			progname, to);
		exit(1);
	}
	line = alloca(1024);
	while(fgets(line, sizeof(line), fdf) != NULL)
		fputs(line, fd);
	fclose(fdf);
	fclose(fd);
	return(0);
}

/*
 * access_ok() -- determine if you have write permission on "file".
 */

access_ok(file)
char *file;
{
	if(access(file, 2) != 0)
		return(-1);
	else
		return(1);
}

/*
 * usage() -- print usage message and then say good-bye.
 */

usage()
{
	fprintf(stderr, "usage: %s [ -c str -m -i -s -M ] file [ file1 file2 ... ]\n", 
		progname);
	exit(1);
}

/*
 * autoguess() -- try to be intelligent and guess the type of file.
 */

char *
autoguess(file)
char *file;
{
	char *str, *str2, *msg;
	char *rindex();

	if((str = rindex(file, '.')) != NULL)
		str++;
	if((str2 = rindex(file, '/')) == NULL)
		str2 = file;
	else
		++str2;
	if(strncmp(str, "h", 1) == 0) {
		iflag = TRUE;
		sflag = FALSE;
		mflag = FALSE;
		Mflag = FALSE;
		msg = "Include";
	} else if(strncmp(str, "c", 1) == 0) {
		iflag = FALSE;
		sflag = FALSE;
		mflag = FALSE;
		Mflag = FALSE;
		msg = "Standard";
	} else if((strncmp(str, "sh", 2) == 0)) {
		sflag = TRUE;
		iflag = FALSE;
		mflag = FALSE;
		Mflag = FALSE;
		msg = "Script";
	} else if((strncmp(str2, "Makefile", 8) == 0) || 
	    (strncmp(str2, "makefile", 8) == 0) ||
	    (strncmp(str, "mk", 2) == 0)) {
		Mflag = TRUE;
		iflag = FALSE;
		sflag = FALSE;
		mflag = FALSE;
		msg = "Makefile";
	} else if(isdigit(str[0])) {
		mflag = TRUE;
		Mflag = FALSE;
		iflag = FALSE;
		sflag = FALSE;
		msg = "Manual";
	} else {
		fprintf(stderr, "%s: Unknown type of file.\n", progname);
		usage();
	}
	return(msg);
}
SHAR_EOF
if test -f 'rcsit.1l'
then
	echo shar: over-writing existing file "'rcsit.1l'"
fi
cat << \SHAR_EOF > 'rcsit.1l'
.TH RCSIT 1l LOCAL
.SH NAME
rcsit \- Add RCS headers to files
.SH SYNOPSIS
.B rcsit
[
.B \-c str
]
[
.B \-isqmM
]
.B file
[
.B file1 file2 ...
]
.SH DESCRIPTION
.I Rcsit
is a semi-intelligent program for adding the $Header
and $Log
keywords to files.
.PP
.I Rcsit
will automatically determine the type of file by looking at the ``.''
suffix of each file name and the whole file name to determine if it is
a file for 
.ul
make(1).
The file being named either ``makefile'' or ``Makefile'' will cause 
.I rcsit
to assume the file is for
.ul
make(1).
.I Rcsit
knows how to prepare shell scripts
.B (.sh), 
.ul
make(1)
files
.B (.mk),
manuals
.B (.#
where ``#''
is a digit), standard C files
.B (.c),
and standard C include files
.B (.h).
This feature can be turned off by specifying which format to use through
one of the following options:
.IP \-i 
Use the 
.ul 
include
style.
.IP \-s
Use the
.ul 1
shell script
style.
.IP \-m 
Use the
.ul 
manual
style.
.IP \-M 
Use the
.ul 
make(1)
file style.
.IP \-q
This option will make 
.I rcsit
quiet about its operations.
.PP
Note that the \-s and \-M options basically do the same thing.  That is,
they use the same comment string and format.
.SH FILES
/tmp/rcsit*		Temporary files
.SH SEE ALSO
rcs(1), rcsintro(1), make(1)
.SH DIAGNOSTICS
Self documenting.
.SH BUGS
Probably infinite.
SHAR_EOF
#	End of shell archive
exit 0
-- 
					Michael Cooper

______________________________________________________________________________
{decvax, ucbvax, purdue, uw-beaver, masscomp, cbosg, aat, sdcrdcf,
 mit-ems, psu-cs, uoregon, orstcs, ihnp4, uf-cgrl, ssc-vax}!tektronix 
								\
						                 +--!reed!mikec 
{teneron, ogcvax, muddcs, cadic, oresoft, grpwre,     		/
 	  harvard, psu-cs, omen, isonvax, nsc-pdc}-------------+