xref: /inferno-os/appl/lib/format.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Format;
2*37da2899SCharles.Forsythinclude "sys.m";
3*37da2899SCharles.Forsyth	sys: Sys;
4*37da2899SCharles.Forsythinclude "bufio.m";
5*37da2899SCharles.Forsyth	bufio: Bufio;
6*37da2899SCharles.Forsyth	Iobuf: import bufio;
7*37da2899SCharles.Forsythinclude "sexprs.m";
8*37da2899SCharles.Forsyth	sexprs: Sexprs;
9*37da2899SCharles.Forsyth	Sexp: import sexprs;
10*37da2899SCharles.Forsythinclude "format.m";
11*37da2899SCharles.Forsyth
12*37da2899SCharles.Forsyth# possible addition?
13*37da2899SCharles.Forsyth# se2spec(se: list of ref Sexp): (array of Fmtspec, string)
14*37da2899SCharles.Forsyth
15*37da2899SCharles.Forsythinit()
16*37da2899SCharles.Forsyth{
17*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
18*37da2899SCharles.Forsyth	sexprs = load Sexprs Sexprs->PATH;
19*37da2899SCharles.Forsyth	sexprs->init();
20*37da2899SCharles.Forsyth	bufio = load Bufio Bufio->PATH;
21*37da2899SCharles.Forsyth}
22*37da2899SCharles.Forsyth
23*37da2899SCharles.Forsythspec2se(spec: array of Fmtspec): list of ref Sexp
24*37da2899SCharles.Forsyth{
25*37da2899SCharles.Forsyth	l: list of ref Sexp;
26*37da2899SCharles.Forsyth	for(i := len spec - 1; i >= 0; i--){
27*37da2899SCharles.Forsyth		if((sp := spec[i]).fields != nil)
28*37da2899SCharles.Forsyth			l = ref Sexp.List(ref Sexp.String(sp.name, nil) :: spec2se(sp.fields)) :: l;
29*37da2899SCharles.Forsyth		else if(sp.name != nil)
30*37da2899SCharles.Forsyth			l = ref Sexp.String(sp.name, nil) :: l;
31*37da2899SCharles.Forsyth	}
32*37da2899SCharles.Forsyth	return l;
33*37da2899SCharles.Forsyth}
34*37da2899SCharles.Forsyth
35*37da2899SCharles.Forsythspec2fmt(specs: array of Fmtspec): array of Fmt
36*37da2899SCharles.Forsyth{
37*37da2899SCharles.Forsyth	if(specs == nil)
38*37da2899SCharles.Forsyth		return nil;
39*37da2899SCharles.Forsyth	f := array[len specs] of Fmt;
40*37da2899SCharles.Forsyth	for(i := 0; i < len specs; i++){
41*37da2899SCharles.Forsyth		if(specs[i].name == nil)
42*37da2899SCharles.Forsyth			f[i].kind = -1;
43*37da2899SCharles.Forsyth		else
44*37da2899SCharles.Forsyth			f[i] = (i, spec2fmt(specs[i].fields));
45*37da2899SCharles.Forsyth	}
46*37da2899SCharles.Forsyth	return f;
47*37da2899SCharles.Forsyth}
48*37da2899SCharles.Forsyth
49*37da2899SCharles.Forsyth
50*37da2899SCharles.Forsythse2fmt(spec: array of Fmtspec, se: ref Sexp): (array of Fmt, string)
51*37da2899SCharles.Forsyth{
52*37da2899SCharles.Forsyth	if(!se.islist())
53*37da2899SCharles.Forsyth		return (nil, "format must be a list");
54*37da2899SCharles.Forsyth	return ses2fmt(spec, se.els());
55*37da2899SCharles.Forsyth}
56*37da2899SCharles.Forsyth
57*37da2899SCharles.Forsythses2fmt(spec: array of Fmtspec, els: list of ref Sexp): (array of Fmt, string)
58*37da2899SCharles.Forsyth{
59*37da2899SCharles.Forsyth	a := array[len els] of Fmt;
60*37da2899SCharles.Forsyth	for(i := 0; els != nil; els = tl els){
61*37da2899SCharles.Forsyth		name := (hd els).op();
62*37da2899SCharles.Forsyth		for(j := 0; j < len spec; j++)
63*37da2899SCharles.Forsyth			if(spec[j].name == name)
64*37da2899SCharles.Forsyth				break;
65*37da2899SCharles.Forsyth		if(j == len spec)
66*37da2899SCharles.Forsyth			return (nil, sys->sprint("format name %#q not found", name));
67*37da2899SCharles.Forsyth		sp := spec[j];
68*37da2899SCharles.Forsyth		if((hd els).islist() == 0)
69*37da2899SCharles.Forsyth			a[i++] = Fmt(j, spec2fmt(sp.fields));
70*37da2899SCharles.Forsyth		else if(sp.fields == nil)
71*37da2899SCharles.Forsyth			return (nil, sys->sprint("unexpected list %#q", name));
72*37da2899SCharles.Forsyth		else{
73*37da2899SCharles.Forsyth			(f, err) := ses2fmt(sp.fields, (hd els).args());
74*37da2899SCharles.Forsyth			if(f == nil)
75*37da2899SCharles.Forsyth				return (nil, err);
76*37da2899SCharles.Forsyth			a[i++] = Fmt(j, f);
77*37da2899SCharles.Forsyth		}
78*37da2899SCharles.Forsyth	}
79*37da2899SCharles.Forsyth	return (a, nil);
80*37da2899SCharles.Forsyth}
81*37da2899SCharles.Forsyth
82*37da2899SCharles.Forsythrec2val(spec: array of Fmtspec, se: ref Sexprs->Sexp): (array of Fmtval, string)
83*37da2899SCharles.Forsyth{
84*37da2899SCharles.Forsyth	if(se.islist() == 0)
85*37da2899SCharles.Forsyth		return (nil, "expected list of fields; got "+se.text());
86*37da2899SCharles.Forsyth	els := se.els();
87*37da2899SCharles.Forsyth	if(len els > len spec)
88*37da2899SCharles.Forsyth		return (nil, sys->sprint("too many fields found, expected %d, got %s", len spec, se.text()));
89*37da2899SCharles.Forsyth	a := array[len spec] of Fmtval;
90*37da2899SCharles.Forsyth	err: string;
91*37da2899SCharles.Forsyth	for(i := 0; i < len spec; i++){
92*37da2899SCharles.Forsyth		f := spec[i];
93*37da2899SCharles.Forsyth		if(f.name == nil)
94*37da2899SCharles.Forsyth			continue;
95*37da2899SCharles.Forsyth		if(els == nil)
96*37da2899SCharles.Forsyth			return (nil, sys->sprint("too few fields found, expected %d, got %s", len spec, se.text()));
97*37da2899SCharles.Forsyth		el := hd els;
98*37da2899SCharles.Forsyth		if(f.fields == nil)
99*37da2899SCharles.Forsyth			a[i].val = el;
100*37da2899SCharles.Forsyth		else{
101*37da2899SCharles.Forsyth			if(el.islist() == 0)
102*37da2899SCharles.Forsyth				return (nil, "expected list of elements; got "+el.text());
103*37da2899SCharles.Forsyth			vl := el.els();
104*37da2899SCharles.Forsyth			a[i].recs = recs := array[len vl] of array of Fmtval;
105*37da2899SCharles.Forsyth			for(j := 0; vl != nil; vl = tl vl){
106*37da2899SCharles.Forsyth				(recs[j++], err) = rec2val(spec[i].fields, hd vl);
107*37da2899SCharles.Forsyth				if(err != nil)
108*37da2899SCharles.Forsyth					return (nil, err);
109*37da2899SCharles.Forsyth			}
110*37da2899SCharles.Forsyth		}
111*37da2899SCharles.Forsyth		els = tl els;
112*37da2899SCharles.Forsyth	}
113*37da2899SCharles.Forsyth	return (a, nil);
114*37da2899SCharles.Forsyth}
115*37da2899SCharles.Forsyth
116*37da2899SCharles.ForsythFmtval.text(v: self Fmtval): string
117*37da2899SCharles.Forsyth{
118*37da2899SCharles.Forsyth	return v.val.astext();
119*37da2899SCharles.Forsyth}
120*37da2899SCharles.Forsyth
121*37da2899SCharles.ForsythFmtfile.new(spec: array of Fmtspec): Fmtfile
122*37da2899SCharles.Forsyth{
123*37da2899SCharles.Forsyth	return (spec, (ref Sexp.List(spec2se(spec))).pack());
124*37da2899SCharles.Forsyth}
125*37da2899SCharles.Forsyth
126*37da2899SCharles.ForsythFmtfile.open(f: self Fmtfile, name: string): ref Bufio->Iobuf
127*37da2899SCharles.Forsyth{
128*37da2899SCharles.Forsyth	fd := sys->open(name, Sys->ORDWR);
129*37da2899SCharles.Forsyth	if(fd == nil){
130*37da2899SCharles.Forsyth		sys->werrstr(sys->sprint("open failed: %r"));
131*37da2899SCharles.Forsyth		return nil;
132*37da2899SCharles.Forsyth	}
133*37da2899SCharles.Forsyth	if(sys->write(fd, f.descr, len f.descr) == -1){
134*37da2899SCharles.Forsyth		sys->werrstr(sys->sprint("format write failed: %r"));
135*37da2899SCharles.Forsyth		return nil;
136*37da2899SCharles.Forsyth	}
137*37da2899SCharles.Forsyth	sys->seek(fd, big 0, Sys->SEEKSTART);
138*37da2899SCharles.Forsyth	return bufio->fopen(fd, Sys->OREAD);
139*37da2899SCharles.Forsyth}
140*37da2899SCharles.Forsyth
141*37da2899SCharles.ForsythFmtfile.read(f: self Fmtfile, iob: ref Iobuf): (array of Fmtval, string)
142*37da2899SCharles.Forsyth{
143*37da2899SCharles.Forsyth	(se, err) := Sexp.read(iob);
144*37da2899SCharles.Forsyth	if(se == nil)
145*37da2899SCharles.Forsyth		return (nil, err);
146*37da2899SCharles.Forsyth	return rec2val(f.spec, se);
147*37da2899SCharles.Forsyth}
148