1 /* $NetBSD: term_private.h,v 1.22 2025/09/23 20:31:20 js Exp $ */ 2 3 /* 4 * Copyright (c) 2009, 2010, 2013, 2020 The NetBSD Foundation, Inc. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Roy Marples. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #ifndef _TERM_PRIVATE_H_ 31 #define _TERM_PRIVATE_H_ 32 33 /* This header should only be used by libterminfo, tic and infocmp. */ 34 35 /* The terminfo database structure is private to us, 36 * so it's documented here. 37 * 38 * Version 1 - types 1 and 2. 39 * terminfo defines the largest number as 32767 and the largest 40 * compiled entry as 4093 bytes long. Negative numbers are not allowed. 41 * Thus, we store all numbers as uint16_t, including string length. 42 * We reserve negative numbers -1 and -2 to mean absent or cancelled. 43 * All strings are prefixed by length, including the null terminator. 44 * The largest string length we can handle is 65535 bytes, 45 * including the null terminator. 46 * The largest capability block we can handle is 65535 bytes. 47 * 48 * Version 2 - type 3 49 * Extends terminfo numbers upto 2147483647 by storing the value as a uint32_t. 50 * This means that we exceed the current terminfo defined limits in every way. 51 * 52 * Type 1 capabilities are defined as: 53 * header byte (always 1) 54 * name 55 * description, 56 * cap length, num flags, index, char, 57 * cap length, num numbers, index, number, 58 * cap length, num strings, index, string, 59 * cap length, num undefined caps, name, type (char), flag, number, string 60 * 61 * Type 2 entries are aliases and defined as: 62 * header byte (always 2) 63 * 32bit id of the corresponding terminal in the file 64 * name 65 * 66 * Type 3 extends Type 1 so that it can store terminfo numbers 67 * as uint32_t. All other numerics are still stored as uint16_t. 68 * 69 * The database itself is created using cdbw(3) and the numbers are 70 * always stored as little endian. 71 */ 72 73 #if HAVE_NBTOOL_CONFIG_H 74 # include "nbtool_config.h" 75 #endif 76 #if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H 77 # include <sys/endian.h> 78 #endif 79 #include <sys/types.h> 80 #include <assert.h> 81 #include <limits.h> 82 83 #define _TERMINFO 84 #define TERMINFO_RTYPE_O1 1 85 #define TERMINFO_ALIAS 2 86 #define TERMINFO_RTYPE 3 87 88 /* , and | are the two print characters now allowed 89 * in terminfo aliases or long descriptions. 90 * As | is generally used to delimit aliases inside the 91 * description, we use a comma. */ 92 #define TERMINFO_VDELIM ',' 93 #define TERMINFO_VDELIMSTR "," 94 95 /* We use the same ncurses tic macros so that our data is identical 96 * when a caller uses the long name macros to access te terminfo data 97 * directly. */ 98 #define ABSENT_BOOLEAN ((signed char)-1) /* 255 */ 99 #define ABSENT_NUMERIC (-1) 100 #define ABSENT_STRING (char *)0 101 #define CANCELLED_BOOLEAN ((signed char)-2) /* 254 */ 102 #define CANCELLED_NUMERIC (-2) 103 #define CANCELLED_STRING (char *)(-1) 104 #define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1) /* reject "-1" */ 105 #define VALID_NUMERIC(s) ((s) >= 0) 106 #define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING) 107 108 typedef struct { 109 const char *id; 110 char type; 111 char flag; 112 int num; 113 const char *str; 114 } TERMUSERDEF; 115 116 typedef struct { 117 int fildes; 118 /* We need to expose these so that the macros work */ 119 const char *name; 120 const char *desc; 121 signed char *flags; 122 int *nums; 123 const char **strs; 124 /* Storage area for terminfo data */ 125 char *_area; 126 size_t _arealen; 127 size_t _nuserdefs; 128 TERMUSERDEF *_userdefs; 129 /* So we don't rely on the global ospeed */ 130 short _ospeed; 131 /* Output buffer for tparm */ 132 char *_buf; 133 size_t _buflen; 134 size_t _bufpos; 135 /* A-Z static variables for tparm */ 136 long _snums[26]; 137 /* aliases of the terminal, | separated */ 138 const char *_alias; 139 } TERMINAL; 140 141 extern const char * _ti_database; 142 143 ssize_t _ti_flagindex(const char *); 144 ssize_t _ti_numindex(const char *); 145 ssize_t _ti_strindex(const char *); 146 const char * _ti_flagid(ssize_t); 147 const char * _ti_numid(ssize_t); 148 const char * _ti_strid(ssize_t); 149 int _ti_getterm(TERMINAL *, const char *, int); 150 void _ti_setospeed(TERMINAL *); 151 152 /* libterminfo can compile terminfo strings too */ 153 #define TIC_WARNING (1 << 0) 154 #define TIC_DESCRIPTION (1 << 1) 155 #define TIC_ALIAS (1 << 2) 156 #define TIC_COMMENT (1 << 3) 157 #define TIC_EXTRA (1 << 4) 158 #define TIC_COMPAT_V1 (1 << 5) 159 160 typedef struct { 161 char *buf; 162 size_t buflen; 163 size_t bufpos; 164 size_t entries; 165 } TBUF; 166 167 typedef struct { 168 char *name; 169 char *alias; 170 char *desc; 171 int rtype; 172 TBUF flags; 173 TBUF nums; 174 TBUF strs; 175 TBUF extras; 176 } TIC; 177 178 #define _ti_numsize(tic) \ 179 ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t)) 180 181 int _ti_promote(TIC *); 182 char *_ti_grow_tbuf(TBUF *, size_t); 183 char *_ti_get_token(char **, char); 184 const char *_ti_find_cap(TIC *, TBUF *, char, short); 185 const char *_ti_find_extra(TIC *, TBUF *, const char *); 186 char *_ti_getname(int, const char *); 187 size_t _ti_store_extra(TIC *, int, const char *, char, char, int, 188 const char *, size_t, int); 189 TIC *_ti_compile(char *, int); 190 ssize_t _ti_flatten(uint8_t **, const TIC *); 191 void _ti_freetic(TIC *); 192 193 int _ti_encode_buf_id_num(TBUF *, int, int, size_t); 194 int _ti_encode_buf_id_count_str(TBUF *, int, const void *, size_t); 195 int _ti_encode_buf_id_flags(TBUF *, int, int); 196 197 #define TPARM_MAX 9 /* not likely to change */ 198 int _ti_parm_analyse(const char *, int *, int); 199 200 static __inline int 201 _ti_decode_16(const char **cap) 202 { 203 int num = (int16_t)le16dec(*cap); 204 205 *cap += sizeof(uint16_t); 206 return num; 207 } 208 209 static __inline int 210 _ti_decode_32(const char **cap) 211 { 212 int num = (int32_t)le32dec(*cap); 213 214 *cap += sizeof(uint32_t); 215 return num; 216 } 217 218 static __inline int 219 _ti_decode_num(const char **cap, int rtype) 220 { 221 if (rtype == TERMINFO_RTYPE_O1) { 222 return _ti_decode_16(cap); 223 } else { 224 return _ti_decode_32(cap); 225 } 226 } 227 228 static __inline void 229 _ti_encode_16(char **cap, size_t num) 230 { 231 _DIAGASSERT(num <= UINT16_MAX); 232 le16enc(*cap, (uint16_t)num); 233 *cap += sizeof(uint16_t); 234 } 235 236 static __inline void 237 _ti_encode_32(char **cap, size_t num) 238 { 239 _DIAGASSERT(num <= UINT32_MAX); 240 le32enc(*cap, (uint32_t)num); 241 *cap += sizeof(uint32_t); 242 } 243 244 static __inline void 245 _ti_encode_str(char **cap, const void *buf, size_t len) 246 { 247 memcpy(*cap, buf, len); 248 *cap += len; 249 } 250 251 static __inline void 252 _ti_encode_count_str(char **cap, const char *name, size_t len) 253 { 254 _ti_encode_16(cap, (uint16_t)len); 255 if (name == NULL) 256 return; 257 _ti_encode_str(cap, name, len); 258 } 259 260 static __inline void 261 _ti_encode_buf_16(TBUF *tbuf, size_t num) 262 { 263 _DIAGASSERT(num <= UINT16_MAX); 264 le16enc(tbuf->buf + tbuf->bufpos, (uint16_t)num); 265 tbuf->bufpos += sizeof(uint16_t); 266 } 267 268 static __inline void 269 _ti_encode_buf_32(TBUF *tbuf, size_t num) 270 { 271 _DIAGASSERT(num <= UINT32_MAX); 272 le32enc(tbuf->buf + tbuf->bufpos, (uint32_t)num); 273 tbuf->bufpos += sizeof(uint32_t); 274 } 275 276 static __inline void 277 _ti_encode_buf_count_str(TBUF *tbuf, const void *buf, size_t len) 278 { 279 _ti_encode_buf_16(tbuf, len); 280 memcpy(tbuf->buf + tbuf->bufpos, buf, len); 281 tbuf->bufpos += len; 282 } 283 284 static __inline void 285 _ti_encode_buf_num(TBUF *tbuf, int num, int rtype) 286 { 287 if (rtype == TERMINFO_RTYPE_O1) { 288 if (num > INT16_MAX) 289 num = INT16_MAX; 290 _ti_encode_buf_16(tbuf, (uint16_t)num); 291 } else { 292 if (num > INT32_MAX) 293 num = INT32_MAX; 294 _ti_encode_buf_32(tbuf, (uint32_t)num); 295 } 296 } 297 298 #endif 299