cpp_re.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 439 行

CPP
439
字号
/*=============================================================================    Boost.Wave: A Standard compliant C++ preprocessor library    Copyright (c) 2001 Daniel C. Nuffer    Copyright (c) 2001-2008 Hartmut Kaiser.     Distributed under the Boost Software License, Version 1.0. (See accompanying     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)    TODO:         It also may be necessary to add $ to identifiers, for asm.         handle errors better.        have some easier way to parse strings instead of files (done) =============================================================================*/#define BOOST_WAVE_SOURCE 1#include <ctime>#include <cstdlib>#include <cstdio>#include <cstring>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <boost/wave/wave_config.hpp>          // configuration data#if defined(BOOST_HAS_UNISTD_H)#include <unistd.h>#else#include <io.h>#endif #include <boost/assert.hpp>#include <boost/detail/workaround.hpp>#include <boost/wave/token_ids.hpp>#include <boost/wave/cpplexer/re2clex/aq.hpp>#include <boost/wave/cpplexer/re2clex/scanner.hpp>#include <boost/wave/cpplexer/re2clex/cpp_re.hpp>#include <boost/wave/cpplexer/cpplexer_exceptions.hpp>// this must occur after all of the includes and before any code appears#ifdef BOOST_HAS_ABI_HEADERS#include BOOST_ABI_PREFIX#endif///////////////////////////////////////////////////////////////////////////////#if defined(BOOST_MSVC)#pragma warning (disable: 4101)     // 'foo' : unreferenced local variable#pragma warning (disable: 4102)     // 'foo' : unreferenced label#endif///////////////////////////////////////////////////////////////////////////////#define BOOST_WAVE_BSIZE     196608#define YYCTYPE   uchar#define YYCURSOR  cursor#define YYLIMIT   limit#define YYMARKER  marker#define YYFILL(n)                                                             \    {                                                                         \        cursor = uchar_wrapper(fill(s, cursor), cursor.column);               \        limit = uchar_wrapper (s->lim);                                       \    }                                                                         \    /**/#include <iostream>///////////////////////////////////////////////////////////////////////////////#define BOOST_WAVE_UPDATE_CURSOR()                                            \    {                                                                         \        s->line += count_backslash_newlines(s, cursor);                       \        s->curr_column = cursor.column;                                       \        s->cur = cursor;                                                      \        s->lim = limit;                                                       \        s->ptr = marker;                                                      \    }                                                                         \    /**////////////////////////////////////////////////////////////////////////////////#define BOOST_WAVE_RET(i)                                                     \    {                                                                         \        BOOST_WAVE_UPDATE_CURSOR()                                            \        if (s->cur > s->lim)                                                  \            return T_EOF;     /* may happen for empty files */                \        return (i);                                                           \    }                                                                         \    /**////////////////////////////////////////////////////////////////////////////////namespace boost {namespace wave {namespace cpplexer {namespace re2clex {#define RE2C_ASSERT BOOST_ASSERTint get_one_char(Scanner *s){    if (0 != s->act) {        RE2C_ASSERT(s->first != 0 && s->last != 0);        RE2C_ASSERT(s->first <= s->act && s->act <= s->last);        if (s->act < s->last)             return *(s->act)++;    }    return -1;}std::ptrdiff_t rewind_stream (Scanner *s, int cnt){    if (0 != s->act) {        RE2C_ASSERT(s->first != 0 && s->last != 0);        s->act += cnt;        RE2C_ASSERT(s->first <= s->act && s->act <= s->last);        return s->act - s->first;    }    return 0;}std::size_t get_first_eol_offset(Scanner* s){    if (!AQ_EMPTY(s->eol_offsets))    {        return s->eol_offsets->queue[s->eol_offsets->head];    }    else    {        return (unsigned int)-1;    }}void adjust_eol_offsets(Scanner* s, std::size_t adjustment){    aq_queue q;    std::size_t i;        if (!s->eol_offsets)        s->eol_offsets = aq_create();    q = s->eol_offsets;    if (AQ_EMPTY(q))        return;    i = q->head;    while (i != q->tail)    {        if (adjustment > q->queue[i])            q->queue[i] = 0;        else            q->queue[i] -= adjustment;        ++i;        if (i == q->max_size)            i = 0;    }    if (adjustment > q->queue[i])        q->queue[i] = 0;    else        q->queue[i] -= adjustment;}int count_backslash_newlines(Scanner *s, uchar *cursor){    std::size_t diff, offset;    int skipped = 0;        /* figure out how many backslash-newlines skipped over unknowingly. */    diff = cursor - s->bot;    offset = get_first_eol_offset(s);    while (offset <= diff && offset != (unsigned int)-1)    {        skipped++;        aq_pop(s->eol_offsets);        offset = get_first_eol_offset(s);    }    return skipped;}bool is_backslash(uchar *p, uchar *end, int &len){    if (*p == '\\') {        len = 1;        return true;    }    else if (*p == '?' && *(p+1) == '?' && (p+2 < end && *(p+2) == '/')) {        len = 3;        return true;    }    return false;}uchar *fill(Scanner *s, uchar *cursor){    using namespace std;    // some systems have memcpy etc. in namespace std    if(!s->eof)    {        uchar* p;        std::ptrdiff_t cnt = s->tok - s->bot;        if(cnt)        {            if (NULL == s->lim)                s->lim = s->top;            memmove(s->bot, s->tok, s->lim - s->tok);            s->tok = s->cur = s->bot;            s->ptr -= cnt;            cursor -= cnt;            s->lim -= cnt;            adjust_eol_offsets(s, cnt);        }        if((s->top - s->lim) < BOOST_WAVE_BSIZE)        {            uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BOOST_WAVE_BSIZE)*sizeof(uchar));            if (buf == 0)            {                using namespace std;      // some systems have printf in std                if (0 != s->error_proc) {                    (*s->error_proc)(s, lexing_exception::unexpected_error,                         "Out of memory!");                }                else                     printf("Out of memory!\n");                                    /* get the scanner to stop */                *cursor = 0;                return cursor;            }            memmove(buf, s->tok, s->lim - s->tok);            s->tok = s->cur = buf;            s->ptr = &buf[s->ptr - s->bot];            cursor = &buf[cursor - s->bot];            s->lim = &buf[s->lim - s->bot];            s->top = &s->lim[BOOST_WAVE_BSIZE];            free(s->bot);            s->bot = buf;        }        if (s->act != 0) {            cnt = s->last - s->act;            if (cnt > BOOST_WAVE_BSIZE)                cnt = BOOST_WAVE_BSIZE;            memmove(s->lim, s->act, cnt);            s->act += cnt;            if (cnt != BOOST_WAVE_BSIZE)             {                s->eof = &s->lim[cnt]; *(s->eof)++ = '\0';            }        }                /* backslash-newline erasing time */        /* first scan for backslash-newline and erase them */        for (p = s->lim; p < s->lim + cnt - 2; ++p)        {            int len = 0;            if (is_backslash(p, s->lim + cnt, len))            {                if (*(p+len) == '\n')                {                    int offset = len + 1;                    memmove(p, p + offset, s->lim + cnt - p - offset);                    cnt -= offset;                    --p;                    aq_enqueue(s->eol_offsets, p - s->bot + 1);                    }                else if (*(p+len) == '\r')                {                    if (*(p+len+1) == '\n')                    {                        int offset = len + 2;                        memmove(p, p + offset, s->lim + cnt - p - offset);                        cnt -= offset;                        --p;                    }                    else                    {                        int offset = len + 1;                        memmove(p, p + offset, s->lim + cnt - p - offset);                        cnt -= offset;                        --p;                    }                    aq_enqueue(s->eol_offsets, p - s->bot + 1);                    }            }        }        /* FIXME: the following code should be fixed to recognize correctly the                   trigraph backslash token */                          /* check to see if what we just read ends in a backslash */        if (cnt >= 2)        {            uchar last = s->lim[cnt-1];            uchar last2 = s->lim[cnt-2];            /* check \ EOB */            if (last == '\\')            {                int next = get_one_char(s);                /* check for \ \n or \ \r or \ \r \n straddling the border */                if (next == '\n')                {                    --cnt; /* chop the final \, we've already read the \n. */                    aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));                    }                else if (next == '\r')                {                    int next2 = get_one_char(s);                    if (next2 == '\n')                    {                        --cnt; /* skip the backslash */                    }                    else                    {                        /* rewind one, and skip one char */                        rewind_stream(s, -1);                        --cnt;                    }                    aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));                    }                else if (next != -1) /* -1 means end of file */                {                    /* next was something else, so rewind the stream */                    rewind_stream(s, -1);                }            }            /* check \ \r EOB */            else if (last == '\r' && last2 == '\\')            {                int next = get_one_char(s);                if (next == '\n')                {                    cnt -= 2; /* skip the \ \r */                }                else                {                    /* rewind one, and skip two chars */                    rewind_stream(s, -1);                    cnt -= 2;                }                aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));                }            /* check \ \n EOB */            else if (last == '\n' && last2 == '\\')            {                cnt -= 2;                aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));                }        }                s->lim += cnt;        if (s->eof) /* eof needs adjusting if we erased backslash-newlines */        {            s->eof = s->lim;            *(s->eof)++ = '\0';        }    }    return cursor;}/////////////////////////////////////////////////////////////////////////////////  Special wrapper class holding the current cursor position struct uchar_wrapper{    uchar_wrapper (uchar *base_cursor, unsigned int column = 1)    :   base_cursor(base_cursor), column(column)    {}        uchar_wrapper& operator++()     {        ++base_cursor;        ++column;        return *this;    }        uchar_wrapper& operator--()     {        --base_cursor;        --column;        return *this;    }        uchar operator* () const    {        return *base_cursor;    }        operator uchar *() const    {        return base_cursor;    }        friend std::ptrdiff_t     operator- (uchar_wrapper const& lhs, uchar_wrapper const& rhs)    {        return lhs.base_cursor - rhs.base_cursor;    }        uchar *base_cursor;    unsigned int column;};///////////////////////////////////////////////////////////////////////////////boost::wave::token_id scan(Scanner *s){    BOOST_ASSERT(0 != s->error_proc);     // error handler must be given        uchar_wrapper cursor (s->tok = s->cur, s->column = s->curr_column);    uchar_wrapper marker (s->ptr);    uchar_wrapper limit (s->lim);// include the correct Re2C token definition rules#if BOOST_WAVE_USE_STRICT_LEXER != 0#include "strict_cpp_re.inc"#else#include "cpp_re.inc"#endif} /* end of scan *////////////////////////////////////////////////////////////////////////////////}   // namespace re2clex}   // namespace cpplexer}   // namespace wave}   // namespace boost#undef BOOST_WAVE_RET#undef BOOST_WAVE_BSIZE #undef YYCTYPE#undef YYCURSOR#undef YYLIMIT#undef YYMARKER#undef YYFILL// the suffix header occurs after all of the code#ifdef BOOST_HAS_ABI_HEADERS#include BOOST_ABI_SUFFIX#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?