This is system.c in view mode; [Download] [Up]
/**************************************************************************** ** *A system.c GAP source Martin Schoenert *A & Frank Celler (MACH) *A & Steve Linton (MS-DOS) *A & Harald Boegeholz (OS/2) *A & Paul Doyle (VMS) *A & Dave Bayer (MAC) *A & Burkhard Hoefling (MAC) ** *H @(#)$Id: system.c,v 3.5.1.5 1995/05/18 12:54:49 mschoene Rel $ ** *Y Copyright (C) 1993, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany ** ** The file 'system.c' contains all operating system dependent functions. ** The following labels determine which operating system is actually used. ** ** SYS_IS_BSD ** For Berkeley UNIX systems, such as 4.2 BSD, 4.3 BSD, free 386BSD, ** and DEC's Ultrix. ** ** SYS_IS_USG ** For System V UNIX systems, such as SUN's SunOS 4.0, Hewlett Packard's ** HP-UX, Masscomp's RTU, free Linux, and MIPS Risc/OS. ** ** SYS_IS_MACH ** For Mach derived systems, such as NeXT's NextStep. ** ** SYS_IS_OS2_EMX ** For OS/2 2.x and DOS with the EMX port of the GNU C compiler. ** ** SYS_IS_MSDOS_DJGPP ** For MS-DOS with Delories port of the GNU C compiler. ** ** SYS_IS_TOS_GCC2 ** For Atari's TOS with the port of the GNU C compiler. ** ** SYS_IS_VMS ** For DEC's VMS 5.0 or later with the VAX C compiler 3.0 or later. ** ** SYS_IS_MAC_MPW ** For Apple's Macintosh with the Mac Programmers Workshop compiler. ** ** SYS_IS_MAC_SYC ** For Apple's Macintosh with the Symantec C++ 7.0 (or Think C 6.0) ** compiler. ** ** Also the file contains prototypes for all the system calls and/or library ** function used as defined in ``Harbison & Steele, A C Reference Manual''. ** ** If there is a prototype in an include file and it does not agree with ** this one, then the compiler will signal an error or warning, and you can ** manually check whether the incompatibility is critical or quite harmless. ** If there is a prototype in an include file and it agrees with this one, ** then the compiler will be silent. If there is no prototype in an include ** file, the compiler cannot check, but then the prototype does no harm. ** ** Unfortunately there can be some incompatibilities with the prototypes in ** the include files. To overcome this difficulties it is possible to ** change or undefine the prototypes with the following symbols. They ** should be added to the 'Makefile' if neccessary. ** ** SYS_HAS_ANSI=<ansi> ** Some functions have different prototypes in ANSI and traditional C. ** For compilers that are ANSI the default uses the ANSI prototypes, ** and you use the traditional prototypes by defining 'SYS_HAS_ANSI=0'. ** For non ANSI compilers the default uses the traditional prototypes, ** and you can use the ANSI prototypes by defining 'SYS_HAS_ANSI=1'. ** ** SYS_HAS_CONST=<const_q> ** Some functions do not modifiy some of their arguments, and have ** thus 'const' qualifiers for those arguments in their prototypes. ** For compilers that are ANSI the default uses the const qualifiers, ** and you can remove the const qualifiers by defining 'SYS_HAS_CONST='. ** For compilers that are not ANSI the default does not use the const ** qualifiers and you can use them by defining 'SYS_HAS_CONST=const'. ** ** SYS_HAS_SIG_T=<sig_t> ** Use this to define the type of the value returned by signal handlers. ** This should be either 'void' (default, ANSI C) or 'int' (older UNIX). ** ** SYS_HAS_STDIO_PROTO ** Use this to undefine the prototypes for 'fopen', 'fclose', 'setbuf', ** 'fgets', 'fputs', 'read', and 'write'. ** ** SYS_HAS_READ_PROTO ** Use this to undefine the prototypes for 'read' and 'write'. ** ** SYS_HAS_STRING_PROTO ** Use this to undefine the prototypes for 'strncat', 'strcmp', and ** 'strlen'. ** ** SYS_HAS_IOCTL_PROTO ** Use this to undefine the prototype for 'ioctl'. ** ** SYS_HAS_SIGNAL_PROTO ** Use this to undefine the prototypes for 'signal', 'getpid', and ** 'kill'. ** ** SYS_HAS_TIME_PROTO ** Use this to undefine the prototypes for 'time', 'times', and ** 'getrusage'. ** ** SYS_HAS_MALLOC_PROTO ** Use this to undefine the prototypes for 'malloc' and 'free'. ** ** SYS_HAS_MISC_PROTO ** Use this to undefine the prototypes for 'exit', 'system', 'tmpnam', ** 'sbrk', 'getenv', 'atoi', 'isatty', and 'ttyname'. ** ** SYS_HAS_BROKEN_STRNCAT ** Use this if your 'strncat' is broken. At least in SCO ODT2.0 ** (SVR3.2) 'strncat' has problems if the len is a multiple of 4. ** *H $Log: system.c,v $ *H Revision 3.5.1.5 1995/05/18 12:54:49 mschoene *H fixed 'SyHelp', manual now has more than 64 chapters *H *H Revision 3.5.1.4 1995/05/18 03:23:21 mschoene *H added Macintosh support by Burkhard Hoefling *H *H Revision 3.5.1.3 1995/05/11 14:52:23 mschoene *H fixed 'SyHelp' to tolerate funny table of contents lines *H *H Revision 3.5.1.2 1994/09/07 07:08:50 fceller *H added SYS_HAS_BROKEN_STRNCAT *H *H Revision 3.5.1.1 1994/09/06 10:15:02 fceller *H added '-r' option to avoid reading of the .gaprc file *H *H Revision 3.5 1993/12/17 07:26:32 mschoene *H changed signal handlers to accept the signal number, which they ignore *H *H Revision 3.4 1993/12/17 07:17:51 mschoene *H included Harald's changes for OS/2 *H *H Revision 3.3 1993/10/29 12:01:33 martin *H fixed 'SyFgets' to copy terminating '\0' *H *H Revision 3.2 1993/10/27 10:16:29 martin *H do not buffer 'stderr' under MS-DOS and TOS, use '\\' under MS-DOS and TOS *H *H Revision 3.1 1993/10/18 12:45:07 martin *H initial revision under RCS (of the new system file) *H */ #include "system.h" /* declaration part of the package */ #ifdef SYS_HAS_ANSI # define SYS_ANSI SYS_HAS_ANSI #else # ifdef __STDC__ # define SYS_ANSI 1 # else # define SYS_ANSI 0 # endif #endif #ifdef SYS_HAS_CONST # define SYS_CONST SYS_HAS_CONST #else # ifdef __STDC__ # define SYS_CONST const # else # define SYS_CONST # endif #endif /**************************************************************************** ** *V SyFlags . . . . . . . . . . . . . . . . . . . . flags used when compiling ** ** 'SyFlags' is the name of the target for which GAP was compiled. ** ** It is '[bsd|mach|usg|os2|msdos|tos|vms|mac] [gcc|emx|djgpp|mpw|syc] [ansi]'. ** ** It is used in 'InitGap' for the 'VERSYS' variable. */ char SyFlags [] = { #ifdef SYS_IS_BSD 'b', 's', 'd', # define SYS_BSD 1 #else # define SYS_BSD 0 #endif #ifdef SYS_IS_MACH 'm', 'a', 'c', 'h', # define SYS_MACH 1 #else # define SYS_MACH 0 #endif #ifdef SYS_IS_USG 'u', 's', 'g', # define SYS_USG 1 #else # define SYS_USG 0 #endif #ifdef SYS_IS_OS2_EMX 'o', 's', '2', ' ', 'e', 'm', 'x', # define SYS_OS2_EMX 1 #else # define SYS_OS2_EMX 0 #endif #ifdef SYS_IS_MSDOS_DJGPP 'm', 's', 'd', 'o', 's', ' ', 'd', 'j', 'g', 'p', 'p', # define SYS_MSDOS_DJGPP 1 #else # define SYS_MSDOS_DJGPP 0 #endif #ifdef SYS_IS_TOS_GCC2 't', 'o', 's', ' ', 'g', 'c', 'c', '2', # define SYS_TOS_GCC2 1 #else # define SYS_TOS_GCC2 0 #endif #ifdef SYS_IS_VMS 'v', 'm', 's', # define SYS_VMS 1 #else # define SYS_VMS 0 #endif #ifdef __MWERKS__ # define SYS_IS_MAC_MPW # define SYS_HAS_CALLOC_PROTO #endif #ifdef SYS_IS_MAC_MPW 'm', 'a', 'c', ' ', 'm', 'p', 'w', # define SYS_MAC_MPW 1 #else # define SYS_MAC_MPW 0 #endif #ifdef SYS_IS_MAC_SYC 'm', 'a', 'c', ' ', 's', 'y', 'c', # define SYS_MAC_SYC 1 #else # define SYS_MAC_SYC 0 #endif #if __GNUC__ ' ', 'g', 'c', 'c', #endif #if SYS_ANSI ' ', 'a', 'n', 's', 'i', #endif #ifdef SYS_HAS_BROKEN_STRNCAT ' ', 's', 't', 'r', 'n', 'c', 'a', 't', #endif '\0' }; /**************************************************************************** ** *V SyStackSpace . . . . . . . . . . . . . . . . . . . amount of stack space ** ** 'SyStackSpace' is the amount of stackspace that GAP gets. ** ** Under TOS and on the Mac special actions must be taken to ensure that ** enough space is available. */ #if SYS_TOS_GCC2 # define __NO_INLINE__ int _stksize = 64 * 1024; /* GNU C, amount of stack space */ long SyStackSpace = 64 * 1024; #endif #if SYS_MAC_MPW || SYS_MAC_SYC long SyStackSpace = 64 * 1024; #endif /**************************************************************************** ** *V SyLibname . . . . . . . . . . . . . . . . . name of the library directory ** ** 'SyLibname' is the name of the directory where the GAP library files are ** located. ** ** This is per default the subdirectory 'lib/' of the current directory. ** It is usually changed with the '-l' option in the script that starts GAP. ** ** Is copied into the GAP variable called 'LIBNAME' and used by 'Readlib'. ** This is also used in 'LIBNAME/init.g' to find the group library directory ** by replacing 'lib' with 'grp', etc. ** ** It must end with the pathname seperator, eg. if 'init.g' is the name of a ** library file 'strcat( SyLibname, "init.g" );' must be a valid filename. ** Further neccessary transformation of the filename are done in 'SyOpen'. ** ** Put in this package because the command line processing takes place here. */ #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX char SyLibname [256] = "lib/"; #endif #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 char SyLibname [256] = "lib\\"; #endif #if SYS_VMS char SyLibname [256] = "[.lib]"; #endif #if SYS_MAC_MPW || SYS_MAC_SYC char SyLibname [256] = ":lib:"; #endif /**************************************************************************** ** *V SyHelpname . . . . . . . . . . . . . . name of the online help directory ** ** 'SyHelpname' is the name of the directory where the GAP online help files ** are located. ** ** By default it is computed from 'SyLibname' by replacing 'lib' with 'doc'. ** It can be changed with the '-h' option. ** ** It is used by 'SyHelp' to find the online documentation. */ char SyHelpname [256]; /**************************************************************************** ** *V SyBanner . . . . . . . . . . . . . . . . . . . . . . . . surpress banner ** ** 'SyBanner' determines whether GAP should print the banner. ** ** Per default it is true, i.e., GAP prints the nice banner. It can be ** changed by the '-b' option to have GAP surpress the banner. ** ** It is copied into the GAP variable 'BANNER', which is used in 'init.g'. ** ** Put in this package because the command line processing takes place here. */ long SyBanner = 1; /**************************************************************************** ** *V SyQuiet . . . . . . . . . . . . . . . . . . . . . . . . . surpress prompt ** ** 'SyQuit' determines whether GAP should print the prompt and the banner. ** ** Per default its false, i.e. GAP prints the prompt and the nice banner. ** It can be changed by the '-q' option to have GAP operate in silent mode. ** ** It is used by the functions in 'gap.c' to surpress printing the prompts. ** Is also copied into the GAP variable 'QUIET' which is used in 'init.g'. ** ** Put in this package because the command line processing takes place here. */ long SyQuiet = 0; /**************************************************************************** ** *V SyNrCols . . . . . . . . . . . . . . . . . . length of the output lines ** ** 'SyNrCols' is the length of the lines on the standard output device. ** ** Per default this is 80 characters which is the usual width of terminals. ** It can be changed by the '-x' options for larger terminals or printers. ** ** 'Pr' uses this to decide where to insert a <newline> on the output lines. ** 'SyRead' uses it to decide when to start scrolling the echoed input line. ** ** Put in this package because the command line processing takes place here. */ long SyNrCols = 80; /**************************************************************************** ** *V SyNrRows . . . . . . . . . . . . . . . . . number of lines on the screen ** ** 'SyNrRows' is the number of lines on the standard output device. ** ** Per default this is 24, which is the usual size of terminal screens. ** It can be changed with the '-y' option for larger terminals or printers. ** ** 'SyHelp' uses this to decide where to stop with '-- <space> for more --'. */ long SyNrRows = 24; /**************************************************************************** ** *V SyGasman . . . . . . . . . . . . . . . . . . . . enable gasman messages ** ** 'SyGasman' determines whether garabage collections are reported or not. ** ** Per default it is false, i.e. Gasman is silent about garbage collections. ** It can be changed by using the '-g' option on the GAP command line. ** ** This is used in 'CollectGarbage' to decide whether to be silent or not. ** ** Put in this package because the command line processing takes place here. */ long SyGasman = 0; /**************************************************************************** ** *V SyMemory . . . . . . . . . . . . . . default size for initial workspace ** ** 'SyMemory' is the size of the initial workspace allocated by Gasman. ** ** This is per default 4 Megabyte, which is often a reasonable value. ** It is usually changed with the '-m' option in the script that starts GAP. ** ** This value is used in 'InitGasman' to allocate the initial workspace. ** ** Put in this package because the command line processing takes place here. */ #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX long SyMemory = 4 * 1024 * 1024; #endif #if SYS_MSDOS_DJGPP long SyMemory = 4 * 1024 * 1024; #endif #if SYS_TOS_GCC2 long SyMemory = 0; #endif #if SYS_VMS long SyMemory = 4 * 1024 * 1024; #endif #if SYS_MAC_MPW || SYS_MAC_SYC long SyMemory = 0; #endif /**************************************************************************** ** *V SyInitfiles[] . . . . . . . . . . . list of filenames to be read in init ** ** 'SyInitfiles' is a list of file to read upon startup of GAP. ** ** It contains the 'init.g' file and a user specific init file if it exists. ** It also contains all names all the files specified on the command line. ** ** This is used in 'InitGap' which tries to read those files upon startup. ** ** Put in this package because the command line processing takes place here. ** ** For UNIX this list contains 'LIBNAME/init.g' and '$HOME/.gaprc'. */ char SyInitfiles [16] [256]; /**************************************************************************** ** *V syWindow . . . . . . . . . . . . . . . . running under a window handler ** ** 'syWindow' is 1 if GAP is running under a window handler front end such ** as 'xgap', and 0 otherwise. ** ** If running under a window handler front end, GAP adds various commands ** starting with '@' to the output to let 'xgap' know what is going on. */ long syWindow = 0; /**************************************************************************** ** *V syStartTime . . . . . . . . . . . . . . . . . . time when GAP was started *V syStopTime . . . . . . . . . . . . . . . . . . time when reading started */ unsigned long syStartTime; unsigned long syStopTime; /**************************************************************************** ** *F IsAlpha( <ch> ) . . . . . . . . . . . . . is a character a normal letter *F IsDigit( <ch> ) . . . . . . . . . . . . . . . . . is a character a digit ** ** 'IsAlpha' returns 1 if its character argument is a normal character from ** the range 'a..zA..Z' and 0 otherwise. ** ** 'IsDigit' returns 1 if its character argument is a digit from the range ** '0..9' and 0 otherwise. ** ** 'IsAlpha' and 'IsDigit' are implemented in the declaration part of this ** package as follows: ** #include <ctype.h> #define IsAlpha(ch) (isalpha(ch)) #define IsDigit(ch) (isdigit(ch)) */ /**************************************************************************** ** *F SyStrlen( <str> ) . . . . . . . . . . . . . . . . . . length of a string ** ** 'SyStrlen' returns the length of the string <str>, i.e., the number of ** characters in <str> that precede the terminating null character. */ #ifndef SYS_STRING_H /* string functions */ # include <string.h> # define SYS_STRING_H #endif #ifndef SYS_HAS_STRING_PROTO /* ANSI/TRAD decl. from H&S 13 */ # if SYS_ANSI extern char * strncat P(( char *, SYS_CONST char *, size_t )); extern int strcmp P(( SYS_CONST char *, SYS_CONST char * )); extern size_t strlen P(( SYS_CONST char * )); # else extern char * strncat P(( char *, SYS_CONST char *, int )); extern int strcmp P(( SYS_CONST char *, SYS_CONST char * )); extern int strlen P(( SYS_CONST char * )); # endif #endif long SyStrlen ( str ) char * str; { return strlen( str ); } /**************************************************************************** ** *F SyStrcmp( <str1>, <str2> ) . . . . . . . . . . . . . compare two strings ** ** 'SyStrcmp' returns an integer greater than, equal to, or less than zero ** according to whether <str1> is greater than, equal to, or less than ** <str2> lexicographically. */ long SyStrcmp ( str1, str2 ) char * str1; char * str2; { return strcmp( str1, str2 ); } /**************************************************************************** ** *F SyStrncat( <dst>, <src>, <len> ) . . . . . append one string to another ** ** 'SyStrncat' appends characters from the <src> to <dst> until either a ** null character is encoutered or <len> characters have been copied. ** <dst> becomes the concatenation of <dst> and <src>. The resulting string ** is always null terminated. 'SyStrncat' returns a pointer to <dst>. */ #ifdef SYS_HAS_BROKEN_STRNCAT char * SyStrncat ( dst, src, len ) char * dst; char * src; long len; { char * p; char * q; for ( p = dst; *p; p++ ) ; for ( q = src; *q && 0 < len; len-- ) *p++ = *q++; *p = 0; return dst; } #else char * SyStrncat ( dst, src, len ) char * dst; char * src; long len; { return strncat( dst, src, len ); } #endif /**************************************************************************** ** *V 'syBuf' . . . . . . . . . . . . . buffer and other info for files, local ** ** 'syBuf' is a array used as buffers for file I/O to prevent the C I/O ** routines from allocating theis buffers using 'malloc', which would ** otherwise confuse Gasman. */ #ifndef SYS_STDIO_H /* standard input/output functions */ # include <stdio.h> # define SYS_STDIO_H #endif #ifndef SYS_HAS_STDIO_PROTO /* ANSI/TRAD decl. from H&S 15 */ extern FILE * fopen P(( SYS_CONST char *, SYS_CONST char * )); extern int fclose P(( FILE * )); extern void setbuf P(( FILE *, char * )); extern char * fgets P(( char *, int, FILE * )); extern int fputs P(( SYS_CONST char *, FILE * )); #endif struct { FILE * fp; /* file pointer for this file */ FILE * echo; /* file pointer for the echo */ char buf [BUFSIZ]; /* the buffer for this file */ } syBuf [16]; /**************************************************************************** ** *F SyFopen( <name>, <mode> ) . . . . . . . . open the file with name <name> ** ** The function 'SyFopen' is called to open the file with the name <name>. ** If <mode> is "r" it is opened for reading, in this case it must exist. ** If <mode> is "w" it is opened for writing, it is created if neccessary. ** If <mode> is "a" it is opened for appending, i.e., it is not truncated. ** ** 'SyFopen' returns an integer used by the scanner to identify the file. ** 'SyFopen' returns -1 if it cannot open the file. ** ** The following standard files names and file identifiers are guaranteed: ** 'SyFopen( "*stdin*", "r")' returns 0 identifying the standard input file. ** 'SyFopen( "*stdout*","w")' returns 1 identifying the standard outpt file. ** 'SyFopen( "*errin*", "r")' returns 2 identifying the brk loop input file. ** 'SyFopen( "*errout*","w")' returns 3 identifying the error messages file. ** ** If it is necessary to adjust the filename this should be done here. ** Right now GAP does not read nonascii files, but if this changes sometimes ** 'SyFopen' must adjust the mode argument to open the file in binary mode. */ long SyFopen ( name, mode ) char * name; char * mode; { long fid; /* handle standard files */ if ( SyStrcmp( name, "*stdin*" ) == 0 ) { if ( SyStrcmp( mode, "r" ) != 0 ) return -1; return 0; } else if ( SyStrcmp( name, "*stdout*" ) == 0 ) { if ( SyStrcmp( mode, "w" ) != 0 ) return -1; return 1; } else if ( SyStrcmp( name, "*errin*" ) == 0 ) { if ( SyStrcmp( mode, "r" ) != 0 ) return -1; if ( syBuf[2].fp == (FILE*)0 ) return -1; return 2; } else if ( SyStrcmp( name, "*errout*" ) == 0 ) { if ( SyStrcmp( mode, "w" ) != 0 ) return -1; return 3; } /* try to find an unused file identifier */ for ( fid = 4; fid < sizeof(syBuf)/sizeof(syBuf[0]); ++fid ) if ( syBuf[fid].fp == (FILE*)0 ) break; if ( fid == sizeof(syBuf)/sizeof(syBuf[0]) ) return (long)-1; /* try to open the file */ syBuf[fid].fp = fopen( name, mode ); if ( syBuf[fid].fp == (FILE*)0 ) return (long)-1; /* allocate the buffer */ setbuf( syBuf[fid].fp, syBuf[fid].buf ); /* return file identifier */ return fid; } /**************************************************************************** ** *F SyFclose( <fid> ) . . . . . . . . . . . . . . . . . close the file <fid> ** ** 'SyFclose' closes the file with the identifier <fid> which is obtained ** from 'SyFopen'. */ void SyFclose ( fid ) long fid; { /* check file identifier */ if ( syBuf[fid].fp == (FILE*)0 ) { fputs("gap: panic 'SyFclose' asked to close closed file!\n",stderr); SyExit( 1 ); } /* refuse to close the standard files */ if ( fid == 0 || fid == 1 || fid == 2 || fid == 3 ) { return; } /* try to close the file */ if ( fclose( syBuf[fid].fp ) == EOF ) { fputs("gap: 'SyFclose' cannot close file, ",stderr); fputs("maybe your file system is full?\n",stderr); } /* mark the buffer as unused */ syBuf[fid].fp = (FILE*)0; } /**************************************************************************** ** *F SyFgets( <line>, <lenght>, <fid> ) . . . . . get a line from file <fid> ** ** 'SyFgets' is called to read a line from the file with identifier <fid>. ** 'SyFgets' (like 'fgets') reads characters until either <length>-1 chars ** have been read or until a <newline> or an <eof> character is encoutered. ** It retains the '\n' (unlike 'gets'), if any, and appends '\0' to <line>. ** 'SyFgets' returns <line> if any char has been read, otherwise '(char*)0'. ** ** 'SyFgets' allows to edit the input line if the file <fid> refers to a ** terminal with the following commands: ** ** <ctr>-A move the cursor to the beginning of the line. ** <esc>-B move the cursor to the beginning of the previous word. ** <ctr>-B move the cursor backward one character. ** <ctr>-F move the cursor forward one character. ** <esc>-F move the cursor to the end of the next word. ** <ctr>-E move the cursor to the end of the line. ** ** <ctr>-H, <del> delete the character left of the cursor. ** <ctr>-D delete the character under the cursor. ** <ctr>-K delete up to the end of the line. ** <esc>-D delete forward to the end of the next word. ** <esc>-<del> delete backward to the beginning of the last word. ** <ctr>-X delete entire input line, and discard all pending input. ** <ctr>-Y insert (yank) a just killed text. ** ** <ctr>-T exchange (twiddle) current and previous character. ** <esc>-U uppercase next word. ** <esc>-L lowercase next word. ** <esc>-C capitalize next word. ** ** <tab> complete the identifier before the cursor. ** <ctr>-L insert last input line before current character. ** <ctr>-P redisplay the last input line, another <ctr>-P will redisplay ** the line before that, etc. If the cursor is not in the first ** column only the lines starting with the string to the left of ** the cursor are taken. The history is limitied to ~8000 chars. ** <ctr>-N Like <ctr>-P but goes the other way round through the history ** <esc>-< goes to the beginning of the history. ** <esc>-> goes to the end of the history. ** <ctr>-O accept this line and perform a <ctr>-N. ** ** <ctr>-V enter next character literally. ** <ctr>-U execute the next command 4 times. ** <esc>-<num> execute the next command <num> times. ** <esc>-<ctr>-L repaint input line. ** ** Not yet implemented commands: ** ** <ctr>-S search interactive for a string forward. ** <ctr>-R search interactive for a string backward. ** <esc>-Y replace yanked string with previously killed text. ** <ctr>-_ undo a command. ** <esc>-T exchange two words. */ extern int syStartraw P(( long fid )); extern void syStopraw P(( long fid )); extern int syGetch P(( long fid )); #if SYS_MAC_SYC extern int syGetch2 P(( long fid, int cur )); #endif extern void syEchoch P(( int ch, long fid )); extern void syEchos P(( char * str, long fid )); extern unsigned long iscomplete P(( char * name, unsigned long len, unsigned long rn )); extern unsigned long completion P(( char * name, unsigned long len, unsigned long rn )); extern void syWinPut P(( long fid, char * cmd, char * str )); long syLineEdit = 1; /* 0: no line editing */ /* 1: line editing if terminal */ /* 2: always line editing (EMACS) */ long syCTRD = 1; /* true if '<ctr>-D' is <eof> */ long syNrchar; /* nr of chars already on the line */ char syPrompt [256]; /* characters alread on the line */ char syHistory [8192]; /* history of command lines */ char * syHi = syHistory; /* actual position in history */ int syCTRO; /* number of '<ctr>-O' pending */ #define CTR(C) ((C) & 0x1F) /* <ctr> character */ #define ESC(C) ((C) | 0x100) /* <esc> character */ #define CTV(C) ((C) | 0x200) /* <ctr>V quotes characters */ #define IS_SEP(C) (!IsAlpha(C) && !IsDigit(C) && (C)!='_') char * SyFgets ( line, length, fid ) char line []; long length; long fid; { int ch, ch2, ch3, last; char * p, * q, * r, * s, * t; char * h; static char yank [512]; char old [512], new [512]; int oldc, newc; int rep; char buffer [512]; int rn; /* no line editing if the file is not '*stdin*' or '*errin*' */ if ( fid != 0 && fid != 2 ) { p = fgets( line, (int)length, syBuf[fid].fp ); return p; } /* no line editing if the user disabled it */ if ( syLineEdit == 0 ) { syStopTime = SyTime(); p = fgets( line, (int)length, syBuf[fid].fp ); syStartTime += SyTime() - syStopTime; return p; } /* no line editing if the file cannot be turned to raw mode */ if ( syLineEdit == 1 && ! syStartraw(fid) ) { syStopTime = SyTime(); p = fgets( line, (int)length, syBuf[fid].fp ); syStartTime += SyTime() - syStopTime; return p; } /* stop the clock, reading should take no time */ syStopTime = SyTime(); /* the line starts out blank */ line[0] = '\0'; p = line; h = syHistory; for ( q = old; q < old+sizeof(old); ++q ) *q = ' '; oldc = 0; last = 0; while ( 1 ) { /* get a character, handle <ctr>V<chr>, <esc><num> and <ctr>U<num> */ rep = 1; ch2 = 0; do { if ( syCTRO % 2 == 1 ) { ch = CTR('N'); syCTRO = syCTRO - 1; } else if ( syCTRO != 0 ) { ch = CTR('O'); rep = syCTRO / 2; } #if ! SYS_MAC_SYC else ch = syGetch(fid); #endif #if SYS_MAC_SYC else ch = syGetch2(fid,*p); #endif 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;} } 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; 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'); /* now perform the requested action <rep> times in the input line */ while ( rep-- > 0 ) { 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 */ case 127: 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 ) { 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 CTR('L'): /* insert last input line */ for ( r = syHistory; *r != '\0' && *r != '\n'; ++r ) { ch2 = *r; for ( q = p; ch2; ++q ) { ch3 = *q; *q = ch2; ch2 = ch3; } *q = '\0'; ++p; } break; case CTR('Y'): /* insert (yank) deleted text */ for ( r = yank; *r != '\0' && *r != '\n'; ++r ) { ch2 = *r; for ( q = p; ch2; ++q ) { ch3 = *q; *q = ch2; ch2 = ch3; } *q = '\0'; ++p; } break; case CTR('P'): /* fetch old input line */ while ( *h != '\0' ) { for ( q = line; q < p; ++q ) if ( *q != h[q-line] ) break; if ( q == p ) break; while ( *h != '\n' && *h != '\0' ) ++h; if ( *h == '\n' ) ++h; } q = p; while ( *h!='\0' && h[q-line]!='\n' && h[q-line]!='\0' ) { *q = h[q-line]; ++q; } *q = '\0'; while ( *h != '\0' && *h != '\n' ) ++h; if ( *h == '\n' ) ++h; else h = syHistory; syHi = h; break; case CTR('N'): /* fetch next input line */ h = syHi; if ( h > syHistory ) { do {--h;} while (h>syHistory && *(h-1)!='\n'); if ( h==syHistory ) while ( *h != '\0' ) ++h; } while ( *h != '\0' ) { if ( h==syHistory ) while ( *h != '\0' ) ++h; do {--h;} while (h>syHistory && *(h-1)!='\n'); for ( q = line; q < p; ++q ) if ( *q != h[q-line] ) break; if ( q == p ) break; if ( h==syHistory ) while ( *h != '\0' ) ++h; } q = p; while ( *h!='\0' && h[q-line]!='\n' && h[q-line]!='\0' ) { *q = h[q-line]; ++q; } *q = '\0'; while ( *h != '\0' && *h != '\n' ) ++h; if ( *h == '\n' ) ++h; else h = syHistory; syHi = h; break; case ESC('<'): /* goto beginning of the history */ while ( *h != '\0' ) ++h; do {--h;} while (h>syHistory && *(h-1)!='\n'); q = p = line; while ( *h!='\0' && h[q-line]!='\n' && h[q-line]!='\0' ) { *q = h[q-line]; ++q; } *q = '\0'; while ( *h != '\0' && *h != '\n' ) ++h; if ( *h == '\n' ) ++h; else h = syHistory; syHi = h; break; case ESC('>'): /* goto end of the history */ h = syHistory; p = line; *p = '\0'; syHi = h; break; case CTR('S'): /* search for a line forward */ /* search for a line forward, not fully implemented !!! */ if ( *p != '\0' ) { ch2 = syGetch(fid); q = p+1; while ( *q != '\0' && *q != ch2 ) ++q; if ( *q == ch2 ) p = q; } break; case CTR('R'): /* search for a line backward */ /* search for a line backward, not fully implemented !!! */ if ( p > line ) { ch2 = syGetch(fid); q = p-1; while ( q > line && *q != ch2 ) --q; if ( *q == ch2 ) p = q; } 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'): /* 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]) ) { ch2 = ch & 0xff; for ( q = p; ch2; ++q ) { ch3 = *q; *q = ch2; ch2 = ch3; } *q = '\0'; ++p; } else { if ( (q = p) > line ) do { --q; } while ( q>line && (!IS_SEP(*(q-1)) || IS_SEP(*q))); rn = (line < q && *(q-1) == '.'); r = buffer; s = q; while ( s < p ) *r++ = *s++; *r = '\0'; if ( iscomplete( buffer, p-q, rn ) ) { if ( last != CTR('I') ) syEchoch( CTR('G'), fid ); else { syWinPut( fid, "@c", "" ); syEchos( "\n ", fid ); syEchos( buffer, fid ); while ( completion( buffer, p-q, rn ) ) { 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"), "" ); } } else if ( ! completion( buffer, p-q, rn ) ) { if ( last != CTR('I') ) syEchoch( CTR('G'), fid ); else { syWinPut( fid, "@c", "" ); syEchos("\n identifier has no completions\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"), "" ); } } else { t = p; for ( s = buffer+(p-q); *s != '\0'; s++ ) { ch2 = *s; for ( r = p; ch2; r++ ) { ch3 = *r; *r = ch2; ch2 = ch3; } *r = '\0'; p++; } while ( t < p && completion( buffer, t-q, rn ) ) { r = t; s = buffer+(t-q); while ( r < p && *r == *s ) { r++; s++; } s = p; p = r; while ( *s != '\0' ) *r++ = *s++; *r = '\0'; } if ( t == p ) { if ( last != CTR('I') ) syEchoch( CTR('G'), fid ); else { syWinPut( fid, "@c", "" ); buffer[t-q] = '\0'; while ( completion( buffer, t-q, rn ) ) { 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"), ""); } } } } break; default: /* default, insert normal character */ ch2 = ch & 0xff; for ( q = p; ch2; ++q ) { ch3 = *q; *q = ch2; ch2 = ch3; } *q = '\0'; ++p; break; } /* switch ( ch ) */ last = ch; } if ( ch==EOF || ch=='\n' || ch=='\r' || ch==CTR('O') ) { 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); } else if ( *q==0x7F ) { *r++ = '^'; *r++ = '?'; } else if ( '\0'<=*q && *q<' ' ) { *r++ = '^'; *r++ = *q+'@'; } else if ( ' ' <=*q && *q<0x7F ) { *r++ = *q; } else { *r++ = '\\'; *r++ = '0'+(unsigned)*q/64%4; *r++ = '0'+(unsigned)*q/8 %8; *r++ = '0'+(unsigned)*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] = '$'; else if ( q[1] == '\0' && ' ' <= *q && *q < 0x7F ) new[SyNrCols-syNrchar-2] = *q; else if ( 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; } } /* Now we put the new string into the history, first all old strings */ /* are moved backwards, then we enter the new string in syHistory[]. */ for ( q = syHistory+sizeof(syHistory)-3; q >= syHistory+(p-line); --q ) *q = *(q-(p-line)); for ( p = line, q = syHistory; *p != '\0'; ++p, ++q ) *q = *p; syHistory[sizeof(syHistory)-3] = '\n'; if ( syHi != syHistory ) syHi = syHi + (p-line); if ( syHi > syHistory+sizeof(syHistory)-2 ) syHi = syHistory+sizeof(syHistory)-2; /* send the whole line (unclipped) to the window handler */ syWinPut( fid, (*line != '\0' ? "@r" : "@x"), line ); /* strip away prompts (usefull for pasting old stuff) */ if (line[0]=='g'&&line[1]=='a'&&line[2]=='p'&&line[3]=='>'&&line[4]==' ') for ( p = line, q = line+5; q[-1] != '\0'; p++, q++ ) *p = *q; if (line[0]=='b'&&line[1]=='r'&&line[2]=='k'&&line[3]=='>'&&line[4]==' ') for ( p = line, q = line+5; q[-1] != '\0'; p++, q++ ) *p = *q; if (line[0]=='>'&&line[1]==' ') for ( p = line, q = line+2; q[-1] != '\0'; p++, q++ ) *p = *q; /* switch back to cooked mode */ if ( syLineEdit == 1 ) syStopraw(fid); /* start the clock again */ syStartTime += SyTime() - syStopTime; /* return the line (or '0' at end-of-file) */ if ( *line == '\0' ) return (char*)0; return line; } /**************************************************************************** ** *F syStartraw(<fid>) . . . . . . . start raw mode on input file <fid>, local *F syStopraw(<fid>) . . . . . . . stop raw mode on input file <fid>, local *F syGetch(<fid>) . . . . . . . . . . . . . . get a char from <fid>, local *F syEchoch(<ch>,<fid>) . . . . . . . . . . . . echo a char to <fid>, local ** ** This four functions are the actual system dependent part of 'SyFgets'. ** ** 'syStartraw' tries to put the file with the file identifier <fid> into ** raw mode. I.e., disabling echo and any buffering. It also finds a ** place to put the echoing for 'syEchoch'. If 'syStartraw' succedes it ** returns 1, otherwise, e.g., if the <fid> is not a terminal, it returns 0. ** ** 'syStopraw' stops the raw mode for the file <fid> again, switching it ** back into whatever mode the terminal had before 'syStartraw'. ** ** 'syGetch' reads one character from the file <fid>, which must have been ** turned into raw mode before, and returns it. ** ** 'syEchoch' puts the character <ch> to the file opened by 'syStartraw' for ** echoing. Note that if the user redirected 'stdout' but not 'stdin', the ** echo for 'stdin' must go to 'ttyname(fileno(stdin))' instead of 'stdout'. */ /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For Berkeley UNIX, input/output redirection and typeahead are supported. ** We switch the terminal line into 'CBREAK' mode and also disable the echo. ** We do not switch to 'RAW' mode because this would flush all typeahead. ** Because 'CBREAK' leaves signals enabled we have to disable the characters ** for interrupt and quit, which are usually set to '<ctr>-C' and '<ctr>-B'. ** We also turn off the xon/xoff start and stop characters, which are ** usually set to '<ctr>-S' and '<ctr>-Q' so we can get those characters. ** We do not change the suspend character, which is usually '<ctr>-Z', ** instead we catch the signal, so that we can turn the terminal line back ** to cooked mode before stopping GAP and back to raw mode when continueing. */ #if SYS_BSD || SYS_MACH #ifndef SYS_SGTTY_H /* terminal control functions */ # include <sgtty.h> # define SYS_SGTTY_H #endif #ifndef SYS_HAS_IOCTL_PROTO /* UNIX decl. from 'man' */ extern int ioctl P(( int, unsigned long, char * )); #endif struct sgttyb syOld, syNew; /* old and new terminal state */ struct tchars syOldT, syNewT; /* old and new special characters */ #ifndef SYS_SIGNAL_H /* signal handling functions */ # include <signal.h> # ifdef SYS_HAS_SIG_T # define SYS_SIG_T SYS_HAS_SIG_T # else # define SYS_SIG_T void # endif # define SYS_SIGNAL_H typedef SYS_SIG_T sig_handler_t P(( int )); #endif #ifndef SYS_HAS_SIGNAL_PROTO /* ANSI/TRAD decl. from H&S 19.6 */ extern sig_handler_t * signal P(( int, sig_handler_t * )); extern int getpid P(( void )); extern int kill P(( int, int )); #endif #ifndef SYS_HAS_READ_PROTO /* UNIX decl. from 'man' */ extern int read P(( int, char *, int )); extern int write P(( int, char *, int )); #endif #ifdef SIGTSTP long syFid; SYS_SIG_T syAnswerCont ( signr ) int signr; { syStartraw( syFid ); signal( SIGCONT, SIG_DFL ); kill( getpid(), SIGCONT ); #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } SYS_SIG_T syAnswerTstp ( signr ) int signr; { syStopraw( syFid ); signal( SIGCONT, syAnswerCont ); kill( getpid(), SIGTSTP ); #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } #endif int syStartraw ( fid ) long fid; { /* if running under a window handler, tell it that we want to read */ if ( syWindow ) { if ( fid == 0 ) { syWinPut( fid, "@i", "" ); return 1; } else if ( fid == 2 ) { syWinPut( fid, "@e", "" ); return 1; } else { return 0; } } /* try to get the terminal attributes, will fail if not terminal */ if ( ioctl( fileno(syBuf[fid].fp), TIOCGETP, (char*)&syOld ) == -1 ) return 0; /* disable interrupt, quit, start and stop output characters */ if ( ioctl( fileno(syBuf[fid].fp), TIOCGETC, (char*)&syOldT ) == -1 ) return 0; syNewT = syOldT; syNewT.t_intrc = -1; syNewT.t_quitc = -1; /*C 27-Nov-90 martin changing '<ctr>S' and '<ctr>Q' does not work */ /*C syNewT.t_startc = -1; */ /*C syNewT.t_stopc = -1; */ if ( ioctl( fileno(syBuf[fid].fp), TIOCSETC, (char*)&syNewT ) == -1 ) return 0; /* disable input buffering, line editing and echo */ syNew = syOld; syNew.sg_flags |= CBREAK; syNew.sg_flags &= ~ECHO; if ( ioctl( fileno(syBuf[fid].fp), TIOCSETN, (char*)&syNew ) == -1 ) return 0; #ifdef SIGTSTP /* install signal handler for stop */ syFid = fid; signal( SIGTSTP, syAnswerTstp ); #endif /* indicate success */ return 1; } void syStopraw ( fid ) long 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 */ if ( ioctl( fileno(syBuf[fid].fp), TIOCSETN, (char*)&syOld ) == -1 ) fputs("gap: 'ioctl' could not turn off raw mode!\n",stderr); /* enable interrupt, quit, start and stop output characters again */ if ( ioctl( fileno(syBuf[fid].fp), TIOCSETC, (char*)&syOldT ) == -1 ) fputs("gap: 'ioctl' could not turn off raw mode!\n",stderr); } int syGetch ( fid ) long fid; { char ch; /* read a character */ while ( read( fileno(syBuf[fid].fp), &ch, 1 ) != 1 || ch == '\0' ) ; /* if running under a window handler, handle special characters */ if ( syWindow && ch == '@' ) { do { while ( read(fileno(syBuf[fid].fp), &ch, 1) != 1 || ch == '\0' ) ; } while ( ch < '@' || 'z' < ch ); if ( ch == 'y' ) { syWinPut( fileno(syBuf[fid].echo), "@s", "" ); ch = syGetch(fid); } else if ( 'A' <= ch && ch <= 'Z' ) ch = CTR(ch); } /* return the character */ return ch; } void syEchoch ( ch, fid ) int ch; long fid; { char ch2; /* write the character to the associate echo output device */ ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); /* if running under a window handler, duplicate '@' */ if ( syWindow && ch == '@' ) { ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); } } void syEchos ( str, fid ) char * str; long 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 write( fileno(syBuf[fid].echo), str, SyStrlen(str) ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For UNIX System V, input/output redirection and typeahead are supported. ** We turn off input buffering and canonical input editing and also echo. ** Because we leave the signals enabled we have to disable the characters ** for interrupt and quit, which are usually set to '<ctr>-C' and '<ctr>-B'. ** We also turn off the xon/xoff start and stop characters, which are ** usually set to '<ctr>-S' and '<ctr>-Q' so we can get those characters. ** We do not turn of signals 'ISIG' because we want to catch stop and ** continue signals if this particular version of UNIX supports them, so we ** can turn the terminal line back to cooked mode before stopping GAP. */ #if SYS_USG #ifndef SYS_TERMIO_H /* terminal control functions */ # include <termio.h> # define SYS_TERMIO_H #endif #ifndef SYS_HAS_IOCTL_PROTO /* UNIX decl. from 'man' */ extern int ioctl P(( int, int, struct termio * )); #endif struct termio syOld, syNew; /* old and new terminal state */ #ifndef SYS_SIGNAL_H /* signal handling functions */ # include <signal.h> # ifdef SYS_HAS_SIG_T # define SYS_SIG_T SYS_HAS_SIG_T # else # define SYS_SIG_T void # endif # define SYS_SIGNAL_H typedef SYS_SIG_T sig_handler_t P(( int )); #endif #ifndef SYS_HAS_SIGNAL_PROTO /* ANSI/TRAD decl. from H&S 19.6 */ extern sig_handler_t * signal P(( int, sig_handler_t * )); extern int getpid P(( void )); extern int kill P(( int, int )); #endif #ifndef SYS_HAS_READ_PROTO /* UNIX decl. from 'man' */ extern int read P(( int, char *, int )); extern int write P(( int, char *, int )); #endif #ifdef SIGTSTP long syFid; SYS_SIG_T syAnswerCont ( signr ) int signr; { syStartraw( syFid ); signal( SIGCONT, SIG_DFL ); kill( getpid(), SIGCONT ); #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } SYS_SIG_T syAnswerTstp ( signr ) int signr; { syStopraw( syFid ); signal( SIGCONT, syAnswerCont ); kill( getpid(), SIGTSTP ); #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } #endif int syStartraw ( fid ) long fid; { /* if running under a window handler, tell it that we want to read */ if ( syWindow ) { if ( fid == 0 ) { syWinPut( fid, "@i", "" ); return 1; } else if ( fid == 2 ) { syWinPut( fid, "@e", "" ); return 1; } else { return 0; } } /* try to get the terminal attributes, will fail if not terminal */ if ( ioctl( fileno(syBuf[fid].fp), TCGETA, &syOld ) == -1 ) return 0; /* 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 ( ioctl( fileno(syBuf[fid].fp), TCSETAW, &syNew ) == -1 ) return 0; #ifdef SIGTSTP /* install signal handler for stop */ syFid = fid; signal( SIGTSTP, syAnswerTstp ); #endif /* indicate success */ return 1; } void syStopraw ( fid ) long 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 */ if ( ioctl( fileno(syBuf[fid].fp), TCSETAW, &syOld ) == -1 ) fputs("gap: 'ioctl' could not turn off raw mode!\n",stderr); } int syGetch ( fid ) long fid; { char ch; /* read a character */ while ( read( fileno(syBuf[fid].fp), &ch, 1 ) != 1 || ch == '\0' ) ; /* if running under a window handler, handle special characters */ if ( syWindow && ch == '@' ) { do { while ( read(fileno(syBuf[fid].fp), &ch, 1) != 1 || ch == '\0' ) ; } while ( ch < '@' || 'z' < ch ); if ( ch == 'y' ) { syWinPut( fileno(syBuf[fid].echo), "@s", "" ); ch = syGetch(fid); } else if ( 'A' <= ch && ch <= 'Z' ) ch = CTR(ch); } /* return the character */ return ch; } void syEchoch ( ch, fid ) int ch; long fid; { char ch2; /* write the character to the associate echo output device */ ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); /* if running under a window handler, duplicate '@' */ if ( syWindow && ch == '@' ) { ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); } } void syEchos ( str, fid ) char * str; long 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 write( fileno(syBuf[fid].echo), str, SyStrlen(str) ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** OS/2 is almost the same as UNIX System V, except for function keys. */ #if SYS_OS2_EMX #ifndef SYS_TERMIO_H /* terminal control functions */ # include <termio.h> # define SYS_TERMIO_H #endif #ifndef SYS_HAS_IOCTL_PROTO /* UNIX decl. from 'man' */ extern int ioctl P(( int, int, struct termio * )); #endif struct termio syOld, syNew; /* old and new terminal state */ #ifndef SYS_SIGNAL_H /* signal handling functions */ # include <signal.h> # ifdef SYS_HAS_SIG_T # define SYS_SIG_T SYS_HAS_SIG_T # else # define SYS_SIG_T void # endif # define SYS_SIGNAL_H typedef SYS_SIG_T sig_handler_t P(( int )); #endif #ifndef SYS_HAS_SIGNAL_PROTO /* ANSI/TRAD decl. from H&S 19.6 */ extern sig_handler_t * signal P(( int, sig_handler_t * )); extern int getpid P(( void )); extern int kill P(( int, int )); #endif #ifndef SYS_HAS_READ_PROTO /* UNIX decl. from 'man' */ extern int read P(( int, char *, int )); extern int write P(( int, char *, int )); #endif #ifdef SIGTSTP long syFid; SYS_SIG_T syAnswerCont ( signr ) int signr; { syStartraw( syFid ); signal( SIGCONT, SIG_DFL ); kill( getpid(), SIGCONT ); #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } SYS_SIG_T syAnswerTstp ( signr ) int signr; { syStopraw( syFid ); signal( SIGCONT, syAnswerCont ); kill( getpid(), SIGTSTP ); #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } #endif int syStartraw ( fid ) long fid; { /* if running under a window handler, tell it that we want to read */ if ( syWindow ) { if ( fid == 0 ) { syWinPut( fid, "@i", "" ); return 1; } else if ( fid == 2 ) { syWinPut( fid, "@e", "" ); return 1; } else { return 0; } } /* try to get the terminal attributes, will fail if not terminal */ if ( ioctl( fileno(syBuf[fid].fp), TCGETA, &syOld ) == -1 ) return 0; /* 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|IDEFAULT); if ( ioctl( fileno(syBuf[fid].fp), TCSETAW, &syNew ) == -1 ) return 0; #ifdef SIGTSTP /* install signal handler for stop */ syFid = fid; signal( SIGTSTP, syAnswerTstp ); #endif /* indicate success */ return 1; } void syStopraw ( fid ) long 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 */ if ( ioctl( fileno(syBuf[fid].fp), TCSETAW, &syOld ) == -1 ) fputs("gap: 'ioctl' could not turn off raw mode!\n",stderr); } #ifndef SYS_KBD_H /* keyboard scan codes */ # include <sys/kbdscan.h> # define SYS_KBD_H #endif int syGetch ( fid ) long fid; { unsigned char ch; int ch2; syGetchAgain: /* read a character */ while ( read( fileno(syBuf[fid].fp), &ch, 1 ) != 1 ) ; /* if running under a window handler, handle special characters */ if ( syWindow && ch == '@' ) { do { while ( read(fileno(syBuf[fid].fp), &ch, 1) != 1 ) ; } while ( ch < '@' || 'z' < ch ); if ( ch == 'y' ) { syWinPut( fileno(syBuf[fid].echo), "@s", "" ); ch = syGetch(fid); } else if ( 'A' <= ch && ch <= 'Z' ) ch = CTR(ch); } ch2 = ch; /* handle function keys */ if ( ch == '\0' ) { while ( read( fileno(syBuf[fid].fp), &ch, 1 ) != 1 ) ; switch ( ch ) { case K_LEFT: ch2 = CTR('B'); break; case K_RIGHT: ch2 = CTR('F'); break; case K_UP: case K_PAGEUP: ch2 = CTR('P'); break; case K_DOWN: case K_PAGEDOWN: ch2 = CTR('N'); break; case K_DEL: ch2 = CTR('D'); break; case K_HOME: ch2 = CTR('A'); break; case K_END: ch2 = CTR('E'); break; case K_CTRL_END: ch2 = CTR('K'); break; case K_CTRL_LEFT: case K_ALT_B: ch2 = ESC('B'); break; case K_CTRL_RIGHT: case K_ALT_F: ch2 = ESC('F'); break; case K_ALT_D: ch2 = ESC('D'); break; case K_ALT_DEL: case K_ALT_BACKSPACE: ch2 = ESC(127); break; case K_ALT_U: ch2 = ESC('U'); break; case K_ALT_L: ch2 = ESC('L'); break; case K_ALT_C: ch2 = ESC('C'); break; case K_CTRL_PAGEUP: ch2 = ESC('<'); break; case K_CTRL_PAGEDOWN: ch2 = ESC('>'); break; default: goto syGetchAgain; } } /* return the character */ return ch2; } void syEchoch ( ch, fid ) int ch; long fid; { char ch2; /* write the character to the associate echo output device */ ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); /* if running under a window handler, duplicate '@' */ if ( syWindow && ch == '@' ) { ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); } } void syEchos ( str, fid ) char * str; long 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 write( fileno(syBuf[fid].echo), str, SyStrlen(str) ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For MS-DOS we read directly from the keyboard. ** Note that the window handler is not currently supported. */ #if SYS_MSDOS_DJGPP #ifndef SYS_KBD_H /* keyboard functions */ # include <pc.h> # define GETKEY() getkey() # define PUTCHAR(C) putchar(C) # define KBHIT() kbhit() # define SYS_KBD_H #endif unsigned long syStopout; /* output is stopped by <ctr>-'S' */ char syTypeahead [256]; /* characters read by 'SyIsIntr' */ char syAltMap [35] = "QWERTYUIOP ASDFGHJKL ZXCVBNM"; int syStartraw ( fid ) long fid; { /* check if the file is a terminal */ if ( ! isatty( fileno(syBuf[fid].fp) ) ) return 0; /* indicate success */ return 1; } void syStopraw ( fid ) long fid; { } int syGetch ( fid ) long fid; { int ch; /* if chars have been typed ahead and read by 'SyIsIntr' read them */ if ( syTypeahead[0] != '\0' ) { ch = syTypeahead[0]; strcpy( syTypeahead, syTypeahead+1 ); } /* otherwise read from the keyboard */ else { ch = GETKEY(); } /* postprocess the character */ if ( 0x110 <= ch && ch <= 0x132 ) ch = ESC( syAltMap[ch-0x110] ); else if ( ch == 0x147 ) ch = CTR('A'); else if ( ch == 0x14f ) ch = CTR('E'); else if ( ch == 0x148 ) ch = CTR('P'); else if ( ch == 0x14b ) ch = CTR('B'); else if ( ch == 0x14d ) ch = CTR('F'); else if ( ch == 0x150 ) ch = CTR('N'); else if ( ch == 0x153 ) ch = CTR('D'); else ch &= 0xFF; /* return the character */ return ch; } void syEchoch ( ch, fid ) int ch; long fid; { PUTCHAR( ch ); } void syEchos ( str, fid ) char * str; long fid; { char * s; /* handle stopped output */ while ( syStopout ) syStopout = (GETKEY() == CTR('S')); /* echo the string */ for ( s = str; *s != '\0'; s++ ) PUTCHAR( *s ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For TOS we read directly from the keyboard. ** Note that the window handler is not currently supported. */ #if SYS_TOS_GCC2 #ifndef SYS_KBD_H /* keyboard functions */ # include <unixlib.h> /* declaration of 'isatty' */ # include <osbind.h> /* operating system binding */ # define GETKEY() Bconin( 2 ) # define PUTCHAR(C) do{if(C=='\n')Bconout(2,'\r');Bconout(2,C);}while(0) # define KBHIT() Bconstat( 2 ) # define SYS_KBD_H #endif unsigned long syStopout; /* output is stopped by <ctr>-'S' */ char syTypeahead [256]; /* characters read by 'SyIsIntr' */ int syStartraw ( fid ) long fid; { /* check if the file is a terminal */ if ( ! isatty( fileno(syBuf[fid].fp) ) ) return 0; /* indicate success */ return 1; } void syStopraw ( fid ) long fid; { } int syGetch ( fid ) long fid; { int ch; /* if chars have been typed ahead and read by 'SyIsIntr' read them */ if ( syTypeahead[0] != '\0' ) { ch = syTypeahead[0]; strcpy( syTypeahead, syTypeahead+1 ); } /* otherwise read from the keyboard */ else { ch = GETKEY(); } /* postprocess the character */ if ( ch == 0x00480000 ) ch = CTR('P'); else if ( ch == 0x004B0000 ) ch = CTR('B'); else if ( ch == 0x004D0000 ) ch = CTR('F'); else if ( ch == 0x00500000 ) ch = CTR('N'); else if ( ch == 0x00730000 ) ch = CTR('Y'); else if ( ch == 0x00740000 ) ch = CTR('Z'); else ch = ch & 0xFF; /* return the character */ return ch; } void syEchoch ( ch, fid ) int ch; long fid; { PUTCHAR( ch ); } void syEchos ( str, fid ) char * str; long fid; { char * s; /* handle stopped output */ while ( syStopout ) syStopout = (GETKEY() == CTR('S')); /* echo the string */ for ( s = str; *s != '\0'; s++ ) PUTCHAR( *s ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For VMS we use a virtual keyboard to read and write from the unique tty. ** We do not support the window handler. */ #if SYS_VMS #ifndef SYS_HAS_MISC_PROTO /* UNIX decl. from 'man' */ extern int isatty P(( int )); #endif unsigned int syVirKbd; /* virtual (raw) keyboard */ int syStartraw ( fid ) long fid; { /* test whether the file is connected to a terminal */ return isatty( fileno(syBuf[fid].fp) ); } void syStopraw ( fid ) long fid; { } int syGetch ( fid ) long fid; { char ch; /* read a character */ smg$read_keystroke( &syVirKbd, &ch ); /* return the character */ return ch; } void syEchoch ( ch, fid ) int ch; long fid; { char ch2; /* write the character to the associate echo output device */ ch2 = ch; write( fileno(syBuf[fid].echo), (char*)&ch2, 1 ); } void syEchos ( str, fid ) char * str; long fid; { write( fileno(syBuf[fid].echo), str, SyStrlen(str) ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For the MAC with MPW we do not really know how to do this. */ #if SYS_MAC_MPW int syStartraw ( fid ) long fid; { /* clear away pending <command>-'.' */ SyIsIntr(); return 0; } void syStopraw ( fid ) long fid; { } int syGetch ( fid ) long fid; { } void syEchoch ( ch, fid ) int ch; long fid; { } void syEchos ( str, fid ) char * str; long fid; { char * s; for ( s = str; *s != '\0'; s++ ) putchar( *s ); fflush( stdout ); } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For the MAC with Symantec C we use the console input/output package. ** We must set the console to raw mode and back to echo mode. ** In raw mode there is no cursor, so we reverse the current character. */ #if SYS_MAC_SYC #ifndef SYS_UNIX_H /* unix stuff: */ # include <unix.h> /* 'isatty' */ # define SYS_UNIX_H #endif #ifndef SYS_CONSOLE_H /* console stuff: */ # include <Console.h> /* 'csetmode' */ # define SYS_CONSOLE_H #endif #ifndef SYS_OSUTILS_H /* system utils: */ # include <OSUtils.h> /* 'SysBeep' */ # define SYS_OSUTILS_H #endif int syStartraw ( fid ) long fid; { /* cannot switch ordinary files to raw mode */ if ( ! isatty( fileno(syBuf[fid].fp) ) ) return 0; /* turn terminal to raw mode */ csetmode( C_RAW, syBuf[fid].fp ); return 1; } void syStopraw ( fid ) long fid; { /* probably only paranoid */ if ( isatty( fileno(syBuf[fid].fp) ) ) return; /* turn terminal back to echo mode */ csetmode( C_ECHO, syBuf[fid].fp ); } int syGetch ( fid ) long fid; { /* return character */ return syGetch2( fid, '\0' ); } int syGetch2 ( fid, cur ) long fid; int cur; { int ch; /* probably only paranoid */ if ( ! isatty( fileno(syBuf[fid].fp) ) ) return EOF; /* make the current character reverse to simulate a cursor */ syEchoch( (cur != '\0' ? cur : ' ') | 0x80, fid ); syEchoch( '\b', fid ); /* get a character, ignore EOF and chars beyond 0x7F (reverse video) */ while ( ((ch = getchar()) == EOF) || (0x7F < ch) ) ; /* handle special characters */ if ( ch == 28 ) ch = CTR('B'); else if ( ch == 29 ) ch = CTR('F'); else if ( ch == 30 ) ch = CTR('P'); else if ( ch == 31 ) ch = CTR('N'); /* make the current character normal again */ syEchoch( (cur != '\0' ? cur : ' '), fid ); syEchoch( '\b', fid ); /* return the character */ return ch; } void syEchoch ( ch, fid ) int ch; long fid; { /* probably only paranoid */ if ( ! isatty( fileno(syBuf[fid].fp) ) ) return; /* echo the character */ if ( 31 < (ch & 0x7F) || ch == '\b' || ch == '\n' || ch == '\r' ) putchar( ch ); else if ( ch == CTR('G') ) SysBeep( 1 ); else putchar( '?' ); } void syEchos ( str, fid ) char * str; long fid; { char * s; /* probably only paranoid */ if ( ! isatty( fileno(syBuf[fid].fp) ) ) return; /* print the string */ for ( s = str; *s != '\0'; s++ ) putchar( *s ); } #endif /**************************************************************************** ** *F SyFputs( <line>, <fid> ) . . . . . . . . write a line to the file <fid> ** ** 'SyFputs' is called to put the <line> to the file identified by <fid>. */ #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX || SYS_VMS || SYS_MAC_MPW || SYS_MAC_SYC void SyFputs ( line, fid ) char line []; long fid; { long i; /* if outputing to the terminal compute the cursor position and length */ if ( fid == 1 || fid == 3 ) { syNrchar = 0; for ( i = 0; line[i] != '\0'; i++ ) { if ( line[i] == '\n' ) syNrchar = 0; else syPrompt[syNrchar++] = line[i]; } syPrompt[syNrchar] = '\0'; } /* otherwise compute only the length */ else { for ( i = 0; line[i] != '\0'; i++ ) ; } /* if running under a window handler, send the line to it */ if ( syWindow && fid < 4 ) syWinPut( fid, (fid == 1 ? "@n" : "@f"), line ); /* otherwise, write it to the output file */ else #if ! (SYS_MAC_MPW || SYS_MAC_SYC) write( fileno(syBuf[fid].fp), line, i ); #endif #if SYS_MAC_MPW || SYS_MAC_SYC fputs( line, syBuf[fid].fp ); #endif } #endif #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 void SyFputs ( line, fid ) char line []; long fid; { long i; char * s; /* handle the console */ if ( isatty( fileno(syBuf[fid].fp) ) ) { /* test whether this is a line with a prompt */ syNrchar = 0; for ( i = 0; line[i] != '\0'; i++ ) { if ( line[i] == '\n' ) syNrchar = 0; else syPrompt[syNrchar++] = line[i]; } syPrompt[syNrchar] = '\0'; /* handle stopped output */ while ( syStopout ) syStopout = (GETKEY() == CTR('S')); /* output the line */ for ( s = line; *s != '\0'; s++ ) PUTCHAR( *s ); } /* ordinary file */ else { fputs( line, syBuf[fid].fp ); } } #endif /**************************************************************************** ** *F syWinPut(<fid>,<cmd>,<str>) . . . . . . send a line to the window handler ** ** 'syWinPut' send the command <cmd> and the string <str> to the window ** handler associated with the file identifier <fid>. In the string <str> ** '@' characters are duplicated, and control characters are converted to ** '@<chr>', e.g., <newline> is converted to '@J'. */ #if ! (SYS_MAC_MPW || SYS_MAC_SYC) void syWinPut ( fid, cmd, str ) long fid; char * cmd; char * str; { long fd; /* file descriptor */ char tmp [130]; /* temporary buffer */ char * s; /* pointer into the string */ char * t; /* pointer into the temporary */ /* if not running under a window handler, don't do nothing */ if ( ! syWindow || 4 <= fid ) return; /* get the file descriptor */ if ( fid == 0 || fid == 2 ) fd = fileno(syBuf[fid].echo); else fd = fileno(syBuf[fid].fp); /* print the cmd */ write( fd, cmd, SyStrlen(cmd) ); /* print the output line, duplicate '@' and handle <ctr>-<chr> */ s = str; t = tmp; while ( *s != '\0' ) { if ( *s == '@' ) { *t++ = '@'; *t++ = *s++; } else if ( CTR('A') <= *s && *s <= CTR('Z') ) { *t++ = '@'; *t++ = *s++ - CTR('A') + 'A'; } else { *t++ = *s++; } if ( 128 <= t-tmp ) { write( fd, tmp, t-tmp ); t = tmp; } } if ( 0 < t-tmp ) { write( fd, tmp, t-tmp ); } } #endif #if SYS_MAC_MPW || SYS_MAC_SYC void syWinPut ( fid, cmd, str ) long fid; char * cmd; char * str; { } #endif /**************************************************************************** ** *F SyPinfo( <nr>, <size> ) . . . . . . . . . . . . . . . print garbage info ** ** 'SyPinfo' is called from Gasman to inform the window handler about the ** current Gasman statistics. <nr> determines the phase the garbage ** collection is currently in, and <size> is the correspoding value, e.g., ** number of live bags. */ void SyPinfo ( nr, size ) int nr; long size; { char cmd [3]; char buf [16]; char * b; /* set up the command */ cmd[0] = '@'; cmd[1] = nr + '0'; cmd[2] = '\0'; /* stringify the argument */ b = buf; while ( 0 < size ) { *b++ = (size % 10) + '0'; size /= 10; } *b++ = '+'; *b = '\0'; /* send it to the window handler */ syWinPut( 1, cmd, buf ); } /**************************************************************************** ** *F SyWinCmd( <str>, <len> ) . . . . . . . . . . . . . execute a window cmd ** ** 'SyWinCmd' send the command <str> to the window handler (<len> is ** ignored). In the string <str> '@' characters are duplicated, and control ** characters are converted to '@<chr>', e.g., <newline> is converted to ** '@J'. Then 'SyWinCmd' waits for the window handlers answer and returns ** that string. */ #if ! (SYS_MAC_MPW || SYS_MAC_SYC) char WinCmdBuffer [8000]; char * SyWinCmd ( str, len ) char * str; long len; { char buf [130]; /* temporary buffer */ char * s; /* pointer into the string */ char * b; /* pointer into the temporary */ unsigned long i; /* loop variable */ /* if not running under a window handler, don't do nothing */ if ( ! syWindow ) return "I1+S52000000No 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 ( i = 0; i < 8; i++ ) { *b++ = (len % 10) + '0'; len /= 10; } *b = '\0'; syWinPut( 1, "@w", buf ); /* send the string to the window handler */ syWinPut( 1, "", str ); /* read the length of the answer */ s = WinCmdBuffer; i = 10; do { while ( 0 < i ) { len = read( 0, s, i ); i -= len; s += len; } if ( WinCmdBuffer[0] == '@' && WinCmdBuffer[1] == 'y' ) { for ( i = 2; i < 10; i++ ) WinCmdBuffer[i-2] = WinCmdBuffer[i]; s -= 2; i = 2; } } while ( 0 < i ); if ( WinCmdBuffer[0] != '@' || WinCmdBuffer[1] != 'a' ) return "I1+S41000000Illegal Answer"; for ( len = 0, i = 9; 1 < i; i-- ) len = len*10 + (WinCmdBuffer[i]-'0'); /* read the arguments of the answer */ s = WinCmdBuffer; i = len; while ( 0 < i ) { len = read( 0, s, i ); i -= len; s += len; } /* shrink '@@' into '@' */ for ( b = s = WinCmdBuffer; 0 < len; len-- ) { if ( *s == '@' ) { s++; if ( *s == '@' ) *b++ = '@'; else if ( 'A' <= *s && *s <= 'Z' ) *b++ = CTR(*s); s++; } else { *b++ = *s++; } } *b = 0; /* return the string */ return WinCmdBuffer; } #endif #if SYS_MAC_MPW || SYS_MAC_SYC char * SyWinCmd ( str, len ) char * str; long len; { return 0; } #endif /**************************************************************************** ** *F SyIsIntr() . . . . . . . . . . . . . . . . check wether user hit <ctr>-C ** ** 'SyIsIntr' is called from the evaluator at regular intervals to check ** wether the user hit '<ctr>-C' to interrupt a computation. ** ** 'SyIsIntr' returns 1 if the user typed '<ctr>-C' and 0 otherwise. */ /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For UNIX, OS/2 and VMS we install 'syAnswerIntr' to answer interrupt ** 'SIGINT'. If two interrupts occur within 1 second 'syAnswerIntr' exits ** GAP. */ #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX || SYS_VMS #ifndef SYS_SIGNAL_H /* signal handling functions */ # include <signal.h> # ifdef SYS_HAS_SIG_T # define SYS_SIG_T SYS_HAS_SIG_T # else # define SYS_SIG_T void # endif # define SYS_SIGNAL_H typedef SYS_SIG_T sig_handler_t P(( int )); #endif #ifndef SYS_HAS_SIGNAL_PROTO /* ANSI/TRAD decl. from H&S 19.6 */ extern sig_handler_t * signal P(( int, sig_handler_t * )); extern int getpid P(( void )); extern int kill P(( int, int )); #endif #ifndef SYS_TIME_H /* time functions */ # if SYS_VMS # include <types.h> /* declaration of type 'time_t' */ # endif # include <time.h> # define SYS_TIME_H #endif #ifndef SYS_HAS_TIME_PROTO /* ANSI/TRAD decl. from H&S 18.1 */ # if SYS_ANSI extern time_t time P(( time_t * buf )); # else extern long time P(( long * buf )); # endif #endif unsigned long syLastIntr; /* time of the last interrupt */ SYS_SIG_T syAnswerIntr ( signr ) int signr; { unsigned long nowIntr; /* 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; /* reinstall 'syAnswerIntr' as signal handler */ #if ! SYS_OS2_EMX signal( SIGINT, syAnswerIntr ); #else signal( signr, SIG_ACK ); #endif #ifdef SYS_HAS_SIG_T return 0; /* is ignored */ #endif } long SyIsIntr () { long isIntr; isIntr = (syLastIntr != 0); syLastIntr = 0; return isIntr; } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** In DOS we check the input queue to look for <ctr>-'C', chars read are put ** on the 'osTypeahead' buffer. The buffer is flushed if <ctr>-'C' is found. ** Actually with the current DOS extender we cannot trap <ctr>-'C', because ** the DOS extender does so already, so be use <ctr>-'Z' and <alt>-'C'. ** ** In TOS we check the input queue to look for <ctr>-'C', chars read are put ** on the 'osTypeahead' buffer. The buffer is flushed if <ctr>-'C' is found. ** There is however a problem, if 2 or more characters are pending (that is ** waiting to be read by either 'SyIsIntr' or 'SyGetch') and the second is a ** <ctr>-'C', GAP will be killed when 'SyIsIntr' or 'syGetch' tries to read ** the first character. Thus if you typed ahead and want to interrupt the ** computation, wait some time to make sure that the typed ahead characters ** have been read by 'SyIsIntr' befor you hit <ctr>-'C'. */ #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 long syIsIntrFreq = 20; long syIsIntrCount = 0; long SyIsIntr () { int ch, i; /* don't check for interrupts every time 'SyIsIntr' is called */ if ( 0 < --syIsIntrCount ) return 0; syIsIntrCount = syIsIntrFreq; /* check for interrupts stuff the rest in typeahead buffer */ if ( syLineEdit && KBHIT() ) { while ( KBHIT() ) { ch = GETKEY(); if ( ch == CTR('C') || ch == CTR('Z') || ch == 0x12E ) { PUTCHAR('^'); PUTCHAR('C'); syTypeahead[0] = '\0'; syStopout = 0; return 1L; } else if ( ch == CTR('X') ) { PUTCHAR('^'); PUTCHAR('X'); syTypeahead[0] = '\0'; syStopout = 0; } else if ( ch == CTR('S') ) { syStopout = 1; } else if ( syStopout ) { syStopout = 0; } else { for ( i = 0; i < sizeof(syTypeahead)-1; ++i ) { if ( syTypeahead[i] == '\0' ) { PUTCHAR(ch); syTypeahead[i] = ch; syTypeahead[i+1] = '\0'; break; } } } } return 0L; } return 0L; } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For a MPW Tool, we install 'syAnswerIntr' to answer interrupt 'SIGINT'. ** However, the interrupt is only delivered when the system has a control, ** namely when we call the toolbox function 'SpinCursor' in 'SyIsIntr'. ** Thus the mechanism is effectively polling. ** ** For a MPW SIOW, we search the event queue for a <cmd>-'.' or a <cnt>-'C'. ** If one is found, all keyboard events are flushed. ** *N 1995/04/30 mschoene these should be merged */ #if SYS_MAC_MPW #ifdef SYS_HAS_TOOL #ifndef SYS_SIGNAL_H /* signal handling functions */ # include <Signal.h> # ifdef SYS_HAS_SIG_T # define SYS_SIG_T SYS_HAS_SIG_T # else # define SYS_SIG_T void # endif # define SYS_SIGNAL_H typedef SYS_SIG_T sig_handler_t P(( int )); #endif #ifndef SYS_HAS_SIGNAL_PROTO /* ANSI/TRAD decl. from H&S 19.6 */ extern sig_handler_t * signal P(( int, sig_handler_t * )); #endif #ifndef SYS_CURSORCTL_H /* cursor control functions: */ # include <CursorCtl.h> /* 'Show_Cursor', 'SpinCursor' */ # define SYS_CURSORCTL_H #endif unsigned long syNrIntr; /* number of interrupts */ unsigned long syLastIntr; /* time of the last interrupt */ long syIsIntrFreq = 100; /* frequency to test interrupts */ long syIsIntrCount = 0; /* countdown to test interrupts */ void syAnswerIntr ( signr ) int signr; { /* reinstall the signal handler */ signal( SIGINT, &syAnswerIntr ); /* exit if two interrupts happen within one second */ /*N 1993/05/28 martin this doesn't work, because interrupts are only */ /*N delivered when we call 'SpinCursor' below */ if ( syNrIntr && SyTime()-syLastIntr <= 1000 ) SyExit( 1 ); /* got one more interrupt */ syNrIntr = syNrIntr + 1; syLastIntr = SyTime(); } long SyIsIntr () { long syIsIntr; /* don't check for interrupts every time 'SyIsIntr' is called */ if ( 0 < --syIsIntrCount ) return 0; syIsIntrCount = syIsIntrFreq; /* spin the beachball */ Show_Cursor( HIDDEN_CURSOR ); SpinCursor( 8 ); /* check for interrupts */ syIsIntr = (syNrIntr != 0); /* every interrupt leaves a <eof>, which we want to remove */ while ( syNrIntr ) { while ( getchar() != EOF ) ; clearerr( stdin ); syNrIntr = syNrIntr - 1; } /* return whether an interrupt has happened */ return syIsIntr; } #else #ifndef SYS_TYPES_H /* various types */ # include <Types.h> # define SYS_TYPES_H #endif #ifndef SYS_OSUTILS_H /* system utils: */ # include <OSUtils.h> /* 'QHdr' */ # define SYS_OSUTILS_H #endif #ifndef SYS_OSEVENTS_H /* system events, low level: */ # include <OSEvents.h> /* 'EvQEl', 'GetEvQHdr', */ /* 'FlushEvents' */ # define SYS_OSEVENTS_H #endif #ifndef SYS_EVENTS_H /* system events, high level: */ # include <Events.h> /* 'EventRecord', 'GetNextEvent' */ # define SYS_EVENTS_H #endif unsigned long syNrIntr; /* number of interrupts */ unsigned long syLastIntr; /* time of the last interrupt */ long syIsIntrFreq = 100; /* frequency to test interrupts */ long syIsIntrCount = 0; /* countdown to test interrupts */ long SyIsIntr () { long syIsIntr; struct QHdr * queue; struct EvQEl * qentry; /* don't check for interrupts every time 'SyIsIntr' is called */ if ( 0 < --syIsIntrCount ) return 0; syIsIntrCount = syIsIntrFreq; /* look through the event queue for <command>-'.' or <control>-'C' */ queue = GetEvQHdr(); qentry = (struct EvQEl *)(queue->qHead); while ( qentry ) { if ( qentry->evtQWhat == keyDown && ( ((qentry->evtQModifiers & controlKey) != 0) && ((qentry->evtQMessage & charCodeMask) == 3)) || ( ((qentry->evtQModifiers & cmdKey ) != 0) && ((qentry->evtQMessage & charCodeMask) == '.')) ) { syNrIntr++; } qentry = (struct EvQEl *)(qentry->qLink); } /* check for interrupts */ syIsIntr = (syNrIntr != 0); /* flush away all keyboard events after an interrupt */ if ( syNrIntr ) { FlushEvents( keyDownMask, 0 ); syNrIntr = 0; } /* return whether an interrupt has happened */ return syIsIntr; } #endif #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For Symantec C, we search the event queue for a <cmd>-'.' or a <cnt>-'C'. ** If one is found, all keyboard events are flushed, and 'true' is returned. ** We also check for signals just to be safe. Because signals are only ** delivered when the system is in control, e.g., when we call 'SystemTask', ** there is no point to test for two interrupts within a second. */ #if SYS_MAC_SYC #ifndef SYS_SIGNAL_H /* signal handling functions */ # include <signal.h> # ifdef SYS_HAS_SIG_T # define SYS_SIG_T SYS_HAS_SIG_T # else # define SYS_SIG_T void # endif # define SYS_SIGNAL_H typedef SYS_SIG_T sig_handler_t P(( int )); #endif #ifndef SYS_HAS_SIGNAL_PROTO /* ANSI/TRAD decl. from H&S 19.6 */ extern sig_handler_t * signal P(( int, sig_handler_t * )); #endif #ifndef SYS_TYPES_H /* various types */ # include <Types.h> # define SYS_TYPES_H #endif #ifndef SYS_LOWMEM_H /* variables in low memory: */ # include <LowMem.h> /* 'LMGetTicks' */ # define SYS_LOWMEM_H #endif #ifndef SYS_OSUTILS_H /* system utils: */ # include <OSUtils.h> /* 'QHdr' */ # define SYS_OSUTILS_H #endif #ifndef SYS_OSEVENTS_H /* system events, low level: */ # include <OSEvents.h> /* 'EvQEl', 'GetEvQHdr', */ /* 'FlushEvents' */ # define SYS_OSEVENTS_H #endif #ifndef SYS_EVENTS_H /* system events, high level: */ # include <Events.h> /* 'EventRecord', 'GetNextEvent' */ # define SYS_EVENTS_H #endif #ifndef SYS_LOMEM_H /* variables in low memory */ # include <LoMem.h> /* 'SEvtEnb' */ # define SYS_LOMEM_H #endif #ifndef SYS_DESK_H # include <Desk.h> /* 'SystemTask' */ # define SYS_DESK_H #endif unsigned long syNrIntr; /* number of interrupts */ long syIsIntrFreq = 60; /* frequency to test interrupts */ long syIsIntrCount = 0; /* countdown to test interrupts */ long syIsBackFreq = 600; /* frequence background switching */ long syIsBackCount = 0; /* countdown background switching */ void syAnswerIntr ( signr ) int signr; { /* reinstall the signal handler */ signal( SIGINT, &syAnswerIntr ); /* got one more interrupt */ syNrIntr = syNrIntr + 1; } long SyIsIntr () { long syIsIntr; struct QHdr * queue; struct EvQEl * qentry; EventRecord theEvent; /* don't check for interrupts every time 'SyIsIntr' is called */ if ( (*(long*)0x016A) <= syIsIntrCount ) return 0; syIsIntrCount = (*(long*)0x016A) + syIsIntrFreq; /* allow for system activities */ if ( syIsBackCount < (*(long*)0x016A) ) { syIsBackCount = (*(long*)0x016A) + syIsBackFreq; SystemTask(); SEvtEnb = false; GetNextEvent( activMask, &theEvent ); } /* check for caught interrupts */ syIsIntr = (syNrIntr != 0); /* every caught interrupt leaves a <eof>, which we want to remove */ while ( syNrIntr ) { while ( getchar() != EOF ) ; clearerr( stdin ); syNrIntr = syNrIntr - 1; } /* look through the event queue for <command>-'.' or <control>-'C' */ queue = GetEvQHdr(); qentry = (struct EvQEl *)(queue->qHead); while ( qentry ) { if ( qentry->evtQWhat == keyDown && ( ((qentry->evtQModifiers & controlKey) != 0) && ((qentry->evtQMessage & charCodeMask) == 3)) || ( ((qentry->evtQModifiers & cmdKey ) != 0) && ((qentry->evtQMessage & charCodeMask) == '.')) ) { syNrIntr++; } qentry = (struct EvQEl *)(qentry->qLink); } /* check for interrupts */ syIsIntr = syIsIntr || (syNrIntr != 0); /* flush away all keyboard events after an interrupt */ if ( syNrIntr ) { FlushEvents( keyDownMask, 0 ); syNrIntr = 0; } /* return whether an interrupt has happened */ return syIsIntr; } #endif /**************************************************************************** ** *F SyExit( <ret> ) . . . . . . . . . . . . . exit GAP with return code <ret> ** ** 'SyExit' is the offical way to exit GAP, bus errors are the inoffical. ** The function 'SyExit' must perform all the neccessary cleanup operations. ** If ret is 0 'SyExit' should signal to a calling proccess that all is ok. ** If ret is 1 'SyExit' should signal a failure to the calling proccess. */ #ifndef SYS_STDLIB_H /* ANSI standard functions */ # if SYS_ANSI # include <stdlib.h> # endif # define SYS_STDLIB_H #endif #ifndef SYS_HAS_MISC_PROTO /* ANSI/TRAD decl. from H&S 19.3 */ /* extern void exit P(( int )); */ #endif #if SYS_MAC_SYC #ifndef SYS_CONSOLE_H /* console stuff */ # include <Console.h> /* 'console_options' */ # define SYS_CONSOLE_H #endif #endif void SyExit ( ret ) long ret; { #if SYS_MAC_MPW # ifndef SYS_HAS_TOOL fputs("gap: please use <option>-'Q' to close the window.\n",stdout); # endif #endif #if SYS_MAC_SYC /* if something went wrong, then give the user a change to see it */ if ( ret != 0 ) console_options.pause_atexit = 1; /* if GAP will pause before exiting, tell the user */ if ( console_options.pause_atexit == 1 ) printf( "gap: enter <return> to exit"); #endif exit( (int)ret ); } /**************************************************************************** ** *F SyExec( <cmd> ) . . . . . . . . . . . execute command in operating system ** ** 'SyExec' executes the command <cmd> (a string) in the operating system. ** ** 'SyExec' should call a command interpreter to execute the command, so ** that file name expansion and other common actions take place. If the OS ** does not support this 'SyExec' should print a message and return. ** ** For UNIX we can use 'system', which does exactly what we want. */ #ifndef SYS_STDLIB_H /* ANSI standard functions */ # if SYS_ANSI # include <stdlib.h> # endif # define SYS_STDLIB_H #endif #ifndef SYS_HAS_MISC_PROTO /* ANSI/TRAD decl. from H&S 19.2 */ extern int system P(( SYS_CONST char * )); #endif #if ! (SYS_MAC_MPW || SYS_MAC_SYC) void SyExec ( cmd ) char * cmd; { long ignore; syWinPut( 0, "@z", "" ); ignore = system( cmd ); syWinPut( 0, "@mAgIc", "" ); } #endif #if SYS_MAC_MPW || SYS_MAC_SYC void SyExec ( cmd ) char * cmd; { } #endif /**************************************************************************** ** *F SyTime() . . . . . . . . . . . . . . . return time spent in milliseconds ** ** 'SyTime' returns the number of milliseconds spent by GAP so far. ** ** Should be as accurate as possible, because it is used for profiling. */ /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For Berkeley UNIX the clock ticks in 1/60. On some (all?) BSD systems we ** can use 'getrusage', which gives us a much better resolution. */ #if SYS_BSD || SYS_MACH || SYS_MSDOS_DJGPP #ifndef SYS_HAS_NO_GETRUSAGE #ifndef SYS_RESOURCE_H /* definition of 'struct rusage' */ # include <sys/time.h> /* definition of 'struct timeval' */ # include <sys/resource.h> # define SYS_RESOURCE_H #endif #ifndef SYS_HAS_TIME_PROTO /* UNIX decl. from 'man' */ extern int getrusage P(( int, struct rusage * )); #endif unsigned long SyTime () { struct rusage buf; if ( getrusage( RUSAGE_SELF, &buf ) ) { fputs("gap: panic 'SyTime' cannot get time!\n",stderr); SyExit( 1 ); } return buf.ru_utime.tv_sec*1000 + buf.ru_utime.tv_usec/1000 -syStartTime; } #endif #ifdef SYS_HAS_NO_GETRUSAGE #ifndef SYS_TIMES_H /* time functions */ # include <sys/types.h> # include <sys/times.h> # define SYS_TIMES_H #endif #ifndef SYS_HAS_TIME_PROTO /* UNIX decl. from 'man' */ extern int times P(( struct tms * )); #endif unsigned long SyTime () { struct tms tbuf; if ( times( &tbuf ) == -1 ) { fputs("gap: panic 'SyTime' cannot get time!\n",stderr); SyExit( 1 ); } return 100 * tbuf.tms_utime / (60/10) - syStartTime; } #endif #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For UNIX System V and OS/2 the clock ticks in 1/HZ, this is usually 1/60 ** or 1/100. */ #if SYS_USG || SYS_OS2_EMX #ifndef SYS_TIMES_H /* time functions */ # include <sys/param.h> /* definition of 'HZ' */ # include <sys/types.h> # include <sys/times.h> # define SYS_TIMES_H #endif #ifndef SYS_HAS_TIME_PROTO /* UNIX decl. from 'man' */ extern int times P(( struct tms * )); #endif unsigned long SyTime () { struct tms tbuf; if ( times( &tbuf ) == -1 ) { fputs("gap: panic 'SyTime' cannot get time!\n",stderr); SyExit( 1 ); } return 100 * tbuf.tms_utime / (HZ / 10) - syStartTime; } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For TOS and VMS we use the function 'clock' and allow to stop the clock. */ #if SYS_TOS_GCC2 || SYS_VMS #ifndef SYS_TIME_H /* time functions */ # include <time.h> # define SYS_TIME_H #endif #ifndef SYS_HAS_TIME_PROTO /* ANSI/TRAD decl. from H&S 18.2 */ # if SYS_ANSI extern clock_t clock P(( void )); # define SYS_CLOCKS CLOCKS_PER_SEC # else extern long clock P(( void )); # if SYS_TOS_GCC2 # define SYS_CLOCKS 200 # else # define SYS_CLOCKS 100 # endif # endif #endif unsigned long SyTime () { return 100 * (unsigned long)clock() / (SYS_CLOCKS/10) - syStartTime; } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For MAC with MPW we use the 'TickCount' function and allow to stop the ** clock. */ #if SYS_MAC_MPW || SYS_MAC_SYC #ifndef SYS_TYPES_H /* various types */ # include <Types.h> # define SYS_TYPES_H #endif #ifndef SYS_EVENTS_H /* system events, high level: */ # include <Events.h> /* 'TickCount' */ # define SYS_EVENTS_H #endif unsigned long SyTime () { return 100 * (unsigned long)TickCount() / (60/10) - syStartTime; } #endif /**************************************************************************** ** *F SyTmpname() . . . . . . . . . . . . . . . . . return a temporary filename ** ** 'SyTmpname' creates and returns a new temporary name. */ #ifndef SYS_STDIO_H /* standard input/output functions */ # include <stdio.h> # define SYS_STDIO_H #endif #ifndef SYS_HAS_MISC_PROTO /* ANSI/TRAD decl. from H&S 15.16 */ extern char * tmpnam P(( char * )); #endif char * SyTmpname () { return tmpnam( (char*)0 ); } /**************************************************************************** ** *F SyHelp( <topic>, <fid> ) . . . . . . . . . . . . . . display online help ** ** This function is of course way to large. But what the heck, it works. */ char syChapnames [128][16]; char syLastTopics [16] [64] = { "Welcome to GAP" }; short syLastIndex = 0; void SyHelp ( topic, fin ) char * topic; /* topic for which help is sought */ long fin; /* file id of input and output */ { char filename [256]; /* filename of various files */ long fid; /* file identifier of various files*/ char line [256]; /* single line from those files */ unsigned long chapnr; /* number of the chapter */ char chapname [64]; /* name of the chapter */ unsigned long secnr; /* number of the section */ char secname [1024]; /* name of the section */ char secline [128]; /* '\Section <secname>' */ long match; /* does the section match topic */ long matches; /* how many sections matched */ char last [256]; /* last line from table of contents*/ char last2 [256]; /* last chapter line from toc */ long offset; /* '<' is -1, '>' is 1 */ char ch; /* char read after '-- <space> --' */ long spaces; /* spaces to be inserted for just */ char status; /* 'a', '$', '|', or '#' */ char * p, * q, * r; /* loop variables */ unsigned long i, j; /* loop variables */ unsigned long raw; /* is input in raw mode? */ /* try to switch the input into raw mode */ raw = (syLineEdit == 1 && syStartraw( fin )); /* inform the window handler */ syWinPut( fin, "@h", "" ); /* set 'SyHelpname' to 'SyLibname' with 'lib' replaced by 'doc' */ if ( SyHelpname[0] == '\0' ) { q = SyHelpname; p = SyLibname; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; for ( p = SyHelpname; *p != '\0'; p++ ) ; while ( SyHelpname < p && (p[0]!='l' || p[1]!='i' || p[2]!='b') ) p--; p[0] = 'd'; p[1] = 'o'; p[2] = 'c'; } /* skip leading blanks in the topic */ while ( *topic == ' ' ) topic++; /* if the topic is empty take the last one again */ if ( topic[0] == '\0' ) { topic = syLastTopics[ syLastIndex ]; } /* if the topic is '<' we are interested in the one before 'LastTopic' */ offset = 0; last[0] = '\0'; if ( SyStrcmp( topic, "<" ) == 0 ) { topic = syLastTopics[ syLastIndex ]; offset = -1; } /* if the topic is '>' we are interested in the one after 'LastTopic' */ if ( SyStrcmp( topic, ">" ) == 0 ) { topic = syLastTopics[ syLastIndex ]; offset = 1; } /* if the topic is '<<' we are interested in the first section */ last2[0] = '\0'; if ( SyStrcmp( topic, "<<" ) == 0 ) { topic = syLastTopics[ syLastIndex ]; offset = -2; } /* if the topic is '>>' we are interested in the next chapter */ if ( SyStrcmp( topic, ">>" ) == 0 ) { topic = syLastTopics[ syLastIndex ]; offset = 2; } /* if the topic is '-' we are interested in the previous section again */ if ( topic[0] == '-' ) { while ( *topic++ == '-' ) syLastIndex = (syLastIndex + 15) % 16; topic = syLastTopics[ syLastIndex ]; if ( topic[0] == '\0' ) { syEchos( "Help: this section has no previous section\n", fin ); syLastIndex = (syLastIndex + 1) % 16; if ( raw ) syStopraw( fin ); return; } syLastIndex = (syLastIndex + 15) % 16; } /* if the topic is '+' we are interested in the last section again */ if ( topic[0] == '+' ) { while ( *topic++ == '+' ) syLastIndex = (syLastIndex + 1) % 16; topic = syLastTopics[ syLastIndex ]; if ( topic[0] == '\0' ) { syEchos( "Help: this section has no previous section\n", fin ); syLastIndex = (syLastIndex + 15) % 16; if ( raw ) syStopraw( fin ); return; } syLastIndex = (syLastIndex + 15) % 16; } /* if the subject is 'Welcome to GAP' display a welcome message */ if ( SyStrcmp( topic, "Welcome to GAP" ) == 0 ) { syEchos( " Welcome to GAP ______________________________", fin ); syEchos( "_____________ Welcome to GAP\n", fin ); syEchos( "\n", fin ); syEchos( " Welcome to GAP.\n", fin ); syEchos( "\n", fin ); syEchos( " GAP is a system for computational group theor", fin ); syEchos( "y.\n", fin ); syEchos( "\n", fin ); syEchos( " Enter '?About GAP' for a step by step intr", fin ); syEchos( "oduction to GAP.\n", fin ); syEchos( " Enter '?Help' for information how to ", fin ); syEchos( "use the GAP help system.\n", fin ); syEchos( " Enter '?Chapters' for a list of the chapt", fin ); syEchos( "ers of the GAP help system.\n", fin ); syEchos( " Enter '?Copyright' for the terms under whi", fin ); syEchos( "ch you can use and copy GAP.\n", fin ); syEchos( "\n", fin ); syEchos( " In each case do *not* enter the single quotes", fin ); syEchos( "(') , they are used in help\n", fin ); syEchos( " sections only to delimit text that you actual", fin ); syEchos( "ly enter.\n", fin ); syEchos( "\n", fin ); /* remember this topic for the next time */ p = "Welcome to GAP"; syLastIndex = (syLastIndex + 1) % 16; q = syLastTopics[ syLastIndex ]; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; if ( raw ) syStopraw( fin ); return; } /* if the topic is 'chapter' display the table of chapters */ if ( SyStrcmp(topic,"chapters")==0 || SyStrcmp(topic,"Chapters")==0 ) { /* open the table of contents file */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-12 ); SyStrncat( filename, "manual.toc", 11 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the table of contents file '",fin ); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <hlpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* print the header line */ syEchos( " Table of Chapters _________________", fin ); syEchos( "____________________ Table of Contents\n", fin ); /* scan the table of contents for chapter lines */ offset = 2; while ( SyFgets( line, sizeof(line), fid ) ) { /* parse table of contents line */ for ( p = line; *p != '\0' && ! IsDigit(*p); p++ ) ; for ( i = 0; IsDigit(*p); p++ ) i = 10*i+*p-'0'; if ( *p == '.' ) p++; for ( j = 0; IsDigit(*p); p++ ) j = 10*j+*p-'0'; if ( *p == '}' ) p++; if ( i == 0 || ! IsAlpha(*p) ) { syEchos("Help: contentsline is garbage in 'manual.toc'",fin); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* skip nonchapter lines */ if ( j != 0 ) continue; /* stop every 24 lines */ if ( offset == SyNrRows && raw ) { syEchos( " -- <space> for more --", fin ); ch = syGetch( fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); syEchos( " ", fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); if ( ch == 'q' ) { syEchos( "\n", fin ); break; } else if ( ch == '\n' || ch == '\r' ) { offset = SyNrRows - 1; } else { offset = 2; } } /* display the line */ q = line; while ( *p != '}' ) *q++ = *p++; *q++ = '\n'; *q = '\0'; syEchos( " ", fin ); syEchos( line, fin ); offset++; } /* remember this topic for the next time */ p = "Chapters"; syLastIndex = (syLastIndex + 1) % 16; q = syLastTopics[ syLastIndex ]; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* if the topic is 'sections' display the table of sections */ if ( SyStrcmp(topic,"sections")==0 || SyStrcmp(topic,"Sections")==0 ) { /* open the table of contents file */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-12 ); SyStrncat( filename, "manual.toc", 11 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the table of contents file '",fin); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <hlpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* print the header line */ syEchos( " Table of Sections _________________", fin ); syEchos( "____________________ Table of Contents\n", fin ); /* scan the table of contents for chapter lines */ offset = 2; while ( SyFgets( line, sizeof(line), fid ) ) { /* parse table of contents line */ for ( p = line; *p != '\0' && ! IsDigit(*p); p++ ) ; for ( i = 0; IsDigit(*p); p++ ) i = 10*i+*p-'0'; if ( *p == '.' ) p++; for ( j = 0; IsDigit(*p); p++ ) j = 10*j+*p-'0'; if ( *p == '}' ) p++; if ( i == 0 || ! IsAlpha(*p) ) { syEchos("Help: contentsline is garbage in 'manual.toc'",fin); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* stop every 24 lines */ if ( offset == SyNrRows && raw ) { syEchos( " -- <space> for more --", fin ); ch = syGetch( fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); syEchos( " ", fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); if ( ch == 'q' ) { syEchos( "\n", fin ); break; } else if ( ch == '\n' || ch == '\r' ) { offset = SyNrRows - 1; } else { offset = 2; } } /* display the line */ q = line; while ( *p != '}' ) *q++ = *p++; *q++ = '\n'; *q = '\0'; if ( j == 0 ) syEchos( " ", fin ); else syEchos( " ", fin ); syEchos( line, fin ); offset++; } /* remember this topic for the next time */ p = "Sections"; syLastIndex = (syLastIndex + 1) % 16; q = syLastTopics[ syLastIndex ]; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* if the topic is 'Copyright' print the copyright */ if ( SyStrcmp(topic,"copyright")==0 || SyStrcmp(topic,"Copyright")==0 ) { /* open the copyright file */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-14 ); SyStrncat( filename, "copyrigh.tex", 13 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the copyright file '",fin); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <helpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* print the header line */ syEchos( " Copyright _________________________", fin ); syEchos( "____________________________ Copyright\n", fin ); /* print the contents of the file */ offset = 2; while ( SyFgets( line, sizeof(line), fid ) ) { /* skip lines that begin with a '%' */ if ( line[0] == '%' ) continue; /* skip the line that begins with '\thispagestyle' */ p = line; q = "\\thispagestyle"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) continue; /* stop every 24 lines */ if ( offset == SyNrRows && raw ) { syEchos( " -- <space> for more --", fin ); ch = syGetch( fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); syEchos( " ", fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); if ( ch == 'q' ) { syEchos( "\n", fin ); break; } else if ( ch == '\n' || ch == '\r' ) { offset = SyNrRows - 1; } else { offset = 2; } } /* fixup the copyright line */ p = line; q = "{\\large"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) { syEchos( " Copyright (c) 1992 ", fin ); syEchos( "by Lehrstuhl D fuer Mathematik\n", fin ); continue; } /* display the line */ p = line; q = last; spaces = 0; while ( *p != '\0' ) { if ( *p == '\\' || *p == '{' || *p == '}' ) { if ( last < q && q[-1] == ' ' ) *q++ = ' '; else spaces++; } else if ( *p == ' ' ) { *q++ = ' '; while ( 0 < spaces ) { *q++ = ' '; spaces--; } } else { *q++ = *p; } p++; } *q = '\0'; syEchos( " ", fin ); syEchos( last, fin ); offset++; } /* remember this topic for the next time */ p = "Copyright"; syLastIndex = (syLastIndex + 1) % 16; q = syLastTopics[ syLastIndex ]; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* if the topic is '?<string>' search the index */ if ( topic[0] == '?' ) { /* skip leading blanks in the topic */ topic++; while ( *topic == ' ' ) topic++; /* open the index */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-12 ); SyStrncat( filename, "manual.idx", 11 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the index file '", fin); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <hlpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* make a header line */ line[0] = '\0'; SyStrncat( line, topic, 40 ); SyStrncat( line, " _________________________________________________________________", 73 - 5 ); line[72-5] = ' '; line[73-5] = '\0'; SyStrncat( line, "Index", 6 ); SyStrncat( line, "\n", 2 ); syEchos( " ", fin ); syEchos( line, fin ); /* scan the index */ offset = 2; while ( SyFgets( line, sizeof(line), fid ) ) { /* a '%' line tells us that the next entry is a section name */ if ( line[0] == '%' ) { while ( line[0] == '%' ) { if ( ! SyFgets( line, sizeof(line), fid ) ) { syEchos( "Help: index file is garbage\n", fin ); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } } q = secname; p = line + 12; while ( *p != '}' ) *q++ = *p++; *q = '\0'; } /* skip this entry if we alread had an entry for this section */ if ( secname[0] == '\0' ) continue; /* try to match topic against this index entry */ for ( r = line + 12; *r != '\0'; r++ ) { p = topic; q = r; while ( (*p | 0x20) == (*q | 0x20) ) { p++; q++; } if ( *p == '\0' ) break; } if ( *r == '\0' ) continue; /* stop every 24 lines */ if ( offset == SyNrRows && raw ) { syEchos( " -- <space> for more --", fin ); ch = syGetch( fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); syEchos( " ", fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); if ( ch == 'q' ) { syEchos( "\n", fin ); break; } else if ( ch == '\n' || ch == '\r' ) { offset = SyNrRows - 1; } else { offset = 2; } } /* print the index line */ syEchos( " ", fin ); syEchos( secname, fin ); p = secname; q = line + 12; while ( *p == *q ) { p++; q++; } if ( *p != '\0' ) { syEchos( " (", fin ); for ( p = line + 12; *p != '}'; p++ ) ; *p = '\0'; syEchos( line + 12, fin ); syEchos( ")", fin ); } syEchos( "\n", fin ); offset++; /* we dont want no more index entries for this section */ secname[0] = '\0'; } /* close the index again and return */ SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* open the table of contents */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-12 ); SyStrncat( filename, "manual.toc", 11 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the table of contents file '", fin ); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <hlpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* search the table of contents */ chapnr = 0; secnr = 0; secname[0] = '\0'; matches = 0; while ( SyFgets( line, sizeof(line), fid ) ) { /* parse table of contents line */ for ( p = line; *p != '\0' && ! IsDigit(*p); p++ ) ; for ( i = 0; IsDigit(*p); p++ ) i = 10*i+*p-'0'; if ( *p == '.' ) p++; for ( j = 0; IsDigit(*p); p++ ) j = 10*j+*p-'0'; if ( *p == '}' ) p++; if ( i == 0 || ! IsAlpha(*p) ) { syEchos("Help: contentsline is garbage in 'manual.toc'",fin); SyFclose( fid ); return; } /* compare the line with the topic */ q = topic; match = 2; while ( *p != '}' && match ) { if ( *q != '\0' && (*p | 0x20) == (*q | 0x20) ) { p++; q++; } else if ( *q == ' ' || *q == '\0' ) { p++; match = 1; } else { match = 0; } } if ( *q != '\0' ) match = 0; /* if the offset is '-1' we are interested in the previous section */ if ( match == 2 && offset == -1 ) { if ( last[0] == '\0' ) { syEchos("Help: the last section is the first one\n", fin ); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } q = line; p = last; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; } /* if the offset is '1' we are interested in the next section */ if ( match == 2 && offset == 1 ) { if ( ! SyFgets( line, sizeof(line), fid ) ) { syEchos("Help: the last section is the last one\n", fin ); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } } /* if the offset if '-2' we are interested in the first section */ if ( match == 2 && offset == -2 ) { if ( last2[0] == '\0' ) { syEchos("Help: the last section is the first one\n", fin ); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } q = line; p = last2; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; } /* if the offset is '2' we are interested in the next chapter */ if ( match == 2 && offset == 2 ) { while ( 1 ) { if ( ! SyFgets( line, sizeof(line), fid ) ) { syEchos("Help: the last section is in the last chapter\n", fin ); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } for ( p = line; *p != '\0' && ! IsDigit(*p); p++ ) ; for ( ; *p != '}' && *p != '.'; p++ ) ; if ( *p == '}' ) break; } } /* parse table of contents line (again) */ for ( p = line; *p != '\0' && ! IsDigit(*p); p++ ) ; for ( i = 0; IsDigit(*p); p++ ) i = 10*i+*p-'0'; if ( *p == '.' ) p++; for ( j = 0; IsDigit(*p); p++ ) j = 10*j+*p-'0'; if ( *p == '}' ) p++; if ( i == 0 || ! IsAlpha(*p) ) { syEchos("Help: contentsline is garbage in 'manual.toc'",fin); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* if this is a precise match remember chapter and section number */ if ( match == 2 ) { /* remember the chapter and section number */ chapnr = i; secnr = j; /* get the section name */ q = secname; while ( *p != '}' ) *q++ = *p++; *q = '\0'; /* we dont have to look further */ matches = 1; break; } /* append a weak match to the list of matches */ else if ( match == 1 ) { /* remember the chapter and section number */ chapnr = i; secnr = j; /* append the section name to the list of sections */ q = secname; while ( *q != '\0' ) q++; if ( q != secname && q < secname+sizeof(secname)-1 ) *q++ = '\n'; while ( *p != '}' && q < secname+sizeof(secname)-1 ) *q++ = *p++; *q = '\0'; /* we have to continue the search */ matches++; } /* copy this line into <last> */ q = last; p = line; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; /* if the line is a chapter line copy it into <last2> */ if ( j == 0 ) { q = last2; p = line; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; } } /* close the table of contents file */ SyFclose( fid ); /* if no section was found complain */ if ( matches == 0 ) { syEchos( "Help: no section with this name was found\n", fin ); if ( raw ) syStopraw( fin ); return; } /* if several sections were found return */ if ( 2 <= matches ) { syEchos( "Help: several sections match this topic\n", fin ); syEchos( secname, fin ); syEchos( "\n", fin ); if ( raw ) syStopraw( fin ); return; } /* if this is the first time we help collect the chapter file names */ if ( syChapnames[0][0] == '\0' ) { /* open the 'manual.tex' file */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-12 ); SyStrncat( filename, "manual.tex", 11 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the manual file '", fin ); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <hlpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* scan this file for '\Include' lines, each contains one chapter */ offset = 0; while ( SyFgets( line, sizeof(line), fid ) ) { p = line; q = "\\Include{"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) { q = syChapnames[offset]; while ( *p != '}' ) *q++ = *p++; *q = '\0'; offset++; } } /* close the 'manual.tex' file again */ SyFclose( fid ); } /* try to open the chapter file */ filename[0] = '\0'; SyStrncat( filename, SyHelpname, sizeof(filename)-13 ); SyStrncat( filename, syChapnames[chapnr-1], 9 ); SyStrncat( filename, ".tex", 4 ); fid = SyFopen( filename, "r" ); if ( fid == -1 ) { syEchos( "Help: cannot open the chapter file '", fin ); syEchos( filename, fin ); syEchos( "'\n", fin ); syEchos( "maybe use the option '-h <hlpname>'?\n", fin ); if ( raw ) syStopraw( fin ); return; } /* create the line we are looking for */ if ( secnr == 0 ) { secline[0] = '\0'; SyStrncat( secline, "\\Chapter{", 10 ); SyStrncat( secline, secname, sizeof(secline)-10 ); } else { secline[0] = '\0'; SyStrncat( secline, "\\Section{", 10 ); SyStrncat( secline, secname, sizeof(secline)-10 ); } /* search the file for the correct '\Chapter' or '\Section' line */ match = 0; while ( ! match && SyFgets( line, sizeof(line), fid ) ) { p = line; q = secline; while ( *p == *q ) { p++; q++; } match = (*q == '\0' && *p == '}'); p = line; q = "\\Chapter{"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) { q = chapname; while ( *p != '}' ) *q++ = *p++; *q = '\0'; } } /* raise an error if this line was not found */ if ( ! match ) { syEchos( "Help: could not find section '", fin ); syEchos( secname, fin ); syEchos( "' in chapter file '", fin ); syEchos( filename, fin ); syEchos( "'\n", fin ); SyFclose( fid ); if ( raw ) syStopraw( fin ); return; } /* remember this topic for the next time */ p = secname; syLastIndex = (syLastIndex + 1) % 16; q = syLastTopics[ syLastIndex ]; while ( *p != '\0' ) *q++ = *p++; *q = '\0'; /* make a header line */ line[0] = '\0'; SyStrncat( line, secname, 40 ); SyStrncat( line, " _____________________________________________________________________", 73 - SyStrlen(chapname) ); line[72-SyStrlen(chapname)] = ' '; line[73-SyStrlen(chapname)] = '\0'; SyStrncat( line, chapname, SyStrlen(chapname)+1 ); SyStrncat( line, "\n", 2 ); syEchos( " ", fin ); syEchos( line, fin ); /* print everything from here to the next section line */ offset = 2; status = 'a'; while ( SyFgets( line, sizeof(line), fid ) ) { /* skip lines that begin with '\index{' */ p = line; q = "\\index{"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) continue; /* skip lines that begin with '\newpage' */ p = line; q = "\\newpage"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) continue; /* skip lines that begin with '\begin{' */ p = line; q = "\\begin{"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) continue; /* skip lines that begin with '\end{' */ p = line; q = "\\end{"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) continue; /* break if we reach a '%%%%%%%%%%%%%%%...' line */ p = line; q = "%%%%%%%%%%%%%%%%"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) break; /* skip other lines that begin with a '%' */ p = line; q = "%"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) continue; /* stop every 24 lines */ if ( offset == SyNrRows && raw ) { syEchos( " -- <space> for more --", fin ); ch = syGetch( fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); syEchos( " ", fin ); syEchos("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", fin); if ( ch == 'q' ) { syEchos( "\n", fin ); break; } else if ( ch == '\n' || ch == '\r' ) { offset = SyNrRows - 1; } else { offset = 2; } } /* insert empty line for '\vspace{' */ p = line; q = "\\vspace{"; while ( *p == *q ) { p++; q++; } if ( *q == '\0' ) { syEchos( "\n", fin ); offset++; continue; } /* display the line */ p = line; q = last; spaces = 0; while ( *p != '\0' ) { if ( *p == '\\' && status != '|' ) { if ( last < q && q[-1] == ' ' ) *q++ = ' '; else spaces++; } else if ( *p=='{' && (line==p || p[-1]!='\\') && status!='|' ) { if ( status == '$' ) *q++ = '('; else if ( last < q && q[-1] == ' ' ) *q++ = ' '; else spaces++; } else if ( *p=='}' && (line==p || p[-1]!='\\') && status!='|' ) { if ( status == '$' ) *q++ = ')'; else if ( last < q && q[-1] == ' ' ) *q++ = ' '; else spaces++; } else if ( *p=='$' && (line==p || p[-1]!='\\') && status!='|' ) { if ( last < q && q[-1] == ' ' ) *q++ = ' '; else spaces++; if ( status != '$' ) status = '$'; else status = 'a'; } else if ( *p == ' ' && status != '|' ) { *q++ = ' '; while ( 0 < spaces ) { *q++ = ' '; spaces--; } } else if ( *p=='|' && (line==p || p[-1]!='\\' || status=='|' || status=='#') ) { if ( status == '|' || status == '#' ) status = 'a'; else status = '|'; spaces++; } else if ( *p == '#' ) { if ( status == '|' ) status = '#'; *q++ = *p; } else if ( *p == '\n' ) { if ( status == '#' ) status = '|'; *q++ = *p; } else if ( *p == '>' && line!=p && p[-1]=='\\' ) { spaces++; } else if ( *p == '=' && line!=p && p[-1]=='\\' ) { spaces++; } else { *q++ = *p; } p++; } *q = '\0'; syEchos( " ", fin ); syEchos( last, fin ); offset++; } /* close the file again */ SyFclose( fid ); if ( raw ) syStopraw( fin ); } /**************************************************************************** ** *F SyGetmen( <size> ) . . . . . . . . allocate memory block of <size> bytes ** ** 'SyGetmem' gets a block of <size> bytes from the operating system and ** returns a pointer to it. <size> must be a multiple of 4 and the block ** returned by 'SyGetmem' is lonword aligned. It is cleared to contain only ** zeroes. If there is not enough memory available returns '(char*)-1'. ** 'SyGetmem' returns adjacent blocks on subsequent calls, otherwise Gasman ** would get confused. ** ** If the operating system does not support dynamic memory managment, simply ** give 'SyGetmem' a static buffer, from where it returns the blocks. */ /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For UNIX, OS/2, MS-DOS, TOS, and VMS, 'SyGetmem' calls 'sbrk', checking ** that the new block is adjacent to the old, otherwise other functions, ** e.g., 'malloc' have called 'sbrk'. This can be dealt with by ** pre'malloc'ing storage with the '-a' option. */ #if SYS_BSD||SYS_USG||SYS_OS2_EMX||SYS_MSDOS_DJGPP||SYS_TOS_GCC2||SYS_VMS #ifndef SYS_HAS_MISC_PROTO /* UNIX decl. from 'man' */ extern char * sbrk P(( int )); #endif char * syHighmem; char * SyGetmem ( size ) long size; { char * ret; /* force alignment on first call */ if ( syHighmem == (char*)0 ) ret = sbrk( 4 - (int)sbrk(0) % 4 ); /* get the memory */ ret = sbrk( (int)size ); /* check that the new memory is adjacent to the last block */ if ( ret != (char*)-1 && syHighmem != 0 && ret != syHighmem ) { fputs("gap: sorry, cannot extend the workspace, ",stderr); fputs("maybe use option '-a <memory>'?\n",stderr); SyExit( 1 ); } /* remember the high memory for the next call */ syHighmem = ret + size; /* return address of the block */ return ret; } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Under MACH virtual memory managment functions are used instead of 'sbrk'. */ #if SYS_MACH #ifdef ARCH_INCLUDE # include <mach/mach.h> /* mach 3.0 memory functions */ #else # include <mach.h> /* mach 2.0 memory functions */ #endif vm_address_t syBase = 0; long sySize = 0; long syUsed = 0; /* 'SyGetmem' uses virtual memory on a NeXT */ char * SyGetmem ( size ) long size; { vm_address_t adr; long new; /* allocate memory anywhere on first call */ if ( syBase == 0 ) { sySize = ( (size+vm_page_size-1) / vm_page_size ) * vm_page_size; syUsed = size; if ( vm_allocate(task_self(),&syBase,sySize,TRUE) != KERN_SUCCESS ) { fputs("gap: panic 'SyGetmem' vm_allocate failed!\n",stderr); SyExit(1); } return (char*) syBase; } /* if the new request still fits return */ else if ( syUsed + size <= sySize ) { syUsed += size; return (char*) syBase + (syUsed-size); } /* get more memory from system */ else { new = ( (size+vm_page_size-1) / vm_page_size ) * vm_page_size; adr = (vm_address_t)( (char*) syBase + sySize ); if ( vm_allocate(task_self(),&adr,new,FALSE) != KERN_SUCCESS ) { fputs("gap: sorry, cannot extend the workspace, ",stderr); fputs("maybe use option '-a <memory>'?\n",stderr); SyExit( 1 ); } syUsed += size; sySize += new; return (char*) syBase + (syUsed-size); } } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For the MAC under MPW we currently use 'calloc'. This does not allow to ** extend the arena, but this is a problem of the memory manager anyhow. */ #if SYS_MAC_MPW #ifndef SYS_HAS_CALLOC_PROTO extern char * calloc P(( int, int )); #endif char * syWorkspace; char * SyGetmem ( size ) long size; { /* get the memory */ /*N 1993/05/29 martin try to make it possible to extend the arena */ if ( syWorkspace == 0 ) { syWorkspace = calloc( (int)size/4, 4 ); syWorkspace = (char*)(((long)syWorkspace + 3) & ~3); return syWorkspace; } else { return (char*)-1; } } #endif /** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** For Mac under Think C we use 'NewPtr'. This does not allow to extend the ** area, but this is a problem of the memory manager anyhow. */ #if SYS_MAC_SYC #ifndef SYS_STRING_H /* string functions: */ # include <string.h> /* 'memset' */ # define SYS_STRING_H #endif #ifndef SYS_HAS_MEMSET_PROTO /* ANSI/TRAD decl. from H&S ?.? */ extern void * memset P(( void * mem, int chr, size_t size )); #endif char * syWorkspace; char * SyGetmem ( size ) long size; { /* get the memory */ if ( syWorkspace == 0 ) { syWorkspace = (char*)NewPtr( size + 3 ); syWorkspace = (char*)(((long)syWorkspace + 3) & ~3); memset( syWorkspace, 0, size ); return syWorkspace; } else { return (char*)-1; } } #endif /**************************************************************************** ** *F InitSystem( <argc>, <argv> ) . . . . . . . . . initialize system package ** ** 'InitSystem' is called very early during the initialization from 'main'. ** It is passed the command line array <argc>, <argv> to look for options. ** ** For UNIX it initializes the default files 'stdin', 'stdout' and 'stderr', ** installs the handler 'syAnsIntr' to answer the user interrupts '<ctr>-C', ** scans the command line for options, tries to find 'LIBNAME/init.g' and ** '$HOME/.gaprc' and copies the remaining arguments into 'SyInitfiles'. */ #ifndef SYS_STDLIB_H /* ANSI standard functions */ # if SYS_ANSI # include <stdlib.h> # endif # define SYS_STDLIB_H #endif #ifndef SYS_HAS_MISC_PROTO /* ANSI/TRAD decl. from H&S 20, 13 */ extern char * getenv P(( SYS_CONST char * )); extern int atoi P(( SYS_CONST char * )); #endif #ifndef SYS_HAS_MISC_PROTO /* UNIX decl. from 'man' */ extern int isatty P(( int )); extern char * ttyname P(( int )); #endif #ifndef SYS_STDLIB_H /* ANSI standard functions */ # if SYS_ANSI # include <stdlib.h> # endif # define SYS_STDLIB_H #endif #ifndef SYS_HAS_MALLOC_PROTO # if SYS_ANSI /* ANSI decl. from H&S 16.1, 16.2 */ extern void * malloc P(( size_t )); extern void free P(( void * )); # else /* TRAD decl. from H&S 16.1, 16.2 */ extern char * malloc P(( unsigned )); extern void free P(( char * )); # endif #endif #if SYS_TOS_GCC2 # ifndef SYS_BASEPAGE_H /* definition of basepage */ # include <basepage.h> # define SYS_BASEPAGE_H # endif #endif #if SYS_MAC_SYC #ifndef SYS_CONSOLE_H /* console stuff: */ # include <Console.h> /* 'console_options', 'cinverse' */ # define SYS_CONSOLE_H #endif #endif #if SYS_MAC_MPW || SYS_MAC_SYC # ifndef SYS_HAS_TOOL # ifndef SYS_MEMORY_H /* Memory stuff: */ # include <Memory.h> /* 'GetApplLimit', 'SetApplLimit', */ # define SYS_MEMORY_H /* 'MaxApplZone', 'StackSpace', */ # endif /* 'MaxMem' */ # endif #endif #if SYS_MAC_MPW || SYS_MAC_SYC # ifndef SYS_HAS_TOOL char * syArgv [128]; char syArgl [1024]; # endif #endif #if SYS_MAC_SYC long * dedgen; long * dedcos; long dedSize = 40960; #endif void InitSystem ( argc, argv ) int argc; char * argv []; { long fid; /* file identifier */ long pre = 63*1024; /* amount to pre'malloc'ate */ int gaprc = 1; /* read the .gaprc file */ char * ptr; /* pointer to the pre'malloc'ated */ long i, k; /* loop variables */ #if SYS_MAC_MPW || SYS_MAC_SYC # ifndef SYS_HAS_TOOL /* Increase the amount of stack space available to GAP. */ /* Following "Inside Macintosh - Memory" 1992, pages 1-42. */ /* For use with MPW 'SIOW.o' *after* changing instruction word */ /* at 3F94 from 'A063' (call to '_MaxApplZone') to '4E71' (NOP). */ /* 'fix_SIOW.c' is the source for an MPW tool, which does this safely. */ /* Otherwise bungee-jumping the stack will lead to fatal head injuries.*/ /* Dave Bayer, 1994/07/14 */ SetApplLimit( GetApplLimit() - (SyStackSpace - StackSpace() + 1024) ); MaxApplZone(); if ( StackSpace() < SyStackSpace ) { fputs("gap: cannot get enough stack space.\n",stderr); SyExit( 1 ); } # endif #endif /* open the standard files */ #if SYS_BSD || SYS_MACH || SYS_USG || SYS_VMS syBuf[0].fp = stdin; setbuf( stdin, syBuf[0].buf ); if ( isatty( fileno(stdin) ) ) { if ( isatty( fileno(stdout) ) && ! SyStrcmp( ttyname(fileno(stdin)), ttyname(fileno(stdout)) ) ) syBuf[0].echo = stdout; else syBuf[0].echo = fopen( ttyname(fileno(stdin)), "w" ); if ( syBuf[0].echo != (FILE*)0 && syBuf[0].echo != stdout ) setbuf( syBuf[0].echo, (char*)0 ); } else { syBuf[0].echo = stdout; } syBuf[1].fp = stdout; setbuf( stdout, (char*)0 ); if ( isatty( fileno(stderr) ) ) { if ( isatty( fileno(stdin) ) && ! SyStrcmp( ttyname(fileno(stdin)), ttyname(fileno(stderr)) ) ) syBuf[2].fp = stdin; else syBuf[2].fp = fopen( ttyname(fileno(stderr)), "r" ); if ( syBuf[2].fp != (FILE*)0 && syBuf[2].fp != stdin ) setbuf( syBuf[2].fp, syBuf[2].buf ); syBuf[2].echo = stderr; } syBuf[3].fp = stderr; setbuf( stderr, (char*)0 ); #endif #if SYS_OS2_EMX syBuf[0].fp = stdin; setbuf( stdin, syBuf[0].buf ); if ( isatty( fileno(stdin) ) ) { if ( isatty( fileno(stdout) ) ) syBuf[0].echo = stdout; else syBuf[0].echo = fopen( "CON", "w" ); if ( syBuf[0].echo != (FILE*)0 && syBuf[0].echo != stdout ) setbuf( syBuf[0].echo, (char*)0 ); } else { syBuf[0].echo = stdout; } syBuf[1].fp = stdout; setbuf( stdout, (char*)0 ); if ( isatty( fileno(stderr) ) ) { if ( isatty( fileno(stdin) ) ) syBuf[2].fp = stdin; else syBuf[2].fp = fopen( "CON", "r" ); if ( syBuf[2].fp != (FILE*)0 && syBuf[2].fp != stdin ) setbuf( syBuf[2].fp, syBuf[2].buf ); syBuf[2].echo = stderr; } syBuf[3].fp = stderr; setbuf( stderr, (char*)0 ); #endif #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 syBuf[0].fp = stdin; setbuf( stdin, syBuf[0].buf ); syBuf[1].fp = stdout; setbuf( stdout, (char*)0 ); syBuf[3].fp = stderr; setbuf( stderr, (char*)0 ); if ( isatty( fileno(stderr) ) ) syBuf[2].fp = stderr; #endif #if SYS_MAC_MPW || SYS_MAC_SYC syBuf[0].fp = stdin; syBuf[1].fp = stdout; syBuf[2].fp = stdin; syBuf[3].fp = stderr; #endif /* install the signal handler for '<ctr>-C' */ #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX || SYS_VMS if ( signal( SIGINT, SIG_IGN ) != SIG_IGN ) signal( SIGINT, syAnswerIntr ); #endif #if SYS_OS2_EMX /* under OS/2, pressing <ctr>-Break sometimes generates SIGBREAK */ signal( SIGBREAK, syAnswerIntr ); #endif #if SYS_MAC_MPW # ifdef SYS_HAS_TOOL signal( SIGINT, &syAnswerIntr ); # endif #endif #if SYS_MAC_SYC signal( SIGINT, &syAnswerIntr ); #endif #if SYS_MAC_MPW || SYS_MAC_SYC # ifndef SYS_HAS_TOOL /* the Macintosh doesn't support command line options, read from file */ if ( (fid = SyFopen( "gap.options", "r" )) != -1 ) { argc = 0; argv = syArgv; argv[argc++] = "gap"; ptr = syArgl; while ( SyFgets( ptr, (sizeof(syArgl)-1) - (ptr-syArgl), fid ) && (ptr-syArgl) < (sizeof(syArgl)-1) ) { while ( *ptr != '#' && *ptr != '\0' ) ptr++; } ptr = syArgl; while ( *ptr==' ' || *ptr=='\t' || *ptr=='\n' ) *ptr++ = '\0'; while ( *ptr != '\0' ) { argv[argc++] = ptr; while ( *ptr!=' ' && *ptr!='\t' && *ptr!='\n' && *ptr!='\0' ) { if ( *ptr=='\\' ) for ( k = 0; ptr[k+1] != '\0'; k++ ) ptr[k] = ptr[k+1]; ptr++; } while ( *ptr==' ' || *ptr=='\t' || *ptr=='\n' ) *ptr++ = '\0'; } SyFclose( fid ); } # endif #endif /* scan the command line for options */ while ( argc > 1 && argv[1][0] == '-' ) { if ( SyStrlen(argv[1]) != 2 ) { fputs("gap: sorry, options must not be grouped '",stderr); fputs(argv[1],stderr); fputs("'.\n",stderr); goto usage; } switch ( argv[1][1] ) { case 'b': /* '-b', supress the banner */ SyBanner = ! SyBanner; break; case 'g': /* '-g', Gasman should be verbose */ SyGasman = ! SyGasman; break; case 'l': /* '-l <libname>', change the value of 'LIBNAME' */ if ( argc < 3 ) { fputs("gap: option '-l' must have an argument.\n",stderr); goto usage; } SyLibname[0] = '\0'; SyStrncat( SyLibname, argv[2], sizeof(SyLibname)-2 ); #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX if ( SyLibname[SyStrlen(SyLibname)-1] != '/' && SyLibname[SyStrlen(SyLibname)-1] != ';' ) SyStrncat( SyLibname, "/", 1 ); #endif #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 if ( SyLibname[SyStrlen(SyLibname)-1] != '\\' && SyLibname[SyStrlen(SyLibname)-1] != ';' ) SyStrncat( SyLibname, "\\", 1 ); #endif ++argv; --argc; break; case 'h': /* '-h <hlpname>', change the value of 'HLPNAME' */ if ( argc < 3 ) { fputs("gap: option '-h' must have an argument.\n",stderr); goto usage; } SyHelpname[0] = '\0'; #if SYS_BSD || SYS_MACH || SYS_USG || SYS_OS2_EMX SyStrncat( SyHelpname, argv[2], sizeof(SyLibname)-2 ); if ( SyLibname[SyStrlen(SyHelpname)-1] != '/' ) SyStrncat( SyHelpname, "/", 1 ); #endif #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 SyStrncat( SyHelpname, argv[2], sizeof(SyLibname)-2 ); if ( SyLibname[SyStrlen(SyHelpname)-1] != '\\' ) SyStrncat( SyHelpname, "\\", 1 ); #endif ++argv; --argc; break; case 'm': /* '-m <memory>', change the value of 'SyMemory' */ if ( argc < 3 ) { fputs("gap: option '-m' must have an argument.\n",stderr); goto usage; } SyMemory = atoi(argv[2]); if ( argv[2][SyStrlen(argv[2])-1] == 'k' || argv[2][SyStrlen(argv[2])-1] == 'K' ) SyMemory = SyMemory * 1024; if ( argv[2][SyStrlen(argv[2])-1] == 'm' || argv[2][SyStrlen(argv[2])-1] == 'M' ) SyMemory = SyMemory * 1024 * 1024; ++argv; --argc; break; case 'a': /* '-a <memory>', set amount to pre'm*a*lloc'ate */ if ( argc < 3 ) { fputs("gap: option '-a' must have an argument.\n",stderr); goto usage; } pre = atoi(argv[2]); if ( argv[2][SyStrlen(argv[2])-1] == 'k' || argv[2][SyStrlen(argv[2])-1] == 'K' ) pre = pre * 1024; if ( argv[2][SyStrlen(argv[2])-1] == 'm' || argv[2][SyStrlen(argv[2])-1] == 'M' ) pre = pre * 1024 * 1024; ++argv; --argc; break; case 'n': /* '-n', disable command line editing */ if ( ! syWindow ) syLineEdit = 0; break; case 'f': /* '-f', force line editing */ if ( ! syWindow ) syLineEdit = 2; break; case 'q': /* '-q', GAP should be quiet */ SyQuiet = ! SyQuiet; break; case 'x': /* '-x', specify the length of a line */ if ( argc < 3 ) { fputs("gap: option '-x' must have an argument.\n",stderr); goto usage; } SyNrCols = atoi(argv[2]); ++argv; --argc; break; case 'y': /* '-y', specify the number of lines */ if ( argc < 3 ) { fputs("gap: option '-y' must have an argument.\n",stderr); goto usage; } SyNrRows = atoi(argv[2]); ++argv; --argc; break; case 'e': /* '-e', do not quit GAP on '<ctr>-D' */ if ( ! syWindow ) syCTRD = ! syCTRD; break; #if SYS_BSD || SYS_MACH || SYS_USG case 'p': /* '-p', start GAP package mode for output */ syWindow = 1; syLineEdit = 1; syCTRD = 1; syWinPut( 0, "@p", "" ); syBuf[2].fp = stdin; syBuf[2].echo = stdout; syBuf[3].fp = stdout; break; #endif #if SYS_MSDOS_DJGPP || SYS_TOS_GCC2 || SYS_MAC_MPW || SYS_MAC_SYC case 'z': /* '-z', specify interrupt check frequency */ if ( argc < 3 ) { fputs("gap: option '-z' must have an argument.\n",stderr); goto usage; } syIsIntrFreq = atoi(argv[2]); ++argv; --argc; break; #endif #if SYS_MAC_SYC case 'Z': /* '-Z', specify background check frequency */ if ( argc < 3 ) { fputs("gap: option '-Z' must have an argument.\n",stderr); goto usage; } syIsBackFreq = atoi(argv[2]); ++argv; --argc; break; #endif #if SYS_OS2_EMX case 'E': /* '-E', running under Emacs under OS/2 */ syLineEdit = 2; syBuf[2].fp = stdin; syBuf[2].echo = stderr; break; #endif case 'r': /* don't read the '.gaprc' file */ gaprc = ! gaprc; break; default: /* default, no such option */ fputs("gap: '",stderr); fputs(argv[1],stderr); fputs("' option is unknown.\n",stderr); goto usage; } ++argv; --argc; } #if SYS_MAC_SYC /* set up the console window options */ console_options.title = "\pGAP 3.4.2"; console_options.nrows = SyNrRows; console_options.ncols = SyNrCols; console_options.pause_atexit = 0; cinverse( 1, stdin ); #endif #if SYS_MAC_SYC /* allocate 'dedgen' und 'dedcos' */ dedgen = (long*)NewPtr( dedSize * sizeof(long) ); dedcos = (long*)NewPtr( dedSize * sizeof(long) ); #endif /* premalloc stuff */ ptr = malloc( pre ); if ( ptr != 0 ) free( ptr ); /* try to find 'LIBNAME/init.g' to read it upon initialization */ i = 0; fid = -1; while ( fid == -1 && i <= SyStrlen(SyLibname) ) { for ( k = i; SyLibname[k] != '\0' && SyLibname[k] != ';'; k++ ) ; SyInitfiles[0][0] = '\0'; if ( sizeof(SyInitfiles[0]) < k-i+6+1 ) { fputs("gap: <libname> is too long\n",stderr); goto usage; } SyStrncat( SyInitfiles[0], SyLibname+i, k-i ); SyStrncat( SyInitfiles[0], "init.g", 6 ); if ( (fid = SyFopen( SyInitfiles[0], "r" )) != -1 ) SyFclose( fid ); i = k + 1; } if ( fid != -1 ) { i = 1; } else { i = 0; SyInitfiles[0][0] = '\0'; if ( ! SyQuiet ) { fputs("gap: hmm, I cannot find '",stderr); fputs(SyLibname,stderr); fputs("init.g', maybe use option '-l <libname>'?\n",stderr); } } if ( gaprc ) { #if SYS_BSD || SYS_MACH || SYS_USG if ( getenv("HOME") != 0 ) { SyInitfiles[i][0] = '\0'; SyStrncat(SyInitfiles[i],getenv("HOME"),sizeof(SyInitfiles[0])-1); SyStrncat( SyInitfiles[i], "/.gaprc", (long)(sizeof(SyInitfiles[0])-1-SyStrlen(SyInitfiles[i]))); if ( (fid = SyFopen( SyInitfiles[i], "r" )) != -1 ) { ++i; SyFclose( fid ); } else { SyInitfiles[i][0] = '\0'; } } #endif #if SYS_OS2_EMX || SYS_MSDOS_DJGPP || SYS_TOS_GCC2 if ( getenv("HOME") != 0 ) { SyInitfiles[i][0] = '\0'; SyStrncat(SyInitfiles[i],getenv("HOME"),sizeof(SyInitfiles[0])-1); SyStrncat( SyInitfiles[i], "/gap.rc", (long)(sizeof(SyInitfiles[0])-1-SyStrlen(SyInitfiles[i]))); if ( (fid = SyFopen( SyInitfiles[i], "r" )) != -1 ) { ++i; SyFclose( fid ); } else { SyInitfiles[i][0] = '\0'; } } #endif #if SYS_VMS if ( getenv("GAP_INI") != 0 ) { SyStrncat(SyInitfiles[i],getenv("GAP_INI"),sizeof(SyInitfiles[0])-1); if ( (fid = SyFopen( SyInitfiles[i], "r" )) != -1 ) { ++i; SyFclose( fid ); } else { SyInitfiles[i][0] = '\0'; } } #endif #if SYS_MAC_MPW || SYS_MAC_SYC SyInitfiles[i][0] = '\0'; SyStrncat( SyInitfiles[i], "gap.rc", (long)(sizeof(SyInitfiles[0])-1-SyStrlen(SyInitfiles[i]))); if ( (fid = SyFopen( SyInitfiles[i], "r" )) != -1 ) { ++i; SyFclose( fid ); } else { SyInitfiles[i][0] = '\0'; } #endif } /* use the files from the command line */ while ( argc > 1 ) { if ( i >= sizeof(SyInitfiles)/sizeof(SyInitfiles[0]) ) { fputs("gap: sorry, cannot handle so many init files.\n",stderr); goto usage; } SyInitfiles[i][0] = '\0'; SyStrncat( SyInitfiles[i], argv[1], sizeof(SyInitfiles[0])-1 ); ++i; ++argv; --argc; } #if SYS_TOS_GCC2 /* for TOS we compute the amount of allocatable memory */ if ( SyMemory <= 0 ) { SyMemory = (long)_base->p_hitpa - (long)_base->p_lowtpa - _base->p_tlen - _base->p_dlen - _base->p_blen - _stksize - pre - 8192 + SyMemory; } #endif #if SYS_VMS /* for VMS we need to create the virtual keyboards for raw reading */ smg$create_virtual_keyboard( &syVirKbd ); #endif #if SYS_MAC_MPW || SYS_MAC_SYC # ifndef SYS_HAS_TOOL /* find out how much memory we can now allocate in the zone */ if ( SyMemory <= 0 ) { SyMemory = MaxMem( &i ) - SyMemory - 384*1024; if ( SyMemory < 1024*1024 ) { fputs( "gap: please use the 'Get Info' command in the Finder 'Desk' menu\n", stderr ); fputs( " to set the minimum amount of memory to at least 2560 KByte,\n", stderr ); fputs( " and the preferred amount of memory to 5632 KByte or more.\n", stderr ); SyExit( 1 ); } } # endif #endif /* start the clock */ syStartTime = SyTime(); /* now we start */ return; /* print a usage message */ usage: fputs("usage: gap [-l <libname>] [-h <hlpname>] [-m <memory>]\n",stderr); fputs(" [-g] [-n] [-q] [-b] [-x <nr>] [-y <nr>]\n",stderr); fputs(" <file>...\n",stderr); fputs(" run the Groups, Algorithms and Programming system.\n",stderr); SyExit( 1 ); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.