GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcurses/tinfo/alloc_ttype.c Lines: 0 237 0.0 %
Date: 2017-11-07 Branches: 0 145 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: alloc_ttype.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */
2
3
/****************************************************************************
4
 * Copyright (c) 1999-2006,2008 Free Software Foundation, Inc.              *
5
 *                                                                          *
6
 * Permission is hereby granted, free of charge, to any person obtaining a  *
7
 * copy of this software and associated documentation files (the            *
8
 * "Software"), to deal in the Software without restriction, including      *
9
 * without limitation the rights to use, copy, modify, merge, publish,      *
10
 * distribute, distribute with modifications, sublicense, and/or sell       *
11
 * copies of the Software, and to permit persons to whom the Software is    *
12
 * furnished to do so, subject to the following conditions:                 *
13
 *                                                                          *
14
 * The above copyright notice and this permission notice shall be included  *
15
 * in all copies or substantial portions of the Software.                   *
16
 *                                                                          *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24
 *                                                                          *
25
 * Except as contained in this notice, the name(s) of the above copyright   *
26
 * holders shall not be used in advertising or otherwise to promote the     *
27
 * sale, use or other dealings in this Software without prior written       *
28
 * authorization.                                                           *
29
 ****************************************************************************/
30
31
/****************************************************************************
32
 *  Author: Thomas E. Dickey <dickey@clark.net> 1999-on                     *
33
 ****************************************************************************/
34
35
/*
36
 * align_ttype.c --  functions for TERMTYPE
37
 *
38
 *	_nc_align_termtype()
39
 *	_nc_copy_termtype()
40
 *
41
 */
42
43
#include <curses.priv.h>
44
45
#include <tic.h>
46
#include <term_entry.h>
47
48
MODULE_ID("$Id: alloc_ttype.c,v 1.6 2010/01/12 23:22:06 nicm Exp $")
49
50
#if NCURSES_XNAMES
51
/*
52
 * Merge the a/b lists into dst.  Both a/b are sorted (see _nc_extend_names()),
53
 * so we do not have to worry about order dependencies.
54
 */
55
static int
56
merge_names(char **dst, char **a, int na, char **b, int nb)
57
{
58
    int n = 0;
59
    while (na > 0 && nb > 0) {
60
	int cmp = strcmp(*a, *b);
61
	if (cmp < 0) {
62
	    dst[n++] = *a++;
63
	    na--;
64
	} else if (cmp > 0) {
65
	    dst[n++] = *b++;
66
	    nb--;
67
	} else if (cmp == 0) {
68
	    dst[n++] = *a;
69
	    a++, b++;
70
	    na--, nb--;
71
	}
72
    }
73
    while (na-- > 0) {
74
	dst[n++] = *a++;
75
    }
76
    while (nb-- > 0) {
77
	dst[n++] = *b++;
78
    }
79
    DEBUG(4, ("merge_names -> %d", n));
80
    return n;
81
}
82
83
static bool
84
find_name(char **table, int length, char *name)
85
{
86
    while (length-- > 0) {
87
	if (!strcmp(*table++, name)) {
88
	    DEBUG(4, ("found name '%s'", name));
89
	    return TRUE;
90
	}
91
    }
92
    DEBUG(4, ("did not find name '%s'", name));
93
    return FALSE;
94
}
95
96
static void
97
realign_data(TERMTYPE *to, char **ext_Names,
98
	     int ext_Booleans,
99
	     int ext_Numbers,
100
	     int ext_Strings)
101
{
102
    int n, m, base;
103
    int limit = (to->ext_Booleans + to->ext_Numbers + to->ext_Strings);
104
105
    if (to->ext_Booleans != ext_Booleans) {
106
	to->num_Booleans += (ext_Booleans - to->ext_Booleans);
107
	to->Booleans = typeRealloc(NCURSES_SBOOL, to->num_Booleans, to->Booleans);
108
	for (n = to->ext_Booleans - 1,
109
	     m = ext_Booleans - 1,
110
	     base = to->num_Booleans - (m + 1); m >= 0; m--) {
111
	    if (find_name(to->ext_Names, limit, ext_Names[m])) {
112
		to->Booleans[base + m] = to->Booleans[base + n--];
113
	    } else {
114
		to->Booleans[base + m] = FALSE;
115
	    }
116
	}
117
	to->ext_Booleans = ext_Booleans;
118
    }
119
    if (to->ext_Numbers != ext_Numbers) {
120
	to->num_Numbers += (ext_Numbers - to->ext_Numbers);
121
	to->Numbers = typeRealloc(short, to->num_Numbers, to->Numbers);
122
	for (n = to->ext_Numbers - 1,
123
	     m = ext_Numbers - 1,
124
	     base = to->num_Numbers - (m + 1); m >= 0; m--) {
125
	    if (find_name(to->ext_Names, limit, ext_Names[m + ext_Booleans])) {
126
		to->Numbers[base + m] = to->Numbers[base + n--];
127
	    } else {
128
		to->Numbers[base + m] = ABSENT_NUMERIC;
129
	    }
130
	}
131
	to->ext_Numbers = ext_Numbers;
132
    }
133
    if (to->ext_Strings != ext_Strings) {
134
	to->num_Strings += (ext_Strings - to->ext_Strings);
135
	to->Strings = typeRealloc(char *, to->num_Strings, to->Strings);
136
	for (n = to->ext_Strings - 1,
137
	     m = ext_Strings - 1,
138
	     base = to->num_Strings - (m + 1); m >= 0; m--) {
139
	    if (find_name(to->ext_Names, limit, ext_Names[m + ext_Booleans + ext_Numbers])) {
140
		to->Strings[base + m] = to->Strings[base + n--];
141
	    } else {
142
		to->Strings[base + m] = ABSENT_STRING;
143
	    }
144
	}
145
	to->ext_Strings = ext_Strings;
146
    }
147
}
148
149
/*
150
 * Returns the first index in ext_Names[] for the given token-type
151
 */
152
static int
153
_nc_first_ext_name(TERMTYPE *tp, int token_type)
154
{
155
    int first;
156
157
    switch (token_type) {
158
    case BOOLEAN:
159
	first = 0;
160
	break;
161
    case NUMBER:
162
	first = tp->ext_Booleans;
163
	break;
164
    case STRING:
165
	first = tp->ext_Booleans + tp->ext_Numbers;
166
	break;
167
    default:
168
	first = 0;
169
	break;
170
    }
171
    return first;
172
}
173
174
/*
175
 * Returns the last index in ext_Names[] for the given token-type
176
 */
177
static int
178
_nc_last_ext_name(TERMTYPE *tp, int token_type)
179
{
180
    int last;
181
182
    switch (token_type) {
183
    case BOOLEAN:
184
	last = tp->ext_Booleans;
185
	break;
186
    case NUMBER:
187
	last = tp->ext_Booleans + tp->ext_Numbers;
188
	break;
189
    default:
190
    case STRING:
191
	last = NUM_EXT_NAMES(tp);
192
	break;
193
    }
194
    return last;
195
}
196
197
/*
198
 * Lookup an entry from extended-names, returning -1 if not found
199
 */
200
static int
201
_nc_find_ext_name(TERMTYPE *tp, char *name, int token_type)
202
{
203
    unsigned j;
204
    unsigned first = _nc_first_ext_name(tp, token_type);
205
    unsigned last = _nc_last_ext_name(tp, token_type);
206
207
    for (j = first; j < last; j++) {
208
	if (!strcmp(name, tp->ext_Names[j])) {
209
	    return j;
210
	}
211
    }
212
    return -1;
213
}
214
215
/*
216
 * Translate an index into ext_Names[] into the corresponding index into data
217
 * (e.g., Booleans[]).
218
 */
219
static int
220
_nc_ext_data_index(TERMTYPE *tp, int n, int token_type)
221
{
222
    switch (token_type) {
223
    case BOOLEAN:
224
	n += (tp->num_Booleans - tp->ext_Booleans);
225
	break;
226
    case NUMBER:
227
	n += (tp->num_Numbers - tp->ext_Numbers)
228
	    - (tp->ext_Booleans);
229
	break;
230
    default:
231
    case STRING:
232
	n += (tp->num_Strings - tp->ext_Strings)
233
	    - (tp->ext_Booleans + tp->ext_Numbers);
234
    }
235
    return n;
236
}
237
238
/*
239
 * Adjust tables to remove (not free) an extended name and its corresponding
240
 * data.
241
 */
242
static bool
243
_nc_del_ext_name(TERMTYPE *tp, char *name, int token_type)
244
{
245
    int j;
246
    int first, last;
247
248
    if ((first = _nc_find_ext_name(tp, name, token_type)) >= 0) {
249
	last = NUM_EXT_NAMES(tp) - 1;
250
	for (j = first; j < last; j++) {
251
	    tp->ext_Names[j] = tp->ext_Names[j + 1];
252
	}
253
	first = _nc_ext_data_index(tp, first, token_type);
254
	switch (token_type) {
255
	case BOOLEAN:
256
	    last = tp->num_Booleans - 1;
257
	    for (j = first; j < last; j++)
258
		tp->Booleans[j] = tp->Booleans[j + 1];
259
	    tp->ext_Booleans -= 1;
260
	    tp->num_Booleans -= 1;
261
	    break;
262
	case NUMBER:
263
	    last = tp->num_Numbers - 1;
264
	    for (j = first; j < last; j++)
265
		tp->Numbers[j] = tp->Numbers[j + 1];
266
	    tp->ext_Numbers -= 1;
267
	    tp->num_Numbers -= 1;
268
	    break;
269
	case STRING:
270
	    last = tp->num_Strings - 1;
271
	    for (j = first; j < last; j++)
272
		tp->Strings[j] = tp->Strings[j + 1];
273
	    tp->ext_Strings -= 1;
274
	    tp->num_Strings -= 1;
275
	    break;
276
	}
277
	return TRUE;
278
    }
279
    return FALSE;
280
}
281
282
/*
283
 * Adjust tables to insert an extended name, making room for new data.  The
284
 * index into the corresponding data array is returned.
285
 */
286
static int
287
_nc_ins_ext_name(TERMTYPE *tp, char *name, int token_type)
288
{
289
    unsigned first = _nc_first_ext_name(tp, token_type);
290
    unsigned last = _nc_last_ext_name(tp, token_type);
291
    unsigned total = NUM_EXT_NAMES(tp) + 1;
292
    unsigned j, k;
293
294
    for (j = first; j < last; j++) {
295
	int cmp = strcmp(name, tp->ext_Names[j]);
296
	if (cmp == 0)
297
	    /* already present */
298
	    return _nc_ext_data_index(tp, (int) j, token_type);
299
	if (cmp < 0) {
300
	    break;
301
	}
302
    }
303
304
    tp->ext_Names = typeRealloc(char *, total, tp->ext_Names);
305
    for (k = total - 1; k > j; k--)
306
	tp->ext_Names[k] = tp->ext_Names[k - 1];
307
    tp->ext_Names[j] = name;
308
    j = _nc_ext_data_index(tp, (int) j, token_type);
309
310
    switch (token_type) {
311
    case BOOLEAN:
312
	tp->ext_Booleans += 1;
313
	tp->num_Booleans += 1;
314
	tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans);
315
	for (k = tp->num_Booleans - 1; k > j; k--)
316
	    tp->Booleans[k] = tp->Booleans[k - 1];
317
	break;
318
    case NUMBER:
319
	tp->ext_Numbers += 1;
320
	tp->num_Numbers += 1;
321
	tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers);
322
	for (k = tp->num_Numbers - 1; k > j; k--)
323
	    tp->Numbers[k] = tp->Numbers[k - 1];
324
	break;
325
    case STRING:
326
	tp->ext_Strings += 1;
327
	tp->num_Strings += 1;
328
	tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings);
329
	for (k = tp->num_Strings - 1; k > j; k--)
330
	    tp->Strings[k] = tp->Strings[k - 1];
331
	break;
332
    }
333
    return j;
334
}
335
336
/*
337
 * Look for strings that are marked cancelled, which happen to be the same name
338
 * as a boolean or number.  We'll get this as a special case when we get a
339
 * cancellation of a name that is inherited from another entry.
340
 */
341
static void
342
adjust_cancels(TERMTYPE *to, TERMTYPE *from)
343
{
344
    int first = to->ext_Booleans + to->ext_Numbers;
345
    int last = first + to->ext_Strings;
346
    int j, k;
347
348
    for (j = first; j < last;) {
349
	char *name = to->ext_Names[j];
350
	unsigned j_str = to->num_Strings - first - to->ext_Strings;
351
352
	if (to->Strings[j + j_str] == CANCELLED_STRING) {
353
	    if ((k = _nc_find_ext_name(from, to->ext_Names[j], BOOLEAN)) >= 0) {
354
		if (_nc_del_ext_name(to, name, STRING)
355
		    || _nc_del_ext_name(to, name, NUMBER)) {
356
		    k = _nc_ins_ext_name(to, name, BOOLEAN);
357
		    to->Booleans[k] = FALSE;
358
		} else {
359
		    j++;
360
		}
361
	    } else if ((k = _nc_find_ext_name(from, to->ext_Names[j],
362
					      NUMBER)) >= 0) {
363
		if (_nc_del_ext_name(to, name, STRING)
364
		    || _nc_del_ext_name(to, name, BOOLEAN)) {
365
		    k = _nc_ins_ext_name(to, name, NUMBER);
366
		    to->Numbers[k] = CANCELLED_NUMERIC;
367
		} else {
368
		    j++;
369
		}
370
	    } else if ((k = _nc_find_ext_name(from, to->ext_Names[j],
371
					      STRING)) >= 0) {
372
		if (_nc_del_ext_name(to, name, NUMBER)
373
		    || _nc_del_ext_name(to, name, BOOLEAN)) {
374
		    k = _nc_ins_ext_name(to, name, STRING);
375
		    to->Strings[k] = CANCELLED_STRING;
376
		} else {
377
		    j++;
378
		}
379
	    } else {
380
		j++;
381
	    }
382
	} else {
383
	    j++;
384
	}
385
    }
386
}
387
388
NCURSES_EXPORT(void)
389
_nc_align_termtype(TERMTYPE *to, TERMTYPE *from)
390
{
391
    int na = NUM_EXT_NAMES(to);
392
    int nb = NUM_EXT_NAMES(from);
393
    int n;
394
    bool same;
395
    char **ext_Names;
396
    int ext_Booleans, ext_Numbers, ext_Strings;
397
    bool used_ext_Names = FALSE;
398
399
    DEBUG(2, ("align_termtype to(%d:%s), from(%d:%s)", na, to->term_names,
400
	      nb, from->term_names));
401
402
    if (na != 0 || nb != 0) {
403
	if ((na == nb)		/* check if the arrays are equivalent */
404
	    &&(to->ext_Booleans == from->ext_Booleans)
405
	    && (to->ext_Numbers == from->ext_Numbers)
406
	    && (to->ext_Strings == from->ext_Strings)) {
407
	    for (n = 0, same = TRUE; n < na; n++) {
408
		if (strcmp(to->ext_Names[n], from->ext_Names[n])) {
409
		    same = FALSE;
410
		    break;
411
		}
412
	    }
413
	    if (same)
414
		return;
415
	}
416
	/*
417
	 * This is where we pay for having a simple extension representation.
418
	 * Allocate a new ext_Names array and merge the two ext_Names arrays
419
	 * into it, updating to's counts for booleans, etc.  Fortunately we do
420
	 * this only for the terminfo compiler (tic) and comparer (infocmp).
421
	 */
422
	ext_Names = typeMalloc(char *, na + nb);
423
424
	if (to->ext_Strings && (from->ext_Booleans + from->ext_Numbers))
425
	    adjust_cancels(to, from);
426
427
	if (from->ext_Strings && (to->ext_Booleans + to->ext_Numbers))
428
	    adjust_cancels(from, to);
429
430
	ext_Booleans = merge_names(ext_Names,
431
				   to->ext_Names,
432
				   to->ext_Booleans,
433
				   from->ext_Names,
434
				   from->ext_Booleans);
435
	ext_Numbers = merge_names(ext_Names + ext_Booleans,
436
				  to->ext_Names
437
				  + to->ext_Booleans,
438
				  to->ext_Numbers,
439
				  from->ext_Names
440
				  + from->ext_Booleans,
441
				  from->ext_Numbers);
442
	ext_Strings = merge_names(ext_Names + ext_Numbers + ext_Booleans,
443
				  to->ext_Names
444
				  + to->ext_Booleans
445
				  + to->ext_Numbers,
446
				  to->ext_Strings,
447
				  from->ext_Names
448
				  + from->ext_Booleans
449
				  + from->ext_Numbers,
450
				  from->ext_Strings);
451
	/*
452
	 * Now we must reallocate the Booleans, etc., to allow the data to be
453
	 * overlaid.
454
	 */
455
	if (na != (ext_Booleans + ext_Numbers + ext_Strings)) {
456
	    realign_data(to, ext_Names, ext_Booleans, ext_Numbers, ext_Strings);
457
	    FreeIfNeeded(to->ext_Names);
458
	    to->ext_Names = ext_Names;
459
	    DEBUG(2, ("realigned %d extended names for '%s' (to)",
460
		      NUM_EXT_NAMES(to), to->term_names));
461
	    used_ext_Names = TRUE;
462
	}
463
	if (nb != (ext_Booleans + ext_Numbers + ext_Strings)) {
464
	    nb = (ext_Booleans + ext_Numbers + ext_Strings);
465
	    realign_data(from, ext_Names, ext_Booleans, ext_Numbers, ext_Strings);
466
	    from->ext_Names = typeRealloc(char *, nb, from->ext_Names);
467
	    memcpy(from->ext_Names, ext_Names, sizeof(char *) * nb);
468
	    DEBUG(2, ("realigned %d extended names for '%s' (from)",
469
		      NUM_EXT_NAMES(from), from->term_names));
470
	}
471
	if (!used_ext_Names)
472
	    free(ext_Names);
473
    }
474
}
475
#endif
476
477
NCURSES_EXPORT(void)
478
_nc_copy_termtype(TERMTYPE *dst, TERMTYPE *src)
479
{
480
    unsigned i;
481
482
    *dst = *src;		/* ...to copy the sizes and string-tables */
483
    dst->Booleans = typeMalloc(NCURSES_SBOOL, NUM_BOOLEANS(dst));
484
    dst->Numbers = typeMalloc(short, NUM_NUMBERS(dst));
485
    dst->Strings = typeMalloc(char *, NUM_STRINGS(dst));
486
487
    /* FIXME: use memcpy for these and similar loops */
488
    for_each_boolean(i, dst)
489
	dst->Booleans[i] = src->Booleans[i];
490
    for_each_number(i, dst)
491
	dst->Numbers[i] = src->Numbers[i];
492
    for_each_string(i, dst)
493
	dst->Strings[i] = src->Strings[i];
494
495
    /* FIXME: we probably should also copy str_table and ext_str_table,
496
     * but tic and infocmp are not written to exploit that (yet).
497
     */
498
499
#if NCURSES_XNAMES
500
    if ((i = NUM_EXT_NAMES(src)) != 0) {
501
	dst->ext_Names = typeMalloc(char *, i);
502
	memcpy(dst->ext_Names, src->ext_Names, i * sizeof(char *));
503
    } else {
504
	dst->ext_Names = 0;
505
    }
506
#endif
507
508
}