diff --git a/DEVELOPING.md b/DEVELOPING.md index 157b91b2e5..5b7f2f2a9f 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -156,14 +156,12 @@ multiple parts. - `testinstall`: quick test suite that one can test frequently. Run via `./gap tst/testinstall.g` - `teststandard`: slower but more comprehensive test suite. - Run via `./gap tst/testinstall.g` + Run via `./gap tst/teststandard.g` - `testextra`: very slow test suite that tests even more Run via `./gap tst/testextra.g` - `testbugfix`: additional small test files that are created to verify specific bugfixes work as intended Run via `./gap tst/testbugfix.g` -- `testinstall`: quick test suite that one can test frequently. - Run via `./gap tst/testinstall.g` ## Tracking down regressions diff --git a/dev/releases/HelpLinks-to-JSON.g b/dev/releases/HelpLinks-to-JSON.g index d0bc1a6d0b..613bb8c8f9 100644 --- a/dev/releases/HelpLinks-to-JSON.g +++ b/dev/releases/HelpLinks-to-JSON.g @@ -65,7 +65,7 @@ for x in NamesOfComponents(HELP_BOOKS_INFO) do for i in [1 .. Length(book.entries)] do entry := HELP_BOOK_HANDLER.HelpDataRef(book, i); - name := StripEscapeSequences(entry[1]); + name := _StripEscapeSequences(entry[1]); name := ReplacedString(name, match, ""); NormalizeWhitespace(name); diff --git a/doc/ref/files.xml b/doc/ref/files.xml index 2013360f88..4da8aca5af 100644 --- a/doc/ref/files.xml +++ b/doc/ref/files.xml @@ -122,6 +122,7 @@ for more information how to do this. File Names <#Include Label="Filename"> +<#Include Label="PathSystemProgram"> diff --git a/hpcgap/lib/helpbase.gi b/hpcgap/lib/helpbase.gi index c802ca2dc7..921d65a236 100644 --- a/hpcgap/lib/helpbase.gi +++ b/hpcgap/lib/helpbase.gi @@ -55,11 +55,6 @@ end); ## This utility will first be used in some debug tools showing what is newly ## installed by loading a package. Can be documented if desired. ## -# avoid warning for vars from GAPDoc package -if not IsBound(StripEscapeSequences) then - StripEscapeSequences := 0; -fi; - BindGlobal( "IsDocumentedWord", function( arg ) local inid, word, case, simple, cword, book, matches, a, match; @@ -76,7 +71,7 @@ BindGlobal( "IsDocumentedWord", function( arg ) for book in HELP_KNOWN_BOOKS[1] do matches:= HELP_GET_MATCHES( [ book ], simple, true ); for a in Concatenation( matches ) do - match:= case( StripEscapeSequences( a[1].entries[ a[2] ][1] ) ); + match:= case( _StripEscapeSequences( a[1].entries[ a[2] ][1] ) ); if cword in SplitString( match, "", Difference( match, inid ) ) then return true; fi; @@ -285,7 +280,7 @@ for pair in TRANSATL do for book in HELP_KNOWN_BOOKS[1] do matches:= HELP_GET_MATCHES( [ book ], word, false ); for a in Concatenation( matches ) do - match:= StripEscapeSequences( a[1].entries[ a[2] ][1] ); + match:= _StripEscapeSequences( a[1].entries[ a[2] ][1] ); patterns:=[]; for i in [1..Length(TRANSATL)] do patterns[i]:=[]; @@ -315,10 +310,6 @@ return report; od; # end atomic end); -if StripEscapeSequences = 0 then - Unbind(StripEscapeSequences); -fi; - ############################################################################# ## @@ -1061,9 +1052,6 @@ end); if not IsBound( InitialSubstringUTF8String ) then InitialSubstringUTF8String:= "dummy"; fi; -if not IsBound( LETTERS ) then - LETTERS:= "dummy"; -fi; if not IsBound( WidthUTF8String ) then WidthUTF8String:= "dummy"; fi; @@ -1094,7 +1082,7 @@ BindGlobal( "InitialSubstringUTF8Text", function( str, cols ) fi; # Now pos points at an ESC character; all escape sequences we # support are terminated by a letter, so search for one. - j:= PositionProperty( str, c -> c in LETTERS, pos ); + j:= PositionProperty( str, c -> c in CHARS_ALPHA, pos ); if j = fail then Error( "string end inside escape sequence" ); fi; @@ -1106,9 +1094,6 @@ end ); if not IsReadOnlyGlobal( "InitialSubstringUTF8String" ) then Unbind( InitialSubstringUTF8String ); fi; -if not IsReadOnlyGlobal( "LETTERS" ) then - Unbind( LETTERS ); -fi; if not IsReadOnlyGlobal( "WidthUTF8String" ) then Unbind( WidthUTF8String ); fi; diff --git a/lib/debug.g b/lib/debug.g index d63ce7baca..802a0c7530 100644 --- a/lib/debug.g +++ b/lib/debug.g @@ -89,7 +89,7 @@ Debug := function(arg) fi; # Call the editor: - execpath := Filename(DirectoriesSystemPrograms(),DEBUG.EDITOR.command); + execpath := PathSystemProgram(DEBUG.EDITOR.command); l:= List( DEBUG.EDITOR.args, x -> ReplacedString( x, "###", String( i ) ) ); Add(l,t); # append the temporary filename Process(DirectoryCurrent(),execpath,InputTextUser(),OutputTextUser(),l); diff --git a/lib/files.gd b/lib/files.gd index 38d3a13ad0..5e62bcc54a 100644 --- a/lib/files.gd +++ b/lib/files.gd @@ -157,12 +157,10 @@ DeclareGlobalFunction( "DirectoryDesktop" ); ##

## For example, ## in order to locate the system program date use -## together with the second form of -## . +## . ##

## path := DirectoriesSystemPrograms();; -## gap> date := Filename( path, "date" ); +## gap> date := PathSystemProgram( "date" ); ## "/bin/date" ## ]]> ##

@@ -431,6 +429,37 @@ BIND_GLOBAL( "DirectoriesSystemPrograms", function() end ); +############################################################################# +## +#F PathSystemProgram( ) . . . . . . . . . . path of a system program +## +## <#GAPDoc Label="PathSystemProgram"> +## +## +## +## +## returns either the path of the first +## executable file name in one of the directories returned by +## , +## or fail if no such file exists. +## +## +## <#/GAPDoc> +## +BIND_GLOBAL( "PathSystemProgram", function( name ) + local dir, path; + + for dir in DirectoriesSystemPrograms() do + path:= Filename( dir, name ); + if IsExecutableFile( path ) then + return path; + fi; + od; + + return fail; +end ); + + ############################################################################# ## #F DirectoryTemporary() . . . . . . . . . . . . create a temporary directory @@ -794,16 +823,6 @@ end ); ## DeclareGlobalFunction( "Edit" ); -# the character set definitions might be needed when processing files, thus -# they must come earlier. -BIND_GLOBAL("CHARS_DIGITS",Immutable(SSortedList("0123456789"))); -BIND_GLOBAL("CHARS_UALPHA", - Immutable(SSortedList("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))); -BIND_GLOBAL("CHARS_LALPHA", - Immutable(SSortedList("abcdefghijklmnopqrstuvwxyz"))); -BIND_GLOBAL("CHARS_SYMBOLS",Immutable(SSortedList( - " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"))); - ## <#GAPDoc Label="HexSHA256"> ## diff --git a/lib/files.gi b/lib/files.gi index 936cb71b52..74eccd3305 100644 --- a/lib/files.gi +++ b/lib/files.gi @@ -264,7 +264,7 @@ InstallGlobalFunction( Edit, function( name ) local editor, ret; name := UserHomeExpand(name); - editor := Filename( DirectoriesSystemPrograms(), UserPreference("Editor") ); + editor := PathSystemProgram( UserPreference("Editor") ); if editor = fail then Error( "cannot locate editor `", UserPreference("Editor"), "' (reset via SetUserPreference(\"Editor\", ...))" ); diff --git a/lib/helpbase.gi b/lib/helpbase.gi index 4321909730..f3cf5a8f04 100644 --- a/lib/helpbase.gi +++ b/lib/helpbase.gi @@ -55,11 +55,6 @@ end); ## This utility will first be used in some debug tools showing what is newly ## installed by loading a package. Can be documented if desired. ## -# avoid warning for vars from GAPDoc package -if not IsBound(StripEscapeSequences) then - StripEscapeSequences := 0; -fi; - BindGlobal( "IsDocumentedWord", function( arg ) local inid, word, case, simple, cword, book, matches, a, match; @@ -75,7 +70,7 @@ BindGlobal( "IsDocumentedWord", function( arg ) for book in HELP_KNOWN_BOOKS[1] do matches:= HELP_GET_MATCHES( [ book ], simple, true ); for a in Concatenation( matches ) do - match:= case( StripEscapeSequences( a[1].entries[ a[2] ][1] ) ); + match:= case( _StripEscapeSequences( a[1].entries[ a[2] ][1] ) ); if cword in SplitString( match, "", Difference( match, inid ) ) then return true; fi; @@ -279,7 +274,7 @@ for pair in TRANSATL do for book in HELP_KNOWN_BOOKS[1] do matches:= HELP_GET_MATCHES( [ book ], word, false ); for a in Concatenation( matches ) do - match:= StripEscapeSequences( a[1].entries[ a[2] ][1] ); + match:= _StripEscapeSequences( a[1].entries[ a[2] ][1] ); patterns:=[]; for i in [1..Length(TRANSATL)] do patterns[i]:=[]; @@ -308,10 +303,6 @@ od; return report; end); -if StripEscapeSequences = 0 then - Unbind(StripEscapeSequences); -fi; - ############################################################################# ## @@ -1037,9 +1028,6 @@ end); if not IsBound( InitialSubstringUTF8String ) then InitialSubstringUTF8String:= "dummy"; fi; -if not IsBound( LETTERS ) then - LETTERS:= "dummy"; -fi; if not IsBound( WidthUTF8String ) then WidthUTF8String:= "dummy"; fi; @@ -1070,7 +1058,7 @@ BindGlobal( "InitialSubstringUTF8Text", function( str, cols ) fi; # Now pos points at an ESC character; all escape sequences we # support are terminated by a letter, so search for one. - j:= PositionProperty( str, c -> c in LETTERS, pos ); + j:= PositionProperty( str, c -> c in CHARS_ALPHA, pos ); if j = fail then Error( "string end inside escape sequence" ); fi; @@ -1082,9 +1070,6 @@ end ); if not IsReadOnlyGlobal( "InitialSubstringUTF8String" ) then Unbind( InitialSubstringUTF8String ); fi; -if not IsReadOnlyGlobal( "LETTERS" ) then - Unbind( LETTERS ); -fi; if not IsReadOnlyGlobal( "WidthUTF8String" ) then Unbind( WidthUTF8String ); fi; diff --git a/lib/helpview.gi b/lib/helpview.gi index cafa286ca0..7d497f73f6 100644 --- a/lib/helpview.gi +++ b/lib/helpview.gi @@ -326,7 +326,7 @@ local s,l,a,e,n,c; FWITF:=Filename(DirectoryTemporary(),"clients"); fi; if XLSCLIENTSCMD=false then - XLSCLIENTSCMD:=Filename(DirectoriesSystemPrograms(),"xlsclients"); + XLSCLIENTSCMD:=PathSystemProgram("xlsclients"); fi; if XLSCLIENTSCMD=fail then return fail; @@ -393,7 +393,7 @@ show := function(file) file := file.file; fi; if XRMTCMD=false then - XRMTCMD:=Filename(DirectoriesSystemPrograms(),"xrmtcmd"); + XRMTCMD:=PathSystemProgram("xrmtcmd"); fi; if XRMTCMD<>fail then wnum:=FindWindowId("xdvi",file); # get the window ID of a running XDVI diff --git a/lib/package.gi b/lib/package.gi index 82573104fa..226dba4014 100644 --- a/lib/package.gi +++ b/lib/package.gi @@ -2086,10 +2086,6 @@ InstallGlobalFunction( AutoloadPackages, function() ## #F GAPDocManualLab() . create manual.lab for package w/ GAPDoc docs ## -# avoid warning (will be def. in GAPDoc) -if not IsBound(StripEscapeSequences) then - StripEscapeSequences := 0; -fi; InstallGlobalFunction( GAPDocManualLabFromSixFile, function( bookname, sixfilepath ) local stream, entries, SecNumber, esctex, file; @@ -2112,7 +2108,7 @@ InstallGlobalFunction( GAPDocManualLabFromSixFile, # throw away TeX critical characters here esctex:= function( str ) - return Filtered( StripEscapeSequences( str ), c -> not c in "%#$&^_~" ); + return Filtered( _StripEscapeSequences( str ), c -> not c in "%#$&^_~" ); end; bookname:= LowercaseString( bookname ); @@ -2160,9 +2156,6 @@ InstallGlobalFunction( GAPDocManualLab, function(pkgname) GAPDocManualLabFromSixFile( book.BookName, file ); od; end ); -if StripEscapeSequences = 0 then - Unbind(StripEscapeSequences); -fi; ############################################################################# diff --git a/lib/pager.gi b/lib/pager.gi index 2559ff3be8..7144d48f65 100644 --- a/lib/pager.gi +++ b/lib/pager.gi @@ -290,13 +290,12 @@ end); # +num for starting display in line num BindGlobal("PAGER_EXTERNAL", function( lines ) - local path, pager, linepos, str, i, cmdargs, stream; + local pager, linepos, str, i, cmdargs, stream; pager := UserPreference("Pager"); if not (Length(pager) > 0 and pager[1] = '/' and IsExecutableFile(pager)) then - path := DirectoriesSystemPrograms(); - pager := Filename( path, UserPreference("Pager") ); + pager := PathSystemProgram( UserPreference("Pager") ); fi; if pager=fail then Error( "Pager ", UserPreference("Pager"), diff --git a/lib/polyconw.gi b/lib/polyconw.gi index 7fe647ca68..2bb620661f 100644 --- a/lib/polyconw.gi +++ b/lib/polyconw.gi @@ -133,7 +133,7 @@ end); ## str := ""; ## get := OutputTextString(str, false); ## comm := "wget -q ftp://ftp.comlab.ox.ac.uk/pub/Documents/techpapers/Richard.Brent/factors/factors.gz -O - | gzip -dc "; -## Process(DirectoryCurrent(), Filename(DirectoriesSystemPrograms(),"sh"), +## Process(DirectoryCurrent(), PathSystemProgram("sh"), ## InputTextUser(), get, ["-c", comm]); ## res := [[],[]]; ## n := 0; diff --git a/lib/process.gd b/lib/process.gd index 5eb90924cd..c92665ffa9 100644 --- a/lib/process.gd +++ b/lib/process.gd @@ -69,10 +69,10 @@ ## directory. ##

## path := DirectoriesSystemPrograms();; -## gap> ls := Filename( path, "ls" );; +## gap> ls := PathSystemProgram( "ls" );; ## gap> stdin := InputTextUser();; ## gap> stdout := OutputTextUser();; +## gap> path := DirectoriesSystemPrograms();; ## gap> Process( path[1], ls, stdin, stdout, ["-c"] );; ## awk ls mkdir ## gap> # current directory, here the root directory @@ -123,12 +123,10 @@ ## Note that input/output redirection commands are not allowed as ## options. ##

-## In order to find a system program use -## together with . +## In order to find a system program use . ##

## path := DirectoriesSystemPrograms();; -## gap> date := Filename( path, "date" ); +## gap> date := PathSystemProgram( "date" ); ## "/bin/date" ## ]]> ##

diff --git a/lib/process.gi b/lib/process.gi index 3c2d42a3b7..0253cc13a0 100644 --- a/lib/process.gi +++ b/lib/process.gi @@ -247,10 +247,10 @@ InstallGlobalFunction( Exec, function( arg ) # on Windows, we use the native shell such that behaviour does # not depend on whether cygwin is installed or not. # cmd.exe is preferable to old-style `command.com' - shell := Filename( DirectoriesSystemPrograms(), "cmd.exe" ); + shell := PathSystemProgram( "cmd.exe" ); cs := "/C"; else - shell := Filename( DirectoriesSystemPrograms(), "sh" ); + shell := PathSystemProgram( "sh" ); cs := "-c"; fi; diff --git a/lib/profile.g b/lib/profile.g index ca7d399c09..fbb52c8236 100644 --- a/lib/profile.g +++ b/lib/profile.g @@ -778,7 +778,7 @@ BIND_GLOBAL("ProfileOperationsOff",function() UnprofileMethods(\+,\-,\*,\/,\^,\mod,\<,\=,\in, \.,\.\:\=,IsBound\.,Unbind\., \[\],\[\]\:\=,IsBound\[\],Unbind\[\]); -#T Why? These operations are listed in PFOFILED_OPERATIONS! +#T Why? These operations are listed in PROFILED_OPERATIONS! end); BIND_GLOBAL("ProfileOperations",function( arg ) @@ -836,7 +836,7 @@ BIND_GLOBAL("ProfileOperationsAndMethodsOn",function() ProfileMethods(\+,\-,\*,\/,\^,\mod,\<,\=,\in, \.,\.\:\=,IsBound\.,Unbind\., \[\],\[\]\:\=,IsBound\[\],Unbind\[\]); -#T Why? These operations are listed in PFOFILED_OPERATIONS! +#T Why? These operations are listed in PROFILED_OPERATIONS! end); ProfileOperationsAndMethodsOff := ProfileOperationsOff; diff --git a/lib/streams.gd b/lib/streams.gd index e9b6365227..5551d01efd 100644 --- a/lib/streams.gd +++ b/lib/streams.gd @@ -908,7 +908,7 @@ DeclareCategory( "IsInputOutputStream", IsInputStream and ## d := DirectoryCurrent(); ## dir("./") -## gap> f := Filename(DirectoriesSystemPrograms(), "rev"); +## gap> f := PathSystemProgram("rev"); ## "/usr/bin/rev" ## gap> s := InputOutputLocalProcess(d,f,[]); ## < input/output stream to rev > diff --git a/lib/string.g b/lib/string.g index 536b964759..36ee0f3d4d 100644 --- a/lib/string.g +++ b/lib/string.g @@ -349,3 +349,70 @@ BIND_GLOBAL("UserHomeExpand", function(str) return str; fi; end); + + +# the character set definitions might be needed when processing files, thus +# they must come earlier. +BIND_GLOBAL("CHARS_DIGITS",MakeImmutable(LIST_SORTED_LIST("0123456789"))); +BIND_GLOBAL("CHARS_UALPHA", + MakeImmutable(LIST_SORTED_LIST("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))); +BIND_GLOBAL("CHARS_LALPHA", + MakeImmutable(LIST_SORTED_LIST("abcdefghijklmnopqrstuvwxyz"))); +BIND_GLOBAL("CHARS_ALPHA", + MakeImmutable(LIST_SORTED_LIST("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"))); +BIND_GLOBAL("CHARS_SYMBOLS", + MakeImmutable(LIST_SORTED_LIST(" !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"))); + + +############################################################################# +## +#F _StripEscapeSequences( ) . . . . . remove escape sequences from str +## +## <#GAPDoc Label="_StripEscapeSequences"> +## +## +## string without escape sequences +## +## This function returns the string one gets from the string str by +## removing all escape sequences. If str does not contain such a +## sequence then str itself is returned. +## +## +## <#/GAPDoc> +## +BIND_GLOBAL("_StripEscapeSequences", function(str) + local esc, res, i, ls, p; + esc := CHAR_INT(27); + res := ""; + i := 1; + ls := Length(str); + while i <= ls do + if str[i] = esc then + i := i+1; + while not str[i] in CHARS_ALPHA do + i := i+1; + od; + # first letter is last character of escape sequence + i := i+1; + # remove \027 marker of inner escape sequences as well + if IsBound(str[i]) and str[i] = '\027' then + i := i+1; + fi; + else + p := Position(str, esc, i); + if p=fail then + if i=1 then + # don't copy if no escape there + return str; + else + Append(res, str{[i..ls]}); + return res; + fi; + else + Append(res, str{[i..p-1]}); + i := p; + fi; + fi; + od; + return res; +end); diff --git a/lib/string.gi b/lib/string.gi index b5cf315b65..aab31a454b 100644 --- a/lib/string.gi +++ b/lib/string.gi @@ -40,8 +40,7 @@ InstallGlobalFunction(IsLowerAlphaChar,x->x in CHARS_LALPHA); ## #F IsAlphaChar() ## -InstallGlobalFunction(IsAlphaChar, - x->x in CHARS_LALPHA or x in CHARS_UALPHA); +InstallGlobalFunction(IsAlphaChar,x->x in CHARS_ALPHA); ############################################################################# diff --git a/lib/test.gi b/lib/test.gi index 3de30989a5..dd467eb217 100644 --- a/lib/test.gi +++ b/lib/test.gi @@ -807,7 +807,7 @@ end); ## ## The argument inlist must be either a single filename ## or directory name, or a list of filenames and directories. -## The function will take create a list of files +## The function will create a list of files ## to be tested by taking any files in inlist, and recursively searching ## any directories in inlist for files ending in .tst. ## Each of these files is then run through , and the results diff --git a/src/julia_gc.c b/src/julia_gc.c index 4c9ea0628a..2c13e10d89 100644 --- a/src/julia_gc.c +++ b/src/julia_gc.c @@ -421,7 +421,7 @@ static void FindLiveRangeReverse(PtrArray * arr, void * start, void * end) { // HACK: the following deals with stacks of 'negative size' exposed by // Julia -- however, despite us having this code in here for a few years, - // I know think it may actually be due to a bug on the Julia side. See + // I now think it may actually be due to a bug on the Julia side. See // for details. if (lt_ptr(end, start)) { SWAP(void *, start, end); diff --git a/tst/delegation.g b/tst/delegation.g index e8dee4758c..9a8fd47747 100644 --- a/tst/delegation.g +++ b/tst/delegation.g @@ -53,9 +53,9 @@ for pos in [1..Length(rules)] do while true do n := POSITION_SUBSTRING(str, r, n); if n = fail then break; fi; - if n > 1 and str[n-1] in LETTERS then continue; fi; + if n > 1 and str[n-1] in CHARS_ALPHA then continue; fi; if Length(str) >= n + Length(r) then - if not str[n + Length(r)] in LETTERS then + if not str[n + Length(r)] in CHARS_ALPHA then Add( illegal_delegations, r ); break; fi; diff --git a/tst/testinstall/testunix/streams.tst b/tst/testinstall/testunix/streams.tst index 21677f906d..5712ba2517 100644 --- a/tst/testinstall/testunix/streams.tst +++ b/tst/testinstall/testunix/streams.tst @@ -5,7 +5,7 @@ gap> START_TEST("streams.tst"); # gap> d := DirectoryCurrent();; #@if ARCH_IS_UNIX() -gap> f := Filename(DirectoriesSystemPrograms(), "cat");; +gap> f := PathSystemProgram("cat");; gap> s := InputOutputLocalProcess(d,f,[]); < input/output stream to cat > gap> WriteLine(s,"The cat sat on the mat"); diff --git a/tst/teststandard/varnames.tst b/tst/teststandard/varnames.tst index 3c8d8e28cb..af9f4663b5 100644 --- a/tst/teststandard/varnames.tst +++ b/tst/teststandard/varnames.tst @@ -7,7 +7,7 @@ gap> Filtered( NamesSystemGVars(), x -> not x in ALL_KEYWORDS() and > ( Length(x)=1 or (IsLowerAlphaChar(x[1]) and Length(x) < 5) ) ); [ "*", "+", "-", ".", "/", "<", "=", "E", "X", "Z", "^", "fail", "last", "time" ] -gap> Filtered(NamesSystemGVars(),name->IsSubset(LETTERS,name));; +gap> Filtered(NamesSystemGVars(),name->IsSubset(CHARS_ALPHA,name));; gap> IsSubset(IDENTS_GVAR(), IDENTS_BOUND_GVARS() ); true gap> E;