ref: 7a7dfee4fab3e9a725422edff93251ef0a717492
dir: /libinterp/runt.c/
#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>=Runemax)
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;
}