Serenity Operating System
at portability 220 lines 6.5 kB view raw
1/* 2 * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se) 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by Opsycon AB. 15 * 4. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31#include <ctype.h> 32#include <stdarg.h> 33#include <stdint.h> 34#include <stdio.h> 35#include <string.h> 36 37static const char* determine_base(const char* p, int& base) 38{ 39 if (p[0] == '0') { 40 switch (p[1]) { 41 case 'x': 42 base = 16; 43 break; 44 case 't': 45 case 'n': 46 base = 10; 47 break; 48 case 'o': 49 base = 8; 50 break; 51 default: 52 base = 10; 53 return p; 54 } 55 return p + 2; 56 } 57 base = 10; 58 return p; 59} 60 61static int _atob(unsigned long* vp, const char* p, int base) 62{ 63 unsigned long value, v1, v2; 64 const char *q; 65 char tmp[20]; 66 int digit; 67 68 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { 69 base = 16; 70 p += 2; 71 } 72 73 if (base == 16 && (q = strchr(p, '.')) != 0) { 74 if (q - p > (int)sizeof(tmp) - 1) 75 return 0; 76 strncpy(tmp, p, q - p); 77 tmp[q - p] = '\0'; 78 if (!_atob(&v1, tmp, 16)) 79 return 0; 80 ++q; 81 if (strchr(q, '.')) 82 return 0; 83 if (!_atob(&v2, q, 16)) 84 return 0; 85 *vp = (v1 << 16) + v2; 86 return 1; 87 } 88 89 value = *vp = 0; 90 for (; *p; p++) { 91 if (*p >= '0' && *p <= '9') 92 digit = *p - '0'; 93 else if (*p >= 'a' && *p <= 'f') 94 digit = *p - 'a' + 10; 95 else if (*p >= 'A' && *p <= 'F') 96 digit = *p - 'A' + 10; 97 else 98 return 0; 99 100 if (digit >= base) 101 return 0; 102 value *= base; 103 value += digit; 104 } 105 *vp = value; 106 return 1; 107} 108 109int atob(unsigned int* vp, const char* p, int base) 110{ 111 unsigned long v; 112 113 if (base == 0) 114 p = determine_base(p, base); 115 if (_atob(&v, p, base)) { 116 *vp = v; 117 return 1; 118 } 119 return 0; 120} 121 122#define ISSPACE " \t\n\r\f\v" 123 124int vsscanf(const char* buf, const char* s, va_list ap) 125{ 126 int base = 10; 127 char* t; 128 char tmp[BUFSIZ]; 129 bool noassign = false; 130 int count = 0; 131 int width = 0; 132 133 while (*s && *buf) { 134 while (isspace(*s)) 135 s++; 136 if (*s == '%') { 137 s++; 138 for (; *s; s++) { 139 if (strchr("dibouxcsefg%", *s)) 140 break; 141 if (*s == '*') 142 noassign = true; 143 else if (*s >= '1' && *s <= '9') { 144 const char* tc; 145 for (tc = s; isdigit(*s); s++) 146 ; 147 strncpy(tmp, tc, s - tc); 148 tmp[s - tc] = '\0'; 149 atob((uint32_t*)&width, tmp, 10); 150 s--; 151 } 152 } 153 if (*s == 's') { 154 while (isspace(*buf)) 155 buf++; 156 if (!width) 157 width = strcspn(buf, ISSPACE); 158 if (!noassign) { 159 strncpy(t = va_arg(ap, char*), buf, width); 160 t[width] = '\0'; 161 } 162 buf += width; 163 } else if (*s == 'c') { 164 if (!width) 165 width = 1; 166 if (!noassign) { 167 strncpy(t = va_arg(ap, char*), buf, width); 168 t[width] = '\0'; 169 } 170 buf += width; 171 } else if (strchr("dobxu", *s)) { 172 while (isspace(*buf)) 173 buf++; 174 if (*s == 'd' || *s == 'u') 175 base = 10; 176 else if (*s == 'x') 177 base = 16; 178 else if (*s == 'o') 179 base = 8; 180 else if (*s == 'b') 181 base = 2; 182 if (!width) { 183 if (isspace(*(s + 1)) || *(s + 1) == 0) { 184 width = strcspn(buf, ISSPACE); 185 } else { 186 auto* p = strchr(buf, *(s + 1)); 187 if (p) 188 width = p - buf; 189 else { 190 noassign = true; 191 width = 0; 192 } 193 } 194 } 195 strncpy(tmp, buf, width); 196 tmp[width] = '\0'; 197 buf += width; 198 if (!noassign) { 199 if (!atob(va_arg(ap, uint32_t*), tmp, base)) 200 noassign = true; 201 } 202 } 203 if (!noassign) 204 ++count; 205 width = 0; 206 noassign = false; 207 ++s; 208 } else { 209 while (isspace(*buf)) 210 buf++; 211 if (*s != *buf) 212 break; 213 else { 214 ++s; 215 ++buf; 216 } 217 } 218 } 219 return count; 220}