return form of the verb (input plural) for present tense 3rd person subj */
| 2560 | |
| 2561 | /* return form of the verb (input plural) for present tense 3rd person subj */ |
| 2562 | char * |
| 2563 | vtense(const char *subj, const char *verb) |
| 2564 | { |
| 2565 | char *buf = nextobuf(), *bspot; |
| 2566 | int len, ltmp; |
| 2567 | const char *sp, *spot; |
| 2568 | const char *const *spec; |
| 2569 | |
| 2570 | /* |
| 2571 | * verb is given in plural (without trailing s). Return as input |
| 2572 | * if subj appears to be plural. Add special cases as necessary. |
| 2573 | * Many hard cases can already be handled by using otense() instead. |
| 2574 | * If this gets much bigger, consider decomposing makeplural. |
| 2575 | * Note: monster names are not expected here (except before corpse). |
| 2576 | * |
| 2577 | * Special case: allow null sobj to get the singular 3rd person |
| 2578 | * present tense form so we don't duplicate this code elsewhere. |
| 2579 | */ |
| 2580 | if (subj) { |
| 2581 | if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3)) |
| 2582 | goto sing; |
| 2583 | spot = (const char *) 0; |
| 2584 | for (sp = subj; (sp = strchr(sp, ' ')) != 0; ++sp) { |
| 2585 | if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6) |
| 2586 | || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7) |
| 2587 | || !strncmpi(sp, " labeled ", 9)) { |
| 2588 | if (sp != subj) |
| 2589 | spot = sp - 1; |
| 2590 | break; |
| 2591 | } |
| 2592 | } |
| 2593 | len = (int) strlen(subj); |
| 2594 | if (!spot) |
| 2595 | spot = subj + len - 1; |
| 2596 | |
| 2597 | /* |
| 2598 | * plural: anything that ends in 's', but not '*us' or '*ss'. |
| 2599 | * Guess at a few other special cases that makeplural creates. |
| 2600 | */ |
| 2601 | if ((lowc(*spot) == 's' && spot != subj |
| 2602 | && !strchr("us", lowc(*(spot - 1)))) |
| 2603 | || !BSTRNCMPI(subj, spot - 3, "eeth", 4) |
| 2604 | || !BSTRNCMPI(subj, spot - 3, "feet", 4) |
| 2605 | || !BSTRNCMPI(subj, spot - 1, "ia", 2) |
| 2606 | || !BSTRNCMPI(subj, spot - 1, "ae", 2)) { |
| 2607 | /* check for special cases to avoid false matches */ |
| 2608 | len = (int) (spot - subj) + 1; |
| 2609 | for (spec = special_subjs; *spec; spec++) { |
| 2610 | ltmp = Strlen(*spec); |
| 2611 | if (len == ltmp && !strncmpi(*spec, subj, len)) |
| 2612 | goto sing; |
| 2613 | /* also check for <prefix><space><special_subj> |
| 2614 | to catch things like "the invisible erinys" */ |
| 2615 | if (len > ltmp && *(spot - ltmp) == ' ' |
| 2616 | && !strncmpi(*spec, spot - ltmp + 1, ltmp)) |
| 2617 | goto sing; |
| 2618 | } |
| 2619 |
no test coverage detected