xref: /inferno-os/appl/lib/convcs/convcs.b (revision 9b29ac7ea714507a9c0690620c02c8ca5ab25f90)
1implement Convcs;
2
3include "sys.m";
4include "cfg.m";
5include "convcs.m";
6
7DEFCSFILE : con "/lib/convcs/charsets";
8
9sys : Sys;
10cfg : Cfg;
11
12Record, Tuple : import cfg;
13
14init(csfile : string) : string
15{
16	sys = load Sys Sys->PATH;
17	cfg = load Cfg Cfg->PATH;
18	if (cfg == nil)
19		return sys->sprint("cannot load module %s: %r", Cfg->PATH);
20	if (csfile == nil)
21		csfile = DEFCSFILE;
22	err := cfg->init(csfile);
23	if (err != nil) {
24		cfg = nil;
25		return err;
26	}
27	return nil;
28}
29
30getbtos(cs : string) : (Btos, string)
31{
32	cs = normalize(cs);
33	(rec, err) := csalias(cs);
34	if (err != nil)
35		return (nil, err);
36
37	(path, btostup) := rec.lookup("btos");
38	if (path == nil)
39		return (nil, sys->sprint("no converter for %s", cs));
40	arg := btostup.lookup("arg");
41
42	btos := load Btos path;
43	if (btos == nil)
44		return (nil, sys->sprint("cannot load converter: %r"));
45	err = btos->init(arg);
46	if (err != nil)
47		return (nil, err);
48	return (btos, nil);
49}
50
51getstob(cs : string) : (Stob, string)
52{
53	cs = normalize(cs);
54	(rec, err) := csalias(cs);
55	if (err != nil)
56		return (nil, err);
57
58	(path, stobtup) := rec.lookup("stob");
59	if (path == nil)
60		return (nil, sys->sprint("no converter for %s", cs));
61	arg := stobtup.lookup("arg");
62
63	stob := load Stob path;
64	if (stob == nil)
65		return (nil, sys->sprint("cannot load converter: %r"));
66	err = stob->init(arg);
67	if (err != nil)
68		return (nil, err);
69	return (stob, nil);
70}
71
72csalias(cs : string) : (ref Cfg->Record, string)
73{
74	# search out charset record - allow for one level of renaming
75	for (i := 0; i < 2; i++) {
76		recs := cfg->lookup(cs);
77		if (recs == nil)
78			return (nil, sys->sprint("unknown charset %s", cs));
79		(val, rec) := hd recs;
80		if (val != nil) {
81			cs = val;
82			continue;
83		}
84		return (rec, nil);
85	}
86	return (nil, sys->sprint("too man aliases for %s\n", cs));
87}
88
89enumcs() : list of (string, string, int)
90{
91	d : list of (string, string, int);
92	for (csl := cfg->getkeys(); csl != nil; csl = tl csl) {
93		cs := hd csl;
94		recs := cfg->lookup(cs);
95		if (recs == nil)
96			continue;	# shouldn't happen!
97		(val, rec) := hd recs;
98		if (val != nil)
99			# an alias - ignore
100			continue;
101
102		(btos, nil) := rec.lookup("btos");
103		(stob, nil) := rec.lookup("stob");
104
105		if (btos == nil && stob == nil)
106			continue;
107		mode := 0;
108		if (btos != nil)
109			mode = BTOS;
110		if (stob != nil)
111			mode |= STOB;
112
113		(desc, nil) := rec.lookup("desc");
114		if (desc == nil)
115			desc = cs;
116
117		d = (cs, desc, mode) :: d;
118	}
119	# d is in reverse order to that in the csfile file
120	l : list of (string, string, int);
121	for (; d != nil; d = tl d)
122		l = hd d :: l;
123	return l;
124}
125
126aliases(cs : string) : (string, list of string)
127{
128	cs = normalize(cs);
129	(mainrec, err) := csalias(cs);
130	if (err != nil)
131		return (err, nil);
132
133	cs = (hd (hd mainrec.tuples).attrs).name;
134
135	(desc, nil) := mainrec.lookup("desc");
136	if (desc == nil)
137		desc = cs;
138
139	al := cs :: nil;
140	for (csl := cfg->getkeys(); csl != nil; csl = tl csl) {
141		name := hd csl;
142		recs := cfg->lookup(name);
143		if (recs == nil)
144			continue;	# shouldn't happen!
145		(val, nil) := hd recs;
146		if (val != cs)
147			continue;
148		al = name :: al;
149	}
150
151	r : list of string;
152	for (; al != nil; al = tl al)
153		r = hd al :: r;
154	return (desc, r);
155}
156
157normalize(s : string) : string
158{
159	for (i := 0; i < len s; i++) {
160		r := s[i];
161		if (r >= 'A' && r <= 'Z')
162			s[i] = r + ('a' - 'A');
163	}
164	return s;
165}
166