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.