8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / common / ficl / loader.c
blob054beba91ae6198663b07995ff3fca8db467a47a
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 STAND
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 STAND
52 #include <uuid.h>
53 #else
54 #include <uuid/uuid.h>
55 #endif
56 #include <string.h>
57 #include "ficl.h"
59 extern int biospci_count_device_type(uint32_t);
60 extern int biospci_write_config(uint32_t, int, int, uint32_t);
61 extern int biospci_read_config(uint32_t, int, int, uint32_t *);
62 extern int biospci_find_devclass(uint32_t, int, uint32_t *);
63 extern int biospci_find_device(uint32_t, int, uint32_t *);
64 extern uint32_t biospci_locator(uint8_t, uint8_t, uint8_t);
67 * FreeBSD's loader interaction words and extras
69 * setenv ( value n name n' -- )
70 * setenv? ( value n name n' flag -- )
71 * getenv ( addr n -- addr' n' | -1 )
72 * unsetenv ( addr n -- )
73 * copyin ( addr addr' len -- )
74 * copyout ( addr addr' len -- )
75 * findfile ( name len type len' -- addr )
76 * pnpdevices ( -- addr )
77 * pnphandlers ( -- addr )
78 * ccall ( [[...[p10] p9] ... p1] n addr -- result )
79 * uuid-from-string ( addr n -- addr' )
80 * uuid-to-string ( addr' -- addr n | -1 )
81 * .# ( value -- )
84 void
85 ficlSetenv(ficlVm *pVM)
87 char *name, *value;
88 char *namep, *valuep;
89 int names, values;
91 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 0);
93 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
94 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
95 values = ficlStackPopInteger(ficlVmGetDataStack(pVM));
96 valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
98 name = (char *)ficlMalloc(names+1);
99 if (!name)
100 ficlVmThrowError(pVM, "Error: out of memory");
101 strncpy(name, namep, names);
102 name[names] = '\0';
103 value = (char *)ficlMalloc(values+1);
104 if (!value)
105 ficlVmThrowError(pVM, "Error: out of memory");
106 strncpy(value, valuep, values);
107 value[values] = '\0';
109 setenv(name, value, 1);
110 ficlFree(name);
111 ficlFree(value);
114 void
115 ficlSetenvq(ficlVm *pVM)
117 char *name, *value;
118 char *namep, *valuep;
119 int names, values, overwrite;
121 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 5, 0);
123 overwrite = ficlStackPopInteger(ficlVmGetDataStack(pVM));
124 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
125 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
126 values = ficlStackPopInteger(ficlVmGetDataStack(pVM));
127 valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
129 name = (char *)ficlMalloc(names+1);
130 if (!name)
131 ficlVmThrowError(pVM, "Error: out of memory");
132 strncpy(name, namep, names);
133 name[names] = '\0';
134 value = (char *)ficlMalloc(values+1);
135 if (!value)
136 ficlVmThrowError(pVM, "Error: out of memory");
137 strncpy(value, valuep, values);
138 value[values] = '\0';
140 setenv(name, value, overwrite);
141 ficlFree(name);
142 ficlFree(value);
145 void
146 ficlGetenv(ficlVm *pVM)
148 char *name, *value;
149 char *namep;
150 int names;
152 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2);
154 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
155 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
157 name = (char *)ficlMalloc(names+1);
158 if (!name)
159 ficlVmThrowError(pVM, "Error: out of memory");
160 strncpy(name, namep, names);
161 name[names] = '\0';
163 value = getenv(name);
164 ficlFree(name);
166 if (value != NULL) {
167 ficlStackPushPointer(ficlVmGetDataStack(pVM), value);
168 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value));
169 } else
170 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
173 void
174 ficlUnsetenv(ficlVm *pVM)
176 char *name;
177 char *namep;
178 int names;
180 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
182 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
183 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
185 name = (char *)ficlMalloc(names+1);
186 if (!name)
187 ficlVmThrowError(pVM, "Error: out of memory");
188 strncpy(name, namep, names);
189 name[names] = '\0';
191 unsetenv(name);
192 ficlFree(name);
195 void
196 ficlCopyin(ficlVm *pVM)
198 #ifdef STAND
199 void* src;
200 vm_offset_t dest;
201 size_t len;
202 #endif
204 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0);
206 #ifdef STAND
207 len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
208 dest = ficlStackPopInteger(ficlVmGetDataStack(pVM));
209 src = ficlStackPopPointer(ficlVmGetDataStack(pVM));
210 archsw.arch_copyin(src, dest, len);
211 #else
212 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
213 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
214 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
215 #endif
218 void
219 ficlCopyout(ficlVm *pVM)
221 #ifdef STAND
222 void* dest;
223 vm_offset_t src;
224 size_t len;
225 #endif
227 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0);
229 #ifdef STAND
230 len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
231 dest = ficlStackPopPointer(ficlVmGetDataStack(pVM));
232 src = ficlStackPopInteger(ficlVmGetDataStack(pVM));
233 archsw.arch_copyout(src, dest, len);
234 #else
235 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
236 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
237 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
238 #endif
241 void
242 ficlFindfile(ficlVm *pVM)
244 #ifdef STAND
245 char *name, *type;
246 char *namep, *typep;
247 int names, types;
248 #endif
249 struct preloaded_file *fp;
251 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 1);
253 #ifdef STAND
254 types = ficlStackPopInteger(ficlVmGetDataStack(pVM));
255 typep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
256 names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
257 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
259 name = (char *)ficlMalloc(names+1);
260 if (!name)
261 ficlVmThrowError(pVM, "Error: out of memory");
262 strncpy(name, namep, names);
263 name[names] = '\0';
264 type = (char *)ficlMalloc(types+1);
265 if (!type)
266 ficlVmThrowError(pVM, "Error: out of memory");
267 strncpy(type, typep, types);
268 type[types] = '\0';
270 fp = file_findfile(name, type);
271 #else
272 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
273 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
274 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
275 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
277 fp = NULL;
278 #endif
279 ficlStackPushPointer(ficlVmGetDataStack(pVM), fp);
282 #ifdef STAND
283 #ifdef HAVE_PNP
285 void
286 ficlPnpdevices(ficlVm *pVM)
288 static int pnp_devices_initted = 0;
290 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
292 if (!pnp_devices_initted) {
293 STAILQ_INIT(&pnp_devices);
294 pnp_devices_initted = 1;
297 ficlStackPushPointer(ficlVmGetDataStack(pVM), &pnp_devices);
300 void
301 ficlPnphandlers(ficlVm *pVM)
303 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
305 ficlStackPushPointer(ficlVmGetDataStack(pVM), pnphandlers);
308 #endif
309 #endif /* ifdef STAND */
311 void
312 ficlCcall(ficlVm *pVM)
314 int (*func)(int, ...);
315 int result, p[10];
316 int nparam, i;
318 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
320 func = (int (*)(int, ...))ficlStackPopPointer(ficlVmGetDataStack(pVM));
321 nparam = ficlStackPopInteger(ficlVmGetDataStack(pVM));
323 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), nparam, 1);
325 for (i = 0; i < nparam; i++)
326 p[i] = ficlStackPopInteger(ficlVmGetDataStack(pVM));
328 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
329 p[9]);
331 ficlStackPushInteger(ficlVmGetDataStack(pVM), result);
334 void
335 ficlUuidFromString(ficlVm *pVM)
337 char *uuid;
338 char *uuid_ptr;
339 int uuid_size;
340 uuid_t *u;
341 #ifdef STAND
342 uint32_t status;
343 #else
344 int status;
345 #endif
347 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
349 uuid_size = ficlStackPopInteger(ficlVmGetDataStack(pVM));
350 uuid_ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM));
352 uuid = ficlMalloc(uuid_size + 1);
353 if (!uuid)
354 ficlVmThrowError(pVM, "Error: out of memory");
355 (void) memcpy(uuid, uuid_ptr, uuid_size);
356 uuid[uuid_size] = '\0';
358 u = ficlMalloc(sizeof (*u));
359 #ifdef STAND
360 uuid_from_string(uuid, u, &status);
361 ficlFree(uuid);
362 if (status != uuid_s_ok) {
363 ficlFree(u);
364 u = NULL;
366 #else
367 status = uuid_parse(uuid, *u);
368 ficlFree(uuid);
369 if (status != 0) {
370 ficlFree(u);
371 u = NULL;
373 #endif
374 ficlStackPushPointer(ficlVmGetDataStack(pVM), u);
377 void
378 ficlUuidToString(ficlVm *pVM)
380 char *uuid;
381 uuid_t *u;
382 #ifdef STAND
383 uint32_t status;
384 #endif
386 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
388 u = ficlStackPopPointer(ficlVmGetDataStack(pVM));
389 #ifdef STAND
390 uuid_to_string(u, &uuid, &status);
391 if (status == uuid_s_ok) {
392 ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid);
393 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid));
394 } else
395 #else
396 uuid = ficlMalloc(UUID_PRINTABLE_STRING_LENGTH);
397 if (uuid != NULL) {
398 uuid_unparse(*u, uuid);
399 ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid);
400 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid));
401 } else
402 #endif
403 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
407 * f i c l E x e c F D
408 * reads in text from file fd and passes it to ficlExec()
409 * returns FICL_VM_STATUS_OUT_OF_TEXT on success or the ficlExec() error
410 * code on failure.
412 #define nLINEBUF 256
414 ficlExecFD(ficlVm *pVM, int fd)
416 char cp[nLINEBUF];
417 int nLine = 0, rval = FICL_VM_STATUS_OUT_OF_TEXT;
418 char ch;
419 ficlCell id;
420 ficlString s;
422 id = pVM->sourceId;
423 pVM->sourceId.i = fd+1; /* in loader we can get 0, there is no stdin */
425 /* feed each line to ficlExec */
426 while (1) {
427 int status, i;
429 i = 0;
430 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
431 cp[i++] = ch;
432 nLine++;
433 if (!i) {
434 if (status < 1)
435 break;
436 continue;
438 if (cp[i] == '\n')
439 cp[i] = '\0';
441 FICL_STRING_SET_POINTER(s, cp);
442 FICL_STRING_SET_LENGTH(s, i);
444 rval = ficlVmExecuteString(pVM, s);
445 if (rval != FICL_VM_STATUS_QUIT &&
446 rval != FICL_VM_STATUS_USER_EXIT &&
447 rval != FICL_VM_STATUS_OUT_OF_TEXT) {
448 pVM->sourceId = id;
449 (void) ficlVmEvaluate(pVM, "");
450 return (rval);
453 pVM->sourceId = id;
456 * Pass an empty line with SOURCE-ID == -1 to flush
457 * any pending REFILLs (as required by FILE wordset)
459 (void) ficlVmEvaluate(pVM, "");
461 if (rval == FICL_VM_STATUS_USER_EXIT)
462 ficlVmThrow(pVM, FICL_VM_STATUS_USER_EXIT);
464 return (rval);
467 static void displayCellNoPad(ficlVm *pVM)
469 ficlCell c;
470 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
472 c = ficlStackPop(ficlVmGetDataStack(pVM));
473 ficlLtoa((c).i, pVM->pad, pVM->base);
474 ficlVmTextOut(pVM, pVM->pad);
478 * isdir? - Return whether an fd corresponds to a directory.
480 * isdir? ( fd -- bool )
482 static void
483 isdirQuestion(ficlVm *pVM)
485 struct stat sb;
486 ficlInteger flag;
487 int fd;
489 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
491 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
492 flag = FICL_FALSE;
493 do {
494 if (fd < 0)
495 break;
496 if (fstat(fd, &sb) < 0)
497 break;
498 if (!S_ISDIR(sb.st_mode))
499 break;
500 flag = FICL_TRUE;
501 } while (0);
502 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
506 * fopen - open a file and return new fd on stack.
508 * fopen ( ptr count mode -- fd )
510 extern char *get_dev(const char *);
512 static void
513 pfopen(ficlVm *pVM)
515 int mode, fd, count;
516 char *ptr, *name;
517 #ifndef STAND
518 char *tmp;
519 #endif
521 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
523 mode = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get mode */
524 count = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get count */
525 ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get ptr */
527 if ((count < 0) || (ptr == NULL)) {
528 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
529 return;
532 /* ensure that the string is null terminated */
533 name = (char *)malloc(count+1);
534 bcopy(ptr, name, count);
535 name[count] = 0;
536 #ifndef STAND
537 tmp = get_dev(name);
538 free(name);
539 name = tmp;
540 #endif
542 /* open the file */
543 fd = open(name, mode);
544 free(name);
545 ficlStackPushInteger(ficlVmGetDataStack(pVM), fd);
549 * fclose - close a file who's fd is on stack.
550 * fclose ( fd -- )
552 static void
553 pfclose(ficlVm *pVM)
555 int fd;
557 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
559 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
560 if (fd != -1)
561 close(fd);
565 * fread - read file contents
566 * fread ( fd buf nbytes -- nread )
568 static void
569 pfread(ficlVm *pVM)
571 int fd, len;
572 char *buf;
574 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
576 len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
577 buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */
578 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
579 if (len > 0 && buf && fd != -1)
580 ficlStackPushInteger(ficlVmGetDataStack(pVM),
581 read(fd, buf, len));
582 else
583 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
587 * fopendir - open directory
589 * fopendir ( addr len -- ptr TRUE | FALSE )
591 static void pfopendir(ficlVm *pVM)
593 #ifndef STAND
594 DIR *dir;
595 char *tmp;
596 #else
597 struct stat sb;
598 int fd;
599 #endif
600 int count;
601 char *ptr, *name;
602 ficlInteger flag = FICL_FALSE;
604 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 1);
606 count = ficlStackPopInteger(ficlVmGetDataStack(pVM));
607 ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get ptr */
609 if ((count < 0) || (ptr == NULL)) {
610 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
611 return;
613 /* ensure that the string is null terminated */
614 name = (char *)malloc(count+1);
615 bcopy(ptr, name, count);
616 name[count] = 0;
617 #ifndef STAND
618 tmp = get_dev(name);
619 free(name);
620 name = tmp;
621 #else
622 fd = open(name, O_RDONLY);
623 free(name);
624 do {
625 if (fd < 0)
626 break;
627 if (fstat(fd, &sb) < 0)
628 break;
629 if (!S_ISDIR(sb.st_mode))
630 break;
631 flag = FICL_TRUE;
632 ficlStackPushInteger(ficlVmGetDataStack(pVM), fd);
633 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
634 return;
635 } while (0);
637 if (fd >= 0)
638 close(fd);
640 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
641 return;
642 #endif
643 #ifndef STAND
644 dir = opendir(name);
645 if (dir == NULL) {
646 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
647 return;
648 } else
649 flag = FICL_TRUE;
651 ficlStackPushPointer(ficlVmGetDataStack(pVM), dir);
652 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
653 #endif
657 * freaddir - read directory contents
658 * freaddir ( fd -- ptr len TRUE | FALSE )
660 static void
661 pfreaddir(ficlVm *pVM)
663 #ifndef STAND
664 static DIR *dir = NULL;
665 #else
666 int fd;
667 #endif
668 struct dirent *d = NULL;
670 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 3);
672 * libstand readdir does not always return . nor .. so filter
673 * them out to have consistent behaviour.
675 #ifndef STAND
676 dir = ficlStackPopPointer(ficlVmGetDataStack(pVM));
677 if (dir != NULL)
678 do {
679 d = readdir(dir);
680 if (d != NULL && strcmp(d->d_name, ".") == 0)
681 continue;
682 if (d != NULL && strcmp(d->d_name, "..") == 0)
683 continue;
684 break;
685 } while (d != NULL);
686 #else
687 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
688 if (fd != -1)
689 do {
690 d = readdirfd(fd);
691 if (d != NULL && strcmp(d->d_name, ".") == 0)
692 continue;
693 if (d != NULL && strcmp(d->d_name, "..") == 0)
694 continue;
695 break;
696 } while (d != NULL);
697 #endif
698 if (d != NULL) {
699 ficlStackPushPointer(ficlVmGetDataStack(pVM), d->d_name);
700 ficlStackPushInteger(ficlVmGetDataStack(pVM),
701 strlen(d->d_name));
702 ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_TRUE);
703 } else {
704 ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_FALSE);
709 * fclosedir - close a dir on stack.
711 * fclosedir ( fd -- )
713 static void
714 pfclosedir(ficlVm *pVM)
716 #ifndef STAND
717 DIR *dir;
718 #else
719 int fd;
720 #endif
722 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
724 #ifndef STAND
725 dir = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get dir */
726 if (dir != NULL)
727 closedir(dir);
728 #else
729 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
730 if (fd != -1)
731 close(fd);
732 #endif
736 * fload - interpret file contents
738 * fload ( fd -- )
740 static void pfload(ficlVm *pVM)
742 int fd;
744 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
746 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
747 if (fd != -1)
748 ficlExecFD(pVM, fd);
752 * fwrite - write file contents
754 * fwrite ( fd buf nbytes -- nwritten )
756 static void
757 pfwrite(ficlVm *pVM)
759 int fd, len;
760 char *buf;
762 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
764 len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* bytes to read */
765 buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */
766 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
767 if (len > 0 && buf && fd != -1)
768 ficlStackPushInteger(ficlVmGetDataStack(pVM),
769 write(fd, buf, len));
770 else
771 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
775 * fseek - seek to a new position in a file
777 * fseek ( fd ofs whence -- pos )
779 static void
780 pfseek(ficlVm *pVM)
782 int fd, pos, whence;
784 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
786 whence = ficlStackPopInteger(ficlVmGetDataStack(pVM));
787 pos = ficlStackPopInteger(ficlVmGetDataStack(pVM));
788 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
789 ficlStackPushInteger(ficlVmGetDataStack(pVM), lseek(fd, pos, whence));
793 * key - get a character from stdin
795 * key ( -- char )
797 static void
798 key(ficlVm *pVM)
800 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
802 ficlStackPushInteger(ficlVmGetDataStack(pVM), getchar());
806 * key? - check for a character from stdin (FACILITY)
807 * key? ( -- flag )
809 static void
810 keyQuestion(ficlVm *pVM)
812 #ifndef STAND
813 char ch = -1;
814 struct termios oldt;
815 struct termios newt;
816 #endif
818 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
820 #ifndef STAND
821 tcgetattr(STDIN_FILENO, &oldt);
822 newt = oldt;
823 newt.c_lflag &= ~(ICANON | ECHO);
824 newt.c_cc[VMIN] = 0;
825 newt.c_cc[VTIME] = 0;
826 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
827 ch = getchar();
828 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
830 if (ch != -1)
831 (void) ungetc(ch, stdin);
833 ficlStackPushInteger(ficlVmGetDataStack(pVM),
834 ch != -1? FICL_TRUE : FICL_FALSE);
835 #else
836 ficlStackPushInteger(ficlVmGetDataStack(pVM),
837 ischar()? FICL_TRUE : FICL_FALSE);
838 #endif
842 * seconds - gives number of seconds since beginning of time
844 * beginning of time is defined as:
846 * BTX - number of seconds since midnight
847 * FreeBSD - number of seconds since Jan 1 1970
849 * seconds ( -- u )
851 static void
852 pseconds(ficlVm *pVM)
854 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
856 ficlStackPushUnsigned(ficlVmGetDataStack(pVM),
857 (ficlUnsigned) time(NULL));
861 * ms - wait at least that many milliseconds (FACILITY)
862 * ms ( u -- )
864 static void
865 ms(ficlVm *pVM)
867 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
869 #ifndef STAND
870 usleep(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000);
871 #else
872 delay(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000);
873 #endif
877 * fkey - get a character from a file
878 * fkey ( file -- char )
880 static void
881 fkey(ficlVm *pVM)
883 int i, fd;
884 char ch;
886 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
888 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
889 i = read(fd, &ch, 1);
890 ficlStackPushInteger(ficlVmGetDataStack(pVM), i > 0 ? ch : -1);
894 #ifdef STAND
895 #ifdef __i386__
898 * outb ( port# c -- )
899 * Store a byte to I/O port number port#
901 void
902 ficlOutb(ficlVm *pVM)
904 uint8_t c;
905 uint32_t port;
907 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
908 c = ficlStackPopInteger(ficlVmGetDataStack(pVM));
909 outb(port, c);
913 * inb ( port# -- c )
914 * Fetch a byte from I/O port number port#
916 void
917 ficlInb(ficlVm *pVM)
919 uint8_t c;
920 uint32_t port;
922 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM));
923 c = inb(port);
924 ficlStackPushInteger(ficlVmGetDataStack(pVM), c);
928 * pcibios-device-count (devid -- count)
930 * Returns the PCI BIOS' count of how many devices matching devid are
931 * in the system. devid is the 32-bit vendor + device.
933 static void
934 ficlPciBiosCountDevices(ficlVm *pVM)
936 uint32_t devid;
937 int i;
939 devid = ficlStackPopInteger(ficlVmGetDataStack(pVM));
941 i = biospci_count_device_type(devid);
943 ficlStackPushInteger(ficlVmGetDataStack(pVM), i);
947 * pcibios-write-config (locator offset width value -- )
949 * Writes the specified config register.
950 * Locator is bus << 8 | device << 3 | fuction
951 * offset is the pci config register
952 * width is 0 for byte, 1 for word, 2 for dword
953 * value is the value to write
955 static void
956 ficlPciBiosWriteConfig(ficlVm *pVM)
958 uint32_t value, width, offset, locator;
960 value = ficlStackPopInteger(ficlVmGetDataStack(pVM));
961 width = ficlStackPopInteger(ficlVmGetDataStack(pVM));
962 offset = ficlStackPopInteger(ficlVmGetDataStack(pVM));
963 locator = ficlStackPopInteger(ficlVmGetDataStack(pVM));
965 biospci_write_config(locator, offset, width, value);
969 * pcibios-read-config (locator offset width -- value)
971 * Reads the specified config register.
972 * Locator is bus << 8 | device << 3 | fuction
973 * offset is the pci config register
974 * width is 0 for byte, 1 for word, 2 for dword
975 * value is the value to read from the register
977 static void
978 ficlPciBiosReadConfig(ficlVm *pVM)
980 uint32_t value, width, offset, locator;
982 width = ficlStackPopInteger(ficlVmGetDataStack(pVM));
983 offset = ficlStackPopInteger(ficlVmGetDataStack(pVM));
984 locator = ficlStackPopInteger(ficlVmGetDataStack(pVM));
986 biospci_read_config(locator, offset, width, &value);
988 ficlStackPushInteger(ficlVmGetDataStack(pVM), value);
992 * pcibios-find-devclass (class index -- locator)
994 * Finds the index'th instance of class in the pci tree.
995 * must be an exact match.
996 * class is the class to search for.
997 * index 0..N (set to 0, increment until error)
999 * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
1001 static void
1002 ficlPciBiosFindDevclass(ficlVm *pVM)
1004 uint32_t index, class, locator;
1006 index = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1007 class = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1009 if (biospci_find_devclass(class, index, &locator))
1010 locator = 0xffffffff;
1012 ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
1016 * pcibios-find-device(devid index -- locator)
1018 * Finds the index'th instance of devid in the pci tree.
1019 * must be an exact match.
1020 * class is the class to search for.
1021 * index 0..N (set to 0, increment until error)
1023 * Locator is bus << 8 | device << 3 | fuction (or -1 on error)
1025 static void
1026 ficlPciBiosFindDevice(ficlVm *pVM)
1028 uint32_t index, devid, locator;
1030 index = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1031 devid = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1033 if (biospci_find_device(devid, index, &locator))
1034 locator = 0xffffffff;
1036 ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
1040 * pcibios-find-device(bus device function -- locator)
1042 * converts bus, device, function to locator.
1044 * Locator is bus << 8 | device << 3 | fuction
1046 static void
1047 ficlPciBiosLocator(ficlVm *pVM)
1049 uint32_t bus, device, function, locator;
1051 function = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1052 device = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1053 bus = ficlStackPopInteger(ficlVmGetDataStack(pVM));
1055 locator = biospci_locator(bus, device, function);
1057 ficlStackPushInteger(ficlVmGetDataStack(pVM), locator);
1059 #endif
1060 #endif
1063 * Retrieves free space remaining on the dictionary
1065 static void
1066 freeHeap(ficlVm *pVM)
1068 ficlStackPushInteger(ficlVmGetDataStack(pVM),
1069 ficlDictionaryCellsAvailable(ficlVmGetDictionary(pVM)));
1073 * f i c l C o m p i l e P l a t f o r m
1074 * Build FreeBSD platform extensions into the system dictionary
1076 void
1077 ficlSystemCompilePlatform(ficlSystem *pSys)
1079 ficlDictionary *dp = ficlSystemGetDictionary(pSys);
1080 ficlDictionary *env = ficlSystemGetEnvironment(pSys);
1082 FICL_SYSTEM_ASSERT(pSys, dp);
1083 FICL_SYSTEM_ASSERT(pSys, env);
1085 ficlDictionarySetPrimitive(dp, ".#", displayCellNoPad,
1086 FICL_WORD_DEFAULT);
1087 ficlDictionarySetPrimitive(dp, "isdir?", isdirQuestion,
1088 FICL_WORD_DEFAULT);
1089 ficlDictionarySetPrimitive(dp, "fopen", pfopen, FICL_WORD_DEFAULT);
1090 ficlDictionarySetPrimitive(dp, "fclose", pfclose, FICL_WORD_DEFAULT);
1091 ficlDictionarySetPrimitive(dp, "fread", pfread, FICL_WORD_DEFAULT);
1092 ficlDictionarySetPrimitive(dp, "fopendir", pfopendir,
1093 FICL_WORD_DEFAULT);
1094 ficlDictionarySetPrimitive(dp, "freaddir", pfreaddir,
1095 FICL_WORD_DEFAULT);
1096 ficlDictionarySetPrimitive(dp, "fclosedir", pfclosedir,
1097 FICL_WORD_DEFAULT);
1098 ficlDictionarySetPrimitive(dp, "fload", pfload, FICL_WORD_DEFAULT);
1099 ficlDictionarySetPrimitive(dp, "fkey", fkey, FICL_WORD_DEFAULT);
1100 ficlDictionarySetPrimitive(dp, "fseek", pfseek, FICL_WORD_DEFAULT);
1101 ficlDictionarySetPrimitive(dp, "fwrite", pfwrite, FICL_WORD_DEFAULT);
1102 ficlDictionarySetPrimitive(dp, "key", key, FICL_WORD_DEFAULT);
1103 ficlDictionarySetPrimitive(dp, "key?", keyQuestion, FICL_WORD_DEFAULT);
1104 ficlDictionarySetPrimitive(dp, "ms", ms, FICL_WORD_DEFAULT);
1105 ficlDictionarySetPrimitive(dp, "seconds", pseconds, FICL_WORD_DEFAULT);
1106 ficlDictionarySetPrimitive(dp, "heap?", freeHeap, FICL_WORD_DEFAULT);
1108 ficlDictionarySetPrimitive(dp, "setenv", ficlSetenv, FICL_WORD_DEFAULT);
1109 ficlDictionarySetPrimitive(dp, "setenv?", ficlSetenvq,
1110 FICL_WORD_DEFAULT);
1111 ficlDictionarySetPrimitive(dp, "getenv", ficlGetenv, FICL_WORD_DEFAULT);
1112 ficlDictionarySetPrimitive(dp, "unsetenv", ficlUnsetenv,
1113 FICL_WORD_DEFAULT);
1114 ficlDictionarySetPrimitive(dp, "copyin", ficlCopyin, FICL_WORD_DEFAULT);
1115 ficlDictionarySetPrimitive(dp, "copyout", ficlCopyout,
1116 FICL_WORD_DEFAULT);
1117 ficlDictionarySetPrimitive(dp, "findfile", ficlFindfile,
1118 FICL_WORD_DEFAULT);
1119 ficlDictionarySetPrimitive(dp, "ccall", ficlCcall, FICL_WORD_DEFAULT);
1120 ficlDictionarySetPrimitive(dp, "uuid-from-string", ficlUuidFromString,
1121 FICL_WORD_DEFAULT);
1122 ficlDictionarySetPrimitive(dp, "uuid-to-string", ficlUuidToString,
1123 FICL_WORD_DEFAULT);
1124 #ifdef STAND
1125 #ifdef __i386__
1126 ficlDictionarySetPrimitive(dp, "outb", ficlOutb, FICL_WORD_DEFAULT);
1127 ficlDictionarySetPrimitive(dp, "inb", ficlInb, FICL_WORD_DEFAULT);
1128 #endif
1129 #ifdef HAVE_PNP
1130 ficlDictionarySetPrimitive(dp, "pnpdevices", ficlPnpdevices,
1131 FICL_WORD_DEFAULT);
1132 ficlDictionarySetPrimitive(dp, "pnphandlers", ficlPnphandlers,
1133 FICL_WORD_DEFAULT);
1134 #endif
1135 #ifdef __i386__
1136 ficlDictionarySetPrimitive(dp, "pcibios-device-count",
1137 ficlPciBiosCountDevices, FICL_WORD_DEFAULT);
1138 ficlDictionarySetPrimitive(dp, "pcibios-read-config",
1139 ficlPciBiosReadConfig, FICL_WORD_DEFAULT);
1140 ficlDictionarySetPrimitive(dp, "pcibios-write-config",
1141 ficlPciBiosWriteConfig, FICL_WORD_DEFAULT);
1142 ficlDictionarySetPrimitive(dp, "pcibios-find-devclass",
1143 ficlPciBiosFindDevclass, FICL_WORD_DEFAULT);
1144 ficlDictionarySetPrimitive(dp, "pcibios-find-device",
1145 ficlPciBiosFindDevice, FICL_WORD_DEFAULT);
1146 ficlDictionarySetPrimitive(dp, "pcibios-locator", ficlPciBiosLocator,
1147 FICL_WORD_DEFAULT);
1148 #endif
1149 #endif
1151 #if defined(__i386__) || defined(__amd64__)
1152 ficlDictionarySetConstant(env, "arch-i386", FICL_TRUE);
1153 ficlDictionarySetConstant(env, "arch-sparc", FICL_FALSE);
1154 #endif
1155 #ifdef __sparc
1156 ficlDictionarySetConstant(env, "arch-i386", FICL_FALSE);
1157 ficlDictionarySetConstant(env, "arch-sparc", FICL_TRUE);
1158 #endif