[net.sources] Princeton FORTH v2.0 for the VAX, part 1 of 8

wls@astrovax.UUCP (William L. Sebok) (06/26/84)

Part 1 of 8

  This is a 32 bit public domain implementation of Forth has been written for
a VAX running under 4.1 or 4.2 BSD UNIX.  It has been running now for
about two years at the Astrophysics Dept. at Princeton University and is used
for image processing.  It follows the 79-standards except: 1) entries on the
parameter stack are 32 bits wide,  2) addresses are 32 bits (rather than the
demanded 16 bits) wide, 3) Certain escape sequences beginning with a backslash
are recognized in the printing word  ." ......"

  Some extensions to the 79-standard are: 1) A character string stack, with a
full set of string operators. This also make manipulation of Unix file names
infinitely easier,  2) A floating point stack, and 3) A set of Unix interface
words.

  Colon definitions are compiled as a series of bsbb, bsbw, or jsb instructions
(the shortest one that will reach) rather than as  list of pointers.  The ICODE
operator can be used instead of the ICODE operator for short definitions.  When
a word defined by the ICODE operator is compiled its code is stuffed in-line
rather than referenced.  Number references are compiled as the shortest of the
many possible instructions to push that number onto the stack.

Dearchive this package in a directory called forth.  Edit the makefile to
point to the directory it is in.  Convert the file ./vaxforth/forth.blk.txt
to a forth screen file ./vaxforth/forth.blk  with the provided utility utf :
	utf forth.blk.txt forth.blk

Good luck.  I will be gone to an observing run at Mt. Palomar to use the
60 inch telescope there till July 11.  I will happy to answer questions after
that.

William L. Sebok
Princeton Univ. Observatory
Peyton Hall, Rm. 129
Princeton, NJ 08544
Phone: (609)452-3586
Uucp: {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,vax135}!astrovax!wls
--------------Cut here------------------
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Making directory "."'
mkdir .
/bin/echo 'Extracting ./README'
sed 's/^X//' <<'//go.sysin dd *' >./README
Dear potential users:

This is my implementation of the Forth language on 4.1-4.2 bsd VAX/Unix.
The documentation is in the subdirectory doc .  Read first the file `basics'.
I do not have the time nor the inclination to make a forth tutorial.  That is
probably better done by one of the books on the market.  I have made an attempt
to follow the 79-Forth standards, so that a copy of these standards would be
handy.  Typing VLIST will list the forth directory, showing the commands
available.
	Kernel source is in subdirectory `vaxforth'.  As is usual part of
the basic system (i.e. what comes up when you run `forth') is written in
forth and is stored in the file  vaxforth/forth.blk.  You will want to
make yourself a kernel which knows about the pathname of this file and
the pathname of where you have installed the "standard forth directory" (i.e.
what you have created by reading in this tar tape).  The makefile in directory
vaxforth and the compiled kernel have these defined as
X/usr/forth/vaxforth/forth.blk  and /usr/forth , respectively.  To change these
things, change the FBLK and FDIR variables in the makefile and run
	make forth
to recompile the kernel.  In a pinch,
	forth xxxx
will use file xxxx as its blockfile.
	forth -w
opens its blockfile for update,
	forth -l
causes it not to do its initial load from the blockfile, and
	forth -s
causes it to not set signals to be caught.  The last two are debugging options.

Good luck.  Forth is never done.  I have some ambitions to add new features to
this kernel.  When they are ready I will post them.

William L. Sebok
Princeton Univ. Observatory
Peyton Hall, Rm. 129
Princeton, N.J. 08544
(609) 452-3586
(uucp) {allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,vax135}!astrovax!wls
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 ./README
	/bin/echo -n '	'; /bin/ls -ld ./README
fi
/bin/echo 'Making directory "./bin"'
mkdir ./bin
if [ $made = TRUE ]; then
	/bin/chmod 755 ./bin
	/bin/echo -n '	'; /bin/ls -ld ./bin
fi
/bin/echo 'Making directory "./doc"'
mkdir ./doc
/bin/echo 'Extracting ./doc/assembler'
sed 's/^X//' <<'//go.sysin dd *' >./doc/assembler
Assembler

	In the Assembler vocabulary essentially all Vax machine instructions
	are compiled by an expression of the form:
		operandn ... operand2 operand1  operator
	
	The `operator' names are out of the VAX Architecture Manual. A few
	operator names are slightly modified so as to be distinguishable within
	the first 5 characters.  These are:

	     from manual	in this implementation
		MOVZWL 			MVZWL
		MOVZBL			MVZBL
		MOVZBW			MVZBW
		PUSHAL			PUSAL
		PUSHAB			PUSAB
		PUSHAQ			PUSAQ
		PUSHAW			PUSAW

	Operands are expressed in reverse order from the way they appear in
	VAX MACRO/11 or the vax as assembler. 

	Operands are of the form:

		n		Register
		n )		Register Deferred
		n )+		Autoincrement
		n -)		Autodecrement
		n )+ )		Autoincrement Deferred
		off n ))	displacement
		off n )) )	displacement deferred
		num #		immediate (or literal)
		addr @#		absolute
		addr R)		relative
		addr R) )	relative deferred
		addr		relative (if addr > 255)
		addr )		relative deferred (if addr > 255)

	Added after any of the above:
		n ]		indexed by register `n'

	`n' is a register number that can have values from 0 to 15, although
	CONSTANT's are provided for common values.  `#' produces immediate
	or literal mode addressing, depending on whether the number `num'
	is within range for literal mode.  On floating point operands `num' is
	taken from the floating point stack.  Otherwise `num' is taken from
	the parameter stack.  A stack value greater than 255 is interpreted
	as an address to be assembled as a relative mode operand.  Relative mode
	references to addresses less than or equal to 255 must use the R)
	construction.  Displacements for relative and displacement mode are 
	selected from byte, half-word, or long-word offsets as the smallest
	sufficient offset size.

	The following are the assigned registers.  The letters are defined as
	constants.
		Name	value	function
		U	7	User area pointer
		H	8	dictionary pointer
		C	9	string stack pointer
		F	10	floating point stack pointer
		S	11	parameter stack pointer
		R	14	return stack pointer

	Registers 0-6 are available for scratch.

	Some instructions are listed in the Achitecture Manual as taking address
	displacements as operands.  In these cases one gives an address with
	which the assembler uses to construct displacements.

	Examples of such operators are: ACBW, ACBF, ACBB, ACBL, AOBLSS,
	AOBLEQ, SOBGEQ, and SOBGTR.  In such cases the address can be supplied
	by BEGIN (which places an address on the stack) to form loops of the
	form (for example):

		BEGIN  ...  0 SOBGTR

Conditionals

	Conditional expressions are of the form:
		cond IF  . . .   ELSE  . . .  THEN
	or
		cond IF	 . . .  THEN
	
	where the else clause is optional.  This expression compiles as a
	conditional branch to ELSE or, if ELSE is not present, to THEN, and an
	unconditional branch to the THEN.  A brw branch is used for the
	unconditional branch.  A conditional byte-displacement branch (the only
	type that exists) around a brw branch is used for the conditional
	branch.  Thus the size of the IF and ELSE clauses must be each smaller
	than 32767 bytes.  Since individual forth words should be reasonably
	small this should not ordinarily be a problem.

	`cond' is a CONSTANT that puts a value on the stack used in the
	compilation of the conditional branch.  The following such CONSTANT's
	are available.

	0<>	not equal to less   or	not equal to zero 
	0=	equal to	or	equal to zero

	0>	greater than (signed) or greater than zero
	0<=	less than or equal to (signed)  or  less than or equal to zero
	0>=	greater than or equal to (signed)  or greater than or equal to
		zero
	0<	less than (signed)  or less than zero
	HI	greater than (unsigned)
	LO	less than (unsigned)
	1V	overflow
	1C	carry

	One more operator is available:

NOT		cond  --- not_cond
	reverse the logic of the condition

	A conditional loop structure is available:

	BEGIN  ...  cond UNTIL

	which also uses the above options for `cond' 

Further operators and utilities:

ABORT		---  addr				assembler
	Address of assembler entry to Forth abort routine.  This entry assumes
	that the message number is in register 0.

JBSB		addr  ---				assembler
	Construct a jump or branch to subroutine to address `addr'.  One of the
	three operators: bsbb, bsbw, or jsb is selected, depending on which
	takes the least memory but is sufficient to reach the destination.
	(aside, the brain-damaged Unix "as" assembler does not provide the
	equivalent to this although it provides the equivalent for an
	unconditional branch).

BR		addr  ---				assembler
	Construct an unconditional jump or branch to the address `addr'.  One
	of the three operators: brb, brw, or jmp is selected, depending on
	which takes the least memory but is sufficient to reach the destination.

OP		addr ---				assembler
	Construct an operator for an otherwise unsupported machine
	instruction.  Used in definitions of the form:

		addr OP <name>

	<name> when executed compiles an instruction into the dictionary with
	the same syntax as the supplied machine instruction words.  `addr'
	points to a null terminated string describing the op code and operands
	of the instruction.  The first one or two bytes are the op code of the
	instruction.  The rest of the bytes describe the instruction operands.
	These bytes have the following values:

	0	terminator
	1	bit or register mask
	2	byte offset (address)
	3	2 byte word offset (address)
	4	byte
	5	2 byte word integer
	6	4 byte longword integer
	7	8 byte quadword integer
	8	single precision floating point
	9	double precision floatin point
	10	16 byte octoword integer
	11	G floating point
	12	H floating point

	Essentially all of the operands present in the Architecture Manual are
	included except the priveged operators, packed decimal, and G and H
	floating.  OP allows one to define these otherwise unsupported operators
	if needed.

The operators which are defined are:

ACBB, ACBF, ACBL, ACBW, ADDB2, ADDB3, ADDF2, ADDF3, ADDL2, ADDL3, ADDW2, ADDW3,
ADWC, AOBLEQ, AOBLSS, ASHL, ASHQ, BBC, BBCC, BBCS, BBS, BBSC, BBSS, BICB2,
BICB3, BICL2, BICL3, BICPSL, BICW2, BICW3, BISB2, BISB3, BISL2, BISL3, BISPSL,
BISW2, BISW3, BITB, BITL, BITW, BLBC, BLBS, CALLG, CALLS, CASEB, CASEL, CASEW,
CHMK, CLRB, CLRL, CLRQ, CLRW, CMPB, CMPC3, CMPC5, CMPF, CMPL, CMPV, CMPW,
CMPZV, CRC, CVTBF, CVTBL, CVTBW, CVTFB, CVTFD, CVTFL, CVTFW, CVTLB, CVTLF,
CVTLW, CVTRFL, CVTWB, CVTWF, DECB, DECL, DECW, DIVB2, DIVB3, DIVF2, DIVF3,
DIVF3, DIVF3, DIVF3, DIVL2, DIVL3, DIVW2, DIVW3, EDIV, EMODF, EMUL, EXTV,
EXTZV, FFC, FFS, INCB, INCL, INCW, INDEX, INSQUE, INSV, JMP, JSB, LOCC,
MATCHC, MCOMB, MCOML, MCOMW, MNEGB, MNEGF, MNEGL, MNEGW, MOVAB, MOVAL, MOVAQ,
MOVAW, MOVB, MOVC3, MOVC5, MOVD, MOVF, MOVL, MOVPSL, MOVQ, MOVTC, MOVTUC,
MOVW, MULB2, MULB3, MULF2, MULF3, MULL2, MULL3, MULW2, MULW3, MVZBL, MVZBW,
MVZWL, POLYF, POPR, PUSAB, PUSAL, PUSAL, PUSAQ, PUSAW, PUSHR, REI, REMQUE,
RET, ROTL, RSB, SBWC, SCANC, SKPC, SOBGEQ, SOBGTR, SPANC, SUBB2, SUBB3, SUBF2,
SUBF3, SUBL2, SUBL3, SUBW2, SUBW3, TSTB, TSTF, TSTL, TSTW, XORB2, XORB3,
XXORL2, XORL3, XORW2, XORW3
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/assembler
	/bin/echo -n '	'; /bin/ls -ld ./doc/assembler
fi
/bin/echo 'Extracting ./doc/basics'
sed 's/^X//' <<'//go.sysin dd *' >./doc/basics
Basics:

The following discussion is not meant to be complete (it can't be) but to
outline some of the most important things needed to get started.
In the following discussion <cr> means to press carriage return.  In the
definitions of forth commands (words), Forth word names are usually given in
capitals with their arguments in lower-case.  The word names can actually
be typed in either lower or upper case.

To enter forth type
	forth <cr>
To exit forth either type a control D or type:
	bye

   Commands can be in either upper or lower case.  The case in command names is
not distinguishable.  However the case in character strings is distinguishable.
In particular, the case in file names is distiguishable.  Thus
	loadf xxx	and
	LOADF xxx	will load file xxx but
	LOADF XXX	will load file XXX which in Unix is a different thing.
   Commands are distinguished from each other by their first 5 characters plus
the count of the total number of characters.
	
You can stop execution of forth at any time with a control Z. This will return
control to the original shell.
Most signals are caught, causing a message and a return to the forth outer
interpreter.  The QUIT signal (usually invoked with a control backslash) is
deliberately left uncaught as an last-resort exit.

Typing
	sh <cr>      or
	csh <cr>
will execute  a shell  or c-shell  escape, respectively.
	sh[ command]
will invoke a (Bourne) shell to execute the program `command'.  This
construction (like most other string constructions in this implementation)
can appear inside a colon definition.
	
Program text:
This Forth compiler can read either forth screens or regular text files
created with your favorite editor.  These files can contain forth text.  Forth
screen files contain no newlines and are assumed to be divided into 1024 byte
screens.  Each 1024 byte screen is assumed to be divided into 64 byte lines
for editing purposes.  Regular text files or forth screen can be loaded (i.e.
the input stream from the terminal temporarily made to come from contents of
the file) with the command
	FLOAD filname
Where `filname' is the name of the file.  Screen files only can be loaded with:
	LOADF filname
Text files can contain LOAD's, FLOAD's, and LOADF's.  This Loading can be thus
nested to any level.

A new forth screen file name `filnam' containing `n' screens can be created
and initialized to contain blanks with the command:
	n FCREATE filname

A "block mapping table" is kept map screen files with ranges of forth block
numbers.  The current contents of the block mapping table can be examined
with the command:
	BLKTAB
BLKTAB currently shows file descriptor numbers and the first and last block
numbers of a file.  Initially a file forth.blk is mapped read-only into
block number 0.

A file can be added to the block mapping table with the command:
	n INSTALL filnam
Forth block number `n' will then correspond to the beginning of the file. The
last block number of the mapping will depend on the length of the file.  The
file is opened for read/write if it has the necessary permissions.  Otherwise
the file is opened read-only.  The command
	n RINSTALL filnam
can be used to force the file to be opened read-only.

A file can be closed and removed from the block mapping table with the command:
	n REMOVE
`n' is the first block number of the file to be removedstart of the file
and the last block n

INSTALL, RINSTALL, LOADF, and FLOAD will first look for the file in the current
directory, then if they do not find it they will look in the standard forth
directory. The name of the standard forth directory (usually /usr/forth) is
kept in the string (stack) constant FDIR .  Prefixing the file name with a <
(less than) character will force the above words to look only in the standard
forth directory.  Some time in the future directory search paths (like the
environment $PATH variable) may be implemented.

The forth screen editor is loaded with
	LOADF edit
after which a block `n'can be edited with:
	n EDIT

The keys to push on your terminal to invoke the editor commands will appear
the bottom of the screen.

At the moment the terminals supported are vt100, televideo model 950 (termcap
entry tvi950) and Heathkit/Zenith model 19 (h19 and h19us).  Hopefully other
terminals will be added in the future.  You can add other terminals by creating
files in the forth directory subdirectories `keys' and `termcap'. Until I get
around to properly documenting this, the easiest way to understand how to do
this is to examine the code already written for the existing terminals. If
I get ambitious I may write a default driver that uses /etc/termcap. The
problem with termcap is that 1) this editor uses terminal features that are
not in termcap 2) termcap says nothing about the mapping of editor commands
to labeled control keys on your terminal.

Without the screen editor you are unfortunately forced to use to the line
editor.  The line editor commands are built-in but kept in the EDITOR
vocabulary. One can shift into the EDITOR vocabulary by typing EDITOR (you can
later shift out of it by typing FORTH ).  Then list the screen with the
command:
	n LIST
besides listing the screen this sets block `n' as the current screen, the
screen being edited.  One can also set this directly with the commands:
	n SCR !

There are 16 lines numbered 0 through 15 of 64 characters each in the screen.
The following are the editor commands.

	n T	Type line n, also placing a copy of it on the string stack.
	n D	Delete line n, placing a copy of it on the string stack.
		The lines below n are moved up and a blank line is placed
		in line 15.
	n I	Pop the top string from the string stack and insert it at
		line `n'. The lines after `n' are scrolled down with line
		15 falling off the end and lost.

		Note that lines can be moved with combinations of the D and
		I commands.

	n R	Pop the top string from the string stack and replace the
		contents of line `n' with it.

	L	Re-list the current block.

   The commands to place text `xxxxxxxxx' on the string stack (for the I and R
commands), are:
	" xxxxxxxx"
	( xxxxxxxx)
	(( xxxxxxx)
	[[ xxxxxxx]
Note the initial blank delimiter.  The character string runs from the blank to
but not including the final delimiter.  The double quote operator (not really
an editor command) is most commonly used, the others provided for text which
contains double quotes.  The T command has been designed so that the OK prompt
typed at the end of the line provides a right margin for the `"' and `('
commands.  Note also that for all except the `(' (left parenthesis) commands,
that backslashes in the text will cause it and the following character(s) to be
interpreted as a control character.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/basics
	/bin/echo -n '	'; /bin/ls -ld ./doc/basics
fi
/bin/echo 'Extracting ./doc/bin'
sed 's/^X//' <<'//go.sysin dd *' >./doc/bin
The forth/bin directory contains non-forth written utilities. These are
utilities provided to ease the handling of forth screen files.

utf	Text file to forth screen filter.
ftu	Forth screen to text file filter.
prf	print forth screens.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/bin
	/bin/echo -n '	'; /bin/ls -ld ./doc/bin
fi
/bin/echo 'Extracting ./doc/editor'
sed 's/^X//' <<'//go.sysin dd *' >./doc/editor
COPY		scr1  scr2  ---					editor
	Copy screen 1 to screen 2.  Only the ownership of the buffer is changed,
	no actual copying is done until the next "FLUSH" or until that buffer
	is needed.

L		scr  ---					editor
	List the current screen.  The current screen is contained in the user
	variable "SCR".  SCR is set by LIST.

I		lin_s  n  ---					editor
	Expand character string `lin_s' to 64 bytes and insert before line `n'
	in the current screen, scrolling the rest of the lines towards the
	end of the screen.  Line 15 is lost.

D		n  ---  lin_s					editor
	Delete line `n' from the current screen, returning the deleted line
	on the string stack.  The lines following the deleted line are scrolled
	up, with line 15 being replaced by a blank line.

R		lin_s  n  ---					editor
	Expand character string `lin_s' to 64 bytes and use it to replace
	line `n' in the current screen.

T		n  ---  lin_s					editor
	Print line `n' in the current screen and return it on the string
	stack as `lin_s'.  The line is printed with trailing blanks NOT
	deleted and with two preceeding spaces.  This allows the trailing
	OK to serve as a margin for entry  of text with `"' or `('.

(		--- lin_s					editor

	Used in expressions of the form:

		( text.....)
	The "text", from but not including the initial left parenthesis and
	space up to but not including the trailing right parenthesis delimiter
	are placed on the string stack.  Included escapes (combinations of
	characters beginning with a backslash) are NOT specially interpreted.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/editor
	/bin/echo -n '	'; /bin/ls -ld ./doc/editor
fi
/bin/echo 'Extracting ./doc/forth.1'
sed 's/^X//' <<'//go.sysin dd *' >./doc/forth.1
X.TH forth 1 forth 6/25/84
X.SH NAME
forth \- run the forth interpreter
X.SH SYNOPSIS
X.B forth
[
X.B -w
] [
X.B -l
] [
X.B -s
] [
X.B -buf
bufs
] [
X.B -top
topaddr ] [ blkfile ]
X.SH DESCRIPTION
X.PP
X.I forth
runs a 32 bit implementation of the Forth 79 Standards.  Extensions include
X.IP 1)
a floating point stack
X.IP 2)
a string stack
X.IP 3)
Unix interface words.
X.PP
When
X.I forth
is run it will attempt to load some of its words from screen #3 of the screen
format file /usr/src/forth/vaxforth (a screen format file consists of
contiguous 1024 byte blocks with no newlines).
The `blkfile' parameter on the command line allows another file to be
substituted.
The
X.I -l
flag will turn off this automatic loading.
X.PP
The
X.I -w
flag will cause this screen file to be opened for read/write rather than
the default opened read-only.
X.PP
The
X.I -s
flag causes the catching of error signals to be disabled.
X.PP
Normally the forth grows its stacks downward from the top of available
memory.  The top of memory used can be lowered by specifying the
X.I -top
flag followed by the address of the desired top of memory in octal.
X.PP
7 buffers are normally allocated in the block buffer pool.  This can be changed
for one invocation by specifying
X.I -buf
followed by the desired number of buffers in octal.
X.SH FILES
X/usr/src/forth/vaxforth/forth.blk
X.SH BUGS
Should use hex for addresses and decimal for buffer count.  Should provide
parameters for changing stack sizes during an invocation.  Should provide
Forth 83 standard words, etc, etc.
X.SH AUTHOR
William L. Sebok (astrovax!wls)
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/forth.1
	/bin/echo -n '	'; /bin/ls -ld ./doc/forth.1
fi
/bin/echo 'Extracting ./doc/ftu.1'
sed 's/^X//' <<'//go.sysin dd *' >./doc/ftu.1
X.TH ftu 1 local 6/25/84
X.SH NAME
ftu \- convert a screen format file to a text file
X.SH SYNOPSIS
X.B ftu
[ file1  [ file2 ] . . .  out ]
X.SH DESCRIPTION
X.PP
The screen-format files mentioned in the command line are converted to a text
file.
Screen files consist of 1024 byte blocks containing no newlines.  Each block
is divided into 16 fix-length lines of 64 bytes apiece.
X.PP
If there are no arguments given the command behaves like a filter.
If there is one argument that file is used as input and output is sent to
the standard output.
If the first argument is
X.I -
(a dash), then the input is taken from the standard input.
Output is placed in the file given at the end of the command line.
X.SH AUTHOR
William L. Sebok (astrovax!wls)
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/ftu.1
	/bin/echo -n '	'; /bin/ls -ld ./doc/ftu.1
fi
/bin/echo 'Extracting ./doc/notation'
sed 's/^X//' <<'//go.sysin dd *' >./doc/notation
Notation for parameters:

The  behavior of a word is given in the form (for example):

	a b c d e  ---  f g h

The items to the left of the triple dash are the items on the stack(s) before
the execution of the word with the top of the stack(s) on the right.  These
items are consumed by execution of the word.  Which stack an item is on is
indicated by a suffix on the name of the item (see below).  The items to the
right of the triple dash are the items left on the stack(s) by the execution of
the word with (again) the top of the stack(s) to the right.

Due to the presense of several different stacks a slightly non-standard
notation is used to express stack items.  Items have a suffix consisting of an
underscore and a key letter.  The key letter indicates the item type.  The
stack upon which the item resides depends on the key letter, for instance: an
item with the suffix `_s' would reside on the string stack and an item with the
suffix `_f' would reside on the floating point stack.

An item without a suffix is an integer occupying one stack cell width (32 bits
on the Vax).

The suffixes currently defined are:

suffix	stack		item

_2	parameter	double integer (two stack cells)
_d	floating point	double precision floating point item
_f	floating point	floating point item
_l	parameter	32 bit integer (1 cell on 32 bit machine, 2 cells on
			16 bit machine) note the important distinction between
			an _l and a _2.
_s	string		string item
_u	parameter	unsigned
_u2	parameter	unsigned double integer
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/notation
	/bin/echo -n '	'; /bin/ls -ld ./doc/notation
fi
/bin/echo 'Extracting ./doc/prf.1'
sed 's/^X//' <<'//go.sysin dd *' >./doc/prf.1
X.TH prf 1 local 6/25/84
X.SH NAME
prf \- format for printing a forth screen format file
X.SH SYNOPSIS
X.B prf
file  . . .
X.SH DESCRIPTION
X.PP
The screen files mentioned in the command line are formatted for printing.
Three screens are printed per page with the line numbers in the left hand
columns.  The file name and the date are printed on top of the page.
X.PP
Screen files consist of 1024 byte blocks containing no newlines.  Each block
is divided into 16 fix-length lines of 64 bytes apiece.
X.SH AUTHOR
William L. Sebok (astrovax!wls)
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/prf.1
	/bin/echo -n '	'; /bin/ls -ld ./doc/prf.1
fi
/bin/echo 'Extracting ./doc/utf.1'
sed 's/^X//' <<'//go.sysin dd *' >./doc/utf.1
X.TH utf 1 local 6/25/84
X.SH NAME
utf \- convert a text file to a screen format file
X.SH SYNOPSIS
X.B utf
[ file1  [ file2 ] . . .  out ]
X.SH DESCRIPTION
X.PP
The text files mentioned in the command line are converted to screen-format
files.
Screen files consist of 1024 byte blocks containing no newlines.  Each block
is divided into 16 fix-length lines of 64 bytes apiece.
X.PP
If there are no arguments given the command behaves like a filter.
If there is one argument that file is used as input and output is sent to
the standard output.
If the first argument is
X.I -
(a dash), then the input is taken from the standard input.
Output is placed in the file given at the end of the command line.
X.SH AUTHOR
William L. Sebok (astrovax!wls)
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./doc/utf.1
	/bin/echo -n '	'; /bin/ls -ld ./doc/utf.1
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 ./doc
	/bin/echo -n '	'; /bin/ls -ld ./doc
fi
/bin/echo 'Making directory "./src"'
mkdir ./src
/bin/echo 'Extracting ./src/ftu.c'
sed 's/^X//' <<'//go.sysin dd *' >./src/ftu.c
X/*
 * Convert List Forth Block Files to ordinary line oriented files
 */
main(argc,argv)	
int argc ;
char *argv[] ;
{
#define BLANK 040
#define LINSIZ 64

	char line[LINSIZ+1];
	register int n;
	int fil, ofil; 

	argc--; argv++;

	if (argc>1) {
		argc--;
		ofil = creat(argv[argc], 0666);
		if (ofil<0) {
			perror(argv[argc]);
			exit(1);
		}
	} else {
		ofil = 1;
	}

	do {
		if (argc>0 && (argv[0][0] != '-' ||  argv[0][1] != '\0')) {
			fil = open(*argv,0) ;
			if (fil<0) {
				perror(*argv);
				continue;
			}
		} else {
			fil = 0;
		}

		while ( (n = read(fil,line,LINSIZ)) == LINSIZ ) {
			while (n>0 && line[--n] == BLANK) ;
			line[++n] = '\n' ;
			write(ofil,line,n+1) ;
		}
		if (fil>0)
			close(fil);

		argv++;
	} while (--argc>0) ;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./src/ftu.c
	/bin/echo -n '	'; /bin/ls -ld ./src/ftu.c
fi
/bin/echo 'Extracting ./src/prf.c'
sed 's/^X//' <<'//go.sysin dd *' >./src/prf.c
X/* List FORTH block Files */

#include	<stdio.h>

main(argc,argv)
int argc ;
char *argv[] ;
{
#define	BLANK	040
#define NULL	0
#define	LINSIZ	64
#define	LINES	16
#define PAGSIZ	3*LINSIZ*LINES

	register char *p , *pp ;
	register int n ;
	int	pnt, fil, lin, blk, first, last ;
	char	page[PAGSIZ] ;
	char	line[LINSIZ+1] ;
	long	tvec ;
	char	*ctime() ;
	char	*fcolon();

	char buf[BUFSIZ] ;
	setbuf(stdout,buf) ;

	pnt = 1 ;
	if (argc == 1) {
		fil = 0 ;
		pnt = 0 ;
	}

	do {
		first = 0 ; last = 32667 ;
		if (pnt) {
			p = argv[pnt] ;
			pp = fcolon(p) ;
			if (pp != NULL) {
				first = (atoi(pp)/3)*3 ;
				pp = fcolon(pp) ;
				if (pp != NULL) last = ((atoi(pp)+3)/3)*3 ;
			}
			fil = open(p,0) ;
			if (fil<0) {
				fprintf(stderr,"Unable to Open %s\n",p);
				break ;
			}

			if (first>0) {
				if (lseek(fil, (long)first << 10, 0) < 0)
					perror("On seek") ;
			}
		}

		for(blk=first ; blk<last ; blk++) {
			if (blk%3==0) {
				n = read(fil,page,PAGSIZ) ;
				if (n<0) { perror("on input") ; break ; }
				if (n<PAGSIZ) {
					p = page + n ;
					n = PAGSIZ - n ;
					do *p++ = 0 ; while (--n>0) ;
					last = blk ;
				}
				if (*page==0 && *(page+1024)==0 &&
				    *(page+2048)==0) { blk += 2 ; continue ; }
				time(&tvec) ;
				printf("\014\n%s %s",argv[pnt],ctime(&tvec) ) ;
				p = page ;
			}
			printf("\n\n%d\n\n",blk) ;
			if (*p==0) printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n") ;
			else {
				for( lin=0 ; lin<LINES ; lin++) {
					pp = line ;
					n = LINSIZ ;
					do *pp++ = *p++ ; while (--n>0) ;
					while (pp>line && *(--pp)==BLANK) ;
					*++pp = 0 ;
					printf("%2d  %s\n",lin,line) ;
				}
			}
		}
		close(fil) ;
	} while (++pnt<argc) ;
}
char *fcolon(str)
char *str ;
{
	register char *p ;
	p = str ;
	for (;;) {
		if (*p == '\0') return ((char*)NULL) ;
		if (*p == ':') { *p++ = 0 ; return(p) ; }
		p++ ;
	}
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 664 ./src/prf.c
	/bin/echo -n '	'; /bin/ls -ld ./src/prf.c
fi
/bin/echo 'Extracting ./src/utf.c'
sed 's/^X//' <<'//go.sysin dd *' >./src/utf.c
X/*
 * translate Unix text files to Forth Screens
 */
#include <stdio.h>
main(argc,argv)	
	int argc; char *argv[];
{
#define BLANK 040
#define LINSIZ 64

	char line[512], buf[512] ;
	int l, n, a ;
	register int b ;
	register char *p1, *p2 ;
	int fil, ofil;

	argc--; argv++;

	if (argc>1) {
		argc--;
		ofil = creat(argv[argc], 0666);
		if (ofil<0) {
			perror(argv[argc]);
			exit(1);
		}
	} else {
		ofil = 1;
	}

	do {
		if (argc>0 && (argv[0][0] != '-' ||  argv[0][1] != '\0')) {
			fil = open(*argv,0) ;
			if (fil<0) {
				perror(*argv);
				continue;
			}
		} else {
			fil = 0;
		}

		p2 = line ;
		a=1 ;
		l=1 ;

		while (a>0) {
			a = b = read(fil, buf, 512) ;
			p1 = buf ;
			while ( b-- > 0 ) {
				if ( (*(p2++) = *(p1++) ) == '\n' ) {
					--p2 ;
					n = p2-line ;
					if (n>LINSIZ) {
						fprintf(stderr,
					"Line %d has %d characters.\n",
							l,n) ;
						n = LINSIZ ;
					}
					while (n++<LINSIZ) *(p2++) = BLANK ;
		/* output a line */	write(ofil,line,LINSIZ) ;
					p2 = line ;
					l++ ;
				}
			}
		}

		if (fil>0)
			close(fil);

		argv++;
	} while (--argc>0) ;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 ./src/utf.c
	/bin/echo -n '	'; /bin/ls -ld ./src/utf.c
fi
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 755 ./src
	/bin/echo -n '	'; /bin/ls -ld ./src
fi
exit
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,burl,cbosgd,decvax,ihnp4,kpno,princeton,vax135}!astrovax!wls