// vsscanf // Programmed by Giuseppe Gatta, 2011 // Inherited from PSXSDK C library #include #include #include #include #include // Uncomment to enable support for %f. //#define ALLOW_FLOAT char libc_vsscanf_buf[512]; char libc_vsscanf_allow[256]; enum { elem_skip_space = 1, }; int libc_vsscanf_get_element(char *dst, const char *src, int flag, int s) { int i; const char *osrc = src; if(flag & elem_skip_space) { while(*src == ' ') src++; } for(i=0;i 512) fsz = 512; // 512 is the maximum. break; case '@': // Binary. Non-standard extension libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); buf = strtoll(libc_vsscanf_buf, &ep, 2); sp += ep - libc_vsscanf_buf; if(!suppress) { switch(sz) { case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf;break; case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; case scanf_s_long_long: *(va_arg(ap, long long*)) = buf; break; } r++; } conv = 0; break; case 'D': sz++; case 'd': // Decimal case 'u': libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); buf = strtoll(libc_vsscanf_buf, &ep, 10); sp += ep - libc_vsscanf_buf; if(!suppress) { switch(sz) { case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf;break; case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; case scanf_s_long_long: *(va_arg(ap, long long*)) = buf; break; } r++; } conv = 0; break; case 's': // String sp += libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); if(!suppress) { strcpy(va_arg(ap, char*), libc_vsscanf_buf); r++; } conv = 0; break; case 'c': if(def_fsz) fsz = 1; sp += (i = libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], (exspace ? elem_skip_space : 0), fsz)); if(!suppress) { memcpy(va_arg(ap, char*), libc_vsscanf_buf, (fsz>i)?i:fsz); r++; } break; case 'n': if(!suppress) { *(va_arg(ap, int*)) = sp; r++; } break; case 'p': case 'x': case 'X': libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); buf = strtoll(libc_vsscanf_buf, &ep, 16); sp += ep - libc_vsscanf_buf; if(!suppress) { switch(sz) { case scanf_s_char: *(va_arg(ap, unsigned char*)) = (unsigned char)buf; break; case scanf_s_short: *(va_arg(ap, unsigned short*)) = (unsigned short)buf; break; case scanf_s_int: *(va_arg(ap, unsigned int*)) = (unsigned int)buf; break; case scanf_s_long: *(va_arg(ap, unsigned long*)) = (unsigned long)buf; break; case scanf_s_long_long: *(va_arg(ap, unsigned long long*)) = (unsigned long long)buf; break; } r++; } conv = 0; break; case 'O': sz++; case 'o': // Octal integer libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); buf = strtoll(libc_vsscanf_buf, &ep, 8); sp += ep - libc_vsscanf_buf; if(!suppress) { switch(sz) { case scanf_s_char: *(va_arg(ap, unsigned char*)) = (unsigned char)buf;break; case scanf_s_short: *(va_arg(ap, unsigned short*)) = (unsigned short)buf; break; case scanf_s_int: *(va_arg(ap, unsigned int*)) = (unsigned int)buf;break; case scanf_s_long: *(va_arg(ap, unsigned long*)) = (unsigned long)buf; break; case scanf_s_long_long: *(va_arg(ap, unsigned long long*)) = (unsigned long long)buf;break; } r++; } conv = 0; break; case 'i': libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); if(libc_vsscanf_buf[0] == '0') { if(libc_vsscanf_buf[1] == 'x' || libc_vsscanf_buf[1] == 'X') i = 16; else i = 8; } else i = 10; buf = strtoll(libc_vsscanf_buf, &ep, i); sp += ep - libc_vsscanf_buf; if(!suppress) { switch(sz) { case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf; break; case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; case scanf_s_long_long: *(va_arg(ap, long long*)) = (long long)buf; break; } r++; } conv = 0; break; case '[': i=0; x=0; // Exclusion? h=0; // Hyphen? fp++; i++; while(format[fp]) { if(format[fp] == '^' && i==1) { memset(libc_vsscanf_allow, 1, 256); x = 1; fp++; i++; continue; } if(x) { if(format[fp] == ']' && i>=3) break; } else { if(format[fp] == ']' && i>=2) break; } if(format[fp] == '-') { if(format[fp+1] != ']') y = 1; else libc_vsscanf_allow['-'] = x^1; } else { if(y == 1) { if(format[fp] < format[fp-2]) libc_vsscanf_allow[format[fp]] = x^1; else for(z = format[fp-2]; z <= format[fp]; z++) libc_vsscanf_allow[z] = x^1; y = 0; //printf("%s all chars from %c to %c\n", x?"Excluding":"Including",format[fp-2], format[fp]); } else libc_vsscanf_allow[format[fp]] = x^1; } fp++; i++; } // Now as we know what our character set is, let's get data from the string /* puts("Character set:"); for(y=0;y<16;y++) { for(x=0;x<16;x++) if(libc_vsscanf_allow[(y*16) + x]) putchar((y*16)+x); else putchar('*'); putchar('\n'); } */ i = 0; while(libc_vsscanf_allow[str[sp]] && i<512) libc_vsscanf_buf[i++] = str[sp++]; libc_vsscanf_buf[i] = 0; if(!suppress) { strcpy(va_arg(ap, char*), libc_vsscanf_buf); r++; } break; #ifdef ALLOW_FLOAT case 'f': // Floating point number libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); fbuf = strtod(libc_vsscanf_buf, &ep); sp += ep - libc_vsscanf_buf; if(!suppress) { switch(sz) { case scanf_s_char: case scanf_s_short: case scanf_s_int: *(va_arg(ap, float*)) = (float)fbuf; break; case scanf_s_long: case scanf_s_long_long: *(va_arg(ap, double*)) = fbuf; break; } r++; } conv = 0; break; #endif } } else { if(format[fp] == '%') { conv = 1; neg = 0; suppress = 0; sz = scanf_s_int; fsz = 512; def_fsz = 1; exspace = 0; alt = 0; bzero(libc_vsscanf_allow, 256); //chset = 0; } else if(format[fp] != ' ') { if(format[fp] != str[sp]) exit_loop=1; sp++; } } fp++; } return r; } int sscanf(const char *str, const char *fmt, ...) { int r; va_list ap; va_start(ap, fmt); r = vsscanf(str, fmt, ap); va_end(ap); return r; }