home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume36 / translit / part08 < prev    next >
Encoding:
Text File  |  1993-03-21  |  62.7 KB  |  1,913 lines

  1. Newsgroups: comp.sources.misc
  2. From: jkl@osc.edu (Jan Labanowski)
  3. Subject: REPOST: v36i030:  translit - transliterate foreign alphabets, Part08/10
  4. Message-ID: <1993Mar23.031051.21304@sparky.imd.sterling.com>
  5. X-Md4-Signature: 8dbd56262e22e63de4c0c140853fb7e5
  6. Date: Tue, 23 Mar 1993 03:10:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jkl@osc.edu (Jan Labanowski)
  10. Posting-number: Volume 36, Issue 30
  11. Archive-name: translit/part08
  12. Environment: UNIX, MS-DOS, VMS
  13.  
  14. [ This is being reposted due to a file containing control characters ]
  15. [ didn't make it through news systems...        -Kent+               ]
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  example.tex.UU koi8-tex.rus readme.doc reg_exp.c
  22. # Wrapped by kent@sparky on Fri Mar 19 16:00:14 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 8 (of 10)."'
  26. if test -f 'example.tex.UU' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'example.tex.UU'\"
  28. else
  29.   echo shar: Extracting \"'example.tex.UU'\" \(13202 characters\)
  30.   sed "s/^X//" >'example.tex.UU' <<'END_OF_FILE'
  31. begin 664 example.tex
  32. M7&1O8W5M96YT<W1Y;&5[87)T:6-L97T*7&EN<'5T(&-Y<F%C8RYD968*7&9O
  33. M;G1<=&5N8WER/7=N8WER,3 *7&1E9EQC>7)[7'1E;F-Y<EQC>7)A8V-]"EQB
  34. M96=I;GMD;V-U;65N='T*('M<8WER($$@0B!6($<@1"!%(%PB12!::"!:($D@
  35. M>UQU($E]($L@3"!-($X@3R!0(%(@4R!4(%4@1B!+:"!#($-H(%-H(%-H8V@@
  36. M>UQ#9'!R:6UE?2!9('M<0W!R:6UE?2!<8$4@674@66$@4UQ<#0IA(&(@=B!G
  37. M(&0@92!<(F4@>F@@>B!I('M<=2!I?2!K(&P@;2!N(&\@<"!R(',@="!U(&8@
  38. M:V@@8R!C:"!S:"!S:&-H('M<8V1P<FEM97T@>2![7&-P<FEM97T@7&!E('EU
  39. M('EA(%1<7 T*>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]
  40. M>UP@7"!]>UP@7"!]("AI>B!G87IE='D@4TUO<VMO=G-K:64@;F]V;W-T:50L
  41. M(#8N,3(N.3(I7%P-"GM<(%P@?7M<(%P@?7M<(%P@?7M<(%P@?7M<(%P@?7M<
  42. M(%P@?7M<(%P@?7M<(%P@?7M<(%P@?7M<(%P@?7M<(%P@?7M<(%P@?7M<(%P@
  43. M?7M<(%P@?7M<(%P@?2!665I/5GM<(%P@?2 H8VAA<W1[7&-P<FEM97T@<&5R
  44. M=F%Y82E<7 T*>UP@7"!]>UP@7"!]5B!K86MO>UQU(&E]('-U971E(&UY('-E
  45. M9V]D;GEA('IH:79<(F5M+GM<(%P@?41A>FAE('!O;&ET:6MA+"!I('1A(&1A
  46. M=FYO('5Z:&5<7 T*<&5R97-T86QA(&YA<R!Z86YI;6%T>UQC<')I;65]+GM<
  47. M(%P@?4UY(&]B<F%S:&-H865M(&YA(&YE7")E('9N:6UA;FEE('1O;'M<8W!R
  48. M:6UE?6MO('1O9V1A+"!K;V=D85Q<#0IN879E<FMH=2!R87IG;W)A971[7&-Y
  49. M9&]T?7-Y82!O8VAE<F5D;F%Y82!S=F%R82Y[7"!<('U.92!V;VQN=7EU="!N
  50. M87,@:2!M:7)O=GEE('!R;V)L96UY+EQ<#0I#:'1O('IH+"!Z87IE;6Q<(F5N
  51. M;F]S='M<8W!R:6UE?2!N87-H96=O(&)Y=&EY82!V<&]L;F4@<&]N>6%T;F$N
  52. M>UP@7"!]02!M97IH9'4@=&5M('!R;VES:VAO9'EA<VAC:&5E7%P-"G9O:W)U
  53. M9R!D97M<=2!I?7-T=FET96Q[7&-P<FEM97UN;R!P<FEO8G)E=&%E="!G;&]B
  54. M86Q[7&-P<FEM97UN>64@:7IM97)E;FEY82Y<7 T*>UP@7"!]>UP@7"!]>UP@
  55. M7"!]>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]+BXN+BXN+BXN+BXN
  56. M+BXN+BXN+BXN+BXN+BXN+BXN+BXN+EQ<#0I[7"!<('U[7"!<('U[7"!<('U[
  57. M7"!<('U[7"!<('U[7"!<('U[7"!<('U[7"!<('U[7"!<('U[7"!<('T@4U-3
  58. M4B!53452+GM<(%P@?4M43R!03T)%1$E,/UQ<#0I[7"!<('U[7"!<('TN+BY)
  59. M=&%K+"!T;VQ[7&-P<FEM97UK;R!T97!E<GM<8W!R:6UE?2!N86-H:6YA>75T
  60. M('9Y<FES;W9Y=F%T>UQC<')I;65]<WEA(&MO;G1U<GD@=&5K:"!G<F%N9&EO
  61. M>FYY:VA<7 T*<&]S;&5D<W1V:7M<=2!I?2P@:V]T;W)Y92!S=GEA>F%N>2!S
  62. M(&MR86MH;VT@:V]M;75N:7IM82!V(%-O=F5T>UQC>61O='US:V]M(%-O>75Z
  63. M92!I(&5G;UQ<#0IR87-P861O;2Y[7"!<('U%<VAC:%PB92!V8VAE<F$@>F%R
  64. M=6)E>FAN>64@86YA;&ET:6MI(',@;VQI;7!I>UQU(&E]<VMI;2!B97-P<FES
  65. M=')A<W1I96U<7 T*=GII<F%L:2!N82!B97IR87-S=61O8VAN>64@:7IG:6)Y
  66. M(&YA<VAE9V\@=GER>79N;V=O(&D@;F5P;VYY871N;V=O(&1V:7IH96YI>6$N
  67. M7%P-"E-E9V]D;GEA('5Z:&4@;6YO9VEM('-T86YO=FET>UQC>61O='US>6$@
  68. M>6%S;F\L(&-H=&\@<W5M8G5R;GEE(&MO;G9U;'M<8W!R:6UE?7-I:5Q<#0IP
  69. M;W-T:V]M;75N:7-T:6-H97-K;V=O(&UI<F$@<V%M>6T@;F5P;W-R961S='9E
  70. M;FYY;2!O8G)A>F]M('IA=')A9VEV87EU=%Q<#0ID86Q[7&-P<FEM97UN97M<
  71. M=2!I?7-H=7EU('-U9'M<8W!R:6UE?6)U('9S96=O(&UE>FAD=6YA<F]D;F]G
  72. M;R!S;V]B<VAC:&5S='9A+GM<(%P@?41A+"!K;VUM=6YI>FT@<G5K:&YU;"Q<
  73. M7 T*4U-34B!I<V-H97H@<R!P;VQI=&EC:&5S:V][7'4@:7T@:V%R='DL(&YO
  74. M('1E;2!S86UY;2!B>6QA('IA=F5R<VAE;F$@8V5L87EA(&=L879A7%P-"G8@
  75. M:7-T;W)I:2!V<V5[7'4@:7T@8VEV:6QI>F%C:6DN7%P-"GM<(%P@?7M<(%P@
  76. M?4YE('1O;'M<8W!R:6UE?6MO(&YA<VQE9&YI:VD@:V]M;75N:7IM82P@;F\@
  77. M:2!O<W1A;'M<8W!R:6UE?6YO>UQU(&E](&UI<B!O:V%Z86QI<WM<8W!R:6UE
  78. M?2!V9')U9UQ<#0IP97)E9"!C:&ES='EM(&QI<W1O;2Y[7"!<('U0;R!M97)E
  79. M(&]S;WIN86YI>6$@7&!E=&]G;R!F86MT82!V('IA<G5B97IH;GEK:%Q<#0IP
  80. M;VQI=&EC:&5S:VEK:"!K<G5G86MH('!E<G9A>6$@7&!E>UQU(&E]9F]R:7EA
  81. M('!O8F5D>2!N860@4VEM<&5R:65[7'4@:7T@>FQA5"!I(&YE:V]E9V]<7 T*
  82. M<V%M;W5D;W9L971V;W)E;FEY82!S;65N>6%E='M<8WED;W1]<WEA('9S7")E
  83. M(&)O;'M<8W!R:6UE?7-H97M<=2!I?2!O>F%B;V-H96YN;W-T>UQC<')I;65]
  84. M>74L(')A<W1E<GEA;FYO<W1[7&-P<FEM97UY=2Q<7 T*82!K;V4M9V1E(&D@
  85. M<&%N:6MO>UQU(&E]+GM<(%P@?5)E8VA[7&-P<FEM97T@:61<(F5T(&YE('1O
  86. M;'M<8W!R:6UE?6MO(&\@=')E=F]G92P@=GEZ=F%N;F][7'4@:7U<7 T*;F5P
  87. M<F5D<VMA>G5E;6]S='M<8W!R:6UE?7EU('!R;V-E<W-O=B!N82!T97)R:71O
  88. M<FEI('9C:&5R87-H;F5G;R!34U-2+GM<(%P@?4MS=&%T:2P@<&]K85Q<#0IO
  89. M;FD@;F4@<')I;GEA;&D@<W1O;'M<8W!R:6UE?2!A<&]K86QI<'-I8VAE<VMO
  90. M>UQU(&E](&9O<FUY+"!K86L@;WIH:61A;&D@;6YO9VEE+"!I7%P-"G!R;W1E
  91. M:V%Y=70@=B!O=&QI8VAI92!O="!9=6=O<VQA=FEI(&)O;&5E(&-I=FEL:7IO
  92. M=F%N;F\N7%P-"GM<(%P@?7M<(%P@?59D<G5G(',@;V-H979I9&YO<W1[7&-P
  93. M<FEM97UY=2!O=&MR>6QO<WM<8W!R:6UE?2!D<G5G;V4@+2!C:'1O+"!N97-M
  94. M;W1R>6$@;F$@=FYE<VAN95Q<#0IA8G-O;'EU=&YU>74@<')O=&EV;W!O;&]Z
  95. M:&YO<W1[7&-P<FEM97T@>F%P861N;WM<=2!I?2!I(&MO;6UU;FES=&EC:&5S
  96. M:V][7'4@:7T@<VES=&5M+"!O;FE<7 T*=GIA:6UO<W9Y87IA;GDN>UP@7"!]
  97. M365K:&%N:7IM(')A>G9I=&EY82!T;WM<=2!I?2!I(&1R=6=O>UQU(&E]+"!K
  98. M86L@=&5P97)[7&-P<FEM97T@;V)N87)U>FAI=F%E='M<8WED;W1]<WEA+%Q<
  99. M#0IB>6P@>F%P<F]G<F%M;6ER;W9A;B!N82!N86QI8VAI92!S=F]E9V\@86YT
  100. M86=O;FES=&$N7%P-"GM<(%P@?7M<(%P@?45S:&-H7")E('!R961S=&]I="!R
  101. M87IO8G)A='M<8W!R:6UE?7-Y82P@=B!K86MO>UQU(&E]('-T97!E;FD@=&4@
  102. M:6QI(&EN>64@=&5N9&5N8VEI7%P-"F]B<VAC:&5S='9E;FYO>UQU(&E]('IH
  103. M:7IN:2!:87!A9&$@>6%V:6QI<WM<8W!R:6UE?2!R97IU;'M<8W!R:6UE?71A
  104. M=&]M(&5G;R!V;G5T<F5N;GE[7'4@:7T@7&!E=F]L>75C:6DL(&%<7 T*=B!K
  105. M86MO>UQU(&E](&)Y;&D@;V)U<VQO=FQE;GD@<W5S:&-H97-T=F]V86YI96T@
  106. M:V]M;75N:7-T:6-H97-K;V=O(&]B<VAC:&5S='9A+"!I7%P-"FYA;V)O<F]T
  107. M+GM<(%P@?4YO('IA<&%D;GE[7'4@:7T@;6ER+"!T86L@9&]L9V\@:2!A:W1I
  108. M=FYO(&1O8FEV879S:&E[7'4@:7US>6$@:V]N8V%<7 T*:V]M;75N:7IM82P@
  109. M;VMA>F%L<WEA(&YE('!O9&=O=&]V;&5N;GEM(&L@>FAI>FYI('!O<VQE(&5G
  110. M;R!P861E;FEY82Y[7"!<('U/;F]<7 T*;F%R=7-H:6QO(&=L;V)A;'M<8W!R
  111. M:6UE?6YU>74@<VES=&5M=2!B97IO<&%S;F]S=&D@:2!O8G-H8VAE>FAI=&EY
  112. M82P@:V]T;W)A>6$@<VMR=7!U;%PB97IN;UQ<#0IS;WID879A;&%S>UQC<')I
  113. M;65]('!O<VQE('9T;W)O>UQU(&E](&UI<F]V;WM<=2!I?2!V;WM<=2!I?6YY
  114. M+"!U<W!E;&$@;V)R87-T:2!S=F]E>UQU(&E](&)Y=7)O:W)A=&EE>UQU(&E]
  115. M(&E<7 T*<&]L=6-H:71[7&-P<FEM97T@9&%Z:&4@<V]B<W1V96YN=7EU(&QO
  116. M9VEK=2!R87IV:71I>6$N>UP@7"!]02!T=70@=B!O9&YO(&UG;F]V96YI92!<
  117. M8&5T;W1<7 T*;6ER;W!O<GEA9&]K(')A>G9A;&EL<WEA+EQ<#0I[7"!<('U[
  118. M7"!<('U6;65S=&4@<R!N:6T@<&]K86-H;G5L87-[7&-P<FEM97T@=G-Y82!R
  119. M87IV971V;%PB96YN87EA('-I<W1E;6$@:6YS=&ET=71O=B!I7%P-"F-E;FYO
  120. M<W1E>UQU(&E]+"!N82!K;W1O<GEK:"!D;R!S:6MH('!O<B!D97)Z:&%L;W-[
  121. M7&-P<FEM97T@:VAR=7!K;V4@;6ER;W9O92!R879N;W9E<VEE+EQ<#0I3=&%L
  122. M;R!Y87-N;RP@8VAT;R!N92!T;VQ[7&-P<FEM97UK;R!B>79S:&EM(&MO;6UU
  123. M;FES=&EC:&5S:VEM(&=O<W5D87)S='9A;2P@;F\@:5Q<#0IV<V5M=2!M:7)O
  124. M=F]M=2!S;V]B<VAC:&5S='9U('!R961S=&]I="!I<VMA='M<8W!R:6UE?2!N
  125. M;W9Y92!F;W)M>2!S=7-H8VAE<W1V;W9A;FEY82Y<7 T*4')I9%PB971[7&-Y
  126. M9&]T?7-Y82!Z86YO=F\@;W-M>7-L:79A='M<8W!R:6UE?2!M;F]G:64@=F]P
  127. M<F]S>2P@:V%Z879S:&EE<WEA(')A>B!I(&YA=G-E9V1A7%P-"G)E<VA<(F5N
  128. M;GEM:2Y[7"!<('U3:V%Z:&5M+"!S=&%B:6Q[7&-P<FEM97UN;W-T>UQC<')I
  129. M;65](&=R86YI8R!I;&D@;V)E<W!E8VAE;FEE(&-E;&]S=&YO<W1I7%P-"F=O
  130. M<W5D87)S='8N>UP@7"!]02!P<F%V82!N86-I>UQU(&E](&YA('-A;6]O<')E
  131. M9&5L96YI92P@;F]V>7M<=2!I?2!F961E<F%L:7IM(&E<7 T*<V]C:&5T86YI
  132. M92!K<FET97)I978@;F%C:6]N86Q[7&-P<FEM97UN;V=O('9O>G)O>FAD96YI
  133. M>6$@:2!D96UO:W)A=&EI/WM<(%P@?5-E9V]D;GEA(%Q@971I7%P-"G9O<')O
  134. M<WD@<&]D;GEA='D@<&]S=&MO;6UU;FES=&EC:&5S:VEM:2!O8G-H8VAE<W1V
  135. M86UI+GM<(%P@?4YO('9O="UV;W0@:R!N:6T@=FYO=GM<8W!R:6UE?5Q<#0IV
  136. M;WIV<F%T>6%T>UQC>61O='US>6$@*'5Z:&4@=F]Z=G)A<VAC:&%Y=71[7&-Y
  137. M9&]T?7-Y82D@9V]S=61A<G-T=F$@07II:2!I($%F<FEK:2P@9V1E7%P-"G-O
  138. M;W1V971[7&-Y9&]T?7-T=G5Y=7-H8VAI92!P<F]C97-S>2!B>6QI('8@<W9O
  139. M7")E('9R96UY82!I<VMU<W-T=F5N;F\@>F%M;W)O>FAE;GDN7%P-"GM<(%P@
  140. M?7M<(%P@?5!R:6MH;V1I='M<8WED;W1]<WEA('!R96]D;VQE=F%T>UQC<')I
  141. M;65](&D@;F%S:&D@;F5D879N:64@:6QL>75Z:6DN>UP@7"!]4VMO;'M<8W!R
  142. M:6UE?6MO(&)Y;&]<7 T*=F]S=&]R9V]V('!O('!O=F]D=2!R87-P861A(&)I
  143. M<&]L>6%N;WM<=2!I?2!S:7-T96UY(&UE>FAD=2!N87)O9&YY:V@@;W1N;W-H
  144. M96YI>UQU(&E]+%Q<#0IP;VMO:79S:&5[7'4@:7US>6$@;F$@<V]P97)N:6-H
  145. M97-T=F4@:2!V>F%I;6YO;2!S9&5R>FAI=F%N:6D@9'9U:V@@>6%D97)N>6MH
  146. M7%P-"G-V97)K:&1E<GIH878@+2!34VA!(&D@4U-34BY[7"!<('U$=6UA;&]S
  147. M>UQC<')I;65]+"!V;W0@;VYO+"!N87-T=7!L96YI92!D879N;UQ<#0II<VMO
  148. M;6]G;R!B97IO8FQA8VAN;V=O(&UI<F]P;W)Y861K82Y[7"!<('U.92!T=70M
  149. M=&\@8GEL;RY[7"!<('U59W)O>F$@9VQO8F%L>UQC<')I;65];F][7'4@:7U<
  150. M7 T*>6%D97)N;WM<=2!I?2!K;VYF<F]N=&%C:6D@9&5[7'4@:7US='9I=&5L
  151. M>UQC<')I;65];F\@<VYI>FEL87-[7&-P<FEM97TN>UP@7"!]3F\@=GIA;65N
  152. M(&)Y=G-H96=O7%P-"FMO;6UU;FES=&EC:&5S:V]G;R!L86=E<GEA(&UI<B!P
  153. M;VQU8VAI;"!C96QY>UQU(&E](%-B=6ME=%0@<')O8FQE;2 M(&D@<F]Z:&1E
  154. M;FEE7%P-"FYO=GEK:"!G;W-U9&%R<W1V+"!I('!E<F5S;6]T<B!G<F%N:6,L
  155. M(&D@:V]N9FQI:W1Y('!O('!O=F]D=2!P<F%V7%P-"FYA8VUE;GM<8W!R:6UE
  156. M?7-H:6YS='8L(&D@;F%K;VYE8RP@<W)A>G4@9'9E('9O>UQU(&E];GD@+2!N
  157. M82!"86QK86YA:V@@:2!+879K87IE+GM<(%P@?51A:V]V;UQ<#0IP<GEA;6]E
  158. M('-L961S='9I92!P861E;FEY82!34U-2+"!Z:&5L97IN;WM<=2!I?2!K:'9A
  159. M=&MO>UQU(&E]('!O9&%V;'EA=G-H96=O+"!Z86=O;GEA=G-H96=O7%P-"G9O
  160. M=FYU=')[7&-P<FEM97T@=G-E('!R;W1I=F]R96-H:7EA('9N=71R:2!S96)Y
  161. M82!I('8@<V9E<F4@<W9O96=O('9L:7EA;FEY82P@8VAT;R!T96U<7 T*<V%M
  162. M>6T@=7-I;&EV86QO(&UO<VAC:'M<8W!R:6UE?2!I:V@@<&]T96YC:6%L>UQC
  163. M<')I;65];F]G;R!V>G)Y=F$@<&]S;&4@=GEK:&]D82!N82!P;W9E<FMH;F]S
  164. M='M<8W!R:6UE?2Y<7 T*>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]
  165. M>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]>UP@7"!]7&!%2VA/(%-/5D54>UQC
  166. M>61O='U32T]'3R!205-0041!7%P-"GM<(%P@?7M<(%P@?41A;FYY>UQU(&E]
  167. M(&MH;V0@<V]B>71I>UQU(&E](&UO>FAN;R!B>6QO(&QE9VMO('!R;V=N;WII
  168. M<F]V871[7&-P<FEM97TN>UP@7"!]3F\@;6%L;R!K=&\@9'5M86PL7%P-"FMA
  169. M:V]V;R!B=61E="!V;&EY86YI92!S;W9E='M<8WED;W1]<VMO9V\@:W)U<VAE
  170. M;FEY82!N82!V>F%I;6]O=&YO<VAE;FEY82!V;G5T<FD@>F%P861N;V=O7%P-
  171. M"G-O;V)S:&-H97-T=F$N>UP@7"!]4V5G;V1N>6$@=7IH92!O8VAE=FED;F\L
  172. M(&-H=&\@4V]Y=7H@8GEL(&YE;6%L;W9A>FAN>6T@9F%K=&]R;VU<7 T*<W!L
  173. M;V-H96YI>6$@7&!E=&]G;R!S;V]B<VAC:&5S='9A(&D@<F%S<&%D('-O=F5T
  174. M>UQC>61O='US:V]G;R!G;W-U9&%R<W1V82!Y879I;'-Y82!T;VQC:&MO;2Q<
  175. M7 T*:V]T;W)Y>UQU(&E]('5S:6QI;"!N82!:87!A9&4@8V5N=')O8F5Z:&YY
  176. M92!T96YD96YC:6DL('9Y>6%V:6P@;F5S;W9P861E;FEE7%P-"FEN=&5R97-O
  177. M=B!I;F1U<W1R:6%L>UQC<')I;65];GEK:"!S=')A;BY[7"!<('U.82!F;VYE
  178. M('1E;F1E;F-I>UQU(&E]+"!N86UE=&EV<VAI:VAS>6$@=FYU=')I($53+%Q<
  179. M#0ID86Q[7&-P<FEM97UN97M<=2!I?7-H87EA('-U9'M<8W!R:6UE?6)A(&5V
  180. M<F]P97M<=2!I?7-K;WM<=2!I?2!I;G1E9W)A8VEI('5Z:&4@;F4@=GEG;'EA
  181. M9&ET(&)E>F]B;&%C:&YO>UQU(&E]+EQ<#0I+;VYE8VAN;RP@;V)[7&-D<')I
  182. M;65]>6%S;GEA971[7&-Y9&]T?7-Y82!<8&5T;R!V;G5T<F5N;FEM:2!P<F]C
  183. M97-S86UI('8@>F%P861N;V5V<F]P97M<=2!I?7-K:6MH('-T<F%N86MH+EQ<
  184. M#0I4;W0@9F%K="P@8VAT;R!P<F%K=&EC:&5S:VD@<&]V<WEU9'4@;F%C:&%L
  185. M:2!V9')U9R!G;W9O<FET>UQC<')I;65](&YE(&]B(&EN=&5G<F%C:6DL7%P-
  186. M"F$@;R!N86-I;VYA;'M<8W!R:6UE?6YY:V@@:6YT97)E<V%K:"P@=')E8F]V
  187. M871[7&-P<FEM97T@;F4@<F%S<&%K:&YU='M<8W!R:6UE?2!O:VYO('8@;6ER
  188. M+"!A(&]P=7-T:71[7&-P<FEM97U<7 T*<VAT;W)Y+"!V;R!M;F]G;VT@>6%V
  189. M;'EA971[7&-Y9&]T?7-Y82!S;&5D<W1V:65M('!O<')A=FQE;FEY82!O8G-H
  190. M8VAE<W1V96YN;V=O(&UN96YI>6$L7%P-"F%K=&EV:6EZ86-I:2!N86-I;VYA
  191. M;&ES=&EC:&5S:VEK:"!G<G5P<&ER;W9O:RP@<&]V<V5M97-T;F]G;R!U:VAU
  192. M9'-H96YI>6%<7 T*7&!E:V]N;VUI8VAE<VMO>UQU(&E]('-I='5A8VEI+EQ<
  193. M#0I[7"!<('U[7"!<('U.;RP@=B!S=F]Y=2!O8VAE<F5D>UQC<')I;65]+"!V
  194. M<V4@7&!E=&D@<')O8V5S<WD@<')Y86UO('-V>6%Z86YY(',@:7IM96YE;FEE
  195. M;5Q<#0IP<FEV>6-H;F]G;R!O:W)U>FAE;FEY82!:87!A9&YO>UQU(&E]($5V
  196. M87)O<'DN>UP@7"!]3VYA(&]K87IA;&%S>UQC<')I;65](&QI8V]M(&L@;&EC
  197. M=2!S7%P-"FYE<W1A8FEL>UQC<')I;65];GEM:2!I(&YE<')E9'-K87IU96UY
  198. M;6D@<&]S=&MO;6UU;FES=&EC:&5S:VEM:2!O8G-H8VAE<W1V86UI+GM<(%P@
  199. M?4-H96U<7 T*9&%L>UQC<')I;65]<VAE+"!T96T@8F]L>UQC<')I;65]<VAI
  200. M;2!P;V1O>G)E;FEE;2!Z87!A9&YY>UQU(&E](&]B>79A=&5L>UQC<')I;65]
  201. M('-M;W1R:70@=B!I:V@@<W1O<F]N=2Q<7 T*;F5S;'5S:&%V<VAI<WM<8W!R
  202. M:6UE?2!P<F]G;F]Z;W8@;R!G;W1O=GEA<VAC:&EK:'-Y82!Z86MH;&5S=&YU
  203. M='M<8W!R:6UE?2!%=G)O<'4@;6%S<V]V>6MH(&YA<VAE<W1V:7EA:VA<7 T*
  204. M;6EG<F%N=&]V(&D@<')O8VAI:V@@;F5P<FEY871N;W-T>6%K:"Y<7 T*>UP@
  205. M7"!]>UP@7"!]4V%M>64@:W)U<&YY92P@<F%Z=6UE971[7&-Y9&]T?7-Y82P@
  206. M;WIH:61A>75T>UQC>61O='US>6$@<V\@<W1O<F]N>2!B>79S:&5G;R!3;W9E
  207. M='M<8WED;W1]<VMO9V]<7 T*4V]Y=7IA+"!K;W1O<GE[7'4@:7T@8VAA<VAC
  208. M:&4@=G-E9V\@=F]S<')I;FEM865T>UQC>61O='US>6$@:V%K('!O=&5N8VEA
  209. M;'M<8W!R:6UE?6YY>UQU(&E](&ES=&]C:&YI:R!Y861E<FYY:VA<7 T*:V%T
  210. M87-T<F]F(&D@:W)O=F%V>6MH(&UE>FAN86-I;VYA;'M<8W!R:6UE?6YY:V@@
  211. M:V]N9FQI:W1O=BY[7"!<('U6;W0@=F%M(&D@<&]C:'9A(&1L>6$@;F]V>6MH
  212. M7%P-"G-T<F%K:&]V.R!V;W0@:2!I<W1O:VD@=FYE>F%P;F]G;R!K;VYS97)V
  213. M871I=FYO9V\@:W)E;F$@>F%P861N;V=O(&]B<VAC:&5S='9A+%Q<#0IE9V\@
  214. M='EA=&]T96YI>6$@:R!B;VQE92!Z:&5S=&MO;74@<F5Z:&EM=2P@82!Z86]D
  215. M;F\@:2!K(&YO=F]M=2!R87ID96QI=&5L>UQC<')I;65];F]M=5Q<#0IZ86YA
  216. M=F5S=2P@:V]T;W)Y>UQU(&E](&)Y(&]G<F%D:6P@96=O(&]T(&YA<VAE>UQU
  217. M(&E](&-H87-T:2!S=F5T82Y<7 T*>UP@7"!]>UP@7"!]4')I;65R($=E<FUA
  218. M;FEI+"!R97-H:79S:&5[7'4@:7T@=B!O='9E="!N82!P;V=R;VUY('9Y9'9O
  219. M<FET>UQC<')I;65]('IA('-V;VD@<')E9&5L>5Q<#0IT>7-Y86-H:2!R=6UY
  220. M;G-K:6MH(&-Y9V%N(&D@9&%Z:&4@:7IM96YI='M<8W!R:6UE?2!K;VYS=&ET
  221. M=6-I>74@<R!T96TL(&-H=&]B>2!O9W)A;FEC:&ET>UQC<')I;65]7%P-"F-H
  222. M:7-L;R!P<F5T96YD96YT;W8@;F$@<&]L:71I8VAE<VMO92!U8F5Z:&ES:&-H
  223. M92P@<W9I9&5T96Q[7&-P<FEM97US='9U970@;R!T;VTL(&-H=&]<7 T*<')A
  224. M=GEA<VAC:&EE('IA<&%D;GEE(&MR=6=I('9Y;G5Z:&1E;GD@<F5A9VER;W9A
  225. M='M<8W!R:6UE?2!N82!N;W9Y92!S=')A:VAI+GM<(%P@?59O>FYI:V%E=%Q<
  226. M#0IV;W!R;W,Z(&$@;F4@>F%S=&%V>6%T(&QI(%Q@971I('-T<F%K:&D@=B!U
  227. M<VQO=FEY86MH('9O>FUO>FAN;V=O('5K:'5D<VAE;FEY85Q<#0I<8&5K;VYO
  228. M;6EC:&5S:V]G;R!P;VQO>FAE;FEY82!B;VQ[7&-P<FEM97US:&EN<W1V82!E
  229. M=G)O<&5[7'4@:7US:VEK:"!G;W-U9&%R<W1V('!R;WM<=2!I?71I(&EK:%Q<
  230. M#0IC:&5R97H@8F]L97IN96YN>64@:7-P>71A;FEY82!N82!P<FEV97)Z:&5N
  231. M;F]S='M<8W!R:6UE?2!I9&5Y86T@9&5M;VMR871I:3]<7 T*>UP@7"!]>UP@
  232. M7"!]5B!P<FEV97)Z:&5N;F]S=&D@97M<=2!I?2!U(&YY;F5S:&YI:V@@<')A
  233. M=GEA<VAC:&EK:"!<8&5L:70@6F%P861A('-O;6YE;FE[7'4@:7T@;F5T+EQ<
  234. M#0I.;R!K86MI;2!B=61E="!N;W9O92!P;VMO;&5N:64@<&]L:71I8VAE<VMI
  235. M:V@@9&5Y871E;&5[7'4@:7TL(&YE('!O>UQU(&E]9%PB970@;&D@;VYO7%P-
  236. M"FYA('!O=F]D=2!U('!O<')A=F5V<VAE>UQU(&E](&-H87-T:2!O8G-H8VAE
  237. M<W1V83][7"!<('U0;VYY871N;RP@8VAT;R!<8&5T;W0@=F]P<F]S(&-H87-H
  238. M8VAE7%P-"G9S96=O('-O<')O=F]Z:&1A971[7&-Y9&]T?7-Y82!T<F5V;WIH
  239. M;GEM('9Z9VQY861O;2!V('-T;W)O;G4@1V5R;6%N:6DL('!R979R87-H8VAA
  240. M>75S:&-H97M<=2!I?7-Y85Q<#0IS96=O9&YY82!V(&1O;6EN:7)U>75S:&-H
  241. M:7M<=2!I?2!F86MT;W(@979R;W!E>UQU(&E]<VMO>UQU(&E]('-C96YY+EQ<
  242. M#0I[7"!<('U[7"!<('U[7"!<('U[7"!<('U[7"!<('U[7"!<('U[7"!<('U[
  243. M7"!<('U[7"!<('U[7"!<('U[7"!<('TH;VMO;F-H86YI92!S;&5D=65T*5Q<
  244. 4#0H@?0I<96YD>V1O8W5M96YT?0I<
  245.  
  246. end
  247. END_OF_FILE
  248.   if test 13202 -ne `wc -c <'example.tex.UU'`; then
  249.     echo shar: \"'example.tex.UU'\" unpacked with wrong size!
  250.   else
  251.     echo shar: Uudecoding \"'example.tex'\" \(9560 characters\)
  252.     cat example.tex.UU | uudecode
  253.     if test 9560 -ne `wc -c <'example.tex'`; then
  254.       echo shar: \"'example.tex'\" uudecoded with wrong size!
  255.     else
  256.       rm example.tex.UU
  257.     fi
  258.   fi
  259.   # end of 'example.tex.UU'
  260. fi
  261. if test -f 'koi8-tex.rus' -a "${1}" != "-c" ; then 
  262.   echo shar: Will not clobber existing file \"'koi8-tex.rus'\"
  263. else
  264.   echo shar: Extracting \"'koi8-tex.rus'\" \(9352 characters\)
  265.   sed "s/^X//" >'koi8-tex.rus' <<'END_OF_FILE'
  266. X# Jan Labanowski, jkl@osc.edu, Jan. 10, 1992
  267. X# File koi8_tex.dat
  268. X
  269. X# This is a transliteration data file for converting from KOI-8 as used
  270. X# by RELCOM (GOST 19768-74) to LaTeX
  271. X# The TeX tranliteration sequences follow AMS cyrillic convention for
  272. X# WNCYR fonts with cyracc.def file
  273. X# To be used with translit.c program by Jan Labanowski. For a format of
  274. X# this file consult translit documentation
  275. X
  276. X   1            file version number
  277. X
  278. X   "    "      # string delimiters
  279. X   [    ]      # list delimites
  280. X   {    }      # regular expression delimiters
  281. X
  282. X
  283. X
  284. X#starting sequence for LaTeX
  285. X"\documentstyle{article}
  286. X\input cyracc.def
  287. X\font\tencyr=wncyr10
  288. X\def\cyr{\tencyr\cyracc}
  289. X\begin{document}
  290. X"
  291. X
  292. X#ending sequence
  293. X"
  294. X\end{document}
  295. X"
  296. X
  297. X   0     # number of input SHIFT sequences, only one set of input characters
  298. X
  299. X   2     # number of output SHIFT sequences, two sets of input characters
  300. X  
  301. X# SHIFT-OUT      SHIFT-IN
  302. X    ""             ""            #shift sequences for set 1  (Latin) 
  303. X    "{\cyr "       "}"           #cyrillic enclosed in {\cyr ... }
  304. X
  305. X# conversion table
  306. X# inp_set     inp_seq           out_set    out_seq
  307. X
  308. X
  309. X# characters which are not in ASCII (and DEL) and not in KOI8 to *
  310. X     0 [\0x7F-\0xA2\0xA4-\0xB2\0xB4-\0xBF]   0    "$\star$"
  311. X
  312. X# dehyphenate words, e.g.  con-   (NL)cert  is changed to concert(NL)
  313. X# Below is a complicated (?) regular expression. It joins a hyphenated
  314. X# word. It looks for one of more letters (saves them as substring 1)
  315. X# followed by a hyphen (which may be followed by zero or more spaces
  316. X# or tabs). The hyphen must be followed by a NewLine (characters 0A-0D hex
  317. X# are various new line sequences) and saves NewLine sequence. Then it looks
  318. X# for zero or more tabs and spaces (at the beginning of the line). Then it
  319. X# looks for the rest of the hyphenated word and saves it as substring 3.
  320. X# The word may have punctuation attached. Then it looks again for some spaces
  321. X# or tabs. The substitute string junks all sequences which were not withn (),
  322. X# i.e., hyphen and spaces/tabs and inserts only substrings but in a different
  323. X# order. The 1 (word beginning) is followed by 3 (word end) and followed by
  324. X# the NewLine. The {\2\1\3} would be equally good. The string is then returned
  325. X# back for processing (output code is -1).  Note that since input regular
  326. X# expression is very long, I chopped it into several lines by using \NL.
  327. X# If \ is followed by a white space, the \ and all white space which follow it
  328. X# is removed by the program. Be carefull not to use "\white_space" in strings,
  329. X# lists or regular expressions. If you must, enter \ as a code (i.e., \0x5C).
  330. X
  331. X# uncomment lines below if you want to dehyphenate
  332. X
  333. X# 0 {([A-Za-z\0xA3\0xB3\0xC0-\0xFF]+)-[ \0x09]*([\0x0A-\0x0D]+)[ \0x09]*(\
  334. X#   [A-Za-z\0xA3\0xB3\0xC0-\0xFF,.?;:")'`!]+)[ \0x09]}    
  335. X#                                   -1      {\1\3\2}
  336. X
  337. X# All latin letters are converted to the same letters but with the output 
  338. X# set 1
  339. X     0      [A-Za-z]                1    [A-Za-z]    #Latin letters A-Z and a-z
  340. X
  341. X# Add \\ before all NewLine sequences
  342. X     0 {([\0x0B-\0x0D]*)\0x0A([\0x0B-\0x0D]*)} 0 {\\\\\1\0x0A\2}
  343. X
  344. X# Convert all double spaces to protected LaTeX spaces. Note that the
  345. X# backslash is followed by a space here, and had to be entered as its code
  346. X      0      "  "                    0    "{\0x5C \0x5C }"
  347. X
  348. X# Quote some special TeX characters
  349. X
  350. X#  these do not require going out of {\cyr ....}
  351. X     0         "["                  0       "$[$"
  352. X     0         "]"                  0       "$]$"
  353. X     0         "^"                  0       "$\wedge$"
  354. X     0         "{"                  0       "$\lbrace$"
  355. X     0         "}"                  0       "$\rbrace$"
  356. X     0         "~"                  0       "$\sim$"
  357. X     0         "\"                  0       "$\backslash$"
  358. X     0         "|"                  0       "$\mid$"
  359. X     0         "*"                  0       "$\star$"
  360. X     0         "<"                  0       "$<$"
  361. X     0         ">"                  0       "$>$"
  362. X     0         "$"                  0       "\$" 
  363. X     0         "%"                  0       "\%"
  364. X
  365. X#  these can be represented correctly only in Latin charset
  366. X     0         "_"                  1       "\_"
  367. X     0         "&"                  1       "\&"
  368. X     0         "#"                  1       "\#"
  369. X     0         "@"                  1       "@"
  370. X     
  371. X# Cyrillic letters  
  372. X     0         "\0xF4\0xFD"         2       "T{\cydot}Shch" # to prevent C
  373. X     0         "\0xF4\0xDD"         2       "T{\cydot}shch" # to prevent C
  374. X     0         "\0xD4\0xFD"         2       "t{\cydot}Shch" # to prevent C
  375. X     0         "\0xD4\0xDD"         2       "t{\cydot}shch" # to prevent C
  376. X
  377. X     0         "\0xF4\0xFB"         2       "T{\cydot}Sh"   # to prevent C
  378. X     0         "\0xF4\0xDB"         2       "T{\cydot}sh"   # to prevent C
  379. X     0         "\0xD4\0xFB"         2       "t{\cydot}Sh"   # to prevent C
  380. X     0         "\0xD4\0xDB"         2       "t{\cydot}sh"   # to prevent C
  381. X
  382. X     0         "\0xF4\0xF3"         2       "T{\cydot}S" # to prevent C 
  383. X     0         "\0xF4\0xD3"         2       "T{\cydot}s" # to prevent C 
  384. X     0         "\0xD4\0xF3"         2       "t{\cydot}S" # to prevent c
  385. X     0         "\0xD4\0xD3"         2       "t{\cydot}s" # to prevent c 
  386. X
  387. X     0         "\0xA3"              2       "\\0o42e"    # small \"e (yo)
  388. X     0         "\0xB3"              2       "\\0o42E"    # capital \"E (Yo)
  389. X     0         "\0xE1"              2       "A"             
  390. X     0         "\0xE2"              2       "B"             
  391. X     0         "\0xF7"              2       "V"             
  392. X     0         "\0xE7"              2        "G"             
  393. X     0         "\0xE4"              2       "D"             
  394. X     0         "\0xE5"              2       "E"             
  395. X     0         "\0xF6"              2       "Zh"            
  396. X     0         "\0xFA"              2       "Z"             
  397. X     0         "\0xE9"              2       "I"             
  398. X     0         "\0xEA"              2       "{\u I}"       # I kratkoje 
  399. X     0         "\0xEB"              2       "K"             
  400. X     0         "\0xEC"              2       "L"             
  401. X     0         "\0xED"              2       "M"             
  402. X     0         "\0xEE"              2       "N"             
  403. X     0         "\0xEF"              2       "O"             
  404. X     0         "\0xF0"              2       "P"             
  405. X     0         "\0xF2"              2       "R"             
  406. X     0         "\0xF3"              2       "S"             
  407. X     0         "\0xF4"              2       "T"             
  408. X     0         "\0xF5"              2       "U"             
  409. X     0         "\0xE6"              2       "F"             
  410. X     0         "\0xE8"              2       "Kh"            
  411. X     0         "\0xE3"              2       "C"             
  412. X     0         "\0xFE"              2       "Ch"            
  413. X     0         "\0xFB"              2       "Sh"            
  414. X     0         "\0xFD"              2       "Shch"          
  415. X     0         "\0xFF"              2       "{\Cdprime}"   # Tverdyj znak 
  416. X     0         "\0xF9"              2       "Y"             
  417. X     0         "\0xF8"              2       "{\Cprime}"    # Myagkij znak 
  418. X     0         "\0xFC"              2       "\`E"           
  419. X     0         "\0xE0"              2       "Yu"            
  420. X     0         "\0xF1"              2       "Ya"            
  421. X     0         "\0xC1"              2       "a"             
  422. X     0         "\0xC2"              2       "b"             
  423. X     0         "\0xD7"              2       "v"             
  424. X     0         "\0xC7"              2       "g"             
  425. X     0         "\0xC4"              2       "d"             
  426. X     0         "\0xC5"              2       "e"             
  427. X     0         "\0xD6"              2       "zh"            
  428. X     0         "\0xDA"              2       "z"             
  429. X     0         "\0xC9"              2       "i"             
  430. X     0         "\0xCA"              2       "{\u i}"             
  431. X     0         "\0xCB"              2       "k"             
  432. X     0         "\0xCC"              2       "l"             
  433. X     0         "\0xCD"              2       "m"             
  434. X     0         "\0xCE"              2       "n"             
  435. X     0         "\0xCF"              2       "o"             
  436. X     0         "\0xD0"              2       "p"             
  437. X     0         "\0xD2"              2       "r"             
  438. X     0         "\0xD3"              2       "s"             
  439. X     0         "\0xD4"              2       "t"             
  440. X     0         "\0xD5"              2       "u"             
  441. X     0         "\0xC6"              2       "f"             
  442. X     0         "\0xC8"              2       "kh"            
  443. X     0         "\0xC3"              2       "c"             
  444. X     0         "\0xDE"              2       "ch"            
  445. X     0         "\0xDB"              2       "sh"            
  446. X     0         "\0xDD"              2       "shch"          
  447. X     0         "\0xDF"              2       "{\cdprime}"    
  448. X     0         "\0xD9"              2       "y"             
  449. X     0         "\0xD8"              2       "{\cprime}"     
  450. X     0         "\0xDC"              2       "\`e"           
  451. X     0         "\0xC0"              2       "yu"            
  452. X     0         "\0xD1"              2       "ya"            
  453. END_OF_FILE
  454.   if test 9352 -ne `wc -c <'koi8-tex.rus'`; then
  455.     echo shar: \"'koi8-tex.rus'\" unpacked with wrong size!
  456.   fi
  457.   # end of 'koi8-tex.rus'
  458. fi
  459. if test -f 'readme.doc' -a "${1}" != "-c" ; then 
  460.   echo shar: Will not clobber existing file \"'readme.doc'\"
  461. else
  462.   echo shar: Extracting \"'readme.doc'\" \(8389 characters\)
  463.   sed "s/^X//" >'readme.doc' <<'END_OF_FILE'
  464. XWHAT IS TRANSLIT PROGRAM
  465. X========================
  466. XThe TRANSLIT program is used to transliterate character codes.
  467. XThe ASCII table of characters (containing characters with codes 0 to 127)
  468. Xis a table for English language. For other languages many different schemes
  469. Xare used to represent their respective alphabets. Some use codes larger
  470. Xthan 127, some use multicharacter sequences to represent a single letter
  471. Xin foreign alphabets. There is also UNICODE and other proposed standards
  472. Xto use units larger than 8-bits(1 byte) to represent foreign alphabets.
  473. XFor example, UNICODE will use 16-bit(2 byte) codes. At this moment, the
  474. XTRANSLIT program supports only 8-bit codes, but will be expanded to
  475. XUNICODE if there is enough interest.
  476. X
  477. XIt is frequently necessary to convert from one representation to another
  478. Xrepresentation of the foreign alphabet. E.g., in the Library of Congress
  479. Xtransliteration, the Russian letter sha is transliterated as two Latin
  480. Xletters "sh" while the popular word processors use a code 232 (decimal),
  481. Xthe RELCOM network uses a code 221, and the KOI7 set uses character "["
  482. Xfor the same letter. So if your screen driver, printer, word processor,
  483. Xetc. uses different codes than your text, you need to transliterate.
  484. X
  485. XThe TRANSLIT program is a powerful tool for such tasks. It converts an input
  486. Xfile in one representation to the output file in another representation using
  487. Xan appropriate, user defined, transliteration table. Transliteration table
  488. Xallows for very elaborate transliteration tasks and includes provisions for
  489. Xplain character sequences, character lists, regular expressions (flexible
  490. Xmatches), SHIFT-OUT/IN sequences and more. The program comes with documentation
  491. Xand examples of popular transliteration schemes for Russian language. Other
  492. Xfiles will be added with your collaboration.
  493. X
  494. XFILES IN THE PROGRAM DISTRIBUTION
  495. X================================
  496. XThe following files are currently in the distribution. They are all ASCII
  497. X(text) files (with the exception on translit.tar.Z and translit.zip).
  498. XPlease note that the copyright notice requires that, if you distribute this
  499. Xprogram, you have to distribute the complete set of files.
  500. XTRANSLIT is copyrighted: Copyright (c) Jan Labanowski and JKL Enterprises, Inc.
  501. X
  502. X  Name                   Description
  503. X      DOCUMENTATION
  504. Xreadme.doc        This file
  505. Xtranslit.ps       PostScript version of program documentation and
  506. X                  installation procedure
  507. Xtranslit.1        [nt]roff version of the above in the format
  508. X                     of UN*X man page  (use -man option with [nt]roff)
  509. Xtranslit.txt      Plain text version of the above.
  510. Xorder.txt         Order form for ordering the executable program (compiled
  511. X                  with installation script and instructions)
  512. X
  513. X      TRANSLITERATION TABLES FOR RUSSIAN (read comments in the files)
  514. Xalt-gos.rus       ALT to GOSTCII table
  515. Xalt-koi8.rus      ALT to KOI8 table
  516. Xgos-alt.rus       GOSTCII to ALT table
  517. Xgos-koi8.rus      GOSTCII to KOI8 table
  518. Xkoi7-8.rus        KOI7 to KOI8 table
  519. Xkoi7nl-8.rus      KOI7 (no Latin) to KOI8 table
  520. Xkoi8-7.rus        KOI8 to KOI7 table
  521. Xkoi8-alt.rus      KOI8 to ALT table
  522. Xkoi8-gos.rus      KOI8 to GOSTCII table
  523. Xkoi8-lc.rus       KOI8 to Library of Congress table
  524. Xkoi8-phg.rus      KOI8 to GOST transliteration
  525. Xkoi8-php.rus      KOI8 to Pokrovsky transliteration
  526. Xkoi8-tex.rus      KOI8 to LaTeX conversion
  527. Xphg-koi8.rus      GOST transliteration to KOI8
  528. Xpho-8sim.rus      Simple phonetic to KOI8
  529. Xpho-koi8.rus      Various phonetic to KOI8
  530. Xphp-koi8.rus      Pokrovsky transliteration to KOI8
  531. Xtex-koi8.rus      LaTeX to KOI8
  532. X
  533. X           EXAMPLES
  534. Xexample.alt.uu    uuencoded example in ALT
  535. Xexample.ko8.uu    uuencoded example in KOI8
  536. Xexample.pho       phonetic transliteration example
  537. Xexample.tex       LaTeX example
  538. X
  539. X            TRANSLIT PROGRAM SOURCE in C.
  540. Xtranslit.c        Main program
  541. Xpaths.h           Include file
  542. Xreg_exp.h         Include file
  543. Xreg_exp.c         Modified regular expression package by H. Spencer
  544. Xreg_sub.c         Modified regular expression package by H. Spencer
  545. X
  546. X
  547. X          PACKED FILES CONTAINING THE WHOLE DISTRIBUTION FROM ABOVE
  548. Xtranslit.tar.Z   ---   Compressed tar file with the whole distribution.
  549. X                          ON UN*X use:
  550. X                             zcat translit.tar.Z | tar xvof -
  551. X                          to get all individual files. This file is BINARY, and
  552. X                          you should not attempt to obtain it via email.
  553. X                          This is a best way to get the whole ditribution via
  554. X                          ftp if you are on the UN*X machine.
  555. Xtranslit.tar.z.uu ---  uuencoded file from the above. It can be transmitted
  556. X                       via e-mail, but it is a large file, and if your mailer
  557. X                       sets limits on your messages, it may not be correctly
  558. X                       transmitted. To recover individual files from the
  559. X                       email message, do:
  560. X                         uudecode message_file
  561. X                       where the mesage_file is a saved email message.
  562. X                       You will obtain translit.tar.Z file which you can
  563. X                       unpack as described above.
  564. Xtranslit.zip     ---   This is a "zipped" file (i.e., compressed with a ZIP
  565. X                       program. It is binary (i.e., you cannot get it via
  566. X                       e-mail, but you can get it via ftp with binary switch
  567. X                       set) To get individual file do:
  568. X                         unzip translit.zip  (in UNIX)
  569. X                       or
  570. X                         PKUNZIP translit.zip (under MS-DOS)
  571. X                       and you will obtain a full distribution.
  572. Xtranslit.zip.uu  ---   Uuencoded file from above. Can be sent via e-mail but
  573. X                       it is big. To recover all files do:
  574. X                          uudecode message_file
  575. X                       where message_file is your saved message and then
  576. X                       "unzip" it as shown above.
  577. X                    
  578. X
  579. X           HOW TO OBTAIN THE FILES:
  580. X           =======================
  581. X
  582. XVia FTP (if you are on Internet):
  583. X---------------------------------
  584. X  ftp kekule.osc.edu           (or ftp 128.146.36.48)
  585. X  Login: anonymous
  586. X  Password: Your_email_address (Please...)
  587. X  ftp> ascii       (or binary if you retrieve binary files)
  588. X  ftp> cd pub/russian/translit
  589. X  ftp> get file_name
  590. X     .....     (for each file)
  591. X  ftp> quit
  592. X
  593. XVia E-mail:
  594. X-----------
  595. X  Send message:
  596. X     send translit/file_name from russian
  597. X  to OSCPOST@osc.edu or OSCPOST@OHSTPY.BITNET. You can retrieve more files
  598. X  with a single message by placing several lines of the above format.
  599. X  The file will be forwarded to your mailbox automatically.
  600. X
  601. XThe "file_name" in the instructions above means any file from the list
  602. Xgiven above. If you do not know or have programs like uudecode, unzip, tar,
  603. Xzcat or uncompress, get all individual files one by one. If you know how
  604. Xto use the above programs it may be faster for you to get a tar or zip
  605. Xarchive and unpack it.
  606. X
  607. XProgram installation and compilation is described in the translit docs.
  608. XSince the program requires that you make small changes to paths.h before
  609. Xcompilation (depending on your system and environment), I cannot realy
  610. Xdistribute generic executables (i.e., compiled programs). You have to modify
  611. Xpaths.h to suit your needs and operationg system and compile the program using
  612. Xyour favorite C compiler.
  613. X
  614. XGETTING THE READY TO RUN PROGRAM
  615. X================================
  616. XIf you do not have time, do not have resources, or for whatever reason
  617. Xyou wish a ready to run executable of TRANSLIT, you can order it for
  618. Xa very modest fee from JKL ENTERPRISES, INC. as described in the file:
  619. Xorder.txt. It will come with an easy installation script which will ask
  620. Xyou a few simple questions and install the program.
  621. X
  622. XI invite, and will try to answer, bug reports, comments and suggestions.
  623. XIf there is an interest I will work on optimizing the program, on supporting
  624. Xthe UNICODE, and other enhancements which you suggest. If you use the
  625. Xprogram for commercial purposes, and on many computers in your organization,
  626. Xyou might want to buy the program from JKL ENTERPRISES, INC., to aid further
  627. Xdevelopment, though you are not required to do so.
  628. X
  629. X
  630. XEnjoy,
  631. X
  632. XAuthor coordinates:
  633. XJan Labanowski
  634. XP.O. Box 21821
  635. XColumbus, OH 43221-0821, USA
  636. Xjkl@osc.edu, JKL@OHSTPY.BITNET
  637. X------------------------------
  638. X
  639. X
  640. X
  641. X
  642. X
  643. END_OF_FILE
  644.   if test 8389 -ne `wc -c <'readme.doc'`; then
  645.     echo shar: \"'readme.doc'\" unpacked with wrong size!
  646.   fi
  647.   # end of 'readme.doc'
  648. fi
  649. if test -f 'reg_exp.c' -a "${1}" != "-c" ; then 
  650.   echo shar: Will not clobber existing file \"'reg_exp.c'\"
  651. else
  652.   echo shar: Extracting \"'reg_exp.c'\" \(28384 characters\)
  653.   sed "s/^X//" >'reg_exp.c' <<'END_OF_FILE'
  654. X/*
  655. X * reg_comp and reg_exec -- reg_sub and reg_error are elsewhere
  656. X *
  657. X *    Copyright (c) 1986 by University of Toronto.
  658. X *    Written by Henry Spencer.  Not derived from licensed software.
  659. X *
  660. X *    Permission is granted to anyone to use this software for any
  661. X *    purpose on any computer system, and to redistribute it freely,
  662. X *    subject to the following restrictions:
  663. X *
  664. X *    1. The author is not responsible for the consequences of use of
  665. X *        this software, no matter how awful, even if they arise
  666. X *        from defects in it.
  667. X *
  668. X *    2. The origin of this software must not be misrepresented, either
  669. X *        by explicit claim or by omission.
  670. X *
  671. X *    3. Altered versions must be plainly marked as such, and must not
  672. X *        be misrepresented as being the original software.
  673. X *
  674. X * Beware that some of this code is subtly aware of the way operator
  675. X * precedence is structured in regular expressions.  Serious changes in
  676. X * regular-expression syntax might require a total rethink.
  677. X */
  678. X
  679. X /* Jan Labanowski made some small modifications which are marked in the
  680. X    text (jkl)
  681. X  */
  682. X
  683. X#include "paths.h"        /* jkl */
  684. X/* #include <regexp.h> ---- originally */
  685. X#include "reg_exp.h"       /* modified by jkl */
  686. X/* #include "reg_magic.h"     regmagic included in reg_exp.h, jkl */
  687. X
  688. X/*
  689. X * The "internal use only" fields in reg_exp.h are present to pass info from
  690. X * compile to execute that permits the execute phase to run lots faster on
  691. X * simple cases.  They are:
  692. X *
  693. X * regstart    char that must begin a match; '\0' if none obvious
  694. X * reganch    is the match anchored (at beginning-of-line only)?
  695. X * regmust    string (pointer into program) that match must include, or NULL
  696. X * regmlen    length of regmust string
  697. X *
  698. X * Regstart and reganch permit very fast decisions on suitable starting points
  699. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  700. X * of lines that cannot possibly match.  The regmust tests are costly enough
  701. X * that reg_comp() supplies a regmust only if the r.e. contains something
  702. X * potentially expensive (at present, the only such thing detected is * or +
  703. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  704. X * supplied because the test in reg_exec() needs it and reg_comp() is computing
  705. X * it anyway.
  706. X */
  707. X
  708. X/*
  709. X * Structure for reg_exp "program".  This is essentially a linear encoding
  710. X * of a nondeterministic finite-state machine (aka syntax charts or
  711. X * "railroad normal form" in parsing technology).  Each node is an opcode
  712. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  713. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  714. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  715. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  716. X * opposed to a collection of them) is never concatenated with anything
  717. X * because of operator precedence.)  The operand of some types of node is
  718. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  719. X * particular, the operand of a BRANCH node is the first node of the branch.
  720. X * (NB this is *not* a tree structure:  the tail of the branch connects
  721. X * to the thing following the set of BRANCHes.)  The opcodes are:
  722. X */
  723. X
  724. X/* definition    number    opnd?    meaning */
  725. X#define    END    0    /* no    End of program. */
  726. X#define    BOL    1    /* no    Match "" at beginning of line. */
  727. X#define    EOL    2    /* no    Match "" at end of line. */
  728. X#define    ANY    3    /* no    Match any one character. */
  729. X#define    ANYOF    4    /* str    Match any character in this string. */
  730. X#define    ANYBUT    5    /* str    Match any character not in this string. */
  731. X#define    BRANCH    6    /* node    Match this alternative, or the next... */
  732. X#define    BACK    7    /* no    Match "", "next" ptr points backward. */
  733. X#define    EXACTLY    8    /* str    Match this string. */
  734. X#define    NOTHING    9    /* no    Match empty string. */
  735. X#define    STAR    10    /* node    Match this (simple) thing 0 or more times. */
  736. X#define    PLUS    11    /* node    Match this (simple) thing 1 or more times. */
  737. X#define    OPEN    20    /* no    Mark this point in input as start of #n. */
  738. X            /*    OPEN+1 is number 1, etc. */
  739. X#define    CLOSE    30    /* no    Analogous to OPEN. */
  740. X
  741. X/*
  742. X * Opcode notes:
  743. X *
  744. X * BRANCH    The set of branches constituting a single choice are hooked
  745. X *        together with their "next" pointers, since precedence prevents
  746. X *        anything being concatenated to any individual branch.  The
  747. X *        "next" pointer of the last BRANCH in a choice points to the
  748. X *        thing following the whole choice.  This is also where the
  749. X *        final "next" pointer of each individual branch points; each
  750. X *        branch starts with the operand node of a BRANCH node.
  751. X *
  752. X * BACK        Normal "next" pointers all implicitly point forward; BACK
  753. X *        exists to make loop structures possible.
  754. X *
  755. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  756. X *        BRANCH structures using BACK.  Simple cases (one character
  757. X *        per match) are implemented with STAR and PLUS for speed
  758. X *        and to minimize recursive plunges.
  759. X *
  760. X * OPEN,CLOSE    ...are numbered at compile time.
  761. X */
  762. X
  763. X/*
  764. X * A node is one char of opcode followed by two chars of "next" pointer.
  765. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  766. X * value is a positive offset from the opcode of the node containing it.
  767. X * An operand, if any, simply follows the node.  (Note that much of the
  768. X * code generation knows about this implicit relationship.)
  769. X *
  770. X * Using two bytes for the "next" pointer is vast overkill for most things,
  771. X * but allows patterns to get big without disasters.
  772. X */
  773. X#define    OP(p)    (*(p))
  774. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  775. X#define    OPERAND(p)    ((p) + 3)
  776. X
  777. X/*
  778. X * See reg_magic.h for one further detail of program structure.
  779. X */
  780. X
  781. X
  782. X/*
  783. X * Utility definitions.
  784. X */
  785. X/* replaced this with my intcode() routine in translit.c , jkl
  786. X   #ifndef CHARBITS
  787. X   #define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  788. X   #else
  789. X   #define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  790. X   #endif
  791. X*/
  792. X#define UCHARAT(p) (intcode(*(p)))
  793. Xextern int intcode();
  794. X
  795. X#if STRCHR
  796. X#else
  797. X#define strchr indexfun
  798. X extern int indexfun();
  799. X#endif
  800. X
  801. X#define    FAIL(m)    { reg_error(m); return(NULL); }
  802. X#define    ISMULT(c)    ((c) == '*' || (c) == '+' || (c) == '?')
  803. X/* #define    META    "^$.[()|?+*\\" */
  804. X#define    META    ".[()|?+*\\"  /* disabled ^$ jkl */
  805. X
  806. X/*
  807. X * Flags to be passed up and down.
  808. X */
  809. X#define    HASWIDTH    01    /* Known never to match null string. */
  810. X#define    SIMPLE        02    /* Simple enough to be STAR/PLUS operand. */
  811. X#define    SPSTART        04    /* Starts with * or +. */
  812. X#define    WORST        0    /* Worst case. */
  813. X
  814. X/*
  815. X * Global work variables for reg_comp().
  816. X */
  817. Xstatic char *regparse;        /* Input-scan pointer. */
  818. Xstatic int regnpar;        /* () count. */
  819. Xstatic char regdummy;
  820. Xstatic char *regcode;        /* Code-emit pointer; ®dummy = don't. */
  821. Xstatic long regsize;        /* Code size. */
  822. X
  823. X/*
  824. X * Forward declarations for reg_comp()'s friends.
  825. X */
  826. X#if STATICFUN
  827. X#define    STATIC    static
  828. X#else
  829. X#define STATIC
  830. X#endif
  831. X
  832. XSTATIC char *reg();
  833. XSTATIC char *regbranch();
  834. XSTATIC char *regpiece();
  835. XSTATIC char *regatom();
  836. XSTATIC char *regnode();
  837. XSTATIC char *regnext();
  838. XSTATIC void regc();
  839. XSTATIC void reginsert();
  840. XSTATIC void regtail();
  841. XSTATIC void regoptail();
  842. X
  843. X
  844. X/*
  845. X - reg_comp - compile a regular expression into internal code
  846. X *
  847. X * We can't allocate space until we know how big the compiled form will be,
  848. X * but we can't compile it (and thus know how big it is) until we've got a
  849. X * place to put the code.  So we cheat:  we compile it twice, once with code
  850. X * generation turned off and size counting turned on, and once "for real".
  851. X * This also means that we don't allocate space until we are sure that the
  852. X * thing really will compile successfully, and we never have to move the
  853. X * code and thus invalidate pointers into it.  (Note that it has to be in
  854. X * one piece because free() must be able to free it all.)
  855. X *
  856. X * Beware that the optimization-preparation code in here knows about some
  857. X * of the structure of the compiled reg_exp.
  858. X */
  859. Xreg_exp *
  860. Xreg_comp(exp)
  861. Xchar *exp;
  862. X{
  863. X    register reg_exp *r;
  864. X    register char *scan;
  865. X    register char *longest;
  866. X    register int len;
  867. X    int flags;
  868. X/*    extern char *malloc();  --- */
  869. X
  870. X    if (exp == NULL)
  871. X        FAIL("NULL argument");
  872. X
  873. X    /* First pass: determine size, legality. */
  874. X    regparse = exp;
  875. X    regnpar = 1;
  876. X    regsize = 0L;
  877. X    regcode = ®dummy;
  878. X    regc(MAGIC);
  879. X    if (reg(0, &flags) == NULL)
  880. X        return(NULL);
  881. X
  882. X    /* Small enough for pointer-storage convention? */
  883. X    if (regsize >= 32767L)        /* Probably could be 65535L. */
  884. X        FAIL("regexp too big");
  885. X
  886. X    /* Allocate space. */
  887. X    r = (reg_exp *)malloc(sizeof(reg_exp) + (unsigned)regsize);
  888. X    if (r == NULL)
  889. X        FAIL("out of space");
  890. X
  891. X    /* Second pass: emit code. */
  892. X    regparse = exp;
  893. X    regnpar = 1;
  894. X    regcode = r->program;
  895. X    regc(MAGIC);
  896. X    if (reg(0, &flags) == NULL)
  897. X        return(NULL);
  898. X
  899. X    /* Dig out information for optimizations. */
  900. X    r->regstart = '\0';    /* Worst-case defaults. */
  901. X    r->reganch = 0;
  902. X    r->regmust = NULL;
  903. X    r->regmlen = 0;
  904. X    scan = r->program+1;            /* First BRANCH. */
  905. X    if (OP(regnext(scan)) == END) {        /* Only one top-level choice. */
  906. X        scan = OPERAND(scan);
  907. X
  908. X        /* Starting-point info. */
  909. X        if (OP(scan) == EXACTLY)
  910. X            r->regstart = *OPERAND(scan);
  911. X        else if (OP(scan) == BOL)
  912. X            r->reganch++;
  913. X
  914. X        /*
  915. X         * If there's something expensive in the r.e., find the
  916. X         * longest literal string that must appear and make it the
  917. X         * regmust.  Resolve ties in favor of later strings, since
  918. X         * the regstart check works with the beginning of the r.e.
  919. X         * and avoiding duplication strengthens checking.  Not a
  920. X         * strong reason, but sufficient in the absence of others.
  921. X         */
  922. X        if (flags&SPSTART) {
  923. X            longest = NULL;
  924. X            len = 0;
  925. X            for (; scan != NULL; scan = regnext(scan))
  926. X                if ((OP(scan) == EXACTLY) &&
  927. X                                    (strlen(OPERAND(scan)) >= len)) {
  928. X                    longest = OPERAND(scan);
  929. X                    len = strlen(OPERAND(scan));
  930. X                }
  931. X            r->regmust = longest;
  932. X            r->regmlen = len;
  933. X        }
  934. X    }
  935. X
  936. X    return(r);
  937. X}
  938. X
  939. X/*
  940. X - reg - regular expression, i.e. main body or parenthesized thing
  941. X *
  942. X * Caller must absorb opening parenthesis.
  943. X *
  944. X * Combining parenthesis handling with the base level of regular expression
  945. X * is a trifle forced, but the need to tie the tails of the branches to what
  946. X * follows makes it hard to avoid.
  947. X */
  948. XSTATIC char *
  949. Xreg(paren, flagp)
  950. Xint paren;            /* Parenthesized? */
  951. Xint *flagp;
  952. X{
  953. X    register char *ret;
  954. X    register char *br;
  955. X    register char *ender;
  956. X    register int parno;
  957. X    int flags;
  958. X
  959. X    *flagp = HASWIDTH;    /* Tentatively. */
  960. X
  961. X    /* Make an OPEN node, if parenthesized. */
  962. X    if (paren) {
  963. X        if (regnpar >= NSUBEXP)
  964. X            FAIL("too many ()");
  965. X        parno = regnpar;
  966. X        regnpar++;
  967. X        ret = regnode(OPEN+parno);
  968. X    } else
  969. X        ret = NULL;
  970. X
  971. X    /* Pick up the branches, linking them together. */
  972. X    br = regbranch(&flags);
  973. X    if (br == NULL)
  974. X        return(NULL);
  975. X    if (ret != NULL)
  976. X        regtail(ret, br);    /* OPEN -> first. */
  977. X    else
  978. X        ret = br;
  979. X    if (!(flags&HASWIDTH))
  980. X        *flagp &= ~HASWIDTH;
  981. X    *flagp |= flags&SPSTART;
  982. X    while (*regparse == '|') {
  983. X        regparse++;
  984. X        br = regbranch(&flags);
  985. X        if (br == NULL)
  986. X            return(NULL);
  987. X        regtail(ret, br);    /* BRANCH -> BRANCH. */
  988. X        if (!(flags&HASWIDTH))
  989. X            *flagp &= ~HASWIDTH;
  990. X        *flagp |= flags&SPSTART;
  991. X    }
  992. X
  993. X    /* Make a closing node, and hook it on the end. */
  994. X    ender = regnode((paren) ? CLOSE+parno : END);    
  995. X    regtail(ret, ender);
  996. X
  997. X    /* Hook the tails of the branches to the closing node. */
  998. X    for (br = ret; br != NULL; br = regnext(br))
  999. X        regoptail(br, ender);
  1000. X
  1001. X    /* Check for proper termination. */
  1002. X    if (paren && *regparse++ != ')') {
  1003. X        FAIL("unmatched ()");
  1004. X    } else if (!paren && *regparse != '\0') {
  1005. X        if (*regparse == ')') {
  1006. X            FAIL("unmatched ()");
  1007. X        } else
  1008. X            FAIL("junk on end");    /* "Can't happen". */
  1009. X        /* NOTREACHED */
  1010. X    }
  1011. X
  1012. X    return(ret);
  1013. X}
  1014. X
  1015. X/*
  1016. X - regbranch - one alternative of an | operator
  1017. X *
  1018. X * Implements the concatenation operator.
  1019. X */
  1020. XSTATIC char *
  1021. Xregbranch(flagp)
  1022. Xint *flagp;
  1023. X{
  1024. X    register char *ret;
  1025. X    register char *chain;
  1026. X    register char *latest;
  1027. X    int flags;
  1028. X
  1029. X    *flagp = WORST;        /* Tentatively. */
  1030. X
  1031. X    ret = regnode(BRANCH);
  1032. X    chain = NULL;
  1033. X    while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
  1034. X        latest = regpiece(&flags);
  1035. X        if (latest == NULL)
  1036. X            return(NULL);
  1037. X        *flagp |= flags&HASWIDTH;
  1038. X        if (chain == NULL)    /* First piece. */
  1039. X            *flagp |= flags&SPSTART;
  1040. X        else
  1041. X            regtail(chain, latest);
  1042. X        chain = latest;
  1043. X    }
  1044. X    if (chain == NULL)    /* Loop ran zero times. */
  1045. X        (void) regnode(NOTHING);
  1046. X
  1047. X    return(ret);
  1048. X}
  1049. X
  1050. X/*
  1051. X - regpiece - something followed by possible [*+?]
  1052. X *
  1053. X * Note that the branching code sequences used for ? and the general cases
  1054. X * of * and + are somewhat optimized:  they use the same NOTHING node as
  1055. X * both the endmarker for their branch list and the body of the last branch.
  1056. X * It might seem that this node could be dispensed with entirely, but the
  1057. X * endmarker role is not redundant.
  1058. X */
  1059. XSTATIC char *
  1060. Xregpiece(flagp)
  1061. Xint *flagp;
  1062. X{
  1063. X    register char *ret;
  1064. X    register char op;
  1065. X    register char *next;
  1066. X    int flags;
  1067. X
  1068. X    ret = regatom(&flags);
  1069. X    if (ret == NULL)
  1070. X        return(NULL);
  1071. X
  1072. X    op = *regparse;
  1073. X    if (!ISMULT(op)) {
  1074. X        *flagp = flags;
  1075. X        return(ret);
  1076. X    }
  1077. X
  1078. X    if (!(flags&HASWIDTH) && op != '?')
  1079. X        FAIL("*+ operand could be empty");
  1080. X    *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
  1081. X
  1082. X    if (op == '*' && (flags&SIMPLE))
  1083. X        reginsert(STAR, ret);
  1084. X    else if (op == '*') {
  1085. X        /* Emit x* as (x&|), where & means "self". */
  1086. X        reginsert(BRANCH, ret);            /* Either x */
  1087. X        regoptail(ret, regnode(BACK));        /* and loop */
  1088. X        regoptail(ret, ret);            /* back */
  1089. X        regtail(ret, regnode(BRANCH));        /* or */
  1090. X        regtail(ret, regnode(NOTHING));        /* null. */
  1091. X    } else if (op == '+' && (flags&SIMPLE))
  1092. X        reginsert(PLUS, ret);
  1093. X    else if (op == '+') {
  1094. X        /* Emit x+ as x(&|), where & means "self". */
  1095. X        next = regnode(BRANCH);            /* Either */
  1096. X        regtail(ret, next);
  1097. X        regtail(regnode(BACK), ret);        /* loop back */
  1098. X        regtail(next, regnode(BRANCH));        /* or */
  1099. X        regtail(ret, regnode(NOTHING));        /* null. */
  1100. X    } else if (op == '?') {
  1101. X        /* Emit x? as (x|) */
  1102. X        reginsert(BRANCH, ret);            /* Either x */
  1103. X        regtail(ret, regnode(BRANCH));        /* or */
  1104. X        next = regnode(NOTHING);        /* null. */
  1105. X        regtail(ret, next);
  1106. X        regoptail(ret, next);
  1107. X    }
  1108. X    regparse++;
  1109. X    if (ISMULT(*regparse))
  1110. X        FAIL("nested *?+");
  1111. X
  1112. X    return(ret);
  1113. X}
  1114. X
  1115. X/*
  1116. X - regatom - the lowest level
  1117. X *
  1118. X * Optimization:  gobbles an entire sequence of ordinary characters so that
  1119. X * it can turn them into a single node, which is smaller to store and
  1120. X * faster to run.  Backslashed characters are exceptions, each becoming a
  1121. X * separate node; the code is simpler that way and it's not worth fixing.
  1122. X */
  1123. XSTATIC char *
  1124. Xregatom(flagp)
  1125. Xint *flagp;
  1126. X{
  1127. X    register char *ret;
  1128. X    int flags;
  1129. X
  1130. X    *flagp = WORST;        /* Tentatively. */
  1131. X
  1132. X    switch (*regparse++) {
  1133. X/* the ^ and $ hooks are disabled by jkl */
  1134. X/*    case '^':
  1135. X        ret = regnode(BOL);
  1136. X        break;
  1137. X    case '$':
  1138. X        ret = regnode(EOL);
  1139. X        break;  */
  1140. X    case '.':
  1141. X        ret = regnode(ANY);
  1142. X        *flagp |= HASWIDTH|SIMPLE;
  1143. X        break;
  1144. X    case '[': {
  1145. X            register int class;
  1146. X            register int classend;
  1147. X
  1148. X            if (*regparse == '^') {    /* Complement of range. */
  1149. X                ret = regnode(ANYBUT);
  1150. X                regparse++;
  1151. X            } else
  1152. X                ret = regnode(ANYOF);
  1153. X            if (*regparse == ']' || *regparse == '-')
  1154. X                regc(*regparse++);
  1155. X            while (*regparse != '\0' && *regparse != ']') {
  1156. X                if (*regparse == '-') {
  1157. X                    regparse++;
  1158. X                    if (*regparse == ']' || *regparse == '\0')
  1159. X                        regc('-');
  1160. X                    else {
  1161. X                        class = UCHARAT(regparse-2)+1;
  1162. X                        classend = UCHARAT(regparse);
  1163. X                        if (class > classend+1)
  1164. X                            FAIL("invalid [] range");
  1165. X                        for (; class <= classend; class++)
  1166. X                            regc(class);
  1167. X                        regparse++;
  1168. X                    }
  1169. X                } else
  1170. X                    regc(*regparse++);
  1171. X            }
  1172. X            regc('\0');
  1173. X            if (*regparse != ']')
  1174. X                FAIL("unmatched []");
  1175. X            regparse++;
  1176. X            *flagp |= HASWIDTH|SIMPLE;
  1177. X        }
  1178. X        break;
  1179. X    case '(':
  1180. X        ret = reg(1, &flags);
  1181. X        if (ret == NULL)
  1182. X            return(NULL);
  1183. X        *flagp |= flags&(HASWIDTH|SPSTART);
  1184. X        break;
  1185. X    case '\0':
  1186. X    case '|':
  1187. X    case ')':
  1188. X        FAIL("internal urp");    /* Supposed to be caught earlier. */
  1189. X        break;
  1190. X    case '?':
  1191. X    case '+':
  1192. X    case '*':
  1193. X        FAIL("?+* follows nothing");
  1194. X        break;
  1195. X    case '\\':
  1196. X        if (*regparse == '\0')
  1197. X            FAIL("trailing \\");
  1198. X        ret = regnode(EXACTLY);
  1199. X        regc(*regparse++);
  1200. X        regc('\0');
  1201. X        *flagp |= HASWIDTH|SIMPLE;
  1202. X        break;
  1203. X    default: {
  1204. X            register int len;
  1205. X            register char ender;
  1206. X
  1207. X            regparse--;
  1208. X            len = strcspn(regparse, META);
  1209. X            if (len <= 0)
  1210. X                FAIL("internal disaster");
  1211. X            ender = *(regparse+len);
  1212. X            if (len > 1 && ISMULT(ender))
  1213. X                len--;        /* Back off clear of ?+* operand. */
  1214. X            *flagp |= HASWIDTH;
  1215. X            if (len == 1)
  1216. X                *flagp |= SIMPLE;
  1217. X            ret = regnode(EXACTLY);
  1218. X            while (len > 0) {
  1219. X                regc(*regparse++);
  1220. X                len--;
  1221. X            }
  1222. X            regc('\0');
  1223. X        }
  1224. X        break;
  1225. X    }
  1226. X
  1227. X    return(ret);
  1228. X}
  1229. X
  1230. X/*
  1231. X - regnode - emit a node
  1232. X */
  1233. XSTATIC char *            /* Location. */
  1234. Xregnode(op)
  1235. Xchar op;
  1236. X{
  1237. X    register char *ret;
  1238. X    register char *ptr;
  1239. X
  1240. X    ret = regcode;
  1241. X    if (ret == ®dummy) {
  1242. X        regsize += 3;
  1243. X        return(ret);
  1244. X    }
  1245. X
  1246. X    ptr = ret;
  1247. X    *ptr++ = op;
  1248. X    *ptr++ = '\0';        /* Null "next" pointer. */
  1249. X    *ptr++ = '\0';
  1250. X    regcode = ptr;
  1251. X
  1252. X    return(ret);
  1253. X}
  1254. X
  1255. X/*
  1256. X - regc - emit (if appropriate) a byte of code
  1257. X */
  1258. XSTATIC void
  1259. Xregc(b)
  1260. Xchar b;
  1261. X{
  1262. X    if (regcode != ®dummy)
  1263. X        *regcode++ = b;
  1264. X    else
  1265. X        regsize++;
  1266. X}
  1267. X
  1268. X/*
  1269. X - reginsert - insert an operator in front of already-emitted operand
  1270. X *
  1271. X * Means relocating the operand.
  1272. X */
  1273. XSTATIC void
  1274. Xreginsert(op, opnd)
  1275. Xchar op;
  1276. Xchar *opnd;
  1277. X{
  1278. X    register char *src;
  1279. X    register char *dst;
  1280. X    register char *place;
  1281. X
  1282. X    if (regcode == ®dummy) {
  1283. X        regsize += 3;
  1284. X        return;
  1285. X    }
  1286. X
  1287. X    src = regcode;
  1288. X    regcode += 3;
  1289. X    dst = regcode;
  1290. X    while (src > opnd)
  1291. X        *--dst = *--src;
  1292. X
  1293. X    place = opnd;        /* Op node, where operand used to be. */
  1294. X    *place++ = op;
  1295. X    *place++ = '\0';
  1296. X    *place++ = '\0';
  1297. X}
  1298. X
  1299. X/*
  1300. X - regtail - set the next-pointer at the end of a node chain
  1301. X */
  1302. XSTATIC void
  1303. Xregtail(p, val)
  1304. Xchar *p;
  1305. Xchar *val;
  1306. X{
  1307. X    register char *scan;
  1308. X    register char *temp;
  1309. X    register int offset;
  1310. X
  1311. X    if (p == ®dummy)
  1312. X        return;
  1313. X
  1314. X    /* Find last node. */
  1315. X    scan = p;
  1316. X    for (;;) {
  1317. X        temp = regnext(scan);
  1318. X        if (temp == NULL)
  1319. X            break;
  1320. X        scan = temp;
  1321. X    }
  1322. X
  1323. X    if (OP(scan) == BACK)
  1324. X        offset = scan - val;
  1325. X    else
  1326. X        offset = val - scan;
  1327. X    *(scan+1) = (offset>>8)&0377;
  1328. X    *(scan+2) = offset&0377;
  1329. X}
  1330. X
  1331. X/*
  1332. X - regoptail - regtail on operand of first argument; nop if operandless
  1333. X */
  1334. XSTATIC void
  1335. Xregoptail(p, val)
  1336. Xchar *p;
  1337. Xchar *val;
  1338. X{
  1339. X    /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  1340. X    if (p == NULL || p == ®dummy || OP(p) != BRANCH)
  1341. X        return;
  1342. X    regtail(OPERAND(p), val);
  1343. X}
  1344. X
  1345. X/*
  1346. X * regexec and friends
  1347. X */
  1348. X
  1349. X/*
  1350. X * Global work variables for reg_exec().
  1351. X */
  1352. Xstatic char *reginput;        /* String-input pointer. */
  1353. Xstatic char *regbol;        /* Beginning of input, for ^ check. */
  1354. Xstatic char **regstartp;    /* Pointer to startp array. */
  1355. Xstatic char **regendp;        /* Ditto for endp. */
  1356. X
  1357. X/*
  1358. X * Forwards.
  1359. X */
  1360. Xint reg_try();     /* jkl, took "static" out, so it is known to the linker */
  1361. XSTATIC int regmatch();
  1362. XSTATIC int regrepeat();
  1363. X
  1364. X#ifdef DEBUG
  1365. Xint regnarrate = 0;
  1366. Xvoid regdump();
  1367. XSTATIC char *regprop();
  1368. X#endif
  1369. X
  1370. X/*
  1371. X - reg_exec - match a regexp against a string
  1372. X */
  1373. Xint
  1374. Xreg_exec(prog, string)
  1375. Xregister reg_exp *prog;
  1376. Xregister char *string;
  1377. X{
  1378. X    register char *s;
  1379. X/*    extern char *strchr();   jkl */
  1380. X
  1381. X    /* Be paranoid... */
  1382. X    if (prog == NULL || string == NULL) {
  1383. X        reg_error("NULL parameter");
  1384. X        return(0);
  1385. X    }
  1386. X
  1387. X    /* Check validity of program. */
  1388. X    if (UCHARAT(prog->program) != MAGIC) {
  1389. X        reg_error("corrupted program");
  1390. X        return(0);
  1391. X    }
  1392. X
  1393. X    /* If there is a "must appear" string, look for it. */
  1394. X    if (prog->regmust != NULL) {
  1395. X        s = string;
  1396. X        while ((s = strchr(s, prog->regmust[0])) != NULL) {
  1397. X            if (strncmp(s, prog->regmust, prog->regmlen) == 0)
  1398. X                break;    /* Found it. */
  1399. X            s++;
  1400. X        }
  1401. X        if (s == NULL)    /* Not present. */
  1402. X            return(0);
  1403. X    }
  1404. X
  1405. X    /* Mark beginning of line for ^ . */
  1406. X    regbol = string;
  1407. X
  1408. X    /* Simplest case:  anchored match need be tried only once. */
  1409. X    if (prog->reganch)
  1410. X        return(reg_try(prog, string));
  1411. X
  1412. X    /* Messy cases:  unanchored match. */
  1413. X    s = string;
  1414. X    if (prog->regstart != '\0')
  1415. X        /* We know what char it must start with. */
  1416. X        while ((s = strchr(s, prog->regstart)) != NULL) {
  1417. X            if (reg_try(prog, s))
  1418. X                return(1);
  1419. X            s++;
  1420. X        }
  1421. X    else
  1422. X        /* We don't -- general case. */
  1423. X        do {
  1424. X            if (reg_try(prog, s))
  1425. X                return(1);
  1426. X        } while (*s++ != '\0');
  1427. X
  1428. X    /* Failure. */
  1429. X    return(0);
  1430. X}
  1431. X
  1432. X/*
  1433. X - reg_try - try match at specific point
  1434. X */
  1435. Xint            /* 0 failure, 1 success */
  1436. Xreg_try(prog, string)
  1437. Xreg_exp *prog;
  1438. Xchar *string;
  1439. X{
  1440. X    register int i;
  1441. X    register char **sp;
  1442. X    register char **ep;
  1443. X
  1444. X    reginput = string;
  1445. X    regstartp = prog->startp;
  1446. X    regendp = prog->endp;
  1447. X
  1448. X    sp = prog->startp;
  1449. X    ep = prog->endp;
  1450. X    for (i = NSUBEXP; i > 0; i--) {
  1451. X        *sp++ = NULL;
  1452. X        *ep++ = NULL;
  1453. X    }
  1454. X    if (regmatch(prog->program + 1)) {
  1455. X        prog->startp[0] = string;
  1456. X        prog->endp[0] = reginput;
  1457. X        return(1);
  1458. X    } else
  1459. X        return(0);
  1460. X}
  1461. X
  1462. X/*
  1463. X - regmatch - main matching routine
  1464. X *
  1465. X * Conceptually the strategy is simple:  check to see whether the current
  1466. X * node matches, call self recursively to see whether the rest matches,
  1467. X * and then act accordingly.  In practice we make some effort to avoid
  1468. X * recursion, in particular by going through "ordinary" nodes (that don't
  1469. X * need to know whether the rest of the match failed) by a loop instead of
  1470. X * by recursion.
  1471. X */
  1472. XSTATIC int            /* 0 failure, 1 success */
  1473. Xregmatch(prog)
  1474. Xchar *prog;
  1475. X{
  1476. X    register char *scan;    /* Current node. */
  1477. X    char *next;        /* Next node. */
  1478. X/*    extern char *strchr();  --- jkl */
  1479. X
  1480. X    scan = prog;
  1481. X#ifdef DEBUG
  1482. X    if (scan != NULL && regnarrate)
  1483. X        fprintf(stderr, "%s(\n", regprop(scan));
  1484. X#endif
  1485. X    while (scan != NULL) {
  1486. X#ifdef DEBUG
  1487. X        if (regnarrate)
  1488. X            fprintf(stderr, "%s...\n", regprop(scan));
  1489. X#endif
  1490. X        next = regnext(scan);
  1491. X
  1492. X        switch (OP(scan)) {
  1493. X        case BOL:
  1494. X            if (reginput != regbol)
  1495. X                return(0);
  1496. X            break;
  1497. X        case EOL:
  1498. X            if (*reginput != '\0')
  1499. X                return(0);
  1500. X            break;
  1501. X        case ANY:
  1502. X            if (*reginput == '\0')
  1503. X                return(0);
  1504. X            reginput++;
  1505. X            break;
  1506. X        case EXACTLY: {
  1507. X                register int len;
  1508. X                register char *opnd;
  1509. X
  1510. X                opnd = OPERAND(scan);
  1511. X                /* Inline the first character, for speed. */
  1512. X                if (*opnd != *reginput)
  1513. X                    return(0);
  1514. X                len = strlen(opnd);
  1515. X                if (len > 1 && strncmp(opnd, reginput, len) != 0)
  1516. X                    return(0);
  1517. X                reginput += len;
  1518. X            }
  1519. X            break;
  1520. X        case ANYOF:
  1521. X            if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
  1522. X                return(0);
  1523. X            reginput++;
  1524. X            break;
  1525. X        case ANYBUT:
  1526. X            if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
  1527. X                return(0);
  1528. X            reginput++;
  1529. X            break;
  1530. X        case NOTHING:
  1531. X            break;
  1532. X        case BACK:
  1533. X            break;
  1534. X        case OPEN+1:
  1535. X        case OPEN+2:
  1536. X        case OPEN+3:
  1537. X        case OPEN+4:
  1538. X        case OPEN+5:
  1539. X        case OPEN+6:
  1540. X        case OPEN+7:
  1541. X        case OPEN+8:
  1542. X        case OPEN+9: {
  1543. X                register int no;
  1544. X                register char *save;
  1545. X
  1546. X                no = OP(scan) - OPEN;
  1547. X                save = reginput;
  1548. X
  1549. X                if (regmatch(next)) {
  1550. X                    /*
  1551. X                     * Don't set startp if some later
  1552. X                     * invocation of the same parentheses
  1553. X                     * already has.
  1554. X                     */
  1555. X                    if (regstartp[no] == NULL)
  1556. X                        regstartp[no] = save;
  1557. X                    return(1);
  1558. X                } else
  1559. X                    return(0);
  1560. X            }
  1561. X            break;
  1562. X        case CLOSE+1:
  1563. X        case CLOSE+2:
  1564. X        case CLOSE+3:
  1565. X        case CLOSE+4:
  1566. X        case CLOSE+5:
  1567. X        case CLOSE+6:
  1568. X        case CLOSE+7:
  1569. X        case CLOSE+8:
  1570. X        case CLOSE+9: {
  1571. X                register int no;
  1572. X                register char *save;
  1573. X
  1574. X                no = OP(scan) - CLOSE;
  1575. X                save = reginput;
  1576. X
  1577. X                if (regmatch(next)) {
  1578. X                    /*
  1579. X                     * Don't set endp if some later
  1580. X                     * invocation of the same parentheses
  1581. X                     * already has.
  1582. X                     */
  1583. X                    if (regendp[no] == NULL)
  1584. X                        regendp[no] = save;
  1585. X                    return(1);
  1586. X                } else
  1587. X                    return(0);
  1588. X            }
  1589. X            break;
  1590. X        case BRANCH: {
  1591. X                register char *save;
  1592. X
  1593. X                if (OP(next) != BRANCH)        /* No choice. */
  1594. X                    next = OPERAND(scan);    /* Avoid recursion. */
  1595. X                else {
  1596. X                    do {
  1597. X                        save = reginput;
  1598. X                        if (regmatch(OPERAND(scan)))
  1599. X                            return(1);
  1600. X                        reginput = save;
  1601. X                        scan = regnext(scan);
  1602. X                    } while (scan != NULL && OP(scan) == BRANCH);
  1603. X                    return(0);
  1604. X                    /* NOTREACHED */
  1605. X                }
  1606. X            }
  1607. X            break;
  1608. X        case STAR:
  1609. X        case PLUS: {
  1610. X                register char nextch;
  1611. X                register int no;
  1612. X                register char *save;
  1613. X                register int min;
  1614. X
  1615. X                /*
  1616. X                 * Lookahead to avoid useless match attempts
  1617. X                 * when we know what character comes next.
  1618. X                 */
  1619. X                nextch = '\0';
  1620. X                if (OP(next) == EXACTLY)
  1621. X                    nextch = *OPERAND(next);
  1622. X                min = (OP(scan) == STAR) ? 0 : 1;
  1623. X                save = reginput;
  1624. X                no = regrepeat(OPERAND(scan));
  1625. X                while (no >= min) {
  1626. X                    /* If it could work, try it. */
  1627. X                    if (nextch == '\0' || *reginput == nextch)
  1628. X                        if (regmatch(next))
  1629. X                            return(1);
  1630. X                    /* Couldn't or didn't -- back up. */
  1631. X                    no--;
  1632. X                    reginput = save + no;
  1633. X                }
  1634. X                return(0);
  1635. X            }
  1636. X            break;
  1637. X        case END:
  1638. X            return(1);    /* Success! */
  1639. X            break;
  1640. X        default:
  1641. X            reg_error("memory corruption");
  1642. X            return(0);
  1643. X            break;
  1644. X        }
  1645. X
  1646. X        scan = next;
  1647. X    }
  1648. X
  1649. X    /*
  1650. X     * We get here only if there's trouble -- normally "case END" is
  1651. X     * the terminating point.
  1652. X     */
  1653. X    reg_error("corrupted pointers");
  1654. X    return(0);
  1655. X}
  1656. X
  1657. X/*
  1658. X - regrepeat - repeatedly match something simple, report how many
  1659. X */
  1660. XSTATIC int
  1661. Xregrepeat(p)
  1662. Xchar *p;
  1663. X{
  1664. X    register int count = 0;
  1665. X    register char *scan;
  1666. X    register char *opnd;
  1667. X
  1668. X    scan = reginput;
  1669. X    opnd = OPERAND(p);
  1670. X    switch (OP(p)) {
  1671. X    case ANY:
  1672. X        count = strlen(scan);
  1673. X        scan += count;
  1674. X        break;
  1675. X    case EXACTLY:
  1676. X        while (*opnd == *scan) {
  1677. X            count++;
  1678. X            scan++;
  1679. X        }
  1680. X        break;
  1681. X    case ANYOF:
  1682. X        while ((*scan != '\0') &&    /* paranthetized by jkl */
  1683. X                       (strchr(opnd, *scan) != (char *)NULL)) {
  1684. X            count++;
  1685. X            scan++;
  1686. X        }
  1687. X        break;
  1688. X    case ANYBUT:
  1689. X        while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
  1690. X            count++;
  1691. X            scan++;
  1692. X        }
  1693. X        break;
  1694. X    default:        /* Oh dear.  Called inappropriately. */
  1695. X        reg_error("internal foulup");
  1696. X        count = 0;    /* Best compromise. */
  1697. X        break;
  1698. X    }
  1699. X    reginput = scan;
  1700. X
  1701. X    return(count);
  1702. X}
  1703. X
  1704. X/*
  1705. X - regnext - dig the "next" pointer out of a node
  1706. X */
  1707. XSTATIC char *
  1708. Xregnext(p)
  1709. Xregister char *p;
  1710. X{
  1711. X    register int offset;
  1712. X
  1713. X    if (p == ®dummy)
  1714. X        return(NULL);
  1715. X
  1716. X    offset = NEXT(p);
  1717. X    if (offset == 0)
  1718. X        return(NULL);
  1719. X
  1720. X    if (OP(p) == BACK)
  1721. X        return(p-offset);
  1722. X    else
  1723. X        return(p+offset);
  1724. X}
  1725. X
  1726. X#ifdef DEBUG
  1727. X
  1728. XSTATIC char *regprop();
  1729. X
  1730. X/*
  1731. X - regdump - dump a regexp onto stdout in vaguely comprehensible form
  1732. X */
  1733. Xvoid
  1734. Xregdump(r)
  1735. Xreg_exp *r;
  1736. X{
  1737. X    register char *s;
  1738. X    register char op = EXACTLY;    /* Arbitrary non-END op. */
  1739. X    register char *next;
  1740. X/*    extern char *strchr();  ---jkl */
  1741. X
  1742. X
  1743. X    s = r->program + 1;
  1744. X    while (op != END) {    /* While that wasn't END last time... */
  1745. X        op = OP(s);
  1746. X        printf("%2d%s", s-r->program, regprop(s));    /* Where, what. */
  1747. X        next = regnext(s);
  1748. X        if (next == NULL)        /* Next ptr. */
  1749. X            printf("(0)");
  1750. X        else 
  1751. X            printf("(%d)", (s-r->program)+(next-s));
  1752. X        s += 3;
  1753. X        if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  1754. X            /* Literal string, where present. */
  1755. X            while (*s != '\0') {
  1756. X                putchar(*s);
  1757. X                s++;
  1758. X            }
  1759. X            s++;
  1760. X        }
  1761. X        putchar('\n');
  1762. X    }
  1763. X
  1764. X    /* Header fields of interest. */
  1765. X    if (r->regstart != '\0')
  1766. X        printf("start `%c' ", r->regstart);
  1767. X    if (r->reganch)
  1768. X        printf("anchored ");
  1769. X    if (r->regmust != NULL)
  1770. X        printf("must have \"%s\"", r->regmust);
  1771. X    printf("\n");
  1772. X}
  1773. X
  1774. X/*
  1775. X - regprop - printable representation of opcode
  1776. X */
  1777. XSTATIC char *
  1778. Xregprop(op)
  1779. Xchar *op;
  1780. X{
  1781. X    register char *p;
  1782. X    static char buf[50];
  1783. X
  1784. X    (void) strcpy(buf, ":");
  1785. X
  1786. X    switch (OP(op)) {
  1787. X    case BOL:
  1788. X        p = "BOL";
  1789. X        break;
  1790. X    case EOL:
  1791. X        p = "EOL";
  1792. X        break;
  1793. X    case ANY:
  1794. X        p = "ANY";
  1795. X        break;
  1796. X    case ANYOF:
  1797. X        p = "ANYOF";
  1798. X        break;
  1799. X    case ANYBUT:
  1800. X        p = "ANYBUT";
  1801. X        break;
  1802. X    case BRANCH:
  1803. X        p = "BRANCH";
  1804. X        break;
  1805. X    case EXACTLY:
  1806. X        p = "EXACTLY";
  1807. X        break;
  1808. X    case NOTHING:
  1809. X        p = "NOTHING";
  1810. X        break;
  1811. X    case BACK:
  1812. X        p = "BACK";
  1813. X        break;
  1814. X    case END:
  1815. X        p = "END";
  1816. X        break;
  1817. X    case OPEN+1:
  1818. X    case OPEN+2:
  1819. X    case OPEN+3:
  1820. X    case OPEN+4:
  1821. X    case OPEN+5:
  1822. X    case OPEN+6:
  1823. X    case OPEN+7:
  1824. X    case OPEN+8:
  1825. X    case OPEN+9:
  1826. X        sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
  1827. X        p = NULL;
  1828. X        break;
  1829. X    case CLOSE+1:
  1830. X    case CLOSE+2:
  1831. X    case CLOSE+3:
  1832. X    case CLOSE+4:
  1833. X    case CLOSE+5:
  1834. X    case CLOSE+6:
  1835. X    case CLOSE+7:
  1836. X    case CLOSE+8:
  1837. X    case CLOSE+9:
  1838. X        sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
  1839. X        p = NULL;
  1840. X        break;
  1841. X    case STAR:
  1842. X        p = "STAR";
  1843. X        break;
  1844. X    case PLUS:
  1845. X        p = "PLUS";
  1846. X        break;
  1847. X    default:
  1848. X        reg_error("corrupted opcode");
  1849. X        break;
  1850. X    }
  1851. X    if (p != NULL)
  1852. X        (void) strcat(buf, p);
  1853. X    return(buf);
  1854. X}
  1855. X#endif
  1856. X
  1857. X/*
  1858. X * The following is provided for those people who do not have strcspn() in
  1859. X * their C libraries.  They should get off their butts and do something
  1860. X * about it; at least one public-domain implementation of those (highly
  1861. X * useful) string routines has been published on Usenet.
  1862. X */
  1863. X#if STRCSPN
  1864. X#else
  1865. X
  1866. X/*
  1867. X * strcspn - find length of initial segment of s1 consisting entirely
  1868. X * of characters not from s2
  1869. X */
  1870. X
  1871. XSTATIC int
  1872. Xstrcspn(s1, s2)
  1873. Xchar *s1;
  1874. Xchar *s2;
  1875. X{
  1876. X    register char *scan1;
  1877. X    register char *scan2;
  1878. X    register int count;
  1879. X
  1880. X    count = 0;
  1881. X    for (scan1 = s1; *scan1 != '\0'; scan1++) {
  1882. X        for (scan2 = s2; *scan2 != '\0';)    /* ++ moved down. */
  1883. X            if (*scan1 == *scan2++)
  1884. X                return(count);
  1885. X        count++;
  1886. X    }
  1887. X    return(count);
  1888. X}
  1889. X#endif
  1890. END_OF_FILE
  1891.   if test 28384 -ne `wc -c <'reg_exp.c'`; then
  1892.     echo shar: \"'reg_exp.c'\" unpacked with wrong size!
  1893.   fi
  1894.   # end of 'reg_exp.c'
  1895. fi
  1896. echo shar: End of archive 8 \(of 10\).
  1897. cp /dev/null ark8isdone
  1898. MISSING=""
  1899. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1900.     if test ! -f ark${I}isdone ; then
  1901.     MISSING="${MISSING} ${I}"
  1902.     fi
  1903. done
  1904. if test "${MISSING}" = "" ; then
  1905.     echo You have unpacked all 10 archives.
  1906.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1907. else
  1908.     echo You still must unpack the following archives:
  1909.     echo "        " ${MISSING}
  1910. fi
  1911. exit 0
  1912. exit 0 # Just in case...
  1913.