version 1.17, 2004/12/16 18:55:52 |
version 1.18, 2004/12/17 21:13:58 |
|
|
#include "rcs.h" |
#include "rcs.h" |
#include "log.h" |
#include "log.h" |
|
|
#define RCS_BUFSIZE 8192 |
#define RCS_BUFSIZE 16384 |
|
#define RCS_BUFEXTSIZE 8192 |
|
|
|
|
/* RCS token types */ |
/* RCS token types */ |
|
|
|
|
/* opaque parse data */ |
/* opaque parse data */ |
struct rcs_pdata { |
struct rcs_pdata { |
u_int rp_line; |
u_int rp_lines; |
|
|
char *rp_buf; |
char *rp_buf; |
size_t rp_blen; |
size_t rp_blen; |
|
char *rp_bufend; |
|
|
/* pushback token buffer */ |
/* pushback token buffer */ |
char rp_ptok[128]; |
char rp_ptok[128]; |
|
|
static void rcs_freepdata (struct rcs_pdata *); |
static void rcs_freepdata (struct rcs_pdata *); |
static int rcs_gettok (RCSFILE *); |
static int rcs_gettok (RCSFILE *); |
static int rcs_pushtok (RCSFILE *, const char *, int); |
static int rcs_pushtok (RCSFILE *, const char *, int); |
|
static int rcs_growbuf (RCSFILE *); |
static int rcs_patch_lines (struct rcs_foo *, struct rcs_foo *); |
static int rcs_patch_lines (struct rcs_foo *, struct rcs_foo *); |
|
|
static struct rcs_delta* rcs_findrev (RCSFILE *, RCSNUM *); |
static struct rcs_delta* rcs_findrev (RCSFILE *, RCSNUM *); |
|
|
{ "text", RCS_TOK_TEXT, RCS_TOK_STRING, RCS_NOSCOL }, |
{ "text", RCS_TOK_TEXT, RCS_TOK_STRING, RCS_NOSCOL }, |
}; |
}; |
|
|
|
#define RCS_NKEYS (sizeof(rcs_keys)/sizeof(rcs_keys[0])) |
|
|
|
|
/* |
/* |
|
|
} |
} |
memset(pdp, 0, sizeof(*pdp)); |
memset(pdp, 0, sizeof(*pdp)); |
|
|
pdp->rp_line = 1; |
pdp->rp_lines = 0; |
pdp->rp_pttype = RCS_TOK_ERR; |
pdp->rp_pttype = RCS_TOK_ERR; |
|
|
pdp->rp_file = fopen(rfp->rf_path, "r"); |
pdp->rp_file = fopen(rfp->rf_path, "r"); |
|
|
return (-1); |
return (-1); |
} |
} |
pdp->rp_blen = RCS_BUFSIZE; |
pdp->rp_blen = RCS_BUFSIZE; |
|
pdp->rp_bufend = pdp->rp_buf + pdp->rp_blen - 1; |
|
|
/* ditch the strict lock */ |
/* ditch the strict lock */ |
rfp->rf_flags &= ~RCS_RF_SLOCK; |
rfp->rf_flags &= ~RCS_RF_SLOCK; |
|
|
} |
} |
|
|
cvs_log(LP_DEBUG, "RCS file `%s' parsed OK (%u lines)", rfp->rf_path, |
cvs_log(LP_DEBUG, "RCS file `%s' parsed OK (%u lines)", rfp->rf_path, |
pdp->rp_line); |
pdp->rp_lines); |
|
|
rcs_freepdata(pdp); |
rcs_freepdata(pdp); |
|
|
|
|
} |
} |
|
|
rk = NULL; |
rk = NULL; |
for (i = 0; i < sizeof(rcs_keys)/sizeof(rcs_keys[0]); i++) |
for (i = 0; i < RCS_NKEYS; i++) |
if (rcs_keys[i].rk_id == tok) |
if (rcs_keys[i].rk_id == tok) |
rk = &(rcs_keys[i]); |
rk = &(rcs_keys[i]); |
|
|
|
|
} |
} |
|
|
rk = NULL; |
rk = NULL; |
for (i = 0; i < sizeof(rcs_keys)/sizeof(rcs_keys[0]); i++) |
for (i = 0; i < RCS_NKEYS; i++) |
if (rcs_keys[i].rk_id == tok) |
if (rcs_keys[i].rk_id == tok) |
rk = &(rcs_keys[i]); |
rk = &(rcs_keys[i]); |
|
|
|
|
* Free the contents of a delta structure. |
* Free the contents of a delta structure. |
*/ |
*/ |
|
|
void |
static void |
rcs_freedelta(struct rcs_delta *rdp) |
rcs_freedelta(struct rcs_delta *rdp) |
{ |
{ |
struct rcs_branch *rb; |
struct rcs_branch *rb; |
|
|
{ |
{ |
u_int i; |
u_int i; |
int ch, last, type; |
int ch, last, type; |
char *bp, *bep; |
size_t len; |
|
char *bp; |
struct rcs_pdata *pdp = (struct rcs_pdata *)rfp->rf_pdata; |
struct rcs_pdata *pdp = (struct rcs_pdata *)rfp->rf_pdata; |
|
|
type = RCS_TOK_ERR; |
type = RCS_TOK_ERR; |
bp = pdp->rp_buf; |
bp = pdp->rp_buf; |
bep = pdp->rp_buf + pdp->rp_blen - 1; |
|
*bp = '\0'; |
*bp = '\0'; |
|
|
if (pdp->rp_pttype != RCS_TOK_ERR) { |
if (pdp->rp_pttype != RCS_TOK_ERR) { |
|
|
do { |
do { |
ch = getc(pdp->rp_file); |
ch = getc(pdp->rp_file); |
if (ch == '\n') |
if (ch == '\n') |
pdp->rp_line++; |
pdp->rp_lines++; |
} while (isspace(ch)); |
} while (isspace(ch)); |
|
|
if (ch == EOF) { |
if (ch == EOF) { |
|
|
} else if (ch == ':') { |
} else if (ch == ':') { |
type = RCS_TOK_COLON; |
type = RCS_TOK_COLON; |
} else if (isalpha(ch)) { |
} else if (isalpha(ch)) { |
|
type = RCS_TOK_STRING; |
*(bp++) = ch; |
*(bp++) = ch; |
while (bp <= bep - 1) { |
for (;;) { |
ch = getc(pdp->rp_file); |
ch = getc(pdp->rp_file); |
if (!isalnum(ch) && ch != '_' && ch != '-') { |
if (!isalnum(ch) && ch != '_' && ch != '-') { |
ungetc(ch, pdp->rp_file); |
ungetc(ch, pdp->rp_file); |
break; |
break; |
} |
} |
*(bp++) = ch; |
*(bp++) = ch; |
|
if (bp == pdp->rp_bufend - 1) { |
|
len = bp - pdp->rp_buf; |
|
if (rcs_growbuf(rfp) < 0) { |
|
type = RCS_TOK_ERR; |
|
break; |
|
} |
|
bp = pdp->rp_buf + len; |
|
} |
} |
} |
*bp = '\0'; |
*bp = '\0'; |
|
|
for (i = 0; i < sizeof(rcs_keys)/sizeof(rcs_keys[0]); i++) { |
if (type != RCS_TOK_ERR) { |
if (strcmp(rcs_keys[i].rk_str, pdp->rp_buf) == 0) { |
for (i = 0; i < RCS_NKEYS; i++) { |
type = rcs_keys[i].rk_id; |
if (strcmp(rcs_keys[i].rk_str, |
break; |
pdp->rp_buf) == 0) { |
|
type = rcs_keys[i].rk_id; |
|
break; |
|
} |
} |
} |
} |
} |
|
|
/* not a keyword, assume it's just a string */ |
|
if (type == RCS_TOK_ERR) |
|
type = RCS_TOK_STRING; |
|
|
|
} else if (ch == '@') { |
} else if (ch == '@') { |
/* we have a string */ |
/* we have a string */ |
|
type = RCS_TOK_STRING; |
for (;;) { |
for (;;) { |
ch = getc(pdp->rp_file); |
ch = getc(pdp->rp_file); |
if (ch == '@') { |
if (ch == '@') { |
|
|
break; |
break; |
} |
} |
} else if (ch == '\n') |
} else if (ch == '\n') |
pdp->rp_line++; |
pdp->rp_lines++; |
|
|
*(bp++) = ch; |
*(bp++) = ch; |
if (bp == bep) |
if (bp == pdp->rp_bufend - 1) { |
break; |
len = bp - pdp->rp_buf; |
|
if (rcs_growbuf(rfp) < 0) { |
|
type = RCS_TOK_ERR; |
|
break; |
|
} |
|
bp = pdp->rp_buf + len; |
|
} |
} |
} |
|
|
*bp = '\0'; |
*bp = '\0'; |
type = RCS_TOK_STRING; |
|
} else if (isdigit(ch)) { |
} else if (isdigit(ch)) { |
*(bp++) = ch; |
*(bp++) = ch; |
last = ch; |
last = ch; |
|
|
|
|
for (;;) { |
for (;;) { |
ch = getc(pdp->rp_file); |
ch = getc(pdp->rp_file); |
if (bp == bep) |
if (bp == pdp->rp_bufend) |
break; |
break; |
if (!isdigit(ch) && ch != '.') { |
if (!isdigit(ch) && ch != '.') { |
ungetc(ch, pdp->rp_file); |
ungetc(ch, pdp->rp_file); |
|
|
last = ch; |
last = ch; |
*(bp++) = ch; |
*(bp++) = ch; |
} |
} |
*(bp) = '\0'; |
*bp = '\0'; |
} |
} |
|
|
return (type); |
return (type); |
|
|
} |
} |
free(fp->rl_data); |
free(fp->rl_data); |
free(fp); |
free(fp); |
|
} |
|
|
|
/* |
|
* rcs_growbuf() |
|
* |
|
* Attempt to grow the internal parse buffer for the RCS file <rf> by |
|
* RCS_BUFEXTSIZE. |
|
* In case of failure, the original buffer is left unmodified. |
|
* Returns 0 on success, or -1 on failure. |
|
*/ |
|
|
|
static int |
|
rcs_growbuf(RCSFILE *rf) |
|
{ |
|
void *tmp; |
|
struct rcs_pdata *pdp = (struct rcs_pdata *)rf->rf_pdata; |
|
|
|
tmp = realloc(pdp->rp_buf, pdp->rp_blen + RCS_BUFEXTSIZE); |
|
if (tmp == NULL) { |
|
cvs_log(LP_ERRNO, "failed to grow RCS parse buffer"); |
|
return (-1); |
|
} |
|
|
|
pdp->rp_buf = (char *)tmp; |
|
pdp->rp_blen += RCS_BUFEXTSIZE; |
|
pdp->rp_bufend = pdp->rp_buf + pdp->rp_blen - 1; |
|
|
|
return (0); |
} |
} |