|
|
1.1 ! root 1: /* ! 2: * libc/stdio/_dscan.c ! 3: * ANSI-compliant C standard i/o library internals. ! 4: * _dscan(), _dassign() ! 5: * ANSI 4.9.6.2. ! 6: * Floating point support for _scanf(). ! 7: * Kept in a separate source to allow scanf() et al. to link ! 8: * without floating point support. ! 9: */ ! 10: ! 11: #include <stdio.h> ! 12: #include <stdlib.h> ! 13: ! 14: #if 0 ! 15: #include <locale.h> ! 16: #else ! 17: #define _decimal_point '.' ! 18: #endif ! 19: ! 20: /* Compile-time options. */ ! 21: #define LONGDOUBLE 0 /* iff sizeof(double) != sizeof(long double) */ ! 22: ! 23: /* ! 24: * Read an ASCII floating point number ! 25: * containing at most 'width' characters from 'fp' into 'buf'. ! 26: * Convert the result using strtod() and store it through *dp. ! 27: * Return the number of characters read. ! 28: * Use the finite state machine shown below. In the diagram, ! 29: * states are in (parens) ! 30: * inputs are in [brackets] ! 31: * For all inputs not shown, transition is to (end) state. ! 32: * -- ! 33: * / \ ! 34: * v \ ! 35: * ----------> [0-9] -> (3) ! 36: * / ^ | \ ! 37: * / / | \ ! 38: * / / v \ ! 39: * / / [.] \ ->[+-] - ! 40: * / / | \ / \ ! 41: * / / | \ / \ ! 42: * / / v v / v ! 43: * (0) --> [+-] -> (1) (4) --> [Ee] -> (6) -> [0-9] -> (7) ! 44: * \ / / ^ ^ / ! 45: * \ / / / \ / ! 46: * \ / / / -- ! 47: * \ / / / ! 48: * \ / / / ! 49: * \ / / / ! 50: * v v / ! 51: * [.] --> (2) -> [0-9] -> (5) ! 52: * ^ / ! 53: * \ / ! 54: * -- ! 55: * This cannot be done correctly with the single character pushback ! 56: * guaranteed by ungetc(); for example, rejecting "+y", "1Ex" or "1E+x" ! 57: * requires two or three character pushback. ! 58: */ ! 59: int ! 60: _dscan(buf, fp, width, dp) register char *buf; FILE *fp; int width; double *dp; ! 61: { ! 62: register int c, state, count; ! 63: register char *cp; ! 64: ! 65: cp = buf; ! 66: for (state = count = 0; count < width; ++count) { ! 67: *cp++ = c = getc(fp); ! 68: switch (c) { ! 69: case '+': ! 70: case '-': ! 71: if (state != 0 && state != 6) ! 72: break; ! 73: state++; ! 74: continue; ! 75: case '0': ! 76: case '1': ! 77: case '2': ! 78: case '3': ! 79: case '4': ! 80: case '5': ! 81: case '6': ! 82: case '7': ! 83: case '8': ! 84: case '9': ! 85: if (state == 0 || state == 1 || state == 3) ! 86: state = 3; ! 87: else if (state == 2 || state == 4 || state == 5) ! 88: state = 5; ! 89: else if (state == 6 || state == 7) ! 90: state = 7; ! 91: else ! 92: break; ! 93: continue; ! 94: case 'E': ! 95: case 'e': ! 96: if (state < 3 || 5 < state) ! 97: break; ! 98: state = 6; ! 99: continue; ! 100: default: ! 101: if (c != _decimal_point) ! 102: break; ! 103: if (state <= 1) ! 104: state = 2; ! 105: else if (state == 3) ! 106: state++; ! 107: else ! 108: break; ! 109: continue; ! 110: } ! 111: --cp; ! 112: ungetc(c, fp); ! 113: break; ! 114: } ! 115: *cp = '\0'; ! 116: *dp = strtod(buf, (char **)NULL); ! 117: return ((int)(cp - buf)); ! 118: } ! 119: ! 120: /* ! 121: * Assign *dp through *vp, width depending on flag. ! 122: */ ! 123: void ! 124: _dassign(vp, dp, flag) Void *vp; double *dp; int flag; ! 125: { ! 126: #if LONGDOUBLE ! 127: if (flag == 'L') ! 128: *(long double *)vp = (long double)*dp; ! 129: else if (flag == 'l') ! 130: #else ! 131: if (flag == 'L' || flag == 'l') ! 132: #endif ! 133: *(double *)vp = *dp; ! 134: else ! 135: *(float *)vp = (float)*dp; ! 136: } ! 137: ! 138: /* end of libc/stdio/_dscan.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.