Mercurial > hg > jgplsrc
view io.c @ 0:e0bbaa717f41 draft default tip
lol J
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Mon, 25 Nov 2013 11:56:30 -0500 |
parents | |
children |
line wrap: on
line source
/* Copyright 1990-2011, Jsoftware Inc. All rights reserved. */ /* License in license.txt. */ /* */ /* Input/Output */ #ifdef _WIN32 #include <windows.h> #include <winbase.h> #else #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #define _stdcall #endif #include "j.h" #include "d.h" void jtwri(J jt,I type,C*p,I m,C*s){C buf[1024],*t=jt->outseq,*v=buf;I c,d,e,n; if(jt->tostdout){ c=strlen(p); /* prompt */ e=strlen(t); /* end-of-line */ n=sizeof(buf)-(c+e+1); /* main text */ d=m>n?n-3:m; memcpy(v,p,c); v+=c; memcpy(v,s,d); v+=d; if(m>n){memcpy(v,"...",3L); v+=3;} memcpy(v,t,e); v+=e; *v=0; jsto(jt,type,buf); }} static void jtwrf(J jt,I n,C*v,F f){C*u,*x;I j=0,m; while(n>j){ u=j+v; m=(x=memchr(u,CLF,n-j))?1+x-u:n-j; fwrite(u,sizeof(C),m,f); j+=m; }} A jtinpl(J jt,B b,I n,C*s){C c;I k=0; if(n&&(c=*(s+n-1),CLF==c||CCR==c))--n; ASSERT(!*jt->adbreak,EVINPRUPT); if(!b){ /* 1==b means literal input */ if(n&&COFF==*(s+n-1))joff(zero); c=jt->bx[9]; if(c<0)DO(n, if(' '!=s[i]&&c!=s[i]){k=i; break;}); } R str(n-k,s+k); } static I advl(I j,I n,C*s){B b;C c,*v; v=j+s; DO(n-j, c=*v++; b=c==CCR; if(b||c==CLF)R j+1+i+(b&&CLF==*v);); R n; } /* advance one line on CR, CRLF, or LF */ void breakclose(J jt); static C* nfeinput(J jt,C* s){A y; jt->breakignore=1; y=exec1(cstr(s)); jt->breakignore=0; if(!y){breakclose(jt);exit(2);} /* J input verb failed */ jtwri(jt,MTYOLOG,"",strlen(CAV(y)),CAV(y)); return CAV(y); /* don't combine with previous line! CAV runs (x) 2 times! */ } A jtjgets(J jt,C*p){A y;B b;C*v;I j,k,m,n;UC*s; *jt->adbreak=0; if(b=1==*p)p=""; /* 1 means literal input */ if(jt->dcs){ ++jt->dcs->dcn; j=jt->dcs->dci; y=jt->dcs->dcy; n=AN(y); s=UAV(y); RZ(j<n); jt->dcs->dcj=k=j; jt->dcs->dci=j=advl(j,n,s); m=j-k; if(m&&32>s[k+m-1])--m; if(m&&32>s[k+m-1])--m; jtwri(jt,MTYOLOG,p,m,k+s); R inpl(b,m,k+s); } /* J calls for input in 3 cases: debug suspension for normal input n : 0 input lines up to terminating ) 1!:1[1 read from keyboard */ showerr(); if(jt->nfe) v=nfeinput(jt,*p?"input_jfe_' '":"input_jfe_''"); else{ ASSERT(jt->sminput,EVBREAK); v=((inputtype)(jt->sminput))(jt,p); } R inpl(b,(I)strlen(v),v); } extern C breakdata; #if SYS&SYS_UNIX void breakclose(J jt) { if(jt->adbreak==&breakdata) return; munmap(jt->adbreak,1); jt->adbreak=&breakdata; close(jt->breakfh); jt->breakfh=0; unlink(jt->breakfn); *jt->breakfn=0; } #else void breakclose(J jt) { if(jt->adbreak==&breakdata) return; UnmapViewOfFile(jt->adbreak); jt->adbreak=&breakdata; CloseHandle(jt->breakmh); jt->breakmh=0; CloseHandle(jt->breakfh); jt->breakfh=0; #if SY_WINCE DeleteFile(tounibuf(jt->breakfn)); #else DeleteFile(jt->breakfn); #endif *jt->breakfn=0; } #endif F1(jtjoff){I x; RZ(w); x=i0(w); breakclose(jt); if(jt->sesm)jsto(jt, MTYOEXIT,(C*)x); exit((int)x); R 0; } #if (SYS & SYS_SESM) I jdo(J jt, C* lp){I e,old;A x; jt->jerr=0; jt->etxn=0; /* clear old errors */ old=jt->tbase+jt->ttop; *jt->adbreak=0; x=inpl(0,(I)strlen(lp),lp); while(jt->iepdo&&jt->iep){jt->iepdo=0; immex(jt->iep); jt->jerr=0; tpop(old);} if(!jt->jerr)immex(x); e=jt->jerr; jt->jerr=0; if(e&&DBERRCAP==jt->db&&jt->dbtrap){ jt->db=0; immex(jt->dbtrap); jt->jerr=0; } while(jt->iepdo&&jt->iep){jt->iepdo=0; immex(jt->iep); jt->jerr=0; tpop(old);} showerr(); spfree(); tpop(old); R e; } #define SZINT ((I)sizeof(int)) DF1(jtwd){A z=0;C*p=0;D*pd;I e,*pi,t;V*sv; F1RANK(1,jtwd,self); RZ(w); ASSERT(2>AR(w),EVRANK); sv=VAV(self); t=i0(sv->g); if(t>=2000 && t<3000 && AN(w) && LIT!=AT(w) && C2T!=AT(w) && INT!=AT(w)) { switch(AT(w)) { case B01: RZ(w=vi(w));break; case FL: pd=DAV(w); GA(w,INT,AN(w),AR(w),0); pi=AV(w); DO(AN(w),*pi++=(I)(jfloor(0.5+*pd++));); break; default: ASSERT(0,EVDOMAIN); } } // t is 11!:t and w is wd argument e=jt->smdowd ? ((dowdtype)(jt->smdowd))(jt, (int)t, w, &z) : EVDOMAIN; if(!e) R mtm; // e==0 is MTM if(e==-1) R z; // e---1 is zp ASSERT(e<=0,e); // e>=0 is EVDOMAIN etc RZ(z=df1(z,cut(ds(CBOX),num[-2]))); // e==-2 is lit pairs R reshape(v2(AN(z)/2,2L),z); } C* getlocale(J jt){A y=locname(mtv); y=*AAV(y); R CAV(y);} static char breaknone=0; B jtsesminit(J jt){jt->adbreak=&breakdata; R 1;} #endif int _stdcall JDo(J jt, char* lp){int r; r=(int)jdo(jt,lp); while(jt->nfe) r=(int)jdo(jt,nfeinput(jt,"input_jfe_' '")); R r; } /* socket protocol CMDGET name */ A _stdcall JGetA(J jt, I n, C* name){A x; jt->jerr=0; RZ(x=symbrdlock(nfs(n,name))); ASSERT(!(FUNC&AT(x)),EVDOMAIN); R binrep1(x); } /* socket protocol CMDSET */ I _stdcall JSetA(J jt,I n,C* name,I dlen,C* d){I old; jt->jerr=0; if(!vnm(n,name)) R EVILNAME; old=jt->tbase+jt->ttop; symbis(nfs(n,name),jtunbin(jt,str(dlen,d)),jt->global); tpop(old); R jt->jerr; } /* set jclient callbacks */ void _stdcall JSM(J jt, void* callbacks[]) { jt->smoutput = (outputtype)callbacks[0]; jt->smdowd = (dowdtype)callbacks[1]; jt->sminput = (inputtype)callbacks[2]; jt->sm = (I)callbacks[4]; } C* _stdcall JGetLocale(J jt){return getlocale(jt);} A _stdcall Jga(J jt, I t, I n, I r, I*s){ return ga(t, n, r, s); } void oleoutput(J jt, I n, char* s); /* SY_WIN32 only */ /* jsto - display output in output window */ void jsto(J jt,I type,C*s){C e;I ex; if(jt->nfe) { C q[]="0 output_jfe_ (15!:18)0"; q[0]+=(C)type; jt->mtyostr=s; e=jt->jerr; ex=jt->etxn; jt->jerr=0; jt->etxn=0; jt->breakignore=1;exec1(cstr(q));jt->breakignore=0; jt->jerr=e; jt->etxn=ex; }else{ if(jt->smoutput) ((outputtype)(jt->smoutput))(jt,(int)type,s); #if SY_WIN32 && !SY_WINCE if(type & MTYOFM) oleoutput(jt,strlen(s),s); /* save output for ole */ #endif }} #if SYS&SYS_UNIX J JInit(void){ J jt; /* jtglobinit must be done once when dll is first loaded Windows does it in dll load routine - thread safe Unix does it here once, but this is not thread safe */ static J g_jt=0; if(!g_jt) { g_jt=malloc(sizeof(JST)); if(!g_jt) R 0; memset(g_jt,0,sizeof(JST)); if(!jtglobinit(g_jt)){free(g_jt);g_jt=0; R 0;} } RZ(jt=malloc(sizeof(JST))); memset(jt,0,sizeof(JST)); if(!jtjinit2(jt,0,0)){free(jt); R 0;}; R jt; } int JFree(J jt){return 0;} #endif F1(jtbreakfnq){ ASSERTMTV(w); R cstr(jt->breakfn); } F1(jtbreakfns){A z;I *fh,*mh; void* ad; ASSERT(1>=AR(w),EVRANK); ASSERT(!AN(w)||AT(w)&LIT,EVDOMAIN); ASSERT(AN(w)<NPATH,EVDOMAIN); if(!strcmp(jt->breakfn,CAV(w))) R mtm; breakclose(jt); #if SYS&SYS_UNIX fh=(I*)(I)open(CAV(w),O_RDWR); ASSERT(-1!=(I)fh,EVDOMAIN); ad=mmap(0,1,PROT_READ|PROT_WRITE,MAP_SHARED,(I)fh,0); if(0==ad){close(fh); ASSERT(0,EVDOMAIN);} #else RZ(z=toutf16x(w)); fh=CreateFileW(USAV(z),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0); ASSERT(INVALID_HANDLE_VALUE!=fh,EVDOMAIN); mh=CreateFileMapping(fh,0,PAGE_READWRITE,0,1,0); if(0==mh){CloseHandle(fh); ASSERT(0,EVDOMAIN);} ad=MapViewOfFile(mh,FILE_MAP_WRITE,0,0,0); if(0==ad){CloseHandle(mh); CloseHandle(fh); ASSERT(0,EVDOMAIN);} #endif strcpy(jt->breakfn,CAV(w)); jt->breakfh=fh; jt->breakmh=mh; jt->adbreak=ad; R mtm; } int valid(C* psrc, C* psnk) { while(*psrc == ' ') ++psrc; if(!isalpha(*psrc)) return EVILNAME; while(isalnum(*psrc) || *psrc=='_') *psnk++ = *psrc++; while(*psrc == ' ') ++psrc; if(*psrc) return EVILNAME; *psnk = 0; return 0; } int _stdcall JGetM(J jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata) { A a; char gn[256]; if(strlen(name) >= sizeof(gn)) return EVILNAME; if(valid(name, gn)) return EVILNAME; RZ(a=symbrdlock(nfs(strlen(gn),gn))); if(FUNC&AT(a))R EVDOMAIN; *jtype = AT(a); *jrank = AR(a); *jshape = (I)AS(a); *jdata = (I)AV(a); return 0; } static int setterm(J jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata) { A a; I k=1,i,n; char gn[256]; switch(*jtype) { case LIT: case B01: n = sizeof(char); break; case INT: n = sizeof(I); break; case FL: n = sizeof(double); break; case CMPX: n = 2 * sizeof(double); break; default: return EVDOMAIN; } // validate name if(strlen(name) >= sizeof(gn)) return EVILNAME; if(valid(name, gn)) return EVILNAME; for(i=0; i<*jrank; ++i) k *= ((I*)(*jshape))[i]; a = ga(*jtype, k, *jrank, (I*)*jshape); if(!a) return EVWSFULL; memcpy(AV(a), (void*)*jdata, n*k); jset(gn, a); return jt->jerr; } int _stdcall JSetM(J jt, C* name, I* jtype, I* jrank, I* jshape, I* jdata) { int er; PROLOG; er = setterm(jt, name, jtype, jrank, jshape, jdata); tpop(_ttop); return er; } #define EDCBUSY -1 #define EDCEXE -2 C* esub(J jt, I ec) { if(!ec) return ""; if(ec == EDCBUSY) return "busy with previous input"; if(ec == EDCEXE) return "not supported in EXE server"; if(ec > NEVM || ec < 0) return "unknown error"; return (C*)AV(*(ec+AAV(jt->evm))); } int _stdcall JErrorTextM(J jt, I ec, I* p) { *p = (I)esub(jt, ec); return 0; }