diff options
Diffstat (limited to 'usr.bin/cvs/rcs.c')
-rw-r--r-- | usr.bin/cvs/rcs.c | 220 |
1 files changed, 37 insertions, 183 deletions
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index b9c6d59c078..b801a316539 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.93 2005/10/22 17:23:21 joris Exp $ */ +/* $OpenBSD: rcs.c,v 1.94 2005/10/22 17:32:57 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -38,6 +38,7 @@ #include <string.h> #include <unistd.h> +#include "cvs.h" #include "log.h" #include "rcs.h" #include "diff.h" @@ -98,24 +99,10 @@ struct rcs_pdata { }; -struct rcs_line { - char *rl_line; - int rl_lineno; - TAILQ_ENTRY(rcs_line) rl_list; -}; -TAILQ_HEAD(rcs_tqh, rcs_line); - -struct rcs_foo { - int rl_nblines; - char *rl_data; - struct rcs_tqh rl_lines; -}; - #define RCS_TOKSTR(rfp) ((struct rcs_pdata *)rfp->rf_pdata)->rp_buf #define RCS_TOKLEN(rfp) ((struct rcs_pdata *)rfp->rf_pdata)->rp_tlen - /* invalid characters in RCS symbol names */ static const char rcs_sym_invch[] = RCS_SYM_INVALCHAR; @@ -297,14 +284,11 @@ static void rcs_freepdata(struct rcs_pdata *); static int rcs_gettok(RCSFILE *); 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_strprint(const u_char *, size_t, FILE *); static int rcs_expand_keywords(char *, struct rcs_delta *, char *, char *, size_t, int); static struct rcs_delta *rcs_findrev(RCSFILE *, const RCSNUM *); -static struct rcs_foo *rcs_splitlines(const char *); -static void rcs_freefoo(struct rcs_foo *); /* * rcs_open() @@ -1168,76 +1152,22 @@ rcs_tag_resolve(RCSFILE *file, const char *tag) return (num); } - -/* - * rcs_patch() - * - * Apply an RCS-format patch pointed to by <patch> to the file contents - * found in <data>. - * Returns 0 on success, or -1 on failure. - */ -BUF* -rcs_patch(const char *data, const char *patch) -{ - struct rcs_foo *dlines, *plines; - struct rcs_line *lp; - size_t len; - int lineno; - BUF *res; - - len = strlen(data); - res = cvs_buf_alloc(len, BUF_AUTOEXT); - if (res == NULL) - return (NULL); - - dlines = rcs_splitlines(data); - if (dlines == NULL) { - cvs_buf_free(res); - return (NULL); - } - - plines = rcs_splitlines(patch); - if (plines == NULL) { - cvs_buf_free(res); - rcs_freefoo(dlines); - return (NULL); - } - - if (rcs_patch_lines(dlines, plines) < 0) { - cvs_buf_free(res); - rcs_freefoo(plines); - rcs_freefoo(dlines); - return (NULL); - } - - lineno = 0; - TAILQ_FOREACH(lp, &dlines->rl_lines, rl_list) { - if (lineno != 0) - cvs_buf_fappend(res, "%s\n", lp->rl_line); - lineno++; - } - - rcs_freefoo(dlines); - rcs_freefoo(plines); - return (res); -} - -static int -rcs_patch_lines(struct rcs_foo *dlines, struct rcs_foo *plines) +int +rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) { char op, *ep; - struct rcs_line *lp, *dlp, *ndlp; + struct cvs_line *lp, *dlp, *ndlp; int i, lineno, nbln; - dlp = TAILQ_FIRST(&(dlines->rl_lines)); - lp = TAILQ_FIRST(&(plines->rl_lines)); + dlp = TAILQ_FIRST(&(dlines->l_lines)); + lp = TAILQ_FIRST(&(plines->l_lines)); /* skip first bogus line */ - for (lp = TAILQ_NEXT(lp, rl_list); lp != NULL; - lp = TAILQ_NEXT(lp, rl_list)) { - op = *(lp->rl_line); - lineno = (int)strtol((lp->rl_line + 1), &ep, 10); - if ((lineno > dlines->rl_nblines) || (lineno < 0) || + for (lp = TAILQ_NEXT(lp, l_list); lp != NULL; + lp = TAILQ_NEXT(lp, l_list)) { + op = *(lp->l_line); + lineno = (int)strtol((lp->l_line + 1), &ep, 10); + if ((lineno > dlines->l_nblines) || (lineno < 0) || (*ep != ' ')) { cvs_log(LP_ERR, "invalid line specification in RCS patch"); @@ -1255,13 +1185,13 @@ rcs_patch_lines(struct rcs_foo *dlines, struct rcs_foo *plines) for (;;) { if (dlp == NULL) break; - if (dlp->rl_lineno == lineno) + if (dlp->l_lineno == lineno) break; - if (dlp->rl_lineno > lineno) { - dlp = TAILQ_PREV(dlp, rcs_tqh, rl_list); - } else if (dlp->rl_lineno < lineno) { - ndlp = TAILQ_NEXT(dlp, rl_list); - if (ndlp->rl_lineno > lineno) + if (dlp->l_lineno > lineno) { + dlp = TAILQ_PREV(dlp, cvs_tqh, l_list); + } else if (dlp->l_lineno < lineno) { + ndlp = TAILQ_NEXT(dlp, l_list); + if (ndlp->l_lineno > lineno) break; dlp = ndlp; } @@ -1274,25 +1204,25 @@ rcs_patch_lines(struct rcs_foo *dlines, struct rcs_foo *plines) if (op == 'd') { for (i = 0; (i < nbln) && (dlp != NULL); i++) { - ndlp = TAILQ_NEXT(dlp, rl_list); - TAILQ_REMOVE(&(dlines->rl_lines), dlp, rl_list); + ndlp = TAILQ_NEXT(dlp, l_list); + TAILQ_REMOVE(&(dlines->l_lines), dlp, l_list); dlp = ndlp; } } else if (op == 'a') { for (i = 0; i < nbln; i++) { ndlp = lp; - lp = TAILQ_NEXT(lp, rl_list); + lp = TAILQ_NEXT(lp, l_list); if (lp == NULL) { cvs_log(LP_ERR, "truncated RCS patch"); return (-1); } - TAILQ_REMOVE(&(plines->rl_lines), lp, rl_list); - TAILQ_INSERT_AFTER(&(dlines->rl_lines), dlp, - lp, rl_list); + TAILQ_REMOVE(&(plines->l_lines), lp, l_list); + TAILQ_INSERT_AFTER(&(dlines->l_lines), dlp, + lp, l_list); dlp = lp; /* we don't want lookup to block on those */ - lp->rl_lineno = lineno; + lp->l_lineno = lineno; lp = ndlp; } @@ -1302,15 +1232,15 @@ rcs_patch_lines(struct rcs_foo *dlines, struct rcs_foo *plines) } /* last line of the patch, done */ - if (lp->rl_lineno == plines->rl_nblines) + if (lp->l_lineno == plines->l_nblines) break; } /* once we're done patching, rebuild the line numbers */ lineno = 0; - TAILQ_FOREACH(lp, &(dlines->rl_lines), rl_list) - lp->rl_lineno = lineno++; - dlines->rl_nblines = lineno - 1; + TAILQ_FOREACH(lp, &(dlines->l_lines), l_list) + lp->l_lineno = lineno++; + dlines->l_nblines = lineno - 1; return (0); } @@ -1331,8 +1261,8 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) RCSNUM *crev, *rev; BUF *rbuf, *dbuf = NULL; struct rcs_delta *rdp = NULL; - struct rcs_foo *lines; - struct rcs_line *lp; + struct cvs_lines *lines; + struct cvs_line *lp; char out[1024]; /* XXX */ if (rfp->rf_head == NULL) @@ -1378,7 +1308,8 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) return (NULL); } bp = cvs_buf_release(rbuf); - rbuf = rcs_patch((char *)bp, (char *)rdp->rd_text); + rbuf = cvs_patchfile((char *)bp, (char *)rdp->rd_text, + rcs_patch_lines); free(bp); if (rbuf == NULL) break; @@ -1405,16 +1336,16 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) } bp = cvs_buf_release(rbuf); - if ((lines = rcs_splitlines((char *)bp)) != NULL) { + if ((lines = cvs_splitlines((char *)bp)) != NULL) { res = 0; - TAILQ_FOREACH(lp, &lines->rl_lines, rl_list) { + TAILQ_FOREACH(lp, &lines->l_lines, l_list) { if (res++ == 0) continue; rcs_expand_keywords(rfp->rf_path, rdp, - lp->rl_line, out, sizeof(out), expmode); + lp->l_line, out, sizeof(out), expmode); cvs_buf_fappend(dbuf, "%s\n", out); } - rcs_freefoo(lines); + cvs_freelines(lines); } free(bp); } @@ -2689,83 +2620,6 @@ rcs_pushtok(RCSFILE *rfp, const char *tok, int type) /* - * rcs_splitlines() - * - * Split the contents of a file into a list of lines. - */ -static struct rcs_foo* -rcs_splitlines(const char *fcont) -{ - char *dcp; - struct rcs_foo *foo; - struct rcs_line *lp; - - foo = (struct rcs_foo *)malloc(sizeof(*foo)); - if (foo == NULL) { - cvs_log(LP_ERR, "failed to allocate line structure"); - return (NULL); - } - TAILQ_INIT(&(foo->rl_lines)); - foo->rl_nblines = 0; - foo->rl_data = strdup(fcont); - if (foo->rl_data == NULL) { - cvs_log(LP_ERRNO, "failed to copy file contents"); - free(foo); - return (NULL); - } - - /* - * Add a first bogus line with line number 0. This is used so we - * can position the line pointer before 1 when changing the first line - * in rcs_patch(). - */ - lp = (struct rcs_line *)malloc(sizeof(*lp)); - if (lp == NULL) { - rcs_freefoo(foo); - return (NULL); - } - - lp->rl_line = NULL; - lp->rl_lineno = 0; - TAILQ_INSERT_TAIL(&(foo->rl_lines), lp, rl_list); - - - for (dcp = foo->rl_data; *dcp != '\0';) { - lp = (struct rcs_line *)malloc(sizeof(*lp)); - if (lp == NULL) { - rcs_freefoo(foo); - cvs_log(LP_ERR, "failed to allocate line entry"); - return (NULL); - } - - lp->rl_line = dcp; - lp->rl_lineno = ++(foo->rl_nblines); - TAILQ_INSERT_TAIL(&(foo->rl_lines), lp, rl_list); - - dcp = strchr(dcp, '\n'); - if (dcp == NULL) { - break; - } - *(dcp++) = '\0'; - } - - return (foo); -} - -static void -rcs_freefoo(struct rcs_foo *fp) -{ - struct rcs_line *lp; - - while ((lp = TAILQ_FIRST(&fp->rl_lines)) != NULL) { - TAILQ_REMOVE(&fp->rl_lines, lp, rl_list); - free(lp); - } - free(fp->rl_data); - free(fp); -} - -/* * rcs_growbuf() * * Attempt to grow the internal parse buffer for the RCS file <rf> by |