#ifndef soundex_c
#define soundex_c 1

#ifdef LIB_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif


/* isalpha & toupper; define your own if you don't have ctype.h */
#include <ctype.h>

/*

    File:    soundex.c
    Authors: Jonathan Leffler
    Purpose: Approximate string equality test.
    Functions exported:  soundex
    Internal functions:  nsoundex

Description:

 There are umpteen soundexes around. At least this one is commented...
 (Actually I'd prefer one which understood ph/f and Mac/Mc as special
  cases; short of a proper phonetic alg such as I'm currently developing)
 See below for description:

*/

/*
**      SOUNDEX CODING
**
**      Rules:
**      1.      Retain the first letter; ignore non-alphabetic characters.
**      2.      Replace second and subsequent characters by a group code.
**              Group   Letters
**              1               BFPV
**              2               CGJKSXZ
**              3               DT
**              4               L
**              5               MN
**              6               R
**      3.      Do not repeat digits
**      4.      Truncate or ser-pad to 4-character result.
**
**      Originally formatted with tabstops set at 4 spaces -- you were warned!
**
**      Code by: Jonathan Leffler (john@sphinx.co.uk)
**      This code is shareware -- I wrote it; you can have it for free
**      if you supply it to anyone else who wants it for free.
**
**      BUGS: Assumes 7-ASCII; fails on ISO Latin1
*/

static char lookup[] = {
        '0',    /* A */        '1',    /* B */        '2',    /* C */
        '3',    /* D */        '0',    /* E */        '1',    /* F */
        '2',    /* G */        '0',    /* H */        '0',    /* I */
        '2',    /* J */        '2',    /* K */        '4',    /* L */
        '5',    /* M */        '5',    /* N */        '0',    /* O */
        '1',    /* P */        '0',    /* Q */        '6',    /* R */
        '2',    /* S */        '3',    /* T */        '0',    /* U */
        '1',    /* V */        '0',    /* W */        '2',    /* X */
        '0',    /* Y */        '2'     /* Z */
};

/* Soundex for arbitrary number of characters of information */
#define MAX_SOUNDEX_LEN 10

static char *
#ifdef PROTOTYPES
nsoundex(char *str, int n)
#else
nsoundex(str, n)
char *str;                   /* In: String to be converted */
int n;                       /* In: Number of characters in result string */
#endif
{
  static char buff[MAX_SOUNDEX_LEN];
  register char *s;
  register char *t;
  char c;
  char l;

  if (n <= 0) n = 4;  /* Default */
  if (n > sizeof(buff) - 1)  n = sizeof(buff) - 1;
  t = &buff[0];

  for (s = str; ((c = *s) != '\0') && t < &buff[n]; s++) {
    if (!isalpha(c)) continue;
    c = toupper(c);
    if (t == &buff[0]) {
      l = *t++ = c;
      continue;
    }
    c = lookup[c-'A'];  /* Fails on any alpha not in 'a'..'z' */
    if (c != '0' && c != l) l = *t++ = c;
  }
  while (t < &buff[n]) *t++ = '0'; *t = '\0';
  return(&buff[0]);
}

/* Normal external interface */
char *
#ifdef PROTOTYPES
soundex(char *str)
#else
soundex(str)
char *str;
#endif
{
  return(nsoundex(str, 4));  /* vary this? - try 5 or 6? */
}
#endif /* soundex_c */


