home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 152.lha / Startups / startup.asm < prev    next >
Assembly Source File  |  1988-04-26  |  21KB  |  756 lines

  1.  
  2. *------ startup.asm  v 34.12   Copyright 1988 Commodore-Amiga, Inc.
  3. *------
  4. *------ Conditional assembly flags
  5. *------ ASTART:   1=Standard Globals Defined    0=Reentrant Only
  6. *------ WINDOW:   1=AppWindow for WB startup    0=No AppWindow code
  7. *------ XNIL:     1=Remove startup NIL: init    0=Default Nil: WB Output
  8. *------ NARGS:    1=Argv[0] only                0=Normal cmd line arg parse
  9. *------ DEBUG:    1=Set up old statics for Wack 0=No extra statics
  10. *------ QARG:     1=No argv                 0=Passes argc,argv
  11.  
  12. * Include the appropriate .i file to set the flags
  13.  
  14.     INCLUDE "astartup.i"
  15.  
  16. * Flags for  [A]start  AWstart  Rstart  RWstart  RXstart  QStart
  17. * ASTART         1        1       0        0        0       0
  18. * WINDOW         0        1       0        1        0       0
  19. * XNIL           0        0       0        0        1       1
  20. * NARGS          0        0       0        0        0       0
  21. * DEBUG          0        0       0        0        0       0
  22. * QARG           0        0       0        0        0       1
  23.  
  24. ;------   Flag WB output initialization
  25. WBOUT     SET   (ASTART!WINDOW!(1-XNIL))
  26.  
  27. ************************************************************************
  28. *
  29. *   startup.asm --- Reentrant C Program Startup/Exit (CLI and WB)
  30. *                   Made reentrant by C. Scheppner
  31. *            Optimized by Kodiak Burns
  32. *                   v34.12  07/25/88
  33. *
  34. *   Copyright (c) 1988 Commodore-Amiga, Inc.
  35. *
  36. *   Title to this software and all copies thereof remain vested in the
  37. *   authors indicated in the above copyright notice.  The object version
  38. *   of this code may be used in software for Commodore Amiga computers.
  39. *   All other rights are reserved.
  40. *
  41. *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE
  42. *   ACCURACY, RELIABILITY, PERFORMANCE OR OPERATION OF THIS SOFTWARE,
  43. *   AND ALL SUCH USE IS AT YOUR OWN RISK.  NEITHER COMMODORE NOR THE
  44. *   AUTHORS ASSUME ANY RESPONSIBILITY OR LIABILITY WHATSOEVER WITH
  45. *   RESPECT TO YOUR USE OF THIS SOFTWARE.
  46. *
  47. *
  48. *   RSTARTUP.ASM
  49. *
  50. *      This startup dynamically allocates a structure which includes
  51. *   the argv buffers.  If you use this startup, your code must return
  52. *   to this startup when it exits.  Use exit(n) or final curly brace
  53. *   (rts) to return here.  Do not use AmigaDOS Exit() function.
  54. *   Due to this dynamic allocation and some code consolidation, this
  55. *   startup can make executables several hundred bytes smaller.
  56. *
  57. *       Because a static initialSP variable can not be used, this
  58. *   code depends on the fact that AmigaDOS places the address of
  59. *   the top of our stack in SP and proc->pr_ReturnAddr right before
  60. *   JSR'ing to us.  This code uses pr_ReturnAddr when restoring SP.
  61. *
  62. *       Most versions of startup will initialize a Workbench process's
  63. *   input and output streams (and stdio globals if present) to NIL:
  64. *   if no other form of Workbench output (like WINDOW) is provided.
  65. *   This should help prevent crashes if a user puts an icon on a CLI
  66. *   program, and will also protect against careless stdio debugging
  67. *   or error messages left in a Workbench program.  The code for
  68. *   initializing Workbench IO streams only be removed by assembling
  69. *   startup with ASTART and WINDOW set to 0, and XNIL set to 1.
  70. *
  71. *
  72. *   Some startups which can be conditionally assembled:
  73. *
  74. *      1. Standard Astartup for non-reentrant code
  75. *      2. Reentrant Rstartup (no unshareable globals)
  76. *      3. Smaller reentrant-only RXstartup (no NIL: WB init code)
  77. *      4. Standard AWstartup (WB output window) for non-reentrant code
  78. *      5. Reentrant RWstartup (WB output window, no unshareable globals)
  79. *      6. Smallest Qstartup  (No argv - argv is ptr to NULL string)
  80. *
  81. *
  82. *   Explanation of conditional assembly flags:
  83. *
  84. *      ASTART (ASTART SET 1) startups will set up and XDEF the
  85. *   global variables _stdin, _stdout, _stderr, _errno and  _WBenchMsg.
  86. *   These startups can be used as smaller replacements for startups
  87. *   like (A)startup.obj and TWstartup.obj.  Startups with ASTART
  88. *   would generally be used for non-reentrant programs, although the
  89. *   startup code itself is still reentrant if the globals are not
  90. *   referenced.
  91. *      Reentrant (ASTART SET 0) startups will NOT set up or
  92. *   XDEF the stdio and WBenchMsg globals.  This not only makes the
  93. *   startup slightly smaller, but also lets you know if your code
  94. *   is referencing these non-reentrant globals (you will get an
  95. *   unresolved external reference when you link).  Programs
  96. *   get their input and output handles from Input() and Output(),
  97. *   and the WBenchMsg is passed in argv on Workbench startup.
  98. *
  99. *      WINDOW (WINDOW SET 1) startups use an XREF'd CON: string
  100. *   named AppWindow, defined in your application, to open a stdio
  101. *   console window when your application is started from Workbench.
  102. *   For non-reentrant programs, this window can be used for normal
  103. *   stdio (printf, getchar, etc).  For reentrant programs the window
  104. *   is Input() and Output().  WINDOW is useful when adding Workbench
  105. *   capability to a stdio application, and also for debugging other
  106. *   Workbench applications.  To insure that applications requiring
  107. *   a window startup are linked with a window startup, the label
  108. *   _NeedWStartup can be externed and referenced in the application
  109. *   so that a linker error will occur if linked with a standard
  110. *   startup.
  111. *
  112. *       example:   /* Optional safety reference to NeedWStartup */
  113. *                    extern UBYTE  NeedWStartup;
  114. *                    UBYTE  *HaveWStartup = &NeedWStartup;
  115. *                  /* Required window specification */
  116. *                    char AppWindow[] = "CON:30/30/200/150/MyProgram";
  117. *                    ( OR  char AppWindow[] = "\0";  for no window )
  118. *
  119. *
  120. *      XNIL (XNIL SET 1) allows the creation of a smaller startup
  121. *   by removing the code that initializes a Workbench process's
  122. *   output streams to NIL:.  This flag can only remove the code
  123. *   if it is not required for ASTART or WINDOW.
  124. *
  125. *      NARGS (NARGS SET 1) removes the code used to parse command line
  126. *   arguments.  The command name is still passed to _main as argv[0].
  127. *   This option can take about 120 bytes off the size of any program that
  128. *   does not use command line args.
  129. *
  130. *      DEBUG (DEBUG SET 1) will cause the old startup.asm statics
  131. *   initialSP, dosCmdLen and dosCmdBuf to be defined and initialized
  132. *   by the startup code, for use as debugging symbols when using Wack.
  133. *
  134. *      QARG (QARG SET TO 1) will bypass all argument parsing.  A CLI
  135. *   startup is passed argc == 1, and a Workbench startup is passed
  136. *   argc == 0.  Argv[0] will be a pointer to a NULL string rather than
  137. *   a pointer to the command name.  This option creates a very small
  138. *   startup with no sVar structure allocation, and therefore must be used
  139. *   with XNIL (it is incompatible with default or AWindow output options).
  140. *
  141. *
  142. *   RULES FOR REENTRANT CODE
  143. *
  144. *      - Make no direct or indirect (printf, etc) references to the
  145. *        globals _stdin, _stdout, _stderr, _errno, or _WBenchMsg.
  146. *
  147. *      - For stdio use either special versions of printf and getchar
  148. *        that use Input() and Output() rather than _stdin and _stdout,
  149. *        or use fprintf and fgetc with Input() and Output() file handles.
  150. *
  151. *      - Workbench applications must get the pointer to the WBenchMsg
  152. *        from argv rather than from a global extern WBenchMsg.
  153. *
  154. *      - Use no global or static variables within your code.  Instead,
  155. *        put all former globals in a dynamically allocated structure, and
  156. *        pass around a pointer to that structure.  The only acceptable
  157. *        globals are constants (message strings, etc) and global copies
  158. *        of Library Bases to resolve Amiga.lib references.  Your code
  159. *        must return all OpenLibrary's into non-global variables,
  160. *        copy the result to the global library base only if successful,
  161. *        and use the non-globals when deciding whether to Close any
  162. *        opened libraries.  
  163. *
  164. ************************************************************************
  165.  
  166.  
  167. ******* Included Files *************************************************
  168.  
  169.     INCLUDE    "exec/types.i"
  170.     INCLUDE    "exec/alerts.i"
  171.     INCLUDE    "exec/memory.i"
  172.     INCLUDE    "libraries/dos.i"
  173.     INCLUDE    "libraries/dosextens.i"
  174.     INCLUDE    "workbench/startup.i"
  175.  
  176.  
  177. ******* Macros *********************************************************
  178.  
  179. xlib    macro
  180.     xref    _LVO\1
  181.     endm
  182.  
  183. callsys    macro
  184.     CALLLIB    _LVO\1
  185.     endm
  186.  
  187. ******* Imported *******************************************************
  188.  
  189. ABSEXECBASE    EQU    4
  190.  
  191.     xref    _main        ; C code entry point
  192.  
  193.     IFGT    WINDOW
  194.     xref    _AppWindow    ; CON: spec in application for WB stdio window
  195.     xdef    _NeedWStartup    ; May be externed and referenced in application
  196.     ENDC    WINDOW
  197.  
  198.     xlib    Alert
  199.     xlib    AllocMem
  200.     xlib    FindTask
  201.     xlib    Forbid
  202.     xlib    FreeMem
  203.     xlib    GetMsg
  204.     xlib    OpenLibrary
  205.     xlib    CloseLibrary
  206.     xlib    ReplyMsg
  207.     xlib    Wait
  208.     xlib    WaitPort
  209.  
  210.     xlib    CurrentDir
  211.     xlib    Open
  212.     xlib    Close
  213.     xlib    Input
  214.     xlib    Output
  215.  
  216. ******* Exported *******************************************************
  217.  
  218. *----- These globals are set up for standard startup code only
  219.     IFGT    ASTART
  220.     xdef    _stdin
  221.     xdef    _stdout
  222.     xdef    _stderr
  223.     xdef    _errno
  224.     xdef    _WBenchMsg
  225.     ENDC    ASTART
  226.  
  227. *----- These globals available to normal and reentrant code
  228.  
  229.     xdef    _SysBase
  230.     xdef    _DOSBase
  231.     xdef    _exit        ; standard C exit function
  232.  
  233.  
  234. ***** Startup Variables structure **********************************
  235.  
  236.     IFEQ    QARG
  237. ARGVSLOTS    EQU    32
  238.  
  239.  STRUCTURE  SVar,0
  240.     LONG    sv_WbOutput
  241.     STRUCT  sv_argvArray,ARGVSLOTS*4
  242.     STRUCT  sv_argvBuffer,256
  243.     LABEL   SV_SIZEOF
  244.     ENDC    QARG
  245.  
  246. ************************************************************************
  247. *
  248. *   Standard Program Entry Point
  249. *
  250. ************************************************************************
  251. *
  252. *    Entered with
  253. *        d0  dosCmdLen
  254. *        a0  dosCmdBuf
  255. *    Any registers (except sp) are allowed to be modified
  256. *
  257. *    Calls
  258. *        main (argc, argv)
  259. *        int   argc;
  260. *        char *argv[]; 
  261. *
  262. *        For Workbench startup, argc=0, argv=WBenchMsg
  263. *
  264. ************************************************************************
  265. startup:
  266.     IFGT    DEBUG
  267.         move.l    sp,initialSP
  268.         move.l    d0,dosCmdLen
  269.         move.l    a0,dosCmdBuf
  270.     ENDC    DEBUG
  271.  
  272.     IFEQ    QARG
  273.         move.l    d0,d2
  274.         move.l    a0,a2
  275.     ENDC    QARG
  276.  
  277.     ;------ get Exec library base pointer
  278.         movea.l    ABSEXECBASE,a6
  279.         move.l    a6,_SysBase
  280.  
  281.     ;------ get the address of our task
  282.         suba.l    a1,a1        ; clear a1
  283.         callsys    FindTask
  284.         move.l    d0,a4        ; keep task address in a4
  285.  
  286.     ;------ get DOS library base pointer
  287.         moveq    #0,d0
  288.         lea    DOSName(pc),A1    ; dos.library
  289.         callsys    OpenLibrary
  290.  
  291.         tst.l   d0
  292.         beq    alertDOS    ; fail on null with alert
  293.         move.l    d0,_DOSBase    ; Else set the global
  294.     
  295.  
  296.     IFEQ    QARG
  297.     ;------ alloc the argument structure
  298.         move.l    #SV_SIZEOF,d0
  299.         move.l    #(MEMF_PUBLIC!MEMF_CLEAR),d1
  300.         callsys    AllocMem
  301.         tst.l    d0
  302.         beq    alertMem    ; fail on null with alert
  303.         move.l    d0,-(sp)    ; save sVar ptr on stack
  304.         move.l    d0,a5        ; sVar ptr to a5
  305.     ENDC    QARG
  306.     IFGT    QARG
  307.         clr.l    -(sp)
  308.     ENDC    QARG
  309.  
  310.         clr.l    -(sp)        ; reserve space for WBenchMsg if any
  311.  
  312.     ;------ branch to Workbench startup code if not a CLI process
  313.         move.l    pr_CLI(A4),d0
  314.         beq    fromWorkbench
  315.  
  316. ;=======================================================================
  317. ;====== CLI Startup Code ===============================================
  318. ;=======================================================================
  319. ;    d0  process CLI BPTR (passed in), then temporary
  320. ;    d2  dos command length (passed in)
  321. ;    d3  argument count
  322. ;    a0  temporary
  323. ;    a1  argv buffer
  324. ;    a2  dos command buffer (passed in)
  325. ;    a3  argv array
  326. ;    a4  Task (passed in)
  327. ;    a5  SVar structure if not QARG (passed in)
  328. ;    a6  AbsExecBase (passed in)
  329. ;    sp  WBenchMsg (still 0), sVar or 0, then RetAddr (passed in)
  330. ;    sp  argc, argv, WBenchMsg, sVar or 0,RetAddr (at bra domain)
  331.  
  332.     IFEQ    QARG
  333.     ;------ find command name
  334.         lsl.l    #2,d0        ; pr_CLI bcpl pointer conversion
  335.         move.l    d0,a0
  336.         move.l    cli_CommandName(a0),d0
  337.         lsl.l    #2,d0        ; bcpl pointer conversion
  338.  
  339.         ;-- start argv array
  340.         lea    sv_argvBuffer(a5),a1
  341.         lea    sv_argvArray(a5),a3
  342.  
  343.         ;-- copy command name
  344.         move.l    d0,a0
  345.         moveq.l    #0,d0
  346.         move.b    (a0)+,d0    ; size of command name
  347.         clr.b    0(a0,d0.l)    ; terminate the command name
  348.         move.l    a0,(a3)+
  349.         moveq    #1,d3        ; start counting arguments
  350.  
  351.     IFEQ    NARGS    
  352.     ;------ null terminate the arguments, eat trailing control characters
  353.         lea    0(a2,d2.l),a0
  354. stripjunk:
  355.         cmp.b    #' ',-(a0)
  356.         dbhi    d2,stripjunk
  357.  
  358.         clr.b    1(a0)
  359.  
  360.     ;------ start gathering arguments into buffer
  361. newarg:
  362.         ;-- skip spaces
  363.         move.b    (a2)+,d1
  364.         beq.s    parmExit
  365.         cmp.b    #' ',d1
  366.         beq.s    newarg
  367.         cmp.b    #9,d1        ; tab
  368.         beq.s    newarg
  369.  
  370.         ;-- check for argument count overflow
  371.         cmp.w    #ARGVSLOTS-1,d3
  372.         beq.s    parmExit
  373.  
  374.         ;-- push address of the next parameter
  375.         move.l    a1,(a3)+
  376.         addq.w    #1,d3
  377.  
  378.         ;-- process quotes
  379.         cmp.b    #'"',d1
  380.         beq.s    doquote
  381.  
  382.         ;-- copy the parameter in
  383.         move.b    d1,(a1)+
  384.  
  385. nextchar:
  386.         ;------ null termination check
  387.         move.b    (a2)+,d1
  388.         beq.s    parmExit
  389.         cmp.b    #' ',d1
  390.         beq.s    endarg
  391.  
  392.         move.b    d1,(a1)+
  393.         bra.s    nextchar
  394.  
  395. endarg:
  396.         clr.b    (a1)+
  397.         bra.s    newarg
  398.  
  399. doquote:
  400.     ;------ process quoted strings
  401.         move.b    (a2)+,d1
  402.         beq.s    parmExit
  403.         cmp.b    #'"',d1
  404.         beq.s    endarg
  405.  
  406.         ;-- '*' is the BCPL escape character
  407.         cmp.b    #'*',d1
  408.         bne.s    addquotechar
  409.  
  410.         move.b    (a2)+,d1
  411.         move.b    d1,d2
  412.         and.b    #$df,d2        ;d2 is temp toupper'd d1
  413.  
  414.         cmp.b    #'N',d2        ;check for dos newline char
  415.         bne.s    checkEscape
  416.  
  417.         ;--    got a *N -- turn into a newline
  418.         moveq    #10,d1
  419.         bra.s    addquotechar
  420.  
  421. checkEscape:
  422.         cmp.b    #'E',d2
  423.         bne.s    addquotechar
  424.  
  425.         ;--    got a *E -- turn into a escape
  426.         moveq    #27,d1
  427.  
  428. addquotechar:
  429.         move.b    d1,(a1)+
  430.         bra.s    doquote
  431.  
  432. parmExit:
  433.     ;------ all done -- null terminate the arguments
  434.         clr.b    (a1)
  435.         clr.l    (a3)
  436.     ENDC NARGS
  437.  
  438.         pea    sv_argvArray(a5) ; argv
  439.         move.l    d3,-(sp)     ; argc
  440.     ENDC    QARG
  441.  
  442.     IFGT    QARG
  443.         pea    nullArgV(pc)    ; pointer to pointer to null string
  444.         pea    1        ; only one pointer
  445.     ENDC
  446.  
  447.     IFGT    ASTART
  448.         movea.l    _DOSBase,a6
  449.     ;------ get standard input handle:
  450.         callsys    Input
  451.         move.l    d0,_stdin
  452.  
  453.     ;------ get standard output handle:
  454.         callsys    Output
  455.         move.l    d0,_stdout
  456.         move.l    d0,_stderr
  457.         movea.l    ABSEXECBASE,a6
  458.     ENDC ASTART
  459.  
  460.         bra    domain
  461.  
  462.  
  463. ;=======================================================================
  464. ;====== Workbench Startup Code =========================================
  465. ;=======================================================================
  466. ;    a2  WBenchMsg
  467. ;    a4  Task (passed in)
  468. ;    a5  SVar structure if not QARG (passed in)
  469. ;    a6  AbsExecBase (passed in)
  470. ;    sp  WBenchMsg (still 0), sVar or 0, then RetAddr (passed in)
  471. ;    sp  argc=0,argv=WBenchMsg,WBenchMsg,sVar or 0,RetAddr (at domain)
  472.  
  473. fromWorkbench:
  474.     ;------ get the startup message that workbench will send to us.
  475.     ;    must get this message before doing any DOS calls
  476.         bsr.s   getWbMsg
  477.  
  478.     ;------ save the message so we can return it later
  479.         move.l    d0,(sp)
  480.     IFGT    ASTART
  481.         move.l    d0,_WBenchMsg
  482.     ENDC    ASTART
  483.  
  484.     ;------ push the message on the stack for wbmain (as argv)
  485.         move.l    d0,-(sp)
  486.         clr.l    -(sp)        ; indicate run from Workbench (argc=0)
  487.  
  488.     IFNE    (1-QARG)+WBOUT
  489.     ;------ put DOSBase in a6 for next few calls
  490.         move.l    _DOSBase,a6
  491.     ENDC    (1-QARG)+WBOUT
  492.  
  493.     IFEQ    QARG
  494.     ;------ get the first argument
  495.         move.l    d0,a2
  496.         move.l    sm_ArgList(a2),d0
  497.         beq.s    doCons
  498.  
  499.     ;------ and set the current directory to the same directory
  500.         move.l    d0,a0
  501.         move.l    wa_Lock(a0),d1
  502.         callsys    CurrentDir
  503. doCons: 
  504.     ENDC    QARG
  505.  
  506.     IFGT    WBOUT
  507.  
  508.     ;------ Open NIL: or AppWindow for WB Input()/Output() handle
  509.     ;    Also for possible initialization of stdio globals
  510.     ;    Stdio used to be initialized to -1
  511.  
  512.       
  513.     IFGT    WINDOW
  514.     ;------ Get AppWindow defined in application
  515.         lea    _AppWindow,a0
  516.         cmp.b    #0,(a0)
  517.         bne.s    doOpen        ; Open if not null string
  518.     ENDC    WINDOW
  519.  
  520.     ;------ Open NIL: if no window provided
  521.     lea    NilName(PC),a0
  522.  
  523. doOpen:
  524.     ;------ Open up the file whose name is in a0
  525.     ;    DOSBase still in a6
  526.         move.l    a0,d1
  527.         move.l    #MODE_OLDFILE,d2 
  528.         callsys    Open 
  529.     ;------ d0 now contains handle for Workbench Output
  530.     ;------ save handle for closing on exit
  531.         move.l    d0,sv_WbOutput(a5)
  532.         bne.s    gotOpen
  533.         moveq.l #RETURN_FAIL,d2
  534.         bra     exit2
  535. gotOpen:
  536.     IFGT ASTART
  537.     ;------ set the C input and output descriptors 
  538.         move.l    d0,_stdin
  539.         move.l    d0,_stdout
  540.         move.l    d0,_stderr
  541.     ENDC ASTART
  542.  
  543.     ;------ set the console task (so Open( "*", mode ) will work 
  544.     ;    task pointer still in A4
  545.         move.l    d0,pr_CIS(A4)
  546.         move.l    d0,pr_COS(A4)
  547.         lsl.l    #2,d0 
  548.         move.l    d0,a0 
  549.         move.l    fh_Type(a0),d0
  550.         beq.s    noConTask
  551.         move.l    d0,pr_ConsoleTask(A4)
  552. noConTask:
  553.     ENDC WBOUT
  554.  
  555.     ;------ Fall though to common WB/CLI code
  556.  
  557.  
  558. ****************************************************
  559. **                                                **
  560. ** This code now used by both CLI and WB startup  **
  561. **                                                **
  562. ****************************************************
  563.  
  564. domain:
  565.         jsr    _main
  566.     ;------ main didn't use exit(n) so provide success return code
  567.         moveq.l    #RETURN_OK,d2
  568.         bra.s    exit2
  569.  
  570.  
  571. ****************************************************
  572. **                                                **
  573. **    subroutines here to allow short branches    **
  574. **                                                **
  575. ****************************************************
  576.  
  577. getWbMsg:
  578.     ;------ a6 = ExecBase
  579.         lea    pr_MsgPort(A4),a0    ; our process base
  580.         callsys    WaitPort
  581.         lea    pr_MsgPort(A4),a0    ; our process base
  582.         callsys    GetMsg
  583.         rts
  584.  
  585. ****************************************************
  586.  
  587. alertDOS:
  588.     ;------ do recoverable alert for no DOS and exit
  589.         ALERT    (AG_OpenLib!AO_DOSLib)
  590.     
  591.     ;------ do recoverable alert for no memory and exit
  592.     ;------ If we got this far, DOS is open, so close it
  593.     IFEQ QARG
  594.         bra.s    failExit
  595. alertMem:
  596.         movea.l _DOSBase,a1
  597.         callsys CloseLibrary    
  598.         ALERT    AG_NoMemory
  599.     ENDC QARG
  600. failExit:
  601.         tst.l   pr_CLI(a4)
  602.         bne.s   fail2
  603.         bsr.s    getWbMsg
  604.         movea.l d0,a2
  605.         bsr.s    repWbMsg
  606. fail2:
  607.         moveq.l    #RETURN_FAIL,d0
  608.         rts
  609.  
  610. ****************************************************
  611.  
  612. repWbMsg:
  613.     ;------ return the startup message to our parent
  614.     ;       a6 = ExecBase (passed)
  615.     ;    a2 = WBenchMsg (passed)
  616.     ;    we forbid so workbench can't UnLoadSeg() us before we are done
  617.         callsys    Forbid
  618.         move.l    a2,a1
  619.         callsys    ReplyMsg
  620.         rts
  621.  
  622.  
  623. *******************************************************
  624. **                                                   **
  625. **  C Program exit() Function, return code on stack  **
  626. **                                                   **
  627. **  pr_ReturnAddr points to our RTS addr on stack    **
  628. **  and we use this to calculate our stack ptr:      ** 
  629. **                                                   **
  630. **      SP ->   WBenchMsg or 0 (CLI)                 **
  631. **              sVar ptr or 0 (QARG)                 **
  632. **              Address for RTS to DOS               **
  633. **                                                   **
  634. *******************************************************
  635.  
  636. _exit:
  637.         move.l    4(sp),d2    ; exit(n) return code to d2
  638.  
  639. exit2:                    ;exit code in d2
  640.     ;------ restore initial stack ptr
  641.         ;-- FindTask
  642.         movea.l    ABSEXECBASE,a6
  643.         suba.l    a1,a1
  644.         callsys    FindTask
  645.         ;-- get SP as it was prior to DOS's jsr to us
  646.         move.l    d0,a4
  647.         move.l    pr_ReturnAddr(a4),a5
  648.         ;-- subtract 4 for return address, 4 for SVar, 4 for WBenchMsg
  649.         suba.w    #12,a5
  650.  
  651.         ;-- restore sp
  652.         move.l    a5,sp
  653.     
  654.         ;-- recover WBenchMsg
  655.         move.l    (sp)+,a2
  656.         ;-- recover SVar
  657.         move.l    (sp)+,a5
  658.  
  659.  
  660.     IFGT    WBOUT
  661.     ;------ Close any WbOutput file before closing dos.library
  662.         move.l    sv_WbOutput(a5),d1
  663.         beq.s    noWbOut
  664.         move.l    _DOSBase,a6
  665.         callsys Close
  666. noWbOut:
  667.     ;------ Restore a6 = ExecBase
  668.         movea.l ABSEXECBASE,a6
  669.     ENDC    WBOUT
  670.  
  671.     ;------ Close DOS library, if we got here it was opened
  672.     ;    SysBase still in a6
  673.         movea.l    _DOSBase,a1
  674.         callsys    CloseLibrary
  675.  
  676.     ;------ if we ran from CLI, skip workbench reply
  677. checkWB:
  678.         move.l    a2,d0
  679.         beq.s    deallocSV
  680.  
  681.         bsr.s    repWbMsg
  682.  
  683. deallocSV:
  684.     IFEQ    QARG
  685.     ;------ deallocate the SVar structure
  686.         move.l    a5,a1
  687.         move.l    #SV_SIZEOF,d0
  688.         callsys FreeMem
  689.     ENDC    QARG
  690.  
  691.     ;------ this rts sends us back to DOS:
  692.         move.l    d2,d0
  693.         rts
  694.  
  695.  
  696. **********************************************************************
  697.  
  698. ;----- PC relative data
  699.  
  700. DOSName        DOSNAME
  701. NilName        dc.b    'NIL:',0
  702.     IFGT    QARG
  703. nullArgV    dc.l    nullArg
  704. nullArg        dc.l    0        ; "" & the null entry after nullArgV
  705.     ENDC
  706.  
  707. **********************************************************************
  708.  
  709.    DATA
  710.  
  711. **********************************************************************
  712.  
  713. _SysBase    dc.l    0
  714. _DOSBase    dc.l    0
  715.  
  716.     IFGT    ASTART
  717. _WBenchMsg    dc.l    0
  718. _stdin        dc.l    0
  719. _stdout        dc.l    0
  720. _stderr        dc.l    0
  721. _errno        dc.l    0
  722.     ENDC    ASTART
  723.  
  724.     IFGT    DEBUG
  725. initialSP    dc.l    0
  726. dosCmdLen    dc.l    0
  727. dosCmdBuf    dc.l    0
  728.     ENDC    DEBUG
  729.  
  730. VerRev        dc.w    34,12
  731.     IFGT    ASTART
  732.         dc.b    'A'
  733.     ENDC    ASTART
  734.     IFEQ    ASTART
  735.         dc.b    'R'
  736.     ENDC    ASTART
  737.     IFGT    WINDOW
  738. _NeedWStartup:
  739.         dc.b    'W'
  740.     ENDC    WINDOW
  741.     IFEQ    WBOUT
  742.         dc.b    'X'
  743.     ENDC    WBOUT
  744.     IFGT    NARGS
  745.         dc.b    'N'
  746.     ENDC    NARGS
  747.     IFGT    DEBUG
  748.         dc.b    'D'
  749.     ENDC    DEBUG
  750.     IFGT    QARG
  751.         dc.b    'Q'
  752.     ENDC    QARG
  753.  
  754.     END
  755.  
  756.