----------------------------------------------------------------------
=>  Saturday, December 30, 2006   11:09pm

VDIR -- 16-bit DOS dir lister
public domain with .ASM source

Anthony J. Williams (not the ALink guy)
rugxulo@bellsouth.net

----------------------------------------------------------------------

This file mostly contains .SED scripts needed for auto-conversion to
  other assemblers (used by V??OTH*.BAT):

SED15X.ZIP, SED15.ZIP        (HHsed 1.5, 16-bit, real mode)
SEDMOD10.ZIP                 (SEDMOD 1.0, 16-bit, real mode)
???, ???                     (csed 2004-02-12, 16-bit, real mode)
SED3028B.ZIP, SED3028S.ZIP   (GNU/DJGPP sed 3.02.80, 32-bit, pmode)
SED415B.ZIP, SED415S.ZIP     (GNU/DJGPP sed 4.1.5, 32-bit, pmode)

----------------------------------------------------------------------

+=============+
|  ARROWASM:  |
+=============+

 The only reasons to have the main .ASM version be in ArrowASM are:

    1). ArrowASM is basically MASM 3.0 compatible (and MASM is/was
        the standard assembly format).
    2). ArrowASM produces code that is smallest (after being UPX'd).
    3). ArrowASM produces .OBJ code that can be debugged with GRDB or
        386SWAT (see my DEBUGIT.BAT).
    4). ArrowASM is discontinued (i.e., stable, won't introduce more bugs
        or break anything).
    5). ArrowASM can only target a 286 or less (so I don't have to worry
        about near jumps behind my back, etc).
    6). Also, even though it comes with no source, it's public domain.

+========+
|  UPX:  |
+========+

 I use UPX (slightly less efficient) instead of aPACK because:

        1). fully open source unlike aPACK
        2). supports many formats (watcom/le, djgpp2/coff, win32/pe, etc.)
        3). multi-OS ('portable endian-neutral C++')
        4). can unpack its own work
        5). free ("no cost"), even for commercial use

        N.B. The UPX .COM stub is copyrighted but freely distributable
             (as long as it isn't modified).

        P.S. You can unpack .COMs compressed by aPACK, UPX, 624, or DIET with
             Frank Zago's public domain IUP 0.67 (comes w/ .ASM src, too!).

  Addendum:  Okay, I've started using aPACK regardless.
             BUT, UPX rules, so I may use it post-beta!  ;-)

+===========+
|  FIXME!:  |
+===========+

   ---->  fix it so that 'sed' takes care of putting 'V??' wherever
            %V% is (instead of having 'V??' or 'V49' hardcoded everywhere).

   ---->  mention specific quirks or bugs that I have worked around:
            (Eric Pement's sed FAQ mentions other common sed bugs)


          1). The following is a rough estimate of DOS sed speeds

                 (tested on Pentium 166 with DR-DOS 7.03 Lite with
                  UPX-packed sed .EXEs, V49*.* files were in memory on RAM
                  drive, and NWCACHE was disabled, timed using UPCT.EXE
                  by Erik de Neve, freeware from http://www.sac.sk):

                 (TODO:  test on my old 486 Sx/25; disable SMARTDRV!)

          'upct v49other ngasm wolf nbasm16' :

               a). SEDMOD : 9.56 secs.
                   = a little faster than HHsed (surprisingly)
               b). HHsed : 10.39 secs.
                   = pretty fast (I use it by default)
               c). csed : 17.41 secs.
                   = a lot faster than the GNU seds but sometimes slower
                     than HHsed (though not always)
               d). GNU/DJGPP sed 4.1.5 : 30.37 secs.
                   = usually a good deal faster than NNsed
               e). GNU/DJGPP sed 3.02.80 (aka, NNsed) : 43.18 secs.
                   = sometimes quite noticeably slower than the others
                     (but not always)

               N.B. I've added '/blah/' before 's/blah/bah/' etc. because
                    that makes it run faster (supposedly):

                          '/blah/s//bah/'


          2). 'echo dummy | hhsed -e"s/m/\\/g"'
              'echo dummy | hhsed -e "s/m/\\/g"'        (also works)

          3). 'echo dummy | sedmod -e "s/m/\\/g"'
              'echo dummy | sedmod -e"s/m/\\/g"'        (won't work)

          4). 'echo dummy | sed --posix -e "s/m/\\/g"'  (won't work)
              'echo dummy | sed --posix -e"s/m/\\/g"'   (won't work)
              'echo dummy | sed --posix "s/m/\\/g"'     (won't work)
              'echo dummy | sed --posix -e "y/m/\\/"    (works)
              'echo dummy | sed --posix -e"y/m/\\/"     (works)
              'echo dummy | sed --posix "y/m/\\/"       (works)

          5). HHsed needs a semicolon ';' after '{}'  :
     hhsed -n "/xor \(..\),\1/{=;p;}" v49.asm | hhsed -n "$!{N;s/\n//p;}"

          6). SEDMOD handles '\(^' etc. differently than '^\(' compared
              to HHsed (if I remember correctly...)

          7). SEDMOD needs prototype in DECL.H for listto()
                 to be changed to compile with TC++ 1.01:

                    'listto(char *p1,struct _iobuf *fp);'

                          (should become)

                    'listto(char *p1,FILE *fp);'

          8). SEDMOD and HHsed have a script limit of 200 lines (doh!)

          9). HHsed is the only one to support '%' (previous replaced text)

          10). SEDMOD doesn't seem to support "s///4":
               'echo blah blah blah blah | sedmod "s/a/_/2"'  (won't work)

               (the sed from Berkeley Utilities only works with
                "s/a/_/02" (N.B. put a zero before the number!))

          11). SEDMOD also can't handle \{ \} ranges  :-/
               - obviously, we can't rely completely on SEDMOD for all
                 our sed needs  :-P

          12). some (older) seds hate ANY # comments in scripts
               - see my guidelines below for more things to beware of

          13). 'sedmod -n -i "/sub \(..\),\1/p" V49.ASM'
                (won't work without the Sep. 22, 1998 patch from
                 Ken Pizzini to seders mailing list, SEDMFIX1.TXT):

          14). try `sed "\=/////=!d" codetips.txt' instead of
                   `sed "/\/\/\/\/\//!d" codetips.txt' to be nicer  :-)
                   (doesn't work w/ old GNU sed 1.6.1.2 or SEDMOD 1.0)

          15). GNU sed (3.02.80 and 4.1.5) and HHsed 1.5 are the only
               seds to support `sed "\=/////=,+2!d" codetips.txt'


==========<SEDMFIX1.TXT begins here>======================================
--- sedcomp.c-orig      Tue Sep 22 19:44:27 1998
+++ sedcomp.c   Tue Sep 22 20:08:48 1998
@@ -258,6 +258,8 @@
                 else if ((fp = address(cmdp->addr1 = fp)) == BAD)
                         ABORT(AGMSG);
 
+                cmdp->flags.igcase = iflag;
+
                 if (fp == cmdp->addr1)     /* if empty RE was found */
                 {
                         if (lastre)        /* if there was previous RE */
@@ -327,8 +329,6 @@
         sedcmd          *sp1, *sp2;        /* temps for label searches */
         label           *lpt, *search();   /* ditto, and the searcher */
         char            redelim;           /* current RE delimiter */
-
-        cmdp->flags.igcase = iflag;
 
         switch(cchar)
         {
==========<SEDMFIX1.TXT ends here>========================================

----------------------------------------------------------------------


+===============+
|  GUIDELINES:  |
+===============+

(I follow these, if possible):

        1). Make scripts work with the following 5 DOS seds:
                HHsed 1.5,
                SEDMOD 1.0,
                GNU/DJGPP sed 3.02.80
                GNU/DJGPP sed 4.1.5
                csed (2004-02-12)

            N.B. HHsed, SEDMOD, and csed all share a common ancestry:
                 Eric Raymond's sed (which Minix still uses).
                 They are all inferior to GNU sed, BUT they are:
                        a). smaller
                        b). faster
                        c). easier/quicker to compile
                        d). run on pre-386 computers
                        e). don't need a PMODE extender
                        f). use less memory
                        g). take up less cache memory, too

                 I try to avoid too many external utils, especially since I
                 would rather you were able to rebuild everything straight
                 out of the box without needing to download (yet another)
                 make, assembler, compiler, sed, grep, OS, etc.

                 Wouldn't it be horribly useless if you weren't able to get
                 it to work because your version of sed wouldn't work with
                 my sed scripts and the only assembler you had was NASM?

                 Therefore, I've tried to support as many seds as possible
                 (including GNU, which will probably outlive us all!). I
                 probably will also include a TDE macro for quick conversion
                 to certain assemblers (since NASM and FASM are very common
                 these days). Then, you won't even need to rely on sed in
                 those cases. The only thing better than that would be VIM
                 and ed scripts (which are even more common utils than TDE).

        2). Avoid a\ i\ c\
            = sometimes these are handled differently (use s// instead)
              = i.e., these may not work the same for all seds
                = or, at least, I haven't found a compatible way (yet)

        3). Avoid extended regular expressions
            \< \> \+ \| [:alnum:] \? \{ \} \n \t  etc...
            = BEWARE!:   '+' vs. '\+' or '?' vs. '\?'
              = ??? HHsed and SEDMOD vs. GNU sed vs. GNU 'sed -r' ???

        4). Avoid any GNU extentions or SEDMOD "improvements":
            = '-r', '-i', '-g', '\L', '\U', '\E', 's///I', '$1', etc.
              = even '#n' on the first line might not work (SEDMOD)!

        5). Some (old) seds don't like ANY comments
            = nevertheless, I've added some here since you can remove them
              quite easily, if necessary
              = V??OTHER.BAT automatically removes them, but V??OTH2.BAT
                doesn't!
                = 'sed "/^# /d" V??SED.TXT > V??SED.NEW' will delete
                   every comment that isn't needed by V??OTHER.BAT or
                   V??OTH2.BAT (i.e., you still need "#V??NASM.SED begins"
                   and "#ifdef YASM???" for V??OTH2.BAT)
            = comments are always good, never bad, so it can't hurt!
              = make sure not to add comments between a line continuation
                and the ending slash (else it'll include that, too!)

                  's/blah/some\
                  # this line is included in the .ASM
                  thing/'

                = see? that would be bad!  :-P

        6). Keep this file < 80 columns wide (including CR+LF).

            = "LONGLINE V??SED.TXT"     (should report no numbers)
            = (TDE "Shift+KeyPad Enter" should say:
                 "Lines\n  min:.*\n  max:  77"
                  (or less, if possible)


P.S.   Have fun!   :-)

----------------------------------------------------------------------

#OCTLITE.SED begins
# this allows Octasm 0.15 to work w/ EMM386 loaded (but not HIMEM.SYS)
#   since it only has 64k available in V86 mode (unlike clean boot,
#   when it has access to all your extended RAM)
# this creates a slightly less functional .COM (won't work for 0.14)
# to create the full-size .COM (0.14 or 0.15), clean boot first, then
#   1).  clean boot (Ctrl-Alt-Del, then press F5 at 'Starting ...')
#   2a). 'V??OTH2.BAT octasm'
#           or
#   2b). 'set LITE=n'
#        'V??OTHER.BAT octasm'

# the following deletes some less useful routines to save memory
/^#ansi_fix_colors/,/    ret/d
/^#clear_screen/,/    ret/d
/^#dummy/,/    ret/d
/^#get_rows/,/    ret/d
/^#logfile_error_print/,/    ret/d
/^#r_option/,/    ret/d
/^#textfiles_only/,/    ret/d
/^#write_logfile/,/    ret/d

/^#option_[mrz]/,/    ret/d
/^#option_t/,/^#option_t_ret/{
/^#option_t_ret/{
N
N
}
d
}

# remove the ability to call these (now deleted) options
/dw option_/s/option_[mrzt]/0/g

# delete ext_colors (since that bloats up a lot of space)
/#ext_colors db /!{
/^ *db '\./d
/^ *db .*,EXT_STOP/d
}

# write smaller, simpler version of ext_colors
/#ext_colors/s/^ *\(#ext_colors db\).*/\1 '.com.exe.bat.btm.',RED,EXT_STOP\
  db '.zip.tgz.tbz.tar.uha.7z.zoo.lzh.',DARKGRAY,EXT_STOP\
  db '.txt.doc.htm.man.1.inf.pdf.1st.me.dos.',CYAN,EXT_STOP\
  db '.wav.mp3.mod.s3m.it.xm.mid.',LIGHTBLUE,EXT_STOP\
  db '.asm.bas.pas.c.cc.cpp.awk.for.sed.',WHITE,EXT_STOP,0/

# delete some more (now) unused stuff
/#logfile_error  *[dD][bB]/d
/#textfiles  *[dD][bB]/d
/ansi_normal  *[dD][bB]/d
/call r_option/d

# write to V??OCT.NEW
# 'octlite' results from OCTLITE.SED run on V??OCT.ASM, which comes from
#   V??OCT.SED run on V??.ASM
w v49oct.new
#OCTLITE.SED ends

----------------------------------------------------------------------

#V49OCT.SED begins

# 'octasm' (not lite) only needs V??OCT.SED run on V??.ASM
# this will assemble with either 0.14 or 0.15 (clean boot only!)
1s/.*/LANG OCTASM,0.1\
&/
/org 100h/s//& use16/

# make sure to avoid ';;' since it's the multi-line comment token!
/;;/s/;;;*/;/g

s/V\([0-9][0-9]\)\.ASM/V\1OCT.ASM/

# put in the file which assembler we're targeting
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /OCTASM 0.15 /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/OCTASM 0.15 /
}

# red tape (boring!)
/code ends/d
/end Komenco/d
/assume [cdes]s:/d
/org 80h/d

# set some defines (mainly to aid readability vs. ArrowASM version)
s/.*code segment.*/define offset\
define short/

# 'equ' still needs to become '=' (see farther below)
/dta equ/s/^\(dta equ\).*/\1 80h/

# no 'COPY /B' needed for Octasm  :-)
/help_msg equ /s/help_msg equ \$/#help_msg include \\v49help.txt/

# Octasm doesn't handle the 'NOT' operator at compile time
/^;/!s/\(.*\),(\([A-Z_]*OPT_[A-Z]\) or \([A-Z_]*OPT_[A-Z]\))/        push ax\
        mov ax,\2 \
        or ax,\3 \
\1,ax\
        pop ax/

/ equ /s//=/

# Octasm needs '[es+di]' instead of 'es:[di] (MASM)' or '[es:di]' (NASM)
s/ \([cdes]s\):\[/ [\1+/

# labels are specified like '#mylabel', not 'mylabel:'
s/^\([a-zA-Z0-9_][a-zA-Z0-9_]*\):/#\1/

# 'blah db 5 dup(0)' needs to become '#blah rb 5'
/ [Dd][BbWwDd] [0-9][0-9]* dup(0)/{
/^;/!s/^/#/
}
/dup(0)/s/ db \([0-9][0-9]*\) dup(0)/ rb \1/
/[a-zA-Z0-9_] [dD][bBwWdD] /{
/^;/!s/^/#/
}

# Octasm doesn't handle the 'not' operator at compile time
/bl *, *not/!{
/word ptr/!{
/^;/!s/\(.*\),not\(.*\)/        push bx\
        mov bl,\2 \
        not bl\
\1,bl\
        pop bx/
}
}

# Octasm doesn't handle the 'NOT' operator at compile time
/word ptr/s/^\([^;].*\),not\(.*\)/        push bx\
        mov bx,\2 \
        not bx\
\1,bx\
        pop bx/

# Octasm supports A86-like short versions of size overrides
/byte ptr /s//b /
/word ptr /s//w /

# 'aam' by itself needs to be 'aam 10'
/    aam [0-9][0-9]*/!{
/    aam/s//& 10/
}

# write to V??OCT.ASM
w v49oct.asm
#V49OCT.SED ends

----------------------------------------------------------------------

#V49PAS32.SED begins

s/V\([0-9][0-9]\)\.ASM/V\1PAS32.ASM/

# it should work with other versions, too (PASS32NC, 3.07 alpha, 2.4)
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /Pass32 2.5.2 (Apr 9, 2000) /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/Pass32 2.5.2 (Apr 9, 2000) /
}

# red tape:  go bye bye
/assume [cdes]s:/d
/code ends/d
/org 100h/d
/org 80h/d
/dta equ/s/\(dta equ\).*/\1 80h/

# put an 'end' statement at the end of the resulting V??PAS32.ASM file
/end /s/^ *end [a-zA-Z0-9_][a-zA-Z0-9_]*/&\
end/

# '.model tiny' then '.code' tells Pass32 what it needs to know
# although 'pass32 V??PAS32.ASM -nw -t' tells it "No Warnings, Tiny"
# (if you don't use '-t', it works, but the .COM output is renamed .EXE)
/code segment/s/.*code segment.*/.model tiny\
.code\
/
/option_z_ret:/{
n
/    ret/s/.*/option_z_ret:\
&\
.data\
.noalign/
# I don't think '.noalign' actually does what I want  :-(
}

# Pass32 confuses '(DIR)' with the 'DIR equ 10h' line
/'(DIR)'/s//'(','D','I','R',')'/

/options_list dw /s//.const\
&/

# switch to '.data' temporarily for our option list
/option_y/s/option_z/&\
.data/

# add 'offset' keyword (necessary here but not with most assemblers)
/options_list dw/,/^ *$/{
s/[Dd][Ww]  *\([a-z0-9_][a-z0-9_]*\)/dw offset \1/
s/, *\([a-z0-9_][a-z0-9_]*\)/,offset \1/g
}

# Pass32 doesn't need 'COPY /B' for adding the help text
/help_msg equ \$/s//.code\
help_msg: .loadbin v49help.txt/

# this is to avoid four-byte jumps (two-byte jump plus two nops:  bug??)
/    jmp /!s/    j[a-z][a-z]* /&short /

# 'REPNE' is necessary for Pass32NC (no coproc version), I think
/ repnz /s/\(    repn\)z /\1e /

/ equ /s// .equ /g

# write to V??PAS32.ASM
w v49pas32.asm
#V49PAS32.SED ends

----------------------------------------------------------------------

#V49NASM.SED begins

s/V\([0-9][0-9]\)\.ASM/V\1NASM.ASM/

# NASM 0.97 still works too (and other older versions)
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /NASM 0.98.39 /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/NASM 0.98.39 /
}

# 'offset' and 'ptr' are useless to NASM, so we define 'em as no-ops
/code segment/s/code segment.*/%idefine offset\
%idefine ptr\
\
segment .text/

# the following removes some MASM-y red tape  :-P
/code ends/d
/end Komenco/d
/assume [cdes]s:/d
/org 80h/d

# 'dta equ 80h' works like we want
/dta equ/s/^\(dta equ\).*/\1 80h/


# change 'es:[di]' (MASM style) to '[es:di]' (same as FASM)
s/\([de]\)s:\[/[\1s:/

# fix the unknown 'dup' to NASM's 'times' directive
/dup/s/ db / times /
/ times /s/dup.*$/db 0/

# NASM also doesn't need 'COPY /B' (thankfully)
/help_msg equ /s/help_msg equ \$/help_msg: incbin "v49help.txt"/

# NASM uses C-style boolean operators for compile-time evaluation
/OPT_[A-Z] or /s/ or / | /g
/,not /s//,~/

# write to V??NASM.ASM
w v49nasm.asm
#V49NASM.SED ends

----------------------------------------------------------------------

#V49YASM.SED begins

# don't remove the following 'ifdef', I use it in V??OTHER.BAT !
#  (hmmm, should I attempt to actually only output one V??YASM.ASM file ??)
#  (yes, but only '-D' actually works in YASM 0.3.0 AND 0.4.0 AND newer!  )
#ifdef YASM030

# YASM 0.3.0 doesn't like boolean operators (although 0.4.0 and better do)
/^;/!s/\(.*\),(\([A-Z_]*OPT_[A-Z]\) or \([A-Z_]*OPT_[A-Z]\))/        push ax\
        mov ax,\2 \
        or ax,\3 \
\1,ax\
        pop ax/

/bl *, *not/!{
/word ptr/!{
/^;/!s/\(.*\),not\(.*\)/        push bx\
        mov bl,\2 \
        not bl\
\1,bl\
        pop bx/
}
}

/word ptr/s/^\([^;].*\),not\(.*\)/        push bx\
        mov bx,\2 \
        not bx\
\1,bx\
        pop bx/
# the above kludge really bloats the .COM but is necessary for 0.3.0
# by default, V??OTH*.BAT assume YASM 0.4.0
# 'V??OTH2 yasm yasm030' will use 0.3.0
# 'V??OTHER yasm' depends on the value of %YASM% (default: 4)
#    (you can set it to '3' or '4' or '5')
#    ('5' means the latest YASM 0.5.0 or any recent snapshots)

/org 100h/s/^org 100h/[&]/
# YASM 0.3.0 needs the primitive form (unlike later versions)

# put what YASM version we're targeting in V??YASM.ASM
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /YASM 0.3.0 (Sep. 4, 2003) or later /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/YASM 0.3.0 (Sep. 4, 2003) or later /
}
#endif YASM030

s/V\([0-9][0-9]\)\.ASM/V\1YASM.ASM/
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /YASM 0.4.0 (Oct 31, 2004) or later /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/YASM 0.4.0 (Oct 31, 2004) or later /
}

# 'cpu 8086' and 'bits 16' are used to avoid the broken optimizer's bloat
#    (after a few hundred bytes, it wrongly makes jumps 'near'! [386+])
#     *** fixed in yasm1606 ***
/code segment/s/code segment.*/%idefine offset\
%idefine ptr\
\
cpu 8086\
bits 16\
\
segment .text/

/assume [cdes]s:/d
/org 80h/d

# 'dta equ 80h' does what we want
/dta equ/s/^\(dta equ\).*/\1 80h/

# the following removes more MASM-y red tape
/code ends/d
/end Komenco/d

# changes 'es:[di]' (MASM) to '[es:di]' (NASM format)
s/\([de]\)s:\[/[\1s:/

# since YASM is basically a NASM fork/rewrite, it uses 'times' not 'dup'
/dup/s/ db / times /
/ times /s/dup.*$/db 0/

# YASM 0.4.0 and earlier don't work correctly with 'incbin'
#   (but later snapshots do; see V??OTHER.BAT)
/help_msg equ /s/help_msg equ \$/help_msg: ;incbin "v49help.txt"/

# YASM uses C-style operators like NASM does
/OPT_[A-Z] or /s/ or / | /g
/,not /s//,~/

# the following fix is only necessary if not using a newer YASM snapshot
# i.e., YASM 0.3.0 and 0.4.0 need it, but YASM1468 doesn't
/    jcxz /{
/^;/!s/ jcxz \([^ ][^ ]*\)/ test cx,cx\
        jz \1/
}

# write to V??YASM.ASM
w v49yasm.asm
#V49YASM.SED ends

----------------------------------------------------------------------

#V49WOLF.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1WOLF.ASM/

# older Wolfware assembler versions should work too
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /Wolfware ASM 2.23 /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/Wolfware ASM 2.23 /
}

# ignore all comment lines (starting w/ semicolon ';')
/^;/!{

# the following puts the seg override on its own line above the statement
/^[^;][^;]*[de]s:\[/s/\(.* \)\([de]\)s:\(\[.*\)/        \2s:\
\1\3 /

# change 'rcl ax,1' to 'rcl ax', etc. (else it assembles for a 286 !)
/rc[lr] .., *1/s/, *1/;&/
/sh[lr] .., *1/s/, *1/;&/

# put the 'REPxx' prefixes on their own line above the 'MOVSx/SCASx/CMPSx'
/rep[a-z]* /s/    rep[a-z]* /&\
        /

# change these words to similar alternatives
/jmp short/s//jmps/
/word ptr/s//word/
/byte ptr/s//byte/

# remove the colon ':' from after labels (Wolfware doesn't like 'em)
/^[a-zA-Z0-9_][a-zA-Z0-9_]*:/s/^\([a-zA-Z0-9_][a-zA-Z0-9_]*\):/\1/
}

# more useless red tape
/code segment/d
/assume [cdes]s:/d
/org 80h/d

# 'dta equ 80h' works like we want
/dta equ/s/^\(dta equ\).*/\1 80h/

# Wolfware only outputs to .COM (unless you use the .OBJ macros)
/org 100h/d

# more minor differences in keywords
/xlat/s/xlatb/xlat/

# add 'offset' keyword (necessary here but not with most assemblers)
/options_list dw/,/^ *$/{
s/[Dd][Ww]  *\([a-z0-9_][a-z0-9_]*\)/dw offset \1/
s/, *\([a-z0-9_][a-z0-9_]*\)/,offset \1/g
}

# change 'dup' to 'ds'
/dup/s/dup(.*$/;&/
/;dup(/s/db /ds /

/help_msg equ /s/help_msg equ \$/help_msg/
/code ends/d
/end Komenco/d

# the following is only just in case I ever meet an assembler that
#   needs 'mylabel proc near'
#/^; [a-zA-Z0-9_]* *$/ {
#n
#s/\([a-zA-Z0-9_]\):/\1 proc near/
#}
#/ret:/!s/    ret/&\
#        endp/

# this is used so JMP2RET.BAT won't break it
/    ret/s//&n/

# write to V??WOLF.ASM
w v49wolf.asm
#V49WOLF.SED ends

----------------------------------------------------------------------

#V49FASM.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1FASM.ASM/

# I've tested a lot of older versions (and the newer 1.65.xx snapshots),
#   and they all seem to (mostly) work correctly...
#   BUT, you will need to remove the 'short equ byte' line (below) if using
#   1.65.20 or newer.
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /FASM 1.67.18 (Dec. 27, 2006 bugfix) /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/FASM 1.67.18 (Dec. 27, 2006 bugfix) /
}

# 'short' is useless to FASM < 1.65.20, but I keep it (to minimize changes);
# also, I redefine it to 'byte' so that FASM doesn't generate 386 near
# jumps behind my back (w/ no warning!) if a short jump is too long!  :-P
# 'offset' and 'ptr' are also useless to FASM
/code segment/s/^code segment.*/offset equ\
ptr equ\
;short equ byte ; remove this line if using FASM 1.65.20 or newer!\
use16/

# 'dta equ 80h' appears to work (for most but not all assemblers)
/dta equ/s/^\(dta equ\).*/\1 80h/

# yay, more red tape!  :-P
/assume [cdes]s:/d
/org 80h/d
/code ends/d
/end Komenco/d

# the following makes sure no 386 near jumps are used anywhere
# (I always use 'jmp short' if possible, so we don't need to fix that)
#/    jmp /!s/    j[a-z][a-z]* /&short /
/jmp short /s//jmp /

# change 'es:[di]' (MASM style) to '[es:di]' (NASM style)
s/\([de]\)s:\[/[\1s:/

# 'dup' needs to become 'rb'
#    (actually, FASM now supports 'dup' natively, but I keep this
#     so that you can still use an older FASM (pre-1.56 ??), if that's
#     all you can get your hands on.
/dup(/{
s/dup.*//
s/db /rb /
}

# FASM also luckily doesn't need 'COPY /B'
/help_msg equ /s/^help_msg equ \$.*/help_msg: file "v49help.txt"/

# write V??FASM.ASM
w v49fasm.asm
#V49FASM.SED ends

----------------------------------------------------------------------

#V49NBASM.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1NBASM.ASM/

# some older versions of NBASM32 won't work, but most probably will
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /NBASM32 00.26.06 (Oct. 17, 2006) /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/NBASM32 00.26.06 (Oct. 17, 2006) /
}

# NBASM32 confuses 'DIR' with my 'DIR equ 10h' equate
# I've come to realize that 'equ' is sometimes considered an exact text
#   replacement/substitution keyword
#   (N.B. this was fixed in 00.26.05)
/'(DIR)'/s//'(','D','I','R',')'/

# remove some comments so as not to confuse the .SED script
/^[^;][^;]*;.*/s/;.*/\
&/

# the following sets up the .COM file (aka, tiny model)
/code segment/s/^code segment.*/.model tiny\
.code/

# red tape (useless garbage here)
/assume [cdes]s:/d
/org 80h/d
/code ends/d
/org 100h/d

# 'dta equ 80h' should work like we want
/dta equ/s/^\(dta equ\).*/\1 80h/

# you MUST have the '.end' keyword at the end of your file
/end Komenco/s//.end/

# shorten 'word ptr' to 'word'; same with 'byte ptr' => 'byte'
/word ptr/s//word/
/byte ptr/s//byte/

# the following is because NBASM32 doesn't like unnecessary 'word ptr'
#   specifications (unlike NASM, which just silently ignores them),
#   so I have to remove them!  :-P
/word */{
/^[^;][^;]*[, ][abcdsb][xip]/{
s/word//
}
}

# same with unnecessary 'byte ptr' wordage:  delete (or else!)
/byte/{
/^[^;][^;]*[, ][abcd][hl]/{
s/byte//
}
}

# put 'REPxx' prefix on a separate line above the 'MOVSx/CMPSx/SCASx'
/^;/!s/    rep[a-z]* /&\
        /

# ('incbin' is now available since 00.26.04 but must be at start of line!)
# /help_msg equ /s/help_msg equ \$/help_msg:\
# incbin v49help.txt/
/help_msg equ /s/help_msg equ \$/help_msg:/

# the 'dup' keyword has different syntax here than with other assemblers
/dup(0)/{
/db  *[0-9][0-9]*/{
s/  *dup.*//
s/[0-9][0-9]*/dup &,0/
}
}
/dup/s/db //

# the following is because of the 'exact textual replacement' EQU thingy
#   (N.B. this was fixed in 00.26.05)
/SUBOPT_H/s//SUBOPT_HELP/

# like NASM/YASM, it uses C-style boolean operators
/OPT_[A-Z][A-Z]* or /s/ or / | /g
/,not /s//,~/
/~/s/\(~[^ ]*\)/(\1)/

# write to V??NBASM.ASM
w v49nbasm.asm
#V49NBASM.SED ends

----------------------------------------------------------------------

#V49TMA.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1TMA.ASM/

# TMA 980717 and 980729 work also (but probably not earlier)
# no linker necessary with TMA  :-)
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /Tetrabyte ASM 980705 or later /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/Tetrabyte ASM 980705 or later /
}

# 'help_msg equ $' is buggy in 980729 (but not 980717), so I avoid it
/help_msg equ /s/help_msg equ \$/help_msg:/

# make sure it's 'repz' and not 'rep' because that's buggy  :-P
/ rep /s/\(    rep\) /\1z /

# 'equ' is not supported; use '=' instead
/ equ /s//=/

# write to V??TMA.ASM
w v49tma.asm
#V49TMA.SED ends

----------------------------------------------------------------------

#V49LAZY.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1LAZY.ASM/

# earlier LazyASM versions should work too (0.47 or later, I think)
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /Lazy ASM 0.53 + any linker /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/Lazy ASM 0.53 + any linker /
}

/assume [cdes]s:/d
/org 80h/d
/code ends/d

# 'dta equ 80h' works like we want
/dta equ/s/^\(dta equ\).*/\1 80h/

# 'es:[di]' => '[es:di]'
s/ \([de]\)s:\[/ [\1s:/

# 'byte ptr [' => '[byte ptr', etc.
/byte ptr /s/\(byte ptr \)\[/[\1/
/word ptr /s/\(word ptr \)\[/[\1/

# the following is necessary b/c LazyASM is IDEAL-mode compatible only!
/code segment/s/code segment.*/model tiny\
codeseg\
startupcode/

# 'COPY /B' not necessary  :-)
/help_msg equ /s/help_msg equ \$/help_msg: includebin "v49help.txt"/

# write to V??LAZY.ASM
w v49lazy.asm
#V49LAZY.SED ends

----------------------------------------------------------------------

#V49NB16.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1NB16.ASM/

# 00.24.95 is the latest (unsupported) 16-bit version of the NewBasic ASM
# it requires a 186 or better (but doesn't need DPMI, obviously)
# also, it's much faster and smaller than its big brother, NBASM32
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /NBASM16 00.24.95 /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/NBASM16 00.24.95 /
}

# remove some comments just so we won't trip over them with this script
/^[^;][^;]*;.*/s/;.*/\
&/

/code segment/s/^code segment.*/.model tiny\
.code/
/end Komenco/s//.end/

# red tape to delete (since it's unneeded)
/assume [cdes]s:/d
/org 80h/d
/code ends/d
/org 100h/d

# again, 'dta equ 80h' seems to work  :-)
/dta equ/s/^\(dta equ\).*/\1 80h/

# change 'byte ptr' to 'byte', etc.
/word ptr/s//word/
/byte ptr/s//byte/

# doh, not this again!
# yes, even the old NBASM16 chokes on unnecessary 'byte ptr', etc. wordage
/word */{
/^[^;][^;]*[, ][abcdsb][xip]/{
s/word //
}
}

/byte/{
/^[^;][^;]*[, ][abcd][hl]/{
s/byte //
}
}

# put 'REPxx' prefix on a line by itself above the directive it applies to
/^;/!s/    rep[a-z]* /&\
        /

/help_msg equ /s/help_msg equ \$/help_msg:/

# change the standard 'dup' usage to a similar variation
/dup(0)/{
/db  *[0-9][0-9]*/{
s/  *dup.*/;&/
s/[0-9][0-9]*/dup &,0/
}
}
/dup/s/db //

# uh oh, found a bug!  :-)
# it won't be fixed since NBASM16 is discontinued
# so, I work around it by using literal bytes of the equivalent instruction
/push word /s/push word \[\([a-zA-Z0-9_]*\)\]/db 0FFh,36h\
        dw offset \1 ; &/
/pop word /s/pop word \[\([a-zA-Z0-9_]*\)\]/db 08Fh,06h\
        dw offset \1 ; &/

# dunno why, but this won't work either (maybe '.adsize' will help ??)
/    jcxz /{
/^;/!s/ jcxz \([^ ][^ ]*\)/ test cx,cx\
        jz \1/
}

# ah, the textual substitution EQU, we meet again!
/SUBOPT_H/s//SUBOPT_HELP/

# C-style boolean operators, oh my!
/OPT_[A-Z][A-Z]* or /s/ or / | /g
/,not /s//,~/
/~/s/\(~[^ ]*\)/(\1)/

# write to V??NB16.ASM
w v49nb16.asm
#V49NB16.SED ends

----------------------------------------------------------------------

#V49WAT.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1WAT.ASM/

# OpenWatcom 1.3 works too (as does real-mode WASMR.EXE from 1.4 or newer)
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /Open Watcom WASM 1.6 + any linker /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/Open Watcom WASM 1.6 + any linker /
}

/ equ \$/s// label byte/
/code segment/s/code segment\(.*\)/& use16 ; \1/

# 'readonly','error':  reserved keywords?? probably...
/READONLY/s//RDONLY/
/\[error\]/s//[my_error]/
/error /s/^\( *\)error *\([dD][bBwWdD]\)/\1my_error \2/

# no idea why 'rep cmpsb' isn't allowed; no biggie though
/cmpsb/s/\(    rep\)  *\(cmpsb\)/\1z \2/

# write to V??WAT.ASM
w v49wat.asm
#V49WAT.SED ends

----------------------------------------------------------------------

#V49NGASM.SED begins
s/V\([0-9][0-9]\)\.ASM/V\1NGASM.ASM/

# the older NGASM (1.2) also seems to work
/ArrowASM/{
s/ArrowASM.*Val[ '0-9]* /NGASM 1.3 /
s/ArrowASM.*Warp[lL]ink[0-9. ]*/NGASM 1.3 /
}

/code segment/d
/assume cs:/d
/org [0-9]/d
/code ends/d
/end Komenco/d
/dta equ/s/dta equ /& 80h ;/

# uncomment the DTA stuff (if 'dta equ 80h' won't work)
#/^;setup_dta:/,/;ret/s/[; ]*//
#/^;dta db/s/^;//
#/^; *call setup_dta/s/^;//

# 'ptr' is (mostly?) ignored
/ptr /s///g

# not sure about the following, but it (seems to) work
/jmp short /s/\(jmp \)short /\1/
/push word /s/\(push \)word /\1/
/pop word /s/\(pop \)word /\1/
/xchg [a-d]l,byte/s/\(xchg [a-d]l,\)byte/\1/
/xlat/s/xlatb/xlat/

# we need to include our data first to eliminate forward references
/Komenco:/s//& jmp Begin_all\
        include V49ngasm.inc\
Begin_all:/

# make a short help message (else it'd be a forward reference: invalid!)
/help_msg equ /s/^\(help_msg\) equ .*/\1 db CR,LF,'VDIR (aka, V49)',CR,LF,0/

# shorten option_h (since we are using a minimal help message)
/^option_h:/,/^option_h_ret:/{
/^option_h:/!d
s/option_h:/&\
        mov si,offset help_msg\
        call print\
        mov ax,4C00h\
        int 21h\
option_h_ret:\
;        ret\
/
}

# write all data to separate file for including (to avoid forward refs)
/^[a-zA-Z0-9_]*  *[dD][bBwWdD]  */{
w v49ngasm.inc

# after write data, delete 'em from the main source file
d
}

# NGASM also hates boolean operators at compile time
/^;/!s/\(.*\),(\([A-Z_]*OPT_[A-Z]\) or \([A-Z_]*OPT_[A-Z]\))/        push ax\
        mov ax,\2 \
        or ax,\3 \
\1,ax\
        pop ax/

# guess what? 'not' will not work with NGASM
/bl *, *not/!{
/^[^;]*word \[/!{
/^;/!s/\(.*\),not\(.*\)/        push bx\
        mov bl,\2 \
        not bl\
\1,bl\
        pop bx/
}
}

/^[^;]*word \[/s/^\([^;].*\),not\(.*\)/        push bx\
        mov bx,\2 \
        not bx\
\1,bx\
        pop bx/

# no simple expressions evaluated? doh!
/(PAUZE_NUMBER.2)/{
s/\(.*\),(\(PAUZE_NUMBER\)\/2)\(.*\)/        push ax\
        mov ax,\2 \
        shr ax,1\
\1,ax\3 \
        pop ax/

s/\(.*\),(\(PAUZE_NUMBER\)\*2)\(.*\)/        push ax\
        mov ax,\2 \
        shl ax,1\
\1,ax\3 \
        pop ax/
}

# write to V??NGASM.ASM
w v49ngasm.asm
#V49NGASM.SED ends

----------------------------------------------------------------------
EOF

hey, it's over, go home!  :-)

Vivu Esperanto!  :-D

