PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/sw/lib/printf.c

https://github.com/fjullien/orpsocv2
C | 746 lines | 423 code | 84 blank | 239 comment | 81 complexity | 8fd6342c1caa8dc5934cb916f6a5cfc3 MD5 | raw file
  1. // Ripped out of latest ecos build from
  2. //http://sources-redhat.mirrors.airband.net/ecos/releases/ecos-3.0b1/ecos-3.0beta1.i386linux.tar.bz2
  3. // File: ecos-3.0b1/packages/language/c/libc/stdio/v3_0b1/src/output/vfnprintf.cxx
  4. // Hacked to pieces so it would work with OpenRISC compiler, not using libc
  5. //===========================================================================
  6. //
  7. // vfnprintf.c
  8. //
  9. // I/O routines for vfnprintf() for use with ANSI C library
  10. //
  11. //===========================================================================
  12. // ####ECOSGPLCOPYRIGHTBEGIN####
  13. // -------------------------------------------
  14. // This file is part of eCos, the Embedded Configurable Operating System.
  15. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  16. //
  17. // eCos is free software; you can redistribute it and/or modify it under
  18. // the terms of the GNU General Public License as published by the Free
  19. // Software Foundation; either version 2 or (at your option) any later
  20. // version.
  21. //
  22. // eCos is distributed in the hope that it will be useful, but WITHOUT
  23. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  24. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  25. // for more details.
  26. //
  27. // You should have received a copy of the GNU General Public License
  28. // along with eCos; if not, write to the Free Software Foundation, Inc.,
  29. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  30. //
  31. // As a special exception, if other files instantiate templates or use
  32. // macros or inline functions from this file, or you compile this file
  33. // and link it with other works to produce a work based on this file,
  34. // this file does not by itself cause the resulting work to be covered by
  35. // the GNU General Public License. However the source code for this file
  36. // must still be made available in accordance with section (3) of the GNU
  37. // General Public License v2.
  38. //
  39. // This exception does not invalidate any other reasons why a work based
  40. // on this file might be covered by the GNU General Public License.
  41. // -------------------------------------------
  42. // ####ECOSGPLCOPYRIGHTEND####
  43. //===========================================================================
  44. //#####DESCRIPTIONBEGIN####
  45. //
  46. // Author(s): jlarmour
  47. // Contributors:
  48. // Date: 2000-04-20
  49. // Purpose:
  50. // Description:
  51. // Usage:
  52. //
  53. //####DESCRIPTIONEND####
  54. //
  55. //===========================================================================
  56. //
  57. // This code is based on original code with the following copyright:
  58. //
  59. /*-
  60. * Copyright (c) 1990 The Regents of the University of California.
  61. * All rights reserved.
  62. *
  63. * This code is derived from software contributed to Berkeley by
  64. * Chris Torek.
  65. *
  66. * Redistribution and use in source and binary forms, with or without
  67. * modification, are permitted provided that the following conditions
  68. * are met:
  69. * 1. Redistributions of source code must retain the above copyright
  70. * notice, this list of conditions and the following disclaimer.
  71. * 2. Redistributions in binary form must reproduce the above copyright
  72. * notice, this list of conditions and the following disclaimer in the
  73. * documentation and/or other materials provided with the distribution.
  74. * 3. Neither the name of the University nor the names of its contributors
  75. * may be used to endorse or promote products derived from this software
  76. * without specific prior written permission.
  77. *
  78. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  79. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  80. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  81. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  82. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  83. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  84. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  85. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  86. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  87. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  88. * SUCH DAMAGE.
  89. */
  90. // CONFIGURATION
  91. //#include <pkgconf/libc_stdio.h> // Configuration header
  92. //#include <pkgconf/libc_i18n.h> // Configuration header for mb support
  93. // INCLUDES
  94. //jb#include <stdarg.h> // Variable argument definitions
  95. //jb#include <string.h> // memchr() and strlen() functions
  96. //#include <stdio.h> // Standard header for all stdio files
  97. //#include <cyg/libc/stdio/stream.hxx> // C library streams
  98. //#include "vfnprintf.h"
  99. //jb#include <stddef.h> // for null, va_lsit
  100. #include "lib-utils.h" // has all these required basic c functions now
  101. //#include <cyg/infra/cyg_type.h> // Common type definitions and support
  102. #define CYG_MACRO_START do {
  103. #define CYG_MACRO_END } while (0)
  104. #define CYG_EMPTY_STATEMENT CYG_MACRO_START CYG_MACRO_END
  105. #define CYG_UNUSED_PARAM( _type_, _name_ ) CYG_MACRO_START \
  106. _type_ __tmp1 = (_name_); \
  107. _type_ __tmp2 = __tmp1; \
  108. __tmp1 = __tmp2; \
  109. CYG_MACRO_END
  110. # define BUF 40
  111. /*
  112. * Actual printf innards.
  113. *
  114. * This code is large and complicated...
  115. */
  116. /*
  117. * Macros for converting digits to letters and vice versa
  118. */
  119. #define to_digit(c) ((c) - '0')
  120. #define is_digit(c) ((unsigned)to_digit(c) <= 9)
  121. #define to_char(n) ((n) + '0')
  122. /*
  123. * Flags used during conversion.
  124. */
  125. #define ALT 0x001 /* alternate form */
  126. #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
  127. #define LADJUST 0x004 /* left adjustment */
  128. #define LONGDBL 0x008 /* long double; unimplemented */
  129. #define LONGINT 0x010 /* long integer */
  130. #define QUADINT 0x020 /* quad integer */
  131. #define SHORTINT 0x040 /* short integer */
  132. #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
  133. #define FPT 0x100 /* Floating point number */
  134. #define SIZET 0x200 /* size_t */
  135. // Function which prints back to the buffer, ptr, len bytes
  136. // returns 1 if it should finish up, otherwise 0 to continue
  137. int
  138. print_back_to_string(char * ptr, int len, size_t * n, int * ret, char ** stream)
  139. {
  140. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  141. do {
  142. int length = MIN( (int) len, *n - *ret - 1);
  143. memcpy(*stream + *ret, ptr, length);
  144. if (length < (int)len) {
  145. *ret += length;
  146. return 1; // finish up
  147. }
  148. } while(0);
  149. return 0;
  150. }
  151. //externC int
  152. int
  153. //vfnprintf ( FILE *stream, size_t n, const char *format, va_list arg) __THROW
  154. vfnprintf ( char *stream, size_t n, const char *format, va_list arg)
  155. {
  156. char *fmt; /* format string */
  157. int ch; /* character from fmt */
  158. int x, y; /* handy integers (short term usage) */
  159. char *cp; /* handy char pointer (short term usage) */
  160. int flags; /* flags as above */
  161. int ret; /* return value accumulator */
  162. int width; /* width from format (%8d), or 0 */
  163. int prec; /* precision from format (%.3d), or -1 */
  164. char sign; /* sign prefix (' ', '+', '-', or \0) */
  165. wchar_t wc;
  166. #define quad_t long long
  167. #define u_quad_t unsigned long long
  168. u_quad_t _uquad; /* integer arguments %[diouxX] */
  169. enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
  170. int dprec; /* a copy of prec if [diouxX], 0 otherwise */
  171. int fieldsz; /* field size expanded by sign, etc */
  172. int realsz; /* field size expanded by dprec */
  173. int size; /* size of converted field or string */
  174. char *xdigs; /* digits for [xX] conversion */
  175. #define NIOV 8
  176. char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
  177. char ox[2]; /* space for 0x hex-prefix */
  178. /*
  179. * Choose PADSIZE to trade efficiency vs. size. If larger printf
  180. * fields occur frequently, increase PADSIZE and make the initialisers
  181. * below longer.
  182. */
  183. #define PADSIZE 16 /* pad chunk size */
  184. static char blanks[PADSIZE] =
  185. {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
  186. static char zeroes[PADSIZE] =
  187. {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
  188. /*
  189. * BEWARE, these `goto error' on error, and PAD uses `n'.
  190. */
  191. // We'll copy len bytes from (char*) ptr, into the output stream
  192. // making sure we don't go over the end, so calculate length to be
  193. // either the whole length we've been passed, or the whole length
  194. // that is possible to write
  195. // We finish if it was not possible to write the entire variable
  196. // into the buffer, ie we had to write all we could, not all we
  197. // wanted to.
  198. /*
  199. #define PRINT(ptr, len) \
  200. CYG_MACRO_START \
  201. int length = MIN( (int) len, n - ret - 1); \
  202. char* begin_stream_write = stream; \
  203. stream = memcpy(stream, ptr, length); \
  204. length = (unsigned long) stream - (unsigned long) begin_stream_write; \
  205. if (length < (int)len) { \
  206. ret += length; \
  207. goto done; \
  208. } \
  209. CYG_MACRO_END
  210. */
  211. //PRINT(with, PADSIZE); \
  212. //PRINT(with, x); \
  213. #define PAD(howmany, with) \
  214. CYG_MACRO_START \
  215. if ((x = (howmany)) > 0) { \
  216. while (x > PADSIZE) { \
  217. if (print_back_to_string(with, PADSIZE, &n, &ret, &stream)) goto done; \
  218. x -= PADSIZE; \
  219. } \
  220. if (print_back_to_string(with, x, &n, &ret, &stream))goto done; \
  221. } \
  222. CYG_MACRO_END
  223. /*
  224. * To extend shorts properly, we need both signed and unsigned
  225. * argument extraction methods.
  226. */
  227. #define SARG() \
  228. (flags&QUADINT ? va_arg(arg, long long) : \
  229. flags&LONGINT ? va_arg(arg, long) : \
  230. flags&SHORTINT ? (long)(short)va_arg(arg, int) : \
  231. flags&SIZET ? (long)va_arg(arg, size_t) : \
  232. (long)va_arg(arg, int))
  233. #define UARG() \
  234. (flags&QUADINT ? va_arg(arg, unsigned long long) : \
  235. flags&LONGINT ? va_arg(arg, unsigned long) : \
  236. flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(arg, int) : \
  237. flags&SIZET ? va_arg(arg, size_t) : \
  238. (unsigned long)va_arg(arg, unsigned int))
  239. xdigs = (char *) NULL; // stop compiler whinging
  240. fmt = (char *)format;
  241. ret = 0;
  242. /*
  243. * Scan the format for conversions (`%' character).
  244. */
  245. for (;;) {
  246. cp = (char *)fmt; // char pointer - set to where we begin looking from
  247. while ((x = ((wc = *fmt) != 0))) { // While, wc=next char and x is one while there's still chars left
  248. fmt += x; // increment the pointer to the char
  249. if (wc == '%') { // check if it's the beginning of
  250. fmt--; // Decrement the char pointer, actually
  251. break;
  252. }
  253. }
  254. if ((y = fmt - cp) != 0) { // y is length of string to copy out just now
  255. //PRINT(cp, y); // Copy macro
  256. if(print_back_to_string(cp, y, &n, &ret, &stream)) goto done; // Copy macro
  257. ret += y; // increment return chars
  258. }
  259. if ((x <= 0) || (ret >= (int)n)) // @@@ this check with n isn't good enough
  260. goto done;
  261. fmt++; /* skip over '%' */
  262. flags = 0;
  263. dprec = 0;
  264. width = 0;
  265. prec = -1;
  266. sign = '\0';
  267. rflag: ch = *fmt++;
  268. reswitch: switch (ch) {
  269. case ' ':
  270. /*
  271. * ``If the space and + flags both appear, the space
  272. * flag will be ignored.''
  273. * -- ANSI X3J11
  274. */
  275. if (!sign)
  276. sign = ' ';
  277. goto rflag;
  278. case '#':
  279. flags |= ALT;
  280. goto rflag;
  281. case '*':
  282. /*
  283. * ``A negative field width argument is taken as a
  284. * - flag followed by a positive field width.''
  285. * -- ANSI X3J11
  286. * They don't exclude field widths read from args.
  287. */
  288. if ((width = va_arg(arg, int)) >= 0)
  289. goto rflag;
  290. width = -width;
  291. /* FALLTHROUGH */
  292. case '-':
  293. flags |= LADJUST;
  294. goto rflag;
  295. case '+':
  296. sign = '+';
  297. goto rflag;
  298. case '.':
  299. if ((ch = *fmt++) == '*') {
  300. x = va_arg(arg, int);
  301. prec = x < 0 ? -1 : x;
  302. goto rflag;
  303. }
  304. x = 0;
  305. while (is_digit(ch)) {
  306. x = 10 * x + to_digit(ch);
  307. ch = *fmt++;
  308. }
  309. prec = x < 0 ? -1 : x;
  310. goto reswitch;
  311. case '0':
  312. /*
  313. * ``Note that 0 is taken as a flag, not as the
  314. * beginning of a field width.''
  315. * -- ANSI X3J11
  316. */
  317. flags |= ZEROPAD;
  318. goto rflag;
  319. case '1': case '2': case '3': case '4':
  320. case '5': case '6': case '7': case '8': case '9':
  321. x = 0;
  322. do {
  323. x = 10 * x + to_digit(ch);
  324. ch = *fmt++;
  325. } while (is_digit(ch));
  326. width = x;
  327. goto reswitch;
  328. case 'h':
  329. flags |= SHORTINT;
  330. goto rflag;
  331. case 'l':
  332. if (*fmt == 'l') {
  333. fmt++;
  334. flags |= QUADINT;
  335. } else {
  336. flags |= LONGINT;
  337. }
  338. goto rflag;
  339. case 'q':
  340. flags |= QUADINT;
  341. goto rflag;
  342. case 'c':
  343. *(cp = buf) = va_arg(arg, int);
  344. size = 1;
  345. sign = '\0';
  346. break;
  347. case 'D':
  348. flags |= LONGINT;
  349. /*FALLTHROUGH*/
  350. case 'd':
  351. case 'i':
  352. _uquad = SARG();
  353. #ifndef _NO_LONGLONG
  354. if ((quad_t)_uquad < 0)
  355. #else
  356. if ((long) _uquad < 0)
  357. #endif
  358. {
  359. _uquad = -_uquad;
  360. sign = '-';
  361. }
  362. base = DEC;
  363. goto number;
  364. case 'e':
  365. case 'E':
  366. case 'f':
  367. case 'g':
  368. case 'G':
  369. // Output nothing at all
  370. (void) va_arg(arg, double); // take off arg anyway
  371. cp = "";
  372. size = 0;
  373. sign = '\0';
  374. break;
  375. case 'n':
  376. #ifndef _NO_LONGLONG
  377. if (flags & QUADINT)
  378. *va_arg(arg, quad_t *) = ret;
  379. else
  380. #endif
  381. if (flags & LONGINT)
  382. *va_arg(arg, long *) = ret;
  383. else if (flags & SHORTINT)
  384. *va_arg(arg, short *) = ret;
  385. else if (flags & SIZET)
  386. *va_arg(arg, size_t *) = ret;
  387. else
  388. *va_arg(arg, int *) = ret;
  389. continue; /* no output */
  390. case 'O':
  391. flags |= LONGINT;
  392. /*FALLTHROUGH*/
  393. case 'o':
  394. _uquad = UARG();
  395. base = OCT;
  396. goto nosign;
  397. case 'p':
  398. /*
  399. * ``The argument shall be a pointer to void. The
  400. * value of the pointer is converted to a sequence
  401. * of printable characters, in an implementation-
  402. * defined manner.''
  403. * -- ANSI X3J11
  404. */
  405. /* NOSTRICT */
  406. _uquad = (unsigned long)va_arg(arg, void *);
  407. base = HEX;
  408. xdigs = (char *)"0123456789abcdef";
  409. flags |= HEXPREFIX;
  410. ch = 'x';
  411. goto nosign;
  412. case 's':
  413. if ((cp = va_arg(arg, char *)) == NULL)
  414. cp = (char *)"(null)";
  415. if (prec >= 0) {
  416. /*
  417. * can't use strlen; can only look for the
  418. * NUL in the first `prec' characters, and
  419. * strlen() will go further.
  420. */
  421. char *p = (char *)memchr(cp, 0, prec);
  422. if (p != NULL) {
  423. size = p - cp;
  424. if (size > prec)
  425. size = prec;
  426. } else
  427. size = prec;
  428. } else
  429. size = strlen(cp);
  430. sign = '\0';
  431. break;
  432. case 'U':
  433. flags |= LONGINT;
  434. /*FALLTHROUGH*/
  435. case 'u':
  436. _uquad = UARG();
  437. base = DEC;
  438. goto nosign;
  439. case 'X':
  440. xdigs = (char *)"0123456789ABCDEF";
  441. goto hex;
  442. case 'x':
  443. xdigs = (char *)"0123456789abcdef";
  444. hex: _uquad = UARG();
  445. base = HEX;
  446. /* leading 0x/X only if non-zero */
  447. if (flags & ALT && _uquad != 0)
  448. flags |= HEXPREFIX;
  449. /* unsigned conversions */
  450. nosign: sign = '\0';
  451. /*
  452. * ``... diouXx conversions ... if a precision is
  453. * specified, the 0 flag will be ignored.''
  454. * -- ANSI X3J11
  455. */
  456. number: if ((dprec = prec) >= 0)
  457. flags &= ~ZEROPAD;
  458. /*
  459. * ``The result of converting a zero value with an
  460. * explicit precision of zero is no characters.''
  461. * -- ANSI X3J11
  462. */
  463. cp = buf + BUF;
  464. if (_uquad != 0 || prec != 0) {
  465. /*
  466. * Unsigned mod is hard, and unsigned mod
  467. * by a constant is easier than that by
  468. * a variable; hence this switch.
  469. */
  470. switch (base) {
  471. case OCT:
  472. do {
  473. *--cp = to_char(_uquad & 7);
  474. _uquad >>= 3;
  475. } while (_uquad);
  476. /* handle octal leading 0 */
  477. if (flags & ALT && *cp != '0')
  478. *--cp = '0';
  479. break;
  480. case DEC:
  481. if (!(flags & QUADINT)) {
  482. /* many numbers are 1 digit */
  483. unsigned long v = (unsigned long)_uquad;
  484. while (v >= 10) {
  485. /* The following is usually faster than using a modulo */
  486. unsigned long next = v / 10;
  487. *--cp = to_char(v - (next * 10));
  488. v = next;
  489. }
  490. *--cp = to_char(v);
  491. }
  492. else {
  493. while (_uquad >= 10) {
  494. /* The following is usually faster than using a modulo */
  495. u_quad_t next = _uquad / 10;
  496. *--cp = to_char(_uquad - (next * 10));
  497. _uquad = next;
  498. }
  499. *--cp = to_char(_uquad);
  500. }
  501. break;
  502. case HEX:
  503. do {
  504. *--cp = xdigs[_uquad & 15];
  505. _uquad >>= 4;
  506. } while (_uquad);
  507. break;
  508. default:
  509. cp = (char *)"bug in vfprintf: bad base";
  510. size = strlen(cp);
  511. goto skipsize;
  512. }
  513. }
  514. size = buf + BUF - cp;
  515. skipsize:
  516. break;
  517. case 'z':
  518. flags |= SIZET;
  519. goto rflag;
  520. default: /* "%?" prints ?, unless ? is NUL */
  521. if (ch == '\0')
  522. goto done;
  523. /* pretend it was %c with argument ch */
  524. cp = buf;
  525. *cp = ch;
  526. size = 1;
  527. sign = '\0';
  528. break;
  529. }
  530. /*
  531. * All reasonable formats wind up here. At this point, `cp'
  532. * points to a string which (if not flags&LADJUST) should be
  533. * padded out to `width' places. If flags&ZEROPAD, it should
  534. * first be prefixed by any sign or other prefix; otherwise,
  535. * it should be blank padded before the prefix is emitted.
  536. * After any left-hand padding and prefixing, emit zeroes
  537. * required by a decimal [diouxX] precision, then print the
  538. * string proper, then emit zeroes required by any leftover
  539. * floating precision; finally, if LADJUST, pad with blanks.
  540. *
  541. * Compute actual size, so we know how much to pad.
  542. * fieldsz excludes decimal prec; realsz includes it.
  543. */
  544. #ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
  545. fieldsz = size + fpprec;
  546. #else
  547. fieldsz = size;
  548. #endif
  549. if (sign)
  550. fieldsz++;
  551. else if (flags & HEXPREFIX)
  552. fieldsz+= 2;
  553. realsz = dprec > fieldsz ? dprec : fieldsz;
  554. /* right-adjusting blank padding */
  555. if ((flags & (LADJUST|ZEROPAD)) == 0) {
  556. if (width - realsz > 0) {
  557. PAD(width - realsz, blanks);
  558. ret += width - realsz;
  559. }
  560. }
  561. /* prefix */
  562. if (sign) {
  563. //PRINT(&sign, 1);
  564. if(print_back_to_string(&sign, 1, &n, &ret, &stream))goto done;
  565. ret++;
  566. } else if (flags & HEXPREFIX) {
  567. ox[0] = '0';
  568. ox[1] = ch;
  569. //PRINT(ox, 2);
  570. if(print_back_to_string(ox, 2, &n, &ret, &stream))goto done;
  571. ret += 2;
  572. }
  573. /* right-adjusting zero padding */
  574. if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
  575. if (width - realsz > 0) {
  576. PAD(width - realsz, zeroes);
  577. ret += width - realsz;
  578. }
  579. }
  580. if (dprec - fieldsz > 0) {
  581. /* leading zeroes from decimal precision */
  582. PAD(dprec - fieldsz, zeroes);
  583. ret += dprec - fieldsz;
  584. }
  585. /* the string or number proper */
  586. //PRINT(cp, size);
  587. if(print_back_to_string(cp,size, &n, &ret, &stream))goto done;
  588. ret += size;
  589. #ifdef CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT
  590. /* trailing f.p. zeroes */
  591. PAD(fpprec, zeroes);
  592. ret += fpprec;
  593. #endif
  594. /* left-adjusting padding (always blank) */
  595. if (flags & LADJUST) {
  596. if (width - realsz > 0) {
  597. PAD(width - realsz, blanks);
  598. ret += width - realsz;
  599. }
  600. }
  601. }
  602. done:
  603. error:
  604. return ret;// remove this error stuff (((Cyg_OutputStream *) stream)->get_error() ? EOF : ret);
  605. /* NOTREACHED */
  606. }
  607. int
  608. sprintf(char* str, const char *fmt, ...)
  609. {
  610. va_list args;
  611. va_start(args, fmt);
  612. return vfnprintf(str, 1024, fmt, args);
  613. }
  614. #include "printf.h"
  615. #include "cpu-utils.h"
  616. // Actual printf function we call, with static buffer of 512 bytes
  617. char PRINTFBUFFER[PRINTFBUFFER_SIZE]; // Declare a global printf buffer
  618. int
  619. printf_to_sim(const char *fmt, ...)
  620. {
  621. va_list args;
  622. va_start(args, fmt);
  623. int str_l = vfnprintf(PRINTFBUFFER, PRINTFBUFFER_SIZE, fmt, args);
  624. if (!str_l) return -1; // no length string - just return
  625. char c;
  626. int i=0;
  627. while(i<str_l) sim_putc(PRINTFBUFFER[i++]);
  628. va_end(args);
  629. return str_l;
  630. }
  631. int
  632. puts_to_sim(const char *str)
  633. {
  634. return printf_to_sim("%s\n", str);
  635. }
  636. // Calls to the UART driver are always in the library - hence it is always
  637. // required to compile everything.
  638. #include "uart.h"
  639. int
  640. printf_to_uart(const char *fmt, ...)
  641. {
  642. va_list args;
  643. va_start(args, fmt);
  644. int str_l = vfnprintf(PRINTFBUFFER, PRINTFBUFFER_SIZE, fmt, args);
  645. if (!str_l) return -1; // no length string - just return
  646. // Assumes uart is initialised
  647. int i=0;while(i<str_l) uart_putc(DEFAULT_UART,PRINTFBUFFER[i++]);
  648. va_end(args);
  649. return str_l;
  650. }
  651. int
  652. putchar_to_uart(int c)
  653. {
  654. printf_to_uart("%c",c);
  655. return c;
  656. }
  657. int
  658. puts_to_uart(const char *str)
  659. {
  660. return printf_to_uart("%s\n", str);
  661. }
  662. // EOF printf.c