\ @(#) savedicd.fth 98/01/26 1.2
\ Save dictionary as data table.
\
\ Author: Phil Burk
\ Copyright 1987 Phil Burk
\ All Rights Reserved.
\
\ 970311 PLB Fixed problem with calling SDAD when in HEX mode.

decimal
ANEW TASK-SAVE_DIC_AS_DATA

\ !!! set to 4 for minimally sized dictionary to prevent DIAB
\ compiler from crashing!  Allocate more space in pForth.
4 constant SDAD_NAMES_EXTRA   \ space for additional names
4 constant SDAD_CODE_EXTRA    \ space for additional names

\ buffer the file I/O for better performance
256 constant SDAD_BUFFER_SIZE
create SDAD-BUFFER SDAD_BUFFER_SIZE allot
variable SDAD-BUFFER-INDEX
variable SDAD-BUFFER-FID
		0 SDAD-BUFFER-FID !

: SDAD.FLUSH  ( -- ior )
	sdad-buffer sdad-buffer-index @  \ data
\ 2dup type
	sdad-buffer-fid @  write-file
	0 sdad-buffer-index !
;

: SDAD.EMIT  ( char -- )
    sdad-buffer-index @  sdad_buffer_size >=
    IF
    	sdad.flush abort" SDAD.FLUSH failed!"
    THEN
\
    sdad-buffer sdad-buffer-index @ + c!
    1 sdad-buffer-index +!
;

: SDAD.TYPE  ( c-addr cnt -- )
	0 DO
		dup c@ sdad.emit    \ char to buffer
		1+   \ advance char pointer
	LOOP
	drop
;

: $SDAD.LINE  ( $addr -- )
	count sdad.type
	EOL sdad.emit
;

: (U8.)  ( u -- a l , unsigned conversion, at least 8 digits )
	0 <#  # # # #  # # # #S #>
;
: (U2.)  ( u -- a l , unsigned conversion, at least 2 digits )
	0 <#  # #S #>
;

: SDAD.CLOSE ( -- )
	SDAD-BUFFER-FID @ ?dup
	IF
		sdad.flush abort" SDAD.FLUSH failed!"
		close-file drop
		0 SDAD-BUFFER-FID !
	THEN
;

: SDAD.OPEN  ( -- ior, open file )
	sdad.close
	s" pfdicdat.h" r/w create-file dup >r
	IF
		drop ." Could not create file pfdicdat.h" cr
	ELSE
		SDAD-BUFFER-FID !
	THEN
	r>
;

: SDAD.DUMP.HEX  { val -- }
	base @ >r hex
	s" 0x" sdad.type
	val (u8.) sdad.type
	r> base !
;
: SDAD.DUMP.HEX, 
	s"    " sdad.type
	sdad.dump.hex
	ascii , sdad.emit
;

: SDAD.DUMP.HEX.BYTE  { val -- }
	base @ >r hex
	s" 0x" sdad.type
	val (u2.) sdad.type
	r> base !
;
: SDAD.DUMP.HEX.BYTE,
	sdad.dump.hex.byte
	ascii , sdad.emit
;

: SDAD.DUMP.DATA { start-address end-address num-zeros | num-bytes -- }
	end-address start-address - -> num-bytes
	num-bytes 0
	?DO
		i $ 7FF and 0= IF ." 0x" i .hex cr THEN   \ progress report
		i 15 and 0=
		IF
			 
			 EOL sdad.emit
			 s" /* " sdad.type
			 i sdad.dump.hex
			 s" : */ " sdad.type
		THEN   \ 16 bytes per line, print offset
		start-address   i + c@
		sdad.dump.hex.byte,
	LOOP
\
	num-zeros 0
	?DO
		i $ 7FF and 0= IF i . cr THEN   \ progress report
		i 15 and 0= IF EOL sdad.emit THEN   \ 15 numbers per line
		0 sdad.dump.hex.byte,
	LOOP
;

: SDAD.DEFINE  { $name val -- }
	s" #define " sdad.type
	$name  count sdad.type
	s"   (" sdad.type
	val sdad.dump.hex
	c" )" $sdad.line
;

: IS.LITTLE.ENDIAN?  ( -- flag , is Forth in Little Endian mode? )
	1 pad !
	pad c@
;
	
: SDAD   { | fid -- }
	sdad.open abort" sdad.open failed!"
\ Write headers.
	c" /* This file generated by the Forth command SAVE-DIC-AS-DATA */" $sdad.line

	c" HEADERPTR" headers-ptr @ namebase - sdad.define
	c" RELCONTEXT" context @ namebase - sdad.define
	c" CODEPTR" here codebase - sdad.define
	c" IF_LITTLE_ENDIAN" IS.LITTLE.ENDIAN? IF 1 ELSE 0 THEN sdad.define
	
." Saving Names" cr
	s" static const uint8 MinDicNames[] = {" sdad.type
	namebase headers-ptr @ SDAD_NAMES_EXTRA sdad.dump.data
	EOL sdad.emit
	c" };" $sdad.line
	
." Saving Code" cr
	s" static const uint8 MinDicCode[] = {" sdad.type
	codebase here SDAD_CODE_EXTRA sdad.dump.data
	EOL sdad.emit
	c" };" $sdad.line

	sdad.close
;

if.forgotten sdad.close

." Enter: SDAD" cr
