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