tinystdio.c 23 KB

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