summaryrefslogtreecommitdiff
path: root/language/tibetan/steiner/ttt.c
diff options
context:
space:
mode:
Diffstat (limited to 'language/tibetan/steiner/ttt.c')
-rw-r--r--language/tibetan/steiner/ttt.c1121
1 files changed, 1121 insertions, 0 deletions
diff --git a/language/tibetan/steiner/ttt.c b/language/tibetan/steiner/ttt.c
new file mode 100644
index 0000000000..c5765dce58
--- /dev/null
+++ b/language/tibetan/steiner/ttt.c
@@ -0,0 +1,1121 @@
+/***********************************************************************/
+/***********************************************************************/
+/* */
+/* Tibetan Transcript Translator */
+/* */
+/***********************************************************************/
+/***********************************************************************/
+/*
+ (C) Dec 1996 / Jan, Feb 1997 by
+ Beat Steiner, Brunngasse 12, 3011 Bern, Switzerland
+ e-mail: Beat.Steiner@gseved.admin.ch
+ Version 0.1 alpha prerelease
+
+
+ LEGAL STUFF
+ -----------
+ Refer to GNU General Public License (feel free to use and distribute
+ this program at your own risk but at no cost, keeping copyright
+ notices intact).
+
+
+ DESCRIPTION
+ -----------
+ This program is intended to convert different transcript standards
+ of the Tibetan language or even to perform a transcript import into
+ a document processing system.
+
+ At present, it is able to convert transcripts to LaTeX, based
+ on Jeff sparkes' and / or Sam Sirlin's fonts and ideas. Since I
+ got into trouble to reverse engineer Sparkes' code, I have rewriten
+ the complete transcript translator, only picking some ideas from his
+ code.
+
+ The main additional feature is fully automatic ligature generation,
+ openness towards different transcript standards and inline LaTeX
+ command support.
+
+ The main disadvantages are:
+ ** Sparkes' and Sirlin's language mix handling is not supported yet.
+ ** vovels on tsa, tsha, dza (resp. TZA, TSA, DZA) do not look nice.
+
+ WARNING: the ttd file format is still subject to change.
+ If you create your own ttd files now, you risk to spend much work
+ on updating them.
+
+
+ INSTALLING
+ ----------
+ Install Sam Sirlin's fonts from the CTAN archive
+ tex/language/tibetan/sirlin
+ to the appropriate directory or set the Tex font path.
+ Do the same with the tfm files. Look at the README file
+ for help on this. If you dont have metafont, use Jeff Sparkes'
+ pk and tfm files.
+
+ This is a single file program which can be compiled without
+ complication by
+ gcc ttt.c -o ttt
+ or
+ cc ttt.c -o ttt
+ or whatever ANSI compliant C compiler you have.
+
+
+ STARTING THIS PROGRAM
+ ---------------------
+ In order to translate ACIP to LaTeX, use
+
+ ttt acip.ttd latex.ttd input.tib output.tex
+
+ where acip.ttd is the input transcript definition file
+ . latex.ttd is the output transcript definition file
+ . input.tib is your ACIP input text
+ . output.tex is the output file to be processed by latex
+
+ On Linux, you will enjoy the feature of magic line support:
+ In your input.tib file, add the following two lines at the
+ VERY TOP (replacing the respective filenames):
+
+ #!/bin/sh
+ ttt acip.ttd latex.ttd $0 output.tex; latex output; exit
+
+ Due to the magic line at the top, (ba)sh will think that your text
+ input.tib is a shell script, executing the 2nd line.
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ This program will ignore the FIRST AND THE SECOND
+ line if the FIRST line starts with #!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ Do not put anything, even not comments above these lines.
+ $0 is automatically replaced by the file name (e.g. input.tib).
+
+ Then turn your input.tib file into an executable by
+ chmod 755 input.tib
+
+ Now, you can start this program by entering
+ input.tib
+ at the shell command prompt.
+
+ DOS users, please write an apropriate *.BAT file (without $0).
+ Windows users may set the command line options as program properties.
+
+
+ RETURN VALUES
+ -------------
+ 0: Normal program completion.
+ 1: x___error occurred (unknown input key, missing output ligature
+ . and such)
+ 2: Could not open a file or bad number of command line arguments
+ 3: Static memory allocation overrun
+
+
+ IMPLEMENTATION NOTICE
+ ---------------------
+ This kind of implementation was motivated by the need of importing
+ texts typed at Sera Monastery into the ClearLook document
+ processing system and solving other conversion problems like
+ differences between ACIP and Wiley transcripts plus the need to
+ import both of them into LaTeX, ClearLook, Lout and other programs.
+
+ Therefore, a very flexible solution based on Tibetan Transcript
+ Definition (ttd) files has been chosen.
+ They map the different transcribed letters, control sequences
+ and ligatures (btags pa) to common keys.
+
+ example: ACIP --> LaTeX conversion for the letter 'tsa
+ the acip.ttd file says:
+ c___tsa TZ
+ which associates the key 'tsa' to the value 'TZ'
+ the tex.ttd file says:
+ c___tsa \tibetan\char16
+ which associates the key 'tsa' to the tex font chracter.
+
+ The magic characters before the transcript key have the following
+ meaning:
+
+ 1st char:
+ c: normal consonant
+ p: potential prefix (negative bias for ligature generation)
+ b: potential btagspa (simplified lower part of ligatureand ha,
+ positive bias for ligature generation)
+ .: punctuation (Terminates syllable and suppresses tsheg)
+ x: program control
+
+ 2nd char and 3rd char:
+ reserved for generic ligature generation (join styles,
+ character substitution)
+
+ 4th char:
+ _: just to increase readability of ttd file
+
+ Meaning of x___ keys:
+
+ General controls:
+ x___preamble Will be at top of output without being asked for
+ x___postamble Will be at bottom of output without being asked for
+ x___error Error message included to output file
+
+ Generic ligatures:
+ x___inner_box{ Encapsulation of individual characters (no vovels)
+ x___inner_box}
+ x___outer_box{ Encapsulation of whole ligature without vovel
+ x___outer_box}
+
+ Mixed language handling (subject to change, not fully implemented yet)
+ x___transp_word Input will be put out without modification til space
+ x___transp_char Unmodified character passing
+ x___transp_reg{ Unmodified region passing start
+ x___transp_reg} end
+ x___transp_reg~ toggle
+
+
+ WARNING: The values of the input ttd and the keys of the output
+ ttd file MUST be unique, otherwise the result is undefined.
+
+ The input stream is scanned for the largest matched value in the
+ input ttd file, giving the common key. A lookup in the output ttd
+ file generates the output stream.
+
+ The ligature generation is a special issue documented at the
+ rather complicated if construct in the main function.
+
+
+ To Do:
+ ------
+
+ ** Better char comparison in ttread
+ ** Write documentation
+ ** allow comments in ttd files
+ ** Warn on ambiguous transcript (gyin, gyas, ...)
+ ** Full support of Sirlin and Sparkes
+ ** Mixed language support
+ Two flags allow mixing Tibetan, other languages and control sequences:
+ 'active' says wether or not the lookup and ligature generation
+ . take place or not. If not,
+ 'transparent' says wether the input stream is passed unmodified to
+ . the output stream or simply be ignored (crunched).
+
+ ** Clean escape char handling for binary output
+
+ ** More intelligence for Generic Ligatures
+ ** Font: Character fragments for generic ligatures
+ ** Vertically stretched (50% or 75%) chars for generic ligatures
+ ** Mirrored gigu
+
+ ALMOST DONE
+ -----------
+ ** Clean up and update comments and program style
+ ** Read filenames from command line
+ . (unflexible, no default handling, magic lines for linux only)
+ ** Vovel support for generic ligatures (still a LaTeX problem to solve)
+ ** (Only) two vovels on a character supported
+
+ PERFORMANCE
+ -----------
+ The actual lookup process is performed by a binary search although
+ a hash table lookup is expected to be about 5 times faster. This is
+ just caused by my not being that much familiar with C++ and g++.
+ Furtheron, bsearch is better documented and available on more
+ compilers.
+ This program needs less than 1 second to produce 6 a4paper output pages
+ on my 5x86 machine. So there are more important problems to solve now.
+ */
+
+/***********************************************************************/
+/* May this program contribute to the */
+/* Dharma practice of many people */
+/***********************************************************************/
+
+/******************************/
+/******************************/
+/* */
+/* Includes */
+/* */
+/******************************/
+/******************************/
+
+#include <stdio.h>
+#include <stdlib.h> /* contians qsort and bsearch */
+#include <string.h>
+
+
+/******************************/
+/******************************/
+/* */
+/* Static Memory Allocations */
+/* */
+/******************************/
+/******************************/
+
+const int MAX_SYL_SIZE_LINE = __LINE__ + 1;
+#define MAX_SYL_SIZE 50
+/* maximum characters per syllable (ligature complexity)
+ very cheap and should be enough
+ */
+
+const int MAX_KEY_VAL_LENGTH_LINE = __LINE__ + 1;
+#define MAX_KEY_VAL_LENGTH 44
+/* maximum ttd key/value length
+ critical for output preamble
+ hint: try to include the preamble
+ */
+
+const int TTSIZE_LINE = __LINE__ + 1;
+#define TTSIZE 300
+/* transcript table size
+ critical for predefined ligatures
+ keep in mind that you add an appropriate command margin
+ to the number of characters in your font.
+ */
+
+const int INPUT_LINEBUFFER_LENGTH_LINE = __LINE__ + 1;
+#define INPUT_LINEBUFFER_LENGTH 180
+/* Maximum line length of input text file */
+
+
+/******************************/
+/******************************/
+/* */
+/* Global stuff */
+/* */
+/******************************/
+/******************************/
+
+typedef struct
+{
+ char key[MAX_KEY_VAL_LENGTH];
+ char val[MAX_KEY_VAL_LENGTH];
+} ttentry;
+
+char ESCAPE_CHAR='\xff';
+int KEY_LEN[MAX_KEY_VAL_LENGTH];
+int X_ERROR_OCCURRED = 0;
+static FILE *OUTTEXT;
+
+/******************************/
+/******************************/
+/* */
+/* Functions */
+/* */
+/******************************/
+/******************************/
+
+void trace(char *message)
+{
+ /*
+ if (message == NULL)
+ {
+ fprintf(stderr, "<NULL>");
+ fflush(stderr);
+ }else{
+ fprintf(stderr, "<%s>", message);
+ fflush(stderr);
+ }
+ */
+}
+
+
+/******************************/
+
+/* clean interface for strncmp */
+int ttcmp(const void *first, const void *second)
+{
+ return strncmp(((ttentry*)first)->key, ((ttentry*)second)->key,
+ MAX_KEY_VAL_LENGTH); }
+
+
+/******************************/
+
+void ttprepare(ttentry ttable[])
+{
+ qsort(&ttable[0], TTSIZE, sizeof(ttentry), ttcmp);
+}
+
+
+/******************************/
+
+char *ttlookup(const char *key, const ttentry ttable[])
+{
+ ttentry *found=NULL;
+
+ if (key)
+ {
+ found=(ttentry*)bsearch(key, ttable, TTSIZE,
+ sizeof(ttentry), ttcmp);
+
+ if (found)
+ {
+ return found->val;
+ }else{
+ return NULL;
+ }
+ }
+}
+
+
+/******************************/
+
+void ttread(const char *name, int swap, ttentry ttable[])
+{
+ /* This procedure reads the transcript definition files.
+ The first column MUST be strictly left aligned.
+ 'name' is the filenamae
+ 'swap' is a flag which swaps the key/value reading order:
+ file contents for swap=0:
+ <key> <value>
+ file contents for swap=1:
+ <value> <key>
+ 'ttable' is the transcript table where the file is read into.
+ 'TTSIZE' is allocated statically and needed to avoid an
+ index overflow
+ */
+ char c = ' '; /* not EOF */
+ char *cp = NULL;
+ char *cp_start = NULL; /* Needed for ptr range check */
+ FILE *ttd = NULL;
+ int idx = 0;
+
+ void CheckCP(void)
+ {
+ if ((cp - cp_start) >= (MAX_KEY_VAL_LENGTH - 1))
+ {
+ fprintf(stderr, "Insufficient static memory allocation. ");
+ fprintf(stderr, "Please increase MAX_KEY_VAL_LENGTH in ");
+ fprintf(stderr, "line %d of %s and compile again.\n",
+ MAX_KEY_VAL_LENGTH_LINE, __FILE__);
+ exit(3);
+ }
+ }
+
+ /* Clear array storing input ttd key length flags
+ for boosting performance in charparse() */
+ for (idx = 0; idx < MAX_KEY_VAL_LENGTH; idx++)
+ {
+ KEY_LEN[idx] = 0;
+ }
+ idx = 0;
+
+ /* Clear transcript table struct arrays */
+ for (idx = 0; idx < TTSIZE; idx++)
+ {
+ *ttable[idx].key = '\0';
+ *ttable[idx].val = '\0';
+ }
+ idx = 0;
+
+
+ if (!(ttd = fopen(name, "r") ))
+ {
+ fprintf(stderr, "%s %s\n", "could not open ttd file ", name);
+ exit(2);
+ }
+
+
+ /* ev. better with strpbrk() */
+ while (c != EOF && idx < TTSIZE)
+ {
+ /* Read ttd keys/values */
+ if (swap) cp = ttable[idx].val;
+ else cp = ttable[idx].key;
+
+ cp_start = cp;
+
+ c = fgetc(ttd);
+ while ( c != ' ' && c != '\t' && c != '\n' && c != EOF)
+ {
+ *cp++ = c; CheckCP();
+ c=fgetc(ttd);
+ }
+ *cp++ = '\0'; CheckCP();
+
+ /* Eliminate separtor garbage */
+ while ( c == ' ' || c == '\t' )
+ { c = fgetc(ttd);
+ }
+
+ /* Read ttd values/keys */
+ if (swap) cp = ttable[idx].key;
+ else cp = ttable[idx].val;
+
+ cp_start = cp;
+ while ( c != '\t' && c != '\n' && c != EOF )
+ /* ev. add comment char and spaces */
+ {
+ *cp++ = c; CheckCP();
+ c = fgetc(ttd);
+ }
+ *cp++ = '\0'; CheckCP();
+
+ /* Eliminate trailing garbage */
+ while ( c != '\n' && c != EOF )
+ { c = fgetc(ttd);
+ }
+
+ /* mark existing key lengths */
+ KEY_LEN[strlen(ttable[idx].key)] = !0;
+
+ idx++;
+ }
+ if (idx >= TTSIZE)
+ {
+ fprintf(stderr, "Insufficient memory allocation. Please increase");
+ fprintf(stderr,
+ " TTSIZE in line %d of %s and compile again.\n",
+ TTSIZE_LINE, __FILE__);
+ exit(3);
+ }
+}
+
+
+/******************************/
+
+void prepare_flags(ttentry inptrans[], ttentry outtrans[],
+ int *active, int *transparent)
+{
+ char *charptr;
+
+ /* Set activity flag according to INPUT ttd */
+ charptr=ttlookup("x___init_active", inptrans);
+ if (charptr)
+ {
+ if ( strcasecmp("yes", charptr) == 0 )
+ { *active = 1; }else{ *active = 0;
+ }
+ }
+
+ /* Set transparency flag according to OUTPUT ttd */
+ charptr=ttlookup("x___init_transprent", outtrans);
+ if (charptr)
+ {
+ if ( strcasecmp("yes", charptr) == 0 )
+ { *transparent = 1; }else{ *transparent = 0;
+ }
+ }
+
+
+ /* Set escape character
+ In this release, escapechar is only accepted if it is the first
+ char in the output ttd */
+
+ charptr=ttlookup("x___escape_char", outtrans);
+ if (charptr)
+ {
+ ESCAPE_CHAR = *charptr;
+ }
+}
+
+
+/******************************/
+
+char *charparse(const char *input, int *parsestep,
+ const ttentry *inptrans)
+{
+ char yigcpy[MAX_KEY_VAL_LENGTH+1];
+ char *charptr=NULL;
+ int parselen;
+ int yiglen;
+
+ strncpy(yigcpy, input, MAX_KEY_VAL_LENGTH);
+ parselen=strlen(input);
+ if (parselen > MAX_KEY_VAL_LENGTH) parselen=MAX_KEY_VAL_LENGTH;
+ yiglen=parselen;
+
+ while (yiglen > 0 && charptr == NULL)
+ {
+ yigcpy[yiglen] = '\0';
+ if (KEY_LEN[yiglen]) charptr = ttlookup(yigcpy, inptrans);
+ yiglen--;
+ }
+ *parsestep=yiglen+1;
+ return charptr;
+}
+
+
+/******************************/
+
+void yigprint(char *yig,
+ ttentry *outtrans)
+{
+ char *charptr=NULL;
+ if (yig != NULL)
+ {
+ charptr=ttlookup(yig, outtrans);
+ if (charptr)
+ {
+ /* DIRTY: detects escape char only if it is the first one. */
+ if (*charptr != ESCAPE_CHAR)
+ {
+ if (*charptr != '\0') fprintf(OUTTEXT, "%s", charptr);
+ /* fflush(OUTTEXT); */
+ }else{
+ charptr++; /* skip the escape char itself */
+ fprintf(OUTTEXT, "%c", (char)strtol(charptr, NULL, 0));
+ /* fflush(OUTTEXT); */
+ }
+ }else{ /* no output ttd match */
+ X_ERROR_OCCURRED = !0;
+ fprintf(OUTTEXT, "%s", ttlookup("x___error", outtrans));
+ fflush(OUTTEXT);
+ trace(yig);
+ }
+ }else{
+ /* trace("gugus"); */
+ }
+}
+
+
+/******************************/
+
+int vovel_left(char *syl[MAX_SYL_SIZE], int start, int syllength)
+{
+ int i;
+ int result = 0;
+
+ for (i=start; i<syllength; i++)
+ {
+ /* trace(syl[i]); */
+ if (*syl[i] == 'v') result = !0;
+ }
+ return result;
+}
+
+
+/**********************************************************************/
+/**********************************************************************/
+/********************* *********************/
+/********************* Main *********************/
+/********************* *********************/
+/**********************************************************************/
+/**********************************************************************/
+
+int main(int argc, char **argv)
+{
+ /* Trnscript tables
+ TTSIZE is #defined at the static memory allocations at top of code
+ */
+ ttentry inptrans[TTSIZE];
+ ttentry outtrans[TTSIZE];
+
+ /* Filter activity flag */
+ int active = 0; /* 0=non-Tibetan, 1=Tibetan text */
+
+ /* Filter transparency flag */
+ int transparent = 0; /* 0=crunch non-Tibetan, 1=pass non-Tibetan */
+
+ int pending_tsheg = 0; /* (c) by Jeff Sparkes */
+ int pending_shad_space = 0; /* (c) by Jeff Sparkes */
+
+ /* Char & syllable buffers */
+ char linebuf [INPUT_LINEBUFFER_LENGTH + 1];
+ char inner_vovel_key_buf [MAX_KEY_VAL_LENGTH + 2];
+ char outer_vovel_key_buf [MAX_KEY_VAL_LENGTH + 2];
+ char lig_key[MAX_SYL_SIZE * MAX_KEY_VAL_LENGTH];
+ char *charptr = NULL;
+ char *parseptr = NULL;
+ char *yig = NULL;
+/* char *yigbuf = NULL; */
+
+ char *syllable[MAX_SYL_SIZE];
+ int sylindex;
+ int sylend;
+ int parsestep;
+ int i;
+ int geni;
+ int firstline = !0;
+ int skipline = 0;
+
+ char *active_start = NULL;
+ char *active_end = NULL;
+ char *active_toggle = NULL;
+
+ int active_start_len = 0;
+ int active_end_len = 0;
+ int active_toggle_len = 0;
+
+
+ /* Input text file */
+ static FILE *inptext;
+ /* OUTTEXT is defined in the global section */
+
+
+/******************************/
+/* */
+/* Preparation */
+/* */
+/******************************/
+
+
+ if (argc != 5)
+ {
+ /* fprintf(stderr, "You gave %d arguments:\n", argc - 1);
+ fprintf(stderr, "Input ttd: %s\n", argv[1]);
+ fprintf(stderr, "Output ttd: %s\n", argv[2]); */
+ fprintf(stderr,
+ "USAGE: %s input.ttd output.ttd input.text output.text\n",
+ argv[0]);
+ exit(2);
+ }
+
+
+ /* Read transcript tables from files and prepare (sort) them
+ for binary search. Input ttd MUST be read last in order to
+ maintain the KEY_LEN array
+ */
+ ttread (argv[2], 0, outtrans);
+ ttread (argv[1], 1, inptrans);
+ ttprepare(inptrans);
+ ttprepare(outtrans);
+
+
+trace(ttlookup("c___ka", outtrans));
+
+trace("prepare activity flags");
+
+// active_start = ttlookup("x___active_in{", outtrans);
+// if (active_start != NULL) active_start_len = strlen(active_start);
+// trace(active_start);
+// active_end = ttlookup("x___active_in}", outtrans);
+// if (active_end != NULL) active_end_len = strlen(active_end);
+// trace(active_end);
+// active_toggle = ttlookup("x___active_in~", outtrans);
+// if (active_toggle != NULL) active_toggle_len = strlen(active_toggle);
+// trace(active_toggle);
+
+ if (ttlookup("x___active_init", inptrans) != NULL)
+ {
+ active = !0;
+ }else{
+ active = 0;
+ }
+
+/******************************/
+/* */
+/* Open Files */
+/* */
+/******************************/
+
+
+ /* Open input text file */
+ if (strncmp(argv[3], "-", 2) != 0)
+ {
+ if (!( inptext = fopen(argv[3], "r") ))
+ {
+ fprintf(stderr, "%s", "Could not open input text file");
+ exit(2);
+ }
+ }else{
+ inptext = stdin;
+ }
+
+ /* Open output text file (outtext is global)*/
+ if (strncmp(argv[4], "-", 2) != 0)
+ {
+ if (!( OUTTEXT = fopen(argv[4], "w") ))
+ {
+ fprintf(stderr, "%s", "Could not open output text file");
+ exit(2);
+ }
+ }else{
+ OUTTEXT = stdout;
+ }
+
+
+/******************************/
+/* */
+/* Start Output */
+/* */
+/******************************/
+
+ /* Output preamble */
+ yigprint("x___preamble", outtrans);
+
+ prepare_flags(inptrans, outtrans,
+ &active, &transparent);
+
+
+ /* read input text file */
+ while (fgets(linebuf, INPUT_LINEBUFFER_LENGTH, inptext) != NULL)
+ {
+ if (strlen(linebuf) >= (INPUT_LINEBUFFER_LENGTH-1))
+ {
+ fprintf(stderr, "Input file contains too long lines. ");
+ fprintf(stderr, "Please keep them shorter than %d ",
+ INPUT_LINEBUFFER_LENGTH);
+ fprintf(stderr, "characters or increase ");
+ fprintf(stderr, "INPUT_LINEBUFFER_LENGTH in line %d of %s",
+ INPUT_LINEBUFFER_LENGTH_LINE, __FILE__);
+ fprintf(stderr, " and compile again.\n");
+ exit(3);
+ }
+
+ if (skipline)
+ {
+ *linebuf = '\0';
+ skipline = 0;
+ }
+
+ /* Filter out magic lines for Linux */
+ parseptr = linebuf + 1;
+ if (firstline && (*linebuf == '#') && (*parseptr == '!'))
+ {
+ *linebuf = '\0';
+ skipline = !0;
+ }
+ firstline = 0;
+
+ parseptr = linebuf;
+
+ /* parse until end of line */
+ while (*parseptr != '\0' && *parseptr != '\n' && *parseptr != '\13')
+ {
+ yig = charparse(parseptr, &parsestep, inptrans);
+ if (yig != NULL)
+ {
+ if (*yig == 'x') trace(yig);
+
+ if (strncmp(yig, "x___active{", MAX_KEY_VAL_LENGTH) == 0)
+ {
+ parseptr += parsestep;
+ active = !0;
+ if (ttlookup("x___active{", outtrans))
+ {
+ yigprint("x___active{", outtrans);
+ }
+ }
+
+ if (strncmp(yig, "x___active}", MAX_KEY_VAL_LENGTH) == 0)
+ {
+ parseptr += parsestep;
+ active = 0;
+ if (ttlookup("x___active}", outtrans))
+ {
+ yigprint("x___active}", outtrans);
+ }
+ }
+
+ if (strncmp(yig, "x___active~", MAX_KEY_VAL_LENGTH) == 0)
+ {
+ parseptr += parsestep;
+ trace("active toggle");
+ active = !active;
+ if (active)
+ {
+ if (ttlookup("x___active{", outtrans))
+ {
+ yigprint("x___active{", outtrans);
+ }
+ }else{
+ if (ttlookup("x___active}", outtrans))
+ {
+ yigprint("x___active}", outtrans);
+ }
+ }
+ }
+ }
+ if (active)
+ {
+ /*** read one syllable ***/
+ sylindex = 0;
+
+ do{
+ yig = charparse(parseptr, &parsestep, inptrans);
+ if (yig == NULL)
+ {
+ sylend = !0;
+ if ( *parseptr == ' ' || *parseptr == '\x0D'
+ || *parseptr == '\0' || *parseptr == '\n'
+ || *parseptr == '\t' )
+ {
+ }else{
+ X_ERROR_OCCURRED = !0;
+ yigprint("x___error", outtrans);
+ /* fprintf(OUTTEXT, "Input not defined"); */
+ }
+ parseptr++;
+ }else{
+ if (*yig != '.' && *yig != 'x')
+ {
+ sylend = 0;
+ }else{
+ pending_tsheg = 0;
+ sylend = !0;
+ if (strncmp(yig, ".___shad", MAX_KEY_VAL_LENGTH) == 0)
+ {
+ pending_shad_space = !0;
+ }
+ if (strncmp(yig, ".___tshegshad",
+ MAX_KEY_VAL_LENGTH) == 0)
+ {
+ pending_shad_space = !0;
+ }
+ if (strncmp(yig, "x___transp_line",
+ MAX_KEY_VAL_LENGTH) == 0)
+ {
+ while(!( *parseptr == '\0'
+ || *parseptr == '\n'))
+ {
+ fprintf(OUTTEXT, "%c", *parseptr++);
+ }
+ }
+ if (strncmp(yig, "x___transp_word",
+ MAX_KEY_VAL_LENGTH) == 0)
+ {
+ while(!(*parseptr == ' '
+ || *parseptr == '\x0D'
+ || *parseptr == '\0'
+ || *parseptr == '\t'
+ || *parseptr == '\n'))
+ {
+ fprintf(OUTTEXT, "%c", *parseptr++);
+ }
+ }
+ if (strncmp(yig, "x___transp_char",
+ MAX_KEY_VAL_LENGTH) == 0)
+ {
+ fprintf(OUTTEXT, "%c", *parseptr++);
+ }
+ }
+ if ( *yig == 'v' || *yig == 'c'
+ || *yig == 'p' || *yig == 'b')
+ {
+ pending_tsheg = !0;
+ }
+ syllable[sylindex++] = yig;
+ if (parsestep > 0)
+ {
+ parseptr += parsestep;
+ }else{
+ X_ERROR_OCCURRED = !0;
+ yigprint("x___error", outtrans);
+ fprintf(OUTTEXT, "sylr 2");
+ parseptr++;
+ }
+ }
+ }
+ while (!sylend);
+
+ /*** trace("syllable read"); ***/
+
+ /******************************/
+ /* */
+ /* Syllable Analysis */
+ /* */
+ /******************************/
+
+
+ /* does syllable contain a prefix ? */
+ if (sylindex >= 3)
+ /* at least 2 chars + 1 (inherent)vovel */
+ {
+ if (*syllable[0] == 'p'
+ /* potential prefix marked as such in ttd */
+
+ && *syllable[1] != 'v'
+ /* vovel? -> pot. prefix is main letter */
+
+ /* is pot. prefix part of a ligature? */
+ && !(strncmp(syllable[0], "p___'a",
+ MAX_KEY_VAL_LENGTH) != 0
+ /* 'a is NEVER upper part of a ligature */
+ /* ( I at least hope so ) */
+
+ && *syllable[1] == 'b'
+ /* ya, ra, la, wa subjoined to pot. prefix */
+
+ && *syllable[2] == 'v'
+ /* ligature complete -> no prefix
+ examples: bya, gya ....
+ negative examples: brgyad ... */
+
+ /* WARNING: gyin, gyas ... give wrong result
+ (ambiguous transcript).
+ Work around this using the
+ dummy vovel (usually '-').
+ Examples: g-yin, g-yas, bu -ddha, ...
+ */
+ )
+ )
+ {
+ yigprint(syllable[0], outtrans); /* output prefix */
+ for (i = 0; i < sylindex; i++)
+ {
+ /* shift away prefix */
+ syllable[i] = syllable[i + 1];
+ }
+ sylindex--;
+ }
+ } /* min length for prefix */
+
+ /******************************/
+ /* */
+ /* Ligature Generation */
+ /* */
+ /******************************/
+
+ i = 0;
+ while (vovel_left(syllable, i, sylindex))
+ {
+ if (*syllable[i] == 'v' &&
+ strncmp(syllable[i], "v___dummy", MAX_KEY_VAL_LENGTH)
+ != 0)
+ {
+ strncpy(lig_key, "c___a", MAX_KEY_VAL_LENGTH);
+ }
+ else if(*syllable[i + 1] == 'v')
+ {
+ strncpy(lig_key, syllable[i++], MAX_KEY_VAL_LENGTH);
+ }
+ else
+ {
+ geni = i;
+ strncpy(lig_key, "l__", MAX_KEY_VAL_LENGTH);
+ while (i < sylindex && *syllable[i] != 'v')
+ /* compose ligature key */
+ {
+ charptr = syllable[i];
+ charptr += 3; /* cut off type */
+ /* example p___ba + b___ya => l___ba_ya */
+
+ strncat(lig_key, charptr, MAX_KEY_VAL_LENGTH);
+ i++;
+ }
+ }
+ strncpy(inner_vovel_key_buf, syllable[i++],
+ MAX_KEY_VAL_LENGTH);
+
+ if (i < sylindex)
+ {
+ if (*syllable[i] == 'v')
+ {
+ strncpy( outer_vovel_key_buf, syllable[i++],
+ MAX_KEY_VAL_LENGTH);
+ strncat( outer_vovel_key_buf, "{",
+ MAX_KEY_VAL_LENGTH);
+ yigprint(outer_vovel_key_buf, outtrans);
+ }else{
+ *outer_vovel_key_buf = '\0';
+ }
+ }else{
+ *outer_vovel_key_buf = '\0';
+ }
+ strncat( inner_vovel_key_buf, "{", MAX_KEY_VAL_LENGTH);
+ yigprint(inner_vovel_key_buf, outtrans);
+
+ if (ttlookup(lig_key, outtrans))
+ {
+ /* Predefined ligature */
+ yigprint(lig_key, outtrans);
+ }else{
+ /* Automatic ligature generation */
+ yigprint("x___outer_box{", outtrans);
+ while (*syllable[geni] != 'v')
+ {
+ yigprint("x___inner_box{", outtrans);
+
+
+ /* Look for predefined two-letter ligatures
+ within generic ligature */
+ charptr = NULL;
+ if (*syllable[geni+1] != 'v')
+ {
+ strncpy(lig_key, "l__", MAX_KEY_VAL_LENGTH);
+ charptr = syllable[geni];
+ charptr += 3;
+ strncat(lig_key, charptr, MAX_KEY_VAL_LENGTH);
+ charptr = syllable[geni+1];
+ charptr += 3;
+ strncat(lig_key, charptr, MAX_KEY_VAL_LENGTH);
+ charptr = ttlookup(lig_key, outtrans);
+ }
+
+ if (charptr)
+ {
+ yigprint(lig_key, outtrans);
+ geni += 2;
+ }else{
+ /* Single-letter generic ligature part */
+ yigprint(syllable[geni++], outtrans);
+ }
+ yigprint("x___inner_box}", outtrans);
+ }
+ yigprint("x___outer_box}", outtrans);
+ }
+
+ inner_vovel_key_buf[strlen(inner_vovel_key_buf) - 1] = '}';
+ yigprint(inner_vovel_key_buf, outtrans);
+
+ if (*outer_vovel_key_buf != '\0')
+ {
+ outer_vovel_key_buf[strlen(outer_vovel_key_buf) - 1]
+ = '}';
+ yigprint(outer_vovel_key_buf, outtrans);
+ }
+
+ } /* while vovel left */
+
+ while (i < sylindex) /* output suffix */
+ {
+ yigprint(syllable[i], outtrans);
+ i++;
+ }
+
+ if (pending_tsheg)
+ {
+ yigprint(".___tsheg", outtrans);
+ pending_tsheg = 0;
+ }
+
+ if (pending_shad_space && (*parseptr == ' '
+ || *parseptr == '\t'
+ || *parseptr == '\x0D'
+ || *parseptr == '\0'
+ || *parseptr == '\n'))
+ {
+ yigprint(".___shad_space", outtrans);
+ }
+ pending_shad_space = 0; /* MUST be after '}' */
+
+ }else{ /* not active */
+// if (strncmp(parseptr, "%%", 2) == 0)
+// {
+// active = !0;
+ fprintf(OUTTEXT, "%c", *parseptr++);
+ }
+
+ } /* while parseptr */
+
+ fprintf(OUTTEXT, "\n");
+
+ } /* while fgets */
+
+ yigprint("x___postamble", outtrans);
+ fprintf(OUTTEXT, "\n");
+
+ if (X_ERROR_OCCURRED)
+ {
+ exit(1);
+ }else{
+ exit(0);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+