2. Write Image Format File

#SILENCE

# wiff.int - Write (interp) Image Format File
#
# This script writes out any global function definitions it finds,
# then it writes out any local function definitions it finds,
# then it writes out the End-of-Data record.
#
# I tested it this way:
#   cd <interp-build-directory>
#   ./interp -N -f DOC/SAMPLE_SCRIPTS/kdump.int -f DOC/SAMPLE_SCRIPTS/argtest.int -f wiff.int "FA FK" >test.iif
#   od -Ax -t x1 -c test.iif
#
# This script needs a data stack depth of at least 8.
# No functions are defined by this script.
# No global or local variables are used by this script.
#
# Known Bugs:
# If you run this and there are no function definitions,
# the resulting IIF file will be illegal because it will
# only have an End-of-Data Record.

#define GFTstart=19K@
#define LFTstart=20K@
#define ARGC=24K
#define ARGV=25K
#define OPTIND=26K@
#define GFR=0xA1
#define LFR=0xB1
#define EODR=0xA0


  __ WRITElength ( length -- ) write the 4-byte length, LSB first
#define WRITElength=dup 0xFF&, 8>> dup 0xFF&, 8>> dup 0xFF&, 8>> 0xFF&,


  __ WRITEbody ( start-address -- ) write the function body including the EOS
  __  dup "!A"        __ write the function body including the EOS
  __  loop
  __    "@c"          __ write each character
  __    dup b@ while  __ quit the loop after writing the EOS
  __    1+            __ otherwise increment the function body pointer
  __  endloop
  __  drop            __ drop the function body pointer
#define WRITEbody=dup "!A" loop "@c" dup b@ while 1+ endloop drop


  __ STRlength ( start-address -- length ) counts the bytes in the string
  __    including the end-of-string character ('\0'.)
  __  0               __ placeholder for the calculated length
  __  loop            __ calculate the length of the function body
  __    2dup + b@     __ use the length as the index and get the next character
  __    swap 1+ swap  __ increment the length (it includes the end-of-string)
  __    while         __ exit the loop when the character is the end-of-string
  __  endloop
  __  swap drop       __ drop the start address of the function definition
#define STRlength=0 loop 2dup + b@ swap 1+ swap while endloop swap drop


  __ write out all global function definitions.
#BUFFER
255 0 loop          __ look at all 256 entries in the global function table
2dup swap <= while  __ each entry is a 4-byte function body pointer
  GFTstart over 2<< + __ calculate address of next 4-byte table entry
  @ dup             __ get the function body pointer, and save a copy
  if                __ if it is not NULL (0), output a Global Function Record
    GFR,            __ start the Global Function Record
    dup             __ replace the copy of the function body pointer
    STRlength       __ calculate the length of the function body
    1+              __ include the length of the function name
    WRITElength     __ write the 4-byte length, LSB first
    over,           __ the table index is also the function name, write it
    WRITEbody       __ write the function body including the EOS
  else              __ otherwise, drop the entry (points to the function body)
    drop
  endif
  1+                __ increment the global function table index
endloop
2drop               __ drop the index and the max-index-value
#EXECUTE

  __ write out all local function definitions
#BUFFER
255 0 loop          __ look at all 256 entries in the local function table
2dup swap <= while  __ each entry is a 4-byte function body pointer
  LFTstart over 2<< + __ calculate address of next 4-byte table entry
  @ dup             __ get the function body pointer, and save a copy
  if                __ if it is not NULL (0), output a Local Function Record
    LFR,            __ start the Global Function Record
    dup             __ replace the copy of the function body pointer
    STRlength       __ calculate the length of the function body
    1+              __ include the length of the function name
    WRITElength     __ write the 4-byte length, LSB first
    over,           __ the table index is also the function name, write it
    WRITEbody       __ write the function body including the EOS
  else              __ otherwise, drop the entry (points to the function body)
    drop
  endif
  1+                __ increment the local function table index
endloop
2drop               __ drop the index and the max-index-value
#EXECUTE

  __ write the End-of-Data record, with an optional auto-start string
#BUFFER
EODR,               __ start the End-of-Data Record
OPTIND ARGC < if    __ if a script argument is present, write with auto-start
  ARGV OPTIND 2<< + __ calculate the address of the script argument pointer
  @                 __ get the pointer to the startup script
  dup               __ make a copy of it
  STRlength         __ calculate the length of the startup script
  WRITElength       __ write the 4-byte length, LSB first
  WRITEbody         __ write the startup script including the EOS
else
  0,0,0,0,          __ because there were no arguments left, no auto-start
endif
#EXECUTE

#PROMPT