]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/tinfo/parse_entry.c
ncurses 5.7 - patch 20090711
[ncurses.git] / ncurses / tinfo / parse_entry.c
index 24bf3c37f584bd9bd6edb0d66e60e8ba936bfb2a..6e59775b7bd70831fc54271e8d89670402127057 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -29,6 +29,7 @@
 /****************************************************************************
  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
  ****************************************************************************/
 
 /*
  *     from the input stream.
  */
 
+#define __INTERNAL_CAPS_VISIBLE
 #include <curses.priv.h>
 
 #include <ctype.h>
 #include <tic.h>
-#define __INTERNAL_CAPS_VISIBLE
 #include <term_entry.h>
 
-MODULE_ID("$Id: parse_entry.c,v 1.48 2000/10/03 09:38:48 tom Exp $")
+MODULE_ID("$Id: parse_entry.c,v 1.71 2009/07/11 18:14:21 tom Exp $")
 
 #ifdef LINT
 static short const parametrized[] =
@@ -83,13 +84,13 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type)
     case NUMBER:
        first = tp->ext_Booleans;
        last = tp->ext_Numbers + first;
-       offset = tp->ext_Booleans + tp->ext_Numbers;
+       offset = (unsigned) (tp->ext_Booleans + tp->ext_Numbers);
        tindex = tp->num_Numbers;
        break;
     case STRING:
-       first = tp->ext_Booleans + tp->ext_Numbers;
+       first = (unsigned) (tp->ext_Booleans + tp->ext_Numbers);
        last = tp->ext_Strings + first;
-       offset = tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings;
+       offset = (unsigned) (tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings);
        tindex = tp->num_Strings;
        break;
     case CANCEL:
@@ -136,27 +137,31 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type)
            break;
        }
     }
+
+#define for_each_value(max) \
+       for (last = (unsigned) (max - 1); last > tindex; last--)
+
     if (!found) {
        switch (token_type) {
        case BOOLEAN:
-           tp->ext_Booleans += 1;
-           tp->num_Booleans += 1;
-           tp->Booleans = typeRealloc(char, tp->num_Booleans, tp->Booleans);
-           for (last = tp->num_Booleans - 1; last > tindex; last--)
+           tp->ext_Booleans++;
+           tp->num_Booleans++;
+           tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans);
+           for_each_value(tp->num_Booleans)
                tp->Booleans[last] = tp->Booleans[last - 1];
            break;
        case NUMBER:
-           tp->ext_Numbers += 1;
-           tp->num_Numbers += 1;
+           tp->ext_Numbers++;
+           tp->num_Numbers++;
            tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers);
-           for (last = tp->num_Numbers - 1; last > tindex; last--)
+           for_each_value(tp->num_Numbers)
                tp->Numbers[last] = tp->Numbers[last - 1];
            break;
        case STRING:
-           tp->ext_Strings += 1;
-           tp->num_Strings += 1;
+           tp->ext_Strings++;
+           tp->num_Strings++;
            tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings);
-           for (last = tp->num_Strings - 1; last > tindex; last--)
+           for_each_value(tp->num_Strings)
                tp->Strings[last] = tp->Strings[last - 1];
            break;
        }
@@ -169,7 +174,7 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type)
 
     temp.nte_name = tp->ext_Names[offset];
     temp.nte_type = token_type;
-    temp.nte_index = tindex;
+    temp.nte_index = (short) tindex;
     temp.nte_link = -1;
 
     return &temp;
@@ -188,21 +193,26 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type)
  *     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
+ *             check for existence and type-correctness
  *             enter cap into structure
  *             if STRING
  *                 save string in entry's string table
  *     push back token
  */
 
-int
+#define BAD_TC_USAGE if (!bad_tc_usage) \
+       { bad_tc_usage = TRUE; \
+        _nc_warning("Legacy termcap allows only a trailing tc= clause"); }
+
+NCURSES_EXPORT(int)
 _nc_parse_entry(struct entry *entryp, int literal, bool silent)
 {
     int token_type;
     struct name_table_entry const *entry_ptr;
     char *ptr, *base;
+    bool bad_tc_usage = FALSE;
 
-    token_type = _nc_get_token();
+    token_type = _nc_get_token(silent);
 
     if (token_type == EOF)
        return (EOF);
@@ -216,15 +226,32 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
     entryp->startline = _nc_start_line;
     DEBUG(2, ("Comment range is %ld to %ld", entryp->cstart, entryp->cend));
 
-    /* junk the 2-character termcap name, if present */
+    /*
+     * Strip off the 2-character termcap name, if present.  Originally termcap
+     * used that as an indexing aid.  We can retain 2-character terminfo names,
+     * but note that they would be lost if we translate to/from termcap.  This
+     * feature is supposedly obsolete since "newer" BSD implementations do not
+     * use it; however our reference for this feature is SunOS 4.x, which
+     * implemented it.  Note that the resulting terminal type was never the
+     * 2-character name, but was instead the first alias after that.
+     */
     ptr = _nc_curr_token.tk_name;
-    if (ptr[2] == '|') {
-       ptr = _nc_curr_token.tk_name + 3;
-       _nc_curr_token.tk_name[2] = '\0';
+    if (_nc_syntax == SYN_TERMCAP
+#if NCURSES_XNAMES
+       && !_nc_user_definable
+#endif
+       ) {
+       if (ptr[2] == '|') {
+           ptr += 3;
+           _nc_curr_token.tk_name[2] = '\0';
+       }
     }
 
     entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr);
 
+    if (entryp->tterm.str_table == 0)
+       return (ERR);
+
     DEBUG(1, ("Starting '%s'", ptr));
 
     /*
@@ -242,24 +269,28 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
                        (base == entryp->tterm.term_names)
                        ? "primary name"
                        : "alias",
-                       ptr - base, base);
+                       (int) (ptr - base), base);
        }
     }
 
     entryp->nuses = 0;
 
-    for (token_type = _nc_get_token();
+    for (token_type = _nc_get_token(silent);
         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) {
+        token_type = _nc_get_token(silent)) {
+       bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0);
+       bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0);
+       if (is_use || is_tc) {
            entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring);
            entryp->uses[entryp->nuses].line = _nc_curr_line;
            entryp->nuses++;
+           if (entryp->nuses > 1 && is_tc) {
+               BAD_TC_USAGE
+           }
        } else {
            /* normal token lookup */
            entry_ptr = _nc_find_entry(_nc_curr_token.tk_name,
-                                      _nc_syntax ? _nc_cap_hash_table : _nc_info_hash_table);
+                                      _nc_get_hash_table(_nc_syntax));
 
            /*
             * Our kluge to handle aliasing.  The reason it's done
@@ -273,7 +304,10 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
                const struct alias *ap;
 
                if (_nc_syntax == SYN_TERMCAP) {
-                   for (ap = _nc_capalias_table; ap->from; ap++)
+                   if (entryp->nuses != 0) {
+                       BAD_TC_USAGE
+                   }
+                   for (ap = _nc_get_alias_table(TRUE); ap->from; ap++)
                        if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) {
                            if (ap->to == (char *) 0) {
                                _nc_warning("%s (%s termcap extension) ignored",
@@ -281,14 +315,15 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
                                goto nexttok;
                            }
 
-                           entry_ptr = _nc_find_entry(ap->to, _nc_cap_hash_table);
+                           entry_ptr = _nc_find_entry(ap->to,
+                                                      _nc_get_hash_table(TRUE));
                            if (entry_ptr && !silent)
                                _nc_warning("%s (%s termcap extension) aliased to %s",
                                            ap->from, ap->source, ap->to);
                            break;
                        }
                } else {        /* if (_nc_syntax == SYN_TERMINFO) */
-                   for (ap = _nc_infoalias_table; ap->from; ap++)
+                   for (ap = _nc_get_alias_table(FALSE); ap->from; ap++)
                        if (strcmp(ap->from, _nc_curr_token.tk_name) == 0) {
                            if (ap->to == (char *) 0) {
                                _nc_warning("%s (%s terminfo extension) ignored",
@@ -296,7 +331,8 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
                                goto nexttok;
                            }
 
-                           entry_ptr = _nc_find_entry(ap->to, _nc_info_hash_table);
+                           entry_ptr = _nc_find_entry(ap->to,
+                                                      _nc_get_hash_table(FALSE));
                            if (entry_ptr && !silent)
                                _nc_warning("%s (%s terminfo extension) aliased to %s",
                                            ap->from, ap->source, ap->to);
@@ -343,23 +379,26 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
                 * type, this will do the job.
                 */
 
-               /* tell max_attributes from arrow_key_map */
-               if (token_type == NUMBER && !strcmp("ma", _nc_curr_token.tk_name))
+               if (token_type == NUMBER
+                   && !strcmp("ma", _nc_curr_token.tk_name)) {
+                   /* tell max_attributes from arrow_key_map */
                    entry_ptr = _nc_find_type_entry("ma", NUMBER,
-                                                   _nc_get_table(_nc_syntax
-                                                                 != 0));
+                                                   _nc_syntax != 0);
+                   assert(entry_ptr != 0);
 
-               /* map terminfo's string MT to MT */
-               else if (token_type == STRING && !strcmp("MT", _nc_curr_token.tk_name))
+               } else if (token_type == STRING
+                          && !strcmp("MT", _nc_curr_token.tk_name)) {
+                   /* map terminfo's string MT to MT */
                    entry_ptr = _nc_find_type_entry("MT", STRING,
-                                                   _nc_get_table(_nc_syntax
-                                                                 != 0));
+                                                   _nc_syntax != 0);
+                   assert(entry_ptr != 0);
 
-               /* treat strings without following "=" as empty strings */
-               else if (token_type == BOOLEAN && entry_ptr->nte_type == STRING)
+               } else if (token_type == BOOLEAN
+                          && entry_ptr->nte_type == STRING) {
+                   /* treat strings without following "=" as empty strings */
                    token_type = STRING;
-               /* we couldn't recover; skip this token */
-               else {
+               } else {
+                   /* we couldn't recover; skip this token */
                    if (!silent) {
                        const char *type_name;
                        switch (entry_ptr->nte_type) {
@@ -407,7 +446,7 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
 
            case NUMBER:
                entryp->tterm.Numbers[entry_ptr->nte_index] =
-                   _nc_curr_token.tk_valnumber;
+                   (short) _nc_curr_token.tk_valnumber;
                break;
 
            case STRING:
@@ -422,7 +461,7 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
            default:
                if (!silent)
                    _nc_warning("unknown token type");
-               _nc_panic_mode((_nc_syntax == SYN_TERMCAP) ? ':' : ',');
+               _nc_panic_mode((char) ((_nc_syntax == SYN_TERMCAP) ? ':' : ','));
                continue;
            }
        }                       /* end else cur_token.name != "use" */
@@ -442,7 +481,7 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
     if (!literal) {
        if (_nc_syntax == SYN_TERMCAP) {
            bool has_base_entry = FALSE;
-           int i;
+           unsigned i;
 
            /*
             * Don't insert defaults if this is a `+' entry meant only
@@ -464,12 +503,12 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent)
        } else
            postprocess_terminfo(&entryp->tterm);
     }
-    _nc_wrap_entry(entryp);
+    _nc_wrap_entry(entryp, FALSE);
 
     return (OK);
 }
 
-int
+NCURSES_EXPORT(int)
 _nc_capcmp(const char *s, const char *t)
 /* compare two string capabilities, stripping out padding */
 {
@@ -481,15 +520,21 @@ _nc_capcmp(const char *s, const char *t)
     for (;;) {
        if (s[0] == '$' && s[1] == '<') {
            for (s += 2;; s++)
-               if (!(isdigit(*s) || *s == '.' || *s == '*' || *s == '/' ||
-                     *s == '>'))
+               if (!(isdigit(UChar(*s))
+                     || *s == '.'
+                     || *s == '*'
+                     || *s == '/'
+                     || *s == '>'))
                    break;
        }
 
        if (t[0] == '$' && t[1] == '<') {
            for (t += 2;; t++)
-               if (!(isdigit(*t) || *t == '.' || *t == '*' || *t == '/' ||
-                     *t == '>'))
+               if (!(isdigit(UChar(*t))
+                     || *t == '.'
+                     || *t == '*'
+                     || *t == '/'
+                     || *t == '>'))
                    break;
        }
 
@@ -507,19 +552,19 @@ _nc_capcmp(const char *s, const char *t)
 }
 
 static void
-append_acs0(string_desc *dst, int code, int src)
+append_acs0(string_desc * dst, int code, int src)
 {
     if (src != 0) {
        char temp[3];
-       temp[0] = code;
-       temp[1] = src;
+       temp[0] = (char) code;
+       temp[1] = (char) src;
        temp[2] = 0;
        _nc_safe_strcat(dst, temp);
     }
 }
 
 static void
-append_acs(string_desc *dst, int code, char *src)
+append_acs(string_desc * dst, int code, char *src)
 {
     if (src != 0 && strlen(src) == 1) {
        append_acs0(dst, code, *src);
@@ -587,7 +632,7 @@ static const char C_HT[] = "\t";
 #define CUR tp->
 
 static void
-postprocess_termcap(TERMTYPE * tp, bool has_base)
+postprocess_termcap(TERMTYPE *tp, bool has_base)
 {
     char buf[MAX_LINE * 2 + 2];
     string_desc result;
@@ -657,12 +702,12 @@ postprocess_termcap(TERMTYPE * tp, bool has_base)
            } else if (PRESENT(carriage_return) && PRESENT(scroll_forward)) {
                _nc_str_init(&result, buf, sizeof(buf));
                if (_nc_safe_strcat(&result, carriage_return)
-                && _nc_safe_strcat(&result, scroll_forward))
+                   && _nc_safe_strcat(&result, scroll_forward))
                    newline = _nc_save_str(buf);
            } else if (PRESENT(carriage_return) && PRESENT(cursor_down)) {
                _nc_str_init(&result, buf, sizeof(buf));
                if (_nc_safe_strcat(&result, carriage_return)
-                && _nc_safe_strcat(&result, cursor_down))
+                   && _nc_safe_strcat(&result, cursor_down))
                    newline = _nc_save_str(buf);
            }
        }
@@ -745,13 +790,14 @@ postprocess_termcap(TERMTYPE * tp, bool has_base)
        for (base = other_non_function_keys;
             (cp = strchr(base, ',')) != 0;
             base = cp + 1) {
-           size_t len = cp - base;
+           size_t len = (unsigned) (cp - base);
 
-           for (ap = ko_xlate; ap->from; ap++)
+           for (ap = ko_xlate; ap->from; ap++) {
                if (len == strlen(ap->from)
                    && strncmp(ap->from, base, len) == 0)
                    break;
-           if (!ap->to) {
+           }
+           if (!(ap->from && ap->to)) {
                _nc_warning("unknown capability `%.*s' in ko string",
                            (int) len, base);
                continue;
@@ -760,8 +806,8 @@ postprocess_termcap(TERMTYPE * tp, bool has_base)
 
            /* now we know we found a match in ko_table, so... */
 
-           from_ptr = _nc_find_entry(ap->from, _nc_cap_hash_table);
-           to_ptr = _nc_find_entry(ap->to, _nc_info_hash_table);
+           from_ptr = _nc_find_entry(ap->from, _nc_get_hash_table(TRUE));
+           to_ptr = _nc_find_entry(ap->to, _nc_get_hash_table(FALSE));
 
            if (!from_ptr || !to_ptr)   /* should never happen! */
                _nc_err_abort("ko translation table is invalid, I give up");
@@ -813,13 +859,15 @@ postprocess_termcap(TERMTYPE * tp, bool has_base)
        }
     }
 
-    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);
+    if (!has_base) {
+       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);
+       }
     }
 
     /*
@@ -841,17 +889,17 @@ postprocess_termcap(TERMTYPE * tp, bool has_base)
        _nc_str_init(&result, buf2, sizeof(buf2));
        _nc_safe_strcat(&result, acs_chars);
 
-       append_acs (&result, 'j', acs_lrcorner);
-       append_acs (&result, 'k', acs_urcorner);
-       append_acs (&result, 'l', acs_ulcorner);
-       append_acs (&result, 'm', acs_llcorner);
-       append_acs (&result, 'n', acs_plus);
-       append_acs (&result, 'q', acs_hline);
-       append_acs (&result, 't', acs_ltee);
-       append_acs (&result, 'u', acs_rtee);
-       append_acs (&result, 'v', acs_btee);
-       append_acs (&result, 'w', acs_ttee);
-       append_acs (&result, 'x', acs_vline);
+       append_acs(&result, 'j', acs_lrcorner);
+       append_acs(&result, 'k', acs_urcorner);
+       append_acs(&result, 'l', acs_ulcorner);
+       append_acs(&result, 'm', acs_llcorner);
+       append_acs(&result, 'n', acs_plus);
+       append_acs(&result, 'q', acs_hline);
+       append_acs(&result, 't', acs_ltee);
+       append_acs(&result, 'u', acs_rtee);
+       append_acs(&result, 'v', acs_btee);
+       append_acs(&result, 'w', acs_ttee);
+       append_acs(&result, 'x', acs_vline);
 
        if (buf2[0]) {
            acs_chars = _nc_save_str(buf2);
@@ -860,13 +908,12 @@ postprocess_termcap(TERMTYPE * tp, bool has_base)
     } else if (acs_chars == 0
               && enter_alt_charset_mode != 0
               && exit_alt_charset_mode != 0) {
-       acs_chars =
-           _nc_save_str("``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~");
+       acs_chars = _nc_save_str(VT_ACSC);
     }
 }
 
 static void
-postprocess_terminfo(TERMTYPE * tp)
+postprocess_terminfo(TERMTYPE *tp)
 {
     /*
      * TERMINFO-TO-TERMINFO MAPPINGS FOR SOURCE TRANSLATION
@@ -883,17 +930,17 @@ postprocess_terminfo(TERMTYPE * tp)
        _nc_str_init(&result, buf2, sizeof(buf2));
        _nc_safe_strcat(&result, acs_chars);
 
-       append_acs0 (&result, 'l', box_chars_1[0]);     /* ACS_ULCORNER */
-       append_acs0 (&result, 'q', box_chars_1[1]);     /* ACS_HLINE */
-       append_acs0 (&result, 'k', box_chars_1[2]);     /* ACS_URCORNER */
-       append_acs0 (&result, 'x', box_chars_1[3]);     /* ACS_VLINE */
-       append_acs0 (&result, 'j', box_chars_1[4]);     /* ACS_LRCORNER */
-       append_acs0 (&result, 'm', box_chars_1[5]);     /* ACS_LLCORNER */
-       append_acs0 (&result, 'w', box_chars_1[6]);     /* ACS_TTEE */
-       append_acs0 (&result, 'u', box_chars_1[7]);     /* ACS_RTEE */
-       append_acs0 (&result, 'v', box_chars_1[8]);     /* ACS_BTEE */
-       append_acs0 (&result, 't', box_chars_1[9]);     /* ACS_LTEE */
-       append_acs0 (&result, 'n', box_chars_1[10]);    /* ACS_PLUS */
+       append_acs0(&result, 'l', box_chars_1[0]);      /* ACS_ULCORNER */
+       append_acs0(&result, 'q', box_chars_1[1]);      /* ACS_HLINE */
+       append_acs0(&result, 'k', box_chars_1[2]);      /* ACS_URCORNER */
+       append_acs0(&result, 'x', box_chars_1[3]);      /* ACS_VLINE */
+       append_acs0(&result, 'j', box_chars_1[4]);      /* ACS_LRCORNER */
+       append_acs0(&result, 'm', box_chars_1[5]);      /* ACS_LLCORNER */
+       append_acs0(&result, 'w', box_chars_1[6]);      /* ACS_TTEE */
+       append_acs0(&result, 'u', box_chars_1[7]);      /* ACS_RTEE */
+       append_acs0(&result, 'v', box_chars_1[8]);      /* ACS_BTEE */
+       append_acs0(&result, 't', box_chars_1[9]);      /* ACS_LTEE */
+       append_acs0(&result, 'n', box_chars_1[10]);     /* ACS_PLUS */
 
        if (buf2[0]) {
            acs_chars = _nc_save_str(buf2);