home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / MATH.ZIP / SCANTOD.CAS < prev    next >
Encoding:
Text File  |  1990-06-07  |  22.9 KB  |  736 lines

  1. /*------------------------------------------------------------------------
  2.  * filename - scantod.cas
  3.  *
  4.  * function(s)
  5.  *        scantod  - converts a string to floating-point number
  6.  *        scanpop  - Clean stack after conversion error
  7.  *        scanrslt - Get conversion result
  8.  *-----------------------------------------------------------------------*/
  9.  
  10. /*[]------------------------------------------------------------[]*/
  11. /*|                                                              |*/
  12. /*|     Turbo C Run Time Library - Version 3.0                   |*/
  13. /*|                                                              |*/
  14. /*|                                                              |*/
  15. /*|     Copyright (c) 1987, 1990 by Borland International        |*/
  16. /*|     All Rights Reserved.                                     |*/
  17. /*|                                                              |*/
  18. /*[]------------------------------------------------------------[]*/
  19.  
  20.  
  21. #pragma  inline
  22. #include <asmrules.h>
  23.  
  24. #include <_scanf.h>
  25. #include <ctype.h>
  26. #include <_math.h>
  27. #include <math.h>
  28. #include <stdlib.h>
  29.  
  30. #if LPROG
  31. #define  EXTPROC1(x)  asm push cs ;  asm call near ptr (x)
  32. #else
  33. #define  EXTPROC1(x)  asm call near ptr (x)
  34. #endif
  35.  
  36. /*
  37.   Internal RTL function to perform double/float truncations.
  38.   REMOVE!!!!
  39. */
  40. #define    FLT    0
  41. #define    DBL    1
  42. double near pascal __ldtrunc(int flag, long double x, double xhuge);
  43.  
  44. /*--------------------------------------------------------------------------*
  45.  
  46. Name            scantod - converts a string to floating-point number
  47.  
  48. Usage           long double _scantod (int  near (* Get) (void *srceP),
  49.                                  void  near (* UnGet) (int ch, void *srceP),
  50.                                  const void  *srceP,
  51.                                  int     width,
  52.                                  int    *countP,
  53.                                  int    *statusP )
  54.  
  55. Prototype in    _scanf.h
  56.  
  57. Description     Convert a string to a long double precision real. The syntax
  58.                 of the string must be:
  59.  
  60.                 float    ::= [isspace]* [sign] [realnum] [exponent]
  61.  
  62.                 isspace  ::= as per <ctype.h>:isspace
  63.  
  64.                 realnum  ::= {digit [digit]* ['.' [digit]* ]} |
  65.                              {'.' digit [digit]*}
  66.  
  67.                 exponent ::= 'e'|'E' [sign] digit [digit]*
  68.  
  69.                 "srceP"  is a  pointer to  some kind  of object  from which
  70.                          characters are  scanned. For example, it  may be a
  71.                          FILE  *. The  functions Get()  and UnGet() operate
  72.                          upon srceP to get  characters and possibly replace
  73.                          one character, allowing LR(1) scanning rules.
  74.  
  75.                 The digits must be decimal.
  76.  
  77.                 The width is the limit on the number of digits which may be
  78.                 accepted. It includes the sign  character, if any, but does
  79.                 not include any leading spaces.
  80.  
  81.                 The count  value returned to the  caller is a count  of all
  82.                 the characters  consumed, including leading spaces  even if
  83.                 no numerals are found. It is ADDED to the existing value of
  84.                 count.
  85.  
  86.                 The status  returned is EOF  if EOF was  encountered before
  87.                 conversion could begin, 0 if  no numerals were found before
  88.                 some   other   character  occurred,  1  if  the  conversion
  89.                 proceeded   correctly,  and  2  if  overflow  or  underflow
  90.                 occurred.
  91.  
  92.                 If the source string is  not a valid floating point numeral
  93.                 then the result value is zero and the next char left in the
  94.                 source will be  the first char encountered which  could not
  95.                 be part  of the number. If  the number is too  large or too
  96.                 tiny then the result is signed HUGE_VAL or zero.
  97.  
  98. Method          The conversion proceeds in two stages. Firstly, the decimal
  99.                 strings for fraction and exponent must be captured.
  100.  
  101.                 The  fraction is  held as   a 63-bit  unsigned integer  (18
  102.                 decimals of  precision), with separate sign.  Digits beyond
  103.                 the 18th are truncated.
  104.  
  105.                 The exponent is  held as a short integer  in binary format,
  106.                 and is adjusted  to note the position of  the decimal point
  107.                 in the fraction so that  the "fraction" is normalized as an
  108.                 integer with decimal point to the right.
  109.  
  110.                 When  both fraction  and exponent  have been  captured, the
  111.                 second  stage is  to combine  them. This  is done  with the
  112.                 formula:
  113.  
  114.                         result = 10^(exponent) * fraction * sign.
  115.  
  116.                 If the  result overflows + or  - HUGE will be  returned. If
  117.                 the result is an underflow, zero is returned.
  118.  
  119.                 The iNDP-87 is not used as  much as might be optimum if the
  120.                 user has a coprocessor installed.  A balance is sought,  so
  121.                 that the routine makes  strategic use of co-intructions but
  122.                 not  frequent use  which would  be quite  slow if  software
  123.                 emulation is used in place of a chip.
  124.  
  125.                 The following diagram may be helpful with understanding the
  126.                 relations between the variables:
  127.  
  128.                    000012345789012345.098765432109876E+99
  129.                       |---decimals-->|
  130.                       |--------------.----digits---->|   not counting the '.'
  131.  
  132.                 Decimals are  counted negative if   the '.' is  left of the
  133.                 first digit.  Digits are positive unless  no non-zero digit
  134.                 is ever seen.
  135.  
  136. Return value    _scantod returns the converted value of the input string
  137.  
  138. *---------------------------------------------------------------------------*/
  139.  
  140.         /* +/- infinity, +/- NAN */
  141.  
  142. static const float INF   =   1.0/0.0;
  143. static const float INFM  = -(1.0/0.0);
  144. static const float NAN   =   0.0/0.0;
  145. static const float NANM  = -(0.0/0.0);
  146.  
  147. #pragma warn -rvl
  148. #pragma warn -use
  149. #pragma warn -sus
  150. static long double near _scantod (
  151.                         int  near (* Get) (void *srceP),
  152.                         void near (* UnGet) (int ch, void *srceP),
  153.                         const void  *srceP,
  154.                         int     width,
  155.                         int    *countP,
  156.                         int    *statusP )
  157. {
  158.         int     decimals;           /* register SI = 0x8000         */
  159.         int     digits;             /* register DI = -2             */
  160.         int     exponent;
  161.         char    sign    = 0;
  162.         char    FirstDigit = 1;
  163.         char    saw_sign= 0;
  164.         char    expSign = 0;
  165.         char    ExpOflow= 0;
  166.         int     ct      = 0;
  167.         int     status  = 1;
  168.  
  169.         long double frac= 0.0;
  170.  
  171.  
  172. asm     mov     si, 8000h
  173. asm     mov     di, -2
  174.  
  175. /*
  176.   Skip leading spaces on the input numeral.
  177. */
  178. std_nextBlank:
  179.     ct ++;
  180.     Get (srceP);
  181.  
  182. asm     or      ax, ax
  183. asm     jnl     not_instantEOF          /* No EOF the first time        */
  184. asm     jmp     std_EOF                 /* EOF happened first thing     */
  185.  
  186. not_instantEOF:
  187. asm     cbw
  188. asm     xchg    bx, ax
  189. asm     test    bl, 80h
  190. asm     jnz     std_notSpace
  191. #if __HUGE__
  192. asm     mov     ax, seg _ctype
  193. asm     mov     ES, ax
  194. asm     test    BY0 (ES: _ctype [bx+1]), _IS_SP
  195. #else
  196. asm     test    BY0 (_ctype [bx+1]), _IS_SP
  197. #endif
  198. asm     jnz     std_nextBlank
  199.  
  200. std_notSpace:
  201. asm     xchg    ax, bx
  202. asm     dec     W0 (width)
  203. asm     jl      std_fractionLimited
  204.  
  205. /*
  206.   Is the numeral preceded by a sign ?
  207. */
  208. asm     cmp     al, '+'
  209. asm     je      std_signSeen
  210. asm     cmp     al, '-'
  211. asm     jne     std_fracChar            /* AL must hold a fraction character. */
  212. asm     inc     BY0 (sign)              /* set flag to true == negative */
  213.  
  214. std_signSeen:
  215.         saw_sign++;
  216.  
  217. std_fracLoop:                   /* Pick up the next character of the fraction.  */
  218. asm     dec     W0 (width)
  219. asm     jl      std_fractionLimited
  220.  
  221.         ct ++;
  222.         Get (srceP);
  223.  
  224. /*-------------------------------------------------------------------------
  225.   We need to check for the special cases where +INF -INF +NAN -NAN 
  226.   might be specified.
  227. -------------------------------------------------------------------------*/
  228. asm     cmp     BY0 (FirstDigit), 1
  229. asm     jne     std_fracChar            /* Its not 1st char, continue   */
  230. asm     cmp     BY0 (saw_sign), 0
  231. asm     je      std_fracChar            /* There was no sign, continue  */
  232. asm     cmp     al, 'I'
  233. asm     je      relPossibleINF          /* Maybe we have +/-INF         */
  234. asm     cmp     al, 'N'
  235. asm     je      relPossibleNAN          /* Maybe we have +/-NAN         */
  236. asm     jmp     short std_fracChar      /* Its not a special case       */
  237.  
  238. relPossibleINF:
  239. asm     jmp     PossibleINF;            /* far jmp within relative range*/
  240.  
  241. relPossibleNAN:
  242. asm     jmp     PossibleNAN;            /* far jmp within relative range*/
  243.  
  244. std_fracChar:
  245. asm     mov     BY0 (FirstDigit), 0
  246. asm     cmp     al, '.'         /* Watch for decimal points     */
  247. asm     je      std_fracPoint
  248. asm     cmp     al, '9'
  249. asm     ja      std_fracEndJmp  /* All other non-numeric characters ..  */
  250. asm     cmp     al, '0'
  251. asm     jb      std_fracEndJmp  /* .. are fraction terminators. */
  252.  
  253. asm     sub     al, '0'         /* convert digit to equivalent number.  */
  254. asm     cbw
  255.  
  256. /*
  257.   Keep a count of the digits seen.
  258. */
  259. asm     inc     di
  260. asm     jg      std_notFirst            /* was it the first digit ?     */
  261.  
  262. /*
  263.   The first digit begins the fraction.  Leading zeros are noted by setting
  264.   digits -1, so that the fraction syntax is valid if no other digits
  265.   are seen, but following digits will still be treated as "firsts".
  266.   Leading non-zero digits cause digits to be set to 1.
  267. */
  268. asm     mov     frac [0], al
  269. asm     mov     di, 1
  270. asm     or      al, al
  271. asm     jnz     std_fracLoop
  272. asm     neg     di
  273. asm     cmp     si, 8000h               /* has decimal point been seen ? */
  274. asm     je      std_fracLoop
  275. asm     dec     si                      /* if yes, move it to the left. */
  276. asm     jmp     short   std_fracLoop
  277.  
  278.  
  279. /*
  280.   Arrive here when fraction is width-limited but valid.
  281. */
  282. std_fractionLimited:
  283. asm     mov     al, 'e'                 /* Behave as if exponent started. */
  284.  
  285. jmp_to_fracEnd:                         /* Label within relative range  */
  286. asm     jmp     std_fracEnd             /* Width will limit exponent, too. */
  287.  
  288. /*
  289.   Error action placed here for short jump range.
  290. */
  291. std_EOF:
  292.     status = -1;
  293. asm     jmp     short   std_noResult
  294.  
  295.  
  296. std_fracEndJmp:                 /* extend jump range    */
  297. asm     jmp     std_fracEnd
  298.  
  299.  
  300. /*
  301.   A decimal point has been seen
  302. */
  303. std_fracPoint:
  304. asm     cmp     si, 8000h               /* Has a previous decimal point been seen ?     */
  305. asm     jne     jmp_to_fracEnd          /* If so, the fraction is terminated.   */
  306.  
  307. asm     sub     si, si                  /* result if '.' before any digit */
  308. asm     or      di, di
  309. asm     jng     std_fracLoop
  310. asm     mov     si, di                  /* decimals = digits    */
  311. asm     jmp     short   std_fracLoop
  312.  
  313. /*
  314.   If a digit is seen, then multiply the existing fraction by 10 and
  315.   add in the new digit.  The special case of the first 5 digits is
  316.   treated separately for speed.
  317. */
  318. std_notFirst:
  319. asm     cmp     di, 5
  320. asm     ja      std_beyond5
  321.  
  322. asm     xchg    bx, ax
  323. asm     mov     ax, 10
  324. asm     mul     W0 (frac)
  325. asm     add     ax, bx
  326. asm     adc     dl, dh
  327. asm     mov     frac [0], ax
  328. asm     mov     frac [2], dx
  329. asm     jmp     std_fracLoop
  330.  
  331. /*
  332.   Digits beyond the 6th are more rare in practice (even in 6-digit
  333.   numbers, 5 will be quick), so no further special cases are
  334.   justified.  Beyond 18 digits, ignore the digit values but
  335.   keep scanning.
  336. */
  337. std_beyond5:
  338. asm     cmp     di, 18
  339. asm     ja      jmp_frac_loop
  340.  
  341. asm     xchg    bx, ax
  342. asm     mov     ax, 10
  343. asm     mul     W0 (frac [6])
  344. asm     mov     (frac [6]), ax
  345. asm     mov     ax, 10
  346. asm     mul     W0 (frac [4])
  347. asm     mov     (frac [4]), ax
  348. asm     push    dx
  349. asm     mov     ax, 10
  350. asm     mul     W0 (frac [2])
  351. asm     mov     (frac [2]), ax
  352. asm     push    dx
  353. asm     mov     ax, 10
  354. asm     mul     W0 (frac [0])
  355. asm     add     ax, bx
  356. asm     mov     (frac [0]), ax
  357. asm     adc     (frac [2]), dx
  358. asm     pop     dx
  359. asm     adc     (frac [4]), dx
  360. asm     pop     dx
  361. asm     adc     (frac [6]), dx
  362.  
  363. jmp_frac_loop:
  364. asm     jmp     std_fracLoop
  365.  
  366.  
  367. /*
  368.         error clauses placed here within short-jump range of whole routine.
  369.  
  370.         Arrive here if an error occurred.
  371. */
  372. std_noDigitSeen:
  373.         status = 0;
  374.  
  375. std_noResult:
  376.         if (width >= 0)
  377.         {
  378.                 UnGet (_AX, srceP);
  379.                 ct --;
  380.         }
  381. asm     FLDZ                    /*     and a zero numeric result. */
  382. asm     jmp     std_end
  383.  
  384. /**      end of error clauses.
  385. */
  386.  
  387.  
  388. /*
  389.   The fraction was ended.  If it was valid, it must have had at least
  390.   one digit.  AL must hold the character which terminated the fraction.
  391. */
  392. std_fracEnd:
  393. asm     cmp     di, -2
  394. asm     jz      std_noDigitSeen
  395.  
  396. /*
  397.   If no decimal point was seen, then the decimal is assumed to be at
  398.   the rightmost edge.
  399. */
  400. asm     cmp     si, 8000h
  401. asm     jne     std_exponent
  402. asm     mov     si, di                  /* decimals = digits    */
  403.  
  404. /*
  405.   Now we must gather the exponent.  First, check for 'E' or 'e' to
  406.   introduce it, then if found gather the short integer.
  407. */
  408. std_exponent:
  409. asm     mov     digits, di
  410. asm     mov     decimals, si
  411. asm     sub     di, di          /* DI = exponent  */
  412.  
  413. asm     cmp     al, 'E'
  414. asm     je      std_present
  415. asm     cmp     al, 'e'
  416. asm     jne     std_combine
  417.  
  418. std_present:
  419. asm     dec     W0 (width)
  420. asm     jl      std_exponentLimited
  421.  
  422.         ct ++;
  423.         Get (srceP);
  424.  
  425. asm     cmp     al, '+'
  426. asm     je      std_expNext
  427. asm     cmp     al, '-'         /* is exponent negative ?       */
  428. asm     jne     std_expGotNext
  429.  
  430.         expSign ++;
  431.  
  432. std_expNext:
  433. asm     dec     W0 (width)
  434. asm     jl     std_exponentLimited
  435.  
  436.         ct ++;
  437.         Get (srceP);
  438.  
  439. std_expGotNext:                 /* if no leading sign, must be leading digit. */
  440. asm     cmp     al, '9'
  441. asm     ja      std_combine
  442. asm     sub     al, '0'
  443. asm     jb      std_expNonDigit
  444. asm     cbw
  445.  
  446. /*
  447.   The largest IEEE long doubles have exponents -4932 <= X <= +4932.  
  448.   Numbers outside that range will be accepted as infinite or zero,
  449.   according to the sign of the exponent.
  450. */
  451. std_expLoop:
  452. asm     xchg    ax, di
  453. asm     mov     dx, 10
  454. asm     mul     dx
  455. asm     add     di, ax                  /* DI = exponent        */
  456.  
  457. asm     cmp     di, 4932                /* The upper limit on exponents */
  458. asm     jle     std_expNext
  459.  
  460. asm     xor    di, di            /* Exponent overflow, set flag */
  461. asm    mov    BY0 (ExpOflow), 1
  462. asm     jmp     short   std_expNext
  463.  
  464. std_expNonDigit:
  465. asm     add     al, '0'                 /* restore original terminator  */
  466.  
  467. /*
  468.   Arrive here when a valid syntax has been terminated.
  469.  
  470.   AL must still contain the terminating character, unchanged.
  471. */
  472. std_combine:
  473.         UnGet (_AX, srceP);
  474.         ct--;
  475.  
  476. /*
  477.   Arrive here with valid termination but no terminator to be pushed back.
  478. */
  479. std_exponentLimited:
  480.  
  481. asm     test    BY0 (expSign), 0FFH     /* was the exponent signed ?    */
  482. asm     jz      skip_neg
  483. asm     neg     di
  484. /*
  485.   Normal stays normal, Infinity becomes 0 if exponent was hugely negative.
  486. */
  487. asm    neg    BY0 (ExpOflow)
  488.  
  489. skip_neg:
  490.  
  491. /*
  492.   The special case when digits = -1 occurs when the fraction is zero.
  493.   In that case, the result is always zero, whatever the exponent.
  494. */
  495. asm     mov     bx, digits
  496. asm     or      bx, bx
  497. asm     jnl     std_nonZero
  498. asm     FLDZ
  499. asm     jmp     std_end
  500.  
  501. /*
  502.   Combine the decimal point position with the exponent.  The exponent
  503.   begins with a value that reflects the position of the decimal point.
  504. */
  505. std_nonZero:
  506. asm     mov     cx, decimals
  507. asm     mov     ax, cx
  508. asm     add     ax, di          /* 1.0E(decimals+exponent) = upper bound */
  509.  
  510. /*                                 0.1E(decimals+exponent) = lower bound
  511.   Convert underflows to zero and overflows to ld HUGE_VAL.
  512. */
  513. asm    cmp    BY0 (ExpOflow), 1    /* big (+) exp -> ld HUGE_VAL */
  514. asm    je    std_isInfinite
  515. asm    cmp    BY0 (ExpOflow), -1    /* big (-) exp -> 0   */
  516. asm     jne     std_isNormal
  517.  
  518. std_isZero:
  519. asm     FLDZ
  520. asm     jmp     short status2
  521.  
  522. std_isInfinite:
  523. /* 
  524.         Make 'frac' a long double HUGE_VAL 
  525. */
  526. asm     mov     ax, -1
  527. asm     mov     frac[0], ax
  528. asm     mov     frac[2], ax
  529. asm     mov     frac[4], ax
  530. asm     mov     frac[6], ax
  531. asm     mov     frac[8], 07FFEH
  532.  
  533. asm     FLD     LONGDOUBLE( frac )
  534. status2:
  535. asm     mov     W0 (status), 2
  536. asm     jmp     std_end
  537.  
  538.  
  539. std_isNormal:           /* For normal numbers multiply fraction * 10^exponent */
  540. asm     mov     ax, bx
  541. asm     cmp     bx, 18
  542. asm     jna     std_usualPoint
  543. asm     mov     bx, 18          /* a maximum of 18 digits are used      */
  544.  
  545. std_usualPoint:
  546. asm     add     ax, cx
  547. asm     sub     cx, bx
  548.  
  549. std_beginExp:                   /* CX = decimal point contribution to exponent */
  550. asm     add     di, CX          /* DI = combined exponent       */
  551.  
  552. asm     FILD    qword ptr (frac)
  553.  
  554. asm     mov     ax, di          /* Calculate 10^(|exponent|).   */
  555. asm     or      ax, ax
  556. asm     jz      std_end         /* no multiply required if exponent is zero. */
  557. asm     jnl     std_pow
  558. asm     neg     ax
  559.  
  560. std_pow:
  561. asm     push    ax
  562.     EXTPROC1 (pow10) /* leaves result in iNDP-87 ST(0) TOS   */
  563. asm     pop     ax
  564.  
  565. asm     or      di, di
  566. asm     jnl     std_expPlus
  567.  
  568. asm     FDIV                    /* negative exponent --> 1 / 10^|exponent|      */
  569. asm     jmp     short   std_end
  570.  
  571. std_expPlus:
  572. asm     FMUL                    /* combine the exponent with the fraction. */
  573.  
  574. std_end:
  575.         if (sign)
  576.         {
  577. asm             FCHS            /* negate the result    */
  578.         }
  579.  
  580. std_returnPP:  /* update *(suffixPP) with the next character's position. */
  581. /*
  582.   Finally, of course, don't forget to return the converted number !
  583. */
  584. std_exit:
  585. asm     LES_    di, countP
  586. asm     mov     bx, ct
  587. asm     add     ES_ [di], bx
  588. asm     LES_    di, statusP
  589. asm     mov     bx, status
  590. asm     mov     ES_ [di], bx
  591.         return;
  592.  
  593. /*-------------------------------------------------------------------------
  594.                 Special case code to scan +INF -INF +NAN -NAN
  595.   -------------------------------------------------------------------------
  596.   This special case code is positioned down here so that it won't mess up
  597.   relative jumps for the rest of the function.
  598.  
  599.   One side effect here, if this ultimately isn't +INF -INF +NAN -NAN will be
  600.   that the apps input stream is now messed up because we needed to look 
  601.   ahead more than 1 character to recognize INF or NAN. The 'unget' functions
  602.   are only guaranteed to be able to unget a maximum of one char. This means
  603.   on a worst case input like "+INX" there will be 3 characters we won't be 
  604.   able to push back on the stream successfully.  There's not much that can
  605.   be done to prevent this.  The same kind of thing can happen when reading
  606.   E format numbers, for example "1.234E+Q".  By the time the 'Q' is seen
  607.   "E+" has gone by.
  608. --------------------------------------------------------------------------*/
  609. PossibleINF:
  610.         ct ++;
  611.         Get (srceP);
  612. asm     dec     W0 (width)
  613. asm     jl      Didnt_pan_out
  614. asm     cmp     al, 'N'
  615. asm     jne     Didnt_pan_out
  616.         ct ++;
  617.         Get (srceP);
  618. asm     dec     W0 (width)
  619. asm     jl      Didnt_pan_out
  620. asm     cmp     al, 'F'
  621. asm     jne     Didnt_pan_out
  622.         if (sign)
  623.         {
  624. asm     FLD     FLOAT( INFM )
  625.         }
  626.         else
  627.         {
  628. asm     FLD     FLOAT( INF )
  629.         }
  630. asm     jmp     std_returnPP
  631.  
  632. PossibleNAN:
  633.         ct ++;
  634.         Get (srceP);
  635. asm     dec     W0 (width)
  636. asm     jl      Didnt_pan_out
  637. asm     cmp     al, 'A'
  638. asm     jne     Didnt_pan_out
  639.         ct ++;
  640.         Get (srceP);
  641. asm     dec     W0 (width)
  642. asm     jl      Didnt_pan_out
  643. asm     cmp     al, 'N'
  644. asm     jne     Didnt_pan_out
  645.         if (sign)
  646.         {
  647. asm     FLD     FLOAT( NANM )
  648.         }
  649.         else
  650.         {
  651. asm     FLD     FLOAT( NAN )
  652.         }
  653. asm     jmp     std_returnPP
  654.  
  655. Didnt_pan_out:                          /* It wasn't +/-/INF/NAN        */
  656.         status = 0;
  657. asm     jmp     std_noDigitSeen
  658. }
  659. #pragma warn .rvl
  660. #pragma warn .use
  661. #pragma warn .sus
  662.  
  663. /*--------------------------------------------------------------------------*
  664.  
  665. Name            scanpop - Clean stack after conversion error
  666.  
  667. Usage           void _scanpop(void);
  668.  
  669. Description     This function is used to clean the stack after a conversion
  670.                 error in _scanner function
  671.  
  672. *---------------------------------------------------------------------------*/
  673.  
  674. static  void  near _scanpop()
  675.         {
  676. asm     FSTP    ST(0)   /* pop math coprocessor stack    */
  677.         }
  678.  
  679. /*--------------------------------------------------------------------------*
  680.  
  681. Name            scanrslt - Get conversion result
  682.  
  683. Usage           void _scanrslt(double *rsltP, int rsltType);
  684.  
  685. Description     This function is  used to get the result  of the conversion
  686.                 in _scanner function
  687.  
  688. *---------------------------------------------------------------------------*/
  689.  
  690. static  void  near  _scanrslt(void *rsltP, int rsltType)
  691. {
  692.     long double temp;
  693.  
  694. asm    FSTP    LONGDOUBLE (temp)
  695.  
  696.         if (rsltType & isLong)
  697.         *(double *)rsltP = __ldtrunc(DBL, temp, HUGE_VAL);
  698.         else if (rsltType & isLongDouble)
  699.         *(long double *)rsltP = temp;
  700.         else
  701.         *(float *)rsltP = __ldtrunc(FLT, temp, 1./0.);
  702. }
  703.  
  704. /*--------------------------------------------------------------------------*
  705.  
  706. Description     The functions described above are essentially used by scanf
  707.                 functions family. As for  _realcvt, these functions are not
  708.                 called  directly, but  via a  pointer to  function. This is
  709.                 done  in  order  to  include  the  real  conversion only if
  710.                 needed.
  711.  
  712.                 Each  time the  compiler needs  to build  a reference  to a
  713.                 double or  float value, it generates  an external reference
  714.                 to __turboFloat which forces this module to be linked in.
  715.  
  716. *---------------------------------------------------------------------------*/
  717.  
  718. #define CodeSeg _TEXT
  719. #define cPtr    dw
  720.  
  721. #pragma warn -use
  722. #pragma warn -asm
  723.  
  724. static  void    turboFloat()
  725. {
  726. asm     CodeSeg ENDS
  727. asm             PUBLIC  __turboFloat
  728. asm     __turboFloat      equ     8087h
  729. asm     _SCNSEG SEGMENT PUBLIC WORD 'DATA'
  730. asm             cPtr    _scantod
  731. asm             cPtr    _scanrslt
  732. asm             cPtr    _scanpop
  733. asm     _SCNSEG ENDS
  734. asm     CodeSeg SEGMENT
  735. }
  736.