home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / ansi / zansi / zansi_p.asm < prev    next >
Assembly Source File  |  1987-07-02  |  12KB  |  299 lines

  1. ;----- zansi_p.asm --------------------------------------------------------
  2. ; Zephyr ANSI terminal driver.
  3. ;    Copyright (C) 1986-1987, Thomas Hanlin III, Alexandria VA.
  4. ;    Based on original code for NANSI by Daniel Kegel, Pasadena CA.
  5. ;------------------------------------------------------------------------
  6. ; A state machine implementation of the mechanics of ANSI terminal control
  7. ; string parsing.
  8. ;
  9. ; Entered with a jump to f_escape when driver finds an escape, or
  10. ; to f_in_escape when the last string written to this device ended in the
  11. ; middle of an escape sequence.
  12. ;
  13. ; Exits by jumping to f_ANSI_exit when an escape sequence ends, or
  14. ; to f_not_ANSI when a bad escape sequence is found, or (after saving state)
  15. ; to f_loopdone when the write ends in the middle of an escape sequence.
  16. ;
  17. ; Parameters are stored as bytes in param_buffer.  If a parameter is
  18. ; omitted, it is stored as zero.  Each character in a keyboard reassignment
  19. ; command counts as one parameter.
  20. ;
  21. ; When a complete escape sequence has been parsed, the address of the
  22. ; ANSI routine to call is found in ansi_fn_table.
  23. ;
  24. ; Register usage during parsing:
  25. ;  DS:SI points to the incoming string.
  26. ;  CX holds the length remaining in the incoming string.
  27. ;  ES:DI points to the current location on the memory-mapped screen.
  28. ;  DX is number of characters remaining on the current screen line.
  29. ;  BX points to the current paramter byte being assembled from the incoming
  30. ;  string.  (Stored in cur_parm_ptr between device driver calls, if needed.)
  31. ;
  32. ; The registers are set as follows before calling the ANSI subroutine:
  33. ;  AX = max(1, value of first parameter)
  34. ;  CX = number of paramters
  35. ;  SI = offset of second parameter from CS
  36. ;  DS = CS
  37. ;  ES:DI points to the current location on the memory-mapped screen.
  38. ;  DX is number of characters remaining on the current screen line.
  39. ; The subroutine is free to trash AX, BX, CX, SI, and DS.
  40. ; It must preserve ES, and can alter DX and DI if it wants to move the
  41. ; cursor.
  42. ;
  43. ;------------------------------------------------------------------------
  44.  
  45.         ; From zansi.asm
  46.         extrn   f_not_ANSI:near         ; exit: abort bad ANSI cmd
  47.         extrn   f_ANSI_exit:near        ; exit: good cmd done
  48.         extrn   f_loopdone:near         ; exit: ran out of chars. State saved.
  49.         extrn   escvector:word          ; saved state: where to jump
  50.         extrn   cur_parm_ptr:word       ; saved state: where to put next param
  51.         extrn   string_term:byte        ; saved state: what ends string
  52.         extrn   cur_x:byte, max_x:byte  ; 0 <= cur_x <= max_x
  53.         extrn   cur_attrib:byte         ; current color/attribute
  54.  
  55.         ; from zansi_f.asm
  56.         extrn   ansi_fn_table:word      ; ANSI subroutine table
  57.  
  58.         ; Used in zansi.asm
  59.         public  f_escape                ; entry: found an escape
  60.         public  f_in_escape             ; entry: restore state, keep parsing
  61.  
  62.         ; Used in zansi_i.asm and zansi_f.asm
  63.         public  param_buffer, param_end
  64.  
  65.  
  66. code    segment byte public 'CODE'
  67.         assume  cs:code
  68.  
  69. ; More saved state
  70. in_num          db      ?       ; true if between a digit and a semi in parse
  71. param_buffer    dw      ?       ; address of first byte free for new params
  72. param_end       dw      ?       ; address of end of free area
  73.  
  74.  
  75. ;----- next_is -------------------------------------------------------
  76. ; Next_is is used to advance to the next state.  If there are characters
  77. ; left in the input string, we jump immediately to the new state;
  78. ; otherwise, we shut down the recognizer, and wait for the next call
  79. ; to the device driver.
  80. next_is macro   statename
  81.         loop    statename
  82.         mov     ax, offset statename
  83.         jmp     sleep
  84.         endm
  85.  
  86. ;----- sleep --------------------------------------------------------
  87. ; Remember bx and next state, then jump to device driver exit routine.
  88. ; Device driver will re-enter at f_in_escape upon next invocation
  89. ; because escvector is nonzero; parsing will then be resumed.
  90. sleep:  mov     cs:cur_parm_ptr, bx
  91.         mov     cs:escvector, ax
  92.         jmp     f_loopdone
  93.  
  94. ;----- f_in_escape ---------------------------------------------------
  95. ; Main loop noticed that escvector was not zero.
  96. ; Recall value of BX saved when sleep was jumped to, and jump into parser.
  97. f_in_escape:
  98.         mov     bx, cs:cur_parm_ptr
  99.         jmp     word ptr cs:escvector
  100.  
  101. fbr_syntax_error_gate:          ; jumped to from inside f_bracket
  102.         jmp     syntax_error
  103.  
  104. ;----- f_escape ------------------------------------------------------
  105. ; We found an escape.  Next character should be a left bracket.
  106. f_escape:
  107.         next_is f_bracket
  108.  
  109. ;----- f_bracket -----------------------------------------------------
  110. ; Last char was an escape.  This one should be a [; if not, print it.
  111. ; Next char should begin a parameter string.
  112. f_bracket:
  113.         lodsb
  114.         cmp     al, '['
  115.         jnz     fbr_syntax_error_gate
  116.         ; Set up for getting a parameter string.
  117.         mov     bx, cs:param_buffer
  118.         mov     byte ptr cs:[bx], 0
  119.         mov     cs:in_num, 0
  120.         next_is f_get_args
  121.  
  122. ;----- f_get_args ---------------------------------------------------
  123. ; Last char was a [.  If the current char is a '=' or a '?', eat it.
  124. ; In any case, proceed to f_get_param.
  125. ; This is only here to strip off the strange chars that follow [ in
  126. ; the SET/RESET MODE escape sequence.
  127. f_get_args:
  128.         lodsb
  129.         cmp     al, '='
  130.         jz      fga_ignore
  131.         cmp     al, '?'
  132.         jz      fga_ignore
  133.                 dec     si              ; let f_get_param fetch al again
  134.                 jmp     short f_get_param
  135. fga_ignore:
  136.         next_is f_get_param
  137.  
  138. ;----- f_get_param ---------------------------------------------------
  139. ; Last char was one of the four characters "]?=;".
  140. ; We are getting the first digit of a parameter, a quoted string,
  141. ; a ;, or a command.
  142. f_get_param:
  143.         lodsb
  144.         cmp     al, '0'
  145.         jb      fgp_may_quote
  146.         cmp     al, '9'
  147.         ja      fgp_may_quote
  148.                 ; It's the first digit.  Initialize current parameter with it.
  149.                 sub     al, '0'
  150.                 mov     byte ptr cs:[bx], al
  151.                 mov     cs:in_num, 1    ; set flag for sensing at cmd exec
  152.                 next_is f_in_param
  153. fgp_may_quote:
  154.         cmp     al, '"'
  155.         jz      fgp_isquote
  156.         cmp     al, "'"
  157.         jnz     fgp_semi_or_cmd         ; jump to code shared with f_in_param
  158. fgp_isquote:
  159.         mov     cs:string_term, al      ; save it for end of string
  160.         next_is f_get_string            ; and read string into param_buffer
  161.  
  162. ;----- f_get_string -------------------------------------
  163. ; Last character was a quote or a string element.
  164. ; Get characters until ending quote found.
  165. f_get_string:
  166.         lodsb
  167.         cmp     al, cs:string_term
  168.         jz      fgs_init_next_param
  169.         mov     byte ptr cs:[bx], al
  170.         cmp     bx, cs:param_end
  171.         adc     bx, 0                   ; if bx<param_end bx++;
  172.         next_is f_get_string
  173. ; Ending quote was found.
  174. fgs_init_next_param:
  175.         mov     byte ptr cs:[bx], 0     ; initialize new parameter
  176.         ; | Eat following semicolon, if any.
  177.         next_is f_eat_semi
  178.  
  179. ;----- f_eat_semi -------------------------------------
  180. ; Last character was an ending quote.
  181. ; If this char is a semi, eat it; else unget it.
  182. ; Next state is always f_get_param.
  183. f_eat_semi:
  184.         lodsb
  185.         cmp     al, ';'
  186.         jz      fes_eaten
  187.         inc     cx
  188.         dec     si
  189. fes_eaten:
  190.         next_is f_get_param
  191.  
  192. ;----- syntax_error ---------------------------------------
  193. ; A character was rejected by the state machine.  Exit to
  194. ; main loop, and print offending character.  Let main loop
  195. ; decrement CX (length of input string).
  196. syntax_error:
  197.         mov     cs:escvector, 0
  198.         mov     ah, cs:cur_attrib
  199.         jmp     f_not_ANSI      ; exit, print offending char
  200.  
  201. ;------ f_in_param -------------------------------------
  202. ; Last character was a digit.
  203. ; Looking for more digits, a semicolon, or a command character.
  204. f_in_param:
  205.         lodsb
  206.         cmp     al, '0'
  207.         jb      fgp_semi_or_cmd
  208.         cmp     al, '9'
  209.         ja      fgp_semi_or_cmd
  210.         ; It's another digit.  Add into current parameter.
  211.         sub     al, '0'
  212.         xchg    byte ptr cs:[bx], al
  213.         push    dx
  214.         mov     dl, 10
  215.         mul     dl
  216.         pop     dx
  217.         add     byte ptr cs:[bx], al
  218.         next_is f_in_param
  219.         ; Code common to states get_param and in_param.
  220.         ; Accepts a semicolon or a command letter.
  221. fgp_semi_or_cmd:
  222.         cmp     al, ';'
  223.         jnz     fgp_not_semi
  224.         cmp     bx, cs:param_end        ; prepare for next param-
  225.         adc     bx, 0                   ; if bp<param_end bp++;
  226.         ; Set new param to zero, enter state f_get_param.
  227.         mov     cs:in_num, 0            ; no longer inside number
  228.         jmp     fgs_init_next_param     ; spaghetti code attack!
  229. fgp_not_semi:
  230.         ; It must be a command letter.
  231.         cmp     al, '@'
  232.         jb      syntax_error
  233.         cmp     al, 'z'
  234.         ja      syntax_error
  235.         cmp     al, 'Z'
  236.         jbe     fgp_is_cmd
  237.         cmp     al, 'a'
  238.         jb      syntax_error
  239.         ; It's a lower-case command letter.
  240.         ; Remove hole between Z and a to save space in table.
  241.         sub     al, 'a'-'['
  242. fgp_is_cmd:
  243.         ; It's a command letter.  Save registers, convert letter
  244.         ; into address of routine, set up new register usage, call routine.
  245.         push    si                      ; These three registers hold info
  246.         push    cx                      ; having to do with the input string,
  247.         push    ds                      ; which has no interest at all to the
  248.                                         ; control routine.
  249.  
  250.         push    cs
  251.         pop     ds                      ; ds is now cs
  252.  
  253.         sub     al, '@'                 ; first command is @: insert chars
  254.         cbw
  255.         shl     ax,1
  256.         add     ax, offset ansi_fn_table
  257.         ; ax is now pointer to command routine address in table
  258.  
  259.         mov     cx, bx
  260.         mov     si, param_buffer        ; si is now pointer to parameters
  261.         sub     cx, si                  ;
  262.         test    in_num, 1
  263.         jz      fip_out_num
  264.         inc     cx
  265. fip_out_num:                            ; cx is now # of parameters
  266.  
  267.         mov     bx,ax                   ; save pointer to routine in bx
  268.  
  269.         ; Calculate cur_x from DX.
  270.         mov     al, max_x
  271.         inc     ax
  272.         sub     al, dl
  273.         mov     cur_x, al
  274.  
  275.         ; Get first parameter into AX; if defaulted, set it to 1.
  276.         xor     ah,ah
  277.         lodsb
  278.         or      al, al
  279.         jnz     fgp_callem
  280.         inc     ax
  281. fgp_callem:
  282.         ; Finally, call the command subroutine.
  283.         call    word ptr [bx]
  284.  
  285.         pop     ds
  286.         pop     cx
  287.         pop     si
  288.  
  289.         mov     ah, cs:cur_attrib       ; Prepare for STOSW.
  290.         mov     cs:escvector, 0         ; No longer parsing escape sequence.
  291.         ; Set flags for reentry at loopnz
  292.         or      dx, dx                  ; "Any columns left on line?"
  293.         ; Re-enter at bottom of main loop.
  294.         jmp     f_ansi_exit
  295.  
  296.  
  297. code    ends
  298.         end
  299.