charstod.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * The authors of this software are Rob Pike and Ken Thompson.
  3. * Copyright (c) 2002 by Lucent Technologies.
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose without fee is hereby granted, provided that this entire notice
  6. * is included in all copies of any software which is or includes a copy
  7. * or modification of this software and in all copies of the supporting
  8. * documentation for such software.
  9. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
  10. * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
  11. * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
  12. * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
  13. */
  14. #include <u.h>
  15. #include <libc.h>
  16. #include "fmtdef.h"
  17. /*
  18. * Reads a floating-point number by interpreting successive characters
  19. * returned by (*f)(vp). The last call it makes to f terminates the
  20. * scan, so is not a character in the number. It may therefore be
  21. * necessary to back up the input stream up one byte after calling charstod.
  22. */
  23. double
  24. fmtcharstod(int(*f)(void*), void *vp)
  25. {
  26. double num, dem;
  27. int neg, eneg, dig, exp, c;
  28. num = 0;
  29. neg = 0;
  30. dig = 0;
  31. exp = 0;
  32. eneg = 0;
  33. c = (*f)(vp);
  34. while(c == ' ' || c == '\t')
  35. c = (*f)(vp);
  36. if(c == '-' || c == '+'){
  37. if(c == '-')
  38. neg = 1;
  39. c = (*f)(vp);
  40. }
  41. while(c >= '0' && c <= '9'){
  42. num = num*10 + c-'0';
  43. c = (*f)(vp);
  44. }
  45. if(c == '.')
  46. c = (*f)(vp);
  47. while(c >= '0' && c <= '9'){
  48. num = num*10 + c-'0';
  49. dig++;
  50. c = (*f)(vp);
  51. }
  52. if(c == 'e' || c == 'E'){
  53. c = (*f)(vp);
  54. if(c == '-' || c == '+'){
  55. if(c == '-'){
  56. dig = -dig;
  57. eneg = 1;
  58. }
  59. c = (*f)(vp);
  60. }
  61. while(c >= '0' && c <= '9'){
  62. exp = exp*10 + c-'0';
  63. c = (*f)(vp);
  64. }
  65. }
  66. exp -= dig;
  67. if(exp < 0){
  68. exp = -exp;
  69. eneg = !eneg;
  70. }
  71. dem = __fmtpow10(exp);
  72. if(eneg)
  73. num /= dem;
  74. else
  75. num *= dem;
  76. if(neg)
  77. return -num;
  78. return num;
  79. }