home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / ansi / nnansi / nnansi_p.asm < prev    next >
Assembly Source File  |  1990-08-28  |  10KB  |  307 lines

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