home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / emit / emit.a86 next >
Text File  |  1994-06-17  |  9KB  |  296 lines

  1. ;EMIT.A - Unix-style utility to output control characters
  2. ;Author: John Lene-Comeau, Industrial Control Technology, jcomeau@world.std.com
  3. ;Specialists in utilities and device drivers under RSX, VMS, and MS-DOS.
  4. ;PO Box 100632, Ft. Lauderdale, FL 33310-0632 * (305)966-0162
  5. ;
  6. ;Uncopyrighted (U) 1994 John Lene Comeau. Public Domain software.
  7. ;
  8. ;To use: emit 0x1b "[7mThis is a test",27,"[m" ;comment
  9. ; note that whitespace or commas can be separators
  10. ; text may be in single or double quotes
  11. ; numbers beginning with 0x are hexadecimal, with 0 are octal, otherwise decimal
  12. ; comment may follow, preceded by semicolon
  13. ; default output to screen may be overridden by using redirection
  14. ;
  15. dos    equ    21h
  16. ;set up for stack variables
  17. _byte    equ    -1
  18. _word    equ    -2
  19. _dword    equ    -4
  20. ;
  21. stackv    macro    ;set up variables on stack, index to using BP
  22.     ##if !stktop
  23.     stktop = 0
  24.     ##endif
  25. #1    equ    stktop + #2
  26. stktop = #1
  27.     #em
  28. ;
  29. newstate macro    ;set new processing state
  30.     mov    cx,offset #1    ;move memory to memory using CX
  31.     mov    state[bp],cx
  32.     #em
  33. ;
  34. error    macro    ;output message to STDERR and exit with specified errorlevel
  35.     ##if #s2 ;if there's a string supplied
  36.     mov    cx,#s2-2 ;number of bytes in message
  37.     ##else
  38.     xor    cx,cx    ;else don't print anything
  39.     ##endif
  40.     mov    bx,2    ;STDERR
  41.     mov    dx,offset >m1
  42.     mov    ah,40h    ;dos WRITE function
  43.     int    dos    ;do it
  44.     mov    ax,4c00h+#1 ;set errorlevel
  45.     int    dos    ;and exit
  46. m1:    db    #2
  47.     #em
  48. ;
  49. ;the variables themselves...
  50. ;
  51.     stackv    state,_word
  52.     stackv    delimiter,_word
  53. ;
  54.     mov    bp,sp    ;get current stack pointer
  55.     add    sp,stktop ;initialize variable space on stack
  56.     newstate start  ;initialize state
  57.     mov    bx,80h    ;point to input character count
  58.     mov    dl,[bx]    ;get count byte
  59.     add    bl,dl    ;point to end...
  60.     inc    bx    ;now it does
  61.     mov    byte ptr [bx],0 ;zero-terminate it
  62.     mov    si,81h    ;point DS:SI to arg string
  63.  
  64. emitloop:
  65.     lodsb    ;get next byte
  66.     jmp    state[bp] ;jump to routine corresponding to state
  67. ;
  68. start:
  69.     mov    bx,offset >s1 ;load table
  70.     call    bounds    ;get appropriate subroutine
  71.     jmp    >s2[bx]    ;and jump to it
  72. s1:    db    1,0,1,';',2,' ',0
  73. s2:    dw    >s3,>s4,>s5,>s6
  74. s3:    error    1,'Usage: emit nn [nn...] ;nn is value of ASCII character'
  75. s4:    error    0    ;exit normally
  76. s5:    newstate waiting ;else now waiting for an arg
  77.     jmp    emitloop ;so go back and find one
  78. s6:    error    2,'EMIT -- Error - Invalid character found'
  79. ;
  80.  
  81. waiting:
  82.     mov    bx,offset >s1 ;load table
  83.     call    bounds    ;get appropriate subroutine
  84.     jmp    >s2[bx]    ;and jump to it
  85. s1:    db    1,0,1,';',1,"'",1,'"',2,' ',1,',',8,'0'-1,1,'0',2,'9',0
  86. s2:    dw    >s3,>s3,>s4,>s4,emitloop,emitloop,>s5,>s6,>s7,>s5
  87. s3:    error    0    ;normal exit on null or comment
  88. s4:    newstate string    ;switch to string storage state
  89.     mov    delimiter[bp],al ;store delimiter
  90.     jmp    emitloop ;loop around
  91. s5:    error    3,'EMIT -- Error - expecting string or number'
  92. s6:    newstate number ;start of hex or octal number
  93.     xor    dx,dx    ;clear result register
  94.     jmp    emitloop ;loop back for more
  95. s7:    newstate decimal ;start of decimal number
  96.     xor    dx,dx    ;clear result register
  97.     jmp    decimal    ;go straight to it with this digit
  98. ;
  99.  
  100. string:
  101.     or    al,al    ;end of command line?
  102.     je    >s1    ;error if so
  103.     cmp    al,delimiter[bp] ;otherwise, same as starting delimiter?
  104.     je    >s2    ;end of string mode if so
  105.     mov    dl,al    ;else send char
  106.     mov    ah,2    ;DOS function
  107.     int    dos    ;do it
  108.     jmp    emitloop
  109. s1:    error    4,'EMIT -- Error - Unexpected termination within string'
  110. s2:    newstate waiting ;done with string processing
  111.     jmp    emitloop ;back for more input
  112. ;
  113. number:
  114.     mov    bx,offset >s1 ;load table
  115.     call    bounds    ;get subroutine offset
  116.     jmp    >s2[bx] ;jump to it
  117. s1:    db    1,0,2,' ',1,',',1,';',1,'X',1,'x',8,'0'-1,2,'7',0
  118. s2:    dw    >s3,>s4,>s4,>s3,>s5,>s5,>s6,>s7,>s6
  119. s3:    call    numout    ;output number as is (must be zero)
  120.     error    0    ;and exit
  121. s4:    call    numout    ;output the null
  122.     jmp    emitloop ;loop back for more
  123. s5:    newstate hexadecimal ;switch to HEX processing state
  124.     jmp    emitloop ;go get the rest
  125. s6:    error    5,'EMIT -- Error - Invalid octal digit found'
  126. s7:    newstate octal ;switch to OCTAL processing state
  127.     jmp    octal    ;and go straight to it from here
  128. ;
  129. decimal:
  130. mov    bx,offset >s1 ;load table
  131.     call    bounds    ;get subroutine offset
  132.     jmp    >s2[bx] ;jump to it
  133. s1:    db    1,0,2,' ',1,',',1,';',8,'0'-1,2,'9',0
  134. s2:    dw    >s3,>s4,>s4,>s3,>s5,>s6,>s5
  135. s3:    call    numout    ;output what we have so far
  136.     error    0    ;exit
  137. s4:    call    numout    ;output what we have
  138.     newstate waiting ;back to fishing mode
  139.     jmp    emitloop ;go get rest of command line
  140. s5:    error    6,'EMIT -- Error - Invalid decimal digit found'
  141. s6:    aam    10h    ;split so AL contains decimal digit
  142.     xchg    ax,dx    ;switch with result register
  143.     mov    cl,10
  144.     mul    cl    ;shift current result one decimal place over
  145.     add    al,dl    ;and merge in current digit
  146.     xchg    ax,dx    ;switch back
  147.     jmp    emitloop ;go back for more
  148. ;
  149.  
  150. hexadecimal:
  151.     mov    bx,offset >s1 ;load table
  152.     call    bounds    ;get subroutine offset
  153.     jmp    >s2[bx]    ;jump to it
  154. s1:    db    1,0,2,' ',1,',',1,';',8,'0'-1,2,'9',8,'A'-1,2,'F'
  155.     db    8,'a'-1,2,'f',0
  156. s2:    dw    >s3,>s4,>s4,>s3,>s5,>s6,>s5,>s7,>s5,>s7,>s5
  157. s3:    call    numout    ;output what we have so far
  158.     error    0    ;exit
  159. s4:    call    numout    ;output what we have
  160.     newstate waiting ;no longer in HEX mode
  161.     jmp    emitloop ;go get rest of command line
  162. s5:    error    7,'EMIT -- Error - Invalid hexadecimal digit found'
  163. s6:    aam    10h    ;split so AL contains decimal digit
  164.     mov    cl,4    ;8088 won't accept SHL DX,4
  165.     shl    dx,cl    ;shift current result one nybble over
  166.     add    dl,al    ;and merge in current digit
  167.     jmp    emitloop ;go back for more
  168. s7:    aam    10h    ;split so AL contains 1 thru 6
  169.     add    al,9    ;now make it 0xa-0xf
  170.     mov    cl,4    ;in case running on 8086/88
  171.     shl    dx,cl    ;shift current result one nybble over
  172.     add    dl,al    ;and merge in current digit
  173.     jmp    emitloop ;go back for more
  174. octal:
  175.     mov    bx,offset >s1 ;load table
  176.     call    bounds    ;get subroutine offset
  177.     jmp    >s2[bx] ;jump to it
  178. s1:    db    1,0,2,' ',1,',',1,';',8,'0'-1,2,'7',0
  179. s2:    dw    >s3,>s4,>s4,>s3,>s5,>s6,>s5
  180. s3:    call    numout    ;output what we have so far
  181.     error    0    ;exit
  182. s4:    call    numout    ;output what we have
  183.     newstate waiting
  184.     jmp    emitloop ;go get rest of command line
  185. s5:    error    8,'EMIT -- Error - Invalid octal digit found'
  186. s6:    aam    10h    ;split so AL contains octal digit
  187.     mov    cl,3    ;in case running on 8088
  188.     shl    dx,cl    ;shift current result one octal place over
  189.     add    dl,al    ;and merge in current digit
  190.     jmp    emitloop ;go back for more
  191. ;
  192. numout:
  193.     mov    ah,2    ;DOS function for character output
  194.     int    dos    ;do it (send DL)
  195.     ret        ;and return
  196. ;
  197.  
  198. bounds:
  199. ;This routine is passed a character in AL and a table address in
  200. ;BX. The table consists of word entries, each with the low byte
  201. ;containing an action code and the high byte a character code. The
  202. ;action codes are:
  203. ; 0 - end of table
  204. ; 1 - char is legal
  205. ; 2 - chars less than or equal to this is legal
  206. ; 3 - chars greater than this are legal
  207. ; 4 - char is ignored
  208. ; 5 - chars <= are ignored
  209. ; 6 - chars > are ignored
  210. ; 7 - char is illegal
  211. ; 8 - chars <= are illegal
  212. ; 9 - chars > are illegal
  213. ;returns S set if char is illegal
  214. ;Z set if char is legal
  215. ;C set if passed bad parameters (program error) or reached end of table
  216. ;no flags if char is to be ignored
  217. ;doesn't change AX, but BX is returned as word offset to entry where
  218. ;match occurred. All other regs are saved.
  219.     push    dx    ;save aux register
  220.     push    ax    ;save character
  221.     push    bx    ;save start of table
  222.     mov    ah,10    ;highest legal action code is 9
  223.     jmp    b2    ;skip cleanup routine on first entry
  224. b1:    xchg    bx,dx    ;swap regs back where they belong
  225.     inc    bx    ;and point to next word entry
  226. b2:    cmp    [bx],ah    ;past highest legal action code?
  227.     jnc    b96    ;if so, quit
  228.     mov    dl,[bx]    ;else get the action code
  229.     xor    dh,dh    ;make word pointer
  230.     shl    dx,1
  231.     inc    bx    ;point to character code
  232.     cmp    al,[bx] ;compare current character to it
  233.     xchg    bx,dx    ;must be in BX to use indirectly
  234.     jmp    b4[bx]    ;jump to appropriate action routine
  235. b4:    dw    b96    ;end of table is error, shouldn't happen
  236.     dw    b10
  237.     dw    b20
  238.     dw    b30
  239.     dw    b40
  240.     dw    b50
  241.     dw    b60
  242.     dw    b70
  243.     dw    b80
  244.     dw    b90
  245. b10:    je    b97    ;char is legal, finish up
  246.     jmp    b1    ;else loop back and try again
  247. b20:    jbe    b97
  248.     jmp    b1
  249. b30:    ja    b97
  250.     jmp    b1
  251. b40:    je    b95
  252.     jmp    b1
  253. b50:    jbe    b95
  254.     jmp    b1
  255. b60:    ja    b95
  256.     jmp    b1
  257. b70:    je    b98
  258.     jmp    b1
  259. b80:    jbe    b98
  260.     jmp    b1
  261. b90:    ja    b98
  262.     jmp    b1
  263. b95:    xchg    bx,dx    ;get final address
  264.     dec    bx    ;make word
  265.     pop    dx    ;now get start of table
  266.     sub    bx,dx    ;and make offset
  267.     mov    al,1    ;reset all the flags
  268.     or    al,al    ;like this
  269.     pop    ax    ;now restore the registers
  270.     pop    dx
  271.     ret
  272. b96:    xchg    bx,dx    ;same except for carry flag set before RET
  273.     dec    bx
  274.     pop    dx
  275.     sub    bx,dx
  276.     stc        ;error indicator set here
  277.     pop    ax
  278.     pop    dx
  279.     ret
  280. b97:    xchg    bx,dx
  281.     dec    bx
  282.     pop    dx
  283.     sub    bx,dx
  284.     xor    al,al    ;set Z flag
  285.     pop    ax
  286.     pop    dx
  287.     ret
  288. b98:    xchg    bx,dx
  289.     dec    bx
  290.     pop    dx
  291.     sub    bx,dx
  292.     or    al,80h    ;set S flag
  293.     pop    ax
  294.     pop    dx
  295.     ret
  296.