1*b6924e8aSmartin /* $NetBSD: term.c,v 1.34 2020/04/05 14:53:39 martin Exp $ */
24ca00e00Sroy
34ca00e00Sroy /*
4aadfdb11Sroy * Copyright (c) 2009, 2010, 2011, 2020 The NetBSD Foundation, Inc.
54ca00e00Sroy *
64ca00e00Sroy * This code is derived from software contributed to The NetBSD Foundation
74ca00e00Sroy * by Roy Marples.
84ca00e00Sroy *
94ca00e00Sroy * Redistribution and use in source and binary forms, with or without
104ca00e00Sroy * modification, are permitted provided that the following conditions
114ca00e00Sroy * are met:
124ca00e00Sroy * 1. Redistributions of source code must retain the above copyright
134ca00e00Sroy * notice, this list of conditions and the following disclaimer.
144ca00e00Sroy * 2. Redistributions in binary form must reproduce the above copyright
154ca00e00Sroy * notice, this list of conditions and the following disclaimer in the
164ca00e00Sroy * documentation and/or other materials provided with the distribution.
174ca00e00Sroy *
184ca00e00Sroy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
194ca00e00Sroy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
204ca00e00Sroy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
214ca00e00Sroy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
224ca00e00Sroy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
234ca00e00Sroy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
244ca00e00Sroy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
254ca00e00Sroy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
264ca00e00Sroy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
274ca00e00Sroy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284ca00e00Sroy */
294ca00e00Sroy
304ca00e00Sroy #include <sys/cdefs.h>
31*b6924e8aSmartin __RCSID("$NetBSD: term.c,v 1.34 2020/04/05 14:53:39 martin Exp $");
324ca00e00Sroy
334ca00e00Sroy #include <sys/stat.h>
344ca00e00Sroy
354ca00e00Sroy #include <assert.h>
36fc67b0cdSjoerg #include <cdbr.h>
374ca00e00Sroy #include <ctype.h>
384ca00e00Sroy #include <errno.h>
394ca00e00Sroy #include <fcntl.h>
404ca00e00Sroy #include <limits.h>
414ca00e00Sroy #include <stdio.h>
424ca00e00Sroy #include <stdlib.h>
434ca00e00Sroy #include <string.h>
444ca00e00Sroy #include <term_private.h>
454ca00e00Sroy #include <term.h>
464ca00e00Sroy
47aadfdb11Sroy /*
48aadfdb11Sroy * Although we can read v1 structure (which includes v2 alias records)
49aadfdb11Sroy * we really want a v3 structure to get numerics of type int rather than short.
50aadfdb11Sroy */
513958d16aSchristos #define _PATH_TERMINFO "/usr/share/misc/terminfo"
524ca00e00Sroy
539e387da6Sroy #ifdef TERMINFO_DB
542678fcfdSroy static char __ti_database[PATH_MAX];
559e387da6Sroy #endif
564ca00e00Sroy const char *_ti_database;
574ca00e00Sroy
58420f923aSroy /* Include a generated list of pre-compiled terminfo descriptions. */
59420f923aSroy #include "compiled_terms.c"
6090cead5eSroy
614ca00e00Sroy static int
allocset(void * pp,int init,size_t nelem,size_t elemsize)62f464a786Schristos allocset(void *pp, int init, size_t nelem, size_t elemsize)
63f464a786Schristos {
64f464a786Schristos void **p = pp;
65f464a786Schristos if (*p) {
66f464a786Schristos memset(*p, init, nelem * elemsize);
67f464a786Schristos return 0;
68f464a786Schristos }
69f464a786Schristos
70f464a786Schristos if ((*p = calloc(nelem, elemsize)) == NULL)
71f464a786Schristos return -1;
72f464a786Schristos
73f464a786Schristos if (init != 0)
74f464a786Schristos memset(*p, init, nelem * elemsize);
75f464a786Schristos return 0;
76f464a786Schristos }
77f464a786Schristos
78f464a786Schristos static int
_ti_readterm(TERMINAL * term,const char * cap,size_t caplen,int flags)7990cead5eSroy _ti_readterm(TERMINAL *term, const char *cap, size_t caplen, int flags)
804ca00e00Sroy {
81aadfdb11Sroy char rtype;
824ca00e00Sroy uint16_t ind, num;
834ca00e00Sroy size_t len;
844ca00e00Sroy TERMUSERDEF *ud;
854ca00e00Sroy
86ee97ae6aSchristos if (caplen == 0)
87ee97ae6aSchristos goto out;
88aadfdb11Sroy rtype = *cap++;
89ee97ae6aSchristos caplen--;
90aadfdb11Sroy /* Only read type 1 or 3 records */
91aadfdb11Sroy if (rtype != TERMINFO_RTYPE && rtype != TERMINFO_RTYPE_O1)
92ee97ae6aSchristos goto out;
934ca00e00Sroy
94f464a786Schristos if (allocset(&term->flags, 0, TIFLAGMAX+1, sizeof(*term->flags)) == -1)
9591ab69b0Sroy return -1;
96f464a786Schristos
97f464a786Schristos if (allocset(&term->nums, -1, TINUMMAX+1, sizeof(*term->nums)) == -1)
9891ab69b0Sroy return -1;
99f464a786Schristos
100f464a786Schristos if (allocset(&term->strs, 0, TISTRMAX+1, sizeof(*term->strs)) == -1)
10191ab69b0Sroy return -1;
102f464a786Schristos
103f464a786Schristos if (term->_arealen != caplen) {
10490cead5eSroy term->_arealen = caplen;
105f464a786Schristos term->_area = realloc(term->_area, term->_arealen);
1064ca00e00Sroy if (term->_area == NULL)
10791ab69b0Sroy return -1;
108f464a786Schristos }
109f5cb16e7Schristos memcpy(term->_area, cap, term->_arealen);
1104ca00e00Sroy
1114ca00e00Sroy cap = term->_area;
1121d30fdaeSchristos len = _ti_decode_16(&cap);
1134ca00e00Sroy term->name = cap;
1144ca00e00Sroy cap += len;
1151d30fdaeSchristos len = _ti_decode_16(&cap);
116ae351fabSroy if (len == 0)
117ae351fabSroy term->_alias = NULL;
118ae351fabSroy else {
119ae351fabSroy term->_alias = cap;
120ae351fabSroy cap += len;
121ae351fabSroy }
1221d30fdaeSchristos len = _ti_decode_16(&cap);
1230c02e7a2Sroy if (len == 0)
1240c02e7a2Sroy term->desc = NULL;
1250c02e7a2Sroy else {
1264ca00e00Sroy term->desc = cap;
1274ca00e00Sroy cap += len;
1280c02e7a2Sroy }
1294ca00e00Sroy
1301d30fdaeSchristos num = _ti_decode_16(&cap);
1314ca00e00Sroy if (num != 0) {
1321d30fdaeSchristos num = _ti_decode_16(&cap);
1334ca00e00Sroy for (; num != 0; num--) {
1341d30fdaeSchristos ind = _ti_decode_16(&cap);
1354ca00e00Sroy term->flags[ind] = *cap++;
1364ca00e00Sroy if (flags == 0 && !VALID_BOOLEAN(term->flags[ind]))
1374ca00e00Sroy term->flags[ind] = 0;
1384ca00e00Sroy }
1394ca00e00Sroy }
1404ca00e00Sroy
1411d30fdaeSchristos num = _ti_decode_16(&cap);
1424ca00e00Sroy if (num != 0) {
1431d30fdaeSchristos num = _ti_decode_16(&cap);
1444ca00e00Sroy for (; num != 0; num--) {
1451d30fdaeSchristos ind = _ti_decode_16(&cap);
1461d30fdaeSchristos term->nums[ind] = _ti_decode_num(&cap, rtype);
1474ca00e00Sroy if (flags == 0 && !VALID_NUMERIC(term->nums[ind]))
1484ca00e00Sroy term->nums[ind] = ABSENT_NUMERIC;
1494ca00e00Sroy }
1504ca00e00Sroy }
1514ca00e00Sroy
1521d30fdaeSchristos num = _ti_decode_16(&cap);
1534ca00e00Sroy if (num != 0) {
1541d30fdaeSchristos num = _ti_decode_16(&cap);
1554ca00e00Sroy for (; num != 0; num--) {
1561d30fdaeSchristos ind = _ti_decode_16(&cap);
1571d30fdaeSchristos len = _ti_decode_16(&cap);
1584ca00e00Sroy if (len > 0)
1594ca00e00Sroy term->strs[ind] = cap;
1604ca00e00Sroy else if (flags == 0)
1614ca00e00Sroy term->strs[ind] = ABSENT_STRING;
1624ca00e00Sroy else
1634ca00e00Sroy term->strs[ind] = CANCELLED_STRING;
1644ca00e00Sroy cap += len;
1654ca00e00Sroy }
1664ca00e00Sroy }
1674ca00e00Sroy
1681d30fdaeSchristos num = _ti_decode_16(&cap);
1694ca00e00Sroy if (num != 0) {
1701d30fdaeSchristos num = _ti_decode_16(&cap);
171f464a786Schristos if (num != term->_nuserdefs) {
172f464a786Schristos free(term->_userdefs);
173f464a786Schristos term->_userdefs = NULL;
174f464a786Schristos term->_nuserdefs = num;
175f464a786Schristos }
176f464a786Schristos if (allocset(&term->_userdefs, 0, term->_nuserdefs,
177f464a786Schristos sizeof(*term->_userdefs)) == -1)
178f464a786Schristos return -1;
1794ca00e00Sroy for (num = 0; num < term->_nuserdefs; num++) {
1804ca00e00Sroy ud = &term->_userdefs[num];
1811d30fdaeSchristos len = _ti_decode_16(&cap);
1824ca00e00Sroy ud->id = cap;
1834ca00e00Sroy cap += len;
1844ca00e00Sroy ud->type = *cap++;
1854ca00e00Sroy switch (ud->type) {
1864ca00e00Sroy case 'f':
1874ca00e00Sroy ud->flag = *cap++;
1884ca00e00Sroy if (flags == 0 &&
1894ca00e00Sroy !VALID_BOOLEAN(ud->flag))
1904ca00e00Sroy ud->flag = 0;
1914ca00e00Sroy ud->num = ABSENT_NUMERIC;
1924ca00e00Sroy ud->str = ABSENT_STRING;
1934ca00e00Sroy break;
1944ca00e00Sroy case 'n':
1954ca00e00Sroy ud->flag = ABSENT_BOOLEAN;
1961d30fdaeSchristos ud->num = _ti_decode_num(&cap, rtype);
1974ca00e00Sroy if (flags == 0 &&
1984ca00e00Sroy !VALID_NUMERIC(ud->num))
1994ca00e00Sroy ud->num = ABSENT_NUMERIC;
2004ca00e00Sroy ud->str = ABSENT_STRING;
2014ca00e00Sroy break;
2024ca00e00Sroy case 's':
2034ca00e00Sroy ud->flag = ABSENT_BOOLEAN;
2044ca00e00Sroy ud->num = ABSENT_NUMERIC;
2051d30fdaeSchristos len = _ti_decode_16(&cap);
2064ca00e00Sroy if (len > 0)
2074ca00e00Sroy ud->str = cap;
2084ca00e00Sroy else if (flags == 0)
2094ca00e00Sroy ud->str = ABSENT_STRING;
2104ca00e00Sroy else
2114ca00e00Sroy ud->str = CANCELLED_STRING;
2124ca00e00Sroy cap += len;
2134ca00e00Sroy break;
2144ca00e00Sroy default:
215ee97ae6aSchristos goto out;
2164ca00e00Sroy }
2174ca00e00Sroy }
218f464a786Schristos } else {
219f464a786Schristos term->_nuserdefs = 0;
220f464a786Schristos if (term->_userdefs) {
221f464a786Schristos free(term->_userdefs);
222f464a786Schristos term->_userdefs = NULL;
2234ca00e00Sroy }
224f464a786Schristos }
225f464a786Schristos
2264ca00e00Sroy return 1;
227ee97ae6aSchristos out:
228ee97ae6aSchristos errno = EINVAL;
229ee97ae6aSchristos return -1;
2304ca00e00Sroy }
2314ca00e00Sroy
2329e387da6Sroy #if defined(TERMINFO_DB) || defined(TERMINFO_COMPILE)
2334ca00e00Sroy static int
_ti_checkname(const char * name,const char * termname,const char * termalias)2348e374e1bSroy _ti_checkname(const char *name, const char *termname, const char *termalias)
2352b9f5c3fSroy {
2368e374e1bSroy const char *alias, *s;
2378e374e1bSroy size_t len, l;
2382b9f5c3fSroy
2392b9f5c3fSroy /* Check terminal name matches. */
2408e374e1bSroy if (strcmp(termname, name) == 0)
2412b9f5c3fSroy return 1;
2422b9f5c3fSroy
2432b9f5c3fSroy /* Check terminal aliases match. */
2448e374e1bSroy if (termalias == NULL)
2458e374e1bSroy return 0;
2468e374e1bSroy
2478e374e1bSroy len = strlen(name);
2488e374e1bSroy alias = termalias;
2498e374e1bSroy while (*alias != '\0') {
2508e374e1bSroy s = strchr(alias, '|');
2518e374e1bSroy if (s == NULL)
2528e374e1bSroy l = strlen(alias);
2538e374e1bSroy else
2548e374e1bSroy l = (size_t)(s - alias);
2558e374e1bSroy if (len == l && memcmp(alias, name, l) == 0)
2562b9f5c3fSroy return 1;
2578e374e1bSroy if (s == NULL)
2588e374e1bSroy break;
2598e374e1bSroy alias = s + 1;
2602b9f5c3fSroy }
2612b9f5c3fSroy
2622b9f5c3fSroy /* No match. */
2632b9f5c3fSroy return 0;
2642b9f5c3fSroy }
2659e387da6Sroy #endif
2662b9f5c3fSroy
2679e387da6Sroy #ifdef TERMINFO_DB
2682b9f5c3fSroy static int
_ti_dbgetterm(TERMINAL * term,const char * path,const char * name,int flags)2694ca00e00Sroy _ti_dbgetterm(TERMINAL *term, const char *path, const char *name, int flags)
2704ca00e00Sroy {
271fc67b0cdSjoerg struct cdbr *db;
272fc67b0cdSjoerg const void *data;
273fc67b0cdSjoerg const uint8_t *data8;
274fc67b0cdSjoerg size_t len, klen;
2754ca00e00Sroy int r;
2764ca00e00Sroy
2777b8fbc2dSroy r = snprintf(__ti_database, sizeof(__ti_database), "%s.cdb", path);
2787b8fbc2dSroy if (r < 0 || (size_t)r > sizeof(__ti_database)) {
2797b8fbc2dSroy db = NULL;
2807b8fbc2dSroy errno = ENOENT; /* To fall back to a non extension. */
2817b8fbc2dSroy } else
2822678fcfdSroy db = cdbr_open(__ti_database, CDBR_DEFAULT);
2837b8fbc2dSroy
2847b8fbc2dSroy /* Target file *may* be a cdb file without the extension. */
2857b8fbc2dSroy if (db == NULL && errno == ENOENT) {
2867b8fbc2dSroy len = strlcpy(__ti_database, path, sizeof(__ti_database));
2877b8fbc2dSroy if (len < sizeof(__ti_database))
2887b8fbc2dSroy db = cdbr_open(__ti_database, CDBR_DEFAULT);
2897b8fbc2dSroy }
2904ca00e00Sroy if (db == NULL)
2914ca00e00Sroy return -1;
292fc67b0cdSjoerg
2932b9f5c3fSroy r = 0;
294fc67b0cdSjoerg klen = strlen(name) + 1;
295fc67b0cdSjoerg if (cdbr_find(db, name, klen, &data, &len) == -1)
2962b9f5c3fSroy goto out;
297fc67b0cdSjoerg data8 = data;
298fc67b0cdSjoerg if (len == 0)
2992b9f5c3fSroy goto out;
300fc67b0cdSjoerg
3012b9f5c3fSroy /* If the entry is an alias, load the indexed terminfo description. */
3023958d16aSchristos if (data8[0] == TERMINFO_ALIAS) {
3032b9f5c3fSroy if (cdbr_get(db, le32dec(data8 + 1), &data, &len))
3042b9f5c3fSroy goto out;
3052b9f5c3fSroy data8 = data;
3062b9f5c3fSroy }
3074ca00e00Sroy
308fc67b0cdSjoerg r = _ti_readterm(term, data, len, flags);
3092b9f5c3fSroy /* Ensure that this is the right terminfo description. */
3102b9f5c3fSroy if (r == 1)
3118e374e1bSroy r = _ti_checkname(name, term->name, term->_alias);
3122b9f5c3fSroy /* Remember the database we read. */
3132b9f5c3fSroy if (r == 1)
3142b9f5c3fSroy _ti_database = __ti_database;
3152b9f5c3fSroy
3162b9f5c3fSroy out:
317fc67b0cdSjoerg cdbr_close(db);
3184ca00e00Sroy return r;
3194ca00e00Sroy }
3204ca00e00Sroy
3214ca00e00Sroy static int
_ti_dbgettermp(TERMINAL * term,const char * path,const char * name,int flags)3224ca00e00Sroy _ti_dbgettermp(TERMINAL *term, const char *path, const char *name, int flags)
3234ca00e00Sroy {
3244ca00e00Sroy const char *p;
3253edb4adcSroy char pathbuf[PATH_MAX];
3264ca00e00Sroy size_t l;
3274ca00e00Sroy int r, e;
3284ca00e00Sroy
3294ca00e00Sroy e = -1;
3304ca00e00Sroy r = 0;
3314ca00e00Sroy do {
3324ca00e00Sroy for (p = path; *path != '\0' && *path != ':'; path++)
3334ca00e00Sroy continue;
33404f58b48Sroy l = (size_t)(path - p);
3354ca00e00Sroy if (l != 0 && l + 1 < sizeof(pathbuf)) {
3364ca00e00Sroy memcpy(pathbuf, p, l);
3374ca00e00Sroy pathbuf[l] = '\0';
3384ca00e00Sroy r = _ti_dbgetterm(term, pathbuf, name, flags);
3394ca00e00Sroy if (r == 1)
3404ca00e00Sroy return 1;
3414ca00e00Sroy if (r == 0)
3424ca00e00Sroy e = 0;
3434ca00e00Sroy }
3444ca00e00Sroy } while (*path++ == ':');
3454ca00e00Sroy return e;
3464ca00e00Sroy }
3479e387da6Sroy #endif
3484ca00e00Sroy
349b32b792eSroy static int
_ti_findterm(TERMINAL * term,const char * name,int flags)350b32b792eSroy _ti_findterm(TERMINAL *term, const char *name, int flags)
3514ca00e00Sroy {
352*b6924e8aSmartin #ifndef TERMINFO_DB
353*b6924e8aSmartin _ti_database = NULL;
354*b6924e8aSmartin
355*b6924e8aSmartin return 0;
356*b6924e8aSmartin #else
3574ca00e00Sroy int r;
3582e0a9a1dSroy char *c, *e;
3594ca00e00Sroy
3604ca00e00Sroy _DIAGASSERT(term != NULL);
3614ca00e00Sroy _DIAGASSERT(name != NULL);
3624ca00e00Sroy
3634ca00e00Sroy _ti_database = NULL;
364fde317d2Sroy r = 0;
36590cead5eSroy
3669e387da6Sroy e = getenv("TERMINFO");
3679e387da6Sroy if (e != NULL && *e == '/')
3684ca00e00Sroy return _ti_dbgetterm(term, e, name, flags);
369007ba6f7Sroy
370007ba6f7Sroy c = NULL;
3719e387da6Sroy #ifdef TERMINFO_COMPILE
372007ba6f7Sroy if (e == NULL && (c = getenv("TERMCAP")) != NULL) {
373007ba6f7Sroy if (*c != '\0' && *c != '/') {
374007ba6f7Sroy c = strdup(c);
375007ba6f7Sroy if (c != NULL) {
376007ba6f7Sroy e = captoinfo(c);
377fde317d2Sroy free(c);
378007ba6f7Sroy }
379007ba6f7Sroy }
380007ba6f7Sroy }
381007ba6f7Sroy
382007ba6f7Sroy if (e != NULL) {
3832e0a9a1dSroy TIC *tic;
3842e0a9a1dSroy
385007ba6f7Sroy if (c == NULL)
386007ba6f7Sroy e = strdup(e); /* So we don't destroy env */
387007ba6f7Sroy if (e == NULL)
388007ba6f7Sroy tic = NULL;
389f464a786Schristos else {
390007ba6f7Sroy tic = _ti_compile(e, TIC_WARNING |
391007ba6f7Sroy TIC_ALIAS | TIC_DESCRIPTION | TIC_EXTRA);
392007ba6f7Sroy free(e);
393f464a786Schristos }
3948e374e1bSroy if (tic != NULL &&
3958e374e1bSroy _ti_checkname(name, tic->name, tic->alias) == 1)
3968e374e1bSroy {
3972e0a9a1dSroy uint8_t *f;
3982e0a9a1dSroy ssize_t len;
3992e0a9a1dSroy
400fde317d2Sroy len = _ti_flatten(&f, tic);
401fde317d2Sroy if (len != -1) {
402ed684e08Sroy r = _ti_readterm(term, (char *)f, (size_t)len,
403ed684e08Sroy flags);
404fde317d2Sroy free(f);
405fde317d2Sroy }
406fde317d2Sroy }
407fde317d2Sroy _ti_freetic(tic);
408fde317d2Sroy if (r == 1) {
409007ba6f7Sroy if (c == NULL)
410fde317d2Sroy _ti_database = "$TERMINFO";
411007ba6f7Sroy else
412007ba6f7Sroy _ti_database = "$TERMCAP";
413fde317d2Sroy return r;
414fde317d2Sroy }
4154ca00e00Sroy }
4164ca00e00Sroy
417b32b792eSroy if ((e = getenv("TERMINFO_DIRS")) != NULL)
418b32b792eSroy return _ti_dbgettermp(term, e, name, flags);
419b32b792eSroy
420b32b792eSroy if ((e = getenv("HOME")) != NULL) {
4212e0a9a1dSroy char homepath[PATH_MAX];
4222e0a9a1dSroy
4232e0a9a1dSroy if (snprintf(homepath, sizeof(homepath), "%s/.terminfo", e) > 0)
4242e0a9a1dSroy r = _ti_dbgetterm(term, homepath, name, flags);
425b32b792eSroy }
426b32b792eSroy if (r != 1)
427b32b792eSroy r = _ti_dbgettermp(term, _PATH_TERMINFO, name, flags);
4289e387da6Sroy #endif
429b32b792eSroy
430b32b792eSroy return r;
431*b6924e8aSmartin #endif
432b32b792eSroy }
433b32b792eSroy
434b32b792eSroy int
_ti_getterm(TERMINAL * term,const char * name,int flags)435b32b792eSroy _ti_getterm(TERMINAL *term, const char *name, int flags)
436b32b792eSroy {
437b32b792eSroy int r;
438b32b792eSroy size_t i;
439b32b792eSroy const struct compiled_term *t;
4409e387da6Sroy #ifdef TERMINFO_COMPAT
4413958d16aSchristos char *namev3;
4423958d16aSchristos
4433958d16aSchristos namev3 = _ti_getname(TERMINFO_RTYPE, name);
4443958d16aSchristos if (namev3 != NULL) {
4453958d16aSchristos r = _ti_findterm(term, namev3, flags);
4463958d16aSchristos free(namev3);
4473958d16aSchristos if (r == 1)
4483958d16aSchristos return r;
4493958d16aSchristos }
4509e387da6Sroy #endif
451b32b792eSroy
452b32b792eSroy r = _ti_findterm(term, name, flags);
453298c3fd5Sroy if (r == 1)
454fde317d2Sroy return r;
455298c3fd5Sroy
456a2e27dcdSroy for (i = 0; i < __arraycount(compiled_terms); i++) {
457a2e27dcdSroy t = &compiled_terms[i];
458a2e27dcdSroy if (strcmp(name, t->name) == 0) {
459a2e27dcdSroy r = _ti_readterm(term, t->cap, t->caplen, flags);
46090cead5eSroy break;
46190cead5eSroy }
462a2e27dcdSroy }
46390cead5eSroy
464298c3fd5Sroy return r;
4654ca00e00Sroy }
466