From 89bb2de49afb6be7edcddebfa0b3d2eacf33a280 Mon Sep 17 00:00:00 2001 From: cbmarini Date: Wed, 24 Jun 2026 14:29:13 +0200 Subject: [PATCH 1/2] coverage: wrap unfinished features into custom lcov exclusion markers, see the new .lcovrc, to hide them from coverage statistics. This commit hides the following: - #namespace - #setflag - MultiBracket - Complete checkpoint.c file - Complete diagrams.c file --- .github/workflows/test.yml | 2 +- .lcovrc | 8 ++++++++ sources/checkpoint.c | 4 ++-- sources/compcomm.c | 12 ++++++------ sources/diagrams.c | 4 +++- sources/pre.c | 24 ++++++++++++------------ 6 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 .lcovrc diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 93f653ed..772b0815 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -216,7 +216,7 @@ jobs: - name: Generate LCOV coverage data run: | - lcov -d . -c -o coverage.lcov + lcov --config-file .lcovrc -d . -c -o coverage.lcov lcov -r coverage.lcov '*/usr/include/*' '*/extern/*'${{ matrix.flint != 'no' && ' ''*/lib/*''' || '' }} -o coverage.lcov - name: Coveralls Parallel diff --git a/.lcovrc b/.lcovrc new file mode 100644 index 00000000..9b69157b --- /dev/null +++ b/.lcovrc @@ -0,0 +1,8 @@ +# FORM-specific LCOV exclusion markers: +# +# - INTERNAL_ERROR_EXCL_...: exclude internal errors from the coverage statistics +# - UNFINISHED_FEATURE_EXCL_...: exclude unfinished features code. +# +lcov_excl_start = (INTERNAL_ERROR_EXCL_START|UNFINISHED_FEATURE_EXCL_START) +lcov_excl_stop = (INTERNAL_ERROR_EXCL_STOP|UNFINISHED_FEATURE_EXCL_STOP) +lcov_excl_line = (INTERNAL_ERROR_EXCL_LINE|UNFINISHED_FEATURE_EXCL_LINE) diff --git a/sources/checkpoint.c b/sources/checkpoint.c index ce318fe8..343170d6 100644 --- a/sources/checkpoint.c +++ b/sources/checkpoint.c @@ -80,7 +80,7 @@ #] License : #[ Includes : */ - +/* UNFINISHED_FEATURE_EXCL_START */ #include "form3.h" #include @@ -3244,7 +3244,7 @@ void DoCheckpoint(int moduletype) }/*if(PF.me != MASTER)*/ #endif } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] DoCheckpoint : */ diff --git a/sources/compcomm.c b/sources/compcomm.c index ac38ead5..7a84f26c 100644 --- a/sources/compcomm.c +++ b/sources/compcomm.c @@ -3920,7 +3920,7 @@ int CoAntiBracket(UBYTE *inp) Syntax: MultiBracket:{A|B} bracketinfo:...:{A|B} bracketinfo; */ - +/* UNFINISHED_FEATURE_EXCL_START */ int CoMultiBracket(UBYTE *inp) { GETIDENTITY @@ -4027,7 +4027,7 @@ int CoMultiBracket(UBYTE *inp) AT.bracketindexflag = 0; return(error); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] CoMultiBracket : #[ CountComp : @@ -7404,7 +7404,7 @@ int CoEndSwitch(UBYTE *s) #] CoEndSwitch : #[ CoSetUserFlag : */ - +/* UNFINISHED_FEATURE_EXCL_START */ int CoSetUserFlag(UBYTE *s) { int error = 0; @@ -7427,12 +7427,12 @@ int CoSetUserFlag(UBYTE *s) } return(error); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] CoSetUserFlag : #[ CoClearUserFlag : */ - +/* UNFINISHED_FEATURE_EXCL_START */ int CoClearUserFlag(UBYTE *s) { int error = 0; @@ -7455,7 +7455,7 @@ int CoClearUserFlag(UBYTE *s) } return(error); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] CoClearUserFlag : #[ CoCreateAllLoops : diff --git a/sources/diagrams.c b/sources/diagrams.c index 90f691c6..37ce01d6 100644 --- a/sources/diagrams.c +++ b/sources/diagrams.c @@ -31,7 +31,7 @@ /* #[ Includes : diagrams.c */ - +/* UNFINISHED_FEATURE_EXCL_START */ #include "form3.h" static WORD one = 1; @@ -661,3 +661,5 @@ MesPrint("partitions = %a",2*nvert,partitions); /* #] DoShattering : */ + +/* UNFINISHED_FEATURE_EXCL_STOP */ diff --git a/sources/pre.c b/sources/pre.c index cee07818..4c04f53e 100644 --- a/sources/pre.c +++ b/sources/pre.c @@ -7308,7 +7308,7 @@ int DoTimeOutAfter(UBYTE *s) Names of preprocessor variables are excluded! Names of built in objects are excluded! (like sum_, d_ etc.) */ - +/* UNFINISHED_FEATURE_EXCL_START */ int DoNamespace(UBYTE *s) { UBYTE *s1, *s2, c; @@ -7351,12 +7351,12 @@ int DoNamespace(UBYTE *s) *s1 = c; return(0); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] DoNamespace : #[ DoEndNamespace : */ - +/* UNFINISHED_FEATURE_EXCL_START */ int DoEndNamespace(UBYTE *s) { NAMESPACE *namespace; @@ -7374,7 +7374,7 @@ int DoEndNamespace(UBYTE *s) M_free(namespace,"namespace"); return(0); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] DoEndNamespace : #[ SkipName : @@ -7571,7 +7571,7 @@ UBYTE *ConstructName(UBYTE *s,UBYTE type) The names are stored in a balanced tree. Each namespace may have its own tree. The toplevel (no namespace) does not allow a #use. */ - +/* UNFINISHED_FEATURE_EXCL_START */ int DoUse(UBYTE *s) { NAMESPACE *namespace; @@ -7603,7 +7603,7 @@ int DoUse(UBYTE *s) } return(0); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] DoUse : #[ UserFlags : @@ -7619,7 +7619,7 @@ int DoUse(UBYTE *s) #SetFlag par == 0: Clear, par == 1: Set. */ - +/* UNFINISHED_FEATURE_EXCL_START */ int UserFlags(UBYTE *s,int par) { int mask = 0, error = 0, i; @@ -7721,27 +7721,27 @@ int UserFlags(UBYTE *s,int par) MesPrint("@Illegal name in #...Flag instruction."); return(1); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] UserFlags : #[ DoClearUserFlag : */ - +/* UNFINISHED_FEATURE_EXCL_START */ int DoClearUserFlag(UBYTE *s) { return(UserFlags(s,0)); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] DoClearUserFlag : #[ DoSetUserFlag : */ - +/* UNFINISHED_FEATURE_EXCL_START */ int DoSetUserFlag(UBYTE *s) { return(UserFlags(s,1)); } - +/* UNFINISHED_FEATURE_EXCL_STOP */ /* #] DoSetUserFlag : #[ DoStartFloat : From 1d963a50e139b08cad05240fbdf51468aaf43c05 Mon Sep 17 00:00:00 2001 From: cbmarini Date: Tue, 30 Jun 2026 13:11:32 +0200 Subject: [PATCH 2/2] feature: add `!>` as a marker for internal errors in MesPrint(). - This should go together with the lcov exclusion markers INTERNAL_ERROR_EXCL_START etc. fix: don't allow MesPrint error markers `@` and `#` in the regular Print statement, similar as already implemented for `&`. --- sources/flintinterface.cc | 80 +++++++++++++++++++++++++++++---------- sources/message.c | 20 +++++++++- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/sources/flintinterface.cc b/sources/flintinterface.cc index ef524234..42e515f0 100644 --- a/sources/flintinterface.cc +++ b/sources/flintinterface.cc @@ -100,16 +100,20 @@ WORD* flint::divmod_mpoly(PHEAD const WORD *a, const WORD *b, const bool return_ // The input won't have any symbols with negative powers, but there may be rational // coefficients. Verify this: if ( fmpz_mpoly_is_fmpz(denpa.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::divmod_mpoly: error: denpa is non-constant"); + MesPrint("!>flint::divmod_mpoly: error: denpa is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } if ( fmpz_mpoly_is_fmpz(denpb.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::divmod_mpoly: error: denpb is non-constant"); + MesPrint("!>flint::divmod_mpoly: error: denpb is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } @@ -169,16 +173,20 @@ WORD* flint::divmod_poly(PHEAD const WORD *a, const WORD *b, const bool return_r // The input won't have any symbols with negative powers, but there may be rational // coefficients. Verify this: if ( fmpz_poly_length(denpa.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::divmod_poly: error: denpa is non-constant"); + MesPrint("!>flint::divmod_poly: error: denpa is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } if ( fmpz_poly_length(denpb.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::divmod_poly: error: denpb is non-constant"); + MesPrint("!>flint::divmod_poly: error: denpb is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } flint::fmpz scale; @@ -241,10 +249,12 @@ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool w flint::from_argument_mpoly(arg.d, den.d, argin, with_arghead, var_map, ctx.d); // The denominator must be 1: if ( fmpz_mpoly_is_one(den.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::factorize_mpoly error: den != 1"); + MesPrint("!>flint::factorize_mpoly error: den != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } @@ -258,10 +268,12 @@ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool w // FORM should always have taken the overall constant out in the content. Thus this overall // constant factor should be +- 1 here. Verify this: if ( ! ( fmpz_equal_si(overall_constant.d, 1) || fmpz_equal_si(overall_constant.d, -1) ) ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::factorize_mpoly error: overall constant factor != +-1"); + MesPrint("!>flint::factorize_mpoly error: overall constant factor != +-1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } // Construct the output. If argout is not NULL, we write the result there. @@ -389,10 +401,12 @@ WORD* flint::factorize_poly(PHEAD const WORD *argin, WORD *argout, const bool wi flint::from_argument_poly(arg.d, den.d, argin, with_arghead); // The denominator must be 1: if ( fmpz_poly_is_one(den.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::factorize_poly error: den != 1"); + MesPrint("!>flint::factorize_poly error: den != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } @@ -512,11 +526,13 @@ void flint::form_sort(PHEAD WORD *terms) { // Check the final size if ( in_size != out_size ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::form_sort: error: unexpected sorted arg length change %d->%d", in_size, + MesPrint("!>flint::form_sort: error: unexpected sorted arg length change %d->%d", in_size, out_size); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } AR.SortType = oldsorttype; @@ -949,16 +965,20 @@ WORD* flint::gcd_mpoly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_t // denpa, denpb must be 1: if ( fmpz_mpoly_is_one(denpa.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_mpoly: error: denpa != 1"); + MesPrint("!>flint::gcd_mpoly: error: denpa != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } if ( fmpz_mpoly_is_one(denpb.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_mpoly: error: denpb != 1"); + MesPrint("!>flint::gcd_mpoly: error: denpb != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } // poly returns pa if pa == pb, regardless of the lcoeff sign @@ -973,17 +993,21 @@ WORD* flint::gcd_mpoly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_t flint::mpoly tmp(ctx.d); fmpz_mpoly_term_content(tmp.d, pa.d, ctx.d); if ( fmpz_mpoly_is_one(tmp.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_mpoly: error: content of 1st arg != 1"); + MesPrint("!>flint::gcd_mpoly: error: content of 1st arg != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } fmpz_mpoly_term_content(tmp.d, pb.d, ctx.d); if ( fmpz_mpoly_is_one(tmp.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_mpoly: error: content of 2nd arg != 1"); + MesPrint("!>flint::gcd_mpoly: error: content of 2nd arg != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } // The poly class now divides the content out of a,b so that they have a positive lcoeff. @@ -1044,16 +1068,20 @@ WORD* flint::gcd_poly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_te // denpa, denpb must be 1: if ( fmpz_poly_is_one(denpa.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_poly: error: denpa != 1"); + MesPrint("!>flint::gcd_poly: error: denpa != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } if ( fmpz_poly_is_one(denpb.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_poly: error: denpb != 1"); + MesPrint("!>flint::gcd_poly: error: denpb != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } // poly returns pa if pa == pb, regardless of the lcoeff sign @@ -1067,17 +1095,21 @@ WORD* flint::gcd_poly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_te flint::fmpz tmp; fmpz_poly_content(tmp.d, pa.d); if ( fmpz_is_one(tmp.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_poly: error: content of 1st arg != 1"); + MesPrint("!>flint::gcd_poly: error: content of 1st arg != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } fmpz_poly_content(tmp.d, pb.d); if ( fmpz_is_one(tmp.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::gcd_poly: error: content of 2nd arg != 1"); + MesPrint("!>flint::gcd_poly: error: content of 2nd arg != 1"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } fmpz_poly_gcd(gcd.d, pa.d, pb.d); @@ -1325,16 +1357,20 @@ WORD* flint::mul_mpoly(PHEAD const WORD *a, const WORD *b, const var_map_t &var_ // denpa, denpb must be integers. Negative symbol powers have been converted to extra symbols. if ( fmpz_mpoly_is_fmpz(denpa.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::mul_mpoly: error: denpa is non-constant"); + MesPrint("!>flint::mul_mpoly: error: denpa is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } if ( fmpz_mpoly_is_fmpz(denpb.d, ctx.d) != 1 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::mul_mpoly: error: denpb is non-constant"); + MesPrint("!>flint::mul_mpoly: error: denpb is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } // Multiply numerators, store result in pa @@ -1376,16 +1412,20 @@ WORD* flint::mul_poly(PHEAD const WORD *a, const WORD *b, const var_map_t &var_m // denpa, denpb must be integers. Negative symbol powers have been converted to extra symbols. if ( fmpz_poly_degree(denpa.d) != 0 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::mul_poly: error: denpa is non-constant"); + MesPrint("!>flint::mul_poly: error: denpa is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } if ( fmpz_poly_degree(denpb.d) != 0 ) { + // INTERNAL_ERROR_EXCL_START MLOCK(ErrorMessageLock); - MesPrint("flint::mul_poly: error: denpb is non-constant"); + MesPrint("!>flint::mul_poly: error: denpb is non-constant"); MUNLOCK(ErrorMessageLock); Terminate(-1); + // INTERNAL_ERROR_EXCL_STOP } // Multiply numerators, store result in pa diff --git a/sources/message.c b/sources/message.c index 736cff42..1a174e38 100644 --- a/sources/message.c +++ b/sources/message.c @@ -124,6 +124,7 @@ NORETURN void MesWork(void) # " ==> " @ " ==> " Preprocessor error & ' --> ' Regular compiler error + !> ' ~~> ' Internal error Each call is terminated with a new line. Put a % at the end of the string to suppress the new line. @@ -172,7 +173,7 @@ int MesPrint(const char *fmt, ... ) t = Out; stopper = Out + AC.LineLength; while ( *s ) { - if ( ( ( *s == '&' && AO.ErrorBlock == 0 ) || *s == '@' || *s == '#' ) && AC.CurrentStream != 0 ) { + if ( ( *s == '&' || *s == '@' || *s == '#' || ( *s == '!' && s[1] == '>' ) ) && AO.ErrorBlock == 0 && AC.CurrentStream != 0 ) { u = (char *)AC.CurrentStream->name; while ( *u ) { *t++ = *u++; @@ -199,9 +200,24 @@ int MesPrint(const char *fmt, ... ) if ( ( *s == '&' && AO.ErrorBlock == 0 ) ) { *t++ = ' '; *t++ = '-'; *t++ = '-'; *t++ = '>'; *t++ = ' '; s++; } - else if ( *s == '@' || *s == '#' ) { + else if ( ( *s == '@' || *s == '#' ) && AO.ErrorBlock == 0 ) { *t++ = ' '; *t++ = '='; *t++ = '='; *t++ = '>'; *t++ = ' '; s++; } + else if ( *s == '!' && s[1] == '>' && AO.ErrorBlock == 0 ) { + const char *m = " ~~> Internal error, please report with the following message:"; + while ( *m ) { + *t++ = *m++; + if ( t >= stopper ) { + num = t - Out; + WriteString(ERROROUT,(UBYTE *)Out,num); + num = 0; t = Out; + } + } + num = t - Out; + WriteString(ERROROUT,(UBYTE *)Out,num); + num = 0; t = Out; + s += 2; + } /* else if ( *s == '&' && AO.ErrorBlock == 1 ) {