
* C.ASM  (ASTARTUP.ASM with modifications)
*
*
* This is exactly Lattice's Astartup.asm with some small modificatons
* to save the BCPL register state on startup.
*
************************************************************************
*
*   C Program Startup/Exit (Combo Version: CLI and WorkBench)
*
************************************************************************
*
*   Source Control:
*
*       $Header$
*
*       $Locker$
*
*       $Log$
*
************************************************************************


******* Included Files *************************************************

   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"


******* Imported *******************************************************

xlib   macro
   xref   _LVO\1
   endm

   xref   _AbsExecBase
   xref   _Input
   xref   _Output

   xref   _main         ; C code entry point

   xlib   Alert
   xlib   FindTask
   xlib   Forbid
   xlib   GetMsg
   xlib   OpenLibrary
   xlib   CloseLibrary
   xlib   ReplyMsg
   xlib   Wait
   xlib   WaitPort

   xlib   CurrentDir
   xlib   Open


******* Exported *******************************************************

   xdef   _SysBase
   xdef   _DOSBase

   xdef   _errno
   xdef   _stdin
   xdef   _stdout
   xdef   _stderr

   xdef   _exit         ; standard C exit function
   xdef   _SysRegs      ; D0-D7 A0-A6 system registers on startup


callsys   macro
   CALLLIB   _LVO\1
   endm


************************************************************************
*
*   Standard Program Entry Point
*
************************************************************************
*
*   main (argc, argv)
*      int  argc;
*      char *argv[]; 
*
************************************************************************

startup:            ; reference for Wack users
      movem.l  D0-D7/A0-A6,_SysRegs
      move.l   sp,initialSP   ; initial task stack pointer
      move.l   d0,dosCmdLen
      move.l   a0,dosCmdBuf
      clr.l   returnMsg

   ;------ get Exec's library base pointer:
      move.l   _AbsExecBase,a6
      move.l   a6,_SysBase

   ;------ get the address of our task
      suba.l   a1,a1
      callsys   FindTask
      move.l   d0,a4

   ;------ are we running as a son of Workbench?
      tst.l   pr_CLI(A4)
      beq   fromWorkbench

;=======================================================================
;====== CLI Startup Code ===============================================
;=======================================================================
fromCLI:
   ;------   attempt to open DOS library:
      bsr   openDOS

   ;------ find command name:
      move.l   pr_CLI(a4),a0
      add.l   a0,a0      ; bcpl pointer conversion
      add.l   a0,a0
      move.l   cli_CommandName(a0),a0
      add.l   a0,a0      ; bcpl pointer conversion
      add.l   a0,a0

   ;------ create buffer and array:
*      link   a6,#-(100+16*4+2*4)
      movem.l   d2/a2/a3,-(sp)
      lea   argvBuffer,a2
      lea   argvArray,a3
*      move.l   a3,16(sp)   ; save 
      moveq.l   #1,d2      ; param counter

   ;------ fetch command name:
      moveq.l   #0,d0
      move.b   (a0)+,d0   ; size of command name
      move.l   a2,(a3)+   ; ptr to command name
      bra.s   1$
2$:      move.b   (a0)+,(a2)+
1$:      dbf   d0,2$
      clr.b   (a2)+

   ;------   collect parameters:
      move.l   dosCmdLen,d0
      move.l   dosCmdBuf,a0

   ;------ skip control characters and space:
3$:      move.b   (a0)+,d1
      subq.l   #1,d0
      ble.s   parmExit
      cmp.b   #' ',d1
      ble.s   3$

   ;------ copy parameter:
      addq.l   #1,d2
      move.l   a2,(a3)+
      bra.s   5$
4$:      move.b   (a0)+,d1
      subq.l   #1,d0
      cmp.b   #' ',d1
      ble.s   6$
5$:      move.b   d1,(a2)+
      bra.s   4$
6$:
      clr.b   (a2)+
      bra.s   3$
parmExit:   clr.b   (a2)+
      clr.l   (a3)+

      move.l   d2,d0
      movem.l   (sp)+,d2/a2/a3
      pea   argvArray
      move.l   d0,-(sp)


*
*  The above code relies on the end of line containing a control
*  character of any type, i.e. a valid character must not be the
*  last.  This fact is ensured by DOS.
*
      

   ;------ get standard input handle:
      jsr   _Input
      move.l   d0,_stdin

   ;------ get standard output handle:
      jsr   _Output
      move.l   d0,_stdout
      move.l   d0,_stderr

   ;------ call C main entry point
      jsr   _main

   ;------ return success code:
      moveq.l   #0,D0
      move.l   initialSP,sp   ; restore stack ptr
      rts

;=======================================================================
;====== Workbench Startup Code =========================================
;=======================================================================
fromWorkbench:
   ;------ open the DOS library:
      bsr   openDOS

   ;------ we are now set up.  wait for a message from our starter
      bsr   waitmsg

   ;------ save the message so we can return it later
      move.l   d0,returnMsg   NOTE: no GetMsg performed

   ;------ push the message on the stack for wbmain
      clr.l   -(SP)      indicate: run from Workbench
      move.l   d0,-(SP)

   ;------ get the first argument
      move.l   d0,a2
      move.l   sm_ArgList(a2),d0
      beq.s   docons

   ;------ and set the current directory to the same directory
      move.l   _DOSBase,a6
      move.l   d0,a0
      move.l   wa_Lock(a0),d1
      callsys   CurrentDir

docons:
   ;------ get the toolwindow argument
      move.l   sm_ToolWindow(A2),d1
      beq.s   domain

   ;------ open up the file
      move.l   #MODE_OLDFILE,d2
      callsys   Open

   ;------ set the C input and output descriptors
      move.l   d0,_stdin
      move.l   d0,_stdout
      move.l   d0,_stderr
      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:
      jsr   _main
      moveq.l   #0,d0      Successful return code
      bra.s   exit2


************************************************************************
*
*   C Program Exit Function
*
************************************************************************
*
*  Warning: this function really needs to do more than this.
*
************************************************************************

_exit:
      move.l   4(SP),d0   ; extract return code
exit2:
      move.l  initialSP,SP   ; restore stack pointer
      move.l   d0,-(SP)   ; save return code

   ;------ close DOS library:
      move.l   _AbsExecBase,A6
      move.l   _DOSBase,d0
      beq.s   1$
      move.l   d0,a1
1$:      callsys   CloseLibrary

   ;------ if we ran from CLI, skip workbench cleanup:
      tst.l   returnMsg
      beq.s   exitToDOS

   ;------ return the startup message to our parent
   ;   we forbid so workbench can't UnLoadSeg() us
   ;   before we are done:
      callsys Forbid
      move.l   returnMsg,a1
      callsys   ReplyMsg

   ;------ this rts sends us back to DOS:
exitToDOS:
      move.l   (SP)+,d0
      rts


;-----------------------------------------------------------------------
noDOS:
      ALERT   (AG_OpenLib!AO_DOSLib)
      moveq.l   #100,d0
      bra.s   exit2


;-----------------------------------------------------------------------
; This routine gets the message that workbench will send to us
; called with task id in A4

waitmsg:
      lea   pr_MsgPort(A4),a0     * our process base
      callsys   WaitPort
      lea   pr_MsgPort(A4),a0     * our process base
      callsys GetMsg
      rts

;-----------------------------------------------------------------------
;  Open the DOS library:

openDOS
      clr.l   _DOSBase
      lea   DOSName,A1
      move.l   #LIBRARY_VERSION,d0
      callsys OpenLibrary
      move.l   D0,_DOSBase
      beq   noDOS
      rts


************************************************************************

   DATA

************************************************************************

VerRev      dc.w   1,0

_SysBase   dc.l   0
_DOSBase   dc.l   0

_SysRegs    ds.l  16
_errno      dc.l   0
_stdin      dc.l   0
_stdout      dc.l   0
_stderr      dc.l   0

initialSP   dc.l   0
returnMsg   dc.l   0

dosCmdLen   dc.l   0
dosCmdBuf   dc.l   0

argvArray   ds.l   32
argvBuffer   ds.b   256

DOSName      DOSNAME


   END
