[net.sources] Trying to Talk

banan@butler.UUCP (Mohsen) (01/17/86)

Ipa2sc is a filter that converts International Phonetic Alphabet
code to Votrax SC01 phoneme codes.

Do what you always do with a shar file and read readme.

# The rest of this file is a shell script which will extract:
# readme makefile mkp pdtbat getopt.h mbstd.h mbsup.h msc3sup.h rule.h string.h arg_str.c bsearch.c cantopen.c getopt.c ipa2sc.c nl_elim.c prs_str.c sc_rules.c setmode.c strupr.c x_ipa2sc.c bdpdt.bat mkpdt.bat
echo x - readme
cat >readme <<'!Funky!Stuff!'
BACKGROUND:

Last April, John A. Wasser posted an English to International
Phonetic Alphabet (IPA) program. Let me call John's program
eng2ipa.  eng2ipa is based on a navy research report done
in 1976 (See sc_rules.c). My compliments to Mr. Wasser for eng2ipa.

What is to follow (ipa2sc) is designed to work with the output
of eng2ipa. It converts IPA codes to Votrax SC01 phoneme codes.
The structure of the code is very similar to that of eng2ipa.
The tables for the conversion come from the same navy research report.
Typical usage would be: "eng2ipa < file.eng | ipa2sc".

The code has been minimally tested on BSD4.2 and the IBM-PC (using
MSC 3.0 compiler).

Ipa2sc is part of a bigger program that I have been working on.
I have developed a simple board for the IBM-PC based around the 
Votrax Chip that takes the phoneme codes and talks (tries to talk).
The code to support SC01&IPA local dictionaries will also be posted
later.
Should you be interested in all of this or the talking board, 
e-mail me a note or call me at home (206)821-8560.

Also, please e-mail me any bugs you find or any enhancements you make.


SOFTWARE ORGANIZATION:

Ipa2sc is part of a bigger program. That is why the structure of all 
of this may come across as somewhat funny.
mkp is a pre-processor for make. 
To recreate ipa2sc under unix. Make mkp executable and run it.

With an IBM-PC, simply run mkpdt.bat and bdpdt.bat in that order.
mkpdt.bat and bdpdt.bat have been created by pdtbat using the makefile.

bsearch and getopt are not mine, but the rest is.
And Naturally:
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
!Funky!Stuff!
echo x - makefile
cat >makefile <<'!Funky!Stuff!'
# ::::::::::::::::::::::::::::::::::::::::::::::::::
#
#  File: Makefile
#  Description: Makefile for creating 
#
#  This module is the proprietary property of the
#  Teltone Corporation, copyright 1985,
#  all rights reserved.
#
#
#  Audit Trail:  $Log:$
#
#  $Header: $
#
# ::::::::::::::::::::::::::::::::::::::::::::::::::

MAKEFILE = makefile
PDT = ipa2sc
PUB_H = 
LCL_H = getopt.h mbstd.h mbsup.h msc3sup.h rule.h string.h
LCL_C = ipa2sc.c arg_str.c cantopen.c getopt.c nl_elim.c prs_str.c \
	setmode.c strupr.c bsearch.c x_ipa2sc.c sc_rules.c
C_SRC =  ${PUB_H} ${LCL_H} ${LCL_C}
OBJS = ipa2sc.o arg_str.o cantopen.o getopt.o nl_elim.o prs_str.o \
	setmode.o strupr.o bsearch.o  x_ipa2sc.o sc_rules.o
#
LOADER = ld

#
$(PDT):       $(OBJS) 
	${LOADER} -M -X -o ${PDT} /lib/crt0.o ${OBJS} -lg -lc
#
e_make:
	@echo ${MAKEFILE}
e_pub_h:
	@echo ${PUB_H}
e_lcl_h:
	@echo ${LCL_H}
e_lcl_c:
	@echo ${LCL_C}
e_c_src:
	@echo ${C_SRC}
e_objs:
	@echo ${OBJS}
e_libs:
	@echo ${LIBS}
e_pdt:
	@echo ${PDT}
#
ctags:  ${LCL_C}
		$(CTAGS) $(LCL_C)
#
lint:
		$(LINT) ${LFLAGS} $(LCL_C)

depend:
		mv Makefile Makefile.old
		sed -n '1,/^# MAKE DEPEND/p' Makefile.old > Makefile
		/we/sw/cds/avail/common/bin/mkdp -m $(CFILES) >> Makefile

# Do not change anything these comments or it will
# be lost by the next "make depend"
# MAKE DEPEND
!Funky!Stuff!
echo x - mkp
cat >mkp <<'!Funky!Stuff!'
#!/bin/csh -f
# This is the make pre-processor program written in the 'C' shell.
#
#   mkp defines a group of parameters and passes them to make.
#   SWITCHES:
#       -f <filename>
#           source <filename. priore to invoking make.
#           If -f is not present and .mkprc exists in the current directory
#           it is sourced. Otherwise if .mkprc exists in the home directory
#           it is sourced.
#       -- 
#           argument parsing is terminated remainder of command line is passed
#           to make as is.
#
set MKPFILE=.mkprc
set mkpname=$0
set mkpname=$mkpname:t
# ### VISIBLE MAKE TOOLS
set MAKE=make
set CC=cc
set AS="as -"
set LK=""
set LD=""
set LINT="lint -u"
set REMOVE="rm -f"
set CTAGS="ctags -w"
# Internal parametrs
set BASE = ~/sw
set COMMON = ${BASE}/common
set COMMON_H_PATH = ${COMMON}/header
#set INCFLAGS = "-I. -I${COMMON_H_PATH} -I${BASE}/cd/header"
set INCFLAGS = "-I. "
# ### VISIBLE MAKE PARAMETERS
set CFLAGS = "-gx ${INCFLAGS} -DBSD4_2"
set LINTFLAGS = "${INCFLAGS}"
set TARGETS
# MKP FLAGS
set S_MKPFILE
# 
umask 002
#
#
# Gather command line options
#
foreach i ($*)
    switch ($1)
    case -f:
        shift argv
        set S_MKPFILE=$1
        breaksw
    case --:
        shift argv
        break
    default:
        break
        breaksw
    endsw
    shift argv
end
#
#
#
#
if ("$S_MKPFILE" != "") then
    set MKPFILE = "$S_MKPFILE"
    source $MKPFILE
else if (-f $MKPFILE) then
    source $MKPFILE
else if (-f $HOME/$MKPFILE) then
    source $HOME/$MKPFILE
endif
#
set TARGETS="$*"
#
$MAKE  "CC=$CC" "AS=$AS" \
    "CFLAGS=$CFLAGS" "LINTFLAGS=$LINTFLAGS" \
    "LINT=$LINT"  \
    "REMOVE=$REMOVE" "CTAGS=$CTAGS" \
    $TARGETS
set ret=$status
if ("$ret" != "0") then
    exit 1
endif
exit 0
!Funky!Stuff!
echo x - pdtbat
cat >pdtbat <<'!Funky!Stuff!'
#
rm -f mkpdt.bat
rm -f bdpdt.bat
set lcl_c = `make e_lcl_c`
set pdt = `make e_pdt`
set olibs = (`make e_libs`)
set tlibs = ()
set libs = ()
while ($#olibs > 0)
	set tlibs = ($tlibs $olibs[1]:t)
	shift olibs
end
while ($#tlibs > 0)
	set libs = ($libs $tlibs[1]:r.lib)
	shift tlibs
end
foreach i ($lcl_c)
echo cl -c -DMSDOS $i >> mkpdt.bat
end
echo -n "cl -o $pdt:r " >> bdpdt.bat
foreach i ($lcl_c)
echo -n "$i:r " >> bdpdt.bat
end
echo -n " -link " >> bdpdt.bat
echo -n " $libs " >> bdpdt.bat
echo  >> bdpdt.bat
exit 0

!Funky!Stuff!
echo x - getopt.h
cat >getopt.h <<'!Funky!Stuff!'
#ifndef GETOPT_H
#define GETOPT_H

extern char *optarg;
extern int optind;
extern int getopt();

#endif GETOPT_H
!Funky!Stuff!
echo x - mbstd.h
cat >mbstd.h <<'!Funky!Stuff!'
#ifndef MBSTD_H
#define MBSTD_H

#define CHAR    char
#define SCHAR   char
typedef unsigned char  UCHAR;

#define INT     int
#define SINT    int
typedef unsigned int UINT;

#define SHORT   short
#define SSHORT  short
typedef unsigned short USHORT;

#define LONG    long
#define SLONG   long
typedef unsigned long ULONG;

#define DOUBLE  double

#define BOOL    int
#define SUCC_FAIL   int 
#ifndef VOID
#define VOID    void
#endif

#define STATIC  static      /* Names not needed outside this src module  */

#define LOCAL               /* Names not needed outside this software module */
#define LCL_XTRN extern     /* Names defines within this software module */

#define PUBLIC              /* Names needed outside this software module */
#define EXTERN  extern      /* Names defined outside this software module */

#define TRUE    1
#define FALSE   0

#define SUCCESS 0
#define FAIL    (-1)

#define OOPS()  fprintf(stderr,"OOPS: file %s, line %d\n", __FILE__, __LINE__);

#endif MBSTD_H
!Funky!Stuff!
echo x - mbsup.h
cat >mbsup.h <<'!Funky!Stuff!'
#ifndef MBSUP_H
#define MBSUP_H

#include "mbstd.h"

extern int str2flds();
extern int arg_str();
extern char prs_str();
extern VOID cant_open();
extern VOID nl_elim();

#endif MBSUP_H
!Funky!Stuff!
echo x - msc3sup.h
cat >msc3sup.h <<'!Funky!Stuff!'
#ifndef MSC3SUP_H
#define MSC3SUP_H

#ifdef unix
#define O_TEXT   0x4000
#define O_BINARY 0x8000
#endif

extern int setmode();
extern char * bsearch();

#endif MSC3SUP_H
!Funky!Stuff!
echo x - rule.h
cat >rule.h <<'!Funky!Stuff!'
/*+
 * File: 
 * Description:
 *
 *
 * $Header$
 *
 * Audit Trail:  $Log$
 *
-*/

#ifndef RULE_H
#define RULE_H


typedef struct {
    CHAR * left;
    CHAR * match;
    CHAR * right;
    CHAR * out;
} RULE;


/* Context definitions */
static char Anything[] = "";    /* No context requirement */
static char Nothing[] = " ";    /* Context is beginning or end of word */

/* Phoneme definitions */
static char Pause[] = " ";  /* Short silence */
static char Silent[] = "";  /* No phonemes */

#define E_O_RULE    ((CHAR *) 0)
 
#endif
!Funky!Stuff!
echo x - string.h
cat >string.h <<'!Funky!Stuff!'
#ifndef STRING_H
#define STRING_H

#ifdef BSD4_2
#define strchr index
#include <strings.h>
extern char * strlwr();
extern char * strupr();
extern char * strdup();
#endif

#endif STRING_H
!Funky!Stuff!
echo x - arg_str.c
cat >arg_str.c <<'!Funky!Stuff!'
/*+
 * File: 
 * Description:
 *
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log$
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header$";
#endif

#include "mbstd.h"



/*<
 * Function: str2flds
 * Description:
 *  Gets an array of arguments from a string
 *  Returned Value:
 *      Number of arguments detected.
 *
 * 
>*/
PUBLIC int 
str2flds(p_str, flds, maxflds, seps)
char **p_str;
char *flds[];     /* Where to put the parsed fields */
int maxflds;     /* Maximum number of arguments expected */
char * seps;
{
    int argc;
    char  * str;
    char prs_str();
    char sep_fnd;
    
    str = *p_str;
    argc  = 0;
    do {
        sep_fnd = prs_str(p_str, str, seps);
        flds[argc++] = str;
        str = *p_str;
    } while ((argc < maxflds) && sep_fnd);
    
    return argc;
}



/*<
 * Function: arg_str
 * Description:
 *  Gets an array of arguments from a string
 *  Returned Value:
 *      Number of arguments detected.
 *
 * 
>*/
PUBLIC int 
arg_str(p_str, argv, maxarg)
char **p_str;
char *argv[];     /* pointer to an array of strings containing the arguments */
int maxarg;     /* Maximum number of arguments expected */
{
    static char blank_sep[] = " ";
#if 0
    int argc;
    char  * str;
    char prs_str();
    char sep_fnd;
    
    str = *p_str;
    argc  = 0;
    do {
        sep_fnd = prs_str(p_str, str, blank_sep);
        argv[argc++] = str;
        str = *p_str;
    } while ((argc < maxarg) && sep_fnd);
    
    return argc;
#endif
    return (str2flds(p_str, argv, maxarg, blank_sep));
}

!Funky!Stuff!
echo x - bsearch.c
cat >bsearch.c <<'!Funky!Stuff!'
char    *bsearch(key, base, nelem, width, fcmp)
    char    *key;
    char    *base;
    register int    nelem;
    int width;
    int (*fcmp)();
    {
    char    *kmin, *probe;
    int i, j;

    kmin = base;
    while   (nelem > 0){
        i = nelem >> 1;
        probe = kmin + i * width;
        j = (*fcmp)(key, probe);
        if  (j == 0)
            return(probe);
        else if (j < 0)
            nelem = i;
        else    {
            kmin = probe + width;
            nelem = nelem - i - 1;
            }
        }
    return(0);
    }
!Funky!Stuff!
echo x - cantopen.c
cat >cantopen.c <<'!Funky!Stuff!'
#include "mbstd.h"
#include <stdio.h>

PUBLIC VOID
cant_open (prog_name,filename)
char * prog_name;
char * filename;
{
    fprintf (stderr, "%s :can not open %s \n", prog_name, filename);
} 

!Funky!Stuff!
echo x - getopt.c
cat >getopt.c <<'!Funky!Stuff!'
/*
 * getopt - get option letter from argv
 */

#include <stdio.h>
#include <string.h>

char    *optarg;    /* Global argument pointer. */
int optind = 0; /* Global argv index. */

static char *scan = NULL;   /* Private scan pointer. */


int
getopt(argc, argv, optstring)
int argc;
char *argv[];
char *optstring;
{
    register char c;
    register char *place;

    optarg = NULL;

    if (scan == NULL || *scan == '\0') {
        if (optind == 0)
            optind++;
    
        if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
            return(EOF);
        if (strcmp(argv[optind], "--")==0) {
            optind++;
            return(EOF);
        }
    
        scan = argv[optind]+1;
        optind++;
    }

    c = *scan++;
    place = strchr(optstring, c);

    if (place == NULL || c == ':') {
        fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
        return('?');
    }

    place++;
    if (*place == ':') {
        if (*scan != '\0') {
            optarg = scan;
            scan = NULL;
        } else if (optind < argc) {
            optarg = argv[optind];
            optind++;
        } else {
            fprintf(stderr, "%s: -%c argument missing\n", argv[0], c);
            return('?');
        }
    }

    return(c);
}
!Funky!Stuff!
echo x - ipa2sc.c
cat >ipa2sc.c <<'!Funky!Stuff!'
/*+
 * File: ipa2sc
 * Description:
 *  ipa2sc is a filter.
 *  ipa2sc processes i_files or the standard input.
 *  ipa2sc writes to o_file or standard output.
 *
 *  
 * Usages:
 *  ipa2sc [-t] [-p] [-o] <o_file> <i_files>
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log:  dosb2t.c,v $
 * Revision 1.1  85/08/28  08:38:24  mohsen
 * original posting to the net
 * 
 * 
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header: dosb2t.c,v 1.1 85/08/28 08:38:24 mohsen Exp $";
#endif

/* #includes */
#include "mbstd.h"
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#ifdef BSD4_2
#include "msc3sup.h"
#endif
#include "getopt.h"
 
/* #defines */

/* external variables */

/* referenced external function declarations */

/* internal function declarations */
PUBLIC VOID ipa2sc();
STATIC VOID usage();
STATIC int compare();

/* global variables */

/* static variables */
STATIC  char * prog_name;



/*<
 * Function:
 * Description:
 *
 * Arguments:
 *
 * Returns:
 *
 * 
>*/
INT
main (argc, argv)
INT argc;
CHAR * argv[];
{
    FILE * i_fp;
    FILE * o_fp;

    INT i, c;
#define LINE_LENGTH 128
#define WORDS_IN_LINE 128
    static char line[LINE_LENGTH];
    char * line_var;
    static char * words[WORDS_IN_LINE];
    char word_cnvrt[80];
    static char line_cnvrt[256];
    int words_cnt;
    BOOL t_flg = FALSE;         /* TALK */
    BOOL p_flg = FALSE;         /* Print While Talking */
    BOOL err_flg = FALSE;
#define MAX_IFILES 50
    CHAR *ifiles[MAX_IFILES+1], **p_ifile;
    CHAR *ofile = (CHAR *)0;

    i_fp = stdin;
    o_fp = stdout;
    prog_name = argv[0];

    while ((c = getopt(argc, argv, "tTpPo:O:")) != EOF) {
        switch (c) {
        case 't':
        case 'T':
            t_flg = TRUE;
#ifdef HARDWARE
            ini_st_ppi();
#endif
            break;
        case 'p':
        case 'P':
            p_flg = TRUE;
            break;
        case 'o':
        case 'O':
            ofile = optarg;
            break;
        case '?':
        default:
            err_flg = TRUE;
            break;
        } 
    }
    if (err_flg) {
        usage();
        exit(1);
    }
    for (i = 0; (optind < argc) || (i < MAX_IFILES); optind++, i++) {
        ifiles[i] = argv[optind];
    }
    ifiles[i] = (CHAR *)0;
    if ( ofile ) {
        if ( !(o_fp = fopen(ofile, "w")) ) {
            cant_open (prog_name, ofile);
            exit (1);
        }
    }
    p_ifile = ifiles;
    do {
        if (ifiles[0]) {
            if (!(i_fp = fopen (*p_ifile, "r"))) {
                cant_open (prog_name, *p_ifile);
                exit (1);
            } 
        } else {
            /* We are processing STDIN, make sure that this is the last one */
            * (p_ifile + 1) = (CHAR *)0;
        }
        setmode (fileno(i_fp), O_TEXT);
        setmode (fileno(o_fp), O_TEXT);
        while (fgets(line, LINE_LENGTH, i_fp)) {
            int i;
            nl_elim(line);
            line_var = line;
            words_cnt = arg_str(&line_var, words, WORDS_IN_LINE);
            line_cnvrt[0] = '\0';
            for (i=0; i < words_cnt; ++i) {
                word_cnvrt[0] = '\0';
                x_ipa2sc(words[i], word_cnvrt, 80);
                if ( t_flg ) {
#ifdef HARDWARE
                    sca_say(word_cnvrt);
                    sca_utter("STP");   
#endif
                } 
                strcat(line_cnvrt, word_cnvrt);
                strcat(line_cnvrt, " ");
            }
            /* If t_flag is true and p_flg is false, don't print */
            if ( !(t_flg && !p_flg) ) {
                fputs(line_cnvrt, o_fp);
                fputc('\n', o_fp);
            } 
        }
        fclose (i_fp);
    } while (*(++p_ifile));
    fclose (o_fp);
    exit (0);
}


STATIC VOID
usage ()
{
    fprintf (stderr, "Usage: %s [-t] [-p] [-o] <o_file> <i_files> \n", prog_name);
}

!Funky!Stuff!
echo x - nl_elim.c
cat >nl_elim.c <<'!Funky!Stuff!'
/*+
 * File: 
 * Description:
 *
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log$
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header$";
#endif

/* #includes */
#include "mbstd.h"
#include <stdio.h>
 
/*<
 * Function:
 * Description:
 *
 * Arguments:
 *
 * Returns:
 *
 * Side Effects:
 *
 * Calls:
 * 
>*/
PUBLIC VOID
nl_elim (iline)
char  iline[];
{
    char * cp;
    cp= &iline[strlen(iline)-1]; 
    if (*cp == '\n') {
        *cp = '\0';
    }
}
!Funky!Stuff!
echo x - prs_str.c
cat >prs_str.c <<'!Funky!Stuff!'
/*+
 * File: 
 * Description:
 *
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log$
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header$";
#endif

/* #includes */
#include "mbstd.h"
#include <stdio.h>
#include <string.h>
 
/* #defines */

/* external variables */

/* referenced external function declarations */

/* internal function declarations */

/* global variables */

/* static variables */



/*<
 * Function: prs_str
 * Description:
 *  Given a a pointer to the input string, prs_str copies contents of 
 *  i_str to o_str until any of charachters in p_seps is detected.
 *  -) All initial seperators are ignored.
 *  -)A '\0' is written to o_str instead of the seperator.
 *  -) contents of p_i_str points to the character following the seperator
 *      unless the seperator had been a '\0' in which case p_i_str points to
 *      it.
 *  -) single quote ('\'') is not copied to output, what is enclosed in 
 *      single quotes is immune to seperator detection.
 *
 * Returns:
 *  detected seperator.
 *
 * 
>*/

PUBLIC char 
prs_str(p_i_str, o_str, p_seps)
char  ** p_i_str;       /* pointer to input string */
char  * o_str;          /* pointer to output string */
char  * p_seps;
{
    char * i_str;
    char * p_fnd;
    char c;

    i_str = * p_i_str;

    /* Skipp over initial seperators */
    do {
        if ( (c = *i_str++) == '\0' ) {
            break;
        }
    } while (p_fnd = strchr(p_seps, c));

    while ((p_fnd = strchr(p_seps, c)) == NULL) {
        int completed;
        switch (c) {
        case '\'':
            completed = FALSE;
            while (c = *i_str++) {
                if (c == '\'') {
                    completed = TRUE;
                    break;
                } else {
                    *o_str++ = c;
                }
            }
            if (!completed) {
                --i_str;
                fprintf (stderr, "Unmatched \'\n");
            }
            break;
        default:
            *o_str++ = c;
            break;
        }
        c = *i_str++;
    }
    if ( *p_fnd == '\0') {
        --i_str;
    }
    *o_str = '\0';
    *p_i_str = i_str;
    return (*p_fnd);
}
!Funky!Stuff!
echo x - sc_rules.c
cat >sc_rules.c <<'!Funky!Stuff!'
/*+
 * File: 
 * Description:
 *	
 *	This File contains a set of rules for converting  International
 *	Phonetic Alphabet, representation of phonemes, to SC01 Ascii
 *	codes. 
 *	The tables had been taken from the 
 *      Navy Research Laboratory Report 7948
 *	Which is distributed as
 *	AD-A021-929
 *	National Technical Information Service
 *	U.S. Department of Commerce
 *	tel:	Info. (703) 487-4600
 *	tel:	order (703) 487-4650
 *
 *  ***
 *  DIFFERENCES:
 *	The following changes have been made to NRL report tables:
 *	NX is replaced by NG.
 *	JH is replaced by j.
 *      HH is replaced by h.
 *  This was done (reluctantly) to be compatible with english-to-ipa
 *  program.
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log$
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header$";
#endif

/* #includes */
#include  "mbstd.h"
#include  "rule.h"
 
/* internal function declarations */
STATIC int compare();




/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE IY_rule[] = {
	{Anything,	"IY",		Anything,	"E"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 
/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE IH_rule[] = {
	{Anything,	"IH",		Anything,	"I"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE EY_rule[] = {
	{"l",		"EY",		"r",		"UH3-A1-I3"	},
	{"l",		"EY",		Anything,	"UH3-A1-AY"	},
	{Anything,	"EY",		"r",		"A-I3"	},
	{Anything,	"EY",		Anything,	"A-AY"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 
/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE EH_rule[] = {
	{"l",		"EH",		Anything,	"UH3-EH"	},
	{Anything,	"EH",		Anything,	"EH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AE_rule[] = {
	{"l",		"AE",		"r",		"UH3-AE-EH3"	},
	{"l",		"AE",		Anything,	"UH3-AE"	},
	{Anything,	"AE",		"r",		"AE1-EH3"	},
	{Anything,	"AE",		Anything,	"AE"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AA_rule[] = {
	{Anything,	"AA",		Anything,	"AH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 
/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AO_rule[] = {
	{"l",		"AO",		"r",		"UH3-O"		},
	{"l",		"AO",		"ER",		"UH3-AW-O2"	},
	{"l",		"AO",		Anything,	"UH3-AW"	},
	{Anything,	"AO",		"r",		"O"		},
	{Anything,	"AO",		"ER",		"AW-O2"		},
	{Anything,	"AO",		Anything,	"AW"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE OW_rule[] = {
	{"l",		"OW",		Anything,	"UH3-O1-U1"	},
	{Anything,	"OW",		Anything,	"O1-U1"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE UH_rule[] = {
	{"l",		"UH",		Anything,	"UH3-OO"	},
	{Anything,	"UH",		Anything,	"OO"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE UW_rule[] = {
	{Anything,	"UW",		Anything,	"IU-U"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE ER_rule[] = {
	{"IY",		"ER",		Anything,	"I3_ER"		},
	{"ER",		"ER",		Anything,	"IU-r"		},
	{"l",		"ER",		Anything,	"UH3-ER"	},
	{Anything,	"ER",		"l",		"UH3-ER"	},
	{"r",		"ER",		Anything,	"UH3-r"		},
	{Anything,	"ER",		Anything,	"ER"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AX_rule[] = {
	{Anything,	"AX",		Anything,	"UH2"		},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AH_rule[] = {
	{Anything,	"AH",		Anything,	"UH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 
/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AY_rule[] = {
	{Anything,	"AY",		"l",		"AH-AY"		},
	{Anything,	"AY",		"r",		"AH-I3"		},
	{Anything,	"AY",		"ER",		"AH-AY"		},
	{Anything,	"AY",		Anything,	"AH-E1"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE AW_rule[] = {
	{Anything,	"AW",		Anything,	"AH-O1"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE OY_rule[] = {
	{"l",		"OY",		"ER",		"UH3-O1-AY"	},
	{"l",		"OY",		"l",		"UH3-O1-AY"	},
	{"l",		"OY",		"r",		"UH3-O1-EH2"	},
	{Anything,	"OY",		"ER",		"O1-AY"		},
	{Anything,	"OY",		"l",		"O1-AY"		},
	{Anything,	"OY",		"r",		"O1-EH2"	},
	{Anything,	"OY",		Anything,	"O1-E1"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE y_rule[] = {
	{Anything,	"y",		Anything,	"Y"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE p_rule[] = {
	{Anything,	"p",		Anything,	"P"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE b_rule[] = {
	{Anything,	"b",		Anything,	"B"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE t_rule[] = {
	{Anything,	"t",		Anything,	"T"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};



/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE d_rule[] = {
	{Anything,	"d",		Anything,	"D"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE k_rule[] = {
	{Anything,	"k",		Anything,	"K"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE g_rule[] = {
	{Anything,	"g",		Anything,	"G"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE f_rule[] = {
	{Anything,	"f",		Anything,	"F"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};



/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE v_rule[] = {
	{Anything,	"v",		Anything,	"V"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE TH_rule[] = {
	{Anything,	"TH",		Anything,	"TH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE DH_rule[] = {
	{Anything,	"DH",		Anything,	"THV"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE s_rule[] = {
	{Anything,	"s",		Anything,	"S"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE z_rule[] = {
	{Anything,	"z",		Anything,	"Z"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE SH_rule[] = {
	{Anything,	"SH",		Anything,	"SH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};



/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE ZH_rule[] = {
	{Anything,	"ZH",		Anything,	"ZH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE h_rule[] = {
	{Anything,	"h",		Anything,	"H"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};



/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE CH_rule[] = {
	{Anything,	"CH",		Anything,	"T-CH"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE j_rule[] = {
	{Anything,	"j",		Anything,	"D-J"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE m_rule[] = {
	{Anything,	"m",		Anything,	"M"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE n_rule[] = {
	{Anything,	"n",		Anything,	"N"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE NG_rule[] = {
	{Anything,	"NG",		Anything,	"NG"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 
/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE l_rule[] = {
	{"IY",		"l",		Anything,	"I3-L"	},
	{"EY",		"l",		Anything,	"I3-L"	},
	{"AY",		"l",		Anything,	"I3-L"	},
	{"OY",		"l",		Anything,	"I3-L"	},
	{"AE",		"l",		Anything,	"UH3-L"	},
	{"AO",		"l",		Anything,	"UH3-L"	},
	{"OW",		"l",		Anything,	"UH3-L"	},
	{Anything,	"l",		Anything,	"L"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE w_rule[] = {
	{Anything,	"w",		Anything,	"W"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE WH_rule[] = {
	{Anything,	"WH",		Anything,	"H-W"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};
 


/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE r_rule[] = {
	{Anything,	"r",		"l",		"UH3-R"		},
	{Anything,	"r",		Anything,	"R"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};

/*
**	LEFT_PART	MATCH_PART	RIGHT_PART	OUT_PART
*/
STATIC RULE punct_rules[] = {
	{Anything,	" ",		Anything,	"PA0"	},
	{Anything,	",",		Anything,	"PA1"	},
	{Anything,	".",		Anything,	"PA1-PA1"	},
	{Anything,	"?",		Anything,	"PA1-PA1"	},
	{Anything,	"-",		Anything,	"PA1"	},
	{Anything,	E_O_RULE,	Anything,	Silent	},
};


/*<
 * Function:
 * Description:
 *	Table, associating IPAs to the RULEs.
 *
>*/

typedef struct {
	CHAR * ipa;
	RULE * sc_rule;
} IPA_SC;

STATIC IPA_SC ipa_sc_tbl[] = {
	{"AA", 	AA_rule	},
	{"AE", 	AE_rule	},
	{"AH", 	AH_rule	},
	{"AO", 	AO_rule	},
	{"AW", 	AW_rule	},
	{"AX", 	AX_rule	},
	{"AY", 	AY_rule	},
	{"CH", 	CH_rule	},
	{"DH", 	DH_rule	},
	{"EH", 	EH_rule	},
	{"ER", 	ER_rule	},
	{"EY", 	EY_rule	},
	{"IH", 	IH_rule	},
	{"IY", 	IY_rule	},
	{"NG", 	NG_rule	},
	{"OW", 	OW_rule	},
	{"OY", 	OY_rule	},
	{"SH", 	SH_rule	},
	{"TH", 	TH_rule	},
	{"UH", 	UH_rule	},
	{"UW", 	UW_rule	},
	{"WH", 	WH_rule	},
	{"ZH", 	ZH_rule	},
	{"b", 	b_rule	},
	{"d", 	d_rule	},
	{"f", 	f_rule	},
	{"g", 	g_rule	},
	{"h", 	h_rule	},
	{"j", 	j_rule	},
	{"k", 	k_rule	},
	{"l", 	l_rule	},
	{"m", 	m_rule	},
	{"n", 	n_rule	},
	{"p", 	p_rule	},
	{"r", 	r_rule	},
	{"s", 	s_rule	},
	{"t", 	t_rule	},
	{"v", 	v_rule	},
	{"w", 	w_rule	},
	{"y", 	y_rule	},
	{"z", 	z_rule	},
};

#define TBL_SIZE	((sizeof(ipa_sc_tbl))/(sizeof(IPA_SC)))


/*<
 * Function:
 * Description:
 *	Finds the rule corresponding to the specified IPA.
 *
 * Returns:
 *	Pointer to RULE.
 *	NULL if specified ipa was not in the table.
 *  
>*/
PUBLIC RULE * 
xrule (ipa)
char * ipa;
{
    extern char * bsearch();
    RULE * retval;
    IPA_SC * p_fnd;
    IPA_SC key;
    char * fnd_code;

    key.ipa = ipa;
    if (p_fnd = (IPA_SC *) bsearch ((char *)&key,
        (char *)ipa_sc_tbl, TBL_SIZE, sizeof(IPA_SC), compare)) {

        retval  = p_fnd->sc_rule;
    }  else {
        retval = (RULE *) 0;
    }
    return (retval);
}

STATIC int 
compare (ky_cd1, ky_cd2)
IPA_SC * ky_cd1;
IPA_SC * ky_cd2;
{
    return (strcmp(ky_cd1->ipa, ky_cd2->ipa));
}
!Funky!Stuff!
echo x - setmode.c
cat >setmode.c <<'!Funky!Stuff!'
#include "mbstd.h"

PUBLIC int
setmode(handle, mode)
int handle;
int mode;
{}
!Funky!Stuff!
echo x - strupr.c
cat >strupr.c <<'!Funky!Stuff!'

/*+
 * File: 
 * Description:
 *  The strlwr function converts any upper case letters in the given
 *  null terminated string to lowercase. Other characters are not affected.
 *
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log$
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header$";
#endif

#include "mbstd.h"
#include <ctype.h>


PUBLIC char *
strupr (str)
char * str;
{
    char c;
    char * retval;

    retval = str;
    while ( c= *str ) {
        if (islower(c)) {
            *str++ = toupper(c);
        } else {
            str++;
        }
    }
    return retval;
}
!Funky!Stuff!
echo x - x_ipa2sc.c
cat >x_ipa2sc.c <<'!Funky!Stuff!'
/*+
 * File: 
 * Description:
 *
 *
 *
 *  Author: Mohsen Banan.
 *
 *  This program is public domain software, no warranty intended or
 *  implied.
 *  General permission to copy or modify, but not for profit,  is
 *  hereby  granted.
 *
 * Functions:
 *
 *
 * Audit Trail:  $Log$
 *
-*/

#ifdef RCS_VER
static char *rcs = "$Header$";
#endif

/* #includes */
#include "mbstd.h"
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#ifdef BSD4_2
#include "msc3sup.h"
#endif
#include "rule.h"
 
/* #defines */

/* external variables */

/* referenced external function declarations */

/* internal function declarations */

/* global variables */

/* static variables */




/*<
 * Function:
 * Description:
 *
 * Returns:
 *  
 *  
>*/
PUBLIC  SUCC_FAIL
x_ipa2sc (ipa_word, sc_out, out_len)
CHAR * ipa_word;
CHAR * sc_out;
INT out_len;
{
    static CHAR buf1[3] = {'\0'};
    static CHAR buf2[3] = {'\0'};
    static CHAR buf3[3] = {'\0'};
    CHAR * prev_left;
    CHAR * left_ipa = buf1;
    CHAR * match_ipa = buf2;
    CHAR * right_ipa = buf3;
    BOOL e_o_ipa_word = FALSE;
    CHAR *in_index, *out_index, *out_end;
    CHAR c1, c;
    RULE *rules, *rule;
    extern RULE * xrule();
    SUCC_FAIL retval;

    retval = SUCCESS;
    in_index = ipa_word;
    out_index = sc_out;
    out_end = sc_out + (out_len - 1);       /* Room for end-of-string */
    *left_ipa = *match_ipa = *right_ipa = '\0';

    do {
        prev_left = left_ipa;
        left_ipa = match_ipa;
        match_ipa = right_ipa;
        right_ipa = prev_left;

        if ( (! e_o_ipa_word) && (c1 = *in_index++) ) {
            CHAR * buf = right_ipa;
            if ( islower(c1) ) {
                *buf++ = c1;
                *buf = '\0';
            } else {
                *buf++ = c1;
                if (c1 = *in_index++) {
                    *buf++ = c1;
                    *buf = '\0';
                } else {
                    e_o_ipa_word = TRUE;
                    *buf = '\0';
                    OOPS();
                }
            }
        } else {
            e_o_ipa_word = TRUE;
            *right_ipa = '\0';
        }

        if (*match_ipa) {
            if ( rules = xrule(match_ipa) ) {
                BOOL found = FALSE;
                CHAR * p_out;
                for ( rule=rules; rule->match != E_O_RULE; ++rule ) {
                    if ( *(rule->left) != '\0' ) {
                        if ( strcmp(rule->left, left_ipa) ) {
                            continue;
                        }
                    }
                    if ( *rule->right != '\0' ) {
                        if ( strcmp(rule->right, right_ipa) ) {
                            continue;
                        }
                    }

                    /* then it is found */
                    p_out = rule->out;
                    while ( c = *p_out++ ) {
                        if ( out_index >= out_end ) {
                            OOPS();
                            *out_index = '\0';
                            return FAIL;
                        } else {
                            *out_index++ = c;
                        }
                    }
                    *out_index++ = '-';

                    found = TRUE;
                    break;
                }
                if ( ! found ) {
                    OOPS();
                    retval = FAIL;
                }
            } else {
                OOPS();
                retval = FAIL;
            }
        }
    } while ( (*match_ipa) || (*right_ipa) );

    /* Handle an empty string input and convert the last '-' to a '\0' */   
    if ( out_index > sc_out ) {
        *(out_index - 1) = '\0';
    }

    return retval;  
}
!Funky!Stuff!
echo x - bdpdt.bat
cat >bdpdt.bat <<'!Funky!Stuff!'
cl -o ipa2sc ipa2sc arg_str cantopen getopt nl_elim prs_str setmode strupr bsearch x_ipa2sc sc_rules  -link   !Funky!Stuff!
echo x - mkpdt.bat
cat >mkpdt.bat <<'!Funky!Stuff!'
cl -c -DMSDOS ipa2sc.c
cl -c -DMSDOS arg_str.c
cl -c -DMSDOS cantopen.c
cl -c -DMSDOS getopt.c
cl -c -DMSDOS nl_elim.c
cl -c -DMSDOS prs_str.c
cl -c -DMSDOS setmode.c
cl -c -DMSDOS strupr.c
cl -c -DMSDOS bsearch.c
cl -c -DMSDOS x_ipa2sc.c
cl -c -DMSDOS sc_rules.c
!Funky!Stuff!