Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/ficl/loader.c
34677 views
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 "ficl.h"
48
49
/* FreeBSD's loader interaction words and extras
50
*
51
* setenv ( value n name n' -- )
52
* setenv? ( value n name n' flag -- )
53
* getenv ( addr n -- addr' n' | -1 )
54
* unsetenv ( addr n -- )
55
* copyin ( addr addr' len -- )
56
* copyout ( addr addr' len -- )
57
* findfile ( name len type len' -- addr )
58
* pnpdevices ( -- addr )
59
* pnphandlers ( -- addr )
60
* ccall ( [[...[p10] p9] ... p1] n addr -- result )
61
* uuid-from-string ( addr n -- addr' )
62
* uuid-to-string ( addr' -- addr n )
63
* .# ( value -- )
64
*/
65
66
void
67
ficlSetenv(FICL_VM *pVM)
68
{
69
#ifndef TESTMAIN
70
char *name, *value;
71
#endif
72
char *namep, *valuep;
73
int names, values;
74
75
#if FICL_ROBUST > 1
76
vmCheckStack(pVM, 4, 0);
77
#endif
78
names = stackPopINT(pVM->pStack);
79
namep = (char*) stackPopPtr(pVM->pStack);
80
values = stackPopINT(pVM->pStack);
81
valuep = (char*) stackPopPtr(pVM->pStack);
82
83
#ifndef TESTMAIN
84
name = (char*) ficlMalloc(names+1);
85
if (!name)
86
vmThrowErr(pVM, "Error: out of memory");
87
strncpy(name, namep, names);
88
name[names] = '\0';
89
value = (char*) ficlMalloc(values+1);
90
if (!value)
91
vmThrowErr(pVM, "Error: out of memory");
92
strncpy(value, valuep, values);
93
value[values] = '\0';
94
95
setenv(name, value, 1);
96
ficlFree(name);
97
ficlFree(value);
98
#endif
99
100
return;
101
}
102
103
void
104
ficlSetenvq(FICL_VM *pVM)
105
{
106
#ifndef TESTMAIN
107
char *name, *value;
108
#endif
109
char *namep, *valuep;
110
int names, values, overwrite;
111
112
#if FICL_ROBUST > 1
113
vmCheckStack(pVM, 5, 0);
114
#endif
115
overwrite = stackPopINT(pVM->pStack);
116
names = stackPopINT(pVM->pStack);
117
namep = (char*) stackPopPtr(pVM->pStack);
118
values = stackPopINT(pVM->pStack);
119
valuep = (char*) stackPopPtr(pVM->pStack);
120
121
#ifndef TESTMAIN
122
name = (char*) ficlMalloc(names+1);
123
if (!name)
124
vmThrowErr(pVM, "Error: out of memory");
125
strncpy(name, namep, names);
126
name[names] = '\0';
127
value = (char*) ficlMalloc(values+1);
128
if (!value)
129
vmThrowErr(pVM, "Error: out of memory");
130
strncpy(value, valuep, values);
131
value[values] = '\0';
132
133
setenv(name, value, overwrite);
134
ficlFree(name);
135
ficlFree(value);
136
#endif
137
138
return;
139
}
140
141
void
142
ficlGetenv(FICL_VM *pVM)
143
{
144
#ifndef TESTMAIN
145
char *name, *value;
146
#endif
147
char *namep;
148
int names;
149
150
#if FICL_ROBUST > 1
151
vmCheckStack(pVM, 2, 2);
152
#endif
153
names = stackPopINT(pVM->pStack);
154
namep = (char*) stackPopPtr(pVM->pStack);
155
156
#ifndef TESTMAIN
157
name = (char*) ficlMalloc(names+1);
158
if (!name)
159
vmThrowErr(pVM, "Error: out of memory");
160
strncpy(name, namep, names);
161
name[names] = '\0';
162
163
value = getenv(name);
164
ficlFree(name);
165
166
if(value != NULL) {
167
stackPushPtr(pVM->pStack, value);
168
stackPushINT(pVM->pStack, strlen(value));
169
} else
170
#endif
171
stackPushINT(pVM->pStack, -1);
172
173
return;
174
}
175
176
void
177
ficlUnsetenv(FICL_VM *pVM)
178
{
179
#ifndef TESTMAIN
180
char *name;
181
#endif
182
char *namep;
183
int names;
184
185
#if FICL_ROBUST > 1
186
vmCheckStack(pVM, 2, 0);
187
#endif
188
names = stackPopINT(pVM->pStack);
189
namep = (char*) stackPopPtr(pVM->pStack);
190
191
#ifndef TESTMAIN
192
name = (char*) ficlMalloc(names+1);
193
if (!name)
194
vmThrowErr(pVM, "Error: out of memory");
195
strncpy(name, namep, names);
196
name[names] = '\0';
197
198
unsetenv(name);
199
ficlFree(name);
200
#endif
201
202
return;
203
}
204
205
void
206
ficlCopyin(FICL_VM *pVM)
207
{
208
void* src;
209
vm_offset_t dest;
210
size_t len;
211
212
#if FICL_ROBUST > 1
213
vmCheckStack(pVM, 3, 0);
214
#endif
215
216
len = stackPopINT(pVM->pStack);
217
dest = stackPopINT(pVM->pStack);
218
src = stackPopPtr(pVM->pStack);
219
220
#ifndef TESTMAIN
221
archsw.arch_copyin(src, dest, len);
222
#endif
223
224
return;
225
}
226
227
void
228
ficlCopyout(FICL_VM *pVM)
229
{
230
void* dest;
231
vm_offset_t src;
232
size_t len;
233
234
#if FICL_ROBUST > 1
235
vmCheckStack(pVM, 3, 0);
236
#endif
237
238
len = stackPopINT(pVM->pStack);
239
dest = stackPopPtr(pVM->pStack);
240
src = stackPopINT(pVM->pStack);
241
242
#ifndef TESTMAIN
243
archsw.arch_copyout(src, dest, len);
244
#endif
245
246
return;
247
}
248
249
void
250
ficlFindfile(FICL_VM *pVM)
251
{
252
#ifndef TESTMAIN
253
char *name, *type;
254
#endif
255
char *namep, *typep;
256
struct preloaded_file* fp;
257
int names, types;
258
259
#if FICL_ROBUST > 1
260
vmCheckStack(pVM, 4, 1);
261
#endif
262
263
types = stackPopINT(pVM->pStack);
264
typep = (char*) stackPopPtr(pVM->pStack);
265
names = stackPopINT(pVM->pStack);
266
namep = (char*) stackPopPtr(pVM->pStack);
267
#ifndef TESTMAIN
268
name = (char*) ficlMalloc(names+1);
269
if (!name)
270
vmThrowErr(pVM, "Error: out of memory");
271
strncpy(name, namep, names);
272
name[names] = '\0';
273
type = (char*) ficlMalloc(types+1);
274
if (!type)
275
vmThrowErr(pVM, "Error: out of memory");
276
strncpy(type, typep, types);
277
type[types] = '\0';
278
279
fp = file_findfile(name, type);
280
#else
281
fp = NULL;
282
#endif
283
stackPushPtr(pVM->pStack, fp);
284
285
return;
286
}
287
288
#ifndef TESTMAIN
289
290
/* isvirtualized? - Return whether the loader runs under a
291
* hypervisor.
292
*
293
* isvirtualized? ( -- flag )
294
*/
295
static void
296
ficlIsvirtualizedQ(FICL_VM *pVM)
297
{
298
FICL_INT flag;
299
const char *hv;
300
301
#if FICL_ROBUST > 1
302
vmCheckStack(pVM, 0, 1);
303
#endif
304
305
hv = (archsw.arch_hypervisor != NULL)
306
? (*archsw.arch_hypervisor)()
307
: NULL;
308
flag = (hv != NULL) ? FICL_TRUE : FICL_FALSE;
309
stackPushINT(pVM->pStack, flag);
310
}
311
312
#endif /* ndef TESTMAIN */
313
314
void
315
ficlCcall(FICL_VM *pVM)
316
{
317
int (*func)(int, ...);
318
int result, p[10];
319
int nparam, i;
320
321
#if FICL_ROBUST > 1
322
vmCheckStack(pVM, 2, 0);
323
#endif
324
325
func = stackPopPtr(pVM->pStack);
326
nparam = stackPopINT(pVM->pStack);
327
328
#if FICL_ROBUST > 1
329
vmCheckStack(pVM, nparam, 1);
330
#endif
331
332
for (i = 0; i < nparam; i++)
333
p[i] = stackPopINT(pVM->pStack);
334
335
result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
336
p[9]);
337
338
stackPushINT(pVM->pStack, result);
339
340
return;
341
}
342
343
void
344
ficlUuidFromString(FICL_VM *pVM)
345
{
346
#ifndef TESTMAIN
347
char *uuid;
348
uint32_t status;
349
#endif
350
char *uuidp;
351
int uuids;
352
uuid_t *u;
353
354
#if FICL_ROBUST > 1
355
vmCheckStack(pVM, 2, 0);
356
#endif
357
358
uuids = stackPopINT(pVM->pStack);
359
uuidp = (char *) stackPopPtr(pVM->pStack);
360
361
#ifndef TESTMAIN
362
uuid = (char *)ficlMalloc(uuids + 1);
363
if (!uuid)
364
vmThrowErr(pVM, "Error: out of memory");
365
strncpy(uuid, uuidp, uuids);
366
uuid[uuids] = '\0';
367
368
u = (uuid_t *)ficlMalloc(sizeof (*u));
369
370
uuid_from_string(uuid, u, &status);
371
ficlFree(uuid);
372
if (status != uuid_s_ok) {
373
ficlFree(u);
374
u = NULL;
375
}
376
#else
377
u = NULL;
378
#endif
379
stackPushPtr(pVM->pStack, u);
380
381
382
return;
383
}
384
385
void
386
ficlUuidToString(FICL_VM *pVM)
387
{
388
#ifndef TESTMAIN
389
char *uuid;
390
uint32_t status;
391
#endif
392
uuid_t *u;
393
394
#if FICL_ROBUST > 1
395
vmCheckStack(pVM, 1, 0);
396
#endif
397
398
u = (uuid_t *)stackPopPtr(pVM->pStack);
399
400
#ifndef TESTMAIN
401
uuid_to_string(u, &uuid, &status);
402
if (status != uuid_s_ok) {
403
stackPushPtr(pVM->pStack, uuid);
404
stackPushINT(pVM->pStack, strlen(uuid));
405
} else
406
#endif
407
stackPushINT(pVM->pStack, -1);
408
409
return;
410
}
411
412
/**************************************************************************
413
f i c l E x e c F D
414
** reads in text from file fd and passes it to ficlExec()
415
* returns VM_OUTOFTEXT on success or the ficlExec() error code on
416
* failure.
417
*/
418
#define nLINEBUF 256
419
int ficlExecFD(FICL_VM *pVM, int fd)
420
{
421
char cp[nLINEBUF];
422
int nLine = 0, rval = VM_OUTOFTEXT;
423
char ch;
424
CELL id;
425
426
id = pVM->sourceID;
427
pVM->sourceID.i = fd;
428
429
/* feed each line to ficlExec */
430
while (1) {
431
int status, i;
432
433
i = 0;
434
while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
435
cp[i++] = ch;
436
nLine++;
437
if (!i) {
438
if (status < 1)
439
break;
440
continue;
441
}
442
rval = ficlExecC(pVM, cp, i);
443
if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
444
{
445
pVM->sourceID = id;
446
return rval;
447
}
448
}
449
/*
450
** Pass an empty line with SOURCE-ID == -1 to flush
451
** any pending REFILLs (as required by FILE wordset)
452
*/
453
pVM->sourceID.i = -1;
454
ficlExec(pVM, "");
455
456
pVM->sourceID = id;
457
return rval;
458
}
459
460
static void displayCellNoPad(FICL_VM *pVM)
461
{
462
CELL c;
463
#if FICL_ROBUST > 1
464
vmCheckStack(pVM, 1, 0);
465
#endif
466
c = stackPop(pVM->pStack);
467
ltoa((c).i, pVM->pad, pVM->base);
468
vmTextOut(pVM, pVM->pad, 0);
469
return;
470
}
471
472
/* isdir? - Return whether an fd corresponds to a directory.
473
*
474
* isdir? ( fd -- bool )
475
*/
476
static void isdirQuestion(FICL_VM *pVM)
477
{
478
struct stat sb;
479
FICL_INT flag;
480
int fd;
481
482
#if FICL_ROBUST > 1
483
vmCheckStack(pVM, 1, 1);
484
#endif
485
486
fd = stackPopINT(pVM->pStack);
487
flag = FICL_FALSE;
488
do {
489
if (fd < 0)
490
break;
491
if (fstat(fd, &sb) < 0)
492
break;
493
if (!S_ISDIR(sb.st_mode))
494
break;
495
flag = FICL_TRUE;
496
} while (0);
497
stackPushINT(pVM->pStack, flag);
498
}
499
500
/* fopen - open a file and return new fd on stack.
501
*
502
* fopen ( ptr count mode -- fd )
503
*/
504
static void pfopen(FICL_VM *pVM)
505
{
506
int mode, fd, count;
507
char *ptr, *name;
508
509
#if FICL_ROBUST > 1
510
vmCheckStack(pVM, 3, 1);
511
#endif
512
513
mode = stackPopINT(pVM->pStack); /* get mode */
514
count = stackPopINT(pVM->pStack); /* get count */
515
ptr = stackPopPtr(pVM->pStack); /* get ptr */
516
517
if ((count < 0) || (ptr == NULL)) {
518
stackPushINT(pVM->pStack, -1);
519
return;
520
}
521
522
/* ensure that the string is null terminated */
523
name = (char *)malloc(count+1);
524
bcopy(ptr,name,count);
525
name[count] = 0;
526
527
/* open the file */
528
fd = open(name, mode);
529
#ifdef LOADER_VERIEXEC
530
if (fd >= 0) {
531
if (verify_file(fd, name, 0, VE_GUESS, __func__) < 0) {
532
/* not verified writing ok but reading is not */
533
if ((mode & O_ACCMODE) != O_WRONLY) {
534
close(fd);
535
fd = -1;
536
}
537
} else {
538
/* verified reading ok but writing is not */
539
if ((mode & O_ACCMODE) != O_RDONLY) {
540
close(fd);
541
fd = -1;
542
}
543
}
544
}
545
#endif
546
free(name);
547
stackPushINT(pVM->pStack, fd);
548
return;
549
}
550
551
/* fclose - close a file who's fd is on stack.
552
*
553
* fclose ( fd -- )
554
*/
555
static void pfclose(FICL_VM *pVM)
556
{
557
int fd;
558
559
#if FICL_ROBUST > 1
560
vmCheckStack(pVM, 1, 0);
561
#endif
562
fd = stackPopINT(pVM->pStack); /* get fd */
563
if (fd != -1)
564
close(fd);
565
return;
566
}
567
568
/* fread - read file contents
569
*
570
* fread ( fd buf nbytes -- nread )
571
*/
572
static void pfread(FICL_VM *pVM)
573
{
574
int fd, len;
575
char *buf;
576
577
#if FICL_ROBUST > 1
578
vmCheckStack(pVM, 3, 1);
579
#endif
580
len = stackPopINT(pVM->pStack); /* get number of bytes to read */
581
buf = stackPopPtr(pVM->pStack); /* get buffer */
582
fd = stackPopINT(pVM->pStack); /* get fd */
583
if (len > 0 && buf && fd != -1)
584
stackPushINT(pVM->pStack, read(fd, buf, len));
585
else
586
stackPushINT(pVM->pStack, -1);
587
return;
588
}
589
590
/* freaddir - read directory contents
591
*
592
* freaddir ( fd -- ptr len TRUE | FALSE )
593
*/
594
static void pfreaddir(FICL_VM *pVM)
595
{
596
#ifdef TESTMAIN
597
static struct dirent dirent;
598
struct stat sb;
599
char *buf;
600
off_t off, ptr;
601
u_int blksz;
602
int bufsz;
603
#endif
604
struct dirent *d;
605
int fd;
606
607
#if FICL_ROBUST > 1
608
vmCheckStack(pVM, 1, 3);
609
#endif
610
611
fd = stackPopINT(pVM->pStack);
612
#if TESTMAIN
613
/*
614
* The readdirfd() function is specific to the loader environment.
615
* We do the best we can to make freaddir work, but it's not at
616
* all guaranteed.
617
*/
618
d = NULL;
619
buf = NULL;
620
do {
621
if (fd == -1)
622
break;
623
if (fstat(fd, &sb) == -1)
624
break;
625
blksz = (sb.st_blksize) ? sb.st_blksize : getpagesize();
626
if ((blksz & (blksz - 1)) != 0)
627
break;
628
buf = malloc(blksz);
629
if (buf == NULL)
630
break;
631
off = lseek(fd, 0LL, SEEK_CUR);
632
if (off == -1)
633
break;
634
ptr = off;
635
if (lseek(fd, 0, SEEK_SET) == -1)
636
break;
637
bufsz = getdents(fd, buf, blksz);
638
while (bufsz > 0 && bufsz <= ptr) {
639
ptr -= bufsz;
640
bufsz = getdents(fd, buf, blksz);
641
}
642
if (bufsz <= 0)
643
break;
644
d = (void *)(buf + ptr);
645
dirent = *d;
646
off += d->d_reclen;
647
d = (lseek(fd, off, SEEK_SET) != off) ? NULL : &dirent;
648
} while (0);
649
if (buf != NULL)
650
free(buf);
651
#else
652
d = readdirfd(fd);
653
#endif
654
if (d != NULL) {
655
stackPushPtr(pVM->pStack, d->d_name);
656
stackPushINT(pVM->pStack, strlen(d->d_name));
657
stackPushINT(pVM->pStack, FICL_TRUE);
658
} else {
659
stackPushINT(pVM->pStack, FICL_FALSE);
660
}
661
}
662
663
/* fload - interpret file contents
664
*
665
* fload ( fd -- )
666
*/
667
static void pfload(FICL_VM *pVM)
668
{
669
int fd;
670
671
#if FICL_ROBUST > 1
672
vmCheckStack(pVM, 1, 0);
673
#endif
674
fd = stackPopINT(pVM->pStack); /* get fd */
675
if (fd != -1)
676
ficlExecFD(pVM, fd);
677
return;
678
}
679
680
/* fwrite - write file contents
681
*
682
* fwrite ( fd buf nbytes -- nwritten )
683
*/
684
static void pfwrite(FICL_VM *pVM)
685
{
686
int fd, len;
687
char *buf;
688
689
#if FICL_ROBUST > 1
690
vmCheckStack(pVM, 3, 1);
691
#endif
692
len = stackPopINT(pVM->pStack); /* get number of bytes to read */
693
buf = stackPopPtr(pVM->pStack); /* get buffer */
694
fd = stackPopINT(pVM->pStack); /* get fd */
695
if (len > 0 && buf && fd != -1)
696
stackPushINT(pVM->pStack, write(fd, buf, len));
697
else
698
stackPushINT(pVM->pStack, -1);
699
return;
700
}
701
702
/* fseek - seek to a new position in a file
703
*
704
* fseek ( fd ofs whence -- pos )
705
*/
706
static void pfseek(FICL_VM *pVM)
707
{
708
int fd, pos, whence;
709
710
#if FICL_ROBUST > 1
711
vmCheckStack(pVM, 3, 1);
712
#endif
713
whence = stackPopINT(pVM->pStack);
714
pos = stackPopINT(pVM->pStack);
715
fd = stackPopINT(pVM->pStack);
716
stackPushINT(pVM->pStack, lseek(fd, pos, whence));
717
return;
718
}
719
720
/* key - get a character from stdin
721
*
722
* key ( -- char )
723
*/
724
static void key(FICL_VM *pVM)
725
{
726
#if FICL_ROBUST > 1
727
vmCheckStack(pVM, 0, 1);
728
#endif
729
stackPushINT(pVM->pStack, getchar());
730
return;
731
}
732
733
/* key? - check for a character from stdin (FACILITY)
734
*
735
* key? ( -- flag )
736
*/
737
static void keyQuestion(FICL_VM *pVM)
738
{
739
#if FICL_ROBUST > 1
740
vmCheckStack(pVM, 0, 1);
741
#endif
742
#ifdef TESTMAIN
743
/* XXX Since we don't fiddle with termios, let it always succeed... */
744
stackPushINT(pVM->pStack, FICL_TRUE);
745
#else
746
/* But here do the right thing. */
747
stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
748
#endif
749
return;
750
}
751
752
/* seconds - gives number of seconds since beginning of time
753
*
754
* beginning of time is defined as:
755
*
756
* BTX - number of seconds since midnight
757
* FreeBSD - number of seconds since Jan 1 1970
758
*
759
* seconds ( -- u )
760
*/
761
static void pseconds(FICL_VM *pVM)
762
{
763
#if FICL_ROBUST > 1
764
vmCheckStack(pVM,0,1);
765
#endif
766
stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
767
return;
768
}
769
770
/* ms - wait at least that many milliseconds (FACILITY)
771
*
772
* ms ( u -- )
773
*
774
*/
775
static void ms(FICL_VM *pVM)
776
{
777
#if FICL_ROBUST > 1
778
vmCheckStack(pVM,1,0);
779
#endif
780
#ifdef TESTMAIN
781
usleep(stackPopUNS(pVM->pStack)*1000);
782
#else
783
delay(stackPopUNS(pVM->pStack)*1000);
784
#endif
785
return;
786
}
787
788
/* fkey - get a character from a file
789
*
790
* fkey ( file -- char )
791
*/
792
static void fkey(FICL_VM *pVM)
793
{
794
int i, fd;
795
char ch;
796
797
#if FICL_ROBUST > 1
798
vmCheckStack(pVM, 1, 1);
799
#endif
800
fd = stackPopINT(pVM->pStack);
801
i = read(fd, &ch, 1);
802
stackPushINT(pVM->pStack, i > 0 ? ch : -1);
803
return;
804
}
805
806
807
/*
808
** Retrieves free space remaining on the dictionary
809
*/
810
811
static void freeHeap(FICL_VM *pVM)
812
{
813
stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
814
}
815
816
817
/******************* Increase dictionary size on-demand ******************/
818
819
static void ficlDictThreshold(FICL_VM *pVM)
820
{
821
stackPushPtr(pVM->pStack, &dictThreshold);
822
}
823
824
static void ficlDictIncrease(FICL_VM *pVM)
825
{
826
stackPushPtr(pVM->pStack, &dictIncrease);
827
}
828
829
/**************************************************************************
830
f i c l C o m p i l e P l a t f o r m
831
** Build FreeBSD platform extensions into the system dictionary
832
**************************************************************************/
833
void ficlCompilePlatform(FICL_SYSTEM *pSys)
834
{
835
ficlCompileFcn **fnpp;
836
FICL_DICT *dp = pSys->dp;
837
assert (dp);
838
839
dictAppendWord(dp, ".#", displayCellNoPad, FW_DEFAULT);
840
dictAppendWord(dp, "isdir?", isdirQuestion, FW_DEFAULT);
841
dictAppendWord(dp, "fopen", pfopen, FW_DEFAULT);
842
dictAppendWord(dp, "fclose", pfclose, FW_DEFAULT);
843
dictAppendWord(dp, "fread", pfread, FW_DEFAULT);
844
dictAppendWord(dp, "freaddir", pfreaddir, FW_DEFAULT);
845
dictAppendWord(dp, "fload", pfload, FW_DEFAULT);
846
dictAppendWord(dp, "fkey", fkey, FW_DEFAULT);
847
dictAppendWord(dp, "fseek", pfseek, FW_DEFAULT);
848
dictAppendWord(dp, "fwrite", pfwrite, FW_DEFAULT);
849
dictAppendWord(dp, "key", key, FW_DEFAULT);
850
dictAppendWord(dp, "key?", keyQuestion, FW_DEFAULT);
851
dictAppendWord(dp, "ms", ms, FW_DEFAULT);
852
dictAppendWord(dp, "seconds", pseconds, FW_DEFAULT);
853
dictAppendWord(dp, "heap?", freeHeap, FW_DEFAULT);
854
dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
855
dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
856
857
dictAppendWord(dp, "setenv", ficlSetenv, FW_DEFAULT);
858
dictAppendWord(dp, "setenv?", ficlSetenvq, FW_DEFAULT);
859
dictAppendWord(dp, "getenv", ficlGetenv, FW_DEFAULT);
860
dictAppendWord(dp, "unsetenv", ficlUnsetenv, FW_DEFAULT);
861
dictAppendWord(dp, "copyin", ficlCopyin, FW_DEFAULT);
862
dictAppendWord(dp, "copyout", ficlCopyout, FW_DEFAULT);
863
dictAppendWord(dp, "findfile", ficlFindfile, FW_DEFAULT);
864
dictAppendWord(dp, "ccall", ficlCcall, FW_DEFAULT);
865
dictAppendWord(dp, "uuid-from-string", ficlUuidFromString, FW_DEFAULT);
866
dictAppendWord(dp, "uuid-to-string", ficlUuidToString, FW_DEFAULT);
867
#ifndef TESTMAIN
868
dictAppendWord(dp, "isvirtualized?", ficlIsvirtualizedQ, FW_DEFAULT);
869
#endif
870
871
SET_FOREACH(fnpp, X4th_compile_set)
872
(*fnpp)(pSys);
873
874
#if defined(__i386__)
875
ficlSetEnv(pSys, "arch-i386", FICL_TRUE);
876
ficlSetEnv(pSys, "arch-powerpc", FICL_FALSE);
877
#elif defined(__powerpc__)
878
ficlSetEnv(pSys, "arch-i386", FICL_FALSE);
879
ficlSetEnv(pSys, "arch-powerpc", FICL_TRUE);
880
#endif
881
882
return;
883
}
884
885