1 /****************************************************************************
2 * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
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: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
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. *
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 *
27 ****************************************************************************/
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 ****************************************************************************/
36 * alloc_entry.c -- allocation functions for terminfo entries
46 #include <curses.priv.h>
50 MODULE_ID("$Id: alloc_entry.c,v 1.58 2013/08/17 19:20:38 tom Exp $")
52 #define ABSENT_OFFSET -1
53 #define CANCELLED_OFFSET -2
55 #define MAX_STRTAB 4096 /* documented maximum entry size */
57 static char *stringbuf
; /* buffer for string capabilities */
58 static size_t next_free
; /* next free character in stringbuf */
61 _nc_init_entry(TERMTYPE
*const tp
)
62 /* initialize a terminal type data block */
67 FreeAndNull(stringbuf
);
74 TYPE_MALLOC(char, (size_t) MAX_STRTAB
, stringbuf
);
78 _nc_init_termtype(tp
);
81 NCURSES_EXPORT(ENTRY
*)
82 _nc_copy_entry(ENTRY
* oldp
)
84 ENTRY
*newp
= typeCalloc(ENTRY
, 1);
88 _nc_copy_termtype(&(newp
->tterm
), &(oldp
->tterm
));
93 /* save a copy of string in the string buffer */
94 NCURSES_EXPORT(char *)
95 _nc_save_str(const char *const string
)
98 size_t old_next_free
= next_free
;
99 size_t len
= strlen(string
) + 1;
101 if (len
== 1 && next_free
!= 0) {
103 * Cheat a little by making an empty string point to the end of the
106 if (next_free
< MAX_STRTAB
) {
107 result
= (stringbuf
+ next_free
- 1);
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
));
114 result
= (stringbuf
+ old_next_free
);
116 _nc_warning("Too much data, some is lost: %s", string
);
122 _nc_wrap_entry(ENTRY
* const ep
, bool copy_strings
)
123 /* copy the string parts to allocated storage, preserving pointers to it */
125 int offsets
[MAX_ENTRY_SIZE
/ sizeof(short)];
126 int useoffsets
[MAX_USES
];
128 unsigned nuses
= ep
->nuses
;
129 TERMTYPE
*tp
= &(ep
->tterm
);
132 next_free
= 0; /* clear static storage */
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
]);
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
);
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
;
161 offsets
[i
] = (int) (tp
->Strings
[i
] - stringbuf
);
166 for (i
= 0; i
< nuses
; i
++) {
167 if (ep
->uses
[i
].name
== 0)
168 useoffsets
[i
] = ABSENT_OFFSET
;
170 useoffsets
[i
] = (int) (ep
->uses
[i
].name
- stringbuf
);
173 TYPE_MALLOC(char, next_free
, tp
->str_table
);
174 (void) memcpy(tp
->str_table
, stringbuf
, next_free
);
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
;
184 tp
->Strings
[i
] = tp
->str_table
+ offsets
[i
];
191 if ((n
= (unsigned) NUM_EXT_NAMES(tp
)) != 0) {
192 if (n
< SIZEOF(offsets
)) {
195 for (i
= 0; i
< n
; i
++) {
196 length
+= strlen(tp
->ext_Names
[i
]) + 1;
197 offsets
[i
] = (int) (tp
->ext_Names
[i
] - stringbuf
);
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
],
205 offset
+= strlen(tp
->ext_Names
[i
]) + 1;
212 for (i
= 0; i
< nuses
; i
++) {
213 if (useoffsets
[i
] == ABSENT_OFFSET
)
214 ep
->uses
[i
].name
= 0;
216 ep
->uses
[i
].name
= (tp
->str_table
+ useoffsets
[i
]);
221 _nc_merge_entry(TERMTYPE
*const to
, TERMTYPE
*const from
)
222 /* merge capabilities from `from' entry into `to' entry */
227 _nc_align_termtype(to
, from
);
229 for_each_boolean(i
, from
) {
230 if (to
->Booleans
[i
] != (char) CANCELLED_BOOLEAN
) {
231 int mergebool
= from
->Booleans
[i
];
233 if (mergebool
== CANCELLED_BOOLEAN
)
234 to
->Booleans
[i
] = FALSE
;
235 else if (mergebool
== TRUE
)
236 to
->Booleans
[i
] = (char) mergebool
;
240 for_each_number(i
, from
) {
241 if (to
->Numbers
[i
] != CANCELLED_NUMERIC
) {
242 short mergenum
= from
->Numbers
[i
];
244 if (mergenum
== CANCELLED_NUMERIC
)
245 to
->Numbers
[i
] = ABSENT_NUMERIC
;
246 else if (mergenum
!= ABSENT_NUMERIC
)
247 to
->Numbers
[i
] = mergenum
;
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.
256 for_each_string(i
, from
) {
257 if (to
->Strings
[i
] != CANCELLED_STRING
) {
258 char *mergestring
= from
->Strings
[i
];
260 if (mergestring
== CANCELLED_STRING
)
261 to
->Strings
[i
] = ABSENT_STRING
;
262 else if (mergestring
!= ABSENT_STRING
)
263 to
->Strings
[i
] = mergestring
;
270 _nc_alloc_entry_leaks(void)
272 if (stringbuf
!= 0) {
273 FreeAndNull(stringbuf
);