printf.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. #include "pal_internal.h"
  16. #include "api.h"
  17. // Collect up to PRINTBUF_SIZE characters into a buffer
  18. // and perform ONE system call to print all of them,
  19. // in order to make the lines output to the console atomic
  20. // and prevent interrupts from causing context switches
  21. // in the middle of a console output line and such.
  22. #define PRINTBUF_SIZE 256
  23. struct printbuf {
  24. int idx; // current buffer index
  25. int cnt; // total bytes printed so far
  26. char buf[PRINTBUF_SIZE];
  27. };
  28. struct sprintbuf {
  29. char * buf;
  30. char * ebuf;
  31. int cnt;
  32. };
  33. static void
  34. fputch(void * f, int ch, struct printbuf * b)
  35. {
  36. b->buf[b->idx++] = ch;
  37. if (b->idx == PRINTBUF_SIZE-1) {
  38. _DkPrintConsole(b->buf, b->idx);
  39. b->idx = 0;
  40. }
  41. b->cnt++;
  42. }
  43. static int
  44. vprintf(const char * fmt, va_list ap)
  45. {
  46. struct printbuf b;
  47. b.idx = 0;
  48. b.cnt = 0;
  49. vfprintfmt((void *) &fputch, NULL, &b, fmt, ap);
  50. _DkPrintConsole(b.buf, b.idx);
  51. return b.cnt;
  52. }
  53. int
  54. printf(const char * fmt, ...)
  55. {
  56. va_list ap;
  57. int cnt;
  58. va_start(ap, fmt);
  59. cnt = vprintf(fmt, ap);
  60. va_end(ap);
  61. return cnt;
  62. }
  63. extern_alias(printf);
  64. static void
  65. sprintputch(void * f, int ch, struct sprintbuf * b)
  66. {
  67. b->cnt++;
  68. if (b->buf < b->ebuf)
  69. *b->buf++ = ch;
  70. }
  71. static int
  72. vsprintf(char * buf, int n, const char * fmt, va_list ap)
  73. {
  74. struct sprintbuf b = {buf, buf + n - 1, 0};
  75. if (buf == NULL || n < 1) {
  76. return -1;
  77. }
  78. // print the string to the buffer
  79. vfprintfmt((void *) sprintputch, (void *) 0, &b, fmt, ap);
  80. // null terminate the buffer
  81. *b.buf = '\0';
  82. return b.cnt;
  83. }
  84. int
  85. snprintf(char * buf, size_t n, const char * fmt, ...)
  86. {
  87. va_list ap;
  88. int rc;
  89. va_start(ap, fmt);
  90. rc = vsprintf(buf, n, fmt, ap);
  91. va_end(ap);
  92. return rc;
  93. }
  94. extern_alias(snprintf);