* lib/listfile.c (list_file): factor out most of the logic.
* bootstrap.conf (gnulib_modules): add inttotr (which is now used in
lib/listfile.c).
---
bootstrap.conf | 1 +
lib/listfile.c | 817 ++++++++++++++++++++++++++-----------------------
2 files changed, 438 insertions(+), 380 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index b7de74e3..da72c2ed 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -119,6 +119,7 @@ gnulib_modules="
idcache
inline
intprops
+ inttostr
inttypes-h
isblank
locale-h
diff --git a/lib/listfile.c b/lib/listfile.c
index 464528e3..0afa3135 100644
--- a/lib/listfile.c
+++ b/lib/listfile.c
@@ -19,6 +19,7 @@
/* system headers. */
#include <alloca.h>
+#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
@@ -29,12 +30,13 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
-#include <unistd.h> /* for readlink() */
+#include <unistd.h> /* for readlink() */
/* gnulib headers. */
#include "areadlink.h"
#include "filemode.h"
#include "human.h"
+#include "inttostr.h"
#include "mbswidth.h"
#include "idcache.h"
#include "pathmax.h"
@@ -51,7 +53,7 @@
# ifdef MAJOR_IN_SYSMACROS
# include <sys/sysmacros.h>
# else
-# ifndef major /* Might be defined in sys/types.h. */
+# ifndef major /* Might be defined in sys/types.h. */
# define major(dev) (((dev) >> 8) & 0xff)
# define minor(dev) ((dev) & 0xff)
# endif
@@ -59,7 +61,8 @@
#endif
-static bool print_name (register const char *p, FILE *stream, int
literal_control_chars);
+static bool print_name (register const char *p, FILE * stream,
+ int literal_control_chars);
/* We have some minimum field sizes, though we try to widen these fields on
systems
* where we discover examples where the field width we started with is not
enough. */
@@ -71,388 +74,441 @@ static int group_width = 8;
/* We don't print st_author even if the system has it. */
static int major_device_number_width = 3;
static int minor_device_number_width = 3;
-static int file_size_width = 8;
+static int file_device_or_size_width = 8;
+static int time_stamp_width = 12;
-static bool print_num(FILE *stream, unsigned long num, int *width)
+static bool
+update_width_if_success (int chars_out, int *width)
{
- const int chars_out = fprintf (stream, "%*lu", *width, num);
if (chars_out >= 0)
{
if (*width < chars_out)
- *width = chars_out;
+ *width = chars_out;
return true;
}
return false;
}
-/* NAME is the name to print.
- RELNAME is the path to access it from the current directory.
- STATP is the results of stat or lstat on it.
- Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
- Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
- and sizes.
- STREAM is the stdio stream to print on. */
-void
-list_file (const char *name,
- int dir_fd,
- const char *relname,
- const struct stat *statp,
- time_t current_time,
- int output_block_size,
- int literal_control_chars,
- FILE *stream)
+static bool
+print_num (FILE *stream, unsigned long num, int *width)
+{
+ return update_width_if_success (fprintf (stream, "%*lu", *width, num),
+ width);
+}
+
+
+static bool
+print_block_count (const struct stat *statp,
+ int output_block_size, FILE *stream)
{
- char modebuf[12];
- struct tm const *when_local;
- char const *user_name;
- char const *group_name;
char hbuf[LONGEST_HUMAN_READABLE + 1];
- bool output_good = true;
- int chars_out;
- int failed_at = 000;
+ int chars_out = fprintf (stream, "%*s",
+ block_size_width,
+ human_readable ((uintmax_t) ST_NBLOCKS (*statp),
+ hbuf,
+ human_ceiling,
+ ST_NBLOCKSIZE, output_block_size));
+ return update_width_if_success (chars_out, &block_size_width);
+}
+
+static bool
+print_file_size (const struct stat *statp,
+ int output_block_size, FILE *stream)
+{
+ char hbuf[LONGEST_HUMAN_READABLE + 1];
+ const int blocksize = output_block_size < 0 ? output_block_size : 1;
+ int chars_out = fprintf (stream, "%*s",
+ file_device_or_size_width,
+ human_readable ((uintmax_t) statp->st_size,
+ hbuf,
+ human_ceiling,
+ 1, blocksize));
+ return update_width_if_success (chars_out, &file_device_or_size_width);
+}
+
+static bool
+print_file_inum (const struct stat *statp, FILE *stream)
+{
+ char umaxtostr_buf[INT_BUFSIZE_BOUND (uintmax_t)];
+ int chars_out = fprintf (stream, "%*s", inode_number_width,
+ umaxtostr (statp->st_ino, umaxtostr_buf));
+ return update_width_if_success (chars_out, &inode_number_width);
+}
+
+
+static bool
+print_struct_tm (const struct tm *when_local,
+ time_t file_timestamp, time_t current_time, FILE *stream)
+{
+ char init_bigbuf[256];
+ char *buf = init_bigbuf;
+ size_t bufsize = sizeof init_bigbuf;
+
+ /* Use strftime rather than ctime, because the former can produce
+ locale-dependent names for the month (%b).
+
+ Output the year if the file is fairly old or in the future.
+ POSIX says the cutoff is 6 months old;
+ approximate this by 6*30 days.
+ Allow a 1 hour slop factor for what is considered "the future",
+ to allow for NFS server/client clock disagreement. */
+ char const *fmt =
+ ((current_time - 6 * 30 * 24 * 60 * 60 <= file_timestamp
+ && file_timestamp <= current_time + 60 * 60)
+ ? "%b %e %H:%M" : "%b %e %Y");
+
+ while (!strftime (buf, bufsize, fmt, when_local))
+ buf = alloca (bufsize *= 2);
+
+ int chars_out = fprintf (stream, "%*s", time_stamp_width, buf);
+ return update_width_if_success (chars_out, &time_stamp_width);
+}
+
+
+/* Print a time which cannot be represented as a local time,
+ as a (presumably huge) integer number of seconds. */
+static bool
+print_raw_timestamp (time_t time_val, FILE *stream)
+{
+ char intmaxtostr_buf[1 + INT_BUFSIZE_BOUND (intmax_t)];
+
+ char const *num = imaxtostr (time_val, intmaxtostr_buf);
+ return update_width_if_success (fprintf (stream, "%s", num),
+ &time_stamp_width);
+}
-#if HAVE_ST_DM_MODE
- /* Cray DMF: look at the file's migrated, not real, status */
- strmode (statp->st_dm_mode, modebuf);
-#else
- strmode (statp->st_mode, modebuf);
-#endif
- chars_out = fprintf (stream, "%*s", inode_number_width,
- human_readable ((uintmax_t) statp->st_ino, hbuf,
- human_ceiling,
- 1u, 1u));
- if (chars_out < 0)
+static bool
+print_file_mtime (const struct stat *statp, time_t current_time, FILE *stream)
+{
+ struct tm const *when_local = localtime (&statp->st_mtime);
+ if (when_local)
{
- output_good = false;
- failed_at = 100;
+ return print_struct_tm (when_local, statp->st_mtime, current_time,
+ stream);
}
- else if (chars_out > inode_number_width)
+ else
{
- inode_number_width = chars_out;
+ /* The time cannot be represented as a local time; print it as
+ an integer. */
+ return print_raw_timestamp (statp->st_mtime, stream);
}
- if (output_good)
+}
+
+
+static bool
+print_file_owner (const struct stat *statp, FILE *stream)
+{
+ char const *user_name = getuser (statp->st_uid);
+ int chars_out;
+ if (user_name)
{
- if (EOF == putc(' ', stream))
- {
- output_good = false;
- failed_at = 150;
- }
- chars_out = fprintf (stream, "%*s",
- block_size_width,
- human_readable ((uintmax_t) ST_NBLOCKS (*statp),
hbuf,
- human_ceiling,
- ST_NBLOCKSIZE, output_block_size));
- if (chars_out < 0)
- {
- output_good = false;
- failed_at = 200;
- }
- else
- {
- if (chars_out > block_size_width)
- block_size_width = chars_out;
- }
+ int len = mbswidth (user_name, 0);
+ if (len > owner_width)
+ owner_width = len;
+ chars_out = fprintf (stream, "%-*s ", owner_width, user_name);
}
-
- if (output_good)
+ else
{
- if (EOF == putc(' ', stream))
- {
- output_good = false;
- failed_at = 250;
- }
+ chars_out = fprintf (stream, "%-8lu ", (unsigned long) statp->st_uid);
}
- if (output_good)
+ return update_width_if_success (chars_out, &owner_width);
+}
+
+static bool
+print_file_group (const struct stat *statp, FILE *stream)
+{
+ char const *group_name = getgroup (statp->st_gid);
+ int chars_out;
+ if (group_name)
{
- /* modebuf includes the space between the mode and the number of links,
- as the POSIX "optional alternate access method flag". */
- if (fputs (modebuf, stream) < 0)
- {
- output_good = false;
- failed_at = 275;
- }
+ int len = mbswidth (group_name, 0);
+ if (len > group_width)
+ group_width = len;
+ chars_out = fprintf (stream, "%-*s ", group_width, group_name);
}
- if (output_good)
+ else
{
- /* This format used to end in a space, but the output of "ls"
- has only one space between the link count and the owner name,
- so we removed the trailing space. Happily this also makes it
- easier to update nlink_width. */
- chars_out = fprintf (stream, "%*lu",
- nlink_width, (unsigned long) statp->st_nlink);
- if (chars_out < 0)
- {
- output_good = false;
- failed_at = 300;
- }
- else
- {
- if (chars_out > nlink_width)
- nlink_width = chars_out;
- }
+ chars_out = fprintf (stream, "%-*lu",
+ group_width, (unsigned long) statp->st_gid);
}
+ return update_width_if_success (chars_out, &group_width);
+}
+
+static bool
+print_file_mode (const struct stat *statp, FILE *stream)
+{
+ char modebuf[12];
+#if HAVE_ST_DM_MODE
+ /* Cray DMF: look at the file's migrated, not real, status */
+ strmode (statp->st_dm_mode, modebuf);
+#else
+ strmode (statp->st_mode, modebuf);
+#endif
+ /* modebuf normally includes a trailing space the space between the
+ mode and the number of links, as the POSIX "optional alternate
+ access method flag". Alternatively though the last character may
+ be non-blank. In that case we need to emit a space to separate
+ the mode and link count.
+ */
+ return fputs (modebuf, stream) >= 0;
+}
- if (output_good)
+static bool
+format_dev_major_or_minor (char *buf,
+ size_t buf_siz,
+ unsigned long dev_maj_or_min, int *max_width)
+{
+ const char *format = "%*lu";
+ int needed = snprintf (NULL, 0, format, *max_width, dev_maj_or_min);
+ if (needed >= buf_siz || *max_width > buf_siz)
{
- if (EOF == putc(' ', stream))
- {
- output_good = false;
- failed_at = 250;
- }
- user_name = getuser (statp->st_uid);
- if (user_name)
- {
- int len = mbswidth (user_name, 0);
- if (len > owner_width)
- owner_width = len;
- output_good = (fprintf (stream, "%-*s ", owner_width, user_name) >=
0);
- if (!output_good)
- failed_at = 400;
- }
- else
- {
- chars_out = fprintf (stream, "%-8lu ", (unsigned long)
statp->st_uid);
- if (chars_out > owner_width)
- owner_width = chars_out;
- output_good = (chars_out > 0);
- if (!output_good)
- failed_at = 450;
- }
+ /* This is in effect an assertion failure, but we still want to
+ * perform the check when _NDEBUG is defined, otherwise we get a
+ * compiler warning.
+ */
+ error (1, 0,
+ "device number output buffer is too short to output a field with
width %d (want %d, have %zu)",
+ *max_width, needed, buf_siz);
+ return false;
}
-
- if (output_good)
+ int output_size = sprintf (buf, format, *max_width, dev_maj_or_min);
+ if (output_size == buf_siz || output_size == 0)
{
- group_name = getgroup (statp->st_gid);
- if (group_name)
- {
- int len = mbswidth (group_name, 0);
- if (len > group_width)
- group_width = len;
- output_good = (fprintf (stream, "%-*s ", group_width, group_name) >=
0);
- if (!output_good)
- failed_at = 500;
- }
- else
- {
- chars_out = fprintf (stream, "%-*lu",
- group_width, (unsigned long) statp->st_gid);
- if (chars_out > group_width)
- group_width = chars_out;
- output_good = (chars_out >= 0);
- if (output_good)
- {
- if (EOF == putc(' ', stream))
- {
- output_good = false;
- failed_at = 525;
- }
- }
- else
- {
- if (!output_good)
- failed_at = 550;
- }
- }
+ /* Truncated output; result is not terminated. */
+ return false;
}
-
- if (output_good)
+ --output_size; /* discount the terminating null character */
+ if (output_size > *max_width)
{
- if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
- {
+ *max_width = output_size;
+ }
+ return true;
+}
+
+
+
+static bool
+print_file_device (const struct stat *statp, FILE *stream)
+{
+ char dev_maj_buf[INT_BUFSIZE_BOUND (unsigned long)];
+ char dev_min_buf[INT_BUFSIZE_BOUND (unsigned long)];
+ const char *separator = "";
+
#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (!print_num (stream,
- (unsigned long) major (statp->st_rdev),
- &major_device_number_width))
- {
- output_good = false;
- failed_at = 600;
- }
- if (output_good)
- {
- if (fprintf (stream, ", ") < 0)
- {
- output_good = false;
- failed_at = 625;
- }
- }
- if (output_good)
- {
- if (!print_num (stream,
- (unsigned long) minor (statp->st_rdev),
- &minor_device_number_width))
- {
- output_good = false;
- failed_at = 650;
- }
- }
+ separator = ",";
+ if (!format_dev_major_or_minor (dev_maj_buf, sizeof (dev_maj_buf),
+ (unsigned long) major (statp->st_rdev),
+ &major_device_number_width))
+ return false;
+ if (!format_dev_major_or_minor (dev_min_buf, sizeof (dev_min_buf),
+ (unsigned long) minor (statp->st_rdev),
+ &minor_device_number_width))
+ return false;
#else
- if (fprintf (stream, "%*s %*s",
- major_device_number_width,
- minor_device_number_width) < 0)
- {
- output_good = false;
- failed_at = 700;
- }
+ dev_maj_buf[0] = 0;
+ dev_min_buf[0] = 0;
#endif
- }
- else
- {
- const int blocksize = output_block_size < 0 ? output_block_size : 1;
- chars_out = fprintf (stream, "%*s",
- file_size_width,
- human_readable ((uintmax_t) statp->st_size,
hbuf,
- human_ceiling,
- 1, blocksize));
- if (chars_out < 0)
- {
- output_good = false;
- failed_at = 800;
- }
- else
- {
- if (chars_out > file_size_width)
- {
- file_size_width = chars_out;
- }
- }
- }
- }
+ int chars_out = fprintf (stream, "%*s%-2s%*s",
+ major_device_number_width,
+ dev_maj_buf,
+ separator,
+ minor_device_number_width,
+ dev_min_buf);
+ return update_width_if_success (chars_out, &file_device_or_size_width);
+}
- if (output_good)
+static bool
+print_file_dev_or_size (const struct stat *statp,
+ int output_block_size, FILE *stream)
+{
+ if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
{
- if (EOF == putc(' ', stream))
- {
- output_good = false;
- failed_at = 850;
- }
+ return print_file_device (statp, stream);
}
-
- if (output_good)
+ else
{
- if ((when_local = localtime (&statp->st_mtime)))
- {
- char init_bigbuf[256];
- char *buf = init_bigbuf;
- size_t bufsize = sizeof init_bigbuf;
-
- /* Use strftime rather than ctime, because the former can produce
- locale-dependent names for the month (%b).
-
- Output the year if the file is fairly old or in the future.
- POSIX says the cutoff is 6 months old;
- approximate this by 6*30 days.
- Allow a 1 hour slop factor for what is considered "the future",
- to allow for NFS server/client clock disagreement. */
- char const *fmt =
- ((current_time - 6 * 30 * 24 * 60 * 60 <= statp->st_mtime
- && statp->st_mtime <= current_time + 60 * 60)
- ? "%b %e %H:%M"
- : "%b %e %Y");
-
- while (!strftime (buf, bufsize, fmt, when_local))
- buf = alloca (bufsize *= 2);
-
- if (fprintf (stream, "%s ", buf) < 0)
- {
- output_good = false;
- failed_at = 900;
- }
- }
- else
- {
- /* The time cannot be represented as a local time;
- print it as a huge integer number of seconds. */
- int width = 12;
-
- if (statp->st_mtime < 0)
- {
- char const *num = human_readable (- (uintmax_t) statp->st_mtime,
- hbuf, human_ceiling, 1, 1);
- int sign_width = width - strlen (num);
- if (fprintf (stream, "%*s%s ",
- sign_width < 0 ? 0 : sign_width, "-", num) < 0)
- {
- output_good = false;
- failed_at = 1000;
- }
- }
- else
- {
- if (fprintf (stream, "%*s ", width,
- human_readable ((uintmax_t) statp->st_mtime, hbuf,
- human_ceiling,
- 1, 1)) < 0)
- {
- output_good = false;
- failed_at = 1100;
- }
- }
- }
+ const int blocksize = output_block_size < 0 ? output_block_size : 1;
+ return print_file_size (statp, blocksize, stream);
}
+}
+
- if (output_good)
+static bool
+print_link_count (const struct stat *statp, FILE *stream)
+{
+ /* This field used to end in a space, but the output of "ls"
+ has only one space between the link count and the owner name,
+ so we removed the trailing space. Happily this also makes it
+ easier to update nlink_width. */
+ return print_num (stream, statp->st_nlink, &nlink_width);
+}
+
+static bool
+print_file_link_target (const struct stat *statp,
+ int dir_fd,
+ const char *relname,
+ int literal_control_chars,
+ bool *issued_diagnostic, FILE *stream)
+{
+ char *linkname = areadlinkat (dir_fd, relname);
+ if (!linkname)
{
- output_good = print_name (name, stream, literal_control_chars);
- if (!output_good)
- {
- failed_at = 1200;
- }
+ error (0, errno, "%s", relname);
+ *issued_diagnostic = true;
+ return false;
}
- if (output_good)
+ bool result = true;
+ if (fputs (" -> ", stream) < 0)
+ result = false;
+ if (result)
{
- if (S_ISLNK (statp->st_mode))
- {
- char *linkname = areadlinkat (dir_fd, relname);
- if (linkname)
- {
- if (fputs (" -> ", stream) < 0)
- {
- output_good = false;
- failed_at = 1300;
- }
- if (output_good)
- {
- output_good = print_name (linkname, stream,
literal_control_chars);
- if (!output_good)
- {
- failed_at = 1350;
- }
- }
- }
- else
- {
- /* POSIX requires in the case of find that if we issue a
- * diagnostic we should have a nonzero status. However,
- * this function doesn't have a way of telling the caller to
- * do that. However, since this function is only used when
- * processing "-ls", we're already using an extension.
- */
- error (0, errno, "%s", name);
- }
- free (linkname);
- }
- if (output_good)
- {
- if (EOF == putc ('\n', stream))
- {
- output_good = false;
- if (!output_good)
- {
- failed_at = 1400;
- }
- }
- }
+ if (!print_name (linkname, stream, literal_control_chars))
+ result = false;
}
- if (!output_good)
+ free (linkname);
+ return result;
+}
+
+static bool
+maybe_print_file_link_target (const struct stat *statp,
+ int dir_fd,
+ const char *relname,
+ int literal_control_chars,
+ bool *issued_diagnostic, FILE *stream)
+{
+ if (S_ISLNK (statp->st_mode))
{
- error (EXIT_FAILURE, errno, _("Failed to write output (at stage %d)"),
failed_at);
+ return print_file_link_target (statp, dir_fd, relname,
+ literal_control_chars, issued_diagnostic,
+ stream);
}
+ return true;
+}
+
+
+static bool
+print_single_space (FILE *stream)
+{
+ if (EOF == putc (' ', stream))
+ return false;
+ return true;
}
+/* NAME is the name to print.
+ RELNAME is the path to access it from the current directory.
+ STATP is the results of stat or lstat on it.
+ Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
+ Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
+ and sizes.
+ ISSUED_DIAGNOSTIC is set to true when the return value is false
+ and we have already emitted a diagnostic on stderr.
+ STREAM is the stdio stream to print on. */
+
+static bool
+list_file_internal (const char *name,
+ int dir_fd,
+ const char *relname,
+ const struct stat *statp,
+ time_t current_time,
+ int output_block_size,
+ int literal_control_chars,
+ bool *issued_diagnostic, FILE *stream)
+{
+
+ if (!print_file_inum (statp, stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ if (!print_block_count (statp, output_block_size, stream))
+ return false;
+
+ if (!print_file_mode (statp, stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ if (!print_link_count (statp, stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ if (!print_file_owner (statp, stream))
+ return false;
+
+ if (!print_file_group (statp, stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ if (!print_file_dev_or_size (statp, output_block_size, stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ if (!print_file_mtime (statp, current_time, stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ if (!print_name (name, stream, literal_control_chars))
+ return false;
+
+ if (!maybe_print_file_link_target
+ (statp, dir_fd, relname, literal_control_chars, issued_diagnostic,
+ stream))
+ return false;
+
+ if (!print_single_space (stream))
+ return false;
+
+ return true;
+}
+
+
+/* NAME is the name to print.
+ RELNAME is the path to access it from the current directory.
+ STATP is the results of stat or lstat on it.
+ Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
+ Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
+ and sizes.
+ STREAM is the stdio stream to print on. */
+
+void
+list_file (const char *name,
+ int dir_fd,
+ const char *relname,
+ const struct stat *statp,
+ time_t current_time,
+ int output_block_size, int literal_control_chars, FILE *stream)
+{
+ /* POSIX requires in the case of find that if we issue a diagnostic
+ * we should have a nonzero status. But since this function
+ * currently returns void, we cannot do that.
+ *
+ * POSIX doesn't include -ls, so this is already an extension. But
+ * still, it would be good to fix this.
+ */
+ bool issued_diagnostic = false;
+ bool success =
+ list_file_internal (name, dir_fd, relname, statp, current_time,
+ output_block_size, literal_control_chars,
+ &issued_diagnostic, stream);
+ if (!success && !issued_diagnostic)
+ {
+ error (EXIT_FAILURE, errno, _("Failed to write output"));
+ }
+}
static bool
print_name_without_quoting (const char *p, FILE *stream)
@@ -470,58 +526,59 @@ print_name_with_quoting (register const char *p, FILE
*stream)
{
int fprintf_result = -1;
switch (c)
- {
- case '\\':
- fprintf_result = fprintf (stream, "\\\\");
- break;
-
- case '\n':
- fprintf_result = fprintf (stream, "\\n");
- break;
-
- case '\b':
- fprintf_result = fprintf (stream, "\\b");
- break;
-
- case '\r':
- fprintf_result = fprintf (stream, "\\r");
- break;
-
- case '\t':
- fprintf_result = fprintf (stream, "\\t");
- break;
-
- case '\f':
- fprintf_result = fprintf (stream, "\\f");
- break;
-
- case ' ':
- fprintf_result = fprintf (stream, "\\ ");
- break;
-
- case '"':
- fprintf_result = fprintf (stream, "\\\"");
- break;
-
- default:
- if (c > 040 && c < 0177)
- {
- if (EOF == putc (c, stream))
- return false;
- fprintf_result = 1; /* otherwise it's used uninitialized. */
- }
- else
- {
- fprintf_result = fprintf (stream, "\\%03o", (unsigned int) c);
- }
- }
+ {
+ case '\\':
+ fprintf_result = fprintf (stream, "\\\\");
+ break;
+
+ case '\n':
+ fprintf_result = fprintf (stream, "\\n");
+ break;
+
+ case '\b':
+ fprintf_result = fprintf (stream, "\\b");
+ break;
+
+ case '\r':
+ fprintf_result = fprintf (stream, "\\r");
+ break;
+
+ case '\t':
+ fprintf_result = fprintf (stream, "\\t");
+ break;
+
+ case '\f':
+ fprintf_result = fprintf (stream, "\\f");
+ break;
+
+ case ' ':
+ fprintf_result = fprintf (stream, "\\ ");
+ break;
+
+ case '"':
+ fprintf_result = fprintf (stream, "\\\"");
+ break;
+
+ default:
+ if (c > 040 && c < 0177)
+ {
+ if (!print_single_space (stream))
+ return false;
+ fprintf_result = 1; /* otherwise it's used uninitialized. */
+ }
+ else
+ {
+ fprintf_result = fprintf (stream, "\\%03o", (unsigned int) c);
+ }
+ }
if (fprintf_result < 0)
- return false;
+ return false;
}
return true;
}
-static bool print_name (register const char *p, FILE *stream, int
literal_control_chars)
+static bool
+print_name (register const char *p, FILE *stream, int literal_control_chars)
{
if (literal_control_chars)
return print_name_without_quoting (p, stream);
--
2.47.3