/* * escape_ansi.c * ------------- * Functions for escaping non-printable characters. * * * Copyright 2008, 2009 Sebastien Aperghis-Tramoni * * This program is free software; you can redistribute it * and/or modify it under the same terms as Perl itself. */ /* standard includes */ #include /* custom includes */ #include "escape_chars.h" /* private macros */ #define NON_PRINTABLE(x) ((x) <= '\x1F' || (x) == '\x7F') #define CHAR_INDEX(x) ( (x) <= '\x1F' ? (int)((x) - '\x00') \ : (x) == '\x7F' ? (int)((x) - '\x1F' + 1) \ : (int)((x) - '\x1F' + 2) ) /* structures */ struct { const char code; const char *name; } charname[] = { { '\x00', "NUL" }, /* "\\0" */ { '\x01', "SOH" }, { '\x02', "STX" }, { '\x03', "ETX" }, { '\x04', "EOT" }, { '\x05', "ENQ" }, { '\x06', "ACK" }, { '\x07', "BEL" }, /* "\\a" */ { '\x08', "BS" }, /* "\\b" */ { '\x09', "HT" }, /* "\\t" */ { '\x0A', "LF" }, /* "\\n" */ { '\x0B', "VT" }, /* "\\v" */ { '\x0C', "FF" }, /* "\\f" */ { '\x0D', "CR" }, /* "\\r" */ { '\x0E', "SO" }, { '\x0F', "SI" }, { '\x10', "DLE" }, { '\x11', "DC1" }, { '\x12', "DC2" }, { '\x13', "DC3" }, { '\x14', "DC4" }, { '\x15', "NAK" }, { '\x16', "SYN" }, { '\x17', "ETB" }, { '\x18', "CAN" }, { '\x19', "EM" }, { '\x1A', "SUB" }, { '\x1B', "ESC" }, { '\x1C', "FS" }, { '\x1D', "GS" }, { '\x1E', "RS" }, { '\x1F', "US" }, { '\x7F', "DEL" }, { 0, "???" }, }; /* * escape_non_printable_chars() * -------------------------- /*! Escape non-printable characters * * This function parse the given null-terminated string and looks for * non-printable characters to escape. * * If there are any, a new string is allocated where each non-printable * character is replaced with a human-readable representation. For example * the character '\x1B' (ESC) is replace with "". * * If there is no character to escape, the original string is returned. * * Typical usage: * * char input[] = ""; * char *output; * * output = escape_non_printable_chars(input); * ... * if (output != input) * free(output); * * * @param input null-terminated string * @return null-terminated string * */ char * escape_non_printable_chars(const char *input) { char *output; const char *i; const char *n; char *o; int len = 0; int num = 0; /* first loop to calculate the number of characters to escape */ for (i=input; *i != '\0'; i++) { len++; if (NON_PRINTABLE(*i)) num++; } /* if there's nothing to escape, just return the input string */ if (num == 0) return (char *) input; output = (char *) malloc(len + 4*num); /* second loop to actually escape the non-printable characters */ for (i=input, o=output; *i != '\0'; i++) { if (NON_PRINTABLE(*i)) { *o++ = '<'; for (n=charname[CHAR_INDEX(*i)].name; *n != '\0'; n++) *o++ = *n; *o++ = '>'; } else *o++ = *i; } *o = '\0'; return output; }