From f857abdb719407b7fde55967aecfd4257dba6885 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 16 Feb 2025 23:04:39 +0100 Subject: [PATCH 01/12] kernel: clang-format and slightly refactor AddList3 code Replace one IS_PLIST check by a direct tnum comparison, split 2 and 3 argument variant implementation --- src/listfunc.c | 109 +++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/src/listfunc.c b/src/listfunc.c index c4b1818911..d4cd342ef6 100644 --- a/src/listfunc.c +++ b/src/listfunc.c @@ -44,86 +44,72 @@ */ static void AddList3(Obj list, Obj obj, Int pos) { - Int len; - Int i; + Int len; + Int i; len = LEN_LIST(list); - if (pos == (Int) -1) - pos = len + 1; - for (i = len +1; i > pos; i--) - ASS_LIST(list, i, ELM_LIST(list, i-1)); - ASS_LIST( list, pos, obj ); + if (pos == (Int)-1) + pos = len + 1; + for (i = len + 1; i > pos; i--) + ASS_LIST(list, i, ELM_LIST(list, i - 1)); + ASS_LIST(list, pos, obj); } -void AddList ( - Obj list, - Obj obj) +void AddList(Obj list, Obj obj) { - AddList3(list, obj, -1); + AddList3(list, obj, -1); } static void AddPlist3(Obj list, Obj obj, Int pos) { - UInt len; + UInt len; - if ( ! IS_PLIST_MUTABLE(list) ) { + if (!IS_PLIST_MUTABLE(list)) { ErrorMayQuit("List Assignment: must be a mutable list", 0, 0); } // in order to be optimistic when building list call assignment - len = LEN_PLIST( list ); + len = LEN_PLIST(list); if (pos == (Int)-1) - pos = len + 1; - if ( len == 0) { - AssPlistEmpty( list, pos, obj ); + pos = len + 1; + if (len == 0) { + AssPlistEmpty(list, pos, obj); return; } if (pos <= len) { - GROW_PLIST(list, len+1); - SET_LEN_PLIST(list, len+1); - Obj * ptr = ADDR_OBJ(list) + pos; - SyMemmove(ptr + 1, ptr, sizeof(Obj) * (len - pos + 1)); + GROW_PLIST(list, len + 1); + SET_LEN_PLIST(list, len + 1); + Obj * ptr = ADDR_OBJ(list) + pos; + SyMemmove(ptr + 1, ptr, sizeof(Obj) * (len - pos + 1)); } ASS_LIST(list, pos, obj); } -void AddPlist ( - Obj list, - Obj obj) +void AddPlist(Obj list, Obj obj) { - - AddPlist3(list, obj, -1); + AddPlist3(list, obj, -1); } static Obj AddListOper; static Obj FuncADD_LIST3(Obj self, Obj list, Obj obj, Obj pos) { - // dispatch - Int ipos; - if (pos == (Obj)0) - ipos = -1; - else if (IS_POS_INTOBJ(pos)) - ipos = INT_INTOBJ(pos); - else { - DoOperation3Args( self, list, obj, pos); - return (Obj) 0; - } - UInt tnum = TNUM_OBJ(list); - if ( IS_PLIST( list ) ) { - AddPlist3( list, obj, ipos ); - } else if ( FIRST_LIST_TNUM <= tnum && tnum <= LAST_LIST_TNUM ) { - AddList3( list, obj, ipos ); -#ifdef HPCGAP - // Only support adding to end of atomic lists - } else if ( tnum == T_ALIST && pos == (Obj)0 ) { - AddAList( list, obj ); -#endif - } else { - if (pos == 0) - DoOperation2Args( self, list, obj ); - else - DoOperation3Args( self, list, obj, pos); - } + if (!IS_POS_INTOBJ(pos)) { + DoOperation3Args(self, list, obj, pos); + return 0; + } + + UInt tnum = TNUM_OBJ(list); + if (FIRST_PLIST_TNUM <= tnum && tnum <= LAST_PLIST_TNUM) { + AddPlist3(list, obj, INT_INTOBJ(pos)); + return 0; + } + else if (FIRST_LIST_TNUM <= tnum && tnum <= LAST_LIST_TNUM) { + AddList3(list, obj, INT_INTOBJ(pos)); + return 0; + } + else { + DoOperation3Args(self, list, obj, pos); + } return 0; } @@ -131,8 +117,23 @@ static Obj FuncADD_LIST3(Obj self, Obj list, Obj obj, Obj pos) static Obj FuncADD_LIST(Obj self, Obj list, Obj obj) { - FuncADD_LIST3(self, list, obj, (Obj)0); - return (Obj) 0; + UInt tnum = TNUM_OBJ(list); + if (FIRST_PLIST_TNUM <= tnum && tnum <= LAST_PLIST_TNUM) { + AddPlist3(list, obj, -1); + } + else if (FIRST_LIST_TNUM <= tnum && tnum <= LAST_LIST_TNUM) { + AddList3(list, obj, -1); + } +#ifdef HPCGAP + else if (tnum == T_ALIST) { + AddAList(list, obj); + } +#endif + else { + DoOperation2Args(self, list, obj); + } + + return 0; } From 5c6105553c62d32932dab9de15f735ad51d4e33f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Feb 2025 09:18:24 +0100 Subject: [PATCH 02/12] kernel: export AddPlist3 --- src/listfunc.c | 2 +- src/listfunc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/listfunc.c b/src/listfunc.c index d4cd342ef6..5da324d25a 100644 --- a/src/listfunc.c +++ b/src/listfunc.c @@ -60,7 +60,7 @@ void AddList(Obj list, Obj obj) } -static void AddPlist3(Obj list, Obj obj, Int pos) +void AddPlist3(Obj list, Obj obj, Int pos) { UInt len; diff --git a/src/listfunc.h b/src/listfunc.h index 9bc7a598bc..b1609b4724 100644 --- a/src/listfunc.h +++ b/src/listfunc.h @@ -28,6 +28,7 @@ void AddList(Obj list, Obj obj); void AddPlist(Obj list, Obj obj); +void AddPlist3(Obj list, Obj obj, Int pos); /**************************************************************************** ** From e8263425ce59b692cba68e58d2293f44bf59a659 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Feb 2025 09:25:22 +0100 Subject: [PATCH 03/12] kernel: let SyFindGapRootFile return a string obj --- src/streams.c | 10 ++++------ src/sysroots.c | 24 ++++++++++-------------- src/sysroots.h | 12 +++++------- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/streams.c b/src/streams.c index 1a45a105ef..cb531ae11e 100644 --- a/src/streams.c +++ b/src/streams.c @@ -358,10 +358,8 @@ Obj READ_AS_FUNC(TypInputFile * input) */ Int READ_GAP_ROOT ( const Char * filename ) { - char path[GAP_PATH_MAX]; - // try to find the GAP file - SyFindGapRootFile(filename, path, sizeof(path)); + Obj path = SyFindGapRootFile(filename); // try to find compiled version of the GAP file if (SyUseModule) { @@ -378,7 +376,7 @@ Int READ_GAP_ROOT ( const Char * filename ) if (info) { // found a matching statically linked module; if there is also // a GAP file, compare their CRC - if (*path && info->crc != SyGAPCRC(path)) { + if (path && info->crc != SyGAPCRC(CSTR_STRING(path))) { Pr("#W Static module %s has CRC mismatch, ignoring\n", (Int)filename, 0); } @@ -395,7 +393,7 @@ Int READ_GAP_ROOT ( const Char * filename ) } // not found? - if (*path == 0) + if (path == 0) return 0; #ifdef GAP_ENABLE_SAVELOAD @@ -415,7 +413,7 @@ Int READ_GAP_ROOT ( const Char * filename ) } TypInputFile input; - if (!OpenInput(&input, path)) + if (!OpenInput(&input, CSTR_STRING(path))) return 0; GAP_TRY diff --git a/src/sysroots.c b/src/sysroots.c index 42e4e42fe9..5a4bf55b21 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -43,28 +43,24 @@ static Char SyGapRootPaths[MAX_GAP_DIRS][GAP_PATH_MAX]; /**************************************************************************** ** -*F SyFindGapRootFile( , , ) . find file in system area +*F SyFindGapRootFile( ) . . . . . . . . find file in system area ** -** must point to a buffer of at least characters. This function -** then searches for a readable file with the name in the system -** area. If sich a file is found then its absolute path is copied into -** , and is returned. If no file is found or if is not big -** enough, then is set to an empty string and NULL is returned. +** This function searches for a readable file with the name in +** the system area. If such a file is found then its absolute path is +** returned as a string object. If no file is found then NULL is returned. */ -Char * SyFindGapRootFile(const Char * filename, Char * buf, size_t size) +Obj SyFindGapRootFile(const Char * filename) { + int len = strlen(filename); for (int k = 0; k < ARRAY_SIZE(SyGapRootPaths); k++) { if (SyGapRootPaths[k][0]) { - if (gap_strlcpy(buf, SyGapRootPaths[k], size) >= size) - continue; - if (gap_strlcat(buf, filename, size) >= size) - continue; - if (SyIsReadableFile(buf) == 0) { - return buf; + Obj path = MakeString(SyGapRootPaths[k]); + AppendCStr(path, filename, len); + if (SyIsReadableFile(CSTR_STRING(path)) == 0) { + return path; } } } - buf[0] = '\0'; return 0; } diff --git a/src/sysroots.h b/src/sysroots.h index ae7341ce94..a73a17bbca 100644 --- a/src/sysroots.h +++ b/src/sysroots.h @@ -34,15 +34,13 @@ void SySetGapRootPath(const Char * string); /**************************************************************************** ** -*F SyFindGapRootFile( , , ) . find file in system area +*F SyFindGapRootFile( ) . . . . . . . . find file in system area ** -** must point to a buffer of at least characters. This function -** then searches for a readable file with the name in the system -** area. If sich a file is found then its absolute path is copied into -** , and is returned. If no file is found or if is not big -** enough, then is set to an empty string and NULL is returned. +** This function searches for a readable file with the name in +** the system area. If such a file is found then its absolute path is +** returned as a string object. If no file is found then NULL is returned. */ -Char * SyFindGapRootFile(const Char * filename, Char * buf, size_t size); +Obj SyFindGapRootFile(const Char * filename); /**************************************************************************** From 26738d000d4cd9db5ebc52f85424013739484753 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Feb 2025 23:07:57 +0100 Subject: [PATCH 04/12] kernel: pass stackBottom explicitly to init functions --- src/gap.c | 13 +++++-------- src/gap.h | 4 ++-- src/libgap-api.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/gap.c b/src/gap.c index d40660e89d..129bb9f2a9 100644 --- a/src/gap.c +++ b/src/gap.c @@ -405,7 +405,7 @@ int realmain(int argc, const char * argv[]) Int4 crc; // crc of file to compile // initialize everything and read init.g which runs the GAP session - InitializeGap(&argc, argv, 1); + InitializeGap(&argc, argc, argv, 1); if (!STATE(UserHasQUIT)) { /* maybe the user QUIT from the initial read of init.g somehow*/ // maybe compile in which case init.g got skipped @@ -1452,21 +1452,18 @@ StructInitInfo * InitInfoGap ( void ) ** function. We use the resulting pointer as a hint to the garbage collector ** as to where the execution stack (might) start. */ -void InitializeGap(int * pargc, const char * argv[], BOOL handleSignals) +void InitializeGap(void * stackBottom, int argc, const char * argv[], BOOL handleSignals) { - const int argc = *pargc; - // initialize the basic system and gasman InitSystem(argc, argv, handleSignals); // Initialise memory -- have to do this here to make sure we are at top of C stack - InitBags( + Bag * alignedStackBottom = (Bag *)(((UInt)stackBottom / C_STACK_ALIGN) * C_STACK_ALIGN); #if defined(USE_GASMAN) - SyStorMin, + InitBags(SyStorMin, alignedStackBottom); #else - 0, + InitBags(0, alignedStackBottom); #endif - (Bag *)(((UInt)pargc / C_STACK_ALIGN) * C_STACK_ALIGN)); STATE(UserHasQUIT) = FALSE; STATE(UserHasQuit) = FALSE; diff --git a/src/gap.h b/src/gap.h index b3bab8df92..ff01637abc 100644 --- a/src/gap.h +++ b/src/gap.h @@ -83,9 +83,9 @@ BOOL IsUsingLibGap(void); /**************************************************************************** ** -*F InitializeGap( , , ) . . . . . . . init GAP +*F InitializeGap() . . . . . . . . . . . . . . . . . . . . . initialize GAP */ -void InitializeGap(int * pargc, const char * argv[], BOOL handleSignals); +void InitializeGap(void * stackBottom, int argc, const char * argv[], BOOL handleSignals); /**************************************************************************** diff --git a/src/libgap-api.c b/src/libgap-api.c index becc8858f0..55b5764099 100644 --- a/src/libgap-api.c +++ b/src/libgap-api.c @@ -59,7 +59,7 @@ void GAP_Initialize(int argc, { UsingLibGap = TRUE; - InitializeGap(&argc, (const char **)argv, handleSignals); + InitializeGap(&argc, argc, (const char **)argv, handleSignals); SetExtraMarkFuncBags(markBagsCallback); STATE(JumpToCatchCallback) = errorCallback; From 2c47319c0d840fa14f28350acbf425f923ccdcb3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 5 Jan 2025 22:34:02 +0100 Subject: [PATCH 05/12] kernel: split CLI arg parsing into two stages Most arguments are handled in the first stage. In particular all that are relevant for the GC. The second stage is only for the arguments which add GAP roots paths: those involve storing strings, which can be of arbitrary size. We'd like to switch their handling from C strings to GAP strings, but that requires the memory manager to be initialized. With this patch, it *is* initialized before we parse the root paths. --- src/gap.c | 2 ++ src/system.c | 84 +++++++++++++++++++++++++++++----------------------- src/system.h | 4 +++ 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/gap.c b/src/gap.c index 129bb9f2a9..b98438b841 100644 --- a/src/gap.c +++ b/src/gap.c @@ -1475,6 +1475,8 @@ void InitializeGap(void * stackBottom, int argc, const char * argv[], BOOL handl // call kernel initialisation ModulesInitKernel(); + InitRootPaths(argc, argv); + #ifdef HPCGAP InitMainThread(); #endif diff --git a/src/system.c b/src/system.c index df3d1ef1e3..eb28e2d09d 100644 --- a/src/system.c +++ b/src/system.c @@ -360,11 +360,12 @@ static void usage(void) } struct optInfo { - Char shortkey; - Char longkey[50]; - int (*handler)(const char * argv[], void *); - void *otherArg; - UInt minargs; + int phase; + char shortkey; + char longkey[50]; + int (*handler)(const char * argv[], void *); + void *otherArg; + UInt minargs; }; @@ -486,48 +487,48 @@ static int printVersion(const char * argv[], void * dummy) // These options must be kept in sync with those in system.g, so the help // output is correct static const struct optInfo options[] = { - { 'C', "", processCompilerArgs, 0, 4}, // must handle in kernel - { 'D', "debug-loading", toggle, &SyDebugLoading, 0}, // must handle in kernel + { 0, 'C', "", processCompilerArgs, 0, 4}, // must handle in kernel + { 0, 'D', "debug-loading", toggle, &SyDebugLoading, 0}, // must handle in kernel #if defined(USE_GASMAN) || defined(USE_BOEHM_GC) - { 'K', "maximal-workspace", storeMemory2, &SyStorKill, 1}, // could handle from library with new interface + { 0, 'K', "maximal-workspace", storeMemory2, &SyStorKill, 1}, // could handle from library with new interface #endif #ifdef GAP_ENABLE_SAVELOAD - { 'L', "", storeString, &SyRestoring, 1}, // must be handled in kernel - { 'R', "", unsetString, &SyRestoring, 0}, // kernel + { 0, 'L', "", storeString, &SyRestoring, 1}, // must be handled in kernel + { 0, 'R', "", unsetString, &SyRestoring, 0}, // kernel #endif - { 'M', "", toggle, &SyUseModule, 0}, // must be handled in kernel - { 'e', "", toggle, &SyCTRD, 0 }, // kernel - { 'f', "", forceLineEditing, (void *)2, 0 }, // probably library now - { 'E', "", toggle, &SyUseReadline, 0 }, // kernel - { 'l', "roots", setGapRootPath, 0, 1}, // kernel + { 0, 'M', "", toggle, &SyUseModule, 0}, // must be handled in kernel + { 0, 'e', "", toggle, &SyCTRD, 0 }, // kernel + { 0, 'f', "", forceLineEditing, (void *)2, 0 }, // probably library now + { 0, 'E', "", toggle, &SyUseReadline, 0 }, // kernel + { 1, 'l', "roots", setGapRootPath, 0, 1}, // kernel #ifdef USE_GASMAN - { 'm', "", storeMemory2, &SyStorMin, 1 }, // kernel + { 0, 'm', "", storeMemory2, &SyStorMin, 1 }, // kernel #endif - { 'r', "", toggle, &IgnoreGapRC, 0 }, // kernel + { 0, 'r', "", toggle, &IgnoreGapRC, 0 }, // kernel #ifdef USE_GASMAN - { 's', "", storeMemory, &SyAllocPool, 1 }, // kernel + { 0, 's', "", storeMemory, &SyAllocPool, 1 }, // kernel #endif - { 'n', "", forceLineEditing, 0, 0}, // prob library + { 0, 'n', "", forceLineEditing, 0, 0}, // prob library #ifdef USE_GASMAN - { 'o', "", storeMemory2, &SyStorMax, 1 }, // library with new interface + { 0, 'o', "", storeMemory2, &SyStorMax, 1 }, // library with new interface #endif - { 'p', "", toggle, &SyWindow, 0 }, // ?? - { 'q', "quiet", toggle, &SyQuiet, 0 }, // ?? + { 0, 'p', "", toggle, &SyWindow, 0 }, // ?? + { 0, 'q', "quiet", toggle, &SyQuiet, 0 }, // ?? #ifdef HPCGAP - { 'S', "", toggle, &ThreadUI, 0 }, // Thread UI - { 'Z', "", toggle, &DeadlockCheck, 0 }, // Deadlock prevention - { 'P', "", storePosInteger, &SyNumProcessors, 1 }, // number of CPUs - { 'G', "", storePosInteger, &SyNumGCThreads, 1 }, // number of GC threads - { 0 , "single-thread", toggle, &SingleThreadStartup, 0 }, // startup with one thread only + { 0, 'S', "", toggle, &ThreadUI, 0 }, // Thread UI + { 0, 'Z', "", toggle, &DeadlockCheck, 0 }, // Deadlock prevention + { 0, 'P', "", storePosInteger, &SyNumProcessors, 1 }, // number of CPUs + { 0, 'G', "", storePosInteger, &SyNumGCThreads, 1 }, // number of GC threads + { 0, 0 , "single-thread", toggle, &SingleThreadStartup, 0 }, // startup with one thread only #endif // The following options must be handled in the kernel so they are set up before loading the library - { 0 , "prof", enableProfilingAtStartup, 0, 1}, // enable profiling at startup - { 0 , "memprof", enableMemoryProfilingAtStartup, 0, 1 }, // enable memory profiling at startup - { 0 , "cover", enableCodeCoverageAtStartup, 0, 1}, // enable code coverage at startup - { 0 , "quitonbreak", toggle, &SyQuitOnBreak, 0}, // Quit GAP if we enter the break loop - { 0 , "enableMemCheck", enableMemCheck, 0, 0 }, - { 0 , "version", printVersion, 0, 0 }, - { 0, "", 0, 0, 0}}; + { 0, 0 , "prof", enableProfilingAtStartup, 0, 1}, // enable profiling at startup + { 0, 0 , "memprof", enableMemoryProfilingAtStartup, 0, 1 }, // enable memory profiling at startup + { 0, 0 , "cover", enableCodeCoverageAtStartup, 0, 1}, // enable code coverage at startup + { 0, 0 , "quitonbreak", toggle, &SyQuitOnBreak, 0}, // Quit GAP if we enter the break loop + { 0, 0 , "enableMemCheck", enableMemCheck, 0, 0 }, + { 0, 0 , "version", printVersion, 0, 0 }, + { 0, 0, "", 0, 0, 0}}; static void InitSysOpts(void) @@ -579,7 +580,7 @@ static void InitSysOpts(void) SyWindow = 0; } -static void ParseCommandLineOptions(int argc, const char * argv[]) +static void ParseCommandLineOptions(int argc, const char * argv[], int phase) { // scan the command line for options that we have to process in the kernel // we just scan the whole command line looking for the keys for the @@ -637,7 +638,8 @@ static void ParseCommandLineOptions(int argc, const char * argv[]) usage(); } - (*options[i].handler)(argv + 1, options[i].otherArg); + if (options[i].phase == phase) + (*options[i].handler)(argv + 1, options[i].otherArg); argv += options[i].minargs; argc -= options[i].minargs; @@ -687,7 +689,9 @@ void InitSystem(int argc, const char * argv[], BOOL handleSignals) InitSysFiles(); - ParseCommandLineOptions(argc, argv); + // first stage of command line options parsing: handle everything except + // for root paths + ParseCommandLineOptions(argc, argv, 0); #ifdef HAVE_LIBREADLINE InitReadline(); @@ -702,6 +706,12 @@ void InitSystem(int argc, const char * argv[], BOOL handleSignals) SyRedirectStderrToStdOut(); syWinPut(0, "@p", "1."); } +} + +void InitRootPaths(int argc, const char * argv[]) +{ + // second stage of command line options parsing: handle root paths + ParseCommandLineOptions(argc, argv, 1); InitDotGapPath(); } diff --git a/src/system.h b/src/system.h index c530d7c4ea..cbdab82dbb 100644 --- a/src/system.h +++ b/src/system.h @@ -136,4 +136,8 @@ void Panic_(const char * file, int line, const char * fmt, ...) NORETURN */ void InitSystem(int argc, const char * argv[], BOOL handleSignals); + +void InitRootPaths(int argc, const char * argv[]); + + #endif // GAP_SYSTEM_H From 7b8a5edb6dbc501acba1b8f8e890172f533038f6 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Feb 2025 22:31:17 +0100 Subject: [PATCH 06/12] kernel: add SyDefaultRootPath --- src/main.c | 9 ++------- src/sysroots.c | 10 ++++++++++ src/sysroots.h | 11 +++++++++++ src/system.c | 2 ++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index 39457f5f3d..69d5e3dd95 100644 --- a/src/main.c +++ b/src/main.c @@ -41,7 +41,7 @@ extern int realmain(int argc, const char * argv[]); static void SetupInitialGapRoot(const char * argv0) { - SySetGapRootPath(SYS_DEFAULT_PATHS); + gap_strlcpy(SyDefaultRootPath, SYS_DEFAULT_PATHS, sizeof(SyDefaultRootPath)); } #else @@ -165,7 +165,7 @@ static void SySetInitialGapRootPaths(const char * GAPExecLocation) strxcat(initgbuf, "lib/init.g", sizeof(initgbuf)); if (SyIsReadableFile(initgbuf) == 0) { - SySetGapRootPath(pathbuf); + gap_strlcpy(SyDefaultRootPath, pathbuf, sizeof(SyDefaultRootPath)); // escape from loop return; } @@ -173,11 +173,6 @@ static void SySetInitialGapRootPaths(const char * GAPExecLocation) strxcat(pathbuf, "../", sizeof(pathbuf)); } } - - // Set GAP root path to current directory, if we have no other - // idea, and for backwards compatibility. - // Note that GAPExecLocation must always end with a slash. - SySetGapRootPath("./"); } static void SetupInitialGapRoot(const char * argv0) diff --git a/src/sysroots.c b/src/sysroots.c index 5a4bf55b21..ca8fe8eba7 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -21,6 +21,16 @@ #include +/**************************************************************************** +** +*V SyDefaultRootPath +** +** Default initial root path. Default is the current directory, if we have +** no other idea, for backwards compatibility. +*/ +char SyDefaultRootPath[GAP_PATH_MAX] = "./"; + + /**************************************************************************** ** *V SyGapRootPaths . . . . . . . . . . . . . . . . . . . array of root paths diff --git a/src/sysroots.h b/src/sysroots.h index a73a17bbca..4d12129a7d 100644 --- a/src/sysroots.h +++ b/src/sysroots.h @@ -13,6 +13,17 @@ #define GAP_SYSROOTS_H #include "common.h" +#include "system.h" + + +/**************************************************************************** +** +*V SyDefaultRootPath +** +** Default initial root path. Default is the current directory, if we have +** no other idea, for backwards compatibility. +*/ +extern char SyDefaultRootPath[GAP_PATH_MAX]; #include diff --git a/src/system.c b/src/system.c index eb28e2d09d..a68cf41df5 100644 --- a/src/system.c +++ b/src/system.c @@ -713,5 +713,7 @@ void InitRootPaths(int argc, const char * argv[]) // second stage of command line options parsing: handle root paths ParseCommandLineOptions(argc, argv, 1); + SySetGapRootPath(SyDefaultRootPath); + InitDotGapPath(); } From b9b18fbad93c7f888f556602b85900d501fa9095 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 14 Feb 2025 09:38:37 +0100 Subject: [PATCH 07/12] WIP --- src/gap.c | 2 + src/sysroots.c | 153 +++++++++++++++++++++---------------------------- src/sysroots.h | 19 +++++- 3 files changed, 84 insertions(+), 90 deletions(-) diff --git a/src/gap.c b/src/gap.c index b98438b841..03c4dbee16 100644 --- a/src/gap.c +++ b/src/gap.c @@ -1335,6 +1335,8 @@ static Int InitKernel ( InitGlobalBag( &WindowCmdString, "src/gap.c:WindowCmdString" ); InitGlobalBag( &KernelArgs, "src/gap.c:KernelArgs" ); + InitGlobalBag( &SyGapRootPaths, "src/gap.c:SyGapRootPaths" ); // FIXME + // init filters and functions InitHdlrFuncsFromTable( GVarFuncs ); diff --git a/src/sysroots.c b/src/sysroots.c index ca8fe8eba7..7d301477c1 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -12,6 +12,7 @@ #include "sysroots.h" #include "gaputils.h" +#include "listfunc.h" #include "plist.h" #include "stringobj.h" #include "sysfiles.h" @@ -47,8 +48,7 @@ char SyDefaultRootPath[GAP_PATH_MAX] = "./"; ** name of a library file 'strcat( SyGapRootPaths[i], "lib/init.g" );' must ** be a valid filename. */ -enum { MAX_GAP_DIRS = 16 }; -static Char SyGapRootPaths[MAX_GAP_DIRS][GAP_PATH_MAX]; +Obj SyGapRootPaths; /**************************************************************************** @@ -62,13 +62,12 @@ static Char SyGapRootPaths[MAX_GAP_DIRS][GAP_PATH_MAX]; Obj SyFindGapRootFile(const Char * filename) { int len = strlen(filename); - for (int k = 0; k < ARRAY_SIZE(SyGapRootPaths); k++) { - if (SyGapRootPaths[k][0]) { - Obj path = MakeString(SyGapRootPaths[k]); - AppendCStr(path, filename, len); - if (SyIsReadableFile(CSTR_STRING(path)) == 0) { - return path; - } + int npaths = LEN_PLIST(SyGapRootPaths); + for (int k = 1; k <= npaths; k++) { + Obj path = ELM_PLIST(SyGapRootPaths, k); + AppendCStr(path, filename, len); + if (SyIsReadableFile(CSTR_STRING(path)) == 0) { + return path; } } return 0; @@ -95,10 +94,13 @@ Obj SyFindGapRootFile(const Char * filename) */ void SySetGapRootPath(const Char * string) { - const Char * p; - Char * q; - Int i; - Int n; + Int pos; + Int pos = 1; + + if (SyGapRootPaths == 0) { + SyGapRootPaths = NEW_PLIST(T_PLIST_EMPTY, 0); // FIXME + } + // set string to a default value if unset if (string == 0 || *string == 0) { @@ -107,94 +109,73 @@ void SySetGapRootPath(const Char * string) // check if we append, prepend or overwrite. if (string[0] == ';') { - // Count the number of root directories already present. - n = 0; - while (SyGapRootPaths[n][0] != '\0') - n++; + // append + pos = LEN_PLIST(SyGapRootPaths) + 1; // Skip leading semicolon. string++; } else if (string[strlen(string) - 1] == ';') { - // Count the number of directories in 'string'. - n = 0; - p = string; - while (*p) - if (*p++ == ';') - n++; - - // Find last root path. - for (i = 0; i < MAX_GAP_DIRS; i++) - if (SyGapRootPaths[i][0] == '\0') - break; - i--; - -#ifdef HPCGAP - n *= 2; // for each root we also add as a root -#endif - - // Move existing root paths to the back - if (i + n >= MAX_GAP_DIRS) - return; - while (i >= 0) { - memcpy(SyGapRootPaths[i + n], SyGapRootPaths[i], - sizeof(SyGapRootPaths[i + n])); - i--; - } - - n = 0; + // prepend } else { - // Make sure to wipe out all possibly existing root paths - for (i = 0; i < MAX_GAP_DIRS; i++) - SyGapRootPaths[i][0] = '\0'; - n = 0; + SET_LEN_PLIST(SyGapRootPaths, 0); + RetypeBagSM(SyGapRootPaths, T_PLIST_EMPTY); + // TODO: also adjust filters... } // unpack the argument - p = string; + const Char * p = string; while (*p) { - if (n >= MAX_GAP_DIRS) - return; - - q = SyGapRootPaths[n]; - while (*p && *p != ';') { - *q = *p++; - -#ifdef SYS_IS_CYGWIN32 - // change backslash to slash for Windows - if (*q == '\\') - *q = '/'; -#endif + Obj path; + // locate next semicolon or string end + const Char * q = p; + while (*q && *q != ';') { q++; } - if (q == SyGapRootPaths[n]) { - strxcpy(SyGapRootPaths[n], "./", sizeof(SyGapRootPaths[n])); - } - else if (q[-1] != '/') { - *q++ = '/'; - *q = '\0'; - } - else { - *q = '\0'; - } - if (*p) { - p++; + + if (q == p) { + // empty string treated as ./ + path = MakeString("./"); + } else { + path = MakeStringWithLen(p, q - p); + + Char * r = CSTR_STRING(path); + #ifdef SYS_IS_CYGWIN32 + while (*r) { + // change backslash to slash for Windows + if (*r == '\\') + *r = '/'; + r++; + } + #endif + + // ensure path ends with a slash + r = CSTR_STRING(path) + GET_LEN_STRING(path) - 1; + if (*r != '/') { + AppendCStr(path, "/", 1); + } } - n++; + + p = *q ? q + 1 : q; + + AddPlist3(SyGapRootPaths, path, pos); + pos++; + #ifdef HPCGAP // for each root to be added, we first add as a root - if (n < MAX_GAP_DIRS) { - gap_strlcpy(SyGapRootPaths[n], SyGapRootPaths[n - 1], - sizeof(SyGapRootPaths[n])); - } - strxcat(SyGapRootPaths[n - 1], "hpcgap/", - sizeof(SyGapRootPaths[n - 1])); - n++; + path = CopyToStringRep(path); + AppendCStr(path, "hpcgap/", 7); + + AddPlist3(SyGapRootPaths, path, pos); + pos++; #endif } +#if 0 +// TODO: add this code back in + // replace leading tilde ~ by HOME environment variable // TODO; instead of iterating over all entries each time, just // do this for the new entries @@ -212,6 +193,7 @@ void SySetGapRootPath(const Char * string) memcpy(SyGapRootPaths[i], userhome, userhomelen); } } +#endif } @@ -221,12 +203,5 @@ void SySetGapRootPath(const Char * string) */ Obj SyGetGapRootPaths(void) { - Obj tmp = NEW_PLIST_IMM(T_PLIST, MAX_GAP_DIRS); - for (int i = 0; i < MAX_GAP_DIRS; i++) { - if (SyGapRootPaths[i][0]) { - PushPlist(tmp, MakeImmString(SyGapRootPaths[i])); - } - } - MakeImmutableNoRecurse(tmp); - return tmp; + return SyGapRootPaths; } diff --git a/src/sysroots.h b/src/sysroots.h index 4d12129a7d..136c0517cf 100644 --- a/src/sysroots.h +++ b/src/sysroots.h @@ -25,7 +25,24 @@ */ extern char SyDefaultRootPath[GAP_PATH_MAX]; -#include + +/**************************************************************************** +** +*V SyGapRootPaths . . . . . . . . . . . . . . . . . . . array of root paths +** +** 'SyGapRootPaths' contains the names of the directories where the GAP +** files are located. +** +** It is modified by the command line option -l. +** +** It is copied into the GAP variable 'GAPInfo.RootPaths' and used by +** 'SyFindGapRootFile'. +** +** Each entry must end with the pathname separator, e.g. if 'init.g' is the +** name of a library file 'strcat( SyGapRootPaths[i], "lib/init.g" );' must +** be a valid filename. +*/ +extern Obj SyGapRootPaths; /**************************************************************************** From 170c996380d8ab974295ddc9de29076a123e2da0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 18 Feb 2025 13:16:04 +0100 Subject: [PATCH 08/12] oops --- src/sysroots.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sysroots.c b/src/sysroots.c index 7d301477c1..fd7d87042f 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -94,7 +94,6 @@ Obj SyFindGapRootFile(const Char * filename) */ void SySetGapRootPath(const Char * string) { - Int pos; Int pos = 1; if (SyGapRootPaths == 0) { From 63c70b8916bd694cb0d288307621e1f96d8eb4ef Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 18 Feb 2025 23:28:16 +0100 Subject: [PATCH 09/12] WIP --- lib/package.gi | 26 +++++++++++++------------- src/sysroots.c | 1 + 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/package.gi b/lib/package.gi index ba0612a535..54ca1984d8 100644 --- a/lib/package.gi +++ b/lib/package.gi @@ -1862,19 +1862,19 @@ InstallGlobalFunction( SetPackagePath, function( pkgname, pkgpath ) #F ExtendRootDirectories( ) ## InstallGlobalFunction( ExtendRootDirectories, function( rootpaths ) - local i; - - rootpaths:= Filtered( rootpaths, path -> not path in GAPInfo.RootPaths ); - if not IsEmpty( rootpaths ) then - # 'DirectoriesLibrary' concatenates root paths with directory names. - for i in [ 1 .. Length( rootpaths ) ] do - if not EndsWith( rootpaths[i], "/" ) then - rootpaths[i]:= Concatenation( rootpaths[i], "/" ); - fi; - od; - # Append the new root paths. - GAPInfo.RootPaths:= Immutable( Concatenation( GAPInfo.RootPaths, - rootpaths ) ); + local path, changed; + + changed:= false; + for path in rootpaths do + if not EndsWith( path, "/" ) then + path:= Concatenation( path, "/" ); + fi; + if not path in GAPInfo.RootPaths then + Add( GAPInfo.RootPaths, path ); + changed:= true; + fi; + od; + if changed then # Clear the cache. GAPInfo.DirectoriesLibrary:= AtomicRecord( rec() ); # Reread the package information. diff --git a/src/sysroots.c b/src/sysroots.c index fd7d87042f..387e0907b7 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -137,6 +137,7 @@ void SySetGapRootPath(const Char * string) if (q == p) { // empty string treated as ./ path = MakeString("./"); + // TODO: insert output of getcwd?? } else { path = MakeStringWithLen(p, q - p); From 7d50d490a216a43dc9c3764c52bea3c96080eda2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 18 Feb 2025 23:47:59 +0100 Subject: [PATCH 10/12] oops again --- src/sysroots.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sysroots.c b/src/sysroots.c index 387e0907b7..ab8d669763 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -64,7 +64,7 @@ Obj SyFindGapRootFile(const Char * filename) int len = strlen(filename); int npaths = LEN_PLIST(SyGapRootPaths); for (int k = 1; k <= npaths; k++) { - Obj path = ELM_PLIST(SyGapRootPaths, k); + Obj path = CopyToStringRep(ELM_PLIST(SyGapRootPaths, k)); AppendCStr(path, filename, len); if (SyIsReadableFile(CSTR_STRING(path)) == 0) { return path; From 0b831fc909dc950be04f489f6e50637036976e63 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 19 Feb 2025 00:06:17 +0100 Subject: [PATCH 11/12] fixup! kernel: add SyDefaultRootPath --- src/system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system.c b/src/system.c index a68cf41df5..c84653caed 100644 --- a/src/system.c +++ b/src/system.c @@ -710,10 +710,10 @@ void InitSystem(int argc, const char * argv[], BOOL handleSignals) void InitRootPaths(int argc, const char * argv[]) { + SySetGapRootPath(SyDefaultRootPath); + // second stage of command line options parsing: handle root paths ParseCommandLineOptions(argc, argv, 1); - SySetGapRootPath(SyDefaultRootPath); - InitDotGapPath(); } From 063917fbb02718c0f82fcf872d7019f825480be8 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 19 Feb 2025 00:07:06 +0100 Subject: [PATCH 12/12] WIP: implement tilde expansion --- src/sysroots.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/sysroots.c b/src/sysroots.c index ab8d669763..e12a656246 100644 --- a/src/sysroots.c +++ b/src/sysroots.c @@ -139,7 +139,17 @@ void SySetGapRootPath(const Char * string) path = MakeString("./"); // TODO: insert output of getcwd?? } else { - path = MakeStringWithLen(p, q - p); + if (*p == '~') { + const char * userhome = getenv("HOME"); + if (!userhome) + userhome = ""; + path = MakeString(userhome); + p++; + AppendCStr(path, p, q - p); + } + else { + path = MakeStringWithLen(p, q - p); + } Char * r = CSTR_STRING(path); #ifdef SYS_IS_CYGWIN32 @@ -172,28 +182,6 @@ void SySetGapRootPath(const Char * string) pos++; #endif } - -#if 0 -// TODO: add this code back in - - // replace leading tilde ~ by HOME environment variable - // TODO; instead of iterating over all entries each time, just - // do this for the new entries - char * userhome = getenv("HOME"); - if (!userhome || !*userhome) - return; - const UInt userhomelen = strlen(userhome); - for (i = 0; i < MAX_GAP_DIRS && SyGapRootPaths[i][0]; i++) { - const UInt pathlen = strlen(SyGapRootPaths[i]); - if (SyGapRootPaths[i][0] == '~' && - userhomelen + pathlen < sizeof(SyGapRootPaths[i])) { - SyMemmove(SyGapRootPaths[i] + userhomelen, - // don't copy the ~ but the trailing '\0' - SyGapRootPaths[i] + 1, pathlen); - memcpy(SyGapRootPaths[i], userhome, userhomelen); - } - } -#endif }