home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR8 / VMAC111.ZIP / VMAC.ASM < prev    next >
Assembly Source File  |  1993-08-05  |  82KB  |  2,127 lines

  1. ;███████████████████████████████████████████████████████████████████████████████
  2. ;                           VMAC.ASM  (Version 1.11)
  3. ;      Macro Compiler for Eric Meyer's VDE (Versions 1.53-1.65 and 1.70+)
  4. ;
  5. ;  Source code for assembly under WASM, the Wolfware Assembler, by Eric Tauck.
  6. ;
  7. ; Author:  Richard Cowell
  8. ; Address: S.K. Heights #6
  9. ;          Suwa 239, Takatsu-ku
  10. ;          Kawasaki, Kanagawa  213
  11. ;          JAPAN
  12. ;███████████████████████████████████████████████████████████████████████████████
  13.  
  14. ;=======================================
  15. ;[ INITIALIZATION ]
  16.           mov       dx,DTA              ; set DTA
  17.           mov       ah,1Ah
  18.           int       21h
  19.  
  20.           mov       si,081h             ; check command line
  21. SkipSpaces
  22.           lodsb
  23.           cmp       al,' '
  24.           jz        SkipSpaces
  25.           jb        Usage
  26.           cmp       al,'/'              ; if start of pathname
  27.           jnz       Go                  ;   jump
  28.           lodsb                         ; else al = option
  29. Option
  30.           cmp       al,'7'
  31.           jz        Seven
  32.           and       al,CAPMASK
  33.           cmp       al,'U'
  34.           jnz       Usage
  35.           or        Flag,USEDONLY
  36.           jmps      AnyMore
  37. Seven
  38.           or        Flag,VERSION170
  39. AnyMore
  40.           lodsb
  41.           cmp       al,' '
  42.           jz        SkipSpaces
  43.           ja        Option
  44. Usage
  45.           mov       si,offset Umsg
  46.           call      Puts
  47. ;---------------------------------------;
  48. TheEnd                                  ;
  49.           int       20h                 ;
  50. ;---------------------------------------;
  51. Go
  52.           dec       si
  53.           mov       pArg,si             ; set pArg to start of filename
  54.  
  55. ;=======================================
  56. ;[ MAIN LOOP ]
  57. NextArg
  58.           call      GetPath
  59.           jc        TheEnd
  60.           test      Flag,WILDCARD
  61.           jz        Process
  62.  
  63.           mov       dx,PATH             ; find first file
  64.           xor       cx,cx               ; attribute: ordinary files
  65.           mov       ah,04Eh
  66.           int       21h
  67.           jnc       WildLoop
  68.           mov       si,offset XFfmsg    ; "no matching files" message
  69.           call      Puts
  70.           mov       si,PATH
  71.           call      Puts
  72.           call      PutCrlf
  73.           jmps      NextArg
  74.  
  75. WildLoop
  76.           mov       si,DTANAME          ; copy filename onto drive:\dir spec.
  77.           mov       di,PATH
  78.           add       di,DrivDirLen
  79.           mov       cx,13
  80.           rep
  81.           movsb
  82.  
  83. Process
  84.           call      Convert
  85.  
  86.           test      Flag,WILDCARD
  87.           jz        NextArg
  88.           mov       ah,04Fh             ; find next file
  89.           int       21h
  90.           jnc       WildLoop
  91.           jmps      NextArg
  92.  
  93. ;█████████████████████████████████ PROCEDURES ██████████████████████████████████
  94. ;╒══════════════════════════════════════╕
  95. ;│              GetPath                 │
  96. ;│ copies argument to PATH              │
  97. ;│ if wildcard found:                   │
  98. ;│             WILDCARD flag set        │
  99. ;│             DrivDirLen set           │
  100. ;│ CF set if no more arguments          │
  101. ;╘══════════════════════════════════════╛
  102. GetPath   PROC      NEAR
  103.           mov       si,pArg
  104.           lodsb
  105.           or        al,al               ; any arguments?
  106.           jnz       Check_gp            ;   yes, go
  107.           stc                           ;   no, set CF
  108.           ret
  109. ;=======================================
  110.      ;[ find start of pathname ]
  111. Skip_gp
  112.           lodsb
  113. Check_gp
  114.           cmp       al,' '
  115.           jz        Skip_gp
  116.           mov       bx,si
  117.           dec       bx                  ; bx = start of pathname
  118.  
  119.      ;[ find end ]
  120. Advance_gp
  121.           lodsb
  122.           cmp       al,' '
  123.           ja        Advance_gp
  124.           mov       byte [si-1],0       ; make ASCIZ
  125.           mov       dx,si               ; save position for length calculation
  126.           jz        Store_gp            ;   if al = space, jump
  127.           dec       si                  ;   else al = CR, move si back to 0
  128. Store_gp
  129.           mov       pArg,si             ; store position for next call
  130.  
  131.      ;[ length ]
  132.           sub       dx,bx
  133.           dec       dx                  ; dx = length of pathname w/o 0
  134.  
  135.      ;[ capitalize and copy ]
  136.           mov       si,bx               ; si = start of pathname
  137.           mov       cx,dx               ; cx = length
  138.           mov       di,PATH
  139. Next_gp
  140.           lodsb
  141.           cmp       al,'a'
  142.           jb        Copy_gp
  143.           cmp       al,'z'
  144.           ja        Copy_gp
  145.           and       al,CAPMASK
  146. Copy_gp
  147.           stosb
  148.           loop      Next_gp
  149.           movsb                         ; include terminal 0
  150.  
  151.      ;[ check for wildcards ]
  152.           and       Flag,FIXEDFLAGS
  153.           mov       DrivDirLen,0
  154.           mov       si,PATH             ; si = start of pathname
  155.           mov       cx,dx               ; cx = length
  156. AstQuest_gp
  157.           lodsb
  158.           cmp       al, '*'
  159.           jz        Wild_gp
  160.           cmp       al,'?'
  161.           jz        Wild_gp
  162.           loop      AstQuest_gp
  163.           jmps      Ret_gp
  164. ;=======================================
  165. Wild_gp
  166.           or        Flag,WILDCARD
  167.  
  168.      ;[ Check for drive\dir spec. ]
  169.           sub       si,2                ; si points to char before wildcard
  170.           mov       cx,si
  171.           sub       cx,PATH - 1         ; cx = bytes to check
  172.           jle       Ret_gp              ; if negative or zero, no drive\dir
  173.           std                           ; direction = backward
  174. Back_gp
  175.           lodsb
  176.           cmp       al,'\'
  177.           jz        DDLen_gp            ; if '\' found, jump
  178.           cmp       al,':'
  179.           jz        DDLen_gp            ; if ':' found, jump
  180.           loop      Back_gp
  181. DDLen_gp                                ; cx = 0 on fall-through
  182.           mov       DrivDirLen, cx      ; cx = number of bytes in driv\dir spec
  183.           cld
  184. Ret_gp
  185.           clc
  186.           ret
  187.           ENDP
  188. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ MAIN ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  189. ;╒══════════════════════════════════════╕
  190. ;│             Convert                  │
  191. ;╘══════════════════════════════════════╛
  192. Convert   PROC      NEAR
  193.           call      OpenFile
  194.           jc        Error_cnv
  195.           call      ReadFile
  196.           jc        Error_cnv
  197.  
  198.           mov       VDXbytes,0          ; count of mode+definition bytes
  199.  
  200.           test      Flag,VDKINPUT or VDFINPUT
  201.           jnz       Macro_cnv
  202.  
  203.           call      TextToMac
  204.           jnc       Output_cnv
  205.           jmps      Error_cnv
  206. Macro_cnv
  207.           call      MacToText
  208.           jc        Error_cnv
  209. Output_cnv
  210.           call      WriteBuff
  211.           jc        Error_cnv
  212. Flags_cnv
  213.           and       Flag,FIXEDFLAGS OR WILDCARD
  214.           ret
  215. ;---------------------------------------
  216. Error_cnv
  217.           call      PutCrlf             ; out: ah = 0Eh
  218.           test      Flag,LINEERROR
  219.           jz        ErrMsg_cnv
  220.           mov       al,'<'
  221.           int       10h
  222.           mov       si,PATH
  223.           call      Puts
  224.           mov       al,'>'
  225.           int       10h
  226.           call      PutCrlf
  227.           mov       si,pLine
  228.           call      Puts
  229.           call      PutCrlf
  230.  
  231. ErrMsg_cnv
  232.           mov       si,dx
  233.           call      Puts
  234.  
  235.           test      Flag,SHOWOVERFLOW
  236.           jz        FileErr_cnv
  237.           mov       ax,VDXBytes
  238.           call      Putu
  239.           mov       si,offset Bmsg
  240.           jmps      Puts_cnv
  241.  
  242. FileErr_cnv
  243.           test      Flag,FILEERROR
  244.           jz        Ret_cnv
  245.           mov       si,PATH
  246. Puts_cnv
  247.           call      Puts
  248. Ret_cnv
  249.           call      PutCrlf
  250.           jmps      Flags_cnv
  251.           ENDP
  252. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ INPUT FILE ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  253. ;╒══════════════════════════════════════╕
  254. ;│               OpenFile               │
  255. ;│     checks extension, opens file     │
  256. ;│                                      │
  257. ;│ Out: CF clear, bx = handle           │
  258. ;│ Err: CF set,   dx = error message    │
  259. ;╘══════════════════════════════════════╛
  260. OpenFile  PROC      NEAR
  261.      ;[ find start of extension ]
  262.           mov       di,PATH
  263.           add       di,DrivDirLen       ; di = ptr to start of filename
  264.           mov       cx,9                ; max. 8-byte filename + 1
  265.           mov       al,'.'              ; scan for period
  266.           repne
  267.           scasb
  268.           jnz       Xx_opf              ; if not found, error. jump
  269.  
  270.      ;[ check 1st characters ]
  271.           mov       ax,[di]             ; ax should contain 'VT' or 'VD'
  272.           inc       di
  273.           mov       pMidExt,di          ; pMidExt points to 2nd char of extension
  274.           inc       di                  ; di points to 3rd char of extension
  275.           cmp       ax,'VT'
  276.           jz        Text_opf
  277.           cmp       ax,'VD'
  278.           jnz       Xx_opf
  279.  
  280.      ;[ macro file .VDx ]
  281.           cmp       byte [di],'K'
  282.           jnz       VDF_opf
  283.           or        Flag,VDKINPUT       ; VDK
  284.           mov       Indent,INDENTVTK
  285.           jmps      Open_opf
  286.  
  287. VDF_opf
  288.           cmp       byte [di],'F'
  289.           jnz       Xx_opf
  290.           or        Flag,VDFINPUT       ; VDF
  291.           mov       Indent,INDENTVTF
  292.           jmps      Open_opf
  293.  
  294.      ;[ text file .VTx ]
  295. Text_opf
  296.           cmp       byte [di],'K'
  297.           jnz       VTF_opf
  298.           or        Flag,VTKINPUT       ; VTK
  299.           jmps      Open_opf
  300.  
  301. VTF_opf
  302.           cmp       byte [di],'F'       ; VTF
  303.           jnz       Xx_opf
  304.           or        Flag,VTFINPUT       ; CF clear
  305.  
  306.      ;[ open file ]
  307. Open_opf
  308.           mov       dx,PATH             ; dx = ptr to filename
  309.           mov       ax,03D00h           ; open file, read access (al = 0)
  310.           int       21h
  311.           jc        Xo_opf              ; jump on error
  312.           mov       bx,ax               ; out: bx = handle.  CF clear.
  313.           ret
  314. ;---------------------------------------
  315. Xx_opf
  316.           mov       dx,offset XFxmsg
  317.           jmps      X_opf
  318. Xo_opf
  319.           mov       dx,offset XFomsg    ; "can't open" message
  320. X_opf
  321.           or        Flag,FILEERROR
  322.           stc
  323.           ret
  324.           ENDP
  325. ;╒══════════════════════════════════════╕
  326. ;│              ReadFile                │
  327. ;│   reads input file into buffer and   │
  328. ;│   closes file                        │
  329. ;│                                      │
  330. ;│  In: bx = handle                     │
  331. ;│ Out: Bytes = bytes read to buffer    │
  332. ;│ Err: CF set,   dx = error message    │
  333. ;╘══════════════════════════════════════╛
  334. ReadFile  PROC      NEAR
  335.           mov       dx,VDXBUFFER        ; address of buffer
  336.           mov       cx,VDXSIZE          ; bytes available
  337.           test      Flag,VDFINPUT OR VDKINPUT
  338.           jnz       Read_rdf
  339.           mov       dx,TEXTBUFFER       ; address of buffer
  340.           mov       cx,TEXTSIZE         ; bytes available
  341.  
  342. Read_rdf
  343.           mov       bp,cx               ; save buffer size in bp
  344.           mov       ah,03Fh             ; read file  (bx = handle)
  345.           int       21h
  346.           jc        Xr_rdf              ; jump on error
  347.           or        ax,ax
  348.           jz        Xr_rdf              ; if no bytes read, error. jump
  349.           mov       Bytes,ax            ; store bytes read
  350.  
  351.           cmp       ax,bp               ; is buffer completely full?
  352.           jz        Xl_rdf              ;   yes, file is too large. jump
  353.           clc
  354.  
  355.      ;[ close file ]
  356. Close_rdf
  357.           pushf
  358.           mov       ah,03Eh             ; (bx = handle)
  359.           int       21h
  360.           popf
  361.           ret
  362. ;---------------------------------------
  363. Xl_rdf
  364.           mov       dx,offset XFlmsg    ; "too large to handle" message
  365.           jmps      X_rdf
  366. Xr_rdf
  367.           mov       dx,offset XFrmsg    ; "read problem" message
  368. X_rdf
  369.           or        Flag,FILEERROR
  370.           stc
  371.           jmps      Close_rdf
  372.           ENDP
  373. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ MACRO --> TEXT ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  374. ;╒══════════════════════════════════════╕
  375. ;│              MacToText               │
  376. ;│converts .VDF or .VDK file in VDXBUFFR│
  377. ;│to text in TEXTBUFFER                 │
  378. ;│                                      │
  379. ;│ Out: di = limit of data in TEXTBUFFER│
  380. ;│ Err: CF set, dx = error message      │
  381. ;│                                      │
  382. ;│ Important registers:                 │
  383. ;│   si = ptr to macro file in VDXBUFFER│
  384. ;│   di = ptr to text in TEXTBUFFER     │
  385. ;│   bp = ptr to table of key names     │
  386. ;│   In macro loop:                     │
  387. ;│        dx = length of key name       │
  388. ;│   In def loop:                       │
  389. ;│        dl = length of key name       │
  390. ;│        dh = line length              │
  391. ;│        cx = bytes remaining in def   │
  392. ;│        al = byte of def              │
  393. ;╘══════════════════════════════════════╛
  394. MacToText PROC      NEAR
  395. ;=======================================
  396. ;[ I. check file ID ]
  397.           mov       si,VDXBUFFER
  398.           lodsw
  399.           cmp       ax,FILEID153
  400.           jz        Go_mtt
  401.           cmp       ax,FILEID170
  402.           jz        Check_mtt
  403.           mov       dx,offset XFimsg
  404.           or        Flag,FILEERROR
  405.           stc
  406.           ret
  407.  
  408. ;=======================================
  409. ;[ II. initialization ]
  410. Check_mtt
  411.           call      ChekLabel           ; sets ISLABEL Flag and Indent if label
  412. Go_mtt
  413.           mov       di,TEXTBUFFER       ; di = destination
  414.           test      Flag,VDFINPUT
  415.           jnz       VDF_mtt
  416.  
  417.           mov       bp,offset CharKeys     ; initialize ptr to key name table
  418.           mov       dx,CHARKEYLENGTH       ; length of key name
  419.           mov       pKeyLimit,CHARKEYLIMIT ; limit of table
  420.           jmps      MacStart_mtt
  421.  
  422. VDF_mtt
  423.           mov       bp,offset FuncKeys      ; initialize ptr to key name table
  424.           mov       dx,FUNCKEYLENGTH        ; length of key name
  425.           mov       pKeyLimit,NRMFUNCLIMIT  ; limit of table
  426.           jmps      MacStart_mtt
  427.  
  428. ;=======================================
  429. ;[ III. macro loop ]
  430.  
  431. AddCRLF_mtt
  432.           mov       ax,CRLF             ; write CRLF
  433.           stosw
  434.           xor       dh,dh               ; dx = length of key name
  435.  
  436. NextMac_mtt
  437.           add       bp,dx               ; advance ptr to next name in table
  438.           cmp       bp,pKeyLimit        ; end of table?
  439.           jz        CheckFunc_mtt       ;   yes, jump.
  440.           ;------------------------------
  441.  
  442. MacStart_mtt
  443.      ;[A. length ]
  444.           lodsb                         ; al = definition length
  445.           or        al,al               ; definition exists?
  446.           jnz       KeyName_mtt         ;   yes, jump to write name
  447.           test      Flag,USEDONLY       ; write used key names only?
  448.           jnz       NextMac_mtt         ;   yes, jump back
  449.                                         ;   no, write all names
  450.      ;[B. key name ]
  451. KeyName_mtt
  452.           mov       ah,al               ; save length of definition in ah
  453.           call      WriteKey
  454.           mov       cl,ah
  455.           xor       ch,ch               ; cx = bytes in definition
  456.           jcxz      AddCRLF_mtt         ;   if none, jump
  457.  
  458.           inc       cx                  ; include mode byte in count
  459.           add       VDXBytes,cx         ; update byte count for display
  460.           dec       cx
  461.  
  462.      ;[C. label ]
  463.           lodsb
  464.           mov       dh,al               ; dh = macflag: mode+autoexec+label bits
  465.           test      Flag,ISLABEL
  466.           jz        Mode_mtt
  467.           call      WritLabel
  468.  
  469.      ;[D. mode ]
  470. Mode_mtt
  471.           mov       bl,dh
  472.           and       bx,MODEBITS
  473.           add       bx,offset Mode      ; [bx] = space, Q, N, or B
  474.           test      dh,AUTOEXEC
  475.           jz        NoAuto_mtt
  476.           mov       al,'A'
  477.           mov       ah,[bx]
  478.           jmps      StoMode_mtt
  479. NoAuto_mtt
  480.           mov       al,[bx]
  481.           mov       ah,' '
  482. StoMode_mtt
  483.           stosw
  484.  
  485.      ;[E. equal sign ]
  486.           mov       ax,'= '
  487.           stosw
  488.  
  489.      ;[F. definition ]
  490.           call      WriteDef
  491.           jmps      AddCRLF_mtt
  492. ;=======================================
  493. CheckFunc_mtt                           ; see if F11,F12,etc. need to be shown
  494.           cmp       bp,NRMFUNCLIMIT
  495.           jnz       Ret_mtt
  496.           cmp       word [si],0         ; F11, F12
  497.           jnz       ShowExt_mtt
  498.           cmp       word [si+2],0       ; !F11,!F12
  499.           jnz       ShowExt_mtt
  500.           cmp       word [si+4],0       ; ^F11,^F12
  501.           jnz       ShowExt_mtt
  502.           cmp       word [si+6],0       ; @F11,@F12
  503.           jz        Ret_mtt
  504. ShowExt_mtt
  505.           mov       pKeyLimit,EXTFUNCLIMIT
  506.           jmps      MacStart_mtt
  507.  
  508. Ret_mtt
  509.           clc
  510.           ret
  511.           ENDP
  512. ;╒══════════════════════════════════════╕
  513. ;│              ChekLabel               │
  514. ;│ If .VDF file has any labels:         │
  515. ;│    sets ISLABEL Flag                 │
  516. ;│    resets Indent                     │
  517. ;│                                      │
  518. ;│ In: si = VDXBUFFER+2: start of macros│
  519. ;╘══════════════════════════════════════╛
  520. ChekLabel PROC      NEAR
  521.           xor       ah,ah
  522.           mov       cx,FUNCKEYNUMB
  523. Go_cl
  524.           lodsb                         ; al = length w/o flag byte
  525.           or        al,al
  526.           jz        Loop_cl
  527.           test      byte [si],LABELBIT  ; si points to flag byte
  528.           jnz       Flag_cl             ; if label, jump to set Flag
  529.           add       si,ax               ; else go to next macro
  530. Loop_cl
  531.           loop      Go_cl
  532. Ret_cl
  533.           mov       si,VDXBUFFER+2      ; si = start of macros
  534.           ret
  535. ;=======================================
  536. Flag_cl
  537.           or        Flag,ISLABEL
  538.           mov       Indent,INDENTVTFLBL
  539.           jmps      Ret_cl
  540.           ENDP
  541. ;╒══════════════════════════════════════╕
  542. ;│               WriteKey               │
  543. ;│ In: ah = definition length           │
  544. ;│     bp = ptr to key name             │
  545. ;│     di = ptr to TEXTBUFFER           │
  546. ;│Preserves: si, dl                     │
  547. ;╘══════════════════════════════════════╛
  548. WriteKey  PROC      NEAR
  549.           mov       al,'['
  550.           stosb
  551.           test      Flag,VDFINPUT
  552.           jnz       FuncKey_wk
  553.  
  554.      ;[ character key ]
  555.           mov       al,[bp]
  556.           stosb
  557.           xor       cx,cx
  558.           jmps      RghBraket_wk
  559.  
  560.      ;[ function key ]
  561. FuncKey_wk
  562.           mov       bx,si               ; save si in bx
  563.           mov       si,bp               ; si = ptr to key name
  564.           mov       cx,4                ; cx = max. length of name
  565. NextChar_wk
  566.           lodsb
  567.           or        al,al
  568.           jz        Restore_wk
  569.           stosb
  570.           loop      NextChar_wk
  571. Restore_wk
  572.           mov       si,bx               ; restore ptr to VDXBUFFER in si
  573.  
  574. RghBraket_wk
  575.           mov       al,']'
  576.           stosb
  577.           or        ah,ah               ; definition exists?
  578.           jz        Ret_wk              ;   no, jump
  579.  
  580.      ;[ write spaces ]
  581.           inc       cx
  582.           mov       al,' '
  583.           rep
  584.           stosb
  585. Ret_wk
  586.           ret
  587.           ENDP
  588. ;╒══════════════════════════════════════╕
  589. ;│              WritLabel               │
  590. ;│ In: dh = macro flag                  │
  591. ;│     si = ptr to byte after macro flag│
  592. ;│     di = ptr to text buffer          │
  593. ;│     cx = bytes remaining in macro    │
  594. ;│ Preserves: dl                        │
  595. ;╘══════════════════════════════════════╛
  596. WritLabel PROC      NEAR
  597.           mov       bx,cx                 ; save macro length in bx
  598.           mov       al,'<'
  599.           stosb
  600.           mov       cx,7
  601.           test      dh,LABELBIT
  602.           jz        NoLabel_wrl
  603.           sub       bx,cx               ; adjust bytes remaining
  604.           rep                           ; copy label
  605.           movsb
  606.           jmps      Done_wrl
  607.  
  608. NoLabel_wrl
  609.           mov       al,' '              ; no label: write spaces
  610.           rep
  611.           stosb
  612. Done_wrl
  613.           mov       ax,'> '
  614.           stosw
  615.           mov       cx,bx               ; restore bytes remaining in macro in cx
  616.           ret
  617.           ENDP
  618. ;╒══════════════════════════════════════╕
  619. ;│               WriteDef               │
  620. ;│ In: cx = bytes in definition         │
  621. ;│     si = ptr to definition           │
  622. ;│     di = ptr to TEXTBUFFER           │
  623. ;│     dl = length of name              │
  624. ;╘══════════════════════════════════════╛
  625. WriteDef  PROC      NEAR
  626.           mov       dh,Indent           ; dh = bytes already written to line
  627.           jmps      Space_wrd
  628. ;=======================================
  629. ;[--- new line of text ---]
  630. NewLine_wrd
  631.           call      NewLine
  632. Space_wrd
  633.           cmp       byte [si],' '       ; is first character a space?
  634.           jnz       GetByte_wrd         ;   no, jump
  635.           mov       byte [di],'`'       ;   yes, write special character (`)
  636.           inc       di                  ;        advance pointer
  637.           inc       dh                  ;        update line length
  638.           jmps      GetByte_wrd         ;        jump
  639. ;=======================================
  640. ;[--- definition loop ---]
  641. LineLeng_wrd
  642.           cmp       dh,MAXLINELENGTH    ; is this line already long enough?
  643.           jae       NewLine_wrd         ;   yes, jump to wrap def to new line
  644. GetByte_wrd
  645.           lodsb                         ; al = definition byte
  646.  
  647.      ;[<<DECISIONS>>]
  648.           cmp       al,' '              ; al < space ?
  649.           jb        Ctrl_wrd            ;   yes, control character. jump
  650.           cmp       al,0FFh             ; al = FFh ?
  651.           jz        FF_wrd              ;   yes, jump
  652.           cmp       al,'@'              ; check for characters @ ^ `
  653.           jz        AtCaretAcut_wrd
  654.           cmp       al,'^'
  655.           jz        AtCaretAcut_wrd
  656.           cmp       al,'`'
  657.           jz        AtCaretAcut_wrd
  658.           cmp       al,07Fh             ; ^BkSp?
  659.           jz        CtrlBkSp_wrd
  660.  
  661.      ;-----------------------
  662.      ;[ store one character ]
  663. StoreByte_wrd
  664.           stosb                         ; write one byte
  665.           inc       dh                  ; update line length
  666.           loop      LineLeng_wrd        ; loop back to get check line length
  667.           jmps      EndDef_wrd
  668.  
  669.      ;----------------------------
  670.      ;[ Special character: @ ^ ` ]
  671. AtCaretAcut_wrd
  672.           mov       byte [di],'`'       ; write "no translation" character (`)
  673.           inc       di                  ; advance pointer
  674.           inc       dh                  ; update line length
  675.           jmps      StoreByte_wrd       ; jump to store character
  676.  
  677.      ;----------------------
  678.      ;[ key names: "[xxxxx]" ]
  679. FFSpecial_wrd
  680.           call      FndKeyNam
  681.           jmps      WriteName_wrd
  682. CtrlBkSp_wrd
  683.           mov       bx,offset CtrlBkSp
  684.           jmps      WriteName_wrd
  685. CtrlEsc_wrd
  686.           mov       bx,offset CtrlEsc
  687.           jmps      WriteName_wrd
  688. Esc_wrd
  689.           mov       bx,offset EscKey
  690.  
  691. WriteName_wrd
  692.           xchg      bx,si               ; save ptr to def in bx. si = name.
  693. WriteNext_wrd
  694.           lodsb
  695.           stosb
  696.           inc       dh
  697.           cmp       al,']'
  698.           jnz       WriteNext_wrd
  699.           mov       si,bx               ; restore ptr to definition in si
  700.           loop      LineLeng_wrd        ; loop back to check line length
  701.           jmps      EndDef_wrd          ; else jump to end processing
  702.  
  703.      ;----------
  704.      ;[ <Ctrl> ]
  705. Ctrl_wrd
  706.           cmp       al,ESCAPE           ; Esc?
  707.           jz        Esc_wrd             ;   yes, jump to write '[Esc]'
  708.           mov       ah,al               ; change 1-->^A, 2-->^B, 3-->^C,....
  709.           add       ah,'A'-1
  710.           mov       al,'^'
  711.           stosw
  712.           add       dh,2                ; update line length
  713.           loop      LineLeng_wrd        ; loop back to check line length
  714.           jmps      EndDef_wrd          ; else jump to end processing
  715.  
  716.      ;--------------------
  717.      ;[ ASCII code = FFh ]
  718. FF_wrd
  719.           lodsb                         ; get next byte
  720.           dec       cx                  ; reduce bytes remaining
  721.  
  722.          ;[<<DECISIONS>>]
  723.           cmp       al,LOWESTALTX
  724.           jb        FFSpecial_wrd
  725.           cmp       al,HIGHESTALTX
  726.           ja        FFSpecial_wrd
  727.           cmp       al,0AAh             ; CtrlEsc ?
  728.           jz        CtrlEsc_wrd         ;   yes, jump
  729.  
  730.           call      WriteAltX           ; write '@X'
  731.           loop      LineLeng_wrd        ; loop back to check line length
  732.                                         ; else fall through to end processing
  733. ;=======================================
  734. ;[--- end of definition ---]
  735. EndDef_wrd
  736.           cmp       byte [di-1],' '     ; does macro end with a space?
  737.           jz        AddSpecial_wrd      ;   yes, jump
  738.           ret
  739. AddSpecial_wrd
  740.           mov       word [di-1],'` '    ;   change space to "` " as visual aid
  741.           inc       di                  ;        advance pointer
  742.           ret
  743.           ENDP
  744. ;╒══════════════════════════════════════╕
  745. ;│               NewLine                │
  746. ;│        wraps line in TEXTBUFFER      │
  747. ;│                                      │
  748. ;│  In: di = ptr to TEXTBUFFER          │
  749. ;│ Out: dh = bytes written to new line  │
  750. ;│ Preserves: cx (bytes in definition)  │
  751. ;│            dl (length of key name)   │
  752. ;╘══════════════════════════════════════╛
  753. NewLine   PROC      NEAR
  754.           mov       bx,cx               ; save bytes remaining in bx
  755.  
  756.      ;[ check end of current line for space ]
  757.           cmp       byte [di-1],' '     ; does line end with a space?
  758.           jnz       CRLF_nwl            ;   no, jump
  759.           mov       word [di-1],'` '    ;   yes, change to "` " as visual aid
  760.           inc       di                  ;        advance pointer
  761. CRLF_nwl
  762.           mov       ax,CRLF             ; write CRLF
  763.           stosw
  764.  
  765.      ;[ set up indentation of new line ]
  766.           mov       dh,Indent           ; start of definition
  767.           mov       cl,dh
  768.           xor       ch,ch
  769.           sub       cx,2                ; allow 2 bytes for '= '
  770.           mov       al,' '              ; write spaces
  771.           rep
  772.           stosb
  773.           mov       ax,'= '
  774.           stosw
  775.  
  776.           mov       cx,bx               ; restore bytes remaining in cx
  777.           ret
  778.           ENDP
  779. ;╒══════════════════════════════════════╕
  780. ;│              WriteAltX               │
  781. ;│ In: al = scan code for Alt + Letter  │
  782. ;│ Out: writes '@X' to TEXTBUFFER       │
  783. ;│      updates dh (line length)        │
  784. ;│ Preserves: cx                        │
  785. ;╘══════════════════════════════════════╛
  786. WriteAltX PROC      NEAR
  787.           push      cx
  788.           mov       bx,di               ; save ptr to TEXTBUFFER in bx
  789.           mov       di,offset AltXScan  ; scan table of scan codes
  790.           mov       cx,ALTXNUMB
  791.           repne
  792.           scasb                         ; cx = reverse index into alphabet
  793.           mov       di,bx               ; restore ptr to TEXTBUFFER in di
  794.  
  795.           mov       bx,LASTLETTER       ; bx = ptr to last letter of alphabet
  796.           sub       bx,cx               ; subtract index
  797.           mov       ah,[bx]             ; ah = letter
  798.           mov       al,'@'              ; al = '@'
  799.           stosw                         ; store in TEXTBuFF
  800.           add       dh,2                ; update line length
  801.           pop       cx
  802.           ret
  803.           ENDP
  804. ;╒══════════════════════════════════════╕
  805. ;│              FndKeyNam               │
  806. ;│ In: al = scan code                   │
  807. ;│Out: bx = address of key name         │
  808. ;│Preserves: cx,di                      │
  809. ;╘══════════════════════════════════════╛
  810. FndKeyNam PROC      NEAR
  811.           push      cx
  812.           mov       bx,di               ; save ptr to TEXTBUFFER in bx
  813.           mov       di,offset KeyCodes  ; scan table of codes
  814.           mov       cx,KEYCODENUMB
  815.           repne
  816.           scasb                         ; cx = reverse index into list of names
  817.           mov       di,bx               ; restore ptr to TEXTBUFFER in di
  818.  
  819.           mov       bx,LASTKEYNAME      ; bx = ptr to last entry in name list
  820.           shl       cx                  ; index --> offset (8 bytes/name)
  821.           shl       cx
  822.           shl       cx
  823.           sub       bx,cx               ; subtract offset
  824.           pop       cx
  825.           ret
  826.           ENDP
  827. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ TEXT --> MACROS ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  828. ;╒══════════════════════════════════════╕
  829. ;│              TextToMac               │
  830. ;│  converts text file in TEXTBUFFER to │
  831. ;│  macros in VDXBUFFER                 │
  832. ;│                                      │
  833. ;│ Out: di = limit of data in VDXBUFFER │
  834. ;│ Err: CF set, dx = error message      │
  835. ;╘══════════════════════════════════════╛
  836. TextToMac PROC      NEAR
  837.      ;[ initialization ]
  838.           test      Flag,CAPITALIZED
  839.           jnz       Init_ttm
  840.           call      CapNames
  841. Init_ttm
  842.           mov       bx,VDXBUFFER        ; bx = ptr to VDXBUFFER
  843.           mov       pTextMark,TEXTBUFFER
  844.           mov       ax,FILEID153
  845.           mov       pMacLimit,MACLIMIT5
  846.  
  847.           test      Flag,VTKINPUT
  848.           jnz       VTK_ttm
  849.  
  850.          ;[ function key macros ]
  851.           mov       pKey,offset FuncKeys         ; ptr to table of key names
  852.           mov       pFindMacKy,offset FindFncKy  ; ptr to search procedure
  853.           test      Flag,VERSION170
  854.           jz        Version_ttm
  855.           mov       ax,FILEID170
  856.           mov       pMacLimit,MACLIMIT7
  857.           jmps      Version_ttm
  858.  
  859. VTK_ttm   ;[ character key macros ]
  860.           mov       pKey,offset CharKeys         ; ptr to table of key names
  861.           mov       pFindMacKy,offset FindChrKy  ; ptr to search procedure
  862.           test      Flag,VERSION170
  863.           jz        Version_ttm
  864.           mov       dx,offset XFvmsg
  865.           or        Flag,FILEERROR
  866.           stc
  867.           ret
  868. ;---------------------------------------
  869. Version_ttm
  870.           mov       [bx],ax             ; store version number in VDXBUFFER
  871.           add       bx,2
  872. ;=======================================
  873. ;[ MAIN LOOP ]
  874. Line_ttm
  875.           call      GetLine             ; get data line
  876.           jc        Zero_ttm            ;   if none, done. jump
  877.  
  878. Find_ttm
  879.           call      pFindMacKy          ; out: si points to byte after name
  880.           jc        Xn_ttm              ;   jump on error
  881.           call      ModeLabel           ; out: si points to 1st byte of def
  882.           jc        Ret_ttm             ;   jump on error
  883.           or        si,si               ; does definition exist?
  884.           jz        NoDef_ttm           ;   no, jump
  885. Def_ttm
  886.           call      TextToDef           ; convert text to macro definition
  887.           jc        Ret_ttm             ; jump on error
  888.  
  889. Line2_ttm
  890.           call      GetLine             ; get next line
  891.           jc        Copy_ttm            ;   if none, jump to copy current macro
  892.           cmp       byte [si],'['       ; new macro key?
  893.           jz        Copy_ttm            ;   yes, jump to copy current macro
  894.           inc       si                  ;   no, continuation. advance beyond '='
  895.  
  896.      ;[ continuation: find start of definition ]
  897.           call      SkipSpace
  898.           jc        Line2_ttm           ; if end of line, get another one
  899.           dec       si                  ; move back to start of definition
  900.           jmps      Def_ttm             ; jump to convert
  901.  
  902.      ;[ copy macro to VDXBUFFER]
  903. Copy_ttm
  904.           call      CopyMacro
  905.           jc        Ret_ttm
  906.           or        si,si               ; end of text file?
  907.           jnz       Find_ttm            ;   no, jump to process next macro
  908.           jmps      Zero_ttm            ;   yes, zero out rest of VDXBUFFER
  909.  
  910.      ;[ no definition ]
  911. NoDef_ttm
  912.           mov       byte [bx],0         ; add 0 to VDXBUFFER
  913.           inc       bx                  ; advance pointer
  914.           jmps      Line_ttm
  915.  
  916.      ;[ zero out rest of file ]
  917. Zero_ttm
  918.           mov       di,bx               ; bx = limit of data in VDXBUFFER
  919.           mov       cx,VDXFILELIMIT     ; = VDXBUFFER + 1024
  920.           sub       cx,di               ; cx = limit of file - limit of data
  921.           xor       ax,ax               ; write zeros
  922.           shr       cx                  ; cx = words to write
  923.           rep
  924.           stosw
  925.           adc       cx,0                ; do last byte if it exists
  926.           rep
  927.           stosb                         ; out: di = limit of data in VDXBUFFER
  928.  
  929.      ;[ final check for V1.70+ macros ]
  930.           test      Flag,AUTOEXECSET or ISLABEL
  931.           jz        Ret_ttm
  932.           test      Flag,VTKINPUT               ; .VTK file?
  933.           jnz       Xk_ttm                      ;   yes, error. jump
  934.           mov       word [VDXBUFFER],FILEID170  ; set file ID in case /7 option
  935. Ret_ttm                                         ;   wasn't specified
  936.           ret
  937. ;---------------------------------------
  938. Xn_ttm
  939.           mov       dx,offset XLnmsg
  940.           or        Flag,LINEERROR
  941.           jmps      X_ttm
  942. Xk_ttm
  943.           mov       dx,offset XFkmsg
  944.           or        Flag,FILEERROR
  945. X_ttm
  946.           stc
  947.           ret
  948.           ENDP
  949. ;╒══════════════════════════════════════╕
  950. ;│              CapNames                │
  951. ;│ Makes capitalized key name table at  │
  952. ;│ CAPKEYNAMES                          │
  953. ;╘══════════════════════════════════════╛
  954. CapNames  PROC      NEAR
  955.           mov       si,offset KeyNames
  956.           mov       di,CAPKEYNAMES
  957.           mov       cx,KEYNAMELENGTH * KEYNAMENUMB
  958. Next_ntu
  959.           lodsb
  960.           cmp       al,'a'
  961.           jb        Store_ntu
  962.           cmp       al,'z'
  963.           ja        Store_ntu
  964.           and       al,CAPMASK
  965. Store_ntu
  966.           stosb
  967.           loop      Next_ntu
  968.           or        Flag,CAPITALIZED
  969.           ret
  970.           ENDP
  971. ;╒══════════════════════════════════════╕
  972. ;│              GetLine                 │
  973. ;│gets start of next data line, skipping│
  974. ;│   comment lines and blank lines      │
  975. ;│puts 0 at limit of defintion, that is │
  976. ;│   changes line to ASCIZ string       │
  977. ;│                                      │
  978. ;│  In: pTextMark = ptr to TEXTBUFFER   │
  979. ;│      Bytes = bytes remaining         │
  980. ;│ Out: si = pLine = ptr to next line   │
  981. ;│      pTextMark = limit of line       │
  982. ;│      Bytes updated                   │
  983. ;│      CF clear                        │
  984. ;│Else: if end of buffer, CF set & si=0 │
  985. ;╘══════════════════════════════════════╛
  986. GetLine   PROC      NEAR
  987.           mov       di,pTextMark        ; starting place in TEXTBUFFER
  988.           mov       cx,Bytes            ; bytes remaining in TEXTBUFFER
  989.  
  990. ;=======================================
  991. ;[ I. find start of next line ]
  992.           cmp       di,TEXTBUFFER       ; at beginning of buffer?
  993.           jz        Skip_gtl            ;   yes, jump
  994.  
  995.      ;[ scan to next LF ]
  996. Next_gtl
  997.           mov       al,LF
  998.           repne
  999.           scasb
  1000.           jcxz      None_gtl            ; if no more bytes, jump
  1001.  
  1002.      ;[ skip initial whitespace ]
  1003. Skip_gtl
  1004.           cmp       byte [di],' '
  1005.           ja        Check_gtl           ; if [di] > ' ', jump to check
  1006.           jb        Inc_gtl             ; if [di] < ' ' (CR,LF,Tab), jump to skip
  1007.           mov       al,' '              ; if [di] = ' ', scan past spaces
  1008.           repe
  1009.           scasb
  1010.           jcxz      None_gtl            ; if no more bytes, done
  1011.           dec       di                  ; go back to 1st non-space character
  1012.           inc       cx                  ; update byte count
  1013.           cmp       byte [di],' '       ; is [di] a CR,LF or Tab?
  1014.           ja        Check_gtl           ;   no, jump to check
  1015. Inc_gtl
  1016.           inc       di
  1017.           dec       cx
  1018.           jnz       Skip_gtl
  1019. None_gtl
  1020.           xor       si,si
  1021.           stc
  1022.           ret
  1023.  
  1024.      ;[ check for comment ]
  1025. Check_gtl
  1026.           cmp       cx,3                ; less than 3 bytes left (i.e. "= x")
  1027.           jb        None_gtl            ;   yes, can't be any more macros. done
  1028.           mov       al,[di]             ; dl = first character
  1029.           cmp       al,'['              ; '[' ?
  1030.           jz        Start_gtl           ;   yes, found start, jump
  1031.           cmp       al,'='              ; '=' ?
  1032.           jnz       Next_gtl            ;   no, it's a comment, try again
  1033.                                         ;   yes, found start
  1034.      ;[ save start ]
  1035. Start_gtl
  1036.           mov       si,di               ; out: si = ptr to line
  1037.           mov       pLine,si            ; store start for writing error message
  1038.  
  1039. ;=======================================
  1040. ;[ II. find limit of line ]
  1041.      ;[ scan to next LF ]
  1042.           mov       al,LF
  1043.           repne
  1044.           scasb
  1045.           jz        LF_gtl              ; if LF found, jump
  1046.  
  1047.      ;[ LF not found: end of buffer ]
  1048.           cmp       byte [di-1],EOF     ; is EOF last character in buffer?
  1049.           jnz       Set_gtl             ;    no, jump
  1050.           dec       di                  ;    yes, move back one byte to EOF
  1051.           jmps      Set_gtl
  1052.  
  1053.      ;[ LF found ]
  1054. LF_gtl
  1055.           sub       di,2                ; go back to CR
  1056.           add       cx,2                ; adjust remaining bytes
  1057.  
  1058. ;=======================================
  1059. ;[ III. set variables ]
  1060. Set_gtl
  1061.           mov       pTextMark,di        ; store position for next call
  1062.           mov       Bytes,cx            ; store remaining bytes
  1063.  
  1064. ;=======================================
  1065. ;[ IV. remove comments from end of line ]
  1066.           mov       cx,di               ; di = limit of line
  1067.           sub       cx,si               ; cx = limit - start = length
  1068.           mov       di,si               ; di = start of line
  1069.           mov       al,';'              ; look for ';'
  1070. Semi_gtl
  1071.           repne
  1072.           scasb
  1073.           jcxz      Done_gtl            ; if end of line, done (di = mac limit)
  1074.           cmp       byte [di],';'       ; found. next character = ';'?
  1075.           jnz       Semi_gtl            ;   no, go back and check some more
  1076.           cmp       byte [di-2],' '     ; byte before 1st ';' = space ?
  1077.           jnz       Semi_gtl            ;   no, go back and check some more
  1078.  
  1079.      ;[ found comment. find end of macro ]
  1080.           sub       di,2                ; di points to space
  1081.           mov       cx,di
  1082.           sub       cx,si               ; cx = di - start = bytes to start - 1
  1083.           mov       al,' '              ; skip spaces
  1084.           std                           ; go backward
  1085.           repe
  1086.           scasb
  1087.           cld                           ; clear direction flag
  1088.           inc       di                  ; go forward to last non-space character
  1089.           cmp       byte [di],'`'       ; is it a special character?
  1090.           jnz       Zero_gtl            ;    no, jump to put '0'
  1091.           inc       di                  ;    yes, include 1 space
  1092. Zero_gtl
  1093.           inc       di
  1094. Done_gtl
  1095.           mov       byte [di],0         ; zero out limit of macro
  1096.           clc
  1097.           ret
  1098.           ENDP
  1099. ;╒══════════════════════════════════════╕
  1100. ;│              FindChrKy               │
  1101. ;│  In: si = ptr to key name in TEXTBUFF│
  1102. ;│      bx = ptr to VDXBUFFER           │
  1103. ;│    pKey = ptr to table of key names  │
  1104. ;│                                      │
  1105. ;│ Out: si points to 1st byte after name│
  1106. ;│      bx,pKey updated                 │
  1107. ;│ Err: CF set, dx = error message      │
  1108. ;╘══════════════════════════════════════╛
  1109. FindChrKy PROC      NEAR
  1110.           lodsb
  1111.           cmp       al,'['              ; check left bracket
  1112.           jnz       X_fck
  1113.           lodsb                         ; al = character key
  1114.           cmp       byte [si],']'       ; check right bracket
  1115.           jnz       X_fck
  1116.           inc       si                  ; out: si points to byte after key name
  1117.           mov       di,pKey             ; di = ptr into list of character keys
  1118.           cmp       al,'A'              ; if number, jump
  1119.           jb        Next_fck
  1120.           and       al,CAPMASK          ; capitalize letter
  1121.  
  1122. Next_fck
  1123.           cmp       di,CHARKEYLIMIT     ; beyond last key?
  1124.           jz        X_fck               ;   yes, error
  1125.           cmp       al,[di]
  1126.           jz        Done_fck            ; if found, done
  1127.           inc       di                  ; else advance di to next character key
  1128.           mov       byte [bx],0         ;      add 0 to VDXBUFFER
  1129.           inc       bx                  ;      advance pointer
  1130.           jmps      Next_fck
  1131.  
  1132. Done_fck
  1133.           inc       di                  ; advance di to next character key
  1134.           mov       pKey,di             ; update pKey
  1135.           clc
  1136.           ret
  1137. ;---------------------------------------
  1138. X_fck
  1139.           stc
  1140.           ret
  1141.           ENDP
  1142. ;╒══════════════════════════════════════╕
  1143. ;│              FindFncKy               │
  1144. ;│  In: si = start of key name          │
  1145. ;│      bx = ptr to VDXBUFFER           │
  1146. ;│    pKey = ptr to table of key names  │
  1147. ;│                                      │
  1148. ;│ Out: si = 1 byte after key name      │
  1149. ;│      bx,pKey updated                 │
  1150. ;│ Err: CF set,   dx = error message    │
  1151. ;╘══════════════════════════════════════╛
  1152. FindFncKy PROC      NEAR
  1153.           lodsb
  1154.           cmp       al,'['              ; check left bracket
  1155.           jnz       X_ffk
  1156.           mov       bp,si               ; save start of target in bp
  1157.  
  1158.      ;[ capitalize 'f' if necessary ]
  1159.           cmp       byte [si],'f'
  1160.           jz        BigF_ffk
  1161.           inc       si
  1162.           cmp       byte [si],'f'
  1163.           jnz       Length_ffk
  1164. BigF_ffk
  1165.           mov       byte [si],'F'
  1166.  
  1167.      ;[ get length of key name from data line ]
  1168. Length_ffk
  1169.           mov       di,bp               ; di = start of target
  1170.           mov       al,']'              ; look for right bracket
  1171.           mov       cx,FUNCKEYLENGTH+1  ; max. name length + right bracket
  1172.           repne
  1173.           scasb
  1174.           jnz       X_ffk               ; if no bracket, error. jump
  1175.           neg       cx
  1176.           add       cx,FUNCKEYLENGTH    ; cx = length of name
  1177.           cmp       cx,1
  1178.           jbe       X_ffk               ; if '[]' or '[x]', error
  1179.           mov       dx,cx               ; save length in dx
  1180.           mov       ax,pKey             ; ax = ptr to table of names
  1181.  
  1182. Next_ffk
  1183.           cmp       ax,EXTFUNCLIMIT     ; beyond last name?
  1184.           jz        X_ffk               ;   yes, error
  1185.  
  1186.           mov       di,ax               ; di = ptr to key name
  1187.           add       ax,FUNCKEYLENGTH    ; advance ptr to next key
  1188.           mov       si,bp               ; si = ptr to target name
  1189.           mov       cx,dx               ; cx = bytes to check
  1190.           repe
  1191.           cmpsb
  1192.           jz        Check_ffk           ; if found, jump to check
  1193.  
  1194.      ;[ add 0 to buffer ]
  1195.           mov       byte [bx],0
  1196.           inc       bx
  1197.           jmps      Next_ffk
  1198.  
  1199. Check_ffk                               ; check for mismatch of [xF1] against
  1200.           cmp       di,ax               ;   [xF10],[xF11],or [xF12]
  1201.           jz        Done_ffk            ; if target was 4 characters long, OK
  1202.           cmp       byte [di],0         ; if not, di should point to 0.
  1203.           jnz       X_ffk
  1204. Done_ffk                                ;   (CF clear if ZF set)
  1205.           inc       si                  ; move si past right bracket
  1206.           mov       pKey,ax             ; store ptr to next name
  1207.           ret
  1208. ;---------------------------------------
  1209. X_ffk
  1210.           stc
  1211.           ret
  1212.           ENDP
  1213. ;╒══════════════════════════════════════╕
  1214. ;│              SkipSpace               │
  1215. ;│ In: si = ptr to ASCIZ string         │
  1216. ;│Out: CF clear                         │
  1217. ;│        al = non-space non-tab char   │
  1218. ;│        si = ptr to next byte         │
  1219. ;│     CF set if end of line            │
  1220. ;╘══════════════════════════════════════╛
  1221. SkipSpace PROC      NEAR
  1222.           lodsb
  1223.           or        al,al               ; end of line?
  1224.           jz        STC_sksp            ;       yes, jump
  1225.           cmp       al,' '              ; space or tab?
  1226.           jbe       SkipSpace           ;   yes, try again
  1227.           ret                           ; if al > ' ', CF clear
  1228. STC_sksp
  1229.           stc
  1230.           ret
  1231.           ENDP
  1232. ;╒══════════════════════════════════════╕
  1233. ;│             ModeLabel                │
  1234. ;│      writes mode code to buffer.     │
  1235. ;│      writes label to buffer          │
  1236. ;│      initializes pMacMark            │
  1237. ;│      finds start of definition.      │
  1238. ;│                                      │
  1239. ;│  In: si = one byte past key name     │
  1240. ;│                                      │
  1241. ;│ Def exists: CF clear, si = start     │
  1242. ;│ No def:     CF clear, si = 0         │
  1243. ;│ Err:        CF set, dx = error msg   │
  1244. ;╘══════════════════════════════════════╛
  1245. ModeLabel PROC      NEAR
  1246.           mov       pMacMark,MACSTART1  ; initialize ptr to MACBUFFER
  1247.           mov       byte [MACFLAG],0    ; initialize macro flag
  1248.           call      SkipSpace
  1249.           jc        NoDef_gml           ; if end of line, no definition. jump
  1250.  
  1251.      ;[ label ]
  1252.           cmp       al,'<'
  1253.           jnz       Mode_gml
  1254.           call      GetLabel
  1255.           jc        X_gml
  1256.           call      SkipSpace
  1257.           jc        NoDef_gml
  1258.  
  1259.      ;[ mode ]
  1260. Mode_gml
  1261.           call      GetMode
  1262.           jc        X_gml
  1263.           or        al,al               ; if end of line, no definition
  1264.           jz        NoDef_gml
  1265.           cmp       al,' '              ; if space or tab....
  1266.           ja        Equals_gml
  1267.           call      SkipSpace           ;    ....skip
  1268.           jc        NoDef_gml
  1269.  
  1270.      ;[ equal sign ]
  1271. Equals_gml
  1272.           cmp       al,'='
  1273.           jnz       Xe_gml
  1274.  
  1275.      ;[ definition ]
  1276.           call      SkipSpace
  1277.           jc        NoDef_gml           ; if end of line, no def. jump
  1278.           dec       si                  ; move back to start of definition
  1279.           ret                           ; def exists: CF clear, si = start
  1280. ;---------------------------------------
  1281. NoDef_gml
  1282.           xor       si,si               ; no def: CF clear, si = 0
  1283.           ret
  1284. ;---------------------------------------
  1285. Xe_gml
  1286.           mov       dx,offset XLemsg
  1287. X_gml
  1288.           or        Flag,LINEERROR
  1289.           stc
  1290.           ret
  1291.           ENDP
  1292. ;╒══════════════════════════════════════╕
  1293. ;│               GetLabel               │
  1294. ;│ In: si = first byte after '<'        │
  1295. ;│Out: si = first byte after '>'        │
  1296. ;│     pMacMark updated                 │
  1297. ;│     ISLABEL flag set if label exists │
  1298. ;╘══════════════════════════════════════╛
  1299. GetLabel  PROC      NEAR
  1300.           xor       cx,cx               ; cl = characters, ch = spaces
  1301.           mov       di,si               ; save start in di
  1302. Next_glb
  1303.           lodsb
  1304.           or        al,al               ; end of line?
  1305.           jz        X_glb               ;   yes, error. jump
  1306.           cmp       al,'>'              ; end of label?
  1307.           jz        Length_glb          ;   yes, jump
  1308.           inc       cl                  ; count 1 character
  1309.           js        X_glb               ;   if sign, label is much too long
  1310.           cmp       al,' '              ; space?
  1311.           jnz       Next_glb            ;   no, jump
  1312.           inc       ch                  ;   yes, count 1 space
  1313.           jmps      Next_glb
  1314.  
  1315. Length_glb
  1316.           cmp       cl,7
  1317.           ja        X_glb               ; if over 7 bytes, too long. jump
  1318.           cmp       cl,ch               ; if spaces = characters, no label
  1319.           jz        Ret_glb             ;    (CF clear if ZF set)
  1320.  
  1321.      ;[ label exists ]
  1322.           or        byte [MACFLAG],LABELBIT  ; set macro flag
  1323.           mov       pMacMark,MACSTART2       ; update pointer into MACBUFFER
  1324.           xor       ch,ch
  1325.           mov       dx,cx               ; save number of characters in dx
  1326.           mov       si,di               ; si = start of label
  1327.           mov       di,MACSTART1        ; di = destination in MACBUFFER
  1328.           rep                           ; copy label to buffer
  1329.           movsb
  1330.           mov       cx,7                ; pad with spaces
  1331.           sub       cx,dx
  1332.           mov       al,' '
  1333.           rep
  1334.           stosb
  1335.           inc       si                  ; advance si past '>'
  1336.           or        Flag,ISLABEL        ; (CF clear)
  1337. Ret_glb
  1338.           mov       pMacLimit,MACLIMIT7 ; set def length to 255 bytes just in
  1339.           ret                           ;    case /7 option wasn't specified
  1340. ;---------------------------------------
  1341. X_glb
  1342.           mov       dx,offset XLlmsg
  1343.           stc
  1344.           ret
  1345.           ENDP
  1346. ;╒══════════════════════════════════════╕
  1347. ;│               GetMode                │
  1348. ;│ In: al = character to check          │
  1349. ;│     si = ptr to next byte            │
  1350. ;│Out: al = first non-mode character    │
  1351. ;│     si = next byte                   │
  1352. ;╘══════════════════════════════════════╛
  1353. GetMode   PROC      NEAR
  1354.           xor       ah,ah               ; code: 0  for nothing
  1355.           jmps      Equals_gmd
  1356.  
  1357. NextMod_gmd
  1358.           lodsb
  1359.           or        al,al
  1360.           jz        Ret_gmd
  1361.           cmp       al,' '
  1362.           jz        Store_gmd
  1363. Equals_gmd
  1364.           cmp       al,'='
  1365.           jz        Store_gmd
  1366.  
  1367.           and       al,CAPMASK
  1368.           cmp       al,'N'
  1369.           jz        N_gmd
  1370.           cmp       al,'Q'
  1371.           jz        Q_gmd
  1372.           cmp       al,'B'
  1373.           jz        B_gmd
  1374.           cmp       al,'A'
  1375.           jnz       Xm_gmd
  1376.           test      Flag,VTKINPUT
  1377.           jnz       Xy_gmd
  1378.           test      Flag,AUTOEXECSET
  1379.           jnz       Xx_gmd
  1380.           or        Flag,AUTOEXECSET
  1381.           mov       pMacLimit,MACLIMIT7  ; set macro length to 255 bytes in case
  1382.           mov       cl,AUTOEXEC          ;    /7 option wasn't specified
  1383.           jmps      SetMode_gmd
  1384. N_gmd
  1385.           mov       cl,NOREPEAT
  1386.           jmps      Test_gmd
  1387. Q_gmd
  1388.           mov       cl,QUIET
  1389.           jmps      Test_gmd
  1390. B_gmd
  1391.           mov       cl,BOTH
  1392.  
  1393. Test_gmd
  1394.           test      ah,cl               ; already set?
  1395.           jnz       Xm_gmd              ; yes, error. jump
  1396. SetMode_gmd
  1397.           or        ah,cl               ; set ah
  1398.           jmps      NextMod_gmd
  1399.  
  1400. Store_gmd
  1401.           or        [MACFLAG],ah        ;  store code in MACBUFFER
  1402. Ret_gmd
  1403.           clc
  1404.           ret
  1405. ;---------------------------------------
  1406. Xm_gmd
  1407.           mov       dx,offset XLmmsg
  1408.           jmps      X_gmd
  1409. Xx_gmd
  1410.           mov       dx,offset XLxmsg
  1411.           jmps      X_gmd
  1412. Xy_gmd
  1413.           mov       dx,offset XLymsg
  1414. X_gmd
  1415.           stc
  1416.           ret
  1417.           ENDP
  1418. ;╒══════════════════════════════════════╕
  1419. ;│              TextToDef               │
  1420. ;│converts text to definition in MACBUFF│
  1421. ;│                                      │
  1422. ;│  In: si = ptr to text definition     │
  1423. ;│      pMacMark = ptr to MACBUFFER     │
  1424. ;│ Out: pMacMark updated, CF clear      │
  1425. ;│ Err: CF set,   dx = error message    │
  1426. ;╘══════════════════════════════════════╛
  1427. TextToDef PROC      NEAR
  1428.           mov       di,pMacMark         ; di = ptr to MACBUFFER
  1429. Next_ttd
  1430.           lodsb
  1431.  
  1432.      ;[<<DECISIONS>>]
  1433.           or        al,al               ; end of line?
  1434.           jz        End_ttd             ;   yes, jump
  1435.           cmp       al,'^'
  1436.           jz        Ctrl_ttd
  1437.           cmp       al,'@'
  1438.           jz        Alt_ttd
  1439.           cmp       al,'`'
  1440.           jz        Spec_ttd
  1441.           cmp       al,'['
  1442.           jz        Name_ttd
  1443.  
  1444.      ;[ ordinary character ]
  1445.           stosb
  1446.           jmps      Next_ttd
  1447.  
  1448.      ;[ '^' character ]
  1449. Ctrl_ttd
  1450.           call      StoreCtrl
  1451.           jnc       Next_ttd
  1452.           jmps      X_ttd
  1453.  
  1454.      ;[ '@' character ]
  1455. Alt_ttd
  1456.           call      StoreAlt
  1457.           jnc       Next_ttd
  1458.           jmps      X_ttd
  1459.  
  1460.      ;[ '`' character ]
  1461. Spec_ttd
  1462.           lodsb
  1463.           or        al,al               ; end of line?
  1464.           jz        Xc_ttd              ;   yes, error. jump
  1465.           stosb
  1466.           jmps      Next_ttd
  1467.  
  1468.      ;[ key name: [xxxxx] ]
  1469. Name_ttd
  1470.           call      StoreName
  1471.           jmps      Next_ttd
  1472.  
  1473. End_ttd
  1474.           cmp       di,pMacLimit        ; have exceeded max bytes/definition?
  1475.           ja        Xt_ttd              ;   yes, jump
  1476.           mov       pMacMark,di         ; out: pMacMark = limit of data
  1477.           clc
  1478.           ret
  1479. ;---------------------------------------
  1480. Xc_ttd
  1481.           mov       dx,offset XLcmsg    ; "bad last character" message
  1482.           jmps      X_ttd
  1483.  
  1484. Xt_ttd
  1485.           sub       di,pMacLimit
  1486.           mov       VDXBytes,di         ; amount of overflow for error message
  1487.           mov       dx,offset XLbmsg    ; "too many bytes" message
  1488.           or        Flag,SHOWOVERFLOW
  1489. X_ttd
  1490.           or        Flag,LINEERROR
  1491.           stc
  1492.           ret
  1493.           ENDP
  1494. ;╒══════════════════════════════════════╕
  1495. ;│              StoreCtrl               │
  1496. ;│ In: al = '^'                         │
  1497. ;│     si = ptr to next byte in TEXTBUFF│
  1498. ;│     di = ptr into MACBUFFER          │
  1499. ;╘══════════════════════════════════════╛
  1500. StoreCtrl PROC      NEAR
  1501.           lodsb
  1502.           or        al,al               ; end of line?
  1503.           jz        Xc_stc              ;   yes, error. jump
  1504.           sub       al,'A'-1            ; ^A --> 1, ^B --> 2, etc.
  1505.           jle       Xd_stc              ; if al <= 0, error. jump
  1506.           cmp       al,31
  1507.           ja        Xd_stc              ; if al > 31, error. jump
  1508.           stosb
  1509.           clc
  1510.           ret
  1511. ;---------------------------------------
  1512. Xc_stc
  1513.           mov       dx,offset XLcmsg
  1514.           jmps      X_stc
  1515. Xd_stc
  1516.           mov       dx,offset XLdmsg
  1517. X_stc
  1518.           stc
  1519.           ret
  1520.           ENDP
  1521. ;╒══════════════════════════════════════╕
  1522. ;│               StoreAlt               │
  1523. ;│ In: al = '@'                         │
  1524. ;│     si = ptr to next byte in TEXTBUFF│
  1525. ;│     di = ptr into MACBUFFER          │
  1526. ;╘══════════════════════════════════════╛
  1527. StoreAlt  PROC      NEAR
  1528.           lodsb                         ; al = letter of alphabet (maybe)
  1529.           or        al,al               ; end of line?
  1530.           jz        Xc_sta              ;   yes, error. jump
  1531.           and       al,CAPMASK          ; capitalize
  1532.           mov       bp,di               ; save position in MACBUFFER
  1533.           mov       di,offset Alphabet
  1534.           mov       cx,ALTXNUMB
  1535.           repne
  1536.           scasb
  1537.           jnz       Xa_sta
  1538.           mov       di,LASTALTXSCAN
  1539.           sub       di,cx
  1540.           mov       ah,[di]
  1541.           mov       al,0FFh
  1542.           mov       di,bp               ; restore ptr to MACBUFFER in di
  1543.           stosw
  1544.           clc
  1545.           ret
  1546. ;---------------------------------------
  1547. Xc_sta
  1548.           mov       dx,offset XLcmsg
  1549.           jmps      X_sta
  1550. Xa_sta
  1551.           mov       dx,offset XLamsg
  1552. X_sta
  1553.           stc
  1554.           ret
  1555.           ENDP
  1556. ;╒══════════════════════════════════════╕
  1557. ;│              StoreName               │
  1558. ;│ In: al = '['                         │
  1559. ;│     si = ptr to byte after '['       │
  1560. ;│     di = ptr into MACBUFFER          │
  1561. ;╘══════════════════════════════════════╛
  1562. StoreName PROC      NEAR
  1563.           mov       dx,di               ; save ptr into MACBUFFER in dx
  1564.           mov       bp,si               ; save ptr to text string in bp
  1565.  
  1566.      ;[ copy key name to SYMBUFFER ]
  1567.           mov       cx,KEYNAMELENGTH    ; counter
  1568.           mov       di,SYMBUFFER
  1569. Sym_stn
  1570.           stosb
  1571.           dec       cx
  1572.           jz        NoGo0_stn           ; if max length already copied, jump
  1573.           lodsb
  1574.           or        al,al               ; end of line?
  1575.           jz        NoGo0_stn           ;   yes, not key name. jump.
  1576.           cmp       al,'['              ; start of key name?
  1577.           jz        NoGo0_stn           ;   yes, current can't be key name. jump
  1578.           cmp       al,']'              ; end of key name?
  1579.           jz        EndName_stn         ;   yes, jump
  1580.           cmp       al,'a'              ; capitalize
  1581.           jb        Sym_stn
  1582.           cmp       al,'z'
  1583.           ja        Sym_stn
  1584.           and       al,CAPMASK
  1585.           jmps      Sym_stn
  1586. EndName_stn
  1587.           stosb                         ; save ']'
  1588.  
  1589.           cmp       cx,KEYNAMELENGTH - MINKEYLENGTH ; length too short?
  1590.           ja        NoGo0_stn                       ;   yes, not key name. jump.
  1591.           xor       ax,ax
  1592.           stosw                         ; pad SYMBUFFER with zeros
  1593.           stosw
  1594.           stosw
  1595.  
  1596.      ;[ binary search ]
  1597.           push      bx                  ; save ptr to VDXBUFFER
  1598.           push      dx                  ; save ptr to MACBUFFER
  1599.           push      si                  ; save current position in text string
  1600.           push      bp                  ; save original position in text string
  1601.           call      BinSearch
  1602.           pop       bp
  1603.           pop       si
  1604.           pop       di                  ; restore ptr to MACBUFFER in di
  1605.           pop       bx
  1606.           jc        NoGo_stn
  1607.           cmp       ah,080h             ; ah < 80h only for Esc and ^BkSp
  1608.           jb        Other_stn
  1609.           mov       al,0FFh             ; al = ASCII code for special key
  1610.           stosw                         ; store ASCII:scan codes
  1611.           ret
  1612. ;---------------------------------------
  1613. Other_stn
  1614.           mov       al,ah               ; ASCII code for Esc or ^BkSp
  1615.           stosb
  1616.           ret
  1617. ;---------------------------------------
  1618. NoGo0_stn
  1619.           mov       di,dx               ; restore pointer to MACBUFFER
  1620. NoGo_stn
  1621.           mov       al,'['              ; not a key name, store '['
  1622.           mov       si,bp               ; restore original position in text
  1623.           stosb
  1624.           ret
  1625.           ENDP
  1626. ;╒══════════════════════════════════════╕
  1627. ;│             BinSearch                │
  1628. ;│binary search procedure for key name  │
  1629. ;│                                      │
  1630. ;│Found:                                │
  1631. ;│  ah = scan code for special key, or  │
  1632. ;│       ASCII code for Esc or ^BkSp    │
  1633. ;│       CF clear                       │
  1634. ;│Else:  CF set                         │
  1635. ;╘══════════════════════════════════════╛
  1636. BinSearch PROC      NEAR
  1637.      ;[initialize bx,bp ]
  1638.           mov       bx,CAPKEYNAMES      ; bx = left
  1639.           mov       bp,LASTCAPNAME      ; bp = right
  1640.  
  1641.      ;[ check first element of symbol table ]
  1642.           mov       si,bx               ; check left
  1643.           mov       di,SYMBUFFER        ; di = ptr to target
  1644.           mov       cx,KEYNAMELENGTH    ; cx = bytes to check
  1645.           repe
  1646.           cmpsb
  1647.           jb        Start_bs            ; if left < target, jump to search
  1648.           jz        OK_bs               ; if match, done
  1649.           jmps      NotFound_bs         ; if target < left, not found
  1650.  
  1651.      ;[ search loop ]
  1652. Left_bs
  1653.           mov       bx,ax               ; middle < target, so new left = middle
  1654. Start_bs
  1655.           mov       ax,bp               ; ax = bp = right
  1656. Next_bs
  1657.           sub       ax,bx               ; ax = right - left
  1658.           cmp       ax,KEYNAMELENGTH    ; ax <= length of entry ?
  1659.           jbe       Last_bs             ;    yes, jump to last check
  1660.           shr       ax                  ; ax = (right-left)/2
  1661.           and       ax,0FFF8h            ; round off to multiple of 8
  1662.           add       ax,bx               ; ax = middle entry
  1663.  
  1664.           mov       si,ax               ; check middle
  1665.           mov       di,SYMBUFFER        ; di = ptr to target
  1666.           mov       cx,KEYNAMELENGTH    ; cx = bytes to check
  1667.           repe
  1668.           cmpsb
  1669.           jb        Left_bs             ; if middle < target, jump to set left
  1670.           jz        OK_bs               ; if match, done
  1671.           mov       bp,ax               ; target < middle, so new right = middle
  1672.           jmps      Next_bs
  1673.  
  1674.      ;[ final check on right ]
  1675. Last_bs
  1676.           mov       si,bp               ; si = right
  1677.           mov       di,SYMBUFFER        ; di = ptr to target
  1678.           mov       cx,KEYNAMELENGTH    ; cx = bytes to check
  1679.           repe
  1680.           cmpsb
  1681.           jnz       NotFound_bs
  1682. OK_bs
  1683.           sub       si,8                ; si = ptr to matching key name
  1684.           sub       si,CAPKEYNAMES      ; si = offset into array
  1685.           shr       si                  ; si/8 = index into array
  1686.           shr       si
  1687.           shr       si
  1688.           add       si,offset KeyCodes  ; si = ptr into table of codes
  1689.           mov       ah,[si]             ; ah = code
  1690.           clc
  1691.           ret
  1692. ;---------------------------------------;
  1693. NotFound_bs
  1694.           stc
  1695.           ret
  1696.           ENDP
  1697. ;╒══════════════════════════════════════╕
  1698. ;│              CopyMacro               │
  1699. ;│ copies macro in MACBUFFER to VDXBUFFR│
  1700. ;│                                      │
  1701. ;│  In: pMacMark = limit of macro       │
  1702. ;│      bx = ptr to VDXBUFFER           │
  1703. ;│ Out: bx updated, CF clear            │
  1704. ;│ Err: CF set, dx = error msg          │
  1705. ;│                                      │
  1706. ;│ Preserves: si (ptr to next line)     │
  1707. ;╘══════════════════════════════════════╛
  1708. CopyMacro PROC      NEAR
  1709.           mov       bp,si               ; save si in bp
  1710.           mov       cx,pMacMark         ; limit of data in MACBUFFER
  1711.           sub       cx,MACSTART1        ; length=limit - start of def (or label)
  1712.           mov       si,MACBUFFER        ; start of macro
  1713.           mov       [si],cl             ; store length
  1714.  
  1715.           inc       cx                  ; include mode byte
  1716.           add       VDXBytes,cx         ; update count
  1717.           cmp       VDXBytes,VDXMACLIMIT  ; have exceeded allowed bytes/file?
  1718.           ja        X_cpm                 ;   yes, jump
  1719.  
  1720.           inc       cx                  ; include length byte for copy
  1721.           mov       di,bx               ; destination in VDXBUFFER
  1722.           rep
  1723.           movsb
  1724.           mov       bx,di               ; update position in VDXBUFFER
  1725.           mov       si,bp               ; restore si
  1726.           clc
  1727.           ret
  1728. ;---------------------------------------
  1729. X_cpm
  1730.           sub       VDXBytes,VDXMACLIMIT ; amount of overflow
  1731.           mov       dx,offset XLsmsg     ; "maximum size exceeded" message
  1732.           or        Flag,LINEERROR or SHOWOVERFLOW
  1733.           stc
  1734.           ret
  1735.           ENDP
  1736. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ OUTPUT ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1737. ;╒══════════════════════════════════════╕
  1738. ;│              WriteBuff               │
  1739. ;│ In: di = limit of data in buffer     │
  1740. ;│ Err: CF set,   dx = error message    │
  1741. ;╘══════════════════════════════════════╛
  1742. WriteBuff PROC      NEAR
  1743.           mov       si,pMidExt          ; si points to middle letter of extension
  1744.  
  1745.           test      Flag,VDKINPUT or VDFINPUT
  1746.           jz        TextIn_wb
  1747.           mov       byte [si],'T'       ; change  VDx --> VTx
  1748.           mov       bp,TEXTBUFFER       ; bp = buffer to write from
  1749.           jmps      Create_wb
  1750.  
  1751. TextIn_wb
  1752.           mov       byte [si],'D'       ; change  VTx --> VDx
  1753.           mov       bp,VDXBUFFER        ; bp = buffer to write from
  1754.  
  1755.      ;[ create output file ]
  1756. Create_wb
  1757.           mov       dx,PATH
  1758.           xor       cx,cx               ; ordinary attribute
  1759.           mov       ah,03Ch
  1760.           int       21h
  1761.           jc        Xc_wb
  1762.           mov       bx,ax               ; bx = handle
  1763.  
  1764.      ;[ write output ]
  1765.           mov       dx,bp               ; dx = ptr to buffer
  1766.           mov       cx,di               ; di = limit of data in buffer
  1767.           sub       cx,dx               ; cx = limit - start = bytes to write
  1768.           mov       ah,040h
  1769.           int       21h
  1770.           pushf                         ; save flags
  1771.           mov       dx,ax               ; save bytes written in dx
  1772.  
  1773.           mov       ah,03Eh             ; close file
  1774.           int       21h
  1775.  
  1776.           popf
  1777.           jc        Xw_wb
  1778.           cmp       cx,dx               ; bytes requested = bytes written?
  1779.           jnz       Xw_wb
  1780.  
  1781.           call      PutCrlf
  1782.           mov       si,PATH             ; write filename
  1783.           call      Puts
  1784.           mov       si,offset Cmsg      ; "created" message
  1785.           call      Puts
  1786.  
  1787.           mov       ax,VDXMACLIMIT      ;    write free space
  1788.           sub       ax,VDXBytes
  1789.           call      Putu
  1790.           mov       si,offset Fmsg      ;    "free bytes" message
  1791.           call      Puts
  1792.           call      PutCrlf
  1793.           clc
  1794.           ret
  1795. ;---------------------------------------
  1796. Xc_wb
  1797.           mov       dx,offset XFcmsg
  1798.           jmps      X_wb
  1799. Xw_wb
  1800.           mov       dx,PATH
  1801.           mov       ah,041h             ; delete file
  1802.           int       21h
  1803.           mov       dx,offset XFwmsg
  1804. X_wb
  1805.           or        Flag,FILEERROR
  1806.           stc
  1807.           ret
  1808.           ENDP
  1809. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ STRING STUFF ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1810. ;╒══════════════════════════════════════╕
  1811. ;│                 Puts                 │
  1812. ;│  In: si = ptr to ASCIZ string        │
  1813. ;│ Out: ah = 0Eh                        │
  1814. ;╘══════════════════════════════════════╛
  1815. Puts      PROC      NEAR
  1816.           mov       ah,0Eh
  1817. Next_pts
  1818.           lodsb
  1819.           or        al,al
  1820.           jz        Done_pts
  1821.           int       10h
  1822.           jmps      Next_pts
  1823. Done_pts
  1824.           ret
  1825.           ENDP
  1826. ;╒══════════════════════════════════════╕
  1827. ;│             PutCRLF                  │
  1828. ;╘══════════════════════════════════════╛
  1829. PutCRLF   PROC      NEAR
  1830.           mov       ax,0E0Dh
  1831.           int       10h
  1832.           mov       al,0Ah
  1833.           int       10h
  1834.           ret
  1835.           ENDP
  1836. ;╒══════════════════════════════════════╕
  1837. ;│               PUTU                   │
  1838. ;│  In: ax = unsigned number            │
  1839. ;│  Destroys: ax,bx,cx,dx               │
  1840. ;╘══════════════════════════════════════╛
  1841. PutU      PROC      NEAR
  1842.           mov       bx,10               ; going to divide by 10
  1843.           xor       cx,cx               ; holds number of digits
  1844. Digit_ptu
  1845.           xor       dx,dx
  1846.           div       bx                  ; unsigned division ax/10 with rem in dx
  1847.           push      dx                  ; save on stack
  1848.           inc       cx                  ; count one digit
  1849.           or        ax,ax               ; any more?
  1850.           jnz       Digit_ptu
  1851.  
  1852. Char_ptu
  1853.           pop       ax
  1854.           add       ax,0E30h            ; TTY + '0'
  1855.           int       10h
  1856.           loop      Char_ptu
  1857.  
  1858.           ret
  1859.           ENDP
  1860. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ DATA ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1861. ; Format of output text files
  1862. ;         (M = mode = space, Q, N, or B)
  1863. ;         (A = AUTOEXEC for Version 1.70)
  1864. ;--(1)--------------------------------------------------------
  1865. ;     === .VTK file ===
  1866. ;
  1867. ;          [X] M = definition
  1868. ;       -->|8 byts|<--
  1869.  
  1870. INDENTVTK      EQU  8
  1871. ;--(2)--------------------------------------------------------
  1872. ;     === .VTF files:  Vers.1.53 or Vers.1.70 with no labels ===
  1873. ;
  1874. ;          [xFxx] M = definition
  1875. ;          [xFxx] AM= definition
  1876. ;       -->|11 bytes |<--
  1877.  
  1878. INDENTVTF      EQU  11
  1879. ;--(3)--------------------------------------------------------
  1880. ;     === .VTF files:  Vers.1.70 with labels ===
  1881. ;
  1882. ;          [xFxx] <LLLLLLL> M = definition
  1883. ;          [xFxx] <LLLLLLL> AM= definition
  1884. ;          |<--   21 bytes  -->|
  1885.  
  1886. INDENTVTFLBL   EQU  21
  1887. ;───────────────────────────────────────────────────────────────────────────────
  1888. FILEID153      EQU   5301h              ; file ID for Version 1.53
  1889. FILEID170      EQU   7001h              ; file ID for Version 1.70
  1890. MAXLINELENGTH  EQU      72              ; wrap lines in text file longer than
  1891.                                         ;   72 characters since longest key name
  1892.                                         ;   is 8 bytes long
  1893. ;───────────────────────────────────────────────────────────────────────────────
  1894. ;---- Word-Length Variables ----
  1895. Bytes          dw        ?
  1896. DrivDirLen     dw        0
  1897. VDXBytes       dw        0
  1898. pArg           dw        81h            ; current position on command line
  1899. pFindMacKy     dw        ?              ; ptr to name finding procedure
  1900. pKey           dw        ?              ; ptr into table of key names
  1901. pKeyLimit      dw        ?              ; ptr to limit of table of key names
  1902. pLine          dw        ?              ; ptr to start of data line in TEXTBUFFR
  1903. pMacLimit      dw        ?              ; acceptable limit of macro in MACBUFFER
  1904. pMacMark       dw        ?              ; ptr marking position in MACBUFFER
  1905. pMidExt        dw        ?              ; ptr to middle character of extension
  1906. pTextMark      dw        ?              ; ptr marking position in TEXTBUFFER
  1907. ;───────────────────────────────────────────────────────────────────────────────
  1908. Flag           dw                 0
  1909. USEDONLY       EQU                1b    ; set with /U option
  1910. VERSION170     EQU               10b    ; set with /7 option
  1911. CAPITALIZED    EQU              100b    ; set if key name table capitalized
  1912. WILDCARD       EQU             1000b
  1913. VDFINPUT       EQU            10000b    ; set if input file is .VDF
  1914. VDKINPUT       EQU           100000b    ; set if input file is .VDK
  1915. VTFINPUT       EQU          1000000b    ; set if input file is .VTF
  1916. VTKINPUT       EQU         10000000b    ; set if input file is .VTK
  1917. ISLABEL        EQU        100000000b
  1918. AUTOEXECSET    EQU       1000000000b
  1919. FILEERROR      EQU   10000000000000b
  1920. LINEERROR      EQU  100000000000000b
  1921. SHOWOVERFLOW   EQU 1000000000000000b
  1922.  
  1923. FIXEDFLAGS     EQU USEDONLY OR VERSION170 OR CAPITALIZED
  1924. ;───────────────────────────────────────────────────────────────────────────────
  1925. ;--- Macro Flag ---
  1926. NOREPEAT       EQU        01b
  1927. QUIET          EQU        10b
  1928. BOTH           EQU        11b
  1929. AUTOEXEC       EQU      1000b
  1930. LABELBIT       EQU  10000000b
  1931.  
  1932. MODEBITS       EQU        11b
  1933. Mode           db   ' NQB'
  1934. ;───────────────────────────────────────────────────────────────────────────────
  1935. ;--- Byte-Length Variables ---
  1936. Indent         db        0              ; number of columns prior to definition
  1937.                                         ;    in output text file
  1938. ;───────────────────────────────────────────────────────────────────────────────
  1939. ;--- Character Codes ---
  1940. LF             EQU     0Ah
  1941. CR             EQU     0Dh
  1942. CRLF           EQU   0A0Dh
  1943. EOF            EQU    01Ah
  1944. ESCAPE         EQU    01Bh
  1945. CAPMASK        EQU    05Fh
  1946.  
  1947.  
  1948. ;═══════════════════════════════════════════════════════════════════════════════
  1949. ;                            === KEYS AND CODES ===
  1950. ;═══════════════════════════════════════════════════════════════════════════════
  1951. ;--- Key names in 8-byte field in ASCII order ---
  1952.                                         ; ASCII   scan
  1953.                                         ; ~~~~~   ~~~~
  1954. KeyNames       db   '[!Down]',0         ;  FFh     B4h
  1955.                db   '[!End]',0,0        ;   "      B8h
  1956.                db   '[!Home]',0         ;   "      B7h
  1957.                db   '[!Left]',0         ;   "      B5h
  1958.                db   '[!PgDn]',0         ;   "      BAh
  1959.                db   '[!PgUp]',0         ;   "      B9h
  1960.                db   '[!Right]'          ;   "      B6h
  1961.                db   '[!Tab]',0,0        ;   "      8Fh
  1962.                db   '[!Up]',0,0,0       ;   "      B3h
  1963.                db   '[+]',0,0,0,0,0     ;   "      CEh
  1964.                db   '[-]',0,0,0,0,0     ;   "      CAh
  1965.                db   '[5]',0,0,0,0,0     ;   "      CCh
  1966.                db   '[Del]',0,0,0       ;   "      D3h
  1967.                db   '[Down]',0,0        ;   "      D0h
  1968.                db   '[End]',0,0,0       ;   "      CFh
  1969. EscKey         db   '[Esc]',0,0,0       ; (1Bh)          Exception
  1970.                db   '[Home]',0,0        ;   "      C7h
  1971.                db   '[Ins]',0,0,0       ;   "      D2h
  1972.                db   '[Left]',0,0        ;   "      CBh
  1973.                db   '[PgDn]',0,0        ;   "      D1h
  1974.                db   '[PgUp]',0,0        ;   "      C9h
  1975.                db   '[Right]',0         ;   "      CDh
  1976.                db   '[Up]',0,0,0,0      ;   "      C8h
  1977. CtrlBkSp       db   '[^BkSp]',0         ; (7Fh)          Exception
  1978.                db   '[^Down]',0         ;   "      C6h
  1979.                db   '[^End]',0,0        ;   "      F5h
  1980. CtrlEsc        db   '[^Esc]',0,0        ;   "      AAh
  1981.                db   '[^Home]',0         ;   "      F7h
  1982.                db   '[^Ins]',0,0        ;   "      C5h
  1983.                db   '[^Left]',0         ;   "      F3h
  1984.                db   '[^PgDn]',0         ;   "      F6h
  1985.                db   '[^PgUp]',0         ;   "      84h
  1986.                db   '[^Right]'          ;   "      F4h
  1987.                db   '[^Up]',0,0,0       ;   "      8Dh
  1988. LASTKEYNAME    EQU  $ - 8
  1989. MINKEYLENGTH   EQU  3                   ; minimum length of key name, e.g. [+]
  1990. KEYNAMELENGTH  EQU  8
  1991. KEYNAMENUMB    EQU  34
  1992.  
  1993. ;--- Scan codes for keys in above list, but ASCII codes for [Esc] and [^BkSp]
  1994. KeyCodes       db   0B4h,0B8h,0B7h,0B5h,0BAh,0B9h,0B6h,08Fh,0B3h,0CEh
  1995.                db   0CAh,0CCh,0D3h,0D0h,0CFh,01Bh,0C7h,0D2h,0CBh,0D1h
  1996.                db   0C9h,0CDh,0C8h,07Fh,0C6h,0F5h,0AAh,0F7h,0C5h,0F3h
  1997.                db   0F6h,084h,0F4h,08Dh
  1998. KEYCODENUMB    EQU  34
  1999. ;───────────────────────────────────────────────────────────────────────────────
  2000. ;--- Scan codes for @A - @Z ---
  2001. AltXScan       db   09Eh,0B0h,0AEh,0A0h,092h,0A1h,0A2h,0A3h,097h,0A4h
  2002.                db   0A5h,0A6h,0B2h,0B1h,098h,099h,090h,093h,09Fh,094h
  2003.                db   096h,0AFh,091h,0ADh,095h,0ACh
  2004. LASTALTXSCAN   EQU  $-1
  2005. LOWESTALTX     EQU  090h                ; lowest scan code in the list
  2006. HIGHESTALTX    EQU  0B2h                ; highest scan code in the list
  2007. ALTXNUMB       EQU  26
  2008. ;──────────────────────────────────────────────────────────────────────────────
  2009. CHARKEYLENGTH  EQU  1
  2010. CharKeys       db   '0123456789'
  2011. Alphabet       db   'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  2012. LASTLETTER     EQU  $-1
  2013. CHARKEYLIMIT   EQU  $
  2014. ;──────────────────────────────────────────────────────────────────────────────
  2015. FUNCKEYLENGTH  EQU  4
  2016. FuncKeys       db   'F1',0,0,  'F2',0,0,  'F3',0,0,  'F4',0,0,  'F5',0,0
  2017.                db   'F6',0,0,  'F7',0,0,  'F8',0,0,  'F9',0,0,  'F10',0
  2018.  
  2019.                db   '!F1',0,   '!F2',0,   '!F3',0,   '!F4',0,   '!F5',0
  2020.                db   '!F6',0,   '!F7',0,   '!F8',0,   '!F9',0,   '!F10'
  2021.  
  2022.                db   '^F1',0,   '^F2',0,   '^F3',0,   '^F4',0,   '^F5',0
  2023.                db   '^F6',0,   '^F7',0,   '^F8',0,   '^F9',0,   '^F10'
  2024.  
  2025.                db   '@F1',0,   '@F2',0,   '@F3',0,   '@F4',0,   '@F5',0
  2026.                db   '@F6',0,   '@F7',0,   '@F8',0,   '@F9',0,   '@F10'
  2027. NRMFUNCLIMIT   EQU  $
  2028.  
  2029.                db   'F11',0,   'F12',0,   '!F11',    '!F12'
  2030.                db   '^F11',    '^F12',    '@F11',    '@F12'
  2031. EXTFUNCLIMIT   EQU  $
  2032. FUNCKEYNUMB    EQU  48
  2033.  
  2034. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ MESSAGES ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  2035. Bmsg      db   ' bytes.',0
  2036. Fmsg      db   ' bytes of free space.',0
  2037. Cmsg      db   ' created.   ',0
  2038. ;──────────────────────────────────────────────────────────────────────────────
  2039. ;                           ----- File Errors -----
  2040. XFcmsg    db   'Cannot create the output file:  ',0
  2041. XFfmsg    db   'No files match this pattern:  ',0
  2042. XFimsg    db   'Wrong file identifier for V1.53+ or V1.70+ macros in  ',0
  2043. XFkmsg    db   'Labels are not allowed in .VTK files like  ',0
  2044. XFlmsg    db   'The 56kb buffer is not large enough for  ',0
  2045. XFomsg    db   'Cannot open this file:  ',0
  2046. XFrmsg    db   'Problem reading this file:  ',0
  2047. XFvmsg    db   'VDE Version 1.70+ does not use .VDK files like  ',0
  2048. XFwmsg    db   'Problem writing output data to  ',0
  2049. XFxmsg    db   'Wrong extension:  ',0
  2050. ;──────────────────────────────────────────────────────────────────────────────
  2051. ;                           ----- Line Errors -----
  2052. XLamsg    db   '    An @ representing <Alt> is not followed by a letter of the alphabet.',CR,LF
  2053.           db   '    Use `@ for the @ character itself.',0
  2054. XLbmsg    db   '    In this line the definition exceeded the maximum length by ',0
  2055. XLcmsg    db   '    The last character should have ` in front of it or something after it.',0
  2056. XLdmsg    db   '    A caret (^) representing <Ctrl> is not followed by A-Z, [, \, ], ^, or _.',CR,LF
  2057.           db   '    Use `^ for the ^ character itself.',0
  2058. XLemsg    db   '    There is no equal sign.',0
  2059. XLlmsg    db   '    Bad label (too long, missing right bracket, etc.)',0
  2060. XLmmsg    db   '    Incorrect mode: (none), N, Q, B, [A for Version 1.70+ only]',0
  2061. XLnmsg    db   '    The key name is invalid, nonexistent, or not in the proper order.',0
  2062. XLsmsg    db   '    The maximum size of a macro file was exceeded in this line by ',0
  2063. XLxmsg    db   '    Autoexec has already been set for another function key.',0
  2064. XLymsg    db   '    The Autoexec setting can only be used in function key files.',0
  2065. ;──────────────────────────────────────────────────────────────────────────────
  2066. BUFFERAREA     EQU  ($ + 1) AND 0FFFEh  ; start buffers here since usage message
  2067.                                         ; is not needed during conversion
  2068. ;──────────────────────────────────────────────────────────────────────────────
  2069. ;                           ---- Usage Message ----
  2070. Umsg db   CR,LF
  2071.      db   '             VMAC.COM (Version 1.11)                 Richard Cowell',CR,LF
  2072.      db   '                   Compiler for VDE V1.53+ and V1.70+ Macros',CR,LF
  2073.      db   '             Converts:  .VD[FK] macro files <--> .VT[FK] text files',CR,LF,CR,LF
  2074.  
  2075.      db   'USAGE:  VMAC {/U7} Filename {Fil*nam? ...}',CR,LF,CR,LF
  2076.  
  2077.      db   '     Options for converting macro files to text files:',CR,LF
  2078.      db   '         (none) = list ALL key names',CR,LF
  2079.      db   '             /U = list only names of keys USED for macros',CR,LF,CR,LF
  2080.  
  2081.      db   '     Option for converting .VTF text files to .VDF macro files:',CR,LF
  2082.      db   '             /7 = Version 1.70+ (maximum of 255 bytes/macro)',CR,LF,CR,LF
  2083.  
  2084.      db   'Format of .VT[FK] text file:',CR,LF
  2085.      db   '[Key] {< Label >} Mode = Definition     (Mode:  none, Q, N, B, {A for V1.70+})',CR,LF
  2086.      db   '                      {= Continuation}  (Label: only for V.1.70+)',CR,LF,CR,LF
  2087.  
  2088.      db   'Special character (`):',CR,LF
  2089.      db   '  Use `@  `^  `` for the literal characters @ ^ `',CR,LF
  2090.      db   '  Use ` in front of a space: 1) at the beginning of a definition',CR,LF
  2091.      db   '                             2) at the end of a definition with a comment',CR,LF,0
  2092. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ HEAP ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  2093. CAPKEYNAMES    EQU  BUFFERAREA
  2094. LASTCAPNAME    EQU  CAPKEYNAMES +  ( (KEYNAMENUMB - 1) * KEYNAMELENGTH )
  2095. CAPKEYSIZE     EQU  KEYNAMENUMB * KEYNAMELENGTH
  2096.  
  2097. DTA            EQU       CAPKEYNAMES + CAPKEYSIZE
  2098. DTANAME        EQU       DTA + 30
  2099. DTASIZE        EQU       48                  ; 43 + 5 byte margin
  2100.  
  2101. PATH           EQU       DTA + DTASIZE
  2102. PATHSIZE       EQU       64
  2103.  
  2104. SYMBUFFER      EQU       PATH + PATHSIZE
  2105. SYMSIZE        EQU       16
  2106.  
  2107. MACBUFFER      EQU       SYMBUFFER + SYMSIZE
  2108. MACFLAG        EQU       MACBUFFER + 1
  2109. MACSTART1      EQU       MACBUFFER + 2  ; start of def w/o label, or label
  2110. MACSTART2      EQU       MACBUFFER + 9  ; start of def with label
  2111. DEFLENGTH5     EQU       126            ; bytes allowed in V1.53 macro def.
  2112. DEFLENGTH7     EQU       253            ; bytes allowed in V1.70 macro def.
  2113. MACLIMIT5      EQU       MACBUFFER + DEFLENGTH5 + 2   ; 2 = length + mode bytes
  2114. MACLIMIT7      EQU       MACBUFFER + DEFLENGTH7 + 2
  2115. MACBUFFSIZE    EQU       512                          ; provide a little margin
  2116.  
  2117. VDXBUFFER      EQU       MACBUFFER + MACBUFFSIZE
  2118. VDXMACLIMIT    EQU       974                 ; bytes available for mode+def
  2119. VDXFILELIMIT   EQU       VDXBUFFER + 1024    ; .VD[FK] files are 1024 bytes
  2120. VDXSIZE        EQU       1024 + 256          ; provide a little margin
  2121.  
  2122. TEXTBUFFER     EQU       VDXBUFFER + VDXSIZE
  2123. HEAPEND        EQU       0FFFEh
  2124. STACKSIZE      EQU       1024
  2125. TEXTSIZE       EQU       HEAPEND - STACKSIZE - TEXTBUFFER  ; about 57,000 bytes
  2126. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  2127.