version 1.20, 2017/05/11 19:13:17 |
version 1.21, 2023/10/17 09:52:10 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
|
|
/**************************************************************************** |
/**************************************************************************** |
* Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * |
* Copyright 2018-2022,2023 Thomas E. Dickey * |
|
* Copyright 1998-2016,2017 Free Software Foundation, Inc. * |
* * |
* * |
* Permission is hereby granted, free of charge, to any person obtaining a * |
* Permission is hereby granted, free of charge, to any person obtaining a * |
* copy of this software and associated documentation files (the * |
* copy of this software and associated documentation files (the * |
|
|
#define __INTERNAL_CAPS_VISIBLE |
#define __INTERNAL_CAPS_VISIBLE |
#include <progs.priv.h> |
#include <progs.priv.h> |
|
|
#include "dump_entry.h" |
#include <dump_entry.h> |
#include "termsort.c" /* this C file is generated */ |
#include <termsort.h> /* this C file is generated */ |
#include <parametrized.h> /* so is this */ |
#include <parametrized.h> /* so is this */ |
|
|
MODULE_ID("$Id$") |
MODULE_ID("$Id$") |
|
|
#define INDENT 8 |
|
#define DISCARD(string) string = ABSENT_STRING |
#define DISCARD(string) string = ABSENT_STRING |
#define PRINTF (void) printf |
#define PRINTF (void) printf |
|
#define WRAPPED 32 |
|
|
#define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array)) |
#define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array)) |
|
#define TcOutput() (outform == F_TERMCAP || outform == F_TCONVERR) |
|
|
typedef struct { |
typedef struct { |
char *text; |
char *text; |
|
|
static int outform; /* output format to use */ |
static int outform; /* output format to use */ |
static int sortmode; /* sort mode to use */ |
static int sortmode; /* sort mode to use */ |
static int width = 60; /* max line width for listings */ |
static int width = 60; /* max line width for listings */ |
|
static int height = 65535; /* max number of lines for listings */ |
static int column; /* current column, limited by 'width' */ |
static int column; /* current column, limited by 'width' */ |
static int oldcol; /* last value of column before wrap */ |
static int oldcol; /* last value of column before wrap */ |
static bool pretty; /* true if we format if-then-else strings */ |
static bool pretty; /* true if we format if-then-else strings */ |
|
static bool wrapped; /* true if we wrap too-long strings */ |
|
static bool did_wrap; /* true if last wrap_concat did wrapping */ |
|
static bool checking; /* true if we are checking for tic */ |
|
static int quickdump; /* true if we are dumping compiled data */ |
|
|
static char *save_sgr; |
static char *save_sgr; |
|
|
|
|
static NCURSES_CONST char *const *num_names; |
static NCURSES_CONST char *const *num_names; |
static NCURSES_CONST char *const *str_names; |
static NCURSES_CONST char *const *str_names; |
|
|
static const char *separator, *trailer; |
static const char *separator = "", *trailer = ""; |
|
static int indent = 8; |
|
|
/* cover various ports and variants of terminfo */ |
/* cover various ports and variants of terminfo */ |
#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ |
#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ |
#define V_SVR1 1 /* SVR1, Ultrix */ |
#define V_SVR1 1 /* SVR1, Ultrix */ |
#define V_HPUX 2 /* HP/UX */ |
#define V_HPUX 2 /* HP-UX */ |
#define V_AIX 3 /* AIX */ |
#define V_AIX 3 /* AIX */ |
#define V_BSD 4 /* BSD */ |
#define V_BSD 4 /* BSD */ |
|
|
|
|
#define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') |
#define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') |
#endif |
#endif |
|
|
#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n)) |
#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && (sortmode != S_VARIABLE) && OBSOLETE(n)) |
|
|
#if NCURSES_XNAMES |
#if NCURSES_XNAMES |
#define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) |
#define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) |
|
|
#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) |
#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) |
#endif |
#endif |
|
|
|
static GCC_NORETURN void |
|
failed(const char *s) |
|
{ |
|
perror(s); |
|
ExitProgram(EXIT_FAILURE); |
|
} |
|
|
static void |
static void |
strncpy_DYN(DYNBUF * dst, const char *src, size_t need) |
strncpy_DYN(DYNBUF * dst, const char *src, size_t need) |
{ |
{ |
|
|
if (want > dst->size) { |
if (want > dst->size) { |
dst->size += (want + 1024); /* be generous */ |
dst->size += (want + 1024); /* be generous */ |
dst->text = typeRealloc(char, dst->size, dst->text); |
dst->text = typeRealloc(char, dst->size, dst->text); |
|
if (dst->text == 0) |
|
failed("strncpy_DYN"); |
} |
} |
(void) strncpy(dst->text + dst->used, src, need); |
_nc_STRNCPY(dst->text + dst->used, src, need + 1); |
dst->used += need; |
dst->used += need; |
dst->text[dst->used] = 0; |
dst->text[dst->used] = 0; |
} |
} |
|
|
#endif |
#endif |
|
|
#define NameTrans(check,result) \ |
#define NameTrans(check,result) \ |
if (OkIndex(np->nte_index, check) \ |
if ((np->nte_index <= OK_ ## check) \ |
&& check[np->nte_index]) \ |
&& check[np->nte_index]) \ |
return (result[np->nte_index]) |
return (result[np->nte_index]) |
|
|
NCURSES_CONST char * |
NCURSES_CONST char * |
nametrans(const char *name) |
nametrans(const char *name) |
/* translate a capability name from termcap to terminfo */ |
/* translate a capability name to termcap from terminfo */ |
{ |
{ |
const struct name_table_entry *np; |
const struct name_table_entry *np; |
|
|
if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) |
if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) { |
switch (np->nte_type) { |
switch (np->nte_type) { |
case BOOLEAN: |
case BOOLEAN: |
NameTrans(bool_from_termcap, boolcodes); |
NameTrans(bool_from_termcap, boolcodes); |
|
|
NameTrans(str_from_termcap, strcodes); |
NameTrans(str_from_termcap, strcodes); |
break; |
break; |
} |
} |
|
} |
|
|
return (0); |
return (0); |
} |
} |
|
|
void |
void |
dump_init(const char *version, int mode, int sort, int twidth, int traceval, |
dump_init(const char *version, |
bool formatted) |
int mode, |
|
int sort, |
|
bool wrap_strings, |
|
int twidth, |
|
int theight, |
|
unsigned traceval, |
|
bool formatted, |
|
bool check, |
|
int quick) |
/* set up for entry display */ |
/* set up for entry display */ |
{ |
{ |
width = twidth; |
width = twidth; |
|
height = theight; |
pretty = formatted; |
pretty = formatted; |
|
wrapped = wrap_strings; |
|
checking = check; |
|
quickdump = (quick & 3); |
|
|
|
did_wrap = (width <= 0); |
|
|
/* versions */ |
/* versions */ |
if (version == 0) |
if (version == 0) |
tversion = V_ALLCAPS; |
tversion = V_ALLCAPS; |
|
|
bool_names = boolnames; |
bool_names = boolnames; |
num_names = numnames; |
num_names = numnames; |
str_names = strnames; |
str_names = strnames; |
separator = twidth ? ", " : ","; |
separator = (twidth > 0 && theight > 1) ? ", " : ","; |
trailer = "\n\t"; |
trailer = "\n\t"; |
break; |
break; |
|
|
|
|
bool_names = boolfnames; |
bool_names = boolfnames; |
num_names = numfnames; |
num_names = numfnames; |
str_names = strfnames; |
str_names = strfnames; |
separator = twidth ? ", " : ","; |
separator = (twidth > 0 && theight > 1) ? ", " : ","; |
trailer = "\n\t"; |
trailer = "\n\t"; |
break; |
break; |
|
|
|
|
trailer = "\\\n\t:"; |
trailer = "\\\n\t:"; |
break; |
break; |
} |
} |
|
indent = 8; |
|
|
/* implement sort modes */ |
/* implement sort modes */ |
switch (sortmode = sort) { |
switch (sortmode = sort) { |
|
|
_nc_progname, width, tversion, outform); |
_nc_progname, width, tversion, outform); |
} |
} |
|
|
static TERMTYPE *cur_type; |
static TERMTYPE2 *cur_type; |
|
|
static int |
static int |
dump_predicate(PredType type, PredIdx idx) |
dump_predicate(PredType type, PredIdx idx) |
|
|
return (FALSE); /* pacify compiler */ |
return (FALSE); /* pacify compiler */ |
} |
} |
|
|
static void set_obsolete_termcaps(TERMTYPE *tp); |
static void set_obsolete_termcaps(TERMTYPE2 *tp); |
|
|
/* is this the index of a function key string? */ |
/* is this the index of a function key string? */ |
#define FNKEY(i) (((i)>= 65 && (i)<= 75) || ((i)>= 216 && (i)<= 268)) |
#define FNKEY(i) \ |
|
(((i) >= STR_IDX(key_f0) && \ |
|
(i) <= STR_IDX(key_f9)) || \ |
|
((i) >= STR_IDX(key_f11) && \ |
|
(i) <= STR_IDX(key_f63))) |
|
|
/* |
/* |
* If we configure with a different Caps file, the offsets into the arrays |
* If we configure with a different Caps file, the offsets into the arrays |
|
|
oldcol = column; |
oldcol = column; |
trim_trailing(); |
trim_trailing(); |
strcpy_DYN(&outbuf, trailer); |
strcpy_DYN(&outbuf, trailer); |
column = INDENT; |
column = indent; |
} |
} |
|
|
|
static int |
|
op_length(const char *src, int offset) |
|
{ |
|
int result = 0; |
|
|
|
if (offset > 0 && src[offset - 1] == '\\') { |
|
result = 0; |
|
} else { |
|
int ch; |
|
|
|
result++; /* for '%' mark */ |
|
ch = src[offset + result]; |
|
if (TcOutput()) { |
|
if (ch == '>') { |
|
result += 3; |
|
} else if (ch == '+') { |
|
result += 2; |
|
} else { |
|
result++; |
|
} |
|
} else if (ch == '\'') { |
|
result += 3; |
|
} else if (ch == L_CURL[0]) { |
|
int n = result; |
|
while ((ch = src[offset + n]) != '\0') { |
|
if (ch == R_CURL[0]) { |
|
result = ++n; |
|
break; |
|
} |
|
n++; |
|
} |
|
} else if (strchr("pPg", ch) != 0) { |
|
result += 2; |
|
} else { |
|
result++; /* ordinary operator */ |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/* |
|
* When wrapping too-long strings, avoid splitting a backslash sequence, or |
|
* a terminfo '%' operator. That will leave things a little ragged, but avoids |
|
* a stray backslash at the end of the line, as well as making the result a |
|
* little more readable. |
|
*/ |
|
static int |
|
find_split(const char *src, int step, int size) |
|
{ |
|
int result = size; |
|
|
|
if (size > 0) { |
|
/* check if that would split a backslash-sequence */ |
|
int mark = size; |
|
int n; |
|
|
|
for (n = size - 1; n > 0; --n) { |
|
int ch = UChar(src[step + n]); |
|
if (ch == '\\') { |
|
if (n > 0 && src[step + n - 1] == ch) |
|
--n; |
|
mark = n; |
|
break; |
|
} else if (!isalnum(ch)) { |
|
break; |
|
} |
|
} |
|
if (mark < size) { |
|
result = mark; |
|
} else { |
|
/* check if that would split a backslash-sequence */ |
|
for (n = size - 1; n > 0; --n) { |
|
int ch = UChar(src[step + n]); |
|
if (ch == '%') { |
|
int need = op_length(src, step + n); |
|
if ((n + need) > size) { |
|
mark = n; |
|
} |
|
break; |
|
} |
|
} |
|
if (mark < size) { |
|
result = mark; |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
/* |
|
* If we are going to wrap lines, we cannot leave literal spaces because that |
|
* would be ambiguous if we split on that space. |
|
*/ |
|
static char * |
|
fill_spaces(const char *src) |
|
{ |
|
const char *fill = "\\s"; |
|
size_t need = strlen(src); |
|
size_t size = strlen(fill); |
|
char *result = 0; |
|
int pass; |
|
size_t s, d; |
|
for (pass = 0; pass < 2; ++pass) { |
|
for (s = d = 0; src[s] != '\0'; ++s) { |
|
if (src[s] == ' ') { |
|
if (pass) { |
|
_nc_STRCPY(&result[d], fill, need + 1 - d); |
|
d += size; |
|
} else { |
|
need += size; |
|
} |
|
} else { |
|
if (pass) { |
|
result[d++] = src[s]; |
|
} else { |
|
++d; |
|
} |
|
} |
|
} |
|
if (pass) { |
|
result[d] = '\0'; |
|
} else { |
|
result = calloc(need + 1, sizeof(char)); |
|
if (result == 0) |
|
failed("fill_spaces"); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
typedef enum { |
|
wOFF = 0 |
|
,w1ST = 1 |
|
,w2ND = 2 |
|
,wEND = 4 |
|
,wERR = 8 |
|
} WRAPMODE; |
|
|
|
#define wrap_1ST(mode) ((mode)&w1ST) |
|
#define wrap_END(mode) ((mode)&wEND) |
|
#define wrap_ERR(mode) ((mode)&wERR) |
|
|
static void |
static void |
wrap_concat(const char *src) |
wrap_concat(const char *src, int need, unsigned mode) |
{ |
{ |
unsigned need = strlen(src); |
int gaps = (int) strlen(separator); |
unsigned want = strlen(separator) + need; |
int want = gaps + need; |
|
|
if (column > INDENT |
did_wrap = (width <= 0); |
&& column + (int) want > width) { |
if (wrap_1ST(mode) |
|
&& column > indent |
|
&& column + want > width) { |
force_wrap(); |
force_wrap(); |
} |
} |
strcpy_DYN(&outbuf, src); |
if ((wrap_END(mode) && !wrap_ERR(mode)) && |
strcpy_DYN(&outbuf, separator); |
wrapped && |
column += (int) need; |
(width >= 0) && |
|
(column + want) > width) { |
|
int step = 0; |
|
int used = width > WRAPPED ? width : WRAPPED; |
|
int base = 0; |
|
char *p, align[9]; |
|
const char *my_t = trailer; |
|
char *fill = fill_spaces(src); |
|
int last = (int) strlen(fill); |
|
|
|
need = last; |
|
|
|
if (TcOutput()) |
|
trailer = "\\\n\t "; |
|
|
|
if (!TcOutput() && (p = strchr(fill, '=')) != 0) { |
|
base = (int) (p + 1 - fill); |
|
if (base > 8) |
|
base = 8; |
|
_nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " "); |
|
} else if (column > 8) { |
|
base = column - 8; |
|
if (base > 8) |
|
base = 8; |
|
_nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " "); |
|
} else { |
|
align[base] = '\0'; |
|
} |
|
/* "pretty" overrides wrapping if it already split the line */ |
|
if (!pretty || strchr(fill, '\n') == 0) { |
|
int tag = 0; |
|
|
|
if (TcOutput() && outbuf.used && !wrap_1ST(mode)) { |
|
tag = 3; |
|
} |
|
|
|
while ((column + (need + gaps)) > used) { |
|
int size = used - tag; |
|
if (step) { |
|
strcpy_DYN(&outbuf, align); |
|
size -= base; |
|
} |
|
if (size > (last - step)) { |
|
size = (last - step); |
|
} |
|
size = find_split(fill, step, size); |
|
strncpy_DYN(&outbuf, fill + step, (size_t) size); |
|
step += size; |
|
need -= size; |
|
if (need > 0) { |
|
force_wrap(); |
|
did_wrap = TRUE; |
|
tag = 0; |
|
} |
|
} |
|
} |
|
if (need > 0) { |
|
if (step) |
|
strcpy_DYN(&outbuf, align); |
|
strcpy_DYN(&outbuf, fill + step); |
|
} |
|
if (wrap_END(mode)) |
|
strcpy_DYN(&outbuf, separator); |
|
trailer = my_t; |
|
force_wrap(); |
|
|
|
free(fill); |
|
} else { |
|
strcpy_DYN(&outbuf, src); |
|
if (wrap_END(mode)) |
|
strcpy_DYN(&outbuf, separator); |
|
column += (int) strlen(src); |
|
} |
} |
} |
|
|
|
static void |
|
wrap_concat1(const char *src) |
|
{ |
|
int need = (int) strlen(src); |
|
wrap_concat(src, need, w1ST | wEND); |
|
} |
|
|
|
static void |
|
wrap_concat3(const char *name, const char *eqls, const char *value) |
|
{ |
|
int nlen = (int) strlen(name); |
|
int elen = (int) strlen(eqls); |
|
int vlen = (int) strlen(value); |
|
|
|
wrap_concat(name, nlen + elen + vlen, w1ST); |
|
wrap_concat(eqls, elen + vlen, w2ND); |
|
wrap_concat(value, vlen, wEND); |
|
} |
|
|
#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ |
#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ |
if ((size_t)(last - first) > sizeof(sep_trail)-1 \ |
if ((size_t)(last - first) > sizeof(sep_trail)-1 \ |
&& !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ |
&& !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ |
|
|
int n; |
int n; |
|
|
for (n = 0; n < level; n++) |
for (n = 0; n < level; n++) |
strncpy_DYN(buffer, "\t", 1); |
strncpy_DYN(buffer, "\t", (size_t) 1); |
} |
} |
|
|
|
/* |
|
* Check if the current line which was begun consists only of a tab and the |
|
* given leading text. |
|
*/ |
static bool |
static bool |
has_params(const char *src) |
leading_DYN(DYNBUF * buffer, const char *leading) |
{ |
{ |
bool result = FALSE; |
bool result = FALSE; |
|
size_t need = strlen(leading); |
|
if (buffer->used > need) { |
|
need = buffer->used - need; |
|
if (!strcmp(buffer->text + need, leading)) { |
|
result = TRUE; |
|
while (--need != 0) { |
|
if (buffer->text[need] == '\n') { |
|
break; |
|
} |
|
if (buffer->text[need] != '\t') { |
|
result = FALSE; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
bool |
|
has_params(const char *src, bool formatting) |
|
{ |
|
bool result = FALSE; |
int len = (int) strlen(src); |
int len = (int) strlen(src); |
int n; |
int n; |
bool ifthen = FALSE; |
bool ifthen = FALSE; |
bool params = FALSE; |
bool params = FALSE; |
|
|
for (n = 0; n < len - 1; ++n) { |
for (n = 0; n < len - 1; ++n) { |
if (!strncmp(src + n, "%p", 2)) { |
if (!strncmp(src + n, "%p", (size_t) 2)) { |
params = TRUE; |
params = TRUE; |
} else if (!strncmp(src + n, "%;", 2)) { |
} else if (!strncmp(src + n, "%;", (size_t) 2)) { |
ifthen = TRUE; |
ifthen = TRUE; |
result = params; |
result = params; |
break; |
break; |
} |
} |
} |
} |
if (!ifthen) { |
if (!ifthen) { |
result = ((len > 50) && params); |
if (formatting) { |
|
result = ((len > 50) && params); |
|
} else { |
|
result = params; |
|
} |
} |
} |
return result; |
return result; |
} |
} |
|
|
static char * |
static char * |
fmt_complex(char *src, int level) |
fmt_complex(TERMTYPE2 *tterm, const char *capability, char *src, int level) |
{ |
{ |
bool percent = FALSE; |
bool percent = FALSE; |
bool params = has_params(src); |
bool params = has_params(src, TRUE); |
|
|
while (*src != '\0') { |
while (*src != '\0') { |
switch (*src) { |
switch (*src) { |
|
case '^': |
|
percent = FALSE; |
|
strncpy_DYN(&tmpbuf, src++, (size_t) 1); |
|
break; |
case '\\': |
case '\\': |
percent = FALSE; |
percent = FALSE; |
strncpy_DYN(&tmpbuf, src++, 1); |
strncpy_DYN(&tmpbuf, src++, (size_t) 1); |
break; |
break; |
case '%': |
case '%': |
percent = TRUE; |
percent = TRUE; |
|
|
/* treat a "%e" as else-if, on the same level */ |
/* treat a "%e" as else-if, on the same level */ |
if (*src == 'e') { |
if (*src == 'e') { |
indent_DYN(&tmpbuf, level); |
indent_DYN(&tmpbuf, level); |
strncpy_DYN(&tmpbuf, "%", 1); |
strncpy_DYN(&tmpbuf, "%", (size_t) 1); |
strncpy_DYN(&tmpbuf, src, 1); |
strncpy_DYN(&tmpbuf, src, (size_t) 1); |
src++; |
src++; |
params = has_params(src); |
params = has_params(src, TRUE); |
if (!params && *src != '\0' && *src != '%') { |
if (!params && *src != '\0' && *src != '%') { |
strncpy_DYN(&tmpbuf, "\n", 1); |
strncpy_DYN(&tmpbuf, "\n", (size_t) 1); |
indent_DYN(&tmpbuf, level + 1); |
indent_DYN(&tmpbuf, level + 1); |
} |
} |
} else { |
} else { |
indent_DYN(&tmpbuf, level + 1); |
indent_DYN(&tmpbuf, level + 1); |
strncpy_DYN(&tmpbuf, "%", 1); |
strncpy_DYN(&tmpbuf, "%", (size_t) 1); |
strncpy_DYN(&tmpbuf, src, 1); |
strncpy_DYN(&tmpbuf, src, (size_t) 1); |
if (*src++ == '?') { |
if (*src++ == '?') { |
src = fmt_complex(src, level + 1); |
src = fmt_complex(tterm, capability, src, level + 1); |
if (*src != '\0' && *src != '%') { |
if (*src != '\0' && *src != '%') { |
strncpy_DYN(&tmpbuf, "\n", 1); |
strncpy_DYN(&tmpbuf, "\n", (size_t) 1); |
indent_DYN(&tmpbuf, level + 1); |
indent_DYN(&tmpbuf, level + 1); |
} |
} |
} else if (level == 1) { |
} else if (level == 1) { |
_nc_warning("%%%c without %%?", *src); |
if (checking) |
|
_nc_warning("%s: %%%c without %%? in %s", |
|
_nc_first_name(tterm->term_names), |
|
*src, capability); |
} |
} |
} |
} |
continue; |
continue; |
|
|
if (level > 1) { |
if (level > 1) { |
tmpbuf.text[tmpbuf.used - 1] = '\n'; |
tmpbuf.text[tmpbuf.used - 1] = '\n'; |
indent_DYN(&tmpbuf, level); |
indent_DYN(&tmpbuf, level); |
strncpy_DYN(&tmpbuf, "%", 1); |
strncpy_DYN(&tmpbuf, "%", (size_t) 1); |
strncpy_DYN(&tmpbuf, src++, 1); |
strncpy_DYN(&tmpbuf, src++, (size_t) 1); |
|
if (src[0] == '%' |
|
&& src[1] != '\0' |
|
&& (strchr("?e;", src[1])) == 0) { |
|
tmpbuf.text[tmpbuf.used++] = '\n'; |
|
indent_DYN(&tmpbuf, level); |
|
} |
return src; |
return src; |
} |
} |
_nc_warning("%%; without %%?"); |
if (checking) |
|
_nc_warning("%s: %%; without %%? in %s", |
|
_nc_first_name(tterm->term_names), |
|
capability); |
} |
} |
break; |
break; |
case 'p': |
case 'p': |
if (percent && params) { |
if (percent && params && !leading_DYN(&tmpbuf, "%")) { |
tmpbuf.text[tmpbuf.used - 1] = '\n'; |
tmpbuf.text[tmpbuf.used - 1] = '\n'; |
indent_DYN(&tmpbuf, level + 1); |
indent_DYN(&tmpbuf, level + 1); |
strncpy_DYN(&tmpbuf, "%", 1); |
strncpy_DYN(&tmpbuf, "%", (size_t) 1); |
} |
} |
params = FALSE; |
|
percent = FALSE; |
percent = FALSE; |
break; |
break; |
case ' ': |
case ' ': |
strncpy_DYN(&tmpbuf, "\\s", 2); |
strncpy_DYN(&tmpbuf, "\\s", (size_t) 2); |
++src; |
++src; |
continue; |
continue; |
default: |
default: |
percent = FALSE; |
percent = FALSE; |
break; |
break; |
} |
} |
strncpy_DYN(&tmpbuf, src++, 1); |
strncpy_DYN(&tmpbuf, src++, (size_t) 1); |
} |
} |
return src; |
return src; |
} |
} |
|
|
|
/* |
|
* Make "large" numbers a little easier to read by showing them in hexadecimal |
|
* if they are "close" to a power of two. |
|
*/ |
|
static const char * |
|
number_format(int value) |
|
{ |
|
const char *result = "%d"; |
|
|
|
if ((outform != F_TERMCAP) && (value > 255)) { |
|
unsigned long lv = (unsigned long) value; |
|
int bits = sizeof(unsigned long) * 8; |
|
int nn; |
|
|
|
for (nn = 8; nn < bits; ++nn) { |
|
unsigned long mm; |
|
|
|
mm = 1UL << nn; |
|
if ((mm - 16) <= lv && (mm + 16) > lv) { |
|
result = "%#x"; |
|
break; |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) |
#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) |
#define EXTRA_CAP 20 |
#define EXTRA_CAP 20 |
|
|
int |
int |
fmt_entry(TERMTYPE *tterm, |
fmt_entry(TERMTYPE2 *tterm, |
PredFunc pred, |
PredFunc pred, |
bool content_only, |
int content_only, |
bool suppress_untranslatable, |
int suppress_untranslatable, |
bool infodump, |
int infodump, |
int numbers) |
int numbers) |
{ |
{ |
PredIdx i, j; |
PredIdx i, j; |
char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; |
char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; |
char *capability; |
|
NCURSES_CONST char *name; |
NCURSES_CONST char *name; |
int predval, len; |
int predval, len; |
PredIdx num_bools = 0; |
PredIdx num_bools = 0; |
|
|
PredIdx num_strings = 0; |
PredIdx num_strings = 0; |
bool outcount = 0; |
bool outcount = 0; |
|
|
#define WRAP_CONCAT \ |
#define WRAP_CONCAT1(s) wrap_concat1(s); outcount = TRUE |
wrap_concat(buffer); \ |
#define WRAP_CONCAT WRAP_CONCAT1(buffer) |
outcount = TRUE |
|
|
|
len = 12; /* terminfo file-header */ |
len = 12; /* terminfo file-header */ |
|
|
|
|
|
|
strcpy_DYN(&outbuf, 0); |
strcpy_DYN(&outbuf, 0); |
if (content_only) { |
if (content_only) { |
column = INDENT; /* FIXME: workaround to prevent empty lines */ |
column = indent; /* workaround to prevent empty lines */ |
} else { |
} else { |
strcpy_DYN(&outbuf, tterm->term_names); |
strcpy_DYN(&outbuf, tterm->term_names); |
|
|
|
/* |
|
* Colon is legal in terminfo descriptions, but not in termcap. |
|
*/ |
|
if (!infodump) { |
|
char *p = outbuf.text; |
|
while (*p) { |
|
if (*p == ':') { |
|
*p = '='; |
|
} |
|
++p; |
|
} |
|
} |
strcpy_DYN(&outbuf, separator); |
strcpy_DYN(&outbuf, separator); |
column = (int) outbuf.used; |
column = (int) outbuf.used; |
force_wrap(); |
if (height > 1) |
|
force_wrap(); |
} |
} |
|
|
for_each_boolean(j, tterm) { |
for_each_boolean(j, tterm) { |
i = BoolIndirect(j); |
i = BoolIndirect(j); |
name = ExtBoolname(tterm, i, bool_names); |
name = ExtBoolname(tterm, (int) i, bool_names); |
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); |
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); |
|
|
if (!version_filter(BOOLEAN, i)) |
if (!version_filter(BOOLEAN, i)) |
|
|
|
|
predval = pred(BOOLEAN, i); |
predval = pred(BOOLEAN, i); |
if (predval != FAIL) { |
if (predval != FAIL) { |
(void) strlcpy(buffer, name, sizeof buffer); |
_nc_STRCPY(buffer, name, sizeof(buffer)); |
if (predval <= 0) |
if (predval <= 0) |
(void) strlcat(buffer, "@", sizeof buffer); |
_nc_STRCAT(buffer, "@", sizeof(buffer)); |
else if (i + 1 > num_bools) |
else if (i + 1 > num_bools) |
num_bools = i + 1; |
num_bools = i + 1; |
WRAP_CONCAT; |
WRAP_CONCAT; |
} |
} |
} |
} |
|
|
if (column != INDENT) |
if (column != indent && height > 1) |
force_wrap(); |
force_wrap(); |
|
|
for_each_number(j, tterm) { |
for_each_number(j, tterm) { |
i = NumIndirect(j); |
i = NumIndirect(j); |
name = ExtNumname(tterm, i, num_names); |
name = ExtNumname(tterm, (int) i, num_names); |
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); |
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); |
|
|
if (!version_filter(NUMBER, i)) |
if (!version_filter(NUMBER, i)) |
|
|
predval = pred(NUMBER, i); |
predval = pred(NUMBER, i); |
if (predval != FAIL) { |
if (predval != FAIL) { |
if (tterm->Numbers[i] < 0) { |
if (tterm->Numbers[i] < 0) { |
snprintf(buffer, sizeof buffer, "%s@", name); |
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
|
"%s@", name); |
} else { |
} else { |
snprintf(buffer, sizeof buffer, "%s#%d", name, tterm->Numbers[i]); |
size_t nn; |
|
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
|
"%s#", name); |
|
nn = strlen(buffer); |
|
_nc_SPRINTF(buffer + nn, _nc_SLIMIT(sizeof(buffer) - nn) |
|
number_format(tterm->Numbers[i]), |
|
tterm->Numbers[i]); |
if (i + 1 > num_values) |
if (i + 1 > num_values) |
num_values = i + 1; |
num_values = i + 1; |
} |
} |
|
|
} |
} |
} |
} |
|
|
if (column != INDENT) |
if (column != indent && height > 1) |
force_wrap(); |
force_wrap(); |
|
|
len += (int) (num_bools |
len += (int) (num_bools |
|
|
#undef CUR |
#undef CUR |
#define CUR tterm-> |
#define CUR tterm-> |
if (outform == F_TERMCAP) { |
if (outform == F_TERMCAP) { |
if (termcap_reset != ABSENT_STRING) { |
if (VALID_STRING(termcap_reset)) { |
if (init_3string != ABSENT_STRING |
if (VALID_STRING(init_3string) |
&& !strcmp(init_3string, termcap_reset)) |
&& !strcmp(init_3string, termcap_reset)) |
DISCARD(init_3string); |
DISCARD(init_3string); |
|
|
if (reset_2string != ABSENT_STRING |
if (VALID_STRING(reset_2string) |
&& !strcmp(reset_2string, termcap_reset)) |
&& !strcmp(reset_2string, termcap_reset)) |
DISCARD(reset_2string); |
DISCARD(reset_2string); |
} |
} |
} |
} |
|
|
for_each_string(j, tterm) { |
for_each_string(j, tterm) { |
|
char *capability; |
i = StrIndirect(j); |
i = StrIndirect(j); |
name = ExtStrname(tterm, i, str_names); |
name = ExtStrname(tterm, (int) i, str_names); |
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); |
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); |
|
|
capability = tterm->Strings[i]; |
capability = tterm->Strings[i]; |
|
|
if (PRESENT(insert_character) || PRESENT(parm_ich)) { |
if (PRESENT(insert_character) || PRESENT(parm_ich)) { |
if (SAME_CAP(i, enter_insert_mode) |
if (SAME_CAP(i, enter_insert_mode) |
&& enter_insert_mode == ABSENT_STRING) { |
&& enter_insert_mode == ABSENT_STRING) { |
(void) strlcpy(buffer, "im=", sizeof(buffer)); |
_nc_STRCPY(buffer, "im=", sizeof(buffer)); |
WRAP_CONCAT; |
WRAP_CONCAT; |
continue; |
continue; |
} |
} |
|
|
if (SAME_CAP(i, exit_insert_mode) |
if (SAME_CAP(i, exit_insert_mode) |
&& exit_insert_mode == ABSENT_STRING) { |
&& exit_insert_mode == ABSENT_STRING) { |
(void) strlcpy(buffer, "ei=", sizeof(buffer)); |
_nc_STRCPY(buffer, "ei=", sizeof(buffer)); |
WRAP_CONCAT; |
WRAP_CONCAT; |
continue; |
continue; |
} |
} |
|
|
set_attributes = save_sgr; |
set_attributes = save_sgr; |
|
|
trimmed_sgr0 = _nc_trim_sgr0(tterm); |
trimmed_sgr0 = _nc_trim_sgr0(tterm); |
if (strcmp(capability, trimmed_sgr0)) |
if (strcmp(capability, trimmed_sgr0)) { |
capability = trimmed_sgr0; |
capability = trimmed_sgr0; |
|
} else { |
|
if (trimmed_sgr0 != exit_attribute_mode) |
|
free(trimmed_sgr0); |
|
} |
|
|
set_attributes = my_sgr; |
set_attributes = my_sgr; |
} |
} |
|
|
buffer[0] = '\0'; |
buffer[0] = '\0'; |
|
|
if (predval != FAIL) { |
if (predval != FAIL) { |
if (capability != ABSENT_STRING |
if (VALID_STRING(capability) |
&& i + 1 > num_strings) |
&& i + 1 > num_strings) |
num_strings = i + 1; |
num_strings = i + 1; |
|
|
if (!VALID_STRING(capability)) { |
if (!VALID_STRING(capability)) { |
snprintf(buffer, sizeof(buffer), "%s@", name); |
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
|
"%s@", name); |
WRAP_CONCAT; |
WRAP_CONCAT; |
} else if (outform == F_TERMCAP || outform == F_TCONVERR) { |
} else if (TcOutput()) { |
|
char *srccap = _nc_tic_expand(capability, TRUE, numbers); |
int params = ((i < (int) SIZEOF(parametrized)) |
int params = ((i < (int) SIZEOF(parametrized)) |
? parametrized[i] |
? parametrized[i] |
: 0); |
: ((*srccap == 'k') |
char *srccap = _nc_tic_expand(capability, TRUE, numbers); |
? 0 |
|
: has_params(srccap, FALSE))); |
char *cv = _nc_infotocap(name, srccap, params); |
char *cv = _nc_infotocap(name, srccap, params); |
|
|
if (cv == 0) { |
if (cv == 0) { |
if (outform == F_TCONVERR) { |
if (outform == F_TCONVERR) { |
snprintf(buffer, sizeof(buffer), |
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
"%s=!!! %s WILL NOT CONVERT !!!", name, srccap); |
"%s=!!! %s WILL NOT CONVERT !!!", |
|
name, srccap); |
|
WRAP_CONCAT; |
} else if (suppress_untranslatable) { |
} else if (suppress_untranslatable) { |
continue; |
continue; |
} else { |
} else { |
char *d, *s = srccap; |
char *s = srccap, *d = buffer; |
snprintf(buffer, sizeof(buffer), "..%s=", name); |
int need = 3 + (int) strlen(name); |
d = buffer + strlen(buffer); |
while ((*d = *s++) != 0) { |
while ((*d = *s++) != 0) { /* XXX overflow */ |
if ((d - buffer + 2) >= (int) sizeof(buffer)) { |
|
fprintf(stderr, |
|
"%s: value for %s is too long\n", |
|
_nc_progname, |
|
name); |
|
*d = '\0'; |
|
break; |
|
} |
if (*d == ':') { |
if (*d == ':') { |
*d++ = '\\'; |
*d++ = '\\'; |
*d = ':'; |
*d = ':'; |
} else if (*d == '\\') { |
} else if (*d == '\\') { |
*++d = *s++; |
if ((*++d = *s++) == '\0') |
|
break; |
} |
} |
d++; |
d++; |
|
*d = '\0'; |
} |
} |
|
need += (int) (d - buffer); |
|
wrap_concat("..", need, w1ST | wERR); |
|
need -= 2; |
|
wrap_concat(name, need, wOFF | wERR); |
|
need -= (int) strlen(name); |
|
wrap_concat("=", need, w2ND | wERR); |
|
need -= 1; |
|
wrap_concat(buffer, need, wEND | wERR); |
|
outcount = TRUE; |
} |
} |
} else { |
} else { |
snprintf(buffer, sizeof buffer, "%s=%s", name, cv); |
wrap_concat3(name, "=", cv); |
} |
} |
len += (int) strlen(capability) + 1; |
len += (int) strlen(capability) + 1; |
WRAP_CONCAT; |
|
} else { |
} else { |
char *src = _nc_tic_expand(capability, |
char *src = _nc_tic_expand(capability, |
outform == F_TERMINFO, numbers); |
outform == F_TERMINFO, numbers); |
|
|
if (pretty |
if (pretty |
&& (outform == F_TERMINFO |
&& (outform == F_TERMINFO |
|| outform == F_VARIABLE)) { |
|| outform == F_VARIABLE)) { |
fmt_complex(src, 1); |
fmt_complex(tterm, name, src, 1); |
} else { |
} else { |
strcpy_DYN(&tmpbuf, src); |
strcpy_DYN(&tmpbuf, src); |
} |
} |
len += (int) strlen(capability) + 1; |
len += (int) strlen(capability) + 1; |
wrap_concat(tmpbuf.text); |
WRAP_CONCAT1(tmpbuf.text); |
outcount = TRUE; |
|
} |
} |
} |
} |
/* e.g., trimmed_sgr0 */ |
/* e.g., trimmed_sgr0 */ |
if (capability != tterm->Strings[i]) |
if (VALID_STRING(capability) && |
|
capability != tterm->Strings[i]) |
free(capability); |
free(capability); |
} |
} |
len += (int) (num_strings * 2); |
len += (int) (num_strings * 2); |
|
|
*/ |
*/ |
if (tversion == V_HPUX) { |
if (tversion == V_HPUX) { |
if (VALID_STRING(memory_lock)) { |
if (VALID_STRING(memory_lock)) { |
(void) snprintf(buffer, sizeof(buffer), "meml=%s", memory_lock); |
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
|
"meml=%s", memory_lock); |
WRAP_CONCAT; |
WRAP_CONCAT; |
} |
} |
if (VALID_STRING(memory_unlock)) { |
if (VALID_STRING(memory_unlock)) { |
(void) snprintf(buffer, sizeof(buffer), "memu=%s", memory_unlock); |
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
|
"memu=%s", memory_unlock); |
WRAP_CONCAT; |
WRAP_CONCAT; |
} |
} |
} else if (tversion == V_AIX) { |
} else if (tversion == V_AIX) { |
|
|
|
|
tp = boxchars; |
tp = boxchars; |
for (cp = acstrans; *cp; cp++) { |
for (cp = acstrans; *cp; cp++) { |
sp = strchr(acs_chars, *cp); |
sp = (strchr) (acs_chars, *cp); |
if (sp) |
if (sp) |
*tp++ = sp[1]; |
*tp++ = sp[1]; |
else { |
else { |
|
|
tp[0] = '\0'; |
tp[0] = '\0'; |
|
|
if (box_ok) { |
if (box_ok) { |
(void) strlcpy(buffer, "box1=", sizeof(buffer)); |
char *tmp = _nc_tic_expand(boxchars, |
(void) strlcat(buffer, _nc_tic_expand(boxchars, |
(outform == F_TERMINFO), |
outform == F_TERMINFO, numbers), sizeof(buffer)); |
numbers); |
|
_nc_STRCPY(buffer, "box1=", sizeof(buffer)); |
|
while (*tmp != '\0') { |
|
size_t have = strlen(buffer); |
|
size_t next = strlen(tmp); |
|
size_t want = have + next + 1; |
|
size_t last = next; |
|
char save = '\0'; |
|
|
|
/* |
|
* If the expanded string is too long for the buffer, |
|
* chop it off and save the location where we chopped it. |
|
*/ |
|
if (want >= sizeof(buffer)) { |
|
save = tmp[last]; |
|
tmp[last] = '\0'; |
|
} |
|
_nc_STRCAT(buffer, tmp, sizeof(buffer)); |
|
|
|
/* |
|
* If we chopped the buffer, replace the missing piece and |
|
* shift everything to append the remainder. |
|
*/ |
|
if (save != '\0') { |
|
next = 0; |
|
tmp[last] = save; |
|
while ((tmp[next] = tmp[last + next]) != '\0') { |
|
++next; |
|
} |
|
} else { |
|
break; |
|
} |
|
} |
WRAP_CONCAT; |
WRAP_CONCAT; |
} |
} |
} |
} |
|
|
*/ |
*/ |
if (outcount) { |
if (outcount) { |
bool trimmed = FALSE; |
bool trimmed = FALSE; |
j = outbuf.used; |
j = (PredIdx) outbuf.used; |
if (j >= 2 |
if (wrapped && did_wrap) { |
&& outbuf.text[j - 1] == '\t' |
/* EMPTY */ ; |
&& outbuf.text[j - 2] == '\n') { |
} else if (j >= 2 |
|
&& outbuf.text[j - 1] == '\t' |
|
&& outbuf.text[j - 2] == '\n') { |
outbuf.used -= 2; |
outbuf.used -= 2; |
trimmed = TRUE; |
trimmed = TRUE; |
} else if (j >= 4 |
} else if (j >= 4 |
|
|
} |
} |
|
|
static bool |
static bool |
kill_string(TERMTYPE *tterm, char *cap) |
kill_string(TERMTYPE2 *tterm, const char *const cap) |
{ |
{ |
unsigned n; |
unsigned n; |
for (n = 0; n < NUM_STRINGS(tterm); ++n) { |
for (n = 0; n < NUM_STRINGS(tterm); ++n) { |
|
|
} |
} |
|
|
static char * |
static char * |
find_string(TERMTYPE *tterm, char *name) |
find_string(TERMTYPE2 *tterm, char *name) |
{ |
{ |
PredIdx n; |
PredIdx n; |
for (n = 0; n < NUM_STRINGS(tterm); ++n) { |
for (n = 0; n < NUM_STRINGS(tterm); ++n) { |
|
|
* make it smaller. |
* make it smaller. |
*/ |
*/ |
static int |
static int |
kill_labels(TERMTYPE *tterm, int target) |
kill_labels(TERMTYPE2 *tterm, int target) |
{ |
{ |
int n; |
int n; |
int result = 0; |
int result = 0; |
char *cap; |
char name[20]; |
char name[10]; |
|
|
|
for (n = 0; n <= 10; ++n) { |
for (n = 0; n <= 10; ++n) { |
snprintf(name, sizeof(name), "lf%d", n); |
char *cap; |
if ((cap = find_string(tterm, name)) != ABSENT_STRING |
|
|
_nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n); |
|
cap = find_string(tterm, name); |
|
if (VALID_STRING(cap) |
&& kill_string(tterm, cap)) { |
&& kill_string(tterm, cap)) { |
target -= (int) (strlen(cap) + 5); |
target -= (int) (strlen(cap) + 5); |
++result; |
++result; |
|
|
* make it smaller. |
* make it smaller. |
*/ |
*/ |
static int |
static int |
kill_fkeys(TERMTYPE *tterm, int target) |
kill_fkeys(TERMTYPE2 *tterm, int target) |
{ |
{ |
int n; |
int n; |
int result = 0; |
int result = 0; |
char *cap; |
char name[20]; |
char name[10]; |
|
|
|
for (n = 60; n >= 0; --n) { |
for (n = 60; n >= 0; --n) { |
snprintf(name, sizeof(name), "kf%d", n); |
char *cap; |
if ((cap = find_string(tterm, name)) != ABSENT_STRING |
|
|
_nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n); |
|
cap = find_string(tterm, name); |
|
if (VALID_STRING(cap) |
&& kill_string(tterm, cap)) { |
&& kill_string(tterm, cap)) { |
target -= (int) (strlen(cap) + 5); |
target -= (int) (strlen(cap) + 5); |
++result; |
++result; |
|
|
{ |
{ |
bool result = TRUE; |
bool result = TRUE; |
|
|
if (mapping != ABSENT_STRING) { |
if (VALID_STRING(mapping)) { |
int n = 0; |
int n = 0; |
while (mapping[n] != '\0') { |
while (mapping[n] != '\0' && mapping[n + 1] != '\0') { |
if (isLine(mapping[n]) && |
if (isLine(mapping[n]) && |
mapping[n] != mapping[n + 1]) { |
mapping[n] != mapping[n + 1]) { |
result = FALSE; |
result = FALSE; |
|
|
#define SHOW_WHY PRINTF |
#define SHOW_WHY PRINTF |
|
|
static bool |
static bool |
purged_acs(TERMTYPE *tterm) |
purged_acs(TERMTYPE2 *tterm) |
{ |
{ |
bool result = FALSE; |
bool result = FALSE; |
|
|
|
|
return result; |
return result; |
} |
} |
|
|
|
static void |
|
encode_b64(char *target, char *source, unsigned state, int *saved) |
|
{ |
|
/* RFC-4648 */ |
|
static const char data[] = |
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
|
"abcdefghijklmnopqrstuvwxyz" |
|
"0123456789" "-_"; |
|
int ch = UChar(source[state]); |
|
|
|
switch (state % 3) { |
|
case 0: |
|
*target++ = data[(ch >> 2) & 077]; |
|
*saved = (ch << 4); |
|
break; |
|
case 1: |
|
*target++ = data[((ch >> 4) | *saved) & 077]; |
|
*saved = (ch << 2); |
|
break; |
|
case 2: |
|
*target++ = data[((ch >> 6) | *saved) & 077]; |
|
*target++ = data[ch & 077]; |
|
*saved = 0; |
|
break; |
|
} |
|
*target = '\0'; |
|
} |
|
|
/* |
/* |
* Dump a single entry. |
* Dump a single entry. |
*/ |
*/ |
void |
void |
dump_entry(TERMTYPE *tterm, |
dump_entry(TERMTYPE2 *tterm, |
bool suppress_untranslatable, |
int suppress_untranslatable, |
bool limited, |
int limited, |
int numbers, |
int numbers, |
PredFunc pred) |
PredFunc pred) |
{ |
{ |
TERMTYPE save_tterm; |
TERMTYPE2 save_tterm; |
int len, critlen; |
int critlen; |
const char *legend; |
const char *legend; |
bool infodump; |
bool infodump; |
|
|
if (outform == F_TERMCAP || outform == F_TCONVERR) { |
if (quickdump) { |
|
char bigbuf[65536]; |
|
unsigned offset = 0; |
|
|
|
separator = ""; |
|
trailer = "\n"; |
|
indent = 0; |
|
|
|
if (_nc_write_object(tterm, bigbuf, &offset, sizeof(bigbuf)) == OK) { |
|
char numbuf[80]; |
|
unsigned n; |
|
|
|
if (quickdump & 1) { |
|
if (outbuf.used) |
|
wrap_concat1("\n"); |
|
wrap_concat1("hex:"); |
|
for (n = 0; n < offset; ++n) { |
|
_nc_SPRINTF(numbuf, _nc_SLIMIT(sizeof(numbuf)) |
|
"%02X", UChar(bigbuf[n])); |
|
wrap_concat1(numbuf); |
|
} |
|
} |
|
if (quickdump & 2) { |
|
static char padding[] = |
|
{0, 0}; |
|
int value = 0; |
|
|
|
if (outbuf.used) |
|
wrap_concat1("\n"); |
|
wrap_concat1("b64:"); |
|
for (n = 0; n < offset; ++n) { |
|
encode_b64(numbuf, bigbuf, n, &value); |
|
wrap_concat1(numbuf); |
|
} |
|
switch (n % 3) { |
|
case 0: |
|
break; |
|
case 1: |
|
encode_b64(numbuf, padding, 1, &value); |
|
wrap_concat1(numbuf); |
|
wrap_concat1("=="); |
|
break; |
|
case 2: |
|
encode_b64(numbuf, padding, 1, &value); |
|
wrap_concat1(numbuf); |
|
wrap_concat1("="); |
|
break; |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
if (TcOutput()) { |
critlen = MAX_TERMCAP_LENGTH; |
critlen = MAX_TERMCAP_LENGTH; |
legend = "older termcap"; |
legend = "older termcap"; |
infodump = FALSE; |
infodump = FALSE; |
|
|
|
|
save_sgr = set_attributes; |
save_sgr = set_attributes; |
|
|
if (((len = FMT_ENTRY()) > critlen) |
if ((FMT_ENTRY() > critlen) |
|
&& TcOutput() |
&& limited) { |
&& limited) { |
|
|
save_tterm = *tterm; |
save_tterm = *tterm; |
|
|
critlen); |
critlen); |
suppress_untranslatable = TRUE; |
suppress_untranslatable = TRUE; |
} |
} |
if ((len = FMT_ENTRY()) > critlen) { |
if (FMT_ENTRY() > critlen) { |
/* |
/* |
* We pick on sgr because it's a nice long string capability that |
* We pick on sgr because it is a nice long string capability that |
* is really just an optimization hack. Another good candidate is |
* is really just an optimization hack. Another good candidate is |
* acsc since it is both long and unused by BSD termcap. |
* acsc since it is both long and unused by BSD termcap. |
*/ |
*/ |
|
|
*/ |
*/ |
unsigned n; |
unsigned n; |
for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { |
for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { |
const char *name = ExtStrname(tterm, n, strnames); |
const char *name = ExtStrname(tterm, (int) n, strnames); |
|
|
if (VALID_STRING(tterm->Strings[n])) { |
if (VALID_STRING(tterm->Strings[n])) { |
set_attributes = ABSENT_STRING; |
set_attributes = ABSENT_STRING; |
|
|
critlen); |
critlen); |
} |
} |
changed = TRUE; |
changed = TRUE; |
if ((len = FMT_ENTRY()) <= critlen) |
if (FMT_ENTRY() <= critlen) |
break; |
break; |
} |
} |
} |
} |
|
|
critlen); |
critlen); |
changed = TRUE; |
changed = TRUE; |
} |
} |
if (!changed || ((len = FMT_ENTRY()) > critlen)) { |
if (!changed || (FMT_ENTRY() > critlen)) { |
if (purged_acs(tterm)) { |
if (purged_acs(tterm)) { |
acs_chars = ABSENT_STRING; |
acs_chars = ABSENT_STRING; |
SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n", |
SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n", |
|
|
changed = TRUE; |
changed = TRUE; |
} |
} |
} |
} |
if (!changed || ((len = FMT_ENTRY()) > critlen)) { |
if (!changed || (FMT_ENTRY() > critlen)) { |
int oldversion = tversion; |
int oldversion = tversion; |
|
int len; |
|
|
tversion = V_BSD; |
tversion = V_BSD; |
SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", |
SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", |
|
|
} |
} |
if (len > critlen) { |
if (len > critlen) { |
(void) fprintf(stderr, |
(void) fprintf(stderr, |
"warning: %s entry is %d bytes long\n", |
"%s: %s entry is %d bytes long\n", |
|
_nc_progname, |
_nc_first_name(tterm->term_names), |
_nc_first_name(tterm->term_names), |
len); |
len); |
SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", |
SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", |
|
|
} else if (!version_filter(STRING, STR_IDX(acs_chars))) { |
} else if (!version_filter(STRING, STR_IDX(acs_chars))) { |
save_tterm = *tterm; |
save_tterm = *tterm; |
if (purged_acs(tterm)) { |
if (purged_acs(tterm)) { |
len = FMT_ENTRY(); |
(void) FMT_ENTRY(); |
} |
} |
*tterm = save_tterm; |
*tterm = save_tterm; |
} |
} |
} |
} |
|
|
void |
void |
dump_uses(const char *name, bool infodump) |
dump_uses(const char *value, bool infodump) |
/* dump "use=" clauses in the appropriate format */ |
/* dump "use=" clauses in the appropriate format */ |
{ |
{ |
char buffer[MAX_TERMINFO_LENGTH]; |
char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; |
|
int limit = (VALID_STRING(value) ? (int) strlen(value) : 0); |
|
const char *cap = infodump ? "use" : "tc"; |
|
|
if (outform == F_TERMCAP || outform == F_TCONVERR) |
if (TcOutput()) |
trim_trailing(); |
trim_trailing(); |
(void) snprintf(buffer, sizeof(buffer), "%s%s", infodump ? "use=" : "tc=", |
if (limit == 0) { |
name); |
_nc_warning("empty \"%s\" field", cap); |
wrap_concat(buffer); |
value = ""; |
|
} else if (limit > MAX_ALIAS) { |
|
_nc_warning("\"%s\" field too long (%d), limit to %d", |
|
cap, limit, MAX_ALIAS); |
|
limit = MAX_ALIAS; |
|
} |
|
_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) |
|
"%s=%.*s", cap, limit, value); |
|
wrap_concat1(buffer); |
} |
} |
|
|
int |
int |
show_entry(void) |
show_entry(void) |
{ |
{ |
trim_trailing(); |
/* |
(void) fputs(outbuf.text, stdout); |
* Trim any remaining whitespace. |
putchar('\n'); |
*/ |
|
if (outbuf.used != 0) { |
|
bool infodump = !TcOutput(); |
|
char delim = (char) (infodump ? ',' : ':'); |
|
int j; |
|
|
|
for (j = (int) outbuf.used - 1; j > 0; --j) { |
|
char ch = outbuf.text[j]; |
|
if (ch == '\n') { |
|
; |
|
} else if (isspace(UChar(ch))) { |
|
outbuf.used = (size_t) j; |
|
} else if (!infodump && ch == '\\') { |
|
outbuf.used = (size_t) j; |
|
} else if (ch == delim && (outbuf.text[j - 1] != '\\')) { |
|
outbuf.used = (size_t) (j + 1); |
|
} else { |
|
break; |
|
} |
|
} |
|
outbuf.text[outbuf.used] = '\0'; |
|
} |
|
if (outbuf.text != 0) { |
|
(void) fputs(outbuf.text, stdout); |
|
putchar('\n'); |
|
} |
return (int) outbuf.used; |
return (int) outbuf.used; |
} |
} |
|
|
void |
void |
compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), |
compare_entry(PredHook hook, |
TERMTYPE *tp GCC_UNUSED, |
TERMTYPE2 *tp GCC_UNUSED, |
bool quiet) |
bool quiet) |
/* compare two entries */ |
/* compare two entries */ |
{ |
{ |
|
|
fputs(" comparing booleans.\n", stdout); |
fputs(" comparing booleans.\n", stdout); |
for_each_boolean(j, tp) { |
for_each_boolean(j, tp) { |
i = BoolIndirect(j); |
i = BoolIndirect(j); |
name = ExtBoolname(tp, i, bool_names); |
name = ExtBoolname(tp, (int) i, bool_names); |
|
|
if (isObsolete(outform, name)) |
if (isObsolete(outform, name)) |
continue; |
continue; |
|
|
fputs(" comparing numbers.\n", stdout); |
fputs(" comparing numbers.\n", stdout); |
for_each_number(j, tp) { |
for_each_number(j, tp) { |
i = NumIndirect(j); |
i = NumIndirect(j); |
name = ExtNumname(tp, i, num_names); |
name = ExtNumname(tp, (int) i, num_names); |
|
|
if (isObsolete(outform, name)) |
if (isObsolete(outform, name)) |
continue; |
continue; |
|
|
fputs(" comparing strings.\n", stdout); |
fputs(" comparing strings.\n", stdout); |
for_each_string(j, tp) { |
for_each_string(j, tp) { |
i = StrIndirect(j); |
i = StrIndirect(j); |
name = ExtStrname(tp, i, str_names); |
name = ExtStrname(tp, (int) i, str_names); |
|
|
if (isObsolete(outform, name)) |
if (isObsolete(outform, name)) |
continue; |
continue; |
|
|
#define CUR tp-> |
#define CUR tp-> |
|
|
static void |
static void |
set_obsolete_termcaps(TERMTYPE *tp) |
set_obsolete_termcaps(TERMTYPE2 *tp) |
{ |
{ |
#include "capdefaults.c" |
#include "capdefaults.c" |
} |
} |
|
|
* unique. |
* unique. |
*/ |
*/ |
void |
void |
repair_acsc(TERMTYPE *tp) |
repair_acsc(TERMTYPE2 *tp) |
{ |
{ |
if (VALID_STRING(acs_chars)) { |
if (VALID_STRING(acs_chars)) { |
size_t n, m; |
size_t n; |
char mapped[256]; |
char mapped[256]; |
char extra = 0; |
|
unsigned source; |
unsigned source; |
unsigned target; |
unsigned target; |
bool fix_needed = FALSE; |
bool fix_needed = FALSE; |
|
|
if (acs_chars[n + 1]) |
if (acs_chars[n + 1]) |
n++; |
n++; |
} |
} |
|
|
if (fix_needed) { |
if (fix_needed) { |
|
size_t m; |
|
char extra = 0; |
|
|
memset(mapped, 0, sizeof(mapped)); |
memset(mapped, 0, sizeof(mapped)); |
for (n = 0; acs_chars[n] != 0; n++) { |
for (n = 0; acs_chars[n] != 0; n++) { |
source = UChar(acs_chars[n]); |
source = UChar(acs_chars[n]); |