MFC - tracking commit

This commit is contained in:
Mark Murray 2013-10-09 17:41:47 +00:00
commit 371cbaafa8
154 changed files with 28070 additions and 1528 deletions

View file

@ -38,29 +38,6 @@
# xargs -n1 | sort | uniq -d;
# done
# 20131015: removal of RCS from base
OLD_FILES+=usr/bin/ci
OLD_FILES+=usr/bin/co
OLD_FILES+=usr/bin/ident
OLD_FILES+=usr/bin/merge
OLD_FILES+=usr/bin/rcs
OLD_FILES+=usr/bin/rcsclean
OLD_FILES+=usr/bin/rcsdiff
OLD_FILES+=usr/bin/rcsfreeze
OLD_FILES+=usr/bin/rcsmerge
OLD_FILES+=usr/bin/rlog
OLD_FILES+=usr/share/man/man1/ci.1.gz
OLD_FILES+=usr/share/man/man1/co.1.gz
OLD_FILES+=usr/share/man/man1/ident.1.gz
OLD_FILES+=usr/share/man/man1/merge.1.gz
OLD_FILES+=usr/share/man/man1/rcs.1.gz
OLD_FILES+=usr/share/man/man1/rcsclean.1.gz
OLD_FILES+=usr/share/man/man1/rcsdiff.1.gz
OLD_FILES+=usr/share/man/man1/rcsfreeze.1.gz
OLD_FILES+=usr/share/man/man1/rcsintro.1.gz
OLD_FILES+=usr/share/man/man1/rcsmerge.1.gz
OLD_FILES+=usr/share/man/man1/rlog.1.gz
OLD_FILES+=usr/share/man/man5/rcsfile.5.gz
# 20131001: ar and ranlib from binutils not used
OLD_FILES+=usr/bin/gnu-ar
OLD_FILES+=usr/bin/gnu-ranlib

View file

@ -31,10 +31,6 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
20131006:
RCS has been removed from the base system. If you need RCS
install either devel/rcs or devel/rcs57.
20130930:
BIND has been removed from the base system. If all you need
is a local resolver, simply enable and start the local_unbound

View file

@ -12,6 +12,7 @@ SUBDIR= ${_binutils} \
${_gperf} \
grep \
${_groff} \
${_rcs} \
sdiff \
send-pr \
${_texinfo}
@ -31,6 +32,10 @@ _dtc= dtc
_texinfo= texinfo
.endif
.if ${MK_RCS} != "no"
_rcs= rcs
.endif
.if ${MK_BINUTILS} != "no"
_binutils= binutils
.endif

24
gnu/usr.bin/rcs/CREDITS Normal file
View file

@ -0,0 +1,24 @@
RCS was designed and built by Walter F. Tichy of Purdue University.
RCS version 3 was released in 1983.
Adam Hammer, Thomas Narten, and Daniel Trinkle of Purdue supported RCS through
version 4.3, released in 1990. Guy Harris of Sun contributed many porting
fixes. Paul Eggert of System Development Corporation contributed bug fixes
and tuneups. Jay Lepreau contributed 4.3BSD support.
Paul Eggert of Twin Sun wrote the changes for RCS versions 5.5 and 5.6 (1991).
Rich Braun of Kronos and Andy Glew of Intel contributed ideas for new options.
Bill Hahn of Stratus contributed ideas for setuid support.
Ideas for piece tables came from Joe Berkovitz of Stratus and Walter F. Tichy.
Matt Cross of Stratus contributed test case ideas.
Adam Hammer of Purdue QAed.
Paul Eggert wrote most of the changes for this version of RCS,
currently in beta test. K. Richard Pixley of Cygnus Support
contributed several bug fixes. Robert Lupton of Princeton
and Daniel Trinkle contributed ideas for $Name expansion.
Brendan Kehoe of Cygnus Support suggested rlog's -N option.
Paul D. Smith of Data General suggested improvements in option
and error processing. Adam Hammer of Purdue QAed.
$FreeBSD$

3
gnu/usr.bin/rcs/Makefile Normal file
View file

@ -0,0 +1,3 @@
SUBDIR= lib ci co ident merge rcs rcsclean rcsdiff rcsmerge rlog rcsfreeze
.include <bsd.subdir.mk>

View file

@ -0,0 +1,3 @@
# $FreeBSD$
LIBRCS= ${.OBJDIR}/../lib/librcs.a

548
gnu/usr.bin/rcs/NEWS Normal file
View file

@ -0,0 +1,548 @@
Recent changes to RCS (and possible future changes)
$FreeBSD$
Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2, or (at your
option) any later version.
RCS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
Here is a brief summary of user-visible changes since 5.6.
New options:
`-kb' supports binary files.
`-T' preserves the modification time of RCS files.
`-V' prints the version number.
`-zLT' causes RCS to use local time in working files and logs.
`rcsclean -n' outputs what rcsclean would do, without actually doing it.
`rlog -N' omits symbolic names.
There is a new keyword `Name'.
Inserted log lines now have the same prefix as the preceding `$Log' line.
Most changes for RCS version 5.7 are to fix bugs and improve portability.
RCS now conforms to GNU configuration standards and to Posix 1003.1b-1993.
Features new to RCS version 5.7, and possibly incompatible
in minor ways with previous practice, include:
Inserted log lines now have the same prefix as the preceding `$Log' line.
E.g. if a $Log line starts with `// $Log', log lines are prefixed with `// '.
RCS still records the (now obsolescent) comment leader inside RCS files,
but it ignores the comment leader unless it is emulating older RCS versions.
If you plan to access a file with both old and new versions of RCS,
make sure its comment leader matches its `$Log' line prefix.
For backwards compatibility with older versions of RCS,
if the log prefix is `/*' or `(*' surrounded by optional white space,
inserted log lines contain ` *' instead of `/*' or `(*';
however, this usage is obsolescent and should not be relied on.
$Log string `Revision' times now use the same format as other times.
Log lines are now inserted even if -kk is specified; this simplifies merging.
ci's -rR option (with a nonempty R) now just specifies a revision number R.
In some beta versions, it also reestablished the default behavior of
releasing a lock and removing the working file.
Now, only the bare -r option does this.
With an empty extension, any appearance of a directory named `RCS'
in a pathname identifies the pathname as being that of an RCS file.
For example, `a/RCS/b/c' is now an RCS file with an empty extension.
Formerly, `RCS' had to be the last directory in the pathname.
rlog's -d option by default now uses exclusive time ranges.
E.g. `rlog -d"<T"' now excludes revisions whose times equal T exactly.
Use `rlog -d"<=T"' to get the old behavior.
merge now takes up to three -L options, one for each input file.
Formerly, it took at most two -L options, for the 1st and 3rd input files.
`rcs' now requires at least one option; this is for future expansion.
Other features new to RCS version 5.7 include:
merge and rcsmerge now pass -A, -E, and -e options to the subsidiary diff3.
rcs -kb acts like rcs -ko, except it uses binary I/O on working files.
This makes no difference under Posix or Unix, but it does matter elsewhere.
With -kb in effect, rcsmerge refuses to merge;
this avoids common problems with CVS merging.
The following is for future use by GNU Emacs 19's version control package:
rcs's new -M option causes it to not send mail when you break somebody
else's lock. This is not meant for casual use; see rcs(1).
ci's new -i option causes an error if the RCS file already exists.
Similarly, -j causes an error if the RCS file does not already exist.
The new keyword `Name' is supported; its value is the name, if any,
used to check out the revision. E.g. `co -rN foo' causes foo's
$Name...$ keyword strings to end in `: N $'.
The new -zZONE option causes RCS to output dates and times using ISO 8601
format with ZONE as the time zone, and to use ZONE as the default time
zone for input. Its most common use is the -zLT option, which causes RCS
to use local time externally. You can also specify foreign time zones;
e.g. -z+05:30 causes RCS to use India time (5 hours 30 minutes east of UTC).
This option does not affect RCS files themselves, which always use UTC;
it affects only output (e.g. rlog output, keyword expansion, diff -c times)
and interpretation of options (e.g. the -d option of ci, co, and rlog).
Bare -z restores the default behavior of UTC with no time zone indication,
and the traditional RCS date separator `/' instead of the ISO 8601 `-'.
RCSINIT may contain a -z option. ci -k parses UTC offsets.
The new -T option of ci, co, rcs, and rcsclean preserves the modification
time of the RCS file unless a revision is added or removed.
ci -T sets the RCS file's modification time to the new revision's time
if the former precedes the latter and there is a new revision;
otherwise, it preserves the RCS file's modification time.
Use this option with care, as it can confuse `make'; see ci(1).
The new -N option of rlog omits symbolic names from the output.
A revision number that starts with `.' is considered to be relative to
the default branch (normally the trunk). A branch number followed by `.'
stands for the last revision on that branch.
If someone else already holds the lock, rcs -l now asks whether you want
to break it, instead of immediately reporting an error.
ci now always unlocks a revision like 3.5 if you check in a revision
like 3.5.2.1 that is the first of a new branch of that revision.
Formerly it was inconsistent.
File names may now contain tab, newline, space, and '$'.
They are represented in keyword strings with \t, \n, \040, and \044.
\ in a file name is now represented by \\ in a keyword string.
Identifiers may now start with a digit and (unless they are symbolic names)
may contain `.'. This permits author names like `john.doe' and `4tran'.
A bare -V option now prints the current version number.
rcsdiff outputs more readable context diff headers if diff -L works.
rcsdiff -rN -rN now suppresses needless checkout and comparison
of identical revisions.
Error messages now contain the names of files to which they apply.
Mach style memory mapping is now supported.
The installation procedure now conforms to the GNU coding standards.
When properly configured, RCS now strictly conforms to Posix 1003.1b-1993.
Features new to RCS version 5.6 include:
Security holes have been plugged; setgid use is no longer supported.
co can retrieve old revisions much more efficiently.
To generate the Nth youngest revision on the trunk,
the old method used up to N passes through copies of the working file;
the new method uses a piece table to generate the working file in one pass.
When ci finds no changes in the working file,
it automatically reverts to the previous revision unless -f is given.
RCS follows symbolic links to RCS files instead of breaking them,
and warns when it breaks hard links to RCS files.
`$' stands for the revision number taken from working file keyword strings.
E.g. if F contains an Id keyword string,
`rcsdiff -r$ F' compares F to its checked-in revision, and
`rcs -nL:$ F' gives the symbolic name L to F's revision.
co and ci's new -M option sets the modification time
of the working file to be that of the revision.
Without -M, ci now tries to avoid changing the working file's
modification time if its contents are unchanged.
rcs's new -m option changes the log message of an old revision.
RCS is portable to hosts that do not permit `,' in filenames.
(`,' is not part of the Posix portable filename character set.)
A new -x option specifies extensions other than `,v' for RCS files.
The Unix default is `-x,v/', so that the working file `w' corresponds
to the first file in the list `RCS/w,v', `w,v', `RCS/w' that works.
The non-Unix default is `-x', so that only `RCS/w' is tried.
Eventually, the Unix default should change to `-x/,v'
to encourage interoperability among all Posix hosts.
A new RCSINIT environment variable specifies defaults for options like -x.
The separator for revision ranges has been changed from `-' to `:', because
the range `A-B' is ambiguous if `A', `B' and `A-B' are all symbolic names.
E.g. the old `rlog -r1.5-1.7' is now `rlog -r1.5:1.7'; ditto for `rcs -o'.
For a while RCS will still support (but warn about) the old `-' separator.
RCS manipulates its lock files using a method that is more reliable under NFS.
Features new to RCS version 5 include:
RCS can check in arbitrary files, not just text files, if diff -a works.
RCS can merge lines containing just a single `.' if diff3 -m works.
GNU diff supports the -a and -m options.
RCS can now be used as a setuid program.
See ci(1) for how users can employ setuid copies of ci, co, and rcsclean.
Setuid privileges yield extra security if the effective user owns RCS files
and directories, and if only the effective user can write RCS directories.
RCS uses the real user for all accesses other than writing RCS directories.
As described in ci(1), there are three levels of setuid support.
1. Setuid works fully if the seteuid() system call lets any
process switch back and forth between real and effective users,
as specified in Posix 1003.1a Draft 5.
2. On hosts with saved setuids (a Posix 1003.1-1990 option) and without
a modern seteuid(), setuid works unless the real or effective user is root.
3. On hosts that lack both modern seteuid() and saved setuids,
setuid does not work, and RCS uses the effective user for all accesses;
formerly it was inconsistent.
New options to co, rcsdiff, and rcsmerge give more flexibility to keyword
substitution.
-kkv substitutes the default `$Keyword: value $' for keyword strings.
However, a locker's name is inserted only as a file is being locked,
i.e. by `ci -l' and `co -l'. This is normally the default.
-kkvl acts like -kkv, except that a locker's name is always inserted
if the given revision is currently locked. This was the default in
version 4. It is now the default only with when using rcsdiff to
compare a revision to a working file whose mode is that of a file
checked out for changes.
-kk substitutes just `$Keyword$', which helps to ignore keyword values
when comparing revisions.
-ko retrieves the old revision's keyword string, thus bypassing keyword
substitution.
-kv retrieves just `value'. This can ease the use of keyword values, but
it is dangerous because it causes RCS to lose track of where the keywords
are, so for safety the owner write permission of the working file is
turned off when -kv is used; to edit the file later, check it out again
without -kv.
rcs -ko sets the default keyword substitution to be in the style of co -ko,
and similarly for the other -k options. This can be useful with file
formats that cannot tolerate changing the lengths of keyword strings.
However it also renders a RCS file readable only by RCS version 5 or later.
Use rcs -kkv to restore the usual default substitution.
RCS can now be used by development groups that span time zone boundaries.
All times are now displayed in UTC, and UTC is the default time zone.
To use local time with co -d, append ` LT' to the time.
When interchanging RCS files with sites running older versions of RCS,
time stamp discrepancies may prevent checkins; to work around this,
use `ci -d' with a time slightly in the future.
Dates are now displayed using four-digit years, not two-digit years.
Years given in -d options must now have four digits.
This change is required for RCS to continue to work after 1999/12/31.
The form of dates in version 5 RCS files will not change until 2000/01/01,
so in the meantime RCS files can still be interchanged with sites
running older versions of RCS. To make room for the longer dates,
rlog now outputs `lines: +A -D' instead of `lines added/del: A/D'.
To help prevent diff programs that are broken or have run out of memory
from trashing an RCS file, ci now checks diff output more carefully.
ci -k now handles the Log keyword, so that checking in a file
with -k does not normally alter the file's contents.
RCS no longer outputs white space at the ends of lines
unless the original working file had it.
For consistency with other keywords,
a space, not a tab, is now output after `$Log:'.
Rlog now puts lockers and symbolic names on separate lines in the output
to avoid generating lines that are too long.
A similar fix has been made to lists in the RCS files themselves.
RCS no longer outputs the string `Locker: ' when expanding Header or Id
keywords. This saves space and reverts back to version 3 behavior.
The default branch is not put into the RCS file unless it is nonempty.
Therefore, files generated by RCS version 5 can be read by RCS version 3
unless they use the default branch feature introduced in version 4.
This fixes a compatibility problem introduced by version 4.
RCS can now emulate older versions of RCS; see `co -V'.
This may be useful to overcome compatibility problems
due to the above changes.
Programs like Emacs can now interact with RCS commands via a pipe:
the new -I option causes ci, co, and rcs to run interactively,
even if standard input is not a terminal.
These commands now accept multiple inputs from stdin separated by `.' lines.
ci now silently ignores the -t option if the RCS file already exists.
This simplifies some shell scripts and improves security in setuid sites.
Descriptive text may be given directly in an argument of the form -t-string.
The character set for symbolic names has been upgraded
from Ascii to ISO 8859.
rcsdiff now passes through all options used by GNU diff;
this is a longer list than 4.3BSD diff.
merge's new -L option gives tags for merge's overlap report lines.
This ability used to be present in a different, undocumented form;
the new form is chosen for compatibility with GNU diff3's -L option.
rcsmerge and merge now have a -q option, just like their siblings do.
rcsclean's new -n option outputs what rcsclean would do,
without actually doing it.
RCS now attempts to ignore parts of an RCS file that look like they come
from a future version of RCS.
When properly configured, RCS now strictly conforms with Posix 1003.1-1990.
RCS can still be compiled in non-Posix traditional Unix environments,
and can use common BSD and USG extensions to Posix.
RCS is a conforming Standard C program, and also compiles under traditional C.
Arbitrary limits on internal table sizes have been removed.
The only limit now is the amount of memory available via malloc().
File temporaries, lock files, signals, and system call return codes
are now handled more cleanly, portably, and quickly.
Some race conditions have been removed.
A new compile-time option RCSPREFIX lets administrators avoid absolute path
names for subsidiary programs, trading speed for flexibility.
The configuration procedure is now more automatic.
Snooping has been removed.
Version 4 was the first version distributed by FSF.
Beside bug fixes, features new to RCS version 4 include:
The notion of default branch has been added; see rcs -b.
Version 3 was included in the 4.3BSD distribution.
Here are some possible future changes for RCS:
Bring back sccstorcs.
Add an option to `rcsmerge' so that it can use an arbitrary program
to do the 3-way merge, instead of the default `merge'.
Likewise for `rcsdiff' and `diff'. It should be possible to pass
arbitrary options to these programs, and to the subsidiary `co's.
Add format options for finer control over the output of ident and rlog.
E.g. there should be an easy way for rlog to output lines like
`src/main.c 2.4 wft', one for each locked revision.
rlog options should have three orthogonal types: selecting files,
selecting revisions, and selecting rlog format.
Add format options for finer control over the output of keyword strings.
E.g. there should be some way to prepend @(#), and there should be some
way to change $ to some other character to disable further substitution.
These options should make the resulting files uneditable, like -kv.
Add long options, e.g. `--version'. Unfortunately RCS's option syntax
is incompatible with getopt. Perhaps the best way is to overload `rcs', e.g.
`rcs diff --keyword-substitution=old file' instead of `rcsdiff -ko file'.
Add a way to put only the interesting part of the path into the $Header
keyword expansion.
rlog -rM:N should work even if M and N have different numbers of fields,
so long as M is an ancestor of N or vice versa.
rcs should evaluate options in order; this allows rcs -oS -nS.
rcs should be able to fix minor mistakes in checkin dates and authors.
Be able to redo your most recent checkin with minor changes.
co -u shouldn't complain about a writable working file if it won't change
its contents.
Configure the Makefile automatically, as well as conf.h.
Add a new option to rcs that behaves like -o, but that doesn't lose the
nonempty log messages, but instead merges them with the next revision
if it exists, perhaps with a 1-line header containing author, date, etc.
Add a `-' option to take the list of pathnames from standard input.
Perhaps the pathnames should be null-terminated, not newline-terminated,
so that pathnames that contain newlines are handled properly.
Permit multiple option-pathname pairs, e.g. co -r1.4 a -r1.5 b.
Add options to allow arbitrary combinations of working file names
with RCS file names -- they shouldn't have to match.
Add an option to break a symbolic link to an RCS file,
instead of breaking the hard link that it points to.
Add ways to specify the earliest revision, the most recent revision,
the earliest or latest revision on a particular branch, and
the parent or child of some other revision.
If a user has multiple locks, perhaps ci should fall back on ci -k's
method to figure out which revision to use.
Symbolic names need not refer to existing branches and revisions.
rcs(1)'s BUGS section says this is a bug. Is it? If so, it should be fixed.
Add an option to rcs -o so that old log messages are not deleted if
the next undeleted revision exists, but are merely appended to the log
message of that revision.
ci -k should be able to get keyword values from the first `$Log' entry.
Add an option to rcsclean to clean directories recursively.
Write an rcsck program that repairs corrupted RCS files,
much as fsck repairs corrupted file systems.
For example, it should remove stale lock files.
Clean up the source code with a consistent indenting style.
Update the date parser to use the more modern getdate.y by Bellovin,
Salz, and Berets, or the even more modern getdate by Moraes. None of
these getdate implementations are as robust as RCS's old warhorse in
avoiding problems like arithmetic overflow, so they'll have to be
fixed first.
Break up the code into a library so that it's easier to write new programs
that manipulate RCS files, and so that useless code is removed from the
existing programs. For example, the rcs command contains unnecessary
keyword substitution baggage, and the merge command can be greatly pruned.
Make it easier to use your favorite text editor to edit log messages,
etc. instead of having to type them in irretrievably at the terminal.
Let the user specify a search path for default branches,
e.g. to use L as the default branch if it works, and M otherwise.
Let the user require that at least one entry in the default branch path works.
Let the user say that later entries in the default branch path are read only,
i.e. one cannot check in changes to them.
This should be an option settable by RCSINIT.
Add a way for a user to see which revisions affected which lines.
Have `rlog -nN F' print just the revision number that N translates to.
E.g. `rlog -nB. F' would print the highest revision on the branch B.
Use this to add an option -bB to rcsbranch, to freeze the named branch.
This should interact well with default branches.
Add a co option that prints the revision number before each line,
as SCCS's `get -m' does.
The following projects require a change to RCS file format.
Allow keyword expansion to be changed on a per-revision basis,
not on a per-file basis as now. This would allow -ko to be used
on imported revisions, with the default -kkv otherwise.
When two or more branches are merged, record all the ancestors
of the new revision. The hard part of this is keeping track of all
the ancestors of a working file while it's checked out.
Add loose locking, which is like non-strict but applies to all users,
not just the owner of the RCS file.
Be able to store RCS files in compressed format.
Don't bother to use a .Z extension that would exceed file name length limits;
just look at the magic number.
Add locker commentary, e.g. `co -l -m"checkout to fix merge bug" foo'
to tell others why you checked out `foo'.
Also record the time when the revision was locked,
and perhaps the working pathname (if applicable).
Let the user mark an RCS revision as deleted; checking out such a revision
would result in no working file. Similarly, using `co -d' with a date either
before the initial revision or after the file was marked deleted should
remove the working file. For extra credit, extend the notion of `deleted' to
include `renamed'. RCS should support arbitrary combinations of renaming and
deletion, e.g. renaming A to B and B to A, checking in new revisions to both
files, and then renaming them back.
Be able to check in an entire directory structure into a single RCS file.
Use a better scheme for locking revisions; the current scheme requires
changing the RCS file just to lock or unlock a revision.
The new scheme should coexist as well as possible with older versions of RCS,
and should avoid the rare NFS bugs mentioned in rcsedit.c.
E.g. if there's a reliable lockd running, RCS should use it
instead of relying on NFS.
Add rcs options for changing keyword names, e.g. XConsortium instead of Id.
Add a `$Description' keyword; but this may be tricky, since descriptions can
contain newlines and $s.
Add a `$Copyright' keyword that expands to a copyright notice.
Add frozen branches a la SCCS. In general, be able to emulate all of
SCCS, so that an SCCS-to-RCS program can be practical. For example,
there should be an equivalent to the SCCS prt command.
Add support for distributed RCS, where widely separated
users cannot easily access each others' RCS files,
and must periodically distribute and reconcile new revisions.
Be able to create empty branches.
Be able to store just deltas from a read-only principal copy,
e.g. from source on CD-ROM.
Improve RCS's method for storing binary files.
Although it is more efficient than SCCS's,
the diff algorithm is still line oriented,
and often generates long output for minor changes to an executable file.
From the user's point of view, it would be best if
RCS detected and handled binary files without human intervention,
switching expansion methods as needed from revision to revision.
Allow RCS to determine automagically whether -ko or -kb should be the default
by inspecting the file's contents or name. The magic should be optional
and user-programmable.
Extend the grammar of RCS files so that keywords need not be in a fixed order.
Internationalize messages; unfortunately, there's no common standard yet.
This requires a change in RCS file format because of the
`empty log message' and `checked in with -k' hacks inside RCS files.
Add documentation in texinfo format.

90
gnu/usr.bin/rcs/REFS Normal file
View file

@ -0,0 +1,90 @@
Here are references to RCS and related free software and documentation.
Some of this information changes often; see the Frequently Asked Questions
for more up-to-date references.
$FreeBSD$
Frequently Asked Questions (FAQs)
<http://www.qucis.queensu.ca/Software-Engineering/>
<ftp://rtfm.mit.edu//pub/usenet-by-hierarchy/comp/software-eng/>
for software engineering; e.g. see
<http://www.qucis.queensu.ca/Software-Engineering/blurb/rcs>.
<http://www.iac.honeywell.com/Pub/Tech/CM/CMFAQ.html>
<ftp://rtfm.mit.edu//pub/usenet-by-hierarchy/comp/software/config-mgmt/>
for configuration management
<http://www.winternet.com/~zoo/cvs/FAQ.txt>
<ftp://ftp.odi.com/pub/users/dgg/FAQ.gz>
for CVS (see below)
RCS and related GNU project software
<ftp://ftp.cs.purdue.edu/pub/RCS/>
The RCS project distribution directory also contains beta versions,
ports, and prebuilt documentation.
<ftp://prep.ai.mit.edu/pub/gnu/>
The GNU project distribution directory contains:
diffutils-N-tar.gz
the latest diffutils release; recommended for RCS
emacs-N-tar.gz
The latest Emacs release contains VC, a version-control package
that makes RCS easier to use.
make-N-tar.gz
GNU Make, which can automatically build from RCS files.
rcs-N-tar.gz
the latest RCS release
cvs-N-tar.gz
the latest official CVS release (see below)
<ftp://ftp.leo.org/pub/comp/os/os2/gnu/devtools/> DOS, OS/2 ports
<ftp://ftp.cc.utexas.edu/microlib/nt/gnu/> NT port
CVS
CVS, the Concurrent Versions System, keeps tracks of source changes
made by groups of developers working on the same files concurrently,
allowing them to resync as needed.
<http://www.winternet.com/~zoo/cvs/>
<http://www.loria.fr/~molli/cvs-index.html>
These pages have useful information about CVS.
<ftp://prep.ai.mit.edu/pub/gnu/cvs-1.3.tar.gz>
CVS 1.3 is the latest released version.
<ftp://ftp.delos.com/pub/cvs/alpha/cvs-1.4A2.tar.gz>
CVS 1.4 is in alpha test, but it is recommended if you are installing CVS
for the first time, or on a recent operating system.
<ftp://ftp-os2.cdrom.com/pub/os2/unix/> DOS, OS/2 ports
<ftp://ftp.cc.utexas.edu/microlib/nt/gnu/> NT port
<ftp://ftp.cyclic.com/pub/cvs/>
Cyclic CVS adds network transparency to CVS; it supports efficient,
reliable, and authenticated repository access via TCP/IP.
Other software that uses RCS
<ftp://ftp.nau.edu/pub/Aegis/>
Aegis manages revisions, baselines, mandatory reviews, and mandatory testing.
<ftp://ftp.vix.com/pub/patches/csu/>
BCS, the Baseline Configuration System,
manages revisions, baselines, and staging areas.
<ftp://riftp.osf.org/pub/ode/>
ODE, the Open Software Foundation Development Environment,
manages revisions, builds, and sandboxes.
OSF uses it for their own development.
<ftp://bellcore.com/pub/Odin/>
Odin, a `make' replacement, can build directly from arbitrary revisions
without requiring checkouts of working copies. It also handles
parallel builds on multiple remote hosts and of multiple variants.

View file

@ -0,0 +1,8 @@
PROG= ci
SRCS= ci.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

898
gnu/usr.bin/rcs/ci/ci.1 Normal file
View file

@ -0,0 +1,898 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds i \&\s-1ISO\s0
.ds r \&\s-1RCS\s0
.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH CI 1 \*(Dt GNU
.SH NAME
ci \- check in RCS revisions
.SH SYNOPSIS
.B ci
.RI [ options ] " file " .\|.\|.
.SH DESCRIPTION
.B ci
stores new revisions into \*r files.
Each pathname matching an \*r suffix
is taken to be an \*r file.
All others
are assumed to be working files containing new revisions.
.B ci
deposits the contents of each working file
into the corresponding \*r file.
If only a working file is given,
.B ci
tries to find the corresponding \*r file in an \*r subdirectory
and then in the working file's directory.
For more details, see
.SM "FILE NAMING"
below.
.PP
For
.B ci
to work, the caller's login must be on the access list,
except if the access list is empty or the caller is the superuser or the
owner of the file.
To append a new revision to an existing branch, the tip revision on
that branch must be locked by the caller. Otherwise, only a
new branch can be created. This restriction is not enforced
for the owner of the file if non-strict locking is used
(see
.BR rcs (1)).
A lock held by someone else can be broken with the
.B rcs
command.
.PP
Unless the
.B \-f
option is given,
.B ci
checks whether the revision to be deposited differs from the preceding one.
If not, instead of creating a new revision
.B ci
reverts to the preceding one.
To revert, ordinary
.B ci
removes the working file and any lock;
.B "ci\ \-l"
keeps and
.B "ci\ \-u"
removes any lock, and then they both generate a new working file much as if
.B "co\ \-l"
or
.B "co\ \-u"
had been applied to the preceding revision.
When reverting, any
.B \-n
and
.B \-s
options apply to the preceding revision.
.PP
For each revision deposited,
.B ci
prompts for a log message.
The log message should summarize the change and must be terminated by
end-of-file or by a line containing
.BR \&. "\ by"
itself.
If several files are checked in
.B ci
asks whether to reuse the
previous log message.
If the standard input is not a terminal,
.B ci
suppresses the prompt
and uses the same log message for all files.
See also
.BR \-m .
.PP
If the \*r file does not exist,
.B ci
creates it and
deposits the contents of the working file as the initial revision
(default number:
.BR 1.1 ).
The access list is initialized to empty.
Instead of the log message,
.B ci
requests descriptive text (see
.B \-t
below).
.PP
The number
.I rev
of the deposited revision can be given by any of the options
.BR \-f ,
.BR \-i ,
.BR \-I ,
.BR \-j ,
.BR \-k ,
.BR \-l ,
.BR \-M ,
.BR \-q ,
.BR \-r ,
or
.BR \-u .
.I rev
can be symbolic, numeric, or mixed.
Symbolic names in
.I rev
must already be defined;
see the
.B \-n
and
.B \-N
options for assigning names during checkin.
If
.I rev
is
.BR $ ,
.B ci
determines the revision number from keyword values in the working file.
.PP
If
.I rev
begins with a period,
then the default branch (normally the trunk) is prepended to it.
If
.I rev
is a branch number followed by a period,
then the latest revision on that branch is used.
.PP
If
.I rev
is a revision number, it must be higher than the latest
one on the branch to which
.I rev
belongs, or must start a new branch.
.PP
If
.I rev
is a branch rather than a revision number,
the new revision is appended to that branch. The level number is obtained
by incrementing the tip revision number of that branch.
If
.I rev
indicates a non-existing branch,
that branch is created with the initial revision numbered
.IB rev .1\f1.\fP
.br
.ne 8
.PP
If
.I rev
is omitted,
.B ci
tries to derive the new revision number from
the caller's last lock. If the caller has locked the tip revision of a branch,
the new revision is appended to that branch.
The new revision number is obtained
by incrementing the tip revision number.
If the caller locked a non-tip revision, a new branch is started at
that revision by incrementing the highest branch number at that revision.
The default initial branch and level numbers are
.BR 1 .
.PP
If
.I rev
is omitted and the caller has no lock, but owns
the file and locking
is not set to
.IR strict ,
then the revision is appended to the
default branch (normally the trunk; see the
.B \-b
option of
.BR rcs (1)).
.PP
Exception: On the trunk, revisions can be appended to the end, but
not inserted.
.SH OPTIONS
.TP
.BI \-r rev
Check in revision
.IR rev .
.TP
.BR \-r
The bare
.B \-r
option (without any revision) has an unusual meaning in
.BR ci .
With other \*r commands, a bare
.B \-r
option specifies the most recent revision on the default branch,
but with
.BR ci ,
a bare
.B \-r
option reestablishes the default behavior of releasing a lock and
removing the working file, and is used to override any default
.B \-l
or
.B \-u
options established by shell aliases or scripts.
.TP
.BR \-l [\f2rev\fP]
works like
.BR \-r ,
except it performs an additional
.B "co\ \-l"
for the
deposited revision. Thus, the deposited revision is immediately
checked out again and locked.
This is useful for saving a revision although one wants to continue
editing it after the checkin.
.TP
.BR \-u [\f2rev\fP]
works like
.BR \-l ,
except that the deposited revision is not locked.
This lets one read the working file
immediately after checkin.
.RS
.PP
The
.BR \-l ,
bare
.BR \-r ,
and
.B \-u
options are mutually exclusive and silently override each other.
For example,
.B "ci\ \-u\ \-r"
is equivalent to
.B "ci\ \-r"
because bare
.B \-r
overrides
.BR \-u .
.RE
.TP
.BR \-f [\f2rev\fP]
forces a deposit; the new revision is deposited even it is not different
from the preceding one.
.TP
.BR \-k [\f2rev\fP]
searches the working file for keyword values to determine its revision number,
creation date, state, and author (see
.BR co (1)),
and assigns these
values to the deposited revision, rather than computing them locally.
It also generates a default login message noting the login of the caller
and the actual checkin date.
This option is useful for software distribution. A revision that is sent to
several sites should be checked in with the
.B \-k
option at these sites to
preserve the original number, date, author, and state.
The extracted keyword values and the default log message can be overridden
with the options
.BR \-d ,
.BR \-m ,
.BR \-s ,
.BR \-w ,
and any option that carries a revision number.
.TP
.BR \-q [\f2rev\fP]
quiet mode; diagnostic output is not printed.
A revision that is not different from the preceding one is not deposited,
unless
.B \-f
is given.
.TP
.BR \-i [\f2rev\fP]
initial checkin; report an error if the \*r file already exists.
This avoids race conditions in certain applications.
.TP
.BR \-j [\f2rev\fP]
just checkin and do not initialize;
report an error if the \*r file does not already exist.
.TP
.BR \-I [\f2rev\fP]
interactive mode;
the user is prompted and questioned
even if the standard input is not a terminal.
.TP
.BR \-d "[\f2date\fP]"
uses
.I date
for the checkin date and time.
The
.I date
is specified in free format as explained in
.BR co (1).
This is useful for lying about the checkin date, and for
.B \-k
if no date is available.
If
.I date
is empty, the working file's time of last modification is used.
.TP
.BR \-M [\f2rev\fP]
Set the modification time on any new working file
to be the date of the retrieved revision.
For example,
.BI "ci\ \-d\ \-M\ \-u" "\ f"
does not alter
.IR f 's
modification time, even if
.IR f 's
contents change due to keyword substitution.
Use this option with care; it can confuse
.BR make (1).
.TP
.BI \-m "msg"
uses the string
.I msg
as the log message for all revisions checked in.
By convention, log messages that start with
.B #
are comments and are ignored by programs like GNU Emacs's
.B vc
package.
Also, log messages that start with
.BI { clumpname }
(followed by white space) are meant to be clumped together if possible,
even if they are associated with different files; the
.BI { clumpname }
label is used only for clumping,
and is not considered to be part of the log message itself.
.TP
.BI \-n "name"
assigns the symbolic name
.I name
to the number of the checked-in revision.
.B ci
prints an error message if
.I name
is already assigned to another
number.
.TP
.BI \-N "name"
same as
.BR \-n ,
except that it overrides a previous assignment of
.IR name .
.TP
.BI \-s "state"
sets the state of the checked-in revision to the identifier
.IR state .
The default state is
.BR Exp .
.TP
.BI \-t file
writes descriptive text from the contents of the named
.I file
into the \*r file,
deleting the existing text.
The
.I file
cannot begin with
.BR \- .
.TP
.BI \-t\- string
Write descriptive text from the
.I string
into the \*r file, deleting the existing text.
.RS
.PP
The
.B \-t
option, in both its forms, has effect only during an initial checkin;
it is silently ignored otherwise.
.PP
During the initial checkin, if
.B \-t
is not given,
.B ci
obtains the text from standard input,
terminated by end-of-file or by a line containing
.BR \&. "\ by"
itself.
The user is prompted for the text if interaction is possible; see
.BR \-I .
.PP
For backward compatibility with older versions of \*r, a bare
.B \-t
option is ignored.
.RE
.TP
.B \-T
Set the \*r file's modification time to the new revision's time
if the former precedes the latter and there is a new revision;
preserve the \*r file's modification time otherwise.
If you have locked a revision,
.B ci
usually updates the \*r file's modification time to the current time,
because the lock is stored in the \*r file
and removing the lock requires changing the \*r file.
This can create an \*r file newer than the working file in one of two ways:
first,
.B "ci\ \-M"
can create a working file with a date before the current time;
second, when reverting to the previous revision
the \*r file can change while the working file remains unchanged.
These two cases can cause excessive recompilation caused by a
.BR make (1)
dependency of the working file on the \*r file.
The
.B \-T
option inhibits this recompilation by lying about the \*r file's date.
Use this option with care; it can suppress recompilation even when
a checkin of one working file should affect
another working file associated with the same \*r file.
For example, suppose the \*r file's time is 01:00,
the (changed) working file's time is 02:00,
some other copy of the working file has a time of 03:00,
and the current time is 04:00.
Then
.B "ci\ \-d\ \-T"
sets the \*r file's time to 02:00 instead of the usual 04:00;
this causes
.BR make (1)
to think (incorrectly) that the other copy is newer than the \*r file.
.TP
.BI \-w "login"
uses
.I login
for the author field of the deposited revision.
Useful for lying about the author, and for
.B \-k
if no author is available.
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.IR n .
See
.BR co (1)
for details.
.TP
.BI \-x "suffixes"
specifies the suffixes for \*r files.
A nonempty suffix matches any pathname ending in the suffix.
An empty suffix matches any pathname of the form
.BI RCS/ path
or
.IB path1 /RCS/ path2.
The
.B \-x
option can specify a list of suffixes
separated by
.BR / .
For example,
.B \-x,v/
specifies two suffixes:
.B ,v
and the empty suffix.
If two or more suffixes are specified,
they are tried in order when looking for an \*r file;
the first one that works is used for that file.
If no \*r file is found but an \*r file can be created,
the suffixes are tried in order
to determine the new \*r file's name.
The default for
.IR suffixes
is installation-dependent; normally it is
.B ,v/
for hosts like Unix that permit commas in filenames,
and is empty (i.e. just the empty suffix) for other hosts.
.TP
.BI \-z zone
specifies the date output format in keyword substitution,
and specifies the default time zone for
.I date
in the
.BI \-d date
option.
The
.I zone
should be empty, a numeric \*u offset, or the special string
.B LT
for local time.
The default is an empty
.IR zone ,
which uses the traditional \*r format of \*u without any time zone indication
and with slashes separating the parts of the date;
otherwise, times are output in \*i 8601 format with time zone indication.
For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
eight hours west of \*u,
then the time is output as follows:
.RS
.LP
.RS
.nf
.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
.ne 4
\f2option\fP \f2time output\fP
\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
.ta 4n +4n +4n +4n
.fi
.RE
.LP
The
.B \-z
option does not affect dates stored in \*r files,
which are always \*u.
.SH "FILE NAMING"
Pairs of \*r files and working files can be specified in three ways
(see also the
example section).
.PP
1) Both the \*r file and the working file are given. The \*r pathname is of
the form
.IB path1 / workfileX
and the working pathname is of the form
.IB path2 / workfile
where
.IB path1 /
and
.IB path2 /
are (possibly different or empty) paths,
.I workfile
is a filename, and
.I X
is an \*r suffix.
If
.I X
is empty,
.IB path1 /
must start with
.B RCS/
or must contain
.BR /RCS/ .
.PP
2) Only the \*r file is given. Then the working file is created in the current
directory and its name is derived from the name of the \*r file
by removing
.IB path1 /
and the suffix
.IR X .
.PP
3) Only the working file is given.
Then
.B ci
considers each \*r suffix
.I X
in turn, looking for an \*r file of the form
.IB path2 /RCS/ workfileX
or (if the former is not found and
.I X
is nonempty)
.IB path2 / workfileX.
.PP
If the \*r file is specified without a path in 1) and 2),
.B ci
looks for the \*r file first in the directory
.B ./RCS
and then in the current
directory.
.PP
.B ci
reports an error if an attempt to open an \*r file fails for an unusual reason,
even if the \*r file's pathname is just one of several possibilities.
For example, to suppress use of \*r commands in a directory
.IR d ,
create a regular file named
.IB d /RCS
so that casual attempts to use \*r commands in
.I d
fail because
.IB d /RCS
is not a directory.
.SH EXAMPLES
Suppose
.B ,v
is an \*r suffix and the current directory contains a subdirectory
.B RCS
with an \*r file
.BR io.c,v .
Then each of the following commands check in a copy of
.B io.c
into
.B RCS/io.c,v
as the latest revision, removing
.BR io.c .
.LP
.RS
.nf
.ft 3
ci io.c; ci RCS/io.c,v; ci io.c,v;
ci io.c RCS/io.c,v; ci io.c io.c,v;
ci RCS/io.c,v io.c; ci io.c,v io.c;
.ft
.fi
.RE
.PP
Suppose instead that the empty suffix
is an \*r suffix and the current directory contains a subdirectory
.B RCS
with an \*r file
.BR io.c .
The each of the following commands checks in a new revision.
.LP
.RS
.nf
.ft 3
ci io.c; ci RCS/io.c;
ci io.c RCS/io.c;
ci RCS/io.c io.c;
.ft
.fi
.RE
.SH "FILE MODES"
An \*r file created by
.B ci
inherits the read and execute permissions
from the working file. If the \*r file exists already,
.B ci
preserves its read and execute permissions.
.B ci
always turns off all write permissions of \*r files.
.SH FILES
Temporary files are created in the directory containing
the working file, and also in the temporary directory (see
.B \s-1TMPDIR\s0
under
.BR \s-1ENVIRONMENT\s0 ).
A semaphore file or files are created in the directory containing the \*r file.
With a nonempty suffix, the semaphore names begin with
the first character of the suffix; therefore, do not specify an suffix
whose first character could be that of a working filename.
With an empty suffix, the semaphore names end with
.B _
so working filenames should not end in
.BR _ .
.PP
.B ci
never changes an \*r or working file.
Normally,
.B ci
unlinks the file and creates a new one;
but instead of breaking a chain of one or more symbolic links to an \*r file,
it unlinks the destination file instead.
Therefore,
.B ci
breaks any hard or symbolic links to any working file it changes;
and hard links to \*r files are ineffective,
but symbolic links to \*r files are preserved.
.PP
The effective user must be able to
search and write the directory containing the \*r file.
Normally, the real user must be able to
read the \*r and working files
and to search and write the directory containing the working file;
however, some older hosts
cannot easily switch between real and effective users,
so on these hosts the effective user is used for all accesses.
The effective user is the same as the real user
unless your copies of
.B ci
and
.B co
have setuid privileges.
As described in the next section,
these privileges yield extra security if
the effective user owns all \*r files and directories,
and if only the effective user can write \*r directories.
.PP
Users can control access to \*r files by setting the permissions
of the directory containing the files; only users with write access
to the directory can use \*r commands to change its \*r files.
For example, in hosts that allow a user to belong to several groups,
one can make a group's \*r directories writable to that group only.
This approach suffices for informal projects,
but it means that any group member can arbitrarily change the group's \*r files,
and can even remove them entirely.
Hence more formal projects sometimes distinguish between an \*r administrator,
who can change the \*r files at will, and other project members,
who can check in new revisions but cannot otherwise change the \*r files.
.SH "SETUID USE"
To prevent anybody but their \*r administrator from deleting revisions,
a set of users can employ setuid privileges as follows.
.nr n \w'\(bu'+2n-1/1n
.ds n \nn
.if \n(.g .if r an-tag-sep .ds n \w'\(bu'u+\n[an-tag-sep]u
.IP \(bu \*n
Check that the host supports \*r setuid use.
Consult a trustworthy expert if there are any doubts.
It is best if the
.B seteuid
system call works as described in Posix 1003.1a Draft 5,
because \*r can switch back and forth easily
between real and effective users, even if the real user is
.BR root .
If not, the second best is if the
.B setuid
system call supports saved setuid
(the {\s-1_POSIX_SAVED_IDS\s0} behavior of Posix 1003.1-1990);
this fails only if the real or effective user is
.BR root .
If \*r detects any failure in setuid, it quits immediately.
.IP \(bu \nn
Choose a user
.I A
to serve as \*r administrator for the set of users.
Only
.I A
can invoke the
.B rcs
command on the users' \*r files.
.I A
should not be
.B root
or any other user with special powers.
Mutually suspicious sets of users should use different administrators.
.IP \(bu \nn
Choose a pathname
.I B
to be a directory of files to be executed by the users.
.IP \(bu \nn
Have
.I A
set up
.I B
to contain copies of
.B ci
and
.B co
that are setuid to
.I A
by copying the commands from their standard installation directory
.I D
as follows:
.LP
.RS
.nf
.ne 3
\f3mkdir\fP \f2B\fP
\f3cp\fP \f2D\fP\^\f3/c[io]\fP \f2B\fP
\f3chmod go\-w,u+s\fP \f2B\fP\f3/c[io]\fP
.fi
.RE
.IP \(bu \nn
Have each user prepend
.I B
to their path as follows:
.LP
.RS
.nf
.ne 2
\f3PATH=\fP\f2B\fP\f3:$PATH; export PATH\fP # ordinary shell
\f3set path=(\fP\f2B\fP \f3$path)\fP # C shell
.fi
.RE
.IP \(bu \nn
Have
.I A
create each \*r directory
.I R
with write access only to
.I A
as follows:
.LP
.RS
.nf
.ne 2
\f3mkdir\fP \f2R\fP
\f3chmod go\-w\fP \f2R\fP
.fi
.RE
.IP \(bu \nn
If you want to let only certain users read the \*r files,
put the users into a group
.IR G ,
and have
.I A
further protect the \*r directory as follows:
.LP
.RS
.nf
.ne 2
\f3chgrp\fP \f2G R\fP
\f3chmod g\-w,o\-rwx\fP \f2R\fP
.fi
.RE
.IP \(bu \nn
Have
.I A
copy old \*r files (if any) into
.IR R ,
to ensure that
.I A
owns them.
.IP \(bu \nn
An \*r file's access list limits who can check in and lock revisions.
The default access list is empty,
which grants checkin access to anyone who can read the \*r file.
If you want limit checkin access,
have
.I A
invoke
.B "rcs\ \-a"
on the file; see
.BR rcs (1).
In particular,
.BI "rcs\ \-e\ \-a" A
limits access to just
.IR A .
.IP \(bu \nn
Have
.I A
initialize any new \*r files with
.B "rcs\ \-i"
before initial checkin, adding the
.B \-a
option if you want to limit checkin access.
.IP \(bu \nn
Give setuid privileges only to
.BR ci ,
.BR co ,
and
.BR rcsclean ;
do not give them to
.B rcs
or to any other command.
.IP \(bu \nn
Do not use other setuid commands to invoke \*r commands;
setuid is trickier than you think!
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
A backslash escapes spaces within an option.
The
.B \s-1RCSINIT\s0
options are prepended to the argument lists of most \*r commands.
Useful
.B \s-1RCSINIT\s0
options include
.BR \-q ,
.BR \-V ,
.BR \-x ,
and
.BR \-z .
.TP
.B \s-1TMPDIR\s0
Name of the temporary directory.
If not set, the environment variables
.B \s-1TMP\s0
and
.B \s-1TEMP\s0
are inspected instead and the first value found is taken;
if none of them are set,
a host-dependent default is used, typically
.BR /tmp .
.SH DIAGNOSTICS
For each revision,
.B ci
prints the \*r file, the working file, and the number
of both the deposited and the preceding revision.
The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
co(1),
ident(1), make(1), rcs(1), rcsclean(1), rcsdiff(1),
rcsintro(1), rcsmerge(1), rlog(1), setuid(2), rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.br

1318
gnu/usr.bin/rcs/ci/ci.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
PROG= co
SRCS= co.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

736
gnu/usr.bin/rcs/co/co.1 Normal file
View file

@ -0,0 +1,736 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds i \&\s-1ISO\s0
.ds r \&\s-1RCS\s0
.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH CO 1 \*(Dt GNU
.SH NAME
co \- check out RCS revisions
.SH SYNOPSIS
.B co
.RI [ options ] " file " .\|.\|.
.SH DESCRIPTION
.B co
retrieves a revision from each \*r file and stores it into
the corresponding working file.
.PP
Pathnames matching an \*r suffix denote \*r files;
all others denote working files.
Names are paired as explained in
.BR ci (1).
.PP
Revisions of an \*r file can be checked out locked or unlocked. Locking a
revision prevents overlapping updates. A revision checked out for reading or
processing (e.g., compiling) need not be locked. A revision checked out
for editing and later checkin must normally be locked. Checkout with locking
fails if the revision to be checked out is currently locked by another user.
(A lock can be broken with
.BR rcs "(1).)\ \&"
Checkout with locking also requires the caller to be on the access list of
the \*r file, unless he is the owner of the
file or the superuser, or the access list is empty.
Checkout without locking is not subject to accesslist restrictions, and is
not affected by the presence of locks.
.PP
A revision is selected by options for revision or branch number,
checkin date/time, author, or state.
When the selection options
are applied in combination,
.B co
retrieves the latest revision
that satisfies all of them.
If none of the selection options
is specified,
.B co
retrieves the latest revision
on the default branch (normally the trunk, see the
.B \-b
option of
.BR rcs (1)).
A revision or branch number can be attached
to any of the options
.BR \-f ,
.BR \-I ,
.BR \-l ,
.BR \-M ,
.BR \-p ,
.BR \-q ,
.BR \-r ,
or
.BR \-u .
The options
.B \-d
(date),
.B \-s
(state), and
.B \-w
(author)
retrieve from a single branch, the
.I selected
branch,
which is either specified by one of
.BR \-f ,
\&.\|.\|.,
.BR \-u ,
or the default branch.
.PP
A
.B co
command applied to an \*r
file with no revisions creates a zero-length working file.
.B co
always performs keyword substitution (see below).
.SH OPTIONS
.TP
.BR \-r [\f2rev\fP]
retrieves the latest revision whose number is less than or equal to
.IR rev .
If
.I rev
indicates a branch rather than a revision,
the latest revision on that branch is retrieved.
If
.I rev
is omitted, the latest revision on the default branch
(see the
.B \-b
option of
.BR rcs (1))
is retrieved.
If
.I rev
is
.BR $ ,
.B co
determines the revision number from keyword values in the working file.
Otherwise, a revision is composed of one or more numeric or symbolic fields
separated by periods.
If
.I rev
begins with a period,
then the default branch (normally the trunk) is prepended to it.
If
.I rev
is a branch number followed by a period,
then the latest revision on that branch is used.
The numeric equivalent of a symbolic field
is specified with the
.B \-n
option of the commands
.BR ci (1)
and
.BR rcs (1).
.TP
.BR \-l [\f2rev\fP]
same as
.BR \-r ,
except that it also locks the retrieved revision for
the caller.
.TP
.BR \-u [\f2rev\fP]
same as
.BR \-r ,
except that it unlocks the retrieved revision if it was
locked by the caller. If
.I rev
is omitted,
.B \-u
retrieves the revision locked by the caller, if there is one; otherwise,
it retrieves the latest revision on the default branch.
.TP
.BR \-f [\f2rev\fP]
forces the overwriting of the working file;
useful in connection with
.BR \-q .
See also
.SM "FILE MODES"
below.
.TP
.B \-kkv
Generate keyword strings using the default form, e.g.\&
.B "$\&Revision: \*(Rv $"
for the
.B Revision
keyword.
A locker's name is inserted in the value of the
.BR Header ,
.BR Id ,
and
.B Locker
keyword strings
only as a file is being locked,
i.e. by
.B "ci\ \-l"
and
.BR "co\ \-l".
This is the default.
.TP
.B \-kkvl
Like
.BR \-kkv ,
except that a locker's name is always inserted
if the given revision is currently locked.
.TP
.B \-kk
Generate only keyword names in keyword strings; omit their values.
See
.SM "KEYWORD SUBSTITUTION"
below.
For example, for the
.B Revision
keyword, generate the string
.B $\&Revision$
instead of
.BR "$\&Revision: \*(Rv $" .
This option is useful to ignore differences due to keyword substitution
when comparing different revisions of a file.
Log messages are inserted after
.B $\&Log$
keywords even if
.B \-kk
is specified,
since this tends to be more useful when merging changes.
.TP
.B \-ko
Generate the old keyword string,
present in the working file just before it was checked in.
For example, for the
.B Revision
keyword, generate the string
.B "$\&Revision: 1.1 $"
instead of
.B "$\&Revision: \*(Rv $"
if that is how the string appeared when the file was checked in.
This can be useful for file formats
that cannot tolerate any changes to substrings
that happen to take the form of keyword strings.
.TP
.B \-kb
Generate a binary image of the old keyword string.
This acts like
.BR \-ko ,
except it performs all working file input and output in binary mode.
This makes little difference on Posix and Unix hosts,
but on DOS-like hosts one should use
.B "rcs\ \-i\ \-kb"
to initialize an \*r file intended to be used for binary files.
Also, on all hosts,
.BR rcsmerge (1)
normally refuses to merge files when
.B \-kb
is in effect.
.TP
.B \-kv
Generate only keyword values for keyword strings.
For example, for the
.B Revision
keyword, generate the string
.B \*(Rv
instead of
.BR "$\&Revision: \*(Rv $" .
This can help generate files in programming languages where it is hard to
strip keyword delimiters like
.B "$\&Revision:\ $"
from a string.
However, further keyword substitution cannot be performed once the
keyword names are removed, so this option should be used with care.
Because of this danger of losing keywords,
this option cannot be combined with
.BR \-l ,
and the owner write permission of the working file is turned off;
to edit the file later, check it out again without
.BR \-kv .
.TP
.BR \-p [\f2rev\fP]
prints the retrieved revision on the standard output rather than storing it
in the working file.
This option is useful when
.B co
is part of a pipe.
.TP
.BR \-q [\f2rev\fP]
quiet mode; diagnostics are not printed.
.TP
.BR \-I [\f2rev\fP]
interactive mode;
the user is prompted and questioned
even if the standard input is not a terminal.
.TP
.BI \-d date
retrieves the latest revision on the selected branch whose checkin date/time is
less than or equal to
.IR date .
The date and time can be given in free format.
The time zone
.B LT
stands for local time;
other common time zone names are understood.
For example, the following
.IR date s
are equivalent
if local time is January 11, 1990, 8pm Pacific Standard Time,
eight hours west of Coordinated Universal Time (\*u):
.RS
.LP
.RS
.nf
.ta \w'\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP 'u
.ne 10
\f38:00 pm lt\fP
\f34:00 AM, Jan. 12, 1990\fP default is \*u
\f31990-01-12 04:00:00+00\fP \*i 8601 (\*u)
\f31990-01-11 20:00:00\-08\fP \*i 8601 (local time)
\f31990/01/12 04:00:00\fP traditional \*r format
\f3Thu Jan 11 20:00:00 1990 LT\fP output of \f3ctime\fP(3) + \f3LT\fP
\f3Thu Jan 11 20:00:00 PST 1990\fP output of \f3date\fP(1)
\f3Fri Jan 12 04:00:00 GMT 1990\fP
\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP Internet RFC 822
\f312-January-1990, 04:00 WET\fP
.ta 4n +4n +4n +4n
.fi
.RE
.LP
Most fields in the date and time can be defaulted.
The default time zone is normally \*u, but this can be overridden by the
.B \-z
option.
The other defaults are determined in the order year, month, day,
hour, minute, and second (most to least significant). At least one of these
fields must be provided. For omitted fields that are of higher significance
than the highest provided field, the time zone's current values are assumed.
For all other omitted fields,
the lowest possible values are assumed.
For example, without
.BR \-z ,
the date
.B "20, 10:30"
defaults to
10:30:00 \*u of the 20th of the \*u time zone's current month and year.
The date/time must be quoted if it contains spaces.
.RE
.TP
.BR \-M [\f2rev\fP]
Set the modification time on the new working file
to be the date of the retrieved revision.
Use this option with care; it can confuse
.BR make (1).
.TP
.BI \-s state
retrieves the latest revision on the selected branch whose state is set to
.IR state .
.TP
.B \-T
Preserve the modification time on the \*r file
even if the \*r file changes because a lock is added or removed.
This option can suppress extensive recompilation caused by a
.BR make (1)
dependency of some other copy of the working file on the \*r file.
Use this option with care; it can suppress recompilation even when it is needed,
i.e. when the change of lock
would mean a change to keyword strings in the other working file.
.TP
.BR \-w [\f2login\fP]
retrieves the latest revision on the selected branch which was checked in
by the user with login name
.IR login .
If the argument
.I login
is
omitted, the caller's login is assumed.
.TP
.BI \-j joinlist
generates a new revision which is the join of the revisions on
.IR joinlist .
This option is largely obsoleted by
.BR rcsmerge (1)
but is retained for backwards compatibility.
.RS
.PP
The
.I joinlist
is a comma-separated list of pairs of the form
.IB rev2 : rev3,
where
.I rev2
and
.I rev3
are (symbolic or numeric)
revision numbers.
For the initial such pair,
.I rev1
denotes the revision selected
by the above options
.BR \-f ,
\&.\|.\|.,
.BR \-w .
For all other pairs,
.I rev1
denotes the revision generated by the previous pair.
(Thus, the output
of one join becomes the input to the next.)
.PP
For each pair,
.B co
joins revisions
.I rev1
and
.I rev3
with respect to
.IR rev2 .
This means that all changes that transform
.I rev2
into
.I rev1
are applied to a copy of
.IR rev3 .
This is particularly useful if
.I rev1
and
.I rev3
are the ends of two branches that have
.I rev2
as a common ancestor. If
.IR rev1 < rev2 < rev3
on the same branch,
joining generates a new revision which is like
.I rev3,
but with all changes that lead from
.I rev1
to
.I rev2
undone.
If changes from
.I rev2
to
.I rev1
overlap with changes from
.I rev2
to
.I rev3,
.B co
reports overlaps as described in
.BR merge (1).
.PP
For the initial pair,
.I rev2
can be omitted. The default is the common
ancestor.
If any of the arguments indicate branches, the latest revisions
on those branches are assumed.
The options
.B \-l
and
.B \-u
lock or unlock
.IR rev1 .
.RE
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.I n,
where
.I n
can be
.BR 3 ,
.BR 4 ,
or
.BR 5 .
This can be useful when interchanging \*r files with others who are
running older versions of \*r.
To see which version of \*r your correspondents are running, have them invoke
.BR "rcs \-V" ;
this works with newer versions of \*r.
If it doesn't work, have them invoke
.B rlog
on an \*r file;
if none of the first few lines of output contain the string
.B branch:
it is version 3;
if the dates' years have just two digits, it is version 4;
otherwise, it is version 5.
An \*r file generated while emulating version 3 loses its default branch.
An \*r revision generated while emulating version 4 or earlier has
a time stamp that is off by up to 13 hours.
A revision extracted while emulating version 4 or earlier contains
abbreviated dates of the form
.IB yy / mm / dd
and can also contain different white space and line prefixes
in the substitution for
.BR $\&Log$ .
.TP
.BI \-x "suffixes"
Use
.I suffixes
to characterize \*r files.
See
.BR ci (1)
for details.
.TP
.BI \-z zone
specifies the date output format in keyword substitution,
and specifies the default time zone for
.I date
in the
.BI \-d date
option.
The
.I zone
should be empty, a numeric \*u offset, or the special string
.B LT
for local time.
The default is an empty
.IR zone ,
which uses the traditional \*r format of \*u without any time zone indication
and with slashes separating the parts of the date;
otherwise, times are output in \*i 8601 format with time zone indication.
For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
eight hours west of \*u,
then the time is output as follows:
.RS
.LP
.RS
.nf
.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
.ne 4
\f2option\fP \f2time output\fP
\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
.ta 4n +4n +4n +4n
.fi
.RE
.LP
The
.B \-z
option does not affect dates stored in \*r files,
which are always \*u.
.RE
.SH "KEYWORD SUBSTITUTION"
Strings of the form
.BI $ keyword $
and
.BI $ keyword : .\|.\|. $
embedded in
the text are replaced
with strings of the form
.BI $ keyword : value $
where
.I keyword
and
.I value
are pairs listed below.
Keywords can be embedded in literal strings
or comments to identify a revision.
.PP
Initially, the user enters strings of the form
.BI $ keyword $ .
On checkout,
.B co
replaces these strings with strings of the form
.BI $ keyword : value $ .
If a revision containing strings of the latter form
is checked back in, the value fields will be replaced during the next
checkout.
Thus, the keyword values are automatically updated on checkout.
This automatic substitution can be modified by the
.B \-k
options.
.PP
Keywords and their corresponding values:
.TP
.B $\&Author$
The login name of the user who checked in the revision.
.TP
.B $\&Date$
The date and time the revision was checked in.
With
.BI \-z zone
a numeric time zone offset is appended; otherwise, the date is \*u.
.TP
.B $\&Header$
A standard header containing the full pathname of the \*r file, the
revision number, the date and time, the author, the state,
and the locker (if locked).
With
.BI \-z zone
a numeric time zone offset is appended to the date; otherwise, the date is \*u.
.TP
.B $\&Id$
Same as
.BR $\&Header$ ,
except that the \*r filename is without a path.
.TP
.B $\&Locker$
The login name of the user who locked the revision (empty if not locked).
.TP
.B $\&Log$
The log message supplied during checkin, preceded by a header
containing the \*r filename, the revision number, the author, and the date
and time.
With
.BI \-z zone
a numeric time zone offset is appended; otherwise, the date is \*u.
Existing log messages are
.I not
replaced.
Instead, the new log message is inserted after
.BR $\&Log: .\|.\|. $ .
This is useful for
accumulating a complete change log in a source file.
.RS
.LP
Each inserted line is prefixed by the string that prefixes the
.B $\&Log$
line. For example, if the
.B $\&Log$
line is
.RB \*(lq "//\ $\&Log: tan.cc\ $" \*(rq,
\*r prefixes each line of the log with
.RB \*(lq "//\ " \*(rq.
This is useful for languages with comments that go to the end of the line.
The convention for other languages is to use a
.RB \*(lq " \(** " \(rq
prefix inside a multiline comment.
For example, the initial log comment of a C program
conventionally is of the following form:
.RS
.LP
.nf
.ft 3
.ne 3
/\(**
.in +\w'/'u
\(** $\&Log$
\(**/
.in
.ft
.fi
.RE
.LP
For backwards compatibility with older versions of \*r, if the log prefix is
.B /\(**
or
.B (\(**
surrounded by optional white space, inserted log lines contain a space
instead of
.B /
or
.BR ( ;
however, this usage is obsolescent and should not be relied on.
.RE
.TP
.B $\&Name$
The symbolic name used to check out the revision, if any.
For example,
.B "co\ \-rJoe"
generates
.BR "$\&Name:\ Joe\ $" .
Plain
.B co
generates just
.BR "$\&Name:\ \ $" .
.TP
.B $\&RCSfile$
The name of the \*r file without a path.
.TP
.B $\&Revision$
The revision number assigned to the revision.
.TP
.B $\&Source$
The full pathname of the \*r file.
.TP
.B $\&State$
The state assigned to the revision with the
.B \-s
option of
.BR rcs (1)
or
.BR ci (1).
.PP
The following characters in keyword values are represented by escape sequences
to keep keyword strings well-formed.
.LP
.RS
.nf
.ne 6
.ta \w'newline 'u
\f2char escape sequence\fP
tab \f3\et\fP
newline \f3\en\fP
space \f3\e040
$ \e044
\e \e\e\fP
.fi
.RE
.SH "FILE MODES"
The working file inherits the read and execute permissions from the \*r
file. In addition, the owner write permission is turned on, unless
.B \-kv
is set or the file
is checked out unlocked and locking is set to strict (see
.BR rcs (1)).
.PP
If a file with the name of the working file exists already and has write
permission,
.B co
aborts the checkout,
asking beforehand if possible.
If the existing working file is
not writable or
.B \-f
is given, the working file is deleted without asking.
.SH FILES
.B co
accesses files much as
.BR ci (1)
does, except that it does not need to read the working file
unless a revision number of
.B $
is specified.
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
See
.BR ci (1)
for details.
.SH DIAGNOSTICS
The \*r pathname, the working pathname,
and the revision number retrieved are
written to the diagnostic output.
The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
rcsintro(1), ci(1), ctime(3), date(1), ident(1), make(1),
rcs(1), rcsclean(1), rcsdiff(1), rcsmerge(1), rlog(1),
rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.SH LIMITS
Links to the \*r and working files are not preserved.
.PP
There is no way to selectively suppress the expansion of keywords, except
by writing them differently. In nroff and troff, this is done by embedding the
null-character
.B \e&
into the keyword.
.br

826
gnu/usr.bin/rcs/co/co.c Normal file
View file

@ -0,0 +1,826 @@
/* Check out working files from revisions of RCS files. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.18 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.17 1995/06/01 16:23:43 eggert
* (main, preparejoin): Pass argument instead of using `join' static variable.
* (main): Add -kb.
*
* Revision 5.16 1994/03/17 14:05:48 eggert
* Move buffer-flushes out of critical sections, since they aren't critical.
* Use ORCSerror to clean up after a fatal error. Remove lint.
* Specify subprocess input via file descriptor, not file name.
*
* Revision 5.15 1993/11/09 17:40:15 eggert
* -V now prints version on stdout and exits. Don't print usage twice.
*
* Revision 5.14 1993/11/03 17:42:27 eggert
* Add -z. Generate a value for the Name keyword.
* Don't arbitrarily limit the number of joins.
* Improve quality of diagnostics.
*
* Revision 5.13 1992/07/28 16:12:44 eggert
* Add -V. Check that working and RCS files are distinct.
*
* Revision 5.12 1992/02/17 23:02:08 eggert
* Add -T.
*
* Revision 5.11 1992/01/24 18:44:19 eggert
* Add support for bad_creat0. lint -> RCS_lint
*
* Revision 5.10 1992/01/06 02:42:34 eggert
* Update usage string.
*
* Revision 5.9 1991/10/07 17:32:46 eggert
* -k affects just working file, not RCS file.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Warn before removing somebody else's file.
* Add -M. Fix co -j bugs. Tune.
*
* Revision 5.7 1991/04/21 11:58:15 eggert
* Ensure that working file is newer than RCS file after co -[lu].
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.6 1990/12/04 05:18:38 eggert
* Don't checkaccesslist() unless necessary.
* Use -I for prompts and -q for diagnostics.
*
* Revision 5.5 1990/11/01 05:03:26 eggert
* Fix -j. Add -I.
*
* Revision 5.4 1990/10/04 06:30:11 eggert
* Accumulate exit status across files.
*
* Revision 5.3 1990/09/11 02:41:09 eggert
* co -kv yields a readonly working file.
*
* Revision 5.2 1990/09/04 08:02:13 eggert
* Standardize yes-or-no procedure.
*
* Revision 5.0 1990/08/22 08:10:02 eggert
* Permit multiple locks by same user. Add setuid support.
* Remove compile-time limits; use malloc instead.
* Permit dates past 1999/12/31. Switch to GMT.
* Make lock and temp files faster and safer.
* Ansify and Posixate. Add -k, -V. Remove snooping. Tune.
*
* Revision 4.7 89/05/01 15:11:41 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.6 88/08/09 19:12:15 eggert
* Fix "co -d" core dump; rawdate wasn't always initialized.
* Use execv(), not system(); fix putchar('\0') and diagnose() botches; remove lint
*
* Revision 4.5 87/12/18 11:35:40 narten
* lint cleanups (from Guy Harris)
*
* Revision 4.4 87/10/18 10:20:53 narten
* Updating version numbers changes relative to 1.1, are actually
* relative to 4.2
*
* Revision 1.3 87/09/24 13:58:30 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:21:38 jenkins
* Port to suns
*
* Revision 4.2 83/12/05 13:39:48 wft
* made rewriteflag external.
*
* Revision 4.1 83/05/10 16:52:55 wft
* Added option -u and -f.
* Added handling of default branch.
* Replaced getpwuid() with getcaller().
* Removed calls to stat(); now done by pairfilenames().
* Changed and renamed rmoldfile() to rmworkfile().
* Replaced catchints() calls with restoreints(), unlink()--link() with rename();
*
* Revision 3.7 83/02/15 15:27:07 wft
* Added call to fastcopy() to copy remainder of RCS file.
*
* Revision 3.6 83/01/15 14:37:50 wft
* Added ignoring of interrupts while RCS file is renamed; this avoids
* deletion of RCS files during the unlink/link window.
*
* Revision 3.5 82/12/08 21:40:11 wft
* changed processing of -d to use DATEFORM; removed actual from
* call to preparejoin; re-fixed printing of done at the end.
*
* Revision 3.4 82/12/04 18:40:00 wft
* Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE.
* Fixed printing of "done".
*
* Revision 3.3 82/11/28 22:23:11 wft
* Replaced getlogin() with getpwuid(), flcose() with ffclose(),
* %02d with %.2d, mode generation for working file with WORKMODE.
* Fixed nil printing. Fixed -j combined with -l and -p, and exit
* for non-existing revisions in preparejoin().
*
* Revision 3.2 82/10/18 20:47:21 wft
* Mode of working file is now maintained even for co -l, but write permission
* is removed.
* The working file inherits its mode from the RCS file, plus write permission
* for the owner. The write permission is not given if locking is strict and
* co does not lock.
* An existing working file without write permission is deleted automatically.
* Otherwise, co asks (empty answer: abort co).
* Call to getfullRCSname() added, check for write error added, call
* for getlogin() fixed.
*
* Revision 3.1 82/10/13 16:01:30 wft
* fixed type of variables receiving from getc() (char -> int).
* removed unused variables.
*/
#include "rcsbase.h"
static char *addjoin P((char*));
static char const *getancestor P((char const*,char const*));
static int buildjoin P((char const*));
static int preparejoin P((char*));
static int rmlock P((struct hshentry const*));
static int rmworkfile P((void));
static void cleanup P((void));
static char const quietarg[] = "-q";
static char const *expandarg, *suffixarg, *versionarg, *zonearg;
static char const **joinlist; /* revisions to be joined */
static int joinlength;
static FILE *neworkptr;
static int exitstatus;
static int forceflag;
static int lastjoin; /* index of last element in joinlist */
static int lockflag; /* -1 -> unlock, 0 -> do nothing, 1 -> lock */
static int mtimeflag;
static struct hshentries *gendeltas; /* deltas to be generated */
static struct hshentry *targetdelta; /* final delta to be generated */
static struct stat workstat;
mainProg(coId, "co", "$FreeBSD$")
{
static char const cmdusage[] =
"\nco usage: co -{fIlMpqru}[rev] -ddate -jjoins -ksubst -sstate -T -w[who] -Vn -xsuff -zzone file ...";
char *a, *joinflag, **newargv;
char const *author, *date, *rev, *state;
char const *joinname, *newdate, *neworkname;
int changelock; /* 1 if a lock has been changed, -1 if error */
int expmode, r, tostdout, workstatstat;
int Ttimeflag;
struct buf numericrev; /* expanded revision number */
char finaldate[datesize];
# if OPEN_O_BINARY
int stdout_mode = 0;
# endif
setrid();
author = date = rev = state = 0;
joinflag = 0;
bufautobegin(&numericrev);
expmode = -1;
suffixes = X_DEFAULT;
tostdout = false;
Ttimeflag = false;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
switch (*a++) {
case 'r':
revno:
if (*a) {
if (rev) warn("redefinition of revision number");
rev = a;
}
break;
case 'f':
forceflag=true;
goto revno;
case 'l':
if (lockflag < 0) {
warn("-u overridden by -l.");
}
lockflag = 1;
goto revno;
case 'u':
if (0 < lockflag) {
warn("-l overridden by -u.");
}
lockflag = -1;
goto revno;
case 'p':
tostdout = true;
goto revno;
case 'I':
interactiveflag = true;
goto revno;
case 'q':
quietflag=true;
goto revno;
case 'd':
if (date)
redefined('d');
str2date(a, finaldate);
date=finaldate;
break;
case 'j':
if (*a) {
if (joinflag) redefined('j');
joinflag = a;
}
break;
case 'M':
mtimeflag = true;
goto revno;
case 's':
if (*a) {
if (state) redefined('s');
state = a;
}
break;
case 'T':
if (*a)
goto unknown;
Ttimeflag = true;
break;
case 'w':
if (author) redefined('w');
if (*a)
author = a;
else
author = getcaller();
break;
case 'x':
suffixarg = *argv;
suffixes = a;
break;
case 'V':
versionarg = *argv;
setRCSversion(versionarg);
break;
case 'z':
zonearg = *argv;
zone_set(a);
break;
case 'k': /* set keyword expand mode */
expandarg = *argv;
if (0 <= expmode) redefined('k');
if (0 <= (expmode = str2expmode(a)))
break;
/* fall into */
default:
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
/* Now handle all pathnames. */
if (nerror) cleanup();
else if (argc < 1) faterror("no input file%s", cmdusage);
else for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
if (pairnames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
continue;
/*
* RCSname contains the name of the RCS file, and finptr
* points at it. workname contains the name of the working file.
* Also, RCSstat has been set.
*/
diagnose("%s --> %s\n", RCSname, tostdout?"standard output":workname);
workstatstat = -1;
if (tostdout) {
# if OPEN_O_BINARY
int newmode = Expand==BINARY_EXPAND ? OPEN_O_BINARY : 0;
if (stdout_mode != newmode) {
stdout_mode = newmode;
oflush();
VOID setmode(STDOUT_FILENO, newmode);
}
# endif
neworkname = 0;
neworkptr = workstdout = stdout;
} else {
workstatstat = stat(workname, &workstat);
if (workstatstat == 0 && same_file(RCSstat, workstat, 0)) {
rcserror("RCS file is the same as working file %s.",
workname
);
continue;
}
neworkname = makedirtemp(1);
if (!(neworkptr = fopenSafer(neworkname, FOPEN_W_WORK))) {
if (errno == EACCES)
workerror("permission denied on parent directory");
else
eerror(neworkname);
continue;
}
}
gettree(); /* reads in the delta tree */
if (!Head) {
/* no revisions; create empty file */
diagnose("no revisions present; generating empty revision 0.0\n");
if (lockflag)
warn(
"no revisions, so nothing can be %slocked",
lockflag < 0 ? "un" : ""
);
Ozclose(&fcopy);
if (workstatstat == 0)
if (!rmworkfile()) continue;
changelock = 0;
newdate = 0;
} else {
int locks = lockflag ? findlock(false, &targetdelta) : 0;
if (rev) {
/* expand symbolic revision number */
if (!expandsym(rev, &numericrev))
continue;
} else {
switch (locks) {
default:
continue;
case 0:
bufscpy(&numericrev, Dbranch?Dbranch:"");
break;
case 1:
bufscpy(&numericrev, targetdelta->num);
break;
}
}
/* get numbers of deltas to be generated */
if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas)))
continue;
/* check reservations */
changelock =
lockflag < 0 ?
rmlock(targetdelta)
: lockflag == 0 ?
0
:
addlock(targetdelta, true);
if (
changelock < 0
|| (changelock && !checkaccesslist())
|| dorewrite(lockflag, changelock) != 0
)
continue;
if (0 <= expmode)
Expand = expmode;
if (0 < lockflag && Expand == VAL_EXPAND) {
rcserror("cannot combine -kv and -l");
continue;
}
if (joinflag && !preparejoin(joinflag))
continue;
diagnose("revision %s%s\n",targetdelta->num,
0<lockflag ? " (locked)" :
lockflag<0 ? " (unlocked)" : "");
/* Prepare to remove old working file if necessary. */
if (workstatstat == 0)
if (!rmworkfile()) continue;
/* skip description */
getdesc(false); /* don't echo*/
locker_expansion = 0 < lockflag;
targetdelta->name = namedrev(rev, targetdelta);
joinname = buildrevision(
gendeltas, targetdelta,
joinflag&&tostdout ? (FILE*)0 : neworkptr,
Expand < MIN_UNEXPAND
);
# 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,
Ttimeflag ? RCSstat.st_mtime : (time_t)-1
) != 0)
continue;
if (changelock) {
locks += lockflag;
if (1 < locks)
rcswarn("You now have %d locks.", locks);
}
newdate = targetdelta->date;
if (joinflag) {
newdate = 0;
if (!joinname) {
aflush(neworkptr);
joinname = neworkname;
}
if (Expand == BINARY_EXPAND)
workerror("merging binary files");
if (!buildjoin(joinname))
continue;
}
}
if (!tostdout) {
mode_t m = WORKMODE(RCSstat.st_mode,
! (Expand==VAL_EXPAND || (lockflag<=0 && StrictLocks))
);
time_t t = mtimeflag&&newdate ? date2time(newdate) : (time_t)-1;
aflush(neworkptr);
ignoreints();
r = chnamemod(&neworkptr, neworkname, workname, 1, m, t);
keepdirtemp(neworkname);
restoreints();
if (r != 0) {
eerror(workname);
error("see %s", neworkname);
continue;
}
diagnose("done\n");
}
}
tempunlink();
Ofclose(workstdout);
exitmain(exitstatus);
} /* end of main (co) */
static void
cleanup()
{
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
ORCSclose();
# if !large_memory
if (fcopy!=workstdout) Ozclose(&fcopy);
# endif
if (neworkptr!=workstdout) Ozclose(&neworkptr);
dirtempunlink();
}
#if RCS_lint
# define exiterr coExit
#endif
void
exiterr()
{
ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
}
/*****************************************************************
* The following routines are auxiliary routines
*****************************************************************/
static int
rmworkfile()
/*
* Prepare to remove workname, 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): ",
workname,
myself(workstat.st_uid) ? "" : ", and you do not own it"
)) {
error(!quietflag && ttystdin()
? "checkout aborted"
: "writable %s exists; checkout aborted", workname);
return false;
}
}
/* Actual unlink is done later by caller. */
return true;
}
static int
rmlock(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 rcslock * next, * trail;
char const *num;
struct rcslock dummy;
int whomatch, nummatch;
num=delta->num;
dummy.nextlock=next=Locks;
trail = &dummy;
while (next) {
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)) {
rcserror("revision %s locked by %s; use co -r or rcs -u",
num, next->login
);
return -1;
}
trail=next;
next=next->nextlock;
}
if (next) {
/*found one; delete it */
trail->nextlock=next->nextlock;
Locks=dummy.nextlock;
next->delta->lockedby = 0;
return 1; /*success*/
} else return 0; /*no lock on delta*/
}
/*****************************************************************
* The rest of the routines are for handling joins
*****************************************************************/
static char *
addjoin(joinrev)
char *joinrev;
/* Add joinrev's number to joinlist, yielding address of char past joinrev,
* or 0 if no such revision exists.
*/
{
register char *j;
register struct hshentry *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*)0,(char*)0,(char*)0,&joindeltas);
bufautoend(&numrev);
*j = terminator;
if (d) {
joinlist[++lastjoin] = d->num;
return j;
}
return 0;
}
static int
preparejoin(j)
register char *j;
/* Parse join list J and place pointers to the
* revision numbers into joinlist.
*/
{
lastjoin= -1;
for (;;) {
while ((*j==' ')||(*j=='\t')||(*j==',')) j++;
if (*j=='\0') break;
if (lastjoin>=joinlength-2) {
joinlist =
(joinlength *= 2) == 0
? tnalloc(char const *, joinlength = 16)
: trealloc(char const *, joinlist, joinlength);
}
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 {
rcsfaterror("join pair incomplete");
}
} 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 {
rcsfaterror("join pair incomplete");
}
}
}
if (lastjoin < 1)
rcsfaterror("empty join");
return true;
}
static char const *
getancestor(r1, r2)
char const *r1, *r2;
/* Yield the common ancestor of r1 and r2 if successful, 0 otherwise.
* Work reliably only if r1 and r2 are not branch numbers.
*/
{
static struct buf t1, t2;
int 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 ? 2 : l1);
VOID partialno(&t2, r2, l2>2 ? 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);
}
rcserror("common ancestor of %s and %s undefined", r1, r2);
return 0;
}
static int
buildjoin(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[11];
char const **p;
bufautobegin(&commarg);
bufautobegin(&subs);
rev2 = maketemp(0);
rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */
cov[1] = CO;
/* cov[2] setup below */
p = &cov[3];
if (expandarg) *p++ = expandarg;
if (suffixarg) *p++ = suffixarg;
if (versionarg) *p++ = versionarg;
if (zonearg) *p++ = zonearg;
*p++ = quietarg;
*p++ = RCSname;
*p = 0;
mergev[1] = MERGE;
mergev[2] = mergev[4] = "-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[2] = commarg.string;
if (runv(-1, rev2, cov))
goto badmerge;
diagnose("revision %s\n",joinlist[i+1]);
bufscpy(&commarg, "-p");
bufscat(&commarg, joinlist[i+1]);
cov[2] = commarg.string;
if (runv(-1, rev3, cov))
goto badmerge;
diagnose("merging...\n");
mergev[3] = subs.string;
mergev[5] = joinlist[i+1];
p = &mergev[6];
if (quietflag) *p++ = quietarg;
if (lastjoin<=i+2 && workstdout) *p++ = "-p";
*p++ = initialfile;
*p++ = rev2;
*p++ = rev3;
*p = 0;
switch (runv(-1, (char*)0, 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;
}

1518
gnu/usr.bin/rcs/doc/rcs.ms Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,95 @@
.SH
Functions of RCS (Revision Control System)
.PP
RCS manages software libraries. It greatly increases programmer productivity
by providing the following functions.
.IP 1.
RCS stores and retrieves multiple revisions of program and other text.
Thus, one can maintain one or more releases while developing the next
release, with a minimum of space overhead. Changes no longer destroy the
original -- previous revisions remain accessible.
.RS
.IP a.
Maintains each module as a tree of revisions.
.IP b.
Project libraries can
be organized centrally, decentralized, or any way you like.
.IP c.
RCS works for any type of text: programs, documentation, memos, papers,
graphics, VLSI layouts, form letters, etc.
.RE
.IP 2.
RCS maintains a complete history of changes.
Thus, one can find out what happened to a module easily
and quickly, without having to compare source listings or
having to track down colleagues.
.RS
.IP a.
RCS performs automatic record keeping.
.IP b.
RCS logs all changes automatically.
.IP c.
RCS guarantees project continuity.
.RE
.IP 3.
RCS manages multiple lines of development.
.IP 4.
RCS can merge multiple lines of development.
Thus, when several parallel lines of development must be consolidated
into one line, the merging of changes is automatic.
.IP 5.
RCS flags coding conflicts.
If two or more lines of development modify the same section of code,
RCS can alert programmers about overlapping changes.
.IP 6.
RCS resolves access conflicts.
When two or more programmers wish to modify the same revision,
RCS alerts the programmers and makes sure that one modification won't wipe
out the other one.
.IP 7.
RCS provides high-level retrieval functions.
Revisions can be retrieved according to ranges of revision numbers,
symbolic names, dates, authors, and states.
.IP 8.
RCS provides release and configuration control.
Revisions can be marked as released, stable, experimental, etc.
Configurations of modules can be described simply and directly.
.IP 9.
RCS performs automatic identification of modules with name, revision
number, creation time, author, etc.
Thus, it is always possible to determine which revisions of which
modules make up a given configuration.
.IP 10.
Provides high-level management visibility.
Thus, it is easy to track the status of a software project.
.RS
.IP a.
RCS provides a complete change history.
.IP b.
RCS records who did what when to which revision of which module.
.RE
.IP 11.
RCS is fully compatible with existing software development tools.
RCS is unobtrusive -- its interface to the file system is such that
all your existing software tools can be used as before.
.IP 12.
RCS' basic user interface is extremely simple. The novice need to learn
only two commands. Its more sophisticated features have been
tuned towards advanced software development environments and the
experienced software professional.
.IP 13.
RCS simplifies software distribution if customers
maintain sources with RCS also. This technique assures proper
identification of versions and configurations, and tracking of customer
modifications. Customer modifications can be merged into distributed
versions locally or by the development group.
.IP 14.
RCS needs little extra space for the revisions (only the differences).
If intermediate revisions are deleted, the corresponding
differences are compressed into the shortest possible form.
.IP 15.
RCS is implemented with reverse deltas. This means that
the latest revision, which is the one that is accessed most often,
is stored intact. All others are regenerated from the latest one
by applying reverse deltas (backward differences). This
results in fast access time for the revision needed most often.

View file

@ -0,0 +1,8 @@
PROG= ident
SRCS= ident.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View file

@ -0,0 +1,182 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
.ds iD \\$3 \\$4 \\$5 \\$6 \\$7
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH IDENT 1 \*(Dt GNU
.SH NAME
ident \- identify RCS keyword strings in files
.SH SYNOPSIS
.B ident
[
.B \-q
] [
.B \-V
] [
.I file
\&.\|.\|. ]
.SH DESCRIPTION
.B ident
searches for all instances of the pattern
.BI $ keyword : "\ text\ " $
in the named files or, if no files are named, the standard input.
.PP
These patterns are normally inserted automatically by the \*r command
.BR co (1),
but can also be inserted manually.
The option
.B \-q
suppresses
the warning given if there are no patterns in a file.
The option
.B \-V
prints
.BR ident 's
version number.
.PP
.B ident
works on text files as well as object files and dumps.
For example, if the C program in
.B f.c
contains
.IP
.ft 3
#include <stdio.h>
.br
static char const rcsid[] =
.br
\&"$\&Id: f.c,v \*(iD $\&";
.br
int main() { return printf(\&"%s\en\&", rcsid) == EOF; }
.ft P
.LP
and
.B f.c
is compiled into
.BR f.o ,
then the command
.IP
.B "ident f.c f.o"
.LP
will output
.nf
.IP
.ft 3
f.c:
$\&Id: f.c,v \*(iD $
f.o:
$\&Id: f.c,v \*(iD $
.ft
.fi
.PP
If a C program defines a string like
.B rcsid
above but does not use it,
.BR lint (1)
may complain, and some C compilers will optimize away the string.
The most reliable solution is to have the program use the
.B rcsid
string, as shown in the example above.
.PP
.B ident
finds all instances of the
.BI $ keyword : "\ text\ " $
pattern, even if
.I keyword
is not actually an \*r-supported keyword.
This gives you information about nonstandard keywords like
.BR $\&XConsortium$ .
.SH KEYWORDS
Here is the list of keywords currently maintained by
.BR co (1).
All times are given in Coordinated Universal Time (\*u,
sometimes called \&\s-1GMT\s0) by default, but if the files
were checked out with
.BR co 's
.BI \-z zone
option, times are given with a numeric time zone indication appended.
.TP
.B $\&Author$
The login name of the user who checked in the revision.
.TP
.B $\&Date$
The date and time the revision was checked in.
.TP
.B $\&Header$
A standard header containing the full pathname of the \*r file, the
revision number, the date and time, the author, the state,
and the locker (if locked).
.TP
.B $\&Id$
Same as
.BR $\&Header$ ,
except that the \*r filename is without a path.
.TP
.B $\&Locker$
The login name of the user who locked the revision (empty if not locked).
.TP
.B $\&Log$
The log message supplied during checkin.
For
.BR ident 's
purposes, this is equivalent to
.BR $\&RCSfile$ .
.TP
.B $\&Name$
The symbolic name used to check out the revision, if any.
.TP
.B $\&RCSfile$
The name of the \*r file without a path.
.TP
.B $\&Revision$
The revision number assigned to the revision.
.TP
.B $\&Source$
The full pathname of the \*r file.
.TP
.B $\&State$
The state assigned to the revision with the
.B \-s
option of
.BR rcs (1)
or
.BR ci (1).
.PP
.BR co (1)
represents the following characters in keyword values by escape sequences
to keep keyword strings well-formed.
.LP
.RS
.nf
.ne 6
.ta \w'newline 'u
\f2char escape sequence\fP
tab \f3\et\fP
newline \f3\en\fP
space \f3\e040
$ \e044
\e \e\e\fP
.fi
.RE
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1992, 1993 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.

View file

@ -0,0 +1,270 @@
/* Identify RCS keyword strings in files. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.9 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.8 1995/06/01 16:23:43 eggert
* (exiterr, reportError): New functions, needed for DOS and OS/2 ports.
* (scanfile): Use them.
*
* Revision 5.7 1994/03/20 04:52:58 eggert
* Remove `exiting' from identExit.
*
* Revision 5.6 1993/11/09 17:40:15 eggert
* Add -V.
*
* Revision 5.5 1993/11/03 17:42:27 eggert
* Test for char == EOF, not char < 0.
*
* Revision 5.4 1992/01/24 18:44:19 eggert
* lint -> RCS_lint
*
* Revision 5.3 1991/09/10 22:15:46 eggert
* Open files with FOPEN_R, not FOPEN_R_WORK,
* because they might be executables, not working files.
*
* Revision 5.2 1991/08/19 03:13:55 eggert
* Report read errors immediately.
*
* Revision 5.1 1991/02/25 07:12:37 eggert
* Don't report empty keywords. Check for I/O errors.
*
* Revision 5.0 1990/08/22 08:12:37 eggert
* Don't limit output to known keywords.
* Remove arbitrary limits and lint. Ansify and Posixate.
*
* Revision 4.5 89/05/01 15:11:54 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 87/10/23 17:09:57 narten
* added exit(0) so exit return code would be non random
*
* Revision 4.3 87/10/18 10:23:55 narten
* Updating version numbers. Changes relative to 1.1 are actually relative
* to 4.1
*
* Revision 1.3 87/07/09 09:20:52 trinkle
* Added check to make sure there is at least one arg before comparing argv[1]
* with "-q". This necessary on machines that don't allow dereferncing null
* pointers (i.e. Suns).
*
* Revision 1.2 87/03/27 14:21:47 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:31:02 wft
* Added option -q and input from reading stdin.
* Marker matching is now done with trymatch() (independent of keywords).
*
* Revision 3.4 83/02/18 17:37:49 wft
* removed printing of new line after last file.
*
* Revision 3.3 82/12/04 12:48:55 wft
* Added LOCKER.
*
* Revision 3.2 82/11/28 18:24:17 wft
* removed Suffix; added ungetc to avoid skipping over trailing KDELIM.
*
* Revision 3.1 82/10/13 15:58:51 wft
* fixed type of variables receiving from getc() (char-->int).
*/
#include "rcsbase.h"
static int match P((FILE*));
static int scanfile P((FILE*,char const*,int));
static void reportError P((char const*));
mainProg(identId, "ident", "$FreeBSD$")
/* Ident searches the named files for all occurrences
* of the pattern $@: text $ where @ is a keyword.
*/
{
FILE *fp;
int quiet = 0;
int status = EXIT_SUCCESS;
char const *a;
while ((a = *++argv) && *a=='-')
while (*++a)
switch (*a) {
case 'q':
quiet = 1;
break;
case 'V':
VOID printf("RCS version %s\n", RCS_version_string);
quiet = -1;
break;
default:
VOID fprintf(stderr,
"ident: usage: ident -{qV} [file...]\n"
);
exitmain(EXIT_FAILURE);
break;
}
if (0 <= quiet)
if (!a)
VOID scanfile(stdin, (char*)0, quiet);
else
do {
if (!(fp = fopen(a, FOPEN_RB))) {
reportError(a);
status = EXIT_FAILURE;
} else if (
scanfile(fp, a, quiet) != 0
|| (argv[1] && putchar('\n') == EOF)
)
break;
} while ((a = *++argv));
if (ferror(stdout) || fclose(stdout)!=0) {
reportError("standard output");
status = EXIT_FAILURE;
}
exitmain(status);
}
#if RCS_lint
# define exiterr identExit
#endif
void
exiterr()
{
_exit(EXIT_FAILURE);
}
static void
reportError(s)
char const *s;
{
int e = errno;
VOID fprintf(stderr, "%s error: ", cmdid);
errno = e;
perror(s);
}
static int
scanfile(file, name, quiet)
register FILE *file;
char const *name;
int quiet;
/* Function: scan an open file with descriptor file for keywords.
* Return -1 if there's a write error; exit immediately on a read error.
*/
{
register int c;
if (name) {
VOID printf("%s:\n", name);
if (ferror(stdout))
return -1;
} else
name = "standard input";
c = 0;
while (c != EOF || ! (feof(file)|ferror(file))) {
if (c == KDELIM) {
if ((c = match(file)))
continue;
if (ferror(stdout))
return -1;
quiet = true;
}
c = getc(file);
}
if (ferror(file) || fclose(file) != 0) {
reportError(name);
/*
* The following is equivalent to exit(EXIT_FAILURE), but we invoke
* exiterr to keep lint happy. The DOS and OS/2 ports need exiterr.
*/
VOID fflush(stderr);
VOID fflush(stdout);
exiterr();
}
if (!quiet)
VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name);
return 0;
}
static int
match(fp) /* group substring between two KDELIM's; then do pattern match */
register FILE *fp;
{
char line[BUFSIZ];
register int c;
register char * tp;
tp = line;
while ((c = getc(fp)) != VDELIM) {
if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
case LETTER: case Letter: case DIGIT:
*tp++ = c;
if (tp < line+sizeof(line)-4)
break;
/* fall into */
default:
return c ? c : '\n'/* anything but 0 or KDELIM or EOF */;
}
}
if (tp == line)
return c;
*tp++ = c;
if ((c = getc(fp)) != ' ')
return c ? c : '\n';
*tp++ = c;
while( (c = getc(fp)) != KDELIM ) {
if (c == EOF && feof(fp) | ferror(fp))
return c;
switch (ctab[c]) {
default:
*tp++ = c;
if (tp < line+sizeof(line)-2)
break;
/* fall into */
case NEWLN: case UNKN:
return c ? c : '\n';
}
}
if (tp[-1] != ' ')
return c;
*tp++ = c; /*append trailing KDELIM*/
*tp = '\0';
VOID printf(" %c%s\n", KDELIM, line);
return 0;
}

View file

@ -0,0 +1,14 @@
# $FreeBSD$
# Define FSYNC_ALL to get slower but safer writes in case of crashes in
# the middle of CVS/RCS changes
#CFLAGS += -DFSYNC_ALL
LIB = rcs
SRCS = maketime.c partime.c rcsedit.c rcsfcmp.c rcsfnms.c rcsgen.c \
rcskeep.c rcskeys.c rcslex.c rcsmap.c rcsrev.c rcssyn.c rcstime.c \
rcsutil.c merger.c version.c
INTERNALLIB=
.include <bsd.lib.mk>

400
gnu/usr.bin/rcs/lib/conf.h Normal file
View file

@ -0,0 +1,400 @@
/* RCS compile-time configuration */
/* $FreeBSD$ */
/*
* This file is generated automatically.
* If you edit it by hand your changes may be lost.
* Instead, please try to fix conf.sh,
* and send your fixes to rcs-bugs@cs.purdue.edu.
*/
#define exitmain(n) return n /* how to exit from main() */
/* #define _POSIX_C_SOURCE 2147483647L */ /* if strict C + Posix 1003.1b-1993 or later */
/* #define _POSIX_SOURCE */ /* if strict C + Posix 1003.1-1990 */
#include <errno.h>
#include <stdio.h>
#include <time.h>
/* Comment out #include lines below that do not work. */
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
/* #include <mach/mach.h> */
/* #include <net/errno.h> */
#include <pwd.h>
/* #include <siginfo.h> */
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
/* #include <ucontext.h> */
#include <unistd.h>
#include <utime.h>
/* #include <vfork.h> */
/* Define boolean symbols to be 0 (false, the default), or 1 (true). */
#define has_sys_param_h 1 /* Does #include <sys/param.h> work? */
/* extern int errno; */ /* Uncomment if <errno.h> doesn't declare errno. */
#define has_readlink 1 /* Does readlink() work? */
#define readlink_isreg_errno EINVAL /* errno after readlink on regular file */
#if has_readlink && !defined(MAXSYMLINKS)
# if has_sys_param_h
# include <sys/param.h>
# endif
# ifndef MAXSYMLINKS
# define MAXSYMLINKS 20 /* BSD; not standard yet */
# endif
#endif
/* Comment out the typedefs below if the types are already declared. */
/* Fix any uncommented typedefs that are wrong. */
/* typedef int mode_t; */
/* typedef long off_t; */
/* typedef int pid_t; */
/* typedef int sig_atomic_t; */
/* typedef unsigned size_t; */
/* typedef int ssize_t; */
/* typedef long time_t; */
/* typedef int uid_t; */
/* Comment out the keyword definitions below if the keywords work. */
/* #define const */
/* #define volatile */
/* Define boolean symbols to be 0 (false, the default), or 1 (true). */
#define has_prototypes 1 /* Do function prototypes work? */
#define has_stdarg 1 /* Does <stdarg.h> work? */
/* #define has_varargs ? */ /* Does <varargs.h> work? */
#define va_start_args 2 /* How many args does va_start() take? */
#if O_BINARY
/* Text and binary i/o behave differently. */
/* This is incompatible with Posix and Unix. */
# define FOPEN_RB "rb"
# define FOPEN_R_WORK (Expand==BINARY_EXPAND ? "r" : "rb")
# define FOPEN_WB "wb"
# define FOPEN_W_WORK (Expand==BINARY_EXPAND ? "w" : "wb")
# define FOPEN_WPLUS_WORK (Expand==BINARY_EXPAND ? "w+" : "w+b")
# define OPEN_O_BINARY O_BINARY
#else
/*
* Text and binary i/o behave the same.
* Omit "b", since some nonstandard hosts reject it.
*/
# define FOPEN_RB "r"
# define FOPEN_R_WORK "r"
# define FOPEN_WB "w"
# define FOPEN_W_WORK "w"
# define FOPEN_WPLUS_WORK "w+"
# define OPEN_O_BINARY 0
#endif
/* This may need changing on non-Unix systems (notably DOS). */
#define OPEN_CREAT_READONLY (S_IRUSR|S_IRGRP|S_IROTH) /* lock file mode */
#define OPEN_O_LOCK 0 /* extra open flags for creating lock file */
#define OPEN_O_WRONLY O_WRONLY /* main open flag for creating a lock file */
/* Define or comment out the following symbols as needed. */
#if has_prototypes
# define P(params) params
#else
# define P(params) ()
#endif
#if has_stdarg
# include <stdarg.h>
#else
# if has_varargs
# include <varargs.h>
# else
typedef char *va_list;
# define va_dcl int va_alist;
# define va_start(ap) ((ap) = (va_list)&va_alist)
# define va_arg(ap,t) (((t*) ((ap)+=sizeof(t))) [-1])
# define va_end(ap)
# endif
#endif
#if va_start_args == 2
# define vararg_start va_start
#else
# define vararg_start(ap,p) va_start(ap)
#endif
#define bad_chmod_close 0 /* Can chmod() close file descriptors? */
#define bad_creat0 0 /* Do writes fail after creat(f,0)? */
#define bad_fopen_wplus 0 /* Does fopen(f,"w+") fail to truncate f? */
#define getlogin_is_secure 0 /* Is getlogin() secure? Usually it's not. */
#define has_attribute_noreturn 1 /* Does __attribute__((noreturn)) work? */
#if has_attribute_noreturn
# define exiting __attribute__((noreturn))
#else
# define exiting
#endif
#define has_dirent 1 /* Do opendir(), readdir(), closedir() work? */
#define void_closedir 0 /* Does closedir() yield void? */
#define has_fchmod 1 /* Does fchmod() work? */
#define has_fflush_input 0 /* Does fflush() work on input files? */
#define has_fputs 1 /* Does fputs() work? */
#define has_ftruncate 1 /* Does ftruncate() work? */
#define has_getuid 1 /* Does getuid() work? */
#define has_getpwuid 1 /* Does getpwuid() work? */
#define has_memcmp 1 /* Does memcmp() work? */
#define has_memcpy 1 /* Does memcpy() work? */
#define has_memmove 1 /* Does memmove() work? */
#define has_map_fd 0 /* Does map_fd() work? */
#define has_mmap 1 /* Does mmap() work on regular files? */
#define has_madvise 0 /* Does madvise() work? */
#define mmap_signal SIGBUS /* signal received if you reference nonexistent part of mmapped file */
#define has_rename 1 /* Does rename() work? */
#define bad_a_rename 0 /* Does rename(A,B) fail if A is unwritable? */
#define bad_b_rename 0 /* Does rename(A,B) fail if B is unwritable? */
#define bad_NFS_rename 0 /* Can rename(A,B) falsely report success? */
/* typedef int void; */ /* Some ancient compilers need this. */
#define VOID (void) /* 'VOID e;' discards the value of an expression 'e'. */
#define has_seteuid 1 /* Does seteuid() work? See ../INSTALL.RCS. */
#define has_setreuid 0 /* Does setreuid() work? See ../INSTALL.RCS. */
#define has_setuid 1 /* Does setuid() exist? */
#define has_sigaction 1 /* Does struct sigaction work? */
#define has_sa_sigaction 1 /* Does struct sigaction have sa_sigaction? */
#define has_signal 1 /* Does signal() work? */
#define signal_type void /* type returned by signal handlers */
#define sig_zaps_handler 0 /* Must a signal handler reinvoke signal()? */
/* #define has_sigblock ? */ /* Does sigblock() work? */
/* #define sigmask(s) (1 << ((s)-1)) */ /* Yield mask for signal number. */
typedef size_t fread_type; /* type returned by fread() and fwrite() */
typedef size_t freadarg_type; /* type of their size arguments */
typedef void *malloc_type; /* type returned by malloc() */
#define has_getcwd 1 /* Does getcwd() work? */
/* #define has_getwd ? */ /* Does getwd() work? */
#define needs_getabsname 0 /* Must we define getabsname? */
#define has_mktemp 1 /* Does mktemp() work? */
#define has_mkstemp 1 /* Does mkstemp() work? */
#define has_NFS 1 /* Might NFS be used? */
#define has_psiginfo 0 /* Does psiginfo() work? */
#define has_psignal 1 /* Does psignal() work? */
/* #define has_si_errno ? */ /* Does siginfo_t have si_errno? */
/* #define has_sys_siglist ? */ /* Does sys_siglist[] work? */
/* #define strchr index */ /* Use old-fashioned name for strchr()? */
/* #define strrchr rindex */ /* Use old-fashioned name for strrchr()? */
#define bad_unlink 0 /* Does unlink() fail on unwritable files? */
#define has_vfork 1 /* Does vfork() work? */
#define has_fork 1 /* Does fork() work? */
#define has_spawn 0 /* Does spawn*() work? */
#define has_waitpid 1 /* Does waitpid() work? */
#define bad_wait_if_SIGCHLD_ignored 0 /* Does ignoring SIGCHLD break wait()? */
#define RCS_SHELL "/bin/sh" /* shell to run RCS subprograms */
#define has_printf_dot 1 /* Does "%.2d" print leading 0? */
#define has_vfprintf 1 /* Does vfprintf() work? */
#define has_attribute_format_printf 1 /* Does __attribute__((format(printf,N,N+1))) work? */
#if has_attribute_format_printf
# define printf_string(m, n) __attribute__((format(printf, m, n)))
#else
# define printf_string(m, n)
#endif
#if has_attribute_format_printf && has_attribute_noreturn
/* Work around a bug in GCC 2.5.x. */
# define printf_string_exiting(m, n) __attribute__((format(printf, m, n), noreturn))
#else
# define printf_string_exiting(m, n) printf_string(m, n) exiting
#endif
/* #define has__doprintf ? */ /* Does _doprintf() work? */
/* #define has__doprnt ? */ /* Does _doprnt() work? */
/* #undef EXIT_FAILURE */ /* Uncomment this if EXIT_FAILURE is broken. */
#define large_memory 1 /* Can main memory hold entire RCS files? */
#ifndef LONG_MAX
#define LONG_MAX 2147483647L /* long maximum */
#endif
/* Do struct stat s and t describe the same file? Answer d if unknown. */
#define same_file(s,t,d) ((s).st_ino==(t).st_ino && (s).st_dev==(t).st_dev)
#define has_utimbuf 1 /* Does struct utimbuf work? */
#define CO "/usr/bin/co" /* name of 'co' program */
#define COMPAT2 0 /* Are version 2 files supported? */
#define DIFF "/usr/bin/diff" /* name of 'diff' program */
#define DIFF3 "/usr/bin/diff3" /* name of 'diff3' program */
#define DIFF3_BIN 1 /* Is diff3 user-visible (not the /usr/lib auxiliary)? */
#define DIFFFLAGS "-an" /* Make diff output suitable for RCS. */
#define DIFF_L 1 /* Does diff -L work? */
#define DIFF_SUCCESS 0 /* DIFF status if no differences are found */
#define DIFF_FAILURE 1 /* DIFF status if differences are found */
#define DIFF_TROUBLE 2 /* DIFF status if trouble */
#define ED "/bin/ed" /* name of 'ed' program (used only if !DIFF3_BIN) */
#define MERGE "/usr/bin/merge" /* name of 'merge' program */
#define TMPDIR "/tmp" /* default directory for temporary files */
#define SLASH '/' /* principal filename separator */
#define SLASHes '/' /* `case SLASHes:' labels all filename separators */
#define isSLASH(c) ((c) == SLASH) /* Is arg a filename separator? */
#define ROOTPATH(p) isSLASH((p)[0]) /* Is p an absolute pathname? */
#define X_DEFAULT ",v/" /* default value for -x option */
#define SLASHSLASH_is_SLASH 1 /* Are // and / the same directory? */
#define ALL_ABSOLUTE 1 /* Do all subprograms satisfy ROOTPATH? */
#define DIFF_ABSOLUTE 1 /* Is ROOTPATH(DIFF) true? */
#define SENDMAIL "/usr/sbin/sendmail" /* how to send mail */
#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work? */
/* Adjust the following declarations as needed. */
/* The rest is for the benefit of non-standard, traditional hosts. */
/* Don't bother to declare functions that in traditional hosts do not appear, */
/* or are declared in .h files, or return int or void. */
/* traditional BSD */
#if has_sys_siglist && !defined(sys_siglist)
extern char const * const sys_siglist[];
#endif
/* Posix (ISO/IEC 9945-1: 1990 / IEEE Std 1003.1-1990) */
/* <fcntl.h> */
#ifdef O_CREAT
# define open_can_creat 1
#else
# define open_can_creat 0
# define O_RDONLY 0
# define O_WRONLY 1
# define O_RDWR 2
# define O_CREAT 01000
# define O_TRUNC 02000
#endif
#ifndef O_EXCL
#define O_EXCL 0
#endif
/* <sys/stat.h> */
#ifndef S_IRUSR
# ifdef S_IREAD
# define S_IRUSR S_IREAD
# else
# define S_IRUSR 0400
# endif
# ifdef S_IWRITE
# define S_IWUSR S_IWRITE
# else
# define S_IWUSR (S_IRUSR/2)
# endif
#endif
#ifndef S_IRGRP
# if has_getuid
# define S_IRGRP (S_IRUSR / 0010)
# define S_IWGRP (S_IWUSR / 0010)
# define S_IROTH (S_IRUSR / 0100)
# define S_IWOTH (S_IWUSR / 0100)
# else
/* single user OS -- not Posix or Unix */
# define S_IRGRP 0
# define S_IWGRP 0
# define S_IROTH 0
# define S_IWOTH 0
# endif
#endif
#ifndef S_ISREG
#define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
#endif
/* <sys/wait.h> */
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat_val) (((stat_val) & 0377) == 0)
#endif
#ifndef WTERMSIG
#define WTERMSIG(stat_val) ((stat_val) & 0177)
#undef WIFSIGNALED /* Avoid 4.3BSD incompatibility with Posix. */
#endif
#ifndef WIFSIGNALED
#define WIFSIGNALED(stat_val) ((unsigned)(stat_val) - 1 < 0377)
#endif
/* <unistd.h> */
char *getlogin P((void));
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
#endif
#if has_fork && !has_vfork
# undef vfork
# define vfork fork
#endif
#if has_getcwd || !has_getwd
char *getcwd P((char*,size_t));
#else
char *getwd P((char*));
#endif
#if has_setuid && !has_seteuid
# undef seteuid
# define seteuid setuid
#endif
#if has_spawn
# if ALL_ABSOLUTE
# define spawn_RCS spawnv
# else
# define spawn_RCS spawnvp
# endif
#else
# if ALL_ABSOLUTE
# define exec_RCS execv
# else
# define exec_RCS execvp
# endif
#endif
/* utime.h */
#if !has_utimbuf
struct utimbuf { time_t actime, modtime; };
#endif
/* Standard C library */
/* <stdio.h> */
#ifndef L_tmpnam
#define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#if has_mktemp
char *mktemp P((char*)); /* traditional */
#else
char *tmpnam P((char*));
#endif
/* <stdlib.h> */
char *getenv P((char const*));
void _exit P((int)) exiting;
void exit P((int)) exiting;
malloc_type malloc P((size_t));
malloc_type realloc P((malloc_type,size_t));
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
/* <string.h> */
char *strcpy P((char*,char const*));
char *strchr P((char const*,int));
char *strrchr P((char const*,int));
void *memcpy P((void*,void const*,size_t));
#if has_memmove
void *memmove P((void*,void const*,size_t));
#endif
/* <time.h> */
time_t time P((time_t*));

View file

@ -0,0 +1,344 @@
/* Convert struct partime into time_t. */
/* Copyright 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#if has_conf_h
# include "conf.h"
#else
# ifdef __STDC__
# define P(x) x
# else
# define const
# define P(x) ()
# endif
# include <stdlib.h>
# include <time.h>
#endif
#include "partime.h"
#include "maketime.h"
char const maketId[]
= "$FreeBSD$";
static int isleap P((int));
static int month_days P((struct tm const*));
static time_t maketime P((struct partime const*,time_t));
/*
* For maximum portability, use only localtime and gmtime.
* Make no assumptions about the time_t epoch or the range of time_t values.
* Avoid mktime because it's not universal and because there's no easy,
* portable way for mktime to yield the inverse of gmtime.
*/
#define TM_YEAR_ORIGIN 1900
static int
isleap(y)
int y;
{
return (y&3) == 0 && (y%100 != 0 || y%400 == 0);
}
static int const month_yday[] = {
/* days in year before start of months 0-12 */
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
/* Yield the number of days in TM's month. */
static int
month_days(tm)
struct tm const *tm;
{
int m = tm->tm_mon;
return month_yday[m+1] - month_yday[m]
+ (m==1 && isleap(tm->tm_year + TM_YEAR_ORIGIN));
}
/*
* Convert UNIXTIME to struct tm form.
* Use gmtime if available and if !LOCALZONE, localtime otherwise.
*/
struct tm *
time2tm(unixtime, localzone)
time_t unixtime;
int localzone;
{
struct tm *tm;
# if TZ_must_be_set
static char const *TZ;
if (!TZ && !(TZ = getenv("TZ")))
faterror("The TZ environment variable is not set; please set it to your timezone");
# endif
if (localzone || !(tm = gmtime(&unixtime)))
tm = localtime(&unixtime);
return tm;
}
/* Yield A - B, measured in seconds. */
time_t
difftm(a, b)
struct tm const *a, *b;
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
int difference_in_day_of_year = a->tm_yday - b->tm_yday;
int intervening_leap_days = (
((ay >> 2) - (by >> 2))
- (ay/100 - by/100)
+ ((ay/100 >> 2) - (by/100 >> 2))
);
time_t difference_in_years = ay - by;
time_t difference_in_days = (
difference_in_years*365
+ (intervening_leap_days + difference_in_day_of_year)
);
return
(
(
24*difference_in_days
+ (a->tm_hour - b->tm_hour)
)*60 + (a->tm_min - b->tm_min)
)*60 + (a->tm_sec - b->tm_sec);
}
/*
* Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth.
* Adjust only T's year, mon, mday, hour, min and sec members;
* plus adjust wday if it is defined.
*/
void
adjzone(t, seconds)
register struct tm *t;
long seconds;
{
/*
* This code can be off by a second if SECONDS is not a multiple of 60,
* if T is local time, and if a leap second happens during this minute.
* But this bug has never occurred, and most likely will not ever occur.
* Liberia, the last country for which SECONDS % 60 was nonzero,
* switched to UTC in May 1972; the first leap second was in June 1972.
*/
int leap_second = t->tm_sec == 60;
long sec = seconds + (t->tm_sec - leap_second);
if (sec < 0) {
if ((t->tm_min -= (59-sec)/60) < 0) {
if ((t->tm_hour -= (59-t->tm_min)/60) < 0) {
t->tm_hour += 24;
if (TM_DEFINED(t->tm_wday) && --t->tm_wday < 0)
t->tm_wday = 6;
if (--t->tm_mday <= 0) {
if (--t->tm_mon < 0) {
--t->tm_year;
t->tm_mon = 11;
}
t->tm_mday = month_days(t);
}
}
t->tm_min += 24 * 60;
}
sec += 24L * 60 * 60;
} else
if (60 <= (t->tm_min += sec/60))
if (24 <= (t->tm_hour += t->tm_min/60)) {
t->tm_hour -= 24;
if (TM_DEFINED(t->tm_wday) && ++t->tm_wday == 7)
t->tm_wday = 0;
if (month_days(t) < ++t->tm_mday) {
if (11 < ++t->tm_mon) {
++t->tm_year;
t->tm_mon = 0;
}
t->tm_mday = 1;
}
}
t->tm_min %= 60;
t->tm_sec = (int) (sec%60) + leap_second;
}
/*
* Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
* Use only TM's year, mon, mday, hour, min, and sec members.
* Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
* Yield -1 on failure (e.g. a member out of range).
* Posix 1003.1-1990 doesn't allow leap seconds, but some implementations
* have them anyway, so allow them if localtime/gmtime does.
*/
time_t
tm2time(tm, localzone)
struct tm *tm;
int localzone;
{
/* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */
static time_t t_cache[2];
static struct tm tm_cache[2];
time_t d, gt;
struct tm const *gtm;
/*
* The maximum number of iterations should be enough to handle any
* combinations of leap seconds, time zone rule changes, and solar time.
* 4 is probably enough; we use a bigger number just to be safe.
*/
int remaining_tries = 8;
/* Avoid subscript errors. */
if (12 <= (unsigned)tm->tm_mon)
return -1;
tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday
- (tm->tm_mon<2 || ! isleap(tm->tm_year + TM_YEAR_ORIGIN));
/* Make a first guess. */
gt = t_cache[localzone];
gtm = gt ? &tm_cache[localzone] : time2tm(gt,localzone);
/* Repeatedly use the error from the guess to improve the guess. */
while ((d = difftm(tm, gtm)) != 0) {
if (--remaining_tries == 0)
return -1;
gt += d;
gtm = time2tm(gt,localzone);
}
t_cache[localzone] = gt;
tm_cache[localzone] = *gtm;
/*
* Check that the guess actually matches;
* overflow can cause difftm to yield 0 even on differing times,
* or tm may have members out of range (e.g. bad leap seconds).
*/
if ( (tm->tm_year ^ gtm->tm_year)
| (tm->tm_mon ^ gtm->tm_mon)
| (tm->tm_mday ^ gtm->tm_mday)
| (tm->tm_hour ^ gtm->tm_hour)
| (tm->tm_min ^ gtm->tm_min)
| (tm->tm_sec ^ gtm->tm_sec))
return -1;
tm->tm_wday = gtm->tm_wday;
return gt;
}
/*
* Check *PT and convert it to time_t.
* If it is incompletely specified, use DEFAULT_TIME to fill it out.
* Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
* Yield -1 on failure.
* ISO 8601 day-of-year and week numbers are not yet supported.
*/
static time_t
maketime(pt, default_time)
struct partime const *pt;
time_t default_time;
{
int localzone, wday;
struct tm tm;
struct tm *tm0 = 0;
time_t r;
tm0 = 0; /* Keep gcc -Wall happy. */
localzone = pt->zone==TM_LOCAL_ZONE;
tm = pt->tm;
if (TM_DEFINED(pt->ymodulus) || !TM_DEFINED(tm.tm_year)) {
/* Get tm corresponding to current time. */
tm0 = time2tm(default_time, localzone);
if (!localzone)
adjzone(tm0, pt->zone);
}
if (TM_DEFINED(pt->ymodulus))
tm.tm_year +=
(tm0->tm_year + TM_YEAR_ORIGIN)/pt->ymodulus * pt->ymodulus;
else if (!TM_DEFINED(tm.tm_year)) {
/* Set default year, month, day from current time. */
tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN;
if (!TM_DEFINED(tm.tm_mon)) {
tm.tm_mon = tm0->tm_mon;
if (!TM_DEFINED(tm.tm_mday))
tm.tm_mday = tm0->tm_mday;
}
}
/* Convert from partime year (Gregorian) to Posix year. */
tm.tm_year -= TM_YEAR_ORIGIN;
/* Set remaining default fields to be their minimum values. */
if (!TM_DEFINED(tm.tm_mon)) tm.tm_mon = 0;
if (!TM_DEFINED(tm.tm_mday)) tm.tm_mday = 1;
if (!TM_DEFINED(tm.tm_hour)) tm.tm_hour = 0;
if (!TM_DEFINED(tm.tm_min)) tm.tm_min = 0;
if (!TM_DEFINED(tm.tm_sec)) tm.tm_sec = 0;
if (!localzone)
adjzone(&tm, -pt->zone);
wday = tm.tm_wday;
/* Convert and fill in the rest of the tm. */
r = tm2time(&tm, localzone);
/* Check weekday. */
if (r != -1 && TM_DEFINED(wday) && wday != tm.tm_wday)
return -1;
return r;
}
/* Parse a free-format date in SOURCE, yielding a Unix format time. */
time_t
str2time(source, default_time, default_zone)
char const *source;
time_t default_time;
long default_zone;
{
struct partime pt;
if (*partime(source, &pt))
return -1;
if (pt.zone == TM_UNDEFINED_ZONE)
pt.zone = default_zone;
return maketime(&pt, default_time);
}
#if TEST
#include <stdio.h>
int
main(argc, argv) int argc; char **argv;
{
time_t default_time = time((time_t *)0);
long default_zone = argv[1] ? atol(argv[1]) : 0;
char buf[1000];
while (fgets(buf, 1000, stdin)) {
time_t t = str2time(buf, default_time, default_zone);
printf("%s", asctime(gmtime(&t)));
}
return 0;
}
#endif

View file

@ -0,0 +1,39 @@
/* Yield time_t from struct partime yielded by partime. */
/* Copyright 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#if defined(__STDC__) || has_prototypes
# define __MAKETIME_P(x) x
#else
# define __MAKETIME_P(x) ()
#endif
struct tm *time2tm __MAKETIME_P((time_t,int));
time_t difftm __MAKETIME_P((struct tm const *, struct tm const *));
time_t str2time __MAKETIME_P((char const *, time_t, long));
time_t tm2time __MAKETIME_P((struct tm *, int));
void adjzone __MAKETIME_P((struct tm *, long));

View file

@ -0,0 +1,148 @@
/* three-way file merge internals */
/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#include "rcsbase.h"
libId(mergerId, "$FreeBSD$")
static char const *normalize_arg P((char const*,char**));
static char const *
normalize_arg(s, b)
char const *s;
char **b;
/*
* If S looks like an option, prepend ./ to it. Yield the result.
* Set *B to the address of any storage that was allocated.
*/
{
char *t;
if (*s == '-') {
*b = t = testalloc(strlen(s) + 3);
VOID sprintf(t, ".%c%s", SLASH, s);
return t;
} else {
*b = 0;
return s;
}
}
int
merge(tostdout, edarg, label, argv)
int tostdout;
char const *edarg;
char const *const label[3];
char const *const argv[3];
/*
* Do `merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2',
* where TOSTDOUT specifies whether -p is present,
* EDARG gives the editing type (e.g. "-A", or null for the default),
* LABEL gives l0, l1 and l2, and ARGV gives a0, a1 and a2.
* Yield DIFF_SUCCESS or DIFF_FAILURE.
*/
{
register int i;
FILE *f;
RILE *rt;
char const *a[3], *t;
char *b[3];
int s;
#if !DIFF3_BIN
char const *d[2];
#endif
for (i=3; 0<=--i; )
a[i] = normalize_arg(argv[i], &b[i]);
if (!edarg)
edarg = "-E";
#if DIFF3_BIN
t = 0;
if (!tostdout)
t = maketemp(0);
s = run(
-1, t,
DIFF3, edarg, "-am",
"-L", label[0],
"-L", label[1],
"-L", label[2],
a[0], a[1], a[2], (char*)0
);
switch (s) {
case DIFF_SUCCESS:
break;
case DIFF_FAILURE:
warn("conflicts during merge");
break;
default:
exiterr();
}
if (t) {
if (!(f = fopenSafer(argv[0], "w")))
efaterror(argv[0]);
if (!(rt = Iopen(t, "r", (struct stat*)0)))
efaterror(t);
fastcopy(rt, f);
Ifclose(rt);
Ofclose(f);
}
#else
for (i=0; i<2; i++)
switch (run(
-1, d[i]=maketemp(i),
DIFF, a[i], a[2], (char*)0
)) {
case DIFF_FAILURE: case DIFF_SUCCESS: break;
default: faterror("diff failed");
}
t = maketemp(2);
s = run(
-1, t,
DIFF3, edarg, d[0], d[1], a[0], a[1], a[2],
label[0], label[2], (char*)0
);
if (s != DIFF_SUCCESS) {
s = DIFF_FAILURE;
warn("overlaps or other problems during merge");
}
if (!(f = fopenSafer(t, "a+")))
efaterror(t);
aputs(tostdout ? "1,$p\n" : "w\n", f);
Orewind(f);
aflush(f);
if (run(fileno(f), (char*)0, ED, "-", a[0], (char*)0))
exiterr();
Ofclose(f);
#endif
tempunlink();
for (i=3; 0<=--i; )
if (b[i])
tfree(b[i]);
return s;
}

View file

@ -0,0 +1,701 @@
/* Parse a string, yielding a struct partime that describes it. */
/* Copyright 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#if has_conf_h
# include "conf.h"
#else
# ifdef __STDC__
# define P(x) x
# else
# define const
# define P(x) ()
# endif
# include <limits.h>
# include <time.h>
#endif
#include <ctype.h>
#undef isdigit
#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than stock */
#include "partime.h"
char const partimeId[]
= "$FreeBSD$";
/* Lookup tables for names of months, weekdays, time zones. */
#define NAME_LENGTH_MAXIMUM 4
struct name_val {
char name[NAME_LENGTH_MAXIMUM];
int val;
};
static char const *parse_decimal P((char const*,int,int,int,int,int*,int*));
static char const *parse_fixed P((char const*,int,int*));
static char const *parse_pattern_letter P((char const*,int,struct partime*));
static char const *parse_prefix P((char const*,struct partime*,int*));
static char const *parse_ranged P((char const*,int,int,int,int*));
static int lookup P((char const*,struct name_val const[]));
static int merge_partime P((struct partime*, struct partime const*));
static void undefine P((struct partime*));
static struct name_val const month_names[] = {
{"jan",0}, {"feb",1}, {"mar",2}, {"apr",3}, {"may",4}, {"jun",5},
{"jul",6}, {"aug",7}, {"sep",8}, {"oct",9}, {"nov",10}, {"dec",11},
{"", TM_UNDEFINED}
};
static struct name_val const weekday_names[] = {
{"sun",0}, {"mon",1}, {"tue",2}, {"wed",3}, {"thu",4}, {"fri",5}, {"sat",6},
{"", TM_UNDEFINED}
};
#define hr60nonnegative(t) ((t)/100 * 60 + (t)%100)
#define hr60(t) ((t)<0 ? -hr60nonnegative(-(t)) : hr60nonnegative(t))
#define zs(t,s) {s, hr60(t)}
#define zd(t,s,d) zs(t, s), zs((t)+100, d)
static struct name_val const zone_names[] = {
zs(-1000, "hst"), /* Hawaii */
zd(-1000,"hast","hadt"),/* Hawaii-Aleutian */
zd(- 900,"akst","akdt"),/* Alaska */
zd(- 800, "pst", "pdt"),/* Pacific */
zd(- 700, "mst", "mdt"),/* Mountain */
zd(- 600, "cst", "cdt"),/* Central */
zd(- 500, "est", "edt"),/* Eastern */
zd(- 400, "ast", "adt"),/* Atlantic */
zd(- 330, "nst", "ndt"),/* Newfoundland */
zs( 000, "utc"), /* Coordinated Universal */
zs( 000, "cut"), /* " */
zs( 000, "ut"), /* Universal */
zs( 000, "z"), /* Zulu (required by ISO 8601) */
zd( 000, "gmt", "bst"),/* Greenwich Mean, British Summer */
zs( 000, "wet"), /* Western Europe */
zs( 100, "met"), /* Middle Europe */
zs( 100, "cet"), /* Central Europe */
zs( 200, "eet"), /* Eastern Europe */
zs( 530, "ist"), /* India */
zd( 900, "jst", "jdt"),/* Japan */
zd( 900, "kst", "kdt"),/* Korea */
zd( 1200,"nzst","nzdt"),/* New Zealand */
{ "lt", 1 },
#if 0
/* The following names are duplicates or are not well attested. */
zs(-1100, "sst"), /* Samoa */
zs(-1000, "tht"), /* Tahiti */
zs(- 930, "mqt"), /* Marquesas */
zs(- 900, "gbt"), /* Gambier */
zd(- 900, "yst", "ydt"),/* Yukon - name is no longer used */
zs(- 830, "pit"), /* Pitcairn */
zd(- 500, "cst", "cdt"),/* Cuba */
zd(- 500, "ast", "adt"),/* Acre */
zd(- 400, "wst", "wdt"),/* Western Brazil */
zd(- 400, "ast", "adt"),/* Andes */
zd(- 400, "cst", "cdt"),/* Chile */
zs(- 300, "wgt"), /* Western Greenland */
zd(- 300, "est", "edt"),/* Eastern South America */
zs(- 300, "mgt"), /* Middle Greenland */
zd(- 200, "fst", "fdt"),/* Fernando de Noronha */
zs(- 100, "egt"), /* Eastern Greenland */
zs(- 100, "aat"), /* Atlantic Africa */
zs(- 100, "act"), /* Azores and Canaries */
zs( 000, "wat"), /* West Africa */
zs( 100, "cat"), /* Central Africa */
zd( 100, "mez","mesz"),/* Mittel-Europaeische Zeit */
zs( 200, "sat"), /* South Africa */
zd( 200, "ist", "idt"),/* Israel */
zs( 300, "eat"), /* East Africa */
zd( 300, "ast", "adt"),/* Arabia */
zd( 300, "msk", "msd"),/* Moscow */
zd( 330, "ist", "idt"),/* Iran */
zs( 400, "gst"), /* Gulf */
zs( 400, "smt"), /* Seychelles & Mascarene */
zd( 400, "esk", "esd"),/* Yekaterinburg */
zd( 400, "bsk", "bsd"),/* Baku */
zs( 430, "aft"), /* Afghanistan */
zd( 500, "osk", "osd"),/* Omsk */
zs( 500, "pkt"), /* Pakistan */
zd( 500, "tsk", "tsd"),/* Tashkent */
zs( 545, "npt"), /* Nepal */
zs( 600, "bgt"), /* Bangladesh */
zd( 600, "nsk", "nsd"),/* Novosibirsk */
zs( 630, "bmt"), /* Burma */
zs( 630, "cct"), /* Cocos */
zs( 700, "ict"), /* Indochina */
zs( 700, "jvt"), /* Java */
zd( 700, "isk", "isd"),/* Irkutsk */
zs( 800, "hkt"), /* Hong Kong */
zs( 800, "pst"), /* Philippines */
zs( 800, "sgt"), /* Singapore */
zd( 800, "cst", "cdt"),/* China */
zd( 800, "ust", "udt"),/* Ulan Bator */
zd( 800, "wst", "wst"),/* Western Australia */
zd( 800, "ysk", "ysd"),/* Yakutsk */
zs( 900, "blt"), /* Belau */
zs( 900, "mlt"), /* Moluccas */
zd( 900, "vsk", "vsd"),/* Vladivostok */
zd( 930, "cst", "cst"),/* Central Australia */
zs( 1000, "gst"), /* Guam */
zd( 1000, "gsk", "gsd"),/* Magadan */
zd( 1000, "est", "est"),/* Eastern Australia */
zd( 1100,"lhst","lhst"),/* Lord Howe */
zd( 1100, "psk", "psd"),/* Petropavlovsk-Kamchatski */
zs( 1100,"ncst"), /* New Caledonia */
zs( 1130,"nrft"), /* Norfolk */
zd( 1200, "ask", "asd"),/* Anadyr */
zs( 1245,"nz-chat"), /* Chatham */
zs( 1300, "tgt"), /* Tongatapu */
#endif
{"", -1}
};
static int
lookup (s, table)
char const *s;
struct name_val const table[];
/* Look for a prefix of S in TABLE, returning val for first matching entry. */
{
int j;
char buf[NAME_LENGTH_MAXIMUM];
for (j = 0; j < NAME_LENGTH_MAXIMUM; j++) {
unsigned char c = *s++;
buf[j] = isupper (c) ? tolower (c) : c;
if (!isalpha (c))
break;
}
for (; table[0].name[0]; table++)
for (j = 0; buf[j] == table[0].name[j]; )
if (++j == NAME_LENGTH_MAXIMUM || !table[0].name[j])
goto done;
done:
return table[0].val;
}
static void
undefine (t) struct partime *t;
/* Set *T to ``undefined'' values. */
{
t->tm.tm_sec = t->tm.tm_min = t->tm.tm_hour = t->tm.tm_mday = t->tm.tm_mon
= t->tm.tm_year = t->tm.tm_wday = t->tm.tm_yday
= t->ymodulus = t->yweek
= TM_UNDEFINED;
t->zone = TM_UNDEFINED_ZONE;
}
/*
* Array of patterns to look for in a date string.
* Order is important: we look for the first matching pattern
* whose values do not contradict values that we already know about.
* See `parse_pattern_letter' below for the meaning of the pattern codes.
*/
static char const * const patterns[] = {
/*
* These traditional patterns must come first,
* to prevent an ISO 8601 format from misinterpreting their prefixes.
*/
"E_n_y", "x", /* RFC 822 */
"E_n", "n_E", "n", "t:m:s_A", "t:m_A", "t_A", /* traditional */
"y/N/D$", /* traditional RCS */
/* ISO 8601:1988 formats, generalized a bit. */
"y-N-D$", "4ND$", "Y-N$",
"RND$", "-R=N$", "-R$", "--N=D$", "N=DT",
"--N$", "---D$", "DT",
"Y-d$", "4d$", "R=d$", "-d$", "dT",
"y-W-X", "yWX", "y=W",
"-r-W-X", "r-W-XT", "-rWX", "rWXT", "-W=X", "W=XT", "-W",
"-w-X", "w-XT", "---X$", "XT", "4$",
"T",
"h:m:s$", "hms$", "h:m$", "hm$", "h$", "-m:s$", "-ms$", "-m$", "--s$",
"Y", "Z",
0
};
static char const *
parse_prefix (str, t, pi) char const *str; struct partime *t; int *pi;
/*
* Parse an initial prefix of STR, setting *T accordingly.
* Return the first character after the prefix, or 0 if it couldn't be parsed.
* Start with pattern *PI; if success, set *PI to the next pattern to try.
* Set *PI to -1 if we know there are no more patterns to try;
* if *PI is initially negative, give up immediately.
*/
{
int i = *pi;
char const *pat;
unsigned char c;
if (i < 0)
return 0;
/* Remove initial noise. */
while (!isalnum (c = *str) && c != '-' && c != '+') {
if (!c) {
undefine (t);
*pi = -1;
return str;
}
str++;
}
/* Try a pattern until one succeeds. */
while ((pat = patterns[i++]) != 0) {
char const *s = str;
undefine (t);
do {
if (!(c = *pat++)) {
*pi = i;
return s;
}
} while ((s = parse_pattern_letter (s, c, t)) != 0);
}
return 0;
}
static char const *
parse_fixed (s, digits, res) char const *s; int digits, *res;
/*
* Parse an initial prefix of S of length DIGITS; it must be a number.
* Store the parsed number into *RES.
* Return the first character after the prefix, or 0 if it couldn't be parsed.
*/
{
int n = 0;
char const *lim = s + digits;
while (s < lim) {
unsigned d = *s++ - '0';
if (9 < d)
return 0;
n = 10*n + d;
}
*res = n;
return s;
}
static char const *
parse_ranged (s, digits, lo, hi, res) char const *s; int digits, lo, hi, *res;
/*
* Parse an initial prefix of S of length DIGITS;
* it must be a number in the range LO through HI.
* Store the parsed number into *RES.
* Return the first character after the prefix, or 0 if it couldn't be parsed.
*/
{
s = parse_fixed (s, digits, res);
return s && lo<=*res && *res<=hi ? s : 0;
}
static char const *
parse_decimal (s, digits, lo, hi, resolution, res, fres)
char const *s;
int digits, lo, hi, resolution, *res, *fres;
/*
* Parse an initial prefix of S of length DIGITS;
* it must be a number in the range LO through HI
* and it may be followed by a fraction that is to be computed using RESOLUTION.
* Store the parsed number into *RES; store the fraction times RESOLUTION,
* rounded to the nearest integer, into *FRES.
* Return the first character after the prefix, or 0 if it couldn't be parsed.
*/
{
s = parse_fixed (s, digits, res);
if (s && lo<=*res && *res<=hi) {
int f = 0;
if ((s[0]==',' || s[0]=='.') && isdigit ((unsigned char) s[1])) {
char const *s1 = ++s;
int num10 = 0, denom10 = 10, product;
while (isdigit ((unsigned char) *++s))
denom10 *= 10;
s = parse_fixed (s1, s - s1, &num10);
product = num10*resolution;
f = (product + (denom10>>1)) / denom10;
f -= f & (product%denom10 == denom10>>1); /* round to even */
if (f < 0 || product/resolution != num10)
return 0; /* overflow */
}
*fres = f;
return s;
}
return 0;
}
char *
parzone (s, zone) char const *s; long *zone;
/*
* Parse an initial prefix of S; it must denote a time zone.
* Set *ZONE to the number of seconds east of GMT,
* or to TM_LOCAL_ZONE if it is the local time zone.
* Return the first character after the prefix, or 0 if it couldn't be parsed.
*/
{
char sign;
int hh, mm, ss;
int minutesEastOfUTC;
long offset, z;
/*
* The formats are LT, n, n DST, nDST, no, o
* where n is a time zone name
* and o is a time zone offset of the form [-+]hh[:mm[:ss]].
*/
switch (*s) {
case '-': case '+':
z = 0;
break;
default:
minutesEastOfUTC = lookup (s, zone_names);
if (minutesEastOfUTC == -1)
return 0;
/* Don't bother to check rest of spelling. */
while (isalpha ((unsigned char) *s))
s++;
/* Don't modify LT. */
if (minutesEastOfUTC == 1) {
*zone = TM_LOCAL_ZONE;
return (char *) s;
}
z = minutesEastOfUTC * 60L;
/* Look for trailing " DST". */
if (
(s[-1]=='T' || s[-1]=='t') &&
(s[-2]=='S' || s[-2]=='s') &&
(s[-3]=='D' || s[-3]=='t')
)
goto trailing_dst;
while (isspace ((unsigned char) *s))
s++;
if (
(s[0]=='D' || s[0]=='d') &&
(s[1]=='S' || s[1]=='s') &&
(s[2]=='T' || s[2]=='t')
) {
s += 3;
trailing_dst:
*zone = z + 60*60;
return (char *) s;
}
switch (*s) {
case '-': case '+': break;
default: return (char *) s;
}
}
sign = *s++;
if (!(s = parse_ranged (s, 2, 0, 23, &hh)))
return 0;
mm = ss = 0;
if (*s == ':')
s++;
if (isdigit ((unsigned char) *s)) {
if (!(s = parse_ranged (s, 2, 0, 59, &mm)))
return 0;
if (*s==':' && s[-3]==':' && isdigit ((unsigned char) s[1])) {
if (!(s = parse_ranged (s + 1, 2, 0, 59, &ss)))
return 0;
}
}
if (isdigit ((unsigned char) *s))
return 0;
offset = (hh*60 + mm)*60L + ss;
*zone = z + (sign=='-' ? -offset : offset);
/*
* ?? Are fractions allowed here?
* If so, they're not implemented.
*/
return (char *) s;
}
static char const *
parse_pattern_letter (s, c, t) char const *s; int c; struct partime *t;
/*
* Parse an initial prefix of S, matching the pattern whose code is C.
* Set *T accordingly.
* Return the first character after the prefix, or 0 if it couldn't be parsed.
*/
{
switch (c) {
case '$': /* The next character must be a non-digit. */
if (isdigit ((unsigned char) *s))
return 0;
break;
case '-': case '/': case ':':
/* These characters stand for themselves. */
if (*s++ != c)
return 0;
break;
case '4': /* 4-digit year */
s = parse_fixed (s, 4, &t->tm.tm_year);
break;
case '=': /* optional '-' */
s += *s == '-';
break;
case 'A': /* AM or PM */
/*
* This matches the regular expression [AaPp][Mm]?.
* It must not be followed by a letter or digit;
* otherwise it would match prefixes of strings like "PST".
*/
switch (*s++) {
case 'A': case 'a':
if (t->tm.tm_hour == 12)
t->tm.tm_hour = 0;
break;
case 'P': case 'p':
if (t->tm.tm_hour != 12)
t->tm.tm_hour += 12;
break;
default: return 0;
}
switch (*s) {
case 'M': case 'm': s++; break;
}
if (isalnum (*s))
return 0;
break;
case 'D': /* day of month [01-31] */
s = parse_ranged (s, 2, 1, 31, &t->tm.tm_mday);
break;
case 'd': /* day of year [001-366] */
s = parse_ranged (s, 3, 1, 366, &t->tm.tm_yday);
t->tm.tm_yday--;
break;
case 'E': /* extended day of month [1-9, 01-31] */
s = parse_ranged (s, (
isdigit ((unsigned char) s[0]) &&
isdigit ((unsigned char) s[1])
) + 1, 1, 31, &t->tm.tm_mday);
break;
case 'h': /* hour [00-23 followed by optional fraction] */
{
int frac;
s = parse_decimal (s, 2, 0, 23, 60*60, &t->tm.tm_hour, &frac);
t->tm.tm_min = frac / 60;
t->tm.tm_sec = frac % 60;
}
break;
case 'm': /* minute [00-59 followed by optional fraction] */
s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec);
break;
case 'n': /* month name [e.g. "Jan"] */
if (!TM_DEFINED (t->tm.tm_mon = lookup (s, month_names)))
return 0;
/* Don't bother to check rest of spelling. */
while (isalpha ((unsigned char) *s))
s++;
break;
case 'N': /* month [01-12] */
s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);
t->tm.tm_mon--;
break;
case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */
s = parse_fixed (s, 1, &t->tm.tm_year);
t->ymodulus = 10;
break;
case_R:
case 'R': /* year % 100 (remainder in origin-0 century) [00-99] */
s = parse_fixed (s, 2, &t->tm.tm_year);
t->ymodulus = 100;
break;
case 's': /* second [00-60 followed by optional fraction] */
{
int frac;
s = parse_decimal (s, 2, 0, 60, 1, &t->tm.tm_sec, &frac);
t->tm.tm_sec += frac;
}
break;
case 'T': /* 'T' or 't' */
switch (*s++) {
case 'T': case 't': break;
default: return 0;
}
break;
case 't': /* traditional hour [1-9 or 01-12] */
s = parse_ranged (s, (
isdigit ((unsigned char) s[0]) && isdigit ((unsigned char) s[1])
) + 1, 1, 12, &t->tm.tm_hour);
break;
case 'w': /* 'W' or 'w' only (stands for current week) */
switch (*s++) {
case 'W': case 'w': break;
default: return 0;
}
break;
case 'W': /* 'W' or 'w', followed by a week of year [00-53] */
switch (*s++) {
case 'W': case 'w': break;
default: return 0;
}
s = parse_ranged (s, 2, 0, 53, &t->yweek);
break;
case 'X': /* weekday (1=Mon ... 7=Sun) [1-7] */
s = parse_ranged (s, 1, 1, 7, &t->tm.tm_wday);
t->tm.tm_wday--;
break;
case 'x': /* weekday name [e.g. "Sun"] */
if (!TM_DEFINED (t->tm.tm_wday = lookup (s, weekday_names)))
return 0;
/* Don't bother to check rest of spelling. */
while (isalpha ((unsigned char) *s))
s++;
break;
case 'y': /* either R or Y */
if (
isdigit ((unsigned char) s[0]) &&
isdigit ((unsigned char) s[1]) &&
!isdigit ((unsigned char) s[2])
)
goto case_R;
/* fall into */
case 'Y': /* year in full [4 or more digits] */
{
int len = 0;
while (isdigit ((unsigned char) s[len]))
len++;
if (len < 4)
return 0;
s = parse_fixed (s, len, &t->tm.tm_year);
}
break;
case 'Z': /* time zone */
s = parzone (s, &t->zone);
break;
case '_': /* possibly empty sequence of non-alphanumerics */
while (!isalnum (*s) && *s)
s++;
break;
default: /* bad pattern */
return 0;
}
return s;
}
static int
merge_partime (t, u) struct partime *t; struct partime const *u;
/*
* If there is no conflict, merge into *T the additional information in *U
* and return 0. Otherwise do nothing and return -1.
*/
{
# define conflict(a,b) ((a) != (b) && TM_DEFINED (a) && TM_DEFINED (b))
if (
conflict (t->tm.tm_sec, u->tm.tm_sec) ||
conflict (t->tm.tm_min, u->tm.tm_min) ||
conflict (t->tm.tm_hour, u->tm.tm_hour) ||
conflict (t->tm.tm_mday, u->tm.tm_mday) ||
conflict (t->tm.tm_mon, u->tm.tm_mon) ||
conflict (t->tm.tm_year, u->tm.tm_year) ||
conflict (t->tm.tm_wday, u->tm.tm_yday) ||
conflict (t->ymodulus, u->ymodulus) ||
conflict (t->yweek, u->yweek) ||
(
t->zone != u->zone &&
t->zone != TM_UNDEFINED_ZONE &&
u->zone != TM_UNDEFINED_ZONE
)
)
return -1;
# undef conflict
# define merge_(a,b) if (TM_DEFINED (b)) (a) = (b);
merge_ (t->tm.tm_sec, u->tm.tm_sec)
merge_ (t->tm.tm_min, u->tm.tm_min)
merge_ (t->tm.tm_hour, u->tm.tm_hour)
merge_ (t->tm.tm_mday, u->tm.tm_mday)
merge_ (t->tm.tm_mon, u->tm.tm_mon)
merge_ (t->tm.tm_year, u->tm.tm_year)
merge_ (t->tm.tm_wday, u->tm.tm_yday)
merge_ (t->ymodulus, u->ymodulus)
merge_ (t->yweek, u->yweek)
# undef merge_
if (u->zone != TM_UNDEFINED_ZONE) t->zone = u->zone;
return 0;
}
char *
partime (s, t) char const *s; struct partime *t;
/*
* Parse a date/time prefix of S, putting the parsed result into *T.
* Return the first character after the prefix.
* The prefix may contain no useful information;
* in that case, *T will contain only undefined values.
*/
{
struct partime p;
undefine (t);
while (*s) {
int i = 0;
char const *s1;
do {
if (!(s1 = parse_prefix (s, &p, &i)))
return (char *) s;
} while (merge_partime (t, &p) != 0);
s = s1;
}
return (char *) s;
}

View file

@ -0,0 +1,71 @@
/* Parse a string, yielding a struct partime that describes it. */
/* Copyright 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#define TM_UNDEFINED (-1)
#define TM_DEFINED(x) (0 <= (x))
#define TM_UNDEFINED_ZONE ((long) -24 * 60 * 60)
#define TM_LOCAL_ZONE (TM_UNDEFINED_ZONE - 1)
struct partime {
/*
* This structure describes the parsed time.
* Only the following tm_* values in it are used:
* sec, min, hour, mday, mon, year, wday, yday.
* If TM_UNDEFINED(value), the parser never found the value.
* The tm_year field is the actual year, not the year - 1900;
* but see ymodulus below.
*/
struct tm tm;
/*
* If !TM_UNDEFINED(ymodulus),
* then tm.tm_year is actually modulo ymodulus.
*/
int ymodulus;
/*
* Week of year, ISO 8601 style.
* If TM_UNDEFINED(yweek), the parser never found yweek.
* Weeks start on Mondays.
* Week 1 includes Jan 4.
*/
int yweek;
/* Seconds east of UTC; or TM_LOCAL_ZONE or TM_UNDEFINED_ZONE. */
long zone;
};
#if defined(__STDC__) || has_prototypes
# define __PARTIME_P(x) x
#else
# define __PARTIME_P(x) ()
#endif
char *partime __PARTIME_P((char const *, struct partime *));
char *parzone __PARTIME_P((char const *, long *));

View file

@ -0,0 +1,762 @@
/* RCS common definitions and data structures */
#define RCSBASE "$FreeBSD$"
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.20 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.19 1995/06/01 16:23:43 eggert
* (SIZEABLE_PATH): Don't depend on PATH_MAX: it's not worth configuring.
* (Ioffset_type,BINARY_EXPAND,MIN_UNEXPAND,MIN_UNCHANGED_EXPAND): New macros.
* (maps_memory): New macro; replaces many instances of `has_mmap'.
* (cacheptr): Renamed from cachetell.
* (struct RILE): New alternate name for RILE; the type is now recursive.
* (deallocate): New member for RILE, used for generic buffer deallocation.
* (cacheunget_): No longer take a failure arg; just call Ierror on failure.
* (struct rcslock): Renamed from struct lock, to avoid collisions with
* system headers on some hosts. All users changed.
* (basefilename): Renamed from basename, likewise.
* (dirtpname): Remove; no longer external.
* (dirlen, dateform): Remove; no longer used.
* (cmpdate, fopenSafer, fdSafer, readAccessFilenameBuffer): New functions.
* (zonelenmax): Increase to 9 for full ISO 8601 format.
* (catchmmapints): Depend on has_NFS.
*
* Revision 5.18 1994/03/17 14:05:48 eggert
* Add primitives for reading backwards from a RILE;
* this is needed to go back and find the $Log prefix.
* Specify subprocess input via file descriptor, not file name. Remove lint.
*
* Revision 5.17 1993/11/09 17:40:15 eggert
* Move RCS-specific time handling into rcstime.c.
* printf_string now takes two arguments, alas.
*
* Revision 5.16 1993/11/03 17:42:27 eggert
* Don't arbitrarily limit the number of joins. Remove `nil'.
* Add Name keyword. Don't discard ignored phrases.
* Add support for merge -A vs -E, and allow up to three labels.
* Improve quality of diagnostics and prototypes.
*
* Revision 5.15 1992/07/28 16:12:44 eggert
* Statement macro names now end in _.
*
* Revision 5.14 1992/02/17 23:02:22 eggert
* Add -T support. Work around NFS mmap SIGBUS problem.
*
* Revision 5.13 1992/01/24 18:44:19 eggert
* Add support for bad_creat0. lint -> RCS_lint
*
* Revision 5.12 1992/01/06 02:42:34 eggert
* while (E) ; -> while (E) continue;
*
* Revision 5.11 1991/10/07 17:32:46 eggert
* Support piece tables even if !has_mmap.
*
* Revision 5.10 1991/09/24 00:28:39 eggert
* Remove unexported functions.
*
* Revision 5.9 1991/08/19 03:13:55 eggert
* Add piece tables and other tuneups, and NFS workarounds.
*
* Revision 5.8 1991/04/21 11:58:20 eggert
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.7 1991/02/28 19:18:50 eggert
* Try setuid() if seteuid() doesn't work.
*
* Revision 5.6 1991/02/26 17:48:37 eggert
* Support new link behavior. Move ANSI C / Posix declarations into conf.sh.
*
* Revision 5.5 1990/12/04 05:18:43 eggert
* Use -I for prompts and -q for diagnostics.
*
* Revision 5.4 1990/11/01 05:03:35 eggert
* Don't assume that builtins are functions; they may be macros.
* Permit arbitrary data in logs.
*
* Revision 5.3 1990/09/26 23:36:58 eggert
* Port wait() to non-Posix ANSI C hosts.
*
* Revision 5.2 1990/09/04 08:02:20 eggert
* Don't redefine NAME_MAX, PATH_MAX.
* Improve incomplete line handling. Standardize yes-or-no procedure.
*
* Revision 5.1 1990/08/29 07:13:53 eggert
* Add -kkvl. Fix type typos exposed by porting. Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:12:44 eggert
* Adjust ANSI C / Posix support. Add -k, -V, setuid. Don't call access().
* Remove compile-time limits; use malloc instead.
* Ansify and Posixate. Add support for ISO 8859.
* Remove snoop and v2 support.
*
* Revision 4.9 89/05/01 15:17:14 narten
* botched previous USG fix
*
* Revision 4.8 89/05/01 14:53:05 narten
* changed #include <strings.h> -> string.h for USG systems.
*
* Revision 4.7 88/11/08 15:58:45 narten
* removed defs for functions loaded from libraries
*
* Revision 4.6 88/08/09 19:12:36 eggert
* Shrink stdio code size; remove lint; permit -Dhshsize=nn.
*
* Revision 4.5 87/12/18 17:06:41 narten
* made removed BSD ifdef, now uses V4_2BSD
*
* Revision 4.4 87/10/18 10:29:49 narten
* Updating version numbers
* Changes relative to 1.1 are actually relative to 4.2
*
* Revision 1.3 87/09/24 14:02:25 narten
* changes for lint
*
* Revision 1.2 87/03/27 14:22:02 jenkins
* Port to suns
*
* Revision 4.2 83/12/20 16:04:20 wft
* merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
* moved setting of STRICT_LOCKING to Makefile.
* changed DOLLAR to UNKN (conflict with KDELIM).
*
* Revision 4.1 83/05/04 09:12:41 wft
* Added markers Id and RCSfile.
* Added Dbranch for default branches.
*
* Revision 3.6.1.1 83/12/02 21:56:22 wft
* Increased logsize, added macro SMALLOG.
*
* Revision 3.6 83/01/15 16:43:28 wft
* 4.2 prerelease
*
* Revision 3.6 83/01/15 16:43:28 wft
* Replaced dbm.h with BYTESIZ, fixed definition of rindex().
* Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
* Added macro DELNUMFORM to have uniform format for printing delta text nodes.
* Added macro DELETE to mark deleted deltas.
*
* Revision 3.5 82/12/10 12:16:56 wft
* Added two forms of DATEFORM, one using %02d, the other %.2d.
*
* Revision 3.4 82/12/04 20:01:25 wft
* added LOCKER, Locker, and USG (redefinition of rindex).
*
* Revision 3.3 82/12/03 12:22:04 wft
* Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
* PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
* using NCPPN. Changed putc() to abort on write error.
*
* Revision 3.2 82/10/18 15:03:52 wft
* added macro STRICT_LOCKING, removed RCSUMASK.
* renamed JOINFILE[1,2] to JOINFIL[1,2].
*
* Revision 3.1 82/10/11 19:41:17 wft
* removed NBPW, NBPC, NCPW.
* added typdef int void to aid compiling
*/
#include "conf.h"
#define EXIT_TROUBLE DIFF_TROUBLE
#ifdef _POSIX_PATH_MAX
# define SIZEABLE_PATH _POSIX_PATH_MAX
#else
# define SIZEABLE_PATH 255 /* size of a large path; not a hard limit */
#endif
/* for traditional C hosts with unusual size arguments */
#define Fread(p,s,n,f) fread(p, (freadarg_type)(s), (freadarg_type)(n), f)
#define Fwrite(p,s,n,f) fwrite(p, (freadarg_type)(s), (freadarg_type)(n), f)
/*
* Parameters
*/
/* backwards compatibility with old versions of RCS */
#define VERSION_min 3 /* old output RCS format supported */
#define VERSION_max 5 /* newest output RCS format supported */
#ifndef VERSION_DEFAULT /* default RCS output format */
# define VERSION_DEFAULT VERSION_max
#endif
#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
#ifndef STRICT_LOCKING
#define STRICT_LOCKING 1
#endif
/* 0 sets the default locking to non-strict; */
/* used in experimental environments. */
/* 1 sets the default locking to strict; */
/* used in production environments. */
#define yearlength 16 /* (good through AD 9,999,999,999,999,999) */
#define datesize (yearlength+16) /* size of output of time2date */
#define RCSTMPPREFIX '_' /* prefix for temp files in working dir */
#define KDELIM '$' /* delimiter for keywords */
#define VDELIM ':' /* separates keywords from values */
#define DEFAULTSTATE "Exp" /* default state of revisions */
#define true 1
#define false 0
/*
* RILE - readonly file
* declarecache; - declares local cache for RILE variable(s)
* setupcache - sets up the local RILE cache, but does not initialize it
* cache, uncache - caches and uncaches the local RILE;
* (uncache,cache) is needed around functions that advance the RILE pointer
* Igeteof_(f,c,s) - get a char c from f, executing statement s at EOF
* cachegeteof_(c,s) - Igeteof_ applied to the local RILE
* Iget_(f,c) - like Igeteof_, except EOF is an error
* cacheget_(c) - Iget_ applied to the local RILE
* cacheunget_(f,c,s) - read c backwards from cached f, executing s at BOF
* Ifileno, Ioffset_type, Irewind, Itell - analogs to stdio routines
*
* By conventions, macros whose names end in _ are statements, not expressions.
* Following such macros with `; else' results in a syntax error.
*/
#define maps_memory (has_map_fd || has_mmap)
#if large_memory
typedef unsigned char const *Iptr_type;
typedef struct RILE {
Iptr_type ptr, lim;
unsigned char *base; /* not Iptr_type for lint's sake */
unsigned char *readlim;
int fd;
# if maps_memory
void (*deallocate) P((struct RILE *));
# else
FILE *stream;
# endif
} RILE;
# if maps_memory
# define declarecache register Iptr_type ptr, lim
# define setupcache(f) (lim = (f)->lim)
# define Igeteof_(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++;
# define cachegeteof_(c,s) if (ptr==lim) s else (c)= *ptr++;
# else
int Igetmore P((RILE*));
# define declarecache register Iptr_type ptr; register RILE *rRILE
# define setupcache(f) (rRILE = (f))
# define Igeteof_(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++;
# define cachegeteof_(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++;
# endif
# define uncache(f) ((f)->ptr = ptr)
# define cache(f) (ptr = (f)->ptr)
# define Iget_(f,c) Igeteof_(f,c,Ieof();)
# define cacheget_(c) cachegeteof_(c,Ieof();)
# define cacheunget_(f,c) (c)=(--ptr)[-1];
# define Ioffset_type size_t
# define Itell(f) ((f)->ptr - (f)->base)
# define Irewind(f) ((f)->ptr = (f)->base)
# define cacheptr() ptr
# define Ifileno(f) ((f)->fd)
#else
# define RILE FILE
# define declarecache register FILE *ptr
# define setupcache(f) (ptr = (f))
# define uncache(f)
# define cache(f)
# define Igeteof_(f,c,s) {if(((c)=getc(f))==EOF){testIerror(f);if(feof(f))s}}
# define cachegeteof_(c,s) Igeteof_(ptr,c,s)
# define Iget_(f,c) { if (((c)=getc(f))==EOF) testIeof(f); }
# define cacheget_(c) Iget_(ptr,c)
# define cacheunget_(f,c) if(fseek(ptr,-2L,SEEK_CUR))Ierror();else cacheget_(c)
# define Ioffset_type long
# define Itell(f) ftell(f)
# define Ifileno(f) fileno(f)
#endif
/* Print a char, but abort on write error. */
#define aputc_(c,o) { if (putc(c,o)==EOF) testOerror(o); }
/* Get a character from an RCS file, perhaps copying to a new RCS file. */
#define GETCeof_(o,c,s) { cachegeteof_(c,s) if (o) aputc_(c,o) }
#define GETC_(o,c) { cacheget_(c) if (o) aputc_(c,o) }
#define WORKMODE(RCSmode, writable) (((RCSmode)&(mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) | ((writable)?S_IWUSR:0))
/* computes mode of working file: same as RCSmode, but write permission */
/* determined by writable */
/* character classes and token codes */
enum tokens {
/* classes */ DELIM, DIGIT, IDCHAR, NEWLN, LETTER, Letter,
PERIOD, SBEGIN, SPACE, UNKN,
/* tokens */ COLON, ID, NUM, SEMI, STRING
};
#define SDELIM '@' /* the actual character is needed for string handling*/
/* SDELIM must be consistent with ctab[], so that ctab[SDELIM]==SBEGIN.
* there should be no overlap among SDELIM, KDELIM, and VDELIM
*/
#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
/***************************************
* Data structures for the symbol table
***************************************/
/* Buffer of arbitrary data */
struct buf {
char *string;
size_t size;
};
struct cbuf {
char const *string;
size_t size;
};
/* Hash table entry */
struct hshentry {
char const * num; /* pointer to revision number (ASCIZ) */
char const * date; /* pointer to date of checkin */
char const * author; /* login of person checking in */
char const * lockedby; /* who locks the revision */
char const * state; /* state of revision (Exp by default) */
char const * name; /* name (if any) by which retrieved */
struct cbuf log; /* log message requested at checkin */
struct branchhead * branches; /* list of first revisions on branches*/
struct cbuf ig; /* ignored phrases in admin part */
struct cbuf igtext; /* ignored phrases in deltatext part */
struct hshentry * next; /* next revision on same branch */
struct hshentry * nexthsh; /* next revision with same hash value */
long insertlns;/* lines inserted (computed by rlog) */
long deletelns;/* lines deleted (computed by rlog) */
char selector; /* true if selected, false if deleted */
};
/* list of hash entries */
struct hshentries {
struct hshentries *rest;
struct hshentry *first;
};
/* list element for branch lists */
struct branchhead {
struct hshentry * hsh;
struct branchhead * nextbranch;
};
/* accesslist element */
struct access {
char const * login;
struct access * nextaccess;
};
/* list element for locks */
struct rcslock {
char const * login;
struct hshentry * delta;
struct rcslock * nextlock;
};
/* list element for symbolic names */
struct assoc {
char const * symbol;
char const * num;
struct assoc * nextassoc;
};
#define mainArgs (argc,argv) int argc; char **argv;
#if RCS_lint
# define libId(name,rcsid)
# define mainProg(name,cmd,rcsid) int name mainArgs
#else
# define libId(name,rcsid) char const name[] = rcsid;
# define mainProg(n,c,i) char const Copyright[] = "Copyright 1982,1988,1989 Walter F. Tichy, Purdue CS\nCopyright 1990,1991,1992,1993,1994,1995 Paul Eggert", baseid[] = RCSBASE, cmdid[] = c; libId(n,i) int main P((int,char**)); int main mainArgs
#endif
/*
* Markers for keyword expansion (used in co and ident)
* Every byte must have class LETTER or Letter.
*/
#define AUTHOR "Author"
#define DATE "Date"
#define HEADER "Header"
#define IDH "Id"
#define LOCKER "Locker"
#define LOG "Log"
#define NAME "Name"
#define RCSFILE "RCSfile"
#define REVISION "Revision"
#define SOURCE "Source"
#define STATE "State"
#define CVSHEADER "CVSHeader"
#define keylength 9 /* max length of any of the above keywords */
enum markers { Nomatch, Author, Date, Header, Id,
Locker, Log, Name, RCSfile, Revision, Source, State, CVSHeader,
LocalId };
/* This must be in the same order as rcskeys.c's Keyword[] array. */
#define DELNUMFORM "\n\n%s\n%s\n"
/* used by putdtext and scanlogtext */
#define EMPTYLOG "*** empty log message ***" /* used by ci and rlog */
/* main program */
extern char const cmdid[];
void exiterr P((void)) exiting;
/* merge */
int merge P((int,char const*,char const*const[3],char const*const[3]));
/* rcsedit */
#define ciklogsize 23 /* sizeof("checked in with -k by ") */
extern FILE *fcopy;
extern char const *resultname;
extern char const ciklog[ciklogsize];
extern int locker_expansion;
RILE *rcswriteopen P((struct buf*,struct stat*,int));
char const *makedirtemp P((int));
char const *getcaller P((void));
int addlock P((struct hshentry*,int));
int addsymbol P((char const*,char const*,int));
int checkaccesslist P((void));
int chnamemod P((FILE**,char const*,char const*,int,mode_t,time_t));
int donerewrite P((int,time_t));
int dorewrite P((int,int));
int expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*,int));
int findlock P((int,struct hshentry**));
int setmtime P((char const*,time_t));
void ORCSclose P((void));
void ORCSerror P((void));
void copystring P((void));
void dirtempunlink P((void));
void enterstring P((void));
void finishedit P((struct hshentry const*,FILE*,int));
void keepdirtemp P((char const*));
void openfcopy P((FILE*));
void snapshotedit P((FILE*));
void xpandstring P((struct hshentry const*));
#if has_NFS || bad_unlink
int un_link P((char const*));
#else
# define un_link(s) unlink(s)
#endif
#if large_memory
void edit_string P((void));
# define editstring(delta) edit_string()
#else
void editstring P((struct hshentry const*));
#endif
/* rcsfcmp */
int rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
/* rcsfnms */
#define bufautobegin(b) clear_buf(b)
#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
extern FILE *workstdout;
extern char *workname;
extern char const *RCSname;
extern char const *suffixes;
extern int fdlock;
extern struct stat RCSstat;
RILE *rcsreadopen P((struct buf*,struct stat*,int));
char *bufenlarge P((struct buf*,char const**));
char const *basefilename P((char const*));
char const *getfullRCSname P((void));
char const *getfullCVSname P((void));
char const *maketemp P((int));
char const *rcssuffix P((char const*));
int pairnames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
struct cbuf bufremember P((struct buf*,size_t));
void bufalloc P((struct buf*,size_t));
void bufautoend P((struct buf*));
void bufrealloc P((struct buf*,size_t));
void bufscat P((struct buf*,char const*));
void bufscpy P((struct buf*,char const*));
void tempunlink P((void));
/* rcsgen */
extern int interactiveflag;
extern struct buf curlogbuf;
char const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int));
int getcstdin P((void));
int putdtext P((struct hshentry const*,char const*,FILE*,int));
int ttystdin P((void));
int yesorno P((int,char const*,...)) printf_string(2,3);
struct cbuf cleanlogmsg P((char*,size_t));
struct cbuf getsstdin P((char const*,char const*,char const*,struct buf*));
void putdesc P((int,char*));
void putdftext P((struct hshentry const*,RILE*,FILE*,int));
/* rcskeep */
extern int prevkeys;
extern struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
int getoldkeys P((RILE*));
/* rcskeys */
extern char const *Keyword[];
extern enum markers LocalIdMode;
enum markers trymatch P((char const*));
void setRCSLocalId(char const *);
void setIncExc(char const *);
/* rcslex */
extern FILE *foutptr;
extern FILE *frewrite;
extern RILE *finptr;
extern char const *NextString;
extern enum tokens nexttok;
extern int hshenter;
extern int nerror;
extern int nextc;
extern int quietflag;
extern long rcsline;
char const *getid P((void));
void efaterror P((char const*)) exiting;
void enfaterror P((int,char const*)) exiting;
void fatcleanup P((int)) exiting;
void faterror P((char const*,...)) printf_string_exiting(1,2);
void fatserror P((char const*,...)) printf_string_exiting(1,2);
void rcsfaterror P((char const*,...)) printf_string_exiting(1,2);
void Ieof P((void)) exiting;
void Ierror P((void)) exiting;
void Oerror P((void)) exiting;
char *checkid P((char*,int));
char *checksym P((char*,int));
int eoflex P((void));
int getkeyopt P((char const*));
int getlex P((enum tokens));
struct cbuf getphrases P((char const*));
struct cbuf savestring P((struct buf*));
struct hshentry *getnum P((void));
void Ifclose P((RILE*));
void Izclose P((RILE**));
void Lexinit P((void));
void Ofclose P((FILE*));
void Orewind P((FILE*));
void Ozclose P((FILE**));
void aflush P((FILE*));
void afputc P((int,FILE*));
void aprintf P((FILE*,char const*,...)) printf_string(2,3);
void aputs P((char const*,FILE*));
void checksid P((char*));
void checkssym P((char*));
void diagnose P((char const*,...)) printf_string(1,2);
void eerror P((char const*));
void eflush P((void));
void enerror P((int,char const*));
void error P((char const*,...)) printf_string(1,2);
void fvfprintf P((FILE*,char const*,va_list));
void getkey P((char const*));
void getkeystring P((char const*));
void nextlex P((void));
void oflush P((void));
void printstring P((void));
void readstring P((void));
void redefined P((int));
void rcserror P((char const*,...)) printf_string(1,2);
void rcswarn P((char const*,...)) printf_string(1,2);
void testIerror P((FILE*));
void testOerror P((FILE*));
void warn P((char const*,...)) printf_string(1,2);
void warnignore P((void));
void workerror P((char const*,...)) printf_string(1,2);
void workwarn P((char const*,...)) printf_string(1,2);
#if has_madvise && has_mmap && large_memory
void advise_access P((RILE*,int));
# define if_advise_access(p,f,advice) if (p) advise_access(f,advice)
#else
# define advise_access(f,advice)
# define if_advise_access(p,f,advice)
#endif
#if large_memory && maps_memory
RILE *I_open P((char const*,struct stat*));
# define Iopen(f,m,s) I_open(f,s)
#else
RILE *Iopen P((char const*,char const*,struct stat*));
#endif
#if !large_memory
void testIeof P((FILE*));
void Irewind P((RILE*));
#endif
/* rcsmap */
extern enum tokens const ctab[];
/* rcsrev */
char *partialno P((struct buf*,char const*,int));
char const *namedrev P((char const*,struct hshentry*));
char const *tiprev P((void));
int cmpdate P((char const*,char const*));
int cmpnum P((char const*,char const*));
int cmpnumfld P((char const*,char const*,int));
int compartial P((char const*,char const*,int));
int expandsym P((char const*,struct buf*));
int fexpandsym P((char const*,struct buf*,RILE*));
struct hshentry *genrevs P((char const*,char const*,char const*,char const*,struct hshentries**));
int countnumflds P((char const*));
void getbranchno P((char const*,struct buf*));
/* rcssyn */
/* These expand modes must agree with Expand_names[] in rcssyn.c. */
#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
#define KEY_EXPAND 2 /* -kk `$Keyword$' */
#define VAL_EXPAND 3 /* -kv `value' */
#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
#define BINARY_EXPAND 5 /* -kb like -ko, but use binary mode I/O */
#define MIN_UNEXPAND OLD_EXPAND /* min value for no logical expansion */
#define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? BINARY_EXPAND : OLD_EXPAND)
/* min value guaranteed to yield an identical file */
struct diffcmd {
long
line1, /* number of first line */
nlines, /* number of lines affected */
adprev, /* previous 'a' line1+1 or 'd' line1 */
dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
};
extern char const * Dbranch;
extern struct access * AccessList;
extern struct assoc * Symbols;
extern struct cbuf Comment;
extern struct cbuf Ignored;
extern struct rcslock *Locks;
extern struct hshentry * Head;
extern int Expand;
extern int StrictLocks;
extern int TotalDeltas;
extern char const *const expand_names[];
extern char const
Kaccess[], Kauthor[], Kbranch[], Kcomment[],
Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
void unexpected_EOF P((void)) exiting;
int getdiffcmd P((RILE*,int,FILE*,struct diffcmd*));
int str2expmode P((char const*));
void getadmin P((void));
void getdesc P((int));
void gettree P((void));
void ignorephrases P((char const*));
void initdiffcmd P((struct diffcmd*));
void putadmin P((void));
void putstring P((FILE*,int,struct cbuf,int));
void puttree P((struct hshentry const*,FILE*));
/* rcstime */
#define zonelenmax 9 /* maxiumum length of time zone string, e.g. "+12:34:56" */
char const *date2str P((char const[datesize],char[datesize + zonelenmax]));
time_t date2time P((char const[datesize]));
void str2date P((char const*,char[datesize]));
void time2date P((time_t,char[datesize]));
void zone_set P((char const*));
/* rcsutil */
extern int RCSversion;
FILE *fopenSafer P((char const*,char const*));
char *cgetenv P((char const*));
char *fstr_save P((char const*));
char *str_save P((char const*));
char const *getusername P((int));
int fdSafer P((int));
int getRCSINIT P((int,char**,char***));
int run P((int,char const*,...));
int runv P((int,char const*,char const**));
malloc_type fremember P((malloc_type));
malloc_type ftestalloc P((size_t));
malloc_type testalloc P((size_t));
malloc_type testrealloc P((malloc_type,size_t));
#define ftalloc(T) ftnalloc(T,1)
#define talloc(T) tnalloc(T,1)
#if RCS_lint
extern malloc_type lintalloc;
# define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
# define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
# define trealloc(T,p,n) (lintalloc = testrealloc((malloc_type)0, sizeof(T)*(n)), p)
# define tfree(p)
#else
# define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
# define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
# define trealloc(T,p,n) ((T*) testrealloc((malloc_type)(p), sizeof(T)*(n)))
# define tfree(p) free((malloc_type)(p))
#endif
time_t now P((void));
void awrite P((char const*,size_t,FILE*));
void fastcopy P((RILE*,FILE*));
void ffree P((void));
void ffree1 P((char const*));
void setRCSversion P((char const*));
#if has_signal
void catchints P((void));
void ignoreints P((void));
void restoreints P((void));
#else
# define catchints()
# define ignoreints()
# define restoreints()
#endif
#if has_mmap && large_memory
# if has_NFS && mmap_signal
void catchmmapints P((void));
void readAccessFilenameBuffer P((char const*,unsigned char const*));
# else
# define catchmmapints()
# endif
#endif
#if has_getuid
uid_t ruid P((void));
# define myself(u) ((u) == ruid())
#else
# define myself(u) true
#endif
#if has_setuid
uid_t euid P((void));
void nosetid P((void));
void seteid P((void));
void setrid P((void));
#else
# define nosetid()
# define seteid()
# define setrid()
#endif
/* version */
extern char const RCS_version_string[];

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,354 @@
/* Compare working files, ignoring RCS keyword strings. */
/*****************************************************************************
* rcsfcmp()
* Testprogram: define FCMPTEST
*****************************************************************************
*/
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.14 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.13 1995/06/01 16:23:43 eggert
* (rcsfcmp): Add -kb support.
*
* Revision 5.12 1994/03/17 14:05:48 eggert
* Normally calculate the $Log prefix from context, not from RCS file.
* Calculate line numbers correctly even if the $Log prefix contains newlines.
* Remove lint.
*
* Revision 5.11 1993/11/03 17:42:27 eggert
* Fix yet another off-by-one error when comparing Log string expansions.
*
* Revision 5.10 1992/07/28 16:12:44 eggert
* Statement macro names now end in _.
*
* Revision 5.9 1991/10/07 17:32:46 eggert
* Count log lines correctly.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Tune.
*
* Revision 5.7 1991/04/21 11:58:22 eggert
* Fix errno bug. Add MS-DOS support.
*
* Revision 5.6 1991/02/28 19:18:47 eggert
* Open work file at most once.
*
* Revision 5.5 1990/11/27 09:26:05 eggert
* Fix comment leader bug.
*
* Revision 5.4 1990/11/01 05:03:42 eggert
* Permit arbitrary data in logs and comment leaders.
*
* Revision 5.3 1990/09/11 02:41:15 eggert
* Don't ignore differences inside keyword strings if -ko is set.
*
* Revision 5.1 1990/08/29 07:13:58 eggert
* Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:12:49 eggert
* Don't append "checked in with -k by " log to logs,
* so that checking in a program with -k doesn't change it.
* Ansify and Posixate. Remove lint.
*
* Revision 4.5 89/05/01 15:12:42 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 88/08/09 19:12:50 eggert
* Shrink stdio code size.
*
* Revision 4.3 87/12/18 11:40:02 narten
* lint cleanups (Guy Harris)
*
* Revision 4.2 87/10/18 10:33:06 narten
* updting version number. Changes relative to 1.1 actually relative to
* 4.1
*
* Revision 1.2 87/03/27 14:22:19 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:24:04 wft
* Marker matching now uses trymatch(). Marker pattern is now
* checked precisely.
*
* Revision 3.1 82/12/04 13:21:40 wft
* Initial revision.
*
*/
/*
#define FCMPTEST
*/
/* Testprogram; prints out whether two files are identical,
* except for keywords
*/
#include "rcsbase.h"
libId(fcmpId, "$FreeBSD$")
static int discardkeyval P((int,RILE*));
static int
discardkeyval(c, f)
register int c;
register RILE *f;
{
for (;;)
switch (c) {
case KDELIM:
case '\n':
return c;
default:
Igeteof_(f, c, return EOF;)
break;
}
}
int
rcsfcmp(xfp, xstatp, uname, delta)
register RILE *xfp;
struct stat const *xstatp;
char const *uname;
struct hshentry const *delta;
/* Compare the files xfp and uname. Return zero
* if xfp has the same contents as uname and neither has keywords,
* otherwise -1 if they are the same ignoring keyword values,
* and 1 if they differ even ignoring
* keyword values. For the LOG-keyword, rcsfcmp skips the log message
* given by the parameter delta in xfp. Thus, rcsfcmp returns nonpositive
* if xfp contains the same as uname, with the keywords expanded.
* Implementation: character-by-character comparison until $ is found.
* If a $ is found, read in the marker keywords; if they are real keywords
* and identical, read in keyword value. If value is terminated properly,
* disregard it and optionally skip log message; otherwise, compare value.
*/
{
register int xc, uc;
char xkeyword[keylength+2];
int eqkeyvals;
register RILE *ufp;
register int xeof, ueof;
register char * tp;
register char const *sp;
register size_t leaderlen;
int result;
enum markers match1;
struct stat ustat;
if (!(ufp = Iopen(uname, FOPEN_R_WORK, &ustat))) {
efaterror(uname);
}
xeof = ueof = false;
if (MIN_UNEXPAND <= Expand) {
if (!(result = xstatp->st_size!=ustat.st_size)) {
# if large_memory && maps_memory
result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
# else
for (;;) {
/* get the next characters */
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
if (xc != uc)
goto return1;
}
# endif
}
} else {
xc = 0;
uc = 0; /* Keep lint happy. */
leaderlen = 0;
result = 0;
for (;;) {
if (xc != KDELIM) {
/* get the next characters */
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
} else {
/* try to get both keywords */
tp = xkeyword;
for (;;) {
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
if (xc != uc)
break;
switch (xc) {
default:
if (xkeyword+keylength <= tp)
break;
*tp++ = xc;
continue;
case '\n': case KDELIM: case VDELIM:
break;
}
break;
}
if (
(xc==KDELIM || xc==VDELIM) && (uc==KDELIM || uc==VDELIM) &&
(*tp = xc, (match1 = trymatch(xkeyword)) != Nomatch)
) {
#ifdef FCMPTEST
VOID printf("found common keyword %s\n",xkeyword);
#endif
result = -1;
for (;;) {
if (xc != uc) {
xc = discardkeyval(xc, xfp);
uc = discardkeyval(uc, ufp);
if ((xeof = xc==EOF) | (ueof = uc==EOF))
goto eof;
eqkeyvals = false;
break;
}
switch (xc) {
default:
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
continue;
case '\n': case KDELIM:
eqkeyvals = true;
break;
}
break;
}
if (xc != uc)
goto return1;
if (xc==KDELIM) {
/* Skip closing KDELIM. */
Igeteof_(xfp, xc, xeof=true;)
Igeteof_(ufp, uc, ueof=true;)
if (xeof | ueof)
goto eof;
/* if the keyword is LOG, also skip the log message in xfp*/
if (match1==Log) {
/* first, compute the number of line feeds in log msg */
int lncnt;
size_t ls, ccnt;
sp = delta->log.string;
ls = delta->log.size;
if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
/*
* This log message was inserted. Skip its header.
* The number of newlines to skip is
* 1 + (C+1)*(1+L+1), where C is the number of newlines
* in the comment leader, and L is the number of
* newlines in the log string.
*/
int c1 = 1;
for (ccnt=Comment.size; ccnt--; )
c1 += Comment.string[ccnt] == '\n';
lncnt = 2*c1 + 1;
while (ls--) if (*sp++=='\n') lncnt += c1;
for (;;) {
if (xc=='\n')
if(--lncnt==0) break;
Igeteof_(xfp, xc, goto returnresult;)
}
/* skip last comment leader */
/* Can't just skip another line here, because there may be */
/* additional characters on the line (after the Log....$) */
ccnt = RCSversion<VERSION(5) ? Comment.size : leaderlen;
do {
Igeteof_(xfp, xc, goto returnresult;)
/*
* Read to the end of the comment leader or '\n',
* whatever comes first, because the leader's
* trailing white space was probably stripped.
*/
} while (ccnt-- && (xc!='\n' || --c1));
}
}
} else {
/* both end in the same character, but not a KDELIM */
/* must compare string values.*/
#ifdef FCMPTEST
VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
#endif
if (!eqkeyvals)
goto return1;
}
}
}
if (xc != uc)
goto return1;
if (xc == '\n')
leaderlen = 0;
else
leaderlen++;
}
}
eof:
if (xeof==ueof)
goto returnresult;
return1:
result = 1;
returnresult:
Ifclose(ufp);
return result;
}
#ifdef FCMPTEST
char const cmdid[] = "rcsfcmp";
main(argc, argv)
int argc; char *argv[];
/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
* 4th: unexpanded file
*/
{ struct hshentry delta;
Comment.string = argv[1];
Comment.size = strlen(argv[1]);
delta.log.string = argv[2];
delta.log.size = strlen(argv[2]);
if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
VOID printf("files are the same\n");
else VOID printf("files are different\n");
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,681 @@
/* Generate RCS revisions. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.16 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.15 1995/06/01 16:23:43 eggert
* (putadmin): Open RCS file with FOPEN_WB.
*
* Revision 5.14 1994/03/17 14:05:48 eggert
* Work around SVR4 stdio performance bug.
* Flush stderr after prompt. Remove lint.
*
* Revision 5.13 1993/11/03 17:42:27 eggert
* Don't discard ignored phrases. Improve quality of diagnostics.
*
* Revision 5.12 1992/07/28 16:12:44 eggert
* Statement macro names now end in _.
* Be consistent about pathnames vs filenames.
*
* Revision 5.11 1992/01/24 18:44:19 eggert
* Move put routines here from rcssyn.c.
* Add support for bad_creat0.
*
* Revision 5.10 1991/10/07 17:32:46 eggert
* Fix log bugs, e.g. ci -t/dev/null when has_mmap.
*
* Revision 5.9 1991/09/10 22:15:46 eggert
* Fix test for redirected stdin.
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Add piece tables. Tune.
*
* Revision 5.7 1991/04/21 11:58:24 eggert
* Add MS-DOS support.
*
* Revision 5.6 1990/12/27 19:54:26 eggert
* Fix bug: rcs -t inserted \n, making RCS file grow.
*
* Revision 5.5 1990/12/04 05:18:45 eggert
* Use -I for prompts and -q for diagnostics.
*
* Revision 5.4 1990/11/01 05:03:47 eggert
* Add -I and new -t behavior. Permit arbitrary data in logs.
*
* Revision 5.3 1990/09/21 06:12:43 hammer
* made putdesc() treat stdin the same whether or not it was from a terminal
* by making it recognize that a single '.' was then end of the
* description always
*
* Revision 5.2 1990/09/04 08:02:25 eggert
* Fix `co -p1.1 -ko' bug. Standardize yes-or-no procedure.
*
* Revision 5.1 1990/08/29 07:14:01 eggert
* Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:12:52 eggert
* Remove compile-time limits; use malloc instead.
* Ansify and Posixate.
*
* Revision 4.7 89/05/01 15:12:49 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.6 88/08/28 14:59:10 eggert
* Shrink stdio code size; allow cc -R; remove lint; isatty() -> ttystdin()
*
* Revision 4.5 87/12/18 11:43:25 narten
* additional lint cleanups, and a bug fix from the 4.3BSD version that
* keeps "ci" from sticking a '\377' into the description if you run it
* with a zero-length file as the description. (Guy Harris)
*
* Revision 4.4 87/10/18 10:35:10 narten
* Updating version numbers. Changes relative to 1.1 actually relative to
* 4.2
*
* Revision 1.3 87/09/24 13:59:51 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:27 jenkins
* Port to suns
*
* Revision 4.2 83/12/02 23:01:39 wft
* merged 4.1 and 3.3.1.1 (clearerr(stdin)).
*
* Revision 4.1 83/05/10 16:03:33 wft
* Changed putamin() to abort if trying to reread redirected stdin.
* Fixed getdesc() to output a prompt on initial newline.
*
* Revision 3.3.1.1 83/10/19 04:21:51 lepreau
* Added clearerr(stdin) for re-reading description from stdin.
*
* Revision 3.3 82/11/28 21:36:49 wft
* 4.2 prerelease
*
* Revision 3.3 82/11/28 21:36:49 wft
* Replaced ferror() followed by fclose() with ffclose().
* Putdesc() now suppresses the prompts if stdin
* is not a terminal. A pointer to the current log message is now
* inserted into the corresponding delta, rather than leaving it in a
* global variable.
*
* Revision 3.2 82/10/18 21:11:26 wft
* I added checks for write errors during editing, and improved
* the prompt on putdesc().
*
* Revision 3.1 82/10/13 15:55:09 wft
* corrected type of variables assigned to by getc (char --> int)
*/
#include "rcsbase.h"
libId(genId, "$FreeBSD$")
int interactiveflag; /* Should we act as if stdin is a tty? */
struct buf curlogbuf; /* buffer for current log message */
enum stringwork { enter, copy, edit, expand, edit_expand };
static void putdelta P((struct hshentry const*,FILE*));
static void scandeltatext P((struct hshentry*,enum stringwork,int));
char const *
buildrevision(deltas, target, outfile, expandflag)
struct hshentries const *deltas;
struct hshentry *target;
FILE *outfile;
int expandflag;
/* Function: Generates the revision given by target
* by retrieving all deltas given by parameter deltas and combining them.
* If outfile is set, the revision is output to it,
* otherwise written into a temporary file.
* Temporary files are allocated by maketemp().
* if expandflag is set, keyword expansion is performed.
* Return 0 if outfile is set, the name of the temporary file otherwise.
*
* Algorithm: Copy initial revision unchanged. Then edit all revisions but
* the last one into it, alternating input and output files (resultname and
* editname). The last revision is then edited in, performing simultaneous
* keyword substitution (this saves one extra pass).
* All this simplifies if only one revision needs to be generated,
* or no keyword expansion is necessary, or if output goes to stdout.
*/
{
if (deltas->first == target) {
/* only latest revision to generate */
openfcopy(outfile);
scandeltatext(target, expandflag?expand:copy, true);
if (outfile)
return 0;
else {
Ozclose(&fcopy);
return resultname;
}
} else {
/* several revisions to generate */
/* Get initial revision without keyword expansion. */
scandeltatext(deltas->first, enter, false);
while ((deltas=deltas->rest)->rest) {
/* do all deltas except last one */
scandeltatext(deltas->first, edit, false);
}
if (expandflag || outfile) {
/* first, get to beginning of file*/
finishedit((struct hshentry*)0, outfile, false);
}
scandeltatext(target, expandflag?edit_expand:edit, true);
finishedit(
expandflag ? target : (struct hshentry*)0,
outfile, true
);
if (outfile)
return 0;
Ozclose(&fcopy);
return resultname;
}
}
static void
scandeltatext(delta, func, needlog)
struct hshentry *delta;
enum stringwork func;
int needlog;
/* Function: Scans delta text nodes up to and including the one given
* by delta. For the one given by delta, the log message is saved into
* delta->log if needlog is set; func specifies how to handle the text.
* Similarly, if needlog, delta->igtext is set to the ignored phrases.
* Assumes the initial lexeme must be read in first.
* Does not advance nexttok after it is finished.
*/
{
struct hshentry const *nextdelta;
struct cbuf cb;
for (;;) {
if (eoflex())
fatserror("can't find delta for revision %s", delta->num);
nextlex();
if (!(nextdelta=getnum())) {
fatserror("delta number corrupted");
}
getkeystring(Klog);
if (needlog && delta==nextdelta) {
cb = savestring(&curlogbuf);
delta->log = cleanlogmsg(curlogbuf.string, cb.size);
nextlex();
delta->igtext = getphrases(Ktext);
} else {readstring();
ignorephrases(Ktext);
}
getkeystring(Ktext);
if (delta==nextdelta)
break;
readstring(); /* skip over it */
}
switch (func) {
case enter: enterstring(); break;
case copy: copystring(); break;
case expand: xpandstring(delta); break;
case edit: editstring((struct hshentry *)0); break;
case edit_expand: editstring(delta); break;
}
}
struct cbuf
cleanlogmsg(m, s)
char *m;
size_t s;
{
register char *t = m;
register char const *f = t;
struct cbuf r;
while (s) {
--s;
if ((*t++ = *f++) == '\n')
while (m < --t)
if (t[-1]!=' ' && t[-1]!='\t') {
*t++ = '\n';
break;
}
}
while (m < t && (t[-1]==' ' || t[-1]=='\t' || t[-1]=='\n'))
--t;
r.string = m;
r.size = t - m;
return r;
}
int ttystdin()
{
static int initialized;
if (!initialized) {
if (!interactiveflag)
interactiveflag = isatty(STDIN_FILENO);
initialized = true;
}
return interactiveflag;
}
int
getcstdin()
{
register FILE *in;
register int c;
in = stdin;
if (feof(in) && ttystdin())
clearerr(in);
c = getc(in);
if (c == EOF) {
testIerror(in);
if (feof(in) && ttystdin())
afputc('\n',stderr);
}
return c;
}
#if has_prototypes
int
yesorno(int default_answer, char const *question, ...)
#else
/*VARARGS2*/ int
yesorno(default_answer, question, va_alist)
int default_answer; char const *question; va_dcl
#endif
{
va_list args;
register int c, r;
if (!quietflag && ttystdin()) {
oflush();
vararg_start(args, question);
fvfprintf(stderr, question, args);
va_end(args);
eflush();
r = c = getcstdin();
while (c!='\n' && !feof(stdin))
c = getcstdin();
if (r=='y' || r=='Y')
return true;
if (r=='n' || r=='N')
return false;
}
return default_answer;
}
void
putdesc(textflag, textfile)
int textflag;
char *textfile;
/* Function: puts the descriptive text into file frewrite.
* if finptr && !textflag, the text is copied from the old description.
* Otherwise, if textfile, the text is read from that
* file, or from stdin, if !textfile.
* A textfile with a leading '-' is treated as a string, not a pathname.
* If finptr, the old descriptive text is discarded.
* Always clears foutptr.
*/
{
static struct buf desc;
static struct cbuf desclean;
register FILE *txt;
register int c;
register FILE * frew;
register char *p;
register size_t s;
char const *plim;
frew = frewrite;
if (finptr && !textflag) {
/* copy old description */
aprintf(frew, "\n\n%s%c", Kdesc, nextc);
foutptr = frewrite;
getdesc(false);
foutptr = 0;
} else {
foutptr = 0;
/* get new description */
if (finptr) {
/*skip old description*/
getdesc(false);
}
aprintf(frew,"\n\n%s\n%c",Kdesc,SDELIM);
if (!textfile)
desclean = getsstdin(
"t-", "description",
"NOTE: This is NOT the log message!\n", &desc
);
else if (!desclean.string) {
if (*textfile == '-') {
p = textfile + 1;
s = strlen(p);
} else {
if (!(txt = fopenSafer(textfile, "r")))
efaterror(textfile);
bufalloc(&desc, 1);
p = desc.string;
plim = p + desc.size;
for (;;) {
if ((c=getc(txt)) == EOF) {
testIerror(txt);
if (feof(txt))
break;
}
if (plim <= p)
p = bufenlarge(&desc, &plim);
*p++ = c;
}
if (fclose(txt) != 0)
Ierror();
s = p - desc.string;
p = desc.string;
}
desclean = cleanlogmsg(p, s);
}
putstring(frew, false, desclean, true);
aputc_('\n', frew)
}
}
struct cbuf
getsstdin(option, name, note, buf)
char const *option, *name, *note;
struct buf *buf;
{
register int c;
register char *p;
register size_t i;
register int tty = ttystdin();
if (tty) {
aprintf(stderr,
"enter %s, terminated with single '.' or end of file:\n%s>> ",
name, note
);
eflush();
} else if (feof(stdin))
rcsfaterror("can't reread redirected stdin for %s; use -%s<%s>",
name, option, name
);
for (
i = 0, p = 0;
c = getcstdin(), !feof(stdin);
bufrealloc(buf, i+1), p = buf->string, p[i++] = c
)
if (c == '\n')
if (i && p[i-1]=='.' && (i==1 || p[i-2]=='\n')) {
/* Remove trailing '.'. */
--i;
break;
} else if (tty) {
aputs(">> ", stderr);
eflush();
}
return cleanlogmsg(p, i);
}
void
putadmin()
/* Output the admin node. */
{
register FILE *fout;
struct assoc const *curassoc;
struct rcslock const *curlock;
struct access const *curaccess;
if (!(fout = frewrite)) {
# if bad_creat0
ORCSclose();
fout = fopenSafer(makedirtemp(0), FOPEN_WB);
# else
int fo = fdlock;
fdlock = -1;
fout = fdopen(fo, FOPEN_WB);
# endif
if (!(frewrite = fout))
efaterror(RCSname);
}
/*
* Output the first character with putc, not printf.
* Otherwise, an SVR4 stdio bug buffers output inefficiently.
*/
aputc_(*Khead, fout)
aprintf(fout, "%s\t%s;\n", Khead + 1, Head?Head->num:"");
if (Dbranch && VERSION(4)<=RCSversion)
aprintf(fout, "%s\t%s;\n", Kbranch, Dbranch);
aputs(Kaccess, fout);
curaccess = AccessList;
while (curaccess) {
aprintf(fout, "\n\t%s", curaccess->login);
curaccess = curaccess->nextaccess;
}
aprintf(fout, ";\n%s", Ksymbols);
curassoc = Symbols;
while (curassoc) {
aprintf(fout, "\n\t%s:%s", curassoc->symbol, curassoc->num);
curassoc = curassoc->nextassoc;
}
aprintf(fout, ";\n%s", Klocks);
curlock = Locks;
while (curlock) {
aprintf(fout, "\n\t%s:%s", curlock->login, curlock->delta->num);
curlock = curlock->nextlock;
}
if (StrictLocks) aprintf(fout, "; %s", Kstrict);
aprintf(fout, ";\n");
if (Comment.size) {
aprintf(fout, "%s\t", Kcomment);
putstring(fout, true, Comment, false);
aprintf(fout, ";\n");
}
if (Expand != KEYVAL_EXPAND)
aprintf(fout, "%s\t%c%s%c;\n",
Kexpand, SDELIM, expand_names[Expand], SDELIM
);
awrite(Ignored.string, Ignored.size, fout);
aputc_('\n', fout)
}
static void
putdelta(node, fout)
register struct hshentry const *node;
register FILE * fout;
/* Output the delta NODE to FOUT. */
{
struct branchhead const *nextbranch;
if (!node) return;
aprintf(fout, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
node->num,
Kdate, node->date,
Kauthor, node->author,
Kstate, node->state?node->state:""
);
nextbranch = node->branches;
while (nextbranch) {
aprintf(fout, "\n\t%s", nextbranch->hsh->num);
nextbranch = nextbranch->nextbranch;
}
aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:"");
awrite(node->ig.string, node->ig.size, fout);
}
void
puttree(root, fout)
struct hshentry const *root;
register FILE *fout;
/* Output the delta tree with base ROOT in preorder to FOUT. */
{
struct branchhead const *nextbranch;
if (!root) return;
if (root->selector)
putdelta(root, fout);
puttree(root->next, fout);
nextbranch = root->branches;
while (nextbranch) {
puttree(nextbranch->hsh, fout);
nextbranch = nextbranch->nextbranch;
}
}
int
putdtext(delta, srcname, fout, diffmt)
struct hshentry const *delta;
char const *srcname;
FILE *fout;
int diffmt;
/*
* Output a deltatext node with delta number DELTA->num, log message DELTA->log,
* ignored phrases DELTA->igtext and text SRCNAME to FOUT.
* Double up all SDELIMs in both the log and the text.
* Make sure the log message ends in \n.
* Return false on error.
* If DIFFMT, also check that the text is valid diff -n output.
*/
{
RILE *fin;
if (!(fin = Iopen(srcname, "r", (struct stat*)0))) {
eerror(srcname);
return false;
}
putdftext(delta, fin, fout, diffmt);
Ifclose(fin);
return true;
}
void
putstring(out, delim, s, log)
register FILE *out;
struct cbuf s;
int delim, log;
/*
* Output to OUT one SDELIM if DELIM, then the string S with SDELIMs doubled.
* If LOG is set then S is a log string; append a newline if S is nonempty.
*/
{
register char const *sp;
register size_t ss;
if (delim)
aputc_(SDELIM, out)
sp = s.string;
for (ss = s.size; ss; --ss) {
if (*sp == SDELIM)
aputc_(SDELIM, out)
aputc_(*sp++, out)
}
if (s.size && log)
aputc_('\n', out)
aputc_(SDELIM, out)
}
void
putdftext(delta, finfile, foutfile, diffmt)
struct hshentry const *delta;
RILE *finfile;
FILE *foutfile;
int diffmt;
/* like putdtext(), except the source file is already open */
{
declarecache;
register FILE *fout;
register int c;
register RILE *fin;
int ed;
struct diffcmd dc;
fout = foutfile;
aprintf(fout, DELNUMFORM, delta->num, Klog);
/* put log */
putstring(fout, true, delta->log, true);
aputc_('\n', fout)
/* put ignored phrases */
awrite(delta->igtext.string, delta->igtext.size, fout);
/* put text */
aprintf(fout, "%s\n%c", Ktext, SDELIM);
fin = finfile;
setupcache(fin);
if (!diffmt) {
/* Copy the file */
cache(fin);
for (;;) {
cachegeteof_(c, break;)
if (c==SDELIM) aputc_(SDELIM, fout) /*double up SDELIM*/
aputc_(c, fout)
}
} else {
initdiffcmd(&dc);
while (0 <= (ed = getdiffcmd(fin, false, fout, &dc)))
if (ed) {
cache(fin);
while (dc.nlines--)
do {
cachegeteof_(c, { if (!dc.nlines) goto OK_EOF; unexpected_EOF(); })
if (c == SDELIM)
aputc_(SDELIM, fout)
aputc_(c, fout)
} while (c != '\n');
uncache(fin);
}
}
OK_EOF:
aprintf(fout, "%c\n", SDELIM);
}

View file

@ -0,0 +1,452 @@
/* Extract RCS keyword string values from working files. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.10 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.9 1995/06/01 16:23:43 eggert
* (getoldkeys): Don't panic if a Name: is empty.
*
* Revision 5.8 1994/03/17 14:05:48 eggert
* Remove lint.
*
* Revision 5.7 1993/11/09 17:40:15 eggert
* Use simpler timezone parsing strategy now that we're using ISO 8601 format.
*
* Revision 5.6 1993/11/03 17:42:27 eggert
* Scan for Name keyword. Improve quality of diagnostics.
*
* Revision 5.5 1992/07/28 16:12:44 eggert
* Statement macro names now end in _.
*
* Revision 5.4 1991/08/19 03:13:55 eggert
* Tune.
*
* Revision 5.3 1991/04/21 11:58:25 eggert
* Shorten names to keep them distinct on shortname hosts.
*
* Revision 5.2 1990/10/04 06:30:20 eggert
* Parse time zone offsets; future RCS versions may output them.
*
* Revision 5.1 1990/09/20 02:38:56 eggert
* ci -k now checks dates more thoroughly.
*
* Revision 5.0 1990/08/22 08:12:53 eggert
* Retrieve old log message if there is one.
* Don't require final newline.
* Remove compile-time limits; use malloc instead. Tune.
* Permit dates past 1999/12/31. Ansify and Posixate.
*
* Revision 4.6 89/05/01 15:12:56 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.5 88/08/09 19:13:03 eggert
* Remove lint and speed up by making FILE *fp local, not global.
*
* Revision 4.4 87/12/18 11:44:21 narten
* more lint cleanups (Guy Harris)
*
* Revision 4.3 87/10/18 10:35:50 narten
* Updating version numbers. Changes relative to 1.1 actually relative
* to 4.1
*
* Revision 1.3 87/09/24 14:00:00 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:29 jenkins
* Port to suns
*
* Revision 4.1 83/05/10 16:26:44 wft
* Added new markers Id and RCSfile; extraction added.
* Marker matching with trymatch().
*
* Revision 3.2 82/12/24 12:08:26 wft
* added missing #endif.
*
* Revision 3.1 82/12/04 13:22:41 wft
* Initial revision.
*
*/
#include "rcsbase.h"
libId(keepId, "$FreeBSD$")
static int badly_terminated P((void));
static int checknum P((char const*));
static int get0val P((int,RILE*,struct buf*,int));
static int getval P((RILE*,struct buf*,int));
static int keepdate P((RILE*));
static int keepid P((int,RILE*,struct buf*));
static int keeprev P((RILE*));
int prevkeys;
struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
int
getoldkeys(fp)
register RILE *fp;
/* Function: Tries to read keyword values for author, date,
* revision number, and state out of the file fp.
* If fp is null, workname is opened and closed instead of using fp.
* The results are placed into
* prevauthor, prevdate, prevname, prevrev, prevstate.
* Aborts immediately if it finds an error and returns false.
* If it returns true, it doesn't mean that any of the
* values were found; instead, check to see whether the corresponding arrays
* contain the empty string.
*/
{
register int c;
char keyword[keylength+1];
register char * tp;
int needs_closing;
int prevname_found;
if (prevkeys)
return true;
needs_closing = false;
if (!fp) {
if (!(fp = Iopen(workname, FOPEN_R_WORK, (struct stat*)0))) {
eerror(workname);
return false;
}
needs_closing = true;
}
/* initialize to empty */
bufscpy(&prevauthor, "");
bufscpy(&prevdate, "");
bufscpy(&prevname, ""); prevname_found = 0;
bufscpy(&prevrev, "");
bufscpy(&prevstate, "");
c = '\0'; /* anything but KDELIM */
for (;;) {
if ( c==KDELIM) {
do {
/* try to get keyword */
tp = keyword;
for (;;) {
Igeteof_(fp, c, goto ok;)
switch (c) {
default:
if (keyword+keylength <= tp)
break;
*tp++ = c;
continue;
case '\n': case KDELIM: case VDELIM:
break;
}
break;
}
} while (c==KDELIM);
if (c!=VDELIM) continue;
*tp = c;
Igeteof_(fp, c, break;)
switch (c) {
case ' ': case '\t': break;
default: continue;
}
switch (trymatch(keyword)) {
case Author:
if (!keepid(0, fp, &prevauthor))
return false;
c = 0;
break;
case Date:
if (!(c = keepdate(fp)))
return false;
break;
case Header:
case Id:
case LocalId:
if (!(
getval(fp, (struct buf*)0, false) &&
keeprev(fp) &&
(c = keepdate(fp)) &&
keepid(c, fp, &prevauthor) &&
keepid(0, fp, &prevstate)
))
return false;
/* Skip either ``who'' (new form) or ``Locker: who'' (old). */
if (getval(fp, (struct buf*)0, true) &&
getval(fp, (struct buf*)0, true))
c = 0;
else if (nerror)
return false;
else
c = KDELIM;
break;
case Locker:
(void) getval(fp, (struct buf*)0, false);
c = 0;
break;
case Log:
case RCSfile:
case Source:
if (!getval(fp, (struct buf*)0, false))
return false;
c = 0;
break;
case Name:
if (getval(fp, &prevname, false)) {
if (*prevname.string)
checkssym(prevname.string);
prevname_found = 1;
}
c = 0;
break;
case Revision:
if (!keeprev(fp))
return false;
c = 0;
break;
case State:
if (!keepid(0, fp, &prevstate))
return false;
c = 0;
break;
default:
continue;
}
if (!c)
Igeteof_(fp, c, c=0;)
if (c != KDELIM) {
workerror("closing %c missing on keyword", KDELIM);
return false;
}
if (prevname_found &&
*prevauthor.string && *prevdate.string &&
*prevrev.string && *prevstate.string
)
break;
}
Igeteof_(fp, c, break;)
}
ok:
if (needs_closing)
Ifclose(fp);
else
Irewind(fp);
prevkeys = true;
return true;
}
static int
badly_terminated()
{
workerror("badly terminated keyword value");
return false;
}
static int
getval(fp, target, optional)
register RILE *fp;
struct buf *target;
int optional;
/* Reads a keyword value from FP into TARGET.
* Returns true if one is found, false otherwise.
* Does not modify target if it is 0.
* Do not report an error if OPTIONAL is set and KDELIM is found instead.
*/
{
int c;
Igeteof_(fp, c, return badly_terminated();)
return get0val(c, fp, target, optional);
}
static int
get0val(c, fp, target, optional)
register int c;
register RILE *fp;
struct buf *target;
int optional;
/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
* Same as getval, except C is the lookahead character.
*/
{ register char * tp;
char const *tlim;
register int got1;
if (target) {
bufalloc(target, 1);
tp = target->string;
tlim = tp + target->size;
} else
tlim = tp = 0;
got1 = false;
for (;;) {
switch (c) {
default:
got1 = true;
if (tp) {
*tp++ = c;
if (tlim <= tp)
tp = bufenlarge(target, &tlim);
}
break;
case ' ':
case '\t':
if (tp) {
*tp = 0;
# ifdef KEEPTEST
VOID printf("getval: %s\n", target);
# endif
}
return got1;
case KDELIM:
if (!got1 && optional)
return false;
/* fall into */
case '\n':
case 0:
return badly_terminated();
}
Igeteof_(fp, c, return badly_terminated();)
}
}
static int
keepdate(fp)
RILE *fp;
/* Function: reads a date prevdate; checks format
* Return 0 on error, lookahead character otherwise.
*/
{
struct buf prevday, prevtime;
register int c;
c = 0;
bufautobegin(&prevday);
if (getval(fp,&prevday,false)) {
bufautobegin(&prevtime);
if (getval(fp,&prevtime,false)) {
Igeteof_(fp, c, c=0;)
if (c) {
register char const *d = prevday.string, *t = prevtime.string;
bufalloc(&prevdate, strlen(d) + strlen(t) + 9);
VOID sprintf(prevdate.string, "%s%s %s%s",
/* Parse dates put out by old versions of RCS. */
isdigit(d[0]) && isdigit(d[1]) && !isdigit(d[2])
? "19" : "",
d, t,
strchr(t,'-') || strchr(t,'+') ? "" : "+0000"
);
}
}
bufautoend(&prevtime);
}
bufautoend(&prevday);
return c;
}
static int
keepid(c, fp, b)
int c;
RILE *fp;
struct buf *b;
/* Get previous identifier from C+FP into B. */
{
if (!c)
Igeteof_(fp, c, return false;)
if (!get0val(c, fp, b, false))
return false;
checksid(b->string);
return !nerror;
}
static int
keeprev(fp)
RILE *fp;
/* Get previous revision from FP into prevrev. */
{
return getval(fp,&prevrev,false) && checknum(prevrev.string);
}
static int
checknum(s)
char const *s;
{
register char const *sp;
register int dotcount = 0;
for (sp=s; ; sp++) {
switch (*sp) {
case 0:
if (dotcount & 1)
return true;
else
break;
case '.':
dotcount++;
continue;
default:
if (isdigit(*sp))
continue;
break;
}
break;
}
workerror("%s is not a revision number", s);
return false;
}
#ifdef KEEPTEST
/* Print the keyword values found. */
char const cmdid[] ="keeptest";
int
main(argc, argv)
int argc; char *argv[];
{
while (*(++argv)) {
workname = *argv;
getoldkeys((RILE*)0);
VOID printf("%s: revision: %s, date: %s, author: %s, name: %s, state: %s\n",
*argv, prevrev.string, prevdate.string, prevauthor.string, prevname.string, prevstate.string);
}
exitmain(EXIT_SUCCESS);
}
#endif

View file

@ -0,0 +1,186 @@
/* RCS keyword table and match operation */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.4 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.3 1993/11/03 17:42:27 eggert
* Add Name keyword.
*
* Revision 5.2 1991/08/19 03:13:55 eggert
* Say `T const' instead of `const T'; it's less confusing for pointer types.
* (This change was made in other source files too.)
*
* Revision 5.1 1991/04/21 11:58:25 eggert
* Don't put , just before } in initializer.
*
* Revision 5.0 1990/08/22 08:12:54 eggert
* Add -k. Ansify and Posixate.
*
* Revision 4.3 89/05/01 15:13:02 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.2 87/10/18 10:36:33 narten
* Updating version numbers. Changes relative to 1.1 actuallyt
* relative to 4.1
*
* Revision 1.2 87/09/24 14:00:10 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 4.1 83/05/04 10:06:53 wft
* Initial revision.
*
*/
#include "rcsbase.h"
libId(keysId, "$FreeBSD$")
char const *Keyword[] = {
/* This must be in the same order as rcsbase.h's enum markers type. */
0,
AUTHOR, DATE, HEADER, IDH,
LOCKER, LOG, NAME, RCSFILE, REVISION, SOURCE, STATE, CVSHEADER,
NULL
};
/* Expand all keywords by default */
static int ExpandKeyword[] = {
false,
true, true, true, true,
true, true, true, true, true, true, true, true,
true
};
enum markers LocalIdMode = Id;
enum markers
trymatch(string)
char const *string;
/* function: Checks whether string starts with a keyword followed
* by a KDELIM or a VDELIM.
* If successful, returns the appropriate marker, otherwise Nomatch.
*/
{
register int j;
register char const *p, *s;
for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); ) {
if (!ExpandKeyword[j])
continue;
/* try next keyword */
p = Keyword[j];
if (p == NULL)
continue;
s = string;
while (*p++ == *s++) {
if (!*p)
switch (*s) {
case KDELIM:
case VDELIM:
return (enum markers)j;
default:
return Nomatch;
}
}
}
return(Nomatch);
}
void
setIncExc(arg)
char const *arg;
/* Sets up the ExpandKeyword table according to command-line flags */
{
char *key;
char *copy, *next;
int include = 0, j;
copy = strdup(arg);
next = copy;
switch (*next++) {
case 'e':
include = false;
break;
case 'i':
include = true;
break;
default:
free(copy);
return;
}
if (include)
for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); )
ExpandKeyword[j] = false;
key = strtok(next, ",");
while (key) {
for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); ) {
if (Keyword[j] == NULL)
continue;
if (!strcmp(key, Keyword[j]))
ExpandKeyword[j] = include;
}
key = strtok(NULL, ",");
}
free(copy);
return;
}
void
setRCSLocalId(string)
char const *string;
/* function: sets local RCS id and RCSLOCALID envariable */
{
static char local_id[keylength+1];
char *copy, *next, *key;
int j;
copy = strdup(string);
next = copy;
key = strtok(next, "=");
if (strlen(key) > keylength)
faterror("LocalId is too long");
VOID strcpy(local_id, key);
Keyword[LocalId] = local_id;
/* options? */
while (key = strtok(NULL, ",")) {
if (!strcmp(key, Keyword[Id]))
LocalIdMode=Id;
else if (!strcmp(key, Keyword[Header]))
LocalIdMode=Header;
else if (!strcmp(key, Keyword[CVSHeader]))
LocalIdMode=CVSHeader;
else
error("Unknown LocalId mode");
}
free(copy);
}

1568
gnu/usr.bin/rcs/lib/rcslex.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,69 @@
/* RCS map of character types */
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1995 by Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#include "rcsbase.h"
libId(mapId, "$FreeBSD$")
/* map of character types */
/* ISO 8859/1 (Latin-1) */
enum tokens const ctab[] = {
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
SPACE, SPACE, NEWLN, SPACE, SPACE, SPACE, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
SPACE, IDCHAR, IDCHAR, IDCHAR, DELIM, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, DELIM, IDCHAR, PERIOD, IDCHAR,
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
DIGIT, DIGIT, COLON, SEMI, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
SBEGIN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, IDCHAR, IDCHAR, IDCHAR, IDCHAR, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, IDCHAR,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, IDCHAR,
Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter
};

View file

@ -0,0 +1,911 @@
/* Handle RCS revision numbers. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.10 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.9 1995/06/01 16:23:43 eggert
* (cmpdate, normalizeyear): New functions work around MKS RCS incompatibility.
* (cmpnum, compartial): s[d] -> *(s+d) to work around Cray compiler bug.
* (genrevs, genbranch): cmpnum -> cmpdate
*
* Revision 5.8 1994/03/17 14:05:48 eggert
* Remove lint.
*
* Revision 5.7 1993/11/09 17:40:15 eggert
* Fix format string typos.
*
* Revision 5.6 1993/11/03 17:42:27 eggert
* Revision number `.N' now stands for `D.N', where D is the default branch.
* Add -z. Improve quality of diagnostics. Add `namedrev' for Name support.
*
* Revision 5.5 1992/07/28 16:12:44 eggert
* Identifiers may now start with a digit. Avoid `unsigned'.
*
* Revision 5.4 1992/01/06 02:42:34 eggert
* while (E) ; -> while (E) continue;
*
* Revision 5.3 1991/08/19 03:13:55 eggert
* Add `-r$', `-rB.'. Remove botches like `<now>' from messages. Tune.
*
* Revision 5.2 1991/04/21 11:58:28 eggert
* Add tiprev().
*
* Revision 5.1 1991/02/25 07:12:43 eggert
* Avoid overflow when comparing revision numbers.
*
* Revision 5.0 1990/08/22 08:13:43 eggert
* Remove compile-time limits; use malloc instead.
* Ansify and Posixate. Tune.
* Remove possibility of an internal error. Remove lint.
*
* Revision 4.5 89/05/01 15:13:22 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 87/12/18 11:45:22 narten
* more lint cleanups. Also, the NOTREACHED comment is no longer necessary,
* since there's now a return value there with a value. (Guy Harris)
*
* Revision 4.3 87/10/18 10:38:42 narten
* Updating version numbers. Changes relative to version 1.1 actually
* relative to 4.1
*
* Revision 1.3 87/09/24 14:00:37 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:37 jenkins
* Port to suns
*
* Revision 4.1 83/03/25 21:10:45 wft
* Only changed $Header to $Id.
*
* Revision 3.4 82/12/04 13:24:08 wft
* Replaced getdelta() with gettree().
*
* Revision 3.3 82/11/28 21:33:15 wft
* fixed compartial() and compnum() for nil-parameters; fixed nils
* in error messages. Testprogram output shortenend.
*
* Revision 3.2 82/10/18 21:19:47 wft
* renamed compnum->cmpnum, compnumfld->cmpnumfld,
* numericrevno->numricrevno.
*
* Revision 3.1 82/10/11 19:46:09 wft
* changed expandsym() to check for source==nil; returns zero length string
* in that case.
*/
#include "rcsbase.h"
libId(revId, "$FreeBSD$")
static char const *branchtip P((char const*));
static char const *lookupsym P((char const*));
static char const *normalizeyear P((char const*,char[5]));
static struct hshentry *genbranch P((struct hshentry const*,char const*,int,char const*,char const*,char const*,struct hshentries**));
static void absent P((char const*,int));
static void cantfindbranch P((char const*,char const[datesize],char const*,char const*));
static void store1 P((struct hshentries***,struct hshentry*));
int
countnumflds(s)
char const *s;
/* Given a pointer s to a dotted number (date or revision number),
* countnumflds returns the number of digitfields in s.
*/
{
register char const *sp;
register int count;
if (!(sp=s) || !*sp)
return 0;
count = 1;
do {
if (*sp++ == '.') count++;
} while (*sp);
return(count);
}
void
getbranchno(revno,branchno)
char const *revno;
struct buf *branchno;
/* Given a revision number revno, getbranchno copies the number of the branch
* on which revno is into branchno. If revno itself is a branch number,
* it is copied unchanged.
*/
{
register int numflds;
register char *tp;
bufscpy(branchno, revno);
numflds=countnumflds(revno);
if (!(numflds & 1)) {
tp = branchno->string;
while (--numflds)
while (*tp++ != '.')
continue;
*(tp-1)='\0';
}
}
int cmpnum(num1, num2)
char const *num1, *num2;
/* compares the two dotted numbers num1 and num2 lexicographically
* by field. Individual fields are compared numerically.
* returns <0, 0, >0 if num1<num2, num1==num2, and num1>num2, resp.
* omitted fields are assumed to be higher than the existing ones.
*/
{
register char const *s1, *s2;
register size_t d1, d2;
register int r;
s1 = num1 ? num1 : "";
s2 = num2 ? num2 : "";
for (;;) {
/* Give precedence to shorter one. */
if (!*s1)
return (unsigned char)*s2;
if (!*s2)
return -1;
/* Strip leading zeros, then find number of digits. */
while (*s1=='0') ++s1;
while (*s2=='0') ++s2;
for (d1=0; isdigit(*(s1+d1)); d1++) continue;
for (d2=0; isdigit(*(s2+d2)); d2++) continue;
/* Do not convert to integer; it might overflow! */
if (d1 != d2)
return d1<d2 ? -1 : 1;
if ((r = memcmp(s1, s2, d1)))
return r;
s1 += d1;
s2 += d1;
/* skip '.' */
if (*s1) s1++;
if (*s2) s2++;
}
}
int cmpnumfld(num1, num2, fld)
char const *num1, *num2;
int fld;
/* Compare the two dotted numbers at field fld.
* num1 and num2 must have at least fld fields.
* fld must be positive.
*/
{
register char const *s1, *s2;
register size_t d1, d2;
s1 = num1;
s2 = num2;
/* skip fld-1 fields */
while (--fld) {
while (*s1++ != '.')
continue;
while (*s2++ != '.')
continue;
}
/* Now s1 and s2 point to the beginning of the respective fields */
while (*s1=='0') ++s1; for (d1=0; isdigit(*(s1+d1)); d1++) continue;
while (*s2=='0') ++s2; for (d2=0; isdigit(*(s2+d2)); d2++) continue;
return d1<d2 ? -1 : d1==d2 ? memcmp(s1,s2,d1) : 1;
}
int
cmpdate(d1, d2)
char const *d1, *d2;
/*
* Compare the two dates. This is just like cmpnum,
* except that for compatibility with old versions of RCS,
* 1900 is added to dates with two-digit years.
*/
{
char year1[5], year2[5];
int r = cmpnumfld(normalizeyear(d1,year1), normalizeyear(d2,year2), 1);
if (r)
return r;
else {
while (isdigit(*d1)) d1++; d1 += *d1=='.';
while (isdigit(*d2)) d2++; d2 += *d2=='.';
return cmpnum(d1, d2);
}
}
static char const *
normalizeyear(date, year)
char const *date;
char year[5];
{
if (isdigit(date[0]) && isdigit(date[1]) && !isdigit(date[2])) {
year[0] = '1';
year[1] = '9';
year[2] = date[0];
year[3] = date[1];
year[4] = 0;
return year;
} else
return date;
}
static void
cantfindbranch(revno, date, author, state)
char const *revno, date[datesize], *author, *state;
{
char datebuf[datesize + zonelenmax];
rcserror("No revision on branch %s has%s%s%s%s%s%s.",
revno,
date ? " a date before " : "",
date ? date2str(date,datebuf) : "",
author ? " and author "+(date?0:4) : "",
author ? author : "",
state ? " and state "+(date||author?0:4) : "",
state ? state : ""
);
}
static void
absent(revno, field)
char const *revno;
int field;
{
struct buf t;
bufautobegin(&t);
rcserror("%s %s absent", field&1?"revision":"branch",
partialno(&t,revno,field)
);
bufautoend(&t);
}
int
compartial(num1, num2, length)
char const *num1, *num2;
int length;
/* compare the first "length" fields of two dot numbers;
the omitted field is considered to be larger than any number */
/* restriction: at least one number has length or more fields */
{
register char const *s1, *s2;
register size_t d1, d2;
register int r;
s1 = num1; s2 = num2;
if (!s1) return 1;
if (!s2) return -1;
for (;;) {
if (!*s1) return 1;
if (!*s2) return -1;
while (*s1=='0') ++s1; for (d1=0; isdigit(*(s1+d1)); d1++) continue;
while (*s2=='0') ++s2; for (d2=0; isdigit(*(s2+d2)); d2++) continue;
if (d1 != d2)
return d1<d2 ? -1 : 1;
if ((r = memcmp(s1, s2, d1)))
return r;
if (!--length)
return 0;
s1 += d1;
s2 += d1;
if (*s1 == '.') s1++;
if (*s2 == '.') s2++;
}
}
char * partialno(rev1,rev2,length)
struct buf *rev1;
char const *rev2;
register int length;
/* Function: Copies length fields of revision number rev2 into rev1.
* Return rev1's string.
*/
{
register char *r1;
bufscpy(rev1, rev2);
r1 = rev1->string;
while (length) {
while (*r1!='.' && *r1)
++r1;
++r1;
length--;
}
/* eliminate last '.'*/
*(r1-1)='\0';
return rev1->string;
}
static void
store1(store, next)
struct hshentries ***store;
struct hshentry *next;
/*
* Allocate a new list node that addresses NEXT.
* Append it to the list that **STORE is the end pointer of.
*/
{
register struct hshentries *p;
p = ftalloc(struct hshentries);
p->first = next;
**store = p;
*store = &p->rest;
}
struct hshentry * genrevs(revno,date,author,state,store)
char const *revno, *date, *author, *state;
struct hshentries **store;
/* Function: finds the deltas needed for reconstructing the
* revision given by revno, date, author, and state, and stores pointers
* to these deltas into a list whose starting address is given by store.
* The last delta (target delta) is returned.
* If the proper delta could not be found, 0 is returned.
*/
{
int length;
register struct hshentry * next;
int result;
char const *branchnum;
struct buf t;
char datebuf[datesize + zonelenmax];
bufautobegin(&t);
if (!(next = Head)) {
rcserror("RCS file empty");
goto norev;
}
length = countnumflds(revno);
if (length >= 1) {
/* at least one field; find branch exactly */
while ((result=cmpnumfld(revno,next->num,1)) < 0) {
store1(&store, next);
next = next->next;
if (!next) {
rcserror("branch number %s too low", partialno(&t,revno,1));
goto norev;
}
}
if (result>0) {
absent(revno, 1);
goto norev;
}
}
if (length<=1){
/* pick latest one on given branch */
branchnum = next->num; /* works even for empty revno*/
while (next &&
cmpnumfld(branchnum,next->num,1) == 0 &&
(
(date && cmpdate(date,next->date) < 0) ||
(author && strcmp(author,next->author) != 0) ||
(state && strcmp(state,next->state) != 0)
)
)
{
store1(&store, next);
next=next->next;
}
if (!next ||
(cmpnumfld(branchnum,next->num,1)!=0))/*overshot*/ {
cantfindbranch(
length ? revno : partialno(&t,branchnum,1),
date, author, state
);
goto norev;
} else {
store1(&store, next);
}
*store = 0;
return next;
}
/* length >=2 */
/* find revision; may go low if length==2*/
while ((result=cmpnumfld(revno,next->num,2)) < 0 &&
(cmpnumfld(revno,next->num,1)==0) ) {
store1(&store, next);
next = next->next;
if (!next)
break;
}
if (!next || cmpnumfld(revno,next->num,1) != 0) {
rcserror("revision number %s too low", partialno(&t,revno,2));
goto norev;
}
if ((length>2) && (result!=0)) {
absent(revno, 2);
goto norev;
}
/* print last one */
store1(&store, next);
if (length>2)
return genbranch(next,revno,length,date,author,state,store);
else { /* length == 2*/
if (date && cmpdate(date,next->date)<0) {
rcserror("Revision %s has date %s.",
next->num,
date2str(next->date, datebuf)
);
return 0;
}
if (author && strcmp(author,next->author)!=0) {
rcserror("Revision %s has author %s.",
next->num, next->author
);
return 0;
}
if (state && strcmp(state,next->state)!=0) {
rcserror("Revision %s has state %s.",
next->num,
next->state ? next->state : "<empty>"
);
return 0;
}
*store = 0;
return next;
}
norev:
bufautoend(&t);
return 0;
}
static struct hshentry *
genbranch(bpoint, revno, length, date, author, state, store)
struct hshentry const *bpoint;
char const *revno;
int length;
char const *date, *author, *state;
struct hshentries **store;
/* Function: given a branchpoint, a revision number, date, author, and state,
* genbranch finds the deltas necessary to reconstruct the given revision
* from the branch point on.
* Pointers to the found deltas are stored in a list beginning with store.
* revno must be on a side branch.
* Return 0 on error.
*/
{
int field;
register struct hshentry * next, * trail;
register struct branchhead const *bhead;
int result;
struct buf t;
char datebuf[datesize + zonelenmax];
field = 3;
bhead = bpoint->branches;
do {
if (!bhead) {
bufautobegin(&t);
rcserror("no side branches present for %s",
partialno(&t,revno,field-1)
);
bufautoend(&t);
return 0;
}
/*find branch head*/
/*branches are arranged in increasing order*/
while (0 < (result=cmpnumfld(revno,bhead->hsh->num,field))) {
bhead = bhead->nextbranch;
if (!bhead) {
bufautobegin(&t);
rcserror("branch number %s too high",
partialno(&t,revno,field)
);
bufautoend(&t);
return 0;
}
}
if (result<0) {
absent(revno, field);
return 0;
}
next = bhead->hsh;
if (length==field) {
/* pick latest one on that branch */
trail = 0;
do { if ((!date || cmpdate(date,next->date)>=0) &&
(!author || strcmp(author,next->author)==0) &&
(!state || strcmp(state,next->state)==0)
) trail = next;
next=next->next;
} while (next);
if (!trail) {
cantfindbranch(revno, date, author, state);
return 0;
} else { /* print up to last one suitable */
next = bhead->hsh;
while (next!=trail) {
store1(&store, next);
next=next->next;
}
store1(&store, next);
}
*store = 0;
return next;
}
/* length > field */
/* find revision */
/* check low */
if (cmpnumfld(revno,next->num,field+1)<0) {
bufautobegin(&t);
rcserror("revision number %s too low",
partialno(&t,revno,field+1)
);
bufautoend(&t);
return 0;
}
do {
store1(&store, next);
trail = next;
next = next->next;
} while (next && cmpnumfld(revno,next->num,field+1)>=0);
if ((length>field+1) && /*need exact hit */
(cmpnumfld(revno,trail->num,field+1) !=0)){
absent(revno, field+1);
return 0;
}
if (length == field+1) {
if (date && cmpdate(date,trail->date)<0) {
rcserror("Revision %s has date %s.",
trail->num,
date2str(trail->date, datebuf)
);
return 0;
}
if (author && strcmp(author,trail->author)!=0) {
rcserror("Revision %s has author %s.",
trail->num, trail->author
);
return 0;
}
if (state && strcmp(state,trail->state)!=0) {
rcserror("Revision %s has state %s.",
trail->num,
trail->state ? trail->state : "<empty>"
);
return 0;
}
}
bhead = trail->branches;
} while ((field+=2) <= length);
*store = 0;
return trail;
}
static char const *
lookupsym(id)
char const *id;
/* Function: looks up id in the list of symbolic names starting
* with pointer SYMBOLS, and returns a pointer to the corresponding
* revision number. Return 0 if not present.
*/
{
register struct assoc const *next;
for (next = Symbols; next; next = next->nextassoc)
if (strcmp(id, next->symbol)==0)
return next->num;
return 0;
}
int expandsym(source, target)
char const *source;
struct buf *target;
/* Function: Source points to a revision number. Expandsym copies
* the number to target, but replaces all symbolic fields in the
* source number with their numeric values.
* Expand a branch followed by `.' to the latest revision on that branch.
* Ignore `.' after a revision. Remove leading zeros.
* returns false on error;
*/
{
return fexpandsym(source, target, (RILE*)0);
}
int
fexpandsym(source, target, fp)
char const *source;
struct buf *target;
RILE *fp;
/* Same as expandsym, except if FP is nonzero, it is used to expand KDELIM. */
{
register char const *sp, *bp;
register char *tp;
char const *tlim;
int dots;
sp = source;
bufalloc(target, 1);
tp = target->string;
if (!sp || !*sp) { /* Accept 0 pointer as a legal value. */
*tp='\0';
return true;
}
if (sp[0] == KDELIM && !sp[1]) {
if (!getoldkeys(fp))
return false;
if (!*prevrev.string) {
workerror("working file lacks revision number");
return false;
}
bufscpy(target, prevrev.string);
return true;
}
tlim = tp + target->size;
dots = 0;
for (;;) {
register char *p = tp;
size_t s = tp - target->string;
int id = false;
for (;;) {
switch (ctab[(unsigned char)*sp]) {
case IDCHAR:
case LETTER:
case Letter:
id = true;
/* fall into */
case DIGIT:
if (tlim <= p)
p = bufenlarge(target, &tlim);
*p++ = *sp++;
continue;
default:
break;
}
break;
}
if (tlim <= p)
p = bufenlarge(target, &tlim);
*p = 0;
tp = target->string + s;
if (id) {
bp = lookupsym(tp);
if (!bp) {
rcserror("Symbolic name `%s' is undefined.",tp);
return false;
}
} else {
/* skip leading zeros */
for (bp = tp; *bp=='0' && isdigit(bp[1]); bp++)
continue;
if (!*bp)
if (s || *sp!='.')
break;
else {
/* Insert default branch before initial `.'. */
char const *b;
if (Dbranch)
b = Dbranch;
else if (Head)
b = Head->num;
else
break;
getbranchno(b, target);
bp = tp = target->string;
tlim = tp + target->size;
}
}
while ((*tp++ = *bp++))
if (tlim <= tp)
tp = bufenlarge(target, &tlim);
switch (*sp++) {
case '\0':
return true;
case '.':
if (!*sp) {
if (dots & 1)
break;
if (!(bp = branchtip(target->string)))
return false;
bufscpy(target, bp);
return true;
}
++dots;
tp[-1] = '.';
continue;
}
break;
}
rcserror("improper revision number: %s", source);
return false;
}
char const *
namedrev(name, delta)
char const *name;
struct hshentry *delta;
/* Yield NAME if it names DELTA, 0 otherwise. */
{
if (name) {
char const *id = 0, *p, *val;
for (p = name; ; p++)
switch (ctab[(unsigned char)*p]) {
case IDCHAR:
case LETTER:
case Letter:
id = name;
break;
case DIGIT:
break;
case UNKN:
if (!*p && id &&
(val = lookupsym(id)) &&
strcmp(val, delta->num) == 0
)
return id;
/* fall into */
default:
return 0;
}
}
return 0;
}
static char const *
branchtip(branch)
char const *branch;
{
struct hshentry *h;
struct hshentries *hs;
h = genrevs(branch, (char*)0, (char*)0, (char*)0, &hs);
return h ? h->num : (char const*)0;
}
char const *
tiprev()
{
return Dbranch ? branchtip(Dbranch) : Head ? Head->num : (char const*)0;
}
#ifdef REVTEST
/*
* Test the routines that generate a sequence of delta numbers
* needed to regenerate a given delta.
*/
char const cmdid[] = "revtest";
int
main(argc,argv)
int argc; char * argv[];
{
static struct buf numricrevno;
char symrevno[100]; /* used for input of revision numbers */
char author[20];
char state[20];
char date[20];
struct hshentries *gendeltas;
struct hshentry * target;
int i;
if (argc<2) {
aputs("No input file\n",stderr);
exitmain(EXIT_FAILURE);
}
if (!(finptr=Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
faterror("can't open input file %s", argv[1]);
}
Lexinit();
getadmin();
gettree();
getdesc(false);
do {
/* all output goes to stderr, to have diagnostics and */
/* errors in sequence. */
aputs("\nEnter revision number or <return> or '.': ",stderr);
if (!fgets(symrevno, 100, stdin)) break;
if (*symrevno == '.') break;
aprintf(stderr,"%s;\n",symrevno);
expandsym(symrevno,&numricrevno);
aprintf(stderr,"expanded number: %s; ",numricrevno.string);
aprintf(stderr,"Date: ");
fgets(date, 20, stdin); aprintf(stderr,"%s; ",date);
aprintf(stderr,"Author: ");
fgets(author, 20, stdin); aprintf(stderr,"%s; ",author);
aprintf(stderr,"State: ");
fgets(state, 20, stdin); aprintf(stderr, "%s;\n", state);
target = genrevs(numricrevno.string, *date?date:(char *)0, *author?author:(char *)0,
*state?state:(char*)0, &gendeltas);
if (target) {
while (gendeltas) {
aprintf(stderr,"%s\n",gendeltas->first->num);
gendeltas = gendeltas->next;
}
}
} while (true);
aprintf(stderr,"done\n");
exitmain(EXIT_SUCCESS);
}
void exiterr() { _exit(EXIT_FAILURE); }
#endif

View file

@ -0,0 +1,681 @@
/* RCS file syntactic analysis */
/******************************************************************************
* Syntax Analysis.
* Keyword table
* Testprogram: define SYNTEST
* Compatibility with Release 2: define COMPAT2=1
******************************************************************************
*/
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.15 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.14 1995/06/01 16:23:43 eggert
* (expand_names): Add "b" for -kb.
* (getdelta): Don't strip leading "19" from MKS RCS dates; see cmpdate.
*
* Revision 5.13 1994/03/20 04:52:58 eggert
* Remove lint.
*
* Revision 5.12 1993/11/03 17:42:27 eggert
* Parse MKS RCS dates; ignore \r in diff control lines.
* Don't discard ignored phrases. Improve quality of diagnostics.
*
* Revision 5.11 1992/07/28 16:12:44 eggert
* Avoid `unsigned'. Statement macro names now end in _.
*
* Revision 5.10 1992/01/24 18:44:19 eggert
* Move put routines to rcsgen.c.
*
* Revision 5.9 1992/01/06 02:42:34 eggert
* ULONG_MAX/10 -> ULONG_MAX_OVER_10
* while (E) ; -> while (E) continue;
*
* Revision 5.8 1991/08/19 03:13:55 eggert
* Tune.
*
* Revision 5.7 1991/04/21 11:58:29 eggert
* Disambiguate names on shortname hosts.
* Fix errno bug. Add MS-DOS support.
*
* Revision 5.6 1991/02/28 19:18:51 eggert
* Fix null termination bug in reporting keyword expansion.
*
* Revision 5.5 1991/02/25 07:12:44 eggert
* Check diff output more carefully; avoid overflow.
*
* Revision 5.4 1990/11/01 05:28:48 eggert
* When ignoring unknown phrases, copy them to the output RCS file.
* Permit arbitrary data in logs and comment leaders.
* Don't check for nontext on initial checkin.
*
* Revision 5.3 1990/09/20 07:58:32 eggert
* Remove the test for non-text bytes; it caused more pain than it cured.
*
* Revision 5.2 1990/09/04 08:02:30 eggert
* Parse RCS files with no revisions.
* Don't strip leading white space from diff commands. Count RCS lines better.
*
* Revision 5.1 1990/08/29 07:14:06 eggert
* Add -kkvl. Clean old log messages too.
*
* Revision 5.0 1990/08/22 08:13:44 eggert
* Try to parse future RCS formats without barfing.
* Add -k. Don't require final newline.
* Remove compile-time limits; use malloc instead.
* Don't output branch keyword if there's no default branch,
* because RCS version 3 doesn't understand it.
* Tune. Remove lint.
* Add support for ISO 8859. Ansify and Posixate.
* Check that a newly checked-in file is acceptable as input to 'diff'.
* Check diff's output.
*
* Revision 4.6 89/05/01 15:13:32 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.5 88/08/09 19:13:21 eggert
* Allow cc -R; remove lint.
*
* Revision 4.4 87/12/18 11:46:16 narten
* more lint cleanups (Guy Harris)
*
* Revision 4.3 87/10/18 10:39:36 narten
* Updating version numbers. Changes relative to 1.1 actually relative to
* 4.1
*
* Revision 1.3 87/09/24 14:00:49 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:40 jenkins
* Port to suns
*
* Revision 4.1 83/03/28 11:38:49 wft
* Added parsing and printing of default branch.
*
* Revision 3.6 83/01/15 17:46:50 wft
* Changed readdelta() to initialize selector and log-pointer.
* Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
*
* Revision 3.5 82/12/08 21:58:58 wft
* renamed Commentleader to Commleader.
*
* Revision 3.4 82/12/04 13:24:40 wft
* Added routine gettree(), which updates keeplock after reading the
* delta tree.
*
* Revision 3.3 82/11/28 21:30:11 wft
* Reading and printing of Suffix removed; version COMPAT2 skips the
* Suffix for files of release 2 format. Fixed problems with printing nil.
*
* Revision 3.2 82/10/18 21:18:25 wft
* renamed putdeltatext to putdtext.
*
* Revision 3.1 82/10/11 19:45:11 wft
* made sure getc() returns into an integer.
*/
/* version COMPAT2 reads files of the format of release 2 and 3, but
* generates files of release 3 format. Need not be defined if no
* old RCS files generated with release 2 exist.
*/
#include "rcsbase.h"
libId(synId, "$FreeBSD$")
static char const *getkeyval P((char const*,enum tokens,int));
static int getdelta P((void));
static int strn2expmode P((char const*,size_t));
static struct hshentry *getdnum P((void));
static void badDiffOutput P((char const*)) exiting;
static void diffLineNumberTooLarge P((char const*)) exiting;
static void getsemi P((char const*));
/* keyword table */
char const
Kaccess[] = "access",
Kauthor[] = "author",
Kbranch[] = "branch",
Kcomment[] = "comment",
Kdate[] = "date",
Kdesc[] = "desc",
Kexpand[] = "expand",
Khead[] = "head",
Klocks[] = "locks",
Klog[] = "log",
Knext[] = "next",
Kstate[] = "state",
Kstrict[] = "strict",
Ksymbols[] = "symbols",
Ktext[] = "text";
static char const
#if COMPAT2
Ksuffix[] = "suffix",
#endif
K_branches[]= "branches";
static struct buf Commleader;
struct cbuf Comment;
struct cbuf Ignored;
struct access * AccessList;
struct assoc * Symbols;
struct rcslock *Locks;
int Expand;
int StrictLocks;
struct hshentry * Head;
char const * Dbranch;
int TotalDeltas;
static void
getsemi(key)
char const *key;
/* Get a semicolon to finish off a phrase started by KEY. */
{
if (!getlex(SEMI))
fatserror("missing ';' after '%s'", key);
}
static struct hshentry *
getdnum()
/* Get a delta number. */
{
register struct hshentry *delta = getnum();
if (delta && countnumflds(delta->num)&1)
fatserror("%s isn't a delta number", delta->num);
return delta;
}
void
getadmin()
/* Read an <admin> and initialize the appropriate global variables. */
{
register char const *id;
struct access * newaccess;
struct assoc * newassoc;
struct rcslock *newlock;
struct hshentry * delta;
struct access **LastAccess;
struct assoc **LastSymbol;
struct rcslock **LastLock;
struct buf b;
struct cbuf cb;
TotalDeltas=0;
getkey(Khead);
Head = getdnum();
getsemi(Khead);
Dbranch = 0;
if (getkeyopt(Kbranch)) {
if ((delta = getnum()))
Dbranch = delta->num;
getsemi(Kbranch);
}
#if COMPAT2
/* read suffix. Only in release 2 format */
if (getkeyopt(Ksuffix)) {
if (nexttok==STRING) {
readstring(); nextlex(); /* Throw away the suffix. */
} else if (nexttok==ID) {
nextlex();
}
getsemi(Ksuffix);
}
#endif
getkey(Kaccess);
LastAccess = &AccessList;
while ((id = getid())) {
newaccess = ftalloc(struct access);
newaccess->login = id;
*LastAccess = newaccess;
LastAccess = &newaccess->nextaccess;
}
*LastAccess = 0;
getsemi(Kaccess);
getkey(Ksymbols);
LastSymbol = &Symbols;
while ((id = getid())) {
if (!getlex(COLON))
fatserror("missing ':' in symbolic name definition");
if (!(delta=getnum())) {
fatserror("missing number in symbolic name definition");
} else { /*add new pair to association list*/
newassoc = ftalloc(struct assoc);
newassoc->symbol=id;
newassoc->num = delta->num;
*LastSymbol = newassoc;
LastSymbol = &newassoc->nextassoc;
}
}
*LastSymbol = 0;
getsemi(Ksymbols);
getkey(Klocks);
LastLock = &Locks;
while ((id = getid())) {
if (!getlex(COLON))
fatserror("missing ':' in lock");
if (!(delta=getdnum())) {
fatserror("missing number in lock");
} else { /*add new pair to lock list*/
newlock = ftalloc(struct rcslock);
newlock->login=id;
newlock->delta=delta;
*LastLock = newlock;
LastLock = &newlock->nextlock;
}
}
*LastLock = 0;
getsemi(Klocks);
if ((StrictLocks = getkeyopt(Kstrict)))
getsemi(Kstrict);
clear_buf(&Comment);
if (getkeyopt(Kcomment)) {
if (nexttok==STRING) {
Comment = savestring(&Commleader);
nextlex();
}
getsemi(Kcomment);
}
Expand = KEYVAL_EXPAND;
if (getkeyopt(Kexpand)) {
if (nexttok==STRING) {
bufautobegin(&b);
cb = savestring(&b);
if ((Expand = strn2expmode(cb.string,cb.size)) < 0)
fatserror("unknown expand mode %.*s",
(int)cb.size, cb.string
);
bufautoend(&b);
nextlex();
}
getsemi(Kexpand);
}
Ignored = getphrases(Kdesc);
}
char const *const expand_names[] = {
/* These must agree with *_EXPAND in rcsbase.h. */
"kv", "kvl", "k", "v", "o", "b",
0
};
int
str2expmode(s)
char const *s;
/* Yield expand mode corresponding to S, or -1 if bad. */
{
return strn2expmode(s, strlen(s));
}
static int
strn2expmode(s, n)
char const *s;
size_t n;
{
char const *const *p;
for (p = expand_names; *p; ++p)
if (memcmp(*p,s,n) == 0 && !(*p)[n])
return p - expand_names;
return -1;
}
void
ignorephrases(key)
const char *key;
/*
* Ignore a series of phrases that do not start with KEY.
* Stop when the next phrase starts with a token that is not an identifier,
* or is KEY.
*/
{
for (;;) {
nextlex();
if (nexttok != ID || strcmp(NextString,key) == 0)
break;
warnignore();
hshenter=false;
for (;; nextlex()) {
switch (nexttok) {
case SEMI: hshenter=true; break;
case ID:
case NUM: ffree1(NextString); continue;
case STRING: readstring(); continue;
default: continue;
}
break;
}
}
}
static int
getdelta()
/* Function: reads a delta block.
* returns false if the current block does not start with a number.
*/
{
register struct hshentry * Delta, * num;
struct branchhead **LastBranch, *NewBranch;
if (!(Delta = getdnum()))
return false;
hshenter = false; /*Don't enter dates into hashtable*/
Delta->date = getkeyval(Kdate, NUM, false);
hshenter=true; /*reset hshenter for revision numbers.*/
Delta->author = getkeyval(Kauthor, ID, false);
Delta->state = getkeyval(Kstate, ID, true);
getkey(K_branches);
LastBranch = &Delta->branches;
while ((num = getdnum())) {
NewBranch = ftalloc(struct branchhead);
NewBranch->hsh = num;
*LastBranch = NewBranch;
LastBranch = &NewBranch->nextbranch;
}
*LastBranch = 0;
getsemi(K_branches);
getkey(Knext);
Delta->next = num = getdnum();
getsemi(Knext);
Delta->lockedby = 0;
Delta->log.string = 0;
Delta->selector = true;
Delta->ig = getphrases(Kdesc);
TotalDeltas++;
return (true);
}
void
gettree()
/* Function: Reads in the delta tree with getdelta(), then
* updates the lockedby fields.
*/
{
struct rcslock const *currlock;
while (getdelta())
continue;
currlock=Locks;
while (currlock) {
currlock->delta->lockedby = currlock->login;
currlock = currlock->nextlock;
}
}
void
getdesc(prdesc)
int prdesc;
/* Function: read in descriptive text
* nexttok is not advanced afterwards.
* If prdesc is set, the text is printed to stdout.
*/
{
getkeystring(Kdesc);
if (prdesc)
printstring(); /*echo string*/
else readstring(); /*skip string*/
}
static char const *
getkeyval(keyword, token, optional)
char const *keyword;
enum tokens token;
int optional;
/* reads a pair of the form
* <keyword> <token> ;
* where token is one of <id> or <num>. optional indicates whether
* <token> is optional. A pointer to
* the actual character string of <id> or <num> is returned.
*/
{
register char const *val = 0;
getkey(keyword);
if (nexttok==token) {
val = NextString;
nextlex();
} else {
if (!optional)
fatserror("missing %s", keyword);
}
getsemi(keyword);
return(val);
}
void
unexpected_EOF()
{
rcsfaterror("unexpected EOF in diff output");
}
void
initdiffcmd(dc)
register struct diffcmd *dc;
/* Initialize *dc suitably for getdiffcmd(). */
{
dc->adprev = 0;
dc->dafter = 0;
}
static void
badDiffOutput(buf)
char const *buf;
{
rcsfaterror("bad diff output line: %s", buf);
}
static void
diffLineNumberTooLarge(buf)
char const *buf;
{
rcsfaterror("diff line number too large: %s", buf);
}
int
getdiffcmd(finfile, delimiter, foutfile, dc)
RILE *finfile;
FILE *foutfile;
int delimiter;
struct diffcmd *dc;
/* Get a editing command output by 'diff -n' from fin.
* The input is delimited by SDELIM if delimiter is set, EOF otherwise.
* Copy a clean version of the command to fout (if nonnull).
* Yield 0 for 'd', 1 for 'a', and -1 for EOF.
* Store the command's line number and length into dc->line1 and dc->nlines.
* Keep dc->adprev and dc->dafter up to date.
*/
{
register int c;
declarecache;
register FILE *fout;
register char *p;
register RILE *fin;
long line1, nlines, t;
char buf[BUFSIZ];
fin = finfile;
fout = foutfile;
setupcache(fin); cache(fin);
cachegeteof_(c, { if (delimiter) unexpected_EOF(); return -1; } )
if (delimiter) {
if (c==SDELIM) {
cacheget_(c)
if (c==SDELIM) {
buf[0] = c;
buf[1] = 0;
badDiffOutput(buf);
}
uncache(fin);
nextc = c;
if (fout)
aprintf(fout, "%c%c", SDELIM, c);
return -1;
}
}
p = buf;
do {
if (buf+BUFSIZ-2 <= p) {
rcsfaterror("diff output command line too long");
}
*p++ = c;
cachegeteof_(c, unexpected_EOF();)
} while (c != '\n');
uncache(fin);
if (delimiter)
++rcsline;
*p = '\0';
for (p = buf+1; (c = *p++) == ' '; )
continue;
line1 = 0;
while (isdigit(c)) {
if (
LONG_MAX/10 < line1 ||
(t = line1 * 10, (line1 = t + (c - '0')) < t)
)
diffLineNumberTooLarge(buf);
c = *p++;
}
while (c == ' ')
c = *p++;
nlines = 0;
while (isdigit(c)) {
if (
LONG_MAX/10 < nlines ||
(t = nlines * 10, (nlines = t + (c - '0')) < t)
)
diffLineNumberTooLarge(buf);
c = *p++;
}
if (c == '\r')
c = *p++;
if (c || !nlines) {
badDiffOutput(buf);
}
if (line1+nlines < line1)
diffLineNumberTooLarge(buf);
switch (buf[0]) {
case 'a':
if (line1 < dc->adprev) {
rcsfaterror("backward insertion in diff output: %s", buf);
}
dc->adprev = line1 + 1;
break;
case 'd':
if (line1 < dc->adprev || line1 < dc->dafter) {
rcsfaterror("backward deletion in diff output: %s", buf);
}
dc->adprev = line1;
dc->dafter = line1 + nlines;
break;
default:
badDiffOutput(buf);
}
if (fout) {
aprintf(fout, "%s\n", buf);
}
dc->line1 = line1;
dc->nlines = nlines;
return buf[0] == 'a';
}
#ifdef SYNTEST
/* Input an RCS file and print its internal data structures. */
char const cmdid[] = "syntest";
int
main(argc,argv)
int argc; char * argv[];
{
if (argc<2) {
aputs("No input file\n",stderr);
exitmain(EXIT_FAILURE);
}
if (!(finptr = Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
faterror("can't open input file %s", argv[1]);
}
Lexinit();
getadmin();
fdlock = STDOUT_FILENO;
putadmin();
gettree();
getdesc(true);
nextlex();
if (!eoflex()) {
fatserror("expecting EOF");
}
exitmain(EXIT_SUCCESS);
}
void exiterr() { _exit(EXIT_FAILURE); }
#endif

View file

@ -0,0 +1,191 @@
/* Convert between RCS time format and Posix and/or C formats. */
/* Copyright 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#include "rcsbase.h"
#include "partime.h"
#include "maketime.h"
libId(rcstimeId, "$FreeBSD$")
static long zone_offset; /* seconds east of UTC, or TM_LOCAL_ZONE */
static int use_zone_offset; /* if zero, use UTC without zone indication */
/*
* Convert Unix time to RCS format.
* For compatibility with older versions of RCS,
* dates from 1900 through 1999 are stored without the leading "19".
*/
void
time2date(unixtime,date)
time_t unixtime;
char date[datesize];
{
register struct tm const *tm = time2tm(unixtime, RCSversion<VERSION(5));
VOID sprintf(date,
# if has_printf_dot
"%.2d.%.2d.%.2d.%.2d.%.2d.%.2d",
# else
"%02d.%02d.%02d.%02d.%02d.%02d",
# endif
tm->tm_year + ((unsigned)tm->tm_year < 100 ? 0 : 1900),
tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec
);
}
/* Like str2time, except die if an error was found. */
static time_t str2time_checked P((char const*,time_t,long));
static time_t
str2time_checked(source, default_time, default_zone)
char const *source;
time_t default_time;
long default_zone;
{
time_t t = str2time(source, default_time, default_zone);
if (t == -1)
faterror("unknown date/time: %s", source);
return t;
}
/*
* Parse a free-format date in SOURCE, convert it
* into RCS internal format, and store the result into TARGET.
*/
void
str2date(source, target)
char const *source;
char target[datesize];
{
time2date(
str2time_checked(source, now(),
use_zone_offset ? zone_offset
: RCSversion<VERSION(5) ? TM_LOCAL_ZONE
: 0
),
target
);
}
/* Convert an RCS internal format date to time_t. */
time_t
date2time(source)
char const source[datesize];
{
char s[datesize + zonelenmax];
return str2time_checked(date2str(source, s), (time_t)0, 0);
}
/* Set the time zone for date2str output. */
void
zone_set(s)
char const *s;
{
if ((use_zone_offset = *s)) {
long zone;
char const *zonetail = parzone(s, &zone);
if (!zonetail || *zonetail)
error("%s: not a known time zone", s);
else
zone_offset = zone;
}
}
/*
* Format a user-readable form of the RCS format DATE into the buffer DATEBUF.
* Yield DATEBUF.
*/
char const *
date2str(date, datebuf)
char const date[datesize];
char datebuf[datesize + zonelenmax];
{
register char const *p = date;
while (*p++ != '.')
continue;
if (!use_zone_offset)
VOID sprintf(datebuf,
"19%.*s/%.2s/%.2s %.2s:%.2s:%s"
+ (date[2]=='.' && VERSION(5)<=RCSversion ? 0 : 2),
(int)(p-date-1), date,
p, p+3, p+6, p+9, p+12
);
else {
struct tm t;
struct tm const *z;
int non_hour;
long zone;
char c;
t.tm_year = atoi(date) - (date[2]=='.' ? 0 : 1900);
t.tm_mon = atoi(p) - 1;
t.tm_mday = atoi(p+3);
t.tm_hour = atoi(p+6);
t.tm_min = atoi(p+9);
t.tm_sec = atoi(p+12);
t.tm_wday = -1;
zone = zone_offset;
if (zone == TM_LOCAL_ZONE) {
time_t u = tm2time(&t, 0), d;
z = localtime(&u);
d = difftm(z, &t);
zone = (time_t)-1 < 0 || d < -d ? d : -(long)-d;
} else {
adjzone(&t, zone);
z = &t;
}
c = '+';
if (zone < 0) {
zone = -zone;
c = '-';
}
VOID sprintf(datebuf,
# if has_printf_dot
"%.2d-%.2d-%.2d %.2d:%.2d:%.2d%c%.2d",
# else
"%02d-%02d-%02d %02d:%02d:%02d%c%02d",
# endif
z->tm_year + 1900,
z->tm_mon + 1, z->tm_mday, z->tm_hour, z->tm_min, z->tm_sec,
c, (int) (zone / (60*60))
);
if ((non_hour = zone % (60*60))) {
# if has_printf_dot
static char const fmt[] = ":%.2d";
# else
static char const fmt[] = ":%02d";
# endif
VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour / 60);
if ((non_hour %= 60))
VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour);
}
}
return datebuf;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
#include "rcsbase.h"
char const RCS_version_string[] = "5.7";

View file

@ -0,0 +1,8 @@
PROG= merge
SRCS= merge.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View file

@ -0,0 +1,137 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.TH MERGE 1 \*(Dt GNU
.SH NAME
merge \- three-way file merge
.SH SYNOPSIS
.B merge
[
.I "options"
]
.I "file1 file2 file3"
.SH DESCRIPTION
.B merge
incorporates all changes that lead from
.I file2
to
.I file3
into
.IR file1 .
The result ordinarily goes into
.IR file1 .
.B merge
is useful for combining separate changes to an original. Suppose
.I file2
is the original, and both
.I file1
and
.I file3
are modifications of
.IR file2 .
Then
.B merge
combines both changes.
.PP
A conflict occurs if both
.I file1
and
.I file3
have changes in a common segment of lines.
If a conflict is found,
.B merge
normally outputs a warning and brackets the conflict with
.B <<<<<<<
and
.B >>>>>>>
lines.
A typical conflict will look like this:
.LP
.RS
.nf
.BI <<<<<<< " file A"
.I "lines in file A"
.B "======="
.I "lines in file B"
.BI >>>>>>> " file B"
.RE
.fi
.LP
If there are conflicts, the user should edit the result and delete one of the
alternatives.
.SH OPTIONS
.TP
.B \-A
Output conflicts using the
.B \-A
style of
.BR diff3 (1),
if supported by
.BR diff3 .
This merges all changes leading from
.I file2
to
.I file3
into
.IR file1 ,
and generates the most verbose output.
.TP
\f3\-E\fP, \f3\-e\fP
These options specify conflict styles that generate less information
than
.BR \-A .
See
.BR diff3 (1)
for details.
The default is
.BR \-E .
With
.BR \-e ,
.B merge
does not warn about conflicts.
.TP
.BI \-L " label"
This option may be given up to three times, and specifies labels
to be used in place of the corresponding file names in conflict reports.
That is,
.B "merge\ \-L\ x\ \-L\ y\ \-L\ z\ a\ b\ c"
generates output that looks like it came from files
.BR x ,
.B y
and
.B z
instead of from files
.BR a ,
.B b
and
.BR c .
.TP
.BI \-p
Send results to standard output instead of overwriting
.IR file1 .
.TP
.BI \-q
Quiet; do not warn about conflicts.
.TP
.BI \-V
Print \*r's version number.
.SH DIAGNOSTICS
Exit status is 0 for no conflicts, 1 for some conflicts, 2 for trouble.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH SEE ALSO
diff3(1), diff(1), rcsmerge(1), co(1).
.SH BUGS
It normally does not make sense to merge binary files as if they were text, but
.B merge
tries to do it anyway.
.br

View file

@ -0,0 +1,113 @@
/* merge - three-way file merge */
/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#include "rcsbase.h"
static void badoption P((char const*));
static char const usage[] =
"\nmerge: usage: merge [-AeEpqxX3] [-L lab [-L lab [-L lab]]] file1 file2 file3";
static void
badoption(a)
char const *a;
{
error("unknown option: %s%s", a, usage);
}
mainProg(mergeId, "merge", "$FreeBSD$")
{
register char const *a;
char const *arg[3], *label[3], *edarg = 0;
int labels, tostdout;
labels = 0;
tostdout = false;
for (; (a = *++argv) && *a++ == '-'; --argc) {
switch (*a++) {
case 'A': case 'E': case 'e':
if (edarg && edarg[1] != (*argv)[1])
error("%s and %s are incompatible",
edarg, *argv
);
edarg = *argv;
break;
case 'p': tostdout = true; break;
case 'q': quietflag = true; break;
case 'L':
if (3 <= labels)
faterror("too many -L options");
if (!(label[labels++] = *++argv))
faterror("-L needs following argument");
--argc;
break;
case 'V':
printf("RCS version %s\n", RCS_version_string);
exitmain(0);
default:
badoption(a - 2);
continue;
}
if (*a)
badoption(a - 2);
}
if (argc != 4)
faterror("%s arguments%s",
argc<4 ? "not enough" : "too many", usage
);
/* This copy keeps us `const'-clean. */
arg[0] = argv[0];
arg[1] = argv[1];
arg[2] = argv[2];
for (; labels < 3; labels++)
label[labels] = arg[labels];
if (nerror)
exiterr();
exitmain(merge(tostdout, edarg, label, arg));
}
#if RCS_lint
# define exiterr mergeExit
#endif
void
exiterr()
{
tempunlink();
_exit(DIFF_TROUBLE);
}

View file

@ -0,0 +1,10 @@
# $FreeBSD$
PROG= rcs
MAN= rcs.1 rcsintro.1 rcsfile.5
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

454
gnu/usr.bin/rcs/rcs/rcs.1 Normal file
View file

@ -0,0 +1,454 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
.if !\n(.g \{\
. if !\w|\*(lq| \{\
. ds lq ``
. if \w'\(lq' .ds lq "\(lq
. \}
. if !\w|\*(rq| \{\
. ds rq ''
. if \w'\(rq' .ds rq "\(rq
. \}
.\}
.TH RCS 1 \*(Dt GNU
.SH NAME
rcs \- change RCS file attributes
.SH SYNOPSIS
.B rcs
.IR "options file " .\|.\|.
.SH DESCRIPTION
.B rcs
creates new \*r files or changes attributes of existing ones.
An \*r file contains multiple revisions of text,
an access list, a change log,
descriptive text,
and some control attributes.
For
.B rcs
to work, the caller's login name must be on the access list,
except if the access list is empty, the caller is the owner of the file
or the superuser, or
the
.B \-i
option is present.
.PP
Pathnames matching an \*r suffix denote \*r files;
all others denote working files.
Names are paired as explained in
.BR ci (1).
Revision numbers use the syntax described in
.BR ci (1).
.SH OPTIONS
.TP
.B \-i
Create and initialize a new \*r file, but do not deposit any revision.
If the \*r file has no path prefix, try to place it
first into the subdirectory
.BR ./RCS ,
and then into the current directory.
If the \*r file
already exists, print an error message.
.TP
.BI \-a "logins"
Append the login names appearing in the comma-separated list
.I logins
to the access list of the \*r file.
.TP
.BI \-A "oldfile"
Append the access list of
.I oldfile
to the access list of the \*r file.
.TP
.BR \-e [\f2logins\fP]
Erase the login names appearing in the comma-separated list
.I logins
from the access list of the \*r file.
If
.I logins
is omitted, erase the entire access list.
.TP
.BR \-b [\f2rev\fP]
Set the default branch to
.IR rev .
If
.I rev
is omitted, the default
branch is reset to the (dynamically) highest branch on the trunk.
.TP
.BI \-c string
Set the comment leader to
.IR string .
An initial
.BR ci ,
or an
.B "rcs\ \-i"
without
.BR \-c ,
guesses the comment leader from the suffix of the working filename.
.RS
.PP
This option is obsolescent, since \*r normally uses the preceding
.B $\&Log$
line's prefix when inserting log lines during checkout (see
.BR co (1)).
However, older versions of \*r use the comment leader instead of the
.B $\&Log$
line's prefix, so
if you plan to access a file with both old and new versions of \*r,
make sure its comment leader matches its
.B $\&Log$
line prefix.
.RE
.TP
.BI \-k subst
Set the default keyword substitution to
.IR subst .
The effect of keyword substitution is described in
.BR co (1).
Giving an explicit
.B \-k
option to
.BR co ,
.BR rcsdiff ,
and
.B rcsmerge
overrides this default.
Beware
.BR "rcs\ \-kv",
because
.B \-kv
is incompatible with
.BR "co\ \-l".
Use
.B "rcs\ \-kkv"
to restore the normal default keyword substitution.
.TP
.BR \-l [\f2rev\fP]
Lock the revision with number
.IR rev .
If a branch is given, lock the latest revision on that branch.
If
.I rev
is omitted, lock the latest revision on the default branch.
Locking prevents overlapping changes.
If someone else already holds the lock, the lock is broken as with
.B "rcs\ \-u"
(see below).
.TP
.BR \-u [\f2rev\fP]
Unlock the revision with number
.IR rev .
If a branch is given, unlock the latest revision on that branch.
If
.I rev
is omitted, remove the latest lock held by the caller.
Normally, only the locker of a revision can unlock it.
Somebody else unlocking a revision breaks the lock.
This causes a mail message to be sent to the original locker.
The message contains a commentary solicited from the breaker.
The commentary is terminated by end-of-file or by a line containing
.BR \&. "\ by"
itself.
.TP
.B \-L
Set locking to
.IR strict .
Strict locking means that the owner
of an \*r file is not exempt from locking for checkin.
This option should be used for files that are shared.
.TP
.B \-U
Set locking to non-strict. Non-strict locking means that the owner of
a file need not lock a revision for checkin.
This option should
.I not
be used for files that are shared.
Whether default locking is strict is determined by your system administrator,
but it is normally strict.
.TP
\f3\-m\fP\f2rev\fP\f3:\fP\f2msg\fP
Replace revision
.IR rev 's
log message with
.IR msg .
.TP
.B \-M
Do not send mail when breaking somebody else's lock.
This option is not meant for casual use;
it is meant for programs that warn users by other means, and invoke
.B "rcs\ \-u"
only as a low-level lock-breaking operation.
.TP
\f3\-n\fP\f2name\fP[\f3:\fP[\f2rev\fP]]
Associate the symbolic name
.I name
with the branch or
revision
.IR rev .
Delete the symbolic name if both
.B :
and
.I rev
are omitted; otherwise, print an error message if
.I name
is already associated with
another number.
If
.I rev
is symbolic, it is expanded before association.
A
.I rev
consisting of a branch number followed by a
.B .\&
stands for the current latest revision in the branch.
A
.B :
with an empty
.I rev
stands for the current latest revision on the default branch,
normally the trunk.
For example,
.BI "rcs\ \-n" name ":\ RCS/*"
associates
.I name
with the current latest revision of all the named \*r files;
this contrasts with
.BI "rcs\ \-n" name ":$\ RCS/*"
which associates
.I name
with the revision numbers extracted from keyword strings
in the corresponding working files.
.TP
\f3\-N\fP\f2name\fP[\f3:\fP[\f2rev\fP]]
Act like
.BR \-n ,
except override any previous assignment of
.IR name .
.TP
.BI \-o range
deletes (\*(lqoutdates\*(rq) the revisions given by
.IR range .
A range consisting of a single revision number means that revision.
A range consisting of a branch number means the latest revision on that
branch.
A range of the form
.IB rev1 : rev2
means
revisions
.I rev1
to
.I rev2
on the same branch,
.BI : rev
means from the beginning of the branch containing
.I rev
up to and including
.IR rev ,
and
.IB rev :
means
from revision
.I rev
to the end of the branch containing
.IR rev .
None of the outdated revisions can have branches or locks.
.TP
.B \-q
Run quietly; do not print diagnostics.
.TP
.B \-I
Run interactively, even if the standard input is not a terminal.
.TP
.B \-s\f2state\fP\f1[\fP:\f2rev\fP\f1]\fP
Set the state attribute of the revision
.I rev
to
.IR state .
If
.I rev
is a branch number, assume the latest revision on that branch.
If
.I rev
is omitted, assume the latest revision on the default branch.
Any identifier is acceptable for
.IR state .
A useful set of states
is
.B Exp
(for experimental),
.B Stab
(for stable), and
.B Rel
(for
released).
By default,
.BR ci (1)
sets the state of a revision to
.BR Exp .
.TP
.BR \-t [\f2file\fP]
Write descriptive text from the contents of the named
.I file
into the \*r file, deleting the existing text.
The
.IR file
pathname cannot begin with
.BR \- .
If
.I file
is omitted, obtain the text from standard input,
terminated by end-of-file or by a line containing
.BR \&. "\ by"
itself.
Prompt for the text if interaction is possible; see
.BR \-I .
With
.BR \-i ,
descriptive text is obtained
even if
.B \-t
is not given.
.TP
.BI \-t\- string
Write descriptive text from the
.I string
into the \*r file, deleting the existing text.
.TP
.B \-T
Preserve the modification time on the \*r file
unless a revision is removed.
This option can suppress extensive recompilation caused by a
.BR make (1)
dependency of some copy of the working file on the \*r file.
Use this option with care; it can suppress recompilation even when it is needed,
i.e. when a change to the \*r file
would mean a change to keyword strings in the working file.
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.IR n .
See
.BR co (1)
for details.
.TP
.BI \-x "suffixes"
Use
.I suffixes
to characterize \*r files.
See
.BR ci (1)
for details.
.TP
.BI \-z zone
Use
.I zone
as the default time zone.
This option has no effect;
it is present for compatibility with other \*r commands.
.PP
At least one explicit option must be given,
to ensure compatibility with future planned extensions
to the
.B rcs
command.
.SH COMPATIBILITY
The
.BI \-b rev
option generates an \*r file that cannot be parsed by \*r version 3 or earlier.
.PP
The
.BI \-k subst
options (except
.BR \-kkv )
generate an \*r file that cannot be parsed by \*r version 4 or earlier.
.PP
Use
.BI "rcs \-V" n
to make an \*r file acceptable to \*r version
.I n
by discarding information that would confuse version
.IR n .
.PP
\*r version 5.5 and earlier does not support the
.B \-x
option, and requires a
.B ,v
suffix on an \*r pathname.
.SH FILES
.B rcs
accesses files much as
.BR ci (1)
does,
except that it uses the effective user for all accesses,
it does not write the working file or its directory,
and it does not even read the working file unless a revision number of
.B $
is specified.
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
See
.BR ci (1)
for details.
.SH DIAGNOSTICS
The \*r pathname and the revisions outdated are written to
the diagnostic output.
The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
rcsintro(1), co(1), ci(1), ident(1), rcsclean(1), rcsdiff(1),
rcsmerge(1), rlog(1), rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.SH BUGS
A catastrophe (e.g. a system crash) can cause \*r to leave behind
a semaphore file that causes later invocations of \*r to claim
that the \*r file is in use.
To fix this, remove the semaphore file.
A semaphore file's name typically begins with
.B ,
or ends with
.BR _ .
.PP
The separator for revision ranges in the
.B \-o
option used to be
.B \-
instead of
.BR : ,
but this leads to confusion when symbolic names contain
.BR \- .
For backwards compatibility
.B "rcs \-o"
still supports the old
.B \-
separator, but it warns about this obsolete use.
.PP
Symbolic names need not refer to existing revisions or branches.
For example, the
.B \-o
option does not remove symbolic names for the outdated revisions; you must use
.B \-n
to remove the names.
.br

1629
gnu/usr.bin/rcs/rcs/rcs.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,425 @@
.lf 1 ./rcsfile.5in
.\" Set p to 1 if your formatter can handle pic output.
.if t .nr p 1
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
.TH RCSFILE 5 \*(Dt GNU
.SH NAME
rcsfile \- format of RCS file
.SH DESCRIPTION
An \*r file's
contents are described by the grammar
below.
.PP
The text is free format: space, backspace, tab, newline, vertical
tab, form feed, and carriage return (collectively,
.IR "white space")
have no significance except in strings.
However, white space cannot appear within an id, num, or sym,
and an \*r file must end with a newline.
.PP
Strings are enclosed by
.BR @ .
If a string contains a
.BR @ ,
it must be doubled;
otherwise, strings can contain arbitrary binary data.
.PP
The meta syntax uses the following conventions: `|' (bar) separates
alternatives; `{' and `}' enclose optional phrases; `{' and `}*' enclose
phrases that can be repeated zero or more times;
`{' and '}+' enclose phrases that must appear at least once and can be
repeated;
Terminal symbols are in
.BR boldface ;
nonterminal symbols are in
.IR italics .
.LP
.nr w \w'\f3deltatext\fP '
.nr y \w'\f3newphrase\fP '
.if \nw<\ny .nr w \ny
.nr x \w'\f3branches\fP'
.nr y \w'{ \f3comment\fP'
.if \nx<\ny .nr x \ny
.nr y \w'\f3{ branch\fP'
.if \nx<\ny .nr x \ny
.ta \nwu +\w'::= 'u +\nxu+\w' 'u
.fc #
.nf
\f2rcstext\fP ::= \f2admin\fP {\f2delta\fP}* \f2desc\fP {\f2deltatext\fP}*
.LP
\f2admin\fP ::= \f3head\fP {\f2num\fP}\f3;\fP
{ \f3branch\fP {\f2num\fP}\f3;\fP }
\f3access\fP {\f2id\fP}*\f3;\fP
\f3symbols\fP {\f2sym\fP \f3:\fP \f2num\fP}*\f3;\fP
\f3locks\fP {\f2id\fP \f3:\fP \f2num\fP}*\f3;\fP {\f3strict ;\fP}
{ \f3comment\fP {\f2string\fP}\f3;\fP }
{ \f3expand\fP {\f2string\fP}\f3;\fP }
{ \f2newphrase\fP }*
.LP
\f2delta\fP ::= \f2num\fP
\f3date\fP \f2num\fP\f3;\fP
\f3author\fP \f2id\fP\f3;\fP
\f3state\fP {\f2id\fP}\f3;\fP
\f3branches\fP {\f2num\fP}*\f3;\fP
\f3next\fP {\f2num\fP}\f3;\fP
{ \f2newphrase\fP }*
.LP
\f2desc\fP ::= \f3desc\fP \f2string\fP
.LP
\f2deltatext\fP ::= \f2num\fP
\f3log\fP \f2string\fP
{ \f2newphrase\fP }*
\f3text\fP \f2string\fP
.LP
\f2num\fP ::= {\f2digit\fP | \f3.\fP}+
.LP
\f2digit\fP ::= \f30\fP | \f31\fP | \f32\fP | \f33\fP | \f34\fP | \f35\fP | \f36\fP | \f37\fP | \f38\fP | \f39\fP
.LP
\f2id\fP ::= {\f2num\fP} \f2idchar\fP {\f2idchar\fP | \f2num\fP}*
.LP
\f2sym\fP ::= {\f2digit\fP}* \f2idchar\fP {\f2idchar\fP | \f2digit\fP}*
.LP
\f2idchar\fP ::= any visible graphic character except \f2special\fP
.LP
\f2special\fP ::= \f3$\fP | \f3,\fP | \f3.\fP | \f3:\fP | \f3;\fP | \f3@\fP
.LP
\f2string\fP ::= \f3@\fP{any character, with \f3@\fP doubled}*\f3@\fP
.LP
\f2newphrase\fP ::= \f2id\fP \f2word\fP* \f3;\fP
.LP
\f2word\fP ::= \f2id\fP | \f2num\fP | \f2string\fP | \f3:\fP
.fi
.PP
Identifiers are case sensitive. Keywords are in lower case only.
The sets of keywords and identifiers can overlap.
In most environments \*r uses the \s-1ISO\s0 8859/1 encoding:
visible graphic characters are codes 041\-176 and 240\-377,
and white space characters are codes 010\-015 and 040.
.PP
Dates, which appear after the
.B date
keyword, are of the form
\f2Y\fP\f3.\fP\f2mm\fP\f3.\fP\f2dd\fP\f3.\fP\f2hh\fP\f3.\fP\f2mm\fP\f3.\fP\f2ss\fP,
where
.I Y
is the year,
.I mm
the month (01\-12),
.I dd
the day (01\-31),
.I hh
the hour (00\-23),
.I mm
the minute (00\-59),
and
.I ss
the second (00\-60).
.I Y
contains just the last two digits of the year
for years from 1900 through 1999,
and all the digits of years thereafter.
Dates use the Gregorian calendar; times use UTC.
.PP
The
.I newphrase
productions in the grammar are reserved for future extensions
to the format of \*r files.
No
.I newphrase
will begin with any keyword already in use.
.PP
The
.I delta
nodes form a tree. All nodes whose numbers
consist of a single pair
(e.g., 2.3, 2.1, 1.3, etc.)
are on the trunk, and are linked through the
.B next
field in order of decreasing numbers.
The
.B head
field in the
.I admin
node points to the head of that sequence (i.e., contains
the highest pair).
The
.B branch
node in the admin node indicates the default
branch (or revision) for most \*r operations.
If empty, the default
branch is the highest branch on the trunk.
.PP
All
.I delta
nodes whose numbers consist of
.RI 2 n
fields
.RI ( n \(>=2)
(e.g., 3.1.1.1, 2.1.2.2, etc.)
are linked as follows.
All nodes whose first
.RI 2 n \-1
number fields are identical are linked through the
.B next
field in order of increasing numbers.
For each such sequence,
the
.I delta
node whose number is identical to the first
.RI 2 n \-2
number fields of the deltas on that sequence is called the branchpoint.
The
.B branches
field of a node contains a list of the
numbers of the first nodes of all sequences for which it is a branchpoint.
This list is ordered in increasing numbers.
.LP
The following diagram shows an example of an \*r file's organization.
.if !\np \{\
.nf
.vs 12
.ne 36
.cs 1 20
.eo
Head
|
|
v / \
--------- / \
/ \ / \ | | / \ / \
/ \ / \ | 2.1 | / \ / \
/ \ / \ | | / \ / \
/1.2.1.3\ /1.3.1.1\ | | /1.2.2.2\ /1.2.2.1.1.1\
--------- --------- --------- --------- -------------
^ ^ | ^ ^
| | | | |
| | v | |
/ \ | --------- / \ |
/ \ | \ 1.3 / / \ |
/ \ ---------\ / / \-----------
/1.2.1.1\ \ / /1.2.2.1\
--------- \ / ---------
^ | ^
| | |
| v |
| --------- |
| \ 1.2 / |
----------------------\ /---------
\ /
\ /
|
|
v
---------
\ 1.1 /
\ /
\ /
\ /
.ec
.cs 1
.vs
.fi
.\}
.if \np \{\
.lf 232
.PS 4.250i 3.812i
.\" -2.0625 -4.25 1.75 0
.\" 0.000i 4.250i 3.812i 0.000i
.nr 00 \n(.u
.nf
.nr 0x 1
\h'3.812i'
.sp -1
.lf 242
\h'2.062i-(\w'Head'u/2u)'\v'0.125i-(0v/2u)+0v+0.22m'Head
.sp -1
\h'2.062i'\v'0.250i'\D'l0.000i 0.500i'
.sp -1
\h'2.087i'\v'0.650i'\D'l-0.025i 0.100i'
.sp -1
\h'2.062i'\v'0.750i'\D'l-0.025i -0.100i'
.sp -1
\h'1.688i'\v'1.250i'\D'l0.750i 0.000i'
.sp -1
\h'2.438i'\v'1.250i'\D'l0.000i -0.500i'
.sp -1
\h'2.438i'\v'0.750i'\D'l-0.750i 0.000i'
.sp -1
\h'1.688i'\v'0.750i'\D'l0.000i 0.500i'
.sp -1
.lf 244
\h'2.062i-(\w'2.1'u/2u)'\v'1.000i-(0v/2u)+0v+0.22m'2.1
.sp -1
\h'2.062i'\v'1.250i'\D'l0.000i 0.500i'
.sp -1
\h'2.087i'\v'1.650i'\D'l-0.025i 0.100i'
.sp -1
\h'2.062i'\v'1.750i'\D'l-0.025i -0.100i'
.sp -1
.lf 246
\h'2.062i-(\w'1.3'u/2u)'\v'2.000i-(1v/2u)+0v+0.22m'1.3
.sp -1
\h'2.062i'\v'2.250i'\D'l-0.375i -0.500i'
.sp -1
\h'1.688i'\v'1.750i'\D'l0.750i 0.000i'
.sp -1
\h'2.438i'\v'1.750i'\D'l-0.375i 0.500i'
.sp -1
\h'1.875i'\v'2.000i'\D'~-0.500i 0.000i 0.000i -0.500i'
.sp -1
\h'1.350i'\v'1.600i'\D'l0.025i -0.100i'
.sp -1
\h'1.375i'\v'1.500i'\D'l0.025i 0.100i'
.sp -1
.lf 249
\h'1.375i-(\w'1.3.1.1'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.3.1.1
.sp -1
\h'1.375i'\v'1.000i'\D'l-0.375i 0.500i'
.sp -1
\h'1.000i'\v'1.500i'\D'l0.750i 0.000i'
.sp -1
\h'1.750i'\v'1.500i'\D'l-0.375i -0.500i'
.sp -1
\h'2.062i'\v'2.250i'\D'l0.000i 0.500i'
.sp -1
\h'2.087i'\v'2.650i'\D'l-0.025i 0.100i'
.sp -1
\h'2.062i'\v'2.750i'\D'l-0.025i -0.100i'
.sp -1
.lf 252
\h'2.062i-(\w'1.2'u/2u)'\v'3.000i-(1v/2u)+0v+0.22m'1.2
.sp -1
\h'2.062i'\v'3.250i'\D'l-0.375i -0.500i'
.sp -1
\h'1.688i'\v'2.750i'\D'l0.750i 0.000i'
.sp -1
\h'2.438i'\v'2.750i'\D'l-0.375i 0.500i'
.sp -1
\h'1.875i'\v'3.000i'\D'~-0.500i 0.000i -0.500i 0.000i -0.500i 0.000i 0.000i -0.500i'
.sp -1
\h'0.350i'\v'2.600i'\D'l0.025i -0.100i'
.sp -1
\h'0.375i'\v'2.500i'\D'l0.025i 0.100i'
.sp -1
.lf 255
\h'0.375i-(\w'1.2.1.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.1.1
.sp -1
\h'0.375i'\v'2.000i'\D'l-0.375i 0.500i'
.sp -1
\h'0.000i'\v'2.500i'\D'l0.750i 0.000i'
.sp -1
\h'0.750i'\v'2.500i'\D'l-0.375i -0.500i'
.sp -1
\h'0.375i'\v'2.000i'\D'l0.000i -0.500i'
.sp -1
\h'0.350i'\v'1.600i'\D'l0.025i -0.100i'
.sp -1
\h'0.375i'\v'1.500i'\D'l0.025i 0.100i'
.sp -1
.lf 257
\h'0.375i-(\w'1.2.1.3'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.1.3
.sp -1
\h'0.375i'\v'1.000i'\D'l-0.375i 0.500i'
.sp -1
\h'0.000i'\v'1.500i'\D'l0.750i 0.000i'
.sp -1
\h'0.750i'\v'1.500i'\D'l-0.375i -0.500i'
.sp -1
\h'2.250i'\v'3.000i'\D'~0.500i 0.000i 0.000i -0.500i'
.sp -1
\h'2.725i'\v'2.600i'\D'l0.025i -0.100i'
.sp -1
\h'2.750i'\v'2.500i'\D'l0.025i 0.100i'
.sp -1
.lf 261
\h'2.750i-(\w'1.2.2.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.2.1
.sp -1
\h'2.750i'\v'2.000i'\D'l-0.375i 0.500i'
.sp -1
\h'2.375i'\v'2.500i'\D'l0.750i 0.000i'
.sp -1
\h'3.125i'\v'2.500i'\D'l-0.375i -0.500i'
.sp -1
\h'2.938i'\v'2.250i'\D'~0.500i 0.000i 0.000i -0.500i 0.000i -0.500i'
.sp -1
\h'3.413i'\v'1.350i'\D'l0.025i -0.100i'
.sp -1
\h'3.438i'\v'1.250i'\D'l0.025i 0.100i'
.sp -1
.lf 264
\h'3.438i-(\w'\s-21.2.2.1.1.1\s0'u/2u)'\v'1.000i-(1v/2u)+1v+0.22m'\s-21.2.2.1.1.1\s0
.sp -1
\h'3.438i'\v'0.750i'\D'l-0.375i 0.500i'
.sp -1
\h'3.062i'\v'1.250i'\D'l0.750i 0.000i'
.sp -1
\h'3.812i'\v'1.250i'\D'l-0.375i -0.500i'
.sp -1
\h'2.750i'\v'2.000i'\D'l0.000i -0.500i'
.sp -1
\h'2.725i'\v'1.600i'\D'l0.025i -0.100i'
.sp -1
\h'2.750i'\v'1.500i'\D'l0.025i 0.100i'
.sp -1
.lf 267
\h'2.750i-(\w'1.2.2.2'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.2.2
.sp -1
\h'2.750i'\v'1.000i'\D'l-0.375i 0.500i'
.sp -1
\h'2.375i'\v'1.500i'\D'l0.750i 0.000i'
.sp -1
\h'3.125i'\v'1.500i'\D'l-0.375i -0.500i'
.sp -1
\h'2.062i'\v'3.250i'\D'l0.000i 0.500i'
.sp -1
\h'2.087i'\v'3.650i'\D'l-0.025i 0.100i'
.sp -1
\h'2.062i'\v'3.750i'\D'l-0.025i -0.100i'
.sp -1
.lf 270
\h'2.062i-(\w'1.1'u/2u)'\v'4.000i-(1v/2u)+0v+0.22m'1.1
.sp -1
\h'2.062i'\v'4.250i'\D'l-0.375i -0.500i'
.sp -1
\h'1.688i'\v'3.750i'\D'l0.750i 0.000i'
.sp -1
\h'2.438i'\v'3.750i'\D'l-0.375i 0.500i'
.sp -1
.sp 4.250i+1
.if \n(00 .fi
.br
.nr 0x 0
.lf 271
.PE
.lf 272
.\}
.SH IDENTIFICATION
.de VL
\\$2
..
Author: Walter F. Tichy,
Purdue University, West Lafayette, IN, 47907.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH SEE ALSO
rcsintro(1), ci(1), co(1), ident(1), rcs(1), rcsclean(1), rcsdiff(1),
rcsmerge(1), rlog(1)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.

View file

@ -0,0 +1,302 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
.if !\n(.g \{\
. if !\w|\*(lq| \{\
. ds lq ``
. if \w'\(lq' .ds lq "\(lq
. \}
. if !\w|\*(rq| \{\
. ds rq ''
. if \w'\(rq' .ds rq "\(rq
. \}
.\}
.am SS
.LP
..
.TH RCSINTRO 1 \*(Dt GNU
.SH NAME
rcsintro \- introduction to RCS commands
.SH DESCRIPTION
The Revision Control System (\*r) manages multiple revisions of files.
\*r automates the storing, retrieval, logging, identification, and merging
of revisions. \*r is useful for text that is revised frequently, for example
programs, documentation, graphics, papers, and form letters.
.PP
The basic user interface is extremely simple. The novice only needs
to learn two commands:
.BR ci (1)
and
.BR co (1).
.BR ci ,
short for \*(lqcheck in\*(rq, deposits the contents of a
file into an archival file called an \*r file. An \*r file
contains all revisions of a particular file.
.BR co ,
short for \*(lqcheck out\*(rq, retrieves revisions from an \*r file.
.SS "Functions of \*r"
.IP \(bu
Store and retrieve multiple revisions of text. \*r saves all old
revisions in a space efficient way.
Changes no longer destroy the original, because the
previous revisions remain accessible. Revisions can be retrieved according to
ranges of revision numbers, symbolic names, dates, authors, and
states.
.IP \(bu
Maintain a complete history of changes.
\*r logs all changes automatically.
Besides the text of each revision, \*r stores the author, the date and time of
check-in, and a log message summarizing the change.
The logging makes it easy to find out
what happened to a module, without having to compare
source listings or having to track down colleagues.
.IP \(bu
Resolve access conflicts. When two or more programmers wish to
modify the same revision, \*r alerts the programmers and prevents one
modification from corrupting the other.
.IP \(bu
Maintain a tree of revisions. \*r can maintain separate lines of development
for each module. It stores a tree structure that represents the
ancestral relationships among revisions.
.IP \(bu
Merge revisions and resolve conflicts.
Two separate lines of development of a module can be coalesced by merging.
If the revisions to be merged affect the same sections of code, \*r alerts the
user about the overlapping changes.
.IP \(bu
Control releases and configurations.
Revisions can be assigned symbolic names
and marked as released, stable, experimental, etc.
With these facilities, configurations of modules can be
described simply and directly.
.IP \(bu
Automatically identify each revision with name, revision number,
creation time, author, etc.
The identification is like a stamp that can be embedded at an appropriate place
in the text of a revision.
The identification makes it simple to determine which
revisions of which modules make up a given configuration.
.IP \(bu
Minimize secondary storage. \*r needs little extra space for
the revisions (only the differences). If intermediate revisions are
deleted, the corresponding deltas are compressed accordingly.
.SS "Getting Started with \*r"
Suppose you have a file
.B f.c
that you wish to put under control of \*r.
If you have not already done so, make an \*r directory with the command
.IP
.B "mkdir RCS"
.LP
Then invoke the check-in command
.IP
.B "ci f.c"
.LP
This command creates an \*r file in the
.B RCS
directory,
stores
.B f.c
into it as revision 1.1, and
deletes
.BR f.c .
It also asks you for a description. The description
should be a synopsis of the contents of the file. All later check-in
commands will ask you for a log entry, which should summarize the
changes that you made.
.PP
Files in the \*r directory are called \*r files;
the others are called working files.
To get back the working file
.B f.c
in the previous example, use the check-out
command
.IP
.B "co f.c"
.LP
This command extracts the latest revision from the \*r file
and writes
it into
.BR f.c .
If you want to edit
.BR f.c ,
you must lock it as you check it out with the command
.IP
.B "co \-l f.c"
.LP
You can now edit
.BR f.c .
.PP
Suppose after some editing you want to know what changes that you have made.
The command
.IP
.B "rcsdiff f.c"
.LP
tells you the difference between the most recently checked-in version
and the working file.
You can check the file back in by invoking
.IP
.B "ci f.c"
.LP
This increments the revision number properly.
.PP
If
.B ci
complains with the message
.IP
.BI "ci error: no lock set by " "your name"
.LP
then you have tried to check in a file even though you did not
lock it when you checked it out.
Of course, it is too late now to do the check-out with locking, because
another check-out would
overwrite your modifications. Instead, invoke
.IP
.B "rcs \-l f.c"
.LP
This command will lock the latest revision for you, unless somebody
else got ahead of you already. In this case, you'll have to negotiate with
that person.
.PP
Locking assures that you, and only you, can check in the next update, and
avoids nasty problems if several people work on the same file.
Even if a revision is locked, it can still be checked out for
reading, compiling, etc. All that locking
prevents is a
.I "check-in"
by anybody but the locker.
.PP
If your \*r file is private, i.e., if you are the only person who is going
to deposit revisions into it, strict locking is not needed and you
can turn it off.
If strict locking is turned off,
the owner of the \*r file need not have a lock for check-in; all others
still do. Turning strict locking off and on is done with the commands
.IP
.BR "rcs \-U f.c" " and " "rcs \-L f.c"
.LP
If you don't want to clutter your working directory with \*r files, create
a subdirectory called
.B RCS
in your working directory, and move all your \*r
files there. \*r commands will look first into that directory to find
needed files. All the commands discussed above will still work, without any
modification.
(Actually, pairs of \*r and working files can be specified in three ways:
(a) both are given, (b) only the working file is given, (c) only the
\*r file is given. Both \*r and working files may have arbitrary path prefixes;
\*r commands pair them up intelligently.)
.PP
To avoid the deletion of the working file during check-in (in case you want to
continue editing or compiling), invoke
.IP
.BR "ci \-l f.c" " or " "ci \-u f.c"
.LP
These commands check in
.B f.c
as usual, but perform an implicit
check-out. The first form also locks the checked in revision, the second one
doesn't. Thus, these options save you one check-out operation.
The first form is useful if you want to continue editing,
the second one if you just want to read the file.
Both update the identification markers in your working file (see below).
.PP
You can give
.B ci
the number you want assigned to a checked in
revision. Assume all your revisions were numbered 1.1, 1.2, 1.3, etc.,
and you would like to start release 2.
The command
.IP
.BR "ci \-r2 f.c" " or " "ci \-r2.1 f.c"
.LP
assigns the number 2.1 to the new revision.
From then on,
.B ci
will number the subsequent revisions
with 2.2, 2.3, etc. The corresponding
.B co
commands
.IP
.BR "co \-r2 f.c" " and " "co \-r2.1 f.c"
.PP
retrieve the latest revision numbered
.RI 2. x
and the revision 2.1,
respectively.
.B co
without a revision number selects
the latest revision on the
.IR trunk ,
i.e. the highest
revision with a number consisting of two fields. Numbers with more than two
fields are needed for branches.
For example, to start a branch at revision 1.3, invoke
.IP
.B "ci \-r1.3.1 f.c"
.LP
This command starts a branch numbered 1 at revision 1.3, and assigns
the number 1.3.1.1 to the new revision. For more information about
branches, see
.BR rcsfile (5).
.SS "Automatic Identification"
\*r can put special strings for identification into your source and object
code. To obtain such identification, place the marker
.IP
.B "$\&Id$"
.LP
into your text, for instance inside a comment.
\*r will replace this marker with a string of the form
.IP
.BI $\&Id: " filename revision date time author state " $
.LP
With such a marker on the first page of each module, you can
always see with which revision you are working.
\*r keeps the markers up to date automatically.
To propagate the markers into your object code, simply put
them into literal character strings. In C, this is done as follows:
.IP
.ft 3
static char rcsid[] = \&"$\&Id$\&";
.ft
.LP
The command
.B ident
extracts such markers from any file, even object code
and dumps.
Thus,
.B ident
lets you find out
which revisions of which modules were used in a given program.
.PP
You may also find it useful to put the marker
.B $\&Log$
into your text, inside a comment. This marker accumulates
the log messages that are requested during check-in.
Thus, you can maintain the complete history of your file directly inside it.
There are several additional identification markers; see
.BR co (1)
for
details.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.br

View file

@ -0,0 +1,8 @@
PROG= rcsclean
SRCS= rcsclean.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View file

@ -0,0 +1,203 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
.TH RCSCLEAN 1 \*(Dt GNU
.SH NAME
rcsclean \- clean up working files
.SH SYNOPSIS
.B rcsclean
.RI [ options "] [ " file " .\|.\|. ]"
.SH DESCRIPTION
.B rcsclean
removes files that are not being worked on.
.B "rcsclean \-u"
also unlocks and removes files that are being worked on
but have not changed.
.PP
For each
.I file
given,
.B rcsclean
compares the working file and a revision in the corresponding
\*r file. If it finds a difference, it does nothing.
Otherwise, it first unlocks the revision if the
.B \-u
option is given,
and then removes the working file
unless the working file is writable and the revision is locked.
It logs its actions by outputting the corresponding
.B "rcs \-u"
and
.B "rm \-f"
commands on the standard output.
.PP
Files are paired as explained in
.BR ci (1).
If no
.I file
is given, all working files in the current directory are cleaned.
Pathnames matching an \*r suffix denote \*r files;
all others denote working files.
.PP
The number of the revision to which the working file is compared
may be attached to any of the options
.BR \-n ,
.BR \-q ,
.BR \-r ,
or
.BR \-u .
If no revision number is specified, then if the
.B \-u
option is given and the caller has one revision locked,
.B rcsclean
uses that revision; otherwise
.B rcsclean
uses the latest revision on the default branch, normally the root.
.PP
.B rcsclean
is useful for
.B clean
targets in makefiles.
See also
.BR rcsdiff (1),
which prints out the differences,
and
.BR ci (1),
which
normally reverts to the previous revision
if a file was not changed.
.SH OPTIONS
.TP
.BI \-k subst
Use
.I subst
style keyword substitution when retrieving the revision for comparison.
See
.BR co (1)
for details.
.TP
.BR \-n [\f2rev\fP]
Do not actually remove any files or unlock any revisions.
Using this option will tell you what
.B rcsclean
would do without actually doing it.
.TP
.BR \-q [\f2rev\fP]
Do not log the actions taken on standard output.
.TP
.BR \-r [\f2rev\fP]
This option has no effect other than specifying the revision for comparison.
.TP
.B \-T
Preserve the modification time on the \*r file
even if the \*r file changes because a lock is removed.
This option can suppress extensive recompilation caused by a
.BR make (1)
dependency of some other copy of the working file on the \*r file.
Use this option with care; it can suppress recompilation even when it is needed,
i.e. when the lock removal
would mean a change to keyword strings in the other working file.
.TP
.BR \-u [\f2rev\fP]
Unlock the revision if it is locked and no difference is found.
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.IR n .
See
.BR co (1)
for details.
.TP
.BI \-x "suffixes"
Use
.I suffixes
to characterize \*r files.
See
.BR ci (1)
for details.
.TP
.BI \-z zone
Use
.I zone
as the time zone for keyword substitution;
see
.BR co (1)
for details.
.SH EXAMPLES
.LP
.RS
.ft 3
rcsclean *.c *.h
.ft
.RE
.LP
removes all working files ending in
.B .c
or
.B .h
that were not changed
since their checkout.
.LP
.RS
.ft 3
rcsclean
.ft
.RE
.LP
removes all working files in the current directory
that were not changed since their checkout.
.SH FILES
.B rcsclean
accesses files much as
.BR ci (1)
does.
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
A backslash escapes spaces within an option.
The
.B \s-1RCSINIT\s0
options are prepended to the argument lists of most \*r commands.
Useful
.B \s-1RCSINIT\s0
options include
.BR \-q ,
.BR \-V ,
.BR \-x ,
and
.BR \-z .
.SH DIAGNOSTICS
The exit status is zero if and only if all operations were successful.
Missing working files and \*r files are silently ignored.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.SH BUGS
At least one
.I file
must be given in older Unix versions that
do not provide the needed directory scanning operations.
.br

View file

@ -0,0 +1,333 @@
/* Clean up working files. */
/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
#include "rcsbase.h"
#if has_dirent
static int get_directory P((char const*,char***));
#endif
static int unlock P((struct hshentry *));
static void cleanup P((void));
static RILE *workptr;
static int exitstatus;
mainProg(rcscleanId, "rcsclean", "$FreeBSD$")
{
static char const usage[] =
"\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
static struct buf revision;
char *a, **newargv;
char const *rev, *p;
int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
int Ttimeflag;
struct hshentries *deltas;
struct hshentry *delta;
struct stat workstat;
setrid();
expmode = -1;
rev = 0;
suffixes = X_DEFAULT;
perform = true;
unlockflag = false;
Ttimeflag = false;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
for (;;) {
if (--argc < 1) {
# if has_dirent
argc = get_directory(".", &newargv);
argv = newargv;
break;
# else
faterror("no pathnames specified");
# endif
}
a = *++argv;
if (!*a || *a++ != '-')
break;
switch (*a++) {
case 'k':
if (0 <= expmode)
redefined('k');
if ((expmode = str2expmode(a)) < 0)
goto unknown;
break;
case 'n':
perform = false;
goto handle_revision;
case 'q':
quietflag = true;
/* fall into */
case 'r':
handle_revision:
if (*a) {
if (rev)
warn("redefinition of revision number");
rev = a;
}
break;
case 'T':
if (*a)
goto unknown;
Ttimeflag = true;
break;
case 'u':
unlockflag = true;
goto handle_revision;
case 'V':
setRCSversion(*argv);
break;
case 'x':
suffixes = a;
break;
case 'z':
zone_set(a);
break;
default:
unknown:
error("unknown option: %s%s", *argv, usage);
}
}
dounlock = perform & unlockflag;
if (nerror)
cleanup();
else
for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
if (!(
0 < pairnames(
argc, argv,
dounlock ? rcswriteopen : rcsreadopen,
true, true
) &&
(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
))
continue;
if (same_file(RCSstat, workstat, 0)) {
rcserror("RCS file is the same as working file %s.",
workname
);
continue;
}
gettree();
p = 0;
if (rev) {
if (!fexpandsym(rev, &revision, workptr))
continue;
p = revision.string;
} else if (Head)
switch (unlockflag ? findlock(false,&delta) : 0) {
default:
continue;
case 0:
p = Dbranch ? Dbranch : "";
break;
case 1:
p = delta->num;
break;
}
delta = 0;
deltas = 0; /* Keep lint happy. */
if (p && !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
continue;
waslocked = delta && delta->lockedby;
locker_expansion = unlock(delta);
unlocked = locker_expansion & unlockflag;
if (unlocked<waslocked && workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
continue;
if (unlocked && !checkaccesslist())
continue;
if (dorewrite(dounlock, unlocked) != 0)
continue;
if (0 <= expmode)
Expand = expmode;
else if (
waslocked &&
Expand == KEYVAL_EXPAND &&
WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
)
Expand = KEYVALLOCK_EXPAND;
getdesc(false);
if (
!delta ? workstat.st_size!=0 :
0 < rcsfcmp(
workptr, &workstat,
buildrevision(deltas, delta, (FILE*)0, false),
delta
)
)
continue;
if (quietflag < unlocked)
aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
if (perform & unlocked) {
if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
if (donerewrite(true,
Ttimeflag ? RCSstat.st_mtime : (time_t)-1
) != 0)
continue;
}
if (!quietflag)
aprintf(stdout, "rm -f %s\n", workname);
Izclose(&workptr);
if (perform && un_link(workname) != 0)
eerror(workname);
}
tempunlink();
if (!quietflag)
Ofclose(stdout);
exitmain(exitstatus);
}
static void
cleanup()
{
if (nerror) exitstatus = EXIT_FAILURE;
Izclose(&finptr);
Izclose(&workptr);
Ozclose(&fcopy);
ORCSclose();
dirtempunlink();
}
#if RCS_lint
# define exiterr rcscleanExit
#endif
void
exiterr()
{
ORCSerror();
dirtempunlink();
tempunlink();
_exit(EXIT_FAILURE);
}
static int
unlock(delta)
struct hshentry *delta;
{
register struct rcslock **al, *l;
if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
for (al = &Locks; (l = *al); al = &l->nextlock)
if (l->delta == delta) {
*al = l->nextlock;
delta->lockedby = 0;
return true;
}
return false;
}
#if has_dirent
static int
get_directory(dirname, aargv)
char const *dirname;
char ***aargv;
/*
* Put a vector of all DIRNAME's directory entries names into *AARGV.
* Ignore names of RCS files.
* Yield the number of entries found. Terminate the vector with 0.
* Allocate the storage for the vector and entry names.
* Do not sort the names. Do not include '.' and '..'.
*/
{
int i, entries = 0, entries_max = 64;
size_t chars = 0, chars_max = 1024;
size_t *offset = tnalloc(size_t, entries_max);
char *a = tnalloc(char, chars_max), **p;
DIR *d;
struct dirent *e;
if (!(d = opendir(dirname)))
efaterror(dirname);
while ((errno = 0, e = readdir(d))) {
char const *en = e->d_name;
size_t s = strlen(en) + 1;
if (en[0]=='.' && (!en[1] || (en[1]=='.' && !en[2])))
continue;
if (rcssuffix(en))
continue;
while (chars_max < s + chars)
a = trealloc(char, a, chars_max<<=1);
if (entries == entries_max)
offset = trealloc(size_t, offset, entries_max<<=1);
offset[entries++] = chars;
VOID strcpy(a+chars, en);
chars += s;
}
# if void_closedir
# define close_directory(d) (closedir(d), 0)
# else
# define close_directory(d) closedir(d)
# endif
if (errno || close_directory(d) != 0)
efaterror(dirname);
if (chars)
a = trealloc(char, a, chars);
else
tfree(a);
*aargv = p = tnalloc(char*, entries+1);
for (i=0; i<entries; i++)
*p++ = a + offset[i];
*p = 0;
tfree(offset);
return entries;
}
#endif

View file

@ -0,0 +1,8 @@
PROG= rcsdiff
SRCS= rcsdiff.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View file

@ -0,0 +1,158 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
.TH RCSDIFF 1 \*(Dt GNU
.SH NAME
rcsdiff \- compare RCS revisions
.SH SYNOPSIS
.B rcsdiff
[
.BI \-k subst
] [
.B \-q
] [
.BI \-r rev1
[
.BI \-r rev2
] ] [
.B \-T
] [
.RI "\f3\-V\fP[" n ]
] [
.BI \-x suffixes
] [
.BI \-z zone
] [
.I "diff options"
]
.I "file .\|.\|."
.SH DESCRIPTION
.B rcsdiff
runs
.BR diff (1)
to compare two revisions of each \*r file given.
.PP
Pathnames matching an \*r suffix denote \*r files;
all others denote working files.
Names are paired as explained in
.BR ci (1).
.PP
The option
.B \-q
suppresses diagnostic output.
Zero, one, or two revisions may be specified with
.BR \-r .
The option
.BI \-k subst
affects keyword substitution when extracting
revisions, as described in
.BR co (1);
for example,
.B "\-kk\ \-r1.1\ \-r1.2"
ignores differences in keyword values when comparing revisions
.B 1.1
and
.BR 1.2 .
To avoid excess output from locker name substitution,
.B \-kkvl
is assumed if (1) at most one revision option is given,
(2) no
.B \-k
option is given, (3)
.B \-kkv
is the default keyword substitution, and
(4) the working file's mode would be produced by
.BR "co\ \-l".
See
.BR co (1)
for details
about
.BR \-T ,
.BR \-V ,
.B \-x
and
.BR \-z .
Otherwise, all options of
.BR diff (1)
that apply to regular files are accepted, with the same meaning as for
.BR diff .
.PP
If both
.I rev1
and
.I rev2
are omitted,
.B rcsdiff
compares the latest revision on the
default branch (by default the trunk)
with the contents of the corresponding working file. This is useful
for determining what you changed since the last checkin.
.PP
If
.I rev1
is given, but
.I rev2
is omitted,
.B rcsdiff
compares revision
.I rev1
of the \*r file with
the contents of the corresponding working file.
.PP
If both
.I rev1
and
.I rev2
are given,
.B rcsdiff
compares revisions
.I rev1
and
.I rev2
of the \*r file.
.PP
Both
.I rev1
and
.I rev2
may be given numerically or symbolically.
.SH EXAMPLE
The command
.LP
.B " rcsdiff f.c"
.LP
compares the latest revision on the default branch of the \*r file
to the contents of the working file
.BR f.c .
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
See
.BR ci (1)
for details.
.SH DIAGNOSTICS
Exit status is 0 for no differences during any comparison,
1 for some differences, 2 for trouble.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), diff(1), ident(1), rcs(1), rcsintro(1), rcsmerge(1), rlog(1)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.br

View file

@ -0,0 +1,480 @@
/* Compare RCS revisions. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.19 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.18 1995/06/01 16:23:43 eggert
* (main): Pass "--binary" if -kb and if --binary makes a difference.
* Don't treat + options specially.
*
* Revision 5.17 1994/03/17 14:05:48 eggert
* Specify subprocess input via file descriptor, not file name. Remove lint.
*
* Revision 5.16 1993/11/09 17:40:15 eggert
* -V now prints version on stdout and exits. Don't print usage twice.
*
* Revision 5.15 1993/11/03 17:42:27 eggert
* Add -z. Ignore -T. Pass -Vn to `co'. Add Name keyword.
* Put revision numbers in -c output. Improve quality of diagnostics.
*
* Revision 5.14 1992/07/28 16:12:44 eggert
* Add -V. Use co -M for better dates with traditional diff -c.
*
* Revision 5.13 1992/02/17 23:02:23 eggert
* Output more readable context diff headers.
* Suppress needless checkout and comparison of identical revisions.
*
* Revision 5.12 1992/01/24 18:44:19 eggert
* Add GNU diff 1.15.2's new options. lint -> RCS_lint
*
* Revision 5.11 1992/01/06 02:42:34 eggert
* Update usage string.
*
* Revision 5.10 1991/10/07 17:32:46 eggert
* Remove lint.
*
* Revision 5.9 1991/08/19 03:13:55 eggert
* Add RCSINIT, -r$. Tune.
*
* Revision 5.8 1991/04/21 11:58:21 eggert
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.7 1990/12/13 06:54:07 eggert
* GNU diff 1.15 has -u.
*
* Revision 5.6 1990/11/01 05:03:39 eggert
* Remove unneeded setid check.
*
* Revision 5.5 1990/10/04 06:30:19 eggert
* Accumulate exit status across files.
*
* Revision 5.4 1990/09/27 01:31:43 eggert
* Yield 1, not EXIT_FAILURE, when diffs are found.
*
* Revision 5.3 1990/09/11 02:41:11 eggert
* Simplify -kkvl test.
*
* Revision 5.2 1990/09/04 17:07:19 eggert
* Diff's argv was too small by 1.
*
* Revision 5.1 1990/08/29 07:13:55 eggert
* Add -kkvl.
*
* Revision 5.0 1990/08/22 08:12:46 eggert
* Add -k, -V. Don't use access(). Add setuid support.
* Remove compile-time limits; use malloc instead.
* Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
* Add GNU diff's flags. Make lock and temp files faster and safer.
* Ansify and Posixate.
*
* Revision 4.6 89/05/01 15:12:27 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.5 88/08/09 19:12:41 eggert
* Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
*
* Revision 4.4 87/12/18 11:37:46 narten
* changes Jay Lepreau made in the 4.3 BSD version, to add support for
* "-i", "-w", and "-t" flags and to permit flags to be bundled together,
* merged in.
*
* Revision 4.3 87/10/18 10:31:42 narten
* Updating version numbers. Changes relative to 1.1 actually
* relative to 4.1
*
* Revision 1.3 87/09/24 13:59:21 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:15 jenkins
* Port to suns
*
* Revision 4.1 83/05/03 22:13:19 wft
* Added default branch, option -q, exit status like diff.
* Added fterror() to replace faterror().
*
* Revision 3.6 83/01/15 17:52:40 wft
* Expanded mainprogram to handle multiple RCS files.
*
* Revision 3.5 83/01/06 09:33:45 wft
* Fixed passing of -c (context) option to diff.
*
* Revision 3.4 82/12/24 15:28:38 wft
* Added call to catchsig().
*
* Revision 3.3 82/12/10 16:08:17 wft
* Corrected checking of return code from diff; improved error msgs.
*
* Revision 3.2 82/12/04 13:20:09 wft
* replaced getdelta() with gettree(). Changed diagnostics.
*
* Revision 3.1 82/11/28 19:25:04 wft
* Initial revision.
*
*/
#include "rcsbase.h"
#if DIFF_L
static char const *setup_label P((struct buf*,char const*,char const[datesize]));
#endif
static void cleanup P((void));
static int exitstatus;
static RILE *workptr;
static struct stat workstat;
mainProg(rcsdiffId, "rcsdiff", "$FreeBSD$")
{
static char const cmdusage[] =
"\nrcsdiff usage: rcsdiff -ksubst -q -rrev1 [-rrev2] -Vn -xsuff -zzone [diff options] file ...";
int revnums; /* counter for revision numbers given */
char const *rev1, *rev2; /* revision numbers from command line */
char const *xrev1, *xrev2; /* expanded revision numbers */
char const *expandarg, *lexpandarg, *suffixarg, *versionarg, *zonearg;
#if DIFF_L
static struct buf labelbuf[2];
int file_labels;
char const **diff_label1, **diff_label2;
char date2[datesize];
#endif
char const *cov[10 + !DIFF_L];
char const **diffv, **diffp, **diffpend; /* argv for subsidiary diff */
char const **pp, *p, *diffvstr;
struct buf commarg;
struct buf numericrev; /* expanded revision number */
struct hshentries *gendeltas; /* deltas to be generated */
struct hshentry * target;
char *a, *dcp, **newargv;
int no_diff_means_no_output;
register c;
exitstatus = DIFF_SUCCESS;
bufautobegin(&commarg);
bufautobegin(&numericrev);
revnums = 0;
rev1 = rev2 = xrev2 = 0;
#if DIFF_L
file_labels = 0;
#endif
expandarg = suffixarg = versionarg = zonearg = 0;
no_diff_means_no_output = true;
suffixes = X_DEFAULT;
/*
* Room for runv extra + args [+ --binary] [+ 2 labels]
* + 1 file + 1 trailing null.
*/
diffv = tnalloc(char const*, 1 + argc + !!OPEN_O_BINARY + 2*DIFF_L + 2);
diffp = diffv + 1;
*diffp++ = DIFF;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
dcp = a;
while ((c = *a++)) switch (c) {
case 'r':
switch (++revnums) {
case 1: rev1=a; break;
case 2: rev2=a; break;
default: error("too many revision numbers");
}
goto option_handled;
case '-': case 'D':
no_diff_means_no_output = false;
/* fall into */
case 'C': case 'F': case 'I': case 'L': case 'W':
#if DIFF_L
if (c == 'L' && file_labels++ == 2)
faterror("too many -L options");
#endif
*dcp++ = c;
if (*a)
do *dcp++ = *a++;
while (*a);
else {
if (!--argc)
faterror("-%c needs following argument%s",
c, cmdusage
);
*diffp++ = *argv++;
}
break;
case 'y':
no_diff_means_no_output = false;
/* fall into */
case 'B': case 'H':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'h': case 'i': case 'n': case 'p':
case 't': case 'u': case 'w':
*dcp++ = c;
break;
case 'q':
quietflag=true;
break;
case 'x':
suffixarg = *argv;
suffixes = *argv + 2;
goto option_handled;
case 'z':
zonearg = *argv;
zone_set(*argv + 2);
goto option_handled;
case 'T':
/* Ignore -T, so that RCSINIT can contain -T. */
if (*a)
goto unknown;
break;
case 'V':
versionarg = *argv;
setRCSversion(versionarg);
goto option_handled;
case 'k':
expandarg = *argv;
if (0 <= str2expmode(expandarg+2))
goto option_handled;
/* fall into */
default:
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
option_handled:
if (dcp != *argv+1) {
*dcp = 0;
*diffp++ = *argv;
}
} /* end of option processing */
for (pp = diffv+2, c = 0; pp<diffp; )
c += strlen(*pp++) + 1;
diffvstr = a = tnalloc(char, c + 1);
for (pp = diffv+2; pp<diffp; ) {
p = *pp++;
*a++ = ' ';
while ((*a = *p++))
a++;
}
*a = 0;
#if DIFF_L
diff_label1 = diff_label2 = 0;
if (file_labels < 2) {
if (!file_labels)
diff_label1 = diffp++;
diff_label2 = diffp++;
}
#endif
diffpend = diffp;
cov[1] = CO;
cov[2] = "-q";
# if !DIFF_L
cov[3] = "-M";
# endif
/* Now handle all pathnames. */
if (nerror)
cleanup();
else if (argc < 1)
faterror("no input file%s", cmdusage);
else
for (; 0 < argc; cleanup(), ++argv, --argc) {
ffree();
if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
continue;
diagnose("===================================================================\nRCS file: %s\n",RCSname);
if (!rev2) {
/* Make sure work file is readable, and get its status. */
if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
eerror(workname);
continue;
}
}
gettree(); /* reads in the delta tree */
if (!Head) {
rcserror("no revisions present");
continue;
}
if (revnums==0 || !*rev1)
rev1 = Dbranch ? Dbranch : Head->num;
if (!fexpandsym(rev1, &numericrev, workptr)) continue;
if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
xrev1=target->num;
#if DIFF_L
if (diff_label1)
*diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
#endif
lexpandarg = expandarg;
if (revnums==2) {
if (!fexpandsym(
*rev2 ? rev2 : Dbranch ? Dbranch : Head->num,
&numericrev,
workptr
))
continue;
if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
xrev2=target->num;
if (no_diff_means_no_output && xrev1 == xrev2)
continue;
} else if (
target->lockedby
&& !lexpandarg
&& Expand == KEYVAL_EXPAND
&& WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
)
lexpandarg = "-kkvl";
Izclose(&workptr);
#if DIFF_L
if (diff_label2)
if (revnums == 2)
*diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
else {
time2date(workstat.st_mtime, date2);
*diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
}
#endif
diagnose("retrieving revision %s\n", xrev1);
bufscpy(&commarg, "-p");
bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
pp = &cov[3 + !DIFF_L];
*pp++ = commarg.string;
if (lexpandarg) *pp++ = lexpandarg;
if (suffixarg) *pp++ = suffixarg;
if (versionarg) *pp++ = versionarg;
if (zonearg) *pp++ = zonearg;
*pp++ = RCSname;
*pp = 0;
diffp = diffpend;
# if OPEN_O_BINARY
if (Expand == BINARY_EXPAND)
*diffp++ = "--binary";
# endif
diffp[0] = maketemp(0);
if (runv(-1, diffp[0], cov)) {
rcserror("co failed");
continue;
}
if (!rev2) {
diffp[1] = workname;
if (*workname == '-') {
char *dp = ftnalloc(char, strlen(workname)+3);
diffp[1] = dp;
*dp++ = '.';
*dp++ = SLASH;
VOID strcpy(dp, workname);
}
} else {
diagnose("retrieving revision %s\n",xrev2);
bufscpy(&commarg, "-p");
bufscat(&commarg, rev2); /* not xrev2, for $Name's sake */
cov[3 + !DIFF_L] = commarg.string;
diffp[1] = maketemp(1);
if (runv(-1, diffp[1], cov)) {
rcserror("co failed");
continue;
}
}
if (!rev2)
diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workname);
else
diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
diffp[2] = 0;
switch (runv(-1, (char*)0, diffv)) {
case DIFF_SUCCESS:
break;
case DIFF_FAILURE:
if (exitstatus == DIFF_SUCCESS)
exitstatus = DIFF_FAILURE;
break;
default:
workerror("diff failed");
}
}
tempunlink();
exitmain(exitstatus);
}
static void
cleanup()
{
if (nerror) exitstatus = DIFF_TROUBLE;
Izclose(&finptr);
Izclose(&workptr);
}
#if RCS_lint
# define exiterr rdiffExit
#endif
void
exiterr()
{
tempunlink();
_exit(DIFF_TROUBLE);
}
#if DIFF_L
static char const *
setup_label(b, num, date)
struct buf *b;
char const *num;
char const date[datesize];
{
char *p;
char datestr[datesize + zonelenmax];
VOID date2str(date, datestr);
bufalloc(b,
strlen(workname)
+ sizeof datestr + 4
+ (num ? strlen(num) : 0)
);
p = b->string;
if (num)
VOID sprintf(p, "-L%s\t%s\t%s", workname, datestr, num);
else
VOID sprintf(p, "-L%s\t%s", workname, datestr);
return p;
}
#endif

View file

@ -0,0 +1,7 @@
# $FreeBSD$
SCRIPTS= rcsfreeze.sh
MAN= rcsfreeze.1
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View file

@ -0,0 +1,68 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \s-1RCS\s0
.TH RCSFREEZE 1 \*(Dt GNU
.SH NAME
rcsfreeze \- freeze a configuration of sources checked in under RCS
.SH SYNOPSIS
.B rcsfreeze
.RI [ "name" ]
.SH DESCRIPTION
.B rcsfreeze
assigns a symbolic revision
number to a set of \*r files that form a valid configuration.
.PP
The idea is to run
.B rcsfreeze
each time a new version is checked
in. A unique symbolic name (\c
.BI C_ number,
where
.I number
is increased each time
.B rcsfreeze
is run) is then assigned to the most
recent revision of each \*r file of the main trunk.
.PP
An optional
.I name
argument to
.B rcsfreeze
gives a symbolic name to the configuration.
The unique identifier is still generated
and is listed in the log file but it will not appear as
part of the symbolic revision name in the actual \*r files.
.PP
A log message is requested from the user for future reference.
.PP
The shell script works only on all \*r files at one time.
All changed files must be checked in already.
Run
.IR rcsclean (1)
first and see whether any sources remain in the current directory.
.SH FILES
.TP
.B RCS/.rcsfreeze.ver
version number
.TP
.B RCS/.rcsfreeze.log
log messages, most recent first
.SH AUTHOR
Stephan v. Bechtolsheim
.SH "SEE ALSO"
co(1), rcs(1), rcsclean(1), rlog(1)
.SH BUGS
.B rcsfreeze
does not check whether any sources are checked out and modified.
.PP
Although both source file names and RCS file names are accepted,
they are not paired as usual with RCS commands.
.PP
Error checking is rudimentary.
.PP
.B rcsfreeze
is just an optional example shell script, and should not be taken too seriously.
See \s-1CVS\s0 for a more complete solution.

View file

@ -0,0 +1,99 @@
#! /bin/sh
# rcsfreeze - assign a symbolic revision number to a configuration of RCS files
# $FreeBSD$
# The idea is to run rcsfreeze each time a new version is checked
# in. A unique symbolic revision number (C_[number], where number
# is increased each time rcsfreeze is run) is then assigned to the most
# recent revision of each RCS file of the main trunk.
#
# If the command is invoked with an argument, then this
# argument is used as the symbolic name to freeze a configuration.
# The unique identifier is still generated
# and is listed in the log file but it will not appear as
# part of the symbolic revision name in the actual RCS file.
#
# A log message is requested from the user which is saved for future
# references.
#
# The shell script works only on all RCS files at one time.
# It is important that all changed files are checked in (there are
# no precautions against any error in this respect).
# file names:
# {RCS/}.rcsfreeze.ver version number
# {RCS/}.rscfreeze.log log messages, most recent first
PATH=/bin:/usr/bin:$PATH
export PATH
DATE=`LC_ALL=C date` || exit
# Check whether we have an RCS subdirectory, so we can have the right
# prefix for our paths.
if test -d RCS
then RCSDIR=RCS/ EXT=
else RCSDIR= EXT=,v
fi
# Version number stuff, log message file
VERSIONFILE=${RCSDIR}.rcsfreeze.ver
LOGFILE=${RCSDIR}.rcsfreeze.log
# Initialize, rcsfreeze never run before in the current directory
test -r $VERSIONFILE || { echo 0 >$VERSIONFILE && >>$LOGFILE; } || exit
# Get Version number, increase it, write back to file.
VERSIONNUMBER=`cat $VERSIONFILE` &&
VERSIONNUMBER=`expr $VERSIONNUMBER + 1` &&
echo $VERSIONNUMBER >$VERSIONFILE || exit
# Symbolic Revision Number
SYMREV=C_$VERSIONNUMBER
# Allow the user to give a meaningful symbolic name to the revision.
SYMREVNAME=${1-$SYMREV}
echo >&2 "rcsfreeze: symbolic revision number computed: \"${SYMREV}\"
rcsfreeze: symbolic revision number used: \"${SYMREVNAME}\"
rcsfreeze: the two differ only when rcsfreeze invoked with argument
rcsfreeze: give log message, summarizing changes (end with EOF or single '.')" \
|| exit
# Stamp the logfile. Because we order the logfile the most recent
# first we will have to save everything right now in a temporary file.
TMPLOG=/tmp/rcsfrz$$
trap 'rm -f $TMPLOG; exit 1' 1 2 13 15
# Now ask for a log message, continously add to the log file
(
echo "Version: $SYMREVNAME($SYMREV), Date: $DATE
-----------" || exit
while read MESS
do
case $MESS in
.) break
esac
echo " $MESS" || exit
done
echo "-----------
" &&
cat $LOGFILE
) >$TMPLOG &&
# combine old and new logfiles
cp $TMPLOG $LOGFILE &&
rm -f $TMPLOG &&
# Now the real work begins by assigning a symbolic revision number
# to each rcs file. Take the most recent version on the default branch.
# If there are any .*,v files, throw them in too.
# But ignore RCS/.* files that do not end in ,v.
DOTFILES=
for DOTFILE in ${RCSDIR}.*,v
do
if test -f "$DOTFILE"
then
DOTFILES="${RCSDIR}.*,v"
break
fi
done
exec rcs -q -n$SYMREVNAME: ${RCSDIR}*$EXT $DOTFILES

View file

@ -0,0 +1,8 @@
PROG= rcsmerge
SRCS= rcsmerge.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View file

@ -0,0 +1,189 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds r \&\s-1RCS\s0
.if n .ds - \%--
.if t .ds - \(em
.TH RCSMERGE 1 \*(Dt GNU
.SH NAME
rcsmerge \- merge RCS revisions
.SH SYNOPSIS
.B rcsmerge
.RI [ options ] " file"
.SH DESCRIPTION
.B rcsmerge
incorporates the changes between two revisions
of an \*r file into the corresponding working file.
.PP
Pathnames matching an \*r suffix denote \*r files;
all others denote working files.
Names are paired as explained in
.BR ci (1).
.PP
At least one revision must be specified with one of the options
described below, usually
.BR \-r .
At most two revisions may be specified.
If only one revision is specified, the latest
revision on the default branch (normally the highest branch on the trunk)
is assumed for the second revision.
Revisions may be specified numerically or symbolically.
.PP
.B rcsmerge
prints a warning if there are overlaps, and delimits
the overlapping regions as explained in
.BR merge (1).
The command is useful for incorporating changes into a checked-out revision.
.SH OPTIONS
.TP
.B \-A
Output conflicts using the
.B \-A
style of
.BR diff3 (1),
if supported by
.BR diff3 .
This merges all changes leading from
.I file2
to
.I file3
into
.IR file1 ,
and generates the most verbose output.
.TP
\f3\-E\fP, \f3\-e\fP
These options specify conflict styles that generate less information
than
.BR \-A .
See
.BR diff3 (1)
for details.
The default is
.BR \-E .
With
.BR \-e ,
.B rcsmerge
does not warn about conflicts.
.TP
.BI \-k subst
Use
.I subst
style keyword substitution.
See
.BR co (1)
for details.
For example,
.B "\-kk\ \-r1.1\ \-r1.2"
ignores differences in keyword values when merging the changes from
.B 1.1
to
.BR 1.2 .
It normally does not make sense to merge binary files as if they were text, so
.B rcsmerge
refuses to merge files if
.B \-kb
expansion is used.
.TP
.BR \-p [\f2rev\fP]
Send the result to standard output instead of overwriting the working file.
.TP
.BR \-q [\f2rev\fP]
Run quietly; do not print diagnostics.
.TP
.BR \-r [\f2rev\fP]
Merge with respect to revision
.IR rev .
Here an empty
.I rev
stands for the latest revision on the default branch, normally the head.
.TP
.B \-T
This option has no effect;
it is present for compatibility with other \*r commands.
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.IR n .
See
.BR co (1)
for details.
.TP
.BI \-x "suffixes"
Use
.I suffixes
to characterize \*r files.
See
.BR ci (1)
for details.
.TP
.BI \-z zone
Use
.I zone
as the time zone for keyword substitution.
See
.BR co (1)
for details.
.SH EXAMPLES
Suppose you have released revision 2.8 of
.BR f.c .
Assume
furthermore that after you complete an unreleased revision 3.4, you receive
updates to release 2.8 from someone else.
To combine the updates to 2.8 and your changes between 2.8 and 3.4,
put the updates to 2.8 into file f.c and execute
.LP
.B " rcsmerge \-p \-r2.8 \-r3.4 f.c >f.merged.c"
.PP
Then examine
.BR f.merged.c .
Alternatively, if you want to save the updates to 2.8 in the \*r file,
check them in as revision 2.8.1.1 and execute
.BR "co \-j":
.LP
.B " ci \-r2.8.1.1 f.c"
.br
.B " co \-r3.4 \-j2.8:2.8.1.1 f.c"
.PP
As another example, the following command undoes the changes
between revision 2.4 and 2.8 in your currently checked out revision
in
.BR f.c .
.LP
.B " rcsmerge \-r2.8 \-r2.4 f.c"
.PP
Note the order of the arguments, and that
.B f.c
will be
overwritten.
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
See
.BR ci (1)
for details.
.SH DIAGNOSTICS
Exit status is 0 for no overlaps, 1 for some overlaps, 2 for trouble.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), ident(1), merge(1), rcs(1), rcsdiff(1), rcsintro(1), rlog(1),
rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.br

View file

@ -0,0 +1,286 @@
/* Merge RCS revisions. */
/* Copyright 1982, 1988, 1989 Walter Tichy
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* Revision 5.15 1995/06/16 06:19:24 eggert
* Update FSF address.
*
* Revision 5.14 1995/06/01 16:23:43 eggert
* (main): Report an error if -kb, so don't worry about binary stdout.
* Punctuate messages properly. Rewrite to avoid `goto end'.
*
* Revision 5.13 1994/03/17 14:05:48 eggert
* Specify subprocess input via file descriptor, not file name. Remove lint.
*
* Revision 5.12 1993/11/09 17:40:15 eggert
* -V now prints version on stdout and exits. Don't print usage twice.
*
* Revision 5.11 1993/11/03 17:42:27 eggert
* Add -A, -E, -e, -z. Ignore -T. Allow up to three file labels.
* Pass -Vn to `co'. Pass unexpanded revision name to `co', so that Name works.
*
* Revision 5.10 1992/07/28 16:12:44 eggert
* Add -V.
*
* Revision 5.9 1992/01/24 18:44:19 eggert
* lint -> RCS_lint
*
* Revision 5.8 1992/01/06 02:42:34 eggert
* Update usage string.
*
* Revision 5.7 1991/11/20 17:58:09 eggert
* Don't Iopen(f, "r+"); it's not portable.
*
* Revision 5.6 1991/08/19 03:13:55 eggert
* Add -r$. Tune.
*
* Revision 5.5 1991/04/21 11:58:27 eggert
* Add -x, RCSINIT, MS-DOS support.
*
* Revision 5.4 1991/02/25 07:12:43 eggert
* Merging a revision to itself is no longer an error.
*
* Revision 5.3 1990/11/01 05:03:50 eggert
* Remove unneeded setid check.
*
* Revision 5.2 1990/09/04 08:02:28 eggert
* Check for I/O error when reading working file.
*
* Revision 5.1 1990/08/29 07:14:04 eggert
* Add -q. Pass -L options to merge.
*
* Revision 5.0 1990/08/22 08:13:41 eggert
* Propagate merge's exit status.
* Remove compile-time limits; use malloc instead.
* Make lock and temp files faster and safer. Ansify and Posixate. Add -V.
* Don't use access(). Tune.
*
* Revision 4.5 89/05/01 15:13:16 narten
* changed copyright header to reflect current distribution rules
*
* Revision 4.4 88/08/09 19:13:13 eggert
* Beware merging into a readonly file.
* Beware merging a revision to itself (no change).
* Use execv(), not system(); yield exit status like diff(1)'s.
*
* Revision 4.3 87/10/18 10:38:02 narten
* Updating version numbers. Changes relative to version 1.1
* actually relative to 4.1
*
* Revision 1.3 87/09/24 14:00:31 narten
* Sources now pass through lint (if you ignore printf/sprintf/fprintf
* warnings)
*
* Revision 1.2 87/03/27 14:22:36 jenkins
* Port to suns
*
* Revision 4.1 83/03/28 11:14:57 wft
* Added handling of default branch.
*
* Revision 3.3 82/12/24 15:29:00 wft
* Added call to catchsig().
*
* Revision 3.2 82/12/10 21:32:02 wft
* Replaced getdelta() with gettree(); improved error messages.
*
* Revision 3.1 82/11/28 19:27:44 wft
* Initial revision.
*
*/
#include "rcsbase.h"
static char const co[] = CO;
mainProg(rcsmergeId, "rcsmerge", "$FreeBSD$")
{
static char const cmdusage[] =
"\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] -ksubst -{pq}[rev] -Vn -xsuff -zzone file";
static char const quietarg[] = "-q";
register int i;
char *a, **newargv;
char const *arg[3];
char const *rev[3], *xrev[3]; /*revision numbers*/
char const *edarg, *expandarg, *suffixarg, *versionarg, *zonearg;
int tostdout;
int status;
RILE *workptr;
struct buf commarg;
struct buf numericrev; /* holds expanded revision number */
struct hshentries *gendeltas; /* deltas to be generated */
struct hshentry * target;
bufautobegin(&commarg);
bufautobegin(&numericrev);
edarg = rev[1] = rev[2] = 0;
status = 0; /* Keep lint happy. */
tostdout = false;
expandarg = suffixarg = versionarg = zonearg = quietarg; /* no-op */
suffixes = X_DEFAULT;
argc = getRCSINIT(argc, argv, &newargv);
argv = newargv;
while (a = *++argv, 0<--argc && *a++=='-') {
switch (*a++) {
case 'p':
tostdout=true;
goto revno;
case 'q':
quietflag = true;
revno:
if (!*a)
break;
/* falls into -r */
case 'r':
if (!rev[1])
rev[1] = a;
else if (!rev[2])
rev[2] = a;
else
error("too many revision numbers");
break;
case 'A': case 'E': case 'e':
if (*a)
goto unknown;
edarg = *argv;
break;
case 'x':
suffixarg = *argv;
suffixes = a;
break;
case 'z':
zonearg = *argv;
zone_set(a);
break;
case 'T':
/* Ignore -T, so that RCSINIT can contain -T. */
if (*a)
goto unknown;
break;
case 'V':
versionarg = *argv;
setRCSversion(versionarg);
break;
case 'k':
expandarg = *argv;
if (0 <= str2expmode(expandarg+2))
break;
/* fall into */
default:
unknown:
error("unknown option: %s%s", *argv, cmdusage);
};
} /* end of option processing */
if (!rev[1]) faterror("no base revision number given");
/* Now handle all pathnames. */
if (!nerror) {
if (argc < 1)
faterror("no input file%s", cmdusage);
if (0 < pairnames(argc, argv, rcsreadopen, true, false)) {
if (argc>2 || (argc==2 && argv[1]))
warn("excess arguments ignored");
if (Expand == BINARY_EXPAND)
workerror("merging binary files");
diagnose("RCS file: %s\n", RCSname);
if (!(workptr = Iopen(workname, FOPEN_R_WORK, (struct stat*)0)))
efaterror(workname);
gettree(); /* reads in the delta tree */
if (!Head) rcsfaterror("no revisions present");
if (!*rev[1])
rev[1] = Dbranch ? Dbranch : Head->num;
if (fexpandsym(rev[1], &numericrev, workptr)
&& (target=genrevs(numericrev.string, (char *)0, (char *)0, (char*)0, &gendeltas))
) {
xrev[1] = target->num;
if (!rev[2] || !*rev[2])
rev[2] = Dbranch ? Dbranch : Head->num;
if (fexpandsym(rev[2], &numericrev, workptr)
&& (target=genrevs(numericrev.string, (char *)0, (char *)0, (char *)0, &gendeltas))
) {
xrev[2] = target->num;
if (strcmp(xrev[1],xrev[2]) == 0) {
if (tostdout) {
fastcopy(workptr, stdout);
Ofclose(stdout);
}
} else {
Izclose(&workptr);
for (i=1; i<=2; i++) {
diagnose("retrieving revision %s\n", xrev[i]);
bufscpy(&commarg, "-p");
bufscat(&commarg, rev[i]); /* not xrev[i], for $Name's sake */
if (run(
-1,
/* Do not collide with merger.c maketemp(). */
arg[i] = maketemp(i+2),
co, quietarg, commarg.string,
expandarg, suffixarg, versionarg, zonearg,
RCSname, (char*)0
))
rcsfaterror("co failed");
}
diagnose("Merging differences between %s and %s into %s%s\n",
xrev[1], xrev[2], workname,
tostdout?"; result to stdout":"");
arg[0] = xrev[0] = workname;
status = merge(tostdout, edarg, xrev, arg);
}
}
}
Izclose(&workptr);
}
}
tempunlink();
exitmain(nerror ? DIFF_TROUBLE : status);
}
#if RCS_lint
# define exiterr rmergeExit
#endif
void
exiterr()
{
tempunlink();
_exit(DIFF_TROUBLE);
}

454
gnu/usr.bin/rcs/rcstest Executable file
View file

@ -0,0 +1,454 @@
#! /bin/sh
# Test RCS's functions.
# The RCS commands are searched for in the PATH as usual;
# to test the working directory's commands, prepend . to your PATH.
# Test RCS by creating files RCS/a.* and RCS/a.c.
# If all goes well, output nothing, and remove the temporary files.
# Otherwise, send a message to standard output.
# Exit status is 0 if OK, 1 if an RCS bug is found, and 2 if scaffolding fails.
# With the -v option, output more debugging info.
# If diff outputs `No differences encountered' when comparing identical files,
# then rcstest may also output these noise lines; ignore them.
# The current directory and ./RCS must be readable, writable, and searchable.
# $FreeBSD$
# Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
# Distributed under license by the Free Software Foundation, Inc.
#
# This file is part of RCS.
#
# RCS is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# RCS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RCS; see the file COPYING.
# If not, write to the Free Software Foundation,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Report problems and direct all questions to:
#
# rcs-bugs@cs.purdue.edu
# The Makefile overrides the following defaults.
: ${ALL_CFLAGS=-Dhas_conf_h}
: ${CC=cc}
: ${DIFF=diff}
# : ${LDFLAGS=} ${LIBS=} tickles old shell bug
CL="$CC $ALL_CFLAGS $LDFLAGS -o a.out"
L=$LIBS
RCSINIT=-x
export RCSINIT
SLASH=/
RCSfile=RCS${SLASH}a.c
RCS_alt=RCS${SLASH}a.d
lockfile=RCS${SLASH}a._
case $1 in
-v) q=; set -x;;
'') q=-q;;
*) echo >&2 "$0: usage: $0 [-v]"; exit 2
esac
if test -d RCS
then rmdir=:
else rmdir=rmdir; mkdir RCS || exit
fi
rm -f a.* $RCSfile $RCS_alt $lockfile &&
echo 1.1 >a.11 &&
echo 1.1.1.1 >a.3x1 &&
echo 1.2 >a.12 || { echo "#initialization failed"; exit 2; }
case "`$DIFF -c a.11 a.3x1`" in
*!\ 1.1.1.1)
diff="$DIFF -c";;
*)
echo "#warning: $DIFF -c does not work, so diagnostics may be cryptic"
diff=$DIFF
esac
rcs -i -L -ta.11 $q a.c &&
test -r $RCSfile || {
echo "#rcs -i -L failed; perhaps RCS is not properly installed."
exit 1
}
rlog a.c >/dev/null || { echo "#rlog failed on empty RCS file"; exit 1; }
rm -f $RCSfile || exit 2
cp a.11 a.c &&
ci -ta.11 -mm $q a.c &&
test -r $RCSfile &&
rcs -L $q a.c || { echo "#ci+rcs -L failed"; exit 1; }
test ! -f a.c || { echo "#ci did not remove working file"; exit 1; }
for l in '' '-l'
do
co $l $q a.c &&
test -f a.c || { echo '#co' $l did not create working file; exit 1; }
$diff a.11 a.c || { echo '#ci' followed by co $l is not a no-op; exit 1; }
done
cp a.12 a.c &&
ci -mm $q a.c &&
co $q a.c &&
$diff a.12 a.c || { echo "#ci+co failed"; exit 1; }
rm -f a.c &&
co -r1.1 $q a.c &&
$diff a.11 a.c || { echo "#can't retrieve first revision"; exit 1; }
rm -f a.c &&
cp a.3x1 a.c &&
ci -r1.1.1 -mm $q a.c &&
co -r1.1.1.1 $q a.c &&
$diff a.3x1 a.c || { echo "#branches failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
ci -f -mm $q a.c &&
co -r1.3 $q a.c &&
$diff a.12 a.c || { echo "#(co -l; ci -f) failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 1.4 >a.c &&
ci -l -mm $q a.c &&
echo error >a.c &&
ci -mm $q a.c || { echo "#ci -l failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 1.5 >a.c &&
ci -u -mm $q a.c &&
test -r a.c || { echo "#ci -u didn't create a working file"; exit 1; }
rm -f a.c &&
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#ci -u didn't unlock the file"; exit 1; }
rm -f a.c &&
rcs -l $q a.c &&
co -u $q a.c || { echo "#rcs -l + co -u failed"; exit 1; }
rm -f a.c &&
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#co -u didn't unlock the file"; exit 1; }
rm -f a.c &&
cp a.11 a.c &&
co -f $q a.c || { echo "#co -f failed"; exit 1; }
$diff a.11 a.c >/dev/null && { echo "#co -f had no effect"; exit 1; }
co -p1.1 $q a.c >a.t &&
$diff a.11 a.t || { echo "#co -p failed"; exit 1; }
for n in n N
do
rm -f a.c &&
co -l $q a.c &&
echo $n >a.$n &&
cp a.$n a.c &&
ci -${n}n -mm $q a.c &&
co -rn $q a.c &&
$diff a.$n a.c || { echo "#ci -$n failed"; exit 1; }
done
case $LOGNAME in
?*) me=$LOGNAME;;
*)
case $USER in
?*) me=$USER;;
*)
me=`who am i` || exit 2
me=`echo "$me" | sed -e 's/ .*//' -e 's/.*!//'`
case $me in
'') echo >&2 "$0: cannot deduce user name"; exit 2
esac
esac
esac
# Get the date of the previous revision in UTC.
date=`rlog -r a.c | sed -n '/^date: /{ s///; s/;.*//; p; q; }'` || exit
case $date in
[0-9][0-9][0-9]*[0-9]/[0-1][0-9]/[0-3][0-9]\ [0-2][0-9]:[0-5][0-9]:[0-6][0-9]);;
*) echo >&2 "$0: $date: bad rlog date output"; exit 1
esac
PWD=`pwd` && export PWD &&
rm -f a.c &&
co -l $q a.c &&
sed 's/@/$/g' >a.kv <<EOF
@Author: w @
@Date: $date @
@Header: $PWD$SLASH$RCSfile 2.1 $date w s @
@Id: a.c 2.1 $date w s @
@Locker: @
* @Log: a.c @
* Revision 2.1 $date w
* m
*
@Name: Oz @
@RCSfile: a.c @
@Revision: 2.1 @
@Source: $PWD$SLASH$RCSfile @
@State: s @
EOF
test $? = 0 &&
sed 's/:.*\$/$/' a.kv >a.k &&
sed -e 's/w s [$]/w s '"$me"' $/' -e 's/[$]Locker: /&'"$me/" a.kv >a.kvl &&
sed s/Oz//g a.kv >a.e &&
sed s/Oz/N/g a.kv >a.N &&
sed -e '/\$/!d' -e 's/\$$/: old $/' a.k >a.o &&
sed -e 's/\$[^ ]*: //' -e 's/ \$//' a.kv >a.v &&
cp a.o a.c &&
ci -d"$date" -nOz -ss -ww -u2.1 -mm $q a.c &&
$diff a.kv a.c || { echo "#keyword expansion failed"; exit 1; }
co -pOz -ko $q a.c >a.oo &&
$diff a.o a.oo || { echo "#co -p -ko failed"; exit 1; }
cp a.kv a.o && cp a.o a.b || exit 2
rcs -oOz $q a.c &&
rcs -l $q a.c &&
ci -k -u $q a.c &&
$diff a.kv a.c || { echo "#ci -k failed"; exit 1; }
sed -n 's/^[^$]*\$/$/p' a.kv >a.i &&
ident a.c >a.i1 &&
sed -e 1d -e 's/^[ ]*//' a.i1 >a.i2 &&
$diff a.i a.i2 || { echo "#ident failed"; exit 1; }
rcs -i $q a.c 2>/dev/null && { echo "#rcs -i permitted existing file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo 2.2 >a.c &&
ci -mm $q a.c &&
echo 1.1.1.2 >a.c &&
rcs -l1.1.1 $q a.c &&
ci -r1.1.1.2 -mm $q a.c &&
rcs -b1.1.1 $q a.c &&
test " `co -p $q a.c`" = ' 1.1.1.2' || { echo "#rcs -b1.1.1 failed"; exit 1; }
rcs -b $q a.c &&
test " `co -p $q a.c`" = ' 2.2' || { echo "#rcs -b failed"; exit 1; }
echo 2.3 >a.c || exit 2
rcs -U $q a.c || { echo "#rcs -U failed"; exit 1; }
ci -mm $q a.c || { echo "#rcs -U didn't unset strict locking"; exit 1; }
rcs -L $q a.c || { echo "#rcs -L failed"; exit 1; }
echo error >a.c || exit 2
ci -mm $q a.c 2>/dev/null && { echo "#ci retest failed"; exit 1; }
rm -f a.c &&
log0=`rlog -h a.c` &&
co -l $q a.c &&
ci -mm $q a.c &&
log1=`rlog -h a.c` &&
test " $log0" = " $log1" || { echo "#unchanged ci didn't revert"; exit 1; }
rm -f a.c &&
rcs -nN:1.1 $q a.c &&
co -rN $q a.c &&
$diff a.11 a.c || { echo "#rcs -n failed"; exit 1; }
rm -f a.c &&
rcs -NN:2.1 $q a.c &&
co -rN $q a.c &&
$diff a.N a.c || { echo "#rcs -N failed"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
echo ':::$''Log$' >a.c &&
ci -u -mm $q a.c &&
test " `sed '$!d' a.c`" = ' :::' || { echo "#comment leader failed"; exit 1; }
rm -f a.c &&
rcs -o2.2: $q a.c &&
co $q a.c &&
$diff a.e a.c || { echo "#rcs -o failed"; exit 1; }
rcsdiff -r1.1 -rOz $q a.c >a.0
case $? in
1) ;;
*) echo "#rcsdiff bad status"; exit 1
esac
$DIFF a.11 a.kv >a.1
$diff a.0 a.1 || { echo "#rcsdiff failed"; exit 1; }
rcs -l2.1 $q a.c || { echo "#rcs -l2.1 failed"; exit 1; }
for i in b k kv kvl o v
do
rm -f a.c &&
cp a.$i a.c &&
rcsdiff -k$i -rOz $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; }
done
co -p1.1 -ko $q a.c >a.t &&
$diff a.11 a.t || { echo "#co -p1.1 -ko failed"; exit 1; }
rcs -u2.1 $q a.c || { echo "#rcs -u2.1 failed"; exit 1; }
rm -f a.c &&
rcsclean $q a.c &&
rcsclean -u $q a.c || { echo "#rcsclean botched a nonexistent file"; exit 1; }
rm -f a.c &&
co $q a.c &&
rcsclean -n $q a.c &&
rcsclean -n -u $q a.c &&
test -f a.c || { echo "#rcsclean -n removed a file"; exit 1; }
rm -f a.c &&
co $q a.c &&
rcsclean $q a.c &&
test ! -f a.c || { echo "#rcsclean missed an unlocked file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
rcsclean $q a.c &&
test -f a.c || { echo "#rcsclean removed a locked file"; exit 1; }
rcsclean -u $q a.c &&
test ! -f a.c || {
echo "#rcsclean -u missed an unchanged locked file"; exit 1;
}
rm -f a.c &&
co -l $q a.c &&
echo change >>a.c &&
rcsclean $q a.c &&
rcsclean $q -u a.c &&
test -f a.c || { echo "#rcsclean removed a changed file"; exit 1; }
rm -f a.c &&
co -l $q a.c &&
cat >a.c <<'EOF'
2.2
a
b
c
d
EOF
test $? = 0 &&
ci -l -mm $q a.c &&
co -p2.2 $q a.c | sed -e s/2.2/2.3/ -e s/b/b1/ >a.c &&
ci -l -mm $q a.c &&
co -p2.2 $q a.c | sed -e s/2.2/new/ -e s/d/d1/ >a.c || exit 2
cat >a.0 <<'EOF'
2.3
a
b1
c
d1
EOF
cat >a.1 <<'EOF'
<<<<<<< a.c
new
=======
2.3
>>>>>>> 2.3
a
b1
c
d1
EOF
rcsmerge -E -r2.2 -r2.3 $q a.c
case $? in
0)
if $diff a.0 a.c >/dev/null
then echo "#warning: diff3 -E does not work, " \
"so merge and rcsmerge ignore overlaps and suppress overlap lines."
else
$diff a.1 a.c || { echo "#rcsmerge failed (status 0)"; exit 1; }
echo "#warning: The diff3 lib program exit status ignores overlaps," \
"so rcsmerge does not warn about overlap lines that it generates."
fi
;;
1)
$diff a.1 a.c || { echo "#rcsmerge failed (status 1)"; exit 1; }
;;
*)
echo "#rcsmerge bad status"; exit 1
esac
# Avoid `tr' if possible; it's not portable, and it can't handle null bytes.
# Our substitute exclusive-ORs with '\n';
# this ensures null bytes on output, which is even better than `tr',
# since some diffs think a file is binary only if it contains null bytes.
cat >a.c <<'EOF'
#include <stdio.h>
int main() {
int c;
while ((c=getchar()) != EOF)
putchar(c ^ '\n');
return 0;
}
EOF
tr=tr
if (rm -f a.exe a.out && $CL a.c $L >&2) >/dev/null 2>&1
then
if test -s a.out
then tr=./a.out
elif test -s a.exe
then tr=./a.exe
fi
fi
{
co -p $q a.c | $tr '\012' '\200' >a.24 &&
cp a.24 a.c &&
ciOut=`(ci -l -mm $q a.c 2>&1)` &&
case $ciOut in
?*) echo >&2 "$ciOut"
esac &&
co -p $q a.c | $tr '\200' '\012' >a.c &&
rcsdiff -r2.3 $q a.c >/dev/null &&
echo 2.5 >a.c &&
ci -l -mm $q a.c &&
cp a.24 a.c &&
rcsdiff -r2.4 $q a.c >/dev/null
} || echo "#warning: Traditional diff is used, so RCS is limited to text files."
rcs -u -o2.4: $q a.c || { echo "#rcs -u -o failed"; exit 1; }
rcs -i -Aa.c -t- $q a.d || { echo "#rcs -i -A failed"; exit 1; }
rlog -r2.1 a.c >a.t &&
grep '^checked in with -k' a.t >/dev/null &&
sed '/^checked in with -k/d' a.t >a.u &&
$diff - a.u <<EOF
RCS file: $RCSfile
Working file: a.c
head: 2.3
branch:
locks: strict
access list:
symbolic names:
N: 2.1
Oz: 2.1
n: 1.8
keyword substitution: kv
total revisions: 13; selected revisions: 1
description:
1.1
----------------------------
revision 2.1
date: $date; author: w; state: s; lines: +14 -1
=============================================================================
EOF
test $? = 0 || { echo "#rlog failed"; exit 1; }
test ! -f $lockfile || { echo "#lock file not removed"; exit 1; }
rm -f a.* $RCSfile $RCS_alt
$rmdir RCS

View file

@ -0,0 +1,8 @@
PROG= rlog
SRCS= rlog.c
CFLAGS+= -I${.CURDIR}/../lib
LDADD= ${LIBRCS}
DPADD= ${LIBRCS}
.include "../../Makefile.inc"
.include <bsd.prog.mk>

318
gnu/usr.bin/rcs/rlog/rlog.1 Normal file
View file

@ -0,0 +1,318 @@
.de Id
.ds Rv \\$3
.ds Dt \\$4
..
.Id $FreeBSD$
.ds i \&\s-1ISO\s0
.ds r \&\s-1RCS\s0
.ds u \&\s-1UTC\s0
.if n .ds - \%--
.if t .ds - \(em
.TH RLOG 1 \*(Dt GNU
.SH NAME
rlog \- print log messages and other information about RCS files
.SH SYNOPSIS
.B rlog
.RI [ " options " ] " file " .\|.\|.
.SH DESCRIPTION
.B rlog
prints information about \*r files.
.PP
Pathnames matching an \*r suffix denote \*r files;
all others denote working files.
Names are paired as explained in
.BR ci (1).
.PP
.B rlog
prints the following information for each
\*r file: \*r pathname, working pathname, head (i.e., the number
of the latest revision on the trunk), default branch, access list, locks,
symbolic names, suffix, total number of revisions,
number of revisions selected for printing, and
descriptive text. This is followed by entries for the selected revisions in
reverse chronological order for each branch. For each revision,
.B rlog
prints revision number, author, date/time, state, number of
lines added/deleted (with respect to the previous revision),
locker of the revision (if any), and log message.
All times are displayed in Coordinated Universal Time (\*u) by default;
this can be overridden with
.BR \-z .
Without options,
.B rlog
prints complete information.
The options below restrict this output.
.nr n \w'\f3\-V\fP\f2n\fP'+2n-1/1n
.ds n \nn
.if \n(.g .if r an-tag-sep .ds n \w'\f3\-V\fP\f2n\fP'u+\n[an-tag-sep]u
.TP \*n
.B \-L
Ignore \*r files that have no locks set.
This is convenient in combination with
.BR \-h ,
.BR \-l ,
and
.BR \-R .
.TP
.B \-R
Print only the name of the \*r file.
This is convenient for translating a
working pathname into an \*r pathname.
.TP
.BI \-v "[string]"
Print only the working pathname and tip-revision.
The optional string is prepended to the outputline.
.TP
.B \-h
Print only the \*r pathname, working pathname, head,
default branch, access list, locks,
symbolic names, and suffix.
.TP
.B \-t
Print the same as
.BR \-h ,
plus the descriptive text.
.TP
.B \-N
Do not print the symbolic names.
.TP
.B \-b
Print information about the revisions on the default branch, normally
the highest branch on the trunk.
.TP
.BI \-d "dates"
Print information about revisions with a checkin date/time in the ranges given by
the semicolon-separated list of
.IR dates .
A range of the form
.IB d1 < d2
or
.IB d2 > d1
selects the revisions that were deposited between
.I d1
and
.I d2
exclusive.
A range of the form
.BI < d
or
.IB d >
selects
all revisions earlier than
.IR d .
A range of the form
.IB d <
or
.BI > d
selects
all revisions dated later than
.IR d .
If
.B <
or
.B >
is followed by
.B =
then the ranges are inclusive, not exclusive.
A range of the form
.I d
selects the single, latest revision dated
.I d
or earlier.
The date/time strings
.IR d ,
.IR d1 ,
and
.I d2
are in the free format explained in
.BR co (1).
Quoting is normally necessary, especially for
.B <
and
.BR > .
Note that the separator is
a semicolon.
.TP
.BR \-l [\f2lockers\fP]
Print information about locked revisions only.
In addition, if the comma-separated list
.I lockers
of login names is given,
ignore all locks other than those held by the
.IR lockers .
For example,
.B "rlog\ \-L\ \-R\ \-lwft\ RCS/*"
prints the name of \*r files locked by the user
.BR wft .
.TP
.BR \-r [\f2revisions\fP]
prints information about revisions given in the comma-separated list
.I revisions
of revisions and ranges.
A range
.IB rev1 : rev2
means revisions
.I rev1
to
.I rev2
on the same branch,
.BI : rev
means revisions from the beginning of the branch up to and including
.IR rev ,
and
.IB rev :
means revisions starting with
.I rev
to the end of the branch containing
.IR rev .
An argument that is a branch means all
revisions on that branch.
A range of branches means all revisions
on the branches in that range.
A branch followed by a
.B .\&
means the latest revision in that branch.
A bare
.B \-r
with no
.I revisions
means the latest revision on the default branch, normally the trunk.
.TP
.BI \-s states
prints information about revisions whose state attributes match one of the
states given in the comma-separated list
.IR states .
.TP
.BR \-w [\f2logins\fP]
prints information about revisions checked in by users with
login names appearing in the comma-separated list
.IR logins .
If
.I logins
is omitted, the user's login is assumed.
.TP
.B \-T
This option has no effect;
it is present for compatibility with other \*r commands.
.TP
.BI \-V
Print \*r's version number.
.TP
.BI \-V n
Emulate \*r version
.I n
when generating logs.
See
.BR co (1)
for more.
.TP
.BI \-x "suffixes"
Use
.I suffixes
to characterize \*r files.
See
.BR ci (1)
for details.
.PP
.B rlog
prints the intersection of the revisions selected with
the options
.BR \-d ,
.BR \-l ,
.BR \-s ,
and
.BR \-w ,
intersected
with the union of the revisions selected by
.B \-b
and
.BR \-r .
.TP
.BI \-z zone
specifies the date output format,
and specifies the default time zone for
.I date
in the
.BI \-d dates
option.
The
.I zone
should be empty, a numeric \*u offset, or the special string
.B LT
for local time.
The default is an empty
.IR zone ,
which uses the traditional \*r format of \*u without any time zone indication
and with slashes separating the parts of the date;
otherwise, times are output in \*i 8601 format with time zone indication.
For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
eight hours west of \*u,
then the time is output as follows:
.RS
.LP
.RS
.nf
.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
.ne 4
\f2option\fP \f2time output\fP
\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
.ta 4n +4n +4n +4n
.fi
.RE
.SH EXAMPLES
.LP
.nf
.B " rlog \-L \-R RCS/*"
.B " rlog \-L \-h RCS/*"
.B " rlog \-L \-l RCS/*"
.B " rlog RCS/*"
.fi
.LP
The first command prints the names of all \*r files in the subdirectory
.B RCS
that have locks. The second command prints the headers of those files,
and the third prints the headers plus the log messages of the locked revisions.
The last command prints complete information.
.SH ENVIRONMENT
.TP
.B \s-1RCSINIT\s0
options prepended to the argument list, separated by spaces.
See
.BR ci (1)
for details.
.SH DIAGNOSTICS
The exit status is zero if and only if all operations were successful.
.SH IDENTIFICATION
Author: Walter F. Tichy.
.br
Manual Page Revision: \*(Rv; Release Date: \*(Dt.
.br
Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
.br
Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
.SH "SEE ALSO"
ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1),
rcsfile(5)
.br
Walter F. Tichy,
\*r\*-A System for Version Control,
.I "Software\*-Practice & Experience"
.BR 15 ,
7 (July 1985), 637-654.
.SH BUGS
The separator for revision ranges in the
.B \-r
option used to be
.B \-
instead of
.BR : ,
but this leads to confusion when symbolic names contain
.BR \- .
For backwards compatibility
.B "rlog \-r"
still supports the old
.B \-
separator, but it warns about this obsolete use.
.br

1290
gnu/usr.bin/rcs/rlog/rlog.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
# $FreeBSD$
SUBDIR= rcs rcs_func
.include <bsd.subdir.mk>

View file

@ -0,0 +1,5 @@
# $FreeBSD$
VOLUME= psd/13.rcs
MACROS= -ms
SRCDIR= ${.CURDIR}/../../../../../gnu/usr.bin/rcs/doc

View file

@ -0,0 +1,7 @@
# $FreeBSD$
SRCS= rcs.ms
USE_PIC=
USE_TBL=
.include <bsd.doc.mk>

View file

@ -0,0 +1,6 @@
# $FreeBSD$
DOC= rcs_func
SRCS= rcs_func.ms
.include <bsd.doc.mk>

View file

@ -20,6 +20,7 @@ SUBDIR= title \
05.sysman \
06.Clang \
12.make \
13.rcs \
15.yacc \
16.lex \
17.m4 \

View file

@ -909,6 +909,11 @@ This includes
.Xr rlogin 1 ,
.Xr rsh 1 ,
etc.
.It Va WITHOUT_RCS
.\" from FreeBSD: head/tools/build/options/WITHOUT_RCS 156932 2006-03-21 07:50:50Z ru
Set to not build
.Xr rcs 1
and related utilities.
.It Va WITHOUT_RESCUE
.\" from FreeBSD: head/tools/build/options/WITHOUT_RESCUE 156932 2006-03-21 07:50:50Z ru
Set to not build

View file

@ -334,6 +334,7 @@ __DEFAULT_YES_OPTIONS = \
PROFILE \
QUOTAS \
RCMDS \
RCS \
RESCUE \
ROUTED \
SENDMAIL \

View file

@ -35,7 +35,6 @@ static driver_t uart_s3c2410_driver = {
sizeof(struct uart_softc),
};
extern struct uart_class uart_s3c2410_class;
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_s3c2410_probe(device_t dev)

View file

@ -47,8 +47,6 @@ extern struct uart_ops uart_s3c2410_ops;
vm_offset_t s3c2410_uart_vaddr;
unsigned int s3c2410_pclk;
extern struct uart_class uart_s3c2410_class;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{

View file

@ -2415,7 +2415,7 @@ xptsetasyncbusfunc(struct cam_eb *bus, void *arg)
struct ccb_setasync *csa = (struct ccb_setasync *)arg;
xpt_compile_path(&path, /*periph*/NULL,
bus->sim->path_id,
bus->path_id,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD);
xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL);
@ -3840,13 +3840,8 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
/* Couldn't satisfy request */
return (CAM_RESRC_UNAVAIL);
}
if (strcmp(sim->sim_name, "xpt") != 0) {
sim->path_id =
xptpathid(sim->sim_name, sim->unit_number, sim->bus_id);
}
TAILQ_INIT(&new_bus->et_entries);
new_bus->path_id = sim->path_id;
cam_sim_hold(sim);
new_bus->sim = sim;
timevalclear(&new_bus->last_reset);
@ -3855,6 +3850,8 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
new_bus->generation = 0;
xpt_lock_buses();
sim->path_id = new_bus->path_id =
xptpathid(sim->sim_name, sim->unit_number, sim->bus_id);
old_bus = TAILQ_FIRST(&xsoftc.xpt_busses);
while (old_bus != NULL
&& old_bus->path_id < new_bus->path_id)
@ -3958,8 +3955,8 @@ xptnextfreepathid(void)
path_id_t pathid;
const char *strval;
mtx_assert(&xsoftc.xpt_topo_lock, MA_OWNED);
pathid = 0;
xpt_lock_buses();
bus = TAILQ_FIRST(&xsoftc.xpt_busses);
retry:
/* Find an unoccupied pathid */
@ -3968,7 +3965,6 @@ retry:
pathid++;
bus = TAILQ_NEXT(bus, links);
}
xpt_unlock_buses();
/*
* Ensure that this pathid is not reserved for
@ -3977,7 +3973,6 @@ retry:
if (resource_string_value("scbus", pathid, "at", &strval) == 0) {
++pathid;
/* Start the search over */
xpt_lock_buses();
goto retry;
}
return (pathid);
@ -3993,6 +3988,8 @@ xptpathid(const char *sim_name, int sim_unit, int sim_bus)
pathid = CAM_XPT_PATH_ID;
snprintf(buf, sizeof(buf), "%s%d", sim_name, sim_unit);
if (strcmp(buf, "xpt0") == 0 && sim_bus == 0)
return (pathid);
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", buf)) == 0) {
if (strcmp(dname, "scbus")) {

View file

@ -229,8 +229,6 @@ cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request)
/*
* The target MUST silently ignore any non-immediate command outside
* of this range.
*
* XXX: ... or non-immediate duplicates within the range.
*/
if (cmdsn < cs->cs_cmdsn || cmdsn > cs->cs_cmdsn + maxcmdsn_delta) {
CFISCSI_SESSION_UNLOCK(cs);
@ -288,8 +286,8 @@ cfiscsi_pdu_handle(struct icl_pdu *request)
CFISCSI_SESSION_WARN(cs, "received PDU with unsupported "
"opcode 0x%x; dropping connection",
request->ip_bhs->bhs_opcode);
cfiscsi_session_terminate(cs);
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
}
}
@ -455,6 +453,9 @@ cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
struct iscsi_bhs_nop_out *bhsno;
struct iscsi_bhs_nop_in *bhsni;
struct icl_pdu *response;
void *data = NULL;
size_t datasize;
int error;
cs = PDU_SESSION(request);
bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
@ -468,9 +469,26 @@ cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
return;
}
datasize = icl_pdu_data_segment_length(request);
if (datasize > 0) {
data = malloc(datasize, M_CFISCSI, M_NOWAIT | M_ZERO);
if (data == NULL) {
CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
"dropping connection");
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
}
icl_pdu_get_data(request, 0, data, datasize);
}
response = cfiscsi_pdu_new_response(request, M_NOWAIT);
if (response == NULL) {
CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
"droppping connection");
free(data, M_CFISCSI);
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
}
bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
@ -478,14 +496,19 @@ cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
bhsni->bhsni_flags = 0x80;
bhsni->bhsni_initiator_task_tag = bhsno->bhsno_initiator_task_tag;
bhsni->bhsni_target_transfer_tag = 0xffffffff;
#if 0
/* XXX */
response->ip_data_len = request->ip_data_len;
response->ip_data_mbuf = request->ip_data_mbuf;
request->ip_data_len = 0;
request->ip_data_mbuf = NULL;
#endif
if (datasize > 0) {
error = icl_pdu_append_data(response, data, datasize, M_NOWAIT);
if (error != 0) {
CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
"dropping connection");
free(data, M_CFISCSI);
icl_pdu_free(request);
icl_pdu_free(response);
cfiscsi_session_terminate(cs);
return;
}
free(data, M_CFISCSI);
}
icl_pdu_free(request);
cfiscsi_pdu_queue(response);
@ -507,14 +530,16 @@ cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request)
if (request->ip_data_len > 0 && cs->cs_immediate_data == false) {
CFISCSI_SESSION_WARN(cs, "unsolicited data with "
"ImmediateData=No; dropping connection");
cfiscsi_session_terminate(cs);
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
}
io = ctl_alloc_io(cs->cs_target->ct_softc->fe.ctl_pool_ref);
if (io == NULL) {
CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io");
CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io; "
"dropping connection");
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
}
ctl_zero_io(io);
@ -554,10 +579,12 @@ cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request)
refcount_acquire(&cs->cs_outstanding_ctl_pdus);
error = ctl_queue(io);
if (error != CTL_RETVAL_COMPLETE) {
CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error);
CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; "
"dropping connection", error);
ctl_free_io(io);
refcount_release(&cs->cs_outstanding_ctl_pdus);
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
}
}
@ -575,8 +602,10 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
io = ctl_alloc_io(cs->cs_target->ct_softc->fe.ctl_pool_ref);
if (io == NULL) {
CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io");
CFISCSI_SESSION_WARN(cs, "can't allocate ctl_io;"
"dropping connection");
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
}
ctl_zero_io(io);
@ -617,7 +646,10 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
response = cfiscsi_pdu_new_response(request, M_NOWAIT);
if (response == NULL) {
CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
"dropping connection");
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
}
bhstmr2 = (struct iscsi_bhs_task_management_response *)
@ -636,10 +668,12 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
refcount_acquire(&cs->cs_outstanding_ctl_pdus);
error = ctl_queue(io);
if (error != CTL_RETVAL_COMPLETE) {
CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error);
CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; "
"dropping connection", error);
ctl_free_io(io);
refcount_release(&cs->cs_outstanding_ctl_pdus);
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
}
}
@ -649,7 +683,7 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
struct iscsi_bhs_data_out *bhsdo;
struct cfiscsi_session *cs;
struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
size_t copy_len, off, buffer_offset;
size_t copy_len, len, off, buffer_offset;
int ctl_sg_count;
union ctl_io *io;
@ -684,10 +718,6 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
ctl_sglist->len = io->scsiio.kern_data_len;
ctl_sg_count = 1;
}
#if 0
if (ctl_sg_count > 1)
CFISCSI_SESSION_DEBUG(cs, "ctl_sg_count = %d", ctl_sg_count);
#endif
if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
ISCSI_BHS_OPCODE_SCSI_DATA_OUT)
@ -707,7 +737,20 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
return (true);
}
/*
* This is the offset within the PDU data segment, as opposed
* to buffer_offset, which is the offset within the task (SCSI
* command).
*/
off = 0;
len = icl_pdu_data_segment_length(request);
/*
* Iterate over the scatter/gather segments, filling them with data
* from the PDU data segment. Note that this can get called multiple
* times for one SCSI command; the cdw structure holds state for the
* scatter/gather list.
*/
for (;;) {
KASSERT(cdw->cdw_sg_index < ctl_sg_count,
("cdw->cdw_sg_index >= ctl_sg_count"));
@ -715,7 +758,8 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len;
}
copy_len = icl_pdu_data_segment_length(request) - off;
KASSERT(off <= len, ("len > off"));
copy_len = len - off;
if (copy_len > cdw->cdw_sg_len)
copy_len = cdw->cdw_sg_len;
@ -726,15 +770,27 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
io->scsiio.ext_data_filled += copy_len;
if (cdw->cdw_sg_len == 0) {
if (cdw->cdw_sg_index == ctl_sg_count - 1)
/*
* End of current segment.
*/
if (cdw->cdw_sg_index == ctl_sg_count - 1) {
/*
* Last segment in scatter/gather list.
*/
break;
}
cdw->cdw_sg_index++;
}
if (off == icl_pdu_data_segment_length(request))
if (off == len) {
/*
* End of PDU payload.
*/
break;
}
}
if (off < icl_pdu_data_segment_length(request)) {
if (len > off) {
CFISCSI_SESSION_WARN(cs, "received too much data: got %zd bytes, "
"expected %zd", icl_pdu_data_segment_length(request), off);
cfiscsi_session_terminate(cs);
@ -808,8 +864,8 @@ cfiscsi_pdu_handle_data_out(struct icl_pdu *request)
CFISCSI_SESSION_UNLOCK(cs);
if (cdw == NULL) {
CFISCSI_SESSION_WARN(cs, "data transfer tag 0x%x, initiator task tag "
"0x%x, not found", bhsdo->bhsdo_target_transfer_tag,
bhsdo->bhsdo_initiator_task_tag);
"0x%x, not found; dropping connection",
bhsdo->bhsdo_target_transfer_tag, bhsdo->bhsdo_initiator_task_tag);
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
@ -846,6 +902,7 @@ cfiscsi_pdu_handle_logout_request(struct icl_pdu *request)
case BHSLR_REASON_CLOSE_CONNECTION:
response = cfiscsi_pdu_new_response(request, M_NOWAIT);
if (response == NULL) {
CFISCSI_SESSION_DEBUG(cs, "failed to allocate memory");
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
@ -863,6 +920,8 @@ cfiscsi_pdu_handle_logout_request(struct icl_pdu *request)
case BHSLR_REASON_REMOVE_FOR_RECOVERY:
response = cfiscsi_pdu_new_response(request, M_NOWAIT);
if (response == NULL) {
CFISCSI_SESSION_WARN(cs,
"failed to allocate memory; dropping connection");
icl_pdu_free(request);
cfiscsi_session_terminate(cs);
return;
@ -934,7 +993,7 @@ cfiscsi_callout(void *context)
cp = icl_pdu_new_bhs(cs->cs_conn, M_NOWAIT);
if (cp == NULL) {
CFISCSI_SESSION_WARN(cs, "failed to allocate PDU");
CFISCSI_SESSION_WARN(cs, "failed to allocate memory");
return;
}
bhsni = (struct iscsi_bhs_nop_in *)cp->ip_bhs;
@ -2275,11 +2334,6 @@ cfiscsi_datamove_in(union ctl_io *io)
*/
PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len;
#if 0
if (ctl_sg_count > 1)
CFISCSI_SESSION_DEBUG(cs, "ctl_sg_count = %d", ctl_sg_count);
#endif
/*
* This is the offset within the current SCSI command;
* i.e. for the first call of datamove(), it will be 0,
@ -2287,8 +2341,6 @@ cfiscsi_datamove_in(union ctl_io *io)
* of previous ones.
*/
off = htonl(io->scsiio.kern_rel_offset);
if (off > 1)
CFISCSI_SESSION_DEBUG(cs, "off = %zd", off);
i = 0;
addr = NULL;
@ -2361,7 +2413,7 @@ cfiscsi_datamove_in(union ctl_io *io)
/*
* Can't stuff more data into the current PDU;
* queue it. Note that's not enough to check
* for kern_data_resid == 0 instead; there
* for kern_data_resid == 0 instead; there
* may be several Data-In PDUs for the final
* call to cfiscsi_datamove(), and we want
* to set the F flag only on the last of them.
@ -2380,10 +2432,12 @@ cfiscsi_datamove_in(union ctl_io *io)
if (response != NULL) {
if (off == io->scsiio.kern_total_len) {
bhsdi->bhsdi_flags |= BHSDI_FLAGS_F;
#if 0
} else {
CFISCSI_SESSION_DEBUG(cs, "not setting the F flag; "
"have %zd, need %zd", off,
(size_t)io->scsiio.kern_total_len);
#endif
}
KASSERT(response->ip_data_len > 0, ("sending empty Data-In"));
cfiscsi_pdu_queue(response);

View file

@ -159,7 +159,7 @@ ipf_p_rcmd_portmsg(fin, aps, nat)
ip6_t *ip6;
#endif
int tcpsz;
int slen;
int slen = 0; /* silence gcc */
ip_t *ip;
mb_t *m;

View file

@ -1,6 +1,6 @@
/******************************************************************************
Copyright (c) 2001-2011, Intel Corporation
Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -32,16 +32,12 @@
******************************************************************************/
/*$FreeBSD$*/
/*
* 80003ES2LAN Gigabit Ethernet Controller (Copper)
/* 80003ES2LAN Gigabit Ethernet Controller (Copper)
* 80003ES2LAN Gigabit Ethernet Controller (Serdes)
*/
#include "e1000_api.h"
static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw);
static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);
static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);
static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
@ -71,14 +67,12 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
u16 *data);
static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
u16 data);
static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
/*
* A table for the GG82563 cable length where the range is defined
/* A table for the GG82563 cable length where the range is defined
* with a lower bound at "index" and the upper bound at
* "index + 5".
*/
@ -95,13 +89,13 @@ static const u16 e1000_gg82563_cable_length_table[] = {
static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
DEBUGFUNC("e1000_init_phy_params_80003es2lan");
if (hw->phy.media_type != e1000_media_type_copper) {
phy->type = e1000_phy_none;
goto out;
return E1000_SUCCESS;
} else {
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
@ -133,12 +127,9 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
ret_val = e1000_get_phy_id(hw);
/* Verify phy id */
if (phy->id != GG82563_E_PHY_ID) {
ret_val = -E1000_ERR_PHY;
goto out;
}
if (phy->id != GG82563_E_PHY_ID)
return -E1000_ERR_PHY;
out:
return ret_val;
}
@ -176,8 +167,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
E1000_EECD_SIZE_EX_SHIFT);
/*
* Added to a constant, "size" becomes the left-shift value
/* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
@ -234,8 +224,8 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
/* FWSM register */
mac->has_fwsm = TRUE;
/* ARC supported; valid only if manageability features are enabled. */
mac->arc_subsystem_valid = (E1000_READ_REG(hw, E1000_FWSM) &
E1000_FWSM_MODE_MASK) ? TRUE : FALSE;
mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) &
E1000_FWSM_MODE_MASK);
/* Adaptive IFS not supported */
mac->adaptive_ifs = FALSE;
@ -377,14 +367,13 @@ static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
if (ret_val)
goto out;
return ret_val;
ret_val = e1000_acquire_nvm_generic(hw);
if (ret_val)
e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM);
out:
return ret_val;
}
@ -415,23 +404,20 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
u32 swfw_sync;
u32 swmask = mask;
u32 fwmask = mask << 16;
s32 ret_val = E1000_SUCCESS;
s32 i = 0, timeout = 50;
s32 i = 0;
s32 timeout = 50;
DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan");
while (i < timeout) {
if (e1000_get_hw_semaphore_generic(hw)) {
ret_val = -E1000_ERR_SWFW_SYNC;
goto out;
}
if (e1000_get_hw_semaphore_generic(hw))
return -E1000_ERR_SWFW_SYNC;
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
if (!(swfw_sync & (fwmask | swmask)))
break;
/*
* Firmware currently using resource (fwmask)
/* Firmware currently using resource (fwmask)
* or other software thread using resource (swmask)
*/
e1000_put_hw_semaphore_generic(hw);
@ -441,8 +427,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
if (i == timeout) {
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
ret_val = -E1000_ERR_SWFW_SYNC;
goto out;
return -E1000_ERR_SWFW_SYNC;
}
swfw_sync |= swmask;
@ -450,8 +435,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
e1000_put_hw_semaphore_generic(hw);
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -497,14 +481,13 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000_acquire_phy_80003es2lan(hw);
if (ret_val)
goto out;
return ret_val;
/* Select Configuration Page */
if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
page_select = GG82563_PHY_PAGE_SELECT;
} else {
/*
* Use Alternative Page Select register to access
/* Use Alternative Page Select register to access
* registers 30 and 31
*/
page_select = GG82563_PHY_PAGE_SELECT_ALT;
@ -514,12 +497,11 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
if (ret_val) {
e1000_release_phy_80003es2lan(hw);
goto out;
return ret_val;
}
if (hw->dev_spec._80003es2lan.mdic_wa_enable == TRUE) {
/*
* The "ready" bit in the MDIC register may be incorrectly set
if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
/* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
@ -529,9 +511,8 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
ret_val = -E1000_ERR_PHY;
e1000_release_phy_80003es2lan(hw);
goto out;
return -E1000_ERR_PHY;
}
usec_delay(200);
@ -549,7 +530,6 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
e1000_release_phy_80003es2lan(hw);
out:
return ret_val;
}
@ -572,14 +552,13 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000_acquire_phy_80003es2lan(hw);
if (ret_val)
goto out;
return ret_val;
/* Select Configuration Page */
if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
page_select = GG82563_PHY_PAGE_SELECT;
} else {
/*
* Use Alternative Page Select register to access
/* Use Alternative Page Select register to access
* registers 30 and 31
*/
page_select = GG82563_PHY_PAGE_SELECT_ALT;
@ -589,12 +568,11 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
if (ret_val) {
e1000_release_phy_80003es2lan(hw);
goto out;
return ret_val;
}
if (hw->dev_spec._80003es2lan.mdic_wa_enable == TRUE) {
/*
* The "ready" bit in the MDIC register may be incorrectly set
if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
/* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
@ -604,9 +582,8 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
ret_val = -E1000_ERR_PHY;
e1000_release_phy_80003es2lan(hw);
goto out;
return -E1000_ERR_PHY;
}
usec_delay(200);
@ -624,7 +601,6 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
e1000_release_phy_80003es2lan(hw);
out:
return ret_val;
}
@ -655,7 +631,6 @@ static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
{
s32 timeout = PHY_CFG_TIMEOUT;
s32 ret_val = E1000_SUCCESS;
u32 mask = E1000_NVM_CFG_DONE_PORT_0;
DEBUGFUNC("e1000_get_cfg_done_80003es2lan");
@ -671,12 +646,10 @@ static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
}
if (!timeout) {
DEBUGOUT("MNG configuration cycle has not completed.\n");
ret_val = -E1000_ERR_RESET;
goto out;
return -E1000_ERR_RESET;
}
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -688,33 +661,32 @@ out:
**/
static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
u16 phy_data;
bool link;
DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan");
if (!(hw->phy.ops.read_reg))
goto out;
return E1000_SUCCESS;
/*
* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
/* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
* forced whenever speed and duplex are forced.
*/
ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
goto out;
return ret_val;
phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
if (ret_val)
goto out;
return ret_val;
DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
goto out;
return ret_val;
e1000_phy_force_speed_duplex_setup(hw, &phy_data);
@ -723,7 +695,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
if (ret_val)
goto out;
return ret_val;
usec_delay(1);
@ -733,32 +705,30 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
goto out;
return ret_val;
if (!link) {
/*
* We didn't get link.
/* We didn't get link.
* Reset the DSP and cross our fingers.
*/
ret_val = e1000_phy_reset_dsp_generic(hw);
if (ret_val)
goto out;
return ret_val;
}
/* Try once more */
ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
if (ret_val)
goto out;
return ret_val;
}
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
&phy_data);
if (ret_val)
goto out;
return ret_val;
/*
* Resetting the phy means we need to verify the TX_CLK corresponds
/* Resetting the phy means we need to verify the TX_CLK corresponds
* to the link speed. 10Mbps -> 2.5MHz, else 25MHz.
*/
phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
@ -767,15 +737,13 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
else
phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
/*
* In addition, we must re-enable CRS on Tx for both half and full
/* In addition, we must re-enable CRS on Tx for both half and full
* duplex.
*/
phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
phy_data);
out:
return ret_val;
}
@ -789,32 +757,29 @@ out:
static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
u16 phy_data, index;
DEBUGFUNC("e1000_get_cable_length_80003es2lan");
if (!(hw->phy.ops.read_reg))
goto out;
return E1000_SUCCESS;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
if (ret_val)
goto out;
return ret_val;
index = phy_data & GG82563_DSPD_CABLE_LENGTH;
if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) {
ret_val = -E1000_ERR_PHY;
goto out;
}
if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5)
return -E1000_ERR_PHY;
phy->min_cable_length = e1000_gg82563_cable_length_table[index];
phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -855,11 +820,11 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
u16 kum_reg_data;
DEBUGFUNC("e1000_reset_hw_80003es2lan");
/*
* Prevent the PCI-E bus from sticking if there is no TLP connection
/* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = e1000_disable_pcie_master_generic(hw);
@ -878,23 +843,30 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
ctrl = E1000_READ_REG(hw, E1000_CTRL);
ret_val = e1000_acquire_phy_80003es2lan(hw);
if (ret_val)
return ret_val;
DEBUGOUT("Issuing a global reset to MAC\n");
E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
e1000_release_phy_80003es2lan(hw);
/* Disable IBIST slave mode (far-end loopback) */
e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
&kum_reg_data);
kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
kum_reg_data);
ret_val = e1000_get_auto_rd_done_generic(hw);
if (ret_val)
/* We don't want to continue accessing MAC registers. */
goto out;
return ret_val;
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
E1000_READ_REG(hw, E1000_ICR);
ret_val = e1000_check_alt_mac_addr_generic(hw);
out:
return ret_val;
return e1000_check_alt_mac_addr_generic(hw);
}
/**
@ -917,9 +889,9 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
/* Initialize identification LED */
ret_val = mac->ops.id_led_init(hw);
/* An error is not fatal and we should not stop init due to this */
if (ret_val)
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
/* Disabling VLAN filtering */
DEBUGOUT("Initializing the IEEE VLAN\n");
@ -935,6 +907,8 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
/* Setup link and flow control */
ret_val = mac->ops.setup_link(hw);
if (ret_val)
return ret_val;
/* Disable IBIST slave mode (far-end loopback) */
e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
@ -945,14 +919,14 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
/* Set the transmit descriptor write-back policy */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
/* ...for both queues. */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
/* Enable retransmit on late collisions */
@ -979,18 +953,16 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
/* default to TRUE to enable the MDIC W/A */
hw->dev_spec._80003es2lan.mdic_wa_enable = TRUE;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET >>
E1000_KMRNCTRLSTA_OFFSET_SHIFT,
&i);
ret_val =
e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >>
E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i);
if (!ret_val) {
if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
hw->dev_spec._80003es2lan.mdic_wa_enable = FALSE;
}
/*
* Clear all of the statistics registers (clear on read). It is
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
@ -1037,6 +1009,13 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
reg |= (1 << 28);
E1000_WRITE_REG(hw, E1000_TARC(1), reg);
/* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
reg = E1000_READ_REG(hw, E1000_RFCTL);
reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
E1000_WRITE_REG(hw, E1000_RFCTL, reg);
return;
}
@ -1050,14 +1029,14 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
u32 ctrl_ext;
u32 reg;
u16 data;
DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
if (ret_val)
goto out;
return ret_val;
data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
@ -1065,10 +1044,9 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
if (ret_val)
goto out;
return ret_val;
/*
* Options:
/* Options:
* MDI/MDI-X = 0 (default)
* 0 - Auto for all speeds
* 1 - MDI mode
@ -1077,7 +1055,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
*/
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
if (ret_val)
goto out;
return ret_val;
data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
@ -1094,8 +1072,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
break;
}
/*
* Options:
/* Options:
* disable_polarity_correction = 0 (default)
* Automatic Correction for Reversed Cable Polarity
* 0 - Disabled
@ -1107,90 +1084,86 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data);
if (ret_val)
goto out;
return ret_val;
/* SW Reset the PHY so all changes take effect */
ret_val = hw->phy.ops.commit(hw);
if (ret_val) {
DEBUGOUT("Error Resetting the PHY\n");
goto out;
return ret_val;
}
/* Bypass Rx and Tx FIFO's */
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL;
data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
if (ret_val)
goto out;
return ret_val;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, &data);
reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data);
if (ret_val)
goto out;
return ret_val;
data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, data);
ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
if (ret_val)
goto out;
return ret_val;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
if (ret_val)
goto out;
return ret_val;
data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
if (ret_val)
goto out;
return ret_val;
ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
ctrl_ext &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
if (ret_val)
goto out;
return ret_val;
/*
* Do not init these registers when the HW is in IAMT mode, since the
/* Do not init these registers when the HW is in IAMT mode, since the
* firmware will have already initialized them. We only initialize
* them if the HW is not in IAMT mode.
*/
if (!(hw->mac.ops.check_mng_mode(hw))) {
if (!hw->mac.ops.check_mng_mode(hw)) {
/* Enable Electrical Idle on the PHY */
data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
data);
if (ret_val)
goto out;
return ret_val;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
&data);
if (ret_val)
goto out;
return ret_val;
data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
data);
if (ret_val)
goto out;
return ret_val;
}
/*
* Workaround: Disable padding in Kumeran interface in the MAC
/* Workaround: Disable padding in Kumeran interface in the MAC
* and in the PHY to avoid CRC errors.
*/
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
if (ret_val)
goto out;
return ret_val;
data |= GG82563_ICR_DIS_PADDING;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
if (ret_val)
goto out;
return ret_val;
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -1213,42 +1186,42 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
/*
* Set the mac to wait the maximum time between each
/* Set the mac to wait the maximum time between each
* iteration and increase the max iterations when
* polling the phy; this fixes erroneous timeouts at 10Mbps.
*/
ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
0xFFFF);
if (ret_val)
goto out;
return ret_val;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
&reg_data);
if (ret_val)
goto out;
return ret_val;
reg_data |= 0x3F;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
reg_data);
if (ret_val)
goto out;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, &reg_data);
return ret_val;
ret_val =
e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
&reg_data);
if (ret_val)
goto out;
return ret_val;
reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, reg_data);
ret_val =
e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
reg_data);
if (ret_val)
goto out;
return ret_val;
ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw);
if (ret_val)
goto out;
return ret_val;
ret_val = e1000_setup_copper_link_generic(hw);
out:
return ret_val;
return e1000_setup_copper_link_generic(hw);
}
/**
@ -1271,7 +1244,7 @@ static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
ret_val = e1000_get_speed_and_duplex_copper_generic(hw, &speed,
&duplex);
if (ret_val)
goto out;
return ret_val;
if (speed == SPEED_1000)
ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
@ -1279,7 +1252,6 @@ static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
}
out:
return ret_val;
}
@ -1293,7 +1265,7 @@ out:
**/
static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
{
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
u32 tipg;
u32 i = 0;
u16 reg_data, reg_data2;
@ -1301,11 +1273,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
DEBUGFUNC("e1000_configure_kmrn_for_10_100");
reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
reg_data);
ret_val =
e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
reg_data);
if (ret_val)
goto out;
return ret_val;
/* Configure Transmit Inter-Packet Gap */
tipg = E1000_READ_REG(hw, E1000_TIPG);
@ -1317,12 +1290,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
&reg_data);
if (ret_val)
goto out;
return ret_val;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
&reg_data2);
if (ret_val)
goto out;
return ret_val;
i++;
} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
@ -1331,11 +1304,7 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
else
reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
reg_data);
out:
return ret_val;
return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
}
/**
@ -1347,7 +1316,7 @@ out:
**/
static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
u16 reg_data, reg_data2;
u32 tipg;
u32 i = 0;
@ -1355,10 +1324,12 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_configure_kmrn_for_1000");
reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data);
ret_val =
e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
reg_data);
if (ret_val)
goto out;
return ret_val;
/* Configure Transmit Inter-Packet Gap */
tipg = E1000_READ_REG(hw, E1000_TIPG);
@ -1370,21 +1341,18 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
&reg_data);
if (ret_val)
goto out;
return ret_val;
ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
&reg_data2);
if (ret_val)
goto out;
return ret_val;
i++;
} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
reg_data);
out:
return ret_val;
return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
}
/**
@ -1401,13 +1369,13 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
u16 *data)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan");
ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
if (ret_val)
goto out;
return ret_val;
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
@ -1421,7 +1389,6 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
e1000_release_mac_csr_80003es2lan(hw);
out:
return ret_val;
}
@ -1439,13 +1406,13 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
u16 data)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan");
ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
if (ret_val)
goto out;
return ret_val;
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
E1000_KMRNCTRLSTA_OFFSET) | data;
@ -1456,7 +1423,6 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
e1000_release_mac_csr_80003es2lan(hw);
out:
return ret_val;
}
@ -1466,23 +1432,19 @@ out:
**/
static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
/*
* If there's an alternate MAC address place it in RAR0
/* If there's an alternate MAC address place it in RAR0
* so that it will override the Si installed default perm
* address.
*/
ret_val = e1000_check_alt_mac_addr_generic(hw);
if (ret_val)
goto out;
return ret_val;
ret_val = e1000_read_mac_addr_generic(hw);
out:
return ret_val;
return e1000_read_mac_addr_generic(hw);
}
/**

View file

@ -1,6 +1,6 @@
/******************************************************************************
Copyright (c) 2001-2011, Intel Corporation
Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -51,34 +51,32 @@
#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C
#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004
#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gig Carry Extend Padding */
#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000
#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8
#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9
/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Disabled */
#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Dis */
#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060
#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */
#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */
#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */
/* PHY Specific Control Register 2 (Page 0, Register 26) */
#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Nego */
#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Neg */
/* MAC Specific Control Register (Page 2, Register 21) */
/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
#define GG82563_MSCR_TX_CLK_MASK 0x0007
#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004
#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005
#define GG82563_MSCR_TX_CLK_1000MBPS_2_5 0x0006
#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007
#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */
/* DSP Distance Register (Page 5, Register 26) */
/*
/* DSP Distance Register (Page 5, Register 26)
* 0 = <50M
* 1 = 50-80M
* 2 = 80-100M

View file

@ -927,9 +927,9 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
}
for (i = 0; i < words; i++) {
eewr = (data[i] << E1000_NVM_RW_REG_DATA) |
((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
E1000_NVM_RW_REG_START;
eewr = ((data[i] << E1000_NVM_RW_REG_DATA) |
((offset + i) << E1000_NVM_RW_ADDR_SHIFT) |
E1000_NVM_RW_REG_START);
ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE);
if (ret_val)
@ -1101,8 +1101,6 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
default:
break;
}
if (ret_val)
DEBUGOUT("Cannot acquire MDIO ownership\n");
ctrl = E1000_READ_REG(hw, E1000_CTRL);
@ -1111,9 +1109,16 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
/* Must release MDIO ownership and mutex after MAC reset. */
switch (hw->mac.type) {
case e1000_82573:
/* Release mutex only if the hw semaphore is acquired */
if (!ret_val)
e1000_put_hw_semaphore_82573(hw);
break;
case e1000_82574:
case e1000_82583:
e1000_put_hw_semaphore_82574(hw);
/* Release mutex only if the hw semaphore is acquired */
if (!ret_val)
e1000_put_hw_semaphore_82574(hw);
break;
default:
break;
@ -1222,8 +1227,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
/* Set the transmit descriptor write-back policy */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
/* ...for both queues. */
@ -1239,9 +1244,9 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
break;
default:
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB |
E1000_TXDCTL_COUNT_DESC;
reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB |
E1000_TXDCTL_COUNT_DESC);
E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
break;
}

View file

@ -52,6 +52,7 @@ static void e1000_release_phy_82575(struct e1000_hw *hw);
static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw);
static void e1000_release_nvm_82575(struct e1000_hw *hw);
static s32 e1000_check_for_link_82575(struct e1000_hw *hw);
static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw);
static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw);
static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
u16 *duplex);
@ -144,6 +145,7 @@ static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
break;
case e1000_82580:
case e1000_i350:
case e1000_i354:
case e1000_i210:
case e1000_i211:
reg = E1000_READ_REG(hw, E1000_MDICNFG);
@ -207,6 +209,7 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
switch (hw->mac.type) {
case e1000_82580:
case e1000_i350:
case e1000_i354:
phy->ops.read_reg = e1000_read_phy_reg_82580;
phy->ops.write_reg = e1000_write_phy_reg_82580;
break;
@ -226,6 +229,8 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
/* Verify phy id and set remaining function pointers */
switch (phy->id) {
case M88E1543_E_PHY_ID:
case M88E1512_E_PHY_ID:
case I347AT4_E_PHY_ID:
case M88E1112_E_PHY_ID:
case M88E1340M_E_PHY_ID:
@ -238,9 +243,36 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
phy->id == M88E1340M_E_PHY_ID)
phy->ops.get_cable_length =
e1000_get_cable_length_m88_gen2;
else if (phy->id == M88E1543_E_PHY_ID ||
phy->id == M88E1512_E_PHY_ID)
phy->ops.get_cable_length =
e1000_get_cable_length_m88_gen2;
else
phy->ops.get_cable_length = e1000_get_cable_length_m88;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
/* Check if this PHY is confgured for media swap. */
if (phy->id == M88E1112_E_PHY_ID) {
u16 data;
ret_val = phy->ops.write_reg(hw,
E1000_M88E1112_PAGE_ADDR,
2);
if (ret_val)
goto out;
ret_val = phy->ops.read_reg(hw,
E1000_M88E1112_MAC_CTRL_1,
&data);
if (ret_val)
goto out;
data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >>
E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT;
if (data == E1000_M88E1112_AUTO_COPPER_SGMII ||
data == E1000_M88E1112_AUTO_COPPER_BASEX)
hw->mac.ops.check_for_link =
e1000_check_for_link_media_swap;
}
break;
case IGP03E1000_E_PHY_ID:
case IGP04E1000_E_PHY_ID:
@ -355,6 +387,7 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
nvm->ops.update = e1000_update_nvm_checksum_82580;
break;
case e1000_i350:
case e1000_i354:
nvm->ops.validate = e1000_validate_nvm_checksum_i350;
nvm->ops.update = e1000_update_nvm_checksum_i350;
break;
@ -388,7 +421,7 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
if (mac->type == e1000_82580)
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
if (mac->type == e1000_i350)
if (mac->type == e1000_i350 || mac->type == e1000_i354)
mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
/* Enable EEE default settings for EEE supported devices */
@ -436,7 +469,7 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
/* multicast address update */
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
if (mac->type == e1000_i350) {
if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) {
/* writing VFTA */
mac->ops.write_vfta = e1000_write_vfta_i350;
/* clearing VFTA */
@ -622,6 +655,10 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_get_phy_id_82575");
/* some i354 devices need an extra read for phy id */
if (hw->mac.type == e1000_i354)
e1000_get_phy_id(hw);
/*
* For SGMII PHYs, we try the list of possible addresses until
* we find one that works. For non-SGMII PHYs
@ -645,6 +682,7 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
break;
case e1000_82580:
case e1000_i350:
case e1000_i354:
case e1000_i210:
case e1000_i211:
mdic = E1000_READ_REG(hw, E1000_MDICNFG);
@ -1172,6 +1210,61 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
return ret_val;
}
/**
* e1000_check_for_link_media_swap - Check which M88E1112 interface linked
* @hw: pointer to the HW structure
*
* Poll the M88E1112 interfaces to see which interface achieved link.
*/
static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
u16 data;
u8 port = 0;
DEBUGFUNC("e1000_check_for_link_media_swap");
/* Check the copper medium. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
if (ret_val)
return ret_val;
ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
if (ret_val)
return ret_val;
if (data & E1000_M88E1112_STATUS_LINK)
port = E1000_MEDIA_PORT_COPPER;
/* Check the other medium. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1);
if (ret_val)
return ret_val;
ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
if (ret_val)
return ret_val;
/* reset page to 0 */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
if (ret_val)
return ret_val;
if (data & E1000_M88E1112_STATUS_LINK)
port = E1000_MEDIA_PORT_OTHER;
/* Determine if a swap needs to happen. */
if (port && (hw->dev_spec._82575.media_port != port)) {
hw->dev_spec._82575.media_port = port;
hw->dev_spec._82575.media_changed = TRUE;
} else {
ret_val = e1000_check_for_link_82575(hw);
}
return E1000_SUCCESS;
}
/**
* e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown
* @hw: pointer to the HW structure
@ -1215,6 +1308,7 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
{
struct e1000_mac_info *mac = &hw->mac;
u32 pcs;
u32 status;
DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
@ -1245,6 +1339,18 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
else
*duplex = HALF_DUPLEX;
/* Check if it is an I354 2.5Gb backplane connection. */
if (mac->type == e1000_i354) {
status = E1000_READ_REG(hw, E1000_STATUS);
if ((status & E1000_STATUS_2P5_SKU) &&
!(status & E1000_STATUS_2P5_SKU_OVER)) {
*speed = SPEED_2500;
*duplex = FULL_DUPLEX;
DEBUGOUT("2500 Mbs, ");
DEBUGOUT("Full Duplex\n");
}
}
} else {
mac->serdes_has_link = FALSE;
*speed = 0;
@ -1430,11 +1536,18 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
/* Clear Go Link Disconnect bit */
if (hw->mac.type >= e1000_82580) {
/* Clear Go Link Disconnect bit on supported devices */
switch (hw->mac.type) {
case e1000_82580:
case e1000_i350:
case e1000_i210:
case e1000_i211:
phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
phpm_reg &= ~E1000_82580_PM_GO_LINKD;
E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
break;
default:
break;
}
ret_val = e1000_setup_serdes_link_82575(hw);
@ -1458,6 +1571,8 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
case I347AT4_E_PHY_ID:
case M88E1112_E_PHY_ID:
case M88E1340M_E_PHY_ID:
case M88E1543_E_PHY_ID:
case M88E1512_E_PHY_ID:
case I210_I_PHY_ID:
ret_val = e1000_copper_link_setup_m88_gen2(hw);
break;
@ -2132,42 +2247,33 @@ out:
**/
void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
{
u32 dtxswc;
u32 reg_val, reg_offset;
switch (hw->mac.type) {
case e1000_82576:
dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
if (enable) {
dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
/* The PF can spoof - it has to in order to
* support emulation mode NICs */
dtxswc ^= (1 << pf | 1 << (pf +
E1000_DTXSWC_VLAN_SPOOF_SHIFT));
} else {
dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
}
E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
reg_offset = E1000_DTXSWC;
break;
case e1000_i350:
dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
if (enable) {
dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
/* The PF can spoof - it has to in order to
* support emulation mode NICs
*/
dtxswc ^= (1 << pf | 1 << (pf +
E1000_DTXSWC_VLAN_SPOOF_SHIFT));
} else {
dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
}
E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
default:
case e1000_i354:
reg_offset = E1000_TXSWC;
break;
default:
return;
}
reg_val = E1000_READ_REG(hw, reg_offset);
if (enable) {
reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
/* The PF can spoof - it has to in order to
* support emulation mode NICs
*/
reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
} else {
reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
E1000_DTXSWC_VLAN_SPOOF_MASK);
}
E1000_WRITE_REG(hw, reg_offset, reg_val);
}
/**
@ -2191,6 +2297,7 @@ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
break;
case e1000_i350:
case e1000_i354:
dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
if (enable)
dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
@ -2387,10 +2494,6 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
DEBUGOUT("Auto Read Done did not complete\n");
}
/* If EEPROM is not present, run manual init scripts */
if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
e1000_reset_init_script_82575(hw);
/* clear global device reset status bit */
E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET);
@ -2644,6 +2747,45 @@ out:
return ret_val;
}
/**
* __e1000_access_emi_reg - Read/write EMI register
* @hw: pointer to the HW structure
* @addr: EMI address to program
* @data: pointer to value to read/write from/to the EMI address
* @read: boolean flag to indicate read or write
**/
static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address,
u16 *data, bool read)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("__e1000_access_emi_reg");
ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address);
if (ret_val)
return ret_val;
if (read)
ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data);
else
ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data);
return ret_val;
}
/**
* e1000_read_emi_reg - Read Extended Management Interface register
* @hw: pointer to the HW structure
* @addr: EMI address to program
* @data: value to be read from the EMI address
**/
s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data)
{
DEBUGFUNC("e1000_read_emi_reg");
return __e1000_access_emi_reg(hw, addr, data, TRUE);
}
/**
* e1000_set_eee_i350 - Enable/disable EEE support
* @hw: pointer to the HW structure
@ -2689,6 +2831,114 @@ out:
return ret_val;
}
/**
* e1000_set_eee_i354 - Enable/disable EEE support
* @hw: pointer to the HW structure
*
* Enable/disable EEE legacy mode based on setting in dev_spec structure.
*
**/
s32 e1000_set_eee_i354(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
u16 phy_data;
DEBUGFUNC("e1000_set_eee_i354");
if ((hw->phy.media_type != e1000_media_type_copper) ||
((phy->id != M88E1543_E_PHY_ID) &&
(phy->id != M88E1512_E_PHY_ID)))
goto out;
if (!hw->dev_spec._82575.eee_disable) {
/* Switch to PHY page 18. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18);
if (ret_val)
goto out;
ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1,
&phy_data);
if (ret_val)
goto out;
phy_data |= E1000_M88E1543_EEE_CTRL_1_MS;
ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1,
phy_data);
if (ret_val)
goto out;
/* Return the PHY to page 0. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
if (ret_val)
goto out;
/* Turn on EEE advertisement. */
ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
E1000_EEE_ADV_DEV_I354,
&phy_data);
if (ret_val)
goto out;
phy_data |= E1000_EEE_ADV_100_SUPPORTED |
E1000_EEE_ADV_1000_SUPPORTED;
ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
E1000_EEE_ADV_DEV_I354,
phy_data);
} else {
/* Turn off EEE advertisement. */
ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
E1000_EEE_ADV_DEV_I354,
&phy_data);
if (ret_val)
goto out;
phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED |
E1000_EEE_ADV_1000_SUPPORTED);
ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
E1000_EEE_ADV_DEV_I354,
phy_data);
}
out:
return ret_val;
}
/**
* e1000_get_eee_status_i354 - Get EEE status
* @hw: pointer to the HW structure
* @status: EEE status
*
* Get EEE status by guessing based on whether Tx or Rx LPI indications have
* been received.
**/
s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
u16 phy_data;
DEBUGFUNC("e1000_get_eee_status_i354");
/* Check if EEE is supported on this device. */
if ((hw->phy.media_type != e1000_media_type_copper) ||
((phy->id != M88E1543_E_PHY_ID) &&
(phy->id != M88E1512_E_PHY_ID)))
goto out;
ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354,
E1000_PCS_STATUS_DEV_I354,
&phy_data);
if (ret_val)
goto out;
*status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD |
E1000_PCS_STATUS_RX_LPI_RCVD) ? TRUE : FALSE;
out:
return ret_val;
}
/* Due to a hw errata, if the host tries to configure the VFTA register
* while performing queries from the BMC or DMA, then the VFTA in some
* cases won't be written.
@ -3286,4 +3536,3 @@ void e1000_i2c_bus_clear(struct e1000_hw *hw)
e1000_i2c_stop(hw);
}

View file

@ -245,6 +245,8 @@ union e1000_adv_rx_desc {
#define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009
/* RSS Packet Types as indicated in the receive descriptor */
#define E1000_RXDADV_PKTTYPE_ILMASK 0x000000F0
#define E1000_RXDADV_PKTTYPE_TLMASK 0x00000F00
#define E1000_RXDADV_PKTTYPE_NONE 0x00000000
#define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */
#define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */
@ -491,7 +493,10 @@ void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
u16 e1000_rxpbs_adjust_82580(u32 data);
s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data);
s32 e1000_set_eee_i350(struct e1000_hw *);
s32 e1000_set_eee_i354(struct e1000_hw *);
s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *);
/* I2C SDA and SCL timing parameters for standard mode */
#define E1000_I2C_T_HD_STA 4

View file

@ -329,9 +329,8 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_I350_DA4:
mac->type = e1000_i350;
break;
#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW)
case E1000_DEV_ID_I210_NVMLESS:
#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */
case E1000_DEV_ID_I210_COPPER_FLASHLESS:
case E1000_DEV_ID_I210_SERDES_FLASHLESS:
case E1000_DEV_ID_I210_COPPER:
case E1000_DEV_ID_I210_COPPER_OEM1:
case E1000_DEV_ID_I210_COPPER_IT:
@ -352,6 +351,11 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
mac->type = e1000_vfadapt_i350;
break;
case E1000_DEV_ID_I354_BACKPLANE_1GBPS:
case E1000_DEV_ID_I354_SGMII:
case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS:
mac->type = e1000_i354;
break;
default:
/* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT;
@ -447,6 +451,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_82576:
case e1000_82580:
case e1000_i350:
case e1000_i354:
e1000_init_function_pointers_82575(hw);
break;
case e1000_i210:

View file

@ -43,6 +43,8 @@
/* Wake Up Control */
#define E1000_WUC_APME 0x00000001 /* APM Enable */
#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */
/* Wake Up Filter Control */
@ -287,7 +289,10 @@
#define E1000_CONNSW_ENRGSRC 0x4
#define E1000_CONNSW_PHYSD 0x400
#define E1000_CONNSW_PHY_PDN 0x800
#define E1000_CONNSW_SERDESD 0x200
#define E1000_CONNSW_AUTOSENSE_CONF 0x2
#define E1000_CONNSW_AUTOSENSE_EN 0x1
#define E1000_PCS_CFG_PCS_EN 8
#define E1000_PCS_LCTL_FLV_LINK_UP 1
#define E1000_PCS_LCTL_FSV_10 0
@ -325,6 +330,8 @@
#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */
#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
#define E1000_STATUS_2P5_SKU 0x00001000 /* Val of 2.5GBE SKU strap */
#define E1000_STATUS_2P5_SKU_OVER 0x00002000 /* Val of 2.5GBE SKU Over */
#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */
@ -336,6 +343,7 @@
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define SPEED_2500 2500
#define HALF_DUPLEX 1
#define FULL_DUPLEX 2
@ -650,6 +658,7 @@
#define E1000_EITR_ITR_INT_MASK 0x0000FFFF
/* E1000_EITR_CNT_IGNR is only for 82576 and newer */
#define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
#define E1000_EITR_INTERVAL 0x00007FFC
/* Transmit Descriptor Control */
#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
@ -805,6 +814,17 @@
#define E1000_MDICNFG_PHY_MASK 0x03E00000
#define E1000_MDICNFG_PHY_SHIFT 21
#define E1000_MEDIA_PORT_COPPER 1
#define E1000_MEDIA_PORT_OTHER 2
#define E1000_M88E1112_AUTO_COPPER_SGMII 0x2
#define E1000_M88E1112_AUTO_COPPER_BASEX 0x3
#define E1000_M88E1112_STATUS_LINK 0x0004 /* Interface Link Bit */
#define E1000_M88E1112_MAC_CTRL_1 0x10
#define E1000_M88E1112_MAC_CTRL_1_MODE_MASK 0x0380 /* Mode Select */
#define E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT 7
#define E1000_M88E1112_PAGE_ADDR 0x16
#define E1000_M88E1112_STATUS 0x01
#define E1000_THSTAT_LOW_EVENT 0x20000000 /* Low thermal threshold */
#define E1000_THSTAT_MID_EVENT 0x00200000 /* Mid thermal threshold */
#define E1000_THSTAT_HIGH_EVENT 0x00002000 /* High thermal threshold */
@ -821,7 +841,21 @@
#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
#define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */
#define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */
#define E1000_EEE_LP_ADV_ADDR_I350 0x040F /* EEE LP Advertisement */
#define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */
#define E1000_M88E1543_EEE_CTRL_1 0x0
#define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */
#define E1000_EEE_ADV_DEV_I354 7
#define E1000_EEE_ADV_ADDR_I354 60
#define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */
#define E1000_EEE_ADV_1000_SUPPORTED (1 << 2) /* 1000BaseT EEE Supported */
#define E1000_PCS_STATUS_DEV_I354 3
#define E1000_PCS_STATUS_ADDR_I354 1
#define E1000_PCS_STATUS_RX_LPI_RCVD 0x0400
#define E1000_PCS_STATUS_TX_LPI_RCVD 0x0800
#define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */
#define E1000_EEE_LP_ADV_DEV_I210 7 /* EEE LP Adv Device */
#define E1000_EEE_LP_ADV_ADDR_I210 61 /* EEE LP Adv Register */
/* PCI Express Control */
#define E1000_GCR_RXD_NO_SNOOP 0x00000001
#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
@ -841,6 +875,8 @@
E1000_GCR_TXDSCW_NO_SNOOP | \
E1000_GCR_TXDSCR_NO_SNOOP)
#define E1000_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */
/* mPHY address control and data registers */
#define E1000_MPHY_ADDR_CTL 0x0024 /* Address Control Reg */
#define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000
@ -1169,6 +1205,8 @@
#define M88E1011_I_PHY_ID 0x01410C20
#define IGP01E1000_I_PHY_ID 0x02A80380
#define M88E1111_I_PHY_ID 0x01410CC0
#define M88E1543_E_PHY_ID 0x01410EA0
#define M88E1512_E_PHY_ID 0x01410DD0
#define M88E1112_E_PHY_ID 0x01410C90
#define I347AT4_E_PHY_ID 0x01410DC0
#define M88E1340M_E_PHY_ID 0x01410DF0
@ -1416,4 +1454,6 @@
/* Lan ID bit field offset in status register */
#define E1000_STATUS_LAN_ID_OFFSET 2
#define E1000_VFTA_ENTRIES 128
#define E1000_UNUSEDARG
#define ERROR_REPORT(fmt) do { } while (0)
#endif /* _E1000_DEFINES_H_ */

View file

@ -165,7 +165,12 @@ struct e1000_hw;
#define E1000_DEV_ID_I210_FIBER 0x1536
#define E1000_DEV_ID_I210_SERDES 0x1537
#define E1000_DEV_ID_I210_SGMII 0x1538
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
#define E1000_DEV_ID_I211_COPPER 0x1539
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
#define E1000_DEV_ID_I354_SGMII 0x1F41
#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
@ -217,6 +222,7 @@ enum e1000_mac_type {
e1000_82576,
e1000_82580,
e1000_i350,
e1000_i354,
e1000_i210,
e1000_i211,
e1000_vfadapt,
@ -238,6 +244,7 @@ enum e1000_nvm_type {
e1000_nvm_eeprom_spi,
e1000_nvm_eeprom_microwire,
e1000_nvm_flash_hw,
e1000_nvm_invm,
e1000_nvm_flash_sw
};
@ -391,6 +398,10 @@ union e1000_rx_desc_extended {
};
#define MAX_PS_BUFFERS 4
/* Number of packet split data buffers (not including the header buffer) */
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
/* Receive Descriptor - Packet Split */
union e1000_rx_desc_packet_split {
struct {
@ -415,7 +426,8 @@ union e1000_rx_desc_packet_split {
} middle;
struct {
__le16 header_status;
__le16 length[3]; /* length of buffers 1-3 */
/* length of buffers 1-3 */
__le16 length[PS_PAGE_BUFFERS];
} upper;
__le64 reserved;
} wb; /* writeback */
@ -940,6 +952,8 @@ struct e1000_dev_spec_82575 {
bool clear_semaphore_once;
u32 mtu;
struct sfp_e1000_flags eth_flags;
u8 media_port;
bool media_changed;
};
struct e1000_dev_spec_vf {

View file

@ -42,8 +42,6 @@ static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
/**
* e1000_acquire_nvm_i210 - Request for access to EEPROM
@ -180,9 +178,8 @@ static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
}
if (i == timeout) {
/*
* In rare circumstances, the driver may not have released the
* SW semaphore. Clear the semaphore once before giving up.
/* In rare circumstances, the SW semaphore may already be held
* unintentionally. Clear the semaphore once before giving up.
*/
if (hw->dev_spec._82575.clear_semaphore_once) {
hw->dev_spec._82575.clear_semaphore_once = FALSE;
@ -368,87 +365,7 @@ out:
return ret_val;
}
/**
* e1000_read_nvm_i211 - Read NVM wrapper function for I211
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Wrapper function to return data formerly found in the NVM.
**/
static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_nvm_i211");
/* Only the MAC addr is required to be present in the iNVM */
switch (offset) {
case NVM_MAC_ADDR:
ret_val = e1000_read_invm_i211(hw, (u8)offset, &data[0]);
ret_val |= e1000_read_invm_i211(hw, (u8)offset+1, &data[1]);
ret_val |= e1000_read_invm_i211(hw, (u8)offset+2, &data[2]);
if (ret_val != E1000_SUCCESS)
DEBUGOUT("MAC Addr not found in iNVM\n");
break;
case NVM_INIT_CTRL_2:
ret_val = e1000_read_invm_i211(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_2_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_INIT_CTRL_4:
ret_val = e1000_read_invm_i211(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_4_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_1_CFG:
ret_val = e1000_read_invm_i211(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_1_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_0_2_CFG:
ret_val = e1000_read_invm_i211(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_0_2_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_ID_LED_SETTINGS:
ret_val = e1000_read_invm_i211(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = ID_LED_RESERVED_FFFF;
ret_val = E1000_SUCCESS;
}
break;
case NVM_SUB_DEV_ID:
*data = hw->subsystem_device_id;
break;
case NVM_SUB_VEN_ID:
*data = hw->subsystem_vendor_id;
break;
case NVM_DEV_ID:
*data = hw->device_id;
break;
case NVM_VEN_ID:
*data = hw->vendor_id;
break;
default:
DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
*data = NVM_RESERVED_WORD;
break;
}
return ret_val;
}
/**
* e1000_read_invm_i211 - Reads OTP
/** e1000_read_invm_word_i210 - Reads OTP
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
@ -456,14 +373,14 @@ static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset,
* Reads 16-bit words from the OTP. Return error when the word is not
* stored in OTP.
**/
s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data)
static s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
{
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u32 invm_dword;
u16 i;
u8 record_type, word_address;
DEBUGFUNC("e1000_read_invm_i211");
DEBUGFUNC("e1000_read_invm_word_i210");
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
@ -491,6 +408,86 @@ s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data)
return status;
}
/** e1000_read_invm_i210 - Read invm wrapper function for I210/I211
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Wrapper function to return data formerly found in the NVM.
**/
static s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset,
u16 E1000_UNUSEDARG words, u16 *data)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_invm_i210");
/* Only the MAC addr is required to be present in the iNVM */
switch (offset) {
case NVM_MAC_ADDR:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]);
ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1,
&data[1]);
ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2,
&data[2]);
if (ret_val != E1000_SUCCESS)
DEBUGOUT("MAC Addr not found in iNVM\n");
break;
case NVM_INIT_CTRL_2:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_2_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_INIT_CTRL_4:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_4_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_1_CFG:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_1_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_0_2_CFG:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_0_2_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_ID_LED_SETTINGS:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = ID_LED_RESERVED_FFFF;
ret_val = E1000_SUCCESS;
}
break;
case NVM_SUB_DEV_ID:
*data = hw->subsystem_device_id;
break;
case NVM_SUB_VEN_ID:
*data = hw->subsystem_vendor_id;
break;
case NVM_DEV_ID:
*data = hw->device_id;
break;
case NVM_VEN_ID:
*data = hw->vendor_id;
break;
default:
DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
*data = NVM_RESERVED_WORD;
break;
}
return ret_val;
}
/**
* e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum
* @hw: pointer to the HW structure
@ -591,6 +588,26 @@ out:
return ret_val;
}
/**
* e1000_get_flash_presence_i210 - Check if flash device is detected.
* @hw: pointer to the HW structure
*
**/
bool e1000_get_flash_presence_i210(struct e1000_hw *hw)
{
u32 eec = 0;
bool ret_val = FALSE;
DEBUGFUNC("e1000_get_flash_presence_i210");
eec = E1000_READ_REG(hw, E1000_EECD);
if (eec & E1000_EECD_FLASH_DETECTED_I210)
ret_val = TRUE;
return ret_val;
}
/**
* e1000_update_flash_i210 - Commit EEPROM to the flash
* @hw: pointer to the HW structure
@ -650,7 +667,7 @@ s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
* e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers
* @hw: pointer to the HW structure
*
* Initialize the i210 NVM parameters and function pointers.
* Initialize the i210/i211 NVM parameters and function pointers.
**/
static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
{
@ -660,41 +677,25 @@ static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_i210");
ret_val = e1000_init_nvm_params_82575(hw);
nvm->ops.acquire = e1000_acquire_nvm_i210;
nvm->ops.release = e1000_release_nvm_i210;
nvm->ops.read = e1000_read_nvm_srrd_i210;
nvm->ops.write = e1000_write_nvm_srwr_i210;
nvm->ops.valid_led_default = e1000_valid_led_default_i210;
nvm->ops.validate = e1000_validate_nvm_checksum_i210;
nvm->ops.update = e1000_update_nvm_checksum_i210;
if (e1000_get_flash_presence_i210(hw)) {
hw->nvm.type = e1000_nvm_flash_hw;
nvm->ops.read = e1000_read_nvm_srrd_i210;
nvm->ops.write = e1000_write_nvm_srwr_i210;
nvm->ops.validate = e1000_validate_nvm_checksum_i210;
nvm->ops.update = e1000_update_nvm_checksum_i210;
} else {
hw->nvm.type = e1000_nvm_invm;
nvm->ops.read = e1000_read_invm_i210;
nvm->ops.write = e1000_null_write_nvm;
nvm->ops.validate = e1000_null_ops_generic;
nvm->ops.update = e1000_null_ops_generic;
}
return ret_val;
}
/**
* e1000_init_nvm_params_i211 - Initialize i211 NVM function pointers
* @hw: pointer to the HW structure
*
* Initialize the NVM parameters and function pointers for i211.
**/
static s32 e1000_init_nvm_params_i211(struct e1000_hw *hw)
{
struct e1000_nvm_info *nvm = &hw->nvm;
DEBUGFUNC("e1000_init_nvm_params_i211");
nvm->ops.acquire = e1000_acquire_nvm_i210;
nvm->ops.release = e1000_release_nvm_i210;
nvm->ops.read = e1000_read_nvm_i211;
nvm->ops.valid_led_default = e1000_valid_led_default_i210;
nvm->ops.write = e1000_null_write_nvm;
nvm->ops.validate = e1000_null_ops_generic;
nvm->ops.update = e1000_null_ops_generic;
return E1000_SUCCESS;
}
/**
* e1000_init_function_pointers_i210 - Init func ptrs.
* @hw: pointer to the HW structure
@ -704,17 +705,8 @@ static s32 e1000_init_nvm_params_i211(struct e1000_hw *hw)
void e1000_init_function_pointers_i210(struct e1000_hw *hw)
{
e1000_init_function_pointers_82575(hw);
hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
switch (hw->mac.type) {
case e1000_i210:
hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
break;
case e1000_i211:
hw->nvm.ops.init_params = e1000_init_nvm_params_i211;
break;
default:
break;
}
return;
}
@ -752,3 +744,74 @@ static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
out:
return ret_val;
}
/**
* __e1000_access_xmdio_reg - Read/write XMDIO register
* @hw: pointer to the HW structure
* @address: XMDIO address to program
* @dev_addr: device address to program
* @data: pointer to value to read/write from/to the XMDIO address
* @read: boolean flag to indicate read or write
**/
static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address,
u8 dev_addr, u16 *data, bool read)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("__e1000_access_xmdio_reg");
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
if (ret_val)
return ret_val;
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
if (ret_val)
return ret_val;
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
dev_addr);
if (ret_val)
return ret_val;
if (read)
ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
else
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
if (ret_val)
return ret_val;
/* Recalibrate the device back to 0 */
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
if (ret_val)
return ret_val;
return ret_val;
}
/**
* e1000_read_xmdio_reg - Read XMDIO register
* @hw: pointer to the HW structure
* @addr: XMDIO address to program
* @dev_addr: device address to program
* @data: value to be read from the EMI address
**/
s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
{
DEBUGFUNC("e1000_read_xmdio_reg");
return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, TRUE);
}
/**
* e1000_write_xmdio_reg - Write XMDIO register
* @hw: pointer to the HW structure
* @addr: XMDIO address to program
* @dev_addr: device address to program
* @data: value to be written to the XMDIO address
**/
s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
{
DEBUGFUNC("e1000_read_xmdio_reg");
return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, FALSE);
}

View file

@ -35,6 +35,7 @@
#ifndef _E1000_I210_H_
#define _E1000_I210_H_
bool e1000_get_flash_presence_i210(struct e1000_hw *hw);
s32 e1000_update_flash_i210(struct e1000_hw *hw);
s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw);
s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw);
@ -42,9 +43,12 @@ s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data);
s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
u16 *data);
s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
u16 data);
#define E1000_STM_OPCODE 0xDB00
#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
@ -82,7 +86,7 @@ enum E1000_INVM_STRUCTURE_TYPE {
(ID_LED_OFF1_OFF2))
#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_DEF1_DEF2))
(ID_LED_OFF1_ON2))
/* NVM offset defaults for I211 devices */
#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243

View file

@ -59,6 +59,10 @@
* 82578DC Gigabit Network Connection
* 82579LM Gigabit Network Connection
* 82579V Gigabit Network Connection
* Ethernet Connection I217-LM
* Ethernet Connection I217-V
* Ethernet Connection I218-V
* Ethernet Connection I218-LM
*/
#include "e1000_api.h"
@ -71,6 +75,7 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw);
static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
u8 *mc_addr_list,
u32 mc_addr_count);
@ -181,8 +186,9 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
{
u16 phy_reg = 0;
u32 phy_id = 0;
s32 ret_val;
s32 ret_val = 0;
u16 retry_count;
u32 mac_reg = 0;
for (retry_count = 0; retry_count < 2; retry_count++) {
ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_reg);
@ -201,23 +207,84 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
if (hw->phy.id) {
if (hw->phy.id == phy_id)
return TRUE;
goto out;
} else if (phy_id) {
hw->phy.id = phy_id;
hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK);
return TRUE;
goto out;
}
/* In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
*/
hw->phy.ops.release(hw);
ret_val = e1000_set_mdio_slow_mode_hv(hw);
if (!ret_val)
ret_val = e1000_get_phy_id(hw);
hw->phy.ops.acquire(hw);
if (hw->mac.type < e1000_pch_lpt) {
hw->phy.ops.release(hw);
ret_val = e1000_set_mdio_slow_mode_hv(hw);
if (!ret_val)
ret_val = e1000_get_phy_id(hw);
hw->phy.ops.acquire(hw);
}
return !ret_val;
if (ret_val)
return FALSE;
out:
if (hw->mac.type == e1000_pch_lpt) {
/* Unforce SMBus mode in PHY */
hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg);
phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg);
/* Unforce SMBus mode in MAC */
mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
}
return TRUE;
}
/**
* e1000_toggle_lanphypc_pch_lpt - toggle the LANPHYPC pin value
* @hw: pointer to the HW structure
*
* Toggling the LANPHYPC pin value fully power-cycles the PHY and is
* used to reset the PHY to a quiescent state when necessary.
**/
void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw)
{
u32 mac_reg;
DEBUGFUNC("e1000_toggle_lanphypc_pch_lpt");
/* Set Phy Config Counter to 50msec */
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM3);
mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
E1000_WRITE_REG(hw, E1000_FEXTNVM3, mac_reg);
/* Toggle LANPHYPC Value bit */
mac_reg = E1000_READ_REG(hw, E1000_CTRL);
mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
E1000_WRITE_FLUSH(hw);
usec_delay(10);
mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
E1000_WRITE_FLUSH(hw);
if (hw->mac.type < e1000_pch_lpt) {
msec_delay(50);
} else {
u16 count = 20;
do {
msec_delay(5);
} while (!(E1000_READ_REG(hw, E1000_CTRL_EXT) &
E1000_CTRL_EXT_LPCD) && count--);
msec_delay(30);
}
}
/**
@ -231,7 +298,6 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
{
u32 mac_reg, fwsm = E1000_READ_REG(hw, E1000_FWSM);
s32 ret_val;
u16 phy_reg;
DEBUGFUNC("e1000_init_phy_workarounds_pchlan");
@ -262,24 +328,16 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
/* Wait 50 milliseconds for MAC to finish any retries
* that it might be trying to perform from previous
* attempts to acknowledge any phy read requests.
*/
msec_delay(50);
/* fall-through */
case e1000_pch2lan:
if (e1000_phy_is_accessible_pchlan(hw)) {
if (hw->mac.type == e1000_pch_lpt) {
/* Unforce SMBus mode in PHY */
hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL,
&phy_reg);
phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL,
phy_reg);
/* Unforce SMBus mode in MAC */
mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
}
if (e1000_phy_is_accessible_pchlan(hw))
break;
}
/* fall-through */
case e1000_pchlan:
@ -289,44 +347,27 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
if (hw->phy.ops.check_reset_block(hw)) {
DEBUGOUT("Required LANPHYPC toggle blocked by ME\n");
ret_val = -E1000_ERR_PHY;
break;
}
DEBUGOUT("Toggling LANPHYPC\n");
/* Toggle LANPHYPC Value bit */
e1000_toggle_lanphypc_pch_lpt(hw);
if (hw->mac.type >= e1000_pch_lpt) {
if (e1000_phy_is_accessible_pchlan(hw))
break;
/* Set Phy Config Counter to 50msec */
mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM3);
mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
E1000_WRITE_REG(hw, E1000_FEXTNVM3, mac_reg);
if (hw->mac.type == e1000_pch_lpt) {
/* Toggling LANPHYPC brings the PHY out of SMBus mode
* So ensure that the MAC is also out of SMBus mode
* so ensure that the MAC is also out of SMBus mode
*/
mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
}
/* Toggle LANPHYPC Value bit */
mac_reg = E1000_READ_REG(hw, E1000_CTRL);
mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
E1000_WRITE_FLUSH(hw);
usec_delay(10);
mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
E1000_WRITE_FLUSH(hw);
if (hw->mac.type < e1000_pch_lpt) {
msec_delay(50);
} else {
u16 count = 20;
do {
msec_delay(5);
} while (!(E1000_READ_REG(hw, E1000_CTRL_EXT) &
E1000_CTRL_EXT_LPCD) && count--);
if (e1000_phy_is_accessible_pchlan(hw))
break;
ret_val = -E1000_ERR_PHY;
}
break;
default:
@ -334,13 +375,33 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
}
hw->phy.ops.release(hw);
if (!ret_val) {
/* Reset the PHY before any access to it. Doing so, ensures
* that the PHY is in a known good state before we read/write
* PHY registers. The generic reset is sufficient here,
* because we haven't determined the PHY type yet.
*/
ret_val = e1000_phy_hw_reset_generic(hw);
/* Check to see if able to reset PHY. Print error if not */
if (hw->phy.ops.check_reset_block(hw)) {
ERROR_REPORT("Reset blocked by ME\n");
goto out;
}
/* Reset the PHY before any access to it. Doing so, ensures
* that the PHY is in a known good state before we read/write
* PHY registers. The generic reset is sufficient here,
* because we haven't determined the PHY type yet.
*/
ret_val = e1000_phy_hw_reset_generic(hw);
if (ret_val)
goto out;
/* On a successful reset, possibly need to wait for the PHY
* to quiesce to an accessible state before returning control
* to the calling function. If the PHY does not quiesce, then
* return E1000E_BLK_PHY_RESET, as this is the condition that
* the PHY is in.
*/
ret_val = hw->phy.ops.check_reset_block(hw);
if (ret_val)
ERROR_REPORT("ME blocked access to PHY after reset\n");
}
out:
/* Ungate automatic PHY configuration on non-managed 82579 */
@ -572,8 +633,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* find total size of the NVM, then cut in half since the total
* size represents two separate NVM banks.
*/
nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
<< FLASH_SECTOR_ADDR_SHIFT;
nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
<< FLASH_SECTOR_ADDR_SHIFT);
nvm->flash_bank_size /= 2;
/* Adjust to word count */
nvm->flash_bank_size /= sizeof(u16);
@ -766,7 +827,7 @@ s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data)
*
* Assumes the SW/FW/HW Semaphore is already acquired.
**/
static s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
{
DEBUGFUNC("e1000_read_emi_reg_locked");
@ -780,18 +841,35 @@ static s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
* Enable/disable EEE based on setting in dev_spec structure, the duplex of
* the link and the EEE capabilities of the link partner. The LPI Control
* register bits will remain set only if/when link is up.
*
* EEE LPI must not be asserted earlier than one second after link is up.
* On 82579, EEE LPI should not be enabled until such time otherwise there
* can be link issues with some switches. Other devices can have EEE LPI
* enabled immediately upon link up since they have a timer in hardware which
* prevents LPI from being asserted too early.
**/
static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
s32 ret_val;
u16 lpi_ctrl;
u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data;
DEBUGFUNC("e1000_set_eee_pchlan");
if ((hw->phy.type != e1000_phy_82579) &&
(hw->phy.type != e1000_phy_i217))
switch (hw->phy.type) {
case e1000_phy_82579:
lpa = I82579_EEE_LP_ABILITY;
pcs_status = I82579_EEE_PCS_STATUS;
adv_addr = I82579_EEE_ADVERTISEMENT;
break;
case e1000_phy_i217:
lpa = I217_EEE_LP_ABILITY;
pcs_status = I217_EEE_PCS_STATUS;
adv_addr = I217_EEE_ADVERTISEMENT;
break;
default:
return E1000_SUCCESS;
}
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
@ -806,34 +884,24 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
/* Enable EEE if not disabled by user */
if (!dev_spec->eee_disable) {
u16 lpa, pcs_status, data;
/* Save off link partner's EEE ability */
switch (hw->phy.type) {
case e1000_phy_82579:
lpa = I82579_EEE_LP_ABILITY;
pcs_status = I82579_EEE_PCS_STATUS;
break;
case e1000_phy_i217:
lpa = I217_EEE_LP_ABILITY;
pcs_status = I217_EEE_PCS_STATUS;
break;
default:
ret_val = -E1000_ERR_PHY;
goto release;
}
ret_val = e1000_read_emi_reg_locked(hw, lpa,
&dev_spec->eee_lp_ability);
if (ret_val)
goto release;
/* Read EEE advertisement */
ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv);
if (ret_val)
goto release;
/* Enable EEE only for speeds in which the link partner is
* EEE capable.
* EEE capable and for which we advertise EEE.
*/
if (dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED)
if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED)
lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE;
if (dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) {
if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) {
hw->phy.ops.read_reg_locked(hw, PHY_LP_ABILITY, &data);
if (data & NWAY_LPAR_100TX_FD_CAPS)
lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE;
@ -845,13 +913,13 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
dev_spec->eee_lp_ability &=
~I82579_EEE_100_SUPPORTED;
}
/* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
if (ret_val)
goto release;
}
/* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
if (ret_val)
goto release;
ret_val = hw->phy.ops.write_reg_locked(hw, I82579_LPI_CTRL, lpi_ctrl);
release:
hw->phy.ops.release(hw);
@ -867,30 +935,31 @@ release:
* When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
* preventing further DMA write requests. Workaround the issue by disabling
* the de-assertion of the clock request when in 1Gpbs mode.
* Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link
* speeds in order to avoid Tx hangs.
**/
static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
{
u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
u32 status = E1000_READ_REG(hw, E1000_STATUS);
s32 ret_val = E1000_SUCCESS;
u16 reg;
if (link && (E1000_READ_REG(hw, E1000_STATUS) &
E1000_STATUS_SPEED_1000)) {
u16 kmrn_reg;
if (link && (status & E1000_STATUS_SPEED_1000)) {
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
ret_val =
e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
&kmrn_reg);
&reg);
if (ret_val)
goto release;
ret_val =
e1000_write_kmrn_reg_locked(hw,
E1000_KMRNCTRLSTA_K1_CONFIG,
kmrn_reg &
reg &
~E1000_KMRNCTRLSTA_K1_ENABLE);
if (ret_val)
goto release;
@ -903,13 +972,45 @@ static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
ret_val =
e1000_write_kmrn_reg_locked(hw,
E1000_KMRNCTRLSTA_K1_CONFIG,
kmrn_reg);
reg);
release:
hw->phy.ops.release(hw);
} else {
/* clear FEXTNVM6 bit 8 on link down or 10/100 */
E1000_WRITE_REG(hw, E1000_FEXTNVM6,
fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
if (!link || ((status & E1000_STATUS_SPEED_100) &&
(status & E1000_STATUS_FD)))
goto update_fextnvm6;
ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, &reg);
if (ret_val)
return ret_val;
/* Clear link status transmit timeout */
reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK;
if (status & E1000_STATUS_SPEED_100) {
/* Set inband Tx timeout to 5x10us for 100Half */
reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
/* Do not extend the K1 entry latency for 100Half */
fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
} else {
/* Set inband Tx timeout to 50x10us for 10Full/Half */
reg |= 50 <<
I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
/* Extend the K1 entry latency for 10 Mbps */
fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
}
ret_val = hw->phy.ops.write_reg(hw, I217_INBAND_CTRL, reg);
if (ret_val)
return ret_val;
update_fextnvm6:
E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
}
return ret_val;
@ -1018,7 +1119,6 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
lat_ns /= 1000000000;
obff_hwm = (s32)(rxa - lat_ns);
}
if ((obff_hwm < 0) || (obff_hwm > E1000_SVT_OFF_HWM_MASK)) {
DEBUGOUT1("Invalid high water mark %d\n", obff_hwm);
return -E1000_ERR_CONFIG;
@ -1103,13 +1203,13 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (!mac->get_link_status)
return E1000_SUCCESS;
/* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
return ret_val;
/* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
return ret_val;
if (hw->mac.type == e1000_pchlan) {
ret_val = e1000_k1_gig_workaround_hv(hw, link);
@ -1153,8 +1253,9 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
}
if (hw->mac.type == e1000_pch_lpt) {
/* Set platform power management values for Latency Tolerance
* Reporting (LTR) and Optimized Buffer Flush/Fill (OBFF).
/* Set platform power management values for
* Latency Tolerance Reporting (LTR)
* Optimized Buffer Flush/Fill (OBFF)
*/
ret_val = e1000_platform_pm_pch_lpt(hw, link);
if (ret_val)
@ -1206,9 +1307,11 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
e1000_check_downshift_generic(hw);
/* Enable/Disable EEE after link up */
ret_val = e1000_set_eee_pchlan(hw);
if (ret_val)
return ret_val;
if (hw->phy.type > e1000_phy_82579) {
ret_val = e1000_set_eee_pchlan(hw);
if (ret_val)
return ret_val;
}
/* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
@ -1396,9 +1499,9 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
fwsm = E1000_READ_REG(hw, E1000_FWSM);
return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
((fwsm & E1000_FWSM_MODE_MASK) ==
(E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
return ((fwsm & E1000_ICH_FWSM_FW_VALID) &&
((fwsm & E1000_FWSM_MODE_MASK) ==
(E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)));
}
/**
@ -1459,7 +1562,10 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
return;
}
if (index < hw->mac.rar_entry_count) {
/* RAR[1-6] are owned by manageability. Skip those and program the
* next address into the SHRA register array.
*/
if (index < (u32) (hw->mac.rar_entry_count - 6)) {
s32 ret_val;
ret_val = e1000_acquire_swflag_ich8lan(hw);
@ -1619,13 +1725,21 @@ release:
static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
{
u32 fwsm;
bool blocked = FALSE;
int i = 0;
DEBUGFUNC("e1000_check_reset_block_ich8lan");
fwsm = E1000_READ_REG(hw, E1000_FWSM);
return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS
: E1000_BLK_PHY_RESET;
do {
fwsm = E1000_READ_REG(hw, E1000_FWSM);
if (!(fwsm & E1000_ICH_FWSM_RSPCIPHY)) {
blocked = TRUE;
msec_delay(10);
continue;
}
blocked = FALSE;
} while (blocked && (i++ < 10));
return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS;
}
/**
@ -1825,9 +1939,9 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
if (ret_val)
goto release;
status_reg &= BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_MASK;
status_reg &= (BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_MASK);
if (status_reg == (BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
@ -1841,9 +1955,9 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
if (ret_val)
goto release;
status_reg &= HV_M_STATUS_LINK_UP |
HV_M_STATUS_AUTONEG_COMPLETE |
HV_M_STATUS_SPEED_MASK;
status_reg &= (HV_M_STATUS_LINK_UP |
HV_M_STATUS_AUTONEG_COMPLETE |
HV_M_STATUS_SPEED_MASK);
if (status_reg == (HV_M_STATUS_LINK_UP |
HV_M_STATUS_AUTONEG_COMPLETE |
@ -2125,8 +2239,8 @@ void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
if (ret_val)
goto release;
/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
/* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */
for (i = 0; i < (hw->mac.rar_entry_count); i++) {
mac_reg = E1000_READ_REG(hw, E1000_RAL(i));
hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
(u16)(mac_reg & 0xFFFF));
@ -2191,10 +2305,10 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
return ret_val;
if (enable) {
/* Write Rx addresses (rar_entry_count for RAL/H, +4 for
/* Write Rx addresses (rar_entry_count for RAL/H, and
* SHRAL/H) and initial CRC values to the MAC
*/
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
for (i = 0; i < hw->mac.rar_entry_count; i++) {
u8 mac_addr[ETH_ADDR_LEN] = {0};
u32 addr_high, addr_low;
@ -3112,11 +3226,11 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
DEBUGFUNC("e1000_read_flash_data_ich8lan");
if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
return -E1000_ERR_NVM;
flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
hw->nvm.flash_base_addr;
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
hw->nvm.flash_base_addr);
do {
usec_delay(1);
@ -3133,8 +3247,9 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
ret_val = e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_READ_COMMAND_TIMEOUT);
ret_val =
e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_READ_COMMAND_TIMEOUT);
/* Check if FCERR is set to 1, if set to 1, clear it
* and try the whole sequence a few more times, else
@ -3437,8 +3552,8 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
offset > ICH_FLASH_LINEAR_ADDR_MASK)
return -E1000_ERR_NVM;
flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) +
hw->nvm.flash_base_addr;
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
hw->nvm.flash_base_addr);
do {
usec_delay(1);
@ -3465,8 +3580,9 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
/* check if FCERR is set to 1 , if set to 1, clear it
* and try the whole sequence a few more times else done
*/
ret_val = e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_WRITE_COMMAND_TIMEOUT);
ret_val =
e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_WRITE_COMMAND_TIMEOUT);
if (ret_val == E1000_SUCCESS)
break;
@ -3602,8 +3718,10 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
flash_linear_addr = hw->nvm.flash_base_addr;
flash_linear_addr += (bank) ? flash_bank_size : 0;
for (j = 0; j < iteration ; j++) {
for (j = 0; j < iteration; j++) {
do {
u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT;
/* Steps */
ret_val = e1000_flash_cycle_init_ich8lan(hw);
if (ret_val)
@ -3626,8 +3744,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR,
flash_linear_addr);
ret_val = e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_ERASE_COMMAND_TIMEOUT);
ret_val = e1000_flash_cycle_ich8lan(hw, timeout);
if (ret_val == E1000_SUCCESS)
break;
@ -3947,16 +4064,16 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
/* Set the transmit descriptor write-back policy for both queues */
txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB;
txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB);
txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) |
E1000_TXDCTL_MAX_TX_DESC_PREFETCH);
E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1));
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB;
txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB);
txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) |
E1000_TXDCTL_MAX_TX_DESC_PREFETCH);
E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl);
/* ICH8 has opposite polarity of no_snoop bits.
@ -4041,6 +4158,7 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
*/
reg = E1000_READ_REG(hw, E1000_RFCTL);
reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
/* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
@ -4502,14 +4620,25 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
/* Disable LPLU if both link partners support 100BaseT
* EEE and 100Full is advertised on both ends of the
* link.
* link, and enable Auto Enable LPI since there will
* be no driver to enable LPI while in Sx.
*/
if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
(dev_spec->eee_lp_ability &
I82579_EEE_100_SUPPORTED) &&
(hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
(hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) {
phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
E1000_PHY_CTRL_NOND0A_LPLU);
/* Set Auto Enable LPI after link up */
hw->phy.ops.read_reg_locked(hw,
I217_LPI_GPIO_CTRL,
&phy_reg);
phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
hw->phy.ops.write_reg_locked(hw,
I217_LPI_GPIO_CTRL,
phy_reg);
}
}
/* For i217 Intel Rapid Start Technology support,
@ -4613,6 +4742,11 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
return;
}
/* Clear Auto Enable LPI after link up */
hw->phy.ops.read_reg_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg);
phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
hw->phy.ops.write_reg_locked(hw, I217_LPI_GPIO_CTRL, phy_reg);
if (!(E1000_READ_REG(hw, E1000_FWSM) &
E1000_ICH_FWSM_FW_VALID)) {
/* Restore clear on SMB if no manageability engine

View file

@ -60,10 +60,10 @@
#define ICH_FLASH_SEG_SIZE_8K 8192
#define ICH_FLASH_SEG_SIZE_64K 65536
#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */
#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */
/* FW established a valid mode */
#define E1000_ICH_FWSM_FW_VALID 0x00008000
#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */
#define E1000_ICH_FWSM_FW_VALID 0x00008000
#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */
#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000
#define E1000_ICH_MNG_IAMT_MODE 0x2
@ -88,7 +88,7 @@
#define E1000_ICH8_LAN_INIT_TIMEOUT 1500
#define E1000_FEXTNVM_SW_CONFIG 1
#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */
#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* different on ICH8M */
#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000
#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000
@ -98,18 +98,19 @@
#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3
#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100
#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
#define E1000_ICH_RAR_ENTRIES 7
#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
#define E1000_PCH2_RAR_ENTRIES 11 /* RAR[0-6], SHRA[0-3] */
#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */
#define PHY_PAGE_SHIFT 5
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
((reg) & MAX_PHY_REG_ADDRESS))
#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */
#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */
#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */
#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */
#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002
#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300
@ -140,19 +141,20 @@
#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
#define HV_STATS_PAGE 778
#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
/* Half-duplex collision counts */
#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision */
#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17)
#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. */
#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19)
#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Collision */
#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21)
#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision */
#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision */
#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26)
#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28)
#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Tx with no CRS */
#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30)
#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */
@ -201,6 +203,15 @@
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */
/* Inband Control */
#define I217_INBAND_CTRL PHY_REG(770, 18)
#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK 0x3F00
#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT 8
/* Low Power Idle GPIO Control */
#define I217_LPI_GPIO_CTRL PHY_REG(772, 18)
#define I217_LPI_GPIO_CTRL_AUTO_EN_LPI 0x0800
/* PHY Low Power Idle Control */
#define I82579_LPI_CTRL PHY_REG(772, 20)
#define I82579_LPI_CTRL_100_ENABLE 0x2000
@ -208,6 +219,10 @@
#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80
/* 82579 DFT Control */
#define I82579_DFT_CTRL PHY_REG(769, 20)
#define I82579_DFT_CTRL_GATE_PHY_RESET 0x0040 /* Gate PHY Reset on MAC Reset */
/* Extended Management Interface (EMI) Registers */
#define I82579_EMI_ADDR 0x10
#define I82579_EMI_DATA 0x11
@ -216,12 +231,12 @@
#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */
#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
#define I82579_RX_CONFIG 0x3412 /* Receive configuration */
#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */
#define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */
#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */
#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */
#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */
#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */
#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */
#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */
#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */
#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
@ -274,4 +289,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data);
s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data);
s32 e1000_set_eee_pchlan(struct e1000_hw *hw);
void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw);
#endif /* _E1000_ICH8LAN_H_ */

View file

@ -85,7 +85,7 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw)
* e1000_null_ops_generic - No-op function, returns 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_ops_generic(struct e1000_hw *hw)
s32 e1000_null_ops_generic(struct e1000_hw E1000_UNUSEDARG *hw)
{
DEBUGFUNC("e1000_null_ops_generic");
return E1000_SUCCESS;
@ -95,7 +95,7 @@ s32 e1000_null_ops_generic(struct e1000_hw *hw)
* e1000_null_mac_generic - No-op function, return void
* @hw: pointer to the HW structure
**/
void e1000_null_mac_generic(struct e1000_hw *hw)
void e1000_null_mac_generic(struct e1000_hw E1000_UNUSEDARG *hw)
{
DEBUGFUNC("e1000_null_mac_generic");
return;
@ -105,7 +105,8 @@ void e1000_null_mac_generic(struct e1000_hw *hw)
* e1000_null_link_info - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d)
s32 e1000_null_link_info(struct e1000_hw E1000_UNUSEDARG *hw,
u16 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d)
{
DEBUGFUNC("e1000_null_link_info");
return E1000_SUCCESS;
@ -115,7 +116,8 @@ s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d)
* e1000_null_mng_mode - No-op function, return FALSE
* @hw: pointer to the HW structure
**/
bool e1000_null_mng_mode(struct e1000_hw *hw) {
bool e1000_null_mng_mode(struct e1000_hw E1000_UNUSEDARG *hw)
{
DEBUGFUNC("e1000_null_mng_mode");
return FALSE;
}
@ -124,7 +126,8 @@ bool e1000_null_mng_mode(struct e1000_hw *hw) {
* e1000_null_update_mc - No-op function, return void
* @hw: pointer to the HW structure
**/
void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a)
void e1000_null_update_mc(struct e1000_hw E1000_UNUSEDARG *hw,
u8 E1000_UNUSEDARG *h, u32 E1000_UNUSEDARG a)
{
DEBUGFUNC("e1000_null_update_mc");
return;
@ -134,7 +137,8 @@ void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a)
* e1000_null_write_vfta - No-op function, return void
* @hw: pointer to the HW structure
**/
void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b)
void e1000_null_write_vfta(struct e1000_hw E1000_UNUSEDARG *hw,
u32 E1000_UNUSEDARG a, u32 E1000_UNUSEDARG b)
{
DEBUGFUNC("e1000_null_write_vfta");
return;
@ -144,7 +148,8 @@ void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b)
* e1000_null_rar_set - No-op function, return void
* @hw: pointer to the HW structure
**/
void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a)
void e1000_null_rar_set(struct e1000_hw E1000_UNUSEDARG *hw,
u8 E1000_UNUSEDARG *h, u32 E1000_UNUSEDARG a)
{
DEBUGFUNC("e1000_null_rar_set");
return;
@ -154,7 +159,8 @@ void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a)
* e1000_null_set_obff_timer - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_set_obff_timer(struct e1000_hw *hw, u32 a)
s32 e1000_null_set_obff_timer(struct e1000_hw E1000_UNUSEDARG *hw,
u32 E1000_UNUSEDARG a)
{
DEBUGFUNC("e1000_null_set_obff_timer");
return E1000_SUCCESS;
@ -940,6 +946,7 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
{
s32 ret_val;
u16 nvm_data;
u16 nvm_offset = 0;
DEBUGFUNC("e1000_set_default_fc_generic");
@ -951,7 +958,18 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
* control setting, then the variable hw->fc will
* be initialized based on a value in the EEPROM.
*/
ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
if (hw->mac.type == e1000_i350) {
nvm_offset = NVM_82580_LAN_FUNC_OFFSET(hw->bus.func);
ret_val = hw->nvm.ops.read(hw,
NVM_INIT_CONTROL2_REG +
nvm_offset,
1, &nvm_data);
} else {
ret_val = hw->nvm.ops.read(hw,
NVM_INIT_CONTROL2_REG,
1, &nvm_data);
}
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
@ -1675,7 +1693,7 @@ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
* Sets the speed and duplex to gigabit full duplex (the only possible option)
* for fiber/serdes links.
**/
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSEDARG *hw,
u16 *speed, u16 *duplex)
{
DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
@ -2187,7 +2205,7 @@ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
* Validate the MDI/MDIx setting, allowing for auto-crossover during forced
* operation.
**/
s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw)
s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw E1000_UNUSEDARG *hw)
{
DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic");

View file

@ -60,6 +60,7 @@
#define ASSERT(x) if(!(x)) panic("EM: x")
#define usec_delay(x) DELAY(x)
#define usec_delay_irq(x) DELAY(x)
#define msec_delay(x) DELAY(1000*(x))
#define msec_delay_irq(x) DELAY(1000*(x))

View file

@ -104,7 +104,8 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw)
* e1000_null_set_page - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
s32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw,
u16 E1000_UNUSEDARG data)
{
DEBUGFUNC("e1000_null_set_page");
return E1000_SUCCESS;
@ -114,7 +115,8 @@ s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
* e1000_null_read_reg - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data)
s32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw,
u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data)
{
DEBUGFUNC("e1000_null_read_reg");
return E1000_SUCCESS;
@ -124,7 +126,7 @@ s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data)
* e1000_null_phy_generic - No-op function, return void
* @hw: pointer to the HW structure
**/
void e1000_null_phy_generic(struct e1000_hw *hw)
void e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw)
{
DEBUGFUNC("e1000_null_phy_generic");
return;
@ -134,7 +136,8 @@ void e1000_null_phy_generic(struct e1000_hw *hw)
* e1000_null_lplu_state - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active)
s32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw,
bool E1000_UNUSEDARG active)
{
DEBUGFUNC("e1000_null_lplu_state");
return E1000_SUCCESS;
@ -144,7 +147,8 @@ s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active)
* e1000_null_write_reg - No-op function, return 0
* @hw: pointer to the HW structure
**/
s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
s32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw,
u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data)
{
DEBUGFUNC("e1000_null_write_reg");
return E1000_SUCCESS;
@ -158,8 +162,10 @@ s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
* @data: data value read
*
**/
s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data)
s32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
u8 E1000_UNUSEDARG byte_offset,
u8 E1000_UNUSEDARG dev_addr,
u8 E1000_UNUSEDARG *data)
{
DEBUGFUNC("e1000_read_i2c_byte_null");
return E1000_SUCCESS;
@ -173,10 +179,10 @@ s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
* @data: data value to write
*
**/
s32 e1000_write_i2c_byte_null(struct e1000_hw *hw,
u8 byte_offset,
u8 dev_addr,
u8 data)
s32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
u8 E1000_UNUSEDARG byte_offset,
u8 E1000_UNUSEDARG dev_addr,
u8 E1000_UNUSEDARG data)
{
DEBUGFUNC("e1000_write_i2c_byte_null");
return E1000_SUCCESS;
@ -302,7 +308,7 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
* the lower time out
*/
for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
usec_delay(50);
usec_delay_irq(50);
mdic = E1000_READ_REG(hw, E1000_MDIC);
if (mdic & E1000_MDIC_READY)
break;
@ -327,7 +333,7 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
usec_delay(100);
usec_delay_irq(100);
return E1000_SUCCESS;
}
@ -368,7 +374,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
* the lower time out
*/
for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
usec_delay(50);
usec_delay_irq(50);
mdic = E1000_READ_REG(hw, E1000_MDIC);
if (mdic & E1000_MDIC_READY)
break;
@ -392,7 +398,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
usec_delay(100);
usec_delay_irq(100);
return E1000_SUCCESS;
}
@ -1054,16 +1060,12 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
}
}
/* Enable CRS on Tx. This must be set for half-duplex operation.
* Not required on some PHYs.
*/
/* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
if (ret_val)
return ret_val;
if ((hw->phy.type != e1000_phy_82579) &&
(hw->phy.type != e1000_phy_i217))
phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
/* Enable downshift */
phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
@ -1249,12 +1251,6 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
return ret_val;
}
if (phy->type == e1000_phy_i210) {
ret_val = e1000_set_master_slave_mode(hw);
if (ret_val)
return ret_val;
}
return E1000_SUCCESS;
}
@ -1318,6 +1314,20 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
/* Enable downshift and setting it to X6 */
if (phy->id == M88E1543_E_PHY_ID) {
phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE;
ret_val =
phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
return ret_val;
ret_val = phy->ops.commit(hw);
if (ret_val) {
DEBUGOUT("Error committing the PHY changes\n");
return ret_val;
}
}
phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
@ -1333,6 +1343,10 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
return ret_val;
}
ret_val = e1000_set_master_slave_mode(hw);
if (ret_val)
return ret_val;
return E1000_SUCCESS;
}
@ -1847,6 +1861,8 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
case I347AT4_E_PHY_ID:
case M88E1340M_E_PHY_ID:
case M88E1112_E_PHY_ID:
case M88E1543_E_PHY_ID:
case M88E1512_E_PHY_ID:
case I210_I_PHY_ID:
reset_dsp = FALSE;
break;
@ -1889,6 +1905,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
return E1000_SUCCESS;
if (hw->phy.id == I210_I_PHY_ID)
return E1000_SUCCESS;
if ((hw->phy.id == M88E1543_E_PHY_ID) ||
(hw->phy.id == M88E1512_E_PHY_ID))
return E1000_SUCCESS;
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
if (ret_val)
return ret_val;
@ -2194,9 +2213,9 @@ s32 e1000_check_polarity_m88(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
if (!ret_val)
phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal;
phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal);
return ret_val;
}
@ -2240,9 +2259,9 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, offset, &data);
if (!ret_val)
phy->cable_polarity = (data & mask)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal;
phy->cable_polarity = ((data & mask)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal);
return ret_val;
}
@ -2274,9 +2293,9 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, offset, &phy_data);
if (!ret_val)
phy->cable_polarity = (phy_data & mask)
phy->cable_polarity = ((phy_data & mask)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal;
: e1000_rev_polarity_normal);
return ret_val;
}
@ -2392,8 +2411,8 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
if (ret_val)
return ret_val;
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT;
index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT);
if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
return -E1000_ERR_PHY;
@ -2437,6 +2456,8 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
phy->cable_length = phy_data / (is_cm ? 100 : 1);
break;
case M88E1543_E_PHY_ID:
case M88E1512_E_PHY_ID:
case M88E1340M_E_PHY_ID:
case I347AT4_E_PHY_ID:
/* Remember the original page select and set it to 7 */
@ -2554,8 +2575,8 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
* that can be put into the lookup table to obtain the
* approximate cable length.
*/
cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
IGP02E1000_AGC_LENGTH_MASK;
cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
IGP02E1000_AGC_LENGTH_MASK);
/* Array index bound check. */
if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
@ -2578,8 +2599,8 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
/* Calculate cable length with the error range of +/- 10 meters. */
phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
(agc_value - IGP02E1000_AGC_RANGE) : 0;
phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
(agc_value - IGP02E1000_AGC_RANGE) : 0);
phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
@ -2763,9 +2784,9 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
return ret_val;
} else {
/* Polarity is forced */
phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal;
phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal);
}
ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
@ -2863,7 +2884,7 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
* Generic function to wait 10 milli-seconds for configuration to complete
* and return success.
**/
s32 e1000_get_cfg_done_generic(struct e1000_hw *hw)
s32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw)
{
DEBUGFUNC("e1000_get_cfg_done_generic");
@ -2970,6 +2991,8 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
case M88E1000_E_PHY_ID:
case M88E1111_I_PHY_ID:
case M88E1011_I_PHY_ID:
case M88E1543_E_PHY_ID:
case M88E1512_E_PHY_ID:
case I347AT4_E_PHY_ID:
case M88E1112_E_PHY_ID:
case M88E1340M_E_PHY_ID:
@ -3776,8 +3799,8 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
DEBUGFUNC("e1000_access_phy_debug_regs_hv");
/* This takes care of the difference with desktop vs mobile phy */
addr_reg = (hw->phy.type == e1000_phy_82578) ?
I82578_ADDR_REG : I82577_ADDR_REG;
addr_reg = ((hw->phy.type == e1000_phy_82578) ?
I82578_ADDR_REG : I82577_ADDR_REG);
data_reg = addr_reg + 1;
/* All operations in this function are phy address 2 */
@ -3833,8 +3856,8 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
if (ret_val)
return ret_val;
data &= BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_MASK;
data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_MASK);
if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_1000))
@ -3872,9 +3895,9 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw)
ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
if (!ret_val)
phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal;
phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY)
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal);
return ret_val;
}
@ -4009,8 +4032,8 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
if (ret_val)
return ret_val;
length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
I82577_DSTATUS_CABLE_LENGTH_SHIFT;
length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
I82577_DSTATUS_CABLE_LENGTH_SHIFT);
if (length == E1000_CABLE_LENGTH_UNDEFINED)
return -E1000_ERR_PHY;
@ -4083,3 +4106,157 @@ release:
return ret_val;
}
/**
* e1000_read_phy_reg_mphy - Read mPHY control register
* @hw: pointer to the HW structure
* @address: address to be read
* @data: pointer to the read data
*
* Reads the mPHY control register in the PHY at offset and stores the
* information read to data.
**/
s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data)
{
u32 mphy_ctrl = 0;
bool locked = FALSE;
bool ready = FALSE;
DEBUGFUNC("e1000_read_phy_reg_mphy");
/* Check if mPHY is ready to read/write operations */
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
/* Check if mPHY access is disabled and enable it if so */
mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
locked = TRUE;
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
}
/* Set the address that we want to read */
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
/* We mask address, because we want to use only current lane */
mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK &
~E1000_MPHY_ADDRESS_FNC_OVERRIDE) |
(address & E1000_MPHY_ADDRESS_MASK);
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
/* Read data from the address */
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
*data = E1000_READ_REG(hw, E1000_MPHY_DATA);
/* Disable access to mPHY if it was originally disabled */
if (locked)
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
E1000_MPHY_DIS_ACCESS);
return E1000_SUCCESS;
}
/**
* e1000_write_phy_reg_mphy - Write mPHY control register
* @hw: pointer to the HW structure
* @address: address to write to
* @data: data to write to register at offset
* @line_override: used when we want to use different line than default one
*
* Writes data to mPHY control register.
**/
s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
bool line_override)
{
u32 mphy_ctrl = 0;
bool locked = FALSE;
bool ready = FALSE;
DEBUGFUNC("e1000_write_phy_reg_mphy");
/* Check if mPHY is ready to read/write operations */
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
/* Check if mPHY access is disabled and enable it if so */
mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
locked = TRUE;
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
}
/* Set the address that we want to read */
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
/* We mask address, because we want to use only current lane */
if (line_override)
mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE;
else
mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE;
mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) |
(address & E1000_MPHY_ADDRESS_MASK);
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
/* Read data from the address */
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
E1000_WRITE_REG(hw, E1000_MPHY_DATA, data);
/* Disable access to mPHY if it was originally disabled */
if (locked)
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
E1000_MPHY_DIS_ACCESS);
return E1000_SUCCESS;
}
/**
* e1000_is_mphy_ready - Check if mPHY control register is not busy
* @hw: pointer to the HW structure
*
* Returns mPHY control register status.
**/
bool e1000_is_mphy_ready(struct e1000_hw *hw)
{
u16 retry_count = 0;
u32 mphy_ctrl = 0;
bool ready = FALSE;
while (retry_count < 2) {
mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
if (mphy_ctrl & E1000_MPHY_BUSY) {
usec_delay(20);
retry_count++;
continue;
}
ready = TRUE;
break;
}
if (!ready)
DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n");
return ready;
}

View file

@ -116,6 +116,10 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data);
s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
bool line_override);
bool e1000_is_mphy_ready(struct e1000_hw *hw);
#define E1000_MAX_PHY_ADDR 8
@ -170,7 +174,7 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
#define I82577_ADDR_REG 16
#define I82577_CFG_REG 22
#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15)
#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */
#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift */
#define I82577_CTRL_REG 23
/* 82577 specific PHY registers */
@ -201,6 +205,12 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
#define E1000_MPHY_DIS_ACCESS 0x80000000 /* disable_access bit */
#define E1000_MPHY_ENA_ACCESS 0x40000000 /* enable_access bit */
#define E1000_MPHY_BUSY 0x00010000 /* busy bit */
#define E1000_MPHY_ADDRESS_FNC_OVERRIDE 0x20000000 /* fnc_override bit */
#define E1000_MPHY_ADDRESS_MASK 0x0000FFFF /* address mask */
/* BM PHY Copper Specific Control 1 */
#define BM_CS_CTRL1 16
@ -247,7 +257,7 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
#define IGP02E1000_PHY_AGC_C 0x14B1
#define IGP02E1000_PHY_AGC_D 0x18B1
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
#define IGP02E1000_AGC_RANGE 15
@ -267,8 +277,8 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Control */
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */
#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */
#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
/* IFE PHY Extended Status Control */

View file

@ -50,6 +50,10 @@
#define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */
#define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */
#define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */
#define E1000_MPHY_ADDR_CTRL 0x0024 /* GbE MPHY Address Control */
#define E1000_MPHY_DATA 0x0E10 /* GBE MPHY Data */
#define E1000_MPHY_STAT 0x0E0C /* GBE MPHY Statistics */
#define E1000_PPHY_CTRL 0x5b48 /* PCIe PHY Control */
#define E1000_I350_BARCTRL 0x5BFC /* BAR ctrl reg */
#define E1000_I350_DTXMXPKTSZ 0x355C /* Maximum sent packet size reg*/
#define E1000_SCTL 0x00024 /* SerDes Control - RW */
@ -94,6 +98,7 @@
#define E1000_TBT 0x00448 /* Tx Burst Timer - RW */
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
#define E1000_LEDMUX 0x08130 /* LED MUX Control */
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
@ -152,6 +157,8 @@
#define E1000_PBRWAC 0x024E8 /* Rx packet buffer wrap around counter - RO */
#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
#define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */
#define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */
#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */
#define E1000_I210_FLMNGCTL 0x12038
#define E1000_I210_FLMNGDATA 0x1203C
@ -208,6 +215,9 @@
/* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */
#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n))
#define E1000_MMDAC 13 /* MMD Access Control */
#define E1000_MMDAAD 14 /* MMD Access Address/Data */
/* Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
@ -484,8 +494,6 @@
#define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
#define E1000_HOST_IF 0x08800 /* Host Interface */
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
#define E1000_HIBBA 0x8F40 /* Host Interface Buffer Base Address */
/* Flexible Host Filter Table */
#define E1000_FHFT(_n) (0x09000 + ((_n) * 0x100))

View file

@ -1,6 +1,6 @@
/******************************************************************************
Copyright (c) 2001-2010, Intel Corporation
Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -41,48 +41,50 @@
struct e1000_hw;
#define E1000_DEV_ID_82576_VF 0x10CA
#define E1000_DEV_ID_I350_VF 0x1520
#define E1000_DEV_ID_82576_VF 0x10CA
#define E1000_DEV_ID_I350_VF 0x1520
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
#define E1000_VF_INIT_TIMEOUT 200 /* Num of retries to clear RSTI */
/* Additional Descriptor Control definitions */
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
/* SRRCTL bit definitions */
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
(0x0C00C + ((_n) * 0x40)))
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
/* Interrupt Defines */
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
#define E1000_EITR(_n) (0x01680 + ((_n) << 2))
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
#define E1000_IVAR_VALID 0x80
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
#define E1000_EITR(_n) (0x01680 + ((_n) << 2))
#define E1000_EICS 0x01520 /* Ext. Intr Cause Set -W0 */
#define E1000_EIMS 0x01524 /* Ext. Intr Mask Set/Read -RW */
#define E1000_EIMC 0x01528 /* Ext. Intr Mask Clear -WO */
#define E1000_EIAC 0x0152C /* Ext. Intr Auto Clear -RW */
#define E1000_EIAM 0x01530 /* Ext. Intr Ack Auto Clear Mask -RW */
#define E1000_IVAR0 0x01700 /* Intr Vector Alloc (array) -RW */
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes -RW */
#define E1000_IVAR_VALID 0x80
/* Receive Descriptor - Advanced */
union e1000_adv_rx_desc {
struct {
u64 pkt_addr; /* Packet buffer address */
u64 hdr_addr; /* Header buffer address */
u64 pkt_addr; /* Packet buffer address */
u64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
@ -96,23 +98,23 @@ union e1000_adv_rx_desc {
} hs_rss;
} lo_dword;
union {
u32 rss; /* RSS Hash */
u32 rss; /* RSS Hash */
struct {
u16 ip_id; /* IP id */
u16 csum; /* Packet Checksum */
u16 ip_id; /* IP id */
u16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
u32 status_error; /* ext status/error */
u16 length; /* Packet length */
u16 vlan; /* VLAN tag */
u32 status_error; /* ext status/error */
u16 length; /* Packet length */
u16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
@ -129,15 +131,15 @@ union e1000_adv_tx_desc {
};
/* Adv Transmit Descriptor Config Masks */
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
/* Context descriptors */
struct e1000_adv_tx_context_desc {
@ -147,11 +149,11 @@ struct e1000_adv_tx_context_desc {
u32 mss_l4len_idx;
};
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
enum e1000_mac_type {
e1000_undefined = 0,

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/******************************************************************************
Copyright (c) 2001-2011, Intel Corporation
Copyright (c) 2001-2013, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -162,6 +162,9 @@
/* PHY master/slave setting */
#define IGB_MASTER_SLAVE e1000_ms_hw_default
/* Support AutoMediaDetect for Marvell M88 PHY in i354 */
#define IGB_MEDIA_RESET (1 << 0)
/*
* Micellaneous constants
*/
@ -173,11 +176,13 @@
#define IGB_SMARTSPEED_MAX 15
#define IGB_MAX_LOOP 10
#define IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8)
#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : \
((hw->mac.type <= e1000_82576) ? 16 : 8))
#define IGB_RX_HTHRESH 8
#define IGB_RX_WTHRESH 1
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
adapter->msix_mem) ? 1 : 4)
#define IGB_TX_PTHRESH 8
#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
#define IGB_TX_HTHRESH 1
#define IGB_TX_WTHRESH ((hw->mac.type != e1000_82575 && \
adapter->msix_mem) ? 1 : 16)
@ -190,11 +195,6 @@
#define IGB_EEPROM_APME 0x400;
/* Queue minimum free for use */
#define IGB_QUEUE_THRESHOLD (adapter->num_tx_desc / 8)
/* Queue bit defines */
#define IGB_QUEUE_IDLE 1
#define IGB_QUEUE_WORKING 2
#define IGB_QUEUE_HUNG 4
#define IGB_QUEUE_DEPLETED 8
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
@ -228,8 +228,10 @@
#define IGB_BR_SIZE 4096 /* ring buf size */
#define IGB_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
#define IGB_TSO_SEG_SIZE 4096 /* Max dma segment size */
#define IGB_TXPBSIZE 20408
#define IGB_HDR_BUF 128
#define IGB_PKTTYPE_MASK 0x0000FFF0
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coalesce Flush */
#define ETH_ZLEN 60
#define ETH_ADDR_LEN 6
@ -245,6 +247,7 @@
#define IGB_DEFAULT_ITR ((1000000/IGB_INTS_PER_SEC) << 2)
#define IGB_LINK_ITR 2000
#define I210_LINK_DELAY 1000
/* Precision Time Sync (IEEE 1588) defines */
#define ETHERTYPE_IEEE1588 0x88F7
@ -284,34 +287,42 @@ struct igb_queue {
};
/*
* Transmit ring: one per queue
* The transmit ring, one per queue
*/
struct tx_ring {
struct adapter *adapter;
u32 me;
struct adapter *adapter;
struct mtx tx_mtx;
char mtx_name[16];
u32 me;
int watchdog_time;
union e1000_adv_tx_desc *tx_base;
struct igb_tx_buf *tx_buffers;
struct igb_dma_alloc txdma;
struct e1000_tx_desc *tx_base;
u32 next_avail_desc;
u32 next_to_clean;
volatile u16 tx_avail;
struct igb_tx_buffer *tx_buffers;
u16 next_avail_desc;
u16 next_to_clean;
u16 process_limit;
u16 num_desc;
enum {
IGB_QUEUE_IDLE = 1,
IGB_QUEUE_WORKING = 2,
IGB_QUEUE_HUNG = 4,
IGB_QUEUE_DEPLETED = 8,
} queue_status;
u32 txd_cmd;
bus_dma_tag_t txtag;
char mtx_name[16];
#ifndef IGB_LEGACY_TX
struct buf_ring *br;
struct task txq_task;
#endif
bus_dma_tag_t txtag;
u32 bytes;
u32 bytes; /* used for AIM */
u32 packets;
int queue_status;
int watchdog_time;
int tdt;
int tdh;
/* Soft Stats */
unsigned long tso_tx;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
u64 no_desc_avail;
u64 tx_packets;
u64 total_packets;
};
/*
@ -353,43 +364,38 @@ struct rx_ring {
};
struct adapter {
struct ifnet *ifp;
struct e1000_hw hw;
struct ifnet *ifp;
struct e1000_hw hw;
struct e1000_osdep osdep;
struct device *dev;
struct cdev *led_dev;
struct e1000_osdep osdep;
struct device *dev;
struct cdev *led_dev;
struct resource *pci_mem;
struct resource *msix_mem;
struct resource *res;
void *tag;
u32 que_mask;
struct resource *pci_mem;
struct resource *msix_mem;
int memrid;
int linkvec;
int link_mask;
struct task link_task;
int link_irq;
/*
* Interrupt resources: this set is
* either used for legacy, or for Link
* when doing MSIX
*/
void *tag;
struct resource *res;
struct ifmedia media;
struct callout timer;
int msix; /* total vectors allocated */
int if_flags;
int max_frame_size;
int min_frame_size;
int pause_frames;
struct mtx core_mtx;
int igb_insert_vlan_header;
u16 num_queues;
u16 vf_ifp; /* a VF interface */
struct ifmedia media;
struct callout timer;
int msix;
int if_flags;
int pause_frames;
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
u32 num_vlans;
struct mtx core_mtx;
/* Management and WOL features */
int wol;
int has_manage;
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
u16 num_vlans;
u16 num_queues;
/*
** Shadow VFTA table, this is needed because
@ -397,66 +403,86 @@ struct adapter {
** a soft reset and the driver needs to be able
** to repopulate it.
*/
u32 shadow_vfta[IGB_VFTA_SIZE];
u32 shadow_vfta[IGB_VFTA_SIZE];
/* Info about the interface */
u16 link_active;
u16 fc;
u16 link_speed;
u16 link_duplex;
u32 smartspeed;
u32 dmac;
int enable_aim;
u32 optics;
u32 fc; /* local flow ctrl setting */
int advertise; /* link speeds */
bool link_active;
u16 max_frame_size;
u16 num_segs;
u16 link_speed;
bool link_up;
u32 linkvec;
u16 link_duplex;
u32 dmac;
int link_mask;
/* Interface queues */
/* Flags */
u32 flags;
/* Mbuf cluster size */
u32 rx_mbuf_sz;
/* Support for pluggable optics */
bool sfp_probe;
struct task link_task; /* Link tasklet */
struct task mod_task; /* SFP tasklet */
struct task msf_task; /* Multispeed Fiber */
struct taskqueue *tq;
/*
** Queues:
** This is the irq holder, it has
** and RX/TX pair or rings associated
** with it.
*/
struct igb_queue *queues;
/*
* Transmit rings
* Transmit rings:
* Allocated at run time, an array of rings.
*/
struct tx_ring *tx_rings;
u16 num_tx_desc;
u32 num_tx_desc;
/* Multicast array pointer */
u8 *mta;
/*
* Receive rings
/*
* Receive rings:
* Allocated at run time, an array of rings.
*/
struct rx_ring *rx_rings;
bool rx_hdr_split;
u16 num_rx_desc;
int rx_process_limit;
u32 rx_mbuf_sz;
u32 rx_mask;
u64 que_mask;
u32 num_rx_desc;
/* Multicast array memory */
u8 *mta;
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long mbuf_defrag_failed;
unsigned long mbuf_header_failed;
unsigned long mbuf_packet_failed;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long rx_overruns;
unsigned long device_control;
unsigned long rx_control;
unsigned long int_mask;
unsigned long eint_mask;
unsigned long packet_buf_alloc_rx;
unsigned long packet_buf_alloc_tx;
unsigned long dropped_pkts;
unsigned long mbuf_defrag_failed;
unsigned long mbuf_header_failed;
unsigned long mbuf_packet_failed;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long link_irq;
unsigned long rx_overruns;
unsigned long device_control;
unsigned long rx_control;
unsigned long int_mask;
unsigned long eint_mask;
unsigned long packet_buf_alloc_rx;
unsigned long packet_buf_alloc_tx;
/* Used in pf and vf */
void *stats;
boolean_t in_detach;
int enable_aim;
int has_manage;
int wol;
int rx_process_limit;
u16 vf_ifp; /* a VF interface */
bool in_detach; /* Used only in igb_ioctl */
#ifdef IGB_IEEE1588
/* IEEE 1588 precision time support */
struct cyclecounter cycles;
struct nettimer clock;
struct nettime_compare compare;
struct hwtstamp_ctrl hwtstamp;
#endif
void *stats;
};
/* ******************************************************************************
@ -474,11 +500,10 @@ typedef struct _igb_vendor_info_t {
unsigned int index;
} igb_vendor_info_t;
struct igb_tx_buffer {
int next_eop; /* Index of the desc to watch */
struct mbuf *m_head;
bus_dmamap_t map; /* bus_dma map for packet */
struct igb_tx_buf {
union e1000_adv_tx_desc *eop;
struct mbuf *m_head;
bus_dmamap_t map;
};
struct igb_rx_buf {

View file

@ -726,10 +726,15 @@ iscsi_error_callback(struct icl_conn *ic)
static void
iscsi_pdu_handle_nop_in(struct icl_pdu *response)
{
struct iscsi_session *is;
struct iscsi_bhs_nop_out *bhsno;
struct iscsi_bhs_nop_in *bhsni;
struct icl_pdu *request;
void *data = NULL;
size_t datasize;
int error;
is = PDU_SESSION(response);
bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
if (bhsni->bhsni_target_transfer_tag == 0xffffffff) {
@ -741,22 +746,47 @@ iscsi_pdu_handle_nop_in(struct icl_pdu *response)
return;
}
datasize = icl_pdu_data_segment_length(response);
if (datasize > 0) {
data = malloc(datasize, M_ISCSI, M_NOWAIT | M_ZERO);
if (data == NULL) {
ISCSI_SESSION_WARN(is, "failed to allocate memory; "
"reconnecting");
icl_pdu_free(response);
iscsi_session_reconnect(is);
return;
}
icl_pdu_get_data(response, 0, data, datasize);
}
request = icl_pdu_new_bhs(response->ip_conn, M_NOWAIT);
if (request == NULL) {
ISCSI_SESSION_WARN(is, "failed to allocate memory; "
"reconnecting");
free(data, M_ISCSI);
icl_pdu_free(response);
iscsi_session_reconnect(is);
return;
}
bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
ISCSI_BHS_OPCODE_IMMEDIATE;
bhsno->bhsno_flags = 0x80;
bhsno->bhsno_initiator_task_tag = 0xffffffff; /* XXX */
bhsno->bhsno_initiator_task_tag = 0xffffffff;
bhsno->bhsno_target_transfer_tag = bhsni->bhsni_target_transfer_tag;
request->ip_data_len = response->ip_data_len;
request->ip_data_mbuf = response->ip_data_mbuf;
response->ip_data_len = 0;
response->ip_data_mbuf = NULL;
if (datasize > 0) {
error = icl_pdu_append_data(request, data, datasize, M_NOWAIT);
if (error != 0) {
ISCSI_SESSION_WARN(is, "failed to allocate memory; "
"reconnecting");
free(data, M_ISCSI);
icl_pdu_free(request);
icl_pdu_free(response);
iscsi_session_reconnect(is);
return;
}
free(data, M_ISCSI);
}
icl_pdu_free(response);
iscsi_pdu_queue_locked(request);

View file

@ -153,7 +153,7 @@ igb_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
/* curr is the current slot in the nic ring */
union e1000_adv_tx_desc *curr =
(union e1000_adv_tx_desc *)&txr->tx_base[l];
struct igb_tx_buffer *txbuf = &txr->tx_buffers[l];
struct igb_tx_buf *txbuf = &txr->tx_buffers[l];
int flags = ((slot->flags & NS_REPORT) ||
j == 0 || j == report_frequency) ?
E1000_ADVTXD_DCMD_RS : 0;

View file

@ -65,7 +65,7 @@ u_long sb_max_adj =
static u_long sb_efficiency = 8; /* parameter for sbreserve() */
static void sbdrop_internal(struct sockbuf *sb, int len);
static struct mbuf *sbcut_internal(struct sockbuf *sb, int len);
static void sbflush_internal(struct sockbuf *sb);
/*
@ -818,7 +818,7 @@ sbflush_internal(struct sockbuf *sb)
*/
if (!sb->sb_cc && (sb->sb_mb == NULL || sb->sb_mb->m_len))
break;
sbdrop_internal(sb, (int)sb->sb_cc);
m_freem(sbcut_internal(sb, (int)sb->sb_cc));
}
if (sb->sb_cc || sb->sb_mb || sb->sb_mbcnt)
panic("sbflush_internal: cc %u || mb %p || mbcnt %u",
@ -843,15 +843,16 @@ sbflush(struct sockbuf *sb)
}
/*
* Drop data from (the front of) a sockbuf.
* Cut data from (the front of) a sockbuf.
*/
static void
sbdrop_internal(struct sockbuf *sb, int len)
static struct mbuf *
sbcut_internal(struct sockbuf *sb, int len)
{
struct mbuf *m;
struct mbuf *next;
struct mbuf *m, *n, *next, *mfree;
next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
mfree = NULL;
while (len > 0) {
if (m == 0) {
if (next == 0)
@ -872,11 +873,17 @@ sbdrop_internal(struct sockbuf *sb, int len)
}
len -= m->m_len;
sbfree(sb, m);
m = m_free(m);
n = m->m_next;
m->m_next = mfree;
mfree = m;
m = n;
}
while (m && m->m_len == 0) {
sbfree(sb, m);
m = m_free(m);
n = m->m_next;
m->m_next = mfree;
mfree = m;
m = n;
}
if (m) {
sb->sb_mb = m;
@ -894,6 +901,8 @@ sbdrop_internal(struct sockbuf *sb, int len)
} else if (m->m_nextpkt == NULL) {
sb->sb_lastrecord = m;
}
return (mfree);
}
/*
@ -904,17 +913,31 @@ sbdrop_locked(struct sockbuf *sb, int len)
{
SOCKBUF_LOCK_ASSERT(sb);
m_freem(sbcut_internal(sb, len));
}
sbdrop_internal(sb, len);
/*
* Drop data from (the front of) a sockbuf,
* and return it to caller.
*/
struct mbuf *
sbcut_locked(struct sockbuf *sb, int len)
{
SOCKBUF_LOCK_ASSERT(sb);
return (sbcut_internal(sb, len));
}
void
sbdrop(struct sockbuf *sb, int len)
{
struct mbuf *mfree;
SOCKBUF_LOCK(sb);
sbdrop_locked(sb, len);
mfree = sbcut_internal(sb, len);
SOCKBUF_UNLOCK(sb);
m_freem(mfree);
}
/*

View file

@ -1461,6 +1461,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
u_long tiwin;
char *s;
struct in_conninfo *inc;
struct mbuf *mfree;
struct tcpopt to;
#ifdef TCPDEBUG
@ -2718,15 +2719,17 @@ process_ACK:
SOCKBUF_LOCK(&so->so_snd);
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
sbdrop_locked(&so->so_snd, (int)so->so_snd.sb_cc);
mfree = sbcut_locked(&so->so_snd,
(int)so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
sbdrop_locked(&so->so_snd, acked);
mfree = sbcut_locked(&so->so_snd, acked);
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
/* NB: sowwakeup_locked() does an implicit unlock. */
sowwakeup_locked(so);
m_freem(mfree);
/* Detect una wraparound. */
if (!IN_RECOVERY(tp->t_flags) &&
SEQ_GT(tp->snd_una, tp->snd_recover) &&

Some files were not shown because too many files have changed in this diff Show more