tccpp: cleanup options -dD -dM, remove -C
The lexer is for reading files, not for writing. Also : - macro_is_equal(): avoid crash if redefining __FILE__
This commit is contained in:
		
							parent
							
								
									caebbc3ee1
								
							
						
					
					
						commit
						fe845cf53d
					
				
					 5 changed files with 198 additions and 246 deletions
				
			
		
							
								
								
									
										50
									
								
								libtcc.c
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								libtcc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1132,18 +1132,14 @@ LIBTCCAPI TCCState *tcc_new(void)
 | 
			
		|||
    tcc_define_symbol(s, "__linux", NULL);
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(__FreeBSD__)
 | 
			
		||||
#  define str(s) #s
 | 
			
		||||
    tcc_define_symbol(s, "__FreeBSD__", str( __FreeBSD__));
 | 
			
		||||
#  undef str
 | 
			
		||||
    tcc_define_symbol(s, "__FreeBSD__", "__FreeBSD__");
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(__FreeBSD_kernel__)
 | 
			
		||||
    tcc_define_symbol(s, "__FreeBSD_kernel__", NULL);
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
# if defined(__NetBSD__)
 | 
			
		||||
#  define str(s) #s
 | 
			
		||||
    tcc_define_symbol(s, "__NetBSD__", str( __NetBSD__));
 | 
			
		||||
#  undef str
 | 
			
		||||
    tcc_define_symbol(s, "__NetBSD__", "__NetBSD__");
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
    /* TinyCC & gcc defines */
 | 
			
		||||
| 
						 | 
				
			
			@ -1227,8 +1223,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
 | 
			
		|||
    /* close a preprocessor output */
 | 
			
		||||
    if (s1->ppfp && s1->ppfp != stdout)
 | 
			
		||||
        fclose(s1->ppfp);
 | 
			
		||||
    if (s1->dffp && s1->dffp != s1->ppfp)
 | 
			
		||||
        fclose(s1->dffp);
 | 
			
		||||
 | 
			
		||||
    /* free all sections */
 | 
			
		||||
    for(i = 1; i < s1->nb_sections; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -1614,12 +1608,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
 | 
			
		|||
            if (!s->ppfp)
 | 
			
		||||
                tcc_error("could not write '%s'", s->outfile);
 | 
			
		||||
        }
 | 
			
		||||
        s->dffp = s->ppfp;
 | 
			
		||||
        if (s->dflag == 'M')
 | 
			
		||||
            s->ppfp = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (s->option_C && !s->ppfp)
 | 
			
		||||
        s->option_C = 0;
 | 
			
		||||
 | 
			
		||||
    if (!s->nostdinc) {
 | 
			
		||||
        /* default include paths */
 | 
			
		||||
| 
						 | 
				
			
			@ -1670,7 +1659,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
 | 
			
		|||
        tcc_add_crt(s, "crti.o");
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_TCC_BCHECK
 | 
			
		||||
    if (s->do_bounds_check && (output_type == TCC_OUTPUT_EXE))
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1681,12 +1669,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
 | 
			
		|||
            put_extern_sym(sym, NULL, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (s->normalize_inc_dirs)
 | 
			
		||||
        tcc_normalize_inc_dirs(s);
 | 
			
		||||
    if (s->output_type == TCC_OUTPUT_PREPROCESS)
 | 
			
		||||
        print_defines();
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1963,7 +1947,6 @@ enum {
 | 
			
		|||
    TCC_OPTION_b,
 | 
			
		||||
    TCC_OPTION_g,
 | 
			
		||||
    TCC_OPTION_c,
 | 
			
		||||
    TCC_OPTION_C,
 | 
			
		||||
    TCC_OPTION_dumpversion,
 | 
			
		||||
    TCC_OPTION_d,
 | 
			
		||||
    TCC_OPTION_float_abi,
 | 
			
		||||
| 
						 | 
				
			
			@ -2021,7 +2004,6 @@ static const TCCOption tcc_options[] = {
 | 
			
		|||
#endif
 | 
			
		||||
    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
 | 
			
		||||
    { "c", TCC_OPTION_c, 0 },
 | 
			
		||||
    { "C", TCC_OPTION_C, 0 },
 | 
			
		||||
    { "dumpversion", TCC_OPTION_dumpversion, 0},
 | 
			
		||||
    { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
 | 
			
		||||
#ifdef TCC_TARGET_ARM
 | 
			
		||||
| 
						 | 
				
			
			@ -2210,17 +2192,15 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
 | 
			
		|||
                tcc_warning("-c: some compiler action already specified (%d)", s->output_type);
 | 
			
		||||
            s->output_type = TCC_OUTPUT_OBJ;
 | 
			
		||||
            break;
 | 
			
		||||
        case TCC_OPTION_C:
 | 
			
		||||
            s->option_C = 1;
 | 
			
		||||
            break;
 | 
			
		||||
        case TCC_OPTION_d:
 | 
			
		||||
            if (*optarg == 'D' || *optarg == 'M')
 | 
			
		||||
                s->dflag = *optarg;
 | 
			
		||||
            else {
 | 
			
		||||
                if (s->warn_unsupported)
 | 
			
		||||
                    goto unsupported_option;
 | 
			
		||||
                tcc_error("invalid option -- '%s'", r);
 | 
			
		||||
            }
 | 
			
		||||
            if (*optarg == 'D')
 | 
			
		||||
                s->dflag = 3;
 | 
			
		||||
            else if (*optarg == 'M')
 | 
			
		||||
                s->dflag = 7;
 | 
			
		||||
            else if (*optarg == 'b')
 | 
			
		||||
                s->dflag = 8;
 | 
			
		||||
            else
 | 
			
		||||
                goto unsupported_option;
 | 
			
		||||
            break;
 | 
			
		||||
#ifdef TCC_TARGET_ARM
 | 
			
		||||
        case TCC_OPTION_float_abi:
 | 
			
		||||
| 
						 | 
				
			
			@ -2310,12 +2290,11 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
 | 
			
		|||
            do ++s->verbose; while (*optarg++ == 'v');
 | 
			
		||||
            break;
 | 
			
		||||
        case TCC_OPTION_f:
 | 
			
		||||
            if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
 | 
			
		||||
            if (tcc_set_flag(s, optarg, 1) < 0)
 | 
			
		||||
                goto unsupported_option;
 | 
			
		||||
            break;
 | 
			
		||||
        case TCC_OPTION_W:
 | 
			
		||||
            if (tcc_set_warning(s, optarg, 1) < 0 &&
 | 
			
		||||
                s->warn_unsupported)
 | 
			
		||||
            if (tcc_set_warning(s, optarg, 1) < 0)
 | 
			
		||||
                goto unsupported_option;
 | 
			
		||||
            break;
 | 
			
		||||
        case TCC_OPTION_w:
 | 
			
		||||
| 
						 | 
				
			
			@ -2378,10 +2357,9 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv)
 | 
			
		|||
            /* ignored */
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            if (s->warn_unsupported) {
 | 
			
		||||
            unsupported_option:
 | 
			
		||||
unsupported_option:
 | 
			
		||||
            if (s->warn_unsupported)
 | 
			
		||||
                tcc_warning("unsupported option '%s'", r);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								tcc.c
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								tcc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -98,9 +98,8 @@ static void help(void)
 | 
			
		|||
           "  -Dsym[=val] define 'sym' with value 'val'\n"
 | 
			
		||||
           "  -Usym       undefine 'sym'\n"
 | 
			
		||||
           "  -E          preprocess only\n"
 | 
			
		||||
           "    -P[1]       no/alternative output of #line directives\n"
 | 
			
		||||
           "    -d{D|M}     dump defines\n"
 | 
			
		||||
           "    -C          keep comments\n"
 | 
			
		||||
           "  -P[1]       no / alternative #line output with -E\n"
 | 
			
		||||
           "  -dD -dM     output #define directives with -E\n"
 | 
			
		||||
           "Linker options:\n"
 | 
			
		||||
           "  -Ldir       add library path 'dir'\n"
 | 
			
		||||
           "  -llib       link with dynamic or static library 'lib'\n"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								tcc.h
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								tcc.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -775,7 +775,6 @@ struct TCCState {
 | 
			
		|||
	LINE_MACRO_OUTPUT_FORMAT_STD
 | 
			
		||||
    } Pflag; /* -P switch */
 | 
			
		||||
    char dflag; /* -dX value */
 | 
			
		||||
    FILE *dffp;
 | 
			
		||||
 | 
			
		||||
    /* for -MD/-MF: collected dependencies for this compilation */
 | 
			
		||||
    char **target_deps;
 | 
			
		||||
| 
						 | 
				
			
			@ -858,7 +857,6 @@ struct TCCState {
 | 
			
		|||
    char *option_m; /* only -m32/-m64 handled */
 | 
			
		||||
    int print_search_dirs; /* option */
 | 
			
		||||
    int option_r; /* option -r */
 | 
			
		||||
    int option_C; /* option -C, keep comments when -E */
 | 
			
		||||
    int do_bench; /* option -bench */
 | 
			
		||||
    int gen_deps; /* option -MD  */
 | 
			
		||||
    char *deps_outfile; /* option -MF */
 | 
			
		||||
| 
						 | 
				
			
			@ -1296,7 +1294,6 @@ ST_INLN void define_push(int v, int macro_type, TokenString *str, Sym *first_arg
 | 
			
		|||
ST_FUNC void define_undef(Sym *s);
 | 
			
		||||
ST_INLN Sym *define_find(int v);
 | 
			
		||||
ST_FUNC void free_defines(Sym *b);
 | 
			
		||||
ST_FUNC void print_defines(void);
 | 
			
		||||
ST_FUNC Sym *label_find(int v);
 | 
			
		||||
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags);
 | 
			
		||||
ST_FUNC void label_pop(Sym **ptop, Sym *slast);
 | 
			
		||||
| 
						 | 
				
			
			@ -1453,7 +1450,7 @@ ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
 | 
			
		|||
#ifndef TCC_TARGET_PE
 | 
			
		||||
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
 | 
			
		||||
ST_FUNC int tcc_load_ldscript(TCCState *s1);
 | 
			
		||||
ST_FUNC uint8_t *parse_comment(uint8_t *p, int skip);
 | 
			
		||||
ST_FUNC uint8_t *parse_comment(uint8_t *p);
 | 
			
		||||
ST_FUNC void minp(void);
 | 
			
		||||
ST_INLN void inp(void);
 | 
			
		||||
ST_FUNC int handle_eob(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								tccelf.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								tccelf.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -3282,7 +3282,7 @@ static int ld_next(TCCState *s1, char *name, int name_size)
 | 
			
		|||
    case '/':
 | 
			
		||||
        minp();
 | 
			
		||||
        if (ch == '*') {
 | 
			
		||||
            file->buf_ptr = parse_comment(file->buf_ptr,0);
 | 
			
		||||
            file->buf_ptr = parse_comment(file->buf_ptr);
 | 
			
		||||
            ch = file->buf_ptr[0];
 | 
			
		||||
            goto redo;
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										382
									
								
								tccpp.c
									
										
									
									
									
								
							
							
						
						
									
										382
									
								
								tccpp.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -49,6 +49,9 @@ static char token_buf[STRING_MAX_SIZE + 1];
 | 
			
		|||
static CString cstr_buf;
 | 
			
		||||
static TokenString tokstr_buf;
 | 
			
		||||
static unsigned char isidnum_table[256 - CH_EOF];
 | 
			
		||||
static int pp_debug_tok, pp_debug_symv;
 | 
			
		||||
static void tok_print(const char *msg, const int *str);
 | 
			
		||||
 | 
			
		||||
/* isidnum_table flags: */
 | 
			
		||||
#define IS_SPC 1
 | 
			
		||||
#define IS_ID  2
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +132,21 @@ ST_FUNC void end_macro(void)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC char *trimfront(char *p)
 | 
			
		||||
{
 | 
			
		||||
    while (*p && (unsigned char)*p <= ' ')
 | 
			
		||||
	++p;
 | 
			
		||||
    return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC char *trimback(char *a, char *e)
 | 
			
		||||
{
 | 
			
		||||
    while (e > a && (unsigned char)e[-1] <= ' ')
 | 
			
		||||
	--e;
 | 
			
		||||
    *e = 0;;
 | 
			
		||||
    return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------- */
 | 
			
		||||
/* Custom allocator for tiny objects */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -675,80 +693,12 @@ ST_FUNC void minp(void)
 | 
			
		|||
        handle_stray();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pp_line(TCCState *s1, BufferedFile *f, int level)
 | 
			
		||||
{
 | 
			
		||||
    if (s1->ppfp) {
 | 
			
		||||
        int d = f->line_num - f->line_ref;
 | 
			
		||||
        if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE
 | 
			
		||||
            || (level == 0 && f->line_ref && d < 8)) {
 | 
			
		||||
            while (d > 0)
 | 
			
		||||
                fputs("\n", s1->ppfp), --d;
 | 
			
		||||
        } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) {
 | 
			
		||||
            fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename);
 | 
			
		||||
        } else {
 | 
			
		||||
            fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename,
 | 
			
		||||
                level > 0 ? " 1" : level < 0 ? " 2" : "");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    f->line_ref = f->line_num;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t *parse_print_comment(uint8_t *p, int is_line_comment)
 | 
			
		||||
{
 | 
			
		||||
    int c, star_count;
 | 
			
		||||
    FILE *ppfp = tcc_state->ppfp;
 | 
			
		||||
 | 
			
		||||
    if ((file->line_num - file->line_ref) > 0) {
 | 
			
		||||
        fputc('\n', ppfp);
 | 
			
		||||
        file->line_ref++;
 | 
			
		||||
        pp_line(tcc_state, file, 0);
 | 
			
		||||
    }
 | 
			
		||||
    if (is_line_comment)
 | 
			
		||||
        fputs("//", ppfp); else
 | 
			
		||||
        fputs("/*", ppfp);
 | 
			
		||||
 | 
			
		||||
    star_count = 0;
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        c = *p;
 | 
			
		||||
        if (c == '\\') {
 | 
			
		||||
            file->buf_ptr = p;
 | 
			
		||||
            c = handle_eob();
 | 
			
		||||
            p = file->buf_ptr;
 | 
			
		||||
        }
 | 
			
		||||
        if (c == CH_EOF) {
 | 
			
		||||
            if (is_line_comment) break;
 | 
			
		||||
            tcc_error("unexpected end of file in comment");
 | 
			
		||||
        }
 | 
			
		||||
        if (c == '*')
 | 
			
		||||
            star_count++;
 | 
			
		||||
        else {
 | 
			
		||||
            if ((c == '/') && star_count && !is_line_comment)
 | 
			
		||||
                break;
 | 
			
		||||
            star_count = 0;
 | 
			
		||||
            if (c == '\n') {
 | 
			
		||||
                if (is_line_comment) break;
 | 
			
		||||
                file->line_num++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        fputc(c, ppfp);
 | 
			
		||||
        p++;
 | 
			
		||||
    }
 | 
			
		||||
    if (!is_line_comment) {
 | 
			
		||||
        fputc('/', ppfp);
 | 
			
		||||
        p++;
 | 
			
		||||
        file->line_ref = file->line_num;
 | 
			
		||||
    }
 | 
			
		||||
    return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* single line C++ comments */
 | 
			
		||||
static uint8_t *parse_line_comment(uint8_t *p, int skip)
 | 
			
		||||
static uint8_t *parse_line_comment(uint8_t *p)
 | 
			
		||||
{
 | 
			
		||||
    int c;
 | 
			
		||||
 | 
			
		||||
    p++;
 | 
			
		||||
    if (tcc_state->option_C && !skip)
 | 
			
		||||
        return parse_print_comment(p, 1);
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        c = *p;
 | 
			
		||||
    redo:
 | 
			
		||||
| 
						 | 
				
			
			@ -781,13 +731,11 @@ static uint8_t *parse_line_comment(uint8_t *p, int skip)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* C comments */
 | 
			
		||||
ST_FUNC uint8_t *parse_comment(uint8_t *p, int skip)
 | 
			
		||||
ST_FUNC uint8_t *parse_comment(uint8_t *p)
 | 
			
		||||
{
 | 
			
		||||
    int c;
 | 
			
		||||
 | 
			
		||||
    p++;
 | 
			
		||||
    if (tcc_state->option_C && !skip)
 | 
			
		||||
        return parse_print_comment(p, 0);
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        /* fast skip loop */
 | 
			
		||||
        for(;;) {
 | 
			
		||||
| 
						 | 
				
			
			@ -994,9 +942,9 @@ redo_start:
 | 
			
		|||
            minp();
 | 
			
		||||
            p = file->buf_ptr;
 | 
			
		||||
            if (ch == '*') {
 | 
			
		||||
                p = parse_comment(p,1);
 | 
			
		||||
                p = parse_comment(p);
 | 
			
		||||
            } else if (ch == '/') {
 | 
			
		||||
                p = parse_line_comment(p,1);
 | 
			
		||||
                p = parse_line_comment(p);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case '#':
 | 
			
		||||
| 
						 | 
				
			
			@ -1017,9 +965,9 @@ redo_start:
 | 
			
		|||
                else if (tok == TOK_LINEFEED)
 | 
			
		||||
                    goto redo_start;
 | 
			
		||||
                else if (parse_flags & PARSE_FLAG_ASM_FILE)
 | 
			
		||||
                    p = parse_line_comment(p,0);
 | 
			
		||||
                    p = parse_line_comment(p);
 | 
			
		||||
            } else if (parse_flags & PARSE_FLAG_ASM_FILE)
 | 
			
		||||
                p = parse_line_comment(p,0);
 | 
			
		||||
                p = parse_line_comment(p);
 | 
			
		||||
            break;
 | 
			
		||||
_default:
 | 
			
		||||
        default:
 | 
			
		||||
| 
						 | 
				
			
			@ -1287,6 +1235,10 @@ static int macro_is_equal(const int *a, const int *b)
 | 
			
		|||
{
 | 
			
		||||
    CValue cv;
 | 
			
		||||
    int t;
 | 
			
		||||
 | 
			
		||||
    if (!a || !b)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
    while (*a && *b) {
 | 
			
		||||
        /* first time preallocate static cstr_buf, next time only reset position to start */
 | 
			
		||||
        cstr_reset(&cstr_buf);
 | 
			
		||||
| 
						 | 
				
			
			@ -1299,106 +1251,25 @@ static int macro_is_equal(const int *a, const int *b)
 | 
			
		|||
    return !(*a || *b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tok_print(const char *msg, const int *str)
 | 
			
		||||
{
 | 
			
		||||
    FILE *pr = tcc_state->dffp;
 | 
			
		||||
    int t;
 | 
			
		||||
    CValue cval;
 | 
			
		||||
 | 
			
		||||
    fprintf(pr, "%s ", msg);
 | 
			
		||||
    while (str) {
 | 
			
		||||
        TOK_GET(&t, &str, &cval);
 | 
			
		||||
        if (!t)
 | 
			
		||||
            break;
 | 
			
		||||
        fprintf(pr,"%s", get_tok_str(t, &cval));
 | 
			
		||||
    }
 | 
			
		||||
    fprintf(pr, "\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int define_print_prepared(Sym *s)
 | 
			
		||||
{
 | 
			
		||||
    if (!s || !tcc_state->dffp || tcc_state->dflag == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    if (s->v < TOK_IDENT || s->v >= tok_ident)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    if (file && tcc_state->dflag == 'D') {
 | 
			
		||||
        file->line_num--;
 | 
			
		||||
        pp_line(tcc_state, file, 0);
 | 
			
		||||
        file->line_ref = ++file->line_num;
 | 
			
		||||
    }
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void define_print(int v)
 | 
			
		||||
{
 | 
			
		||||
    FILE *pr = tcc_state->dffp;
 | 
			
		||||
    Sym *s, *a;
 | 
			
		||||
 | 
			
		||||
    s = define_find(v);
 | 
			
		||||
    if (define_print_prepared(s) == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    fprintf(pr, "// #define %s", get_tok_str(v, NULL));
 | 
			
		||||
    if (s->type.t == MACRO_FUNC) {
 | 
			
		||||
        a = s->next;
 | 
			
		||||
        fprintf(pr,"(");
 | 
			
		||||
        if (a)
 | 
			
		||||
            for (;;) {
 | 
			
		||||
                fprintf(pr,"%s", get_tok_str(a->v & ~SYM_FIELD, NULL));
 | 
			
		||||
                if (!(a = a->next))
 | 
			
		||||
                    break;
 | 
			
		||||
                fprintf(pr,",");
 | 
			
		||||
            }
 | 
			
		||||
        fprintf(pr,")");
 | 
			
		||||
    }
 | 
			
		||||
    tok_print("", s->d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void undef_print(int v)
 | 
			
		||||
{
 | 
			
		||||
    FILE *pr = tcc_state->dffp;
 | 
			
		||||
    Sym *s;
 | 
			
		||||
 | 
			
		||||
    s = define_find(v);
 | 
			
		||||
    if (define_print_prepared(s) == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    fprintf(pr, "// #undef %s\n", get_tok_str(s->v, NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC void print_defines(void)
 | 
			
		||||
{
 | 
			
		||||
    Sym *top = define_stack;
 | 
			
		||||
    while (top) {
 | 
			
		||||
        define_print(top->v);
 | 
			
		||||
        top = top->prev;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* defines handling */
 | 
			
		||||
ST_INLN void define_push(int v, int macro_type, TokenString *str, Sym *first_arg)
 | 
			
		||||
{
 | 
			
		||||
    Sym *s;
 | 
			
		||||
 | 
			
		||||
    if (str) {
 | 
			
		||||
        s = define_find(v);
 | 
			
		||||
        if (s && !macro_is_equal(s->d, str->str))
 | 
			
		||||
            tcc_warning("%s redefined", get_tok_str(v, NULL));
 | 
			
		||||
    }
 | 
			
		||||
    Sym *s, *o;
 | 
			
		||||
 | 
			
		||||
    o = define_find(v);
 | 
			
		||||
    s = sym_push2(&define_stack, v, macro_type, 0);
 | 
			
		||||
    s->d = str ? tok_str_dup(str) : NULL;
 | 
			
		||||
    s->next = first_arg;
 | 
			
		||||
    table_ident[v - TOK_IDENT]->sym_define = s;
 | 
			
		||||
 | 
			
		||||
    if (o && !macro_is_equal(o->d, s->d))
 | 
			
		||||
	tcc_warning("%s redefined", get_tok_str(v, NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* undefined a define symbol. Its name is just set to zero */
 | 
			
		||||
ST_FUNC void define_undef(Sym *s)
 | 
			
		||||
{
 | 
			
		||||
    int v = s->v;
 | 
			
		||||
    undef_print(v);
 | 
			
		||||
    if (v >= TOK_IDENT && v < tok_ident)
 | 
			
		||||
        table_ident[v - TOK_IDENT]->sym_define = NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1602,7 +1473,6 @@ ST_FUNC void parse_define(void)
 | 
			
		|||
bad_twosharp:
 | 
			
		||||
        tcc_error("'##' cannot appear at either end of macro");
 | 
			
		||||
    define_push(v, t, &tokstr_buf, first);
 | 
			
		||||
    define_print(v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int hash_cached_include(const char *filename)
 | 
			
		||||
| 
						 | 
				
			
			@ -1688,6 +1558,7 @@ static void pragma_parse(TCCState *s1)
 | 
			
		|||
            table_ident[v - TOK_IDENT]->sym_define = s->d ? s : NULL;
 | 
			
		||||
        else
 | 
			
		||||
            tcc_warning("unbalanced #pragma pop_macro");
 | 
			
		||||
        pp_debug_tok = t, pp_debug_symv = v;
 | 
			
		||||
 | 
			
		||||
    } else if (tok == TOK_once) {
 | 
			
		||||
        char buf1[sizeof(file->filename) + sizeof(ONCE_PREFIX)];
 | 
			
		||||
| 
						 | 
				
			
			@ -1788,11 +1659,15 @@ ST_FUNC void preprocess(int is_bof)
 | 
			
		|||
 redo:
 | 
			
		||||
    switch(tok) {
 | 
			
		||||
    case TOK_DEFINE:
 | 
			
		||||
        pp_debug_tok = tok;
 | 
			
		||||
        next_nomacro();
 | 
			
		||||
        pp_debug_symv = tok;
 | 
			
		||||
        parse_define();
 | 
			
		||||
        break;
 | 
			
		||||
    case TOK_UNDEF:
 | 
			
		||||
        pp_debug_tok = tok;
 | 
			
		||||
        next_nomacro();
 | 
			
		||||
        pp_debug_symv = tok;
 | 
			
		||||
        s = define_find(tok);
 | 
			
		||||
        /* undefine symbol by putting an invalid name */
 | 
			
		||||
        if (s)
 | 
			
		||||
| 
						 | 
				
			
			@ -2059,7 +1934,7 @@ _line_num:
 | 
			
		|||
            goto ignore;
 | 
			
		||||
        tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
 | 
			
		||||
    ignore:
 | 
			
		||||
        file->buf_ptr = parse_line_comment(file->buf_ptr,0);
 | 
			
		||||
        file->buf_ptr = parse_line_comment(file->buf_ptr);
 | 
			
		||||
        goto the_end;
 | 
			
		||||
    }
 | 
			
		||||
    /* ignore other preprocess commands or #! for C scripts */
 | 
			
		||||
| 
						 | 
				
			
			@ -2655,7 +2530,7 @@ maybe_newline:
 | 
			
		|||
                tok = TOK_TWOSHARPS;
 | 
			
		||||
            } else {
 | 
			
		||||
                if (parse_flags & PARSE_FLAG_ASM_FILE) {
 | 
			
		||||
                    p = parse_line_comment(p - 1,0);
 | 
			
		||||
                    p = parse_line_comment(p - 1);
 | 
			
		||||
                    goto redo_no_start;
 | 
			
		||||
                } else {
 | 
			
		||||
                    tok = '#';
 | 
			
		||||
| 
						 | 
				
			
			@ -2918,17 +2793,13 @@ maybe_newline:
 | 
			
		|||
    case '/':
 | 
			
		||||
        PEEKC(c, p);
 | 
			
		||||
        if (c == '*') {
 | 
			
		||||
            p = parse_comment(p,0);
 | 
			
		||||
            p = parse_comment(p);
 | 
			
		||||
            /* comments replaced by a blank */
 | 
			
		||||
            tok = ' ';
 | 
			
		||||
            if (tcc_state->option_C)
 | 
			
		||||
                goto redo_no_start;
 | 
			
		||||
            goto keep_tok_flags;
 | 
			
		||||
        } else if (c == '/') {
 | 
			
		||||
            p = parse_line_comment(p,0);
 | 
			
		||||
            p = parse_line_comment(p);
 | 
			
		||||
            tok = ' ';
 | 
			
		||||
            if (tcc_state->option_C)
 | 
			
		||||
                goto redo_no_start;
 | 
			
		||||
            goto keep_tok_flags;
 | 
			
		||||
        } else if (c == '=') {
 | 
			
		||||
            p++;
 | 
			
		||||
| 
						 | 
				
			
			@ -3150,10 +3021,10 @@ static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *w
 | 
			
		|||
                        uint8_t *p = file->buf_ptr;
 | 
			
		||||
                        PEEKC(c, p);
 | 
			
		||||
                        if (c == '*') {
 | 
			
		||||
                            p = parse_comment(p,0);
 | 
			
		||||
                            p = parse_comment(p);
 | 
			
		||||
                            file->buf_ptr = p - 1;
 | 
			
		||||
                        } else if (c == '/') {
 | 
			
		||||
                            p = parse_line_comment(p,0);
 | 
			
		||||
                            p = parse_line_comment(p);
 | 
			
		||||
                            file->buf_ptr = p - 1;
 | 
			
		||||
                        } else
 | 
			
		||||
                            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -3570,8 +3441,6 @@ ST_INLN void unget_tok(int last_tok)
 | 
			
		|||
    tok = last_tok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* better than nothing, but needs extension to handle '-E' option
 | 
			
		||||
   correctly too */
 | 
			
		||||
ST_FUNC void preprocess_init(TCCState *s1)
 | 
			
		||||
{
 | 
			
		||||
    s1->include_stack_ptr = s1->include_stack;
 | 
			
		||||
| 
						 | 
				
			
			@ -3585,8 +3454,7 @@ ST_FUNC void preprocess_init(TCCState *s1)
 | 
			
		|||
    s1->pack_stack_ptr = s1->pack_stack;
 | 
			
		||||
 | 
			
		||||
    isidnum_table['$' - CH_EOF] =
 | 
			
		||||
        tcc_state->dollars_in_identifiers ? IS_ID : 0;
 | 
			
		||||
 | 
			
		||||
        s1->dollars_in_identifiers ? IS_ID : 0;
 | 
			
		||||
    isidnum_table['.' - CH_EOF] =
 | 
			
		||||
        (parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3665,11 +3533,122 @@ ST_FUNC void preprocess_delete(void)
 | 
			
		|||
    cstr_alloc = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------- */
 | 
			
		||||
/* tcc -E [-P[1]] [-dD} support */
 | 
			
		||||
 | 
			
		||||
static void tok_print(const char *msg, const int *str)
 | 
			
		||||
{
 | 
			
		||||
    FILE *fp;
 | 
			
		||||
    int t;
 | 
			
		||||
    CValue cval;
 | 
			
		||||
 | 
			
		||||
    fp = tcc_state->ppfp;
 | 
			
		||||
    if (!fp || !tcc_state->dflag)
 | 
			
		||||
        fp = stdout;
 | 
			
		||||
 | 
			
		||||
    fprintf(fp, "%s ", msg);
 | 
			
		||||
    while (str) {
 | 
			
		||||
	TOK_GET(&t, &str, &cval);
 | 
			
		||||
	if (!t)
 | 
			
		||||
	    break;
 | 
			
		||||
	fprintf(fp,"%s", get_tok_str(t, &cval));
 | 
			
		||||
    }
 | 
			
		||||
    fprintf(fp, "\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pp_line(TCCState *s1, BufferedFile *f, int level)
 | 
			
		||||
{
 | 
			
		||||
    int d = f->line_num - f->line_ref;
 | 
			
		||||
 | 
			
		||||
    if (s1->dflag & 4)
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
    if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE) {
 | 
			
		||||
	if (level == 0 && f->line_ref && d) {
 | 
			
		||||
	    d = 1;
 | 
			
		||||
	    goto simple;
 | 
			
		||||
	}
 | 
			
		||||
    } else if (level == 0 && f->line_ref && d < 8) {
 | 
			
		||||
simple:
 | 
			
		||||
	while (d > 0)
 | 
			
		||||
	    fputs("\n", s1->ppfp), --d;
 | 
			
		||||
    } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) {
 | 
			
		||||
	fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename);
 | 
			
		||||
    } else {
 | 
			
		||||
	fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename,
 | 
			
		||||
	    level > 0 ? " 1" : level < 0 ? " 2" : "");
 | 
			
		||||
    }
 | 
			
		||||
    f->line_ref = f->line_num;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void define_print(TCCState *s1, int v)
 | 
			
		||||
{
 | 
			
		||||
    FILE *fp;
 | 
			
		||||
    Sym *s;
 | 
			
		||||
 | 
			
		||||
    s = define_find(v);
 | 
			
		||||
    if (NULL == s || NULL == s->d)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    fp = s1->ppfp;
 | 
			
		||||
    fprintf(fp, "#define %s", get_tok_str(v, NULL));
 | 
			
		||||
    if (s->type.t == MACRO_FUNC) {
 | 
			
		||||
        Sym *a = s->next;
 | 
			
		||||
        fprintf(fp,"(");
 | 
			
		||||
        if (a)
 | 
			
		||||
            for (;;) {
 | 
			
		||||
                fprintf(fp,"%s", get_tok_str(a->v & ~SYM_FIELD, NULL));
 | 
			
		||||
                if (!(a = a->next))
 | 
			
		||||
                    break;
 | 
			
		||||
                fprintf(fp,",");
 | 
			
		||||
            }
 | 
			
		||||
        fprintf(fp,")");
 | 
			
		||||
    }
 | 
			
		||||
    tok_print("", s->d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pp_debug_defines(TCCState *s1)
 | 
			
		||||
{
 | 
			
		||||
    int v, t;
 | 
			
		||||
    const char *vs;
 | 
			
		||||
    FILE *fp;
 | 
			
		||||
 | 
			
		||||
    t = pp_debug_tok;
 | 
			
		||||
    if (t == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    file->line_num--;
 | 
			
		||||
    pp_line(s1, file, 0);
 | 
			
		||||
    file->line_ref = ++file->line_num;
 | 
			
		||||
 | 
			
		||||
    fp = s1->ppfp;
 | 
			
		||||
    v = pp_debug_symv;
 | 
			
		||||
    vs = get_tok_str(v, NULL);
 | 
			
		||||
    if (t == TOK_DEFINE) {
 | 
			
		||||
        define_print(s1, v);
 | 
			
		||||
    } else if (t == TOK_UNDEF) {
 | 
			
		||||
        fprintf(fp, "#undef %s\n", vs);
 | 
			
		||||
    } else if (t == TOK_push_macro) {
 | 
			
		||||
        fprintf(fp, "#pragma push_macro(\"%s\")\n", vs);
 | 
			
		||||
    } else if (t == TOK_pop_macro) {
 | 
			
		||||
        fprintf(fp, "#pragma pop_macro(\"%s\")\n", vs);
 | 
			
		||||
    }
 | 
			
		||||
    pp_debug_tok = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pp_debug_builtins(TCCState *s1)
 | 
			
		||||
{
 | 
			
		||||
    int v;
 | 
			
		||||
    for (v = TOK_IDENT; v < tok_ident; ++v)
 | 
			
		||||
        define_print(s1, v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Preprocess the current file */
 | 
			
		||||
ST_FUNC int tcc_preprocess(TCCState *s1)
 | 
			
		||||
{
 | 
			
		||||
    BufferedFile **iptr;
 | 
			
		||||
    int token_seen, spcs, level;
 | 
			
		||||
    Sym *define_start;
 | 
			
		||||
 | 
			
		||||
    preprocess_init(s1);
 | 
			
		||||
    ch = file->buf_ptr[0];
 | 
			
		||||
| 
						 | 
				
			
			@ -3680,12 +3659,19 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
 | 
			
		|||
                | PARSE_FLAG_SPACES
 | 
			
		||||
                | PARSE_FLAG_ACCEPT_STRAYS
 | 
			
		||||
                ;
 | 
			
		||||
    define_start = define_stack;
 | 
			
		||||
 | 
			
		||||
#ifdef PP_BENCH
 | 
			
		||||
    /* for PP benchmarks */
 | 
			
		||||
    do next(); while (tok != TOK_EOF); return 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    token_seen = spcs = 0;
 | 
			
		||||
    if (s1->dflag & 1) {
 | 
			
		||||
        pp_debug_builtins(s1);
 | 
			
		||||
        s1->dflag &= ~1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token_seen = TOK_LINEFEED, spcs = 0;
 | 
			
		||||
    pp_line(s1, file, 0);
 | 
			
		||||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3700,7 +3686,13 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
 | 
			
		|||
            pp_line(s1, file, level);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (0 == token_seen) {
 | 
			
		||||
        if (s1->dflag) {
 | 
			
		||||
            pp_debug_defines(s1);
 | 
			
		||||
            if (s1->dflag & 4)
 | 
			
		||||
                continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (token_seen == TOK_LINEFEED) {
 | 
			
		||||
            if (tok == ' ') {
 | 
			
		||||
                ++spcs;
 | 
			
		||||
                continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -3710,33 +3702,19 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
 | 
			
		|||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            pp_line(s1, file, 0);
 | 
			
		||||
            while (s1->ppfp && spcs > 0)
 | 
			
		||||
                fputs(" ", s1->ppfp), --spcs;
 | 
			
		||||
            spcs = 0;
 | 
			
		||||
            token_seen = 1;
 | 
			
		||||
 | 
			
		||||
        } else if (tok == TOK_LINEFEED) {
 | 
			
		||||
            ++file->line_ref;
 | 
			
		||||
            token_seen = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (s1->ppfp)
 | 
			
		||||
            fputs(get_tok_str(tok, &tokc), s1->ppfp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        while (spcs)
 | 
			
		||||
            fputs(" ", s1->ppfp), --spcs;
 | 
			
		||||
        fputs(get_tok_str(tok, &tokc), s1->ppfp);
 | 
			
		||||
 | 
			
		||||
        token_seen = tok;
 | 
			
		||||
    }
 | 
			
		||||
    /* reset define stack, but keep -D and built-ins */
 | 
			
		||||
    free_defines(define_start);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC char *trimfront(char *p)
 | 
			
		||||
{
 | 
			
		||||
    while (*p && (unsigned char)*p <= ' ')
 | 
			
		||||
        ++p;
 | 
			
		||||
    return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ST_FUNC char *trimback(char *a, char *e)
 | 
			
		||||
{
 | 
			
		||||
    while (e > a && (unsigned char)e[-1] <= ' ')
 | 
			
		||||
        --e;
 | 
			
		||||
    *e = 0;;
 | 
			
		||||
    return a;
 | 
			
		||||
}
 | 
			
		||||
/* ------------------------------------------------------------------------- */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue