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