summaryrefslogtreecommitdiff
path: root/language/oriya/bin
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /language/oriya/bin
Initial commit
Diffstat (limited to 'language/oriya/bin')
-rw-r--r--language/oriya/bin/oriya.c1147
1 files changed, 1147 insertions, 0 deletions
diff --git a/language/oriya/bin/oriya.c b/language/oriya/bin/oriya.c
new file mode 100644
index 0000000000..c526900e8d
--- /dev/null
+++ b/language/oriya/bin/oriya.c
@@ -0,0 +1,1147 @@
+/***************************************************************************/
+/* */
+/* oriya.c v0.99 */
+/* */
+/* Source code for "Oriya-TeX" preprocessor. */
+/* Anshuman Pandey <apandey@u.washington.edu>, 2003/01/22 */
+/* */
+/* Based on Revision 1.1 1996/03/05 of skt.c preprocessor developed by */
+/* Charles Wikner <wikner@nacdh4.nac.ac.za> */
+/* */
+/***************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+/* DECLARE FUNCTIONS */
+void exit (int);
+void search (void);
+void write_outbuf(void);
+void write_line (char *);
+char * str_find (char *, char *);
+void getline (void);
+char * command (char *);
+void error (char *, int);
+void process (void);
+void chrcat (char *, char);
+void bncont (void);
+void bnword (void);
+void single (char);
+void frontac (void);
+void backac (void);
+void sam_warning (void);
+void samyoga (void);
+
+FILE *infile, *outfile, *fopen();
+char infilename[80];
+char outfilename[80];
+
+#define TRUE 1
+#define FALSE 0
+
+unsigned char bnline; /* flag TRUE if there is any Oriya on this line */
+unsigned char bnmode; /* flag TRUE while within {\orx } */
+unsigned char eof_flag; /* flag True when end of file detected */
+unsigned char ac_flag; /* flag TRUE while processing Oriya vowels */
+unsigned char roman_flag; /* flag TRUE if previous output was Roman string */
+
+int nest_cnt; /* '{' increments, '}' decrements, while in \orx */
+int err_cnt; /* incremented by any error while in \orx */
+#define err_max 10 /* after err_max errors, program aborts */
+int line_cnt; /* line number of current input line */
+
+char inbuf[133]; /* input file line buffer of text being processed */
+char *i_ptr; /* general pointer to input buffer */
+char outbuf[512]; /* output file line buffer of text processed */
+char *o_ptr; /* general pointer to output buffer */
+
+unsigned char cont_end; /* flag TRUE when line ends with %-continuation */
+unsigned char cont_begin; /* flag TRUE when line begins after %-continuation */
+unsigned char hal_flag; /* flag TRUE when hal_type detected in syllable */
+unsigned char ac_char; /* storage for working vowel character */
+unsigned char pre_ra; /* storage/flag for 'r' at beginning of samyoga */
+char ac_hook; /* vowel diacritic code */
+char bnbuf[255]; /* storage for Oriya in internal code */
+char *s_ptr; /* general pointer to Oriya buffer */
+char *old_sptr; /* points to samyoga start; used by warning message */
+char work[80]; /* general scratchpad */
+char *w_ptr; /* general pointer to work buffer */
+char tmp[80]; /* temporary buffer for previous syllable */
+int ra; /* post_ra type to use with this character */
+int ya; /* post_ya type to use with this character */
+int va; /* post_va type to use with this character */
+int na; /* post_na type to use with this character */
+int ma; /* post_ma type to use with this character */
+int la; /* post_la type to use with this character */
+int post_ra; /* flag to append ra to samyoga */
+int post_ya; /* flag to append ya to samyoga */
+int post_va; /* flag to append va to samyoga */
+int post_na; /* flag to append na to samyoga */
+int post_ma; /* flag to append ma to samyoga */
+int post_la; /* flag to append la to samyoga */
+int hasanta; /* flag to add hasanta to samyoga (i.e. no vowel) */
+int hr_flag; /* flag indicates vowel picked up in samyoga (h.r) */
+int low;
+
+
+/***************************************************************************/
+/* Function: main() */
+/***************************************************************************/
+
+main(argc,argv)
+int argc;
+char *argv[];
+{ char *p; int k;
+
+ /* Initialization */
+
+ bnmode = eof_flag = FALSE;
+ nest_cnt = err_cnt = 0;
+ line_cnt = 0;
+ i_ptr = inbuf; *i_ptr = '\0';
+ s_ptr = bnbuf; *s_ptr = '\0';
+ o_ptr = outbuf; *o_ptr = '\0';
+
+ /* handle command-line options */
+
+ k=0;
+ if (argc>1) strcpy(infilename,argv[1]);
+ if (strcmp(infilename,"-h")==0)
+ { k=1;
+ strcpy(infilename,"");
+ printf("Preprocessor for \"Oriya-TeX\" package v.099, 2003.01.22\n");
+ printf("Anshuman Pandey <apandey@u.washington.edu>\n");
+ printf("Syntax: oriya infile[.or] [outfile[.tex]]\n");
+ exit(0);
+ }
+
+ /* then get file names */
+ switch(argc-k)
+ { case 3: strcpy(infilename,argv[1+k]);
+ strcpy(outfilename,argv[2+k]);
+ break;
+ case 2: strcpy(infilename,argv[1+k]);
+ strcpy(outfilename,"");
+ break;
+ default: strcpy(infilename,"");
+ while(strlen(infilename) == 0)
+ { printf("Input file: "); gets(infilename); }
+ printf("Output file: ");
+ gets(outfilename);
+ }
+
+ if (strlen(outfilename) == 0)
+ { strcpy (outfilename,infilename); /* default output file name */
+ p = strchr(outfilename,'.');
+ if (p != 0) *p = '\0'; /* delete out file name extension */
+ }
+ p = strchr(infilename,'.');
+ if (p == 0) strcat(infilename,".or"); /* default input file extension */
+ if ((infile=fopen(infilename,"r")) == NULL)
+ { printf("Cannot open file %s\n",infilename); exit(1); }
+ getline(); if (eof_flag)
+ { printf("Input file %s is empty.\n",infilename); exit(1); }
+ p = strchr(outfilename,'.');
+ if (p == 0)
+ { if (inbuf[0] == '@') strcat(outfilename,".dn");
+ else strcat(outfilename,".tex"); /* set default output file extension */
+ }
+ if ((outfile=fopen(outfilename,"w")) == NULL)
+ { printf("Cannot open output file %s\n",outfilename); exit(1); }
+
+ /* Normal main loop */
+
+ while(eof_flag == 0)
+ { while(!bnmode && !eof_flag) search(); /* search for \orx command */
+ while( bnmode && !eof_flag) process(); /* process Oriya text */
+ if (err_cnt >= err_max)
+ { printf("Too many (%d) errors, aborting program\n",err_cnt); break; }
+ }
+ if ((err_cnt < err_max) && (nest_cnt != 0))
+ printf("Brace mismatch within \\orx = %d\n",nest_cnt);
+ fclose(infile);
+ fclose(outfile);
+ exit(1);
+
+}
+
+
+/***************************************************************************/
+/* Function: search() */
+/* */
+/* Search inbuf for '{\orx', getting more input lines as necessary */
+/* until string found or end of file, copying input to output; if */
+/* the string is found but command not recognised, it is treated as */
+/* ordinary text; if valid command i_ptr points to first sanskrit */
+/* char after command, and sets bnmode TRUE. */
+/***************************************************************************/
+
+void search(void)
+{
+unsigned char c;
+char *p,*q;
+ while (eof_flag == 0)
+ { p = str_find(i_ptr,"{\\orx");
+ if (p == 0)
+ { if (bnline == TRUE) { strcat(outbuf,i_ptr); write_outbuf(); }
+ else { write_line(inbuf); o_ptr = outbuf; *o_ptr = '\0'; }
+ getline();
+ continue;
+ }
+ q = i_ptr; i_ptr = p;
+ if ((p = command(p)) == 0) /* test command string \orx */
+ { p = i_ptr; i_ptr = q; /* if bad \orx command */
+ c = *++p; *p = '\0'; /* copy partial line, and search more */
+ strcat(outbuf,i_ptr); *p = c; i_ptr = p; continue;
+ }
+ i_ptr = q;
+ nest_cnt++; c = *p; *p = '\0'; /* skip over '{\orx' */
+ strcat(outbuf,i_ptr); /* append partial line to outbuf */
+ *p = c; i_ptr = p;
+ bnmode = TRUE; bnline = TRUE; /* now comes the fun! */
+ break;
+ }
+}
+
+
+/***************************************************************************/
+/* Function: write_outbuf() */
+/* */
+/* Write outbuf in 80 character lines */
+/***************************************************************************/
+
+void write_outbuf(void)
+{
+char c, d, e;
+ while(1)
+ { c = '\0';
+ if (strlen(outbuf) < 81) { write_line(outbuf); break; }
+ for (o_ptr = outbuf + 78; o_ptr > outbuf + 50; o_ptr--)
+ { if (*o_ptr == ' ') break; }
+ if (*o_ptr != ' ') { for (o_ptr = outbuf+78; o_ptr > outbuf + 50; o_ptr--)
+ if ((*o_ptr=='\\') && (*(o_ptr-1)!='\\')) break;
+ if (o_ptr == outbuf+50) o_ptr = outbuf+78;
+ c = *o_ptr; *o_ptr++ = '%'; d = *o_ptr;
+ }
+ *o_ptr++ = '\n'; e = *o_ptr; *o_ptr = '\0';
+ write_line(outbuf);
+ *o_ptr = e;
+ if (c!='\0') { *--o_ptr = d; *--o_ptr = c; } /* restore displaced chars */
+ strcpy(outbuf,o_ptr);
+ }
+ o_ptr = outbuf;
+ *o_ptr = '\0';
+}
+
+
+/***************************************************************************/
+/* Function: write_line() */
+/* */
+/* Write p-string to output device */
+/***************************************************************************/
+
+void write_line(char *p)
+{
+ if (err_cnt == 0) fputs(p,outfile);
+}
+
+
+/***************************************************************************/
+/* Function: str_find() */
+/* */
+/* Find first occasion of string *str within *buf before '%' char; */
+/* return pointer first char of str within buf, else 0. */
+/***************************************************************************/
+
+char * str_find(char *buf, char *str)
+{ char *p, *x;
+ p = strstr(buf,str);
+ if (p == 0) return(0);
+ x = strchr(buf,'%');
+ if ((x != 0) && (p > x)) return(0);
+ return(p);
+}
+
+
+/***************************************************************************/
+/* Function: getline() */
+/* */
+/* Get another line from input file; reset i_ptr, increments */
+/* line_cnt, and sets eof_flag if EOF. */
+/***************************************************************************/
+
+void getline(void)
+{
+char *p;
+ i_ptr = inbuf;
+ *i_ptr = '\0';
+ line_cnt++;
+ if (fgets(inbuf,133,infile) == NULL) eof_flag = TRUE;
+ if (bnmode == FALSE) bnline = FALSE;
+}
+
+
+/***************************************************************************/
+/* Function: command() */
+/* */
+/* Check for valid \orx command; if invalid command, print error message */
+/***************************************************************************/
+
+char * command(char *p)
+{ p += 5; /* skip over '{\orx' */
+ if (*p++ != ' ') p = 0;
+ if (p == 0) error("Unrecognised command string",7);
+ return(p);
+}
+
+
+/***************************************************************************/
+/* Function: error() */
+/* */
+/* Print out error message, including string *s and 'n' characters */
+/* of inbuf. */
+/***************************************************************************/
+
+void error(char *s, int n)
+{ char err_str[80]; int j;
+ if (++err_cnt <= err_max)
+ { if (n > 0) { for (j=0; j<n; j++) err_str[j] = *(i_ptr+j);
+ err_str[j] = '\0';
+ }
+ if (n == 0) { strcpy(err_str,"oct(");
+ chrcat(err_str,'0' + (*i_ptr/64));
+ chrcat(err_str,'0' + (*i_ptr/8));
+ chrcat(err_str,'0' + (*i_ptr & 7));
+ strcat(err_str,")");
+ }
+ if (n < 0) { err_str[0] = '\0'; }
+ }
+ printf("Line %4d Error: %s %s\n",line_cnt,s,err_str);
+}
+
+
+/***************************************************************************/
+/* Function: process() */
+/* */
+/* Process input text within {\orx, converting to internal format in bnbuf */
+/***************************************************************************/
+
+#define ISAC(c) (((strchr("aAiIuUxXeEoO",c) != 0) && c) ? TRUE : FALSE)
+
+/* wW removed from the definition of ISAC above (.R .L) */
+
+void process(void)
+{ int cap_flag, underscore;
+unsigned char *i, c, d;
+#define CF ac_flag=underscore=cap_flag=roman_flag=FALSE
+#define CC CF; continue
+#define CR ac_flag=underscore=cap_flag=FALSE;
+#define CI i_ptr++; CC
+
+ CF;
+ while(1)
+ { if (eof_flag) return;
+ if (err_cnt >= err_max)
+ { bnmode = FALSE; return; }
+ c = *i_ptr; d = *(i_ptr+1);
+/* END OF LINE */
+ if ((c == '\0') || (c == '\n'))
+ { bnword(); strcat (outbuf,i_ptr); write_outbuf(); getline(); CC; }
+/* IMBEDDED ROMAN */
+ if (strchr("!'()*+,-/:;=?[]`",c) || ((c == '.') && (*(i_ptr+1) == '.')))
+ { if (c == '.') i_ptr++;
+ if (bnbuf[0]) { bnword(); }
+ while(1)
+ { chrcat(outbuf,c); c = *++i_ptr;
+ if (c == '.')
+ { if (*(i_ptr+1) != '.') break;
+ i_ptr++; continue;
+ }
+ if ((strchr("!'()*+,-/:;=?[]`",c) && c) == 0) break;
+ }
+ CR; continue;
+ }
+/* ILLEGAL CHARS */
+ if (strchr("_$fqwxzBCDEFGJKNOPQSTVWXYZ\177",c))
+ { error("Illegal oriya character: ",1); CI; }
+ if (c>127) { error("Invalid character >80H: ",1); CI; }
+/*?? Since we are now case sensitive (unlike skt), the list of */
+/*?? illegal chars has been increased (_ added, and & removed) */
+/* CONTROL CHARACTERS */
+ if (c < ' ')
+ { error("Illegal control character: ",0); CI; }
+/* IMBEDDED LATEX COMMAND STRINGS */
+ if (c == '\\')
+ { if (d == '-') /* imbedded discretionary hyphen */
+ { strcat(bnbuf,"!"); i_ptr++; CI; }
+ bnword();
+ if (isalpha(d) == 0)
+ { chrcat(outbuf,c); chrcat(outbuf,*++i_ptr); CI; }
+ else
+ { while (1)
+ { chrcat(outbuf,c); c = *++i_ptr; if (isalpha(c) == 0) break; }
+ }
+ CC;
+ }
+/* SPACE CHAR */
+ if (c == ' ')
+ { bnword(); while(*++i_ptr == ' '); chrcat(outbuf,c); CC;
+ }
+/*?? slight change here, since underscore is now an illegal character */
+/* COMMENT DELIMITER */
+ if (c == '%')
+ { if (*(i_ptr+1) == '\n') bncont();
+ else bnword();
+ strcat(outbuf,i_ptr); write_outbuf(); getline(); CC;
+ }
+
+/* HASANTA */
+ if (c == '&') {
+ c = '@';
+ }
+
+/* BRACES */
+ if (c == '{') { if (d == '}') { i_ptr++; CI; } /* for words like pra{}uga */
+ else { nest_cnt++; bncont(); chrcat(outbuf,c); CI; }
+ }
+ if (c == '}')
+ { bnword(); chrcat(outbuf,c);
+ if (--nest_cnt == 0)
+ { bnmode = FALSE;
+ i_ptr++; return;
+ }
+ else CI;
+ }
+/* UPPER CASE */
+ if (isupper(c))
+ { switch (c)
+ { case 'A':
+ case 'I':
+ case 'U':
+ case 'M':
+ case 'H': break;
+ case 'L': break;
+ case 'R': c = 'w'; break;
+ default: c = '*'; break;
+ }
+ if (c=='*') { error("Invalid upper case: ",1); CI; }
+ }
+/*?? big change with that code: the upper case has a different *meaning* than */
+/*?? the lower case: fortunately, AIUMH are the same as the internal code :-) */
+
+/* EQUATE VA WITH BA */
+ if (c == 'v') {
+ c = 'b';
+ }
+
+/* DOT_CHAR */
+ if (c == '.') { switch(d)
+ { case 'y': c = 'Y'; break;
+ case 'd': c = 'q'; break;
+ case 'h': c = 'H'; break;
+ case 'l': c = 'X'; break;
+ case 'm': c = 'M'; break;
+ case 'n': c = 'N'; break;
+ case 'o': c = '%'; break;
+ case 'r': c = 'x'; break;
+ case 's': c = 'S'; break;
+ case 't': c = 'f'; break;
+ case 'a': c = '\\'; break;
+ case 'b': c = 'v'; break;
+ }
+ if (c=='.') { error("Invalid dot_character: ",2); CI; }
+ i_ptr++; d = *(i_ptr+1);
+ }
+
+/* NEXT CHAR IS H */
+ if (d=='h')
+ { if (strchr("bcdfgjkptqw",c)) { c=toupper(c); i_ptr++; d=*(i_ptr+1); }
+ }
+
+/* The upper/lowercase stuff removed: a following 'h' converts a consonant */
+/* to its upper case internal code, e.g th --> T. Note that 'w' is added */
+/* to the list for R Rh */
+
+/* QUOTE CHAR */
+ if (c == '\"') { switch(d)
+ { case 'n': c = 'z'; break;
+ case 's': c = 'Z'; break;
+ }
+ if (c=='\"') { error("Invalid quote_character",2); CI; }
+ i_ptr++; d = *(i_ptr+1);
+ }
+
+/* TILDE CHAR */
+ if (c == '~') { switch (d)
+ { case 'n': c = 'V'; break;
+ case 'm': c = '~'; break;
+ case 'r': c = 'R'; break;
+ default : c = '*'; break;
+ }
+ if (c=='*')
+ { error("Invalid use of tilde character: ",2); CI; }
+ i_ptr++; d = *(i_ptr+1);
+ }
+/* TWO CHAR VOWELS */
+ if ( strchr("aiu",c) && strchr("aiu",d) )
+ { switch(c)
+ { case 'a': switch(d)
+ { case 'a': c = 'A'; break;
+ case 'i': c = 'E'; break;
+ case 'u': c = 'O'; break;
+ } break;
+ case 'i': if (d=='i') c = 'I'; break;
+ case 'u': if (d=='u') c = 'U'; break;
+ }
+ if (isupper(c)) { i_ptr++; d = *(i_ptr+1); }
+ }
+/*?? all the upper/lowercase stuff removed */
+/* NOW CHAR SHOULD BE INTERNAL REPRESENTATION OF SANSKRIT CHAR */
+ if ( ((c=='~' || c=='M') && !(ac_flag)) ) {
+ i_ptr -=2; error("No vowel before nasal: ",3); i_ptr +=2; CF;
+ }
+
+ if (c=='H' && !(ac_flag)) {
+ i_ptr -=2; error("No vowel before visarga: ",3); i_ptr +=2; CF;
+ }
+
+ chrcat(bnbuf,c);
+ CR;
+ if (ISAC(c)) ac_flag = TRUE;
+ i_ptr++;
+ }
+}
+
+#undef CI
+#undef CC
+#undef CR
+#undef CF
+
+
+/***************************************************************************/
+/* Function: chrcat() */
+/* */
+/* Append character c to end of buffer s */
+/***************************************************************************/
+
+void chrcat(char *s, char c)
+{ char temp[] = " "; temp[0] = c; strcat(s,temp);
+}
+
+
+/***************************************************************************/
+/* Function: bncont() */
+/* */
+/* Similar to bnword() but used where input text line ends in '%' to */
+/* continue on next line. */
+/***************************************************************************/
+
+void bncont(void)
+{
+ cont_end = TRUE; bnword();
+ cont_end = FALSE; cont_begin = TRUE;
+}
+
+
+/***************************************************************************/
+/* Function: bnword() */
+/* */
+/* Convert contents of bnbuf to output string in outbuf */
+/***************************************************************************/
+
+/* internal code for consonants */
+static char hal_chars[] = "BCDFGJKLNPQRSTVWYZbcdfghjklmnpqrstvwyz";
+
+#define ISHAL(c) (((strchr(hal_chars,c) != 0) && c) ? TRUE : FALSE)
+
+#define CLRFLAGS ac_hook=post_ra=pre_ra=hasanta=hal_flag=post_ya=post_va=post_na=post_ma=post_la=0
+
+#define CAT(w,x,z) \
+strcat(w,x); strcat(w,z)
+
+void bnword(void)
+{ char c;
+ if (roman_flag && bnbuf[0]) { strcat(outbuf,"\\,"); roman_flag = FALSE; }
+
+/* A word is built up one syllable at a time: a syllable typically comprises */
+/* a consonant (or samyoga) followed by a vowel (with its nasalisation). */
+/* If there is no consonant, then a front-vowel is output; if there */
+/* is no vowel, then a viraama is appended to the consonant/samyoga. */
+/* One effect of this is that, if a consonant cluster is not fully resolved */
+/* into a single samyoga, it will be treated as two syllable: in particular, */
+/* the hook of the short-i will span one samyoga only. */
+/* */
+/* The `work' buffer is used as a scratchpad while building a syllable; on */
+/* completion it is stored in the `tmp' buffer before shipping to the output */
+/* buffer. This temporary storage while working on the next syllable, allows */
+/* changes to the back spacing of the previous syllable for more effiecient */
+/* output. */
+/* */
+/* `ra' is difficult: the first `r' of a consonant cluster is simply flagged */
+/* in `pre_ra', and similarly the final `r' in `post_ra', and then these are */
+/* dealt with when appending a vowel. */
+
+ CLRFLAGS;
+ s_ptr = bnbuf; c = *s_ptr;
+ if (c == '\0') return;
+ *tmp = '\0'; *work = '\0';
+ while (1)
+ { CLRFLAGS; /* in particular, need to clear hal_flag for the likes of kara */
+ c= *s_ptr++;
+ if (c == '\0')
+ { if (*tmp) { if (outbuf[0]=='\0' && tmp[0]=='[') strcat(outbuf,"{}");
+ strcat(outbuf,tmp);
+ }
+ break;
+ }
+ if (ISAC(c))
+ { ac_char = c;
+ frontac();
+ if (*tmp) { if (outbuf[0]=='\0' && tmp[0]=='[') strcat(outbuf,"{}");
+ strcat(outbuf,tmp);
+ }
+ strcpy(tmp,work);
+ *work = '\0'; cont_begin = 0;
+ continue;
+ }
+ if (strchr("0123456789\"!%|\\@~HM",c))
+ { single(c);
+ if (*tmp) { if (outbuf[0]=='\0' && tmp[0]=='[') strcat(outbuf,"{}");
+ strcat(outbuf,tmp);
+ }
+ strcpy(tmp,work);
+ *work = '\0'; cont_begin = 0;
+ continue;
+ }
+ if (c == 'r') { pre_ra = TRUE; c = *s_ptr; }
+ else s_ptr--;
+ old_sptr = s_ptr; /* save pointer to start of samyoga */
+ if (ISHAL(c)) { hal_flag = TRUE; samyoga(); c = *s_ptr; }
+ ac_char = hasanta = 0;
+ if (!hr_flag) { if (ISAC(c)) { ac_char = *s_ptr++; }
+ else hasanta = TRUE; /* hr_flag = h.r parsed by samyoga */
+ }
+ backac(); hr_flag = FALSE;
+ if (*tmp) { if (outbuf[0]=='\0' && tmp[0]=='[') strcat(outbuf,"{}");
+ strcat(outbuf,tmp);
+ }
+ strcpy(tmp,work);
+ *work = '\0'; cont_begin = FALSE;
+
+ }
+ strcat(outbuf,work);
+ s_ptr = bnbuf; *s_ptr = '\0';
+ cont_begin = 0;
+}
+
+
+/***************************************************************************/
+/* Function: single() */
+/* */
+/* Output single (stand-alone) character to work buffer */
+/***************************************************************************/
+
+void single(char c)
+{
+ switch(c)
+ { case '0': strcat(work,"0"); break; /* numerals */
+ case '1': strcat(work,"1"); break;
+ case '2': strcat(work,"2"); break;
+ case '3': strcat(work,"3"); break;
+ case '4': strcat(work,"4"); break;
+ case '5': strcat(work,"5"); break;
+ case '6': strcat(work,"6"); break;
+ case '7': strcat(work,"7"); break;
+ case '8': strcat(work,"8"); break;
+ case '9': strcat(work,"9"); break;
+ case '!': strcat(tmp,"\\-"); break; /* discretionary hyphen */
+ case '%': strcat(work,"{\\char21}"); break; /* OM */
+ case '|': strcat(work,"."); break; /* dnari */
+ case '\\': strcat(work,"{\\char253}"); break; /* avagraha */
+ case '@': strcat(work,"+"); break; /* hasanta */
+ case '~': strcat(work,"/"); break; /* candrabindu */
+ case 'H': strcat(work,"{\\char250}"); break; /* visarga */
+ case 'M': strcat(work,"M"); break; /* anusvara */
+
+ }
+}
+
+
+/***************************************************************************/
+/* Function: frontac() */
+/* */
+/* Process a front-vowel to workbuf */
+/***************************************************************************/
+
+void frontac(void)
+{
+ CLRFLAGS;
+ switch(ac_char)
+ { case 'a': strcat(work,"a"); break;
+ case 'A': strcat(work,"aA"); break;
+ case 'i': strcat(work,"i"); break;
+ case 'I': strcat(work,"I"); break;
+ case 'u': strcat(work,"u"); break;
+ case 'U': strcat(work,"U"); break;
+ case 'x': strcat(work,"{\\char128}"); break;
+ case 'X': strcat(work,"{\\char132}"); break;
+ case 'e': strcat(work,"e"); break;
+ case 'E': strcat(work,"E"); break;
+ case 'o': strcat(work,"o"); break;
+ case 'O': strcat(work,"O"); break;
+ default : error("Lost in frontac()",-1);
+ }
+}
+
+
+/***************************************************************************/
+/* Function: sam_warning() */
+/* */
+/* Print a warning message that a hasanta will be used within a */
+/* samyoga. Also print input file line number, together with an */
+/* indication of the samyoga and where the viraama will be placed. */
+/***************************************************************************/
+
+void sam_warning(void)
+{
+ char *p, msg[80]="";
+ p = old_sptr;
+ if (pre_ra)
+ { strcat(msg,"r");
+ if (p==s_ptr) strcat(msg,"-");
+ }
+ while (ISHAL(*p))
+ { switch (*p)
+ { case 'B': strcat(msg,"bh"); break;
+ case 'C': strcat(msg,"ch"); break;
+ case 'D': strcat(msg,"dh"); break;
+ case 'G': strcat(msg,"gh"); break;
+ case 'H': strcat(msg,".h"); break;
+ case 'J': strcat(msg,"jh"); break;
+ case 'K': strcat(msg,"kh"); break;
+ case 'P': strcat(msg,"ph"); break;
+ case 'T': strcat(msg,"th"); break;
+ case 'f': strcat(msg,".t"); break;
+ case 'F': strcat(msg,".th"); break;
+ case 'N': strcat(msg,".n"); break;
+ case 'q': strcat(msg,".d"); break;
+ case 'Q': strcat(msg,".dh"); break;
+ case 'S': strcat(msg,".s"); break;
+ case 'V': strcat(msg,"~n"); break;
+ case 'Y': strcat(msg,".y"); break;
+ case 'z': strcat(msg,"\"n"); break;
+ case 'Z': strcat(msg,"\"s"); break;
+ default: chrcat(msg,*p); break;
+ }
+ if (++p == s_ptr) strcat(msg,"-");
+ }
+ if (ISAC(*p))
+ { switch (*p)
+ { /* case 'w': strcat(msg,".l"); break; */
+ case 'x': strcat(msg,".r"); break;
+ default: chrcat(msg,*p); break;
+ }
+ }
+ printf("Line %4d Warning: samyoga viraama: %s\n",line_cnt,msg);
+}
+
+
+/***************************************************************************/
+/* Function: backac() */
+/* */
+/* Handle vowel diacritics */
+/***************************************************************************/
+
+void backac(void)
+{ int j,k; char c, *p;
+
+ if (pre_ra && (*work=='\0')) /* case r.r, r.R, r.l, r.L, ru, rU, ra */
+ { c = toupper(ac_char);
+ /* if (c == 'X') {frontac(); } */
+
+ if (c == 'X') {
+ frontac();
+ if ((ac_char == 'x') || (ac_char == 'X')) {
+ strcat(work,"{\\char147}");
+ ac_char = 'a';
+ }
+ } else {
+ strcat(work,"r");
+ }
+
+ pre_ra = FALSE; hal_flag = TRUE;
+ }
+
+ if (post_ra) { strcat(work,"{\\char146}"); } /* ra-phala */
+ if (post_ya) { strcat(work,"{\\char138}"); } /* ya-phala */
+ if (post_va) { strcat(work,"{\\char164}"); } /* va-phala */
+ if (post_na) { strcat(work,"{\\char240}"); } /* na-phala */
+ if (post_ma) { strcat(work,"{\\char136}"); } /* ma-phala */
+ if (post_la) { strcat(work,"{\\char155}"); } /* ma-phala */
+ post_la = post_ma = post_na = post_va = post_ya = post_ra = 0;
+
+ c = ac_char;
+
+ if (pre_ra) { strcat(work,"{\\char147}"); } /* add repha */
+ if (hasanta) { strcat(work,"+"); } /* add halanta */
+
+ if (ac_char == 'A') { strcat(work,"A");} /* add aa-dia */
+ if (ac_char == 'i') { strcat(work,"{\\char91}");} /* add aa-dia */
+ if (ac_char == 'I') { strcat(work,"X"); } /* add ii-dia */
+ if (ac_char == 'u') { /* add u-dia */
+ if (low) {
+ strcat(work,"{\\char216}");
+ low = FALSE;
+ } else {
+ strcat(work,"{\\char93}");
+ }
+ }
+ if (ac_char == 'U') { strcat(work,"{\\char90}");} /* add uu-dia */
+ if (ac_char == 'x') { strcat(work,"{\\char129}");} /* add .r dia */
+ if (ac_char == 'X') { strcat(work,"{\\char133}");} /* add .l dia */
+ if (ac_char == 'e') { CAT(tmp,"<",""); } /* add e-dia */
+ if (ac_char == 'E') { CAT(tmp,"<",""); strcat(work,">");} /* add ai-dia */
+ if (ac_char == 'o') { CAT(tmp,"<",""); strcat(work,"A");} /* add o-dia */
+ if (ac_char == 'O') { CAT(tmp,"<",""); strcat(work,"*");} /* add au-dia */
+
+}
+
+/***************************************************************************/
+/* Function: samyoga() */
+/* */
+/* Work along bnbuf sequentially to build up a samyoga print */
+/* string in the work buffer and update the samyoga parameters. */
+/* */
+/* The method is quite unsophisticated, but its simplicity lends */
+/* clarity for later additions or changes, and for this reason */
+/* is done in Devanagari alphabetical order, but with longer */
+/* strings before shorter. */
+/* */
+/* Cr and Cy conjuncts are not defined in the individual cases for each */
+/* consonant. Rather these are handled in bulk by the program at the end */
+/* of the function. */
+/* */
+/* Macros are used to simplify reading the program --- believe it or not! */
+/* */
+/* Switch/case is used on the first letter, then the main LS macro tests: */
+/* (1) if the test string matches the input exactly, then */
+/* (2) bump input pointer to the character after string match */
+/* (3) use NC etc macro to break out of switch instruction */
+/***************************************************************************/
+
+
+#define LS(a,c,z) n=strlen(a); \
+ if(strncmp(p,a,n)==0) { strcat(work,z); p+=n; c;}
+
+#define NX sam_flag = 'X'; break;
+#define NR sam_flag = 'R'; break;
+#define NC sam_flag = 'C'; break;
+
+#define IX p++; sam_flag = 'X'; break;
+#define IR p++; sam_flag = 'R'; break;
+#define IC p++; sam_flag = 'C'; break;
+
+/******************************************************************************/
+
+void samyoga(void)
+{
+char *p, sam_flag; int n;
+ sam_flag = 0;
+ p = s_ptr;
+ while (1)
+ { if (!ISHAL(*p)) { NX; }
+ switch (*p++)
+ {
+
+
+ /* k */
+ case 'k': if(*p=='A')
+ {p+=1; strcat(work,"{\\char157}"); hr_flag = TRUE; NR;}
+ if(*p=='i')
+ {p+=1; strcat(work,"{\\char141}"); hr_flag = TRUE; NR;}
+ if(*p=='u')
+ {p+=1; strcat(work,"{\\char139}"); hr_flag = TRUE; NR;}
+ if(*p=='U')
+ {p+=1; strcat(work,"{\\char150}"); hr_flag = TRUE; NR;}
+ if(*p=='S' && *(p+1)=='N')
+ {p+=2; strcat(work,"{\\char225}");NR;}
+ LS("k", NR, "{\\char199}" );
+ LS("f", NR, "{\\char27}" );
+ LS("t", NR, "{\\char182}" );
+ LS("T", NR, "k{\\char195}" );
+ LS("r", NR, "{\\char176}" );
+ LS("s", NR, "{\\char203}" );
+ LS("S", NR, "x" );
+ strcat(work,"k"); NR;
+
+ /* kh */
+ case 'K': strcat(work,"K"); NR;
+
+ /* g */
+ case 'g': LS("g", NR, "{\\char30}" );
+ LS("D", NR, "{\\char31}" );
+ strcat(work,"g"); NR;
+
+ /* gh */
+ case 'G': strcat(work,"G"); NR;
+
+ /* "n */
+ case 'z': if(*p=='k' && *(p+1)=='S')
+ {p+=2; strcat(work,"");NR;}
+ LS("k", NR, "{\\char148}");
+ LS("K", NR, "{\\char159}");
+ LS("g", NR, "{\\char160}");
+ LS("G", NR, "{\\char202}");
+ LS("z", NR, "{\\char10}");
+ LS("t", NR, "f{\\char174}");
+ LS("D", NR, "{\\char10}");
+ strcat(work,"f"); NR;
+
+ /* c */
+ case 'c': if(*p=='A')
+ {p+=1; strcat(work,"{\\char137}"); hr_flag = TRUE; NR;}
+ LS("c", NR, "{\\char152}");
+ LS("C", NR, "{\\char210}");
+ strcat(work,"c"); NR;
+
+ /* ch */
+ case 'C': strcat(work,"C"); NR;
+
+ /* j */
+ case 'j': LS("j", NR, "{\\char153}" );
+ LS("J", NR, "{\\char36}" );
+ LS("V", NR, "{\\char179}" );
+ strcat(work,"j"); NR;
+
+ /* jh */
+ case 'J': strcat(work,"J"); NR;
+
+ /* ~n */
+ case 'V': LS("c", NR, "{\\char172}" );
+ LS("C", NR, "{\\char230}" );
+ LS("j", NR, "{\\char189}" );
+ LS("J", NR, "{\\char173}" );
+ strcat(work,"F"); NR;
+
+ /* .t */
+ case 'f': LS("k", NR, "{\\char10}" );
+ LS("f", NR, "{\\char161}" );
+ LS("F", NR, "{\\char10}" );
+ strcat(work,"q"); NR;
+
+ /* .th */
+ case 'F': strcat(work,"Q"); NR;
+
+ /* .da */
+ case 'q': if(*p=='i')
+ {p+=1; strcat(work,"{\\char14}"); hr_flag = TRUE; NR;}
+ LS("g", NR, "{\\char127}" );
+ LS("q", NR, "{\\char236}" );
+ strcat(work,"w"); NR;
+
+ /* .dh */
+ case 'Q': if(*p=='i')
+ {p+=1; strcat(work,"{\\char15}"); hr_flag = TRUE; NR;}
+ strcat(work,"W"); NR;
+
+ /* .n */
+ case 'N': LS("f", NR, "{\\char242}" );
+ LS("F", NR, "{\\char220}" );
+ LS("q", NR, "{\\char187}" );
+ LS("Q", NR, "{\\char188}" );
+ LS("N", NR, "{\\char186}" );
+ LS("t", NR, "{\\char10}" );
+ /* LS("m", NR, "\\oSp{G}" ); */
+ strcat(work,"N"); NR;
+
+ /* t */
+ case 't': if(*p=='A')
+ {p+=1; strcat(work,"{\\char12}"); hr_flag = TRUE; NR;}
+ if(*p=='i')
+ {p+=1; strcat(work,"{\\char193}"); hr_flag = TRUE; NR;}
+ if(*p=='u')
+ {p+=1; strcat(work,"{\\char194}"); hr_flag = TRUE; NR;}
+ if(*p=='U')
+ {p+=1; strcat(work,"{\\char13}"); hr_flag = TRUE; NR;}
+ LS("k", NR, "k{\\char151}" );
+ LS("t", NR, "{\\char154}" );
+ LS("T", NR, "T{\\char151}" );
+ LS("n", NR, "{\\char162}" );
+ LS("p", NR, "{\\char28}" );
+ LS("m", NR, "{\\char163}" );
+ /* LS("y", NR, "y{\\char151}" ); */
+ LS("r", NR, "{\\char177}" );
+ LS("b", NR, "b{\\char151}" );
+ LS("Z", NR, "z{\\char151}" );
+ LS("s", NR, "{\\char241}" );
+ strcat(work,"t"); NR;
+
+ /* th */
+ case 'T': strcat(work,"T"); NR;
+
+ /* d */
+ case 'd': if(*p=='i')
+ {p+=1; strcat(work,"{\\char192}"); hr_flag = TRUE; NR;}
+ LS("g", NR, "{\\char234}");
+ LS("G", NR, "{\\char10}");
+ LS("d", NR, "{\\char169}");
+ LS("D", NR, "{\\char170}");
+ LS("b", NR, "{\\char10}");
+ LS("B", NR, "{\\char214}");
+ strcat(work,"d"); NR;
+
+ /* dh */
+ case 'D': LS("y", NR, "{\\char178}" );
+ strcat(work,"D"); NR;
+
+ /* n */
+ case 'n': if(*p=='i')
+ {p+=1; strcat(work,"{\\char22}"); hr_flag = TRUE; NR;}
+ if(*p=='t' && *(p+1)=='r')
+ {p+=2; strcat(work,"{\\char232}");NR;}
+ LS("f", NR, "{\\char10}" );
+ LS("q", NR, "{\\char10}" );
+ LS("t", NR, "{\\char226}" );
+ LS("T", NR, "{\\char227}" );
+ LS("d", NR, "{\\char165}" );
+ LS("D", NR, "{\\char166}" );
+ strcat(work,"n"); NR;
+
+ /* p */
+ case 'p': LS("t", NR, "{\\char181}" );
+ LS("p", NR, "{\\char183}" );
+ LS("s", NR, "{\\char197}" );
+ strcat(work,"p"); NR;
+
+ /* ph */
+ case 'P': strcat(work,"P"); NR;
+
+ /* b */
+ case 'b': LS("j", NR, "{\\char34}" );
+ LS("d", NR, "{\\char167}" );
+ LS("D", NR, "{\\char29}" );
+ LS("b", NR, "{\\char168}" );
+ strcat(work,"b"); NR;
+
+ /* bh */
+ case 'B': LS("N", NR, "{\\char10}" );
+ strcat(work,"B"); NR;
+
+ /* m */
+ case 'm': LS("N", NR, "\\oSp{B}" );
+ /* LS("n", NR, "{\\char163}" ); */
+ LS("p", NR, "{\\char190}" );
+ LS("P", NR, "{\\char191}" );
+ LS("B", NR, "m{\\char239}" );
+ /* LS("m", NR, "{\\char215}" ); */
+ strcat(work,"m"); NR;
+
+ /* y */
+ case 'y': strcat(work,"y"); NR;
+
+ /* .y */
+ case 'Y': strcat(work,"Y"); NR;
+
+ /* r */
+ case 'r': if(*p=='A')
+ {p+=1; strcat(work,"{\\char11}"); hr_flag = TRUE; NR;}
+ strcat(work,"r"); NR;
+
+ /* l */
+ case 'l': if(*p=='A')
+ {p+=1; strcat(work,"{\\char158}"); hr_flag = TRUE; NR;}
+ LS("k", NR, "{\\char219}" );
+ LS("g", NR, "\\oSp{I}" );
+ LS("f", NR, "{\\char10}" );
+ LS("q", NR, "{\\char10}" );
+ LS("p", NR, "{\\char221}" );
+ LS("P", NR, "{\\char223}" );
+ LS("l", NR, "{\\char237}" );
+ LS("Z", NR, "{\\char10}" );
+ LS("S", NR, "{\\char10}" );
+ strcat(work,"l"); NR;
+
+ /* v */
+ case 'v': LS("v", NR, "{\\char168}" );
+ strcat(work,"{\\char20}"); NR;
+
+ /* "s */
+ case 'Z': LS("c", NR, "{\\char205}" );
+ LS("C", NR, "{\\char229}" );
+ LS("f", NR, "{\\char204}" );
+ LS("Z", NR, "{\\char10}" );
+ strcat(work,"z"); NR;
+
+ /* .s */
+ case 'S': LS("k", NR, "{\\char200}" );
+ LS("f", NR, "{\\char198}" );
+ LS("F", NR, "{\\char207}" );
+ LS("N", NR, "{\\char16}" );
+ LS("p", NR, "{\\char184}" );
+ LS("P", NR, "{\\char222}" );
+ LS("S", NR, "{\\char10}" );
+ strcat(work,"S"); NR;
+
+ /* s */
+ case 's': if(*p=='t' && *(p+1)=='u')
+ {p+=2; strcat(work,"{\\char32}"); hr_flag = TRUE; NR;}
+ if(*p=='t' && *(p+1)=='r')
+ {p+=2; strcat(work,"{\\char233}");NR;}
+ LS("k", NR, "{\\char201}" );
+ LS("K", NR, "{\\char26}" );
+ LS("f", NR, "{\\char10}" );
+ LS("t", NR, "{\\char180}" );
+ LS("T", NR, "{\\char228}" );
+ LS("p", NR, "{\\char185}" );
+ LS("P", NR, "{\\char224}" );
+ LS("s", NR, "\\oSp{H}" );
+ strcat(work,"s"); NR;
+
+ /* h */
+ case 'h': if(*p=='i')
+ {p+=1; strcat(work,"{\\char196}"); hr_flag = TRUE; NR;}
+ if(*p=='u')
+ {p+=1; strcat(work,"{\\char140}"); hr_flag = TRUE; NR;}
+ /* if(*p=='x') { strcat(work,""); hr_flag = TRUE; IX; } */
+ LS("N", NR, "{\\char10}");
+ LS("n", NR, "{\\char94}");
+ LS("b", NR, "{\\char95}");
+ strcat(work,"h"); NR;
+
+ /* R */
+ case 'w': LS("g", NR, "{\\char126}");
+ strcat(work,"w{\\char144}"); NR;
+
+ /* Rh */
+ case 'W': strcat(work,"W{\\char144}"); NR;
+
+ /* L */
+ case 'L': if(*p=='A')
+ {p+=1; strcat(work,"{\\char208}"); hr_flag = TRUE; IX;}
+ if(*p=='i')
+ {p+=1; strcat(work,"{\\char149}"); hr_flag = TRUE; IX;}
+ strcat(work,"L"); NR;
+
+ /* Assamese r */
+ case 'R': strcat(work,""); NR;
+
+ default: error("Lost in samyoga()",-1); NX;
+ }
+
+ if (sam_flag == 'X') { s_ptr = p; break; }
+ if (sam_flag == 'R') { if ((*p=='r')) { post_ra = TRUE; p++; }
+ if ((*p=='y')) { post_ya = TRUE; p++; }
+ if ((*p=='v' || *p=='b')) { post_va = TRUE; p++; }
+ if ((*p=='n')) { post_na = TRUE; p++; }
+ if ((*p=='m')) { post_ma = TRUE; p++; }
+ if ((*p=='l')) { post_la = TRUE; p++; }
+ s_ptr = p; break;
+ }
+ if (!ISHAL(*p)) { s_ptr = p; break; }
+ }
+}
+
+/***************************************************************************/
+/* samapta */
+/***************************************************************************/