Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / os / unix / fsys.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: fsys.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * @(#)fsys.c 1.3 03/08/20
46 * Copyright 1985-1994 Bradley Forthware
47 * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved
48 * Copyright Use is subject to license terms.
49 *
50 * this file contains the routines that have the same function as
51 * those in wrapper.c, except that they use the forth stack to take and
52 * return arguments, effectively they are wrapper additions to the
53 * forth engine hooked into the machine using the same vector interface
54 * as wrapper.c.
55 *
56 */
57
58#include <stdio.h>
59#include <stdlib.h>
60#include <unistd.h>
61#include <fcntl.h>
62#include <strings.h>
63
64#ifdef DLOPEN
65#include <dlfcn.h>
66#include <link.h>
67#endif
68
69#include <sys/types.h>
70#include <sys/time.h>
71#include <sys/param.h>
72#include <sys/stat.h>
73
74#include <signal.h>
75#include <termios.h>
76
77#include "wrapper.h"
78#include "xref_support.h"
79#include "defines.h"
80
81#define FPROTO(x) static fstackp x(fstackp stack)
82#define UNIMPL(xx) printf("%s:%d: Unimplemented syscall " #xx "\n", \
83 __FILE__, __LINE__); \
84 return (stack)
85
86extern char *substr();
87extern void s_bye(long code);
88
89extern int errno; /* Wherever the error code goes */
90
91struct termios ostate;
92struct termios lstate;
93struct termios kstate;
94struct termios kqstate;
95
96#define M_ORIG 0
97#define M_KEY 1
98#define M_LINE 2
99#define M_KEYQ 3
100static lmode = M_ORIG;
101
102static fstackp
103pop_fstring(fstackp stack, char **buf, int *len)
104{
105 char *fstr;
106 *len = POP(stack);
107 fstr = (char *)POP(stack);
108 if (*len) {
109 *buf = malloc(*len+1);
110 strncpy(*buf, fstr, *len);
111 (*buf)[*len] = 0;
112 *len++;
113 } else {
114 *buf = NULL;
115 }
116 return (stack);
117}
118
119static fstackp
120push_cstring(fstackp stack, char *buf, int len)
121{
122 PUSH(len, stack);
123 PUSH(buf, stack);
124 return (stack);
125}
126
127static void
128initline(void)
129{
130 if (lmode != M_ORIG)
131 return;
132
133 tcgetattr(0, &ostate); /* save old state */
134
135 tcgetattr(0, &lstate); /* base of line state */
136 lstate.c_iflag |= IXON|IXANY|IXOFF; /* XON/XOFF */
137 lstate.c_iflag |= ICRNL; /* CR/NL munging */
138#ifndef FreeBSD
139 lstate.c_iflag &= ~(IUCLC); /* no case folding */
140#endif
141/* Always turning on ONLCR is safe, but it is a pain in an EMACS window */
142#ifdef notdef
143 lstate.c_oflag |= OPOST|ONLCR; /* Map NL to CR-LF */
144 lstate.c_oflag &= ~(OLCUC); /* No case folding */
145 lstate.c_oflag &= ~(OCRNL|ONLRET); /* Don't swap cr and lf */
146#else
147 lstate.c_oflag |= OPOST;
148#endif
149 lstate.c_lflag |= ICANON|ECHO; /* Line editing on */
150 lstate.c_cc[VMIN] = 1; /* Don't hold up input */
151 lstate.c_cc[VTIME] = 0; /* No input delay */
152
153 tcgetattr(0, &kstate); /* base of key state */
154 kstate.c_iflag &= ~(IXON|IXANY|IXOFF); /* no XON/XOFF */
155 kstate.c_iflag &= ~(INLCR|ICRNL); /* no CR/NL munging */
156#ifndef FreeBSD
157 kstate.c_iflag &= ~(IUCLC); /* no case folding */
158#endif
159/* Always turning on ONLCR is safe, but it is a pain in an EMACS window */
160#ifdef notdef
161 kstate.c_oflag |= OPOST|ONLCR; /* Map NL to CR-LF */
162 kstate.c_oflag &= ~(OLCUC); /* No case folding */
163 kstate.c_oflag &= ~(OCRNL|ONLRET); /* Don't swap cr and lf */
164#else
165 kstate.c_oflag |= OPOST; /* */
166#endif
167 kstate.c_lflag &= ~(ICANON|ECHO); /* No editing characters */
168 kstate.c_cc[VMIN] = 1; /* Don't hold up input */
169 kstate.c_cc[VTIME] = 0; /* No input delay */
170
171 kqstate = kstate;
172 kqstate.c_cc[VMIN] = 0; /* Poll for character */
173
174}
175
176static void
177linemode(void)
178{
179 initline();
180 if (lmode != M_LINE) {
181 tcsetattr(0, TCSANOW, &lstate);
182 lmode = M_LINE;
183 }
184}
185
186static void
187keyqmode(void)
188{
189 initline();
190 if (lmode != M_KEYQ) {
191 tcsetattr(0, TCSANOW, &kqstate);
192 lmode = M_KEYQ;
193 }
194}
195
196static void
197keymode(void)
198{
199 initline();
200 if (lmode != M_KEY) {
201 tcsetattr(0, TCSANOW, &kstate);
202 lmode = M_KEY;
203 }
204}
205
206static void
207restoremode(void)
208{
209 initline();
210 if (lmode != M_ORIG) {
211 tcsetattr(0, TCSANOW, &ostate);
212 lmode = M_ORIG;
213 }
214}
215
216/*
217 * Function semantics:
218 *
219 * Functions which are the names of Unix system calls have the semantics
220 * of those Unix system calls.
221 *
222 * char c_key(); Gets next input character
223 * no echo or editing, don't wait for a newline.
224 * c_emit(char c); Outputs the character.
225 * long f_open(char *path, long mode); Opens a file.
226 * Mode must agree with wrsys.fth
227 * long f_creat(char *path, long mode); Creates a file.
228 * Mode must agree with wrsys.fth
229 * long f_read(long fd, char *buf, long cnt); Reads from a file
230 * long f_write(long fd, char *buf, long cnt); Writes to a file
231 * long f_ioctl(long fd, long code, char *buf); Is not used right now.
232 * long c_keyques(); True if a keystroke is pending.
233 * If you can't implement this, return false.
234 * s_bye(long status); Cleans up and exits.
235 * long f_lseek(long fd, long offset, long whence);Changes file position.
236 * Whence: 0 - from start of file 1 - from current pos. 2 - from end
237 * long f_unlink(char *path); Deletes a file.
238 * long fileques(); True if input stream has been
239 * redirected away from a keyboard.
240 * long c_type(long len, char *addr); Outputs len characters.
241 * long c_expect(long max, char *buffer); Reads an edited line of input.
242 * long c_cr(); Advances to next line.
243 * long f_crstr() Returns file line terminator.
244 * long syserror(); Error code from the last
245 * failed system call.
246 */
247
248extern char *progname;
249extern char sccs_get_cmd[128]; /* sccs get command string */
250extern int uflag;
251extern int vflag;
252extern int xref_enabled;
253extern int show_symbols;
254
255/*
256 * Returns true if a key has been typed on the keyboard since the last
257 * call to c_key().
258 */
259FPROTO(c_keyques)
260{
261 int nchars = 0;
262
263 fflush(stdout);
264
265#ifdef FreeBSD
266 if ((nchars = stdin->_r) == 0) {
267 char c[1];
268 keyqmode();
269 nchars = read(0, c, 1) > 0;
270 if (nchars)
271 ungetc(c[0], stdin);
272 }
273#else
274#ifdef IRIS
275 return (0);
276#endif
277#endif
278 {
279 char c[1];
280 keyqmode();
281 nchars = read(0, c, 1) > 0;
282 if (nchars)
283 ungetc(c[0], stdin);
284 }
285
286 PUSH(nchars, stack);
287 return (stack);
288}
289
290FPROTO(f_bye)
291{
292 int status;
293
294 status = POP(stack);
295 s_bye(status);
296 return (stack);
297}
298
299/*
300 * Get the next character from the input stream.
301 */
302/*
303 * There is a minor problem under Regulus relating to interrupted system
304 * calls. If the user types the INTERRUPT character (e.g. DEL) while
305 * Forth is waiting for input, the read system call will be interrupted.
306 * Forth will field the signal thus generated, save the state, and return
307 * to the Forth interpreter. If the user then tries to restart from the
308 * saved state, the restarted system call will return 0, which is the same
309 * code that is returned for end-of-file. This is especially nasty when
310 * using the Regulus standard-I/O package, because when it see the 0-length
311 * read, it set a flag in the stdio file descriptor and returns EOF
312 * forevermore. What we really want to happen is for the read system call
313 * to restart cleanly and continue waiting for input, rather than returning
314 * 0.
315 */
316
317FPROTO(c_key)
318{
319 int c;
320
321 keymode();
322
323 fflush(stdout);
324 if ((c = getc(stdin)) != EOF) {
325 PUSH(c, stack);
326 return (stack);
327 }
328 s_bye(0L);
329 return (NULL);
330}
331
332/*
333 * Send the character c to the output stream.
334 */
335FPROTO(c_emit)
336{
337 int c;
338
339 c = (int)POP(stack);
340 putchar(c);
341 fflush(stdout);
342 return (stack);
343}
344
345/*
346 * This routine is called by the Forth system to determine whether
347 * its input stream is connected to a file or to a terminal.
348 * It uses this information to decide whether or not to
349 * prompt at the beginning of a line. If you are running in an environment
350 * where input cannot be redirected away from the terminal, just return 0L.
351 */
352FPROTO(fileques)
353{
354 int status = !isatty(fileno(stdin));
355 PUSH(status, stack);
356 return (stack);
357}
358
359/*
360 * Get an edited line of input from the keyboard, placing it at buffer.
361 * At most "max" characters will be placed in the buffer.
362 * The line terminator character is not stored in the buffer.
363 */
364FPROTO(c_expect)
365{
366 int c;
367 long max;
368 char *buffer;
369 char *p;
370
371 max = POP(stack);
372 buffer = (char *)POP(stack);
373
374 p = buffer;
375 linemode();
376
377 fflush(stdout);
378 while (max-- && ((c = getc(stdin)) != '\n') && (c != EOF))
379 *p++ = c;
380 if (c == EOF)
381 *p++ = '\n';
382 keymode();
383
384 PUSH((p-buffer), stack);
385 return (stack);
386}
387
388/*
389 * Send len characters from the buffer at addr to the output stream.
390 */
391FPROTO(c_type)
392{
393 long len;
394 char *addr;
395
396 len = POP(stack);
397 addr = (char *)POP(stack);
398
399 while (len--)
400 putchar(*addr++);
401 fflush(stdout);
402
403 return (stack);
404}
405
406/*
407 * Sends an end-of-line sequence to the output stream.
408 */
409FPROTO(c_cr)
410{
411 putchar('\n');
412 fflush(stdout);
413 return (stack);
414}
415
416/*
417 * Returns the end-of-line sequence that is used within files as
418 * a packed (leading count byte) string.
419 */
420FPROTO(f_crstr)
421{
422 char crstr[2] = { 0x01, '\n' };
423 PUSH(crstr, stack);
424 return (stack);
425}
426
427/* Find the error code returned by the last failing system call. */
428FPROTO(syserror)
429{
430 PUSH(errno, stack);
431 return (stack);
432}
433
434/* Display an error message */
435
436FPROTO(pr_error)
437{
438 errno = POP(stack);
439 perror("");
440 return (stack);
441}
442
443FPROTO(f_open)
444{
445 char *name;
446 int flag;
447 mode_t mode;
448 int status;
449
450 mode = (mode_t)POP(stack);
451 flag = (int)POP(stack);
452 name = (char *)POP(stack);
453 name = expand_name(name);
454
455#ifdef SCCS
456 if (uflag)
457 if (isobsolete(name) == 1)
458 system(sccs_get(name));
459#endif SCCS
460 if (vflag)
461 printf("File: %s\n", name);
462
463 status = open(name, flag, mode);
464 return (stack);
465}
466
467FPROTO(f_creat)
468{
469#if 0
470 (char *name, long mode)
471 name = expand_name(name);
472
473 return ((long)open(name, O_RDWR|O_CREAT|O_TRUNC, (int)mode));
474#endif
475 return (stack);
476}
477
478/* f_read ( fd buf len -- #bytes ) */
479FPROTO(f_read)
480{
481 int fd;
482 char *buf;
483 size_t len;
484 ssize_t bytes;
485
486 len = POP(stack);
487 buf = (char *)POP(stack);
488 fd = POP(stack);
489 bytes = read(fd, buf, len);
490 PUSH(bytes, stack);
491 return (stack);
492}
493
494/* f_write ( fd adr len -- #written ) */
495FPROTO(f_write)
496{
497 int fd;
498 char *buf;
499 size_t len;
500 ssize_t bytes;
501
502 len = POP(stack);
503 buf = (char *)POP(stack);
504 fd = POP(stack);
505
506 bytes = write(fd, buf, len);
507 PUSH(bytes, stack);
508 return (stack);
509}
510
511FPROTO(f_close)
512{
513 int fd, status;
514
515 fd = POP(stack);
516 status = close(fd);
517 return (stack);
518}
519
520/* unlink ( str,len -- ok? ) */
521FPROTO(f_unlink)
522{
523 int len;
524 char *buffer;
525 char *path;
526 int status;
527
528 stack = pop_fstring(stack, &path, &len);
529#if 0
530 status = unlink(path);
531#else
532 printf("UNLINK: %s\n", path);
533#endif
534 free(path);
535 PUSH(status, stack);
536 return (stack);
537}
538
539/* f_seek ( fd offset whence -- ) */
540FPROTO(f_lseek)
541{
542 int fd;
543 off_t offset;
544 int whence;
545 off_t status;
546
547 whence = POP(stack);
548 offset = POP(stack);
549 fd = POP(stack);
550
551 status = lseek(fd, offset, whence);
552
553 PUSH(status, stack);
554 return (stack);
555}
556
557FPROTO(f_ioctl)
558{
559 int fd;
560 char *buf;
561 int code;
562 int status;
563
564 buf = (char *)POP(stack);
565 code = POP(stack);
566 fd = POP(stack);
567
568 status = ioctl(fd, code, buf);
569 PUSH(status, stack);
570 return (stack);
571}
572
573FPROTO(s_signal)
574{
575 void (*disp)(int);
576 int sig;
577 void (*prev)(int);
578
579 disp = (void (*)())POP(stack);
580 sig = POP(stack);
581 prev = signal(sig, disp);
582 PUSH(prev, stack);
583 return (stack);
584}
585
586FPROTO(s_system)
587{
588 int len, status;
589 char *buf;
590 char *sbuf;
591
592 stack = pop_fstring(stack, &sbuf, &len);
593
594 linemode();
595 status = system(sbuf);
596 keymode();
597 free(sbuf);
598
599 PUSH(status, stack);
600 return (stack);
601}
602
603/* chdir ( str,len -- ok? ) */
604FPROTO(s_chdir)
605{
606 int len, status;
607 char *buf;
608 char *sbuf;
609
610 stack = pop_fstring(stack, &sbuf, &len);
611 status = chdir(sbuf);
612 free(sbuf);
613
614 PUSH(status, stack);
615 return (stack);
616}
617
618/* getwd ( -- str,len ) */
619FPROTO(s_getwd)
620{
621 char *buf, *sbuf;
622 int len;
623
624 buf = malloc(MAXPATHLEN+1);
625 sbuf = getwd(buf);
626 if (sbuf != NULL) {
627 len = strlen(buf);
628 sbuf = strdup(buf);
629 free(buf);
630 buf = sbuf;
631 } else {
632 free(buf);
633 len = 0;
634 }
635 PUSH(buf, stack);
636 PUSH(len, stack);
637 return (stack);
638}
639
640/* alloc ( len -- buf ) */
641FPROTO(m_alloc)
642{
643 size_t size;
644 void *buf;
645
646#ifdef PPCSIM
647 size = (size+7) & ~7;
648#endif
649 buf = malloc(size);
650 if (buf != NULL)
651 memset(buf, 0, size);
652
653 PUSH(buf, stack);
654 return (stack);
655}
656
657/* free ( adr,len -- ) */
658FPROTO(m_free)
659{
660 int len;
661 char *buf;
662
663 len = POP(stack);
664 buf = (char *)POP(stack);
665 free(buf);
666 return (stack);
667}
668
669/* sbrk ( size -- va ) */
670FPROTO(m_sbrk)
671{
672 intptr_t size;
673 void *ptr;
674
675 size = POP(stack);
676 ptr = sbrk(size);
677 PUSH(ptr, stack);
678 return (stack);
679}
680
681#ifndef DLOPEN
682FPROTO(f_dlopen)
683{
684 UNIMPL(f_dlopen);
685}
686
687FPROTO(f_dlclose)
688{
689 UNIMPL(f_dlclose);
690}
691
692FPROTO(f_dlsym)
693{
694 UNIMPL(f_dlsym);
695}
696
697FPROTO(f_dlerror)
698{
699 UNIMPL(f_dlerror);
700}
701#else
702/* dlopen ( str,len mode -- handle ) */
703FPROTO(f_dlopen)
704{
705 int mode;
706 int len;
707 char *lib;
708 void *handle;
709
710 mode = POP(stack);
711 stack = pop_fstring(stack, &lib, &len);
712
713 handle = dlopen(lib, mode);
714 free(lib);
715 PUSH(handle, stack);
716 return (stack);
717}
718
719/* dlclose ( handle -- ) */
720FPROTO(f_dlclose)
721{
722 void *handle;
723 handle = (void *)POP(stack);
724 dlclose(handle);
725 return (stack);
726}
727
728/* dlerror ( -- str,len ) */
729FPROTO(f_dlerror)
730{
731 int len;
732 char *err = dlerror();
733
734 if (err != NULL) {
735 stack = push_cstring(stack, err, strlen(err));
736 } else {
737 stack = push_cstring(stack, err, 0);
738 }
739 return (stack);
740}
741
742/* dlsym ( str,len handle -- ptr ) */
743FPROTO(f_dlsym)
744{
745 void *handle, *symptr;
746 char *sym;
747 int len;
748
749 handle = (void *)POP(stack);
750 stack = pop_fstring(stack, &sym, &len);
751 symptr = dlsym(handle, sym);
752 free(sym);
753 PUSH(symptr, stack);
754 return (stack);
755}
756#endif
757
758/* getenv ( str,len -- buf,len ) */
759FPROTO(c_getenv)
760{
761 int len, blen;
762 char *cstr, *sbuf, *buf;
763
764 stack = pop_fstring(stack, &sbuf, &len);
765 buf = getenv(sbuf);
766 free(sbuf);
767 if (buf == NULL) {
768 blen = 0;
769 } else {
770 blen = strlen(buf);
771 }
772 PUSH(buf, stack);
773 PUSH(blen, stack);
774 return (stack);
775}
776
777FPROTO(today)
778{
779 long tadd;
780
781 time(&tadd);
782 PUSH(localtime(&tadd), stack);
783 return (stack);
784}
785
786FPROTO(timez)
787{
788 UNIMPL(timez);
789}
790
791FPROTO(timezstr)
792{
793 UNIMPL(timezstr);
794}
795
796/*
797 * Flush the data cache if necessary and possible. Used after writing
798 * instructions into the dictionary.
799 */
800FPROTO(s_flushcache)
801{
802#ifdef NeXT
803 asm("trap #2");
804#endif
805 UNIMPL(s_flushcache);
806}
807
808FPROTO(f_init)
809{
810 UNIMPL(f_init);
811}
812
813FPROTO(f_op)
814{
815 UNIMPL(f_op);
816}
817
818FPROTO(f_move)
819{
820 UNIMPL(f_move);
821}
822
823FPROTO(f_rows)
824{
825 UNIMPL(f_rows);
826}
827
828FPROTO(f_cols)
829{
830 UNIMPL(f_cols);
831}
832
833FPROTO(pathname)
834{
835 UNIMPL(pathname);
836}
837
838#ifdef SIMFORTH
839FPROTO(find_next)
840{
841 int shift = POP(stack);
842 int token_size = POP(stack);
843 int origin = POP(stack);
844 char *link = (char *)POP(stack);
845 char *str = (char *)POP(stack);
846 int len, nextlen;
847 char *namep;
848 char *p = str;
849
850 len = strlen(p);
851
852 if (tshift == 0)
853 link = (char *)((*(unsigned long *)(link)) +(origin));
854 else
855 link = (char *)((*(unsigned short *)(link) << tshift) +(origin));
856
857 while (link != (char *)origin) {
858 p = str;
859 namep = link - token_size - 1;
860 nextlen = (*namep) & 0x1f;
861 namep = namep - nextlen;
862 if (len == nextlen)
863 while (nextlen--)
864 if (*(namep++) != *(p++))
865 break;
866 if (nextlen == -1) {
867 PUSH((((long)link)-token_size), stack);
868 return (stack);
869 }
870
871 if (tshift == 0)
872 link = (char *)((*(unsigned long *)(link-token_size))
873 +(origin));
874 else
875 link = (char *)((*(unsigned short *)(link-token_size)
876 << tshift) +(origin));
877 }
878
879 PUSH(0, stack);
880 return (stack);
881}
882#endif /* SIMFORTH */
883
884/* save-image ( up,len origin,len name,len -- ) */
885FPROTO(save_image)
886{
887 char *fname;
888 uchar_t *upaddr, *dicaddr;
889 int flen, ulen, dlen;
890 FILE *file;
891
892 stack = pop_fstring(stack, &fname, &flen);
893 dlen = POP(stack);
894 dicaddr = (uchar_t *)POP(stack);
895 ulen = POP(stack);
896 upaddr = (uchar_t *)POP(stack);
897
898 file = fopen(fname, "wb");
899 if (file == NULL) {
900 fprintf(stderr, "save_image: failed to create %s\n",
901 fname);
902 return (stack);
903 }
904 fwrite(dicaddr, 1, dlen, file);
905 fwrite(upaddr, 1, ulen, file);
906 fclose(file);
907 return (stack);
908}
909
910static include_file_t *includes = NULL;
911
912/* include ( str,len -- str,len ) */
913FPROTO(includefile)
914{
915 include_file_t *newfile;
916 FILE *fd;
917 char *cname, *name;
918 char *fname;
919 int len;
920 fstackp current;
921
922 (void) pop_fstring(stack, &cname, &len);
923
924 name = expand_name(cname);
925
926#ifdef SCCS
927 if (uflag)
928 if (isobsolete(name) == 1)
929 system(sccs_get(name));
930#endif
931 /*
932 * open the file, using SCCS if required
933 */
934 fd = fopen(name, "r");
935 if (fd == NULL) {
936 printf("failed to open %s\n", name);
937 }
938 newfile = malloc(sizeof (include_file_t));
939 if (newfile == NULL) {
940 printf("Malloc failed for include file: %s\n", name);
941 exit(1);
942 }
943 newfile->next = includes;
944 newfile->linenum = 0;
945 newfile->name = strdup(name);
946 newfile->fd = fd;
947 includes = newfile;
948 if (vflag) {
949 printf("File: %s\n", name);
950 }
951 free(cname);
952 return (current);
953}
954
955/* bootstrap ( str,len -- buf,len ) */
956FPROTO(bootstrap)
957{
958 int fd;
959 char *cname, *name;
960 struct stat sbuf;
961 int flen, len;
962 char *fname, *buffer;
963
964 stack = pop_fstring(stack, &cname, &len);
965 if (len == 0) {
966 buffer = NULL;
967 goto error;
968 }
969 name = expand_name(cname);
970
971 printf("Bootstrap: %s (%s)\n", cname, name);
972#ifdef SCCS
973 if (uflag)
974 if (isobsolete(name) == 1)
975 system(sccs_get(name));
976#endif
977
978 /*
979 * open the file, using SCCS if required
980 */
981 fd = open(name, O_RDONLY);
982 if (fd < 0) {
983 printf("failed to open bootstrap file %s\n", name);
984 buffer = NULL;
985 goto error;
986 }
987 fstat(fd, &sbuf);
988 buffer = malloc(sbuf.st_size+1);
989 if (buffer == NULL) {
990 printf("Malloc failed for bootstrap file: %s\n", name);
991 buffer = NULL;
992 goto error;
993 }
994 len = read(fd, buffer, sbuf.st_size);
995 buffer[len] = 0;
996 close(fd);
997 if (len != sbuf.st_size) {
998 printf("Short read on bootstrap file %s\n", name);
999 free(buffer);
1000 buffer = NULL;
1001 len = 0;
1002 goto error;
1003 } else {
1004 if (vflag > 1) {
1005 printf("Bootstrapped: %s [%d bytes]\n",
1006 name, sbuf.st_size);
1007 }
1008 }
1009error:
1010 if (cname != NULL)
1011 free(cname);
1012 PUSH(buffer, stack);
1013 PUSH(len, stack);
1014 return (stack);
1015}
1016
1017/*
1018 * xref_symbol ( str,len line# state -- str,len )
1019 * state:
1020 * 0 symbol_reference
1021 * 1 symbol_definition
1022 * 2 smybol_hide
1023 * 3 symbol_reveal
1024 * 4 string content
1025 */
1026FPROTO(xref_symbol)
1027{
1028 int state;
1029 int len;
1030 char *name;
1031 char *fnname = NULL;
1032 int line;
1033 state = POP(stack);
1034
1035#ifdef SHOWREFS
1036#define RPRINTF(x) printf x
1037#else
1038#define RPRINTF(x)
1039#endif
1040
1041 if (xref_enabled) {
1042 switch (state) {
1043 case 0:
1044 line = POP(stack);
1045 pop_fstring(stack, &fnname, &len);
1046 RPRINTF(("ref: %s\n", fnname));
1047 xref_add_symbol_reference(fnname, line);
1048 break;
1049
1050 case 1:
1051 line = POP(stack);
1052 pop_fstring(stack, &fnname, &len);
1053 RPRINTF(("define: %s\n", fnname));
1054 xref_add_symbol_definition(fnname, line);
1055 break;
1056
1057 case 2:
1058 pop_fstring(stack, &fnname, &len);
1059 RPRINTF(("hide: %s\n", fnname));
1060 xref_modify_symbol_definition(fnname, 0);
1061 break;
1062
1063 case 3:
1064 pop_fstring(stack, &fnname, &len);
1065 RPRINTF(("reveal: %s\n", fnname));
1066 xref_modify_symbol_definition(fnname, 1);
1067 break;
1068
1069 case 4:
1070 line = POP(stack);
1071 pop_fstring(stack, &fnname, &len);
1072 RPRINTF(("string: %s\n", fnname));
1073 xref_add_string(fnname, len, line);
1074 break;
1075
1076 default:
1077 printf("%s:%d: xref_symbol invalid state %d\n",
1078 __FILE__, __LINE__, state);
1079 break;
1080 }
1081 if (fnname != NULL)
1082 free(fnname);
1083 }
1084 return (stack);
1085}
1086
1087/* xref-file ( [name,len,-1 -- name,len] | [ 0 -- ] ) */
1088FPROTO(xref_file)
1089{
1090 int state;
1091 int len;
1092 char *name;
1093 char *fname = NULL;
1094
1095 state = POP(stack);
1096 if (state) {
1097 /*
1098 * We dont actually pop the stack though..
1099 */
1100 pop_fstring(stack, &fname, &len);
1101#if 0
1102 printf("Pushing.. %s\n", fname);
1103#endif
1104 }
1105
1106 if ((xref_enabled) || 1) {
1107 if (state) {
1108 xref_add_file_reference(fname);
1109 } else {
1110 xref_remove_file_reference();
1111 }
1112 }
1113 if (fname != NULL)
1114 free(fname);
1115 return (stack);
1116}
1117
1118/* xref_trigger ( state -- ) */
1119FPROTO(xref_trigger)
1120{
1121 int what;
1122 char *symbol;
1123 char *preload;
1124 extern int xref_enable_forward_refs;
1125
1126 what = POP(stack);
1127 switch (what) {
1128 case 0:
1129 /*
1130 * Xref Off
1131 * Flush the xref-file to disk.
1132 */
1133 if (xref_enabled)
1134 xref_generate(1);
1135 xref_enabled = 0;
1136 break;
1137
1138 case 1:
1139 /*
1140 * Xref On
1141 */
1142 symbol = "XREF-FILE";
1143 if (symbol_defined(symbol)) {
1144 xref_enabled = 1;
1145 }
1146 break;
1147
1148 case -1:
1149 /*
1150 * Init; extract the xref variables from the symbol table.
1151 */
1152 symbol = "XREF-FILE";
1153 if (symbol_defined(symbol)) {
1154 char *symdata = extract_symbol(symbol);
1155 char *preload = extract_symbol("XREF-PRELOAD");
1156 xref_init(symdata, preload, xref_enable_forward_refs);
1157 PUSH(-1, stack);
1158 } else {
1159 PUSH(0, stack);
1160 }
1161 break;
1162
1163 default:
1164 printf("%s:%d Unexpected Xref trigger\n", __FILE__, __LINE__);
1165 break;
1166 }
1167 return (stack);
1168}
1169
1170/* xref_stat ( -- ) */
1171FPROTO(xref_stat)
1172{
1173 printf("Xref enabled?: %d\n", xref_enabled);
1174 xref_status();
1175 return (stack);
1176}
1177
1178/* symbol-set ( data,dlen symbol,len create? -- ) */
1179FPROTO(symbol_set)
1180{
1181 int create;
1182 int slen;
1183 char *sname;
1184 int dlen;
1185 char *data;
1186 char *symbol;
1187
1188 create = POP(stack);
1189 stack = pop_fstring(stack, &symbol, &slen);
1190 if (create) {
1191 stack = pop_fstring(stack, &data, &dlen);
1192 if (dlen) {
1193 char cstr[256];
1194
1195 snprintf(cstr, sizeof (cstr), "%s=%s", symbol, data);
1196 free(data);
1197 free(symbol);
1198 symbol = strdup(cstr);
1199 }
1200 define_symbol(symbol, FORTH_DEFINE);
1201 } else {
1202 undef_symbol(symbol, FORTH_UNDEF);
1203 }
1204 free(symbol);
1205 return (stack);
1206}
1207
1208/* symbol-exists( symbol,len -- exists? ) */
1209FPROTO(symbol_exists)
1210{
1211 int slen;
1212 char *symname;
1213 char *symbol;
1214 int defined;
1215 int invert = 0;
1216
1217 stack = pop_fstring(stack, &symbol, &slen);
1218 symname = symbol;
1219 if (symname[0] == '!') {
1220 symname++;
1221 invert = 1;
1222 }
1223 defined = symbol_defined(symname);
1224 if (invert) {
1225 defined = !defined;
1226 }
1227 free(symbol);
1228 PUSH(defined, stack);
1229 return (stack);
1230}
1231
1232/* symbol-value( symbol,len -- value,len ) */
1233FPROTO(symbol_value)
1234{
1235 int slen;
1236 int invert = 0;
1237 char *symname;
1238 char *symbol;
1239 char *value;
1240 char *symdata;
1241
1242 stack = pop_fstring(stack, &symname, &slen);
1243 symbol = symname;
1244 if (symname[0] == '!') {
1245 symbol++;
1246 invert = 1;
1247 }
1248 if (symbol_defined(symbol)) {
1249 symdata = extract_symbol(symbol);
1250 if (symdata == NULL) {
1251 symdata = (char *)&slen;
1252 slen = 0;
1253 } else {
1254 slen = strlen(symdata);
1255 }
1256 if (invert) {
1257 symdata = NULL;
1258 slen = 0;
1259 }
1260 } else {
1261 symdata = NULL;
1262 if (invert) {
1263 symdata = (char *)&slen;
1264 }
1265 slen = 0;
1266 }
1267 free(symname);
1268 PUSH(symdata, stack);
1269 PUSH(slen, stack);
1270 return (stack);
1271}
1272
1273FPROTO(stack_syscall)
1274{
1275 long tos;
1276 int i;
1277
1278 tos = POP(stack);
1279 printf("Tos: %x\n", tos);
1280 PUSH(1, stack);
1281 PUSH(2, stack);
1282
1283 return (stack);
1284}
1285
1286FPROTO(compile_info)
1287{
1288 extern int compile_msgs;
1289 compile_msgs++;
1290 return (stack);
1291}
1292
1293FPROTO(compile_abort)
1294{
1295 extern int compile_errors;
1296 compile_errors++;
1297 return (stack);
1298}
1299
1300FPROTO(compile_warn)
1301{
1302 extern int compile_warnings;
1303 compile_warnings++;
1304 return (stack);
1305}
1306
1307/*
1308 * Now the function table.
1309 */
1310fstackp ((*sfunctions[])(fstackp)) = {
1311 /* 0 1 */
1312 c_key, c_emit,
1313
1314 /* 2 3 4 5 */
1315 f_open, f_creat, f_close, f_read,
1316
1317 /* 6 7 8 */
1318 f_write, f_ioctl, c_keyques,
1319
1320 /* 9 10 11 12 */
1321 f_bye, f_lseek, f_unlink, fileques,
1322
1323 /* 13 14 15 */
1324 c_type, c_expect, syserror,
1325
1326 /* 16 17 18 */
1327 today, timez, timezstr,
1328
1329 /* 19 20 */
1330#if 0
1331 fork, execve,
1332#else
1333 0L, 0L,
1334#endif
1335 /* 21 */
1336 c_getenv,
1337
1338 /* 22 23 */
1339 s_system, s_signal,
1340
1341 /* 24 25 */
1342 s_chdir, s_getwd,
1343
1344 /* 26 27 28 */
1345 m_alloc, c_cr, f_crstr,
1346
1347 /* 29 30 31 */
1348 s_flushcache, pr_error, 0,
1349
1350 /* 32 */
1351 m_free,
1352
1353 /* 33 34 35 36 37 */
1354 f_init, f_op, f_move, f_rows, f_cols,
1355
1356 /* 38 */
1357 pathname,
1358
1359#ifdef PPCSIM
1360 /* 39 40 41 42 */
1361 printnum, mmap, open, close,
1362#else
1363 /* 39 */
1364 m_sbrk,
1365
1366 /* 40 41 42 43 */
1367 f_dlopen, f_dlsym, f_dlerror, f_dlclose,
1368
1369 /* 44 */
1370#ifdef SIMFORTH
1371 find_next,
1372#else
1373 0,
1374#endif
1375 /* 45, , 46 , 47 , 48 */
1376 save_image, bootstrap, includefile, 0,
1377
1378 /* 49, 50 51 , 52 */
1379 xref_symbol, xref_file, xref_trigger, xref_stat,
1380
1381 /* 53, 54, 55, */
1382 symbol_set, symbol_exists, symbol_value,
1383
1384 /* 56 */
1385 stack_syscall,
1386
1387 /* 57 58, 59, 60 */
1388 compile_info, compile_abort, compile_warn, 0,
1389#endif
1390 /* EOT */
1391 0
1392};