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 12 sysmodinit(void) 13 { 14 sysinit(); 15 builtinmod("$Sys", Sysmodtab, Sysmodlen); 16 } 17 18 int 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 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 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 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 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 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 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 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 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 * 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 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 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* 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 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