git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/libc/sprintf.c

      1 #include <types.h>
      2 #include <stdio.h>
      3 #include <stdarg.h>
      4 #include <stdlib.h>
      5 #include <stdint.h>
      6 
      7 #if defined(__PORT_mos6502)
      8 typedef void (*emitter_t)(char, char **) REENTRANT;
      9 #else
     10 typedef void (*emitter_t)(char, char **) OLDCALL;
     11 #endif
     12 
     13 static const char _hex[] = "0123456789ABCDEF";
     14 
     15 inline void _printhex(uint16_t u, emitter_t emitter, char ** pData)
     16 {
     17     (*emitter)(_hex[(uint8_t)(u >> 8) >> 4], pData);
     18     (*emitter)(_hex[(uint8_t)(u >> 8) & 0x0fu], pData);
     19     (*emitter)(_hex[((uint8_t)u >> 4) & 0x0fu], pData);
     20     (*emitter)(_hex[(uint8_t)u & 0x0fu], pData);
     21 }
     22 
     23 inline void _printhexbyte(uint8_t u, emitter_t emitter, char ** pData)
     24 {
     25     (*emitter)(_hex[u >> 4], pData);
     26     (*emitter)(_hex[u & 0x0fu], pData);
     27 }
     28 
     29 static void _printbuf(char * buf, emitter_t emitter, char ** pData) {
     30     for (char *s = buf; *s; s++) (*emitter)(*s, pData);
     31 }
     32 
     33 void __printf(const char *format, emitter_t emitter, char **pData, va_list va)
     34 {
     35     char buf[16];
     36     while ((uint8_t)(*format)) {
     37         if ((uint8_t)(*format) == '%') {
     38             format++;
     39 
     40             // 0 Padding is not supported, ignore
     41             if ((uint8_t)(*format) == '0') format++;
     42 
     43             // Width Specifier is not supported, ignore 1 digit worth
     44             if ((uint8_t)((uint8_t)(*format) - '1') < 9u) format++;
     45 
     46             switch ((uint8_t)(*format)) {
     47                 case 'h':
     48                     switch ((uint8_t)(*++format)) {
     49                         case 'X' :
     50                         case 'x' :
     51                             _printhexbyte(va_arg(va, char), emitter, pData);
     52                             break;
     53                         case 'u':
     54                             uitoa((unsigned char)va_arg(va, char), buf, 10);
     55                             _printbuf(buf, emitter, pData);
     56                             break;
     57                         case 'd':
     58                             itoa((signed char)va_arg(va, char), buf, 10);
     59                             _printbuf(buf, emitter, pData);
     60                             break;
     61                     }
     62                     break;
     63                 case 'u':
     64                     uitoa(va_arg(va, int), buf, 10);
     65                     _printbuf(buf, emitter, pData);
     66                     break;
     67                 case 'd':
     68                     itoa(va_arg(va, int), buf, 10);
     69                     _printbuf(buf, emitter, pData);
     70                     break;
     71                 case 's': 
     72                     _printbuf(va_arg(va, char *), emitter, pData);
     73                     break;
     74                 case 'c': 
     75                     char c = va_arg(va, char);
     76                     (*emitter)(c, pData);
     77                     break;
     78                 case 'X':
     79                 case 'x':
     80                     _printhex(va_arg(va, int), emitter, pData);
     81                     break;
     82                 default:
     83                     (*emitter)(*format, pData);
     84                     break;
     85             }
     86         } else {
     87             (*emitter)(*format, pData);
     88         }
     89         format++;
     90     }
     91 }
     92 
     93 #if defined(__PORT_mos6502)
     94 static void _sprintf_emitter(char c, char ** pData) REENTRANT
     95 #else
     96 static void _sprintf_emitter(char c, char ** pData) OLDCALL
     97 #endif
     98 {
     99     **pData = c;
    100     (*pData)++;
    101 }
    102 
    103 void sprintf(char *into, const char *format, ...) {
    104     va_list va;
    105     va_start(va, format);
    106 
    107     __printf(format, _sprintf_emitter, &into, va);
    108     _sprintf_emitter('\0', &into);
    109 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.