From 69a137ff889f552b3ce58b861f3f0601c1818d6b Mon Sep 17 00:00:00 2001 From: grischka Date: Fri, 14 Jul 2017 19:26:01 +0200 Subject: [PATCH] #pragma comment(option,"-..."), bitfields test, etc... tccpp.c: * #pragma comment(option,"-some-option") to set commandline option from C code. May work only for some options. libtcc.c: * option "-d1..9": sets a 'g_debug' global variable. (for development) tests2/Makefile: * new make targets: tests2.37 / tests2.37+ run single test from tests2, optionally update .expect * new variable GEN-ALWAYS to always generate certain .expects * bitfields test tccgen.c: * bitfields: fix a bug and improve slightly more * _Generic: ignore "type match twice" --- Makefile | 13 +- libtcc.c | 2 + tcc.h | 1 + tccgen.c | 67 ++++----- tccpp.c | 22 +-- tcctok.h | 1 + tests/tests2/95_bitfields.c | 215 ++++++++++++++++++++++++++++ tests/tests2/95_bitfields_ms.c | 2 + tests/tests2/95_bitfields_ms.expect | 152 ++++++++++++++++++++ tests/tests2/Makefile | 56 ++++++-- 10 files changed, 476 insertions(+), 55 deletions(-) create mode 100644 tests/tests2/95_bitfields.c create mode 100644 tests/tests2/95_bitfields_ms.c create mode 100644 tests/tests2/95_bitfields_ms.expect diff --git a/Makefile b/Makefile index ee8dcd92..62b73722 100644 --- a/Makefile +++ b/Makefile @@ -345,9 +345,12 @@ tar: tcc-doc.html config.mak: $(if $(wildcard $@),,@echo "Please run ./configure." && exit 1) -# in tests subdir +# run all tests test: $(MAKE) -C tests +# run test(s) from tests2 subdir (see make help) +tests2.%: + $(MAKE) -C tests/tests2 $@ clean: rm -f $(PROGS) $(PROGS_CROSS) tcc_p$(EXESUF) tcc.pod @@ -389,8 +392,14 @@ help: @echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include" @echo " DEF-i386 += -D__linux__" @echo "" + @echo "make test" + @echo " run all tests" + @echo "" + @echo "make tests2.all / make tests2.37 / make tests2.37+" + @echo " run all/single test(s) from tests2, optionally update .expect" + @echo "" @echo "Other supported make targets:" - @echo " install install-strip test tags ETAGS tar clean distclean help" + @echo " install install-strip tags ETAGS tar clean distclean help" @echo "" # -------------------------------------------------------------------------- diff --git a/libtcc.c b/libtcc.c index 1adcca66..72f53c0a 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1801,6 +1801,8 @@ reparse: s->dflag = 3; else if (*optarg == 'M') s->dflag = 7; + else if (isnum(*optarg)) + g_debug = atoi(optarg); else goto unsupported_option; break; diff --git a/tcc.h b/tcc.h index 8b565167..5d2cbde1 100644 --- a/tcc.h +++ b/tcc.h @@ -1289,6 +1289,7 @@ ST_DATA int func_var; /* true if current function is variadic */ ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA const char *funcname; +ST_DATA int g_debug; ST_FUNC void tcc_debug_start(TCCState *s1); ST_FUNC void tcc_debug_end(TCCState *s1); diff --git a/tccgen.c b/tccgen.c index 5a503c3c..3cc61089 100644 --- a/tccgen.c +++ b/tccgen.c @@ -57,6 +57,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA const char *funcname; +ST_DATA int g_debug; ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; @@ -1083,8 +1084,7 @@ static void load_packed_bf(CType *type, int bit_pos, int bit_size) { int n, o, bits; save_reg_upstack(vtop->r, 1); - vpushi(0); // B X - vtop->type.t |= type->t; + vpush64(type->t & VT_BTYPE, 0); // B X bits = 0, o = bit_pos >> 3, bit_pos &= 7; do { vswap(); // X B @@ -1113,7 +1113,7 @@ static void load_packed_bf(CType *type, int bit_pos, int bit_size) } /* single-byte store mode for packed or otherwise unaligned bitfields */ -void store_packed_bf(int bit_pos, int bit_size) +static void store_packed_bf(int bit_pos, int bit_size) { int bits, n, o, m, c; @@ -1148,7 +1148,7 @@ void store_packed_bf(int bit_pos, int bit_size) vpop(), vpop(); } -int adjust_bf(SValue *sv, int bit_pos, int bit_size) +static int adjust_bf(SValue *sv, int bit_pos, int bit_size) { int t; if (0 == sv->type.ref) @@ -2781,7 +2781,7 @@ static void type_to_str(char *buf, int buf_size, pstrcat(buf, buf_size, "inline "); buf_size -= strlen(buf); buf += strlen(buf); - if (IS_ENUM(type->t)) { + if (IS_ENUM(t)) { tstr = "enum "; goto tstruct; } @@ -3405,9 +3405,12 @@ static void struct_layout(CType *type, AttributeDef *ad) //#define BF_DEBUG for (f = type->ref->next; f; f = f->next) { - if (f->type.t & VT_BITFIELD) + if (f->type.t & VT_BITFIELD) { bit_size = BIT_SIZE(f->type.t); - else + /* in pcc mode, long long bitfields have type int if they fit */ + if (pcc && (f->type.t & VT_BTYPE) == VT_LLONG && bit_size <= 32) + f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT; + } else bit_size = -1; size = type_size(&f->type, &align); a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0; @@ -3476,16 +3479,10 @@ static void struct_layout(CType *type, AttributeDef *ad) goto new_field; } - /* in pcc mode, long long bitfields have type int if they fit */ - if (size == 8 && bit_size <= 32) { - f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT; - size = 4; - } - if (bit_pos >= size * 8) { - c += size; - bit_pos -= size * 8; - } + while (bit_pos >= align * 8) + c += align, bit_pos -= align * 8; offset = c; + /* In PCC layout named bit-fields influence the alignment of the containing struct using the base types alignment, except for packed fields (which here have correct align). */ @@ -3576,14 +3573,20 @@ static void struct_layout(CType *type, AttributeDef *ad) if (pcc) c += (bit_pos + 7) >> 3; - a = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 0; + /* store size and alignment */ + a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1; if (a < maxalign) a = maxalign; - c = (c + a - 1) & -a; - - /* store size and alignment */ - type->ref->c = c; type->ref->r = a; + if (pragma_pack && pragma_pack < maxalign) { + /* can happen if individual align for some member was given. In + this case MSVC ignores maxalign when aligning the size */ + a = pragma_pack; + if (a < bt) + a = bt; + } + c = (c + a - 1) & -a; + type->ref->c = c; #ifdef BF_DEBUG printf("struct size %-2d align %-2d\n\n", c, a), fflush(stdout); @@ -3603,7 +3606,6 @@ static void struct_layout(CType *type, AttributeDef *ad) continue; bit_pos = BIT_POS(f->type.t); size = type_size(&f->type, &align); - if (bit_pos + bit_size <= size * 8 && f->c + size <= c) continue; @@ -3637,19 +3639,20 @@ static void struct_layout(CType *type, AttributeDef *ad) | (bit_pos << VT_STRUCT_SHIFT); if (s != size) f->auxtype = t.t; +#ifdef BF_DEBUG + printf("FIX field %s offset %-2d size %-2d align %-2d " + "pos %-2d bits %-2d\n", + get_tok_str(f->v & ~SYM_FIELD, NULL), + cx, s, align, px, bit_size); +#endif } else { /* fall back to load/store single-byte wise */ f->auxtype = VT_STRUCT; - } - #ifdef BF_DEBUG - printf("FIX field %s offset %-2d size %-2d align %-2d " - "pos %-2d bits %-2d %s\n", - get_tok_str(f->v & ~SYM_FIELD, NULL), - cx, s, align, px, bit_size, - f->auxtype == VT_PTR ? " byte-wise" : "" - ); + printf("FIX field %s : load byte-wise\n", + get_tok_str(f->v & ~SYM_FIELD, NULL)); #endif + } } } @@ -4915,9 +4918,9 @@ ST_FUNC void unary(void) type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT); if (compare_types(&controlling_type, &cur_type, 0)) { if (has_match) { - tcc_error("type march twice"); + // tcc_error("type march twice"); } - if (has_default) + if (str) tok_str_free(str); has_match = 1; learn = 1; diff --git a/tccpp.c b/tccpp.c index 9ac98a61..0e46510d 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1658,24 +1658,28 @@ static void pragma_parse(TCCState *s1) goto pragma_err; } else if (tok == TOK_comment) { - char *file; + char *p; int t; next(); skip('('); - if (tok != TOK_lib) - goto pragma_warn; + t = tok; next(); skip(','); if (tok != TOK_STR) goto pragma_err; - file = tcc_strdup((char *)tokc.str.data); - dynarray_add(&s1->pragma_libs, &s1->nb_pragma_libs, file); + p = tcc_strdup((char *)tokc.str.data); next(); if (tok != ')') goto pragma_err; - } else { -pragma_warn: - if (s1->warn_unsupported) - tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); + if (t == TOK_lib) { + dynarray_add(&s1->pragma_libs, &s1->nb_pragma_libs, p); + } else { + if (t == TOK_option) + tcc_set_options(s1, p); + tcc_free(p); + } + + } else if (s1->warn_unsupported) { + tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc)); } return; diff --git a/tcctok.h b/tcctok.h index 6d4ad304..5380ff3e 100644 --- a/tcctok.h +++ b/tcctok.h @@ -167,6 +167,7 @@ DEF(TOK_push_macro, "push_macro") DEF(TOK_pop_macro, "pop_macro") DEF(TOK_once, "once") + DEF(TOK_option, "option") /* builtin functions or variables */ #ifndef TCC_ARM_EABI diff --git a/tests/tests2/95_bitfields.c b/tests/tests2/95_bitfields.c new file mode 100644 index 00000000..1ec9781e --- /dev/null +++ b/tests/tests2/95_bitfields.c @@ -0,0 +1,215 @@ +/* ----------------------------------------------------------------------- */ +#if TEST == 1 +{ + struct M P A __s + { + unsigned x : 12; + unsigned char y : 7; + unsigned z : 28; + unsigned a: 4; + unsigned b: 5; + }; + TEST_STRUCT(0x333,0x44,0x555555,6,7); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 2 +{ + struct M P __s + { + int x: 12; + char y: 6; + long long z:63; + A char a:4; + long long b:2; + + }; + TEST_STRUCT(3,30,0x123456789abcdef0LL,5,2); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 3 +{ + struct M P __s + { + unsigned x:5, y:5, :0, z:5; char a:5; A short b:5; + }; + TEST_STRUCT(21,23,25,6,14); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 4 +{ + struct M P __s { + int x : 3; + int : 2; + int y : 1; + int : 0; + int z : 5; + int a : 7; + unsigned int b : 7; + }; + TEST_STRUCT(3,1,15,120,120); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 5 +{ + struct M P __s { + long long x : 45; + long long : 2; + long long y : 35; + unsigned long long z : 38; + char a; short b; + }; + TEST_STRUCT(0x123456789ULL, 120<<25, 120, 0x44, 0x77); +} + +/* ----------------------------------------------------------------------- */ +#elif TEST == 6 +{ + struct M P __s { + int a; + char b; + int x : 12, y : 4, : 0, : 4, z : 3; + char d; + }; + TEST_STRUCT(1,2,3,4,-3); +} + +/* ----------------------------------------------------------------------- */ +#elif defined PACK + +#if PACK +# pragma pack(push,1) +# define P //_P +#else +# define P +#endif + +#define TEST 1 +#include SELF +#define TEST 2 +#include SELF +#define TEST 3 +#include SELF +#define TEST 4 +#include SELF +#define TEST 5 +#include SELF +#define TEST 6 +#include SELF +printf("\n\n"); + +#if PACK +# pragma pack(pop) +#endif + +#undef P +#undef PACK + +/* ----------------------------------------------------------------------- */ +#elif defined ALIGN + +#if ALIGN +# define A _A(16) +#else +# define A +#endif + +#define PACK 0 +#include SELF +#define PACK 1 +#include SELF + +#undef A +#undef ALIGN + +/* ----------------------------------------------------------------------- */ +#elif defined MS_BF + +#if MS_BF +# ifdef __TINYC__ +# pragma comment(option, "-mms-bitfields") +# elif defined __GNUC__ +# define M __attribute__((ms_struct)) +# endif +#else +# ifdef __TINYC__ +# pragma comment(option, "-mno-ms-bitfields") +# elif defined __GNUC__ +# define M __attribute__((gcc_struct)) +# endif +#endif +#ifndef M +# define M +#endif + +#define ALIGN 0 +#include SELF +#define ALIGN 1 +#include SELF + +#undef M +#undef MS_BF + +/* ----------------------------------------------------------------------- */ +#else + +#include +#include +/* some gcc headers #define __attribute__ to empty if it's not gcc */ +#undef __attribute__ + +void dump(void *p, int s) +{ + int i; + for (i = s; --i >= 0;) + printf("%02X", ((unsigned char*)p)[i]); + printf("\n"); +} + +#define pv(m) \ + printf(sizeof (s->m + 0) == 8 ? " %016llx" : " %02x", s->m) + +#define TEST_STRUCT(v1,v2,v3,v4,v5) { \ + struct __s _s, *s = & _s; \ + printf("---- TEST %d%s%s%s ----\n", \ + TEST, MS_BF?" - MS-BITFIELDS":"", \ + PACK?" - PACKED":"", \ + ALIGN?" - WITH ALIGN":""); \ + memset(s, 0, sizeof *s); \ + s->x = -1, s->y = -1, s->z = -1, s->a = -1, s->b = -1; \ + printf("bits in use : "), dump(s, sizeof *s); \ + s->x = v1, s->y = v2, s->z = v3, s->a += v4, ++s->a, s->b = v5; \ + printf("bits as set : "), dump(s, sizeof *s); \ + printf("values :"), pv(x), pv(y), pv(z), pv(a), pv(b), printf("\n"); \ + printf("align/size : %d %d\n\n", alignof(struct __s),sizeof(struct __s)); \ + } + +#ifdef _MSC_VER +# define _A(n) __declspec(align(n)) +# define _P +# define alignof(x) __alignof(x) +#else +# define _A(n) __attribute__((aligned(n))) +# define _P __attribute__((packed)) +# define alignof(x) __alignof__(x) +#endif + +#ifndef MS_BITFIELDS +# define MS_BITFIELDS 0 +#endif + +#define SELF "95_bitfields.c" + +int main() +{ +#define MS_BF MS_BITFIELDS +#include SELF + return 0; +} + +/* ----------------------------------------------------------------------- */ +#endif +#undef TEST diff --git a/tests/tests2/95_bitfields_ms.c b/tests/tests2/95_bitfields_ms.c new file mode 100644 index 00000000..b196fbd6 --- /dev/null +++ b/tests/tests2/95_bitfields_ms.c @@ -0,0 +1,2 @@ +#define MS_BITFIELDS 1 +#include "95_bitfields.c" diff --git a/tests/tests2/95_bitfields_ms.expect b/tests/tests2/95_bitfields_ms.expect new file mode 100644 index 00000000..f4eb2d36 --- /dev/null +++ b/tests/tests2/95_bitfields_ms.expect @@ -0,0 +1,152 @@ +---- TEST 1 - MS-BITFIELDS ---- +bits in use : 0000001FFFFFFFFF0000007F00000FFF +bits as set : 00000007605555550000004400000333 +values : 333 44 555555 06 07 +align/size : 4 16 + +---- TEST 2 - MS-BITFIELDS ---- +bits in use : 0000000000000003000000000000000F7FFFFFFFFFFFFFFF0000003F00000FFF +bits as set : 00000000000000020000000000000005123456789ABCDEF00000001E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 8 32 + +---- TEST 3 - MS-BITFIELDS ---- +bits in use : 001F001F0000001F000003FF +bits as set : 000E000600000019000002F5 +values : 15 17 19 06 0e +align/size : 4 12 + +---- TEST 4 - MS-BITFIELDS ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 4 8 + +---- TEST 5 - MS-BITFIELDS ---- +bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF +bits as set : 0000000000770044000000000000007800000007F00000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 8 32 + +---- TEST 6 - MS-BITFIELDS ---- +bits in use : 00000000000000700000FFFF000000FFFFFFFFFF +bits as set : 000000000000003000002001000000FD00000004 +values : 01 02 03 04 fffffffd +align/size : 4 20 + + + +---- TEST 1 - MS-BITFIELDS - PACKED ---- +bits in use : 0000001FFFFFFFFF7F00000FFF +bits as set : 00000007605555554400000333 +values : 333 44 555555 06 07 +align/size : 1 13 + +---- TEST 2 - MS-BITFIELDS - PACKED ---- +bits in use : 00000000000000030F7FFFFFFFFFFFFFFF3F00000FFF +bits as set : 000000000000000205123456789ABCDEF01E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 1 22 + +---- TEST 3 - MS-BITFIELDS - PACKED ---- +bits in use : 001F1F0000001F000003FF +bits as set : 000E0600000019000002F5 +values : 15 17 19 06 0e +align/size : 1 11 + +---- TEST 4 - MS-BITFIELDS - PACKED ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 1 8 + +---- TEST 5 - MS-BITFIELDS - PACKED ---- +bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF +bits as set : 007744000000000000007800000007F00000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 1 27 + +---- TEST 6 - MS-BITFIELDS - PACKED ---- +bits in use : 00000000700000FFFFFFFFFFFFFF +bits as set : 000000003000002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 1 14 + + + +---- TEST 1 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0000001FFFFFFFFF0000007F00000FFF +bits as set : 00000007605555550000004400000333 +values : 333 44 555555 06 07 +align/size : 16 16 + +---- TEST 2 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0000000000000003000000000000000F7FFFFFFFFFFFFFFF0000003F00000FFF +bits as set : 00000000000000020000000000000005123456789ABCDEF00000001E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 16 32 + +---- TEST 3 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0000000000000000000000000000001F000000000000001F0000001F000003FF +bits as set : 0000000000000000000000000000000E000000000000000600000019000002F5 +values : 15 17 19 06 0e +align/size : 16 32 + +---- TEST 4 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 4 8 + +---- TEST 5 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF +bits as set : 0000000000770044000000000000007800000007F00000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 8 32 + +---- TEST 6 - MS-BITFIELDS - WITH ALIGN ---- +bits in use : 00000000000000700000FFFF000000FFFFFFFFFF +bits as set : 000000000000003000002001000000FD00000004 +values : 01 02 03 04 fffffffd +align/size : 4 20 + + + +---- TEST 1 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 0000000000001FFFFFFFFF7F00000FFF +bits as set : 00000000000007605555554400000333 +values : 333 44 555555 06 07 +align/size : 16 16 + +---- TEST 2 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 00000000000000030F0000007FFFFFFFFFFFFFFF3F00000FFF +bits as set : 000000000000000205000000123456789ABCDEF01E00000003 +values : 03 1e 123456789abcdef0 05 fffffffffffffffe +align/size : 16 25 + +---- TEST 3 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 001F000000000000001F0000001F000003FF +bits as set : 000E000000000000000600000019000002F5 +values : 15 17 19 06 0e +align/size : 16 18 + +---- TEST 4 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 0007FFFF00000027 +bits as set : 00078F0F00000023 +values : 03 ffffffff 0f fffffff8 78 +align/size : 1 8 + +---- TEST 5 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF +bits as set : 007744000000000000007800000007F00000000000000123456789 +values : 0000000123456789 fffffffff0000000 0000000000000078 44 77 +align/size : 1 27 + +---- TEST 6 - MS-BITFIELDS - PACKED - WITH ALIGN ---- +bits in use : 00000000700000FFFFFFFFFFFFFF +bits as set : 000000003000002001FD00000004 +values : 01 02 03 04 fffffffd +align/size : 1 14 + + + diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index e921f574..44f20f72 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -18,6 +18,9 @@ NORUN = FLAGS = 76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers +# Always generate certain .expects (don't put these in the GIT), +GEN-ALWAYS = 95_bitfields.expect + # Filter source directory in warnings/errors (out-of-tree builds) FILTER = 2>&1 | sed 's,$(SRC)/,,g' # Filter some always-warning @@ -40,26 +43,55 @@ endif ifeq (,$(filter i386 x86_64,$(ARCH))) SKIP += 85_asm-outside-function.test endif +ifeq (-$(findstring gcc,$(CC)-)-,--) + SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS)) +endif +ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-) + SKIP += 95_bitfields_ms.test # type_align is differnt on 32bit-non-windows +endif -all test: $(filter-out $(SKIP),$(TESTS)) +all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ; %.test: %.c %.expect @echo Test: $*... -# test -run - @if test -z "$(NORUN)"; then \ - $(TCC) $(FLAGS) -run $< $(ARGS) $(FILTER) >$*.output 2>&1 || true; \ - else \ - $(TCC) $(FLAGS) $< -o ./$*.exe $(FILTER) >$*.output 2>&1; \ - ./$*.exe $(ARGS) >>$*.output 2>&1 || true; \ - fi - @diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output $*.exe + @$(if $(NORUN),\ + ($(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)),\ + $(TCC) $(FLAGS) -run $< $(ARGS)\ + ) $(FILTER) >$*.output 2>&1 || true + @diff -Nbu $(filter %.expect,$^) $*.output \ + && rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS)) + +F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test) +F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)" + +# run single test and update .expect file, e.g. "make tests2.37+" +tests2.%+: + @$(MAKE) $(call F2,$(call F1,$*)) --no-print-directory + +# run single test, e.g. "make tests2.37" +tests2.%: + @$(MAKE) $(call F1,$*) --no-print-directory # automatically generate .expect files with gcc: -%.expect : # %.c - (gcc -w $*.c -o a.exe && ./a.exe $(ARGS)) $(FILTER) >$*.expect 2>&1; rm -f a.exe +%.expect : + @echo Generating: $@ + @$(CC) -w -std=gnu99 $(FLAGS) $(SRC)/$*.c -o a.exe + @./a.exe $(ARGS) $(FILTER) >$@ 2>&1 + @rm -f a.exe + +# using the ms compiler for the really ms-compatible bitfields +MS-CC = cl +95_bitfields_ms.expect : + @echo Generating: $@ + @$(MS-CC) $(basename $@).c + @./$(basename $@).exe >$@ 2>&1 + @rm -f *.exe *.obj *.pdb # tell make not to delete .PRECIOUS: %.expect +$(sort $(GEN-ALWAYS) $(UPDATE)) : force +force: + clean: - rm -f fred.txt *.output a.exe + rm -f fred.txt *.output a.exe $(GEN-ALWAYS)