From decwrl!wyse!mips!apple!bridge2!jarthur!uunet!allbery Wed May 16 10:16:14 PDT 1990
Article 1576 of comp.sources.misc:
Path: decwrl!wyse!mips!apple!bridge2!jarthur!uunet!allbery
From: williams@mimsy.umd.edu (Jim Williams)
Newsgroups: comp.sources.misc
Subject: v12i098: Telephone number to word conversion
Message-ID: <88891@uunet.UU.NET>
Date: 14 May 90 23:18:38 GMT
Sender: allbery@uunet.UU.NET
Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742
Lines: 369
Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)

Posting-number: Volume 12, Issue 98
Submitted-by: williams@mimsy.umd.edu (Jim Williams)
Archive-name: telewords/part01

This is a share file of telewords and telenum.  Telewords will map
a telephone number into all the corresponding "words", using the
standard mapping found on American phones (2=ABC, 3=DEF, etc.).  Telenum
will do the opposite mapping, taking a string of letters and printing
what the corresponding phone number would be.  Both programs also supports
alternate mappings.  See the man pages.

Enjoy!
Jim Williams

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	telefun.1
#	telenum.c
#	telewords.c
# This archive created: Sun Jan 28 16:56:44 1990
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
all:	telewords telenum

telewords: telewords.c
	cc -s -O telewords.c -o telewords

telenum: telenum.c
	cc -s -O telenum.c -o telenum
SHAR_EOF
fi # end of overwriting check
if test -f 'telefun.1'
then
	echo shar: will not over-write existing file "'telefun.1'"
else
cat << \SHAR_EOF > 'telefun.1'
.TH TELEFUN 1
.UC 4
.SH NAME
telewords, telenum \- convert telephone numbers into words and vice versa
.SH SYNOPSIS
telewords [-\fId\fPc...] ... number
.br
telenum [-\fId\fPc...] ...  string ...
.SH DESCRIPTION
\fITelewords\fP takes a telephone number as the single input argument
and outputs, one per line, all of the equivalent "words",
in the hope that one of them will be a real word, or at least
pronounceable.  The digits 0 and 1,  which don't have corresponding letters,
are printed as themselves.  Command line options allow you to change
the string of characters into which any digit is mapped.
This is helpful with some automatic teller machine keypads that
put q and z on the 1 key.   (Why doesn't the phone company do that?)
The given phone number can have a arbitrary number of digits, and non-digits
are ignored: '(301) 555-1212' is the same as '3015551212' (provided the
space is properly quoted to the shell).
.PP
\fITelenum\fP performs the reverse transform.  Given a string of alphabetic
characters (either case) it will print the equivalent phone number.
The same remapping, using the same syntax as \fItelewords\fP can be used.
.SH OPTIONS  
The -\fId\fP option allows you to change the mapping for any digit. 
The \fId\fP represents any digit.  This digit is
followed by a string of characters which will be used as the characters
into which that digit maps.  Thus, to cause 1 to map to 'q' and 'z'
use the command 
.sp
telewords -1qz 555-1212
.sp
As many -\fId\fP options can be given as desired, allowing the complete map
to be redefined.  If a -\fId\fP option is given without a following string
then mapping for that digit will be turned off, and the input digit will
print as itself.  Thus, the default behaviour 
is as if the command had been given with options -0 and -1.
.SH DIAGNOSTICS
None.
.SH BUGS
There is no easy way in the current implementation to allow a digit
to map to a string instead of just a character.  This would allow, for
example, 0 to map to "oper".
(I once knew a person whose number spelled INoperTUNE!)
.SH AUTHOR
.nf
James W. Williams
williams \@ cs.umd.edu
.fi
SHAR_EOF
fi # end of overwriting check
if test -f 'telenum.c'
then
	echo shar: will not over-write existing file "'telenum.c'"
else
cat << \SHAR_EOF > 'telenum.c'
/*
   Telenum changes each of its string arguments into the corresponding
   telephone number.  There is no restriction on the length of the string
   and input letters can be of either case.
   The mapping used is the standard American mapping, unless the -<digit>
   options are used to change it.  Letters which do not map to any digit
   are printed as themselves.  This is the default for q and z.
  
   Written by James W. Williams
   williams@cs.umd.edu
   Last hacked on 28 January 1990.
  	This really ought to be ASNIfied at some point...
*/

#include <stdio.h>
#include <ctype.h>

#define USAGE	fprintf(stderr, "\tusage: telenum [-<digit>c...] ...  word ...\n")

/* table is used to map an input letter to the corresponding digit. */
unsigned char	table[256];

initTable()
{
	int i;

	/* first make each character map to itself, then set up
	   default mapping
	*/
	for (i=0; i < 256; i++) table[i] = i;

	table['A'] = table['a'] = '2';
	table['B'] = table['b'] = '2';
	table['C'] = table['c'] = '2';
	table['D'] = table['d'] = '3';
	table['E'] = table['e'] = '3';
	table['F'] = table['f'] = '3';
	table['G'] = table['g'] = '4';
	table['H'] = table['h'] = '4';
	table['I'] = table['i'] = '4';
	table['J'] = table['j'] = '5';
	table['K'] = table['k'] = '5';
	table['L'] = table['l'] = '5';
	table['M'] = table['m'] = '6';
	table['N'] = table['n'] = '6';
	table['O'] = table['o'] = '6';
	table['P'] = table['p'] = '7';
	table['R'] = table['r'] = '7';
	table['S'] = table['s'] = '7';
	table['T'] = table['t'] = '8';
	table['U'] = table['u'] = '8';
	table['V'] = table['v'] = '8';
	table['W'] = table['w'] = '9';
	table['X'] = table['x'] = '9';
	table['Y'] = table['y'] = '9';
}

int
main(argc, argv)
int argc;
char **argv;
{
	int i;
	char *argptr, *cp, optChar, *currentStr;

        if (argc < 2) {
		USAGE;
		exit(1);
        }

	initTable();

	/* process arguments. */
	argv++; argc--;
	while (**argv == '-') {
		argptr = *argv;
		optChar = argptr[1];
		switch (optChar) {
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			cp = &argptr[2];
			while (*cp != '\0') {
				table[*cp] = optChar;
				if (isupper(*cp))
					table[tolower(*cp)] = optChar;
				else if (islower(*cp))
					table[toupper(*cp)] = optChar;
				cp++;
			}
			break;
		default: /* unknown option */
			fprintf(stderr, "Unknown option letter %c.\n", argptr[1]);
		}
		argv++; argc--;
	}

	if (argc < 1) {
		fprintf(stderr, "Missing argument.\n");
		USAGE;
		exit (1);
	}

	while (*argv != NULL) {
		currentStr = *argv++;
		while (*currentStr) putchar(table[*currentStr++]);
		putchar('\n');
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'telewords.c'
then
	echo shar: will not over-write existing file "'telewords.c'"
else
cat << \SHAR_EOF > 'telewords.c'
/*
   Telewords takes a telephone number as the single input argument
   and outputs, one per line, all of the equivalent character strings,
   in the hope that one of them will be a real word, or at least
   pronouncable..  The digits 0 and 1, * which don't have letters,
   are printed as themselves.  Command line options allow you to change
   the string of characters into which each digit is mapped.
   This is helpful for selecting a PIN number on automatic teller machines
   that put q and z on the 1 (Why doesn't the phone company do that?).
   The phone number can have a arbitrary number of digits, and non-digits
   are ignored: '(301) 555-1212' is the same as '3015551212', provided the
   space is properly quoted to the shell.
  
   Written by James W. Williams
   williams@cs.umd.edu
   Last hacked on 28 January 1990.
  	This really ought to be ASNIfied at some point...
*/

#include <stdio.h>
#include <ctype.h>

#define USAGE	fprintf(stderr, "\tusage: telewords [-<digit>c...] ...  telephone-number\n")

char	*table[]   = {	"0",	/* mapping table for input digits. */
			"1",	/* The -<digit> options can modify */
			"abc",	/* this table. */
			"def",
			"ghi",
			"jkl",
			"mno",
			"prs",
			"tuv",
			"wxy"
			},
	teleword[128];  	/* buffer to hold output word. */


/*
 * A recursive subroutine to do the dirty work.
 */

void
doLetter(numberString, currentLetter)
char	*numberString,		/* pointer into input phone number string */
	*currentLetter;	/* pointer into the output word string */
{

	register char	ch, *mapstring;

	/* get the string of characters to use for the leading digit
	   in numberString and iterate over each character.  currentLetter
	   points to the position in teleword into which to stick each
	   possible mapping of the current digit.
	 */
	mapstring = table[*numberString-'0'];
	while (ch = *mapstring++) {
		*currentLetter = ch;
		if (*(numberString+1) == '\0') {
			printf("%s\n", teleword);
		}
		else {
			doLetter(numberString+1, currentLetter+1);
		}
	}
}

int
main(argc, argv)
int argc;
char **argv;
{
	int i;
	char *argptr, *cp = teleword, *to, *from;

        if (argc < 2) {
		USAGE;
		exit(1);
        }

	/* process arguments */
	argv++; argc--;
	while (**argv == '-') {
		argptr = *argv;
		switch (argptr[1]) {
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			if (argptr[2] == '\0') {
				/* null string means map this digit 
				 * into itself.
				 */
				table[argptr[1]-'0'][0] = argptr[1];
				table[argptr[1]-'0'][1] = '\0';
			}
			else {
				/* the map for this digit is the string
				 * following the -<digit>
				 */
				table[argptr[1]-'0'] = &argptr[2];
			}
			break;
		default: /* unknown option */
			fprintf(stderr, "Unknown option letter %c.\n", argptr[1]);
		}
		argv++; argc--;
	}

	if (argc > 1) {
		fprintf(stderr, "Too many arguments!\n");
		USAGE;
		exit (1);
	}
	else if (argc < 1) {
		fprintf(stderr, "Missing telephone number.\n");
		USAGE;
		exit (1);
	}

	/* squeeze out all non-digits from argv[0].  This simplifies doLetter.
	 */
	to = from = argv[0];
	while (*from != '\0') {
		if (isdigit(*from)) {
			*to++ = *from++;
		}
		else {
			from++;
		}
	}
	*to = '\0';

	doLetter(argv[0], teleword);
}
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0


