tinystdio.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. /*
  2. File: tinyprintf.c
  3. Copyright (C) 2004 Kustaa Nyholm
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #include "tinystdio.h"
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <math.h>
  20. /*
  21. * Configuration
  22. */
  23. /* Enable long int support */
  24. #define PRINTF_LONG_SUPPORT
  25. /* Enable long long int support (implies long int support) */
  26. #define PRINTF_LONG_LONG_SUPPORT
  27. /* Enable %z (size_t) support */
  28. #define PRINTF_SIZE_T_SUPPORT
  29. /*
  30. * Configuration adjustments
  31. */
  32. #ifdef PRINTF_LONG_LONG_SUPPORT
  33. # define PRINTF_LONG_SUPPORT
  34. #endif
  35. /* __SIZEOF_<type>__ defined at least by gcc */
  36. #ifdef __SIZEOF_POINTER__
  37. # define SIZEOF_POINTER __SIZEOF_POINTER__
  38. #endif
  39. #ifdef __SIZEOF_LONG_LONG__
  40. # define SIZEOF_LONG_LONG __SIZEOF_LONG_LONG__
  41. #endif
  42. #ifdef __SIZEOF_LONG__
  43. # define SIZEOF_LONG __SIZEOF_LONG__
  44. #endif
  45. #ifdef __SIZEOF_INT__
  46. # define SIZEOF_INT __SIZEOF_INT__
  47. #endif
  48. #ifdef __GNUC__
  49. # define _TFP_GCC_NO_INLINE_ __attribute__ ((noinline))
  50. #else
  51. # define _TFP_GCC_NO_INLINE_
  52. #endif
  53. /*
  54. * Implementation
  55. */
  56. struct param {
  57. char lz:1; /**< Leading zeros */
  58. char alt:1; /**< alternate form */
  59. char uc:1; /**< Upper case (for base16 only) */
  60. char align_left:1; /**< 0 == align right (default), 1 == align left */
  61. int width; /**< field width */
  62. char sign; /**< The sign to display (if any) */
  63. unsigned int base; /**< number base (e.g.: 8, 10, 16) */
  64. char *bf; /**< Buffer to output */
  65. char prec;
  66. };
  67. #ifdef PRINTF_LONG_LONG_SUPPORT
  68. static void _TFP_GCC_NO_INLINE_ ulli2a(
  69. unsigned long long int num, struct param *p)
  70. {
  71. int n = 0;
  72. unsigned long long int d = 1;
  73. char *bf = p->bf;
  74. while (num / d >= p->base)
  75. d *= p->base;
  76. while (d != 0) {
  77. int dgt = num / d;
  78. num %= d;
  79. d /= p->base;
  80. if (n || dgt > 0 || d == 0) {
  81. *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
  82. ++n;
  83. }
  84. }
  85. *bf = 0;
  86. }
  87. static void lli2a(long long int num, struct param *p)
  88. {
  89. if (num < 0) {
  90. num = -num;
  91. p->sign = '-';
  92. }
  93. ulli2a(num, p);
  94. }
  95. #endif
  96. #ifdef PRINTF_LONG_SUPPORT
  97. static void uli2a(unsigned long int num, struct param *p)
  98. {
  99. int n = 0;
  100. unsigned long int d = 1;
  101. char *bf = p->bf;
  102. while (num / d >= p->base)
  103. d *= p->base;
  104. while (d != 0) {
  105. int dgt = num / d;
  106. num %= d;
  107. d /= p->base;
  108. if (n || dgt > 0 || d == 0) {
  109. *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
  110. ++n;
  111. }
  112. }
  113. *bf = 0;
  114. }
  115. static void li2a(long num, struct param *p)
  116. {
  117. if (num < 0) {
  118. num = -num;
  119. p->sign = '-';
  120. }
  121. uli2a(num, p);
  122. }
  123. #endif
  124. static void ui2a(unsigned int num, struct param *p)
  125. {
  126. int n = 0;
  127. unsigned int d = 1;
  128. char *bf = p->bf;
  129. while (num / d >= p->base)
  130. d *= p->base;
  131. while (d != 0) {
  132. int dgt = num / d;
  133. num %= d;
  134. d /= p->base;
  135. if (n || dgt > 0 || d == 0) {
  136. *bf++ = dgt + (dgt < 10 ? '0' : (p->uc ? 'A' : 'a') - 10);
  137. ++n;
  138. }
  139. }
  140. *bf = 0;
  141. }
  142. static void i2a(int num, struct param *p)
  143. {
  144. if (num < 0) {
  145. num = -num;
  146. p->sign = '-';
  147. }
  148. ui2a(num, p);
  149. }
  150. static int a2d(char ch)
  151. {
  152. if (ch >= '0' && ch <= '9')
  153. return ch - '0';
  154. else if (ch >= 'a' && ch <= 'f')
  155. return ch - 'a' + 10;
  156. else if (ch >= 'A' && ch <= 'F')
  157. return ch - 'A' + 10;
  158. else
  159. return -1;
  160. }
  161. static char a2u(char ch, const char **src, int base, unsigned int *nump)
  162. {
  163. const char *p = *src;
  164. unsigned int num = 0;
  165. int digit;
  166. while ((digit = a2d(ch)) >= 0) {
  167. if (digit > base)
  168. break;
  169. num = num * base + digit;
  170. ch = *p++;
  171. }
  172. *src = p;
  173. *nump = num;
  174. return ch;
  175. }
  176. void float_to_s(double a, char buffer[])
  177. {
  178. if (a < 0)
  179. {
  180. a = -a;
  181. tfp_sprintf(buffer, "-%d.%d", (int)a, (int)((a - (int)a)*1000));
  182. }
  183. else
  184. tfp_sprintf(buffer, "%d.%d", (int)a, (int)((a - (int)a)*1000));
  185. }
  186. double s_to_float(char* str)
  187. {
  188. int neg;
  189. double fvalue = 0;
  190. int pos;
  191. if (*str == '-')
  192. {
  193. neg = 1;
  194. str++;
  195. }
  196. else
  197. neg = 0;
  198. int point_flag = 0;
  199. int exp = 0;
  200. for (fvalue = 0, pos = 0; *str != 0 ; str++, pos++)
  201. {
  202. if (*str == '.')
  203. {
  204. point_flag = 1;
  205. str++;
  206. }
  207. if ('0' <= *str && *str <= '9')
  208. fvalue = fvalue*10 + (int)(*str - '0');
  209. else
  210. break;
  211. if (point_flag == 1)
  212. exp++;
  213. }
  214. if (pos == 0)
  215. return 0;
  216. for (pos = 0; pos < exp; pos++)
  217. fvalue = fvalue/10.0;
  218. return neg ? -fvalue : fvalue;
  219. }
  220. static void putchw(void *putp, putcf putf, struct param *p)
  221. {
  222. char ch;
  223. int n = p->width;
  224. char *bf = p->bf;
  225. /* Number of filling characters */
  226. while (*bf++ && n > 0)
  227. n--;
  228. if (p->sign)
  229. n--;
  230. if (p->alt && p->base == 16)
  231. n -= 2;
  232. else if (p->alt && p->base == 8)
  233. n--;
  234. /* Fill with space to align to the right, before alternate or sign */
  235. if (!p->lz && !p->align_left) {
  236. while (n-- > 0)
  237. putf(putp, ' ');
  238. }
  239. /* print sign */
  240. if (p->sign)
  241. putf(putp, p->sign);
  242. /* Alternate */
  243. if (p->alt && p->base == 16) {
  244. putf(putp, '0');
  245. putf(putp, (p->uc ? 'X' : 'x'));
  246. } else if (p->alt && p->base == 8) {
  247. putf(putp, '0');
  248. }
  249. /* Fill with zeros, after alternate or sign */
  250. if (p->lz) {
  251. while (n-- > 0)
  252. putf(putp, '0');
  253. }
  254. /* Put actual buffer */
  255. bf = p->bf;
  256. while ((ch = *bf++))
  257. putf(putp, ch);
  258. /* Fill with space to align to the left, after string */
  259. if (!p->lz && p->align_left) {
  260. while (n-- > 0)
  261. putf(putp, ' ');
  262. }
  263. }
  264. void tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
  265. {
  266. struct param p;
  267. double fval;
  268. int temp_buffer[10];
  269. int fpart;
  270. int fiter;
  271. int ffactor;
  272. int sign;
  273. #ifdef PRINTF_LONG_SUPPORT
  274. char bf[23]; /* long = 64b on some architectures */
  275. #else
  276. char bf[12]; /* int = 32b on some architectures */
  277. #endif
  278. char ch;
  279. p.bf = bf;
  280. while ((ch = *(fmt++))) {
  281. if (ch != '%') {
  282. putf(putp, ch);
  283. } else {
  284. #ifdef PRINTF_LONG_SUPPORT
  285. char lng = 0; /* 1 for long, 2 for long long */
  286. #endif
  287. /* Init parameter struct */
  288. p.lz = 0;
  289. p.alt = 0;
  290. p.width = 0;
  291. p.align_left = 0;
  292. p.sign = 0;
  293. p.prec = 2;
  294. /* Flags */
  295. while ((ch = *(fmt++))) {
  296. switch (ch) {
  297. case '-':
  298. p.align_left = 1;
  299. continue;
  300. case '0':
  301. p.lz = 1;
  302. continue;
  303. case '#':
  304. p.alt = 1;
  305. continue;
  306. case '+':
  307. p.sign = 1;
  308. continue;
  309. default:
  310. break;
  311. }
  312. break;
  313. }
  314. /* Width */
  315. if (ch >= '0' && ch <= '9') {
  316. ch = a2u(ch, &fmt, 10, &(p.width));
  317. }
  318. /* We accept 'x.y' format but don't support it completely:
  319. * we ignore the 'y' digit => this ignores 0-fill
  320. * size and makes it == width (ie. 'x') */
  321. if (ch == '.') {
  322. //p.lz = 1; /* zero-padding */
  323. /* ignore actual 0-fill size: */
  324. ch = *(fmt++);
  325. if (ch >= '0' && ch <= '9')
  326. p.prec = ch - '0';
  327. do
  328. {
  329. ch = *(fmt++);
  330. } while (ch >= '0' && ch <= '9');
  331. }
  332. #ifdef PRINTF_SIZE_T_SUPPORT
  333. # ifdef PRINTF_LONG_SUPPORT
  334. if (ch == 'z') {
  335. ch = *(fmt++);
  336. if (sizeof(size_t) == sizeof(unsigned long int))
  337. lng = 1;
  338. # ifdef PRINTF_LONG_LONG_SUPPORT
  339. else if (sizeof(size_t) == sizeof(unsigned long long int))
  340. lng = 2;
  341. # endif
  342. } else
  343. # endif
  344. #endif
  345. #ifdef PRINTF_LONG_SUPPORT
  346. if (ch == 'l') {
  347. ch = *(fmt++);
  348. lng = 1;
  349. #ifdef PRINTF_LONG_LONG_SUPPORT
  350. if (ch == 'l') {
  351. ch = *(fmt++);
  352. lng = 2;
  353. }
  354. #endif
  355. }
  356. #endif
  357. switch (ch) {
  358. case 0:
  359. goto abort;
  360. case 'u':
  361. p.base = 10;
  362. #ifdef PRINTF_LONG_SUPPORT
  363. #ifdef PRINTF_LONG_LONG_SUPPORT
  364. if (2 == lng)
  365. ulli2a(va_arg(va, unsigned long long int), &p);
  366. else
  367. #endif
  368. if (1 == lng)
  369. uli2a(va_arg(va, unsigned long int), &p);
  370. else
  371. #endif
  372. ui2a(va_arg(va, unsigned int), &p);
  373. putchw(putp, putf, &p);
  374. break;
  375. case 'd':
  376. case 'i':
  377. p.base = 10;
  378. #ifdef PRINTF_LONG_SUPPORT
  379. #ifdef PRINTF_LONG_LONG_SUPPORT
  380. if (2 == lng)
  381. lli2a(va_arg(va, long long int), &p);
  382. else
  383. #endif
  384. if (1 == lng)
  385. li2a(va_arg(va, long int), &p);
  386. else
  387. #endif
  388. i2a(va_arg(va, int), &p);
  389. putchw(putp, putf, &p);
  390. break;
  391. #ifdef SIZEOF_POINTER
  392. case 'p':
  393. p.alt = 1;
  394. # if defined(SIZEOF_INT) && SIZEOF_POINTER <= SIZEOF_INT
  395. lng = 0;
  396. # elif defined(SIZEOF_LONG) && SIZEOF_POINTER <= SIZEOF_LONG
  397. lng = 1;
  398. # elif defined(SIZEOF_LONG_LONG) && SIZEOF_POINTER <= SIZEOF_LONG_LONG
  399. lng = 2;
  400. # endif
  401. #endif
  402. case 'x':
  403. case 'X':
  404. p.base = 16;
  405. p.uc = (ch == 'X')?1:0;
  406. #ifdef PRINTF_LONG_SUPPORT
  407. #ifdef PRINTF_LONG_LONG_SUPPORT
  408. if (2 == lng)
  409. ulli2a(va_arg(va, unsigned long long int), &p);
  410. else
  411. #endif
  412. if (1 == lng)
  413. uli2a(va_arg(va, unsigned long int), &p);
  414. else
  415. #endif
  416. ui2a(va_arg(va, unsigned int), &p);
  417. putchw(putp, putf, &p);
  418. break;
  419. case 'o':
  420. p.base = 8;
  421. ui2a(va_arg(va, unsigned int), &p);
  422. putchw(putp, putf, &p);
  423. break;
  424. case 'c':
  425. putf(putp, (char)(va_arg(va, int)));
  426. break;
  427. case 's':
  428. p.bf = va_arg(va, char *);
  429. putchw(putp, putf, &p);
  430. p.bf = bf;
  431. break;
  432. case '%':
  433. putf(putp, ch);
  434. break;
  435. case 'f':
  436. case 'F':
  437. fval = va_arg(va, double);
  438. sign = 0;
  439. if (fval < 0)
  440. {
  441. sign = 1;
  442. p.width--;
  443. fval = - fval;
  444. }
  445. else if (p.sign) {
  446. sign = 2;
  447. p.width--;
  448. }
  449. fpart = (int)fval;
  450. fiter = 0;
  451. while (fpart != 0)
  452. {
  453. temp_buffer[fiter++] = fpart % 10;
  454. fpart = fpart / 10;
  455. }
  456. fiter--;
  457. if (fiter == -1)
  458. p.width--;
  459. /* Leading zeros */
  460. if (p.lz) {
  461. if (sign == 1)
  462. putf(putp, '-');
  463. else if (sign == 2)
  464. putf(putp, '+');
  465. while (p.width-- > p.prec + fiter + 2)
  466. {
  467. putf(putp, '0');
  468. }
  469. }
  470. else
  471. {
  472. while (p.width-- > p.prec + fiter + 2)
  473. {
  474. putf(putp, ' ');
  475. }
  476. if (sign == 1)
  477. putf(putp, '-');
  478. else if (sign == 2)
  479. putf(putp, '+');
  480. }
  481. if (fiter == -1)
  482. putf(putp, '0');
  483. while (fiter > -1)
  484. {
  485. putf(putp, '0' + (temp_buffer[fiter--]));
  486. }
  487. putf(putp, '.');
  488. ffactor = 1;
  489. while (p.prec-- > 0)
  490. {
  491. ffactor *= 10;
  492. fpart = (int)((fval - (int)fval)*ffactor);
  493. if (fpart == 0)
  494. putf(putp, '0');
  495. }
  496. fiter = 0;
  497. while (fpart != 0)
  498. {
  499. temp_buffer[fiter++] = fpart % 10;
  500. fpart = fpart / 10;
  501. }
  502. fiter--;
  503. while (fiter > -1)
  504. {
  505. putf(putp, '0' + (temp_buffer[fiter--]));
  506. }
  507. break;
  508. default:
  509. break;
  510. }
  511. }
  512. }
  513. abort:;
  514. }
  515. #if TINYPRINTF_DEFINE_TFP_PRINTF
  516. static putcf stdout_putf;
  517. static void *stdout_putp;
  518. void init_printf(void *putp, putcf putf)
  519. {
  520. stdout_putf = putf;
  521. stdout_putp = putp;
  522. }
  523. void tfp_printf(char *fmt, ...)
  524. {
  525. va_list va;
  526. va_start(va, fmt);
  527. tfp_format(stdout_putp, stdout_putf, fmt, va);
  528. va_end(va);
  529. }
  530. #endif
  531. #if TINYPRINTF_DEFINE_TFP_SPRINTF
  532. struct _vsnprintf_putcf_data
  533. {
  534. size_t dest_capacity;
  535. char *dest;
  536. size_t num_chars;
  537. };
  538. static void _vsnprintf_putcf(void *p, char c)
  539. {
  540. struct _vsnprintf_putcf_data *data = (struct _vsnprintf_putcf_data*)p;
  541. if (data->num_chars < data->dest_capacity)
  542. data->dest[data->num_chars] = c;
  543. data->num_chars ++;
  544. }
  545. int tfp_vsnprintf(char *str, size_t size, const char *format, va_list ap)
  546. {
  547. struct _vsnprintf_putcf_data data;
  548. if (size < 1)
  549. return 0;
  550. data.dest = str;
  551. data.dest_capacity = size-1;
  552. data.num_chars = 0;
  553. tfp_format(&data, _vsnprintf_putcf, format, ap);
  554. if (data.num_chars < data.dest_capacity)
  555. data.dest[data.num_chars] = '\0';
  556. else
  557. data.dest[data.dest_capacity] = '\0';
  558. return data.num_chars;
  559. }
  560. int tfp_snprintf(char *str, size_t size, const char *format, ...)
  561. {
  562. va_list ap;
  563. int retval;
  564. va_start(ap, format);
  565. retval = tfp_vsnprintf(str, size, format, ap);
  566. va_end(ap);
  567. return retval;
  568. }
  569. struct _vsprintf_putcf_data
  570. {
  571. char *dest;
  572. size_t num_chars;
  573. };
  574. static void _vsprintf_putcf(void *p, char c)
  575. {
  576. struct _vsprintf_putcf_data *data = (struct _vsprintf_putcf_data*)p;
  577. data->dest[data->num_chars++] = c;
  578. }
  579. int tfp_vsprintf(char *str, const char *format, va_list ap)
  580. {
  581. struct _vsprintf_putcf_data data;
  582. data.dest = str;
  583. data.num_chars = 0;
  584. tfp_format(&data, _vsprintf_putcf, format, ap);
  585. data.dest[data.num_chars] = '\0';
  586. return data.num_chars;
  587. }
  588. int tfp_sprintf(char *str, const char *format, ...)
  589. {
  590. va_list ap;
  591. int retval;
  592. va_start(ap, format);
  593. retval = tfp_vsprintf(str, format, ap);
  594. va_end(ap);
  595. return retval;
  596. }
  597. int isdigit (char c) {
  598. if ((c>='0') && (c<='9')) return 1;
  599. return 0;
  600. }
  601. int tfp_vsscanf(const char* str, const char* format, ...)
  602. {
  603. va_list ap;
  604. int value, tmp, width;
  605. float fvalue;
  606. double Fvalue;
  607. int count = 0;
  608. int pos;
  609. char neg, fmt_code;
  610. const char* pf;
  611. const char *tc;
  612. char tmp_str[20];
  613. va_start(ap, format);
  614. for (pf = format, count = 0; *format != 0 && *str != 0; format++, str++)
  615. {
  616. while (*format == ' ' && *format != 0)
  617. format++;
  618. if (*format == 0)
  619. break;
  620. while (*str == ' ' && *str != 0)
  621. str++;
  622. if (*str == 0)
  623. break;
  624. if (*format == '%')
  625. {
  626. format++;
  627. if (*format == 'n')
  628. {
  629. if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
  630. {
  631. fmt_code = 'x';
  632. str += 2;
  633. }
  634. else
  635. if (str[0] == 'b')
  636. {
  637. fmt_code = 'b';
  638. str++;
  639. }
  640. else
  641. fmt_code = 'd';
  642. }
  643. else if (*format >= '1' && *format <= '9') {
  644. for (tc = format; isdigit (*format); format++);
  645. strncpy(tmp_str, tc, format - tc);
  646. tmp_str[format - tc] = '\0';
  647. width = atoi(tmp_str);
  648. fmt_code = *format;
  649. }
  650. else
  651. fmt_code = *format;
  652. switch (fmt_code)
  653. {
  654. case 'x':
  655. case 'X':
  656. for (value = 0, pos = 0; *str != 0; str++, pos++)
  657. {
  658. if ('0' <= *str && *str <= '9')
  659. tmp = *str - '0';
  660. else
  661. if ('a' <= *str && *str <= 'f')
  662. tmp = *str - 'a' + 10;
  663. else
  664. if ('A' <= *str && *str <= 'F')
  665. tmp = *str - 'A' + 10;
  666. else
  667. break;
  668. value *= 16;
  669. value += tmp;
  670. }
  671. if (pos == 0)
  672. return count;
  673. *(va_arg(ap, int*)) = value;
  674. count++;
  675. break;
  676. case 'b':
  677. for (value = 0, pos = 0; *str != 0; str++, pos++)
  678. {
  679. if (*str != '0' && *str != '1')
  680. break;
  681. value *= 2;
  682. value += *str - '0';
  683. }
  684. if (pos == 0)
  685. return count;
  686. *(va_arg(ap, int*)) = value;
  687. count++;
  688. break;
  689. case 'd':
  690. if (*str == '-')
  691. {
  692. neg = 1;
  693. str++;
  694. }
  695. else
  696. neg = 0;
  697. if (!width) {
  698. for (value = 0, pos = 0; *str != 0; str++, pos++)
  699. {
  700. if ('0' <= *str && *str <= '9')
  701. value = value*10 + (int)(*str - '0');
  702. else{
  703. break;
  704. }
  705. }
  706. }
  707. else{
  708. for (value = 0, pos = 0; pos != width; str++, pos++)
  709. {
  710. if ('0' <= *str && *str <= '9')
  711. value = value*10 + (int)(*str - '0');
  712. else{
  713. break;
  714. }
  715. }
  716. str--;
  717. }
  718. if (pos == 0)
  719. return count;
  720. *(va_arg(ap, int*)) = neg ? -value : value;
  721. count++;
  722. break;
  723. case 'f':
  724. if (*str == '-')
  725. {
  726. neg = 1;
  727. str++;
  728. }
  729. else
  730. neg = 0;
  731. int point_flag = 0;
  732. int exp = 0;
  733. for (fvalue = 0, pos = 0; *str != 0 ; str++, pos++)
  734. {
  735. if (*str == '.')
  736. {
  737. point_flag = 1;
  738. str++;
  739. }
  740. if ('0' <= *str && *str <= '9')
  741. fvalue = fvalue*10 + (int)(*str - '0');
  742. else
  743. break;
  744. if (point_flag == 1)
  745. exp++;
  746. }
  747. if (pos == 0)
  748. return count;
  749. for (pos = 0; pos < exp; pos++)
  750. fvalue = fvalue/10.0;
  751. *(va_arg(ap, float*)) = neg ? -fvalue : fvalue;
  752. count++;
  753. break;
  754. case 'F':
  755. if (*str == '-')
  756. {
  757. neg = 1;
  758. str++;
  759. }
  760. else
  761. neg = 0;
  762. int Fpoint_flag = 0;
  763. int Fexp = 0;
  764. for (Fvalue = 0, pos = 0; *str != 0 ; str++, pos++)
  765. {
  766. if (*str == '.')
  767. {
  768. Fpoint_flag = 1;
  769. str++;
  770. }
  771. if ('0' <= *str && *str <= '9')
  772. Fvalue = Fvalue*10 + (int)(*str - '0');
  773. else
  774. break;
  775. if (Fpoint_flag == 1)
  776. Fexp++;
  777. }
  778. if (pos == 0)
  779. return count;
  780. for (pos = 0; pos < Fexp; pos++)
  781. Fvalue = Fvalue/10.0;
  782. *(va_arg(ap, double*)) = neg ? -Fvalue : Fvalue;
  783. count++;
  784. break;
  785. case 'c':
  786. *(va_arg(ap, char*)) = *str;
  787. count++;
  788. break;
  789. case 's':
  790. pos = 0;
  791. char* tab = va_arg(ap, char**);
  792. while (*str != ' ' && *str != 0)
  793. *(tab++) = *str++;
  794. *tab = 0;
  795. count++;
  796. break;
  797. default:
  798. return count;
  799. }
  800. }
  801. else
  802. {
  803. if (*format != *str)
  804. break;
  805. }
  806. }
  807. va_end(ap);
  808. return count;
  809. }
  810. #endif