home *** CD-ROM | disk | FTP | other *** search
- /*-----------------------------------------------------------------------*
- * filename - scantol.cas
- *
- * function(s)
- * stl_Digit - converts an ascii digit to a character digit
- * _scantol - scans a source for an ascii long
- *-----------------------------------------------------------------------*/
-
- /*[]------------------------------------------------------------[]*/
- /*| |*/
- /*| Turbo C Run Time Library - Version 3.0 |*/
- /*| |*/
- /*| |*/
- /*| Copyright (c) 1987,1988,1990 by Borland International |*/
- /*| All Rights Reserved. |*/
- /*| |*/
- /*[]------------------------------------------------------------[]*/
-
- #pragma inline
- #include <asmrules.h>
- #include <_scanf.h>
- #include <stdio.h>
- #include <ctype.h>
-
-
-
- /*-----------------------------------------------------------------------*
-
- Name stl_Digit - converts an ascii digit to a character digit
-
- Usage static char near stl_Digit (void)
-
- Description This procedure converts a character in range '0..9',
- 'a..z'|'A..Z' into a numeric digit. The result is the
- unchanged character if it was not a digit.
-
- The radix must be in CL at time of calling, and the character
- is in BL.
-
- If the result is a digit carry is clear, else carry is set.
- On output AH = sign extend of AL and no other registers are
- changed.
-
- The method is as follows:
-
- - for any ASCII <= '9', map letters '0..9' onto values 0..9,
- discarding any ASCII below '0'.
-
- - for any ASCII > '9', map letters 'A..Z' or 'a..z' onto
- values 10..36, and discard any ASCII which map to less
- than 10.
-
- - for any value that passed correctly through the above
- mapping, discard it if it is not less than the radix.
-
- Return value the numeric value on success; the original character on
- failure.
-
- *------------------------------------------------------------------------*/
- static void near stl_Digit (void)
- {
- asm push bx /* remember original character. */
-
- asm sub bl, '0'
- asm jb stld_badEnd
- asm cmp bl, 9
- asm jna stld_digitised /* digitized values are 0..9 */
-
- asm cmp bl, ('Z' - '0')
- asm ja stld_maybeLower
- asm sub bl, ('A' - '0' - 10)
- asm jmp short stld_extended
-
- stld_maybeLower:
- asm sub bl, ('a' - '0' - 10)
-
- stld_extended: /* extended digits are 10..radix */
- asm cmp bl, 9
- asm jna stld_badEnd
-
- stld_digitised:
- asm cmp bl, cl /* is digit within radix range ? */
- asm jnb stld_badEnd
-
- asm inc sp /* forget the original char */
- asm inc sp
- asm clc /* since we found a true digit */
- asm mov bh, 0
-
- stld_end:
- return;
-
- stld_badEnd:
- asm pop bx /* recover original character */
- asm stc /* carry set, was not a char. */
- }
-
- /*-----------------------------------------------------------------------*
-
- Name _scantol - scans a source for an ascii long
-
- Prototype in _scanf.h
-
- Description Scan input to parse a long integer. The syntax of the
- string must be:
-
- long ::= [isspace]* [sign] numeral;
-
- numeral ::= { '0' ['x'|'X'] digit [digit]* } |
- { digit [digit] }
-
- "srceP" must be a source of characters, such as a FILE *.
- Get() and UnGet() must operate on srceP to read and replace
- characters so that LR(1) parsing is permitted.
-
- The radix may be zero, or any number 2..36. If the radix
- is zero, then a radix will be chosen from the possibilities
- 8, 10, or 16, by the usual "C" rules for distinguishing octal,
- decimal, and hex numerals.
-
- If radix > 10 then the letters of the alphabet "A..Z" form
- the extended set of valid digits.
-
- If the radix is invalid or no number could be found then the
- result value is zero and the next char pointer will equal
- the starting string pointer.
-
- The width is the limit on the number of digits which may be
- accepted. It includes the sign character, if any, but does
- not include any leading spaces.
-
- The count value returned to the caller is a count of all the
- characters consumed, including leading spaces even if no
- numerals are found. It is ADDED to the existing value of
- count.
-
- The status returned is EOF if EOF was encountered before
- conversion could begin, 0 if no numerals were found before
- some other character occurred, 1 if the conversion proceeded
- correctly, and 2 if overflow occurred.
-
- Return value
- *------------------------------------------------------------------------*/
- #pragma warn -sus
- #pragma warn -rvl
- long near _scantol( int near (*Get) (void *srceP),
- void near (*UnGet) (int ch, void *srceP),
- const void *srceP,
- int radix,
- int width,
- int *countP,
- int *statusP )
- {
- char sign = 0;
- int ct = 0;
- int status = 1;
-
- /* First skip over any white-space prefix. */
- stl_skipSpace:
- ct ++;
- Get (srceP);
-
- asm or ax, ax
- asm jl stl_EOF
- asm cbw
-
- asm xchg bx, ax
- asm test bl, 80h
- asm jnz stl_notSpace
- #ifdef __HUGE__
- asm mov ax, seg _ctype
- asm mov DS, ax
- #endif
- asm mov di, 1 + offset (ES_ _ctype)
- asm test BY0 ([bx+di]), _IS_SP /* (1 + _ctype) [bx] */
- asm jnz stl_skipSpace
-
- stl_notSpace:
- asm xchg ax, bx
- asm dec W0 (width)
- asm jl stl_noDigitSeen
- /* next check for an optional negative sign. */
- asm cmp al, '+'
- asm je stl_signSeen
- asm cmp al, '-'
- asm jne stl_signed
- sign++;
-
- stl_signSeen:
- asm dec W0 (width)
- asm jl stl_noDigitSeen
- ct ++;
- Get (srceP);
- asm or ax, ax
- asm jl stl_EOF
-
- stl_signed:
- asm sub si, si /* DI:SI hold the result. */
- asm mov di, si /* default result is zero. */
-
- asm mov cx, radix
- asm jcxz stl_autoRadix
- asm cmp cx, 36
- asm ja stl_badRadix
- asm cmp cl, 2
- asm jb stl_badRadix
-
- /*
- The first few digits are special cases. Firstly, there must be
- at least one digit. Secondly, the second "digit" may be 'X' or 'x'
- if the radix is hexadecimal.
- */
- stl_radixSet:
- asm cmp al, '0'
- asm jne stl_digitNeeded
- asm cmp cl, 16 /* is "0x.." allowed ? */
- asm jne stl_nextWordDigitJmp
-
- asm dec W0 (width)
- asm jl stl_resultJmp /* DI:SI is the result */
- ct ++;
- Get (srceP);
-
- asm cmp al, 'x'
- asm je stl_nextWordDigitJmp
- asm cmp al, 'X' /* continue main part of the number */
- asm je stl_nextWordDigitJmp
- asm jmp stl_inspectDigit
-
-
- stl_EOF: /* source ended before any digit seen */
- status = EOF;
- asm jmp short stl_backUp
-
-
- /* When a syntax error occurs, the result is always zero. */
- stl_badRadix:
- stl_noDigitSeen:
- status = 0;
- stl_backUp:
- UnGet (_AX, srceP);
- ct --;
- asm sub ax, ax
- asm cwd
- goto stl_end;
-
-
- stl_resultJmp:
- asm jmp stl_result /* extend jump range */
-
-
- /*
- Automatic radix recognition:
- Note: single digit "0" with no following digits is a valid octal zero.
- */
- stl_autoRadix:
- asm cmp al, '0'
- radix = 10; /* if first digit not '0', numeral is decimal. */
- asm jne stl_digitNeeded
-
- asm dec W0 (width)
- asm jl stl_resultJmp
- ct ++;
- Get (srceP);
-
- radix = 8; /* if begins "0.." then will be octal */
-
- asm cmp al, 'x' /* unless "0x.." or "0X..", which is hex */
- asm je stl_autoHex
- asm cmp al, 'X'
- asm jne stl_inspectDigit
-
- stl_autoHex:
- radix = 16;
- stl_nextWordDigitJmp:
- asm jmp short stl_nextWordDigit
-
-
- /* If arrived here then a first true digit is still awaited. */
- stl_digitNeeded:
- asm mov cx, radix
- asm xchg bx, ax
- asm call stl_Digit
- asm xchg ax, bx
- asm jc stl_noDigitSeen
- asm xchg si, ax
- asm jmp short stl_nextWordDigit
-
-
- /*
- This is the short (16-bit) loop which accumulates digits after
- the radix and start digits have been processed, until either
- the accumulated value overflows 16 bits or until there are no
- more digits in the source string.
-
- The loop calculation is: DI:SI = (radix * SI) + new digit.
- */
- stl_digitOnWord:
- asm xchg ax, si
- asm mul W0 (radix)
- asm add si, ax
- asm adc di, dx
- asm jnz stl_nextDigit
-
- stl_nextWordDigit:
- asm dec W0 (width)
- asm jl stl_result
- ct ++;
- Get (srceP);
-
- stl_inspectDigit:
- asm mov cx, radix
- asm xchg bx, ax
- asm call stl_Digit
- asm xchg ax, bx
- asm jnc stl_digitOnWord
-
- asm jmp short stl_term
-
-
- /*
- Loop accumulating digits until overflow or the end of the digits.
-
- The loop calculation is DI:SI = (DI:SI * radix) + new digit.
- */
- stl_digitOnLong:
- asm xchg ax, si
- asm mul cx /* CX == radix */
- asm xchg ax, di
- asm xchg cx, dx
- asm mul dx
- asm add si, di
- asm adc ax, cx
- asm xchg di, ax /* result in DI:SI */
- asm adc dl, dh /* bits beyond 32nd should be zero. */
- asm jnz stl_overflow
-
- stl_nextDigit:
- asm dec W0 (width)
- asm jl stl_result
- ct ++;
- Get (srceP);
-
- asm mov cx, radix
- asm xchg bx, ax
- asm call stl_Digit
- asm xchg ax, bx
- asm jnc stl_digitOnLong
-
- /*
- Arrive here if no error but terminator character has been seen.
-
- The original terminator character must be in AL.
- */
- stl_term:
- UnGet (_AX, srceP); /* unget to the terminator. */
- ct --;
-
- stl_result:
- asm mov dx, di
- asm xchg ax, si /* result is now in DX:AX */
-
- /* Was '-' negative seen ? If so, then negate the result. */
- if (sign)
- {
- asm neg dx
- asm neg ax
- asm sbb dx, 0 /* negate (DX:AX) */
- }
-
- stl_end:
- asm LES_ di, countP
- asm mov bx, ct
- asm add ES_ [di], bx
- asm LES_ di, statusP
- asm mov bx, status
- asm mov ES_ [di], bx
-
- return( MK_LONG );
-
- /* An overflow produces a maximum result. */
- stl_overflow:
- asm mov ax, 0FFFFh
- asm mov dx, 7FFFh
- asm add al, sign
- asm adc ah, 0
- asm adc dx, 0 /* result 8000:0000h if signed. */
- status = 2;
- asm jmp short stl_end
- }
- #pragma warn .sus
- #pragma warn .rvl
-
-