Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346/****************************************************************************1**2*W gap.c GAP source Frank Celler3*W & Martin Schönert4**5**6*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany7*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland8*Y Copyright (C) 2002 The GAP Group9**10** This file contains the various read-eval-print loops and related stuff.11*/12#include <stdio.h>13#include <assert.h>14#include <string.h> /* memcpy */15#include <stdlib.h>1617#include "system.h" /* system dependent part */1819#ifdef HAVE_SYS_STAT_H20#include <sys/stat.h>21#endif2223#include <sys/time.h>24#include <unistd.h> /* move this and wrap execvp later */2526#include "gasman.h" /* garbage collector */27#include "objects.h" /* objects */28#include "scanner.h" /* scanner */2930#include "gap.h" /* error handling, initialisation */31#include "tls.h" /* thread-local storage */3233#include "read.h" /* reader */3435#include "gvars.h" /* global variables */36#include "calls.h" /* generic call mechanism */37#include "opers.h" /* generic operations */3839#include "ariths.h" /* basic arithmetic */4041#include "integer.h" /* integers */42#include "rational.h" /* rationals */43#include "cyclotom.h" /* cyclotomics */44#include "finfield.h" /* finite fields and ff elements */4546#include "bool.h" /* booleans */47#include "macfloat.h" /* machine doubles */48#include "permutat.h" /* permutations */49#include "trans.h" /* transformations */50#include "pperm.h" /* partial perms */5152#include "records.h" /* generic records */53#include "precord.h" /* plain records */5455#include "lists.h" /* generic lists */56#include "listoper.h" /* operations for generic lists */57#include "listfunc.h" /* functions for generic lists */58#include "plist.h" /* plain lists */59#include "set.h" /* plain sets */60#include "vector.h" /* functions for plain vectors */61#include "vecffe.h" /* functions for fin field vectors */62#include "blister.h" /* boolean lists */63#include "range.h" /* ranges */64#include "string.h" /* strings */65#include "vecgf2.h" /* functions for GF2 vectors */66#include "vec8bit.h" /* functions for other compressed67GF(q) vectors */68#include "objfgelm.h" /* objects of free groups */69#include "objpcgel.h" /* objects of polycyclic groups */70#include "objscoll.h" /* single collector */71#include "objccoll.h" /* combinatorial collector */72#include "objcftl.h" /* from the left collect */7374#include "dt.h" /* deep thought */75#include "dteval.h" /* deep thought evaluation */7677#include "sctable.h" /* structure constant table */78#include "costab.h" /* coset table */79#include "tietze.h" /* tietze helper functions */8081#include "code.h" /* coder */8283#include "exprs.h" /* expressions */84#include "stats.h" /* statements */85#include "funcs.h" /* functions */8687#include "intrprtr.h" /* interpreter */8889#include "compiler.h" /* compiler */9091#include "compstat.h" /* statically linked modules */9293#include "saveload.h" /* saving and loading */9495#include "streams.h" /* streams package */96#include "sysfiles.h" /* file input/output */97#include "weakptr.h" /* weak pointers */98#include "profile.h" /* profiling */99#ifdef GAPMPI100#include "gapmpi.h" /* ParGAP/MPI */101#endif102103#include "thread.h"104#include "tls.h"105#include "aobjects.h"106107#include "vars.h" /* variables */108109#include "intfuncs.h"110#include "iostream.h"111112/****************************************************************************113**114115*V Last . . . . . . . . . . . . . . . . . . . . . . global variable 'last'116**117** 'Last', 'Last2', and 'Last3' are the global variables 'last', 'last2',118** and 'last3', which are automatically assigned the result values in the119** main read-eval-print loop.120*/121UInt Last;122123124/****************************************************************************125**126*V Last2 . . . . . . . . . . . . . . . . . . . . . . global variable 'last2'127*/128UInt Last2;129130131/****************************************************************************132**133*V Last3 . . . . . . . . . . . . . . . . . . . . . . global variable 'last3'134*/135UInt Last3;136137138/****************************************************************************139**140*V Time . . . . . . . . . . . . . . . . . . . . . . global variable 'time'141**142** 'Time' is the global variable 'time', which is automatically assigned the143** time the last command took.144*/145UInt Time;146147148/****************************************************************************149**150*F ViewObjHandler . . . . . . . . . handler to view object and catch errors151**152** This is the function actually called in Read-Eval-View loops.153** We might be in trouble if the library has not (yet) loaded and so ViewObj154** is not yet defined, or the fallback methods not yet installed. To avoid155** this problem, we check, and use PrintObj if there is a problem156**157** We also install a hook to use the GAP level function 'CustomView' if158** it exists. This can for example be used to restrict the amount of output159** or to show long output in a pager or .....160**161** This function also supplies the \n after viewing.162*/163UInt ViewObjGVar;164UInt CustomViewGVar;165166void ViewObjHandler ( Obj obj )167{168volatile Obj func;169volatile Obj cfunc;170syJmp_buf readJmpError;171172/* get the functions */173func = ValAutoGVar(ViewObjGVar);174cfunc = ValAutoGVar(CustomViewGVar);175176/* if non-zero use this function, otherwise use `PrintObj' */177memcpy( readJmpError, TLS(ReadJmpError), sizeof(syJmp_buf) );178if ( ! READ_ERROR() ) {179if ( cfunc != 0 && TNUM_OBJ(cfunc) == T_FUNCTION ) {180CALL_1ARGS(cfunc, obj);181}182else if ( func != 0 && TNUM_OBJ(func) == T_FUNCTION ) {183ViewObj(obj);184}185else {186PrintObj( obj );187}188Pr( "\n", 0L, 0L );189memcpy( TLS(ReadJmpError), readJmpError, sizeof(syJmp_buf) );190}191else {192memcpy( TLS(ReadJmpError), readJmpError, sizeof(syJmp_buf) );193}194}195196197/****************************************************************************198**199*F main( <argc>, <argv> ) . . . . . . . main program, read-eval-print loop200*/201UInt QUITTINGGVar;202203204typedef struct {205const Char * name;206Obj * address;207} StructImportedGVars;208209#ifndef MAX_IMPORTED_GVARS210#define MAX_IMPORTED_GVARS 1024211#endif212213static StructImportedGVars ImportedGVars[MAX_IMPORTED_GVARS];214static Int NrImportedGVars;215216static StructImportedGVars ImportedFuncs[MAX_IMPORTED_GVARS];217static Int NrImportedFuncs;218219char *original_argv0;220static char **sysargv;221static char **sysenviron;222223Obj ShellContext = 0;224Obj BaseShellContext = 0;225UInt ShellContextDepth;226227228Obj Shell ( Obj context,229UInt canReturnVoid,230UInt canReturnObj,231UInt lastDepth,232UInt setTime,233Char *prompt,234Obj preCommandHook,235UInt catchQUIT,236Char *inFile,237Char *outFile)238{239UInt time = 0;240UInt status;241UInt dualSemicolon;242UInt oldindent;243UInt oldPrintDepth;244Obj res;245Obj oldShellContext;246Obj oldBaseShellContext;247Int oldRecursionDepth;248oldShellContext = TLS(ShellContext);249TLS(ShellContext) = context;250oldBaseShellContext = TLS(BaseShellContext);251TLS(BaseShellContext) = context;252TLS(ShellContextDepth) = 0;253oldRecursionDepth = TLS(RecursionDepth);254255/* read-eval-print loop */256if (!OpenOutput(outFile))257ErrorQuit("SHELL: can't open outfile %s",(Int)outFile,0);258259if(!OpenInput(inFile))260{261CloseOutput();262ErrorQuit("SHELL: can't open infile %s",(Int)inFile,0);263}264265oldPrintDepth = TLS(PrintObjDepth);266TLS(PrintObjDepth) = 0;267oldindent = TLS(Output)->indent;268TLS(Output)->indent = 0;269270while ( 1 ) {271272/* start the stopwatch */273if (setTime)274time = SyTime();275276/* read and evaluate one command */277TLS(Prompt) = prompt;278ClearError();279TLS(PrintObjDepth) = 0;280TLS(Output)->indent = 0;281TLS(RecursionDepth) = 0;282283/* here is a hook: */284if (preCommandHook) {285if (!IS_FUNC(preCommandHook))286{287Pr("#E CommandHook was non-function, ignoring\n",0L,0L);288}289else290{291Call0ArgsInNewReader(preCommandHook);292/* Recover from a potential break loop: */293TLS(Prompt) = prompt;294ClearError();295}296}297298/* now read and evaluate and view one command */299status = ReadEvalCommand(TLS(ShellContext), &dualSemicolon);300if (TLS(UserHasQUIT))301break;302303304/* handle ordinary command */305if ( status == STATUS_END && TLS(ReadEvalResult) != 0 ) {306307/* remember the value in 'last' */308if (lastDepth >= 3)309AssGVar( Last3, VAL_GVAR( Last2 ) );310if (lastDepth >= 2)311AssGVar( Last2, VAL_GVAR( Last ) );312if (lastDepth >= 1)313AssGVar( Last, TLS(ReadEvalResult) );314315/* print the result */316if ( ! dualSemicolon ) {317ViewObjHandler( TLS(ReadEvalResult) );318}319320}321322/* handle return-value or return-void command */323else if (status & STATUS_RETURN_VAL)324if(canReturnObj)325break;326else327Pr( "'return <object>' cannot be used in this read-eval-print loop\n",3280L, 0L );329330else if (status & STATUS_RETURN_VOID)331if(canReturnVoid )332break;333else334Pr( "'return' cannot be used in this read-eval-print loop\n",3350L, 0L );336337/* handle quit command or <end-of-file> */338else if ( status & (STATUS_EOF | STATUS_QUIT ) ) {339TLS(RecursionDepth) = 0;340TLS(UserHasQuit) = 1;341break;342}343344/* handle QUIT */345else if (status & (STATUS_QQUIT)) {346TLS(UserHasQUIT) = 1;347break;348}349350/* stop the stopwatch */351if (setTime)352AssGVar( Time, INTOBJ_INT( SyTime() - time ) );353354if (TLS(UserHasQuit))355{356FlushRestOfInputLine();357TLS(UserHasQuit) = 0; /* quit has done its job if we are here */358}359360}361362TLS(PrintObjDepth) = oldPrintDepth;363TLS(Output)->indent = oldindent;364CloseInput();365CloseOutput();366TLS(BaseShellContext) = oldBaseShellContext;367TLS(ShellContext) = oldShellContext;368TLS(RecursionDepth) = oldRecursionDepth;369if (TLS(UserHasQUIT))370{371if (catchQUIT)372{373TLS(UserHasQUIT) = 0;374MakeReadWriteGVar(QUITTINGGVar);375AssGVar(QUITTINGGVar, True);376MakeReadOnlyGVar(QUITTINGGVar);377return Fail;378}379else380ReadEvalError();381}382383if (status & (STATUS_EOF | STATUS_QUIT | STATUS_QQUIT))384{385return Fail;386}387if (status & STATUS_RETURN_VOID)388{389res = NEW_PLIST(T_PLIST_EMPTY,0);390SET_LEN_PLIST(res,0);391return res;392}393if (status & STATUS_RETURN_VAL)394{395res = NEW_PLIST(T_PLIST_HOM,1);396SET_LEN_PLIST(res,1);397SET_ELM_PLIST(res,1,TLS(ReadEvalResult));398return res;399}400assert(0);401return (Obj) 0;402}403404405406Obj FuncSHELL (Obj self, Obj args)407{408Obj context = 0;409UInt canReturnVoid = 0;410UInt canReturnObj = 0;411Int lastDepth = 0;412UInt setTime = 0;413Obj prompt = 0;414Obj preCommandHook = 0;415Obj infile;416Obj outfile;417Obj res;418Char promptBuffer[81];419UInt catchQUIT = 0;420421if (!IS_PLIST(args) || LEN_PLIST(args) != 10)422ErrorMayQuit("SHELL takes 10 arguments",0,0);423424context = ELM_PLIST(args,1);425if (TNUM_OBJ(context) != T_LVARS)426ErrorMayQuit("SHELL: 1st argument should be a local variables bag",0,0);427428if (ELM_PLIST(args,2) == True)429canReturnVoid = 1;430else if (ELM_PLIST(args,2) == False)431canReturnVoid = 0;432else433ErrorMayQuit("SHELL: 2nd argument (can return void) should be true or false",0,0);434435if (ELM_PLIST(args,3) == True)436canReturnObj = 1;437else if (ELM_PLIST(args,3) == False)438canReturnObj = 0;439else440ErrorMayQuit("SHELL: 3rd argument (can return object) should be true or false",0,0);441442if (!IS_INTOBJ(ELM_PLIST(args,4)))443ErrorMayQuit("SHELL: 4th argument (last depth) should be a small integer",0,0);444lastDepth = INT_INTOBJ(ELM_PLIST(args,4));445if (lastDepth < 0 )446{447Pr("#W SHELL: negative last depth treated as zero",0,0);448lastDepth = 0;449}450else if (lastDepth > 3 )451{452Pr("#W SHELL: last depth greater than 3 treated as 3",0,0);453lastDepth = 3;454}455456if (ELM_PLIST(args,5) == True)457setTime = 1;458else if (ELM_PLIST(args,5) == False)459setTime = 0;460else461ErrorMayQuit("SHELL: 5th argument (set time) should be true or false",0,0);462463prompt = ELM_PLIST(args,6);464if (!IsStringConv(prompt) || GET_LEN_STRING(prompt) > 80)465ErrorMayQuit("SHELL: 6th argument (prompt) must be a string of length at most 80 characters",0,0);466promptBuffer[0] = '\0';467strlcat(promptBuffer, CSTR_STRING(prompt), sizeof(promptBuffer));468469preCommandHook = ELM_PLIST(args,7);470471if (preCommandHook == False)472preCommandHook = 0;473else if (!IS_FUNC(preCommandHook))474ErrorMayQuit("SHELL: 7th argument (preCommandHook) must be function or false",0,0);475476477infile = ELM_PLIST(args,8);478if (!IsStringConv(infile))479ErrorMayQuit("SHELL: 8th argument (infile) must be a string",0,0);480481outfile = ELM_PLIST(args,9);482if (!IsStringConv(infile))483ErrorMayQuit("SHELL: 9th argument (outfile) must be a string",0,0);484485if (ELM_PLIST(args,10) == True)486catchQUIT = 1;487else if (ELM_PLIST(args,10) == False)488catchQUIT = 0;489else490ErrorMayQuit("SHELL: 10th argument (catch QUIT) should be true or false",0,0);491492res = Shell(context, canReturnVoid, canReturnObj, lastDepth, setTime, promptBuffer, preCommandHook, catchQUIT,493CSTR_STRING(infile), CSTR_STRING(outfile));494495TLS(UserHasQuit) = 0;496return res;497}498#ifdef HAVE_REALPATH499500static void StrAppend(char **st, const char *st2)501{502Int len,len2;503if (*st == NULL)504len = 0;505else506len = strlen(*st);507len2 = strlen(st2);508*st = realloc(*st,len+len2+1);509if (*st == NULL) {510printf("Extremely unexpected out of memory error. Giving up.\n");511exit(1);512}513memcpy(*st + len, st2, len2);514}515516static void DoFindMyself(char *myself, char **mypath, char **gappath)517{518char *tmppath;519char *p;520521/* First we find our own position in the filesystem: */522*mypath = realpath(myself,NULL);523if (*mypath == NULL) {524printf("Could not determine my own path, giving up.\n");525exit(-1);526}527tmppath = NULL;528StrAppend(&tmppath,*mypath);529p = tmppath+strlen(tmppath);530while (*p != '/') p--;531*p = 0;532StrAppend(&tmppath,"/../..");533*gappath = realpath(tmppath,NULL);534if (*gappath == NULL) {535printf("Could not determine GAP path, giving up.\n");536exit(-2);537}538free(tmppath);539}540541542int DoCreateStartupScript(int argc, char *argv[], int withws)543{544/* This is used to create a startup shell script, possibly using545* a saved workspace in a standard location. */546/* We can use malloc/realloc here arbitrarily since this GAP547* process will never start its memory manager before terminating! */548char *mypath;549char *gappath;550char *tmppath;551char *p;552FILE *f;553int i;554555DoFindMyself(argv[0],&mypath,&gappath);556557/* Now write out the startup script: */558f = fopen(argv[2],"w");559if (f == NULL) {560printf("Could not write startup script to\n %s\ngiving up.\n",argv[2]);561return -3;562}563fprintf(f,"#!/bin/sh\n");564fprintf(f,"# Created by %s\n",mypath);565fprintf(f,"GAP_DIR=\"%s\"\n",gappath);566fprintf(f,"GAP_PRG=\"%s\"\n",mypath);567fprintf(f,"GAP_ARCH=\"%s\"\n",SYS_ARCH);568tmppath = NULL;569StrAppend(&tmppath,SYS_ARCH);570p = tmppath;571while (*p != 0 && *p != '/') p++;572*p++ = 0;573fprintf(f,"GAP_ARCH_SYS=\"%s\"\n",tmppath);574fprintf(f,"GAP_ARCH_ABI=\"%s\"\n",p); // FIXME: WRONG575fprintf(f,"exec %s -l %s",mypath,gappath);576if (withws) {577tmppath[0] = 0;578StrAppend(&tmppath,mypath);579p = tmppath+strlen(tmppath);580while (*p != '/') p--;581p[1] = 0;582StrAppend(&tmppath,"workspace.gap");583fprintf(f," -L %s",tmppath);584}585for (i = 3;i < argc;i++) fprintf(f," %s",argv[i]);586fprintf(f," \"$@\"\n");587fclose(f);588#ifdef HAVE_CHMOD589chmod(argv[2],S_IRUSR | S_IWUSR | S_IXUSR |590S_IRGRP | S_IWGRP | S_IXGRP |591S_IROTH | S_IXOTH);592#else593printf("Warning: Do not have chmod to make script executable!\n");594#endif595free(tmppath);596free(mypath);597free(gappath);598return 0;599}600601int DoCreateWorkspace(char *myself)602{603/* This is used to create an architecture-dependent saved604* workspace in a standard location. */605char *mypath;606char *gappath;607char *command;608char *tmppath;609char *p;610FILE *f;611612DoFindMyself(myself,&mypath,&gappath);613614/* Now we create a saved workspace: */615printf("Creating workspace...\n");616command = NULL;617StrAppend(&command,mypath);618StrAppend(&command," -r");619StrAppend(&command," -l ");620StrAppend(&command,gappath);621622tmppath = NULL;623StrAppend(&tmppath,mypath);624p = tmppath+strlen(tmppath);625while (*p != '/') p--;626p[1] = 0;627StrAppend(&tmppath,"workspace.gap");628629/* Now to the action: */630f = popen(command,"w");631if (f == NULL) {632printf("Could not start myself to save workspace, giving up.\n");633return -6;634}635fprintf(f,"??blabla\n");636fprintf(f,"SaveWorkspace(\"%s\");\n",tmppath);637fprintf(f,"quit;\n");638fflush(f);639pclose(f);640printf("\nDone creating workspace in\n %s\n",tmppath);641642free(tmppath);643free(command);644free(gappath);645free(mypath);646647return 0;648}649650int DoFixGac(char *myself)651{652char *mypath;653char *gappath;654FILE *f;655char *gacpath;656char *gapbin;657char *newpath;658char *p,*q,*r;659char *buf,*buf2;660size_t len,written;661662DoFindMyself(myself,&mypath,&gappath);663gacpath = NULL;664StrAppend(&gacpath,mypath);665p = gacpath + strlen(gacpath);666while (*p != '/') p--;667*p = 0;668gapbin = NULL;669StrAppend(&gapbin,gacpath);670StrAppend(&gacpath,"/gac");671newpath = NULL;672StrAppend(&newpath,gacpath);673StrAppend(&newpath,".new");674f = fopen(gacpath,"r");675if (f == NULL) {676printf("Could not open gac. Giving up.\n");677return -7;678}679buf = malloc(65536);680buf2 = malloc(65536+strlen(gapbin)+10);681if (buf == NULL || buf2 == NULL) {682printf("Could not allocate 128kB of memory. Giving up.\n");683return -8;684}685len = fread(buf,1,65534,f);686fclose(f);687688/* Now manipulate it: */689p = buf;690p[len] = 0;691p[len+1] = 0;692q = buf2;693while (*p) {694if (!strncmp(p,"gap_bin=",8)) {695while (*p != '\n' && *p != 0) p++;696*q++ = 'g'; *q++ = 'a'; *q++ = 'p'; *q++ = '_';697*q++ = 'b'; *q++ = 'i'; *q++ = 'n'; *q++ = '=';698r = gapbin;699while (*r) *q++ = *r++;700*q++ = '\n';701} else {702while (*p != '\n' && *p != 0) *q++ = *p++;703*q++ = *p++;704}705}706len = q - buf2;707708f = fopen(newpath,"w");709if (f == NULL) {710printf("Could not open gac.new. Giving up.\n");711return -9;712}713written = fwrite(buf2,1,len,f);714if (written < len) {715printf("Could not write gac.new. Giving up.\n");716fclose(f);717return -10;718}719if (fclose(f) < 0) {720printf("Could not close gac.new. Giving up.\n");721fclose(f);722return -11;723}724if (rename(newpath,gacpath) < 0) {725printf("Could not replace gac with new version. Giving up.\n");726return -12;727}728return 0;729}730#endif731732#ifdef COMPILECYGWINDLL733#define main realmain734#endif735736int main (737int argc,738char * argv [],739char * environ [] )740{741UInt type; /* result of compile */742Obj func; /* function (compiler) */743Int4 crc; /* crc of file to compile */744745#ifdef HAVE_REALPATH746if (argc >= 3 && !strcmp(argv[1],"--createstartupscript")) {747return DoCreateStartupScript(argc,argv,0);748}749if (argc >= 3 && !strcmp(argv[1],"--createstartupscriptwithws")) {750return DoCreateStartupScript(argc,argv,1);751}752if (argc >= 2 && !strcmp(argv[1],"--createworkspace")) {753return DoCreateWorkspace(argv[0]);754}755if (argc >= 2 && !strcmp(argv[1],"--fixgac")) {756return DoFixGac(argv[0]);757}758#endif759760original_argv0 = argv[0];761sysargv = argv;762sysenviron = environ;763764/* Initialize assorted variables in this file */765/* BreakOnError = 1;766ErrorCount = 0; */767NrImportedGVars = 0;768NrImportedFuncs = 0;769TLS(UserHasQUIT) = 0;770TLS(UserHasQuit) = 0;771SystemErrorCode = 0;772773/* initialize everything and read init.g which runs the GAP session */774InitializeGap( &argc, argv );775if (!TLS(UserHasQUIT)) { /* maybe the user QUIT from the initial776read of init.g somehow*/777/* maybe compile in which case init.g got skipped */778if ( SyCompilePlease ) {779if ( ! OpenInput(SyCompileInput) ) {780SyExit(1);781}782func = READ_AS_FUNC();783crc = SyGAPCRC(SyCompileInput);784if (strlen(SyCompileOptions) != 0)785SetCompileOpts(SyCompileOptions);786type = CompileFunc(787SyCompileOutput,788func,789SyCompileName,790crc,791SyCompileMagic1 );792if ( type == 0 )793SyExit( 1 );794SyExit( 0 );795}796}797SyExit(SystemErrorCode);798return 0;799}800801/****************************************************************************802**803*F FuncID_FUNC( <self>, <val1> ) . . . . . . . . . . . . . . . return <val1>804*/805Obj FuncID_FUNC (806Obj self,807Obj val1 )808{809return val1;810}811812/****************************************************************************813**814*F FuncRETURN_FIRST( <self>, <args> ) . . . . . . . . Return first argument815*/816Obj FuncRETURN_FIRST (817Obj self,818Obj args )819{820if (!IS_PLIST(args) || LEN_PLIST(args) < 1)821ErrorMayQuit("RETURN_FIRST requires one or more arguments",0,0);822823return ELM_PLIST(args, 1);824}825826/****************************************************************************827**828*F FuncRETURN_NOTHING( <self>, <arg> ) . . . . . . . . . . . Return nothing829*/830Obj FuncRETURN_NOTHING (831Obj self,832Obj arg )833{834return 0;835}836837838/****************************************************************************839**840*F FuncRuntime( <self> ) . . . . . . . . . . . . internal function 'Runtime'841**842** 'FuncRuntime' implements the internal function 'Runtime'.843**844** 'Runtime()'845**846** 'Runtime' returns the time spent since the start of GAP in milliseconds.847** How much time execution of statements take is of course system dependent.848** The accuracy of this number is also system dependent.849*/850Obj FuncRuntime (851Obj self )852{853return INTOBJ_INT( SyTime() );854}855856857Obj FuncRUNTIMES( Obj self)858{859Obj res;860res = NEW_PLIST(T_PLIST, 4);861SET_LEN_PLIST(res, 4);862SET_ELM_PLIST(res, 1, INTOBJ_INT( SyTime() ));863SET_ELM_PLIST(res, 2, INTOBJ_INT( SyTimeSys() ));864SET_ELM_PLIST(res, 3, INTOBJ_INT( SyTimeChildren() ));865SET_ELM_PLIST(res, 4, INTOBJ_INT( SyTimeChildrenSys() ));866return res;867}868869870/****************************************************************************871**872*F FuncSizeScreen( <self>, <args> ) . . . . internal function 'SizeScreen'873**874** 'FuncSizeScreen' implements the internal function 'SizeScreen' to get875** or set the actual screen size.876**877** 'SizeScreen()'878**879** In this form 'SizeScreen' returns the size of the screen as a list with880** two entries. The first is the length of each line, the second is the881** number of lines.882**883** 'SizeScreen( [ <x>, <y> ] )'884**885** In this form 'SizeScreen' sets the size of the screen. <x> is the length886** of each line, <y> is the number of lines. Either value may be missing,887** to leave this value unaffected. Note that those parameters can also be888** set with the command line options '-x <x>' and '-y <y>'.889*/890Obj FuncSizeScreen (891Obj self,892Obj args )893{894Obj size; /* argument and result list */895Obj elm; /* one entry from size */896UInt len; /* length of lines on the screen */897UInt nr; /* number of lines on the screen */898899/* check the arguments */900while ( ! IS_SMALL_LIST(args) || 1 < LEN_LIST(args) ) {901args = ErrorReturnObj(902"Function: number of arguments must be 0 or 1 (not %d)",903LEN_LIST(args), 0L,904"you can replace the argument list <args> via 'return <args>;'" );905}906907/* get the arguments */908if ( LEN_LIST(args) == 0 ) {909size = NEW_PLIST( T_PLIST, 0 );910SET_LEN_PLIST( size, 0 );911}912913/* otherwise check the argument */914else {915size = ELM_LIST( args, 1 );916while ( ! IS_SMALL_LIST(size) || 2 < LEN_LIST(size) ) {917size = ErrorReturnObj(918"SizeScreen: <size> must be a list of length 2",9190L, 0L,920"you can replace <size> via 'return <size>;'" );921}922}923924/* extract the length */925if ( LEN_LIST(size) < 1 || ELM0_LIST(size,1) == 0 ) {926len = 0;927}928else {929elm = ELMW_LIST(size,1);930while ( TNUM_OBJ(elm) != T_INT ) {931elm = ErrorReturnObj(932"SizeScreen: <x> must be an integer",9330L, 0L,934"you can replace <x> via 'return <x>;'" );935}936len = INT_INTOBJ( elm );937if ( len < 20 ) len = 20;938if ( MAXLENOUTPUTLINE < len ) len = MAXLENOUTPUTLINE;939}940941/* extract the number */942if ( LEN_LIST(size) < 2 || ELM0_LIST(size,2) == 0 ) {943nr = 0;944}945else {946elm = ELMW_LIST(size,2);947while ( TNUM_OBJ(elm) != T_INT ) {948elm = ErrorReturnObj(949"SizeScreen: <y> must be an integer",9500L, 0L,951"you can replace <y> via 'return <y>;'" );952}953nr = INT_INTOBJ( elm );954if ( nr < 10 ) nr = 10;955}956957/* set length and number */958if (len != 0)959{960SyNrCols = len;961SyNrColsLocked = 1;962}963if (nr != 0)964{965SyNrRows = nr;966SyNrRowsLocked = 1;967}968969/* make and return the size of the screen */970size = NEW_PLIST( T_PLIST, 2 );971SET_LEN_PLIST( size, 2 );972SET_ELM_PLIST( size, 1, INTOBJ_INT(SyNrCols) );973SET_ELM_PLIST( size, 2, INTOBJ_INT(SyNrRows) );974return size;975976}977978979/****************************************************************************980**981*F FuncWindowCmd( <self>, <args> ) . . . . . . . . execute a window command982*/983static Obj WindowCmdString;984985Obj FuncWindowCmd (986Obj self,987Obj args )988{989Obj tmp;990Obj list;991Int len;992Int n, m;993Int i;994Char * ptr;995Char * qtr;996997/* check arguments */998while ( ! IS_SMALL_LIST(args) ) {999args = ErrorReturnObj( "argument list must be a list (not a %s)",1000(Int)TNAM_OBJ(args), 0L,1001"you can replace the argument list <args> via 'return <args>;'" );10021003}1004tmp = ELM_LIST(args,1);1005while ( ! IsStringConv(tmp) || 3 != LEN_LIST(tmp) ) {1006while ( ! IsStringConv(tmp) ) {1007tmp = ErrorReturnObj( "<cmd> must be a string (not a %s)",1008(Int)TNAM_OBJ(tmp), 0L,1009"you can replace <cmd> via 'return <cmd>;'" );1010}1011if ( 3 != LEN_LIST(tmp) ) {1012tmp = ErrorReturnObj( "<cmd> must be a string of length 3",10130L, 0L,1014"you can replace <cmd> via 'return <cmd>;'" );1015}1016}10171018/* compute size needed to store argument string */1019len = 13;1020for ( i = 2; i <= LEN_LIST(args); i++ )1021{1022tmp = ELM_LIST( args, i );1023while ( TNUM_OBJ(tmp) != T_INT && ! IsStringConv(tmp) ) {1024tmp = ErrorReturnObj(1025"%d. argument must be a string or integer (not a %s)",1026i, (Int)TNAM_OBJ(tmp),1027"you can replace the argument <arg> via 'return <arg>;'" );1028SET_ELM_PLIST( args, i, tmp );1029}1030if ( TNUM_OBJ(tmp) == T_INT )1031len += 12;1032else1033len += 12 + LEN_LIST(tmp);1034}1035if ( SIZE_OBJ(WindowCmdString) <= len ) {1036ResizeBag( WindowCmdString, 2*len+1 );1037}10381039/* convert <args> into an argument string */1040ptr = (Char*) CSTR_STRING(WindowCmdString);10411042/* first the command name */1043memcpy( ptr, CSTR_STRING( ELM_LIST(args,1) ), 3 + 1 );1044ptr += 3;10451046/* and now the arguments */1047for ( i = 2; i <= LEN_LIST(args); i++ )1048{1049tmp = ELM_LIST(args,i);10501051if ( TNUM_OBJ(tmp) == T_INT ) {1052*ptr++ = 'I';1053m = INT_INTOBJ(tmp);1054for ( m = (m<0)?-m:m; 0 < m; m /= 10 )1055*ptr++ = (m%10) + '0';1056if ( INT_INTOBJ(tmp) < 0 )1057*ptr++ = '-';1058else1059*ptr++ = '+';1060}1061else {1062*ptr++ = 'S';1063m = LEN_LIST(tmp);1064for ( ; 0 < m; m/= 10 )1065*ptr++ = (m%10) + '0';1066*ptr++ = '+';1067qtr = CSTR_STRING(tmp);1068for ( m = LEN_LIST(tmp); 0 < m; m-- )1069*ptr++ = *qtr++;1070}1071}1072*ptr = 0;10731074/* now call the window front end with the argument string */1075qtr = CSTR_STRING(WindowCmdString);1076ptr = SyWinCmd( qtr, strlen(qtr) );1077len = strlen(ptr);10781079/* now convert result back into a list */1080list = NEW_PLIST( T_PLIST, 11 );1081SET_LEN_PLIST( list, 0 );1082i = 1;1083while ( 0 < len ) {1084if ( *ptr == 'I' ) {1085ptr++;1086for ( n=0,m=1; '0' <= *ptr && *ptr <= '9'; ptr++,m *= 10,len-- )1087n += (*ptr-'0') * m;1088if ( *ptr++ == '-' )1089n *= -1;1090len -= 2;1091AssPlist( list, i, INTOBJ_INT(n) );1092}1093else if ( *ptr == 'S' ) {1094ptr++;1095for ( n=0,m=1; '0' <= *ptr && *ptr <= '9'; ptr++,m *= 10,len-- )1096n += (*ptr-'0') * m;1097ptr++; /* ignore the '+' */1098C_NEW_STRING(tmp, n, ptr);1099ptr += n;1100len -= n+2;1101AssPlist( list, i, tmp );1102}1103else {1104ErrorQuit( "unknown return value '%s'", (Int)ptr, 0 );1105return 0;1106}1107i++;1108}11091110/* if the first entry is one signal an error */1111if ( ELM_LIST(list,1) == INTOBJ_INT(1) ) {1112C_NEW_STRING_CONST(tmp, "window system: ");1113SET_ELM_PLIST( list, 1, tmp );1114SET_LEN_PLIST( list, i-1 );1115return CALL_XARGS(Error,list);1116/* return FuncError( 0, list );*/1117}1118else {1119for ( m = 1; m <= i-2; m++ )1120SET_ELM_PLIST( list, m, ELM_PLIST(list,m+1) );1121SET_LEN_PLIST( list, i-2 );1122return list;1123}1124}112511261127/****************************************************************************1128**11291130*F * * * * * * * * * * * * * * error functions * * * * * * * * * * * * * * *1131*/1132113311341135/****************************************************************************1136**1137*F FuncDownEnv( <self>, <level> ) . . . . . . . . . change the environment1138*/11391140Obj ErrorLVars0;1141Obj ErrorLVars;1142Int ErrorLLevel;11431144extern Obj BottomLVars;114511461147void DownEnvInner( Int depth )1148{1149/* if we really want to go up */1150if ( depth < 0 && -TLS(ErrorLLevel) <= -depth ) {1151depth = 0;1152TLS(ErrorLVars) = TLS(ErrorLVars0);1153TLS(ErrorLLevel) = 0;1154TLS(ShellContextDepth) = 0;1155TLS(ShellContext) = TLS(BaseShellContext);1156}1157else if ( depth < 0 ) {1158depth = -TLS(ErrorLLevel) + depth;1159TLS(ErrorLVars) = TLS(ErrorLVars0);1160TLS(ErrorLLevel) = 0;1161TLS(ShellContextDepth) = 0;1162TLS(ShellContext) = TLS(BaseShellContext);1163}11641165/* now go down */1166while ( 0 < depth1167&& TLS(ErrorLVars) != TLS(BottomLVars)1168&& PTR_BAG(TLS(ErrorLVars))[2] != TLS(BottomLVars) ) {1169TLS(ErrorLVars) = PTR_BAG(TLS(ErrorLVars))[2];1170TLS(ErrorLLevel)--;1171TLS(ShellContext) = PTR_BAG(TLS(ShellContext))[2];1172TLS(ShellContextDepth)--;1173depth--;1174}1175}11761177Obj FuncDownEnv (1178Obj self,1179Obj args )1180{1181Int depth;11821183if ( LEN_LIST(args) == 0 ) {1184depth = 1;1185}1186else if ( LEN_LIST(args) == 1 && IS_INTOBJ( ELM_PLIST(args,1) ) ) {1187depth = INT_INTOBJ( ELM_PLIST( args, 1 ) );1188}1189else {1190ErrorQuit( "usage: DownEnv( [ <depth> ] )", 0L, 0L );1191return 0;1192}1193if ( TLS(ErrorLVars) == 0 ) {1194Pr( "not in any function\n", 0L, 0L );1195return 0;1196}11971198DownEnvInner( depth);11991200/* return nothing */1201return 0;1202}12031204Obj FuncUpEnv (1205Obj self,1206Obj args )1207{1208Int depth;1209if ( LEN_LIST(args) == 0 ) {1210depth = 1;1211}1212else if ( LEN_LIST(args) == 1 && IS_INTOBJ( ELM_PLIST(args,1) ) ) {1213depth = INT_INTOBJ( ELM_PLIST( args, 1 ) );1214}1215else {1216ErrorQuit( "usage: UpEnv( [ <depth> ] )", 0L, 0L );1217return 0;1218}1219if ( TLS(ErrorLVars) == 0 ) {1220Pr( "not in any function\n", 0L, 0L );1221return 0;1222}12231224DownEnvInner(-depth);1225return 0;1226}122712281229Obj FuncPrintExecutingStatement(Obj self, Obj context)1230{1231Obj currLVars = TLS(CurrLVars);1232Expr call;1233if (context == TLS(BottomLVars))1234return (Obj) 0;1235SWITCH_TO_OLD_LVARS(context);1236call = BRK_CALL_TO();1237if ( call == 0 ) {1238Pr( "<compiled or corrupted statement> ", 0L, 0L );1239}1240#if T_PROCCALL_0ARGS1241else if ( FIRST_STAT_TNUM <= TNUM_STAT(call)1242&& TNUM_STAT(call) <= LAST_STAT_TNUM ) {1243#else1244else if ( TNUM_STAT(call) <= LAST_STAT_TNUM ) {1245#endif1246PrintStat( call );1247Pr(" at %s:%d",(UInt)CSTR_STRING(FILENAME_STAT(call)),LINE_STAT(call));1248}1249else if ( FIRST_EXPR_TNUM <= TNUM_EXPR(call)1250&& TNUM_EXPR(call) <= LAST_EXPR_TNUM ) {1251PrintExpr( call );1252Pr(" at %s:%d",(UInt)CSTR_STRING(FILENAME_STAT(call)),LINE_STAT(call));1253}1254SWITCH_TO_OLD_LVARS( currLVars );1255return (Obj) 0;1256}12571258/****************************************************************************1259**1260*F FuncCallFuncTrapError( <self>, <func> )1261**1262*/12631264/* syJmp_buf CatchBuffer; */1265Obj ThrownObject = 0;12661267Obj FuncCALL_WITH_CATCH( Obj self, Obj func, Obj args )1268{1269syJmp_buf readJmpError;1270Obj res;1271Obj currLVars;1272Obj result;1273Int recursionDepth;1274Stat currStat;1275if (!IS_FUNC(func))1276ErrorMayQuit("CALL_WITH_CATCH(<func>, <args>): <func> must be a function",0,0);1277if (!IS_LIST(args))1278ErrorMayQuit("CALL_WITH_CATCH(<func>, <args>): <args> must be a list",0,0);1279memcpy((void *)&readJmpError, (void *)&TLS(ReadJmpError), sizeof(syJmp_buf));1280currLVars = TLS(CurrLVars);1281currStat = TLS(CurrStat);1282recursionDepth = TLS(RecursionDepth);1283res = NEW_PLIST(T_PLIST_DENSE+IMMUTABLE,2);1284if (sySetjmp(TLS(ReadJmpError))) {1285SET_LEN_PLIST(res,2);1286SET_ELM_PLIST(res,1,False);1287SET_ELM_PLIST(res,2,TLS(ThrownObject));1288CHANGED_BAG(res);1289TLS(ThrownObject) = 0;1290TLS(CurrLVars) = currLVars;1291TLS(PtrLVars) = PTR_BAG(TLS(CurrLVars));1292TLS(PtrBody) = (Stat*)PTR_BAG(BODY_FUNC(CURR_FUNC));1293TLS(CurrStat) = currStat;1294TLS(RecursionDepth) = recursionDepth;1295} else {1296result = CallFuncList(func, args);1297SET_ELM_PLIST(res,1,True);1298if (result)1299{1300SET_LEN_PLIST(res,2);1301SET_ELM_PLIST(res,2,result);1302CHANGED_BAG(res);1303}1304else1305SET_LEN_PLIST(res,1);1306}1307memcpy((void *)&TLS(ReadJmpError), (void *)&readJmpError, sizeof(syJmp_buf));1308return res;1309}13101311Obj FuncJUMP_TO_CATCH( Obj self, Obj payload)1312{1313TLS(ThrownObject) = payload;1314syLongjmp(TLS(ReadJmpError), 1);1315return 0;1316}131713181319UInt UserHasQuit;1320UInt UserHasQUIT;1321UInt SystemErrorCode;13221323Obj FuncSetUserHasQuit( Obj Self, Obj value)1324{1325TLS(UserHasQuit) = INT_INTOBJ(value);1326if (TLS(UserHasQuit))1327TLS(RecursionDepth) = 0;1328return 0;1329}133013311332#define MAX_TIMEOUT_NESTING_DEPTH 102413331334syJmp_buf AlarmJumpBuffers[MAX_TIMEOUT_NESTING_DEPTH];1335UInt NumAlarmJumpBuffers = 0;13361337Obj FuncTIMEOUTS_SUPPORTED(Obj self) {1338return SyHaveAlarms ? True: False;1339}13401341Obj FuncCALL_WITH_TIMEOUT( Obj self, Obj seconds, Obj microseconds, Obj func, Obj args )1342{1343Obj res;1344Obj currLVars;1345Obj result;1346Int recursionDepth;1347Stat currStat;13481349if (!SyHaveAlarms)1350ErrorMayQuit("CALL_WITH_TIMEOUT: timeouts not supported on this system", 0L, 0L);1351if (!IS_INTOBJ(seconds) || 0 > INT_INTOBJ(seconds))1352ErrorMayQuit("CALL_WITH_TIMEOUT(<seconds>, <microseconds>, <func>, <args>):"1353" <seconds> must be a non-negative small integer",0,0);1354if (!IS_INTOBJ(microseconds) || 0 > INT_INTOBJ(microseconds) || 999999999 < INT_INTOBJ(microseconds))1355ErrorMayQuit("CALL_WITH_TIMEOUT(<seconds>, <microseconds>, <func>, <args>):"1356" <microseconds> must be a non-negative small integer less than 10^9",0,0);1357if (!IS_FUNC(func))1358ErrorMayQuit("CALL_WITH_TIMEOUT(<seconds>, <microseconds>, <func>,<args>): <func> must be a function",0,0);1359if (!IS_LIST(args))1360ErrorMayQuit("CALL_WITH_TIMEOUT(<seconds>, <microseconds>, <func>,<args>): <args> must be a list",0,0);1361if (SyAlarmRunning) {1362ErrorMayQuit("CALL_WITH_TIMEOUT cannot currently be nested except via break loops."1363" There is already a timeout running", 0, 0);1364}1365if (NumAlarmJumpBuffers >= MAX_TIMEOUT_NESTING_DEPTH-1)1366ErrorMayQuit("Nesting depth of timeouts via break loops limited to %i", MAX_TIMEOUT_NESTING_DEPTH, 0L);1367currLVars = TLS(CurrLVars);1368currStat = TLS(CurrStat);1369recursionDepth = TLS(RecursionDepth);1370res = NEW_PLIST( T_PLIST_DENSE+IMMUTABLE, 2 );1371SET_LEN_PLIST(res, 1);1372if (sySetjmp(AlarmJumpBuffers[NumAlarmJumpBuffers++])) {1373/* Timeout happened */1374TLS(CurrLVars) = currLVars;1375TLS(PtrLVars) = PTR_BAG(TLS(CurrLVars));1376TLS(PtrBody) = (Stat*)PTR_BAG(BODY_FUNC(CURR_FUNC));1377TLS(CurrStat) = currStat;1378TLS(RecursionDepth) = recursionDepth;1379SET_ELM_PLIST(res, 1, False);1380} else {1381SyInstallAlarm( INT_INTOBJ(seconds), 1000*INT_INTOBJ(microseconds));1382result = CallFuncList(func, args);1383/* make sure the alarm is not still running */1384SyStopAlarm( NULL, NULL);1385/* Now the alarm might have gone off since we executed the last statement1386of func. So */1387if (SyAlarmHasGoneOff) {1388SyAlarmHasGoneOff = 0;1389UnInterruptExecStat();1390}1391assert(NumAlarmJumpBuffers);1392NumAlarmJumpBuffers--;1393SET_ELM_PLIST(res,1,True);1394if (result)1395{1396SET_LEN_PLIST(res,2);1397SET_ELM_PLIST(res,2,result);1398}1399}1400CHANGED_BAG(res);1401return res;1402}14031404Obj FuncSTOP_TIMEOUT( Obj self ) {1405UInt seconds, nanoseconds;1406if (!SyHaveAlarms || !SyAlarmRunning)1407return Fail;1408SyStopAlarm(&seconds, &nanoseconds);1409Obj state = NEW_PLIST(T_PLIST_CYC+IMMUTABLE, 3);1410SET_ELM_PLIST(state,1,INTOBJ_INT(seconds));1411SET_ELM_PLIST(state,2,INTOBJ_INT(nanoseconds/1000));1412SET_ELM_PLIST(state,3,INTOBJ_INT(NumAlarmJumpBuffers));1413SET_LEN_PLIST(state,3);1414return state;1415}14161417Obj FuncRESUME_TIMEOUT( Obj self, Obj state ) {1418if (!SyHaveAlarms || SyAlarmRunning)1419return Fail;1420if (!IS_PLIST(state) || LEN_PLIST(state) < 2)1421return Fail;1422if (!IS_INTOBJ(ELM_PLIST(state,1)) ||1423!IS_INTOBJ(ELM_PLIST(state,2)))1424return Fail;1425Int s = INT_INTOBJ(ELM_PLIST(state,1));1426Int us = INT_INTOBJ(ELM_PLIST(state,2));1427if (s < 0 || us < 0 || us > 999999)1428return Fail;1429Int depth = INT_INTOBJ(ELM_PLIST(state,3));1430if (depth < 0 || depth >= MAX_TIMEOUT_NESTING_DEPTH)1431return Fail;1432NumAlarmJumpBuffers = depth;1433SyInstallAlarm(s, 1000*us);1434return True;1435}1436143714381439/****************************************************************************1440**1441*F ErrorQuit( <msg>, <arg1>, <arg2> ) . . . . . . . . . . . print and quit1442*/14431444static Obj ErrorMessageToGAPString(1445const Char * msg,1446Int arg1,1447Int arg2 )1448{1449Char message[120];1450Obj Message;1451SPrTo(message, sizeof(message), msg, arg1, arg2);1452message[sizeof(message)-1] = '\0';1453C_NEW_STRING_DYN(Message, message);1454return Message;1455}14561457Obj CallErrorInner (1458const Char * msg,1459Int arg1,1460Int arg2,1461UInt justQuit,1462UInt mayReturnVoid,1463UInt mayReturnObj,1464Obj lateMessage,1465UInt printThisStatement)1466{1467Obj EarlyMsg;1468Obj r = NEW_PREC(0);1469Obj l;1470EarlyMsg = ErrorMessageToGAPString(msg, arg1, arg2);1471AssPRec(r, RNamName("context"), TLS(CurrLVars));1472AssPRec(r, RNamName("justQuit"), justQuit? True : False);1473AssPRec(r, RNamName("mayReturnObj"), mayReturnObj? True : False);1474AssPRec(r, RNamName("mayReturnVoid"), mayReturnVoid? True : False);1475AssPRec(r, RNamName("printThisStatement"), printThisStatement? True : False);1476AssPRec(r, RNamName("lateMessage"), lateMessage);1477l = NEW_PLIST(T_PLIST_HOM+IMMUTABLE, 1);1478SET_ELM_PLIST(l,1,EarlyMsg);1479SET_LEN_PLIST(l,1);1480SET_BRK_CALL_TO(TLS(CurrStat));1481Obj res = CALL_2ARGS(ErrorInner,r,l);1482return res;1483}14841485void ErrorQuit (1486const Char * msg,1487Int arg1,1488Int arg2 )1489{1490CallErrorInner(msg, arg1, arg2, 1, 0, 0, False, 1);1491}149214931494/****************************************************************************1495**1496*F ErrorQuitBound( <name> ) . . . . . . . . . . . . . . . unbound variable1497*/1498void ErrorQuitBound (1499const Char * name )1500{1501ErrorQuit(1502"variable '%s' must have an assigned value",1503(Int)name, 0L );1504}150515061507/****************************************************************************1508**1509*F ErrorQuitFuncResult() . . . . . . . . . . . . . . . . must return a value1510*/1511void ErrorQuitFuncResult ( void )1512{1513ErrorQuit(1514"function must return a value",15150L, 0L );1516}151715181519/****************************************************************************1520**1521*F ErrorQuitIntSmall( <obj> ) . . . . . . . . . . . . . not a small integer1522*/1523void ErrorQuitIntSmall (1524Obj obj )1525{1526ErrorQuit(1527"<obj> must be a small integer (not a %s)",1528(Int)TNAM_OBJ(obj), 0L );1529}153015311532/****************************************************************************1533**1534*F ErrorQuitIntSmallPos( <obj> ) . . . . . . . not a positive small integer1535*/1536void ErrorQuitIntSmallPos (1537Obj obj )1538{1539ErrorQuit(1540"<obj> must be a positive small integer (not a %s)",1541(Int)TNAM_OBJ(obj), 0L );1542}15431544/****************************************************************************1545**1546*F ErrorQuitIntPos( <obj> ) . . . . . . . not a positive small integer1547*/1548void ErrorQuitIntPos (1549Obj obj )1550{1551ErrorQuit(1552"<obj> must be a positive integer (not a %s)",1553(Int)TNAM_OBJ(obj), 0L );1554}155515561557/****************************************************************************1558**1559*F ErrorQuitBool( <obj> ) . . . . . . . . . . . . . . . . . . not a boolean1560*/1561void ErrorQuitBool (1562Obj obj )1563{1564ErrorQuit(1565"<obj> must be 'true' or 'false' (not a %s)",1566(Int)TNAM_OBJ(obj), 0L );1567}156815691570/****************************************************************************1571**1572*F ErrorQuitFunc( <obj> ) . . . . . . . . . . . . . . . . . not a function1573*/1574void ErrorQuitFunc (1575Obj obj )1576{1577ErrorQuit(1578"<obj> must be a function (not a %s)",1579(Int)TNAM_OBJ(obj), 0L );1580}158115821583/****************************************************************************1584**1585*F ErrorQuitNrArgs( <narg>, <args> ) . . . . . . . wrong number of arguments1586*/1587void ErrorQuitNrArgs (1588Int narg,1589Obj args )1590{1591ErrorQuit(1592"Function Calls: number of arguments must be %d (not %d)",1593narg, LEN_PLIST( args ) );1594}15951596/****************************************************************************1597**1598*F ErrorQuitRange3( <first>, <second>, <last> ) . . divisibility1599*/1600void ErrorQuitRange3 (1601Obj first,1602Obj second,1603Obj last)1604{1605ErrorQuit(1606"Range expression <last>-<first> must be divisible by <second>-<first>, not %d %d",1607INT_INTOBJ(last)-INT_INTOBJ(first), INT_INTOBJ(second)-INT_INTOBJ(first) );1608}160916101611/****************************************************************************1612**1613*F ErrorReturnObj( <msg>, <arg1>, <arg2>, <msg2> ) . . print and return obj1614*/1615Obj ErrorReturnObj (1616const Char * msg,1617Int arg1,1618Int arg2,1619const Char * msg2 )1620{1621Obj LateMsg;1622C_NEW_STRING_DYN(LateMsg, msg2);1623return CallErrorInner(msg, arg1, arg2, 0, 0, 1, LateMsg, 1);1624}162516261627/****************************************************************************1628**1629*F ErrorReturnVoid( <msg>, <arg1>, <arg2>, <msg2> ) . . . print and return1630*/1631void ErrorReturnVoid (1632const Char * msg,1633Int arg1,1634Int arg2,1635const Char * msg2 )1636{1637Obj LateMsg;1638C_NEW_STRING_DYN(LateMsg, msg2);1639CallErrorInner( msg, arg1, arg2, 0,1,0,LateMsg, 1);1640/* ErrorMode( msg, arg1, arg2, (Obj)0, msg2, 'x' ); */1641}16421643/****************************************************************************1644**1645*F ErrorMayQuit( <msg>, <arg1>, <arg2> ) . . . print and return1646*/1647void ErrorMayQuit (1648const Char * msg,1649Int arg1,1650Int arg2)1651{1652CallErrorInner(msg, arg1, arg2, 0, 0,0, False, 1);16531654}16551656Obj Error;1657Obj ErrorInner;165816591660/****************************************************************************1661**16621663*F * * * * * * * * * functions for creating the init file * * * * * * * * * *1664*/16651666/* deleted 9/5/11 */16671668/*************************************************************************1669**16701671*F * * * * * * * * * functions for dynamical/static modules * * * * * * * * *1672*/1673167416751676/****************************************************************************1677**16781679*F FuncGAP_CRC( <self>, <name> ) . . . . . . . create a crc value for a file1680*/1681Obj FuncGAP_CRC (1682Obj self,1683Obj filename )1684{1685/* check the argument */1686while ( ! IsStringConv( filename ) ) {1687filename = ErrorReturnObj(1688"<filename> must be a string (not a %s)",1689(Int)TNAM_OBJ(filename), 0L,1690"you can replace <filename> via 'return <filename>;'" );1691}16921693/* compute the crc value */1694return INTOBJ_INT( SyGAPCRC( CSTR_STRING(filename) ) );1695}169616971698/****************************************************************************1699**1700*F FuncLOAD_DYN( <self>, <name>, <crc> ) . . . try to load a dynamic module1701*/1702Obj FuncLOAD_DYN (1703Obj self,1704Obj filename,1705Obj crc )1706{1707InitInfoFunc init;1708StructInitInfo * info;1709Obj crc1;1710Int res;17111712/* check the argument */1713while ( ! IsStringConv( filename ) ) {1714filename = ErrorReturnObj(1715"<filename> must be a string (not a %s)",1716(Int)TNAM_OBJ(filename), 0L,1717"you can replace <filename> via 'return <filename>;'" );1718}1719while ( ! IS_INTOBJ(crc) && crc!=False ) {1720crc = ErrorReturnObj(1721"<crc> must be a small integer or 'false' (not a %s)",1722(Int)TNAM_OBJ(crc), 0L,1723"you can replace <crc> via 'return <crc>;'" );1724}17251726/* try to read the module */1727init = SyLoadModule( CSTR_STRING(filename) );1728if ( (Int)init == 1 )1729ErrorQuit( "module '%s' not found", (Int)CSTR_STRING(filename), 0L );1730else if ( (Int) init == 3 )1731ErrorQuit( "symbol 'Init_Dynamic' not found", 0L, 0L );1732else if ( (Int) init == 5 )1733ErrorQuit( "forget symbol failed", 0L, 0L );17341735/* no dynamic library support */1736else if ( (Int) init == 7 ) {1737if ( SyDebugLoading ) {1738Pr( "#I LOAD_DYN: no support for dynamical loading\n", 0L, 0L );1739}1740return False;1741}17421743/* get the description structure */1744info = (*init)();1745if ( info == 0 )1746ErrorQuit( "call to init function failed", 0L, 0L );17471748/* check the crc value */1749if ( crc != False ) {1750crc1 = INTOBJ_INT( info->crc );1751if ( ! EQ( crc, crc1 ) ) {1752if ( SyDebugLoading ) {1753Pr( "#I LOAD_DYN: crc values do not match, gap ", 0L, 0L );1754PrintInt( crc );1755Pr( ", dyn ", 0L, 0L );1756PrintInt( crc1 );1757Pr( "\n", 0L, 0L );1758}1759return False;1760}1761}17621763/* link and init me */1764info->isGapRootRelative = 0;1765res = (info->initKernel)(info);1766UpdateCopyFopyInfo();17671768/* Start a new executor to run the outer function of the module1769in global context */1770ExecBegin( TLS(BottomLVars) );1771res = res || (info->initLibrary)(info);1772ExecEnd(res ? STATUS_ERROR : STATUS_END);1773if ( res ) {1774Pr( "#W init functions returned non-zero exit code\n", 0L, 0L );1775}1776RecordLoadedModule(info, CSTR_STRING(filename));17771778return True;1779}178017811782/****************************************************************************1783**1784*F FuncLOAD_STAT( <self>, <name>, <crc> ) . . . . try to load static module1785*/1786Obj FuncLOAD_STAT (1787Obj self,1788Obj filename,1789Obj crc )1790{1791StructInitInfo * info = 0;1792Obj crc1;1793Int k;1794Int res;17951796/* check the argument */1797while ( ! IsStringConv( filename ) ) {1798filename = ErrorReturnObj(1799"<filename> must be a string (not a %s)",1800(Int)TNAM_OBJ(filename), 0L,1801"you can replace <filename> via 'return <filename>;'" );1802}1803while ( !IS_INTOBJ(crc) && crc!=False ) {1804crc = ErrorReturnObj(1805"<crc> must be a small integer or 'false' (not a %s)",1806(Int)TNAM_OBJ(crc), 0L,1807"you can replace <crc> via 'return <crc>;'" );1808}18091810/* try to find the module */1811for ( k = 0; CompInitFuncs[k]; k++ ) {1812info = (*(CompInitFuncs[k]))();1813if ( info == 0 ) {1814continue;1815}1816if ( ! strcmp( CSTR_STRING(filename), info->name ) ) {1817break;1818}1819}1820if ( CompInitFuncs[k] == 0 ) {1821if ( SyDebugLoading ) {1822Pr( "#I LOAD_STAT: no module named '%s' found\n",1823(Int)CSTR_STRING(filename), 0L );1824}1825return False;1826}18271828/* check the crc value */1829if ( crc != False ) {1830crc1 = INTOBJ_INT( info->crc );1831if ( ! EQ( crc, crc1 ) ) {1832if ( SyDebugLoading ) {1833Pr( "#I LOAD_STAT: crc values do not match, gap ", 0L, 0L );1834PrintInt( crc );1835Pr( ", stat ", 0L, 0L );1836PrintInt( crc1 );1837Pr( "\n", 0L, 0L );1838}1839return False;1840}1841}18421843/* link and init me */1844info->isGapRootRelative = 0;1845res = (info->initKernel)(info);1846UpdateCopyFopyInfo();1847/* Start a new executor to run the outer function of the module1848in global context */1849ExecBegin( TLS(BottomLVars) );1850res = res || (info->initLibrary)(info);1851ExecEnd(res ? STATUS_ERROR : STATUS_END);1852if ( res ) {1853Pr( "#W init functions returned non-zero exit code\n", 0L, 0L );1854}1855RecordLoadedModule(info, CSTR_STRING(filename));18561857return True;1858}185918601861/****************************************************************************1862**1863*F FuncSHOW_STAT() . . . . . . . . . . . . . . . . . . . show static modules1864*/1865Obj FuncSHOW_STAT (1866Obj self )1867{1868Obj modules;1869Obj name;1870StructInitInfo * info;1871Int k;1872Int im;18731874/* count the number of install modules */1875for ( k = 0, im = 0; CompInitFuncs[k]; k++ ) {1876info = (*(CompInitFuncs[k]))();1877if ( info == 0 ) {1878continue;1879}1880im++;1881}18821883/* make a list of modules with crc values */1884modules = NEW_PLIST( T_PLIST, 2*im );1885SET_LEN_PLIST( modules, 2*im );18861887for ( k = 0, im = 1; CompInitFuncs[k]; k++ ) {1888info = (*(CompInitFuncs[k]))();1889if ( info == 0 ) {1890continue;1891}1892C_NEW_STRING_DYN(name, info->name);18931894SET_ELM_PLIST( modules, im, name );18951896/* compute the crc value */1897SET_ELM_PLIST( modules, im+1, INTOBJ_INT( info->crc ) );1898im += 2;1899}19001901return modules;1902}190319041905/****************************************************************************1906**1907*F FuncLoadedModules( <self> ) . . . . . . . . . . . list all loaded modules1908*/1909Obj FuncLoadedModules (1910Obj self )1911{1912Int i;1913StructInitInfo * m;1914Obj str;1915Obj list;19161917/* create a list */1918list = NEW_PLIST( T_PLIST, NrModules * 3 );1919SET_LEN_PLIST( list, NrModules * 3 );1920for ( i = 0; i < NrModules; i++ ) {1921m = Modules[i];1922if ( m->type == MODULE_BUILTIN ) {1923SET_ELM_PLIST( list, 3*i+1, ObjsChar[(Int)'b'] );1924CHANGED_BAG(list);1925C_NEW_STRING_DYN( str, m->name );1926SET_ELM_PLIST( list, 3*i+2, str );1927SET_ELM_PLIST( list, 3*i+3, INTOBJ_INT(m->version) );1928}1929else if ( m->type == MODULE_DYNAMIC ) {1930SET_ELM_PLIST( list, 3*i+1, ObjsChar[(Int)'d'] );1931CHANGED_BAG(list);1932C_NEW_STRING_DYN( str, m->name );1933SET_ELM_PLIST( list, 3*i+2, str );1934CHANGED_BAG(list);1935C_NEW_STRING_DYN( str, m->filename );1936SET_ELM_PLIST( list, 3*i+3, str );1937}1938else if ( m->type == MODULE_STATIC ) {1939SET_ELM_PLIST( list, 3*i+1, ObjsChar[(Int)'s'] );1940CHANGED_BAG(list);1941C_NEW_STRING_DYN( str, m->name );1942SET_ELM_PLIST( list, 3*i+2, str );1943CHANGED_BAG(list);1944C_NEW_STRING_DYN( str, m->filename );1945SET_ELM_PLIST( list, 3*i+3, str );1946}1947}1948return CopyObj( list, 0 );1949}195019511952/****************************************************************************1953**195419551956*F * * * * * * * * * * * * * * debug functions * * * * * * * * * * * * * * *1957*/19581959/****************************************************************************1960**19611962*F FuncGASMAN( <self>, <args> ) . . . . . . . . . expert function 'GASMAN'1963**1964** 'FuncGASMAN' implements the internal function 'GASMAN'1965**1966** 'GASMAN( "display" | "clear" | "collect" | "message" | "partial" )'1967*/1968Obj FuncGASMAN (1969Obj self,1970Obj args )1971{1972Obj cmd; /* argument */1973UInt i, k; /* loop variables */1974Char buf[41];19751976/* check the argument */1977while ( ! IS_SMALL_LIST(args) || LEN_LIST(args) == 0 ) {1978args = ErrorReturnObj(1979"usage: GASMAN( \"display\"|\"displayshort\"|\"clear\"|\"collect\"|\"message\"|\"partial\" )",19800L, 0L,1981"you can replace the argument list <args> via 'return <args>;'" );1982}19831984/* loop over the arguments */1985for ( i = 1; i <= LEN_LIST(args); i++ ) {19861987/* evaluate and check the command */1988cmd = ELM_PLIST( args, i );1989again:1990while ( ! IsStringConv(cmd) ) {1991cmd = ErrorReturnObj(1992"GASMAN: <cmd> must be a string (not a %s)",1993(Int)TNAM_OBJ(cmd), 0L,1994"you can replace <cmd> via 'return <cmd>;'" );1995}19961997/* if request display the statistics */1998if ( strcmp( CSTR_STRING(cmd), "display" ) == 0 ) {1999Pr( "%40s ", (Int)"type", 0L );2000Pr( "%8s %8s ", (Int)"alive", (Int)"kbyte" );2001Pr( "%8s %8s\n", (Int)"total", (Int)"kbyte" );2002for ( k = 0; k < 256; k++ ) {2003if ( InfoBags[k].name != 0 ) {2004buf[0] = '\0';2005strlcat( buf, InfoBags[k].name, sizeof(buf) );2006Pr("%40s ", (Int)buf, 0L );2007Pr("%8d %8d ", (Int)InfoBags[k].nrLive,2008(Int)(InfoBags[k].sizeLive/1024));2009Pr("%8d %8d\n",(Int)InfoBags[k].nrAll,2010(Int)(InfoBags[k].sizeAll/1024));2011}2012}2013}20142015/* if request give a short display of the statistics */2016else if ( strcmp( CSTR_STRING(cmd), "displayshort" ) == 0 ) {2017Pr( "%40s ", (Int)"type", 0L );2018Pr( "%8s %8s ", (Int)"alive", (Int)"kbyte" );2019Pr( "%8s %8s\n", (Int)"total", (Int)"kbyte" );2020for ( k = 0; k < 256; k++ ) {2021if ( InfoBags[k].name != 0 &&2022(InfoBags[k].nrLive != 0 ||2023InfoBags[k].sizeLive != 0 ||2024InfoBags[k].nrAll != 0 ||2025InfoBags[k].sizeAll != 0) ) {2026buf[0] = '\0';2027strlcat( buf, InfoBags[k].name, sizeof(buf) );2028Pr("%40s ", (Int)buf, 0L );2029Pr("%8d %8d ", (Int)InfoBags[k].nrLive,2030(Int)(InfoBags[k].sizeLive/1024));2031Pr("%8d %8d\n",(Int)InfoBags[k].nrAll,2032(Int)(InfoBags[k].sizeAll/1024));2033}2034}2035}20362037/* if request display the statistics */2038else if ( strcmp( CSTR_STRING(cmd), "clear" ) == 0 ) {2039for ( k = 0; k < 256; k++ ) {2040#ifdef GASMAN_CLEAR_TO_LIVE2041InfoBags[k].nrAll = InfoBags[k].nrLive;2042InfoBags[k].sizeAll = InfoBags[k].sizeLive;2043#else2044InfoBags[k].nrAll = 0;2045InfoBags[k].sizeAll = 0;2046#endif2047}2048}20492050/* or collect the garbage */2051else if ( strcmp( CSTR_STRING(cmd), "collect" ) == 0 ) {2052CollectBags(0,1);2053}20542055/* or collect the garbage */2056else if ( strcmp( CSTR_STRING(cmd), "partial" ) == 0 ) {2057CollectBags(0,0);2058}20592060/* or display information about global bags */2061else if ( strcmp( CSTR_STRING(cmd), "global" ) == 0 ) {2062for ( i = 0; i < GlobalBags.nr; i++ ) {2063if ( *(GlobalBags.addr[i]) != 0 ) {2064Pr( "%50s: %12d bytes\n", (Int)GlobalBags.cookie[i],2065(Int)SIZE_BAG(*(GlobalBags.addr[i])) );2066}2067}2068}20692070/* or finally toggle Gasman messages */2071else if ( strcmp( CSTR_STRING(cmd), "message" ) == 0 ) {2072SyMsgsFlagBags = (SyMsgsFlagBags + 1) % 3;2073}20742075/* otherwise complain */2076else {2077cmd = ErrorReturnObj(2078"GASMAN: <cmd> must be %s or %s",2079(Int)"\"display\" or \"clear\" or \"global\" or ",2080(Int)"\"collect\" or \"partial\" or \"message\"",2081"you can replace <cmd> via 'return <cmd>;'" );2082goto again;2083}2084}20852086/* return nothing, this function is a procedure */2087return 0;2088}20892090Obj FuncGASMAN_STATS(Obj self)2091{2092Obj res;2093Obj row;2094Obj entry;2095UInt i,j;2096Int x;2097res = NEW_PLIST(T_PLIST_TAB_RECT + IMMUTABLE, 2);2098SET_LEN_PLIST(res, 2);2099for (i = 1; i <= 2; i++)2100{2101row = NEW_PLIST(T_PLIST_CYC + IMMUTABLE, 9);2102SET_ELM_PLIST(res, i, row);2103CHANGED_BAG(res);2104SET_LEN_PLIST(row, 9);2105for (j = 1; j <= 8; j++)2106{2107x = SyGasmanNumbers[i-1][j];21082109/* convert x to GAP integer. x may be too big to be a small int */2110if (x < (1L << NR_SMALL_INT_BITS))2111entry = INTOBJ_INT(x);2112else2113entry = SUM( PROD(INTOBJ_INT(x >> (NR_SMALL_INT_BITS/2)),2114INTOBJ_INT(1 << (NR_SMALL_INT_BITS/2))),2115INTOBJ_INT( x % ( 1 << (NR_SMALL_INT_BITS/2))));2116SET_ELM_PLIST(row, j, entry);2117}2118SET_ELM_PLIST(row, 9, INTOBJ_INT(SyGasmanNumbers[i-1][0]));2119}2120return res;2121}21222123Obj FuncGASMAN_MESSAGE_STATUS( Obj self )2124{2125return INTOBJ_INT(SyMsgsFlagBags);2126}21272128Obj FuncGASMAN_LIMITS( Obj self )2129{2130Obj list;2131list = NEW_PLIST(T_PLIST_CYC+IMMUTABLE, 3);2132SET_LEN_PLIST(list,3);2133SET_ELM_PLIST(list, 1, INTOBJ_INT(SyStorMin));2134SET_ELM_PLIST(list, 2, INTOBJ_INT(SyStorMax));2135SET_ELM_PLIST(list, 3, INTOBJ_INT(SyStorKill));2136return list;2137}21382139/****************************************************************************2140**2141*F FuncSHALLOW_SIZE( <self>, <obj> ) . . . . expert function 'SHALLOW_SIZE'2142*/2143Obj FuncSHALLOW_SIZE (2144Obj self,2145Obj obj )2146{2147if (IS_INTOBJ(obj) || IS_FFE(obj))2148return INTOBJ_INT(0);2149else2150return ObjInt_UInt( SIZE_BAG( obj ) );2151}215221532154/****************************************************************************2155**2156*F FuncTNUM_OBJ( <self>, <obj> ) . . . . . . . . expert function 'TNUM_OBJ'2157*/21582159Obj FuncTNUM_OBJ (2160Obj self,2161Obj obj )2162{2163Obj res;2164Obj str;2165const Char * cst;21662167res = NEW_PLIST( T_PLIST, 2 );2168SET_LEN_PLIST( res, 2 );21692170/* set the type */2171SET_ELM_PLIST( res, 1, INTOBJ_INT( TNUM_OBJ(obj) ) );2172cst = TNAM_OBJ(obj);2173C_NEW_STRING_DYN(str, cst);2174SET_ELM_PLIST( res, 2, str );21752176/* and return */2177return res;2178}21792180Obj FuncTNUM_OBJ_INT (2181Obj self,2182Obj obj )2183{218421852186return INTOBJ_INT( TNUM_OBJ(obj) ) ;2187}21882189/****************************************************************************2190**2191*F FuncOBJ_HANDLE( <self>, <obj> ) . . . . . . expert function 'OBJ_HANDLE'2192*/2193Obj FuncOBJ_HANDLE (2194Obj self,2195Obj obj )2196{2197UInt hand;2198UInt prod;2199Obj rem;22002201if ( IS_INTOBJ(obj) ) {2202return (Obj)INT_INTOBJ(obj);2203}2204else if ( TNUM_OBJ(obj) == T_INTPOS ) {2205hand = 0;2206prod = 1;2207while ( EQ( obj, INTOBJ_INT(0) ) == 0 ) {2208rem = RemInt( obj, INTOBJ_INT( 1 << 16 ) );2209obj = QuoInt( obj, INTOBJ_INT( 1 << 16 ) );2210hand = hand + prod * INT_INTOBJ(rem);2211prod = prod * ( 1 << 16 );2212}2213return (Obj) hand;2214}2215else {2216ErrorQuit( "<handle> must be a positive integer", 0L, 0L );2217return (Obj) 0;2218}2219}222022212222/****************************************************************************2223**2224*F FuncHANDLE_OBJ( <self>, <obj> ) . . . . . . expert function 'HANDLE_OBJ'2225*/2226Obj FuncHANDLE_OBJ (2227Obj self,2228Obj obj )2229{2230Obj hnum;2231Obj prod;2232Obj tmp;2233UInt hand;22342235hand = (UInt) obj;2236hnum = INTOBJ_INT(0);2237prod = INTOBJ_INT(1);2238while ( 0 < hand ) {2239tmp = PROD( prod, INTOBJ_INT( hand & 0xffff ) );2240prod = PROD( prod, INTOBJ_INT( 1 << 16 ) );2241hnum = SUM( hnum, tmp );2242hand = hand >> 16;2243}2244return hnum;2245}22462247Obj FuncMASTER_POINTER_NUMBER(Obj self, Obj o)2248{2249if ((void **) o >= (void **) MptrBags && (void **) o < (void **) OldBags) {2250return INTOBJ_INT( ((void **) o - (void **) MptrBags) + 1 );2251} else {2252return INTOBJ_INT( 0 );2253}2254}22552256Obj FuncFUNC_BODY_SIZE(Obj self, Obj f)2257{2258Obj body;2259if (TNUM_OBJ(f) != T_FUNCTION) return Fail;2260body = BODY_FUNC(f);2261if (body == 0) return INTOBJ_INT(0);2262else return INTOBJ_INT( SIZE_BAG( body ) );2263}22642265/****************************************************************************2266**2267*F FuncSWAP_MPTR( <self>, <obj1>, <obj2> ) . . . . . . . swap master pointer2268**2269** Never use this function unless you are debugging.2270*/2271Obj FuncSWAP_MPTR (2272Obj self,2273Obj obj1,2274Obj obj2 )2275{2276if ( TNUM_OBJ(obj1) == T_INT || TNUM_OBJ(obj1) == T_FFE ) {2277ErrorQuit("SWAP_MPTR: <obj1> must not be an integer or ffe", 0L, 0L);2278return 0;2279}2280if ( TNUM_OBJ(obj2) == T_INT || TNUM_OBJ(obj2) == T_FFE ) {2281ErrorQuit("SWAP_MPTR: <obj2> must not be an integer or ffe", 0L, 0L);2282return 0;2283}22842285SwapMasterPoint( obj1, obj2 );2286return 0;2287}228822892290/****************************************************************************2291**22922293*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *2294*/229522962297/****************************************************************************2298**22992300*F FillInVersion( <module>, <rev_c>, <rev_h> ) . . . fill in version number2301*/2302void FillInVersion (2303StructInitInfo * module )2304{2305}230623072308/****************************************************************************2309**2310*F RequireModule( <calling>, <required>, <version> ) . . . . require module2311*/2312void RequireModule (2313StructInitInfo * module,2314const Char * required,2315UInt version )2316{2317}231823192320/****************************************************************************2321**2322*F InitBagNamesFromTable( <table> ) . . . . . . . . . initialise bag names2323*/2324void InitBagNamesFromTable (2325StructBagNames * tab )2326{2327Int i;23282329for ( i = 0; tab[i].tnum != -1; i++ ) {2330InfoBags[tab[i].tnum].name = tab[i].name;2331}2332}233323342335/****************************************************************************2336**2337*F InitClearFiltsTNumsFromTable( <tab> ) . . . initialise clear filts tnums2338*/2339void InitClearFiltsTNumsFromTable (2340Int * tab )2341{2342Int i;23432344for ( i = 0; tab[i] != -1; i += 2 ) {2345ClearFiltsTNums[tab[i]] = tab[i+1];2346}2347}234823492350/****************************************************************************2351**2352*F InitHasFiltListTNumsFromTable( <tab> ) . . initialise tester filts tnums2353*/2354void InitHasFiltListTNumsFromTable (2355Int * tab )2356{2357Int i;23582359for ( i = 0; tab[i] != -1; i += 3 ) {2360HasFiltListTNums[tab[i]][tab[i+1]] = tab[i+2];2361}2362}236323642365/****************************************************************************2366**2367*F InitSetFiltListTNumsFromTable( <tab> ) . . initialise setter filts tnums2368*/2369void InitSetFiltListTNumsFromTable (2370Int * tab )2371{2372Int i;23732374for ( i = 0; tab[i] != -1; i += 3 ) {2375SetFiltListTNums[tab[i]][tab[i+1]] = tab[i+2];2376}2377}237823792380/****************************************************************************2381**2382*F InitResetFiltListTNumsFromTable( <tab> ) initialise unsetter filts tnums2383*/2384void InitResetFiltListTNumsFromTable (2385Int * tab )2386{2387Int i;23882389for ( i = 0; tab[i] != -1; i += 3 ) {2390ResetFiltListTNums[tab[i]][tab[i+1]] = tab[i+2];2391}2392}239323942395/****************************************************************************2396**2397*F InitGVarFiltsFromTable( <tab> ) . . . . . . . . . . . . . . . new filters2398*/2399void InitGVarFiltsFromTable (2400StructGVarFilt * tab )2401{2402Int i;24032404for ( i = 0; tab[i].name != 0; i++ ) {2405UInt gvar = GVarName( tab[i].name );2406AssGVar( gvar,2407NewFilter( NameGVarObj( gvar ), 1, ArgStringToList( tab[i].argument ), tab[i].handler ) );2408MakeReadOnlyGVar( gvar );2409}2410}241124122413/****************************************************************************2414**2415*F InitGVarAttrsFromTable( <tab> ) . . . . . . . . . . . . . new attributes2416*/2417void InitGVarAttrsFromTable (2418StructGVarAttr * tab )2419{2420Int i;24212422for ( i = 0; tab[i].name != 0; i++ ) {2423UInt gvar = GVarName( tab[i].name );2424AssGVar( gvar,2425NewAttribute( NameGVarObj( gvar ),24261,2427ArgStringToList( tab[i].argument ),2428tab[i].handler ) );2429MakeReadOnlyGVar( gvar );2430}2431}243224332434/****************************************************************************2435**2436*F InitGVarPropsFromTable( <tab> ) . . . . . . . . . . . . . new properties2437*/2438void InitGVarPropsFromTable (2439StructGVarProp * tab )2440{2441Int i;24422443for ( i = 0; tab[i].name != 0; i++ ) {2444UInt gvar = GVarName( tab[i].name );2445AssGVar( gvar,2446NewProperty( NameGVarObj( gvar ),24471,2448ArgStringToList( tab[i].argument ),2449tab[i].handler ) );2450MakeReadOnlyGVar( gvar );2451}2452}245324542455/****************************************************************************2456**2457*F InitGVarOpersFromTable( <tab> ) . . . . . . . . . . . . . new operations2458*/2459void InitGVarOpersFromTable (2460StructGVarOper * tab )2461{2462Int i;24632464for ( i = 0; tab[i].name != 0; i++ ) {2465UInt gvar = GVarName( tab[i].name );2466AssGVar( gvar,2467NewOperation( NameGVarObj( gvar ),2468tab[i].nargs,2469ArgStringToList( tab[i].args ),2470tab[i].handler ) );2471MakeReadOnlyGVar( gvar );2472}2473}247424752476/****************************************************************************2477**2478*F InitGVarFuncsFromTable( <tab> ) . . . . . . . . . . . . . . new functions2479*/2480void InitGVarFuncsFromTable (2481StructGVarFunc * tab )2482{2483Int i;24842485for ( i = 0; tab[i].name != 0; i++ ) {2486UInt gvar = GVarName( tab[i].name );2487AssGVar( gvar,2488NewFunction( NameGVarObj( gvar ),2489tab[i].nargs,2490ArgStringToList( tab[i].args ),2491tab[i].handler ) );2492MakeReadOnlyGVar( gvar );2493}2494}249524962497/****************************************************************************2498**2499*F InitHdlrFiltsFromTable( <tab> ) . . . . . . . . . . . . . . . new filters2500*/2501void InitHdlrFiltsFromTable (2502StructGVarFilt * tab )2503{2504Int i;25052506for ( i = 0; tab[i].name != 0; i++ ) {2507InitHandlerFunc( tab[i].handler, tab[i].cookie );2508InitFopyGVar( tab[i].name, tab[i].filter );2509}2510}251125122513/****************************************************************************2514**2515*F InitHdlrAttrsFromTable( <tab> ) . . . . . . . . . . . . . new attributes2516*/2517void InitHdlrAttrsFromTable (2518StructGVarAttr * tab )2519{2520Int i;25212522for ( i = 0; tab[i].name != 0; i++ ) {2523InitHandlerFunc( tab[i].handler, tab[i].cookie );2524InitFopyGVar( tab[i].name, tab[i].attribute );2525}2526}252725282529/****************************************************************************2530**2531*F InitHdlrPropsFromTable( <tab> ) . . . . . . . . . . . . . new properties2532*/2533void InitHdlrPropsFromTable (2534StructGVarProp * tab )2535{2536Int i;25372538for ( i = 0; tab[i].name != 0; i++ ) {2539InitHandlerFunc( tab[i].handler, tab[i].cookie );2540InitFopyGVar( tab[i].name, tab[i].property );2541}2542}254325442545/****************************************************************************2546**2547*F InitHdlrOpersFromTable( <tab> ) . . . . . . . . . . . . . new operations2548*/2549void InitHdlrOpersFromTable (2550StructGVarOper * tab )2551{2552Int i;25532554for ( i = 0; tab[i].name != 0; i++ ) {2555InitHandlerFunc( tab[i].handler, tab[i].cookie );2556InitFopyGVar( tab[i].name, tab[i].operation );2557}2558}255925602561/****************************************************************************2562**2563*F InitHdlrFuncsFromTable( <tab> ) . . . . . . . . . . . . . . new functions2564*/2565void InitHdlrFuncsFromTable (2566StructGVarFunc * tab )2567{2568Int i;25692570for ( i = 0; tab[i].name != 0; i++ ) {2571InitHandlerFunc( tab[i].handler, tab[i].cookie );2572}2573}257425752576/****************************************************************************2577**2578*F ImportGVarFromLibrary( <name>, <address> ) . . . import global variable2579*/258025812582void ImportGVarFromLibrary(2583const Char * name,2584Obj * address )2585{2586if ( NrImportedGVars == 1024 ) {2587Pr( "#W warning: too many imported GVars\n", 0L, 0L );2588}2589else {2590ImportedGVars[NrImportedGVars].name = name;2591ImportedGVars[NrImportedGVars].address = address;2592NrImportedGVars++;2593}2594if ( address != 0 ) {2595InitCopyGVar( name, address );2596}2597}259825992600/****************************************************************************2601**2602*F ImportFuncFromLibrary( <name>, <address> ) . . . import global function2603*/260426052606void ImportFuncFromLibrary(2607const Char * name,2608Obj * address )2609{2610if ( NrImportedFuncs == 1024 ) {2611Pr( "#W warning: too many imported Funcs\n", 0L, 0L );2612}2613else {2614ImportedFuncs[NrImportedFuncs].name = name;2615ImportedFuncs[NrImportedFuncs].address = address;2616NrImportedFuncs++;2617}2618if ( address != 0 ) {2619InitFopyGVar( name, address );2620}2621}262226232624/****************************************************************************2625**2626*F FuncExportToKernelFinished( <self> ) . . . . . . . . . . check functions2627*/2628Obj FuncExportToKernelFinished (2629Obj self )2630{2631UInt i;2632Int errs = 0;2633Obj val;26342635SyInitializing = 0;2636for ( i = 0; i < NrImportedGVars; i++ ) {2637if ( ImportedGVars[i].address == 0 ) {2638val = ValAutoGVar(GVarName(ImportedGVars[i].name));2639if ( val == 0 ) {2640errs++;2641if ( ! SyQuiet ) {2642Pr( "#W global variable '%s' has not been defined\n",2643(Int)ImportedFuncs[i].name, 0L );2644}2645}2646}2647else if ( *ImportedGVars[i].address == 0 ) {2648errs++;2649if ( ! SyQuiet ) {2650Pr( "#W global variable '%s' has not been defined\n",2651(Int)ImportedGVars[i].name, 0L );2652}2653}2654else {2655MakeReadOnlyGVar(GVarName(ImportedGVars[i].name));2656}2657}26582659for ( i = 0; i < NrImportedFuncs; i++ ) {2660if ( ImportedFuncs[i].address == 0 ) {2661val = ValAutoGVar(GVarName(ImportedFuncs[i].name));2662if ( val == 0 || ! IS_FUNC(val) ) {2663errs++;2664if ( ! SyQuiet ) {2665Pr( "#W global function '%s' has not been defined\n",2666(Int)ImportedFuncs[i].name, 0L );2667}2668}2669}2670else if ( *ImportedFuncs[i].address == ErrorMustEvalToFuncFunc2671|| *ImportedFuncs[i].address == ErrorMustHaveAssObjFunc )2672{2673errs++;2674if ( ! SyQuiet ) {2675Pr( "#W global function '%s' has not been defined\n",2676(Int)ImportedFuncs[i].name, 0L );2677}2678}2679else {2680MakeReadOnlyGVar(GVarName(ImportedFuncs[i].name));2681}2682}26832684return errs == 0 ? True : False;2685}268626872688/****************************************************************************2689**2690*F FuncSleep( <self>, <secs> )2691**2692*/26932694Obj FuncSleep( Obj self, Obj secs )2695{2696Int s;26972698while( ! IS_INTOBJ(secs) )2699secs = ErrorReturnObj( "<secs> must be a small integer", 0L, 0L,2700"you can replace <secs> via 'return <secs>;'" );270127022703if ( (s = INT_INTOBJ(secs)) > 0)2704SySleep((UInt)s);27052706/* either we used up the time, or we were interrupted. */2707if (SyIsIntr())2708{2709ClearError(); /* The interrupt may still be pending */2710ErrorReturnVoid("user interrupt in sleep", 0L, 0L,2711"you can 'return;' as if the sleep was finished");2712}27132714return (Obj) 0;2715}27162717// Common code in the next 3 methods.2718static int SetExitValue(Obj code)2719{2720if (code == False || code == Fail)2721SystemErrorCode = 1;2722else if (code == True)2723SystemErrorCode = 0;2724else if (IS_INTOBJ(code))2725SystemErrorCode = INT_INTOBJ(code);2726else2727return 0;2728return 1;2729}27302731/****************************************************************************2732**2733*F FuncGAP_EXIT_CODE() . . . . . . . . Set the code with which GAP exits.2734**2735*/27362737Obj FuncGAP_EXIT_CODE( Obj self, Obj code )2738{2739if (!SetExitValue(code))2740ErrorQuit("GAP_EXIT_CODE: Argument must be boolean or integer", 0L, 0L);2741return (Obj) 0;2742}274327442745/****************************************************************************2746**2747*F FuncQUIT_GAP()2748**2749*/27502751Obj FuncQUIT_GAP( Obj self, Obj args )2752{2753if ( LEN_LIST(args) == 0 ) {2754SystemErrorCode = 0;2755}2756else if ( LEN_LIST(args) != 12757|| !SetExitValue(ELM_PLIST(args, 1) ) ) {2758ErrorQuit( "usage: QUIT_GAP( [ <return value> ] )", 0L, 0L );2759return 0;2760}2761TLS(UserHasQUIT) = 1;2762ReadEvalError();2763return (Obj)0;2764}27652766/****************************************************************************2767**2768*F FuncFORCE_QUIT_GAP()2769**2770*/27712772Obj FuncFORCE_QUIT_GAP( Obj self, Obj args )2773{2774if ( LEN_LIST(args) == 0 )2775{2776SyExit(SystemErrorCode);2777}2778else if ( LEN_LIST(args) != 12779|| !SetExitValue(ELM_PLIST(args, 1) ) ) {2780ErrorQuit( "usage: FORCE_QUIT_GAP( [ <return value> ] )", 0L, 0L );2781return 0;2782}2783SyExit(SystemErrorCode);2784return (Obj) 0; /* should never get here */2785}278627872788/****************************************************************************2789**2790*F KERNEL_INFO() ......................record of information from the kernel2791**2792** The general idea is to put all kernel-specific info in here, and clean up2793** the assortment of global variables previously used2794*/27952796Obj FuncKERNEL_INFO(Obj self) {2797Obj res = NEW_PREC(0);2798UInt r,lenvec,lenstr,lenstr2;2799Char *p;2800Obj tmp,list,str;2801UInt i,j;28022803/* GAP_ARCHITECTURE */2804C_NEW_STRING_DYN( tmp, SyArchitecture );2805RetypeBag( tmp, IMMUTABLE_TNUM(TNUM_OBJ(tmp)) );2806r = RNamName("GAP_ARCHITECTURE");2807AssPRec(res,r,tmp);2808/* KERNEL_VERSION */2809C_NEW_STRING_DYN( tmp, SyKernelVersion );2810RetypeBag( tmp, IMMUTABLE_TNUM(TNUM_OBJ(tmp)) );2811r = RNamName("KERNEL_VERSION");2812AssPRec(res,r,tmp);2813C_NEW_STRING_DYN( tmp, SyBuildVersion );2814RetypeBag( tmp, IMMUTABLE_TNUM(TNUM_OBJ(tmp)) );2815r = RNamName("BUILD_VERSION");2816AssPRec(res,r,tmp);2817C_NEW_STRING_DYN( tmp, SyBuildDateTime );2818RetypeBag( tmp, IMMUTABLE_TNUM(TNUM_OBJ(tmp)) );2819r = RNamName("BUILD_DATETIME");2820AssPRec(res,r,tmp);2821/* GAP_ROOT_PATH */2822/* do we need this. Could we rebuild it from the command line in GAP2823if so, should we */2824list = NEW_PLIST( T_PLIST+IMMUTABLE, MAX_GAP_DIRS );2825for ( i = 0, j = 1; i < MAX_GAP_DIRS; i++ ) {2826if ( SyGapRootPaths[i][0] ) {2827C_NEW_STRING_DYN( tmp, SyGapRootPaths[i] );2828RetypeBag( tmp, IMMUTABLE_TNUM(TNUM_OBJ(tmp)) );2829SET_ELM_PLIST( list, j, tmp );2830j++;2831}2832}2833SET_LEN_PLIST( list, j-1 );2834r = RNamName("GAP_ROOT_PATHS");2835AssPRec(res,r,list);2836/* And also the DotGapPath if available */2837#if HAVE_DOTGAPRC2838C_NEW_STRING_DYN( tmp, DotGapPath );2839RetypeBag( tmp, IMMUTABLE_TNUM(TNUM_OBJ(tmp)) );2840r = RNamName("DOT_GAP_PATH");2841AssPRec(res,r,tmp);2842#endif28432844/* make command line and environment available to GAP level */2845for (lenvec=0; SyOriginalArgv[lenvec]; lenvec++);2846tmp = NEW_PLIST( T_PLIST+IMMUTABLE, lenvec );2847SET_LEN_PLIST( tmp, lenvec );2848for (i = 0; i<lenvec; i++) {2849C_NEW_STRING_DYN( str, SyOriginalArgv[i] );2850SET_ELM_PLIST(tmp, i+1, str);2851CHANGED_BAG(tmp);2852}2853r = RNamName("COMMAND_LINE");2854AssPRec(res,r, tmp);28552856tmp = NEW_PREC(0);2857for (i = 0; sysenviron[i]; i++) {2858for (p = sysenviron[i]; *p != '='; p++)2859;2860lenstr2 = (UInt) (p-sysenviron[i]);2861p++; /* Move pointer behind = character */2862lenstr = strlen(p);2863if (lenstr2 > lenstr)2864str = NEW_STRING(lenstr2);2865else2866str = NEW_STRING(lenstr);2867strncat(CSTR_STRING(str),sysenviron[i],lenstr2);2868r = RNamName(CSTR_STRING(str));2869*(CSTR_STRING(str)) = 0;2870strncat(CSTR_STRING(str),p, lenstr);2871SET_LEN_STRING(str, lenstr);2872SHRINK_STRING(str);2873AssPRec(tmp,r , str);2874}2875r = RNamName("ENVIRONMENT");2876AssPRec(res,r, tmp);28772878/* and also the CONFIGNAME of the running GAP kernel */2879C_NEW_STRING_DYN( str, CONFIGNAME );2880r = RNamName("CONFIGNAME");2881AssPRec(res, r, str);28822883/* export if we want to use readline */2884r = RNamName("HAVE_LIBREADLINE");2885if (SyUseReadline)2886AssPRec(res, r, True);2887else2888AssPRec(res, r, False);28892890return res;28912892}289328942895/****************************************************************************2896**2897*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export2898*/2899static StructGVarFunc GVarFuncs [] = {29002901{ "Runtime", 0, "",2902FuncRuntime, "src/gap.c:Runtime" },29032904{ "RUNTIMES", 0, "",2905FuncRUNTIMES, "src/gap.c:RUNTIMES" },29062907{ "SizeScreen", -1, "args",2908FuncSizeScreen, "src/gap.c:SizeScreen" },29092910{ "ID_FUNC", 1, "object",2911FuncID_FUNC, "src/gap.c:ID_FUNC" },29122913{ "RETURN_FIRST", -1, "object",2914FuncRETURN_FIRST, "src/gap.c:RETURN_FIRST" },29152916{ "RETURN_NOTHING", -1, "object",2917FuncRETURN_NOTHING, "src/gap.c:RETURN_NOTHING" },29182919{ "ExportToKernelFinished", 0, "",2920FuncExportToKernelFinished, "src/gap.c:ExportToKernelFinished" },29212922{ "DownEnv", -1, "args",2923FuncDownEnv, "src/gap.c:DownEnv" },29242925{ "UpEnv", -1, "args",2926FuncUpEnv, "src/gap.c:UpEnv" },29272928{ "GAP_CRC", 1, "filename",2929FuncGAP_CRC, "src/gap.c:GAP_CRC" },29302931{ "LOAD_DYN", 2, "filename, crc",2932FuncLOAD_DYN, "src/gap.c:LOAD_DYN" },29332934{ "LOAD_STAT", 2, "filename, crc",2935FuncLOAD_STAT, "src/gap.c:LOAD_STAT" },29362937{ "SHOW_STAT", 0, "",2938FuncSHOW_STAT, "src/gap.c:SHOW_STAT" },29392940{ "GASMAN", -1, "args",2941FuncGASMAN, "src/gap.c:GASMAN" },29422943{ "GASMAN_STATS", 0, "",2944FuncGASMAN_STATS, "src/gap.c:GASMAN_STATS" },29452946{ "GASMAN_MESSAGE_STATUS", 0, "",2947FuncGASMAN_MESSAGE_STATUS, "src/gap.c:GASMAN_MESSAGE_STATUS" },29482949{ "GASMAN_LIMITS", 0, "",2950FuncGASMAN_LIMITS, "src/gap.c:GASMAN_LIMITS" },29512952{ "SHALLOW_SIZE", 1, "object",2953FuncSHALLOW_SIZE, "src/gap.c:SHALLOW_SIZE" },29542955{ "TNUM_OBJ", 1, "object",2956FuncTNUM_OBJ, "src/gap.c:TNUM_OBJ" },29572958{ "TNUM_OBJ_INT", 1, "object",2959FuncTNUM_OBJ_INT, "src/gap.c:TNUM_OBJ_INT" },29602961{ "OBJ_HANDLE", 1, "object",2962FuncOBJ_HANDLE, "src/gap.c:OBJ_HANDLE" },29632964{ "HANDLE_OBJ", 1, "object",2965FuncHANDLE_OBJ, "src/gap.c:HANDLE_OBJ" },29662967{ "SWAP_MPTR", 2, "obj1, obj2",2968FuncSWAP_MPTR, "src/gap.c:SWAP_MPTR" },29692970{ "LoadedModules", 0, "",2971FuncLoadedModules, "src/gap.c:LoadedModules" },29722973{ "WindowCmd", 1, "arg-list",2974FuncWindowCmd, "src/gap.c:WindowCmd" },297529762977{ "Sleep", 1, "secs",2978FuncSleep, "src/gap.c:Sleep" },29792980{ "GAP_EXIT_CODE", 1, "exit code",2981FuncGAP_EXIT_CODE, "src/gap.c:GAP_EXIT_CODE" },29822983{ "QUIT_GAP", -1, "args",2984FuncQUIT_GAP, "src/gap.c:QUIT_GAP" },29852986{ "FORCE_QUIT_GAP", -1, "args",2987FuncFORCE_QUIT_GAP, "src/gap.c:FORCE_QUIT_GAP" },29882989{ "SHELL", -1, "context, canReturnVoid, canReturnObj, lastDepth, setTime, prompt, promptHook, infile, outfile",2990FuncSHELL, "src/gap.c:FuncSHELL" },29912992{ "CALL_WITH_CATCH", 2, "func, args",2993FuncCALL_WITH_CATCH, "src/gap.c:CALL_WITH_CATCH" },29942995{ "TIMEOUTS_SUPPORTED", 0, "",2996FuncTIMEOUTS_SUPPORTED, "src/gap.c:TIMEOUTS_SUPPORTED" },29972998{ "CALL_WITH_TIMEOUT", 4, "seconds, microseconds, func, args",2999FuncCALL_WITH_TIMEOUT, "src/gap.c:CALL_WITH_TIMEOUT" },30003001{"STOP_TIMEOUT", 0, "",3002FuncSTOP_TIMEOUT, "src/gap.c:FuncSTOP_TIMEOUT" },30033004{"RESUME_TIMEOUT", 1, "state",3005FuncRESUME_TIMEOUT, "src/gap.c:FuncRESUME_TIMEOUT" },30063007{ "JUMP_TO_CATCH", 1, "payload",3008FuncJUMP_TO_CATCH, "src/gap.c:JUMP_TO_CATCH" },300930103011{ "KERNEL_INFO", 0, "",3012FuncKERNEL_INFO, "src/gap.c:KERNEL_INFO" },30133014{ "SetUserHasQuit", 1, "value",3015FuncSetUserHasQuit, "src/gap.c:SetUserHasQuit" },30163017{ "MASTER_POINTER_NUMBER", 1, "ob",3018FuncMASTER_POINTER_NUMBER, "src/gap.c:MASTER_POINTER_NUMBER" },30193020{ "FUNC_BODY_SIZE", 1, "f",3021FuncFUNC_BODY_SIZE, "src/gap.c:FUNC_BODY_SIZE" },30223023{ "PRINT_CURRENT_STATEMENT", 1, "context",3024FuncPrintExecutingStatement, "src/gap.c:PRINT_CURRENT_STATEMENT" },302530263027{ 0 }30283029};303030313032/****************************************************************************3033**30343035*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures3036*/3037static Int InitKernel (3038StructInitInfo * module )3039{3040/* init the completion function */3041InitGlobalBag( &ThrownObject, "src/gap.c:ThrownObject" );30423043/* list of exit functions */3044InitGlobalBag( &WindowCmdString, "src/gap.c:WindowCmdString" );30453046/* init filters and functions */3047InitHdlrFuncsFromTable( GVarFuncs );3048304930503051/* establish Fopy of ViewObj */3052ImportFuncFromLibrary( "ViewObj", 0L );3053ImportFuncFromLibrary( "Error", &Error );3054ImportFuncFromLibrary( "ErrorInner", &ErrorInner );305530563057#if HAVE_SELECT3058InitCopyGVar("OnCharReadHookActive",&OnCharReadHookActive);3059InitCopyGVar("OnCharReadHookInFds",&OnCharReadHookInFds);3060InitCopyGVar("OnCharReadHookInFuncs",&OnCharReadHookInFuncs);3061InitCopyGVar("OnCharReadHookOutFds",&OnCharReadHookOutFds);3062InitCopyGVar("OnCharReadHookOutFuncs",&OnCharReadHookOutFuncs);3063InitCopyGVar("OnCharReadHookExcFds",&OnCharReadHookExcFds);3064InitCopyGVar("OnCharReadHookExcFuncs",&OnCharReadHookExcFuncs);3065#endif30663067/* return success */3068return 0;3069}307030713072/****************************************************************************3073**3074*F PostRestore( <module> ) . . . . . . . . . . . . . after restore workspace3075*/3076static Int PostRestore (3077StructInitInfo * module )3078{3079UInt var;30803081/* library name and other stuff */3082var = GVarName( "DEBUG_LOADING" );3083MakeReadWriteGVar(var);3084AssGVar( var, (SyDebugLoading ? True : False) );3085MakeReadOnlyGVar(var);30863087/* construct the `ViewObj' variable */3088ViewObjGVar = GVarName( "ViewObj" );3089CustomViewGVar = GVarName( "CustomView" );30903091/* construct the last and time variables */3092Last = GVarName( "last" );3093Last2 = GVarName( "last2" );3094Last3 = GVarName( "last3" );3095Time = GVarName( "time" );3096AssGVar(Time, INTOBJ_INT(0));3097QUITTINGGVar = GVarName( "QUITTING" );30983099/* return success */3100return 0;3101}310231033104/****************************************************************************3105**3106*F InitLibrary( <module> ) . . . . . . . initialise library data structures3107*/3108static Int InitLibrary (3109StructInitInfo * module )3110{3111/* init filters and functions */3112InitGVarFuncsFromTable( GVarFuncs );31133114/* create windows command buffer */3115WindowCmdString = NEW_STRING( 1000 );31163117/* return success */3118return PostRestore( module );3119}312031213122/****************************************************************************3123**3124*F InitInfoGap() . . . . . . . . . . . . . . . . . . table of init functions3125*/3126static StructInitInfo module = {3127MODULE_BUILTIN, /* type */3128"gap", /* name */31290, /* revision entry of c file */31300, /* revision entry of h file */31310, /* version */31320, /* crc */3133InitKernel, /* initKernel */3134InitLibrary, /* initLibrary */31350, /* checkInit */31360, /* preSave */31370, /* postSave */3138PostRestore /* postRestore */3139};31403141StructInitInfo * InitInfoGap ( void )3142{3143return &module;3144}314531463147/****************************************************************************3148**31493150*V InitFuncsBuiltinModules . . . . . list of builtin modules init functions3151*/3152static InitInfoFunc InitFuncsBuiltinModules[] = {31533154/* global variables */3155InitInfoGVars,31563157/* objects */3158InitInfoObjects,31593160/* profiling information */3161InitInfoProfile,31623163/* scanner, reader, interpreter, coder, caller, compiler */3164InitInfoScanner,3165InitInfoRead,3166InitInfoCalls,3167InitInfoExprs,3168InitInfoStats,3169InitInfoCode,3170InitInfoVars, /* must come after InitExpr and InitStats */3171InitInfoFuncs,3172InitInfoOpers,3173InitInfoIntrprtr,3174InitInfoCompiler,31753176/* arithmetic operations */3177InitInfoAriths,3178InitInfoInt,3179InitInfoIntFuncs,3180InitInfoRat,3181InitInfoCyc,3182InitInfoFinfield,3183InitInfoPermutat,3184InitInfoTrans,3185InitInfoPPerm,3186InitInfoBool,3187InitInfoMacfloat,31883189/* record packages */3190InitInfoRecords,3191InitInfoPRecord,31923193/* list packages */3194InitInfoLists,3195InitInfoListOper,3196InitInfoListFunc,3197InitInfoPlist,3198InitInfoSet,3199InitInfoVector,3200InitInfoVecFFE,3201InitInfoBlist,3202InitInfoRange,3203InitInfoString,3204InitInfoGF2Vec,3205InitInfoVec8bit,32063207/* free and presented groups */3208InitInfoFreeGroupElements,3209InitInfoCosetTable,3210InitInfoTietze,3211InitInfoPcElements,3212InitInfoSingleCollector,3213InitInfoCombiCollector,3214InitInfoPcc,3215InitInfoDeepThought,3216InitInfoDTEvaluation,32173218/* algebras */3219InitInfoSCTable,32203221/* save and load workspace, weak pointers */3222InitInfoWeakPtr,3223InitInfoSaveLoad,32243225/* input and output */3226InitInfoStreams,3227InitInfoSysFiles,3228InitInfoIOStream,32293230/* main module */3231InitInfoGap,32323233#ifdef GAPMPI3234/* ParGAP/MPI module */3235InitInfoGapmpi,3236#endif3237323803239};324032413242/****************************************************************************3243**3244*F Modules . . . . . . . . . . . . . . . . . . . . . . . . . list of modules3245*/3246#ifndef MAX_MODULES3247#define MAX_MODULES 10003248#endif324932503251#ifndef MAX_MODULE_FILENAMES3252#define MAX_MODULE_FILENAMES (MAX_MODULES*50)3253#endif32543255Char LoadedModuleFilenames[MAX_MODULE_FILENAMES];3256Char *NextLoadedModuleFilename = LoadedModuleFilenames;325732583259StructInitInfo * Modules [ MAX_MODULES ];3260UInt NrModules;3261UInt NrBuiltinModules;326232633264/****************************************************************************3265**3266*F RecordLoadedModule( <module> ) . . . . . . . . store module in <Modules>3267*/32683269void RecordLoadedModule (3270StructInitInfo * info,3271Char *filename )3272{3273UInt len;3274if ( NrModules == MAX_MODULES ) {3275Pr( "panic: no room to record module\n", 0L, 0L );3276}3277len = strlen(filename);3278if (NextLoadedModuleFilename + len + 13279> LoadedModuleFilenames+MAX_MODULE_FILENAMES) {3280Pr( "panic: no room for module filename\n", 0L, 0L );3281}3282*NextLoadedModuleFilename = '\0';3283memcpy(NextLoadedModuleFilename, filename, len+1);3284info->filename = NextLoadedModuleFilename;3285NextLoadedModuleFilename += len +1;3286Modules[NrModules++] = info;3287}328832893290/****************************************************************************3291**3292*F InitializeGap() . . . . . . . . . . . . . . . . . . . . . . intialize GAP3293**3294** Each module (builtin or compiled) exports a sturctures which contains3295** information about the name, version, crc, init function, save and restore3296** functions.3297**3298** The init process is split into three different functions:3299**3300** `InitKernel': This function setups the internal data structures and3301** tables, registers the global bags and functions handlers, copies and3302** fopies. It is not allowed to create objects, gvar or rnam numbers. This3303** function is used for both starting and restoring.3304**3305** `InitLibrary': This function creates objects, gvar and rnam number, and3306** does assignments of auxillary C variables (for example, pointers from3307** objects, length of hash lists). This function is only used for starting.3308**3309** `PostRestore': Everything in `InitLibrary' execpt creating objects. In3310** general `InitLibrary' will create all objects and then calls3311** `PostRestore'. This function is only used when restoring.3312*/3313#ifndef BOEHM_GC3314extern TNumMarkFuncBags TabMarkFuncBags [ 256 ];3315#endif33163317static Obj POST_RESTORE;33183319void InitializeGap (3320int * pargc,3321char * argv [] )3322{3323/* UInt type; */3324UInt i;3325Int ret;332633273328/* initialize the basic system and gasman */3329#ifdef GAPMPI3330/* ParGAP/MPI needs to call MPI_Init() first to remove command line args */3331InitGapmpi( pargc, &argv );3332#endif33333334InitSystem( *pargc, argv );33353336/* Initialise memory -- have to do this here to make sure we are at top of C stack */3337InitBags( SyAllocBags, SyStorMin,33380, (Bag*)(((UInt)pargc/SyStackAlign)*SyStackAlign), SyStackAlign,3339SyCacheSize, 0, SyAbortBags );3340InitMsgsFuncBags( SyMsgsBags );334133423343/* get info structures for the build in modules */3344NrModules = 0;3345for ( i = 0; InitFuncsBuiltinModules[i]; i++ ) {3346if ( NrModules == MAX_MODULES ) {3347FPUTS_TO_STDERR( "panic: too many builtin modules\n" );3348SyExit(1);3349}3350Modules[NrModules++] = InitFuncsBuiltinModules[i]();3351# ifdef DEBUG_LOADING3352FPUTS_TO_STDERR( "#I InitInfo(builtin " );3353FPUTS_TO_STDERR( Modules[NrModules-1]->name );3354FPUTS_TO_STDERR( ")\n" );3355# endif3356}3357NrBuiltinModules = NrModules;33583359/* call kernel initialisation */3360for ( i = 0; i < NrBuiltinModules; i++ ) {3361if ( Modules[i]->initKernel ) {3362# ifdef DEBUG_LOADING3363FPUTS_TO_STDERR( "#I InitKernel(builtin " );3364FPUTS_TO_STDERR( Modules[i]->name );3365FPUTS_TO_STDERR( ")\n" );3366# endif3367ret =Modules[i]->initKernel( Modules[i] );3368if ( ret ) {3369FPUTS_TO_STDERR( "#I InitKernel(builtin " );3370FPUTS_TO_STDERR( Modules[i]->name );3371FPUTS_TO_STDERR( ") returned non-zero value\n" );3372}3373}3374}33753376InitGlobalBag(&POST_RESTORE, "gap.c: POST_RESTORE");3377InitFopyGVar( "POST_RESTORE", &POST_RESTORE);33783379/* you should set 'COUNT_BAGS' as well */3380# ifdef DEBUG_LOADING3381if ( SyRestoring ) {3382Pr( "#W after setup\n", 0L, 0L );3383Pr( "#W %36s ", (Int)"type", 0L );3384Pr( "%8s %8s ", (Int)"alive", (Int)"kbyte" );3385Pr( "%8s %8s\n", (Int)"total", (Int)"kbyte" );3386for ( i = 0; i < 256; i++ ) {3387if ( InfoBags[i].name != 0 && InfoBags[i].nrAll != 0 ) {3388char buf[41];33893390buf[0] = '\0';3391strlcat( buf, InfoBags[i].name, sizeof(buf) );3392Pr("#W %36s ", (Int)buf, 0L );3393Pr("%8d %8d ", (Int)InfoBags[i].nrLive,3394(Int)(InfoBags[i].sizeLive/1024));3395Pr("%8d %8d\n",(Int)InfoBags[i].nrAll,3396(Int)(InfoBags[i].sizeAll/1024));3397}3398}3399}3400# endif34013402#ifndef BOEHM_GC3403/* and now for a special hack */3404for ( i = LAST_CONSTANT_TNUM+1; i <= LAST_REAL_TNUM; i++ ) {3405if (TabMarkFuncBags[i + COPYING] == MarkAllSubBagsDefault)3406TabMarkFuncBags[ i+COPYING ] = TabMarkFuncBags[ i ];3407}3408#endif34093410/* if we are restoring, load the workspace and call the post restore */3411if ( SyRestoring ) {3412LoadWorkspace(SyRestoring);3413for ( i = 0; i < NrModules; i++ ) {3414if ( Modules[i]->postRestore ) {3415# ifdef DEBUG_LOADING3416FPUTS_TO_STDERR( "#I PostRestore(builtin " );3417FPUTS_TO_STDERR( Modules[i]->name );3418FPUTS_TO_STDERR( ")\n" );3419# endif3420ret = Modules[i]->postRestore( Modules[i] );3421if ( ret ) {3422FPUTS_TO_STDERR( "#I PostRestore(builtin " );3423FPUTS_TO_STDERR( Modules[i]->name );3424FPUTS_TO_STDERR( ") returned non-zero value\n" );3425}3426}3427}3428SyRestoring = NULL;342934303431/* Call POST_RESTORE which is a GAP function that now takes control,3432calls the post restore functions and then runs a GAP session */3433if (POST_RESTORE != (Obj) 0 &&3434IS_FUNC(POST_RESTORE))3435if (!READ_ERROR())3436CALL_0ARGS(POST_RESTORE);3437}343834393440/* otherwise call library initialisation */3441else {3442WarnInitGlobalBag = 1;3443# ifdef DEBUG_HANDLER_REGISTRATION3444CheckAllHandlers();3445# endif34463447SyInitializing = 1;3448for ( i = 0; i < NrBuiltinModules; i++ ) {3449if ( Modules[i]->initLibrary ) {3450# ifdef DEBUG_LOADING3451FPUTS_TO_STDERR( "#I InitLibrary(builtin " );3452FPUTS_TO_STDERR( Modules[i]->name );3453FPUTS_TO_STDERR( ")\n" );3454# endif3455ret = Modules[i]->initLibrary( Modules[i] );3456if ( ret ) {3457FPUTS_TO_STDERR( "#I InitLibrary(builtin " );3458FPUTS_TO_STDERR( Modules[i]->name );3459FPUTS_TO_STDERR( ") returned non-zero value\n" );3460}3461}3462}3463WarnInitGlobalBag = 0;3464}34653466/* check initialisation */3467for ( i = 0; i < NrModules; i++ ) {3468if ( Modules[i]->checkInit ) {3469# ifdef DEBUG_LOADING3470FPUTS_TO_STDERR( "#I CheckInit(builtin " );3471FPUTS_TO_STDERR( Modules[i]->name );3472FPUTS_TO_STDERR( ")\n" );3473# endif3474ret = Modules[i]->checkInit( Modules[i] );3475if ( ret ) {3476FPUTS_TO_STDERR( "#I CheckInit(builtin " );3477FPUTS_TO_STDERR( Modules[i]->name );3478FPUTS_TO_STDERR( ") returned non-zero value\n" );3479}3480}3481}34823483/* read the init files3484this now actually runs the GAP session, we only get3485past here when we're about to exit.3486*/3487if ( SySystemInitFile[0] ) {3488if (!READ_ERROR()) {3489if ( READ_GAP_ROOT(SySystemInitFile) == 0 ) {3490/* if ( ! SyQuiet ) { */3491Pr( "gap: hmm, I cannot find '%s' maybe",3492(Int)SySystemInitFile, 0L );3493Pr( " use option '-l <gaproot>'?\n If you ran the GAP"3494" binary directly, try running the 'gap.sh' or 'gap.bat'"3495" script instead.", 0L, 0L );3496}3497}3498else3499{3500Pr("Caught error at top-most level, probably quit from library loading",0L,0L);3501SyExit(1);3502}3503/* } */3504}35053506}35073508/****************************************************************************3509**3510*E gap.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here3511*/351235133514