[comp.sources.amiga] v89i224: rcs - revision control system, Part09/14

page%swap@Sun.COM (Bob Page) (11/19/89)

Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
Posting-number: Volume 89, Issue 224
Archive-name: unix/rcs.09

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	rcs/rcs.rcsfiles/rcsclean.sh,v
#	rcs/rcs.rcsfiles/rcsedit.c,v
#	rcs/rcs.rcsfiles/rcsfcmp.c,v
#	rcs/rcs.rcsfiles/rcsfnms.c,v
# This is archive 9 of a 14-part kit.
# This archive created: Sun Nov 19 01:12:10 1989
if `test ! -d rcs`
then
  mkdir rcs
  echo "mkdir rcs"
fi
if `test ! -d rcs/rcs.rcsfiles`
then
  mkdir rcs/rcs.rcsfiles
  echo "mkdir rcs/rcs.rcsfiles"
fi
echo "extracting rcs/rcs.rcsfiles/rcsclean.sh,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsclean.sh,v
Xhead     1.5;
Xbranch   1.5.2;
Xaccess   ;
Xsymbols  amiga_rcs:1.5.2 cbmvax_source:1.5.1 uunet_june89_dist:1.5;
Xlocks    ; strict;
Xcomment  @# @;
X
X
X1.5
Xdate     86.07.03.13.09.55;  author jdl;  state Exp;
Xbranches 1.5.1.1 1.5.2.1;
Xnext     ;
X
X1.5.1.1
Xdate     89.08.11.01.42.19;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X1.5.2.1
Xdate     89.10.13.19.20.06;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@RCS cleanup operation.
X@
X
X
X
X1.5
Xlog
X@checked in with -k by rsbx at 89.08.10.16.18.40.
X@
Xtext
X@#! /bin/sh
X#
X# RCS cleanup operation.
X# $Header: /arthur/src/local/bin/rcs/src/RCS/rcsclean.sh,v 1.5 86/07/03 13:09:55 jdl Exp $
X#
X# This program removes working files which are copies of the latest
X# revision on the default branch of the corresponding RCS files.
X# For each file given, rcsclean performs a co operation for the latest
X# revision on the default branch, and compares
X# the result with the working file. If the two are identical,
X# the working file is deleted.
X#
X# A typical application in a Makefile would be:
X# clean:;       rm *.o; rcsclean *.c *.o
X#
X# Limitation: This program doesn't work if given the name of
X# an RCS file rather than the name of the working file.
X
XPATH=/usr/new/bin:/usr/local/bin:/bin:/usr/bin:/usr/ucb
Xexport PATH
Xprogname=$0
Xif [ $# = 0 ] ; then
X    echo        "usage: $progname file ..."
X    echo        "removes all working files that are checked in and are unchanged"
X    exit  0
Xfi
XTMPFILE=/tmp/rcscl$$.tmp
Xwhile test $# -gt 0 ; do
X    if test -f $1 ; then
X	co -p -q $1 > $TMPFILE
X	if [ $? = 0 ] ; then
X	    cmp -s $1 $TMPFILE
X	    if [ $? = 0 ] ; then
X		chmod +w $1; rm -f $1; rcs -u -q $1
X	    fi
X	fi
X    fi
X    shift
Xdone
Xrm -f $TMPFILE
X@
X
X
X1.5.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d4 1
Xa4 1
X# $Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/rcsclean.sh,v 1.5.1.1 89/08/11 01:42:19 rsbx Exp Locker: rsbx $
X@
X
X
X1.5.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@d4 1
Xa4 1
X# $Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/rcsclean.sh,v 1.5 86/07/03 13:09:55 jdl Exp $
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsedit.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsedit.c,v
Xhead     4.8;
Xbranch   4.8.2;
Xaccess   ;
Xsymbols  amiga_rcs:4.8.2 cbmvax_source:4.8.1 uunet_june89_dist:4.8;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X4.8
Xdate     89.05.01.15.12.35;  author narten;  state Exp;
Xbranches 4.8.1.1 4.8.2.1;
Xnext     ;
X
X4.8.1.1
Xdate     89.08.11.01.42.25;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X4.8.2.1
Xdate     89.10.13.19.18.24;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.2;
X
X4.8.2.2
Xdate     89.10.15.15.44.09;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.3;
X
X4.8.2.3
Xdate     89.10.16.19.07.14;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.4;
X
X4.8.2.4
Xdate     89.10.16.23.42.40;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@RCS stream editor.
X@
X
X
X
X4.8
Xlog
X@checked in with -k by rsbx at 89.08.10.16.19.26.
X@
Xtext
X@/*
X *                     RCS stream editor
X */
X#ifndef lint
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8 89/05/01 15:12:35 narten Exp $ Purdue CS";
X#endif
X/**********************************************************************************
X *                       edits the input file according to a
X *                       script from stdin, generated by diff -n
X *                       performs keyword expansion
X **********************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X *   rcs-bugs@@cs.purdue.edu
X * 
X
X
X
X
X
X
X
X*/
X
X
X/* $Log:	rcsedit.c,v $
X * Revision 4.8  89/05/01  15:12:35  narten
X * changed copyright header to reflect current distribution rules
X * 
X * Revision 4.7  88/11/08  13:54:14  narten
X * misplaced semicolon caused infinite loop
X * 
X * Revision 4.6  88/11/08  12:01:41  narten
X * changes from  eggert@@sm.unisys.com (Paul Eggert)
X * 
X * Revision 4.6  88/08/09  19:12:45  eggert
X * Shrink stdio code size; allow cc -R.
X * 
X * Revision 4.5  87/12/18  11:38:46  narten
X * Changes from the 43. version. Don't know the significance of the
X * first change involving "rewind". Also, additional "lint" cleanup.
X * (Guy Harris)
X * 
X * Revision 4.4  87/10/18  10:32:21  narten
X * Updating version numbers. Changes relative to version 1.1 actually
X * relative to 4.1
X * 
X * Revision 1.4  87/09/24  13:59:29  narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
X * warnings)
X * 
X * Revision 1.3  87/09/15  16:39:39  shepler
X * added an initializatin of the variables editline and linecorr
X * this will be done each time a file is processed.
X * (there was an obscure bug where if co was used to retrieve multiple files
X *  it would dump)
X * fix attributed to  Roy Morris @@FileNet Corp ...!felix!roy
X * 
X * Revision 1.2  87/03/27  14:22:17  jenkins
X * Port to suns
X * 
X * Revision 1.1  84/01/23  14:50:20  kcs
X * Initial revision
X * 
X * Revision 4.1  83/05/12  13:10:30  wft
X * Added new markers Id and RCSfile; added locker to Header and Id.
X * Overhauled expandline completely() (problem with $01234567890123456789@@).
X * Moved trymatch() and marker table to rcskeys.c.
X * 
X * Revision 3.7  83/05/12  13:04:39  wft
X * Added retry to expandline to resume after failed match which ended in $.
X * Fixed truncation problem for $19chars followed by@@@@.
X * Log no longer expands full path of RCS file.
X * 
X * Revision 3.6  83/05/11  16:06:30  wft
X * added retry to expandline to resume after failed match which ended in $.
X * Fixed truncation problem for $19chars followed by@@@@.
X * 
X * Revision 3.5  82/12/04  13:20:56  wft
X * Added expansion of keyword Locker.
X *
X * Revision 3.4  82/12/03  12:26:54  wft
X * Added line number correction in case editing does not start at the
X * beginning of the file.
X * Changed keyword expansion to always print a space before closing KDELIM;
X * Expansion for Header shortened.
X *
X * Revision 3.3  82/11/14  14:49:30  wft
X * removed Suffix from keyword expansion. Replaced fclose with ffclose.
X * keyreplace() gets log message from delta, not from curlogmsg.
X * fixed expression overflow in while(c=putc(GETC....
X * checked nil printing.
X *
X * Revision 3.2  82/10/18  21:13:39  wft
X * I added checks for write errors during the co process, and renamed
X * expandstring() to xpandstring().
X *
X * Revision 3.1  82/10/13  15:52:55  wft
X * changed type of result of getc() from char to int.
X * made keyword expansion loop in expandline() portable to machines
X * without sign-extension.
X */
X
X
X#include "rcsbase.h"
X
X
Xextern FILE * fopen();
Xextern char * mktempfile();
Xextern char * bindex();
Xextern FILE * finptr, * frewrite;
Xextern int rewriteflag;
Xextern int nextc;
Xextern char * RCSfilename, * workfilename;
Xextern char * bindex();
Xextern char * getfullRCSname();
Xextern enum markers trymatch();
X
X
XFILE  * fcopy,  * fedit; /* result and edit file descriptors                */
Xchar  *resultfile;       /* result file name                                */
Xchar  * editfile;        /* edit   file name                                */
Xint editline;  /*line counter in fedit; starts with 1, is always #lines+1   */
Xint linecorr;  /*contains #adds - #deletes in each edit run.                */
X               /*used to correct editline in case file is not rewound after */
X               /* applying one delta                                        */
X
Xiniteditfiles(dir)
Xchar * dir;
X/* Function: Initializes resultfile and editfile with temporary filenames
X * in directory dir. Opens resultfile for reading and writing, with fcopy
X * as file descriptor. fedit is set to nil.
X */
X{
X	editline = linecorr = 0;    /* make sure we start from the beginning*/
X        resultfile=mktempfile(dir,TMPFILE1);
X        editfile  =mktempfile(dir,TMPFILE2);
X        fedit=nil;
X        if ((fcopy=fopen(resultfile,"w+"))==NULL) {
X                faterror("Can't open working file %s",resultfile);
X        }
X}
X
X
Xswapeditfiles(tostdout)
X/* Function: swaps resultfile and editfile, assigns fedit=fcopy,
X * rewinds fedit for reading, and opens resultfile for reading and
X * writing, using fcopy. If tostdout, fcopy is set to stdout.
X */
X{       char * tmpptr;
X        if(ferror(fcopy))
X                faterror("write failed on %s -- file system full?",resultfile);
X        fedit=fcopy;
X        rewind(fedit);
X        editline = 1; linecorr=0;
X        tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
X        if (tostdout)
X                fcopy=stdout;
X        elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
X                faterror("Can't open working file %s",resultfile);
X        }
X}
X
X
Xfinishedit(delta)
Xstruct hshentry * delta;
X/* copy the rest of the edit file and close it (if it exists).
X * if delta!=nil, perform keyword substitution at the same time.
X */
X{
X        register int c;
X        if (fedit!=nil) {
X                if (delta!=nil) {
X                        while (expandline(fedit,fcopy,delta,false,false)) editline++;
X                } else {
X                        while((c=getc(fedit))!=EOF) {
X                                VOID putc(c,fcopy);
X                                if (c=='\n') editline++;
X                        }
X                }
X                ffclose(fedit);
X        }
X}
X
X
Xcopylines(line,delta)
Xregister int line; struct hshentry * delta;
X/* Function: copies input lines editline..line-1 from fedit to fcopy.
X * If delta != nil, keyword expansion is done simultaneously.
X * editline is updated. Rewinds a file only if necessary.
X */
X{
X
X        if (editline>line) {
X                /* swap files */
X                finishedit((struct hshentry *)nil); swapeditfiles(false);
X                /* assumes edit only during last pass, from the beginning*/
X        }
X        while (editline<line) {
X                /*copy another line*/
X                if (delta)
X                        VOID expandline(fedit,fcopy,delta,false,false);
X                else
X                        while (putc(getc(fedit),fcopy)!='\n');
X                editline++;
X        }
X}
X
X
X
Xxpandstring(delta)
Xstruct hshentry * delta;
X/* Function: Reads a string terminated by SDELIM from finptr and writes it
X * to fcopy. Double SDELIM is replaced with single SDELIM.
X * Keyword expansion is performed with data from delta.
X * If rewriteflag==true, the string is also copied unchanged to frewrite.
X * editline is updated.
X */
X{
X        editline=1;
X        while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
X        nextc='\n';
X}
X
X
Xcopystring()
X/* Function: copies a string terminated with a single SDELIM from finptr to
X * fcopy, replacing all double SDELIM with a single SDELIM.
X * If rewriteflag==true, the string also copied unchanged to frewrite.
X * editline is set to (number of lines copied)+1.
X * Assumption: next character read is first string character.
X */
X{	register c;
X	register FILE *fin, *frew, *fcop;
X	register write;
X
X	fin=finptr; frew=frewrite; fcop=fcopy;
X        write=rewriteflag;
X        editline=1;
X        while ((c=GETC(fin,frew,write)) != EOF) {
X                if ((c==SDELIM)&&((c=GETC(fin,frew,write)) != SDELIM)){
X                        /* end of string */
X                        nextc = c;
X                        return;
X                }
X                VOID putc(c,fcop);
X                if (c=='\n') editline++;
X        }
X        nextc = c;
X        serror("Unterminated string");
X        return;
X}
X
X
X
X
Xeditstring(delta)
Xstruct hshentry * delta;
X/* Function: reads an edit script from finptr and applies it to
X * file fedit; the result is written to fcopy.
X * If delta!=nil, keyword expansion is performed simultaneously.
X * If frewrite==true, the edit script is also copied verbatim to frewrite.
X * Assumes that all these files are open.
X * If running out of lines in fedit, fedit and fcopy are swapped.
X * resultfile and editfile are the names of the files that go with fcopy
X * and fedit, respectively.
X * Assumes the next input character from finptr is the first character of
X * the edit script. Resets nextc on exit.
X */
X{
X        int ed; /* editor command */
X        register int c;
X	register FILE *fin, *frew;
X        register int write, i;
X        int line, length;
X
X	fin=finptr;  frew=frewrite;
X        editline += linecorr; linecorr=0; /*correct line number*/
X        write=rewriteflag;
X        for (;;) {
X                /* read next command and decode */
X                /* assume next non-white character is command name*/
X                while((ed=GETC(fin,frew,write))=='\n'||
X                        ed==' ' || ed=='\t');
X                if (ed==SDELIM) break;
X                /* now attempt to read numbers. */
X                /* fscanf causes trouble because of the required echoing */
X                while ((c=GETC(fin,frew,write))==' ');  /*skip spaces*/
X                if (!('0'<=c && c<='9')) {
X                        faterror("missing line number in edit script");
X                        break;
X                }
X                line= c -'0';
X                while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
X                        line = line*10 + c-'0';
X                }
X                while (c==' ') c=GETC(fin,frew,write);
X                if (!('0'<=c && c<='9')) {
X                        faterror("incorrect range in edit script");
X                        break;
X                }
X                length= c -'0';
X                while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
X                        length = length*10 + c-'0';
X                }
X                while(c!='\n'&&c!=EOF) c=GETC(fin,frew,write); /* skip to end of line */
X
X                switch (ed) {
X                case 'd':
X                        copylines(line,delta);
X                        /* skip over unwanted lines */
X                        for (i=length;i>0;i--) {
X                                /*skip next line*/
X                                while ((c=getc(fedit))!='\n')
X					if (c==EOF)
X						faterror("EOF during edit");
X                                editline++;
X                        }
X                        linecorr -= length;
X                        break;
X                case 'a':
X                        copylines(line+1,delta); /*copy only; no delete*/
X                        for (i=length;i>0;i--) {
X                                /*copy next line from script*/
X                                if (delta!=nil)
X                                       VOID expandline(fin,fcopy,delta,true,write);
X                                else {
X                                       c = GETC(fin,frew,write);
X                                       while (putc(c,fcopy)!='\n'){
X                                               if ((c==SDELIM)&&((c=GETC(fin,frew,write))!=SDELIM)){
X                                                       serror("Missing string delimiter in edit script");
X                                                       VOID putc(c,fcopy);
X                                               }
X                                               c = GETC(fin,frew,write);
X                                       }
X                                }
X                        }
X                        linecorr += length;
X                        break;
X                default:
X                        faterror("unknown command in edit script: %c", ed);
X                        break;
X                }
X        }
X        nextc=GETC(fin,frew,write);
X}
X
X
X
X/* The rest is for keyword expansion */
X
X
X
Xexpandline(in, out, delta,delimstuffed,write)
Xregister FILE * in, * out; struct hshentry * delta;
Xint delimstuffed, write;
X/* Function: Reads a line from in and writes it to out.
X * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
X * Keyword expansion is performed with data from delta.
X * If write==true, the string is also copied unchanged to frewrite.
X * Returns false if end-of-string or end-of-line is detected, true otherwise.
X */
X{
X	register c;
X	register FILE * frew;
X	register w, ds;
X	register char * tp;
X	char keystring[keylength+2];
X	char keyval[keyvallength+2];
X        enum markers matchresult;
X
X	frew = frewrite;
X	w = write;
X	ds = delimstuffed;
X	c=GETC(in,frew,w);
X        for (;;) {
X                if (c==EOF) {
X                        if(ds) {
X                                error("unterminated string");
X                                nextc=c;
X                        }
X                        return(false);
X                }
X
X                if (c==SDELIM && ds) {
X                        if ((c=GETC(in,frew,w))!=SDELIM) {
X                                /* end of string */
X                                nextc=c;
X                                return false;
X                        }
X                }
X                VOID putc(c,out);
X
X                if (c=='\n') return true; /* end of line */
X
X		if (c==KDELIM) {
X                        /* check for keyword */
X                        /* first, copy a long enough string into keystring */
X			tp=keystring;
X			while (((c=GETC(in,frew,w))!=EOF) && (tp<keystring+keylength) && (c!='\n')
X			       && (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
X                              VOID putc(c,out);
X			      *tp++ = c;
X                        }
X			*tp++ = c; *tp = '\0';
X			matchresult=trymatch(keystring,false);
X			if (matchresult==Nomatch) continue;
X			/* last c will be dealt with properly by continue*/
X
X			/* Now we have a keyword terminated with a K/VDELIM */
X			if (c==VDELIM) {
X			      /* try to find closing KDELIM, and replace value */
X			      tp=keyval;
X			      while (((c=GETC(in,frew,w)) != EOF)
X				     && (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
X				      *tp++ =c;
X				      if (c==SDELIM && ds) { /*skip next SDELIM */
X						c=GETC(in,frew,w);
X						/* Can't be at end of string.
X						/* always a \n before closing SDELIM */
X				      }
X			      }
X			      if (c!=KDELIM) {
X				    /* couldn't find closing KDELIM -- give up */
X				    VOID putc(VDELIM,out); *tp='\0';
X				    VOID fputs(keyval,out);
X				    continue;   /* last c handled properly */
X			      }
X			}
X			/* now put out the new keyword value */
X			keyreplace(matchresult,delta,out);
X                }
X                c=GETC(in,frew,w);
X        } /* end for */
X}
X
X
X
Xkeyreplace(marker,delta,out)
Xenum markers marker; struct hshentry * delta; register FILE * out;
X/* function: ouputs the keyword value(s) corresponding to marker.
X * Attributes are derived from delta.
X */
X{
X        char * date;
X        register char * sp;
X
X        date= delta->date;
X
X        switch (marker) {
X        case Author:
X                VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
X                break;
X        case Date:
X                VOID putc(VDELIM,out);VOID putc(' ',out);
X                VOID PRINTDATE(out,date);VOID putc(' ',out);
X                VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
X                break;
X        case Id:
X	case Header:
X		VOID putc(VDELIM,out); VOID putc(' ',out);
X		if (marker==Id)
X			 VOID fputs(bindex(RCSfilename,'/'),out);
X		else     VOID fputs(getfullRCSname(),out);
X		VOID fprintf(out," %s ", delta->num);
X                VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
X		VOID fprintf(out, " %s %s ",delta->author,delta->state);
X		if (delta->lockedby!=nil)
X			 VOID fprintf(out,"Locker: %s ",delta->lockedby);
X		VOID putc(KDELIM,out);
X                break;
X        case Locker:
X                VOID fprintf(out,"%c %s %c", VDELIM,
X                        delta->lockedby==nil?"":delta->lockedby,KDELIM);
X                break;
X        case Log:
X                VOID fprintf(out, "%c\t%s %c\n%sRevision %s  ",
X                        VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
X                VOID PRINTDATE(out,date);VOID fputs("  ",out);VOID PRINTTIME(out,date);
X                VOID fprintf(out, "  %s\n%s",delta->author,Comment);
X                /* do not include state here because it may change and is not updated*/
X                sp = delta->log;
X                while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
X                /* Comment is the comment leader */
X                break;
X        case RCSfile:
X                VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
X                break;
X        case Revision:
X                VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
X                break;
X        case Source:
X                VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
X                break;
X        case State:
X                VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
X                break;
X        case Nomatch:
X                VOID putc(KDELIM,out);
X                break;
X        }
X}
X
X
X@
X
X
X4.8.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d5 1
Xa5 5
X<<<<<<< rcsedit.c
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.1.1 89/08/11 01:42:25 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
Xstatic char rcsid[]= "$Id: rcsedit.c,v 1.2 89/09/17 13:35:29 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa40 11
X<<<<<<< rcsedit.c
X * Revision 4.8.1.1  89/08/11  01:42:25  rsbx
X * Start of cbmvax RCS source branch.
X=======
X * Revision 1.2  89/09/17  13:35:29  rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA).  This version
X * compiles correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X * 
X<<<<<<< rcsedit.c
Xa41 3
X * checked in with -k by rsbx at 89.08.10.16.19.26.
X * 
X * Revision 4.8  89/05/01  15:12:35  narten
Xa52 5
X=======
X * Revision 1.2  88/09/03  15:09:56  rick
X * Port to AmigaDos.  All done with conditional compiles
X * 
X>>>>>>> 1.2
Xa166 2
X        if (fedit != NULL)
X        	fclose(fedit);
X@
X
X
X4.8.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d5 5
Xa9 1
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.1 89/10/13 19:18:24 rsbx Exp Locker: rsbx $ Purdue CS";
Xd45 1
Xa45 3
X * Revision 4.8.2.1  89/10/13  19:18:24  rsbx
X * Start of Amiga RCS port branch.
X * 
Xd48 6
Xd55 1
Xd71 5
Xd457 1
Xa457 1
X						GETC(in,frew,w);
X@
X
X
X4.8.2.3
Xlog
X@Changed file path handling to deal with Amiga file path sematics.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.2 89/10/15 15:44:09 rsbx Exp $ Purdue CS";
Xa40 4
X * Revision 4.8.2.2  89/10/15  15:44:09  rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X * 
Xd133 1
Xd138 1
Xd488 1
Xa488 1
X			 VOID fputs(fnamepart(RCSfilename),out);
Xd503 1
Xa503 1
X                        VDELIM, fnamepart(RCSfilename), KDELIM, Comment, delta->num);
Xd512 1
Xa512 1
X                VOID fprintf(out,"%c %s %c",VDELIM,fnamepart(RCSfilename),KDELIM);
X@
X
X
X4.8.2.4
Xlog
X@Added function return type for fnamepart().
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.3 89/10/16 19:07:14 rsbx Exp $ Purdue CS";
Xa40 3
X * Revision 4.8.2.3  89/10/16  19:07:14  rsbx
X * Changed file path handling to deal with Amiga file path sematics.
X * 
Xa135 1
Xextern char * fnamepart();
X@
X
X
X4.8.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a41 3
X * checked in with -k by rsbx at 89.08.10.16.19.26.
X * 
X * Revision 4.8  89/05/01  15:12:35  narten
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsfcmp.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfcmp.c,v
Xhead     4.5;
Xbranch   4.5.2;
Xaccess   ;
Xsymbols  amiga_rcs:4.5.2 cbmvax_source:4.5.1 uunet_june89_dist:4.5;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X4.5
Xdate     89.05.01.15.12.42;  author narten;  state Exp;
Xbranches 4.5.1.1 4.5.2.1;
Xnext     ;
X
X4.5.1.1
Xdate     89.08.11.01.42.29;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X4.5.2.1
Xdate     89.10.13.19.18.28;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.5.2.2;
X
X4.5.2.2
Xdate     89.10.15.15.44.13;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@RCS file comparison.
X@
X
X
X
X4.5
Xlog
X@checked in with -k by rsbx at 89.08.10.16.19.42.
X@
Xtext
X@/*
X *                     RCS file comparison
X */
X#ifndef lint
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5 89/05/01 15:12:42 narten Exp $ Purdue CS";
X#endif
X/*****************************************************************************
X *                       rcsfcmp()
X *                       Testprogram: define FCMPTEST
X *****************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X *   rcs-bugs@@cs.purdue.edu
X * 
X
X
X
X
X
X
X
X*/
X
X
X
X
X
X/* $Log:	rcsfcmp.c,v $
X * Revision 4.5  89/05/01  15:12:42  narten
X * changed copyright header to reflect current distribution rules
X * 
X * Revision 4.4  88/11/08  12:01:33  narten
X * changes from  eggert@@sm.unisys.com (Paul Eggert)
X * 
X * Revision 4.4  88/08/09  19:12:50  eggert
X * Shrink stdio code size.
X * 
X * Revision 4.3  87/12/18  11:40:02  narten
X * lint cleanups (Guy Harris)
X * 
X * Revision 4.2  87/10/18  10:33:06  narten
X * updting version number. Changes relative to 1.1 actually relative to 
X * 4.1
X * 
X * Revision 1.2  87/03/27  14:22:19  jenkins
X * Port to suns
X * 
X * Revision 1.1  84/01/23  14:50:23  kcs
X * Initial revision
X * 
X * Revision 4.1  83/05/10  16:24:04  wft
X * Marker matching now uses trymatch(). Marker pattern is now
X * checked precisely.
X * 
X * Revision 3.1  82/12/04  13:21:40  wft
X * Initial revision.
X *
X */
X
X/*
X#define FCMPTEST
X/* Testprogram; prints out whether two files are identical,
X * except for keywords
X */
X
X#include  "rcsbase.h"
Xextern FILE * fopen();
Xextern enum markers trymatch(); /* check for keywords */
X
X
Xrcsfcmp(xfname,uxfname,delta)
Xchar * xfname, *uxfname; struct hshentry *delta;
X/* Function: compares the files xfname and uxfname. Returns true
X * if xfname has the same contents as uxfname, while disregarding
X * keyword values. For the LOG-keyword, rcsfcmp skips the log message
X * given by the parameter delta in xfname. Thus, rcsfcmp returns true
X * if xfname contains the same as uxfname, with the keywords expanded.
X * Implementation: character-by-character comparison until $ is found.
X * If a $ is found, read in the marker keywords; if they are real keywords
X * and identical, read in keyword value. If value is terminated properly,
X * disregard it and optionally skip log message; otherwise, compare value.
X */
X{
X    register int xc,uxc;
X    char xkeyword[keylength+2],   uxkeyword[keylength+2];
X    char xkeyval[keyvallength+1], uxkeyval[keyvallength+1];
X    register FILE * xfp, * uxfp;
X    register char * tp;
X    int result;
X    enum markers match1,match2;
X
X    if ((xfp=fopen(tp=xfname,"r"))==NULL || (uxfp=fopen(tp=uxfname,"r"))==NULL) {
X       faterror("Can't open %s\n", tp);
X       return false;
X    }
X    result=false;
X    xc=getc(xfp); uxc=getc(uxfp);
X    while( xc == uxc) { /* comparison loop */
X        if (xc==EOF) { /* finished; everything is the same*/
X            result=true;
X            break;
X        }
X        if ( xc!=KDELIM) {
X            /* get the next characters */
X            xc=getc(xfp); uxc=getc(uxfp);
X        } else {
X            /* try to get both keywords */
X            tp = xkeyword;
X            while( (xc=getc(xfp))!=EOF && (tp< xkeyword+keylength) && (xc!='\n')
X                   && (xc!=KDELIM) && (xc!=VDELIM))
X                *tp++ = xc;
X	    *tp++ = xc;  /* add closing K/VDELIM */
X            *tp='\0';
X            tp = uxkeyword;
X            while( (uxc=getc(uxfp))!=EOF && (tp< uxkeyword+keylength) && (uxc!='\n')
X                   && (uxc!=KDELIM) && (uxc!=VDELIM))
X                *tp++ = uxc;
X	    *tp++ = xc;  /* add closing K/VDELIM */
X            *tp='\0';
X            /* now we have 2 keywords, or something thal looks like it.*/
X	    match1=trymatch(xkeyword,false);
X	    match2=trymatch(uxkeyword,false);
X	    if (match1 != match2) break; /* not identical */
X#ifdef FCMPTEST
X	    VOID printf("found potential keywords %s and %s\n",xkeyword,uxkeyword);
X#endif
X
X	    if (match1 == Nomatch) {
X		/* not a keyword pattern, but could still be identical */
X		if (strcmp(xkeyword,uxkeyword)==0)
X		     continue;
X		else break;
X	    }
X#ifdef FCMPTEST
X	    VOID printf("found common keyword %s\n",xkeyword);
X#endif
X	    tp=xkeyval;
X	    if (xc==VDELIM) {/* get value */
X		while (((xc=getc(xfp))!=KDELIM) && (xc!='\n') && (xc!=EOF) &&
X			(tp<xkeyval+keyvallength))
X		    *tp++ = xc;
X	    }
X	    *tp = '\0';   /*xkeyval now filled with value; possibly empty*/
X	    tp=uxkeyval;
X	    if (uxc==VDELIM) {/* get value */
X		while (((uxc=getc(uxfp))!=KDELIM) && (uxc!='\n') && (uxc!=EOF) &&
X			(tp<uxkeyval+keyvallength))
X		    *tp++ = uxc;
X	    }
X	    *tp = '\0';   /*uxkeyval now filled with value; possibly empty*/
X	    if (xc!=uxc) break; /* not the same */
X	    if (xc==KDELIM) {
X		xc=getc(xfp); uxc=getc(uxfp); /* skip closing KDELIM */
X		/* if the keyword is LOG, also skip the log message in xfp*/
X		if (match1==Log) {
X		    /* first, compute the number of line feeds in log msg */
X		    int lncnt, ccnt;
X		    lncnt=2; tp=delta->log;
X		    while(*tp) if(*tp++=='\n') lncnt++;
X		    while(xc!=EOF) {
X			if (xc=='\n')
X			    if(--lncnt==0) break;
X			xc=getc(xfp);
X		    }
X		    /* skip last comment leader */
X		    /* Can't just skip another line here, because there may be */
X		    /* additional characters on the line (after the Log....$)  */
X		    for (ccnt=strlen(Comment); ccnt>=0; lncnt--) {
X			xc=getc(xfp);
X			if(xc=='\n') break;
X			/* reads to the end of the comment leader or '\n',     */
X			/* whatever comes first. This is because some editors  */
X			/* strip off trailing blanks from a leader like " * ". */
X		    }
X		}
X	    } else {
X		/* both end in the same character, but not a KDELIM */
X		/* must compare string values.*/
X#ifdef FCMPTEST
X		VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
X#endif
X		if (strcmp(xkeyval,uxkeyval)!=0) break; /*different */
X		xc=getc(xfp); uxc=getc(uxfp); /* skip closing char  */
X            }
X        }
X    }
X    VOID fclose(xfp); VOID fclose(uxfp);
X    return result;
X}
X
X
X
X#ifdef FCMPTEST
Xchar * RCSfilename, * workfilename;
X
Xchar * Comment;
X
Xmain(argc, argv)
Xint  argc; char  *argv[];
X/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
X * 4th: unexpanded file
X */
X{       struct hshentry delta;
X
X        cmdid="rcsfcmp";
X        Comment=argv[1];
X        delta.log=argv[2];
X        if (rcsfcmp(argv[3],argv[4],&delta))
X                VOID printf("files are the same\n");
X        else    VOID printf("files are different\n");
X}
X#endif
X@
X
X
X4.5.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d5 1
Xa5 5
X<<<<<<< rcsfcmp.c
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5.1.1 89/08/11 01:42:29 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 1.2 89/09/17 13:42:09 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa42 16
X<<<<<<< rcsfcmp.c
X * Revision 4.5.1.1  89/08/11  01:42:29  rsbx
X * Start of cbmvax RCS source branch.
X * 
X * Revision 4.5  89/05/01  15:12:42  narten
X * checked in with -k by rsbx at 89.08.10.16.19.42.
X=======
X * Revision 1.2  89/09/17  13:42:09  rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with condition compile (#ifdef AMIGA).  This
X * version compiles correctly with Lattice C version 5.02 or later.
X * 
X * Revision 1.1  89/09/17  13:04:37  rick
X * Initial revision
X>>>>>>> 1.2
X * 
X@
X
X
X4.5.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d5 5
Xa9 1
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5.2.1 89/10/13 19:18:28 rsbx Exp Locker: rsbx $ Purdue CS";
Xd47 1
Xa47 3
X * Revision 4.5.2.1  89/10/13  19:18:28  rsbx
X * Start of Amiga RCS port branch.
X * 
Xd53 5
Xd59 4
Xd202 1
Xa202 1
X		    for (ccnt=strlen(Comment); ccnt>=0;) {
X@
X
X
X4.5.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a43 3
X * checked in with -k by rsbx at 89.08.10.16.19.42.
X * 
X * Revision 4.5  89/05/01  15:12:42  narten
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsfnms.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfnms.c,v
Xhead     4.8;
Xbranch   4.8.2;
Xaccess   ;
Xsymbols  amiga_rcs:4.8.2 cbmvax_source:4.8.1 uunet_june89_dist:4.8;
Xlocks    ; strict;
Xcomment  @ * @;
X
X
X4.8
Xdate     89.05.01.15.09.41;  author narten;  state Exp;
Xbranches 4.8.1.1 4.8.2.1;
Xnext     ;
X
X4.8.1.1
Xdate     89.08.11.01.42.32;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X4.8.2.1
Xdate     89.10.13.19.18.32;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.2;
X
X4.8.2.2
Xdate     89.10.15.15.44.18;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.3;
X
X4.8.2.3
Xdate     89.10.15.18.27.52;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.4;
X
X4.8.2.4
Xdate     89.10.16.19.07.19;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.5;
X
X4.8.2.5
Xdate     89.10.16.23.54.04;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.6;
X
X4.8.2.6
Xdate     89.10.17.16.17.29;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.7;
X
X4.8.2.7
Xdate     89.10.17.18.38.55;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.8;
X
X4.8.2.8
Xdate     89.10.30.13.44.29;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.9;
X
X4.8.2.9
Xdate     89.10.30.13.53.10;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.10;
X
X4.8.2.10
Xdate     89.11.01.14.43.14;  author rsbx;  state Exp;
Xbranches ;
Xnext     4.8.2.11;
X
X4.8.2.11
Xdate     89.11.05.18.03.59;  author rsbx;  state Exp;
Xbranches ;
Xnext     ;
X
X
Xdesc
X@RCS file name handling.
X@
X
X
X
X4.8
Xlog
X@checked in with -k by rsbx at 89.08.10.16.20.00.
X@
Xtext
X@/*
X *                     RCS file name handling
X */
X#ifndef lint
X static char
X rcsid[]= "$Id: rcsfnms.c,v 4.8 89/05/01 15:09:41 narten Exp $ Purdue CS";
X#endif
X/****************************************************************************
X *                     creation and deletion of semaphorefile,
X *                     creation of temporary filenames and cleanup()
X *                     pairing of RCS file names and working file names.
X *                     Testprogram: define PAIRTEST
X ****************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X *   rcs-bugs@@cs.purdue.edu
X * 
X
X
X
X
X
X
X
X*/
X
X
X
X
X/* $Log:	rcsfnms.c,v $
X * Revision 4.8  89/05/01  15:09:41  narten
X * changed getwd to not stat empty directories.
X * 
X * Revision 4.7  88/11/08  12:01:22  narten
X * changes from  eggert@@sm.unisys.com (Paul Eggert)
X * 
X * Revision 4.7  88/08/09  19:12:53  eggert
X * Fix troff macro comment leader bug; add Prolog; allow cc -R; remove lint.
X * 
X * Revision 4.6  87/12/18  11:40:23  narten
X * additional file types added from 4.3 BSD version, and SPARC assembler
X * comment character added. Also, more lint cleanups. (Guy Harris)
X * 
X * Revision 4.5  87/10/18  10:34:16  narten
X * Updating version numbers. Changes relative to 1.1 actually relative
X * to verion 4.3
X * 
X * Revision 1.3  87/03/27  14:22:21  jenkins
X * Port to suns
X * 
X * Revision 1.2  85/06/26  07:34:28  svb
X * Comment leader '% ' for '*.tex' files added.
X * 
X * Revision 1.1  84/01/23  14:50:24  kcs
X * Initial revision
X * 
X * Revision 4.3  83/12/15  12:26:48  wft
X * Added check for KDELIM in file names to pairfilenames().
X * 
X * Revision 4.2  83/12/02  22:47:45  wft
X * Added csh, red, and sl file name suffixes.
X * 
X * Revision 4.1  83/05/11  16:23:39  wft
X * Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
X * 1. added copying of path from workfile to RCS file, if RCS file is omitted;
X * 2. added getting the file status of RCS and working files;
X * 3. added ignoring of directories.
X * 
X * Revision 3.7  83/05/11  15:01:58  wft
X * Added comtable[] which pairs file name suffixes with comment leaders;
X * updated InitAdmin() accordingly.
X * 
X * Revision 3.6  83/04/05  14:47:36  wft
X * fixed Suffix in InitAdmin().
X * 
X * Revision 3.5  83/01/17  18:01:04  wft
X * Added getwd() and rename(); these can be removed by defining
X * V4_2BSD, since they are not needed in 4.2 bsd.
X * Changed sys/param.h to sys/types.h.
X *
X * Revision 3.4  82/12/08  21:55:20  wft
X * removed unused variable.
X *
X * Revision 3.3  82/11/28  20:31:37  wft
X * Changed mktempfile() to store the generated file names.
X * Changed getfullRCSname() to store the file and pathname, and to
X * delete leading "../" and "./".
X *
X * Revision 3.2  82/11/12  14:29:40  wft
X * changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(),
X * checksuffix(), checkfullpath(). Semaphore name generation updated.
X * mktempfile() now checks for nil path; freefilename initialized properly.
X * Added Suffix .h to InitAdmin. Added testprogram PAIRTEST.
X * Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here.
X *
X * Revision 3.1  82/10/18  14:51:28  wft
X * InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h).
X * renamed checkpath() to checkfullpath().
X */
X
X
X#include "rcsbase.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X
Xextern char * rindex();
Xextern char * mktemp();
Xextern FILE * fopen();
Xextern char * getwd();         /* get working directory; forward decl       */
Xextern int    stat(), fstat();
X
Xextern FILE * finptr;          /* RCS input file descriptor                 */
Xextern FILE * frewrite;        /* New RCS file descriptor                   */
Xextern char * RCSfilename, * workfilename; /* filenames                     */
Xstruct stat RCSstat, workstat; /* file status for RCS file and working file */
Xint    haveRCSstat,  haveworkstat; /* indicators if status availalble       */
X
X
Xchar tempfilename [NCPFN+10];  /* used for derived file names               */
Xchar sub1filename [NCPPN];     /* used for files path/file.sfx,v            */
Xchar sub2filename [NCPPN];     /* used for files path/RCS/file.sfx,v        */
Xchar semafilename [NCPPN];     /* name of semaphore file                    */
Xint  madesema;                 /* indicates whether a semaphore file has been set */
Xchar * tfnames[10];            /* temp. file names to be unlinked when finished   */
Xint  freefilename;             /* index of next free file name in tfnames[]  */
X
X
Xstruct compair {
X        char * suffix, * comlead;
X};
X
Xstruct compair comtable[] = {
X/* comtable pairs each filename suffix with a comment leader. The comment   */
X/* leader is placed before each line generated by the $Log keyword. This    */
X/* table is used to guess the proper comment leader from the working file's */
X/* suffix during initial ci (see InitAdmin()). Comment leaders are needed   */
X/* for languages without multiline comments; for others they are optional.  */
X        "c",   " * ",   /* C           */
X	"csh", "# ",    /* shell       */
X        "e",   "# ",    /* efl         */
X        "f",   "c ",    /* fortran     */
X        "h",   " * ",   /* C-header    */
X        "l",   " * ",   /* lex         NOTE: conflict between lex and franzlisp*/
X        "mac", "; ",    /* macro       vms or dec-20 or pdp-11 macro */
X	"me",  ".\\\" ",/* me-macros   t/nroff*/
X	"mm",  ".\\\" ",/* mm-macros   t/nroff*/
X	"ms",  ".\\\" ",/* ms-macros   t/nroff*/
X        "p",   " * ",   /* pascal      */
X	"pl",  "% ",	/* prolog      */
X        "r",   "# ",    /* ratfor      */
X        "red", "% ",    /* psl/rlisp   */
X
X#ifdef sparc
X        "s",   "! ",    /* assembler   */
X#endif
X#ifdef mc68000
X        "s",   "| ",    /* assembler   */
X#endif
X#ifdef pdp11
X        "s",   "/ ",    /* assembler   */
X#endif
X#ifdef vax
X        "s",   "# ",    /* assembler   */
X#endif
X
X        "sh",  "# ",    /* shell       */
X        "sl",  "% ",    /* psl         */
X        "red", "% ",    /* psl/rlisp   */
X        "cl",  ";;; ",  /* common lisp   */
X        "ml",  "; ",    /* mocklisp    */
X        "el",  "; ",    /* gnulisp     */
X	"tex", "% ",	/* tex	       */
X        "y",   " * ",   /* yacc        */
X        "ye",  " * ",   /* yacc-efl    */
X        "yr",  " * ",   /* yacc-ratfor */
X        "",    "# ",    /* default for empty suffix */
X        nil,   ""       /* default for unknown suffix; must always be last */
X};
X
X
Xffclose(fptr)
XFILE * fptr;
X/* Function: checks ferror(fptr) and aborts the program if there were
X * errors; otherwise closes fptr.
X */
X{       if (ferror(fptr) || fclose(fptr)==EOF)
X                faterror("File read or write error; file system full?");
X}
X
X
X
Xint trysema(RCSname,makesema)
Xchar * RCSname; int makesema;
X/* Function: Checks whether a semaphore file exists for RCSname. If yes,
X * returns false. If not, creates one if makesema==true and returns true
X * if successful. If a semaphore file was created, madesema is set to true.
X * The name of the semaphore file is put into variable semafilename.
X */
X{
X        register char * tp, *sp, *lp;
X        int fdesc;
X
X        sp=RCSname;
X        lp = rindex(sp,'/');
X        if (lp==0) {
X                semafilename[0]='.'; semafilename[1]='/';
X                tp= &semafilename[2];
X        } else {
X                /* copy path */
X                tp=semafilename;
X                do *tp++ = *sp++; while (sp<=lp);
X        }
X        /*now insert `,' and append file name */
X        *tp++ = ',';
X        lp = rindex(sp, RCSSEP);
X        while (sp<lp) *tp++ = *sp++;
X        *tp++ = ','; *tp++ = '\0'; /* will be the same length as RCSname*/
X
X        madesema = false;
X        if (access(semafilename, 0) == 0) {
X                error("RCS file %s is in use",RCSname);
X                return false;
X        }
X        if (makesema) {
X                if ((fdesc=creat(semafilename, 000)) == -1) {
X                     error("Can't create semaphore file for RCS file %s",RCSname);
X                     return false;
X                } else
X                     VOID close(fdesc);
X                     madesema=true;
X        }
X        return true;
X}
X
X
Xrmsema()
X/* Function: delete the semaphore file if madeseam==true;
X * sets madesema to false.
X */
X{
X        if (madesema) {
X                madesema=false;
X                if (unlink(semafilename) == -1) {
X                        error("Can't find semaphore file %s",semafilename);
X                }
X        }
X}
X
X
X
XInitCleanup()
X{       freefilename =  0;  /* initialize pointer */
X}
X
X
Xcleanup()
X/* Function: closes input file and rewrite file.
X * Unlinks files in tfnames[], deletes semaphore file.
X */
X{
X        register int i;
X
X        if (finptr!=NULL)   VOID fclose(finptr);
X        if (frewrite!=NULL) VOID fclose(frewrite);
X        for (i=0; i<freefilename; i++) {
X            if (tfnames[i][0]!='\0')  VOID unlink(tfnames[i]);
X        }
X        InitCleanup();
X        rmsema();
X}
X
X
Xchar * mktempfile(fullpath,filename)
Xregister char * fullpath, * filename;
X/* Function: Creates a unique filename using the process id and stores it
X * into a free slot in tfnames. The filename consists of the path contained
X * in fullpath concatenated with filename. filename should end in "XXXXXX".
X * Because of storage in tfnames, cleanup() can unlink the file later.
X * freefilename indicates the lowest unoccupied slot in tfnames.
X * Returns a pointer to the filename created.
X * Example use: mktempfile("/tmp/", somefilename)
X */
X{
X        register char * lastslash, *tp;
X        if ((tp=tfnames[freefilename])==nil)
X              tp=tfnames[freefilename] = talloc(NCPPN);
X        if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
X                /* copy path */
X                while (fullpath<=lastslash) *tp++ = *fullpath++;
X        }
X        while (*tp++ = *filename++);
X        return (mktemp(tfnames[freefilename++]));
X}
X
X
X
X
Xchar * bindex(sp,c)
Xregister char * sp, c;
X/* Function: Finds the last occurrence of character c in string sp
X * and returns a pointer to the character just beyond it. If the
X * character doesn't occur in the string, sp is returned.
X */
X{       register char * r;
X        r = sp;
X        while (*sp) {
X                if (*sp++ == c) r=sp;
X        }
X        return r;
X}
X
X
X
X
X
XInitAdmin()
X/* function: initializes an admin node */
X{       register char * Suffix;
X        register int i;
X
X        Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
X        StrictLocks=STRICT_LOCKING;
X
X        /* guess the comment leader from the suffix*/
X        Suffix=bindex(workfilename, '.');
X        if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
X        for (i=0;;i++) {
X                if (comtable[i].suffix==nil) {
X                        Comment=comtable[i].comlead; /*default*/
X                        break;
X                } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
X                        Comment=comtable[i].comlead; /*default*/
X                        break;
X                }
X        }
X        Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
X}
X
X
X
Xchar * findpairfile(argc, argv, fname)
Xint argc; char * argv[], *fname;
X/* Function: Given a filename fname, findpairfile scans argv for a pathname
X * ending in fname. If found, returns a pointer to the pathname, and sets
X * the corresponding pointer in argv to nil. Otherwise returns fname.
X * argc indicates the number of entries in argv. Some of them may be nil.
X */
X{
X        register char * * next, * match;
X        register int count;
X
X        for (next = argv, count = argc; count>0; next++,count--) {
X                if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
X                        /* bindex finds the beginning of the file name stem */
X                        match= *next;
X                        *next=nil;
X                        return match;
X                }
X        }
X        return fname;
X}
X
X
Xint pairfilenames(argc, argv, mustread, tostdout)
Xint argc; char ** argv; int mustread, tostdout;
X/* Function: Pairs the filenames pointed to by argv; argc indicates
X * how many there are.
X * Places a pointer to the RCS filename into RCSfilename,
X * and a pointer to the name of the working file into workfilename.
X * If both the workfilename and the RCS filename are given, and tostdout
X * is true, a warning is printed.
X *
X * If the working file exists, places its status into workstat and
X * sets haveworkstat to 0; otherwise, haveworkstat is set to -1;
X * Similarly for the RCS file and the variables RCSstat and haveRCSstat.
X *
X * If the RCS file exists, it is opened for reading, the file pointer
X * is placed into finptr, and the admin-node is read in; returns 1.
X * If the RCS file does not exist and mustread==true, an error is printed
X * and 0 returned.
X * If the RCS file does not exist and mustread==false, the admin node
X * is initialized to empty (Head, AccessList, Locks, Symbols, StrictLocks, Dbranch)
X * and -1 returned.
X *
X * 0 is returned on all errors. Files that are directories are errors.
X * Also calls InitCleanup();
X */
X{
X        register char * sp, * tp;
X        char * lastsep, * purefname, * pureRCSname;
X        int opened, returncode;
X        char * RCS1;
X	char prefdir[NCPPN];
X
X        if (*argv == nil) return 0; /* already paired filename */
X	if (rindex(*argv,KDELIM)!=0) {
X		/* KDELIM causes havoc in keyword expansion    */
X		error("RCS file name may not contain %c",KDELIM);
X		return 0;
X	}
X        InitCleanup();
X
X        /* first check suffix to see whether it is an RCS file or not */
X        purefname=bindex(*argv, '/'); /* skip path */
X        lastsep=rindex(purefname, RCSSEP);
X        if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
X                /* RCS file name given*/
X                RCS1=(*argv); pureRCSname=purefname;
X                /* derive workfilename*/
X                sp = purefname; tp=tempfilename;
X                while (sp<lastsep) *tp++ = *sp++; *tp='\0';
X                /* try to find workfile name among arguments */
X                workfilename=findpairfile(argc-1,argv+1,tempfilename);
X                if (strlen(pureRCSname)>NCPFN) {
X                        error("RCS file name %s too long",RCS1);
X                        return 0;
X                }
X        } else {
X                /* working file given; now try to find RCS file */
X                workfilename= *argv;
X                /* derive RCS file name*/
X                sp=purefname; tp=tempfilename;
X                while (*tp++ = *sp++);
X                *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp++='\0';
X                /* Try to find RCS file name among arguments*/
X                RCS1=findpairfile(argc-1,argv+1,tempfilename);
X                pureRCSname=bindex(RCS1, '/');
X                if (strlen(pureRCSname)>NCPFN) {
X                        error("working file name %s too long",workfilename);
X                        return 0;
X                }
X        }
X        /* now we have a (tentative) RCS filename in RCS1 and workfilename  */
X        /* First, get status of workfilename */
X        haveworkstat=stat(workfilename, &workstat);
X        if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
X                diagnose("Directory %s ignored",workfilename);
X                return 0;
X        }
X        /* Second, try to find the right RCS file */
X        if (pureRCSname!=RCS1) {
X                /* a path for RCSfile is given; single RCS file to look for */
X                finptr=fopen(RCSfilename=RCS1, "r");
X                if (finptr!=NULL) {
X                    returncode=1;
X                } else { /* could not open */
X                    if (access(RCSfilename,0)==0) {
X                        error("Can't open existing %s", RCSfilename);
X                        return 0;
X                    }
X                    if (mustread) {
X                        error("Can't find %s", RCSfilename);
X                        return 0;
X                    } else {
X                        /* initialize if not mustread */
X                        returncode = -1;
X                    }
X                }
X        } else {
X		/* no path for RCS file name. Prefix it with path of work */
X		/* file if RCS file omitted. Make a second name including */
X		/* RCSDIR and try to open that one first.                 */
X		sub1filename[0]=sub2filename[0]= '\0';
X		if (RCS1==tempfilename) {
X			/* RCS file name not given; prepend work path */
X			sp= *argv; tp= sub1filename;
X			while (sp<purefname) *tp++ = *sp ++;
X			*tp='\0';
X			VOID strcpy(sub2filename,sub1filename); /* second one */
X		}
X		VOID strcat(sub1filename,RCSDIR);
X		VOID strcpy(prefdir,sub1filename); /* preferred directory for RCS file*/
X		VOID strcat(sub1filename,RCS1); VOID strcat(sub2filename,RCS1);
X
X
X                opened=(
X		((finptr=fopen(RCSfilename=sub1filename, "r"))!=NULL) ||
X		((finptr=fopen(RCSfilename=sub2filename,"r"))!=NULL) );
X
X                if (opened) {
X                        /* open succeeded */
X                        returncode=1;
X                } else {
X                        /* open failed; may be read protected */
X			if ((access(RCSfilename=sub1filename,0)==0) ||
X			    (access(RCSfilename=sub2filename,0)==0)) {
X                                error("Can't open existing %s",RCSfilename);
X                                return 0;
X                        }
X                        if (mustread) {
X				error("Can't find %s nor %s",sub1filename,sub2filename);
X                                return 0;
X                        } else {
X                                /* initialize new file. Put into ./RCS if possible, strip off suffix*/
X				RCSfilename= (access(prefdir,0)==0)?sub1filename:sub2filename;
X                                returncode= -1;
X                        }
X                }
X        }
X
X        if (returncode == 1) { /* RCS file open */
X                haveRCSstat=fstat(fileno(finptr),&RCSstat);
X                if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
X                        diagnose("Directory %s ignored",RCSfilename);
X                        return 0;
X                }
X                Lexinit(); getadmin();
X        } else {  /* returncode == -1; RCS file nonexisting */
X                haveRCSstat = -1;
X                InitAdmin();
X        };
X
X        if (tostdout&&
X            !(RCS1==tempfilename||workfilename==tempfilename))
X                /*The last term determines whether a pair of        */
X                /* file names was given in the argument list        */
X                warn("Option -p is set; ignoring output file %s",workfilename);
X
X        return returncode;
X}
X
X
Xchar * getfullRCSname()
X/* Function: returns a pointer to the full path name of the RCS file.
X * Calls getwd(), but only once.
X * removes leading "../" and "./".
X */
X{       static char pathbuf[NCPPN];
X        static char namebuf[NCPPN];
X        static int  pathlength;
X
X        register char * realname, * lastpathchar;
X        register int  dotdotcounter, realpathlength;
X
X        if (*RCSfilename=='/') {
X                return(RCSfilename);
X        } else {
X                if (pathlength==0) { /*call curdir for the first time*/
X                    if (getwd(pathbuf)==NULL)
X                        faterror("Can't build current directory path");
X                    pathlength=strlen(pathbuf);
X                    if (!((pathlength==1) && (pathbuf[0]=='/'))) {
X                        pathbuf[pathlength++]='/';
X                        /* Check needed because some getwd implementations */
X                        /* generate "/" for the root.                      */
X                    }
X                }
X                /*the following must be redone since RCSfilename may change*/
X                /* find how many ../ to remvove from RCSfilename */
X                dotdotcounter =0;
X                realname = RCSfilename;
X                while( realname[0]=='.' &&
X                      (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
X                        if (realname[1]=='/') {
X                            /* drop leading ./ */
X                            realname += 2;
X                        } else {
X                            /* drop leading ../ and remember */
X                            dotdotcounter++;
X                            realname += 3;
X                        }
X                }
X                /* now remove dotdotcounter trailing directories from pathbuf*/
X                lastpathchar=pathbuf + pathlength-1;
X                while (dotdotcounter>0 && lastpathchar>pathbuf) {
X                    /* move pointer backwards over trailing directory */
X                    lastpathchar--;
X                    if (*lastpathchar=='/') {
X                        dotdotcounter--;
X                    }
X                }
X                if (dotdotcounter>0) {
X                    error("Can't generate full path name for RCS file");
X                    return RCSfilename;
X                } else {
X                    /* build full path name */
X                    realpathlength=lastpathchar-pathbuf+1;
X                    VOID strncpy(namebuf,pathbuf,realpathlength);
X                    VOID strcpy(&namebuf[realpathlength],realname);
X                    return(namebuf);
X                }
X        }
X}
X
X
X
Xint trydiraccess(filename)
Xchar * filename;
X/* checks write permission in directory of filename and returns
X * true if writable, false otherwise
X */
X{
X        char pathname[NCPPN];
X        register char * tp, *sp, *lp;
X        lp = rindex(filename,'/');
X        if (lp==0) {
X                /* check current directory */
X                if (access(".",2)==0)
X                        return true;
X                else {
X                        error("Current directory not writable");
X                        return false;
X                }
X        }
X        /* copy path */
X        sp=filename;
X        tp=pathname;
X        do *tp++ = *sp++; while (sp<=lp);
X        *tp='\0';
X        if (access(pathname,2)==0)
X                return true;
X        else {
X                error("Directory %s not writable", pathname);
X                return false;
X        }
X}
X
X
X
X#ifndef V4_2BSD
X/* rename() and getwd() will be provided in bsd 4.2 */
X
X
Xint rename(from, to)
Xchar * from, *to;
X/* Function: renames a file with the name given by from to the name given by to.
X * unlinks the to-file if it already exists. returns -1 on error, 0 otherwise.
X */
X{       VOID unlink(to);      /* no need to check return code; will be caught by link*/
X                         /* no harm done if file "to" does not exist            */
X        if (link(from,to)<0) return -1;
X        return(unlink(from));
X}
X
X
X
X#define dot     "."
X#define dotdot  ".."
X
X
X
Xchar * getwd(name)
Xchar * name;
X/* Function: places full pathname of current working directory into name and
X * returns name on success, NULL on failure.
X * getwd is an adaptation of pwd. May not return to the current directory on
X * failure.
X */
X{
X        FILE    *file;
X        struct  stat    d, dd;
X        char buf[2];    /* to NUL-terminate dir.d_name */
X        struct  direct  dir;
X
X        int rdev, rino;
X        int off;
X        register i,j;
X
X        name[off= 0] = '/';
X        name[1] = '\0';
X        buf[0] = '\0';
X        if (stat("/", &d)<0) return NULL;
X        rdev = d.st_dev;
X        rino = d.st_ino;
X        for (;;) {
X                if (stat(dot, &d)<0) return NULL;
X                if (d.st_ino==rino && d.st_dev==rdev) {
X                        if (name[off] == '/') name[off] = '\0';
X                        chdir(name); /*change back to current directory*/
X                        return name;
X                }
X                if ((file = fopen(dotdot,"r")) == NULL) return NULL;
X                if (fstat(fileno(file), &dd)<0) goto fail;
X                chdir(dotdot);
X                if(d.st_dev == dd.st_dev) {
X                        if(d.st_ino == dd.st_ino) {
X                            if (name[off] == '/') name[off] = '\0';
X                            chdir(name); /*change back to current directory*/
X                            VOID fclose(file);
X                            return name;
X                        }
X                        do {
X                            if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
X                                goto fail;
X                        } while (dir.d_ino != d.st_ino);
X                }
X                else do {
X                        if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
X                            goto fail;
X                        }
X                        if (dir.d_ino == 0)
X			    dd.st_ino = d.st_ino + 1;
X                        else if (stat(dir.d_name, &dd) < 0)
X			    goto fail;
X                } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
X                VOID fclose(file);
X
X                /* concatenate file name */
X                i = -1;
X                while (dir.d_name[++i] != 0);
X                for(j=off+1; j>0; --j)
X                        name[j+i+1] = name[j];
X                off=i+off+1;
X                name[i+1] = '/';
X                for(--i; i>=0; --i)
X                        name[i+1] = dir.d_name[i];
X        } /* end for */
X
Xfail:   VOID fclose(file);
X        return NULL;
X}
X
X
X#endif
X
X
X#ifdef PAIRTEST
X/* test program for pairfilenames() and getfullRCSname() */
Xchar * workfilename, *RCSfilename;
Xextern int quietflag;
X
Xmain(argc, argv)
Xint argc; char *argv[];
X{
X        int result;
X        int initflag,tostdout;
X        quietflag=tostdout=initflag=false;
X        cmdid="pair";
X
X        while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
X                switch ((*argv)[1]) {
X
X                case 'p':       tostdout=true;
X                                break;
X                case 'i':       initflag=true;
X                                break;
X                case 'q':       quietflag=true;
X                                break;
X                default:        error("unknown option: %s", *argv);
X                                break;
X                }
X        }
X
X        do {
X                RCSfilename=workfilename=nil;
X                result=pairfilenames(argc,argv,!initflag,tostdout);
X                if (result!=0) {
X                     diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
X                     diagnose("Full RCS file name: %s", getfullRCSname());
X                }
X                switch (result) {
X                        case 0: continue; /* already paired file */
X
X                        case 1: if (initflag) {
X                                    error("RCS file %s exists already",RCSfilename);
X                                } else {
X                                    diagnose("RCS file %s exists",RCSfilename);
X                                }
X                                VOID fclose(finptr);
X                                break;
X
X                        case -1:diagnose("RCS file does not exist");
X                                break;
X                }
X
X        } while (++argv, --argc>=1);
X
X}
X#endif
X@
X
X
X4.8.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d6 1
Xa6 5
X<<<<<<< rcsfnms.c
X rcsid[]= "$Id: rcsfnms.c,v 4.8.1.1 89/08/11 01:42:32 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
X rcsid[]= "$Id: rcsfnms.c,v 1.2 89/09/17 13:35:38 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa44 11
X<<<<<<< rcsfnms.c
X * Revision 4.8.1.1  89/08/11  01:42:32  rsbx
X * Start of cbmvax RCS source branch.
X=======
X * Revision 1.2  89/09/17  13:35:38  rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA).  This version
X * compiles correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X * 
X<<<<<<< rcsfnms.c
Xa45 3
X * checked in with -k by rsbx at 89.08.10.16.20.00.
X * 
X * Revision 4.8  89/05/01  15:09:41  narten
Xa53 8
X=======
X * Revision 1.3  89/09/16  09:43:16  rick
X * Modified AMIGA changes to work with Lattice C
X * 
X * Revision 1.2  88/09/03  15:10:24  rick
X * Port to AmigaDos.  All done with conditional compiles
X * 
X>>>>>>> 1.2
Xd115 2
Xa116 3
X#ifdef AMIGA
X#include "stat.h"
X#else
Xa119 2
X#endif
X#include "rcsbase.h"
Xa120 2
Xextern int errno;
X
Xd201 1
Xa201 9
X{
X	if (fptr == NULL)
X		return;
X#ifdef AMIGA
X	if (ferror(fptr))
X		warn("File read or write error %d; file system full?",errno);
X	fclose(fptr);
X#else
X        if (ferror(fptr) || (fclose(fptr)==EOF))
Xa202 1
X#endif
Xa220 3
X#ifdef AMIGA
X				tp = &semafilename[0];
X#else
Xa222 1
X#endif
Xa299 1
X<<<<<<< rcsfnms.c
Xa301 14
X=======
X        lastfilename++;
X        if ((tp=tfnames[lastfilename])==nil)
X              tp=tfnames[lastfilename] = malloc(NCPPN);
X#ifdef AMIGA
X	*tp = 0;
X	if (fullpath!=nil) {
X		if ((lastslash=rindex(fullpath,'/')) == NULL)
X			lastslash = rindex(fullpath,':');
X		if (lastslash != NULL)
X	                while (fullpath<=lastslash) *tp++ = *fullpath++;
X        }
X#else
X>>>>>>> 1.2
Xa305 1
X#endif
Xa450 1
X#ifndef AMIGA
Xa454 1
X#endif
Xa516 1
X#ifndef AMIGA
Xa521 1
X#endif
Xa612 3
X#ifdef AMIGA
X                return true;
X#else
Xa618 1
X#endif
Xd638 1
Xa638 1
X#ifndef AMIGA
Xa648 1
X#endif
Xa649 3
X#ifdef AMIGA
X#include <libraries/dosextens.h>
X#include <exec/memory.h>
Xa650 3
Xextern struct Process *FindTask();
Xextern struct FileLock *ParentDir(), *Lock();
Xextern char *AllocMem();
Xa651 51
Xchar *followpath(lock,level)
Xstruct FileLock *lock;
Xint		level;
X{
X	struct FileInfoBlock *fib;
X	struct FileLock *newlock;
X	static char pathbuf[NCPPN];
X
X	if (! lock)
X		return(pathbuf);
X	if (level == 0)
X		pathbuf[0] = 0;
X	fib = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CLEAR);
X	if (fib == NULL) {
X		printf("followpath: Out of Memory\n");
X		return(pathbuf);
X		}
X	newlock = ParentDir(lock);
X	followpath(newlock,1);
X	if (Examine(lock,fib)) {
X		if (fib->fib_FileName[0] > ' ')
X			strcat(pathbuf,fib->fib_FileName);
X		else
X			strcat(pathbuf,"RAM");
X		if (newlock == NULL)
X			strcat(pathbuf,":");
X		else
X			strcat(pathbuf,"/");
X		}
X	UnLock(lock);
X	if (fib)
X		FreeMem(fib,(long) sizeof(struct FileInfoBlock));
X	return(pathbuf);
X}
X
Xchar *getwd(name)
Xchar	*name;
X{
X	struct FileLock *oldlock;
X
X	oldlock = Lock("",ACCESS_READ);
X	if (oldlock == NULL)
X		return(NULL);
X	strcpy(name,followpath(oldlock,0));
X	if (name[strlen(name)-1] == '/')
X		name[strlen(name)-1] = 0;
X	return(name);
X}
X
X#else
X
Xa727 1
X#endif
Xa782 33
X}
X#endif
X
X#ifdef AMIGA
Xchar *mktemp(template)
Xchar *template;
X{
X	register char *cp;
X	register unsigned long val;
X
X	cp = template;
X	cp += strlen(cp);
X	for (val = (unsigned long) FindTask(0L) ; ; )
X		if (*--cp == 'X') {
X			*cp = val%10 + '0';
X			val /= 10;
X		} else if (*cp != '.')
X			break;
X
X	if (*++cp != 0) {
X		*cp = 'A';
X		while (access(template, 0) == 0) {
X			if (*cp == 'Z') {
X				*template = 0;
X				break;
X			}
X			++*cp;
X		}
X	} else {
X		if (access(template, 0) == 0)
X			*template = 0;
X	}
X	return template;
X@
X
X
X4.8.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d6 5
Xa10 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.1 89/10/13 19:18:32 rsbx Exp Locker: rsbx $ Purdue CS";
Xd49 1
Xa49 3
X * Revision 4.8.2.1  89/10/13  19:18:32  rsbx
X * Start of Amiga RCS port branch.
X * 
Xd52 6
Xd59 1
Xd72 8
Xd276 1
Xa276 1
X        *tp++ = ','; *tp = '\0'; /* will be the same length as RCSname*/
Xd344 1
Xd347 4
Xd360 1
Xd499 1
Xa499 1
X                *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp='\0';
Xa719 1
X#ifdef RICKS
Xa774 10
X#else
Xchar *getwd(char *name)
X	{
X	if (getcd(0, name) == 0)
X		{
X		return name;
X		}
X	return NULL;
X	}
X#endif RICKS
X@
X
X
X4.8.2.3
Xlog
X@More changes to make Amiga port work.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.2 89/10/15 15:44:18 rsbx Exp $ Purdue CS";
Xa44 4
X * Revision 4.8.2.2  89/10/15  15:44:18  rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X * 
Xd245 1
Xa245 1
X		tp = &semafilename[0];
Xa260 5
X#ifdef DEBUG
X	fprintf(stderr,"semafilename = %%%s%%\n", semafilename);
X	fflush(stderr);
X#endif
X
Xd529 1
Xd549 1
Xa549 21
X				struct stat pdirstat;
X
X				if (stat(prefdir,&pdirstat))
X					{
X					RCSfilename=sub2filename;
X					}
X				else
X					{
X#ifdef AMIGA
X					if (pdirstat.st_type > 0)
X#else
X					if ((pdirstat.st_mode & S_IFMT) != S_IFREG)
X#endif
X						{
X						RCSfilename = sub1filename;
X						}
X					else
X						{
X						RCSfilename = sub2filename;
X						}
X					}
X@
X
X
X4.8.2.4
Xlog
X@Changed file path handling to deal with Amiga file path sematics.
X@
Xtext
X@d2 1
Xa2 1
X *		     RCS file name handling
Xd6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.3 89/10/15 18:27:52 rsbx Exp $ Purdue CS";
Xd9 4
Xa12 4
X *		     creation and deletion of semaphorefile,
X *		     creation of temporary filenames and cleanup()
X *		     pairing of RCS file names and working file names.
X *		     Testprogram: define PAIRTEST
Xa44 3
X * Revision 4.8.2.3  89/10/15  18:27:52  rsbx
X * More changes to make Amiga port work.
X * 
Xd171 1
Xa171 1
X	"c",   " * ",   /* C           */
Xd173 5
Xa177 5
X	"e",   "# ",    /* efl         */
X	"f",   "c ",    /* fortran     */
X	"h",   " * ",   /* C-header    */
X	"l",   " * ",   /* lex         NOTE: conflict between lex and franzlisp*/
X	"mac", "; ",    /* macro       vms or dec-20 or pdp-11 macro */
Xd181 1
Xa181 1
X	"p",   " * ",   /* pascal      */
Xd183 2
Xa184 2
X	"r",   "# ",    /* ratfor      */
X	"red", "% ",    /* psl/rlisp   */
Xd187 1
Xa187 1
X	"s",   "! ",    /* assembler   */
Xd190 1
Xa190 1
X	"s",   "| ",    /* assembler   */
Xd193 1
Xa193 1
X	"s",   "/ ",    /* assembler   */
Xd196 1
Xa196 1
X	"s",   "# ",    /* assembler   */
Xa197 4
X#ifdef AMIGA
X	"asm", "* ",	/* assembler   */
X	"i",   "* ",	/* assembler include */
X#endif
Xd199 6
Xa204 6
X	"sh",  "# ",    /* shell       */
X	"sl",  "% ",    /* psl         */
X	"red", "% ",    /* psl/rlisp   */
X	"cl",  ";;; ",  /* common lisp   */
X	"ml",  "; ",    /* mocklisp    */
X	"el",  "; ",    /* gnulisp     */
Xd206 5
Xa210 5
X	"y",   " * ",   /* yacc        */
X	"ye",  " * ",   /* yacc-efl    */
X	"yr",  " * ",   /* yacc-ratfor */
X	"",    "# ",    /* default for empty suffix */
X	nil,   ""       /* default for unknown suffix; must always be last */
Xd227 2
Xa228 2
X	if (ferror(fptr) || (fclose(fptr)==EOF))
X		faterror("File read or write error; file system full?");
Xd242 2
Xa243 2
X	register char * tp, *sp, *lp;
X	int fdesc;
Xd245 3
Xa247 1
X	sp=RCSname;
Xa248 17
X	if (lp = index(sp,':'))			/* volume: ? */
X		{
X		if (tp = rindex(lp,'/'))	/* volume:path/ ? */
X			{
X			lp = tp;
X			}
X		}
X	else
X		{
X		lp = rindex(sp,'/');
X		}
X#else
X	lp = rindex(sp,'/');
X#endif
X
X	if (lp==0) {
X#ifdef AMIGA
Xd251 2
Xa252 2
X		semafilename[0]='.'; semafilename[1]='/';
X		tp= &semafilename[2];
Xd254 10
Xa263 10
X	} else {
X		/* copy path */
X		tp=semafilename;
X		do *tp++ = *sp++; while (sp<=lp);
X	}
X	/*now insert `,' and append file name */
X	*tp++ = ',';
X	lp = rindex(sp, RCSSEP);
X	while (sp<lp) *tp++ = *sp++;
X	*tp++ = ','; *tp = '\0'; /* will be the same length as RCSname*/
Xd270 14
Xa283 14
X	madesema = false;
X	if (access(semafilename, 0) == 0) {
X		error("RCS file %s is in use",RCSname);
X		return false;
X	}
X	if (makesema) {
X		if ((fdesc=creat(semafilename, 000)) == -1) {
X			error("Can't create semaphore file for RCS file %s",RCSname);
X			return false;
X		}
X		VOID close(fdesc);
X		madesema=true;
X	}
X	return true;
Xd292 7
Xa298 7
X	if (madesema) {
X		madesema=false;
X		if (unlink(semafilename) == -1) {
X			error("Can't find semaphore file %s",semafilename);
X		}
X	}
X}
Xd312 1
Xa312 1
X	register int i;
Xd314 7
Xa320 7
X	if (finptr!=NULL)   VOID fclose(finptr);
X	if (frewrite!=NULL) VOID fclose(frewrite);
X	for (i=0; i<freefilename; i++) {
X		if (tfnames[i][0]!='\0')  VOID unlink(tfnames[i]);
X	}
X	InitCleanup();
X	rmsema();
Xd335 3
Xa337 3
X	register char * lastslash, *tp;
X	if ((tp=tfnames[freefilename])==nil)
X		tp=tfnames[freefilename] = talloc(NCPPN);
Xd344 2
Xa345 2
X			while (fullpath<=lastslash) *tp++ = *fullpath++;
X	}
Xd347 4
Xa350 4
X	if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
X		/* copy path */
X		while (fullpath<=lastslash) *tp++ = *fullpath++;
X	}
Xd352 2
Xa353 2
X	while (*tp++ = *filename++);
X	return (mktemp(tfnames[freefilename++]));
Xd366 5
Xa370 5
X	r = sp;
X	while (*sp) {
X		if (*sp++ == c) r=sp;
X	}
X	return r;
Xa375 7
X#ifdef AMIGA
Xchar * fnamepart(char *sp)
X/*
X * Function: Finds the filename part of a path.
X */
X	{
X	char *p1;
Xa376 23
X	if (p1 = bindex(sp,':'))		/* volume: ? */
X		{
X		return bindex(p1, '/');
X		}
X	else
X		{
X		return bindex(sp,'/');
X		}
X
X	}
X#else
Xchar * fnamepart(char *sp)
X/*
X * Function: Finds the filename part of a path.
X */
X	{
X	return bindex(sp, '/');
X	}
X#endif
X
X
X
X
Xd380 1
Xa380 1
X	register int i;
Xd382 2
Xa383 2
X	Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
X	StrictLocks=STRICT_LOCKING;
Xd385 14
Xa398 14
X	/* guess the comment leader from the suffix*/
X	Suffix=bindex(workfilename, '.');
X	if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
X	for (i=0;;i++) {
X		if (comtable[i].suffix==nil) {
X			Comment=comtable[i].comlead; /*default*/
X			break;
X		} elsif (strcmp(Suffix,comtable[i].suffix)==0) {
X			Comment=comtable[i].comlead; /*default*/
X			break;
X		}
X	}
X	Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
X}
Xd410 2
Xa411 2
X	register char * * next, * match;
X	register int count;
Xd413 10
Xa422 10
X	for (next = argv, count = argc; count>0; next++,count--) {
X		if ((*next != nil) && strcmp(fnamepart(*next),fname)==0) {
X			/* fnamepart finds the beginning of the file name stem */
X			match= *next;
X			*next=nil;
X			return match;
X		}
X	}
X	return fname;
X}
Xd450 4
Xa453 4
X	register char * sp, * tp;
X	char * lastsep, * purefname, * pureRCSname;
X	int opened, returncode;
X	char * RCS1;
Xd456 1
Xa456 1
X	if (*argv == nil) return 0; /* already paired filename */
Xd462 1
Xa462 1
X	InitCleanup();
Xd464 38
Xa501 38
X	/* first check suffix to see whether it is an RCS file or not */
X	purefname=fnamepart(*argv); /* skip path */
X	lastsep=rindex(purefname, RCSSEP);
X	if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
X		/* RCS file name given*/
X		RCS1=(*argv); pureRCSname=purefname;
X		/* derive workfilename*/
X		sp = purefname; tp=tempfilename;
X		while (sp<lastsep) *tp++ = *sp++; *tp='\0';
X		/* try to find workfile name among arguments */
X		workfilename=findpairfile(argc-1,argv+1,tempfilename);
X		if (strlen(pureRCSname)>NCPFN) {
X			error("RCS file name %s too long",RCS1);
X			return 0;
X		}
X	} else {
X		/* working file given; now try to find RCS file */
X		workfilename= *argv;
X		/* derive RCS file name*/
X		sp=purefname; tp=tempfilename;
X		while (*tp++ = *sp++);
X		*(tp-1)=RCSSEP; *tp++=RCSSUF; *tp='\0';
X		/* Try to find RCS file name among arguments*/
X		RCS1=findpairfile(argc-1,argv+1,tempfilename);
X		pureRCSname=fnamepart(RCS1);
X		if (strlen(pureRCSname)>NCPFN) {
X			error("working file name %s too long",workfilename);
X			return 0;
X		}
X	}
X	/* now we have a (tentative) RCS filename in RCS1 and workfilename  */
X	/* First, get status of workfilename */
X	haveworkstat=stat(workfilename, &workstat);
X#ifdef TODO
X	if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
X		diagnose("Directory %s ignored",workfilename);
X		return 0;
X	}
Xd503 20
Xa522 20
X	/* Second, try to find the right RCS file */
X	if (pureRCSname!=RCS1) {
X		/* a path for RCSfile is given; single RCS file to look for */
X		finptr=fopen(RCSfilename=RCS1, "r");
X		if (finptr!=NULL) {
X			returncode=1;
X		} else { /* could not open */
X			if (access(RCSfilename,0)==0) {
X				error("Can't open existing %s", RCSfilename);
X				return 0;
X			}
X			if (mustread) {
X				error("Can't find %s", RCSfilename);
X				return 0;
X			} else {
X				/* initialize if not mustread */
X				returncode = -1;
X			}
X		}
X	} else {
Xd538 1
Xa538 1
X		opened=(
Xd542 5
Xa546 5
X		if (opened) {
X			/* open succeeded */
X			returncode=1;
X		} else {
X			/* open failed; may be read protected */
Xd549 4
Xa552 4
X				error("Can't open existing %s",RCSfilename);
X				return 0;
X			}
X			if (mustread) {
Xd554 3
Xa556 3
X				return 0;
X			} else {
X				/* initialize new file. Put into ./RCS if possible, strip off suffix*/
Xd559 2
Xa560 1
X				if (stat(prefdir,&pdirstat)) {
Xd562 3
Xa564 1
X				} else {
Xd566 1
Xa566 1
X					if (pdirstat.st_type > 0) {
Xd568 1
Xa568 1
X					if ((pdirstat.st_mode & S_IFMT) != S_IFREG) {
Xd570 1
Xd572 3
Xa574 1
X					} else {
Xd576 1
Xd578 4
Xa581 5
X				}
X				returncode= -1;
X			}
X		}
X	}
Xd583 7
Xa589 7
X	if (returncode == 1) { /* RCS file open */
X#ifdef TODO
X		haveRCSstat=fstat(fileno(finptr),&RCSstat);
X		if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
X			diagnose("Directory %s ignored",RCSfilename);
X			return 0;
X		}
Xd591 5
Xa595 5
X		Lexinit(); getadmin();
X	} else {  /* returncode == -1; RCS file nonexisting */
X		haveRCSstat = -1;
X		InitAdmin();
X	};
Xd597 5
Xa601 5
X	if (tostdout&&
X	    !(RCS1==tempfilename||workfilename==tempfilename))
X		/*The last term determines whether a pair of        */
X		/* file names was given in the argument list        */
X		warn("Option -p is set; ignoring output file %s",workfilename);
Xd603 1
Xa603 1
X	return returncode;
Xd613 2
Xa614 2
X	static char namebuf[NCPPN];
X	static int  pathlength;
Xd616 2
Xa617 2
X	register char * realname, * lastpathchar;
X	register int  dotdotcounter, realpathlength;
Xd619 49
Xa667 49
X	if (*RCSfilename=='/') {
X		return(RCSfilename);
X	} else {
X		if (pathlength==0) { /*call curdir for the first time*/
X			if (getwd(pathbuf)==NULL)
X				faterror("Can't build current directory path");
X			pathlength=strlen(pathbuf);
X			if (!((pathlength==1) && (pathbuf[0]=='/'))) {
X				pathbuf[pathlength++]='/';
X				/* Check needed because some getwd implementations */
X				/* generate "/" for the root.                      */
X			}
X		}
X		/*the following must be redone since RCSfilename may change*/
X		/* find how many ../ to remvove from RCSfilename */
X		dotdotcounter =0;
X		realname = RCSfilename;
X		while( realname[0]=='.' &&
X		      (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
X			if (realname[1]=='/') {
X				/* drop leading ./ */
X				realname += 2;
X			} else {
X				/* drop leading ../ and remember */
X				dotdotcounter++;
X				realname += 3;
X			}
X		}
X		/* now remove dotdotcounter trailing directories from pathbuf*/
X		lastpathchar=pathbuf + pathlength-1;
X		while (dotdotcounter>0 && lastpathchar>pathbuf) {
X			/* move pointer backwards over trailing directory */
X			lastpathchar--;
X			if (*lastpathchar=='/') {
X				dotdotcounter--;
X			}
X		}
X		if (dotdotcounter>0) {
X			error("Can't generate full path name for RCS file");
X			return RCSfilename;
X		} else {
X			/* build full path name */
X			realpathlength=lastpathchar-pathbuf+1;
X			VOID strncpy(namebuf,pathbuf,realpathlength);
X			VOID strcpy(&namebuf[realpathlength],realname);
X			return(namebuf);
X		}
X	}
X}
Xd677 5
Xa681 5
X	char pathname[NCPPN];
X	register char * tp, *sp, *lp;
X	lp = rindex(filename,'/');
X	if (lp==0) {
X		/* check current directory */
Xd683 1
Xa683 1
X		return true;
Xd685 6
Xa690 6
X		if (access(".",2)==0)
X			return true;
X		else {
X			error("Current directory not writable");
X			return false;
X		}
Xd692 12
Xa703 12
X	}
X	/* copy path */
X	sp=filename;
X	tp=pathname;
X	do *tp++ = *sp++; while (sp<=lp);
X	*tp='\0';
X	if (access(pathname,2)==0)
X		return true;
X	else {
X		error("Directory %s not writable", pathname);
X		return false;
X	}
Xd718 3
Xa720 3
X			 /* no harm done if file "to" does not exist            */
X	if (link(from,to)<0) return -1;
X	return(unlink(from));
Xd807 4
Xa810 4
X	FILE    *file;
X	struct  stat    d, dd;
X	char buf[2];    /* to NUL-terminate dir.d_name */
X	struct  direct  dir;
Xd812 3
Xa814 3
X	int rdev, rino;
X	int off;
X	register i,j;
Xd816 38
Xa853 38
X	name[off= 0] = '/';
X	name[1] = '\0';
X	buf[0] = '\0';
X	if (stat("/", &d)<0) return NULL;
X	rdev = d.st_dev;
X	rino = d.st_ino;
X	for (;;) {
X		if (stat(dot, &d)<0) return NULL;
X		if (d.st_ino==rino && d.st_dev==rdev) {
X			if (name[off] == '/') name[off] = '\0';
X			chdir(name); /*change back to current directory*/
X			return name;
X		}
X		if ((file = fopen(dotdot,"r")) == NULL) return NULL;
X		if (fstat(fileno(file), &dd)<0) goto fail;
X		chdir(dotdot);
X		if(d.st_dev == dd.st_dev) {
X			if(d.st_ino == dd.st_ino) {
X				if (name[off] == '/') name[off] = '\0';
X				chdir(name); /*change back to current directory*/
X				VOID fclose(file);
X				return name;
X			}
X			do {
X				if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
X					goto fail;
X			} while (dir.d_ino != d.st_ino);
X		}
X		else do {
X			if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
X				goto fail;
X			}
X			if (dir.d_ino == 0)
X				dd.st_ino = d.st_ino + 1;
X			else if (stat(dir.d_name, &dd) < 0)
X				goto fail;
X		} while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
X		VOID fclose(file);
Xd855 10
Xa864 10
X		/* concatenate file name */
X		i = -1;
X		while (dir.d_name[++i] != 0);
X		for(j=off+1; j>0; --j)
X			name[j+i+1] = name[j];
X		off=i+off+1;
X		name[i+1] = '/';
X		for(--i; i>=0; --i)
X			name[i+1] = dir.d_name[i];
X	} /* end for */
Xd867 1
Xa867 1
X	return NULL;
Xd883 4
Xa886 4
X	int result;
X	int initflag,tostdout;
X	quietflag=tostdout=initflag=false;
X	cmdid="pair";
Xd888 2
Xa889 2
X	while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
X		switch ((*argv)[1]) {
Xd891 10
Xa900 10
X		case 'p':       tostdout=true;
X				break;
X		case 'i':       initflag=true;
X				break;
X		case 'q':       quietflag=true;
X				break;
X		default:	error("unknown option: %s", *argv);
X				break;
X		}
X	}
Xd902 9
Xa910 9
X	do {
X		RCSfilename=workfilename=nil;
X		result=pairfilenames(argc,argv,!initflag,tostdout);
X		if (result!=0) {
X			diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
X			diagnose("Full RCS file name: %s", getfullRCSname());
X		}
X		switch (result) {
X			case 0: continue; /* already paired file */
Xd912 7
Xa918 7
X			case 1: if (initflag) {
X					error("RCS file %s exists already",RCSfilename);
X				} else {
X					diagnose("RCS file %s exists",RCSfilename);
X				}
X				VOID fclose(finptr);
X				break;
Xd920 3
Xa922 3
X			case -1:diagnose("RCS file does not exist");
X				break;
X		}
Xd924 1
Xa924 1
X	} while (++argv, --argc>=1);
X@
X
X
X4.8.2.5
Xlog
X@Removed some debugging code.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.4 89/10/16 19:07:19 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.4  89/10/16  19:07:19  rsbx
X * Changed file path handling to deal with Amiga file path sematics.
X * 
Xd286 5
X@
X
X
X4.8.2.6
Xlog
X@Fix to fnamepart().
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.5 89/10/16 23:54:04 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.5  89/10/16  23:54:04  rsbx
X * Removed some debugging code.
X * 
Xd404 1
Xa404 1
X	if (p1 = strchr(sp,':'))		/* volume: ? */
Xa405 1
X		p1++;
X@
X
X
X4.8.2.7
Xlog
X@getfullRCSname() fixed up.
X@
Xtext
X@a152 3
X#ifdef AMIGA
Xchar * getfullRCSname();
X#endif
Xa654 1
X#ifndef AMIGA
Xa715 1
X#endif
Xd770 71
X@
X
X
X4.8.2.8
Xlog
X@mktemp() changed to use hex digits instead of decimal digits in temp
Xfile name.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.7 89/10/17 18:38:55 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.7  89/10/17  18:38:55  rsbx
X * getfullRCSname() fixed up.
X * 
Xd912 5
Xa916 1
Xstatic char *hex = "0123456789abcdef";
Xa917 5
Xchar *mktemp(char *template)
X	{
X	char *cp;
X	unsigned long val;
X
Xa920 1
X		{
Xd922 3
Xa924 7
X			*cp = hex[val%16];
X			val /= 16;
X		}
X	else
X		{
X		if (*cp != '.')
X			{
Xa925 2
X			}
X		}
Xd927 1
Xa927 2
X	if (*++cp != 0)
X		{
Xd929 2
Xa930 4
X		while (access(template, 0) == 0)
X			{
X			if (*cp == 'Z')
X				{
Xd933 1
Xa933 1
X				}
Xa934 1
X			}
Xd936 1
Xa936 2
X	else
X		{
Xa937 1
X			{
Xd939 1
Xa939 2
X			}
X		}
Xd941 1
Xa941 1
X	}
X@
X
X
X4.8.2.9
Xlog
X@Previous changes to mktemp() had syntax errors.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.8 89/10/30 13:44:29 rsbx Exp $ Purdue CS";
Xa44 4
X * Revision 4.8.2.8  89/10/30  13:44:29  rsbx
X * mktemp() changed to use hex digits instead of decimal digits in temp
X * file name.
X * 
Xd926 1
Xa926 2
X		if (*--cp == 'X')
X			{
Xd929 4
Xa932 2
X			}
X		else
Xd934 1
Xa934 4
X			if (*cp != '.')
X				{
X				break;
X				}
X@
X
X
X4.8.2.10
Xlog
X@Changes to make the delete bit to track the write bit. Made protection
Xbit manipulation less insane.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.9 89/10/30 13:53:10 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.9  89/10/30  13:53:10  rsbx
X * Previous changes to mktemp() had syntax errors.
X * 
Xa641 1
X		haveRCSstat=stat(RCSfilename,&RCSstat);
Xd643 1
X@
X
X
X4.8.2.11
Xlog
X@Added support for RCS_link files to be used as a poor O/S's symbolic link.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.10 89/11/01 14:43:14 rsbx Exp $ Purdue CS";
Xa44 4
X * Revision 4.8.2.10  89/11/01  14:43:14  rsbx
X * Changes to make the delete bit to track the write bit. Made protection
X * bit manipulation less insane.
X * 
Xa176 3
X#ifdef LINK
Xchar sub3filename [NCPPN];     /* used for files path/RCS/file.sfx,v        */
X#endif /* LINK */
Xa521 3
X#ifdef LINK
X	char prefdir2[NCPPN];
X#endif /* LINK */
Xa592 13
X#ifdef LINK
X		FILE *symbolic_link_file = NULL;
X		sub3filename[0]='\0';
X		if ( access( "RCS_link", 0 ) == 0 )
X			symbolic_link_file = fopen( "RCS_link", "r" );
X		if ( symbolic_link_file ){
X			int sl;
X			fgets( sub3filename, NCPPN, symbolic_link_file );
X			fclose( symbolic_link_file );
X			sl = strlen(sub3filename);
X			sub3filename[sl?sl-1:0] = '\0';
X		}
X#endif /* LINK */
Xa601 5
X#ifdef LINK
X		prefdir2[0] = '\0';
X		if ( sub3filename[0] )
X			VOID strcpy(prefdir2,sub3filename); /* preferred directory for RCS file*/
X#endif /* LINK */
Xd603 1
Xa603 5
X		VOID strcat(sub1filename,RCS1);
X		VOID strcat(sub2filename,RCS1);
X#ifdef LINK
X		VOID strcat(sub3filename,RCS1);
X#endif /* LINK */
Xa604 1
X
Xd607 1
Xa607 6
X#ifdef LINK
X		((finptr=fopen(RCSfilename=sub2filename, "r"))!=NULL) ||
X		(sub3filename[0] && ((finptr=fopen(RCSfilename=sub3filename, "r"))!=NULL)));
X#else
X		((finptr=fopen(RCSfilename=sub2filename, "r"))!=NULL) );
X#endif /* LINK */
Xa614 4
X#ifdef LINK
X			    (access(RCSfilename=sub2filename,0)==0) ||
X			    (sub3filename[0] &&	(access(RCSfilename=sub3filename,0)==0))){
X#else
Xa615 1
X#endif /* LINK */
Xa619 6
X#ifdef LINK
X				if ( sub3filename[0] )
X					error("Can't find %s, %s nor %s",sub1filename,sub2filename,sub3filename);
X				else
X					error("Can't find %s nor %s",sub1filename,sub2filename);
X#else
Xa620 1
X#endif /* LINK */
Xa625 19
X#ifdef LINK
X#ifdef AMIGA
X				if (!stat(prefdir, &pdirstat) && (pdirstat.st_type > 0)) {
X#else
X				if (!stat(prefdir, &pdirstat) && ((pdirstat.st_mode & S_IFMT) != S_IFREG)) {
X#endif
X					RCSfilename = sub1filename;
X				} else {
X#ifdef AMIGA
X					if (!stat(prefdir2, &pdirstat) && (pdirstat.st_type > 0)) {
X#else
X					if (!stat(prefdir2, &pdirstat) && ((pdirstat.st_mode & S_IFMT) != S_IFREG)) {
X#endif
X						RCSfilename = sub3filename;
X					} else {
X						RCSfilename = sub2filename;
X					}
X				}
X#else
Xa638 1
X#endif /* LINK */
X@
X
X
X4.8.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a45 3
X * checked in with -k by rsbx at 89.08.10.16.20.00.
X * 
X * Revision 4.8  89/05/01  15:09:41  narten
X@
SHAR_EOF
echo "End of archive 9 (of 14)"
# if you want to concatenate archives, remove anything after this line
exit