Back to index

openldap  2.4.31
Defines | Functions | Variables
phonetic.c File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/socket.h>
#include <ac/time.h>
#include "slap.h"

Go to the source code of this file.

Defines

#define SLAPD_METAPHONE
#define iswordbreak(x)
#define MAXPHONEMELEN   4
#define vowel(x)   ((x) != '\0' && vsvfn[(x) - 'A'] & 1) /* AEIOU */
#define same(x)   ((x) != '\0' && vsvfn[(x) - 'A'] & 2) /* FJLMNR */
#define varson(x)   ((x) != '\0' && vsvfn[(x) - 'A'] & 4) /* CGPST */
#define frontv(x)   ((x) != '\0' && vsvfn[(x) - 'A'] & 8) /* EIY */
#define noghf(x)   ((x) != '\0' && vsvfn[(x) - 'A'] & 16) /* BDH */

Functions

char * phonetic (char *Word)

Variables

static const char vsvfn [26]

Define Documentation

#define frontv (   x)    ((x) != '\0' && vsvfn[(x) - 'A'] & 8) /* EIY */

Definition at line 209 of file phonetic.c.

#define iswordbreak (   x)
Value:
(!isascii(x) || isspace((unsigned char) (x)) || \
                      ispunct((unsigned char) (x)) || \
                      isdigit((unsigned char) (x)) || (x) == '\0')

Definition at line 42 of file phonetic.c.

#define MAXPHONEMELEN   4

Definition at line 105 of file phonetic.c.

#define noghf (   x)    ((x) != '\0' && vsvfn[(x) - 'A'] & 16) /* BDH */

Definition at line 210 of file phonetic.c.

#define same (   x)    ((x) != '\0' && vsvfn[(x) - 'A'] & 2) /* FJLMNR */

Definition at line 207 of file phonetic.c.

#define SLAPD_METAPHONE

Definition at line 39 of file phonetic.c.

#define varson (   x)    ((x) != '\0' && vsvfn[(x) - 'A'] & 4) /* CGPST */

Definition at line 208 of file phonetic.c.

#define vowel (   x)    ((x) != '\0' && vsvfn[(x) - 'A'] & 1) /* AEIOU */

Definition at line 206 of file phonetic.c.


Function Documentation

char* phonetic ( char *  Word)

Definition at line 213 of file phonetic.c.

{
       char           *n, *n_start, *n_end;      /* pointers to string */
       char           *metaph_end; /* pointers to metaph */
       char            ntrans[40]; /* word with uppercase letters */
       int             KSflag;     /* state flag for X -> KS */
       char          buf[MAXPHONEMELEN + 2];
       char          *Metaph;

       /*
        * Copy Word to internal buffer, dropping non-alphabetic characters
        * and converting to upper case
        */

       for (n = ntrans + 4, n_end = ntrans + 35; !iswordbreak( *Word ) &&
           n < n_end; Word++) {
              if (isalpha((unsigned char)*Word))
                     *n++ = TOUPPER((unsigned char)*Word);
       }
       Metaph = buf;
       *Metaph = '\0';
       if (n == ntrans + 4) {
              return( ch_strdup( buf ) );        /* Return if null */
       }
       n_end = n;           /* Set n_end to end of string */

       /* ntrans[0] will always be == 0 */
       ntrans[0] = '\0';
       ntrans[1] = '\0';
       ntrans[2] = '\0';
       ntrans[3] = '\0';
       *n++ = 0;
       *n++ = 0;
       *n++ = 0;
       *n = 0;                     /* Pad with nulls */
       n = ntrans + 4;             /* Assign pointer to start */

       /* Check for PN, KN, GN, AE, WR, WH, and X at start */
       switch (*n) {
       case 'P':
       case 'K':
       case 'G':
              /* 'PN', 'KN', 'GN' becomes 'N' */
              if (*(n + 1) == 'N')
                     *n++ = 0;
              break;
       case 'A':
              /* 'AE' becomes 'E' */
              if (*(n + 1) == 'E')
                     *n++ = 0;
              break;
       case 'W':
              /* 'WR' becomes 'R', and 'WH' to 'H' */
              if (*(n + 1) == 'R')
                     *n++ = 0;
              else if (*(n + 1) == 'H') {
                     *(n + 1) = *n;
                     *n++ = 0;
              }
              break;
       case 'X':
              /* 'X' becomes 'S' */
              *n = 'S';
              break;
       }

       /*
        * Now, loop step through string, stopping at end of string or when
        * the computed 'metaph' is MAXPHONEMELEN characters long
        */

       KSflag = 0;          /* state flag for KS translation */
       for (metaph_end = Metaph + MAXPHONEMELEN, n_start = n;
            n <= n_end && Metaph < metaph_end; n++) {
              if (KSflag) {
                     KSflag = 0;
                     *Metaph++ = 'S';
              } else {
                     /* Drop duplicates except for CC */
                     if (*(n - 1) == *n && *n != 'C')
                            continue;
                     /* Check for F J L M N R or first letter vowel */
                     if (same(*n) || (n == n_start && vowel(*n)))
                            *Metaph++ = *n;
                     else
                            switch (*n) {
                            case 'B':

                                   /*
                                    * B unless in -MB
                                    */
                                   if (n == (n_end - 1) && *(n - 1) != 'M')
                                          *Metaph++ = *n;
                                   break;
                            case 'C':

                                   /*
                                    * X if in -CIA-, -CH- else S if in
                                    * -CI-, -CE-, -CY- else dropped if
                                    * in -SCI-, -SCE-, -SCY- else K
                                    */
                                   if (*(n - 1) != 'S' || !frontv(*(n + 1))) {
                                          if (*(n + 1) == 'I' && *(n + 2) == 'A')
                                                 *Metaph++ = 'X';
                                          else if (frontv(*(n + 1)))
                                                 *Metaph++ = 'S';
                                          else if (*(n + 1) == 'H')
                                                 *Metaph++ = ((n == n_start && !vowel(*(n + 2)))
                                                  || *(n - 1) == 'S')
                                                     ? (char) 'K' : (char) 'X';
                                          else
                                                 *Metaph++ = 'K';
                                   }
                                   break;
                            case 'D':

                                   /*
                                    * J if in DGE or DGI or DGY else T
                                    */
                                   *Metaph++ = (*(n + 1) == 'G' && frontv(*(n + 2)))
                                       ? (char) 'J' : (char) 'T';
                                   break;
                            case 'G':

                                   /*
                                    * F if in -GH and not B--GH, D--GH,
                                    * -H--GH, -H---GH else dropped if
                                    * -GNED, -GN, -DGE-, -DGI-, -DGY-
                                    * else J if in -GE-, -GI-, -GY- and
                                    * not GG else K
                                    */
                                   if ((*(n + 1) != 'J' || vowel(*(n + 2))) &&
                                       (*(n + 1) != 'N' || ((n + 1) < n_end &&
                                                         (*(n + 2) != 'E' || *(n + 3) != 'D'))) &&
                                       (*(n - 1) != 'D' || !frontv(*(n + 1))))
                                          *Metaph++ = (frontv(*(n + 1)) &&
                                                      *(n + 2) != 'G') ? (char) 'G' : (char) 'K';
                                   else if (*(n + 1) == 'H' && !noghf(*(n - 3)) &&
                                           *(n - 4) != 'H')
                                          *Metaph++ = 'F';
                                   break;
                            case 'H':

                                   /*
                                    * H if before a vowel and not after
                                    * C, G, P, S, T else dropped
                                    */
                                   if (!varson(*(n - 1)) && (!vowel(*(n - 1)) ||
                                                    vowel(*(n + 1))))
                                          *Metaph++ = 'H';
                                   break;
                            case 'K':

                                   /*
                                    * dropped if after C else K
                                    */
                                   if (*(n - 1) != 'C')
                                          *Metaph++ = 'K';
                                   break;
                            case 'P':

                                   /*
                                    * F if before H, else P
                                    */
                                   *Metaph++ = *(n + 1) == 'H' ?
                                       (char) 'F' : (char) 'P';
                                   break;
                            case 'Q':

                                   /*
                                    * K
                                    */
                                   *Metaph++ = 'K';
                                   break;
                            case 'S':

                                   /*
                                    * X in -SH-, -SIO- or -SIA- else S
                                    */
                                   *Metaph++ = (*(n + 1) == 'H' ||
                                               (*(n + 1) == 'I' && (*(n + 2) == 'O' ||
                                                   *(n + 2) == 'A')))
                                       ? (char) 'X' : (char) 'S';
                                   break;
                            case 'T':

                                   /*
                                    * X in -TIA- or -TIO- else 0 (zero)
                                    * before H else dropped if in -TCH-
                                    * else T
                                    */
                                   if (*(n + 1) == 'I' && (*(n + 2) == 'O' ||
                                                    *(n + 2) == 'A'))
                                          *Metaph++ = 'X';
                                   else if (*(n + 1) == 'H')
                                          *Metaph++ = '0';
                                   else if (*(n + 1) != 'C' || *(n + 2) != 'H')
                                          *Metaph++ = 'T';
                                   break;
                            case 'V':

                                   /*
                                    * F
                                    */
                                   *Metaph++ = 'F';
                                   break;
                            case 'W':

                                   /*
                                    * W after a vowel, else dropped
                                    */
                            case 'Y':

                                   /*
                                    * Y unless followed by a vowel
                                    */
                                   if (vowel(*(n + 1)))
                                          *Metaph++ = *n;
                                   break;
                            case 'X':

                                   /*
                                    * KS
                                    */
                                   if (n == n_start)
                                          *Metaph++ = 'S';
                                   else {
                                          *Metaph++ = 'K';     /* Insert K, then S */
                                          KSflag = 1;
                                   }
                                   break;
                            case 'Z':

                                   /*
                                    * S
                                    */
                                   *Metaph++ = 'S';
                                   break;
                            }
              }
       }

       *Metaph = 0;         /* Null terminate */
       return( ch_strdup( buf ) );
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const char vsvfn[26] [static]
Initial value:
 {
          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}

Definition at line 199 of file phonetic.c.