#include "rcsbase.h"
libId(keepId, "$Id: rcskeep.c,v 1.1.1.1 1999/04/23 01:43:39 wsanchez Exp $")
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;
{
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;
}
bufscpy(&prevauthor, "");
bufscpy(&prevdate, "");
bufscpy(&prevname, ""); prevname_found = 0;
bufscpy(&prevrev, "");
bufscpy(&prevstate, "");
c = '\0';
for (;;) {
if ( c==KDELIM) {
do {
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:
if (!(
getval(fp, (struct buf*)0, false) &&
keeprev(fp) &&
(c = keepdate(fp)) &&
keepid(c, fp, &prevauthor) &&
keepid(0, fp, &prevstate)
))
return false;
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;
{
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;
{ 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;
case '\n':
case 0:
return badly_terminated();
}
Igeteof_(fp, c, return badly_terminated();)
}
}
static int
keepdate(fp)
RILE *fp;
{
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",
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;
{
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;
{
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
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