1 /* $NetBSD: term_private.h,v 1.19 2020/06/21 15:05:23 roy 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 #include <sys/types.h> 74 #include <assert.h> 75 #include <limits.h> 76 77 #define _TERMINFO 78 #define TERMINFO_RTYPE_O1 1 79 #define TERMINFO_ALIAS 2 80 #define TERMINFO_RTYPE 3 81 82 /* , and | are the two print characters now allowed 83 * in terminfo aliases or long descriptions. 84 * As | is generally used to delimit aliases inside the 85 * description, we use a comma. */ 86 #define TERMINFO_VDELIM ',' 87 #define TERMINFO_VDELIMSTR "," 88 89 /* We use the same ncurses tic macros so that our data is identical 90 * when a caller uses the long name macros to access te terminfo data 91 * directly. */ 92 #define ABSENT_BOOLEAN ((signed char)-1) /* 255 */ 93 #define ABSENT_NUMERIC (-1) 94 #define ABSENT_STRING (char *)0 95 #define CANCELLED_BOOLEAN ((signed char)-2) /* 254 */ 96 #define CANCELLED_NUMERIC (-2) 97 #define CANCELLED_STRING (char *)(-1) 98 #define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1) /* reject "-1" */ 99 #define VALID_NUMERIC(s) ((s) >= 0) 100 #define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING) 101 102 typedef struct { 103 const char *id; 104 char type; 105 char flag; 106 int num; 107 const char *str; 108 } TERMUSERDEF; 109 110 typedef struct { 111 int fildes; 112 /* We need to expose these so that the macros work */ 113 const char *name; 114 const char *desc; 115 signed char *flags; 116 int *nums; 117 const char **strs; 118 /* Storage area for terminfo data */ 119 char *_area; 120 size_t _arealen; 121 size_t _nuserdefs; 122 TERMUSERDEF *_userdefs; 123 /* So we don't rely on the global ospeed */ 124 short _ospeed; 125 /* Output buffer for tparm */ 126 char *_buf; 127 size_t _buflen; 128 size_t _bufpos; 129 /* A-Z static variables for tparm */ 130 long _snums[26]; 131 /* aliases of the terminal, | separated */ 132 const char *_alias; 133 } TERMINAL; 134 135 extern const char * _ti_database; 136 137 ssize_t _ti_flagindex(const char *); 138 ssize_t _ti_numindex(const char *); 139 ssize_t _ti_strindex(const char *); 140 const char * _ti_flagid(ssize_t); 141 const char * _ti_numid(ssize_t); 142 const char * _ti_strid(ssize_t); 143 int _ti_getterm(TERMINAL *, const char *, int); 144 void _ti_setospeed(TERMINAL *); 145 146 /* libterminfo can compile terminfo strings too */ 147 #define TIC_WARNING (1 << 0) 148 #define TIC_DESCRIPTION (1 << 1) 149 #define TIC_ALIAS (1 << 2) 150 #define TIC_COMMENT (1 << 3) 151 #define TIC_EXTRA (1 << 4) 152 #define TIC_COMPAT_V1 (1 << 5) 153 154 typedef struct { 155 char *buf; 156 size_t buflen; 157 size_t bufpos; 158 size_t entries; 159 } TBUF; 160 161 typedef struct { 162 char *name; 163 char *alias; 164 char *desc; 165 int rtype; 166 TBUF flags; 167 TBUF nums; 168 TBUF strs; 169 TBUF extras; 170 } TIC; 171 172 #define _ti_numsize(tic) \ 173 ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t)) 174 175 int _ti_promote(TIC *); 176 char *_ti_grow_tbuf(TBUF *, size_t); 177 char *_ti_get_token(char **, char); 178 const char *_ti_find_cap(TIC *, TBUF *, char, short); 179 const char *_ti_find_extra(TIC *, TBUF *, const char *); 180 char *_ti_getname(int, const char *); 181 size_t _ti_store_extra(TIC *, int, const char *, char, char, int, 182 const char *, size_t, int); 183 TIC *_ti_compile(char *, int); 184 ssize_t _ti_flatten(uint8_t **, const TIC *); 185 void _ti_freetic(TIC *); 186 187 int _ti_encode_buf_id_num(TBUF *, int, int, size_t); 188 int _ti_encode_buf_id_count_str(TBUF *, int, const void *, size_t); 189 int _ti_encode_buf_id_flags(TBUF *, int, int); 190 191 #define TPARM_MAX 9 /* not likely to change */ 192 int _ti_parm_analyse(const char *, int *, int); 193 194 static __inline int 195 _ti_decode_16(const char **cap) 196 { 197 int num = (int16_t)le16dec(*cap); 198 199 *cap += sizeof(uint16_t); 200 return num; 201 } 202 203 static __inline int 204 _ti_decode_32(const char **cap) 205 { 206 int num = (int32_t)le32dec(*cap); 207 208 *cap += sizeof(uint32_t); 209 return num; 210 } 211 212 static __inline int 213 _ti_decode_num(const char **cap, int rtype) 214 { 215 if (rtype == TERMINFO_RTYPE_O1) { 216 return _ti_decode_16(cap); 217 } else { 218 return _ti_decode_32(cap); 219 } 220 } 221 222 static __inline void 223 _ti_encode_16(char **cap, size_t num) 224 { 225 _DIAGASSERT(num <= UINT16_MAX); 226 le16enc(*cap, (uint16_t)num); 227 *cap += sizeof(uint16_t); 228 } 229 230 static __inline void 231 _ti_encode_32(char **cap, size_t num) 232 { 233 _DIAGASSERT(num <= UINT32_MAX); 234 le32enc(*cap, (uint32_t)num); 235 *cap += sizeof(uint32_t); 236 } 237 238 static __inline void 239 _ti_encode_str(char **cap, const void *buf, size_t len) 240 { 241 memcpy(*cap, buf, len); 242 *cap += len; 243 } 244 245 static __inline void 246 _ti_encode_count_str(char **cap, const char *name, size_t len) 247 { 248 _ti_encode_16(cap, (uint16_t)len); 249 if (name == NULL) 250 return; 251 _ti_encode_str(cap, name, len); 252 } 253 254 static __inline void 255 _ti_encode_buf_16(TBUF *tbuf, size_t num) 256 { 257 _DIAGASSERT(num <= UINT16_MAX); 258 le16enc(tbuf->buf + tbuf->bufpos, (uint16_t)num); 259 tbuf->bufpos += sizeof(uint16_t); 260 } 261 262 static __inline void 263 _ti_encode_buf_32(TBUF *tbuf, size_t num) 264 { 265 _DIAGASSERT(num <= UINT32_MAX); 266 le32enc(tbuf->buf + tbuf->bufpos, (uint32_t)num); 267 tbuf->bufpos += sizeof(uint32_t); 268 } 269 270 static __inline void 271 _ti_encode_buf_count_str(TBUF *tbuf, const void *buf, size_t len) 272 { 273 _ti_encode_buf_16(tbuf, len); 274 memcpy(tbuf->buf + tbuf->bufpos, buf, len); 275 tbuf->bufpos += len; 276 } 277 278 static __inline void 279 _ti_encode_buf_num(TBUF *tbuf, int num, int rtype) 280 { 281 if (rtype == TERMINFO_RTYPE_O1) { 282 if (num > INT16_MAX) 283 num = INT16_MAX; 284 _ti_encode_buf_16(tbuf, (uint16_t)num); 285 } else { 286 if (num > INT32_MAX) 287 num = INT32_MAX; 288 _ti_encode_buf_32(tbuf, (uint32_t)num); 289 } 290 } 291 292 #endif 293