⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcc.c

📁 tcc
💻 C
📖 第 1 页 / 共 5 页
字号:
            } else if (c == '\\') {                /* escape : just skip \[\r]\n */                PEEKC_EOB(c, p);                if (c == '\n') {                    file->line_num++;                    p++;                } else if (c == '\r') {                    PEEKC_EOB(c, p);                    if (c != '\n')                        expect("'\n' after '\r'");                    file->line_num++;                    p++;                } else if (c == CH_EOF) {                    goto unterminated_string;                } else {                    if (str) {                        cstr_ccat(str, '\\');                        cstr_ccat(str, c);                    }                    p++;                }            }        } else if (c == '\n') {            file->line_num++;            goto add_char;        } else if (c == '\r') {            PEEKC_EOB(c, p);            if (c != '\n') {                cstr_ccat(str, '\r');            } else {                file->line_num++;                goto add_char;            }        } else {        add_char:            if (str)                cstr_ccat(str, c);            p++;        }    }    p++;    return p;}/* skip block of text until #else, #elif or #endif. skip also pairs of   #if/#endif */void preprocess_skip(void){    int a, start_of_line, c;    uint8_t *p;    p = file->buf_ptr;    start_of_line = 1;    a = 0;    for(;;) {    redo_no_start:        c = *p;        switch(c) {        case ' ':        case '\t':        case '\f':        case '\v':        case '\r':            p++;            goto redo_no_start;        case '\n':            start_of_line = 1;            file->line_num++;            p++;            goto redo_no_start;        case '\\':            file->buf_ptr = p;            c = handle_eob();            if (c == CH_EOF) {                expect("#endif");            } else if (c == '\\') {                /* XXX: incorrect: should not give an error */                ch = file->buf_ptr[0];                handle_stray();            }            p = file->buf_ptr;            goto redo_no_start;            /* skip strings */        case '\"':        case '\'':            p = parse_pp_string(p, c, NULL);            break;            /* skip comments */        case '/':            file->buf_ptr = p;            ch = *p;            minp();            p = file->buf_ptr;            if (ch == '*') {                p = parse_comment(p);            } else if (ch == '/') {                p = parse_line_comment(p);            }            break;        case '#':            p++;            if (start_of_line) {                file->buf_ptr = p;                next_nomacro();                p = file->buf_ptr;                if (a == 0 &&                     (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))                    goto the_end;                if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)                    a++;                else if (tok == TOK_ENDIF)                    a--;            }            break;        default:            p++;            break;        }        start_of_line = 0;    } the_end: ;    file->buf_ptr = p;}/* ParseState handling *//* XXX: currently, no include file info is stored. Thus, we cannot display   accurate messages if the function or data definition spans multiple   files *//* save current parse state in 's' */void save_parse_state(ParseState *s){    s->line_num = file->line_num;    s->macro_ptr = macro_ptr;    s->tok = tok;    s->tokc = tokc;}/* restore parse state from 's' */void restore_parse_state(ParseState *s){    file->line_num = s->line_num;    macro_ptr = s->macro_ptr;    tok = s->tok;    tokc = s->tokc;}/* return the number of additional 'ints' necessary to store the   token */static inline int tok_ext_size(int t){    switch(t) {        /* 4 bytes */    case TOK_CINT:    case TOK_CUINT:    case TOK_CCHAR:    case TOK_LCHAR:    case TOK_STR:    case TOK_LSTR:    case TOK_CFLOAT:    case TOK_LINENUM:    case TOK_PPNUM:        return 1;    case TOK_CDOUBLE:    case TOK_CLLONG:    case TOK_CULLONG:        return 2;    case TOK_CLDOUBLE:        return LDOUBLE_SIZE / 4;    default:        return 0;    }}/* token string handling */static inline void tok_str_new(TokenString *s){    s->str = NULL;    s->len = 0;    s->allocated_len = 0;    s->last_line_num = -1;}static void tok_str_free(int *str){    const int *p;    CString *cstr;    int t;    p = str;    for(;;) {        t = *p;        /* NOTE: we test zero separately so that GCC can generate a           table for the following switch */        if (t == 0)            break;        switch(t) {        case TOK_CINT:        case TOK_CUINT:        case TOK_CCHAR:        case TOK_LCHAR:        case TOK_CFLOAT:        case TOK_LINENUM:            p += 2;            break;        case TOK_PPNUM:        case TOK_STR:        case TOK_LSTR:            /* XXX: use a macro to be portable on 64 bit ? */            cstr = (CString *)p[1];            cstr_free(cstr);            tcc_free(cstr);            p += 2;            break;        case TOK_CDOUBLE:        case TOK_CLLONG:        case TOK_CULLONG:            p += 3;            break;        case TOK_CLDOUBLE:            p += 1 + (LDOUBLE_SIZE / 4);            break;        default:            p++;            break;        }    }    tcc_free(str);}static int *tok_str_realloc(TokenString *s){    int *str, len;    len = s->allocated_len + TOK_STR_ALLOC_INCR;    str = tcc_realloc(s->str, len * sizeof(int));    if (!str)        error("memory full");    s->allocated_len = len;    s->str = str;    return str;}static void tok_str_add(TokenString *s, int t){    int len, *str;    len = s->len;    str = s->str;    if (len >= s->allocated_len)        str = tok_str_realloc(s);    str[len++] = t;    s->len = len;}static void tok_str_add2(TokenString *s, int t, CValue *cv){    int len, *str;    len = s->len;    str = s->str;    /* allocate space for worst case */    if (len + TOK_MAX_SIZE > s->allocated_len)        str = tok_str_realloc(s);    str[len++] = t;    switch(t) {    case TOK_CINT:    case TOK_CUINT:    case TOK_CCHAR:    case TOK_LCHAR:    case TOK_CFLOAT:    case TOK_LINENUM:        str[len++] = cv->tab[0];        break;    case TOK_PPNUM:    case TOK_STR:    case TOK_LSTR:        str[len++] = (int)cstr_dup(cv->cstr);        break;    case TOK_CDOUBLE:    case TOK_CLLONG:    case TOK_CULLONG:        str[len++] = cv->tab[0];        str[len++] = cv->tab[1];        break;    case TOK_CLDOUBLE:#if LDOUBLE_SIZE == 12        str[len++] = cv->tab[0];        str[len++] = cv->tab[1];        str[len++] = cv->tab[2];#else#error add long double size support#endif        break;    default:        break;    }    s->len = len;}/* add the current parse token in token string 's' */static void tok_str_add_tok(TokenString *s){    CValue cval;    /* save line number info */    if (file->line_num != s->last_line_num) {        s->last_line_num = file->line_num;        cval.i = s->last_line_num;        tok_str_add2(s, TOK_LINENUM, &cval);    }    tok_str_add2(s, tok, &tokc);}#if LDOUBLE_SIZE == 12#define LDOUBLE_GET(p, cv)                      \        cv.tab[0] = p[0];                       \        cv.tab[1] = p[1];                       \        cv.tab[2] = p[2];#else#error add long double size support#endif/* get a token from an integer array and increment pointer   accordingly. we code it as a macro to avoid pointer aliasing. */#define TOK_GET(t, p, cv)                       \{                                               \    t = *p++;                                   \    switch(t) {                                 \    case TOK_CINT:                              \    case TOK_CUINT:                             \    case TOK_CCHAR:                             \    case TOK_LCHAR:                             \    case TOK_CFLOAT:                            \    case TOK_LINENUM:                           \    case TOK_STR:                               \    case TOK_LSTR:                              \    case TOK_PPNUM:                             \        cv.tab[0] = *p++;                       \        break;                                  \    case TOK_CDOUBLE:                           \    case TOK_CLLONG:                            \    case TOK_CULLONG:                           \        cv.tab[0] = p[0];                       \        cv.tab[1] = p[1];                       \        p += 2;                                 \        break;                                  \    case TOK_CLDOUBLE:                          \        LDOUBLE_GET(p, cv);                     \        p += LDOUBLE_SIZE / 4;                  \        break;                                  \    default:                                    \        break;                                  \    }                                           \}/* defines handling */static inline void define_push(int v, int macro_type, int *str, Sym *first_arg){    Sym *s;    s = sym_push2(&define_stack, v, macro_type, (int)str);    s->next = first_arg;    table_ident[v - TOK_IDENT]->sym_define = s;}/* undefined a define symbol. Its name is just set to zero */static void define_undef(Sym *s){    int v;    v = s->v;    if (v >= TOK_IDENT && v < tok_ident)        table_ident[v - TOK_IDENT]->sym_define = NULL;    s->v = 0;}static inline Sym *define_find(int v){    v -= TOK_IDENT;    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))        return NULL;    return table_ident[v]->sym_define;}/* free define stack until top reaches 'b' */static void free_defines(Sym *b){    Sym *top, *top1;    int v;    top = define_stack;    while (top != b) {        top1 = top->prev;        /* do not free args or predefined defines */        if (top->c)            tok_str_free((int *)top->c);        v = top->v;        if (v >= TOK_IDENT && v < tok_ident)            table_ident[v - TOK_IDENT]->sym_define = NULL;        tcc_free(top);        top = top1;    }    define_stack = b;}/* label lookup */static Sym *label_find(int v){    v -= TOK_IDENT;    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))        return NULL;    return table_ident[v]->sym_label;}static Sym *label_push(Sym **ptop, int v, int flags){    Sym *s, **ps;    s = sym_push2(ptop, v, 0, 0);    s->r = flags;    ps = &table_ident[v - TOK_IDENT]->sym_label;    if (ptop == &global_label_stack) {        /* modify the top most local identifier, so that           sym_identifier will point to 's' when popped */        while (*ps != NULL)            ps = &(*ps)->prev_tok;    }    s->prev_tok = *ps;    *ps = s;    return s;}/* pop labels until element last is reached. Look if any labels are   undefined. Define symbols if '&&label' was used. */static void label_pop(Sym **ptop, Sym *slast){    Sym *s, *s1;    for(s = *ptop; s != slast; s = s1) {        s1 = s->prev;        if (s->r == LABEL_DECLARED) {            warning("label '%s' declared but not used", get_tok_str(s->v, NULL));        } else if (s->r == LABEL_FORWARD) {                error("label '%s' used but not defined",                      get_tok_str(s->v, NULL));        } else {            if (s->c) {                /* define corresponding symbol. A size of                   1 is put. */                put_extern_sym(s, cur_text_section, (long)s->next, 1);            }        }        /* remove label */        table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;        tcc_free(s);    }    *ptop = slast;}/* eval an expression for #if/#elif */static int expr_preprocess(void){    int c, t;    TokenString str;        tok_str_new(&str);    while (tok != TOK_LINEFEED && tok != TOK_EOF) {        next(); /* do macro subst */        if (tok == TOK_DEFINED) {            next_nomacro();            t = tok;            if (t == '(')                 next_nomacro();            c = define_find(tok) != 0;            if (t == '(')                next_nomacro();            tok = TOK_C

⌨️ 快捷键说明

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