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/scanf.c

      1 #include <stdint.h>
      2 #include <stdio.h>
      3 #include <stdarg.h>
      4 #include <ctype.h>
      5 
      6 static unsigned char scan_skip(char *s, unsigned char i)
      7 {
      8 oncemore:
      9   while(isspace(s[i]))
     10     i++;
     11   if(s[i] == 0) {
     12     gets(s);
     13     i = 0;
     14     goto oncemore;
     15   }
     16   return i;
     17 }
     18 
     19 static unsigned char scan_int(char *s, unsigned char i, unsigned char base, char *nb)
     20 {
     21   char n = 0;
     22   unsigned char j, sign = 0;
     23 
     24   switch(s[i])
     25     {
     26     case '-':
     27       sign++;
     28       /* and fall through */
     29     case '+':
     30       ++i;
     31       break;
     32     }
     33   while(1) {
     34     if(isdigit(s[i]))
     35       j = s[i] - '0';
     36     else if(isalpha(s[i]))
     37       j = toupper(s[i]) - 'A' + 10;
     38     else
     39       break;
     40     if(j >= base)
     41       break;
     42     n = base * n + j;
     43     i++;
     44   }
     45   *nb = (sign == 0 ? n : -n);
     46   return i;
     47 }
     48 
     49 static unsigned char scan_long(char *s, unsigned char i, unsigned char base, int *nb)
     50 {
     51   int n = 0;
     52   unsigned char j, sign = 0;
     53 
     54   switch(s[i])
     55     {
     56     case '-':
     57       sign++;
     58       /* and fall through */
     59     case '+':
     60       ++i;
     61       break;
     62     }
     63   while(1) {
     64     if(isdigit(s[i]))
     65       j = s[i] - '0';
     66     else if(isalpha(s[i]))
     67       j = toupper(s[i]) - 'A' + 10;
     68     else
     69       break;
     70     if(j >= base)
     71       break;
     72     n = base * n + j;
     73     i++;
     74   }
     75   *nb = (sign == 0 ? n : -n);
     76   return i;
     77 }
     78 
     79 char scanf(char *fmt, ...)
     80 {
     81   va_list ap;
     82   char s[64];
     83   unsigned char i = 0;
     84   char nb = 0;
     85 
     86   gets(s);
     87   va_start(ap, fmt);
     88   for(; *fmt; fmt++) {
     89     if(isspace(*fmt))
     90       continue;
     91     i = scan_skip(s, i);
     92     if(*fmt == '%') {
     93       switch(*++fmt) {
     94       case 'c':
     95 	/* char */
     96 	*va_arg(ap, char *) = s[i++];
     97 	break;
     98       case 'd':
     99 	/* decimal int */
    100       case 'u':
    101 	/* unsigned int */
    102 	i = scan_int(s, i, 10, va_arg(ap, char *));
    103 	break;
    104       case 'o':
    105 	/* octal int */
    106 	i = scan_int(s, i, 8, va_arg(ap, char *));
    107 	break;
    108       case 'x':
    109 	/* hexadecimal int */
    110 	i = scan_int(s, i, 16, va_arg(ap, char *));
    111 	break;
    112       case 's':
    113 	/* string */
    114 	{
    115 	  char j = 0;
    116 	  char *d = va_arg(ap, char *);
    117 	  while((d[j++] = s[i++]) != 0)
    118 	    ;
    119 	}
    120       break;
    121       case 'l':
    122 	/* long */
    123 	switch(*++fmt) {
    124 	case 'd':
    125 	  /* decimal long */
    126 	case 'u':
    127 	  /* unsigned long */
    128 	  i = scan_long(s, i, 10, va_arg(ap, int *));
    129 	  break;
    130 	case 'o':
    131 	  /* octal long */
    132 	  i = scan_long(s, i, 8, va_arg(ap, int *));
    133 	  break;
    134 	case 'x':
    135 	  /* hexadecimal long */
    136 	  i = scan_long(s, i, 16, va_arg(ap, int *));
    137 	  break;
    138 	}
    139 	break;
    140       default:
    141 	if(s[i] != *fmt)
    142 	  return -1;
    143 	break;
    144       }
    145       nb++;
    146     } else
    147       if(s[i] != *fmt)
    148 	return -1;
    149   }
    150   va_end(ap);
    151 
    152   return nb;
    153 }

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