1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "raise.h"
5 #include "pool.h"
6
7 #define OP(fn) void fn(void)
8 #define B(r) *((BYTE*)(R.r))
9 #define W(r) *((WORD*)(R.r))
10 #define F(r) *((REAL*)(R.r))
11 #define V(r) *((LONG*)(R.r))
12 #define S(r) *((String**)(R.r))
13 #define A(r) *((Array**)(R.r))
14 #define L(r) *((List**)(R.r))
15 #define P(r) *((WORD**)(R.r))
16 #define C(r) *((Channel**)(R.r))
17 #define T(r) *((void**)(R.r))
18
OP(indc)19 OP(indc)
20 {
21 int l;
22 ulong v;
23 String *ss;
24
25 v = W(m);
26 ss = S(s);
27
28 if(ss == H)
29 error(exNilref);
30
31 l = ss->len;
32 if(l < 0) {
33 if(v >= -l)
34 e: error(exBounds);
35 l = ss->Srune[v];
36 }
37 else {
38 if(v >= l)
39 goto e;
40 l = ss->Sascii[v];
41 }
42 W(d) = l;
43 }
44
OP(insc)45 OP(insc)
46 {
47 ulong v;
48 int l, r, expand;
49 String *ss, *ns, **sp;
50
51 r = W(s);
52 v = W(m);
53 ss = S(d);
54
55 expand = r >= Runeself;
56
57 if(ss == H) {
58 ss = newstring(0);
59 if(expand) {
60 l = 0;
61 ss->max /= sizeof(Rune);
62 goto r;
63 }
64 }
65 else
66 if(D2H(ss)->ref > 1 || (expand && ss->len > 0))
67 ss = splitc(R.d, expand);
68
69 l = ss->len;
70 if(l < 0 || expand) {
71 l = -l;
72 r:
73 if(v < l)
74 ss->Srune[v] = r;
75 else
76 if(v == l && v < ss->max) {
77 ss->len = -(v+1);
78 ss->Srune[v] = r;
79 }
80 else {
81 if(v != l)
82 error(exBounds);
83 ns = newstring((v + 1 + v/4)*sizeof(Rune));
84 memmove(ns->Srune, ss->Srune, -ss->len*sizeof(Rune));
85 ns->Srune[v] = r;
86 ns->len = -(v+1);
87 ns->max /= sizeof(Rune);
88 ss = ns;
89 }
90 }
91 else {
92 if(v < l)
93 ss->Sascii[v] = r;
94 else
95 if(v == l && v < ss->max) {
96 ss->len = v+1;
97 ss->Sascii[v] = r;
98 }
99 else {
100 if(v != l)
101 error(exBounds);
102 ns = newstring(v + 1 + v/4);
103 memmove(ns->Sascii, ss->Sascii, l);
104 ns->Sascii[v] = r;
105 ns->len = v+1;
106 ss = ns;
107 }
108 }
109 if(ss != S(d)) {
110 sp = R.d;
111 destroy(*sp);
112 *sp = ss;
113 }
114 }
115
116 String*
slicer(ulong start,ulong v,String * ds)117 slicer(ulong start, ulong v, String *ds)
118 {
119 String *ns;
120 int l, nc;
121
122 if(ds == H) {
123 if(start == 0 && v == 0)
124 return H;
125
126 error(exBounds);
127 }
128
129 nc = v - start;
130 if(ds->len < 0) {
131 l = -ds->len;
132 if(v < start || v > l)
133 error(exBounds);
134 if(nc == 0)
135 return H;
136 ns = newrunes(nc);
137 memmove(ns->Srune, &ds->Srune[start], nc*sizeof(Rune));
138 }
139 else {
140 l = ds->len;
141 if(v < start || v > l)
142 error(exBounds);
143 if(nc == 0)
144 return H;
145 ns = newstring(nc);
146 memmove(ns->Sascii, &ds->Sascii[start], nc);
147 }
148
149 return ns;
150 }
151
OP(slicec)152 OP(slicec)
153 {
154 String *ns, **sp;
155
156 ns = slicer(W(s), W(m), S(d));
157 sp = R.d;
158 destroy(*sp);
159 *sp = ns;
160 }
161
162 void
cvtup(Rune * r,String * s)163 cvtup(Rune *r, String *s)
164 {
165 uchar *bp, *ep;
166
167 bp = (uchar*)s->Sascii;
168 ep = bp + s->len;
169 while(bp < ep)
170 *r++ = *bp++;
171 }
172
173 String*
addstring(String * s1,String * s2,int append)174 addstring(String *s1, String *s2, int append)
175 {
176 Rune *r;
177 String *ns;
178 int l, l1, l2;
179
180 if(s1 == H) {
181 if(s2 == H)
182 return H;
183 return stringdup(s2);
184 }
185 if(D2H(s1)->ref > 1)
186 append = 0;
187 if(s2 == H) {
188 if(append)
189 return s1;
190 return stringdup(s1);
191 }
192
193 if(s1->len < 0) {
194 l1 = -s1->len;
195 if(s2->len < 0)
196 l = l1 - s2->len;
197 else
198 l = l1 + s2->len;
199 if(append && l <= s1->max)
200 ns = s1;
201 else {
202 ns = newrunes(append? (l+l/4): l);
203 memmove(ns->Srune, s1->Srune, l1*sizeof(Rune));
204 }
205 ns->len = -l;
206 r = &ns->Srune[l1];
207 if(s2->len < 0)
208 memmove(r, s2->Srune, -s2->len*sizeof(Rune));
209 else
210 cvtup(r, s2);
211
212 return ns;
213 }
214
215 if(s2->len < 0) {
216 l2 = -s2->len;
217 l = s1->len + l2;
218 ns = newrunes(append? (l+l/4): l);
219 ns->len = -l;
220 cvtup(ns->Srune, s1);
221 memmove(&ns->Srune[s1->len], s2->Srune, l2*sizeof(Rune));
222 return ns;
223 }
224
225 l1 = s1->len;
226 l = l1 + s2->len;
227 if(append && l <= s1->max)
228 ns = s1;
229 else {
230 ns = newstring(append? (l+l/4): l);
231 memmove(ns->Sascii, s1->Sascii, l1);
232 }
233 ns->len = l;
234 memmove(ns->Sascii+l1, s2->Sascii, s2->len);
235
236 return ns;
237 }
238
OP(addc)239 OP(addc)
240 {
241 String *ns, **sp;
242
243 ns = addstring(S(m), S(s), R.m == R.d);
244
245 sp = R.d;
246 if(ns != *sp) {
247 destroy(*sp);
248 *sp = ns;
249 }
250 }
251
OP(cvtca)252 OP(cvtca)
253 {
254 int l;
255 Rune *r;
256 char *p;
257 String *ss;
258 Array *a, **ap;
259
260 ss = S(s);
261 if(ss == H) {
262 a = mem2array(nil, 0);
263 goto r;
264 }
265 if(ss->len < 0) {
266 l = -ss->len;
267 a = mem2array(nil, runenlen(ss->Srune, l));
268 p = (char*)a->data;
269 r = ss->Srune;
270 while(l--)
271 p += runetochar(p, r++);
272 goto r;
273 }
274 a = mem2array(ss->Sascii, ss->len);
275
276 r: ap = R.d;
277 destroy(*ap);
278 *ap = a;
279 }
280
OP(cvtac)281 OP(cvtac)
282 {
283 Array *a;
284 String *ds, **dp;
285
286 ds = H;
287 a = A(s);
288 if(a != H)
289 ds = c2string((char*)a->data, a->len);
290
291 dp = R.d;
292 destroy(*dp);
293 *dp = ds;
294 }
295
OP(lenc)296 OP(lenc)
297 {
298 int l;
299 String *ss;
300
301 l = 0;
302 ss = S(s);
303 if(ss != H) {
304 l = ss->len;
305 if(l < 0)
306 l = -l;
307 }
308 W(d) = l;
309 }
310
OP(cvtcw)311 OP(cvtcw)
312 {
313 String *s;
314
315 s = S(s);
316 if(s == H)
317 W(d) = 0;
318 else
319 if(s->len < 0)
320 W(d) = strtol(string2c(s), nil, 10);
321 else {
322 s->Sascii[s->len] = '\0';
323 W(d) = strtol(s->Sascii, nil, 10);
324 }
325 }
326
OP(cvtcf)327 OP(cvtcf)
328 {
329 String *s;
330
331 s = S(s);
332 if(s == H)
333 F(d) = 0.0;
334 else
335 if(s->len < 0)
336 F(d) = strtod(string2c(s), nil);
337 else {
338 s->Sascii[s->len] = '\0';
339 F(d) = strtod(s->Sascii, nil);
340 }
341 }
342
OP(cvtwc)343 OP(cvtwc)
344 {
345 String *ds, **dp;
346
347 ds = newstring(16);
348 ds->len = sprint(ds->Sascii, "%d", W(s));
349
350 dp = R.d;
351 destroy(*dp);
352 *dp = ds;
353 }
354
OP(cvtlc)355 OP(cvtlc)
356 {
357 String *ds, **dp;
358
359 ds = newstring(16);
360 ds->len = sprint(ds->Sascii, "%lld", V(s));
361
362 dp = R.d;
363 destroy(*dp);
364 *dp = ds;
365 }
366
OP(cvtfc)367 OP(cvtfc)
368 {
369 String *ds, **dp;
370
371 ds = newstring(32);
372 ds->len = sprint(ds->Sascii, "%g", F(s));
373 dp = R.d;
374 destroy(*dp);
375 *dp = ds;
376 }
377
378 char*
string2c(String * s)379 string2c(String *s)
380 {
381 char *p;
382 int c, l, nc;
383 Rune *r, *er;
384
385 if(s == H)
386 return "";
387
388 if(s->len >= 0) {
389 s->Sascii[s->len] = '\0';
390 return s->Sascii;
391 }
392
393 nc = -s->len;
394 l = (nc * UTFmax) + UTFmax;
395 if(s->tmp == nil || msize(s->tmp) < l) {
396 free(s->tmp);
397 s->tmp = malloc(l);
398 if(s->tmp == nil)
399 error(exNomem);
400 }
401
402 p = s->tmp;
403 r = s->Srune;
404 er = r + nc;
405 while(r < er) {
406 c = *r++;
407 if(c < Runeself)
408 *p++ = c;
409 else
410 p += runetochar(p, r-1);
411 }
412
413 *p = 0;
414
415 return s->tmp;
416 }
417
418 String*
c2string(char * cs,int len)419 c2string(char *cs, int len)
420 {
421 uchar *p;
422 char *ecs;
423 String *s;
424 Rune *r, junk;
425 int c, nc, isrune;
426
427 isrune = 0;
428 ecs = cs+len;
429 p = (uchar*)cs;
430 while(len--) {
431 c = *p++;
432 if(c >= Runeself) {
433 isrune = 1;
434 break;
435 }
436 }
437
438 if(isrune == 0) {
439 nc = ecs - cs;
440 s = newstring(nc);
441 memmove(s->Sascii, cs, nc);
442 return s;
443 }
444
445 p--;
446 nc = p - (uchar*)cs;
447 while(p < (uchar*)ecs) {
448 c = *p;
449 if(c < Runeself)
450 p++;
451 else if(p+UTFmax<=(uchar*)ecs || fullrune((char*)p, (uchar*)ecs-p))
452 p += chartorune(&junk, (char*)p);
453 else
454 break;
455 nc++;
456 }
457 s = newrunes(nc);
458 r = s->Srune;
459 while(nc--)
460 cs += chartorune(r++, cs);
461
462 return s;
463 }
464
465 String*
newstring(int nb)466 newstring(int nb)
467 {
468 Heap *h;
469 String *s;
470
471 h = nheap(sizeof(String)+nb);
472 h->t = &Tstring;
473 Tstring.ref++;
474 s = H2D(String*, h);
475 s->tmp = nil;
476 s->len = nb;
477 s->max = hmsize(h) - (sizeof(String)+sizeof(Heap));
478 return s;
479 }
480
481 String*
newrunes(int nr)482 newrunes(int nr)
483 {
484 Heap *h;
485 String *s;
486
487 if(nr == 0)
488 return newstring(nr);
489 if(nr < 0)
490 nr = -nr;
491 h = nheap(sizeof(String)+nr*sizeof(Rune));
492 h->t = &Tstring;
493 Tstring.ref++;
494 s = H2D(String*, h);
495 s->tmp = nil;
496 s->len = -nr;
497 s->max = (hmsize(h) - (sizeof(String)+sizeof(Heap)))/sizeof(Rune);
498 return s;
499 }
500
501 String*
stringdup(String * s)502 stringdup(String *s)
503 {
504 String *ns;
505
506 if(s == H)
507 return H;
508
509 if(s->len >= 0) {
510 ns = newstring(s->len);
511 memmove(ns->Sascii, s->Sascii, s->len);
512 return ns;
513 }
514
515 ns = newrunes(-s->len);
516 memmove(ns->Srune, s->Srune,-s->len*sizeof(Rune));
517
518 return ns;
519 }
520
521 int
stringcmp(String * s1,String * s2)522 stringcmp(String *s1, String *s2)
523 {
524 Rune *r1, *r2;
525 char *a1, *a2;
526 int v, n, n1, n2, c1, c2;
527 static String snil = { 0, 0, nil };
528
529 if(s1 == H)
530 s1 = &snil;
531 if(s2 == H)
532 s2 = &snil;
533
534 if(s1 == s2)
535 return 0;
536
537 v = 0;
538 n1 = s1->len;
539 if(n1 < 0) {
540 n1 = -n1;
541 v |= 1;
542 }
543 n2 = s2->len;
544 if(n2 < 0) {
545 n2 = -n2;
546 v |= 2;
547 }
548
549 n = n1;
550 if(n2 < n)
551 n = n2;
552
553 switch(v) {
554 case 0: /* Ascii Ascii */
555 n = memcmp(s1->Sascii, s2->Sascii, n);
556 if(n == 0)
557 n = n1 - n2;
558 return n;
559 case 1: /* Rune Ascii */
560 r1 = s1->Srune;
561 a2 = s2->Sascii;
562 while(n > 0) {
563 c1 = *r1++;
564 c2 = *a2++;
565 if(c1 != c2)
566 goto ne;
567 n--;
568 }
569 break;
570 case 2: /* Ascii Rune */
571 a1 = s1->Sascii;
572 r2 = s2->Srune;
573 while(n > 0) {
574 c1 = *a1++;
575 c2 = *r2++;
576 if(c1 != c2)
577 goto ne;
578 n--;
579 }
580 break;
581 case 3: /* Rune Rune */
582 r1 = s1->Srune;
583 r2 = s2->Srune;
584 while(n > 0) {
585 c1 = *r1++;
586 c2 = *r2++;
587 if(c1 != c2)
588 goto ne;
589 n--;
590 }
591 break;
592 }
593 return n1 - n2;
594
595 ne: if(c1 < c2)
596 return -1;
597 return 1;
598 }
599
600 String*
splitc(String ** s,int expand)601 splitc(String **s, int expand)
602 {
603 String *ss, *ns;
604
605 ss = *s;
606 if(expand && ss->len > 0) {
607 ns = newrunes(ss->len);
608 cvtup(ns->Srune, ss);
609 }
610 else
611 ns = stringdup(ss);
612
613 destroy(ss);
614 *s = ns;
615 return ns;
616 }
617