home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / source / c.a < prev    next >
Encoding:
Text File  |  1996-12-24  |  42.3 KB  |  1,220 lines

  1. *
  2. * C initial startup procedure under AmigaDOS
  3. * Use the following command line to make c.o
  4. * asm -u c.a
  5. *
  6. * Use the following command line to make cres.o
  7. * asm -u -dRESIDENT -ocres.o c.a
  8. *
  9. * Use the following command line to make catch.o (standard GURU catcher)
  10. * asm -u -dCATCH -ocatch.o c.a
  11. *
  12. * Use the following command line to make catchnr.o (GURU catcher w/out requester)
  13. * asm -u -dCATCH -dNOREQ -ocatchnr.o c.a
  14. *
  15. * Use the following command line to make catchres.o (resident GURU catcher)
  16. * asm -u -dCATCH -dRESIDENT -ocatchres.o c.a
  17. *
  18. * Use the following command line to make catchresnr.o (resi GURU catcher w/out req)
  19. * asm -u -dCATCH -dRESIDENT -dNOREQ -ocatchresnr.o c.a
  20. *
  21.         IFD  CATCH
  22.           IFND NOREQ
  23. AUTOREQ         set        1
  24.           ENDC
  25.         ENDC
  26.  
  27.         INCLUDE        "exec/types.i"
  28.         INCLUDE        "exec/alerts.i"
  29.         INCLUDE        "exec/nodes.i"
  30.         INCLUDE        "exec/lists.i"
  31.         INCLUDE        "exec/ports.i"
  32.         INCLUDE        "exec/libraries.i"
  33.         INCLUDE        "exec/tasks.i"
  34.         INCLUDE        "exec/memory.i"
  35.         INCLUDE        "exec/execbase.i"
  36.         INCLUDE        "libraries/dos.i"
  37.         INCLUDE        "libraries/dosextens.i"
  38.         INCLUDE        "workbench/startup.i"
  39.         INCLUDE        "exec/funcdef.i"
  40.         INCLUDE        "exec/exec_lib.i"
  41.         INCLUDE        "libraries/dos_lib.i"
  42.  
  43.         IFD   CATCH
  44.         INCLUDE        "intuition/intuition.i"
  45. VERSION  equ    1
  46. REVISION equ    0
  47.         ENDC
  48.         
  49. MEMFLAGS        EQU        MEMF_CLEAR+MEMF_PUBLIC
  50. AbsExecBase     EQU        4
  51.  
  52. ;;;
  53. ;;;   Stack map.
  54. ;;;
  55.       OFFSET  0
  56.            ds.b    4
  57. savereg    ds.b    13*4
  58. stackbtm   ds.b    4
  59.  
  60.  
  61.  
  62. ; some usefull macros:
  63.  
  64. callsys macro
  65.         CALLLIB _LVO\1
  66.         endm
  67.         
  68.         xdef        _XCEXIT                * exit(code) is standard way to leave C.
  69.         xdef        @_XCEXIT
  70.         xdef        __startup
  71.         
  72.         xref        LinkerDB        * linker defined base value
  73.         xref        _BSSBAS                * linker defined base of BSS
  74.         xref        _BSSLEN                * linker defined length of BSS
  75.         xref        __stack
  76.  
  77.        IFD          RESIDENT
  78.         xref        RESLEN
  79.         xref        RESBASE
  80.         xref        NEWDATAL
  81.        ENDC
  82.         
  83. *       library references
  84.  
  85.         section text,code
  86.  
  87.         xref    __main                  * Name of C program to start with.
  88.         xref    __fpinit                * initialize floating point
  89.         xref    __fpterm                * terminate floating point
  90.  
  91. __startup:
  92. start:
  93.         movem.l d1-d6/a0-a6,-(a7)       * save registers
  94.  
  95.         move.l  a0,a2                   * save command pointer
  96.         move.l  d0,d2                   * and command length
  97.         lea     LinkerDB,a4             * load base register
  98.         move.l  AbsExecBase.W,a6
  99.  
  100.  
  101.         IFND        RESIDENT
  102.         lea     _BSSBAS,a3              * get base of BSS
  103.         moveq   #0,d1
  104.         move.l  #_BSSLEN,d0             * get length of BSS in longwords
  105.         bra.s   clr_lp                  * and clear for length given
  106. clr_bss move.l  d1,(a3)+
  107. clr_lp  dbf     d0,clr_bss
  108.         move.l  a7,_StackPtr(A4)        * Save stack ptr
  109.         move.l  a6,SysBase(A4)
  110.  
  111. *------ get the size of the stack, if CLI use cli_DefaultStack
  112. *------                                 if WB use a7 - TC_SPLOWER
  113.         move.l        ThisTask(a6),A3
  114.         move.l        pr_CLI(A3),d0
  115.         beq.s         fromwb
  116.         lsl.l         #2,d0
  117.         move.l        d0,a0
  118.         move.l        cli_DefaultStack(a0),d0
  119.         lsl.l         #2,d0             * # longwords -> # bytes
  120.         bra.s         dostack
  121.  
  122. fromwb:
  123.         move.l        a7,d0                         
  124.         sub.l         TC_SPLOWER(a3),d0
  125. dostack:
  126.  
  127. *------ Set __base for stack checking
  128.         move.l       a7,d1
  129.         sub.l        d0,d1               * get top of stack
  130.         add.l        #128,D1             * allow for parms overflow
  131.         move.l       D1,__base(A4)       * save for stack checking
  132.         
  133.         cmp.l         __stack(a4),d0
  134.         bcc.s        nochange        
  135.  
  136. *-- current stack is not as big as __stack says it needs
  137. *-- to be. Allocate a new one.
  138.         move.l        __stack(a4),d0
  139.         add.l         #128,d0           * extra room
  140.         move.l        d0,newstacksize(a4)
  141.  
  142.         move.l        #MEMFLAGS,d1
  143.         callsys       AllocMem
  144.         tst.l         d0
  145.         beq.w         return
  146.         
  147.         move.l        d0,newstack(a4)
  148.         add.l         #128,d0           * extra room
  149.         move.l        d0,__base(a4)
  150.         
  151.         add.l         __stack(a4),d0
  152.         move.l        d0,d1
  153.         
  154. *-- If we're running under 2.0, call StackSwap to set up
  155. *-- the new stack. Otherwise, just jam the new value into
  156. *-- A7.        
  157.         cmpi.w        #36,$14(a6)
  158.         blt.s         no20
  159.  
  160.         move.l        d0,mystk_Pointer(a4)
  161.         move.l        d1,mystk_Upper(a4)
  162.         sub.l         newstacksize(a4),d1
  163.         lea           mystk_Lower(a4),a0
  164.         move.l        d1,(a0)
  165.         callsys       StackSwap
  166.         bra.s         nochange
  167.            
  168. no20:   move.l        d0,a7
  169.                 
  170. nochange:
  171.         ENDC
  172.  
  173.  
  174.  
  175.         IFD        RESIDENT
  176.         move.l        d2,-(a7)
  177.         movem.l       a0-a2,-(a7)
  178.  
  179. *------ get the size of the stack, if CLI use cli_DefaultStack
  180. *------                                 if WB use a7 - TC_SPLOWER
  181.         move.l        ThisTask(a6),A3
  182.         move.l        pr_CLI(A3),d1
  183.         beq.s         fromwb
  184.         lsl.l         #2,d1
  185.         move.l        d1,a0
  186.         move.l        cli_DefaultStack(a0),d1
  187.         lsl.l         #2,d1             * # longwords -> # bytes
  188.         bra.s         dostack
  189.  
  190. fromwb:
  191.         move.l        a7,d1                         
  192.         sub.l         TC_SPLOWER(a3),d1
  193. dostack:
  194.         moveq        #0,d2              * use d2 as flag for newstack or not
  195.         move.l       #RESLEN,d0
  196.         cmp.l        __stack(a4),d1     * This a4 is in the original 
  197.                                         * set of data
  198.         bcc.s        nochange        
  199.         move.l        __stack(a4),d1
  200.         add.l        d1,d0              * increase size of mem for new stack
  201.         moveq        #1,d2              * set flag
  202.                 
  203. nochange:
  204.         move.l        d1,a3             * save stacksize to set up stack checking
  205.         move.l        #MEMFLAGS,d1
  206.         callsys       AllocMem
  207.         tst.l         d0
  208.         bne.s         ok1
  209.         movem.l       (a7)+,d2/a0-a2
  210.         bra.w         return
  211.  
  212. ok1:    move.l        d0,a0
  213.         move.l        d0,a2             * a2 now has difference
  214.         
  215.         move.l        d0,a1
  216.         move.l        #NEWDATAL,d0
  217.         sub.l         #RESBASE,a4
  218.  
  219.                                         * copy data over
  220. cpy:    move.l        (a4)+,(a0)+
  221.         subq.l        #1,d0
  222.         bne.s         cpy
  223.  
  224.                                         * a4 now points at number of relocs
  225.         move.l        (a4)+,d0
  226. reloc:  beq.s         nreloc
  227.         move.l        a1,a0
  228.         add.l         (a4)+,a0          * a0 now has add of reloc
  229.         add.l         (a0),a2
  230.         move.l        a2,(a0) 
  231.         move.l        a1,a2             * restore offset
  232.         subq.l        #1,d0
  233.         bra.s         reloc
  234.         
  235. nreloc: move.l        a1,a4             * set up new base register
  236.         add.l         #RESBASE,a4
  237.  
  238.         move.l        #RESLEN,realdatasize(a4)
  239.         movem.l       (a7)+,a0-a2
  240.  
  241.         move.l        a6,SysBase(A4)
  242.         tst.b         d2
  243.         movem.l       (a7)+,d2          * restore d2 
  244.         movem.l       a7,_StackPtr(A4)  * Save stack ptr (movem doesn't
  245.                                         * change flags
  246.         beq.s         nochg2
  247.  
  248. *------ set up new stack
  249.         move.l       a4,d0
  250.         sub.l        #RESBASE,d0
  251.         add.l        #RESLEN,d0
  252.         add.l        __stack(a4),d0     * here a4 will be pointing at the
  253.                                         * new data, but __stack will be the
  254.                                         * same if all goes well
  255.         move.l       d0,d1             
  256.  
  257.  
  258. *-- If we're running under 2.0, call StackSwap to set up
  259. *-- the new stack. Otherwise, just jam the new value into
  260. *-- A7.        
  261.         cmpi.w        #36,$14(a6)
  262.         blt.s         no20a
  263.  
  264.         move.l        d0,mystk_Pointer(a4)
  265.         move.l        d1,mystk_Upper(a4)
  266.         sub.l         __stack(a4),d1
  267.         lea           mystk_Lower(a4),a0
  268.         move.l        d1,(a0)
  269.         callsys       StackSwap
  270.         bra.s         doneswap
  271.            
  272. no20a:  move.l        d0,a7
  273.                 
  274. doneswap:
  275.  
  276.         move.l       __stack(a4),d0
  277.         add.l        d0,realdatasize(a4) * need to know how much to free later
  278.  
  279. nochg2:
  280. *------ Set __base for stack checking
  281.         move.l       a7,d1
  282.         sub.l        a3,d1               * get top of stack
  283.         add.l        #128,D1             * allow for parms overflow
  284.         move.l       D1,__base(A4)       * save for stack checking
  285.  
  286.         ENDC
  287.  
  288.  
  289. *------ Save the current stack. We'll reset it to here to
  290. *------ Run the autoterminators.
  291.         move.l       a7,newst_Pointer(a4)
  292.         move.l       a7,newst_Upper(a4)
  293.         lea          newst_Lower(a4),a0
  294.         move.l       __base(a4),(a0)
  295.  
  296.         cmpi.w        #36,$14(a6)
  297.         blt.s         no20b
  298.         callsys       StackSwap
  299.  
  300. no20b:
  301.  
  302.         ifd     CATCH
  303.         move.w  AttnFlags(a6),Environment+2(a4) * save copy for dump
  304.         endc
  305.  
  306.  
  307.  
  308. clrwb:
  309.         clr.l        _WBenchMsg(A4)
  310.  
  311. *-----  clear any pending signals
  312.         moveq         #0,d0
  313.         move.l        #$00003000,d1
  314.         callsys       SetSignal
  315.         
  316.  
  317.         move.l        ThisTask(a6),A3
  318.  
  319.         ifd        CATCH
  320.         move.l        A3,TaskID(a4)
  321.  
  322. *------ initialize exception handler
  323. *------ Remember to preserve the old handler first
  324.         move.l        TC_TRAPDATA(a3),oldtrapdata(A4)
  325.         move.l        TC_TRAPCODE(a3),d0              ; check current exception
  326.         move.l        d0,oldtrapcode(A4)
  327.  
  328.         move.l        d0,a1
  329.         callsys TypeOfMem
  330.         tst.l d0
  331.         bne.s        1$                               * somebody else (debugger?) has vector
  332.  
  333.         move.l        #Exception,TC_TRAPCODE(a3)      * install pointers to code
  334.         move.l        a4,TC_TRAPDATA(a3)              * ...and data
  335. 1$:
  336.         ifd         AUTOREQ
  337. *------ attempt to open Intuition library:
  338.         bsr.w                openIntui
  339.         endc
  340.         endc
  341.  
  342.  
  343. *------ attempt to open DOS library:
  344.         lea           DOSName(PC),A1
  345.         moveq.l       #0,D0
  346.         callsys       OpenLibrary
  347.         move.l        D0,DOSBase(A4)
  348.         bne.s         ok2
  349.         moveq.l       #100,d0
  350.         bra.w         exit2
  351.  
  352. ok2:
  353.  
  354. *------ are we running as a son of Workbench?
  355.         move.l        pr_CurrentDir(A3),__curdir(A4)
  356.         tst.l         pr_CLI(A3)
  357.         beq.w         fromWorkbench
  358.         
  359. *=======================================================================
  360. *====== CLI Startup Code ===============================================
  361. *=======================================================================
  362. *
  363. * Entry: D2 = command length
  364. *        A2 = Command pointer
  365. fromCLI:
  366.         ifd        CATCH
  367.         moveq         #-1,d0
  368.         move.l        d0,Starter(a4)        * non-zero means CLI
  369.         move.l        a5,StackTop(a4)
  370.         endc
  371.  
  372. *------ find command name:
  373.         move.l      pr_CLI(a3),a0
  374.         add.l       a0,a0                   * bcpl pointer conversion
  375.         add.l       a0,a0
  376.         move.l      cli_CommandName(a0),a1
  377.  
  378.         IFD         CATCH 
  379.         IFND        AUTOREQ
  380.         move.l      cli_StandardOutput(a0),GConsole(a4)   * save output fh
  381.         ENDC
  382.         ENDC
  383.         
  384.         add.l       a1,a1                   * bcpl pointer conversion
  385.         add.l       a1,a1
  386.  
  387. *------ collect parameters:
  388.         move.l      d2,d0                   * get command line length
  389.         moveq.l     #0,d1
  390.         move.b      (a1)+,d1
  391.         move.l      a1,_ProgramName(A4)
  392.         add.l       d1,d0                   * add length of command name
  393.         addq.l      #7,d0                   * allow for space after command, quotes
  394.                                             * and null terminator, as well as 
  395.         andi.w      #$fffc,D0               * force to long word boundary
  396.         move.l      d0,Commandlen(a4)
  397.    
  398.         movem.l     d1/a1,-(a7)
  399.         move.l      #MEMFLAGS,d1
  400.         callsys     AllocMem
  401.         movem.l     (a7)+,d1/a1
  402.         tst.l       d0
  403.         bne.s       ok_copy
  404.    
  405.         moveq.l     #20,d0                  * what should the return code be for out of mem?
  406.         move.l      d0,-(a7)                * put a return code on the stack
  407.         beq.w       nodofree                * Was exitToDOS
  408.    
  409. ok_copy:
  410.         move.l      d0,a0
  411.         move.l      d0,Commandbuf(a4)
  412.          
  413. *------ copy command line into memory
  414.         move.l     d2,d0                    * get command line length
  415.         subq.l     #1,d0
  416.         add.l      d1,d2
  417.    
  418. copy_line:
  419.         move.b     0(A2,D0.W),2(A0,D2.W)    * copy command line to stack
  420.         subq.l     #1,d2
  421.         dbf        d0,copy_line
  422.         move.b     #' ',2(a0,d2.w)          * add space between command and parms
  423.         subq.l     #1,d2
  424.         move.b     #'"',2(a0,d2.w)          * add end quote
  425.    
  426. copy_cmd:
  427.         move.b     0(a1,d2.w),1(a0,d2.w)    * copy command name to stack
  428.         dbf        d2,copy_cmd
  429.         move.b     #'"',(a0)
  430.         move.l     A0,-(A7)                 * push command line address
  431.         bra.s      main                     * call C entrypoint
  432.  
  433. *=======================================================================
  434. *====== Workbench Startup Code =========================================
  435. *=======================================================================
  436.  
  437. fromWorkbench:
  438.  
  439.         ifd        CATCH
  440.         move.l     TC_SPUPPER(a3),StackTop(a4)  * set top of stack
  441.         endc
  442.  
  443.  
  444. *------ we are now set up.  wait for a message from our starter
  445.         lea        pr_MsgPort(A3),a0         * our process base
  446.         callsys    WaitPort
  447.         lea        pr_MsgPort(A3),a0         * our process base
  448.         callsys    GetMsg
  449.         move.l     d0,_WBenchMsg(a4)
  450.         move.l     d0,-(SP)
  451.  
  452.         move.l     d0,a2                     * get first argument
  453.         move.l     sm_ArgList(a2),d0
  454.         beq.s      do_main
  455.         move.l     DOSBase(a4),a6
  456.         move.l     d0,a0
  457.         move.l     wa_Lock(a0),d1
  458.         callsys    DupLock
  459.         move.l     d0,__curdir(A4)
  460.         move.l     d0,d1
  461.         callsys    CurrentDir
  462.  
  463. do_main:
  464.         move.l     _WBenchMsg(A4),a0         * get address of workbench message
  465.         move.l     a0,-(a7)                  * push argv
  466.         pea        NULL(a4)                  * push argc
  467.         move.l     sm_ArgList(a0),a0         * get address of arguments
  468.         move.l     wa_Name(a0),_ProgramName(A4) * get name of program
  469.  
  470. *=============================================
  471. *------ common code --------
  472. *=============================================
  473.  
  474. main    jsr        __fpinit(PC)              * Initialize floating point and constructors
  475.         tst.l      d0
  476.         bne.s      exit2
  477.         jsr        __main(PC)                * call C entrypoint
  478.         moveq.l    #0,d0                     * set successful status
  479.         bra.s      exit2
  480. *
  481.  
  482. XCEXIT:
  483. _XCEXIT:
  484.         move.l     4(SP),d0                  * extract return code
  485. @XCEXIT:
  486. @_XCEXIT:
  487. exit2:
  488.  
  489. *-- Save Return Code on the original stack
  490.         move.l     _StackPtr(a4),a2
  491.         move.l     d0,-(a2)
  492.  
  493. *-- Set the stack to the first NEW stack we allocated
  494. *-- So C++ destructors can run with a large stack if required
  495.         move.l     newst_Lower(a4),__base(a4)        
  496.         move.l     AbsExecBase.W,A6
  497.         subq.l     #4,newst_Pointer(a4)      * make room for the ret code  
  498.         cmpi.w     #36,$14(a6)
  499.         blt.s      noswap1
  500.         lea        newst_Lower(a4),a0
  501.         callsys    StackSwap
  502.         bra.b      swapdone
  503. noswap1:
  504.         move.l     newst_Pointer(a4),a7
  505. swapdone:        
  506.         move.l     _ONEXIT(A4),d0            * exit trap function?
  507.         beq.s      exit3
  508.         move.l     d0,a0
  509.         jsr        (a0)
  510. exit3:
  511.         jsr        __fpterm(PC)              * clean up any floating point
  512.  
  513.  
  514. *-- Swap back to original stack
  515. *-- If we're running under 2.0, call StackSwap
  516. *-- Otherwise, just jam the new value into a7
  517.         move.l     AbsExecBase.W,A6
  518.         cmpi.w     #36,$14(a6)
  519.         blt.s      noswap
  520.         tst.l      mystk_Lower(a4)
  521.         beq.s      noswap
  522.  
  523.         lea        mystk_Lower(a4),a0
  524.         subq.l     #4,mystk_Pointer(a4)      * make room for the ret code  
  525.         callsys    StackSwap
  526.            
  527. noswap:  
  528.         movea.l    a2,a7                     * restore stack ptr
  529.  
  530.  
  531.         ifnd       RESIDENT
  532. *------ free the stack if we allocated one
  533.         move.l     newstacksize(a4),d0
  534.         beq.s      exit4
  535.         move.l     newstack(a4),a1
  536.         move.l     AbsExecBase.W,A6
  537.         callsys    FreeMem
  538.         endc
  539.  
  540. exit4:
  541. *------ if we ran from CLI, skip workbench cleanup:
  542.         tst.l      _WBenchMsg(A4)
  543.         beq.s      exitToDOS
  544.         move.l     DOSBase(A4),a6
  545.         move.l     __curdir(a4),d1
  546.         beq.s      done_5
  547.         callsys    UnLock
  548. done_5:
  549. *------ return the startup message to our parent
  550. *       we forbid so workbench can't UnLoadSeg() us
  551. *       before we are done:
  552.         move.l     AbsExecBase.W,A6
  553.         callsys    Forbid
  554.         move.l     _WBenchMsg(a4),a1
  555.         callsys    ReplyMsg
  556.         bra.s      nodofree
  557.  
  558. exitToDOS:
  559.         move.l     AbsExecBase.W,a6
  560.  
  561. *------ Restore the original exception handler
  562.         ifd    CATCH
  563.         move.l        ThisTask(a6),A3
  564.         move.l        oldtrapdata(A4),TC_TRAPDATA(a3)
  565.         move.l        oldtrapcode(A4),TC_TRAPCODE(a3) * check current exception
  566.          ifd         AUTOREQ
  567.           move.l        IntuiBase(a4),a1
  568.           callsys         CloseLibrary                * close Intuition library
  569.          endc
  570.         ENDC
  571.  
  572. *------ free the command line buffer
  573.         move.l     Commandlen(a4),d0
  574.         beq.s      nodofree
  575.         move.l     Commandbuf(a4),a1
  576.         callsys    FreeMem
  577.    
  578. *------ this rts sends us back to DOS:
  579. nodofree:
  580.         move.l     DOSBase(A4),a1
  581.         callsys    CloseLibrary              * close Dos library
  582.  
  583.         IFD        RESIDENT
  584.         move.l     realdatasize(a4),d0
  585.         move.l     a4,a1
  586.         sub.l      #RESBASE,a1
  587.         callsys    FreeMem
  588.         ENDC
  589.         move.l     (a7)+,d0
  590.  
  591. return:        
  592.         movem.l    (a7)+,d1-d6/a0-a6
  593.         rts
  594.  
  595. DOSName dc.b    'dos.library',0
  596.  
  597.         ifd        CATCH
  598. *-----------------------------------------------------------------------
  599. *        Open the Intuition library:
  600.  
  601. openIntui:
  602.         lea        IntuiName(PC),A1
  603.         moveq.l    #0,D0
  604.         callsys    OpenLibrary
  605.         move.l     D0,IntuiBase(A4)
  606.         beq.s      noDOS
  607.         rts
  608.  
  609. *-----------------------------------------------------------------------
  610. noDOS:
  611.         moveq.l #100,d0
  612.         bra.w    exit2
  613.  
  614.  
  615. IntuiName  dc.b        'intuition.library',0
  616.  
  617. *-----------------------------------------------------------------------
  618. *        The Exception Handler - catches GURUs and exits (semi)cleanly
  619. Exception:
  620.         movem.l    a0,-(a7)
  621.         move.l     AbsExecBase.W,a0
  622.         move.l     ThisTask(a0),a0
  623.         move.l     TC_TRAPDATA(a0),a0        * ...and data
  624.         move.l     (sp)+,ADump(a0)           * save a0
  625.         move.l     d0,ADump+4(a0)            * and d0
  626.  
  627.         move.l     (a7)+,d0                  * get exception # from stack
  628.         move.l     d0,GURUNum(a0)            * and save it
  629.         cmpi.l     #3,d0                     * ADDRESS or BUS error?
  630.         bgt.s      1$                        * no, skip adjustment
  631.         btst       #0,Environment+3(a0)      * is it 68010 or 68020?
  632.         bne.s      1$                        * 0 means NO
  633.         addq.l     #8,a7                     * adjust for 68000
  634. 1$:
  635.         move.l     2(a7),d0                  * get PC at crash
  636.         move.l     d0,GURUAddr(a0)           * and save it
  637.         move.l     ADump+4(a0),d0            * restore a0 and d0
  638.         move.l     ADump(a0),a0
  639.         move.l     #GURUExit,2(a7)           * use our own exit point
  640.         rte
  641.         
  642. *-----------------------------------------------------------------------
  643. *        The Exception exit routine - write 'PGTB' IFF chunk to file
  644. *        'SnapShot.TB' in current directory, then exit to system.
  645.  
  646. GURUExit:
  647.         movem.l    d0-d7/a0-a7,-(sp)         * save all registers
  648.         move.l     AbsExecBase.W,a6          * make sure we are working with Exec
  649.         callsys    GetCC                     * safe way - works with all CPUs
  650.         move.l     ThisTask(a6),a3
  651.         move.l     TC_TRAPDATA(a3),a4        * make sure we have a valid # in a4
  652.         move.l     d0,Flags(a4)              * save area
  653.         movem.l    (sp)+,d0-d7
  654.         movem.l    d0-d7,DDump(a4)           * save data reg contents
  655.         movem.l    (sp)+,d0-d7
  656.         movem.l    d0-d7,ADump(a4)           * save address reg contents
  657.         tst.l      StackPtr(a4)              * if there's something there
  658.         bne        GExit1                    * ...we've been here before!
  659.         lea        TempStore(a4),a0          * calculate addr of TempStore
  660.         move.l     a0,TempAddr(a4)           * ...and save for later access
  661.         move.l     A7Store(a4),d0            * make sure we have proper TOS
  662.         move.l     d0,StackPtr(a4)           * ...and save it
  663.         moveq      #0,d0
  664.         move.l     _ProgramName(a4),a0       * find length of program name
  665.  
  666.         ifd        AUTOREQ
  667.         move.l     a0,PName(a4)
  668.         endc
  669.  
  670.         subq.l     #1,a0
  671.         move.b     (a0),d0
  672.         addq.l     #4,d0                     * adjust for shift
  673.         lsr.l      #2,d0
  674.         move.l     d0,NameLen(a4)            * store length
  675.         add.l      d0,FAILlen(a4)            * and sub-chunk total
  676.  
  677.         moveq      #0,d0                     * clear d0 for use
  678.         lea        VBlankFrequency(a6),a0    * set up a0 to find correct data
  679.         move.b     (a0)+,d0                  * get just in case
  680.         move.l     d0,VBlankFreq(a4)         * ...so we can figure what
  681.         move.b     (a0),d0                   * ...type of machine
  682.         move.l     d0,PowerSupFreq(a4)       * ...we're working on
  683.  
  684.         lea        start-4(pc),a0            * get seglist ptr
  685.         moveq      #-1,d0                    * always at least 1
  686. 2$:
  687.         addq.l     #1,d0
  688.         move.l     (a0),d1                   * find end of list
  689.         beq.s      3$
  690.         lsl.l      #2,d1                     * BPTR!!!!!
  691.         move.l     d1,a0
  692.         bra.s      2$
  693. 3$:
  694.         add.l      d0,SegCount(a4)           * store # of seglist pointers
  695.         lsl.l      #1,d0                     * multiply by 2 for longword count
  696.         add.l      d0,FAILlen(a4)            * and sub-chunk length
  697.  
  698.         move.l     StackTop(a4),d0           * get top of stack
  699.         sub.l      StackPtr(a4),d0           * find number of bytes used
  700.         addq.l     #4,d0                     * adjust for longword conversion
  701.         lsr.l      #2,d0                     * convert from bytes to long
  702.         move.l     d0,StackLen(a4)           * and save
  703.         add.l      d0,s2len(a4)              * and sub-chunk total
  704.  
  705.         move.l     a5,-(sp)                  * save a5 for later
  706.         callsys    Forbid                    * don't let 'em change while we ask
  707.         move.l     MemList+LH_HEAD(a6),d0    * first node in MemList
  708. checkchip:
  709.         move.l     d0,a5                     * move node address to address reg
  710.         move.w     MH_ATTRIBUTES(a5),d4      * get node attributes
  711.         btst       #MEMB_CHIP,d4             * is it chip?
  712.         beq.s      checkfast                 * no, go on
  713.         lea        chipAvail(a4),a3
  714.         bsr.w      AddIt
  715. checkfast:
  716.         btst       #MEMB_FAST,d4             * is it fast?
  717.         beq.s      next                      * no, go on
  718.         lea        fastAvail(a4),a3
  719.         bsr.w      AddIt
  720. next:
  721.         move.l     LN_SUCC(a5),d0            * get address of next node
  722.         bne.s      checkchip                 * ...and loop back if valid
  723.         callsys    Permit                    * allow others access again
  724.         move.l     #MEMF_CHIP+MEMF_LARGEST,d1 * to find largest hunk in chip ram
  725.         callsys    AvailMem
  726.         move.l     d0,chipLargest(a4)         * store
  727.         move.l     #MEMF_FAST+MEMF_LARGEST,d1 * to find largest hunk in fast ram
  728.         callsys    AvailMem
  729.         move.l     d0,fastLargest(a4)        * store
  730.         move.l     (sp)+,a5                  * and restore a5
  731.  
  732.         ifd        AUTOREQ
  733.         moveq      #0,d0                     * PosFlag
  734.         move.l     d0,d1                     * NegFlag
  735.         move.l     d0,a0                     * 0 means use current window
  736.         lea        IText1(a4),a1             * Body Text
  737.         lea        IText5(a4),a2             * Positive Gadget Text
  738.         lea        IText6(a4),a3             * Negative Gadget Text
  739.         moveq      #1,d2
  740.         lsl.l      #8,d2                     * quick way to set Width
  741.         moveq      #76,d3                    * Height
  742.         move.l     IntuiBase(a4),a6          * get intuition library pointer
  743.         jsr        -$15c(A6)                 * callsys       AutoRequest
  744.         move.l     AbsExecBase.W,a6
  745.         tst.l      d0                        * save SnapShot?
  746.         beq.w      GExit2                    * no, just exit
  747.         endc
  748.  
  749.         move.l     DOSBase(a4),a6
  750.         lea        DumpName(a4),a0           * get name of output file
  751.         move.l     a0,d1
  752.         move.l     #MODE_NEWFILE,d2          * create new file
  753.         callsys    Open 
  754.         bne.s      4$
  755.         lea        DumpPath(a4),a0           * if error in current dir, try DF1:
  756.         move.l     a0,d1
  757.         move.l     #MODE_NEWFILE,d2
  758.         callsys    Open
  759.         bne.s      4$
  760.         move.b     #'0',DumpPath+2(a4)       * still error?  Try DF0:
  761.         lea        DumpPath(a4),a0
  762.         move.l     a0,d1
  763.         move.l     #MODE_NEWFILE,d2
  764.         callsys    Open
  765.  
  766.         ifnd        AUTOREQ
  767.         bne.s      4$                        * if no error, continue (finally!)
  768.         move.l     GConsole(a4),d1
  769.         beq.w      GExit2
  770.         lea        failmsg(a4),a0
  771.         move.l     a0,d2
  772.         move.l     #23,d3
  773.         callsys    Write
  774.         endc
  775.  
  776.         bra.w      GExit2                    * else, print msg & DIE gracefully
  777. 4$:
  778.         move.l     d0,d5                     * save file handle for Write
  779.         move.l     d0,fp(a4)                 * ...and in a safe place for later
  780.         move.l     d5,d1                     * get file handle
  781.         lea        PGTB(a4),a0               * first part of fixed
  782.         move.l     a0,d2
  783.         move.l     #chunk_len_1,d3           * length of first
  784.         callsys    Write                     * ...since it gets written over
  785.  
  786.         move.l     d5,d1                     * get file handle
  787.         move.l     _ProgramName(a4),d2       * get address of program name
  788.         move.l     NameLen(a4),d3            * get # longs in program name
  789.         lsl.l      #2,d3                     * ..and convert to bytes
  790.         callsys    Write
  791.  
  792.         move.l     d5,d1                     * get file handle
  793.         lea        Environment(a4),a0        * second part of fixed
  794.         move.l     a0,d2
  795.         move.l     #chunk_len_2,d3           * length of second part
  796.         callsys    Write
  797.  
  798.         lea        start-8(pc),a0            * address of seglist (size of seg)
  799.         move.l     (a0)+,d0                  * segsize
  800.         move.l     d0,TempStore+4(a4)        * save it
  801.         move.l     a0,TempStore(a4)          * store first number
  802.         move.l     SegCount(a4),d4
  803. 5$:
  804.         move.l     d5,d1                     * get file handle
  805.         move.l     TempAddr(a4),d2           * address of write buffer
  806.         moveq      #TempSize,d3              * size of segment pointer
  807.         callsys    Write
  808.         move.l     TempStore(a4),a0          * retrieve pointer
  809.         move.l     (a0),d0                   * get next seg pointer
  810.         lsl.l      #2,d0                     * adjust
  811.         move.l     d0,TempStore(a4)          * ..and save
  812.         move.l     d0,a0
  813.         beq.b      donesegs                  * last segment?
  814.         move.l     -4(a0),d0                 * get segsize
  815.         move.l     d0,TempStore+4(a4)        * ...and save it
  816.         subq.l     #1,d4                     * done yet?
  817.         bne.s      5$                        * no, do next
  818.  
  819. donesegs:
  820.         tst.l      _FMEM(a4)                 * do they want memory reported?
  821.         beq.s      55$                       * no, forget it
  822.         move.l     d5,d1
  823.         lea        subFMEM(a4),a0
  824.         move.l     a0,d2
  825.         move.l     #FMEMlen,d3
  826.         callsys    Write
  827.  
  828. 55$:
  829.         move.l     d5,d1                     * (get the idea?)
  830.         lea        subREGS(a4),a0            * third part of fixed
  831.         move.l     a0,d2
  832.         move.l     #chunk_len_3,d3           * length of third
  833.         callsys    Write
  834.  
  835.         move.l     StackLen(a4),d0           * get length of stack used
  836.         cmpi.l     #2048,d0                  * > 8k ?
  837.         bgt.s      6$                        * yes, dump two chunks
  838.         move.l     d5,d1
  839.         lea        STAK2(a4),a0              * whole stack chunk
  840.         move.l     a0,d2
  841.         moveq      #STAK2len,d3              * length of fixed part
  842.         callsys    Write
  843.  
  844.         move.l     d5,d1
  845.         move.l     StackPtr(a4),d2           * address of stack
  846.         move.l     StackLen(a4),d3           * get # longwords on stack
  847.         lsl.l      #2,d3                     * ..and convert to bytes
  848.         callsys    Write
  849.         bra.s      7$
  850. 6$:
  851.         move.l     d5,d1
  852.         lea        STAK3(a4),a0              * top4k chunk
  853.         move.l     a0,d2
  854.         moveq      #STAK3len,d3              * length of fixed part
  855.         callsys    Write
  856.  
  857.         move.l     d5,d1
  858.         move.l     StackTop(a4),d2           * find top of stack
  859.         sub.l      #4096,d2                  * find top-4k
  860.         move.l     #4096,d3                  * # bytes to write
  861.         callsys    Write
  862.  
  863.         move.l     d5,d1
  864.         lea        STAK4(a4),a0              * bottom4k chunk
  865.         move.l     a0,d2
  866.         moveq      #STAK4len,d3              * length of fixed part
  867.         callsys    Write
  868.  
  869.         move.l     d5,d1
  870.         move.l     StackPtr(a4),d2           * current stack address
  871.         move.l     #4096,d3                  * # bytes to write
  872.         callsys    Write
  873. 7$:
  874.         move.l     _STAKOffset(a4),d3
  875.         beq.s      8$
  876.         lsr.l      #2,d3
  877.         addq.l     #1,d3
  878.         move.l     d3,_STAKOffset(a4)
  879.         addq.l     #1,d3
  880.         move.l     d5,d1
  881.         lea        STAK5(a4),a0
  882.         move.l     a0,d2
  883.         moveq      #STAK5len,d3
  884.         callsys    Write
  885.  
  886.         move.l     d5,d1
  887.         move.l     StackPtr(a4),d2
  888.         move.l     _STAKOffset(a4),d3
  889.         subq.l     #1,d3
  890.         move.l     StackLen(a4),d4
  891.         cmp.l      d3,d4
  892.         bge.s      75$
  893.         move.l     StackLen(a4),d3
  894. 75$:
  895.         lsl.l      #2,d3
  896.         callsys    Write
  897. 8$:
  898.         tst.l      _ONGURU(A4)               * user GURU function?
  899.         beq.s      9$
  900.         move.l     d5,-(sp)
  901.         move.l     d5,d1
  902.         lea        UDAT(a4),a0
  903.         move.l     a0,d2
  904.         move.l     #UDATlen,d3
  905.         callsys    Write
  906.         move.l     d5,d1
  907.         moveq      #0,d2                     * zero offset
  908.         moveq      #1,d3                     * ...from EOF
  909.         callsys    Seek
  910.         move.l     d0,SeekStore(a4)
  911.         move.l     _ONGURU(a4),a0
  912.         jsr        (a0)
  913.         addq.l     #4,sp
  914. 9$:
  915.         move.l     fp(a4),d5
  916.         move.l     d5,d1
  917.         moveq      #0,d2                     * offset from EOF
  918.         moveq      #1,d3                     * OFFSET_END
  919.         callsys    Seek                      * Seek returns OLD position
  920.         move.l     d0,d1
  921.         andi.l     #3,d1                     * did user write even longwords?
  922.         beq.s      10$                       * Yep!        Nice Human.
  923.         move.l     d1,d6                     * Nope, save for later.
  924.         clr.l      TempStore(a4)             * clear temp storage
  925.         move.l     d5,d1
  926.         move.l     TempAddr(a4),d2
  927.         moveq      #4,d3
  928.         sub.l      d6,d3                     * find how many NULLs to pad
  929.         callsys    Write
  930.         bra.s      9$
  931. 10$:
  932.         tst.l      SeekStore(a4)             * did we write UDAT?
  933.         beq.s      11$                       * nope!
  934.         sub.l      SeekStore(a4),d0          * find length of UDAT section
  935.         lsr.l      #2,d0                     * adjust to longwords
  936.         move.l     d0,TempStore(a4)          * save UDAT length for write
  937.         move.l     d5,d1
  938.         move.l     SeekStore(a4),d2          * find where to write it
  939.         subq.l     #4,d2
  940.         moveq      #-1,d3                    * OFFSET_BEGINNING
  941.         callsys    Seek
  942.         move.l     d5,d1
  943.         move.l     TempAddr(a4),d2
  944.         move.l     #4,d3
  945.         callsys    Write                     * write length of UDAT field to file
  946. 11$:
  947.         move.l     d5,d1
  948.         moveq      #0,d2                     * offset to 'Length' field
  949.         moveq      #1,d3                     * OFFSET_END
  950.         callsys    Seek                      * make sure we are at end of file
  951.         move.l     d5,d1
  952.         moveq      #4,d2                     * offset to 'Length' field
  953.         moveq      #-1,d3                    * OFFSET_BEGINNING
  954.         callsys    Seek
  955.         subq.l     #8,d0                     * adjust total length
  956.         lsr.l      #2,d0                     * adjust to longwords
  957.         move.l     d0,TempStore(a4)          * save for write
  958.         move.l     d5,d1
  959.         move.l     TempAddr(a4),d2
  960.         move.l     #4,d3
  961.         callsys    Write                     * write 'Length' field
  962. GExit1:
  963.         move.l     fp(a4),d1
  964.         beq.s      GExit2
  965.         move.l     DOSBase(a4),a6
  966.         callsys    Close
  967.  
  968.         ifnd        AUTOREQ
  969.         move.l      GConsole(a4),d1
  970.         beq.s       GExit2
  971.         lea         success(a4),a0
  972.         move.l      a0,d2
  973.         move.l      #32,d3
  974.         callsys     Write
  975.         endc
  976.         
  977. GExit2:
  978.         move.l       TaskID(a4),a6
  979.         move.l       AbsExecBase.W,a6
  980.         moveq        #$47,d0
  981.         bra.w        exit2
  982.  
  983. *-----------------------------------------------------------------------
  984. * AddIt:        routine to add memory parts to variables
  985.  
  986. AddIt:
  987.         move.l       MH_FREE(a5),d0
  988.         add.l        d0,(a3)                 * add to available
  989.         move.l       MH_UPPER(a5),d0
  990.         sub.l        MH_LOWER(a5),d0
  991.         add.l        d0,4(a3)                * add to Max section
  992.         rts
  993.         endc
  994.  
  995.  
  996.         IFD     CATCH
  997.         section __MERGED,DATA
  998. _ONGURU        dc.l        0
  999. IntuiBase      dc.l        0
  1000. TaskID         dc.l        0
  1001. oldtrapcode    dc.l        0
  1002. oldtrapdata    dc.l        0
  1003.  
  1004.         ifnd        AUTOREQ
  1005. GConsole        dc.l        0
  1006. failmsg         dc.b        7,'Can''t write SnapShot!',10
  1007. success         dc.b        7,'GURU caught; SnapShot written!',10
  1008.         endc
  1009.  
  1010.         cnop        0,4
  1011. _FMEM           dc.l        0
  1012. fp              dc.l        0                  * save SnapShot file pointer
  1013. DumpPath        dc.b        'DF1:'
  1014. DumpName        dc.b        'SnapShot.TB',0
  1015. SeekStore       dc.l        0
  1016. TempAddr        dc.l        0                  * Storage for &TempStore
  1017. TempStore       dc.l        0,0                * Temporary storage for BPTR -> APTR
  1018. TempSize        equ        *-TempStore
  1019.  
  1020.         cnop        0,4
  1021.         ifd        AUTOREQ
  1022. TAttr:                                         * Text attributes for font
  1023.         dc.l        TName                      * name of font
  1024.         dc.w        TOPAZ_EIGHTY               * font size
  1025.         dc.b        FS_NORMAL                  * font style
  1026.         dc.b        FPF_ROMFONT                * font preferences
  1027. TName:
  1028.         dc.b        'topaz.font',0
  1029.         cnop        0,4
  1030.  
  1031. IText1:                                        * Text definitions for AutoReq call
  1032.         dc.b        3,0,RP_JAM1,0              * front & back pens, drawmode and filler byte
  1033.         dc.w        6,4                        * XY origin relative to container TopLeft
  1034.         dc.l        TAttr                      * font pointer or NULL for default
  1035.         dc.l        ITextText1                 * pointer to text
  1036.         dc.l        IText2                     * next IntuiText structure
  1037. ITextText1:
  1038.         dc.b        'Program:',0
  1039.         cnop 0,4
  1040. IText2:
  1041.         dc.b        3,0,RP_JAM1,0
  1042.         dc.w        78,4
  1043.         dc.l        TAttr
  1044. PName   dc.l        0
  1045.         dc.l        IText3
  1046.         cnop        0,4
  1047. IText3:
  1048.         dc.b        3,0,RP_JAM1,0
  1049.         dc.w        55,16
  1050.         dc.l        TAttr
  1051.         dc.l        ITextText3
  1052.         dc.l        IText4
  1053. ITextText3:
  1054.         dc.b        'I caught a GURU!',0
  1055.         cnop 0,4
  1056. IText4:
  1057.         dc.b        3,0,RP_JAM1,0
  1058.         dc.w        20,28
  1059.         dc.l        TAttr
  1060.         dc.l        ITextText4
  1061.         dc.l        0
  1062. ITextText4:
  1063.         dc.b        'Should I make a SnapShot?',0
  1064.         cnop 0,4
  1065. IText5:
  1066.         dc.b        3,0,RP_JAM2,0
  1067.         dc.w        6,3
  1068.         dc.l        TAttr
  1069.         dc.l        ITextText5
  1070.         dc.l        0
  1071. ITextText5:
  1072.         dc.b        'YES',0
  1073.         cnop 0,4
  1074. IText6:
  1075.         dc.b        3,0,RP_JAM2,0
  1076.         dc.w        6,3
  1077.         dc.l        TAttr
  1078.         dc.l        ITextText6
  1079.         dc.l        0
  1080. ITextText6:
  1081.         dc.b        'NO',0
  1082.         endc
  1083.  
  1084.         cnop 0,4
  1085.  
  1086. *--------------------------------------------------------------------------
  1087. * New IFF chunk format -
  1088. *        PGTB = Program Traceback, header for chunk
  1089. *        FAIL = reason for and environment of crash
  1090. *        REGS = registers at time of crash, including PC and CCR
  1091. *        VERS = version, revision, name of this program
  1092. *        STAK = ENTIRE stack at time of crash or, alternately,
  1093. *                the top and bottom 4k if the stack used is > 8k
  1094. *        UDAT = optional user data dump (if _ONGURU is set to a
  1095. *                function pointer in the user's program)
  1096. *--------------------------------------------------------------------------
  1097.  
  1098. PGTB            dc.b        'PGTB'
  1099. Length          dc.l        0                * length of chunk (in longwords)
  1100.  
  1101. subFAIL         dc.b        'FAIL'
  1102. FAILlen         dc.l        9
  1103. NameLen         dc.l        0                * length of program name
  1104. chunk_len_1     equ         *-PGTB
  1105. Environment     dc.l        0                * CPU (, Math)
  1106. VBlankFreq      dc.l        0                *        PAL = 50, NTSC = 60 (approx.)
  1107. PowerSupFreq    dc.l        0                * Europe = 50,        USA = 60 (approx.)
  1108. Starter         dc.l        0                * 0 = WB, -1 = CLI
  1109. GURUNum         dc.l        0                * cause of crash (GURU #)
  1110. SegCount        dc.l        1                * # hunks in seglist
  1111. chunk_len_2     equ         *-Environment
  1112.  
  1113. subFMEM         dc.b        'FMEM'           * FMEM - free memory at crash
  1114.                 dc.l        6
  1115. chipAvail       dc.l        0                * available chip memory
  1116. chipMax         dc.l        0                *        maximum chip memory
  1117. chipLargest     dc.l        0                *        largest chip memory
  1118. fastAvail       dc.l        0                * available fast memory
  1119. fastMax         dc.l        0                *        maximum fast memory
  1120. fastLargest     dc.l        0                *        largest fast memory
  1121. FMEMlen         equ         *-subFMEM
  1122.  
  1123. subREGS         dc.b        'REGS'           * REGS - register storage field
  1124. REGSlen         dc.l        18
  1125. GURUAddr        dc.l        0                * PC at time of crash
  1126. Flags           dc.l        0                * Condition Code Register (CCR)
  1127. DDump           dc.l        0,0,0,0,0,0,0,0  * data registers
  1128. ADump           dc.l        0,0,0,0,0,0,0    * address registers
  1129. A7Store         dc.l        0
  1130.  
  1131. subVERS         dc.b        'VERS'           * VERS - program version field
  1132.                 dc.l        6
  1133.                 dc.l        VERSION          * version #
  1134.                 dc.l        REVISION         * revision #
  1135.                 dc.l        3                * length of name of program
  1136.                 IFD        RESIDENT
  1137.                 dc.b        'catchres.o',0,0 * name
  1138.                 ENDC
  1139.                 IFND        RESIDENT
  1140.                 dc.b        'catch.o   ',0,0 * name
  1141.                 ENDC
  1142.  
  1143. subSTAK         dc.b        'STAK'           * STAK - stack field
  1144. STAKlen         dc.l        4
  1145. Type            dc.l        0                * 0 = Info
  1146. StackTop        dc.l        0                * top of stack pointer
  1147. StackPtr        dc.l        0                * current Stack Pointer
  1148. StackLen        dc.l        0                * # bytes used on stack
  1149. chunk_len_3     equ         *-subREGS
  1150.  
  1151. STAK2           dc.b        'STAK'
  1152. s2len           dc.l        1                * length of subtype
  1153.                 dc.l        1                * 1 = whole stack
  1154. STAK2len        equ         *-STAK2
  1155.  
  1156. STAK3           dc.b        'STAK'
  1157.                 dc.l        1025
  1158.                 dc.l        2                * 2 = top 4k of stack
  1159. STAK3len        equ         *-STAK3
  1160.  
  1161. STAK4           dc.b        'STAK'
  1162.                 dc.l        1025
  1163.                 dc.l        3                * 3 = bottom 4k of stack
  1164. STAK4len        equ         *-STAK4
  1165.  
  1166. STAK5           dc.b        'STAK'
  1167. _STAKOffset     dc.l        0
  1168.                 dc.l        4                * 4 = user defined amount
  1169. STAK5len        equ         *-STAK5
  1170.  
  1171. UDAT            dc.b        'UDAT'
  1172.                 dc.l        0
  1173. UDATlen         equ         *-UDAT
  1174.         endc
  1175.  
  1176.  
  1177.  
  1178.         section __MERGED,BSS
  1179.  
  1180.         xdef    NULL,SysBase,DOSBase
  1181.     xref    _FPERR
  1182.  
  1183.         xref    _WBenchMsg
  1184.         xref    __curdir
  1185.         xref    _OSERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  1186.         xref    _SIGINT
  1187.         xref    _ProgramName,_StackPtr,__base
  1188.  
  1189.         ifd        CATCH
  1190.         xdef        _ONGURU,_FMEM,_STAKOffset
  1191.         endc
  1192.  
  1193.  
  1194.         
  1195. NULL          ds.b    4        
  1196. DOSBase       ds.b    4
  1197. SysBase       ds.b    4
  1198. Commandbuf    ds.b    4
  1199. Commandlen    ds.b    4
  1200. mystk_Lower   ds.b    4
  1201. mystk_Upper   ds.b    4
  1202. mystk_Pointer ds.b    4
  1203. newst_Lower   ds.b    4
  1204. newst_Upper   ds.b    4
  1205. newst_Pointer ds.b    4
  1206.  
  1207.  
  1208.  
  1209.         ifd        RESIDENT
  1210. realdatasize ds.b    4                   * size of memory allocated for data +
  1211.                                          * possible stack
  1212.         endc
  1213.         ifnd       RESIDENT
  1214. newstack     ds.b    4                   * pointer to new stack (if needed)
  1215. newstacksize ds.b    4                   * size of new stack
  1216.         endc
  1217.  
  1218.              END
  1219.