Annotation of coherent/g/usr/lib/misc/metaphone.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Metaphone algorithm for translating a word to
        !             3:  * a short phonetic equivalent for lookup.
        !             4:  * char * metaphone(char * word)
        !             5:  *
        !             6:  * Original algorithm by Larry Phillips
        !             7:  * Algorithim is in public domain.
        !             8:  */
        !             9: #include <ctype.h>
        !            10: 
        !            11: static char vsvfn[26] = {
        !            12:      /*  A  B C  D E F G  H I J K L M N O P Q R S T U V W X Y Z */
        !            13:         1,16,4,16,9,2,4,16,9,2,0,2,2,2,1,4,0,2,4,4,1,0,0,0,8,0
        !            14: };
        !            15: 
        !            16: #define FN(x) ((c = (x)) ? vsvfn[c - 'A'] : 0)
        !            17: #define VOWEL(x)   (FN(x) &  1) /* AEIOU */
        !            18: #define SAME(x)    (FN(x) &  2) /* FJLMNR */
        !            19: #define VARSON(x)  (FN(x) &  4) /* CGPST */
        !            20: #define FRONTV(x)  (FN(x) &  8) /* EIY */
        !            21: #define NOGHF(x)   (FN(x) & 16) /* BDH */
        !            22: 
        !            23: #define SAY(x) { *Metaph++ = (x); continue; }
        !            24: 
        !            25: #define MAXMET 4       /* size of thing created */
        !            26: #define TRANS 32
        !            27: 
        !            28: char *
        !            29: metaphone(word)
        !            30: unsigned char *word;
        !            31: {
        !            32:        unsigned char *n, *n_start, *n_end, c;
        !            33:        unsigned char *Metaph, *metaph_end;
        !            34:        int KSflag;     /* state flag */
        !            35:        unsigned char ntrans[TRANS + 2];
        !            36:        static unsigned char metaph[MAXMET + 1];
        !            37: 
        !            38:        /* clear work areas */
        !            39:        memset(ntrans, '\0', TRANS + 2);
        !            40:        memset(metaph, '\0', MAXMET + 1);
        !            41: 
        !            42:        /* Isolate word and make upper case */
        !            43:        for (n = ntrans + 1, n_end = ntrans + TRANS;
        !            44:             (c = *word++) && n < n_end;)
        !            45:                if (isalpha(c))
        !            46:                        *n++ = toupper(c);
        !            47:                else
        !            48:                        break;
        !            49: 
        !            50:        n_end = n;
        !            51:        n = ntrans + 1;
        !            52:        
        !            53:        /* process first character */
        !            54:        switch (*n) {
        !            55:        case 0:
        !            56:                return (n);     /* no word found */
        !            57: 
        !            58:        case 'P':
        !            59:        case 'G':
        !            60:        case 'K':
        !            61:                if ('N' == n[1])
        !            62:                        *n++ = '\0';
        !            63:                break;
        !            64: 
        !            65:        case 'A':
        !            66:                if ('E' == n[1])
        !            67:                        *n++ = '\0';
        !            68:                break;
        !            69: 
        !            70:        case 'W':
        !            71:                switch (n[1]) {
        !            72:                case 'H':
        !            73:                        n[1] = *n;
        !            74:                        *n++ = 'E';
        !            75:                        break;
        !            76:                case 'R':
        !            77:                        *n++ = 0;
        !            78:                }
        !            79:                break;
        !            80: 
        !            81:        case 'X':
        !            82:                *n = 'S';
        !            83:        }
        !            84: 
        !            85:        /* Process rest of word  SAY does continue */
        !            86:        KSflag = 0;
        !            87:        metaph_end = (Metaph = metaph) + MAXMET;
        !            88:        n_start = n;
        !            89:        for (; Metaph < metaph_end; n++) {
        !            90:                if (KSflag) {
        !            91:                        KSflag = 0;
        !            92:                        SAY(*n)
        !            93:                }
        !            94:                if (n >= n_end)
        !            95:                        break;
        !            96: 
        !            97:                /* Drop double letters except CC */
        !            98:                if (n[-1] == *n && *n != 'C')
        !            99:                        continue;
        !           100: 
        !           101:                /* check for FJLMNR or first letter vowel */
        !           102:                if (SAME(*n) || ((n == n_start) && VOWEL(*n)))
        !           103:                        SAY(*n)
        !           104: 
        !           105:                switch (*n) {
        !           106:                case 'B':
        !           107:                        if (n < n_end || n[-1] != 'M')
        !           108:                                SAY(*n)
        !           109:                        break;
        !           110: 
        !           111:                case 'C':
        !           112:                        if (n[-1] != 'S' || !FRONTV(n[1])) {
        !           113:                                if (n[1] == 'I' && n[2] == 'A')
        !           114:                                        SAY('X')
        !           115:                                if (FRONTV(n[1]))
        !           116:                                        SAY('S')
        !           117:                                if (n[1] == 'H')
        !           118:                                        if ((n == n_start && !VOWEL(n[2])) ||
        !           119:                                              n[-1] == 'S')
        !           120:                                                SAY('K')
        !           121:                                        else
        !           122:                                                SAY('X')
        !           123:                                else
        !           124:                                        SAY('K')
        !           125:                        }
        !           126:                        break;
        !           127: 
        !           128:                case 'D':
        !           129:                        SAY((n[1] == 'G' && FRONTV(n[2])) ? 'J' : 'T')
        !           130: 
        !           131:                case 'G':
        !           132:                        if ((n[1] != 'H' || VOWEL(n[2])) &&
        !           133:                            (n[1] != 'N' || ((n + 1) < n_end &&
        !           134:                            (n[2] != 'E' || n[3] != 'D'))) &&
        !           135:                            (n[-1] != 'D' || !FRONTV(n[1])))
        !           136:                                SAY((FRONTV(n[1]) && n[2] != 'G') ? 'J' : 'K')
        !           137:                        break;
        !           138: 
        !           139:                case 'H':
        !           140:                        if (!VARSON(n[-1]) && (!VOWEL(n[-1]) || VOWEL(n[1])))
        !           141:                                SAY('H')
        !           142:                        break;
        !           143: 
        !           144:                case 'K':
        !           145:                        if (n[-1] != 'C')
        !           146:                                SAY('K')
        !           147:                        break;
        !           148: 
        !           149:                case 'P':
        !           150:                        SAY(n[1] == 'H' ? 'F' : 'P')
        !           151: 
        !           152:                case 'Q':
        !           153:                        SAY('K')
        !           154: 
        !           155:                case 'S':
        !           156:                        if (n[1] == 'H' || (n[1] == 'I' && 
        !           157:                            (n[2] == 'O' || n[2] == 'A')))
        !           158:                                SAY('X')
        !           159:                        else
        !           160:                                SAY('S')
        !           161: 
        !           162:                case 'T':
        !           163:                        if (n[1] == 'I' &&
        !           164:                            (n[2] == 'O' || n[2] == 'A'))
        !           165:                                SAY('X')
        !           166:                        if (n[1] == 'H')
        !           167:                                SAY('O')
        !           168:                        if (n[1] != 'C' || n[2] == 'H')
        !           169:                                SAY('T')
        !           170:                        break;
        !           171: 
        !           172:                case 'V':
        !           173:                        SAY('F')
        !           174: 
        !           175:                case 'W':
        !           176:                        if(VOWEL(n[-1]))
        !           177:                                SAY(*n)
        !           178:                        break;
        !           179: 
        !           180:                case 'Y':
        !           181:                        if(!VOWEL(n[1]))
        !           182:                                SAY(*n)
        !           183:                        break;
        !           184: 
        !           185:                case 'X':
        !           186:                        if (n == n_start)
        !           187:                                SAY('S')
        !           188:                        KSflag = 1;
        !           189:                        SAY('K')
        !           190: 
        !           191:                case 'Z':
        !           192:                        SAY('S')
        !           193:                }
        !           194:        }
        !           195:        return (metaph);
        !           196: }
        !           197: 
        !           198: #ifdef TEST
        !           199: #include <misc.h>
        !           200: main()
        !           201: {
        !           202:        char buf[80];
        !           203: 
        !           204:        while (NULL != ask(buf, "string"))
        !           205:                printf("%s\n", metaphone(buf));
        !           206: }
        !           207: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.