8888 loader: rename STAND to _STANDALONE
[unleashed.git] / usr / src / common / ficl / loader.c
blobbe642c3b46f316e879fb02ff518332ba88e10064
1 /*
2 * Copyright (c) 2000 Daniel Capo Sobral
3 * All rights reserved.
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.
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.
26 * $FreeBSD$
30 * l o a d e r . c
31 * Additional FICL words designed for FreeBSD's loader
34 #ifndef _STANDALONE
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <strings.h>
43 #include <termios.h>
44 #else
45 #include <stand.h>
46 #ifdef __i386__
47 #include <machine/cpufunc.h>
48 #endif
49 #include "bootstrap.h"
50 #endif
51 #ifdef _STANDALONE
52 #include <uuid.h>
53 #else
54 #include <uuid/uuid.h>
55 #endif
56 #include <string.h>
57 #include "ficl.h"
60 * FreeBSD's loader interaction words and extras
62 * setenv ( value n name n' -- )
63 * setenv? ( value n name n' flag -- )
64 * getenv ( addr n -- addr' n' | -1 )
65 * unsetenv ( addr n -- )
66 * copyin ( addr addr' len -- )
67 * copyout ( addr addr' len -- )
68 * findfile ( name len type len' -- addr )
69 * ccall ( [[...[p10] p9] ... p1] n addr -- result )
70 * uuid-from-string ( addr n -- addr' )
71 * uuid-to-string ( addr' -- addr n | -1 )
72 * .# ( value -- )
75 void
76 ficlSetenv(ficlVm *pVM)
78 char *name, *value;
79 char *namep, *valuep;
80 int names, values;
82 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 0);
84 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
85 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
86 values = ficlStackPopInteger(ficlVmGetDataStack(pVM));
87 valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
89 name = (char *)ficlMalloc(names+1);
90 if (!name)
91 ficlVmThrowError(pVM, "Error: out of memory");
92 strncpy(name, namep, names);
93 name[names] = '\0';
94 value = (char *)ficlMalloc(values+1);
95 if (!value)
96 ficlVmThrowError(pVM, "Error: out of memory");
97 strncpy(value, valuep, values);
98 value[values] = '\0';
100 setenv(name, value, 1);
101 ficlFree(name);
102 ficlFree(value);
105 void
106 ficlSetenvq(ficlVm *pVM)
108 char *name, *value;
109 char *namep, *valuep;
110 int names, values, overwrite;
112 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 5, 0);
114 overwrite = ficlStackPopInteger(ficlVmGetDataStack(pVM));
115 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
116 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
117 values = ficlStackPopInteger(ficlVmGetDataStack(pVM));
118 valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
120 name = (char *)ficlMalloc(names+1);
121 if (!name)
122 ficlVmThrowError(pVM, "Error: out of memory");
123 strncpy(name, namep, names);
124 name[names] = '\0';
125 value = (char *)ficlMalloc(values+1);
126 if (!value)
127 ficlVmThrowError(pVM, "Error: out of memory");
128 strncpy(value, valuep, values);
129 value[values] = '\0';
131 setenv(name, value, overwrite);
132 ficlFree(name);
133 ficlFree(value);
136 void
137 ficlGetenv(ficlVm *pVM)
139 char *name, *value;
140 char *namep;
141 int names;
143 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2);
145 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
146 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
148 name = (char *)ficlMalloc(names+1);
149 if (!name)
150 ficlVmThrowError(pVM, "Error: out of memory");
151 strncpy(name, namep, names);
152 name[names] = '\0';
154 value = getenv(name);
155 ficlFree(name);
157 if (value != NULL) {
158 ficlStackPushPointer(ficlVmGetDataStack(pVM), value);
159 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value));
160 } else
161 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
164 void
165 ficlUnsetenv(ficlVm *pVM)
167 char *name;
168 char *namep;
169 int names;
171 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
173 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
174 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
176 name = (char *)ficlMalloc(names+1);
177 if (!name)
178 ficlVmThrowError(pVM, "Error: out of memory");
179 strncpy(name, namep, names);
180 name[names] = '\0';
182 unsetenv(name);
183 ficlFree(name);
186 void
187 ficlCopyin(ficlVm *pVM)
189 #ifdef _STANDALONE
190 void* src;
191 vm_offset_t dest;
192 size_t len;
193 #endif
195 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0);
197 #ifdef _STANDALONE
198 len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
199 dest = ficlStackPopInteger(ficlVmGetDataStack(pVM));
200 src = ficlStackPopPointer(ficlVmGetDataStack(pVM));
201 archsw.arch_copyin(src, dest, len);
202 #else
203 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
204 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
205 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
206 #endif
209 void
210 ficlCopyout(ficlVm *pVM)
212 #ifdef _STANDALONE
213 void* dest;
214 vm_offset_t src;
215 size_t len;
216 #endif
218 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0);
220 #ifdef _STANDALONE
221 len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
222 dest = ficlStackPopPointer(ficlVmGetDataStack(pVM));
223 src = ficlStackPopInteger(ficlVmGetDataStack(pVM));
224 archsw.arch_copyout(src, dest, len);
225 #else
226 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
227 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
228 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
229 #endif
232 void
233 ficlFindfile(ficlVm *pVM)
235 #ifdef _STANDALONE
236 char *name, *type;
237 char *namep, *typep;
238 int names, types;
239 #endif
240 struct preloaded_file *fp;
242 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 1);
244 #ifdef _STANDALONE
245 types = ficlStackPopInteger(ficlVmGetDataStack(pVM));
246 typep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
247 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
248 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
250 name = (char *)ficlMalloc(names+1);
251 if (!name)
252 ficlVmThrowError(pVM, "Error: out of memory");
253 strncpy(name, namep, names);
254 name[names] = '\0';
255 type = (char *)ficlMalloc(types+1);
256 if (!type)
257 ficlVmThrowError(pVM, "Error: out of memory");
258 strncpy(type, typep, types);
259 type[types] = '\0';
261 fp = file_findfile(name, type);
262 #else
263 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
264 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
265 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
266 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
268 fp = NULL;
269 #endif
270 ficlStackPushPointer(ficlVmGetDataStack(pVM), fp);
273 void
274 ficlCcall(ficlVm *pVM)
276 int (*func)(int, ...);
277 int result, p[10];
278 int nparam, i;
280 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
282 func = (int (*)(int, ...))ficlStackPopPointer(ficlVmGetDataStack(pVM));
283 nparam = ficlStackPopInteger(ficlVmGetDataStack(pVM));
285 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), nparam, 1);
287 for (i = 0; i < nparam; i++)
288 p[i] = ficlStackPopInteger(ficlVmGetDataStack(pVM));
290 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
291 p[9]);
293 ficlStackPushInteger(ficlVmGetDataStack(pVM), result);
296 void
297 ficlUuidFromString(ficlVm *pVM)
299 char *uuid;
300 char *uuid_ptr;
301 int uuid_size;
302 uuid_t *u;
303 #ifdef _STANDALONE
304 uint32_t status;
305 #else
306 int status;
307 #endif
309 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
311 uuid_size = ficlStackPopInteger(ficlVmGetDataStack(pVM));
312 uuid_ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM));
314 uuid = ficlMalloc(uuid_size + 1);
315 if (!uuid)
316 ficlVmThrowError(pVM, "Error: out of memory");
317 (void) memcpy(uuid, uuid_ptr, uuid_size);
318 uuid[uuid_size] = '\0';
320 u = ficlMalloc(sizeof (*u));
321 #ifdef _STANDALONE
322 uuid_from_string(uuid, u, &status);
323 ficlFree(uuid);
324 if (status != uuid_s_ok) {
325 ficlFree(u);
326 u = NULL;
328 #else
329 status = uuid_parse(uuid, *u);
330 ficlFree(uuid);
331 if (status != 0) {
332 ficlFree(u);
333 u = NULL;
335 #endif
336 ficlStackPushPointer(ficlVmGetDataStack(pVM), u);
339 void
340 ficlUuidToString(ficlVm *pVM)
342 char *uuid;
343 uuid_t *u;
344 #ifdef _STANDALONE
345 uint32_t status;
346 #endif
348 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
350 u = ficlStackPopPointer(ficlVmGetDataStack(pVM));
351 #ifdef _STANDALONE
352 uuid_to_string(u, &uuid, &status);
353 if (status == uuid_s_ok) {
354 ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid);
355 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid));
356 } else
357 #else
358 uuid = ficlMalloc(UUID_PRINTABLE_STRING_LENGTH);
359 if (uuid != NULL) {
360 uuid_unparse(*u, uuid);
361 ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid);
362 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid));
363 } else
364 #endif
365 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
369 * f i c l E x e c F D
370 * reads in text from file fd and passes it to ficlExec()
371 * returns FICL_VM_STATUS_OUT_OF_TEXT on success or the ficlExec() error
372 * code on failure.
374 #define nLINEBUF 256
376 ficlExecFD(ficlVm *pVM, int fd)
378 char cp[nLINEBUF];
379 int nLine = 0, rval = FICL_VM_STATUS_OUT_OF_TEXT;
380 char ch;
381 ficlCell id;
382 ficlString s;
384 id = pVM->sourceId;
385 pVM->sourceId.i = fd+1; /* in loader we can get 0, there is no stdin */
387 /* feed each line to ficlExec */
388 while (1) {
389 int status, i;
391 i = 0;
392 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
393 cp[i++] = ch;
394 nLine++;
395 if (!i) {
396 if (status < 1)
397 break;
398 continue;
400 if (cp[i] == '\n')
401 cp[i] = '\0';
403 FICL_STRING_SET_POINTER(s, cp);
404 FICL_STRING_SET_LENGTH(s, i);
406 rval = ficlVmExecuteString(pVM, s);
407 if (rval != FICL_VM_STATUS_QUIT &&
408 rval != FICL_VM_STATUS_USER_EXIT &&
409 rval != FICL_VM_STATUS_OUT_OF_TEXT) {
410 pVM->sourceId = id;
411 (void) ficlVmEvaluate(pVM, "");
412 return (rval);
415 pVM->sourceId = id;
418 * Pass an empty line with SOURCE-ID == -1 to flush
419 * any pending REFILLs (as required by FILE wordset)
421 (void) ficlVmEvaluate(pVM, "");
423 if (rval == FICL_VM_STATUS_USER_EXIT)
424 ficlVmThrow(pVM, FICL_VM_STATUS_USER_EXIT);
426 return (rval);
429 static void displayCellNoPad(ficlVm *pVM)
431 ficlCell c;
432 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
434 c = ficlStackPop(ficlVmGetDataStack(pVM));
435 ficlLtoa((c).i, pVM->pad, pVM->base);
436 ficlVmTextOut(pVM, pVM->pad);
440 * isdir? - Return whether an fd corresponds to a directory.
442 * isdir? ( fd -- bool )
444 static void
445 isdirQuestion(ficlVm *pVM)
447 struct stat sb;
448 ficlInteger flag;
449 int fd;
451 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
453 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
454 flag = FICL_FALSE;
455 do {
456 if (fd < 0)
457 break;
458 if (fstat(fd, &sb) < 0)
459 break;
460 if (!S_ISDIR(sb.st_mode))
461 break;
462 flag = FICL_TRUE;
463 } while (0);
464 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
468 * fopen - open a file and return new fd on stack.
470 * fopen ( ptr count mode -- fd )
472 extern char *get_dev(const char *);
474 static void
475 pfopen(ficlVm *pVM)
477 int mode, fd, count;
478 char *ptr, *name;
479 #ifndef _STANDALONE
480 char *tmp;
481 #endif
483 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
485 mode = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get mode */
486 count = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get count */
487 ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get ptr */
489 if ((count < 0) || (ptr == NULL)) {
490 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
491 return;
494 /* ensure that the string is null terminated */
495 name = (char *)malloc(count+1);
496 bcopy(ptr, name, count);
497 name[count] = 0;
498 #ifndef _STANDALONE
499 tmp = get_dev(name);
500 free(name);
501 name = tmp;
502 #endif
504 /* open the file */
505 fd = open(name, mode);
506 free(name);
507 ficlStackPushInteger(ficlVmGetDataStack(pVM), fd);
511 * fclose - close a file who's fd is on stack.
512 * fclose ( fd -- )
514 static void
515 pfclose(ficlVm *pVM)
517 int fd;
519 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
521 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
522 if (fd != -1)
523 close(fd);
527 * fread - read file contents
528 * fread ( fd buf nbytes -- nread )
530 static void
531 pfread(ficlVm *pVM)
533 int fd, len;
534 char *buf;
536 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
538 len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
539 buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */
540 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
541 if (len > 0 && buf && fd != -1)
542 ficlStackPushInteger(ficlVmGetDataStack(pVM),
543 read(fd, buf, len));
544 else
545 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
549 * fopendir - open directory
551 * fopendir ( addr len -- ptr TRUE | FALSE )
553 static void pfopendir(ficlVm *pVM)
555 #ifndef _STANDALONE
556 DIR *dir;
557 char *tmp;
558 #else
559 struct stat sb;
560 int fd;
561 #endif
562 int count;
563 char *ptr, *name;
564 ficlInteger flag = FICL_FALSE;
566 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 1);
568 count = ficlStackPopInteger(ficlVmGetDataStack(pVM));
569 ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get ptr */
571 if ((count < 0) || (ptr == NULL)) {
572 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
573 return;
575 /* ensure that the string is null terminated */
576 name = (char *)malloc(count+1);
577 bcopy(ptr, name, count);
578 name[count] = 0;
579 #ifndef _STANDALONE
580 tmp = get_dev(name);
581 free(name);
582 name = tmp;
583 #else
584 fd = open(name, O_RDONLY);
585 free(name);
586 do {
587 if (fd < 0)
588 break;
589 if (fstat(fd, &sb) < 0)
590 break;
591 if (!S_ISDIR(sb.st_mode))
592 break;
593 flag = FICL_TRUE;
594 ficlStackPushInteger(ficlVmGetDataStack(pVM), fd);
595 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
596 return;
597 } while (0);
599 if (fd >= 0)
600 close(fd);
602 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
603 return;
604 #endif
605 #ifndef _STANDALONE
606 dir = opendir(name);
607 if (dir == NULL) {
608 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
609 return;
610 } else
611 flag = FICL_TRUE;
613 ficlStackPushPointer(ficlVmGetDataStack(pVM), dir);
614 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
615 #endif
619 * freaddir - read directory contents
620 * freaddir ( fd -- ptr len TRUE | FALSE )
622 static void
623 pfreaddir(ficlVm *pVM)
625 #ifndef _STANDALONE
626 static DIR *dir = NULL;
627 #else
628 int fd;
629 #endif
630 struct dirent *d = NULL;
632 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 3);
634 * libstand readdir does not always return . nor .. so filter
635 * them out to have consistent behaviour.
637 #ifndef _STANDALONE
638 dir = ficlStackPopPointer(ficlVmGetDataStack(pVM));
639 if (dir != NULL)
640 do {
641 d = readdir(dir);
642 if (d != NULL && strcmp(d->d_name, ".") == 0)
643 continue;
644 if (d != NULL && strcmp(d->d_name, "..") == 0)
645 continue;
646 break;
647 } while (d != NULL);
648 #else
649 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
650 if (fd != -1)
651 do {
652 d = readdirfd(fd);
653 if (d != NULL && strcmp(d->d_name, ".") == 0)
654 continue;
655 if (d != NULL && strcmp(d->d_name, "..") == 0)
656 continue;
657 break;
658 } while (d != NULL);
659 #endif
660 if (d != NULL) {
661 ficlStackPushPointer(ficlVmGetDataStack(pVM), d->d_name);
662 ficlStackPushInteger(ficlVmGetDataStack(pVM),
663 strlen(d->d_name));
664 ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_TRUE);
665 } else {
666 ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_FALSE);
671 * fclosedir - close a dir on stack.
673 * fclosedir ( fd -- )
675 static void
676 pfclosedir(ficlVm *pVM)
678 #ifndef _STANDALONE
679 DIR *dir;
680 #else
681 int fd;
682 #endif
684 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
686 #ifndef _STANDALONE
687 dir = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get dir */
688 if (dir != NULL)
689 closedir(dir);
690 #else
691 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
692 if (fd != -1)
693 close(fd);
694 #endif
698 * fload - interpret file contents
700 * fload ( fd -- )
702 static void pfload(ficlVm *pVM)
704 int fd;
706 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
708 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
709 if (fd != -1)
710 ficlExecFD(pVM, fd);
714 * fwrite - write file contents
716 * fwrite ( fd buf nbytes -- nwritten )
718 static void
719 pfwrite(ficlVm *pVM)
721 int fd, len;
722 char *buf;
724 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
726 len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* bytes to read */
727 buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */
728 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
729 if (len > 0 && buf && fd != -1)
730 ficlStackPushInteger(ficlVmGetDataStack(pVM),
731 write(fd, buf, len));
732 else
733 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
737 * fseek - seek to a new position in a file
739 * fseek ( fd ofs whence -- pos )
741 static void
742 pfseek(ficlVm *pVM)
744 int fd, pos, whence;
746 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
748 whence = ficlStackPopInteger(ficlVmGetDataStack(pVM));
749 pos = ficlStackPopInteger(ficlVmGetDataStack(pVM));
750 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
751 ficlStackPushInteger(ficlVmGetDataStack(pVM), lseek(fd, pos, whence));
755 * key - get a character from stdin
757 * key ( -- char )
759 static void
760 key(ficlVm *pVM)
762 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
764 ficlStackPushInteger(ficlVmGetDataStack(pVM), getchar());
768 * key? - check for a character from stdin (FACILITY)
769 * key? ( -- flag )
771 static void
772 keyQuestion(ficlVm *pVM)
774 #ifndef _STANDALONE
775 char ch = -1;
776 struct termios oldt;
777 struct termios newt;
778 #endif
780 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
782 #ifndef _STANDALONE
783 tcgetattr(STDIN_FILENO, &oldt);
784 newt = oldt;
785 newt.c_lflag &= ~(ICANON | ECHO);
786 newt.c_cc[VMIN] = 0;
787 newt.c_cc[VTIME] = 0;
788 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
789 ch = getchar();
790 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
792 if (ch != -1)
793 (void) ungetc(ch, stdin);
795 ficlStackPushInteger(ficlVmGetDataStack(pVM),
796 ch != -1? FICL_TRUE : FICL_FALSE);
797 #else
798 ficlStackPushInteger(ficlVmGetDataStack(pVM),
799 ischar()? FICL_TRUE : FICL_FALSE);
800 #endif
804 * seconds - gives number of seconds since beginning of time
806 * beginning of time is defined as:
808 * BTX - number of seconds since midnight
809 * FreeBSD - number of seconds since Jan 1 1970
811 * seconds ( -- u )
813 static void
814 pseconds(ficlVm *pVM)
816 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
818 ficlStackPushUnsigned(ficlVmGetDataStack(pVM),
819 (ficlUnsigned) time(NULL));
823 * ms - wait at least that many milliseconds (FACILITY)
824 * ms ( u -- )
826 static void
827 ms(ficlVm *pVM)
829 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
831 #ifndef _STANDALONE
832 usleep(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000);
833 #else
834 delay(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000);
835 #endif
839 * fkey - get a character from a file
840 * fkey ( file -- char )
842 static void
843 fkey(ficlVm *pVM)
845 int i, fd;
846 char ch;
848 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
850 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
851 i = read(fd, &ch, 1);
852 ficlStackPushInteger(ficlVmGetDataStack(pVM), i > 0 ? ch : -1);
856 #ifdef _STANDALONE
857 #ifdef __i386__
860 * outb ( port# c -- )
861 * Store a byte to I/O port number port#
863 void
864 ficlOutb(ficlVm *pVM)
866 uint8_t c;
867 uint32_t port;
869 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
870 c = ficlStackPopInteger(ficlVmGetDataStack(pVM));
871 outb(port, c);
875 * inb ( port# -- c )
876 * Fetch a byte from I/O port number port#
878 void
879 ficlInb(ficlVm *pVM)
881 uint8_t c;
882 uint32_t port;
884 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
885 c = inb(port);
886 ficlStackPushInteger(ficlVmGetDataStack(pVM), c);
888 #endif
889 #endif
892 * Retrieves free space remaining on the dictionary
894 static void
895 freeHeap(ficlVm *pVM)
897 ficlStackPushInteger(ficlVmGetDataStack(pVM),
898 ficlDictionaryCellsAvailable(ficlVmGetDictionary(pVM)));
902 * f i c l C o m p i l e P l a t f o r m
903 * Build FreeBSD platform extensions into the system dictionary
905 void
906 ficlSystemCompilePlatform(ficlSystem *pSys)
908 ficlDictionary *dp = ficlSystemGetDictionary(pSys);
909 ficlDictionary *env = ficlSystemGetEnvironment(pSys);
910 #ifdef _STANDALONE
911 ficlCompileFcn **fnpp;
912 #endif
914 FICL_SYSTEM_ASSERT(pSys, dp);
915 FICL_SYSTEM_ASSERT(pSys, env);
917 ficlDictionarySetPrimitive(dp, ".#", displayCellNoPad,
918 FICL_WORD_DEFAULT);
919 ficlDictionarySetPrimitive(dp, "isdir?", isdirQuestion,
920 FICL_WORD_DEFAULT);
921 ficlDictionarySetPrimitive(dp, "fopen", pfopen, FICL_WORD_DEFAULT);
922 ficlDictionarySetPrimitive(dp, "fclose", pfclose, FICL_WORD_DEFAULT);
923 ficlDictionarySetPrimitive(dp, "fread", pfread, FICL_WORD_DEFAULT);
924 ficlDictionarySetPrimitive(dp, "fopendir", pfopendir,
925 FICL_WORD_DEFAULT);
926 ficlDictionarySetPrimitive(dp, "freaddir", pfreaddir,
927 FICL_WORD_DEFAULT);
928 ficlDictionarySetPrimitive(dp, "fclosedir", pfclosedir,
929 FICL_WORD_DEFAULT);
930 ficlDictionarySetPrimitive(dp, "fload", pfload, FICL_WORD_DEFAULT);
931 ficlDictionarySetPrimitive(dp, "fkey", fkey, FICL_WORD_DEFAULT);
932 ficlDictionarySetPrimitive(dp, "fseek", pfseek, FICL_WORD_DEFAULT);
933 ficlDictionarySetPrimitive(dp, "fwrite", pfwrite, FICL_WORD_DEFAULT);
934 ficlDictionarySetPrimitive(dp, "key", key, FICL_WORD_DEFAULT);
935 ficlDictionarySetPrimitive(dp, "key?", keyQuestion, FICL_WORD_DEFAULT);
936 ficlDictionarySetPrimitive(dp, "ms", ms, FICL_WORD_DEFAULT);
937 ficlDictionarySetPrimitive(dp, "seconds", pseconds, FICL_WORD_DEFAULT);
938 ficlDictionarySetPrimitive(dp, "heap?", freeHeap, FICL_WORD_DEFAULT);
940 ficlDictionarySetPrimitive(dp, "setenv", ficlSetenv, FICL_WORD_DEFAULT);
941 ficlDictionarySetPrimitive(dp, "setenv?", ficlSetenvq,
942 FICL_WORD_DEFAULT);
943 ficlDictionarySetPrimitive(dp, "getenv", ficlGetenv, FICL_WORD_DEFAULT);
944 ficlDictionarySetPrimitive(dp, "unsetenv", ficlUnsetenv,
945 FICL_WORD_DEFAULT);
946 ficlDictionarySetPrimitive(dp, "copyin", ficlCopyin, FICL_WORD_DEFAULT);
947 ficlDictionarySetPrimitive(dp, "copyout", ficlCopyout,
948 FICL_WORD_DEFAULT);
949 ficlDictionarySetPrimitive(dp, "findfile", ficlFindfile,
950 FICL_WORD_DEFAULT);
951 ficlDictionarySetPrimitive(dp, "ccall", ficlCcall, FICL_WORD_DEFAULT);
952 ficlDictionarySetPrimitive(dp, "uuid-from-string", ficlUuidFromString,
953 FICL_WORD_DEFAULT);
954 ficlDictionarySetPrimitive(dp, "uuid-to-string", ficlUuidToString,
955 FICL_WORD_DEFAULT);
956 #ifdef _STANDALONE
957 #ifdef __i386__
958 ficlDictionarySetPrimitive(dp, "outb", ficlOutb, FICL_WORD_DEFAULT);
959 ficlDictionarySetPrimitive(dp, "inb", ficlInb, FICL_WORD_DEFAULT);
960 #endif
961 /* Register words from linker set. */
962 SET_FOREACH(fnpp, Xficl_compile_set)
963 (*fnpp)(pSys);
964 #endif
966 #if defined(__i386__) || defined(__amd64__)
967 ficlDictionarySetConstant(env, "arch-i386", FICL_TRUE);
968 ficlDictionarySetConstant(env, "arch-sparc", FICL_FALSE);
969 #endif
970 #ifdef __sparc
971 ficlDictionarySetConstant(env, "arch-i386", FICL_FALSE);
972 ficlDictionarySetConstant(env, "arch-sparc", FICL_TRUE);
973 #endif