1 /* $NetBSD: compile.c,v 1.9 2013/06/07 13:16:18 roy Exp $ */
4 * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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.
30 #if HAVE_NBTOOL_CONFIG_H
31 #include "nbtool_config.h"
34 #include <sys/cdefs.h>
35 __RCSID("$NetBSD: compile.c,v 1.9 2013/06/07 13:16:18 roy Exp $");
37 #if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H
38 #include <sys/endian.h>
51 #include <term_private.h>
54 static void __printflike(2, 3)
55 dowarn(int flags
, const char *fmt
, ...)
60 if (flags
& TIC_WARNING
) {
68 _ti_grow_tbuf(TBUF
*tbuf
, size_t len
)
73 _DIAGASSERT(tbuf
!= NULL
);
75 l
= tbuf
->bufpos
+ len
;
76 if (l
> tbuf
->buflen
) {
77 if (tbuf
->buflen
== 0)
80 buf
= realloc(tbuf
->buf
, l
);
90 _ti_find_cap(TBUF
*tbuf
, char type
, short ind
)
96 _DIAGASSERT(tbuf
!= NULL
);
99 for (n
= tbuf
->entries
; n
> 0; n
--) {
101 cap
+= sizeof(uint16_t);
109 cap
+= sizeof(uint16_t);
113 cap
+= sizeof(uint16_t);
124 _ti_find_extra(TBUF
*tbuf
, const char *code
)
130 _DIAGASSERT(tbuf
!= NULL
);
131 _DIAGASSERT(code
!= NULL
);
134 for (n
= tbuf
->entries
; n
> 0; n
--) {
136 cap
+= sizeof(uint16_t);
137 if (strcmp(cap
, code
) == 0)
145 cap
+= sizeof(uint16_t);
149 cap
+= sizeof(uint16_t);
160 _ti_store_extra(TIC
*tic
, int wrn
, char *id
, char type
, char flag
, short num
,
161 char *str
, size_t strl
, int flags
)
165 _DIAGASSERT(tic
!= NULL
);
167 if (strcmp(id
, "use") != 0) {
168 if (_ti_find_extra(&tic
->extras
, id
) != NULL
)
170 if (!(flags
& TIC_EXTRA
)) {
172 dowarn(flags
, "%s: %s: unknown capability",
179 if (l
> UINT16_T_MAX
) {
180 dowarn(flags
, "%s: %s: cap name is too long", tic
->name
, id
);
184 if (!_ti_grow_tbuf(&tic
->extras
,
185 l
+ strl
+ (sizeof(uint16_t) * 2) + 1))
187 le16enc(tic
->extras
.buf
+ tic
->extras
.bufpos
, l
);
188 tic
->extras
.bufpos
+= sizeof(uint16_t);
189 memcpy(tic
->extras
.buf
+ tic
->extras
.bufpos
, id
, l
);
190 tic
->extras
.bufpos
+= l
;
191 tic
->extras
.buf
[tic
->extras
.bufpos
++] = type
;
194 tic
->extras
.buf
[tic
->extras
.bufpos
++] = flag
;
197 le16enc(tic
->extras
.buf
+ tic
->extras
.bufpos
, num
);
198 tic
->extras
.bufpos
+= sizeof(uint16_t);
201 le16enc(tic
->extras
.buf
+ tic
->extras
.bufpos
, strl
);
202 tic
->extras
.bufpos
+= sizeof(uint16_t);
203 memcpy(tic
->extras
.buf
+ tic
->extras
.bufpos
, str
, strl
);
204 tic
->extras
.bufpos
+= strl
;
207 tic
->extras
.entries
++;
212 _ti_flatten(uint8_t **buf
, const TIC
*tic
)
214 size_t buflen
, len
, alen
, dlen
;
217 _DIAGASSERT(buf
!= NULL
);
218 _DIAGASSERT(tic
!= NULL
);
220 len
= strlen(tic
->name
) + 1;
221 if (tic
->alias
== NULL
)
224 alen
= strlen(tic
->alias
) + 1;
225 if (tic
->desc
== NULL
)
228 dlen
= strlen(tic
->desc
) + 1;
229 buflen
= sizeof(char) +
230 sizeof(uint16_t) + len
+
231 sizeof(uint16_t) + alen
+
232 sizeof(uint16_t) + dlen
+
233 (sizeof(uint16_t) * 2) + tic
->flags
.bufpos
+
234 (sizeof(uint16_t) * 2) + tic
->nums
.bufpos
+
235 (sizeof(uint16_t) * 2) + tic
->strs
.bufpos
+
236 (sizeof(uint16_t) * 2) + tic
->extras
.bufpos
;
237 *buf
= malloc(buflen
);
244 cap
+= sizeof(uint16_t);
245 memcpy(cap
, tic
->name
, len
);
249 cap
+= sizeof(uint16_t);
250 if (tic
->alias
!= NULL
) {
251 memcpy(cap
, tic
->alias
, alen
);
255 cap
+= sizeof(uint16_t);
256 if (tic
->desc
!= NULL
) {
257 memcpy(cap
, tic
->desc
, dlen
);
261 if (tic
->flags
.entries
== 0) {
263 cap
+= sizeof(uint16_t);
265 le16enc(cap
, (tic
->flags
.bufpos
+ sizeof(uint16_t)));
266 cap
+= sizeof(uint16_t);
267 le16enc(cap
, tic
->flags
.entries
);
268 cap
+= sizeof(uint16_t);
269 memcpy(cap
, tic
->flags
.buf
, tic
->flags
.bufpos
);
270 cap
+= tic
->flags
.bufpos
;
273 if (tic
->nums
.entries
== 0) {
275 cap
+= sizeof(uint16_t);
277 le16enc(cap
, (tic
->nums
.bufpos
+ sizeof(uint16_t)));
278 cap
+= sizeof(uint16_t);
279 le16enc(cap
, tic
->nums
.entries
);
280 cap
+= sizeof(uint16_t);
281 memcpy(cap
, tic
->nums
.buf
, tic
->nums
.bufpos
);
282 cap
+= tic
->nums
.bufpos
;
285 if (tic
->strs
.entries
== 0) {
287 cap
+= sizeof(uint16_t);
289 le16enc(cap
, (tic
->strs
.bufpos
+ sizeof(uint16_t)));
290 cap
+= sizeof(uint16_t);
291 le16enc(cap
, tic
->strs
.entries
);
292 cap
+= sizeof(uint16_t);
293 memcpy(cap
, tic
->strs
.buf
, tic
->strs
.bufpos
);
294 cap
+= tic
->strs
.bufpos
;
297 if (tic
->extras
.entries
== 0) {
299 cap
+= sizeof(uint16_t);
301 le16enc(cap
, (tic
->extras
.bufpos
+ sizeof(uint16_t)));
302 cap
+= sizeof(uint16_t);
303 le16enc(cap
, tic
->extras
.entries
);
304 cap
+= sizeof(uint16_t);
305 memcpy(cap
, tic
->extras
.buf
, tic
->extras
.bufpos
);
306 cap
+= tic
->extras
.bufpos
;
313 encode_string(const char *term
, const char *cap
, TBUF
*tbuf
, const char *str
,
317 char ch
, *p
, *s
, last
;
319 if (_ti_grow_tbuf(tbuf
, strlen(str
) + 1) == NULL
)
321 p
= s
= tbuf
->buf
+ tbuf
->bufpos
;
324 /* Convert escape codes */
325 while ((ch
= *str
++) != '\0') {
326 if (slash
== 0 && ch
== '\\') {
331 if (last
!= '%' && ch
== '^') {
333 if (((unsigned char)ch
) >= 128)
335 "%s: %s: illegal ^ character",
341 else if ((ch
&= 037) == 0)
349 if (ch
>= '0' && ch
<= '7') {
351 for (i
= 0; i
< 2; i
++) {
352 if (*str
< '0' || *str
> '7') {
353 if (isdigit((unsigned char)*str
))
356 " digit", term
, cap
);
360 num
= num
* 8 + *str
++ - '0';
374 case 'e': /* FALLTHROUGH */
381 case 'l': /* FALLTHROUGH */
395 /* We should warn here */
406 tbuf
->bufpos
+= p
- s
;
411 _ti_get_token(char **cap
, char sep
)
415 while (isspace((unsigned char)**cap
))
420 /* We can't use stresep(3) as ^ we need two escape chars */
423 **cap
!= '\0' && (esc
!= '\0' || **cap
!= sep
);
427 if (**cap
== '\\' || **cap
== '^')
430 /* termcap /E/ is valid */
431 if (sep
== ':' && esc
== '\\' && **cap
== 'E')
445 _ti_compile(char *cap
, int flags
)
447 char *token
, *p
, *e
, *name
, *desc
, *alias
;
456 _DIAGASSERT(cap
!= NULL
);
458 name
= _ti_get_token(&cap
, ',');
460 dowarn(flags
, "no seperator found: %s", cap
);
463 desc
= strrchr(name
, '|');
466 alias
= strchr(name
, '|');
470 tic
= calloc(sizeof(*tic
), 1);
477 tic
->name
= strdup(name
);
478 if (tic
->name
== NULL
)
480 if (alias
!= NULL
&& flags
& TIC_ALIAS
) {
481 tic
->alias
= strdup(alias
);
482 if (tic
->alias
== NULL
)
485 if (desc
!= NULL
&& flags
& TIC_DESCRIPTION
) {
486 tic
->desc
= strdup(desc
);
487 if (tic
->desc
== NULL
)
491 for (token
= _ti_get_token(&cap
, ',');
492 token
!= NULL
&& *token
!= '\0';
493 token
= _ti_get_token(&cap
, ','))
495 /* Skip commented caps */
496 if (!(flags
& TIC_COMMENT
) && token
[0] == '.')
499 /* Obsolete entries */
500 if (token
[0] == 'O' && token
[1] == 'T') {
501 if (!(flags
& TIC_EXTRA
))
507 p
= strchr(token
, '=');
510 /* Don't use the string if we already have it */
511 ind
= _ti_strindex(token
);
513 _ti_find_cap(&tic
->strs
, 's', ind
) != NULL
)
516 /* Encode the string to our scratch buffer */
518 if (encode_string(tic
->name
, token
,
519 &buf
, p
, flags
) == -1)
521 if (buf
.bufpos
> UINT16_T_MAX
) {
522 dowarn(flags
, "%s: %s: string is too long",
526 if (!VALID_STRING(buf
.buf
)) {
527 dowarn(flags
, "%s: %s: invalid string",
533 _ti_store_extra(tic
, 1, token
, 's', -1, -2,
534 buf
.buf
, buf
.bufpos
, flags
);
536 if (!_ti_grow_tbuf(&tic
->strs
,
537 (sizeof(uint16_t) * 2) + buf
.bufpos
))
539 le16enc(tic
->strs
.buf
+ tic
->strs
.bufpos
, ind
);
540 tic
->strs
.bufpos
+= sizeof(uint16_t);
541 le16enc(tic
->strs
.buf
+ tic
->strs
.bufpos
,
543 tic
->strs
.bufpos
+= sizeof(uint16_t);
544 memcpy(tic
->strs
.buf
+ tic
->strs
.bufpos
,
545 buf
.buf
, buf
.bufpos
);
546 tic
->strs
.bufpos
+= buf
.bufpos
;
553 p
= strchr(token
, '#');
556 /* Don't use the number if we already have it */
557 ind
= _ti_numindex(token
);
559 _ti_find_cap(&tic
->nums
, 'n', ind
) != NULL
)
562 cnum
= strtol(p
, &e
, 0);
564 dowarn(flags
, "%s: %s: not a number",
568 if (!VALID_NUMERIC(cnum
)) {
569 dowarn(flags
, "%s: %s: number out of range",
575 _ti_store_extra(tic
, 1, token
, 'n', -1,
576 num
, NULL
, 0, flags
);
578 if (_ti_grow_tbuf(&tic
->nums
,
579 sizeof(uint16_t) * 2) == NULL
)
581 le16enc(tic
->nums
.buf
+ tic
->nums
.bufpos
, ind
);
582 tic
->nums
.bufpos
+= sizeof(uint16_t);
583 le16enc(tic
->nums
.buf
+ tic
->nums
.bufpos
, num
);
584 tic
->nums
.bufpos
+= sizeof(uint16_t);
591 len
= strlen(token
) - 1;
592 if (token
[len
] == '@') {
593 flag
= CANCELLED_BOOLEAN
;
596 ind
= _ti_flagindex(token
);
597 if (ind
== -1 && flag
== CANCELLED_BOOLEAN
) {
598 if ((ind
= _ti_numindex(token
)) != -1) {
599 if (_ti_find_cap(&tic
->nums
, 'n', ind
) != NULL
)
601 if (_ti_grow_tbuf(&tic
->nums
,
602 sizeof(uint16_t) * 2) == NULL
)
604 le16enc(tic
->nums
.buf
+ tic
->nums
.bufpos
, ind
);
605 tic
->nums
.bufpos
+= sizeof(uint16_t);
606 le16enc(tic
->nums
.buf
+ tic
->nums
.bufpos
,
607 (uint16_t)CANCELLED_NUMERIC
);
608 tic
->nums
.bufpos
+= sizeof(uint16_t);
611 } else if ((ind
= _ti_strindex(token
)) != -1) {
612 if (_ti_find_cap(&tic
->strs
, 's', ind
) != NULL
)
614 if (_ti_grow_tbuf(&tic
->strs
,
615 (sizeof(uint16_t) * 2) + 1) == NULL
)
617 le16enc(tic
->strs
.buf
+ tic
->strs
.bufpos
, ind
);
618 tic
->strs
.bufpos
+= sizeof(uint16_t);
619 le16enc(tic
->strs
.buf
+ tic
->strs
.bufpos
, 0);
620 tic
->strs
.bufpos
+= sizeof(uint16_t);
626 _ti_store_extra(tic
, 1, token
, 'f', flag
, 0, NULL
, 0,
628 else if (_ti_find_cap(&tic
->flags
, 'f', ind
) == NULL
) {
629 if (_ti_grow_tbuf(&tic
->flags
, sizeof(uint16_t) + 1)
632 le16enc(tic
->flags
.buf
+ tic
->flags
.bufpos
, ind
);
633 tic
->flags
.bufpos
+= sizeof(uint16_t);
634 tic
->flags
.buf
[tic
->flags
.bufpos
++] = flag
;
635 tic
->flags
.entries
++;
649 _ti_freetic(TIC
*tic
)
656 free(tic
->extras
.buf
);
657 free(tic
->flags
.buf
);