home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / proglc / tnylib.lzh / _FMT.ASM next >
Encoding:
Assembly Source File  |  1986-11-20  |  9.6 KB  |  410 lines

  1. include compiler.inc
  2.  
  3.     ttl    _FMT, 1.05, 10-21-86, jwk
  4.  
  5. ;support printf etc - original size 07de bytes
  6.  
  7. ;            BITS in FLG byte
  8. ljust    equ    1
  9. sign    equ    2
  10. blank    equ    4
  11. altern    equ    8
  12. zfill    equ    16
  13. islong    equ    32
  14. issgnd    equ    64
  15.  
  16.     dseg
  17.  
  18. flch    db    '-+0 #', 0        ;flag chars
  19. flgbits    db    ljust, sign, zfill, blank, altern
  20.  
  21. cch    db    'sc'            ;runs on with 'nch'
  22.  
  23. nch    db    'iXoxud%', 0        ;numeric conversions
  24.  
  25.     cseg
  26.  
  27. incptr    macro    bump
  28. ifdef    bump&_v
  29.     inc    word ptr bump&_v
  30. else
  31.     inc    word ptr bump
  32. endif
  33.     endm
  34.  
  35. leads    macro    dest,ofst
  36.     fixds
  37.     lea    dest,ofst
  38.     endm
  39.  
  40. fixds    macro
  41. ifdef    LONGPTR
  42.     mov    ds,saveds
  43. endif
  44.     endm
  45.  
  46. setds    macro
  47. ifdef    LONGPTR
  48.     mov    saveds,ds
  49. endif
  50.     endm
  51.  
  52.     xtfs <index, strlen, tolower, _xd, _xo, _xh>
  53.  
  54.         ;    int _fmt (rtn, arglst)
  55.         ;    int *(rtn)(), **arglst;
  56.  
  57.     procdef    _fmt, <<rtn, fptr>, <arglst, ptr>>
  58.     dclv    ctl, ptr    ; char ptr to control string
  59.     dclv    ctlchr, byte    ; current control character
  60.     dclv    sent, word    ; number of bytes sent out
  61.     dclv    pad, word    ; number of bytes padding required
  62.     dclv    tnum, word    ; total size of prefix+string
  63.     dclv    prec, word    ; precision specified
  64.     dclv    minwid, word    ; minimum field width
  65.     dclv    nbr, word    ; work area
  66.     dclv    prefix, baray, 128
  67.     dclv    str, baray, 64    ; working string buffer
  68.     dclv    flg, byte    ; flag byte for prefix formatting
  69.     dclv    op, ptr        ; char ptr to working buffer
  70.     dclv    saveds, word    ; save word for data segment
  71.     locs    <<strp, ptr>>    ; pointer to output string (str or %s)
  72.     pushreg
  73.     pushds
  74.     setds
  75.     xor    ax, ax        ; sent = 0;
  76.     mov    sent, ax
  77.     ptrcpyinc arglst, ctl    ; ctl = *arglst++;
  78. outer:    ldptr    si, ctl        ; while (*ctl)  /*main loop*/
  79.     mov    al, byte ptr [si]
  80.     or    al, al
  81.     jnz    chrok
  82.     jmp    fini
  83. chrok:    caseb    '%', parse    ; { if (*ctl != '%')
  84.     call    sndout        ;   { if ((*rtn)(*ctl)==EOF)return EOF;++sent;
  85.     jmp    bmpctl        ;   }    /*go step CTL*/
  86. parse:                ;   else
  87.     incptr    ctl        ;   { ++ctl;
  88.     xor    ax, ax        ;     flg = 0;
  89.     mov    flg, al
  90.     dec    ax        ;     prec = -1;
  91.     mov    prec, ax
  92.     setptr    strp, str, ss    ;     strp = str;
  93.     setptr    op, prefix, ss    ;     op = prefix;
  94. flglp:    ldptr    si, ctl        ;     while (regax=index("-+0 #",*ctl))
  95.     mov    al, byte ptr [si]
  96.     xor    ah, ah
  97.     leads    dx, flch
  98.     callit    index, <<ax, reg>, <dx, preg, ds>>
  99.     dec    ax
  100.     js    setwd
  101.     incptr    ctl        ;     { ++ctl;
  102.     mov    bx, ax        ;       flg |= flgbits[regax-1];
  103.     mov    al, 7[bx]
  104.     or    flg, al
  105.     jmp    flglp        ;     }
  106. setwd:    call    getval        ;     minwid = getval(ctl,arglst);
  107.     mov    minwid, ax
  108.     cmp    ax, 0        ;     if (minwid<0)
  109.     jge    setpre
  110.     mov    minwid, 1    ;    minwid = 1;
  111. setpre:    ldptr    si, ctl        ;     if (*ctl=='.')
  112.     cmp    byte ptr [si], '.'
  113.     jne    doltr
  114.     incptr    ctl        ;     {    ++ctl;
  115.     call    getval        ;    prec = getval(ctl,arglst);
  116.     cmp    ax, 0        ;    if (prec<0)
  117.     jge    sprec
  118.     xor    ax, ax        ;      prec = 0;
  119. sprec:    mov    prec, ax    ;     }
  120. doltr:    ldptr    si, ctl        ;     ctlchr = *ctl;
  121.     mov    al, byte ptr [si]
  122.     mov    ctlchr, al
  123.     or    al, 32        ;     switch(tolower(ctlchr))
  124.     caseb    'l', casel    ;     {
  125.     caseb    'i', csisi
  126.     caseb    'd', cased
  127.     jmp    cx1        ;    /*chain the switch tests*/
  128. casel:                ;    case 'l':
  129.     or    flg, islong    ;      flg |= islong;
  130.     incptr    ctl        ;      ++ctl;
  131.     jmp    doltr        ;      goto doltr;
  132.  
  133. csisi:    mov    al, 'd'        ;    case 'i':
  134.     mov    ctlchr, al    ;      ctlchr = 'd';
  135.  
  136. cased:                ;    case 'd':
  137.     or    flg, issgnd    ;      flg |= issgnd
  138.     call    gtrg        ;      nbr = getarg();
  139.     mov    nbr, dx
  140.     cmp    dx, 0        ;      if (nbr<0)
  141.     jge    absdn
  142.     xor    dx, -1        ;        nbr = -nbr;
  143.     xor    ax, -1
  144.     add    ax, 1
  145.     adc    dx, 0
  146. absdn:                ;      _xd(nbr, strp);
  147.     callit    _xd, <<strp, ptr>, <dx, reg>, <ax, reg>>
  148.     cmp    nbr, 0        ;      if ( nbr < 0 )
  149.     jge    noneg
  150.     mov    al, '-'        ;        *op++ = '-';
  151.     jmp    setpfx        ;      else
  152. noneg:    test    flg, sign    ;      if (flg & sign)
  153.     jz    nosgn
  154.     mov    al, '+'        ;        *op++ = '+';
  155.     jmp    setpfx        ;      else
  156. nosgn:    test    flg, blank    ;      if (flg & blank)
  157.     jz    endcsd
  158.     mov    al, ' '        ;        *op++ = ' ';
  159. setpfx:    pci    op
  160. endcsd:    jmp    chrdon        ;      break;
  161.  
  162. cx1:    caseb    'u', caseu        ; more CASE tests
  163.     caseb    'o', caseo
  164.     caseb    'x', casex
  165.     jmp    cx2
  166. caseu:                ;    case 'u':
  167.     call    gtrg        ;      _xd(getarg(), strp);
  168.     callit    _xd, <<strp, ptr>, <dx, reg>, <ax, reg>>
  169.     jmp    chrdon        ;      break;
  170.  
  171. caseo:                ;    case 'o':
  172.     call    gtrg        ;      _xo(getarg(), strp);
  173.     callit    _xo, <<strp, ptr>, <dx, reg>, <ax, reg>>
  174.     mov    al, flg        ;      if (flg & altern)
  175.     and    al, altern
  176.     jz    endcso
  177.     mov    al, '0'        ;        *op++ = '0';
  178.     pci    op
  179. endcso:    jmp    chrdon        ;      break;
  180.  
  181. casex:                ;    case 'x':
  182.     call    gtrg        ;      _xh(getarg(), strp);
  183.     callit    _xh, <<strp, ptr>, <dx, reg>, <ax, reg>>
  184.     mov    al, flg        ;      if (flg & altern)
  185.     and    al, altern
  186.     jz    endcsx
  187.     mov    al, '0'        ;      { *op++ = '0';
  188.     pci    op
  189.     mov    al, 'x'        ;        *op++ = 'x';
  190.     pci    op
  191. endcsx:    jmp    short    chrdon    ;      break;
  192.  
  193. cx2:    caseb    'c', casec
  194.     caseb    's', cases
  195.     caseb    '%', cpct
  196.     jmp    dflt
  197.  
  198. casec:                ;    case 'c':
  199.     gwi    arglst        ;      strp[0] = *arglst++;
  200.     jmp    short    stch    ;      strp[1] = 0; break;
  201.  
  202. cases:                ;    case 's':
  203.     ptrcpyinc arglst, strp    ;      strp = *arglst++;
  204.     mov    ax, prec    ;      if (prec<0)
  205.     cmp    ax, 0
  206.     jge    endcss
  207.     callit    strlen <<strp, ptr>>
  208.     mov    prec, ax    ;        prec = strlen(strp);
  209. endcss:    jmp    short    chrdon    ;      break;
  210.  
  211. cpct:                ;    case '%':
  212.     mov    al, '%'        ;      strp[0] = '%'; strp[1] = 0;
  213.     jmp    short    stch    ;      break;
  214.  
  215. dflt:                ;    default:
  216.     ldptr    si, ctl        ;      strp[0] = *ctl;
  217.     mov    al, byte ptr [si]
  218. stch:
  219.     xor    ah, ah        ;      strp[1] = 0;
  220.     ldptr    di, strp, es
  221.     stosw
  222. ;    jmp    short    chrdon    ;      break;
  223. chrdon:                ;     } /*end of SWITCH on CTLCHR */
  224.     ldptr    si, op        ;     *op = 0;
  225.     mov    byte ptr [si], 0
  226.     lea    ax, prefix    ;     tnum = strlen(prefix)+strlen(strp);
  227.     callit    strlen <<ax, preg, ss>>
  228.     mov    di, ax
  229.     callit    strlen <<strp, ptr>>
  230.     add    ax, di
  231.     mov    tnum, ax
  232.     leads    di, nch        ;     if (index (nch, ctlchr))
  233.     callit    index <<ctlchr, ptr>, <di, preg, ds>>
  234.     or    ax, ax
  235.     jz    notnum
  236. flwhl:    mov    ax, tnum    ;     {    while (tnum<prec)
  237.     cmp    ax, prec
  238.     jge    chkpre
  239.     test    flg, zfill    ;    { *op++ = (flg & zfill) ? '0' : ' ';
  240.     jz    fw1
  241.     mov    al, '0'
  242.     jmp    short    fw2
  243. fw1:    mov    al, ' '
  244. fw2:    pci    op
  245.     xor    al, al        ;      *op = 0;
  246.     mov    byte ptr [di], al
  247.     inc    tnum        ;      ++tnum;
  248.     jmp    flwhl        ;    } /* end of WHILE */
  249. notnum:                ;     } else
  250.     mov    ax, prec    ;     { if (prec < 0)
  251.     cmp    ax, 0
  252.     jge    chkpre
  253.     mov    ax, 1        ;      prec = 1;
  254.     mov    prec, ax    ;     }
  255. chkpre:    mov    ax, prec    ;     nbr = max (prec, minwid);
  256.     cmp    ax, minwid
  257.     jg    svnum
  258.     mov    ax, minwid
  259. svnum:    mov    nbr, ax
  260.     sub    ax, tnum    ;     pad = (tnum<nbr ? nbr-tnum : 0);
  261.     jns    svpad
  262.     xor    ax, ax
  263. svpad:    mov    pad, ax
  264.     mov    al, ctlchr    ;     if (ctlchr=='x')
  265.     cmp    al, 'x'
  266.     jnz    chkch2
  267.     setptr    op, prefix, ss    ;     {    op = prefix;
  268. lcpfx:    ldptr    si, op        ;    while (*op)
  269.     mov    al, byte ptr [si]
  270.     xor    ah, ah
  271.     or    ax, ax
  272.     jz    lcpex
  273.     callit    tolower, <<ax, reg>>
  274.     pci    op        ;      *op++ = tolower(*op);
  275.     jmp    lcpfx
  276. lcpex:    setptr    op, str, ss    ;    op = str;
  277. lcstr:    ldptr    si, op        ;    while (*op)
  278.     mov    al, byte ptr [si]
  279.     xor    ah, ah
  280.     or    ax, ax
  281.     jz    chkch2
  282.     callit    tolower, <<ax, reg>>
  283.     pci    op        ;      *op++ = tolower(*op);
  284.     jmp    lcstr        ;     }    /* end IF(CTLCHR..    */
  285. chkch2:    leads    di, cch        ;     if (index(cch, ctlchr))
  286.     callit    index <<ctlchr, ptr>, <di, preg, ds>>
  287.     or    ax, ax
  288.     jnz    cc2a
  289.     jmp    notctch
  290. cc2a:    test    flg, zfill    ;     { nbr = (flg & zfill ? '0' : ' ');
  291.     jz    cc2b
  292.     mov    al, '0'
  293.     jmp    short    cc2c
  294. cc2b:    mov    al, ' '
  295. cc2c:    mov    nbr, ax
  296.     test    flg, ljust    ;    if (!(flg & ljust)) /* pad on left */
  297.     jnz    lpadx
  298. padlft:    dec    pad        ;      while (--pad >= 0)
  299.     js    lpadx
  300.     mov    ax, nbr        ;        sndout(nbr);
  301.     call    sndout
  302.     jmp    padlft
  303. lpadx:    setptr    op, prefix, ss    ;    op = prefix;    /* out prefix    */
  304. outpfx:    ldptr    si, op        ;    while (*op)
  305.     cmp    byte ptr [si], 0
  306.     je    outstg
  307.     lodsb            ;      sndout(*op++);
  308.     svptr    si, op
  309.     call    sndout
  310.     jmp    outpfx
  311. outstg:    ldptr    si, strp    ;    while (*strp)    /* out string    */
  312.     cmp    byte ptr [si], 0
  313.     je    ckrpad
  314.     cmp    ctlchr, 's'    ;    { if ( ctlchr == 's'
  315.     jnz    notstg
  316.     dec    prec        ;        && --prec < 0 )
  317.     js    ckrpad        ;        break;
  318. notstg:    gci    strp        ;      sndout(*strp++);
  319.     call    sndout
  320.     jmp    outstg        ;    } /* end WHILE */
  321. ckrpad:    test    flg, ljust    ;    if (flg & ljust)    /* pad right */
  322.     jz    bmpctl
  323. dorpad:    dec    pad        ;      while ( --pad >= 0 )
  324.     js    bmpctl
  325.     mov    al, ' '        ;        sndout(' ');
  326.     call    sndout
  327.     jmp    dorpad
  328. notctch:            ;     } else /*end of IF(INDEX... */
  329.     ldptr    si, ctl        ;    sndout(*ctl);
  330.     mov    al, byte ptr [si]
  331.     call    sndout
  332. bmpctl:    incptr    ctl        ;     ++ctl;
  333.     jmp    outer        ;   }    /* main control loop ends here */
  334. fini:    mov    ax, sent    ;   return (sent);
  335. fmtqt:    pret            ; }    /* end of function */
  336.     pend    _fmt
  337.  
  338.     internal    gtrg    ;uses _FMT's BP and offsets
  339.     cld            ;get "long" from arg list
  340.     push    ds
  341.     ldptr    si,arglst    ;grab the pointer
  342.     lodsw
  343.     mov    cl, flg        ;check for sign extension
  344.     test    cl, issgnd
  345.     jnz    sxt
  346.     xor    dx, dx        ;unsigned
  347.     jmp short tstlg
  348. sxt:    cwd            ;assume it's int
  349. tstlg:    and    cl, islong
  350.     jz    gtrgx        ;not a long, done
  351.     xchg    dx, ax        ;was a long, so...
  352.     lodsw            ;get hi word
  353.     xchg    dx, ax
  354. gtrgx:    svptr    si,arglst    ;update ARGLST pointer
  355.     pop    ds
  356.     ret
  357.     iend    gtrg
  358.  
  359.     internal    sndout    ;uses _FMT's BP and offsets
  360.     xor    ah, ah
  361.     push    ax
  362.     fixds
  363.     call    rtn
  364.     inc    sp
  365.     inc    sp
  366.     cmp    ax, -1        ;error?
  367.     jne    sndok        ;no
  368.     inc    sp        ;yes, flush ret address
  369.     inc    sp
  370.     jmp    fmtqt        ;and get out of _fmt()
  371. sndok:    inc    sent        ;bump SENT count
  372.     ret            ;to caller inside _fmt
  373.     iend    sndout
  374.  
  375.     internal    getval    ;must reference from main BP
  376.     push    ds
  377.     mov    cx, -1        ;initialize accumulator
  378.     ldptr    si, ctl
  379.     mov    al, byte ptr [si]
  380.     cmp    al, '*'
  381.     jne    gv_ckn
  382.     gwi    arglst        ;get an argument
  383.     jmp    gv_lx
  384. gv_ckn:    sub    al, '0'
  385.     jb    gv_lr        ;not numeric either
  386.     cmp    al, 9
  387.     ja    gv_lr        ;so return -1
  388.     cbw
  389.     mov    cx, ax        ;re-initialize accumulator
  390.     mov    di, 10
  391. gv_dgl:    inc    si
  392.     mov    al, [si]
  393.     sub    al, '0'
  394.     jb    gv_ls        ;out of digits, return acc
  395.     cmp    al, 9
  396.     ja    gv_ls
  397.     cbw
  398.     xchg    ax, cx        ;swap for multiply by 10
  399.     cwd
  400.     mul    di
  401.     add    cx, ax        ;accumulate it
  402.     jmp    gv_dgl
  403. gv_ls:    svptr    si, ctl        ;update CTL pointer
  404. gv_lr:    mov    ax, cx        ;get return value
  405. gv_lx:    pop    ds
  406.     ret
  407.     iend    getval
  408.  
  409.     finish
  410.