version 1.186, 2006/07/30 03:47:48 |
version 1.187, 2006/08/02 03:23:40 |
|
|
static void rcs_growbuf(RCSFILE *); |
static void rcs_growbuf(RCSFILE *); |
static void rcs_strprint(const u_char *, size_t, FILE *); |
static void rcs_strprint(const u_char *, size_t, FILE *); |
|
|
static char* rcs_expand_keywords(char *, struct rcs_delta *, char *, |
static BUF *rcs_expand_keywords(char *, struct rcs_delta *, BUF *, int); |
size_t, int); |
|
|
|
RCSFILE * |
RCSFILE * |
rcs_open(const char *path, int fd, int flags, ...) |
rcs_open(const char *path, int fd, int flags, ...) |
|
|
* |
* |
* On error, return NULL. |
* On error, return NULL. |
*/ |
*/ |
static char * |
static BUF * |
rcs_expand_keywords(char *rcsfile, struct rcs_delta *rdp, char *data, |
rcs_expand_keywords(char *rcsfile, struct rcs_delta *rdp, BUF *bp, int mode) |
size_t len, int mode) |
|
{ |
{ |
ptrdiff_t c_offset, sizdiff, start_offset; |
BUF *newbuf; |
size_t i; |
|
int kwtype; |
int kwtype; |
u_int j, found; |
u_int j, found; |
char *c, *kwstr, *start, *end, *tbuf; |
u_char *c, *kwstr, *start, *end, *fin; |
char expbuf[256], buf[256]; |
char expbuf[256], buf[256]; |
|
struct tm tb; |
char *fmt; |
char *fmt; |
|
size_t len; |
|
|
kwtype = 0; |
kwtype = 0; |
kwstr = NULL; |
kwstr = NULL; |
i = 0; |
|
|
|
|
len = cvs_buf_len(bp); |
|
|
|
c = cvs_buf_get(bp); |
|
found = 0; |
|
/* Final character in buffer. */ |
|
fin = c + len - 1; |
|
|
|
/* If no keywords are found, return original buffer. */ |
|
newbuf = bp; |
|
|
/* |
/* |
* Keyword formats: |
* Keyword formats: |
* $Keyword$ |
* $Keyword$ |
* $Keyword: value$ |
* $Keyword: value$ |
*/ |
*/ |
for (c = data; *c != '\0' && i < len; c++) { |
for (; c < fin; c++) { |
if (*c == '$') { |
if (*c == '$') { |
|
BUF *tmpbuf; |
|
size_t clen; |
|
|
/* remember start of this possible keyword */ |
/* remember start of this possible keyword */ |
start = c; |
start = c; |
start_offset = start - data; |
|
|
|
/* first following character has to be alphanumeric */ |
/* first following character has to be alphanumeric */ |
c++; |
c++; |
|
|
continue; |
continue; |
} |
} |
|
|
|
/* Number of characters between c and fin, inclusive. */ |
|
clen = fin - c + 1; |
|
|
/* look for any matching keywords */ |
/* look for any matching keywords */ |
found = 0; |
found = 0; |
for (j = 0; j < RCS_NKWORDS; j++) { |
for (j = 0; j < RCS_NKWORDS; j++) { |
if (!strncmp(c, rcs_expkw[j].kw_str, |
size_t kwlen; |
strlen(rcs_expkw[j].kw_str))) { |
|
|
kwlen = strlen(rcs_expkw[j].kw_str); |
|
/* |
|
* kwlen must be less than clen since clen |
|
* includes either a terminating `$' or a `:'. |
|
*/ |
|
if (kwlen < clen && |
|
memcmp(c, rcs_expkw[j].kw_str, kwlen) == 0 && |
|
(c[kwlen] == '$' || c[kwlen] == ':')) { |
found = 1; |
found = 1; |
kwstr = rcs_expkw[j].kw_str; |
kwstr = rcs_expkw[j].kw_str; |
kwtype = rcs_expkw[j].kw_type; |
kwtype = rcs_expkw[j].kw_type; |
|
c += kwlen; |
break; |
break; |
} |
} |
} |
} |
|
|
if (cvs_tagname != NULL && |
|
!strncmp(c, cvs_tagname, strlen(cvs_tagname)) && |
|
found != 1) { |
|
found = 1; |
|
kwstr = cvs_tagname; |
|
kwtype = RCS_KW_ID; |
|
} |
|
|
|
/* unknown keyword, continue looking */ |
/* unknown keyword, continue looking */ |
if (found == 0) { |
if (found == 0) { |
c = start; |
c = start; |
continue; |
continue; |
} |
} |
|
|
/* next character has to be ':' or '$' */ |
|
c += strlen(kwstr); |
|
if (*c != ':' && *c != '$') { |
|
c = start; |
|
continue; |
|
} |
|
|
|
/* |
/* |
* if the next character was ':' we need to look for |
* if the next character was ':' we need to look for |
* an '$' before the end of the line to be sure it is |
* an '$' before the end of the line to be sure it is |
* in fact a keyword. |
* in fact a keyword. |
*/ |
*/ |
if (*c == ':') { |
if (*c == ':') { |
while (*c++) { |
for (; c <= fin; ++c) { |
if (*c == '$' || *c == '\n') |
if (*c == '$' || *c == '\n') |
break; |
break; |
} |
} |
|
|
continue; |
continue; |
} |
} |
} |
} |
c_offset = c - data; |
|
end = c + 1; |
end = c + 1; |
|
|
/* start constructing the expansion */ |
/* start constructing the expansion */ |
|
|
sizeof(expbuf)) >= sizeof(expbuf)) |
sizeof(expbuf)) >= sizeof(expbuf)) |
fatal("rcs_expand_keywords: truncated"); |
fatal("rcs_expand_keywords: truncated"); |
|
|
sizdiff = strlen(expbuf) - (end - start); |
/* Concatenate everything together. */ |
tbuf = xstrdup(end); |
tmpbuf = cvs_buf_alloc(len + strlen(expbuf), BUF_AUTOEXT); |
|
/* Append everything before keyword. */ |
|
cvs_buf_append(tmpbuf, cvs_buf_get(newbuf), |
|
start - (unsigned char *)cvs_buf_get(newbuf)); |
|
/* Append keyword. */ |
|
cvs_buf_append(tmpbuf, expbuf, strlen(expbuf)); |
|
/* Point c to end of keyword. */ |
|
c = cvs_buf_get(tmpbuf) + cvs_buf_len(tmpbuf) - 1; |
|
/* Append everything after keyword. */ |
|
cvs_buf_append(tmpbuf, end, |
|
((unsigned char *)cvs_buf_get(newbuf) + cvs_buf_len(newbuf)) - end); |
|
/* Point fin to end of data. */ |
|
fin = cvs_buf_get(tmpbuf) + cvs_buf_len(tmpbuf) - 1; |
|
/* Recalculate new length. */ |
|
len = cvs_buf_len(tmpbuf); |
|
|
/* only realloc if we have to */ |
/* tmpbuf is now ready, free old newbuf if allocated here. */ |
if (sizdiff > 0) { |
if (newbuf != bp) |
char *newdata; |
cvs_buf_free(newbuf); |
|
newbuf = tmpbuf; |
len += sizdiff; |
|
newdata = xrealloc(data, 1, len); |
|
data = newdata; |
|
|
|
/* |
|
* ensure string pointers are not invalidated |
|
* after realloc() |
|
*/ |
|
start = data + start_offset; |
|
c = data + c_offset; |
|
} |
|
if (strlcpy(start, expbuf, len) >= len || |
|
strlcat(data, tbuf, len) >= len) |
|
fatal("rcs_expand_keywords: string truncated"); |
|
xfree(tbuf); |
|
i += strlen(expbuf); |
|
} |
} |
} |
} |
|
|
return (data); |
return (newbuf); |
} |
} |
|
|
/* |
/* |
|
|
rcs_kwexp_buf(BUF *bp, RCSFILE *rf, RCSNUM *rev) |
rcs_kwexp_buf(BUF *bp, RCSFILE *rf, RCSNUM *rev) |
{ |
{ |
struct rcs_delta *rdp; |
struct rcs_delta *rdp; |
char *expanded, *tbuf; |
|
int expmode; |
int expmode; |
size_t len; |
|
|
|
/* |
/* |
* Do keyword expansion if required. |
* Do keyword expansion if required. |
|
|
if (!(expmode & RCS_KWEXP_NONE)) { |
if (!(expmode & RCS_KWEXP_NONE)) { |
if ((rdp = rcs_findrev(rf, rev)) == NULL) |
if ((rdp = rcs_findrev(rf, rev)) == NULL) |
fatal("could not fetch revision"); |
fatal("could not fetch revision"); |
cvs_buf_putc(bp, '\0'); |
return (rcs_expand_keywords(rf->rf_path, rdp, bp, expmode)); |
len = cvs_buf_len(bp); |
|
tbuf = cvs_buf_release(bp); |
|
expanded = rcs_expand_keywords(rf->rf_path, rdp, |
|
tbuf, len, expmode); |
|
bp = cvs_buf_alloc(len, BUF_AUTOEXT); |
|
cvs_buf_set(bp, expanded, strlen(expanded), 0); |
|
xfree(expanded); |
|
} |
} |
return (bp); |
return (bp); |
} |
} |