diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/devnag/src/devnag.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/devnag/src/devnag.c')
-rw-r--r-- | Build/source/texk/devnag/src/devnag.c | 2419 |
1 files changed, 2419 insertions, 0 deletions
diff --git a/Build/source/texk/devnag/src/devnag.c b/Build/source/texk/devnag/src/devnag.c new file mode 100644 index 00000000000..60a0d178e41 --- /dev/null +++ b/Build/source/texk/devnag/src/devnag.c @@ -0,0 +1,2419 @@ +/* devnag.c v2.13: 4 June 2005 + + * + Preprocessor for Devanagari for TeX package + Copyright (C) 1991-1998 University of Groningen, The Netherlands + * + Author : Frans J. Velthuis <velthuis@rc.rug.nl> + Date : 09 May 1991 + * + The maintainer of this program is now Zdenek Wagner <wagner@cesnet.cz>. + * + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + * + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + * + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + Modified by Marc Csernel, March 1998, to support LaTeX commands + with arguments and environments between the dn delimiters. + */ + +/* + Version 2.0 of devnag is the first major revision of the program + since its original release. It is based on version 1.6 (there are + no releases 1.7, 1.8 or 1.9), and, in addition to Marc Csernel's + LaTeX extensions, it incorporates the following modifications made + by John Smith in 1998-9: + + 1. A major change has been made to the way in which the + preprocessor handles "@" commands. Previously it was only + possible to use these at the start of the .dn file; now they may + be placed anywhere in the text, provided that they do not occur + within passages of Devanagari (where "@" has its own meaning). + New "negative" commands have been added to reverse the effect of + most existing commands: thus it is now possible to enable or + disable specific features for specific passages of text. @hindi + may be disabled with @sanskrit; @dollars with @nodollars or + @dolmode0; @hyphen with @nohyphen; @tabs (a new LaTeX feature + added by Marc Csernel) with @notabs. Since "@" is a perfectly + legal character in TeX, lines beginning with "@" that do not + match any valid "@" command are flagged with a warning, but + processing of the file continues. (In the somewhat unlikely + event that you actually need to have a line of TeX text + consisting exactly of, say, "@hindi", the preprocessor may be + fooled by typing "{}@hindi", "{@hindi}", or anything similar.) + + 2. The old line-splitting code and the @obeylines preprocessor + command to disable it have been withdrawn, so that the program + now outputs one line to the .tex file for every line of the + .dn file. In devnag 2.0, attempted use of @obeylines produces + a specific warning; this is likely to be withdrawn in a future + release, after which attempts to use it will cause "@obeylines" + to be typeset as a part of the text of the document (see 1. + above). + + 3. To complete the line-by-line correspondence between the input + and output files, comments are no longer stripped out, and + preprocessor commands (such as "@hyphen") are passed through + into the output file in the form of comments ("%@hyphen"). + + 4. There is now an option to show the version of the program. If + devnag is invoked as "devnag -v" it will print a banner giving + the version number and other information, and then exit. + + 5. If the input file has a name such as "x.y.dn", the output file + will now be "x.y.tex", not, as previously, "x.tex". In addition, + it is now mandatory for the files to have the suffixes ".dn" and + ".tex", though as before these are supplied by the program if + omitted by the user. This change has been made for safety + reasons: formerly, typing "devnag myfile.tex" would delete + the contents of myfile.tex. + + 6. The sequence ~nj~na now produces the correct form. + + 7. The sequences r.l and r.L now produce the correct forms. + + 8. The sequences ttrya, ttrva, khrya and khrva now produce the + correct forms. + + 9. The correct "caret" form of -r is now produced under kh, ch, + etc., even when a subscript vowel or viraama follows. This has + necessitated a new macro (\qc), which must be defined in + dnmacs.tex (for Plain TeX) or dev.sty (for LaTeX). The + definition is: + + \def\qc#1#2{\setbox0=\hbox{#1}#1\subscr{\char126\kern1.5ex\lower1.25ex + \hbox{\char#2}\kern-1.5ex}} + + Suitable versions of the files are distributed with the current + release of the devnag package. + + 10. A fragment of code which permitted hyphenation in the middle of + a consonant sequence containing a viraama has been removed. + All hyphenation before consonants stopped with viraama has + also been eliminated. + + 11. A change has been introduced in the output that devnag produces + from input such as {\dn .sa.t"siraa.h}, i.e. in cases where an + i-matra vowel is associated with a consonant sequence containing + a viraama. The previous behaviour was to treat the consonant + sequence as if it were a normal conjunct by placing the vowel + symbol before the sequence as a whole. The majority opinion + seems to be that this is undesirable, and that the vowel symbol + should follow the consonant to which the viraama is attached. + A change has therefore been made to implement this. However, the + previous behaviour can be reinstated by means of a new + preprocessor command, @vconjuncts. + + 12. Tab characters in the input file, which previously were treated + as fatal errors, are now silently converted to spaces. + + 13. (Internal coding changes) The order of the C code has been + normalised from the original Pascal-like bottom-up sequence + to a more conventional top-down version. Numerous comments have + been added to assist potential future developers in understanding + the way the program works. A number of bug-fixes and other + improvements have been applied. The insecure gets() calls used + in prompting for user input have been replaced by fgets(). + Variables used only within a single function have been declared + local to that function. Some variables have been renamed in + the interests of clarity and consistency, and some redundant + ones have been eliminated. The functions ch_find() and st_find(), + which simply duplicated the standard library functions strchr() + and strstr(), have also been eliminated. + */ + +/* + Version 2.01 is a bugfix release, containing two changes in + coding. (1) Previous versions of devnag have output "[" and "]" + for Devanagari half-"sa and half-gha. Under some circumstances + this can interact badly with LaTeX, and the form of output has + been changed to avoid the problem. (2) \cline has been added to + the list of LaTeX commands which devnag knows how to handle. + -- John Smith + */ + +/* + Version 2.02 redefines all ^^* characters to be output as + \3XXw because it is more robust. It puts a definition + of \DevnagVersion at the beginning of the output file so + that the new preprocessed files can be automatically recognized + (Z. Wagner, wagner@cesnet.cz, http://icebearsoft.euweb.cz). + This version also defines a new preprodessor directive + @modernhindi, which functions in the same way as @hindi but + uses far fewer Sanskrit-style ligatures, preferring conjuncts + built from half-consonant forms wherever possible. (Thanks to + Raymond Doctor for helpful advice on which ligatures to permit + and which to suppress.) The definition of @sanskrit has been + changed so that it now restores all the ligatures disabled by + @modernhindi, not just those disabled by @hindi. The sequences + kk.sa, .tk.sa, dmya and hmya have been modified to produce + k+k.sa, .t+k.sa, d+mya, h+mya (rather than, as previously, + kk+.sa, .tk+.sa dm+ya, hm+ya). The code which handles all such + substitutions has been radically improved. The special warning + message prompted by the long-defunct preprocessor directive + @obeylines has been removed. + -- John Smith + */ + +/* + Version 2.1 makes the following changes: + * + * Material within {\dn ... } (or $ ... $) may be enclosed within + angle brackets < ... >; it is then not processed, but is passed + through verbatim to the output file, e.g. + {\dn eka do <\hrule width 10 em> tiina caara} + * Changes to the fonts have made an "open ya" glyph available. This + is now used wherever the preprocessor would previously have + produced consonant + viraama + ya. + * The fonts now contain defined glyphs for .n.na; the preprocessor + uses these. + * In previous releases the "half j~na" glyph was not used in @hindi + and @modernhindi modes (the program output "half ja + half ~na"). + This has been corrected. + * The output now avoids using the following control symbols: \", \#, + \$, \%, \&, \'. + -- John Smith + */ + +/* + Version 2.11 is a bugfix release to deal with two problems: + * + * Newline characters were not being properly handled in material + enclosed within angle brackets < ... >; + * The input sequence ~a was producing the wrong output for the + initial form of the vowel. + -- John Smith + */ + +/* + Version 2.12 contains two modification by Kevin Carmody, one to add + the ligature disabling character "+", and one bug fix to avoid the use + of non-standard syntax in invocations of fixconj(). + */ + +/* + Bug fix suggested by John Smith: put_syll() just after case '<' in order + to emit pending syllable. The verbatim material should appear between + words but you can even write {\dn pa<\kern -2pt >de} if you know what + you are doing. However, such use is strongly discouraged. + */ + +/* + Version 2.13: ~m is now a synonym for /, i.e. candrabindu +*/ + +char *version = "2.13"; + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> /* Marc Csernel */ + +/* General constants */ +#define TRUE 1 +#define FALSE 0 +#define VIRAAM 94 +#define SMALLBUF 30 +#define MEDBUF 512 +#define MAXBUF 2048 +#define N_NOLIGS (sizeof nolig / sizeof nolig[0]) +#define N_MNOLIGS (sizeof modnolig / sizeof modnolig[0]) +#define ill_char 29 +#define dummy 30 +#define end_of_file 30 +#define end_of_line 31 + +/* + * Constants used in char_def structs + */ +/* ch_typ constants */ +#define illegal 0 +#define cmr 1 +#define control 2 +#define dn 3 +#define numeral 4 +/* ch_subtyp constants */ +#define lo_vowel 0 +#define hi_vowel 1 +#define consonant 2 +#define special 3 + +/* Constants representing symbols: defined as indexes into out_string[] */ +#define LBRACE 273 +#define RBRACE 264 +#define RE 263 /* \thinspace on switching from cmr to dn */ +#define RDT 266 /* raised r-dot (repha + anusvara) */ +#define RN 265 /* numeral, using cmr or dn as appropriate */ +#define RS 256 /* \thinspace on switching from dn to cmr */ + +/* Global variable declarations */ +FILE *f_in, *f_out; +char *p_in; +int number; +char symbol; +char infil[MEDBUF], outfil[MEDBUF]; +char inbuf[MAXBUF], outbuf[MAXBUF]; +char word[MEDBUF]; +short syll[SMALLBUF]; +int n_halves, buf_idx; +short half_codes[SMALLBUF]; +short joincode; +unsigned char hindi_mode, mhindi_mode, dollar_mode, d_found; +unsigned char tabs_mode; /* Marc Csernel */ +unsigned char no_dn, wait_syll, do_hyphen, do_vconjuncts; +unsigned char cons_seen, vow_seen, front_r, cmr_mode, num_mode; +unsigned char lig_block; /* Kevin Carmody */ +short chr_idx, cons_code; +char *banner = +"Preprocessor for Devanagari for TeX package\n\ +Copyright (C) 1991-1998 University of Groningen, The Netherlands\n\ +Author : Frans J. Velthuis <velthuis@rc.rug.nl>\n\ +Maintainer : Zdenek Wagner <wagner@cesnet.cz>"; + +/* Function declarations */ +int main(int argc, char **argv); +void dnproc(void); +void put_ch(short code); +void sendchar(char c); +void put_sym(short code); +void put_word(void); +void put_syll(void); +void tst_half(void); +void put_macro(short macro); +void err_ill(char *str); +char inp_ch(void); +void expand(void); +char find_dn(void); +int sindex(int i, short t); +void fixconj(short *wrong, short *right); + +/* --------- Addition by Marc Csernel 1998 --------- */ + +int citation; +int optchapter; +int linenumber; +int test_command(void); +char test_sub_com(void); +char comm_double_args(void); +char comm_special(void); +char comm_opt(void); +char comm_chapter(void); +char comm_cite(void); +char *getsubarg(void); +char comm_begin(void); +char ignore(void); + +/* ------------------ End Addition ----------------- */ + +/* + * *** Struct declarations: major data types *** + */ + +/* + A struct of type char_def contains the following information about + any given character: + + ch_typ: dn -- a character of the Devanagari syllabary + cmr -- a Roman character available within {\dn } + numeral -- self-evident: either Devanagari or ASCII as + specified + control -- special TeX character ("\", "{", "}", etc.) + illegal -- none of the above + ch_subtyp: consonant + lo_vowel (subscript) + hi_vowel ("regular" and superscript) + special -- none of the above + ch_code: For ch_typ dn only, gives the octal value of the + character's position in the dvng fonts. For vowels, + refers to the initial form (ch_subcode refers to + non-initial form); composite forms such as initial "o" + (= initial "a" + non-initial "o") have special values + greater than 257 decimal. + ch_subcode: Used for ch_typ dn only. For vowels, gives the octal + value of the non-initial form ("a" has the special value + 257 decimal). For consonants, gives the index into + cons_table[] where the "half-form" of the consonant is + defined. +*/ +struct char_def { + short ch_typ, ch_subtyp, ch_code, ch_subcode; +}; + +/* + A struct of type cons_joins contains the following information about + any given consonant or consonant-group Ca: + + n_ligs: The number of "simple" (two-member) ligatures listed in + lig_table[] for Ca. + lig_code: The index into lig_table[] of the first such ligature. + r_type: Has the value 0 if Ca takes the normal form of following "r" + (decimal 125) or if "Cra" is a predefined ligature; 1 if Ca + requires the "caret" form of following "r" (decimal 126); + 2 if "Cra" is handled as "\qb{Ca}". + j_code: Gives the octal value of the "half-form" of Ca if one exists, + otherwise 0. + */ +struct cons_joins { + short n_ligs, lig_code; + short r_type, j_code; +}; + +/* + A struct of type ligs contains the following information about any + given ligature: + + sym_code: The index into char_table[] of the final member of the + ligature. May be expressed as as a character constant + (e.g. 't') or as a number (e.g. 6, referring to ".s"). + sym_new: Gives either (a) the octal value of the ligature, or (b) a + negative number to be handled by expand(), which will reverse + the sign and subtract 1 (-5 becomes 4), and use the result as + an index into r_ligs[]. (This is done for "ktra", "gra", + ".dra", "dra", "dhra" and ".s.tra".) + join_idx: Gives the index into cons_table[] of the ligature, or 0. + in_use: Boolean TRUE or FALSE according to whether the ligature is + currently enabled (they are all initially enabled in + lig_table[], but may be disabled by e.g. @hindi). + */ +struct ligs { + char sym_code; + short sym_new, join_idx; + unsigned char in_use; +}; + +/* + * *** Data structures used by devnag *** + */ + +/* Ligatures to be disabled by @hindi */ +short nolig[] = { + 2,3,6,7,16,25,27,34,35,39,40,46,47,49,56,58,59,62,65, + 78,81,82,84,85,86,87,88,89,90,91,92,93,94,95,98,99, + 100,101,105 +}; + +/* Ligatures to be disabled by @modernhindi */ +short modnolig[] = { + 0,1,2,3,4,6,7,9,10,11,12,14,16,17,18,19,20,21,22,23, + 24,25,26,27,28,29,30,31,32,33,34,35,36,39,40,41,42,43, + 44,45,46,47,48,49,50,52,53,54,56,58,59,62,64,65,69,70, + 71,72,73,74,75,76,77,78,80,81,82,84,85,86,87,88,89,90,91, + 92,93,94,95,98,99,100,101,102,103,104,105,118,119 +}; + +/* + * ligidxs[] maps the ligature-numbers that the user may specify + * with @lig and @nolig to the appropriate entries in lig_table[] + */ +short ligidxs[] = { + 0,1,2,3,4,6,7,9,11,12,13,14,118,16,17,18,19,20,21,22, + 23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,41, + 42,43,44,45,46,47,48,49,50,52,53,119,54,55,56,58,59,60, + 61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,80, + 81,82,84,85,86,87,88,89,90,91,92,93,94,95,96,98,99,100, + 101,102,104,117,105,106,107,108,109,110,111,112,113 +}; + +/* + * In the following character sets, final space is a dummy value + */ +/* Characters that may be preceded by "." */ +char chset1[] = { + 'k','t','d','o','n','s','r','g', + 'h','a','.','K','T','D','l','L','R','m',' ' +}; +/* Characters with a special meaning if preceded by "a" */ +char chset2[] = {'a','i','u',' '}; +/* Characters that may be preceded by '"' */ +char chset3[] = {'n','s',' '}; +/* Characters that may be followed by "h" */ +char chset4[] = {'k','g','c','j','t','d','p','b','R',' '}; +/* Replacements for chset2 characters when preceded by "a" */ +char chset5[] = {'A','E','O'}; +/* Characters that may be preceded by "~" */ +char chset6[] = {'n','o','a','r','m',' '}; + +/* + * Private character set used internally by devnag -- basically + * ASCII, but with special characters allotted slots below 32: + * conversion from input representation done by dnproc(). + */ +struct char_def char_table[] = { + {illegal,special,0,0}, /* 1 not used */ + {dn,consonant,'\126',34}, /* 2 .t */ + {dn,consonant,'\130',36}, /* 3 .d */ + {dn,special,'\72',0}, /* 4 .o */ + {dn,consonant,'\132',1}, /* 5 .n */ + {dn,consonant,'\161',2}, /* 6 .s */ + {dn,lo_vowel,'\33',2}, /* 7 .r */ + {dn,consonant,'\13',3}, /* 8 .g */ + {dn,special,'\54',0}, /* 9 .h */ + {dn,special,'\137',0}, /* 10 .a */ + {dn,special,'\24',0}, /* 11 .. */ + {dn,consonant,'\14',4}, /* 12 .K */ + {dn,consonant,'\127',35}, /* 13 .T */ + {dn,consonant,'\131',57}, /* 14 .D */ + {dn,lo_vowel,'\30','\37'}, /* 15 .l */ + {dn,lo_vowel,'\31','\174'}, /* 16 .L */ + {dn,lo_vowel,'\21','\16'}, /* 17 .R */ + {dn,consonant,'\122',32}, /* 18 "n */ + {dn,consonant,'\146',5}, /* 19 "s */ + {dn,consonant,'\170',0}, /* 20 Rh */ + {dn,consonant,'\32',11}, /* 21 ~n */ + {dn,hi_vowel,267,262}, /* 22 ~o */ + {dn,hi_vowel,275,4}, /* 23 ~a */ + {dn,consonant,'\35',31}, /* 24 ~r */ + {illegal,special,0,0}, /* 25 not used */ + {illegal,special,0,0}, /* 26 not used */ + {illegal,special,0,0}, /* 27 not used */ + {illegal,special,0,0}, /* 28 not used */ + {illegal,special,0,0}, /* 29 not used */ + {control,special,0,0}, /* 30 dummy */ + {control,special,0,0}, /* 31 end_of_line */ + {control,special,0,0}, /* 32 space */ + {cmr,special,0,0}, /* ! */ + {illegal,special,0,0}, /* " */ + {dn,special,'\25',0}, /* # */ + {illegal,special,0,0}, /* $ */ + {control,special,0,0}, /* % */ + {dn,special,0,0}, /* & */ + {cmr,special,0,0}, /* ' to * */ + {cmr,special,0,0}, /* ' to * */ + {cmr,special,0,0}, /* ' to * */ + {cmr,special,0,0}, /* ' to * */ + {dn,special,0,0}, /* + */ + /* Kevin Carmody: + * "+" changed + * from cmr + * to dn */ + {cmr,special,0,0}, /* , to - */ + {cmr,special,0,0}, /* , to - */ + {illegal,special,0,0}, /* . */ + {dn,special,'\40',0}, /* / */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {numeral,special,0,0}, /* 0 to 9 */ + {cmr,special,0,0}, /* : and ; */ + {cmr,special,0,0}, /* : and ; */ + {control,special,0,0}, /* < */ + {cmr,special,0,0}, /* = */ + {control,special,0,0}, /* > */ + {cmr,special,0,0}, /* ? */ + {dn,special,'\177',0}, /* @ */ + {dn,hi_vowel,258,'\101'}, /* A */ + {dn,consonant,'\102',6}, /* B */ + {dn,consonant,'\103',33}, /* C */ + {dn,consonant,'\104',7}, /* D */ + {dn,hi_vowel,259,'\173'}, /* E */ + {illegal,special,0,0}, /* F */ + {dn,consonant,'\107',8}, /* G */ + {dn,special,'\54',0}, /* H */ + {dn,hi_vowel,'\111','\106'}, /* I */ + {dn,consonant,'\112',9}, /* J */ + {dn,consonant,'\113',10}, /* K */ + {dn,consonant,'\17',30}, /* L */ + {dn,special,'\134',0}, /* M */ + {illegal,special,0,0}, /* N */ + {dn,hi_vowel,260,'\117'}, /* O */ + {dn,consonant,'\120',12}, /* P */ + {illegal,special,0,0}, /* Q */ + {dn,consonant,'\167',0}, /* R */ + {illegal,special,0,0}, /* S */ + {dn,consonant,'\124',13}, /* T */ + {dn,lo_vowel,'\125',1}, /* U */ + {illegal,special,0,0}, /* V to Z */ + {illegal,special,0,0}, /* V to Z */ + {illegal,special,0,0}, /* V to Z */ + {illegal,special,0,0}, /* V to Z */ + {illegal,special,0,0}, /* V to Z */ + {cmr,special,0,0}, /* [ */ + {control,special,0,0}, /* \ */ + {cmr,special,0,0}, /* ] */ + {illegal,special,0,0}, /* ^ */ + {dn,special,0,0}, /* _ */ + /* Marc Csernel: + * "_" changed + * from illegal + * to dn */ + {cmr,special,0,0}, /* ` */ + {dn,hi_vowel,'\141',257}, /* a */ + {dn,consonant,'\142',14}, /* b */ + {dn,consonant,'\143',15}, /* c */ + {dn,consonant,'\144',37}, /* d */ + {dn,hi_vowel,'\145',3}, /* e */ + {dn,consonant,'\47',16}, /* f */ + {dn,consonant,'\147',17}, /* g */ + {dn,consonant,'\150',38}, /* h */ + {dn,hi_vowel,'\151','\105'}, /* i */ + {dn,consonant,'\152',18}, /* j */ + {dn,consonant,'\153',19}, /* k */ + {dn,consonant,'\154',20}, /* l */ + {dn,consonant,'\155',21}, /* m */ + {dn,consonant,'\156',22}, /* n */ + {dn,hi_vowel,261,'\157'}, /* o */ + {dn,consonant,'\160',23}, /* p */ + {dn,consonant,'\52',24}, /* q */ + {dn,consonant,'\162',0}, /* r */ + {dn,consonant,'\163',25}, /* s */ + {dn,consonant,'\164',26}, /* t */ + {dn,lo_vowel,'\165',0}, /* u */ + {dn,consonant,'\166',27}, /* v */ + {illegal,special,0,0}, /* not used */ + {illegal,special,0,0}, /* not used */ + {dn,consonant,'\171',28}, /* y */ + {dn,consonant,'\51',29}, /* z */ + {control,special,0,0}, /* left brace */ + {dn,special,'\56',0}, /* | */ + {control,special,0,0}, /* right brace */ + {illegal,special,0,0}, /* ~ */ + {illegal,special,0,0} /* del */ +}; + +/* + * Unordered table of consonants and consonant-groups giving + * information on the available ligatures, the form taken by a + * following "r", and the location in the dvng fonts of the + * "half-form" (if any) + */ +struct cons_joins cons_table[] = { + {0,0,1,0}, /* 0 */ + {1,120,0,'\27'}, /* 1 .n */ + {2,100,0,'\11'}, /* 2 .s */ + {0,0,0,'\34'}, /* 3 .g */ + {0,0,1,'\7'}, /* 4 .k */ + {6,94,0,'\133'}, /* 5 "s */ + {1,88,0,'\74'}, /* 6 B */ + {2,78,0,'\100'}, /* 7 D */ + {1,16,0,'\135'}, /* 8 G */ + {0,0,1,'\44'}, /* 9 J */ + {0,0,1,'\110'}, /* 10 K */ + {2,39,1,'\26'}, /* 11 ~n */ + {1,115,0,'\45'}, /* 12 P */ + {0,0,0,'\114'}, /* 13 T */ + {3,85,0,'\116'}, /* 14 b */ + {2,34,0,'\121'}, /* 15 c */ + {1,116,0,'\10'}, /* 16 f */ + {1,15,0,'\140'}, /* 17 g */ + {2,37,0,'\76'}, /* 18 j */ + {9,0,0,'\77'}, /* 19 k */ + {1,91,0,'\123'}, /* 20 l */ + {2,89,0,'\115'}, /* 21 m */ + {1,80,0,'\6'}, /* 22 n */ + {4,81,0,'\75'}, /* 23 p */ + {0,0,1,'\12'}, /* 24 q */ + {2,105,0,'\55'}, /* 25 s */ + {3,55,0,'\50'}, /* 26 t */ + {2,92,0,'\46'}, /* 27 v */ + {0,0,1,'\5'}, /* 28 y */ + {1,114,0,'\36'}, /* 29 z */ + {0,0,1,'\20'}, /* 30 L */ + {0,0,1,'\35'}, /* 31 ~r */ + {8,17,1,0}, /* 32 "n */ + {1,36,1,0}, /* 33 C */ + {4,41,1,0}, /* 34 .t */ + {1,45,1,0}, /* 35 .th */ + {6,46,1,0}, /* 36 .d */ + {11,58,2,0}, /* 37 d */ + {7,107,1,0}, /* 38 h */ + {3,9,1,0}, /* 39 k t */ + {1,14,1,0}, /* 40 k v */ + {3,25,1,0}, /* 41 "n k */ + {1,28,1,0}, /* 42 "n kh */ + {1,29,1,0}, /* 43 "n g */ + {2,30,1,0}, /* 44 "n gh */ + {1,32,1,0}, /* 45 "n k t */ + {1,33,1,0}, /* 46 "n k .s */ + {1,52,1,0}, /* 47 .d g */ + {1,53,1,0}, /* 48 .d gh */ + {2,71,2,0}, /* 49 d d */ + {2,73,2,0}, /* 50 d dh */ + {1,75,1,0}, /* 51 d bh */ + {1,77,2,0}, /* 52 d v */ + {3,102,1,0}, /* 53 .s .t */ + {0,0,1,'\43'}, /* 54 k .s */ + {0,0,1,0202}, /* 55 t t */ + {1,117,1,0}, /* 56 .s .t r */ + {1,54,1,0}, /* 57 .dh */ + {1,12,1,0}, /* 58 k n */ + {1,13,1,0}, /* 59 k r */ + {0,0,1,0351}, /* 60 g r */ + {0,0,1,0350}, /* 61 gh n */ + {0,0,1,0352}, /* 62 j ~n */ + {0,0,1,0353}, /* 63 ~n c */ + {0,0,1,0354}, /* 64 t r */ + {1,69,1,0}, /* 65 d g */ + {1,70,1,0}, /* 66 d gh */ + {0,0,1,0361}, /* 67 dh n */ + {0,0,1,0362}, /* 68 dh r */ + {0,0,1,0363}, /* 69 p t */ + {0,0,1,0364}, /* 70 "s c */ + {0,0,1,0365}, /* 71 "s r */ + {0,0,1,0366}, /* 72 "s v */ + {1,118,1,0}, /* 73 k t r */ + {1,119,1,0}, /* 74 .d r */ + {1,76,1,0}, /* 75 d r */ + {0,0,2,0} /* 76 d b */ +}; + +/* + * Ordered table of available ligatures giving each ligature's + * position in the dvng fonts (or a negative number for use by + * expand()) and index into cons_table[] + * + * Note that lig_table[96] is an entry for a ligature that was + * removed from the fonts as of release 2.1. It is therefore + * marked as (permanently) FALSE; it has not been removed from + * the table since to do so would change the index values of all + * succeeding entries, and these occur frequently in the code. + */ +struct ligs lig_table[] = { + {'k',0303,0,TRUE}, /* 0 k k */ + {'t',0304,39,TRUE}, /* 1 k t */ + {'n',0307,58,TRUE}, /* 2 k n */ + {'m',0311,0,TRUE}, /* 3 k m */ + {'y',0310,0,TRUE}, /* 4 k y */ + {'r',0207,59,TRUE}, /* 5 k r */ + {'l',0312,0,TRUE}, /* 6 k l */ + {'v',0313,40,TRUE}, /* 7 k v */ + {6,042,54,TRUE}, /* 8 k .s */ + {'y',0305,0,TRUE}, /* 9 k t y */ + {'r',-5,73,TRUE}, /* 10 k t r */ + {'v',0306,0,TRUE}, /* 11 k t v */ + {'y',0346,0,TRUE}, /* 12 k n y */ + {'y',0347,0,TRUE}, /* 13 k r y */ + {'y',0314,0,TRUE}, /* 14 k v y */ + {'r',-2,60,TRUE}, /* 15 g r */ + {'n',0315,61,TRUE}, /* 16 gh n */ + {'k',0254,41,TRUE}, /* 17 "n k */ + {'K',0262,42,TRUE}, /* 18 "n kh */ + {'g',0275,43,TRUE}, /* 19 "n g */ + {'G',0277,44,TRUE}, /* 20 "n gh */ + {18,0274,0,TRUE}, /* 21 "n "n */ + {'n',0265,0,TRUE}, /* 22 "n n */ + {'m',0301,0,TRUE}, /* 23 "n m */ + {'y',0302,0,TRUE}, /* 24 "n y */ + {'t',0255,45,TRUE}, /* 25 "n k t */ + {'y',0257,0,TRUE}, /* 26 "n k y */ + {6,0260,46,TRUE}, /* 27 "n k .s */ + {'y',0272,0,TRUE}, /* 28 "n kh y */ + {'y',0276,0,TRUE}, /* 29 "n g y */ + {'y',0271,0,TRUE}, /* 30 "n gh y */ + {'r',0300,0,TRUE}, /* 31 "n gh r */ + {'y',0256,0,TRUE}, /* 32 "n k t y */ + {'v',0261,0,TRUE}, /* 33 "n k .s v */ + {'c',0316,0,TRUE}, /* 34 c c */ + {21,0317,0,TRUE}, /* 35 c ~n */ + {'y',0320,0,TRUE}, /* 36 ch y */ + {21,0342,62,TRUE}, /* 37 j ~n */ + {'r',0205,0,TRUE}, /* 38 j r */ + {'c',0321,63,TRUE}, /* 39 ~n c */ + {'j',0322,0,TRUE}, /* 40 ~n j */ + {'k',0326,0,TRUE}, /* 41 .t k */ + {2,0323,0,TRUE}, /* 42 .t .t */ + {13,0341,0,TRUE}, /* 43 .t .th */ + {'y',0324,0,TRUE}, /* 44 .t y */ + {'y',0325,0,TRUE}, /* 45 .th y */ + {'g',0263,47,TRUE}, /* 46 .d g */ + {'G',0264,48,TRUE}, /* 47 .d gh */ + {3,0345,0,TRUE}, /* 48 .d .d */ + {'m',0273,0,TRUE}, /* 49 .d m */ + {'y',0267,0,TRUE}, /* 50 .d y */ + {'r',-6,74,TRUE}, /* 51 .d r */ + {'y',0270,0,TRUE}, /* 52 .d g y */ + {'r',0266,0,TRUE}, /* 53 .d gh r */ + {'y',0344,0,TRUE}, /* 54 .dh y */ + {'t',0201,55,TRUE}, /* 55 t t */ + {'n',0327,0,TRUE}, /* 56 t n */ + {'r',057,64,TRUE}, /* 57 t r */ + {'g',0213,65,TRUE}, /* 58 d g */ + {'G',0212,66,TRUE}, /* 59 d gh */ + {'d',0214,49,TRUE}, /* 60 d d */ + {'D',0210,50,TRUE}, /* 61 d dh */ + {'n',0221,0,TRUE}, /* 62 d n */ + {'b',0223,76,TRUE}, /* 63 d b */ + {'B',0211,51,TRUE}, /* 64 d bh */ + {'m',0224,0,TRUE}, /* 65 d m */ + {'y',0215,0,TRUE}, /* 66 d y */ + {'r',-3,75,TRUE}, /* 67 d r */ + {'v',0222,52,TRUE}, /* 68 d v */ + {'r',0355,0,TRUE}, /* 69 d g r */ + {'r',0356,0,TRUE}, /* 70 d gh r */ + {'y',0220,0,TRUE}, /* 71 d d y */ + {'v',0370,76,TRUE}, /* 72 d d v */ + {'y',0217,0,TRUE}, /* 73 d dh y */ + {'v',0371,0,TRUE}, /* 74 d dh v */ + {'y',0216,0,TRUE}, /* 75 d bh y */ + {'y',0357,0,TRUE}, /* 76 d r y */ + {'y',0225,0,TRUE}, /* 77 d v y */ + {'n',0360,67,TRUE}, /* 78 dh n */ + {'r',-4,68,TRUE}, /* 79 dh r */ + {'n',0340,0,TRUE}, /* 80 n n */ + {'t',0330,69,TRUE}, /* 81 p t */ + {'n',0331,0,TRUE}, /* 82 p n */ + {'r',0376,0,TRUE}, /* 83 p r */ + {'l',0332,0,TRUE}, /* 84 p l */ + {'n',0247,0,TRUE}, /* 85 b n */ + {'b',0251,0,TRUE}, /* 86 b b */ + {'v',0333,0,TRUE}, /* 87 b v */ + {'n',0336,0,TRUE}, /* 88 bh n */ + {'n',0337,0,TRUE}, /* 89 m n */ + {'l',0335,0,TRUE}, /* 90 m l */ + {'l',0245,0,TRUE}, /* 91 l l */ + {'n',0246,0,TRUE}, /* 92 v n */ + {'v',0250,0,TRUE}, /* 93 v v */ + {'c',0226,70,TRUE}, /* 94 "s c */ + {'n',0227,0,TRUE}, /* 95 "s n */ + {'b',0233,0,FALSE}, /* 96 "s b */ + {'r',0231,71,TRUE}, /* 97 "s r */ + {'l',0232,0,TRUE}, /* 98 "s l */ + {'v',0230,72,TRUE}, /* 99 "s v */ + {2,0243,53,TRUE}, /* 100 .s .t */ + {13,0244,0,TRUE}, /* 101 .s .th */ + {'y',0367,0,TRUE}, /* 102 .s .t y */ + {'r',-1,56,TRUE}, /* 103 .s .t r */ + {'v',0253,0,TRUE}, /* 104 .s .t v */ + {'n',0334,0,TRUE}, /* 105 s n */ + {'r',0372,0,TRUE}, /* 106 s r */ + {5,0242,0,TRUE}, /* 107 h .n */ + {'n',0241,0,TRUE}, /* 108 h n */ + {'m',0234,0,TRUE}, /* 109 h m */ + {'y',0235,0,TRUE}, /* 110 h y */ + {'r',0240,0,TRUE}, /* 111 h r */ + {'l',0236,0,TRUE}, /* 112 h l */ + {'v',0237,0,TRUE}, /* 113 h v */ + {'r',0206,0,TRUE}, /* 114 z r */ + {'r',0203,0,TRUE}, /* 115 ph r */ + {'r',0204,0,TRUE}, /* 116 f r */ + {'y',0252,0,TRUE}, /* 117 .s .t r y */ + {'y',0374,0,TRUE}, /* 118 k t r y */ + {'y',0373,0,TRUE}, /* 119 .d r y */ + {5,0233,0,TRUE} /* 120 .n .n */ +}; + +/* + * Table of the actual codes output by devnag + */ +char *out_string[] = { + "\\7{","\\8{","\\9{","\\?","\\<","\\305w","\\306w", /* 0-6 */ + "\\307w","\\308w","\\309w","\\30Aw","\\30Bw","\\30Cw", /* 7-12 */ + "\\0","\\qx{","\\30Fw","\\310w","\\311w","\\312w", /* 13-18 */ + "\\313w","\\314w","\\315w","\\316w","\\317w","\\318w", /* 19-24 */ + "\\319w","\\31Aw","\\31Bw","\\31Cw","\\31Dw", /* 25-29 */ + "\\31Ew","\\qy{","\\1","!","\\322w","\\323w","\\324w", /* 30-36 */ + "\\325w","\\326w","\\327w","(",")","\\32Aw","+",",", /* 37-44 */ + "-",".","/","0","1","2","3","4","5","6","7","8","9", /* 45-57 */ + ":",";","<","=",">","?","@", /* 58-64 */ + "A","B","C","D","E","F","G","H","I","J","K","L","M", /* 65-77 */ + "N","O","P","Q","R","S","T","U","V","W","X","Y","Z", /* 78-90 */ + "\\35Bw","\\2","\\35Dw","\\qq{","\\35Fw","`", /* 91-96 */ + "a","b","c","d","e","f","g","h","i","j","k","l","m", /* 97-109 */ + "n","o","p","q","r","s","t","u","v","w","x","y","z", /* 110-122 */ + "\\4","\\qz{","\\5","\\6{","\\37Fw", /* 123-127 */ + "\\380w","\\381w","\\382w","\\383w","\\384w","\\385w", /* 128-133 */ + "\\386w","\\387w","\\388w","\\389w","\\38Aw","\\38Bw", /* 134-139 */ + "\\38Cw","\\38Dw","\\38Ew","\\38Fw","\\390w","\\391w", /* 140-145 */ + "\\392w","\\393w","\\394w","\\395w","\\396w","\\397w", /* 146-151 */ + "\\398w","\\399w","\\39Aw","\\39Bw","\\39Cw","\\39Dw", /* 152-157 */ + "\\39Ew","\\39Fw","\\3A0w","\\3A1w","\\3A2w","\\3A3w", /* 158-163 */ + "\\3A4w","\\3A5w","\\3A6w","\\3A7w","\\3A8w","\\3A9w", /* 164-169 */ + "\\3AAw","\\3ABw","\\3ACw","\\3ADw","\\3AEw","\\3AFw", /* 170-175 */ + "\\3B0w","\\3B1w","\\3B2w","\\3B3w","\\3B4w","\\3B5w", /* 176-181 */ + "\\3B6w","\\3B7w","\\3B8w","\\3B9w","\\3BAw","\\3BBw", /* 182-187 */ + "\\3BCw","\\3BDw","\\3BEw","\\3BFw","\\3C0w","\\3C1w", /* 188-193 */ + "\\3C2w","\\3C3w","\\3C4w","\\3C5w","\\3C6w","\\3C7w", /* 194-199 */ + "\\3C8w","\\3C9w","\\3CAw","\\3CBw","\\3CCw","\\3CDw", /* 200-205 */ + "\\3CEw","\\3CFw","\\3D0w","\\3D1w","\\3D2w","\\3D3w", /* 206-211 */ + "\\3D4w","\\3D5w","\\3D6w","\\3D7w","\\3D8w","\\3D9w", /* 212-217 */ + "\\3DAw","\\3DBw","\\3DCw","\\3DDw","\\3DEw","\\3DFw", /* 218-223 */ + "\\3E0w","\\3E1w","\\3E2w","\\3E3w","\\3E4w","\\3E5w", /* 224-229 */ + "\\3E6w","\\3E7w","\\3E8w","\\3E9w","\\3EAw","\\3EBw", /* 230-235 */ + "\\3ECw","\\3EDw","\\3EEw","\\3EFw","\\3F0w","\\3F1w", /* 236-241 */ + "\\3F2w","\\3F3w","\\3F4w","\\3F5w","\\3F6w","\\3F7w", /* 242-247 */ + "\\3F8w","\\3F9w","\\3FAw","\\3FBw","\\3FCw","\\3FDw", /* 248-253 */ + "\\3FEw","\\3FFw", /* 254-255 */ + "{\\rs ","","aA","e\\?","aO","ao","A\\<","\\re}","}", /* 256-264 */ + "\\rn{","{\\rdt}","aA\\<","{\\qva}","{\\qvb}","{\\qvc}", /* 265-270 */ + "\\qa{","\\qb{","{","\\qc{","a\\<" /* 271-275 */ +}; + +/* + * Table specifying the form of following "r" for various consonants + * and consonant-groups (used by expand()) + */ +short r_ligs[6][2] = { + {0243,1}, /* .s .t */ + {0147,0}, /* g */ + {0144,2}, /* d */ + {0104,0}, /* dh */ + {0304,1}, /* k t */ + {0130,1} /* .d */ +}; + +/* --------- Addition by Marc Csernel 1998 --------- */ + +/* The array contains a list of LaTeX commands preceded by a code: + + 1 a mandatory argument follows. e.g. \end{enumerate} + 2 the text inclosed by a preceding brace must not be translated + till next closing brace. + 3 two mandatory arguments follow. e.g. \multicolumn{nb}{desc}{text} + 4 For begin: a mandatory argument followed by zero, or one optional, + depending on the first one e.g. \begin{itemize} or + \begin{tabular}{....} + 5 a mandatory argument and optional ones which must not be translated. + \raisebox{raise}[ht][prof]{text to be translated} + 6 one or more optional argument(s) which must not be translated and + a mandatory one which must be translated e.g. + \framebox[6cm][s]{text to be translated} + 7 The command cite: an optional argument which must be translated + and a mandatory one which mustn't. + 8 Commands like chapter, section... with optional argument which + must be translated and a mandatory one which must also be + translated. + +*/ + +typedef struct { + int Typ_Com; + char *Name_com; +} typcom; + +typcom TabCom[] = { + {4,"begin"}, + {1,"end"}, + {1,"label"}, + {1,"pageref"}, + {1,"ref"}, + {1,"index"}, + {1,"hspace"}, + {1,"hspace*"}, + {1,"vspace"}, + {1,"vspace*"}, + {1,"addvspace"}, + {1,"enlargethispage"}, + {1,"enlargethispage*"}, + {1,"include"}, + {1,"input"}, + {1,"parbox"}, + {1,"stepcounter"}, + {1,"refstepcounter"}, + {1,"bibitem"}, + {1,"cline"}, + {2,"rm"}, + {2,"kern"}, + {2,"hskip"}, + {2,"vskip"}, + {2,"vadjust"}, + {3,"addtolength"}, + {3,"setlength"}, + {3,"setcounter"}, + {3,"addtocounter"}, + {3,"multicolumn"}, + {3,"rule"}, + {3,"addcontentsline"}, + {5,"raisebox"}, + {6,"framebox"}, + {6,"makebox"}, + {7,"cite"}, + {8,"chapter"}, + {8,"section"}, + {8,"subsection"}, + {8,"subsubsection"}, + {8,"paragraph"}, + {8,"subparagraph"}, + {8,"part"}, + {0,""} +}; + +/* + For the command begin, depending on the first argument we will + have zero (default), 1, 2.. other arguments following. Within + the following array the first element of an item describes the + number of arguments, the second one the name of the first + argument related with i.e + + \begin {tabular} + + will have 1 argument. + */ +typcom TabSubCom[]= { + {1,"tabular"}, + {1,"supertabular"}, + {1,"longtable"}, + {1,"thebibliography"}, + {0,""} +}; + +char command[100]; /* the text of a current command to test */ +int nbchcomm; /* the number of character of the curent command */ +char subcom [1000]; /* for debugging etc. */ +int nbsub = 0; /* for debugging etc. */ + +/* + This fuction tests if the LaTeX command is one of the TabCom[] + array. In this case the code (Typ_Com) is returned. + */ +int test_command(void) { + int i = 0; + while (TabCom[i].Name_com[0] != 0) { + if (!strcmp(command,TabCom[i++].Name_com)) return TabCom[i-1].Typ_Com; + } + return 0; +} + +/* + This routine writes down all characters it finds; it looks + for a '{' followed by some text and a '}'; no nesting of braces + is considered. + */ +char test_sub_com(void) { + nbsub = 0; + while (symbol != '}') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + return symbol; +} + +/* + This routine writes down all characters it finds; it looks + twice for a '{' followed by some text and a '}'; for the + second time nesting of braces is considered. + */ +char comm_double_args(void) { + nbsub = 0; + while (symbol != '}') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + /* looking for the end of the second argument */ + sendchar(symbol); + symbol = inp_ch(); + while (symbol != '{') { + sendchar(symbol); + symbol = inp_ch(); + } + sendchar(symbol); + symbol = inp_ch(); + symbol = ignore(); + sendchar(symbol); + symbol = inp_ch(); + return symbol; +} + +/* + For LaTeX commands such as \raisebox{5pt}[10pt][25pt]{.sa.t&vidha.m} + where the second argument must be translated + */ +char comm_special(void) { + nbsub = 0; + while (symbol != '}') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + while (symbol != '{') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + return symbol; +} + +/* + For LaTeX commands such as \framebox[10pt][25pt]{.sa.t&vidha.m} + where optional arguments are not translated and the mandatory + one must be translated + */ +char comm_opt(void) { + nbsub = 0; + while (symbol != '{') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + return symbol; +} + +char comm_chapter(void) { + if (symbol == '[') { + optchapter = 1; + sendchar(symbol); + symbol=inp_ch(); + } + if (symbol == '*') { + sendchar(symbol); + symbol=inp_ch(); + } + return symbol; +} + +char comm_cite(void) { + if (symbol == '[') { + citation = 1; + sendchar(symbol); + symbol = inp_ch(); + } + else test_sub_com(); + return symbol; +} + +char *getsubarg(void) { + char com[20], *result; + int i = 0, j = 0; + while (subcom[i] != '{') i++; + i++; + while (subcom[i] == ' ') i++; + while (isalpha(subcom[i])) com[j++]= subcom[i++]; + com[j] = 0; + i = 0; + result = (char*) malloc (strlen(com)+1); + strcpy (result,com); + return result; +} + +/* + The LaTeX command BEGIN treatment + */ +char comm_begin(void) { + int i = 0, nbargs = 0; + char *com; + nbsub = 0; + while (symbol != '}') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + sendchar(symbol); + symbol = inp_ch(); + com = getsubarg(); + while (TabSubCom[i].Name_com[0] != 0) { + if (!strcmp(com,TabSubCom[i++].Name_com)) + nbargs = TabSubCom[i-1].Typ_Com; + } + if (!nbargs) { /* argument not found within the table */ + free(com); + return symbol; + } + while (nbargs--) { + while (symbol != '{') { + sendchar(symbol); + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + symbol = inp_ch(); + } + sendchar(symbol); + symbol = inp_ch(); + symbol = ignore (); + } + sendchar(symbol); + symbol = inp_ch(); + free(com); + return symbol; +} + +/* + This routine assumes that a '{' has already been read; it + looks for the corresponding closing brace '}'; nesting of + braces is considered. + */ +char ignore(void) { + int nbsub = 0; + int nbbraces = 1; + while (nbbraces ) { + subcom[nbsub++] = symbol; + subcom[nbsub] = 0; + switch (symbol) { + case '{': + nbbraces++; + sendchar(symbol); + break; + case '}': + nbbraces--; + if (!nbbraces) return symbol; + sendchar(symbol); + break; + case ' ': + case '\n': + sendchar(symbol); + put_word(); + break; + default : + sendchar(symbol); + break; + } + symbol = inp_ch(); + } + return symbol ; +} + +/* ------------------ End Addition ----------------- */ + +/* + * *** Devnag function definitions *** + */ + +int main(int argc, char **argv) { + char *s_ptr; + int i; + unsigned char dn_yes; + + /* if invoked with "-v", print banner and exit */ + + if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { + printf("devnag v%s\n", version); + puts(banner); + exit(0); + } + + /* get file specifications */ + + if (argc == 3) { + strcpy(infil, argv[1]); + strcpy(outfil, argv[2]); + } + else { + if (argc == 2) { + strcpy(infil, argv[1]); + *outfil = '\0'; + } + else { + do { + printf("input file: "); + fgets(infil, MEDBUF, stdin); + infil[strlen(infil)-1] = '\0'; + } + while (strlen(infil) == 0); + printf("output file: "); + fgets(outfil, MEDBUF, stdin); + outfil[strlen(outfil)-1] = '\0'; + } + } + if (strlen(outfil) == 0) { + strcpy(outfil, infil); + s_ptr = outfil+strlen(outfil)-3; + if (strcmp(s_ptr, ".dn") == 0) *s_ptr = '\0'; + strcat(outfil, ".tex"); + } + else { + s_ptr = outfil+strlen(outfil)-4; + if (strcmp(s_ptr, ".tex") != 0) strcat(outfil, ".tex"); + } + s_ptr = infil+strlen(infil)-3; + if (strcmp(s_ptr, ".dn") != 0) strcat(infil, ".dn"); + + /* open files */ + + if ((f_in = fopen(infil, "r")) == NULL) { + printf("cannot open file %s\n", infil); + exit(1); + } + f_out = fopen(outfil, "w"); + + /* initialization */ + + cons_seen = FALSE; + vow_seen = FALSE; + front_r = FALSE; + wait_syll = FALSE; + cmr_mode = FALSE; + num_mode = FALSE; + hindi_mode = FALSE; + mhindi_mode = FALSE; + dollar_mode = 0; + do_hyphen = FALSE; + do_vconjuncts = FALSE; + tabs_mode = FALSE; /* Marc Csernel */ + lig_block = FALSE; /* Kevin Carmody */ + + chr_idx = 0; + n_halves = 0; /* Kevin Carmody */ + *word = '\0'; + *inbuf = '\0'; + *outbuf = '\0'; + linenumber = 1; + + fprintf(f_out, "\\def\\DevnagVersion{%s}", version); + + /* main loop */ + + do { + p_in = fgets(inbuf, MAXBUF, f_in); + + /* read preprocessor commands */ + + if (*inbuf == '@') { + while (TRUE) { + if (strstr(inbuf, "dollars\n") == inbuf+1) { + dollar_mode = 1; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "nodollars\n") == inbuf+1) { + dollar_mode = 0; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "dolmode0\n") == inbuf+1) { + dollar_mode = 0; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "dolmode1\n") == inbuf+1) { + dollar_mode = 1; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "dolmode2\n") == inbuf+1) { + dollar_mode = 2; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "dolmode3\n") == inbuf+1) { + dollar_mode = 3; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "hindi\n") == inbuf+1) { + hindi_mode = TRUE; + if (mhindi_mode) { + for (i = 0; i < N_MNOLIGS; i++) + lig_table[modnolig[i]].in_use = TRUE; + mhindi_mode = FALSE; + } + for (i = 0; i < N_NOLIGS; i++) + lig_table[nolig[i]].in_use = FALSE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "modernhindi\n") == inbuf+1) { + hindi_mode = TRUE; + mhindi_mode = TRUE; + for (i = 0; i < N_MNOLIGS; i++) + lig_table[modnolig[i]].in_use = FALSE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "sanskrit\n") == inbuf+1) { + hindi_mode = FALSE; + mhindi_mode = FALSE; + for (i = 0; i < N_MNOLIGS; i++) + lig_table[modnolig[i]].in_use = TRUE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "lig") == inbuf+1) { + s_ptr = inbuf; + while (TRUE) { + if ((s_ptr = strchr(s_ptr, ' ')) == NULL) break; + s_ptr++; + if (sscanf(s_ptr, "%d", &number) != 0) + lig_table[ligidxs[number-1]].in_use = TRUE; + } + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "nolig") == inbuf+1) { + s_ptr = inbuf; + while (TRUE) { + if ((s_ptr = strchr(s_ptr, ' ')) == NULL) break; + s_ptr++; + if (sscanf(s_ptr, "%d", &number) != 0) + lig_table[ligidxs[number-1]].in_use = FALSE; + } + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "hyphen\n") == inbuf+1) { + do_hyphen = TRUE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "nohyphen\n") == inbuf+1) { + do_hyphen = FALSE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + if (strstr(inbuf, "vconjuncts\n") == inbuf+1) { + do_vconjuncts = TRUE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + +/* --------- Addition by Marc Csernel 1998 --------- */ + + if (strstr(inbuf, "tabs\n") == inbuf+1) { + tabs_mode = TRUE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + +/* ------------------ End Addition ----------------- */ + + if (strstr(inbuf, "notabs\n") == inbuf+1) { + tabs_mode = FALSE; + fprintf(f_out, "%%%s", inbuf); + linenumber++; + break; + } + + printf("Warning: possible illegal preprocessor command at line "); + printf("%d:\n%s", linenumber, inbuf); + fprintf(f_out, "%s", inbuf); + linenumber++; + break; + } + *inbuf = '\0'; + } + else { + if (!find_dn()) fputs(inbuf, f_out); + + /* process DN text */ + + else do { + buf_idx = 0; + symbol = inp_ch(); + dnproc(); + dn_yes = find_dn(); + if (!dn_yes) { + strcat(outbuf, inbuf); + fputs(outbuf, f_out); + } + } + while (dn_yes); + *inbuf = '\0'; + linenumber++; + *outbuf = '\0';; + } + } + while (p_in != NULL); + fclose(f_in); + fclose(f_out); + exit(0); +} + + +/* + * Read and parse DN input, and convert it into the character set + * defined in char_table[] + */ +void dnproc(void) { + short i; + unsigned char saved, dnready; + short brace_lev; + int test_val; /* Marc Csernel */ + char savchr = 0; + char wrong[10]; + brace_lev = 1; + saved = FALSE; + dnready = FALSE; + do { + switch(symbol) { + case '.': + savchr = inp_ch(); + i = 0; + do { i++; } while ((i != 19) && (chset1[i-1] != savchr)); + if (i == 19) { + wrong[0] = '.'; + wrong[1] = savchr; + wrong[2] = '\0'; + err_ill(wrong); + } + else { + if (i < 4) { + savchr = inp_ch(); + if (savchr == 'h') i += 11; + else saved = TRUE; + if (i == 1) err_ill(".k"); + } + } + if (i == 18) put_ch('M'); + else put_ch(i); + break; + +/* --------- Addition by Marc Csernel 1998 --------- */ + + /* cite and chapter command */ + case ']': + if (citation) { + citation = 0; + if (num_mode) put_ch(dummy); + put_syll(); + test_sub_com(); + } + if (optchapter) { + optchapter = 0; + if (num_mode) put_ch(dummy); + put_syll(); + sendchar(symbol); + break; + } + +/* ------------------ End Addition ----------------- */ + + case 'i': + savchr = inp_ch(); + if (savchr == 'i') put_ch('I'); + else { + put_ch(symbol); + saved = TRUE; + } + break; + case 'u': + savchr = inp_ch(); + if (savchr == 'u') put_ch('U'); + else { + put_ch(symbol); + saved = TRUE; + } + break; + case 'a': + savchr = inp_ch(); + i = 0; + do { i++; } while ((i != 4) && (chset2[i-1] != savchr)); + if (i == 4) { + put_ch(symbol); + saved = TRUE; + } + else put_ch(chset5[i-1]); + break; + case '\"': + savchr = inp_ch(); + i = 0; + do { i++; } while ((i != 3) && (chset3[i-1] != savchr)); + if (i == 3) { + wrong[0] = '\"'; + wrong[1] = savchr; + wrong[2] = '\0'; + err_ill(wrong); + } + else put_ch(i+17); + break; + case '~': + savchr = inp_ch(); + i = 0; + do { i++; } while ((i != 5) && (chset6[i-1] != savchr)); + if (i == 6) { + wrong[0] = '~'; + wrong[1] = savchr; + wrong[2] = '\0'; + err_ill(wrong); + } + else + if (i == 5) put_ch(47); + else put_ch(i+20); + break; + case end_of_line: + put_ch(end_of_line); + break; + case '$': + if (!dollar_mode) put_ch(symbol); + else { + if (no_dn) put_ch(dummy); + else put_ch('}'); + dnready = TRUE; + put_word(); + strcpy(inbuf, &inbuf[buf_idx]); + } + break; + case '}': + brace_lev -= 1; + if ((brace_lev == 0) && (!d_found)) { + if (no_dn) put_ch(dummy); + else put_ch(symbol); + dnready = TRUE; + put_word(); + strcpy(inbuf, &inbuf[buf_idx]); + } + else put_ch(symbol); + break; + case '{': + put_ch(symbol); + brace_lev += 1; + break; + case '%': + put_ch(symbol); + do { + symbol = inp_ch(); + if (symbol != end_of_line) sendchar(symbol); + } + while (symbol != end_of_line); + sendchar('\n'); + break; + case '<': + put_syll(); + do { + symbol = inp_ch(); + if (symbol == end_of_line) symbol = '\n'; + if (symbol != '>') sendchar(symbol); + } + while (symbol != '>'); + break; + case '\\': + put_ch(symbol); + symbol = inp_ch(); + if (symbol == end_of_line) { + put_word(); + strcat(outbuf, "\n"); + fputs(outbuf, f_out); + *outbuf = '\0'; + } + else { + +/* --------- Addition by Marc Csernel 1998 --------- */ + + /* Modified MC May 98 to take \\[5pt] into account */ + if (symbol == '\\') { + sendchar(symbol); + symbol = inp_ch(); + if (symbol == '[') { + while (symbol != ']') { + sendchar(symbol); + symbol = inp_ch(); + } + sendchar(symbol); + symbol = inp_ch(); + } + savchr = symbol; + saved = TRUE; + break; + } + +/* ------------------ End Addition ----------------- */ + + if (!isalpha(symbol)) sendchar(symbol); + else { + nbchcomm = 0; /* Marc Csernel */ + do { + command[nbchcomm++] = symbol; /* Marc Csernel */ + sendchar(symbol); + symbol = inp_ch(); + } + while (isalpha(symbol)); + +/* --------- Addition by Marc Csernel 1998 --------- */ + + command[nbchcomm++] = 0; + test_val = test_command(); + switch (test_val) { + case 1: + savchr = test_sub_com(); + break; + case 2: + savchr = ignore(); + break; + case 3: + savchr = comm_double_args(); + break; + case 4: + savchr = comm_begin(); + break; + case 5: + savchr = comm_special(); + break; + case 6: + savchr = comm_opt(); + break; + case 7: + savchr = comm_cite(); + break; + case 8: + savchr = comm_chapter(); + break; + default: + savchr = symbol; + } + +/* ------------------ End Addition ----------------- */ + + saved = TRUE; + } + } + break; + case ill_char: + err_ill('\0'); + break; + case end_of_file: + puts("Error: missing }"); + exit(1); + default: + i = 0; + do { i++; } while ((i != 10) && (chset4[i-1] != symbol)); + if (i == 10) put_ch(symbol); + else { + savchr = inp_ch(); + if (savchr == 'h') { + if (i == 9) put_ch(20); + else put_ch(symbol-32); + } + else { + put_ch(symbol); + saved = TRUE; + } + } + } + if (saved) { + symbol = savchr; + saved = FALSE; + } + else { + if (!dnready) symbol = inp_ch(); } + } + while (!dnready); +} + +/* + * Read and parse input in the character set defined by char_table[], + * and convert it into TeX text and macros for the dvng fonts. + */ +void put_ch(short code) { + short cons_idx = 0; + char cstr[2]; + struct char_def *c_ptr; + struct cons_joins *q_ptr; + short i, j; + /* --------- Addition by Kevin Carmody 2005 --------- */ + /* + * Conjunct fixes used by fixconj() + */ + short wrong_1[] = {63, 63, 113}; + short right_1[] = {63, 34, 0}; /* kk.sa */ + short wrong_2[] = {94, 214, 264, 113}; + short right_2[] = {94, 86, 264, 34, 0}; /* .tk.sa */ + short wrong_3[] = {22, 62, 26}; + short right_3[] = {22, 226, 0}; /* ~nj~na */ + short wrong_4[] = {274, 88, 264, 273, 57, 52, 264, 121}; + short right_4[] = {126, 88, 264, 43, 0}; /* .drya */ + short wrong_5[] = {94, 140, 264, 118}; + short right_5[] = {94, 100, 264, 146, 0}; /* ddva */ + short wrong_6[] = {94, 136, 264, 118}; + short right_6[] = {94, 100, 264, 64, 118, 0}; /* ddhva */ + short wrong_7[] = {271, 100, 264, 273, 57, 52, 264, 121}; + short right_7[] = {272, 100, 264, 43, 0}; /* drya */ + short wrong_8[] = {9, 274, 86, 264, 273, 57, 52, 264, 121}; + short right_8[] = {9, 126, 86, 264, 43, 0}; /* .s.trya */ + /* ------------------ End Addition ----------------- */ + + c_ptr = &char_table[code-1]; + switch(c_ptr->ch_typ) { + case dn: + if (cmr_mode) { + cmr_mode = FALSE; + put_sym(RE); + } + else { + if (num_mode) { + num_mode = FALSE; + put_sym(RBRACE); + } + } + switch(c_ptr->ch_subtyp) { + case hi_vowel: + if (wait_syll) { + put_syll(); + if (do_hyphen) strcat(word, "\\-"); + } + if (lig_block) err_ill("+"); /* Kevin Carmody */ + if (cons_seen) { + if (syll[chr_idx-1] < 0) expand(); + if (code == 'i') { + for (i = chr_idx; i>= (cons_idx+1); i--) + syll[i] = syll[i-1]; + syll[cons_idx] = c_ptr->ch_subcode; + } + else { + syll[chr_idx] = c_ptr->ch_subcode; + if ((code != 'A') && (code != 'a')) vow_seen = TRUE; + } + } + else syll[chr_idx] = c_ptr->ch_code; + chr_idx += 1; + wait_syll = TRUE; + cons_seen = FALSE; + break; + case lo_vowel: + if (wait_syll) { + put_syll(); + if (do_hyphen) strcat(word, "\\-"); + } + if (lig_block) err_ill("+"); /* Kevin Carmody */ + if (cons_seen) { + if (syll[chr_idx-1] < 0) expand(); + if ((syll[chr_idx-1] == 'r') && (code == 'u')) + syll[--chr_idx] = 'z'; + else { + if ((syll[chr_idx-1] == 'r') && (code == 'U')) + syll[--chr_idx] = '!'; + else { + if ((syll[chr_idx-1] == 'h') && (code == 7)) + syll[--chr_idx] = 0343; + else { + if ((syll[chr_idx-1] == 'r') && ((code == 7) + || (code == 15) || (code == 16) || (code == 17))) { + syll[--chr_idx] = c_ptr->ch_code; + front_r = TRUE; + } + else { + put_macro(c_ptr->ch_subcode); + chr_idx -= 1; + } + } + } + } + } + else syll[chr_idx] = c_ptr->ch_code; + chr_idx += 1; + wait_syll = TRUE; + cons_seen = FALSE; + break; + case consonant: + if (wait_syll) { + put_syll(); + if (do_hyphen) strcat(word, "\\-"); + } + if (!cons_seen) { + + /* Is this the first consonant? */ + + cons_seen = TRUE; + cons_idx = chr_idx; + cons_code = c_ptr->ch_subcode; + syll[chr_idx] = c_ptr->ch_code; + chr_idx += 1; + tst_half(); + } + else { + q_ptr = &cons_table[cons_code]; + if (syll[cons_idx] == 'r') { + + /* Was there an initial "r"? */ + + front_r = TRUE; + syll[chr_idx-1] = c_ptr->ch_code; + cons_code = c_ptr->ch_subcode; + tst_half(); + } + else { + i = q_ptr->lig_code; + for (j = i+(q_ptr->n_ligs); i != j; i++) + if (lig_table[i].sym_code == code) break; + if ((i != j) && (lig_table[i].in_use) + && (!lig_block)) { /* lig_block added Kevin Carmody */ + + /* Is there a ligature? */ + + syll[chr_idx-1] = lig_table[i].sym_new; + cons_code = lig_table[i].join_idx; + joincode = cons_table[cons_code].j_code; + if (joincode != 0) { + half_codes[0] = joincode; + n_halves = 1; + } + else { + + /* ... or a half-form? */ + + joincode = cons_table[c_ptr->ch_subcode].j_code; + if ((joincode != 0) && (n_halves != 0)) { + half_codes[n_halves] = joincode; + n_halves += 1; + } + else n_halves = 0; + } + } + else { + if ((code == 'r') && (!lig_block)) { + /* lig_block added Kevin Carmody */ + if (q_ptr->r_type != 0) { + + /* "Special" non-initial "r"? */ + + syll[chr_idx] = syll[chr_idx-1]; + syll[chr_idx-1] = (q_ptr->r_type == 1) ? '\176' : 272; + syll[chr_idx+1] = RBRACE; + chr_idx += 2; + } + else { + + /* "Normal" non-initial "r"? */ + + syll[chr_idx] = '\175'; + chr_idx += 1; + n_halves = 0; + } + cons_code = 0; + } + else { + if ((q_ptr->j_code != 0) && (!lig_block)) { + /* lig_block added by Kevin Carmody */ + + /* Can we build a conjunct using a ligature? */ + + syll[chr_idx-1] = q_ptr->j_code; + syll[chr_idx] = c_ptr->ch_code; + cons_code = c_ptr->ch_subcode; + chr_idx += 1; + tst_half(); + } + else { + if (n_halves != 0) { + + /* ... or a half-form? */ + + if (syll[chr_idx-1] != RBRACE) { + /* + * There might already have been a + * subscript "-r" in the conjunct! + * (E.g. khrya, ttrya) + * -- John Smith + */ + for (i = 0; i < n_halves; i++) + syll[chr_idx-1+i] = half_codes[i]; + chr_idx += n_halves; + syll[chr_idx-1] = c_ptr->ch_code; + cons_code = c_ptr->ch_subcode; + tst_half(); + } + else { + for (i = 0; i < n_halves; i++) + syll[chr_idx-2+i] = half_codes[i]; + chr_idx += n_halves; + syll[chr_idx-1] = c_ptr->ch_code; + syll[chr_idx-2] = RBRACE; + cons_code = c_ptr->ch_subcode; + tst_half(); + } + } + else { + + /* Fall back on viraama */ + + if (syll[chr_idx-1] < 0) expand(); + put_macro(VIRAAM); + cons_code = c_ptr->ch_subcode; + syll[chr_idx] = c_ptr->ch_code; + chr_idx += 1; + tst_half(); + } + } + } + /* + * This hack is to secure the correct representation + * for various conjuncts that may assume undesirable + * forms. + */ +/* --------- Modification by Kevin Carmody 2005 --------- */ + fixconj(wrong_1, right_1); + fixconj(wrong_2, right_2); + fixconj(wrong_3, right_3); + fixconj(wrong_4, right_4); + fixconj(wrong_5, right_5); + fixconj(wrong_6, right_6); + fixconj(wrong_7, right_7); + fixconj(wrong_8, right_8); +/* ------------------ End Modification ----------------- */ + /* + * Now replace the sequence consonant + viraama + ya + * by consonant + open ya (glyph became available only + * Devnag 2.1). + */ + for (i = 0; i < chr_idx-3; i++) { + if ((syll[i] == 94) && (syll[i+2] == 264) + && (syll[i+3] == 121)) { + syll[i] = syll[i+1]; + syll[i+1] = 43; + chr_idx = i + 2; + } + } + } + } + } + lig_block = FALSE; /* Kevin Carmody */ + break; + case special: + if (lig_block) err_ill("+"); /* Kevin Carmody */ + if (cons_seen) { if (syll[chr_idx-1] < 0) expand(); } + if ((code == 'M') && (front_r)) { + front_r = FALSE; + if (vow_seen) syll[chr_idx] = 270; + else syll[chr_idx] = RDT; + chr_idx += 1; + put_syll(); + } + else { + if ((code == 'M') && (syll[chr_idx-1] == 'I')) { + syll[chr_idx-1] = 18; + put_syll(); + } + else { + if ((code == 'M') && (vow_seen)) { + syll[chr_idx] = 268; + chr_idx += 1; + put_syll(); + } + +/* --------- Addition by Marc Csernel 1998 --------- */ + + else { + if (code == '_') { + if(!cons_seen) err_ill("_"); + else { + put_macro(VIRAAM); + put_syll(); + } + } + else { + if (code == '&') { + if(!tabs_mode) { + if (!cons_seen) { + printf("Error: tabs_mode not selected\n"); + err_ill("&"); + } + else { + put_macro(VIRAAM); + put_syll(); + } + } + else { + if(!cons_seen) sendchar(code); + else { + put_macro(VIRAAM); + put_syll(); + } + } + } + +/* ------------------ End Addition ----------------- */ + + else { + +/* --------- Addition by Kevin Carmody 2005 --------- */ + + if (code == '+') { /* half letter or viraama */ + if (!cons_seen) err_ill("+"); + lig_block = TRUE; + } +/* ------------------ End Addition ------------------ */ + + else { + if ((!hindi_mode) && (cons_seen)) put_macro(VIRAAM); + put_syll(); + put_sym(c_ptr->ch_code); + } + } + } + } + } + } + } + break; + case illegal: + cstr[0] = code; + cstr[1] = '\0'; + err_ill(cstr); + break; + case control: + if (cmr_mode) { + cmr_mode = FALSE; + put_sym(RE); + } + else { + if (lig_block) err_ill("+"); /* Kevin Carmody */ + if (num_mode) { + num_mode = FALSE; + put_sym(RBRACE); + } + else { + if (cons_seen) { + if (syll[chr_idx-1] < 0) expand(); + } + if ((!hindi_mode) && (cons_seen)) put_macro(VIRAAM); + put_syll(); + } + } + if (code == end_of_line) { + put_word(); + strcat(outbuf, "\n"); + fputs(outbuf, f_out); + *outbuf = '\0'; + } + else if (code != dummy) sendchar(code); + break; + case cmr: + if (cmr_mode) sendchar(code); + else { + cmr_mode = TRUE; + if (num_mode) { + num_mode = FALSE; + put_sym(RBRACE); + } + else { + if (lig_block) err_ill("+"); /* Kevin Carmody */ + if (cons_seen) { if (syll[chr_idx-1] < 0) expand(); } + if ((!hindi_mode) && (cons_seen)) put_macro(VIRAAM); + put_syll(); + } + put_sym(RS); + sendchar(code); + } + break; + case numeral: + if (num_mode) sendchar(code); + else { + num_mode = TRUE; + if (cmr_mode) { + cmr_mode = FALSE; + put_sym(RE); + } + else { + if (lig_block) err_ill("+"); /* Kevin Carmody */ + if (cons_seen) { if (syll[chr_idx-1] < 0) expand(); } + if ((!hindi_mode) && (cons_seen)) put_macro(VIRAAM); + put_syll(); + } + put_sym(RN); + sendchar(code); + } + } +} + +/* + * Append a character to word[]; if character is whitespace, + * call put_word(). + */ +void sendchar(char c) { + int i = strlen(word); + word[i] = c; + word[i+1] = '\0'; + if (isspace(c)) put_word(); +} + +/* + * Use the current chacter value as an index into out_string[], and + * append the code found there to the end of word[]. + */ +void put_sym(short code) { + strcat(word, out_string[code]); +} + +/* + * Append word[] to outbuf[]. + */ +void put_word(void) { + /* + * The hack is to avoid hyphenation before any consonant stopped + * with viraama. -- John Smith + */ + char *w_ptr; + if (do_hyphen) { /* hack */ + do { + w_ptr = strstr(word, "\\-\\qq{"); + if (w_ptr != NULL) strcpy(w_ptr, w_ptr+2); + } + while (w_ptr != NULL); + } + strcat(outbuf, word); + *word = '\0'; +} + +/* + * Append syll[] to word[], using the codes defined in out_string[] + */ +void put_syll(void) { + /* + * put_syll() now checks to see whether "old-style" treatment of + * consonant sequences containing viraama has been requested with + * the @vconjuncts preprocessor command. If not, it re-orders the + * characters in any such sequence containing "i" so that the + * i-matra vowel is placed after the viraama rather than before + * the entire sequence. -- John Smith + */ + short i; + int ipos, vpos, bpos; + if (do_vconjuncts == FALSE) { + ipos = sindex(0, '\105'); /* 'i' */ + if (ipos != -1) { + vpos = sindex(ipos, '\136'); /* viraama */ + if (vpos == -1) { + vpos = sindex(ipos, 271); + if (vpos == -1) vpos = sindex(ipos, 274); + if (vpos != -1) { + vpos = sindex(vpos, 273); /* alternative viraama */ + if ((syll[vpos+1] != '9') || (syll[vpos+2] != '4')) vpos = -1; + } + } + if (vpos != -1) { + bpos = sindex(vpos, 264); /* right brace after viraama */ + if (bpos != -1) { + for (i = ipos+1; i <= bpos; i++) + syll[i-1] = syll[i]; + syll[bpos] = '\105'; + } + } + } + } + for (i = 0; i < chr_idx; i++) + strcat(word, out_string[syll[i]]); + if (front_r) { + if (vow_seen) strcat(word, out_string[269]); + else strcat(word, out_string[13]); + front_r = FALSE; + } + chr_idx = 0; + cons_seen = FALSE; + vow_seen = FALSE; + wait_syll = FALSE; + lig_block = FALSE; /* Kevin Carmody */ +} + +/* + * Check whether a "half-form" exists for current consonant, and + * store the result. + */ +void tst_half(void) { + joincode = cons_table[cons_code].j_code; + if (joincode != 0) { + half_codes[0] = joincode; + n_halves = 1; + } + else n_halves = 0; +} + +/* + * Manipulate contents of syll[] to incorporate a macro call, + * using values that are indices into out_string[] (so that + * put_syll() will produce the correct output). + */ +void put_macro(short macro) { + char tmp[5]; + int lt, i; + if (syll[chr_idx-1] == '\175') { + syll[chr_idx+1] = '\175'; + syll[chr_idx] = RBRACE; + syll[chr_idx-1] = syll[chr_idx-2]; + syll[chr_idx-2] = macro; + chr_idx += 2; + } + else { + if (syll[chr_idx-1] == RBRACE) { + /* + * This is a bit of a hack on Velthuis's part! What it + * really means is: if syll[] currently consists of "dr" + * OR a consonant(-group) with the subscript "caret" form + * of "-r" already attached, AND if a subscript vowel + * (or viraama) is to be added to it. In pre-2.0 releases + * of devnag this always produced "\qa{consonant}{vowel}", + * i.e. it used the simple, non-"caret" form of "-r", + * whatever the consonant to which it was to be attached. + * I have fixed this bug (feature?), but at the cost of + * invoking a new macro, \qc, which will have to be + * defined in dnmacs.tex etc. for the new code to work. + * -- John Smith + */ + if (syll[chr_idx-3] == 126) syll[chr_idx-3] = 274; + else syll[chr_idx-3] = 271; + syll[chr_idx] = LBRACE; + sprintf(tmp, "%d", macro); + lt = strlen(tmp); + chr_idx += 1; + for (i = 0; i < lt; i++) + syll[chr_idx+i] = tmp[i]; + chr_idx += lt; + syll[chr_idx] = RBRACE; + chr_idx += 1; + } + else { + syll[chr_idx] = syll[chr_idx-1]; + syll[chr_idx-1] = macro; + syll[chr_idx+1] = RBRACE; + chr_idx += 2; + } + } +} + +/* + * Exit with error message in the case of illegal input. + */ +void err_ill(char *str) { + printf("Error: illegal character(s) \"%s\" detected at line %d:\n", + str, linenumber); + printf(inbuf); + exit(1); +} + +/* + * Read and return the next character from inbuf[], taking appropriate + * action in the case of EOL, EOF or an illegal character. + */ +char inp_ch(void) { + char ch, ch_out; + ch = inbuf[buf_idx++]; + if (ch == '\n') { + if (p_in == 0) ch_out = end_of_file; + else { + p_in = fgets(inbuf, MAXBUF, f_in); + linenumber++; + buf_idx = 0; + ch_out = end_of_line; + } + } + else { + if (ch == '\t') ch_out = ' '; /* Change TABs to spaces */ + else { + if (ch < 32) ch_out = ill_char; + else ch_out = ch; + } + } + return(ch_out); +} + +/* + * Invoked if syll[chr_idx-1] is negative (instead of containing + * an octal character value). Fixes appropriate representation + * for "r". + */ +void expand(void) { + short indx; + indx = -1-syll[chr_idx-1]; + if (r_ligs[indx][1] != 0) { + syll[chr_idx] = r_ligs[indx][0]; + syll[chr_idx-1] = (r_ligs[indx][1] == 1) ? '\176' : 272; + syll[chr_idx+1] = RBRACE; + chr_idx += 2; + } + else { + syll[chr_idx-1] = r_ligs[indx][0]; + syll[chr_idx] = '\175'; + chr_idx += 1; + } + cons_code = 0; +} + +/* + * Search inbuf[] for "{\dn" followed by non-letter or, in dollar + * mode only, for "$". Return TRUE or FALSE as appropriate. If + * TRUE, send inbuf[] text prior to mode-switch to outbuf[], followed + * by mode-switch indicator, and make inbuf[] start at beginning of + * Devanagari text. + */ +char find_dn(void) { + char *d_ptr; + char *dn_ptr; + char *svbuf; + int again; + d_found = FALSE; + svbuf = inbuf; + do { + again = FALSE; + dn_ptr = strstr(svbuf, "{\\dn"); + if (dn_ptr != NULL) { + again = isalpha(dn_ptr[4]); + svbuf = dn_ptr+4; + } + } + while (again); + if (dollar_mode) { + d_ptr = strchr(inbuf, '$'); + if ((d_ptr != NULL) && ((dn_ptr == NULL) || (d_ptr < dn_ptr))) { + d_found = TRUE; + dn_ptr = d_ptr; + } + } + if (dn_ptr == NULL) return(FALSE); + strncat(outbuf, inbuf, dn_ptr-inbuf); + no_dn = FALSE; + if (!d_found) { + if (dn_ptr[4] == '#') { /* equivalent to @dolmode3 */ + no_dn = TRUE; + dn_ptr += 1; + } + else strcat(outbuf, "{\\dn"); + dn_ptr += 4; + } + else { + switch(dollar_mode) { + case 1: + strcat(outbuf, "{\\dn "); + break; + case 2: + strcat(outbuf, "\\pdn "); + case 3: + no_dn = TRUE; + } + dn_ptr += 1; + } + strcpy(inbuf, dn_ptr); + return(TRUE); +} + +/* + * Return index of character value in syll[] starting at syll[i], + * -1 if none + */ +int sindex(int i, short t) { + int j; + for (j = i; j < chr_idx; j++) { + if (syll[j] == t) return j; + } + return -1; +} + +/* + * Replace infelicitous conjuncts + */ +void fixconj(short *wrong, short *right) { + int i; + for (i = 0; i < chr_idx; i++) { + if (syll[i] != wrong[i]) return; + } + for (i = 0; right[i] != 0; i++) { + syll[i] = right[i]; + } + chr_idx = i; +} |