Jump to content
IGNORED

fbForth—TI Forth with File-based Block I/O [Post #1 UPDATED: 06/09/2023]


Lee Stewart

Recommended Posts

FYI - TurboForth has the ability to transfer BLOCKS into D/V80 files (usable by F'WEB or TI-Writer) and D/V80 files to BLOCKS. You might want to look at that code if you haven't already, Lee. Similar routines are available for Wycove Forth and maybe even somewhere in TI-Forth.

 

I need to have a look at it again; but, as I recall, the blocks I/O to/from DV80 files puts block labels, line numbers and a blank-line block separator on DV80 file output and expects that same format on input to blocks files. I don't think I want to do that. Like I said, I need to look at it again.

 

...lee

Link to comment
Share on other sites

Theinclusion of the BLOCK # and other info is user-selectable.

 

Yeah, I see that. The import of DV80 files to a blocks file does expect lines of not more than 64 characters and no headers. The export with block-number headers makes it nicer for the reader, but won't work very well for import. The export does not appear to list line numbers as I previously thought.

 

...lee

  • Like 1
Link to comment
Share on other sites

 

Yeah, I see that. The import of DV80 files to a blocks file does expect lines of not more than 64 characters and no headers. The export with block-number headers makes it nicer for the reader, but won't work very well for import. The export does not appear to list line numbers as I previously thought.

 

...lee

You can toggle headers with HDR.

As you noted, my code truncates incoming DV80 lines where they are > 80 characters.

Link to comment
Share on other sites

D/V80 file support for code import and export... I'd like to see the following:

 

export & import:

preserves block numbers ( since they can be referenced in the code )

supports binary blocks (escaped or something)

words that split across a line are preserved.

 

import:

can consume hand crafted files ( minimal required markup )

fails fast, leaves current block file unchanged if input file doesn't meat requirements

can import results from any options on export

tolerate extra whitespace-only after 64 characters.

 

export:

omit empty blocks

trim to the right lines that don't need 64 characters.

 

FIAD workflows (Classic99 or HDX):

paste code into/from forums into PC hosted files.

live edit in PC programming editors (relying on things like Classic99 FIAD options to read .txt as D/V80.

 

I would be totally satisfied by literal block dumping with only a block header, and user requirements that there are no characters on a line beyond 64.

 

It would be nice if the block doesn't have 16 lines, then only the first n lines less than 16 are required in the import file.

 

I'd prefer not to require line numbers within the block on import, it makes code refactoring on a PC difficult.

 

It would be nice if there could be comments lines that import would ignore so that it is easier to annotate code for forum posts..

as well as ignoring any blank extra lines between blocks, so that hand created D/V80 files are not finicky.

 

Super cool pie in the sky behaviors I'd like to see:

 

Pretty printed output that establishes a mythical forth 'style guide' with indentation and such, disregarding on output that the block becomes much greater than 16 lines, but most lines become effectively shorter. With the counter balance feature of importing these into a 'packed', no extra whitespace, blocks.

 

I've also thought it would be cool to be able to simply compile directly from dv/80, given we have the option to BSAVE to blocks. In this model, the dynamic development workflow that makes forth soooo cool is fairly obliterated though. It becomes a more traditional big-bang flow of source -> compile -> run, forget all, repeat. ( so I give that idea almost no priority :) )

 

And of course the number one #1 requirement is that it is something you enjoy working on :) that works for you, and that you would use.

 

-M@

Link to comment
Share on other sites

It is easy enough to interpret a DV80 file directly. All that needs to be done is to write a utility to read one line at a time into the Terminal Input Buffer (TIB) and to call INTERPRET for each line. Each line could also be echoed to the display (could be made optional) to aid in finding an error during the read/interpret process.

 

Regarding export from a blocks file to a DV80 file. I am inclined to do it only two different ways—one, with block headers and line numbers to facilitate easier reading and printing, much as with Appendix J in the manual—and, the other, with straight output of lines as they appear in the blocks file to facilitate editing for import into the same or another blocks file.

 

Also, I am not sure how smart I want to make the export. Trimming trailing blanks makes sense; but, an empty block will only take 16 bytes no header or line numbers are output. It is also a simple matter to suppress exporting blocks that contain any non-ASCII or non-printable characters (anything other than ASCII 32 – 126).

 

I think it is incumbent upon the user to manage block numbers for both import and export.

 

Suppressing specially coded comment lines upon import could be done by checking the first two columns for, say, '\\'. The only problem with this is that any set of characters could legitimately land in the first two columns, thus screwing up the import. Avoiding this would overly complicate the importer utility.

 

Upon import, I would truncate lines longer than 64 characters and pad lines with spaces that are shorter. This will effectively make the 64th character of one line contiguous with the first character of the next line.

 

Pretty output might be difficult when Forth comments are included—especially, if they are more than one line long.

 

Sorry for all the rambling.

 

...lee

  • Like 1
Link to comment
Share on other sites

My first and primary use case for wanting a feature in this area, is to support source control tools like git. In particular, visual diffs of the code from revision to revision, and reverting to a previous revision.

The features you have sited, would serve that quite well.

 

The second use case, would be exchanging snippets through the web.

The features you have sited, would serve that quite well, as well.

 

Learning how to use the TIB, and working with INTERPRET sounds like a good exercise for the student. :) Or maybe something for the Tutorial Blog :)

Link to comment
Share on other sites

Regarding export from a blocks file to a DV80 file. I am inclined to do it only two different ways—one, with block headers and line numbers to facilitate easier reading and printing, much as with Appendix J in the manual—and, the other, with straight output of lines as they appear in the blocks file to facilitate editing for import into the same or another blocks file.

 

Yes, that's how I'd do it. If you look at the various source listings in publications such as Forth Dimensions, all the Forth systems of the day exported their block output in this way.

Link to comment
Share on other sites

I fixed the “bug” in EMIT8 and TYPE8 (which uses it) in the TI Forth viewer/copier utilities, which act on the ASCII control characters, backspace, linefeed, bell and carriage return, by defining two new words, EMITG (only displays the character graphics of those codes without taking the corresponding actions) and TYPEG (which uses EMITG). The new FBLOCKS ZIP file is posted in post #1.

 

...lee

Link to comment
Share on other sites

This man is TIRELESS!!!

 

Mad kudos!

 

Thanks. It is fun!

 

I am currently trying to make it easier to change colors for all of the various VDP modes that will persist for the current session, even through a soft boot with COLD . As you well know, I am so tight on space that I may not be able to pull it off, but I am hopeful.

 

I am also pursuing a similar persistence for one's preferred text mode (40- or 80-column). I know I do not have enough space left to do what @Willsy did with the power-up menu for TurboForth (after the color-bar screen).

 

If I succeed with the above two pursuits, a user can customize block #1 of FBLOCKS to always start up with user-preferred colors for all VDP modes as well as the text mode of choice.

 

Regarding the user-preferred text mode, I am sure there are utilities I will need to edit to accommodate this change. I know, for example, that I explicitly coded a “return” to text mode in a couple of utilities—probably the resident editors, as well. :-o

 

...lee

Link to comment
Share on other sites

Almost finished with the changes mentioned in my last post, when I realized the three source files I had been working on had been trashed by my ailing free “upgrade” to Win10Pro. I am going to have to take the time to roll back to Win7Pro before any more damage is done. I may be awhile! :skull:

 

...lee

Link to comment
Share on other sites

Almost finished with the changes mentioned in my last post, when I realized the three source files I had been working on had been trashed by my ailing free “upgrade” to Win10Pro. I am going to have to take the time to roll back to Win7Pro before any more damage is done. I may be awhile! :skull:

 

...lee

Wow I'm so glad I didn't upgrade to Win10. The icon is still there next to the clock. In fact, just today a pop-up came up and said that I could still upgrade to Windows10 for free, "for a limited time". Thanks Microsoft but after reading all the reports on how it spies on users and sends data back to The Deathstar Microsoft, my next change of OS will be to Linux.

Link to comment
Share on other sites

I am about ready to release fbForth 2.0:5. So far, the additions to fbForth 2.0:4 in fbForth 2.0:5 are

  • Moved (ABORT) out of ROM space to low RAM to allow setting it to execute a user's error procedure when WARNING is set to -1.
  • Modified ERROR to not leave the contents of IN and BLK on the stack if the input stream is coming from the terminal. This function of ERROR is only useful for block loads so that WHERE can be used to jump into the editor at the error. Otherwise, they are irritating detritus, only serving to confuse the user.
  • Added a table of default colors in low RAM for all VDP modes that is user-modifiable and that persists through a warm boot with COLD .
  • Added to the above table a user-modifiable cell for the default text mode. This also persists after COLD .
  • Added DCT , a constant that leaves the address of the Default Colors Table (listed above). It is through this constant that the user will be able to change the default values in the above table. I will explain how to do this when I release fbForth 2.0:5.

It all seems to be working alright. I think I will post it later today, unless someone has found another bug in fbForth 2.0:4.

 

...lee

Link to comment
Share on other sites

Here is the promised explanation of the default color table—

 

The constant DCT leaves on the stack the address of the first value in the table below:

 

Offset Value Mode
------ ----- ---------
   0   4F00h TEXT80
   2   4F00h TEXT
   4   F4F4h GRAPHICS
   6   11F4h MULTI
   8   FE10h GRAPHICS2
  10   FEF4h SPLIT
  12   FEF4h SPLIT2
  14   0001h Default

 

Except for the value at offset = 14, the high byte (MSB) of each 16-bit value is the FG (high nybble, MSN) and BG (low nybble, LSN) colors for the mode listed in the rightmost column. That byte is the value that gets stored in VR07 (VDP Register #7) when its associated mode is invoked. The MSN only really matters for the two text modes.

 

The LSB, which does not apply to the two text modes, is used for the FG/BG colors of the respective Color Tables. In the SPLIT and SPLIT2 modes, the LSB is used for the Color Table of the the text part of those modes.

 

Last, but not least, the value at offset 14 is the default VDP mode. It was intended to contain only 0 ( TEXT80 ) or 1 ( TEXT ); but, any VDP mode can be put there. COLD is the only word that enforces this default mode.

 

To change any of these defaults, get the table address with DCT , add the offset to the value you want to change and store the new value. It will persist through even a warm boot with COLD . Here are a few examples:

 

HEX F400 DCT 2+ !      <--change default TEXT colors to white on dark blue

HEX F4 DCT 2+ C!       <--same, but store just one byte

HEX 13 DCT 0B + C!     <--change FG/BG of default text part of SPLIT to black on light green

DECIMAL 0 DCT 14 + !   <--change default VDP mode to TEXT80

 

...lee

 

 

 

 

 

Link to comment
Share on other sites

  • 2 weeks later...

I have finally succeeded in porting TurboForth's ASM>CODE to fbForth. You can now copy to DV80 files (including the Windows clipboard, CLIP, if using Classic99) your ALC words assembled with the fbForth TMS9900 Assembler, just as you can do in TurboForth. Here is the code, which will eventually find its way into FBLOCKS after more fiddling to allow the emitted code to be loadable in fbForth**:

 

 

 

( ASM>CODE [port of Mark Wills' code] LES20DEC2015)
BASE @ ( current base to stack) HEX
: VALUE ( n -- ) ( value IS:name ) CONSTANT ;
: TO ( n -- ) ( value IS:name )
-FIND IF
DROP
STATE @ IF
COMPILE LIT ,
COMPILE !
ELSE
!
THEN
ELSE
0 ERROR
THEN ; IMMEDIATE
: +TO ( n -- ) ( value IS:name )
-FIND IF
DROP
STATE @ IF
COMPILE LIT ,
COMPILE +!
ELSE
+!
THEN
ELSE
0 ERROR
THEN ; IMMEDIATE
0 VALUE pfa ( PFA of word definition)
0 VALUE STRPOS ( output string cell-positioin counter)
0 VARIABLE FBUF 4E ALLOT ( RAM file buffer of 80 bytes)
PABS @ ( VRAM location for PAB-ADDR)
FBUF ( RAM location of PAB-BUF)
1200 ( VRAM location of PAB-VBUF)
FILE FileOut ( set up file ID for output file)
FileOut ( make FileOut current)
SET-PAB ( initialize PAB)
: ClearBUF
FBUF 50 BLANKS ; ( 80 blanks starting at FBUF)
: SetFileName ( IS:fileName )
BL WORD ( parse fileName to HERE)
HERE ( fileName packed string [FNPS] RAM src)
PAB-ADDR @ 9 + ( FNPS VRAM dst)
OVER C@ 1+ ( char count, including char-count byte)
VMBW ; ( copy FNPS to PAB)
: ApdERR ( 0 msg# -- flag ) ( append-open error procedure)
DROP ( drop msg# passed to ERROR through ?ERROR by ?ERROR's caller)
PAB-ADDR @ 1+ VSBR ( get PAB flag/status byte)
0E0 AND ( pick off error bits)
OR ( OR with passed 0 flag)
R> R> DROP >R ; ( return to ?ERROR instead of ERROR)
: instApdERR ( install append-open-mode error proc)
' ApdERR CFA ' (ABORT) !
-1 WARNING ! ; ( force ERROR to call our error proc)
: uninstApdERR ( restore system error proc)
' ABORT CFA ' (ABORT) !
1 WARNING ! ;
: OpenFile ( -- )
FileOut ( ensure FileOut is current)
DSPLY ( display-type file)
VRBL ( variable-length records)
50 REC-LEN ( 80-byte records)
instApdERR ( install append error proc)
0 ( flag=0 assumes append-mode success)
APPND OPN ( try to open in append mode as DV80)
uninstApdERR ( restore normal system error proc)
IF ( opening in append mode failed?)
OUTPT OPN ( try to open file in output mode as DV80)
THEN ;
: Asm?
pfa pfa CFA @ = ; ( does CFA point to PFA?)
: copyStr ( addr count -- )
STRPOS 5 * ( next relative output position)
FBUF + ( make it an address)
SWAP CMOVE ; ( copy next substring to FBUF)
: SetName
ClearBUF ( clear output buffer with blanks)
S" CODE " COUNT copyStr ( copy "CODE: " to FBUF)
pfa NFA ( get word's NFA)
DUP C@ 01F AND ( dup it and mask off all but name length)
SWAP 1+ SWAP ( increment NFA to point to first char of name)
FBUF 6 + ( increment output-string pointer past "CODE: ")
SWAP 0 DO ( namelength 0 DO; stack:NFA+1 FBUF+7)
OVER C@ ( get next char of word name)
07F AND ( mask off possible terminator bit)
OVER C! ( copy to output string)
1+ SWAP 1+ SWAP ( increment both addresses to next byte)
LOOP
DROP DROP ; ( drop leftover addresses)
: FlushLine
40 WRT ( write 64 bytes to next record, including trailing blanks)
ClearBUF ( clear output buffer)
0 TO STRPOS ; ( reset string cell-position counter)
: PlaceCell
pfa @ 0 <# # # # # #> ( next cell to string; leave addr, count)
copyStr ( copy next-cell string to output string)
1 +TO STRPOS ( increment string pos)
2 +TO pfa ; ( increment definition address 1 cell)
: &;
S" NEXT," COUNT ( set up code terminator; leave addr, count)
copyStr ; ( copy code terminator to output string)
: ProcessWord
SetName ( set up output string with "CODE: <name>")
FlushLine ( write it to output file)
BASE->R ( save current BASE)
10 BASE ! ( set BASE to hex)
BEGIN ( process word's definition)
pfa @ ( get next cell of definition)
045F = 0= WHILE ( stop if we've reached the end of definition)
PlaceCell ( next cell text to output string)
STRPOS 0C = IF ( line full?)
FlushLine ( flush line to output file)
THEN
REPEAT
&; ( copy code terminator to output string)
FlushLine ( flush line to output file)
R->BASE ; ( restore BASE)
: ASM>CODE ( IS:wordName fileName)
CR
-FIND IF ( look up word; word exists?)
DROP ( yes; drop namelength leaving PFA)
ELSE
0 ( no such word; leave PFA=0)
THEN
TO pfa ( store PFA)
SetFileName ( get fileName from IS and put in PAB)
pfa IF ( do we have a valid PFA)
Asm? IF ( is this word really defined in ALC)
OpenFile
ProcessWord ( get word definition to file)
CLSE ( close output file)
ELSE
." Not an assembly language word"
THEN
ELSE
." Word not found"
THEN ;
BASE !

 

 

 

The snag that took me awhile to get around was the fact that the creation of an empty file in append mode will throw an error that exits the program. I had to install a temporary error procedure just for opening in append mode so I could trap the error, restore the system error proc and open the file in output mode. Except for the temporary error trap, this is how @Willsy did it in TurboForth. Maybe in some future release I will provide the user with a way to modify error handling of file I/O with a flag as an alternative to the default system of issuing an error message and aborting.

 

Usage is the same as in TurboForth:

 

ASM>CODE <word> <filename>

 

Example:

 

ASM>CODE MYWORD DSK1.ASMWORDS

 

An existing output file is always opened in append mode, so using the same output file for several words will result in a single file with several words in CODE ... NEXT, machine-code format. If you use Classic99's CLIP file, you should first clear the Windows clipboard by copying something like an empty line or a comment line to it. Otherwise, you could be surprised with a sizable preamble to your ALC words.

 

...lee

 

** All hex-code numbers within fbForth CODE ... NEXT, words must each be followed by , to compile the number into the definition. I cannot change this behavior for CODE ... NEXT, because I must maintain compatibility with TI Forth. What I may do in the future is to define a different pair of words ( MCODE: , ;MCODE , perhaps) to effect the same procedure as TurboForth in this regard, which will require that I also modify INTERPRET . This may not be possible unless I can make room in the already stuffed-to-the-gills ROM.

 

[EDIT: Corrected definition of Asm? in code in above spoiler]

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...