diff --git a/lib/package.gi b/lib/package.gi index 8916dc312e..bf9345016f 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/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/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 4e4c8181d1..e12a656246 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,34 +48,28 @@ 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; /**************************************************************************** ** -*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) { - 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; - } + int len = strlen(filename); + int npaths = LEN_PLIST(SyGapRootPaths); + for (int k = 1; k <= npaths; k++) { + Obj path = CopyToStringRep(ELM_PLIST(SyGapRootPaths, k)); + AppendCStr(path, filename, len); + if (SyIsReadableFile(CSTR_STRING(path)) == 0) { + return path; } } - buf[0] = '\0'; return 0; } @@ -99,10 +94,12 @@ Char * SyFindGapRootFile(const Char * filename, Char * buf, size_t size) */ void SySetGapRootPath(const Char * string) { - const Char * p; - Char * q; - Int i; - Int n; + 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) { @@ -111,110 +108,79 @@ 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("./"); + // TODO: insert output of getcwd?? + } else { + 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 + 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++; -#endif - } + path = CopyToStringRep(path); + AppendCStr(path, "hpcgap/", 7); - // 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); - } + AddPlist3(SyGapRootPaths, path, pos); + pos++; +#endif } } @@ -225,12 +191,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 4b9dfde11f..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; /**************************************************************************** @@ -45,15 +62,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); /****************************************************************************