1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2018-2019,2020 Thomas E. Dickey                                *
3*32bb5217SDaniel Fojt  * Copyright 1998-2013,2017 Free Software Foundation, Inc.                  *
4fdd4e1e0SJan Lentfer  *                                                                          *
5fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
6fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
7fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
8fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
9fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
10fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
11fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
12fdd4e1e0SJan Lentfer  *                                                                          *
13fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
14fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
15fdd4e1e0SJan Lentfer  *                                                                          *
16fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23fdd4e1e0SJan Lentfer  *                                                                          *
24fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
25fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
26fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
27fdd4e1e0SJan Lentfer  * authorization.                                                           *
28fdd4e1e0SJan Lentfer  ****************************************************************************/
29fdd4e1e0SJan Lentfer 
30fdd4e1e0SJan Lentfer /****************************************************************************
31fdd4e1e0SJan Lentfer  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32fdd4e1e0SJan Lentfer  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
331d102085SJan Lentfer  *     and: Thomas E. Dickey                        1996-on                 *
34fdd4e1e0SJan Lentfer  ****************************************************************************/
35fdd4e1e0SJan Lentfer 
36fdd4e1e0SJan Lentfer /*
37fdd4e1e0SJan Lentfer  * alloc_entry.c -- allocation functions for terminfo entries
38fdd4e1e0SJan Lentfer  *
39fdd4e1e0SJan Lentfer  *	_nc_copy_entry()
40fdd4e1e0SJan Lentfer  *	_nc_init_entry()
41fdd4e1e0SJan Lentfer  *	_nc_merge_entry()
42fdd4e1e0SJan Lentfer  *	_nc_save_str()
43fdd4e1e0SJan Lentfer  *	_nc_wrap_entry()
44fdd4e1e0SJan Lentfer  *
45fdd4e1e0SJan Lentfer  */
46fdd4e1e0SJan Lentfer 
47fdd4e1e0SJan Lentfer #include <curses.priv.h>
48fdd4e1e0SJan Lentfer 
49fdd4e1e0SJan Lentfer #include <tic.h>
50fdd4e1e0SJan Lentfer 
51*32bb5217SDaniel Fojt MODULE_ID("$Id: alloc_entry.c,v 1.64 2020/02/02 23:34:34 tom Exp $")
52fdd4e1e0SJan Lentfer 
53fdd4e1e0SJan Lentfer #define ABSENT_OFFSET    -1
54fdd4e1e0SJan Lentfer #define CANCELLED_OFFSET -2
55fdd4e1e0SJan Lentfer 
56fdd4e1e0SJan Lentfer #define MAX_STRTAB	4096	/* documented maximum entry size */
57fdd4e1e0SJan Lentfer 
58fdd4e1e0SJan Lentfer static char *stringbuf;		/* buffer for string capabilities */
59fdd4e1e0SJan Lentfer static size_t next_free;	/* next free character in stringbuf */
60fdd4e1e0SJan Lentfer 
61fdd4e1e0SJan Lentfer NCURSES_EXPORT(void)
_nc_init_entry(ENTRY * const tp)62*32bb5217SDaniel Fojt _nc_init_entry(ENTRY * const tp)
63fdd4e1e0SJan Lentfer /* initialize a terminal type data block */
64fdd4e1e0SJan Lentfer {
651d102085SJan Lentfer #if NO_LEAKS
6600d8f3c4SJohn Marino     if (tp == 0) {
6700d8f3c4SJohn Marino 	if (stringbuf != 0) {
681d102085SJan Lentfer 	    FreeAndNull(stringbuf);
6900d8f3c4SJohn Marino 	}
701d102085SJan Lentfer 	return;
711d102085SJan Lentfer     }
721d102085SJan Lentfer #endif
731d102085SJan Lentfer 
74fdd4e1e0SJan Lentfer     if (stringbuf == 0)
753468e90cSJohn Marino 	TYPE_MALLOC(char, (size_t) MAX_STRTAB, stringbuf);
76fdd4e1e0SJan Lentfer 
77fdd4e1e0SJan Lentfer     next_free = 0;
783468e90cSJohn Marino 
79*32bb5217SDaniel Fojt     _nc_init_termtype(&(tp->tterm));
80fdd4e1e0SJan Lentfer }
81fdd4e1e0SJan Lentfer 
82fdd4e1e0SJan Lentfer NCURSES_EXPORT(ENTRY *)
_nc_copy_entry(ENTRY * oldp)83fdd4e1e0SJan Lentfer _nc_copy_entry(ENTRY * oldp)
84fdd4e1e0SJan Lentfer {
85fdd4e1e0SJan Lentfer     ENTRY *newp = typeCalloc(ENTRY, 1);
86fdd4e1e0SJan Lentfer 
87fdd4e1e0SJan Lentfer     if (newp != 0) {
88fdd4e1e0SJan Lentfer 	*newp = *oldp;
89*32bb5217SDaniel Fojt 	_nc_copy_termtype2(&(newp->tterm), &(oldp->tterm));
90fdd4e1e0SJan Lentfer     }
91fdd4e1e0SJan Lentfer     return newp;
92fdd4e1e0SJan Lentfer }
93fdd4e1e0SJan Lentfer 
941d102085SJan Lentfer /* save a copy of string in the string buffer */
95fdd4e1e0SJan Lentfer NCURSES_EXPORT(char *)
_nc_save_str(const char * const string)96fdd4e1e0SJan Lentfer _nc_save_str(const char *const string)
97fdd4e1e0SJan Lentfer {
981d102085SJan Lentfer     char *result = 0;
99fdd4e1e0SJan Lentfer     size_t old_next_free = next_free;
100*32bb5217SDaniel Fojt     size_t len;
101*32bb5217SDaniel Fojt 
102*32bb5217SDaniel Fojt     if (!VALID_STRING(string))
103*32bb5217SDaniel Fojt 	return _nc_save_str("");
104*32bb5217SDaniel Fojt     len = strlen(string) + 1;
105fdd4e1e0SJan Lentfer 
1061d102085SJan Lentfer     if (len == 1 && next_free != 0) {
1071d102085SJan Lentfer 	/*
1081d102085SJan Lentfer 	 * Cheat a little by making an empty string point to the end of the
1091d102085SJan Lentfer 	 * previous string.
1101d102085SJan Lentfer 	 */
1111d102085SJan Lentfer 	if (next_free < MAX_STRTAB) {
1121d102085SJan Lentfer 	    result = (stringbuf + next_free - 1);
1131d102085SJan Lentfer 	}
1141d102085SJan Lentfer     } else if (next_free + len < MAX_STRTAB) {
1153468e90cSJohn Marino 	_nc_STRCPY(&stringbuf[next_free], string, MAX_STRTAB);
116fdd4e1e0SJan Lentfer 	DEBUG(7, ("Saved string %s", _nc_visbuf(string)));
117fdd4e1e0SJan Lentfer 	DEBUG(7, ("at location %d", (int) next_free));
118fdd4e1e0SJan Lentfer 	next_free += len;
1191d102085SJan Lentfer 	result = (stringbuf + old_next_free);
1201d102085SJan Lentfer     } else {
1213468e90cSJohn Marino 	_nc_warning("Too much data, some is lost: %s", string);
122fdd4e1e0SJan Lentfer     }
1231d102085SJan Lentfer     return result;
124fdd4e1e0SJan Lentfer }
125fdd4e1e0SJan Lentfer 
126fdd4e1e0SJan Lentfer NCURSES_EXPORT(void)
_nc_wrap_entry(ENTRY * const ep,bool copy_strings)127fdd4e1e0SJan Lentfer _nc_wrap_entry(ENTRY * const ep, bool copy_strings)
128fdd4e1e0SJan Lentfer /* copy the string parts to allocated storage, preserving pointers to it */
129fdd4e1e0SJan Lentfer {
1301d102085SJan Lentfer     int offsets[MAX_ENTRY_SIZE / sizeof(short)];
1311d102085SJan Lentfer     int useoffsets[MAX_USES];
132fdd4e1e0SJan Lentfer     unsigned i, n;
133fdd4e1e0SJan Lentfer     unsigned nuses = ep->nuses;
134*32bb5217SDaniel Fojt     TERMTYPE2 *tp = &(ep->tterm);
135fdd4e1e0SJan Lentfer 
136fdd4e1e0SJan Lentfer     if (copy_strings) {
137fdd4e1e0SJan Lentfer 	next_free = 0;		/* clear static storage */
138fdd4e1e0SJan Lentfer 
139fdd4e1e0SJan Lentfer 	/* copy term_names, Strings, uses */
140fdd4e1e0SJan Lentfer 	tp->term_names = _nc_save_str(tp->term_names);
141fdd4e1e0SJan Lentfer 	for_each_string(i, tp) {
142fdd4e1e0SJan Lentfer 	    if (tp->Strings[i] != ABSENT_STRING &&
143fdd4e1e0SJan Lentfer 		tp->Strings[i] != CANCELLED_STRING) {
144fdd4e1e0SJan Lentfer 		tp->Strings[i] = _nc_save_str(tp->Strings[i]);
145fdd4e1e0SJan Lentfer 	    }
146fdd4e1e0SJan Lentfer 	}
147fdd4e1e0SJan Lentfer 
148fdd4e1e0SJan Lentfer 	for (i = 0; i < nuses; i++) {
149fdd4e1e0SJan Lentfer 	    if (ep->uses[i].name == 0) {
150fdd4e1e0SJan Lentfer 		ep->uses[i].name = _nc_save_str(ep->uses[i].name);
151fdd4e1e0SJan Lentfer 	    }
152fdd4e1e0SJan Lentfer 	}
153fdd4e1e0SJan Lentfer 
154fdd4e1e0SJan Lentfer 	free(tp->str_table);
155fdd4e1e0SJan Lentfer     }
156fdd4e1e0SJan Lentfer 
1571d102085SJan Lentfer     assert(tp->term_names >= stringbuf);
1581d102085SJan Lentfer     n = (unsigned) (tp->term_names - stringbuf);
159fdd4e1e0SJan Lentfer     for_each_string(i, &(ep->tterm)) {
1601d102085SJan Lentfer 	if (i < SIZEOF(offsets)) {
1611d102085SJan Lentfer 	    if (tp->Strings[i] == ABSENT_STRING) {
162fdd4e1e0SJan Lentfer 		offsets[i] = ABSENT_OFFSET;
1631d102085SJan Lentfer 	    } else if (tp->Strings[i] == CANCELLED_STRING) {
164fdd4e1e0SJan Lentfer 		offsets[i] = CANCELLED_OFFSET;
1651d102085SJan Lentfer 	    } else {
16600d8f3c4SJohn Marino 		offsets[i] = (int) (tp->Strings[i] - stringbuf);
167fdd4e1e0SJan Lentfer 	    }
1681d102085SJan Lentfer 	}
1691d102085SJan Lentfer     }
170fdd4e1e0SJan Lentfer 
171fdd4e1e0SJan Lentfer     for (i = 0; i < nuses; i++) {
172fdd4e1e0SJan Lentfer 	if (ep->uses[i].name == 0)
173fdd4e1e0SJan Lentfer 	    useoffsets[i] = ABSENT_OFFSET;
174fdd4e1e0SJan Lentfer 	else
17500d8f3c4SJohn Marino 	    useoffsets[i] = (int) (ep->uses[i].name - stringbuf);
176fdd4e1e0SJan Lentfer     }
177fdd4e1e0SJan Lentfer 
1783468e90cSJohn Marino     TYPE_MALLOC(char, next_free, tp->str_table);
179fdd4e1e0SJan Lentfer     (void) memcpy(tp->str_table, stringbuf, next_free);
180fdd4e1e0SJan Lentfer 
181fdd4e1e0SJan Lentfer     tp->term_names = tp->str_table + n;
182fdd4e1e0SJan Lentfer     for_each_string(i, &(ep->tterm)) {
1831d102085SJan Lentfer 	if (i < SIZEOF(offsets)) {
1841d102085SJan Lentfer 	    if (offsets[i] == ABSENT_OFFSET) {
185fdd4e1e0SJan Lentfer 		tp->Strings[i] = ABSENT_STRING;
1861d102085SJan Lentfer 	    } else if (offsets[i] == CANCELLED_OFFSET) {
187fdd4e1e0SJan Lentfer 		tp->Strings[i] = CANCELLED_STRING;
1881d102085SJan Lentfer 	    } else {
189fdd4e1e0SJan Lentfer 		tp->Strings[i] = tp->str_table + offsets[i];
190fdd4e1e0SJan Lentfer 	    }
1911d102085SJan Lentfer 	}
1921d102085SJan Lentfer     }
193fdd4e1e0SJan Lentfer 
194fdd4e1e0SJan Lentfer #if NCURSES_XNAMES
195fdd4e1e0SJan Lentfer     if (!copy_strings) {
1961d102085SJan Lentfer 	if ((n = (unsigned) NUM_EXT_NAMES(tp)) != 0) {
1971d102085SJan Lentfer 	    if (n < SIZEOF(offsets)) {
19800d8f3c4SJohn Marino 		size_t length = 0;
1993468e90cSJohn Marino 		size_t offset;
200fdd4e1e0SJan Lentfer 		for (i = 0; i < n; i++) {
201fdd4e1e0SJan Lentfer 		    length += strlen(tp->ext_Names[i]) + 1;
20200d8f3c4SJohn Marino 		    offsets[i] = (int) (tp->ext_Names[i] - stringbuf);
203fdd4e1e0SJan Lentfer 		}
2043468e90cSJohn Marino 		TYPE_MALLOC(char, length, tp->ext_str_table);
2053468e90cSJohn Marino 		for (i = 0, offset = 0; i < n; i++) {
2063468e90cSJohn Marino 		    tp->ext_Names[i] = tp->ext_str_table + offset;
2073468e90cSJohn Marino 		    _nc_STRCPY(tp->ext_Names[i],
2083468e90cSJohn Marino 			       stringbuf + offsets[i],
2093468e90cSJohn Marino 			       length - offset);
2103468e90cSJohn Marino 		    offset += strlen(tp->ext_Names[i]) + 1;
211fdd4e1e0SJan Lentfer 		}
212fdd4e1e0SJan Lentfer 	    }
213fdd4e1e0SJan Lentfer 	}
2141d102085SJan Lentfer     }
215fdd4e1e0SJan Lentfer #endif
216fdd4e1e0SJan Lentfer 
217fdd4e1e0SJan Lentfer     for (i = 0; i < nuses; i++) {
218fdd4e1e0SJan Lentfer 	if (useoffsets[i] == ABSENT_OFFSET)
219fdd4e1e0SJan Lentfer 	    ep->uses[i].name = 0;
220fdd4e1e0SJan Lentfer 	else
221fdd4e1e0SJan Lentfer 	    ep->uses[i].name = (tp->str_table + useoffsets[i]);
222fdd4e1e0SJan Lentfer     }
223fdd4e1e0SJan Lentfer }
224fdd4e1e0SJan Lentfer 
225fdd4e1e0SJan Lentfer NCURSES_EXPORT(void)
_nc_merge_entry(ENTRY * const target,ENTRY * const source)226*32bb5217SDaniel Fojt _nc_merge_entry(ENTRY * const target, ENTRY * const source)
227fdd4e1e0SJan Lentfer /* merge capabilities from `from' entry into `to' entry */
228fdd4e1e0SJan Lentfer {
229*32bb5217SDaniel Fojt     TERMTYPE2 *to = &(target->tterm);
230*32bb5217SDaniel Fojt     TERMTYPE2 *from = &(source->tterm);
231*32bb5217SDaniel Fojt #if NCURSES_XNAMES
232*32bb5217SDaniel Fojt     TERMTYPE2 copy;
233*32bb5217SDaniel Fojt #endif
234fdd4e1e0SJan Lentfer     unsigned i;
235fdd4e1e0SJan Lentfer 
236*32bb5217SDaniel Fojt     if (source == 0 || from == 0 || target == 0 || to == 0)
237*32bb5217SDaniel Fojt 	return;
238*32bb5217SDaniel Fojt 
239fdd4e1e0SJan Lentfer #if NCURSES_XNAMES
240*32bb5217SDaniel Fojt     _nc_copy_termtype2(&copy, from);
241*32bb5217SDaniel Fojt     from = &copy;
242fdd4e1e0SJan Lentfer     _nc_align_termtype(to, from);
243fdd4e1e0SJan Lentfer #endif
244fdd4e1e0SJan Lentfer     for_each_boolean(i, from) {
2451d102085SJan Lentfer 	if (to->Booleans[i] != (char) CANCELLED_BOOLEAN) {
246fdd4e1e0SJan Lentfer 	    int mergebool = from->Booleans[i];
247fdd4e1e0SJan Lentfer 
248fdd4e1e0SJan Lentfer 	    if (mergebool == CANCELLED_BOOLEAN)
249fdd4e1e0SJan Lentfer 		to->Booleans[i] = FALSE;
250fdd4e1e0SJan Lentfer 	    else if (mergebool == TRUE)
251*32bb5217SDaniel Fojt 		to->Booleans[i] = (NCURSES_SBOOL) mergebool;
252fdd4e1e0SJan Lentfer 	}
253fdd4e1e0SJan Lentfer     }
254fdd4e1e0SJan Lentfer 
255fdd4e1e0SJan Lentfer     for_each_number(i, from) {
256fdd4e1e0SJan Lentfer 	if (to->Numbers[i] != CANCELLED_NUMERIC) {
257*32bb5217SDaniel Fojt 	    int mergenum = from->Numbers[i];
258fdd4e1e0SJan Lentfer 
259fdd4e1e0SJan Lentfer 	    if (mergenum == CANCELLED_NUMERIC)
260fdd4e1e0SJan Lentfer 		to->Numbers[i] = ABSENT_NUMERIC;
261fdd4e1e0SJan Lentfer 	    else if (mergenum != ABSENT_NUMERIC)
262*32bb5217SDaniel Fojt 		to->Numbers[i] = (NCURSES_INT2) mergenum;
263fdd4e1e0SJan Lentfer 	}
264fdd4e1e0SJan Lentfer     }
265fdd4e1e0SJan Lentfer 
266fdd4e1e0SJan Lentfer     /*
267fdd4e1e0SJan Lentfer      * Note: the copies of strings this makes don't have their own
268fdd4e1e0SJan Lentfer      * storage.  This is OK right now, but will be a problem if we
269fdd4e1e0SJan Lentfer      * we ever want to deallocate entries.
270fdd4e1e0SJan Lentfer      */
271fdd4e1e0SJan Lentfer     for_each_string(i, from) {
272fdd4e1e0SJan Lentfer 	if (to->Strings[i] != CANCELLED_STRING) {
273fdd4e1e0SJan Lentfer 	    char *mergestring = from->Strings[i];
274fdd4e1e0SJan Lentfer 
275fdd4e1e0SJan Lentfer 	    if (mergestring == CANCELLED_STRING)
276fdd4e1e0SJan Lentfer 		to->Strings[i] = ABSENT_STRING;
277fdd4e1e0SJan Lentfer 	    else if (mergestring != ABSENT_STRING)
278fdd4e1e0SJan Lentfer 		to->Strings[i] = mergestring;
279fdd4e1e0SJan Lentfer 	}
280fdd4e1e0SJan Lentfer     }
281*32bb5217SDaniel Fojt #if NCURSES_XNAMES
282*32bb5217SDaniel Fojt     /* Discard the data allocated in _nc_copy_termtype2, but do not use
283*32bb5217SDaniel Fojt      * _nc_free_termtype2 because that frees the string-table (which is
284*32bb5217SDaniel Fojt      * not allocated by _nc_copy_termtype2).
285*32bb5217SDaniel Fojt      */
286*32bb5217SDaniel Fojt     free(copy.Booleans);
287*32bb5217SDaniel Fojt     free(copy.Numbers);
288*32bb5217SDaniel Fojt     free(copy.Strings);
289*32bb5217SDaniel Fojt     free(copy.ext_Names);
290*32bb5217SDaniel Fojt #endif
291fdd4e1e0SJan Lentfer }
2921d102085SJan Lentfer 
2931d102085SJan Lentfer #if NO_LEAKS
2941d102085SJan Lentfer NCURSES_EXPORT(void)
_nc_alloc_entry_leaks(void)2951d102085SJan Lentfer _nc_alloc_entry_leaks(void)
2961d102085SJan Lentfer {
2971d102085SJan Lentfer     if (stringbuf != 0) {
2981d102085SJan Lentfer 	FreeAndNull(stringbuf);
2991d102085SJan Lentfer     }
3001d102085SJan Lentfer     next_free = 0;
3011d102085SJan Lentfer }
3021d102085SJan Lentfer #endif
303