diff options
Diffstat (limited to 'lib/libcurses/tinfo')
42 files changed, 10246 insertions, 0 deletions
diff --git a/lib/libcurses/tinfo/MKcaptab.awk b/lib/libcurses/tinfo/MKcaptab.awk new file mode 100644 index 00000000000..2ea3236af3b --- /dev/null +++ b/lib/libcurses/tinfo/MKcaptab.awk @@ -0,0 +1,66 @@ +#!/bin/sh +# $OpenBSD: MKcaptab.awk,v 1.1 1999/01/18 19:10:12 millert Exp $ +# $From: MKcaptab.awk,v 1.10 1997/09/11 17:40:46 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 <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 + +$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 + } +' + +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 + } +' + +cat <<'EOF' + {(char *)NULL, (char *)NULL, (char *)NULL} +}; + +const struct name_table_entry *_nc_get_table(bool termcap) +{ + return termcap ? _nc_cap_table: _nc_info_table ; +} +EOF diff --git a/lib/libcurses/tinfo/MKfallback.sh b/lib/libcurses/tinfo/MKfallback.sh new file mode 100644 index 00000000000..d6631b2ca8a --- /dev/null +++ b/lib/libcurses/tinfo/MKfallback.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# $OpenBSD: MKfallback.sh,v 1.1 1999/01/18 19:10:12 millert Exp $ +# $From: MKfallback.sh,v 1.8 1996/09/15 01:44:13 tom Exp $ +# +# MKfallback.sh -- create fallback table for entry reads +# +# This script generates source code for a custom version of read_entry.c +# that (instead of reading capabilities for an argument terminal type +# 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. + */ + +#include <curses.priv.h> +#include <term.h> + +EOF + +if [ "$*" ] +then + cat <<EOF +#include <tic.h> + +/* fallback entries for: $* */ + +static const TERMTYPE fallbacks[$#] = +{ +EOF + comma="" + for x in $* + do + echo "$comma /* $x */" + infocmp -e $x + comma="," + done + + cat <<EOF +}; + +EOF +fi + +cat <<EOF +const TERMTYPE *_nc_fallback(const char *name GCC_UNUSED) +{ +EOF + +if [ "$*" ] +then + cat <<EOF + const TERMTYPE *tp; + + for (tp = fallbacks; + tp < fallbacks + sizeof(fallbacks)/sizeof(TERMTYPE); + tp++) + if (_nc_name_match(tp->term_names, name, "|")) + return(tp); +EOF +else + echo " /* the fallback list is empty */"; +fi + +cat <<EOF + return((TERMTYPE *)0); +} +EOF diff --git a/lib/libcurses/tinfo/MKnames.awk b/lib/libcurses/tinfo/MKnames.awk new file mode 100644 index 00000000000..7f49c21b9f5 --- /dev/null +++ b/lib/libcurses/tinfo/MKnames.awk @@ -0,0 +1,99 @@ +# $OpenBSD +# $From: MKnames.awk,v 1.10 1999/01/16 23:36:34 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) 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" + } + +$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" + } + +$3 == "num" { + printf "\t\t\"%s\",\n", $2 > "numnames" + printf "\t\t\"%s\",\n", $1 > "numfnames" + printf "\t\t\"%s\",\n", $4 > "numcodes" + } + +$3 == "str" { + printf "\t\t\"%s\",\n", $2 > "strnames" + printf "\t\t\"%s\",\n", $1 > "strfnames" + printf "\t\t\"%s\",\n", $4 > "strcodes" + } + +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) IT *_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) IT *_nc_##it(void) { return data##it; }" > "codeftr" + print "FIX(boolcodes)" > "codeftr" + print "FIX(numcodes)" > "codeftr" + print "FIX(strcodes)" > "codeftr" + print "#endif /* BROKEN_LINKER */" > "codeftr" + } diff --git a/lib/libcurses/tinfo/access.c b/lib/libcurses/tinfo/access.c new file mode 100644 index 00000000000..20ae2ed4773 --- /dev/null +++ b/lib/libcurses/tinfo/access.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1998 * + ****************************************************************************/ + + +#include <curses.priv.h> + +MODULE_ID("$From: access.c,v 1.1 1998/07/25 20:17:09 tom Exp $") + +int _nc_access(const char *path, int mode) +{ + if (access(path, mode) < 0) { + if ((mode & W_OK) != 0 + && errno == ENOENT) { + char head[PATH_MAX]; + char *leaf = strrchr(strcpy(head, path), '/'); + if (leaf == 0) + leaf = head; + *leaf = '\0'; + if (head == leaf) + (void)strcpy(head, "."); + return access(head, R_OK|W_OK|X_OK); + } + return -1; + } + return 0; +} diff --git a/lib/libcurses/tinfo/add_tries.c b/lib/libcurses/tinfo/add_tries.c new file mode 100644 index 00000000000..31a6e6906ec --- /dev/null +++ b/lib/libcurses/tinfo/add_tries.c @@ -0,0 +1,126 @@ +/* $OpenBSD: add_tries.c,v 1.1 1999/01/18 19:10:12 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1998 * + ****************************************************************************/ + +/* +** add_tries.c +** +** Add keycode/string to tries-tree. +** +*/ + +#include <curses.priv.h> + +MODULE_ID("$From: add_tries.c,v 1.1 1998/11/08 00:04:18 tom Exp $") + +#define SET_TRY(dst,src) if ((dst->ch = *src++) == 128) dst->ch = '\0' +#define CMP_TRY(a,b) ((a)? (a == b) : (b == 128)) + +void _nc_add_to_try(struct tries **tree, char *str, unsigned short code) +{ + static bool out_of_memory = FALSE; + struct tries *ptr, *savedptr; + unsigned char *txt = (unsigned char *)str; + + if (txt == 0 || *txt == '\0' || out_of_memory || code == 0) + return; + + if ((*tree) != 0) { + ptr = savedptr = (*tree); + + for (;;) { + unsigned char cmp = *txt; + + while (!CMP_TRY(ptr->ch, cmp) + && ptr->sibling != 0) + ptr = ptr->sibling; + + if (CMP_TRY(ptr->ch, cmp)) { + if (*(++txt) == '\0') { + ptr->value = code; + return; + } + if (ptr->child != 0) + ptr = ptr->child; + else + break; + } else { + if ((ptr->sibling = typeCalloc(struct tries,1)) == 0) { + out_of_memory = TRUE; + return; + } + + savedptr = ptr = ptr->sibling; + SET_TRY(ptr,txt); + ptr->value = 0; + + break; + } + } /* end for (;;) */ + } else { /* (*tree) == 0 :: First sequence to be added */ + savedptr = ptr = (*tree) = typeCalloc(struct tries,1); + + if (ptr == 0) { + out_of_memory = TRUE; + return; + } + + SET_TRY(ptr,txt); + ptr->value = 0; + } + + /* at this point, we are adding to the try. ptr->child == 0 */ + + while (*txt) { + ptr->child = typeCalloc(struct tries,1); + + ptr = ptr->child; + + if (ptr == 0) { + out_of_memory = TRUE; + + while ((ptr = savedptr) != 0) { + savedptr = ptr->child; + free(ptr); + } + + return; + } + + SET_TRY(ptr,txt); + ptr->value = 0; + } + + ptr->value = code; + return; +} diff --git a/lib/libcurses/tinfo/alloc_entry.c b/lib/libcurses/tinfo/alloc_entry.c new file mode 100644 index 00000000000..49bb255f9a6 --- /dev/null +++ b/lib/libcurses/tinfo/alloc_entry.c @@ -0,0 +1,177 @@ +/* $OpenBSD: alloc_entry.c,v 1.1 1999/01/18 19:10:13 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * alloc_entry.c -- allocation functions for terminfo entries + * + * _nc_init_entry() + * _nc_save_str() + * _nc_merge_entry(); + * _nc_wrap_entry(); + * + */ + +#include <curses.priv.h> + +#include <tic.h> +#include <term.h> +#include <term_entry.h> + +MODULE_ID("$From: alloc_entry.c,v 1.14 1998/07/04 23:17:42 tom 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 size_t next_free; /* next free character in stringbuf */ + +void _nc_init_entry(TERMTYPE *const tp) +/* initialize a terminal type data block */ +{ +int i; + + for (i=0; i < BOOLCOUNT; i++) + tp->Booleans[i] = FALSE; /* FIXME: why not ABSENT_BOOLEAN? */ + + for (i=0; i < NUMCOUNT; i++) + tp->Numbers[i] = ABSENT_NUMERIC; + + for (i=0; i < STRCOUNT; i++) + tp->Strings[i] = ABSENT_STRING; + + next_free = 0; +} + +char *_nc_save_str(const char *const string) +/* save a copy of string in the string buffer */ +{ +size_t old_next_free = next_free; +size_t len = strlen(string) + 1; + + if (next_free + len < MAX_STRTAB) + { + strcpy(&stringbuf[next_free], string); + DEBUG(7, ("Saved string %s", _nc_visbuf(string))); + DEBUG(7, ("at location %d", (int) next_free)); + next_free += len; + } + return(stringbuf + old_next_free); +} + +void _nc_wrap_entry(ENTRY *const ep) +/* copy the string parts to allocated storage, preserving pointers to it */ +{ +int offsets[STRCOUNT], useoffsets[MAX_USES]; +int i, n; + + n = ep->tterm.term_names - stringbuf; + for (i=0; i < STRCOUNT; i++) + if (ep->tterm.Strings[i] == ABSENT_STRING) + offsets[i] = ABSENT_OFFSET; + else if (ep->tterm.Strings[i] == CANCELLED_STRING) + offsets[i] = CANCELLED_OFFSET; + else + offsets[i] = ep->tterm.Strings[i] - stringbuf; + + for (i=0; i < ep->nuses; i++) + if (ep->uses[i].parent == (void *)0) + useoffsets[i] = ABSENT_OFFSET; + else + useoffsets[i] = (char *)(ep->uses[i].parent) - stringbuf; + + if ((ep->tterm.str_table = (char *)malloc(next_free)) == (char *)0) + _nc_err_abort("Out of memory"); + (void) memcpy(ep->tterm.str_table, stringbuf, next_free); + + ep->tterm.term_names = ep->tterm.str_table + n; + for (i=0; i < STRCOUNT; i++) + if (offsets[i] == ABSENT_OFFSET) + ep->tterm.Strings[i] = ABSENT_STRING; + else if (offsets[i] == CANCELLED_OFFSET) + ep->tterm.Strings[i] = CANCELLED_STRING; + else + ep->tterm.Strings[i] = ep->tterm.str_table + offsets[i]; + + for (i=0; i < ep->nuses; i++) + if (useoffsets[i] == ABSENT_OFFSET) + ep->uses[i].parent = (void *)0; + else + ep->uses[i].parent = (char *)(ep->tterm.str_table + useoffsets[i]); +} + +void _nc_merge_entry(TERMTYPE *const to, TERMTYPE *const from) +/* merge capabilities from `from' entry into `to' entry */ +{ + int i; + + for (i=0; i < BOOLCOUNT; i++) + { + int mergebool = from->Booleans[i]; + + if (mergebool == CANCELLED_BOOLEAN) + to->Booleans[i] = FALSE; + else if (mergebool == TRUE) + to->Booleans[i] = mergebool; + } + + for (i=0; i < NUMCOUNT; i++) + { + int mergenum = from->Numbers[i]; + + if (mergenum == CANCELLED_NUMERIC) + to->Numbers[i] = ABSENT_NUMERIC; + else if (mergenum != ABSENT_NUMERIC) + to->Numbers[i] = mergenum; + } + + /* + * Note: the copies of strings this makes don't have their own + * storage. This is OK right now, but will be a problem if we + * we ever want to deallocate entries. + */ + for (i=0; i < STRCOUNT; i++) + { + char *mergestring = from->Strings[i]; + + if (mergestring == CANCELLED_STRING) + to->Strings[i] = ABSENT_STRING; + else if (mergestring != ABSENT_STRING) + to->Strings[i] = mergestring; + } +} + diff --git a/lib/libcurses/tinfo/captoinfo.c b/lib/libcurses/tinfo/captoinfo.c new file mode 100644 index 00000000000..dcdc4c4ca62 --- /dev/null +++ b/lib/libcurses/tinfo/captoinfo.c @@ -0,0 +1,809 @@ +/* $OpenBSD: captoinfo.c,v 1.1 1999/01/18 19:10:13 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + + +/* + * captoinfo.c --- conversion between termcap and terminfo formats + * + * The captoinfo() code was swiped from Ross Ridge's mytinfo package, + * adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>. + * + * There is just one entry point: + * + * char *captoinfo(n, s, parametrized) + * + * Convert value s for termcap string capability named n into terminfo + * format. + * + * This code recognizes all the standard 4.4BSD %-escapes: + * + * %% output `%' + * %d output value as in printf %d + * %2 output value as in printf %2d + * %3 output value as in printf %3d + * %. output value as in printf %c + * %+x add x to value, then do %. + * %>xy if value > x then add y, no output + * %r reverse order of two parameters, no output + * %i increment by one, no output + * %n exclusive-or all parameters with 0140 (Datamedia 2500) + * %B BCD (16*(value/10)) + (value%10), no output + * %D Reverse coding (value - 2*(value%16)), no output (Delta Data). + * + * Also, %02 and %03 are accepted as synonyms for %2 and %3. + * + * Besides all the standard termcap escapes, this translator understands + * the following extended escapes: + * + * used by GNU Emacs termcap libraries + * %a[+*-/=][cp]x GNU arithmetic. + * %m xor the first two parameters by 0177 + * %b backup to previous parameter + * %f skip this parameter + * + * used by the University of Waterloo (MFCF) termcap libraries + * %-x subtract parameter FROM char x and output it as a char + * %ax add the character x to parameter + * + * If #define WATERLOO is on, also enable these translations: + * + * %sx subtract parameter FROM the character x + * + * By default, this Waterloo translations are not compiled in, because + * the Waterloo %s conflicts with the way terminfo uses %s in strings for + * function programming. + * + * Note the two definitions of %a: the GNU definition is translated if the + * characters after the 'a' are valid for it, otherwise the UW definition + * is translated. + */ + +#include <curses.priv.h> + +#include <ctype.h> +#include <tic.h> + +MODULE_ID("$From: captoinfo.c,v 1.21 1998/05/30 23:32:15 Todd.Miller Exp $") + +#define MAX_PUSHED 16 /* max # args we can push onto the stack */ +#define MAX_ENTRY 2048 /* maximum chars in a translated capability */ + +static int stack[MAX_PUSHED]; /* the stack */ +static int stackptr; /* the next empty place on the stack */ +static int onstack; /* the top of stack */ +static int seenm; /* seen a %m */ +static int seenn; /* seen a %n */ +static int seenr; /* seen a %r */ +static int param; /* current parameter */ +static char *dp; /* pointer to end of the converted string */ + +static char *my_string; +static size_t my_length; + +static char *init_string(void) +/* initialize 'my_string', 'my_length' */ +{ + if (my_string == 0) + my_string = malloc(my_length = 256); + if (my_string == 0) + _nc_err_abort("Out of memory"); + + *my_string = '\0'; + return my_string; +} + +static char *save_string(char *d, const char *const s) +{ + size_t have = (d - my_string); + size_t need = have + strlen(s) + 2; + if (need > my_length) { + my_string = realloc(my_string, my_length = (need + need)); + if (my_string == 0) + _nc_err_abort("Out of memory"); + d = my_string + have; + } + (void) strcpy(d, s); + return d + strlen(d); +} + +static inline char *save_char(char *s, char c) +{ + static char temp[2]; + temp[0] = c; + return save_string(s, temp); +} + +static void push(void) +/* push onstack on to the stack */ +{ + if (stackptr > MAX_PUSHED) + _nc_warning("string too complex to convert"); + else + stack[stackptr++] = onstack; +} + +static void pop(void) +/* pop the top of the stack into onstack */ +{ + if (stackptr == 0) { + if (onstack == 0) + _nc_warning("I'm confused"); + else + onstack = 0; + } + else + onstack = stack[--stackptr]; + param++; +} + +static int cvtchar(register const char *sp) +/* convert a character to a terminfo push */ +{ + unsigned char c = 0; + int len; + + switch(*sp) { + case '\\': + switch(*++sp) { + case '\'': + case '$': + case '\\': + case '%': + c = *sp; + len = 2; + break; + case '\0': + c = '\\'; + len = 1; + break; + case '0': + case '1': + case '2': + case '3': + len = 1; + while (isdigit(*sp)) + { + c = 8 * c + (*sp++ - '0'); + len++; + } + break; + default: + c = *sp; + len = 2; + break; + } + break; + case '^': + c = (*++sp & 0x1f); + len = 2; + break; + default: + c = *sp; + len = 1; + } + if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') { + *dp++ = '%'; *dp++ = '\''; *dp++ = c; *dp++ = '\''; + } else { + *dp++ = '%'; *dp++ = '{'; + if (c > 99) + *dp++ = c / 100 + '0'; + if (c > 9) + *dp++ = ((int)(c / 10)) % 10 + '0'; + *dp++ = c % 10 + '0'; + *dp++ = '}'; + } + return len; +} + +static void getparm(int parm, int n) +/* push n copies of param on the terminfo stack if not already there */ +{ + if (seenr) { + if (parm == 1) + parm = 2; + else if (parm == 2) + parm = 1; + } + if (onstack == parm) { + if (n > 1) { + _nc_warning("string may not be optimal"); + *dp++ = '%'; *dp++ = 'P'; *dp++ = 'a'; + while(n--) { + *dp++ = '%'; *dp++ = 'g'; *dp++ = 'a'; + } + } + return; + } + if (onstack != 0) + push(); + + onstack = parm; + + while(n--) { /* %p0 */ + *dp++ = '%'; *dp++ = 'p'; *dp++ = '0' + parm; + } + + if (seenn && parm < 3) { /* %{96}%^ */ + *dp++ = '%'; *dp++ = '{'; *dp++ = '9'; *dp++ = '6'; *dp++ = '}'; + *dp++ = '%'; *dp++ = '^'; + } + + if (seenm && parm < 3) { /* %{127}%^ */ + *dp++ = '%'; *dp++ = '{'; *dp++ = '1'; *dp++ = '2'; *dp++ = '7'; + *dp++ = '}'; *dp++ = '%'; *dp++ = '^'; + } +} + +char *_nc_captoinfo( +/* convert a termcap string to terminfo format */ +register const char *cap, /* relevant terminfo capability index */ +register const char *s, /* string value of the capability */ +int const parametrized) /* do % translations if 1, pad translations if >=0 */ +{ + static char line[MAX_ENTRY]; + const char *capstart; + + stackptr = 0; + onstack = 0; + seenm = 0; + seenn = 0; + seenr = 0; + param = 1; + + dp = line; + + /* skip the initial padding (if we haven't been told not to) */ + capstart = 0; + if (s == 0) + s = ""; + if (parametrized >= 0 && isdigit(*s)) + for (capstart = s; ; s++) + if (!(isdigit(*s) || *s == '*' || *s == '.')) + break; + + while(*s != '\0') { + switch(*s) { + case '%': + s++; + if (parametrized < 1) { + *dp++ = '%'; + break; + } + switch(*s++) { + case '%': *dp++ = '%'; break; + case 'r': + if (seenr++ == 1) { + _nc_warning("saw %%r twice in %s", cap); + } + break; + case 'm': + if (seenm++ == 1) { + _nc_warning("saw %%m twice in %s", cap); + } + break; + case 'n': + if (seenn++ == 1) { + _nc_warning("saw %%n twice in %s", cap); + } + break; + case 'i': *dp++ = '%'; *dp++ = 'i'; break; + case '6': + case 'B': + getparm(param, 2); + /* %{6}%*%+ */ + *dp++ = '%'; *dp++ = '{'; *dp++ = '6'; + *dp++ = '}'; *dp++ = '%'; *dp++ = '*'; + *dp++ = '%'; *dp++ = '+'; + break; + case '8': + case 'D': + getparm(param, 2); + /* %{2}%*%- */ + *dp++ = '%'; *dp++ = '{'; *dp++ = '2'; + *dp++ = '}'; *dp++ = '%'; *dp++ = '*'; + *dp++ = '%'; *dp++ = '-'; + break; + case '>': + getparm(param, 2); + /* %?%{x}%>%t%{y}%+%; */ + *dp++ = '%'; *dp++ = '?'; + s += cvtchar(s); + *dp++ = '%'; *dp++ = '>'; + *dp++ = '%'; *dp++ = 't'; + s += cvtchar(s); + *dp++ = '%'; *dp++ = '+'; + *dp++ = '%'; *dp++ = ';'; + break; + case 'a': + if ((*s == '=' || *s == '+' || *s == '-' + || *s == '*' || *s == '/') + && (s[1] == 'p' || s[1] == 'c') + && s[2] != '\0') { + int l; + l = 2; + if (*s != '=') + getparm(param, 1); + if (s[1] == 'p') { + getparm(param + s[2] - '@', 1); + if (param != onstack) { + pop(); + param--; + } + l++; + } else + l += cvtchar(s + 2); + switch(*s) { + case '+': + *dp++ = '%'; *dp++ = '+'; + break; + case '-': + *dp++ = '%'; *dp++ = '-'; + break; + case '*': + *dp++ = '%'; *dp++ = '*'; + break; + case '/': + *dp++ = '%'; *dp++ = '/'; + break; + case '=': + if (seenr) { + if (param == 1) + onstack = 2; + else if (param == 2) + onstack = 1; + else + onstack = param; + } + else + onstack = param; + break; + } + s += l; + break; + } + getparm(param, 1); + s += cvtchar(s); + *dp++ = '%'; *dp++ = '+'; + break; + case '+': + getparm(param, 1); + s += cvtchar(s); + *dp++ = '%'; *dp++ = '+'; + *dp++ = '%'; *dp++ = 'c'; + pop(); + break; + case 's': +#ifdef WATERLOO + s += cvtchar(s); + getparm(param, 1); + *dp++ = '%'; *dp++ = '-'; +#else + getparm(param, 1); + *dp++ = '%'; *dp++ = 's'; + pop(); +#endif /* WATERLOO */ + break; + case '-': + s += cvtchar(s); + getparm(param, 1); + *dp++ = '%'; *dp++ = '-'; + *dp++ = '%'; *dp++ = 'c'; + pop(); + break; + case '.': + getparm(param, 1); + *dp++ = '%'; *dp++ = 'c'; + pop(); + break; + case '0': /* not clear any of the historical termcaps did this */ + if (*s == '3') + goto see03; + else if (*s != '2') + goto invalid; + /* FALLTHRU */ + case '2': + getparm(param, 1); + *dp++ = '%'; /* *dp++ = '0'; */ + *dp++ = '2'; *dp++ = 'd'; + pop(); + break; + case '3': see03: + getparm(param, 1); + *dp++ = '%'; /* *dp++ = '0'; */ + *dp++ = '3'; *dp++ = 'd'; + pop(); + break; + case 'd': + getparm(param, 1); + *dp++ = '%'; *dp++ = 'd'; + pop(); + break; + case 'f': + param++; + break; + case 'b': + param--; + break; + case '\\': + *dp++ = '%'; + *dp++ = '\\'; + break; + default: invalid: + *dp++ = '%'; + s--; + _nc_warning("unknown %% code %s in %s", + _tracechar(*s), cap); + break; + } + break; +#ifdef REVISIBILIZE + case '\\': + *dp++ = *s++; *dp++ = *s++; break; + case '\n': + *dp++ = '\\'; *dp++ = 'n'; s++; break; + case '\t': + *dp++ = '\\'; *dp++ = 't'; s++; break; + case '\r': + *dp++ = '\\'; *dp++ = 'r'; s++; break; + case '\200': + *dp++ = '\\'; *dp++ = '0'; s++; break; + case '\f': + *dp++ = '\\'; *dp++ = 'f'; s++; break; + case '\b': + *dp++ = '\\'; *dp++ = 'b'; s++; break; + case ' ': + *dp++ = '\\'; *dp++ = 's'; s++; break; + case '^': + *dp++ = '\\'; *dp++ = '^'; s++; break; + case ':': + *dp++ = '\\'; *dp++ = ':'; s++; break; + case ',': + *dp++ = '\\'; *dp++ = ','; s++; break; + default: + if (*s == '\033') { + *dp++ = '\\'; + *dp++ = 'E'; + s++; + } else if (*s > 0 && *s < 32) { + *dp++ = '^'; + *dp++ = *s + '@'; + s++; + } else if (*s <= 0 || *s >= 127) { + *dp++ = '\\'; + *dp++ = ((*s & 0300) >> 6) + '0'; + *dp++ = ((*s & 0070) >> 3) + '0'; + *dp++ = (*s & 0007) + '0'; + s++; + } else + *dp++ = *s++; + break; +#else + default: + *dp++ = *s++; + break; +#endif + } + } + + /* + * Now, if we stripped off some leading padding, add it at the end + * of the string as mandatory padding. + */ + if (capstart) + { + *dp++ = '$'; + *dp++ = '<'; + for (s = capstart; ; s++) + if (isdigit(*s) || *s == '*' || *s == '.') + *dp++ = *s; + else + break; + *dp++ = '/'; + *dp++ = '>'; + } + + *dp = '\0'; + return(line); +} + +/* + * Here are the capabilities infotocap assumes it can translate to: + * + * %% output `%' + * %d output value as in printf %d + * %2 output value as in printf %2d + * %3 output value as in printf %3d + * %. output value as in printf %c + * %+c add character c to value, then do %. + * %>xy if value > x then add y, no output + * %r reverse order of two parameters, no output + * %i increment by one, no output + * %n exclusive-or all parameters with 0140 (Datamedia 2500) + * %B BCD (16*(value/10)) + (value%10), no output + * %D Reverse coding (value - 2*(value%16)), no output (Delta Data). + * %m exclusive-or all parameters with 0177 (not in 4.4BSD) + */ + +char *_nc_infotocap( +/* convert a terminfo string to termcap format */ +register const char *cap GCC_UNUSED, /* relevant termcap capability index */ +register const char *str, /* string value of the capability */ +int const parametrized) /* do % translations if 1, pad translations if >=0 */ +{ + int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0; + const char *padding; + const char *trimmed = 0; + char ch1 = 0, ch2 = 0; + char *bufptr = init_string(); + char temp[256]; + + /* we may have to move some trailing mandatory padding up front */ + padding = str + strlen(str) - 1; + if (*padding == '>' && *--padding == '/') + { + --padding; + while (isdigit(*padding) || *padding == '.' || *padding == '*') + padding--; + if (*padding == '<' && *--padding == '$') + trimmed = padding; + padding += 2; + + while (isdigit(*padding) || *padding == '.' || *padding == '*') + bufptr = save_char(bufptr, *padding++); + } + + for (; *str && str != trimmed; str++) + { + int c1, c2; + char *cp; + + if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) + { + bufptr = save_char(bufptr, *++str); + } + else if (str[0] == '$' && str[1] == '<') /* discard padding */ + { + str += 2; + while (isdigit(*str) || *str == '.' || *str == '*' || *str == '/' || *str == '>') + str++; + --str; + } + else if (*str != '%' || (parametrized < 1)) + bufptr = save_char(bufptr, *str); + else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1,&c2) == 2) + { + str = strchr(str, ';'); + (void) sprintf(temp, "%%>%s%s", unctrl(c1), unctrl(c2)); + bufptr = save_string(bufptr, temp); + } + else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1,&ch2) == 2) + { + str = strchr(str, ';'); + (void) sprintf(temp, "%%>%s%c", unctrl(c1), ch2); + bufptr = save_string(bufptr, temp); + } + else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1,&c2) == 2) + { + str = strchr(str, ';'); + (void) sprintf(temp, "%%>%c%c", ch1, c2); + bufptr = save_string(bufptr, temp); + } + else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) + { + str = strchr(str, ';'); + (void) sprintf(temp, "%%>%c%c", ch1, ch2); + bufptr = save_string(bufptr, temp); + } + else if (strncmp(str, "%{6}%*%+", 8) == 0) + { + str += 7; + (void) sprintf(temp, "%%B"); + bufptr = save_string(bufptr, temp); + } + else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1 + || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1) + && (cp = strchr(str, '+'))) + { + str = cp + 2; + bufptr = save_char(bufptr, '%'); + bufptr = save_char(bufptr, '+'); + + if (ch1) + c1 = ch1; + if (is7bits(c1) && isprint(c1)) + bufptr = save_char(bufptr, (char)c1); + else + { + if (c1 == (c1 & 0x1f)) /* iscntrl() returns T on 255 */ + (void) strcpy(temp, unctrl(c1)); + else + (void) sprintf(temp, "\\%03o", c1); + bufptr = save_string(bufptr, temp); + } + } + else if (strncmp(str, "%{2}%*%-", 8) == 0) + { + str += 7; + (void) sprintf(temp, "%%D"); + bufptr = save_string(bufptr, temp); + } + else if (strncmp(str, "%{96}%^", 7) == 0) + { + str += 6; + if (saw_m++ == 0) + { + (void) sprintf(temp, "%%n"); + bufptr = save_string(bufptr, temp); + } + } + else if (strncmp(str, "%{127}%^", 8) == 0) + { + str += 7; + if (saw_n++ == 0) + { + (void) sprintf(temp, "%%m"); + bufptr = save_string(bufptr, temp); + } + } + else + { + str++; + switch (*str) { + case '%': + bufptr = save_char(bufptr, '%'); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + bufptr = save_char(bufptr, '%'); + while (isdigit(*str)) + bufptr = save_char(bufptr, *str++); + if (*str == 'd') + str++; + else + _nc_warning("numeric prefix is missing trailing d in %s", + cap); + --str; + break; + + case 'd': + bufptr = save_char(bufptr, '%'); + bufptr = save_char(bufptr, 'd'); + break; + + case 'c': + bufptr = save_char(bufptr, '%'); + bufptr = save_char(bufptr, '.'); + break; + + /* + * %s isn't in termcap, but it's convenient to pass it through + * so we can represent things like terminfo pfkey strings in + * termcap notation. + */ + case 's': + bufptr = save_char(bufptr, '%'); + bufptr = save_char(bufptr, 's'); + break; + + case 'p': + str++; + if (*str == '1') + seenone = 1; + else if (*str == '2') + { + if (!seenone && !seentwo) + { + bufptr = save_char(bufptr, '%'); + bufptr = save_char(bufptr, 'r'); + seentwo++; + } + } + else if (*str >= '3') + return(0); + break; + + case 'i': + bufptr = save_char(bufptr, '%'); + bufptr = save_char(bufptr, 'i'); + break; + + default: + return(0); + + } /* endswitch (*str) */ + } /* endelse (*str == '%') */ + + if (*str == '\0') + break; + + } /* endwhile (*str) */ + + return(my_string); +} + +#ifdef MAIN + +int curr_line; + +int main(int argc, char *argv[]) +{ + int c, tc = FALSE; + + while ((c = getopt(argc, argv, "c")) != EOF) + switch (c) + { + case 'c': + tc = TRUE; + break; + } + + curr_line = 0; + for (;;) + { + char buf[BUFSIZ]; + + ++curr_line; + if (fgets(buf, sizeof(buf), stdin) == 0) + break; + buf[strlen(buf) - 1] = '\0'; + _nc_set_source(buf); + + if (tc) + { + char *cp = _nc_infotocap("to termcap", buf, 1); + + if (cp) + (void) fputs(cp, stdout); + } + else + (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout); + (void) putchar('\n'); + } + return(0); +} +#endif /* MAIN */ + +/* captoinfo.c ends here */ + diff --git a/lib/libcurses/tinfo/comp_error.c b/lib/libcurses/tinfo/comp_error.c new file mode 100644 index 00000000000..2a5b115c7ad --- /dev/null +++ b/lib/libcurses/tinfo/comp_error.c @@ -0,0 +1,134 @@ +/* $OpenBSD: comp_error.c,v 1.1 1999/01/18 19:10:13 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * comp_error.c -- Error message routines + * + */ + +#include <curses.priv.h> + +#include <tic.h> + +MODULE_ID("$From: comp_error.c,v 1.16 1998/08/01 23:39:51 tom Exp $") + +bool _nc_suppress_warnings; +int _nc_curr_line; /* current line # in input */ +int _nc_curr_col; /* current column # in input */ + +static const char *sourcename; +static char termtype[MAX_NAME_SIZE+1]; + +void _nc_set_source(const char *const name) +{ + sourcename = name; +} + +void _nc_set_type(const char *const name) +{ + if (name) + strlcpy( termtype, name, sizeof(termtype) ); + else + termtype[0] = '\0'; +} + +void _nc_get_type(char *name) +{ + strcpy( name, termtype ); +} + +static inline void where_is_problem(void) +{ + fprintf (stderr, "\"%s\"", 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); + fputc(':', stderr); + fputc(' ', stderr); +} + +void _nc_warning(const char *const fmt, ...) +{ +va_list argp; + + if (_nc_suppress_warnings) + return; + + where_is_problem(); + va_start(argp,fmt); + vfprintf (stderr, fmt, argp); + fprintf (stderr, "\n"); + va_end(argp); +} + + +void _nc_err_abort(const char *const fmt, ...) +{ +va_list argp; + + where_is_problem(); + va_start(argp,fmt); + vfprintf (stderr, fmt, argp); + fprintf (stderr, "\n"); + va_end(argp); + exit(EXIT_FAILURE); +} + + +void _nc_syserr_abort(const char *const fmt, ...) +{ +va_list argp; + + where_is_problem(); + va_start(argp,fmt); + vfprintf (stderr, fmt, argp); + fprintf (stderr, "\n"); + va_end(argp); + + /* If we're debugging, try to show where the problem occurred - this + * will dump core. + */ +#if defined(TRACE) || !defined(NDEBUG) + abort(); +#else + /* Dumping core in production code is not a good idea. + */ + exit(EXIT_FAILURE); +#endif +} diff --git a/lib/libcurses/tinfo/comp_expand.c b/lib/libcurses/tinfo/comp_expand.c new file mode 100644 index 00000000000..12c7113fb9d --- /dev/null +++ b/lib/libcurses/tinfo/comp_expand.c @@ -0,0 +1,183 @@ +/* $OpenBSD: comp_expand.c,v 1.1 1999/01/18 19:10:13 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1998 * + ****************************************************************************/ + +#include <curses.priv.h> + +#include <ctype.h> +#include <tic.h> + +MODULE_ID("$From: comp_expand.c,v 1.9 1998/09/26 13:41:40 tom Exp $") + +static int trailing_spaces(const char *src) +{ + while (*src == ' ') + src++; + return *src == 0; +} + +/* 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))) + +char *_nc_tic_expand(const char *srcp, bool tic_format, bool numbers) +{ +static char * buffer; +static size_t length; + +int bufp; +const char *ptr, *str = VALID_STRING(srcp) ? srcp : ""; +bool islong = (strlen(str) > 3); +size_t need = (2 + strlen(str)) * 4; +int ch; + + if (buffer == 0 || need > length) { + if ((buffer = (char *)_nc_doalloc(buffer, length = need)) == 0) + return 0; + } + + bufp = 0; + ptr = str; + while ((ch = (*str & 0xff)) != 0) { + if (ch == '%' && REALPRINT(str+1)) { + buffer[bufp++] = *str++; + /* + * Though the character literals are more compact, most + * terminal descriptions use numbers and are not easy + * to read in character-literal form. This is the + * default option for tic/infocmp. + */ + if (numbers + && str[0] == S_QUOTE + && str[1] != '\\' + && REALPRINT(str+1) + && str[2] == S_QUOTE) { + sprintf(buffer+bufp, "{%d}", str[1]); + bufp += strlen(buffer+bufp); + str += 2; + } + /* + * If we have a "%{number}", try to translate it into + * a "%'char'" form, since that will run a little faster + * when we're interpreting it. Also, having one form + * for the constant makes it simpler to compare terminal + * descriptions. + */ + else if (!numbers + && str[0] == L_BRACE + && isdigit(str[1])) { + char *dst = 0; + long value = strtol(str+1, &dst, 0); + if (dst != 0 + && *dst == R_BRACE + && value < 127 + && value != '\\' /* FIXME */ + && isprint((int)value)) { + ch = (int)value; + buffer[bufp++] = S_QUOTE; + if (ch == '\\' + || ch == S_QUOTE) + buffer[bufp++] = '\\'; + buffer[bufp++] = ch; + buffer[bufp++] = S_QUOTE; + str = dst; + } else { + buffer[bufp++] = *str; + } + } else { + buffer[bufp++] = *str; + } + } + else if (ch == 128) { + buffer[bufp++] = '\\'; + buffer[bufp++] = '0'; + } + else if (ch == '\033') { + buffer[bufp++] = '\\'; + buffer[bufp++] = 'E'; + } + else if (ch == '\\' && tic_format && (str == srcp || str[-1] != '^')) { + buffer[bufp++] = '\\'; + buffer[bufp++] = '\\'; + } + else if (ch == ' ' && tic_format && (str == srcp || trailing_spaces(str))) { + buffer[bufp++] = '\\'; + buffer[bufp++] = 's'; + } + else if ((ch == ',' || ch == ':' || ch == '^') && tic_format) { + buffer[bufp++] = '\\'; + buffer[bufp++] = ch; + } + else if (REALPRINT(str) && (ch != ',' && ch != ':' && !(ch == '!' && !tic_format) && ch != '^')) + buffer[bufp++] = ch; +#if 0 /* FIXME: this would be more readable (in fact the whole 'islong' logic should be removed) */ + else if (ch == '\b') { + buffer[bufp++] = '\\'; + buffer[bufp++] = 'b'; + } + else if (ch == '\f') { + buffer[bufp++] = '\\'; + buffer[bufp++] = 'f'; + } + else if (ch == '\t' && islong) { + buffer[bufp++] = '\\'; + buffer[bufp++] = 't'; + } +#endif + else if (ch == '\r' && (islong || (strlen(srcp) > 2 && str[1] == '\0'))) { + buffer[bufp++] = '\\'; + buffer[bufp++] = 'r'; + } + else if (ch == '\n' && islong) { + buffer[bufp++] = '\\'; + buffer[bufp++] = 'n'; + } +#define UnCtl(c) ((c) + '@') + else if (REALCTL(str) && ch != '\\' && (!islong || isdigit(str[1]))) + { + (void) sprintf(&buffer[bufp], "^%c", UnCtl(ch)); + bufp += 2; + } + else + { + (void) sprintf(&buffer[bufp], "\\%03o", ch); + bufp += 4; + } + + str++; + } + + buffer[bufp] = '\0'; + return(buffer); +} diff --git a/lib/libcurses/tinfo/comp_hash.c b/lib/libcurses/tinfo/comp_hash.c new file mode 100644 index 00000000000..a2d7de5866c --- /dev/null +++ b/lib/libcurses/tinfo/comp_hash.c @@ -0,0 +1,334 @@ +/* $OpenBSD: comp_hash.c,v 1.1 1999/01/18 19:10:14 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * comp_hash.c --- Routines to deal with the hashtable of capability + * names. + * + */ + +#include <curses.priv.h> + +#include <tic.h> +#include <hashsize.h> + +#ifdef MAIN_PROGRAM +#include <ctype.h> +#undef DEBUG +#define DEBUG(level, params) /*nothing*/ +#endif + +MODULE_ID("$From: comp_hash.c,v 1.18 1998/08/22 18:01:18 tom Exp $") + +static int hash_function(const char *); + +/* + * _nc_make_hash_table() + * + * Takes the entries in table[] and hashes them into hash_table[] + * by name. There are CAPTABSIZE entries in table[] and HASHTABSIZE + * slots in hash_table[]. + * + */ + +#ifdef MAIN_PROGRAM +static void _nc_make_hash_table(struct name_table_entry *table, + struct name_table_entry **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)); +} +#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. + * + */ + +static +int +hash_function(const char *string) +{ +long sum = 0; + + DEBUG(9, ("hashing %s", string)); + while (*string) { + sum += (long)(*string + (*(string + 1) << 8)); + string++; + } + + DEBUG(9, ("sum is %ld", sum)); + return (int)(sum % HASHTABSIZE); +} + + +/* + * struct name_table_entry * + * find_entry(string) + * + * Finds the entry for the given string in the hash table if present. + * Returns a pointer to the entry in the table or 0 if not found. + * + */ + +#ifndef MAIN_PROGRAM +struct name_table_entry const * +_nc_find_entry(const char *string, const struct name_table_entry *const *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]; + } + } + + return (ptr); +} + +/* + * struct name_table_entry * + * find_type_entry(string, type, table) + * + * Finds the first entry for the given name with the given type in the + * given table if present (as distinct from find_entry, which finds the + * the last entry regardless of type). You can use this if you detect + * a name clash. It's slower, though. Returns a pointer to the entry + * in the table or 0 if not found. + */ + +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; + + 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); +} +#endif + +#ifdef MAIN_PROGRAM +/* + * This filter reads from standard input a list of tab-delimited columns, + * (e.g., from Caps.filtered) computes the hash-value of a specified column and + * writes the hashed tables to standard output. + * + * By compiling the hash table at build time, we're able to make the entire + * set of terminfo and termcap tables readonly (and also provide some runtime + * performance enhancement). + */ + +#if !HAVE_STRDUP +static char *strdup (char *s) +{ + char *p; + + p = malloc(strlen(s)+1); + if (p) + strcpy(p,s); + return(p); +} +#endif /* not HAVE_STRDUP */ + +#define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ + +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 (*++s && isspace(*s)) + /*EMPTY*/; + buffer = s; + } else + break; + } + } + return col ? list : 0; +} + +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); + } + + /* + * 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++; + } + _nc_make_hash_table(name_table, hash_table); + + /* + * Write the compiled tables to standard output + */ + printf("static struct name_table_entry const _nc_%s_table[] =\n", + root_name); + printf("{\n"); + for (n = 0; n < CAPTABSIZE; n++) { + sprintf(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("};\n\n"); + + printf("const struct name_table_entry * const _nc_%s_hash_table[%d] =\n", + root_name, + HASHTABSIZE+1); + printf("{\n"); + for (n = 0; n < HASHTABSIZE; n++) { + if (hash_table[n] != 0) { + sprintf(buffer, "_nc_%s_table + %3ld", + root_name, + (long) (hash_table[n] - name_table)); + } else { + strcpy(buffer, "0"); + } + printf("\t%s,\n", buffer); + } + 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; +} +#endif diff --git a/lib/libcurses/tinfo/comp_parse.c b/lib/libcurses/tinfo/comp_parse.c new file mode 100644 index 00000000000..6416db292ae --- /dev/null +++ b/lib/libcurses/tinfo/comp_parse.c @@ -0,0 +1,539 @@ +/* $OpenBSD: comp_parse.c,v 1.1 1999/01/18 19:10:14 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + + +/* + * comp_parse.c -- parser driver loop and use handling. + * + * _nc_read_entry_source(FILE *, literal, bool, bool (*hook)()) + * _nc_resolve_uses(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 + * storage, do _nc_free_entries(). + * + */ + +#include <curses.priv.h> + +#include <ctype.h> + +#include <tic.h> +#include <term.h> +#include <term_entry.h> + +MODULE_ID("$From: comp_parse.c,v 1.23 1998/05/30 23:38:15 Todd.Miller Exp $") + +static void sanity_check(TERMTYPE *); + +/**************************************************************************** + * + * 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 + */ + +ENTRY *_nc_head, *_nc_tail; + +static void enqueue(ENTRY *ep) +/* add an entry to the in-core list */ +{ + ENTRY *newp = (ENTRY *)malloc(sizeof(ENTRY)); + + if (newp == NULL) + _nc_err_abort("Out of memory"); + + (void) memcpy(newp, ep, sizeof(ENTRY)); + + newp->last = _nc_tail; + _nc_tail = newp; + + newp->next = (ENTRY *)NULL; + if (newp->last) + newp->last->next = newp; +} + +void _nc_free_entries(ENTRY *head) +/* free the allocated storage consumed by list entries */ +{ + ENTRY *ep, *next; + + for (ep = head; 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; + } +} + +bool _nc_entry_match(char *n1, char *n2) +/* do any of the aliases in a pair of terminal names match? */ +{ + char *pstart, *qstart, *pend, *qend; + char nc1[MAX_NAME_SIZE+1], nc2[MAX_NAME_SIZE+1]; + size_t n; + + if (strchr(n1, '|') == NULL) + { + if ((n = strlcpy(nc1, n1, sizeof(nc1))) > sizeof(nc1) - 2) + n = sizeof(nc1) - 2; + nc1[n++] = '|'; + nc1[n] = '\0'; + n1 = nc1; + } + + if (strchr(n2, '|') == NULL) + { + if ((n = strlcpy(nc2, n2, sizeof(nc2))) > sizeof(nc2) - 2) + n = sizeof(nc2) - 2; + nc2[n++] = '|'; + nc2[n] = '\0'; + n2 = nc2; + } + + for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1) + for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1) + if ((pend-pstart == qend-qstart) + && memcmp(pstart, qstart, (size_t)(pend-pstart)) == 0) + return(TRUE); + + return(FALSE); +} + +/**************************************************************************** + * + * Entry compiler and resolution logic + * + ****************************************************************************/ + +void _nc_read_entry_source(FILE *fp, char *buf, + int literal, bool silent, + bool (*hook)(ENTRY *)) +/* slurp all entries in the given file into core */ +{ + ENTRY thisentry; + bool oldsuppress = _nc_suppress_warnings; + int immediate = 0; + + if (silent) + _nc_suppress_warnings = TRUE; /* shut the lexer up, too */ + + for (_nc_reset_input(fp, buf); _nc_parse_entry(&thisentry, literal, silent) != ERR; ) + { + if (!isalnum(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. + */ + if (hook != NULLHOOK && (*hook)(&thisentry)) + immediate++; + else + enqueue(&thisentry); + } + + if (_nc_tail) + { + /* set up the head pointer */ + for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last) + continue; + + DEBUG(1, ("head = %s", _nc_head->tterm.term_names)); + DEBUG(1, ("tail = %s", _nc_tail->tterm.term_names)); + } +#ifdef TRACE + else if (!immediate) + DEBUG(1, ("no entries parsed")); +#endif + + _nc_suppress_warnings = oldsuppress; +} + +int _nc_resolve_uses(void) +/* try to resolve all use capabilities */ +{ + ENTRY *qp, *rp, *lastread = NULL; + bool keepgoing; + int i, j, unresolved, total_unresolved, multiples; + + DEBUG(2, ("RESOLUTION BEGINNING")); + + /* + * Check for multiple occurrences of the same name. + */ + multiples = 0; + for_entry_list(qp) + { + int matchcount = 0; + + for_entry_list(rp) + if (qp > rp + && _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) + { + matchcount++; + if (matchcount == 1) + { + (void) fprintf(stderr, "Name collision between %s", + _nc_first_name(qp->tterm.term_names)); + multiples++; + } + if (matchcount >= 1) + (void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names)); + } + if (matchcount >= 1) + (void) putc('\n', stderr); + } + if (multiples > 0) + return(FALSE); + + DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES")); + + /* + * First resolution stage: replace names in use arrays with entry + * pointers. By doing this, we avoid having to do the same name + * match once for each time a use entry is itself unresolved. + */ + total_unresolved = 0; + _nc_curr_col = -1; + for_entry_list(qp) + { + unresolved = 0; + for (i = 0; i < qp->nuses; i++) + { + bool foundit; + char *child = _nc_first_name(qp->tterm.term_names); + char *lookfor = (char *)(qp->uses[i].parent); + long lookline = qp->uses[i].line; + + foundit = FALSE; + + _nc_set_type(child); + + /* first, try to resolve from in-core records */ + for_entry_list(rp) + if (rp != qp + && _nc_name_match(rp->tterm.term_names, lookfor, "|")) + { + DEBUG(2, ("%s: resolving use=%s (in core)", + child, lookfor)); + + qp->uses[i].parent = rp; + foundit = TRUE; + } + + /* if that didn't work, try to merge in a compiled entry */ + if (!foundit) + { + TERMTYPE thisterm; + char filename[PATH_MAX]; + + if (_nc_read_entry(lookfor, filename, &thisterm) == 1) + { + DEBUG(2, ("%s: resolving use=%s (compiled)", + child, lookfor)); + + rp = (ENTRY *)malloc(sizeof(ENTRY)); + if (rp == NULL) + _nc_err_abort("Out of memory"); + memcpy(&rp->tterm, &thisterm, sizeof(TERMTYPE)); + rp->nuses = 0; + rp->next = lastread; + lastread = rp; + + qp->uses[i].parent = rp; + foundit = TRUE; + } + } + + /* no good, mark this one unresolvable and complain */ + if (!foundit) + { + unresolved++; + total_unresolved++; + + _nc_curr_line = lookline; + _nc_warning("resolution of use=%s failed", lookfor); + qp->uses[i].parent = (ENTRY *)NULL; + } + } + } + if (total_unresolved) + { + /* free entries read in off disk */ + _nc_free_entries(lastread); + return(FALSE); + } + + DEBUG(2, ("NAME RESOLUTION COMPLETED OK")); + + /* + * OK, at this point all (char *) references have been successfully + * replaced by (ENTRY *) pointers. Time to do the actual merges. + */ + do { + TERMTYPE merged; + + keepgoing = FALSE; + + for_entry_list(qp) + if (qp->nuses > 0) + { + DEBUG(2, ("%s: attempting merge", _nc_first_name(qp->tterm.term_names))); + /* + * If any of the use entries we're looking for is + * incomplete, punt. We'll catch this entry on a + * subsequent pass. + */ + for (i = 0; i < qp->nuses; i++) + if (((ENTRY *)qp->uses[i].parent)->nuses) + { + DEBUG(2, ("%s: use entry %d unresolved", + _nc_first_name(qp->tterm.term_names), i)); + goto incomplete; + } + + /* + * 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. + */ + memcpy(&merged, &qp->tterm, sizeof(TERMTYPE)); + + /* + * Now merge in each use entry in the proper + * (reverse) order. + */ + for (; qp->nuses; qp->nuses--) + _nc_merge_entry(&merged, + &((ENTRY *)qp->uses[qp->nuses-1].parent)->tterm); + + /* + * Now merge in the original entry. + */ + _nc_merge_entry(&merged, &qp->tterm); + + /* + * Replace the original entry with the merged one. + */ + memcpy(&qp->tterm, &merged, sizeof(TERMTYPE)); + + /* + * We know every entry is resolvable because name resolution + * didn't bomb. So go back for another pass. + */ + /* FALLTHRU */ + incomplete: + keepgoing = TRUE; + } + } while + (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 (j = 0; j < BOOLCOUNT; j++) + if (qp->tterm.Booleans[j] == CANCELLED_BOOLEAN) + qp->tterm.Booleans[j] = FALSE; + for (j = 0; j < NUMCOUNT; j++) + if (qp->tterm.Numbers[j] == CANCELLED_NUMERIC) + qp->tterm.Numbers[j] = ABSENT_NUMERIC; + for (j = 0; j < STRCOUNT; j++) + if (qp->tterm.Strings[j] == CANCELLED_STRING) + qp->tterm.Strings[j] = ABSENT_STRING; + } + + /* + * We'd like to free entries read in off disk at this point, but can't. + * The merge_entry() code doesn't copy the strings in the use entries, + * it just aliases them. If this ever changes, do a + * free_entries(lastread) here. + */ + + DEBUG(2, ("RESOLUTION FINISHED")); + + _nc_curr_col = -1; + for_entry_list(qp) + { + _nc_curr_line = qp->startline; + _nc_set_type(_nc_first_name(qp->tterm.term_names)); + sanity_check(&qp->tterm); + } + + DEBUG(2, ("SANITY CHECK FINISHED")); + + return(TRUE); +} + +/* + * This bit of legerdemain turns all the terminfo variable names into + * references to locations in the arrays Booleans, Numbers, and Strings --- + * precisely what's needed. + */ + +#undef CUR +#define CUR tp-> + +/* + * Note that WANTED and PRESENT are not simple inverses! If a capability + * has been explicitly cancelled, it's not considered WANTED. + */ +#define WANTED(s) ((s) == ABSENT_STRING) +#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING)) + +#define ANDMISSING(p,q) \ + {if (PRESENT(p) && !PRESENT(q)) _nc_warning(#p " but no " #q);} + +#define PAIRED(p,q) \ + { \ + if (PRESENT(q) && !PRESENT(p)) \ + _nc_warning(#q " but no " #p); \ + if (PRESENT(p) && !PRESENT(q)) \ + _nc_warning(#p " but no " #q); \ + } + +static void sanity_check(TERMTYPE *tp) +{ +#ifdef __UNUSED__ /* this casts too wide a net */ + bool terminal_entry = !strchr(tp->term_names, '+'); +#endif + + if (!PRESENT(exit_attribute_mode)) + { +#ifdef __UNUSED__ /* this casts too wide a net */ + if (terminal_entry && + (PRESENT(set_attributes) + || PRESENT(enter_standout_mode) + || PRESENT(enter_underline_mode) + || PRESENT(enter_blink_mode) + || PRESENT(enter_bold_mode) + || PRESENT(enter_dim_mode) + || PRESENT(enter_secure_mode) + || PRESENT(enter_protected_mode) + || 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) + } + + /* listed in structure-member order of first argument */ +#ifdef __UNUSED__ + ANDMISSING(cursor_invisible, cursor_normal) + ANDMISSING(cursor_visible, cursor_normal) +#endif /* __UNUSED__ */ + 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) + PAIRED(enter_delete_mode, exit_delete_mode) + ANDMISSING(enter_dim_mode, exit_attribute_mode) + PAIRED(enter_insert_mode, exit_insert_mode) + ANDMISSING(enter_secure_mode, exit_attribute_mode) + ANDMISSING(enter_protected_mode, exit_attribute_mode) + ANDMISSING(enter_reverse_mode, exit_attribute_mode) + PAIRED(from_status_line, to_status_line) + PAIRED(meta_off, meta_on) + + PAIRED(prtr_on, prtr_off) + PAIRED(save_cursor, restore_cursor) + PAIRED(enter_xon_mode, exit_xon_mode) + PAIRED(enter_am_mode, exit_am_mode) + ANDMISSING(label_off, label_on) + PAIRED(display_clock, remove_clock) + ANDMISSING(set_color_pair, initialize_pair) + + /* Some checks that we should make, but don't want to confuse people + * with. Put those under the tic -v option so we can still get them. + */ + if (_nc_tracing) { + + /* + * From XSI & O'Reilly, we gather that sc/rc are required if csr is + * given, because the cursor position after the scrolling operation is + * performed is undefined. + */ + ANDMISSING(change_scroll_region, save_cursor) + ANDMISSING(change_scroll_region, restore_cursor) + + /* + * Some non-curses applications (e.g., jove) get confused if we have + * both ich/ich1 and smir/rmir. Let's be nice and warn about that, + * too, even though ncurses handles it. + */ + if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode)) + && (PRESENT(insert_character) || PRESENT(parm_ich))) { + _nc_warning("non-curses applications may be confused by ich/ich1 with smir/rmir"); + } + } +#undef PAIRED +#undef ANDMISSING +} diff --git a/lib/libcurses/tinfo/comp_scan.c b/lib/libcurses/tinfo/comp_scan.c new file mode 100644 index 00000000000..0c9012c835d --- /dev/null +++ b/lib/libcurses/tinfo/comp_scan.c @@ -0,0 +1,756 @@ +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +/* + * comp_scan.c --- Lexical scanner for terminfo compiler. + * + * _nc_reset_input() + * _nc_get_token() + * _nc_panic_mode() + * int _nc_syntax; + * int _nc_curr_line; + * long _nc_curr_file_pos; + * long _nc_comment_start; + * long _nc_comment_end; + */ + +#include <curses.priv.h> + +#include <ctype.h> +#include <tic.h> + +MODULE_ID("$From: comp_scan.c,v 1.34 1998/11/01 00:56:39 tom Exp $") + +/* + * Maximum length of string capability we'll accept before raising an error. + * Yes, there is a real capability in /etc/termcap this long, an "is". + */ +#define MAXCAPLEN 600 + +#define iswhite(ch) (ch == ' ' || ch == '\t') + +int _nc_syntax; /* termcap or terminfo? */ +long _nc_curr_file_pos; /* file offset of current line */ +long _nc_comment_start; /* start of comment range before name */ +long _nc_comment_end; /* end of comment range before name */ +long _nc_start_line; /* start line of current entry */ + +/***************************************************************************** + * + * Token-grabbing machinery + * + *****************************************************************************/ + +static bool first_column; /* See 'next_char()' below */ +static char separator; /* capability separator */ +static int pushtype; /* type of pushback token */ +static char pushname[MAX_NAME_SIZE+1]; + +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); + +/* Assume we may be looking at a termcap-style continuation */ +static inline int eat_escaped_newline(int ch) +{ + if (ch == '\\') + while ((ch = next_char()) == '\n' || iswhite(ch)) + continue; + return ch; +} + +/* + * int + * get_token() + * + * Scans the input for the next token, storing the specifics in the + * global structure 'curr_token' and returning one of the following: + * + * NAMES A line beginning in column 1. 'name' + * will be set to point to everything up to but + * not including the first separator on the line. + * BOOLEAN An entry consisting of a name followed by + * a separator. 'name' will be set to point to + * the name of the capability. + * NUMBER An entry of the form + * name#digits, + * 'name' will be set to point to the capability + * name and 'valnumber' to the number given. + * STRING An entry of the form + * name=characters, + * 'name' is set to the capability name and + * 'valstring' to the string of characters, with + * input translations done. + * CANCEL An entry of the form + * name@, + * 'name' is set to the capability name and + * 'valnumber' to -1. + * EOF The end of the file has been reached. + * + * A `separator' is either a comma or a semicolon, depending on whether + * we are in termcap or terminfo mode. + * + */ + +int _nc_get_token(void) +{ +static const char terminfo_punct[] = "@%&*!#"; +long number; +int type; +int ch; +char * numchk; +char numbuf[80]; +unsigned found; +static char buffer[MAX_ENTRY_SIZE]; +char *ptr; +int dot_flag = FALSE; +long token_start; + + if (pushtype != NO_PUSHBACK) + { + int retval = pushtype; + + _nc_set_type(pushname); + DEBUG(3, ("pushed-back token: `%s', class %d", + _nc_curr_token.tk_name, pushtype)); + + pushtype = NO_PUSHBACK; + pushname[0] = '\0'; + + /* currtok wasn't altered by _nc_push_token() */ + return(retval); + } + + if (end_of_stream()) + return(EOF); + +start_token: + token_start = stream_pos(); + while ((ch = next_char()) == '\n' || iswhite(ch)) + continue; + + ch = eat_escaped_newline(ch); + + if (ch == EOF) + type = EOF; + else { + /* if this is a termcap entry, skip a leading separator */ + if (separator == ':' && ch == ':') + ch = next_char(); + + if (ch == '.') { + dot_flag = TRUE; + DEBUG(8, ("dot-flag set")); + + while ((ch = next_char())=='.' || iswhite(ch)) + continue; + } + + if (ch == EOF) { + type = EOF; + goto end_of_token; + } + + /* have to make some punctuation chars legal for terminfo */ + if (!isalnum(ch) && !strchr(terminfo_punct, (char)ch)) { + _nc_warning("Illegal character (expected alphanumeric or %s) - %s", + terminfo_punct, _tracechar((chtype)ch)); + _nc_panic_mode(separator); + goto start_token; + } + + ptr = buffer; + *(ptr++) = ch; + + if (first_column) { + char *desc; + + _nc_comment_start = token_start; + _nc_comment_end = _nc_curr_file_pos; + _nc_start_line = _nc_curr_line; + + _nc_syntax = ERR; + while ((ch = next_char()) != '\n') + { + if (ch == EOF) + _nc_err_abort("premature EOF"); + else if (ch == ':' && last_char() != ',') + { + _nc_syntax = SYN_TERMCAP; + separator = ':'; + break; + } + else if (ch == ',') + { + _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 allows commas to + * be embedded in description fields of + * either syntax. + */ + /* FALLTHRU */ + } + else + ch = eat_escaped_newline(ch); + + *ptr++ = ch; + } + ptr[0] = '\0'; + if (_nc_syntax == ERR) + { + /* + * Grrr...what we ought to do here is barf, + * complaining that the entry is malformed. + * But because a couple of name fields in the + * 8.2 termcap file end with |\, we just have + * to assume it's termcap syntax. + */ + _nc_syntax = SYN_TERMCAP; + separator = ':'; + } + else if (_nc_syntax == SYN_TERMINFO) + { + /* throw away trailing /, *$/ */ + for (--ptr; iswhite(*ptr) || *ptr == ','; ptr--) + continue; + ptr[1] = '\0'; + } + + /* + * This is the soonest we have the terminal name + * fetched. Set up for following warning messages. + */ + ptr = strchr(buffer, '|'); + if (ptr == (char *)NULL) + ptr = buffer + strlen(buffer); + ch = *ptr; + *ptr = '\0'; + _nc_set_type(buffer); + *ptr = ch; + + /* + * Compute the boundary between the aliases and the + * description field for syntax-checking purposes. + */ + desc = strrchr(buffer, '|'); + if (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 (!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(*ptr)) + { + _nc_warning("whitespace in name or alias field"); + break; + } + else if (*ptr == '/') + { + _nc_warning("slashes aren't allowed in names or aliases"); + break; + } + else if (strchr("$[]!*?", *ptr)) + { + _nc_warning("dubious character `%c' in name or alias field", *ptr); + break; + } + } + + ptr = buffer; + + _nc_curr_token.tk_name = buffer; + type = NAMES; + } else { + while ((ch = next_char()) != EOF) { + if (!isalnum(ch)) { + if (_nc_syntax == SYN_TERMINFO) { + if (ch != '_') + break; + } else { /* allow ';' for "k;" */ + if (ch != ';') + break; + } + } + *(ptr++) = ch; + } + + *ptr++ = '\0'; + switch (ch) { + case ',': + case ':': + if (ch != separator) + _nc_err_abort("Separator inconsistent with syntax"); + _nc_curr_token.tk_name = buffer; + type = BOOLEAN; + break; + case '@': + if ((ch = next_char()) != separator) + _nc_warning("Missing separator after `%s', have %s", + buffer, _tracechar((chtype)ch)); + _nc_curr_token.tk_name = buffer; + type = CANCEL; + break; + + case '#': + found = 0; + while (isalnum(ch = next_char())) { + numbuf[found++] = ch; + if (found >= sizeof(numbuf)-1) + break; + } + numbuf[found] = '\0'; + number = strtol(numbuf, &numchk, 0); + if (numchk == numbuf) + _nc_warning("no value given for `%s'", buffer); + if ((*numchk != '\0') || (ch != separator)) + _nc_warning("Missing separator"); + _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_valnumber = number; + type = NUMBER; + break; + + case '=': + ch = _nc_trans_string(ptr); + if (ch != separator) + _nc_warning("Missing separator"); + _nc_curr_token.tk_name = buffer; + _nc_curr_token.tk_valstring = ptr; + type = STRING; + break; + + case EOF: + type = EOF; + break; + default: + /* just to get rid of the compiler warning */ + type = UNDEF; + _nc_warning("Illegal character - %s", + _tracechar((chtype)ch)); + } + } /* end else (first_column == FALSE) */ + } /* end else (ch != EOF) */ + +end_of_token: + +#ifdef TRACE + if (dot_flag == TRUE) + DEBUG(8, ("Commented out ")); + + if (_nc_tracing & TRACE_IEVENT) + { + fprintf(stderr, "Token: "); + switch (type) + { + case BOOLEAN: + fprintf(stderr, "Boolean; name='%s'\n", + _nc_curr_token.tk_name); + break; + + case NUMBER: + fprintf(stderr, "Number; name='%s', value=%d\n", + _nc_curr_token.tk_name, + _nc_curr_token.tk_valnumber); + break; + + case STRING: + fprintf(stderr, "String; name='%s', value=%s\n", + _nc_curr_token.tk_name, + _nc_visbuf(_nc_curr_token.tk_valstring)); + break; + + case CANCEL: + fprintf(stderr, "Cancel; name='%s'\n", + _nc_curr_token.tk_name); + break; + + case NAMES: + + fprintf(stderr, "Names; value='%s'\n", + _nc_curr_token.tk_name); + break; + + case EOF: + fprintf(stderr, "End of file\n"); + break; + + default: + _nc_warning("Bad token type"); + } + } +#endif + + if (dot_flag == TRUE) /* if commented out, use the next one */ + type = _nc_get_token(); + + DEBUG(3, ("token: `%s', class %d", _nc_curr_token.tk_name, type)); + + return(type); +} + +/* + * char + * trans_string(ptr) + * + * Reads characters using next_char() until encountering a separator, nl, + * or end-of-file. The returned value is the character which caused + * reading to stop. The following translations are done on the input: + * + * ^X goes to ctrl-X (i.e. X & 037) + * {\E,\n,\r,\b,\t,\f} go to + * {ESCAPE,newline,carriage-return,backspace,tab,formfeed} + * {\^,\\} go to {carat,backslash} + * \ddd (for ddd = up to three octal digits) goes to the character ddd + * + * \e == \E + * \0 == \200 + * + */ + +char +_nc_trans_string(char *ptr) +{ +int count = 0; +int number; +int i, c; +chtype ch, last_ch = '\0'; +bool ignored = FALSE; + + while ((ch = c = next_char()) != (chtype)separator && c != EOF) { + if ((_nc_syntax == SYN_TERMCAP) && c == '\n') + break; + if (ch == '^' && last_ch != '%') { + ch = c = next_char(); + if (c == EOF) + _nc_err_abort("Premature EOF"); + + if (! (is7bits(ch) && isprint(ch))) { + _nc_warning("Illegal ^ character - %s", + _tracechar((unsigned char)ch)); + } + if (ch == '?') { + *(ptr++) = '\177'; + } else { + if ((ch &= 037) == 0) + ch = 128; + *(ptr++) = (char)(ch); + } + } + else if (ch == '\\') { + ch = c = next_char(); + if (c == EOF) + _nc_err_abort("Premature EOF"); + + 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"); + + if (c < '0' || c > '7') { + if (isdigit(c)) { + _nc_warning("Non-octal digit `%c' in \\ sequence", c); + /* allow the digit; it'll do less harm */ + } else { + push_back((char)c); + break; + } + } + + number = number * 8 + c - '0'; + } + + if (number == 0) + number = 0200; + *(ptr++) = (char) number; + } else { + switch (c) { + case 'E': + case 'e': *(ptr++) = '\033'; break; + + case 'a': *(ptr++) = '\007'; break; + + case 'l': + case 'n': *(ptr++) = '\n'; break; + + case 'r': *(ptr++) = '\r'; break; + + case 'b': *(ptr++) = '\010'; break; + + case 's': *(ptr++) = ' '; break; + + case 'f': *(ptr++) = '\014'; break; + + case 't': *(ptr++) = '\t'; break; + + case '\\': *(ptr++) = '\\'; break; + + case '^': *(ptr++) = '^'; break; + + case ',': *(ptr++) = ','; break; + + case ':': *(ptr++) = ':'; break; + + case '\n': + continue; + + default: + _nc_warning("Illegal character %s in \\ sequence", + _tracechar((unsigned char)ch)); + *(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 */ + ignored = TRUE; + } else { + *(ptr++) = (char)ch; + } + + if (!ignored) { + last_ch = ch; + count ++; + } + ignored = FALSE; + + if (count > MAXCAPLEN) + _nc_warning("Very long string found. Missing separator?"); + } /* end while */ + + *ptr = '\0'; + + return(ch); +} + +/* + * _nc_push_token() + * + * Push a token of given type so that it will be reread by the next + * get_token() call. + */ + +void _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. + */ + pushtype = tokclass; + _nc_get_type(pushname); + + DEBUG(3, ("pushing token: `%s', class %d", + _nc_curr_token.tk_name, pushtype)); +} + +/* + * Panic mode error recovery - skip everything until a "ch" is found. + */ +void _nc_panic_mode(char ch) +{ + int c; + + for (;;) { + c = next_char(); + if (c == ch) + return; + if (c == EOF) + return; + } +} + +/***************************************************************************** + * + * 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. + */ + +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(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) +{ + if (!yyin) + { + 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 line[LEXBUFSIZ]; + size_t len; + + do { + _nc_curr_file_pos = ftell(yyin); + + if ((bufstart = fgets(line, LEXBUFSIZ, yyin)) != NULL) { + _nc_curr_line++; + _nc_curr_col = 0; + } + bufptr = bufstart; + } while + (bufstart != NULL && line[0] == '#'); + + if (bufstart == NULL) + return (EOF); + + 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') { + bufptr[len-2] = '\n'; + bufptr[len-1] = '\0'; + } + } + } + + 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); +} + +/* comp_scan.c ends here */ diff --git a/lib/libcurses/tinfo/doalloc.c b/lib/libcurses/tinfo/doalloc.c new file mode 100644 index 00000000000..a4d293e77ec --- /dev/null +++ b/lib/libcurses/tinfo/doalloc.c @@ -0,0 +1,60 @@ +/* $OpenBSD: doalloc.c,v 1.1 1999/01/18 19:10:15 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1998 * + ****************************************************************************/ + + +/* + * Wrapper for malloc/realloc. Standard implementations allow realloc with + * a null pointer, but older libraries may not (e.g., SunOS). + * + * Also if realloc fails, we discard the old memory to avoid leaks. + */ + +#include <curses.priv.h> + +MODULE_ID("$From: doalloc.c,v 1.2 1998/08/18 22:52:39 Hans-Joachim.Widmaier Exp $") + +void *_nc_doalloc(void *oldp, size_t amount) +{ + void *newp; + + if (oldp != 0) { + if ((newp = realloc(oldp, amount)) == 0) { + free(oldp); + errno = ENOMEM; /* just in case 'free' reset */ + } + } else { + newp = malloc(amount); + } + return newp; +} diff --git a/lib/libcurses/tinfo/getenv_num.c b/lib/libcurses/tinfo/getenv_num.c new file mode 100644 index 00000000000..21e48bdbafe --- /dev/null +++ b/lib/libcurses/tinfo/getenv_num.c @@ -0,0 +1,58 @@ +/* $OpenBSD: getenv_num.c,v 1.1 1999/01/18 19:10:15 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1998 * + ****************************************************************************/ + +/* + * getenv_num.c -- obtain a number from the environment + */ + +#include <curses.priv.h> + +MODULE_ID("$From: getenv_num.c,v 1.1 1998/09/19 21:30:23 tom Exp $") + +int +_nc_getenv_num(const char *name) +{ + char *dst = 0; + char *src = getenv(name); + long value; + + if ((src == 0) + || (value = strtol(src, &dst, 0)) < 0 + || (dst == src) + || (*dst != '\0') + || (int)value < value) + value = -1; + + return (int) value; +} diff --git a/lib/libcurses/tinfo/home_terminfo.c b/lib/libcurses/tinfo/home_terminfo.c new file mode 100644 index 00000000000..be4feaf927f --- /dev/null +++ b/lib/libcurses/tinfo/home_terminfo.c @@ -0,0 +1,64 @@ +/* $OpenBSD: home_terminfo.c,v 1.1 1999/01/18 19:10:15 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1998 * + ****************************************************************************/ + +/* + * home_terminfo.c -- return the $HOME/.terminfo string, expanded + */ + +#include <curses.priv.h> +#include <tic.h> + +MODULE_ID("$From: home_terminfo.c,v 1.1 1998/09/19 21:25:03 tom Exp $") + +#define my_length (strlen(home) + sizeof(PRIVATE_INFO)) + +/* ncurses extension...fall back on user's private directory */ + +char * +_nc_home_terminfo(void) +{ + char *home; + static char *temp = 0; + + if (temp == 0) { + if ((home = getenv("HOME")) != 0 + && my_length <= PATH_MAX) { + temp = malloc(my_length); + if (temp == 0) + _nc_err_abort("Out of memory"); + (void) sprintf(temp, PRIVATE_INFO, home); + } + } + return temp; +} diff --git a/lib/libcurses/tinfo/keys.list b/lib/libcurses/tinfo/keys.list new file mode 100644 index 00000000000..078c4747aa5 --- /dev/null +++ b/lib/libcurses/tinfo/keys.list @@ -0,0 +1,159 @@ +# $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 new file mode 100644 index 00000000000..ffbd078af01 --- /dev/null +++ b/lib/libcurses/tinfo/lib_acs.c @@ -0,0 +1,141 @@ +/* $OpenBSD: lib_acs.c,v 1.1 1999/01/18 19:10:16 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + + +#include <curses.priv.h> +#include <term.h> /* ena_acs, acs_chars */ + +MODULE_ID("$From: lib_acs.c,v 1.14 1999/01/02 22:37:49 tom Exp $") + +chtype acs_map[ACS_LEN]; + +void init_acs(void) +{ + T(("initializing ACS map")); + + /* + * 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 */ + /* 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 */ + + if (ena_acs != NULL) + { + TPUTS_TRACE("ena_acs"); + putp(ena_acs); + } + +#define ALTCHAR(c) ((chtype)(((unsigned char)(c)) | A_ALTCHARSET)) + + 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; + } + } +#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) { + 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) { + show[m++] = (char)n; + show[m++] = TextOf(acs_map[n]); + } + } + show[m] = 0; + _tracef("%s acs_chars %s", + (acs_chars == NULL) + ? "NULL" + : (strcmp(acs_chars, show) + ? "DIFF" + : "SAME"), + _nc_visbuf(show)); + } +#endif /* TRACE */ +} diff --git a/lib/libcurses/tinfo/lib_baudrate.c b/lib/libcurses/tinfo/lib_baudrate.c new file mode 100644 index 00000000000..97b5eb7c5be --- /dev/null +++ b/lib/libcurses/tinfo/lib_baudrate.c @@ -0,0 +1,171 @@ +/* $OpenBSD: lib_baudrate.c,v 1.1 1999/01/18 19:10:16 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * lib_baudrate.c + * + */ + +#include <curses.priv.h> +#include <term.h> /* cur_term, pad_char */ +#include <termcap.h> /* ospeed */ + +MODULE_ID("$From: lib_baudrate.c,v 1.14 1999/01/03 01:31:45 tom Exp $") + +/* + * int + * baudrate() + * + * Returns the current terminal's baud rate. + * + */ + +struct speed { + speed_t s; + int sp; +}; + +static struct speed const speeds[] = { + {B0, 0}, + {B50, 50}, + {B75, 75}, + {B110, 110}, + {B134, 134}, + {B150, 150}, + {B200, 200}, + {B300, 300}, + {B600, 600}, + {B1200, 1200}, + {B1800, 1800}, + {B2400, 2400}, + {B4800, 4800}, + {B9600, 9600}, +#ifdef B19200 + {B19200, 19200}, +#else +#ifdef EXTA + {EXTA, 19200}, +#endif +#endif +#ifdef B38400 + {B38400, 38400}, +#else +#ifdef EXTB + {EXTB, 38400}, +#endif +#endif +#ifdef B57600 + {B57600, 57600}, +#endif +#ifdef B115200 + {B115200, 115200}, +#endif +#ifdef B230400 + {B230400, 230400}, +#endif +#ifdef B460800 + {B460800, 460800}, +#endif +}; + +int _nc_baudrate(int OSpeed) +{ + int result = ERR; + unsigned i; + + if (OSpeed >= 0) { + for (i = 0; i < SIZEOF(speeds); i++) { + if (speeds[i].s == (speed_t)OSpeed) { + result = speeds[i].sp; + break; + } + } + } + return (result); +} + + +int _nc_ospeed(int BaudRate) +{ + speed_t result = 1; + unsigned i; + + if (BaudRate >= 0) { + for (i = 0; i < SIZEOF(speeds); i++) { + if (speeds[i].sp == BaudRate) { + result = speeds[i].s; + break; + } + } + } + return (result); +} + +int +baudrate(void) +{ +int result; + + T((T_CALLED("baudrate()"))); + + /* + * In debugging, allow the environment symbol to override when we're + * redirecting to a file, so we can construct repeatable test-cases + * that take into account costs that depend on baudrate. + */ +#ifdef TRACE + if (SP && !isatty(fileno(SP->_ofp)) + && getenv("BAUDRATE") != 0) { + int ret; + if ((ret = _nc_getenv_num("BAUDRATE")) <= 0) + ret = 9600; + ospeed = _nc_ospeed(ret); + returnCode(ret); + } + else +#endif + +#ifdef TERMIOS + ospeed = cfgetospeed(&cur_term->Nttyb); +#else + ospeed = cur_term->Nttyb.sg_ospeed; +#endif + result = _nc_baudrate(ospeed); + if (cur_term != 0) + cur_term->_baudrate = result; + + returnCode(result); +} diff --git a/lib/libcurses/tinfo/lib_cur_term.c b/lib/libcurses/tinfo/lib_cur_term.c new file mode 100644 index 00000000000..0429da48316 --- /dev/null +++ b/lib/libcurses/tinfo/lib_cur_term.c @@ -0,0 +1,73 @@ +/* $OpenBSD: lib_cur_term.c,v 1.1 1999/01/18 19:10:17 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1997 * + ****************************************************************************/ +/* + * Module that "owns" the 'cur_term' variable: + * + * TERMINAL *set_curterm(TERMINAL *) + * int del_curterm(TERMINAL *) + */ + +#include <curses.priv.h> +#include <term.h> /* TTY, cur_term */ +#include <termcap.h> /* ospeed */ + +MODULE_ID("$From: lib_cur_term.c,v 1.6 1999/01/10 00:48:44 tom Exp $") + +TERMINAL *cur_term; + +TERMINAL *set_curterm(TERMINAL *term) +{ + TERMINAL *oldterm = cur_term; + + if ((cur_term = term) != 0) { + ospeed = _nc_ospeed(cur_term->_baudrate); + PC = (pad_char != NULL) ? pad_char[0] : 0; + } + return oldterm; +} + +int del_curterm(TERMINAL *term) +{ + T((T_CALLED("del_curterm(%p)"), term)); + + if (term != 0) { + FreeIfNeeded(term->type.str_table); + FreeIfNeeded(term->type.term_names); + free(term); + if (term == cur_term) + cur_term = 0; + returnCode(OK); + } + returnCode(ERR); +} diff --git a/lib/libcurses/tinfo/lib_data.c b/lib/libcurses/tinfo/lib_data.c new file mode 100644 index 00000000000..9fad1c97b3e --- /dev/null +++ b/lib/libcurses/tinfo/lib_data.c @@ -0,0 +1,86 @@ +/* $OpenBSD: lib_data.c,v 1.1 1999/01/18 19:10:17 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +/* +** lib_data.c +** +** Common data that may/may not be allocated, but is referenced globally +** +*/ + +#include <curses.priv.h> + +MODULE_ID("$From: lib_data.c,v 1.13 1998/02/11 12:14:00 tom Exp $") + +/* + * OS/2's native linker complains if we don't initialize public data when + * constructing a dll (reported by J.J.G.Ripoll). + */ +WINDOW *stdscr = 0; +WINDOW *curscr = 0; +WINDOW *newscr = 0; + +SCREEN *_nc_screen_chain = 0; + +/* + * The variable 'SP' will be defined as a function on systems that cannot link + * data-only modules, since it is used in a lot of places within ncurses and we + * cannot guarantee that any application will use any particular function. We + * put the WINDOW variables in this module, because it appears that any + * application that uses them will also use 'SP'. + * + * This module intentionally does not reference other ncurses modules, to avoid + * module coupling that increases the size of the executable. + */ +#if BROKEN_LINKER +static SCREEN *my_screen; + +SCREEN *_nc_screen(void) +{ + return my_screen; +} + +int _nc_alloc_screen(void) +{ + return ((my_screen = typeCalloc(SCREEN, 1)) != 0); +} + +void _nc_set_screen(SCREEN *sp) +{ + my_screen = sp; +} +#else +SCREEN *SP; +#endif diff --git a/lib/libcurses/tinfo/lib_has_cap.c b/lib/libcurses/tinfo/lib_has_cap.c new file mode 100644 index 00000000000..de5ebb5c133 --- /dev/null +++ b/lib/libcurses/tinfo/lib_has_cap.c @@ -0,0 +1,65 @@ +/* $OpenBSD: lib_has_cap.c,v 1.1 1999/01/18 19:10:17 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* +** lib_has_cap.c +** +** The routines to query terminal capabilities +** +*/ + +#include <curses.priv.h> + +#include <term.h> + +MODULE_ID("$From: lib_has_cap.c,v 1.1 1998/10/23 15:32:21 tom Exp $") + +bool has_ic(void) +{ + T((T_CALLED("has_ic()"))); + returnCode(cur_term && + (insert_character || parm_ich + || (enter_insert_mode && exit_insert_mode)) + && (delete_character || parm_dch)); +} + +bool has_il(void) +{ + T((T_CALLED("has_il()"))); + returnCode(cur_term + && (insert_line || parm_insert_line) + && (delete_line || parm_delete_line)); +} diff --git a/lib/libcurses/tinfo/lib_kernel.c b/lib/libcurses/tinfo/lib_kernel.c new file mode 100644 index 00000000000..16cb06afe9d --- /dev/null +++ b/lib/libcurses/tinfo/lib_kernel.c @@ -0,0 +1,132 @@ +/* $OpenBSD: lib_kernel.c,v 1.1 1999/01/18 19:10:17 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * lib_kernel.c + * + * Misc. low-level routines: + * erasechar() + * killchar() + * flushinp() + * + * The baudrate() and delay_output() functions could logically live here, + * but are in other modules to reduce the static-link size of programs + * that use only these facilities. + */ + +#include <curses.priv.h> +#include <term.h> /* cur_term */ + +MODULE_ID("$From: lib_kernel.c,v 1.19 1998/12/20 00:18:45 tom Exp $") + +/* + * erasechar() + * + * Return erase character as given in cur_term->Ottyb. + * + */ + +char +erasechar(void) +{ + T((T_CALLED("erasechar()"))); + + if (cur_term != 0) { +#ifdef TERMIOS + returnCode(cur_term->Ottyb.c_cc[VERASE]); +#else + returnCode(cur_term->Ottyb.sg_erase); +#endif + } + returnCode(ERR); +} + + + +/* + * killchar() + * + * Return kill character as given in cur_term->Ottyb. + * + */ + +char +killchar(void) +{ + T((T_CALLED("killchar()"))); + + if (cur_term != 0) { +#ifdef TERMIOS + returnCode(cur_term->Ottyb.c_cc[VKILL]); +#else + returnCode(cur_term->Ottyb.sg_kill); +#endif + } + returnCode(ERR); +} + + + +/* + * flushinp() + * + * Flush any input on cur_term->Filedes + * + */ + +int flushinp(void) +{ + T((T_CALLED("flushinp()"))); + + if (cur_term != 0) { +#ifdef TERMIOS + tcflush(cur_term->Filedes, TCIFLUSH); +#else + errno = 0; + do { + ioctl(cur_term->Filedes, TIOCFLUSH, 0); + } while + (errno == EINTR); +#endif + if (SP) { + SP->_fifohead = -1; + SP->_fifotail = 0; + SP->_fifopeek = 0; + } + returnCode(OK); + } + returnCode(ERR); +} diff --git a/lib/libcurses/tinfo/lib_longname.c b/lib/libcurses/tinfo/lib_longname.c new file mode 100644 index 00000000000..558453a69bb --- /dev/null +++ b/lib/libcurses/tinfo/lib_longname.c @@ -0,0 +1,60 @@ +/* $OpenBSD: lib_longname.c,v 1.1 1999/01/18 19:10:18 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* +** lib_longname.c +** +** The routine longname(). +** +*/ + +#include <curses.priv.h> + +MODULE_ID("$From: lib_longname.c,v 1.7 1999/01/03 01:47:45 tom Exp $") + +char * +longname(void) +{ +char *ptr; + + T((T_CALLED("longname()"))); + + for (ptr = ttytype + strlen(ttytype); ptr > ttytype; ptr--) + if (*ptr == '|') + returnPtr(ptr + 1); + + returnPtr(ttytype); +} diff --git a/lib/libcurses/tinfo/lib_napms.c b/lib/libcurses/tinfo/lib_napms.c new file mode 100644 index 00000000000..d5dd07be396 --- /dev/null +++ b/lib/libcurses/tinfo/lib_napms.c @@ -0,0 +1,90 @@ +/* $OpenBSD: lib_napms.c,v 1.1 1999/01/18 19:10:18 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * lib_napms.c + * + * The routine napms. + * + */ + +#include <curses.priv.h> + +#if USE_FUNC_POLL +#include <stropts.h> +#include <poll.h> +#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.4 1998/02/13 10:24:54 jbuhler Exp $") + +int napms(int ms) +{ + T((T_CALLED("napms(%d)"), ms)); + +#if HAVE_NANOSLEEP + { + struct timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&ts, NULL); + } +#elif HAVE_USLEEP + usleep(1000*(unsigned)ms); +#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); + } +#endif + returnCode(OK); +} diff --git a/lib/libcurses/tinfo/lib_options.c b/lib/libcurses/tinfo/lib_options.c new file mode 100644 index 00000000000..3ab600ab653 --- /dev/null +++ b/lib/libcurses/tinfo/lib_options.c @@ -0,0 +1,291 @@ +/* $OpenBSD: lib_options.c,v 1.1 1999/01/18 19:10:18 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* +** lib_options.c +** +** The routines to handle option setting. +** +*/ + +#include <curses.priv.h> + +#include <term.h> /* keypad_xmit, keypad_local, meta_on, meta_off */ + /* cursor_visible,cursor_normal,cursor_invisible */ + +MODULE_ID("$From: lib_options.c,v 1.32 1998/12/19 23:09:50 tom Exp $") + +int idlok(WINDOW *win, bool flag) +{ + T((T_CALLED("idlok(%p,%d)"), win, flag)); + + if (win) { + _nc_idlok = win->_idlok = flag && (has_il() || change_scroll_region); + returnCode(OK); + } + else + returnCode(ERR); +} + + +void idcok(WINDOW *win, bool flag) +{ + T((T_CALLED("idcok(%p,%d)"), win, flag)); + + if (win) + _nc_idcok = win->_idcok = flag && has_ic(); + + returnVoid; +} + +int halfdelay(int t) +{ + T((T_CALLED("halfdelay(%d)"), t)); + + if (t < 1 || t > 255) + returnCode(ERR); + + cbreak(); + SP->_cbreak = t+1; + returnCode(OK); +} + +int nodelay(WINDOW *win, bool flag) +{ + T((T_CALLED("nodelay(%p,%d)"), win, flag)); + + if (win) { + if (flag == TRUE) + win->_delay = 0; + else win->_delay = -1; + returnCode(OK); + } + else + returnCode(ERR); +} + +int notimeout(WINDOW *win, bool f) +{ + T((T_CALLED("notimout(%p,%d)"), win, f)); + + if (win) { + win->_notimeout = f; + returnCode(OK); + } + else + returnCode(ERR); +} + +void wtimeout(WINDOW *win, int delay) +{ + T((T_CALLED("wtimeout(%p,%d)"), win, delay)); + + if (win) { + win->_delay = delay; + } +} + +int keypad(WINDOW *win, bool flag) +{ + T((T_CALLED("keypad(%p,%d)"), win, flag)); + + if (win) { + win->_use_keypad = flag; + returnCode(_nc_keypad(flag)); + } + else + returnCode(ERR); +} + + +int meta(WINDOW *win GCC_UNUSED, bool flag) +{ + /* 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); +} + +/* curs_set() moved here to narrow the kernel interface */ + +int curs_set(int vis) +{ +int cursor = SP->_cursor; + + 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; + (void) fflush(SP->_ofp); + + returnCode(cursor==-1 ? 1 : cursor); +} + +int typeahead(int fd) +{ + T((T_CALLED("typeahead(%d)"), fd)); + SP->_checkfd = fd; + returnCode(OK); +} + +/* +** has_key() +** +** Return TRUE if the current terminal has the given key +** +*/ + +#ifdef NCURSES_EXT_FUNCS +static int has_key_internal(int keycode, struct tries *tp) +{ + if (tp == 0) + return(FALSE); + else if (tp->value == keycode) + return(TRUE); + else + return(has_key_internal(keycode, tp->child) + || has_key_internal(keycode, tp->sibling)); +} + +int has_key(int keycode) +{ + T((T_CALLED("has_key(%d)"), keycode)); + returnCode(has_key_internal(keycode, SP->_keytry)); +} +#endif /* NCURSES_EXT_FUNCS */ + +/* +** init_keytry() +** +** Construct the try for the current terminal's keypad keys. +** +*/ + +static void init_keytry(void) +{ +/* LINT_PREPRO +#if 0*/ +#include <keys.tries> +/* LINT_PREPRO +#endif*/ + size_t n; + + /* 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; n < SIZEOF(table); n++) + if (table[n].offset < STRCOUNT) + _nc_add_to_try(&(SP->_keytry), + CUR Strings[table[n].offset], + table[n].code); +} + +/* Turn the keypad on/off + * + * Note: we flush the output because changing this mode causes some terminals + * to emit different escape sequences for cursor and keypad keys. If we don't + * flush, then the next wgetch may get the escape sequence that corresponds to + * the terminal state _before_ switching modes. + */ +int _nc_keypad(bool flag) +{ + if (flag && keypad_xmit) + { + TPUTS_TRACE("keypad_xmit"); + putp(keypad_xmit); + (void) fflush(SP->_ofp); + } + else if (! flag && keypad_local) + { + TPUTS_TRACE("keypad_local"); + putp(keypad_local); + (void) fflush(SP->_ofp); + } + + if (!SP->_tried) { + init_keytry(); + SP->_tried = TRUE; + } + return(OK); +} diff --git a/lib/libcurses/tinfo/lib_print.c b/lib/libcurses/tinfo/lib_print.c new file mode 100644 index 00000000000..2d872a665ed --- /dev/null +++ b/lib/libcurses/tinfo/lib_print.c @@ -0,0 +1,98 @@ +/* $OpenBSD: lib_print.c,v 1.1 1999/01/18 19:10:19 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +#include <curses.priv.h> + +#include <term.h> + +MODULE_ID("$From: lib_print.c,v 1.10 1998/10/13 14:47:53 Alexander.V.Lukyanov Exp $") + +int mcprint(char *data, int len) +/* ship binary character data to the printer via mc4/mc5/mc5p */ +{ + char *mybuf, *switchon; + size_t onsize, offsize, res; + + errno = 0; + if (!cur_term || (!prtr_non && (!prtr_on || !prtr_off))) + { + errno = ENODEV; + return(ERR); + } + + if (prtr_non) + { + switchon = tparm(prtr_non, len); + onsize = strlen(switchon); + offsize = 0; + } + else + { + switchon = prtr_on; + onsize = strlen(prtr_on); + offsize = strlen(prtr_off); + } + + if ((mybuf = malloc(onsize + len + offsize + 1)) == (char *)NULL) + { + errno = ENOMEM; + return(ERR); + } + + (void) strcpy(mybuf, switchon); + memcpy(mybuf + onsize, data, len); + if (offsize) + (void) strcpy(mybuf + onsize + len, prtr_off); + + /* + * We're relying on the atomicity of UNIX writes here. The + * danger is that output from a refresh() might get interspersed + * with the printer data after the write call returns but before the + * data has actually been shipped to the terminal. If the write(2) + * operation is truly atomic we're protected from this. + */ + res = write(cur_term->Filedes, mybuf, onsize + len + offsize); + + /* + * By giving up our scheduler slot here we increase the odds that the + * kernel will ship the contiguous clist items from the last write + * immediately. + */ + (void) sleep(0); + + free(mybuf); + return(res); +} diff --git a/lib/libcurses/tinfo/lib_raw.c b/lib/libcurses/tinfo/lib_raw.c new file mode 100644 index 00000000000..a9280a57edb --- /dev/null +++ b/lib/libcurses/tinfo/lib_raw.c @@ -0,0 +1,235 @@ +/* $OpenBSD: lib_raw.c,v 1.1 1999/01/18 19:10:19 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * raw.c + * + * Routines: + * raw() + * cbreak() + * noraw() + * nocbreak() + * qiflush() + * noqiflush() + * intrflush() + * + */ + +#include <curses.priv.h> +#include <term.h> /* cur_term */ + +MODULE_ID("$From: lib_raw.c,v 1.2 1998/12/20 00:42:58 tom Exp $") + +#if defined(SVR4_TERMIO) && !defined(_POSIX_SOURCE) +#define _POSIX_SOURCE +#endif + +#if HAVE_SYS_TERMIO_H +#include <sys/termio.h> /* needed for ISC */ +#endif + +#ifdef __EMX__ +#include <io.h> +#include <fcntl.h> +#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()) +#else +#define BEFORE(s) +#define AFTER(s) +#endif /* TRACE */ + +int raw(void) +{ + T((T_CALLED("raw()"))); + if (SP != 0 && cur_term != 0) { + + SP->_raw = TRUE; + SP->_cbreak = TRUE; + +#ifdef __EMX__ + setmode(SP->_ifd, O_BINARY); +#endif + +#ifdef TERMIOS + BEFORE("raw"); + cur_term->Nttyb.c_lflag &= ~(ICANON|ISIG); + cur_term->Nttyb.c_iflag &= ~(COOKED_INPUT); + cur_term->Nttyb.c_cc[VMIN] = 1; + cur_term->Nttyb.c_cc[VTIME] = 0; + AFTER("raw"); +#else + cur_term->Nttyb.sg_flags |= RAW; +#endif + returnCode(_nc_set_tty_mode(&cur_term->Nttyb)); + } + returnCode(ERR); +} + +int cbreak(void) +{ + T((T_CALLED("cbreak()"))); + + SP->_cbreak = TRUE; + +#ifdef __EMX__ + setmode(SP->_ifd, O_BINARY); +#endif + +#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"); +#else + cur_term->Nttyb.sg_flags |= CBREAK; +#endif + returnCode(_nc_set_tty_mode( &cur_term->Nttyb)); +} + +void qiflush(void) +{ + T((T_CALLED("qiflush()"))); + + /* + * Note: this implementation may be wrong. See the comment under + * intrflush(). + */ + +#ifdef TERMIOS + BEFORE("qiflush"); + cur_term->Nttyb.c_lflag &= ~(NOFLSH); + AFTER("qiflush"); + (void)_nc_set_tty_mode( &cur_term->Nttyb); + returnVoid; +#endif +} + + +int noraw(void) +{ + T((T_CALLED("noraw()"))); + + SP->_raw = FALSE; + SP->_cbreak = FALSE; + +#ifdef __EMX__ + setmode(SP->_ifd, O_TEXT); +#endif + +#ifdef TERMIOS + BEFORE("noraw"); + cur_term->Nttyb.c_lflag |= ISIG|ICANON; + cur_term->Nttyb.c_iflag |= COOKED_INPUT; + AFTER("noraw"); +#else + cur_term->Nttyb.sg_flags &= ~(RAW|CBREAK); +#endif + returnCode(_nc_set_tty_mode( &cur_term->Nttyb)); +} + + +int nocbreak(void) +{ + T((T_CALLED("nocbreak()"))); + + SP->_cbreak = FALSE; + +#ifdef __EMX__ + setmode(SP->_ifd, O_TEXT); +#endif + +#ifdef TERMIOS + BEFORE("nocbreak"); + cur_term->Nttyb.c_lflag |= ICANON; + cur_term->Nttyb.c_iflag |= ICRNL; + AFTER("nocbreak"); +#else + cur_term->Nttyb.sg_flags &= ~CBREAK; +#endif + returnCode(_nc_set_tty_mode( &cur_term->Nttyb)); +} + +void noqiflush(void) +{ + T((T_CALLED("noqiflush()"))); + + /* + * Note: this implementation may be wrong. See the comment under + * intrflush(). + */ + +#ifdef TERMIOS + BEFORE("noqiflush"); + cur_term->Nttyb.c_lflag |= NOFLSH; + AFTER("noqiflush"); + (void)_nc_set_tty_mode( &cur_term->Nttyb); + returnVoid; +#endif +} + +int intrflush(WINDOW *win GCC_UNUSED, bool flag) +{ + 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. + */ + +#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)); +#else + returnCode(ERR); +#endif +} diff --git a/lib/libcurses/tinfo/lib_setup.c b/lib/libcurses/tinfo/lib_setup.c new file mode 100644 index 00000000000..289309d4f65 --- /dev/null +++ b/lib/libcurses/tinfo/lib_setup.c @@ -0,0 +1,405 @@ +/* $OpenBSD: lib_setup.c,v 1.1 1999/01/18 19:10:19 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * Terminal setup routines common to termcap and terminfo: + * + * use_env(bool) + * setupterm(char *, int, int *) + */ + +#include <curses.priv.h> +#include <tic.h> /* for MAX_NAME_SIZE */ + +#if defined(SVR4_TERMIO) && !defined(_POSIX_SOURCE) +#define _POSIX_SOURCE +#endif + +#include <term.h> /* lines, columns, cur_term */ + +MODULE_ID("$From: lib_setup.c,v 1.48 1999/01/02 23:11:56 tom Exp $") + +/**************************************************************************** + * + * Terminal size computation + * + ****************************************************************************/ + +#if HAVE_SIZECHANGE +# if !defined(sun) || !TERMIOS +# if HAVE_SYS_IOCTL_H +# include <sys/ioctl.h> +# endif +# endif +#endif + +#if NEED_PTEM_H + /* On SCO, they neglected to define struct winsize in termios.h -- it's only + * in termio.h and ptem.h (the former conflicts with other definitions). + */ +# include <sys/stream.h> +# include <sys/ptem.h> +#endif + +/* + * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, + * Solaris, IRIX) define TIOCGWINSZ and struct winsize. + */ +#ifdef TIOCGSIZE +# define IOCTL_WINSIZE TIOCGSIZE +# define STRUCT_WINSIZE struct ttysize +# define WINSIZE_ROWS(n) (int)n.ts_lines +# define WINSIZE_COLS(n) (int)n.ts_cols +#else +# ifdef TIOCGWINSZ +# define IOCTL_WINSIZE TIOCGWINSZ +# define STRUCT_WINSIZE struct winsize +# define WINSIZE_ROWS(n) (int)n.ws_row +# define WINSIZE_COLS(n) (int)n.ws_col +# endif +#endif + +static int _use_env = TRUE; + +static void do_prototype(void); + +void use_env(bool f) +{ + _use_env = f; +} + +int LINES, COLS, TABSIZE; + +static void _nc_get_screensize(int *linep, int *colp) +/* Obtain lines/columns values from the environment and/or terminfo entry */ +{ + /* figure out the size of the screen */ + T(("screen size: terminfo lines = %d columns = %d", lines, columns)); + + if (!_use_env) + { + *linep = (int)lines; + *colp = (int)columns; + } + else /* usually want to query LINES and COLUMNS from environment */ + { + int value; + + *linep = *colp = 0; + + /* first, look for environment variables */ + if ((value = _nc_getenv_num("LINES")) > 0) { + *linep = value; + } + if ((value = _nc_getenv_num("COLUMNS")) > 0) { + *colp = value; + } + T(("screen size: environment LINES = %d COLUMNS = %d",*linep,*colp)); + +#ifdef __EMX__ + if (*linep <= 0 || *colp <= 0) + { + int screendata[2]; + _scrsize(screendata); + *colp = screendata[0]; + *linep = screendata[1]; + T(("EMX screen size: environment LINES = %d COLUMNS = %d",*linep,*colp)); + } +#endif +#if HAVE_SIZECHANGE + /* if that didn't work, maybe we can try asking the OS */ + if (*linep <= 0 || *colp <= 0) + { + if (isatty(cur_term->Filedes)) + { + STRUCT_WINSIZE size; + + errno = 0; + do { + if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) < 0 + && errno != EINTR) + goto failure; + } while + (errno == EINTR); + + /* + * Solaris lets users override either dimension with an + * environment variable. + */ + if (*linep <= 0) + *linep = WINSIZE_ROWS(size); + if (*colp <= 0) + *colp = WINSIZE_COLS(size); + } + /* FALLTHRU */ + failure:; + } +#endif /* HAVE_SIZECHANGE */ + + /* if we can't get dynamic info about the size, use static */ + if (*linep <= 0 || *colp <= 0) + if (lines > 0 && columns > 0) + { + *linep = (int)lines; + *colp = (int)columns; + } + + /* the ultimate fallback, assume fixed 24x80 size */ + if (*linep <= 0 || *colp <= 0) + { + *linep = 24; + *colp = 80; + } + + /* + * Put the derived values back in the screen-size caps, so + * tigetnum() and tgetnum() will do the right thing. + */ + lines = (short)(*linep); + columns = (short)(*colp); + } + + T(("screen size is %dx%d", *linep, *colp)); + + if (init_tabs != -1) + TABSIZE = (int)init_tabs; + else + TABSIZE = 8; + T(("TABSIZE = %d", TABSIZE)); + +} + +#if USE_SIZECHANGE +void _nc_update_screensize(void) +{ + int my_lines, my_cols; + + _nc_get_screensize(&my_lines, &my_cols); + if (SP != 0 && SP->_resize != 0) + SP->_resize(my_lines, my_cols); +} +#endif + +/**************************************************************************** + * + * Terminal setup + * + ****************************************************************************/ + +#define ret_error(code, fmt, arg) if (errret) {\ + *errret = code;\ + returnCode(ERR);\ + } else {\ + fprintf(stderr, fmt, arg);\ + exit(EXIT_FAILURE);\ + } + +#define ret_error0(code, msg) if (errret) {\ + *errret = code;\ + returnCode(ERR);\ + } else {\ + fprintf(stderr, msg);\ + exit(EXIT_FAILURE);\ + } + +#if USE_DATABASE +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 */ +{ + char filename[PATH_MAX]; + int status = 0; + int _nc_read_bsd_terminfo_entry(const char *, TERMTYPE *); /* XXX */ + +#ifdef __OpenBSD__ + status = _nc_read_bsd_terminfo_entry(tn, tp); +#endif /* __OpenBSD__ */ + + if (status != 1 && (status = _nc_read_entry(tn, filename, tp)) != 1) { + +#ifndef 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 */ + + } + + /* + * If we have an entry, force all of the cancelled strings to null + * pointers so we don't have to test them in the rest of the library. + * (The terminfo compiler bypasses this logic, since it must know if + * a string is cancelled, for merging entries). + */ + if (status == 1) { + unsigned n; + for (n = 0; n < BOOLCOUNT; n++) + if (!VALID_BOOLEAN(tp->Booleans[n])) + tp->Booleans[n] = FALSE; + for (n = 0; n < STRCOUNT; n++) + if (tp->Strings[n] == CANCELLED_STRING) + tp->Strings[n] = ABSENT_STRING; + } + return(status); +} +#endif + +char ttytype[NAMESIZE]; + +/* + * setupterm(termname, Filedes, errret) + * + * Find and read the appropriate object file for the terminal + * Make cur_term point to the structure. + * + */ + +int setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) +{ +struct term *term_ptr; +int status; + + T((T_CALLED("setupterm(\"%s\",%d,%p)"), tname, Filedes, errret)); + + if (tname == 0) { + tname = getenv("TERM"); + if (tname == 0 || *tname == '\0') { + ret_error0(-1, "TERM environment variable not set.\n"); + } + } + if (strlen(tname) > MAX_NAME_SIZE) { + ret_error(-1, "TERM environment must be <= %d characters.\n", + MAX_NAME_SIZE); + } + + T(("your terminal name is %s", tname)); + + term_ptr = typeCalloc(TERMINAL, 1); + + 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); +#else + status = 0; +#endif + + /* try fallback list if entry on disk */ + if (status != 1) + { + const TERMTYPE *fallback = _nc_fallback(tname); + + if (fallback) + { + memcpy(&term_ptr->type, fallback, sizeof(TERMTYPE)); + status = 1; + } + } + + if (status == -1) + { + ret_error0(-1, "terminals database is inaccessible\n"); + } + else if (status == 0) + { + ret_error(0, "'%s': unknown terminal type.\n", tname); + } + + set_curterm(term_ptr); + + if (command_character && getenv("CC")) + do_prototype(); + + strlcpy(ttytype, cur_term->type.term_names, NAMESIZE); + + /* + * 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; + cur_term->Filedes = Filedes; + + _nc_get_screensize(&LINES, &COLS); + + if (errret) + *errret = 1; + + T((T_CREATE("screen %s %dx%d"), tname, LINES, COLS)); + + if (generic_type) { + ret_error(0, "'%s': I need something more specific.\n", tname); + } + if (hard_copy) { + ret_error(1, "'%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) +{ +int i, j; +char CC; +char proto; +char *tmp; + + tmp = getenv("CC"); + CC = *tmp; + proto = *command_character; + + for (i=0; i < STRCOUNT; i++) { + j = 0; + while (cur_term->type.Strings[i][j]) { + if (cur_term->type.Strings[i][j] == proto) + cur_term->type.Strings[i][j] = CC; + j++; + } + } +} diff --git a/lib/libcurses/tinfo/lib_termcap.c b/lib/libcurses/tinfo/lib_termcap.c new file mode 100644 index 00000000000..e50b4a622da --- /dev/null +++ b/lib/libcurses/tinfo/lib_termcap.c @@ -0,0 +1,194 @@ +/* $OpenBSD: lib_termcap.c,v 1.1 1999/01/18 19:10:19 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +#include <curses.priv.h> + +#include <termcap.h> +#include <tic.h> + +#define __INTERNAL_CAPS_VISIBLE +#include <term.h> + +MODULE_ID("$From: lib_termcap.c,v 1.25 1999/01/10 00:48:11 tom Exp $") + +/* + some of the code in here was contributed by: + Magnus Bengtsson, d6mbeng@dtek.chalmers.se +*/ + +char *UP; +char *BC; + +/*************************************************************************** + * + * tgetent(bufp, term) + * + * In termcap, this function reads in the entry for terminal `term' into the + * buffer pointed to by bufp. It must be called before any of the functions + * below are called. + * In this terminfo emulation, tgetent() simply calls setupterm() (which + * does a bit more than tgetent() in termcap does), and returns its return + * value (1 if successful, 0 if no terminal with the given name could be + * found, or -1 if no terminal descriptions have been installed on the + * system). The bufp argument is ignored. + * + ***************************************************************************/ + +int tgetent(char *bufp GCC_UNUSED, const char *name) +{ +int errcode; + + T((T_CALLED("tgetent()"))); + + setupterm((NCURSES_CONST char *)name, STDOUT_FILENO, &errcode); + + if (errcode == 1) { + + if (cursor_left) + if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) + backspace_if_not_bs = cursor_left; + + /* we're required to export these */ + if (pad_char != NULL) + PC = pad_char[0]; + if (cursor_up != NULL) + UP = cursor_up; + if (backspace_if_not_bs != NULL) + BC = backspace_if_not_bs; + + (void) baudrate(); /* sets ospeed as a side-effect */ + +/* LINT_PREPRO +#if 0*/ +#include <capdefaults.c> +/* LINT_PREPRO +#endif*/ + + } + returnCode(errcode); +} + +/*************************************************************************** + * + * tgetflag(str) + * + * Look up boolean termcap capability str and return its value (TRUE=1 if + * present, FALSE=0 if not). + * + ***************************************************************************/ + +int tgetflag(NCURSES_CONST char *id) +{ +int i; + + T((T_CALLED("tgetflag(%s)"), id)); + if (cur_term != 0) { + for (i = 0; i < BOOLCOUNT; i++) { + if (!strncmp(id, boolcodes[i], 2)) { + /* setupterm forces invalid booleans to false */ + returnCode(cur_term->type.Booleans[i]); + } + } + } + returnCode(0); /* Solaris does this */ +} + +/*************************************************************************** + * + * tgetnum(str) + * + * Look up numeric termcap capability str and return its value, or -1 if + * not given. + * + ***************************************************************************/ + +int tgetnum(NCURSES_CONST char *id) +{ +int i; + + T((T_CALLED("tgetnum(%s)"), id)); + if (cur_term != 0) { + for (i = 0; i < NUMCOUNT; i++) { + if (!strncmp(id, numcodes[i], 2)) { + if (!VALID_NUMERIC(cur_term->type.Numbers[i])) + return -1; + returnCode(cur_term->type.Numbers[i]); + } + } + } + returnCode(ERR); +} + +/*************************************************************************** + * + * tgetstr(str, area) + * + * Look up string termcap capability str and return a pointer to its value, + * or NULL if not given. + * + ***************************************************************************/ + +char *tgetstr(NCURSES_CONST char *id, char **area GCC_UNUSED) +{ +int i; + + T((T_CALLED("tgetstr(%s,%p)"), id, area)); + if (cur_term != 0) { + for (i = 0; i < STRCOUNT; i++) { + T(("trying %s", strcodes[i])); + if (!strncmp(id, strcodes[i], 2)) { + T(("found match : %s", _nc_visbuf(cur_term->type.Strings[i]))); + /* setupterm forces cancelled strings to null */ + returnPtr(cur_term->type.Strings[i]); + } + } + } + returnPtr(NULL); +} + +/* + * char * + * tgoto(string, x, y) + * + * Retained solely for upward compatibility. Note the intentional + * reversing of the last two arguments. + * + */ + +char *tgoto(const char *string, int x, int y) +{ + T((T_CALLED("tgoto(%s,%d,%d)"), string, x, y)); + returnPtr(tparm((NCURSES_CONST char *)string, y, x)); +} diff --git a/lib/libcurses/tinfo/lib_termname.c b/lib/libcurses/tinfo/lib_termname.c new file mode 100644 index 00000000000..dc4e69e2907 --- /dev/null +++ b/lib/libcurses/tinfo/lib_termname.c @@ -0,0 +1,48 @@ +/* $OpenBSD: lib_termname.c,v 1.1 1999/01/18 19:10:20 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ + +#include <curses.priv.h> +#include <tic.h> /* for MAX_ALIAS */ + +MODULE_ID("$From: lib_termname.c,v 1.1 1998/12/19 23:07:43 tom Exp $") + +char *termname(void) +{ +char *term = getenv("TERM"); +static char ret[MAX_ALIAS+1]; + + T(("termname() called")); + + if (term != 0) { + (void) strncpy(ret, term, sizeof(ret) - 1); + term = ret; + } + return term; +} diff --git a/lib/libcurses/tinfo/lib_ti.c b/lib/libcurses/tinfo/lib_ti.c new file mode 100644 index 00000000000..6d2d792df6e --- /dev/null +++ b/lib/libcurses/tinfo/lib_ti.c @@ -0,0 +1,97 @@ +/* $OpenBSD: lib_ti.c,v 1.1 1999/01/18 19:10:20 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +#include <curses.priv.h> + +#include <term.h> +#include <tic.h> + +MODULE_ID("$From: lib_ti.c,v 1.13 1999/01/03 01:44:27 tom Exp $") + +int tigetflag(NCURSES_CONST char *str) +{ +int i; + + T((T_CALLED("tigetflag(%s)"), str)); + + if (cur_term != 0) { + for (i = 0; i < BOOLCOUNT; i++) { + if (!strcmp(str, boolnames[i])) { + /* setupterm forces invalid booleans to false */ + returnCode(cur_term->type.Booleans[i]); + } + } + } + + returnCode(ABSENT_BOOLEAN); +} + +int tigetnum(NCURSES_CONST char *str) +{ +int i; + + T((T_CALLED("tigetnum(%s)"), str)); + + if (cur_term != 0) { + for (i = 0; i < NUMCOUNT; i++) { + if (!strcmp(str, numnames[i])) { + if (!VALID_NUMERIC(cur_term->type.Numbers[i])) + return -1; + returnCode(cur_term->type.Numbers[i]); + } + } + } + + returnCode(CANCELLED_NUMERIC); /* Solaris returns a -1 instead */ +} + +char *tigetstr(NCURSES_CONST char *str) +{ +int i; + + T((T_CALLED("tigetstr(%s)"), str)); + + if (cur_term != 0) { + for (i = 0; i < STRCOUNT; i++) { + if (!strcmp(str, strnames[i])) { + /* setupterm forces cancelled strings to null */ + returnPtr(cur_term->type.Strings[i]); + } + } + } + + returnPtr(CANCELLED_STRING); +} diff --git a/lib/libcurses/tinfo/lib_tparm.c b/lib/libcurses/tinfo/lib_tparm.c new file mode 100644 index 00000000000..87fad7291c7 --- /dev/null +++ b/lib/libcurses/tinfo/lib_tparm.c @@ -0,0 +1,587 @@ +/* $OpenBSD: lib_tparm.c,v 1.1 1999/01/18 19:10:20 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * tparm.c + * + */ + +#include <curses.priv.h> + +#include <ctype.h> +#include <term.h> +#include <tic.h> + +MODULE_ID("$From: lib_tparm.c,v 1.37 1999/01/02 22:38:25 tom Exp $") + +/* + * char * + * tparm(string, ...) + * + * Substitute the given parameters into the given string by the following + * rules (taken from terminfo(5)): + * + * Cursor addressing and other strings requiring parame- + * ters in the terminal are described by a parameterized string + * capability, with like escapes %x in it. For example, to + * address the cursor, the cup capability is given, using two + * parameters: the row and column to address to. (Rows and + * columns are numbered from zero and refer to the physical + * screen visible to the user, not to any unseen memory.) If + * the terminal has memory relative cursor addressing, that can + * be indicated by + * + * The parameter mechanism uses a stack and special % + * codes to manipulate it. Typically a sequence will push one + * of the parameters onto the stack and then print it in some + * format. Often more complex operations are necessary. + * + * The % encodings have the following meanings: + * + * %% outputs `%' + * %c print pop() like %c in printf() + * %s print pop() like %s in printf() + * %[[:]flags][width[.precision]][doxXs] + * as in printf, flags are [-+#] and space + * + * %p[1-9] push ith parm + * %P[a-z] set dynamic variable [a-z] to pop() + * %g[a-z] get dynamic variable [a-z] and push it + * %P[A-Z] set static variable [A-Z] to pop() + * %g[A-Z] get static variable [A-Z] and push it + * %l push strlen(pop) + * %'c' push char constant c + * %{nn} push integer constant nn + * + * %+ %- %* %/ %m + * arithmetic (%m is mod): push(pop() op pop()) + * %& %| %^ bit operations: push(pop() op pop()) + * %= %> %< logical operations: push(pop() op pop()) + * %A %O logical and & or operations for conditionals + * %! %~ unary operations push(op pop()) + * %i add 1 to first two parms (for ANSI terminals) + * + * %? expr %t thenpart %e elsepart %; + * if-then-else, %e elsepart is optional. + * else-if's are possible ala Algol 68: + * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %; + * + * For those of the above operators which are binary and not commutative, + * the stack works in the usual way, with + * %gx %gy %m + * resulting in x mod y, not the reverse. + */ + +#define STACKSIZE 20 + +typedef union { + unsigned int num; + char *str; +} 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; + +#if NO_LEAKS +void _nc_free_tparm(void) +{ + if (out_buff != 0) { + FreeAndNull(out_buff); + out_size = 0; + out_used = 0; + } +} +#endif + +static void really_get_space(size_t need) +{ + out_size = need * 2; + out_buff = (char *)_nc_doalloc(out_buff, out_size); + if (out_buff == 0) + _nc_err_abort("Out of memory"); +} + +static inline void get_space(size_t need) +{ + need += out_used; + if (need > out_size) + really_get_space(need); +} + +static inline void save_text(const char *fmt, char *s, int len) +{ + size_t s_len = strlen(s); + if (len > (int)s_len) + s_len = len; + + get_space(s_len + 1); + + (void)sprintf(out_buff+out_used, fmt, s); + out_used += strlen(out_buff+out_used); +} + +static 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); + + (void)sprintf(out_buff+out_used, fmt, number); + out_used += strlen(out_buff+out_used); +} + +static inline void save_char(int c) +{ + if (c == 0) + c = 0200; + get_space(1); + out_buff[out_used++] = c; +} + +static inline void npush(int x) +{ + if (stack_ptr < STACKSIZE) { + stack[stack_ptr].num = x; + stack_ptr++; + } +} + +static inline int npop(void) +{ + return (stack_ptr > 0 ? stack[--stack_ptr].num : 0); +} + +static inline char *spop(void) +{ + static char dummy[] = ""; /* avoid const-cast */ + return (stack_ptr > 0 ? stack[--stack_ptr].str : dummy); +} + +static inline const char *parse_format(const char *s, char *format, int *len) +{ + bool done = FALSE; + bool allowminus = FALSE; + bool dot = FALSE; + int prec = 0; + int width = 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++; + dot = TRUE; + break; + case '#': + *format++ = *s++; + break; + case ' ': + *format++ = *s++; + break; + case ':': + s++; + allowminus = TRUE; + break; + case '-': + if (allowminus) { + *format++ = *s++; + } else { + done = TRUE; + } + break; + default: + if (isdigit(*s)) { + if (dot) + prec = (prec * 10) + (*s - '0'); + else + width = (width * 10) + (*s - '0'); + *format++ = *s++; + } else { + done = TRUE; + } + } + } + *format = '\0'; + /* return maximum string length in print */ + *len = (prec > width) ? prec : width; + 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) +{ +#define NUM_VARS 26 +int param[9]; +int popcount; +int number; +int len; +int level; +int x, y; +int i; +register const char *cp; +static size_t len_fmt; +static char *format; +static int dynamic_var[NUM_VARS]; +static int static_vars[NUM_VARS]; + + out_used = 0; + if (string == NULL) + return NULL; + + /* + * 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. + */ + for (cp = string, popcount = number = 0; *cp != '\0'; cp++) { + if (cp[0] == '%' && cp[1] != '\0') { + switch (cp[1]) { + case '%': + cp++; + break; + case 'i': + if (popcount < 2) + popcount = 2; + break; + case 'p': + cp++; + if (cp[1] >= '1' && cp[1] <= '9') { + int c = cp[1] - '0'; + if (c > popcount) + popcount = c; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'd': case 'c': case 's': + ++number; + break; + } + } + } + if ((size_t)(cp - string) > len_fmt) { + len_fmt = (cp - string) + len_fmt + 2; + if ((format = _nc_doalloc(format, len_fmt)) == 0) + return 0; + } + + if (number > 9) number = 9; + for (i = 0; i < max(popcount, number); i++) { + /* + * FIXME: potential loss here if sizeof(int) != sizeof(char *). + * A few caps (such as plab_norm) have string-valued parms. + */ + param[i] = va_arg(ap, int); + } + + /* + * This is a termcap compatibility hack. If there are no explicit pop + * operations in the string, load the stack in such a way that + * successive pops will grab successive parameters. That will make + * the expansion of (for example) \E[%d;%dH work correctly in termcap + * style, which means tparam() will expand termcap strings OK. + */ + stack_ptr = 0; + if (popcount == 0) { + popcount = number; + for (i = number - 1; i >= 0; i--) + npush(param[i]); + } + +#ifdef TRACE + if (_nc_tracing & TRACE_CALLS) { + for (i = 0; i < popcount; i++) + save_number(", %d", param[i], 0); + _tracef(T_CALLED("%s(%s%s)"), tname, _nc_visbuf(string), out_buff); + out_used = 0; + } +#endif /* TRACE */ + + while (*string) { + if (*string != '%') { + save_char(*string); + } else { + string++; + string = parse_format(string, format, &len); + switch (*string) { + default: + break; + case '%': + save_char('%'); + break; + + case 'd': /* FALLTHRU */ + case 'o': /* FALLTHRU */ + case 'x': /* FALLTHRU */ + case 'X': /* FALLTHRU */ + case 'c': + save_number(format, npop(), len); + break; + + case 'l': + save_number("%d", strlen(spop()), 0); + break; + + case 's': + save_text(format, spop(), len); + break; + + case 'p': + string++; + if (*string >= '1' && *string <= '9') + npush(param[*string - '1']); + 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(); + } + 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]); + } + break; + + case S_QUOTE: + string++; + npush(*string); + string++; + break; + + case L_BRACE: + number = 0; + string++; + while (*string >= '0' && *string <= '9') { + number = number * 10 + *string - '0'; + string++; + } + npush(number); + break; + + case '+': + npush(npop() + npop()); + break; + + case '-': + y = npop(); + x = npop(); + npush(x - y); + break; + + case '*': + npush(npop() * npop()); + break; + + case '/': + y = npop(); + x = npop(); + npush(x / y); + break; + + case 'm': + y = npop(); + x = npop(); + npush(x % y); + break; + + case 'A': + npush(npop() && npop()); + break; + + case 'O': + npush(npop() || npop()); + break; + + case '&': + npush(npop() & npop()); + break; + + case '|': + npush(npop() | npop()); + break; + + case '^': + npush(npop() ^ npop()); + break; + + case '=': + y = npop(); + x = npop(); + npush(x == y); + break; + + case '<': + y = npop(); + x = npop(); + npush(x < y); + break; + + case '>': + y = npop(); + x = npop(); + npush(x > y); + break; + + case '!': + npush(! npop()); + break; + + case '~': + npush(~ npop()); + break; + + case 'i': + param[0]++; + param[1]++; + break; + + case '?': + break; + + case 't': + x = npop(); + if (!x) { + /* scan forward for %e or %; at level zero */ + string++; + level = 0; + while (*string) { + if (*string == '%') { + string++; + if (*string == '?') + level++; + else if (*string == ';') { + if (level > 0) + level--; + else + break; + } + else if (*string == 'e' && level == 0) + break; + } + + if (*string) + string++; + } + } + break; + + case 'e': + /* scan forward for a %; at level zero */ + string++; + level = 0; + while (*string) { + if (*string == '%') { + string++; + if (*string == '?') + level++; + else if (*string == ';') { + if (level > 0) + level--; + else + break; + } + } + + if (*string) + string++; + } + break; + + case ';': + break; + + } /* endswitch (*string) */ + } /* endelse (*string == '%') */ + + if (*string == '\0') + break; + + string++; + } /* endwhile (*string) */ + + if (out_buff == 0 && (out_buff = calloc(1,1)) == NULL) + return(NULL); + out_buff[out_used] = '\0'; + + T((T_RETURN("%s"), _nc_visbuf(out_buff))); + return(out_buff); +} + +char *tparm(NCURSES_CONST char *string, ...) +{ +va_list ap; +char *result; + + va_start(ap, string); +#ifdef TRACE + tname = "tparm"; +#endif /* TRACE */ + result = tparam_internal(string, ap); + va_end(ap); + return result; +} diff --git a/lib/libcurses/tinfo/lib_tputs.c b/lib/libcurses/tinfo/lib_tputs.c new file mode 100644 index 00000000000..e4c778332df --- /dev/null +++ b/lib/libcurses/tinfo/lib_tputs.c @@ -0,0 +1,245 @@ +/* $OpenBSD: lib_tputs.c,v 1.1 1999/01/18 19:10:20 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * tputs.c + * delay_output() + * _nc_outch() + * tputs() + * + */ + +#include <curses.priv.h> +#include <ctype.h> +#include <term.h> /* padding_baud_rate, xon_xoff */ +#include <termcap.h> /* ospeed */ +#include <tic.h> + +MODULE_ID("$From: lib_tputs.c,v 1.38 1999/01/10 00:57:41 tom Exp $") + +#define OUTPUT ((SP != 0) ? SP->_ofp : stdout) + +char PC; /* used by termcap library */ +speed_t ospeed; /* used by termcap library */ + +int _nc_nulls_sent; /* used by 'tack' program */ + +static int (*my_outch)(int c) = _nc_outch; + +int delay_output(int ms) +{ + T((T_CALLED("delay_output(%d)"), ms)); + + if (no_pad_char) + napms(ms); + else { + register int nullcount; + + nullcount = (ms * _nc_baudrate(ospeed)) / 10000; + for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) + my_outch(PC); + if (my_outch == _nc_outch) + (void) fflush(OUTPUT); + } + + returnCode(OK); +} + +int _nc_outch(int ch) +{ +#ifdef TRACE + _nc_outchars++; +#endif /* TRACE */ + + putc(ch, OUTPUT); + return OK; +} + +int putp(const char *string) +{ + return tputs(string, 1, _nc_outch); +} + +int tputs(const char *string, int affcnt, int (*outc)(int)) +{ +bool always_delay; +bool normal_delay; +int number; +#ifdef BSD_TPUTS +int trailpad; +#endif /* BSD_TPUTS */ + +#ifdef TRACE +char addrbuf[32]; + + if (_nc_tracing & TRACE_TPUTS) + { + if (outc == _nc_outch) + (void) strcpy(addrbuf, "_nc_outch"); + else + (void) sprintf(addrbuf, "%p", outc); + if (_nc_tputs_trace) { + TR(TRACE_MAXIMUM, ("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, _nc_visbuf(string), affcnt, addrbuf)); + } + else { + TR(TRACE_MAXIMUM, ("tputs(%s, %d, %s) called", _nc_visbuf(string), affcnt, addrbuf)); + } + _nc_tputs_trace = (char *)NULL; + } +#endif /* TRACE */ + + if (string == ABSENT_STRING || string == CANCELLED_STRING) + return ERR; + + if (cur_term == 0) { + always_delay = FALSE; + normal_delay = TRUE; + } else { + always_delay = (string == bell) || (string == flash_screen); + normal_delay = + !xon_xoff + && padding_baud_rate +#ifdef NCURSES_NO_PADDING + && (SP == 0 || !(SP->_no_padding)) +#endif + && (_nc_baudrate(ospeed) >= padding_baud_rate); + } + +#ifdef BSD_TPUTS + /* + * This ugly kluge deals with the fact that some ancient BSD programs + * (like nethack) actually do the likes of tputs("50") to get delays. + */ + trailpad = 0; + if (isdigit(*string)) { + while (isdigit(*string)) { + trailpad = trailpad * 10 + (*string - '0'); + string++; + } + trailpad *= 10; + if (*string == '.') { + string++; + if (isdigit(*string)) { + trailpad += (*string - '0'); + string++; + } + while (isdigit(*string)) + string++; + } + + if (*string == '*') { + trailpad *= affcnt; + string++; + } + } +#endif /* BSD_TPUTS */ + + my_outch = outc; /* redirect delay_output() */ + while (*string) { + if (*string != '$') + (*outc)(*string); + else { + string++; + if (*string != '<') { + (*outc)('$'); + if (*string) + (*outc)(*string); + } else { + bool mandatory; + + string++; + if ((!isdigit(*string) && *string != '.') || !strchr(string, '>')) { + (*outc)('$'); + (*outc)('<'); + continue; + } + + number = 0; + while (isdigit(*string)) { + number = number * 10 + (*string - '0'); + string++; + } + number *= 10; + if (*string == '.') { + string++; + if (isdigit(*string)) { + number += (*string - '0'); + string++; + } + while (isdigit(*string)) + string++; + } + + mandatory = FALSE; + while (*string == '*' || *string == '/') + { + if (*string == '*') { + number *= affcnt; + string++; + } + else /* if (*string == '/') */ { + mandatory = TRUE; + string++; + } + } + + if (number > 0 + && (always_delay + || normal_delay + || mandatory)) + delay_output(number/10); + + } /* endelse (*string == '<') */ + } /* endelse (*string == '$') */ + + if (*string == '\0') + break; + + string++; + } + +#ifdef BSD_TPUTS + /* + * Emit any BSD-style prefix padding that we've accumulated now. + */ + if (trailpad > 0 + && (always_delay || normal_delay)) + delay_output(trailpad/10); +#endif /* BSD_TPUTS */ + + my_outch = _nc_outch; + return OK; +} diff --git a/lib/libcurses/tinfo/lib_ttyflags.c b/lib/libcurses/tinfo/lib_ttyflags.c new file mode 100644 index 00000000000..f3b875c3bd4 --- /dev/null +++ b/lib/libcurses/tinfo/lib_ttyflags.c @@ -0,0 +1,163 @@ +/* $OpenBSD: lib_ttyflags.c,v 1.1 1999/01/18 19:10:21 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ + +/* + * def_prog_mode() + * def_shell_mode() + * reset_prog_mode() + * reset_shell_mode() + * savetty() + * resetty() + */ + +#include <curses.priv.h> +#include <term.h> /* cur_term */ + +MODULE_ID("$From: lib_ttyflags.c,v 1.1 1998/12/20 00:49:19 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 + +int _nc_get_tty_mode(TTY *buf) +{ + if (cur_term == 0 + || GET_TTY(cur_term->Filedes, buf) != 0) + return(ERR); + return (OK); +} + +int _nc_set_tty_mode(TTY *buf) +{ + if (cur_term == 0 + || SET_TTY(cur_term->Filedes, buf) != 0) + return(ERR); + return (OK); +} + +int def_shell_mode(void) +{ + T((T_CALLED("def_shell_mode()"))); + + /* + * Turn off the XTABS bit in the tty structure if it was on. If XTABS + * was on, remove the tab and backtab capabilities. + */ + + if (_nc_get_tty_mode(&cur_term->Ottyb) != OK) + returnCode(ERR); +#ifdef TERMIOS + if (cur_term->Ottyb.c_oflag & tabs) + tab = back_tab = NULL; +#else + if (cur_term->Ottyb.sg_flags & XTABS) + tab = back_tab = NULL; +#endif + returnCode(OK); +} + +int def_prog_mode(void) +{ + T((T_CALLED("def_prog_mode()"))); + + if (_nc_get_tty_mode(&cur_term->Nttyb) != OK) + returnCode(ERR); +#ifdef TERMIOS + cur_term->Nttyb.c_oflag &= ~tabs; +#else + cur_term->Nttyb.sg_flags &= ~XTABS; +#endif + returnCode(OK); +} + +int 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); + } + returnCode(OK); + } + returnCode(ERR); +} + +int reset_shell_mode(void) +{ + T((T_CALLED("reset_shell_mode()"))); + + if (cur_term != 0) { + if (SP) + { + _nc_keypad(FALSE); + fflush(SP->_ofp); + NC_BUFFERED(FALSE); + } + returnCode(_nc_set_tty_mode(&cur_term->Ottyb)); + } + returnCode(ERR); +} + +/* +** savetty() and resetty() +** +*/ + +static TTY buf; + +int savetty(void) +{ + T((T_CALLED("savetty()"))); + + returnCode(_nc_get_tty_mode(&buf)); +} + +int resetty(void) +{ + T((T_CALLED("resetty()"))); + + returnCode(_nc_set_tty_mode(&buf)); +} diff --git a/lib/libcurses/tinfo/make_keys.c b/lib/libcurses/tinfo/make_keys.c new file mode 100644 index 00000000000..70617a42519 --- /dev/null +++ b/lib/libcurses/tinfo/make_keys.c @@ -0,0 +1,136 @@ +/* $OpenBSD: make_keys.c,v 1.1 1999/01/18 19:10:21 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1997 * + ****************************************************************************/ + +/* + * This replaces an awk script which translated keys.list into keys.tries by + * 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. + */ +#include <curses.priv.h> + +MODULE_ID("$From: make_keys.c,v 1.4 1998/02/11 12:13:57 tom Exp $") + +#include <names.c> + +#define UNKNOWN (SIZEOF(strnames) + SIZEOF(strfnames)) + +static size_t lookup(const char *name) +{ + size_t n; + bool found = FALSE; + for (n = 0; strnames[n] != 0; n++) { + if (!strcmp(name, strnames[n])) { + found = TRUE; + break; + } + } + if (!found) { + for (n = 0; strfnames[n] != 0; n++) { + if (!strcmp(name, strfnames[n])) { + found = TRUE; + break; + } + } + } + return found ? n : UNKNOWN; +} + +static void make_keys(FILE *ifp, FILE *ofp) +{ + char buffer[BUFSIZ]; + char from[BUFSIZ]; + char to[BUFSIZ]; + int maxlen = 16; + + while (fgets(buffer, sizeof(buffer), ifp) != 0) { + if (*buffer == '#') + continue; + if (sscanf(buffer, "%s %s", to, from) == 2) { + int code = lookup(from); + if (code == UNKNOWN) + continue; + if ((int)strlen(from) > maxlen) + maxlen = strlen(from); + fprintf(ofp, "\t{ %4d, %-*.*s },\t/* %s */\n", + code, + maxlen, maxlen, + to, + from); + } + } +} + +static void write_list(FILE *ofp, const char **list) +{ + while (*list != 0) + fprintf(ofp, "%s\n", *list++); +} + +int main(int argc, char *argv[]) +{ + static const char *prefix[] = { + "#ifndef NCU_KEYS_H", + "#define NCU_KEYS_H 1", + "", + "/* This file was generated by MAKE_KEYS */", + "", + "static const struct {", + "\tunsigned offset;", + "\tchtype code;", + "} table[] = {", + 0 + }; + static const char *suffix[] = { + "};", + "", + "#endif /* NCU_KEYS_H */", + 0 + }; + + write_list(stdout, prefix); + if (argc > 1) { + int n; + for (n = 1; n < argc; n++) { + FILE *fp = fopen(argv[n], "r"); + if (fp != 0) { + make_keys(fp, stdout); + fclose(fp); + } + } + } else { + make_keys(stdin, stdout); + } + write_list(stdout, suffix); + return EXIT_SUCCESS; +} diff --git a/lib/libcurses/tinfo/name_match.c b/lib/libcurses/tinfo/name_match.c new file mode 100644 index 00000000000..814e780a4d4 --- /dev/null +++ b/lib/libcurses/tinfo/name_match.c @@ -0,0 +1,87 @@ +/* $OpenBSD: name_match.c,v 1.1 1999/01/18 19:10:21 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +#include <curses.priv.h> +#include <term.h> +#include <tic.h> + +MODULE_ID("$From: name_match.c,v 1.7 1998/09/19 20:27:49 Todd.Miller Exp $") + +/* + * _nc_first_name(char *names) + * + * Extract the primary name from a compiled entry. + */ + +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 char *cp; + + (void) strlcpy(buf, sp, sizeof(buf)); + + cp = strchr(buf, '|'); + if (cp) + *cp = '\0'; + + return(buf); +} + +/* + * int _nc_name_match(namelist, name, delim) + * + * Is the given name matched in namelist? + */ + +int _nc_name_match(const char *const namelst, const char *const name, const char *const delim) +/* microtune this, it occurs in several critical loops */ +{ +char namecopy[MAX_ENTRY_SIZE]; /* this may get called on a TERMCAP value */ +register char *cp; + + if (namelst == 0) + return(FALSE); + (void) strlcpy (namecopy, namelst, sizeof(namecopy)); + if ((cp = strtok(namecopy, delim)) != 0) { + do { + /* avoid strcmp() function-call cost if possible */ + if (cp[0] == name[0] && strcmp(cp, name) == 0) + return(TRUE); + } while + ((cp = strtok((char *)0, delim)) != 0); + } + return(FALSE); +} diff --git a/lib/libcurses/tinfo/parse_entry.c b/lib/libcurses/tinfo/parse_entry.c new file mode 100644 index 00000000000..ed44a9840d7 --- /dev/null +++ b/lib/libcurses/tinfo/parse_entry.c @@ -0,0 +1,924 @@ +/* $OpenBSD: parse_entry.c,v 1.1 1999/01/18 19:10:21 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * parse_entry.c -- compile one terminfo or termcap entry + * + * Get an exact in-core representation of an entry. Don't + * try to resolve use or tc capabilities, that is someone + * else's job. Depends on the lexical analyzer to get tokens + * from the input stream. + */ + +#include <curses.priv.h> + +#include <ctype.h> +#include <tic.h> +#define __INTERNAL_CAPS_VISIBLE +#include <term.h> +#include <term_entry.h> + +MODULE_ID("$From: parse_entry.c,v 1.24 1998/07/04 23:08:38 tom Exp $") + +#ifdef LINT +static short const parametrized[] = { 0 }; +#else +#include <parametrized.h> +#endif + +struct token _nc_curr_token; + +static void postprocess_termcap(TERMTYPE *, bool); +static void postprocess_terminfo(TERMTYPE *); +static struct name_table_entry const * lookup_fullname(const char *name); + +/* + * int + * _nc_parse_entry(entry, literal, silent) + * + * Compile one entry. Doesn't try to resolve use or tc capabilities. + * + * found-forward-use = FALSE + * re-initialise internal arrays + * get_token(); + * if the token was not a name in column 1, complain and die + * save names in entry's string table + * while (get_token() is not EOF and not NAMES) + * check for existance and type-correctness + * enter cap into structure + * if STRING + * save string in entry's string table + * push back token + */ + +int _nc_parse_entry(struct entry *entryp, int literal, bool silent) +{ + int token_type; + struct name_table_entry const *entry_ptr; + char *ptr, namecpy[MAX_NAME_SIZE+1]; + + token_type = _nc_get_token(); + + if (token_type == EOF) + return(EOF); + if (token_type != NAMES) + _nc_err_abort("Entry does not start with terminal names in column one"); + + _nc_init_entry(&entryp->tterm); + + entryp->cstart = _nc_comment_start; + entryp->cend = _nc_comment_end; + 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 */ + ptr = _nc_curr_token.tk_name; + if (ptr[2] == '|') + { + ptr = _nc_curr_token.tk_name + 3; + _nc_curr_token.tk_name[2] = '\0'; + } + + entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr); + + DEBUG(1, ("Starting '%s'", ptr)); + + /* + * We do this because the one-token lookahead in the parse loop + * results in the terminal type getting prematurely set to correspond + * to that of the next entry. + */ + _nc_set_type(_nc_first_name(entryp->tterm.term_names)); + + /* check for overly-long names and aliases */ + (void) strlcpy(namecpy, entryp->tterm.term_names, sizeof(namecpy)); + if ((ptr = strrchr(namecpy, '|')) != (char *)0) + *ptr = '\0'; + ptr = strtok(namecpy, "|"); + if (strlen(ptr) > MAX_ALIAS) + _nc_warning("primary name may be too long"); + while ((ptr = strtok((char *)0, "|")) != (char *)0) + if (strlen(ptr) > MAX_ALIAS) + _nc_warning("alias `%s' may be too long", ptr); + + entryp->nuses = 0; + + for (token_type = _nc_get_token(); + token_type != EOF && token_type != NAMES; + token_type = _nc_get_token()) + { + if (strcmp(_nc_curr_token.tk_name, "use") == 0 + || strcmp(_nc_curr_token.tk_name, "tc") == 0) { + entryp->uses[entryp->nuses].parent = (void *)_nc_save_str(_nc_curr_token.tk_valstring); + entryp->uses[entryp->nuses].line = _nc_curr_line; + entryp->nuses++; + } else { + /* normal token lookup */ + entry_ptr = _nc_find_entry(_nc_curr_token.tk_name, + _nc_syntax ? _nc_cap_hash_table : _nc_info_hash_table); + + /* + * Our kluge to handle aliasing. The reason it's done + * this ugly way, with a linear search, is so the hashing + * machinery doesn't have to be made really complicated + * (also we get better warnings this way). No point in + * making this case fast, aliased caps aren't common now + * and will get rarer. + */ + if (entry_ptr == NOTFOUND) + { + const struct alias *ap; + + if (_nc_syntax == SYN_TERMCAP) + { + for (ap = _nc_capalias_table; 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", + ap->from, ap->source); + goto nexttok; + } + + entry_ptr = _nc_find_entry(ap->to, _nc_cap_hash_table); + 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++) + if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) + { + if (ap->to == (char *)0) + { + _nc_warning("%s (%s terminfo extension) ignored", + ap->from, ap->source); + goto nexttok; + } + + entry_ptr = _nc_find_entry(ap->to, _nc_info_hash_table); + if (entry_ptr && !silent) + _nc_warning("%s (%s terminfo extension) aliased to %s", ap->from, ap->source, ap->to); + break; + } + + /* last chance: a full-name */ + if (entry_ptr == NOTFOUND) { + entry_ptr = lookup_fullname(_nc_curr_token.tk_name); + } + } + } + + /* can't find this cap name, not even as an alias */ + if (entry_ptr == NOTFOUND) { + if (!silent) + _nc_warning("unknown capability '%s'", + _nc_curr_token.tk_name); + continue; + } + + /* deal with bad type/value combinations. */ + if (token_type != CANCEL && entry_ptr->nte_type != token_type) + { + /* + * Nasty special cases here handle situations in which type + * information can resolve name clashes. Normal lookup + * finds the last instance in the capability table of a + * given name, regardless of type. find_type_entry looks + * for a first matching instance with given type. So as + * long as all ambiguous names occur in pairs of distinct + * type, this will do the job. + */ + + /* tell max_attributes from arrow_key_map */ + if (token_type == NUMBER && !strcmp("ma", _nc_curr_token.tk_name)) + entry_ptr = _nc_find_type_entry("ma", NUMBER, + _nc_get_table(_nc_syntax != 0)); + + /* map terminfo's string MT to MT */ + else if (token_type==STRING &&!strcmp("MT",_nc_curr_token.tk_name)) + entry_ptr = _nc_find_type_entry("MT", STRING, + _nc_get_table(_nc_syntax != 0)); + + /* treat strings without following "=" as empty strings */ + else if (token_type==BOOLEAN && entry_ptr->nte_type==STRING) + token_type = STRING; + /* we couldn't recover; skip this token */ + else + { + if (!silent) + { + const char *type_name; + switch (entry_ptr->nte_type) + { + case BOOLEAN: + type_name = "boolean"; + break; + case STRING: + type_name = "string"; + break; + case NUMBER: + type_name = "numeric"; + break; + default: + type_name = "unknown"; + break; + } + _nc_warning("wrong type used for %s capability '%s'", + type_name, _nc_curr_token.tk_name); + } + continue; + } + } + + /* now we know that the type/value combination is OK */ + switch (token_type) { + case CANCEL: + switch (entry_ptr->nte_type) { + case BOOLEAN: + entryp->tterm.Booleans[entry_ptr->nte_index] = CANCELLED_BOOLEAN; + break; + + case NUMBER: + entryp->tterm.Numbers[entry_ptr->nte_index] = CANCELLED_NUMERIC; + break; + + case STRING: + entryp->tterm.Strings[entry_ptr->nte_index] = CANCELLED_STRING; + break; + } + break; + + case BOOLEAN: + entryp->tterm.Booleans[entry_ptr->nte_index] = TRUE; + break; + + case NUMBER: + entryp->tterm.Numbers[entry_ptr->nte_index] = + _nc_curr_token.tk_valnumber; + break; + + case STRING: + ptr = _nc_curr_token.tk_valstring; + if (_nc_syntax==SYN_TERMCAP) + ptr = _nc_captoinfo(_nc_curr_token.tk_name, + ptr, + parametrized[entry_ptr->nte_index]); + entryp->tterm.Strings[entry_ptr->nte_index] = _nc_save_str(ptr); + break; + + default: + if (!silent) + _nc_warning("unknown token type"); + _nc_panic_mode((_nc_syntax==SYN_TERMCAP) ? ':' : ','); + continue; + } + } /* end else cur_token.name != "use" */ + nexttok: + continue; /* cannot have a label w/o statement */ + } /* endwhile (not EOF and not NAMES) */ + + _nc_push_token(token_type); + _nc_set_type(_nc_first_name(entryp->tterm.term_names)); + + /* + * Try to deduce as much as possible from extension capabilities + * (this includes obsolete BSD capabilities). Sigh...it would be more + * space-efficient to call this after use resolution, but it has + * to be done before entry allocation is wrapped up. + */ + if (!literal) { + if (_nc_syntax == SYN_TERMCAP) + { + bool has_base_entry = FALSE; + int i; + + /* + * Don't insert defaults if this is a `+' entry meant only + * for inclusion in other entries (not sure termcap ever + * had these, actually). + */ + if (strchr(entryp->tterm.term_names, '+')) + has_base_entry = TRUE; + else + /* + * Otherwise, look for a base entry that will already + * have picked up defaults via translation. + */ + for (i = 0; i < entryp->nuses; i++) + if (!strchr(entryp->uses[i].parent, '+')) + has_base_entry = TRUE; + + postprocess_termcap(&entryp->tterm, has_base_entry); + } + else + postprocess_terminfo(&entryp->tterm); + } + _nc_wrap_entry(entryp); + + return(OK); +} + +int _nc_capcmp(const char *s, const char *t) +/* compare two string capabilities, stripping out padding */ +{ + if (!s && !t) + return(0); + else if (!s || !t) + return(1); + + for (;;) + { + if (s[0] == '$' && s[1] == '<') + { + for (s += 2; ; s++) + if (!(isdigit(*s) || *s=='.' || *s=='*' || *s=='/' || *s=='>')) + break; + } + + if (t[0] == '$' && t[1] == '<') + { + for (t += 2; ; t++) + if (!(isdigit(*t) || *t=='.' || *t=='*' || *t=='/' || *t=='>')) + break; + } + + /* we've now pushed s and t past any padding they were pointing at */ + + if (*s == '\0' && *t == '\0') + return(0); + + if (*s != *t) + return(*t - *s); + + /* else *s == *t but one is not NUL, so continue */ + s++, t++; + } +} + +/* + * The ko capability, if present, consists of a comma-separated capability + * list. For each capability, we may assume there is a keycap that sends the + * string which is the value of that capability. + */ +typedef struct {const char *from; const char *to;} assoc; +static assoc const ko_xlate[] = +{ + {"al", "kil1"}, /* insert line key -> KEY_IL */ + {"bt", "kcbt"}, /* back tab -> KEY_BTAB */ + {"cd", "ked"}, /* clear-to-eos key -> KEY_EOL */ + {"ce", "kel"}, /* clear-to-eol key -> KEY_EOS */ + {"cl", "kclr"}, /* clear key -> KEY_CLEAR */ + {"ct", "tbc"}, /* clear all tabs -> KEY_CATAB */ + {"dc", "kdch1"}, /* delete char -> KEY_DC */ + {"dl", "kdl1"}, /* delete line -> KEY_DL */ + {"do", "kcud1"}, /* down key -> KEY_DOWN */ + {"ei", "krmir"}, /* exit insert key -> KEY_EIC */ + {"ho", "khome"}, /* home key -> KEY_HOME */ + {"ic", "kich1"}, /* insert char key -> KEY_IC */ + {"im", "kIC"}, /* insert-mode key -> KEY_SIC */ + {"le", "kcub1"}, /* le key -> KEY_LEFT */ + {"nd", "kcuf1"}, /* nd key -> KEY_RIGHT */ + {"nl", "kent"}, /* new line key -> KEY_ENTER */ + {"st", "khts"}, /* set-tab key -> KEY_STAB */ + {"ta", CANCELLED_STRING}, + {"up", "kcuu1"}, /* up-arrow key -> KEY_UP */ + {(char *)0, (char *)0}, +}; + +/* + * This routine fills in string caps that either had defaults under + * termcap or can be manufactured from obsolete termcap capabilities. + * It was lifted from Ross Ridge's mytinfo package. + */ + +static const char C_CR[] = "\r"; +static const char C_LF[] = "\n"; +static const char C_BS[] = "\b"; +static const char C_HT[] = "\t"; + +/* + * Note that WANTED and PRESENT are not simple inverses! If a capability + * has been explicitly cancelled, it's not considered WANTED. + */ +#define WANTED(s) ((s) == ABSENT_STRING) +#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING)) + +/* + * This bit of legerdemain turns all the terminfo variable names into + * references to locations in the arrays Booleans, Numbers, and Strings --- + * precisely what's needed. + */ + +#undef CUR +#define CUR tp-> + +static +void postprocess_termcap(TERMTYPE *tp, bool has_base) +{ + char buf[MAX_LINE * 2 + 2]; + + /* + * TERMCAP DEFAULTS AND OBSOLETE-CAPABILITY TRANSLATIONS + * + * This first part of the code is the functional inverse of the + * fragment in capdefaults.c. + * ---------------------------------------------------------------------- + */ + + /* if there was a tc entry, assume we picked up defaults via that */ + if (!has_base) + { + if (WANTED(init_3string) && termcap_init2) + init_3string = _nc_save_str(termcap_init2); + + if (WANTED(reset_2string) && termcap_reset) + reset_2string = _nc_save_str(termcap_reset); + + if (WANTED(carriage_return)) { + if (carriage_return_delay > 0) { + sprintf(buf, "%s$<%d>", C_CR, carriage_return_delay); + carriage_return = _nc_save_str(buf); + } else + carriage_return = _nc_save_str(C_CR); + } + if (WANTED(cursor_left)) { + if (backspace_delay > 0) { + sprintf(buf, "%s$<%d>", C_BS, backspace_delay); + cursor_left = _nc_save_str(buf); + } else if (backspaces_with_bs == 1) + cursor_left = _nc_save_str(C_BS); + else if (PRESENT(backspace_if_not_bs)) + cursor_left = backspace_if_not_bs; + } + /* vi doesn't use "do", but it does seems to use nl (or '\n') instead */ + if (WANTED(cursor_down)) { + if (PRESENT(linefeed_if_not_lf)) + cursor_down = linefeed_if_not_lf; + else if (linefeed_is_newline != 1) { + if (new_line_delay > 0) { + sprintf(buf, "%s$<%d>", C_LF, new_line_delay); + cursor_down = _nc_save_str(buf); + } else + cursor_down = _nc_save_str(C_LF); + } + } + if (WANTED(scroll_forward) && crt_no_scrolling != 1) { + if (PRESENT(linefeed_if_not_lf)) + cursor_down = linefeed_if_not_lf; + else if (linefeed_is_newline != 1) { + if (new_line_delay > 0) { + sprintf(buf, "%s$<%d>", C_LF, new_line_delay); + scroll_forward = _nc_save_str(buf); + } else + scroll_forward = _nc_save_str(C_LF); + } + } + if (WANTED(newline)) { + if (linefeed_is_newline == 1) { + if (new_line_delay > 0) { + sprintf(buf, "%s$<%d>", C_LF, new_line_delay); + newline = _nc_save_str(buf); + } else + newline = _nc_save_str(C_LF); + } else if (PRESENT(carriage_return) && PRESENT(scroll_forward)) { + strlcpy(buf, carriage_return, MAX_LINE+1); + strlcat(buf, scroll_forward, MAX_LINE+1); + newline = _nc_save_str(buf); + } else if (PRESENT(carriage_return) && PRESENT(cursor_down)) { + strlcpy(buf, carriage_return, MAX_LINE+1); + strlcat(buf, cursor_down, MAX_LINE+1); + newline = _nc_save_str(buf); + } + } + } + + /* + * Inverse of capdefaults.c code ends here. + * ---------------------------------------------------------------------- + * + * TERMCAP-TO TERMINFO MAPPINGS FOR SOURCE TRANSLATION + * + * These translations will *not* be inverted by tgetent(). + */ + + if (!has_base) + { + /* + * We wait until now to decide if we've got a working cr because even + * one that doesn't work can be used for newline. Unfortunately the + * space allocated for it is wasted. + */ + if (return_does_clr_eol == 1 || no_correctly_working_cr == 1) + carriage_return = ABSENT_STRING; + + /* + * Supposedly most termcap entries have ta now and '\t' is no longer a + * default, but it doesn't seem to be true... + */ + if (WANTED(tab)) { + if (horizontal_tab_delay > 0) { + sprintf(buf, "%s$<%d>", C_HT, horizontal_tab_delay); + tab = _nc_save_str(buf); + } else + tab = _nc_save_str(C_HT); + } + if (init_tabs == ABSENT_NUMERIC && has_hardware_tabs == TRUE) + init_tabs = 8; + + /* + * Assume we can beep with ^G unless we're given bl@. + */ + if (WANTED(bell)) + bell = _nc_save_str("\007"); + } + + /* + * Translate the old termcap :pt: capability to it#8 + ht=\t + */ + if (has_hardware_tabs == TRUE) { + if (init_tabs != 8 && init_tabs != ABSENT_NUMERIC) + _nc_warning("hardware tabs with a width other than 8: %d", init_tabs); + else + { + if (tab && _nc_capcmp(tab, C_HT)) + _nc_warning("hardware tabs with a non-^I tab string %s", + _nc_visbuf(tab)); + else + { + if (WANTED(tab)) + tab = _nc_save_str(C_HT); + init_tabs = 8; + } + } + } + /* + * Now translate the ko capability, if there is one. This + * isn't from mytinfo... + */ + if (PRESENT(other_non_function_keys)) + { + char *dp, *cp = strtok(other_non_function_keys, ","); + struct name_table_entry const *from_ptr; + struct name_table_entry const *to_ptr; + assoc const *ap; + char buf2[MAX_TERMINFO_LENGTH]; + bool foundim; + + /* we're going to use this for a special case later */ + dp = strchr(other_non_function_keys, 'i'); + foundim = dp && dp[1] == 'm'; + + /* look at each comma-separated capability in the ko string... */ + do { + for (ap = ko_xlate; ap->from; ap++) + if (strcmp(ap->from, cp) == 0) + break; + if (!ap->to) + { + _nc_warning("unknown capability `%s' in ko string", cp); + continue; + } + else if (ap->to == CANCELLED_STRING) /* ignore it */ + continue; + + /* 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); + + if (!from_ptr || !to_ptr) /* should never happen! */ + _nc_err_abort("ko translation table is invalid, I give up"); + + if (WANTED(tp->Strings[from_ptr->nte_index])) + { + _nc_warning("no value for ko capability %s", ap->from); + continue; + } + + if (tp->Strings[to_ptr->nte_index]) + { + /* There's no point in warning about it if it's the same + * string; that's just an inefficiency. + */ + if (strcmp( + tp->Strings[from_ptr->nte_index], + tp->Strings[to_ptr->nte_index]) != 0) + _nc_warning("%s (%s) already has an explicit value %s, ignoring ko", + ap->to, ap->from, + _nc_visbuf(tp->Strings[to_ptr->nte_index]) ); + continue; + } + + /* + * The magic moment -- copy the mapped key string over, + * stripping out padding. + */ + dp = buf2; + for (cp = tp->Strings[from_ptr->nte_index]; *cp; cp++) + { + if (cp[0] == '$' && cp[1] == '<') + { + while (*cp && *cp != '>') + if (!*cp) + break; + else + ++cp; + } + else + *dp++ = *cp; + } + *dp++ = '\0'; + + tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2); + } while + ((cp = strtok((char *)0, ",")) != 0); + + /* + * Note: ko=im and ko=ic both want to grab the `Insert' + * keycap. There's a kich1 but no ksmir, so the ic capability + * got mapped to kich1 and im to kIC to avoid a collision. + * If the description has im but not ic, hack kIC back to kich1. + */ + if (foundim && WANTED(key_ic) && key_sic) + { + key_ic = key_sic; + key_sic = ABSENT_STRING; + } + } + + if (!hard_copy) + { + if (WANTED(key_backspace)) + key_backspace = _nc_save_str(C_BS); + if (WANTED(key_left)) + key_left = _nc_save_str(C_BS); + if (WANTED(key_down)) + key_down = _nc_save_str(C_LF); + } + + /* + * Translate XENIX forms characters. + */ + if (PRESENT(acs_ulcorner) || + PRESENT(acs_llcorner) || + PRESENT(acs_urcorner) || + PRESENT(acs_lrcorner) || + PRESENT(acs_ltee) || + PRESENT(acs_rtee) || + PRESENT(acs_btee) || + PRESENT(acs_ttee) || + PRESENT(acs_hline) || + PRESENT(acs_vline) || + PRESENT(acs_plus)) + { + char buf2[MAX_TERMCAP_LENGTH], *bp = buf2; + + if (acs_chars) + { + (void)strcpy(bp, acs_chars); + bp += strlen(bp); + } + + if (acs_ulcorner && acs_ulcorner[1] == '\0') + { + *bp++ = 'l'; + *bp++ = *acs_ulcorner; + } + if (acs_llcorner && acs_llcorner[1] == '\0') + { + *bp++ = 'm'; + *bp++ = *acs_llcorner; + } + if (acs_urcorner && acs_urcorner[1] == '\0') + { + *bp++ = 'k'; + *bp++ = *acs_urcorner; + } + if (acs_lrcorner && acs_lrcorner[1] == '\0') + { + *bp++ = 'j'; + *bp++ = *acs_lrcorner; + } + if (acs_ltee && acs_ltee[1] == '\0') + { + *bp++ = 't'; + *bp++ = *acs_ltee; + } + if (acs_rtee && acs_rtee[1] == '\0') + { + *bp++ = 'u'; + *bp++ = *acs_rtee; + } + if (acs_btee && acs_btee[1] == '\0') + { + *bp++ = 'v'; + *bp++ = *acs_btee; + } + if (acs_ttee && acs_ttee[1] == '\0') + { + *bp++ = 'w'; + *bp++ = *acs_ttee; + } + if (acs_hline && acs_hline[1] == '\0') + { + *bp++ = 'q'; + *bp++ = *acs_hline; + } + if (acs_vline && acs_vline[1] == '\0') + { + *bp++ = 'x'; + *bp++ = *acs_vline; + } + if (acs_plus) + { + *bp++ = 'n'; + strcpy(bp, acs_plus); + bp = buf2 + strlen(buf2); + } + + if (bp != buf2) + { + *bp++ = '\0'; + acs_chars = _nc_save_str(buf2); + _nc_warning("acsc string synthesized from XENIX capabilities"); + } + } + else if (acs_chars == 0 + && enter_alt_charset_mode != 0 + && exit_alt_charset_mode != 0) + { + acs_chars = _nc_save_str("``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~"); + } +} + +static +void postprocess_terminfo(TERMTYPE *tp) +{ + /* + * TERMINFO-TO-TERMINFO MAPPINGS FOR SOURCE TRANSLATION + * ---------------------------------------------------------------------- + */ + + /* + * Translate AIX forms characters. + */ + if (PRESENT(box_chars_1)) + { + char buf2[MAX_TERMCAP_LENGTH], *bp = buf2; + + if (acs_chars) + { + (void)strcpy(bp, acs_chars); + bp += strlen(bp); + } + + if (box_chars_1[0]) /* ACS_ULCORNER */ + { + *bp++ = 'l'; + *bp++ = box_chars_1[0]; + } + if (box_chars_1[1]) /* ACS_HLINE */ + { + *bp++ = 'q'; + *bp++ = box_chars_1[1]; + } + if (box_chars_1[2]) /* ACS_URCORNER */ + { + *bp++ = 'k'; + *bp++ = box_chars_1[2]; + } + if (box_chars_1[3]) /* ACS_VLINE */ + { + *bp++ = 'x'; + *bp++ = box_chars_1[3]; + } + if (box_chars_1[4]) /* ACS_LRCORNER */ + { + *bp++ = 'j'; + *bp++ = box_chars_1[4]; + } + if (box_chars_1[5]) /* ACS_LLCORNER */ + { + *bp++ = 'm'; + *bp++ = box_chars_1[5]; + } + if (box_chars_1[6]) /* ACS_TTEE */ + { + *bp++ = 'w'; + *bp++ = box_chars_1[6]; + } + if (box_chars_1[7]) /* ACS_RTEE */ + { + *bp++ = 'u'; + *bp++ = box_chars_1[7]; + } + if (box_chars_1[8]) /* ACS_BTEE */ + { + *bp++ = 'v'; + *bp++ = box_chars_1[8]; + } + if (box_chars_1[9]) /* ACS_LTEE */ + { + *bp++ = 't'; + *bp++ = box_chars_1[9]; + } + if (box_chars_1[10]) /* ACS_PLUS */ + { + *bp++ = 'n'; + *bp++ = box_chars_1[10]; + } + + if (bp != buf2) + { + *bp++ = '\0'; + acs_chars = _nc_save_str(buf2); + _nc_warning("acsc string synthesized from AIX capabilities"); + box_chars_1 = ABSENT_STRING; + } + } + /* + * ---------------------------------------------------------------------- + */ +} + +/* + * Do a linear search through the terminfo tables to find a given full-name. + * We don't expect to do this often, so there's no hashing function. + * + * In effect, this scans through the 3 lists of full-names, and looks them + * up in _nc_info_table, which is organized so that the nte_index fields are + * sorted, but the nte_type fields are not necessarily grouped together. + */ +static +struct name_table_entry const * lookup_fullname(const char *find) +{ + int state = -1; + + for (;;) { + int count = 0; + NCURSES_CONST char *const *names; + + switch (++state) { + case BOOLEAN: + names = boolfnames; + break; + case STRING: + names = strfnames; + break; + case NUMBER: + names = numfnames; + break; + default: + return NOTFOUND; + } + + for (count = 0; names[count] != 0; count++) { + if (!strcmp(names[count], find)) { + struct name_table_entry const *entry_ptr = _nc_get_table(FALSE); + while (entry_ptr->nte_type != state + || entry_ptr->nte_index != count) + entry_ptr++; + return entry_ptr; + } + } + } +} + +/* parse_entry.c ends here */ diff --git a/lib/libcurses/tinfo/read_bsd_terminfo.c b/lib/libcurses/tinfo/read_bsd_terminfo.c new file mode 100644 index 00000000000..4e6c6fb1425 --- /dev/null +++ b/lib/libcurses/tinfo/read_bsd_terminfo.c @@ -0,0 +1,140 @@ +/* $OpenBSD: read_bsd_terminfo.c,v 1.1 1999/01/18 19:10:22 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by SigmaSoft, Th. Lockert. + * 4. The name of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: read_bsd_terminfo.c,v 1.1 1999/01/18 19:10:22 millert Exp $"; +#endif + +#include <curses.priv.h> +#include <tic.h> +#include <term.h> /* lines, columns, cur_term */ +#include <term_entry.h> + +#define PVECSIZ 32 +#define _PATH_TERMINFO "/usr/share/misc/terminfo" + +/* + * Look up ``tn'' in the BSD terminfo.db file and fill in ``tp'' + * with the info we find there. + * Returns 1 on success, 0 on failure. + */ +int +_nc_read_bsd_terminfo_entry(tn, tp) + const char *tn; + TERMTYPE *const tp; +{ + char *p; + char *dummy; + char **fname; + int i; + char envterm[PATH_MAX]; /* local copy of $TERMINFO */ + char hometerm[PATH_MAX]; /* local copy of $HOME/.terminfo */ + char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ + char namecpy[MAX_NAME_SIZE+1]; + long num; + size_t len; + + fname = pathvec; + /* $TERMINFO may hold a path to a terminfo file */ + if (!issetugid() && (p = getenv("TERMINFO")) != NULL) { + len = strlcpy(envterm, p, sizeof(envterm)); + if (len < sizeof(envterm)) + *fname++ = envterm; + } + + /* Also check $HOME/.terminfo if it exists */ + if (!issetugid() && (p = getenv("HOME")) != NULL) { + len = snprintf(hometerm, sizeof(hometerm), "%s/.terminfo", p); + if (len < sizeof(hometerm)) + *fname++ = hometerm; + } + + /* Finally we check the system terminfo file and mark the end of vector */ + *fname++ = _PATH_TERMINFO; + *fname = (char *) 0; + + (void) cgetset(NULL); + dummy = NULL; + i = cgetent(&dummy, pathvec, (char *)tn); + + if (i == 0) { + _nc_init_entry(tp); + + /* Set terminal name(s) */ + if ((p = strchr(dummy, ':')) != NULL) + *p = '\0'; + if ((tp->str_table = tp->term_names = strdup(dummy)) == NULL) + return (0); + _nc_set_type(_nc_first_name(tp->term_names)); + if (p) + *p = ':'; + + /* Truncate overly-long names and aliases */ + (void)strlcpy(namecpy, tp->term_names, sizeof(namecpy)); + if ((p = strrchr(namecpy, '|')) != (char *)NULL) + *p = '\0'; + p = strtok(namecpy, "|"); + if (strlen(p) > MAX_ALIAS) + _nc_warning("primary name may be too long"); + while ((p = strtok((char *)NULL, "|")) != (char *)NULL) + if (strlen(p) > MAX_ALIAS) + _nc_warning("alias `%s' may be too long", p); + + /* Copy capabilities */ + for (i = 0 ; i < BOOLCOUNT ; i++) { + if (cgetcap(dummy, (char *)boolnames[i], ':') == NULL) + tp->Booleans[i] = FALSE; + else + tp->Booleans[i] = TRUE; + } + for (i = 0 ; i < NUMCOUNT ; i++) { + if (cgetnum(dummy, (char *)numnames[i], &num) < 0) + tp->Numbers[i] = 0; + else + tp->Numbers[i] = (int)num; + } + for (i = 0 ; i < STRCOUNT ; i++) { + if (cgetstr(dummy, (char *)strnames[i], &p) < 0) + tp->Strings[i] = NULL; + else + tp->Strings[i] = p; + } + i = 0; + } + + /* We are done with the returned getcap buffer now; free it */ + if (dummy) + free(dummy); + + return ((i == 0)); +} diff --git a/lib/libcurses/tinfo/read_entry.c b/lib/libcurses/tinfo/read_entry.c new file mode 100644 index 00000000000..9ebf0779912 --- /dev/null +++ b/lib/libcurses/tinfo/read_entry.c @@ -0,0 +1,362 @@ +/* $OpenBSD: read_entry.c,v 1.1 1999/01/18 19:10:22 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + + +/* + * read_entry.c -- Routine for reading in a compiled terminfo file + * + */ + +#include <curses.priv.h> + +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <term.h> +#include <tic.h> + +MODULE_ID("$From: read_entry.c,v 1.47 1998/12/20 02:51:50 tom Exp $") + +#ifndef O_BINARY +#define O_BINARY 0 +#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]) + +#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. + */ +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) { + char *envp; + if (!issetugid() && (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. + */ +void _nc_keep_tic_dir(const char *path) +{ + _nc_tic_dir(path); + keep_tic_directory = TRUE; +} + +int _nc_read_file_entry(const char *const filename, TERMTYPE *ptr) +/* return 1 if read, 0 if not found or garbled */ +{ + int name_size, bool_count, num_count, str_count, str_size; + int i, fd, numread; + char buf[MAX_ENTRY_SIZE]; + + 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); + } + + T(("read terminfo %s", filename)); + + /* grab the header */ + (void) read(fd, buf, 12); + if (LOW_MSB(buf) != MAGIC) + { + close(fd); + return(0); + } + name_size = LOW_MSB(buf + 2); + bool_count = LOW_MSB(buf + 4); + num_count = LOW_MSB(buf + 6); + str_count = LOW_MSB(buf + 8); + str_size = LOW_MSB(buf + 10); + + if (str_size) + { + /* try to allocate space for the string table */ + ptr->str_table = malloc((unsigned)str_size); + if (ptr->str_table == 0) + { + close(fd); + return(0); + } + } + else + str_count = 0; + + /* grab the name */ + read(fd, buf, min(MAX_NAME_SIZE, (unsigned)name_size)); + buf[MAX_NAME_SIZE] = '\0'; + ptr->term_names = calloc(strlen(buf) + 1, sizeof(char)); + if (ptr->term_names == NULL) { + if (str_size) + free(ptr->str_table); + close(fd); + return(0); + } + (void) strcpy(ptr->term_names, buf); + if (name_size > MAX_NAME_SIZE) + lseek(fd, (off_t) (name_size - MAX_NAME_SIZE), 1); + + /* grab the booleans */ + read(fd, ptr->Booleans, min(BOOLCOUNT, (unsigned)bool_count)); + if (bool_count > BOOLCOUNT) + lseek(fd, (off_t) (bool_count - BOOLCOUNT), 1); + else + for (i=bool_count; i < BOOLCOUNT; i++) + ptr->Booleans[i] = 0; + + /* + * If booleans end on an odd byte, skip it. The machine they + * originally wrote terminfo on must have been a 16-bit + * word-oriented machine that would trap out if you tried a + * word access off a 2-byte boundary. + */ + if ((name_size + bool_count) % 2 != 0) + read(fd, buf, 1); + + /* grab the numbers */ + (void) read(fd, buf, min(NUMCOUNT*2, (unsigned)num_count*2)); + for (i = 0; i < min(num_count, NUMCOUNT); i++) + { + if (IS_NEG1(buf + 2*i)) + ptr->Numbers[i] = ABSENT_NUMERIC; + else if (IS_NEG2(buf + 2*i)) + ptr->Numbers[i] = CANCELLED_NUMERIC; + else + ptr->Numbers[i] = LOW_MSB(buf + 2*i); + } + if (num_count > NUMCOUNT) + lseek(fd, (off_t) (2 * (num_count - NUMCOUNT)), 1); + else + for (i=num_count; i < NUMCOUNT; i++) + ptr->Numbers[i] = ABSENT_NUMERIC; + + if (str_count) + { + if (str_count*2 >= MAX_ENTRY_SIZE) + { + close(fd); + return(0); + } + /* grab the string offsets */ + numread = read(fd, buf, (unsigned)(str_count*2)); + if (numread < str_count*2) + { + close(fd); + return(0); + } + for (i = 0; i < numread/2; i++) + { + if (i >= STRCOUNT) + break; + if (IS_NEG1(buf + 2*i)) + ptr->Strings[i] = ABSENT_STRING; + else if (IS_NEG2(buf + 2*i)) + ptr->Strings[i] = CANCELLED_STRING; + else if (LOW_MSB(buf + 2*i) > str_size) + ptr->Strings[i] = ABSENT_STRING; + else + ptr->Strings[i] = (LOW_MSB(buf+2*i) + ptr->str_table); + } + } + + if (str_count > STRCOUNT) + lseek(fd, (off_t) (2 * (str_count - STRCOUNT)), 1); + else + for (i = str_count; i < STRCOUNT; i++) + ptr->Strings[i] = ABSENT_STRING; + + if (str_size) + { + /* finally, grab the string table itself */ + numread = read(fd, ptr->str_table, (unsigned)str_size); + if (numread != str_size) + { + close(fd); + return(0); + } + } + + /* make sure all strings are NUL terminated */ + for (i = str_count; i < STRCOUNT; i++) { + char *p; + + if (VALID_STRING(ptr->Strings[i])) { + for (p = ptr->Strings[i]; p <= ptr->str_table + str_size; p++) + if (*p == '\0') + break; + /* if there is no NUL, ignore the string */ + if (p > ptr->str_table + str_size) + ptr->Strings[i] = ABSENT_STRING; + } + } + + close(fd); + return(1); +} + +/* + * Build a terminfo pathname and try to read the data. Returns 1 on success, + * 0 on failure. + */ +static int _nc_read_tic_entry(char *const filename, + const char *const dir, const char *ttn, TERMTYPE *const tp) +{ +/* maximum safe length of terminfo root directory name */ +#define MAX_TPATH (PATH_MAX - MAX_ALIAS - 6) + + if (strlen(dir) > MAX_TPATH) + return 0; + (void) sprintf(filename, "%s/%s", dir, ttn); + return _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 = malloc(strlen(dirs) + 1)) == NULL) + return(0); + (void) strcpy(list, dirs); + + for (;;) { + int c = *a; + if (c == 0 || c == ':') { + *a = 0; + if ((b + 1) >= a) + b = TERMINFO; + if (_nc_read_tic_entry(filename, b, ttn, tp) == 1) { + code = 1; + break; + } + b = a + 1; + if (c == 0) + break; + } + a++; + } + + free(list); + return(code); +} + +/* + * _nc_read_entry(char *tn, 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 + * of environment variables and terminal type name can be used to + * overrun the file buffer. + */ + +int _nc_read_entry(const char *const tn, char *const filename, TERMTYPE *const tp) +{ +char *envp; +char ttn[MAX_ALIAS + 3]; + + /* truncate the terminal name to prevent dangerous buffer airline */ + (void) sprintf(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 (!issetugid() && (envp = getenv("TERMINFO")) != 0 + && _nc_read_tic_entry(filename, _nc_tic_dir(envp), ttn, tp) == 1) + return 1; + + if (!issetugid() && (envp = _nc_home_terminfo()) != 0) { + if (_nc_read_tic_entry(filename, envp, ttn, tp) == 1) { + return(1); + } + } + + /* this is an ncurses extension */ + if (!issetugid() && (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 +} + diff --git a/lib/libcurses/tinfo/read_termcap.c b/lib/libcurses/tinfo/read_termcap.c new file mode 100644 index 00000000000..de240b648f3 --- /dev/null +++ b/lib/libcurses/tinfo/read_termcap.c @@ -0,0 +1,1122 @@ +/* $OpenBSD: read_termcap.c,v 1.1 1999/01/18 19:10:22 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * Termcap compatibility support + * + * If your OS integrator didn't install a terminfo database, you can call + * _nc_read_termcap_entry() to support reading and translating capabilities + * from the system termcap file. This is a kludge; it will bulk up and slow + * down every program that uses ncurses, and translated termcap entries cannot + * use full terminfo capabilities. Don't use it unless you absolutely have to; + * instead, get your system people to run tic(1) from root on the terminfo + * master included with ncurses to translate it into a terminfo database. + * + * If USE_GETCAP is enabled, we use what is effectively a copy of the 4.4BSD + * getcap code to fetch entries. There are disadvantages to this; mainly that + * getcap(3) does its own resolution, meaning that entries read in in this way + * can't reference the terminfo tree. The only thing it buys is faster startup + * time, getcap(3) is much faster than our tic parser. + */ + +#include <curses.priv.h> + +#include <ctype.h> +#include <term.h> +#include <tic.h> +#include <term_entry.h> + +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif + +MODULE_ID("$From: read_termcap.c,v 1.37 1998/09/19 21:42:14 tom Exp $") + +#ifndef 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 + +#if USE_GETCAP + +#if HAVE_BSD_CGETENT +#define _nc_cgetcap cgetcap +#define _nc_cgetent(buf, oline, db_array, name) cgetent(buf, db_array, name) +#define _nc_cgetmatch cgetmatch +#define _nc_cgetset cgetset +#else +static int _nc_cgetmatch(char *, const char *); +static int _nc_getent(char **, unsigned int *, int *, int, char **, int, const char *, int, char *); +static int _nc_nfcmp(const char *, char *); + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Casey Leedom of Lawrence Livermore National Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94"; */ + +#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() */ +static int gottoprec; /* Flag indicating retrieval of toprecord */ + +/* + * Cgetset() allows the addition of a user specified buffer to be added to the + * database array, in effect "pushing" the buffer on top of the virtual + * database. 0 is returned on success, -1 on failure. + */ +static int +_nc_cgetset(const char *ent) +{ + if (ent == 0) { + FreeIfNeeded(toprec); + toprec = 0; + topreclen = 0; + return (0); + } + topreclen = strlen(ent); + if ((toprec = malloc (topreclen + 1)) == 0) { + errno = ENOMEM; + return (-1); + } + gottoprec = 0; + (void)strcpy(toprec, ent); + return (0); +} + +/* + * Cgetcap searches the capability record buf for the capability cap with type + * `type'. A pointer to the value of cap is returned on success, 0 if the + * requested capability couldn't be found. + * + * Specifying a type of ':' means that nothing should follow cap (:cap:). In + * this case a pointer to the terminating ':' or NUL will be returned if cap is + * found. + * + * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator) + * return 0. + */ +static char * +_nc_cgetcap(char *buf, const char *cap, int type) +{ + register const char *cp; + register char *bp; + + bp = buf; + for (;;) { + /* + * Skip past the current capability field - it's either the + * name field if this is the first time through the loop, or + * the remainder of a field whose name failed to match cap. + */ + for (;;) { + if (*bp == '\0') + return (0); + else if (*bp++ == ':') + break; + } + + /* + * Try to match (cap, type) in buf. + */ + for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++) + continue; + if (*cp != '\0') + continue; + if (*bp == '@') + return (0); + if (type == ':') { + if (*bp != '\0' && *bp != ':') + continue; + return(bp); + } + if (*bp != type) + continue; + bp++; + return (*bp == '@' ? 0 : bp); + } + /* NOTREACHED */ +} + +/* + * Cgetent extracts the capability record name from the NULL terminated file + * array db_array and returns a pointer to a malloc'd copy of it in buf. Buf + * must be retained through all subsequent calls to cgetcap, cgetnum, cgetflag, + * and cgetstr, but may then be freed. + * + * 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 + */ +static int +_nc_cgetent(char **buf, int *oline, char **db_array, const char *name) +{ + unsigned int dummy; + + return (_nc_getent(buf, &dummy, oline, 0, db_array, -1, name, 0, 0)); +} + +/* + * Getent implements the functions of cgetent. If fd is non-negative, + * *db_array has already been opened and fd is the open file descriptor. We + * do this to save time and avoid using up file descriptors for tc= + * recursions. + * + * Getent returns the same success/failure codes as cgetent. On success, a + * pointer to a malloc'd capability record with all tc= capabilities fully + * expanded and its length (not including trailing ASCII NUL) are left in + * *cap and *len. + * + * Basic algorithm: + * + Allocate memory incrementally as needed in chunks of size BFRAG + * for capability buffer. + * + Recurse for each tc=name and interpolate result. Stop when all + * names interpolated, a name can't be found, or depth exceeds + * MAX_RECURSION. + */ +#define DOALLOC(size) (char *)_nc_doalloc(record, size) +static int +_nc_getent( + char **cap, /* termcap-content */ + unsigned int *len, /* length, needed for recursion */ + int *beginning, /* line-number at match */ + int in_array, /* index in 'db_array[] */ + char **db_array, /* list of files to search */ + int fd, + const char *name, + int depth, + char *nfield) +{ + register char *r_end, *rp; + int myfd = FALSE; + char *record = 0; + int tc_not_resolved; + int current; + int lineno; + + /* + * Return with ``loop detected'' error if we've recurred more than + * MAX_RECURSION times. + */ + if (depth > MAX_RECURSION) + return (TC_REF_LOOP); + + /* + * Check if we have a top record from cgetset(). + */ + if (depth == 0 && toprec != 0 && _nc_cgetmatch(toprec, name) == 0) { + if ((record = DOALLOC(topreclen + BFRAG)) == 0) { + errno = ENOMEM; + return (TC_SYS_ERR); + } + (void)strcpy(record, toprec); + rp = record + topreclen + 1; + r_end = rp + BFRAG; + current = in_array; + } else { + int foundit; + + /* + * Allocate first chunk of memory. + */ + if ((record = DOALLOC(BFRAG)) == 0) { + errno = ENOMEM; + return (TC_SYS_ERR); + } + rp = r_end = record + BFRAG; + foundit = FALSE; + + /* + * Loop through database array until finding the record. + */ + for (current = in_array; db_array[current] != 0; current++) { + int eof = FALSE; + + /* + * Open database if not already open. + */ + if (fd >= 0) { + (void)lseek(fd, (off_t)0, SEEK_SET); + } else if ((_nc_access(db_array[current], R_OK) < 0) + || (fd = open(db_array[current], O_RDONLY, 0)) < 0) { + /* No error on unfound file. */ + if (errno == ENOENT) + continue; + free(record); + return (TC_SYS_ERR); + } else { + myfd = TRUE; + } + lineno = 0; + + /* + * Find the requested capability record ... + */ + { + char buf[2048]; + register char *b_end = buf; + register char *bp = buf; + register int c; + + /* + * Loop invariants: + * There is always room for one more character in record. + * R_end always points just past end of record. + * Rp always points just past last character in record. + * B_end always points just past last character in buf. + * Bp always points at next character in buf. + */ + + for (;;) { + int first = lineno + 1; + + /* + * Read in a line implementing (\, newline) + * line continuation. + */ + rp = record; + for (;;) { + if (bp >= b_end) { + int n; + + n = read(fd, buf, sizeof(buf)); + if (n <= 0) { + if (myfd) + (void)close(fd); + if (n < 0) { + free(record); + return (TC_SYS_ERR); + } + fd = -1; + eof = TRUE; + break; + } + b_end = buf+n; + bp = buf; + } + + c = *bp++; + if (c == '\n') { + lineno++; + if (rp == record || *(rp-1) != '\\') + break; + } + *rp++ = c; + + /* + * Enforce loop invariant: if no room + * left in record buffer, try to get + * some more. + */ + if (rp >= r_end) { + unsigned int pos; + size_t newsize; + + pos = rp - record; + newsize = r_end - record + BFRAG; + record = DOALLOC(newsize); + if (record == 0) { + if (myfd) + (void)close(fd); + errno = ENOMEM; + return (TC_SYS_ERR); + } + r_end = record + newsize; + rp = record + pos; + } + } + /* loop invariant lets us do this */ + *rp++ = '\0'; + + /* + * If encountered eof check next file. + */ + if (eof) + break; + + /* + * Toss blank lines and comments. + */ + if (*record == '\0' || *record == '#') + continue; + + /* + * See if this is the record we want ... + */ + if (_nc_cgetmatch(record, name) == 0 + && (nfield == 0 + || !_nc_nfcmp(nfield, record))) { + foundit = TRUE; + *beginning = first; + break; /* found it! */ + } + } + } + if (foundit) + break; + } + + if (!foundit) + return (TC_NOT_FOUND); + } + + /* + * Got the capability record, but now we have to expand all tc=name + * references in it ... + */ + { + register char *newicap, *s; + register int newilen; + unsigned int ilen; + int diff, iret, tclen, oline; + char *icap, *scan, *tc, *tcstart, *tcend; + + /* + * Loop invariants: + * There is room for one more character in record. + * R_end points just past end of record. + * Rp points just past last character in record. + * Scan points at remainder of record that needs to be + * scanned for tc=name constructs. + */ + scan = record; + tc_not_resolved = FALSE; + for (;;) { + if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0) + break; + + /* + * Find end of tc=name and stomp on the trailing `:' + * (if present) so we can use it to call ourselves. + */ + s = tc; + while (*s != '\0') { + if (*s++ == ':') { + *(s - 1) = '\0'; + break; + } + } + tcstart = tc - 3; + tclen = s - tcstart; + tcend = s; + + iret = _nc_getent(&icap, &ilen, &oline, current, db_array, fd, tc, depth+1, 0); + newicap = icap; /* Put into a register. */ + newilen = ilen; + if (iret != TC_SUCCESS) { + /* an error */ + if (iret < TC_NOT_FOUND) { + if (myfd) + (void)close(fd); + free(record); + return (iret); + } + if (iret == TC_UNRESOLVED) + tc_not_resolved = TRUE; + /* couldn't resolve tc */ + if (iret == TC_NOT_FOUND) { + *(s - 1) = ':'; + scan = s - 1; + tc_not_resolved = TRUE; + continue; + } + } + + /* not interested in name field of tc'ed record */ + s = newicap; + while (*s != '\0' && *s++ != ':') + ; + newilen -= s - newicap; + newicap = s; + + /* make sure interpolated record is `:'-terminated */ + s += newilen; + if (*(s-1) != ':') { + *s = ':'; /* overwrite NUL with : */ + newilen++; + } + + /* + * Make sure there's enough room to insert the + * new record. + */ + diff = newilen - tclen; + if (diff >= r_end - rp) { + unsigned int pos, tcpos, tcposend; + size_t newsize; + + pos = rp - record; + newsize = r_end - record + diff + BFRAG; + tcpos = tcstart - record; + tcposend = tcend - record; + record = DOALLOC(newsize); + if (record == 0) { + if (myfd) + (void)close(fd); + free(icap); + errno = ENOMEM; + return (TC_SYS_ERR); + } + r_end = record + newsize; + rp = record + pos; + tcstart = record + tcpos; + tcend = record + tcposend; + } + + /* + * Insert tc'ed record into our record. + */ + s = tcstart + newilen; + memmove(s, tcend, (size_t)(rp - tcend)); + memmove(tcstart, newicap, (size_t)newilen); + rp += diff; + free(icap); + + /* + * Start scan on `:' so next cgetcap works properly + * (cgetcap always skips first field). + */ + scan = s-1; + } + } + + /* + * Close file (if we opened it), give back any extra memory, and + * return capability, length and success. + */ + if (myfd) + (void)close(fd); + *len = rp - record - 1; /* don't count NUL */ + if (r_end > rp) { + if ((record = DOALLOC((size_t)(rp - record))) == 0) { + errno = ENOMEM; + return (TC_SYS_ERR); + } + } + + *cap = record; + if (tc_not_resolved) + return (TC_UNRESOLVED); + return (current); +} + +/* + * Cgetmatch will return 0 if name is one of the names of the capability + * record buf, -1 if not. + */ +static int +_nc_cgetmatch(char *buf, const char *name) +{ + register const char *np; + register char *bp; + + /* + * Start search at beginning of record. + */ + bp = buf; + for (;;) { + /* + * Try to match a record name. + */ + np = name; + for (;;) { + if (*np == '\0') { + if (*bp == '|' || *bp == ':' || *bp == '\0') + return (0); + else + break; + } else if (*bp++ != *np++) { + break; + } + } + + /* + * Match failed, skip to next name in record. + */ + bp--; /* a '|' or ':' may have stopped the match */ + for (;;) { + if (*bp == '\0' || *bp == ':') + return (-1); /* match failed totally */ + else if (*bp++ == '|') + break; /* found next name */ + } + } +} + +/* + * Compare name field of record. + */ +static int +_nc_nfcmp(const char *nf, char *rec) +{ + char *cp, tmp; + int ret; + + for (cp = rec; *cp != ':'; cp++) + ; + + tmp = *(cp + 1); + *(cp + 1) = '\0'; + ret = strcmp(nf, rec); + *(cp + 1) = tmp; + + return (ret); +} +#endif /* HAVE_BSD_CGETENT */ + +/* + * Since ncurses provides its own 'tgetent()', we cannot use the native one. + * So we reproduce the logic to get down to cgetent() -- or our cut-down + * version of that -- to circumvent the problem of configuring against the + * termcap library. + */ +#define USE_BSD_TGETENT 1 + +#if USE_BSD_TGETENT +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93" */ + +#define PBUFSIZ 512 /* max length of filename path */ +#define PVECSIZ 32 /* max number of names in path */ +#define TBUFSIZ (2048*2) + +static char *tbuf; + +/* + * On entry, srcp points to a non ':' character which is the beginning of the + * token, if any. We'll try to return a string that doesn't end with a ':'. + */ +static char * +get_tc_token(char **srcp, int *endp) +{ + int ch; + bool found = FALSE; + char *s, *base; + char *tok = 0; + + *endp = TRUE; + for (s = base = *srcp; *s != '\0'; ) { + ch = *s++; + if (ch == '\\') { + if (*s == '\0') { + break; + } else if (*s++ == '\n') { + while (isspace(*s)) + s++; + } else { + found = TRUE; + } + } else if (ch == ':') { + if (found) { + tok = base; + s[-1] = '\0'; + *srcp = s; + *endp = FALSE; + break; + } + base = s; + } else if (isgraph(ch)) { + found = TRUE; + } + } + + /* malformed entry may end without a ':' */ + if (tok == 0 && found) { + tok = base; + } + + return tok; +} + +static char * +copy_tc_token(char *dst, const char *src, size_t len) +{ + int ch; + + while ((ch = *src++) != '\0') { + if (ch == '\\' && *src == '\n') { + while (isspace(*src)) + src++; + continue; + } + if (--len == 0) { + dst = 0; + break; + } + *dst++ = ch; + } + return dst; +} + +/* + * Get an entry for terminal name in buffer bp from the termcap file. + */ +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; + char **fname; + char *home; + int i; + 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; + + fname = pathvec; + pvec = pathvec; + tbuf = bp; + p = pathbuf; + cp = getenv("TERMCAP"); + + /* + * TERMCAP can have one of two things in it. It can be the name of a + * file to use instead of /etc/termcap. In this case it better start + * with a "/". Or it can be an entry to use so we don't have to read + * the file. In this case it has to already have the newlines crunched + * out. If TERMCAP does not hold a file name then a path of names is + * searched instead. The path is found in the TERMPATH variable, or + * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists. + */ +#define MY_PATH_DEF "/etc/termcap /usr/share/misc/termcap" + if (issetugid()) + strlcpy(pathbuf, MY_PATH_DEF, PBUFSIZ); + else if (!is_pathname(cp)) { /* no TERMCAP or it holds an entry */ + if ((termpath = getenv("TERMPATH")) != 0) { + strlcpy(pathbuf, termpath, PBUFSIZ); + } else { + if ((home = getenv("HOME")) != 0 && + strlen(home) < PBUFSIZ) { /* setup path */ + p += strlen(home); /* path, looking in */ + strcpy(pathbuf, home); /* $HOME first */ + *p++ = '/'; + } /* if no $HOME look in current directory */ + strlcpy(p, ".termcap " MY_PATH_DEF, + (size_t)(PBUFSIZ - (p - pathbuf))); + } + } + else /* user-defined name in TERMCAP */ + strlcpy(pathbuf, cp, PBUFSIZ); /* still can be tokenized */ + + *fname++ = pathbuf; /* tokenize path into vector of names */ + while (*++p) { + if (*p == ' ' || *p == ':') { + *p = '\0'; + while (*++p) + if (*p != ' ' && *p != ':') + break; + if (*p == '\0') + break; + *fname++ = p; + if (fname >= pathvec + PVECSIZ) { + fname--; + break; + } + } + } + *fname = 0; /* mark end of vector */ + if (is_pathname(cp)) { + if (_nc_cgetset(cp) < 0) { + return(TC_SYS_ERR); + } + } + + i = _nc_cgetent(&dummy, lineno, pathvec, name); + + /* ncurses' termcap-parsing routines cannot handle multiple adjacent + * empty fields, and mistakenly use the last valid cap entry instead of + * the first (breaks tc= includes) + */ + if (i >= 0) { + char *pd, *ps, *tok; + int endflag = FALSE; + char *list[1023]; + size_t n, count = 0; + + pd = bp; + ps = dummy; + while (!endflag && (tok = get_tc_token(&ps, &endflag)) != 0) { + bool ignore = FALSE; + + for (n = 1; n < count; n++) { + char *s = list[n]; + if (s[0] == tok[0] + && s[1] == tok[1]) { + ignore = TRUE; + break; + } + } + if (ignore != TRUE) { + list[count++] = tok; + pd = copy_tc_token(pd, tok, TBUFSIZ - (2+pd-bp)); + if (pd == 0) { + i = -1; + break; + } + *pd++ = ':'; + *pd = '\0'; + } + } + } + + FreeIfNeeded(dummy); + FreeIfNeeded(the_source); + the_source = 0; + + /* This is not related to the BSD cgetent(), but to fake up a suitable + * filename for ncurses' error reporting. (If we are not using BSD + * cgetent, then it is the actual filename). + */ + if (i >= 0) { + the_source = malloc(strlen(pathvec[i]) + 1); + if (the_source != 0) + *sourcename = strcpy(the_source, pathvec[i]); + } + + return(i); +} +#endif /* USE_BSD_TGETENT */ +#endif /* USE_GETCAP */ + +#define MAXPATHS 32 + +/* + * Add a filename to the list in 'termpaths[]', checking that we really have + * a right to open the file. + */ +#if !USE_GETCAP +static int add_tc(char *termpaths[], char *path, int count) +{ + if (count < MAXPATHS + && _nc_access(path, R_OK) == 0) + termpaths[count++] = path; + termpaths[count] = 0; + return count; +} +#define ADD_TC(path, count) filecount = add_tc(termpaths, path, count) +#endif /* !USE_GETCAP */ + +int _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) +{ + int found = FALSE; + ENTRY *ep; +#if USE_GETCAP_CACHE + char cwd_buf[PATH_MAX]; +#endif +#if USE_GETCAP + char tc[TBUFSIZ]; + static char *source; + static int lineno; + + /* we're using getcap(3) */ + if (_nc_tgetent(tc, &source, &lineno, tn) < 0) + return (ERR); + + _nc_curr_line = lineno; + _nc_set_source(source); + _nc_read_entry_source((FILE *)0, tc, FALSE, FALSE, NULLHOOK); +#else + /* + * Here is what the 4.4BSD termcap(3) page prescribes: + * + * It will look in the environment for a TERMCAP variable. If found, + * and the value does not begin with a slash, and the terminal type + * name is the same as the environment string TERM, the TERMCAP string + * is used instead of reading a termcap file. If it does begin with a + * slash, the string is used as a path name of the termcap file to + * search. If TERMCAP does not begin with a slash and name is + * different from TERM, tgetent() searches the files $HOME/.termcap and + * /usr/share/misc/termcap, in that order, unless the environment + * variable TERMPATH exists, in which case it specifies a list of file + * pathnames (separated by spaces or colons) to be searched instead. + * + * It goes on to state: + * + * Whenever multiple files are searched and a tc field occurs in the + * requested entry, the entry it names must be found in the same file + * or one of the succeeding files. + * + * However, this restriction is relaxed in ncurses; tc references to + * previous files are permitted. + * + * This routine returns 1 if an entry is found, 0 if not found, and -1 + * if the database is not accessible. + */ + FILE *fp; + char *tc, *termpaths[MAXPATHS]; + int filecount = 0; + bool use_buffer = FALSE; + char tc_buf[1024]; + char pathbuf[PATH_MAX]; + + termpaths[filecount] = 0; + if ((tc = getenv("TERMCAP")) != 0 && (!issetugid() || !is_pathname(tc))) + { + if (is_pathname(tc)) /* interpret as a filename */ + { + ADD_TC(tc, 0); + } + else if (_nc_name_match(tc, tn, "|:")) /* treat as a capability file */ + { + use_buffer = TRUE; + (void) sprintf(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 == ':') + *cp = '\0'; + else if (cp == tc || cp[-1] == '\0') + { + ADD_TC(cp, filecount); + } + } + } + } + else /* normal case */ + { + char envhome[PATH_MAX], *h; + + filecount = 0; + + /* + * 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); + +#define PRIVATE_CAP "%s/.termcap" + + if (!issetugid() && (h = getenv("HOME")) != NULL + && (strlen(h) + sizeof(PRIVATE_CAP)) < PATH_MAX) + { + /* user's .termcap, if any, should override it */ + (void) strcpy(envhome, h); + (void) sprintf(pathbuf, PRIVATE_CAP, envhome); + ADD_TC(pathbuf, filecount); + } + } + + /* parse the sources */ + if (use_buffer) + { + _nc_set_source("TERMCAP"); + + /* + * 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) + { + _nc_set_source(termpaths[i]); + + /* + * Suppress warning messages. Otherwise you + * get 400 lines of crap from archaic termcap + * files as ncurses complains about all the + * obsolete capabilities. + */ + _nc_read_entry_source(fp, (char*)0, FALSE, TRUE, NULLHOOK); + + (void) fclose(fp); + } + } + } +#endif /* USE_GETCAP */ + + if (_nc_head == 0) + return(ERR); + + /* resolve all use references */ + _nc_resolve_uses(); + + /* find a terminal matching tn, if we can */ +#if USE_GETCAP_CACHE + if (getcwd(cwd_buf, sizeof(cwd_buf)) != 0) + { + _nc_set_writedir((char *)0); /* note: this does a chdir */ +#endif + 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). + */ + memcpy(tp, &ep->tterm, sizeof(TERMTYPE)); + ep->tterm.str_table = (char *)0; + + /* + * OK, now try to write the type to user's + * terminfo directory. Next time he loads + * this, it will come through terminfo. + * + * Advantage: Second and subsequent fetches of + * this entry will be very fast. + * + * Disadvantage: After the first time a + * termcap type is loaded by its user, editing + * it in the /etc/termcap file, or in TERMCAP, + * or in a local ~/.termcap, will be + * ineffective unless the terminfo entry is + * explicitly removed. + */ +#if USE_GETCAP_CACHE + (void) _nc_write_entry(tp); +#endif + found = TRUE; + break; + } + } +#if USE_GETCAP_CACHE + chdir(cwd_buf); + } +#endif + + _nc_free_entries(_nc_head); + return(found); +} +#else +extern void _nc_read_termcap(void); + void _nc_read_termcap(void) { } +#endif /* PURE_TERMINFO */ diff --git a/lib/libcurses/tinfo/setbuf.c b/lib/libcurses/tinfo/setbuf.c new file mode 100644 index 00000000000..03a8c896ba0 --- /dev/null +++ b/lib/libcurses/tinfo/setbuf.c @@ -0,0 +1,137 @@ +/* $OpenBSD: setbuf.c,v 1.1 1999/01/18 19:10:22 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + + +/* +** setbuf.c +** +** Support for set_term(), reset_shell_mode(), reset_prog_mode(). +** +*/ + +#include <curses.priv.h> + +MODULE_ID("$From: setbuf.c,v 1.2 1998/12/13 03:48:09 tom Exp $") + +/* + * If the output file descriptor is connected to a tty (the typical case) it + * will probably be line-buffered. Keith Bostic pointed out that we don't want + * this; it hoses people running over networks by forcing out a bunch of small + * packets instead of one big one, so screen updates on ptys look jerky. + * Restore block buffering to prevent this minor lossage. + * + * The buffer size is a compromise. Ideally we'd like a buffer that can hold + * the maximum possible update size (the whole screen plus cup commands to + * change lines as it's painted). On a 66-line xterm this can become + * excessive. So we min it with the amount of data we think we can get through + * two Ethernet packets (maximum packet size - 100 for TCP/IP overhead). + * + * Why two ethernet packets? It used to be one, on the theory that said + * packets define the maximum size of atomic update. But that's less than the + * 2000 chars on a 25 x 80 screen, and we don't want local updates to flicker + * either. Two packet lengths will handle up to a 35 x 80 screen. + * + * The magic '6' is the estimated length of the end-of-line cup sequence to go + * to the next line. It's generous. We used to mess with the buffering in + * init_mvcur() after cost computation, but that lost the sequences emitted by + * init_acs() in setupscreen(). + * + * "The setvbuf function may be used only after the stream pointed to by stream + * has been associated with an open file and before any other operation is + * performed on the stream." (ISO 7.9.5.6.) + * + * Grrrr... + * + * On a lighter note, many implementations do in fact allow an application to + * reset the buffering after it has been written to. We try to do this because + * otherwise we leave stdout in buffered mode after endwin() is called. (This + * also happens with SVr4 curses). + * + * There are pros/cons: + * + * con: + * There is no guarantee that we can reestablish buffering once we've + * dropped it. + * + * We _may_ lose data if the implementation does not coordinate this with + * fflush. + * + * pro: + * An implementation is more likely to refuse to change the buffering than + * to do it in one of the ways mentioned above. + * + * The alternative is to have the application try to change buffering + * itself, which is certainly no improvement. + * + * Just in case it does not work well on a particular system, the calls to + * change buffering are all via the macro NC_BUFFERED. + */ +void _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 (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 = malloc(buf_len)) == NULL) + return; + SP->_setbuf = buf_ptr; + /* Don't try to free this! */ + } + } else { + buf_len = 0; + buf_ptr = 0; + } + +#if HAVE_SETVBUF +#ifdef SETVBUF_REVERSED /* pre-svr3? */ + (void) setvbuf(ofp, buf_ptr, buf_len, buf_len ? _IOFBF : _IOLBF); +#else + (void) setvbuf(ofp, buf_ptr, buf_len ? _IOFBF : _IOLBF, buf_len); +#endif +#elif HAVE_SETBUFFER + (void) setbuffer(ofp, buf_ptr, (int)buf_len); +#endif + +#endif /* HAVE_SETVBUF || HAVE_SETBUFFER */ +} diff --git a/lib/libcurses/tinfo/write_entry.c b/lib/libcurses/tinfo/write_entry.c new file mode 100644 index 00000000000..22c20151790 --- /dev/null +++ b/lib/libcurses/tinfo/write_entry.c @@ -0,0 +1,469 @@ +/* $OpenBSD: write_entry.c,v 1.1 1999/01/18 19:10:23 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + + +/* + * write_entry.c -- write a terminfo structure onto the file system + */ + +#include <curses.priv.h> + +#include <sys/stat.h> + +#include <tic.h> +#include <term.h> +#include <term_entry.h> + +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR) +#endif + +MODULE_ID("$From: write_entry.c,v 1.34 1998/12/20 02:49:27 tom Exp $") + +static int total_written; + +static int write_object(FILE *, TERMTYPE *); + +static void write_file(char *filename, TERMTYPE *tp) +{ + FILE *fp = (_nc_access(filename, W_OK) == 0) ? fopen(filename, "wb") : 0; + if (fp == 0) { + perror(filename); + _nc_syserr_abort("can't open %s/%s", _nc_tic_dir(0), filename); + } + DEBUG(1, ("Created %s", filename)); + + if (write_object(fp, tp) == ERR) { + _nc_syserr_abort("error writing %s/%s", _nc_tic_dir(0), filename); + } + fclose(fp); +} + +/* + * make_directory(char *path) + * + * Make a directory if it doesn't exist. + */ +static int make_directory(const char *path) +{ +int rc; +struct stat statbuf; +char fullpath[PATH_MAX]; +const char *destination = _nc_tic_dir(0); + + if (path == destination || *path == '/') { + if (strlen(path) + 1 > sizeof(fullpath)) + return(-1); + (void)strcpy(fullpath, path); + } else { + if (strlen(destination) + strlen(path) + 2 > sizeof(fullpath)) + return(-1); + (void)sprintf(fullpath, "%s/%s", destination, path); + } + + 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 */ + } + } + return rc; +} + +void _nc_set_writedir(char *dir) +/* set the write directory for compiled entries */ +{ + const char *destination; + char actual[PATH_MAX]; + + if (dir != 0) + (void) _nc_tic_dir(dir); + else if (getenv("TERMINFO") != NULL) + (void) _nc_tic_dir(getenv("TERMINFO")); + + destination = _nc_tic_dir(0); + if (make_directory(destination) < 0) + { + char *home = _nc_home_terminfo(); + + if (home != 0) { + + if (make_directory(destination) < 0) + _nc_err_abort("%s: permission denied (errno %d)", + destination, errno); + + destination = home; + } + } + + /* + * Note: because of this code, this logic should be exercised + * *once only* per run. + */ + if (chdir(_nc_tic_dir(destination)) < 0 + || getcwd(actual, sizeof(actual)) == 0) + _nc_err_abort("%s: not a directory", destination); + _nc_keep_tic_dir(strcpy(malloc(strlen(actual)+1), 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; + + 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 + * break it up into first-name and all-but-last-name + * creat(first-name) + * write object information to first-name + * close(first-name) + * for each name in all-but-last-name + * link to first-name + * + * Using 'time()' to obtain a reference for file timestamps is unreliable, + * e.g., with NFS, because the filesystem may have a different time + * reference. We check for pre-existence of links by latching the first + * timestamp from a file that we create. + * + * The _nc_warning() calls will report a correct line number only if + * _nc_curr_line is properly set before the write_entry() call. + */ + +void _nc_write_entry(TERMTYPE *const tp) +{ +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]; +#endif /* USE_SYMLINKS */ +static int call_count; +static time_t start_time; /* time at start of writes */ + + if (call_count++ == 0) { + start_time = 0; + } + + (void) strcpy(name_list, tp->term_names); + DEBUG(7, ("Name list = '%s'", name_list)); + + first_name = name_list; + + ptr = &name_list[strlen(name_list) - 1]; + other_names = ptr + 1; + + while (ptr > name_list && *ptr != '|') + ptr--; + + if (ptr != name_list) { + *ptr = '\0'; + + for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++) + continue; + + if (*ptr == '\0') + other_names = ptr; + else { + *ptr = '\0'; + other_names = ptr + 1; + } + } + + DEBUG(7, ("First name = '%s'", first_name)); + DEBUG(7, ("Other names = '%s'", other_names)); + + _nc_set_type(first_name); + + if (strlen(first_name) > sizeof(filename)-3) + _nc_warning("terminal name too long."); + + sprintf(filename, "%c/%s", first_name[0], first_name); + + /* + * Has this primary name been written since the first call to + * write_entry()? If so, the newer write will step on the older, + * so warn the user. + */ + if (start_time > 0 && + stat(filename, &statbuf) >= 0 + && statbuf.st_mtime >= start_time) + { + _nc_warning("name multiply defined."); + } + + check_writeable(first_name[0]); + write_file(filename, tp); + + if (start_time == 0) { + if (stat(filename, &statbuf) < 0 + || (start_time = statbuf.st_mtime) == 0) { + _nc_syserr_abort("error obtaining time from %s/%s", + _nc_tic_dir(0), filename); + } + } + while (*other_names != '\0') { + ptr = other_names++; + while (*other_names != '|' && *other_names != '\0') + other_names++; + + if (*other_names != '\0') + *(other_names++) = '\0'; + + if (strlen(ptr) > sizeof(linkname)-3) { + _nc_warning("terminal alias %s too long.", ptr); + continue; + } + if (strchr(ptr, '/') != 0) { + _nc_warning("cannot link alias %s.", ptr); + continue; + } + + check_writeable(ptr[0]); + sprintf(linkname, "%c/%s", ptr[0], ptr); + + if (strcmp(filename, linkname) == 0) { + _nc_warning("self-synonym ignored"); + } + else if (stat(linkname, &statbuf) >= 0 && + statbuf.st_mtime < start_time) + { + _nc_warning("alias %s multiply defined.", ptr); + } + else if (_nc_access(linkname, W_OK) == 0) +#if HAVE_LINK + { + int code; +#if USE_SYMLINKS + strcpy(symlinkname, "../"); + strncat(symlinkname, filename, sizeof(symlinkname) - 4); + symlinkname[sizeof(symlinkname) - 1] = '\0'; +#endif /* USE_SYMLINKS */ +#if HAVE_REMOVE + code = remove(linkname); +#else + code = unlink(linkname); +#endif + if (code != 0 && errno == ENOENT) + code = 0; +#if USE_SYMLINKS + if (symlink(symlinkname, linkname) < 0) +#else + if (link(filename, linkname) < 0) +#endif /* USE_SYMLINKS */ + { + /* + * If there wasn't anything there, and we cannot + * link to the target because it is the same as the + * target, then the source must be on a filesystem + * that uses caseless filenames, such as Win32, etc. + */ + if (code == 0 && errno == EEXIST) + _nc_warning("can't link %s to %s", filename, linkname); + else if (code == 0 && errno == EPERM) + write_file(linkname, tp); + else + _nc_syserr_abort("can't link %s to %s", filename, linkname); + } + else + { + DEBUG(1, ("Linked %s", linkname)); + } + } +#else /* just make copies */ + write_file(linkname, tp); +#endif /* HAVE_LINK */ + } +} + +#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) + +static int write_object(FILE *fp, TERMTYPE *tp) +{ +char *namelist; +size_t namelen, boolmax, nummax, strmax; +char zero = '\0'; +size_t i; +short nextfree; +short offsets[STRCOUNT]; +unsigned char buf[MAX_ENTRY_SIZE]; + + namelist = tp->term_names; + namelen = strlen(namelist) + 1; + + boolmax = 0; + for (i = 0; i < BOOLWRITE; i++) + if (tp->Booleans[i]) + boolmax = i+1; + + nummax = 0; + for (i = 0; i < NUMWRITE; i++) + if (tp->Numbers[i] != ABSENT_NUMERIC) + nummax = i+1; + + strmax = 0; + for (i = 0; i < STRWRITE; i++) + if (tp->Strings[i] != ABSENT_STRING) + strmax = i+1; + + nextfree = 0; + for (i = 0; i < strmax; i++) + if (tp->Strings[i] == ABSENT_STRING) + offsets[i] = -1; + else if (tp->Strings[i] == CANCELLED_STRING) + offsets[i] = -2; + else + { + offsets[i] = nextfree; + nextfree += strlen(tp->Strings[i]) + 1; + } + + /* fill in the header */ + LITTLE_ENDIAN(buf, MAGIC); + LITTLE_ENDIAN(buf+2, min(namelen, MAX_NAME_SIZE + 1)); + LITTLE_ENDIAN(buf+4, boolmax); + LITTLE_ENDIAN(buf+6, nummax); + LITTLE_ENDIAN(buf+8, strmax); + LITTLE_ENDIAN(buf+10, nextfree); + + /* write out the header */ + if (fwrite(buf, 12, 1, fp) != 1 + || fwrite(namelist, sizeof(char), (size_t)namelen, fp) != namelen + || fwrite(tp->Booleans, sizeof(char), (size_t)boolmax, fp) != boolmax) + return(ERR); + + /* the even-boundary padding byte */ + if ((namelen+boolmax) % 2 != 0 && fwrite(&zero, sizeof(char), 1, fp) != 1) + return(ERR); + +#ifdef SHOWOFFSET + (void) fprintf(stderr, "Numerics begin at %04lx\n", ftell(fp)); +#endif /* SHOWOFFSET */ + + /* the numerics */ + for (i = 0; i < nummax; i++) + { + if (tp->Numbers[i] == -1) /* HI/LO won't work */ + buf[2*i] = buf[2*i + 1] = 0377; + else if (tp->Numbers[i] == -2) /* HI/LO won't work */ + buf[2*i] = 0376, buf[2*i + 1] = 0377; + else + LITTLE_ENDIAN(buf + 2*i, tp->Numbers[i]); + } + if (fwrite(buf, 2, (size_t)nummax, fp) != nummax) + return(ERR); + +#ifdef SHOWOFFSET + (void) fprintf(stderr, "String offets begin at %04lx\n", ftell(fp)); +#endif /* SHOWOFFSET */ + + /* the string offsets */ + for (i = 0; i < strmax; i++) + if (offsets[i] == -1) /* HI/LO won't work */ + buf[2*i] = buf[2*i + 1] = 0377; + else if (offsets[i] == -2) /* HI/LO won't work */ + { + buf[2*i] = 0376; + buf[2*i + 1] = 0377; + } + else + LITTLE_ENDIAN(buf + 2*i, offsets[i]); + if (fwrite(buf, 2, (size_t)strmax, fp) != strmax) + return(ERR); + +#ifdef SHOWOFFSET + (void) fprintf(stderr, "String table begins at %04lx\n", ftell(fp)); +#endif /* SHOWOFFSET */ + + /* the strings */ + for (i = 0; i < strmax; i++) + if (tp->Strings[i] != ABSENT_STRING && tp->Strings[i] != CANCELLED_STRING) + if (fwrite(tp->Strings[i], sizeof(char), strlen(tp->Strings[i]) + 1, fp) != strlen(tp->Strings[i]) + 1) + return(ERR); + + total_written++; + return(OK); +} + +/* + * Returns the total number of entries written by this process + */ +int _nc_tic_written(void) +{ + return total_written; +} |