doscan.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /* $Id$ */
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <varargs.h>
  5. union ptr_union {
  6. char *chr_p;
  7. unsigned short *ushort_p;
  8. unsigned int *uint_p;
  9. unsigned long *ulong_p;
  10. #ifndef NOFLOAT
  11. float *float_p;
  12. double *double_p;
  13. #endif
  14. };
  15. static char Xtable[128];
  16. /*
  17. * the routine that does the job
  18. */
  19. _doscanf (iop, format, ap)
  20. register FILE *iop;
  21. char *format; /* the format control string */
  22. va_list ap;
  23. {
  24. int done = 0; /* number of items done */
  25. int base; /* conversion base */
  26. long val; /* an integer value */
  27. int sign; /* sign flag */
  28. int do_assign; /* assignment suppression flag */
  29. unsigned width; /* width of field */
  30. int widflag; /* width was specified */
  31. int longflag; /* true if long */
  32. int shortflag; /* true if short */
  33. int done_some; /* true if we have seen some data */
  34. int reverse; /* reverse the checking in [...] */
  35. int kind;
  36. register int ic;
  37. #ifndef NOFLOAT
  38. extern double atof();
  39. int dotseen;
  40. int expseen;
  41. char buffer[128];
  42. #endif
  43. ic = getc(iop);
  44. if (ic == EOF) {
  45. done = EOF;
  46. goto quit;
  47. }
  48. while (1) {
  49. if (isspace(*format)) {
  50. while (isspace (*format))
  51. ++format; /* skip whitespace */
  52. while (isspace (ic)) ic = getc(iop);
  53. }
  54. if (!*format)
  55. goto all_done; /* end of format */
  56. if (ic < 0)
  57. goto quit; /* seen an error */
  58. if (*format != '%') {
  59. if (ic != *format)
  60. goto all_done;
  61. ++format;
  62. ic = getc(iop);
  63. continue;
  64. }
  65. ++format;
  66. do_assign = 1;
  67. if (*format == '*') {
  68. ++format;
  69. do_assign = 0;
  70. }
  71. if (isdigit (*format)) {
  72. widflag = 1;
  73. for (width = 0; isdigit (*format);)
  74. width = width * 10 + *format++ - '0';
  75. } else
  76. widflag = 0; /* no width spec */
  77. if (longflag = (*format == 'L' || *format == 'l'))
  78. ++format;
  79. else if (shortflag = (*format == 'H' || *format == 'h'))
  80. ++format;
  81. if (isupper(*format)) {
  82. kind = tolower(*format);
  83. longflag = 1;
  84. }
  85. else kind = *format;
  86. if (kind != 'c' && kind != '[')
  87. while (isspace (ic))
  88. ic = getc(iop);
  89. done_some = 0; /* nothing yet */
  90. switch (kind) {
  91. case 'o':
  92. base = 8;
  93. goto decimal;
  94. case 'u':
  95. case 'd':
  96. base = 10;
  97. goto decimal;
  98. case 'x':
  99. base = 16;
  100. if (((!widflag) || width >= 2) && ic == '0') {
  101. ic = getc(iop);
  102. if (tolower (ic) == 'x') {
  103. width -= 2;
  104. done_some = 1;
  105. ic = getc(iop);
  106. } else {
  107. ungetc(ic, iop);
  108. ic = '0';
  109. }
  110. }
  111. decimal:
  112. val = 0L; /* our result value */
  113. sign = 0; /* assume positive */
  114. if (!widflag)
  115. width = 0xffff; /* very wide */
  116. if (width && ic == '+')
  117. ic = getc(iop);
  118. else if (width && ic == '-') {
  119. sign = 1;
  120. ic = getc(iop);
  121. }
  122. while (width--) {
  123. if (isdigit (ic) && ic - '0' < base)
  124. ic -= '0';
  125. else if (base == 16 && tolower (ic) >= 'a' && tolower (ic) <= 'f')
  126. ic = 10 + tolower (ic) - 'a';
  127. else
  128. break;
  129. val = val * base + ic;
  130. ic = getc(iop);
  131. done_some = 1;
  132. }
  133. if (do_assign) {
  134. if (sign)
  135. val = -val;
  136. if (longflag)
  137. *va_arg(ap, unsigned long *) = (unsigned long) val;
  138. else if (shortflag)
  139. *va_arg(ap, unsigned short *) = (unsigned short) val;
  140. else
  141. *va_arg(ap, unsigned *) = (unsigned) val;
  142. }
  143. if (done_some) {
  144. if (do_assign) ++done;
  145. }
  146. else
  147. goto all_done;
  148. break;
  149. case 'c':
  150. if (!widflag)
  151. width = 1;
  152. { register char *p;
  153. if (do_assign)
  154. p = va_arg(ap, char *);
  155. while (width-- && ic >= 0) {
  156. if (do_assign)
  157. *p++ = (char) ic;
  158. ic = getc(iop);
  159. done_some = 1;
  160. }
  161. }
  162. if (do_assign) {
  163. if (done_some)
  164. ++done;
  165. }
  166. break;
  167. case 's':
  168. if (!widflag)
  169. width = 0xffff;
  170. { register char *p;
  171. if (do_assign)
  172. p = va_arg(ap, char *);
  173. while (width-- && !isspace (ic) && ic > 0) {
  174. if (do_assign)
  175. *p++ = (char) ic;
  176. ic = getc(iop);
  177. done_some = 1;
  178. }
  179. if (do_assign) /* terminate the string */
  180. *p = '\0';
  181. }
  182. if (done_some) {
  183. if (do_assign)
  184. ++done;
  185. }
  186. else
  187. goto all_done;
  188. break;
  189. case '[':
  190. if (!widflag)
  191. width = 0xffff;
  192. if ( *(++format) == '^' ) {
  193. reverse = 1;
  194. format++;
  195. } else
  196. reverse = 0;
  197. { register char *c;
  198. for (c = Xtable; c < &Xtable[128]; c++) *c = 0;
  199. }
  200. while (*format && *format != ']') {
  201. Xtable[*format++] = 1;
  202. }
  203. if (!*format)
  204. goto quit;
  205. { register char *p;
  206. if (do_assign)
  207. p = va_arg(ap, char *);
  208. while (width-- && ic > 0 &&
  209. (Xtable[ic] ^ reverse)) {
  210. if (do_assign)
  211. *p++ = (char) ic;
  212. ic = getc(iop);
  213. done_some = 1;
  214. }
  215. if (do_assign) /* terminate the string */
  216. *p = '\0';
  217. }
  218. if (done_some) {
  219. if (do_assign)
  220. ++done;
  221. }
  222. else
  223. goto all_done;
  224. break;
  225. #ifndef NOFLOAT:
  226. case 'e':
  227. case 'f': {
  228. register char *c = buffer;
  229. if (!widflag) width = 127;
  230. if (width >= 128) width = 127;
  231. if (width && (ic == '+' || ic == '-')) {
  232. *c++ = ic;
  233. width--;
  234. ic = getc(iop);
  235. }
  236. while (isdigit(ic) && width) {
  237. width--;
  238. *c++ = ic;
  239. ic = getc(iop);
  240. }
  241. if (ic == '.' && width) {
  242. width--;
  243. *c++ = ic;
  244. ic = getc(iop);
  245. }
  246. while (isdigit(ic) && width) {
  247. width--;
  248. *c++ = ic;
  249. ic = getc(iop);
  250. }
  251. if (width && (ic == 'e' || ic == 'E')) {
  252. width--;
  253. *c++ = ic;
  254. ic = getc(iop);
  255. if (width && (ic == '+' || ic == '-')) {
  256. width--;
  257. *c++ = ic;
  258. ic = getc(iop);
  259. }
  260. }
  261. while (isdigit(ic) && width) {
  262. width--;
  263. *c++ = ic;
  264. ic = getc(iop);
  265. }
  266. if (c == buffer) goto all_done;
  267. *c = 0;
  268. if (do_assign) {
  269. done++;
  270. if (longflag)
  271. *va_arg(ap, double *) = atof(buffer);
  272. else
  273. *va_arg(ap, float *) = atof(buffer);
  274. }
  275. }
  276. break;
  277. #endif
  278. } /* end switch */
  279. ++format;
  280. }
  281. all_done:
  282. if (ic >= 0)
  283. ungetc(ic, iop);
  284. quit:
  285. return done;
  286. }