Xyris  0.5
stdio.hpp File Reference
#include <stdarg.h>
+ Include dependency graph for stdio.hpp:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define log_all(fmt, ...)
 

Typedefs

typedef int(* printf_cb_fnptr_t) (unsigned c, void **helper)
 

Functions

int printf_helper (const char *fmt, va_list args, printf_cb_fnptr_t fn, void *ptr)
 
int kvsprintf (char *buf, const char *fmt, va_list args)
 
int ksprintf (char *buf, const char *fmt,...)
 

Detailed Description

Author
Keeton Feavel (keeto.nosp@m.nfea.nosp@m.vel@c.nosp@m.edar.nosp@m.ville.nosp@m..edu)
Version
0.3
Date
2020-07-09

Definition in file stdio.hpp.

Macro Definition Documentation

◆ log_all

#define log_all (   fmt,
  ... 
)
Value:
do { \
RS232::printf(fmt, ##__VA_ARGS__); \
Console::printf(fmt, ##__VA_ARGS__); \
} while (0)

Prints a statement to serial debugger and the kernel framebuffer. Max message size is 1024 (including null terminator).

Parameters
fmtFormatted C string
...Sequence of additional arguments

Definition at line 59 of file stdio.hpp.

Typedef Documentation

◆ printf_cb_fnptr_t

typedef int(* printf_cb_fnptr_t) (unsigned c, void **helper)

Definition at line 14 of file stdio.hpp.

Function Documentation

◆ ksprintf()

int ksprintf ( char *  buf,
const char *  fmt,
  ... 
)

Sends formatted output to a string.

Parameters
bufPointer to a buffer where the result is stored
fmtC string that contains a format string
...Sequence of additional arguments
Returns
int The total number of characters written. The number of characters not written if negative.

Definition at line 342 of file printf.cpp.

343 {
344  va_list args;
345  int ret_val;
346 
347  va_start(args, fmt);
348  ret_val = kvsprintf(buf, fmt, args);
349  va_end(args);
350  return ret_val;
351 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ kvsprintf()

int kvsprintf ( char *  buf,
const char *  fmt,
va_list  args 
)

Sends formatted output to a string using an argument list.

Parameters
bufPointer to a buffer where the result is stored
fmtC string that contains a format string
argsA value identifying a variable arguments list
Returns
int The total number of characters written. The number of characters not written if negative.

Definition at line 333 of file printf.cpp.

334 {
335  int ret_val;
336 
337  ret_val = printf_helper(fmt, args, vsprintf_help, (void*)buf);
338  buf[ret_val] = '\0';
339  return ret_val;
340 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ printf_helper()

int printf_helper ( const char *  fmt,
va_list  args,
printf_cb_fnptr_t  fn,
void *  ptr 
)

Perform all printf operations on the format string using the provided argument list and uses the callback function to perform the character printing operation. This allows for adding printf capabilities to a wide range of text output applications, such as an RS232 debug driver, or a framebuffer console.

Parameters
fmtFormat string
argsArguments list
fnCharacter printing callback function pointer
ptrUser-provided data / handle pointer
Returns
int Returns number of characters written

Definition at line 105 of file printf.cpp.

106 {
107  unsigned char radix, *where, buf[PR_BUFLEN];
108  unsigned int state, flags, actual_wd, count, given_wd;
109  long num;
110 
111  state = flags = count = given_wd = 0;
112  /* begin scanning format specifier list */
113  for (; *fmt; fmt++) {
114  switch (state) {
115  /* STATE 0: AWAITING % */
116  case 0:
117  if (*fmt != '%') /* not %... */
118  {
119  fn(*fmt, &ptr); /* ...just echo it */
120  count++;
121  break;
122  }
123  /* found %, get next char and advance state to check if next char is a flag */
124  state++;
125  fmt++;
126  /* FALL THROUGH */
127  /* STATE 1: AWAITING FLAGS (%-0) */
128  case 1:
129  if (*fmt == '%') /* %% */
130  {
131  fn(*fmt, &ptr);
132  count++;
133  state = flags = given_wd = 0;
134  break;
135  }
136  if (*fmt == '-') {
137  if (flags & PR_LJ) /* %-- is illegal */
138  state = flags = given_wd = 0;
139  else
140  flags |= PR_LJ;
141  break;
142  }
143  /* not a flag char: advance state to check if it's field width */
144  state++;
145  /* check now for '%0...' */
146  if (*fmt == '0') {
147  flags |= PR_LZ;
148  fmt++;
149  }
150  /* FALL THROUGH */
151  /* STATE 2: AWAITING (NUMERIC) FIELD WIDTH */
152  case 2:
153  if (*fmt >= '0' && *fmt <= '9') {
154  given_wd = 10 * given_wd + (*fmt - '0');
155  break;
156  }
157  /* not field width: advance state to check if it's a modifier */
158  state++;
159  /* FALL THROUGH */
160  /* STATE 3: AWAITING MODIFIER CHARS (FNlh) */
161  case 3:
162  if (*fmt == 'F') {
163  flags |= PR_FP;
164  break;
165  }
166  if (*fmt == 'N')
167  break;
168 
169  if (*fmt == 'z') {
170 #if (UINTPTR_MAX == UINT32_MAX)
171  flags |= PR_32;
172 #elif (UINTPTR_MAX == UINT64_MAX)
173  flags |= PR_64;
174 #else
175 #error "Unknown UINTPTR_MAX value! Cannot compile printf_helper!"
176 #endif
177  break;
178  }
179  if (*fmt == 'l') {
180  flags |= PR_32;
181  break;
182  }
183  if (*fmt == 'L') {
184  flags |= PR_64;
185  break;
186  }
187  if (*fmt == 'h') {
188  flags |= PR_16;
189  break;
190  }
191  /* not modifier: advance state to check if it's a conversion char */
192  state++;
193  /* FALL THROUGH */
194  /* STATE 4: AWAITING CONVERSION CHARS (Xxpndiuocs) */
195  case 4: {
196  where = buf + PR_BUFLEN - 1;
197  *where = '\0';
198  switch (*fmt) {
199  case 'X':
200  flags |= PR_CA;
201  /* FALL THROUGH */
202  /* xxx - far pointers (%Fp, %Fn) not yet supported */
203  case 'x':
204  case 'p':
205  case 'n':
206  radix = 16;
207  goto DO_NUM;
208  case 'd':
209  case 'i':
210  flags |= PR_SG;
211  /* FALL THROUGH */
212  case 'u':
213  radix = 10;
214  goto DO_NUM;
215  case 'o':
216  radix = 8;
217  /* load the value to be printed. l=long=32 bits: */
218  DO_NUM:
219  if (flags & PR_64)
220  num = va_arg(args, unsigned long long);
221  else if (flags & PR_32)
222  num = va_arg(args, unsigned long);
223  /* h=short=16 bits (signed or unsigned) */
224  else if (flags & PR_16) {
225  if (flags & PR_SG)
226  num = va_arg(args, int);
227  else
228  num = va_arg(args, int);
229  }
230  /* no h nor l: sizeof(int) bits (signed or unsigned) */
231  else {
232  if (flags & PR_SG)
233  num = va_arg(args, int);
234  else
235  num = va_arg(args, unsigned int);
236  }
237  /* take care of sign */
238  if (flags & PR_SG) {
239  if (num < 0) {
240  flags |= PR_WS;
241  num = -num;
242  }
243  }
244  /* convert binary to octal/decimal/hex ASCII
245  OK, I found my mistake. The math here is _always_ unsigned */
246  do {
247  unsigned long temp;
248 
249  temp = (unsigned long)num % radix;
250  where--;
251  if (temp < 10)
252  *where = (unsigned char)(temp + '0');
253  else if (flags & PR_CA)
254  *where = (unsigned char)(temp - 10 + 'A');
255  else
256  *where = (unsigned char)(temp - 10 + 'a');
257  num = (unsigned long)num / radix;
258  } while (num != 0);
259  goto EMIT;
260  case 'c':
261  /* disallow pad-left-with-zeroes for %c */
262  flags &= ~PR_LZ;
263  where--;
264  *where = (unsigned char)va_arg(args, int);
265  actual_wd = 1;
266  goto EMIT2;
267  case 's':
268  /* disallow pad-left-with-zeroes for %s */
269  flags &= ~PR_LZ;
270  where = va_arg(args, unsigned char*);
271  EMIT:
272  actual_wd = strlen((const char*)where);
273  if (flags & PR_WS)
274  actual_wd++;
275  /* if we pad left with ZEROES, do the sign now */
276  if ((flags & (PR_WS | PR_LZ)) == (PR_WS | PR_LZ)) {
277  fn('-', &ptr);
278  count++;
279  }
280  /* pad on left with spaces or zeroes (for right justify) */
281  EMIT2:
282  if ((flags & PR_LJ) == 0) {
283  while (given_wd > actual_wd) {
284  fn(flags & PR_LZ ? '0' : ' ', &ptr);
285  count++;
286  given_wd--;
287  }
288  }
289  /* if we pad left with SPACES, do the sign now */
290  if ((flags & (PR_WS | PR_LZ)) == PR_WS) {
291  fn('-', &ptr);
292  count++;
293  }
294  /* emit string/char/converted number */
295  while (*where != '\0') {
296  fn(*where++, &ptr);
297  count++;
298  }
299  /* pad on right with spaces (for left justify) */
300  if (given_wd < actual_wd)
301  given_wd = 0;
302  else
303  given_wd -= actual_wd;
304  for (; given_wd; given_wd--) {
305  fn(' ', &ptr);
306  count++;
307  }
308  break;
309  default:
310  break;
311  }
312  // Tell the compiler that this isn't an issue (at least I'm assuming it isn't)
313  [[fallthrough]];
314  }
315  default:
316  state = flags = given_wd = 0;
317  break;
318  }
319  }
320  return count;
321 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:
PR_16
@ PR_16
Definition: printf.cpp:89
PR_64
@ PR_64
Definition: printf.cpp:87
kvsprintf
int kvsprintf(char *buf, const char *fmt, va_list args)
Sends formatted output to a string using an argument list.
Definition: printf.cpp:333
PR_LZ
@ PR_LZ
Definition: printf.cpp:91
strlen
int strlen(const char *s)
Returns the length of a string.
Definition: string.cpp:14
PR_BUFLEN
#define PR_BUFLEN
Definition: printf.cpp:97
PR_CA
@ PR_CA
Definition: printf.cpp:85
PR_32
@ PR_32
Definition: printf.cpp:88
Console::printf
int printf(const char *fmt,...)
Definition: console.cpp:273
PR_LJ
@ PR_LJ
Definition: printf.cpp:84
printf_helper
int printf_helper(const char *fmt, va_list args, printf_cb_fnptr_t fn, void *ptr)
Perform all printf operations on the format string using the provided argument list and uses the call...
Definition: printf.cpp:105
PR_SG
@ PR_SG
Definition: printf.cpp:86
PR_WS
@ PR_WS
Definition: printf.cpp:90
PR_FP
@ PR_FP
Definition: printf.cpp:92