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(©, from);
241*32bb5217SDaniel Fojt from = ©
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