Ejemplo n.º 1
0
/*=export_func  ao_string_cook_escape_char
 * private:
 *
 * what:  escape-process a string fragment
 * arg:   + char const * + pzScan  + points to character after the escape +
 * arg:   + char *       + pRes    + Where to put the result byte +
 * arg:   + unsigned int + nl_ch   + replacement char if scanned char is \n +
 *
 * ret-type: unsigned int
 * ret-desc: The number of bytes consumed processing the escaped character.
 *
 * doc:
 *
 *  This function converts "t" into "\t" and all your other favorite
 *  escapes, including numeric ones:  hex and ocatal, too.
 *  The returned result tells the caller how far to advance the
 *  scan pointer (passed in).  The default is to just pass through the
 *  escaped character and advance the scan by one.
 *
 *  Some applications need to keep an escaped newline, others need to
 *  suppress it.  This is accomplished by supplying a '\n' replacement
 *  character that is different from \n, if need be.  For example, use
 *  0x7F and never emit a 0x7F.
 *
 * err:  @code{NULL} is returned if the string is mal-formed.
=*/
unsigned int
ao_string_cook_escape_char(char const * pzIn, char * pRes, uint_t nl)
{
    unsigned int res = 1;

    switch (*pRes = *pzIn++) {
    case NUL:         /* NUL - end of input string */
        return 0;
    case '\r':
        if (*pzIn != NL)
            return 1;
        res++;
        /* FALLTHROUGH */
    case NL:        /* NL  - emit newline        */
        *pRes = (char)nl;
        return res;

    case 'a': *pRes = '\a'; break;
    case 'b': *pRes = '\b'; break;
    case 'f': *pRes = '\f'; break;
    case 'n': *pRes = NL;   break;
    case 'r': *pRes = '\r'; break;
    case 't': *pRes = '\t'; break;
    case 'v': *pRes = '\v'; break;

    case 'x':
    case 'X':         /* HEX Escape       */
        if (IS_HEX_DIGIT_CHAR(*pzIn))  {
            char z[4];
            unsigned int ct = 0;

            do  {
                z[ct] = pzIn[ct];
                if (++ct >= 2)
                    break;
            } while (IS_HEX_DIGIT_CHAR(pzIn[ct]));
            z[ct] = NUL;
            *pRes = (char)strtoul(z, NULL, 16);
            return ct + 1;
        }
        break;

    case '0': case '1': case '2': case '3':
    case '4': case '5': case '6': case '7':
    {
        /*
         *  IF the character copied was an octal digit,
         *  THEN set the output character to an octal value.
         *  The 3 octal digit result might exceed 0xFF, so check it.
         */
        char z[4];
        unsigned long val;
        unsigned int  ct = 0;

        z[ct++] = *--pzIn;
        while (IS_OCT_DIGIT_CHAR(pzIn[ct])) {
            z[ct] = pzIn[ct];
            if (++ct >= 3)
                break;
        }

        z[ct] = NUL;
        val = strtoul(z, NULL, 8);
        if (val > 0xFF)
            val = 0xFF;
        *pRes = (char)val;
        return ct;
    }

    default: /* quoted character is result character */;
    }

    return res;
}
Ejemplo n.º 2
0
/*=export_func  ao_string_cook_escape_char
 * private:
 *
 * what:  escape-process a string fragment
 * arg:   + char const*  + pzScan  + points to character after the escape +
 * arg:   + char*        + pRes    + Where to put the result byte +
 * arg:   + unsigned int + nl_ch   + replacement char if scanned char is \n +
 *
 * ret-type: unsigned int
 * ret-desc: The number of bytes consumed processing the escaped character.
 *
 * doc:
 *
 *  This function converts "t" into "\t" and all your other favorite
 *  escapes, including numeric ones:  hex and ocatal, too.
 *  The returned result tells the caller how far to advance the
 *  scan pointer (passed in).  The default is to just pass through the
 *  escaped character and advance the scan by one.
 *
 *  Some applications need to keep an escaped newline, others need to
 *  suppress it.  This is accomplished by supplying a '\n' replacement
 *  character that is different from \n, if need be.  For example, use
 *  0x7F and never emit a 0x7F.
 *
 * err:  @code{NULL} is returned if the string is mal-formed.
=*/
unsigned int
ao_string_cook_escape_char( char const* pzIn, char* pRes, u_int nl )
{
    unsigned int  res = 1;

    switch (*pRes = *pzIn++) {
    case NUL:         /* NUL - end of input string */
        return 0;
    case '\r':
        if (*pzIn != '\n')
            return 1;
        res++;
        /* FALLTHROUGH */
    case '\n':        /* NL  - emit newline        */
        *pRes = (char)nl;
        return res;

    case 'a': *pRes = '\a'; break;
    case 'b': *pRes = '\b'; break;
    case 'f': *pRes = '\f'; break;
    case 'n': *pRes = '\n'; break;
    case 'r': *pRes = '\r'; break;
    case 't': *pRes = '\t'; break;
    case 'v': *pRes = '\v'; break;

    case 'x':
    case 'X':         /* HEX Escape       */
        if (IS_HEX_DIGIT_CHAR(*pzIn))  {
            char z[4], *pz = z;

            do *(pz++) = *(pzIn++);
            while (IS_HEX_DIGIT_CHAR(*pzIn) && (pz < z + 2));
            *pz = NUL;
            *pRes = (unsigned char)strtoul(z, NULL, 16);
            res += pz - z;
        }
        break;

    case '0': case '1': case '2': case '3':
    case '4': case '5': case '6': case '7':
    {
        /*
         *  IF the character copied was an octal digit,
         *  THEN set the output character to an octal value
         */
        char z[4], *pz = z + 1;
        unsigned long val;
        z[0] = *pRes;

        while (IS_OCT_DIGIT_CHAR(*pzIn) && (pz < z + 3))
            *(pz++) = *(pzIn++);
        *pz = NUL;
        val = strtoul(z, NULL, 8);
        if (val > 0xFF)
            val = 0xFF;
        *pRes = (unsigned char)val;
        res = pz - z;
        break;
    }

    default: ;
    }

    return res;
}