diff --git a/community/gap/PKGBUILD b/community/gap/PKGBUILD index 2ec7cb8ff..342b4021a 100644 --- a/community/gap/PKGBUILD +++ b/community/gap/PKGBUILD @@ -8,14 +8,18 @@ pkgbase=gap pkgname=(gap gap-doc gap-packages) pkgver=4.10.0 -pkgrel=3 +pkgrel=4 pkgdesc="Groups, Algorithms, Programming: a system for computational discrete algebra" arch=(x86_64) url="https://www.gap-system.org/" license=(GPL) -source=("https://www.gap-system.org/pub/gap/gap-${pkgver%.*}/tar.gz/gap-$pkgver.tar.gz" gap-no-packages-by-default.patch) +source=("https://www.gap-system.org/pub/gap/gap-${pkgver%.*}/tar.gz/gap-$pkgver.tar.gz" gap.sh + gap-sagemath-1.patch gap-sagemath-2.patch gap-sagemath-3.patch) sha256sums=('314b8d949c0bb01ef8bee199b29571d42714df660aba0d76ded254f58295904f' - 'e8f19968d998172b7c289d0499b8b8a05bc31119a1ce073181d3842ece6fe3a2') + '143fb8a79a52c007903cce13407850df309ef803a9b00398d05169355917de46' + 'e5f0a71ae5cdcc6596330834ef9fb0a0183890a9cf874a7eb88b819b0030a33b' + '3b66e6b320f56119b1d8eb804a94ee3a7ea71af10bd4f99a61bae32840e62c87' + '511414a8d085a9ef9de5f921fdd45e4bbb3f33c2d88b821da06dfc267c182ddc') makedepends=(libxaw givaro mpfi normaliz boost c-xsc zeromq fplll polymake wget chrpath) prepare() { @@ -23,10 +27,13 @@ prepare() { # Use system normaliz sed -e '/build-normaliz.sh/d' -i bin/BuildPackages.sh -# Don't load any packages by default - patch -p1 -i ../gap-no-packages-by-default.patch # Disable anupq package, it's i686 only rm -r pkg/anupq-* + +# Patches to make sagemath work with GAP's libgap + patch -p1 -i ../gap-sagemath-1.patch + patch -p1 -i ../gap-sagemath-2.patch + patch -p1 -i ../gap-sagemath-3.patch } build() { @@ -39,28 +46,33 @@ build() { ../bin/BuildPackages.sh } +_standardpkgs=(GAPDoc-* primgrp-* SmallGrp-* transgrp atlasrep autpgrp-* alnuth-* crisp-* ctbllib FactInt-* fga irredsol-* laguna-* + polenta-* polycyclic-* resclasses-* sophus-* tomlib-*) + package_gap() { - depends=(gmp) + depends=(gmp zlib) optdepends=('gap-packages: extra packages' 'gap-doc: documentation') -# conflicts=(libgap) - replaces=(gap-data) + conflicts=(libgap) + replaces=(gap-data libgap gap-4.8 gap-4.8-data) cd gap-$pkgver -# make DESTDIR="$pkgdir" install + make DESTDIR="$pkgdir" install-headers install-libgap +# Install missing header + install -Dm644 gen/config.h -t "$pkgdir"/usr/include/gap mkdir -p "$pkgdir"/usr/{bin,lib/gap/pkg} cp -r grp lib "$pkgdir"/usr/lib/gap - cp -r pkg/{GAPDoc-*,primgrp-*,SmallGrp-*,transgrp} "$pkgdir"/usr/lib/gap/pkg - install -m755 gap -t "$pkgdir"/usr/lib/gap - sed -e "s|/build/gap/src/gap-$pkgver|/usr/lib/gap|g" bin/gap.sh > "$pkgdir"/usr/bin/gap - chmod 755 "$pkgdir"/usr/bin/gap - -# install missing header -# cp gen/config.h "$pkgdir"/usr/include/gap + for _pkg in ${_standardpkgs[@]}; do + cp -r pkg/$_pkg "$pkgdir"/usr/lib/gap/pkg + done + install -Dm755 gap -t "$pkgdir"/usr/lib/gap +# Install launcher script + install -Dm755 "$srcdir"/gap.sh "$pkgdir"/usr/bin/gap } package_gap-doc() { depends=(gap) + replaces=(gap-4.8-doc) pkgdesc="Documentation for GAP" cd gap-$pkgver @@ -70,6 +82,7 @@ package_gap-doc() { package_gap-packages() { depends=(gap) + replaces=(gap-4.8-packages) optdepends=('normaliz: Normaliz interface package' 'libxaw: xgap package' 'c-xsc: float package' 'mpfi: float package' 'libmpc: float package' 'fplll: float package' 'zeromq: ZeroMQ interface package' 'polymake: Polymake interface package' 'curl: curl interface package') @@ -80,7 +93,9 @@ package_gap-packages() { cp -r pkg "$pkgdir"/usr/lib/gap # provided by main gap package - rm -r "$pkgdir"/usr/lib/gap/pkg/{GAPDoc-*,primgrp-*,SmallGrp-*,transgrp} + for _pkg in ${_standardpkgs[@]}; do + rm -r "$pkgdir"/usr/lib/gap/pkg/$_pkg + done # fix RPATH if [[ $CARCH == "aarch64" ]]; then diff --git a/community/gap/gap-no-packages-by-default.patch b/community/gap/gap-no-packages-by-default.patch deleted file mode 100644 index 79b90bfa3..000000000 --- a/community/gap/gap-no-packages-by-default.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- gap4r8/lib/package.gi.orig 2016-11-25 18:59:02.234113245 +0000 -+++ gap4r8/lib/package.gi 2016-11-25 18:59:53.093996139 +0000 -@@ -1743,9 +1743,7 @@ - For backwards compatibility, the default lists most of packages \ - that were autoloaded in GAP 4.4 (add or remove packages as you like)." - ], -- default:= [ "autpgrp", "alnuth", "crisp", "ctbllib", "factint", "fga", -- "irredsol", "laguna", "polenta", "polycyclic", "resclasses", -- "sophus", "tomlib" ], -+ default:= [ ], - values:= function() return RecNames( GAPInfo.PackagesInfo ); end, - multi:= true, - ) ); diff --git a/community/gap/gap-sagemath-1.patch b/community/gap/gap-sagemath-1.patch new file mode 100644 index 000000000..be792715c --- /dev/null +++ b/community/gap/gap-sagemath-1.patch @@ -0,0 +1,74 @@ +From 163b8aae99b1b206e5ae85763e21f47b7651f9c4 Mon Sep 17 00:00:00 2001 +From: "Erik M. Bray" +Date: Tue, 4 Dec 2018 12:44:23 +0000 +Subject: [PATCH 1/3] a version of the writeandcheck.patch from Sage that works + against 4.10 + +--- + src/sysfiles.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/src/sysfiles.c b/src/sysfiles.c +index 2250784..45b4347 100644 +--- a/src/sysfiles.c ++++ b/src/sysfiles.c +@@ -159,21 +159,23 @@ SYS_SY_BUFFER syBuffers[32]; + /* utility to check return value of 'write' */ + ssize_t echoandcheck(int fid, const char *buf, size_t count) { + int ret; ++ static int depth = 0; ++ depth++; + if (syBuf[fid].type == gzip_socket) { + ret = gzwrite(syBuf[fid].gzfp, buf, count); +- if (ret < 0) ++ if (ret < 0 && depth == 1) + ErrorQuit( + "Could not write to compressed file, see 'LastSystemError();'\n", + 0L, 0L); + } + else { + ret = write(syBuf[fid].echo, buf, count); +- if (ret < 0) ++ if (ret < 0 && depth == 1) + ErrorQuit("Could not write to file descriptor %d, see " + "'LastSystemError();'\n", + syBuf[fid].fp, 0L); + } +- ++ depth--; + return ret; + } + +@@ -1636,21 +1638,27 @@ Int SyWrite(Int fid, const void * ptr, size_t len) + static ssize_t SyWriteandcheck(Int fid, const void * buf, size_t count) + { + int ret; ++ static int depth = 0; ++ depth++; + if (syBuf[fid].type == gzip_socket) { + ret = gzwrite(syBuf[fid].gzfp, buf, count); +- if (ret < 0) ++ if (ret < 0 && depth == 1) { + ErrorQuit( + "Cannot write to compressed file, see 'LastSystemError();'\n", + 0L, 0L); ++ } + } + else { + ret = write(syBuf[fid].fp, buf, count); +- if (ret < 0) ++ if (ret < 0 && depth == 1) { + ErrorQuit("Cannot write to file descriptor %d, see " + "'LastSystemError();'\n", + syBuf[fid].fp, 0L); ++ } + } + ++ depth--; ++ + return ret; + } + +-- +1.9.1 + diff --git a/community/gap/gap-sagemath-2.patch b/community/gap/gap-sagemath-2.patch new file mode 100644 index 000000000..31906e4eb --- /dev/null +++ b/community/gap/gap-sagemath-2.patch @@ -0,0 +1,122 @@ +From 0cecb79ff97c73a24acacf8afdc3edba93507661 Mon Sep 17 00:00:00 2001 +From: "Erik M. Bray" +Date: Thu, 22 Nov 2018 10:53:31 +0100 +Subject: [PATCH 2/3] kernel: add helper function for writing error messages to + the file/stream referenced by the ERROR_OUTPUT global variable + +--- + src/error.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + src/error.h | 8 ++++++++ + src/scanner.c | 3 ++- + 3 files changed, 52 insertions(+), 1 deletion(-) + +diff --git a/src/error.c b/src/error.c +index 9bb3be8..d43347d 100644 +--- a/src/error.c ++++ b/src/error.c +@@ -33,6 +33,8 @@ + + + static Obj ErrorInner; ++static Obj ERROR_OUTPUT = NULL; ++static Obj IsOutputStream; + + + /**************************************************************************** +@@ -40,6 +42,44 @@ static Obj ErrorInner; + *F * * * * * * * * * * * * * * error functions * * * * * * * * * * * * * * * + */ + ++/**************************************************************************** ++** ++*F OpenErrorOutput() . . . . . . . open the file or stream assigned to the ++** ERROR_OUTPUT global variable defined in ++** error.g, or "*errout*" otherwise ++*/ ++UInt OpenErrorOutput( void ) ++{ ++ /* Try to print the output to stream. Use *errout* as a fallback. */ ++ UInt ret = 0; ++ ++ if (ERROR_OUTPUT != NULL) { ++ if (IsStringConv(ERROR_OUTPUT)) { ++ ret = OpenOutput(CSTR_STRING(ERROR_OUTPUT)); ++ } ++ else { ++ if (CALL_1ARGS(IsOutputStream, ERROR_OUTPUT) == True) { ++ ret = OpenOutputStream(ERROR_OUTPUT); ++ } ++ } ++ } ++ ++ if (!ret) { ++ /* It may be we already tried and failed to open *errout* above but ++ * but this is an extreme case so it can't hurt to try again ++ * anyways */ ++ ret = OpenOutput("*errout*"); ++ if (ret) { ++ Pr("failed to open error stream\n", 0, 0); ++ } ++ else { ++ Panic("failed to open *errout*"); ++ } ++ } ++ ++ return ret; ++} ++ + + /**************************************************************************** + ** +@@ -615,6 +655,8 @@ static Int InitKernel(StructInitInfo * module) + InitHdlrFuncsFromTable(GVarFuncs); + + ImportFuncFromLibrary("ErrorInner", &ErrorInner); ++ ImportFuncFromLibrary("IsOutputStream", &IsOutputStream); ++ ImportGVarFromLibrary("ERROR_OUTPUT", &ERROR_OUTPUT); + + // return success + return 0; +diff --git a/src/error.h b/src/error.h +index 31af256..1f5ee5d 100644 +--- a/src/error.h ++++ b/src/error.h +@@ -32,6 +32,14 @@ Int RegisterBreakloopObserver(intfunc func); + + /**************************************************************************** + ** ++*F OpenErrorOutput() . . . . . . . open the file or stream assigned to the ++** ERROR_OUTPUT global variable defined in ++** error.g, or "*errout*" otherwise ++*/ ++extern UInt OpenErrorOutput(); ++ ++/**************************************************************************** ++** + *F ErrorQuit( , , ) . . . . . . . . . . . print and quit + */ + extern void ErrorQuit(const Char * msg, Int arg1, Int arg2) NORETURN; +diff --git a/src/scanner.c b/src/scanner.c +index 4db17b3..071c0e3 100644 +--- a/src/scanner.c ++++ b/src/scanner.c +@@ -16,6 +16,7 @@ + + #include "scanner.h" + ++#include "error.h" + #include "gapstate.h" + #include "gaputils.h" + #include "io.h" +@@ -42,7 +43,7 @@ static void SyntaxErrorOrWarning(const Char * msg, UInt error) + if (STATE(NrErrLine) == 0) { + + // open error output +- OpenOutput("*errout*"); ++ OpenErrorOutput(); + + // print the message ... + if (error) +-- +1.9.1 + diff --git a/community/gap/gap-sagemath-3.patch b/community/gap/gap-sagemath-3.patch new file mode 100644 index 000000000..4df46f5e3 --- /dev/null +++ b/community/gap/gap-sagemath-3.patch @@ -0,0 +1,269 @@ +From 798756448180195a6ce020565a5c1d160e491e98 Mon Sep 17 00:00:00 2001 +From: "Erik M. Bray" +Date: Thu, 6 Dec 2018 16:11:35 +0000 +Subject: [PATCH 3/3] Prototype for GAP_Enter/Leave macros to bracket use of + libgap and stack local GAP objects in code which embeds libgap + +There are two parts to this: + +First, the outer-most GAP_Enter() must set the StackBottom variable for GASMAN, +without which objects tracked by GASMAN that are allocated on the stack are +properly tracked (see #3089). + +Second, the outer-most GAP_Enter() call should set a jump point for longjmps to +STATE(ReadJmpError). Code within the GAP kernel may reset this, but we should +set it here in case any unexpected errors occur within the GAP kernel that are +not already handled appropriately by a TRY_IF_NO_ERROR. + +For the first issue, we add GAP_EnterStack() and GAP_LeaveStack() macros which +implement *just* the StackBottom handling without any other error handling. We +also add a function to gasman.c called _MarkStackBottomBags which just updates +the StackBottom variable. Then the macro called MarkStackBottomBags (same name +without underscore) can be used within a function to set StackBottom to +somewhere at or near the beginning of that function's stack frame. This uses +GCC's __builtin_frame_address, but supported is probably needed for other +platforms that don't have this. + +The state variable STATE(EnterStackCount) is used to track recursive calls into +GAP_EnterStack(). We only want to set StackBottom on the outer-most call. The +count is decremented on GAP_LeaveStack(). Some functions are provided for +manipulating the counter from the API without directly exposing the GAP state, +but I'm not sure if this is necessary or desirable, especially since it means +EnterStackCount isn't updated atomically. My hope was to avoid exposing too +many GAP internals, but it may be necessary in order to implement these as +macros. + +For setting the STATE(ReadJmpError) jump buffer we provide a macro called +GAP_Error_Setjmp() which is fairly straightforward, except that it needs to be +written in such a way that it can be used in concert correctly with +GAP_EnterStack(). In particular, if returning to the site of a +GAP_Error_Setjmp() call we do not want to accidentally re-increment the +EnterStackCount. + +Finally, the higher-level GAP_Enter() and GAP_Leave() macros are provided: The +latter is just an alias for GAP_LeaveStack(), but the former carefully combines +*both* GAP_Error_Setjmp() and GAP_EnterStack(). Although called like a +function, the GAP_Enter() macro expands to a compound statement (necessary for +both GAP_EnterStack() and GAP_Error_Setjmp() to work properly). The order of +expansion is also deliberate so that this can be used like: + + jmp_retval = GAP_Enter(); + +so that the return value of the setjmp call can be stored in a variable while +using GAP_Enter(), and can be checked to see whether an error occurred. +However, this requires some care to ensure that the following GAP_EnterStack() +doesn't increment the EnterStackCount following a return to this point via a +longjmp. + +Conflicts: + src/libgap-api.h +--- + src/gapstate.h | 3 ++ + src/gasman.c | 6 ++++ + src/gasman.h | 15 ++++++++++ + src/libgap-api.c | 27 +++++++++++++++++ + src/libgap-api.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 5 files changed, 137 insertions(+), 2 deletions(-) + +diff --git a/src/gapstate.h b/src/gapstate.h +index 72ec4c3..7a2a663 100644 +--- a/src/gapstate.h ++++ b/src/gapstate.h +@@ -97,6 +97,9 @@ typedef struct GAPState { + + UInt1 StateSlots[STATE_SLOTS_SIZE]; + ++ /* For libgap-api.c */ ++ Int EnterStackCount; ++ + /* Allocation */ + #if !defined(USE_GASMAN) + #define MAX_GC_PREFIX_DESC 4 +diff --git a/src/gasman.c b/src/gasman.c +index 13c0b1e..4d2ab3d 100644 +--- a/src/gasman.c ++++ b/src/gasman.c +@@ -1193,6 +1193,12 @@ void SetExtraMarkFuncBags(TNumExtraMarkFuncBags func) + } + + ++ ++void _MarkStackBottomBags(void* StackBottom) { ++ StackBottomBags = StackBottom; ++} ++ ++ + void InitBags ( + UInt initial_size, + Bag * stack_bottom, +diff --git a/src/gasman.h b/src/gasman.h +index 236eb8b..55e057a 100644 +--- a/src/gasman.h ++++ b/src/gasman.h +@@ -982,6 +982,21 @@ extern void InitCollectFuncBags ( + typedef void (*TNumExtraMarkFuncBags)(void); + extern void SetExtraMarkFuncBags(TNumExtraMarkFuncBags func); + ++ ++#ifdef __GNUC__ ++#define MarkStackBottomBags() \ ++ _MarkStackBottomBags(__builtin_frame_address(0)); ++/* ++#else ++ * TODO: Detect the best stack frame detection technique at configure time ++ * ++#define MarkStackBottomBags() \ ++ register void* rbp asm("rbp"); \ ++ _MarkStackBottomBags(rbp); ++*/ ++#endif ++extern void _MarkStackBottomBags(void* StackBottom); ++ + /**************************************************************************** + ** + *F InitBags(...) . . . . . . . . . . . . . . . . . . . . . initialize Gasman +diff --git a/src/libgap-api.c b/src/libgap-api.c +index 82cc441..e75b0e2 100644 +--- a/src/libgap-api.c ++++ b/src/libgap-api.c +@@ -10,6 +10,8 @@ + #include "lists.h" + #include "streams.h" + #include "stringobj.h" ++#include "system.h" ++ + + // + // Setup and initialisation +@@ -60,3 +62,28 @@ Obj GAP_EvalString(const char * cmd) + res = READ_ALL_COMMANDS(instream, False, True, viewObjFunc); + return res; + } ++ ++inline syJmp_buf * _GAP_GetReadJmpError(void) ++{ ++ return &(STATE(ReadJmpError)); ++} ++ ++inline Int _GAP_GetEnterStackCount(void) ++{ ++ return STATE(EnterStackCount); ++} ++ ++inline void _GAP_IncEnterStackCount(void) ++{ ++ STATE(EnterStackCount)++; ++} ++ ++inline void _GAP_DecEnterStackCount(void) ++{ ++ STATE(EnterStackCount)--; ++} ++ ++inline void _GAP_SetEnterStackCount(Int count) ++{ ++ STATE(EnterStackCount) = count; ++} +diff --git a/src/libgap-api.h b/src/libgap-api.h +index e45d6fc..55fcd05 100644 +--- a/src/libgap-api.h ++++ b/src/libgap-api.h +@@ -5,9 +5,93 @@ + + #include "gap.h" + +-typedef void (*CallbackFunc)(void); ++#ifdef __GNUC__ ++#define unlikely(x) __builtin_expect(!!(x), 0) ++#else ++#define unlikely(x) (x) ++#endif ++ ++ ++#ifndef GAP_ENTER_DEBUG ++#define GAP_ENTER_DEBUG 0 ++#endif ++ ++ ++extern syJmp_buf * _GAP_GetReadJmpError(void); ++extern Int _GAP_GetEnterStackCount(void); ++extern void _GAP_IncEnterStackCount(void); ++extern void _GAP_DecEnterStackCount(void); ++extern void _GAP_SetEnterStackCount(Int count); ++ ++ ++#if GAP_ENTER_DEBUG ++#define GAP_ENTER_DEBUG_MESSAGE(message, file, line) \ ++ fprintf(stderr, "%s: %d; %s:%d\n", message, _GAP_EnterStackCount, file, line); ++#else ++#define GAP_ENTER_DEBUG_MESSAGE(message, file, line) ++#endif ++ ++ ++#define GAP_EnterStack() \ ++ GAP_ENTER_DEBUG_MESSAGE("EnterStack", __FILE__, __LINE__); \ ++ Int _gap_tmp_enter_stack_count = _GAP_GetEnterStackCount(); \ ++ if (_gap_tmp_enter_stack_count < 0) { \ ++ _GAP_SetEnterStackCount(-_gap_tmp_enter_stack_count); \ ++ } else { \ ++ if (_gap_tmp_enter_stack_count == 0) { \ ++ MarkStackBottomBags(); \ ++ } \ ++ _GAP_IncEnterStackCount(); \ ++ } ++ + +-// Initialisation and finalization ++#define GAP_LeaveStack() \ ++ _GAP_DecEnterStackCount(); \ ++ GAP_ENTER_DEBUG_MESSAGE("LeaveStack", __FILE__, __LINE__); ++ ++ ++static inline int _GAP_Error_Prejmp(const char* file, int line) { ++#if GAP_ENTER_DEBUG ++ GAP_ENTER_DEBUG_MESSAGE("Error_Prejmp", file, line); ++#endif ++ if (_GAP_GetEnterStackCount() > 0) { ++ return 1; ++ } ++ return 0; ++} ++ ++ ++static inline int _GAP_Error_Postjmp(int JumpRet) ++{ ++ if (unlikely(JumpRet != 0)) { ++ /* This only should have been called from the outer-most ++ * GAP_EnterStack() call so make sure it resets the EnterStackCount; We ++ * set EnterStackCount to its negative which indicates to ++ * GAP_EnterStack that we just returned from a long jump and should ++ * reset EnterStackCount to its value at the return point rather than ++ * increment it again */ ++ Int tmp_count = _GAP_GetEnterStackCount(); ++ if (tmp_count > 0) { ++ _GAP_SetEnterStackCount(-tmp_count); ++ } ++ return 0; ++ } ++ ++ return 1; ++} ++ ++#define GAP_Error_Setjmp() (_GAP_Error_Prejmp(__FILE__, __LINE__) || \ ++ _GAP_Error_Postjmp(sySetjmp(*_GAP_GetReadJmpError()))) ++ ++ ++#define GAP_Enter() GAP_Error_Setjmp(); GAP_EnterStack() ++#define GAP_Leave() GAP_LeaveStack() ++ ++ ++//// ++//// Setup and initialisation ++//// ++typedef void (*CallbackFunc)(void); + + void GAP_Initialize(int argc, + char ** argv, +-- +1.9.1 + diff --git a/community/gap/gap.sh b/community/gap/gap.sh new file mode 100644 index 000000000..7b233e7a1 --- /dev/null +++ b/community/gap/gap.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +GAP_ROOT="/usr/lib/gap" +GAP_DIR=$GAP_ROOT +GAP_EXE=$GAP_ROOT + +exec "$GAP_EXE/gap" -l "$GAP_DIR" "$@"