/* $NetBSD: compile.c,v 1.26 2020/06/21 15:05:23 roy Exp $ */
/*
* Copyright (c) 2009, 2010, 2011, 2020 The NetBSD Foundation, Inc.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Roy Marples.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
cap = tbuf->buf;
for (n = tbuf->entries; n > 0; n--) {
num = _ti_decode_16(&cap);
if ((short)num == ind)
return cap;
switch (type) {
case 'f':
cap++;
break;
case 'n':
cap += _ti_numsize(tic);
break;
case 's':
num = _ti_decode_16(&cap);
cap += num;
break;
}
}
cap = tbuf->buf;
for (n = tbuf->entries; n > 0; n--) {
num = _ti_decode_16(&cap);
if (strcmp(cap, code) == 0)
return cap + num;
cap += num;
switch (*cap++) {
case 'f':
cap++;
break;
case 'n':
cap += _ti_numsize(tic);
break;
case 's':
num = _ti_decode_16(&cap);
cap += num;
break;
}
}
/* str cap */
p = strchr(token, '=');
if (p != NULL) {
*p++ = '\0';
/* Don't use the string if we already have it */
ind = (short)_ti_strindex(token);
if (ind != -1 &&
_ti_find_cap(tic, &tic->strs, 's', ind) != NULL)
continue;
/* Encode the string to our scratch buffer */
buf.bufpos = 0;
if (encode_string(tic->name, token,
&buf, p, flags) == -1)
goto error;
if (buf.bufpos > UINT16_MAX - 1) {
dowarn(flags, "%s: %s: string is too long",
tic->name, token);
continue;
}
if (!VALID_STRING(buf.buf)) {
dowarn(flags, "%s: %s: invalid string",
tic->name, token);
continue;
}
if (ind == -1) {
if (!_ti_store_extra(tic, 1, token, 's', -1, -2,
buf.buf, buf.bufpos, flags))
goto error;
} else {
if (!_ti_encode_buf_id_count_str(&tic->strs,
ind, buf.buf, buf.bufpos))
goto error;
}
continue;
}
/* num cap */
p = strchr(token, '#');
if (p != NULL) {
*p++ = '\0';
/* Don't use the number if we already have it */
ind = (short)_ti_numindex(token);
if (ind != -1 &&
_ti_find_cap(tic, &tic->nums, 'n', ind) != NULL)
continue;
cnum = strtol(p, &e, 0);
if (*e != '\0') {
dowarn(flags, "%s: %s: not a number",
tic->name, token);
continue;
}
if (!VALID_NUMERIC(cnum) || cnum > INT32_MAX) {
dowarn(flags, "%s: %s: number %ld out of range",
tic->name, token, cnum);
continue;
}
if (cnum > INT16_MAX) {
if (flags & TIC_COMPAT_V1)
cnum = INT16_MAX;
else if (tic->rtype == TERMINFO_RTYPE_O1)
if (_ti_promote(tic) == -1)
goto error;
}
num = (int)cnum;
if (ind == -1) {
if (!_ti_store_extra(tic, 1, token, 'n', -1,
num, NULL, 0, flags))
goto error;
} else {
if (!_ti_encode_buf_id_num(&tic->nums,
ind, num, _ti_numsize(tic)))
goto error;
}
continue;
}
flag = 1;
len = strlen(token) - 1;
if (token[len] == '@') {
flag = CANCELLED_BOOLEAN;
token[len] = '\0';
}
ind = (short)_ti_flagindex(token);
if (ind == -1 && flag == CANCELLED_BOOLEAN) {
if ((ind = (short)_ti_numindex(token)) != -1) {
if (_ti_find_cap(tic, &tic->nums, 'n', ind)
!= NULL)
continue;
if (!_ti_encode_buf_id_num(&tic->nums, ind,
CANCELLED_NUMERIC, _ti_numsize(tic)))
goto error;
continue;
} else if ((ind = (short)_ti_strindex(token)) != -1) {
if (_ti_find_cap(tic, &tic->strs, 's', ind)
!= NULL)
continue;
if (!_ti_encode_buf_id_num(
&tic->strs, ind, 0, sizeof(uint16_t)))
goto error;
continue;
}
}
if (ind == -1) {
if (!_ti_store_extra(tic, 1, token, 'f', flag, 0, NULL,
0, flags))
goto error;
} else if (_ti_find_cap(tic, &tic->flags, 'f', ind) == NULL) {
if (!_ti_encode_buf_id_flags(&tic->flags, ind, flag))
goto error;
}
}