xref: /inferno-os/appl/ebook/checkxml.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Checkxml;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsyth# simple minded xml checker - checks for basic nestedness, and
4*37da2899SCharles.Forsyth# prints out more informative context on the error messages than
5*37da2899SCharles.Forsyth# the usual xml parser.
6*37da2899SCharles.Forsyth
7*37da2899SCharles.Forsythinclude "sys.m";
8*37da2899SCharles.Forsyth	sys: Sys;
9*37da2899SCharles.Forsythinclude "draw.m";
10*37da2899SCharles.Forsythinclude "bufio.m";
11*37da2899SCharles.Forsythinclude "xml.m";
12*37da2899SCharles.Forsyth	xml: Xml;
13*37da2899SCharles.Forsyth	Parser, Item, Locator: import xml;
14*37da2899SCharles.Forsyth
15*37da2899SCharles.Forsythstderr: ref Sys->FD;
16*37da2899SCharles.ForsythCheckxml: module {
17*37da2899SCharles.Forsyth	init: fn(nil: ref Draw->Context, argv: list of string);
18*37da2899SCharles.Forsyth};
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsythinit(nil: ref Draw->Context, argv: list of string)
21*37da2899SCharles.Forsyth{
22*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
23*37da2899SCharles.Forsyth	stderr = sys->fildes(2);
24*37da2899SCharles.Forsyth	xml = load Xml Xml->PATH;
25*37da2899SCharles.Forsyth	if (xml == nil) {
26*37da2899SCharles.Forsyth		sys->fprint(stderr, "checkxml: cannot load %s: %r\n", Xml->PATH);
27*37da2899SCharles.Forsyth		raise "fail:bad module";
28*37da2899SCharles.Forsyth	}
29*37da2899SCharles.Forsyth	xml->init();
30*37da2899SCharles.Forsyth	if (len argv < 2) {
31*37da2899SCharles.Forsyth		sys->fprint(stderr, "usage: checkxml file...\n");
32*37da2899SCharles.Forsyth		raise "fail:usage";
33*37da2899SCharles.Forsyth	}
34*37da2899SCharles.Forsyth	err := 0;
35*37da2899SCharles.Forsyth	for (argv = tl argv; argv != nil; argv = tl argv) {
36*37da2899SCharles.Forsyth		err = check(hd argv) || err;
37*37da2899SCharles.Forsyth	}
38*37da2899SCharles.Forsyth	if (err)
39*37da2899SCharles.Forsyth		raise "fail:errors";
40*37da2899SCharles.Forsyth}
41*37da2899SCharles.Forsyth
42*37da2899SCharles.Forsythwarningproc(warningch: chan of (Locator, string), finch: chan of int, tagstackch: chan of ref Item.Tag)
43*37da2899SCharles.Forsyth{
44*37da2899SCharles.Forsyth	nw := 0;
45*37da2899SCharles.Forsyth	stack: list of ref Item.Tag;
46*37da2899SCharles.Forsyth	for (;;) {
47*37da2899SCharles.Forsyth		alt {
48*37da2899SCharles.Forsyth		(loc, w) := <-warningch =>
49*37da2899SCharles.Forsyth			if (w == nil) {
50*37da2899SCharles.Forsyth				finch <-= nw;
51*37da2899SCharles.Forsyth				exit;
52*37da2899SCharles.Forsyth			}
53*37da2899SCharles.Forsyth			printerror(loc, w, stack);
54*37da2899SCharles.Forsyth			nw++;
55*37da2899SCharles.Forsyth		item := <-tagstackch =>
56*37da2899SCharles.Forsyth			if (item != nil)
57*37da2899SCharles.Forsyth				stack = item :: stack;
58*37da2899SCharles.Forsyth			else
59*37da2899SCharles.Forsyth				stack = tl stack;
60*37da2899SCharles.Forsyth		}
61*37da2899SCharles.Forsyth	}
62*37da2899SCharles.Forsyth}
63*37da2899SCharles.Forsyth
64*37da2899SCharles.Forsythprinterror(loc: Locator, e: string, tagstack: list of ref Item.Tag)
65*37da2899SCharles.Forsyth{
66*37da2899SCharles.Forsyth	if (tagstack != nil) {
67*37da2899SCharles.Forsyth		sys->print("%s:%d: %s\n", loc.systemid, loc.line, e);
68*37da2899SCharles.Forsyth		for (il := tagstack; il != nil; il = tl il)
69*37da2899SCharles.Forsyth			sys->print("\t%s:%s: <%s>\n", loc.systemid, o2l(loc.systemid, (hd il).fileoffset), (hd il).name);
70*37da2899SCharles.Forsyth	}
71*37da2899SCharles.Forsyth}
72*37da2899SCharles.Forsyth
73*37da2899SCharles.Forsyth# convert file offset to line number... not very efficient, but we don't really care.
74*37da2899SCharles.Forsytho2l(f: string, o: int): string
75*37da2899SCharles.Forsyth{
76*37da2899SCharles.Forsyth	fd := sys->open(f, Sys->OREAD);
77*37da2899SCharles.Forsyth	if (fd == nil)
78*37da2899SCharles.Forsyth		return "#" + string o;
79*37da2899SCharles.Forsyth	buf := array[o] of byte;
80*37da2899SCharles.Forsyth	n := sys->read(fd, buf, len buf);
81*37da2899SCharles.Forsyth	if (n < o)
82*37da2899SCharles.Forsyth		return "#" + string o;
83*37da2899SCharles.Forsyth	nl := 1;
84*37da2899SCharles.Forsyth	for (i := 0; i < len buf; i++)
85*37da2899SCharles.Forsyth		if (buf[i] == byte '\n')
86*37da2899SCharles.Forsyth			nl++;
87*37da2899SCharles.Forsyth	return string nl;
88*37da2899SCharles.Forsyth}
89*37da2899SCharles.Forsyth
90*37da2899SCharles.Forsythcheck(f: string): int
91*37da2899SCharles.Forsyth{
92*37da2899SCharles.Forsyth	spawn warningproc(
93*37da2899SCharles.Forsyth			warningch := chan of (Locator, string),
94*37da2899SCharles.Forsyth			finch := chan of int,
95*37da2899SCharles.Forsyth			tagstackch := chan of ref Item.Tag
96*37da2899SCharles.Forsyth	);
97*37da2899SCharles.Forsyth	(x, e) := xml->open(f, warningch, nil);
98*37da2899SCharles.Forsyth	if (x == nil) {
99*37da2899SCharles.Forsyth		sys->fprint(stderr, "%s: %s\n", f, e);
100*37da2899SCharles.Forsyth		return -1;
101*37da2899SCharles.Forsyth	}
102*37da2899SCharles.Forsyth	{
103*37da2899SCharles.Forsyth		parse(x, tagstackch, warningch);
104*37da2899SCharles.Forsyth		warningch <-= (*ref Locator, nil);
105*37da2899SCharles.Forsyth		return <-finch;
106*37da2899SCharles.Forsyth	} exception ex {
107*37da2899SCharles.Forsyth	"error" =>
108*37da2899SCharles.Forsyth		warningch <-= (*ref Locator, nil);
109*37da2899SCharles.Forsyth		<-finch;
110*37da2899SCharles.Forsyth		return -1;
111*37da2899SCharles.Forsyth	}
112*37da2899SCharles.Forsyth}
113*37da2899SCharles.Forsyth
114*37da2899SCharles.Forsythparse(x: ref Xml->Parser, tagstackch: chan of ref Item.Tag, warningch: chan of (Locator, string))
115*37da2899SCharles.Forsyth{
116*37da2899SCharles.Forsyth	for (;;) {
117*37da2899SCharles.Forsyth		item := x.next();
118*37da2899SCharles.Forsyth		if (item == nil)
119*37da2899SCharles.Forsyth			return;
120*37da2899SCharles.Forsyth		pick i := item {
121*37da2899SCharles.Forsyth		Error =>
122*37da2899SCharles.Forsyth			warningch <-= (i.loc, i.msg);
123*37da2899SCharles.Forsyth			raise "error";
124*37da2899SCharles.Forsyth		Tag =>
125*37da2899SCharles.Forsyth			tagstackch <-= i;
126*37da2899SCharles.Forsyth			x.down();
127*37da2899SCharles.Forsyth			parse(x, tagstackch, warningch);
128*37da2899SCharles.Forsyth			x.up();
129*37da2899SCharles.Forsyth			tagstackch <-= nil;
130*37da2899SCharles.Forsyth		}
131*37da2899SCharles.Forsyth	}
132*37da2899SCharles.Forsyth}
133