home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ka9q / nan24hyc.zip / NANSI_P.ASM < prev    next >
Assembly Source File  |  1990-10-31  |  10KB  |  307 lines

  1.     page    66, 132
  2. ;----- nansi_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. ;------------------------------------------------------------------------
  45.  
  46.     ; From nansi.asm
  47.     extrn    f_not_ANSI:near        ; exit: abort bad ANSI cmd
  48.     extrn    f_ANSI_exit:near    ; exit: good cmd done
  49.     extrn    f_loopdone:near        ; exit: ran out of chars. State saved.
  50.     extrn    escvector:word        ; saved state: where to jump
  51.     extrn    cur_parm_ptr:word    ; saved state: where to put next param
  52.     extrn    string_term:byte    ; saved state: what ends string
  53.     extrn    cur_x:byte, max_x:byte    ; 0 <= cur_x <= max_x
  54.     extrn    cur_attrib:byte        ; current color/attribute
  55.     extrn    xlate_tab_ptr:word
  56.  
  57.     ; from nansi_f.asm
  58.     extrn    ansi_fn_table:word    ; ANSI subroutine table
  59.  
  60.     ; Used in nansi.asm
  61.     public    f_escape        ; entry: found an escape
  62.     public    f_in_escape        ; entry: restore state, keep parsing
  63.  
  64.     ; Used in nansi_i.asm and nansi_f.asm
  65.     public    param_buffer, param_end, redef_end
  66.     
  67.  
  68. code    segment byte public 'CODE'
  69.     assume    cs:code
  70.  
  71. ; More saved state
  72. in_num        db    ?    ; true if between a digit and a semi in parse
  73.  
  74. param_buffer    dw    3000h    ; address of first byte free for new params
  75. param_end    dw    3030h    ; address of end of free area
  76. redef_end    dw    3030h    ; address of end of redefinition area
  77.         ; These initialized values are only for debugging
  78.  
  79. ;----- next_is -------------------------------------------------------
  80. ; Next_is is used to advance to the next state.     If there are characters
  81. ; left in the input string, we jump immediately to the new state;
  82. ; otherwise, we shut down the recognizer, and wait for the next call
  83. ; to the device driver.
  84. next_is macro    statename
  85.     loop    statename
  86.     mov    ax, offset statename
  87.     jmp    sleep
  88.     endm
  89.  
  90. ;----- sleep --------------------------------------------------------
  91. ; Remember bx and next state, then jump to device driver exit routine.
  92. ; Device driver will re-enter at f_in_escape upon next invocation
  93. ; because escvector is nonzero; parsing will then be resumed.
  94. sleep:    mov    cs:cur_parm_ptr, bx
  95.     mov    cs:escvector, ax
  96.     jmp    f_loopdone
  97.  
  98. ;----- f_in_escape ---------------------------------------------------
  99. ; Main loop noticed that escvector was not zero.
  100. ; Recall value of BX saved when sleep was jumped to, and jump into parser.
  101. f_in_escape:
  102.     mov    bx, cs:cur_parm_ptr
  103.     jmp    word ptr cs:escvector
  104.  
  105. fbr_syntax_error_gate:        ; jumped to from inside f_bracket
  106.     jmp    syntax_error
  107.  
  108. ;----- f_escape ------------------------------------------------------
  109. ; We found an escape.  Next character should be a left bracket.
  110. f_escape:
  111.     next_is f_bracket
  112.  
  113. ;----- f_bracket -----------------------------------------------------
  114. ; Last char was an escape.  This one should be a [; if not, print it.
  115. ; Next char should begin a parameter string.
  116. f_bracket:
  117.     lodsb
  118.     cmp    al, '['
  119.     jnz    fbr_syntax_error_gate
  120.     ; Set up for getting a parameter string.
  121.     mov    bx, cs:param_buffer
  122.     mov    byte ptr cs:[bx], 0
  123.     mov    cs:in_num, 0
  124.     next_is f_get_args
  125.  
  126. ;----- f_get_args ---------------------------------------------------
  127. ; Last char was a [.  If the current char is a '=' or a '?', eat it.
  128. ; In any case, proceed to f_get_param.
  129. ; This is only here to strip off the strange chars that follow [ in
  130. ; the SET/RESET MODE escape sequence.
  131. f_get_args:
  132.     lodsb
  133.     cmp    al, '='
  134.     jz    fga_ignore
  135.     cmp    al, '?'
  136.     jz    fga_ignore
  137.         dec    si        ; let f_get_param fetch al again
  138.         jmp    short f_get_param
  139. fga_ignore:
  140.     next_is f_get_param
  141.  
  142. ;----- f_get_param ---------------------------------------------------
  143. ; Last char was one of the four characters "]?=;".
  144. ; We are getting the first digit of a parameter, a quoted string,
  145. ; a ;, or a command.
  146. f_get_param:
  147.     lodsb
  148.     cmp    al, '0'
  149.     jb    fgp_may_quote
  150.     cmp    al, '9'
  151.     ja    fgp_may_quote
  152.         ; It's the first digit.     Initialize current parameter with it.
  153.         sub    al, '0'
  154.         mov    byte ptr cs:[bx], al
  155.         mov    cs:in_num, 1    ; set flag for sensing at cmd exec
  156.         next_is f_in_param
  157. fgp_may_quote:
  158.     cmp    al, '"'
  159.     jz    fgp_isquote
  160.     cmp    al, "'"
  161.     jnz    fgp_semi_or_cmd        ; jump to code shared with f_in_param
  162. fgp_isquote:
  163.     mov    cs:string_term, al    ; save it for end of string
  164.     next_is f_get_string        ; and read string into param_buffer
  165.  
  166. ;----- f_get_string -------------------------------------
  167. ; Last character was a quote or a string element.
  168. ; Get characters until ending quote found.
  169. f_get_string:
  170.     lodsb
  171.     cmp    al, cs:string_term
  172.     jz    fgs_init_next_param
  173.     mov    byte ptr cs:[bx], al
  174.     cmp    bx, cs:param_end
  175.     adc    bx, 0            ; if bx<param_end bx++;
  176.     next_is f_get_string
  177. ; Ending quote was found.
  178. fgs_init_next_param:
  179.     mov    byte ptr cs:[bx], 0    ; initialize new parameter
  180.     ; | Eat following semicolon, if any.
  181.     next_is f_eat_semi
  182.  
  183. ;----- f_eat_semi -------------------------------------
  184. ; Last character was an ending quote.
  185. ; If this char is a semi, eat it; else unget it.
  186. ; Next state is always f_get_param.
  187. f_eat_semi:
  188.     lodsb
  189.     cmp    al, ';'
  190.     jz    fes_eaten
  191.         inc    cx
  192.         dec    si
  193. fes_eaten:
  194.     next_is f_get_param
  195.  
  196. ;----- syntax_error ---------------------------------------
  197. ; A character was rejected by the state machine.  Exit to
  198. ; main loop, and print offending character.  Let main loop
  199. ; decrement CX (length of input string).
  200. syntax_error:
  201.     mov    cs:escvector, 0
  202.     mov    ah, cs:cur_attrib
  203.     mov    bx, cs:xlate_tab_ptr
  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.         inc    ax
  286.         or    ah, ah    ; save Zflag for eid  -- hyc 10-30-90
  287. fgp_callem:
  288.     ; Finally, call the command subroutine.
  289.     call    word ptr [bx]
  290.  
  291.     pop    ds
  292.     pop    cx
  293.     pop    si
  294.  
  295.     mov    ah, cs:cur_attrib    ; Prepare for STOSW.
  296.     mov    bx, cs:xlate_tab_ptr    ; Prepare for translation.
  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 nansi_p.asm
  306.  
  307.