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