]> git.refcnt.org Git - colorize.git/commitdiff
Merge branch 'stack_release_vars'
authorSteven Schubiger <stsc@refcnt.org>
Fri, 8 Jan 2021 21:40:26 +0000 (22:40 +0100)
committerSteven Schubiger <stsc@refcnt.org>
Fri, 8 Jan 2021 21:40:26 +0000 (22:40 +0100)
colorize.c

index d527e5eff4f2f79f0b85b2bb259b69f4518779cd..9a6a6f9d69ac26e2ef023a007038ddfba6026ebe 100644 (file)
 
 #define VALID_FILE_TYPE(mode) (S_ISREG (mode) || S_ISLNK (mode) || S_ISFIFO (mode))
 
-#define STACK_VAR(ptr) do {                                   \
-    stack_var (&vars_list, &stacked_vars, stacked_vars, ptr); \
+#define STACK_VAR(ptr) do {                                           \
+    stack (&vars_list, &stacked_vars, stacked_vars, ptr, IS_GENERIC); \
 } while (false)
-
-#define RELEASE_VAR(ptr) do {                             \
-    release_var (vars_list, stacked_vars, (void **)&ptr); \
+#define STACK_FILE(ptr) do {                                       \
+    stack (&vars_list, &stacked_vars, stacked_vars, ptr, IS_FILE); \
+} while (false)
+#define RELEASE(ptr) do {                             \
+    release (vars_list, stacked_vars, (void **)&ptr); \
 } while (false)
 
 #if !DEBUG
@@ -266,13 +268,23 @@ struct attr {
     enum attr_type type;
 };
 
+enum var_type {
+    IS_GENERIC,
+    IS_FILE,
+    IS_UNUSED
+};
+struct var_list {
+    void *ptr;
+    enum var_type type;
+};
+
 static FILE *stream;
 #if DEBUG
 static FILE *log;
 #endif
 
 static unsigned int stacked_vars;
-static void **vars_list;
+static struct var_list *vars_list;
 
 static bool clean;
 static bool clean_all;
@@ -344,8 +356,8 @@ static bool has_color_name (const char *, const char *);
 static FILE *open_file (const char *, const char *);
 static void vfprintf_diag (const char *, ...);
 static void vfprintf_fail (const char *, ...);
-static void stack_var (void ***, unsigned int *, unsigned int, void *);
-static void release_var (void **, unsigned int, void **);
+static void stack (struct var_list **, unsigned int *, unsigned int, void *, enum var_type);
+static void release (struct var_list *, unsigned int, void **);
 
 extern int optind;
 
@@ -372,6 +384,11 @@ main (int argc, char **argv)
 #if DEBUG
     log = open_file (DEBUG_FILE, "w");
     print_tstamp (log);
+    /* We're in debugging mode, hence we can't invoke STACK_FILE()
+       prior to print_tstamp(), because both cause text to be written
+       to the same logfile which is expected to have the timestamp
+       first.  */
+    STACK_FILE (log);
 #endif
 
     attr[0] = '\0';
@@ -382,7 +399,10 @@ main (int argc, char **argv)
     conf_file = to_str (CONF_FILE_TEST);
 #elif !defined(TEST)
     if (conf_file == NULL)
-      conf_file_path (&conf_file);
+      {
+        conf_file_path (&conf_file);
+        STACK_VAR (conf_file);
+      }
     else
       {
         char *s;
@@ -391,6 +411,7 @@ main (int argc, char **argv)
             free (conf_file);
             conf_file = s;
           }
+        STACK_VAR (conf_file);
         errno = 0;
         if (access (conf_file, F_OK) == -1)
           vfprintf_fail (formats[FMT_CONF_FILE], conf_file, strerror (errno));
@@ -401,7 +422,7 @@ main (int argc, char **argv)
       parse_conf (conf_file, &config);
 #endif
 #if !defined(CONF_FILE_TEST) && !defined(TEST)
-    free (conf_file);
+    RELEASE (conf_file);
 #endif
     init_conf_vars (&config);
 
@@ -448,7 +469,7 @@ main (int argc, char **argv)
 
     free_conf (&config);
 
-    RELEASE_VAR (exclude);
+    RELEASE (exclude);
 
     exit (EXIT_SUCCESS);
 }
@@ -508,6 +529,7 @@ process_opts (int argc, char **argv, char **conf_file)
                   case OPT_ATTR:
                     opts_set |= OPT_ATTR_SET;
                     opts_arg.attr = xstrdup (optarg);
+                    STACK_VAR (opts_arg.attr);
                     break;
                   case OPT_CLEAN:
                     clean = true;
@@ -520,6 +542,7 @@ process_opts (int argc, char **argv, char **conf_file)
                   case OPT_EXCLUDE_RANDOM:
                     opts_set |= OPT_EXCLUDE_RANDOM_SET;
                     opts_arg.exclude_random = xstrdup (optarg);
+                    STACK_VAR (opts_arg.exclude_random);
                     break;
                   case OPT_OMIT_COLOR_EMPTY:
                     opts_set |= OPT_OMIT_COLOR_EMPTY_SET;
@@ -618,7 +641,7 @@ process_opt_attr (const char *p, const bool is_opt)
                 strncpy (attr_invalid, s, p - s);
                 attr_invalid[p - s] = '\0';
                 vfprintf_fail ("%s attribute '%s' is not valid", desc_type[DESC_TYPE], attr_invalid);
-                RELEASE_VAR (attr_invalid); /* never reached */
+                RELEASE (attr_invalid); /* never reached */
               }
           }
         if (*p)
@@ -645,7 +668,7 @@ process_opt_exclude_random (const char *s, const bool is_opt)
 {
     bool valid = false;
     unsigned int i;
-    RELEASE_VAR (exclude);
+    RELEASE (exclude);
     exclude = xstrdup (s);
     STACK_VAR (exclude);
     for (i = 1; i < tables[GENERIC].count - 1; i++) /* skip color none and default */
@@ -675,8 +698,8 @@ init_opts_vars (void)
     if (opts_set & OPT_OMIT_COLOR_EMPTY_SET)
       omit_color_empty = true;
 
-    free (opts_arg.attr);
-    free (opts_arg.exclude_random);
+    RELEASE (opts_arg.attr);
+    RELEASE (opts_arg.exclude_random);
 }
 
 #define IS_SPACE(c) ((c) == ' ' || (c) == '\t')
@@ -689,6 +712,7 @@ parse_conf (const char *conf_file, struct conf *config)
     FILE *conf;
 
     conf = open_file (conf_file, "r");
+    STACK_FILE (conf);
 
     while (fgets (line, sizeof (line), conf))
       {
@@ -751,18 +775,20 @@ parse_conf (const char *conf_file, struct conf *config)
 
         /* save option name */
         cfg = xstrdup (opt);
+        STACK_VAR (cfg);
         /* save option value (allow empty ones) */
         val = strlen (value) ? xstrdup (value) : NULL;
+        STACK_VAR (val);
 
         assign_conf (conf_file, config, cfg, val);
-        free (cfg);
+        RELEASE (cfg);
       }
 
-    fclose (conf);
+    RELEASE (conf);
 }
 
 #define ASSIGN_CONF(str,val) do { \
-    free (str);                   \
+    RELEASE (str);                \
     str = val;                    \
 } while (false)
 
@@ -926,17 +952,32 @@ static void
 cleanup (void)
 {
     if (stream && fileno (stream) != STDIN_FILENO)
-      fclose (stream);
+      RELEASE (stream);
 #if DEBUG
     if (log)
-      fclose (log);
+      RELEASE (log);
 #endif
 
     if (vars_list)
       {
         unsigned int i;
         for (i = 0; i < stacked_vars; i++)
-          free (vars_list[i]);
+          {
+            struct var_list *var = &vars_list[i];
+            switch (var->type)
+              {
+                case IS_GENERIC:
+                  free (var->ptr);
+                  break;
+                case IS_FILE:
+                  fclose (var->ptr);
+                  break;
+                case IS_UNUSED:
+                  break;
+                default: /* never reached */
+                  ABORT_TRACE ();
+              }
+          }
         free_null (vars_list);
       }
 }
@@ -947,19 +988,19 @@ free_color_names (struct color_name **color_names)
     unsigned int i;
     for (i = 0; color_names[i]; i++)
       {
-        RELEASE_VAR (color_names[i]->name);
-        RELEASE_VAR (color_names[i]->orig);
-        RELEASE_VAR (color_names[i]);
+        RELEASE (color_names[i]->name);
+        RELEASE (color_names[i]->orig);
+        RELEASE (color_names[i]);
       }
 }
 
 static void
 free_conf (struct conf *config)
 {
-    free (config->attr);
-    free (config->color);
-    free (config->exclude_random);
-    free (config->omit_color_empty);
+    RELEASE (config->attr);
+    RELEASE (config->color);
+    RELEASE (config->exclude_random);
+    RELEASE (config->omit_color_empty);
 }
 
 static void
@@ -1072,6 +1113,7 @@ process_file_arg (const char *file_string, const char **file, FILE **stream)
               vfprintf_fail (formats[FMT_TYPE], file, "unrecognized type", get_file_type (sb.st_mode));
 
             *stream = open_file (file, "r");
+            STACK_FILE (*stream);
           }
         *file = file_string;
       }
@@ -1202,7 +1244,7 @@ gather_color_names (const char *color_string, char *attr, struct color_name **co
         STACK_VAR (color_names[index]->name);
       }
 
-    RELEASE_VAR (str);
+    RELEASE (str);
 }
 
 static void
@@ -1850,41 +1892,63 @@ vfprintf_fail (const char *fmt, ...)
 }
 
 static void
-stack_var (void ***list, unsigned int *stacked, unsigned int index, void *ptr)
+stack (struct var_list **list, unsigned int *stacked, unsigned int index, void *ptr, enum var_type type)
 {
+    struct var_list *var;
     /* nothing to stack */
     if (ptr == NULL)
       return;
     if (!*list)
-      *list = xmalloc (sizeof (void *));
+      *list = xmalloc (sizeof (struct var_list));
     else
       {
         unsigned int i;
         for (i = 0; i < *stacked; i++)
-          if (!(*list)[i])
-            {
-              (*list)[i] = ptr;
-              return; /* reused */
-            }
-        *list = xrealloc (*list, (*stacked + 1) * sizeof (void *));
+          {
+            var = &(*list)[i];
+            if (var->type == IS_UNUSED)
+              {
+                var->ptr  = ptr;
+                var->type = type;
+                return; /* reused */
+              }
+          }
+        *list = xrealloc (*list, (*stacked + 1) * sizeof (struct var_list));
       }
-    (*list)[index] = ptr;
+    var = &(*list)[index];
+    var->ptr  = ptr;
+    var->type = type;
     (*stacked)++;
 }
 
 static void
-release_var (void **list, unsigned int stacked, void **ptr)
+release (struct var_list *list, unsigned int stacked, void **ptr)
 {
     unsigned int i;
     /* nothing to release */
     if (*ptr == NULL)
       return;
     for (i = 0; i < stacked; i++)
-      if (list[i] == *ptr)
-        {
-          free (*ptr);
-          *ptr = NULL;
-          list[i] = NULL;
-          return;
+      {
+        struct var_list *var = &list[i];
+        if (var->type != IS_UNUSED
+         && var->ptr == *ptr)
+          {
+            switch (var->type)
+              {
+                case IS_GENERIC:
+                  free (*ptr);
+                  break;
+                case IS_FILE:
+                  fclose (*ptr);
+                  break;
+                default: /* never reached */
+                  ABORT_TRACE ();
+              }
+            *ptr = NULL;
+            var->ptr  = NULL;
+            var->type = IS_UNUSED;
+            return;
         }
+    }
 }