Пример #1
0
static void
copy_cooked(ch_t** ppDest, char const ** ppSrc)
{
    ch_t* pDest = (ch_t*)*ppDest;
    const ch_t* pSrc  = (const ch_t*)(*ppSrc + 1);

    for (;;) {
        ch_t ch = *(pSrc++);
        switch (ch) {
        case NUL:   *ppSrc = NULL; return;
        case '"':   goto done;
        case '\\':
            pSrc += ao_string_cook_escape_char((char*)(intptr_t)pSrc, (char*)(intptr_t)&ch, 0x7F);
            if (ch == 0x7F)
                break;
            /* FALLTHROUGH */

        default:
            *(pDest++) = ch;
        }
    }

 done:
    *ppDest = (ch_t*)pDest; /* next spot for storing character */
    *ppSrc  = (char const *)pSrc;  /* char following closing quote    */
}
Пример #2
0
/*=export_func  ao_string_cook
 * private:
 *
 * what:  concatenate and escape-process strings
 * arg:   + char * + pzScan  + The *MODIFIABLE* input buffer +
 * arg:   + int *  + lnct_p  + The (possibly NULL) pointer to a line count +
 *
 * ret-type: char *
 * ret-desc: The address of the text following the processed strings.
 *           The return value is NULL if the strings are ill-formed.
 *
 * doc:
 *
 *  A series of one or more quoted strings are concatenated together.
 *  If they are quoted with double quotes (@code{"}), then backslash
 *  escapes are processed per the C programming language.  If they are
 *  single quote strings, then the backslashes are honored only when they
 *  precede another backslash or a single quote character.
 *
 * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
=*/
char *
ao_string_cook(char * pzScan, int * lnct_p)
{
    int   l = 0;
    char  q = *pzScan;

    /*
     *  It is a quoted string.  Process the escape sequence characters
     *  (in the set "abfnrtv") and make sure we find a closing quote.
     */
    char * pzD = pzScan++;
    char * pzS = pzScan;

    if (lnct_p == NULL)
        lnct_p = &l;

    for (;;) {
        /*
         *  IF the next character is the quote character, THEN we may end the
         *  string.  We end it unless the next non-blank character *after* the
         *  string happens to also be a quote.  If it is, then we will change
         *  our quote character to the new quote character and continue
         *  condensing text.
         */
        while (*pzS == q) {
            *pzD = NUL; /* This is probably the end of the line */
            if (! contiguous_quote(&pzS, &q, lnct_p))
                return pzS;
        }

        /*
         *  We are inside a quoted string.  Copy text.
         */
        switch (*(pzD++) = *(pzS++)) {
        case NUL:
            return NULL;

        case NL:
            (*lnct_p)++;
            break;

        case '\\':
            /*
             *  IF we are escaping a new line,
             *  THEN drop both the escape and the newline from
             *       the result string.
             */
            if (*pzS == NL) {
                pzS++;
                pzD--;
                (*lnct_p)++;
            }

            /*
             *  ELSE IF the quote character is '"' or '`',
             *  THEN we do the full escape character processing
             */
            else if (q != '\'') {
                unsigned int ct;
                ct = ao_string_cook_escape_char(pzS, pzD-1, (uint_t)NL);
                if (ct == 0)
                    return NULL;

                pzS += ct;
            }     /* if (q != '\'')                  */

            /*
             *  OTHERWISE, we only process "\\", "\'" and "\#" sequences.
             *  The latter only to easily hide preprocessing directives.
             */
            else switch (*pzS) {
            case '\\':
            case '\'':
            case '#':
                pzD[-1] = *pzS++;
            }
        }     /* switch (*(pzD++) = *(pzS++))    */
    }         /* for (;;)                        */
}
Пример #3
0
/*=export_func  ao_string_cook
 * private:
 *
 * what:  concatenate and escape-process strings
 * arg:   + char* + pzScan     + The *MODIFIABLE* input buffer +
 * arg:   + int*  + pLineCt    + The (possibly NULL) pointer to a line count +
 *
 * ret-type: char*
 * ret-desc: The address of the text following the processed strings.
 *           The return value is NULL if the strings are ill-formed.
 *
 * doc:
 *
 *  A series of one or more quoted strings are concatenated together.
 *  If they are quoted with double quotes (@code{"}), then backslash
 *  escapes are processed per the C programming language.  If they are
 *  single quote strings, then the backslashes are honored only when they
 *  precede another backslash or a single quote character.
 *
 * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
=*/
char*
ao_string_cook( char* pzScan, int* pLineCt )
{
    int   l = 0;
    char  q = *pzScan;

    /*
     *  It is a quoted string.  Process the escape sequence characters
     *  (in the set "abfnrtv") and make sure we find a closing quote.
     */
    char* pzD = pzScan++;
    char* pzS = pzScan;

    if (pLineCt == NULL)
        pLineCt = &l;

    for (;;) {
        /*
         *  IF the next character is the quote character, THEN we may end the
         *  string.  We end it unless the next non-blank character *after* the
         *  string happens to also be a quote.  If it is, then we will change
         *  our quote character to the new quote character and continue
         *  condensing text.
         */
        while (*pzS == q) {
            *pzD = NUL; /* This is probably the end of the line */
            pzS++;

        scan_for_quote:
            while (isspace((int)*pzS))
                if (*(pzS++) == '\n')
                    (*pLineCt)++;

            /*
             *  IF the next character is a quote character,
             *  THEN we will concatenate the strings.
             */
            switch (*pzS) {
            case '"':
            case '\'':
                break;

            case '/':
                /*
                 *  Allow for a comment embedded in the concatenated string.
                 */
                switch (pzS[1]) {
                default:  return NULL;
                case '/':
                    /*
                     *  Skip to end of line
                     */
                    pzS = strchr( pzS, '\n' );
                    if (pzS == NULL)
                        return NULL;
                    (*pLineCt)++;
                    break;

                case '*':
                {
                    char* p = strstr( pzS+2, "*/" );
                    /*
                     *  Skip to terminating star slash
                     */
                    if (p == NULL)
                        return NULL;
                    while (pzS < p) {
                        if (*(pzS++) == '\n')
                            (*pLineCt)++;
                    }

                    pzS = p + 2;
                }
                }
                goto scan_for_quote;

            default:
                /*
                 *  The next non-whitespace character is not a quote.
                 *  The series of quoted strings has come to an end.
                 */
                return pzS;
            }

            q = *(pzS++);  /* assign new quote character and advance scan */
        }

        /*
         *  We are inside a quoted string.  Copy text.
         */
        switch (*(pzD++) = *(pzS++)) {
        case NUL:
            return NULL;

        case '\n':
            (*pLineCt)++;
            break;

        case '\\':
            /*
             *  IF we are escaping a new line,
             *  THEN drop both the escape and the newline from
             *       the result string.
             */
            if (*pzS == '\n') {
                pzS++;
                pzD--;
                (*pLineCt)++;
            }

            /*
             *  ELSE IF the quote character is '"' or '`',
             *  THEN we do the full escape character processing
             */
            else if (q != '\'') {
                int ct = ao_string_cook_escape_char( pzS, pzD-1, (u_int)'\n' );
                if (ct == 0)
                    return NULL;

                pzS += ct;
            }     /* if (q != '\'')                  */

            /*
             *  OTHERWISE, we only process "\\", "\'" and "\#" sequences.
             *  The latter only to easily hide preprocessing directives.
             */
            else switch (*pzS) {
            case '\\':
            case '\'':
            case '#':
                pzD[-1] = *pzS++;
            }
        }     /* switch (*(pzD++) = *(pzS++))    */
    }         /* for (;;)                        */
}