]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/tinfo/db_iterator.c
ncurses 6.2 - patch 20201227
[ncurses.git] / ncurses / tinfo / db_iterator.c
index 90e73d6bc5990d75160bebe28003389a1bb39389..f0726682c40304151005374a458be949c48238fb 100644 (file)
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2006-2011,2012 Free Software Foundation, Inc.              *
+ * Copyright 2018,2020 Thomas E. Dickey                                     *
+ * Copyright 2006-2016,2017 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            *
@@ -43,7 +44,7 @@
 #include <hashed_db.h>
 #endif
 
-MODULE_ID("$Id: db_iterator.c,v 1.35 2012/08/25 21:55:00 tom Exp $")
+MODULE_ID("$Id: db_iterator.c,v 1.48 2020/02/02 23:34:34 tom Exp $")
 
 #define HaveTicDirectory _nc_globals.have_tic_directory
 #define KeepTicDirectory _nc_globals.keep_tic_directory
@@ -72,15 +73,18 @@ check_existence(const char *name, struct stat *sb)
 {
     bool result = FALSE;
 
-    if (stat(name, sb) == 0
-       && (S_ISDIR(sb->st_mode) || S_ISREG(sb->st_mode))) {
+    if (quick_prefix(name)) {
+       result = TRUE;
+    } else if (stat(name, sb) == 0
+              && (S_ISDIR(sb->st_mode)
+                  || (S_ISREG(sb->st_mode) && sb->st_size))) {
        result = TRUE;
     }
 #if USE_HASHED_DB
     else if (strlen(name) < PATH_MAX - sizeof(DBM_SUFFIX)) {
        char temp[PATH_MAX];
        _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "%s%s", name, DBM_SUFFIX);
-       if (stat(temp, sb) == 0 && S_ISREG(sb->st_mode)) {
+       if (stat(temp, sb) == 0 && S_ISREG(sb->st_mode) && sb->st_size) {
            result = TRUE;
        }
     }
@@ -88,6 +92,27 @@ check_existence(const char *name, struct stat *sb)
     return result;
 }
 
+/*
+ * Trim newlines (and backslashes preceding those) and tab characters to
+ * help simplify scripting of the quick-dump feature.  Leave spaces and
+ * other backslashes alone.
+ */
+static void
+trim_formatting(char *source)
+{
+    char *target = source;
+    char ch;
+
+    while ((ch = *source++) != '\0') {
+       if (ch == '\\' && *source == '\n')
+           continue;
+       if (ch == '\n' || ch == '\t')
+           continue;
+       *target++ = ch;
+    }
+    *target = '\0';
+}
+
 /*
  * Store the latest value of an environment variable in my_vars[] so we can
  * detect if one changes, invalidating the cached search-list.
@@ -99,19 +124,21 @@ update_getenv(const char *name, DBDIRS which)
 
     if (which < dbdLAST) {
        char *value;
+       char *cached_value = my_vars[which].value;
+       bool same_value;
 
-       if ((value = getenv(name)) == 0 || (value = strdup(value)) == 0) {
-           ;
-       } else if (my_vars[which].name == 0 || strcmp(my_vars[which].name, name)) {
-           FreeIfNeeded(my_vars[which].value);
-           my_vars[which].name = name;
-           my_vars[which].value = value;
-           result = TRUE;
-       } else if ((my_vars[which].value != 0) ^ (value != 0)) {
-           FreeIfNeeded(my_vars[which].value);
-           my_vars[which].value = value;
-           result = TRUE;
-       } else if (value != 0 && strcmp(value, my_vars[which].value)) {
+       if ((value = getenv(name)) != 0) {
+           value = strdup(value);
+       }
+       same_value = ((value == 0 && cached_value == 0) ||
+                     (value != 0 &&
+                      cached_value != 0 &&
+                      strcmp(value, cached_value) == 0));
+
+       /* Set variable name to enable checks in cache_expired(). */
+       my_vars[which].name = name;
+
+       if (!same_value) {
            FreeIfNeeded(my_vars[which].value);
            my_vars[which].value = value;
            result = TRUE;
@@ -122,6 +149,7 @@ update_getenv(const char *name, DBDIRS which)
     return result;
 }
 
+#if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP
 static char *
 cache_getenv(const char *name, DBDIRS which)
 {
@@ -133,6 +161,7 @@ cache_getenv(const char *name, DBDIRS which)
     }
     return result;
 }
+#endif
 
 /*
  * The cache expires if at least a second has passed since the initial lookup,
@@ -185,10 +214,12 @@ _nc_tic_dir(const char *path)
        if (path != 0) {
            TicDirectory = path;
            HaveTicDirectory = TRUE;
-       } else if (!HaveTicDirectory && use_terminfo_vars()) {
-           char *envp;
-           if ((envp = getenv("TERMINFO")) != 0)
-               return _nc_tic_dir(envp);
+       } else if (HaveTicDirectory == 0) {
+           if (use_terminfo_vars()) {
+               const char *envp;
+               if ((envp = getenv("TERMINFO")) != 0)
+                   return _nc_tic_dir(envp);
+           }
        }
     }
     return TicDirectory ? TicDirectory : TERMINFO;
@@ -249,7 +280,7 @@ _nc_first_db(DBDIRS * state, int *offset)
     *state = dbdTIC;
     *offset = 0;
 
-    T(("_nc_first_db"));
+    T((T_CALLED("_nc_first_db")));
 
     /* build a blob containing all of the strings we will use for a lookup
      * table.
@@ -258,7 +289,7 @@ _nc_first_db(DBDIRS * state, int *offset)
        size_t blobsize = 0;
        const char *values[dbdLAST];
        struct stat *my_stat;
-       int j, k;
+       int j;
 
        if (cache_has_expired)
            free_cache();
@@ -272,7 +303,7 @@ _nc_first_db(DBDIRS * state, int *offset)
         */
        values[dbdTIC] = TicDirectory;
 
-#if USE_DATABASE
+#if NCURSES_USE_DATABASE
 #ifdef TERMINFO_DIRS
        values[dbdCfgList] = TERMINFO_DIRS;
 #endif
@@ -281,19 +312,19 @@ _nc_first_db(DBDIRS * state, int *offset)
 #endif
 #endif
 
-#if USE_TERMCAP
+#if NCURSES_USE_TERMCAP
        values[dbdCfgList2] = TERMPATH;
 #endif
 
        if (use_terminfo_vars()) {
-#if USE_DATABASE
+#if NCURSES_USE_DATABASE
            values[dbdEnvOnce] = cache_getenv("TERMINFO", dbdEnvOnce);
            values[dbdHome] = _nc_home_terminfo();
            (void) cache_getenv("HOME", dbdHome);
            values[dbdEnvList] = cache_getenv("TERMINFO_DIRS", dbdEnvList);
 
 #endif
-#if USE_TERMCAP
+#if NCURSES_USE_TERMCAP
            values[dbdEnvOnce2] = cache_getenv("TERMCAP", dbdEnvOnce2);
            /* only use $TERMCAP if it is an absolute path */
            if (values[dbdEnvOnce2] != 0
@@ -301,7 +332,7 @@ _nc_first_db(DBDIRS * state, int *offset)
                values[dbdEnvOnce2] = 0;
            }
            values[dbdEnvList2] = cache_getenv("TERMPATH", dbdEnvList2);
-#endif /* USE_TERMCAP */
+#endif /* NCURSES_USE_TERMCAP */
        }
 
        for (j = 0; j < dbdLAST; ++j) {
@@ -328,10 +359,12 @@ _nc_first_db(DBDIRS * state, int *offset)
            my_list = typeCalloc(char *, blobsize);
            my_stat = typeCalloc(struct stat, blobsize);
            if (my_list != 0 && my_stat != 0) {
-               k = 0;
+               int k = 0;
                my_list[k++] = my_blob;
                for (j = 0; my_blob[j] != '\0'; ++j) {
-                   if (my_blob[j] == NCURSES_PATHSEP) {
+                   if (my_blob[j] == NCURSES_PATHSEP
+                       && ((&my_blob[j] - my_list[k - 1]) != 3
+                           || !quick_prefix(my_list[k - 1]))) {
                        my_blob[j] = '\0';
                        my_list[k++] = &my_blob[j + 1];
                    }
@@ -345,8 +378,10 @@ _nc_first_db(DBDIRS * state, int *offset)
                    if (*my_list[j] == '\0')
                        my_list[j] = strdup(TERMINFO);
 #endif
+                   trim_formatting(my_list[j]);
                    for (k = 0; k < j; ++k) {
                        if (!strcmp(my_list[j], my_list[k])) {
+                           T(("duplicate %s", my_list[j]));
                            k = j - 1;
                            while ((my_list[j] = my_list[j + 1]) != 0) {
                                ++j;
@@ -375,6 +410,7 @@ _nc_first_db(DBDIRS * state, int *offset)
                    }
 #endif
                    if (!found) {
+                       T(("not found %s", my_list[j]));
                        k = j;
                        while ((my_list[k] = my_list[k + 1]) != 0) {
                            ++k;
@@ -390,6 +426,7 @@ _nc_first_db(DBDIRS * state, int *offset)
            free(my_stat);
        }
     }
+    returnVoid;
 }
 
 #if NO_LEAKS