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