* Singularize a string the user typed in; this helps reduce the complexity * of readobjnam, and is also used in pager.c to singularize the string * for which help is sought. * * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)? * Its inclusion in as_is[]/special_subj[] makes it get treated as the former. * * A lot of unique monsters have names ending in s; plural, or
| 3034 | * 3.6.0: made case-insensitive. |
| 3035 | */ |
| 3036 | char * |
| 3037 | makesingular(const char *oldstr) |
| 3038 | { |
| 3039 | char *p, *bp; |
| 3040 | const char *excess = 0; |
| 3041 | char *str = nextobuf(); |
| 3042 | |
| 3043 | if (oldstr) |
| 3044 | while (*oldstr == ' ') |
| 3045 | oldstr++; |
| 3046 | if (!oldstr || !*oldstr) { |
| 3047 | impossible("singular of null?"); |
| 3048 | str[0] = '\0'; |
| 3049 | return str; |
| 3050 | } |
| 3051 | /* makeplural() of pronouns isn't reversible but at least we can |
| 3052 | force a singular value */ |
| 3053 | *str = '\0'; |
| 3054 | if (!strcmpi(genders[3].he, oldstr)) /* "they" */ |
| 3055 | Strcpy(str, genders[2].he); /* "it" */ |
| 3056 | else if (!strcmpi(genders[3].him, oldstr)) /* "them" */ |
| 3057 | Strcpy(str, genders[2].him); /* also "it" */ |
| 3058 | else if (!strcmpi(genders[3].his, oldstr)) /* "their" */ |
| 3059 | Strcpy(str, genders[2].his); /* "its" */ |
| 3060 | if (*str) { |
| 3061 | if (oldstr[0] == highc(oldstr[0])) |
| 3062 | str[0] = highc(str[0]); |
| 3063 | return str; |
| 3064 | } |
| 3065 | |
| 3066 | bp = strcpy(str, oldstr); |
| 3067 | |
| 3068 | /* check for "foo of bar" so that we can focus on "foo" */ |
| 3069 | if ((p = singplur_compound(bp)) != 0) { |
| 3070 | excess = oldstr + (int) (p - bp); |
| 3071 | *p = '\0'; |
| 3072 | } else |
| 3073 | p = eos(bp); |
| 3074 | |
| 3075 | /* dispense with some words which don't need singularization */ |
| 3076 | if (singplur_lookup(bp, p, FALSE, special_subjs)) |
| 3077 | goto bottom; |
| 3078 | |
| 3079 | /* remove -s or -es (boxes) or -ies (rubies) */ |
| 3080 | if (p >= bp + 1 && lowc(p[-1]) == 's') { |
| 3081 | if (p >= bp + 2 && lowc(p[-2]) == 'e') { |
| 3082 | if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */ |
| 3083 | if (!BSTRCMPI(bp, p - 7, "cookies") |
| 3084 | || (!BSTRCMPI(bp, p - 4, "pies") |
| 3085 | /* avoid false match for "harpies" */ |
| 3086 | && (p - 4 == bp || p[-5] == ' ')) |
| 3087 | /* alternate djinni/djinn spelling; not really needed */ |
| 3088 | || (!BSTRCMPI(bp, p - 6, "genies") |
| 3089 | /* avoid false match for "progenies" */ |
| 3090 | && (p - 6 == bp || p[-7] == ' ')) |
| 3091 | || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */ |
| 3092 | || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */ |
| 3093 | goto mins; |
no test coverage detected