From 2956bd85cde6a01db1bfc527e1380c9d8817484c Mon Sep 17 00:00:00 2001 From: bellard Date: Fri, 22 Nov 2002 18:12:41 +0000 Subject: [PATCH] suppressed ch1 and preparser --- tcc.c | 375 ++++++++++++++++++++++++++++++++++++++++----------------------- tccelf.c | 125 +++++++++++++-------- 2 files changed, 320 insertions(+), 180 deletions(-) diff --git a/tcc.c b/tcc.c index da642c45..c8637e2b 100644 --- a/tcc.c +++ b/tcc.c @@ -43,7 +43,8 @@ #include "libtcc.h" -//#define DEBUG +/* parser debug */ +//#define PARSE_DEBUG /* preprocessor debug */ //#define PP_DEBUG /* include file debug */ @@ -249,7 +250,7 @@ typedef struct CachedInclude { /* parser */ struct BufferedFile *file; -int ch, ch1, tok, tok1; +int ch, tok, tok1; CValue tokc, tok1c; CString tokcstr; /* current parsed string, if any */ /* if true, line feed is returned as a token. line feed is also @@ -1481,7 +1482,7 @@ BufferedFile *tcc_open(TCCState *s1, const char *filename) bf->buf_end = bf->buffer; bf->buffer[0] = CH_EOB; /* put eob symbol */ pstrcpy(bf->filename, sizeof(bf->filename), filename); - bf->line_num = 1; + bf->line_num = 0; bf->ifndef_macro = 0; bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; // printf("opening '%s'\n", filename); @@ -1495,9 +1496,6 @@ void tcc_close(BufferedFile *bf) tcc_free(bf); } -/* read one char. MUST call tcc_fillbuf if CH_EOB is read */ -#define TCC_GETC(bf) (*(bf)->buf_ptr++) - /* fill input buffer and return next char */ int tcc_getc_slow(BufferedFile *bf) { @@ -1534,12 +1532,12 @@ void handle_eob(void) return; for(;;) { - ch1 = tcc_getc_slow(file); - if (ch1 != CH_EOF) + ch = tcc_getc_slow(file); + if (ch != CH_EOF) return; eof_seen = 1; if (return_linefeed) { - ch1 = '\n'; + ch = '\n'; return; } if (s1->include_stack_ptr == s1->include_stack) @@ -1555,81 +1553,101 @@ void handle_eob(void) } } -/* read next char from current input file */ +/* read next char from current input file and handle end of input buffer */ static inline void inp(void) { - ch1 = TCC_GETC(file); + ch = *(file->buf_ptr++); /* end of buffer/file handling */ - if (ch1 == CH_EOB) + if (ch == CH_EOB) handle_eob(); - if (ch1 == '\n') - file->line_num++; - // printf("ch1=%c 0x%x\n", ch1, ch1); } -/* handle '\\n' and '\\r\n' */ +/* handle '\[\r]\n' */ static void handle_stray(void) { - do { - if (ch1 == '\n') { + while (ch == '\\') { + inp(); + if (ch == '\n') { + file->line_num++; inp(); - } else if (ch1 == '\r') { + } else if (ch == '\r') { inp(); - if (ch1 != '\n') - error("invalid character after '\\'"); + if (ch != '\n') + goto fail; + file->line_num++; inp(); } else { - break; + fail: + error("stray '\\' in program"); } - ch = ch1; - inp(); - } while (ch == '\\'); + } } -/* input with '\\n' handling. Also supports '\\r\n' for horrible MSDOS - case */ -static inline void minp(void) +/* input with '\[\r]\n' handling. Note that this function cannot + handle other characters after '\', so you cannot call it inside + strings or comments */ +static void minp(void) { - ch = ch1; inp(); if (ch == '\\') handle_stray(); } -/* same as minp, but also skip comments */ -static void cinp(void) +static void parse_line_comment(void) { - int c; - - if (ch1 == '/') { + /* single line C++ comments */ + /* XXX: accept '\\\n' ? */ + inp(); + while (ch != '\n' && ch != TOK_EOF) inp(); - if (ch1 == '/') { - /* single line C++ comments */ +} + +static void parse_comment(void) +{ + /* C comments */ + minp(); + for(;;) { + /* fast skip loop */ + while (ch != '\n' && ch != '*' && ch != TOK_EOF) inp(); - while (ch1 != '\n' && ch1 != CH_EOF) - inp(); - ch = ' '; /* return space */ - } else if (ch1 == '*') { - /* C comments */ + /* now we can handle all the cases */ + if (ch == '\n') { + file->line_num++; inp(); - while (ch1 != CH_EOF) { - c = ch1; - inp(); - if (c == '*' && ch1 == '/') { + } else if (ch == '*') { + for(;;) { inp(); - ch = ' '; /* return space */ - break; - } + if (ch == '/') { + goto end_of_comment; + } else if (ch == '\\') { + inp(); + if (ch == '\n') { + file->line_num++; + inp(); + } else if (ch == '\r') { + inp(); + if (ch != '\n') + break; + file->line_num++; + inp(); + } else { + break; + } + } else if (ch != '*') { + break; + } } } else { - ch = '/'; + error("unexpected end of file in comment"); } - } else { - minp(); } + end_of_comment: + inp(); } +#define cinp minp + /* space exlcuding newline */ static inline int is_space(int ch) { @@ -1646,28 +1664,85 @@ static inline void skip_spaces(void) #if/#endif */ void preprocess_skip(void) { - int a; + int a, start_of_line, sep; + + start_of_line = 1; a = 0; while (1) { - while (ch != '\n') { - if (ch == CH_EOF) - expect("#endif"); - cinp(); - } - cinp(); - skip_spaces(); - if (ch == '#') { - cinp(); - next_nomacro(); - if (a == 0 && - (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF)) - break; - if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF) - a++; - else if (tok == TOK_ENDIF) - a--; + switch(ch) { + case ' ': + case '\t': + case '\f': + case '\v': + case '\r': + inp(); + break; + case '\n': + start_of_line = 1; + file->line_num++; + inp(); + break; + case '\\': + handle_stray(); + break; + /* skip strings */ + case '\"': + case '\'': + start_of_line = 0; + sep = ch; + inp(); + while (ch != sep) { + /* XXX: better error message */ + if (ch == TOK_EOF) { + error("unterminated string"); + } else if (ch == '\n') { + file->line_num++; + } else if (ch == '\\') { + /* ignore next char */ + inp(); + if (ch == '\n') + file->line_num++; + } + inp(); + } + minp(); + break; + /* skip comments */ + case '/': + minp(); + if (ch == '*') { + parse_comment(); + } else if (ch == '/') { + parse_line_comment(); + } else { + start_of_line = 0; + } + break; + + case '#': + minp(); + if (start_of_line) { + next_nomacro(); + 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--; + } + start_of_line = 0; + break; + case CH_EOF: + expect("#endif"); + break; + default: + inp(); + start_of_line = 0; + break; } } + the_end: ; } /* ParseState handling */ @@ -1927,7 +2002,7 @@ int expr_preprocess(void) return c != 0; } -#if defined(DEBUG) || defined(PP_DEBUG) +#if defined(PARSE_DEBUG) || defined(PP_DEBUG) void tok_print(int *str) { int t; @@ -2054,7 +2129,6 @@ void preprocess(void) state = INCLUDE_STATE_NONE; eof_seen = 0; redo1: - cinp(); next_nomacro(); redo: switch(tok) { @@ -2085,10 +2159,12 @@ void preprocess(void) minp(); } *q = '\0'; +#if 0 /* eat all spaces and comments after include */ /* XXX: slightly incorrect */ while (ch1 != '\n' && ch1 != CH_EOF) inp(); +#endif } else { /* computed #include : either we have only strings or we have anything enclosed in '<>' */ @@ -2185,6 +2261,7 @@ void preprocess(void) if (ch != '#') goto the_end; state = INCLUDE_STATE_SEEK_IFNDEF; + cinp(); goto redo1; } break; @@ -2324,7 +2401,7 @@ static int getn(int b) if (t < 0 || t >= b) break; n = n * b + t; - cinp(); + inp(); } return n; } @@ -2334,50 +2411,76 @@ static int getq(void) { int c; + redo: c = ch; - minp(); + inp(); if (c == '\\') { - if (isoct(ch)) { + switch(ch) { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': /* at most three octal digits */ c = ch - '0'; - minp(); + inp(); if (isoct(ch)) { c = c * 8 + ch - '0'; - minp(); + inp(); if (isoct(ch)) { c = c * 8 + ch - '0'; - minp(); + inp(); } } return c; - } else if (ch == 'x') { - minp(); + case 'x': + inp(); return getn(16); - } else { - if (ch == 'a') - c = '\a'; - else if (ch == 'b') - c = '\b'; - else if (ch == 'f') - c = '\f'; - else if (ch == 'n') - c = '\n'; - else if (ch == 'r') - c = '\r'; - else if (ch == 't') - c = '\t'; - else if (ch == 'v') - c = '\v'; - else if (ch == 'e' && gnu_ext) - c = 27; - else if (ch == '\'' || ch == '\"' || ch == '\\' || ch == '?') - c = ch; - else - error("invalid escaped char"); - minp(); + case 'a': + c = '\a'; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case 'e': + if (!gnu_ext) + goto invalid_escape; + c = 27; + break; + case '\'': + case '\"': + case '\\': + case '?': + c = ch; + break; + case '\n': + inp(); + goto redo; + case '\r': + inp(); + if (ch != '\n') + goto invalid_escape; + inp(); + goto redo; + default: + invalid_escape: + error("invalid escaped char"); } + inp(); } else if (c == '\r' && ch == '\n') { - minp(); + inp(); c = '\n'; } return c; @@ -2677,10 +2780,11 @@ void parse_number(const char *p) /* return next token without macro substitution */ static inline void next_nomacro1(void) { - int b, t; + int b, t, start_of_line; char *q; TokenSym *ts; + start_of_line = 0; redo_no_start: switch(ch) { case ' ': @@ -2688,38 +2792,36 @@ static inline void next_nomacro1(void) case '\f': case '\v': case '\r': - cinp(); + inp(); goto redo_no_start; + case '\\': + handle_stray(); + goto redo_no_start; + case '\n': + file->line_num++; if (return_linefeed) { /* XXX: should eat token ? */ tok = TOK_LINEFEED; } else { - cinp(); - skip_spaces(); - if (ch == '#') { - /* preprocessor command if # at start of line after - spaces */ - preprocess(); - } + start_of_line = 1; + inp(); goto redo_no_start; } break; case '#': - tok = ch; - cinp(); -#if 0 + minp(); if (start_of_line) { preprocess(); goto redo_no_start; - } else -#endif - { + } else { if (ch == '#') { - cinp(); + inp(); tok = TOK_TWOSHARPS; + } else { + tok = '#'; } } break; @@ -2754,7 +2856,7 @@ static inline void next_nomacro1(void) tok = ts->tok; break; case 'L': - cinp(); + minp(); if (ch == '\'') { tok = TOK_LCHAR; goto char_const; @@ -2810,7 +2912,7 @@ static inline void next_nomacro1(void) case '\'': tok = TOK_CCHAR; char_const: - minp(); + inp(); b = getq(); /* this cast is needed if >= 128 */ if (tok == TOK_CCHAR) @@ -2818,12 +2920,12 @@ static inline void next_nomacro1(void) tokc.i = b; if (ch != '\'') error("unterminated character constant"); - minp(); + inp(); break; case '\"': tok = TOK_STR; str_const: - minp(); + inp(); cstr_reset(&tokcstr); while (ch != '\"') { b = getq(); @@ -2839,7 +2941,7 @@ static inline void next_nomacro1(void) else cstr_wccat(&tokcstr, '\0'); tokc.cstr = &tokcstr; - minp(); + inp(); break; case '<': @@ -2976,18 +3078,19 @@ static inline void next_nomacro1(void) /* comments or operator */ case '/': - tok = ch; - cinp(); - if (ch == '=') { + minp(); + if (ch == '*') { + parse_comment(); + goto redo_no_start; + } else if (ch == '/') { + parse_line_comment(); + goto redo_no_start; + } else if (ch == '=') { cinp(); tok = TOK_A_DIV; - } -#if 0 - else if (ch == '/' || ch == '*') { - parse_comments(); - goto redo_no_start; + } else { + tok = '/'; } -#endif break; /* simple tokens */ @@ -3012,6 +3115,9 @@ static inline void next_nomacro1(void) error("unrecognized character \\x%02x", ch); break; } +#if defined(PARSE_DEBUG) + printf("token = %s\n", get_tok_str(tok, &tokc)); +#endif } /* return next token without macro substitution. Can read input from @@ -3437,9 +3543,6 @@ static void next(void) parse_number((char *)tokc.cstr->data); } } -#if defined(DEBUG) - printf("token = %s\n", get_tok_str(tok, &tokc)); -#endif } void swap(int *p, int *q) @@ -7539,7 +7642,6 @@ static int tcc_compile(TCCState *s1) s1->nb_errors = 0; s1->error_set_jmp_enabled = 1; - inp(); ch = '\n'; /* needed to parse correctly first preprocessor command */ next(); decl(VT_CONST); @@ -7617,7 +7719,6 @@ void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) s1->include_stack_ptr = s1->include_stack; /* parse with define parser */ - inp(); ch = '\n'; /* needed to parse correctly first preprocessor command */ next_nomacro(); parse_define(); diff --git a/tccelf.c b/tccelf.c index a162e27a..e5341727 100644 --- a/tccelf.c +++ b/tccelf.c @@ -378,7 +378,7 @@ static void relocate_common_syms(void) static void *resolve_sym(const char *sym) { - return dlsym(NULL, sym); + return dlsym(RTLD_DEFAULT, sym); } /* relocate symbol table, resolve undefined symbols if do_resolve is @@ -1813,71 +1813,110 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) return ret; } -/* return -2 if error and CH_EOF if eof */ -static void ld_skipspaces(void) -{ - while (ch == ' ' || ch == '\t' || ch == '\n') - cinp(); -} +#define LD_TOK_NAME 256 +#define LD_TOK_EOF (-1) -static int ld_get_cmd(char *cmd, int cmd_size) +/* return next ld script token */ +static int ld_next(TCCState *s1, char *name, int name_size) { + int c; char *q; - ld_skipspaces(); - if (ch == CH_EOF) - return -1; - q = cmd; - for(;;) { - if (!((ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - strchr("/.-_+=$:\\,~?*", ch))) - break; - if ((q - cmd) >= (cmd_size - 1)) - return -2; - *q++ = ch; - cinp(); + redo: + switch(ch) { + case ' ': + case '\t': + case '\f': + case '\v': + case '\r': + case '\n': + inp(); + goto redo; + case '/': + minp(); + if (ch == '*') { + parse_comment(); + goto redo; + } else { + q = name; + *q++ = '/'; + goto parse_name; + } + break; + case 'a' ... 'z': + case 'A' ... 'Z': + case '_': + case '\\': + case '.': + case '$': + case '~': + q = name; + parse_name: + for(;;) { + if (!((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + strchr("/.-_+=$:\\,~", ch))) + break; + if ((q - name) < name_size - 1) { + *q++ = ch; + } + minp(); + } + *q = '\0'; + c = LD_TOK_NAME; + break; + case CH_EOF: + c = LD_TOK_EOF; + break; + default: + c = ch; + inp(); + break; } - *q = '\0'; - return 0; +#if 0 + printf("tok=%c %d\n", c, c); + if (c == LD_TOK_NAME) + printf(" name=%s\n", name); +#endif + return c; } - + /* interpret a subset of GNU ldscripts to handle the dummy libc.so files */ static int tcc_load_ldscript(TCCState *s1) { char cmd[64]; char filename[1024]; - int ret; + int t; inp(); - cinp(); for(;;) { - ret = ld_get_cmd(cmd, sizeof(cmd)); - if (ret == CH_EOF) + t = ld_next(s1, cmd, sizeof(cmd)); + if (t == LD_TOK_EOF) return 0; - else if (ret < 0) + else if (t != LD_TOK_NAME) return -1; - // printf("cmd='%s'\n", cmd); if (!strcmp(cmd, "INPUT") || !strcmp(cmd, "GROUP")) { - ld_skipspaces(); - if (ch != '(') + t = ld_next(s1, cmd, sizeof(cmd)); + if (t != '(') expect("("); - cinp(); + t = ld_next(s1, filename, sizeof(filename)); for(;;) { - ld_get_cmd(filename, sizeof(filename)); - tcc_add_file(s1, filename); - ld_skipspaces(); - if (ch == ',') { - cinp(); - } else if (ch == ')') { - cinp(); - break; - } else if (ch == CH_EOF) { + if (t == LD_TOK_EOF) { error_noabort("unexpected end of file"); return -1; + } else if (t == ')') { + break; + } else if (t != LD_TOK_NAME) { + error_noabort("filename expected"); + return -1; + } + tcc_add_file(s1, filename); + t = ld_next(s1, filename, sizeof(filename)); + if (t == ',') { + t = ld_next(s1, filename, sizeof(filename)); } } } else { -- 2.11.4.GIT