Hi, The struct rcs_num in rcs(1) had a pointer for rn_id, but the version in cvs(1) had an array of size RCSNUM_MAX. This patch tries to make rcs(1) follow cvs(1) here, so rn_id doesn't need to be freed. As a result the rcsnum_free() function is replaced by one free().
After applying this patch I tried "ci", "co", "ci" (2nd rev), then "rlog" on a test file and it seemed to work fine. I didn't try rcsdiff or rcsmerge though. Does this break anything for you? - Michael Index: ci.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/ci.c,v retrieving revision 1.224 diff -u -p -u -r1.224 ci.c --- ci.c 4 Jul 2016 01:39:12 -0000 1.224 +++ ci.c 4 Sep 2017 08:21:45 -0000 @@ -314,7 +314,7 @@ checkin_main(int argc, char **argv) rcs_close(pb.file); if (rev_str != NULL) - rcsnum_free(pb.newrev); + free(pb.newrev); pb.newrev = NULL; } @@ -400,7 +400,7 @@ checkin_getlogmsg(RCSNUM *rev, RCSNUM *r rcsnum_tostr(rcsnum_inc(tmprev), nrev, sizeof(nrev)); else rcsnum_tostr(rev2, nrev, sizeof(nrev)); - rcsnum_free(tmprev); + free(tmprev); if (!(flags & QUIET)) (void)fprintf(stderr, "new revision: %s; " @@ -635,7 +635,7 @@ skipdesc: if (fetchlog == 1) { pb->rcs_msg = checkin_getlogmsg(pb->frev, pb->newrev, pb->flags); - rcsnum_free(pb->frev); + free(pb->frev); } /* Index: co.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/co.c,v retrieving revision 1.123 diff -u -p -u -r1.123 co.c --- co.c 29 Aug 2017 16:47:33 -0000 1.123 +++ co.c 4 Sep 2017 08:21:45 -0000 @@ -199,7 +199,7 @@ checkout_main(int argc, char **argv) if (checkout_rev(file, rev, argv[i], flags, username, author, state, date) < 0) { rcs_close(file); - rcsnum_free(rev); + free(rev); ret = 1; continue; } @@ -207,7 +207,7 @@ checkout_main(int argc, char **argv) if (!(flags & QUIET)) (void)fprintf(stderr, "done\n"); - rcsnum_free(rev); + free(rev); rcs_write(file); if (flags & PRESERVETIME) Index: rcs.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcs.c,v retrieving revision 1.85 diff -u -p -u -r1.85 rcs.c --- rcs.c 9 May 2016 13:03:55 -0000 1.85 +++ rcs.c 4 Sep 2017 08:21:46 -0000 @@ -165,7 +165,7 @@ rcs_close(RCSFILE *rfp) while (!TAILQ_EMPTY(&(rfp->rf_symbols))) { rsp = TAILQ_FIRST(&(rfp->rf_symbols)); TAILQ_REMOVE(&(rfp->rf_symbols), rsp, rs_list); - rcsnum_free(rsp->rs_num); + free(rsp->rs_num); free(rsp->rs_name); free(rsp); } @@ -173,13 +173,13 @@ rcs_close(RCSFILE *rfp) while (!TAILQ_EMPTY(&(rfp->rf_locks))) { rlp = TAILQ_FIRST(&(rfp->rf_locks)); TAILQ_REMOVE(&(rfp->rf_locks), rlp, rl_list); - rcsnum_free(rlp->rl_num); + free(rlp->rl_num); free(rlp->rl_name); free(rlp); } - rcsnum_free(rfp->rf_head); - rcsnum_free(rfp->rf_branch); + free(rfp->rf_head); + free(rfp->rf_branch); if (rfp->rf_file != NULL) fclose(rfp->rf_file); @@ -579,7 +579,7 @@ rcs_sym_remove(RCSFILE *file, const char TAILQ_REMOVE(&(file->rf_symbols), symp, rs_list); free(symp->rs_name); - rcsnum_free(symp->rs_num); + free(symp->rs_num); free(symp); /* not synced anymore */ @@ -738,7 +738,7 @@ rcs_lock_remove(RCSFILE *file, const cha } TAILQ_REMOVE(&(file->rf_locks), lkp, rl_list); - rcsnum_free(lkp->rl_num); + free(lkp->rl_num); free(lkp->rl_name); free(lkp); @@ -1228,10 +1228,10 @@ rcs_rev_remove(RCSFILE *rf, RCSNUM *rev) if (rcs_head_set(rf, prevrdp->rd_num) < 0) errx(1, "rcs_head_set failed"); } else if (nextrdp != NULL) { - rcsnum_free(nextrdp->rd_next); + free(nextrdp->rd_next); nextrdp->rd_next = rcsnum_alloc(); } else { - rcsnum_free(rf->rf_head); + free(rf->rf_head); rf->rf_head = NULL; } @@ -1292,7 +1292,7 @@ rcs_findrev(RCSFILE *rfp, RCSNUM *rev) frev = rdp->rd_next; } - rcsnum_free(brev); + free(brev); return (rdp); } @@ -1405,8 +1405,8 @@ rcs_freedelta(struct rcs_delta *rdp) { struct rcs_branch *rb; - rcsnum_free(rdp->rd_num); - rcsnum_free(rdp->rd_next); + free(rdp->rd_num); + free(rdp->rd_next); free(rdp->rd_author); free(rdp->rd_locker); @@ -1416,7 +1416,7 @@ rcs_freedelta(struct rcs_delta *rdp) while ((rb = TAILQ_FIRST(&(rdp->rd_branches))) != NULL) { TAILQ_REMOVE(&(rdp->rd_branches), rb, rb_list); - rcsnum_free(rb->rb_num); + free(rb->rb_num); free(rb); } Index: rcs.h =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcs.h,v retrieving revision 1.18 diff -u -p -u -r1.18 rcs.h --- rcs.h 29 Aug 2017 16:47:33 -0000 1.18 +++ rcs.h 4 Sep 2017 08:21:46 -0000 @@ -148,7 +148,7 @@ struct rcs_kw { typedef struct rcs_num { u_int rn_len; - u_int16_t *rn_id; + u_int16_t rn_id[RCSNUM_MAXLEN]; } RCSNUM; struct rcs_access { @@ -259,7 +259,6 @@ RCSNUM *rcsnum_parse(const char *); RCSNUM *rcsnum_brtorev(const RCSNUM *); RCSNUM *rcsnum_revtobr(const RCSNUM *); RCSNUM *rcsnum_inc(RCSNUM *); -void rcsnum_free(RCSNUM *); int rcsnum_addmagic(RCSNUM *); int rcsnum_aton(const char *, const char **, RCSNUM *); char *rcsnum_tostr(const RCSNUM *, char *, size_t); Index: rcsdiff.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcsdiff.c,v retrieving revision 1.84 diff -u -p -u -r1.84 rcsdiff.c --- rcsdiff.c 2 Nov 2015 16:45:21 -0000 1.84 +++ rcsdiff.c 4 Sep 2017 08:21:46 -0000 @@ -250,8 +250,8 @@ rcsdiff_main(int argc, char **argv) status = rcsdiff_rev(file, rev1, rev2, dflags); rcs_close(file); - rcsnum_free(rev1); - rcsnum_free(rev2); + free(rev1); + free(rev2); rev1 = rev2 = NULL; } Index: rcsmerge.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcsmerge.c,v retrieving revision 1.57 diff -u -p -u -r1.57 rcsmerge.c --- rcsmerge.c 26 Aug 2016 09:02:54 -0000 1.57 +++ rcsmerge.c 4 Sep 2017 08:21:46 -0000 @@ -174,8 +174,8 @@ rcsmerge_main(int argc, char **argv) out: rcs_close(file); - rcsnum_free(rev1); - rcsnum_free(rev2); + free(rev1); + free(rev2); return (status); } Index: rcsnum.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcsnum.c,v retrieving revision 1.20 diff -u -p -u -r1.20 rcsnum.c --- rcsnum.c 29 Aug 2017 16:47:33 -0000 1.20 +++ rcsnum.c 4 Sep 2017 08:21:46 -0000 @@ -51,9 +51,8 @@ rcsnum_alloc(void) { RCSNUM *rnp; - rnp = xmalloc(sizeof(*rnp)); + rnp = xcalloc(1, sizeof(*rnp)); rnp->rn_len = 0; - rnp->rn_id = NULL; return (rnp); } @@ -89,7 +88,7 @@ rcsnum_parse(const char *str) num = rcsnum_alloc(); if (rcsnum_aton(str, &ep, num) < 0 || *ep != '\0') { - rcsnum_free(num); + free(num); num = NULL; if (*ep != '\0') rcs_errno = RCS_ERR_BADNUM; @@ -99,20 +98,6 @@ rcsnum_parse(const char *str) } /* - * rcsnum_free() - * - * Free an RCSNUM structure previously allocated with rcsnum_alloc(). - */ -void -rcsnum_free(RCSNUM *rn) -{ - if (rn == NULL) - return; - free(rn->rn_id); - free(rn); -} - -/* * rcsnum_tostr() * * Format the RCS number <nump> into a human-readable dot-separated @@ -244,9 +229,6 @@ rcsnum_aton(const char *str, const char const char *sp; char *s; - if (nump->rn_id == NULL) - nump->rn_id = xmalloc(sizeof(*(nump->rn_id))); - nump->rn_len = 0; nump->rn_id[0] = 0; @@ -261,8 +243,6 @@ rcsnum_aton(const char *str, const char } nump->rn_len++; - nump->rn_id = xreallocarray(nump->rn_id, - nump->rn_len + 1, sizeof(*(nump->rn_id))); nump->rn_id[nump->rn_len] = 0; continue; } @@ -275,7 +255,7 @@ rcsnum_aton(const char *str, const char } if (ep != NULL) - *ep = sp; + *(const char **)ep = sp; /* * Handle "magic" RCS branch numbers. @@ -313,7 +293,7 @@ rcsnum_aton(const char *str, const char * so the .0. is removed. */ if (!strncmp(s, RCS_MAGIC_BRANCH, - strlen(RCS_MAGIC_BRANCH))) { + sizeof(RCS_MAGIC_BRANCH) - 1)) { nump->rn_id[nump->rn_len - 1] = nump->rn_id[nump->rn_len]; nump->rn_len--; @@ -324,8 +304,6 @@ rcsnum_aton(const char *str, const char /* We can't have a single-digit rcs number. */ if (nump->rn_len == 0) { nump->rn_len++; - nump->rn_id = xreallocarray(nump->rn_id, - nump->rn_len + 1, sizeof(*(nump->rn_id))); nump->rn_id[nump->rn_len] = 0; } @@ -334,8 +312,6 @@ rcsnum_aton(const char *str, const char rcsnum_aton_failed: nump->rn_len = 0; - free(nump->rn_id); - nump->rn_id = NULL; return (-1); } @@ -404,6 +380,5 @@ rcsnum_brtorev(const RCSNUM *brnum) static void rcsnum_setsize(RCSNUM *num, u_int len) { - num->rn_id = xreallocarray(num->rn_id, len, sizeof(*(num->rn_id))); num->rn_len = len; } Index: rcsparse.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcsparse.c,v retrieving revision 1.16 diff -u -p -u -r1.16 rcsparse.c --- rcsparse.c 26 Aug 2016 09:02:54 -0000 1.16 +++ rcsparse.c 4 Sep 2017 08:21:46 -0000 @@ -343,7 +343,7 @@ rcsparse_free(RCSFILE *rfp) free(pdp->rp_buf); if (pdp->rp_token == RCS_TYPE_REVISION) - rcsnum_free(pdp->rp_value.rev); + free(pdp->rp_value.rev); free(pdp); } @@ -557,12 +557,12 @@ rcsparse_textrevision(RCSFILE *rfp, stru if (rdp == NULL) { rcsparse_warnx(rfp, "delta for revision \"%s\" not found", pdp->rp_buf); - rcsnum_free(pdp->rp_value.rev); + free(pdp->rp_value.rev); return (1); } pdp->rp_delta = rdp; - rcsnum_free(pdp->rp_value.rev); + free(pdp->rp_value.rev); return (0); } @@ -1027,7 +1027,7 @@ rcsparse_token(RCSFILE *rfp, int allowed return (0); } if (datenum->rn_len != 6) { - rcsnum_free(datenum); + free(datenum); rcsparse_warnx(rfp, "invalid date \"%s\"", pdp->rp_buf); return (0); } @@ -1039,7 +1039,7 @@ rcsparse_token(RCSFILE *rfp, int allowed pdp->rp_value.date.tm_hour = datenum->rn_id[3]; pdp->rp_value.date.tm_min = datenum->rn_id[4]; pdp->rp_value.date.tm_sec = datenum->rn_id[5]; - rcsnum_free(datenum); + free(datenum); break; case RCS_TYPE_NUMBER: pdp->rp_value.rev = rcsnum_parse(pdp->rp_buf); @@ -1057,7 +1057,7 @@ rcsparse_token(RCSFILE *rfp, int allowed return (0); } if (!RCSNUM_ISBRANCH(pdp->rp_value.rev)) { - rcsnum_free(pdp->rp_value.rev); + free(pdp->rp_value.rev); rcsparse_warnx(rfp, "expected branch, got \"%s\"", pdp->rp_buf); return (0); @@ -1077,7 +1077,7 @@ rcsparse_token(RCSFILE *rfp, int allowed pdp->rp_value.rev = rcsnum_parse(pdp->rp_buf); if (pdp->rp_value.rev != NULL) { if (RCSNUM_ISBRANCH(pdp->rp_value.rev)) { - rcsnum_free(pdp->rp_value.rev); + free(pdp->rp_value.rev); rcsparse_warnx(rfp, "expected revision, got \"%s\"", pdp->rp_buf); Index: rcsprog.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rcsprog.c,v retrieving revision 1.161 diff -u -p -u -r1.161 rcsprog.c --- rcsprog.c 4 Jul 2016 01:39:12 -0000 1.161 +++ rcsprog.c 4 Sep 2017 08:21:46 -0000 @@ -365,11 +365,11 @@ rcs_main(int argc, char **argv) warnx("failed to set logmsg for `%s' to `%s'", logstr, logmsg); rcs_close(file); - rcsnum_free(logrev); + free(logrev); continue; } - rcsnum_free(logrev); + free(logrev); } /* entries to add from <oldfile> */ @@ -464,7 +464,7 @@ rcs_main(int argc, char **argv) if (rcs_lock_add(file, username, rev) != -1 && !(rcsflags & QUIET)) (void)fprintf(stderr, "%s locked\n", rev_str); - rcsnum_free(rev); + free(rev); } if (rcsflags & RCSPROG_UFLAG) { @@ -501,7 +501,7 @@ rcs_main(int argc, char **argv) (void)fprintf(stderr, "%s unlocked\n", rev_str); } - rcsnum_free(rev); + free(rev); } if (orange != NULL) { Index: rlog.c =================================================================== RCS file: /cvs/src/usr.bin/rcs/rlog.c,v retrieving revision 1.74 diff -u -p -u -r1.74 rlog.c --- rlog.c 16 Oct 2016 13:35:51 -0000 1.74 +++ rlog.c 4 Sep 2017 08:21:46 -0000 @@ -566,7 +566,7 @@ rlog_rev_print(struct rcs_delta *rdp) branch = rcsnum_revtobr(rb->rb_num); (void)rcsnum_tostr(branch, numb, sizeof(numb)); printf(" %s;", numb); - rcsnum_free(branch); + free(branch); } printf("\n"); }