scanf.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * This file based on scanf.c from 'Dlibs' on the atari ST (RdeBath)
  3. *
  4. * 19-OCT-88: Dale Schumacher
  5. * > John Stanley has again been a great help in debugging, particularly
  6. * > with the printf/scanf functions which are his creation.
  7. *
  8. * Dale Schumacher 399 Beacon Ave.
  9. * (alias: Dalnefre') St. Paul, MN 55104
  10. * dal@syntel.UUCP United States of America
  11. * "It's not reality that's important, but how you perceive things."
  12. *
  13. */
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  18. #include <stdarg.h>
  19. #define va_strt va_start
  20. #else
  21. #include <varargs.h>
  22. #define va_strt(p,i) va_start(p)
  23. #endif
  24. #ifdef L_scanf
  25. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  26. int scanf(const char * fmt, ...)
  27. #else
  28. int scanf(fmt, va_alist)
  29. __const char *fmt;
  30. va_dcl
  31. #endif
  32. {
  33. va_list ptr;
  34. int rv;
  35. va_strt(ptr, fmt);
  36. rv = vfscanf(stdin,fmt,ptr);
  37. va_end(ptr);
  38. return rv;
  39. }
  40. #endif
  41. #ifdef L_sscanf
  42. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  43. int sscanf(char * sp, const char * fmt, ...)
  44. #else
  45. int sscanf(sp, fmt, va_alist)
  46. char * sp;
  47. __const char *fmt;
  48. va_dcl
  49. #endif
  50. {
  51. static FILE string[1] =
  52. {
  53. {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1,
  54. _IOFBF | __MODE_READ}
  55. };
  56. va_list ptr;
  57. int rv;
  58. va_strt(ptr, fmt);
  59. string->bufpos = sp;
  60. rv = vfscanf(string,fmt,ptr);
  61. va_end(ptr);
  62. return rv;
  63. }
  64. #endif
  65. #ifdef L_fscanf
  66. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  67. int fscanf(FILE * fp, const char * fmt, ...)
  68. #else
  69. int fscanf(fp, fmt, va_alist)
  70. FILE * fp;
  71. __const char *fmt;
  72. va_dcl
  73. #endif
  74. {
  75. va_list ptr;
  76. int rv;
  77. va_strt(ptr, fmt);
  78. rv = vfscanf(fp,fmt,ptr);
  79. va_end(ptr);
  80. return rv;
  81. }
  82. #endif
  83. #ifdef L_vscanf
  84. int vscanf(fmt, ap)
  85. __const char *fmt;
  86. va_list ap;
  87. {
  88. return vfscanf(stdin,fmt,ap);
  89. }
  90. #endif
  91. #ifdef L_vsscanf
  92. int vsscanf(sp, fmt, ap)
  93. char * sp;
  94. __const char *fmt;
  95. {
  96. static FILE string[1] =
  97. {
  98. {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1,
  99. _IOFBF | __MODE_READ}
  100. };
  101. string->bufpos = sp;
  102. return vfscanf(string,fmt,ap);
  103. }
  104. #endif
  105. #ifdef L_vfscanf
  106. /* #define skip() do{c=getc(fp); if (c<1) goto done;}while(isspace(c))*/
  107. #define skip() while(isspace(c)) { if ((c=getc(fp))<1) goto done; }
  108. #if FLOATS
  109. /* fp scan actions */
  110. #define F_NADA 0 /* just change state */
  111. #define F_SIGN 1 /* set sign */
  112. #define F_ESIGN 2 /* set exponent's sign */
  113. #define F_INT 3 /* adjust integer part */
  114. #define F_FRAC 4 /* adjust fraction part */
  115. #define F_EXP 5 /* adjust exponent part */
  116. #define F_QUIT 6
  117. #define NSTATE 8
  118. #define FS_INIT 0 /* initial state */
  119. #define FS_SIGNED 1 /* saw sign */
  120. #define FS_DIGS 2 /* saw digits, no . */
  121. #define FS_DOT 3 /* saw ., no digits */
  122. #define FS_DD 4 /* saw digits and . */
  123. #define FS_E 5 /* saw 'e' */
  124. #define FS_ESIGN 6 /* saw exp's sign */
  125. #define FS_EDIGS 7 /* saw exp's digits */
  126. #define FC_DIG 0
  127. #define FC_DOT 1
  128. #define FC_E 2
  129. #define FC_SIGN 3
  130. /* given transition,state do what action? */
  131. int fp_do[][NSTATE] = {
  132. {F_INT,F_INT,F_INT,
  133. F_FRAC,F_FRAC,
  134. F_EXP,F_EXP,F_EXP}, /* see digit */
  135. {F_NADA,F_NADA,F_NADA,
  136. F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT}, /* see '.' */
  137. {F_QUIT,F_QUIT,
  138. F_NADA,F_QUIT,F_NADA,
  139. F_QUIT,F_QUIT,F_QUIT}, /* see e/E */
  140. {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT,
  141. F_ESIGN,F_QUIT,F_QUIT}, /* see sign */
  142. };
  143. /* given transition,state what is new state? */
  144. int fp_ns[][NSTATE] = {
  145. {FS_DIGS,FS_DIGS,FS_DIGS,
  146. FS_DD,FS_DD,
  147. FS_EDIGS,FS_EDIGS,FS_EDIGS}, /* see digit */
  148. {FS_DOT,FS_DOT,FS_DD,
  149. }, /* see '.' */
  150. {0,0,
  151. FS_E,0,FS_E,
  152. }, /* see e/E */
  153. {FS_SIGNED,0,0,0,0,
  154. FS_ESIGN,0,0}, /* see sign */
  155. };
  156. /* which states are valid terminators? */
  157. int fp_sval[NSTATE] = {
  158. 0,0,1,0,1,0,0,1
  159. };
  160. #endif
  161. vfscanf(fp, fmt, ap)
  162. register FILE *fp;
  163. register char *fmt;
  164. va_list ap;
  165. {
  166. register long n;
  167. register int c, width, lval, cnt = 0;
  168. int store, neg, base, wide1, endnull, rngflag, c2;
  169. register unsigned char *p;
  170. unsigned char delim[128], digits[17], *q;
  171. #if FLOATS
  172. long frac, expo;
  173. int eneg, fraclen, fstate, trans;
  174. double fx, fp_scan();
  175. #endif
  176. if (!*fmt)
  177. return (0);
  178. c = getc(fp);
  179. while (c > 0)
  180. {
  181. store = 0;
  182. if (*fmt == '%')
  183. {
  184. n = 0;
  185. width = -1;
  186. wide1 = 1;
  187. base = 10;
  188. lval = (sizeof(long) == sizeof(int));
  189. store = 1;
  190. endnull = 1;
  191. neg = -1;
  192. strcpy(delim, "\011\012\013\014\015 ");
  193. strcpy(digits, "0123456789ABCDEF");
  194. if (fmt[1] == '*')
  195. {
  196. endnull = store = 0;
  197. ++fmt;
  198. }
  199. while (isdigit(*++fmt))/* width digit(s) */
  200. {
  201. if (width == -1)
  202. width = 0;
  203. wide1 = width = (width * 10) + (*fmt - '0');
  204. }
  205. --fmt;
  206. fmtnxt:
  207. ++fmt;
  208. switch (tolower(*fmt)) /* tolower() is a MACRO! */
  209. {
  210. case '*':
  211. endnull = store = 0;
  212. goto fmtnxt;
  213. case 'l': /* long data */
  214. lval = 1;
  215. goto fmtnxt;
  216. case 'h': /* short data */
  217. lval = 0;
  218. goto fmtnxt;
  219. case 'i': /* any-base numeric */
  220. base = 0;
  221. goto numfmt;
  222. case 'b': /* unsigned binary */
  223. base = 2;
  224. goto numfmt;
  225. case 'o': /* unsigned octal */
  226. base = 8;
  227. goto numfmt;
  228. case 'x': /* unsigned hexadecimal */
  229. base = 16;
  230. goto numfmt;
  231. case 'd': /* SIGNED decimal */
  232. neg = 0;
  233. /* FALL-THRU */
  234. case 'u': /* unsigned decimal */
  235. numfmt:skip();
  236. if (isupper(*fmt))
  237. lval = 1;
  238. if (!base)
  239. {
  240. base = 10;
  241. neg = 0;
  242. if (c == '%')
  243. {
  244. base = 2;
  245. goto skip1;
  246. }
  247. else if (c == '0')
  248. {
  249. c = getc(fp);
  250. if (c < 1)
  251. goto savnum;
  252. if ((c != 'x')
  253. && (c != 'X'))
  254. {
  255. base = 8;
  256. digits[8] = '\0';
  257. goto zeroin;
  258. }
  259. base = 16;
  260. goto skip1;
  261. }
  262. }
  263. if ((neg == 0) && (base == 10)
  264. && ((neg = (c == '-')) || (c == '+')))
  265. {
  266. skip1:
  267. c = getc(fp);
  268. if (c < 1)
  269. goto done;
  270. }
  271. digits[base] = '\0';
  272. p = ((unsigned char *)
  273. strchr(digits, toupper(c)));
  274. if ((!c || !p) && width)
  275. goto done;
  276. while (p && width-- && c)
  277. {
  278. n = (n * base) + (p - digits);
  279. c = getc(fp);
  280. zeroin:
  281. p = ((unsigned char *)
  282. strchr(digits, toupper(c)));
  283. }
  284. savnum:
  285. if (store)
  286. {
  287. if (neg == 1)
  288. n = -n;
  289. if (lval)
  290. *va_arg(ap, long*) = n;
  291. else
  292. *va_arg(ap, short*) = n;
  293. ++cnt;
  294. }
  295. break;
  296. #if FLOATS
  297. case 'e': /* float */
  298. case 'f':
  299. case 'g':
  300. skip();
  301. if (isupper(*fmt))
  302. lval = 1;
  303. fstate = FS_INIT;
  304. neg = 0;
  305. eneg = 0;
  306. n = 0;
  307. frac = 0;
  308. expo = 0;
  309. fraclen = 0;
  310. while (c && width--)
  311. {
  312. if (c >= '0' && c <= '9')
  313. trans = FC_DIG;
  314. else if (c == '.')
  315. trans = FC_DOT;
  316. else if (c == '+' || c == '-')
  317. trans = FC_SIGN;
  318. else if (tolower(c) == 'e')
  319. trans = FC_E;
  320. else
  321. goto fdone;
  322. switch (fp_do[trans][fstate])
  323. {
  324. case F_SIGN:
  325. neg = (c == '-');
  326. break;
  327. case F_ESIGN:
  328. eneg = (c == '-');
  329. break;
  330. case F_INT:
  331. n = 10 * n + (c - '0');
  332. break;
  333. case F_FRAC:
  334. frac = 10 * frac + (c - '0');
  335. fraclen++;
  336. break;
  337. case F_EXP:
  338. expo = 10 * expo + (c - '0');
  339. break;
  340. case F_QUIT:
  341. goto fdone;
  342. }
  343. fstate = fp_ns[trans][fstate];
  344. c = getc(fp);
  345. }
  346. fdone:
  347. if (!fp_sval[fstate])
  348. goto done;
  349. if (store)
  350. {
  351. fx = fp_scan(neg, eneg, n, frac, expo, fraclen);
  352. if (lval)
  353. *va_arg(ap, double *) = fx;
  354. else
  355. *va_arg(ap, float *) = fx;
  356. ++cnt;
  357. }
  358. break;
  359. #endif
  360. case 'c': /* character data */
  361. width = wide1;
  362. lval = endnull = 0;
  363. delim[0] = '\0';
  364. goto strproc;
  365. case '[': /* string w/ delimiter set */
  366. /* get delimiters */
  367. p = delim;
  368. if (*++fmt == '^')
  369. {
  370. fmt++;
  371. lval = 0;
  372. }
  373. else
  374. lval = 1;
  375. rngflag = 2;
  376. if ((*fmt == ']') || (*fmt == '-'))
  377. {
  378. *p++ = *fmt++;
  379. rngflag = 0;
  380. }
  381. while (*fmt != ']')
  382. {
  383. if (*fmt == '\0')
  384. goto done;
  385. switch (rngflag)
  386. {
  387. case 1:
  388. c2 = *(p - 2);
  389. if (c2 <= *fmt)
  390. {
  391. p -= 2;
  392. while (c2 < *fmt)
  393. *p++ = c2++;
  394. rngflag = 2;
  395. break;
  396. }
  397. /* fall thru intentional */
  398. case 0:
  399. rngflag = (*fmt == '-');
  400. break;
  401. case 2:
  402. rngflag = 0;
  403. }
  404. *p++ = *fmt++;
  405. }
  406. *p = '\0';
  407. goto strproc;
  408. case 's': /* string data */
  409. lval = 0;
  410. skip();
  411. strproc:
  412. /* process string */
  413. p = va_arg(ap, unsigned char *);
  414. /* if the 1st char fails, match fails */
  415. if (width)
  416. {
  417. q = ((unsigned char *)
  418. strchr(delim, c));
  419. if ((c < 1) || lval == (q==0))
  420. {
  421. if (endnull)
  422. *p = '\0';
  423. goto done;
  424. }
  425. }
  426. for (;;) /* FOREVER */
  427. {
  428. if (store)
  429. *p++ = c;
  430. if (((c = getc(fp)) < 1) ||
  431. (--width == 0))
  432. break;
  433. q = ((unsigned char *)
  434. strchr(delim, c));
  435. if (lval == (q==0))
  436. break;
  437. }
  438. if (store)
  439. {
  440. if (endnull)
  441. *p = '\0';
  442. ++cnt;
  443. }
  444. break;
  445. case '\0': /* early EOS */
  446. --fmt;
  447. /* FALL THRU */
  448. default:
  449. goto cmatch;
  450. }
  451. }
  452. else if (isspace(*fmt)) /* skip whitespace */
  453. {
  454. skip();
  455. }
  456. else
  457. { /* normal match char */
  458. cmatch:
  459. if (c != *fmt)
  460. break;
  461. c = getc(fp);
  462. }
  463. if (!*++fmt)
  464. break;
  465. }
  466. done: /* end of scan */
  467. if ((c == EOF) && (cnt == 0))
  468. return (EOF);
  469. if( c != EOF )
  470. ungetc(c, fp);
  471. return (cnt);
  472. }
  473. #endif