int mof_parseliteralstring()

in LCM/codec/mof/parser/moflex.c [278:432]


int mof_parseliteralstring(_Inout_ MOF_State * state)
{
    Buffer buf = BUFFER_INITIALIZER;
    MOF_Buffer * mb = &(state->buf);
    wchar_t nullterm = L'\0';
    size_t n = 0;
    void * bufToAppend;
    char chr;
    wchar_t wchr;

    _mof_buffer_marktokenstart(mb);

    /* Skip " character */
    mof_nextchar(mb);

    /* Scan until the closing " is found */
    for (;;)
    {
        if (mof_eof(mb) || mof_isdoulbequotes(mb->e, mb->cur))
            break;

        bufToAppend = mb->cur;

        /* if backslash, get next character */
        if (mof_isbackslash(mb->e, mb->cur))
        {
            int c = mof_nextcharn(mb, &n);
            char ec;
            unsigned long escapedchar;
            int r;
            if (mof_eof(mb))
                break;

            /* Parse escaped HEX char \xXXXX */
            if (c == 'x' || c == 'X')
            {
                int len = 0;
                MI_Boolean incompletechar = MI_FALSE;
                char hexbuf[5 * sizeof(wchar_t)] = {0};
                void *hexdata = hexbuf;
                while(mof_neof(mb) && (len < 4))
                {
                    c = mof_nextchar(mb);
                    if (mof_isdoulbequotes(mb->e, mb->cur))
                    {
                        incompletechar = MI_TRUE;
                        break;
                    }
                    hexdata = mof_setchar(mb->e.u, hexdata, c);
                    len ++;
                }
                if (incompletechar || (len != 4) || mof_eof(mb))
                {
                    yyerrorf(state->errhandler, ID_SYNTAX_ERROR_INCOMPLETE_ESCAPED_CHAR16_VALUE,
                        "",
                        mb->llineNo,
                        mb->lcharPosOfLine);
                    return TOK_ERROR;
                }
                /* convert HEX string to integer */
                {
                    unsigned long chr = 0;
                    MI_Boolean res;
                    mof_setchar(mb->e.u, hexdata, 0);
                    res = mof_isvalidhexstring(state->buf.e.u, hexbuf, (size_t)len);
                    if (res == MI_TRUE)
                    {
                        res = mof_strtoul(state->buf.e.u,
                            hexbuf,
                            16,
                            NULL,
                            &chr);
                    }
                    if (MI_FALSE == res)
                    {
                        yyerrorf(state->errhandler, ID_ILLEGAL_HEX_CHARACTER, "", (MI_Char*)hexbuf);
                        return TOK_ERROR;
                    }
                    escapedchar = chr;
                }
            }
            else
            {
                /* Parse escaped char other than HEX char */
                r = _mof_getescapedchar(c, &ec);
                escapedchar = ec;
                if (r != 0)
                {
                    yyerrorf(state->errhandler, ID_SYNTAX_ERROR_INVALID_ESCAPED_CHAR, "", c);
                    return TOK_ERROR;
                }
            }

            if (mb->e.u)
            {
                if (mb->e.t == UTF16BE || mb->e.t == UNIBE)
                {
                    /* Might not work on non-windows platform */
                    wchar_t w = (wchar_t)escapedchar;
                    wchr = (w << 8) + (w >> 8);
                }
                else
                {
                    wchr = (wchar_t)escapedchar;
                }
                bufToAppend = &wchr;
            }
            else
            {
                chr = (char)escapedchar;
                bufToAppend = &chr;
            }
        }

        /* Append character to buffer */
        if (mof_bufferappend(state, &buf, bufToAppend) != 0)
        {
            yyerrorf(state->errhandler, ID_OUT_OF_MEMORY, "out of memory");
            return TOK_ERROR;
        }
        mof_nextcharn(mb, &n);
    }
    if (mof_eof(mb))
    {
        yyerrorf(state->errhandler, ID_SYNTAX_ERROR_INCOMPLETE_STRING_VALUE, "",
            mb->llineNo, mb->lcharPosOfLine);
        return TOK_ERROR;
    }

    /* Skip closing " character */
    mof_nextchar(mb);

    /* Append zero-terminator */
    if (mof_bufferappend(state, &buf, &nullterm) != 0)
    {
        yyerrorf(state->errhandler, ID_OUT_OF_MEMORY, "out of memory");
        return TOK_ERROR;
    }
    n++;

    /* Copy listeral string and return */
    {
        int ret;
        MOF_StringLen r;
        r.len = n;
        r.str.data = buf.data;
        if (mof_converttoUTF16LE(state, &r) != 0)
        {
            return TOK_ERROR;
        }
        ret = mof_getidentifiervalue(state, &r);
        if (ret == 0) return TOK_STRING_VALUE;
        else return ret;
    }
}