1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "runt.h"
5 #include "sysmod.h"
6 #include "raise.h"
7
8
9 static int utfnleng(char*, int, int*);
10
11 void
sysmodinit(void)12 sysmodinit(void)
13 {
14 sysinit();
15 builtinmod("$Sys", Sysmodtab, Sysmodlen);
16 }
17
18 int
xprint(Prog * xp,void * vfp,void * vva,String * s1,char * buf,int n)19 xprint(Prog *xp, void *vfp, void *vva, String *s1, char *buf, int n)
20 {
21 WORD i;
22 void *p;
23 LONG bg;
24 Type *t;
25 double d;
26 String *ss;
27 ulong *ptr;
28 uchar *fp, *va;
29 int nc, c, isbig, isr, sip;
30 char *b, *eb, *f, fmt[32];
31 Rune r;
32
33 fp = vfp;
34 va = vva;
35
36 sip = 0;
37 isr = 0;
38 if(s1 == H)
39 return 0;
40 nc = s1->len;
41 if(nc < 0) {
42 nc = -nc;
43 isr = 1;
44 }
45
46 b = buf;
47 eb = buf+n-1;
48 while(nc--) {
49 c = isr ? s1->Srune[sip] : s1->Sascii[sip];
50 sip++;
51 if(c != '%') {
52 if(b < eb) {
53 if(c < Runeself)
54 *b++ = c;
55 else
56 b += snprint(b, eb-b, "%C", c);
57 }
58 continue;
59 }
60 f = fmt;
61 *f++ = c;
62 isbig = 0;
63 while(nc--) {
64 c = isr ? s1->Srune[sip] : s1->Sascii[sip];
65 sip++;
66 *f++ = c;
67 *f = '\0';
68 switch(c) {
69 default:
70 continue;
71 case '*':
72 i = *(WORD*)va;
73 f--;
74 f += snprint(f, sizeof(fmt)-(f-fmt), "%d", i);
75 va += IBY2WD;
76 continue;
77 case 'b':
78 f[-1] = 'l';
79 *f++ = 'l';
80 *f = '\0';
81 isbig = 1;
82 continue;
83 case '%':
84 if(b < eb)
85 *b++ = '%';
86 break;
87 case 'q':
88 case 's':
89 ss = *(String**)va;
90 va += IBY2WD;
91 if(ss == H)
92 p = "";
93 else
94 if(ss->len < 0) {
95 f[-1] += 'A'-'a';
96 ss->Srune[-ss->len] = L'\0';
97 p = ss->Srune;
98 }
99 else {
100 ss->Sascii[ss->len] = '\0';
101 p = ss->Sascii;
102 }
103 b += snprint(b, eb-b, fmt, p);
104 break;
105 case 'E':
106 f--;
107 r = 0x00c9; /* L'É' */
108 f += runetochar(f, &r); /* avoid clash with ether address */
109 *f = '\0';
110 /* fall through */
111 case 'e':
112 case 'f':
113 case 'g':
114 case 'G':
115 while((va - fp) & (sizeof(REAL)-1))
116 va++;
117 d = *(REAL*)va;
118 b += snprint(b, eb-b, fmt, d);
119 va += sizeof(REAL);
120 break;
121 case 'd':
122 case 'o':
123 case 'x':
124 case 'X':
125 case 'c':
126 if(isbig) {
127 while((va - fp) & (IBY2LG-1))
128 va++;
129 bg = *(LONG*)va;
130 b += snprint(b, eb-b, fmt, bg);
131 va += IBY2LG;
132 }
133 else {
134 i = *(WORD*)va;
135 /* always a unicode character */
136 if(c == 'c')
137 f[-1] = 'C';
138 b += snprint(b, eb-b, fmt, i);
139 va += IBY2WD;
140 }
141 break;
142 case 'r':
143 b = syserr(b, eb, xp);
144 break;
145 /* Debugging formats - may disappear */
146 case 'H':
147 ptr = *(ulong**)va;
148 c = -1;
149 t = nil;
150 if(ptr != H) {
151 c = D2H(ptr)->ref;
152 t = D2H(ptr)->t;
153 }
154 b += snprint(b, eb-b, "%d.%.8lux", c, (ulong)t);
155 va += IBY2WD;
156 break;
157 }
158 break;
159 }
160 }
161 return b - buf;
162 }
163
164 int
bigxprint(Prog * xp,void * vfp,void * vva,String * s1,char ** buf,int s)165 bigxprint(Prog *xp, void *vfp, void *vva, String *s1, char **buf, int s)
166 {
167 char *b;
168 int m, n;
169
170 m = s;
171 for (;;) {
172 m *= 2;
173 b = malloc(m);
174 if (b == nil)
175 error(exNomem);
176 n = xprint(xp, vfp, vva, s1, b, m);
177 if (n < m-UTFmax-2)
178 break;
179 free(b);
180 }
181 *buf = b;
182 return n;
183 }
184
185 void
Sys_sprint(void * fp)186 Sys_sprint(void *fp)
187 {
188 int n;
189 char buf[256], *b = buf;
190 F_Sys_sprint *f;
191
192 f = fp;
193 n = xprint(currun(), f, &f->vargs, f->s, buf, sizeof(buf));
194 if (n >= sizeof(buf)-UTFmax-2)
195 n = bigxprint(currun(), f, &f->vargs, f->s, &b, sizeof(buf));
196 b[n] = '\0';
197 retstr(b, f->ret);
198 if (b != buf)
199 free(b);
200 }
201
202 void
Sys_aprint(void * fp)203 Sys_aprint(void *fp)
204 {
205 int n;
206 char buf[256], *b = buf;
207 F_Sys_aprint *f;
208
209 f = fp;
210 n = xprint(currun(), f, &f->vargs, f->s, buf, sizeof(buf));
211 if (n >= sizeof(buf)-UTFmax-2)
212 n = bigxprint(currun(), f, &f->vargs, f->s, &b, sizeof(buf));
213 destroy(*f->ret);
214 *f->ret = mem2array(b, n);
215 if (b != buf)
216 free(b);
217 }
218
219 static int
tokdelim(int c,String * d)220 tokdelim(int c, String *d)
221 {
222 int l;
223 char *p;
224 Rune *r;
225
226 l = d->len;
227 if(l < 0) {
228 l = -l;
229 for(r = d->Srune; l != 0; l--)
230 if(*r++ == c)
231 return 1;
232 return 0;
233 }
234 for(p = d->Sascii; l != 0; l--)
235 if(*p++ == c)
236 return 1;
237 return 0;
238 }
239
240 void
Sys_tokenize(void * fp)241 Sys_tokenize(void *fp)
242 {
243 String *s, *d;
244 List **h, *l, *nl;
245 F_Sys_tokenize *f;
246 int n, c, nc, first, last, srune;
247
248 f = fp;
249 s = f->s;
250 d = f->delim;
251
252 if(s == H || d == H) {
253 f->ret->t0 = 0;
254 destroy(f->ret->t1);
255 f->ret->t1 = H;
256 return;
257 }
258
259 n = 0;
260 l = H;
261 h = &l;
262 first = 0;
263 srune = 0;
264
265 nc = s->len;
266 if(nc < 0) {
267 nc = -nc;
268 srune = 1;
269 }
270
271 while(first < nc) {
272 while(first < nc) {
273 c = srune ? s->Srune[first] : s->Sascii[first];
274 if(tokdelim(c, d) == 0)
275 break;
276 first++;
277 }
278
279 last = first;
280
281 while(last < nc) {
282 c = srune ? s->Srune[last] : s->Sascii[last];
283 if(tokdelim(c, d) != 0)
284 break;
285 last++;
286 }
287
288 if(first == last)
289 break;
290
291 nl = cons(IBY2WD, h);
292 nl->tail = H;
293 nl->t = &Tptr;
294 Tptr.ref++;
295 *(String**)nl->data = slicer(first, last, s);
296 h = &nl->tail;
297
298 first = last;
299 n++;
300 }
301
302 f->ret->t0 = n;
303 destroy(f->ret->t1);
304 f->ret->t1 = l;
305 }
306
307 void
Sys_utfbytes(void * fp)308 Sys_utfbytes(void *fp)
309 {
310 Array *a;
311 int nbyte;
312 F_Sys_utfbytes *f;
313
314 f = fp;
315 a = f->buf;
316 if(a == H || (UWORD)f->n > a->len)
317 error(exBounds);
318
319 utfnleng((char*)a->data, f->n, &nbyte);
320 *f->ret = nbyte;
321 }
322
323 void
Sys_byte2char(void * fp)324 Sys_byte2char(void *fp)
325 {
326 Rune r;
327 char *p;
328 int n, w;
329 Array *a;
330 F_Sys_byte2char *f;
331
332 f = fp;
333 a = f->buf;
334 n = f->n;
335 if(a == H || (UWORD)n >= a->len)
336 error(exBounds);
337 r = a->data[n];
338 if(r < Runeself){
339 f->ret->t0 = r;
340 f->ret->t1 = 1;
341 f->ret->t2 = 1;
342 return;
343 }
344 p = (char*)a->data+n;
345 if(n+UTFmax <= a->len || fullrune(p, a->len-n))
346 w = chartorune(&r, p);
347 else {
348 /* insufficient data */
349 f->ret->t0 = Runeerror;
350 f->ret->t1 = 0;
351 f->ret->t2 = 0;
352 return;
353 }
354 if(r == Runeerror && w==1){ /* encoding error */
355 f->ret->t0 = Runeerror;
356 f->ret->t1 = 1;
357 f->ret->t2 = 0;
358 return;
359 }
360 f->ret->t0 = r;
361 f->ret->t1 = w;
362 f->ret->t2 = 1;
363 }
364
365 void
Sys_char2byte(void * fp)366 Sys_char2byte(void *fp)
367 {
368 F_Sys_char2byte *f;
369 Array *a;
370 int n, c;
371 Rune r;
372
373 f = fp;
374 a = f->buf;
375 n = f->n;
376 c = f->c;
377 if(a == H || (UWORD)n>=a->len)
378 error(exBounds);
379 if(c<0 || c>=Runemax)
380 c = Runeerror;
381 if(c < Runeself){
382 a->data[n] = c;
383 *f->ret = 1;
384 return;
385 }
386 r = c;
387 if(n+UTFmax<=a->len || runelen(c)<=a->len-n){
388 *f->ret = runetochar((char*)a->data+n, &r);
389 return;
390 }
391 *f->ret = 0;
392 }
393
394 Module *
builtinmod(char * name,void * vr,int rlen)395 builtinmod(char *name, void *vr, int rlen)
396 {
397 Runtab *r = vr;
398 Type *t;
399 Module *m;
400 Link *l;
401
402 m = newmod(name);
403 if(rlen == 0){
404 while(r->name){
405 rlen++;
406 r++;
407 }
408 r = vr;
409 }
410 l = m->ext = (Link*)malloc((rlen+1)*sizeof(Link));
411 if(l == nil){
412 freemod(m);
413 return nil;
414 }
415 while(r->name) {
416 t = dtype(freeheap, r->size, r->map, r->np);
417 runtime(m, l, r->name, r->sig, r->fn, t);
418 r++;
419 l++;
420 }
421 l->name = nil;
422 return m;
423 }
424
425 void
retnstr(char * s,int n,String ** d)426 retnstr(char *s, int n, String **d)
427 {
428 String *s1;
429
430 s1 = H;
431 if(n != 0)
432 s1 = c2string(s, n);
433 destroy(*d);
434 *d = s1;
435 }
436
437 void
retstr(char * s,String ** d)438 retstr(char *s, String **d)
439 {
440 String *s1;
441
442 s1 = H;
443 if(s != nil)
444 s1 = c2string(s, strlen(s));
445 destroy(*d);
446 *d = s1;
447 }
448
449 Array*
mem2array(void * va,int n)450 mem2array(void *va, int n)
451 {
452 Heap *h;
453 Array *a;
454
455 if(n < 0)
456 n = 0;
457 h = nheap(sizeof(Array)+n);
458 h->t = &Tarray;
459 h->t->ref++;
460 a = H2D(Array*, h);
461 a->t = &Tbyte;
462 Tbyte.ref++;
463 a->len = n;
464 a->root = H;
465 a->data = (uchar*)a+sizeof(Array);
466 if(va != 0)
467 memmove(a->data, va, n);
468
469 return a;
470 }
471
472 static int
utfnleng(char * s,int nb,int * ngood)473 utfnleng(char *s, int nb, int *ngood)
474 {
475 int c;
476 long n;
477 Rune rune;
478 char *es, *starts;
479
480 starts = s;
481 es = s+nb;
482 for(n = 0; s < es; n++) {
483 c = *(uchar*)s;
484 if(c < Runeself)
485 s++;
486 else {
487 if(s+UTFmax<=es || fullrune(s, es-s))
488 s += chartorune(&rune, s);
489 else
490 break;
491 }
492 }
493 if(ngood)
494 *ngood = s-starts;
495 return n;
496 }
497