Major overhaul. No longer read from /etc/DIR_COLORS or from ~/.dircolors.
authorJim Meyering <jim@meyering.net>
Sat, 22 Jun 1996 22:02:37 +0000 (22:02 +0000)
committerJim Meyering <jim@meyering.net>
Sat, 22 Jun 1996 22:02:37 +0000 (22:02 +0000)
Defaults are now compiled in.  If you specify a file on the command line,
it is used instead of the compiled-in defaults.

src/dircolors.c

index 8b19721..a116d60 100644 (file)
@@ -1,7 +1,10 @@
 /* FIXME: accept, but ignore EIGHTBIT option
-   FIXME: embed contents of default mapping file
    FIXME: add option to print that default mapping?
 
+   dircolors: use compiled-in defaults, output a string setting LS_COLORS
+   dircolors -p: output the compiled-in defaults
+   dircolors FILE: use FILE, output a string setting LS_COLORS
+
    Only distinction necessary: Bourne vs. C-shell
    Use obstack to accumulate rhs of setenv
  */
@@ -32,18 +35,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 
 #include "system.h"
+#include "getline.h"
 #include "long-options.h"
 #include "error.h"
+#include "dircolors.h"
 
 char *xmalloc ();
+char *basename ();
 
-#define USER_FILE ".dir_colors"        /* Versus user's home directory */
-#define SYSTEM_FILE "DIR_COLORS" /* System-wide file in directory SYSTEM_DIR
-                                    (defined on the cc command line).  */
-
-#define STRINGLEN 2048         /* Max length of a string */
+/* Nonzero if any of the files read were the standard input. */
+static int have_read_stdin;
 
-enum modes { SHELLTYPE_BOURNE, SHELLTYPE_C, SHELLTYPE_UNKNOWN };
+enum Shell_syntax
+{
+  SHELL_SYNTAX_BOURNE,
+  SHELL_SYNTAX_C,
+  SHELL_SYNTAX_UNKNOWN
+};
 
 /* Parser needs these state variables.  */
 enum states { ST_TERMNO, ST_TERMYES, ST_TERMSURE, ST_GLOBAL };
@@ -93,28 +101,24 @@ Determine format of output:\n\
   exit (status);
 }
 
-/* If SHELL is csh or tcsh, assume C-shell.  Else Bourne shell.  */
+/* If the SHELL environment variable is set to `csh' or `tcsh,'
+   assume C-shell.  Else Bourne shell.  */
 
-static int
-figure_mode (void)
+static enum Shell_syntax
+guess_shell_syntax (void)
 {
-  char *shell, *shellv;
+  char *shell;
 
-  shellv = getenv ("SHELL");
-  if (shellv == NULL || *shellv == '\0')
-    return SHELLTYPE_UNKNOWN;
+  shell = getenv ("SHELL");
+  if (shell == NULL || *shell == '\0')
+    return SHELL_SYNTAX_UNKNOWN;
 
-  shell = strrchr (shellv, '/');
-  if (shell != NULL)
-    ++shell;
-  else
-    shell = shellv;
+  shell = basename (shell);
 
-  if (strcmp (shell, "csh") == 0
-      || strcmp (shell, "tcsh") == 0)
-    return SHELLTYPE_C;
+  if (STREQ (shell, "csh") || STREQ (shell, "tcsh"))
+    return SHELL_SYNTAX_C;
 
-  return SHELLTYPE_BOURNE;
+  return SHELL_SYNTAX_BOURNE;
 }
 
 static void
@@ -189,108 +193,50 @@ put_seq (const char *str, char follow)
   putchar (follow);            /* The character that ends the sequence.  */
 }
 
-int
-main (int argc, char *argv[])
+/* FIXME: Accumulate settings in obstack and convert to string in *RESULT.  */
+
+static int
+dc_parse_stream (FILE *fp, const char *filename, char **result)
 {
-  char *p;
-  int optc;
-  int mode = SHELLTYPE_UNKNOWN;
-  FILE *fp = NULL;
-  char *term;
+  size_t line_number = 0;
+  char *line = NULL;
+  size_t line_chars_allocated = 0;
   int state;
+  char *term;
+  int err = 0;
 
-  char line[STRINGLEN];
-  char *keywd, *arg;
-
-  char *input_file;
-
-  program_name = argv[0];
-  setlocale (LC_ALL, "");
-  bindtextdomain (PACKAGE, LOCALEDIR);
-  textdomain (PACKAGE);
-
-  parse_long_options (argc, argv, "dircolors", PACKAGE_VERSION, usage);
-
-  while ((optc = getopt_long (argc, argv, "bc", long_options, NULL))
-        != EOF)
-    switch (optc)
-      {
-      case 'b':        /* Bourne shell mode.  */
-       mode = SHELLTYPE_BOURNE;
-       break;
-
-      case 'c':        /* Bourne shell mode.  */
-       mode = SHELLTYPE_C;
-       break;
-
-      default:
-       usage (1);
-      }
-
-  /* Use shell to determine mode, if not already done. */
-  if (mode == SHELLTYPE_UNKNOWN)
-    {
-      mode = figure_mode ();
-      if (mode == SHELLTYPE_UNKNOWN)
-       {
-         error (1, 0, _("\
-no SHELL environment variable, and no shell type option given"));
-       }
-    }
-
-  /* Open dir_colors file */
-  if (optind == argc)
-    {
-      p = getenv ("HOME");
-      if (p != NULL && *p != '\0')
-       {
-         /* Note: deliberate leak.  It's not worth freeing this.  */
-         input_file = xmalloc (strlen (p) + 1 + strlen (USER_FILE) + 1);
-         stpcpy (stpcpy (stpcpy (input_file, p), "/"), USER_FILE);
-         fp = fopen (input_file, "r");
-       }
-
-      if (fp == NULL)
-       {
-         /* Note: deliberate leak.  It's not worth freeing this.  */
-         input_file = xmalloc (strlen (SHAREDIR) + 1
-                               + strlen (USER_FILE) + 1);
-         stpcpy (stpcpy (stpcpy (input_file, SHAREDIR), "/"),
-                 SYSTEM_FILE);
-         fp = fopen (input_file, "r");
-       }
-    }
-  else
-    {
-      input_file = argv[optind];
-      fp = fopen (input_file, "r");
-    }
-
-  if (fp == NULL)
-    error (1, errno, _("while opening input file `%s'"), input_file);
+  state = ST_GLOBAL;
 
   /* Get terminal type */
   term = getenv ("TERM");
   if (term == NULL || *term == '\0')
     term = "none";
 
-  /* Write out common start */
-  switch (mode)
+  while (1)
     {
-    case SHELLTYPE_C:
-      puts ("set noglob;\nsetenv LS_COLORS \':");
-      break;
+      int line_length;
+      char *keywd, *arg;
 
-    case SHELLTYPE_BOURNE:
-      fputs ("LS_COLORS=\'", stdout);
-      break;
-    }
+      ++line_number;
 
-  state = ST_GLOBAL;
+      if (fp)
+       {
+         line_length = getline (&line, &line_chars_allocated, fp);
+         if (line_length <= 0)
+           {
+             if (line)
+               free (line);
+             break;
+           }
+       }
+      else
+       {
+         line = (char *) (G_line[line_number - 1]);
+         line_length = G_line_length[line_number - 1];
+         if (line_number > G_N_LINES)
+           break;
+       }
 
-  /* FIXME: use getline */
-  while (fgets (line, STRINGLEN, fp) != NULL)
-    {
       parse_line (&keywd, &arg, line);
       if (*keywd != '\0')
        {
@@ -341,29 +287,111 @@ no SHELL environment variable, and no shell type option given"));
                          put_seq (arg, ':');
                        }
                      else
-                       error (0, 0, _("Unknown keyword %s\n"), keywd);
+                       {
+                         error (0, 0, _("%s:%lu: unrecognized keyword %s\n"),
+                                filename, (long unsigned) line_number, keywd);
+                         err = 1;
+                       }
                    }
                }
            }
        }
     }
 
-  fclose (fp);
+  return err;
+}
+
+static int
+dc_parse_file (const char *filename, char **ls_color_string)
+{
+  FILE *fp;
+  int err;
 
-  /* Write it out.  */
-  switch (mode)
+  if (strcmp (filename, "-") == 0)
+    {
+      have_read_stdin = 1;
+      fp = stdin;
+    }
+  else
     {
-    case SHELLTYPE_BOURNE:
-      printf ("\';\nexport LS_COLORS\n");
-      break;
+      /* OPENOPTS is a macro.  It varies with the system.
+        Some systems distinguish between internal and
+        external text representations.  */
 
-    case SHELLTYPE_C:
-      printf ("\'\nunset noglob\n");
-      break;
+      fp = fopen (filename, "r");
+      if (fp == NULL)
+       {
+         error (0, errno, "%s", filename);
+         return 1;
+       }
+    }
+
+  err = dc_parse_stream (fp, filename, ls_color_string);
+  if (err)
+    {
+      error (0, errno, "%s", filename);
+      if (fp != stdin)
+       fclose (fp);
+      return 1;
+    }
 
-    default:
-      abort ();
+  if (fp != stdin && fclose (fp) == EOF)
+    {
+      error (0, errno, "%s", filename);
+      return 1;
     }
 
-  exit (0);
+  return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int err;
+  int optc;
+  enum Shell_syntax syntax = SHELL_SYNTAX_UNKNOWN;
+  char *ls_color_string;
+  char *file;
+
+  program_name = argv[0];
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  parse_long_options (argc, argv, "dircolors", PACKAGE_VERSION, usage);
+
+  while ((optc = getopt_long (argc, argv, "bc", long_options, NULL))
+        != EOF)
+    switch (optc)
+      {
+      case 'b':        /* Bourne shell syntax.  */
+       syntax = SHELL_SYNTAX_BOURNE;
+       break;
+
+      case 'c':        /* C-shell syntax.  */
+       syntax = SHELL_SYNTAX_C;
+       break;
+
+      default:
+       usage (1);
+      }
+
+  /* Use shell to determine mode, if not already done. */
+  if (syntax == SHELL_SYNTAX_UNKNOWN)
+    {
+      syntax = guess_shell_syntax ();
+      if (syntax == SHELL_SYNTAX_UNKNOWN)
+       {
+         error (1, 0,
+          _("no SHELL environment variable, and no shell type option given"));
+       }
+    }
+
+  file = argv[optind];
+  err = dc_parse_file (file, &ls_color_string);
+
+  if (have_read_stdin && fclose (stdin) == EOF)
+    error (EXIT_FAILURE, errno, _("standard input"));
+
+  exit (err == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }