I would implement your custom print function slightly differently:
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
static int output_escaped(FILE *out, const char *str, const char *end)
{
int count = 0;
while (str < end)
switch (*str) {
case '\\': fputs("\\\\", out); count++; break;
case '\a': fputs("\\a", out); count++; break;
case '\b': fputs("\\b", out); count++; break;
case '\t': fputs("\\t", out); count++; break;
case '\n': fputs("\\n", out); count++; break;
case '\v': fputs("\\v", out); count++; break;
case '\f': fputs("\\f", out); count++; break;
case '\r': fputs("\\r", out); count++; break;
default:
if (isprint((unsigned char)(*str)))
fputc(*str, out);
else {
fprintf(out, "\\x%02x", (unsigned char)(*str));
count += 3; /* Note: incremented by one later */
}
}
str++;
count++;
}
return count;
}
with wrapper functions
int escape(const char *str)
{
if (!stdout || !str) {
errno = EINVAL;
return -1;
} else
return output_escaped(stdout, str, str + strlen(str));
}
int escapen(const char *str, const size_t len)
{
if (!stdout || !str) {
errno = EINVAL;
return -1;
} else
return output_escaped(stdout, str, str + len);
}
int fescape(FILE *out, const char *str)
{
if (!out || !str) {
errno = EINVAL;
return -1;
} else
return output_escaped(out, str, str + strlen(str));
}
int fescapen(FILE *out, const char *str, const size_t len)
{
if (!out || !str) {
errno = EINVAL;
return -1;
} else
return output_escaped(out, str, str + len);
}
The four wrappers cater for the cases when you want to print the entire thing, or just some len first characters, to stdout or a specific stream. All return the number of characters output, or -1 if an error occurs (and errno set).
Note that this prints \ as \\, and other non-printable characters using a hexadecimal escape sequence \x00 to \xFF. If you want octal (\001 through \377) rather than hexadecimal escapes, use
else {
fprintf(out, "\\%03o", (unsigned char)(*str));
count += 3; /* Note: incremented by one later */
}
instead.
The (unsigned char) casts ensure that the character value is never negative.