[comp.sys.atari.8bit] ACTION COMPILE TO DISK

curzon@kaoa01.dec.com (01/21/87)

    Action language hackers:  many people probably already have this compile to
disk program.  This is one of the Action modules by Clint Parker made available
by him thru his BBS and the OSS BBS (not public domain, but may be used in
"not-for-profit" ways).  Some of them have appeared here, but I don't think 
this one has.  (thanks to BL for this)

    It's really Exhibit A to my problem: 
    "Why do I run out of memory when I compile a large program to disk?" 
     (error 14 - I think).  I trust it doesn't compile to RAM at the same
       time... else what's the point! & how can I fix it to direct output
       ONLY to disk?   This stuff is a bit too tricky for me...

MODULE ; CMPTODSK.ACT 

; Copyright (c) 1983
; by Action Computer Services
; All Rights Reserved

; version 1.0
; last modified October 22, 1984

; Compile to disk for ACTION! 
; compiler.  Note that all ARRAY
; declarations that generate storage
; must be before the first procedure
; declaration or else the address of
; the storage will not be setup
; correctly (all dimensioned ARRAYs
; which are not assigned an initial
; value except BYTE/CHAR arrays of
; size 256 or less).  Local ARRAY
; declarations in the main PROC (last
; procedure in program) are also
; allowed.  Note:  there must be at 
; least one PROC/FUNC in program.

; Output file name will be same name
; as program being compiled with
; extention .OBJ

; IF AN ERROR OCCURS DURING
; COMPILATION, YOU SHOULD USE
; "/" to close all open files:
;      >/

; change dev in SPLEnd below to direct
; output to printer.

DEFINE STRING = "CHAR ARRAY"
DEFINE JMP = "$4C" ; JMP addr16

TYPE INSTR=[BYTE op CARD addr]
INSTR Segvec=$4C6
INSTR SPLvec=$4DD
INSTR MonCmd=$4FB
INSTR OldMon

BYTE oldDevice, curBank=$4C9
BYTE pf, Zop=$8A, tZop, dev
CARD curproc=$8E, code=$E
CARD codeBase=$491, codeSize=$493
CARD codeOff=$B5
CARD globals, gsize
CARD totalSize, codeStart
CHAR ARRAY cmdLine(0)=$590
BYTE ARRAY bank(0)=$D500
BYTE ARRAY zpage(32), temps(16)


PROC InitMon()
; add "/" command to monitor which
; closes channels 1-5 and warm
; starts cartridge.

  CHAR cmdchar=$591
  BYTE i, WARMST=$8
  DEFINE JMPI="$6C"

; make sure right command
  IF cmdchar{##}'/ THEN [JMP OldMon] FI

  bank(0) = 0 ; init library routines
  FOR i = 1 TO 5 DO
    Close(i)
  OD

  WARMST = 1
[JMPI $BFFA] ; warm start cart.


INCLUDE "BLKIO.ACT"


PROC Save()
; save state of variables used by
; both compiler and library routines

  bank(0) = 0 ; init library routines
  tZop = Zop
  MoveBlock(zpage, $B0, $1B) ; to $CA
  MoveBlock(temps, $5F0, 16)
RETURN


PROC Restore()
; restore state of variables used by
; both compiler and library routines
  CARD tcodeOff

  Zop = tZop
  tcodeOff = codeOff
  MoveBlock($B0, zpage, $1B) ; to $CA
  MoveBlock($5F0, temps, 16)
  codeOff = tcodeOff

  bank(curBank) = 0
RETURN


PROC WriteHdr()
  PutCD(5, $FFFF)
  PutCD(5, codeStart)
  PutCD(5, codeStart+totalSize-1)
  WriteBlock(5, globals, gsize)
RETURN


PROC WriteCode()
  codeSize = code - codeBase
  PrintD(dev, curproc)
  PrintD(dev, ": ")
  PrintCDE(dev, codeSize)
  totalSize = totalSize + codeSize
  WriteBlock(5, codeBase, codeSize)
  code = codeBase
  codeOff = codeOff + codeSize
RETURN


PROC SegEnd()
  Save()
  IF pf THEN ; print locals
    WriteCode()
  ELSE
    pf = 1
    globals = codeBase
    gsize = code - codeBase
    codeBase = code
    totalSize = gsize
    codeStart = globals + codeOff
    WriteHdr()
  FI
  Restore()
RETURN


PROC SPL() ; dummy proc for call below


PROC SPLEnd()
  CHAR c
  BYTE nxttoken=$D3, i, n, buf=$9B^
  CARD nxtaddr=$C9, start=$2E2
  STRING inbuf(0)=$5C8, name
  STRING out(17)

  DEFINE PLA = "$68",
         STA = "$8D"

  Save()

  dev = 0
; to get output to printer:
; dev = 4
; Close(4)  Open(4, "P:", 8, 0)

; get output name
  IF nxttoken=30 THEN ; command line
    name = nxtaddr
  ELSE ; editor buffer
    name = inbuf
  FI

; see if device needed
  n = 0
  IF name(2){##}': AND name(3){##}': THEN
    out(1) = 'D   out(2) = ':  n = 2
  FI

; get name without extension
  FOR i = 1 TO name(0) DO
    c = name(i)
    IF c='. THEN EXIT FI
    IF c>'Z THEN c = c {#&} $5F FI
    out(i+n) = c   
  OD

; add extension
  out(i+n) = '.
  out(i+n+1) = 'O
  out(i+n+2) = 'B
  out(i+n+3) = 'J
  out(0) = i + n + 3

  PutE()
  Print("output file is ")
  PrintE(out)
  PutE()

  Close(5)  Open(5, out, 8, 0)
  buf = 0 ; clear buf used by Open

  pf = 0 ; no proc decl yet

; JSR for return so that we come
; back here after compilation
  [   
    PLA
    STA SPL+1
    PLA
    STA SPL+2
  ]
  SPL = SPL + 1 ; get right address
  Restore()

  SPL()

  Save()

; ignore space for arrays
  code = codeBase + codeSize

  WriteCode()
  PutCD(5, $2E2)
  PutCD(5, $2E3)
  PutCD(5, start)
  Close(5)

  Open(5, out, $C, 0)
  WriteHdr()
  Close(5)

  PutDE(dev)
  PrintCD(dev, totalSize)
  PrintDE(dev, " bytes of code")

  Restore()
  codeOff = 0
RETURN


; only code generated before Init is
; allocated space.  Init will be
; garbage collected (well kind of).

PROC Init()
  CARD codeBlock, bsize, csize, nBlock
  CARD POINTER cur, next

; link in our routines
  Segvec.op = JMP
  Segvec.addr = SegEnd
  SPLvec.op = JMP
  SPLvec.addr = SPLEnd
  OldMon.op = MonCmd.op
  OldMon.addr = MonCmd.addr
  MonCmd.op = JMP
  MonCmd.addr = InitMon

; allocate our routine so it won't
; go away.
  codeBlock = codeBase - 4
  next = $80 ; AFbase
  DO
    cur = next
    next = next^
  UNTIL next=0 OR next=codeBlock OD

  IF next=0 THEN
    PutE()   Put($FD)
    PrintE("I can't allocate space for your code")
    PrintE("You better Boot and try again!")
    RETURN
  FI

; assume we can split block
  csize = @codeBlock-codeBlock
  nBlock = next^
  bsize = next(1) - csize
  next = @codeBlock
  cur^ = next
  next^ = nBlock
  next(1) = bsize
  codeBase = next + 4
RETURN
;----------------end-of-cmptodsk.act--------------------------


				Dick Curzon
				Digital Equipment of Canada
                                PO Box 13000
                                Kanata Ontario      K2K 2A6
                                Canada.

(DEC E-NET)	KAOA01::CURZON
(UUCP)		{decvax, ucbvax, allegra}!decwrl!kaoa01.dec.com!curzon
(ARPA)		curzon%kaoa01.DEC@decwrl.ARPA