/* A new sscanf() like efun /Gwendolyn@nannymud.lysator.liu.se 2000 */ -------------------------------------------------------------- NAME xscanf - match strings and return an array of matched SYNOPSIS mixed *xscanf(string str, string fmt) DESCRIPTION This one is similar to sscanf in that it match a string against a pattern. The most important difference is that instead of taking a list of variables to put the values in it returns the matched items in an array. Also it recognizes some extra types: %s - string %d - decimal integer %c - character (gives the char as an int) %n - matched characters sofar %o - octal integer %x - hexadecimal integer SEE ALSO sscanf ----------------------------------------------------------- struct vector *xscanf(char *str, char *fmt) { struct vector *match, *vec; char *mem, *tst; int i, j, k, l, num = 0; for(i = 0; i < strlen(fmt);) { if(fmt[i++] == '%' && i < strlen(fmt) && (fmt[i] == 'c' || fmt[i] == 'd' || fmt[i] == 'n' || fmt[i] == 's' || fmt[i] == 'o' || fmt[i] == 'x')) num++; } if(num == 0) { if(strncmp(str, fmt, strlen(fmt))) match = (struct vector *) 0; else match = allocate_array(0); return match; } match = allocate_array(num); for(i = 0, j = 0, k = 0; fmt[j]; j++, k++) { if(!str[k]) break; if(fmt[j] == '%' && fmt[j + 1] == 's') { for(j++, tst = fmt + j + 1; tst[0] && tst[0] != '%'; tst++); if(tst == fmt + j + 1) l = strlen(str); else { for(l = k; l < strlen(str); l++) { if(!strncmp(str + l, fmt + j + 1, tst - fmt - j - 1)) break; } if(l >= strlen(str)) break; } if((mem = (char *) malloc(l - k + 1)) == NULL) { free_vector(match); error("Internal error."); } if(l > k) (void) strncpy(mem, str + k, l - k); mem[l - k] = '\0'; match->item[i].type = T_STRING; match->item[i].string_type = STRING_MALLOC; match->item[i].u.string = mem; k = l - 1; i++; } else if(fmt[j] == '%' && fmt[j + 1] == 'd') { for(l = 0; str[k] >= '0' && str[k] <= '9'; k++) l = l * 10 + str[k] - '0'; match->item[i].type = T_NUMBER; match->item[i].u.number = l; k--; j++; i++; } else if(fmt[j] == '%' && fmt[j + 1] == 'c') { match->item[i].type = T_NUMBER; match->item[i].u.number = (int) str[k]; j++; i++; } else if(fmt[j] == '%' && fmt[j + 1] == 'n') { match->item[i].type = T_NUMBER; match->item[i].u.number = k; k--; j++; i++; } else if(fmt[j] == '%' && fmt[j + 1] == 'o') { for(l = 0; str[k] >= '0' && str[k] <= '7'; k++) l = l * 8 + str[k] - '0'; match->item[i].type = T_NUMBER; match->item[i].u.number = l; k--; j++; i++; } else if(fmt[j] == '%' && fmt[j + 1] == 'x') { for(l = 0; (str[k] >= '0' && str[k] <= '9') || (str[k] >= 'a' && str[k] <= 'f') || (str[k] >= 'A' && str[k] <= 'F'); k++) { l *= 16; if(str[k] >= '0' && str[k] <= '9') l += str[k] - '0'; else if(str[k] >= 'a' && str[k] <= 'f') l += str[k] - 'a' + 10; else l += str[k] - 'A' + 10; } match->item[i].type = T_NUMBER; match->item[i].u.number = l; k--; j++; i++; } else if(fmt[j] != str[k]) break; } if(!i) { free_vector(match); vec = allocate_array(0); } else if(i == num) vec = match; else { vec = slice_array(match, 0, i - 1); free_vector(match); } return vec; }