home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / stdlib.zip / SCANF.ASM < prev    next >
Assembly Source File  |  1990-06-25  |  11KB  |  525 lines

  1. stdlib        segment    para public 'slcode'
  2.         assume    cs:stdlib
  3.     extrn sl_print:far,sl_putw:far, sl_putcr:far
  4. print    macro
  5.  call sl_print
  6.   endm
  7. ;
  8.         extrn    sl_gets:far, sl_free:far, sl_atoi2:far
  9.         extrn    sl_atou2:far, sl_atol2:far, sl_atoul2:far
  10.         extrn    sl_atoh2:far
  11. ;
  12. ;
  13. ; Scanf- Like the "C" routine by the same name.  Calling sequence:
  14. ;
  15. ;               call    scanf
  16. ;               db      "format string",0
  17. ;               dd      item1, item2, ..., itemn
  18. ;
  19. ; The format string is identical to "C".  Item1..Itemn are pointers to
  20. ; values to print for this string.  Each item must be matched by the
  21. ; corresponding "%xxx" item in the format string.
  22. ;
  23. ; Format string format:
  24. ;
  25. ; 1)    If a non-whitespace character in the format string matches the next
  26. ;    input character, scanf eats that input character;  otherwise scanf
  27. ;    ignores the character in the format string.  If any whitespace char-
  28. ;    acter appears, scanf ignores all leading whitespace characters (new-
  29. ;    line not included) before an item.  If there is no whitespace on the
  30. ;    input, scanf ignores the whitespace characters in the input stream.
  31. ;
  32. ; 2)    Format Control Strings:
  33. ;
  34. ;    General format:  "%^f" where:
  35. ;
  36. ;                ^ = ^
  37. ;                f = a format character
  38. ;
  39. ;            The "^" is optional.
  40. ;
  41. ;    ^ present    The address associated with f is the address of a
  42. ;                pointer to the object, not the address of
  43. ;                the object itself.  The pointer is a far ptr.
  44. ;
  45. ;    f is one of the following
  46. ;
  47. ;        d -    Read a signed integer in decimal notation.
  48. ;        i -    Read a signed integer in decimal notation.
  49. ;        x -    Read a word value in hexadecimal notation.
  50. ;        h -    Read a byte value in hexadecimal notation.
  51. ;        u -    Read an unsigned integer in decimal notation.
  52. ;        c -    Read a character.
  53. ;        s -    Read a string.
  54. ;
  55. ;        ld-    Read a long signed integer.
  56. ;        li-    Read a long signed integer.
  57. ;        lx-    Read a long hexadecimal number.
  58. ;        lu-    Read a long unsigned number.
  59. ;
  60. ;
  61. ;    Calling Sequence:
  62. ;
  63. ;        call    Scanf
  64. ;        db    "Format String",0
  65. ;        dd    adrs1, adrs2, ..., adrsn
  66. ;
  67. ;    Where the format string is ala "C" (and the descriptions above)
  68. ;    and adrs1..adrsn are addresses (far ptr) to the items to print.
  69. ;    Unless the "^" modifier is present, these addresses are the actual
  70. ;    addresses of the objects to print.
  71. ;
  72. ; Note: Scanf always calls GETS to read a new string from the standard
  73. ;    input device.  Reading a string variable always reads all input
  74. ;    from the current position to the end of the current line.
  75. ;
  76. ;
  77. cr        equ    0dh
  78. ff        equ    0ch
  79. lf        equ    0ah
  80. tab        equ    09h
  81. bs        equ    08h
  82. ;
  83. RtnAdrs        equ    2[bp]
  84. OprndPtr    equ    -4[bp]
  85. InputPtr    equ    -8[bp]
  86. InpIndex    equ    -10[bp]
  87. ;
  88.         public  sl_scanf
  89. sl_scanf    proc    far
  90. ;
  91. ; Read a line from the standard input and save away a pointer to it.
  92. ;
  93.         push    bp
  94.         mov    bp, sp
  95.         sub    sp, 10            ;Save ptr to operands here.
  96.         pushf
  97.         push    ax
  98.         push    bx
  99.         push    cx
  100.         push    dx
  101.         push    di
  102.         push    si
  103.         push    es
  104.         push    ds
  105. ;
  106.         call    sl_gets
  107.         call    scanf
  108.         les    di, InputPtr
  109.         call    sl_free
  110.         mov    di, OprndPtr
  111.         mov    RtnAdrs, di    ;Put out new return address.
  112. ;
  113.         pop    ds
  114.         pop    es
  115.         pop    si
  116.         pop    di
  117.         pop    dx
  118.         pop    cx
  119.         pop    bx
  120.         pop    ax
  121.         popf
  122.         mov    sp, bp        ;Remove local variables.
  123.         pop    bp
  124.         ret
  125. ;
  126. sl_scanf    endp
  127. ;
  128. ;
  129. ; SSCANF-    Just like SCANF except you pass a pointer to the data
  130. ;        string in es:di rather than having scanf read it from
  131. ;        the keyboard.
  132. ;
  133.         public    sl_sscanf
  134. sl_sscanf    proc    far
  135.         push    bp
  136.         mov    bp, sp
  137.         sub    sp, 10            ;Save ptr to operands here.
  138.         pushf
  139.         push    ax
  140.         push    bx
  141.         push    cx
  142.         push    dx
  143.         push    di
  144.         push    si
  145.         push    es
  146.         push    ds
  147. ;
  148.         call    scanf
  149.         mov    di, OprndPtr
  150.         mov    RtnAdrs, di    ;Put out new return address.
  151. ;
  152.         pop    ds
  153.         pop    es
  154.         pop    si
  155.         pop    di
  156.         pop    dx
  157.         pop    cx
  158.         pop    bx
  159.         pop    ax
  160.         popf
  161.         mov    sp, bp        ;Remove local variables.
  162.         pop    bp
  163.         ret
  164. sl_sscanf    endp
  165. ;
  166. ;
  167. ; "Guts" of the scanf routines.
  168. ;
  169. scanf        proc    near
  170.         mov    InputPtr+2, es        ;Sock away ptr to string.
  171.         mov    InputPtr, di
  172.         mov    word ptr InpIndex, 0
  173. ;
  174. ;
  175. ; Get pointers to the return address (format string).
  176. ;
  177.         cld
  178.         les    di, RtnAdrs
  179.         lds    si, RtnAdrs
  180. ;
  181. ; Okay, search for the end of the format string.  After these instructions,
  182. ; di points just beyond the zero byte at the end of the format string.  This,
  183. ; of course, points at the first address beyond the format string.
  184. ;
  185.         mov    al, 0
  186.         mov    cx, 65535
  187.     repne    scasb
  188.         mov     OprndPtr, di
  189.         mov    OprndPtr+2, es
  190. ;
  191. ScanItems:      lodsb            ;Get char si points at.
  192. ScanItems2:    cmp    al, 0        ;EOS?
  193.         jz    ScanfDone
  194.         cmp    al, "%"        ;Start of a format string?
  195.         jz    FmtItem
  196. SkipIt:        cmp    al, " "
  197.         jz    SkipWS
  198.         les    di, InputPtr
  199.         mov    bx, InpIndex
  200.         cmp    al, es:[di][bx]
  201.         jnz    ScanItems
  202.         inc    word ptr InpIndex
  203.         jmp    ScanItems
  204. ;
  205. SkipWS:        les    di, InputPtr
  206.         mov    bx, InpIndex
  207. SkipWSLp:    cmp    byte ptr es:[di][bx], ' '
  208.         jnz    DoneSkip
  209.         inc    bx
  210.         jmp    SkipWSLp
  211. ;
  212. DoneSkip:    mov    InpIndex, bx
  213. Skip2:        lodsb
  214.         cmp    al, ' '            ;Skip additional whitespace
  215.         jz    Skip2            ; in the format string.
  216.         dec    si
  217.         jmp    ScanItems
  218. ;
  219. ;
  220. FmtItem:    call    GetFmtItem    ;Process the format item here.
  221.         jmp    ScanItems
  222. ;
  223. ;
  224. ScanfDone:        ret
  225. scanf        endp
  226. ;
  227. ;
  228. ;
  229. ; If we just saw a "%", come down here to handle the format item.
  230. ;
  231. GetFmtItem    proc    near
  232. ;
  233.         lodsb                ;Get char beyond "%"
  234. ;
  235. ; See if the user wants to specify a handle rather than a straight pointer
  236. ;
  237.         cmp    al, '^'
  238.         jne     ChkFmtChars
  239.         mov    ah, al
  240.         lodsb                ;Skip "^" character
  241. ;
  242. ; Okay, process the format characters down here.
  243. ;
  244. ChkFmtChars:    and    al, 05fh        ;l.c. -> U.C.
  245.         cmp    al, 'D'
  246.         je    GetDec
  247.         cmp    al, 'I'
  248.         je    GetDec
  249.         cmp    al, 'C'
  250.         je    GetChar
  251. ;
  252.         cmp    al, 'X'
  253.         jne    TryH
  254.         jmp    GetHexWord
  255. ;
  256. TryH:        cmp    al, 'H'
  257.         jne    TryU
  258.         jmp    GetHexByte
  259. ;
  260. TryU:        cmp    al, 'U'
  261.         jne    TryString
  262.         jmp    GetUDec
  263. ;
  264. TryString:    cmp    al, 'S'
  265.         jne    TryLong
  266.         jmp    GetString
  267. ;
  268. TryLong:    cmp    al, 'L'
  269.         jne    Default
  270. ;
  271. ; If we've got the "L" modifier, this is a long value to print, get the
  272. ; data type character as the next value:
  273. ;
  274.         lodsb
  275.         and    al, 05fh        ;l.c. -> U.C.
  276.         cmp    al, 'D'
  277.         je    JmpDec
  278.         cmp    al, 'I'
  279.         jne    TryLU
  280. JmpDec:        jmp    LongDec
  281. ;
  282. TryLU:        cmp    al, 'U'
  283.         jne    Default
  284.         jmp    LongU
  285. ;
  286. ;
  287. ;
  288. ; If none of the above, simply return without printing anything.
  289. ;
  290. Default:    ret
  291. ;
  292. ;
  293. ;
  294. ;
  295. ;
  296. ; Get a signed decimal value here.
  297. ;
  298. GetDec:        call    GetPtr            ;Get next pointer into ES:BX
  299.         push    ax            ;Save possible "^" char in ah
  300.         push    es
  301.         les    di, InputPtr
  302.         add    di, InpIndex        ;Point SI at integer.
  303.         cmp    byte ptr es:[di], 0    ;At end of string?
  304.         jz    QuitGetDec
  305.         call    sl_atoi2        ;Convert to integer in AX.
  306.         sub    di, InputPtr
  307.         mov    InpIndex, di
  308.         pop    es                 ; Ignore overflow or error.
  309.         mov    es:[bx], ax
  310. ;
  311.         pop    ax
  312.         ret
  313. ;
  314. QuitGetDec:    pop    es
  315.         pop    ax
  316.         ret                ;We're done!
  317. ;
  318. ;
  319. ;
  320. ; Print a character variable here.
  321. ;
  322. GetChar:    call    GetPtr            ;Get next pointer into ES:BX
  323.         push    ax            ;Save possible "^" char in ah
  324.         push    es
  325.         les    di, InputPtr
  326.         add    di, InpIndex        ;Point SI at char.
  327.         mov    al, es:[di]        ;Get char
  328.         cmp    al, 0            ;See if at EOS.
  329.         jz    QuitGetChar
  330.         inc    word ptr InpIndex    ;Bump up index.
  331.         pop    es             
  332.         mov    es:[bx], al
  333. ;
  334.         pop    ax
  335.         ret
  336. ;
  337. QuitGetChar:    pop    es
  338.         pop    ax
  339.         ret                ;We're done!
  340. ;
  341. ;
  342. ;
  343. ; Print a hexadecimal word value here.
  344. ;
  345. GetHexWord:    call    GetPtr            ;Get next pointer into ES:BX
  346.         push    ax            ;Save possible "^" char in ah
  347.         push    es
  348.         les    di, InputPtr
  349.         add    di, InpIndex        ;Point SI at integer.
  350.         cmp    byte ptr es:[di], 0    ;Check for EOS
  351.         jz    QuitGetHexWord
  352.         call    sl_atoh2        ;Convert to integer in AX.
  353.         sub    di, InputPtr
  354.         mov    InpIndex, di
  355.         pop    es                 ; Ignore overflow or error.
  356.         mov    es:[bx], ax
  357. ;
  358.         pop    ax
  359.         ret
  360. ;
  361. QuitGetHexWord:    pop    es
  362.         pop    ax
  363.         ret                ;We're done!
  364. ;
  365. ;
  366. ;
  367. ;
  368. ; Print hex bytes here.
  369. ;
  370. ;
  371. GetHexByte:    call    GetPtr            ;Get next pointer into ES:BX
  372.         push    ax            ;Save possible "^" char in ah
  373.         push    es
  374.         les    di, InputPtr
  375.         add    di, InpIndex        ;Point SI at integer.
  376.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  377.         jz    QuitGetHexByte
  378.         call    sl_atoh2        ;Convert to integer in AX.
  379.         sub    di, InputPtr
  380.         mov    InpIndex, di
  381.         pop    es                 ; Ignore overflow or error.
  382.         mov    es:[bx], al
  383. ;
  384.         pop    ax
  385.         ret
  386. ;
  387. QuitGetHexByte:    pop    es
  388.         pop    ax
  389.         ret                ;We're done!
  390. ;
  391. ;
  392. ;
  393. ; Output unsigned decimal numbers here:
  394. ;
  395. GetUDec:    call    GetPtr            ;Get next pointer into ES:BX
  396.         push    ax            ;Save possible "^" char in ah
  397.         push    es
  398.         les    di, InputPtr
  399.         add    di, InpIndex        ;Point SI at integer.
  400.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  401.         jz    QuitGetUDec
  402.         call    sl_atou2        ;Convert to integer in AX.
  403.         sub    di, InputPtr
  404.         mov    InpIndex, di
  405.         pop    es                 ; Ignore overflow or error.
  406.         mov    es:[bx], ax
  407. ;
  408.         pop    ax
  409.         ret
  410. ;
  411. QuitGetUDec:    pop    es
  412.         pop    ax
  413.         ret                ;We're done!
  414. ;
  415. ;
  416. ; Output a string here:
  417. ;
  418. GetString:    push    ax
  419.         push    si
  420.         push    es
  421.         push    ds
  422. ;
  423.         call    GetPtr
  424.         mov    di, bx
  425.         lds    si, InputPtr
  426.         add    si, InpIndex
  427. GetStrLp:    lodsb            ;Get next char
  428.         stosb
  429.         cmp    al, 0
  430.         jnz    GetStrLp
  431.         sub    si, InputPtr
  432.         dec    si
  433.         mov    InpIndex, si
  434. ;
  435.         pop    ds
  436.         pop    es
  437.         pop    si
  438.         pop    ax
  439.         ret                ;We're done!
  440. ;
  441. ;
  442. ;
  443. ; Print a signed long decimal value here.
  444. ;
  445. LongDec:    push    dx
  446.         call    GetPtr            ;Get next pointer into ES:BX
  447.         push    ax            ;Save possible "^" char in ah
  448.         push    es
  449.         les    di, InputPtr
  450.         add    di, InpIndex        ;Point SI at integer.
  451.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  452.         jz    QuitLongDec
  453.         call    sl_atol2        ;Convert to integer in AX.
  454.         sub    di, InputPtr
  455.         mov    InpIndex, di
  456.         pop    es                 ; Ignore overflow or error.
  457.         mov    es:[bx], ax
  458.         mov    es:2[bx], dx
  459. ;
  460.         pop    ax
  461.         pop    dx
  462.         ret                ;We're done!
  463. ;
  464. QuitLongDec:    pop    es
  465.         pop    ax
  466.         pop    dx
  467.         ret
  468. ;
  469. ;
  470. ;
  471. ; Print an unsigned long decimal value here.
  472. ;
  473. LongU:        push    dx
  474.         call    GetPtr            ;Get next pointer into ES:BX
  475.         push    ax            ;Save possible "^" char in ah
  476.         push    es
  477.         les    di, InputPtr
  478.         add    di, InpIndex        ;Point SI at integer.
  479.         cmp    byte ptr es:[di], 0
  480.         je    QuitLongU
  481.         call    sl_atoul2        ;Convert to integer in AX.
  482.         sub    di, InputPtr
  483.         mov    InpIndex, di
  484.         pop    es                 ; Ignore overflow or error.
  485.         mov    es:[bx], ax
  486.         mov    es:2[bx], dx
  487. ;
  488.         pop    ax
  489.         pop    dx
  490.         ret                ;We're done!
  491. ;
  492. QuitLongU:    pop    es
  493.         pop    ax
  494.         pop    dx
  495.         ret
  496. ;
  497. GetFmtItem    endp
  498. ;
  499. ;
  500. ;
  501. ;
  502. ;
  503. ;
  504. ; GetPtr- Grabs the next pointer which OprndPtr points at and returns this
  505. ;      far pointer in ES:BX.
  506. ;
  507. GetPtr        proc    near
  508.         les    di, OprndPtr
  509.         les    bx, es:[di]
  510.         add    word ptr OprndPtr, 4
  511. ;
  512. ; See if this is a handle rather than a pointer.
  513. ;
  514.         cmp    ah, '^'
  515.         jne    NotHandle
  516.         les    bx, es:[bx]
  517. NotHandle:    ret
  518. GetPtr        endp
  519. ;
  520. ;
  521. ;
  522. ;
  523. stdlib        ends
  524.         end
  525.