+int
+chise_ds_foreach_char_feature_name (CHISE_DS *ds,
+ int (*func) (CHISE_DS *ds,
+ unsigned char *name))
+{
+ unsigned char *dname
+ = alloca (strlen (ds->location) + sizeof ("/character/feature") + 1);
+ DIR *dir;
+ struct dirent *de;
+
+ strcpy (dname, ds->location);
+ strcat (dname, "/character/feature");
+
+ if ( (dir = opendir (dname)) == NULL)
+ return -1;
+
+ while ( (de = readdir (dir)) != NULL )
+ {
+ if ( (strcmp (de->d_name, ".") != 0) &&
+ (strcmp (de->d_name, "..") != 0) )
+ {
+ int i, need_to_decode = 0;
+ unsigned char *cp;
+ unsigned char *name;
+ unsigned char *np;
+
+ for (cp = de->d_name, i = 0; *cp != '\0'; i++)
+ {
+ if (*cp++ == '%')
+ need_to_decode = 1;
+ }
+ if (need_to_decode)
+ {
+ int index = -1;
+ int ch, c[2];
+ int hex[2];
+
+ name = (unsigned char *) alloca (i);
+ cp = de->d_name;
+ np = name;
+
+ while ( (ch = *cp++) != '\0')
+ {
+ if (ch == '%')
+ {
+ if (index >= 0)
+ {
+ *np++ = '%';
+ if (index == 1)
+ *np++ = c[0];
+ }
+ index = 0;
+ }
+ else if (index >= 0)
+ {
+ c[index] = ch;
+
+ if ( ('0' <= ch) && (ch <= '9') )
+ hex[index++] = ch - '0';
+ else if ( ('A' <= ch) && (ch <= 'F') )
+ hex[index++] = ch - 'A' + 10;
+ else if ( ('a' <= ch) && (ch <= 'f') )
+ hex[index++] = ch - 'a' + 10;
+ else
+ {
+ *np++ = '%';
+ if (index == 1)
+ *np++ = c[0];
+ *np++ = ch;
+ index = -1;
+ continue;
+ }
+ if (index == 2)
+ {
+ *np++ = (hex[0] << 4) | hex[1];
+ index = -1;
+ continue;
+ }
+ }
+ else
+ *np++ = ch;
+ }
+ *np = '\0';
+ }
+ else
+ name = de->d_name;
+
+ if (func (ds, name))
+ return closedir (dir);
+ }
+ }
+ return closedir (dir);
+}