home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / BDSC / BDSC-2 / L2-225.ARK / SPR.MAC < prev    next >
Text File  |  1988-05-21  |  9KB  |  655 lines

  1.  
  2.     .comment    `
  3. Assembler version of BDS-C (v. 2.50) standard library function '_spr'.
  4. Greg Lee, July 1984.
  5.             `
  6.  
  7.  
  8. MAXLINE    equ    150    ;maybe this should be 250
  9.  
  10. ; Addresses in C.CCC
  11. agbs    equ    0205H
  12. agbu    equ    01F3H
  13. albs    equ    01FAH
  14. albu    equ    01ECH
  15. bgas    equ    0204H
  16. bgau    equ    01F2H
  17. blas    equ    01F9H
  18. blau    equ    01EBH
  19. cmd    equ    0302H
  20. cmh    equ    02FAH
  21. cmphd    equ    02DDH
  22. eqwel    equ    01E5H
  23. mapuc    equ    059EH
  24. pcind    equ    01CDH
  25. pcinh    equ    01A9H
  26. pmind    equ    01DFH
  27. pminh    equ    01BBH
  28. pncind    equ    01D3H
  29. pncinh    equ    01AFH
  30. pnzind    equ    01C7H
  31. pnzinh    equ    01A3H
  32. ppind    equ    01D9H
  33. ppinh    equ    01B5H
  34. pzind    equ    01C1H
  35. pzinh    equ    019DH
  36. sdiv    equ    02CBH
  37. sdli    equ    0190H
  38. shllbe    equ    02F3H
  39. shlrbe    equ    02E5H
  40. smod    equ    020FH
  41. smul    equ    023FH
  42. usdiv    equ    0289H
  43. usmod    equ    0229H
  44. usmul    equ    026BH
  45.  
  46.  
  47.  
  48.     .comment    `
  49.  
  50. _spr(fmt,putcf,arg1)
  51. int (*putcf)();
  52. char **fmt;
  53. {
  54.     char _uspr(), c, base, *sptr, *format;
  55.     char wbuf[MAXLINE], *wptr, pf, ljflag, zfflag;
  56.     int width, precision,  *args;
  57.             `
  58.  
  59. _spr::
  60.     pop    d
  61. ;
  62.     pop    h
  63. ;    shld    fmt    (save 2 bytes by reusing args)
  64.     shld    args
  65.  
  66.     pop    h
  67.     shld    putcf
  68.     pop    h
  69.     shld    arg1
  70. ; fix back stack
  71.     push    h
  72.     push    h
  73.     push    h
  74.     push    d
  75.  
  76.     push    b
  77. ;BC will hold format
  78.  
  79.     lxi    h,-MAXLINE    ;still use stack for wbuf
  80.     dad    sp
  81.     sphl
  82.     shld    wbuf
  83. ;
  84. ;    format = *fmt++;    /* fmt first points to the format string    */
  85.  
  86. ;    lhld    fmt
  87.     lhld    args    ;args was used to hold fmt
  88.     mov    c,m    ;BC = format
  89.     inx    h
  90.     mov    b,m
  91.     inx    h
  92. ;    shld    fmt    ;fmt is not subsequently used, so why save it?
  93.     shld    args    ;cf. next statement
  94.  
  95. ;    args = fmt;        /* now fmt points to the first arg value    */
  96.  
  97. ;
  98. ;    while (c = *format++)
  99.  
  100. .p1:
  101.     ldax    b
  102.     inx    b
  103.     ora    a
  104.     jz    .pxOK
  105.  
  106. ;      if (c == '%') {
  107.  
  108. ;c in in A reg.
  109.     cpi    '%'
  110.     jnz    .default
  111.  
  112. ;        wptr = wbuf;
  113.  
  114.     lhld    wbuf
  115.     shld    wptr
  116.  
  117. ;        precision = 6;
  118.  
  119.     lxi    h,6
  120.     shld    precision
  121.  
  122. ;        ljflag = pf = zfflag = 0;
  123.  
  124.     xra    a
  125.     sta    ljflag
  126.     sta    pf
  127.     sta    zfflag
  128.  
  129. ;
  130. ;        if (*format == '-') {
  131.  
  132.     ldax    b
  133.     cpi    '-'
  134.     jnz    .p2
  135.  
  136. ;            format++;
  137.     inx    b
  138.  
  139. ;            ljflag++;
  140.  
  141.     sta    ljflag
  142.  
  143. ;         }
  144. ;
  145. ;
  146. ;        if (*format == '0') zfflag++;    /* test for zero-fill */
  147.  
  148. .p2:
  149.     ldax    b
  150.     cpi    '0'
  151.     jnz    .p3
  152.     sta    zfflag
  153. ;
  154. ;        width = (isdigit(*format)) ? _gv2(&format) : 0;
  155.  
  156. .p3:
  157.     lxi    h,0    ;width if not digit
  158. ;    cpi    '0'    ;already compared above
  159.     jc    .p4
  160.     cpi    '9'+1
  161.     cc    _gv2    ;now uses 'format' (in BC) directly, so no need
  162.             ; to pass it 
  163. .p4:    shld    width
  164. ;
  165. ;        if ((c = *format++) == '.') {
  166.  
  167.     ldax    b
  168.     inx    b
  169.     cpi    '.'
  170.     jnz    .p6
  171.  
  172. ;            precision = _gv2(&format);
  173.  
  174.     call    _gv2
  175.     shld    precision
  176.  
  177. ;            pf++;
  178.  
  179.     lxi    h,pf
  180.     inr    m
  181. ;            c = *format++;
  182.  
  183.     ldax    b
  184.     inx    b
  185.  
  186. ;         }
  187. ;
  188. ;        switch(toupper(c)) {
  189.  
  190. .p6:
  191.     cpi    'a'
  192.     jc    .p7
  193.     cpi    'z'+1
  194.     jnc    .p7
  195.     ani    5FH
  196. .p7:
  197.     cpi    'D'
  198.     jz    .decimal
  199. ;for next  few branches, value in E will be put in 'base'
  200.     cpi    'U'
  201.     mvi    e,10
  202.     jz    .bval
  203.     cpi    'X'
  204.     mvi    e,16
  205.     jz    .bval
  206.     cpi    'O'
  207.     mvi    e,8
  208.     jz    .bval
  209.     cpi    'C'
  210.     jz    .char
  211.     cpi    'S'
  212.     jz    .string
  213.     cpi    0
  214.     jz    .pxOK
  215. .default:
  216.     call    c_putcf
  217.     jmp    .p1
  218.  
  219. ;
  220. ;        case 'D':  if (*args < 0) {
  221. ;                *wptr++ = '-';
  222. ;                *args = -*args;
  223. ;                width--;
  224. ;                }
  225.  
  226. .decimal:
  227.     lhld    args
  228.     mov    e,m
  229.     inx    h
  230.     mov    d,m
  231.     mov    a,d
  232.     ral
  233.     jnc    .unsigned
  234.  
  235. ;*args = -*args
  236.     call    cmd
  237.     mov    m,d
  238.     dcx    h
  239.     mov    m,e
  240.  
  241.     lhld    wptr
  242.     mvi    m,'-'
  243.     inx    h
  244.     shld    wptr
  245.  
  246.     lhld    width
  247.     dcx    h
  248.     shld    width
  249.  
  250. ;for the next 3 cases, the value for 'base' was
  251. ; put in E before the switch branch
  252. ;
  253. ;        case 'U':  base = 10; goto val;
  254.  
  255. .unsigned:
  256.     mvi    e,10
  257. ;
  258. ;        case 'X':  base = 16; goto val;
  259.  
  260. ;
  261. ;        case 'O':  base = 8;  /* note that arbitrary bases can be
  262. ;                         added easily before this line */
  263.  
  264.  
  265. .bval:    mov    a,e
  266.     sta    base
  267. ;
  268. ;             val:  width -= _uspr(&wptr,*args++,base);
  269. ;               goto pad;
  270. .val:
  271.     lhld    args
  272.     mov    e,m
  273.     inx    h
  274.     mov    d,m
  275.     inx    h
  276.     shld    args
  277.     push    b    ;save format
  278.     mov    c,e    ;pass *args in BC (_uspr now accesses other
  279.     mov    b,d    ;           former arguments directly)
  280.     call    _uspr
  281.     pop    b
  282.  
  283.     call    cmh
  284.     xchg
  285.     lhld    width
  286.     dad    d
  287.     jmp    ..sw.pad
  288.  
  289. ;
  290. ;        case 'C':  *wptr++ = *args++;
  291. ;               width--;
  292. ;               goto pad;
  293.  
  294. .char:
  295.     lhld    args
  296.     mov    e,m
  297.     inx    h
  298.     inx    h
  299.     shld    args
  300.  
  301.     lhld    wptr
  302.     mov    m,e
  303.     inx    h
  304.     shld    wptr    
  305.  
  306.     lhld    width
  307.     dcx    h
  308. ..sw.pad:
  309.     shld    width
  310.  
  311.     jmp    .pad
  312. ;
  313. ;        case 'S':  if (!pf) precision = 200;
  314. ;               sptr = *args++;
  315. ;               while (*sptr && precision) {
  316. ;                *wptr++ = *sptr++;
  317. ;                precision--;
  318. ;                width--;
  319. ;                }
  320. ;(sptr used only for case 'S' -- can use DE to hold its value)
  321.  
  322. .string:
  323.     lda    pf
  324.     ora    a
  325.     jnz    ..s1
  326.  
  327.     lxi    h,200
  328.     shld    precision
  329. ..s1:
  330.     lhld    args
  331.     mov    e,m
  332.     inx    h
  333.     mov    d,m
  334.     inx    h
  335.     shld    args
  336. ;now DE = sptr
  337. ..s2:
  338.     ldax    d
  339.     ora    a
  340.     jz    .pad
  341.  
  342.     lhld    precision
  343.     mov    a,h
  344.     ora    l
  345.     jz    .pad
  346.  
  347.     dcx    h
  348.     shld    precision
  349.  
  350.     ldax    d
  351.     inx    d
  352.     lhld    wptr
  353.     mov    m,a
  354.     inx    h
  355.     shld    wptr
  356.  
  357.  
  358.     lhld    width
  359.     dcx    h
  360.     shld    width
  361.  
  362.     jmp    ..s2
  363. ;
  364. ;             pad:  *wptr = '\0';
  365.  
  366. .pad:
  367.     lhld    wptr
  368.     mvi    m,0
  369. ;             pad2: wptr = wbuf;
  370.  
  371.     lhld    wbuf
  372.     shld    wptr
  373.  
  374. ;               if (!ljflag)
  375.  
  376.     lda    ljflag
  377.     ora    a
  378.     jnz    .p8
  379. ;                while (width-- > 0)
  380.  
  381. ..pd1:
  382.     lhld    width    ;i.e. "while (--width >= 0)"
  383.     dcx    h
  384.     shld    width
  385.     mov    a,h
  386.     ral
  387.     jc    .p8
  388.  
  389. ;                    if ((*putcf)(zfflag ? '0' : ' ',arg1)
  390. ;                        == ERROR) return ERROR;;
  391.  
  392.     lda    zfflag
  393.     ora    a
  394.     mvi    a,' '
  395.     jz    ..pd2
  396.     mvi    a,'0'
  397. ..pd2:
  398.     call    c_putcf
  399.     jmp    ..pd1
  400. ;
  401. ;               while (*wptr)
  402.  
  403. .p8:
  404.     lhld    wptr
  405.     mov    a,m
  406.     ora    a
  407.     jz    .p9
  408. ;                if ((*putcf)(*wptr++,arg1) == ERROR) 
  409. ;                    return ERROR;
  410.     inx    h
  411.     shld    wptr
  412.     call    c_putcf
  413.     jmp    .p8
  414.  
  415. ;
  416. ;               if (ljflag)
  417.  
  418. .p9:
  419.     lda    ljflag
  420.     ora    a
  421.     jz    .p1
  422. ;                while (width-- > 0)
  423.  
  424. .p10:
  425.     lhld    width
  426.     dcx    h
  427.     shld    width
  428.     mov    a,h
  429.     ral
  430.     jc    .p1
  431. ;                    if ((*putcf)(' ',arg1) == ERROR)
  432. ;                        return ERROR;
  433. ;               break;
  434.     mvi    a,' '
  435.     call    c_putcf
  436.     jmp    .p10
  437.  
  438. ;
  439. ;        case NULL:
  440. ;               return OK;
  441.  
  442. ;(same as .pxOK)
  443. ;.null:    lxi    h,0
  444. ;    jmp    ..ret
  445.  
  446. ;
  447. ;        default:   if ((*putcf)(c,arg1) == ERROR)
  448. ;                return ERROR;
  449. ;         }
  450. ;      }
  451. ;(default done in place)
  452. ;.default:
  453. ;    call    c_putcf
  454. ;    jmp    .p1
  455.  
  456. ;      else if ((*putcf)(c,arg1) == ERROR)
  457. ;            return ERROR;
  458. ;(cf. above)
  459.  
  460.  
  461.  
  462. ;    return OK;
  463.  
  464. .pxOK:    lxi    h,0
  465. ;}
  466.  
  467.  
  468. ..ret:
  469.     xchg
  470.     lxi    h,MAXLINE
  471.     dad    sp
  472.     sphl
  473.     xchg
  474.     pop    b
  475.     ret
  476.  
  477. c_putcf:
  478. arg1    equ    $+1
  479.     lxi    h,0
  480.     push    h
  481.  
  482.     mov    l,a
  483.     mvi    h,0
  484.     push    h
  485.  
  486. putcf    equ    $+1
  487.     call    0
  488.     pop    d
  489.     pop    d
  490.     inx    h
  491.     mov    a,h
  492.     ora    l
  493.     rnz
  494. ;if error, don't return to caller -- escape from
  495. ; function, returning ERROR value
  496.     pop    h
  497.     lxi    h,-1
  498.     jmp    ..ret
  499.  
  500.  
  501.  
  502. ;arguments
  503. ;fmt:        dw    0     ;(args now used to hold fmt)
  504.  
  505. ;locals
  506. base:        db    0,0    ;2nd byte always 0 -- cf lhld in _uspr
  507. ;sptr:        dw    0    ;(*sptr kept in DE when needed)
  508. ;format:    dw    0    ;(*format now kept in BC)
  509.  
  510. wbuf:        dw    0    ;pointer to MAXLINE chars on stack
  511. wptr:        dw    0    ;*wptr
  512. pf:        db    0
  513. ljflag:        db    0
  514. zfflag:        db    0
  515. width:        dw    0
  516. precision:    dw    0
  517. args:        dw    0    ;*args
  518.  
  519.     .comment    `
  520. /*
  521.     Internal routine used by "_spr" to perform ascii-
  522.     to-decimal conversion and update an associated pointer:
  523. */
  524.  
  525. int _gv2(sptr)
  526. char **sptr;
  527. {
  528.     int n;
  529.     n = 0;
  530.     while (isdigit(**sptr)) n = 10 * n + *(*sptr)++ - '0';
  531.     return n;
  532. }            `
  533.  
  534.  
  535. _gv2:
  536. ;value of n kept in HL
  537. ;*sptr (=format) passed and kept in BC
  538.  
  539.     lxi    h,0
  540. .gvL:
  541.     ldax    b    ;*format
  542.     cpi    '0'
  543.     rc
  544.     cpi    '9'+1
  545.     rnc
  546.  
  547.     lxi    d,10    ;n = 10 * n
  548.     call    smul
  549.  
  550.     ldax    b    ;*format++
  551.     inx    b
  552.  
  553.     sui    '0'
  554.     mov    e,a
  555.     mvi    d,0
  556.  
  557.     dad    d
  558.  
  559.     jmp    .gvL
  560.  
  561.     .comment    `
  562.  
  563. char _uspr(string, n, base)
  564. char **string;
  565. unsigned n;
  566. {
  567.     char length;
  568.             `
  569.  
  570. ; Now 'n' passed in BC is only arg passed -- *string  (= wptr) and base
  571. ;  referred to directly.
  572.  
  573.  
  574. _uspr:
  575.  
  576. ;    if (n<base) {
  577.  
  578.     lhld    base
  579.     mov    e,c
  580.     mov    d,b
  581.     call    albu
  582.     jnc    .up3
  583.  
  584. ;        *(*string)++ = (n < 10) ? n + '0' : n + 55;
  585.  
  586.     mov    l,c
  587.     mov    h,b
  588.     lxi    d,-10
  589.     dad    d
  590.     jc    .up1
  591.  
  592.     mov    l,c
  593.     mov    h,b
  594.     lxi    d,'0'
  595.     dad    d
  596.     jmp    .up2
  597.  
  598. .up1:
  599.     mov    l,c
  600.     mov    h,b
  601.     lxi    d,55
  602.     dad    d
  603. .up2:
  604.     xchg
  605.     lhld    wptr
  606.     mov    m,e
  607.     inx    h
  608.     shld    wptr
  609.  
  610. ;        return 1;
  611. ;    }
  612.     lxi    h,1
  613.     ret
  614.  
  615. ;    length = _uspr(string, n/base, base);
  616.  
  617. .up3:
  618.     lhld    base
  619.     mov    e,c
  620.     mov    d,b
  621.     call    usdiv
  622. ;HL = n/base
  623.  
  624.     push    b    ;save n for mod operation in next statement
  625.     mov    c,l
  626.     mov    b,h
  627.     call    _uspr
  628.     pop    b    ;restore n
  629.  
  630.     push    h    ;save length for return value
  631.  
  632. ;    _uspr(string, n%base, base);
  633.  
  634.     lhld    base
  635.     mov    e,c
  636.     mov    d,b
  637.     call    usmod
  638. ;HL = n%base
  639.  
  640.     mov    c,l
  641.     mov    b,h
  642.     call    _uspr
  643.  
  644. ;    return length + 1;
  645. ;}
  646.     pop    h
  647.     mvi    h,0
  648.     inr    l
  649.     ret
  650.  
  651. ;*****************************************
  652.  
  653.     end
  654.  
  655.