diff options
Diffstat (limited to 'lib/libcurses/tinfo')
55 files changed, 5547 insertions, 2543 deletions
diff --git a/lib/libcurses/tinfo/MKcaptab.awk b/lib/libcurses/tinfo/MKcaptab.awk index 4f5df3afdb2..b105931c55d 100644 --- a/lib/libcurses/tinfo/MKcaptab.awk +++ b/lib/libcurses/tinfo/MKcaptab.awk @@ -1,72 +1,95 @@ -#!/bin/sh -# $OpenBSD: MKcaptab.awk,v 1.3 2001/01/22 18:01:49 millert Exp $ -# $From: MKcaptab.awk,v 1.12 2000/12/10 00:14:12 tom Exp $ -AWK=${1-awk} -DATA=${2-../include/Caps} - -cat <<'EOF' -/* - * comp_captab.c -- The names of the capabilities indexed via a hash - * table for the compiler. - * - */ - -#include <ncurses_cfg.h> -#include <curses.priv.h> -#include <tic.h> -#include <term.h> - -EOF - -./make_hash 1 info <$DATA -./make_hash 3 cap <$DATA - -cat <<'EOF' -const struct alias _nc_capalias_table[] = -{ -EOF +# $OpenBSD: MKcaptab.awk,v 1.4 2010/01/12 23:22:06 nicm Exp $ +############################################################################## +# Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: MKcaptab.awk,v 1.4 2010/01/12 23:22:06 nicm Exp $ +function add_string(text) { + if (text != "IGNORE") { + offsets[num_strings] = offset; + offset = offset + length(text) + 1; + printf "%s\\0", text; + } else { + offsets[num_strings] = -1; + } + num_strings = num_strings + 1; + if ((num_strings % 3) == 0) { + printf "\\\n"; + } + return offsets[num_strings - 1]; +} +BEGIN { + first = 1; + num_aliases = 0; + num_strings = 0; + offset = 0; +} -$AWK <$DATA ' -$1 == "capalias" { - if ($3 == "IGNORE") - to = "(char *)NULL"; - else - to = "\"" $3 "\""; - printf "\t{\"%s\", %s, \"%s\"},\t /* %s */\n", - $2, to, $4, $5 +/^[^#]/ { + if (first) { + printf "/* generated by MKcaptab.awk %s(%d) */\n", tablename, bigstrings; + print "" + if (bigstrings) { + printf "static struct alias *_nc_%s_table = 0;\n", tablename; + print ""; + printf "static const char %s_text[] = \"\\\n", tablename; + } else { + printf "static const struct alias _nc_%s_table[] =\n", tablename; + printf "{\n"; } -' - -cat <<'EOF' - {(char *)NULL, (char *)NULL, (char *)NULL} -}; - -const struct alias _nc_infoalias_table[] = -{ -EOF - -$AWK <$DATA ' -$1 == "infoalias" { - if ($3 == "IGNORE") - to = "(char *)NULL"; - else - to = "\"" $3 "\""; - printf "\t{\"%s\", %s, \"%s\"},\t /* %s */\n", - $2, to, $4, $5 + first = 0; + } + if ($1 == tablename) { + if ($3 == "IGNORE") { + to = "(char *)NULL"; + } else { + to = "\"" $3 "\""; } -' - -cat <<'EOF' - {(char *)NULL, (char *)NULL, (char *)NULL} -}; - -NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool termcap) -{ - return termcap ? _nc_cap_table: _nc_info_table ; -} - -NCURSES_EXPORT(const struct name_table_entry * const *) _nc_get_hash_table (bool termcap) -{ - return termcap ? _nc_cap_hash_table: _nc_info_hash_table ; -} -EOF + if (bigstrings) { + c1 = add_string($2); + c2 = add_string($3); + c3 = add_string($4); + aliases[num_aliases] = sprintf("\t{%5d, %5d, %5d},\t /* %s */", c1, c2, c3, $5); + num_aliases = num_aliases + 1; + } else { + printf "\t{\"%s\", %s, \"%s\"},\t /* %s */\n", $2, to, $4, $5; + } + } + } +END { + if (bigstrings) { + printf "\";\n\n"; + printf "static const alias_table_data %s_data[] = {\n", tablename; + for (n = 0; n < num_aliases; ++n) { + printf "%s\n", aliases[n]; + } + printf "};\n\n"; + } else { + printf "\t{(char *)NULL, (char *)NULL, (char *)NULL}\n"; + printf "};\n\n"; + } + } +# vile:sw=4: diff --git a/lib/libcurses/tinfo/MKcaptab.sh b/lib/libcurses/tinfo/MKcaptab.sh new file mode 100644 index 00000000000..d7305f2f88e --- /dev/null +++ b/lib/libcurses/tinfo/MKcaptab.sh @@ -0,0 +1,150 @@ +#!/bin/sh +# $OpenBSD: MKcaptab.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ +############################################################################## +# Copyright (c) 2007 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: MKcaptab.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ +AWK=${1-awk} +OPT1=${2-0} +OPT2=${3-tinfo/MKcaptab.awk} +DATA=${4-../include/Caps} + +cat <<'EOF' +/* + * comp_captab.c -- The names of the capabilities indexed via a hash + * table for the compiler. + * + */ + +#include <curses.priv.h> +#include <tic.h> +#include <hashsize.h> + +EOF + +./make_hash 1 info $OPT1 <$DATA +./make_hash 3 cap $OPT1 <$DATA + +$AWK -f $OPT2 bigstrings=$OPT1 tablename=capalias <$DATA + +$AWK -f $OPT2 bigstrings=$OPT1 tablename=infoalias <$DATA + +cat <<EOF + +#if $OPT1 +static void +next_string(const char *strings, unsigned *offset) +{ + *offset += strlen(strings + *offset) + 1; +} + +static const struct name_table_entry * +_nc_build_names(struct name_table_entry **actual, + const name_table_data *source, + const char *strings) +{ + if (*actual == 0) { + *actual = typeCalloc(struct name_table_entry, CAPTABSIZE); + if (*actual != 0) { + unsigned n; + unsigned len = 0; + for (n = 0; n < CAPTABSIZE; ++n) { + (*actual)[n].nte_name = strings + len; + (*actual)[n].nte_type = source[n].nte_type; + (*actual)[n].nte_index = source[n].nte_index; + (*actual)[n].nte_link = source[n].nte_link; + next_string(strings, &len); + } + } + } + return *actual; +} + +#define add_alias(field) \\ + if (source[n].field >= 0) { \\ + (*actual)[n].field = strings + source[n].field; \\ + } + +static const struct alias * +_nc_build_alias(struct alias **actual, + const alias_table_data *source, + const char *strings, + unsigned tablesize) +{ + if (*actual == 0) { + *actual = typeCalloc(struct alias, tablesize + 1); + if (*actual != 0) { + unsigned n; + for (n = 0; n < tablesize; ++n) { + add_alias(from); + add_alias(to); + add_alias(source); + } + } + } + return *actual; +} + +#define build_names(root) _nc_build_names(&_nc_##root##_table, \\ + root##_names_data, \\ + root##_names_text) +#define build_alias(root) _nc_build_alias(&_nc_##root##alias_table, \\ + root##alias_data, \\ + root##alias_text, \\ + SIZEOF(root##alias_data)) +#else +#define build_names(root) _nc_ ## root ## _table +#define build_alias(root) _nc_ ## root ## alias_table +#endif + +NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool termcap) +{ + return termcap ? build_names(cap) : build_names(info) ; +} + +NCURSES_EXPORT(const short *) _nc_get_hash_table (bool termcap) +{ + return termcap ? _nc_cap_hash_table: _nc_info_hash_table ; +} + +NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool termcap) +{ + return termcap ? build_alias(cap) : build_alias(info) ; +} + +#if NO_LEAKS +NCURSES_EXPORT(void) _nc_comp_captab_leaks(void) +{ +#if $OPT1 + FreeIfNeeded(_nc_cap_table); + FreeIfNeeded(_nc_info_table); + FreeIfNeeded(_nc_capalias_table); + FreeIfNeeded(_nc_infoalias_table); +#endif +} +#endif /* NO_LEAKS */ +EOF diff --git a/lib/libcurses/tinfo/MKcodes.awk b/lib/libcurses/tinfo/MKcodes.awk new file mode 100644 index 00000000000..669f673c91b --- /dev/null +++ b/lib/libcurses/tinfo/MKcodes.awk @@ -0,0 +1,165 @@ +# $OpenBSD: MKcodes.awk,v 1.1 2010/01/12 23:22:06 nicm Exp $ +############################################################################## +# Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: MKcodes.awk,v 1.1 2010/01/12 23:22:06 nicm Exp $ +function large_item(value) { + result = sprintf("%d,", offset); + offset = offset + length(value) + 1; + offcol = offcol + length(result) + 2; + if (offcol > 70) { + result = result "\n"; + offcol = 0; + } else { + result = result " "; + } + bigstr = bigstr sprintf("\"%s\\0\" ", value); + bigcol = bigcol + length(value) + 5; + if (bigcol > 70) { + bigstr = bigstr "\\\n"; + bigcol = 0; + } + return result; +} + +function small_item(value) { + return sprintf("\t\t\"%s\",\n", value); +} + +function print_strings(name,value) { + printf "DCL(%s) = {\n", name + print value + print "\t\t(NCURSES_CONST char *)0," + print "};" + print "" +} + +function print_offsets(name,value) { + printf "static const short _nc_offset_%s[] = {\n", name + printf "%s", value + print "};" + print "" + printf "static NCURSES_CONST char ** ptr_%s = 0;\n", name + print "" +} + +BEGIN { + print "/* This file was generated by MKcodes.awk */" + print "" + print "#include <curses.priv.h>" + print "" + print "#define IT NCURSES_CONST char * const" + print "" + offset = 0; + offcol = 0; + bigcol = 0; + } + +$1 ~ /^#/ {next;} + +$1 == "SKIPWARN" {next;} + +$3 == "bool" { + small_boolcodes = small_boolcodes small_item($4); + large_boolcodes = large_boolcodes large_item($4); + } + +$3 == "num" { + small_numcodes = small_numcodes small_item($4); + large_numcodes = large_numcodes large_item($4); + } + +$3 == "str" { + small_strcodes = small_strcodes small_item($4); + large_strcodes = large_strcodes large_item($4); + } + +END { + print "" + print "#if BROKEN_LINKER || USE_REENTRANT" + print "" + print "#include <term.h>" + print "" + if (bigstrings) { + printf "static const char _nc_code_blob[] = \n" + printf "%s;\n", bigstr; + print_offsets("boolcodes", large_boolcodes); + print_offsets("numcodes", large_numcodes); + print_offsets("strcodes", large_strcodes); + print "" + print "static IT *" + print "alloc_array(NCURSES_CONST char ***value, const short *offsets, unsigned size)" + print "{" + print " if (*value == 0) {" + print " if ((*value = typeCalloc(NCURSES_CONST char *, size + 1)) != 0) {" + print " unsigned n;" + print " for (n = 0; n < size; ++n) {" + print " (*value)[n] = _nc_code_blob + offsets[n];" + print " }" + print " }" + print " }" + print " return *value;" + print "}" + print "" + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }" + } else { + print "#define DCL(it) static IT data##it[]" + print "" + print_strings("boolcodes", small_boolcodes); + print_strings("numcodes", small_numcodes); + print_strings("strcodes", small_strcodes); + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }" + } + print "" + print "FIX(boolcodes)" + print "FIX(numcodes)" + print "FIX(strcodes)" + print "" + print "#define FREE_FIX(it) if (ptr_##it) { FreeAndNull(ptr_##it); }" + print "" + print "#if NO_LEAKS" + print "NCURSES_EXPORT(void)" + print "_nc_codes_leaks(void)" + print "{" + if (bigstrings) { + print "FREE_FIX(boolcodes)" + print "FREE_FIX(numcodes)" + print "FREE_FIX(strcodes)" + } + print "}" + print "#endif" + print "" + print "#else" + print "" + print "#define DCL(it) NCURSES_EXPORT_VAR(IT) it[]" + print "" + print_strings("boolcodes", small_boolcodes); + print_strings("numcodes", small_numcodes); + print_strings("strcodes", small_strcodes); + print "" + print "#endif /* BROKEN_LINKER */" + } diff --git a/lib/libcurses/tinfo/MKfallback.sh b/lib/libcurses/tinfo/MKfallback.sh index ce7d14cb7a4..c33d8489e9f 100644 --- a/lib/libcurses/tinfo/MKfallback.sh +++ b/lib/libcurses/tinfo/MKfallback.sh @@ -1,6 +1,33 @@ #!/bin/sh -# $OpenBSD: MKfallback.sh,v 1.3 2001/01/22 18:01:50 millert Exp $ -# $From: MKfallback.sh,v 1.10 2000/12/10 00:14:39 tom Exp $ +# $OpenBSD: MKfallback.sh,v 1.4 2010/01/12 23:22:06 nicm Exp $ +############################################################################## +# Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: MKfallback.sh,v 1.4 2010/01/12 23:22:06 nicm Exp $ # # MKfallback.sh -- create fallback table for entry reads # @@ -9,6 +36,7 @@ # from an on-disk terminfo tree) tries to match the type with one of a # specified list of types generated in. # + cat <<EOF /* * DO NOT EDIT THIS FILE BY HAND! It is generated by MKfallback.sh. diff --git a/lib/libcurses/tinfo/MKkeys_list.sh b/lib/libcurses/tinfo/MKkeys_list.sh new file mode 100644 index 00000000000..e28d899fedf --- /dev/null +++ b/lib/libcurses/tinfo/MKkeys_list.sh @@ -0,0 +1,63 @@ +#! /bin/sh +# $OpenBSD: MKkeys_list.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ +# $Id: MKkeys_list.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ +############################################################################## +# Copyright (c) 2001,2003 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# +# MKkey_defs.sh -- generate list of function-keys for terminfo database +# +# Author: Thomas E. Dickey 2001 +# +# Extract function-key names from the Caps file +# +: ${AWK-awk} +DATA=${1-../../include/Caps} + +data=data$$ +trap 'rm -f $data' 0 1 2 5 15 +sed -e 's/[ ][ ]*/ /g' < $DATA >$data + +cat <<EOF +# These definitions were generated by $0 $DATA +KEY_BREAK +KEY_SRESET +KEY_RESET +KEY_RESIZE +EOF + +${AWK-awk} <$data ' +/^#/ {next;} +/^capalias/ {next;} +/^infoalias/ {next;} + +$5 != "-" { + if (substr($5, 1, 4) == "KEY_" ) { + printf "%s %s\n", $5, $1 + } +} +' diff --git a/lib/libcurses/tinfo/MKnames.awk b/lib/libcurses/tinfo/MKnames.awk index 5fdb8c20690..64ce6431fb7 100644 --- a/lib/libcurses/tinfo/MKnames.awk +++ b/lib/libcurses/tinfo/MKnames.awk @@ -1,99 +1,187 @@ -# $OpenBSD: MKnames.awk,v 1.2 2001/01/22 18:01:50 millert Exp $ -# $From: MKnames.awk,v 1.11 2000/12/09 23:46:13 tom Exp $ -BEGIN { - print "/* This file was generated by MKnames.awk */" > "namehdr" - print "" > "namehdr" - print "#include <curses.priv.h>" > "namehdr" - print "" > "namehdr" - print "#define IT NCURSES_CONST char * const" > "namehdr" - print "" > "namehdr" - print "#if BROKEN_LINKER" > "namehdr" - print "#include <term.h>" > "namehdr" - print "#define DCL(it) static IT data##it[]" > "namehdr" - print "#else" > "namehdr" - print "#define DCL(it) NCURSES_EXPORT_VAR(IT) it[]" > "namehdr" - print "#endif" > "namehdr" - print "" > "namehdr" - print "/*" > "boolnames" - print " * names.c - Arrays of capability names and codes" > "boolnames" - print " *" > "boolnames" - print " */" > "boolnames" - print "" > "boolnames" - print "DCL(boolnames) = {" > "boolnames" - print "DCL(boolfnames) = {" > "boolfnames" - print "DCL(boolcodes) = {" > "boolcodes" - print "DCL(numnames) = {" > "numnames" - print "DCL(numfnames) = {" > "numfnames" - print "DCL(numcodes) = {" > "numcodes" - print "DCL(strnames) = {" > "strnames" - print "DCL(strfnames) = {" > "strfnames" - print "DCL(strcodes) = {" > "strcodes" - } +# $OpenBSD: MKnames.awk,v 1.3 2010/01/12 23:22:06 nicm Exp $ +############################################################################## +# Copyright (c) 2007,2008 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: MKnames.awk,v 1.3 2010/01/12 23:22:06 nicm Exp $ +function large_item(value) { + result = sprintf("%d,", offset); + offset = offset + length(value) + 1; + offcol = offcol + length(result) + 2; + if (offcol > 70) { + result = result "\n"; + offcol = 0; + } else { + result = result " "; + } + bigstr = bigstr sprintf("\"%s\\0\" ", value); + bigcol = bigcol + length(value) + 5; + if (bigcol > 70) { + bigstr = bigstr "\\\n"; + bigcol = 0; + } + return result; +} + +function small_item(value) { + return sprintf("\t\t\"%s\",\n", value); +} + +function print_strings(name,value) { + printf "DCL(%s) = {\n", name + print value + print "\t\t(NCURSES_CONST char *)0," + print "};" + print "" +} + +function print_offsets(name,value) { + printf "static const short _nc_offset_%s[] = {\n", name + printf "%s", value + print "};" + print "" + printf "static NCURSES_CONST char ** ptr_%s = 0;\n", name + print "" +} + +BEGIN { + print "/* This file was generated by MKnames.awk */" + print "" + print "#include <curses.priv.h>" + print "" + print "#define IT NCURSES_CONST char * const" + print "" + offset = 0; + offcol = 0; + bigcol = 0; + } $1 ~ /^#/ {next;} $1 == "SKIPWARN" {next;} $3 == "bool" { - printf "\t\t\"%s\",\n", $2 > "boolnames" - printf "\t\t\"%s\",\n", $1 > "boolfnames" - printf "\t\t\"%s\",\n", $4 > "boolcodes" + small_boolnames = small_boolnames small_item($2); + large_boolnames = large_boolnames large_item($2); + small_boolfnames = small_boolfnames small_item($1); + large_boolfnames = large_boolfnames large_item($1); } $3 == "num" { - printf "\t\t\"%s\",\n", $2 > "numnames" - printf "\t\t\"%s\",\n", $1 > "numfnames" - printf "\t\t\"%s\",\n", $4 > "numcodes" + small_numnames = small_numnames small_item($2); + large_numnames = large_numnames large_item($2); + small_numfnames = small_numfnames small_item($1); + large_numfnames = large_numfnames large_item($1); } $3 == "str" { - printf "\t\t\"%s\",\n", $2 > "strnames" - printf "\t\t\"%s\",\n", $1 > "strfnames" - printf "\t\t\"%s\",\n", $4 > "strcodes" + small_strnames = small_strnames small_item($2); + large_strnames = large_strnames large_item($2); + small_strfnames = small_strfnames small_item($1); + large_strfnames = large_strfnames large_item($1); } -END { - print "\t\t(NCURSES_CONST char *)0," > "boolnames" - print "};" > "boolnames" - print "" > "boolnames" - print "\t\t(NCURSES_CONST char *)0," > "boolfnames" - print "};" > "boolfnames" - print "" > "boolfnames" - print "\t\t(NCURSES_CONST char *)0," > "boolcodes" - print "};" > "boolcodes" - print "" > "boolcodes" - print "\t\t(NCURSES_CONST char *)0," > "numnames" - print "};" > "numnames" - print "" > "numnames" - print "\t\t(NCURSES_CONST char *)0," > "numfnames" - print "};" > "numfnames" - print "" > "numfnames" - print "\t\t(NCURSES_CONST char *)0," > "numcodes" - print "};" > "numcodes" - print "" > "numcodes" - print "\t\t(NCURSES_CONST char *)0," > "strnames" - print "};" > "strnames" - print "" > "strnames" - print "\t\t(NCURSES_CONST char *)0," > "strfnames" - print "};" > "strfnames" - print "" > "strfnames" - print "\t\t(NCURSES_CONST char *)0," > "strcodes" - print "};" > "strcodes" - print "" > "strcodes" - print "#if BROKEN_LINKER" > "nameftr" - print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }" > "nameftr" - print "FIX(boolnames)" > "nameftr" - print "FIX(boolfnames)" > "nameftr" - print "FIX(numnames)" > "nameftr" - print "FIX(numfnames)" > "nameftr" - print "FIX(strnames)" > "nameftr" - print "FIX(strfnames)" > "nameftr" - print "#endif /* BROKEN_LINKER */" > "nameftr" - print "" > "codeftr" - print "#if BROKEN_LINKER" > "codeftr" - print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }" > "codeftr" - print "FIX(boolcodes)" > "codeftr" - print "FIX(numcodes)" > "codeftr" - print "FIX(strcodes)" > "codeftr" - print "#endif /* BROKEN_LINKER */" > "codeftr" +END { + print "" + print "#if BROKEN_LINKER || USE_REENTRANT" + print "" + print "#include <term.h>" + print "" + if (bigstrings) { + printf "static const char _nc_name_blob[] = \n" + printf "%s;\n", bigstr; + print_offsets("boolfnames", large_boolfnames); + print_offsets("boolnames", large_boolnames); + print_offsets("numfnames", large_numfnames); + print_offsets("numnames", large_numnames); + print_offsets("strfnames", large_strfnames); + print_offsets("strnames", large_strnames); + print "" + print "static IT *" + print "alloc_array(NCURSES_CONST char ***value, const short *offsets, unsigned size)" + print "{" + print " if (*value == 0) {" + print " if ((*value = typeCalloc(NCURSES_CONST char *, size + 1)) != 0) {" + print " unsigned n;" + print " for (n = 0; n < size; ++n) {" + print " (*value)[n] = (NCURSES_CONST char *) _nc_name_blob + offsets[n];" + print " }" + print " }" + print " }" + print " return *value;" + print "}" + print "" + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }" + } else { + print "#define DCL(it) static IT data##it[]" + print "" + print_strings("boolnames", small_boolnames); + print_strings("boolfnames", small_boolfnames); + print_strings("numnames", small_numnames); + print_strings("numfnames", small_numfnames); + print_strings("strnames", small_strnames); + print_strings("strfnames", small_strfnames); + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }" + } + print "" + print "FIX(boolnames)" + print "FIX(boolfnames)" + print "FIX(numnames)" + print "FIX(numfnames)" + print "FIX(strnames)" + print "FIX(strfnames)" + print "" + print "" + print "#define FREE_FIX(it) if (ptr_##it) { FreeAndNull(ptr_##it); }" + print "" + print "#if NO_LEAKS" + print "NCURSES_EXPORT(void)" + print "_nc_names_leaks(void)" + print "{" + if (bigstrings) { + print "FREE_FIX(boolnames)" + print "FREE_FIX(boolfnames)" + print "FREE_FIX(numnames)" + print "FREE_FIX(numfnames)" + print "FREE_FIX(strnames)" + print "FREE_FIX(strfnames)" } + print "}" + print "#endif" + print "" + print "#else" + print "" + print "#define DCL(it) NCURSES_EXPORT_VAR(IT) it[]" + print "" + print_strings("boolnames", small_boolnames); + print_strings("boolfnames", small_boolfnames); + print_strings("numnames", small_numnames); + print_strings("numfnames", small_numfnames); + print_strings("strnames", small_strnames); + print_strings("strfnames", small_strfnames); + print "" + print "#endif /* BROKEN_LINKER */" + } diff --git a/lib/libcurses/tinfo/access.c b/lib/libcurses/tinfo/access.c index a4a184e699c..0ea39c1106c 100644 --- a/lib/libcurses/tinfo/access.c +++ b/lib/libcurses/tinfo/access.c @@ -1,5 +1,7 @@ +/* $OpenBSD: access.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ + /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -27,27 +29,83 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1998,2000 * + * Author: Thomas E. Dickey * ****************************************************************************/ #include <curses.priv.h> + +#include <ctype.h> +#include <sys/stat.h> + #include <tic.h> +#include <nc_alloc.h> -MODULE_ID("$From: access.c,v 1.7 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: access.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") + +#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c)) NCURSES_EXPORT(char *) -_nc_basename(char *path) +_nc_rootname(char *path) { - char *result = strrchr(path, '/'); + char *result = _nc_basename(path); +#if !MIXEDCASE_FILENAMES || defined(PROG_EXT) + static char *temp; + char *s; + + temp = strdup(result); + result = temp; +#if !MIXEDCASE_FILENAMES + for (s = result; *s != '\0'; ++s) { + *s = LOWERCASE(*s); + } +#endif +#if defined(PROG_EXT) + if ((s = strrchr(result, '.')) != 0) { + if (!strcmp(s, PROG_EXT)) + *s = '\0'; + } +#endif +#endif + return result; +} + +/* + * Check if a string appears to be an absolute pathname. + */ +NCURSES_EXPORT(bool) +_nc_is_abs_path(const char *path) +{ +#if defined(__EMX__) || defined(__DJGPP__) +#define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \ + || (((s)[0] != 0) && ((s)[1] == ':'))) +#else +#define is_pathname(s) ((s) != 0 && (s)[0] == '/') +#endif + return is_pathname(path); +} + +/* + * Return index of the basename + */ +NCURSES_EXPORT(unsigned) +_nc_pathlast(const char *path) +{ + const char *test = strrchr(path, '/'); #ifdef __EMX__ - if (result == 0) - result = strrchr(path, '\\'); + if (test == 0) + test = strrchr(path, '\\'); #endif - if (result == 0) - result = path; + if (test == 0) + test = path; else - result++; - return result; + test++; + return (test - path); +} + +NCURSES_EXPORT(char *) +_nc_basename(char *path) +{ + return path + _nc_pathlast(path); } NCURSES_EXPORT(int) @@ -59,10 +117,10 @@ _nc_access(const char *path, int mode) && strlen(path) < PATH_MAX) { char *leaf, head[PATH_MAX]; - strlcpy(head, path, sizeof(head)); - if ((leaf = _nc_basename(head)) == 0) - leaf = head; - *leaf = '\0'; + strlcpy(head, path, sizeof(head)); + if ((leaf = _nc_basename(head)) == 0) + leaf = head; + *leaf = '\0'; if (head == leaf) (void) strlcpy(head, ".", sizeof(head)); @@ -73,6 +131,32 @@ _nc_access(const char *path, int mode) return 0; } +NCURSES_EXPORT(bool) +_nc_is_dir_path(const char *path) +{ + bool result = FALSE; + struct stat sb; + + if (stat(path, &sb) == 0 + && (sb.st_mode & S_IFMT) == S_IFDIR) { + result = TRUE; + } + return result; +} + +NCURSES_EXPORT(bool) +_nc_is_file_path(const char *path) +{ + bool result = FALSE; + struct stat sb; + + if (stat(path, &sb) == 0 + && (sb.st_mode & S_IFMT) == S_IFREG) { + result = TRUE; + } + return result; +} + #ifndef USE_ROOT_ENVIRON /* * Returns true if we allow application to use environment variables that are diff --git a/lib/libcurses/tinfo/add_tries.c b/lib/libcurses/tinfo/add_tries.c index 55ad69543d5..247087fd815 100644 --- a/lib/libcurses/tinfo/add_tries.c +++ b/lib/libcurses/tinfo/add_tries.c @@ -1,7 +1,7 @@ -/* $OpenBSD: add_tries.c,v 1.3 2001/01/22 18:01:50 millert Exp $ */ +/* $OpenBSD: add_tries.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +29,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1998 * + * Author: Thomas E. Dickey 1998-on * ****************************************************************************/ /* @@ -41,20 +41,20 @@ #include <curses.priv.h> -MODULE_ID("$From: add_tries.c,v 1.4 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: add_tries.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") #define SET_TRY(dst,src) if ((dst->ch = *src++) == 128) dst->ch = '\0' #define CMP_TRY(a,b) ((a)? (a == b) : (b == 128)) -NCURSES_EXPORT(void) -_nc_add_to_try(struct tries **tree, const char *str, unsigned short code) +NCURSES_EXPORT(int) +_nc_add_to_try(TRIES ** tree, const char *str, unsigned code) { - static bool out_of_memory = FALSE; - struct tries *ptr, *savedptr; + TRIES *ptr, *savedptr; unsigned const char *txt = (unsigned const char *) str; - if (txt == 0 || *txt == '\0' || out_of_memory || code == 0) - return; + T((T_CALLED("_nc_add_to_try(%p, %s, %u)"), *tree, _nc_visbuf(str), code)); + if (txt == 0 || *txt == '\0' || code == 0) + returnCode(ERR); if ((*tree) != 0) { ptr = savedptr = (*tree); @@ -69,16 +69,15 @@ _nc_add_to_try(struct tries **tree, const char *str, unsigned short code) if (CMP_TRY(ptr->ch, cmp)) { if (*(++txt) == '\0') { ptr->value = code; - return; + returnCode(OK); } if (ptr->child != 0) ptr = ptr->child; else break; } else { - if ((ptr->sibling = typeCalloc(struct tries, 1)) == 0) { - out_of_memory = TRUE; - return; + if ((ptr->sibling = typeCalloc(TRIES, 1)) == 0) { + returnCode(ERR); } savedptr = ptr = ptr->sibling; @@ -89,11 +88,10 @@ _nc_add_to_try(struct tries **tree, const char *str, unsigned short code) } } /* end for (;;) */ } else { /* (*tree) == 0 :: First sequence to be added */ - savedptr = ptr = (*tree) = typeCalloc(struct tries, 1); + savedptr = ptr = (*tree) = typeCalloc(TRIES, 1); if (ptr == 0) { - out_of_memory = TRUE; - return; + returnCode(ERR); } SET_TRY(ptr, txt); @@ -103,19 +101,16 @@ _nc_add_to_try(struct tries **tree, const char *str, unsigned short code) /* at this point, we are adding to the try. ptr->child == 0 */ while (*txt) { - ptr->child = typeCalloc(struct tries, 1); + ptr->child = typeCalloc(TRIES, 1); ptr = ptr->child; if (ptr == 0) { - out_of_memory = TRUE; - while ((ptr = savedptr) != 0) { savedptr = ptr->child; free(ptr); } - - return; + returnCode(ERR); } SET_TRY(ptr, txt); @@ -123,5 +118,5 @@ _nc_add_to_try(struct tries **tree, const char *str, unsigned short code) } ptr->value = code; - return; + returnCode(OK); } diff --git a/lib/libcurses/tinfo/alloc_entry.c b/lib/libcurses/tinfo/alloc_entry.c index b0bab761de8..c0861482018 100644 --- a/lib/libcurses/tinfo/alloc_entry.c +++ b/lib/libcurses/tinfo/alloc_entry.c @@ -1,7 +1,7 @@ -/* $OpenBSD: alloc_entry.c,v 1.5 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: alloc_entry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -49,21 +50,31 @@ #include <tic.h> #include <term_entry.h> -MODULE_ID("$From: alloc_entry.c,v 1.35 2001/01/13 22:40:17 tom Exp $") +MODULE_ID("$Id: alloc_entry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") #define ABSENT_OFFSET -1 #define CANCELLED_OFFSET -2 #define MAX_STRTAB 4096 /* documented maximum entry size */ -static char stringbuf[MAX_STRTAB]; /* buffer for string capabilities */ +static char *stringbuf; /* buffer for string capabilities */ static size_t next_free; /* next free character in stringbuf */ NCURSES_EXPORT(void) -_nc_init_entry(TERMTYPE * const tp) +_nc_init_entry(TERMTYPE *const tp) /* initialize a terminal type data block */ { - int i; + unsigned i; + +#if NO_LEAKS + if (tp == 0 && stringbuf != 0) { + FreeAndNull(stringbuf); + return; + } +#endif + + if (stringbuf == 0) + stringbuf = (char *) malloc(MAX_STRTAB); #if NCURSES_XNAMES tp->num_Booleans = BOOLCOUNT; @@ -74,7 +85,7 @@ _nc_init_entry(TERMTYPE * const tp) tp->ext_Strings = 0; #endif if (tp->Booleans == 0) - tp->Booleans = typeMalloc(char, BOOLCOUNT); + tp->Booleans = typeMalloc(NCURSES_SBOOL, BOOLCOUNT); if (tp->Numbers == 0) tp->Numbers = typeMalloc(short, NUMCOUNT); if (tp->Strings == 0) @@ -104,28 +115,42 @@ _nc_copy_entry(ENTRY * oldp) return newp; } +/* save a copy of string in the string buffer */ NCURSES_EXPORT(char *) _nc_save_str(const char *const string) -/* save a copy of string in the string buffer */ { + char *result = 0; size_t old_next_free = next_free; - size_t len; - - len = strlcpy(stringbuf + next_free, string, sizeof(stringbuf) - next_free); - if (++len < sizeof(stringbuf) - next_free) { + size_t len = strlen(string) + 1; + + if (len == 1 && next_free != 0) { + /* + * Cheat a little by making an empty string point to the end of the + * previous string. + */ + if (next_free < MAX_STRTAB) { + result = (stringbuf + next_free - 1); + } + } else if (next_free + len < MAX_STRTAB) { + strlcpy(&stringbuf[next_free], string, MAX_STRTAB - next_free); DEBUG(7, ("Saved string %s", _nc_visbuf(string))); DEBUG(7, ("at location %d", (int) next_free)); next_free += len; + result = (stringbuf + old_next_free); + } else { + _nc_warning("Too much data, some is lost"); } - return (stringbuf + old_next_free); + return result; } NCURSES_EXPORT(void) _nc_wrap_entry(ENTRY * const ep, bool copy_strings) /* copy the string parts to allocated storage, preserving pointers to it */ { - int offsets[MAX_ENTRY_SIZE / 2], useoffsets[MAX_USES]; - int i, n; + int offsets[MAX_ENTRY_SIZE / sizeof(short)]; + int useoffsets[MAX_USES]; + unsigned i, n; + unsigned nuses = ep->nuses; TERMTYPE *tp = &(ep->tterm); if (copy_strings) { @@ -140,7 +165,7 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) } } - for (i = 0; i < ep->nuses; i++) { + for (i = 0; i < nuses; i++) { if (ep->uses[i].name == 0) { ep->uses[i].name = _nc_save_str(ep->uses[i].name); } @@ -149,17 +174,21 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) free(tp->str_table); } - n = tp->term_names - stringbuf; + assert(tp->term_names >= stringbuf); + n = (unsigned) (tp->term_names - stringbuf); for_each_string(i, &(ep->tterm)) { - if (tp->Strings[i] == ABSENT_STRING) - offsets[i] = ABSENT_OFFSET; - else if (tp->Strings[i] == CANCELLED_STRING) - offsets[i] = CANCELLED_OFFSET; - else - offsets[i] = tp->Strings[i] - stringbuf; + if (i < SIZEOF(offsets)) { + if (tp->Strings[i] == ABSENT_STRING) { + offsets[i] = ABSENT_OFFSET; + } else if (tp->Strings[i] == CANCELLED_STRING) { + offsets[i] = CANCELLED_OFFSET; + } else { + offsets[i] = tp->Strings[i] - stringbuf; + } + } } - for (i = 0; i < ep->nuses; i++) { + for (i = 0; i < nuses; i++) { if (ep->uses[i].name == 0) useoffsets[i] = ABSENT_OFFSET; else @@ -167,43 +196,48 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) } if ((tp->str_table = typeMalloc(char, next_free)) == (char *) 0) - _nc_err_abort("Out of memory"); + _nc_err_abort(MSG_NO_MEMORY); (void) memcpy(tp->str_table, stringbuf, next_free); tp->term_names = tp->str_table + n; for_each_string(i, &(ep->tterm)) { - if (offsets[i] == ABSENT_OFFSET) - tp->Strings[i] = ABSENT_STRING; - else if (offsets[i] == CANCELLED_OFFSET) - tp->Strings[i] = CANCELLED_STRING; - else - tp->Strings[i] = tp->str_table + offsets[i]; + if (i < SIZEOF(offsets)) { + if (offsets[i] == ABSENT_OFFSET) { + tp->Strings[i] = ABSENT_STRING; + } else if (offsets[i] == CANCELLED_OFFSET) { + tp->Strings[i] = CANCELLED_STRING; + } else { + tp->Strings[i] = tp->str_table + offsets[i]; + } + } } #if NCURSES_XNAMES if (!copy_strings) { - if ((n = NUM_EXT_NAMES(tp)) != 0) { - size_t copied, length, strtabsize = 0; - for (i = 0; i < n; i++) { - strtabsize += strlen(tp->ext_Names[i]) + 1; - offsets[i] = tp->ext_Names[i] - stringbuf; - } - if ((tp->ext_str_table = typeMalloc(char, strtabsize)) == 0) - _nc_err_abort("Out of memory"); - for (i = 0, length = 0; i < n; i++) { - tp->ext_Names[i] = tp->ext_str_table + length; - copied = strlcpy(tp->ext_Names[i], stringbuf + offsets[i], - strtabsize) + 1; - if (copied > strtabsize) - _nc_err_abort("Buffer overflow"); - length += copied; - strtabsize -= copied; + if ((n = (unsigned) NUM_EXT_NAMES(tp)) != 0) { + if (n < SIZEOF(offsets)) { + size_t copied, length, strtabsize = 0; + for (i = 0; i < n; i++) { + strtabsize += strlen(tp->ext_Names[i]) + 1; + offsets[i] = tp->ext_Names[i] - stringbuf; + } + if ((tp->ext_str_table = typeMalloc(char, strtabsize)) == 0) + _nc_err_abort(MSG_NO_MEMORY); + for (i = 0, length = 0; i < n; i++) { + tp->ext_Names[i] = tp->ext_str_table + length; + copied = strlcpy(tp->ext_Names[i], stringbuf + offsets[i], + strtabsize) + 1; + if (copied > strtabsize) + _nc_err_abort("Buffer overflow"); + length += copied; + strtabsize -= copied; + } } } } #endif - for (i = 0; i < ep->nuses; i++) { + for (i = 0; i < nuses; i++) { if (useoffsets[i] == ABSENT_OFFSET) ep->uses[i].name = 0; else @@ -212,31 +246,34 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) } NCURSES_EXPORT(void) -_nc_merge_entry -(TERMTYPE * const to, TERMTYPE * const from) +_nc_merge_entry(TERMTYPE *const to, TERMTYPE *const from) /* merge capabilities from `from' entry into `to' entry */ { - int i; + unsigned i; #if NCURSES_XNAMES _nc_align_termtype(to, from); #endif for_each_boolean(i, from) { - int mergebool = from->Booleans[i]; + if (to->Booleans[i] != (char) CANCELLED_BOOLEAN) { + int mergebool = from->Booleans[i]; - if (mergebool == CANCELLED_BOOLEAN) - to->Booleans[i] = FALSE; - else if (mergebool == TRUE) - to->Booleans[i] = mergebool; + if (mergebool == CANCELLED_BOOLEAN) + to->Booleans[i] = FALSE; + else if (mergebool == TRUE) + to->Booleans[i] = (char) mergebool; + } } for_each_number(i, from) { - int mergenum = from->Numbers[i]; + if (to->Numbers[i] != CANCELLED_NUMERIC) { + short mergenum = from->Numbers[i]; - if (mergenum == CANCELLED_NUMERIC) - to->Numbers[i] = ABSENT_NUMERIC; - else if (mergenum != ABSENT_NUMERIC) - to->Numbers[i] = mergenum; + if (mergenum == CANCELLED_NUMERIC) + to->Numbers[i] = ABSENT_NUMERIC; + else if (mergenum != ABSENT_NUMERIC) + to->Numbers[i] = mergenum; + } } /* @@ -245,11 +282,24 @@ _nc_merge_entry * we ever want to deallocate entries. */ for_each_string(i, from) { - char *mergestring = from->Strings[i]; + if (to->Strings[i] != CANCELLED_STRING) { + char *mergestring = from->Strings[i]; + + if (mergestring == CANCELLED_STRING) + to->Strings[i] = ABSENT_STRING; + else if (mergestring != ABSENT_STRING) + to->Strings[i] = mergestring; + } + } +} - if (mergestring == CANCELLED_STRING) - to->Strings[i] = ABSENT_STRING; - else if (mergestring != ABSENT_STRING) - to->Strings[i] = mergestring; +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_alloc_entry_leaks(void) +{ + if (stringbuf != 0) { + FreeAndNull(stringbuf); } + next_free = 0; } +#endif diff --git a/lib/libcurses/tinfo/alloc_ttype.c b/lib/libcurses/tinfo/alloc_ttype.c index 43583824c0f..f474e502be4 100644 --- a/lib/libcurses/tinfo/alloc_ttype.c +++ b/lib/libcurses/tinfo/alloc_ttype.c @@ -1,7 +1,7 @@ -/* $OpenBSD: alloc_ttype.c,v 1.5 2001/01/22 18:01:50 millert Exp $ */ +/* $OpenBSD: alloc_ttype.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1999-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +29,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1999 * + * Author: Thomas E. Dickey <dickey@clark.net> 1999-on * ****************************************************************************/ /* @@ -45,7 +45,7 @@ #include <tic.h> #include <term_entry.h> -MODULE_ID("$From: alloc_ttype.c,v 1.12 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: alloc_ttype.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") #if NCURSES_XNAMES /* @@ -94,15 +94,17 @@ find_name(char **table, int length, char *name) } static void -realign_data(TERMTYPE * to, char **ext_Names, int ext_Booleans, int - ext_Numbers, int ext_Strings) +realign_data(TERMTYPE *to, char **ext_Names, + int ext_Booleans, + int ext_Numbers, + int ext_Strings) { int n, m, base; int limit = (to->ext_Booleans + to->ext_Numbers + to->ext_Strings); if (to->ext_Booleans != ext_Booleans) { to->num_Booleans += (ext_Booleans - to->ext_Booleans); - to->Booleans = typeRealloc(char, to->num_Booleans, to->Booleans); + to->Booleans = typeRealloc(NCURSES_SBOOL, to->num_Booleans, to->Booleans); for (n = to->ext_Booleans - 1, m = ext_Booleans - 1, base = to->num_Booleans - (m + 1); m >= 0; m--) { @@ -148,7 +150,7 @@ realign_data(TERMTYPE * to, char **ext_Names, int ext_Booleans, int * Returns the first index in ext_Names[] for the given token-type */ static int -_nc_first_ext_name(TERMTYPE * tp, int token_type) +_nc_first_ext_name(TERMTYPE *tp, int token_type) { int first; @@ -173,7 +175,7 @@ _nc_first_ext_name(TERMTYPE * tp, int token_type) * Returns the last index in ext_Names[] for the given token-type */ static int -_nc_last_ext_name(TERMTYPE * tp, int token_type) +_nc_last_ext_name(TERMTYPE *tp, int token_type) { int last; @@ -196,7 +198,7 @@ _nc_last_ext_name(TERMTYPE * tp, int token_type) * Lookup an entry from extended-names, returning -1 if not found */ static int -_nc_find_ext_name(TERMTYPE * tp, char *name, int token_type) +_nc_find_ext_name(TERMTYPE *tp, char *name, int token_type) { unsigned j; unsigned first = _nc_first_ext_name(tp, token_type); @@ -215,7 +217,7 @@ _nc_find_ext_name(TERMTYPE * tp, char *name, int token_type) * (e.g., Booleans[]). */ static int -_nc_ext_data_index(TERMTYPE * tp, int n, int token_type) +_nc_ext_data_index(TERMTYPE *tp, int n, int token_type) { switch (token_type) { case BOOLEAN: @@ -238,7 +240,7 @@ _nc_ext_data_index(TERMTYPE * tp, int n, int token_type) * data. */ static bool -_nc_del_ext_name(TERMTYPE * tp, char *name, int token_type) +_nc_del_ext_name(TERMTYPE *tp, char *name, int token_type) { int j; int first, last; @@ -282,7 +284,7 @@ _nc_del_ext_name(TERMTYPE * tp, char *name, int token_type) * index into the corresponding data array is returned. */ static int -_nc_ins_ext_name(TERMTYPE * tp, char *name, int token_type) +_nc_ins_ext_name(TERMTYPE *tp, char *name, int token_type) { unsigned first = _nc_first_ext_name(tp, token_type); unsigned last = _nc_last_ext_name(tp, token_type); @@ -293,7 +295,7 @@ _nc_ins_ext_name(TERMTYPE * tp, char *name, int token_type) int cmp = strcmp(name, tp->ext_Names[j]); if (cmp == 0) /* already present */ - return _nc_ext_data_index(tp, j, token_type); + return _nc_ext_data_index(tp, (int) j, token_type); if (cmp < 0) { break; } @@ -303,13 +305,13 @@ _nc_ins_ext_name(TERMTYPE * tp, char *name, int token_type) for (k = total - 1; k > j; k--) tp->ext_Names[k] = tp->ext_Names[k - 1]; tp->ext_Names[j] = name; - j = _nc_ext_data_index(tp, j, token_type); + j = _nc_ext_data_index(tp, (int) j, token_type); switch (token_type) { case BOOLEAN: tp->ext_Booleans += 1; tp->num_Booleans += 1; - tp->Booleans = typeRealloc(char, tp->num_Booleans, tp->Booleans); + tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans); for (k = tp->num_Booleans - 1; k > j; k--) tp->Booleans[k] = tp->Booleans[k - 1]; break; @@ -337,7 +339,7 @@ _nc_ins_ext_name(TERMTYPE * tp, char *name, int token_type) * cancellation of a name that is inherited from another entry. */ static void -adjust_cancels(TERMTYPE * to, TERMTYPE * from) +adjust_cancels(TERMTYPE *to, TERMTYPE *from) { int first = to->ext_Booleans + to->ext_Numbers; int last = first + to->ext_Strings; @@ -365,6 +367,17 @@ adjust_cancels(TERMTYPE * to, TERMTYPE * from) } else { j++; } + } else if ((k = _nc_find_ext_name(from, to->ext_Names[j], + STRING)) >= 0) { + if (_nc_del_ext_name(to, name, NUMBER) + || _nc_del_ext_name(to, name, BOOLEAN)) { + k = _nc_ins_ext_name(to, name, STRING); + to->Strings[k] = CANCELLED_STRING; + } else { + j++; + } + } else { + j++; } } else { j++; @@ -373,8 +386,7 @@ adjust_cancels(TERMTYPE * to, TERMTYPE * from) } NCURSES_EXPORT(void) -_nc_align_termtype -(TERMTYPE * to, TERMTYPE * from) +_nc_align_termtype(TERMTYPE *to, TERMTYPE *from) { int na = NUM_EXT_NAMES(to); int nb = NUM_EXT_NAMES(from); @@ -382,6 +394,7 @@ _nc_align_termtype bool same; char **ext_Names; int ext_Booleans, ext_Numbers, ext_Strings; + bool used_ext_Names = FALSE; DEBUG(2, ("align_termtype to(%d:%s), from(%d:%s)", na, to->term_names, nb, from->term_names)); @@ -445,6 +458,7 @@ _nc_align_termtype to->ext_Names = ext_Names; DEBUG(2, ("realigned %d extended names for '%s' (to)", NUM_EXT_NAMES(to), to->term_names)); + used_ext_Names = TRUE; } if (nb != (ext_Booleans + ext_Numbers + ext_Strings)) { nb = (ext_Booleans + ext_Numbers + ext_Strings); @@ -454,18 +468,19 @@ _nc_align_termtype DEBUG(2, ("realigned %d extended names for '%s' (from)", NUM_EXT_NAMES(from), from->term_names)); } + if (!used_ext_Names) + free(ext_Names); } } #endif NCURSES_EXPORT(void) -_nc_copy_termtype -(TERMTYPE * dst, TERMTYPE * src) +_nc_copy_termtype(TERMTYPE *dst, TERMTYPE *src) { - int i; + unsigned i; *dst = *src; /* ...to copy the sizes and string-tables */ - dst->Booleans = typeMalloc(char, NUM_BOOLEANS(dst)); + dst->Booleans = typeMalloc(NCURSES_SBOOL, NUM_BOOLEANS(dst)); dst->Numbers = typeMalloc(short, NUM_NUMBERS(dst)); dst->Strings = typeMalloc(char *, NUM_STRINGS(dst)); diff --git a/lib/libcurses/tinfo/captoinfo.c b/lib/libcurses/tinfo/captoinfo.c index 7c6a4587f58..6caf24560d1 100644 --- a/lib/libcurses/tinfo/captoinfo.c +++ b/lib/libcurses/tinfo/captoinfo.c @@ -1,7 +1,7 @@ -/* $OpenBSD: captoinfo.c,v 1.15 2006/10/24 17:25:48 moritz Exp $ */ +/* $OpenBSD: captoinfo.c,v 1.16 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -41,7 +42,7 @@ * * There is just one entry point: * - * char *_nc_captoinfo(n, s, parametrized) + * char *_nc_captoinfo(n, s, parameterized) * * Convert value s for termcap string capability named n into terminfo * format. @@ -94,7 +95,7 @@ #include <ctype.h> #include <tic.h> -MODULE_ID("$From: captoinfo.c,v 1.40 2000/11/05 00:22:36 tom Exp $") +MODULE_ID("$Id: captoinfo.c,v 1.16 2010/01/12 23:22:06 nicm Exp $") #define MAX_PUSHED 16 /* max # args we can push onto the stack */ @@ -117,7 +118,7 @@ init_string(void) if (my_string == 0) my_string = typeMalloc(char, my_length = 256); if (my_string == 0) - _nc_err_abort("Out of memory"); + _nc_err_abort(MSG_NO_MEMORY); *my_string = '\0'; return my_string; @@ -132,19 +133,19 @@ save_string(char *d, const char *const s) if (need > my_length) { my_string = (char *) realloc(my_string, my_length = (need + need)); if (my_string == 0) - _nc_err_abort("Out of memory"); + _nc_err_abort(MSG_NO_MEMORY); d = my_string + have; } if ((copied = strlcpy(d, s, my_length - have)) >= my_length - have) - _nc_err_abort("Buffer overflow"); + _nc_err_abort("Buffer overflow"); return d + copied; } -static inline char * -save_char(char *s, char c) +static NCURSES_INLINE char * +save_char(char *s, int c) { static char temp[2]; - temp[0] = c; + temp[0] = (char) c; return save_string(s, temp); } @@ -152,7 +153,7 @@ static void push(void) /* push onstack on to the stack */ { - if (stackptr > MAX_PUSHED) + if (stackptr >= MAX_PUSHED) _nc_warning("string too complex to convert"); else stack[stackptr++] = onstack; @@ -186,7 +187,7 @@ cvtchar(register const char *sp) case '$': case '\\': case '%': - c = *sp; + c = (unsigned char) (*sp); len = 2; break; case '\0': @@ -198,13 +199,13 @@ cvtchar(register const char *sp) case '2': case '3': len = 1; - while (isdigit(CharOf(*sp))) { + while (isdigit(UChar(*sp))) { c = 8 * c + (*sp++ - '0'); len++; } break; default: - c = *sp; + c = (unsigned char) (*sp); len = 2; break; } @@ -214,7 +215,7 @@ cvtchar(register const char *sp) len = 2; break; default: - c = *sp; + c = (unsigned char) (*sp); len = 1; } if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') { @@ -276,12 +277,12 @@ getparm(int parm, int n) * Convert a termcap string to terminfo format. * 'cap' is the relevant terminfo capability index. * 's' is the string value of the capability. - * 'parametrized' tells what type of translations to do: + * 'parameterized' tells what type of translations to do: * % translations if 1 * pad translations if >=0 */ -char * -_nc_captoinfo(const char *cap, const char *s, int const parametrized) +NCURSES_EXPORT(char *) +_nc_captoinfo(const char *cap, const char *s, int const parameterized) { const char *capstart; @@ -298,16 +299,16 @@ _nc_captoinfo(const char *cap, const char *s, int const parametrized) capstart = 0; if (s == 0) s = ""; - if (parametrized >= 0 && isdigit(CharOf(*s))) + if (parameterized >= 0 && isdigit(UChar(*s))) for (capstart = s;; s++) - if (!(isdigit(CharOf(*s)) || *s == '*' || *s == '.')) + if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.')) break; while (*s != '\0') { switch (*s) { case '%': s++; - if (parametrized < 1) { + if (parameterized < 1) { dp = save_char(dp, '%'); break; } @@ -468,7 +469,7 @@ _nc_captoinfo(const char *cap, const char *s, int const parametrized) dp = save_char(dp, '%'); s--; _nc_warning("unknown %% code %s (%#x) in %s", - unctrl((chtype) * s), CharOf(*s), cap); + unctrl((chtype) *s), UChar(*s), cap); break; } break; @@ -549,7 +550,7 @@ _nc_captoinfo(const char *cap, const char *s, int const parametrized) if (capstart) { dp = save_string(dp, "$<"); for (s = capstart;; s++) - if (isdigit(CharOf(*s)) || *s == '*' || *s == '.') + if (isdigit(UChar(*s)) || *s == '*' || *s == '.') dp = save_char(dp, *s); else break; @@ -573,8 +574,8 @@ bcd_expression(const char *str) char ch1, ch2; if (sscanf(str, fmt, &ch1, &ch2) == 2 - && isdigit(CharOf(ch1)) - && isdigit(CharOf(ch2)) + && isdigit(UChar(ch1)) + && isdigit(UChar(ch2)) && (ch1 == ch2)) { len = 28; #ifndef NDEBUG @@ -640,8 +641,8 @@ save_tc_inequality(char *bufptr, int c1, int c2) * Convert a terminfo string to termcap format. Parameters are as in * _nc_captoinfo(). */ -char * -_nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrized) +NCURSES_EXPORT(char *) +_nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized) { int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0; const char *padding; @@ -655,13 +656,13 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrize padding = str + strlen(str) - 1; if (padding > str && *padding == '>' && *--padding == '/') { --padding; - while (isdigit(CharOf(*padding)) || *padding == '.' || *padding == '*') + while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') padding--; if (padding > str && *padding == '<' && *--padding == '$') trimmed = padding; padding += 2; - while (isdigit(CharOf(*padding)) || *padding == '.' || *padding == '*') + while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') bufptr = save_char(bufptr, *padding++); } @@ -673,7 +674,7 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrize bufptr = save_char(bufptr, *++str); } else if (str[0] == '$' && str[1] == '<') { /* discard padding */ str += 2; - while (isdigit(CharOf(*str)) + while (isdigit(UChar(*str)) || *str == '.' || *str == '*' || *str == '/' @@ -682,7 +683,8 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrize --str; } else if (str[0] == '%' && str[1] == '%') { /* escaped '%' */ bufptr = save_string(bufptr, "%%"); - } else if (*str != '%' || (parametrized < 1)) { + ++str; + } else if (*str != '%' || (parameterized < 1)) { bufptr = save_char(bufptr, *str); } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) { str = strchr(str, ';'); @@ -741,7 +743,7 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrize case '8': case '9': bufptr = save_char(bufptr, '%'); - while (isdigit(CharOf(*str))) + while (isdigit(UChar(*str))) bufptr = save_char(bufptr, *str++); if (strchr("doxX.", *str)) { if (*str != 'd') /* termcap doesn't have octal, hex */ @@ -790,6 +792,11 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrize } /* endswitch (*str) */ } /* endelse (*str == '%') */ + /* + * 'str' always points to the end of what was scanned in this step, + * but that may not be the end of the string. + */ + assert(str != 0); if (*str == '\0') break; @@ -807,7 +814,7 @@ main(int argc, char *argv[]) { int c, tc = FALSE; - while ((c = getopt(argc, argv, "c")) != -1) + while ((c = getopt(argc, argv, "c")) != EOF) switch (c) { case 'c': tc = TRUE; @@ -817,7 +824,6 @@ main(int argc, char *argv[]) curr_line = 0; for (;;) { char buf[BUFSIZ]; - size_t buflen; ++curr_line; if (fgets(buf, sizeof(buf), stdin) == NULL) @@ -840,4 +846,13 @@ main(int argc, char *argv[]) } #endif /* MAIN */ -/* captoinfo.c ends here */ +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_captoinfo_leaks(void) +{ + if (my_string != 0) { + FreeAndNull(my_string); + } + my_length = 0; +} +#endif diff --git a/lib/libcurses/tinfo/comp_error.c b/lib/libcurses/tinfo/comp_error.c index 13259e1efc4..319bd5fb35b 100644 --- a/lib/libcurses/tinfo/comp_error.c +++ b/lib/libcurses/tinfo/comp_error.c @@ -1,7 +1,7 @@ -/* $OpenBSD: comp_error.c,v 1.5 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: comp_error.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -42,48 +43,62 @@ #include <tic.h> -MODULE_ID("$From: comp_error.c,v 1.21 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: comp_error.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT_VAR(bool) _nc_suppress_warnings = FALSE; -NCURSES_EXPORT_VAR(int) -_nc_curr_line = 0; /* current line # in input */ -NCURSES_EXPORT_VAR(int) -_nc_curr_col = 0; /* current column # in input */ +NCURSES_EXPORT_VAR(int) _nc_curr_line = 0; /* current line # in input */ +NCURSES_EXPORT_VAR(int) _nc_curr_col = 0; /* current column # in input */ - static const char *sourcename; - static char termtype[MAX_NAME_SIZE + 1]; +#define SourceName _nc_globals.comp_sourcename +#define TermType _nc_globals.comp_termtype + +NCURSES_EXPORT(const char *) +_nc_get_source(void) +{ + return SourceName; +} NCURSES_EXPORT(void) _nc_set_source(const char *const name) { - sourcename = name; + SourceName = name; } NCURSES_EXPORT(void) _nc_set_type(const char *const name) { - if (name) - strlcpy(termtype, name, sizeof(termtype)); - else - termtype[0] = '\0'; + if (TermType == 0) + TermType = typeMalloc(char, MAX_NAME_SIZE + 1); + if (TermType != 0) { + TermType[0] = '\0'; + if (name) + strncat(TermType, name, MAX_NAME_SIZE); + } } NCURSES_EXPORT(void) _nc_get_type(char *name) { - strlcpy(name, termtype, MAX_NAME_SIZE + 1); +#if NO_LEAKS + if (name == 0 && TermType != 0) { + FreeAndNull(TermType); + return; + } +#endif + if (name != 0) + strlcpy(name, TermType != 0 ? TermType : "", MAX_NAME_SIZE + 1); } -static inline void +static NCURSES_INLINE void where_is_problem(void) { - fprintf(stderr, "\"%s\"", sourcename); + fprintf(stderr, "\"%s\"", SourceName ? SourceName : "?"); if (_nc_curr_line >= 0) fprintf(stderr, ", line %d", _nc_curr_line); if (_nc_curr_col >= 0) fprintf(stderr, ", col %d", _nc_curr_col); - if (termtype[0]) - fprintf(stderr, ", terminal '%s'", termtype); + if (TermType != 0 && TermType[0] != '\0') + fprintf(stderr, ", terminal '%s'", TermType); fputc(':', stderr); fputc(' ', stderr); } diff --git a/lib/libcurses/tinfo/comp_expand.c b/lib/libcurses/tinfo/comp_expand.c index e78d365168c..598592856da 100644 --- a/lib/libcurses/tinfo/comp_expand.c +++ b/lib/libcurses/tinfo/comp_expand.c @@ -1,7 +1,7 @@ -/* $OpenBSD: comp_expand.c,v 1.6 2007/06/02 01:29:11 pvalchev Exp $ */ +/* $OpenBSD: comp_expand.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,7 +37,7 @@ #include <ctype.h> #include <tic.h> -MODULE_ID("$From: comp_expand.c,v 1.15 2000/12/10 01:30:10 tom Exp $") +MODULE_ID("$Id: comp_expand.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") static int trailing_spaces(const char *src) @@ -48,30 +48,37 @@ trailing_spaces(const char *src) } /* this deals with differences over whether 0x7f and 0x80..0x9f are controls */ -#define CHAR_OF(s) (*(unsigned const char *)(s)) -#define REALCTL(s) (CHAR_OF(s) < 127 && iscntrl(CHAR_OF(s))) -#define REALPRINT(s) (CHAR_OF(s) < 127 && isprint(CHAR_OF(s))) +#define REALCTL(s) (UChar(*(s)) < 127 && iscntrl(UChar(*(s)))) +#define REALPRINT(s) (UChar(*(s)) < 127 && isprint(UChar(*(s)))) NCURSES_EXPORT(char *) -_nc_tic_expand -(const char *srcp, bool tic_format, int numbers) +_nc_tic_expand(const char *srcp, bool tic_format, int numbers) { static char *buffer; static size_t length; int bufp; - const char *str = VALID_STRING(srcp) ? srcp : ""; + const char *str = VALID_STRING(srcp) ? srcp : "\0\0"; bool islong = (strlen(str) > 3); size_t need = (2 + strlen(str)) * 4; int ch; +#if NO_LEAKS + if (srcp == 0) { + if (buffer != 0) { + FreeAndNull(buffer); + length = 0; + } + return 0; + } +#endif if (buffer == 0 || need > length) { if ((buffer = typeRealloc(char, length = need, buffer)) == 0) return 0; } bufp = 0; - while ((ch = CharOf(*str)) != 0) { + while ((ch = UChar(*str)) != 0) { if (ch == '%' && REALPRINT(str + 1)) { buffer[bufp++] = *str++; /* @@ -101,7 +108,7 @@ _nc_tic_expand */ case 1: if (str[0] == L_BRACE - && isdigit(CharOf(str[1]))) { + && isdigit(UChar(str[1]))) { char *dst = 0; long value = strtol(str + 1, &dst, 0); if (dst != 0 @@ -114,7 +121,7 @@ _nc_tic_expand if (ch == '\\' || ch == S_QUOTE) buffer[bufp++] = '\\'; - buffer[bufp++] = ch; + buffer[bufp++] = (char) ch; buffer[bufp++] = S_QUOTE; str = dst; } else { @@ -143,13 +150,13 @@ _nc_tic_expand buffer[bufp++] = 's'; } else if ((ch == ',' || ch == ':' || ch == '^') && tic_format) { buffer[bufp++] = '\\'; - buffer[bufp++] = ch; + buffer[bufp++] = (char) ch; } else if (REALPRINT(str) && (ch != ',' && ch != ':' && !(ch == '!' && !tic_format) && ch != '^')) - buffer[bufp++] = ch; + buffer[bufp++] = (char) ch; #if 0 /* FIXME: this would be more readable (in fact the whole 'islong' logic should be removed) */ else if (ch == '\b') { buffer[bufp++] = '\\'; @@ -171,7 +178,7 @@ _nc_tic_expand } #define UnCtl(c) ((c) + '@') else if (REALCTL(str) && ch != '\\' - && (!islong || isdigit(CharOf(str[1])))) { + && (!islong || isdigit(UChar(str[1])))) { (void) snprintf(buffer + bufp, length - bufp, "^%c", UnCtl(ch)); bufp += strlen(buffer + bufp); } else { diff --git a/lib/libcurses/tinfo/comp_hash.c b/lib/libcurses/tinfo/comp_hash.c index a4b10f3c546..87856a7e040 100644 --- a/lib/libcurses/tinfo/comp_hash.c +++ b/lib/libcurses/tinfo/comp_hash.c @@ -1,7 +1,7 @@ -/* $OpenBSD: comp_hash.c,v 1.7 2007/03/20 03:40:06 tedu Exp $ */ +/* $OpenBSD: comp_hash.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,15 +31,16 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ - /* * comp_hash.c --- Routines to deal with the hashtable of capability * names. * */ +#define USE_TERMLIB 1 #include <curses.priv.h> #include <tic.h> @@ -48,12 +49,12 @@ #ifdef MAIN_PROGRAM #include <ctype.h> #undef DEBUG -#define DEBUG(level, params) /*nothing*/ +#define DEBUG(level, params) /*nothing */ #endif -MODULE_ID("$From: comp_hash.c,v 1.21 1999/06/26 21:25:11 tom Exp $") +MODULE_ID("$Id: comp_hash.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") -static int hash_function(const char *); +static int hash_function(const char *); /* * _nc_make_hash_table() @@ -67,59 +68,61 @@ static int hash_function(const char *); #ifdef MAIN_PROGRAM #undef MODULE_ID -#define MODULE_ID(id) /*nothing*/ +#define MODULE_ID(id) /*nothing */ #include <tinfo/doalloc.c> -static void _nc_make_hash_table(struct name_table_entry *table, - struct name_table_entry **hash_table) +static void +_nc_make_hash_table(struct name_table_entry *table, + short *hash_table) { -int i; -int hashvalue; -int collisions = 0; - - for (i = 0; i < CAPTABSIZE; i++) { - hashvalue = hash_function(table[i].nte_name); - - if (hash_table[hashvalue] != (struct name_table_entry *) 0) - collisions++; - - if (hash_table[hashvalue] != 0) - table[i].nte_link = (short)(hash_table[hashvalue] - table); - hash_table[hashvalue] = &table[i]; - } - - DEBUG(4, ("Hash table complete: %d collisions out of %d entries", collisions, CAPTABSIZE)); + short i; + int hashvalue; + int collisions = 0; + + for (i = 0; i < HASHTABSIZE; i++) { + hash_table[i] = -1; + } + for (i = 0; i < CAPTABSIZE; i++) { + hashvalue = hash_function(table[i].nte_name); + + if (hash_table[hashvalue] >= 0) + collisions++; + + if (hash_table[hashvalue] != 0) + table[i].nte_link = hash_table[hashvalue]; + hash_table[hashvalue] = i; + } + + DEBUG(4, ("Hash table complete: %d collisions out of %d entries", + collisions, CAPTABSIZE)); } #endif - /* * int hash_function(string) * * Computes the hashing function on the given string. * * The current hash function is the sum of each consectutive pair - * of characters, taken as two-byte integers, mod Hashtabsize. + * of characters, taken as two-byte integers, mod HASHTABSIZE. * */ -static -int +static int hash_function(const char *string) { -long sum = 0; + long sum = 0; - DEBUG(9, ("hashing %s", string)); - while (*string) { - sum += (long)(*string + (*(string + 1) << 8)); - string++; - } + DEBUG(9, ("hashing %s", string)); + while (*string) { + sum += (long) (*string + (*(string + 1) << 8)); + string++; + } - DEBUG(9, ("sum is %ld", sum)); - return (int)(sum % HASHTABSIZE); + DEBUG(9, ("sum is %ld", sum)); + return (int) (sum % HASHTABSIZE); } - /* * struct name_table_entry * * find_entry(string) @@ -130,23 +133,27 @@ long sum = 0; */ #ifndef MAIN_PROGRAM -struct name_table_entry const * -_nc_find_entry(const char *string, const struct name_table_entry *const *hash_table) +NCURSES_EXPORT(struct name_table_entry const *) +_nc_find_entry(const char *string, + const short *hash_table) { -int hashvalue; -struct name_table_entry const *ptr; - - hashvalue = hash_function(string); - - if ((ptr = hash_table[hashvalue]) != 0) { - while (strcmp(ptr->nte_name, string) != 0) { - if (ptr->nte_link < 0) - return 0; - ptr = ptr->nte_link + hash_table[HASHTABSIZE]; - } + int hashvalue; + struct name_table_entry const *ptr = 0; + struct name_table_entry const *real_table; + + hashvalue = hash_function(string); + + if (hash_table[hashvalue] >= 0) { + real_table = _nc_get_table(hash_table != _nc_get_hash_table(FALSE)); + ptr = real_table + hash_table[hashvalue]; + while (strcmp(ptr->nte_name, string) != 0) { + if (ptr->nte_link < 0) + return 0; + ptr = real_table + (ptr->nte_link + hash_table[HASHTABSIZE]); } + } - return (ptr); + return (ptr); } /* @@ -160,19 +167,19 @@ struct name_table_entry const *ptr; * in the table or 0 if not found. */ -struct name_table_entry const * +NCURSES_EXPORT(struct name_table_entry const *) _nc_find_type_entry(const char *string, int type, const struct name_table_entry *table) { -struct name_table_entry const *ptr; + struct name_table_entry const *ptr; - for (ptr = table; ptr < table + CAPTABSIZE; ptr++) { - if (ptr->nte_type == type && strcmp(string, ptr->nte_name) == 0) - return(ptr); - } + for (ptr = table; ptr < table + CAPTABSIZE; ptr++) { + if (ptr->nte_type == type && strcmp(string, ptr->nte_name) == 0) + return (ptr); + } - return ((struct name_table_entry *)NULL); + return ((struct name_table_entry *) NULL); } #endif @@ -189,140 +196,177 @@ struct name_table_entry const *ptr; #define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ -static char **parse_columns(char *buffer) +static char ** +parse_columns(char *buffer) { - static char **list; - - int col = 0; - - if (list == 0 && (list = typeCalloc(char *, MAX_COLUMNS)) == 0) - return(0); - - if (*buffer != '#') { - while (*buffer != '\0') { - char *s; - for (s = buffer; (*s != '\0') && !isspace(*s); s++) - /*EMPTY*/; - if (s != buffer) { - char mark = *s; - *s = '\0'; - if ((s - buffer) > 1 - && (*buffer == '"') - && (s[-1] == '"')) { /* strip the quotes */ - buffer++; - s[-1] = '\0'; - } - list[col] = buffer; - col++; - if (mark == '\0') - break; - while (isspace(*++s)) - /*EMPTY*/; - buffer = s; - } else - break; + static char **list; + + int col = 0; + + if (list == 0 && (list = typeCalloc(char *, MAX_COLUMNS)) == 0) + return (0); + + if (*buffer != '#') { + while (*buffer != '\0') { + char *s; + for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) + /*EMPTY */ ; + if (s != buffer) { + char mark = *s; + *s = '\0'; + if ((s - buffer) > 1 + && (*buffer == '"') + && (s[-1] == '"')) { /* strip the quotes */ + assert(s > buffer + 1); + s[-1] = '\0'; + buffer++; } + list[col] = buffer; + col++; + if (mark == '\0') + break; + while (*++s && isspace(UChar(*s))) + /*EMPTY */ ; + buffer = s; + } else + break; } - return col ? list : 0; + } + return col ? list : 0; } -int main(int argc, char **argv) +int +main(int argc, char **argv) { - struct name_table_entry *name_table = typeCalloc(struct name_table_entry, CAPTABSIZE); - struct name_table_entry **hash_table = typeCalloc(struct name_table_entry *, HASHTABSIZE); - const char *root_name = ""; - int column = 0; - int n; - char buffer[BUFSIZ]; - - static const char * typenames[] = { "BOOLEAN", "NUMBER", "STRING" }; - - short BoolCount = 0; - short NumCount = 0; - short StrCount = 0; - - /* The first argument is the column-number (starting with 0). - * The second is the root name of the tables to generate. - */ - if (argc <= 2 - || (column = atoi(argv[1])) <= 0 - || (column >= MAX_COLUMNS) - || *(root_name = argv[2]) == 0) { - fprintf(stderr, "usage: make_hash column root_name\n"); - exit(EXIT_FAILURE); + struct name_table_entry *name_table = typeCalloc(struct + name_table_entry, CAPTABSIZE); + short *hash_table = typeCalloc(short, HASHTABSIZE); + const char *root_name = ""; + int column = 0; + int bigstring = 0; + int n; + char buffer[BUFSIZ]; + + static const char *typenames[] = + {"BOOLEAN", "NUMBER", "STRING"}; + + short BoolCount = 0; + short NumCount = 0; + short StrCount = 0; + + /* The first argument is the column-number (starting with 0). + * The second is the root name of the tables to generate. + */ + if (argc <= 3 + || (column = atoi(argv[1])) <= 0 + || (column >= MAX_COLUMNS) + || *(root_name = argv[2]) == 0 + || (bigstring = atoi(argv[3])) < 0 + || name_table == 0 + || hash_table == 0) { + fprintf(stderr, "usage: make_hash column root_name bigstring\n"); + exit(EXIT_FAILURE); + } + + /* + * Read the table into our arrays. + */ + for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { + char **list, *nlp = strchr(buffer, '\n'); + if (nlp) + *nlp = '\0'; + list = parse_columns(buffer); + if (list == 0) /* blank or comment */ + continue; + name_table[n].nte_link = -1; /* end-of-hash */ + name_table[n].nte_name = strdup(list[column]); + if (!strcmp(list[2], "bool")) { + name_table[n].nte_type = BOOLEAN; + name_table[n].nte_index = BoolCount++; + } else if (!strcmp(list[2], "num")) { + name_table[n].nte_type = NUMBER; + name_table[n].nte_index = NumCount++; + } else if (!strcmp(list[2], "str")) { + name_table[n].nte_type = STRING; + name_table[n].nte_index = StrCount++; + } else { + fprintf(stderr, "Unknown type: %s\n", list[2]); + exit(EXIT_FAILURE); } - - /* - * Read the table into our arrays. - */ - for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin); ) { - char **list, *nlp = strchr(buffer, '\n'); - if (nlp) - *nlp = '\0'; - list = parse_columns(buffer); - if (list == 0) /* blank or comment */ - continue; - name_table[n].nte_link = -1; /* end-of-hash */ - name_table[n].nte_name = strdup(list[column]); - if (!strcmp(list[2], "bool")) { - name_table[n].nte_type = BOOLEAN; - name_table[n].nte_index = BoolCount++; - } else if (!strcmp(list[2], "num")) { - name_table[n].nte_type = NUMBER; - name_table[n].nte_index = NumCount++; - } else if (!strcmp(list[2], "str")) { - name_table[n].nte_type = STRING; - name_table[n].nte_index = StrCount++; - } else { - fprintf(stderr, "Unknown type: %s\n", list[2]); - exit(EXIT_FAILURE); - } - n++; + n++; + } + _nc_make_hash_table(name_table, hash_table); + + /* + * Write the compiled tables to standard output + */ + if (bigstring) { + int len = 0; + int nxt; + + printf("static const char %s_names_text[] = \\\n", root_name); + for (n = 0; n < CAPTABSIZE; n++) { + nxt = (int) strlen(name_table[n].nte_name) + 5; + if (nxt + len > 72) { + printf("\\\n"); + len = 0; + } + printf("\"%s\\0\" ", name_table[n].nte_name); + len += nxt; } - _nc_make_hash_table(name_table, hash_table); + printf(";\n\n"); - /* - * Write the compiled tables to standard output - */ - printf("static struct name_table_entry const _nc_%s_table[] =\n", - root_name); + len = 0; + printf("static name_table_data const %s_names_data[] =\n", + root_name); printf("{\n"); for (n = 0; n < CAPTABSIZE; n++) { - snprintf(buffer, sizeof(buffer), "\"%s\"", - name_table[n].nte_name); - printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", - buffer, - typenames[name_table[n].nte_type], - name_table[n].nte_index, - name_table[n].nte_link, - n < CAPTABSIZE - 1 ? ',' : ' '); + printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", + len, + typenames[name_table[n].nte_type], + name_table[n].nte_index, + name_table[n].nte_link, + n < CAPTABSIZE - 1 ? ',' : ' '); + len += (int) strlen(name_table[n].nte_name) + 1; } printf("};\n\n"); + printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); + } else { - printf("const struct name_table_entry * const _nc_%s_hash_table[%d] =\n", - root_name, - HASHTABSIZE+1); + printf("static struct name_table_entry %s _nc_%s_table[] =\n", + bigstring ? "" : "const", + root_name); printf("{\n"); - for (n = 0; n < HASHTABSIZE; n++) { - if (hash_table[n] != 0) { - snprintf(buffer, sizeof(buffer), "_nc_%s_table + %3ld", - root_name, - (long) (hash_table[n] - name_table)); - } else { - buffer[0] = '0'; - buffer[1] = '\0'; - } - printf("\t%s,\n", buffer); + for (n = 0; n < CAPTABSIZE; n++) { + snprintf(buffer, sizeof(buffer), "\"%s\"", + name_table[n].nte_name); + printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", + buffer, + typenames[name_table[n].nte_type], + name_table[n].nte_index, + name_table[n].nte_link, + n < CAPTABSIZE - 1 ? ',' : ' '); } - printf("\t_nc_%s_table\t/* base-of-table */\n", root_name); printf("};\n\n"); - - printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", - BoolCount, NumCount, StrCount); - printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); - printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); - printf("#endif\n\n"); - - return EXIT_SUCCESS; + } + + printf("static const short _nc_%s_hash_table[%d] =\n", + root_name, + HASHTABSIZE + 1); + printf("{\n"); + for (n = 0; n < HASHTABSIZE; n++) { + printf("\t%3d,\n", hash_table[n]); + } + printf("\t0\t/* base-of-table */\n"); + printf("};\n\n"); + + printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", + BoolCount, NumCount, StrCount); + printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); + printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); + printf("#endif\n\n"); + + free(hash_table); + return EXIT_SUCCESS; } #endif diff --git a/lib/libcurses/tinfo/comp_parse.c b/lib/libcurses/tinfo/comp_parse.c index 4c9b83497d3..1cf53acb120 100644 --- a/lib/libcurses/tinfo/comp_parse.c +++ b/lib/libcurses/tinfo/comp_parse.c @@ -1,7 +1,7 @@ -/* $OpenBSD: comp_parse.c,v 1.11 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: comp_parse.c,v 1.12 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,18 +31,19 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* * comp_parse.c -- parser driver loop and use handling. * * _nc_read_entry_source(FILE *, literal, bool, bool (*hook)()) - * _nc_resolve_uses(void) + * _nc_resolve_uses2(void) * _nc_free_entries(void) * * Use this code by calling _nc_read_entry_source() on as many source * files as you like (either terminfo or termcap syntax). If you - * want use-resolution, call _nc_resolve_uses(). To free the list + * want use-resolution, call _nc_resolve_uses2(). To free the list * storage, do _nc_free_entries(). * */ @@ -54,43 +55,23 @@ #include <tic.h> #include <term_entry.h> -MODULE_ID("$From: comp_parse.c,v 1.48 2001/01/15 00:44:51 tom Exp $") +MODULE_ID("$Id: comp_parse.c,v 1.12 2010/01/12 23:22:06 nicm Exp $") +static void sanity_check2(TERMTYPE *, bool); +NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanity_check2; + +/* obsolete: 20040705 */ static void sanity_check(TERMTYPE *); NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype) (TERMTYPE *) = sanity_check; -/**************************************************************************** - * - * Entry queue handling - * - ****************************************************************************/ -/* - * The entry list is a doubly linked list with NULLs terminating the lists: - * - * --------- --------- --------- - * | | | | | | offset - * |-------| |-------| |-------| - * | ----+-->| ----+-->| NULL | next - * |-------| |-------| |-------| - * | NULL |<--+---- |<--+---- | last - * --------- --------- --------- - * ^ ^ - * | | - * | | - * _nc_head _nc_tail - */ - -NCURSES_EXPORT_VAR(ENTRY *) _nc_head = 0; -NCURSES_EXPORT_VAR(ENTRY *) _nc_tail = 0; - - static void - enqueue(ENTRY * ep) +static void +enqueue(ENTRY * ep) /* add an entry to the in-core list */ { ENTRY *newp = _nc_copy_entry(ep); if (newp == 0) - _nc_err_abort("Out of memory"); + _nc_err_abort(MSG_NO_MEMORY); newp->last = _nc_tail; _nc_tail = newp; @@ -100,43 +81,18 @@ NCURSES_EXPORT_VAR(ENTRY *) _nc_tail = 0; newp->last->next = newp; } -NCURSES_EXPORT(void) -_nc_free_entries(ENTRY * headp) -/* free the allocated storage consumed by list entries */ -{ - ENTRY *ep, *next; - - for (ep = headp; ep; ep = next) { - /* - * This conditional lets us disconnect storage from the list. - * To do this, copy an entry out of the list, then null out - * the string-table member in the original and any use entries - * it references. - */ - FreeIfNeeded(ep->tterm.str_table); - - next = ep->next; - - free(ep); - if (ep == _nc_head) - _nc_head = 0; - if (ep == _nc_tail) - _nc_tail = 0; - } -} - static char * force_bar(char *dst, char *src, size_t siz) { if (strchr(src, '|') == 0) { - size_t len; - - len = strlcpy(dst, src, siz); - if (len > siz - 2) - len = siz - 2; - dst[len++] = '|'; - dst[len] = '\0'; - src = dst; + size_t len; + + len = strlcpy(dst, src, siz); + if (len > siz - 2) + len = siz - 2; + dst[len++] = '|'; + dst[len] = '\0'; + src = dst; } return src; } @@ -167,7 +123,7 @@ _nc_entry_match(char *n1, char *n2) ****************************************************************************/ NCURSES_EXPORT(void) -_nc_read_entry_source(FILE * fp, char *buf, +_nc_read_entry_source(FILE *fp, char *buf, int literal, bool silent, bool(*hook) (ENTRY *)) /* slurp all entries in the given file into core */ @@ -184,18 +140,29 @@ _nc_read_entry_source(FILE * fp, char *buf, memset(&thisentry, 0, sizeof(thisentry)); if (_nc_parse_entry(&thisentry, literal, silent) == ERR) break; - if (!isalnum(CharOf(thisentry.tterm.term_names[0]))) + if (!isalnum(UChar(thisentry.tterm.term_names[0]))) _nc_err_abort("terminal names must start with letter or digit"); /* - * This can be used for immediate compilation of entries with no - * use references to disk, so as to avoid chewing up a lot of - * core when the resolution code could fetch entries off disk. + * This can be used for immediate compilation of entries with no "use=" + * references to disk. That avoids consuming a lot of memory when the + * resolution code could fetch entries off disk. */ - if (hook != NULLHOOK && (*hook) (&thisentry)) + if (hook != NULLHOOK && (*hook) (&thisentry)) { immediate++; - else + } else { enqueue(&thisentry); + /* + * The enqueued entry is copied with _nc_copy_termtype(), so we can + * free some of the data from thisentry, i.e., the arrays. + */ + FreeIfNeeded(thisentry.tterm.Booleans); + FreeIfNeeded(thisentry.tterm.Numbers); + FreeIfNeeded(thisentry.tterm.Strings); +#if NCURSES_XNAMES + FreeIfNeeded(thisentry.tterm.ext_Names); +#endif + } } if (_nc_tail) { @@ -215,12 +182,13 @@ _nc_read_entry_source(FILE * fp, char *buf, } NCURSES_EXPORT(int) -_nc_resolve_uses(bool fullresolve) +_nc_resolve_uses2(bool fullresolve, bool literal) /* try to resolve all use capabilities */ { ENTRY *qp, *rp, *lastread = 0; bool keepgoing; - int i, j, unresolved, total_unresolved, multiples; + unsigned i; + int unresolved, total_unresolved, multiples; DEBUG(2, ("RESOLUTION BEGINNING")); @@ -293,7 +261,7 @@ _nc_resolve_uses(bool fullresolve) rp = typeMalloc(ENTRY, 1); if (rp == 0) - _nc_err_abort("Out of memory"); + _nc_err_abort(MSG_NO_MEMORY); rp->tterm = thisterm; rp->nuses = 0; rp->next = lastread; @@ -324,8 +292,8 @@ _nc_resolve_uses(bool fullresolve) DEBUG(2, ("NAME RESOLUTION COMPLETED OK")); /* - * OK, at this point all (char *) references in `name' mwmbers - * have been successfully converred to (ENTRY *) pointers in + * OK, at this point all (char *) references in `name' members + * have been successfully converted to (ENTRY *) pointers in * `link' members. Time to do the actual merges. */ if (fullresolve) { @@ -351,10 +319,10 @@ _nc_resolve_uses(bool fullresolve) } /* - * First, make sure there's no garbage in the - * merge block. as a side effect, copy into - * the merged entry the name field and string - * table pointer. + * First, make sure there is no garbage in the + * merge block. As a side effect, copy into + * the merged entry the name field and string + * table pointer. */ _nc_copy_termtype(&merged, &(qp->tterm)); @@ -377,6 +345,9 @@ _nc_resolve_uses(bool fullresolve) FreeIfNeeded(qp->tterm.Booleans); FreeIfNeeded(qp->tterm.Numbers); FreeIfNeeded(qp->tterm.Strings); +#if NCURSES_XNAMES + FreeIfNeeded(qp->tterm.ext_Names); +#endif qp->tterm = merged; _nc_wrap_entry(qp, TRUE); @@ -393,26 +364,6 @@ _nc_resolve_uses(bool fullresolve) (keepgoing); DEBUG(2, ("MERGES COMPLETED OK")); - - /* - * The exit condition of the loop above is such that all entries - * must now be resolved. Now handle cancellations. In a resolved - * entry there should be no cancellation markers. - */ - for_entry_list(qp) { - for_each_boolean(j, &(qp->tterm)) { - if ((int) qp->tterm.Booleans[j] == CANCELLED_BOOLEAN) - qp->tterm.Booleans[j] = ABSENT_BOOLEAN; - } - for_each_number(j, &(qp->tterm)) { - if (qp->tterm.Numbers[j] == CANCELLED_NUMERIC) - qp->tterm.Numbers[j] = ABSENT_NUMERIC; - } - for_each_string(j, &(qp->tterm)) { - if (qp->tterm.Strings[j] == CANCELLED_STRING) - qp->tterm.Strings[j] = ABSENT_STRING; - } - } } /* @@ -430,7 +381,7 @@ _nc_resolve_uses(bool fullresolve) for_entry_list(qp) { _nc_curr_line = qp->startline; _nc_set_type(_nc_first_name(qp->tterm.term_names)); - _nc_check_termtype(&qp->tterm); + _nc_check_termtype2(&qp->tterm, literal); } DEBUG(2, ("SANITY CHECK FINISHED")); } @@ -438,6 +389,13 @@ _nc_resolve_uses(bool fullresolve) return (TRUE); } +/* obsolete: 20040705 */ +NCURSES_EXPORT(int) +_nc_resolve_uses(bool fullresolve) +{ + return _nc_resolve_uses2(fullresolve, FALSE); +} + /* * This bit of legerdemain turns all the terminfo variable names into * references to locations in the arrays Booleans, Numbers, and Strings --- @@ -448,7 +406,7 @@ _nc_resolve_uses(bool fullresolve) #define CUR tp-> static void -sanity_check(TERMTYPE * tp) +sanity_check2(TERMTYPE *tp, bool literal) { if (!PRESENT(exit_attribute_mode)) { #ifdef __UNUSED__ /* this casts too wide a net */ @@ -465,14 +423,24 @@ sanity_check(TERMTYPE * tp) || PRESENT(enter_reverse_mode))) _nc_warning("no exit_attribute_mode"); #endif /* __UNUSED__ */ - PAIRED(enter_standout_mode, exit_standout_mode) - PAIRED(enter_underline_mode, exit_underline_mode) + PAIRED(enter_standout_mode, exit_standout_mode); + PAIRED(enter_underline_mode, exit_underline_mode); + } + + /* we do this check/fix in postprocess_termcap(), but some packagers + * prefer to bypass it... + */ + if (!literal) { + if (acs_chars == 0 + && enter_alt_charset_mode != 0 + && exit_alt_charset_mode != 0) + acs_chars = strdup(VT_ACSC); + ANDMISSING(enter_alt_charset_mode, acs_chars); + ANDMISSING(exit_alt_charset_mode, acs_chars); } /* listed in structure-member order of first argument */ PAIRED(enter_alt_charset_mode, exit_alt_charset_mode); - ANDMISSING(enter_alt_charset_mode, acs_chars); - ANDMISSING(exit_alt_charset_mode, acs_chars); ANDMISSING(enter_blink_mode, exit_attribute_mode); ANDMISSING(enter_bold_mode, exit_attribute_mode); PAIRED(exit_ca_mode, enter_ca_mode); @@ -490,6 +458,38 @@ sanity_check(TERMTYPE * tp) PAIRED(enter_xon_mode, exit_xon_mode); PAIRED(enter_am_mode, exit_am_mode); ANDMISSING(label_off, label_on); +#ifdef remove_clock PAIRED(display_clock, remove_clock); +#endif ANDMISSING(set_color_pair, initialize_pair); } + +/* obsolete: 20040705 */ +static void +sanity_check(TERMTYPE *tp) +{ + sanity_check2(tp, FALSE); +} + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_leaks_tic(void) +{ + _nc_alloc_entry_leaks(); + _nc_captoinfo_leaks(); + _nc_comp_captab_leaks(); + _nc_comp_scan_leaks(); +#if BROKEN_LINKER || USE_REENTRANT + _nc_names_leaks(); + _nc_codes_leaks(); +#endif + _nc_tic_expand(0, FALSE, 0); +} + +NCURSES_EXPORT(void) +_nc_free_tic(int code) +{ + _nc_leaks_tic(); + _nc_free_tinfo(code); +} +#endif diff --git a/lib/libcurses/tinfo/comp_scan.c b/lib/libcurses/tinfo/comp_scan.c index a241322f188..ff3b9ac7ff2 100644 --- a/lib/libcurses/tinfo/comp_scan.c +++ b/lib/libcurses/tinfo/comp_scan.c @@ -1,5 +1,7 @@ +/* $OpenBSD: comp_scan.c,v 1.15 2010/01/12 23:22:06 nicm Exp $ */ + /**************************************************************************** - * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * + * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996 on * ****************************************************************************/ /* @@ -50,7 +53,7 @@ #include <term_entry.h> #include <tic.h> -MODULE_ID("$From: comp_scan.c,v 1.54 2001/02/04 01:09:26 tom Exp $") +MODULE_ID("$Id: comp_scan.c,v 1.15 2010/01/12 23:22:06 nicm Exp $") /* * Maximum length of string capability we'll accept before raising an error. @@ -84,23 +87,207 @@ _nc_curr_token = *****************************************************************************/ static bool first_column; /* See 'next_char()' below */ +static bool had_newline; static char separator; /* capability separator */ static int pushtype; /* type of pushback token */ -static char pushname[MAX_NAME_SIZE + 1]; +static char *pushname; #if NCURSES_EXT_FUNCS NCURSES_EXPORT_VAR(bool) _nc_disable_period = FALSE; /* used by tic -a option */ #endif -static int last_char(void); -static int next_char(void); -static long stream_pos(void); -static bool end_of_stream(void); -static void push_back(char c); +/***************************************************************************** + * + * Character-stream handling + * + *****************************************************************************/ + +#define LEXBUFSIZ 1024 + +static char *bufptr; /* otherwise, the input buffer pointer */ +static char *bufstart; /* start of buffer so we can compute offsets */ +static FILE *yyin; /* scanner's input file descriptor */ + +/* + * _nc_reset_input() + * + * Resets the input-reading routines. Used on initialization, + * or after a seek has been done. Exactly one argument must be + * non-null. + */ + +NCURSES_EXPORT(void) +_nc_reset_input(FILE *fp, char *buf) +{ + pushtype = NO_PUSHBACK; + if (pushname != 0) + pushname[0] = '\0'; + yyin = fp; + bufstart = bufptr = buf; + _nc_curr_file_pos = 0L; + if (fp != 0) + _nc_curr_line = 0; + _nc_curr_col = 0; +} + +/* + * int last_char() + * + * Returns the final nonblank character on the current input buffer + */ +static int +last_char(void) +{ + size_t len = strlen(bufptr); + while (len--) { + if (!isspace(UChar(bufptr[len]))) + return bufptr[len]; + } + return 0; +} + +/* + * int next_char() + * + * Returns the next character in the input stream. Comments and leading + * white space are stripped. + * + * The global state variable 'firstcolumn' is set TRUE if the character + * returned is from the first column of the input line. + * + * The global variable _nc_curr_line is incremented for each new line. + * The global variable _nc_curr_file_pos is set to the file offset of the + * beginning of each line. + */ + +static int +next_char(void) +{ + static char *result; + static size_t allocated; + int the_char; + + if (!yyin) { + if (result != 0) { + FreeAndNull(result); + FreeAndNull(pushname); + allocated = 0; + } + /* + * An string with an embedded null will truncate the input. This is + * intentional (we don't read binary files here). + */ + if (bufptr == 0 || *bufptr == '\0') + return (EOF); + if (*bufptr == '\n') { + _nc_curr_line++; + _nc_curr_col = 0; + } else if (*bufptr == '\t') { + _nc_curr_col = (_nc_curr_col | 7); + } + } else if (!bufptr || !*bufptr) { + /* + * In theory this could be recoded to do its I/O one character at a + * time, saving the buffer space. In practice, this turns out to be + * quite hard to get completely right. Try it and see. If you + * succeed, don't forget to hack push_back() correspondingly. + */ + size_t used; + size_t len; + + do { + bufstart = 0; + used = 0; + do { + if (used + (LEXBUFSIZ / 4) >= allocated) { + allocated += (allocated + LEXBUFSIZ); + result = typeRealloc(char, allocated, result); + if (result == 0) + return (EOF); + bufstart = result; + } + if (used == 0) + _nc_curr_file_pos = ftell(yyin); + + if (fgets(result + used, (int) (allocated - used), yyin) != 0) { + bufstart = result; + if (used == 0) { + _nc_curr_line++; + _nc_curr_col = 0; + } + } else { + if (used != 0) + strlcat(result, "\n", allocated); + } + if ((bufptr = bufstart) != 0) { + used = strlen(bufptr); + while (iswhite(*bufptr)) { + if (*bufptr == '\t') { + _nc_curr_col = (_nc_curr_col | 7) + 1; + } else { + _nc_curr_col++; + } + bufptr++; + } + + /* + * Treat a trailing <cr><lf> the same as a <newline> so we + * can read files on OS/2, etc. + */ + if ((len = strlen(bufptr)) > 1) { + if (bufptr[len - 1] == '\n' + && bufptr[len - 2] == '\r') { + len--; + bufptr[len - 1] = '\n'; + bufptr[len] = '\0'; + } + } + } else { + return (EOF); + } + } while (bufptr[len - 1] != '\n'); /* complete a line */ + } while (result[0] == '#'); /* ignore comments */ + } else if (*bufptr == '\t') { + _nc_curr_col = (_nc_curr_col | 7); + } + + first_column = (bufptr == bufstart); + if (first_column) + had_newline = FALSE; + + _nc_curr_col++; + the_char = *bufptr++; + return UChar(the_char); +} + +static void +push_back(char c) +/* push a character back onto the input stream */ +{ + if (bufptr == bufstart) + _nc_syserr_abort("Can't backspace off beginning of line"); + *--bufptr = c; + _nc_curr_col--; +} + +static long +stream_pos(void) +/* return our current character position in the input stream */ +{ + return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0)); +} + +static bool +end_of_stream(void) +/* are we at end of input? */ +{ + return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0')) + ? TRUE : FALSE); +} /* Assume we may be looking at a termcap-style continuation */ -static inline int +static NCURSES_INLINE int eat_escaped_newline(int ch) { if (ch == '\\') @@ -109,6 +296,15 @@ eat_escaped_newline(int ch) return ch; } +#define TOK_BUF_SIZE MAX_ENTRY_SIZE + +#define OkToAdd() \ + ((tok_ptr - tok_buf) < (TOK_BUF_SIZE - 2)) + +#define AddCh(ch) \ + *tok_ptr++ = (char) ch; \ + *tok_ptr = '\0' + /* * int * get_token() @@ -146,41 +342,65 @@ NCURSES_EXPORT(int) _nc_get_token(bool silent) { static const char terminfo_punct[] = "@%&*!#"; - long number; - int type; - int ch; + static char *tok_buf; + + char *after_list; + char *after_name; char *numchk; + char *tok_ptr; + char *s; char numbuf[80]; - unsigned found; - static char buffer[MAX_ENTRY_SIZE]; - char *ptr; + int ch; int dot_flag = FALSE; + int type; + long number; long token_start; + unsigned found; +#ifdef TRACE + int old_line; + int old_col; +#endif if (pushtype != NO_PUSHBACK) { int retval = pushtype; - _nc_set_type(pushname); + _nc_set_type(pushname != 0 ? pushname : ""); DEBUG(3, ("pushed-back token: `%s', class %d", _nc_curr_token.tk_name, pushtype)); pushtype = NO_PUSHBACK; - pushname[0] = '\0'; + if (pushname != 0) + pushname[0] = '\0'; /* currtok wasn't altered by _nc_push_token() */ return (retval); } - if (end_of_stream()) + if (end_of_stream()) { + yyin = 0; + next_char(); /* frees its allocated memory */ + if (tok_buf != 0) { + if (_nc_curr_token.tk_name == tok_buf) + _nc_curr_token.tk_name = 0; + FreeAndNull(tok_buf); + } return (EOF); + } start_token: token_start = stream_pos(); - while ((ch = next_char()) == '\n' || iswhite(ch)) + while ((ch = next_char()) == '\n' || iswhite(ch)) { + if (ch == '\n') + had_newline = TRUE; continue; + } ch = eat_escaped_newline(ch); +#ifdef TRACE + old_line = _nc_curr_line; + old_col = _nc_curr_col; +#endif if (ch == EOF) type = EOF; else { @@ -206,33 +426,44 @@ _nc_get_token(bool silent) } /* have to make some punctuation chars legal for terminfo */ - if (!isalnum(ch) + if (!isalnum(UChar(ch)) #if NCURSES_EXT_FUNCS && !(ch == '.' && _nc_disable_period) #endif && !strchr(terminfo_punct, (char) ch)) { if (!silent) - _nc_warning("Illegal character (expected alphanumeric or %s) - %s", + _nc_warning("Illegal character (expected alphanumeric or %s) - '%s'", terminfo_punct, unctrl((chtype) ch)); _nc_panic_mode(separator); goto start_token; } - ptr = buffer; - *(ptr++) = ch; + if (tok_buf == 0) + tok_buf = typeMalloc(char, TOK_BUF_SIZE); - if (first_column) { - char *desc; +#ifdef TRACE + old_line = _nc_curr_line; + old_col = _nc_curr_col; +#endif + tok_ptr = tok_buf; + AddCh(ch); + if (first_column) { _nc_comment_start = token_start; _nc_comment_end = _nc_curr_file_pos; _nc_start_line = _nc_curr_line; _nc_syntax = ERR; + after_name = 0; + after_list = 0; while ((ch = next_char()) != '\n') { - if (ch == EOF) - _nc_err_abort("premature EOF"); - else if (ch == ':' && last_char() != ',') { + if (ch == EOF) { + _nc_err_abort(MSG_NO_INPUTS); + } else if (ch == '|') { + after_list = tok_ptr; + if (after_name == 0) + after_name = tok_ptr; + } else if (ch == ':' && last_char() != ',') { _nc_syntax = SYN_TERMCAP; separator = ':'; break; @@ -240,20 +471,29 @@ _nc_get_token(bool silent) _nc_syntax = SYN_TERMINFO; separator = ','; /* - * Fall-through here is not an accident. The idea is that - * if we see a comma, we figure this is terminfo unless we - * subsequently run into a colon -- but we don't stop - * looking for that colon until hitting a newline. This + * If we did not see a '|', then we found a name with no + * aliases or description. + */ + if (after_name == 0) + break; + /* + * If we see a comma, we assume this is terminfo unless we + * subsequently run into a colon. But we don't stop + * looking for a colon until hitting a newline. This * allows commas to be embedded in description fields of * either syntax. */ - /* FALLTHRU */ } else ch = eat_escaped_newline(ch); - *ptr++ = ch; + if (OkToAdd()) { + AddCh(ch); + } else { + ch = EOF; + break; + } } - ptr[0] = '\0'; + *tok_ptr = '\0'; if (_nc_syntax == ERR) { /* * Grrr...what we ought to do here is barf, complaining that @@ -265,65 +505,71 @@ _nc_get_token(bool silent) separator = ':'; } else if (_nc_syntax == SYN_TERMINFO) { /* throw away trailing /, *$/ */ - for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--) + for (--tok_ptr; + iswhite(*tok_ptr) || *tok_ptr == ','; + tok_ptr--) continue; - ptr[1] = '\0'; + tok_ptr[1] = '\0'; } /* * This is the soonest we have the terminal name fetched. Set up - * for following warning messages. + * for following warning messages. If there's no '|', then there + * is no description. */ - ptr = strchr(buffer, '|'); - if (ptr == (char *) NULL) - ptr = buffer + strlen(buffer); - ch = *ptr; - *ptr = '\0'; - _nc_set_type(buffer); - *ptr = ch; + if (after_name != 0) { + ch = *after_name; + *after_name = '\0'; + _nc_set_type(tok_buf); + *after_name = (char) ch; + } /* * Compute the boundary between the aliases and the description * field for syntax-checking purposes. */ - desc = strrchr(buffer, '|'); - if (!silent && desc) { - if (*desc == '\0') - _nc_warning("empty longname field"); - else if (strchr(desc, ' ') == (char *) NULL) - _nc_warning("older tic versions may treat the description field as an alias"); + if (after_list != 0) { + if (!silent) { + if (*after_list == '\0') + _nc_warning("empty longname field"); + else if (strchr(after_list, ' ') == 0) + _nc_warning("older tic versions may treat the description field as an alias"); + } + } else { + after_list = tok_buf + strlen(tok_buf); + DEBUG(1, ("missing description")); } - if (!desc) - desc = buffer + strlen(buffer); /* * Whitespace in a name field other than the long name can confuse * rdist and some termcap tools. Slashes are a no-no. Other * special characters can be dangerous due to shell expansion. */ - for (ptr = buffer; ptr < desc; ptr++) { - if (isspace(CharOf(*ptr))) { + for (s = tok_buf; s < after_list; ++s) { + if (isspace(UChar(*s))) { if (!silent) _nc_warning("whitespace in name or alias field"); break; - } else if (*ptr == '/') { + } else if (*s == '/') { if (!silent) _nc_warning("slashes aren't allowed in names or aliases"); break; - } else if (strchr("$[]!*?", *ptr)) { + } else if (strchr("$[]!*?", *s)) { if (!silent) - _nc_warning("dubious character `%c' in name or alias field", *ptr); + _nc_warning("dubious character `%c' in name or alias field", *s); break; } } - ptr = buffer; - - _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_name = tok_buf; type = NAMES; } else { + if (had_newline && _nc_syntax == SYN_TERMCAP) { + _nc_warning("Missing backslash before newline"); + had_newline = FALSE; + } while ((ch = next_char()) != EOF) { - if (!isalnum(ch)) { + if (!isalnum(UChar(ch))) { if (_nc_syntax == SYN_TERMINFO) { if (ch != '_') break; @@ -332,30 +578,35 @@ _nc_get_token(bool silent) break; } } - *(ptr++) = ch; + if (OkToAdd()) { + AddCh(ch); + } else { + ch = EOF; + break; + } } - *ptr++ = '\0'; + *tok_ptr++ = '\0'; /* separate name/value in buffer */ switch (ch) { case ',': case ':': if (ch != separator) _nc_err_abort("Separator inconsistent with syntax"); - _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_name = tok_buf; type = BOOLEAN; break; case '@': if ((ch = next_char()) != separator && !silent) _nc_warning("Missing separator after `%s', have %s", - buffer, unctrl((chtype) ch)); - _nc_curr_token.tk_name = buffer; + tok_buf, unctrl((chtype) ch)); + _nc_curr_token.tk_name = tok_buf; type = CANCEL; break; case '#': found = 0; while (isalnum(ch = next_char())) { - numbuf[found++] = ch; + numbuf[found++] = (char) ch; if (found >= sizeof(numbuf) - 1) break; } @@ -363,21 +614,21 @@ _nc_get_token(bool silent) number = strtol(numbuf, &numchk, 0); if (!silent) { if (numchk == numbuf) - _nc_warning("no value given for `%s'", buffer); + _nc_warning("no value given for `%s'", tok_buf); if ((*numchk != '\0') || (ch != separator)) _nc_warning("Missing separator"); } - _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_name = tok_buf; _nc_curr_token.tk_valnumber = number; type = NUMBER; break; case '=': - ch = _nc_trans_string(ptr, buffer + sizeof(buffer)); + ch = _nc_trans_string(tok_ptr, tok_buf + TOK_BUF_SIZE); if (!silent && ch != separator) _nc_warning("Missing separator"); - _nc_curr_token.tk_name = buffer; - _nc_curr_token.tk_valstring = ptr; + _nc_curr_token.tk_name = tok_buf; + _nc_curr_token.tk_valstring = tok_ptr; type = STRING; break; @@ -388,7 +639,7 @@ _nc_get_token(bool silent) /* just to get rid of the compiler warning */ type = UNDEF; if (!silent) - _nc_warning("Illegal character - %s", unctrl((chtype) ch)); + _nc_warning("Illegal character - '%s'", unctrl((chtype) ch)); } } /* end else (first_column == FALSE) */ } /* end else (ch != EOF) */ @@ -399,6 +650,11 @@ _nc_get_token(bool silent) if (dot_flag == TRUE) DEBUG(8, ("Commented out ")); + if (_nc_tracing >= DEBUG_LEVEL(8)) { + _tracef("parsed %d.%d to %d.%d", + old_line, old_col, + _nc_curr_line, _nc_curr_col); + } if (_nc_tracing >= DEBUG_LEVEL(7)) { switch (type) { case BOOLEAN: @@ -443,8 +699,9 @@ _nc_get_token(bool silent) type = _nc_get_token(silent); DEBUG(3, ("token: `%s', class %d", - _nc_curr_token.tk_name != 0 ? _nc_curr_token.tk_name : - "<null>", + ((_nc_curr_token.tk_name != 0) + ? _nc_curr_token.tk_name + : "<null>"), type)); return (type); @@ -469,7 +726,7 @@ _nc_get_token(bool silent) * */ -NCURSES_EXPORT(char) +NCURSES_EXPORT(int) _nc_trans_string(char *ptr, char *last) { int count = 0; @@ -480,17 +737,24 @@ _nc_trans_string(char *ptr, char *last) bool long_warning = FALSE; while ((ch = c = next_char()) != (chtype) separator && c != EOF) { - if (ptr == (last - 1)) + if (ptr >= (last - 1)) { + if (c != EOF) { + while ((c = next_char()) != separator && c != EOF) { + ; + } + ch = c; + } break; + } if ((_nc_syntax == SYN_TERMCAP) && c == '\n') break; if (ch == '^' && last_ch != '%') { ch = c = next_char(); if (c == EOF) - _nc_err_abort("Premature EOF"); + _nc_err_abort(MSG_NO_INPUTS); if (!(is7bits(ch) && isprint(ch))) { - _nc_warning("Illegal ^ character - %s", unctrl(ch)); + _nc_warning("Illegal ^ character - '%s'", unctrl(ch)); } if (ch == '?') { *(ptr++) = '\177'; @@ -504,14 +768,14 @@ _nc_trans_string(char *ptr, char *last) } else if (ch == '\\') { ch = c = next_char(); if (c == EOF) - _nc_err_abort("Premature EOF"); + _nc_err_abort(MSG_NO_INPUTS); if (ch >= '0' && ch <= '7') { number = ch - '0'; for (i = 0; i < 2; i++) { ch = c = next_char(); if (c == EOF) - _nc_err_abort("Premature EOF"); + _nc_err_abort(MSG_NO_INPUTS); if (c < '0' || c > '7') { if (isdigit(c)) { @@ -585,21 +849,31 @@ _nc_trans_string(char *ptr, char *last) continue; default: - _nc_warning("Illegal character %s in \\ sequence", + _nc_warning("Illegal character '%s' in \\ sequence", unctrl(ch)); + /* FALLTHRU */ + case '|': *(ptr++) = (char) ch; } /* endswitch (ch) */ } /* endelse (ch < '0' || ch > '7') */ } /* end else if (ch == '\\') */ else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) { - /* newlines embedded in a terminfo string are ignored */ + /* + * Newlines embedded in a terminfo string are ignored, provided + * that the next line begins with whitespace. + */ ignored = TRUE; } else { *(ptr++) = (char) ch; } if (!ignored) { + if (_nc_curr_col <= 1) { + push_back((char) ch); + ch = '\n'; + break; + } last_ch = ch; count++; } @@ -629,14 +903,19 @@ _nc_push_token(int tokclass) /* * This implementation is kind of bogus, it will fail if we ever do more * than one pushback at a time between get_token() calls. It relies on the - * fact that curr_tok is static storage that nothing but get_token() - * touches. + * fact that _nc_curr_token is static storage that nothing but + * _nc_get_token() touches. */ pushtype = tokclass; + if (pushname == 0) + pushname = typeMalloc(char, MAX_NAME_SIZE + 1); _nc_get_type(pushname); DEBUG(3, ("pushing token: `%s', class %d", - _nc_curr_token.tk_name, pushtype)); + ((_nc_curr_token.tk_name != 0) + ? _nc_curr_token.tk_name + : "<null>"), + pushtype)); } /* @@ -656,168 +935,12 @@ _nc_panic_mode(char ch) } } -/***************************************************************************** - * - * Character-stream handling - * - *****************************************************************************/ - -#define LEXBUFSIZ 1024 - -static char *bufptr; /* otherwise, the input buffer pointer */ -static char *bufstart; /* start of buffer so we can compute offsets */ -static FILE *yyin; /* scanner's input file descriptor */ - -/* - * _nc_reset_input() - * - * Resets the input-reading routines. Used on initialization, - * or after a seek has been done. Exactly one argument must be - * non-null. - */ - +#if NO_LEAKS NCURSES_EXPORT(void) -_nc_reset_input(FILE * fp, char *buf) -{ - pushtype = NO_PUSHBACK; - pushname[0] = '\0'; - yyin = fp; - bufstart = bufptr = buf; - _nc_curr_file_pos = 0L; - if (fp != 0) - _nc_curr_line = 0; - _nc_curr_col = 0; -} - -/* - * int last_char() - * - * Returns the final nonblank character on the current input buffer - */ -static int -last_char(void) -{ - size_t len = strlen(bufptr); - while (len--) { - if (!isspace(CharOf(bufptr[len]))) - return bufptr[len]; - } - return 0; -} - -/* - * int next_char() - * - * Returns the next character in the input stream. Comments and leading - * white space are stripped. - * - * The global state variable 'firstcolumn' is set TRUE if the character - * returned is from the first column of the input line. - * - * The global variable _nc_curr_line is incremented for each new line. - * The global variable _nc_curr_file_pos is set to the file offset of the - * beginning of each line. - */ - -static int -next_char(void) +_nc_comp_scan_leaks(void) { - if (!yyin) { - /* - * An string with an embedded null will truncate the input. This is - * intentional (we don't read binary files here). - */ - if (*bufptr == '\0') - return (EOF); - if (*bufptr == '\n') { - _nc_curr_line++; - _nc_curr_col = 0; - } - } else if (!bufptr || !*bufptr) { - /* - * In theory this could be recoded to do its I/O one character at a - * time, saving the buffer space. In practice, this turns out to be - * quite hard to get completely right. Try it and see. If you - * succeed, don't forget to hack push_back() correspondingly. - */ - static char *result; - static size_t allocated; - size_t used; - size_t len; - - do { - bufstart = 0; - used = 0; - do { - if (used + (LEXBUFSIZ / 4) >= allocated) { - allocated += (allocated + LEXBUFSIZ); - result = _nc_doalloc(result, allocated); - if (result == 0) - return (EOF); - } - if (used == 0) - _nc_curr_file_pos = ftell(yyin); - - if (fgets(result + used, allocated - used, yyin) != NULL) { - bufstart = result; - if (used == 0) { - _nc_curr_line++; - _nc_curr_col = 0; - } - } else { - if (used != 0) - strlcat(result, "\n", allocated); - } - if ((bufptr = bufstart) != 0) { - used = strlen(bufptr); - while (iswhite(*bufptr)) - bufptr++; - - /* - * Treat a trailing <cr><lf> the same as a <newline> so we - * can read files on OS/2, etc. - */ - if ((len = strlen(bufptr)) > 1) { - if (bufptr[len - 1] == '\n' - && bufptr[len - 2] == '\r') { - len--; - bufptr[len - 1] = '\n'; - bufptr[len] = '\0'; - } - } - } else { - return (EOF); - } - } while (bufptr[len - 1] != '\n'); /* complete a line */ - } while (result[0] == '#'); /* ignore comments */ + if (pushname != 0) { + FreeAndNull(pushname); } - - first_column = (bufptr == bufstart); - - _nc_curr_col++; - return (*bufptr++); -} - -static void -push_back(char c) -/* push a character back onto the input stream */ -{ - if (bufptr == bufstart) - _nc_syserr_abort("Can't backspace off beginning of line"); - *--bufptr = c; -} - -static long -stream_pos(void) -/* return our current character position in the input stream */ -{ - return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0)); -} - -static bool -end_of_stream(void) -/* are we at end of input? */ -{ - return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0')) - ? TRUE : FALSE); } +#endif diff --git a/lib/libcurses/tinfo/db_iterator.c b/lib/libcurses/tinfo/db_iterator.c new file mode 100644 index 00000000000..84418492672 --- /dev/null +++ b/lib/libcurses/tinfo/db_iterator.c @@ -0,0 +1,227 @@ +/* $OpenBSD: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ + +/**************************************************************************** + * Copyright (c) 2006,2007 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* + * Iterators for terminal databases. + */ + +#include <curses.priv.h> + +#include <tic.h> + +MODULE_ID("$Id: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") + +#define HaveTicDirectory _nc_globals.have_tic_directory +#define KeepTicDirectory _nc_globals.keep_tic_directory +#define TicDirectory _nc_globals.tic_directory + +/* + * Record the "official" location of the terminfo directory, according to + * the place where we're writing to, or the normal default, if not. + */ +NCURSES_EXPORT(const char *) +_nc_tic_dir(const char *path) +{ + if (!KeepTicDirectory) { + if (path != 0) { + TicDirectory = path; + HaveTicDirectory = TRUE; + } else if (!HaveTicDirectory && use_terminfo_vars()) { + char *envp; + if ((envp = getenv("TERMINFO")) != 0) + return _nc_tic_dir(envp); + } + } + return TicDirectory; +} + +/* + * Special fix to prevent the terminfo directory from being moved after tic + * has chdir'd to it. If we let it be changed, then if $TERMINFO has a + * relative path, we'll lose track of the actual directory. + */ +NCURSES_EXPORT(void) +_nc_keep_tic_dir(const char *path) +{ + _nc_tic_dir(path); + KeepTicDirectory = TRUE; +} + +/* + * Process the list of :-separated directories, looking for the terminal type. + * We don't use strtok because it does not show us empty tokens. + */ +#define ThisDbList _nc_globals.dbi_list +#define ThisDbSize _nc_globals.dbi_size + +/* + * Cleanup. + */ +NCURSES_EXPORT(void) +_nc_last_db(void) +{ + if (ThisDbList != 0) { + FreeAndNull(ThisDbList); + } + ThisDbSize = 0; +} + +/* The TERMINFO_DIRS value, if defined by the configure script, begins with a + * ":", which will be interpreted as TERMINFO. + */ +static const char * +next_list_item(const char *source, int *offset) +{ + if (source != 0) { + FreeIfNeeded(ThisDbList); + ThisDbList = strdup(source); + ThisDbSize = strlen(source); + } + + if (ThisDbList != 0 && ThisDbSize && *offset < ThisDbSize) { + static char system_db[] = TERMINFO; + char *result = ThisDbList + *offset; + char *marker = strchr(result, NCURSES_PATHSEP); + + /* + * Put a null on the marker if a separator was found. Set the offset + * to the next position after the marker so we can call this function + * again, using the data at the offset. + */ + if (marker == 0) { + *offset += strlen(result) + 1; + marker = result + *offset; + } else { + *marker++ = 0; + *offset = marker - ThisDbList; + } + if (*result == 0 && result != (ThisDbList + ThisDbSize)) + result = system_db; + return result; + } + return 0; +} + +#define NEXT_DBD(var, offset) next_list_item((*offset == 0) ? var : 0, offset) + +/* + * This is a simple iterator which allows the caller to step through the + * possible locations for a terminfo directory. ncurses uses this to find + * terminfo files to read. + */ +NCURSES_EXPORT(const char *) +_nc_next_db(DBDIRS * state, int *offset) +{ + const char *result; + char *envp; + + while (*state < dbdLAST) { + DBDIRS next = (DBDIRS) ((int) (*state) + 1); + + result = 0; + + switch (*state) { + case dbdTIC: + if (HaveTicDirectory) + result = _nc_tic_dir(0); + break; +#if USE_DATABASE + case dbdEnvOnce: + if (use_terminfo_vars()) { + if ((envp = getenv("TERMINFO")) != 0) + result = _nc_tic_dir(envp); + } + break; + case dbdHome: + if (use_terminfo_vars()) { + result = _nc_home_terminfo(); + } + break; + case dbdEnvList: + if (use_terminfo_vars()) { + if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0) + next = *state; + } + break; + case dbdCfgList: +#ifdef TERMINFO_DIRS + if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0) + next = *state; +#endif + break; + case dbdCfgOnce: +#ifndef TERMINFO_DIRS + result = TERMINFO; +#endif + break; +#endif /* USE_DATABASE */ +#if USE_TERMCAP + case dbdEnvOnce2: + if (use_terminfo_vars()) { + if ((envp = getenv("TERMCAP")) != 0) + result = _nc_tic_dir(envp); + } + break; + case dbdEnvList2: + if (use_terminfo_vars()) { + if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0) + next = *state; + } + break; + case dbdCfgList2: + if ((result = NEXT_DBD(TERMPATH, offset)) != 0) + next = *state; + break; +#endif /* USE_TERMCAP */ + case dbdLAST: + break; + } + if (*state != next) { + *state = next; + *offset = 0; + _nc_last_db(); + } + if (result != 0) { + return result; + } + } + return 0; +} + +NCURSES_EXPORT(void) +_nc_first_db(DBDIRS * state, int *offset) +{ + *state = dbdTIC; + *offset = 0; +} diff --git a/lib/libcurses/tinfo/doalloc.c b/lib/libcurses/tinfo/doalloc.c index 54659f55888..a28a5cbdffb 100644 --- a/lib/libcurses/tinfo/doalloc.c +++ b/lib/libcurses/tinfo/doalloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: doalloc.c,v 1.6 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: doalloc.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** * Copyright (c) 1998,2000 Free Software Foundation, Inc. * @@ -41,7 +41,7 @@ #include <curses.priv.h> -MODULE_ID("$From: doalloc.c,v 1.7 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: doalloc.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(void *) _nc_doalloc(void *oldp, size_t amount) @@ -54,7 +54,7 @@ _nc_doalloc(void *oldp, size_t amount) errno = ENOMEM; /* just in case 'free' reset */ } } else { - newp = typeMalloc(char, amount); + newp = malloc(amount); } return newp; } @@ -67,7 +67,7 @@ _nc_strdup(const char *src) size_t dsize; if (src != 0) { dsize = strlen(src) + 1; - dst = typeMalloc(char, dsize); + dst = typeMalloc(char, strlen(src) + 1); if (dst != 0) { (void) strlcpy(dst, src, dsize); } diff --git a/lib/libcurses/tinfo/entries.c b/lib/libcurses/tinfo/entries.c new file mode 100644 index 00000000000..ad76fadfb83 --- /dev/null +++ b/lib/libcurses/tinfo/entries.c @@ -0,0 +1,147 @@ +/* $OpenBSD: entries.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ + +/**************************************************************************** + * Copyright (c) 2006-2007,2008 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +#include <curses.priv.h> + +#include <ctype.h> + +#include <tic.h> +#include <term_entry.h> + +MODULE_ID("$Id: entries.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") + +/**************************************************************************** + * + * Entry queue handling + * + ****************************************************************************/ +/* + * The entry list is a doubly linked list with NULLs terminating the lists: + * + * --------- --------- --------- + * | | | | | | offset + * |-------| |-------| |-------| + * | ----+-->| ----+-->| NULL | next + * |-------| |-------| |-------| + * | NULL |<--+---- |<--+---- | last + * --------- --------- --------- + * ^ ^ + * | | + * | | + * _nc_head _nc_tail + */ + +NCURSES_EXPORT_VAR(ENTRY *) _nc_head = 0; +NCURSES_EXPORT_VAR(ENTRY *) _nc_tail = 0; + +NCURSES_EXPORT(void) +_nc_free_entry(ENTRY * headp, TERMTYPE *tterm) +/* free the allocated storage consumed by the given list entry */ +{ + ENTRY *ep; + + if ((ep = _nc_delink_entry(headp, tterm)) != 0) { + free(ep); + } +} + +NCURSES_EXPORT(void) +_nc_free_entries(ENTRY * headp) +/* free the allocated storage consumed by list entries */ +{ + (void) headp; /* unused - _nc_head is altered here! */ + + while (_nc_head != 0) { + _nc_free_termtype(&(_nc_head->tterm)); + } +} + +NCURSES_EXPORT(ENTRY *) +_nc_delink_entry(ENTRY * headp, TERMTYPE *tterm) +/* delink the allocated storage for the given list entry */ +{ + ENTRY *ep, *last; + + for (last = 0, ep = headp; ep != 0; last = ep, ep = ep->next) { + if (&(ep->tterm) == tterm) { + if (last != 0) { + last->next = ep->next; + } + if (ep == _nc_head) { + _nc_head = ep->next; + } + if (ep == _nc_tail) { + _nc_tail = last; + } + break; + } + } + return ep; +} + +NCURSES_EXPORT(void) +_nc_leaks_tinfo(void) +{ +#if NO_LEAKS + char *s; +#endif + + T((T_CALLED("_nc_free_tinfo()"))); +#if NO_LEAKS + _nc_free_tparm(); + _nc_tgetent_leaks(); + _nc_free_entries(_nc_head); + _nc_get_type(0); + _nc_first_name(0); + _nc_keyname_leaks(); +#if BROKEN_LINKER || USE_REENTRANT + _nc_names_leaks(); + _nc_codes_leaks(); + FreeIfNeeded(_nc_prescreen.real_acs_map); +#endif + + if ((s = _nc_home_terminfo()) != 0) + free(s); +#endif /* NO_LEAKS */ + returnVoid; +} + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_free_tinfo(int code) +{ + _nc_leaks_tinfo(); + exit(code); +} +#endif diff --git a/lib/libcurses/tinfo/free_ttype.c b/lib/libcurses/tinfo/free_ttype.c index 3fac7bc6122..a506df3eadf 100644 --- a/lib/libcurses/tinfo/free_ttype.c +++ b/lib/libcurses/tinfo/free_ttype.c @@ -1,7 +1,7 @@ -/* $OpenBSD: free_ttype.c,v 1.6 2007/04/16 11:53:38 otto Exp $ */ +/* $OpenBSD: free_ttype.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1999-2005,2006 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +29,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1999 * + * Author: Thomas E. Dickey 1999-on * ****************************************************************************/ /* @@ -45,11 +45,13 @@ #include <tic.h> #include <term_entry.h> -MODULE_ID("$From: free_ttype.c,v 1.7 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: free_ttype.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(void) -_nc_free_termtype(TERMTYPE * ptr) +_nc_free_termtype(TERMTYPE *ptr) { + T(("_nc_free_termtype(%s)", ptr->term_names)); + FreeIfNeeded(ptr->str_table); FreeIfNeeded(ptr->Booleans); FreeIfNeeded(ptr->Numbers); @@ -59,6 +61,7 @@ _nc_free_termtype(TERMTYPE * ptr) FreeIfNeeded(ptr->ext_Names); #endif memset(ptr, 0, sizeof(TERMTYPE)); + _nc_free_entry(_nc_head, ptr); } #if NCURSES_XNAMES @@ -68,7 +71,9 @@ NCURSES_EXPORT(int) use_extended_names(bool flag) { int oldflag = _nc_user_definable; + + T((T_CALLED("use_extended_names(%d)"), flag)); _nc_user_definable = flag; - return oldflag; + returnBool(oldflag); } #endif diff --git a/lib/libcurses/tinfo/getenv_num.c b/lib/libcurses/tinfo/getenv_num.c index 80723dbedf8..b4c91796ca5 100644 --- a/lib/libcurses/tinfo/getenv_num.c +++ b/lib/libcurses/tinfo/getenv_num.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getenv_num.c,v 1.2 2001/01/22 18:01:51 millert Exp $ */ +/* $OpenBSD: getenv_num.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** * Copyright (c) 1998,2000 Free Software Foundation, Inc. * @@ -38,7 +38,7 @@ #include <curses.priv.h> -MODULE_ID("$From: getenv_num.c,v 1.3 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: getenv_num.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(int) _nc_getenv_num(const char *name) diff --git a/lib/libcurses/tinfo/hashed_db.c b/lib/libcurses/tinfo/hashed_db.c new file mode 100644 index 00000000000..2ce463a707f --- /dev/null +++ b/lib/libcurses/tinfo/hashed_db.c @@ -0,0 +1,262 @@ +/* $OpenBSD: hashed_db.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ + +/**************************************************************************** + * Copyright (c) 2006 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey 2006 * + ****************************************************************************/ + +#include <curses.priv.h> +#include <tic.h> +#include <hashed_db.h> + +#if USE_HASHED_DB + +MODULE_ID("$Id: hashed_db.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") + +#if HASHED_DB_API >= 2 +static DBC *cursor; +#endif + +/* + * Open the database. + */ +NCURSES_EXPORT(DB *) +_nc_db_open(const char *path, bool modify) +{ + DB *result = 0; + +#if HASHED_DB_API >= 4 + db_create(&result, NULL, 0); + result->open(result, + NULL, + path, + NULL, + DB_HASH, + modify ? DB_CREATE : DB_RDONLY, + 0644); +#elif HASHED_DB_API >= 3 + db_create(&result, NULL, 0); + result->open(result, + path, + NULL, + DB_HASH, + modify ? DB_CREATE : DB_RDONLY, + 0644); +#elif HASHED_DB_API >= 2 + int code; + + if ((code = db_open(path, + DB_HASH, + modify ? DB_CREATE : DB_RDONLY, + 0644, + (DB_ENV *) 0, + (DB_INFO *) 0, + &result)) != 0) { + T(("cannot open %s: %s", path, strerror(code))); + result = 0; + } else { + T(("opened %s", path)); + } +#else + result = dbopen(path, + modify ? (O_CREAT | O_RDWR) : O_RDONLY, + 0644, + DB_HASH, + NULL); + if (result != 0) { + T(("opened %s", path)); + } +#endif + return result; +} + +/* + * Close the database. Do not attempt to use the 'db' handle after this call. + */ +NCURSES_EXPORT(int) +_nc_db_close(DB * db) +{ + int result; + +#if HASHED_DB_API >= 2 + result = db->close(db, 0); +#else + result = db->close(db); +#endif + return result; +} + +/* + * Write a record to the database. + * + * Returns 0 on success. + * + * FIXME: the FreeBSD cap_mkdb program assumes the database could have + * duplicates. There appears to be no good reason for that (review/fix). + */ +NCURSES_EXPORT(int) +_nc_db_put(DB * db, DBT * key, DBT * data) +{ + int result; +#if HASHED_DB_API >= 2 + /* remove any pre-existing value, since we do not want duplicates */ + (void) db->del(db, NULL, key, 0); + result = db->put(db, NULL, key, data, DB_NOOVERWRITE); +#else + result = db->put(db, key, data, R_NOOVERWRITE); +#endif + return result; +} + +/* + * Read a record from the database. + * + * Returns 0 on success. + */ +NCURSES_EXPORT(int) +_nc_db_get(DB * db, DBT * key, DBT * data) +{ + int result; + + memset(data, 0, sizeof(*data)); +#if HASHED_DB_API >= 2 + result = db->get(db, NULL, key, data, 0); +#else + result = db->get(db, key, data, 0); +#endif + return result; +} + +/* + * Read the first record from the database, ignoring order. + * + * Returns 0 on success. + */ +NCURSES_EXPORT(int) +_nc_db_first(DB * db, DBT * key, DBT * data) +{ + int result; + + memset(key, 0, sizeof(*key)); + memset(data, 0, sizeof(*data)); +#if HASHED_DB_API >= 2 + if ((result = db->cursor(db, NULL, &cursor, 0)) == 0) { + result = cursor->c_get(cursor, key, data, DB_FIRST); + } +#else + result = db->seq(db, key, data, 0); +#endif + return result; +} + +/* + * Read the next record from the database, ignoring order. + * + * Returns 0 on success. + */ +NCURSES_EXPORT(int) +_nc_db_next(DB * db, DBT * key, DBT * data) +{ + int result; + +#if HASHED_DB_API >= 2 + (void) db; + if (cursor != 0) { + result = cursor->c_get(cursor, key, data, DB_NEXT); + } else { + result = -1; + } +#else + result = db->seq(db, key, data, 0); +#endif + return result; +} + +/* + * Check if a record is a terminfo index record. Index records are those that + * contain only an alias pointing to a list of aliases. + */ +NCURSES_EXPORT(bool) +_nc_db_have_index(DBT * key, DBT * data, char **buffer, int *size) +{ + bool result = FALSE; + int used = data->size - 1; + char *have = (char *) data->data; + + (void) key; + if (*have++ == 2) { + result = TRUE; + } + /* + * Update params in any case for consistency with _nc_db_have_data(). + */ + *buffer = have; + *size = used; + return result; +} + +/* + * Check if a record is the terminfo data record. Ignore index records, e.g., + * those that contain only an alias pointing to a list of aliases. + */ +NCURSES_EXPORT(bool) +_nc_db_have_data(DBT * key, DBT * data, char **buffer, int *size) +{ + bool result = FALSE; + int used = data->size - 1; + char *have = (char *) data->data; + + if (*have++ == 0) { + if (data->size > key->size + && IS_TIC_MAGIC(have)) { + result = TRUE; + } + } + /* + * Update params in any case to make it simple to follow a index record + * to the data record. + */ + *buffer = have; + *size = used; + return result; +} + +#else + +extern +NCURSES_EXPORT(void) +_nc_hashed_db(void); + +NCURSES_EXPORT(void) +_nc_hashed_db(void) +{ +} + +#endif /* USE_HASHED_DB */ diff --git a/lib/libcurses/tinfo/home_terminfo.c b/lib/libcurses/tinfo/home_terminfo.c index 955955484fc..a33924aa46a 100644 --- a/lib/libcurses/tinfo/home_terminfo.c +++ b/lib/libcurses/tinfo/home_terminfo.c @@ -1,7 +1,7 @@ -/* $OpenBSD: home_terminfo.c,v 1.8 2003/03/17 19:16:59 millert Exp $ */ +/* $OpenBSD: home_terminfo.c,v 1.9 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +29,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1998,2000 * + * Author: Thomas E. Dickey * ****************************************************************************/ /* @@ -39,29 +39,31 @@ #include <curses.priv.h> #include <tic.h> -MODULE_ID("$From: home_terminfo.c,v 1.6 2000/12/10 02:55:07 tom Exp $") - -#define my_length (strlen(home) + sizeof(PRIVATE_INFO)) +MODULE_ID("$Id: home_terminfo.c,v 1.9 2010/01/12 23:22:06 nicm Exp $") /* ncurses extension...fall back on user's private directory */ +#define MyBuffer _nc_globals.home_terminfo + NCURSES_EXPORT(char *) _nc_home_terminfo(void) { + char *result = 0; +#if USE_HOME_TERMINFO char *home; - static char *temp = 0; if (use_terminfo_vars()) { - if (temp == 0) { - if ((home = getenv("HOME")) != 0 && *home != '\0' - && my_length <= PATH_MAX) { - temp = typeMalloc(char, my_length); - if (temp == 0) - _nc_err_abort("Out of memory"); - (void) snprintf(temp, my_length, PRIVATE_INFO, home); + if (MyBuffer == 0) { + if ((home = getenv("HOME")) != 0 && *home != '\0') { + size_t want = (strlen(home) + sizeof(PRIVATE_INFO)); + MyBuffer = typeMalloc(char, want); + if (MyBuffer == 0) + _nc_err_abort(MSG_NO_MEMORY); + (void) snprintf(MyBuffer, want, PRIVATE_INFO, home); } } - return temp; + result = MyBuffer; } - return 0; +#endif + return result; } diff --git a/lib/libcurses/tinfo/init_keytry.c b/lib/libcurses/tinfo/init_keytry.c index 083861d2690..05bc1b62343 100644 --- a/lib/libcurses/tinfo/init_keytry.c +++ b/lib/libcurses/tinfo/init_keytry.c @@ -1,7 +1,7 @@ -/* $OpenBSD: init_keytry.c,v 1.5 2001/01/22 18:01:51 millert Exp $ */ +/* $OpenBSD: init_keytry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1999-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,11 +30,15 @@ #include <curses.priv.h> -#include <term.h> /* keypad_xmit, keypad_local, meta_on, meta_off */ - /* cursor_visible,cursor_normal,cursor_invisible */ +#include <term.h> +/* keypad_xmit, keypad_local, meta_on, meta_off */ +/* cursor_visible,cursor_normal,cursor_invisible */ + #include <tic.h> /* struct tinfo_fkeys */ -MODULE_ID("$From: init_keytry.c,v 1.5 2000/12/10 02:55:07 tom Exp $") +#include <term_entry.h> + +MODULE_ID("$Id: init_keytry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") /* ** _nc_init_keytry() @@ -43,6 +47,13 @@ MODULE_ID("$From: init_keytry.c,v 1.5 2000/12/10 02:55:07 tom Exp $") ** */ +/* + * Internal entrypoints use SCREEN* parameter to obtain capabilities rather + * than cur_term. + */ +#undef CUR +#define CUR (sp->_term)->type. + #if BROKEN_LINKER #undef _nc_tinfo_fkeys #endif @@ -54,7 +65,7 @@ MODULE_ID("$From: init_keytry.c,v 1.5 2000/12/10 02:55:07 tom Exp $") #endif*/ #if BROKEN_LINKER -struct tinfo_fkeys * +const struct tinfo_fkeys * _nc_tinfo_fkeysf(void) { return _nc_tinfo_fkeys; @@ -62,21 +73,47 @@ _nc_tinfo_fkeysf(void) #endif NCURSES_EXPORT(void) -_nc_init_keytry(void) +_nc_init_keytry(SCREEN *sp) { size_t n; - /* The SP->_keytry value is initialized in newterm(), where the SP + /* The sp->_keytry value is initialized in newterm(), where the sp * structure is created, because we can not tell where keypad() or * mouse_activate() (which will call keyok()) are first called. */ - for (n = 0; _nc_tinfo_fkeys[n].code; n++) - if (_nc_tinfo_fkeys[n].offset < STRCOUNT) - _nc_add_to_try(&(SP->_keytry), - CUR Strings[_nc_tinfo_fkeys[n].offset], - _nc_tinfo_fkeys[n].code); + if (sp != 0) { + for (n = 0; _nc_tinfo_fkeys[n].code; n++) { + if (_nc_tinfo_fkeys[n].offset < STRCOUNT) { + (void) _nc_add_to_try(&(sp->_keytry), + CUR Strings[_nc_tinfo_fkeys[n].offset], + _nc_tinfo_fkeys[n].code); + } + } +#if NCURSES_XNAMES + /* + * Add any of the extended strings to the tries if their name begins + * with 'k', i.e., they follow the convention of other terminfo key + * names. + */ + { + TERMTYPE *tp = &(sp->_term->type); + for (n = STRCOUNT; n < NUM_STRINGS(tp); ++n) { + const char *name = ExtStrname(tp, n, strnames); + char *value = tp->Strings[n]; + if (name != 0 + && *name == 'k' + && value != 0 + && key_defined(value) == 0) { + (void) _nc_add_to_try(&(sp->_keytry), + value, + n - STRCOUNT + KEY_MAX); + } + } + } +#endif #ifdef TRACE - _nc_trace_tries(SP->_keytry); + _nc_trace_tries(sp->_keytry); #endif + } } diff --git a/lib/libcurses/tinfo/keys.list b/lib/libcurses/tinfo/keys.list deleted file mode 100644 index 078c4747aa5..00000000000 --- a/lib/libcurses/tinfo/keys.list +++ /dev/null @@ -1,159 +0,0 @@ -# $OpenBSD: keys.list,v 1.1 1999/01/18 19:10:15 millert Exp $ -# $From: keys.list,v 1.5 1997/10/25 21:05:24 tom Exp $ -# The first column is the #define symbol that is in curses.h -# The second column is the term.h symbol, for terminfo -# Not all keycodes have corresponding terminfo capabilities. -KEY_A1 key_a1 -KEY_A3 key_a3 -KEY_B2 key_b2 -KEY_BACKSPACE key_backspace -KEY_BEG key_beg -KEY_BREAK -KEY_BTAB key_btab -KEY_C1 key_c1 -KEY_C3 key_c3 -KEY_CANCEL key_cancel -KEY_CATAB key_catab -KEY_CLEAR key_clear -KEY_CLOSE key_close -KEY_COMMAND key_command -KEY_COPY key_copy -KEY_CREATE key_create -KEY_CTAB key_ctab -KEY_DC key_dc -KEY_DL key_dl -KEY_DOWN key_down -KEY_EIC key_eic -KEY_END key_end -KEY_ENTER key_enter -KEY_EOL key_eol -KEY_EOS key_eos -KEY_EXIT key_exit -KEY_F(0) key_f0 -KEY_F(1) key_f1 -KEY_F(10) key_f10 -KEY_F(11) key_f11 -KEY_F(12) key_f12 -KEY_F(13) key_f13 -KEY_F(14) key_f14 -KEY_F(15) key_f15 -KEY_F(16) key_f16 -KEY_F(17) key_f17 -KEY_F(18) key_f18 -KEY_F(19) key_f19 -KEY_F(2) key_f2 -KEY_F(20) key_f20 -KEY_F(21) key_f21 -KEY_F(22) key_f22 -KEY_F(23) key_f23 -KEY_F(24) key_f24 -KEY_F(25) key_f25 -KEY_F(26) key_f26 -KEY_F(27) key_f27 -KEY_F(28) key_f28 -KEY_F(29) key_f29 -KEY_F(3) key_f3 -KEY_F(30) key_f30 -KEY_F(31) key_f31 -KEY_F(32) key_f32 -KEY_F(33) key_f33 -KEY_F(34) key_f34 -KEY_F(35) key_f35 -KEY_F(36) key_f36 -KEY_F(37) key_f37 -KEY_F(38) key_f38 -KEY_F(39) key_f39 -KEY_F(4) key_f4 -KEY_F(40) key_f40 -KEY_F(41) key_f41 -KEY_F(42) key_f42 -KEY_F(43) key_f43 -KEY_F(44) key_f44 -KEY_F(45) key_f45 -KEY_F(46) key_f46 -KEY_F(47) key_f47 -KEY_F(48) key_f48 -KEY_F(49) key_f49 -KEY_F(5) key_f5 -KEY_F(50) key_f50 -KEY_F(51) key_f51 -KEY_F(52) key_f52 -KEY_F(53) key_f53 -KEY_F(54) key_f54 -KEY_F(55) key_f55 -KEY_F(56) key_f56 -KEY_F(57) key_f57 -KEY_F(58) key_f58 -KEY_F(59) key_f59 -KEY_F(6) key_f6 -KEY_F(60) key_f60 -KEY_F(61) key_f61 -KEY_F(62) key_f62 -KEY_F(63) key_f63 -KEY_F(7) key_f7 -KEY_F(8) key_f8 -KEY_F(9) key_f9 -KEY_FIND key_find -KEY_HELP key_help -KEY_HOME key_home -KEY_IC key_ic -KEY_IL key_il -KEY_LEFT key_left -KEY_LL key_ll -KEY_MARK key_mark -KEY_MESSAGE key_message -KEY_MOUSE key_mouse -KEY_MOVE key_move -KEY_NEXT key_next -KEY_NPAGE key_npage -KEY_OPEN key_open -KEY_OPTIONS key_options -KEY_PPAGE key_ppage -KEY_PREVIOUS key_previous -KEY_PRINT key_print -KEY_REDO key_redo -KEY_REFERENCE key_reference -KEY_REFRESH key_refresh -KEY_REPLACE key_replace -KEY_RESET -KEY_RESIZE -KEY_RESTART key_restart -KEY_RESUME key_resume -KEY_RIGHT key_right -KEY_SAVE key_save -KEY_SBEG key_sbeg -KEY_SCANCEL key_scancel -KEY_SCOMMAND key_scommand -KEY_SCOPY key_scopy -KEY_SCREATE key_screate -KEY_SDC key_sdc -KEY_SDL key_sdl -KEY_SELECT key_select -KEY_SEND key_send -KEY_SEOL key_seol -KEY_SEXIT key_sexit -KEY_SF key_sf -KEY_SFIND key_sfind -KEY_SHELP key_shelp -KEY_SHOME key_shome -KEY_SIC key_sic -KEY_SLEFT key_sleft -KEY_SMESSAGE key_smessage -KEY_SMOVE key_smove -KEY_SNEXT key_snext -KEY_SOPTIONS key_soptions -KEY_SPREVIOUS key_sprevious -KEY_SPRINT key_sprint -KEY_SR key_sr -KEY_SREDO key_sredo -KEY_SREPLACE key_sreplace -KEY_SRESET -KEY_SRIGHT key_sright -KEY_SRSUME key_srsume -KEY_SSAVE key_ssave -KEY_SSUSPEND key_ssuspend -KEY_STAB key_stab -KEY_SUNDO key_sundo -KEY_SUSPEND key_suspend -KEY_UNDO key_undo -KEY_UP key_up diff --git a/lib/libcurses/tinfo/lib_acs.c b/lib/libcurses/tinfo/lib_acs.c index 9e406cf4d18..b5a5c12a4be 100644 --- a/lib/libcurses/tinfo/lib_acs.c +++ b/lib/libcurses/tinfo/lib_acs.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_acs.c,v 1.4 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_acs.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,128 +31,158 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ #include <curses.priv.h> #include <term.h> /* ena_acs, acs_chars */ -MODULE_ID("$From: lib_acs.c,v 1.18 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_acs.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +#if BROKEN_LINKER || USE_REENTRANT +#define MyBuffer _nc_prescreen.real_acs_map +NCURSES_EXPORT_VAR(chtype *) +_nc_acs_map(void) +{ + if (MyBuffer == 0) + MyBuffer = typeCalloc(chtype, ACS_LEN); + return MyBuffer; +} +#undef MyBuffer +#else NCURSES_EXPORT_VAR(chtype) acs_map[ACS_LEN] = { 0 }; +#endif NCURSES_EXPORT(void) _nc_init_acs(void) { + chtype *fake_map = acs_map; + chtype *real_map = SP != 0 ? SP->_acs_map : fake_map; + int j; + T(("initializing ACS map")); /* + * If we're using this from curses (rather than terminfo), we are storing + * the mapping information in the SCREEN struct so we can decide how to + * render it. + */ + if (real_map != fake_map) { + for (j = 1; j < ACS_LEN; ++j) { + real_map[j] = 0; + fake_map[j] = A_ALTCHARSET | j; + if (SP) + SP->_screen_acs_map[j] = FALSE; + } + } else { + for (j = 1; j < ACS_LEN; ++j) { + real_map[j] = 0; + } + } + + /* * Initializations for a UNIX-like multi-terminal environment. Use * ASCII chars and count on the terminfo description to do better. */ - ACS_ULCORNER = '+'; /* should be upper left corner */ - ACS_LLCORNER = '+'; /* should be lower left corner */ - ACS_URCORNER = '+'; /* should be upper right corner */ - ACS_LRCORNER = '+'; /* should be lower right corner */ - ACS_RTEE = '+'; /* should be tee pointing left */ - ACS_LTEE = '+'; /* should be tee pointing right */ - ACS_BTEE = '+'; /* should be tee pointing up */ - ACS_TTEE = '+'; /* should be tee pointing down */ - ACS_HLINE = '-'; /* should be horizontal line */ - ACS_VLINE = '|'; /* should be vertical line */ - ACS_PLUS = '+'; /* should be large plus or crossover */ - ACS_S1 = '~'; /* should be scan line 1 */ - ACS_S9 = '_'; /* should be scan line 9 */ - ACS_DIAMOND = '+'; /* should be diamond */ - ACS_CKBOARD = ':'; /* should be checker board (stipple) */ - ACS_DEGREE = '\''; /* should be degree symbol */ - ACS_PLMINUS = '#'; /* should be plus/minus */ - ACS_BULLET = 'o'; /* should be bullet */ - ACS_LARROW = '<'; /* should be arrow pointing left */ - ACS_RARROW = '>'; /* should be arrow pointing right */ - ACS_DARROW = 'v'; /* should be arrow pointing down */ - ACS_UARROW = '^'; /* should be arrow pointing up */ - ACS_BOARD = '#'; /* should be board of squares */ - ACS_LANTERN = '#'; /* should be lantern symbol */ - ACS_BLOCK = '#'; /* should be solid square block */ + real_map['l'] = '+'; /* should be upper left corner */ + real_map['m'] = '+'; /* should be lower left corner */ + real_map['k'] = '+'; /* should be upper right corner */ + real_map['j'] = '+'; /* should be lower right corner */ + real_map['u'] = '+'; /* should be tee pointing left */ + real_map['t'] = '+'; /* should be tee pointing right */ + real_map['v'] = '+'; /* should be tee pointing up */ + real_map['w'] = '+'; /* should be tee pointing down */ + real_map['q'] = '-'; /* should be horizontal line */ + real_map['x'] = '|'; /* should be vertical line */ + real_map['n'] = '+'; /* should be large plus or crossover */ + real_map['o'] = '~'; /* should be scan line 1 */ + real_map['s'] = '_'; /* should be scan line 9 */ + real_map['`'] = '+'; /* should be diamond */ + real_map['a'] = ':'; /* should be checker board (stipple) */ + real_map['f'] = '\''; /* should be degree symbol */ + real_map['g'] = '#'; /* should be plus/minus */ + real_map['~'] = 'o'; /* should be bullet */ + real_map[','] = '<'; /* should be arrow pointing left */ + real_map['+'] = '>'; /* should be arrow pointing right */ + real_map['.'] = 'v'; /* should be arrow pointing down */ + real_map['-'] = '^'; /* should be arrow pointing up */ + real_map['h'] = '#'; /* should be board of squares */ + real_map['i'] = '#'; /* should be lantern symbol */ + real_map['0'] = '#'; /* should be solid square block */ /* these defaults were invented for ncurses */ - ACS_S3 = '-'; /* should be scan line 3 */ - ACS_S7 = '-'; /* should be scan line 7 */ - ACS_LEQUAL = '<'; /* should be less-than-or-equal-to */ - ACS_GEQUAL = '>'; /* should be greater-than-or-equal-to */ - ACS_PI = '*'; /* should be greek pi */ - ACS_NEQUAL = '!'; /* should be not-equal */ - ACS_STERLING = 'f'; /* should be pound-sterling symbol */ + real_map['p'] = '-'; /* should be scan line 3 */ + real_map['r'] = '-'; /* should be scan line 7 */ + real_map['y'] = '<'; /* should be less-than-or-equal-to */ + real_map['z'] = '>'; /* should be greater-than-or-equal-to */ + real_map['{'] = '*'; /* should be greek pi */ + real_map['|'] = '!'; /* should be not-equal */ + real_map['}'] = 'f'; /* should be pound-sterling symbol */ if (ena_acs != NULL) { TPUTS_TRACE("ena_acs"); putp(ena_acs); } -#define ALTCHAR(c) ((chtype)(((unsigned char)(c)) | A_ALTCHARSET)) +#if NCURSES_EXT_FUNCS + /* + * Linux console "supports" the "PC ROM" character set by the coincidence + * that smpch/rmpch and smacs/rmacs have the same values. ncurses has + * no codepage support (see SCO Merge for an example). Outside of the + * values defined in acsc, there are no definitions for the "PC ROM" + * character set (assumed by some applications to be codepage 437), but we + * allow those applications to use those codepoints. + * + * test/blue.c uses this feature. + */ +#define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b)) + if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) && + PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) { + size_t i; + for (i = 1; i < ACS_LEN; ++i) { + if (real_map[i] == 0) { + real_map[i] = i; + if (real_map != fake_map) { + if (SP != 0) + SP->_screen_acs_map[i] = TRUE; + } + } + } + } +#endif if (acs_chars != NULL) { size_t i = 0; size_t length = strlen(acs_chars); - while (i < length) - switch (acs_chars[i]) { - case 'l': - case 'm': - case 'k': - case 'j': - case 'u': - case 't': - case 'v': - case 'w': - case 'q': - case 'x': - case 'n': - case 'o': - case 's': - case '`': - case 'a': - case 'f': - case 'g': - case '~': - case ',': - case '+': - case '.': - case '-': - case 'h': - case 'i': - case '0': - case 'p': - case 'r': - case 'y': - case 'z': - case '{': - case '|': - case '}': - acs_map[(unsigned int) acs_chars[i]] = - ALTCHAR(acs_chars[i + 1]); - i++; - /* FALLTHRU */ - default: - i++; - break; + while (i + 1 < length) { + if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) { + real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET; + if (SP != 0) + SP->_screen_acs_map[UChar(acs_chars[i])] = TRUE; } + i += 2; + } } #ifdef TRACE /* Show the equivalent mapping, noting if it does not match the * given attribute, whether by re-ordering or duplication. */ - if (_nc_tracing & TRACE_CALLS) { + if (USE_TRACEF(TRACE_CALLS)) { size_t n, m; - char show[SIZEOF(acs_map) + 1]; - for (n = 1, m = 0; n < SIZEOF(acs_map); n++) { - if (acs_map[n] != 0) { + char show[ACS_LEN * 2 + 1]; + for (n = 1, m = 0; n < ACS_LEN; n++) { + if (real_map[n] != 0) { show[m++] = (char) n; - show[m++] = TextOf(acs_map[n]); + show[m++] = (char) ChCharOf(real_map[n]); } } show[m] = 0; + if (acs_chars == NULL || strcmp(acs_chars, show)) + _tracef("%s acs_chars %s", + (acs_chars == NULL) ? "NULL" : "READ", + _nc_visbuf(acs_chars)); _tracef("%s acs_chars %s", (acs_chars == NULL) ? "NULL" @@ -160,6 +190,7 @@ _nc_init_acs(void) ? "DIFF" : "SAME"), _nc_visbuf(show)); + _nc_unlock_global(tracef); } #endif /* TRACE */ } diff --git a/lib/libcurses/tinfo/lib_baudrate.c b/lib/libcurses/tinfo/lib_baudrate.c index 39342dcb9ab..a171993945a 100644 --- a/lib/libcurses/tinfo/lib_baudrate.c +++ b/lib/libcurses/tinfo/lib_baudrate.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_baudrate.c,v 1.4 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_baudrate.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -41,8 +42,47 @@ #include <curses.priv.h> #include <term.h> /* cur_term, pad_char */ #include <termcap.h> /* ospeed */ +#if defined(__FreeBSD__) +#include <sys/param.h> +#endif + +/* + * These systems use similar header files, which define B1200 as 1200, etc., + * but can be overridden by defining USE_OLD_TTY so B1200 is 9, which makes all + * of the indices up to B115200 fit nicely in a 'short', allowing us to retain + * ospeed's type for compatibility. + */ +#if (defined(__FreeBSD__) && (__FreeBSD_version < 700000)) || defined(__NetBSD__) || defined(__OpenBSD__) +#undef B0 +#undef B50 +#undef B75 +#undef B110 +#undef B134 +#undef B150 +#undef B200 +#undef B300 +#undef B600 +#undef B1200 +#undef B1800 +#undef B2400 +#undef B4800 +#undef B9600 +#undef B19200 +#undef EXTA +#undef B38400 +#undef EXTB +#undef B57600 +#undef B115200 +#undef B230400 +#undef B460800 +#undef B921600 +#define USE_OLD_TTY +#include <sys/ttydev.h> +#else +#undef USE_OLD_TTY +#endif /* USE_OLD_TTY */ -MODULE_ID("$From: lib_baudrate.c,v 1.19 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_baudrate.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") /* * int @@ -99,21 +139,28 @@ static struct speed const speeds[] = #ifdef B460800 {B460800, 460800}, #endif +#ifdef B921600 + {B921600, 921600}, +#endif }; NCURSES_EXPORT(int) _nc_baudrate(int OSpeed) { +#if !USE_REENTRANT static int last_OSpeed; static int last_baudrate; +#endif - int result; + int result = ERR; unsigned i; +#if !USE_REENTRANT if (OSpeed == last_OSpeed) { result = last_baudrate; - } else { - result = ERR; + } +#endif + if (result == ERR) { if (OSpeed >= 0) { for (i = 0; i < SIZEOF(speeds); i++) { if (speeds[i].s == OSpeed) { @@ -122,7 +169,12 @@ _nc_baudrate(int OSpeed) } } } - last_baudrate = result; +#if !USE_REENTRANT + if (OSpeed == last_OSpeed) { + last_OSpeed = OSpeed; + last_baudrate = result; + } +#endif } return (result); } @@ -157,24 +209,32 @@ baudrate(void) * that take into account costs that depend on baudrate. */ #ifdef TRACE - if (SP && !isatty(fileno(SP->_ofp)) + if (!isatty(fileno(SP ? SP->_ofp : stdout)) && getenv("BAUDRATE") != 0) { int ret; if ((ret = _nc_getenv_num("BAUDRATE")) <= 0) ret = 9600; ospeed = _nc_ospeed(ret); returnCode(ret); - } else + } #endif + if (cur_term != 0) { +#ifdef USE_OLD_TTY + result = cfgetospeed(&cur_term->Nttyb); + ospeed = _nc_ospeed(result); +#else /* !USE_OLD_TTY */ #ifdef TERMIOS ospeed = cfgetospeed(&cur_term->Nttyb); #else ospeed = cur_term->Nttyb.sg_ospeed; #endif - result = _nc_baudrate(ospeed); - if (cur_term != 0) + result = _nc_baudrate(ospeed); +#endif cur_term->_baudrate = result; + } else { + result = ERR; + } returnCode(result); } diff --git a/lib/libcurses/tinfo/lib_cur_term.c b/lib/libcurses/tinfo/lib_cur_term.c index 3fcf4abe47c..68bb567f793 100644 --- a/lib/libcurses/tinfo/lib_cur_term.c +++ b/lib/libcurses/tinfo/lib_cur_term.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_cur_term.c,v 1.5 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_cur_term.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2003,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,33 +42,66 @@ #include <term_entry.h> /* TTY, cur_term */ #include <termcap.h> /* ospeed */ -MODULE_ID("$From: lib_cur_term.c,v 1.11 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_cur_term.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +#undef CUR +#define CUR termp->type. + +#if BROKEN_LINKER || USE_REENTRANT +NCURSES_EXPORT(TERMINAL *) +NCURSES_PUBLIC_VAR(cur_term) (void) +{ + return (SP != 0 && SP->_term != 0) ? SP->_term : _nc_prescreen._cur_term; +} +#else NCURSES_EXPORT_VAR(TERMINAL *) cur_term = 0; +#endif NCURSES_EXPORT(TERMINAL *) set_curterm(TERMINAL * termp) { - TERMINAL *oldterm = cur_term; + TERMINAL *oldterm; + + T((T_CALLED("set_curterm(%p)"), termp)); - if ((cur_term = termp) != 0) { - ospeed = _nc_ospeed(cur_term->_baudrate); - PC = (pad_char != NULL) ? pad_char[0] : 0; + _nc_lock_global(curses); + oldterm = cur_term; + if (SP) + SP->_term = termp; +#if BROKEN_LINKER || USE_REENTRANT + _nc_prescreen._cur_term = termp; +#else + cur_term = termp; +#endif + if (termp != 0) { + ospeed = _nc_ospeed(termp->_baudrate); + if (termp->type.Strings) { + PC = (char) ((pad_char != NULL) ? pad_char[0] : 0); + } } - return oldterm; + _nc_unlock_global(curses); + + T((T_RETURN("%p"), oldterm)); + return (oldterm); } NCURSES_EXPORT(int) del_curterm(TERMINAL * termp) { + int rc = ERR; + T((T_CALLED("del_curterm(%p)"), termp)); + _nc_lock_global(curses); if (termp != 0) { _nc_free_termtype(&(termp->type)); + FreeIfNeeded(termp->_termname); free(termp); if (termp == cur_term) - cur_term = 0; - returnCode(OK); + set_curterm(0); + rc = OK; } - returnCode(ERR); + _nc_unlock_global(curses); + + returnCode(rc); } diff --git a/lib/libcurses/tinfo/lib_data.c b/lib/libcurses/tinfo/lib_data.c index cdc8044ab18..57e8d7e9a06 100644 --- a/lib/libcurses/tinfo/lib_data.c +++ b/lib/libcurses/tinfo/lib_data.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_data.c,v 1.3 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_data.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -42,18 +43,33 @@ #include <curses.priv.h> -MODULE_ID("$From: lib_data.c,v 1.16 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_data.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") /* * OS/2's native linker complains if we don't initialize public data when * constructing a dll (reported by J.J.G.Ripoll). */ -NCURSES_EXPORT_VAR(WINDOW *) -stdscr = 0; -NCURSES_EXPORT_VAR(WINDOW *) -curscr = 0; -NCURSES_EXPORT_VAR(WINDOW *) -newscr = 0; +#if USE_REENTRANT +NCURSES_EXPORT(WINDOW *) +NCURSES_PUBLIC_VAR(stdscr) (void) +{ + return SP ? SP->_stdscr : 0; +} +NCURSES_EXPORT(WINDOW *) +NCURSES_PUBLIC_VAR(curscr) (void) +{ + return SP ? SP->_curscr : 0; +} +NCURSES_EXPORT(WINDOW *) +NCURSES_PUBLIC_VAR(newscr) (void) +{ + return SP ? SP->_newscr : 0; +} +#else +NCURSES_EXPORT_VAR(WINDOW *) stdscr = 0; +NCURSES_EXPORT_VAR(WINDOW *) curscr = 0; +NCURSES_EXPORT_VAR(WINDOW *) newscr = 0; +#endif NCURSES_EXPORT_VAR(SCREEN *) _nc_screen_chain = 0; @@ -68,7 +84,7 @@ NCURSES_EXPORT_VAR(SCREEN *) _nc_screen_chain = 0; * module coupling that increases the size of the executable. */ #if BROKEN_LINKER - static SCREEN *my_screen; +static SCREEN *my_screen; NCURSES_EXPORT(SCREEN *) _nc_screen(void) @@ -83,11 +99,236 @@ _nc_alloc_screen(void) } NCURSES_EXPORT(void) -_nc_set_screen(SCREEN * sp) +_nc_set_screen(SCREEN *sp) { my_screen = sp; } #else -NCURSES_EXPORT_VAR(SCREEN *) SP = NULL; /* Some linkers require initialized data... */ +NCURSES_EXPORT_VAR(SCREEN *) SP = NULL; /* Some linkers require initialized data... */ +#endif +/* *INDENT-OFF* */ +#define CHARS_0s { '\0' } + +#define TGETENT_0 { 0L, FALSE, NULL, NULL, NULL } +#define TGETENT_0s { TGETENT_0, TGETENT_0, TGETENT_0, TGETENT_0 } + +NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { + 0, /* have_sigwinch */ + 0, /* cleanup_nested */ + + FALSE, /* init_signals */ + FALSE, /* init_screen */ + + NULL, /* comp_sourcename */ + NULL, /* comp_termtype */ + + FALSE, /* have_tic_directory */ + FALSE, /* keep_tic_directory */ + TERMINFO, /* tic_directory */ + + NULL, /* dbi_list */ + 0, /* dbi_size */ + + NULL, /* first_name */ + NULL, /* keyname_table */ + + 0, /* slk_format */ + + NULL, /* safeprint_buf */ + 0, /* safeprint_used */ + + TGETENT_0s, /* tgetent_cache */ + 0, /* tgetent_index */ + 0, /* tgetent_sequence */ + + 0, /* _nc_windowlist */ + +#if USE_HOME_TERMINFO + NULL, /* home_terminfo */ +#endif + +#if !USE_SAFE_SPRINTF + 0, /* safeprint_cols */ + 0, /* safeprint_rows */ +#endif + +#ifdef TRACE + FALSE, /* init_trace */ + CHARS_0s, /* trace_fname */ + 0, /* trace_level */ + NULL, /* trace_fp */ + + NULL, /* tracearg_buf */ + 0, /* tracearg_used */ + + NULL, /* tracebuf_ptr */ + 0, /* tracebuf_used */ + + CHARS_0s, /* tracechr_buf */ + + NULL, /* tracedmp_buf */ + 0, /* tracedmp_used */ + + NULL, /* tracetry_buf */ + 0, /* tracetry_used */ + + { CHARS_0s, CHARS_0s }, /* traceatr_color_buf */ + 0, /* traceatr_color_sel */ + -1, /* traceatr_color_last */ + +#endif /* TRACE */ +#ifdef USE_PTHREADS + PTHREAD_MUTEX_INITIALIZER, /* mutex_curses */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_tst_tracef */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_tracef */ + 0, /* nested_tracef */ + 0, /* use_pthreads */ +#endif +}; + +#define STACK_FRAME_0 { { 0 }, 0 } +#define STACK_FRAME_0s { STACK_FRAME_0 } +#define NUM_VARS_0s { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } + +#define RIPOFF_0 { 0,0,0 } +#define RIPOFF_0s { RIPOFF_0 } + +NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = { + TRUE, /* use_env */ + FALSE, /* filter_mode */ + A_NORMAL, /* previous_attr */ + RIPOFF_0s, /* ripoff */ + NULL, /* rsp */ + { /* tparm_state */ +#ifdef TRACE + NULL, /* tname */ +#endif + NULL, /* tparam_base */ + + STACK_FRAME_0s, /* stack */ + 0, /* stack_ptr */ + + NULL, /* out_buff */ + 0, /* out_size */ + 0, /* out_used */ + + NULL, /* fmt_buff */ + 0, /* fmt_size */ + + NUM_VARS_0s, /* dynamic_var */ + NUM_VARS_0s, /* static_vars */ + }, + NULL, /* saved_tty */ +#if NCURSES_NO_PADDING + FALSE, /* flag to set if padding disabled */ +#endif +#if BROKEN_LINKER || USE_REENTRANT + NULL, /* real_acs_map */ + 0, /* LINES */ + 0, /* COLS */ + 0, /* cur_term */ +#ifdef TRACE + 0L, /* _outchars */ + NULL, /* _tputs_trace */ +#endif +#endif +}; +/* *INDENT-ON* */ + +/******************************************************************************/ +#ifdef USE_PTHREADS +static void +init_global_mutexes(void) +{ + static bool initialized = FALSE; + + if (!initialized) { + initialized = TRUE; + _nc_mutex_init(&_nc_globals.mutex_curses); + _nc_mutex_init(&_nc_globals.mutex_tst_tracef); + _nc_mutex_init(&_nc_globals.mutex_tracef); + } +} + +NCURSES_EXPORT(void) +_nc_init_pthreads(void) +{ + if (_nc_use_pthreads) + return; +# if USE_WEAK_SYMBOLS + if ((pthread_mutex_init) == 0) + return; + if ((pthread_mutex_lock) == 0) + return; + if ((pthread_mutex_unlock) == 0) + return; + if ((pthread_mutex_trylock) == 0) + return; + if ((pthread_mutexattr_settype) == 0) + return; +# endif + _nc_use_pthreads = 1; + init_global_mutexes(); +} + +/* + * Use recursive mutexes if we have them - they're part of Unix98. + * For the cases where we do not, _nc_mutex_trylock() is used to avoid a + * deadlock, at the expense of memory leaks and unexpected failures that + * may not be handled by typical clients. + * + * FIXME - need configure check for PTHREAD_MUTEX_RECURSIVE, define it to + * PTHREAD_MUTEX_NORMAL if not supported. + */ +NCURSES_EXPORT(void) +_nc_mutex_init(pthread_mutex_t * obj) +{ + pthread_mutexattr_t recattr; + + if (_nc_use_pthreads) { + pthread_mutexattr_init(&recattr); + pthread_mutexattr_settype(&recattr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(obj, &recattr); + } +} + +NCURSES_EXPORT(int) +_nc_mutex_lock(pthread_mutex_t * obj) +{ + if (_nc_use_pthreads == 0) + return 0; + return pthread_mutex_lock(obj); +} + +NCURSES_EXPORT(int) +_nc_mutex_trylock(pthread_mutex_t * obj) +{ + if (_nc_use_pthreads == 0) + return 0; + return pthread_mutex_trylock(obj); +} + +NCURSES_EXPORT(int) +_nc_mutex_unlock(pthread_mutex_t * obj) +{ + if (_nc_use_pthreads == 0) + return 0; + return pthread_mutex_unlock(obj); +} + +#if USE_WEAK_SYMBOLS +/* + * NB: sigprocmask(2) is global but pthread_sigmask(3p) + * only for the calling thread. + */ +NCURSES_EXPORT(int) +_nc_sigprocmask(int how, const sigset_t * newmask, sigset_t * oldmask) +{ + if ((pthread_sigmask)) + return pthread_sigmask(how, newmask, oldmask); + else + return sigprocmask(how, newmask, oldmask); +} #endif +#endif /* USE_PTHREADS */ diff --git a/lib/libcurses/tinfo/lib_has_cap.c b/lib/libcurses/tinfo/lib_has_cap.c index d95e3f908c7..6be944be979 100644 --- a/lib/libcurses/tinfo/lib_has_cap.c +++ b/lib/libcurses/tinfo/lib_has_cap.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_has_cap.c,v 1.2 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_has_cap.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-2003 * ****************************************************************************/ /* @@ -44,7 +45,7 @@ #include <term.h> -MODULE_ID("$From: lib_has_cap.c,v 1.3 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_has_cap.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(bool) has_ic(void) diff --git a/lib/libcurses/tinfo/lib_kernel.c b/lib/libcurses/tinfo/lib_kernel.c index 730ba1551fd..024227fdc03 100644 --- a/lib/libcurses/tinfo/lib_kernel.c +++ b/lib/libcurses/tinfo/lib_kernel.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_kernel.c,v 1.2 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_kernel.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 2002 * ****************************************************************************/ /* @@ -49,7 +50,28 @@ #include <curses.priv.h> #include <term.h> /* cur_term */ -MODULE_ID("$From: lib_kernel.c,v 1.21 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_kernel.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") + +static int +_nc_vdisable(void) +{ + int value = -1; +#if defined(_POSIX_VDISABLE) && HAVE_UNISTD_H + value = _POSIX_VDISABLE; +#endif +#if defined(_PC_VDISABLE) + if (value == -1) { + value = fpathconf(0, _PC_VDISABLE); + if (value == -1) { + value = 0377; + } + } +#elif defined(VDISABLE) + if (value == -1) + value = VDISABLE; +#endif + return value; +} /* * erasechar() @@ -61,16 +83,19 @@ MODULE_ID("$From: lib_kernel.c,v 1.21 2000/12/10 02:55:07 tom Exp $") NCURSES_EXPORT(char) erasechar(void) { + int result = ERR; T((T_CALLED("erasechar()"))); if (cur_term != 0) { #ifdef TERMIOS - returnCode(cur_term->Ottyb.c_cc[VERASE]); + result = cur_term->Ottyb.c_cc[VERASE]; + if (result == _nc_vdisable()) + result = ERR; #else - returnCode(cur_term->Ottyb.sg_erase); + result = cur_term->Ottyb.sg_erase; #endif } - returnCode(ERR); + returnCode(result); } /* @@ -83,16 +108,19 @@ erasechar(void) NCURSES_EXPORT(char) killchar(void) { + int result = ERR; T((T_CALLED("killchar()"))); if (cur_term != 0) { #ifdef TERMIOS - returnCode(cur_term->Ottyb.c_cc[VKILL]); + result = cur_term->Ottyb.c_cc[VKILL]; + if (result == _nc_vdisable()) + result = ERR; #else - returnCode(cur_term->Ottyb.sg_kill); + result = cur_term->Ottyb.sg_kill; #endif } - returnCode(ERR); + returnCode(result); } /* diff --git a/lib/libcurses/tinfo/lib_longname.c b/lib/libcurses/tinfo/lib_longname.c index 9cbbf5fcbf5..74616fa7bc7 100644 --- a/lib/libcurses/tinfo/lib_longname.c +++ b/lib/libcurses/tinfo/lib_longname.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lib_longname.c,v 1.2 2001/01/22 18:01:52 millert Exp $ */ +/* $OpenBSD: lib_longname.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** * Copyright (c) 1998,2000 Free Software Foundation, Inc. * @@ -42,7 +42,7 @@ #include <curses.priv.h> -MODULE_ID("$From: lib_longname.c,v 1.9 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_longname.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(char *) longname(void) diff --git a/lib/libcurses/tinfo/lib_napms.c b/lib/libcurses/tinfo/lib_napms.c index bf29ef488f5..b92431d9701 100644 --- a/lib/libcurses/tinfo/lib_napms.c +++ b/lib/libcurses/tinfo/lib_napms.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_napms.c,v 1.7 2001/01/22 18:01:53 millert Exp $ */ +/* $OpenBSD: lib_napms.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,6 +38,8 @@ * * The routine napms. * + * (This file was originally written by Eric Raymond; however except for + * comments, none of the original code remains - T.Dickey). */ #include <curses.priv.h> @@ -47,20 +49,9 @@ #if HAVE_SYS_TIME_H #include <sys/time.h> /* needed for MacOS X DP3 */ #endif -#elif USE_FUNC_POLL -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#elif HAVE_SELECT -#if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT -#include <sys/time.h> -#endif -#if HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif #endif -MODULE_ID("$From: lib_napms.c,v 1.11 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_napms.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(int) napms(int ms) @@ -69,23 +60,17 @@ napms(int ms) #if HAVE_NANOSLEEP { - struct timespec ts; - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000; - nanosleep(&ts, NULL); - } -#elif USE_FUNC_POLL - { - struct pollfd fds[1]; - poll(fds, 0, ms); - } -#elif HAVE_SELECT - { - struct timeval tval; - tval.tv_sec = ms / 1000; - tval.tv_usec = (ms % 1000) * 1000; - select(0, NULL, NULL, NULL, &tval); + struct timespec request, remaining; + request.tv_sec = ms / 1000; + request.tv_nsec = (ms % 1000) * 1000000; + while (nanosleep(&request, &remaining) == -1 + && errno == EINTR) { + request = remaining; + } } +#else + _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0)); #endif + returnCode(OK); } diff --git a/lib/libcurses/tinfo/lib_options.c b/lib/libcurses/tinfo/lib_options.c index ca96bc3d7db..00e079fce5b 100644 --- a/lib/libcurses/tinfo/lib_options.c +++ b/lib/libcurses/tinfo/lib_options.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_options.c,v 1.9 2001/01/22 18:01:53 millert Exp $ */ +/* $OpenBSD: lib_options.c,v 1.10 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -44,7 +45,10 @@ #include <term.h> -MODULE_ID("$From: lib_options.c,v 1.42 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_options.c,v 1.10 2010/01/12 23:22:06 nicm Exp $") + +static int _nc_curs_set(SCREEN *, int); +static int _nc_meta(SCREEN *, bool); NCURSES_EXPORT(int) idlok(WINDOW *win, bool flag) @@ -74,7 +78,7 @@ halfdelay(int t) { T((T_CALLED("halfdelay(%d)"), t)); - if (t < 1 || t > 255) + if (t < 1 || t > 255 || SP == 0) returnCode(ERR); cbreak(); @@ -100,7 +104,7 @@ nodelay(WINDOW *win, bool flag) NCURSES_EXPORT(int) notimeout(WINDOW *win, bool f) { - T((T_CALLED("notimout(%p,%d)"), win, f)); + T((T_CALLED("notimeout(%p,%d)"), win, f)); if (win) { win->_notimeout = f; @@ -117,6 +121,7 @@ wtimeout(WINDOW *win, int delay) if (win) { win->_delay = delay; } + returnVoid; } NCURSES_EXPORT(int) @@ -126,7 +131,7 @@ keypad(WINDOW *win, bool flag) if (win) { win->_use_keypad = flag; - returnCode(_nc_keypad(flag)); + returnCode(_nc_keypad(SP, flag)); } else returnCode(ERR); } @@ -134,19 +139,12 @@ keypad(WINDOW *win, bool flag) NCURSES_EXPORT(int) meta(WINDOW *win GCC_UNUSED, bool flag) { + int result; + /* Ok, we stay relaxed and don't signal an error if win is NULL */ T((T_CALLED("meta(%p,%d)"), win, flag)); - - SP->_use_meta = flag; - - if (flag && meta_on) { - TPUTS_TRACE("meta_on"); - putp(meta_on); - } else if (!flag && meta_off) { - TPUTS_TRACE("meta_off"); - putp(meta_off); - } - returnCode(OK); + result = _nc_meta(SP, flag); + returnCode(result); } /* curs_set() moved here to narrow the kernel interface */ @@ -154,51 +152,23 @@ meta(WINDOW *win GCC_UNUSED, bool flag) NCURSES_EXPORT(int) curs_set(int vis) { - int cursor = SP->_cursor; + int result; T((T_CALLED("curs_set(%d)"), vis)); - - if (vis < 0 || vis > 2) - returnCode(ERR); - - if (vis == cursor) - returnCode(cursor); - - switch (vis) { - case 2: - if (cursor_visible) { - TPUTS_TRACE("cursor_visible"); - putp(cursor_visible); - } else - returnCode(ERR); - break; - case 1: - if (cursor_normal) { - TPUTS_TRACE("cursor_normal"); - putp(cursor_normal); - } else - returnCode(ERR); - break; - case 0: - if (cursor_invisible) { - TPUTS_TRACE("cursor_invisible"); - putp(cursor_invisible); - } else - returnCode(ERR); - break; - } - SP->_cursor = vis; - _nc_flush(); - - returnCode(cursor == -1 ? 1 : cursor); + result = _nc_curs_set(SP, vis); + returnCode(result); } NCURSES_EXPORT(int) typeahead(int fd) { T((T_CALLED("typeahead(%d)"), fd)); - SP->_checkfd = fd; - returnCode(OK); + if (SP != 0) { + SP->_checkfd = fd; + returnCode(OK); + } else { + returnCode(ERR); + } } /* @@ -210,7 +180,7 @@ typeahead(int fd) #if NCURSES_EXT_FUNCS static int -has_key_internal(int keycode, struct tries *tp) +has_key_internal(int keycode, TRIES * tp) { if (tp == 0) return (FALSE); @@ -225,10 +195,39 @@ NCURSES_EXPORT(int) has_key(int keycode) { T((T_CALLED("has_key(%d)"), keycode)); - returnCode(has_key_internal(keycode, SP->_keytry)); + returnCode(SP != 0 ? has_key_internal(keycode, SP->_keytry) : FALSE); } #endif /* NCURSES_EXT_FUNCS */ +/* + * Internal entrypoints use SCREEN* parameter to obtain capabilities rather + * than cur_term. + */ +#undef CUR +#define CUR (sp->_term)->type. + +static int +_nc_putp(const char *name GCC_UNUSED, const char *value) +{ + int rc = ERR; + + if (value) { + TPUTS_TRACE(name); + rc = putp(value); + } + return rc; +} + +static int +_nc_putp_flush(const char *name, const char *value) +{ + int rc = _nc_putp(name, value); + if (rc != ERR) { + _nc_flush(); + } + return rc; +} + /* Turn the keypad on/off * * Note: we flush the output because changing this mode causes some terminals @@ -237,21 +236,94 @@ has_key(int keycode) * the terminal state _before_ switching modes. */ NCURSES_EXPORT(int) -_nc_keypad(bool flag) +_nc_keypad(SCREEN *sp, bool flag) { - if (flag && keypad_xmit) { - TPUTS_TRACE("keypad_xmit"); - putp(keypad_xmit); - _nc_flush(); - } else if (!flag && keypad_local) { - TPUTS_TRACE("keypad_local"); - putp(keypad_local); - _nc_flush(); + int rc = ERR; + + if (sp != 0) { +#ifdef USE_PTHREADS + /* + * We might have this situation in a multithreaded application that + * has wgetch() reading in more than one thread. putp() and below + * may use SP explicitly. + */ + if (_nc_use_pthreads && sp != SP) { + SCREEN *save_sp; + + /* cannot use use_screen(), since that is not in tinfo library */ + _nc_lock_global(curses); + save_sp = SP; + _nc_set_screen(sp); + rc = _nc_keypad(sp, flag); + _nc_set_screen(save_sp); + _nc_unlock_global(curses); + } else +#endif + { + if (flag) { + (void) _nc_putp_flush("keypad_xmit", keypad_xmit); + } else if (!flag && keypad_local) { + (void) _nc_putp_flush("keypad_local", keypad_local); + } + + if (flag && !sp->_tried) { + _nc_init_keytry(sp); + sp->_tried = TRUE; + } + sp->_keypad_on = flag; + rc = OK; + } + } + return (rc); +} + +static int +_nc_curs_set(SCREEN *sp, int vis) +{ + int result = ERR; + + T((T_CALLED("curs_set(%d)"), vis)); + if (sp != 0 && vis >= 0 && vis <= 2) { + int cursor = sp->_cursor; + + if (vis == cursor) { + result = cursor; + } else { + switch (vis) { + case 2: + result = _nc_putp_flush("cursor_visible", cursor_visible); + break; + case 1: + result = _nc_putp_flush("cursor_normal", cursor_normal); + break; + case 0: + result = _nc_putp_flush("cursor_invisible", cursor_invisible); + break; + } + if (result != ERR) + result = (cursor == -1 ? 1 : cursor); + sp->_cursor = vis; + } } + returnCode(result); +} + +static int +_nc_meta(SCREEN *sp, bool flag) +{ + int result = ERR; + + /* Ok, we stay relaxed and don't signal an error if win is NULL */ + + if (SP != 0) { + SP->_use_meta = flag; - if (flag && !SP->_tried) { - _nc_init_keytry(); - SP->_tried = TRUE; + if (flag) { + _nc_putp("meta_on", meta_on); + } else { + _nc_putp("meta_off", meta_off); + } + result = OK; } - return (OK); + return result; } diff --git a/lib/libcurses/tinfo/lib_print.c b/lib/libcurses/tinfo/lib_print.c index 9a5b3157e07..5043c551004 100644 --- a/lib/libcurses/tinfo/lib_print.c +++ b/lib/libcurses/tinfo/lib_print.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_print.c,v 1.4 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: lib_print.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,7 +37,7 @@ #include <term.h> -MODULE_ID("$From: lib_print.c,v 1.13 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_print.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(int) mcprint(char *data, int len) @@ -53,7 +53,7 @@ mcprint(char *data, int len) } if (prtr_non) { - switchon = tparm(prtr_non, len); + switchon = TPARM_1(prtr_non, len); onsize = strlen(switchon); offsize = 0; } else { @@ -63,13 +63,13 @@ mcprint(char *data, int len) } res = onsize + len + offsize + 1; - if ((mybuf = typeMalloc(char, res)) == (char *) 0) { + if (switchon == 0 || (mybuf = typeMalloc(char, res)) == 0) { errno = ENOMEM; return (ERR); } (void) strlcpy(mybuf, switchon, res); - memcpy(mybuf + onsize, data, len); + memcpy(mybuf + onsize, data, (unsigned) len); if (offsize) (void) strlcpy(mybuf + onsize + len, prtr_off, res - onsize - len); diff --git a/lib/libcurses/tinfo/lib_raw.c b/lib/libcurses/tinfo/lib_raw.c index eb10b64e30b..724ba92a4a2 100644 --- a/lib/libcurses/tinfo/lib_raw.c +++ b/lib/libcurses/tinfo/lib_raw.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_raw.c,v 1.7 2001/01/22 18:01:53 millert Exp $ */ +/* $OpenBSD: lib_raw.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2002,2007 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1998 on * ****************************************************************************/ /* @@ -50,7 +51,7 @@ #include <curses.priv.h> #include <term.h> /* cur_term */ -MODULE_ID("$From: lib_raw.c,v 1.10 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_raw.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") #if SVR4_TERMIO && !defined(_POSIX_SOURCE) #define _POSIX_SOURCE @@ -62,13 +63,16 @@ MODULE_ID("$From: lib_raw.c,v 1.10 2000/12/10 02:55:07 tom Exp $") #ifdef __EMX__ #include <io.h> +#define _nc_setmode(mode) setmode(SP->_ifd, mode) +#else +#define _nc_setmode(mode) /* nothing */ #endif #define COOKED_INPUT (IXON|BRKINT|PARMRK) #ifdef TRACE -#define BEFORE(N) if (_nc_tracing&TRACE_BITS) _tracef("%s before bits: %s", N, _nc_tracebits()) -#define AFTER(N) if (_nc_tracing&TRACE_BITS) _tracef("%s after bits: %s", N, _nc_tracebits()) +#define BEFORE(N) if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s before bits: %s", N, _nc_tracebits()) +#define AFTER(N) if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s after bits: %s", N, _nc_tracebits()) #else #define BEFORE(s) #define AFTER(s) @@ -77,162 +81,218 @@ MODULE_ID("$From: lib_raw.c,v 1.10 2000/12/10 02:55:07 tom Exp $") NCURSES_EXPORT(int) raw(void) { + int result = ERR; + T((T_CALLED("raw()"))); - if (SP != 0 && cur_term != 0) { - SP->_raw = TRUE; - SP->_cbreak = 1; + if (SP != 0 && cur_term != 0) { + TTY buf; -#ifdef __EMX__ - setmode(SP->_ifd, O_BINARY); -#endif + BEFORE("raw"); + _nc_setmode(O_BINARY); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("raw"); - cur_term->Nttyb.c_lflag &= ~(ICANON | ISIG | IEXTEN); - cur_term->Nttyb.c_iflag &= ~(COOKED_INPUT); - cur_term->Nttyb.c_cc[VMIN] = 1; - cur_term->Nttyb.c_cc[VTIME] = 0; - AFTER("raw"); + buf.c_lflag &= ~(ICANON | ISIG | IEXTEN); + buf.c_iflag &= ~(COOKED_INPUT); + buf.c_cc[VMIN] = 1; + buf.c_cc[VTIME] = 0; #else - cur_term->Nttyb.sg_flags |= RAW; + buf.sg_flags |= RAW; #endif - returnCode(_nc_set_tty_mode(&cur_term->Nttyb)); + if ((result = _nc_set_tty_mode(&buf)) == OK) { + SP->_raw = TRUE; + SP->_cbreak = 1; + cur_term->Nttyb = buf; + } + AFTER("raw"); } - returnCode(ERR); + returnCode(result); } NCURSES_EXPORT(int) cbreak(void) { + int result = ERR; + T((T_CALLED("cbreak()"))); - SP->_cbreak = 1; + if (SP != 0 && cur_term != 0) { + TTY buf; -#ifdef __EMX__ - setmode(SP->_ifd, O_BINARY); -#endif + BEFORE("cbreak"); + _nc_setmode(O_BINARY); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("cbreak"); - cur_term->Nttyb.c_lflag &= ~ICANON; - cur_term->Nttyb.c_iflag &= ~ICRNL; - cur_term->Nttyb.c_lflag |= ISIG; - cur_term->Nttyb.c_cc[VMIN] = 1; - cur_term->Nttyb.c_cc[VTIME] = 0; - AFTER("cbreak"); + buf.c_lflag &= ~ICANON; + buf.c_iflag &= ~ICRNL; + buf.c_lflag |= ISIG; + buf.c_cc[VMIN] = 1; + buf.c_cc[VTIME] = 0; #else - cur_term->Nttyb.sg_flags |= CBREAK; + buf.sg_flags |= CBREAK; #endif - returnCode(_nc_set_tty_mode(&cur_term->Nttyb)); + if ((result = _nc_set_tty_mode(&buf)) == OK) { + SP->_cbreak = 1; + cur_term->Nttyb = buf; + } + AFTER("cbreak"); + } + returnCode(result); } +/* + * Note: + * this implementation may be wrong. See the comment under intrflush(). + */ NCURSES_EXPORT(void) qiflush(void) { + int result = ERR; + T((T_CALLED("qiflush()"))); - /* - * Note: this implementation may be wrong. See the comment under - * intrflush(). - */ + if (cur_term != 0) { + TTY buf; + BEFORE("qiflush"); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("qiflush"); - cur_term->Nttyb.c_lflag &= ~(NOFLSH); - AFTER("qiflush"); - (void) _nc_set_tty_mode(&cur_term->Nttyb); - returnVoid; + buf.c_lflag &= ~(NOFLSH); + result = _nc_set_tty_mode(&buf); +#else + /* FIXME */ #endif + if (result == OK) + cur_term->Nttyb = buf; + AFTER("qiflush"); + } + returnVoid; } NCURSES_EXPORT(int) noraw(void) { + int result = ERR; + T((T_CALLED("noraw()"))); - SP->_raw = FALSE; - SP->_cbreak = 0; + if (SP != 0 && cur_term != 0) { + TTY buf; -#ifdef __EMX__ - setmode(SP->_ifd, O_TEXT); -#endif + BEFORE("noraw"); + _nc_setmode(O_TEXT); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("noraw"); - cur_term->Nttyb.c_lflag |= ISIG | ICANON | - (cur_term->Ottyb.c_lflag & IEXTEN); - cur_term->Nttyb.c_iflag |= COOKED_INPUT; - AFTER("noraw"); + buf.c_lflag |= ISIG | ICANON | + (cur_term->Ottyb.c_lflag & IEXTEN); + buf.c_iflag |= COOKED_INPUT; #else - cur_term->Nttyb.sg_flags &= ~(RAW | CBREAK); + buf.sg_flags &= ~(RAW | CBREAK); #endif - returnCode(_nc_set_tty_mode(&cur_term->Nttyb)); + if ((result = _nc_set_tty_mode(&buf)) == OK) { + SP->_raw = FALSE; + SP->_cbreak = 0; + cur_term->Nttyb = buf; + } + AFTER("noraw"); + } + returnCode(result); } NCURSES_EXPORT(int) nocbreak(void) { + int result = ERR; + T((T_CALLED("nocbreak()"))); - SP->_cbreak = 0; + if (SP != 0 && cur_term != 0) { + TTY buf; -#ifdef __EMX__ - setmode(SP->_ifd, O_TEXT); -#endif + BEFORE("nocbreak"); + _nc_setmode(O_TEXT); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("nocbreak"); - cur_term->Nttyb.c_lflag |= ICANON; - cur_term->Nttyb.c_iflag |= ICRNL; - AFTER("nocbreak"); + buf.c_lflag |= ICANON; + buf.c_iflag |= ICRNL; #else - cur_term->Nttyb.sg_flags &= ~CBREAK; + buf.sg_flags &= ~CBREAK; #endif - returnCode(_nc_set_tty_mode(&cur_term->Nttyb)); + if ((result = _nc_set_tty_mode(&buf)) == OK) { + SP->_cbreak = 0; + cur_term->Nttyb = buf; + } + AFTER("nocbreak"); + } + returnCode(result); } +/* + * Note: + * this implementation may be wrong. See the comment under intrflush(). + */ NCURSES_EXPORT(void) noqiflush(void) { + int result = ERR; + T((T_CALLED("noqiflush()"))); - /* - * Note: this implementation may be wrong. See the comment under - * intrflush(). - */ + if (cur_term != 0) { + TTY buf; + BEFORE("noqiflush"); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("noqiflush"); - cur_term->Nttyb.c_lflag |= NOFLSH; - AFTER("noqiflush"); - (void) _nc_set_tty_mode(&cur_term->Nttyb); - returnVoid; + buf.c_lflag |= NOFLSH; + result = _nc_set_tty_mode(&buf); +#else + /* FIXME */ #endif + if (result == OK) { + cur_term->Nttyb = buf; + } + AFTER("noqiflush"); + } + returnVoid; } +/* + * This call does the same thing as the qiflush()/noqiflush() pair. We know + * for certain that SVr3 intrflush() tweaks the NOFLSH bit; on the other hand, + * the match (in the SVr4 man pages) between the language describing NOFLSH in + * termio(7) and the language describing qiflush()/noqiflush() in + * curs_inopts(3x) is too exact to be coincidence. + */ NCURSES_EXPORT(int) intrflush(WINDOW *win GCC_UNUSED, bool flag) { + int result = ERR; + T((T_CALLED("intrflush(%d)"), flag)); - /* - * This call does the same thing as the qiflush()/noqiflush() pair. We - * know for certain that SVr3 intrflush() tweaks the NOFLSH bit; on the - * other hand, the match (in the SVr4 man pages) between the language - * describing NOFLSH in termio(7) and the language describing - * qiflush()/noqiflush() in curs_inopts(3x) is too exact to be coincidence. - */ + if (cur_term != 0) { + TTY buf; + BEFORE("intrflush"); + buf = cur_term->Nttyb; #ifdef TERMIOS - BEFORE("intrflush"); - if (flag) - cur_term->Nttyb.c_lflag &= ~(NOFLSH); - else - cur_term->Nttyb.c_lflag |= (NOFLSH); - AFTER("intrflush"); - returnCode(_nc_set_tty_mode(&cur_term->Nttyb)); + if (flag) + buf.c_lflag &= ~(NOFLSH); + else + buf.c_lflag |= (NOFLSH); + result = _nc_set_tty_mode(&buf); #else - returnCode(ERR); + /* FIXME */ #endif + if (result == OK) { + cur_term->Nttyb = buf; + } + AFTER("intrflush"); + } + returnCode(result); } diff --git a/lib/libcurses/tinfo/lib_setup.c b/lib/libcurses/tinfo/lib_setup.c index 1db8a06bc1b..63643848a29 100644 --- a/lib/libcurses/tinfo/lib_setup.c +++ b/lib/libcurses/tinfo/lib_setup.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_setup.c,v 1.11 2001/01/22 18:01:53 millert Exp $ */ +/* $OpenBSD: lib_setup.c,v 1.12 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -48,9 +49,13 @@ #define _POSIX_SOURCE #endif +#if HAVE_LOCALE_H +#include <locale.h> +#endif + #include <term.h> /* lines, columns, cur_term */ -MODULE_ID("$From: lib_setup.c,v 1.64 2000/12/10 02:55:07 tom Exp $") +MODULE_ID("$Id: lib_setup.c,v 1.12 2010/01/12 23:22:06 nicm Exp $") /**************************************************************************** * @@ -74,6 +79,10 @@ MODULE_ID("$From: lib_setup.c,v 1.64 2000/12/10 02:55:07 tom Exp $") # include <sys/ptem.h> #endif +#if HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif + /* * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, * Solaris, IRIX) define TIOCGWINSZ and struct winsize. @@ -92,31 +101,113 @@ MODULE_ID("$From: lib_setup.c,v 1.64 2000/12/10 02:55:07 tom Exp $") # endif #endif -static int _use_env = TRUE; +/* + * Reduce explicit use of "cur_term" global variable. + */ +#undef CUR +#define CUR termp->type. + +/* + * Wrap global variables in this module. + */ +#if USE_REENTRANT +NCURSES_EXPORT(char *) +NCURSES_PUBLIC_VAR(ttytype) (void) +{ + static char empty[] = ""; + return cur_term ? cur_term->type.term_names : empty; +} +NCURSES_EXPORT(int *) +_nc_ptr_Lines(void) +{ + return ptrLines(); +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(LINES) (void) +{ + return *_nc_ptr_Lines(); +} +NCURSES_EXPORT(int *) +_nc_ptr_Cols(void) +{ + return ptrCols(); +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(COLS) (void) +{ + return *_nc_ptr_Cols(); +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(TABSIZE) (void) +{ + return SP ? SP->_TABSIZE : 8; +} +#else +NCURSES_EXPORT_VAR(char) ttytype[NAMESIZE] = ""; +NCURSES_EXPORT_VAR(int) LINES = 0; +NCURSES_EXPORT_VAR(int) COLS = 0; +NCURSES_EXPORT_VAR(int) TABSIZE = 0; +#endif + +#if NCURSES_EXT_FUNCS +NCURSES_EXPORT(int) +set_tabsize(int value) +{ + int code = OK; +#if USE_REENTRANT + if (SP) { + SP->_TABSIZE = value; + } else { + code = ERR; + } +#else + TABSIZE = value; +#endif + return code; +} +#endif + +#if USE_SIGWINCH +/* + * If we have a pending SIGWINCH, set the flag in each screen. + */ +NCURSES_EXPORT(int) +_nc_handle_sigwinch(SCREEN *sp) +{ + SCREEN *scan; -static void do_prototype(void); + if (_nc_globals.have_sigwinch) { + _nc_globals.have_sigwinch = 0; + + for (each_screen(scan)) { + scan->_sig_winch = TRUE; + } + } + + return (sp ? sp->_sig_winch : 0); +} + +#endif NCURSES_EXPORT(void) use_env(bool f) { - _use_env = f; + T((T_CALLED("use_env()"))); + _nc_prescreen.use_env = f; + returnVoid; } -NCURSES_EXPORT_VAR(int) -LINES = 0; -NCURSES_EXPORT_VAR(int) -COLS = 0; -NCURSES_EXPORT_VAR(int) -TABSIZE = 0; - - static void - _nc_get_screensize(int *linep, int *colp) +NCURSES_EXPORT(void) +_nc_get_screensize(SCREEN *sp, int *linep, int *colp) /* Obtain lines/columns values from the environment and/or terminfo entry */ { + TERMINAL *termp = cur_term; + int my_tabsize; + /* figure out the size of the screen */ T(("screen size: terminfo lines = %d columns = %d", lines, columns)); - if (!_use_env) { + if (!_nc_prescreen.use_env) { *linep = (int) lines; *colp = (int) columns; } else { /* usually want to query LINES and COLUMNS from environment */ @@ -162,7 +253,7 @@ TABSIZE = 0; * environment variable. */ if (*linep <= 0) - *linep = WINSIZE_ROWS(size); + *linep = (sp != 0 && sp->_filtered) ? 1 : WINSIZE_ROWS(size); if (*colp <= 0) *colp = WINSIZE_COLS(size); } @@ -180,8 +271,10 @@ TABSIZE = 0; } /* the ultimate fallback, assume fixed 24x80 size */ - if (*linep <= 0 || *colp <= 0) { + if (*linep <= 0) { *linep = 24; + } + if (*colp <= 0) { *colp = 80; } @@ -196,22 +289,42 @@ TABSIZE = 0; T(("screen size is %dx%d", *linep, *colp)); if (VALID_NUMERIC(init_tabs)) - TABSIZE = (int) init_tabs; + my_tabsize = (int) init_tabs; else - TABSIZE = 8; - T(("TABSIZE = %d", TABSIZE)); + my_tabsize = 8; +#if USE_REENTRANT + if (sp != 0) + sp->_TABSIZE = my_tabsize; +#else + TABSIZE = my_tabsize; +#endif + T(("TABSIZE = %d", TABSIZE)); } #if USE_SIZECHANGE NCURSES_EXPORT(void) -_nc_update_screensize(void) +_nc_update_screensize(SCREEN *sp) { - int my_lines, my_cols; + TERMINAL *termp = cur_term; + int old_lines = lines; + int new_lines; + int old_cols = columns; + int new_cols; - _nc_get_screensize(&my_lines, &my_cols); - if (SP != 0 && SP->_resize != 0) - SP->_resize(my_lines, my_cols); + _nc_get_screensize(sp, &new_lines, &new_cols); + + /* + * See is_term_resized() and resizeterm(). + * We're doing it this way because those functions belong to the upper + * ncurses library, while this resides in the lower terminfo library. + */ + if (sp != 0 + && sp->_resize != 0) { + if ((new_lines != old_lines) || (new_cols != old_cols)) + sp->_resize(new_lines, new_cols); + sp->_sig_winch = FALSE; + } } #endif @@ -237,33 +350,16 @@ _nc_update_screensize(void) exit(EXIT_FAILURE);\ } -#if USE_DATABASE +#if USE_DATABASE || USE_TERMCAP +/* + * Return 1 if entry found, 0 if not found, -1 if database not accessible, + * just like tgetent(). + */ static int -grab_entry(const char *const tn, TERMTYPE * const tp) -/* return 1 if entry found, 0 if not found, -1 if database not accessible */ +grab_entry(const char *const tn, TERMTYPE *const tp) { char filename[PATH_MAX]; - int status; - - /* - * $TERM shouldn't contain pathname delimiters. - */ - if (strchr(tn, '/')) - return 0; - - if ((status = _nc_read_entry(tn, filename, tp)) != 1) { - -#if !PURE_TERMINFO - /* - * Try falling back on the termcap file. - * Note: allowing this call links the entire terminfo/termcap - * compiler into the startup code. It's preferable to build a - * real terminfo database and use that. - */ - status = _nc_read_termcap_entry(tn, tp); -#endif /* PURE_TERMINFO */ - - } + int status = _nc_read_entry(tn, filename, tp); /* * If we have an entry, force all of the cancelled strings to null @@ -271,8 +367,8 @@ grab_entry(const char *const tn, TERMTYPE * const tp) * (The terminfo compiler bypasses this logic, since it must know if * a string is cancelled, for merging entries). */ - if (status == 1) { - int n; + if (status == TGETENT_YES) { + unsigned n; for_each_boolean(n, tp) { if (!VALID_BOOLEAN(tp->Booleans[n])) tp->Booleans[n] = FALSE; @@ -286,139 +382,252 @@ grab_entry(const char *const tn, TERMTYPE * const tp) } #endif -NCURSES_EXPORT_VAR(char) ttytype[NAMESIZE] = ""; +/* +** do_prototype() +** +** Take the real command character out of the CC environment variable +** and substitute it in for the prototype given in 'command_character'. +*/ +static void +do_prototype(TERMINAL * termp) +{ + unsigned i; + char CC; + char proto; + char *tmp; + + if ((tmp = getenv("CC")) != 0) { + if ((CC = *tmp) != 0) { + proto = *command_character; + + for_each_string(i, &(termp->type)) { + for (tmp = termp->type.Strings[i]; *tmp; tmp++) { + if (*tmp == proto) + *tmp = CC; + } + } + } + } +} /* - * setupterm(termname, Filedes, errret) - * - * Find and read the appropriate object file for the terminal - * Make cur_term point to the structure. - * + * Find the locale which is in effect. + */ +NCURSES_EXPORT(char *) +_nc_get_locale(void) +{ + char *env; +#if HAVE_LOCALE_H + /* + * This is preferable to using getenv() since it ensures that we are using + * the locale which was actually initialized by the application. + */ + env = setlocale(LC_CTYPE, 0); +#else + if (((env = getenv("LC_ALL")) != 0 && *env != '\0') + || ((env = getenv("LC_CTYPE")) != 0 && *env != '\0') + || ((env = getenv("LANG")) != 0 && *env != '\0')) { + ; + } +#endif + T(("_nc_get_locale %s", _nc_visbuf(env))); + return env; +} + +/* + * Check if we are running in a UTF-8 locale. + */ +NCURSES_EXPORT(int) +_nc_unicode_locale(void) +{ + int result = 0; +#if HAVE_LANGINFO_CODESET + char *env = nl_langinfo(CODESET); + result = !strcmp(env, "UTF-8"); + T(("_nc_unicode_locale(%s) ->%d", env, result)); +#else + char *env = _nc_get_locale(); + if (env != 0) { + if (strstr(env, ".UTF-8") != 0) { + result = 1; + T(("_nc_unicode_locale(%s) ->%d", env, result)); + } + } +#endif + return result; +} + +#define CONTROL_N(s) ((s) != 0 && strstr(s, "\016") != 0) +#define CONTROL_O(s) ((s) != 0 && strstr(s, "\017") != 0) + +/* + * Check for known broken cases where a UTF-8 locale breaks the alternate + * character set. */ +NCURSES_EXPORT(int) +_nc_locale_breaks_acs(TERMINAL * termp) +{ + char *env; + + if ((env = getenv("NCURSES_NO_UTF8_ACS")) != 0) { + return atoi(env); + } else if ((env = getenv("TERM")) != 0) { + if (strstr(env, "linux")) + return 1; /* always broken */ + if (strstr(env, "screen") != 0 + && ((env = getenv("TERMCAP")) != 0 + && strstr(env, "screen") != 0) + && strstr(env, "hhII00") != 0) { + if (CONTROL_N(enter_alt_charset_mode) || + CONTROL_O(enter_alt_charset_mode) || + CONTROL_N(set_attributes) || + CONTROL_O(set_attributes)) + return 1; + } + } + return 0; +} +/* + * This entrypoint is called from tgetent() to allow a special case of reusing + * the same TERMINAL data (see comment). + */ NCURSES_EXPORT(int) -setupterm -(NCURSES_CONST char *tname, int Filedes, int *errret) +_nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse) { - struct term *term_ptr; + TERMINAL *termp; int status; + START_TRACE(); T((T_CALLED("setupterm(%s,%d,%p)"), _nc_visbuf(tname), Filedes, errret)); if (tname == 0) { tname = getenv("TERM"); if (tname == 0 || *tname == '\0') { - ret_error0(-1, "TERM environment variable not set.\n"); + ret_error0(TGETENT_ERR, "TERM environment variable not set.\n"); } } + if (strlen(tname) > MAX_NAME_SIZE) { - ret_error(-1, "TERM environment must be <= %d characters.\n", + ret_error(TGETENT_ERR, + "TERM environment must be <= %d characters.\n", MAX_NAME_SIZE); } T(("your terminal name is %s", tname)); - term_ptr = typeCalloc(TERMINAL, 1); + /* + * Allow output redirection. This is what SVr3 does. If stdout is + * directed to a file, screen updates go to standard error. + */ + if (Filedes == STDOUT_FILENO && !isatty(Filedes)) + Filedes = STDERR_FILENO; - if (term_ptr == 0) { - ret_error0(-1, "Not enough memory to create terminal structure.\n"); - } -#if USE_DATABASE - status = grab_entry(tname, &term_ptr->type); + /* + * Check if we have already initialized to use this terminal. If so, we + * do not need to re-read the terminfo entry, or obtain TTY settings. + * + * This is an improvement on SVr4 curses. If an application mixes curses + * and termcap calls, it may call both initscr and tgetent. This is not + * really a good thing to do, but can happen if someone tries using ncurses + * with the readline library. The problem we are fixing is that when + * tgetent calls setupterm, the resulting Ottyb struct in cur_term is + * zeroed. A subsequent call to endwin uses the zeroed terminal settings + * rather than the ones saved in initscr. So we check if cur_term appears + * to contain terminal settings for the same output file as our current + * call - and copy those terminal settings. (SVr4 curses does not do this, + * however applications that are working around the problem will still work + * properly with this feature). + */ + if (reuse + && (termp = cur_term) != 0 + && termp->Filedes == Filedes + && termp->_termname != 0 + && !strcmp(termp->_termname, tname) + && _nc_name_match(termp->type.term_names, tname, "|")) { + T(("reusing existing terminal information and mode-settings")); + } else { + + termp = typeCalloc(TERMINAL, 1); + + if (termp == 0) { + ret_error0(TGETENT_ERR, + "Not enough memory to create terminal structure.\n"); + } +#if USE_DATABASE || USE_TERMCAP + status = grab_entry(tname, &termp->type); #else - status = 0; + status = TGETENT_NO; #endif - /* try fallback list if entry on disk */ - if (status != 1) { - const TERMTYPE *fallback = _nc_fallback(tname); + /* try fallback list if entry on disk */ + if (status != TGETENT_YES) { + const TERMTYPE *fallback = _nc_fallback(tname); - if (fallback) { - term_ptr->type = *fallback; - status = 1; + if (fallback) { + termp->type = *fallback; + status = TGETENT_YES; + } } - } - if (status == -1) { - ret_error0(-1, "terminals database is inaccessible\n"); - } else if (status == 0) { - ret_error(0, "'%s': unknown terminal type.\n", tname); - } + if (status != TGETENT_YES) { + del_curterm(termp); + if (status == TGETENT_ERR) { + ret_error0(status, "terminals database is inaccessible\n"); + } else if (status == TGETENT_NO) { + ret_error(status, "'%s': unknown terminal type.\n", tname); + } + } +#if !USE_REENTRANT + strncpy(ttytype, termp->type.term_names, NAMESIZE - 1); + ttytype[NAMESIZE - 1] = '\0'; +#endif - /* - * Improve on SVr4 curses. If an application mixes curses and termcap - * calls, it may call both initscr and tgetent. This is not really a - * good thing to do, but can happen if someone tries using ncurses with - * the readline library. The problem we are fixing is that when - * tgetent calls setupterm, the resulting Ottyb struct in cur_term is - * zeroed. A subsequent call to endwin uses the zeroed terminal - * settings rather than the ones saved in initscr. So we check if - * cur_term appears to contain terminal settings for the same output - * file as our current call - and copy those terminal settings. (SVr4 - * curses does not do this, however applications that are working - * around the problem will still work properly with this feature). - */ - if (cur_term != 0) { - if (cur_term->Filedes == Filedes) - term_ptr->Ottyb = cur_term->Ottyb; - } + termp->Filedes = Filedes; + termp->_termname = strdup(tname); - set_curterm(term_ptr); + set_curterm(termp); - if (command_character && getenv("CC")) - do_prototype(); + if (command_character && getenv("CC")) + do_prototype(termp); - strlcpy(ttytype, cur_term->type.term_names, NAMESIZE); + /* + * If an application calls setupterm() rather than initscr() or + * newterm(), we will not have the def_prog_mode() call in + * _nc_setupscreen(). Do it now anyway, so we can initialize the + * baudrate. + */ + if (isatty(Filedes)) { + def_prog_mode(); + baudrate(); + } + } /* - * Allow output redirection. This is what SVr3 does. - * If stdout is directed to a file, screen updates go - * to standard error. + * We should always check the screensize, just in case. */ - if (Filedes == STDOUT_FILENO && !isatty(Filedes)) - Filedes = STDERR_FILENO; - cur_term->Filedes = Filedes; - - _nc_get_screensize(&LINES, &COLS); + _nc_get_screensize(SP, ptrLines(), ptrCols()); if (errret) - *errret = 1; - - T((T_CREATE("screen %s %dx%d"), tname, LINES, COLS)); + *errret = TGETENT_YES; if (generic_type) { - ret_error(0, "'%s': I need something more specific.\n", tname); + ret_error(TGETENT_NO, "'%s': I need something more specific.\n", tname); } if (hard_copy) { - ret_error(1, "'%s': I can't handle hardcopy terminals.\n", tname); + ret_error(TGETENT_YES, "'%s': I can't handle hardcopy terminals.\n", tname); } returnCode(OK); } /* -** do_prototype() -** -** Take the real command character out of the CC environment variable -** and substitute it in for the prototype given in 'command_character'. -** -*/ - -static void -do_prototype(void) + * setupterm(termname, Filedes, errret) + * + * Find and read the appropriate object file for the terminal + * Make cur_term point to the structure. + */ +NCURSES_EXPORT(int) +setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) { - int i; - char CC; - char proto; - char *tmp; - - tmp = getenv("CC"); - CC = *tmp; - proto = *command_character; - - for_each_string(i, &(cur_term->type)) { - for (tmp = cur_term->type.Strings[i]; *tmp; tmp++) { - if (*tmp == proto) - *tmp = CC; - } - } + return _nc_setupterm(tname, Filedes, errret, FALSE); } diff --git a/lib/libcurses/tinfo/lib_termcap.c b/lib/libcurses/tinfo/lib_termcap.c index b307aac5754..66ccb8cf63d 100644 --- a/lib/libcurses/tinfo/lib_termcap.c +++ b/lib/libcurses/tinfo/lib_termcap.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_termcap.c,v 1.9 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: lib_termcap.c,v 1.10 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,27 +31,36 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * + * * + * some of the code in here was contributed by: * + * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * + * (but it has changed a lot) * ****************************************************************************/ +#define __INTERNAL_CAPS_VISIBLE #include <curses.priv.h> #include <termcap.h> #include <tic.h> +#include <ctype.h> -#define __INTERNAL_CAPS_VISIBLE #include <term_entry.h> -MODULE_ID("$From: lib_termcap.c,v 1.39 2000/12/10 02:56:30 tom Exp $") +MODULE_ID("$Id: lib_termcap.c,v 1.10 2010/01/12 23:22:06 nicm Exp $") -/* - some of the code in here was contributed by: - Magnus Bengtsson, d6mbeng@dtek.chalmers.se -*/ +NCURSES_EXPORT_VAR(char *) UP = 0; +NCURSES_EXPORT_VAR(char *) BC = 0; -NCURSES_EXPORT_VAR(char *) -UP = 0; -NCURSES_EXPORT_VAR(char *) -BC = 0; +#define MyCache _nc_globals.tgetent_cache +#define CacheInx _nc_globals.tgetent_index +#define CacheSeq _nc_globals.tgetent_sequence + +#define FIX_SGR0 MyCache[CacheInx].fix_sgr0 +#define LAST_TRM MyCache[CacheInx].last_term +#define LAST_BUF MyCache[CacheInx].last_bufp +#define LAST_USE MyCache[CacheInx].last_used +#define LAST_SEQ MyCache[CacheInx].sequence /*************************************************************************** * @@ -69,19 +78,73 @@ BC = 0; ***************************************************************************/ NCURSES_EXPORT(int) -tgetent -(char *bufp GCC_UNUSED, const char *name) +tgetent(char *bufp, const char *name) { int errcode; + int n; + bool found_cache = FALSE; + START_TRACE(); T((T_CALLED("tgetent()"))); - setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode); + _nc_setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode, TRUE); + + /* + * In general we cannot tell if the fixed sgr0 is still used by the + * caller, but if tgetent() is called with the same buffer, that is + * good enough, since the previous data would be invalidated by the + * current call. + * + * bufp may be a null pointer, e.g., GNU termcap. That allocates data, + * which is good until the next tgetent() call. The conventional termcap + * is inconvenient because of the fixed buffer size, but because it uses + * caller-supplied buffers, can have multiple terminal descriptions in + * use at a given time. + */ + for (n = 0; n < TGETENT_MAX; ++n) { + bool same_result = (MyCache[n].last_used && MyCache[n].last_bufp == bufp); + if (same_result) { + CacheInx = n; + if (FIX_SGR0 != 0) { + FreeAndNull(FIX_SGR0); + } + /* + * Also free the terminfo data that we loaded (much bigger leak). + */ + if (LAST_TRM != 0 && LAST_TRM != cur_term) { + TERMINAL *trm = LAST_TRM; + del_curterm(LAST_TRM); + for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) + if (LAST_TRM == trm) + LAST_TRM = 0; + CacheInx = n; + } + found_cache = TRUE; + break; + } + } + if (!found_cache) { + int best = 0; + + for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) { + if (LAST_SEQ < MyCache[best].sequence) { + best = CacheInx; + } + } + CacheInx = best; + } + LAST_TRM = cur_term; + LAST_SEQ = ++CacheSeq; + + PC = 0; + UP = 0; + BC = 0; + FIX_SGR0 = 0; /* don't free it - application may still use */ if (errcode == 1) { if (cursor_left) - if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) + if ((backspaces_with_bs = (char) !strcmp(cursor_left, "\b")) == 0) backspace_if_not_bs = cursor_left; /* we're required to export these */ @@ -92,6 +155,18 @@ tgetent if (backspace_if_not_bs != NULL) BC = backspace_if_not_bs; + if ((FIX_SGR0 = _nc_trim_sgr0(&(cur_term->type))) != 0) { + if (!strcmp(FIX_SGR0, exit_attribute_mode)) { + if (FIX_SGR0 != exit_attribute_mode) { + free(FIX_SGR0); + } + FIX_SGR0 = 0; + } + } + LAST_BUF = bufp; + LAST_USE = TRUE; + + SetNoPadding(SP); (void) baudrate(); /* sets ospeed as a side-effect */ /* LINT_PREPRO @@ -116,7 +191,7 @@ tgetent NCURSES_EXPORT(int) tgetflag(NCURSES_CONST char *id) { - int i; + unsigned i; T((T_CALLED("tgetflag(%s)"), id)); if (cur_term != 0) { @@ -144,7 +219,7 @@ tgetflag(NCURSES_CONST char *id) NCURSES_EXPORT(int) tgetnum(NCURSES_CONST char *id) { - int i; + unsigned i; T((T_CALLED("tgetnum(%s)"), id)); if (cur_term != 0) { @@ -171,28 +246,49 @@ tgetnum(NCURSES_CONST char *id) ***************************************************************************/ NCURSES_EXPORT(char *) -tgetstr -(NCURSES_CONST char *id, char **area) +tgetstr(NCURSES_CONST char *id, char **area) { - int i; + unsigned i; + char *result = NULL, *base; + if (area != 0 && *area != 0) + base = *area; T((T_CALLED("tgetstr(%s,%p)"), id, area)); if (cur_term != 0) { TERMTYPE *tp = &(cur_term->type); for_each_string(i, tp) { const char *capname = ExtStrname(tp, i, strcodes); if (!strncmp(id, capname, 2)) { - TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(tp->Strings[i]))); + result = tp->Strings[i]; + TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); /* setupterm forces canceled strings to null */ - if (area != 0 - && *area != 0 - && VALID_STRING(tp->Strings[i])) { - (void) strlcpy(*area, tp->Strings[i], 1024); - *area += strlen(*area) + 1; + if (VALID_STRING(result)) { + if (result == exit_attribute_mode + && FIX_SGR0 != 0) { + result = FIX_SGR0; + TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); + } + if (area != 0 && *area != 0) { + (void) strlcpy(*area, result, 1024 - (*area - base)); + result = *area; + *area += strlen(*area) + 1; + } } - returnPtr(tp->Strings[i]); + break; } } } - returnPtr(NULL); + returnPtr(result); +} + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_tgetent_leaks(void) +{ + for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) { + FreeIfNeeded(FIX_SGR0); + if (LAST_TRM != 0) + del_curterm(LAST_TRM); + } } +#endif diff --git a/lib/libcurses/tinfo/lib_termname.c b/lib/libcurses/tinfo/lib_termname.c index 8e744f1ed31..f4ddf8b334b 100644 --- a/lib/libcurses/tinfo/lib_termname.c +++ b/lib/libcurses/tinfo/lib_termname.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_termname.c,v 1.4 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: lib_termname.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2001,2003 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,21 +29,18 @@ ****************************************************************************/ #include <curses.priv.h> -#include <tic.h> /* for MAX_ALIAS */ -MODULE_ID("$From: lib_termname.c,v 1.6 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: lib_termname.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(char *) termname(void) { - char *name = getenv("TERM"); - static char ret[MAX_ALIAS + 1]; + char *name = 0; - T(("termname() called")); + T((T_CALLED("termname()"))); - if (name != 0) { - (void) strlcpy(ret, name, sizeof(ret)); - name = ret; - } - return name; + if (cur_term != 0) + name = cur_term->_termname; + + returnPtr(name); } diff --git a/lib/libcurses/tinfo/lib_tgoto.c b/lib/libcurses/tinfo/lib_tgoto.c index bb7fb9c2670..536771fd17e 100644 --- a/lib/libcurses/tinfo/lib_tgoto.c +++ b/lib/libcurses/tinfo/lib_tgoto.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_tgoto.c,v 1.4 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: lib_tgoto.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2000 Free Software Foundation, Inc. * + * Copyright (c) 2000-2006,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,7 +37,7 @@ #include <ctype.h> #include <termcap.h> -MODULE_ID("$From: lib_tgoto.c,v 1.5 2000/12/10 01:33:16 tom Exp $") +MODULE_ID("$Id: lib_tgoto.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") #if !PURE_TERMINFO static bool @@ -91,13 +91,13 @@ tgoto_internal(const char *string, int x, int y) while (*string != 0) { if ((used + need) > length) { length += (used + need); - if ((result = _nc_doalloc(result, length)) == 0) { + if ((result = typeRealloc(char, length, result)) == 0) { length = 0; break; } } if (*string == '%') { - char *fmt = 0; + const char *fmt = 0; switch (*++string) { case '\0': @@ -115,7 +115,7 @@ tgoto_internal(const char *string, int x, int y) *value %= 1000; break; case '+': - *value += CharOf(*++string); + *value += UChar(*++string); /* FALLTHRU */ case '.': /* @@ -131,7 +131,7 @@ tgoto_internal(const char *string, int x, int y) *value = 0200; /* tputs will treat this as \0 */ } } - result[used++] = *value++; + result[used++] = (char) *value++; break; case '%': result[used++] = *string; @@ -158,7 +158,7 @@ tgoto_internal(const char *string, int x, int y) *value = 16 * (*value / 10) + (*value % 10); break; case 'D': /* Reverse coding (Delta Data) */ - *value -= 2 * (*value / 16); + *value -= 2 * (*value % 16); break; } if (fmt != 0) { @@ -175,14 +175,14 @@ tgoto_internal(const char *string, int x, int y) } string++; } - if (need_BC) { + if (result != 0) { copied = strlcpy(result + used, BC, length - used); if (copied < length - used) used += copied; else used += length - used - 1; + result[used] = '\0'; } - result[used] = '\0'; return result; } #endif @@ -192,8 +192,7 @@ tgoto_internal(const char *string, int x, int y) * the last two arguments when invoking tparm(). */ NCURSES_EXPORT(char *) -tgoto -(const char *string, int x, int y) +tgoto(const char *string, int x, int y) { char *result; @@ -203,6 +202,6 @@ tgoto result = tgoto_internal(string, x, y); else #endif - result = tparm((NCURSES_CONST char *) string, y, x); + result = TPARM_2((NCURSES_CONST char *) string, y, x); returnPtr(result); } diff --git a/lib/libcurses/tinfo/lib_ti.c b/lib/libcurses/tinfo/lib_ti.c index 3c1595aef0c..9416c56cca9 100644 --- a/lib/libcurses/tinfo/lib_ti.c +++ b/lib/libcurses/tinfo/lib_ti.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_ti.c,v 1.6 2001/01/22 18:01:54 millert Exp $ */ +/* $OpenBSD: lib_ti.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,12 +38,12 @@ #include <term_entry.h> #include <tic.h> -MODULE_ID("$From: lib_ti.c,v 1.22 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: lib_ti.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(int) tigetflag(NCURSES_CONST char *str) { - int i; + unsigned i; T((T_CALLED("tigetflag(%s)"), str)); @@ -64,7 +64,7 @@ tigetflag(NCURSES_CONST char *str) NCURSES_EXPORT(int) tigetnum(NCURSES_CONST char *str) { - int i; + unsigned i; T((T_CALLED("tigetnum(%s)"), str)); @@ -86,7 +86,7 @@ tigetnum(NCURSES_CONST char *str) NCURSES_EXPORT(char *) tigetstr(NCURSES_CONST char *str) { - int i; + unsigned i; T((T_CALLED("tigetstr(%s)"), str)); diff --git a/lib/libcurses/tinfo/lib_tparm.c b/lib/libcurses/tinfo/lib_tparm.c index 3cdd7b915fc..45c07f01e06 100644 --- a/lib/libcurses/tinfo/lib_tparm.c +++ b/lib/libcurses/tinfo/lib_tparm.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_tparm.c,v 1.8 2003/03/17 19:16:59 millert Exp $ */ +/* $OpenBSD: lib_tparm.c,v 1.9 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey, 1996 on * ****************************************************************************/ /* @@ -44,7 +45,7 @@ #include <term.h> #include <tic.h> -MODULE_ID("$From: lib_tparm.c,v 1.51 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: lib_tparm.c,v 1.9 2010/01/12 23:22:06 nicm Exp $") /* * char * @@ -106,57 +107,37 @@ MODULE_ID("$From: lib_tparm.c,v 1.51 2000/12/10 02:55:08 tom Exp $") * resulting in x mod y, not the reverse. */ -#define STACKSIZE 20 +NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0; -typedef struct { - union { - unsigned int num; - char *str; - } data; - bool num_type; -} stack_frame; - -static stack_frame stack[STACKSIZE]; -static int stack_ptr; - -#ifdef TRACE -static const char *tname; -#endif /* TRACE */ - -static char *out_buff; -static size_t out_size; -static size_t out_used; +#define TPS(var) _nc_prescreen.tparm_state.var #if NO_LEAKS NCURSES_EXPORT(void) _nc_free_tparm(void) { - if (out_buff != 0) { - FreeAndNull(out_buff); - out_size = 0; - out_used = 0; + if (TPS(out_buff) != 0) { + FreeAndNull(TPS(out_buff)); + TPS(out_size) = 0; + TPS(out_used) = 0; + FreeAndNull(TPS(fmt_buff)); + TPS(fmt_size) = 0; } } #endif -static void -really_get_space(size_t need) -{ - out_size = need * 2; - out_buff = typeRealloc(char, out_size, out_buff); - if (out_buff == 0) - _nc_err_abort("Out of memory"); -} - -static inline void +static NCURSES_INLINE void get_space(size_t need) { - need += out_used; - if (need > out_size) - really_get_space(need); + need += TPS(out_used); + if (need > TPS(out_size)) { + TPS(out_size) = need * 2; + TPS(out_buff) = typeRealloc(char, TPS(out_size), TPS(out_buff)); + if (TPS(out_buff) == 0) + _nc_err_abort(MSG_NO_MEMORY); + } } -static inline void +static NCURSES_INLINE void save_text(const char *fmt, const char *s, int len) { size_t s_len = strlen(s); @@ -165,222 +146,223 @@ save_text(const char *fmt, const char *s, int len) get_space(s_len + 1); - (void) snprintf(out_buff + out_used, out_size - out_used, fmt, s); - out_used += strlen(out_buff + out_used); + (void) snprintf(TPS(out_buff) + TPS(out_used), TPS(out_size) - TPS(out_used), fmt, s); + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); } -static inline void +static NCURSES_INLINE void save_number(const char *fmt, int number, int len) { if (len < 30) len = 30; /* actually log10(MAX_INT)+1 */ - get_space(len + 1); + get_space((unsigned) len + 1); - (void) snprintf(out_buff + out_used, out_size - out_used, fmt, number); - out_used += strlen(out_buff + out_used); + (void) snprintf(TPS(out_buff) + TPS(out_used), TPS(out_size) - TPS(out_used), fmt, number); + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); } -static inline void +static NCURSES_INLINE void save_char(int c) { if (c == 0) c = 0200; get_space(1); - out_buff[out_used++] = c; + TPS(out_buff)[TPS(out_used)++] = (char) c; } -static inline void +static NCURSES_INLINE void npush(int x) { - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num_type = TRUE; - stack[stack_ptr].data.num = x; - stack_ptr++; + if (TPS(stack_ptr) < STACKSIZE) { + TPS(stack)[TPS(stack_ptr)].num_type = TRUE; + TPS(stack)[TPS(stack_ptr)].data.num = x; + TPS(stack_ptr)++; + } else { + DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; } } -static inline int +static NCURSES_INLINE int npop(void) { int result = 0; - if (stack_ptr > 0) { - stack_ptr--; - if (stack[stack_ptr].num_type) - result = stack[stack_ptr].data.num; + if (TPS(stack_ptr) > 0) { + TPS(stack_ptr)--; + if (TPS(stack)[TPS(stack_ptr)].num_type) + result = TPS(stack)[TPS(stack_ptr)].data.num; + } else { + DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; } return result; } -static inline void +static NCURSES_INLINE void spush(char *x) { - if (stack_ptr < STACKSIZE) { - stack[stack_ptr].num_type = FALSE; - stack[stack_ptr].data.str = x; - stack_ptr++; + if (TPS(stack_ptr) < STACKSIZE) { + TPS(stack)[TPS(stack_ptr)].num_type = FALSE; + TPS(stack)[TPS(stack_ptr)].data.str = x; + TPS(stack_ptr)++; + } else { + DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; } } -static inline char * +static NCURSES_INLINE char * spop(void) { static char dummy[] = ""; /* avoid const-cast */ char *result = dummy; - if (stack_ptr > 0) { - stack_ptr--; - if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0) - result = stack[stack_ptr].data.str; + if (TPS(stack_ptr) > 0) { + TPS(stack_ptr)--; + if (!TPS(stack)[TPS(stack_ptr)].num_type + && TPS(stack)[TPS(stack_ptr)].data.str != 0) + result = TPS(stack)[TPS(stack_ptr)].data.str; + } else { + DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); + _nc_tparm_err++; } return result; } -static inline const char * +static NCURSES_INLINE const char * parse_format(const char *s, char *format, int *len) { - bool done = FALSE; - bool allowminus = FALSE; - bool dot = FALSE; - bool err = FALSE; - char *fmt = format; - int prec = 0; - int width = 0; - int value = 0; - *len = 0; - *format++ = '%'; - while (*s != '\0' && !done) { - switch (*s) { - case 'c': /* FALLTHRU */ - case 'd': /* FALLTHRU */ - case 'o': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - case 's': - *format++ = *s; - done = TRUE; - break; - case '.': - *format++ = *s++; - if (dot) { - err = TRUE; - } else { - dot = TRUE; - prec = value; - } - value = 0; - break; - case '#': - *format++ = *s++; - break; - case ' ': - *format++ = *s++; - break; - case ':': - s++; - allowminus = TRUE; - break; - case '-': - if (allowminus) { - *format++ = *s++; - } else { + if (format != 0) { + bool done = FALSE; + bool allowminus = FALSE; + bool dot = FALSE; + bool err = FALSE; + char *fmt = format; + int my_width = 0; + int my_prec = 0; + int value = 0; + + *len = 0; + *format++ = '%'; + while (*s != '\0' && !done) { + switch (*s) { + case 'c': /* FALLTHRU */ + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 's': + *format++ = *s; done = TRUE; - } - break; - default: - if (isdigit(CharOf(*s))) { - value = (value * 10) + (*s - '0'); - if (value > 10000) + break; + case '.': + *format++ = *s++; + if (dot) { err = TRUE; + } else { /* value before '.' is the width */ + dot = TRUE; + my_width = value; + } + value = 0; + break; + case '#': *format++ = *s++; - } else { - done = TRUE; + break; + case ' ': + *format++ = *s++; + break; + case ':': + s++; + allowminus = TRUE; + break; + case '-': + if (allowminus) { + *format++ = *s++; + } else { + done = TRUE; + } + break; + default: + if (isdigit(UChar(*s))) { + value = (value * 10) + (*s - '0'); + if (value > 10000) + err = TRUE; + *format++ = *s++; + } else { + done = TRUE; + } } } - } - - /* - * If we found an error, ignore (and remove) the flags. - */ - if (err) { - prec = width = value = 0; - format = fmt; - *format++ = '%'; - *format++ = *s; - } - if (dot) - width = value; - else - prec = value; + /* + * If we found an error, ignore (and remove) the flags. + */ + if (err) { + my_width = my_prec = value = 0; + format = fmt; + *format++ = '%'; + *format++ = *s; + } - *format = '\0'; - /* return maximum string length in print */ - *len = (prec > width) ? prec : width; + /* + * Any value after '.' is the precision. If we did not see '.', then + * the value is the width. + */ + if (dot) + my_prec = value; + else + my_width = value; + + *format = '\0'; + /* return maximum string length in print */ + *len = (my_width > my_prec) ? my_width : my_prec; + } return s; } #define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') #define isLOWER(c) ((c) >= 'a' && (c) <= 'z') -static inline char * -tparam_internal(const char *string, va_list ap) +/* + * Analyze the string to see how many parameters we need from the varargs list, + * and what their types are. We will only accept string parameters if they + * appear as a %l or %s format following an explicit parameter reference (e.g., + * %p2%s). All other parameters are numbers. + * + * 'number' counts coarsely the number of pop's we see in the string, and + * 'popcount' shows the highest parameter number in the string. We would like + * to simply use the latter count, but if we are reading termcap strings, there + * may be cases that we cannot see the explicit parameter numbers. + */ +NCURSES_EXPORT(int) +_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) { -#define NUM_VARS 26 - char *p_is_s[9]; - int param[9]; - int lastpop; - int popcount; - int number; - int len; - int level; - int x, y; - int i; size_t len2; - register const char *cp; - static size_t len_fmt; + int i; + int lastpop = -1; + int len; + int number = 0; + const char *cp = string; static char dummy[] = ""; - static char *format; - static int dynamic_var[NUM_VARS]; - static int static_vars[NUM_VARS]; - out_used = 0; - if (string == NULL) - return NULL; + if (cp == 0) + return 0; - if ((len2 = strlen(string)) > len_fmt) { - len_fmt = len2 + len_fmt + 2; - if ((format = typeRealloc(char, len_fmt, format)) == 0) - return 0; + if ((len2 = strlen(cp)) > TPS(fmt_size)) { + TPS(fmt_size) = len2 + TPS(fmt_size) + 2; + TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff)); + if (TPS(fmt_buff) == 0) + return 0; } - /* - * Find the highest parameter-number referred to in the format string. - * Use this value to limit the number of arguments copied from the - * variable-length argument list. - */ - - number = 0; - lastpop = -1; - popcount = 0; - memset(p_is_s, 0, sizeof(p_is_s)); + memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM); + *popcount = 0; - /* - * Analyze the string to see how many parameters we need from the varargs - * list, and what their types are. We will only accept string parameters - * if they appear as a %l or %s format following an explicit parameter - * reference (e.g., %p2%s). All other parameters are numbers. - * - * 'number' counts coarsely the number of pop's we see in the string, and - * 'popcount' shows the highest parameter number in the string. We would - * like to simply use the latter count, but if we are reading termcap - * strings, there may be cases that we cannot see the explicit parameter - * numbers. - */ - for (cp = string; (cp - string) < (int) len2;) { + while ((cp - string) < (int) len2) { if (*cp == '%') { cp++; - cp = parse_format(cp, format, &len); + cp = parse_format(cp, TPS(fmt_buff), &len); switch (*cp) { default: break; @@ -390,7 +372,8 @@ tparam_internal(const char *string, va_list ap) case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ - number++; + if (lastpop <= 0) + number++; lastpop = -1; break; @@ -403,15 +386,19 @@ tparam_internal(const char *string, va_list ap) case 'p': cp++; - i = (*cp - '0'); - if (i >= 0 && i <= 9) { + i = (UChar(*cp) - '0'); + if (i >= 0 && i <= NUM_PARM) { lastpop = i; - if (lastpop > popcount) - popcount = lastpop; + if (lastpop > *popcount) + *popcount = lastpop; } break; case 'P': + ++number; + ++cp; + break; + case 'g': cp++; break; @@ -423,7 +410,7 @@ tparam_internal(const char *string, va_list ap) case L_BRACE: cp++; - while (*cp >= '0' && *cp <= '9') { + while (isdigit(UChar(*cp))) { cp++; } break; @@ -441,16 +428,18 @@ tparam_internal(const char *string, va_list ap) case '=': case '<': case '>': + lastpop = -1; + number += 2; + break; + case '!': case '~': lastpop = -1; - number += 2; + ++number; break; case 'i': - lastpop = -1; - if (popcount < 2) - popcount = 2; + /* will add 1 to first (usually two) parameters */ break; } } @@ -458,18 +447,52 @@ tparam_internal(const char *string, va_list ap) cp++; } - if (number > 9) - number = 9; + if (number > NUM_PARM) + number = NUM_PARM; + return number; +} + +static NCURSES_INLINE char * +tparam_internal(const char *string, va_list ap) +{ + char *p_is_s[NUM_PARM]; + TPARM_ARG param[NUM_PARM]; + int popcount; + int number; + int len; + int level; + int x, y; + int i; + const char *cp = string; + size_t len2; + + if (cp == NULL) + return NULL; + + TPS(out_used) = 0; + len2 = strlen(cp); + + /* + * Find the highest parameter-number referred to in the format string. + * Use this value to limit the number of arguments copied from the + * variable-length argument list. + */ + number = _nc_tparm_analyze(cp, p_is_s, &popcount); + if (TPS(fmt_buff) == 0) + return NULL; + for (i = 0; i < max(popcount, number); i++) { /* * A few caps (such as plab_norm) have string-valued parms. * We'll have to assume that the caller knows the difference, since - * a char* and an int may not be the same size on the stack. + * a char* and an int may not be the same size on the stack. The + * normal prototype for this uses 9 long's, which is consistent with + * our va_arg() usage. */ if (p_is_s[i] != 0) { p_is_s[i] = va_arg(ap, char *); } else { - param[i] = va_arg(ap, int); + param[i] = va_arg(ap, TPARM_ARG); } } @@ -480,32 +503,37 @@ tparam_internal(const char *string, va_list ap) * the expansion of (for example) \E[%d;%dH work correctly in termcap * style, which means tparam() will expand termcap strings OK. */ - stack_ptr = 0; + TPS(stack_ptr) = 0; if (popcount == 0) { popcount = number; - for (i = number - 1; i >= 0; i--) - npush(param[i]); + for (i = number - 1; i >= 0; i--) { + if (p_is_s[i]) + spush(p_is_s[i]); + else + npush(param[i]); + } } #ifdef TRACE - if (_nc_tracing & TRACE_CALLS) { + if (USE_TRACEF(TRACE_CALLS)) { for (i = 0; i < popcount; i++) { if (p_is_s[i] != 0) save_text(", %s", _nc_visbuf(p_is_s[i]), 0); else save_number(", %d", param[i], 0); } - _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), out_buff); - out_used = 0; + _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff)); + TPS(out_used) = 0; + _nc_unlock_global(tracef); } #endif /* TRACE */ - while (*string) { - if (*string != '%') { - save_char(*string); + while ((cp - string) < (int) len2) { + if (*cp != '%') { + save_char(UChar(*cp)); } else { - string++; - string = parse_format(string, format, &len); - switch (*string) { + TPS(tparam_base) = cp++; + cp = parse_format(cp, TPS(fmt_buff), &len); + switch (*cp) { default: break; case '%': @@ -516,22 +544,25 @@ tparam_internal(const char *string, va_list ap) case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ + save_number(TPS(fmt_buff), npop(), len); + break; + case 'c': /* FALLTHRU */ - save_number(format, npop(), len); + save_char(npop()); break; case 'l': - save_number("%d", strlen(spop()), 0); + save_number("%d", (int) strlen(spop()), 0); break; case 's': - save_text(format, spop(), len); + save_text(TPS(fmt_buff), spop(), len); break; case 'p': - string++; - i = (*string - '1'); - if (i >= 0 && i < 9) { + cp++; + i = (UChar(*cp) - '1'); + if (i >= 0 && i < NUM_PARM) { if (p_is_s[i]) spush(p_is_s[i]); else @@ -540,39 +571,39 @@ tparam_internal(const char *string, va_list ap) break; case 'P': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - static_vars[i] = npop(); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - dynamic_var[i] = npop(); + cp++; + if (isUPPER(*cp)) { + i = (UChar(*cp) - 'A'); + TPS(static_vars)[i] = npop(); + } else if (isLOWER(*cp)) { + i = (UChar(*cp) - 'a'); + TPS(dynamic_var)[i] = npop(); } break; case 'g': - string++; - if (isUPPER(*string)) { - i = (*string - 'A'); - npush(static_vars[i]); - } else if (isLOWER(*string)) { - i = (*string - 'a'); - npush(dynamic_var[i]); + cp++; + if (isUPPER(*cp)) { + i = (UChar(*cp) - 'A'); + npush(TPS(static_vars)[i]); + } else if (isLOWER(*cp)) { + i = (UChar(*cp) - 'a'); + npush(TPS(dynamic_var)[i]); } break; case S_QUOTE: - string++; - npush(*string); - string++; + cp++; + npush(UChar(*cp)); + cp++; break; case L_BRACE: number = 0; - string++; - while (*string >= '0' && *string <= '9') { - number = number * 10 + *string - '0'; - string++; + cp++; + while (isdigit(UChar(*cp))) { + number = (number * 10) + (UChar(*cp) - '0'); + cp++; } npush(number); break; @@ -663,38 +694,38 @@ tparam_internal(const char *string, va_list ap) x = npop(); if (!x) { /* scan forward for %e or %; at level zero */ - string++; + cp++; level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') + while (*cp) { + if (*cp == '%') { + cp++; + if (*cp == '?') level++; - else if (*string == ';') { + else if (*cp == ';') { if (level > 0) level--; else break; - } else if (*string == 'e' && level == 0) + } else if (*cp == 'e' && level == 0) break; } - if (*string) - string++; + if (*cp) + cp++; } } break; case 'e': /* scan forward for a %; at level zero */ - string++; + cp++; level = 0; - while (*string) { - if (*string == '%') { - string++; - if (*string == '?') + while (*cp) { + if (*cp == '%') { + cp++; + if (*cp == '?') level++; - else if (*string == ';') { + else if (*cp == ';') { if (level > 0) level--; else @@ -702,42 +733,65 @@ tparam_internal(const char *string, va_list ap) } } - if (*string) - string++; + if (*cp) + cp++; } break; case ';': break; - } /* endswitch (*string) */ - } /* endelse (*string == '%') */ + } /* endswitch (*cp) */ + } /* endelse (*cp == '%') */ - if (*string == '\0') + if (*cp == '\0') break; - string++; - } /* endwhile (*string) */ + cp++; + } /* endwhile (*cp) */ get_space(1); - out_buff[out_used] = '\0'; + TPS(out_buff)[TPS(out_used)] = '\0'; - T((T_RETURN("%s"), _nc_visbuf(out_buff))); - return (out_buff); + T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff)))); + return (TPS(out_buff)); } +#if NCURSES_TPARM_VARARGS +#define tparm_varargs tparm +#else +#define tparm_proto tparm +#endif + NCURSES_EXPORT(char *) -tparm -(NCURSES_CONST char *string,...) +tparm_varargs(NCURSES_CONST char *string,...) { va_list ap; char *result; + _nc_tparm_err = 0; va_start(ap, string); #ifdef TRACE - tname = "tparm"; + TPS(tname) = "tparm"; #endif /* TRACE */ result = tparam_internal(string, ap); va_end(ap); return result; } + +#if !NCURSES_TPARM_VARARGS +NCURSES_EXPORT(char *) +tparm_proto(NCURSES_CONST char *string, + TPARM_ARG a1, + TPARM_ARG a2, + TPARM_ARG a3, + TPARM_ARG a4, + TPARM_ARG a5, + TPARM_ARG a6, + TPARM_ARG a7, + TPARM_ARG a8, + TPARM_ARG a9) +{ + return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9); +} +#endif /* NCURSES_TPARM_VARARGS */ diff --git a/lib/libcurses/tinfo/lib_tputs.c b/lib/libcurses/tinfo/lib_tputs.c index 634d0317114..c085ecfb77f 100644 --- a/lib/libcurses/tinfo/lib_tputs.c +++ b/lib/libcurses/tinfo/lib_tputs.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_tputs.c,v 1.11 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: lib_tputs.c,v 1.12 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -47,16 +48,30 @@ #include <termcap.h> /* ospeed */ #include <tic.h> -MODULE_ID("$From: lib_tputs.c,v 1.55 2000/12/10 02:55:08 tom Exp $"); +MODULE_ID("$Id: lib_tputs.c,v 1.12 2010/01/12 23:22:06 nicm Exp $") -NCURSES_EXPORT_VAR(char) -PC = 0; /* used by termcap library */ -NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ +NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */ +NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ -NCURSES_EXPORT_VAR(int) -_nc_nulls_sent = 0; /* used by 'tack' program */ +NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */ - static int (*my_outch) (int c) = _nc_outch; +#if NCURSES_NO_PADDING +NCURSES_EXPORT(void) +_nc_set_no_padding(SCREEN *sp) +{ + bool no_padding = (getenv("NCURSES_NO_PADDING") != 0); + + if (sp) + sp->_no_padding = no_padding; + else + _nc_prescreen._no_padding = no_padding; + + TR(TRACE_CHARPUT | TRACE_MOVE, ("padding will%s be used", + GetNoPadding(sp) ? " not" : "")); +} +#endif + +static int (*my_outch) (int c) = _nc_outch; NCURSES_EXPORT(int) delay_output(int ms) @@ -69,7 +84,7 @@ delay_output(int ms) } else { register int nullcount; - nullcount = (ms * _nc_baudrate(ospeed)) / 10000; + nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000); for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) my_outch(PC); if (my_outch == _nc_outch) @@ -88,9 +103,7 @@ _nc_flush(void) NCURSES_EXPORT(int) _nc_outch(int ch) { -#ifdef TRACE - _nc_outchars++; -#endif /* TRACE */ + COUNT_OUTCHARS(1); if (SP != 0 && SP->_cleanup) { @@ -106,72 +119,6 @@ _nc_outch(int ch) return OK; } -#if USE_WIDEC_SUPPORT -/* - * Reference: The Unicode Standard 2.0 - * - * No surrogates supported (we're storing only one 16-bit Unicode value per - * cell). - */ -NCURSES_EXPORT(int) -_nc_utf8_outch(int ch) -{ - static const unsigned byteMask = 0xBF; - static const unsigned otherMark = 0x80; - static const unsigned firstMark[] = - {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; - - int result[7], *ptr; - int count = 0; - - if ((unsigned int) ch < 0x80) - count = 1; - else if ((unsigned int) ch < 0x800) - count = 2; - else if ((unsigned int) ch < 0x10000) - count = 3; - else if ((unsigned int) ch < 0x200000) - count = 4; - else if ((unsigned int) ch < 0x4000000) - count = 5; - else if ((unsigned int) ch <= 0x7FFFFFFF) - count = 6; - else { - count = 3; - ch = 0xFFFD; - } - ptr = result + count; - switch (count) { - case 6: - *--ptr = (ch | otherMark) & byteMask; - ch >>= 6; - /* FALLTHRU */ - case 5: - *--ptr = (ch | otherMark) & byteMask; - ch >>= 6; - /* FALLTHRU */ - case 4: - *--ptr = (ch | otherMark) & byteMask; - ch >>= 6; - /* FALLTHRU */ - case 3: - *--ptr = (ch | otherMark) & byteMask; - ch >>= 6; - /* FALLTHRU */ - case 2: - *--ptr = (ch | otherMark) & byteMask; - ch >>= 6; - /* FALLTHRU */ - case 1: - *--ptr = (ch | firstMark[count]); - break; - } - while (count--) - _nc_outch(*ptr++); - return OK; -} -#endif - NCURSES_EXPORT(int) putp(const char *string) { @@ -179,8 +126,7 @@ putp(const char *string) } NCURSES_EXPORT(int) -tputs -(const char *string, int affcnt, int (*outc) (int)) +tputs(const char *string, int affcnt, int (*outc) (int)) { bool always_delay; bool normal_delay; @@ -192,7 +138,7 @@ tputs #ifdef TRACE char addrbuf[32]; - if (_nc_tracing & TRACE_TPUTS) { + if (USE_TRACEF(TRACE_TPUTS)) { if (outc == _nc_outch) (void) strlcpy(addrbuf, "_nc_outch", sizeof(addrbuf)); else @@ -203,7 +149,8 @@ tputs } else { _tracef("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf); } - _nc_tputs_trace = (char *) NULL; + TPUTS_TRACE(NULL); + _nc_unlock_global(tracef); } #endif /* TRACE */ @@ -219,7 +166,7 @@ tputs !xon_xoff && padding_baud_rate #if NCURSES_NO_PADDING - && (SP == 0 || !(SP->_no_padding)) + && !GetNoPadding(SP) #endif && (_nc_baudrate(ospeed) >= padding_baud_rate); } @@ -230,19 +177,19 @@ tputs * (like nethack) actually do the likes of tputs("50") to get delays. */ trailpad = 0; - if (isdigit(*string)) { - while (isdigit(*string)) { + if (isdigit(UChar(*string))) { + while (isdigit(UChar(*string))) { trailpad = trailpad * 10 + (*string - '0'); string++; } trailpad *= 10; if (*string == '.') { string++; - if (isdigit(*string)) { + if (isdigit(UChar(*string))) { trailpad += (*string - '0'); string++; } - while (isdigit(*string)) + while (isdigit(UChar(*string))) string++; } @@ -267,7 +214,7 @@ tputs bool mandatory; string++; - if ((!isdigit(CharOf(*string)) && *string != '.') + if ((!isdigit(UChar(*string)) && *string != '.') || !strchr(string, '>')) { (*outc) ('$'); (*outc) ('<'); @@ -275,18 +222,18 @@ tputs } number = 0; - while (isdigit(CharOf(*string))) { + while (isdigit(UChar(*string))) { number = number * 10 + (*string - '0'); string++; } number *= 10; if (*string == '.') { string++; - if (isdigit(CharOf(*string))) { + if (isdigit(UChar(*string))) { number += (*string - '0'); string++; } - while (isdigit(CharOf(*string))) + while (isdigit(UChar(*string))) string++; } diff --git a/lib/libcurses/tinfo/lib_ttyflags.c b/lib/libcurses/tinfo/lib_ttyflags.c index 615e0092564..ec604dcaa53 100644 --- a/lib/libcurses/tinfo/lib_ttyflags.c +++ b/lib/libcurses/tinfo/lib_ttyflags.c @@ -1,7 +1,7 @@ -/* $OpenBSD: lib_ttyflags.c,v 1.4 2001/01/22 18:01:54 millert Exp $ */ +/* $OpenBSD: lib_ttyflags.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,79 +40,114 @@ #include <curses.priv.h> #include <term.h> /* cur_term */ -MODULE_ID("$From: lib_ttyflags.c,v 1.5 2000/12/10 02:55:08 tom Exp $") - -#undef tabs - -#ifdef TAB3 -# define tabs TAB3 -#else -# ifdef XTABS -# define tabs XTABS -# else -# ifdef OXTABS -# define tabs OXTABS -# else -# define tabs 0 -# endif -# endif -#endif +MODULE_ID("$Id: lib_ttyflags.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(int) _nc_get_tty_mode(TTY * buf) { - if (cur_term == 0 - || GET_TTY(cur_term->Filedes, buf) != 0) - return (ERR); - TR(TRACE_BITS, ("_nc_get_tty_mode: %s", _nc_tracebits())); - return (OK); + int result = OK; + + if (buf == 0) { + result = ERR; + } else { + if (cur_term == 0) { + result = ERR; + } else { + for (;;) { + if (GET_TTY(cur_term->Filedes, buf) != 0) { + if (errno == EINTR) + continue; + result = ERR; + } + break; + } + } + + if (result == ERR) + memset(buf, 0, sizeof(*buf)); + + TR(TRACE_BITS, ("_nc_get_tty_mode(%d): %s", + cur_term ? cur_term->Filedes : -1, + _nc_trace_ttymode(buf))); + } + return (result); } NCURSES_EXPORT(int) _nc_set_tty_mode(TTY * buf) { - if (cur_term == 0 - || SET_TTY(cur_term->Filedes, buf) != 0) - return (ERR); - TR(TRACE_BITS, ("_nc_set_tty_mode: %s", _nc_tracebits())); - return (OK); + int result = OK; + + if (buf == 0) { + result = ERR; + } else { + if (cur_term == 0) { + result = ERR; + } else { + for (;;) { + if (SET_TTY(cur_term->Filedes, buf) != 0) { + if (errno == EINTR) + continue; + if ((errno == ENOTTY) && (SP != 0)) + SP->_notty = TRUE; + result = ERR; + } + break; + } + } + TR(TRACE_BITS, ("_nc_set_tty_mode(%d): %s", + cur_term ? cur_term->Filedes : -1, + _nc_trace_ttymode(buf))); + } + return (result); } NCURSES_EXPORT(int) def_shell_mode(void) { - T((T_CALLED("def_shell_mode()"))); + int rc = ERR; - /* - * Turn off the XTABS bit in the tty structure if it was on. If XTABS - * was on, remove the tab and backtab capabilities. - */ + T((T_CALLED("def_shell_mode()"))); - if (_nc_get_tty_mode(&cur_term->Ottyb) != OK) - returnCode(ERR); + if (cur_term != 0) { + /* + * If XTABS was on, remove the tab and backtab capabilities. + */ + if (_nc_get_tty_mode(&cur_term->Ottyb) == OK) { #ifdef TERMIOS - if (cur_term->Ottyb.c_oflag & tabs) - tab = back_tab = NULL; + if (cur_term->Ottyb.c_oflag & OFLAGS_TABS) + tab = back_tab = NULL; #else - if (cur_term->Ottyb.sg_flags & XTABS) - tab = back_tab = NULL; + if (cur_term->Ottyb.sg_flags & XTABS) + tab = back_tab = NULL; #endif - returnCode(OK); + rc = OK; + } + } + returnCode(rc); } NCURSES_EXPORT(int) def_prog_mode(void) { + int rc = ERR; + T((T_CALLED("def_prog_mode()"))); - if (_nc_get_tty_mode(&cur_term->Nttyb) != OK) - returnCode(ERR); + if (cur_term != 0) { + /* + * Turn off the XTABS bit in the tty structure if it was on. + */ + if (_nc_get_tty_mode(&cur_term->Nttyb) == OK) { #ifdef TERMIOS - cur_term->Nttyb.c_oflag &= ~tabs; + cur_term->Nttyb.c_oflag &= ~OFLAGS_TABS; #else - cur_term->Nttyb.sg_flags &= ~XTABS; + cur_term->Nttyb.sg_flags &= ~XTABS; #endif - returnCode(OK); + rc = OK; + } + } + returnCode(rc); } NCURSES_EXPORT(int) @@ -121,13 +156,14 @@ reset_prog_mode(void) T((T_CALLED("reset_prog_mode()"))); if (cur_term != 0) { - _nc_set_tty_mode(&cur_term->Nttyb); - if (SP) { - if (stdscr && stdscr->_use_keypad) - _nc_keypad(TRUE); - NC_BUFFERED(TRUE); + if (_nc_set_tty_mode(&cur_term->Nttyb) == OK) { + if (SP) { + if (SP->_keypad_on) + _nc_keypad(SP, TRUE); + NC_BUFFERED(TRUE); + } + returnCode(OK); } - returnCode(OK); } returnCode(ERR); } @@ -139,7 +175,7 @@ reset_shell_mode(void) if (cur_term != 0) { if (SP) { - _nc_keypad(FALSE); + _nc_keypad(SP, FALSE); _nc_flush(); NC_BUFFERED(FALSE); } @@ -148,19 +184,33 @@ reset_shell_mode(void) returnCode(ERR); } +static TTY * +saved_tty(void) +{ + TTY *result = 0; + + if (SP != 0) { + result = &(SP->_saved_tty); + } else { + if (_nc_prescreen.saved_tty == 0) { + _nc_prescreen.saved_tty = typeCalloc(TTY, 1); + } + result = _nc_prescreen.saved_tty; + } + return result; +} + /* ** savetty() and resetty() ** */ -static TTY buf; - NCURSES_EXPORT(int) savetty(void) { T((T_CALLED("savetty()"))); - returnCode(_nc_get_tty_mode(&buf)); + returnCode(_nc_get_tty_mode(saved_tty())); } NCURSES_EXPORT(int) @@ -168,5 +218,5 @@ resetty(void) { T((T_CALLED("resetty()"))); - returnCode(_nc_set_tty_mode(&buf)); + returnCode(_nc_set_tty_mode(saved_tty())); } diff --git a/lib/libcurses/tinfo/make_keys.c b/lib/libcurses/tinfo/make_keys.c index 0b6697d0319..caec31c9ffc 100644 --- a/lib/libcurses/tinfo/make_keys.c +++ b/lib/libcurses/tinfo/make_keys.c @@ -1,7 +1,7 @@ -/* $OpenBSD: make_keys.c,v 1.8 2006/10/10 21:38:16 cloder Exp $ */ +/* $OpenBSD: make_keys.c,v 1.9 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +29,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1997 * + * Author: Thomas E. Dickey 1997-on * ****************************************************************************/ /* @@ -37,9 +37,11 @@ * making the output show the indices into the TERMTYPE Strings array. Doing * it that way lets us cut down on the size of the init_keytry() function. */ + +#define USE_TERMLIB 1 #include <curses.priv.h> -MODULE_ID("$From: make_keys.c,v 1.10 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: make_keys.c,v 1.9 2010/01/12 23:22:06 nicm Exp $") #include <names.c> @@ -68,17 +70,23 @@ lookup(const char *name) } static void -make_keys(FILE * ifp, FILE * ofp) +make_keys(FILE *ifp, FILE *ofp) { char buffer[BUFSIZ]; - char from[BUFSIZ]; - char to[BUFSIZ]; + char from[256]; + char to[256]; int maxlen = 16; + int scanned; while (fgets(buffer, sizeof(buffer), ifp) != NULL) { if (*buffer == '#') continue; - if (sscanf(buffer, "%s %s", to, from) == 2) { + + to[sizeof(to) - 1] = '\0'; + from[sizeof(from) - 1] = '\0'; + + scanned = sscanf(buffer, "%255s %255s", to, from); + if (scanned == 2) { int code = lookup(from); if (code == UNKNOWN) continue; @@ -94,7 +102,7 @@ make_keys(FILE * ifp, FILE * ofp) } static void -write_list(FILE * ofp, const char **list) +write_list(FILE *ofp, const char **list) { while (*list != 0) fprintf(ofp, "%s\n", *list++); @@ -113,7 +121,7 @@ main(int argc, char *argv[]) "#if BROKEN_LINKER", "static", "#endif", - "struct tinfo_fkeys _nc_tinfo_fkeys[] = {", + "const struct tinfo_fkeys _nc_tinfo_fkeys[] = {", 0 }; static const char *suffix[] = diff --git a/lib/libcurses/tinfo/name_match.c b/lib/libcurses/tinfo/name_match.c index 6db7ac7057f..1162430ee2f 100644 --- a/lib/libcurses/tinfo/name_match.c +++ b/lib/libcurses/tinfo/name_match.c @@ -1,7 +1,7 @@ -/* $OpenBSD: name_match.c,v 1.3 2001/01/22 18:01:55 millert Exp $ */ +/* $OpenBSD: name_match.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1999-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,35 +29,48 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1999 * + * Author: Thomas E. Dickey 1999-on * ****************************************************************************/ #include <curses.priv.h> #include <term.h> #include <tic.h> -MODULE_ID("$From: name_match.c,v 1.10 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: name_match.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") /* * _nc_first_name(char *names) * * Extract the primary name from a compiled entry. */ +#define FirstName _nc_globals.first_name NCURSES_EXPORT(char *) _nc_first_name(const char *const sp) /* get the first name from the given name list */ { - static char buf[MAX_NAME_SIZE + 1]; - register unsigned n; + unsigned n; - for (n = 0; n < sizeof(buf) - 1; n++) { - if ((buf[n] = sp[n]) == '\0' - || (buf[n] == '|')) - break; +#if NO_LEAKS + if (sp == 0) { + if (FirstName != 0) + FreeAndNull(FirstName); + } else +#endif + { + if (FirstName == 0) + FirstName = typeMalloc(char, MAX_NAME_SIZE + 1); + + if (FirstName != 0) { + for (n = 0; n < MAX_NAME_SIZE; n++) { + if ((FirstName[n] = sp[n]) == '\0' + || (FirstName[n] == '|')) + break; + } + FirstName[n] = '\0'; + } } - buf[n] = '\0'; - return (buf); + return (FirstName); } /* @@ -67,8 +80,7 @@ _nc_first_name(const char *const sp) */ NCURSES_EXPORT(int) -_nc_name_match -(const char *const namelst, const char *const name, const char *const delim) +_nc_name_match(const char *const namelst, const char *const name, const char *const delim) { const char *s, *d, *t; int code, found; diff --git a/lib/libcurses/tinfo/parse_entry.c b/lib/libcurses/tinfo/parse_entry.c index 4a42654d670..2270ad90c07 100644 --- a/lib/libcurses/tinfo/parse_entry.c +++ b/lib/libcurses/tinfo/parse_entry.c @@ -1,7 +1,7 @@ -/* $OpenBSD: parse_entry.c,v 1.12 2003/03/17 19:16:59 millert Exp $ */ +/* $OpenBSD: parse_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -42,14 +43,14 @@ * from the input stream. */ +#define __INTERNAL_CAPS_VISIBLE #include <curses.priv.h> #include <ctype.h> #include <tic.h> -#define __INTERNAL_CAPS_VISIBLE #include <term_entry.h> -MODULE_ID("$From: parse_entry.c,v 1.52 2001/01/13 22:44:29 tom Exp $") +MODULE_ID("$Id: parse_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $") #ifdef LINT static short const parametrized[] = @@ -143,7 +144,7 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) case BOOLEAN: tp->ext_Booleans += 1; tp->num_Booleans += 1; - tp->Booleans = typeRealloc(char, tp->num_Booleans, tp->Booleans); + tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans); for (last = tp->num_Booleans - 1; last > tindex; last--) tp->Booleans[last] = tp->Booleans[last - 1]; break; @@ -197,13 +198,17 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) * push back token */ +#define BAD_TC_USAGE if (!bad_tc_usage) \ + { bad_tc_usage = TRUE; \ + _nc_warning("Legacy termcap allows only a trailing tc= clause"); } + NCURSES_EXPORT(int) -_nc_parse_entry -(struct entry *entryp, int literal, bool silent) +_nc_parse_entry(struct entry *entryp, int literal, bool silent) { int token_type; struct name_table_entry const *entry_ptr; char *ptr, *base; + bool bad_tc_usage = FALSE; token_type = _nc_get_token(silent); @@ -219,15 +224,32 @@ _nc_parse_entry entryp->startline = _nc_start_line; DEBUG(2, ("Comment range is %ld to %ld", entryp->cstart, entryp->cend)); - /* junk the 2-character termcap name, if present */ + /* + * Strip off the 2-character termcap name, if present. Originally termcap + * used that as an indexing aid. We can retain 2-character terminfo names, + * but note that they would be lost if we translate to/from termcap. This + * feature is supposedly obsolete since "newer" BSD implementations do not + * use it; however our reference for this feature is SunOS 4.x, which + * implemented it. Note that the resulting terminal type was never the + * 2-character name, but was instead the first alias after that. + */ ptr = _nc_curr_token.tk_name; - if (ptr[2] == '|') { - ptr = _nc_curr_token.tk_name + 3; - _nc_curr_token.tk_name[2] = '\0'; + if (_nc_syntax == SYN_TERMCAP +#if NCURSES_XNAMES + && !_nc_user_definable +#endif + ) { + if (ptr[2] == '|') { + ptr += 3; + _nc_curr_token.tk_name[2] = '\0'; + } } entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr); + if (entryp->tterm.str_table == 0) + return (ERR); + DEBUG(1, ("Starting '%s'", ptr)); /* @@ -245,7 +267,7 @@ _nc_parse_entry (base == entryp->tterm.term_names) ? "primary name" : "alias", - ptr - base, base); + (int) (ptr - base), base); } } @@ -254,15 +276,19 @@ _nc_parse_entry for (token_type = _nc_get_token(silent); token_type != EOF && token_type != NAMES; token_type = _nc_get_token(silent)) { - if (strcmp(_nc_curr_token.tk_name, "use") == 0 - || strcmp(_nc_curr_token.tk_name, "tc") == 0) { + bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0); + bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0); + if (is_use || is_tc) { entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring); entryp->uses[entryp->nuses].line = _nc_curr_line; entryp->nuses++; + if (entryp->nuses > 1 && is_tc) { + BAD_TC_USAGE + } } else { /* normal token lookup */ entry_ptr = _nc_find_entry(_nc_curr_token.tk_name, - _nc_syntax ? _nc_cap_hash_table : _nc_info_hash_table); + _nc_get_hash_table(_nc_syntax)); /* * Our kluge to handle aliasing. The reason it's done @@ -276,7 +302,10 @@ _nc_parse_entry const struct alias *ap; if (_nc_syntax == SYN_TERMCAP) { - for (ap = _nc_capalias_table; ap->from; ap++) + if (entryp->nuses != 0) { + BAD_TC_USAGE + } + for (ap = _nc_get_alias_table(TRUE); ap->from; ap++) if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) { if (ap->to == (char *) 0) { _nc_warning("%s (%s termcap extension) ignored", @@ -284,14 +313,15 @@ _nc_parse_entry goto nexttok; } - entry_ptr = _nc_find_entry(ap->to, _nc_cap_hash_table); + entry_ptr = _nc_find_entry(ap->to, + _nc_get_hash_table(TRUE)); if (entry_ptr && !silent) _nc_warning("%s (%s termcap extension) aliased to %s", ap->from, ap->source, ap->to); break; } } else { /* if (_nc_syntax == SYN_TERMINFO) */ - for (ap = _nc_infoalias_table; ap->from; ap++) + for (ap = _nc_get_alias_table(FALSE); ap->from; ap++) if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) { if (ap->to == (char *) 0) { _nc_warning("%s (%s terminfo extension) ignored", @@ -299,7 +329,8 @@ _nc_parse_entry goto nexttok; } - entry_ptr = _nc_find_entry(ap->to, _nc_info_hash_table); + entry_ptr = _nc_find_entry(ap->to, + _nc_get_hash_table(FALSE)); if (entry_ptr && !silent) _nc_warning("%s (%s terminfo extension) aliased to %s", ap->from, ap->source, ap->to); @@ -346,23 +377,28 @@ _nc_parse_entry * type, this will do the job. */ - /* tell max_attributes from arrow_key_map */ - if (token_type == NUMBER && !strcmp("ma", _nc_curr_token.tk_name)) + if (token_type == NUMBER + && !strcmp("ma", _nc_curr_token.tk_name)) { + /* tell max_attributes from arrow_key_map */ entry_ptr = _nc_find_type_entry("ma", NUMBER, _nc_get_table(_nc_syntax != 0)); + assert(entry_ptr != 0); - /* map terminfo's string MT to MT */ - else if (token_type == STRING && !strcmp("MT", _nc_curr_token.tk_name)) + } else if (token_type == STRING + && !strcmp("MT", _nc_curr_token.tk_name)) { + /* map terminfo's string MT to MT */ entry_ptr = _nc_find_type_entry("MT", STRING, _nc_get_table(_nc_syntax != 0)); + assert(entry_ptr != 0); - /* treat strings without following "=" as empty strings */ - else if (token_type == BOOLEAN && entry_ptr->nte_type == STRING) + } else if (token_type == BOOLEAN + && entry_ptr->nte_type == STRING) { + /* treat strings without following "=" as empty strings */ token_type = STRING; - /* we couldn't recover; skip this token */ - else { + } else { + /* we couldn't recover; skip this token */ if (!silent) { const char *type_name; switch (entry_ptr->nte_type) { @@ -425,7 +461,7 @@ _nc_parse_entry default: if (!silent) _nc_warning("unknown token type"); - _nc_panic_mode((_nc_syntax == SYN_TERMCAP) ? ':' : ','); + _nc_panic_mode((char) ((_nc_syntax == SYN_TERMCAP) ? ':' : ',')); continue; } } /* end else cur_token.name != "use" */ @@ -445,7 +481,7 @@ _nc_parse_entry if (!literal) { if (_nc_syntax == SYN_TERMCAP) { bool has_base_entry = FALSE; - int i; + unsigned i; /* * Don't insert defaults if this is a `+' entry meant only @@ -484,7 +520,7 @@ _nc_capcmp(const char *s, const char *t) for (;;) { if (s[0] == '$' && s[1] == '<') { for (s += 2;; s++) - if (!(isdigit(CharOf(*s)) + if (!(isdigit(UChar(*s)) || *s == '.' || *s == '*' || *s == '/' @@ -494,7 +530,7 @@ _nc_capcmp(const char *s, const char *t) if (t[0] == '$' && t[1] == '<') { for (t += 2;; t++) - if (!(isdigit(CharOf(*t)) + if (!(isdigit(UChar(*t)) || *t == '.' || *t == '*' || *t == '/' @@ -520,8 +556,8 @@ append_acs0(string_desc * dst, int code, int src) { if (src != 0) { char temp[3]; - temp[0] = code; - temp[1] = src; + temp[0] = (char) code; + temp[1] = (char) src; temp[2] = 0; _nc_safe_strcat(dst, temp); } @@ -596,7 +632,7 @@ static const char C_HT[] = "\t"; #define CUR tp-> static void -postprocess_termcap(TERMTYPE * tp, bool has_base) +postprocess_termcap(TERMTYPE *tp, bool has_base) { char buf[MAX_LINE * 2 + 2]; string_desc result; @@ -619,7 +655,7 @@ postprocess_termcap(TERMTYPE * tp, bool has_base) if (WANTED(carriage_return)) { if (carriage_return_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_CR, carriage_return_delay); + snprintf(buf, sizeof(buf), "%s$<%d>", C_CR, carriage_return_delay); carriage_return = _nc_save_str(buf); } else carriage_return = _nc_save_str(C_CR); @@ -756,11 +792,12 @@ postprocess_termcap(TERMTYPE * tp, bool has_base) base = cp + 1) { size_t len = cp - base; - for (ap = ko_xlate; ap->from; ap++) + for (ap = ko_xlate; ap->from; ap++) { if (len == strlen(ap->from) && strncmp(ap->from, base, len) == 0) break; - if (!ap->to) { + } + if (!(ap->from && ap->to)) { _nc_warning("unknown capability `%.*s' in ko string", (int) len, base); continue; @@ -769,8 +806,8 @@ postprocess_termcap(TERMTYPE * tp, bool has_base) /* now we know we found a match in ko_table, so... */ - from_ptr = _nc_find_entry(ap->from, _nc_cap_hash_table); - to_ptr = _nc_find_entry(ap->to, _nc_info_hash_table); + from_ptr = _nc_find_entry(ap->from, _nc_get_hash_table(TRUE)); + to_ptr = _nc_find_entry(ap->to, _nc_get_hash_table(FALSE)); if (!from_ptr || !to_ptr) /* should never happen! */ _nc_err_abort("ko translation table is invalid, I give up"); @@ -871,13 +908,12 @@ postprocess_termcap(TERMTYPE * tp, bool has_base) } else if (acs_chars == 0 && enter_alt_charset_mode != 0 && exit_alt_charset_mode != 0) { - acs_chars = - _nc_save_str("``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~"); + acs_chars = _nc_save_str(VT_ACSC); } } static void -postprocess_terminfo(TERMTYPE * tp) +postprocess_terminfo(TERMTYPE *tp) { /* * TERMINFO-TO-TERMINFO MAPPINGS FOR SOURCE TRANSLATION diff --git a/lib/libcurses/tinfo/read_bsd_terminfo.c b/lib/libcurses/tinfo/read_bsd_terminfo.c index dae8298ec69..9c34da830f1 100644 --- a/lib/libcurses/tinfo/read_bsd_terminfo.c +++ b/lib/libcurses/tinfo/read_bsd_terminfo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: read_bsd_terminfo.c,v 1.17 2009/10/28 23:22:45 schwarze Exp $ */ +/* $OpenBSD: read_bsd_terminfo.c,v 1.18 2010/01/12 23:22:06 nicm Exp $ */ /* * Copyright (c) 1998, 1999, 2000 Todd C. Miller <Todd.Miller@courtesan.com> @@ -245,13 +245,10 @@ _nc_lookup_bsd_terminfo_entry(tn, filename, tp) goto done; } - /* - * Save term entry and prevent _nc_free_entries() from freeing - * up the string table (since we use it in tp). - */ - *tp = _nc_head->tterm; - _nc_head->tterm.str_table = NULL; - _nc_free_entries(_nc_head); + /* Save term entry and free from _nc_head list. */ + *tp = _nc_head->tterm; + _nc_free_entry(_nc_head, tp); + _nc_head = _nc_tail = NULL; } done: diff --git a/lib/libcurses/tinfo/read_entry.c b/lib/libcurses/tinfo/read_entry.c index 7bbf35a3a3a..f1b3179705d 100644 --- a/lib/libcurses/tinfo/read_entry.c +++ b/lib/libcurses/tinfo/read_entry.c @@ -1,7 +1,7 @@ -/* $OpenBSD: read_entry.c,v 1.15 2008/01/29 13:02:31 krw Exp $ */ +/* $OpenBSD: read_entry.c,v 1.16 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,77 +31,24 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* * read_entry.c -- Routine for reading in a compiled terminfo file - * */ #include <curses.priv.h> +#include <hashed_db.h> #include <tic.h> #include <term_entry.h> -MODULE_ID("$From: read_entry.c,v 1.72 2000/12/10 02:55:08 tom Exp $") - -#if !HAVE_TELL -#define tell(fd) 0 /* lseek() is POSIX, but not tell() - odd... */ -#endif - -/* - * int - * _nc_read_file_entry(filename, ptr) - * - * Read the compiled terminfo entry in the given file into the - * structure pointed to by ptr, allocating space for the string - * table. - */ - -#undef BYTE -#define BYTE(p,n) (unsigned char)((p)[n]) +MODULE_ID("$Id: read_entry.c,v 1.16 2010/01/12 23:22:06 nicm Exp $") -#define IS_NEG1(p) ((BYTE(p,0) == 0377) && (BYTE(p,1) == 0377)) -#define IS_NEG2(p) ((BYTE(p,0) == 0376) && (BYTE(p,1) == 0377)) -#define LOW_MSB(p) (BYTE(p,0) + 256*BYTE(p,1)) - -static bool have_tic_directory = FALSE; -static bool keep_tic_directory = FALSE; - -/* - * Record the "official" location of the terminfo directory, according to - * the place where we're writing to, or the normal default, if not. - */ -NCURSES_EXPORT(const char *) -_nc_tic_dir(const char *path) -{ - static const char *result = TERMINFO; - - if (!keep_tic_directory) { - if (path != 0) { - result = path; - have_tic_directory = TRUE; - } else if (!have_tic_directory && use_terminfo_vars()) { - char *envp; - if ((envp = getenv("TERMINFO")) != 0) - return _nc_tic_dir(envp); - } - } - return result; -} - -/* - * Special fix to prevent the terminfo directory from being moved after tic - * has chdir'd to it. If we let it be changed, then if $TERMINFO has a - * relative path, we'll lose track of the actual directory. - */ -NCURSES_EXPORT(void) -_nc_keep_tic_dir(const char *path) -{ - _nc_tic_dir(path); - keep_tic_directory = TRUE; -} +#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts)) +#if USE_DATABASE static void convert_shorts(char *buf, short *Numbers, int count) { @@ -128,7 +75,7 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table) Strings[i] = ABSENT_STRING; } else if (IS_NEG2(buf + 2 * i)) { Strings[i] = CANCELLED_STRING; - } else if (LOW_MSB(buf + 2 * i) > size) { + } else if ((int) LOW_MSB(buf + 2 * i) > size) { Strings[i] = ABSENT_STRING; } else { Strings[i] = (LOW_MSB(buf + 2 * i) + table); @@ -147,31 +94,51 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table) } } -#define read_shorts(fd, buf, count) (read(fd, buf, (count)*2) == (count)*2) +static int +fake_read(char *src, int *offset, int limit, char *dst, unsigned want) +{ + int have = (limit - *offset); + + if (have > 0) { + if ((int) want > have) + want = have; + memcpy(dst, src + *offset, want); + *offset += want; + } else { + want = 0; + } + return (int) want; +} + +#define Read(buf, count) fake_read(buffer, &offset, limit, buf, count) + +#define read_shorts(buf, count) \ + (Read(buf, (unsigned) (count)*2) == (int) (count)*2) #define even_boundary(value) \ - if ((value) % 2 != 0) read(fd, buf, 1) + if ((value) % 2 != 0) Read(buf, 1) -static int -read_termtype(int fd, TERMTYPE * ptr) +NCURSES_EXPORT(int) +_nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) /* return 1 if read, 0 if not found or garbled */ { + int offset = 0; int name_size, bool_count, num_count, str_count, str_size; int i; - size_t bsize; - char buf[MAX_ENTRY_SIZE]; + char buf[MAX_ENTRY_SIZE + 1]; + char *string_table; + unsigned want, have; - TR(TRACE_DATABASE, ("READ termtype header @%d", tell(fd))); + TR(TRACE_DATABASE, ("READ termtype header @%d", offset)); memset(ptr, 0, sizeof(*ptr)); /* grab the header */ - if (!read_shorts(fd, buf, 6) - || LOW_MSB(buf) != MAGIC) { - return (0); + if (!read_shorts(buf, 6) + || !IS_TIC_MAGIC(buf)) { + return (TGETENT_NO); } - _nc_free_termtype(ptr); name_size = LOW_MSB(buf + 2); bool_count = LOW_MSB(buf + 4); num_count = LOW_MSB(buf + 6); @@ -187,35 +154,41 @@ read_termtype(int fd, TERMTYPE * ptr) || num_count < 0 || str_count < 0 || str_size < 0) { - return (0); + return (TGETENT_NO); } + want = str_size + name_size + 1; if (str_size) { /* try to allocate space for the string table */ if (str_count * 2 >= (int) sizeof(buf) - || (ptr->str_table = typeMalloc(char, (unsigned) str_size)) == 0) { - return (0); + || (string_table = typeMalloc(char, want)) == 0) { + return (TGETENT_NO); } } else { str_count = 0; + if ((string_table = typeMalloc(char, want)) == 0) { + return (TGETENT_NO); + } } - /* grab the name (a null-terminate string) */ - read(fd, buf, min(MAX_NAME_SIZE, (unsigned) name_size)); - buf[MAX_NAME_SIZE] = '\0'; - bsize = strlen(buf) + 1; - ptr->term_names = typeCalloc(char, bsize); - if (ptr->term_names == NULL) { - return (0); + /* grab the name (a null-terminated string) */ + want = min(MAX_NAME_SIZE, (unsigned) name_size); + ptr->str_table = string_table; + ptr->term_names = string_table; + if ((have = Read(ptr->term_names, want)) != want) { + memset(ptr->term_names + have, 0, want - have); } - (void) strlcpy(ptr->term_names, buf, bsize); - if (name_size > MAX_NAME_SIZE) - lseek(fd, (off_t) (name_size - MAX_NAME_SIZE), 1); + ptr->term_names[want] = '\0'; + string_table += (want + 1); + + if (have > MAX_NAME_SIZE) + offset = (have - MAX_NAME_SIZE); /* grab the booleans */ - if ((ptr->Booleans = typeCalloc(char, max(BOOLCOUNT, bool_count))) == 0 - || read(fd, ptr->Booleans, (unsigned) bool_count) != bool_count) { - return (0); + if ((ptr->Booleans = TYPE_CALLOC(NCURSES_SBOOL, + max(BOOLCOUNT, bool_count))) == 0 + || Read(ptr->Booleans, (unsigned) bool_count) < bool_count) { + return (TGETENT_NO); } /* @@ -227,24 +200,24 @@ read_termtype(int fd, TERMTYPE * ptr) even_boundary(name_size + bool_count); /* grab the numbers */ - if ((ptr->Numbers = typeCalloc(short, max(NUMCOUNT, num_count))) == 0 - || !read_shorts(fd, buf, num_count)) { - return (0); + if ((ptr->Numbers = TYPE_CALLOC(short, max(NUMCOUNT, num_count))) == 0 + || !read_shorts(buf, num_count)) { + return (TGETENT_NO); } convert_shorts(buf, ptr->Numbers, num_count); - if ((ptr->Strings = typeCalloc(char *, max(STRCOUNT, str_count))) == 0) - return (0); + if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0) + return (TGETENT_NO); if (str_count) { /* grab the string offsets */ - if (!read_shorts(fd, buf, str_count)) { - return (0); + if (!read_shorts(buf, str_count)) { + return (TGETENT_NO); } /* finally, grab the string table itself */ - if (read(fd, ptr->str_table, (unsigned) str_size) != str_size) - return (0); - convert_strings(buf, ptr->Strings, str_count, str_size, ptr->str_table); + if (Read(string_table, (unsigned) str_size) != str_size) + return (TGETENT_NO); + convert_strings(buf, ptr->Strings, str_count, str_size, string_table); } #if NCURSES_XNAMES @@ -256,17 +229,17 @@ read_termtype(int fd, TERMTYPE * ptr) * Read extended entries, if any, after the normal end of terminfo data. */ even_boundary(str_size); - TR(TRACE_DATABASE, ("READ extended_header @%d", tell(fd))); - if (_nc_user_definable && read_shorts(fd, buf, 5)) { + TR(TRACE_DATABASE, ("READ extended_header @%d", offset)); + if (_nc_user_definable && read_shorts(buf, 5)) { int ext_bool_count = LOW_MSB(buf + 0); int ext_num_count = LOW_MSB(buf + 2); int ext_str_count = LOW_MSB(buf + 4); int ext_str_size = LOW_MSB(buf + 6); int ext_str_limit = LOW_MSB(buf + 8); - int need = (ext_bool_count + ext_num_count + ext_str_count); + unsigned need = (ext_bool_count + ext_num_count + ext_str_count); int base = 0; - if (need >= (int) sizeof(buf) + if (need >= sizeof(buf) || ext_str_size >= (int) sizeof(buf) || ext_str_limit >= (int) sizeof(buf) || ext_bool_count < 0 @@ -274,13 +247,13 @@ read_termtype(int fd, TERMTYPE * ptr) || ext_str_count < 0 || ext_str_size < 0 || ext_str_limit < 0) - return (0); + return (TGETENT_NO); ptr->num_Booleans = BOOLCOUNT + ext_bool_count; ptr->num_Numbers = NUMCOUNT + ext_num_count; ptr->num_Strings = STRCOUNT + ext_str_count; - ptr->Booleans = typeRealloc(char, ptr->num_Booleans, ptr->Booleans); + ptr->Booleans = typeRealloc(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans); ptr->Numbers = typeRealloc(short, ptr->num_Numbers, ptr->Numbers); ptr->Strings = typeRealloc(char *, ptr->num_Strings, ptr->Strings); @@ -289,36 +262,36 @@ read_termtype(int fd, TERMTYPE * ptr) ext_str_size, ext_str_limit)); TR(TRACE_DATABASE, ("READ %d extended-booleans @%d", - ext_bool_count, tell(fd))); + ext_bool_count, offset)); if ((ptr->ext_Booleans = ext_bool_count) != 0) { - if (read(fd, ptr->Booleans + BOOLCOUNT, (unsigned) + if (Read(ptr->Booleans + BOOLCOUNT, (unsigned) ext_bool_count) != ext_bool_count) - return (0); + return (TGETENT_NO); } even_boundary(ext_bool_count); TR(TRACE_DATABASE, ("READ %d extended-numbers @%d", - ext_num_count, tell(fd))); + ext_num_count, offset)); if ((ptr->ext_Numbers = ext_num_count) != 0) { - if (!read_shorts(fd, buf, ext_num_count)) - return (0); + if (!read_shorts(buf, ext_num_count)) + return (TGETENT_NO); TR(TRACE_DATABASE, ("Before converting extended-numbers")); convert_shorts(buf, ptr->Numbers + NUMCOUNT, ext_num_count); } - TR(TRACE_DATABASE, ("READ extended-offsets @%d", tell(fd))); + TR(TRACE_DATABASE, ("READ extended-offsets @%d", offset)); if ((ext_str_count || need) - && !read_shorts(fd, buf, ext_str_count + need)) - return (0); + && !read_shorts(buf, ext_str_count + need)) + return (TGETENT_NO); TR(TRACE_DATABASE, ("READ %d bytes of extended-strings @%d", - ext_str_limit, tell(fd))); + ext_str_limit, offset)); if (ext_str_limit) { if ((ptr->ext_str_table = typeMalloc(char, ext_str_limit)) == 0) - return (0); - if (read(fd, ptr->ext_str_table, ext_str_limit) != ext_str_limit) - return (0); + return (TGETENT_NO); + if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit) + return (TGETENT_NO); TR(TRACE_DATABASE, ("first extended-string is %s", _nc_visbuf(ptr->ext_str_table))); } @@ -342,12 +315,16 @@ read_termtype(int fd, TERMTYPE * ptr) } if (need) { - if ((ptr->ext_Names = typeCalloc(char *, need)) == 0) - return (0); + if (ext_str_count >= (MAX_ENTRY_SIZE * 2)) + return (TGETENT_NO); + if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0) + return (TGETENT_NO); TR(TRACE_DATABASE, ("ext_NAMES starting @%d in extended_strings, first = %s", base, _nc_visbuf(ptr->ext_str_table + base))); - convert_strings(buf + (2 * ext_str_count), ptr->ext_Names, need, + convert_strings(buf + (2 * ext_str_count), + ptr->ext_Names, + (int) need, ext_str_limit, ptr->ext_str_table + base); } @@ -374,15 +351,24 @@ read_termtype(int fd, TERMTYPE * ptr) for (i = str_count; i < STRCOUNT; i++) ptr->Strings[i] = ABSENT_STRING; - return (1); + return (TGETENT_YES); } +/* + * int + * _nc_read_file_entry(filename, ptr) + * + * Read the compiled terminfo entry in the given file into the + * structure pointed to by ptr, allocating space for the string + * table. + */ NCURSES_EXPORT(int) -_nc_read_file_entry -(const char *const filename, TERMTYPE * ptr) +_nc_read_file_entry(const char *const filename, TERMTYPE *ptr) /* return 1 if read, 0 if not found or garbled */ { int code, fd = -1; + int limit; + char buffer[MAX_ENTRY_SIZE + 1]; #ifdef __OpenBSD__ if (_nc_read_bsd_terminfo_file(filename, ptr) == 1) @@ -392,73 +378,137 @@ _nc_read_file_entry if (_nc_access(filename, R_OK) < 0 || (fd = open(filename, O_RDONLY | O_BINARY)) < 0) { T(("cannot open terminfo %s (errno=%d)", filename, errno)); - return (0); - } + code = TGETENT_NO; + } else { + if ((limit = read(fd, buffer, sizeof(buffer))) > 0) { - T(("read terminfo %s", filename)); - if ((code = read_termtype(fd, ptr)) == 0) - _nc_free_termtype(ptr); - close(fd); + T(("read terminfo %s", filename)); + if ((code = _nc_read_termtype(ptr, buffer, limit)) == TGETENT_NO) { + _nc_free_termtype(ptr); + } + } else { + code = TGETENT_NO; + } + close(fd); + } return (code); } /* - * Build a terminfo pathname and try to read the data. Returns 1 on success, - * 0 on failure. + * Build a terminfo pathname and try to read the data. Returns TGETENT_YES on + * success, TGETENT_NO on failure. */ static int -_nc_read_tic_entry(char *const filename, - const char *const dir, const char *ttn, TERMTYPE * const tp) +_nc_read_tic_entry(char *filename, + unsigned limit, + const char *const path, + const char *name, + TERMTYPE *const tp) { -/* maximum safe length of terminfo root directory name */ -#define MAX_TPATH (PATH_MAX - MAX_ALIAS - 6) + int result = TGETENT_NO; - if (strlen(dir) > MAX_TPATH) - return 0; - (void) snprintf(filename, MAX_TPATH + 1, "%s/%s", dir, ttn); - return _nc_read_file_entry(filename, tp); -} + /* + * If we are looking in a directory, assume the entry is a file under that, + * according to the normal rules. + * + * FIXME - add caseless-filename fixup. + */ + unsigned need = 4 + strlen(path) + strlen(name); + if (need <= limit) { + (void) snprintf(filename, limit, "%s/" LEAF_FMT "/%s", path, *name, name); + if (_nc_is_dir_path(path)) + result = _nc_read_file_entry(filename, tp); + } -/* - * Process the list of :-separated directories, looking for the terminal type. - * We don't use strtok because it does not show us empty tokens. - */ -static int -_nc_read_terminfo_dirs(const char *dirs, char *const filename, const char *const - ttn, TERMTYPE * const tp) -{ - char *list, *a; - const char *b; - int code = 0; - - /* we'll modify the argument, so we must copy */ - if ((b = a = list = strdup(dirs)) == NULL) - return (0); - - for (;;) { - int c = *a; - if (c == 0 || c == NCURSES_PATHSEP) { - *a = 0; - if ((b + 1) >= a) - b = TERMINFO; - if (_nc_read_tic_entry(filename, b, ttn, tp) == 1) { - code = 1; - break; +#if USE_HASHED_DB + else { + static const char suffix[] = DBM_SUFFIX; + DB *capdbp; + unsigned lens = sizeof(suffix) - 1; + unsigned size = strlen(path); + unsigned need = lens + size; + + if (need <= limit) { + if (size >= lens + && !strcmp(path + size - lens, suffix)) + (void) strlcpy(filename, path, limit); + else + (void) snprintf(filename, limit, "%s%s", path, suffix); + + /* + * It would be nice to optimize the dbopen/close activity, as + * done in the cgetent implementation for tc= clauses. However, + * since we support multiple database locations, we cannot do + * that. + */ + if ((capdbp = _nc_db_open(filename, FALSE)) != 0) { + DBT key, data; + int reccnt = 0; + char *save = strdup(name); + + memset(&key, 0, sizeof(key)); + key.data = save; + key.size = strlen(save); + + /* + * This lookup could return termcap data, which we do not want. + * We are looking for compiled (binary) terminfo data. + * + * cgetent uses a two-level lookup. On the first it uses the + * given name to return a record containing only the aliases + * for an entry. On the second (using that list of aliases as + * a key), it returns the content of the terminal description. + * We expect second lookup to return data beginning with the + * same set of aliases. + * + * For compiled terminfo, the list of aliases in the second + * case will be null-terminated. A termcap entry will not be, + * and will run on into the description. So we can easily + * distinguish between the two (source/binary) by checking the + * lengths. + */ + while (_nc_db_get(capdbp, &key, &data) == 0) { + int used = data.size - 1; + char *have = (char *) data.data; + + if (*have++ == 0) { + if (data.size > key.size + && IS_TIC_MAGIC(have)) { + result = _nc_read_termtype(tp, have, used); + if (result == TGETENT_NO) { + _nc_free_termtype(tp); + } + } + break; + } + + /* + * Just in case we have a corrupt database, do not waste + * time with it. + */ + if (++reccnt >= 3) + break; + + /* + * Prepare for the second level. + */ + key.data = have; + key.size = used; + } + + _nc_db_close(capdbp); + free(save); } - b = a + 1; - if (c == 0) - break; } - a++; } - - free(list); - return (code); +#endif + return result; } +#endif /* USE_DATABASE */ /* - * _nc_read_entry(char *tn, char *filename, TERMTYPE *tp) + * _nc_read_entry(char *name, char *filename, TERMTYPE *tp) * * Find and read the compiled entry for a given terminal type, * if it exists. We take pains here to make sure no combination @@ -467,52 +517,43 @@ _nc_read_terminfo_dirs(const char *dirs, char *const filename, const char *const */ NCURSES_EXPORT(int) -_nc_read_entry -(const char *const tn, char *const filename, TERMTYPE * const tp) +_nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) { - char *envp; - char ttn[MAX_ALIAS + 3]; + int code = TGETENT_NO; #ifdef __OpenBSD__ /* First check the BSD terminfo.db file */ - if (_nc_read_bsd_terminfo_entry(tn, filename, tp) == 1) + if (_nc_read_bsd_terminfo_entry(name, filename, tp) == 1) return (1); #endif /* __OpenBSD__ */ - /* truncate the terminal name to prevent dangerous buffer airline */ - (void) snprintf(ttn, sizeof(ttn), "%c/%.*s", *tn, MAX_ALIAS, tn); - - /* This is System V behavior, in conjunction with our requirements for - * writing terminfo entries. - */ - if (have_tic_directory - && _nc_read_tic_entry(filename, _nc_tic_dir(0), ttn, tp) == 1) - return 1; - - if (use_terminfo_vars()) { - if ((envp = getenv("TERMINFO")) != 0 - && _nc_read_tic_entry(filename, _nc_tic_dir(envp), ttn, tp) == 1) - return 1; - - /* this is an ncurses extension */ - if ((envp = _nc_home_terminfo()) != 0) { - if (_nc_read_tic_entry(filename, envp, ttn, tp) == 1) { - return (1); + snprintf(filename, PATH_MAX, "%s", name); + if (strlen(name) == 0 + || strcmp(name, ".") == 0 + || strcmp(name, "..") == 0 + || _nc_pathlast(name) != 0 + || strchr(name, NCURSES_PATHSEP) != 0) { + T(("illegal or missing entry name '%s'", name)); + } else { +#if USE_DATABASE + DBDIRS state = dbdTIC; + int offset = 0; + const char *path; + + while ((path = _nc_next_db(&state, &offset)) != 0) { + code = _nc_read_tic_entry(filename, PATH_MAX, path, name, tp); + if (code == TGETENT_YES) { + _nc_last_db(); + break; } } - - /* this is an ncurses extension */ - if ((envp = getenv("TERMINFO_DIRS")) != 0) - return _nc_read_terminfo_dirs(envp, filename, ttn, tp); - } - - /* Try the system directory. Note that the TERMINFO_DIRS value, if - * defined by the configure script, begins with a ":", which will be - * interpreted as TERMINFO. - */ -#ifdef TERMINFO_DIRS - return _nc_read_terminfo_dirs(TERMINFO_DIRS, filename, ttn, tp); -#else - return _nc_read_tic_entry(filename, TERMINFO, ttn, tp); #endif +#if USE_TERMCAP + if (code != TGETENT_YES) { + code = _nc_read_termcap_entry(name, tp); + snprintf(filename, PATH_MAX, "%s", _nc_get_source()); + } +#endif + } + return code; } diff --git a/lib/libcurses/tinfo/read_termcap.c b/lib/libcurses/tinfo/read_termcap.c index 65dc97fd04a..9968879f235 100644 --- a/lib/libcurses/tinfo/read_termcap.c +++ b/lib/libcurses/tinfo/read_termcap.c @@ -1,5 +1,7 @@ +/* $OpenBSD: read_termcap.c,v 1.22 2010/01/12 23:22:06 nicm Exp $ */ + /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -52,25 +55,31 @@ #include <curses.priv.h> #include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> #include <tic.h> #include <term_entry.h> -MODULE_ID("$From: read_termcap.c,v 1.55 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: read_termcap.c,v 1.22 2010/01/12 23:22:06 nicm Exp $") #if !PURE_TERMINFO -#ifdef __EMX__ -#define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \ - || (((s)[0] != 0) && ((s)[1] == ':'))) -#else -#define is_pathname(s) ((s) != 0 && (s)[0] == '/') -#endif - #define TC_SUCCESS 0 -#define TC_UNRESOLVED -1 -#define TC_NOT_FOUND -2 -#define TC_SYS_ERR -3 -#define TC_REF_LOOP -4 +#define TC_NOT_FOUND -1 +#define TC_SYS_ERR -2 +#define TC_REF_LOOP -3 +#define TC_UNRESOLVED -4 /* this is not returned by BSD cgetent */ + +static NCURSES_CONST char * +get_termpath(void) +{ + NCURSES_CONST char *result; + + if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0) + result = TERMPATH; + T(("TERMPATH is %s", result)); + return result; +} #if USE_GETCAP @@ -119,13 +128,7 @@ static int _nc_nfcmp(const char *, char *); #define BFRAG 1024 #define BSIZE 1024 -#define ESC ('[' & 037) /* ASCII ESC */ #define MAX_RECURSION 32 /* maximum getent recursion */ -#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */ - -#define RECOK (char)0 -#define TCERR (char)1 -#define SHADOW (char)2 static size_t topreclen; /* toprec length */ static char *toprec; /* Additional record specified by cgetset() */ @@ -218,10 +221,10 @@ _nc_cgetcap(char *buf, const char *cap, int type) * Returns: * * positive # on success (i.e., the index in db_array) - * TC_UNRESOLVED if we had too many recurrences to resolve * TC_NOT_FOUND if the requested record couldn't be found * TC_SYS_ERR if a system error was encountered (e.g.,couldn't open a file) * TC_REF_LOOP if a potential reference loop is detected + * TC_UNRESOLVED if we had too many recurrences to resolve */ static int _nc_cgetent(char **buf, int *oline, char **db_array, const char *name) @@ -284,7 +287,7 @@ _nc_getent( errno = ENOMEM; return (TC_SYS_ERR); } - (void) strlcpy(record, toprec, topreclen + BFRAG); + (void) strlcpy(record, toprec, topreclen + BFRAG); rp = record + topreclen + 1; r_end = rp + BFRAG; current = in_array; @@ -659,7 +662,11 @@ _nc_nfcmp(const char *nf, char *rec) * 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. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -701,7 +708,7 @@ get_tc_token(char **srcp, int *endp) if (*s == '\0') { break; } else if (*s++ == '\n') { - while (isspace(*s)) + while (isspace(UChar(*s))) s++; } else { found = TRUE; @@ -715,7 +722,7 @@ get_tc_token(char **srcp, int *endp) break; } base = s; - } else if (isgraph(ch)) { + } else if (isgraph(UChar(ch))) { found = TRUE; } } @@ -735,7 +742,7 @@ copy_tc_token(char *dst, const char *src, size_t len) while ((ch = *src++) != '\0') { if (ch == '\\' && *src == '\n') { - while (isspace(*src)) + while (isspace(UChar(*src))) src++; continue; } @@ -755,7 +762,6 @@ static int _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) { static char *the_source; - register char *p; register char *cp; char *dummy = NULL; @@ -765,7 +771,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) char pathbuf[PBUFSIZ]; /* holds raw path of filenames */ char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ char **pvec; /* holds usable tail of path vector */ - char *termpath; + NCURSES_CONST char *termpath; string_desc desc; fname = pathvec; @@ -785,23 +791,23 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) */ _nc_str_init(&desc, pathbuf, sizeof(pathbuf)); if (cp == NULL) { - _nc_safe_strcpy(&desc, "/usr/share/misc/termcap /etc/termcap"); - } else if (!is_pathname(cp)) { /* TERMCAP holds an entry */ - if ((termpath = getenv("TERMPATH")) != 0) { + _nc_safe_strcpy(&desc, get_termpath()); + } else if (!_nc_is_abs_path(cp)) { /* TERMCAP holds an entry */ + if ((termpath = get_termpath()) != 0) { _nc_safe_strcat(&desc, termpath); } else { char temp[PBUFSIZ]; - size_t len; temp[0] = 0; if ((home = getenv("HOME")) != 0 && *home != '\0' - && strchr(home, ' ') == 0) { /* setup path */ - len = snprintf(temp, sizeof(temp), "%s/.termcap", home); - if (len < sizeof(temp)) { - _nc_safe_strcat(&desc, temp); - } + && strchr(home, ' ') == 0 + && strlen(home) < sizeof(temp) - 10) { /* setup path */ + snprintf(temp, sizeof(temp), "%s/", home); /* $HOME first */ } - _nc_safe_strcat(&desc, " /usr/share/misc/termcap"); - _nc_safe_strcat(&desc, " /etc/termcap"); + /* if no $HOME look in current directory */ + strlcat(temp, ".termcap", sizeof temp); + _nc_safe_strcat(&desc, temp); + _nc_safe_strcat(&desc, " "); + _nc_safe_strcat(&desc, get_termpath()); } } else { /* user-defined name in TERMCAP */ _nc_safe_strcat(&desc, cp); /* still can be tokenized */ @@ -824,7 +830,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) } } *fname = 0; /* mark end of vector */ - if (is_pathname(cp)) { + if (_nc_is_abs_path(cp)) { if (_nc_cgetset(cp) < 0) { return (TC_SYS_ERR); } @@ -877,8 +883,21 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) * cgetent, then it is the actual filename). */ if (i >= 0) { +#if HAVE_BSD_CGETENT + char temp[PATH_MAX]; + + _nc_str_init(&desc, temp, sizeof(temp)); + _nc_safe_strcpy(&desc, pathvec[i]); + _nc_safe_strcat(&desc, ".db"); + if (_nc_access(temp, R_OK) == 0) { + _nc_safe_strcpy(&desc, pathvec[i]); + } + if ((the_source = strdup(temp)) != 0) + *sourcename = the_source; +#else if ((the_source = strdup(pathvec[i])) != 0) *sourcename = the_source; +#endif } return (i); @@ -896,20 +915,26 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) static int add_tc(char *termpaths[], char *path, int count) { + char *save = strchr(path, NCURSES_PATHSEP); + if (save != 0) + *save = '\0'; if (count < MAXPATHS - && _nc_access(path, R_OK) == 0) + && _nc_access(path, R_OK) == 0) { termpaths[count++] = path; + T(("Adding termpath %s", path)); + } termpaths[count] = 0; + if (save != 0) + *save = NCURSES_PATHSEP; return count; } #define ADD_TC(path, count) filecount = add_tc(termpaths, path, count) #endif /* !USE_GETCAP */ NCURSES_EXPORT(int) -_nc_read_termcap_entry -(const char *const tn, TERMTYPE * const tp) +_nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) { - int found = FALSE; + int found = TGETENT_NO; ENTRY *ep; #if USE_GETCAP_CACHE char cwd_buf[PATH_MAX]; @@ -920,20 +945,31 @@ _nc_read_termcap_entry static char *source; static int lineno; + T(("read termcap entry for %s", tn)); + + if (strlen(tn) == 0 + || strcmp(tn, ".") == 0 + || strcmp(tn, "..") == 0 + || _nc_pathlast(tn) != 0) { + T(("illegal or missing entry name '%s'", tn)); + return TGETENT_NO; + } + if (use_terminfo_vars() && (p = getenv("TERMCAP")) != 0 - && !is_pathname(p) && _nc_name_match(p, tn, "|:")) { + && !_nc_is_abs_path(p) && _nc_name_match(p, tn, "|:")) { /* TERMCAP holds a termcap entry */ - strlcpy(tc, p, sizeof(tc)); + strncpy(tc, p, sizeof(tc) - 1); + tc[sizeof(tc) - 1] = '\0'; _nc_set_source("TERMCAP"); } else { /* we're using getcap(3) */ if ((status = _nc_tgetent(tc, &source, &lineno, tn)) < 0) - return (status == -1 ? 0 : -1); + return (status == TC_NOT_FOUND ? TGETENT_NO : TGETENT_ERR); _nc_curr_line = lineno; _nc_set_source(source); } - _nc_read_entry_source((FILE *) 0, tc, FALSE, TRUE, NULLHOOK); + _nc_read_entry_source((FILE *) 0, tc, FALSE, FALSE, NULLHOOK); #else /* * Here is what the 4.4BSD termcap(3) page prescribes: @@ -964,65 +1000,98 @@ _nc_read_termcap_entry FILE *fp; char *tc, *termpaths[MAXPATHS]; int filecount = 0; + int j, k; bool use_buffer = FALSE; + bool normal = TRUE; char tc_buf[1024]; char pathbuf[PATH_MAX]; + char *copied = 0; + char *cp; + struct stat test_stat[MAXPATHS]; termpaths[filecount] = 0; if (use_terminfo_vars() && (tc = getenv("TERMCAP")) != 0) { - if (is_pathname(tc)) { /* interpret as a filename */ + if (_nc_is_abs_path(tc)) { /* interpret as a filename */ ADD_TC(tc, 0); + normal = FALSE; } else if (_nc_name_match(tc, tn, "|:")) { /* treat as a capability file */ use_buffer = TRUE; - (void) snprintf(tc_buf, sizeof(tc_buf), "%.*s\n", - (int) sizeof(tc_buf) - 2, tc); - } else if ((tc = getenv("TERMPATH")) != 0) { - char *cp; - - for (cp = tc; *cp; cp++) { - if (*cp == NCURSES_PATHSEP) - *cp = '\0'; - else if (cp == tc || cp[-1] == '\0') { - ADD_TC(cp, filecount); - } - } + (void) snprintf(tc_buf, sizeof(tc_buf), "%.*s\n", (int) sizeof(tc_buf) - 2, tc); + normal = FALSE; } - } else { /* normal case */ - char envhome[PATH_MAX], *h; + } - filecount = 0; + if (normal) { /* normal case */ + char envhome[PATH_MAX], *h; - /* - * Probably /etc/termcap is a symlink to /usr/share/misc/termcap. - * Avoid reading the same file twice. - */ - if (_nc_access("/etc/termcap", F_OK) == 0) - ADD_TC("/etc/termcap", filecount); - else - ADD_TC("/usr/share/misc/termcap", filecount); + copied = strdup(get_termpath()); + for (cp = copied; *cp; cp++) { + if (*cp == NCURSES_PATHSEP) + *cp = '\0'; + else if (cp == copied || cp[-1] == '\0') { + ADD_TC(cp, filecount); + } + } #define PRIVATE_CAP "%s/.termcap" if (use_terminfo_vars() && (h = getenv("HOME")) != NULL && *h != '\0' && (strlen(h) + sizeof(PRIVATE_CAP)) < PATH_MAX) { /* user's .termcap, if any, should override it */ - (void) strlcpy(envhome, h, sizeof(envhome)); + (void) strlcpy(envhome, h, sizeof(envhome); (void) snprintf(pathbuf, sizeof(pathbuf), PRIVATE_CAP, envhome); ADD_TC(pathbuf, filecount); } } + /* + * Probably /etc/termcap is a symlink to /usr/share/misc/termcap. + * Avoid reading the same file twice. + */ +#if HAVE_LINK + for (j = 0; j < filecount; j++) { + bool omit = FALSE; + if (stat(termpaths[j], &test_stat[j]) != 0 + || (test_stat[j].st_mode & S_IFMT) != S_IFREG) { + omit = TRUE; + } else { + for (k = 0; k < j; k++) { + if (test_stat[k].st_dev == test_stat[j].st_dev + && test_stat[k].st_ino == test_stat[j].st_ino) { + omit = TRUE; + break; + } + } + } + if (omit) { + T(("Path %s is a duplicate", termpaths[j])); + for (k = j + 1; k < filecount; k++) { + termpaths[k - 1] = termpaths[k]; + test_stat[k - 1] = test_stat[k]; + } + --filecount; + --j; + } + } +#endif + /* parse the sources */ if (use_buffer) { _nc_set_source("TERMCAP"); - _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, TRUE, NULLHOOK); + + /* + * We don't suppress warning messages here. The presumption is + * that since it's just a single entry, they won't be a pain. + */ + _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, FALSE, NULLHOOK); } else { int i; for (i = 0; i < filecount; i++) { T(("Looking for %s in %s", tn, termpaths[i])); - if ((fp = fopen(termpaths[i], "r")) != (FILE *) 0) { + if (_nc_access(termpaths[i], R_OK) == 0 + && (fp = fopen(termpaths[i], "r")) != (FILE *) 0) { _nc_set_source(termpaths[i]); /* @@ -1036,13 +1105,15 @@ _nc_read_termcap_entry } } } + if (copied != 0) + free(copied); #endif /* USE_GETCAP */ if (_nc_head == 0) - return (ERR); + return (TGETENT_ERR); /* resolve all use references */ - _nc_resolve_uses(TRUE); + _nc_resolve_uses2(TRUE, FALSE); /* find a terminal matching tn, if we can */ #if USE_GETCAP_CACHE @@ -1052,13 +1123,12 @@ _nc_read_termcap_entry for_entry_list(ep) { if (_nc_name_match(ep->tterm.term_names, tn, "|:")) { /* - * Make a local copy of the terminal capabilities. Free all - * entry storage except the string table for the loaded type - * (which we disconnected from the list by NULLing out - * ep->tterm.str_table above). + * Make a local copy of the terminal capabilities, delinked + * from the list. */ *tp = ep->tterm; - ep->tterm.str_table = (char *) 0; + _nc_delink_entry(_nc_head, &(ep->tterm)); + free(ep); /* * OK, now try to write the type to user's terminfo directory. @@ -1075,7 +1145,7 @@ _nc_read_termcap_entry #if USE_GETCAP_CACHE (void) _nc_write_entry(tp); #endif - found = TRUE; + found = TGETENT_YES; break; } } @@ -1084,7 +1154,6 @@ _nc_read_termcap_entry } #endif - _nc_free_entries(_nc_head); return (found); } #else diff --git a/lib/libcurses/tinfo/setbuf.c b/lib/libcurses/tinfo/setbuf.c index cfe3771b036..a569f45cc52 100644 --- a/lib/libcurses/tinfo/setbuf.c +++ b/lib/libcurses/tinfo/setbuf.c @@ -1,7 +1,7 @@ -/* $OpenBSD: setbuf.c,v 1.4 2001/01/22 18:01:57 millert Exp $ */ +/* $OpenBSD: setbuf.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2003,2007 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,7 +42,7 @@ #include <curses.priv.h> -MODULE_ID("$From: setbuf.c,v 1.7 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: setbuf.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") /* * If the output file descriptor is connected to a tty (the typical case) it @@ -100,47 +100,53 @@ MODULE_ID("$From: setbuf.c,v 1.7 2000/12/10 02:55:08 tom Exp $") * buffer. So we disable this by default (there may yet be a workaround). */ NCURSES_EXPORT(void) -_nc_set_buffer(FILE * ofp, bool buffered) +_nc_set_buffer(FILE *ofp, bool buffered) { /* optional optimization hack -- do before any output to ofp */ #if HAVE_SETVBUF || HAVE_SETBUFFER - unsigned buf_len; - char *buf_ptr; + if (SP->_buffered != buffered) { + unsigned buf_len; + char *buf_ptr; - if (getenv("NCURSES_NO_SETBUF") != 0) - return; + if (getenv("NCURSES_NO_SETBUF") != 0) + return; - fflush(ofp); - if ((SP->_buffered = buffered) != 0) { - buf_len = min(LINES * (COLS + 6), 2800); - if ((buf_ptr = SP->_setbuf) == 0) { - if ((buf_ptr = typeMalloc(char, buf_len)) == NULL) - return; - SP->_setbuf = buf_ptr; - /* Don't try to free this! */ - } + fflush(ofp); +#ifdef __DJGPP__ + setmode(ofp, O_BINARY); +#endif + if (buffered != 0) { + buf_len = min(LINES * (COLS + 6), 2800); + if ((buf_ptr = SP->_setbuf) == 0) { + if ((buf_ptr = typeMalloc(char, buf_len)) == NULL) + return; + SP->_setbuf = buf_ptr; + /* Don't try to free this! */ + } #if !USE_SETBUF_0 - else - return; + else + return; #endif - } else { + } else { #if !USE_SETBUF_0 - return; + return; #else - buf_len = 0; - buf_ptr = 0; + buf_len = 0; + buf_ptr = 0; #endif - } + } #if HAVE_SETVBUF #ifdef SETVBUF_REVERSED /* pre-svr3? */ - (void) setvbuf(ofp, buf_ptr, buf_len, buf_len ? _IOFBF : _IOLBF); + (void) setvbuf(ofp, buf_ptr, buf_len, buf_len ? _IOFBF : _IOLBF); #else - (void) setvbuf(ofp, buf_ptr, buf_len ? _IOFBF : _IOLBF, buf_len); + (void) setvbuf(ofp, buf_ptr, buf_len ? _IOFBF : _IOLBF, buf_len); #endif #elif HAVE_SETBUFFER - (void) setbuffer(ofp, buf_ptr, (int) buf_len); + (void) setbuffer(ofp, buf_ptr, (int) buf_len); #endif + SP->_buffered = buffered; + } #endif /* HAVE_SETVBUF || HAVE_SETBUFFER */ } diff --git a/lib/libcurses/tinfo/strings.c b/lib/libcurses/tinfo/strings.c index fd5d7f314b8..b0f06598466 100644 --- a/lib/libcurses/tinfo/strings.c +++ b/lib/libcurses/tinfo/strings.c @@ -1,7 +1,7 @@ -/* $OpenBSD: strings.c,v 1.3 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: strings.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2000 Free Software Foundation, Inc. * + * Copyright (c) 2000-2003,2007 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,7 +38,7 @@ #include <curses.priv.h> -MODULE_ID("$From: strings.c,v 1.3 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: strings.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") /**************************************************************************** * Useful string functions (especially for mvcur) @@ -46,8 +46,7 @@ MODULE_ID("$From: strings.c,v 1.3 2000/12/10 02:55:08 tom Exp $") #if !HAVE_STRSTR NCURSES_EXPORT(char *) -_nc_strstr -(const char *haystack, const char *needle) +_nc_strstr(const char *haystack, const char *needle) { size_t len1 = strlen(haystack); size_t len2 = strlen(needle); @@ -55,7 +54,7 @@ _nc_strstr while ((len1 != 0) && (len1-- >= len2)) { if (!strncmp(haystack, needle, len2)) { - result = haystack; + result = (char *) haystack; break; } haystack++; @@ -65,16 +64,18 @@ _nc_strstr #endif /* - * Initialize the descriptor so we can append to it. + * Initialize the descriptor so we can append to it. Note that 'src' may + * be a null pointer (see _nc_str_null), so the corresponding strcat and + * strcpy calls have to allow for this. */ NCURSES_EXPORT(string_desc *) -_nc_str_init -(string_desc * dst, char *src, size_t len) +_nc_str_init(string_desc * dst, char *src, size_t len) { if (dst != 0) { dst->s_head = src; dst->s_tail = src; dst->s_size = len - 1; + dst->s_init = dst->s_size; if (src != 0) *src = 0; } @@ -85,8 +86,7 @@ _nc_str_init * Initialize the descriptor for only tracking the amount of memory used. */ NCURSES_EXPORT(string_desc *) -_nc_str_null -(string_desc * dst, size_t len) +_nc_str_null(string_desc * dst, size_t len) { return _nc_str_init(dst, 0, len); } @@ -95,8 +95,7 @@ _nc_str_null * Copy a descriptor */ NCURSES_EXPORT(string_desc *) -_nc_str_copy -(string_desc * dst, string_desc * src) +_nc_str_copy(string_desc * dst, string_desc * src) { *dst = *src; return dst; @@ -137,7 +136,7 @@ _nc_safe_strcpy(string_desc * dst, const char *src) strlcpy(dst->s_head, src, dst->s_size); dst->s_tail = dst->s_head + len; } - dst->s_size -= len; + dst->s_size = dst->s_init - len; return TRUE; } } diff --git a/lib/libcurses/tinfo/trim_sgr0.c b/lib/libcurses/tinfo/trim_sgr0.c new file mode 100644 index 00000000000..017d715bd01 --- /dev/null +++ b/lib/libcurses/tinfo/trim_sgr0.c @@ -0,0 +1,328 @@ +/* $OpenBSD: trim_sgr0.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ + +/**************************************************************************** + * Copyright (c) 2005-2006,2007 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas Dickey * + ****************************************************************************/ + +#include <curses.priv.h> + +#include <ctype.h> + +#include <tic.h> +#include <term_entry.h> + +MODULE_ID("$Id: trim_sgr0.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") + +#undef CUR +#define CUR tp-> + +#define CSI 233 +#define ESC 033 /* ^[ */ +#define L_BRACK '[' + +static char * +set_attribute_9(TERMTYPE *tp, int flag) +{ + const char *result; + + if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0) + result = ""; + return strdup(result); +} + +static int +is_csi(const char *s) +{ + if (UChar(s[0]) == CSI) + return 1; + else if (s[0] == ESC && s[1] == L_BRACK) + return 2; + return 0; +} + +static char * +skip_zero(char *s) +{ + if (s[0] == '0') { + if (s[1] == ';') + s += 2; + else if (isalpha(UChar(s[1]))) + s += 1; + } + return s; +} + +static const char * +skip_delay(const char *s) +{ + if (s[0] == '$' && s[1] == '<') { + s += 2; + while (isdigit(UChar(*s)) || *s == '/') + ++s; + if (*s == '>') + ++s; + } + return s; +} + +/* + * Improve similar_sgr a little by moving the attr-string from the beginning + * to the end of the s-string. + */ +static bool +rewrite_sgr(char *s, char *attr) +{ + if (PRESENT(s)) { + if (PRESENT(attr)) { + unsigned len_s = strlen(s); + unsigned len_a = strlen(attr); + + if (len_s > len_a && !strncmp(attr, s, len_a)) { + unsigned n; + TR(TRACE_DATABASE, ("rewrite:\n\t%s", s)); + for (n = 0; n < len_s - len_a; ++n) { + s[n] = s[n + len_a]; + } + strlcpy(s + n, attr, len_s - n); + TR(TRACE_DATABASE, ("to:\n\t%s", s)); + } + } + return TRUE; + } + return FALSE; /* oops */ +} + +static bool +similar_sgr(char *a, char *b) +{ + bool result = FALSE; + int csi_a = is_csi(a); + int csi_b = is_csi(b); + unsigned len_a; + unsigned len_b; + + TR(TRACE_DATABASE, ("similar_sgr:\n\t%s\n\t%s", + _nc_visbuf2(1, a), + _nc_visbuf2(2, b))); + if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { + a += csi_a; + b += csi_b; + if (*a != *b) { + a = skip_zero(a); + b = skip_zero(b); + } + } + len_a = strlen(a); + len_b = strlen(b); + if (len_a && len_b) { + if (len_a > len_b) + result = (strncmp(a, b, len_b) == 0); + else + result = (strncmp(a, b, len_a) == 0); + } + TR(TRACE_DATABASE, ("...similar_sgr: %d\n\t%s\n\t%s", result, + _nc_visbuf2(1, a), + _nc_visbuf2(2, b))); + return result; +} + +static unsigned +chop_out(char *string, unsigned i, unsigned j) +{ + TR(TRACE_DATABASE, ("chop_out %d..%d from %s", i, j, _nc_visbuf(string))); + while (string[j] != '\0') { + string[i++] = string[j++]; + } + string[i] = '\0'; + return i; +} + +/* + * Compare, ignoring delays. Some of the delay values are inconsistent, and + * we do not want to be stopped by that. + * + * Returns the number of chars from 'full' that we matched. If any mismatch + * occurs, return zero. + */ +static int +compare_part(const char *part, const char *full) +{ + const char *next_part; + const char *next_full; + int used_full = 0; + int used_delay = 0; + + while (*part != 0) { + if (*part != *full) { + used_full = 0; + break; + } + + /* + * Adjust the return-value to allow the rare case of + * string<delay>string + * to remove the whole piece. The most common case is a delay at the + * end of the string. The adjusted string will retain the delay, which + * is conservative. + */ + if (used_delay != 0) { + used_full += used_delay; + used_delay = 0; + } + if (*part == '$' && *full == '$') { + next_part = skip_delay(part); + next_full = skip_delay(full); + if (next_part != part && next_full != full) { + used_delay += (next_full - full); + full = next_full; + part = next_part; + continue; + } + } + ++used_full; + ++part; + ++full; + } + return used_full; +} + +/* + * While 'sgr0' is the "same" as termcap 'me', there is a compatibility issue. + * The sgr/sgr0 capabilities include setting/clearing alternate character set + * mode. A termcap application cannot use sgr, so sgr0 strings that reset + * alternate character set mode will be misinterpreted. Here, we remove those + * from the more common ISO/ANSI/VT100 entries, which have sgr0 agreeing with + * sgr. + * + * This function returns the modified sgr0 if it can be modified, a null if + * an error occurs, or the original sgr0 if no change is needed. + */ +NCURSES_EXPORT(char *) +_nc_trim_sgr0(TERMTYPE *tp) +{ + char *result = exit_attribute_mode; + + T((T_CALLED("_nc_trim_sgr0()"))); + + if (PRESENT(exit_attribute_mode) + && PRESENT(set_attributes)) { + bool found = FALSE; + char *on = set_attribute_9(tp, 1); + char *off = set_attribute_9(tp, 0); + char *end = strdup(exit_attribute_mode); + char *tmp; + size_t i, j, k; + + TR(TRACE_DATABASE, ("checking if we can trim sgr0 based on sgr")); + TR(TRACE_DATABASE, ("sgr0 %s", _nc_visbuf(end))); + TR(TRACE_DATABASE, ("sgr(9:off) %s", _nc_visbuf(off))); + TR(TRACE_DATABASE, ("sgr(9:on) %s", _nc_visbuf(on))); + + if (!rewrite_sgr(on, enter_alt_charset_mode) + || !rewrite_sgr(off, exit_alt_charset_mode) + || !rewrite_sgr(end, exit_alt_charset_mode)) { + FreeIfNeeded(off); + } else if (similar_sgr(off, end) + && !similar_sgr(off, on)) { + TR(TRACE_DATABASE, ("adjusting sgr(9:off) : %s", _nc_visbuf(off))); + result = off; + /* + * If rmacs is a substring of sgr(0), remove that chunk. + */ + if (exit_alt_charset_mode != 0) { + TR(TRACE_DATABASE, ("scan for rmacs %s", _nc_visbuf(exit_alt_charset_mode))); + j = strlen(off); + k = strlen(exit_alt_charset_mode); + if (j > k) { + for (i = 0; i <= (j - k); ++i) { + int k2 = compare_part(exit_alt_charset_mode, off + i); + if (k2 != 0) { + found = TRUE; + chop_out(off, i, i + k2); + break; + } + } + } + } + /* + * SGR 10 would reset to normal font. + */ + if (!found) { + if ((i = is_csi(off)) != 0 + && off[strlen(off) - 1] == 'm') { + TR(TRACE_DATABASE, ("looking for SGR 10 in %s", + _nc_visbuf(off))); + tmp = skip_zero(off + i); + if (tmp[0] == '1' + && skip_zero(tmp + 1) != tmp + 1) { + i = tmp - off; + if (off[i - 1] == ';') + i--; + j = skip_zero(tmp + 1) - off; + i = chop_out(off, i, j); + found = TRUE; + } + } + } + if (!found + && (tmp = strstr(end, off)) != 0 + && strcmp(end, off) != 0) { + i = tmp - end; + j = strlen(off); + tmp = strdup(end); + chop_out(tmp, i, j); + free(off); + result = tmp; + } + TR(TRACE_DATABASE, ("...adjusted sgr0 : %s", _nc_visbuf(result))); + if (!strcmp(result, exit_attribute_mode)) { + TR(TRACE_DATABASE, ("...same result, discard")); + free(result); + result = exit_attribute_mode; + } + } else { + /* + * Either the sgr does not reference alternate character set, + * or it is incorrect. That's too hard to decide right now. + */ + free(off); + } + FreeIfNeeded(end); + FreeIfNeeded(on); + } else { + /* + * Possibly some applications are confused if sgr0 contains rmacs, + * but that would be a different bug report -TD + */ + } + + returnPtr(result); +} diff --git a/lib/libcurses/tinfo/use_screen.c b/lib/libcurses/tinfo/use_screen.c new file mode 100644 index 00000000000..2d79e734601 --- /dev/null +++ b/lib/libcurses/tinfo/use_screen.c @@ -0,0 +1,60 @@ +/* $OpenBSD: use_screen.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ + +/**************************************************************************** + * Copyright (c) 2007,2008 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey 2007 * + ****************************************************************************/ + +#include <curses.priv.h> + +MODULE_ID("$Id: use_screen.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") + +NCURSES_EXPORT(int) +use_screen(SCREEN *screen, NCURSES_SCREEN_CB func, void *data) +{ + SCREEN *save_SP; + int code = OK; + + T((T_CALLED("use_screen(%p,%p,%p)"), screen, func, data)); + + /* + * FIXME - add a flag so a given thread can check if _it_ has already + * recurred through this point, return an error if so. + */ + _nc_lock_global(curses); + save_SP = SP; + set_term(screen); + + code = func(screen, data); + + set_term(save_SP); + _nc_unlock_global(curses); + returnCode(code); +} diff --git a/lib/libcurses/tinfo/write_entry.c b/lib/libcurses/tinfo/write_entry.c index 9aff48b5ef0..4f28313b905 100644 --- a/lib/libcurses/tinfo/write_entry.c +++ b/lib/libcurses/tinfo/write_entry.c @@ -1,7 +1,7 @@ -/* $OpenBSD: write_entry.c,v 1.12 2003/03/18 16:55:54 millert Exp $ */ +/* $OpenBSD: write_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -38,6 +39,7 @@ */ #include <curses.priv.h> +#include <hashed_db.h> #include <sys/stat.h> @@ -48,21 +50,27 @@ #define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR) #endif -#if 0 +#if 1 #define TRACE_OUT(p) DEBUG(2, p) #else #define TRACE_OUT(p) /*nothing */ #endif -MODULE_ID("$From: write_entry.c,v 1.56 2000/12/10 02:55:08 tom Exp $") +MODULE_ID("$Id: write_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $") static int total_written; -static int write_object(FILE *, TERMTYPE *); +static int make_db_root(const char *); +static int write_object(TERMTYPE *, char *, unsigned *, unsigned); +#if !USE_HASHED_DB static void -write_file(char *filename, TERMTYPE * tp) +write_file(char *filename, TERMTYPE *tp) { + char buffer[MAX_ENTRY_SIZE]; + unsigned limit = sizeof(buffer); + unsigned offset = 0; + FILE *fp = (_nc_access(filename, W_OK) == 0) ? fopen(filename, "wb") : 0; if (fp == 0) { perror(filename); @@ -70,49 +78,117 @@ write_file(char *filename, TERMTYPE * tp) } DEBUG(1, ("Created %s", filename)); - if (write_object(fp, tp) == ERR) { + if (write_object(tp, buffer, &offset, limit) == ERR + || fwrite(buffer, sizeof(char), offset, fp) != offset) { _nc_syserr_abort("error writing %s/%s", _nc_tic_dir(0), filename); } + fclose(fp); } /* - * make_directory(char *path) + * Check for access rights to destination directories + * Create any directories which don't exist. * - * Make a directory if it doesn't exist. + * Note: there's no reason to return the result of make_db_root(), since + * this function is called only in instances where that has to succeed. */ +static void +check_writeable(int code) +{ + static const char dirnames[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + static bool verified[sizeof(dirnames)]; + + char dir[sizeof(LEAF_FMT)]; + char *s = 0; + + if (code == 0 || (s = strchr(dirnames, code)) == 0) + _nc_err_abort("Illegal terminfo subdirectory \"" LEAF_FMT "\"", code); + + if (verified[s - dirnames]) + return; + + snprintf(dir, sizeof(dir), LEAF_FMT, code); + if (make_db_root(dir) < 0) { + _nc_err_abort("%s/%s: permission denied", _nc_tic_dir(0), dir); + } + + verified[s - dirnames] = TRUE; +} +#endif /* !USE_HASHED_DB */ + static int -make_directory(const char *path) +make_db_path(char *dst, const char *src, unsigned limit) { - int rc; - struct stat statbuf; - char fullpath[PATH_MAX]; - const char *destination = _nc_tic_dir(0); + int rc = -1; + const char *top = _nc_tic_dir(0); - if (path == destination || *path == '/') { - if (strlcpy(fullpath, path, sizeof(fullpath)) >= sizeof(fullpath)) - return (-1); + if (src == top || _nc_is_abs_path(src)) { + if (strlen(src) + 1 <= limit) { + (void) strlcpy(dst, src, limit); + rc = 0; + } } else { - if (strlen(destination) + strlen(path) + 2 > sizeof(fullpath)) - return (-1); - (void) snprintf(fullpath, sizeof(fullpath), "%s/%s", destination, path); + if (strlen(top) + strlen(src) + 2 <= limit) { + (void) snprintf(dst, limit, "%s/%s", top, src); + rc = 0; + } + } +#if USE_HASHED_DB + if (rc == 0) { + if (_nc_is_dir_path(dst)) { + rc = -1; + } else { + unsigned have = strlen(dst); + if (have > 3 && strcmp(dst + have - 3, DBM_SUFFIX)) { + if (have + 3 <= limit) + strlcat(dst, DBM_SUFFIX, limit); + else + rc = -1; + } + } } +#endif + return rc; +} - if ((rc = stat(path, &statbuf)) < 0) { - rc = mkdir(path, 0777); - } else { - if (_nc_access(path, R_OK | W_OK | X_OK) < 0) { +/* + * Make a database-root if it doesn't exist. + */ +static int +make_db_root(const char *path) +{ + int rc; + char fullpath[PATH_MAX]; + + if ((rc = make_db_path(fullpath, path, sizeof(fullpath))) == 0) { +#if USE_HASHED_DB + DB *capdbp; + + if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL) + rc = -1; + else if (_nc_db_close(capdbp) < 0) + rc = -1; +#else + struct stat statbuf; + + if ((rc = stat(path, &statbuf)) < 0) { + rc = mkdir(path, 0777); + } else if (_nc_access(path, R_OK | W_OK | X_OK) < 0) { rc = -1; /* permission denied */ } else if (!(S_ISDIR(statbuf.st_mode))) { rc = -1; /* not a directory */ } +#endif } return rc; } +/* + * Set the write directory for compiled entries. + */ NCURSES_EXPORT(void) _nc_set_writedir(char *dir) -/* set the write directory for compiled entries */ { const char *destination; char actual[PATH_MAX]; @@ -125,12 +201,12 @@ _nc_set_writedir(char *dir) (void) _nc_tic_dir(dir); destination = _nc_tic_dir(0); - if (make_directory(destination) < 0) { + if (make_db_root(destination) < 0) { char *home = _nc_home_terminfo(); if (home != 0) { destination = home; - if (make_directory(destination) < 0) + if (make_db_root(destination) < 0) _nc_err_abort("%s: permission denied (errno %d)", destination, errno); } @@ -140,51 +216,17 @@ _nc_set_writedir(char *dir) * Note: because of this code, this logic should be exercised * *once only* per run. */ +#if USE_HASHED_DB + make_db_path(actual, destination, sizeof(actual)); +#else if (chdir(_nc_tic_dir(destination)) < 0 || getcwd(actual, sizeof(actual)) == 0) _nc_err_abort("%s: not a directory", destination); +#endif _nc_keep_tic_dir(strdup(actual)); } /* - * check_writeable(char code) - * - * Miscellaneous initialisations - * - * Check for access rights to destination directories - * Create any directories which don't exist. - * Note: there's no reason to return the result of make_directory(), since - * this function is called only in instances where that has to succeed. - * - */ - -static void -check_writeable(int code) -{ - static const char dirnames[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - static bool verified[sizeof(dirnames)]; - - char dir[2]; - char *s = 0; - - if (code == 0 || (s = strchr(dirnames, code)) == 0) - _nc_err_abort("Illegal terminfo subdirectory \"%c\"", code); - - if (verified[s - dirnames]) - return; - - dir[0] = code; - dir[1] = '\0'; - if (make_directory(dir) < 0) { - _nc_err_abort("%s/%s: permission denied", _nc_tic_dir(0), dir); - } - - verified[s - dirnames] = TRUE; -} - -/* - * _nc_write_entry() - * * Save the compiled version of a description in the filesystem. * * make a copy of the name-list @@ -204,24 +246,39 @@ check_writeable(int code) * _nc_curr_line is properly set before the write_entry() call. */ -void -_nc_write_entry(TERMTYPE * const tp) +NCURSES_EXPORT(void) +_nc_write_entry(TERMTYPE *const tp) { +#if USE_HASHED_DB + + char buffer[MAX_ENTRY_SIZE + 1]; + unsigned limit = sizeof(buffer); + unsigned offset = 0; + +#else /* !USE_HASHED_DB */ + struct stat statbuf; - char name_list[MAX_TERMINFO_LENGTH]; - char *first_name, *other_names; - char *ptr; char filename[PATH_MAX]; char linkname[PATH_MAX]; #if USE_SYMLINKS char symlinkname[PATH_MAX]; +#if !HAVE_LINK +#undef HAVE_LINK +#define HAVE_LINK 1 +#endif #endif /* USE_SYMLINKS */ + static int call_count; static time_t start_time; /* time at start of writes */ - if (call_count++ == 0) { - start_time = 0; - } +#endif /* USE_HASHED_DB */ + + char name_list[MAX_TERMINFO_LENGTH]; + char *first_name, *other_names; + char *ptr; + + assert(strlen(tp->term_names) != 0); + assert(strlen(tp->term_names) < sizeof(name_list)); (void) strlcpy(name_list, tp->term_names, sizeof(name_list)); DEBUG(7, ("Name list = '%s'", name_list)); @@ -253,10 +310,59 @@ _nc_write_entry(TERMTYPE * const tp) _nc_set_type(first_name); - if (strlen(first_name) > sizeof(filename) - 3) +#if USE_HASHED_DB + if (write_object(tp, buffer + 1, &offset, limit - 1) != ERR) { + DB *capdb = _nc_db_open(_nc_tic_dir(0), TRUE); + DBT key, data; + + if (capdb != 0) { + buffer[0] = 0; + + memset(&key, 0, sizeof(key)); + key.data = tp->term_names; + key.size = strlen(tp->term_names); + + memset(&data, 0, sizeof(data)); + data.data = buffer; + data.size = offset + 1; + + _nc_db_put(capdb, &key, &data); + + buffer[0] = 2; + + key.data = name_list; + key.size = strlen(name_list); + + strlcpy(buffer + 1, tp->term_names, sizeof(buffer) - 1); + data.size = strlen(tp->term_names) + 1; + + _nc_db_put(capdb, &key, &data); + + while (*other_names != '\0') { + ptr = other_names++; + while (*other_names != '|' && *other_names != '\0') + other_names++; + + if (*other_names != '\0') + *(other_names++) = '\0'; + + key.data = ptr; + key.size = strlen(ptr); + + _nc_db_put(capdb, &key, &data); + } + _nc_db_close(capdb); + } + } +#else /* !USE_HASHED_DB */ + if (call_count++ == 0) { + start_time = 0; + } + + if (strlen(first_name) >= sizeof(filename) - 3) _nc_warning("terminal name too long."); - snprintf(filename, sizeof(filename), "%c/%s", first_name[0], first_name); + snprintf(filename, sizeof(filename), LEAF_FMT "/%s", first_name[0], first_name); /* * Has this primary name been written since the first call to @@ -281,6 +387,7 @@ _nc_write_entry(TERMTYPE * const tp) } while (*other_names != '\0') { ptr = other_names++; + assert(ptr < buffer + sizeof(buffer) - 1); while (*other_names != '|' && *other_names != '\0') other_names++; @@ -297,7 +404,7 @@ _nc_write_entry(TERMTYPE * const tp) } check_writeable(ptr[0]); - snprintf(linkname, sizeof(linkname), "%c/%s", ptr[0], ptr); + snprintf(linkname, sizeof(linkname), LEAF_FMT "/%s", ptr[0], ptr); if (strcmp(filename, linkname) == 0) { _nc_warning("self-synonym ignored"); @@ -309,8 +416,8 @@ _nc_write_entry(TERMTYPE * const tp) { int code; #if USE_SYMLINKS - strlcpy(symlinkname, "../", sizeof(symlinkname)); - strlcat(symlinkname, filename, sizeof(symlinkname)); + strlcpy(symlinkname, "../", sizeof(symlinkname)); + strlcat(symlinkname, filename, sizeof(symlinkname)); #endif /* USE_SYMLINKS */ #if HAVE_REMOVE code = remove(linkname); @@ -351,20 +458,45 @@ _nc_write_entry(TERMTYPE * const tp) write_file(linkname, tp); #endif /* HAVE_LINK */ } +#endif /* USE_HASHED_DB */ } +static unsigned +fake_write(char *dst, + unsigned *offset, + unsigned limit, + char *src, + unsigned want, + unsigned size) +{ + int have = (limit - *offset); + + want *= size; + if (have > 0) { + if ((int) want > have) + want = have; + memcpy(dst + *offset, src, want); + *offset += want; + } else { + want = 0; + } + return (int) (want / size); +} + +#define Write(buf, size, count) fake_write(buffer, offset, limit, (char *) buf, count, size) + #undef LITTLE_ENDIAN /* BSD/OS defines this as a feature macro */ #define HI(x) ((x) / 256) #define LO(x) ((x) % 256) #define LITTLE_ENDIAN(p, x) (p)[0] = LO(x), (p)[1] = HI(x) -#define WRITE_STRING(str) (fwrite(str, sizeof(char), strlen(str) + 1, fp) == strlen(str) + 1) +#define WRITE_STRING(str) (Write(str, sizeof(char), strlen(str) + 1) == strlen(str) + 1) static int -compute_offsets(char **Strings, int strmax, short *offsets) +compute_offsets(char **Strings, unsigned strmax, short *offsets) { size_t nextfree = 0; - int i; + unsigned i; for (i = 0; i < strmax; i++) { if (Strings[i] == ABSENT_STRING) { @@ -374,16 +506,17 @@ compute_offsets(char **Strings, int strmax, short *offsets) } else { offsets[i] = nextfree; nextfree += strlen(Strings[i]) + 1; - TRACE_OUT(("put Strings[%d]=%s(%d)", i, _nc_visbuf(Strings[i]), nextfree)); + TRACE_OUT(("put Strings[%d]=%s(%d)", (int) i, + _nc_visbuf(Strings[i]), (int) nextfree)); } } return nextfree; } static void -convert_shorts(unsigned char *buf, short *Numbers, int count) +convert_shorts(unsigned char *buf, short *Numbers, unsigned count) { - int i; + unsigned i; for (i = 0; i < count; i++) { if (Numbers[i] == ABSENT_NUMERIC) { /* HI/LO won't work */ buf[2 * i] = buf[2 * i + 1] = 0377; @@ -398,10 +531,68 @@ convert_shorts(unsigned char *buf, short *Numbers, int count) } #define even_boundary(value) \ - ((value) % 2 != 0 && fwrite(&zero, sizeof(char), 1, fp) != 1) + ((value) % 2 != 0 && Write(&zero, sizeof(char), 1) != 1) + +#if NCURSES_XNAMES +static unsigned +extended_Booleans(TERMTYPE *tp) +{ + unsigned short result = 0; + unsigned short i; + + for (i = 0; i < tp->ext_Booleans; ++i) { + if (tp->Booleans[BOOLCOUNT + i] == TRUE) + result = (i + 1); + } + return result; +} + +static unsigned +extended_Numbers(TERMTYPE *tp) +{ + unsigned short result = 0; + unsigned short i; + + for (i = 0; i < tp->ext_Numbers; ++i) { + if (tp->Numbers[NUMCOUNT + i] != ABSENT_NUMERIC) + result = (i + 1); + } + return result; +} + +static unsigned +extended_Strings(TERMTYPE *tp) +{ + unsigned short result = 0; + unsigned short i; + + for (i = 0; i < tp->ext_Strings; ++i) { + if (tp->Strings[STRCOUNT + i] != ABSENT_STRING) + result = (i + 1); + } + return result; +} + +/* + * _nc_align_termtype() will extend entries that are referenced in a use= + * clause - discard the unneeded data. + */ +static bool +extended_object(TERMTYPE *tp) +{ + bool result = FALSE; + + if (_nc_user_definable) { + result = ((extended_Booleans(tp) + + extended_Numbers(tp) + + extended_Strings(tp)) != 0); + } + return result; +} +#endif static int -write_object(FILE * fp, TERMTYPE * tp) +write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) { char *namelist; size_t namelen, boolmax, nummax, strmax; @@ -460,9 +651,9 @@ write_object(FILE * fp, TERMTYPE * tp) LITTLE_ENDIAN(buf + 10, nextfree); /* write out the header */ - TRACE_OUT(("Header of %s @%ld", namelist, ftell(fp))); - if (fwrite(buf, 12, 1, fp) != 1 - || fwrite(namelist, sizeof(char), namelen, fp) != namelen) + TRACE_OUT(("Header of %s @%d", namelist, *offset)); + if (Write(buf, 12, 1) != 1 + || Write(namelist, sizeof(char), namelen) != namelen) return (ERR); for (i = 0; i < boolmax; i++) @@ -470,27 +661,27 @@ write_object(FILE * fp, TERMTYPE * tp) buf[i] = TRUE; else buf[i] = FALSE; - if (fwrite(buf, sizeof(char), boolmax, fp) != boolmax) + if (Write(buf, sizeof(char), boolmax) != boolmax) return (ERR); if (even_boundary(namelen + boolmax)) return (ERR); - TRACE_OUT(("Numerics begin at %04lx", ftell(fp))); + TRACE_OUT(("Numerics begin at %04x", *offset)); /* the numerics */ convert_shorts(buf, tp->Numbers, nummax); - if (fwrite(buf, 2, nummax, fp) != nummax) + if (Write(buf, 2, nummax) != nummax) return (ERR); - TRACE_OUT(("String offsets begin at %04lx", ftell(fp))); + TRACE_OUT(("String offsets begin at %04x", *offset)); /* the string offsets */ convert_shorts(buf, offsets, strmax); - if (fwrite(buf, 2, strmax, fp) != strmax) + if (Write(buf, 2, strmax) != strmax) return (ERR); - TRACE_OUT(("String table begins at %04lx", ftell(fp))); + TRACE_OUT(("String table begins at %04x", *offset)); /* the strings */ for (i = 0; i < strmax; i++) @@ -499,15 +690,23 @@ write_object(FILE * fp, TERMTYPE * tp) return (ERR); #if NCURSES_XNAMES - if (NUM_EXT_NAMES(tp)) { + if (extended_object(tp)) { unsigned extcnt = NUM_EXT_NAMES(tp); if (even_boundary(nextfree)) return (ERR); - nextfree = compute_offsets(tp->Strings + STRCOUNT, tp->ext_Strings, offsets); + nextfree = compute_offsets(tp->Strings + STRCOUNT, + tp->ext_Strings, + offsets); TRACE_OUT(("after extended string capabilities, nextfree=%d", nextfree)); - nextfree += compute_offsets(tp->ext_Names, extcnt, offsets + tp->ext_Strings); + + if (tp->ext_Strings >= SIZEOF(offsets)) + return (ERR); + + nextfree += compute_offsets(tp->ext_Names, + extcnt, + offsets + tp->ext_Strings); TRACE_OUT(("after extended capnames, nextfree=%d", nextfree)); strmax = tp->ext_Strings + extcnt; @@ -519,23 +718,23 @@ write_object(FILE * fp, TERMTYPE * tp) LITTLE_ENDIAN(buf + 4, tp->ext_Strings); LITTLE_ENDIAN(buf + 6, strmax); LITTLE_ENDIAN(buf + 8, nextfree); - TRACE_OUT(("WRITE extended-header @%ld", ftell(fp))); - if (fwrite(buf, 10, 1, fp) != 1) + TRACE_OUT(("WRITE extended-header @%d", *offset)); + if (Write(buf, 10, 1) != 1) return (ERR); - TRACE_OUT(("WRITE %d booleans @%ld", tp->ext_Booleans, ftell(fp))); + TRACE_OUT(("WRITE %d booleans @%d", tp->ext_Booleans, *offset)); if (tp->ext_Booleans - && fwrite(tp->Booleans + BOOLCOUNT, sizeof(char), - tp->ext_Booleans, fp) != tp->ext_Booleans) + && Write(tp->Booleans + BOOLCOUNT, sizeof(char), + tp->ext_Booleans) != tp->ext_Booleans) return (ERR); if (even_boundary(tp->ext_Booleans)) return (ERR); - TRACE_OUT(("WRITE %d numbers @%ld", tp->ext_Numbers, ftell(fp))); + TRACE_OUT(("WRITE %d numbers @%d", tp->ext_Numbers, *offset)); if (tp->ext_Numbers) { convert_shorts(buf, tp->Numbers + NUMCOUNT, tp->ext_Numbers); - if (fwrite(buf, 2, tp->ext_Numbers, fp) != tp->ext_Numbers) + if (Write(buf, 2, tp->ext_Numbers) != tp->ext_Numbers) return (ERR); } @@ -544,8 +743,8 @@ write_object(FILE * fp, TERMTYPE * tp) * in that order. */ convert_shorts(buf, offsets, strmax); - TRACE_OUT(("WRITE offsets @%ld", ftell(fp))); - if (fwrite(buf, 2, strmax, fp) != strmax) + TRACE_OUT(("WRITE offsets @%d", *offset)); + if (Write(buf, 2, strmax) != strmax) return (ERR); /* @@ -554,7 +753,7 @@ write_object(FILE * fp, TERMTYPE * tp) */ for (i = 0; i < tp->ext_Strings; i++) { if (VALID_STRING(tp->Strings[i + STRCOUNT])) { - TRACE_OUT(("WRITE ext_Strings[%d]=%s", i, + TRACE_OUT(("WRITE ext_Strings[%d]=%s", (int) i, _nc_visbuf(tp->Strings[i + STRCOUNT]))); if (!WRITE_STRING(tp->Strings[i + STRCOUNT])) return (ERR); @@ -565,7 +764,7 @@ write_object(FILE * fp, TERMTYPE * tp) * Write the extended names */ for (i = 0; i < extcnt; i++) { - TRACE_OUT(("WRITE ext_Names[%d]=%s", i, tp->ext_Names[i])); + TRACE_OUT(("WRITE ext_Names[%d]=%s", (int) i, tp->ext_Names[i])); if (!WRITE_STRING(tp->ext_Names[i])) return (ERR); } |