* ==========================
* amiga.dev/programs #12, from cscheppner, Tue Feb 24 17:54:45 1987
* --------------------------
* TITLE:  TWstartup.asm --- Modified Astartup, opens Amiga stdio under WB
*******************************************************************
* TWStartup.asm  - Amiga Startup opens stdio window on WB startup *
*                  using TWspec defined in application            *
*       example:   char TWspec[] = "CON:30/30/200/150/MyProgram"; *
*                   ( OR  char TWspec = "";  for no window )      *
*                                                                 *
* Modified by C. Scheppner (08/03/86) from the following source:  *
*******************************************************************
*                                                                 *
*   C Program Startup/Exit (Combo Version: CLI and WorkBench)     *
*                                                                 *
*******************************************************************
*                                                                 *
* Modified by Paul Petersen and Lionel Hummel to use with PDC 3.3 *
*                                                                 *
*******************************************************************

******** 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    _Input
               xref    _Output

               xref    __main       ; C code entry point
               xref    _TWspec      ; CON: spec in application for WB
                                    ;      stdio window

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

               xlib    CurrentDir
               xlib    Open
               xlib    Close

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

               xdef    _SysBase
               xdef    _DOSBase
               xdef    _WBenchMsg

               xdef    __initialSP
               xdef    __dosCmdLen
               xdef    __dosCmdBuf

               xdef    __fh_stdin     ; AmigaDOS BPTR for stdin
               xdef    __fh_stdout    ; AmigaDOS BPTR for stdout
               xdef    __fh_stderr    ; AmigaDOS BPTR for stderr

               xdef    __exit         ; standard C exit function


callsys        macro
               CALLLIB _LVO\1
               endm


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

               SECTION  1,CODE

startup:            ; reference for Wack users

               move.l  sp,__initialSP   ; initial task stack pointer
               move.l  d0,__dosCmdLen
               move.l  a0,__dosCmdBuf

      ;------ get Exec's library base pointer:

               move.l  4,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:

               suba.l  a0,a0
               move.l  pr_CLI(a4),d0
               lsl.l   #2,d0                       ; bcpl pointer conversion
               move.l  cli_CommandName(a0,d0.l),d0
               lsl.l   #2,d0                       ; bcpl pointer conversion

      ;------ create buffer and array:

               movem.l a2/a3,-(sp)
               lea     argvBuffer,a2
               lea     argvArray,a3

      ;------ fetch command name:

               move.l  d0,a0
               moveq.l #0,d0
               move.b  (a0)+,d0        ; size of command name
               clr.b   0(a0,d0.l)      ; terminate the string
               move.l  a0,(a3)+

      ;------   collect parameters:

               move.l  __dosCmdLen,d0
               move.l  __dosCmdBuf,a0

      ;------ null terminate the string, eat trailing garbage

               lea     0(a0,d0.l),a1
stripjunk:
               cmp.b   #' ',-(a1)

               dbhi    d0,stripjunk
               clr.b   1(a1)
newarg:

      ;------ skip spaces

               move.b  (a0)+,d1
               beq.s   parmExit
               cmp.b   #' ',d1         ; space
               beq.s   newarg
               cmp.b   #9,d1           ; tab
               beq.s   newarg

      ;------ push address of the next parameter

               move.l  a2,(a3)+

      ;------ process quotes

               cmp.b   #'"',d1
               beq.s   doquote

      ;------ copy the parameter in

               move.b  d1,(a2)+
nextchar:

      ;------ null termination check

               move.b  (a0)+,d1
               beq.s   parmExit
               cmp.b   #' ',d1
               beq.s   endarg

               move.b  d1,(a2)+
               bra.s   nextchar
endarg:
               clr.b   (a2)+
               bra.s   newarg
doquote:

      ;------ process quoted strings

               move.b  (a0)+,d1
               beq.s   parmExit
               cmp.b   #'"',d1
               beq.s   endarg

      ;------ '*' is the BCPL escape character

               cmp.b   #'*',d1
               bne.s   addquotechar

               move.b  (a0)+,d1
               cmp.b   #'N',d1
               beq.s   1$
               cmp.b   #'n',d1
               bne.s   2$
1$:
      ;------ got a *N -- turn into a newline

               moveq   #10,d1
               bra.s   addquotechar
2$:
               cmp.b   #'E',d1
               beq.s   3$
               cmp.b   #'e',d1
               bne.s   addquotechar
3$:
      ;------ got a *E -- turn into a escape

               moveq   #27,d1
addquotechar:
               move.b  d1,(a2)+
               bra.s   doquote

parmExit:

      ;------ all done -- null terminate the baby

               clr.b   (a2)
               clr.l   (a3)

      ;------ compute the # of arguments

               move.l   #__dosCmdBuf,d0
               sub.l   a3,d0
               not.l   d0
               lsr.l   #2,d0

               movem.l   (sp)+,a2/a3
               pea   argvArray         ; *argv[]
               move.l   d0,-(sp)       ;  argc

*
*  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,__fh_stdin
               move.l  d0,_stdin

      ;------ get standard output handle:

               jsr     _Output
               move.l  d0,__fh_stdout
               move.l  d0,__fh_stderr

      ;------ update the shadow variables

               move.l  d0,_stdout
               move.l  d0,_stderr

      ;------ call C main entry point

               jsr   __main

      ;------ return success code: THIS CODE SHOULD NEVER EXECUTE

               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,_WBenchMsg

      ;------ push the message on the stack for wbmain

               move.l  d0,-(SP)
               clr.l   -(SP)      indicate: run from Workbench

      ;------ 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

* ==============================================
* ============ Opens stdio window ==============
* ==============================================

docons:
               lea.l    _TWspec,a0
               cmp.b    #0,(a0)         * No window if TWspec is null string
               beq.s    domain

   ;------ open up the file

               move.l   a0,d1
               move.l   #MODE_OLDFILE,d2
               move.l   _DOSBase,a6
               callsys  Open

   ;------ set the C input and output descriptors

               cmp.l    #0,d0
               beq.s    exit2
               move.l   d0,__fh_stdin
               move.l   d0,__fh_stdout
               move.l   d0,__fh_stderr

   ;------ set the shadow variables

               move.l   d0,_stdin
               move.l   d0,_stdout
               move.l   d0,_stderr

   ;------ set the console task (so Open( "*", mode ) will work
   ;   waitmsg has left the task pointer in A4 for us

               move.l  d0,pr_CIS(A4)
               move.l  d0,pr_COS(A4)
               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:

   ;------ Close ToolWin if we have one:

               tst.l   _WBenchMsg
               beq.s   noTW
               move.l  __fh_stdin,d1
               bmi.s   noTW
               move.l  _DOSBase,a6
               callsys Close
noTW:
               move.l  __initialSP,SP   ; restore stack pointer
               move.l  d0,-(SP)   ; save return code

      ;------ close DOS library:

               move.l  4,A6
               move.l  _DOSBase,d0
               beq.s   1$
               move.l  d0,a1
               callsys CloseLibrary
1$
      ;------ if we ran from CLI, skip workbench cleanup:

               tst.l   _WBenchMsg
               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  _WBenchMsg,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     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:
               lea     DOSName(pc),A1
               moveq   #0,d0
               callsys OpenLibrary
               move.l  D0,_DOSBase
               beq     noDOS

               rts

DOSName        dc.b    'dos.library',0

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

               SECTION 2,DATA

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

VerRev         dc.w    33,1

_SysBase       dc.l    0
_DOSBase       dc.l    0
_errno         dc.l    0
__fh_stdin     dc.l    -1              ; BPTR to AmigaDOS file
__fh_stdout    dc.l    -1              ; BPTR to AmigaDOS file
__fh_stderr    dc.l    -1              ; BPTR to AmigaDOS file

_stdin         dc.l    -1              ; Shadow variable for amiga.lib
_stdout        dc.l    -1              ; Shadow variable for amiga.lib
_stderr        dc.l    -1              ; Shadow variable for amiga.lib

__initialSP      dc.l    0
_WBenchMsg     dc.l    0

__dosCmdLen      dc.l    0
__dosCmdBuf      dc.l    0

argvArray      ds.l    32              ; Maximum of 32 arguments
argvBuffer     ds.b    256             ; Maximum sum of argument lengths

               END

