diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libinterp/runt.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libinterp/runt.c')
| -rw-r--r-- | libinterp/runt.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/libinterp/runt.c b/libinterp/runt.c new file mode 100644 index 00000000..81a5490b --- /dev/null +++ b/libinterp/runt.c @@ -0,0 +1,496 @@ +#include "lib9.h" +#include "isa.h" +#include "interp.h" +#include "runt.h" +#include "sysmod.h" +#include "raise.h" + + +static int utfnleng(char*, int, int*); + +void +sysmodinit(void) +{ + sysinit(); + builtinmod("$Sys", Sysmodtab, Sysmodlen); +} + +int +xprint(Prog *xp, void *vfp, void *vva, String *s1, char *buf, int n) +{ + WORD i; + void *p; + LONG bg; + Type *t; + double d; + String *ss; + ulong *ptr; + uchar *fp, *va; + int nc, c, isbig, isr, sip; + char *b, *eb, *f, fmt[32]; + Rune r; + + fp = vfp; + va = vva; + + sip = 0; + isr = 0; + if(s1 == H) + return 0; + nc = s1->len; + if(nc < 0) { + nc = -nc; + isr = 1; + } + + b = buf; + eb = buf+n-1; + while(nc--) { + c = isr ? s1->Srune[sip] : s1->Sascii[sip]; + sip++; + if(c != '%') { + if(b < eb) { + if(c < Runeself) + *b++ = c; + else + b += snprint(b, eb-b, "%C", c); + } + continue; + } + f = fmt; + *f++ = c; + isbig = 0; + while(nc--) { + c = isr ? s1->Srune[sip] : s1->Sascii[sip]; + sip++; + *f++ = c; + *f = '\0'; + switch(c) { + default: + continue; + case '*': + i = *(WORD*)va; + f--; + f += snprint(f, sizeof(fmt)-(f-fmt), "%d", i); + va += IBY2WD; + continue; + case 'b': + f[-1] = 'l'; + *f++ = 'l'; + *f = '\0'; + isbig = 1; + continue; + case '%': + if(b < eb) + *b++ = '%'; + break; + case 'q': + case 's': + ss = *(String**)va; + va += IBY2WD; + if(ss == H) + p = ""; + else + if(ss->len < 0) { + f[-1] += 'A'-'a'; + ss->Srune[-ss->len] = L'\0'; + p = ss->Srune; + } + else { + ss->Sascii[ss->len] = '\0'; + p = ss->Sascii; + } + b += snprint(b, eb-b, fmt, p); + break; + case 'E': + f--; + r = 0x00c9; /* L'É' */ + f += runetochar(f, &r); /* avoid clash with ether address */ + *f = '\0'; + /* fall through */ + case 'e': + case 'f': + case 'g': + case 'G': + while((va - fp) & (sizeof(REAL)-1)) + va++; + d = *(REAL*)va; + b += snprint(b, eb-b, fmt, d); + va += sizeof(REAL); + break; + case 'd': + case 'o': + case 'x': + case 'X': + case 'c': + if(isbig) { + while((va - fp) & (IBY2LG-1)) + va++; + bg = *(LONG*)va; + b += snprint(b, eb-b, fmt, bg); + va += IBY2LG; + } + else { + i = *(WORD*)va; + /* always a unicode character */ + if(c == 'c') + f[-1] = 'C'; + b += snprint(b, eb-b, fmt, i); + va += IBY2WD; + } + break; + case 'r': + b = syserr(b, eb, xp); + break; +/* Debugging formats - may disappear */ + case 'H': + ptr = *(ulong**)va; + c = -1; + t = nil; + if(ptr != H) { + c = D2H(ptr)->ref; + t = D2H(ptr)->t; + } + b += snprint(b, eb-b, "%d.%.8lux", c, (ulong)t); + va += IBY2WD; + break; + } + break; + } + } + return b - buf; +} + +int +bigxprint(Prog *xp, void *vfp, void *vva, String *s1, char **buf, int s) +{ + char *b; + int m, n; + + m = s; + for (;;) { + m *= 2; + b = malloc(m); + if (b == nil) + error(exNomem); + n = xprint(xp, vfp, vva, s1, b, m); + if (n < m-UTFmax-2) + break; + free(b); + } + *buf = b; + return n; +} + +void +Sys_sprint(void *fp) +{ + int n; + char buf[256], *b = buf; + F_Sys_sprint *f; + + f = fp; + n = xprint(currun(), f, &f->vargs, f->s, buf, sizeof(buf)); + if (n >= sizeof(buf)-UTFmax-2) + n = bigxprint(currun(), f, &f->vargs, f->s, &b, sizeof(buf)); + b[n] = '\0'; + retstr(b, f->ret); + if (b != buf) + free(b); +} + +void +Sys_aprint(void *fp) +{ + int n; + char buf[256], *b = buf; + F_Sys_aprint *f; + + f = fp; + n = xprint(currun(), f, &f->vargs, f->s, buf, sizeof(buf)); + if (n >= sizeof(buf)-UTFmax-2) + n = bigxprint(currun(), f, &f->vargs, f->s, &b, sizeof(buf)); + destroy(*f->ret); + *f->ret = mem2array(b, n); + if (b != buf) + free(b); +} + +static int +tokdelim(int c, String *d) +{ + int l; + char *p; + Rune *r; + + l = d->len; + if(l < 0) { + l = -l; + for(r = d->Srune; l != 0; l--) + if(*r++ == c) + return 1; + return 0; + } + for(p = d->Sascii; l != 0; l--) + if(*p++ == c) + return 1; + return 0; +} + +void +Sys_tokenize(void *fp) +{ + String *s, *d; + List **h, *l, *nl; + F_Sys_tokenize *f; + int n, c, nc, first, last, srune; + + f = fp; + s = f->s; + d = f->delim; + + if(s == H || d == H) { + f->ret->t0 = 0; + destroy(f->ret->t1); + f->ret->t1 = H; + return; + } + + n = 0; + l = H; + h = &l; + first = 0; + srune = 0; + + nc = s->len; + if(nc < 0) { + nc = -nc; + srune = 1; + } + + while(first < nc) { + while(first < nc) { + c = srune ? s->Srune[first] : s->Sascii[first]; + if(tokdelim(c, d) == 0) + break; + first++; + } + + last = first; + + while(last < nc) { + c = srune ? s->Srune[last] : s->Sascii[last]; + if(tokdelim(c, d) != 0) + break; + last++; + } + + if(first == last) + break; + + nl = cons(IBY2WD, h); + nl->tail = H; + nl->t = &Tptr; + Tptr.ref++; + *(String**)nl->data = slicer(first, last, s); + h = &nl->tail; + + first = last; + n++; + } + + f->ret->t0 = n; + destroy(f->ret->t1); + f->ret->t1 = l; +} + +void +Sys_utfbytes(void *fp) +{ + Array *a; + int nbyte; + F_Sys_utfbytes *f; + + f = fp; + a = f->buf; + if(a == H || (UWORD)f->n > a->len) + error(exBounds); + + utfnleng((char*)a->data, f->n, &nbyte); + *f->ret = nbyte; +} + +void +Sys_byte2char(void *fp) +{ + Rune r; + char *p; + int n, w; + Array *a; + F_Sys_byte2char *f; + + f = fp; + a = f->buf; + n = f->n; + if(a == H || (UWORD)n >= a->len) + error(exBounds); + r = a->data[n]; + if(r < Runeself){ + f->ret->t0 = r; + f->ret->t1 = 1; + f->ret->t2 = 1; + return; + } + p = (char*)a->data+n; + if(n+UTFmax <= a->len || fullrune(p, a->len-n)) + w = chartorune(&r, p); + else { + /* insufficient data */ + f->ret->t0 = Runeerror; + f->ret->t1 = 0; + f->ret->t2 = 0; + return; + } + if(r == Runeerror && w==1){ /* encoding error */ + f->ret->t0 = Runeerror; + f->ret->t1 = 1; + f->ret->t2 = 0; + return; + } + f->ret->t0 = r; + f->ret->t1 = w; + f->ret->t2 = 1; +} + +void +Sys_char2byte(void *fp) +{ + F_Sys_char2byte *f; + Array *a; + int n, c; + Rune r; + + f = fp; + a = f->buf; + n = f->n; + c = f->c; + if(a == H || (UWORD)n>=a->len) + error(exBounds); + if(c<0 || c>=(1<<16)) + c = Runeerror; + if(c < Runeself){ + a->data[n] = c; + *f->ret = 1; + return; + } + r = c; + if(n+UTFmax<=a->len || runelen(c)<=a->len-n){ + *f->ret = runetochar((char*)a->data+n, &r); + return; + } + *f->ret = 0; +} + +Module * +builtinmod(char *name, void *vr, int rlen) +{ + Runtab *r = vr; + Type *t; + Module *m; + Link *l; + + m = newmod(name); + if(rlen == 0){ + while(r->name){ + rlen++; + r++; + } + r = vr; + } + l = m->ext = (Link*)malloc((rlen+1)*sizeof(Link)); + if(l == nil){ + freemod(m); + return nil; + } + while(r->name) { + t = dtype(freeheap, r->size, r->map, r->np); + runtime(m, l, r->name, r->sig, r->fn, t); + r++; + l++; + } + l->name = nil; + return m; +} + +void +retnstr(char *s, int n, String **d) +{ + String *s1; + + s1 = H; + if(n != 0) + s1 = c2string(s, n); + destroy(*d); + *d = s1; +} + +void +retstr(char *s, String **d) +{ + String *s1; + + s1 = H; + if(s != nil) + s1 = c2string(s, strlen(s)); + destroy(*d); + *d = s1; +} + +Array* +mem2array(void *va, int n) +{ + Heap *h; + Array *a; + + if(n < 0) + n = 0; + h = nheap(sizeof(Array)+n); + h->t = &Tarray; + h->t->ref++; + a = H2D(Array*, h); + a->t = &Tbyte; + Tbyte.ref++; + a->len = n; + a->root = H; + a->data = (uchar*)a+sizeof(Array); + if(va != 0) + memmove(a->data, va, n); + + return a; +} + +static int +utfnleng(char *s, int nb, int *ngood) +{ + int c; + long n; + Rune rune; + char *es, *starts; + + starts = s; + es = s+nb; + for(n = 0; s < es; n++) { + c = *(uchar*)s; + if(c < Runeself) + s++; + else { + if(s+UTFmax<=es || fullrune(s, es-s)) + s += chartorune(&rune, s); + else + break; + } + } + if(ngood) + *ngood = s-starts; + return n; +} |
