summaryrefslogtreecommitdiff
path: root/new/steer.c
diff options
context:
space:
mode:
Diffstat (limited to 'new/steer.c')
-rw-r--r--new/steer.c2208
1 files changed, 0 insertions, 2208 deletions
diff --git a/new/steer.c b/new/steer.c
deleted file mode 100644
index 27c238d..0000000
--- a/new/steer.c
+++ /dev/null
@@ -1,2208 +0,0 @@
-/* MIRANDA STEER */
-/* initialisation routines and assorted routines for I/O etc */
-
-/**************************************************************************
- * 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. *
- *------------------------------------------------------------------------*/
-
-/* this stuff is to get the time-last-modified of files */
-#include <sys/types.h>
-#include <sys/stat.h>
-/* #include <sys/wait.h> /* seems not needed, oct 05 */
-struct stat buf; /* see man(2) stat - gets file status */
-
-#include "data.h"
-#include "lex.h"
-#include <float.h>
-word nill,Void;
-word main_id; /* change to magic scripts 19.11.2013 */
-word message,standardout;
-word diagonalise,concat,indent_fn,outdent_fn,listdiff_fn;
-word shownum1,showbool,showchar,showlist,showstring,showparen,showpair,
- showvoid,showfunction,showabstract,showwhat;
-
-char PRELUDE[pnlim+10],STDENV[pnlim+9];
- /* if anyone complains, elasticate these buffers! */
-
-#define DFLTSPACE 2500000
-#define DFLTDICSPACE 100000
-/* default values for size of heap, dictionary */
-word SPACELIMIT=DFLTSPACE,DICSPACE=DFLTDICSPACE;
-
-#ifdef CYGWIN
-#define EDITOR "joe +!"
-#else
-#define EDITOR "vi +!"
-#endif
-/* The name of whatever is locally considered to be the default editor - the
- user will be able to override this using the `/editor' command.
- It is also overriden by shell/environment variable EDITOR if present */
-
-extern FILE *s_out;
-word UTF8=0, UTF8OUT=0;
-extern char *vdate, *host;
-extern word version, ND;
-
-char *mkabsolute(char *), *strvers(word);
-void fpe_error(void);
-
-char *editor=NULL;
-word okprel=0; /* set to 1 when prelude loaded */
-word nostdenv=0; /* if set to 1 mira does not load stdenv at startup */
-/* to allow a NOSTDENV directive _in_the_script_ we would need to
- (i) replace isltmess() test in rules by eg is this a list of thing,
- where thing is algebraic type originally defined in STDENV
- (ii) arrange to pick up <stdenv> when current script not loaded
- not implemented */
-word baded=0; /* see fixeditor() */
-char *miralib=NULL;
-char *mirahdr,*lmirahdr;
-char *promptstr="Miranda ";
-char *obsuffix="x";
-FILE *s_in=NULL;
-word commandmode=0; /* true only when reading command-level expressions */
-word atobject=0,atgc=0,atcount=0,debug=0;
-word magic=0; /* set to 1 means script will start with UNIX magic string */
-word making=0; /* set only for mira -make */
-word mkexports=0; /* set only for mira -exports */
-word mksources=0; /* set only for mira -sources */
-word make_status=0; /* exit status of -make */
-word compiling=1;
-/* there are two types of MIRANDA process - compiling (the main process) and
-subsidiary processes launched for each evaluation - the above flag tells
-us which kind of process we are in */
-word ideep=0; /* depth of %include we are at, see mkincludes() */
-word SYNERR=0;
-word initialising=1;
-word primenv=NIL;
-char *current_script;
-word lastexp=UNDEF; /* value of `$$' */
-word echoing=0,listing=0,verbosity;
-word strictif=1,rechecking=0;
-word errline=0; /* records position of last error, for editor */
-word errs=0; /* secondary error location, in inserted script, if relevant */
-word *cstack;
-extern word c;
-extern char *dicp,*dicq;
-char linebuf[BUFSIZE]; /* used for assorted purposes */
- /* NB cannot share with linebuf in lex.c, or !! goes wrong */
-static char ebuf[pnlim];
-word col;
-char home_rc[pnlim+8];
-char lib_rc[pnlim+8];
-char *rc_error=NULL;
-#define badval(x) (x<1||x>478000000)
-
-#include <setjmp.h> /* for longjmp() - see man (3) setjmp */
-jmp_buf env;
-
-#ifdef sparc8
-#include <ieeefp.h>
-fp_except commonmask = FP_X_INV|FP_X_OFL|FP_X_DZ; /* invalid|ovflo|divzero */
-#endif
-
-main(argc,argv) /* system initialisation, followed by call to YACC */
-word argc;
-char *argv[];
-{ word manonly=0;
- char *home, *prs;
- word okhome_rc; /* flags valid HOME/.mirarc file present */
- char *argv0=argv[0];
- char *initscript;
- word badlib=0;
- extern word ARGC; extern char **ARGV;
- extern word newtyps,algshfns;
- char *progname=rindex(argv[0],'/');
- cstack= &manonly;
-/* used to indicate the base of the C stack for garbage collection purposes */
- verbosity=isatty(0);
-/*if(isatty(1))*/ setbuf(stdout,NULL); /* for unbuffered tty output */
- if(home=getenv("HOME"))
- { strcpy(home_rc,home);
- if(strcmp(home_rc,"/")==0)home_rc[0]=0; /* root is special case */
- strcat(home_rc,"/.mirarc");
- okhome_rc=rc_read(home_rc); }
-/*setup policy:
- if valid HOME/.mirarc found look no further, otherwise try
- <miralib>/.mirarc
- Complaints - if any .mirarc contained bad data, `announce' complains about
- the last such looked at. */
- UTF8OUT=UTF8=utf8test();
- while(argc>1&&argv[1][0]=='-') /* strip off flags */
- { if(strcmp(argv[1],"-stdenv")==0)nostdenv=1; else
- if(strcmp(argv[1],"-count")==0)atcount=1; else
- if(strcmp(argv[1],"-list")==0)listing=1; else
- if(strcmp(argv[1],"-nolist")==0)listing=0; else
- if(strcmp(argv[1],"-nostrictif")==0)strictif=0; else
- if(strcmp(argv[1],"-gc")==0)atgc=1; else
- if(strcmp(argv[1],"-object")==0)atobject=1; else
- if(strcmp(argv[1],"-lib")==0)
- { argc--,argv++;
- if(argc==1)missparam("lib"); else miralib=argv[1];
- } else
- if(strcmp(argv[1],"-dic")==0)
- { argc--,argv++;
- if(argc==1)missparam("dic"); else
- if(sscanf(argv[1],"%d",&DICSPACE)!=1||badval(DICSPACE))
- fprintf(stderr,"mira: bad value after flag \"-dic\"\n"),exit(1);
- } else
- if(strcmp(argv[1],"-heap")==0)
- { argc--,argv++;
- if(argc==1)missparam("heap"); else
- if(sscanf(argv[1],"%d",&SPACELIMIT)!=1||badval(SPACELIMIT))
- fprintf(stderr,"mira: bad value after flag \"-heap\"\n"),exit(1);
- } else
- if(strcmp(argv[1],"-editor")==0)
- { argc--,argv++;
- if(argc==1)missparam("editor");
- else editor=argv[1],fixeditor();
- } else
- if(strcmp(argv[1],"-hush")==0)verbosity=0; else
- if(strcmp(argv[1],"-nohush")==0)verbosity=1; else
- if(strcmp(argv[1],"-exp")==0||strcmp(argv[1],"-log")==0)
- fprintf(stderr,"mira: obsolete flag \"%s\"\n"
- "use \"-exec\" or \"-exec2\", see manual\n",
- argv[1]),exit(1); else
- if(strcmp(argv[1],"-exec")==0) /* replaces -exp 26.11.2019 */
- ARGC=argc-2,ARGV=argv+2,magic=1,verbosity=0; else
- if(strcmp(argv[1],"-exec2")==0) /* version of -exec for debugging CGI scripts */
- { if(argc<=2)fprintf(stderr,"incorrect use of -exec2 flag, missing filename\n"),exit(1);
- char *logfilname, *p=strrchr(argv[2],'/');
- FILE *fil=NULL;
- if(!p)p=argv[2]; /* p now holds last component of prog name */
- if(logfilname=malloc((strlen(p)+9)))
- sprintf(logfilname,"miralog/%s",p),
- fil=fopen(logfilname,"a");
- else mallocfail("logfile name");
- /* process requires write permission on local directory "miralog" */
- if(fil)dup2(fileno(fil),2); /* redirect stderr to log file */
- else fprintf(stderr,"could not open %s\n",logfilname);
- ARGC=argc-2,ARGV=argv+2,magic=1,verbosity=0; } else
- if(strcmp(argv[1],"-man")==0){ manonly=1; break; } else
- if(strcmp(argv[1],"-version")==0)v_info(0),exit(0); else
- if(strcmp(argv[1],"-V")==0)v_info(1),exit(0); else
- if(strcmp(argv[1],"-make")==0) making=1,verbosity=0; else
- if(strcmp(argv[1],"-exports")==0) making=mkexports=1,verbosity=0; else
- if(strcmp(argv[1],"-sources")==0) making=mksources=1,verbosity=0; else
- if(strcmp(argv[1],"-UTF-8")==0) UTF8=1; else
- if(strcmp(argv[1],"-noUTF-8")==0) UTF8=0; else
- fprintf(stderr,"mira: unknown flag \"%s\"\n",argv[1]),exit(1);
- argc--,argv++; }
- if(argc>2&&!magic&&!making)fprintf(stderr,"mira: too many args\n"),exit(1);
- if(!miralib) /* no -lib flag */
- { char *m;
- /* note search order */
- if((m=getenv("MIRALIB")))miralib=m; else
- if(checkversion(m="/usr/lib/miralib"))miralib=m; else
- if(checkversion(m="/usr/local/lib/miralib"))miralib=m; else
- if(checkversion(m="miralib"))miralib=m; else
- badlib=1;
- }
- if(badlib)
- { fprintf(stderr,"fatal error: miralib version %s not found\n",
- strvers(version));
- libfails();
- exit(1);
- }
- if(!okhome_rc)
- { if(rc_error==lib_rc)rc_error=NULL;
- (void)strcpy(lib_rc,miralib);
- (void)strcat(lib_rc,"/.mirarc");
- rc_read(lib_rc); }
- if(editor==NULL) /* .mirarc was absent or unreadable */
- { editor=getenv("EDITOR");
- if(editor==NULL)editor=EDITOR;
- else strcpy(ebuf,editor),editor=ebuf,fixeditor(); }
- if(prs=getenv("MIRAPROMPT"))promptstr=prs;
- if(getenv("RECHECKMIRA")&&!rechecking)rechecking=1;
- if(getenv("NOSTRICTIF"))strictif=0;
- setupdic(); /* used by mkabsolute */
- s_in=stdin;
- s_out=stdout;
- miralib=mkabsolute(miralib); /* protection against "/cd" */
- if(manonly)manaction(),exit(0);
- (void)strcpy(PRELUDE,miralib); (void)strcat(PRELUDE,"/prelude");
- /* convention - change spelling of "prelude" at each release */
- (void)strcpy(STDENV,miralib);
- (void)strcat(STDENV,"/stdenv.m");
- mira_setup();
- if(verbosity)announce();
- files=NIL;
- undump(PRELUDE),okprel=1;
- mkprivate(fil_defs(hd[files]));
- files=NIL; /* don't wish unload() to unsetids on prelude */
- if(!nostdenv)
- { undump(STDENV);
- while(files!=NIL) /* stdenv may have %include structure */
- primenv=alfasort(append1(primenv,fil_defs(hd[files]))),
- files=tl[files];
- primenv=alfasort(primenv);
- newtyps=files=NIL; /* don't wish unload() to unsetids */ }
- if(!magic)rc_write();
- echoing = verbosity&listing;
- initialising=0;
- if(mkexports)
- { /* making=1, to say if recompiling, also to undump as for %include */
- word f,argcount=argc-1;
- extern word exports,freeids;
- char *s;
- setjmp(env); /* will return here on blankerr (via reset) */
- while(--argc) /* where do error messages go?? */
- { word x=NIL;
- s=addextn(1,*++argv);
- if(s==dicp)keep(dicp);
- undump(s); /* bug, recompile messages goto stdout - FIX LATER */
- if(files==NIL||ND!=NIL)continue;
- if(argcount!=1)printf("%s\n",s);
- if(exports!=NIL)x=exports;
- /* true (if ever) only if just recompiled */
- else for(f=files;f!=NIL;f=tl[f])x=append1(fil_defs(hd[f]),x);
- /* method very clumsy, because exports not saved in dump */
- if(freeids!=NIL)
- { word f=freeids;
- while(f!=NIL)
- { word n=findid((char *)hd[hd[tl[hd[f]]]]);
- id_type(n)=tl[tl[hd[f]]];
- id_val(n)=the_val(hd[hd[f]]);
- hd[f]=n;
- f=tl[f]; }
- f=freeids=typesfirst(freeids);
- printf("\t%%free {\n");
- while(f!=NIL)
- putchar('\t'),
- report_type(hd[f]),
- putchar('\n'),
- f=tl[f];
- printf("\t}\n"); }
- for(x=typesfirst(alfasort(x));x!=NIL;x=tl[x])
- { putchar('\t');
- report_type(hd[x]);
- putchar('\n'); } }
- exit(0); }
- if(mksources){ extern word oldfiles;
- char *s;
- word f,x=NIL;
- setjmp(env); /* will return here on blankerr (via reset) */
- while(--argc)
- if(stat((s=addextn(1,*++argv)),&buf)==0)
- { if(s==dicp)keep(dicp);
- undump(s);
- for(f=files==NIL?oldfiles:files;f!=NIL;f=tl[f])
- if(!member(x,(word)get_fil(hd[f])))
- x=cons((word)get_fil(hd[f]),x),
- printf("%s\n",get_fil(hd[f]));
- }
- exit(0); }
- if(making){ extern word oldfiles;
- char *s;
- setjmp(env); /* will return here on blankerr (via reset) */
- while(--argc) /* where do error messages go?? */
- { s=addextn(1,*++argv);
- if(s==dicp)keep(dicp);
- undump(s);
- if(ND!=NIL||files==NIL&&oldfiles!=NIL)
- { if(make_status==1)make_status=0;
- make_status=strcons(s,make_status); }
- /* keep list of source files with error-dumps */
- }
- if(tag[make_status]==STRCONS)
- { word h=0,maxw=0,w,n;
- printf("errors or undefined names found in:-\n");
- while(make_status) /* reverse to get original order */
- { h=strcons(hd[make_status],h);
- w=strlen((char *)hd[h]);
- if(w>maxw)maxw=w;
- make_status=tl[make_status]; }
- maxw++;n=78/maxw;w=0;
- while(h)
- printf("%*s%s",maxw,(char *)hd[h],(++w%n)?"":"\n"),
- h=tl[h];
- if(w%n)printf("\n");
- make_status=1; }
- exit(make_status); }
- initscript= argc==1?"script.m":magic?argv[1]:addextn(1,argv[1]);
- if(initscript==dicp)keep(dicp);
-#if sparc8
- fpsetmask(commonmask);
-#elif defined sparc
- ieee_handler("set","common",(sighandler)fpe_error);
-#endif
-#if !defined sparc | sparc8
- (void)signal(SIGFPE,(sighandler)fpe_error); /* catch arithmetic overflow */
-#endif
- (void)signal(SIGTERM,(sighandler)exit); /* flush buffers if killed */
- commandloop(initscript);
- /* parameter is file given as argument */
-}
-
-word vstack[4]; /* record of miralib versions looked at */
-char *mstack[4]; /* and where found */
-word mvp=0;
-
-checkversion(m)
-/* returns 1 iff m is directory with .version containing our version number */
-char *m;
-{ word v1,read=0,r=0;
- FILE *f=fopen(strcat(strcpy(linebuf,m),"/.version"),"r");
- if(f&&fscanf(f,"%u",&v1)==1)r= v1==version, read=1;
- if(f)fclose(f);
- if(read&&!r)mstack[mvp]=m,vstack[mvp++]=v1;
- return r;
-}
-
-libfails()
-{ word i=0;
- fprintf(stderr,"found");
- for(;i<mvp;i++)fprintf(stderr,"\tversion %s at: %s\n",
- strvers(vstack[i]),mstack[i]);
-}
-
-char *strvers(v)
-{ static char vbuf[12];
- if(v<0||v>999999)return "\?\?\?";
- snprintf(vbuf,12,"%.3f",v/1000.0);
- return vbuf;
-}
-
-char *mkabsolute(m) /* make sure m is an absolute pathname */
-char *m;
-{ if(m[0]=='/')return(m);
- if(!getcwd(dicp,pnlim))fprintf(stderr,"panic: cwd too long\n"),exit(1);
- (void)strcat(dicp,"/");
- (void)strcat(dicp,m);
- m=dicp;
- dicp=dicq+=strlen(dicp)+1;
- dic_check();
- return(m);
-}
-
-missparam(s)
-char *s;
-{ fprintf(stderr,"mira: missing param after flag \"-%s\"\n",s);
- exit(1); }
-
-word oldversion=0;
-#define colmax 400
-#define spaces(s) for(j=s;j>0;j--)putchar(' ')
-
-announce()
-{ extern char *vdate;
- word w,j;
-/*clrscr(); /* clear screen on start up */
- w=(twidth()-50)/2;
- printf("\n\n");
- spaces(w); printf(" T h e M i r a n d a S y s t e m\n\n");
- spaces(w+5-strlen(vdate)/2);
- printf(" version %s last revised %s\n\n",strvers(version),vdate);
- spaces(w); printf("Copyright Research Software Ltd 1985-2019\n\n");
- spaces(w); printf(" World Wide Web: http://miranda.org.uk\n\n\n");
- if(SPACELIMIT!=DFLTSPACE)
- printf("(%d cells)\n",SPACELIMIT);
- if(!strictif)printf("(-nostrictif : deprecated!)\n");
-/*printf("\t\t\t\t%dbit platform\n",__WORDSIZE); /* */
- if(oldversion<1999) /* pre release two */
- printf("\
-WARNING:\n\
-a new release of Miranda has been installed since you last used\n\
-the system - please read the `CHANGES' section of the /man pages !!!\n\n");
- else
- if(version>oldversion)
- printf("a new version of Miranda has been installed since you last\n"),
- printf("used the system - see under `CHANGES' in the /man pages\n\n");
- if(version<oldversion)
- printf("warning - this is an older version of Miranda than the one\n"),
- printf("you last used on this machine!!\n\n");
- if(rc_error)
- printf("warning: \"%s\" contained bad data (ignored)\n",rc_error);
-}
-
-
-rc_read(rcfile) /* get settings of system parameters from setup file */
-char *rcfile;
-{ FILE *in;
- char z[20];
- word h,d,v,s,r=0;
- oldversion=version; /* default assumption */
- in=fopen(rcfile,"r");
- if(in==NULL||fscanf(in,"%19s",z)!=1)
- return(0); /* file not present, or not readable */
- if(strncmp(z,"hdve",4)==0 /* current .mirarc format */
- ||strcmp(z,"lhdve")==0) /* alternative format used at release one */
- { char *z1 = &z[3];
- if(z[0]=='l')listing=1,z1++;
- while(*++z1)if(*z1=='l')listing=1; else
- if(*z1=='s') /* ignore */; else
- if(*z1=='r')rechecking=2; else
- rc_error=rcfile;
- if(fscanf(in,"%d%d%d%*c",&h,&d,&v)!=3||!getln(in,pnlim-1,ebuf)
- ||badval(h)||badval(d)||badval(v))rc_error=rcfile;
- else editor=ebuf,SPACELIMIT=h,DICSPACE=d,r=1,
- oldversion=v; } else
- if(strcmp(z,"ehdsv")==0) /* versions before 550 */
- { if(fscanf(in,"%19s%d%d%d%d",ebuf,&h,&d,&s,&v)!=5
- ||badval(h)||badval(d)||badval(v))rc_error=rcfile;
- else editor=ebuf,SPACELIMIT=h,DICSPACE=d,r=1,
- oldversion=v; } else
- if(strcmp(z,"ehds")==0) /* versions before 326, "s" was stacklimit (ignore) */
- { if(fscanf(in,"%s%d%d%d",ebuf,&h,&d,&s)!=4
- ||badval(h)||badval(d))rc_error=rcfile;
- else editor=ebuf,SPACELIMIT=h,DICSPACE=d,r=1,
- oldversion=1; }
- else rc_error=rcfile; /* unrecognised format */
- if(editor)fixeditor();
- fclose(in);
- return(r);
-}
-
-fixeditor()
-{ if(strcmp(editor,"vi")==0)editor="vi +!"; else
- if(strcmp(editor,"pico")==0)editor="pico +!"; else
- if(strcmp(editor,"nano")==0)editor="nano +!"; else
- if(strcmp(editor,"joe")==0)editor="joe +!"; else
- if(strcmp(editor,"jpico")==0)editor="jpico +!"; else
- if(strcmp(editor,"vim")==0)editor="vim +!"; else
- if(strcmp(editor,"gvim")==0)editor="gvim +! % &"; else
- if(strcmp(editor,"emacs")==0)editor="emacs +! % &";
- else { char *p=rindex(editor,'/');
- if(p==0)p=editor; else p++;
- if(strcmp(p,"vi")==0)strcat(p," +!");
- }
- if(rindex(editor,'&'))rechecking=2;
- listing=badeditor();
-}
-
-badeditor() /* does editor know how to open file at line? */
-{ char *p=index(editor,'!');
- while(p&&p[-1]=='\\')p=index(p+1,'!');
- return (baded = !p);
-}
-
-getln(in,n,s) /* reads line (<=n chars) from in into s - returns 1 if ok */
-FILE *in; /* the newline is discarded, and the result '\0' terminated */
-word n;
-char *s;
-{ while(n--&&(*s=getc(in))!='\n')s++;
- if(*s!='\n'||n<0)return(0);
- *s='\0';
- return(1);
-} /* what a pain that `fgets' doesn't do it right !! */
-
-rc_write()
-{ FILE *out=fopen(home_rc,"w");
- if(out==NULL)
- { fprintf(stderr,"warning: cannot write to \"%s\"\n",home_rc);
- return; }
- fprintf(out,"hdve");
- if(listing)fputc('l',out);
- if(rechecking==2)fputc('r',out);
- fprintf(out," %d %d %d %s\n",SPACELIMIT,DICSPACE,version,editor);
- fclose(out);
-}
-
-word lastid=0; /* first inscope identifier of immediately preceding command */
-word rv_expr=0;
-
-commandloop(initscript)
-char* initscript;
-{ word ch;
- word reset();
- extern word cook_stdin,polyshowerror;
- char *lb;
- if(setjmp(env)==0) /* returns here if interrupted, 0 means first time thru */
- { if(magic){ undump(initscript); /* was loadfile() changed 26.11.2019
- to allow dump of magic scripts in ".m"*/
- if(files==NIL||ND!=NIL||id_val(main_id)==UNDEF)
- /* files==NIL=>script absent or has syntax errors
- ND!=NIL=>script has type errors or undefined names
- all reported by undump() or loadfile() on new compile */
- { if(files!=NIL&&ND==NIL&&id_val(main_id)==UNDEF)
- fprintf(stderr,"%s: main not defined\n",initscript);
- fprintf(stderr,"mira: incorrect use of \"-exec\" flag\n");
- exit(1); }
- magic=0; obey(main_id); exit(0); }
- /* was obey(lastexp), change to magic scripts 19.11.2013 */
- (void)signal(SIGINT,(sighandler)reset);
- undump(initscript);
- if(verbosity)printf("for help type /h\n"); }
- for(;;)
- { resetgcstats();
- if(verbosity)printf("%s",promptstr);
- ch = getchar();
- if(rechecking&&src_update())loadfile(current_script);
- /* modified behaviour for `2-window' mode */
- while(ch==' '||ch=='\t')ch=getchar();
- switch(ch)
- { case '?': ch=getchar();
- if(ch=='?')
- { word x; char *aka=NULL;
- if(!token()&&!lastid)
- { printf("\7identifier needed after `\?\?'\n");
- ch=getchar(); /* '\n' */
- break; }
- if(getchar()!='\n'){ xschars(); break; }
- if(baded){ ed_warn(); break; }
- if(dicp[0])x=findid(dicp);
- else printf("??%s\n",get_id(lastid)),x=lastid;
- if(x==NIL||id_type(x)==undef_t)
- { diagnose(dicp[0]?dicp:get_id(lastid));
- lastid=0;
- break; }
- if(id_who(x)==NIL)
- { /* nb - primitives have NIL who field */
- printf("%s -- primitive to Miranda\n",
- dicp[0]?dicp:get_id(lastid));
- lastid=0;
- break; }
- lastid=x;
- x=id_who(x); /* get here info */
- if(tag[x]==CONS)aka=(char *)hd[hd[x]],x=tl[x];
- if(aka)printf("originally defined as \"%s\"\n",
- aka);
- editfile((char *)hd[x],tl[x]);
- break; }
- ungetc(ch,stdin);
- (void)token();
- lastid=0;
- if(dicp[0]=='\0')
- { if(getchar()!='\n')xschars();
- else allnamescom();
- break; }
- while(dicp[0])finger(dicp),(void)token();
- ch=getchar();
- break;
- case ':': /* add (silently) as kindness to Hugs users */
- case '/': (void)token();
- lastid=0;
- command(ch);
- break;
- case '!': if(!(lb=rdline()))break; /* rdline returns NULL on failure */
- lastid=0;
- if(*lb)
- { /*system(lb); */ /* always gives /bin/sh */
- static char *shell=NULL;
- sighandler oldsig;
- word pid;
- if(!shell)
- { shell=getenv("SHELL");
- if(!shell)shell="/bin/sh"; }
- oldsig= signal(SIGINT,SIG_IGN);
- if(pid=fork())
- { /* parent */
- if(pid==-1)
- perror("UNIX error - cannot create process");
- while(pid!=wait(0));
- (void)signal(SIGINT,oldsig); }
- else execl(shell,shell,"-c",lb,(char *)0);
- if(src_update())loadfile(current_script); }
- else printf(
- "No previous shell command to substitute for \"!\"\n");
- break;
- case '|': /* lines beginning "||" are comments */
- if((ch=getchar())!='|')
- printf("\7unknown command - type /h for help\n");
- while(ch!='\n'&&ch!=EOF)ch=getchar();
- case '\n': break;
- case EOF: if(verbosity)printf("\nmiranda logout\n");
- exit(0);
- default: ungetc(ch,stdin);
- lastid=0;
- tl[hd[cook_stdin]]=0; /* unset type of $+ */
- rv_expr=0;
- c = EVAL;
- echoing=0;
- polyshowerror=0; /* gets set by wrong use of $+, readvals */
- commandmode=1;
- yyparse();
- if(SYNERR)SYNERR=0;
- else if(c!='\n') /* APPARENTLY NEVER TRUE */
- { printf("syntax error\n");
- while(c!='\n'&&c!=EOF)
- c=getchar(); /* swallow syntax errors */
- }
- commandmode=0;
- echoing=verbosity&listing;
-}}}
-
-parseline(t,f,fil) /* parses next valid line of f at type t, returns EOF
- if none found. See READVALS in reduce.c */
-word t;
-FILE *f;
-word fil;
-{ word t1,ch;
- lastexp=UNDEF;
- for(;;)
- { ch=getc(f);
- while(ch==' '||ch=='\t'||ch=='\n')ch=getc(f);
- if(ch=='|')
- { ch=getc(f);
- if(ch=='|') /* leading comment */
- { while((ch=getc(f))!='\n'&&ch!=EOF);
- if(ch!=EOF)continue; }
- else ungetc(ch,f); }
- if(ch==EOF)return(EOF);
- ungetc(ch,f);
- c = VALUE;
- echoing=0;
- commandmode=1;
- s_in=f;
- yyparse();
- s_in=stdin;
- if(SYNERR)SYNERR=0,lastexp=UNDEF; else
- if((t1=type_of(lastexp))==wrong_t)lastexp=UNDEF; else
- if(!subsumes(instantiate(t1),t))
- { printf("data has wrong type :: "), out_type(t1),
- printf("\nshould be :: "), out_type(t), putc('\n',stdout);
- lastexp=UNDEF; }
- if(lastexp!=UNDEF)return(codegen(lastexp));
- if(isatty(fileno(f)))printf("please re-enter data:\n");
- else { if(fil)fprintf(stderr,"readvals: bad data in file \"%s\"\n",
- getstring(fil,0));
- else fprintf(stderr,"bad data in $+ input\n");
- outstats(); exit(1); }
-}}
-
-ed_warn()
-{ printf(
-"The currently installed editor command, \"%s\", does not\n\
-include a facility for opening a file at a specified line number. As a\n\
-result the `\?\?' command and certain other features of the Miranda system\n\
-are disabled. See manual section 31/5 on changing the editor for more\n\
-information.\n",editor);
-}
-
-time_t fm_time(f) /* time last modified of file f */
-char *f;
-{ return(stat(f,&buf)==0?buf.st_mtime:0);
- /* non-existent file has conventional mtime of 0 */
-} /* WARNING - we assume time_t can be stored in an int field
- - this may not port */
-
-#define same_file(x,y) (hd[fil_inodev(x)]==hd[fil_inodev(y)]&& \
- tl[fil_inodev(x)]==tl[fil_inodev(y)])
-#define inodev(f) (stat(f,&buf)==0?datapair(buf.st_ino,buf.st_dev):\
- datapair(0,-1))
-
-word oldfiles=NIL; /* most recent set of sources, in case of interrupted or
- failed compilation */
-src_update() /* any sources modified ? */
-{ word ft,f=files==NIL?oldfiles:files;
- while(f!=NIL)
- { if((ft=fm_time(get_fil(hd[f])))!=fil_time(hd[f]))
- { if(ft==0)unlinkx(get_fil(hd[f])); /* tidy up after eg `!rm %' */
- return(1); }
- f=tl[f]; }
- return(0);
-}
-
-word loading;
-char *unlinkme; /* if set, is name of partially created obfile */
-
-reset() /* interrupt catcher - see call to signal in commandloop */
-{ extern word lineptr,ATNAMES,current_id;
- extern word blankerr,collecting/* ,*dstack,*stackp */;
- /*if(!making) /* see note below
- (void)signal(SIGINT,SIG_IGN); /* dont interrupt me while I'm tidying up */
-/*if(magic)exit(0); *//* signal now not set to reset in magic scripts */
- if(collecting)gcpatch();
- if(loading)
- { if(!blankerr)
- printf("\n<<compilation interrupted>>\n");
- if(unlinkme)unlink(unlinkme);
- /* stackp=dstack; /* add if undump() made interruptible later*/
- oldfiles=files,unload(),current_id=ATNAMES=loading=SYNERR=lineptr=0;
- if(blankerr)blankerr=0,makedump(); }
- /* magic script cannot be literate so no guard needed on makedump */
- else printf("<<interrupt>>\n"); /* VAX, SUN, ^C does not cause newline */
- reset_state(); /* see LEX */
- if(collecting)collecting=0,gc(); /* to mark stdenv etc as wanted */
- if(making&&!make_status)make_status=1;
-#ifdef SYSTEM5
- else (void)signal(SIGINT,(sighandler)reset);/*ready for next interrupt*//*see note*/
-#endif
- /* during mira -make blankerr is only use of reset */
- longjmp(env,1);
-}/* under BSD and Linux installed signal remains installed after interrupt
- and further signals blocked until handler returns */
-
-#define checkeol if(getchar()!='\n')break;
-
-word lose;
-
-normal(f) /* s has ".m" suffix */
-char *f;
-{ word n=strlen(f);
- return n>=2&&strcmp(f+n-2,".m")==0;
-}
-
-v_info(word full)
-{ printf("%s last revised %s\n",strvers(version),vdate);
- if(!full)return;
- printf("%s",host);
- printf("XVERSION %u\n",XVERSION);
-}
-
-
-command(c)
-word c;
-{ char *t;
- word ch,ch1;
- switch(dicp[0])
- {
- case 'a': if(is("a")||is("aux"))
- { checkeol;
-/* if(verbosity)clrscr(); */
- (void)strcpy(linebuf,miralib);
- (void)strcat(linebuf,"/auxfile");
- filecopy(linebuf);
- return; }
- case 'c': if(is("count"))
- { checkeol; atcount=1; return; }
- if(is("cd"))
- { char *d=token();
- if(!d)d=getenv("HOME");
- else d=addextn(0,d);
- checkeol;
- if(chdir(d)==-1)printf("cannot cd to %s\n",d);
- else if(src_update())undump(current_script);
- /* alternative: keep old script and recompute pathname
- wrt new directory - LOOK INTO THIS LATER */
- return; }
- case 'd': if(is("dic"))
- { extern char *dic;
- if(!token())
- { lose=getchar(); /* to eat \n */
- printf("%d chars",DICSPACE);
- if(DICSPACE!=DFLTDICSPACE)
- printf(" (default=%d)",DFLTDICSPACE);
- printf(" %d in use\n",dicq-dic);
- return; }
- checkeol;
- printf(
- "sorry, cannot change size of dictionary while in use\n");
- printf(
- "(/q and reinvoke with flag: mira -dic %s ... )\n",dicp);
- return; }
- case 'e': if(is("e")||is("edit"))
- { char *mf=0;
- if(t=token())t=addextn(1,t);
- else t=current_script;
- checkeol;
- if(stat(t,&buf)) /* new file */
- { if(!lmirahdr) /* lazy initialisation */
- { dicp=dicq;
- (void)strcpy(dicp,getenv("HOME"));
- if(strcmp(dicp,"/")==0)
- dicp[0]=0; /* root is special case */
- (void)strcat(dicp,"/.mirahdr");
- lmirahdr=dicp;
- dicq=dicp=dicp+strlen(dicp)+1; } /* ovflo check? */
- if(!stat(lmirahdr,&buf))mf=lmirahdr;
- if(!mf&&!mirahdr) /* lazy initialisation */
- { dicp=dicq;
- (void)strcpy(dicp,miralib);
- (void)strcat(dicp,"/.mirahdr");
- mirahdr=dicp;
- dicq=dicp=dicp+strlen(dicp)+1; }
- if(!mf&&!stat(mirahdr,&buf))mf=mirahdr;
- /*if(mf)printf("mf=%s\n",mf); /* DEBUG*/
- if(mf&&t!=current_script)
- { printf("open new script \"%s\"? [ny]",t);
- ch1=ch=getchar();
- while(ch!='\n'&&ch!=EOF)ch=getchar();
- /*eat rest of line */
- if(ch1!='y'&&ch1!='Y')return; }
- if(mf)filecp(mf,t); }
- editfile(t,strcmp(t,current_script)==0?errline:
- errs&&strcmp(t,(char *)hd[errs])==0?tl[errs]:
- geterrlin(t));
- return; }
- if(is("editor"))
- { char *hold=linebuf,*h;
- if(!getln(stdin,pnlim-1,hold))break; /*reject if too long*/
- if(!*hold)
- { /* lose=getchar(); /* to eat newline */
- printf("%s\n",editor);
- return; }
- h=hold+strlen(hold); /* remove trailing white space */
- while(h[-1]==' '||h[-1]=='\t')*--h='\0';
- if(*hold=='"'||*hold=='\'')
- { printf("please type name of editor without quotation marks\n");
- return; }
- printf("change editor to: \"%s\"? [ny]",hold);
- ch1=ch=getchar();
- while(ch!='\n'&&ch!=EOF)ch=getchar(); /* eat rest of line */
- if(ch1!='y'&&ch1!='Y')
- { printf("editor not changed\n");
- return; }
- (void)strcpy(ebuf,hold);
- editor=ebuf;
- fixeditor(); /* reads "vi" as "vi +!" etc */
- echoing=verbosity&listing;
- rc_write();
- printf("editor = %s\n",editor);
- return; }
- case 'f': if(is("f")||is("file"))
- { char *t=token();
- checkeol;
- if(t)t=addextn(1,t),keep(t);
- /* could get multiple copies of filename in dictionary
- - FIX LATER */
- if(t)errs=errline=0; /* moved here from reset() */
- if(t)if(strcmp(t,current_script)||files==NIL&&okdump(t))
- { extern word CLASHES;
- CLASHES=NIL; /* normally done by load_script */
- undump(t); /* does not always call load_script */
- if(CLASHES!=NIL)/* pathological case, recompile */
- loadfile(t); }
- else loadfile(t); /* force recompilation */
- else printf("%s%s\n",current_script,
- files==NIL?" (not loaded)":"");
- return; }
- if(is("files")) /* info about internal state, not documented */
- { word f=files;
- checkeol;
- for(;f!=NIL;f=tl[f])
- printf("(%s,%d,%d)",get_fil(hd[f]),fil_time(hd[f]),
- fil_share(hd[f])),printlist("",fil_defs(hd[f]));
- return; } /* DEBUG */
- if(is("find"))
- { word i=0;
- while(token())
- { word x=findid(dicp),y,f;
- i++;
- if(x!=NIL)
- { char *n=get_id(x);
- for(y=primenv;y!=NIL;y=tl[y])
- if(tag[hd[y]]==ID)
- if(hd[y]==x||getaka(hd[y])==n)
- finger(get_id(hd[y]));
- for(f=files;f!=NIL;f=tl[f])
- for(y=fil_defs(hd[f]);y!=NIL;y=tl[y])
- if(tag[hd[y]]==ID)
- if(hd[y]==x||getaka(hd[y])==n)
- finger(get_id(hd[y])); }
- }
- ch=getchar(); /* '\n' */
- if(i==0)printf("\7identifier needed after `/find'\n");
- return; }
- case 'g': if(is("gc"))
- { checkeol; atgc=1; return; }
- case 'h': if(is("h")||is("help"))
- { checkeol;
-/* if(verbosity)clrscr(); */
- (void)strcpy(linebuf,miralib);
- (void)strcat(linebuf,"/helpfile");
- filecopy(linebuf);
- return; }
- if(is("heap"))
- { word x;
- if(!token())
- { lose=getchar(); /* to eat \n */
- printf("%d cells",SPACELIMIT);
- if(SPACELIMIT!=DFLTSPACE)
- printf(" (default=%d)",DFLTSPACE);
- printf("\n");
- return; }
- checkeol;
- if(sscanf(dicp,"%d",&x)!=1||badval(x))
- { printf("illegal value (heap unchanged)\n"); return; }
- if(x<trueheapsize())
- printf("sorry, cannot shrink heap to %d at this time\n",x);
- else { if(x!=SPACELIMIT)
- SPACELIMIT=x,resetheap();
- printf("heaplimit = %d cells\n",SPACELIMIT),
- rc_write(); }
- return; }
- if(is("hush"))
- { checkeol; echoing=verbosity=0; return; }
- case 'l': if(is("list"))
- { checkeol; listing=1; echoing=verbosity&listing;
- rc_write(); return; }
- case 'm': if(is("m")||is("man"))
- { checkeol; manaction(); return; }
- if(is("miralib"))
- { checkeol; printf("%s\n",miralib); return; }
- case 'n': /* if(is("namebuckets"))
- { int i,x;
- extern int namebucket[];
- checkeol;
- for(i=0;i<128;i++)
- if(x=namebucket[i])
- { printf("%d:",i);
- while(x)
- putchar(' '),out(stdout,hd[x]),x=tl[x];
- putchar('\n'); }
- return; } /* DEBUG */
- if(is("nocount"))
- { checkeol; atcount=0; return; }
- if(is("nogc"))
- { checkeol; atgc=0; return; }
- if(is("nohush"))
- { checkeol; echoing=listing; verbosity=1; return; }
- if(is("nolist"))
- { checkeol; echoing=listing=0; rc_write(); return; }
- if(is("norecheck"))
- { checkeol; rechecking=0; rc_write(); return; }
-/* case 'o': if(is("object"))
- { checkeol; atobject=1; return; } /* now done by flag -object */
- case 'q': if(is("q")||is("quit"))
- { checkeol; if(verbosity)printf("miranda logout\n"); exit(0); }
- case 'r': if(is("recheck"))
- { checkeol; rechecking=2; rc_write(); return; }
- case 's': if(is("s")||is("settings"))
- { checkeol;
- printf("*\theap %d\n",SPACELIMIT);
- printf("*\tdic %d\n",DICSPACE);
- printf("*\teditor = %s\n",editor);
- printf("*\t%slist\n",listing?"":"no");
- printf("*\t%srecheck\n",rechecking?"":"no");
- if(!strictif)
- printf("\t-nostrictif (deprecated!)\n");
- if(atcount)printf("\tcount\n");
- if(atgc)printf("\tgc\n");
- if(UTF8)printf("\tUTF-8 i/o\n");
- if(!verbosity)printf("\thush\n");
- if(debug)printf("\tdebug 0%o\n",debug);
- printf("\n* items remembered between sessions\n");
- return; }
- case 'v': if(is("v")||is("version"))
- { checkeol;
- v_info(0);
- return; }
- case 'V': if(is("V"))
- { checkeol;
- v_info(1);
- return; }
- default: printf("\7unknown command \"%c%s\"\n",c,dicp);
- printf("type /h for help\n");
- while((ch=getchar())!='\n'&&ch!=EOF);
- return;
- } /* end of switch statement */
- xschars();
-}
-
-manaction()
-{ sprintf(linebuf,"\"%s/menudriver\" \"%s/manual\"",miralib,miralib);
- system(linebuf);
-} /* put quotes around both pathnames to allow for spaces in miralib 8.5.06 */
-
-editfile(t,line)
-char *t;
-word line;
-{ char *ebuf=linebuf;
- char *p=ebuf,*q=editor;
- word tdone=0;
- if(line==0)line=1; /* avoids warnings in some versions of vi */
- while(*p++ = *q++)
- if(p[-1]=='\\'&&(q[0]=='!'||q[0]=='%'))p[-1]= *q++; else
- if(p[-1]=='!')
- (void)
- sprintf(p-1,"%d",line),
- p+=strlen(p); else
- if(p[-1]=='%')p[-1]='"',*p='\0', /* quote filename 9.5.06 */
- (void)strncat(p,t,BUFSIZE+ebuf-p),
- p+=strlen(p),
- *p++ = '"',*p='\0',
- tdone=1;
- if(!tdone)
- p[-1] = ' ',
- *p++ = '"',*p='\0', /* quote filename 9.5.06 */
- (void)strncat(p,t,BUFSIZE+ebuf-p),
- p+=strlen(p),
- *p++ = '"',*p='\0';
- /* printf("%s\n",ebuf); /* DEBUG */
- system(ebuf);
- if(src_update())loadfile(current_script);
- return;
-}
-
-xschars()
-{ word ch;
- printf("\7extra characters at end of command\n");
- while((ch=getchar())!='\n'&&ch!=EOF);
-}
-
-reverse(x) /* x is a cons list */
-word x;
-{ word y = NIL;
- while(x!=NIL)y = cons(hd[x],y), x = tl[x];
- return(y);
-}
-
-shunt(x,y) /* equivalent to append(reverse(x),y) */
-word x,y;
-{ while(x!=NIL)y = cons(hd[x],y), x = tl[x];
- return(y);
-}
-
-char *presym[] =
- {"abstype","div","if","mod","otherwise","readvals","show","type","where",
- "with", 0};
-word presym_n[] =
- { 21, 8, 15, 8, 15, 31, 23, 22, 15,
- 21 };
-
-#include <ctype.h>
-
-filequote(p) /* write p to stdout with <quotes> if appropriate */
-char *p; /* p is a pathname */
-{ static mlen=0;
- if(!mlen)mlen=(rindex(PRELUDE,'/')-PRELUDE)+1;
- if(strncmp(p,PRELUDE,mlen)==0)
- printf("<%s>",p+mlen);
- else printf("\"%s\"",p);
-} /* PRELUDE is a convenient string with the miralib prefix */
-
-finger(n) /* find info about name stored at dicp */
-char *n;
-{ word x,line;
- char *s;
- x=findid(n);
- if(x!=NIL&&id_type(x)!=undef_t)
- { if(id_who(x)!=NIL)
- s=(char *)hd[line=get_here(x)],line=tl[line];
- if(!lastid)lastid=x;
- report_type(x);
- if(id_who(x)==NIL)printf(" ||primitive to Miranda\n");
- else { char *aka=getaka(x);
- if(aka==get_id(x))aka=NULL; /* don't report alias to self */
- if(id_val(x)==UNDEF&&id_type(x)!=wrong_t)
- printf(" ||(UNDEFINED) specified in "); else
- if(id_val(x)==FREE)
- printf(" ||(FREE) specified in "); else
- if(id_type(x)==type_t&&t_class(x)==free_t)
- printf(" ||(free type) specified in "); else
- printf(" ||%sdefined in ",
- id_type(x)==type_t
- && t_class(x)==abstract_t?"(abstract type) ":
- id_type(x)==type_t
- && t_class(x)==algebraic_t?"(algebraic type) ":
- id_type(x)==type_t
- && t_class(x)==placeholder_t?"(placeholder type) ":
- id_type(x)==type_t
- && t_class(x)==synonym_t?"(synonym type) ":
- "");
- filequote(s);
- if(baded||rechecking)printf(" line %d",line);
- if(aka)printf(" (as \"%s\")\n",aka);
- else putchar('\n');
- }
- if(atobject)printf("%s = ",get_id(x)),
- out(stdout,id_val(x)),putchar('\n');
- return; }
- diagnose(n);
-}
-
-diagnose(n)
-char *n;
-{ word i=0;
- if(isalpha(n[0]))
- while(n[i]&&okid(n[i]))i++;
- if(n[i]){ printf("\"%s\" -- not an identifier\n",n); return; }
- for(i=0;presym[i];i++)
- if(strcmp(n,presym[i])==0)
- { printf("%s -- keyword (see manual, section %d)\n",n,presym_n[i]);
- return; }
- printf("identifier \"%s\" not in scope\n",n);
-}
-
-static word sorted=0; /* flag to avoid repeatedly sorting fil_defs */
-static word leftist; /* flag to alternate bias of padding in justification */
-word words[colmax]; /* max plausible size of screen */
-
-allnamescom()
-{ word s;
- word x=ND;
- word y=x,z=0;
- leftist=0;
- namescom(make_fil(nostdenv?0:STDENV,0,0,primenv));
- if(files==NIL)return; else s=tl[files];
- while(s!=NIL)namescom(hd[s]),s=tl[s];
- namescom(hd[files]);
- sorted=1;
- /* now print warnings, if any */
- /*if(ND!=NIL&&id_type(hd[ND])==type_t)
- { printf("ILLEGAL EXPORT LIST - MISSING TYPENAME%s: ",tl[ND]==NIL?"":"S");
- printlist("",ND);
- return; } /* install if incomplete export list is escalated to error */
- while(x!=NIL&&id_type(hd[x])==undef_t)x=tl[x];
- while(y!=NIL&&id_type(hd[y])!=undef_t)y=tl[y];
- if(x!=NIL)
- { printf("WARNING, SCRIPT CONTAINS TYPE ERRORS: ");
- for(;x!=NIL;x=tl[x])
- if(id_type(hd[x])!=undef_t)
- { if(!z)z=1; else putchar(',');
- out(stdout,hd[x]); }
- printf(";\n"); }
- if(y!=NIL)
- { printf("%s UNDEFINED NAMES: ",z?"AND":"WARNING, SCRIPT CONTAINS");
- z=0;
- for(;y!=NIL;y=tl[y])
- if(id_type(hd[y])==undef_t)
- { if(!z)z=1; else putchar(',');
- out(stdout,hd[y]); }
- printf(";\n"); }
-}
-/* There are two kinds of entry in ND
- undefined names: val=UNDEF, type=undef_t
- type errors: val=UNDEF, type=wrong_t
-*/
-
-#define tolerance 3
- /* max number of extra spaces we are willing to insert */
-
-namescom(l) /* l is an element of `files' */
-word l;
-{ word n=fil_defs(l),col=0,undefs=NIL,wp=0;
- word scrwd = twidth();
- if(!sorted&&n!=primenv) /* primenv already sorted */
- fil_defs(l)=n=alfasort(n); /* also removes pnames */
- if(n==NIL)return; /* skip empty files */
- if(get_fil(l))filequote(get_fil(l));
- else printf("primitive:");
- printf("\n");
- while(n!=NIL)
- { if(id_type(hd[n])==wrong_t||id_val(hd[n])!=UNDEF)
- { word w=strlen(get_id(hd[n]));
- if(col+w<scrwd)col += (col!=0); else
- if(wp&&col+w>=scrwd)
- { word i,r,j;
- if(wp>1)i=(scrwd-col)/(wp-1),r=(scrwd-col)%(wp-1);
- if(i+(r>0)>tolerance)i=r=0;
- if(leftist)
- for(col=0;col<wp;)
- { printf("%s",get_id(words[col]));
- if(++col<wp)
- spaces(1+i+(r-- >0)); }
- else
- for(r=wp-1-r,col=0;col<wp;)
- { printf("%s",get_id(words[col]));
- if(++col<wp)
- spaces(1+i+(r-- <=0)); }
- leftist=!leftist,wp=0,col=0,putchar('\n'); }
- col+=w;
- words[wp++]=hd[n]; }
- else undefs=cons(hd[n],undefs); /* undefined but have good types */
- n = tl[n]; }
- if(wp)
- for(col=0;col<wp;)
- printf("%s",get_id(words[col])),putc(++col==wp?'\n':' ',stdout);
- if(undefs==NIL)return;
- undefs=reverse(undefs);
- printlist("SPECIFIED BUT NOT DEFINED: ",undefs);
-}
-
-word detrop=NIL; /* list of unused local definitions */
-word rfl=NIL; /* list of include components containing type orphans */
-word bereaved; /* typenames referred to in exports and not exported */
-word ld_stuff=NIL;
- /* list of list of files, to be unloaded if mkincludes interrupted */
-
-loadfile(t)
-char *t;
-{ extern word fileq;
- extern word current_id,includees,embargoes,exportfiles,freeids,exports;
- extern word fnts,FBS,disgusting,nextpn;
- word h=NIL; /* location of %export directive, if present */
- loading=1;
- errs=errline=0;
- current_script=t;
- oldfiles=NIL;
- unload();
- if(stat(t,&buf))
- { if(initialising){ fprintf(stderr,"panic: %s not found\n",t); exit(1); }
- if(verbosity)printf("new file %s\n",t);
- if(magic)fprintf(stderr,"mira -exec %s%s\n",t,": no such file"),exit(1);
- if(making&&ideep==0)printf("mira -make %s%s\n",t,": no such file");
- else oldfiles=cons(make_fil(t,0,0,NIL),NIL);
- /* for correct record of sources */
- loading=0;
- return; }
- if(!openfile(t))
- { if(initialising){ fprintf(stderr,"panic: cannot open %s\n",t); exit(1); }
- printf("cannot open %s\n",t);
- oldfiles=cons(make_fil(t,0,0,NIL),NIL);
- loading=0;
- return; }
- files = cons(make_fil(t,fm_time(t),1,NIL),NIL);
- current_file = hd[files],tl[hd[fileq]] = current_file;
- if(initialising&&strcmp(t,PRELUDE)==0)privlib(); else
- if(initialising||nostdenv==1)
- if(strcmp(t,STDENV)==0)stdlib();
- c = ' ';
- col = 0;
- s_in = (FILE *)hd[hd[fileq]];
- adjust_prefix(t);
-/*if(magic&&!initialising)
- { if(!(getc(s_in)=='#'&&getc(s_in)=='!'))
- { files=NIL; return; }
- while(getc(s_in)!='\n');
- commandmode=1;
- c=MAGIC; }
- else /* change to magic scripts 19.11.2013 */
- commandmode = 0;
- if(verbosity||making)printf("compiling %s\n",t);
- nextpn=0; /* lose pnames */
- embargoes=detrop=
- fnts=rfl=bereaved=ld_stuff=exportfiles=freeids=exports=includees=FBS=NIL;
- yyparse();
- if(!SYNERR&&exportfiles!=NIL)
- { /* check pathnames in exportfiles have unique bindings */
- word s,i,count;
- for(s=exportfiles;s!=NIL;s=tl[s])
- if(hd[s]==PLUS) /* add current script (less freeids) to exports */
- { for(i=fil_defs(hd[files]);i!=NIL;i=tl[i])
- if(isvariable(hd[i])&&!isfreeid(hd[i]))
- tl[exports]=add1(hd[i],tl[exports]);
- } else
- /* pathnames are expanded to their contents in mkincludes */
- { for(count=0,i=includees;i!=NIL;i=tl[i])
- if(!strcmp((char *)hd[hd[hd[i]]],(char *)hd[s]))
- hd[s]=hd[hd[hd[i]]]/*sharing*/,count++;
- if(count!=1)
- SYNERR=1,
- printf("illegal fileid \"%s\" in export list (%s)\n",
- (char *)hd[s],
- count?"ambiguous":"not %included in script");
- }
- if(SYNERR)
- sayhere(hd[exports],1),
- printf("compilation abandoned\n");
- }
- if(!SYNERR&&includees!=NIL)
- files=append1(files,mkincludes(includees)),includees=NIL;
- ld_stuff=NIL;
- if(!SYNERR&!disgusting)
- { if(verbosity||making&&!mkexports&&!mksources)
- printf("checking types in %s\n",t);
- checktypes();
- /* printf("typecheck complete\n"); /* DEBUG */ }
- if(!SYNERR&&exports!=NIL)
- if(ND!=NIL)exports=NIL; else /* skip check, cannot be %included */
- { /* check exports all present and close under type info */
- word e,u=NIL,n=NIL,c=NIL;
- h=hd[exports]; exports=tl[exports];
- for(e=embargoes;e!=NIL;e=tl[e])
- { if(id_type(hd[e])==undef_t)u=cons(hd[e],u),ND=add1(hd[e],ND); else
- if(!member(exports,hd[e]))n=cons(hd[e],n); }
- if(embargoes!=NIL)
- exports=setdiff(exports,embargoes);
- exports=alfasort(exports);
- for(e=exports;e!=NIL;e=tl[e])
- if(id_type(hd[e])==undef_t)u=cons(hd[e],u),ND=add1(hd[e],ND); else
- if(id_type(hd[e])==type_t&&t_class(hd[e])==algebraic_t)
- c=shunt(t_info(hd[e]),c); /* constructors */
- if(exports==NIL)printf("warning, export list has void contents\n");
- else exports=append1(alfasort(c),exports);
- if(n!=NIL)
- { printf("redundant entr%s in export list:",tl[n]==NIL?"y":"ies");
- while(n!=NIL)printf(" -%s",get_id(hd[n])),n=tl[n]; n=1; /* flag */
- putchar('\n'); }
- if(u!=NIL)exports=NIL,
- printlist("undefined names in export list: ",u);
- if(u!=NIL)sayhere(h,1),h=NIL; else
- if(exports==NIL||n!=NIL)out_here(stderr,h,1),h=NIL;
- /* for warnings call out_here not sayhere, so errinfo not saved in dump */
- }
- if(!SYNERR&&ND==NIL&&(exports!=NIL||tl[files]!=NIL))
- { /* find out if script can create type orphans when %included */
- word e1,t;
- word r=NIL; /* collect list of referenced typenames */
- word e=NIL; /* and list of exported typenames */
- if(exports!=NIL)
- for(e1=exports;e1!=NIL;e1=tl[e1])
- { if((t=id_type(hd[e1]))==type_t)
- if(t_class(hd[e1])==synonym_t)
- r=UNION(r,deps(t_info(hd[e1])));
- else e=cons(hd[e1],e);
- else r=UNION(r,deps(t)); } else
- for(e1=fil_defs(hd[files]);e1!=NIL;e1=tl[e1])
- { if((t=id_type(hd[e1]))==type_t)
- if(t_class(hd[e1])==synonym_t)
- r=UNION(r,deps(t_info(hd[e1])));
- else e=cons(hd[e1],e);
- else r=UNION(r,deps(t)); }
- for(e1=freeids;e1!=NIL;e1=tl[e1])
- if((t=id_type(hd[hd[e1]]))==type_t)
- if(t_class(hd[hd[e1]])==synonym_t)
- r=UNION(r,deps(t_info(hd[hd[e1]])));
- else e=cons(hd[hd[e1]],e);
- else r=UNION(r,deps(t));
- /*printlist("r: ",r); /* DEBUG */
- for(;r!=NIL;r=tl[r])
- if(!member(e,hd[r]))bereaved=cons(hd[r],bereaved);
- /*printlist("bereaved: ",bereaved); /* DEBUG */
- }
- if(exports!=NIL&&bereaved!=NIL)
- { extern word newtyps;
- word b=intersection(bereaved,newtyps);
- /*printlist("newtyps",newtyps); /* DEBUG */
- if(b!=NIL)
- /*ND=b; /* to escalate to type error, see also allnamescom */
- printf("warning, export list is incomplete - missing typename%s: ",
- tl[b]==NIL?"":"s"),
- printlist("",b);
- if(b!=NIL&&h!=NIL)out_here(stdout,h,1); /* sayhere(h,1) for error */
- }
- if(!SYNERR&&detrop!=NIL)
- { word gd=detrop;
- while(detrop!=NIL&&tag[dval(hd[detrop])]==LABEL)detrop=tl[detrop];
- if(detrop!=NIL)
- printf("warning, script contains unused local definitions:-\n");
- while(detrop!=NIL)
- { out_here(stdout,hd[hd[tl[dval(hd[detrop])]]],0), putchar('\t');
- out_pattern(stdout,dlhs(hd[detrop])), putchar('\n');
- detrop=tl[detrop];
- while(detrop!=NIL&&tag[dval(hd[detrop])]==LABEL)
- detrop=tl[detrop]; }
- while(gd!=NIL&&tag[dval(hd[gd])]!=LABEL)gd=tl[gd];
- if(gd!=NIL)
- printf("warning, grammar contains unused nonterminals:-\n");
- while(gd!=NIL)
- { out_here(stdout,hd[dval(hd[gd])],0), putchar('\t');
- out_pattern(stdout,dlhs(hd[gd])), putchar('\n');
- gd=tl[gd];
- while(gd!=NIL&&tag[dval(hd[gd])]!=LABEL)gd=tl[gd]; }
- /* note, usual rhs is tries(pat,list(label(here,exp)))
- grammar rhs is label(here,...) */
- }
- if(!SYNERR)
- { word x; extern word lfrule,polyshowerror;
- /* we invoke the code generator */
- lfrule=0;
- for(x=fil_defs(hd[files]);x!=NIL;x=tl[x])
- if(id_type(hd[x])!=type_t)
- { current_id=hd[x];
- polyshowerror=0;
- id_val(hd[x])=codegen(id_val(hd[x]));
- if(polyshowerror)id_val(hd[x])=UNDEF;
- /* nb - one remaining class of typerrs trapped in codegen,
- namely polymorphic show or readvals */
- }
- current_id=0;
- if(lfrule&&(verbosity||making))
- printf("grammar optimisation: %d common left factors found\n",lfrule);
- if(initialising&&ND!=NIL)
- { fprintf(stderr,"panic: %s contains errors\n",okprel?"stdenv":"prelude");
- exit(1); }
- if(initialising)makedump(); else
- if(normal(t)) /* file ends ".m", formerly if(!magic) */
- fixexports(),makedump(),unfixexports();
- /* changed 26.11.2019 to allow dump of magic scripts ending ".m" */
- if(!errline&&errs&&(char *)hd[errs]==current_script)
- errline=tl[errs]; /* soft error (posn not saved in dump) */
- ND=alfasort(ND);
- /* we could sort and remove pnames from each defs component immediately
- after makedump(), instead of doing this in namescom */
- loading=0;
- return; }
- /* otherwise syntax error found */
- if(initialising)
- { fprintf(stderr,"panic: cannot compile %s\n",okprel?"stdenv":"prelude"); exit(1); }
- oldfiles=files;
- unload();
- if(normal(t)&&SYNERR!=2)makedump(); /* make syntax error dump */
- /* allow dump of magic script in ".m", was if(!magic&&) 26.11.2019 */
- SYNERR=0;
- loading=0;
-}
-
-isfreeid(x)
-{ return(id_type(x)==type_t?t_class(x)==free_t:id_val(x)==FREE); }
-
-word internals=NIL; /* used by fix/unfixexports, list of names not exported */
-#define paint(x) id_val(x)=ap(EXPORT,id_val(x))
-#define unpainted(x) (tag[id_val(x)]!=AP||hd[id_val(x)]!=EXPORT)
-#define unpaint(x) id_val(x)=tl[id_val(x)]
-
-fixexports()
-{ extern exports,exportfiles,embargoes,freeids;
- word e=exports,f;
- /* printlist("exports: ",e); /* DEBUG */
- for(;e!=NIL;e=tl[e])paint(hd[e]);
- internals=NIL;
- if(exports==NIL&&exportfiles==NIL&&embargoes==NIL) /*no %export in script*/
- { for(e=freeids;e!=NIL;e=tl[e])
- internals=cons(privatise(hd[hd[e]]),internals);
- for(f=tl[files];f!=NIL;f=tl[f])
- for(e=fil_defs(hd[f]);e!=NIL;e=tl[e])
- { if(tag[hd[e]]==ID)
- internals=cons(privatise(hd[e]),internals); }}
- else for(f=files;f!=NIL;f=tl[f])
- for(e=fil_defs(hd[f]);e!=NIL;e=tl[e])
- { if(tag[hd[e]]==ID&&unpainted(hd[e]))
- internals=cons(privatise(hd[e]),internals); }
- /* optimisation, need not do this to `silent' components - fix later */
- /*printlist("internals: ",internals); /* DEBUG */
- for(e=exports;e!=NIL;e=tl[e])unpaint(hd[e]);
-} /* may not be interrupt safe, re unload() */
-
-unfixexports()
-{ /*printlist("internals: ",internals); /* DEBUG */
- word i=internals;
- if(mkexports)return; /* in this case don't want internals restored */
- while(i!=NIL) /* lose */
- publicise(hd[i]),i=tl[i];
- internals=NIL;
-} /* may not be interrupt safe, re unload() */
-
-privatise(x) /* change id to pname, and return new id holding it as value */
-word x;
-{ extern word namebucket[],*pnvec;
- word n = make_pn(x),h=namebucket[hash(get_id(x))],i;
- if(id_type(x)==type_t)
- t_info(x)=cons(datapair(getaka(x),0),get_here(x));
- /* to assist identification of danging type refs - see typesharing code
- in mkincludes */
- /* assumption - nothing looks at the t_info after compilation */
- if(id_val(x)==UNDEF) /* name specified but not defined */
- id_val(x)= ap(datapair(getaka(x),0),get_here(x));
- /* this will generate sensible error message on attempt to use value
- see reduction rule for DATAPAIR */
- pnvec[i=hd[n]]=x;
- tag[n]=ID;hd[n]=hd[x];
- tag[x]=STRCONS;hd[x]=i;
- while(hd[h]!=x)h=tl[h];
- hd[h]=n;
- return(n);
-} /* WARNING - dependent on internal representation of ids and pnames */
-/* nasty problem - privatisation can screw AKA's */
-
-publicise(x) /* converse of the above, applied to the new id */
-word x;
-{ extern word namebucket[];
- word i=id_val(x),h=namebucket[hash(get_id(x))];
- tag[i]=ID,hd[i]=hd[x];
- /* WARNING - USES FACT THAT tl HOLDS VALUE FOR BOTH ID AND PNAME */
- if(tag[tl[i]]==AP&&tag[hd[tl[i]]]==DATAPAIR)
- tl[i]=UNDEF; /* undo kludge, see above */
- while(hd[h]!=x)h=tl[h];
- hd[h]=i;
- return(i);
-}
-
-static sigflag=0;
-
-sigdefer()
-{ /* printf("sigdefer()\n"); /* DEBUG */
- sigflag=1; } /* delayed signal handler, installed during load_script() */
-
-mkincludes(includees)
-word includees;
-{ extern word FBS,BAD_DUMP,CLASHES,exportfiles,exports,TORPHANS;
- word pid,result=NIL,tclashes=NIL;
- includees=reverse(includees); /* process in order of occurrence in script */
- if(pid=fork())
- { /* parent */
- word status;
- if(pid==-1)
- { perror("UNIX error - cannot create process"); /* will say why */
- if(ideep>6) /* perhaps cyclic %include */
- fprintf(stderr,"error occurs %d deep in %%include files\n",ideep);
- if(ideep)exit(2);
- SYNERR=2; /* special code to prevent makedump() */
- printf("compilation of \"%s\" abandoned\n",current_script);
- return(NIL); }
- while(pid!=wait(&status));
- if((WEXITSTATUS(status))==2) /* child aborted */
- if(ideep)exit(2); /* recursive abortion of parent process */
- else { SYNERR=2;
- printf("compilation of \"%s\" abandoned\n",current_script);
- return(NIL); }
- /* if we get to here child completed normally, so carry on */
- }
- else { /* child does equivalent of `mira -make' on each includee */
- extern word oldfiles;
- (void)signal(SIGINT,SIG_DFL); /* don't trap interrupts */
- ideep++; making=1; make_status=0; echoing=listing=verbosity=magic=0;
- setjmp(env); /* will return here on blankerr (via reset) */
- while(includees!=NIL&&!make_status) /* stop at first bad includee */
- { undump((char *)hd[hd[hd[includees]]]);
- if(ND!=NIL||files==NIL&&oldfiles!=NIL)make_status=1;
- /* any errors in dump? */
- includees=tl[includees];
- } /* obscure bug - undump above can reinvoke compiler, which
- side effects compiler variable `includees' - to fix this
- had to make sure child is holding local copy of includees*/
- exit(make_status); }
- sigflag=0;
- for(;includees!=NIL;includees=tl[includees])
- { word x=NIL;
- sighandler oldsig;
- FILE *f;
- char *fn=(char *)hd[hd[hd[includees]]];
- extern word DETROP,MISSING,ALIASES,TSUPPRESSED,*stackp,*dstack;
- (void)strcpy(dicp,fn);
- (void)strcpy(dicp+strlen(dicp)-1,obsuffix);
- if(!making) /* cannot interrupt load_script() */
- oldsig=signal(SIGINT,(sighandler)sigdefer);
- if(f=fopen(dicp,"r"))
- x=load_script(f,fn,hd[tl[hd[includees]]],tl[tl[hd[includees]]],0),
- fclose(f);
- ld_stuff=cons(x,ld_stuff);
- if(!making)(void)signal(SIGINT,oldsig);
- if(sigflag)sigflag=0,(* oldsig)(); /* take deferred interrupt */
- if(f&&!BAD_DUMP&&x!=NIL&&ND==NIL&&CLASHES==NIL&&ALIASES==NIL&&
- TSUPPRESSED==NIL&&DETROP==NIL&&MISSING==NIL)
- /* i.e. if load_script worked ok */
- { /* stuff here is to share repeated file components
- issues:
- Consider only includees (fil_share=1), not insertees.
- Effect of sharing is to replace value fields in later copies
- by (pointers to) corresponding ids in first copy - so sharing
- transmitted thru dumps. It is illegal to have more than one
- copy of a (non-synonym) type in the same scope, even under
- different names. */
- word y,z;
- /* printf("start share analysis\n"); /* DEBUG */
- if(TORPHANS)rfl=shunt(x,rfl); /* file has type orphans */
- for(y=x;y!=NIL;y=tl[y])fil_inodev(hd[y])=inodev(get_fil(hd[y]));
- for(y=x;y!=NIL;y=tl[y])
- if(fil_share(hd[y]))
- for(z=result;z!=NIL;z=tl[z])
- if(fil_share(hd[z])&&same_file(hd[y],hd[z])
- &&fil_time(hd[y])==fil_time(hd[z]))
- { word p=fil_defs(hd[y]),q=fil_defs(hd[z]);
- for(;p!=NIL&&q!=NIL;p=tl[p],q=tl[q])
- if(tag[hd[p]]==ID)
- if(id_type(hd[p])==type_t&&
- (tag[hd[q]]==ID||tag[pn_val(hd[q])]==ID))
- { /* typeclash - record in tclashes */
- word w=tclashes;
- word orig=tag[hd[q]]==ID?hd[q]:pn_val(hd[q]);
- if(t_class(hd[p])==synonym_t)continue;
- while(w!=NIL&&((char *)hd[hd[w]]!=get_fil(hd[z])
- ||hd[tl[hd[w]]]!=orig))
- w=tl[w];
- if(w==NIL)
- w=tclashes=cons(strcons(get_fil(hd[z]),
- cons(orig,NIL)),tclashes);
- tl[tl[hd[w]]]=cons(hd[p],tl[tl[hd[w]]]);
- }
- else the_val(hd[q])=hd[p];
- else the_val(hd[p])=hd[q];
- /*following test redundant - remove when sure is ok*/
- if(p!=NIL||q!=NIL)
- fprintf(stderr,"impossible event in mkincludes\n");
- /*break; /* z loop -- NO! (see liftbug) */
- }
- if(member(exportfiles,(word)fn))
- { /* move ids of x onto exports */
- for(y=x;y!=NIL;y=tl[y])
- for(z=fil_defs(hd[y]);z!=NIL;z=tl[z])
- if(isvariable(hd[z]))
- tl[exports]=add1(hd[z],tl[exports]);
- /* skip pnames, constructors (expanded later) */
- }
- result=append1(result,x);
- /* keep `result' in front-first order */
- if(hd[FBS]==NIL)FBS=tl[FBS];
- else hd[FBS]=cons(tl[hd[hd[includees]]],hd[FBS]); /* hereinfo */
- /* printf("share analysis finished\n"); /* DEBUG */
- continue; }
- /* something wrong - find out what */
- if(!f)result=cons(make_fil(hd[hd[hd[includees]]],
- fm_time(fn),0,NIL),result); else
- if(x==NIL&&BAD_DUMP!= -2)result=append1(result,oldfiles),oldfiles=NIL;
- else result=append1(result,x);
- /* above for benefit of `oldfiles' */
- /* BAD_DUMP -2 is nameclashes due to aliasing */
- SYNERR=1;
- printf("unsuccessful %%include directive ");
- sayhere(tl[hd[hd[includees]]],1);
-/* if(!f)printf("\"%s\" non-existent or unreadable\n",fn), */
- if(!f)printf("\"%s\" cannot be loaded\n",fn),
- CLASHES=DETROP=MISSING=NIL;
- /* just in case not cleared from a previous load_script() */
- else
- if(BAD_DUMP== -2)
- printlist("aliasing causes nameclashes: ",CLASHES),
- CLASHES=NIL; else
- if(ALIASES!=NIL||TSUPPRESSED!=NIL)
- { if(ALIASES!=NIL)
- printf("alias fails (name%s not found in file",
- tl[ALIASES]==NIL?"":"s"),
- printlist("): ",ALIASES),ALIASES=NIL;
- if(TSUPPRESSED!=NIL)
- { printf("illegal alias (cannot suppress typename%s):",
- tl[TSUPPRESSED]==NIL?"":"s");
- while(TSUPPRESSED!=NIL)
- printf(" -%s",get_id(hd[TSUPPRESSED])),
- TSUPPRESSED=tl[TSUPPRESSED];
- putchar('\n'); }
- /* if -typename allowed, remember to look for type orphans */
- }else
- if(BAD_DUMP)printf("\"%s\" has bad data in dump file\n",fn); else
- if(x==NIL)printf("\"%s\" contains syntax error\n",fn); else
- if(ND!=NIL)
- printf("\"%s\" contains undefined names or type errors\n",fn);
- if(ND==NIL&&CLASHES!=NIL) /* can have this and failed aliasing */
- printf("\"%s\" ",fn),printlist("causes nameclashes: ",CLASHES);
- while(DETROP!=NIL&&tag[hd[DETROP]]==CONS)
- { word fa=hd[tl[hd[DETROP]]],ta=tl[tl[hd[DETROP]]];
- char *pn=get_id(hd[hd[DETROP]]);
- if(fa== -1||ta== -1)
- printf("`%s' has binding of wrong kind ",pn),
- printf(fa== -1?"(should be \"= value\" not \"== type\")\n"
- :"(should be \"== type\" not \"= value\")\n");
- else
- printf("`%s' has == binding of wrong arity ",pn),
- printf("(formal has arity %d, actual has arity %d)\n",fa,ta);
- DETROP=tl[DETROP]; }
- if(DETROP!=NIL)
- printf("illegal parameter binding (name%s not %%free in file",
- tl[DETROP]==NIL?"":"s"),
- printlist("): ",DETROP),DETROP=NIL;
- if(MISSING!=NIL)
- printf("missing parameter binding%s: ",tl[MISSING]==NIL?"":"s");
- while(MISSING!=NIL)
- printf("%s%s",(char *)hd[hd[MISSING]],tl[MISSING]==NIL?";\n":","),
- MISSING=tl[MISSING];
- printf("compilation abandoned\n");
- stackp=dstack; /* in case of BAD_DUMP */
- return(result); } /* for unload() */
- if(tclashes!=NIL)
- { printf("TYPECLASH - the following type%s multiply named:\n",
- tl[tclashes]==NIL?" is":"s are");
- /* structure of tclashes is list of strcons(filname,list-of-ids) */
- for(;tclashes!=NIL;tclashes=tl[tclashes])
- { printf("\'%s\' of file \"%s\", as: ",
- getaka(hd[tl[hd[tclashes]]]),
- (char *)hd[hd[tclashes]]);
- printlist("",alfasort(tl[hd[tclashes]])); }
- printf("typecheck cannot proceed - compilation abandoned\n");
- SYNERR=1;
- return(result); } /* for unload */
- return(result);
-}
-
-word tlost=NIL;
-word pfrts=NIL; /* list of private free types bound in this script */
-
-readoption() /* readopt type orphans */
-{ word f,t;
- extern word TYPERRS,FBS;
- pfrts=tlost=NIL;
- /* exclude anonymous free types, these dealt with later by mcheckfbs() */
- if(FBS!=NIL)
- for(f=FBS;f!=NIL;f=tl[f])
- for(t=tl[hd[f]];t!=NIL;t=tl[t])
- if(tag[hd[hd[t]]]==STRCONS&&tl[tl[hd[t]]]==type_t)
- pfrts=cons(hd[hd[t]],pfrts);
- /* this may needlessly scan `silent' files - fix later */
- for(;rfl!=NIL;rfl=tl[rfl])
- for(f=fil_defs(hd[rfl]);f!=NIL;f=tl[f])
- if(tag[hd[f]]==ID)
- if((t=id_type(hd[f]))==type_t)
- { if(t_class(hd[f])==synonym_t)
- t_info(hd[f])=fixtype(t_info(hd[f]),hd[f]); }
- else id_type(hd[f])=fixtype(t,hd[f]);
- if(tlost==NIL)return;
- TYPERRS++;
- printf("MISSING TYPENAME%s\n",tl[tlost]==NIL?"":"S");
- printf("the following type%s no name in this scope:\n",
- tl[tlost]==NIL?" is needed but has":"s are needed but have");
- /* structure of tlost is list of cons(losttype,list-of-ids) */
- for(;tlost!=NIL;tlost=tl[tlost])
- { /* printf("tinfo_tlost=");out(stdout,t_info(hd[hd[tlost]]));
- putchar(';'); /*DEBUG */
- printf("\'%s\' of file \"%s\", needed by: ",
- (char *)hd[hd[t_info(hd[hd[tlost]])]],
- (char *)hd[tl[t_info(hd[hd[tlost]])]]);
- printlist("",alfasort(tl[hd[tlost]])); }
-}
-
-/*fixtype(t,x)
-int t,x;
-{ int t1;
- t1=fixtype1(t,x);
- printf("fixing type of %s\n",get_id(x));
- out_type(t); printf(" := ");
- out_type(t1); putchar('\n');
- return(t1);
-} /* DEBUG */
-
-fixtype(t,x) /* substitute out any indirected typenames in t */
-word t,x;
-{ switch(tag[t])
- { case AP:
- case CONS: tl[t]=fixtype(tl[t],x);
- hd[t]=fixtype(hd[t],x);
- default: return(t);
- case STRCONS: if(member(pfrts,t))return(t); /* see jrcfree.bug */
- while(tag[pn_val(t)]!=CONS)t=pn_val(t);/*at most twice*/
- if(tag[t]!=ID)
- { /* lost type - record in tlost */
- word w=tlost;
- while(w!=NIL&&hd[hd[w]]!=t)w=tl[w];
- if(w==NIL)
- w=tlost=cons(cons(t,cons(x,NIL)),tlost);
- tl[hd[w]]=add1(x,tl[hd[w]]);
- }
- return(t);
- }
-}
-
-#define mask(c) (c&0xDF)
-/* masks out lower case bit, which is 0x20 */
-alfa_ls(a,b) /* 'DICTIONARY ORDER' - not currently used */
-char *a,*b;
-{ while(*a&&mask(*a)==mask(*b))a++,b++;
- if(mask(*a)==mask(*b))return(strcmp(a,b)<0); /* lower case before upper */
- return(mask(*a)<mask(*b));
-}
-
-alfasort(x) /* also removes non_IDs from result */
-word x;
-{ word a=NIL,b=NIL,hold=NIL;
- if(x==NIL)return(NIL);
- if(tl[x]==NIL)return(tag[hd[x]]!=ID?NIL:x);
- while(x!=NIL) /* split x */
- { if(tag[hd[x]]==ID)hold=a,a=cons(hd[x],b),b=hold;
- x=tl[x]; }
- a=alfasort(a),b=alfasort(b);
- /* now merge two halves back together */
- while(a!=NIL&&b!=NIL)
- if(strcmp(get_id(hd[a]),get_id(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));
-}
-
-unsetids(d) /* d is a list of identifiers */
-word d;
-{ while(d!=NIL)
- { if(tag[hd[d]]==ID)id_val(hd[d])=UNDEF,
- id_who(hd[d])=NIL,
- id_type(hd[d])=undef_t;
- d=tl[d]; } /* should we remove from namebucket ? */
-}
-
-unload() /* clear out current script in preparation for reloading */
-{ extern word TABSTRS,SGC,speclocs,newtyps,rv_script,algshfns,nextpn,nolib,
- includees,freeids;
- word x;
- sorted=0;
- speclocs=NIL;
- nextpn=0; /* lose pnames */
- rv_script=0;
- algshfns=NIL;
- unsetids(newtyps);
- newtyps=NIL;
- unsetids(freeids);
- freeids=includees=SGC=freeids=TABSTRS=ND=NIL;
- unsetids(internals);
- internals=NIL;
- while(files!=NIL)
- { unsetids(fil_defs(hd[files]));
- fil_defs(hd[files])=NIL;
- files = tl[files]; }
- for(;ld_stuff!=NIL;ld_stuff=tl[ld_stuff])
- for(x=hd[ld_stuff];x!=NIL;x=tl[x])unsetids(fil_defs(hd[x]));
-}
-
-yyerror(s) /* called by YACC in the event of a syntax error */
-char *s;
-{ extern word yychar;
- if(SYNERR)return; /* error already reported, so shut up */
- if(echoing)printf("\n");
- printf("%s - unexpected ",s);
- if(yychar==OFFSIDE&&(c==EOF||c=='|'))
- { if(c==EOF) /* special case introduced by fix for dtbug */
- printf("end of file"); else
- printf("token '|'");
- /* special case introduced by sreds fix to offside rule */
- } else
- { printf(yychar==0?commandmode?"newline":"end of file":"token ");
- if(yychar>=256)putchar('\"');
- if(yychar!=0)out2(stdout,yychar);
- if(yychar>=256)putchar('\"'); }
- printf("\n");
- SYNERR=1;
- reset_lex();
-}
-
-syntax(s) /* called by actions after discovering a (context sensitive) syntax
- error */
-char *s;
-{ if(SYNERR)return;
- if(echoing)printf("\n");
- printf("syntax error: %s",s);
- SYNERR=1; /* this will stop YACC at its next call to yylex() */
- reset_lex();
-}
-
-acterror() /* likewise, but assumes error message output by caller */
-{ if(SYNERR)return;
- SYNERR=1; /* to stop YACC at next symbol */
- reset_lex();
-}
-
-mira_setup()
-{ extern word common_stdin,common_stdinb,cook_stdin;
- setupheap();
- tsetup();
- reset_pns();
- bigsetup();
- common_stdin= ap(READ,0);
- common_stdinb= ap(READBIN,0);
- cook_stdin=ap(readvals(0,0),OFFSIDE);
- nill= cons(CONST,NIL);
- Void=make_id("()");
- id_type(Void)=void_t;
- id_val(Void)=constructor(0,Void);
- message=make_id("sys_message");
- main_id=make_id("main"); /* change to magic scripts 19.11.2013 */
- concat=make_id("concat");
- diagonalise=make_id("diagonalise");
- standardout=constructor(0,"Stdout");
- indent_fn=make_id("indent");
- outdent_fn=make_id("outdent");
- listdiff_fn=make_id("listdiff");
- shownum1=make_id("shownum1");
- showbool=make_id("showbool");
- showchar=make_id("showchar");
- showlist=make_id("showlist");
- showstring=make_id("showstring");
- showparen=make_id("showparen");
- showpair=make_id("showpair");
- showvoid=make_id("showvoid");
- showfunction=make_id("showfunction");
- showabstract=make_id("showabstract");
- showwhat=make_id("showwhat");
- primlib(); } /* sets up predefined ids, not referred to by RULES */
-
-void dieclean() /* called if evaluation is interrupted - see RULES */
-{ printf("<<...interrupt>>\n");
-#ifndef NOSTATSONINT
- outstats(); /* suppress in presence of segfault on ^C with /count */
-#endif
- exit(0);
-}
-
-/* the function process() creates a process and waits for it to die -
- returning 1 in the child and 0 in the parent - it is used in the
- evaluation command (see MIRANDA RULES) */
-process()
-{ word pid;
- sighandler oldsig;
- oldsig = signal(SIGINT,SIG_IGN);
- /* do not let parent receive interrupts intended for child */
- if(pid=fork())
- { /* parent */
- word status; /* see man 2 exit, wait, signal */
- if(pid== -1)
- { perror("UNIX error - cannot create process");
- return(0);
- }
- while(pid!=wait(&status));
- /* low byte of status is termination state of child, next byte is the
- (low order byte of the) exit status */
- if(WIFSIGNALED(status)) /* abnormal termination status */
- { char *cd=status&0200?" (core dumped)":"";
- char *pc=""; /* "probably caused by stack overflow\n";*/
- switch(WTERMSIG(status))
- { case SIGBUS: printf("\n<<...bus error%s>>\n%s",cd,pc); break;
- case SIGSEGV: printf("\n<<...segmentation fault%s>>\n%s",cd,pc); break;
- default: printf("\n<<...uncaught signal %d>>\n",WTERMSIG(status));
- } }
- /*if(status >>= 8)printf("\n(exit status %d)\n",status); */
- (void)signal(SIGINT,oldsig); /* restore interrupt status */
- return(0); }
- else return(1); /* child */
-}
-
-/* Notice that the MIRANDA system has a two-level interrupt structure.
- 1) Each evaluation (see RULES) is an interruptible process.
- 2) If the command loop is interrupted outside an evaluation or during
- compilation it reverts to the top level prompt - see set_jmp and
- signal(reset) in commandloop() */
-
-primdef(n,v,t) /* used by "primlib", see below */
-char *n;
-word v,t;
-{ word x;
- x= make_id(n);
- primenv=cons(x,primenv);
- id_val(x)= v;
- id_type(x)=t; }
-
-predef(n,v,t) /* used by "privlib" and "stdlib", see below */
-char *n;
-word v,t;
-{ word x;
- x= make_id(n);
- addtoenv(x);
- id_val(x)= isconstructor(x)?constructor(v,x):v;
- id_type(x)=t;
-}
-
-primlib() /* called by "mira_setup", this routine enters
- the primitive identifiers into the primitive environment */
-{ primdef("num",make_typ(0,0,synonym_t,num_t),type_t);
- primdef("char",make_typ(0,0,synonym_t,char_t),type_t);
- primdef("bool",make_typ(0,0,synonym_t,bool_t),type_t);
- primdef("True",1,bool_t); /* accessible only to 'finger' */
- primdef("False",0,bool_t); /* likewise - FIX LATER */
-}
-
-privlib() /* called when compiling <prelude>, adds some
- internally defined identifiers to the environment */
-{ extern word ltchar;
- predef("offside",OFFSIDE,ltchar); /* used by `indent' in prelude */
- predef("changetype",I,wrong_t); /* wrong_t to prevent being typechecked */
- predef("first",HD,wrong_t);
- predef("rest",TL,wrong_t);
-/* the following added to make prelude compilable without stdenv */
- predef("code",CODE,undef_t);
- predef("concat",ap2(FOLDR,APPEND,NIL),undef_t);
- predef("decode",DECODE,undef_t);
- predef("drop",DROP,undef_t);
- predef("error",ERROR,undef_t);
- predef("filter",FILTER,undef_t);
- predef("foldr",FOLDR,undef_t);
- predef("hd",HD,undef_t);
- predef("map",MAP,undef_t);
- predef("shownum",SHOWNUM,undef_t);
- predef("take",TAKE,undef_t);
- predef("tl",TL,undef_t);
-}
-
-stdlib() /* called when compiling <stdenv>, adds some
- internally defined identifiers to the environment */
-{ predef("arctan",ARCTAN_FN,undef_t);
- predef("code",CODE,undef_t);
- predef("cos",COS_FN,undef_t);
- predef("decode",DECODE,undef_t);
- predef("drop",DROP,undef_t);
- predef("entier",ENTIER_FN,undef_t);
- predef("error",ERROR,undef_t);
- predef("exp",EXP_FN,undef_t);
- predef("filemode",FILEMODE,undef_t);
- predef("filestat",FILESTAT,undef_t); /* added Feb 91 */
- predef("foldl",FOLDL,undef_t);
- predef("foldl1",FOLDL1,undef_t); /* new at release 2 */
- predef("hugenum",sto_dbl(DBL_MAX),undef_t);
- /* max_normal() if present returns same value (see <math.h>) */
- predef("last",LIST_LAST,undef_t);
- predef("foldr",FOLDR,undef_t);
- predef("force",FORCE,undef_t);
- predef("getenv",GETENV,undef_t);
- predef("integer",INTEGER,undef_t);
- predef("log",LOG_FN,undef_t);
- predef("log10",LOG10_FN,undef_t); /* new at release 2 */
- predef("merge",MERGE,undef_t); /* new at release 2 */
- predef("numval",NUMVAL,undef_t);
- predef("read",STARTREAD,undef_t);
- predef("readb",STARTREADBIN,undef_t);
- predef("seq",SEQ,undef_t);
- predef("shownum",SHOWNUM,undef_t);
- predef("showhex",SHOWHEX,undef_t);
- predef("showoct",SHOWOCT,undef_t);
- predef("showfloat",SHOWFLOAT,undef_t); /* new at release 2 */
- predef("showscaled",SHOWSCALED,undef_t); /* new at release 2 */
- predef("sin",SIN_FN,undef_t);
- predef("sqrt",SQRT_FN,undef_t);
- predef("system",EXEC,undef_t); /* new at release 2 */
- predef("take",TAKE,undef_t);
- predef("tinynum",mktiny(),undef_t); /* new at release 2 */
- predef("zip2",ZIP,undef_t); /* new at release 2 */
-}
-
-mktiny()
-{ volatile
- double x=1.0,x1=x/2.0;
- while(x1>0.0)x=x1,x1/=2.0;
- return(sto_dbl(x));
-}
-/* min_subnormal() if present returns same value (see <math.h>) */
-
-size(x) /* measures the size of a compiled expression */
-word x;
-{ word s;
- s= 0;
- while(tag[x]==CONS||tag[x]==AP)
- { s= s+1+size(hd[x]);
- x= tl[x]; }
- return(s); }
-
-makedump()
-{ char *obf=linebuf;
- FILE *f;
- (void)strcpy(obf,current_script);
- (void)strcpy(obf+strlen(obf)-1,obsuffix);
- f=fopen(obf,"w");
- if(!f){ printf("WARNING: CANNOT WRITE TO %s\n",obf);
- if(strcmp(current_script,PRELUDE)==0||
- strcmp(current_script,STDENV)==0)
- printf(
- "TO FIX THIS PROBLEM PLEASE GET SUPER-USER TO EXECUTE `mira'\n");
- if(making&&!make_status)make_status=1;
- return; }
- /* printf("dumping to %s\n",obf); /* DEBUG */
- unlinkme=obf;
- /* fchmod(fileno(f),0666); /* to make dumps writeable by all */ /* no! */
- setprefix(current_script);
- dump_script(files,f);
- unlinkme=NULL;
- fclose(f);
-}
-
-undump(t) /* restore t from dump, or recompile if necessary */
-char *t;
-{ extern word BAD_DUMP,CLASHES;
- if(!normal(t)&&!initialising)return loadfile(t);
- /* except for prelude, only .m files have dumps */
- char obf[pnlim];
- FILE *f;
- sighandler oldsig;
- word flen=strlen(t);
- time_t t1=fm_time(t),t2;
- if(flen>pnlim)
- { printf("sorry, pathname too long (limit=%d): %s\n",pnlim,t);
- return; } /* if anyone complains, should remove this limit */
- (void)strcpy(obf,t);
- (void)strcpy(obf+flen-1,obsuffix);
- t2=fm_time(obf);
- if(t2&&!t1)t2=0,unlink(obf); /* dump is orphan - remove */
- if(!t2||t2<t1) /* dump is nonexistent or older than source - ignore */
- { loadfile(t); return; }
- f=fopen(obf,"r");
- if(!f){ printf("cannot open %s\n",obf); loadfile(t); return; }
- current_script=t;
- loading=1;
- oldfiles=NIL;
- unload();
-/*if(!initialising)printf("undumping from %s\n",obf); /* DEBUG */
- if(!initialising&&!making) /* ie this is the main script */
- sigflag=0,
- oldsig=signal(SIGINT,(sighandler)sigdefer);
- /* can't take interrupt during load_script */
- files=load_script(f,t,NIL,NIL,!making&!initialising);
- fclose(f);
- if(BAD_DUMP)
- { extern word *stackp,*dstack;
- unlink(obf); unload(); CLASHES=NIL; stackp=dstack;
- printf("warning: %s contains incorrect data (file removed)\n",obf);
- if(BAD_DUMP== -1)printf("(obsolete dump format)\n"); else
- if(BAD_DUMP==1)printf("(wrong source file)\n"); else
- printf("(error %d)\n",BAD_DUMP); }
- if(!initialising&&!making) /* restore interrupt handler */
- (void)signal(SIGINT,oldsig);
- if(sigflag)sigflag=0,(*oldsig)(); /* take deferred interrupt */
- /*if(!initialising)printf("%s undumped\n",obf); /* DEBUG */
- if(CLASHES!=NIL)
- { if(ideep==0)printf("cannot load %s ",obf),
- printlist("due to name clashes: ",alfasort(CLASHES));
- unload();
- loading=0;
- return; }
- if(BAD_DUMP||src_update())loadfile(t);/* any sources modified since dump? */
- else
- if(initialising)
- { if(ND!=NIL||files==NIL) /* error in dump of PRELUDE */
- fprintf(stderr,"panic: %s contains errors\n",obf),
- exit(1); } /* beware of dangling else ! (whence {}) */
- else
- if(verbosity||magic||mkexports) /* for less silent making s/mkexports/making/ */
- if(files==NIL)printf("%s contains syntax error\n",t); else
- if(ND!=NIL)printf("%s contains undefined names or type errors\n",t); else
- if(!making&&!magic)printf("%s\n",t); /* added &&!magic 26.11.2019 */
- if(!files==NIL&&!making&!initialising)unfixexports();
- loading=0;
-}
-
-unlinkx(t) /* remove orphaned .x file */
-char *t;
-{ char *obf=linebuf;
- (void)strcpy(obf,t);
- (void)strcpy(obf+strlen(t)-1,obsuffix);
- if(!stat(obf,&buf))unlink(obf);
-}
-
-void fpe_error()
-{ if(compiling)
- { (void)signal(SIGFPE,(sighandler)fpe_error); /* reset SIGFPE trap */
-#ifdef sparc8
- fpsetmask(commonmask); /* to clear sticky bits */
-#endif
- syntax("floating point number out of range\n");
- SYNERR=0; longjmp(env,1);
- /* go straight back to commandloop - necessary because decoding very
- large numbers can cause huge no. of repeated SIGFPE exceptions */
- }
- else printf("\nFLOATING POINT OVERFLOW\n"),exit(1);
-}
-
-char fbuf[512];
-
-filecopy(fil) /* copy the file "fil" to standard out */
-char *fil;
-{ word in=open(fil,0),n;
- if(in== -1)return;
- while((n=read(in,fbuf,512))>0)write(1,fbuf,n);
- close(in);
-}
-
-filecp(fil1,fil2) /* copy file "fil1" to "fil2" (like `cp') */
-char *fil1,*fil2;
-{ word in=open(fil1,0),n;
- word out=creat(fil2,0644);
- if(in== -1||out== -1)return;
- while((n=read(in,fbuf,512))>0)write(out,fbuf,n);
- close(in);
- close(out);
-}
-
-/* to define winsize and TIOCGWINSZ for twidth() */
-#include <termios.h>
-#include <sys/ioctl.h>
-
-twidth() /* returns width (in columns) of current window, less 2 */
-{
-#ifdef TIOCGWINSZ
- static struct winsize tsize;
- ioctl(fileno(stdout),TIOCGWINSZ,&tsize);
- return (tsize.ws_col==0)?78:tsize.ws_col-2;
-#else
-#error TIOCGWINSZ undefined
-/* porting note: if you cannot find how to enable use of TIOCGWINSZ
- comment out the above #error line */
- return 78; /* give up, we will assume screen width to be 80 */
-#endif
-}
-
-/* was called when Miranda starts up and before /help, /aux
- to clear screen - suppressed Oct 2019 */
-/* clrscr()
-{ printf("\x1b[2J\x1b[H"); fflush(stdout);
-} */
-
-/* the following code tests if we are in a UTF-8 locale */
-
-#ifdef CYGWIN
-#include <windows.h>
-
-utf8test()
-{ return GetACP()==65001; }
-/* codepage 1252 is Windows version of Latin-1; 65001 is UTF-8 */
-
-#else
-
-utf8test()
-{ char *lang;
- if(!(lang=getenv("LC_CTYPE")))
- lang=getenv("LANG");
- if(lang&&
- (strstr(lang,"UTF-8")||strstr(lang,"UTF8")||
- strstr(lang,"utf-8")||strstr(lang,"utf8")))
- return 1;
- return 0;
-}
-#endif
-
-/* end of MIRANDA STEER */
-