[BACK]Return to compile.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libterminfo

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>