1 /**************************************************************************** 2 * Copyright 2018-2019,2020 Thomas E. Dickey * 3 * Copyright 1998-2013,2017 Free Software Foundation, Inc. * 4 * * 5 * Permission is hereby granted, free of charge, to any person obtaining a * 6 * copy of this software and associated documentation files (the * 7 * "Software"), to deal in the Software without restriction, including * 8 * without limitation the rights to use, copy, modify, merge, publish, * 9 * distribute, distribute with modifications, sublicense, and/or sell * 10 * copies of the Software, and to permit persons to whom the Software is * 11 * furnished to do so, subject to the following conditions: * 12 * * 13 * The above copyright notice and this permission notice shall be included * 14 * in all copies or substantial portions of the Software. * 15 * * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 23 * * 24 * Except as contained in this notice, the name(s) of the above copyright * 25 * holders shall not be used in advertising or otherwise to promote the * 26 * sale, use or other dealings in this Software without prior written * 27 * authorization. * 28 ****************************************************************************/ 29 30 /**************************************************************************** 31 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 32 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 33 * and: Thomas E. Dickey 1996-on * 34 ****************************************************************************/ 35 36 /* 37 * alloc_entry.c -- allocation functions for terminfo entries 38 * 39 * _nc_copy_entry() 40 * _nc_init_entry() 41 * _nc_merge_entry() 42 * _nc_save_str() 43 * _nc_wrap_entry() 44 * 45 */ 46 47 #include <curses.priv.h> 48 49 #include <tic.h> 50 51 MODULE_ID("$Id: alloc_entry.c,v 1.64 2020/02/02 23:34:34 tom Exp $") 52 53 #define ABSENT_OFFSET -1 54 #define CANCELLED_OFFSET -2 55 56 #define MAX_STRTAB 4096 /* documented maximum entry size */ 57 58 static char *stringbuf; /* buffer for string capabilities */ 59 static size_t next_free; /* next free character in stringbuf */ 60 61 NCURSES_EXPORT(void) 62 _nc_init_entry(ENTRY * const tp) 63 /* initialize a terminal type data block */ 64 { 65 #if NO_LEAKS 66 if (tp == 0) { 67 if (stringbuf != 0) { 68 FreeAndNull(stringbuf); 69 } 70 return; 71 } 72 #endif 73 74 if (stringbuf == 0) 75 TYPE_MALLOC(char, (size_t) MAX_STRTAB, stringbuf); 76 77 next_free = 0; 78 79 _nc_init_termtype(&(tp->tterm)); 80 } 81 82 NCURSES_EXPORT(ENTRY *) 83 _nc_copy_entry(ENTRY * oldp) 84 { 85 ENTRY *newp = typeCalloc(ENTRY, 1); 86 87 if (newp != 0) { 88 *newp = *oldp; 89 _nc_copy_termtype2(&(newp->tterm), &(oldp->tterm)); 90 } 91 return newp; 92 } 93 94 /* save a copy of string in the string buffer */ 95 NCURSES_EXPORT(char *) 96 _nc_save_str(const char *const string) 97 { 98 char *result = 0; 99 size_t old_next_free = next_free; 100 size_t len; 101 102 if (!VALID_STRING(string)) 103 return _nc_save_str(""); 104 len = strlen(string) + 1; 105 106 if (len == 1 && next_free != 0) { 107 /* 108 * Cheat a little by making an empty string point to the end of the 109 * previous string. 110 */ 111 if (next_free < MAX_STRTAB) { 112 result = (stringbuf + next_free - 1); 113 } 114 } else if (next_free + len < MAX_STRTAB) { 115 _nc_STRCPY(&stringbuf[next_free], string, MAX_STRTAB); 116 DEBUG(7, ("Saved string %s", _nc_visbuf(string))); 117 DEBUG(7, ("at location %d", (int) next_free)); 118 next_free += len; 119 result = (stringbuf + old_next_free); 120 } else { 121 _nc_warning("Too much data, some is lost: %s", string); 122 } 123 return result; 124 } 125 126 NCURSES_EXPORT(void) 127 _nc_wrap_entry(ENTRY * const ep, bool copy_strings) 128 /* copy the string parts to allocated storage, preserving pointers to it */ 129 { 130 int offsets[MAX_ENTRY_SIZE / sizeof(short)]; 131 int useoffsets[MAX_USES]; 132 unsigned i, n; 133 unsigned nuses = ep->nuses; 134 TERMTYPE2 *tp = &(ep->tterm); 135 136 if (copy_strings) { 137 next_free = 0; /* clear static storage */ 138 139 /* copy term_names, Strings, uses */ 140 tp->term_names = _nc_save_str(tp->term_names); 141 for_each_string(i, tp) { 142 if (tp->Strings[i] != ABSENT_STRING && 143 tp->Strings[i] != CANCELLED_STRING) { 144 tp->Strings[i] = _nc_save_str(tp->Strings[i]); 145 } 146 } 147 148 for (i = 0; i < nuses; i++) { 149 if (ep->uses[i].name == 0) { 150 ep->uses[i].name = _nc_save_str(ep->uses[i].name); 151 } 152 } 153 154 free(tp->str_table); 155 } 156 157 assert(tp->term_names >= stringbuf); 158 n = (unsigned) (tp->term_names - stringbuf); 159 for_each_string(i, &(ep->tterm)) { 160 if (i < SIZEOF(offsets)) { 161 if (tp->Strings[i] == ABSENT_STRING) { 162 offsets[i] = ABSENT_OFFSET; 163 } else if (tp->Strings[i] == CANCELLED_STRING) { 164 offsets[i] = CANCELLED_OFFSET; 165 } else { 166 offsets[i] = (int) (tp->Strings[i] - stringbuf); 167 } 168 } 169 } 170 171 for (i = 0; i < nuses; i++) { 172 if (ep->uses[i].name == 0) 173 useoffsets[i] = ABSENT_OFFSET; 174 else 175 useoffsets[i] = (int) (ep->uses[i].name - stringbuf); 176 } 177 178 TYPE_MALLOC(char, next_free, tp->str_table); 179 (void) memcpy(tp->str_table, stringbuf, next_free); 180 181 tp->term_names = tp->str_table + n; 182 for_each_string(i, &(ep->tterm)) { 183 if (i < SIZEOF(offsets)) { 184 if (offsets[i] == ABSENT_OFFSET) { 185 tp->Strings[i] = ABSENT_STRING; 186 } else if (offsets[i] == CANCELLED_OFFSET) { 187 tp->Strings[i] = CANCELLED_STRING; 188 } else { 189 tp->Strings[i] = tp->str_table + offsets[i]; 190 } 191 } 192 } 193 194 #if NCURSES_XNAMES 195 if (!copy_strings) { 196 if ((n = (unsigned) NUM_EXT_NAMES(tp)) != 0) { 197 if (n < SIZEOF(offsets)) { 198 size_t length = 0; 199 size_t offset; 200 for (i = 0; i < n; i++) { 201 length += strlen(tp->ext_Names[i]) + 1; 202 offsets[i] = (int) (tp->ext_Names[i] - stringbuf); 203 } 204 TYPE_MALLOC(char, length, tp->ext_str_table); 205 for (i = 0, offset = 0; i < n; i++) { 206 tp->ext_Names[i] = tp->ext_str_table + offset; 207 _nc_STRCPY(tp->ext_Names[i], 208 stringbuf + offsets[i], 209 length - offset); 210 offset += strlen(tp->ext_Names[i]) + 1; 211 } 212 } 213 } 214 } 215 #endif 216 217 for (i = 0; i < nuses; i++) { 218 if (useoffsets[i] == ABSENT_OFFSET) 219 ep->uses[i].name = 0; 220 else 221 ep->uses[i].name = (tp->str_table + useoffsets[i]); 222 } 223 } 224 225 NCURSES_EXPORT(void) 226 _nc_merge_entry(ENTRY * const target, ENTRY * const source) 227 /* merge capabilities from `from' entry into `to' entry */ 228 { 229 TERMTYPE2 *to = &(target->tterm); 230 TERMTYPE2 *from = &(source->tterm); 231 #if NCURSES_XNAMES 232 TERMTYPE2 copy; 233 #endif 234 unsigned i; 235 236 if (source == 0 || from == 0 || target == 0 || to == 0) 237 return; 238 239 #if NCURSES_XNAMES 240 _nc_copy_termtype2(©, from); 241 from = © 242 _nc_align_termtype(to, from); 243 #endif 244 for_each_boolean(i, from) { 245 if (to->Booleans[i] != (char) CANCELLED_BOOLEAN) { 246 int mergebool = from->Booleans[i]; 247 248 if (mergebool == CANCELLED_BOOLEAN) 249 to->Booleans[i] = FALSE; 250 else if (mergebool == TRUE) 251 to->Booleans[i] = (NCURSES_SBOOL) mergebool; 252 } 253 } 254 255 for_each_number(i, from) { 256 if (to->Numbers[i] != CANCELLED_NUMERIC) { 257 int mergenum = from->Numbers[i]; 258 259 if (mergenum == CANCELLED_NUMERIC) 260 to->Numbers[i] = ABSENT_NUMERIC; 261 else if (mergenum != ABSENT_NUMERIC) 262 to->Numbers[i] = (NCURSES_INT2) mergenum; 263 } 264 } 265 266 /* 267 * Note: the copies of strings this makes don't have their own 268 * storage. This is OK right now, but will be a problem if we 269 * we ever want to deallocate entries. 270 */ 271 for_each_string(i, from) { 272 if (to->Strings[i] != CANCELLED_STRING) { 273 char *mergestring = from->Strings[i]; 274 275 if (mergestring == CANCELLED_STRING) 276 to->Strings[i] = ABSENT_STRING; 277 else if (mergestring != ABSENT_STRING) 278 to->Strings[i] = mergestring; 279 } 280 } 281 #if NCURSES_XNAMES 282 /* Discard the data allocated in _nc_copy_termtype2, but do not use 283 * _nc_free_termtype2 because that frees the string-table (which is 284 * not allocated by _nc_copy_termtype2). 285 */ 286 free(copy.Booleans); 287 free(copy.Numbers); 288 free(copy.Strings); 289 free(copy.ext_Names); 290 #endif 291 } 292 293 #if NO_LEAKS 294 NCURSES_EXPORT(void) 295 _nc_alloc_entry_leaks(void) 296 { 297 if (stringbuf != 0) { 298 FreeAndNull(stringbuf); 299 } 300 next_free = 0; 301 } 302 #endif 303