diff --git a/tcc.h b/tcc.h index e4c38b53..7bae6aff 100644 --- a/tcc.h +++ b/tcc.h @@ -502,7 +502,7 @@ typedef union CValue { float f; uint64_t i; struct { - const void *data; + char *data; int size; } str; int tab[LDOUBLE_SIZE/4]; @@ -1390,6 +1390,7 @@ ST_FUNC void define_undef(Sym *s); ST_INLN Sym *define_find(int v); ST_FUNC void free_defines(Sym *b); ST_FUNC void parse_define(void); +ST_FUNC void skip_to_eol(int warn); ST_FUNC void preprocess(int is_bof); ST_FUNC void next(void); ST_INLN void unget_tok(int last_tok); @@ -1397,6 +1398,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype); ST_FUNC void preprocess_end(TCCState *s1); ST_FUNC void tccpp_new(TCCState *s); ST_FUNC void tccpp_delete(TCCState *s); +ST_FUNC void tccpp_putfile(const char *filename); ST_FUNC int tcc_preprocess(TCCState *s1); ST_FUNC void skip(int c); ST_FUNC NORETURN void expect(const char *msg); @@ -1822,7 +1824,7 @@ ST_FUNC void tcc_debug_start(TCCState *s1); ST_FUNC void tcc_debug_end(TCCState *s1); ST_FUNC void tcc_debug_bincl(TCCState *s1); ST_FUNC void tcc_debug_eincl(TCCState *s1); -ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename); +ST_FUNC void tcc_debug_newfile(TCCState *s1); ST_FUNC void tcc_debug_line(TCCState *s1); ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e); diff --git a/tccasm.c b/tccasm.c index ba7ffe97..d056c703 100644 --- a/tccasm.c +++ b/tccasm.c @@ -728,7 +728,7 @@ static void asm_parse_directive(TCCState *s1, int global) case TOK_ASMDIR_ascii: case TOK_ASMDIR_asciz: { - const uint8_t *p; + const char *p; int i, size, t; t = tok; @@ -772,15 +772,21 @@ static void asm_parse_directive(TCCState *s1, int global) break; case TOK_ASMDIR_file: { - char filename[512]; - - filename[0] = '\0'; + const char *p; + parse_flags &= ~PARSE_FLAG_TOK_STR; next(); - if (tok == TOK_STR) - pstrcat(filename, sizeof(filename), tokc.str.data); - else - pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL)); - tcc_warning_c(warn_unsupported)("ignoring .file %s", filename); + if (tok == TOK_PPNUM) + next(); + if (tok == TOK_PPSTR && tokc.str.data[0] == '"') { + tokc.str.data[tokc.str.size - 2] = 0; + p = tokc.str.data + 1; + } else if (tok >= TOK_IDENT) { + p = get_tok_str(tok, &tokc); + } else { + skip_to_eol(0); + break; + } + tccpp_putfile(p); next(); } break; @@ -968,6 +974,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) next(); if (tok == TOK_EOF) break; + tcc_debug_line(s1); parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ redo: if (tok == '#') { @@ -1033,9 +1040,8 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) /* GCC inline asm support */ /* assemble the string 'str' in the current C compilation unit without - C preprocessing. NOTE: str is modified by modifying the '\0' at the - end */ -static void tcc_assemble_inline(TCCState *s1, char *str, int len, int global) + C preprocessing. */ +static void tcc_assemble_inline(TCCState *s1, const char *str, int len, int global) { const int *saved_macro_ptr = macro_ptr; int dotid = set_idnum('.', IS_ID); diff --git a/tccdbg.c b/tccdbg.c index a2c6b56f..7760f4fd 100644 --- a/tccdbg.c +++ b/tccdbg.c @@ -1048,11 +1048,8 @@ static BufferedFile* put_new_file(TCCState *s1) } /* put alternative filename */ -ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename) +ST_FUNC void tcc_debug_newfile(TCCState *s1) { - if (0 == strcmp(file->filename, filename)) - return; - pstrcpy(file->filename, sizeof(file->filename), filename); if (!s1->do_debug) return; if (s1->dwarf) diff --git a/tccgen.c b/tccgen.c index abde20c4..a1c7db47 100644 --- a/tccgen.c +++ b/tccgen.c @@ -8387,7 +8387,7 @@ static void gen_inline_functions(TCCState *s) /* the function was used or forced (and then not internal): generate its code and convert it to a normal function */ fn->sym = NULL; - tcc_debug_putfile(s, fn->filename); + tccpp_putfile(fn->filename); begin_macro(fn->func_str, 1); next(); cur_text_section = text_section; diff --git a/tccpp.c b/tccpp.c index 7f9bb627..6f2bc173 100644 --- a/tccpp.c +++ b/tccpp.c @@ -53,6 +53,8 @@ static int pp_debug_tok, pp_debug_symv; static int pp_counter; static void tok_print(const int *str, const char *msg, ...); static void next_nomacro(void); +static void parse_number(const char *p); +static void parse_string(const char *p, int len); static struct TinyAlloc *toksym_alloc; static struct TinyAlloc *tokstr_alloc; @@ -884,7 +886,6 @@ redo_start: start_of_line = 1; in_warn_or_error = 0; for(;;) { - redo_no_start: c = *p; switch(c) { case ' ': @@ -893,7 +894,7 @@ redo_start: case '\v': case '\r': p++; - goto redo_no_start; + continue; case '\n': file->line_num++; p++; @@ -904,7 +905,7 @@ redo_start: expect("#endif"); if (c == '\\') ++p; - goto redo_no_start; + continue; /* skip strings */ case '\"': case '\'': @@ -924,7 +925,7 @@ redo_start: } else if (c == '/') { p = parse_line_comment(p); } - break; + continue; case '#': p++; if (start_of_line) { @@ -1209,7 +1210,7 @@ static inline void tok_get(int *t, const int **pp, CValue *cv) case TOK_PPNUM: case TOK_PPSTR: cv->str.size = *p++; - cv->str.data = p; + cv->str.data = (char*)p; p += (cv->str.size + sizeof(int) - 1) / sizeof(int); break; case TOK_CDOUBLE: @@ -1331,6 +1332,16 @@ static void maybe_run_test(TCCState *s) define_push(tok, MACRO_OBJ, NULL, NULL); } +ST_FUNC void skip_to_eol(int warn) +{ + if (tok == TOK_LINEFEED) + return; + if (warn) + tcc_warning("extra tokens after directive"); + file->buf_ptr = parse_line_comment(file->buf_ptr - 1); + tok = TOK_LINEFEED; +} + static CachedInclude * search_cached_include(TCCState *s1, const char *filename, int add); @@ -1370,6 +1381,9 @@ static int parse_include(TCCState *s1, int do_next, int test) memmove(p, p + 1, i - 1), p[i - 1] = 0; } + if (!test) + skip_to_eol(1); + i = do_next ? file->include_next_index : -1; for (;;) { ++i; @@ -1658,7 +1672,7 @@ static CachedInclude *search_cached_include(TCCState *s1, const char *filename, return e; } -static void pragma_parse(TCCState *s1) +static int pragma_parse(TCCState *s1) { next_nomacro(); if (tok == TOK_push_macro || tok == TOK_pop_macro) { @@ -1690,7 +1704,7 @@ static void pragma_parse(TCCState *s1) pp_debug_tok = t, pp_debug_symv = v; } else if (tok == TOK_once) { - search_cached_include(s1, file->filename, 1)->once = 1; + search_cached_include(s1, file->true_filename, 1)->once = 1; } else if (s1->output_type == TCC_OUTPUT_PREPROCESS) { /* tcc -E: keep pragmas below unchanged */ @@ -1698,6 +1712,7 @@ static void pragma_parse(TCCState *s1) unget_tok(TOK_PRAGMA); unget_tok('#'); unget_tok(TOK_LINEFEED); + return 1; } else if (tok == TOK_pack) { /* This may be: @@ -1749,7 +1764,7 @@ static void pragma_parse(TCCState *s1) skip(','); if (tok != TOK_STR) goto pragma_err; - p = tcc_strdup((char *)tokc.str.data); + p = tcc_strdup(tokc.str.data); next(); if (tok != ')') goto pragma_err; @@ -1761,13 +1776,37 @@ static void pragma_parse(TCCState *s1) tcc_free(p); } - } else - tcc_warning_c(warn_unsupported)("#pragma %s ignored", get_tok_str(tok, &tokc)); - return; - + } else { + tcc_warning_c(warn_all)("#pragma %s ignored", get_tok_str(tok, &tokc)); + return 0; + } + next(); + return 1; pragma_err: tcc_error("malformed #pragma directive"); - return; +} + +/* put alternative filename */ +ST_FUNC void tccpp_putfile(const char *filename) +{ + char buf[1024]; + buf[0] = 0; + if (!IS_ABSPATH(filename)) { + /* prepend directory from real file */ + pstrcpy(buf, sizeof buf, file->true_filename); + *tcc_basename(buf) = 0; + } + pstrcat(buf, sizeof buf, filename); +#ifdef _WIN32 + normalize_slashes(buf); +#endif + if (0 == strcmp(file->filename, buf)) + return; + //printf("new file '%s'\n", buf); + if (file->true_filename == file->filename) + file->true_filename = tcc_strdup(file->filename); + pstrcpy(file->filename, sizeof file->filename, buf); + tcc_debug_newfile(tcc_state); } /* is_bof is true if first non space token at beginning of file */ @@ -1803,6 +1842,7 @@ ST_FUNC void preprocess(int is_bof) /* undefine symbol by putting an invalid name */ if (s) define_undef(s); + next_nomacro(); break; case TOK_INCLUDE: case TOK_INCLUDE_NEXT: @@ -1832,12 +1872,14 @@ ST_FUNC void preprocess(int is_bof) || tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT) c ^= 1; + next_nomacro(); do_if: if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) tcc_error("memory full (ifdef)"); *s1->ifdef_stack_ptr++ = c; goto test_skip; case TOK_ELSE: + next_nomacro(); if (s1->ifdef_stack_ptr == s1->ifdef_stack) tcc_error("#else without matching #if"); if (s1->ifdef_stack_ptr[-1] & 2) @@ -1852,6 +1894,7 @@ ST_FUNC void preprocess(int is_bof) tcc_error("#elif after #else"); /* last #if/#elif expression was true: we skip */ if (c == 1) { + skip_to_eol(0); c = 0; } else { c = expr_preprocess(s1); @@ -1862,12 +1905,14 @@ ST_FUNC void preprocess(int is_bof) file->ifndef_macro = 0; test_skip: if (!(c & 1)) { + skip_to_eol(1); preprocess_skip(); is_bof = 0; goto redo; } break; case TOK_ENDIF: + next_nomacro(); if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr) tcc_error("#endif without matching #if"); s1->ifdef_stack_ptr--; @@ -1879,41 +1924,27 @@ ST_FUNC void preprocess(int is_bof) /* need to set to zero to avoid false matches if another #ifndef at middle of file */ file->ifndef_macro = 0; - while (tok != TOK_LINEFEED) - next_nomacro(); tok_flags |= TOK_FLAG_ENDIF; - goto the_end; } break; - case TOK_PPNUM: - n = strtoul((char*)tokc.str.data, &q, 10); - goto _line_num; case TOK_LINE: - next(); - if (tok != TOK_CINT) + next_nomacro(); + if (tok != TOK_PPNUM) _line_err: tcc_error("wrong #line format"); + case TOK_PPNUM: + parse_number(tokc.str.data); n = tokc.i; - _line_num: - next(); + next_nomacro(); if (tok != TOK_LINEFEED) { - if (tok == TOK_STR) { - if (file->true_filename == file->filename) - file->true_filename = tcc_strdup(file->filename); - q = (char *)tokc.str.data; - buf[0] = 0; - if (!IS_ABSPATH(q)) { - /* prepend directory from real file */ - pstrcpy(buf, sizeof buf, file->true_filename); - *tcc_basename(buf) = 0; - } - pstrcat(buf, sizeof buf, q); - tcc_debug_putfile(s1, buf); + if (tok == TOK_PPSTR && tokc.str.data[0] == '"') { + tokc.str.data[tokc.str.size - 2] = 0; + tccpp_putfile(tokc.str.data + 1); } else if (parse_flags & PARSE_FLAG_ASM_FILE) - break; + goto ignore; else goto _line_err; - --n; + next_nomacro(); } if (file->fd > 0) total_lines += file->line_num - n; @@ -1922,6 +1953,7 @@ ST_FUNC void preprocess(int is_bof) case TOK_ERROR: case TOK_WARNING: + { q = buf; c = skip_spaces(); while (c != '\n' && c != CH_EOF) { @@ -1934,9 +1966,12 @@ ST_FUNC void preprocess(int is_bof) tcc_error("#error %s", buf); else tcc_warning("#warning %s", buf); + next_nomacro(); break; + } case TOK_PRAGMA: - pragma_parse(s1); + if (!pragma_parse(s1)) + goto ignore; break; case TOK_LINEFEED: goto the_end; @@ -1945,16 +1980,14 @@ ST_FUNC void preprocess(int is_bof) if (saved_parse_flags & PARSE_FLAG_ASM_FILE) goto ignore; if (tok == '!' && is_bof) - /* '!' is ignored at beginning to allow C scripts. */ + /* '#!' is ignored at beginning to allow C scripts. */ goto ignore; tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc)); ignore: - file->buf_ptr = parse_line_comment(file->buf_ptr - 1); - break; + skip_to_eol(0); + goto the_end; } - /* ignore other preprocess commands or #! for C scripts */ - while (tok != TOK_LINEFEED) - next_nomacro(); + skip_to_eol(1); the_end: parse_flags = saved_parse_flags; } @@ -2006,7 +2039,7 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long c = c - 'A' + 10; else if (isnum(c)) c = c - '0'; - else if (i > 0) + else if (i >= 0) expect("more hex digits in universal-character-name"); else goto add_hex_or_ucn; @@ -2564,7 +2597,7 @@ static void next_nomacro(void) #ifdef INC_DEBUG printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL)); #endif - search_cached_include(s1, file->filename, 1) + search_cached_include(s1, file->true_filename, 1) ->ifndef_macro = file->ifndef_macro_saved; tok_flags &= ~TOK_FLAG_ENDIF; } @@ -3481,10 +3514,10 @@ convert: /* convert preprocessor tokens into C tokens */ if (t == TOK_PPNUM) { if (parse_flags & PARSE_FLAG_TOK_NUM) - parse_number((char *)tokc.str.data); + parse_number(tokc.str.data); } else if (t == TOK_PPSTR) { if (parse_flags & PARSE_FLAG_TOK_STR) - parse_string((char *)tokc.str.data, tokc.str.size - 1); + parse_string(tokc.str.data, tokc.str.size - 1); } }