summaryrefslogtreecommitdiff
path: root/new/data.c
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-03-27 19:04:43 -0400
committerJakob Kaivo <jkk@ung.org>2022-03-27 19:04:43 -0400
commit2797eda2e1d90e6de67cc5c2affe8f59a7d1dfef (patch)
treed159c13aa154cc07ad0fcf4eb7961aafb67481c1 /new/data.c
parenta96bb08fb1886b83802a3b7ed20421ee3a8ee0b0 (diff)
remove unused files
Diffstat (limited to 'new/data.c')
-rw-r--r--new/data.c1250
1 files changed, 0 insertions, 1250 deletions
diff --git a/new/data.c b/new/data.c
deleted file mode 100644
index c7463ac..0000000
--- a/new/data.c
+++ /dev/null
@@ -1,1250 +0,0 @@
-/* MIRANDA DATA REPRESENTATIONS */
-
-/**************************************************************************
- * Copyright (C) Research Software Limited 1985-90. All rights reserved. *
- * The Miranda system is distributed as free software under the terms in *
- * the file "COPYING" which is included in the distribution. *
- *------------------------------------------------------------------------*/
-
-#include "data.h"
-#include "big.h"
-#define INITSPACE 250000
-word SPACE=INITSPACE; /* false ceiling in heap to improve paging behaviour
- during compilation */
-extern word SPACELIMIT; /* see steer.c for default value */
- /* SPACELIMIT controls the size of the heap (i.e. the number of list
- cells available) - the minimum survivable number given the need to
- compile the prelude etc is probably about 6000 */
- /* Note: the size of a list cell is 2 ints + 1 char */
-#define BIGTOP (SPACELIMIT + ATOMLIMIT)
-word listp=ATOMLIMIT-1;
-word *hdspace,*tlspace;
-long long cellcount=0;
-long claims=0;
-long nogcs=0;
-extern word atgc; /* flag, set in steer.c */
-#define poschar(c) !(negchar((c)-1))
-#define negchar(c) (c&128)
- /* safest to test for -ve chars this way, since not all m/c's do sign
- extension - DT Jan 84 */
-
-trueheapsize()
-{ return(nogcs==0?listp-ATOMLIMIT+1:SPACE); }
-
-setupheap()
-{ hdspace=(word *)malloc(SPACELIMIT*sizeof(word));
- tlspace=(word *)malloc(SPACELIMIT*sizeof(word));
- hd=hdspace-ATOMLIMIT; tl=tlspace-ATOMLIMIT;
- if(SPACE>SPACELIMIT)SPACE=SPACELIMIT;
- tag=(char *)calloc(BIGTOP+1,sizeof(char));
- /* NB use calloc because it sets contents to zero */
- /* tag[TOP] must be zero and exists as a sentinel */
- if(hdspace==NULL||tlspace==NULL||tag==NULL)mallocfail("heap");
-}
-
-resetheap() /* warning - cannot do this dynamically, because both the
- compiler and the reducer hold onto absolute heap addresses
- during certain space consuming computations */
-{ if(SPACELIMIT<trueheapsize())
- fprintf(stderr,"impossible event in resetheap\n"),exit(1);
- hdspace=(word *)realloc((char *)hdspace,SPACELIMIT*sizeof(word));
- if(hdspace==NULL)mallocfail("heap");
- tlspace=(word *)realloc((char *)tlspace,SPACELIMIT*sizeof(word));
- if(tlspace==NULL)mallocfail("heap");
- hd=hdspace-ATOMLIMIT; tl=tlspace-ATOMLIMIT;
- tag=(char *)realloc(tag,BIGTOP+1);
- if(tag==NULL)mallocfail("heap");
- tag[BIGTOP]=0;
- if(SPACE>SPACELIMIT)SPACE=SPACELIMIT;
- if(SPACE<INITSPACE&&INITSPACE<=SPACELIMIT)SPACE=INITSPACE,tag[TOP]=0;
- /* tag[TOP] is always zero and exists as a sentinel */
-}
-
-mallocfail(x)
-char *x;
-{ fprintf(stderr,"panic: cannot find enough free space for %s\n",x);
- exit(1);
-}
-
-resetgcstats()
-{ cellcount= -claims;
- nogcs = 0;
- initclock();
-}
-
-make(t,x,y) /* creates a new cell with "tag" t, "hd" x and "tl" y */
-word t,x,y;
-{ while(poschar(tag[++listp]));
- /* find next cell with zero or negative tag (=unwanted) */
- if(listp==TOP)
- { if(SPACE!=SPACELIMIT)
- if(!compiling)SPACE=SPACELIMIT; else
- if(claims<=SPACE/4&&nogcs>1)
- { /* during compilation we raise false ceiling whenever residency
- reaches 75% on 2 successive gc's */
- static word wait=0;
- word sp=SPACE;
- if(wait)wait--; else
- SPACE+= SPACE/2,wait=2,
- SPACE=5000*(1+(SPACE-1)/5000); /* round upwards */
- if(SPACE>SPACELIMIT)SPACE=SPACELIMIT;
- if(atgc&&SPACE>sp)
- printf( "\n<<increase heap from %d to %d>>\n",sp,SPACE);
- }
- if(listp==TOP)
- {
-#if defined ORION105
- asm("savew6");
- gc();
- asm("restw6");
-#elif defined sparc
- asm("ta 0x03"); /* see /usr/include/sun4/trap.h */
- /* asm("ta ST_FLUSH_WINDOWS"); */
- gc();
-#else
- gc();
-#endif
- if(t>STRCONS)mark(x);
- if(t>=INT)mark(y);
- return(make(t,x,y)); }
- }
- claims++;
- tag[listp]= t;
- hd[listp]= x;
- tl[listp]= y;
- return(listp); }
-
-/* cons ap ap2 ap3 are all #defined in terms of make
- - see MIRANDA DECLARATIONS */
-
-setwd(x,a,b)
-word x,a,b;
-{ hd[x]= a;
- tl[x]= b; }
-
-word collecting=0; /* flag for reset(), in case interrupt strikes in gc */
-
-gc() /* the "garbage collector" */
-{ char *p1;
- extern word making;
- collecting=1;
- p1= &(tag[ATOMLIMIT]);
- if(atgc)
- printf("\n<<gc after %ld claims>>\n",claims);
- if(claims<=SPACE/10 && nogcs>1 && SPACE==SPACELIMIT)
- { /* if heap utilisation exceeds 90% on 2 successive gc's, give up */
- static word hnogcs=0;
- if(nogcs==hnogcs)
- { extern word ideep;
- extern char *current_script;
- fprintf(stderr,"<<not enough heap space -- task abandoned>>\n");
- if(!compiling)outstats();
- if(compiling&&ideep==0)
- fprintf(stderr,"not enough heap to compile current script\n"),
- fprintf(stderr,"script = \"%s\", heap = %d\n",current_script,SPACE);
- exit(1); } /* if compiling should reset() instead - FIX LATER */
- else hnogcs=nogcs+1; }
- nogcs++;
- while(*p1= -*p1)p1++; /* make all tags -ve (= unwanted) */
-/*if(atgc)
- { extern int lasthead;
-#define BACKSTOP 020000000000
- printf("bases() called\n");
- printf("lasthead= ");
- if(lasthead==BACKSTOP)printf("BACKSTOP");
- else out(stdout,lasthead);
- putchar('\n'); } /* DEBUG */
- bases();
-/*if(atgc)printf("bases() done\n"); /* DEBUG */
- listp= ATOMLIMIT - 1;
- cellcount+= claims;
- claims= 0;
- collecting=0;
-}
-/* int Icount; /* DEBUG */
-
-gcpatch() /* called when gc interrupted - see reset in steer.c */
-/* must not allocate any cells between calling this and next gc() */
-{ char *p1;
- for(p1= &(tag[ATOMLIMIT]);*p1;p1++)if(negchar(*p1))*p1= -*p1;
- /* otherwise mutator crashes on funny tags */
-}
-
-bases() /* marks everthing that must be saved */
-{ word *p;
- extern YYSTYPE yyval;
- extern word *cstack;
- extern word fileq,primenv;
- extern word cook_stdin,common_stdin,common_stdinb,rv_expr,rv_script;
- extern word margstack,vergstack,litstack,linostack,prefixstack;
- extern word idsused,suppressids,lastname,
- eprodnts,nonterminals,ntmap,ihlist,ntspecmap,gvars,lexvar;
- extern word R,TABSTRS,SGC,ND,SBND,NT,current_id,meta_pending;
- extern word showchain,newtyps,algshfns,errs,speclocs;
- extern word SUBST[],tvmap,localtvmap;
- extern word tfnum,tfbool,tfbool2,tfnum2,tfstrstr,
- tfnumnum,ltchar,bnf_t,tstep,tstepuntil;
- extern word exec_t,read_t,filestat_t;
- extern word big_one;
- extern word nill,standardout;
- extern word lexstates,lexdefs,oldfiles,includees,embargoes,exportfiles,
- exports,internals, freeids,tlost,detrop,rfl,bereaved,ld_stuff;
- extern word CLASHES,ALIASES,SUPPRESSED,TSUPPRESSED,DETROP,MISSING,fnts,FBS;
- extern word outfilq,waiting;
- /* Icount=0; /* DEBUG */
- p= (word *)&p;
-/* we follow everything on the C stack that looks like a pointer into
-list space. This is failsafe in that the worst that can happen,if e.g. a
-stray integer happens to point into list space, is that the garbage
-collector will collect less garbage than it could have done */
- if(p<cstack) /* which way does stack grow? */
- while(++p!=cstack)mark(*p);/* for machines with stack growing downwards */
- else
- while(--p!=cstack)mark(*p);/* for machines with stack growing upwards */
- mark(*cstack);
-/* now follow all pointer-containing external variables */
- mark(outfilq);
- mark(waiting);
- if(compiling||rv_expr||rv_script) /* rv flags indicate `readvals' in use */
- { extern YYSTYPE *yyvs, *yyvsp;
- extern word namebucket[];
- extern word *dstack,*stackp; /* undump stack - see load_script(), below */
- extern word *pnvec,nextpn,loading; /* private name vector */
- extern word make_status;
- word i;
- mark(make_status);
- mark(primenv);
- mark(fileq);
- mark(idsused);
- mark(eprodnts);
- mark(nonterminals);
- mark(ntmap);
- mark(ihlist);
- mark(ntspecmap);
- mark(gvars);
- mark(lexvar);
- mark(common_stdin);
- mark(common_stdinb);
- mark(cook_stdin);
- mark(margstack);
- mark(vergstack);
- mark(litstack);
- mark(linostack);
- mark(prefixstack);
- mark(files);
- mark(oldfiles);
- mark(includees);
- mark(freeids);
- mark(exports);
- mark(internals);
- mark(CLASHES);
- mark(ALIASES);
- mark(SUPPRESSED);
- mark(TSUPPRESSED);
- mark(DETROP);
- mark(MISSING);
- mark(FBS);
- mark(lexstates);
- mark(lexdefs);
- for(i=0;i<128;i++)
- if(namebucket[i])mark(namebucket[i]);
- for(p=dstack;p<stackp;p++)mark(*p);
- if(loading)
- { mark(algshfns);
- mark(speclocs);
- mark(exportfiles);
- mark(embargoes);
- mark(rfl);
- mark(detrop);
- mark(bereaved);
- mark(ld_stuff);
- mark(tlost);
- for(i=0;i<nextpn;i++)mark(pnvec[i]); }
- mark(lastname);
- mark(suppressids);
- mark(lastexp);
- mark(nill);
- mark(standardout);
- mark(big_one);
- mark(yyval);
-/* for(vp= yyvs;vp<=yyvsp;vp++)mark(*vp); */
- mark(yylval);
- mark(R);
- mark(TABSTRS);
- mark(SGC);
- mark(ND);
- mark(SBND);
- mark(NT);
- mark(current_id);
- mark(meta_pending);
- mark(newtyps);
- mark(showchain);
- mark(errs);
- mark(tfnum);
- mark(tfbool);
- mark(tfbool2);
- mark(tfnum2);
- mark(tfstrstr);
- mark(tfnumnum);
- mark(ltchar);
- mark(bnf_t);
- mark(exec_t);
- mark(read_t);
- mark(filestat_t);
- mark(tstep);
- mark(tstepuntil);
- mark(tvmap);
- mark(localtvmap);
- for(i=0;i<hashsize;i++)mark(SUBST[i]); }
-/* if(atgc)printf("<<%d I-nodes>>\n",Icount); /* DEBUG */
-}
-
-#define tlptrbits 030000000000
-/* see reduce.c */
-
-mark(x) /* a marked cell is distinguished by having a +ve "tag" */
-word x;
-{ x&= ~tlptrbits; /* x may be a `reversed pointer' (see reduce.c) */
- while(isptr(x)&&negchar(tag[x]))
- { /*if(hd[x]==I)Icount++; /* DEBUG */
- if((tag[x]= -tag[x])<INT)return;
- if(tag[x]>STRCONS)mark(hd[x]);
- x= tl[x]&~tlptrbits; }
-}
-
-union numparts {double real; struct{word left;word right;} parts;};
-
-double get_dbl(x)
-word x;
-{ union numparts r;
- r.parts.left= hd[x];
- r.parts.right= tl[x];
- return(r.real); }
-
-/* Miranda's arithmetic model requires fp overflow trapped. On sparc this
- can be done by setting a trap with ieee_handler (see steer.c) otherwise
- we test for overflow with finite(), see IEEE754-1985 (Appendix) */
-
-sto_dbl(R)
-double R;
-{ union numparts r;
-#if !defined sparc /* */
- if(!finite(R))fpe_error(); /* see note on arithmetic model above */
-#endif /* */
- r.real=R;
- return(make(DOUBLE,r.parts.left,r.parts.right));
-}
-
-setdbl(x,R)
-double R;
-{ union numparts r;
-#if !defined sparc /* */
- if(!finite(R))fpe_error(); /* see note on arithmetic model above */
-#endif /* */
- r.real=R;
- tag[x]=DOUBLE; hd[x]=r.parts.left; tl[x]=r.parts.right;
-}
-
-sto_char(c) /* assumes 0<=c<=UMAX */
-word c;
-{ return c<256?c:make(UNICODE,c,0); }
-
-get_char(x)
-word x;
-{ if(x<256)return x;
- if(tag[x]==UNICODE)return hd[x];
- fprintf(stderr,"impossible event in get_char(x), tag[x]==%d\n",tag[x]);
- exit(1);
-}
-
-is_char(x)
-word x;
-{ return 0<=x && x<256 || tag[x]==UNICODE; }
-
-sto_id(p1)
-char *p1;
-{ return(make(ID,cons(strcons(p1,NIL),undef_t),UNDEF)); }
- /* the hd of an ID contains cons(strcons(name,who),type) and
- the tl has the value */
- /* who is NIL, hereinfo, or cons(aka,hereinfo) where aka
- is of the form datapair(oldname,0) oldname being a string */
- /* hereinfo is fileinfo(script,line_no) */
-
-/* hereafter is stuff for dumping and undumping compiled scripts
-
- (internal heap object) (external file rep - char sequence)
- ---------------------- -----------------------------------
- 0..127 self
- 128..383 CHAR_X (self-128)
- 384..ATOMLIMIT-1 (self-256)
- integer (-127..127) SHORT_X <byte>
- integer INT_X <4n bytes> (-1)
- double DBL_X <8 bytes>
- unicode_char UNICODE_X <4 bytes>
- typevar TVAR_X <byte>
- ap(x,y) [x] [y] AP_X
- cons(x,y) [y] [x] CONS_X
- id (=occurrence) ID_X <string terminated by '\0'>
- pname (=occurrence) PN_X <2 bytes>
- PN1_X <4 bytes>
- datapair(string,0) AKA_X <string...\0>
- fileinfo(script,line_no) HERE_X <string...\0> <2 bytes> (**)
- constructor(n,x) [x] CONSTRUCT_X <2 bytes>
- readvals(h,t) [t] RV_X
- definition [val] [type] [who] [id] DEF_X
- [val] [pname] DEF_X
- definition-list [definition*] DEF_X
- filename <string terminated by '\0'>
- mtime <4 bytes>
-
- complete script XVERSION
- [ [filename]
- [mtime]
- [shareable] (=0 or 1)
- [definition-list] ]+
- '\0'
- [definition-list] (algshfns)
- [ND] or [True] (see below)
- DEF_X
- [SGC]
- DEF_X
- [freeids]
- DEF_X
- [definition-list] (internals)
-
- type-error script XVERSION
- '\1'
- <4 bytes> (=errline)
- ... (rest as normal script)
-
- syntax-error script XVERSION
- `\0'
- <4 bytes> (=errline)
- [ [filename]
- [mtime] ]+
-
- Notes
- -----
- first filename in dump must be that of `current_script' (ie the
- main source file). All pathnames in dump are correct wrt the
- directory of the main source.
- (**) empty string is abbreviation for current filename in hereinfo
- True in ND position indicates an otherwise correct dump whose exports
- include type orphans
-
- Pending:
- --------
- could have abbreviation for iterated ap and cons
-
- remaining issue - external format should be machine and version
- independent - not clear how to do this
-*/
-
-#define XBASE ATOMLIMIT-256
-#define CHAR_X (XBASE)
-#define SHORT_X (XBASE+1)
-#define INT_X (XBASE+2)
-#define DBL_X (XBASE+3)
-#define ID_X (XBASE+4)
-#define AKA_X (XBASE+5)
-#define HERE_X (XBASE+6)
-#define CONSTRUCT_X (XBASE+7)
-#define RV_X (XBASE+8)
-#define PN_X (XBASE+9)
-#define PN1_X (XBASE+10)
-#define DEF_X (XBASE+11)
-#define AP_X (XBASE+12)
-#define CONS_X (XBASE+13)
-#define TVAR_X (XBASE+14)
-#define UNICODE_X (XBASE+15)
-#define XLIMIT (XBASE+16)
-#if XLIMIT>512
-SEE ME!!! /* coding scheme breaks down if this occurs */
-#else
-
-static char prefix[pnlim];
-word preflen;
-
-setprefix(p) /* to that of pathname p */
-char *p;
-{ char *g;
- (void)strcpy(prefix,p);
- g=rindex(prefix,'/');
- if(g)g[1]='\0';
- else *prefix='\0';
- preflen = strlen(prefix);
-} /* before calling dump_script or load_script must setprefix() to that
- of current pathname of file being dumped/loaded - to get correct
- translation between internal pathnames (relative to dump script)
- and external pathnames */
-
-char *mkrel(p) /* makes pathname p correct relative to prefix */
-char *p; /* must use when writing pathnames to dump */
-{ if(strncmp(prefix,p,preflen)==0)return(p+preflen);
- if(p[0]=='/')return(p);
- fprintf(stderr,"impossible event in mkrelative\n"); /* or use getwd */
- /* not possible because all relative pathnames in files were computed
- wrt current script */
- return(p); /* proforma only */
-}
-
-#define bits_15 0177777
-char *CFN;
-
-dump_script(files,f) /* write compiled script files to file f */
-word files;
-FILE *f;
-{ extern word ND,bereaved,errline,algshfns,internals,freeids,SGC;
- putc(XVERSION,f); /* identifies dump format */
- if(files==NIL){ /* source contains syntax or metatype error */
- extern word oldfiles;
- word x;
- putc(0,f);
- putw(errline,f);
- for(x=oldfiles;x!=NIL;x=tl[x])
- fprintf(f,"%s",mkrel(get_fil(hd[x]))),putc(0,f),
- /*filename*/
- putw(fil_time(hd[x]),f); /* mtime */
- return; }
- if(ND!=NIL)putc(1,f),putw(errline,f);
- for(;files!=NIL;files=tl[files])
- { fprintf(f,"%s",mkrel(CFN=get_fil(hd[files]))); /* filename */
- putc(0,f);
- putw(fil_time(hd[files]),f);
- putc(fil_share(hd[files]),f);
- dump_defs(fil_defs(hd[files]),f);
- }
- putc(0,f); /* header - not a possible filename */
- dump_defs(algshfns,f);
- if(ND==NIL&&bereaved!=NIL)dump_ob(True,f); /* special flag */
- else dump_ob(ND,f);
- putc(DEF_X,f);
- dump_ob(SGC,f);
- putc(DEF_X,f);
- dump_ob(freeids,f);
- putc(DEF_X,f);
- dump_defs(internals,f);
-}
-
-dump_defs(defs,f) /* write list of defs to file f */
-word defs;
-FILE *f;
-{ while(defs!=NIL)
- if(tag[hd[defs]]==STRCONS) /* pname */
- { word v=get_pn(hd[defs]);
- dump_ob(pn_val(hd[defs]),f);
- if(v>bits_15)
- putc(PN1_X,f),
- putw(v,f);
- else
- putc(PN_X,f),
- putc(v&255,f),
- putc(v >> 8,f);
- putc(DEF_X,f);
- defs=tl[defs]; }
- else
- { dump_ob(id_val(hd[defs]),f);
- dump_ob(id_type(hd[defs]),f);
- dump_ob(id_who(hd[defs]),f);
- putc(ID_X,f);
- fprintf(f,"%s",(char *)get_id(hd[defs]));
- putc(0,f);
- putc(DEF_X,f);
- defs=tl[defs]; }
- putc(DEF_X,f); /* delimiter */
-}
-
-dump_ob(x,f) /* write combinatory expression x to file f */
-word x;
-FILE *f;
-{ /* printob("dumping: ",x); /* DEBUG */
- switch(tag[x])
- { case ATOM: if(x<128)putc(x,f); else
- if(x>=384)putc(x-256,f); else
- putc(CHAR_X,f),putc(x-128,f);
- return;
- case TVAR: putc(TVAR_X,f), putc(gettvar(x),f);
- if(gettvar(x)>255)
- fprintf(stderr,"panic, tvar too large\n");
- return;
- case INT: { /* 32 bit version (suppressed)
- int d=get_int(x);
- if(abs(d)<=127)
- { putc(SHORT_X,f); putc(d,f); return; }
- putc(INT_X,f);
- putw(d,f);
- /* variable length version */
- word d=digit(x);
- if(rest(x)==0&&(d&MAXDIGIT)<=127)
- { if(d&SIGNBIT)d= -(d&MAXDIGIT);
- putc(SHORT_X,f); putc(d,f); return; }
- putc(INT_X,f);
- putw(d,f);
- x=rest(x);
- while(x)
- putw(digit(x),f),x=rest(x);
- putw(-1,f);
- /* end of variable length version */
- return; }
- /* 4 bytes per digit wasteful at current value of IBASE */
- case DOUBLE: putc(DBL_X,f);
- putw(hd[x],f);
- putw(tl[x],f);
- return;
- case UNICODE: putc(UNICODE_X,f);
- putw(hd[x],f);
- return;
- case DATAPAIR: fprintf(f,"%c%s",AKA_X,(char *)hd[x]);
- putc(0,f);
- return;
- case FILEINFO: { word line=tl[x];
- if((char *)hd[x]==CFN)putc(HERE_X,f);
- else fprintf(f,"%c%s",HERE_X,mkrel(hd[x]));
- putc(0,f);
- putc(line&255,f);
- putc((line >>= 8)&255,f);
- if(line>255)fprintf(stderr,
- "impossible line number %d in dump_ob\n",tl[x]);
- return; }
- case CONSTRUCTOR: dump_ob(tl[x],f);
- putc(CONSTRUCT_X,f);
- putc(hd[x]&255,f);
- putc(hd[x]>>8,f);
- return;
- case STARTREADVALS: dump_ob(tl[x],f);
- putc(RV_X,f);
- return;
- case ID: fprintf(f,"%c%s",ID_X,get_id(x));
- putc(0,f);
- return;
- case STRCONS: { word v=get_pn(x); /* private name */
- if(v>bits_15)
- putc(PN1_X,f),
- putw(v,f);
- else
- putc(PN_X,f),
- putc(v&255,f),
- putc(v >> 8,f);
- return; }
- case AP: dump_ob(hd[x],f);
- dump_ob(tl[x],f);
- putc(AP_X,f);
- return;
- case CONS: dump_ob(tl[x],f);
- dump_ob(hd[x],f);
- putc(CONS_X,f);
- return;
- default: fprintf(stderr,"impossible tag %d in dump_ob\n",tag[x]);
- }
-}
-
-#define ovflocheck if(dicq-dic>DICSPACE)dicovflo()
-extern char *dic; extern word DICSPACE;
-
-word BAD_DUMP=0,CLASHES=NIL,ALIASES=NIL,PNBASE=0,SUPPRESSED=NIL,
- TSUPPRESSED=NIL,TORPHANS=0;
-
-load_script(f,src,aliases,params,main)
- /* loads a compiled script from file f for source src */
- /* main=1 if is being loaded as main script, 0 otherwise */
-FILE *f;
-char *src;
-word aliases,params,main;
-{ extern word nextpn,ND,errline,algshfns,internals,freeids,includees,SGC;
- extern char *dicp, *dicq;
- word ch,files=NIL;
- TORPHANS=BAD_DUMP=0;
- CLASHES=NIL;
- dsetup();
- setprefix(src);
- if(getc(f)!=XVERSION){ BAD_DUMP= -1; return(NIL); }
- if(aliases!=NIL)
- { /* for each `old' install diversion to `new' */
- /* if alias is of form -old `new' is a pname */
- word a,hold;
- ALIASES=aliases;
- for(a=aliases;a!=NIL;a=tl[a])
- { word old=tl[hd[a]],new=hd[hd[a]];
- hold=cons(id_who(old),cons(id_type(old),id_val(old)));
- id_type(old)=alias_t;
- id_val(old)=new;
- if(tag[new]==ID)
- if((id_type(new)!=undef_t||id_val(new)!=UNDEF)
- &&id_type(new)!=alias_t)
- CLASHES=add1(new,CLASHES);
- hd[hd[a]]=hold;
- }
- if(CLASHES!=NIL){ BAD_DUMP= -2; unscramble(aliases); return(NIL); }
- for(a=aliases;a!=NIL;a=tl[a]) /* FIX1 */
- if(tag[ch=id_val(tl[hd[a]])]==ID) /* FIX1 */
- if(id_type(ch)!=alias_t) /* FIX1 */
- id_type(ch)=new_t; /* FIX1 */
- }
- PNBASE=nextpn; /* base for relocation of internal names in dump */
- SUPPRESSED=NIL; /* list of `-id' aliases successfully obeyed */
- TSUPPRESSED=NIL; /* list of -typename aliases (illegal just now) */
- while((ch=getc(f))!=0&&ch!=EOF&&!BAD_DUMP)
- { word s,holde=0;
- dicq=dicp;
- if(files==NIL&&ch==1) /* type error script */
- { holde=getw(f),ch=getc(f);
- if(main)errline=holde; }
- if(ch!='/')(void)strcpy(dicp,prefix),dicq+=preflen;
- /* locate wrt current posn */
- *dicq++ = ch;
- while((*dicq++ =ch=getc(f))&&ch!=EOF); /* filename */
- ovflocheck;
- ch=getw(f); /* mtime */
- s=getc(f); /* share bit */
- /*printf("loading: %s(%d)\n",dicp,ch); /* DEBUG */
- if(files==NIL) /* is this the right dump? */
- if(strcmp(dicp,src))
- { BAD_DUMP=1;
- if(aliases!=NIL)unscramble(aliases);
- return(NIL); }
- CFN=get_id(name()); /* wasteful way to share filename */
- files = cons(make_fil(CFN,ch,s,load_defs(f)),
- files);
- }
-/* warning: load_defs side effects id's in namebuckets, cannot be undone by
-unload until attached to global `files', so interrupts are disabled during
-load_script - see steer.c */ /* for big dumps this may be too coarse - FIX */
- if(ch==EOF||BAD_DUMP){ if(!BAD_DUMP)BAD_DUMP=2;
- if(aliases!=NIL)unscramble(aliases);
- return(files); }
- if(files==NIL){ /* dump of syntax error state */
- extern word oldfiles;
- ch=getw(f);
- if(main)errline=ch;
- while((ch=getc(f))!=EOF)
- { dicq=dicp;
- if(ch!='/')(void)strcpy(dicp,prefix),dicq+=preflen;
- /* locate wrt current posn */
- *dicq++ = ch;
- while((*dicq++ =ch=getc(f))&&ch!=EOF); /* filename */
- ovflocheck;
- ch=getw(f); /* mtime */
- if(oldfiles==NIL) /* is this the right dump? */
- if(strcmp(dicp,src))
- { BAD_DUMP=1;
- if(aliases!=NIL)unscramble(aliases);
- return(NIL); }
- oldfiles = cons(make_fil(get_id(name()),ch,0,NIL),
- oldfiles);
- }
- if(aliases!=NIL)unscramble(aliases);
- return(NIL); }
- algshfns=append1(algshfns,load_defs(f));
- ND=load_defs(f);
- if(ND==True)ND=NIL,TORPHANS=1;
- SGC=append1(SGC,load_defs(f));
- if(main||includees==NIL)freeids=load_defs(f);
- else bindparams(load_defs(f),hdsort(params));
- if(aliases!=NIL)unscramble(aliases);
- if(main)internals=load_defs(f);
- return(reverse(files));
-}/* was it necessary to unscramble aliases before error returns?
- check this later */
-/* actions labelled FIX1 were inserted to deal with the pathological case
- that the destination of an alias (not part of a cyclic alias) has a direct
- definition in the file and the aliasee is missing from the file
- - this is both nameclash and missing aliasee, but without fix the two
- errors cancel each other out and are unreported */
-
-word DETROP=NIL,MISSING=NIL;
-
-bindparams(formal,actual) /* process bindings of free ids */
-/* formal is list of cons(id,cons(original_name,type)) */
-/* actual is list of cons(name,value) | ap(name,typevalue)) */
-/* both in alpha order of original name */
-word formal,actual;
-{ extern word FBS; word badkind=NIL;
- DETROP=MISSING=NIL;
- FBS=cons(formal,FBS);
- /* FBS is list of list of formals bound in current script */
- for(;;)
- { word a; char *f;
- while(formal!=NIL && (actual==NIL ||
- strcmp((f=(char *)hd[hd[tl[hd[formal]]]]),get_id(a=hd[hd[actual]]))<0))
- /* the_val(hd[hd[formal]])=findid((char *)hd[hd[tl[hd[formal]]]]),
- above line picks up identifier of that name in current scope */
- MISSING=cons(hd[tl[hd[formal]]],MISSING),
- formal=tl[formal];
- if(actual==NIL)break;
- if(formal==NIL||strcmp(f,get_id(a)))DETROP=cons(a,DETROP);
- else { word fa=tl[tl[hd[formal]]]==type_t?t_arity(hd[hd[formal]]):-1;
- word ta=tag[hd[actual]]==AP?t_arity(hd[actual]):-1;
- if(fa!=ta)
- badkind=cons(cons(hd[hd[actual]],datapair(fa,ta)),badkind);
- the_val(hd[hd[formal]])=tl[hd[actual]];
- formal=tl[formal]; }
- actual=tl[actual];
- }
-for(;badkind!=NIL;badkind=tl[badkind])
- DETROP=cons(hd[badkind],DETROP);
-}
-
-unscramble(aliases) /* remove old to new diversions installed above */
-word aliases;
-{ word a=NIL;
- for(;aliases!=NIL;aliases=tl[aliases])
- { word old=tl[hd[aliases]],hold=hd[hd[aliases]];
- word new=id_val(old);
- hd[hd[aliases]]=new; /* put back for missing check, see below */
- id_who(old)=hd[hold]; hold=tl[hold];
- id_type(old)=hd[hold];
- id_val(old)=tl[hold]; }
- for(;ALIASES!=NIL;ALIASES=tl[ALIASES])
- { word new=hd[hd[ALIASES]];
- word old=tl[hd[ALIASES]];
- if(tag[new]!=ID)
- { if(!member(SUPPRESSED,new))a=cons(old,a);
- continue; } /* aka stuff irrelevant to pnames */
- if(id_type(new)==new_t)id_type(new)=undef_t; /* FIX1 */
- if(id_type(new)==undef_t)a=cons(old,a); else
- if(!member(CLASHES,new))
- /* install aka info in new */
- if(tag[id_who(new)]!=CONS)
- id_who(new)=cons(datapair(get_id(old),0),id_who(new)); }
- ALIASES=a; /* transmits info about missing aliasees */
-}
-
-char *getaka(x) /* returns original name of x (as a string) */
-word x;
-{ word y=id_who(x);
- return(tag[y]!=CONS?get_id(x):(char *)hd[hd[y]]);
-}
-
-get_here(x) /* here info for id x */
-word x;
-{ word y=id_who(x);
- return(tag[y]==CONS?tl[y]:y);
-}
-
-word *dstack=0,*stackp,*dlim;
-/* stackp=dstack; /* if load_script made interruptible, add to reset */
-
-dsetup()
-{ if(!dstack)
- { dstack=(word *)malloc(1000*sizeof(word));
- if(dstack==NULL)mallocfail("dstack");
- dlim=dstack+1000; }
- stackp=dstack;
-}
-
-dgrow()
-{ word *hold=dstack;
- dstack=(word *)realloc(dstack,2*(dlim-dstack)*sizeof(word));
- if(dstack==NULL)mallocfail("dstack");
- dlim=dstack+2*(dlim-hold);
- stackp += dstack-hold;
- /*printf("dsize=%d\n",dlim-dstack); /* DEBUG */
-}
-
-load_defs(f) /* load a sequence of definitions from file f, terminated
- by DEF_X, or a single object terminated by DEF_X */
-FILE *f;
-{ extern char *dicp, *dicq;
- extern word *pnvec,common_stdin,common_stdinb,nextpn,rv_script;
- word ch,defs=NIL;
- while((ch=getc(f))!=EOF)
- { if(stackp==dlim)dgrow();
- switch(ch)
- { case CHAR_X: *stackp++ = getc(f)+128;
- continue;
- case TVAR_X: *stackp++ = mktvar(getc(f));
- continue;
- case SHORT_X: ch = getc(f);
- if(ch&128)ch= ch|(~127); /*force a sign extension*/
- *stackp++ = stosmallint(ch);
- continue;
- case INT_X: { word *x;
- ch = getw(f);
- *stackp++ = make(INT,ch,0);
- /* for 32 bit version suppress to end of varpart */
- x = &rest(stackp[-1]);
- ch = getw(f);
- while(ch!= -1)
- *x=make(INT,ch,0),ch=getw(f),x= &rest(*x);
- /* end of variable length part */
- continue; }
- case DBL_X: ch=getw(f);
- *stackp++ = make(DOUBLE,ch,getw(f));
- continue;
- case UNICODE_X: *stackp++ = make(UNICODE,getw(f),0);
- continue;
- case PN_X: ch = getc(f);
- ch = PNBASE+(ch|(getc(f)<<8));
- *stackp++ = ch<nextpn?pnvec[ch]:sto_pn(ch);
- /* efficiency hack for *stackp++ = sto_pn(ch); */
- continue;
- case PN1_X: ch=PNBASE+getw(f);
- *stackp++ = ch<nextpn?pnvec[ch]:sto_pn(ch);
- /* efficiency hack for *stackp++ = sto_pn(ch); */
- continue;
- case CONSTRUCT_X: ch = getc(f);
- ch = ch|(getc(f)<<8);
- stackp[-1] = constructor(ch,stackp[-1]);
- continue;
- case RV_X: stackp[-1] = readvals(0,stackp[-1]);
- rv_script=1;
- continue;
- case ID_X: dicq=dicp;
- while((*dicq++ =ch=getc(f))&&ch!=EOF);
- ovflocheck;
- *stackp++=name(); /* see lex.c */
- if(id_type(stackp[-1])==new_t) /* FIX1 (& next 2 lines) */
- CLASHES=add1(stackp[-1],CLASHES),stackp[-1]=NIL;
- else
- if(id_type(stackp[-1])==alias_t) /* follow alias */
- stackp[-1]=id_val(stackp[-1]);
- continue;
- case AKA_X: dicq=dicp;
- while((*dicq++ =ch=getc(f))&&ch!=EOF);
- ovflocheck;
- *stackp++=datapair(get_id(name()),0);
- /* wasteful, to share string */
- continue;
- case HERE_X: dicq=dicp;
- ch=getc(f);
- if(!ch){ /* coding hack, 0 means current file name */
- ch = getc(f);
- ch = ch|getc(f)<<8;
- *stackp++ = fileinfo(CFN,ch);
- continue; }
- /* next line locates wrt current posn */
- if(ch!='/')(void)strcpy(dicp,prefix),dicq+=preflen;
- *dicq++ = ch;
- while((*dicq++ =ch=getc(f))&&ch!=EOF);
- ovflocheck;
- ch = getc(f);
- ch = ch|getc(f)<<8;
- *stackp++ = fileinfo(get_id(name()),ch); /* wasteful */
- continue;
- case DEF_X: switch(stackp-dstack){
- case 0: /* defs delimiter */
- { /*printlist("contents: ",defs); /* DEBUG */
- return(reverse(defs)); }
- case 1: /* ob delimiter */
- { return(*--stackp); }
- case 2: /* pname defn */
- { ch = *--stackp;
- pn_val(ch)= *--stackp;
- defs=cons(ch,defs); /* NB defs now includes pnames */
- continue; }
- case 4:
- if(tag[stackp[-1]]!=ID)
- if(stackp[-1]==NIL){ stackp -= 4; continue; } /* FIX1 */
- else { /* id aliased to pname */
- word akap;
- ch= *--stackp;
- SUPPRESSED=cons(ch,SUPPRESSED);
- stackp--; /* who */
- akap= tag[*stackp]==CONS?hd[*stackp]:NIL;
- stackp--; /* lose type */
- pn_val(ch)= *--stackp;
- if(stackp[1]==type_t&&t_class(ch)!=synonym_t)
- /* suppressed typename */
- { word a=ALIASES; /* reverse assoc in ALIASES */
- while(a!=NIL&&id_val(tl[hd[a]])!=ch)
- a=tl[a];
- if(a!=NIL) /* surely must hold ?? */
- TSUPPRESSED=cons(tl[hd[a]],TSUPPRESSED);
- /*if(akap==NIL)
- akap=datapair(get_id(tl[hd[a]]),0); */
- /*if(t_class(ch)==algebraic_t)
- CSUPPRESS=append1(CSUPPRESS,t_info(ch));
- t_info(ch)= cons(akap,fileinfo(CFN,0));
- /* assists identifn of dangling typerefs
- see privatise() in steer.c */ }else
- if(pn_val(ch)==UNDEF)
- { /* special kludge for undefined names */
- /* necessary only if we allow names specified
- but not defined to be %included */
- if(akap==NIL) /* reverse assoc in ALIASES */
- { word a=ALIASES;
- while(a!=NIL&&id_val(tl[hd[a]])!=ch)
- a=tl[a];
- if(a!=NIL)
- akap=datapair(get_id(tl[hd[a]]),0); }
- pn_val(ch)= ap(akap,fileinfo(CFN,0));
- /* this will generate sensible error message
- see reduction rule for DATAPAIR */
- }
- defs=cons(ch,defs);
- continue; }
- if(
- id_type(stackp[-1])!=new_t&& /* FIX1 */
- (id_type(stackp[-1])!=undef_t||
- id_val(stackp[-1])!=UNDEF)) /* nameclash */
- { if(id_type(stackp[-1])==alias_t) /* cyclic aliasing */
- { word a=ALIASES;
- while(a!=NIL&&tl[hd[a]]!=stackp[-1])a=tl[a];
- if(a==NIL)
- { fprintf(stderr,
- "impossible event in cyclic alias (%s)\n",
- get_id(stackp[-1]));
- stackp-=4;
- continue; }
- defs=cons(*--stackp,defs);
- hd[hd[hd[a]]]= *--stackp; /* who */
- hd[tl[hd[hd[a]]]]= *--stackp; /* type */
- tl[tl[hd[hd[a]]]]= *--stackp; /* value */
- continue; }
- /*if(strcmp(CFN,hd[get_here(stackp[-1])]))
- /* EXPT (ignore clash if from same original file) */
- CLASHES=add1(stackp[-1],CLASHES);
- stackp-=4; }
- else
- defs=cons(*--stackp,defs),
- /*printf("%s undumped\n",get_id(hd[defs])), /* DEBUG */
- id_who(hd[defs])= *--stackp,
- id_type(hd[defs])= *--stackp,
- id_val(hd[defs])= *--stackp;
- continue;
- default:
- { /* printf("badly formed def in dump\n"); /* DEBUG */
- BAD_DUMP=3; return(defs); } /* should unsetids */
- } /* of switch */
- case AP_X: ch = *--stackp;
- if(stackp[-1]==READ&&ch==0)stackp[-1] = common_stdin; else
- if(stackp[-1]==READBIN&&ch==0)stackp[-1] = common_stdinb; else
- stackp[-1] = ap(stackp[-1],ch);
- continue;
- case CONS_X: ch = *--stackp;
- stackp[-1] = cons(ch,stackp[-1]);
- continue;
- default: *stackp++ = ch>127?ch+256:ch;
- }}
- BAD_DUMP=4; /* should unsetids */
- return(defs);
-}
-
-extern char *obsuffix;
-
-okdump(t) /* return 1 if script t has a non-syntax-error dump */
-char *t;
-{ char obf[120];
- FILE *f;
- (void)strcpy(obf,t);
- (void)strcpy(obf+strlen(obf)-1,obsuffix);
- f=fopen(obf,"r");
- if(f&&getc(f)==XVERSION&&getc(f)){fclose(f); return(1); }
- return(0);
-}
-
-geterrlin(t) /* returns errline from dump of t if relevant, 0 otherwise */
-char *t;
-{ char obf[120];
- extern char *dicp,*dicq;
- word ch,el;
- FILE *f;
- (void)strcpy(obf,t);
- (void)strcpy(obf+strlen(obf)-1,obsuffix);
- if(!(f=fopen(obf,"r")))return(0);
- if(getc(f)!=XVERSION||(ch=getc(f))&&ch!=1){ fclose(f);
- return(0); }
- el=getw(f);
- /* now check this is right dump */
- setprefix(t);
- ch=getc(f);
- dicq=dicp;
- if(ch!='/')(void)strcpy(dicp,prefix),dicq+=preflen;
- /* locate wrt current posn */
- *dicq++ = ch;
- while((*dicq++ =ch=getc(f))&&ch!=EOF); /* filename */
- ch=getw(f); /* mtime */
- if(strcmp(dicp,t)||ch!=fm_time(t))return(0); /* wrong dump */
- /* this test not foolproof, strictly should extract all files and check
- their mtimes, as in undump, but this involves reading the whole dump */
- return(el);
-}
-
-hdsort(x) /* sorts list of name-value pairs on name */
-word x;
-{ word a=NIL,b=NIL,hold=NIL;
- if(x==NIL)return(NIL);
- if(tl[x]==NIL)return(x);
- while(x!=NIL) /* split x */
- { hold=a,a=cons(hd[x],b),b=hold;
- x=tl[x]; }
- a=hdsort(a),b=hdsort(b);
- /* now merge two halves back together */
- while(a!=NIL&&b!=NIL)
- if(strcmp(get_id(hd[hd[a]]),get_id(hd[hd[b]]))<0)x=cons(hd[a],x),a=tl[a];
- else x=cons(hd[b],x),b=tl[b];
- if(a==NIL)a=b;
- while(a!=NIL)x=cons(hd[a],x),a=tl[a];
- return(reverse(x));
-}
-#endif
-
-append1(x,y) /* rude append */
-word x,y;
-{ word x1=x;
- if(x1==NIL)return(y);
- while(tl[x1]!=NIL)x1=tl[x1];
- tl[x1]=y;
- return(x);
-}
-
-/* following is stuff for printing heap objects in readable form - used
- for miscellaneous diagnostics etc - main function is out(FILE *,object) */
-
-/* charname returns the printable name of a character, as a string (using
- C conventions for control characters */ /* DAT 13/9/83 */
-/* NB we use DECIMAL (not octal) for miscellaneous unprintables */
-
-/* WARNING - you should take a copy of the name if you intend to do anything
- with it other than print it immediately */
-
-char *charname(c)
-word c;
-{ static char s[5];
- switch(c)
- { case '\n': return("\\n");
- case '\t': return("\\t");
- case '\b': return("\\b");
- case '\f': return("\\f"); /* form feed */
- case '\r': return("\\r"); /* carriage return */
- case '\\': return("\\\\");
- case '\'': return("\\'");
- case '"': return("\\\"");
- /* we escape all quotes for safety, since the context could be either
- character or string quotation */
- default: if(c<32||c>126) /* miscellaneous unprintables -- convert to decimal */
- sprintf(s,"\\%d",c);
- else s[0]=c,s[1]='\0';
- return(s);
- }
-}
-
-out(f,x)
-/* the routines "out","out1","out2" are for printing compiled expressions */
-FILE *f;
-word x;
-{
-#ifdef DEBUG
- static pending=NIL; /* cycle trap */
- word oldpending=pending; /* cycle trap */
-#endif
- if(x<0||x>TOP){ fprintf(f,"<%d>",x); return; }
-#ifdef DEBUG
- if(member(pending,x)){ fprintf(f,"..."); return; } /* cycle trap */
- pending=cons(x,pending); /* cycle trap */
-#endif
- if(tag[x]==LAMBDA)
- { fprintf(f,"$(");out(f,hd[x]);putc(')',f);
- out(f,tl[x]); } else
- { while(tag[x]==CONS)
- { out1(f,hd[x]);
- putc(':',f);
- x= tl[x];
-#ifdef DEBUG
- if(member(pending,x))break; /* cycle trap */
- pending=cons(x,pending); /* cycle trap */
-#endif
- }
- out1(f,x); }
-#ifdef DEBUG
- pending=oldpending; /* cycle trap */
-#endif
-} /* warning - cycle trap not interrupt safe if `out' used in compiling
- process */
-
-out1(f,x)
-FILE *f;
-word x;
-{ if(x<0||x>TOP){ fprintf(f,"<%d>",x); return; }
- if(tag[x]==AP)
- { out1(f,hd[x]);
- putc(' ',f);
- out2(f,tl[x]); }
- else out2(f,x); }
-
-out2(f,x)
-FILE *f;
-word x;
-{ extern char *yysterm[], *cmbnms[];
- if(x<0||x>TOP){ fprintf(f,"<%d>",x); return; }
- if(tag[x]==INT)
- { if(rest(x))
- { x=bigtostr(x);
- while(x)putc(hd[x],f),x=tl[x]; }
- else fprintf(f,"%d",getsmallint(x));
- return; }
- if(tag[x]==DOUBLE){ outr(f,get_dbl(x)); return; }
- if(tag[x]==ID){ fprintf(f,"%s",get_id(x)); return; }
- if(x<256){ fprintf(f,"\'%s\'",charname(x)); return; }
- if(tag[x]==UNICODE){ fprintf(f,"'\%x'",hd[x]); return; }
- if(tag[x]==ATOM)
- { fprintf(f,"%s",x<CMBASE?yysterm[x-256]:
- x==True?"True":
- x==False?"False":
- x==NIL?"[]":
- x==NILS?"\"\"":
- cmbnms[x-CMBASE]);
- return; }
- if(tag[x]==TCONS||tag[x]==PAIR)
- { fprintf(f,"(");
- while(tag[x]==TCONS)
- out(f,hd[x]), putc(',',f), x=tl[x];
- out(f,hd[x]); putc(',',f); out(f,tl[x]);
- putc(')',f); return; }
- if(tag[x]==TRIES)
- { fprintf(f,"TRIES("); out(f,hd[x]); putc(',',f); out(f,tl[x]);
- putc(')',f); return; }
- if(tag[x]==LABEL)
- { fprintf(f,"LABEL("); out(f,hd[x]); putc(',',f); out(f,tl[x]);
- putc(')',f); return; }
- if(tag[x]==SHOW)
- { fprintf(f,"SHOW("); out(f,hd[x]); putc(',',f); out(f,tl[x]);
- putc(')',f); return; }
- if(tag[x]==STARTREADVALS)
- { fprintf(f,"READVALS("); out(f,hd[x]); putc(',',f); out(f,tl[x]);
- putc(')',f); return; }
- if(tag[x]==LET)
- { fprintf(f,"(LET ");
- out(f,dlhs(hd[x])),fprintf(f,"=");
- out(f,dval(hd[x])),fprintf(f,";IN ");
- out(f,tl[x]);
- fprintf(f,")"); return; }
- if(tag[x]==LETREC)
- { word body=tl[x];
- fprintf(f,"(LETREC ");
- x=hd[x];
- while(x!=NIL)out(f,dlhs(hd[x])),fprintf(f,"="),
- out(f,dval(hd[x])),fprintf(f,";"),x=tl[x];
- fprintf(f,"IN ");
- out(f,body);
- fprintf(f,")"); return; }
- if(tag[x]==DATAPAIR)
- { fprintf(f,"DATAPAIR(%s,%d)",(char *)hd[x],tl[x]);
- return; }
- if(tag[x]==FILEINFO)
- { fprintf(f,"FILEINFO(%s,%d)",(char *)hd[x],tl[x]);
- return; }
- if(tag[x]==CONSTRUCTOR)
- { fprintf(f,"CONSTRUCTOR(%d)",hd[x]);
- return; }
- if(tag[x]==STRCONS)
- { fprintf(f,"<$%d>",hd[x]); return; }/* used as private id's, inter alia*/
- if(tag[x]==SHARE)
- { fprintf(f,"(SHARE:"); out(f,hd[x]); fprintf(f,")"); return; }
- if(tag[x]!=CONS&&tag[x]!=AP&&tag[x]!=LAMBDA)
- /* not a recognised structure */
- { fprintf(f,"<%d|tag=%d>",x,tag[x]); return; }
- putc('(',f);
- out(f,x);
- putc(')',f); }
-
-outr(f,r) /* prints a number */
-FILE *f;
-double r;
-{ double p;
- p= r<0?-r: r;
- if(p>=1000.0||p<=.001)fprintf(f,"%e",r);
- else fprintf(f,"%f",r); }
-
-/* end of MIRANDA DATA REPRESENTATIONS */
-