rcsnum_free(datenum); return (-1);
rcs_parse_delta(RCSFILE *rfp){	int ret, tok, ntok, hmask;	u_int i;	char *tokstr;	RCSNUM *datenum;	struct rcs_delta *rdp;	struct rcs_key *rk;	rdp = (struct rcs_delta *)malloc(sizeof(*rdp));	if (rdp == NULL) {		cvs_log(LP_ERRNO, "failed to allocate RCS delta structure");		return (-1);	}	memset(rdp, 0, sizeof(*rdp));	rdp->rd_num = rcsnum_alloc();	if (rdp->rd_num == NULL) {		rcs_freedelta(rdp);		return (-1);	}	rdp->rd_next = rcsnum_alloc();	if (rdp->rd_next == NULL) {		rcs_freedelta(rdp);		return (-1);	}	TAILQ_INIT(&(rdp->rd_branches));	tok = rcs_gettok(rfp);	if (tok != RCS_TOK_NUM) {		cvs_log(LP_ERR, "unexpected token `%s' at start of delta",		    RCS_TOKSTR(rfp));		rcs_freedelta(rdp);		return (-1);	}	rcsnum_aton(RCS_TOKSTR(rfp), NULL, rdp->rd_num);	hmask = 0;	ret = 0;	tokstr = NULL;	for (;;) {		tok = rcs_gettok(rfp);		if (tok == RCS_TOK_ERR) {			cvs_log(LP_ERR, "parse error in RCS delta section");			rcs_freedelta(rdp);			return (-1);		} else if (tok == RCS_TOK_NUM || tok == RCS_TOK_DESC) {			rcs_pushtok(rfp, RCS_TOKSTR(rfp), tok);			ret = (tok == RCS_TOK_NUM ? 1 : 0);			break;		}		rk = NULL;		for (i = 0; i < RCS_NKEYS; i++)			if (rcs_keys[i].rk_id == tok)				rk = &(rcs_keys[i]);		if (hmask & (1 << tok)) {			cvs_log(LP_ERR, "duplicate RCS key");			rcs_freedelta(rdp);			return (-1);		}		hmask |= (1 << tok);		switch (tok) {		case RCS_TOK_DATE:		case RCS_TOK_AUTHOR:		case RCS_TOK_STATE:		case RCS_TOK_NEXT:			ntok = rcs_gettok(rfp);			if (ntok == RCS_TOK_SCOLON) {				if (rk->rk_flags & RCS_VOPT)					break;				else {					cvs_log(LP_ERR, "missing mandatory "					    "value to RCS key `%s'",					    rk->rk_str);					rcs_freedelta(rdp);					return (-1);				}			}			if (ntok != rk->rk_val) {				cvs_log(LP_ERR,				    "invalid value type for RCS key `%s'",				    rk->rk_str);				rcs_freedelta(rdp);				return (-1);			}			if (tokstr != NULL)				free(tokstr);			tokstr = strdup(RCS_TOKSTR(rfp));			if (tokstr == NULL) {				cvs_log(LP_ERRNO,				    "failed to duplicate rcs token");				rcs_freedelta(rdp);				return (-1);			}			/* now get the expected semi-colon */			ntok = rcs_gettok(rfp);			if (ntok != RCS_TOK_SCOLON) {				cvs_log(LP_ERR,				    "missing semi-colon after RCS `%s' key",				    rk->rk_str);				rcs_freedelta(rdp);				return (-1);			}			if (tok == RCS_TOK_DATE) {				if ((datenum = rcsnum_parse(tokstr)) == NULL) {					rcs_freedelta(rdp);					return (-1);				}				if (datenum->rn_len != 6) {					cvs_log(LP_ERR,					    "RCS date specification has %s "					    "fields",					    (datenum->rn_len > 6) ? "too many" :					    "missing");					rcs_freedelta(rdp);				}				rdp->rd_date.tm_year = datenum->rn_id[0];				if (rdp->rd_date.tm_year >= 1900)					rdp->rd_date.tm_year -= 1900;				rdp->rd_date.tm_mon = datenum->rn_id[1] - 1;				rdp->rd_date.tm_mday = datenum->rn_id[2];				rdp->rd_date.tm_hour = datenum->rn_id[3];				rdp->rd_date.tm_min = datenum->rn_id[4];				rdp->rd_date.tm_sec = datenum->rn_id[5];				rcsnum_free(datenum);			} else if (tok == RCS_TOK_AUTHOR) {				rdp->rd_author = tokstr;				tokstr = NULL;			} else if (tok == RCS_TOK_STATE) {				rdp->rd_state = tokstr;				tokstr = NULL;			} else if (tok == RCS_TOK_NEXT) {				rcsnum_aton(tokstr, NULL, rdp->rd_next);			}			break;		case RCS_TOK_BRANCHES:			rcs_parse_branches(rfp, rdp);			break;		default:			cvs_log(LP_ERR,			    "unexpected token `%s' in RCS delta",			    RCS_TOKSTR(rfp));			rcs_freedelta(rdp);			return (-1);		}	}	if (tokstr != NULL)		free(tokstr);	TAILQ_INSERT_TAIL(&(rfp->rf_delta), rdp, rd_list);	rfp->rf_ndelta++;	return (ret);}