#include <limits.h>
#endif
+#include "obstack.h"
#include "ls.h"
#include "version.h"
#include "safe-stat.h"
#include "safe-lstat.h"
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
#ifndef INT_MAX
#define INT_MAX (((unsigned int) ~(unsigned int) 0) >> 1)
#endif
-#ifndef S_IEXEC
-#define S_IEXEC S_IXUSR
-#endif
-
/* Return an int indicating the result of comparing two longs. */
#if (INT_MAX <= 65535)
#define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
"atime", "access", "use", "ctime", "status", 0
};
+/* FIXME comment */
+static size_t dired_pos;
+
+/* FIXME comment */
+#define PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
+
+/* FIXME comment */
+#define FPUTS(s, stream, s_len) \
+ do {fputs ((s), (stream)); dired_pos += s_len;} while (0)
+
+/* FIXME comment */
+static struct obstack dired_obstack;
+
+/* FIXME comment */
+#define PUSH_CURRENT_DIRED_POS() \
+ do \
+ { \
+ /* FIXME: remove the `&& format == long_format' clause. */ \
+ if (dired && format == long_format) \
+ obstack_grow (&dired_obstack, &dired_pos, sizeof (dired_pos)); \
+ } \
+ while (0)
+
+/* FIXME comment */
+#define PUSH_CURRENT_SUBDIRED_POS() \
+ do \
+ { \
+ /* FIXME: remove the `&& format == long_format' clause. */ \
+ if (dired && format == long_format && trace_dirs) \
+ obstack_grow (&subdired_obstack, &dired_pos, sizeof (dired_pos));\
+ } \
+ while (0)
+
+/* FIXME comment */
+static struct obstack subdired_obstack;
+
static enum time_type const time_types[] =
{
time_atime, time_atime, time_atime, time_ctime, time_ctime
};
\f
+static void
+dired_dump_obstack (prefix, os)
+ const char *prefix;
+ struct obstack *os;
+{
+ int i, n_pos;
+ size_t *pos;
+
+ fputs (prefix, stdout);
+ n_pos = obstack_object_size (os) / sizeof (size_t);
+ pos = obstack_finish (os);
+ for (i=0; i<n_pos; i++)
+ printf (" %d", pos[i]);
+ fputs ("\n", stdout);
+}
+
void
main (argc, argv)
int argc;
|| trace_links || trace_dirs || indicator_style != none
|| print_block_size || print_inode;
+ if (dired && format == long_format)
+ {
+ obstack_init (&dired_obstack);
+ if (trace_dirs)
+ obstack_init (&subdired_obstack);
+ }
+
nfiles = 100;
files = (struct fileinfo *) xmalloc (sizeof (struct fileinfo) * nfiles);
files_index = 0;
{
print_current_files ();
if (pending_dirs)
- putchar ('\n');
+ PUTCHAR ('\n');
}
else if (pending_dirs && pending_dirs->next == 0)
print_dir_name = 0;
print_dir_name = 1;
}
+ if (dired && format == long_format)
+ {
+ /* No need to free these since we're about to exit. */
+ dired_dump_obstack ("//DIRED//", &dired_obstack);
+ if (trace_dirs)
+ dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
+ }
+
exit (exit_status);
}
\f
static void
print_dir (name, realname)
- char *name;
- char *realname;
+ const char *name;
+ const char *realname;
{
register DIR *reading;
register struct dirent *next;
if (print_dir_name)
{
- if (realname)
- printf ("%s:\n", realname);
- else
- printf ("%s:\n", name);
+ const char *dir;
+
+ dir = (realname ? realname : name);
+ PUSH_CURRENT_SUBDIRED_POS ();
+ FPUTS (dir, stdout, strlen (dir));
+ PUSH_CURRENT_SUBDIRED_POS ();
+ FPUTS (":\n", stdout, 2);
}
if (format == long_format || print_block_size)
- printf ("total %u\n", total_blocks);
+ {
+ char buf[6 + 20 + 1 + 1];
+ sprintf (buf, "total %u\n", total_blocks);
+ FPUTS (buf, stdout, strlen (buf));
+ }
if (files_index)
print_current_files ();
if (pending_dirs)
- putchar ('\n');
+ PUTCHAR ('\n');
}
\f
/* Add `pattern' to the list of patterns for which files that match are
for (i = 0; i < files_index; i++)
{
print_long_format (files + i);
- putchar ('\n');
+ PUTCHAR ('\n');
}
break;
}
}
-/* Set QUOTED_LENGTH to strlen(P) and return NULL if P == quoted(P).
- Otherwise, return xmalloc'd storage containing the quoted version
- of P and set QUOTED_LENGTH to the length of the quoted P. */
-
-static char *
-quote_filename (p, quoted_length)
- register const char *p;
- int *quoted_length;
-{
- register unsigned char c;
- const char *p0 = p;
- char *quoted, *q;
- int found_quotable;
-
- if (!quote_as_string && !quote_funny_chars && !qmark_funny_chars)
- {
- *quoted_length = strlen (p);
- return NULL;
- }
-
- found_quotable = 0;
- for (c = *p; c; c = *++p)
- {
- if (quote_funny_chars)
- {
- switch (c)
- {
- case '\\':
- case '\n':
- case '\b':
- case '\r':
- case '\t':
- case '\f':
- case ' ':
- case '"':
- found_quotable = 1;
- break;
-
- default:
- /* FIXME: why not just use the ISPRINT macro here? */
- if (!(c > 040 && c < 0177))
- found_quotable = 1;
- break;
- }
- }
- else
- {
- if (!(c >= 040 && c < 0177) && qmark_funny_chars)
- found_quotable = 1;
- }
- if (found_quotable)
- break;
- }
-
- if (!found_quotable)
- {
- *quoted_length = p - p0;
- return NULL;
- }
-
- p = p0;
- quoted = xmalloc (4 * strlen (p) + 1);
- q = quoted;
-
-#define SAVECHAR(c) *q++ = (c)
-#define SAVE_2_CHARS(c12) \
- do { *q++ = ((c12)[0]); \
- *q++ = ((c12)[1]); } while (0)
-
- if (quote_as_string)
- SAVECHAR ('"');
-
- while ((c = *p++))
- {
- if (quote_funny_chars)
- {
- switch (c)
- {
- case '\\':
- SAVE_2_CHARS ("\\\\");
- break;
-
- case '\n':
- SAVE_2_CHARS ("\\n");
- break;
-
- case '\b':
- SAVE_2_CHARS ("\\b");
- break;
-
- case '\r':
- SAVE_2_CHARS ("\\r");
- break;
-
- case '\t':
- SAVE_2_CHARS ("\\t");
- break;
-
- case '\f':
- SAVE_2_CHARS ("\\f");
- break;
-
- case ' ':
- SAVE_2_CHARS ("\\ ");
- break;
-
- case '"':
- SAVE_2_CHARS ("\\\"");
- break;
-
- default:
- if (c > 040 && c < 0177)
- SAVECHAR (c);
- else
- {
- char buf[5];
- sprintf (buf, "\\%03o", (unsigned int) c);
- q = stpcpy (p, buf);
- }
- }
- }
- else
- {
- if (c >= 040 && c < 0177)
- SAVECHAR (c);
- else if (!qmark_funny_chars)
- SAVECHAR (c);
- else
- SAVECHAR ('?');
- }
- }
-
- if (quote_as_string)
- SAVECHAR ('"');
-
- *quoted_length = q - quoted;
-
- SAVECHAR ('\0');
-
- return quoted;
-}
-
static void
print_long_format (f)
struct fileinfo *f;
{
char modebuf[20];
char timebuf[40];
- char *quoted;
int quoted_length;
/* 7 fields that may (worst case be 64-bit integral values) require 20 bytes,
sprintf (p, "%s ", full_time ? timebuf : timebuf + 4);
p += strlen (p);
- quoted = quote_filename (f->name, "ed_length);
-
if (dired)
- {
- printf ("%d,%d:", p - bigbuf, quoted_length);
- }
+ FPUTS (" ", stdout, 2);
- fputs (bigbuf, stdout);
- fputs (quoted != NULL ? quoted : f->name, stdout);
+ FPUTS (bigbuf, stdout, p - bigbuf);
+ PUSH_CURRENT_DIRED_POS ();
+ print_name_with_quoting (f->name);
+ PUSH_CURRENT_DIRED_POS ();
if (f->filetype == symbolic_link)
{
if (f->linkname)
{
- fputs (" -> ", stdout);
+ FPUTS (" -> ", stdout, 4);
print_name_with_quoting (f->linkname);
if (indicator_style != none)
print_type_indicator (f->linkmode);
}
\f
-static void
-print_name_with_quoting (p)
- register char *p;
+/* Set QUOTED_LENGTH to strlen(P) and return NULL if P == quoted(P).
+ Otherwise, return xmalloc'd storage containing the quoted version
+ of P and set QUOTED_LENGTH to the length of the quoted P. */
+
+static char *
+quote_filename (p, quoted_length)
+ register const char *p;
+ size_t *quoted_length;
{
register unsigned char c;
+ const char *p0 = p;
+ char *quoted, *q;
+ int found_quotable;
+
+ if (!quote_as_string && !quote_funny_chars && !qmark_funny_chars)
+ {
+ *quoted_length = strlen (p);
+ return NULL;
+ }
+
+ found_quotable = 0;
+ for (c = *p; c; c = *++p)
+ {
+ if (quote_funny_chars)
+ {
+ switch (c)
+ {
+ case '\\':
+ case '\n':
+ case '\b':
+ case '\r':
+ case '\t':
+ case '\f':
+ case ' ':
+ case '"':
+ found_quotable = 1;
+ break;
+
+ default:
+ /* FIXME: why not just use the ISPRINT macro here? */
+ if (!(c > 040 && c < 0177))
+ found_quotable = 1;
+ break;
+ }
+ }
+ else
+ {
+ if (!(c >= 040 && c < 0177) && qmark_funny_chars)
+ found_quotable = 1;
+ }
+ if (found_quotable)
+ break;
+ }
+
+ if (!found_quotable)
+ {
+ *quoted_length = p - p0;
+ return NULL;
+ }
+
+ p = p0;
+ quoted = xmalloc (4 * strlen (p) + 1);
+ q = quoted;
+
+#define SAVECHAR(c) *q++ = (c)
+#define SAVE_2_CHARS(c12) \
+ do { *q++ = ((c12)[0]); \
+ *q++ = ((c12)[1]); } while (0)
if (quote_as_string)
- putchar ('"');
+ SAVECHAR ('"');
while ((c = *p++))
{
switch (c)
{
case '\\':
- printf ("\\\\");
+ SAVE_2_CHARS ("\\\\");
break;
case '\n':
- printf ("\\n");
+ SAVE_2_CHARS ("\\n");
break;
case '\b':
- printf ("\\b");
+ SAVE_2_CHARS ("\\b");
break;
case '\r':
- printf ("\\r");
+ SAVE_2_CHARS ("\\r");
break;
case '\t':
- printf ("\\t");
+ SAVE_2_CHARS ("\\t");
break;
case '\f':
- printf ("\\f");
+ SAVE_2_CHARS ("\\f");
break;
case ' ':
- printf ("\\ ");
+ SAVE_2_CHARS ("\\ ");
break;
case '"':
- printf ("\\\"");
+ SAVE_2_CHARS ("\\\"");
break;
default:
if (c > 040 && c < 0177)
- putchar (c);
+ SAVECHAR (c);
else
- printf ("\\%03o", (unsigned int) c);
+ {
+ char buf[5];
+ sprintf (buf, "\\%03o", (unsigned int) c);
+ q = stpcpy (p, buf);
+ }
}
}
else
{
if (c >= 040 && c < 0177)
- putchar (c);
+ SAVECHAR (c);
else if (!qmark_funny_chars)
- putchar (c);
+ SAVECHAR (c);
else
- putchar ('?');
+ SAVECHAR ('?');
}
}
if (quote_as_string)
- putchar ('"');
+ SAVECHAR ('"');
+
+ *quoted_length = q - quoted;
+
+ SAVECHAR ('\0');
+
+ return quoted;
+}
+
+static void
+print_name_with_quoting (p)
+ register char *p;
+{
+ char *quoted;
+ size_t quoted_length;
+
+ quoted = quote_filename (p, "ed_length);
+ FPUTS (quoted != NULL ? quoted : p, stdout, quoted_length);
+ if (quoted)
+ free (quoted);
}
\f
/* Print the file name of `f' with appropriate quoting.
unsigned int mode;
{
if (S_ISDIR (mode))
- putchar ('/');
+ PUTCHAR ('/');
#ifdef S_ISLNK
if (S_ISLNK (mode))
- putchar ('@');
+ PUTCHAR ('@');
#endif
#ifdef S_ISFIFO
if (S_ISFIFO (mode))
- putchar ('|');
+ PUTCHAR ('|');
#endif
#ifdef S_ISSOCK
if (S_ISSOCK (mode))
- putchar ('=');
+ PUTCHAR ('=');
#endif
if (S_ISREG (mode) && indicator_style == all
- && (mode & (S_IEXEC | S_IEXEC >> 3 | S_IEXEC >> 6)))
- putchar ('*');
+ && (mode & (S_IEXEC | S_IXGRP | S_IXOTH)))
+ PUTCHAR ('*');
}
static int