In article <20200324144303.e147610...@quasar.astron.com>, Christos Zoulas <chris...@quasar.astron.com> wrote: >Hello, > >The recent terminfo ABI change to widen numeric constants from 16 bits to >32 bits was done in the following way: > >1. Create a new terminfo2 database and rely on the fact that old > programs will use the old filename and new ones will use the new > filename. >2. Add compatibility code so that the new library can read the old > terminfo database. > >This approach has issues. Aside from the visible effect to have a >new file, it causes us to have to carry an old terminfo file around >to keep old binaries working because we don't have a way to build >the old terminfo file anymore. > >With a little more effort all this can be avoided: > >We can modify the writing code to only write entries in the new >format for the terminal descriptions that require it. We can store >those descriptions under a different name <name>@v2 for example, >while storing a "compatible" description with the original name >with the values that don't fit in 16 bits clamped. The code can >try to find <name>@v2 first and if that fails, attempt to find the >original name. This way we can store all the data in the same file >(no need to create terminfo2 anymore), and have both old programs >keep working, and new programs be able to use the wide fields. >
Below is a patch that does most of the work described above. It creates type 1 and type 3 records in the same file as needed. Old code will not be able to read the type 3 records, which is just a handful of them... I suggest that we apply that now, and keep using /usr/share/misc/terminfo.cdb as before. Index: compile.c =================================================================== RCS file: /cvsroot/src/lib/libterminfo/compile.c,v retrieving revision 1.14 diff -u -u -r1.14 compile.c --- compile.c 13 Mar 2020 15:19:25 -0000 1.14 +++ compile.c 26 Mar 2020 23:48:02 -0000 @@ -51,6 +51,9 @@ #include <term_private.h> #include <term.h> +#define _ti_numsize(tic) \ + ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t)) + static void __printflike(2, 3) dowarn(int flags, const char *fmt, ...) { @@ -87,7 +90,7 @@ } char * -_ti_find_cap(TBUF *tbuf, char type, short ind) +_ti_find_cap(TIC *tic, TBUF *tbuf, char type, short ind) { size_t n; uint16_t num; @@ -106,7 +109,7 @@ cap++; break; case 'n': - cap += sizeof(uint32_t); + cap += _ti_numsize(tic); break; case 's': num = le16dec(cap); @@ -121,7 +124,7 @@ } char * -_ti_find_extra(TBUF *tbuf, const char *code) +_ti_find_extra(TIC *tic, TBUF *tbuf, const char *code) { size_t n; uint16_t num; @@ -142,7 +145,7 @@ cap++; break; case 'n': - cap += sizeof(uint32_t); + cap += _ti_numsize(tic); break; case 's': num = le16dec(cap); @@ -156,6 +159,16 @@ return NULL; } +static void +_ti_encode_num(TIC *tic, TBUF *rbuf, int num) { + if (_ti_numsize(tic) == sizeof(uint16_t)) { + le16enc(rbuf->buf + rbuf->bufpos, (uint16_t)num); + } else { + le32enc(rbuf->buf + rbuf->bufpos, (uint32_t)num); + } + rbuf->bufpos += _ti_numsize(tic); +} + size_t _ti_store_extra(TIC *tic, int wrn, char *id, char type, char flag, int num, char *str, size_t strl, int flags) @@ -165,7 +178,7 @@ _DIAGASSERT(tic != NULL); if (strcmp(id, "use") != 0) { - if (_ti_find_extra(&tic->extras, id) != NULL) + if (_ti_find_extra(tic, &tic->extras, id) != NULL) return 0; if (!(flags & TIC_EXTRA)) { if (wrn != 0) @@ -182,7 +195,7 @@ } if (!_ti_grow_tbuf(&tic->extras, - l + strl + sizeof(uint16_t) + sizeof(uint32_t) + 1)) + l + strl + sizeof(uint16_t) + _ti_numsize(tic) + 1)) return 0; le16enc(tic->extras.buf + tic->extras.bufpos, (uint16_t)l); tic->extras.bufpos += sizeof(uint16_t); @@ -194,8 +207,7 @@ tic->extras.buf[tic->extras.bufpos++] = flag; break; case 'n': - le32enc(tic->extras.buf + tic->extras.bufpos, (uint32_t)num); - tic->extras.bufpos += sizeof(uint32_t); + _ti_encode_num(tic, &tic->extras, num); break; case 's': le16enc(tic->extras.buf + tic->extras.bufpos, (uint16_t)strl); @@ -239,7 +251,7 @@ return -1; cap = *buf; - *cap++ = TERMINFO_RTYPE; /* Record type 3 */ + *cap++ = tic->rtype; le16enc(cap, (uint16_t)len); cap += sizeof(uint16_t); memcpy(cap, tic->name, len); @@ -451,6 +463,17 @@ return token; } +static int +_ti_find_rtype(const char *cap) +{ + for (const char *ptr = cap; (ptr = strchr(ptr, '#')) != NULL;) { + if (strtol(++ptr, NULL, 0) > 0xffff) { + return TERMINFO_RTYPE; + } + } + return TERMINFO_RTYPE_O1; +} + TIC * _ti_compile(char *cap, int flags) { @@ -467,7 +490,7 @@ name = _ti_get_token(&cap, ','); if (name == NULL) { - dowarn(flags, "no seperator found: %s", cap); + dowarn(flags, "no separator found: %s", cap); return NULL; } desc = strrchr(name, '|'); @@ -494,6 +517,7 @@ if (tic == NULL) return NULL; + tic->rtype = _ti_find_rtype(cap); buf.buf = NULL; buf.buflen = 0; @@ -533,7 +557,7 @@ /* Don't use the string if we already have it */ ind = (short)_ti_strindex(token); if (ind != -1 && - _ti_find_cap(&tic->strs, 's', ind) != NULL) + _ti_find_cap(tic, &tic->strs, 's', ind) != NULL) continue; /* Encode the string to our scratch buffer */ @@ -579,7 +603,7 @@ /* Don't use the number if we already have it */ ind = (short)_ti_numindex(token); if (ind != -1 && - _ti_find_cap(&tic->nums, 'n', ind) != NULL) + _ti_find_cap(tic, &tic->nums, 'n', ind) != NULL) continue; cnum = strtol(p, &e, 0); @@ -600,14 +624,12 @@ num, NULL, 0, flags); else { if (_ti_grow_tbuf(&tic->nums, - sizeof(uint16_t) + sizeof(uint32_t))==NULL) + sizeof(uint16_t) + _ti_numsize(tic))==NULL) goto error; le16enc(tic->nums.buf + tic->nums.bufpos, (uint16_t)ind); tic->nums.bufpos += sizeof(uint16_t); - le32enc(tic->nums.buf + tic->nums.bufpos, - (uint32_t)num); - tic->nums.bufpos += sizeof(uint32_t); + _ti_encode_num(tic, &tic->nums, num); tic->nums.entries++; } continue; @@ -622,7 +644,8 @@ ind = (short)_ti_flagindex(token); if (ind == -1 && flag == CANCELLED_BOOLEAN) { if ((ind = (short)_ti_numindex(token)) != -1) { - if (_ti_find_cap(&tic->nums, 'n', ind) != NULL) + if (_ti_find_cap(tic, &tic->nums, 'n', ind) + != NULL) continue; if (_ti_grow_tbuf(&tic->nums, sizeof(uint16_t) * 2) == NULL) @@ -630,13 +653,13 @@ le16enc(tic->nums.buf + tic->nums.bufpos, (uint16_t)ind); tic->nums.bufpos += sizeof(uint16_t); - le32enc(tic->nums.buf + tic->nums.bufpos, - (uint32_t)CANCELLED_NUMERIC); - tic->nums.bufpos += sizeof(uint32_t); + _ti_encode_num(tic, &tic->nums, + CANCELLED_NUMERIC); tic->nums.entries++; continue; } else if ((ind = (short)_ti_strindex(token)) != -1) { - if (_ti_find_cap(&tic->strs, 's', ind) != NULL) + if (_ti_find_cap(tic, &tic->strs, 's', ind) + != NULL) continue; if (_ti_grow_tbuf(&tic->strs, (sizeof(uint16_t) * 2) + 1) == NULL) @@ -652,7 +675,7 @@ if (ind == -1) _ti_store_extra(tic, 1, token, 'f', flag, 0, NULL, 0, flags); - else if (_ti_find_cap(&tic->flags, 'f', ind) == NULL) { + else if (_ti_find_cap(tic, &tic->flags, 'f', ind) == NULL) { if (_ti_grow_tbuf(&tic->flags, sizeof(uint16_t) + 1) == NULL) goto error; Index: term.c =================================================================== RCS file: /cvsroot/src/lib/libterminfo/term.c,v retrieving revision 1.30 diff -u -u -r1.30 term.c --- term.c 13 Mar 2020 15:19:25 -0000 1.30 +++ term.c 26 Mar 2020 23:48:02 -0000 @@ -74,6 +74,21 @@ } static int +_ti_decode_num(int rtype, const char **cap) +{ + int rv; + + if (rtype == TERMINFO_RTYPE_O1) { + rv = (int)le16dec(*cap); + *cap += sizeof(uint16_t); + } else { + rv = (int)le32dec(*cap); + *cap += sizeof(uint32_t); + } + return rv; +} + +static int _ti_readterm(TERMINAL *term, const char *cap, size_t caplen, int flags) { char rtype; @@ -150,13 +165,7 @@ for (; num != 0; num--) { ind = le16dec(cap); cap += sizeof(uint16_t); - if (rtype == TERMINFO_RTYPE_O1) { - term->nums[ind] = (int)le16dec(cap); - cap += sizeof(uint16_t); - } else { - term->nums[ind] = (int)le32dec(cap); - cap += sizeof(uint32_t); - } + term->nums[ind] = _ti_decode_num(rtype, &cap); if (flags == 0 && !VALID_NUMERIC(term->nums[ind])) term->nums[ind] = ABSENT_NUMERIC; } @@ -213,13 +222,7 @@ break; case 'n': ud->flag = ABSENT_BOOLEAN; - if (rtype == TERMINFO_RTYPE_O1) { - ud->num = (int)le16dec(cap); - cap += sizeof(uint16_t); - } else { - ud->num = (int)le32dec(cap); - cap += sizeof(uint32_t); - } + ud->num = _ti_decode_num(rtype, &cap); if (flags == 0 && !VALID_NUMERIC(ud->num)) ud->num = ABSENT_NUMERIC; Index: term_private.h =================================================================== RCS file: /cvsroot/src/lib/libterminfo/term_private.h,v retrieving revision 1.12 diff -u -u -r1.12 term_private.h --- term_private.h 13 Mar 2020 15:19:25 -0000 1.12 +++ term_private.h 26 Mar 2020 23:48:02 -0000 @@ -154,6 +154,7 @@ char *name; char *alias; char *desc; + int rtype; TBUF flags; TBUF nums; TBUF strs; @@ -162,8 +163,8 @@ char *_ti_grow_tbuf(TBUF *, size_t); char *_ti_get_token(char **, char); -char *_ti_find_cap(TBUF *, char, short); -char *_ti_find_extra(TBUF *, const char *); +char *_ti_find_cap(TIC *, TBUF *, char, short); +char *_ti_find_extra(TIC *, TBUF *, const char *); size_t _ti_store_extra(TIC *, int, char *, char, char, int, char *, size_t, int); TIC *_ti_compile(char *, int);