*************************************************************************
*              WBInit.asm---FORTRAN Compiler Startup Code               *
*                    Substantially based upon                           *
*                                the                                    *
*               ABSOFT CORPORATION FORTRAN 77 COMPILER                  *
*                                                                       *
*                       MAIN PROGRAM START UP CODE                      *
*                               FOR                                     *
*                       AMIGADOS BASED SYSTEMS                          *
*                                                                       *
*                       Copyright (C) 1986,1987                         *
*               Absoft Corporation, Royal Oak, MI  48072                *
*                                                                       *
*                                                                       *
*       This code segment is the main program start up procedure, with  *
*       workbench support.   It must be linked using Alink or Blink to  *
*       amiga.lib.                                                      *
*                                                                       *
*       The resulting linker output file must be named "init.sc".       *
*                                                                       *
*       The file is also used in source form as an INCLUDE file when    *
*       assembly language source is being generated by the compiler     *
*       for a main program.                                             *
*                                                                       *
*       The routine performs the following functions:                   *
*                                                                       *
*               1. Test for workbench vs CLI startup                    *
*               2. If workbench, handle all necessary environment issues*
*               3. allocate a memory segment for the heap               *
*               4. open "dos.library"                                   *
*               5. locate the STDIN and STDOUT file handles             *
*               6. load f77.rl into the heap                            *
*                                                                       *
*       The routine passes the following registers to f77.rl:           *
*                                                                       *
*               D2 - run-time library specification:                    *
*                    0 = f77.rl                                         *
*                    1 = hdw.rl (not available for Amiga)               *
*                    2 = m81.rl                                         *
*               D5 - command line length                                *
*               A0 - pointer to heap                                    *
*               A2 - pointer to main program                            *
*               A3 - command line pointer                               *
*               A4 - debug or profil command line pointer               *
*               A5 - pointer to f77.rl                                  *
*                                                                       *
*                                                                       *
*************************************************************************
*
* Edit history:
*
*  19 Feb 86    file created                                            PAJ
*  02 Jun 87    converted to V2.3                                       CAG
*  06 Mar 89    WorkBench support provided         Jim Locker
*

*
* - Selected AmigaDOS equates:
*
   INCLUDE "exec/types.i"
   INCLUDE "exec/alerts.i"
   INCLUDE "exec/nodes.i"
   INCLUDE "exec/lists.i"
   INCLUDE "exec/ports.i"
   INCLUDE "exec/libraries.i"
   INCLUDE "exec/tasks.i"
   INCLUDE "libraries/dos.i"
   INCLUDE "libraries/dosextens.i"
   INCLUDE "workbench/startup.i"

* - from "depsys"

AEXEC   EQU     -16                     * "exec_lib" pointer
DOS     EQU     AEXEC-4                 * "dos.library" pointer
STDIN   EQU     DOS-4                   * file handle for STDIN
STDOUT  EQU     STDIN-4                 * file handle for STDOUT
H.BASE  EQU     STDOUT-4                * base of heap
H.SIZE  EQU     H.BASE-4                * size of heap
WBSTAT  EQU     H.SIZE-2                * running from workbench?
WBMSG   EQU     WBSTAT-4                * loc of WB message
OURTSK  EQU     WBMSG-4                 * loc of our TCB
AMIGA   EQU     -OURTSK                 * size of Amiga global storage

F77.RL  EQU     17408                   * size of "f77.rl"
PCB     EQU     3348
NO_OP   EQU     $4E71                   * hex of NOP instruction

* - from "exec_lib"

_LVOAlert         EQU     -108
_LVOForbid        EQU     -132
_LVOAllocMem      EQU     -198
_LVOFreeMem       EQU     -210
_LVOFindTask      EQU     -294
_LVOWait          EQU     -318
_LVOGetMsg        EQU     -372
_LVOReplyMsg      EQU     -378
_LVOWaitPort      EQU     -384
_LVOOpenLibrary   EQU     -552
_LVODebug         EQU     -114

EXEC.LIB          EQU     4               * pointer to "exec_lib"

* - from "dos.library"

_LVOOpen          EQU     -30
_LVOClose         EQU     -36
_LVORead          EQU     -42
_LVOWrite         EQU     -48
_LVOInput         EQU     -54
_LVOOutput        EQU     -60
_LVOCurrentDir    EQU     -126
_LVOExit          EQU     -144
_LVODelay         EQU     -198

*
* - the following code is already in the source file:
*
*START: LEA     START(PC),A1            * load address of entry point
*       MOVEA.L A1,A2
*       ADDA.L  #OFFSET,A1              * pointer to main program
*       ADDA.L  #OFFSET,A2              * pointer to end of data section
*       MOVE.L  #HEAP,D1                * heap size
*       MOVE.L  #RUN,D2                 * run-time library specification
*
        CLR.W   _WBStat
        CLR.L   _WBenchMsg
        JMP     S1(PC)
        NOP
        NOP
S1:
        MOVE.L  D2,-(A7)
        MOVE.L  A0,_DosCmdBuf           * copy command line pointer
        MOVE.L  A4,-(A7)                * stow original A4 safely away
        MOVE.L  D0,_DosCmdLen           * copy command line length
        MOVEA.L A1,A2                   * copy for global use
        SUBA.L  A1,A1                   * find our own task
        JMP     S2(PC)
        NOP
        NOP
S2:
        MOVE.W  #_LVOFindTask,D6
        BSR     ECALL
        MOVE.L  D0,A4
        tst.l   pr_CLI(A4)
        bne     from_Cli
*
* - open the "dos.library" and locate STDIN and STDOUT
*
fromWB:
        move.w  #111,_WBStat
        MOVEM.L D2/A2,-(A7)
        MOVE.L  #1,_DosCmdLen           * make the run time library happy
        BSR     DOSOPEN
        lea     pr_MsgPort(A4),A0       * our process base
        move.w  #_LVOWaitPort,D6
        BSR     ECALL                   * wait for wbench message
        JMP     S3(PC)
LINKED:
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
S3:
        lea     pr_MsgPort(A4),A0
        move.w  #_LVOGetMsg,D6          * get the message
        BSR     ECALL
        move.l  d0,_WBenchMsg           * save it so we can return it
        move.l  D0,A2                   * get the first argument
        Move.l  sm_ArgList(A2),D0
        beq.s   docons

* - set the current directory to the same directory
        move.l  D0,A0
        move.l  wa_Lock(A0),d1
        move.w  #_LVOCurrentDir,D6
        BSR     DCALL

docons:
*
* - get the toolwindow argument
*
        move.l  sm_ToolWindow(A2),d1       * is there a default window?
        bne.s   opnwndo                    * yes
        lea     NIL(PC),A3                 * no default, so open NIL:
        move.l  A3,D1
        BSR     FILOPEN
        bra.s   filhandl
*
* - open up the file
*
opnwndo:
        BSR     FILOPEN
*
* - set the i/o descriptors
*
filhandl:
        move.l  d0,_stdin
        move.l  d0,_stdout
        beq.s   domain
*
* - set the console task (so Open("*",mode) will work)
*   waitmsg has left the task pointer in A4 for us
*
        lsl.l   #2,d0
        move.l  d0,a0
        move.l  fh_Type(a0),pr_ConsoleTask(A4)
domain:
        MOVEM.L (A7)+,D2/A2
*        MOVE.L  _startkeep,A2
*
* - allocate the heap segment and establish global addresses
*
from_Cli:
        MOVEA.L _DosCmdBuf,A3
        MOVE.L  _DosCmdLen,D5
        MOVE.L  #AMIGA+PCB,D0           * module size
        MOVE.L  #NO_OP,D7               * find out if run time lib is linked  
        CMP.W   LINKED+4,D7
        BNE     S4
        ADD.L   #F77.RL,D0              * if not, need space for it.
S4:
        MOVEQ   #0,D1                   * MEMF_FAST first, then MEMF_CHIP
        MOVE.W  #_LVOAllocMem,D6
        MOVE.L  D0,D4                   * save allocated size
        BSR     ECALL
        TST.L   D0                      * did the allocation succeed?
        BEQ     ERROR                   *   no
        MOVEA.L D0,A0                   * set pointer to base of heap
        MOVE.L  A0,D3                   * save pointer for "f77.rl" load
        MOVE.L  #NO_OP,D7               * find out if run time lib is linked  
        CMP.W   LINKED+4,D7
        BNE     S5
        ADDA.L  #F77.RL,A0              * if not, allocate "f77.rl" area
S5:
        ADDA.L  #AMIGA,A0               * allocate global area
        MOVE.L  D0,H.BASE(A0)           * save base of heap for .FREEMEM.
        MOVE.L  D4,H.SIZE(A0)           * save size of heap for .FREEMEM.
        MOVE.L  EXEC.LIB,AEXEC(A0)      * set pointer to "exec_lib"
        MOVE.L  _stdin,STDIN(A0)        * pick up stdin and stdout from WB
        MOVE.L  _stdout,STDOUT(A0)
        MOVE.L  _DOSBase,DOS(A0)
        MOVE.L  _WBenchMsg,WBMSG(A0)
        MOVE.W  _WBStat,WBSTAT(A0)
        MOVE.L  A4,OURTSK(A0)
        MOVEA.L (A7)+,A4                *restore original A4
*
* - open the "dos.library" and locate STDIN and STDOUT
*
        TST.W   _WBStat                 * running from workbench?
        BNE.S   BYPASS                  * yes..DOS already open
        BSR     DOSOPEN                 * open DOS
        MOVE.L  D0,DOS(A0)              * save pointer, error?
        BNE.S   L1                      *   did open succeed?
ERROR:  RTS                             *   no, fail silently (UNIX style)

L1:     MOVEQ   #_LVOInput,D6
        BSR     DCALL
        MOVE.L  D0,STDIN(A0)
        MOVEQ   #_LVOOutput,D6
        BSR     DCALL
        MOVE.L  D0,STDOUT(A0)
BYPASS:
*
* Now find out if the run time library is linked in.  We do this by testing
* the location that is 4 bytes past the LINKED label.  If it contains the 
* instruction NOP, which is what we put there, then the linker has not linked
* in the run time library.  If the value is different, then the linker has
* stepped on us, with the following code:
*
*       LEA     START(PC),A5
*       ADDA.L  #OFFSET,A5
*       JMP     (A5)
*
* In this case we branch to LINKED and execute the code we find there.  
* Otherwise, we just fall through and find the run time library.
*
        MOVE.L  #NO_OP,D7        
        CMP.W   LINKED+4,D7
        BEQ     FNDLIB
        MOVE.L  (A7)+,D2
        BRA     LINKED
*
* - locate and load "f77.rl"
*
FNDLIB: 
        LEA     F77LIB+6(PC),A6
        MOVE.L  D2,D0                   * load run-time library specifier
        LSL.L   #4,D0                   * calculate table offset
        ADDA.W  D0,A6                   * index specified library
        MOVE.L  A6,D1                   * "name"
        move.l  #MODE_OLDFILE,D2
        move.w  #_LVOOpen,D6
        BSR     DCALL
        MOVE.L  D0,D7                   * found in local library?
        BNE.S   L2                      *   yes
        SUBQ.L  #3,D1
        BSR     DCALL
        MOVE.L  D0,D7                   * found in current volume library?
        BNE.S   L2                      *   yes
        SUBQ.L  #3,D1
        BSR     DCALL
        MOVE.L  D0,D7                   * found in system volume library?
        BEQ.S   L3                      *   no
L2:     MOVEA.L D3,A5                   * set pointer to "f77.rl"
        MOVE.L  D7,D1                   * "file"
        MOVE.L  A5,D2                   * "buffer"
        MOVE.L  #F77.RL,D3              * "length"
        MOVEQ   #_LVORead,D6
        BSR     DCALL                    * load the library
        TST.L   D0                      * error?
        BMI.S   L3                      *   yes
        MOVE.L  D7,D1                   * "file"
        MOVEQ   #_LVOClose,D6
        BSR     DCALL                   * close the file
        MOVE.L  (A7)+,D2                * run-time library specification
        JMP     (A5)                    * transfer control to "f77.rl"

*
* - "f77.rl" load failed: report error and quit
*

L3:     MOVE.L  STDOUT(A0),D1           * "file"
        LEA     ERRMSG(PC),A6
        MOVE.L  A6,D2                   * "buffer"
        MOVEQ   #30,D3                  * "length"
        MOVEQ   #_LVOWrite,D6
        BSR.S   DCALL
        MOVE.L  DOS(A0),-(A7)           * save pointer to "dos.library"
        BSR.S   DCALL
        MOVEA.L H.BASE(A0),A1           * pointer to module to delete
        MOVE.L  H.SIZE(A0),D0           * size of module to delete
        MOVE.W  #_LVOFreeMem,D6
        BSR.S   ECALL
        MOVEA.L (A7)+,A6                * pointer to "dos.library"
        MOVEQ   #10,D1                  * "something wrong"
        JSR     _LVOExit(A6)


*
* - execute "exec_lib" call (offset passed in D6)
*

ECALL:  MOVEM.L D1-D7/A0/A2/A3/A5,-(A7)
        MOVEA.L EXEC.LIB,A6
        JSR     0(A6,D6.W)
        MOVEM.L (A7)+,D1-D7/A0/A2/A3/A5
        RTS

*
* - execute "dos.library" call (offset passed in D6)
*

DCALL:  MOVEM.L D1-D7/A0/A2/A3/A5,-(A7)
        MOVEA.L  _DOSBase,A6
        JSR     0(A6,D6.W)
        MOVEM.L (A7)+,D1-D7/A0/A2/A3/A5
        RTS

DOSOPEN:
        LEA     DOSLIB(PC),A1           * "dos.library"
        MOVEQ   #0,D0                   * any version will do
        MOVE.W  #_LVOOpenLibrary,D6
        BSR     ECALL        
        MOVE.L  D0,_DOSBase             * save pointer
        RTS

FILOPEN:
        MOVE.L  D2,-(A7)
        move.l  #MODE_OLDFILE,D2
        move.w  #_LVOOpen,D6
        BSR     DCALL
        MOVE.L  (A7)+,D2
        rts
 
DOSLIB: DC.B    'dos.library'
        DC.B    0

F77LIB: DC.B    'sys:l/f77.rl'
        DC.L    0

HDWLIB: DC.B    'sys:l/hdw.rl'
        DC.L    0

M81LIB: DC.B    'sys:l/m81.rl'
        DC.B    0

ERRMSG: DC.B    '?cannot load run-time library'
        DC.B    10,0

NIL:    DC.B    'NIL:'
        DC.B    0
_WBStat:     DC.W  0
_stdin:      DC.L  0
_stdout:     DC.L  0
_errno:      DC.L  0
_WBenchMsg:  DC.L  0
_DosCmdBuf:  DC.L  0
_DosCmdLen:  DC.L  0
_DOSBase:    DC.L  0
