OSSP CVS Repository

ossp - ossp-pkg/var/expand-named-characters.c
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/var/expand-named-characters.c
#include "internal.h"

/* Internal parsing code for octal. */

static int isoct(char c)
    {
    if (c >= '0' && c <= '7')
        return 1;
    else
        return 0;
    }

static var_rc_t expand_octal(const char** src, char** dst, const char* end)
    {
    unsigned char c;

    if (end - *src < 3)
        return VAR_INCOMPLETE_OCTAL;
    if (!isoct(**src) || !isoct((*src)[1]) || !isoct((*src)[2]))
        return VAR_INVALID_OCTAL;

    c = **src - '0';
    if (c > 3)
        return VAR_OCTAL_TOO_LARGE;
    c *= 8;
    ++(*src);

    c += **src - '0';
    c *= 8;
    ++(*src);

    c += **src - '0';

    **dst = (char)c;
    ++(*dst);
    return VAR_OK;
    }

static int ishex(char c)
    {
    if ((c >= '0' && c <= '9') ||
        (c >= 'a' && c <= 'f') ||
        (c >= 'A' && c <= 'F'))
        return 1;
    else
        return 0;
    }

/* Internal parsing code for hex. */

static var_rc_t expand_simple_hex(const char** src, char** dst, const char* end)
    {
    unsigned char c = 0;

    if (end - *src < 2)
        return VAR_INCOMPLETE_HEX;
    if (!ishex(**src) || !ishex((*src)[1]))
        return VAR_INVALID_HEX;

    if (**src >= '0' && **src <= '9')
        c = **src - '0';
    else if (c >= 'a' && c <= 'f')
        c = **src - 'a' + 10;
    else if (c >= 'A' && c <= 'F')
        c = **src - 'A' + 10;

    c = c << 4;
    ++(*src);

    if (**src >= '0' && **src <= '9')
        c += **src - '0';
    else if (**src >= 'a' && **src <= 'f')
        c += **src - 'a' + 10;
    else if (**src >= 'A' && **src <= 'F')
        c += **src - 'A' + 10;

    **dst = (char)c;
    ++(*dst);
    return VAR_OK;
    }

static var_rc_t expand_grouped_hex(const char** src, char** dst, const char* end)
    {
    var_rc_t rc;

    while (*src < end && **src != '}')
        {
        if ((rc = expand_simple_hex(src, dst, end)) != 0)
            return rc;
        ++(*src);
        }
    if (*src == end)
        return VAR_INCOMPLETE_GROUPED_HEX;

    return VAR_OK;
    }

static var_rc_t expand_hex(const char** src, char** dst, const char* end)
    {
    if (*src == end)
        return VAR_INCOMPLETE_HEX;
    if (**src == '{')
        {
        ++(*src);
        return expand_grouped_hex(src, dst, end);
        }
    else
        return expand_simple_hex(src, dst, end);
    }

/*
  Expand the following named characters in the buffer:

       \t          tab
       \n          newline
       \r          return
       \033        octal char
       \x1B        hex char
       \x{263a}    wide hex char

  Any other character quoted by a backslash is copied verbatim.
*/

var_rc_t expand_named_characters(const char* src, size_t len, char* dst)
    {
    const char* end = src + len;
    var_rc_t rc;

    assert(src != NULL);
    assert(dst != NULL);

    while (src < end)
        {
        if (*src == '\\')
            {
            if (++src == end)
                return VAR_INCOMPLETE_NAMED_CHARACTER;
            switch (*src)
                {
                case 'n':
                    *dst++ = '\n';
                    break;
                case 't':
                    *dst++ = '\t';
                    break;
                case 'r':
                    *dst++ = '\r';
                    break;
                case 'x':
                    ++src;
                    if ((rc = expand_hex(&src, &dst, end)) != 0)
                        return rc;
                    break;
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    if ((rc = expand_octal(&src, &dst, end)) != 0)
                        return rc;
                    break;
                default:
                    *dst++ = *src;
                }
            ++src;
            }
        else
            *dst++ = *src++;
        }
    *dst = '\0';
    return VAR_OK;
    }

CVSTrac 2.0.1