* ========== Copyright Header Begin ==========================================
* Hypervisor Software File: fsys.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* - Do no alter or remove copyright notices
* - Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* - Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of Sun Microsystems, Inc. or the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or maintenance of
* ========== Copyright Header End ============================================
* @(#)fsys.c 1.3 03/08/20
* Copyright 1985-1994 Bradley Forthware
* Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved
* Copyright Use is subject to license terms.
* this file contains the routines that have the same function as
* those in wrapper.c, except that they use the forth stack to take and
* return arguments, effectively they are wrapper additions to the
* forth engine hooked into the machine using the same vector interface
#include "xref_support.h"
#define FPROTO(x) static fstackp x(fstackp stack)
#define UNIMPL(xx) printf("%s:%d: Unimplemented syscall " #xx "\n", \
extern void s_bye(long code
);
extern int errno
; /* Wherever the error code goes */
pop_fstring(fstackp stack
, char **buf
, int *len
)
fstr
= (char *)POP(stack
);
strncpy(*buf
, fstr
, *len
);
push_cstring(fstackp stack
, char *buf
, int len
)
tcgetattr(0, &ostate
); /* save old state */
tcgetattr(0, &lstate
); /* base of line state */
lstate
.c_iflag
|= IXON
|IXANY
|IXOFF
; /* XON/XOFF */
lstate
.c_iflag
|= ICRNL
; /* CR/NL munging */
lstate
.c_iflag
&= ~(IUCLC
); /* no case folding */
/* Always turning on ONLCR is safe, but it is a pain in an EMACS window */
lstate
.c_oflag
|= OPOST
|ONLCR
; /* Map NL to CR-LF */
lstate
.c_oflag
&= ~(OLCUC
); /* No case folding */
lstate
.c_oflag
&= ~(OCRNL
|ONLRET
); /* Don't swap cr and lf */
lstate
.c_lflag
|= ICANON
|ECHO
; /* Line editing on */
lstate
.c_cc
[VMIN
] = 1; /* Don't hold up input */
lstate
.c_cc
[VTIME
] = 0; /* No input delay */
tcgetattr(0, &kstate
); /* base of key state */
kstate
.c_iflag
&= ~(IXON
|IXANY
|IXOFF
); /* no XON/XOFF */
kstate
.c_iflag
&= ~(INLCR
|ICRNL
); /* no CR/NL munging */
kstate
.c_iflag
&= ~(IUCLC
); /* no case folding */
/* Always turning on ONLCR is safe, but it is a pain in an EMACS window */
kstate
.c_oflag
|= OPOST
|ONLCR
; /* Map NL to CR-LF */
kstate
.c_oflag
&= ~(OLCUC
); /* No case folding */
kstate
.c_oflag
&= ~(OCRNL
|ONLRET
); /* Don't swap cr and lf */
kstate
.c_oflag
|= OPOST
; /* */
kstate
.c_lflag
&= ~(ICANON
|ECHO
); /* No editing characters */
kstate
.c_cc
[VMIN
] = 1; /* Don't hold up input */
kstate
.c_cc
[VTIME
] = 0; /* No input delay */
kqstate
.c_cc
[VMIN
] = 0; /* Poll for character */
tcsetattr(0, TCSANOW
, &lstate
);
tcsetattr(0, TCSANOW
, &kqstate
);
tcsetattr(0, TCSANOW
, &kstate
);
tcsetattr(0, TCSANOW
, &ostate
);
* Functions which are the names of Unix system calls have the semantics
* of those Unix system calls.
* char c_key(); Gets next input character
* no echo or editing, don't wait for a newline.
* c_emit(char c); Outputs the character.
* long f_open(char *path, long mode); Opens a file.
* Mode must agree with wrsys.fth
* long f_creat(char *path, long mode); Creates a file.
* Mode must agree with wrsys.fth
* long f_read(long fd, char *buf, long cnt); Reads from a file
* long f_write(long fd, char *buf, long cnt); Writes to a file
* long f_ioctl(long fd, long code, char *buf); Is not used right now.
* long c_keyques(); True if a keystroke is pending.
* If you can't implement this, return false.
* s_bye(long status); Cleans up and exits.
* long f_lseek(long fd, long offset, long whence);Changes file position.
* Whence: 0 - from start of file 1 - from current pos. 2 - from end
* long f_unlink(char *path); Deletes a file.
* long fileques(); True if input stream has been
* redirected away from a keyboard.
* long c_type(long len, char *addr); Outputs len characters.
* long c_expect(long max, char *buffer); Reads an edited line of input.
* long c_cr(); Advances to next line.
* long f_crstr() Returns file line terminator.
* long syserror(); Error code from the last
extern char sccs_get_cmd
[128]; /* sccs get command string */
* Returns true if a key has been typed on the keyboard since the last
if ((nchars
= stdin
->_r
) == 0) {
nchars
= read(0, c
, 1) > 0;
nchars
= read(0, c
, 1) > 0;
* Get the next character from the input stream.
* There is a minor problem under Regulus relating to interrupted system
* calls. If the user types the INTERRUPT character (e.g. DEL) while
* Forth is waiting for input, the read system call will be interrupted.
* Forth will field the signal thus generated, save the state, and return
* to the Forth interpreter. If the user then tries to restart from the
* saved state, the restarted system call will return 0, which is the same
* code that is returned for end-of-file. This is especially nasty when
* using the Regulus standard-I/O package, because when it see the 0-length
* read, it set a flag in the stdio file descriptor and returns EOF
* forevermore. What we really want to happen is for the read system call
* to restart cleanly and continue waiting for input, rather than returning
if ((c
= getc(stdin
)) != EOF
) {
* Send the character c to the output stream.
* This routine is called by the Forth system to determine whether
* its input stream is connected to a file or to a terminal.
* It uses this information to decide whether or not to
* prompt at the beginning of a line. If you are running in an environment
* where input cannot be redirected away from the terminal, just return 0L.
int status
= !isatty(fileno(stdin
));
* Get an edited line of input from the keyboard, placing it at buffer.
* At most "max" characters will be placed in the buffer.
* The line terminator character is not stored in the buffer.
buffer
= (char *)POP(stack
);
while (max
-- && ((c
= getc(stdin
)) != '\n') && (c
!= EOF
))
* Send len characters from the buffer at addr to the output stream.
addr
= (char *)POP(stack
);
* Sends an end-of-line sequence to the output stream.
* Returns the end-of-line sequence that is used within files as
* a packed (leading count byte) string.
char crstr
[2] = { 0x01, '\n' };
/* Find the error code returned by the last failing system call. */
/* Display an error message */
mode
= (mode_t
)POP(stack
);
name
= (char *)POP(stack
);
name
= expand_name(name
);
if (isobsolete(name
) == 1)
printf("File: %s\n", name
);
status
= open(name
, flag
, mode
);
name
= expand_name(name
);
return ((long)open(name
, O_RDWR
|O_CREAT
|O_TRUNC
, (int)mode
));
/* f_read ( fd buf len -- #bytes ) */
buf
= (char *)POP(stack
);
bytes
= read(fd
, buf
, len
);
/* f_write ( fd adr len -- #written ) */
buf
= (char *)POP(stack
);
bytes
= write(fd
, buf
, len
);
/* unlink ( str,len -- ok? ) */
stack
= pop_fstring(stack
, &path
, &len
);
printf("UNLINK: %s\n", path
);
/* f_seek ( fd offset whence -- ) */
status
= lseek(fd
, offset
, whence
);
buf
= (char *)POP(stack
);
status
= ioctl(fd
, code
, buf
);
disp
= (void (*)())POP(stack
);
prev
= signal(sig
, disp
);
stack
= pop_fstring(stack
, &sbuf
, &len
);
/* chdir ( str,len -- ok? ) */
stack
= pop_fstring(stack
, &sbuf
, &len
);
/* getwd ( -- str,len ) */
buf
= malloc(MAXPATHLEN
+1);
/* alloc ( len -- buf ) */
/* free ( adr,len -- ) */
buf
= (char *)POP(stack
);
/* sbrk ( size -- va ) */
/* dlopen ( str,len mode -- handle ) */
stack
= pop_fstring(stack
, &lib
, &len
);
handle
= dlopen(lib
, mode
);
/* dlclose ( handle -- ) */
handle
= (void *)POP(stack
);
/* dlerror ( -- str,len ) */
stack
= push_cstring(stack
, err
, strlen(err
));
stack
= push_cstring(stack
, err
, 0);
/* dlsym ( str,len handle -- ptr ) */
handle
= (void *)POP(stack
);
stack
= pop_fstring(stack
, &sym
, &len
);
symptr
= dlsym(handle
, sym
);
/* getenv ( str,len -- buf,len ) */
stack
= pop_fstring(stack
, &sbuf
, &len
);
PUSH(localtime(&tadd
), stack
);
* Flush the data cache if necessary and possible. Used after writing
* instructions into the dictionary.
int token_size
= POP(stack
);
char *link
= (char *)POP(stack
);
char *str
= (char *)POP(stack
);
link
= (char *)((*(unsigned long *)(link
)) +(origin
));
link
= (char *)((*(unsigned short *)(link
) << tshift
) +(origin
));
while (link
!= (char *)origin
) {
namep
= link
- token_size
- 1;
nextlen
= (*namep
) & 0x1f;
if (*(namep
++) != *(p
++))
PUSH((((long)link
)-token_size
), stack
);
link
= (char *)((*(unsigned long *)(link
-token_size
))
link
= (char *)((*(unsigned short *)(link
-token_size
)
/* save-image ( up,len origin,len name,len -- ) */
uchar_t
*upaddr
, *dicaddr
;
stack
= pop_fstring(stack
, &fname
, &flen
);
dicaddr
= (uchar_t
*)POP(stack
);
upaddr
= (uchar_t
*)POP(stack
);
file
= fopen(fname
, "wb");
fprintf(stderr
, "save_image: failed to create %s\n",
fwrite(dicaddr
, 1, dlen
, file
);
fwrite(upaddr
, 1, ulen
, file
);
static include_file_t
*includes
= NULL
;
/* include ( str,len -- str,len ) */
(void) pop_fstring(stack
, &cname
, &len
);
name
= expand_name(cname
);
if (isobsolete(name
) == 1)
* open the file, using SCCS if required
printf("failed to open %s\n", name
);
newfile
= malloc(sizeof (include_file_t
));
printf("Malloc failed for include file: %s\n", name
);
newfile
->next
= includes
;
newfile
->name
= strdup(name
);
printf("File: %s\n", name
);
/* bootstrap ( str,len -- buf,len ) */
stack
= pop_fstring(stack
, &cname
, &len
);
name
= expand_name(cname
);
printf("Bootstrap: %s (%s)\n", cname
, name
);
if (isobsolete(name
) == 1)
* open the file, using SCCS if required
fd
= open(name
, O_RDONLY
);
printf("failed to open bootstrap file %s\n", name
);
buffer
= malloc(sbuf
.st_size
+1);
printf("Malloc failed for bootstrap file: %s\n", name
);
len
= read(fd
, buffer
, sbuf
.st_size
);
if (len
!= sbuf
.st_size
) {
printf("Short read on bootstrap file %s\n", name
);
printf("Bootstrapped: %s [%d bytes]\n",
* xref_symbol ( str,len line# state -- str,len )
#define RPRINTF(x) printf x
pop_fstring(stack
, &fnname
, &len
);
RPRINTF(("ref: %s\n", fnname
));
xref_add_symbol_reference(fnname
, line
);
pop_fstring(stack
, &fnname
, &len
);
RPRINTF(("define: %s\n", fnname
));
xref_add_symbol_definition(fnname
, line
);
pop_fstring(stack
, &fnname
, &len
);
RPRINTF(("hide: %s\n", fnname
));
xref_modify_symbol_definition(fnname
, 0);
pop_fstring(stack
, &fnname
, &len
);
RPRINTF(("reveal: %s\n", fnname
));
xref_modify_symbol_definition(fnname
, 1);
pop_fstring(stack
, &fnname
, &len
);
RPRINTF(("string: %s\n", fnname
));
xref_add_string(fnname
, len
, line
);
printf("%s:%d: xref_symbol invalid state %d\n",
__FILE__
, __LINE__
, state
);
/* xref-file ( [name,len,-1 -- name,len] | [ 0 -- ] ) */
* We dont actually pop the stack though..
pop_fstring(stack
, &fname
, &len
);
printf("Pushing.. %s\n", fname
);
if ((xref_enabled
) || 1) {
xref_add_file_reference(fname
);
xref_remove_file_reference();
/* xref_trigger ( state -- ) */
extern int xref_enable_forward_refs
;
* Flush the xref-file to disk.
if (symbol_defined(symbol
)) {
* Init; extract the xref variables from the symbol table.
if (symbol_defined(symbol
)) {
char *symdata
= extract_symbol(symbol
);
char *preload
= extract_symbol("XREF-PRELOAD");
xref_init(symdata
, preload
, xref_enable_forward_refs
);
printf("%s:%d Unexpected Xref trigger\n", __FILE__
, __LINE__
);
printf("Xref enabled?: %d\n", xref_enabled
);
/* symbol-set ( data,dlen symbol,len create? -- ) */
stack
= pop_fstring(stack
, &symbol
, &slen
);
stack
= pop_fstring(stack
, &data
, &dlen
);
snprintf(cstr
, sizeof (cstr
), "%s=%s", symbol
, data
);
define_symbol(symbol
, FORTH_DEFINE
);
undef_symbol(symbol
, FORTH_UNDEF
);
/* symbol-exists( symbol,len -- exists? ) */
stack
= pop_fstring(stack
, &symbol
, &slen
);
defined
= symbol_defined(symname
);
/* symbol-value( symbol,len -- value,len ) */
stack
= pop_fstring(stack
, &symname
, &slen
);
if (symbol_defined(symbol
)) {
symdata
= extract_symbol(symbol
);
printf("Tos: %x\n", tos
);
extern int compile_errors
;
extern int compile_warnings
;
* Now the function table.
fstackp ((*sfunctions
[])(fstackp
)) = {
f_open
, f_creat
, f_close
, f_read
,
f_write
, f_ioctl
, c_keyques
,
f_bye
, f_lseek
, f_unlink
, fileques
,
c_type
, c_expect
, syserror
,
s_flushcache
, pr_error
, 0,
f_init
, f_op
, f_move
, f_rows
, f_cols
,
printnum
, mmap
, open
, close
,
f_dlopen
, f_dlsym
, f_dlerror
, f_dlclose
,
save_image
, bootstrap
, includefile
, 0,
xref_symbol
, xref_file
, xref_trigger
, xref_stat
,
symbol_set
, symbol_exists
, symbol_value
,
compile_info
, compile_abort
, compile_warn
, 0,