xref: /plan9/sys/src/cmd/dict/utils.c (revision eaba85aa6b158bdf68fdb77f770e3ba0899a8b5e)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include "dict.h"
5219b2ee8SDavid du Colombier 
6219b2ee8SDavid du Colombier Dict dicts[] = {
7219b2ee8SDavid du Colombier 	{"oed",		"Oxford English Dictionary, 2nd Ed.",
8219b2ee8SDavid du Colombier 	 "/lib/dict/oed2",	"/lib/dict/oed2index",
9219b2ee8SDavid du Colombier 	 oednextoff,	oedprintentry,		oedprintkey},
10219b2ee8SDavid du Colombier 	{"ahd",		"American Heritage Dictionary, 2nd College Ed.",
11219b2ee8SDavid du Colombier 	 "/lib/ahd/DICT.DB",	"/lib/ahd/index",
12219b2ee8SDavid du Colombier 	 ahdnextoff,	ahdprintentry,		ahdprintkey},
13705edaf8SDavid du Colombier 	{"pgw",		"Project Gutenberg Webster Dictionary",
14705edaf8SDavid du Colombier 	 "/lib/dict/pgw",	"/lib/dict/pgwindex",
15705edaf8SDavid du Colombier 	 pgwnextoff,	pgwprintentry,		pgwprintkey},
16219b2ee8SDavid du Colombier 	{"thesaurus",	"Collins Thesaurus",
17219b2ee8SDavid du Colombier 	 "/lib/dict/thesaurus",	"/lib/dict/thesindex",
18219b2ee8SDavid du Colombier 	 thesnextoff,	thesprintentry,	thesprintkey},
19119a69faSDavid du Colombier 	{"roget",		"Project Gutenberg Roget's Thesaurus",
20119a69faSDavid du Colombier 	 "/lib/dict/roget", "/lib/dict/rogetindex",
21119a69faSDavid du Colombier 	 rogetnextoff,	rogetprintentry,	rogetprintkey},
22219b2ee8SDavid du Colombier 
23219b2ee8SDavid du Colombier 	{"ce",		"Gendai Chinese->English",
24219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic24.dat",
25219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/ceindex",
26219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
27219b2ee8SDavid du Colombier 	{"ceh",		"Gendai Chinese->English (Hanzi index)",
28219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic24.dat",
29219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/cehindex",
30219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
31219b2ee8SDavid du Colombier 	{"ec",		"Gendai English->Chinese",
32219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic24.dat",
33219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/ecindex",
34219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier 	{"dae",		"Gyldendal Danish->English",
37219b2ee8SDavid du Colombier 	 "/lib/dict/world/gylddata/sandic30.dat",
38219b2ee8SDavid du Colombier 	 "/lib/dict/world/gylddata/daeindex",
39219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
40219b2ee8SDavid du Colombier 	{"eda",		"Gyldendal English->Danish",
41219b2ee8SDavid du Colombier 	 "/lib/dict/world/gylddata/sandic29.dat",
42219b2ee8SDavid du Colombier 	 "/lib/dict/world/gylddata/edaindex",
43219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
44219b2ee8SDavid du Colombier 
45219b2ee8SDavid du Colombier 	{"due",		"Wolters-Noordhoff Dutch->English",
46219b2ee8SDavid du Colombier 	 "/lib/dict/world/woltdata/sandic07.dat",
47219b2ee8SDavid du Colombier 	 "/lib/dict/world/woltdata/deindex",
48219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
49219b2ee8SDavid du Colombier 	{"edu",		"Wolters-Noordhoff English->Dutch",
50219b2ee8SDavid du Colombier 	 "/lib/dict/world/woltdata/sandic06.dat",
51219b2ee8SDavid du Colombier 	 "/lib/dict/world/woltdata/edindex",
52219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
53219b2ee8SDavid du Colombier 
54219b2ee8SDavid du Colombier 	{"fie",		"WSOY Finnish->English",
55219b2ee8SDavid du Colombier 	 "/lib/dict/world/werndata/sandic32.dat",
56219b2ee8SDavid du Colombier 	 "/lib/dict/world/werndata/fieindex",
57219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
58219b2ee8SDavid du Colombier 	{"efi",		"WSOY English->Finnish",
59219b2ee8SDavid du Colombier 	 "/lib/dict/world/werndata/sandic31.dat",
60219b2ee8SDavid du Colombier 	 "/lib/dict/world/werndata/efiindex",
61219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
62219b2ee8SDavid du Colombier 
63219b2ee8SDavid du Colombier 	{"fe",		"Collins French->English",
64219b2ee8SDavid du Colombier 	 "/lib/dict/fe",	"/lib/dict/feindex",
65219b2ee8SDavid du Colombier 	 pcollnextoff,	pcollprintentry,	pcollprintkey},
66219b2ee8SDavid du Colombier 	{"ef",		"Collins English->French",
67219b2ee8SDavid du Colombier 	 "/lib/dict/ef",	"/lib/dict/efindex",
68219b2ee8SDavid du Colombier 	 pcollnextoff,	pcollprintentry,	pcollprintkey},
69219b2ee8SDavid du Colombier 
70219b2ee8SDavid du Colombier 	{"ge",		"Collins German->English",
71219b2ee8SDavid du Colombier 	 "/lib/dict/ge",	"/lib/dict/geindex",
72219b2ee8SDavid du Colombier 	 pcollgnextoff,	pcollgprintentry,	pcollgprintkey},
73219b2ee8SDavid du Colombier 	{"eg",		"Collins English->German",
74219b2ee8SDavid du Colombier 	 "/lib/dict/eg",	"/lib/dict/egindex",
75219b2ee8SDavid du Colombier 	 pcollgnextoff,	pcollgprintentry,	pcollgprintkey},
76219b2ee8SDavid du Colombier 
77219b2ee8SDavid du Colombier 	{"ie",		"Collins Italian->English",
78219b2ee8SDavid du Colombier 	 "/lib/dict/ie",	"/lib/dict/ieindex",
79219b2ee8SDavid du Colombier 	 pcollnextoff,	pcollprintentry,	pcollprintkey},
80219b2ee8SDavid du Colombier 	{"ei",		"Collins English->Italian",
81219b2ee8SDavid du Colombier 	 "/lib/dict/ei",	"/lib/dict/eiindex",
82219b2ee8SDavid du Colombier 	 pcollnextoff,	pcollprintentry,	pcollprintkey},
83219b2ee8SDavid du Colombier 
84219b2ee8SDavid du Colombier 	{"je",		"Sanshusha Japanese->English",
85219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic18.dat",
86219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/jeindex",
87219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
88219b2ee8SDavid du Colombier 	{"jek",		"Sanshusha Japanese->English (Kanji index)",
89219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic18.dat",
90219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/jekindex",
91219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
92219b2ee8SDavid du Colombier 	{"ej",		"Sanshusha English->Japanese",
93219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic18.dat",
94219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/ejindex",
95219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
96219b2ee8SDavid du Colombier 
97219b2ee8SDavid du Colombier 	{"tjeg",	"Sanshusha technical Japanese->English,German",
98219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic16.dat",
99219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/tjegindex",
100219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
101219b2ee8SDavid du Colombier 	{"tjegk",	"Sanshusha technical Japanese->English,German (Kanji index)",
102219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic16.dat",
103219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/tjegkindex",
104219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
105219b2ee8SDavid du Colombier 	{"tegj",	"Sanshusha technical English->German,Japanese",
106219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic16.dat",
107219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/tegjindex",
108219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
109219b2ee8SDavid du Colombier 	{"tgje",	"Sanshusha technical German->Japanese,English",
110219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/sandic16.dat",
111219b2ee8SDavid du Colombier 	 "/lib/dict/world/sansdata/tgjeindex",
112219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
113219b2ee8SDavid du Colombier 
114219b2ee8SDavid du Colombier 	{"ne",		"Kunnskapforlaget Norwegian->English",
115219b2ee8SDavid du Colombier 	 "/lib/dict/world/kunndata/sandic28.dat",
116219b2ee8SDavid du Colombier 	 "/lib/dict/world/kunndata/neindex",
117219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
118219b2ee8SDavid du Colombier 	{"en",		"Kunnskapforlaget English->Norwegian",
119219b2ee8SDavid du Colombier 	 "/lib/dict/world/kunndata/sandic27.dat",
120219b2ee8SDavid du Colombier 	 "/lib/dict/world/kunndata/enindex",
121219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
122219b2ee8SDavid du Colombier 
123219b2ee8SDavid du Colombier 	{"re",		"Leon Ungier Russian->English",
124219b2ee8SDavid du Colombier 	 "/lib/dict/re",	"/lib/dict/reindex",
125219b2ee8SDavid du Colombier 	 simplenextoff,	simpleprintentry,	simpleprintkey},
126219b2ee8SDavid du Colombier 	{"er",		"Leon Ungier English->Russian",
127219b2ee8SDavid du Colombier 	 "/lib/dict/re",	"/lib/dict/erindex",
128219b2ee8SDavid du Colombier 	 simplenextoff,	simpleprintentry,	simpleprintkey},
129219b2ee8SDavid du Colombier 
130219b2ee8SDavid du Colombier 	{"se",		"Collins Spanish->English",
131219b2ee8SDavid du Colombier 	 "/lib/dict/se",	"/lib/dict/seindex",
132219b2ee8SDavid du Colombier 	 pcollnextoff,	pcollprintentry,	pcollprintkey},
133219b2ee8SDavid du Colombier 	{"es",		"Collins English->Spanish",
134219b2ee8SDavid du Colombier 	 "/lib/dict/es",	"/lib/dict/esindex",
135219b2ee8SDavid du Colombier 	 pcollnextoff,	pcollprintentry,	pcollprintkey},
136219b2ee8SDavid du Colombier 
137219b2ee8SDavid du Colombier 	{"swe",		"Esselte Studium Swedish->English",
138219b2ee8SDavid du Colombier 	 "/lib/dict/world/essedata/sandic34.dat",
139219b2ee8SDavid du Colombier 	 "/lib/dict/world/essedata/sweindex",
140219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
141219b2ee8SDavid du Colombier 	{"esw",		"Esselte Studium English->Swedish",
142219b2ee8SDavid du Colombier 	 "/lib/dict/world/essedata/sandic33.dat",
143219b2ee8SDavid du Colombier 	 "/lib/dict/world/essedata/eswindex",
144219b2ee8SDavid du Colombier 	 worldnextoff,	worldprintentry,	worldprintkey},
145219b2ee8SDavid du Colombier 
146219b2ee8SDavid du Colombier 	{"movie",	"Movies -- by title",
147219b2ee8SDavid du Colombier 	 "/lib/movie/data",	"/lib/dict/movtindex",
148219b2ee8SDavid du Colombier 	 movienextoff,	movieprintentry,	movieprintkey},
149219b2ee8SDavid du Colombier 	{"moviea",	"Movies -- by actor",
150219b2ee8SDavid du Colombier 	 "/lib/movie/data",	"/lib/dict/movaindex",
151219b2ee8SDavid du Colombier 	 movienextoff,	movieprintentry,	movieprintkey},
152219b2ee8SDavid du Colombier 	{"movied",	"Movies -- by director",
153219b2ee8SDavid du Colombier 	 "/lib/movie/data",	"/lib/dict/movdindex",
154219b2ee8SDavid du Colombier 	 movienextoff,	movieprintentry,	movieprintkey},
155219b2ee8SDavid du Colombier 
156219b2ee8SDavid du Colombier 	{"slang",	"English Slang",
157219b2ee8SDavid du Colombier 	 "/lib/dict/slang",	"/lib/dict/slangindex",
158219b2ee8SDavid du Colombier 	 slangnextoff,	slangprintentry,	slangprintkey},
159219b2ee8SDavid du Colombier 
160219b2ee8SDavid du Colombier 	{"robert",	"Robert Électronique",
161219b2ee8SDavid du Colombier 	 "/lib/dict/robert/_pointers",	"/lib/dict/robert/_index",
162219b2ee8SDavid du Colombier 	 robertnextoff,	robertindexentry,	robertprintkey},
163219b2ee8SDavid du Colombier 	{"robertv",	"Robert Électronique - formes des verbes",
164219b2ee8SDavid du Colombier 	 "/lib/dict/robert/flex.rob",	"/lib/dict/robert/_flexindex",
165219b2ee8SDavid du Colombier 	 robertnextflex,	robertflexentry,	robertprintkey},
166219b2ee8SDavid du Colombier 
167219b2ee8SDavid du Colombier 	{0, 0, 0, 0, 0}
168219b2ee8SDavid du Colombier };
169219b2ee8SDavid du Colombier 
170219b2ee8SDavid du Colombier typedef struct Lig Lig;
171219b2ee8SDavid du Colombier struct Lig {
172219b2ee8SDavid du Colombier 	Rune	start;		/* accent rune */
173219b2ee8SDavid du Colombier 	Rune	*pairs;		/* <char,accented version> pairs */
174219b2ee8SDavid du Colombier };
175219b2ee8SDavid du Colombier 
176219b2ee8SDavid du Colombier static Lig ligtab[Nligs] = {
177219b2ee8SDavid 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ź"},
178219b2ee8SDavid du Colombier [LGRV-LIGS]	{L'ˋ',	L"AÀaàEÈeèIÌiìıìOÒoòUÙuù"},
179219b2ee8SDavid du Colombier [LUML-LIGS]	{L'¨',	L"AÄaäEËeëIÏiïOÖoöUÜuüYŸyÿ"},
180219b2ee8SDavid du Colombier [LCED-LIGS]	{L'¸',	L"CÇcçGĢKĶkķLĻlļNŅnņRŖrŗSŞsşTŢtţ"},
181219b2ee8SDavid du Colombier [LTIL-LIGS]	{L'˜',	L"AÃaãIĨiĩıĩNÑnñOÕoõUŨuũ"},
182219b2ee8SDavid du Colombier [LBRV-LIGS]	{L'˘',	L"AĂaăEĔeĕGĞgğIĬiĭıĭOŎoŏUŬuŭ"},
183219b2ee8SDavid du Colombier [LRNG-LIGS]	{L'˚',	L"AÅaåUŮuů"},
184219b2ee8SDavid du Colombier [LDOT-LIGS]	{L'˙',	L"CĊcċEĖeėGĠgġIİLĿlŀZŻzż"},
185219b2ee8SDavid du Colombier [LDTB-LIGS]	{L'.',	L""},
186219b2ee8SDavid 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ŷ"},
187219b2ee8SDavid du Colombier [LFRB-LIGS]	{L'̯',	L""},
188219b2ee8SDavid du Colombier [LOGO-LIGS]	{L'˛',	L"AĄaąEĘeęIĮiįıįUŲuų"},
189219b2ee8SDavid du Colombier [LMAC-LIGS]	{L'¯',	L"AĀaāEĒeēIĪiīıīOŌoōUŪuū"},
190219b2ee8SDavid du Colombier [LHCK-LIGS]	{L'ˇ',	L"CČcčDĎdďEĚeěLĽlľNŇnňRŘrřSŠsšTŤtťZŽzž"},
191219b2ee8SDavid du Colombier [LASP-LIGS]	{L'ʽ',	L""},
192219b2ee8SDavid du Colombier [LLEN-LIGS]	{L'ʼ',	L""},
193219b2ee8SDavid du Colombier [LBRB-LIGS]	{L'̮',	L""}
194219b2ee8SDavid du Colombier };
195219b2ee8SDavid du Colombier 
196219b2ee8SDavid du Colombier Rune *multitab[Nmulti] = {
197219b2ee8SDavid du Colombier [MAAS-MULTI]	L"ʽα",
198219b2ee8SDavid du Colombier [MALN-MULTI]	L"ʼα",
199219b2ee8SDavid du Colombier [MAND-MULTI]	L"and",
200219b2ee8SDavid du Colombier [MAOQ-MULTI]	L"a/q",
201219b2ee8SDavid du Colombier [MBRA-MULTI]	L"<|",
202219b2ee8SDavid du Colombier [MDD-MULTI]	L"..",
203219b2ee8SDavid du Colombier [MDDD-MULTI]	L"...",
204219b2ee8SDavid du Colombier [MEAS-MULTI]	L"ʽε",
205219b2ee8SDavid du Colombier [MELN-MULTI]	L"ʼε",
206219b2ee8SDavid du Colombier [MEMM-MULTI]	L"——",
207219b2ee8SDavid du Colombier [MHAS-MULTI]	L"ʽη",
208219b2ee8SDavid du Colombier [MHLN-MULTI]	L"ʼη",
209219b2ee8SDavid du Colombier [MIAS-MULTI]	L"ʽι",
210219b2ee8SDavid du Colombier [MILN-MULTI]	L"ʼι",
211219b2ee8SDavid du Colombier [MLCT-MULTI]	L"ct",
212219b2ee8SDavid du Colombier [MLFF-MULTI]	L"ff",
213219b2ee8SDavid du Colombier [MLFFI-MULTI]	L"ffi",
214219b2ee8SDavid du Colombier [MLFFL-MULTI]	L"ffl",
215219b2ee8SDavid du Colombier [MLFL-MULTI]	L"fl",
216219b2ee8SDavid du Colombier [MLFI-MULTI]	L"fi",
217219b2ee8SDavid du Colombier [MLLS-MULTI]	L"ɫɫ",
218219b2ee8SDavid du Colombier [MLST-MULTI]	L"st",
219219b2ee8SDavid du Colombier [MOAS-MULTI]	L"ʽο",
220219b2ee8SDavid du Colombier [MOLN-MULTI]	L"ʼο",
221219b2ee8SDavid du Colombier [MOR-MULTI]	L"or",
222219b2ee8SDavid du Colombier [MRAS-MULTI]	L"ʽρ",
223219b2ee8SDavid du Colombier [MRLN-MULTI]	L"ʼρ",
224219b2ee8SDavid du Colombier [MTT-MULTI]	L"~~",
225219b2ee8SDavid du Colombier [MUAS-MULTI]	L"ʽυ",
226219b2ee8SDavid du Colombier [MULN-MULTI]	L"ʼυ",
227219b2ee8SDavid du Colombier [MWAS-MULTI]	L"ʽω",
228219b2ee8SDavid du Colombier [MWLN-MULTI]	L"ʼω",
229219b2ee8SDavid du Colombier [MOE-MULTI]	L"oe",
230219b2ee8SDavid du Colombier [MES-MULTI]	L"  ",
231219b2ee8SDavid du Colombier };
232219b2ee8SDavid du Colombier 
233219b2ee8SDavid du Colombier static Rune 	*ttabstack[20];
234219b2ee8SDavid du Colombier static int	ntt;
235219b2ee8SDavid du Colombier 
236219b2ee8SDavid du Colombier /*
237219b2ee8SDavid du Colombier  * tab is an array of n Assoc's, sorted by key.
238219b2ee8SDavid du Colombier  * Look for key in tab, and return corresponding val
239219b2ee8SDavid du Colombier  * or -1 if not there
240219b2ee8SDavid du Colombier  */
241219b2ee8SDavid du Colombier long
lookassoc(Assoc * tab,int n,char * key)242219b2ee8SDavid du Colombier lookassoc(Assoc *tab, int n, char *key)
243219b2ee8SDavid du Colombier {
244219b2ee8SDavid du Colombier 	Assoc *q;
245219b2ee8SDavid du Colombier 	long i, low, high;
246219b2ee8SDavid du Colombier 	int r;
247219b2ee8SDavid du Colombier 
248219b2ee8SDavid du Colombier 	for(low = -1, high = n; high > low+1; ){
249219b2ee8SDavid du Colombier 		i = (high+low)/2;
250219b2ee8SDavid du Colombier 		q = &tab[i];
251219b2ee8SDavid du Colombier 		if((r=strcmp(key, q->key))<0)
252219b2ee8SDavid du Colombier 			high = i;
253219b2ee8SDavid du Colombier 		else if(r == 0)
254219b2ee8SDavid du Colombier 			return q->val;
255219b2ee8SDavid du Colombier 		else
256219b2ee8SDavid du Colombier 			low=i;
257219b2ee8SDavid du Colombier 	}
258219b2ee8SDavid du Colombier 	return -1;
259219b2ee8SDavid du Colombier }
260219b2ee8SDavid du Colombier 
261219b2ee8SDavid du Colombier long
looknassoc(Nassoc * tab,int n,long key)262219b2ee8SDavid du Colombier looknassoc(Nassoc *tab, int n, long key)
263219b2ee8SDavid du Colombier {
264219b2ee8SDavid du Colombier 	Nassoc *q;
265219b2ee8SDavid du Colombier 	long i, low, high;
266219b2ee8SDavid du Colombier 
267219b2ee8SDavid du Colombier 	for(low = -1, high = n; high > low+1; ){
268219b2ee8SDavid du Colombier 		i = (high+low)/2;
269219b2ee8SDavid du Colombier 		q = &tab[i];
270219b2ee8SDavid du Colombier 		if(key < q->key)
271219b2ee8SDavid du Colombier 			high = i;
272219b2ee8SDavid du Colombier 		else if(key == q->key)
273219b2ee8SDavid du Colombier 			return q->val;
274219b2ee8SDavid du Colombier 		else
275219b2ee8SDavid du Colombier 			low=i;
276219b2ee8SDavid du Colombier 	}
277219b2ee8SDavid du Colombier 	return -1;
278219b2ee8SDavid du Colombier }
279219b2ee8SDavid du Colombier 
280219b2ee8SDavid du Colombier void
err(char * fmt,...)281219b2ee8SDavid du Colombier err(char *fmt, ...)
282219b2ee8SDavid du Colombier {
283219b2ee8SDavid du Colombier 	char buf[1000];
284219b2ee8SDavid du Colombier 	va_list v;
285219b2ee8SDavid du Colombier 
286219b2ee8SDavid du Colombier 	va_start(v, fmt);
2879a747e4fSDavid du Colombier 	vsnprint(buf, sizeof(buf), fmt, v);
288219b2ee8SDavid du Colombier 	va_end(v);
289219b2ee8SDavid du Colombier 	fprint(2, "%s: %s\n", argv0, buf);
290219b2ee8SDavid du Colombier }
291219b2ee8SDavid du Colombier 
292219b2ee8SDavid du Colombier /*
293219b2ee8SDavid du Colombier  * Write the rune r to bout, keeping track of line length
294219b2ee8SDavid du Colombier  * and breaking the lines (at blanks) when they get too long
295219b2ee8SDavid du Colombier  */
296219b2ee8SDavid du Colombier void
outrune(long r)297219b2ee8SDavid du Colombier outrune(long r)
298219b2ee8SDavid du Colombier {
299219b2ee8SDavid du Colombier 	if(outinhibit)
300219b2ee8SDavid du Colombier 		return;
301219b2ee8SDavid du Colombier 	if(++linelen > breaklen && r == L' ') {
302219b2ee8SDavid du Colombier 		Bputc(bout, '\n');
303219b2ee8SDavid du Colombier 		linelen = 0;
304219b2ee8SDavid du Colombier 	} else
305219b2ee8SDavid du Colombier 		Bputrune(bout, r);
306219b2ee8SDavid du Colombier }
307219b2ee8SDavid du Colombier 
308219b2ee8SDavid du Colombier void
outrunes(Rune * rp)309219b2ee8SDavid du Colombier outrunes(Rune *rp)
310219b2ee8SDavid du Colombier {
311219b2ee8SDavid du Colombier 	Rune r;
312219b2ee8SDavid du Colombier 
313219b2ee8SDavid du Colombier 	while((r = *rp++) != 0)
314219b2ee8SDavid du Colombier 		outrune(r);
315219b2ee8SDavid du Colombier }
316219b2ee8SDavid du Colombier 
317219b2ee8SDavid du Colombier /* like outrune, but when arg is know to be a char */
318219b2ee8SDavid du Colombier void
outchar(int c)319219b2ee8SDavid du Colombier outchar(int c)
320219b2ee8SDavid du Colombier {
321219b2ee8SDavid du Colombier 	if(outinhibit)
322219b2ee8SDavid du Colombier 		return;
323219b2ee8SDavid du Colombier 	if(++linelen > breaklen && c == ' ') {
324219b2ee8SDavid du Colombier 		c ='\n';
325219b2ee8SDavid du Colombier 		linelen = 0;
326219b2ee8SDavid du Colombier 	}
3277dd7cddfSDavid du Colombier 	Bputc(bout, c);
328219b2ee8SDavid du Colombier }
329219b2ee8SDavid du Colombier 
330219b2ee8SDavid du Colombier void
outchars(char * s)331219b2ee8SDavid du Colombier outchars(char *s)
332219b2ee8SDavid du Colombier {
333219b2ee8SDavid du Colombier 	char c;
334219b2ee8SDavid du Colombier 
335219b2ee8SDavid du Colombier 	while((c = *s++) != 0)
336219b2ee8SDavid du Colombier 		outchar(c);
337219b2ee8SDavid du Colombier }
338219b2ee8SDavid du Colombier 
339219b2ee8SDavid du Colombier void
outprint(char * fmt,...)340219b2ee8SDavid du Colombier outprint(char *fmt, ...)
341219b2ee8SDavid du Colombier {
342219b2ee8SDavid du Colombier 	char buf[1000];
343219b2ee8SDavid du Colombier 	va_list v;
344219b2ee8SDavid du Colombier 
345219b2ee8SDavid du Colombier 	va_start(v, fmt);
3469a747e4fSDavid du Colombier 	vsnprint(buf, sizeof(buf), fmt, v);
347219b2ee8SDavid du Colombier 	va_end(v);
348219b2ee8SDavid du Colombier 	outchars(buf);
349219b2ee8SDavid du Colombier }
350219b2ee8SDavid du Colombier 
351219b2ee8SDavid du Colombier void
outpiece(char * b,char * e)352219b2ee8SDavid du Colombier outpiece(char *b, char *e)
353219b2ee8SDavid du Colombier {
354219b2ee8SDavid du Colombier 	int c, lastc;
355219b2ee8SDavid du Colombier 
356219b2ee8SDavid du Colombier 	lastc = 0;
357219b2ee8SDavid du Colombier 	while(b < e) {
358219b2ee8SDavid du Colombier 		c = *b++;
359219b2ee8SDavid du Colombier 		if(c == '\n')
360219b2ee8SDavid du Colombier 			c = ' ';
361219b2ee8SDavid du Colombier 		if(!(c == ' ' && lastc == ' '))
362219b2ee8SDavid du Colombier 			outchar(c);
363219b2ee8SDavid du Colombier 		lastc = c;
364219b2ee8SDavid du Colombier 	}
365219b2ee8SDavid du Colombier }
366219b2ee8SDavid du Colombier 
367219b2ee8SDavid du Colombier /*
368219b2ee8SDavid du Colombier  * Go to new line if not already there; indent if ind != 0.
369219b2ee8SDavid du Colombier  * If ind > 1, leave a blank line too.
370219b2ee8SDavid du Colombier  * Slight hack: assume if current line is only one or two
371219b2ee8SDavid du Colombier  * characters long, then they were spaces.
372219b2ee8SDavid du Colombier  */
373219b2ee8SDavid du Colombier void
outnl(int ind)374219b2ee8SDavid du Colombier outnl(int ind)
375219b2ee8SDavid du Colombier {
376219b2ee8SDavid du Colombier 	if(outinhibit)
377219b2ee8SDavid du Colombier 		return;
378219b2ee8SDavid du Colombier 	if(ind) {
379219b2ee8SDavid du Colombier 		if(ind > 1) {
380219b2ee8SDavid du Colombier 			if(linelen > 2)
381219b2ee8SDavid du Colombier 				Bputc(bout, '\n');
382219b2ee8SDavid du Colombier 			Bprint(bout, "\n  ");
383219b2ee8SDavid du Colombier 		} else if(linelen == 0)
384219b2ee8SDavid du Colombier 			Bprint(bout, "  ");
385219b2ee8SDavid du Colombier 		else if(linelen == 1)
386219b2ee8SDavid du Colombier 			Bputc(bout, ' ');
387219b2ee8SDavid du Colombier 		else if(linelen != 2)
388219b2ee8SDavid du Colombier 			Bprint(bout, "\n  ");
389219b2ee8SDavid du Colombier 		linelen = 2;
390219b2ee8SDavid du Colombier 	} else {
391219b2ee8SDavid du Colombier 		if(linelen) {
392219b2ee8SDavid du Colombier 			Bputc(bout, '\n');
393219b2ee8SDavid du Colombier 			linelen = 0;
394219b2ee8SDavid du Colombier 		}
395219b2ee8SDavid du Colombier 	}
396219b2ee8SDavid du Colombier }
397219b2ee8SDavid du Colombier 
398219b2ee8SDavid du Colombier /*
399219b2ee8SDavid du Colombier  * Fold the runes in null-terminated rp.
400219b2ee8SDavid du Colombier  * Use the sort(1) definition of folding (uppercase to lowercase,
401*eaba85aaSDavid du Colombier  * accented characters to corresponding unaccented chars)
402219b2ee8SDavid du Colombier  */
403219b2ee8SDavid du Colombier void
fold(Rune * rp)404219b2ee8SDavid du Colombier fold(Rune *rp)
405219b2ee8SDavid du Colombier {
406219b2ee8SDavid du Colombier 	Rune r;
407219b2ee8SDavid du Colombier 
408219b2ee8SDavid du Colombier 	while((r = *rp) != 0) {
409*eaba85aaSDavid du Colombier 		r = tobaserune(r);
410*eaba85aaSDavid du Colombier 		if(isupperrune(r))
411*eaba85aaSDavid du Colombier 			r = tolowerrune(r);
412219b2ee8SDavid du Colombier 		*rp++ = r;
413219b2ee8SDavid du Colombier 	}
414219b2ee8SDavid du Colombier }
415219b2ee8SDavid du Colombier 
416219b2ee8SDavid du Colombier /*
417219b2ee8SDavid du Colombier  * Like fold, but put folded result into new
418219b2ee8SDavid du Colombier  * (assumed to have enough space).
419219b2ee8SDavid du Colombier  * old is a regular expression, but we know that
420219b2ee8SDavid du Colombier  * metacharacters aren't affected
421219b2ee8SDavid du Colombier  */
422219b2ee8SDavid du Colombier void
foldre(char * new,char * old)423219b2ee8SDavid du Colombier foldre(char *new, char *old)
424219b2ee8SDavid du Colombier {
425219b2ee8SDavid du Colombier 	Rune r;
426219b2ee8SDavid du Colombier 
427219b2ee8SDavid du Colombier 	while(*old) {
428219b2ee8SDavid du Colombier 		old += chartorune(&r, old);
429*eaba85aaSDavid du Colombier 		r = tobaserune(r);
430*eaba85aaSDavid du Colombier 		if(isupperrune(r))
431*eaba85aaSDavid du Colombier 			r = tolowerrune(r);
432219b2ee8SDavid du Colombier 		new += runetochar(new, &r);
433219b2ee8SDavid du Colombier 	}
434219b2ee8SDavid du Colombier 	*new = 0;
435219b2ee8SDavid du Colombier }
436219b2ee8SDavid du Colombier 
437219b2ee8SDavid du Colombier /*
438219b2ee8SDavid du Colombier  *	acomp(s, t) returns:
439219b2ee8SDavid du Colombier  *		-2 if s strictly precedes t
440219b2ee8SDavid du Colombier  *		-1 if s is a prefix of t
441219b2ee8SDavid du Colombier  *		0 if s is the same as t
442219b2ee8SDavid du Colombier  *		1 if t is a prefix of s
443219b2ee8SDavid du Colombier  *		2 if t strictly precedes s
444219b2ee8SDavid du Colombier  */
445219b2ee8SDavid du Colombier 
446219b2ee8SDavid du Colombier int
acomp(Rune * s,Rune * t)447219b2ee8SDavid du Colombier acomp(Rune *s, Rune *t)
448219b2ee8SDavid du Colombier {
449219b2ee8SDavid du Colombier 	int cs, ct;
450219b2ee8SDavid du Colombier 
451219b2ee8SDavid du Colombier 	for(;;) {
452219b2ee8SDavid du Colombier 		cs = *s;
453219b2ee8SDavid du Colombier 		ct = *t;
454219b2ee8SDavid du Colombier 		if(cs != ct)
455219b2ee8SDavid du Colombier 			break;
456219b2ee8SDavid du Colombier 		if(cs == 0)
457219b2ee8SDavid du Colombier 			return 0;
458219b2ee8SDavid du Colombier 		s++;
459219b2ee8SDavid du Colombier 		t++;
460219b2ee8SDavid du Colombier 	}
461219b2ee8SDavid du Colombier 	if(cs == 0)
462219b2ee8SDavid du Colombier 		return -1;
463219b2ee8SDavid du Colombier 	if(ct == 0)
464219b2ee8SDavid du Colombier 		return 1;
465219b2ee8SDavid du Colombier 	if(cs < ct)
466219b2ee8SDavid du Colombier 		return -2;
467219b2ee8SDavid du Colombier 	return 2;
468219b2ee8SDavid du Colombier }
469219b2ee8SDavid du Colombier 
470219b2ee8SDavid du Colombier /*
471219b2ee8SDavid du Colombier  * Copy null terminated Runes from 'from' to 'to'.
472219b2ee8SDavid du Colombier  */
473219b2ee8SDavid du Colombier void
runescpy(Rune * to,Rune * from)474219b2ee8SDavid du Colombier runescpy(Rune *to, Rune *from)
475219b2ee8SDavid du Colombier {
476219b2ee8SDavid du Colombier 	while((*to++ = *from++) != 0)
477219b2ee8SDavid du Colombier 		continue;
478219b2ee8SDavid du Colombier }
479219b2ee8SDavid du Colombier 
480219b2ee8SDavid du Colombier /*
481219b2ee8SDavid du Colombier  * Conversion of unsigned number to long, no overflow detection
482219b2ee8SDavid du Colombier  */
483219b2ee8SDavid du Colombier long
runetol(Rune * r)484219b2ee8SDavid du Colombier runetol(Rune *r)
485219b2ee8SDavid du Colombier {
486219b2ee8SDavid du Colombier 	int c;
487219b2ee8SDavid du Colombier 	long n;
488219b2ee8SDavid du Colombier 
489219b2ee8SDavid du Colombier 	n = 0;
490219b2ee8SDavid du Colombier 	for(;; r++){
491219b2ee8SDavid du Colombier 		c = *r;
492219b2ee8SDavid du Colombier 		if(L'0'<=c && c<=L'9')
493219b2ee8SDavid du Colombier 			c -= '0';
494219b2ee8SDavid du Colombier 		else
495219b2ee8SDavid du Colombier 			break;
496219b2ee8SDavid du Colombier 		n = n*10 + c;
497219b2ee8SDavid du Colombier 	}
498219b2ee8SDavid du Colombier 	return n;
499219b2ee8SDavid du Colombier }
500219b2ee8SDavid du Colombier 
501219b2ee8SDavid du Colombier /*
502219b2ee8SDavid du Colombier  * See if there is a rune corresponding to the accented
503219b2ee8SDavid du Colombier  * version of r with accent acc (acc in [LIGS..LIGE-1]),
504219b2ee8SDavid du Colombier  * and return it if so, else return NONE.
505219b2ee8SDavid du Colombier  */
506219b2ee8SDavid du Colombier Rune
liglookup(Rune acc,Rune r)507219b2ee8SDavid du Colombier liglookup(Rune acc, Rune r)
508219b2ee8SDavid du Colombier {
509219b2ee8SDavid du Colombier 	Rune *p;
510219b2ee8SDavid du Colombier 
511219b2ee8SDavid du Colombier 	if(acc < LIGS || acc >= LIGE)
512219b2ee8SDavid du Colombier 		return NONE;
513219b2ee8SDavid du Colombier 	for(p = ligtab[acc-LIGS].pairs; *p; p += 2)
514219b2ee8SDavid du Colombier 		if(*p == r)
515219b2ee8SDavid du Colombier 			return *(p+1);
516219b2ee8SDavid du Colombier 	return NONE;
517219b2ee8SDavid du Colombier }
518219b2ee8SDavid du Colombier 
519219b2ee8SDavid du Colombier /*
520219b2ee8SDavid du Colombier  * Maintain a translation table stack (a translation table
521219b2ee8SDavid du Colombier  * is an array of Runes indexed by bytes or 7-bit bytes).
522219b2ee8SDavid du Colombier  * If starting is true, push the curtab onto the stack
523219b2ee8SDavid du Colombier  * and return newtab; else pop the top of the stack and
524219b2ee8SDavid du Colombier  * return it.
525219b2ee8SDavid du Colombier  * If curtab is 0, initialize the stack and return.
526219b2ee8SDavid du Colombier  */
527219b2ee8SDavid du Colombier Rune *
changett(Rune * curtab,Rune * newtab,int starting)528219b2ee8SDavid du Colombier changett(Rune *curtab, Rune *newtab, int starting)
529219b2ee8SDavid du Colombier {
530219b2ee8SDavid du Colombier 	if(curtab == 0) {
531219b2ee8SDavid du Colombier 		ntt = 0;
532219b2ee8SDavid du Colombier 		return 0;
533219b2ee8SDavid du Colombier 	}
534219b2ee8SDavid du Colombier 	if(starting) {
535219b2ee8SDavid du Colombier 		if(ntt >= asize(ttabstack)) {
536219b2ee8SDavid du Colombier 			if(debug)
537219b2ee8SDavid du Colombier 				err("translation stack overflow");
538219b2ee8SDavid du Colombier 			return curtab;
539219b2ee8SDavid du Colombier 		}
540219b2ee8SDavid du Colombier 		ttabstack[ntt++] = curtab;
541219b2ee8SDavid du Colombier 		return newtab;
542219b2ee8SDavid du Colombier 	} else {
543219b2ee8SDavid du Colombier 		if(ntt == 0) {
544219b2ee8SDavid du Colombier 			if(debug)
545219b2ee8SDavid du Colombier 				err("translation stack underflow");
546219b2ee8SDavid du Colombier 			return curtab;
547219b2ee8SDavid du Colombier 		}
548219b2ee8SDavid du Colombier 		return ttabstack[--ntt];
549219b2ee8SDavid du Colombier 	}
550219b2ee8SDavid du Colombier }
551