home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / utility / break / break.asm next >
Assembly Source File  |  1989-03-28  |  12KB  |  252 lines

  1. ******************************************************************************
  2. *                                                                            *
  3. *    break.asm  version 1.0 of 20 August 1988   (C) L.J.M. de Wit 1988       *
  4. *                                                                            *
  5. * This software may be used and distributed freely if not used commercially  *
  6. * and the originator (me) is mentioned.                                      *
  7. *                                                                            *
  8. ******************************************************************************
  9. *
  10. * NAME
  11. *    break - stop current program on receipt of interrupt character
  12. *
  13. * SYNTAX
  14. *    break [-e|-d|-z] [-i|-c<code>]
  15. *
  16. * DESCRIPTION
  17. *
  18. *    After installing break, any program can be interrupted.
  19. *    This is achieved by 'extending' the existing keyboard interrupt
  20. *    routine: after executing the old code the break character check
  21. *    is done.
  22. *
  23. *    The various flags have the following meaning:
  24. *       e(nable) : the current break character will end the program.
  25. *                  the code returned is -32, what seems to be the standard
  26. *                  value for programs interrupted by ^C in GEMDOS.
  27. *       d(isable): no actions are done; this restores the old behaviour
  28. *       z(ero)   : the current break character will be discarded (made 0)
  29. *                  in the input buffer; this can be used to disable ^C.
  30. *       i(nput)  : the break character is prompted for. Combinations with
  31. *                  shift, control and alternate keys are also allowed.
  32. *                  Useful for specifying the break character interactively.
  33. *       c(ode)   : specifies the break character as a hexadecimal code.
  34. *                  The hex code must follow the 'c' flag immediately.
  35. *                  Useful for specifying the break character from a script.
  36. *    Of the flags e,d and z only one should be used; e is the default.
  37. *    Also, of the flags i and c only one should be used; control-delete is
  38. *    the default. This is done on purpose; you can always change it to ^C
  39. *    if you want to (or whatever key you like).
  40. *     
  41. *    The break program can be reused indefinitely, because a next invocation
  42. *    is not made memory resident; it only modifies parameters in the first
  43. *    invocation (the resident one).
  44. *
  45. *    The program can be placed into the \AUTO folder to be installed
  46. *    automatically, or activated 'by hand'. If placed in the \AUTO folder, it
  47. *    should of course have a .PRG extension (break.prg); as \AUTO folder
  48. *    programs don't get arguments, the break will be enabled and the break
  49. *    character is control-delete in this case.
  50. *
  51. * BUGS/SHORTCOMINGS
  52. *    A nice extension would be the possibility to catch the interrupt from
  53. *    a user program; this could be achieved by using a new trap. As this
  54. *    implies restoring the old interrupt catch routine when the program
  55. *    exits, and maybe also core dumps could be added to the action of an
  56. *    (other) interrupt character, such a more general signal mechanism is
  57. *    not added (yet). Gives me time to think of a nice implementation 8-).
  58. *
  59. * JOKE
  60. *    Gimme a break, huh?!
  61. *
  62.  
  63.       module  break
  64.       section s.ccode
  65.  
  66. * character codes
  67. tab      equ   9
  68. lf       equ   10
  69. cr       equ   13
  70.  
  71. * GEMDOS & (X)BIOS stuff
  72. gemdos   equ   1
  73. bios     equ   13
  74. xbios    equ   14
  75. ptermres equ   $31
  76. setexc   equ   5
  77. cconws   equ   9
  78. crawcin  equ   7
  79. super    equ   $20
  80. pterm0   equ   0
  81. pterm    equ   $4c
  82. iorec    equ   14
  83.  
  84. * divers
  85. bpaglen  equ   $100
  86. textlen  equ   12
  87. datalen  equ   20
  88. bsslen   equ   28
  89. intrupt  equ   -32               * Code returned by interrupted programs
  90. curproc  equ   $602c             * Contains base page start of current process
  91.  
  92. * iorec struct offsets; the buffer ptr. itself has offset 0
  93. ibufsize equ 4
  94. ibufhead equ 6
  95. ibuftl   equ 8
  96. ibuflow  equ 10
  97. ibufhi   equ 12
  98.  
  99.  
  100. brkinit
  101.       move.l   4(sp),a0
  102.       adda.w   #$80,a0           * a0 points to argument string start
  103.       moveq.l  #0,d0
  104.       move.b   (a0)+,d0          * Get string length &
  105.       clr.b    (a0,d0.w)         * ensure '\0' termination
  106. nxtbyt
  107.       move.b   (a0)+,d0
  108.       beq      nxtdone           * '\0' char is end of string
  109.       cmp.b    #'A',d0
  110.       blt.s    arge
  111.       cmp.b    #'Z',d0
  112.       bgt.s    arge
  113.       or.b     #$20,d0           * Convert uppercase to lower
  114. arge
  115.       cmp.b    #'e',d0           * enable
  116.       bne.s    argd
  117.       st       enabled           * enabled = TRUE
  118.       bra.s    nxtbyt
  119. argd
  120.       cmp.b    #'d',d0           * disable
  121.       bne.s    argi
  122.       sf       enabled           * enablad= FALSE
  123.       bra.s    nxtbyt
  124. argi
  125.       cmp.b    #'i',d0           * input
  126.       bne.s    argc
  127.       move.l   a0,-(sp)
  128.       pea.l    inpmsg
  129.       move.w   #cconws,-(sp)
  130.       trap     #gemdos           * Prompt for break char
  131.       addq.l   #6,sp
  132.       move.w   #crawcin,-(sp)
  133.       trap     #gemdos           * Read the char
  134.       addq.l   #2,sp
  135.       move.l   d0,breakcode      * and store it
  136.       pea.l    retmsg
  137.       move.w   #cconws,-(sp)
  138.       trap     rap     rap     rap     rap     e.w   #super,-(sp)
  139.       trap     #gemdos           * Supervisor mode
  140.       addq.l   #2,sp
  141.       move.l   d0,(sp)           * Save supervisor stack pointer on stack
  142.       lea.l    magic,a0          * a0 points to 'magic' string in this prog
  143.       move.l   diff,d0
  144.       lea.l    (a0,d0.l),a1      * a1 points (perhaps) to 'magic' in old
  145.       move.l   #(magicend-magic-1),d0 * # chars in 'magic' string minus one
  146. chkmag
  147.       cmp.b    (a0)+,(a1)+       * Check strings for equality
  148.       dbne     d0,chkmag
  149.       beq.s    mageq             * If old prog DID contain magic string; else:
  150. magne
  151.       move.w   #super,-(sp)
  152.       trap     #gemdos           * Back to user mode (sp was still on stack)
  153.       addq.l   #6,sp
  154.       clr.l    diff              * First incarnation: will be made resident
  155.       pea.l    breakey           * breakey will be new keyboard int. vector
  156.       move.w   #$46,-(sp)
  157.       move.w   #setexc,-(sp)
  158.       trap     #bios             * Set it
  159.       addq.l   #8,sp
  160.       move.l   4(sp),a0          * basepage start
  161.       move.l   #bpaglen,d0       * base page length
  162.       add.l    textlen(a0),d0    * + text length
  163.       add.l    datalen(a0),d0    * + data length
  164.       add.l    bsslen(a0),d0     * + bss length
  165.       clr.w    -(sp)             * return value: 0 for success
  166.       move.l   d0,-(sp)          * # bytes to keep
  167.       move.w   #ptermres,-(sp)   * keep process
  168.       trap     #gemdos           * stops here...
  169.  
  170. mageq
  171.       move.w   #super,-(sp)      * A next incarnation of break in this branch.
  172.       trap     #gemdos           * Back to user mode (sp was still on stack)
  173.       addq.l   #6,sp
  174.       move.l   diff,d0
  175.       lea.l    enabled,a0
  176.       move.b   (a0),(a0,d0.l)    * Copy 'enabled' into old image
  177.       lea.l    zeroed,a0
  178.       move.b   (a0),(a0,d0.l)    * Do this too for 'zeroed'
  179.       lea.l    breakcode,a0
  180.       move.l   (a0),(a0,d0.l)    * And also for the current break char
  181.       move.w   #pterm0,-(sp)
  182.       trap     #gemdos           * Exits here with 0 as status.
  183.  
  184. breakey
  185. * The new interrupt routine
  186.       pea.l    breaketc          * Return to breaketc after executing old code
  187.       move.w   sr,-(sp)          * This is because old code ends with 'rte'
  188.       move.l   oldvec,-(sp)      * Push old vector onto stack
  189.       rts                        * and jump to it
  190. breaketc
  191.       movem.l  d0-d1/a0-a2,-(sp)
  192.       tst.b    enabled
  193.       beq.s    breakend          * If not enabled do nothing
  194.       move.l   iop,a0
  195.       move.w   ibuftl(a0),d0
  196.       cmp.w    ibufhead(a0),d0
  197.       beq.s    breakend          * If empty keyboard buffer do nothing
  198.       moveq.l  #2,d0
  199.       move.l   curproc,a1
  200. testbp
  201.       tst.l    (a1)              * At end of list?
  202.       beq.s    breakend          * Cur. prog was desktop or so; don't break
  203.       move.l   36(a1),a1         * Back link to previous process
  204.       dbra     d0,testbp
  205.       moveq.l  #0,d0
  206.       move.w   ibufhead(a0),d0   * d0 is used as index into char buffer
  207.       move.l   breakcode,d1
  208.       move.l   (a0),a1           * a1 points to character buffer
  209. testbuf
  210.       cmp.w    ibuftl(a0),d0
  211.       beq.s    breakend          * Checked them all
  212.       addq.l   #4,d0             * Increment index in buffer
  213.       cmp.w    ibufsize(a0),d0   * If at buffer size
  214.       bne.s    notatend
  215.       moveq.l  #0,d0             * wrap it (circular buffer)
  216. notatend
  217.       cmp.l    (a1,d0.w),d1      * Is char at this index the break char?
  218.       bne.s    testbuf           * No; check next
  219.       tst.b    zeroed            * Yes; is 'zeroed' flag set?
  220.       beq.s    notzeroed
  221.       clr.l    (a1,d0.w)         * Make the break char in the buffer 0;
  222.       bra.s    testbuf           * this eliminates any special meaning
  223. notzeroed
  224.       move.w   ibuftl(a0),ibufhead(a0) * Clear the entire buffer
  225.       move.l   #stop,22(sp)      * Return will be to the routine 'stop'
  226. breakend
  227.       movem.l  (sp)+,d0-d1/a0-a2
  228.       rte
  229.  
  230. stop
  231.       move.w   #intrupt,-(sp)    * Code for interrupted programs
  232.       move.w   #pterm,-(sp)
  233.       trap     #gemdos           * and stop here
  234.  
  235.    section  s.data
  236.  
  237. iop         dc.l  0              * Pointer to iorec struct
  238. breakcode   dc.l  $0053001f      * Default is control_delete
  239. diff        dc.l  0              * Difference in byte distance old <-> new
  240. oldvec      dc.l  0              * previous val of interrupt vector
  241. enabled     dc.b  $ff            * 'enabled' is default true.
  242. zeroed      dc.b  0              * 'zeroed' is default false.
  243. magic       dc.b  'BREAK MARKER',0 * magic string that identifies this prog.
  244. magicend
  245. inpmsg      dc.b  'Input the break code by hitting the key(s) : ',0
  246. usemsg      dc.b  'break: usage: break [-e|-d|-z] [-i|-c<code>]',cr,lf,0
  247. retmsg      dc.b  cr,lf,0
  248.  
  249.    end
  250.  
  251.  
  252.