/* * Definitions and declarations used throughout the run-time system. * These are also used by the linker in constructing data for use by * the run-time system. */ #ifdef StandardC #include #endif /* StandardC */ #include "..\h\cpuconf.h" #include "..\h\memsize.h" /* * Constants that are not likely to vary between implementations. */ #define BitOffMask (IntBits-1) #define CsetSize (256/IntBits) /* number of ints to hold 256 cset * bits. Use (256/IntBits)+1 if * 256 % IntBits != 0 */ #define MinListSlots 8 /* number of elements in an expansion * list element block */ #define MaxCvtLen 257 /* largest string in conversions; the extra * one is for a terminating null */ #define MaxReadStr 512 /* largest string to read() in one piece */ #define MaxIn 32767 /* largest number of bytes to read() at once */ #define RandA 1103515245 /* random seed multiplier */ #define RandC 453816694 /* random seed additive constant */ #define RanScale 4.65661286e-10 /* random scale factor = 1/(2^31-1)) */ /* * File status flags in status field of file blocks. */ #define Fs_Read 01 /* read access */ #define Fs_Write 02 /* write access */ #define Fs_Create 04 /* file created on open */ #define Fs_Append 010 /* append mode */ #define Fs_Pipe 020 /* reading/writing on a pipe */ #ifdef RecordIO #define Fs_Record 040 /* record structured file */ #endif /* RecordIO */ #ifdef StandardLib #define Fs_Reading 0100 /* last file operation was read */ #define Fs_Writing 0200 /* last file operation was write */ #endif /* StandardLib */ /* * Definitions for interpreter actions. */ #define A_Failure 1 /* routine failed */ #define A_Suspension 2 /* routine suspended */ #define A_Return 3 /* routine returned */ #define A_Pret_uw 4 /* interp unwind for Op_Pret */ #define A_Unmark_uw 5 /* interp unwind for Op_Unmark */ #define A_Resumption 6 /* resume generator */ #define A_Pfail_uw 7 /* interp unwind for Op_Pfail */ #define A_Lsusp_uw 8 /* interp unwind for Op_Lsusp */ #define A_Eret_uw 9 /* interp unwind for Op_Eret */ #define A_Coact 10 /* co-expression activated */ #define A_Coret 11 /* co-expression returned */ #define A_Cofail 12 /* co-expression failed */ /* * Codes returned by invoke to indicate action. */ #define I_Builtin 201 /* A built-in routine is to be invoked */ #define I_Fail 202 /* goal-directed evaluation failed */ #define I_Continue 203 /* Continue execution in the interp loop */ #define I_Vararg 204 /* A function with a variable number of args */ /* * Codes returned by runtime support routines. * Note, some conversion routines also return type codes. Other routines may * return positive values other than return codes. sort() places restrictions * on Less, Equal, and Greater. */ #define Less -1 #define Equal 0 #define Greater 1 #define CvtFail -2 #define Cvt -3 #define NoCvt -4 #define Failure -5 #define Defaulted -6 #define Success -7 #define Error -8 /* * Generator types. */ #define G_Csusp 1 #define G_Esusp 2 #define G_Psusp 3 /* * Type codes (descriptors and blocks). */ #define T_Null 0 /* null value */ #define T_Integer 1 /* integer */ #ifdef LargeInts #define T_Bignum 2 /* long integer */ #endif /* LargeInts */ #define T_Real 3 /* real number */ #define T_Cset 4 /* cset */ #define T_File 5 /* file */ #define T_Proc 6 /* procedure */ #define T_List 7 /* list header */ #define T_Table 8 /* table header */ #define T_Record 9 /* record */ #define T_Telem 10 /* table element */ #define T_Lelem 11 /* list element */ #define T_Tvsubs 12 /* substring trapped variable */ #define T_Tvkywd 13 /* keyword trapped variable */ #define T_Tvtbl 14 /* table element trapped variable */ #define T_Set 15 /* set header */ #define T_Selem 16 /* set element */ #define T_Refresh 17 /* refresh block */ #define T_Coexpr 18 /* co-expression */ #define T_External 19 /* external block */ #define T_Slots 20 /* set/table hash slots */ #define MaxType 20 /* maximum type number */ /* * Descriptor types and flags. */ #define D_Null (word)(T_Null | F_Nqual) #define D_Integer (word)(T_Integer | F_Nqual) #ifdef LargeInts #define D_Bignum (word)(T_Bignum | F_Ptr | F_Nqual) #endif /* LargeInts */ #define D_Real (word)(T_Real | F_Ptr | F_Nqual) #define D_Cset (word)(T_Cset | F_Ptr | F_Nqual) #define D_File (word)(T_File | F_Ptr | F_Nqual) #define D_Proc (word)(T_Proc | F_Ptr | F_Nqual) #define D_List (word)(T_List | F_Ptr | F_Nqual) #define D_Table (word)(T_Table | F_Ptr | F_Nqual) #define D_Telem (word)(T_Telem | F_Ptr | F_Nqual) #define D_Tvsubs (word)(T_Tvsubs | D_Tvar) #define D_Tvkywd (word)(T_Tvkywd | D_Tvar) #define D_Tvtbl (word)(T_Tvtbl | D_Tvar) #define D_Record (word)(T_Record | F_Ptr | F_Nqual) #define D_Set (word)(T_Set | F_Ptr | F_Nqual) #define D_Refresh (word)(T_Refresh | F_Ptr | F_Nqual) #define D_Coexpr (word)(T_Coexpr | F_Ptr | F_Nqual) #define D_External (word)(T_External | F_Ptr | F_Nqual) #define D_Slots (word)(T_Slots | F_Ptr | F_Nqual) #define D_Var (word)(F_Var | F_Nqual | F_Ptr) #define D_Tvar (word)(D_Var | F_Tvar) #define TypeMask 63 /* type mask */ #define OffsetMask (~(D_Tvar)) /* offset mask for variables */ /* * Run-time data structures. */ /* * Icode consists of operators and arguments. Operators are small integers, * while arguments may be pointers. To conserve space in icode files on * computers with 16-bit ints, icode is written by the linker as a mixture * of ints and words (longs). When an icode file is read in and processed * by the interpreter, it looks like a C array of mixed ints and words. * Accessing this "nonstandard" structure is handled by a union of int and * word pointers and incrementing is done by incrementing the appropriate * member of the union (see the interpreter). This is a rather dubious * method and certainly not portable. A better way might be to address * icode with a char *, but the incrementing code might be inefficient * (at a place that experiences a lot of execution activity). * * For the moment, the dubious coding is isolated under control of the * size of integers. */ #if IntBits == 16 typedef union { int *op; word *opnd; } inst; #else /* IntBits == 16 */ typedef union { word *op; word *opnd; } inst; #endif /* IntBits == 16 */ /* * Descriptor */ struct descrip { /* descriptor */ word dword; /* type field */ union { word integr; /* integer value */ char *sptr; /* pointer to character string */ union block *bptr; /* pointer to a block */ dptr descptr; /* pointer to a descriptor */ } vword; }; struct sdescrip { word length; /* length of string */ char *string; /* pointer to string */ }; /* * Run-time error numbers and text. */ struct errtab { int err_no; /* error number */ char *errmsg; /* error message */ }; /* * Frame markers */ struct ef_marker { /* expression frame marker */ inst ef_failure; /* failure ipc */ struct ef_marker *ef_efp; /* efp */ struct gf_marker *ef_gfp; /* gfp */ word ef_ilevel; /* ilevel */ }; struct pf_marker { /* procedure frame marker */ word pf_nargs; /* number of arguments */ struct pf_marker *pf_pfp; /* saved pfp */ struct ef_marker *pf_efp; /* saved efp */ struct gf_marker *pf_gfp; /* saved gfp */ dptr pf_argp; /* saved argp */ inst pf_ipc; /* saved ipc */ word pf_ilevel; /* saved ilevel */ dptr pf_scan; /* saved scanning environment */ struct descrip pf_locals[1]; /* descriptors for locals */ }; struct gf_marker { /* generator frame marker */ word gf_gentype; /* type */ struct ef_marker *gf_efp; /* efp */ struct gf_marker *gf_gfp; /* gfp */ inst gf_ipc; /* ipc */ struct pf_marker *gf_pfp; /* pfp */ dptr gf_argp; /* argp */ }; /* * Generator frame marker dummy -- used only for sizing "small" * generator frames where procedure infomation need not be saved. * The first five members here *must* be identical to those for * gf_marker. */ struct gf_smallmarker { /* generator frame marker */ word gf_gentype; /* type */ struct ef_marker *gf_efp; /* efp */ struct gf_marker *gf_gfp; /* gfp */ inst gf_ipc; /* ipc */ }; #ifdef LargeInts typedef unsigned int DIGIT; struct b_bignum { /* large integer block */ word title; /* T_Bignum */ word blksize; /* block size */ word msd, lsd; /* most and least significant digits */ int sign; /* sign; 0 positive, 1 negative */ DIGIT digits[1]; /* digits */ }; #endif /* LargeInts */ struct b_real { /* real block */ word title; /* T_Real */ double realval; /* value */ }; struct b_cset { /* cset block */ word title; /* T_Cset */ word size; /* size of cset */ int bits[CsetSize]; /* array of bits */ }; struct b_file { /* file block */ word title; /* T_File */ FILE *fd; /* Unix file descriptor */ word status; /* file status */ struct descrip fname; /* file name (string qualifier) */ }; struct b_proc { /* procedure block */ word title; /* T_Proc */ word blksize; /* size of block */ union { /* entry points for */ int (*ccode)(); /* C routines */ uword ioff; /* and icode as offset */ pointer icode; /* and icode as absolute pointer */ } entryp; word nparam; /* number of parameters */ word ndynam; /* number of dynamic locals */ word nstatic; /* number of static locals */ word fstatic; /* index (in global table) of first static */ struct descrip pname; /* procedure name (string qualifier) */ struct descrip lnames[1]; /* list of local names (qualifiers) */ }; /* * b_iproc blocks are used to statically initialize information about * functions. They are identical to b_proc blocks except for * the pname field which is a sdecrip (simple/string descriptor) instead * of a descrip. This is done because unions cannot be initialized. */ struct b_iproc { /* procedure block */ word ip_title; /* T_Proc */ word ip_blksize; /* size of block */ int (*ip_entryp)(); /* entry point (code) */ word ip_nparam; /* number of parameters */ word ip_ndynam; /* number of dynamic locals */ word ip_nstatic; /* number of static locals */ word ip_fstatic; /* index (in global table) of first static */ struct sdescrip ip_pname; /* procedure name (string qualifier) */ struct descrip ip_lnames[1]; /* list of local names (qualifiers) */ }; struct b_list { /* list-header block */ word title; /* T_List */ word size; /* current list size */ word id; /* identification number */ union block *listhead; /* pointer to first list-element block */ union block *listtail; /* pointer to last list-element block */ }; struct b_lelem { /* list-element block */ word title; /* T_Lelem */ word blksize; /* size of block */ union block *listprev; /* previous list-element block */ union block *listnext; /* next list-element block */ word nslots; /* total number of slots */ word first; /* index of first used slot */ word nused; /* number of used slots */ struct descrip lslots[1]; /* array of slots */ }; struct b_slots { /* set/table hash slots */ word title; /* T_Slots */ word blksize; /* size of block */ union block *hslots[HSlots]; /* array of slots (HSlots * 2^n entries) */ }; struct b_table { /* table-header block */ word title; /* T_Table */ word size; /* current table size */ word id; /* identification number */ word mask; /* mask to get slot num, equals n slots - 1 */ struct b_slots *hdir[HSegs]; /* directory of hash slot segments */ struct descrip defvalue; /* default table element value */ }; struct b_telem { /* table-element block */ word title; /* T_Telem */ union block *clink; /* hash chain link */ uword hashnum; /* for ordering chain */ struct descrip tref; /* entry value */ struct descrip tval; /* assigned value */ }; /* * A set header must be a proper prefix of a table header, * and a set element must be a proper prefix of a table element. */ struct b_set { /* set-header block */ word title; /* T_Set */ word size; /* size of the set */ word id; /* identification number */ word mask; /* mask to get slot num, equals n slots - 1 */ struct b_slots *hdir[HSegs]; /* directory of hash slot segments */ }; struct b_selem { /* set-element block */ word title; /* T_Selem */ union block *clink; /* hash chain link */ uword hashnum; /* hash number */ struct descrip setmem; /* the element */ }; struct b_record { /* record block */ word title; /* T_Record */ word blksize; /* size of block */ word id; /* identification number */ union block *recdesc; /* pointer to record constructor */ struct descrip fields[1]; /* fields */ }; /* * Alternate uses for procedure block fields, applied to records. */ #define nfields nparam /* number of fields */ #define recnum nstatic /* record number */ #define recid fstatic /* record serial number */ #define recname pname /* record name */ struct b_tvkywd { /* keyword trapped variable block */ word title; /* T_Tvkywd */ int (*putval)(); /* assignment function for keyword */ struct descrip kyval; /* keyword value */ struct descrip kyname; /* keyword name */ }; struct b_tvsubs { /* substring trapped variable block */ word title; /* T_Tvsubs */ word sslen; /* length of substring */ word sspos; /* position of substring */ struct descrip ssvar; /* variable that substring is from */ }; struct b_tvtbl { /* table element trapped variable block */ word title; /* T_Tvtbl */ union block *clink; /* pointer to table header block */ uword hashnum; /* hash number */ struct descrip tref; /* entry value */ struct descrip tval; /* reserved for assigned value */ }; struct b_coexpr { /* co-expression stack block */ word title; /* T_Coexpr */ word size; /* number of results produced */ word id; /* identification number */ struct b_coexpr *nextstk; /* pointer to next allocated stack */ struct pf_marker *es_pfp; /* current pfp */ struct ef_marker *es_efp; /* efp */ struct gf_marker *es_gfp; /* gfp */ dptr es_argp; /* argp */ inst es_ipc; /* ipc */ word es_ilevel; /* interpreter level */ word *es_sp; /* sp */ dptr tvalloc; /* where to place transmitted value */ struct descrip freshblk; /* refresh block pointer */ struct astkblk *es_actstk; /* pointer to activation stack structure */ word cstate[CStateSize]; /* C state information */ }; struct astkblk { /* co-expression activator-stack block */ int nactivators; /* number of valid activator entries in * this block */ struct astkblk *astk_nxt; /* next activator block */ struct actrec { /* activator record */ word acount; /* number of calls by this activator */ struct b_coexpr *activator; /* the activator itself */ } arec[ActStkBlkEnts]; }; struct b_refresh { /* co-expression block */ word title; /* T_Refresh */ word blksize; /* size of block */ word *ep; /* entry point */ word numlocals; /* number of locals */ struct pf_marker pfmkr; /* marker for enclosing procedure */ struct descrip elems[1]; /* arguments and locals, including Arg0 */ }; struct b_external { /* external block */ word title; /* T_External */ word blksize; /* size of block */ word descoff; /* offset to first descriptor */ word exdata[1]; /* words of external data */ }; union block { /* general block */ #ifdef LargeInts struct b_bignum bignumblk; #endif /* LargeInts */ struct b_real realblk; struct b_cset cset; struct b_file file; struct b_proc proc; struct b_list list; struct b_lelem lelem; struct b_table table; struct b_telem telem; struct b_set set; struct b_selem selem; struct b_record record; struct b_tvkywd tvkywd; struct b_tvsubs tvsubs; struct b_tvtbl tvtbl; struct b_refresh refresh; struct b_coexpr coexpr; struct b_external externl; struct b_slots slots; }; /* * Declarations for entries in tables associating icode location with * source program location. */ struct ipc_fname { word ipc; /* offset of instruction into code region */ word fname; /* offset of file name into string region */ }; struct ipc_line { word ipc; /* offset of instruction into code region */ int line; /* line number */ }; /* * External declarations. */ extern char *code; /* start of icode */ extern word stksize; /* size of co-expression stacks in words */ extern word *stackend; /* end of evaluation stack */ extern struct b_coexpr *stklist;/* base of co-expression stack list */ extern word mstksize; /* size of main stack in words */ extern char *statbase; /* start of static space */ extern char *statend; /* end of static space */ extern char *statfree; /* static space free list header */ extern word statsize; /* size of static space */ extern word statincr; /* size of increment for static space */ extern word ssize; /* size of string space (bytes) */ extern char *strbase; /* start of string space */ extern char *strend; /* end of string space */ extern char *strfree; /* string space free pointer */ extern word abrsize; /* size of allocated block region (words) */ extern char *blkbase; /* base of allocated block region */ extern char *blkend; /* maximum address in allocated block region */ extern char *blkfree; /* first free location in allocated block region */ extern int bsizes[]; /* sizes of blocks */ extern int firstd[]; /* offset (words) of first descrip. */ extern char *blkname[]; /* print names for block types. */ extern uword segsize[]; /* size of hash bucket segment */ extern struct b_tvkywd tvky_err; /* trapped variable for &error */ extern struct b_tvkywd tvky_pos; /* trapped variable for &pos */ extern struct b_tvkywd tvky_ran; /* trapped variable for &random */ extern struct b_tvkywd tvky_sub; /* trapped variable for &subject */ extern struct b_tvkywd tvky_trc; /* trapped variable for &trace */ #define k_error tvky_err.kyval.vword.integr /* value of &error */ #define k_pos tvky_pos.kyval.vword.integr /* value of &pos */ #define k_random tvky_ran.kyval.vword.integr /* value of &random */ #define k_subject tvky_sub.kyval /* value of &subject */ #define k_trace tvky_trc.kyval.vword.integr /* value of &trace */ extern struct b_cset k_ascii; /* value of &ascii */ extern struct b_cset k_cset; /* value of &cset */ extern struct b_cset k_digits; /* value of &lcase */ extern struct b_file k_errout; /* value of &errout */ extern struct b_file k_input; /* value of &input */ extern struct b_cset k_lcase; /* value of &lcase */ extern struct b_cset k_letters; /* value of &letters */ extern int k_level; /* value of &level */ extern char *k_errortext; /* value of &errortext */ extern int k_errornumber; /* value of &errornumber */ extern struct descrip k_errorvalue; /* value of &errorvalue */ extern struct descrip k_main; /* value of &main */ extern struct descrip k_current; /* ¤t */ extern struct b_file k_output; /* value of &output */ extern struct b_cset k_ucase; /* value of &ucase */ #ifdef StandardLib extern clock_t starttime; /* start time in milliseconds */ #else /* StandardLib */ extern long starttime; /* start time in milliseconds */ #endif /* StandardLib */ extern struct descrip nulldesc; /* null value */ extern struct descrip zerodesc; /* zero */ extern struct descrip onedesc; /* one */ extern struct descrip emptystr; /* empty string */ extern struct descrip blank; /* blank */ extern struct descrip letr; /* letter "r" */ extern struct descrip maps2; /* second argument to map() */ extern struct descrip maps3; /* third argument to map() */ extern struct descrip input; /* &input */ extern struct descrip errout; /* &errout */ extern struct descrip lcase; /* lowercase string */ extern struct descrip ucase; /* uppercase string */ extern int ntended; /* number of active tended descriptors */ extern struct descrip tended[]; /* tended descriptors */ extern word *sp; /* interpreter stack pointer */ extern word *stack; /* interpreter stack base */ extern struct pf_marker *pfp; /* procedure frame pointer */ extern struct ef_marker *efp; /* expression frame pointer */ extern struct gf_marker *gfp; /* generator frame pointer */ extern inst ipc; /* interpreter program counter */ extern dptr argp; /* argument pointer */ extern int ilevel; /* interpreter level */ #ifdef ExecImages extern int dumped; /* the interpreter has been dumped */ #endif /* ExecImages */ #if EBCDIC == 2 extern char ToEBCDIC[], FromEBCDIC[]; /* ASCII<->EBCDIC maps */ #define ToAscii(e) (FromEBCDIC[e]) #define FromAscii(e) (ToEBCDIC[e]) #else /* EBCDIC == 2 */ #define ToAscii(e) (e) #define FromAscii(e) (e) #endif /* EBCDIC == 2 */ /* * Evaluation stack overflow margin */ #define PerilDelta 100 /* * Macro definitions related to descriptors. */ /* * The following code is operating-system dependent [@rt.01]. Define * PushAval for computers that store longs and pointers differently. */ #if PORT #define PushAVal(x) PushVal(x) Deliberate Syntax Error #endif /* PORT */ #if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || MVS || UNIX || VM || VMS #define PushAVal(x) PushVal(x) #endif /* AMIGA || ATARI_ST || HIGHC_386 ... */ #if MSDOS || OS2 static union { pointer stkadr; word stkint; } stkword; #define PushAVal(x) {sp++; \ stkword.stkadr = (char *)(x); \ *sp = stkword.stkint;} #endif /* MSDOS || OS2 */ /* * End of operating-system specific code. */ /* * Pointer to block. */ #define BlkLoc(d) ((d).vword.bptr) /* * Check for null-valued descriptor. */ #define ChkNull(d) ((d).dword==D_Null) /* * Dereference descriptor. */ #define DeRef(d) (Var(d) ? deref(&d) : Success) /* * Check for equivalent descriptors. */ #define EqlDesc(d1,d2) ((d1).dword == (d2).dword && BlkLoc(d1) == BlkLoc(d2)) /* * Integer value. */ #define IntVal(d) ((d).vword.integr) /* * Offset from top of block to value of variable. */ #define Offset(d) ((d).dword & OffsetMask) /* * Check for pointer. */ #define Pointer(d) ((d).dword & F_Ptr) /* * Check for qualifier. */ #define Qual(d) (!((d).dword & F_Nqual)) /* * Length of string. */ #define StrLen(q) ((q).dword) /* * Location of first character of string. */ #define StrLoc(q) ((q).vword.sptr) /* * Check for trapped variable. */ #define Tvar(d) ((d).dword & F_Tvar) /* * Location of trapped-variable block. */ #define TvarLoc(d) ((d).vword.bptr) /* * Type of descriptor. */ #define Type(d) (int)((d).dword & TypeMask) /* * Check for variable. */ #define Var(d) ((d).dword & F_Var) /* * Location of the value of a variable. */ #define VarLoc(d) ((d).vword.descptr) /* * Important note: The code that follows is not strictly legal C. * It tests to see if pointer p2 is between p1 and p3. This may * involve the comparison of pointers in different arrays, which * is not well-defined. The casts of these pointers to unsigned "words" * (longs or ints, depending) works with all C compilers and architectures * on which Icon has been implemented. However, it is possible it will * not work on some system. If it doesn't, there may be a "false * positive" test, which is likely to cause a memory violation or a * loop. It is not practical to implement Icon on a system on which this * happens. */ #define InRange(p1,p2,p3) ((uword)(p2) >= (uword)(p1) && (uword)(p2) < (uword)(p3)) /* * Macros for pushing values on the interpreter stack. */ /* * Push descriptor. */ #define PushDesc(d) {*++sp = ((d).dword); sp++;*sp =((d).vword.integr);} /* * Push null-valued descriptor. */ #define PushNull {*++sp = D_Null; sp++; *sp = 0;} /* * Push word. */ #define PushVal(v) {*++sp = (word)(v);} /* * Macros related to function and operator definition. */ /* * Procedure block for a function. */ #define FncBlock(f,nargs,deref) \ struct b_iproc Cat(B,f) = {\ T_Proc,\ Vsizeof(struct b_proc),\ Cat(X,f),\ nargs,\ -1,\ deref, 0,\ {sizeof(Lit(f))-1,Lit(f)}}; /* * Function declaration for variable number of arguments. */ #define FncDcl(nm,n) FncBlock(nm,n,0) Cat(X,nm)(cargp) register dptr cargp; /* * Function declaration for variable number of arguments. */ #define FncDclV(nm) FncBlock(nm,-1,0) Cat(X,nm)(nargs,cargp) register dptr cargp; /* * Function declaration without dereferenced arguments. */ #define FncNDcl(nm,n) FncBlock(nm,n,-1) Cat(X,nm)(cargp) register dptr cargp; /* * Function declaration for variable number of arguments. */ #define FncNDclV(nm) FncBlock(nm,-1,-1) Cat(X,nm)(nargs,cargp) register dptr cargp; /* * Declaration for library routine. */ #define LibDcl(nm,n,pn) OpBlock(nm,n,pn,0) Cat(O,nm)(nargs,cargp) \ register dptr cargp; /* * Procedure block for an operator. */ #define OpBlock(f,nargs,sname,realargs)\ struct b_iproc Cat(B,f) = {\ T_Proc,\ Vsizeof(struct b_proc),\ Cat(O,f),\ nargs,\ -1,\ realargs,\ 0,\ {sizeof(sname)-1,sname}}; /* * Operator declaration. */ #define OpDcl(nm,n,pn) OpBlock(nm,n,pn,0) Cat(O,nm)(cargp) register dptr cargp; /* * Agent routine declaration. */ #define AgtDcl(nm) Cat(A,nm)(cargp) register dptr cargp; #ifdef StrInvoke /* * Structure for mapping string names of procedures to block addresses. */ struct pstrnm { char *pstrep; struct b_proc *pblock; }; #endif /* StrInvoke */ /* * Character translations. */ #if EBCDIC == 2 extern char ToEBCDIC[], FromEBCDIC[]; /* ASCII<->EBCDIC maps */ #define ToAscii(e) (FromEBCDIC[e]) #define FromAscii(e) (ToEBCDIC[e]) #else /* EBCDIC == 2 */ #define ToAscii(e) (e) #define FromAscii(e) (e) #endif /* EBCDIC == 2 */ /* * Macros to access Icon arguments in C functions. */ /* * n-th argument. */ #define Arg(n) (cargp[n]) /* * Type field of n-th argument. */ #define ArgType(n) (cargp[n].dword) /* * Value field of n-th argument. */ #define ArgVal(n) (cargp[n].vword.integr) /* * Specific arguments. */ #define Arg0 (cargp[0]) #define Arg1 (cargp[1]) #define Arg2 (cargp[2]) #define Arg3 (cargp[3]) #define Arg4 (cargp[4]) #define Arg5 (cargp[5]) #define Arg6 (cargp[6]) /* * Code expansions for exits from C code for top-level routines. */ #define Fail return A_Failure #define Return return A_Return #define Suspend { \ int rc; \ if ((rc = interp(G_Csusp,cargp)) != A_Resumption) \ return rc;} #define Forward(agent) return Cat(A,agent)(cargp) /* * Miscellaneous macro definitions. */ /* * Error exit from non top-level routines. */ #define RetError(n,v) {\ k_errornumber = n;\ k_errortext = "";\ k_errorvalue = v;\ return Error;} /* * Get floating-point number from real block. */ #ifdef Double #define GetReal(dp,res) { \ word *rp, *rq; \ rp = (word *) &(res); \ rq = (word *) &(BlkLoc(*dp)->realblk.realval); \ *rp++ = *rq++; \ *rp = *rq;} #else /* Double */ #define GetReal(dp,res) res = BlkLoc(*dp)->realblk.realval #endif /* Double */ /* * Absolute value of x (word). */ #if SASC #define Abs(x) __builtin_abs(x) #else /* SASC */ #define Abs(x) (((x) < 0) ? (-(x)) : (x)) #endif /* SASC */ /* * Maximum of x and y. */ #define Max(x,y) ((x)>(y)?(x):(y)) #if SASC #undef Max #define Max(x,y) __builtin_max(x,y) #endif /* SASC */ /* * Minimum of x and y. */ #define Min(x,y) ((x)<(y)?(x):(y)) #if SASC #undef Min #define Min(x,y) __builtin_min(x,y) #endif /* SASC */ /* * Some C compilers take '\n' and '\r' to be the same, so the * following definitions are used. */ #if EBCDIC /* * Note that, in EBCDIC, "line feed" and "new line" are distinct * characters. Icon's use of "line feed" is really "new line" in * C terms. */ #define LineFeed '\n' /* if really "line feed", that's 37 */ #define CarriageReturn '\r' #else /* EBCDIC */ #define LineFeed 10 #define CarriageReturn 13 #endif /* EBCDIC */ /* * Construct an integer descriptor. */ #define MakeInt(i,dp) { \ (dp)->dword = D_Integer; \ IntVal(*dp) = (word)(i);} /* * Check whether a set or table needs resizing. */ #define SP(p) ((struct b_set *)p) #define TooCrowded(p) \ ((SP(p)->size > MaxHLoad*(SP(p)->mask+1)) && (SP(p)->hdir[HSegs-1] == NULL)) #define TooSparse(p) \ ((SP(p)->hdir[1] != NULL) && (SP(p)->size < MinHLoad*(SP(p)->mask+1))) /* * RunErr encapsulates a call to the function runerr, followed * by Fail. The idea is to avoid the problem of calling * runerr directly and forgetting that it may actually return. */ #define RunErr(n,dp) {\ runerr((int)n,dp);\ Fail;\ } /* * Vsizeof is for use with variable-sized (i.e., indefinite) * structures containing an array of descriptors declared of size 1 * to avoid compiler warnings associated with 0-sized arrays. */ #define Vsizeof(s) (sizeof(s) - sizeof(struct descrip)) /* * Offset in word of cset bit. */ #define CsetOff(b) ((b) & BitOffMask) /* * Address of word of cset bit. */ #define CsetPtr(b,c) ((c) + (((b)&0377) >> LogIntBits)) /* * Set bit b in cset c. */ #define Setb(b,c) (*CsetPtr(b,c) |= (01 << CsetOff(b))) /* * Test bit b in cset c. */ #define Testb(b,c) ((*CsetPtr(b,c) >> CsetOff(b)) & 01) /* * Handy sizeof macros: * * Wsizeof(x) -- Size of x in words. * Vwsizeof(x) -- Size of x in words, minus the size of a descriptor. Used * when structures have a potentially null list of descriptors * at their end. */ #define Wsizeof(x) ((sizeof(x) + sizeof(word) - 1) / sizeof(word)) #define Vwsizeof(x) ((sizeof(x) - sizeof(struct descrip) +sizeof(word) - 1)\ / sizeof(word)) /* * Definitions and declarations used for storage management. */ #define F_Mark 0100000 /* bit for marking blocks */ #define Static 1 /* collection is for static region */ #define Strings 2 /* collection is for strings */ #define Blocks 3 /* collection is for blocks */ /* * External definitions. */ extern char *currend; /* current end of memory region */ extern uword blkneed; /* stated need for block space */ extern uword strneed; /* stated need for string space */ extern uword statneed; extern dptr globals; /* start of global variables */ extern dptr eglobals; /* end of global variables */ extern dptr gnames; /* start of global variable names */ extern dptr egnames; /* end of global variable names */ extern dptr statics; /* start of static variables */ extern dptr estatics; /* end of static variables */ extern dptr *quallist; /* start of qualifier list */ extern word qualsize; /* * Get type of block pointed at by x. */ #define BlkType(x) (*(word *)x) /* * BlkSize(x) takes the block pointed to by x and if the size of * the block as indicated by bsizes[] is nonzero it returns the * indicated size; otherwise it returns the second word in the * block contains the size. */ #define BlkSize(x) (bsizes[*(word *)x & ~F_Mark] ? \ bsizes[*(word *)x & ~F_Mark] : *((word *)x + 1)) /* * If memory monitoring is not enabled, redefine function calls * to do nothing. */ #ifndef MemMon #define MMAlc(n,t) #define MMBGC(r) #define MMEGC() #define MMMark(b,t) #define MMShow(d,s) #define MMStat(a,l,c) #define MMStr(n) #define MMSMark(a,n) #endif /* MemMon */ #ifndef FixedRegions /* * Information used with Icon's allocation routines with expandable-regions * memory management. */ typedef int ALIGN; /* pick most stringent type for alignment */ union bhead { /* header of free block */ struct { union bhead *ptr; /* pointer to next free block */ uword bsize; /* free block size */ } s; ALIGN x; /* force block alignment */ }; typedef union bhead HEADER; #define NALLOC 64 /* units to request at one time */ #define FREEMAGIC 0x807F /* magic flag for free blocks (MemMon only) */ #endif /* FixedRegions */