Relay-Version: version B 2.10.3 beta 11/15/85; site seismo.CSS.GOV Posting-Version: version B 2.10.2 9/3/84; site panda.UUCP Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: rcsit - A program to prepare files for RCS Message-ID: <1197@panda.UUCP> Date: 15 Dec 85 14:13:37 GMT Sender: jpn@panda.UUCP Lines: 962 Approved: jpn@panda.UUCP Mod.sources: Volume 3, Issue 61 Submitted by: seismo!riacs!hplabs!sdcrdcf!uscvax!oberon!mcooper Appended you'll find a shar archive of a program I wrote called rcsit(1l). I posted this program over a year ago to net.sources. After changing sites, though, I lost a copy of it and had to totally re-write it. The new program is designed much better than the old one and seems to be much more flexible having more options. The program itself, does things like add rcs headers (for log tracking, version tracking, etc.) and (optionally) run rcs commands (like ci(1)) on the specified files. Please mail me any bugs/comments that you run across. Thanks, Mike Cooper +-----------------------------------------------------------------------------+ | Michael Cooper UUCP: ...!{uscvax, sdcrdcf, engvax, | | University Computing Services scgvaxd, smeagol}!oberon!mcooper | | University of Southern Cal. BITNET: mcooper@uscvaxq, mcooper@jaxom | | Los Angeles, Ca. 90089-0251 ARPA: mcooper@usc-oberon.arpa, | | (213) 743-3462 mcooper@usc-eclc.arpa | +-----------------------------------------------------------------------------+ #!/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: # rcsit.1 # Makefile # rcsit.c # _.template.c # This archive created: Tue Dec 10 13:54:54 1985 # By: Michael Cooper (University Computing Services, U.S.C.) export PATH; PATH=/bin:$PATH if test -f 'rcsit.1' then echo shar: over-writing existing file "'rcsit.1'" fi cat << \SHAR_EOF > 'rcsit.1' ... ... $Header: rcsit.1,v 1.7 85/11/26 16:57:21 mcooper Exp $ ... ... $Log: rcsit.1,v $ ... Revision 1.7 85/11/26 16:57:21 mcooper ... Noted changes to the -t option. ... ... Revision 1.6 85/11/11 21:20:17 mcooper ... Added AUTHOR. ... ... Revision 1.5 85/11/11 20:13:39 mcooper ... Added description of new Fortran recognition. ... ... Revision 1.4 85/10/27 19:18:15 mcooper ... Cleaned up table display. ... ... Revision 1.3 85/10/27 14:55:22 mcooper ... Added description of new template feature. ... ... Revision 1.2 85/09/28 14:22:52 mcooper ... Documented new features of checkdir (symbolic ... linking and RCSDIR). ... ... Revision 1.1 85/09/19 15:44:22 mcooper ... Initial revision ... ... .TH RCSIT 1l .SH NAME rcsit \- A program to prepare files for RCS .SH SYNOPSIS rcsit [ .B \-chfsmM ] [ .B \-qad ] [ \-I\fIflags\fR ] [ \-R\fIflags\fR ] [ \-t\fIdirectory\fR ] .B file [ .B file1, file2, ... ] .SH DESCRIPTION .I Rcsit is a semi-intelligent program to prepare files for .I rcs(1). This involves putting the correct type of headings at the top of the file so that .I rcs(1) will update a header and log changes in the file. .PP By default, .I rcsit will use default headers ``hard-wired'' into itself for each different file type that it ``knows'' about. (See below for list of known file types). .PP If the \-t\fIdirectory\fR option is specified, then .I rcsit will use ``.template.suffix'' files (where ``suffix'' is a suffix that .I rcsit ``knows'' about) found in .I directory. If a directory name is not specified on the command line, then the environment variable TEMPLATES is used. If $TEMPLATES is not set, then the environment varialble, HOME is tried. .LP The following template files are recognized: .sp 2 .in 10 .nf Template Name File Type ------------------------------------------- .template.c Standard C .template.h C Include .template.f Fortran .template.sh Shell Script .template.make Makefile .template.man Manual .sp 2 .in -10 .fi .PP .I Rcsit is ``semi-intelligent'' in that it can guess the type of headers to put in the file by the type of file (C program, C include, makefile, shell script, or manual). It determines the file type by looking at the name of the file. If the name of the file is ``Makefile'' or ``makefile'', then the file type is taken to be for .I make(1). The suffix after the last ``.'' in the file name is then used. The following table shows the suffixes that .I rcsit knows about: .nf .sp 2 .in 10 Suffix File Type ---------------------------------------- c C Program h C Include f Fortran mk \fIMake(1)\fR file sh Shell Script csh Shell Script [1-9] Manual (digits 1 - 9) .fi .PP If the environement variable ``RCSDIR'' is present, then .I rcsit will attempt to make a symbolic link from it to ``RCS'' in the current directory if the \-\fII\fR option is used and there is no directory called ``RCS'' already, in the current directory. If the \-\fII\fR option is used and ``RCSDIR'' is not specified in the environment, then a normal directory called ``RCS'' will be created. This feature can be overrided with the \-\fId\fR option. .SH OPTIONS .TP 10 .B "c" Force file type to be ``Standard C''. .TP 10 .B "h" Force file type to be ``C Include''. .TP 10 .B "f" Force file type to be ``Fortran''. .TP 10 .B "M" Force file type to be ``Manual''. Note: If you also specify the ``I\fIflags\fR'' option, .I rcsit will run .I rcs(1) to tell rcs what kind of comment string to use for the manual file. .TP 10 .B "s" Force file type to be ``Shell Script''. .TP 10 .B "m" Force file type to be ``Makefile''. Note that this does the same thing as the -s option does. It just prints a different message. .TP 10 .B "t" Do not use any Template files for the headers. .TP 10 .B "q" Be quiet. Don't print out what is going on. Only error messages are printed. .TP 10 .B "d" Do not attempt to make the directory ``RCS''. See above for more info. .TP 10 .B "a" Turn off auto guessing of file type. .TP 10 .B "I\fIflags\fR" Check In file. Run RCS's .I ci(1) on the file with ``flags'' being passed onto .I ci(1) as the command line arguments. .TP 10 .B "R\fIflags\fR" Run .I rcs(1) with ``flags'' as the command line arguments. .SH FILES /tmp/rcsit* - temporary buffer .br ~/.template.* - template files to use as the header. .br .SH AUTHOR Michael Cooper (mcooper@usc-oberon.ARPA) .SH SEE ALSO ci(1), make(1), rcs(1) .SH DIAGNOSTICS Complains about the usual stuff. (i.e. - the specified file doesn't exist, or it can't read it...just things like that.) .SH BUGS Acts oddly in the presence of beautiful women. SHAR_EOF if test -f 'Makefile' then echo shar: over-writing existing file "'Makefile'" fi cat << \SHAR_EOF > 'Makefile' # # $Header: Makefile,v 1.1 85/09/19 13:24:27 mcooper Exp $ # # $Log: Makefile,v $ # Revision 1.1 85/09/19 13:24:27 mcooper # Initial revision # # # # Makefile for rcsit.c # BIN = /u/mcooper/bin MAN = /u/mcooper/usr/man/manl/man1 rcsit: rcsit.c cc -O -s -o rcsit rcsit.c dbx: rcsit.c cc -g rcsit.c debug: rcsit.c cc -g -DDEBUG rcsit.c man: rcsit.1 nroff -man rcsit.1 > rcsit.man install: rcsit rcsit.1 mv rcsit $(BIN) cp rcsit.1 $(MAN) SHAR_EOF if test -f 'rcsit.c' then echo shar: over-writing existing file "'rcsit.c'" fi cat << \SHAR_EOF > 'rcsit.c' /* * $Header: rcsit.c,v 1.18 85/11/26 17:03:32 mcooper Exp $ *--------------------------------------------------------- * $Source: /u/mcooper/src/rcsit/RCS/rcsit.c,v $ * $Revision: 1.18 $ * $Date: 85/11/26 17:03:32 $ * $State: Exp $ * $Author: mcooper $ * $Locker: mcooper $ *--------------------------------------------------------- * Michael Cooper (mcooper@usc-oberon.arpa) * University of Southern California, * University Computing Services, * Los Angeles, California, 90089-0251 * (213) 743-3469 *--------------------------------------------------------- * * $Log: rcsit.c,v $ * Revision 1.18 85/11/26 17:03:32 mcooper * Change message telling of what header was added. * * Revision 1.17 85/11/26 16:40:55 mcooper * Changed the default -t option to FALSE. * Added specifying directory to look for .template.* * files in via -tdirectory. * * Revision 1.16 85/11/11 21:35:34 mcooper * Added call to access() to see if the file * could be read. * * Revision 1.15 85/11/11 21:22:33 mcooper * Changed comment char for fortran files * from "*" to "c". This is what RCS uses. * * Revision 1.14 85/11/11 20:08:43 mcooper * Added descriptions for fortran (.f) files. * * Revision 1.13 85/11/11 19:52:17 mcooper * Modified default header templates to not bother specifying * the RCS file name of the file. co(1) worries about it. * * Revision 1.12 85/10/27 19:10:07 mcooper * Fixed bug that would not use template files if a file * type was forced with -c, -h, etc. * * Revision 1.11 85/10/27 18:48:27 mcooper * Extended template file. You can now have template * files describing all the types of files that * rcsit "knows" about. The file $HOME/.template.* * (where ``*'' is a ``.'' suffix rcsit can guess at or * the type of file that is specified with an override) * is checked for existance. If not present, the default * header (built into rcsit) will be used. * * Revision 1.10 85/10/27 16:15:53 mcooper * Added printing of what rcsit is doing if tflag is * true. Also added new headers. * * Revision 1.9 85/10/27 14:47:39 mcooper * Added new template feature. If the file * .template exists in the users HOME directory, * then that file is used as the header file instead * of the defaults for each type of file. This can * be disabled with the -t option in case the file * is say a shell script. With the template feature * turned off, the auto guessing is re-inabled. * Also, rcsit now removes its temporary files. * * Revision 1.8 85/09/28 14:11:45 mcooper * Added feature: if the environment variable RCSDIR is * present, rcsit will attempt to make a symbolic * link to the directory when the -I flag is used. * This is done only when -I is specified AND the * directory RCS is not present. You may disable this * feature with the -d option. Note also that if RCSDIR * is not in the environment and the above conditions * are true, that a normal directory called RCS will * be created. * * Revision 1.7 85/09/19 15:59:53 mcooper * Kludge part 2 -- If you specify a ci -l of a * man file, then the header is messed up. * Fix: After initializing the comment string, * unlink the file and then run co -l. * * Revision 1.6 85/09/19 15:39:57 mcooper * Now knows about ``Manual'' type files. * * Revision 1.5 85/09/19 14:23:24 mcooper * Added lineprint() function to print things out * nicely. Fixed bug for Manual type files. Due * to the fact that RCS does not not the suffixes of * manuals, it therefor does not know what kind of * comment string to use. Thus, I kludge by running * a ``rcs -c`... ' file'' to tell rcs the comment * string. * * Revision 1.4 85/09/19 13:28:22 mcooper * Fixed bug in auto_guess. Would not continue through function * when file type was ``Makefile''. * * Revision 1.3 85/09/19 13:19:50 mcooper * Added ``Shell Script'' file type. * * Revision 1.2 85/09/19 10:08:36 mcooper * Added code to run RCS commands (rcs & ci) on files. * Fixed bug that limited number of command line files specified to * nine. Several other minor fixes and improvements. * * Revision 1.1 85/09/17 11:33:33 mcooper * Initial revision * */ /* * rcsit -- Prepare files for RCS. rcsit puts the correct headings * at the top of files to prepare them for RCS headings * and log tracking. * * Michael Cooper (mcooper@usc-oberon.arpa) * University Computing Services, USC * * 9-16-85 */ #include #include #include #ifdef NULL #undef NULL #endif #define NULL '\0' #define LENGTH 132 /* length of line */ #define TRUE 1 #define FALSE 0 #ifdef DEBUG int debugon = TRUE; #else int debugon = FALSE; #endif static char *progname; /* program name */ static char *rcsdir; /* * Messages to be printed for the user. */ static char *msg_name; static char *m_stdc = "Standard C", *m_include = "C Include", *m_fortran = "Fortran", *m_pascal = "Pascal", *m_make = "Makefile", *m_shell = "Shell Script", *m_manual = "Manual"; /* * The headers to put at the beginning of the file(s). * Notice that the words Header and Log do not appear here * because RCS will put in the keyword substitutions when rcsit.c * is co'ed. */ static char *header; static char *h_stdc = "static char *RCSid = \"$%s$\";\n\n/*\n * $%s$\n */\n\n"; static char *h_include = "/*\n * $%s$\n *\n * $%s$\n */\n\n"; static char *h_make = "#\n# $%s$\n#\n# $%s$\n#\n"; static char *h_manual = "...\n... $%s$\n... \n... $%s$\n...\n"; static char *h_fortran = "c\nc $%s$\nc\nc $%s$\nc\n"; /* * Template file names */ static char *template_c = ".template.c"; /* .c template */ static char *template_h = ".template.h"; /* .h template */ static char *template_f = ".template.f"; /* .f template */ static char *template_p = ".template.p"; /* .p template */ static char *template_man = ".template.man"; /* man template */ static char *template_make = ".template.make"; /* make template */ static char *template_sh = ".template.sh"; /* sh script template */ static char *tpath; /* path to template */ static char tfile[BUFSIZ]; /* template file */ static char tbuf[BUFSIZ]; /* current tfile */ /* * Command line flags */ int Iflag = FALSE; /* run ci(1) */ int rcsflag = FALSE; /* run rcs(1) */ int aflag = TRUE; /* do auto guess */ int dflag = TRUE; /* creat RCS dir. */ int qflag = FALSE; /* be quiet! */ int cflag = FALSE; /* std c file */ int fflag = FALSE; /* fortran file */ int pflag = FALSE; /* pascal file */ int hflag = FALSE; /* include file */ int sflag = FALSE; /* shell script */ int mflag = FALSE; /* Makefile */ int Mflag = FALSE; /* manual */ int tflag = FALSE; /* template flag */ main(argc, argv) int argc; char *argv[]; { int x; char tmp[LENGTH]; char *file; char *flags; char *tmpfile = "/tmp/rcsitXXXXXX"; char *mktemp(); char *gettmp(); char *getenv(); FILE *fd, *fdtmp, *fopen(); progname = *argv; for (x = 1; x < argc; x++) { if (argv[x][0] != '-') break; switch (argv[x][1]) { case 'a': aflag = FALSE; break; case 'q': qflag = TRUE; break; case 'd': dflag = FALSE; break; case 'f': fflag = TRUE; break; case 'h': hflag = TRUE; break; case 's': sflag = TRUE; break; case 'm': mflag = TRUE; break; case 'M': Mflag = TRUE; break; case 'i': case 'I': Iflag = TRUE; flags = &argv[x][2]; break; case 'r': case 'R': rcsflag = TRUE; flags = &argv[x][2]; break; case 't': tflag = TRUE; tpath = &argv[x][2]; break; case 'c': cflag = TRUE; break; default: fatal("Unknown flag %s.",argv); } } argc -= (x - 1); argv += (x - 1); if((hflag && (mflag || Mflag || cflag)) || (mflag && (hflag || cflag || Mflag)) || (Mflag && (cflag || hflag || mflag)) || (cflag && (hflag || Mflag || mflag))) { fatal("Only ONE of -c,-f,-m,-M,-h,-s may be specified."); } if(Iflag && rcsflag) { fatal("Only ONE of ``-i'' and ``-r'' may be specified."); } if(cflag || hflag || mflag || Mflag || fflag || sflag) aflag = FALSE; if((rcsdir = getenv("RCSDIR")) == NULL) rcsdir = "RCS"; if(Iflag && dflag) checkdir(); /* Make RCS directory for ci */ if((*tpath == NULL) && ((tpath = getenv("TEMPLATE")) == NULL)) if((tpath = getenv("HOME")) == NULL) fatal("Cannot find environment variable HOME or TEMPLATE"); /* * make tmp file once. */ mktemp(tmpfile); while (--argc) { /* Main loop */ file = *++argv; debug(sprintf(tmp, "...file (*++argv) = %s...", file)); if(access(file, 4) != 0) fatal("Cannot access %s. No read permission OR file does not exist.", file); if((fdtmp = fopen(tmpfile, "w")) == NULL) { fatal("Cannot open tmpfile (%s).", tmpfile); } if(aflag) auto_guess(file); /* try and guess file type */ else set_flags(); /* check and set flags */ if(tflag) { /* * first get names of templates, then create * path name to it. */ get_temp(); sprintf(tfile, "%s/%s", tpath, tbuf); } if(access(tfile, 0) == 0 && tflag) { if(!qflag || debugon) printf("Adding %s header file to %s...", msg_name, file); copy(tfile, tmpfile, "w"); copy(file, tmpfile, "a"); } else { if(!qflag || debugon) printf( "Adding default header (%s format) to %s...", msg_name, file); /* * put the Keywords into header string */ sprintf(tmp, header, "Header", "Log"); fputs(tmp, fdtmp); /* * fclose'em, just in case. */ fclose(fdtmp); copy(file, tmpfile, "a"); } unlink(file); copy(tmpfile, file, "w"); unlink(tmpfile); if(!qflag || debugon) printf("done.\n"); if(Iflag){ rcs("ci", file, flags); if(Mflag){ /* kludge to tell rcs about manuals */ rcs("rcs", file, "c'... '"); /* * kludge part 2 - if the user tried a ci * with a -l option, then the header is * messed up in the currently checked out * man file. So we have to co the file to * clean up the header. Plus we use the * -l option of co to insure file locking. */ if(checkfor("l", flags)){ unlink(file); rcs("co", file, "l"); } } } if(rcsflag) rcs("rcs", file, flags); } } /* * debug - print (useless) debugging info. */ debug(msg) char *msg; { #ifdef DEBUG fprintf(stderr, msg); putchar ('\n'); #endif } /* * auto_guess - try and be intelligent and guess type of file * by looking at the suffix or the whole name * in the case of a makefile. */ auto_guess(file) char *file; { char *suffix; char *rindex(); suffix = rindex(file, '.')+1; if((strcmp(file, "makefile") == 0) || (strcmp(file, "Makefile") == 0) || (strcmp(suffix, "mk") == 0)) { /* sys V std suffix */ mflag = TRUE; sflag = FALSE; cflag = FALSE; hflag = FALSE; Mflag = FALSE; fflag = FALSE; } if((strcmp(suffix, "sh") == 0) || (strcmp(suffix, "csh") == 0)) { sflag = TRUE; cflag = FALSE; hflag = FALSE; mflag = FALSE; Mflag = FALSE; fflag = FALSE; } if(strcmp(suffix, "c") == 0){ cflag = TRUE; hflag = FALSE; mflag = FALSE; Mflag = FALSE; sflag = FALSE; fflag = FALSE; } if(strcmp(suffix, "h") == 0){ hflag = TRUE; cflag = FALSE; mflag = FALSE; Mflag = FALSE; sflag = FALSE; fflag = FALSE; } if(strcmp(suffix, "f") == 0){ fflag = TRUE; hflag = FALSE; cflag = FALSE; mflag = FALSE; Mflag = FALSE; sflag = FALSE; } if(isdigit(*suffix) != 0) { Mflag = TRUE; hflag = FALSE; cflag = FALSE; mflag = FALSE; sflag = FALSE; fflag = FALSE; } set_flags(); if(!qflag || debugon) printf("Hmm. This file looks like a %s file.\n", msg_name); } /* * set_flags - set & check flags */ set_flags() { if(cflag || hflag || mflag || Mflag || sflag || fflag) { if(cflag) { msg_name = m_stdc; header = h_stdc; } if(hflag) { msg_name = m_include; header = h_include; } if(mflag) { msg_name = m_make; header = h_make; } if(Mflag) { msg_name = m_manual; header = h_manual; } if(sflag) { msg_name = m_shell; header = h_make; } if(fflag) { msg_name = m_fortran; header = h_fortran; } } else { cflag = TRUE; set_flags(); } } /* * copy from -> to */ copy(from, to, mode) char *from; char *to; char *mode; { FILE *fdfrom, *fdto, *fopen(); char tmp[LENGTH]; char s[LENGTH]; if((fdfrom = fopen(from, "r")) == NULL) { fatal("Cannot open %s for reading.",from); } if((fdto = fopen(to, mode)) == NULL) { fatal("Cannot open %s for \"%s\".",to,mode); } while(fgets(s, sizeof(s), fdfrom) != NULL) fputs(s, fdto); fclose(fdfrom); fclose(fdto); } /* * Run RCS's rcsprog on file with flags. */ rcs(rcsprog, file, flags) char *rcsprog; char *file; char *flags; { char buf[LENGTH]; char tmp[LENGTH]; if(!checkfor("q", flags) && qflag) flags = "q"; if(strcmp(flags, NULL) == 0) sprintf(buf, "%s %s", rcsprog, file); else sprintf(buf, "%s -%s %s", rcsprog, flags, file); debug(sprintf(tmp,"Running ``%s''...\n", buf)); if(!qflag) lineprint(sprintf(tmp, "Start of ``%s''", buf)); system(buf); if(!qflag) lineprint(sprintf(tmp, "End of ``%s''", buf)); } /* * checkdir - make RCS directory if not present. */ checkdir() { if(access("RCS", 0) != 0){ if(!qflag || debugon) printf("Cannot find \"RCS\" directory. Creating...\n"); if(strcmp(rcsdir, "RCS") != 0) { if(symlink(rcsdir, "RCS") != 0) fatal("Symbolic link of %s to RCS failed.", rcsdir); } else { if(mkdir(rcsdir, 0755) != 0) fatal("Cannot create \"%s\" directory.", rcsdir); } } } /* * checkfor(x, str) -- check for x in str. Return 1 (TRUE) if exists. * Otherwise 0 (FALSE). */ checkfor(x, str) char *x; char *str; { while(*str) { if(strcmp(str, x) == 0) return(TRUE); *str++; } return(FALSE); } /* * lineprint - print msg in a nice line */ lineprint(msg) char *msg; { int len, left, right, x; len = strlen(msg); right = (75-len)/2; left = right; for(x = 0; x < right; ++x) putchar('-'); printf("[ %s ]", msg); for(x = 0; x < left; ++x) putchar('-'); putchar('\n'); } /* * fatal - print error and then exit(1). */ fatal(format, str) char *format; { static char namefmt[100]; sprintf(namefmt, "%s: %s\n", progname, format); _doprnt(namefmt, &str, stderr); exit(1); } /* * zap str with NULL's */ zap(str) char str[]; { int i, x; i = strlen(str); for(x = 0; x <= i; ) str[x++] = NULL; } /* * get template names */ get_temp() { zap(tbuf); if(mflag) strcpy(tbuf, template_make); if(Mflag) strcpy(tbuf, template_man); if(hflag) strcpy(tbuf, template_h); if(cflag) strcpy(tbuf, template_c); if(sflag) strcpy(tbuf, template_sh); if(fflag) strcpy(tbuf, template_f); } SHAR_EOF if test -f '_.template.c' then echo shar: over-writing existing file "'_.template.c'" fi cat << \SHAR_EOF > '_.template.c' /* * $Header$ *------------------------------------------------------------------ * * $Source$ * $Revision$ * $Date$ * $State$ * $Author$ * $Locker$ * *------------------------------------------------------------------ * * Michael Cooper (mcooper@usc-oberon.arpa) * University Computing Services, * University of Southern California, * Los Angeles, California, 90089-0251 * (213) 743-3469 * *------------------------------------------------------------------ * $Log$ *------------------------------------------------------------------ */ SHAR_EOF # End of shell archive exit 0