⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 co.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
                        if (!rmworkfile()) continue;                /* skip description */                getdesc(false); /* don't echo*/		locker_expansion = 0 < lockflag;		joinfilename = buildrevision(			gendeltas, targetdelta,			join&&tostdout ? (FILE*)0 : neworkptr,			Expand!=OLD_EXPAND		);#		if !large_memory			if (fcopy == neworkptr)				fcopy = 0;  /* Don't close it twice.  */#		endif		if_advise_access(changelock && gendeltas->first!=targetdelta,			finptr, MADV_SEQUENTIAL		);		if (!donerewrite(changelock))			continue;		newdate = targetdelta->date;		if (join) {			newdate = 0;			if (!joinfilename) {				aflush(neworkptr);				joinfilename = neworkfilename;			}			if (!buildjoin(joinfilename))				continue;		}        }	if (!tostdout) {	    r = 0;	    if (mtimeflag && newdate) {		if (!join)		    aflush(neworkptr);		r = setfiledate(neworkfilename, newdate);	    }	    if (r == 0) {		ignoreints();		r = chnamemod(&neworkptr, neworkfilename, workfilename,		  WORKMODE(RCSstat.st_mode,		    !(Expand==VAL_EXPAND || lockflag<=0&&StrictLocks)		  )		);		keepdirtemp(neworkfilename);		restoreints();	    }	    if (r != 0) {		eerror(workfilename);		error("see %s", neworkfilename);		continue;	    }	    diagnose("done\n");	}        } while (cleanup(),                 ++argv, --argc >=1);	tempunlink();	Ofclose(workstdout);	exitmain(exitstatus);}       /* end of main (co) */	static voidcleanup(){	if (nerror) exitstatus = EXIT_FAILURE;	Izclose(&finptr);	Ozclose(&frewrite);#	if !large_memory		if (fcopy!=workstdout) Ozclose(&fcopy);#	endif	if (neworkptr!=workstdout) Ozclose(&neworkptr);	dirtempunlink();}#if lint#	define exiterr coExit#endif	exiting voidexiterr(){	dirtempunlink();	tempunlink();	_exit(EXIT_FAILURE);}/***************************************************************** * The following routines are auxiliary routines *****************************************************************/	static intrmworkfile()/* Function: prepares to remove workfilename, if it exists, and if * it is read-only. * Otherwise (file writable): *   if !quietmode asks the user whether to really delete it (default: fail); *   otherwise failure. * Returns true if permission is gotten. */{	if (workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH) && !forceflag) {	    /* File is writable */	    if (!yesorno(false, "writable %s exists%s; remove it? [ny](n): ",			workfilename,			myself(workstat.st_uid) ? "" : ", and you do not own it"	    )) {		error(!quietflag && ttystdin()			? "checkout aborted"			: "writable %s exists; checkout aborted", workfilename);		return false;            }        }	/* Actual unlink is done later by caller. */	return true;}	static intrmlock(delta)	struct hshentry const *delta;/* Function: removes the lock held by caller on delta. * Returns -1 if someone else holds the lock, * 0 if there is no lock on delta, * and 1 if a lock was found and removed. */{       register struct lock * next, * trail;	char const *num;        struct lock dummy;        int whomatch, nummatch;        num=delta->num;        dummy.nextlock=next=Locks;        trail = &dummy;        while (next!=nil) {		whomatch = strcmp(getcaller(), next->login);                nummatch=strcmp(num,next->delta->num);                if ((whomatch==0) && (nummatch==0)) break;			/*found a lock on delta by caller*/                if ((whomatch!=0)&&(nummatch==0)) {                    error("revision %s locked by %s; use co -r or rcs -u",num,next->login);                    return -1;                }                trail=next;                next=next->nextlock;        }        if (next!=nil) {                /*found one; delete it */                trail->nextlock=next->nextlock;                Locks=dummy.nextlock;                next->delta->lockedby=nil; /* reset locked-by */                return 1; /*success*/        } else  return 0; /*no lock on delta*/}/***************************************************************** * The rest of the routines are for handling joins *****************************************************************/	static char const *addjoin(joinrev)	char *joinrev;/* Add joinrev's number to joinlist, yielding address of char past joinrev, * or nil if no such revision exists. */{	register char *j;	register struct hshentry const *d;	char terminator;	struct buf numrev;	struct hshentries *joindeltas;	j = joinrev;	for (;;) {	    switch (*j++) {		default:		    continue;		case 0:		case ' ': case '\t': case '\n':		case ':': case ',': case ';':		    break;	    }	    break;	}	terminator = *--j;	*j = 0;	bufautobegin(&numrev);	d = 0;	if (expandsym(joinrev, &numrev))	    d = genrevs(numrev.string,(char*)nil,(char*)nil,(char*)nil,&joindeltas);	bufautoend(&numrev);	*j = terminator;	if (d) {		joinlist[++lastjoin] = d->num;		return j;	}	return nil;}	static intpreparejoin()/* Function: Parses a join list pointed to by join and places pointers to the * revision numbers into joinlist. */{	register char const *j;        j=join;        lastjoin= -1;        for (;;) {                while ((*j==' ')||(*j=='\t')||(*j==',')) j++;                if (*j=='\0') break;                if (lastjoin>=joinlength-2) {                        error("too many joins");                        return(false);                }		if (!(j = addjoin(j))) return false;                while ((*j==' ') || (*j=='\t')) j++;                if (*j == ':') {                        j++;                        while((*j==' ') || (*j=='\t')) j++;                        if (*j!='\0') {				if (!(j = addjoin(j))) return false;                        } else {                                error("join pair incomplete");                                return false;                        }                } else {                        if (lastjoin==0) { /* first pair */                                /* common ancestor missing */                                joinlist[1]=joinlist[0];                                lastjoin=1;                                /*derive common ancestor*/				if (!(joinlist[0] = getancestor(targetdelta->num,joinlist[1])))                                       return false;                        } else {                                error("join pair incomplete");                                return false;                        }                }        }        if (lastjoin<1) {                error("empty join");                return false;        } else  return true;}	static char const *getancestor(r1, r2)	char const *r1, *r2;/* Yield the common ancestor of r1 and r2 if successful, nil otherwise. * Work reliably only if r1 and r2 are not branch numbers. */{	static struct buf t1, t2;	unsigned l1, l2, l3;	char const *r;	l1 = countnumflds(r1);	l2 = countnumflds(r2);	if ((2<l1 || 2<l2)  &&  cmpnum(r1,r2)!=0) {	    /* not on main trunk or identical */	    l3 = 0;	    while (cmpnumfld(r1, r2, l3+1)==0 && cmpnumfld(r1, r2, l3+2)==0)		l3 += 2;	    /* This will terminate since r1 and r2 are not the same; see above. */	    if (l3==0) {		/* no common prefix; common ancestor on main trunk */		VOID partialno(&t1, r1, l1>2 ? (unsigned)2 : l1);		VOID partialno(&t2, r2, l2>2 ? (unsigned)2 : l2);		r = cmpnum(t1.string,t2.string)<0 ? t1.string : t2.string;		if (cmpnum(r,r1)!=0 && cmpnum(r,r2)!=0)			return r;	    } else if (cmpnumfld(r1, r2, l3+1)!=0)			return partialno(&t1,r1,l3);	}	error("common ancestor of %s and %s undefined", r1, r2);	return nil;}	static intbuildjoin(initialfile)	char const *initialfile;/* Function: merge pairs of elements in joinlist into initialfile * If workstdout is set, copy result to stdout. * All unlinking of initialfile, rev2, and rev3 should be done by tempunlink(). */{	struct buf commarg;	struct buf subs;	char const *rev2, *rev3;        int i;	char const *cov[10], *mergev[12];	char const **p;	bufautobegin(&commarg);	bufautobegin(&subs);	rev2 = maketemp(0);	rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */	cov[0] = nil;	/* cov[1] setup below */	cov[2] = CO;	/* cov[3] setup below */	p = &cov[4];	if (expandarg) *p++ = expandarg;	if (suffixarg) *p++ = suffixarg;	if (versionarg) *p++ = versionarg;	*p++ = quietarg;	*p++ = RCSfilename;	*p = nil;	mergev[0] = nil;	mergev[1] = nil;	mergev[2] = MERGE;	mergev[3] = mergev[5] = "-L";	/* rest of mergev setup below */        i=0;        while (i<lastjoin) {                /*prepare marker for merge*/                if (i==0)			bufscpy(&subs, targetdelta->num);		else {			bufscat(&subs, ",");			bufscat(&subs, joinlist[i-2]);			bufscat(&subs, ":");			bufscat(&subs, joinlist[i-1]);		}		diagnose("revision %s\n",joinlist[i]);		bufscpy(&commarg, "-p");		bufscat(&commarg, joinlist[i]);		cov[1] = rev2;		cov[3] = commarg.string;		if (runv(cov))			goto badmerge;		diagnose("revision %s\n",joinlist[i+1]);		bufscpy(&commarg, "-p");		bufscat(&commarg, joinlist[i+1]);		cov[1] = rev3;		cov[3] = commarg.string;		if (runv(cov))			goto badmerge;		diagnose("merging...\n");		mergev[4] = subs.string;		mergev[6] = joinlist[i+1];		p = &mergev[7];		if (quietflag) *p++ = quietarg;		if (lastjoin<=i+2 && workstdout) *p++ = "-p";		*p++ = initialfile;		*p++ = rev2;		*p++ = rev3;		*p = nil;		switch (runv(mergev)) {		    case DIFF_FAILURE: case DIFF_SUCCESS:			break;		    default:			goto badmerge;		}                i=i+2;        }	bufautoend(&commarg);	bufautoend(&subs);        return true;    badmerge:	nerror++;	bufautoend(&commarg);	bufautoend(&subs);	return false;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -