#ifdef HAVE_SELECT // Only for the Hook handler calls: #include <sys/time.h> #endif
#ifdef HAVE_SIGNAL_H // signal handling functions #include <signal.h> #endif
#ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> // for TIOCGWINSZ #endif
#ifdef HAVE_LIBREADLINE // the following two definitions silence some compiler warnings in the // readline headers; the first one suppresses the definition of a few // deprecated (!) and unused typedefs; the second indicates that stdarg.h is // available (since compiling GAP requires C99, this is guaranteed) #define _FUNCTION_DEF #define HAVE_STDARG_H #include <readline/readline.h> #endif
#include <zlib.h>
#include <sys/utsname.h>
// 'EndLineHook' is a GAP-level variable which can be set to a function to be // called at end of each command line (i.e. after the user presses enter). // If not bound, nothing is done. static Obj EndLineHook = 0;
// The type of file stored in a 'SYS_SY_BUF' typedefenum {
unused_socket, // Socket is free
raw_socket, // Plain UNIX socket stored in 'fp'
gzip_socket // A gzFile handled by zlib stored in 'gzfp'
} GAPSocketType;
GAP_STATIC_ASSERT(unused_socket == 0, "unused_socket must be zero");
typedefstruct { // gzfp is used if type == gzip_socket
gzFile gzfp;
// file descriptor for this file (only used if type == raw_socket) int fp;
// file descriptor for the echo (only used if type == raw_socket) int echo;
// file is either a plain descriptor, pipe or gzipped
GAPSocketType type;
// set to 1 by any read operation that hits eof; reset to 0 by a // subsequent successful read BOOL ateof;
// records that last character read was \r for cygwin and other systems // that need end-of-line hackery BOOL crlast;
// if non-negative then this file has a buffer in syBuffers[bufno]; if // negative, this file may not be buffered int bufno;
// set when this fid is a *stdin* or *errin* and really is a tty BOOL isTTY;
} SYS_SY_BUF;
// and close it again
SyFclose( fid ); // Emulate a signed shift: if (crc & 0x80000000L) return (Int4) ((crc >> 4) | 0xF0000000L); else return (Int4) (crc >> 4);
}
// And here we include a variant working on a GAP string static Obj FuncCrcString(Obj self, Obj str)
{
UInt4 crc;
UInt4 old;
UInt4 new;
UInt4 i, len; constChar *ptr;
Int4 ch; Int seen_nl;
RequireStringRep(SELF_NAME, str);
ptr = CONST_CSTR_STRING(str);
len = GET_LEN_STRING(str);
crc = 0x12345678L;
seen_nl = 0; for (i = 0; i < len; i++) {
ch = (Int4)(ptr[i]); if ( ch == '\377' || ch == '\n' || ch == '\r' )
ch = '\n'; if ( ch == '\n' ) { if ( seen_nl ) continue; else
seen_nl = 1;
} else
seen_nl = 0;
old = (crc >> 8) & 0x00FFFFFFL; new = syCcitt32[ ( (UInt4)( crc ^ ch ) ) & 0xff ];
crc = old ^ new;
} if ( crc == 0 ) {
crc = 1;
} return INTOBJ_INT(((Int4) crc) >> 4);
}
// Get OS Kernel version. Used to discover if GAP is running inside // 'Windows Subsystem for Linux'
Obj SyGetOsRelease(void)
{
Obj r = NEW_PREC(0); struct utsname buf; if (!uname(&buf)) {
AssPRec(r, RNamName("sysname"), MakeImmString(buf.sysname));
AssPRec(r, RNamName("nodename"), MakeImmString(buf.nodename));
AssPRec(r, RNamName("release"), MakeImmString(buf.release));
AssPRec(r, RNamName("version"), MakeImmString(buf.version));
AssPRec(r, RNamName("machine"), MakeImmString(buf.machine));
}
/**************************************************************************** ** *FCTV(<V>).................convert<V>intoquote<V>
*/
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/**************************************************************************** ** *FsyWinPut(<fid>,<cmd>,<str>)....sendalinetothewindowhandler ** **'syWinPut'sendthecommand<cmd>andthestring<str>tothewindow **handlerassociatedwiththefileidentifier<fid>.Inthestring<str> **'@'charactersareduplicated,andcontrolcharactersareconvertedto **'@<chr>',e.g.,<newline>isconvertedto'@J'.
*/ void syWinPut ( Int fid, constChar * cmd, constChar * str )
{ Char tmp [130]; // temporary buffer constChar * s; // pointer into the string Char * t; // pointer into the temporary
// if not running under a window handler, don't do anything if (!SyWindow || 4 <= fid || syBuf[fid].type == gzip_socket) return;
// print the cmd
echoandcheck( fid, cmd, strlen(cmd) );
constChar * SyWinCmd ( constChar * str,
UInt len )
{ Char buf [130]; // temporary buffer constChar * s; // pointer into the string constChar * bb; // pointer into the temporary Char * b; // pointer into the temporary
UInt i; // loop variable #ifdef SYS_IS_CYGWIN32
UInt len1; // temporary storage for len #endif
// if not running under a window handler, don't do nothing if ( ! SyWindow ) return"I1+S52+No Window Handler Present";
// compute the length of the (expanded) string (and ignore argument)
len = 0; for ( s = str; *s != '\0'; s++ )
len += 1 + (*s == '@' || (CTR('A') <= *s && *s <= CTR('Z')));
// send the length to the window handler
b = buf; for ( ; 0 < len; len /= 10 ) {
*b++ = (len % 10) + '0';
}
*b++ = '+';
*b++ = '\0';
syWinPut( 1, "@w", buf );
// send the string to the window handler
syWinPut( 1, "", str );
// read the length of the answer
b = WinCmdBuffer;
i = 3; while ( 0 < i ) {
len = read( 0, b, i );
i -= len;
b += len;
} if ( WinCmdBuffer[0] != '@' || WinCmdBuffer[1] != 'a' ) return"I1+S41+Illegal Answer";
b = WinCmdBuffer+2; for ( i=1,len=0; '0' <= *b && *b <= '9'; i *= 10 ) {
len += (*b-'0')*i; while ( read( 0, b, 1 ) != 1 ) ;
}
// read the arguments of the answer
b = WinCmdBuffer;
i = len; #ifdef SYS_IS_CYGWIN32
len1 = len; while ( 0 < i ) {
len = read( 0, b, i );
b += len;
i -= len;
s += len;
}
len = len1; #else while ( 0 < i ) {
len = read( 0, b, i );
i -= len;
s += len;
} #endif
// Mark a member of syBuf as unused staticvoid SyBufMarkUnused(Int i)
{
GAP_ASSERT(i >= 0 && i < ARRAY_SIZE(syBuf));
memset(&(syBuf[i]), 0, sizeof(syBuf[i]));
syBuf[i].type = unused_socket;
}
// There is no explicit method to mark syBufs as used, // they are marked as used when created.
// Check if a member of syBuf is in use staticInt SyBufInUse(Int i)
{ if (i >= 0 && i < ARRAY_SIZE(syBuf)) return syBuf[i].type != unused_socket; return0;
}
/**************************************************************************** ** *FSyFclose(<fid>).................closethefile<fid> ** **'SyFclose'closesthefilewiththeidentifier<fid>whichisobtained **from'SyFopen'.
*/ Int SyFclose ( Int fid )
{ // check file identifier if ( ARRAY_SIZE(syBuf) <= fid || fid < 0 ) {
fputs("gap: panic 'SyFclose' asked to close illegal fid!\n",stderr); return -1;
} if ( !SyBufInUse(fid) ) {
fputs("gap: panic 'SyFclose' asked to close closed file!\n",stderr); return -1;
}
// refuse to close the standard files if ( fid == 0 || fid == 1 || fid == 2 || fid == 3 ) { return -1;
}
HashLock(&syBuf); // try to close the file if (syBuf[fid].type == raw_socket && close(syBuf[fid].fp) == EOF) {
fputs("gap: 'SyFclose' cannot close file, ",stderr);
fputs("maybe your file system is full?\n",stderr);
SyBufMarkUnused(fid);
HashUnlock(&syBuf); return -1;
}
if (syBuf[fid].type == gzip_socket) { if (gzclose(syBuf[fid].gzfp) < 0) {
fputs("gap: 'SyFclose' cannot close compressed file", stderr);
}
}
// mark the buffer as unused if (syBuf[fid].bufno >= 0)
syBuffers[syBuf[fid].bufno].inuse = FALSE;
SyBufMarkUnused(fid);
HashUnlock(&syBuf); return0;
}
/**************************************************************************** ** *FSyIsEndOfFile(<fid>)...............endoffilereached
*/ Int SyIsEndOfFile ( Int fid )
{ // check file identifier if ( !SyBufInUse(fid) ) { return -1;
}
// *stdin* and *errin* are never at end of file if ( fid < 4 ) return0;
UInt syStartraw ( Int fid )
{ // if running under a window handler, tell it that we want to read if ( SyWindow ) { if ( fid == 0 ) { syWinPut( fid, "@i", "" ); return1; } elseif ( fid == 2 ) { syWinPut( fid, "@e", "" ); return1; } else { return0; }
}
// try to get the terminal attributes, will fail if not terminal constint fd = SyBufFileno(fid);
GAP_ASSERT(fd >= 0); if ( tcgetattr( fd, &syOld) == -1 ) return0;
// disable interrupt, quit, start and stop output characters
syNew = syOld;
syNew.c_cc[VINTR] = 0377;
syNew.c_cc[VQUIT] = 0377; /*C 27-Nov-90 martin changing '<ctr>S' and '<ctr>Q' does not work */ /*C syNew.c_iflag &= ~(IXON|INLCR|ICRNL); */
syNew.c_iflag &= ~(INLCR|ICRNL);
// disable input buffering, line editing and echo
syNew.c_cc[VMIN] = 1;
syNew.c_cc[VTIME] = 0;
syNew.c_lflag &= ~(ECHO|ICANON);
if ( tcsetattr( fd, TCSANOW, &syNew) == -1 ) return0;
#ifdef SIGTSTP // install signal handler for stop
syFid = fid;
signal( SIGTSTP, syAnswerTstp ); #endif
void syStopraw ( Int fid )
{ // if running under a window handler, don't do nothing if ( SyWindow ) return;
#ifdef SIGTSTP // remove signal handler for stop
signal( SIGTSTP, SIG_DFL ); #endif
// enable input buffering, line editing and echo again constint fd = SyBufFileno(fid);
GAP_ASSERT(fd >= 0); if (tcsetattr(fd, TCSANOW, &syOld) == -1)
fputs("gap: 'tcsetattr' could not turn off raw mode!\n",stderr);
}
#ifdef HAVE_LIBREADLINE // ignore during readline if (doingReadline) return; #endif
// get the current wall clock time
nowIntr = time(0);
// if the last '<ctr>-C' was less than a second ago, exit GAP if ( syLastIntr && nowIntr-syLastIntr < 1 ) {
fputs("gap: you hit '<ctr>-C' twice in a second, goodbye.\n",stderr);
SyExit( 1 );
}
// remember time of this interrupt
syLastIntr = nowIntr;
#ifdef HAVE_SIGNAL // interrupt the executor
InterruptExecStat(); #endif
}
#ifdef USE_TERMCAP // note that if we define TERMCAP, this has to be linked with -ltermcap // maybe that is -ltermlib on some SYSV machines if (SyNrRows <= 0 || SyNrCols <= 0) { // this failed - next attempt: try to find info in TERMCAP char *sp; char bp[1024];
/**************************************************************************** ** *fsyEchos(<ch>,<fid>)
*/ staticvoid syEchos(constChar * str, Int fid)
{ // if running under a window handler, send the line to it if ( SyWindow && fid < 4 )
syWinPut( fid, (fid == 1 ? "@n" : "@f"), str );
// otherwise, write it to the associate echo output device else
echoandcheck(fid, str, strlen(str) );
}
/**************************************************************************** ** *FSyFputs(<line>,<fid>)........writealinetothefile<fid> ** **'SyFputs'iscalledtoputthe<line>tothefileidentifiedby<fid>.
*/ static UInt syNrchar; // nr of chars already on the line staticChar syPrompt[MAXLENOUTPUTLINE]; // characters already on the line
/**************************************************************************** ** *FSyFtell(<fid>)..................positionofstream
*/ Int SyFtell ( Int fid )
{ // check file identifier if ( !SyBufInUse(fid) ) { return -1;
}
Int ret;
switch (syBuf[fid].type) { case raw_socket:
ret = (Int)lseek(syBuf[fid].fp, 0, SEEK_CUR); break; case gzip_socket:
ret = (Int)gzseek(syBuf[fid].gzfp, 0, SEEK_CUR); break; case unused_socket: default: return -1;
}
// Need to account for characters in buffer if (syBuf[fid].bufno >= 0) {
UInt bufno = syBuf[fid].bufno;
ret -= syBuffers[bufno].buflen - syBuffers[bufno].bufstart;
} return ret;
}
/**************************************************************************** ** *FSyFseek(<fid>,<pos>)...........seekapositionofstream
*/ Int SyFseek ( Int fid, Int pos )
{ // check file identifier if ( !SyBufInUse(fid) ) { return -1;
}
/* In the cygwin environment it is not predictable if text files get the *'\r'intheirlineendsfilteredout*before*GAPseesthem.Thisleads *toproblemwithcontinuationofstringsorintegersoverseverallinesin *GAPinput.Thereforeweintroduceahackwhichremovessuch'\r's *before'\n'sonsuchasystem.Addhereifthereareothersystemswith *asimilarproblem.
*/
// if running under a window handler, handle special characters if ( SyWindow && ch == '@' ) { do { while ( (ret = SyRead(fid, &ch, 1)) == -1 &&
errno == EAGAIN ) ; if (ret <= 0) return EOF;
} while ( ch < '@' || 'z' < ch ); if ( ch == 'y' ) { do { while ( (ret = SyRead(fid, &ch, 1)) == -1 &&
errno == EAGAIN ); if (ret <= 0) return EOF;
} while ( ch < '@' || 'z' < ch );
str[0] = ch;
str[1] = 0;
syWinPut( syBuf[fid].echo, "@s", str );
ch = syGetchTerm(fid);
} elseif ( 'A' <= ch && ch <= 'Z' )
ch = CTR(ch);
}
#ifdef LINE_END_HACK /* A hack for non ANSI-C confirming systems which deliver \r or \r\n *lineends.Thesearetranslatedto\nhere.
*/ if (ch == '\n') { if (syBuf[fid].crlast) {
syBuf[fid].crlast = FALSE; goto tryagain;
} else return (UChar)'\n';
} if (ch == '\r') {
syBuf[fid].crlast = TRUE; return (Int)'\n';
} // We saw a '\r' without a '\n'
syBuf[fid].crlast = FALSE; #endif// line end hack
#ifdef LINE_END_HACK /* A hack for non ANSI-C confirming systems which deliver \r or \r\n *lineends.Thesearetranslatedto\nhere.
*/ if (ch == '\n') { if (syBuf[fid].crlast) {
syBuf[fid].crlast = FALSE; goto tryagain;
} else return (UChar)'\n';
} if (ch == '\r') {
syBuf[fid].crlast = TRUE; return (Int)'\n';
} // We saw a '\r' without a '\n'
syBuf[fid].crlast = FALSE; #endif// line end hack
// if we are reading stdin or errin use raw mode if ( fid == 0 || fid == 2 ) {
syStartraw(fid);
}
ch = syGetch(fid); if ( fid == 0 || fid == 2 ) {
syStopraw(fid);
} return ch;
}
/**************************************************************************** ** *FSyFgets(<line>,<length>java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 ** **'SyFgets'iscalledtoreadalinefromthefilewithidentifier<fid>. **'SyFgets'(like'fgets')readscharactersuntileither<length>-1 **havebeenreadoruntila<newline>oran<eof>characterisencountered. **Itretainsthe'\n'(unlike'gets'),ifany,andappends'\0'to<line>. **'SyFgets'returns<line>ifanycharhasbeenread,otherwise'(char*)0'. ** **'SyFgets'allowstoedittheinputlineifthefile<fid>referstoa *withcommands: ** **<ctr>-Amovethecursortothebeginningoftheline. **<esc>{ *ctr>-java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 55 **<ctr*SyGetch(<id>)..............a<> **<esc>-Fmovethecursorjava.lang.StringIndexOutOfBoundsException: Range [0, 34) out of bounds for length 26 **<ctr>-Emovethecursortotheendoftheline. ** **<ctr>-H,<del>// if we are reading stdin **f)java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24 **<ctr>-Kdeleteuptotheendoftheline. **<esc>-Ddeleteforwardtotheendofthenextword. **<esc>-<del>deletebackwardtothebeginningofthelastword. **<ctr>-Xdeleteentireinputline,anddiscardallpendinginput. **<ctr>-Yinsert(yank)ajustkilledtext. ** **<ctr>-Texchange(twiddle)currentandpreviouscharacter. **<esc>-Uuppercasenextword. **<esc>-Llowercasenextword. **<esc>-Ccapitalizenextword. ** **<tab>completetheidentifierbeforethecursor. **<ctr>-Linsertlastinputlinebeforecurrentcharacter. **<ctr>-Predisplaythelastinputline,another<ctr>-Pwillredisplay **thelinebeforethat,etc.Ifthecursorisnotinthefirst **columnonlythelinesstartingwiththestringtotheleftof **thecursoraretaken.Thehistoryislimitedto~8000chars. **<ctr>-NLike<ctr>-Pbutgoestheotherwayroundthroughthehistory **<esc>-<goestothebeginningofthehistory. **<esc>->goestotheendofthehistory. **<ctr>-Oacceptthislineandperforma<ctr>-N. ** **<ctr>-Venternextcharacterliterally. **<ctr>-Uexecutethenextcommand4times. **<esc>-<num>executethenextcommand<num>times. **<esc>-<ctr>-Lrepaintinputline. ** **Notyetimplementedcommands: ** **<ctr>-Ssearchinteractiveforastringforward. **<ctr>-Rsearchinteractiveforastringbackward. **<esc>-Yreplaceyankedstringwithpreviouslykilledtext. **<ctr>-_undoacommand. **<esc>-Texchangetwowords.
*/
static UInt syCTRO; // number of '<ctr>-O' pending static UInt syESCN; // number of '<Esc>-N' pending
UInt FreezeStdin; // When true, ignore if any new input from stdin // This is used to stop HPC-GAP from reading stdin // while forked subprocesses are running.
#ifdef HAVE_SELECT
static Obj OnCharReadHookActive = 0; // if bound the hook is active static Obj OnCharReadHookInFds = 0; // a list of UNIX file descriptors for reading static Obj OnCharReadHookInFuncs = 0; // a list of GAP functions with 0 args static Obj OnCharReadHookOutFds = 0; // a list of UNIX file descriptors for writing static Obj OnCharReadHookOutFuncs = 0;// a list of GAP functions with 0 args static Obj OnCharReadHookExcFds = 0; // a list of UNIX file descriptors static Obj OnCharReadHookExcFuncs = 0;// a list of GAP functions with 0 args
staticvoid HandleCharReadHook(int stdinfd) /* This is called directly before a character is read from stdin in the case *ofaninteractivesessionwithcommandlineediting.Wehavetoreturn *assoonasstdinisreadytoread!Wejustuse`select'andcarefor
* handlers for streams. */
{
fd_set infds,outfds,excfds; int n,maxfd; Int i,j;
Obj o; staticint WeAreAlreadyInHere = 0;
// Just to make sure: if (WeAreAlreadyInHere) return;
WeAreAlreadyInHere = 1;
while (1) { // breaks when fd becomes ready
FD_ZERO(&infds);
FD_ZERO(&outfds);
FD_ZERO(&excfds);
FD_SET(stdinfd,&infds);
maxfd = stdinfd; // Handle input file descriptors: if (OnCharReadHookInFds != (Obj) 0 &&
IS_PLIST(OnCharReadHookInFds) &&
OnCharReadHookInFuncs != (Obj) 0 &&
IS_PLIST(OnCharReadHookInFuncs)) { for (i = 1;i <= LEN_PLIST(OnCharReadHookInFds);i++) {
o = ELM_PLIST(OnCharReadHookInFds,i); if (o != (Obj) 0 && IS_INTOBJ(o)) {
j = INT_INTOBJ(o); // a UNIX file descriptor
FD_SET(j,&infds); if (j > maxfd) maxfd = j;
}
}
} // Handle output file descriptors: if (OnCharReadHookOutFds != (Obj) 0 &&
IS_PLIST(OnCharReadHookOutFds) &&
OnCharReadHookOutFuncs != (Obj) 0 &&
IS_PLIST(OnCharReadHookOutFuncs)) { for (i = 1;i <= LEN_PLIST(OnCharReadHookOutFds);i++) {
o = ELM_PLIST(OnCharReadHookOutFds,i); if (o != (Obj) 0 && IS_INTOBJ(o)) {
j = INT_INTOBJ(o); // a UNIX file descriptor
FD_SET(j,&outfds); if (j > maxfd) maxfd = j;
}
}
} // Handle exception file descriptors: if (OnCharReadHookExcFds != (Obj) 0 &&
IS_PLIST(OnCharReadHookExcFds) &&
OnCharReadHookExcFuncs != (Obj) 0 &&
IS_PLIST(OnCharReadHookExcFuncs)) { for (i = 1;i <= LEN_PLIST(OnCharReadHookExcFds);i++) {
o = ELM_PLIST(OnCharReadHookExcFds,i); if (o != (Obj) 0 && IS_INTOBJ(o)) {
j = INT_INTOBJ(o); // a UNIX file descriptor
FD_SET(j,&excfds); if (j > maxfd) maxfd = j;
}
}
}
n = select(maxfd+1,&infds,&outfds,&excfds,NULL); if (n >= 0) { // Now run through the lists and call functions if ready:
if (OnCharReadHookInFds != (Obj) 0 &&
IS_PLIST(OnCharReadHookInFds) &&
OnCharReadHookInFuncs != (Obj) 0 &&
IS_PLIST(OnCharReadHookInFuncs)) { for (i = 1;i <= LEN_PLIST(OnCharReadHookInFds);i++) {
o = ELM_PLIST(OnCharReadHookInFds,i); if (o != (Obj) 0 && IS_INTOBJ(o)) {
j = INT_INTOBJ(o); // a UNIX file descriptor if (FD_ISSET(j,&infds)) {
o = ELM_PLIST(OnCharReadHookInFuncs,i); if (o != (Obj) 0 && IS_FUNC(o))
Call1ArgsInNewReader(o,INTOBJ_INT(i));
}
}
}
} // Handle output file descriptors: if (OnCharReadHookOutFds != (Obj) 0 &&
IS_PLIST(OnCharReadHookOutFds) &&
OnCharReadHookOutFuncs != (Obj) 0 &&
IS_PLIST(OnCharReadHookOutFuncs)) { for (i = 1;i <= LEN_PLIST(OnCharReadHookOutFds);i++) {
o = ELM_PLIST(OnCharReadHookOutFds,i); if (o != (Obj) 0 && IS_INTOBJ(o)) {
j = INT_INTOBJ(o); // a UNIX file descriptor if (FD_ISSET(j,&outfds)) {
o = ELM_PLIST(OnCharReadHookOutFuncs,i); if (o != (Obj) 0 && IS_FUNC(o))
Call1ArgsInNewReader(o,INTOBJ_INT(i));
}
}
}
} // Handle exception file descriptors: if (OnCharReadHookExcFds != (Obj) 0 &&
IS_PLIST(OnCharReadHookExcFds) &&
OnCharReadHookExcFuncs != (Obj) 0 &&
IS_PLIST(OnCharReadHookExcFuncs)) { for (i = 1;i <= LEN_PLIST(OnCharReadHookExcFds);i++) {
o = ELM_PLIST(OnCharReadHookExcFds,i); if (o != (Obj) 0 && IS_INTOBJ(o)) {
j = INT_INTOBJ(o); // a UNIX file descriptor if (FD_ISSET(j,&excfds)) {
o = ELM_PLIST(OnCharReadHookExcFuncs,i); if (o != (Obj) 0 && IS_FUNC(o))
Call1ArgsInNewReader(o,INTOBJ_INT(i));
}
}
}
}
// Return if there is input to read from stdin, // and FreezeStdin is false. if (FD_ISSET(stdinfd, &infds) && !FreezeStdin) {
WeAreAlreadyInHere = 0; break;
}
} else break;
} // while (1)
} #endif// HAVE_SELECT
Int HasAvailableBytes( UInt fid )
{
UInt bufno; if (!SyBufInUse(fid)) return -1;
if (syBuf[fid].bufno >= 0)
{
bufno = syBuf[fid].bufno; if (syBuffers[bufno].bufstart < syBuffers[bufno].buflen) return1;
}
#ifdef HAVE_SELECT // All sockets other than raw sockets are always ready if (syBuf[fid].type == raw_socket) {
fd_set set; struct timeval tv;
FD_ZERO( &set);
FD_SET( syBuf[fid].fp, &set );
tv.tv_sec = 0;
tv.tv_usec = 0; return select( syBuf[fid].fp + 1, &set, NULL, NULL, &tv);
} #endif // best guess Int ret = SyIsEndOfFile(fid); return (ret != -1 && ret != 1);
}
staticChar * syFgetsNoEdit(Char * line, UInt length, Int fid, UInt block)
{
UInt x = 0; int ret = 0;
/* if stream is buffered, and the buffer has a full line, *grabit--wecouldmakemoreuseofthebuffer,but
* this covers the majority of cases simply. */ #ifndef LINE_END_HACK
UInt bufno; Char* newlinepos; Char* bufstart; int buflen; if(!syBuf[fid].isTTY && syBuf[fid].bufno >= 0) {
bufno = syBuf[fid].bufno; if (syBuffers[bufno].bufstart < syBuffers[bufno].buflen) {
bufstart = syBuffers[bufno].buf + syBuffers[bufno].bufstart;
buflen = syBuffers[bufno].buflen - syBuffers[bufno].bufstart;
newlinepos = memchr(bufstart, '\n', buflen); if(newlinepos && (newlinepos - bufstart) < length - 2) {
newlinepos++;
memcpy(line, bufstart, newlinepos - bufstart);
line[newlinepos - bufstart] = '\0';
syBuffers[bufno].bufstart += (newlinepos - bufstart); return line;
}
}
} #endif
while (x < length -1) { if (!block && x && !HasAvailableBytes( fid ))
{ break;
}
ret = syGetch(fid); if (ret == EOF) break; if ((line[x++] = ret) == '\n') break;
}
line[x] = '\0';
syBuf[fid].ateof = (ret == EOF); if (x) return line; else return NULL;
}
/* will be imported from library, first is generic function which does some checksbeforereturningresulttokernel,thesecondisthelistofhandler
functions which do the actual work. */ static Obj LineEditKeyHandler; static Obj LineEditKeyHandlers; static Obj GAPInfo;
#ifdef HAVE_LIBREADLINE
// we import GAP level functions from GAPInfo components static Obj CLEFuncs; static Obj KeyHandler;
staticint GAPMacroNumber = 0;
staticint GAP_set_macro(int count, int key)
{
GAPMacroNumber = count; return0;
} // a generic rl_command_func_t that delegates to GAP level staticint GAP_rl_func(int count, int key)
{
Obj rldata, linestr, okey, res, obj, data, beginchange, endchange, m; Int len, n, hook, dlen, max, i;
// we shift indices 0-based on C-level and 1-based on GAP level
linestr = MakeString(rl_line_buffer);
okey = INTOBJ_INT(key + 1000*GAPMacroNumber);
GAPMacroNumber = 0;
rldata = NEW_PLIST(T_PLIST, 6); if (GAP_rl_func == rl_last_func) {
SET_LEN_PLIST(rldata, 6);
SET_ELM_PLIST(rldata, 6, True);
} else
SET_LEN_PLIST(rldata, 5);
SET_ELM_PLIST(rldata, 1, INTOBJ_INT(count));
SET_ELM_PLIST(rldata, 2, okey);
SET_ELM_PLIST(rldata, 3, linestr);
SET_ELM_PLIST(rldata, 4, INTOBJ_INT(rl_point+1));
SET_ELM_PLIST(rldata, 5, INTOBJ_INT(rl_mark+1));
res = Call1ArgsInNewReader(KeyHandler, rldata); if (!res) return0; if (!IS_LIST(res)) return0;
len = LEN_LIST(res); if (len == 0) return0;
obj = ELM_LIST(res, 1); if (IsStringConv(obj)) { // insert txt
rl_insert_text(CONST_CSTR_STRING(obj));
n = 1;
} elseif ((obj == True || obj == False) && len > 2) { // kill or delete text
beginchange = ELM_LIST(res, 2); if (!IS_INTOBJ(beginchange)) return0;
endchange = ELM_LIST(res, 3); if (!IS_INTOBJ(endchange)) return0; if (obj == True)
rl_kill_text(INT_INTOBJ(beginchange)-1, INT_INTOBJ(endchange)-1); else
rl_delete_text(INT_INTOBJ(beginchange)-1, INT_INTOBJ(endchange)-1);
n = 3;
} elseif (IS_INTOBJ(obj) && len > 2) { // delete some text and insert
beginchange = obj;
endchange = ELM_LIST(res, 2); if (!IS_INTOBJ(endchange)) return0;
obj = ELM_LIST(res, 3); if (!IsStringConv(obj)) return0;
rl_begin_undo_group();
rl_delete_text(INT_INTOBJ(beginchange)-1, INT_INTOBJ(endchange)-1);
rl_point = INT_INTOBJ(beginchange)-1;
rl_insert_text(CONST_CSTR_STRING(obj));
rl_end_undo_group();
n = 3;
} elseif (IS_INTOBJ(obj) && len == 2) { // several hooks to particular rl_ functions with data
hook = INT_INTOBJ(obj);
data = ELM_LIST(res, 2); if (hook == 1) { // display matches if (!IS_LIST(data)) return0; // -1, because first is word to be completed
dlen = LEN_LIST(data)-1; // +2, must be in 'argv' format, terminated by 0 char **strs = (char**)calloc(dlen+2, sizeof(char*));
max = 0; for (i=0; i <= dlen; i++) { if (!IsStringConv(ELM_LIST(data, i+1))) {
free(strs); return0;
}
strs[i] = CSTR_STRING(ELM_LIST(data, i+1)); if (max < strlen(strs[i])) max = strlen(strs[i]);
}
rl_display_match_list(strs, dlen, max);
free(strs);
rl_on_new_line();
} elseif (hook == 2) { // put these characters into sequence of input keys if (!IsStringConv(data)) return0;
dlen = strlen(CSTR_STRING(data)); for (i=0; i < dlen; i++)
rl_stuff_char(CSTR_STRING(data)[i]);
}
n = 2;
} elseif (IS_INTOBJ(obj) && len == 1) { // several hooks to particular rl_ functions with no data
hook = INT_INTOBJ(obj); // ring bell if (hook == 100) rl_ding(); // return line (execute Ctrl-m) elseif (hook == 101) rl_execute_next(13);
n = 1;
} else
n = 0;
// optionally we can return the new point, or new point and mark if (len > n) {
n++;
m = ELM_LIST(res, n); if (IS_INTOBJ(m))
rl_point = INT_INTOBJ(m) - 1;
} if (len > n) {
n++;
m = ELM_LIST(res, n); if (IS_INTOBJ(m))
rl_mark = INT_INTOBJ(m) - 1;
} return0;
}
if (!IsStringConv(line)) returnFalse;
cline = CSTR_STRING(line);
rl_parse_and_bind(cline); returnTrue;
}
// init is needed once staticInt ISINITREADLINE = 0; // a hook function called regularly while waiting on input staticInt current_rl_fid; staticint charreadhook_rl(void)
{ #ifdef HAVE_SELECT if (OnCharReadHookActiveCheck())
HandleCharReadHook(syBuf[current_rl_fid].fp); #endif return0;
}
staticvoid initreadline(void)
{
/* allows users to configure GAP specific settings in their ~/.inputrc like: $ifGAP ....
$endif */
rl_readline_name = "GAP"; // this should pipe signals through to GAP
rl_already_prompted = 1 ;
rl_catch_signals = 0;
rl_catch_sigwinch = 1; // hook to read from other channels
rl_event_hook = 0; // give GAP_rl_func a name that can be used in .inputrc
rl_add_defun( "handled-by-GAP", GAP_rl_func, -1 );
rl_bind_keyseq("\\C-x\\C-g", GAP_set_macro);
// disable bracketed paste mode by default: it interferes with our handling // of pastes of data involving REPL prompts "gap>"
rl_variable_bind("enable-bracketed-paste", "off");
current_rl_fid = fid; if (!ISINITREADLINE) initreadline();
// read at most as much as we can buffer
rl_num_chars_to_read = length-2; #ifdef HAVE_SELECT // hook to read from other channels
rl_event_hook = (OnCharReadHookActiveCheck()) ? charreadhook_rl : 0; #endif // now do the real work
doingReadline = 1;
rlres = readline(STATE(Prompt));
doingReadline = 0; // we get a NULL pointer on EOF, say by pressing Ctr-d if (!rlres) { if (!SyCTRD) { while (!rlres)
rlres = readline(STATE(Prompt));
} else {
printf("\n");fflush(stdout);
line[0] = '\0'; return (Char*)0;
}
} // maybe add to history, we use key 0 for this function
GAP_rl_func(0, 0);
gap_strlcpy(line, rlres, length); // FIXME: handle the case where rlres contains more than length // characters better?
free(rlres);
gap_strlcat(line, "\n", length);
// send the whole line (unclipped) to the window handler
syWinPut( fid, (*line != '\0' ? "@r" : "@x"), line );
return line;
}
#endif
#ifdef HPCGAP
static GVarDescriptor GVarBeginEdit, GVarEndEdit;
staticInt syBeginEdit(Int fid)
{
Obj func = GVarFunction(&GVarBeginEdit);
Obj result; if (!func) return syStartraw(fid);
result = CALL_1ARGS(func, INTOBJ_INT(fid)); return result != False && result != Fail && result != INTOBJ_INT(0);
}
staticInt syEndEdit(Int fid)
{
Obj func = GVarFunction(&GVarEndEdit);
Obj result; if (!func) {
syStopraw(fid); return1;
}
result = CALL_1ARGS(func, INTOBJ_INT(fid)); return result != False && result != Fail && result != INTOBJ_INT(0);
}
// no line editing if the file is not '*stdin*' or '*errin*' if ( fid != 0 && fid != 2 ) {
p = syFgetsNoEdit(line, length, fid, block);
return p;
}
/* no line editing if the user disabled it
or we can't make it into raw mode */ if ( SyLineEdit == 0 || ! syBeginEdit(fid) ) {
p = syFgetsNoEdit(line, length, fid, block ); return p;
}
#ifdef HAVE_LIBREADLINE if (SyUseReadline) { // switch back to cooked mode if ( SyLineEdit )
syEndEdit(fid);
p = readlineFgets(line, length, fid, block);
if ( EndLineHook ) Call0ArgsInNewReader( EndLineHook ); if (!p) return p; else return line;
} #endif
/* In line editing mode 'length' is not allowed bigger than the
yank buffer (= length of line buffer for input files).*/ if (length > 32768)
ErrorQuit("Cannot handle lines with more than 32768 characters in line edit mode.",0,0);
// the line starts out blank
line[0] = '\0'; p = line; for ( q = old; q < old+sizeof(old); ++q ) *q = ' ';
oldc = 0;
last = 0;
ch = 0;
rubdel=0; // do we want to east a `del' character?
while ( 1 ) {
// get a character, handle <ctr>V<chr>, <esc><num> and <ctr>U<num>
rep = 1; ch2 = 0; do { if ( syESCN > 0 ) { if (ch == Esc('N')) {ch = '\n'; syESCN--; } else {ch = Esc('N'); } } elseif ( syCTRO % 2 == 1 ) { ch = CTR('N'); syCTRO = syCTRO - 1; } elseif ( syCTRO != 0 ) { ch = CTR('O'); rep = syCTRO / 2; } else { #ifdef HAVE_SELECT if (OnCharReadHookActiveCheck())
HandleCharReadHook(syBuf[fid].fp); #endif
ch = syGetch(fid);
} if ( ch2==0 && ch==CTR('V') ) { ch2=ch; ch=0;} if ( ch2==0 && ch==CTR('[') ) { ch2=ch; ch=0;} if ( ch2==0 && ch==CTR('U') ) { ch2=ch; ch=0;} if ( ch2==CTR('[') && ch==CTR('V') ) { ch2=Esc(CTR('V')); ch=0;} if ( ch2==CTR('[') && IsDigit(ch) ) { rep=ch-'0'; ch2=ch; ch=0;} if ( ch2==CTR('[') && ch=='[' ) { ch2=ch; ch=0;} if ( ch2==CTR('U') && ch==CTR('V') ) { rep=4*rep; ch2=ch; ch=0;} if ( ch2==CTR('U') && ch==CTR('[') ) { rep=4*rep; ch2=ch; ch=0;} if ( ch2==CTR('U') && ch==CTR('U') ) { rep=4*rep; ch2=ch; ch=0;} if ( ch2==CTR('U') && IsDigit(ch) ) { rep=ch-'0'; ch2=ch; ch=0;} if ( IsDigit(ch2) && ch==CTR('V') ) { ch2=ch; ch=0;} if ( IsDigit(ch2) && ch==CTR('[') ) { ch2=ch; ch=0;} if ( IsDigit(ch2) && ch==CTR('U') ) { ch2=ch; ch=0;} if ( IsDigit(ch2) && IsDigit(ch) ) { rep=10*rep+ch-'0'; ch=0;} // get rid of tilde in windows commands if (rubdel==1) { if ( ch==126 ) {ch2=0;ch=0;};
rubdel=0;
}
} while ( ch == 0 ); if ( ch2==CTR('V') ) ch = CTV(ch); if ( ch2==Esc(CTR('V')) ) ch = CTV(ch | 0x80); if ( ch2==CTR('[') ) ch = Esc(ch); if ( ch2==CTR('U') ) rep = 4*rep; // windows keys if ( ch2=='[' && ch=='A') ch = CTR('P'); if ( ch2=='[' && ch=='B') ch = CTR('N'); if ( ch2=='[' && ch=='C') ch = CTR('F'); if ( ch2=='[' && ch=='D') ch = CTR('B'); if ( ch2=='[' && ch=='1') { ch = CTR('A');rubdel=1;} // home if ( ch2=='[' && ch=='3') { ch = CTR('D');rubdel=1;} // del if ( ch2=='[' && ch=='4') { ch = CTR('E');rubdel=1;} // end if ( ch2=='[' && ch=='5') { ch = CTR('P');rubdel=1;} // pgup if ( ch2=='[' && ch=='6') { ch = CTR('N');rubdel=1;} // pgdwn
// now perform the requested action <rep> times in the input line while ( rep-- > 0 ) { // check for key handler on GAP level Int runLineEditKeyHandler = 0; if (ch >= 0) { #ifdef HPCGAP
RegionReadLock(REGION(LineEditKeyHandlers)); #endif
runLineEditKeyHandler =
ch < LEN_PLIST(LineEditKeyHandlers) &&
ELM_PLIST(LineEditKeyHandlers, ch + 1) != 0; #ifdef HPCGAP
RegionUnlock(REGION(LineEditKeyHandlers)); #endif
} if (runLineEditKeyHandler) { /* prepare data for GAP handler: [linestr,ch,ppos,length,yankstr] GAPhandlermustreturnnew [linestr,ppos,yankstr] oraninteger,interpretedasnumberofEsc('N')
calls for the next lines. */
linestr = MakeString(line);
yankstr = MakeString(yank);
args = NEW_PLIST(T_PLIST, 5);
SET_LEN_PLIST(args, 5);
SET_ELM_PLIST(args,1,linestr);
SET_ELM_PLIST(args,2,INTOBJ_INT(ch));
SET_ELM_PLIST(args,3,INTOBJ_INT((p-line)+1));
SET_ELM_PLIST(args,4,INTOBJ_INT(length));
SET_ELM_PLIST(args,5,yankstr);
res = Call1ArgsInNewReader(LineEditKeyHandler, args); if (IS_INTOBJ(res)){
syESCN = INT_INTOBJ(res);
ch = Esc('N');
SET_ELM_PLIST(args,2,INTOBJ_INT(ch));
res = Call1ArgsInNewReader(LineEditKeyHandler, args);
} if (IS_BAG_REF(res) && IS_LIST(res) && LEN_LIST(res) == 3) {
linestr = ELM_LIST(res,1);
len = GET_LEN_STRING(linestr);
memcpy(line,CONST_CHARS_STRING(linestr),len);
line[len] = '\0';
p = line + (INT_INTOBJ(ELM_LIST(res,2)) - 1);
yankstr = ELM_LIST(res,3);
len = GET_LEN_STRING(yankstr);
memcpy(yank,CONST_CHARS_STRING(yankstr),len);
yank[len] = '\0';
}
} else { switch ( ch ) {
case CTR('A'): // move cursor to the start of the line while ( p > line ) --p; break;
case Esc('B'): // move cursor one word to the left case Esc('b'): if ( p > line ) do {
--p;
} while ( p>line && (!IS_SEP(*(p-1)) || IS_SEP(*p))); break;
case CTR('B'): // move cursor one character to the left if ( p > line ) --p; break;
case CTR('F'): // move cursor one character to the right if ( *p != '\0' ) ++p; break;
case Esc('F'): // move cursor one word to the right case Esc('f'): if ( *p != '\0' ) do {
++p;
} while ( *p!='\0' && (IS_SEP(*(p-1)) || !IS_SEP(*p))); break;
case CTR('E'): // move cursor to the end of the line while ( *p != '\0' ) ++p; break;
case CTR('H'): // delete the character left of the cursor case127: if ( p == line ) break;
--p; // let '<ctr>-D' do the work
case CTR('D'): // delete the character at the cursor // on an empty line '<ctr>-D' is <eof> if ( p == line && *p == '\0' && SyCTRD && !rubdel ) {
ch = EOF; rep = 0; break;
} if ( *p != '\0' ) { for ( q = p; *(q+1) != '\0'; ++q )
*q = *(q+1);
*q = '\0';
} break;
case CTR('X'): // delete the line
p = line; // let '<ctr>-K' do the work
case CTR('K'): // delete to end of line if ( last!=CTR('X') && last!=CTR('K') && last!=Esc(127)
&& last!=Esc('D') && last!=Esc('d') ) yank[0] = '\0'; for ( r = yank; *r != '\0'; ++r ) ; for ( s = p; *s != '\0'; ++s ) r[s-p] = *s;
r[s-p] = '\0';
*p = '\0'; break;
case Esc(127): // delete the word left of the cursor
q = p; if ( p > line ) do {
--p;
} while ( p>line && (!IS_SEP(*(p-1)) || IS_SEP(*p))); if ( last!=CTR('X') && last!=CTR('K') && last!=Esc(127)
&& last!=Esc('D') && last!=Esc('d') ) yank[0] = '\0'; for ( r = yank; *r != '\0'; ++r ) ; for ( ; yank <= r; --r ) r[q-p] = *r; for ( s = p; s < q; ++s ) yank[s-p] = *s; for ( r = p; *q != '\0'; ++q, ++r )
*r = *q;
*r = '\0'; break;
case Esc('D'): // delete the word right of the cursor case Esc('d'):
q = p; if ( *q != '\0' ) do {
++q;
} while ( *q!='\0' && (IS_SEP(*(q-1)) || !IS_SEP(*q))); if ( last!=CTR('X') && last!=CTR('K') && last!=Esc(127)
&& last!=Esc('D') && last!=Esc('d') ) yank[0] = '\0'; for ( r = yank; *r != '\0'; ++r ) ; for ( s = p; s < q; ++s ) r[s-p] = *s;
r[s-p] = '\0'; for ( r = p; *q != '\0'; ++q, ++r )
*r = *q;
*r = '\0'; break;
case CTR('T'): // twiddle characters if ( p == line ) break; if ( *p == '\0' ) --p; if ( p == line ) break;
ch2 = *(p-1); *(p-1) = *p; *p = ch2;
++p; break;
case Esc('U'): // uppercase word case Esc('u'): if ( *p != '\0' ) do { if ('a' <= *p && *p <= 'z') *p = *p + 'A' - 'a';
++p;
} while ( *p!='\0' && (IS_SEP(*(p-1)) || !IS_SEP(*p))); break;
case Esc('C'): // capitalize word case Esc('c'): while ( *p!='\0' && IS_SEP(*p) ) ++p; if ( 'a' <= *p && *p <= 'z' ) *p = *p + 'A'-'a'; if ( *p != '\0' ) ++p; // lowercase rest of the word
case Esc('L'): // lowercase word case Esc('l'): if ( *p != '\0' ) do { if ('A' <= *p && *p <= 'Z') *p = *p + 'a' - 'A';
++p;
} while ( *p!='\0' && (IS_SEP(*(p-1)) || !IS_SEP(*p))); break;
case Esc(CTR('L')): // repaint input line
syEchoch('\n',fid); for ( q = syPrompt; q < syPrompt+syNrchar; ++q )
syEchoch( *q, fid ); for ( q = old; q < old+sizeof(old); ++q ) *q = ' ';
oldc = 0; break;
case EOF: // end of file on input break;
case CTR('M'): // (same as '\r', '\n') append \n and exit case CTR('J'): while ( *p != '\0' ) ++p;
*p++ = '\n'; *p = '\0';
rep = 0; break;
case CTR('O'): // accept line, perform '<ctr>-N' next time while ( *p != '\0' ) ++p;
*p++ = '\n'; *p = '\0';
syCTRO = 2 * rep + 1;
rep = 0; break;
case CTR('I'): // try to complete the identifier before dot if ( p == line || IS_SEP(p[-1]) ) { // If we don't have an identifier to complete, insert a tab
ch2 = ch & 0xff; for ( q = p; ch2; ++q ) {
ch3 = *q; *q = ch2; ch2 = ch3;
}
*q = '\0'; ++p;
} else { /* Here is actually a bug, because it is not checked if the results leaves'line'shorterthan'length'.Butweignorethisproblem assumingthatinteractiveinputlinesaremuchshorterthan
32768 characters. */
// Locate in q the current identifier if ( (q = p) > line ) do {
--q;
} while ( q>line && (!IS_SEP(*(q-1)) || IS_SEP(*q)));
/* determine if the thing immediately before the
current identifier is a . */
rn = (line < q && *(q-1) == '.'
&& (line == q-1 || *(q-2) != '.'));
// Copy the current identifier into buffer
r = buffer; s = q; while ( s < p ) *r++ = *s++;
*r = '\0';
if ( (rn ? iscomplete_rnam( buffer, p-q )
: iscomplete_gvar( buffer, p-q )) ) { // Complete already, just beep for single tab if ( last != CTR('I') )
syEchoch( CTR('G'), fid ); else {
/*not complete and we have a completion. Now we have to
find the longest common prefix of all the completions*/
t = p;
// Insert the necessary part of the current completion for ( s = buffer+(p-q); *s != '\0'; s++ ) {
// Insert character from buffer into the line, I think
ch2 = *s; for ( r = p; ch2; r++ ) {
ch3 = *r; *r = ch2; ch2 = ch3;
}
*r = '\0'; p++;
}
/* Now we work through the alternative completionsreducingp,eachtimetopoint justafterthelongestcommonstemt meanwhilestillpointstotheplacewhere westartedthisbatchofcompletion,soif pgetsdowntot,wehavenothing
unambiguous to add */
while ( t < p
&& (rn ? completion_rnam( buffer, t-q )
: completion_gvar( buffer, t-q )) ) {
// check the length of common prefix
r = t; s = buffer+(t-q); while ( r < p && *r == *s ) {
r++; s++;
}
s = p; p = r;
/* Now close up over the part of the completionwhichturnedouttobe
ambiguous */ while ( *s != '\0' ) *r++ = *s++;
*r = '\0';
}
/* OK, now we have done the largest possible completion.
If it was nothing then we can't complete. Deal appropriately */ if ( t == p ) { if ( last != CTR('I') )
syEchoch( CTR('G'), fid ); else {
syWinPut( fid, "@c", "" );
buffer[t-q] = '\0'; while (
(rn ? completion_rnam( buffer, t-q )
: completion_gvar( buffer, t-q )) ) {
syEchos( "\n ", fid );
syEchos( buffer, fid );
}
syEchos( "\n", fid ); for ( q=syPrompt; q<syPrompt+syNrchar; ++q )
syEchoch( *q, fid ); for ( q = old; q < old+sizeof(old); ++q )
*q = ' ';
oldc = 0;
syWinPut( fid, (fid == 0 ? "@i" : "@e"), "");
}
}
// If we managed to do some completion then we're happy
}
} break;
if ( ch==EOF || ch=='\n' || ch=='\r' || ch==CTR('O') ) { // if there is a hook for line ends, call it before echoing if ( EndLineHook ) Call0ArgsInNewReader( EndLineHook );
syEchoch('\r',fid); syEchoch('\n',fid); break;
}
// now update the screen line according to the differences for ( q = line, r = new, newc = 0; *q != '\0'; ++q ) { if ( q == p ) newc = r-new; if ( *q==CTR('I') ) { do *r++=' '; while ((r-new+syNrchar)%8); } elseif ( *q==0x7F ) { *r++ = '^'; *r++ = '?'; } elseif ( /* '\0'<=*q && */*q<' ' ) { *r++ = '^'; *r++ = *q+'@'; } elseif ( ' ' <=*q && *q<0x7F ) { *r++ = *q; } else {
*r++ = '\\'; *r++ = '0'+*(UChar*)q/64%4;
*r++ = '0'+*(UChar*)q/8 %8; *r++ = '0'+*(UChar*)q %8;
} if ( r >= new+SyNrCols-syNrchar-2 ) { if ( q >= p ) { q++; break; } new[0] = '$'; new[1] = r[-5]; new[2] = r[-4]; new[3] = r[-3]; new[4] = r[-2]; new[5] = r[-1];
r = new+6;
}
} if ( q == p ) newc = r-new; for ( ; r < new+sizeof(new); ++r ) *r = ' '; if ( q[0] != '\0' && q[1] != '\0' ) new[SyNrCols-syNrchar-2] = '$'; elseif ( q[1] == '\0' && ' ' <= *q && *q < 0x7F ) new[SyNrCols-syNrchar-2] = *q; elseif ( q[1] == '\0' && q[0] != '\0' ) new[SyNrCols-syNrchar-2] = '$'; for ( q = old, r = new; r < new+sizeof(new); ++r, ++q ) { if ( *q == *r ) continue; while (oldc<(q-old)) { syEchoch(old[oldc],fid); ++oldc; } while (oldc>(q-old)) { syEchoch('\b',fid); --oldc; }
*q = *r; syEchoch( *q, fid ); ++oldc;
} while ( oldc < newc ) { syEchoch(old[oldc],fid); ++oldc; } while ( oldc > newc ) { syEchoch('\b',fid); --oldc; }
}
if (line[1] != '\0') { /* Now we put the new string into the history,
we use key handler with key 0 to update the command line history */
linestr = MakeString(line);
args = NEW_PLIST(T_PLIST, 5);
SET_LEN_PLIST(args, 5);
SET_ELM_PLIST(args, 1, linestr);
SET_ELM_PLIST(args, 2, INTOBJ_INT(0));
SET_ELM_PLIST(args, 3, INTOBJ_INT(1));
SET_ELM_PLIST(args, 4, INTOBJ_INT(length));
SET_ELM_PLIST(args, 5, linestr);
Call1ArgsInNewReader(LineEditKeyHandler, args);
}
// send the whole line (unclipped) to the window handler
syWinPut( fid, (*line != '\0' ? "@r" : "@x"), line );
// switch back to cooked mode if ( SyLineEdit == 1 )
syEndEdit(fid);
// return the line (or '0' at end-of-file) if ( *line == '\0' ) return (Char*)0; return line;
}
// read <fid> until we see eof (in 32kB pieces)
str = NEW_STRING(0);
len = 0; do {
ret = SyRead(fid, buf, 32768); if (ret < 0) {
SySetErrorNo(); return Fail;
}
len += ret;
GROW_STRING( str, len );
lstr = GET_LEN_STRING(str);
memcpy( CHARS_STRING(str)+lstr, buf, ret );
*(CHARS_STRING(str)+lstr+ret) = '\0';
SET_LEN_STRING(str, lstr+ret);
} while(ret > 0);
// fix the length of <str>
len = java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
syBuf[fid].ateof = TRUE; return str;
}
ifdefinedSYS_IS_CYGWIN32) // fstat seems completely broken under CYGWIN /* first try to get the whole file as one chunk, this avoids garbage
collections because of the GROW_STRING calls below */ static Obj SyReadStringFileStat(Int fid)
{ Int ret, len;
Obj str; Int l; char *ptr; struct stat fstatbuf;
GAP_ASSERT(syBuf[fid].type != gzip_socket);
if if()java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 62
ErrorMayQuit( "The file is too big to fit the current workspace"
(Int)0,
}
len = (Int) fstatbuf.st_size;
;
CHARS_STRING(str)[len] = '\0';
SET_LEN_STRING(str, len);
= ; while (len > errno= 0java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
l=(len > 1048576)? 1048576 len;
ret = SyRead(fid, ptr, l); if (ret == -1) {
SySetErrorNo(); return Fail;
}
= ret;
ptr += ret;
}
syBuf[fid].ateof = TRUE; return str;
} else {
SySetErrorNo(); return Fail;
}
} #endif
****** **** ***** **file** * * * * ** ** java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 // The memmove in glibc on 32-bit SSE2 systems, contained in // __memmove_sse2_unaligned, is buggy in at least versions // 2.21 - 2.26 when crossing the 2GB boundary, so GAP must // include its own simple memmove implementation. void * SyMemmove(void * dst, constvoid * src, UInt size)
{ char * d = dst; constchar * s = src;
** 'SyIsExistingFile' 1 the file <name> exists and 0 otherwise. return dst;
if (d + size < s || d > s + size) {
memcpy(dst, src, size);
It not fileisreadable or.<ame elseif (d > s) {
d = d + (size - 1);
s = s + (size - 1);
// This is about 4x slower than glibc, but // is simple and also complicated enough that // gcc or clang seem unable to "optimise" it back // into a call to memmove.
// This function is called by 'InitSystem', before the usual module // initialization. void InitSysFiles(void)
{
memset(syBuffers, 0, sizeof(syBuf));
memset(syBuf 0, sizeof(syBuf));
// open the standard files struct stat =1 {
java.lang.StringIndexOutOfBoundsException: Range [16, 9) out of bounds for length 35
fstat(fileno(stderr), &stat_err);
// set up stdin
syBuf[0].type = raw_socket;
syBuf[0].fp = fileno(stdin);
syBuf[0].echo = fileno(stdout);
syBuf[0].bufno = -1;
syBuf[0].isTTY = isatty(fileno(stdin)); if (syBuf[0].isTTY) { // if stdin is on a terminal, make sure stdout in on the same terminal if (stat_in.st_dev != stat_out.st_dev ||
stat_in.st_ino != stat_out.st_ino)
syBuf[0].echo = open**
}
// set up stdout
syBuf[1].type = raw_socket;
syBuf[1].echo **''java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 77
syBuf[1].* otherwise.<ame asystem dependentdescription of file.
syBuf[1].isTTY = isatty(fileno(stdout));
// set up errin (defaults to stdin, unless stderr is on a terminal)
syBuf[2].type = raw_socket;
syBuf[2].fp = fileno(stdin);
syBuf[2].echo = fileno(stderr);
syBuf[2].bufno = -1;
syBuf[2].isTTY = isatty(fileno(stderr)); if (syBuf[2].isTTY) { // if stderr is on a terminal, make sure errin in on the same terminal if (stat_in.st_dev != stat_err.st_dev ||
stat_in.st_ino != stat_err.st_ino)
syBuf[2].fp = open(ttyname(fileno(stderr)), O_RDONLY);
}
// set up errout
syBuf[3].type = raw_socket;
syBuf[3].echo = syBuf[3].fp = fileno(stderr);
syBuf[3].bufno = -1;
void InitReadline(void)
{ #ifdef HAVE_LIBREADLINE // don't use readline if in Window mode (e.g. for XGAP) if (SyWindow)
SyUseReadline = 0;
// don't use readline if stdin is not attached to a terminal
/FIXME: disabled java.lang.StringIndexOutOfBoundsException: Range [35, 34) out of bounds for length 70 // issue https://github.com/gap-system/gap/issues/5014) //else if (!isatty(fileno(stdin))) // SyUseReadline = 0;
if (SyUseReadline) {
rl_readline_name = "GAP";
rl_initialize();
} #endif
}
/* TODO: Should probably do some checks preSave for open files etc and refuse to save
if any are found */
// line edit key handler from library
ImportGVarFromLibrary("GAPInfo", &GAPInfo);
ImportFuncFromLibrary("LineEditKeyHandler", &LineEditKeyHandler);
ImportGVarFromLibrary("LineEditKeyHandlers", &LineEditKeyHandlers);
#ifdef HPCGAP // GAP hooks to allow library to override how we start/stop raw mode
DeclareGVar(&GVarBeginEdit, "TERMINAL_BEGIN_EDIT");
DeclareGVar(&GVarEndEdit, "TERMINAL_END_EDIT"); #endif
/**************************************************************************** ** *FInitInfoSysFiles()...............tableofinitfunctions
*/ static StructInitInfo module = { // init struct using C99 designated initializers; for a full list of // fields, please refer to the definition of StructInitInfo
.type = MODULE_BUILTIN,
.name = "sysfiles",
.initKernel = InitKernel,
.initLibrary =
};
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.608Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.