Re: New Package Maintainer
Sather User <[email protected]> Fri, 2 Sep 2011 23:25:45 +0930 (CST)
| Newsgroups | gmane.comp.lang.sather.announce |
|---|---|
| Message-ID | <[email protected]> |
On Sat, 18 Dec 2010, [email protected] wrote: > There is a bug in the browser. ("May crash later:") I think I'll > start by looking at that (3-4 weeks?)... I have a lot to learn, and > I think finding and fixing a bug is the best way to "get one's hands > dirty". Hi, Sadi. Wondering how you went with the browser. Here is a PGM class. Unsophisticated, like me, no doubt, but may be useful to someone. There are different creates for reading/validating and writing a PGM file. Maybe not ready for release. Use at your own risk. class PGM is shared errno:INT; shared strerr:STR; attr tag:FMAP{STR,STR}; attr comment:FLIST{FSTR}; attr f:FILE; attr height, width, maxval, prod, imsize, start_loc, end_loc:INT; attr deep:BOOL; attr writer:BOOL; oferr(n:INT) is strerr:="could not open file"; errno := n end; ferr(n:INT) is -- format error strerr:="bad file format"; errno := n; end; create(filename:STR, old:SAME, deep:BOOL):SAME is -- Writer create. See comments below. return create(filename, old, deep, void, void) end; create(filename:STR, old:SAME, deep:BOOL, newwidth, newheight:INT):SAME is -- Create a PGM to write from a PGM that was read. -- Assumes we are modifying some PGM or more than one, whose -- headers must be copied. The writing uses self.f which is -- here advanced to the point following the header so -- the first pixel can be written. Can't use old.deep because we -- need the option of converting 16-bit input to 8-bit output. res:SAME:=new; res.writer:=true; if void(filename) then res.f:=FILE::stdout else res.f:=FILE::open_for_write(filename); if res.f.error then oferr(2); return void end; end; res.f+"P5\n"; -- If there were multiple input PGMs, e.g. for noise reduction, -- the header data, comments, specific to all but the last are lost. -- The comments, width and height of the last input PGM only are used. if ~void(old.comment) and old.comment.size > 0 then loop res.f+("#"+old.comment.elt!+"\n") end end; -- Not old.deep: the parameter deep. if deep then res.maxval := 65535 else res.maxval := 255 end; if void(newwidth) then res.width:=old.width else res.width:=newwidth end; if void(newheight) then res.height:=old.height else res.height:=newheight end; res.f+res.width.str+" "+res.height.str+"\n"+res.maxval.str+"\n"; return res end; create(filename, directory:STR):SAME is -- A reader create which does open_for_read of an existing PGM file, -- and some other things. res::=new; if ~void(directory) then filename := directory + "/" + filename end; f::=FILE::open_for_read(filename); if f.error then oferr(2); return void end; res.f:=f; ----------------------------------------------------------- c:CHAR; c:=res.material_next; if c /= 'P' then ferr(29); return void end; c:=res.f.get_char; if c /= '5' then ferr(3); return void end; c:=res.material_next; if ~c.is_digit then ferr(5); return void end; Width ::= res.my_sense(c).t2; c:=res.material_next; if ~c.is_digit then ferr(6); return void end; Height::=res.my_sense(c).t2; c:=res.material_next; if ~c.is_digit then ferr(7); return void end; Maxval_tup::=res.my_sense(c); Maxval::=Maxval_tup.t2; if Maxval_tup.t1.is_space.not then ferr(8); return void end; res.start_loc:=res.f.current_loc; res.f.seek_from_end(0); res.end_loc:=res.f.current_loc; res.f.seek_from_front(res.start_loc); res.width:=#INT(Width); res.height:=#INT(Height); res.maxval:=#INT(Maxval); res.deep:=res.maxval>255; prod::=res.width*res.height; if res.deep then prod:=prod+prod end; res.prod := prod; imsize::=res.end_loc-res.start_loc; res.imsize := imsize; if MAIN::dbg_header then #ERR+"width="+Width+"\theight="+Height+"\tmaxval="+Maxval+"\n"; #ERR+"start_loc="+res.start_loc+"\tend_loc="+res.end_loc+"\n"; #ERR+"prod="+res.prod+"\timsize="+res.imsize; #ERR+"\tprod-imsize="+(res.prod-res.imsize)+"\n"; ferr(0); return void end; -- Final header test: more than 1 char between Maxval and 1st pixel? if prod/=imsize then ferr(9); return void end; -- These must set shared errno:INT and return void return res end; my_sense(n:CHAR):TUP{CHAR,STR} is -- Place the arg in a new string buffer. -- Make it FSTR. -- Read the next character. -- If it is whitespace return the string buffer. -- If it is '#'step over it (saving comment) and return the -- string buffer. -- Otherwise append it to the string buffer and start again. c:CHAR; sb:FSTR:=#; sb:=sb.push(n); loop c:=f.get_char; if c.is_space then return #(c,sb.str) end; if c='#' then comment_collect_skip; return #(c,sb.str) end; sb:=sb.push(c) end end; stepover:CHAR is -- If the next item is a whitespace character or comment -- step over it and return '\0' else step over it and return it c:CHAR; c:=f.get_char; if c.is_space then return '\0' end; if c='#' then comment_collect_skip; return '\0' end; return c end; material_next:CHAR is -- Look for the next character that is not whitespace (inc blank -- lines) and not a comment. Return the character. c:CHAR; loop c:=stepover; while!(c='\0') end; return c end; comment_collect_skip -- A "#" was found. Advance to end of line, putting everthing -- before \n into a new comment item. is s:FSTR; loop c::=f.get_char; until!(c='\n'); s:=s.push(c) end; comment:=comment.push(s) end; plus(i:INT) is -- append a character to new file if ~writer then #ERR+"Not a writer.\n" else if deep then f+i.urshift(8).char; f+i.band(255).char else f+i.char end end end; plus(n:FLT) is plus(n.round.int) end; get_int:INT is if writer then #ERR+"Not a reader.\n"; return 0 end; if deep then return f.get_char.int.utimes(256).uplus(f.get_char.int) end; return f.get_char.int end; pixnum_read_hexstr:STR is s::=get_int.hex_str; w::=s.size-2; return s.tail(w) end; close is f.close end; end; -- Michael Talbot-Wilson