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