Module Name:    src
Committed By:   roy
Date:           Sun Mar 29 21:54:03 UTC 2020

Modified Files:
        src/usr.bin/tic: tic.c

Log Message:
tic: Duplicate and promote v1 records when merging a v3 record

When this occurs, tic merges the matching v1 record into the original v1.

The screen-256color record by itself doesn't have any numerics bigger
than a short, but the xterm+256setaf record does.

The screen-256color record is now as it was before the recent terminfo2.cdb
merge into terminfo.cdb.


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/usr.bin/tic/tic.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/tic/tic.c
diff -u src/usr.bin/tic/tic.c:1.38 src/usr.bin/tic/tic.c:1.39
--- src/usr.bin/tic/tic.c:1.38	Sat Mar 28 15:37:04 2020
+++ src/usr.bin/tic/tic.c	Sun Mar 29 21:54:03 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: tic.c,v 1.38 2020/03/28 15:37:04 roy Exp $ */
+/* $NetBSD: tic.c,v 1.39 2020/03/29 21:54:03 roy Exp $ */
 
 /*
  * Copyright (c) 2009, 2010, 2020 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: tic.c,v 1.38 2020/03/28 15:37:04 roy Exp $");
+__RCSID("$NetBSD: tic.c,v 1.39 2020/03/29 21:54:03 roy Exp $");
 
 #include <sys/types.h>
 #include <sys/queue.h>
@@ -51,6 +51,7 @@ __RCSID("$NetBSD: tic.c,v 1.38 2020/03/2
 #include <fcntl.h>
 #include <search.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -141,6 +142,22 @@ find_term(const char *name)
 }
 
 static TERM *
+find_newest_term(const char *name)
+{
+	char *lname;
+	TERM *term;
+
+	lname = _ti_getname(TERMINFO_RTYPE, name);
+	if (lname == NULL)
+		return NULL;
+	term = find_term(lname);
+	free(lname);
+	if (term == NULL)
+		term = find_term(name);
+	return term;
+}
+
+static TERM *
 store_term(const char *name, TERM *base_term)
 {
 	TERM *term;
@@ -228,24 +245,9 @@ merge(TIC *rtic, TIC *utic, int flags)
 	int num;
 	size_t n;
 
-	/* Promote record type if needed. */
-	if (rtic->rtype < utic->rtype) {
-		char *obuf = rtic->nums.buf;
-
-		cap = rtic->nums.buf;
-		rtic->nums.buf = NULL;
-		rtic->nums.buflen = rtic->nums.bufpos = 0;
-		for (n = rtic->nums.entries; n > 0; n--) {
-			ind = _ti_decode_16(&cap);
-			num = _ti_decode_num(&cap, rtic->rtype);
-			if (VALID_NUMERIC(num) &&
-			    !_ti_encode_buf_id_num(&rtic->nums, ind, num,
-			    _ti_numsize(utic)))
-				err(EXIT_FAILURE, "encode num");
-		}
-		rtic->rtype = utic->rtype;
-		free(obuf);
-	}
+	if (rtic->rtype < utic->rtype)
+		errx(EXIT_FAILURE, "merge rtype diff (%s:%d into %s:%d)",
+		    utic->name, utic->rtype, rtic->name, rtic->rtype);
 
 	cap = utic->flags.buf;
 	for (n = utic->flags.entries; n > 0; n--) {
@@ -318,20 +320,95 @@ merge(TIC *rtic, TIC *utic, int flags)
 	}
 }
 
+static int
+dup_tbuf(TBUF *dst, const TBUF *src)
+{
+
+	if (src->buflen == 0)
+		return 0;
+	dst->buf = malloc(src->buflen);
+	if (dst->buf == NULL)
+		return -1;
+	dst->buflen = src->buflen;
+	memcpy(dst->buf, src->buf, dst->buflen);
+	dst->bufpos = src->bufpos;
+	dst->entries = src->entries;
+	return 0;
+}
+
+static int
+promote(TIC *rtic, TIC *utic)
+{
+	TERM *nrterm = find_newest_term(rtic->name);
+	TERM *nuterm = find_newest_term(utic->name);
+	TERM *term;
+	TIC *tic;
+
+	if (nrterm == NULL || nuterm == NULL)
+		return -1;
+	if (nrterm->tic->rtype >= nuterm->tic->rtype)
+		return 0;
+
+	tic = calloc(1, sizeof(*tic));
+	if (tic == NULL)
+		return -1;
+
+	tic->name = _ti_getname(TERMINFO_RTYPE, rtic->name);
+	if (tic->name == NULL)
+		goto err;
+	if (rtic->desc != NULL) {
+		tic->desc = strdup(rtic->desc);
+		if (tic->desc == NULL)
+			goto err;
+	}
+
+	tic->rtype = rtic->rtype;
+	if (dup_tbuf(&tic->flags, &rtic->flags) == -1)
+		goto err;
+	if (dup_tbuf(&tic->nums, &rtic->nums) == -1)
+		goto err;
+	if (dup_tbuf(&tic->strs, &rtic->strs) == -1)
+		goto err;
+	if (dup_tbuf(&tic->extras, &rtic->extras) == -1)
+		goto err;
+	if (_ti_promote(tic) == -1)
+		goto err;
+
+	term = store_term(tic->name, NULL);
+	if (term != NULL) {
+		term->tic = tic;
+		return 0;
+	}
+
+err:
+	free(tic->flags.buf);
+	free(tic->nums.buf);
+	free(tic->strs.buf);
+	free(tic->extras.buf);
+	free(tic->desc);
+	free(tic->name);
+	free(tic);
+	return -1;
+}
+
 static size_t
 merge_use(int flags)
 {
 	size_t skipped, merged, memn;
 	const char *cap;
+	char *name, *basename;
 	uint16_t num;
 	TIC *rtic, *utic;
-	TERM *term, *uterm;;
+	TERM *term, *uterm;
+	bool promoted;
 
 	skipped = merged = 0;
 	STAILQ_FOREACH(term, &terms, next) {
 		if (term->base_term != NULL)
 			continue;
 		rtic = term->tic;
+		basename = _ti_getname(TERMINFO_RTYPE_O1, rtic->name);
+		promoted = false;
 		while ((cap = _ti_find_extra(rtic, &rtic->extras, "use"))
 		    != NULL) {
 			if (*cap++ != 's') {
@@ -339,11 +416,19 @@ merge_use(int flags)
 				break;
 			}
 			cap += sizeof(uint16_t);
-			if (strcmp(rtic->name, cap) == 0) {
+			if (strcmp(basename, cap) == 0) {
 				dowarn("%s: uses itself", rtic->name);
 				goto remove;
 			}
-			uterm = find_term(cap);
+			name = _ti_getname(rtic->rtype, cap);
+			if (name == NULL) {
+				dowarn("%s: ???: %s", rtic->name, cap);
+				goto remove;
+			}
+			uterm = find_term(name);
+			free(name);
+			if (uterm == NULL)
+				uterm = find_term(cap);
 			if (uterm != NULL && uterm->base_term != NULL)
 				uterm = uterm->base_term;
 			if (uterm == NULL) {
@@ -361,7 +446,16 @@ merge_use(int flags)
 				skipped++;
 				break;
 			}
-			cap = _ti_find_extra(rtic, &rtic->extras, "use");
+
+			/* If we need to merge in a term that requires
+			 * this term to be promoted, we need to duplicate
+			 * this term, promote it and append it to our list. */
+			if (!promoted && rtic->rtype != TERMINFO_RTYPE) {
+				if (promote(rtic, utic) == -1)
+					err(EXIT_FAILURE, "promote");
+				promoted = true;
+			}
+
 			merge(rtic, utic, flags);
 	remove:
 			/* The pointers may have changed, find the use again */
@@ -384,6 +478,7 @@ merge_use(int flags)
 				merged++;
 			}
 		}
+		free(basename);
 	}
 
 	if (merged == 0 && skipped != 0)
@@ -410,7 +505,7 @@ print_dump(int argc, char **argv)
 
 	n = 0;
 	for (i = 0; i < argc; i++) {
-		term = find_term(argv[i]);
+		term = find_newest_term(argv[i]);
 		if (term == NULL) {
 			warnx("%s: no description for terminal", argv[i]);
 			continue;

Reply via email to