/* sscanf.c: Replacement of sscanf for TI-Nspire * * Copyright (C) 2013 by Yogeshwar Velingker, under the GNU General Public * License. No warranty. See COPYING for details. */ #ifdef _TINSPIRE #include #include "defs.h" #include "sscanf.h" /* Checks if char c is in first n bytes of the memory pointed to by mem. */ static int chr_in_mem(const char *mem, char c, size_t n) { size_t i; for (i = 0; i < n; i++) { if (*mem == c) return TRUE; mem++; } return FALSE; } /* Simple sscanf for the purpose of this program. */ int simplesscanf(const char *str, const char *format, ...) { va_list ap; const char *f = format; const char *s = str; char *charp = NULL; int *intp = NULL; unsigned long *longp = NULL; int count = 0; size_t loop; int bracket_chars; unsigned int field_width; int scanset_negated; int store_value; int hex_use_long; va_start(ap, format); if (*f != '%' && !isspace(*f) && isspace(*s)) return 0; while (*f != '\0') { while (isspace(*f)) f++; if (!(*f == '%' && (*(f + 1) == '[' || (*(f + 1) == '*' && *(f + 2) == '[')))) { while (isspace(*s)) s++; } else if (isspace(*(f - 1))) { while (isspace(*s)) s++; } if (*f == '%') { store_value = TRUE; f++; if (*f == '*') { store_value = FALSE; f++; } if (*f == '%') { if (*s != '%') break; } else if (*f == 's') { if (*s == '\0') { if (count == 0) return EOF; else break; } if (store_value) charp = va_arg(ap, char *); while (!isspace(*s) && *s != '\0') { if (store_value) { *charp = *s; charp++; } s++; } if (store_value) { *charp = '\0'; count++; } } else if (*f == 'd') { if (*s == '\0') { if (count == 0) return EOF; else break; } if (*s < '0' || *s > '9') break; if (store_value) { intp = va_arg(ap, int *); *intp = 0; } if (store_value) *intp = atoi(s); while ('0' <= *s && *s <= '9') { s++; } s--; if (store_value) count++; } else if (*f == '[') { if (*s == '\0') { if (count == 0) return EOF; else break; } bracket_chars = 0; f++; if (*f == '^') { f++; scanset_negated = TRUE; } else scanset_negated = FALSE; if (*f == ']') { f++; bracket_chars = 1; } while (*f != ']' && *f != '\0') { f++; bracket_chars++; } if (*f != ']') break; if (store_value) charp = va_arg(ap, char *); if (scanset_negated) { if (chr_in_mem(f - bracket_chars, *s, bracket_chars)) break; while (!chr_in_mem(f - bracket_chars, *s, bracket_chars)) { if (store_value) { *charp = *s; charp++; } s++; if (*s == '\0') break; } } else { if (!chr_in_mem(f - bracket_chars, *s, bracket_chars)) break; while (chr_in_mem(f - bracket_chars, *s, bracket_chars)) { if (store_value) { *charp = *s; charp++; } s++; if (*s == '\0') // Should never happen but included anyway break; } } if (store_value) { *charp = '\0'; count++; } s--; } else if (*f == '0') { if (*s == '\0') { if (count == 0) return EOF; else break; } f++; field_width = 0; while ('0' <= *f && *f <= '9') { field_width *= 10; field_width += (*f - '0'); f++; } if (*f != 'x' && *f != 'X' && *f != 'l') break; if (*f == 'l') { if (*(f + 1) != 'x' && *(f + 1) != 'X') break; if (store_value) { longp = va_arg(ap, unsigned long *); *longp = 0; } hex_use_long = TRUE; f++; } else { if (store_value) { intp = va_arg(ap, int *); *intp = 0; } hex_use_long = FALSE; } if (!('0' <= *s && *s <= '9') && !('a' <= *s && *s <= 'f') && !('A' <= *s && *s <= 'F')) break; for (loop = 0; loop < field_width; loop++) { if (!('0' <= *s && *s <= '9') && !('a' <= *s && *s <= 'f') && !('A' <= *s && *s <= 'F')) break; // Horner's Rule if (hex_use_long) { if (store_value) { *longp *= 16; if ('0' <= *s && *s <= '9') { *longp += (*s - '0'); } else if ('a' <= *s && *s <= 'f') { *longp += (*s - 'a' + 10); } else if ('A' <= *s && *s <= 'F') { *longp += (*s - 'A' + 10); } } } else { if (store_value) { *intp *= 16; if ('0' <= *s && *s <= '9') { *intp += (*s - '0'); } else if ('a' <= *s && *s <= 'f') { *intp += (*s - 'a' + 10); } else if ('A' <= *s && *s <= 'F') { *intp += (*s - 'A' + 10); } } } s++; } s--; if (store_value) count++; } else break; } else { if (*s == '\0') { if (count == 0) return EOF; else break; } if (*s != *f) break; } f++; s++; } va_end(ap); return count; } #endif