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 102typedef struct { 103 const char *id; 104 char type; 105 char flag; 106 int num; 107 const char *str; 108} TERMUSERDEF; 109 110typedef 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 135extern const char * _ti_database; 136 137ssize_t _ti_flagindex(const char *); 138ssize_t _ti_numindex(const char *); 139ssize_t _ti_strindex(const char *); 140const char * _ti_flagid(ssize_t); 141const char * _ti_numid(ssize_t); 142const char * _ti_strid(ssize_t); 143int _ti_getterm(TERMINAL *, const char *, int); 144void _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 154typedef struct { 155 char *buf; 156 size_t buflen; 157 size_t bufpos; 158 size_t entries; 159} TBUF; 160 161typedef 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 175int _ti_promote(TIC *); 176char *_ti_grow_tbuf(TBUF *, size_t); 177char *_ti_get_token(char **, char); 178const char *_ti_find_cap(TIC *, TBUF *, char, short); 179const char *_ti_find_extra(TIC *, TBUF *, const char *); 180char *_ti_getname(int, const char *); 181size_t _ti_store_extra(TIC *, int, const char *, char, char, int, 182 const char *, size_t, int); 183TIC *_ti_compile(char *, int); 184ssize_t _ti_flatten(uint8_t **, const TIC *); 185void _ti_freetic(TIC *); 186 187int _ti_encode_buf_id_num(TBUF *, int, int, size_t); 188int _ti_encode_buf_id_count_str(TBUF *, int, const void *, size_t); 189int _ti_encode_buf_id_flags(TBUF *, int, int); 190 191#define TPARM_MAX 9 /* not likely to change */ 192int _ti_parm_analyse(const char *, int *, int); 193 194static __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 203static __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 212static __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 222static __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 230static __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 238static __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 245static __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 254static __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 262static __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 270static __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 278static __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