[net.sources] rcsit

mikec@reed.UUCP (Michael Cooper) (06/09/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: Sun Jun  9 12:26:47 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'
June 9, 1985		rcsit.c			Version 1.5

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.

Revisions
---------
Version 1.5 has several bug fixes and enchancements over the
originally posted version 1.0.  

1)  I have added the -r option to run rcs's ci(1) on the list 
	of files.  See the manual for more details.  
	
2)  Fixed rcsit.c so that when you check it in to and out of 
	RCS, the $Header and $Log strings found in the body
	of the file are not expanded to the RCS header and log 
	entries.

3)  Added description of the -c option in the manual.  It seems 
	I mentioned it in the syntax section, but forgot to get 
	a description in the body of the manual!  
	
4)  I also fixed the problem with RCS not using the comment 
	string used in the file (by rcsit) for manuals and 
	alternate styles of programs.  

5)  Fixed bug that caused nroff to put a blank page at the 
	beginning of a manual.  This was caused by the extra 
	blank line after the log message and before the body of 
	the manual.

SCCS
----
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.

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

Bugs
----
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'
# 
# $Header: Makefile,v 1.2 85/05/02 21:37:05 mikec Exp $
# 
# $Log:	Makefile,v $
# Revision 1.2  85/05/02  21:37:05  mikec
# Added the install and cleaned up other dependencies.
# 
# Revision 1.1  85/05/02  14:37:16  mikec
# Initial revision
# 
# 
# 

#
# Makefile for rcsit
#
# 4-29-85
#

BIN=/u/v/mikec/.bin
MAN=/u/v/mikec/usr/man/manl/man1

DEFS=
FLAGS= -O -s

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

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

clean:
	/bin/rm -f rcsit log rcsit.man rcsit.shar

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

all: rcsit man

install: rcsit rcsit.1l
	mv rcsit $(BIN)
	cp rcsit.1l $(MAN)
SHAR_EOF
if test -f 'rcsit.c'
then
	echo shar: over-writing existing file "'rcsit.c'"
fi
cat << \SHAR_EOF > 'rcsit.c'
static char *RCSid = "$Header: rcsit.c,v 1.5 85/06/08 21:30:07 mikec Exp $";

/*
 * $Log:	rcsit.c,v $
 * Revision 1.5  85/06/08  21:30:07  mikec
 * Changed "Standard" message to "Standard C" -- some
 * people get easily confused.
 * 
 * Revision 1.4  85/05/03  18:26:09  mikec
 * Fixed bug that causes nroff to put an extra blank page at the
 * beginning of the manual.  This is due to the blank line 
 * between the log message and the body of the manual.  This
 * also might affect an alternate style, so it was fixed for the
 * whole group.
 * 
 * Revision 1.3  85/05/03  18:08:23  mikec
 * Fixed problem with manual and alternate styles.  It seems that RCS
 * doesn't bother to parse the characters before the keywords, but
 * instead looks at the suffix after the ``.'' in the file name just
 * like rcsit does.  Rcsit now runs ``rcs -cstring filename'' where
 * string is the comment string that is being used (``..'' for manuals
 * or the string specified with the -c option).  See the manual
 * for warnings on this.
 * 
 * Revision 1.2  85/05/02  21:33:46  mikec
 * Fixed several minor bugs and made several enhancements.
 * This includes the addition of the -r option to run ci(1)
 * on the file(s).  Also changed the format of the -c option.
 * Specify the -c option and no string is now allowed so that
 * you may have an empty comment string.  Several other
 * minor bug fixes and superficial changes.  See manual and
 * README for more info.
 * 
 * 
 */

/*
 * 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 "-cstring" 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
#define HEADER	"$Header"		/* So RCS doesn't fill in rcsit.c */
#define LOG	"$Log"			/* with the usual header and log  */

static char 	*rstr, 
		*progname,
		*commentstr, 
		*manstr = ".\\\" ";

int aflag = FALSE;			/* automatically guess file type */
int rflag = FALSE;			/* run rcs (ci) */
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 *str, *file, *format, *cibuf, *rcsbuf;
	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;
			str = (*argv)+2;
			break;
		case 'r':
			rflag = TRUE;
			rstr = (*argv)+2;
			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 < 2)
		usage();

	mktemp(tmpfile);

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

	rcsbuf = alloca(2048);
	cibuf = alloca(2048);

	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 = manstr;
		else
			commentstr = " * ";

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

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

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

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

		addfile(fd, ptmp);

		fclose(fd);
		fclose(ptmp);

		renam(tmpfile, file);

		if(!qflag)
			printf("done\n");
		if(rflag) {
			strcat(cibuf, " ");
			strcat(cibuf, file);
			if(mflag) {
				strcat(rcsbuf, " ");
				strcat(rcsbuf, file);
			}
		}
	}

	if(rflag) {
		if(!qflag)
			printf("Starting RCS (ci)...\n");
		ci(cibuf);
		if(mflag) {
			if(!qflag)
				printf("Starting RCS (rcs)...\n");
			rcs(rcsbuf);
		}
	}

	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 [ -cstr ] [ -roptions ] [ -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 C";
	} 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 if(!cflag){
		fprintf(stderr, "%s: Unknown type of file.\n", progname);
		usage();
	}
	return(msg);
}

/*
 * ci() -- routine to run RCS's ``ci'' on file using the options found in rstr.
 *
 */

ci(file)
char *file;
{
	char *buf;
	char *alloca();

	buf = alloca(128);
	if(rstr != NULL)
		sprintf(buf, "ci %s %s", rstr, file);
	else
		sprintf(buf, "ci %s", file);
	
	system(buf);
}

rcs(files)
char *files;
{
	char *buf;
	char *alloca();

	buf = alloca(128);
	sprintf(buf, "rcs -c'%s' %s", cflag ? commentstr : manstr, files);
	system(buf);
}
SHAR_EOF
if test -f 'rcsit.1l'
then
	echo shar: over-writing existing file "'rcsit.1l'"
fi
cat << \SHAR_EOF > 'rcsit.1l'
... 
... $Header: rcsit.1l,v 1.3 85/05/03 18:28:17 mikec Exp $
... 
... $Log:	rcsit.1l,v $
... Revision 1.3  85/05/03  18:28:17  mikec
... Removed newline at end of log message that caused an extra blank
... page at beginning of manual.
... 
... Revision 1.2  85/05/03  18:12:54  mikec
... Added comments and warnings about fix for initializing comment
... strings in manuals and alternate styles.  Also added
... descriptions of the other new options and changes.
... 
... Revision 1.1  85/05/02  21:39:19  mikec
... Initial revision
... 
... 
.TH RCSIT 1l LOCAL
.SH NAME
rcsit \- Add RCS headers to files
.SH SYNOPSIS
.B rcsit
[
.B \-cstr
]
[
.B \-roptions
]
[
.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 and then (optionally) checking the file(s) into RCS
via 
.ul
ci(1).
.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.
.IP \-cstr
This option causes
.ul
str
to be used as the comment string.
.IP \-roptions
This option causes the file names to be buffered and then passed to RCS 
to be checked in via
.ul
ci(1).  
If the string
.ul
options
is present, it is passed to 
.ul
ci(1)
as the options line.
.PP
Note that the \-s and \-M options basically do the same thing.  That is,
they use the same comment string and format.
.PP
If the file is a manual or the 
.B \-cstr
option is used, 
.ul
rcs(1)
will be invoked on the files to initialize the comment string for the RCS
file.  This is done after
.ul
ci(1)
is invoked.  Note that if you specify a string with the 
.B \-roptions
option that causes 
.ul
ci(1)
to check the file out again immediately, the comment string may not be
correct because
.ul
rcs(1)
was not invoked first.
.SH FILES
/tmp/rcsit*		Temporary files
.SH SEE ALSO
ci(1), make(1), rcs(1), rcsintro(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}-------------+