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 * $FreeBSD$ 27 */ 28 29/******************************************************************* 30** l o a d e r . c 31** Additional FICL words designed for FreeBSD's loader 32** 33*******************************************************************/ 34 35#ifdef TESTMAIN 36#include <stdlib.h> 37#else 38#include <stand.h> 39#endif 40#include "bootstrap.h" 41#include <string.h> 42#include "ficl.h" 43 44/* FreeBSD's loader interaction words and extras 45 * 46 * setenv ( value n name n' -- ) 47 * setenv? ( value n name n' flag -- ) 48 * getenv ( addr n -- addr' n' | -1 ) 49 * unsetenv ( addr n -- ) 50 * copyin ( addr addr' len -- ) 51 * copyout ( addr addr' len -- ) 52 * findfile ( name len type len' -- addr ) 53 * pnpdevices ( -- addr ) 54 * pnphandlers ( -- addr ) 55 * ccall ( [[...[p10] p9] ... p1] n addr -- result ) 56 * .# ( value -- ) 57 */ 58 59void 60ficlSetenv(FICL_VM *pVM) 61{ 62#ifndef TESTMAIN 63 char *name, *value; 64#endif 65 char *namep, *valuep; 66 int names, values; 67 68#if FICL_ROBUST > 1 69 vmCheckStack(pVM, 4, 0); 70#endif 71 names = stackPopINT(pVM->pStack); 72 namep = (char*) stackPopPtr(pVM->pStack); 73 values = stackPopINT(pVM->pStack); 74 valuep = (char*) stackPopPtr(pVM->pStack); 75 76#ifndef TESTMAIN 77 name = (char*) ficlMalloc(names+1); 78 if (!name) 79 vmThrowErr(pVM, "Error: out of memory"); 80 strncpy(name, namep, names); 81 name[names] = '\0'; 82 value = (char*) ficlMalloc(values+1); 83 if (!value) 84 vmThrowErr(pVM, "Error: out of memory"); 85 strncpy(value, valuep, values); 86 value[values] = '\0'; 87 88 setenv(name, value, 1); 89 ficlFree(name); 90 ficlFree(value); 91#endif 92 93 return; 94} 95 96void 97ficlSetenvq(FICL_VM *pVM) 98{ 99#ifndef TESTMAIN 100 char *name, *value; 101#endif 102 char *namep, *valuep; 103 int names, values, overwrite; 104 105#if FICL_ROBUST > 1 106 vmCheckStack(pVM, 5, 0); 107#endif 108 overwrite = stackPopINT(pVM->pStack); 109 names = stackPopINT(pVM->pStack); 110 namep = (char*) stackPopPtr(pVM->pStack); 111 values = stackPopINT(pVM->pStack); 112 valuep = (char*) stackPopPtr(pVM->pStack); 113 114#ifndef TESTMAIN 115 name = (char*) ficlMalloc(names+1); 116 if (!name) 117 vmThrowErr(pVM, "Error: out of memory"); 118 strncpy(name, namep, names); 119 name[names] = '\0'; 120 value = (char*) ficlMalloc(values+1); 121 if (!value) 122 vmThrowErr(pVM, "Error: out of memory"); 123 strncpy(value, valuep, values); 124 value[values] = '\0'; 125 126 setenv(name, value, overwrite); 127 ficlFree(name); 128 ficlFree(value); 129#endif 130 131 return; 132} 133 134void 135ficlGetenv(FICL_VM *pVM) 136{ 137#ifndef TESTMAIN 138 char *name; 139#endif 140 char *namep, *value; 141 int names; 142 143#if FICL_ROBUST > 1 144 vmCheckStack(pVM, 2, 2); 145#endif 146 names = stackPopINT(pVM->pStack); 147 namep = (char*) stackPopPtr(pVM->pStack); 148 149#ifndef TESTMAIN 150 name = (char*) ficlMalloc(names+1); 151 if (!name) 152 vmThrowErr(pVM, "Error: out of memory"); 153 strncpy(name, namep, names); 154 name[names] = '\0'; 155 156 value = getenv(name); 157 ficlFree(name); 158 159 if(value != NULL) { 160 stackPushPtr(pVM->pStack, value); 161 stackPushINT(pVM->pStack, strlen(value)); 162 } else 163#endif 164 stackPushINT(pVM->pStack, -1); 165 166 return; 167} 168 169void 170ficlUnsetenv(FICL_VM *pVM) 171{ 172#ifndef TESTMAIN 173 char *name; 174#endif 175 char *namep; 176 int names; 177 178#if FICL_ROBUST > 1 179 vmCheckStack(pVM, 2, 0); 180#endif 181 names = stackPopINT(pVM->pStack); 182 namep = (char*) stackPopPtr(pVM->pStack); 183 184#ifndef TESTMAIN 185 name = (char*) ficlMalloc(names+1); 186 if (!name) 187 vmThrowErr(pVM, "Error: out of memory"); 188 strncpy(name, namep, names); 189 name[names] = '\0'; 190 191 unsetenv(name); 192 ficlFree(name); 193#endif 194 195 return; 196} 197 198void 199ficlCopyin(FICL_VM *pVM) 200{ 201 void* src; 202 vm_offset_t dest; 203 size_t len; 204 205#if FICL_ROBUST > 1 206 vmCheckStack(pVM, 3, 0); 207#endif 208 209 len = stackPopINT(pVM->pStack); 210 dest = stackPopINT(pVM->pStack); 211 src = stackPopPtr(pVM->pStack); 212 213#ifndef TESTMAIN 214 archsw.arch_copyin(src, dest, len); 215#endif 216 217 return; 218} 219 220void 221ficlCopyout(FICL_VM *pVM) 222{ 223 void* dest; 224 vm_offset_t src; 225 size_t len; 226 227#if FICL_ROBUST > 1 228 vmCheckStack(pVM, 3, 0); 229#endif 230 231 len = stackPopINT(pVM->pStack); 232 dest = stackPopPtr(pVM->pStack); 233 src = stackPopINT(pVM->pStack); 234 235#ifndef TESTMAIN 236 archsw.arch_copyout(src, dest, len); 237#endif 238 239 return; 240} 241 242void 243ficlFindfile(FICL_VM *pVM) 244{ 245#ifndef TESTMAIN 246 char *name; 247#endif 248 char *type, *namep, *typep; 249 struct preloaded_file* fp; 250 int names, types; 251 252#if FICL_ROBUST > 1 253 vmCheckStack(pVM, 4, 1); 254#endif 255 256 types = stackPopINT(pVM->pStack); 257 typep = (char*) stackPopPtr(pVM->pStack); 258 names = stackPopINT(pVM->pStack); 259 namep = (char*) stackPopPtr(pVM->pStack); 260#ifndef TESTMAIN 261 name = (char*) ficlMalloc(names+1); 262 if (!name) 263 vmThrowErr(pVM, "Error: out of memory"); 264 strncpy(name, namep, names); 265 name[names] = '\0'; 266 type = (char*) ficlMalloc(types+1); 267 if (!type) 268 vmThrowErr(pVM, "Error: out of memory"); 269 strncpy(type, typep, types); 270 type[types] = '\0'; 271 272 fp = file_findfile(name, type); 273#else 274 fp = NULL; 275#endif 276 stackPushPtr(pVM->pStack, fp); 277 278 return; 279} 280 281#ifndef TESTMAIN 282#ifdef HAVE_PNP 283 284void 285ficlPnpdevices(FICL_VM *pVM) 286{ 287 static int pnp_devices_initted = 0; 288#if FICL_ROBUST > 1 289 vmCheckStack(pVM, 0, 1); 290#endif 291 292 if(!pnp_devices_initted) { 293 STAILQ_INIT(&pnp_devices); 294 pnp_devices_initted = 1; 295 } 296 297 stackPushPtr(pVM->pStack, &pnp_devices); 298 299 return; 300} 301 302void 303ficlPnphandlers(FICL_VM *pVM) 304{ 305#if FICL_ROBUST > 1 306 vmCheckStack(pVM, 0, 1); 307#endif 308 309 stackPushPtr(pVM->pStack, pnphandlers); 310 311 return; 312} 313 314#endif 315 316#endif /* ndef TESTMAIN */ 317 318void 319ficlCcall(FICL_VM *pVM) 320{ 321 int (*func)(int, ...); 322 int result, p[10]; 323 int nparam, i; 324 325#if FICL_ROBUST > 1 326 vmCheckStack(pVM, 2, 0); 327#endif 328 329 func = stackPopPtr(pVM->pStack); 330 nparam = stackPopINT(pVM->pStack); 331 332#if FICL_ROBUST > 1 333 vmCheckStack(pVM, nparam, 1); 334#endif 335 336 for (i = 0; i < nparam; i++) 337 p[i] = stackPopINT(pVM->pStack); 338 339 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], 340 p[9]); 341 342 stackPushINT(pVM->pStack, result); 343 344 return; 345} 346 347/************************************************************************** 348 f i c l E x e c F D 349** reads in text from file fd and passes it to ficlExec() 350 * returns VM_OUTOFTEXT on success or the ficlExec() error code on 351 * failure. 352 */ 353#define nLINEBUF 256 354int ficlExecFD(FICL_VM *pVM, int fd) 355{ 356 char cp[nLINEBUF]; 357 int nLine = 0, rval = VM_OUTOFTEXT; 358 char ch; 359 CELL id; 360 361 id = pVM->sourceID; 362 pVM->sourceID.i = fd; 363 364 /* feed each line to ficlExec */ 365 while (1) { 366 int status, i; 367 368 i = 0; 369 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n') 370 cp[i++] = ch; 371 nLine++; 372 if (!i) { 373 if (status < 1) 374 break; 375 continue; 376 } 377 rval = ficlExecC(pVM, cp, i); 378 if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT) 379 { 380 pVM->sourceID = id; 381 return rval; 382 } 383 } 384 /* 385 ** Pass an empty line with SOURCE-ID == -1 to flush 386 ** any pending REFILLs (as required by FILE wordset) 387 */ 388 pVM->sourceID.i = -1; 389 ficlExec(pVM, ""); 390 391 pVM->sourceID = id; 392 return rval; 393} 394 395static void displayCellNoPad(FICL_VM *pVM) 396{ 397 CELL c; 398#if FICL_ROBUST > 1 399 vmCheckStack(pVM, 1, 0); 400#endif 401 c = stackPop(pVM->pStack); 402 ltoa((c).i, pVM->pad, pVM->base); 403 vmTextOut(pVM, pVM->pad, 0); 404 return; 405} 406 407/* fopen - open a file and return new fd on stack. 408 * 409 * fopen ( ptr count mode -- fd ) 410 */ 411static void pfopen(FICL_VM *pVM) 412{ 413 int mode, fd, count; 414 char *ptr, *name; 415 416#if FICL_ROBUST > 1 417 vmCheckStack(pVM, 3, 1); 418#endif 419 420 mode = stackPopINT(pVM->pStack); /* get mode */ 421 count = stackPopINT(pVM->pStack); /* get count */ 422 ptr = stackPopPtr(pVM->pStack); /* get ptr */ 423 424 if ((count < 0) || (ptr == NULL)) { 425 stackPushINT(pVM->pStack, -1); 426 return; 427 } 428 429 /* ensure that the string is null terminated */ 430 name = (char *)malloc(count+1); 431 bcopy(ptr,name,count); 432 name[count] = 0; 433 434 /* open the file */ 435 fd = open(name, mode); 436 free(name); 437 stackPushINT(pVM->pStack, fd); 438 return; 439} 440 441/* fclose - close a file who's fd is on stack. 442 * 443 * fclose ( fd -- ) 444 */ 445static void pfclose(FICL_VM *pVM) 446{ 447 int fd; 448 449#if FICL_ROBUST > 1 450 vmCheckStack(pVM, 1, 0); 451#endif 452 fd = stackPopINT(pVM->pStack); /* get fd */ 453 if (fd != -1) 454 close(fd); 455 return; 456} 457 458/* fread - read file contents 459 * 460 * fread ( fd buf nbytes -- nread ) 461 */ 462static void pfread(FICL_VM *pVM) 463{ 464 int fd, len; 465 char *buf; 466 467#if FICL_ROBUST > 1 468 vmCheckStack(pVM, 3, 1); 469#endif 470 len = stackPopINT(pVM->pStack); /* get number of bytes to read */ 471 buf = stackPopPtr(pVM->pStack); /* get buffer */ 472 fd = stackPopINT(pVM->pStack); /* get fd */ 473 if (len > 0 && buf && fd != -1) 474 stackPushINT(pVM->pStack, read(fd, buf, len)); 475 else 476 stackPushINT(pVM->pStack, -1); 477 return; 478} 479 480/* fload - interpret file contents 481 * 482 * fload ( fd -- ) 483 */ 484static void pfload(FICL_VM *pVM) 485{ 486 int fd; 487 488#if FICL_ROBUST > 1 489 vmCheckStack(pVM, 1, 0); 490#endif 491 fd = stackPopINT(pVM->pStack); /* get fd */ 492 if (fd != -1) 493 ficlExecFD(pVM, fd); 494 return; 495} 496 497/* fwrite - write file contents 498 * 499 * fwrite ( fd buf nbytes -- nwritten ) 500 */ 501static void pfwrite(FICL_VM *pVM) 502{ 503 int fd, len; 504 char *buf; 505 506#if FICL_ROBUST > 1 507 vmCheckStack(pVM, 3, 1); 508#endif 509 len = stackPopINT(pVM->pStack); /* get number of bytes to read */ 510 buf = stackPopPtr(pVM->pStack); /* get buffer */ 511 fd = stackPopINT(pVM->pStack); /* get fd */ 512 if (len > 0 && buf && fd != -1) 513 stackPushINT(pVM->pStack, write(fd, buf, len)); 514 else 515 stackPushINT(pVM->pStack, -1); 516 return; 517} 518 519/* fseek - seek to a new position in a file 520 * 521 * fseek ( fd ofs whence -- pos ) 522 */ 523static void pfseek(FICL_VM *pVM) 524{ 525 int fd, pos, whence; 526 527#if FICL_ROBUST > 1 528 vmCheckStack(pVM, 3, 1); 529#endif 530 whence = stackPopINT(pVM->pStack); 531 pos = stackPopINT(pVM->pStack); 532 fd = stackPopINT(pVM->pStack); 533 stackPushINT(pVM->pStack, lseek(fd, pos, whence)); 534 return; 535} 536 537/* key - get a character from stdin 538 * 539 * key ( -- char ) 540 */ 541static void key(FICL_VM *pVM) 542{ 543#if FICL_ROBUST > 1 544 vmCheckStack(pVM, 0, 1); 545#endif 546 stackPushINT(pVM->pStack, getchar()); 547 return; 548} 549 550/* key? - check for a character from stdin (FACILITY) 551 * 552 * key? ( -- flag ) 553 */ 554static void keyQuestion(FICL_VM *pVM) 555{ 556#if FICL_ROBUST > 1 557 vmCheckStack(pVM, 0, 1); 558#endif 559#ifdef TESTMAIN 560 /* XXX Since we don't fiddle with termios, let it always succeed... */ 561 stackPushINT(pVM->pStack, FICL_TRUE); 562#else 563 /* But here do the right thing. */ 564 stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE); 565#endif 566 return; 567} 568 569/* seconds - gives number of seconds since beginning of time 570 * 571 * beginning of time is defined as: 572 * 573 * BTX - number of seconds since midnight 574 * FreeBSD - number of seconds since Jan 1 1970 575 * 576 * seconds ( -- u ) 577 */ 578static void pseconds(FICL_VM *pVM) 579{ 580#if FICL_ROBUST > 1 581 vmCheckStack(pVM,0,1); 582#endif 583 stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL)); 584 return; 585} 586 587/* ms - wait at least that many milliseconds (FACILITY) 588 * 589 * ms ( u -- ) 590 * 591 */ 592static void ms(FICL_VM *pVM) 593{ 594#if FICL_ROBUST > 1 595 vmCheckStack(pVM,1,0); 596#endif 597#ifdef TESTMAIN 598 usleep(stackPopUNS(pVM->pStack)*1000); 599#else 600 delay(stackPopUNS(pVM->pStack)*1000); 601#endif 602 return; 603} 604 605/* fkey - get a character from a file 606 * 607 * fkey ( file -- char ) 608 */ 609static void fkey(FICL_VM *pVM) 610{ 611 int i, fd; 612 char ch; 613 614#if FICL_ROBUST > 1 615 vmCheckStack(pVM, 1, 1); 616#endif 617 fd = stackPopINT(pVM->pStack); 618 i = read(fd, &ch, 1); 619 stackPushINT(pVM->pStack, i > 0 ? ch : -1); 620 return; 621} 622 623/* 624** Retrieves free space remaining on the dictionary 625*/ 626 627static void freeHeap(FICL_VM *pVM) 628{ 629 stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys))); 630} 631 632 633/******************* Increase dictionary size on-demand ******************/ 634 635static void ficlDictThreshold(FICL_VM *pVM) 636{ 637 stackPushPtr(pVM->pStack, &dictThreshold); 638} 639 640static void ficlDictIncrease(FICL_VM *pVM) 641{ 642 stackPushPtr(pVM->pStack, &dictIncrease); 643} 644 645 646/************************************************************************** 647 f i c l C o m p i l e P l a t f o r m 648** Build FreeBSD platform extensions into the system dictionary 649**************************************************************************/ 650void ficlCompilePlatform(FICL_SYSTEM *pSys) 651{ 652 FICL_DICT *dp = pSys->dp; 653 assert (dp); 654 655 dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT); 656 dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT); 657 dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT); 658 dictAppendWord(dp, "fread", pfread, FW_DEFAULT); 659 dictAppendWord(dp, "fload", pfload, FW_DEFAULT); 660 dictAppendWord(dp, "fkey", fkey, FW_DEFAULT); 661 dictAppendWord(dp, "fseek", pfseek, FW_DEFAULT); 662 dictAppendWord(dp, "fwrite", pfwrite, FW_DEFAULT); 663 dictAppendWord(dp, "key", key, FW_DEFAULT); 664 dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT); 665 dictAppendWord(dp, "ms", ms, FW_DEFAULT); 666 dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT); 667 dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT); 668 dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT); 669 dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT); 670 671 dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT); 672 dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT); 673 dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT); 674 dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT); 675 dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT); 676 dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT); 677 dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT); 678 dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT); 679#ifndef TESTMAIN 680#ifdef __i386__ 681 dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT); 682 dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT); 683#endif 684#ifdef HAVE_PNP 685 dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT); 686 dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT); 687#endif 688#endif 689 690#if defined(PC98) 691 ficlSetEnv(pSys, "arch-pc98", FICL_TRUE); 692#elif defined(__i386__) 693 ficlSetEnv(pSys, "arch-i386", FICL_TRUE); 694 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE); 695 ficlSetEnv(pSys, "arch-powerpc", FICL_FALSE); 696#elif defined(__ia64__) 697 ficlSetEnv(pSys, "arch-i386", FICL_FALSE); 698 ficlSetEnv(pSys, "arch-ia64", FICL_TRUE); 699 ficlSetEnv(pSys, "arch-powerpc", FICL_FALSE); 700#elif defined(__powerpc__) 701 ficlSetEnv(pSys, "arch-i386", FICL_FALSE); 702 ficlSetEnv(pSys, "arch-ia64", FICL_FALSE); 703 ficlSetEnv(pSys, "arch-powerpc", FICL_TRUE); 704#endif 705 706 return; 707} 708 709