📄 tcc.c
字号:
file->buf_ptr = p; c = handle_eob(); p = file->buf_ptr; if (c == '\\') { PEEKC_EOB(c, p); if (c == '\n') { file->line_num++; PEEKC_EOB(c, p); } else if (c == '\r') { PEEKC_EOB(c, p); if (c == '\n') { file->line_num++; PEEKC_EOB(c, p); } } } else { goto redo; } } else { p++; } } return p;}/* C comments */static uint8_t *parse_comment(uint8_t *p){ int c; p++; for(;;) { /* fast skip loop */ for(;;) { c = *p; if (c == '\n' || c == '*' || c == '\\') break; p++; c = *p; if (c == '\n' || c == '*' || c == '\\') break; p++; } /* now we can handle all the cases */ if (c == '\n') { file->line_num++; p++; } else if (c == '*') { p++; for(;;) { c = *p; if (c == '*') { p++; } else if (c == '/') { goto end_of_comment; } else if (c == '\\') { file->buf_ptr = p; c = handle_eob(); p = file->buf_ptr; if (c == '\\') { /* skip '\[\r]\n', otherwise just skip the stray */ while (c == '\\') { PEEKC_EOB(c, p); if (c == '\n') { file->line_num++; PEEKC_EOB(c, p); } else if (c == '\r') { PEEKC_EOB(c, p); if (c == '\n') { file->line_num++; PEEKC_EOB(c, p); } } else { goto after_star; } } } } else { break; } } after_star: ; } else { /* stray, eob or eof */ file->buf_ptr = p; c = handle_eob(); p = file->buf_ptr; if (c == CH_EOF) { error("unexpected end of file in comment"); } else if (c == '\\') { p++; } } } end_of_comment: p++; return p;}#define cinp minp/* space exlcuding newline */static inline int is_space(int ch){ return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';}static inline void skip_spaces(void){ while (is_space(ch)) cinp();}/* parse a string without interpreting escapes */static uint8_t *parse_pp_string(uint8_t *p, int sep, CString *str){ int c; p++; for(;;) { c = *p; if (c == sep) { break; } else if (c == '\\') { file->buf_ptr = p; c = handle_eob(); p = file->buf_ptr; if (c == CH_EOF) { unterminated_string: /* XXX: indicate line number of start of string */ error("missing terminating %c character", sep); } 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') { if (str) 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_CFLOAT: case TOK_LINENUM: return 1; case TOK_STR: case TOK_LSTR: case TOK_PPNUM: error("unsupported token"); 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){ tcc_free(str);}static int *tok_str_realloc(TokenString *s){ int *str, len; if (s->allocated_len == 0) { len = 8; } else { len = s->allocated_len * 2; } 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: { int nb_words; CString *cstr; nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2; while ((len + nb_words) > s->allocated_len) str = tok_str_realloc(s); cstr = (CString *)(str + len); cstr->data = NULL; cstr->size = cv->cstr->size; cstr->data_allocated = NULL; cstr->size_allocated = cstr->size; memcpy((char *)cstr + sizeof(CString), cv->cstr->data, cstr->size); len += nb_words; } break; case TOK_CDOUBLE: case TOK_CLLONG: case TOK_CULLONG:#if LDOUBLE_SIZE == 8 case TOK_CLDOUBLE:#endif str[len++] = cv->tab[0]; str[len++] = cv->tab[1]; break;#if LDOUBLE_SIZE == 12 case TOK_CLDOUBLE: str[len++] = cv->tab[0]; str[len++] = cv->tab[1]; str[len++] = cv->tab[2];#elif LDOUBLE_SIZE != 8#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];#elif LDOUBLE_SIZE == 8#define LDOUBLE_GET(p, cv) \ cv.tab[0] = p[0]; \ cv.tab[1] = p[1];#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: \ cv.tab[0] = *p++; \ break; \ case TOK_STR: \ case TOK_LSTR: \ case TOK_PPNUM: \ cv.cstr = (CString *)p; \ cv.cstr->data = (char *)p + sizeof(CString);\ p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\ 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; \ } \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -