1 /*- 2 * Copyright (c) 2000 Daniel Capo Sobral 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /******************************************************************* 28 ** l o a d e r . c 29 ** Additional FICL words designed for FreeBSD's loader 30 ** 31 *******************************************************************/ 32 33 #ifdef TESTMAIN 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <dirent.h> 37 #include <fcntl.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <unistd.h> 41 #else 42 #include <stand.h> 43 #endif 44 #include "bootstrap.h" 45 #include <string.h> 46 #include <uuid.h> 47 #include <gfx_fb.h> 48 #include <pnglite.h> 49 #include "ficl.h" 50 51 /* FreeBSD's loader interaction words and extras 52 * 53 * setenv ( value n name n' -- ) 54 * setenv? ( value n name n' flag -- ) 55 * getenv ( addr n -- addr' n' | -1 ) 56 * unsetenv ( addr n -- ) 57 * copyin ( addr addr' len -- ) 58 * copyout ( addr addr' len -- ) 59 * findfile ( name len type len' -- addr ) 60 * pnpdevices ( -- addr ) 61 * pnphandlers ( -- addr ) 62 * ccall ( [[...[p10] p9] ... p1] n addr -- result ) 63 * uuid-from-string ( addr n -- addr' ) 64 * uuid-to-string ( addr' -- addr n ) 65 * .# ( value -- ) 66 */ 67 68 #ifndef TESTMAIN 69 /* ( flags x1 y1 x2 y2 -- flag ) */ 70 void 71 ficl_term_putimage(FICL_VM *pVM) 72 { 73 char *namep, *name; 74 int names; 75 unsigned long ret = FICL_FALSE; 76 uint32_t x1, y1, x2, y2, f; 77 png_t png; 78 int error; 79 80 #if FICL_ROBUST > 1 81 vmCheckStack(pVM, 7, 1); 82 #endif 83 names = stackPopINT(pVM->pStack); 84 namep = (char *) stackPopPtr(pVM->pStack); 85 y2 = stackPopINT(pVM->pStack); 86 x2 = stackPopINT(pVM->pStack); 87 y1 = stackPopINT(pVM->pStack); 88 x1 = stackPopINT(pVM->pStack); 89 f = stackPopINT(pVM->pStack); 90 91 x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width; 92 y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height; 93 if (x2 != 0) { 94 x2 = gfx_state.tg_origin.tp_col + 95 x2 * gfx_state.tg_font.vf_width; 96 } 97 if (y2 != 0) { 98 y2 = gfx_state.tg_origin.tp_row + 99 y2 * gfx_state.tg_font.vf_height; 100 } 101 102 name = ficlMalloc(names + 1); 103 if (!name) 104 vmThrowErr(pVM, "Error: out of memory"); 105 (void) strncpy(name, namep, names); 106 name[names] = '\0'; 107 108 if ((error = png_open(&png, name)) != PNG_NO_ERROR) { 109 if (f & FL_PUTIMAGE_DEBUG) 110 printf("%s\n", png_error_string(error)); 111 } else { 112 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0) 113 ret = FICL_TRUE; /* success */ 114 (void) png_close(&png); 115 } 116 ficlFree(name); 117 stackPushUNS(pVM->pStack, ret); 118 } 119 120 /* ( flags x1 y1 x2 y2 -- flag ) */ 121 void 122 ficl_fb_putimage(FICL_VM *pVM) 123 { 124 char *namep, *name; 125 int names; 126 unsigned long ret = FICL_FALSE; 127 uint32_t x1, y1, x2, y2, f; 128 png_t png; 129 int error; 130 131 #if FICL_ROBUST > 1 132 vmCheckStack(pVM, 7, 1); 133 #endif 134 names = stackPopINT(pVM->pStack); 135 namep = (char *) stackPopPtr(pVM->pStack); 136 y2 = stackPopINT(pVM->pStack); 137 x2 = stackPopINT(pVM->pStack); 138 y1 = stackPopINT(pVM->pStack); 139 x1 = stackPopINT(pVM->pStack); 140 f = stackPopINT(pVM->pStack); 141 142 name = ficlMalloc(names + 1); 143 if (!name) 144 vmThrowErr(pVM, "Error: out of memory"); 145 (void) strncpy(name, namep, names); 146 name[names] = '\0'; 147 148 if ((error = png_open(&png, name)) != PNG_NO_ERROR) { 149 if (f & FL_PUTIMAGE_DEBUG) 150 printf("%s\n", png_error_string(error)); 151 } else { 152 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0) 153 ret = FICL_TRUE; /* success */ 154 (void) png_close(&png); 155 } 156 ficlFree(name); 157 stackPushUNS(pVM->pStack, ret); 158 } 159 160 void 161 ficl_fb_setpixel(FICL_VM *pVM) 162 { 163 FICL_UNS x, y; 164 165 #if FICL_ROBUST > 1 166 vmCheckStack(pVM, 2, 0); 167 #endif 168 169 y = stackPopUNS(pVM->pStack); 170 x = stackPopUNS(pVM->pStack); 171 gfx_fb_setpixel(x, y); 172 } 173 174 void 175 ficl_fb_line(FICL_VM *pVM) 176 { 177 FICL_UNS x0, y0, x1, y1, wd; 178 179 #if FICL_ROBUST > 1 180 vmCheckStack(pVM, 5, 0); 181 #endif 182 183 wd = stackPopUNS(pVM->pStack); 184 y1 = stackPopUNS(pVM->pStack); 185 x1 = stackPopUNS(pVM->pStack); 186 y0 = stackPopUNS(pVM->pStack); 187 x0 = stackPopUNS(pVM->pStack); 188 gfx_fb_line(x0, y0, x1, y1, wd); 189 } 190 191 void 192 ficl_fb_bezier(FICL_VM *pVM) 193 { 194 FICL_UNS x0, y0, x1, y1, x2, y2, width; 195 196 #if FICL_ROBUST > 1 197 vmCheckStack(pVM, 7, 0); 198 #endif 199 200 width = stackPopUNS(pVM->pStack); 201 y2 = stackPopUNS(pVM->pStack); 202 x2 = stackPopUNS(pVM->pStack); 203 y1 = stackPopUNS(pVM->pStack); 204 x1 = stackPopUNS(pVM->pStack); 205 y0 = stackPopUNS(pVM->pStack); 206 x0 = stackPopUNS(pVM->pStack); 207 gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width); 208 } 209 210 void 211 ficl_fb_drawrect(FICL_VM *pVM) 212 { 213 FICL_UNS x1, x2, y1, y2, fill; 214 215 #if FICL_ROBUST > 1 216 vmCheckStack(pVM, 5, 0); 217 #endif 218 219 fill = stackPopUNS(pVM->pStack); 220 y2 = stackPopUNS(pVM->pStack); 221 x2 = stackPopUNS(pVM->pStack); 222 y1 = stackPopUNS(pVM->pStack); 223 x1 = stackPopUNS(pVM->pStack); 224 gfx_fb_drawrect(x1, y1, x2, y2, fill); 225 } 226 227 void 228 ficl_term_drawrect(FICL_VM *pVM) 229 { 230 FICL_UNS x1, x2, y1, y2; 231 232 #if FICL_ROBUST > 1 233 vmCheckStack(pVM, 4, 0); 234 #endif 235 236 y2 = stackPopUNS(pVM->pStack); 237 x2 = stackPopUNS(pVM->pStack); 238 y1 = stackPopUNS(pVM->pStack); 239 x1 = stackPopUNS(pVM->pStack); 240 gfx_term_drawrect(x1, y1, x2, y2); 241 } 242 #endif /* TESTMAIN */ 243 244 void 245 ficlSetenv(FICL_VM *pVM) 246 { 247 #ifndef TESTMAIN 248 char *name, *value; 249 #endif 250 char *namep, *valuep; 251 int names, values; 252 253 #if FICL_ROBUST > 1 254 vmCheckStack(pVM, 4, 0); 255 #endif 256 names = stackPopINT(pVM->pStack); 257 namep = (char*) stackPopPtr(pVM->pStack); 258 values = stackPopINT(pVM->pStack); 259 valuep = (char*) stackPopPtr(pVM->pStack); 260 261 #ifndef TESTMAIN 262 name = (char*) ficlMalloc(names+1); 263 if (!name) 264 vmThrowErr(pVM, "Error: out of memory"); 265 strncpy(name, namep, names); 266 name[names] = '\0'; 267 value = (char*) ficlMalloc(values+1); 268 if (!value) 269 vmThrowErr(pVM, "Error: out of memory"); 270 strncpy(value, valuep, values); 271 value[values] = '\0'; 272 273 setenv(name, value, 1); 274 ficlFree(name); 275 ficlFree(value); 276 #endif 277 278 return; 279 } 280 281 void 282 ficlSetenvq(FICL_VM *pVM) 283 { 284 #ifndef TESTMAIN 285 char *name, *value; 286 #endif 287 char *namep, *valuep; 288 int names, values, overwrite; 289 290 #if FICL_ROBUST > 1 291 vmCheckStack(pVM, 5, 0); 292 #endif 293 overwrite = stackPopINT(pVM->pStack); 294 names = stackPopINT(pVM->pStack); 295 namep = (char*) stackPopPtr(pVM->pStack); 296 values = stackPopINT(pVM->pStack); 297 valuep = (char*) stackPopPtr(pVM->pStack); 298 299 #ifndef TESTMAIN 300 name = (char*) ficlMalloc(names+1); 301 if (!name) 302 vmThrowErr(pVM, "Error: out of memory"); 303 strncpy(name, namep, names); 304 name[names] = '\0'; 305 value = (char*) ficlMalloc(values+1); 306 if (!value) 307 vmThrowErr(pVM, "Error: out of memory"); 308 strncpy(value, valuep, values); 309 value[values] = '\0'; 310 311 setenv(name, value, overwrite); 312 ficlFree(name); 313 ficlFree(value); 314 #endif 315 316 return; 317 } 318 319 void 320 ficlGetenv(FICL_VM *pVM) 321 { 322 #ifndef TESTMAIN 323 char *name, *value; 324 #endif 325 char *namep; 326 int names; 327 328 #if FICL_ROBUST > 1 329 vmCheckStack(pVM, 2, 2); 330 #endif 331 names = stackPopINT(pVM->pStack); 332 namep = (char*) stackPopPtr(pVM->pStack); 333 334 #ifndef TESTMAIN 335 name = (char*) ficlMalloc(names+1); 336 if (!name) 337 vmThrowErr(pVM, "Error: out of memory"); 338 strncpy(name, namep, names); 339 name[names] = '\0'; 340 341 value = getenv(name); 342 ficlFree(name); 343 344 if(value != NULL) { 345 stackPushPtr(pVM->pStack, value); 346 stackPushINT(pVM->pStack, strlen(value)); 347 } else 348 #endif 349 stackPushINT(pVM->pStack, -1); 350 351 return; 352 } 353 354 void 355 ficlUnsetenv(FICL_VM *pVM) 356 { 357 #ifndef TESTMAIN 358 char *name; 359 #endif 360 char *namep; 361 int names; 362 363 #if FICL_ROBUST > 1 364 vmCheckStack(pVM, 2, 0); 365 #endif 366 names = stackPopINT(pVM->pStack); 367 namep = (char*) stackPopPtr(pVM->pStack); 368 369 #ifndef TESTMAIN 370 name = (char*) ficlMalloc(names+1); 371 if (!name) 372 vmThrowErr(pVM, "Error: out of memory"); 373 strncpy(name, namep, names); 374 name[names] = '\0'; 375 376 unsetenv(name); 377 ficlFree(name); 378 #endif 379 380 return; 381 } 382 383 void 384 ficlCopyin(FICL_VM *pVM) 385 { 386 void* src; 387 vm_offset_t dest; 388 size_t len; 389 390 #if FICL_ROBUST > 1 391 vmCheckStack(pVM, 3, 0); 392 #endif 393 394 len = stackPopINT(pVM->pStack); 395 dest = stackPopINT(pVM->pStack); 396 src = stackPopPtr(pVM->pStack); 397 398 #ifndef TESTMAIN 399 archsw.arch_copyin(src, dest, len); 400 #endif 401 402 return; 403 } 404 405 void 406 ficlCopyout(FICL_VM *pVM) 407 { 408 void* dest; 409 vm_offset_t src; 410 size_t len; 411 412 #if FICL_ROBUST > 1 413 vmCheckStack(pVM, 3, 0); 414 #endif 415 416 len = stackPopINT(pVM->pStack); 417 dest = stackPopPtr(pVM->pStack); 418 src = stackPopINT(pVM->pStack); 419 420 #ifndef TESTMAIN 421 archsw.arch_copyout(src, dest, len); 422 #endif 423 424 return; 425 } 426 427 void 428 ficlFindfile(FICL_VM *pVM) 429 { 430 #ifndef TESTMAIN 431 char *name, *type; 432 #endif 433 char *namep, *typep; 434 struct preloaded_file* fp; 435 int names, types; 436 437 #if FICL_ROBUST > 1 438 vmCheckStack(pVM, 4, 1); 439 #endif 440 441 types = stackPopINT(pVM->pStack); 442 typep = (char*) stackPopPtr(pVM->pStack); 443 names = stackPopINT(pVM->pStack); 444 namep = (char*) stackPopPtr(pVM->pStack); 445 #ifndef TESTMAIN 446 name = (char*) ficlMalloc(names+1); 447 if (!name) 448 vmThrowErr(pVM, "Error: out of memory"); 449 strncpy(name, namep, names); 450 name[names] = '\0'; 451 type = (char*) ficlMalloc(types+1); 452 if (!type) 453 vmThrowErr(pVM, "Error: out of memory"); 454 strncpy(type, typep, types); 455 type[types] = '\0'; 456 457 fp = file_findfile(name, type); 458 #else 459 fp = NULL; 460 #endif 461 stackPushPtr(pVM->pStack, fp); 462 463 return; 464 } 465 466 #ifndef TESTMAIN 467 468 /* isvirtualized? - Return whether the loader runs under a 469 * hypervisor. 470 * 471 * isvirtualized? ( -- flag ) 472 */ 473 static void 474 ficlIsvirtualizedQ(FICL_VM *pVM) 475 { 476 FICL_INT flag; 477 const char *hv; 478 479 #if FICL_ROBUST > 1 480 vmCheckStack(pVM, 0, 1); 481 #endif 482 483 hv = (archsw.arch_hypervisor != NULL) 484 ? (*archsw.arch_hypervisor)() 485 : NULL; 486 flag = (hv != NULL) ? FICL_TRUE : FICL_FALSE; 487 stackPushINT(pVM->pStack, flag); 488 } 489 490 #endif /* ndef TESTMAIN */ 491 492 void 493 ficlCcall(FICL_VM *pVM) 494 { 495 int (*func)(int, ...); 496 int result, p[10]; 497 int nparam, i; 498 499 #if FICL_ROBUST > 1 500 vmCheckStack(pVM, 2, 0); 501 #endif 502 503 func = stackPopPtr(pVM->pStack); 504 nparam = stackPopINT(pVM->pStack); 505 506 #if FICL_ROBUST > 1 507 vmCheckStack(pVM, nparam, 1); 508 #endif 509 510 for (i = 0; i < nparam; i++) 511 p[i] = stackPopINT(pVM->pStack); 512 513 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], 514 p[9]); 515 516 stackPushINT(pVM->pStack, result); 517 518 return; 519 } 520 521 void 522 ficlUuidFromString(FICL_VM *pVM) 523 { 524 #ifndef TESTMAIN 525 char *uuid; 526 uint32_t status; 527 #endif 528 char *uuidp; 529 int uuids; 530 uuid_t *u; 531 532 #if FICL_ROBUST > 1 533 vmCheckStack(pVM, 2, 0); 534 #endif 535 536 uuids = stackPopINT(pVM->pStack); 537 uuidp = (char *) stackPopPtr(pVM->pStack); 538 539 #ifndef TESTMAIN 540 uuid = (char *)ficlMalloc(uuids + 1); 541 if (!uuid) 542 vmThrowErr(pVM, "Error: out of memory"); 543 strncpy(uuid, uuidp, uuids); 544 uuid[uuids] = '\0'; 545 546 u = (uuid_t *)ficlMalloc(sizeof (*u)); 547 548 uuid_from_string(uuid, u, &status); 549 ficlFree(uuid); 550 if (status != uuid_s_ok) { 551 ficlFree(u); 552 u = NULL; 553 } 554 #else 555 u = NULL; 556 #endif 557 stackPushPtr(pVM->pStack, u); 558 559 560 return; 561 } 562 563 void 564 ficlUuidToString(FICL_VM *pVM) 565 { 566 #ifndef TESTMAIN 567 char *uuid; 568 uint32_t status; 569 #endif 570 uuid_t *u; 571 572 #if FICL_ROBUST > 1 573 vmCheckStack(pVM, 1, 0); 574 #endif 575 576 u = (uuid_t *)stackPopPtr(pVM->pStack); 577 578 #ifndef TESTMAIN 579 uuid_to_string(u, &uuid, &status); 580 if (status != uuid_s_ok) { 581 stackPushPtr(pVM->pStack, uuid); 582 stackPushINT(pVM->pStack, strlen(uuid)); 583 } else 584 #endif 585 stackPushINT(pVM->pStack, -1); 586 587 return; 588 } 589 590 /************************************************************************** 591 f i c l E x e c F D 592 ** reads in text from file fd and passes it to ficlExec() 593 * returns VM_OUTOFTEXT on success or the ficlExec() error code on 594 * failure. 595 */ 596 #define nLINEBUF 256 597 int ficlExecFD(FICL_VM *pVM, int fd) 598 { 599 char cp[nLINEBUF]; 600 int nLine = 0, rval = VM_OUTOFTEXT; 601 char ch; 602 CELL id; 603 604 id = pVM->sourceID; 605 pVM->sourceID.i = fd; 606 607 /* feed each line to ficlExec */ 608 while (1) { 609 int status, i; 610 611 i = 0; 612 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n') 613 cp[i++] = ch; 614 nLine++; 615 if (!i) { 616 if (status < 1) 617 break; 618 continue; 619 } 620 rval = ficlExecC(pVM, cp, i); 621 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT) 622 { 623 pVM->sourceID = id; 624 return rval; 625 } 626 } 627 /* 628 ** Pass an empty line with SOURCE-ID == -1 to flush 629 ** any pending REFILLs (as required by FILE wordset) 630 */ 631 pVM->sourceID.i = -1; 632 ficlExec(pVM, ""); 633 634 pVM->sourceID = id; 635 return rval; 636 } 637 638 static void displayCellNoPad(FICL_VM *pVM) 639 { 640 CELL c; 641 #if FICL_ROBUST > 1 642 vmCheckStack(pVM, 1, 0); 643 #endif 644 c = stackPop(pVM->pStack); 645 ltoa((c).i, pVM->pad, pVM->base); 646 vmTextOut(pVM, pVM->pad, 0); 647 return; 648 } 649 650 /* isdir? - Return whether an fd corresponds to a directory. 651 * 652 * isdir? ( fd -- bool ) 653 */ 654 static void isdirQuestion(FICL_VM *pVM) 655 { 656 struct stat sb; 657 FICL_INT flag; 658 int fd; 659 660 #if FICL_ROBUST > 1 661 vmCheckStack(pVM, 1, 1); 662 #endif 663 664 fd = stackPopINT(pVM->pStack); 665 flag = FICL_FALSE; 666 do { 667 if (fd < 0) 668 break; 669 if (fstat(fd, &sb) < 0) 670 break; 671 if (!S_ISDIR(sb.st_mode)) 672 break; 673 flag = FICL_TRUE; 674 } while (0); 675 stackPushINT(pVM->pStack, flag); 676 } 677 678 /* fopen - open a file and return new fd on stack. 679 * 680 * fopen ( ptr count mode -- fd ) 681 */ 682 static void pfopen(FICL_VM *pVM) 683 { 684 int mode, fd, count; 685 char *ptr, *name; 686 687 #if FICL_ROBUST > 1 688 vmCheckStack(pVM, 3, 1); 689 #endif 690 691 mode = stackPopINT(pVM->pStack); /* get mode */ 692 count = stackPopINT(pVM->pStack); /* get count */ 693 ptr = stackPopPtr(pVM->pStack); /* get ptr */ 694 695 if ((count < 0) || (ptr == NULL)) { 696 stackPushINT(pVM->pStack, -1); 697 return; 698 } 699 700 /* ensure that the string is null terminated */ 701 name = (char *)malloc(count+1); 702 bcopy(ptr,name,count); 703 name[count] = 0; 704 705 /* open the file */ 706 fd = open(name, mode); 707 #ifdef LOADER_VERIEXEC 708 if (fd >= 0) { 709 if (verify_file(fd, name, 0, VE_GUESS, __func__) < 0) { 710 /* not verified writing ok but reading is not */ 711 if ((mode & O_ACCMODE) != O_WRONLY) { 712 close(fd); 713 fd = -1; 714 } 715 } else { 716 /* verified reading ok but writing is not */ 717 if ((mode & O_ACCMODE) != O_RDONLY) { 718 close(fd); 719 fd = -1; 720 } 721 } 722 } 723 #endif 724 free(name); 725 stackPushINT(pVM->pStack, fd); 726 return; 727 } 728 729 /* fclose - close a file who's fd is on stack. 730 * 731 * fclose ( fd -- ) 732 */ 733 static void pfclose(FICL_VM *pVM) 734 { 735 int fd; 736 737 #if FICL_ROBUST > 1 738 vmCheckStack(pVM, 1, 0); 739 #endif 740 fd = stackPopINT(pVM->pStack); /* get fd */ 741 if (fd != -1) 742 close(fd); 743 return; 744 } 745 746 /* fread - read file contents 747 * 748 * fread ( fd buf nbytes -- nread ) 749 */ 750 static void pfread(FICL_VM *pVM) 751 { 752 int fd, len; 753 char *buf; 754 755 #if FICL_ROBUST > 1 756 vmCheckStack(pVM, 3, 1); 757 #endif 758 len = stackPopINT(pVM->pStack); /* get number of bytes to read */ 759 buf = stackPopPtr(pVM->pStack); /* get buffer */ 760 fd = stackPopINT(pVM->pStack); /* get fd */ 761 if (len > 0 && buf && fd != -1) 762 stackPushINT(pVM->pStack, read(fd, buf, len)); 763 else 764 stackPushINT(pVM->pStack, -1); 765 return; 766 } 767 768 /* freaddir - read directory contents 769 * 770 * freaddir ( fd -- ptr len TRUE | FALSE ) 771 */ 772 static void pfreaddir(FICL_VM *pVM) 773 { 774 #ifdef TESTMAIN 775 static struct dirent dirent; 776 struct stat sb; 777 char *buf; 778 off_t off, ptr; 779 u_int blksz; 780 int bufsz; 781 #endif 782 struct dirent *d; 783 int fd; 784 785 #if FICL_ROBUST > 1 786 vmCheckStack(pVM, 1, 3); 787 #endif 788 789 fd = stackPopINT(pVM->pStack); 790 #if TESTMAIN 791 /* 792 * The readdirfd() function is specific to the loader environment. 793 * We do the best we can to make freaddir work, but it's not at 794 * all guaranteed. 795 */ 796 d = NULL; 797 buf = NULL; 798 do { 799 if (fd == -1) 800 break; 801 if (fstat(fd, &sb) == -1) 802 break; 803 blksz = (sb.st_blksize) ? sb.st_blksize : getpagesize(); 804 if ((blksz & (blksz - 1)) != 0) 805 break; 806 buf = malloc(blksz); 807 if (buf == NULL) 808 break; 809 off = lseek(fd, 0LL, SEEK_CUR); 810 if (off == -1) 811 break; 812 ptr = off; 813 if (lseek(fd, 0, SEEK_SET) == -1) 814 break; 815 bufsz = getdents(fd, buf, blksz); 816 while (bufsz > 0 && bufsz <= ptr) { 817 ptr -= bufsz; 818 bufsz = getdents(fd, buf, blksz); 819 } 820 if (bufsz <= 0) 821 break; 822 d = (void *)(buf + ptr); 823 dirent = *d; 824 off += d->d_reclen; 825 d = (lseek(fd, off, SEEK_SET) != off) ? NULL : &dirent; 826 } while (0); 827 if (buf != NULL) 828 free(buf); 829 #else 830 d = readdirfd(fd); 831 #endif 832 if (d != NULL) { 833 stackPushPtr(pVM->pStack, d->d_name); 834 stackPushINT(pVM->pStack, strlen(d->d_name)); 835 stackPushINT(pVM->pStack, FICL_TRUE); 836 } else { 837 stackPushINT(pVM->pStack, FICL_FALSE); 838 } 839 } 840 841 /* fload - interpret file contents 842 * 843 * fload ( fd -- ) 844 */ 845 static void pfload(FICL_VM *pVM) 846 { 847 int fd; 848 849 #if FICL_ROBUST > 1 850 vmCheckStack(pVM, 1, 0); 851 #endif 852 fd = stackPopINT(pVM->pStack); /* get fd */ 853 if (fd != -1) 854 ficlExecFD(pVM, fd); 855 return; 856 } 857 858 /* fwrite - write file contents 859 * 860 * fwrite ( fd buf nbytes -- nwritten ) 861 */ 862 static void pfwrite(FICL_VM *pVM) 863 { 864 int fd, len; 865 char *buf; 866 867 #if FICL_ROBUST > 1 868 vmCheckStack(pVM, 3, 1); 869 #endif 870 len = stackPopINT(pVM->pStack); /* get number of bytes to read */ 871 buf = stackPopPtr(pVM->pStack); /* get buffer */ 872 fd = stackPopINT(pVM->pStack); /* get fd */ 873 if (len > 0 && buf && fd != -1) 874 stackPushINT(pVM->pStack, write(fd, buf, len)); 875 else 876 stackPushINT(pVM->pStack, -1); 877 return; 878 } 879 880 /* fseek - seek to a new position in a file 881 * 882 * fseek ( fd ofs whence -- pos ) 883 */ 884 static void pfseek(FICL_VM *pVM) 885 { 886 int fd, pos, whence; 887 888 #if FICL_ROBUST > 1 889 vmCheckStack(pVM, 3, 1); 890 #endif 891 whence = stackPopINT(pVM->pStack); 892 pos = stackPopINT(pVM->pStack); 893 fd = stackPopINT(pVM->pStack); 894 stackPushINT(pVM->pStack, lseek(fd, pos, whence)); 895 return; 896 } 897 898 /* key - get a character from stdin 899 * 900 * key ( -- char ) 901 */ 902 static void key(FICL_VM *pVM) 903 { 904 #if FICL_ROBUST > 1 905 vmCheckStack(pVM, 0, 1); 906 #endif 907 stackPushINT(pVM->pStack, getchar()); 908 return; 909 } 910 911 /* key? - check for a character from stdin (FACILITY) 912 * 913 * key? ( -- flag ) 914 */ 915 static void keyQuestion(FICL_VM *pVM) 916 { 917 #if FICL_ROBUST > 1 918 vmCheckStack(pVM, 0, 1); 919 #endif 920 #ifdef TESTMAIN 921 /* XXX Since we don't fiddle with termios, let it always succeed... */ 922 stackPushINT(pVM->pStack, FICL_TRUE); 923 #else 924 /* But here do the right thing. */ 925 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE); 926 #endif 927 return; 928 } 929 930 /* seconds - gives number of seconds since beginning of time 931 * 932 * beginning of time is defined as: 933 * 934 * BTX - number of seconds since midnight 935 * FreeBSD - number of seconds since Jan 1 1970 936 * 937 * seconds ( -- u ) 938 */ 939 static void pseconds(FICL_VM *pVM) 940 { 941 #if FICL_ROBUST > 1 942 vmCheckStack(pVM,0,1); 943 #endif 944 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL)); 945 return; 946 } 947 948 /* ms - wait at least that many milliseconds (FACILITY) 949 * 950 * ms ( u -- ) 951 * 952 */ 953 static void ms(FICL_VM *pVM) 954 { 955 #if FICL_ROBUST > 1 956 vmCheckStack(pVM,1,0); 957 #endif 958 #ifdef TESTMAIN 959 usleep(stackPopUNS(pVM->pStack)*1000); 960 #else 961 delay(stackPopUNS(pVM->pStack)*1000); 962 #endif 963 return; 964 } 965 966 /* fkey - get a character from a file 967 * 968 * fkey ( file -- char ) 969 */ 970 static void fkey(FICL_VM *pVM) 971 { 972 int i, fd; 973 char ch; 974 975 #if FICL_ROBUST > 1 976 vmCheckStack(pVM, 1, 1); 977 #endif 978 fd = stackPopINT(pVM->pStack); 979 i = read(fd, &ch, 1); 980 stackPushINT(pVM->pStack, i > 0 ? ch : -1); 981 return; 982 } 983 984 985 /* 986 ** Retrieves free space remaining on the dictionary 987 */ 988 989 static void freeHeap(FICL_VM *pVM) 990 { 991 stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys))); 992 } 993 994 995 /******************* Increase dictionary size on-demand ******************/ 996 997 static void ficlDictThreshold(FICL_VM *pVM) 998 { 999 stackPushPtr(pVM->pStack, &dictThreshold); 1000 } 1001 1002 static void ficlDictIncrease(FICL_VM *pVM) 1003 { 1004 stackPushPtr(pVM->pStack, &dictIncrease); 1005 } 1006 1007 /************************************************************************** 1008 f i c l C o m p i l e P l a t f o r m 1009 ** Build FreeBSD platform extensions into the system dictionary 1010 **************************************************************************/ 1011 void ficlCompilePlatform(FICL_SYSTEM *pSys) 1012 { 1013 ficlCompileFcn **fnpp; 1014 FICL_DICT *dp = pSys->dp; 1015 assert (dp); 1016 1017 dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT); 1018 dictAppendWord(dp, "isdir?", isdirQuestion, FW_DEFAULT); 1019 dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT); 1020 dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT); 1021 dictAppendWord(dp, "fread", pfread, FW_DEFAULT); 1022 dictAppendWord(dp, "freaddir", pfreaddir, FW_DEFAULT); 1023 dictAppendWord(dp, "fload", pfload, FW_DEFAULT); 1024 dictAppendWord(dp, "fkey", fkey, FW_DEFAULT); 1025 dictAppendWord(dp, "fseek", pfseek, FW_DEFAULT); 1026 dictAppendWord(dp, "fwrite", pfwrite, FW_DEFAULT); 1027 dictAppendWord(dp, "key", key, FW_DEFAULT); 1028 dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT); 1029 dictAppendWord(dp, "ms", ms, FW_DEFAULT); 1030 dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT); 1031 dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT); 1032 dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT); 1033 dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT); 1034 1035 dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT); 1036 dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT); 1037 dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT); 1038 dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT); 1039 dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT); 1040 dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT); 1041 dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT); 1042 dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT); 1043 dictAppendWord(dp, "uuid-from-string", ficlUuidFromString, FW_DEFAULT); 1044 dictAppendWord(dp, "uuid-to-string", ficlUuidToString, FW_DEFAULT); 1045 #ifndef TESTMAIN 1046 dictAppendWord(dp, "fb-setpixel", ficl_fb_setpixel, FW_DEFAULT); 1047 dictAppendWord(dp, "fb-line", ficl_fb_line, FW_DEFAULT); 1048 dictAppendWord(dp, "fb-bezier", ficl_fb_bezier, FW_DEFAULT); 1049 dictAppendWord(dp, "fb-drawrect", ficl_fb_drawrect, FW_DEFAULT); 1050 dictAppendWord(dp, "fb-putimage", ficl_fb_putimage, FW_DEFAULT); 1051 dictAppendWord(dp, "term-drawrect", ficl_term_drawrect, FW_DEFAULT); 1052 dictAppendWord(dp, "term-putimage", ficl_term_putimage, FW_DEFAULT); 1053 dictAppendWord(dp, "isvirtualized?",ficlIsvirtualizedQ, FW_DEFAULT); 1054 #endif 1055 1056 SET_FOREACH(fnpp, Xficl_compile_set) 1057 (*fnpp)(pSys); 1058 1059 #if defined(__i386__) 1060 ficlSetEnv(pSys, "arch-i386", FICL_TRUE); 1061 ficlSetEnv(pSys, "arch-powerpc", FICL_FALSE); 1062 #elif defined(__powerpc__) 1063 ficlSetEnv(pSys, "arch-i386", FICL_FALSE); 1064 ficlSetEnv(pSys, "arch-powerpc", FICL_TRUE); 1065 #endif 1066 1067 return; 1068 } 1069