Annotation of src/lib/libterminfo/compile.c, Revision 1.24
1.24 ! roy 1: /* $NetBSD: compile.c,v 1.23 2020/03/30 00:09:06 roy Exp $ */
1.1 roy 2:
3: /*
1.14 roy 4: * Copyright (c) 2009, 2010, 2011, 2020 The NetBSD Foundation, Inc.
1.1 roy 5: *
6: * This code is derived from software contributed to The NetBSD Foundation
7: * by Roy Marples.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: #if HAVE_NBTOOL_CONFIG_H
31: #include "nbtool_config.h"
32: #endif
33:
34: #include <sys/cdefs.h>
1.24 ! roy 35: __RCSID("$NetBSD: compile.c,v 1.23 2020/03/30 00:09:06 roy Exp $");
1.3 dholland 36:
37: #if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H
38: #include <sys/endian.h>
39: #endif
1.1 roy 40:
41: #include <assert.h>
42: #include <ctype.h>
43: #include <err.h>
44: #include <errno.h>
45: #include <limits.h>
46: #include <stdarg.h>
47: #include <stdlib.h>
48: #include <stdint.h>
49: #include <stdio.h>
50: #include <string.h>
51: #include <term_private.h>
52: #include <term.h>
53:
1.6 joerg 54: static void __printflike(2, 3)
1.1 roy 55: dowarn(int flags, const char *fmt, ...)
56: {
57: va_list va;
58:
59: errno = EINVAL;
60: if (flags & TIC_WARNING) {
61: va_start(va, fmt);
62: vwarnx(fmt, va);
63: va_end(va);
64: }
65: }
66:
1.22 roy 67: int
68: _ti_promote(TIC *tic)
69: {
1.23 roy 70: char *obuf, type, flag, *buf, *delim, *name, *nbuf;
1.22 roy 71: const char *cap, *code, *str;
72: size_t n, entries, strl;
73: uint16_t ind;
74: int num, ortype, error = 0;
75:
76: ortype = tic->rtype;
77: tic->rtype = TERMINFO_RTYPE;
78: obuf = tic->name;
79: tic->name = _ti_getname(tic->rtype, tic->name);
80: if (tic->name == NULL) {
81: warn("_ti_getname");
82: tic->name = obuf;
83: return -1;
84: }
85: free(obuf);
86:
1.23 roy 87: n = 0;
88: obuf = buf = tic->alias;
89: tic->alias = NULL;
90: while (buf != NULL) {
91: delim = strchr(buf, '|');
92: if (delim != NULL)
93: *delim++ = '\0';
94: name = _ti_getname(tic->rtype, buf);
95: strl = strlen(name) + 1;
96: nbuf = realloc(tic->alias, n + strl);
97: if (nbuf == NULL) {
98: free(name);
99: return -1;
100: }
101: tic->alias = nbuf;
102: memcpy(tic->alias + n, name, strl);
103: n += strl;
104: free(name);
105: buf = delim;
106: }
107: free(obuf);
108:
1.22 roy 109: obuf = tic->nums.buf;
110: cap = obuf;
111: entries = tic->nums.entries;
112: tic->nums.buf = NULL;
113: tic->nums.entries = tic->nums.buflen = tic->nums.bufpos = 0;
114: for (n = entries; n > 0; n--) {
115: ind = _ti_decode_16(&cap);
116: num = _ti_decode_num(&cap, ortype);
117: if (VALID_NUMERIC(num) &&
118: !_ti_encode_buf_id_num(&tic->nums, ind, num,
119: _ti_numsize(tic)))
120: {
121: warn("promote num");
122: error = -1;
123: break;
124: }
125: }
126: free(obuf);
127:
128: obuf = tic->extras.buf;
129: cap = obuf;
130: entries = tic->extras.entries;
131: tic->extras.buf = NULL;
132: tic->extras.entries = tic->extras.buflen = tic->extras.bufpos = 0;
133: for (n = entries; n > 0; n--) {
134: num = _ti_decode_16(&cap);
1.24 ! roy 135: flag = 0; /* satisfy gcc, won't be used for non flag types */
! 136: str = NULL; /* satisfy gcc, won't be used as strl is 0 */
1.22 roy 137: strl = 0;
138: code = cap;
139: cap += num;
140: type = *cap++;
141: switch (type) {
142: case 'f':
143: flag = *cap++;
144: break;
145: case 'n':
146: num = _ti_decode_num(&cap, ortype);
147: break;
148: case 's':
149: strl = _ti_decode_16(&cap);
150: str = cap;
151: cap += strl;
152: break;
153: default:
154: errno = EINVAL;
155: break;
156: }
157: if (!_ti_store_extra(tic, 0, code, type, flag, num,
158: str, strl, TIC_EXTRA))
159: {
160: error = -1;
161: break;
162: }
163: }
164: free(obuf);
165:
166: return error;
167: }
168:
1.1 roy 169: char *
170: _ti_grow_tbuf(TBUF *tbuf, size_t len)
171: {
172: char *buf;
173: size_t l;
174:
175: _DIAGASSERT(tbuf != NULL);
176:
177: l = tbuf->bufpos + len;
178: if (l > tbuf->buflen) {
1.7 joerg 179: if (tbuf->buflen == 0)
1.1 roy 180: buf = malloc(l);
181: else
182: buf = realloc(tbuf->buf, l);
183: if (buf == NULL)
184: return NULL;
185: tbuf->buf = buf;
186: tbuf->buflen = l;
187: }
188: return tbuf->buf;
189: }
190:
1.16 christos 191: const char *
1.15 christos 192: _ti_find_cap(TIC *tic, TBUF *tbuf, char type, short ind)
1.1 roy 193: {
194: size_t n;
1.12 roy 195: uint16_t num;
1.16 christos 196: const char *cap;
1.1 roy 197:
198: _DIAGASSERT(tbuf != NULL);
199:
200: cap = tbuf->buf;
201: for (n = tbuf->entries; n > 0; n--) {
1.16 christos 202: num = _ti_decode_16(&cap);
1.12 roy 203: if ((short)num == ind)
1.1 roy 204: return cap;
205: switch (type) {
206: case 'f':
207: cap++;
208: break;
209: case 'n':
1.15 christos 210: cap += _ti_numsize(tic);
1.1 roy 211: break;
212: case 's':
1.16 christos 213: num = _ti_decode_16(&cap);
1.1 roy 214: cap += num;
215: break;
216: }
217: }
1.9 roy 218:
1.1 roy 219: errno = ESRCH;
220: return NULL;
221: }
222:
1.16 christos 223: const char *
1.15 christos 224: _ti_find_extra(TIC *tic, TBUF *tbuf, const char *code)
1.1 roy 225: {
226: size_t n;
1.12 roy 227: uint16_t num;
1.16 christos 228: const char *cap;
1.1 roy 229:
230: _DIAGASSERT(tbuf != NULL);
231: _DIAGASSERT(code != NULL);
232:
233: cap = tbuf->buf;
234: for (n = tbuf->entries; n > 0; n--) {
1.16 christos 235: num = _ti_decode_16(&cap);
1.1 roy 236: if (strcmp(cap, code) == 0)
237: return cap + num;
238: cap += num;
239: switch (*cap++) {
240: case 'f':
241: cap++;
242: break;
243: case 'n':
1.15 christos 244: cap += _ti_numsize(tic);
1.1 roy 245: break;
246: case 's':
1.16 christos 247: num = _ti_decode_16(&cap);
1.1 roy 248: cap += num;
249: break;
250: }
251: }
1.9 roy 252:
1.1 roy 253: errno = ESRCH;
254: return NULL;
255: }
256:
1.15 christos 257: char *
258: _ti_getname(int rtype, const char *orig)
259: {
1.21 roy 260: const char *delim;
1.15 christos 261: char *name;
1.21 roy 262: const char *verstr;
263: size_t diff, vlen;
1.15 christos 264:
1.21 roy 265: switch (rtype) {
266: case TERMINFO_RTYPE:
267: verstr = TERMINFO_VDELIMSTR "v3";
268: break;
269: case TERMINFO_RTYPE_O1:
270: verstr = "";
271: break;
272: default:
273: errno = EINVAL;
274: return NULL;
1.15 christos 275: }
1.21 roy 276:
277: delim = orig;
278: while (*delim != '\0' && *delim != TERMINFO_VDELIM)
279: delim++;
280: diff = delim - orig;
281: vlen = strlen(verstr);
282: name = malloc(diff + vlen + 1);
283: if (name == NULL)
284: return NULL;
285:
286: memcpy(name, orig, diff);
287: memcpy(name + diff, verstr, vlen + 1);
1.15 christos 288: return name;
289: }
290:
1.1 roy 291: size_t
1.15 christos 292: _ti_store_extra(TIC *tic, int wrn, const char *id, char type, char flag,
293: int num, const char *str, size_t strl, int flags)
1.1 roy 294: {
1.22 roy 295: size_t l, capl;
1.1 roy 296:
297: _DIAGASSERT(tic != NULL);
298:
299: if (strcmp(id, "use") != 0) {
1.15 christos 300: if (_ti_find_extra(tic, &tic->extras, id) != NULL)
1.1 roy 301: return 0;
302: if (!(flags & TIC_EXTRA)) {
303: if (wrn != 0)
304: dowarn(flags, "%s: %s: unknown capability",
305: tic->name, id);
306: return 0;
307: }
308: }
1.9 roy 309:
1.1 roy 310: l = strlen(id) + 1;
1.22 roy 311: if (l > UINT16_MAX) {
1.1 roy 312: dowarn(flags, "%s: %s: cap name is too long", tic->name, id);
313: return 0;
314: }
1.9 roy 315:
1.22 roy 316: capl = sizeof(uint16_t) + l + 1;
317: switch (type) {
318: case 'f':
319: capl++;
320: break;
321: case 'n':
322: capl += _ti_numsize(tic);
323: break;
324: case 's':
325: capl += sizeof(uint16_t) + strl;
326: break;
327: }
328:
329: if (!_ti_grow_tbuf(&tic->extras, capl))
1.1 roy 330: return 0;
1.16 christos 331: _ti_encode_buf_count_str(&tic->extras, id, l);
1.1 roy 332: tic->extras.buf[tic->extras.bufpos++] = type;
333: switch (type) {
334: case 'f':
335: tic->extras.buf[tic->extras.bufpos++] = flag;
336: break;
337: case 'n':
1.16 christos 338: _ti_encode_buf_num(&tic->extras, num, tic->rtype);
1.1 roy 339: break;
340: case 's':
1.16 christos 341: _ti_encode_buf_count_str(&tic->extras, str, strl);
1.1 roy 342: break;
343: }
344: tic->extras.entries++;
345: return 1;
346: }
347:
1.16 christos 348: static void
349: _ti_encode_buf(char **cap, const TBUF *buf)
350: {
351: if (buf->entries == 0) {
352: _ti_encode_16(cap, 0);
353: } else {
354: _ti_encode_16(cap, buf->bufpos + sizeof(uint16_t));
355: _ti_encode_16(cap, buf->entries);
356: _ti_encode_str(cap, buf->buf, buf->bufpos);
357: }
358: }
359:
1.1 roy 360: ssize_t
361: _ti_flatten(uint8_t **buf, const TIC *tic)
362: {
363: size_t buflen, len, alen, dlen;
1.16 christos 364: char *cap;
1.1 roy 365:
366: _DIAGASSERT(buf != NULL);
367: _DIAGASSERT(tic != NULL);
368:
369: len = strlen(tic->name) + 1;
370: if (tic->alias == NULL)
371: alen = 0;
372: else
373: alen = strlen(tic->alias) + 1;
374: if (tic->desc == NULL)
375: dlen = 0;
376: else
377: dlen = strlen(tic->desc) + 1;
1.16 christos 378:
1.1 roy 379: buflen = sizeof(char) +
380: sizeof(uint16_t) + len +
381: sizeof(uint16_t) + alen +
382: sizeof(uint16_t) + dlen +
383: (sizeof(uint16_t) * 2) + tic->flags.bufpos +
384: (sizeof(uint16_t) * 2) + tic->nums.bufpos +
385: (sizeof(uint16_t) * 2) + tic->strs.bufpos +
386: (sizeof(uint16_t) * 2) + tic->extras.bufpos;
1.16 christos 387:
1.1 roy 388: *buf = malloc(buflen);
389: if (*buf == NULL)
390: return -1;
1.9 roy 391:
1.16 christos 392: cap = (char *)*buf;
1.15 christos 393: *cap++ = tic->rtype;
1.9 roy 394:
1.16 christos 395: _ti_encode_count_str(&cap, tic->name, len);
396: _ti_encode_count_str(&cap, tic->alias, alen);
397: _ti_encode_count_str(&cap, tic->desc, dlen);
1.9 roy 398:
1.16 christos 399: _ti_encode_buf(&cap, &tic->flags);
1.9 roy 400:
1.16 christos 401: _ti_encode_buf(&cap, &tic->nums);
402: _ti_encode_buf(&cap, &tic->strs);
403: _ti_encode_buf(&cap, &tic->extras);
1.1 roy 404:
1.16 christos 405: return (uint8_t *)cap - *buf;
1.1 roy 406: }
407:
408: static int
409: encode_string(const char *term, const char *cap, TBUF *tbuf, const char *str,
410: int flags)
411: {
412: int slash, i, num;
413: char ch, *p, *s, last;
1.9 roy 414:
1.1 roy 415: if (_ti_grow_tbuf(tbuf, strlen(str) + 1) == NULL)
416: return -1;
417: p = s = tbuf->buf + tbuf->bufpos;
418: slash = 0;
419: last = '\0';
420: /* Convert escape codes */
421: while ((ch = *str++) != '\0') {
1.10 roy 422: if (ch == '\n') {
423: /* Following a newline, strip leading whitespace from
424: * capability strings. */
425: while (isspace((unsigned char)*str))
426: str++;
427: continue;
428: }
1.1 roy 429: if (slash == 0 && ch == '\\') {
430: slash = 1;
431: continue;
432: }
433: if (slash == 0) {
434: if (last != '%' && ch == '^') {
435: ch = *str++;
436: if (((unsigned char)ch) >= 128)
437: dowarn(flags,
438: "%s: %s: illegal ^ character",
439: term, cap);
440: if (ch == '\0')
441: break;
442: if (ch == '?')
443: ch = '\177';
444: else if ((ch &= 037) == 0)
1.5 roy 445: ch = (char)128;
1.11 roy 446: } else if (!isprint((unsigned char)ch))
447: dowarn(flags,
448: "%s: %s: unprintable character",
449: term, cap);
1.1 roy 450: *p++ = ch;
451: last = ch;
452: continue;
453: }
454: slash = 0;
455: if (ch >= '0' && ch <= '7') {
456: num = ch - '0';
457: for (i = 0; i < 2; i++) {
458: if (*str < '0' || *str > '7') {
459: if (isdigit((unsigned char)*str))
460: dowarn(flags,
461: "%s: %s: non octal"
462: " digit", term, cap);
463: else
464: break;
465: }
466: num = num * 8 + *str++ - '0';
467: }
468: if (num == 0)
469: num = 0200;
470: *p++ = (char)num;
471: continue;
472: }
473: switch (ch) {
474: case 'a':
475: *p++ = '\a';
476: break;
477: case 'b':
478: *p++ = '\b';
479: break;
480: case 'e': /* FALLTHROUGH */
481: case 'E':
482: *p++ = '\033';
483: break;
484: case 'f':
485: *p++ = '\014';
486: break;
487: case 'l': /* FALLTHROUGH */
488: case 'n':
489: *p++ = '\n';
490: break;
491: case 'r':
492: *p++ = '\r';
493: break;
494: case 's':
495: *p++ = ' ';
496: break;
497: case 't':
498: *p++ = '\t';
499: break;
500: default:
501: /* We should warn here */
502: case '^':
503: case ',':
504: case ':':
505: case '|':
506: *p++ = ch;
507: break;
508: }
509: last = ch;
510: }
511: *p++ = '\0';
1.12 roy 512: tbuf->bufpos += (size_t)(p - s);
1.1 roy 513: return 0;
514: }
515:
1.4 roy 516: char *
517: _ti_get_token(char **cap, char sep)
1.1 roy 518: {
1.4 roy 519: char esc, *token;
1.1 roy 520:
521: while (isspace((unsigned char)**cap))
522: (*cap)++;
523: if (**cap == '\0')
524: return NULL;
525:
526: /* We can't use stresep(3) as ^ we need two escape chars */
1.4 roy 527: esc = '\0';
1.1 roy 528: for (token = *cap;
1.4 roy 529: **cap != '\0' && (esc != '\0' || **cap != sep);
1.1 roy 530: (*cap)++)
531: {
1.4 roy 532: if (esc == '\0') {
1.1 roy 533: if (**cap == '\\' || **cap == '^')
1.4 roy 534: esc = **cap;
535: } else {
536: /* termcap /E/ is valid */
537: if (sep == ':' && esc == '\\' && **cap == 'E')
538: esc = 'x';
539: else
540: esc = '\0';
541: }
1.1 roy 542: }
543:
544: if (**cap != '\0')
545: *(*cap)++ = '\0';
546:
547: return token;
548: }
549:
1.16 christos 550: int
551: _ti_encode_buf_id_num(TBUF *tbuf, int ind, int num, size_t len)
552: {
553: if (!_ti_grow_tbuf(tbuf, sizeof(uint16_t) + len))
554: return 0;
555: _ti_encode_buf_16(tbuf, ind);
556: if (len == sizeof(uint32_t))
557: _ti_encode_buf_32(tbuf, num);
558: else
559: _ti_encode_buf_16(tbuf, num);
560: tbuf->entries++;
561: return 1;
562: }
563:
564: int
565: _ti_encode_buf_id_count_str(TBUF *tbuf, int ind, const void *buf, size_t len)
566: {
567: if (!_ti_grow_tbuf(tbuf, 2 * sizeof(uint16_t) + len))
568: return 0;
569: _ti_encode_buf_16(tbuf, ind);
570: _ti_encode_buf_count_str(tbuf, buf, len);
571: tbuf->entries++;
572: return 1;
573: }
574:
575: int
576: _ti_encode_buf_id_flags(TBUF *tbuf, int ind, int flag)
577: {
578: if (!_ti_grow_tbuf(tbuf, sizeof(uint16_t) + 1))
579: return 0;
580: _ti_encode_buf_16(tbuf, ind);
581: tbuf->buf[tbuf->bufpos++] = flag;
582: tbuf->entries++;
583: return 1;
584: }
585:
1.1 roy 586: TIC *
587: _ti_compile(char *cap, int flags)
588: {
589: char *token, *p, *e, *name, *desc, *alias;
590: signed char flag;
1.5 roy 591: long cnum;
1.14 roy 592: short ind;
593: int num;
1.1 roy 594: size_t len;
595: TBUF buf;
596: TIC *tic;
597:
1.9 roy 598: _DIAGASSERT(cap != NULL);
1.1 roy 599:
1.4 roy 600: name = _ti_get_token(&cap, ',');
1.1 roy 601: if (name == NULL) {
1.15 christos 602: dowarn(flags, "no separator found: %s", cap);
1.1 roy 603: return NULL;
604: }
605: desc = strrchr(name, '|');
606: if (desc != NULL)
607: *desc++ = '\0';
608: alias = strchr(name, '|');
609: if (alias != NULL)
610: *alias++ = '\0';
611:
1.14 roy 612: if (strlen(name) > UINT16_MAX - 1) {
613: dowarn(flags, "%s: name too long", name);
614: return NULL;
615: }
616: if (desc != NULL && strlen(desc) > UINT16_MAX - 1) {
617: dowarn(flags, "%s: description too long: %s", name, desc);
618: return NULL;
619: }
620: if (alias != NULL && strlen(alias) > UINT16_MAX - 1) {
621: dowarn(flags, "%s: alias too long: %s", name, alias);
622: return NULL;
623: }
624:
1.1 roy 625: tic = calloc(sizeof(*tic), 1);
626: if (tic == NULL)
627: return NULL;
628:
1.22 roy 629: tic->rtype = TERMINFO_RTYPE_O1; /* will promote if needed */
1.1 roy 630: buf.buf = NULL;
631: buf.buflen = 0;
632:
1.15 christos 633: tic->name = _ti_getname(tic->rtype, name);
1.1 roy 634: if (tic->name == NULL)
635: goto error;
636: if (alias != NULL && flags & TIC_ALIAS) {
1.15 christos 637: tic->alias = _ti_getname(tic->rtype, alias);
1.1 roy 638: if (tic->alias == NULL)
639: goto error;
640: }
641: if (desc != NULL && flags & TIC_DESCRIPTION) {
642: tic->desc = strdup(desc);
643: if (tic->desc == NULL)
644: goto error;
645: }
646:
1.4 roy 647: for (token = _ti_get_token(&cap, ',');
1.1 roy 648: token != NULL && *token != '\0';
1.4 roy 649: token = _ti_get_token(&cap, ','))
1.1 roy 650: {
651: /* Skip commented caps */
652: if (!(flags & TIC_COMMENT) && token[0] == '.')
653: continue;
654:
655: /* Obsolete entries */
656: if (token[0] == 'O' && token[1] == 'T') {
657: if (!(flags & TIC_EXTRA))
658: continue;
659: token += 2;
660: }
661:
662: /* str cap */
663: p = strchr(token, '=');
664: if (p != NULL) {
665: *p++ = '\0';
666: /* Don't use the string if we already have it */
1.12 roy 667: ind = (short)_ti_strindex(token);
1.1 roy 668: if (ind != -1 &&
1.15 christos 669: _ti_find_cap(tic, &tic->strs, 's', ind) != NULL)
1.1 roy 670: continue;
671:
672: /* Encode the string to our scratch buffer */
673: buf.bufpos = 0;
674: if (encode_string(tic->name, token,
675: &buf, p, flags) == -1)
676: goto error;
1.14 roy 677: if (buf.bufpos > UINT16_MAX - 1) {
1.1 roy 678: dowarn(flags, "%s: %s: string is too long",
679: tic->name, token);
680: continue;
681: }
682: if (!VALID_STRING(buf.buf)) {
683: dowarn(flags, "%s: %s: invalid string",
684: tic->name, token);
685: continue;
686: }
687:
1.16 christos 688: if (ind == -1) {
689: if (!_ti_store_extra(tic, 1, token, 's', -1, -2,
690: buf.buf, buf.bufpos, flags))
691: goto error;
692: } else {
693: if (!_ti_encode_buf_id_count_str(&tic->strs,
694: ind, buf.buf, buf.bufpos))
1.1 roy 695: goto error;
696: }
697: continue;
698: }
699:
700: /* num cap */
701: p = strchr(token, '#');
702: if (p != NULL) {
703: *p++ = '\0';
704: /* Don't use the number if we already have it */
1.12 roy 705: ind = (short)_ti_numindex(token);
1.1 roy 706: if (ind != -1 &&
1.15 christos 707: _ti_find_cap(tic, &tic->nums, 'n', ind) != NULL)
1.1 roy 708: continue;
709:
1.5 roy 710: cnum = strtol(p, &e, 0);
1.1 roy 711: if (*e != '\0') {
712: dowarn(flags, "%s: %s: not a number",
713: tic->name, token);
714: continue;
715: }
1.14 roy 716: if (!VALID_NUMERIC(cnum) || cnum > INT32_MAX) {
717: dowarn(flags, "%s: %s: number %ld out of range",
718: tic->name, token, cnum);
1.1 roy 719: continue;
720: }
1.22 roy 721: if (cnum > INT16_MAX) {
722: if (flags & TIC_COMPAT_V1)
723: cnum = INT16_MAX;
724: else if (tic->rtype == TERMINFO_RTYPE_O1)
725: if (_ti_promote(tic) == -1)
726: goto error;
727: }
1.13 roy 728:
1.14 roy 729: num = (int)cnum;
1.16 christos 730: if (ind == -1) {
731: if (!_ti_store_extra(tic, 1, token, 'n', -1,
732: num, NULL, 0, flags))
1.1 roy 733: goto error;
1.16 christos 734: } else {
735: if (!_ti_encode_buf_id_num(&tic->nums,
736: ind, num, _ti_numsize(tic)))
737: goto error;
1.1 roy 738: }
739: continue;
740: }
741:
742: flag = 1;
743: len = strlen(token) - 1;
744: if (token[len] == '@') {
745: flag = CANCELLED_BOOLEAN;
746: token[len] = '\0';
747: }
1.12 roy 748: ind = (short)_ti_flagindex(token);
1.1 roy 749: if (ind == -1 && flag == CANCELLED_BOOLEAN) {
1.12 roy 750: if ((ind = (short)_ti_numindex(token)) != -1) {
1.15 christos 751: if (_ti_find_cap(tic, &tic->nums, 'n', ind)
752: != NULL)
1.1 roy 753: continue;
1.16 christos 754: if (!_ti_encode_buf_id_num(&tic->nums, ind,
755: CANCELLED_NUMERIC, _ti_numsize(tic)))
1.1 roy 756: goto error;
757: continue;
1.12 roy 758: } else if ((ind = (short)_ti_strindex(token)) != -1) {
1.15 christos 759: if (_ti_find_cap(tic, &tic->strs, 's', ind)
760: != NULL)
1.1 roy 761: continue;
1.16 christos 762: if (!_ti_encode_buf_id_num(
763: &tic->strs, ind, 0, sizeof(uint16_t)))
1.1 roy 764: goto error;
765: continue;
766: }
767: }
1.16 christos 768: if (ind == -1) {
769: if (!_ti_store_extra(tic, 1, token, 'f', flag, 0, NULL,
770: 0, flags))
771: goto error;
772: } else if (_ti_find_cap(tic, &tic->flags, 'f', ind) == NULL) {
1.20 christos 773: if (!_ti_encode_buf_id_flags(&tic->flags, ind, flag))
1.1 roy 774: goto error;
775: }
776: }
777:
778: free(buf.buf);
779: return tic;
780:
781: error:
782: free(buf.buf);
783: _ti_freetic(tic);
784: return NULL;
785: }
786:
787: void
788: _ti_freetic(TIC *tic)
789: {
790:
791: if (tic != NULL) {
792: free(tic->name);
793: free(tic->alias);
794: free(tic->desc);
1.7 joerg 795: free(tic->extras.buf);
1.1 roy 796: free(tic->flags.buf);
797: free(tic->nums.buf);
798: free(tic->strs.buf);
799: free(tic);
800: }
801: }
CVSweb <webmaster@jp.NetBSD.org>