summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cvs/cvs/rcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cvs/cvs/rcs.c')
-rw-r--r--gnu/usr.bin/cvs/cvs/rcs.c302
1 files changed, 210 insertions, 92 deletions
diff --git a/gnu/usr.bin/cvs/cvs/rcs.c b/gnu/usr.bin/cvs/cvs/rcs.c
index e882b8c..2c424d9 100644
--- a/gnu/usr.bin/cvs/cvs/rcs.c
+++ b/gnu/usr.bin/cvs/cvs/rcs.c
@@ -2,7 +2,7 @@
* Copyright (c) 1992, Brian Berliner and Jeff Polk
*
* You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS 1.3 kit.
+ * specified in the README file that comes with the CVS 1.4 kit.
*
* The routines contained in this file do all the rcs file parsing and
* manipulation
@@ -11,37 +11,54 @@
#include "cvs.h"
#ifndef lint
-static char rcsid[] = "@(#)rcs.c 1.28 92/03/31";
+static char rcsid[] = "$CVSid: @(#)rcs.c 1.40 94/10/07 $";
+USE(rcsid)
#endif
-#if __STDC__
-static char *RCS_getbranch (RCSNode * rcs, char *tag, int force_tag_match);
-static char *RCS_getdatebranch (RCSNode * rcs, char *date, char *branch);
-static int getrcskey (FILE * fp, char **keyp, char **valp);
-static int parse_rcs_proc (Node * file);
-static int checkmagic_proc (Node *p);
-static void do_branches (List * list, char *val);
-static void do_symbols (List * list, char *val);
-static void null_delproc (Node * p);
-static void rcsnode_delproc (Node * p);
-static void rcsvers_delproc (Node * p);
-#else
-static int parse_rcs_proc ();
-static int checkmagic_proc ();
-static void rcsnode_delproc ();
-static void rcsvers_delproc ();
-static void null_delproc ();
-static int getrcskey ();
-static void do_symbols ();
-static void do_branches ();
-static char *RCS_getbranch ();
-static char *RCS_getdatebranch ();
-#endif /* __STDC__ */
+static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, char *rcsfile));
+static char *RCS_getdatebranch PROTO((RCSNode * rcs, char *date, char *branch));
+static int getrcskey PROTO((FILE * fp, char **keyp, char **valp));
+static int parse_rcs_proc PROTO((Node * file, void *closure));
+static int checkmagic_proc PROTO((Node *p, void *closure));
+static void do_branches PROTO((List * list, char *val));
+static void do_symbols PROTO((List * list, char *val));
+static void null_delproc PROTO((Node * p));
+static void rcsnode_delproc PROTO((Node * p));
+static void rcsvers_delproc PROTO((Node * p));
static List *rcslist;
static char *repository;
/*
+ * We don't want to use isspace() from the C library because:
+ *
+ * 1. The definition of "whitespace" in RCS files includes ASCII
+ * backspace, but the C locale doesn't.
+ * 2. isspace is an very expensive function call in some implementations
+ * due to the addition of wide character support.
+ */
+static const char spacetab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x00 - 0x0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
+};
+
+#define whitespace(c) (spacetab[c] != 0)
+
+/*
* Parse all the rcs files specified and return a list
*/
List *
@@ -54,7 +71,7 @@ RCS_parsefiles (files, xrepos)
rcslist = getlist ();
/* walk the list parsing files */
- if (walklist (files, parse_rcs_proc) != 0)
+ if (walklist (files, parse_rcs_proc, NULL) != 0)
{
/* free the list and return NULL on error */
dellist (&rcslist);
@@ -69,10 +86,10 @@ RCS_parsefiles (files, xrepos)
* Parse an rcs file into a node on the rcs list
*/
static int
-parse_rcs_proc (file)
+parse_rcs_proc (file, closure)
Node *file;
+ void *closure;
{
- Node *p;
RCSNode *rdata;
/* parse the rcs file into rdata */
@@ -80,18 +97,33 @@ parse_rcs_proc (file)
/* if we got a valid RCSNode back, put it on the list */
if (rdata != (RCSNode *) NULL)
- {
- p = getnode ();
- p->key = xstrdup (file->key);
- p->delproc = rcsnode_delproc;
- p->type = RCSNODE;
- p->data = (char *) rdata;
- (void) addnode (rcslist, p);
- }
+ RCS_addnode (file->key, rdata, rcslist);
+
return (0);
}
/*
+ * Add an RCSNode to a list of them.
+ */
+
+void
+RCS_addnode (file, rcs, list)
+ char *file;
+ RCSNode *rcs;
+ List *list;
+{
+ Node *p;
+
+ p = getnode ();
+ p->key = xstrdup (file);
+ p->delproc = rcsnode_delproc;
+ p->type = RCSNODE;
+ p->data = (char *) rcs;
+ (void) addnode (list, p);
+}
+
+
+/*
* Parse an rcsfile given a user file name and a repository
*/
RCSNode *
@@ -100,43 +132,46 @@ RCS_parse (file, repos)
char *repos;
{
RCSNode *rcs;
+ FILE *fp;
char rcsfile[PATH_MAX];
(void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT);
- if (!isreadable (rcsfile))
+ if ((fp = fopen (rcsfile, "r")) != NULL)
{
- (void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC,
- file, RCSEXT);
- if (!isreadable (rcsfile))
- return (NULL);
- rcs = RCS_parsercsfile (rcsfile);
+ rcs = RCS_parsercsfile_i(fp, rcsfile);
+ if (rcs != NULL)
+ rcs->flags |= VALID;
+
+ fclose (fp);
+ return (rcs);
+ }
+
+ (void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, file, RCSEXT);
+ if ((fp = fopen (rcsfile, "r")) != NULL)
+ {
+ rcs = RCS_parsercsfile_i(fp, rcsfile);
if (rcs != NULL)
{
rcs->flags |= INATTIC;
rcs->flags |= VALID;
}
+
+ fclose (fp);
return (rcs);
}
- rcs = RCS_parsercsfile (rcsfile);
- if (rcs != NULL)
- rcs->flags |= VALID;
- return (rcs);
+
+ return (NULL);
}
/*
- * Do the real work of parsing an RCS file
+ * Parse a specific rcsfile.
*/
RCSNode *
RCS_parsercsfile (rcsfile)
char *rcsfile;
{
- Node *q, *r;
- RCSNode *rdata;
- RCSVers *vnode;
- int n;
- char *cp;
- char *key, *value;
FILE *fp;
+ RCSNode *rcs;
/* open the rcsfile */
if ((fp = fopen (rcsfile, "r")) == NULL)
@@ -145,9 +180,30 @@ RCS_parsercsfile (rcsfile)
return (NULL);
}
+ rcs = RCS_parsercsfile_i (fp, rcsfile);
+
+ fclose (fp);
+ return (rcs);
+}
+
+/*
+ * Do the real work of parsing an RCS file
+ */
+static RCSNode *
+RCS_parsercsfile_i (fp, rcsfile)
+ FILE *fp;
+ char *rcsfile;
+{
+ Node *q, *r;
+ RCSNode *rdata;
+ RCSVers *vnode;
+ int n;
+ char *cp;
+ char *key, *value;
+
/* make a node */
rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
- bzero ((char *) rdata, sizeof (RCSNode));
+ memset ((char *) rdata, 0, sizeof (RCSNode));
rdata->refcount = 1;
rdata->path = xstrdup (rcsfile);
rdata->versions = getlist ();
@@ -161,14 +217,24 @@ RCS_parsercsfile (rcsfile)
{
/* get the next key/value pair */
- /* if key is NULL here, then the file is missing some headers */
+ /* if key is NULL here, then the file is missing some headers
+ or we had trouble reading the file. */
if (getrcskey (fp, &key, &value) == -1 || key == NULL)
{
+
if (!really_quiet)
- error (0, 0, "`%s' does not appear to be a valid rcs file",
- rcsfile);
+ {
+ if (ferror(fp))
+ {
+ error (1, 0, "error reading `%s'", rcsfile);
+ }
+ else
+ {
+ error (0, 0, "`%s' does not appear to be a valid rcs file",
+ rcsfile);
+ }
+ }
freercsnode (&rdata);
- (void) fclose (fp);
return (NULL);
}
@@ -184,7 +250,7 @@ RCS_parsercsfile (rcsfile)
if ((numdots (rdata->branch) & 1) != 0)
{
/* turn it into a branch if it's a revision */
- cp = rindex (rdata->branch, '.');
+ cp = strrchr (rdata->branch, '.');
*cp = '\0';
}
continue;
@@ -193,9 +259,7 @@ RCS_parsercsfile (rcsfile)
{
if (value != NULL)
{
- /* if there are tags, set up the tag list */
- rdata->symbols = getlist ();
- do_symbols (rdata->symbols, value);
+ rdata->symbols_data = xstrdup(value);
continue;
}
}
@@ -225,7 +289,7 @@ RCS_parsercsfile (rcsfile)
/* grab the value of the date from value */
valp = value + strlen (RCSDATE);/* skip the "date" keyword */
- while (isspace (*valp)) /* take space off front of value */
+ while (whitespace (*valp)) /* take space off front of value */
valp++;
(void) strcpy (date, valp);
@@ -237,7 +301,7 @@ RCS_parsercsfile (rcsfile)
q->delproc = rcsvers_delproc;
r->delproc = null_delproc;
q->data = r->data = xmalloc (sizeof (RCSVers));
- bzero (q->data, sizeof (RCSVers));
+ memset (q->data, 0, sizeof (RCSVers));
vnode = (RCSVers *) q->data;
/* fill in the version before we forget it */
@@ -290,7 +354,6 @@ RCS_parsercsfile (rcsfile)
break;
}
- (void) fclose (fp);
return (rdata);
}
@@ -325,6 +388,8 @@ freercsnode (rnodep)
dellist (&(*rnodep)->dates);
if ((*rnodep)->symbols != (List *) NULL)
dellist (&(*rnodep)->symbols);
+ if ((*rnodep)->symbols_data != (char *) NULL)
+ free ((*rnodep)->symbols_data);
if ((*rnodep)->head != (char *) NULL)
free ((*rnodep)->head);
if ((*rnodep)->branch != (char *) NULL)
@@ -405,14 +470,14 @@ getrcskey (fp, keyp, valp)
*valp = (char *) NULL;
return (-1);
}
- if (!isspace (c))
+ if (!whitespace (c))
break;
}
/* fill in key */
cur = key;
max = key + keysize;
- while (!isspace (c) && c != ';')
+ while (!whitespace (c) && c != ';')
{
if (cur < max)
*cur++ = c;
@@ -432,6 +497,14 @@ getrcskey (fp, keyp, valp)
return (-1);
}
}
+ if (cur >= max)
+ {
+ key = xrealloc (key, keysize + ALLOCINCR);
+ cur = key + keysize;
+ keysize += ALLOCINCR;
+ max = key + keysize;
+ }
+
*cur = '\0';
/* if we got "desc", we are done with the file */
@@ -538,10 +611,10 @@ getrcskey (fp, keyp, valp)
*/
/* whitespace with white set means compress it out */
- if (white && isspace (c))
+ if (white && whitespace (c))
continue;
- if (isspace (c))
+ if (whitespace (c))
{
/* make c a space and set white */
white = 1;
@@ -568,7 +641,16 @@ getrcskey (fp, keyp, valp)
/* terminate the string */
if (cur)
+ {
+ if (cur >= max)
+ {
+ value = xrealloc (value, valsize + ALLOCINCR);
+ cur = value + valsize;
+ valsize += ALLOCINCR;
+ max = value + valsize;
+ }
*cur = '\0';
+ }
/* if the string is empty, make it null */
if (value && *value != '\0')
@@ -594,7 +676,7 @@ do_symbols (list, val)
for (;;)
{
/* skip leading whitespace */
- while (isspace (*cp))
+ while (whitespace (*cp))
cp++;
/* if we got to the end, we are done */
@@ -603,10 +685,10 @@ do_symbols (list, val)
/* split it up into tag and rev */
tag = cp;
- cp = index (cp, ':');
+ cp = strchr (cp, ':');
*cp++ = '\0';
rev = cp;
- while (!isspace (*cp) && *cp != '\0')
+ while (!whitespace (*cp) && *cp != '\0')
cp++;
if (*cp != '\0')
*cp++ = '\0';
@@ -634,7 +716,7 @@ do_branches (list, val)
for (;;)
{
/* skip leading whitespace */
- while (isspace (*cp))
+ while (whitespace (*cp))
cp++;
/* if we got to the end, we are done */
@@ -643,7 +725,7 @@ do_branches (list, val)
/* find the end of this branch */
branch = cp;
- while (!isspace (*cp) && *cp != '\0')
+ while (!whitespace (*cp) && *cp != '\0')
cp++;
if (*cp != '\0')
*cp++ = '\0';
@@ -686,7 +768,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
if (tagrev == NULL)
return ((char *) NULL);
- if ((cp = rindex (tagrev, '.')) != NULL)
+ if ((cp = strrchr (tagrev, '.')) != NULL)
*cp = '\0';
rev = RCS_getdatebranch (rcs, date, tagrev);
free (tagrev);
@@ -733,8 +815,9 @@ RCS_gettag (rcs, tag, force_tag_match)
/* If we got a symbolic tag, resolve it to a numeric */
if (rcs == NULL)
p = NULL;
- else
- p = findnode (rcs->symbols, tag);
+ else {
+ p = findnode (RCS_symbols(rcs), tag);
+ }
if (p != NULL)
{
int dots;
@@ -750,7 +833,7 @@ RCS_gettag (rcs, tag, force_tag_match)
dots = numdots (tag);
if (dots > 2 && (dots & 1) != 0)
{
- branch = rindex (tag, '.');
+ branch = strrchr (tag, '.');
cp = branch++ - 1;
while (*cp != '.')
cp--;
@@ -874,7 +957,7 @@ RCS_magicrev (rcs, rev)
(void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num);
/* walk the symbols list to see if a magic one already exists */
- if (walklist (rcs->symbols, checkmagic_proc) != 0)
+ if (walklist (RCS_symbols(rcs), checkmagic_proc, NULL) != 0)
continue;
/* we found a free magic branch. Claim it as ours */
@@ -887,8 +970,9 @@ RCS_magicrev (rcs, rev)
* Returns 0 if the symbol does not match, 1 if it does.
*/
static int
-checkmagic_proc (p)
+checkmagic_proc (p, closure)
Node *p;
+ void *closure;
{
if (strcmp (check_rev, p->data) == 0)
return (1);
@@ -897,9 +981,9 @@ checkmagic_proc (p)
}
/*
- * Returns non-zero if the specified revision number or symbolic tag
- * resolves to a "branch" within the rcs file. We do take into account
- * any magic branches as well.
+ * Given a list of RCSNodes, returns non-zero if the specified
+ * revision number or symbolic tag resolves to a "branch" within the
+ * rcs file.
*/
int
RCS_isbranch (file, rev, srcfiles)
@@ -907,7 +991,6 @@ RCS_isbranch (file, rev, srcfiles)
char *rev;
List *srcfiles;
{
- int dots;
Node *p;
RCSNode *rcs;
@@ -922,7 +1005,27 @@ RCS_isbranch (file, rev, srcfiles)
/* now, look for a match in the symbols list */
rcs = (RCSNode *) p->data;
- p = findnode (rcs->symbols, rev);
+ return (RCS_nodeisbranch (rev, rcs));
+}
+
+/*
+ * Given an RCSNode, returns non-zero if the specified revision number
+ * or symbolic tag resolves to a "branch" within the rcs file. We do
+ * take into account any magic branches as well.
+ */
+int
+RCS_nodeisbranch (rev, rcs)
+ char *rev;
+ RCSNode *rcs;
+{
+ int dots;
+ Node *p;
+
+ /* numeric revisions are easy -- even number of dots is a branch */
+ if (isdigit (*rev))
+ return ((numdots (rev) & 1) == 0);
+
+ p = findnode (RCS_symbols(rcs), rev);
if (p == NULL)
return (0);
dots = numdots (p->data);
@@ -933,7 +1036,7 @@ RCS_isbranch (file, rev, srcfiles)
if (dots > 2)
{
char *magic;
- char *branch = rindex (p->data, '.');
+ char *branch = strrchr (p->data, '.');
char *cp = branch - 1;
while (*cp != '.')
cp--;
@@ -972,7 +1075,7 @@ RCS_whatbranch (file, rev, srcfiles)
/* now, look for a match in the symbols list */
rcs = (RCSNode *) p->data;
- p = findnode (rcs->symbols, rev);
+ p = findnode (RCS_symbols(rcs), rev);
if (p == NULL)
return ((char *) NULL);
dots = numdots (p->data);
@@ -983,7 +1086,7 @@ RCS_whatbranch (file, rev, srcfiles)
if (dots > 2)
{
char *magic;
- char *branch = rindex (p->data, '.');
+ char *branch = strrchr (p->data, '.');
char *cp = branch++ - 1;
while (*cp != '.')
cp--;
@@ -1008,7 +1111,7 @@ RCS_whatbranch (file, rev, srcfiles)
* Get the head of the specified branch. If the branch does not exist,
* return NULL or RCS_head depending on force_tag_match
*/
-static char *
+char *
RCS_getbranch (rcs, tag, force_tag_match)
RCSNode *rcs;
char *tag;
@@ -1025,7 +1128,7 @@ RCS_getbranch (rcs, tag, force_tag_match)
return ((char *) NULL);
/* find out if the tag contains a dot, or is on the trunk */
- cp = rindex (tag, '.');
+ cp = strrchr (tag, '.');
/* trunk processing is the special case */
if (cp == NULL)
@@ -1237,7 +1340,7 @@ RCS_getdatebranch (rcs, date, branch)
/* look up the first revision on the branch */
xrev = xstrdup (branch);
- cp = rindex (xrev, '.');
+ cp = strrchr (xrev, '.');
if (cp == NULL)
{
free (xrev);
@@ -1374,6 +1477,20 @@ RCS_getrevtime (rcs, rev, date, fudge)
return (revdate);
}
+List *
+RCS_symbols(rcs)
+ RCSNode *rcs;
+{
+ if (rcs->symbols_data) {
+ rcs->symbols = getlist ();
+ do_symbols (rcs->symbols, rcs->symbols_data);
+ free(rcs->symbols_data);
+ rcs->symbols_data = NULL;
+ }
+
+ return rcs->symbols;
+}
+
/*
* The argument ARG is the getopt remainder of the -k option specified on the
* command line. This function returns malloc'ed space that can be used
@@ -1439,7 +1556,7 @@ RCS_check_tag (tag)
if (!isgraph (*cp))
error (1, 0, "tag `%s' has non-visible graphic characters",
tag);
- if (index (invalid, *cp))
+ if (strchr (invalid, *cp))
error (1, 0, "tag `%s' must not contain the characters `%s'",
tag, invalid);
}
@@ -1447,3 +1564,4 @@ RCS_check_tag (tag)
else
error (1, 0, "tag `%s' must start with a letter", tag);
}
+
OpenPOWER on IntegriCloud