diff -Nur fileutils-4.0.31/src/Makefile.am fileutils-4.0.31-align/src/Makefile.am --- fileutils-4.0.31/src/Makefile.am Sun Aug 6 14:21:03 2000 +++ fileutils-4.0.31-align/src/Makefile.am Wed Nov 8 23:19:04 2000 @@ -10,7 +10,7 @@ datadir = $(prefix)/@DATADIRNAME@ localedir = $(datadir)/locale -noinst_HEADERS = system.h sys2.h copy.h cp-hash.h ls.h dircolors.h remove.h +noinst_HEADERS = system.h sys2.h copy.h cp-hash.h ls.h dircolors.h remove.h printf_align.h printf_align_body.c EXTRA_DIST = dcgen dircolors.hin INCLUDES = -I.. -I$(srcdir) -I$(top_srcdir)/lib -I../intl @@ -29,9 +29,9 @@ ginstall_SOURCES = install.c copy.c cp-hash.c cp_SOURCES = cp.c copy.c cp-hash.c -dir_SOURCES = ls.c ls-dir.c -vdir_SOURCES = ls.c ls-vdir.c -ls_SOURCES = ls.c ls-ls.c +dir_SOURCES = ls.c ls-dir.c printf_align.c +vdir_SOURCES = ls.c ls-vdir.c printf_align.c +ls_SOURCES = ls.c ls-ls.c printf_align.c mv_SOURCES = mv.c copy.c cp-hash.c remove.c rm_SOURCES = rm.c remove.c diff -Nur fileutils-4.0.31/src/ls.c fileutils-4.0.31-align/src/ls.c --- fileutils-4.0.31/src/ls.c Sun Oct 29 08:46:04 2000 +++ fileutils-4.0.31-align/src/ls.c Wed Nov 8 23:08:35 2000 @@ -128,6 +128,7 @@ #include "quotearg.h" #include "strverscmp.h" #include "xstrtol.h" +#include "printf_align.h" /* Use access control lists only under all the following conditions. Some systems (OSF4, Irix5, Irix6) have the acl function, but not @@ -2326,6 +2327,7 @@ print_long_format (const struct fileinfo *f) { char modebuf[12]; + struct align_state state; /* 7 fields that may require LONGEST_HUMAN_READABLE bytes, 1 10-byte mode string, @@ -2338,6 +2340,7 @@ + 9 + 1]; char *buf = init_bigbuf; size_t bufsize = sizeof (init_bigbuf); + ssize_t bufrest = bufsize; size_t s; char *p; time_t when; @@ -2345,6 +2348,10 @@ const char *fmt; char *user_name; +restart: + + reset_align(&state); + #if HAVE_ST_DM_MODE /* Cray DMF: look at the file's migrated, not real, status */ mode_string (f->stat.st_dm_mode, modebuf); @@ -2352,7 +2359,7 @@ mode_string (f->stat.st_mode, modebuf); #endif - modebuf[10] = (FILE_HAS_ACL (f) ? '+' : ' '); + modebuf[10] = (FILE_HAS_ACL (f) ? '+' : '\0'); modebuf[11] = '\0'; switch (time_type) @@ -2396,71 +2403,83 @@ if (print_inode) { char hbuf[LONGEST_HUMAN_READABLE + 1]; - sprintf (p, "%*s ", INODE_DIGITS, + s = snprintf_align (&state, p, bufrest, "%*s ", INODE_DIGITS, human_readable ((uintmax_t) f->stat.st_ino, hbuf, 1, 1)); - p += strlen (p); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; } if (print_block_size) { char hbuf[LONGEST_HUMAN_READABLE + 1]; - sprintf (p, "%*s ", block_size_size, + s = snprintf_align (&state, p, bufrest, "%*s ", block_size_size, human_readable_inexact ((uintmax_t) ST_NBLOCKS (f->stat), hbuf, ST_NBLOCKSIZE, output_block_size, human_ceiling)); - p += strlen (p); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; } /* The last byte of the mode string is the POSIX "optional alternate access method flag". */ - sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink); - p += strlen (p); + s = snprintf_align (&state, p, bufrest, "%10s %3u ", modebuf, + (unsigned int) f->stat.st_nlink); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; user_name = (numeric_ids ? NULL : getuser (f->stat.st_uid)); if (user_name) - sprintf (p, "%-8.8s ", user_name); + s = snprintf_align (&state, p, bufrest, "%-8s ", user_name); else - sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid); - p += strlen (p); + s = snprintf_align (&state, p, bufrest, "%-8u ", (unsigned int) f->stat.st_uid); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; if (!inhibit_group) { char *group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid)); if (group_name) - sprintf (p, "%-8.8s ", group_name); + s = snprintf_align (&state, p, bufrest, "%-8s ", group_name); else - sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid); - p += strlen (p); + s = snprintf_align (&state, p, bufrest, "%-8u ", + (unsigned int) f->stat.st_gid); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; } if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode)) - sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev), - (unsigned) minor (f->stat.st_rdev)); + s = snprintf_align (&state, p, bufrest, "%3u, %3u ", + (unsigned) major (f->stat.st_rdev), + (unsigned) minor (f->stat.st_rdev)); else { char hbuf[LONGEST_HUMAN_READABLE + 1]; - sprintf (p, "%8s ", + s = snprintf_align (&state, p, bufrest, "%8s ", human_readable ((uintmax_t) f->stat.st_size, hbuf, 1, output_block_size < 0 ? output_block_size : 1)); } - p += strlen (p); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; /* Use strftime rather than ctime, because the former can produce locale-dependent names for the weekday (%a) and month (%b). */ if ((when_local = localtime (&when))) { - while (! (s = strftime (p, buf + bufsize - p - 1, fmt, when_local))) - { - char *newbuf = (char *) alloca (bufsize *= 2); - memcpy (newbuf, buf, p - buf); - p = newbuf + (p - buf); - buf = newbuf; - } - + if (bufrest <= 0) + goto reallocate; + if (! (s = strftime (p, bufrest-1, fmt, when_local))) + goto reallocate; p += s; *p++ = ' '; + bufrest -= s+1; /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it. */ *p = '\0'; @@ -2476,13 +2495,16 @@ { const char *num = human_readable (- (uintmax_t) when, hbuf, 1, 1); int sign_width = width - strlen (num); - sprintf (p, "%*s%s ", sign_width < 0 ? 0 : sign_width, "-", num); + s = snprintf_align (&state, p, bufrest, "%*s%s ", + sign_width < 0 ? 0 : sign_width, "-", num); } else - sprintf (p, "%*s ", width, - human_readable ((uintmax_t) when, hbuf, 1, 1)); + s = snprintf_align (&state, p, bufrest, "%*s ", width, + human_readable ((uintmax_t) when, hbuf, 1, 1)); - p += strlen (p); + if ((bufrest -= s) < 0) + goto reallocate; + p += s; } DIRED_INDENT (); @@ -2503,6 +2525,13 @@ } else if (indicator_style != none) print_type_indicator (f->stat.st_mode); + + return; + +reallocate: + + buf = alloca (bufsize *= 2); + goto restart; } /* Output to OUT a quoted representation of the file name NAME, diff -Nur fileutils-4.0.31/src/printf_align.c fileutils-4.0.31-align/src/printf_align.c --- fileutils-4.0.31/src/printf_align.c Thu Jan 1 01:00:00 1970 +++ fileutils-4.0.31-align/src/printf_align.c Wed Nov 8 23:23:37 2000 @@ -0,0 +1,75 @@ +#include +#include +#include +#include "printf_align.h" + +void reset_align(struct align_state *align) +{ + align->extra_width = 0; +} + +int printf_align(struct align_state *state, + const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vfprintf_align(state, stdout, format, ap); + va_end(ap); + + return ret; +} + +int fprintf_align(struct align_state *state, FILE *stream, + const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vfprintf_align(state, stream, format, ap); + va_end(ap); + + return ret; +} + +#define OUT(c) do { \ + n++; \ + putc(c, stream); \ + } while(0) +int vfprintf_align(struct align_state *state, FILE *stream, + const char *format, va_list ap) +{ +# include "printf_align_body.c" + return n; +} +#undef OUT + +int snprintf_align(struct align_state *state, char *str, size_t size, + const char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vsnprintf_align(state, str, size, format, ap); + va_end(ap); + + return ret; +} + +#define OUT(c) if (++n < size) \ + *str++ = (c) +int vsnprintf_align(struct align_state *state, char *str, size_t size, + const char *format, va_list ap) +{ +# include "printf_align_body.c" + if (n <= size) + size = n; + if (size > 0) + str[size-1] = '\0'; + + return n; +} +#undef OUT diff -Nur fileutils-4.0.31/src/printf_align.h fileutils-4.0.31-align/src/printf_align.h --- fileutils-4.0.31/src/printf_align.h Thu Jan 1 01:00:00 1970 +++ fileutils-4.0.31-align/src/printf_align.h Wed Nov 8 22:57:22 2000 @@ -0,0 +1,21 @@ +#ifndef __PRINTF_ALIGN +#define __PRINTF_ALIGN + +#include +#include + +struct align_state { + int extra_width; +}; + +void reset_align(struct align_state *align); + +extern int vfprintf_align(struct align_state *, FILE *, const char *, va_list); +extern int fprintf_align(struct align_state *, FILE *, const char *, ...); +extern int printf_align(struct align_state *, const char *, ...); + +extern int vsnprintf_align(struct align_state *, char *, size_t, const char *, va_list); +extern int snprintf_align(struct align_state *, char *, size_t, const char *, ...); + +#endif /* __PRINTF_ALIGN */ + diff -Nur fileutils-4.0.31/src/printf_align_body.c fileutils-4.0.31-align/src/printf_align_body.c --- fileutils-4.0.31/src/printf_align_body.c Thu Jan 1 01:00:00 1970 +++ fileutils-4.0.31-align/src/printf_align_body.c Fri Nov 10 09:09:19 2000 @@ -0,0 +1,132 @@ + int field_width, width, type_long, delta, n = 0; + enum { left_align, right_align } align; + char *s, *t; + union { + long s; + unsigned long u; + } arg; + unsigned long fact; + + if (*format == '\0') { + /* flush remembered spaces */ + while (state->extra_width > 0) { + OUT(' '); + state->extra_width--; + } + } + while (*format != '\0') { + while (*format != '%' && *format != '\0') { + if (*format != ' ') { + while (state->extra_width > 0) { + OUT(' '); + state->extra_width--; + } + } + OUT(*format); + format++; + } + if (*format == '%') { + format++; + if (*format == '*') { + format++; + field_width = va_arg(ap, int); + align = right_align; + if (field_width < 0) { + field_width = -field_width; + align = left_align; + } + } else { + align = right_align; + if (*format == '-') { + format++; + align = left_align; + } + field_width = 0; + while (*format >= '0' && *format <= '9') + field_width = (field_width * 10) + + (*format++ - '0'); + } + type_long = 0; + if (*format == 'l') { + format++; + type_long = 1; + } + switch(*format) { + case 's': + s = va_arg(ap, char *); + width = strlen(s); + break; + case 'd': case 'i': { + long m; + + arg.s = type_long ? + va_arg(ap, long) : + va_arg(ap, int); + width = 1; fact = 1; + if (arg.s < 0) + width++; + for (m = arg.s; m /= 10;) { + fact *= 10; + width++; + } + break; + } + case 'u': { + unsigned long m; + + arg.u = type_long ? + va_arg(ap, unsigned long) : + va_arg(ap, unsigned int); + width = 1; fact = 1; + for (m = arg.u; m /= 10;) { + fact *= 10; + width++; + } + break; + } + default: + OUT(*format); + format++; + goto next; + } + + if (field_width == 0) + field_width = width; + delta = field_width - width; + if (align == right_align) + state->extra_width += delta; + while (state->extra_width > 0) { + OUT(' '); + state->extra_width--; + } + if (align == left_align) + state->extra_width += delta; + + switch(*format) { + case 's': + while (*s) { + OUT(*s); + s++; + } + break; + case 'd': case 'i': + if (arg.s < 0) { + OUT('-'); + arg.s = -arg.s; + } + arg.u = (unsigned long)arg.s; + /* fall through */ + + case 'u': + do { + unsigned long d = arg.u / fact; + arg.u = arg.u % fact; + fact /= 10; + OUT(d + '0'); + } while (fact > 0); + break; + } + format++; + next: + } + }