1 /****************************************************************************
2 * Copyright (c) 1998-2008,2010 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.51 2010/12/25 23:06:01 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 */
69 FreeAndNull(stringbuf
);
76 stringbuf
= (char *) malloc(MAX_STRTAB
);
79 tp
->num_Booleans
= BOOLCOUNT
;
80 tp
->num_Numbers
= NUMCOUNT
;
81 tp
->num_Strings
= STRCOUNT
;
86 if (tp
->Booleans
== 0)
87 tp
->Booleans
= typeMalloc(NCURSES_SBOOL
, BOOLCOUNT
);
89 tp
->Numbers
= typeMalloc(short, NUMCOUNT
);
91 tp
->Strings
= typeMalloc(char *, STRCOUNT
);
93 for_each_boolean(i
, tp
)
94 tp
->Booleans
[i
] = FALSE
;
96 for_each_number(i
, tp
)
97 tp
->Numbers
[i
] = ABSENT_NUMERIC
;
99 for_each_string(i
, tp
)
100 tp
->Strings
[i
] = ABSENT_STRING
;
105 NCURSES_EXPORT(ENTRY
*)
106 _nc_copy_entry(ENTRY
* oldp
)
108 ENTRY
*newp
= typeCalloc(ENTRY
, 1);
112 _nc_copy_termtype(&(newp
->tterm
), &(oldp
->tterm
));
117 /* save a copy of string in the string buffer */
118 NCURSES_EXPORT(char *)
119 _nc_save_str(const char *const string
)
122 size_t old_next_free
= next_free
;
123 size_t len
= strlen(string
) + 1;
125 if (len
== 1 && next_free
!= 0) {
127 * Cheat a little by making an empty string point to the end of the
130 if (next_free
< MAX_STRTAB
) {
131 result
= (stringbuf
+ next_free
- 1);
133 } else if (next_free
+ len
< MAX_STRTAB
) {
134 strcpy(&stringbuf
[next_free
], string
);
135 DEBUG(7, ("Saved string %s", _nc_visbuf(string
)));
136 DEBUG(7, ("at location %d", (int) next_free
));
138 result
= (stringbuf
+ old_next_free
);
140 _nc_warning("Too much data, some is lost");
146 _nc_wrap_entry(ENTRY
* const ep
, bool copy_strings
)
147 /* copy the string parts to allocated storage, preserving pointers to it */
149 int offsets
[MAX_ENTRY_SIZE
/ sizeof(short)];
150 int useoffsets
[MAX_USES
];
152 unsigned nuses
= ep
->nuses
;
153 TERMTYPE
*tp
= &(ep
->tterm
);
156 next_free
= 0; /* clear static storage */
158 /* copy term_names, Strings, uses */
159 tp
->term_names
= _nc_save_str(tp
->term_names
);
160 for_each_string(i
, tp
) {
161 if (tp
->Strings
[i
] != ABSENT_STRING
&&
162 tp
->Strings
[i
] != CANCELLED_STRING
) {
163 tp
->Strings
[i
] = _nc_save_str(tp
->Strings
[i
]);
167 for (i
= 0; i
< nuses
; i
++) {
168 if (ep
->uses
[i
].name
== 0) {
169 ep
->uses
[i
].name
= _nc_save_str(ep
->uses
[i
].name
);
176 assert(tp
->term_names
>= stringbuf
);
177 n
= (unsigned) (tp
->term_names
- stringbuf
);
178 for_each_string(i
, &(ep
->tterm
)) {
179 if (i
< SIZEOF(offsets
)) {
180 if (tp
->Strings
[i
] == ABSENT_STRING
) {
181 offsets
[i
] = ABSENT_OFFSET
;
182 } else if (tp
->Strings
[i
] == CANCELLED_STRING
) {
183 offsets
[i
] = CANCELLED_OFFSET
;
185 offsets
[i
] = (int) (tp
->Strings
[i
] - stringbuf
);
190 for (i
= 0; i
< nuses
; i
++) {
191 if (ep
->uses
[i
].name
== 0)
192 useoffsets
[i
] = ABSENT_OFFSET
;
194 useoffsets
[i
] = (int) (ep
->uses
[i
].name
- stringbuf
);
197 if ((tp
->str_table
= typeMalloc(char, next_free
)) == (char *) 0)
198 _nc_err_abort(MSG_NO_MEMORY
);
199 (void) memcpy(tp
->str_table
, stringbuf
, next_free
);
201 tp
->term_names
= tp
->str_table
+ n
;
202 for_each_string(i
, &(ep
->tterm
)) {
203 if (i
< SIZEOF(offsets
)) {
204 if (offsets
[i
] == ABSENT_OFFSET
) {
205 tp
->Strings
[i
] = ABSENT_STRING
;
206 } else if (offsets
[i
] == CANCELLED_OFFSET
) {
207 tp
->Strings
[i
] = CANCELLED_STRING
;
209 tp
->Strings
[i
] = tp
->str_table
+ offsets
[i
];
216 if ((n
= (unsigned) NUM_EXT_NAMES(tp
)) != 0) {
217 if (n
< SIZEOF(offsets
)) {
219 for (i
= 0; i
< n
; i
++) {
220 length
+= strlen(tp
->ext_Names
[i
]) + 1;
221 offsets
[i
] = (int) (tp
->ext_Names
[i
] - stringbuf
);
223 if ((tp
->ext_str_table
= typeMalloc(char, length
)) == 0)
224 _nc_err_abort(MSG_NO_MEMORY
);
225 for (i
= 0, length
= 0; i
< n
; i
++) {
226 tp
->ext_Names
[i
] = tp
->ext_str_table
+ length
;
227 strcpy(tp
->ext_Names
[i
], stringbuf
+ offsets
[i
]);
228 length
+= strlen(tp
->ext_Names
[i
]) + 1;
235 for (i
= 0; i
< nuses
; i
++) {
236 if (useoffsets
[i
] == ABSENT_OFFSET
)
237 ep
->uses
[i
].name
= 0;
239 ep
->uses
[i
].name
= (tp
->str_table
+ useoffsets
[i
]);
244 _nc_merge_entry(TERMTYPE
*const to
, TERMTYPE
*const from
)
245 /* merge capabilities from `from' entry into `to' entry */
250 _nc_align_termtype(to
, from
);
252 for_each_boolean(i
, from
) {
253 if (to
->Booleans
[i
] != (char) CANCELLED_BOOLEAN
) {
254 int mergebool
= from
->Booleans
[i
];
256 if (mergebool
== CANCELLED_BOOLEAN
)
257 to
->Booleans
[i
] = FALSE
;
258 else if (mergebool
== TRUE
)
259 to
->Booleans
[i
] = (char) mergebool
;
263 for_each_number(i
, from
) {
264 if (to
->Numbers
[i
] != CANCELLED_NUMERIC
) {
265 short mergenum
= from
->Numbers
[i
];
267 if (mergenum
== CANCELLED_NUMERIC
)
268 to
->Numbers
[i
] = ABSENT_NUMERIC
;
269 else if (mergenum
!= ABSENT_NUMERIC
)
270 to
->Numbers
[i
] = mergenum
;
275 * Note: the copies of strings this makes don't have their own
276 * storage. This is OK right now, but will be a problem if we
277 * we ever want to deallocate entries.
279 for_each_string(i
, from
) {
280 if (to
->Strings
[i
] != CANCELLED_STRING
) {
281 char *mergestring
= from
->Strings
[i
];
283 if (mergestring
== CANCELLED_STRING
)
284 to
->Strings
[i
] = ABSENT_STRING
;
285 else if (mergestring
!= ABSENT_STRING
)
286 to
->Strings
[i
] = mergestring
;
293 _nc_alloc_entry_leaks(void)
295 if (stringbuf
!= 0) {
296 FreeAndNull(stringbuf
);