1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <bio.h> 4*219b2ee8SDavid du Colombier #include <stdarg.h> 5*219b2ee8SDavid du Colombier #include "dict.h" 6*219b2ee8SDavid du Colombier 7*219b2ee8SDavid du Colombier Dict dicts[] = { 8*219b2ee8SDavid du Colombier {"oed", "Oxford English Dictionary, 2nd Ed.", 9*219b2ee8SDavid du Colombier "/lib/dict/oed2", "/lib/dict/oed2index", 10*219b2ee8SDavid du Colombier oednextoff, oedprintentry, oedprintkey}, 11*219b2ee8SDavid du Colombier {"ahd", "American Heritage Dictionary, 2nd College Ed.", 12*219b2ee8SDavid du Colombier "/lib/ahd/DICT.DB", "/lib/ahd/index", 13*219b2ee8SDavid du Colombier ahdnextoff, ahdprintentry, ahdprintkey}, 14*219b2ee8SDavid du Colombier {"thesaurus", "Collins Thesaurus", 15*219b2ee8SDavid du Colombier "/lib/dict/thesaurus", "/lib/dict/thesindex", 16*219b2ee8SDavid du Colombier thesnextoff, thesprintentry, thesprintkey}, 17*219b2ee8SDavid du Colombier 18*219b2ee8SDavid du Colombier {"ce", "Gendai Chinese->English", 19*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic24.dat", 20*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/ceindex", 21*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 22*219b2ee8SDavid du Colombier {"ceh", "Gendai Chinese->English (Hanzi index)", 23*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic24.dat", 24*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/cehindex", 25*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 26*219b2ee8SDavid du Colombier {"ec", "Gendai English->Chinese", 27*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic24.dat", 28*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/ecindex", 29*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 30*219b2ee8SDavid du Colombier 31*219b2ee8SDavid du Colombier {"dae", "Gyldendal Danish->English", 32*219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/sandic30.dat", 33*219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/daeindex", 34*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 35*219b2ee8SDavid du Colombier {"eda", "Gyldendal English->Danish", 36*219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/sandic29.dat", 37*219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/edaindex", 38*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 39*219b2ee8SDavid du Colombier 40*219b2ee8SDavid du Colombier {"due", "Wolters-Noordhoff Dutch->English", 41*219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/sandic07.dat", 42*219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/deindex", 43*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 44*219b2ee8SDavid du Colombier {"edu", "Wolters-Noordhoff English->Dutch", 45*219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/sandic06.dat", 46*219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/edindex", 47*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 48*219b2ee8SDavid du Colombier 49*219b2ee8SDavid du Colombier {"fie", "WSOY Finnish->English", 50*219b2ee8SDavid du Colombier "/lib/dict/world/werndata/sandic32.dat", 51*219b2ee8SDavid du Colombier "/lib/dict/world/werndata/fieindex", 52*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 53*219b2ee8SDavid du Colombier {"efi", "WSOY English->Finnish", 54*219b2ee8SDavid du Colombier "/lib/dict/world/werndata/sandic31.dat", 55*219b2ee8SDavid du Colombier "/lib/dict/world/werndata/efiindex", 56*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 57*219b2ee8SDavid du Colombier 58*219b2ee8SDavid du Colombier {"fe", "Collins French->English", 59*219b2ee8SDavid du Colombier "/lib/dict/fe", "/lib/dict/feindex", 60*219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey}, 61*219b2ee8SDavid du Colombier {"ef", "Collins English->French", 62*219b2ee8SDavid du Colombier "/lib/dict/ef", "/lib/dict/efindex", 63*219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey}, 64*219b2ee8SDavid du Colombier 65*219b2ee8SDavid du Colombier {"ge", "Collins German->English", 66*219b2ee8SDavid du Colombier "/lib/dict/ge", "/lib/dict/geindex", 67*219b2ee8SDavid du Colombier pcollgnextoff, pcollgprintentry, pcollgprintkey}, 68*219b2ee8SDavid du Colombier {"eg", "Collins English->German", 69*219b2ee8SDavid du Colombier "/lib/dict/eg", "/lib/dict/egindex", 70*219b2ee8SDavid du Colombier pcollgnextoff, pcollgprintentry, pcollgprintkey}, 71*219b2ee8SDavid du Colombier 72*219b2ee8SDavid du Colombier {"ie", "Collins Italian->English", 73*219b2ee8SDavid du Colombier "/lib/dict/ie", "/lib/dict/ieindex", 74*219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey}, 75*219b2ee8SDavid du Colombier {"ei", "Collins English->Italian", 76*219b2ee8SDavid du Colombier "/lib/dict/ei", "/lib/dict/eiindex", 77*219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey}, 78*219b2ee8SDavid du Colombier 79*219b2ee8SDavid du Colombier {"je", "Sanshusha Japanese->English", 80*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic18.dat", 81*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/jeindex", 82*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 83*219b2ee8SDavid du Colombier {"jek", "Sanshusha Japanese->English (Kanji index)", 84*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic18.dat", 85*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/jekindex", 86*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 87*219b2ee8SDavid du Colombier {"ej", "Sanshusha English->Japanese", 88*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic18.dat", 89*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/ejindex", 90*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 91*219b2ee8SDavid du Colombier 92*219b2ee8SDavid du Colombier {"tjeg", "Sanshusha technical Japanese->English,German", 93*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat", 94*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tjegindex", 95*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 96*219b2ee8SDavid du Colombier {"tjegk", "Sanshusha technical Japanese->English,German (Kanji index)", 97*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat", 98*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tjegkindex", 99*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 100*219b2ee8SDavid du Colombier {"tegj", "Sanshusha technical English->German,Japanese", 101*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat", 102*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tegjindex", 103*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 104*219b2ee8SDavid du Colombier {"tgje", "Sanshusha technical German->Japanese,English", 105*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat", 106*219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tgjeindex", 107*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 108*219b2ee8SDavid du Colombier 109*219b2ee8SDavid du Colombier {"ne", "Kunnskapforlaget Norwegian->English", 110*219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/sandic28.dat", 111*219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/neindex", 112*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 113*219b2ee8SDavid du Colombier {"en", "Kunnskapforlaget English->Norwegian", 114*219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/sandic27.dat", 115*219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/enindex", 116*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 117*219b2ee8SDavid du Colombier 118*219b2ee8SDavid du Colombier {"re", "Leon Ungier Russian->English", 119*219b2ee8SDavid du Colombier "/lib/dict/re", "/lib/dict/reindex", 120*219b2ee8SDavid du Colombier simplenextoff, simpleprintentry, simpleprintkey}, 121*219b2ee8SDavid du Colombier {"er", "Leon Ungier English->Russian", 122*219b2ee8SDavid du Colombier "/lib/dict/re", "/lib/dict/erindex", 123*219b2ee8SDavid du Colombier simplenextoff, simpleprintentry, simpleprintkey}, 124*219b2ee8SDavid du Colombier 125*219b2ee8SDavid du Colombier {"se", "Collins Spanish->English", 126*219b2ee8SDavid du Colombier "/lib/dict/se", "/lib/dict/seindex", 127*219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey}, 128*219b2ee8SDavid du Colombier {"es", "Collins English->Spanish", 129*219b2ee8SDavid du Colombier "/lib/dict/es", "/lib/dict/esindex", 130*219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey}, 131*219b2ee8SDavid du Colombier 132*219b2ee8SDavid du Colombier {"swe", "Esselte Studium Swedish->English", 133*219b2ee8SDavid du Colombier "/lib/dict/world/essedata/sandic34.dat", 134*219b2ee8SDavid du Colombier "/lib/dict/world/essedata/sweindex", 135*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 136*219b2ee8SDavid du Colombier {"esw", "Esselte Studium English->Swedish", 137*219b2ee8SDavid du Colombier "/lib/dict/world/essedata/sandic33.dat", 138*219b2ee8SDavid du Colombier "/lib/dict/world/essedata/eswindex", 139*219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey}, 140*219b2ee8SDavid du Colombier 141*219b2ee8SDavid du Colombier {"movie", "Movies -- by title", 142*219b2ee8SDavid du Colombier "/lib/movie/data", "/lib/dict/movtindex", 143*219b2ee8SDavid du Colombier movienextoff, movieprintentry, movieprintkey}, 144*219b2ee8SDavid du Colombier {"moviea", "Movies -- by actor", 145*219b2ee8SDavid du Colombier "/lib/movie/data", "/lib/dict/movaindex", 146*219b2ee8SDavid du Colombier movienextoff, movieprintentry, movieprintkey}, 147*219b2ee8SDavid du Colombier {"movied", "Movies -- by director", 148*219b2ee8SDavid du Colombier "/lib/movie/data", "/lib/dict/movdindex", 149*219b2ee8SDavid du Colombier movienextoff, movieprintentry, movieprintkey}, 150*219b2ee8SDavid du Colombier 151*219b2ee8SDavid du Colombier {"slang", "English Slang", 152*219b2ee8SDavid du Colombier "/lib/dict/slang", "/lib/dict/slangindex", 153*219b2ee8SDavid du Colombier slangnextoff, slangprintentry, slangprintkey}, 154*219b2ee8SDavid du Colombier 155*219b2ee8SDavid du Colombier {"robert", "Robert Électronique", 156*219b2ee8SDavid du Colombier "/lib/dict/robert/_pointers", "/lib/dict/robert/_index", 157*219b2ee8SDavid du Colombier robertnextoff, robertindexentry, robertprintkey}, 158*219b2ee8SDavid du Colombier {"robertv", "Robert Électronique - formes des verbes", 159*219b2ee8SDavid du Colombier "/lib/dict/robert/flex.rob", "/lib/dict/robert/_flexindex", 160*219b2ee8SDavid du Colombier robertnextflex, robertflexentry, robertprintkey}, 161*219b2ee8SDavid du Colombier 162*219b2ee8SDavid du Colombier {0, 0, 0, 0, 0} 163*219b2ee8SDavid du Colombier }; 164*219b2ee8SDavid du Colombier 165*219b2ee8SDavid du Colombier typedef struct Lig Lig; 166*219b2ee8SDavid du Colombier struct Lig { 167*219b2ee8SDavid du Colombier Rune start; /* accent rune */ 168*219b2ee8SDavid du Colombier Rune *pairs; /* <char,accented version> pairs */ 169*219b2ee8SDavid du Colombier }; 170*219b2ee8SDavid du Colombier 171*219b2ee8SDavid du Colombier static Lig ligtab[Nligs] = { 172*219b2ee8SDavid du Colombier [LACU-LIGS] {L'´', L"AÁaáCĆcćEÉeégģIÍiíıíLĹlĺNŃnńOÓoóRŔrŕSŚsśUÚuúYÝyýZŹzź"}, 173*219b2ee8SDavid du Colombier [LGRV-LIGS] {L'ˋ', L"AÀaàEÈeèIÌiìıìOÒoòUÙuù"}, 174*219b2ee8SDavid du Colombier [LUML-LIGS] {L'¨', L"AÄaäEËeëIÏiïOÖoöUÜuüYŸyÿ"}, 175*219b2ee8SDavid du Colombier [LCED-LIGS] {L'¸', L"CÇcçGĢKĶkķLĻlļNŅnņRŖrŗSŞsşTŢtţ"}, 176*219b2ee8SDavid du Colombier [LTIL-LIGS] {L'˜', L"AÃaãIĨiĩıĩNÑnñOÕoõUŨuũ"}, 177*219b2ee8SDavid du Colombier [LBRV-LIGS] {L'˘', L"AĂaăEĔeĕGĞgğIĬiĭıĭOŎoŏUŬuŭ"}, 178*219b2ee8SDavid du Colombier [LRNG-LIGS] {L'˚', L"AÅaåUŮuů"}, 179*219b2ee8SDavid du Colombier [LDOT-LIGS] {L'˙', L"CĊcċEĖeėGĠgġIİLĿlŀZŻzż"}, 180*219b2ee8SDavid du Colombier [LDTB-LIGS] {L'.', L""}, 181*219b2ee8SDavid du Colombier [LFRN-LIGS] {L'⌢', L"AÂaâCĈcĉEÊeêGĜgĝHĤhĥIÎiîıîJĴjĵOÔoôSŜsŝUÛuûWŴwŵYŶyŷ"}, 182*219b2ee8SDavid du Colombier [LFRB-LIGS] {L'̯', L""}, 183*219b2ee8SDavid du Colombier [LOGO-LIGS] {L'˛', L"AĄaąEĘeęIĮiįıįUŲuų"}, 184*219b2ee8SDavid du Colombier [LMAC-LIGS] {L'¯', L"AĀaāEĒeēIĪiīıīOŌoōUŪuū"}, 185*219b2ee8SDavid du Colombier [LHCK-LIGS] {L'ˇ', L"CČcčDĎdďEĚeěLĽlľNŇnňRŘrřSŠsšTŤtťZŽzž"}, 186*219b2ee8SDavid du Colombier [LASP-LIGS] {L'ʽ', L""}, 187*219b2ee8SDavid du Colombier [LLEN-LIGS] {L'ʼ', L""}, 188*219b2ee8SDavid du Colombier [LBRB-LIGS] {L'̮', L""} 189*219b2ee8SDavid du Colombier }; 190*219b2ee8SDavid du Colombier 191*219b2ee8SDavid du Colombier Rune *multitab[Nmulti] = { 192*219b2ee8SDavid du Colombier [MAAS-MULTI] L"ʽα", 193*219b2ee8SDavid du Colombier [MALN-MULTI] L"ʼα", 194*219b2ee8SDavid du Colombier [MAND-MULTI] L"and", 195*219b2ee8SDavid du Colombier [MAOQ-MULTI] L"a/q", 196*219b2ee8SDavid du Colombier [MBRA-MULTI] L"<|", 197*219b2ee8SDavid du Colombier [MDD-MULTI] L"..", 198*219b2ee8SDavid du Colombier [MDDD-MULTI] L"...", 199*219b2ee8SDavid du Colombier [MEAS-MULTI] L"ʽε", 200*219b2ee8SDavid du Colombier [MELN-MULTI] L"ʼε", 201*219b2ee8SDavid du Colombier [MEMM-MULTI] L"——", 202*219b2ee8SDavid du Colombier [MHAS-MULTI] L"ʽη", 203*219b2ee8SDavid du Colombier [MHLN-MULTI] L"ʼη", 204*219b2ee8SDavid du Colombier [MIAS-MULTI] L"ʽι", 205*219b2ee8SDavid du Colombier [MILN-MULTI] L"ʼι", 206*219b2ee8SDavid du Colombier [MLCT-MULTI] L"ct", 207*219b2ee8SDavid du Colombier [MLFF-MULTI] L"ff", 208*219b2ee8SDavid du Colombier [MLFFI-MULTI] L"ffi", 209*219b2ee8SDavid du Colombier [MLFFL-MULTI] L"ffl", 210*219b2ee8SDavid du Colombier [MLFL-MULTI] L"fl", 211*219b2ee8SDavid du Colombier [MLFI-MULTI] L"fi", 212*219b2ee8SDavid du Colombier [MLLS-MULTI] L"ɫɫ", 213*219b2ee8SDavid du Colombier [MLST-MULTI] L"st", 214*219b2ee8SDavid du Colombier [MOAS-MULTI] L"ʽο", 215*219b2ee8SDavid du Colombier [MOLN-MULTI] L"ʼο", 216*219b2ee8SDavid du Colombier [MOR-MULTI] L"or", 217*219b2ee8SDavid du Colombier [MRAS-MULTI] L"ʽρ", 218*219b2ee8SDavid du Colombier [MRLN-MULTI] L"ʼρ", 219*219b2ee8SDavid du Colombier [MTT-MULTI] L"~~", 220*219b2ee8SDavid du Colombier [MUAS-MULTI] L"ʽυ", 221*219b2ee8SDavid du Colombier [MULN-MULTI] L"ʼυ", 222*219b2ee8SDavid du Colombier [MWAS-MULTI] L"ʽω", 223*219b2ee8SDavid du Colombier [MWLN-MULTI] L"ʼω", 224*219b2ee8SDavid du Colombier [MOE-MULTI] L"oe", 225*219b2ee8SDavid du Colombier [MES-MULTI] L" ", 226*219b2ee8SDavid du Colombier }; 227*219b2ee8SDavid du Colombier 228*219b2ee8SDavid du Colombier #define risupper(r) (L'A' <= (r) && (r) <= L'Z') 229*219b2ee8SDavid du Colombier #define rislatin1(r) (0xC0 <= (r) && (r) <= 0xFF) 230*219b2ee8SDavid du Colombier #define rtolower(r) ((r)-'A'+'a') 231*219b2ee8SDavid du Colombier 232*219b2ee8SDavid du Colombier static Rune latin_fold_tab[] = 233*219b2ee8SDavid du Colombier { 234*219b2ee8SDavid du Colombier /* Table to fold latin 1 characters to ASCII equivalents 235*219b2ee8SDavid du Colombier based at Rune value 0xc0 236*219b2ee8SDavid du Colombier 237*219b2ee8SDavid du Colombier À Á Â Ã Ä Å Æ Ç 238*219b2ee8SDavid du Colombier È É Ê Ë Ì Í Î Ï 239*219b2ee8SDavid du Colombier Ð Ñ Ò Ó Ô Õ Ö × 240*219b2ee8SDavid du Colombier Ø Ù Ú Û Ü Ý Þ ß 241*219b2ee8SDavid du Colombier à á â ã ä å æ ç 242*219b2ee8SDavid du Colombier è é ê ë ì í î ï 243*219b2ee8SDavid du Colombier ð ñ ò ó ô õ ö ÷ 244*219b2ee8SDavid du Colombier ø ù ú û ü ý þ ÿ 245*219b2ee8SDavid du Colombier */ 246*219b2ee8SDavid du Colombier 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 247*219b2ee8SDavid du Colombier 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 248*219b2ee8SDavid du Colombier 'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 , 249*219b2ee8SDavid du Colombier 'o', 'u', 'u', 'u', 'u', 'y', 0 , 0 , 250*219b2ee8SDavid du Colombier 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 251*219b2ee8SDavid du Colombier 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 252*219b2ee8SDavid du Colombier 'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 , 253*219b2ee8SDavid du Colombier 'o', 'u', 'u', 'u', 'u', 'y', 0 , 'y', 254*219b2ee8SDavid du Colombier }; 255*219b2ee8SDavid du Colombier 256*219b2ee8SDavid du Colombier static Rune *ttabstack[20]; 257*219b2ee8SDavid du Colombier static int ntt; 258*219b2ee8SDavid du Colombier 259*219b2ee8SDavid du Colombier /* 260*219b2ee8SDavid du Colombier * tab is an array of n Assoc's, sorted by key. 261*219b2ee8SDavid du Colombier * Look for key in tab, and return corresponding val 262*219b2ee8SDavid du Colombier * or -1 if not there 263*219b2ee8SDavid du Colombier */ 264*219b2ee8SDavid du Colombier long 265*219b2ee8SDavid du Colombier lookassoc(Assoc *tab, int n, char *key) 266*219b2ee8SDavid du Colombier { 267*219b2ee8SDavid du Colombier Assoc *q; 268*219b2ee8SDavid du Colombier long i, low, high; 269*219b2ee8SDavid du Colombier int r; 270*219b2ee8SDavid du Colombier 271*219b2ee8SDavid du Colombier for(low = -1, high = n; high > low+1; ){ 272*219b2ee8SDavid du Colombier i = (high+low)/2; 273*219b2ee8SDavid du Colombier q = &tab[i]; 274*219b2ee8SDavid du Colombier if((r=strcmp(key, q->key))<0) 275*219b2ee8SDavid du Colombier high = i; 276*219b2ee8SDavid du Colombier else if(r == 0) 277*219b2ee8SDavid du Colombier return q->val; 278*219b2ee8SDavid du Colombier else 279*219b2ee8SDavid du Colombier low=i; 280*219b2ee8SDavid du Colombier } 281*219b2ee8SDavid du Colombier return -1; 282*219b2ee8SDavid du Colombier } 283*219b2ee8SDavid du Colombier 284*219b2ee8SDavid du Colombier long 285*219b2ee8SDavid du Colombier looknassoc(Nassoc *tab, int n, long key) 286*219b2ee8SDavid du Colombier { 287*219b2ee8SDavid du Colombier Nassoc *q; 288*219b2ee8SDavid du Colombier long i, low, high; 289*219b2ee8SDavid du Colombier 290*219b2ee8SDavid du Colombier for(low = -1, high = n; high > low+1; ){ 291*219b2ee8SDavid du Colombier i = (high+low)/2; 292*219b2ee8SDavid du Colombier q = &tab[i]; 293*219b2ee8SDavid du Colombier if(key < q->key) 294*219b2ee8SDavid du Colombier high = i; 295*219b2ee8SDavid du Colombier else if(key == q->key) 296*219b2ee8SDavid du Colombier return q->val; 297*219b2ee8SDavid du Colombier else 298*219b2ee8SDavid du Colombier low=i; 299*219b2ee8SDavid du Colombier } 300*219b2ee8SDavid du Colombier return -1; 301*219b2ee8SDavid du Colombier } 302*219b2ee8SDavid du Colombier 303*219b2ee8SDavid du Colombier void 304*219b2ee8SDavid du Colombier err(char *fmt, ...) 305*219b2ee8SDavid du Colombier { 306*219b2ee8SDavid du Colombier char buf[1000]; 307*219b2ee8SDavid du Colombier va_list v; 308*219b2ee8SDavid du Colombier 309*219b2ee8SDavid du Colombier va_start(v, fmt); 310*219b2ee8SDavid du Colombier doprint(buf, &buf[1000], fmt, v); 311*219b2ee8SDavid du Colombier va_end(v); 312*219b2ee8SDavid du Colombier fprint(2, "%s: %s\n", argv0, buf); 313*219b2ee8SDavid du Colombier } 314*219b2ee8SDavid du Colombier 315*219b2ee8SDavid du Colombier /* 316*219b2ee8SDavid du Colombier * Write the rune r to bout, keeping track of line length 317*219b2ee8SDavid du Colombier * and breaking the lines (at blanks) when they get too long 318*219b2ee8SDavid du Colombier */ 319*219b2ee8SDavid du Colombier void 320*219b2ee8SDavid du Colombier outrune(long r) 321*219b2ee8SDavid du Colombier { 322*219b2ee8SDavid du Colombier if(outinhibit) 323*219b2ee8SDavid du Colombier return; 324*219b2ee8SDavid du Colombier if(++linelen > breaklen && r == L' ') { 325*219b2ee8SDavid du Colombier Bputc(bout, '\n'); 326*219b2ee8SDavid du Colombier linelen = 0; 327*219b2ee8SDavid du Colombier } else 328*219b2ee8SDavid du Colombier Bputrune(bout, r); 329*219b2ee8SDavid du Colombier } 330*219b2ee8SDavid du Colombier 331*219b2ee8SDavid du Colombier void 332*219b2ee8SDavid du Colombier outrunes(Rune *rp) 333*219b2ee8SDavid du Colombier { 334*219b2ee8SDavid du Colombier Rune r; 335*219b2ee8SDavid du Colombier 336*219b2ee8SDavid du Colombier while((r = *rp++) != 0) 337*219b2ee8SDavid du Colombier outrune(r); 338*219b2ee8SDavid du Colombier } 339*219b2ee8SDavid du Colombier 340*219b2ee8SDavid du Colombier /* like outrune, but when arg is know to be a char */ 341*219b2ee8SDavid du Colombier void 342*219b2ee8SDavid du Colombier outchar(int c) 343*219b2ee8SDavid du Colombier { 344*219b2ee8SDavid du Colombier if(outinhibit) 345*219b2ee8SDavid du Colombier return; 346*219b2ee8SDavid du Colombier if(++linelen > breaklen && c == ' ') { 347*219b2ee8SDavid du Colombier c ='\n'; 348*219b2ee8SDavid du Colombier linelen = 0; 349*219b2ee8SDavid du Colombier } 350*219b2ee8SDavid du Colombier BPUTC(bout, c); 351*219b2ee8SDavid du Colombier } 352*219b2ee8SDavid du Colombier 353*219b2ee8SDavid du Colombier void 354*219b2ee8SDavid du Colombier outchars(char *s) 355*219b2ee8SDavid du Colombier { 356*219b2ee8SDavid du Colombier char c; 357*219b2ee8SDavid du Colombier 358*219b2ee8SDavid du Colombier while((c = *s++) != 0) 359*219b2ee8SDavid du Colombier outchar(c); 360*219b2ee8SDavid du Colombier } 361*219b2ee8SDavid du Colombier 362*219b2ee8SDavid du Colombier void 363*219b2ee8SDavid du Colombier outprint(char *fmt, ...) 364*219b2ee8SDavid du Colombier { 365*219b2ee8SDavid du Colombier char buf[1000]; 366*219b2ee8SDavid du Colombier va_list v; 367*219b2ee8SDavid du Colombier 368*219b2ee8SDavid du Colombier va_start(v, fmt); 369*219b2ee8SDavid du Colombier doprint(buf, &buf[1000], fmt, v); 370*219b2ee8SDavid du Colombier va_end(v); 371*219b2ee8SDavid du Colombier outchars(buf); 372*219b2ee8SDavid du Colombier } 373*219b2ee8SDavid du Colombier 374*219b2ee8SDavid du Colombier void 375*219b2ee8SDavid du Colombier outpiece(char *b, char *e) 376*219b2ee8SDavid du Colombier { 377*219b2ee8SDavid du Colombier int c, lastc; 378*219b2ee8SDavid du Colombier 379*219b2ee8SDavid du Colombier lastc = 0; 380*219b2ee8SDavid du Colombier while(b < e) { 381*219b2ee8SDavid du Colombier c = *b++; 382*219b2ee8SDavid du Colombier if(c == '\n') 383*219b2ee8SDavid du Colombier c = ' '; 384*219b2ee8SDavid du Colombier if(!(c == ' ' && lastc == ' ')) 385*219b2ee8SDavid du Colombier outchar(c); 386*219b2ee8SDavid du Colombier lastc = c; 387*219b2ee8SDavid du Colombier } 388*219b2ee8SDavid du Colombier } 389*219b2ee8SDavid du Colombier 390*219b2ee8SDavid du Colombier /* 391*219b2ee8SDavid du Colombier * Go to new line if not already there; indent if ind != 0. 392*219b2ee8SDavid du Colombier * If ind > 1, leave a blank line too. 393*219b2ee8SDavid du Colombier * Slight hack: assume if current line is only one or two 394*219b2ee8SDavid du Colombier * characters long, then they were spaces. 395*219b2ee8SDavid du Colombier */ 396*219b2ee8SDavid du Colombier void 397*219b2ee8SDavid du Colombier outnl(int ind) 398*219b2ee8SDavid du Colombier { 399*219b2ee8SDavid du Colombier if(outinhibit) 400*219b2ee8SDavid du Colombier return; 401*219b2ee8SDavid du Colombier if(ind) { 402*219b2ee8SDavid du Colombier if(ind > 1) { 403*219b2ee8SDavid du Colombier if(linelen > 2) 404*219b2ee8SDavid du Colombier Bputc(bout, '\n'); 405*219b2ee8SDavid du Colombier Bprint(bout, "\n "); 406*219b2ee8SDavid du Colombier } else if(linelen == 0) 407*219b2ee8SDavid du Colombier Bprint(bout, " "); 408*219b2ee8SDavid du Colombier else if(linelen == 1) 409*219b2ee8SDavid du Colombier Bputc(bout, ' '); 410*219b2ee8SDavid du Colombier else if(linelen != 2) 411*219b2ee8SDavid du Colombier Bprint(bout, "\n "); 412*219b2ee8SDavid du Colombier linelen = 2; 413*219b2ee8SDavid du Colombier } else { 414*219b2ee8SDavid du Colombier if(linelen) { 415*219b2ee8SDavid du Colombier Bputc(bout, '\n'); 416*219b2ee8SDavid du Colombier linelen = 0; 417*219b2ee8SDavid du Colombier } 418*219b2ee8SDavid du Colombier } 419*219b2ee8SDavid du Colombier } 420*219b2ee8SDavid du Colombier 421*219b2ee8SDavid du Colombier /* 422*219b2ee8SDavid du Colombier * Fold the runes in null-terminated rp. 423*219b2ee8SDavid du Colombier * Use the sort(1) definition of folding (uppercase to lowercase, 424*219b2ee8SDavid du Colombier * latin1-accented characters to corresponding unaccented chars) 425*219b2ee8SDavid du Colombier */ 426*219b2ee8SDavid du Colombier void 427*219b2ee8SDavid du Colombier fold(Rune *rp) 428*219b2ee8SDavid du Colombier { 429*219b2ee8SDavid du Colombier Rune r; 430*219b2ee8SDavid du Colombier 431*219b2ee8SDavid du Colombier while((r = *rp) != 0) { 432*219b2ee8SDavid du Colombier if (rislatin1(r) && latin_fold_tab[r-0xc0]) 433*219b2ee8SDavid du Colombier r = latin_fold_tab[r-0xc0]; 434*219b2ee8SDavid du Colombier if(risupper(r)) 435*219b2ee8SDavid du Colombier r = rtolower(r); 436*219b2ee8SDavid du Colombier *rp++ = r; 437*219b2ee8SDavid du Colombier } 438*219b2ee8SDavid du Colombier } 439*219b2ee8SDavid du Colombier 440*219b2ee8SDavid du Colombier /* 441*219b2ee8SDavid du Colombier * Like fold, but put folded result into new 442*219b2ee8SDavid du Colombier * (assumed to have enough space). 443*219b2ee8SDavid du Colombier * old is a regular expression, but we know that 444*219b2ee8SDavid du Colombier * metacharacters aren't affected 445*219b2ee8SDavid du Colombier */ 446*219b2ee8SDavid du Colombier void 447*219b2ee8SDavid du Colombier foldre(char *new, char *old) 448*219b2ee8SDavid du Colombier { 449*219b2ee8SDavid du Colombier Rune r; 450*219b2ee8SDavid du Colombier 451*219b2ee8SDavid du Colombier while(*old) { 452*219b2ee8SDavid du Colombier old += chartorune(&r, old); 453*219b2ee8SDavid du Colombier if (rislatin1(r) && latin_fold_tab[r-0xc0]) 454*219b2ee8SDavid du Colombier r = latin_fold_tab[r-0xc0]; 455*219b2ee8SDavid du Colombier if(risupper(r)) 456*219b2ee8SDavid du Colombier r = rtolower(r); 457*219b2ee8SDavid du Colombier new += runetochar(new, &r); 458*219b2ee8SDavid du Colombier } 459*219b2ee8SDavid du Colombier *new = 0; 460*219b2ee8SDavid du Colombier } 461*219b2ee8SDavid du Colombier 462*219b2ee8SDavid du Colombier /* 463*219b2ee8SDavid du Colombier * acomp(s, t) returns: 464*219b2ee8SDavid du Colombier * -2 if s strictly precedes t 465*219b2ee8SDavid du Colombier * -1 if s is a prefix of t 466*219b2ee8SDavid du Colombier * 0 if s is the same as t 467*219b2ee8SDavid du Colombier * 1 if t is a prefix of s 468*219b2ee8SDavid du Colombier * 2 if t strictly precedes s 469*219b2ee8SDavid du Colombier */ 470*219b2ee8SDavid du Colombier 471*219b2ee8SDavid du Colombier int 472*219b2ee8SDavid du Colombier acomp(Rune *s, Rune *t) 473*219b2ee8SDavid du Colombier { 474*219b2ee8SDavid du Colombier int cs, ct; 475*219b2ee8SDavid du Colombier 476*219b2ee8SDavid du Colombier for(;;) { 477*219b2ee8SDavid du Colombier cs = *s; 478*219b2ee8SDavid du Colombier ct = *t; 479*219b2ee8SDavid du Colombier if(cs != ct) 480*219b2ee8SDavid du Colombier break; 481*219b2ee8SDavid du Colombier if(cs == 0) 482*219b2ee8SDavid du Colombier return 0; 483*219b2ee8SDavid du Colombier s++; 484*219b2ee8SDavid du Colombier t++; 485*219b2ee8SDavid du Colombier } 486*219b2ee8SDavid du Colombier if(cs == 0) 487*219b2ee8SDavid du Colombier return -1; 488*219b2ee8SDavid du Colombier if(ct == 0) 489*219b2ee8SDavid du Colombier return 1; 490*219b2ee8SDavid du Colombier if(cs < ct) 491*219b2ee8SDavid du Colombier return -2; 492*219b2ee8SDavid du Colombier return 2; 493*219b2ee8SDavid du Colombier } 494*219b2ee8SDavid du Colombier 495*219b2ee8SDavid du Colombier /* 496*219b2ee8SDavid du Colombier * Copy null terminated Runes from 'from' to 'to'. 497*219b2ee8SDavid du Colombier */ 498*219b2ee8SDavid du Colombier void 499*219b2ee8SDavid du Colombier runescpy(Rune *to, Rune *from) 500*219b2ee8SDavid du Colombier { 501*219b2ee8SDavid du Colombier while((*to++ = *from++) != 0) 502*219b2ee8SDavid du Colombier continue; 503*219b2ee8SDavid du Colombier } 504*219b2ee8SDavid du Colombier 505*219b2ee8SDavid du Colombier /* 506*219b2ee8SDavid du Colombier * Conversion of unsigned number to long, no overflow detection 507*219b2ee8SDavid du Colombier */ 508*219b2ee8SDavid du Colombier long 509*219b2ee8SDavid du Colombier runetol(Rune *r) 510*219b2ee8SDavid du Colombier { 511*219b2ee8SDavid du Colombier int c; 512*219b2ee8SDavid du Colombier long n; 513*219b2ee8SDavid du Colombier 514*219b2ee8SDavid du Colombier n = 0; 515*219b2ee8SDavid du Colombier for(;; r++){ 516*219b2ee8SDavid du Colombier c = *r; 517*219b2ee8SDavid du Colombier if(L'0'<=c && c<=L'9') 518*219b2ee8SDavid du Colombier c -= '0'; 519*219b2ee8SDavid du Colombier else 520*219b2ee8SDavid du Colombier break; 521*219b2ee8SDavid du Colombier n = n*10 + c; 522*219b2ee8SDavid du Colombier } 523*219b2ee8SDavid du Colombier return n; 524*219b2ee8SDavid du Colombier } 525*219b2ee8SDavid du Colombier 526*219b2ee8SDavid du Colombier /* 527*219b2ee8SDavid du Colombier * See if there is a rune corresponding to the accented 528*219b2ee8SDavid du Colombier * version of r with accent acc (acc in [LIGS..LIGE-1]), 529*219b2ee8SDavid du Colombier * and return it if so, else return NONE. 530*219b2ee8SDavid du Colombier */ 531*219b2ee8SDavid du Colombier Rune 532*219b2ee8SDavid du Colombier liglookup(Rune acc, Rune r) 533*219b2ee8SDavid du Colombier { 534*219b2ee8SDavid du Colombier Rune *p; 535*219b2ee8SDavid du Colombier 536*219b2ee8SDavid du Colombier if(acc < LIGS || acc >= LIGE) 537*219b2ee8SDavid du Colombier return NONE; 538*219b2ee8SDavid du Colombier for(p = ligtab[acc-LIGS].pairs; *p; p += 2) 539*219b2ee8SDavid du Colombier if(*p == r) 540*219b2ee8SDavid du Colombier return *(p+1); 541*219b2ee8SDavid du Colombier return NONE; 542*219b2ee8SDavid du Colombier } 543*219b2ee8SDavid du Colombier 544*219b2ee8SDavid du Colombier /* 545*219b2ee8SDavid du Colombier * Maintain a translation table stack (a translation table 546*219b2ee8SDavid du Colombier * is an array of Runes indexed by bytes or 7-bit bytes). 547*219b2ee8SDavid du Colombier * If starting is true, push the curtab onto the stack 548*219b2ee8SDavid du Colombier * and return newtab; else pop the top of the stack and 549*219b2ee8SDavid du Colombier * return it. 550*219b2ee8SDavid du Colombier * If curtab is 0, initialize the stack and return. 551*219b2ee8SDavid du Colombier */ 552*219b2ee8SDavid du Colombier Rune * 553*219b2ee8SDavid du Colombier changett(Rune *curtab, Rune *newtab, int starting) 554*219b2ee8SDavid du Colombier { 555*219b2ee8SDavid du Colombier if(curtab == 0) { 556*219b2ee8SDavid du Colombier ntt = 0; 557*219b2ee8SDavid du Colombier return 0; 558*219b2ee8SDavid du Colombier } 559*219b2ee8SDavid du Colombier if(starting) { 560*219b2ee8SDavid du Colombier if(ntt >= asize(ttabstack)) { 561*219b2ee8SDavid du Colombier if(debug) 562*219b2ee8SDavid du Colombier err("translation stack overflow"); 563*219b2ee8SDavid du Colombier return curtab; 564*219b2ee8SDavid du Colombier } 565*219b2ee8SDavid du Colombier ttabstack[ntt++] = curtab; 566*219b2ee8SDavid du Colombier return newtab; 567*219b2ee8SDavid du Colombier } else { 568*219b2ee8SDavid du Colombier if(ntt == 0) { 569*219b2ee8SDavid du Colombier if(debug) 570*219b2ee8SDavid du Colombier err("translation stack underflow"); 571*219b2ee8SDavid du Colombier return curtab; 572*219b2ee8SDavid du Colombier } 573*219b2ee8SDavid du Colombier return ttabstack[--ntt]; 574*219b2ee8SDavid du Colombier } 575*219b2ee8SDavid du Colombier } 576