Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!maverick.ksu.ksu.edu!ux1.cso.uiuc.edu!midway!quads.uchicago.edu!goer From: goer@quads.uchicago.edu (Richard L. Goerwitz) Newsgroups: comp.lang.icon Subject: Re: UUXXCODE Message-ID: <1990Sep20.043409.14256@midway.uchicago.edu> Date: 20 Sep 90 04:34:09 GMT References: <0093CBF0039A4D60.20400E83@mis.mcw.edu> Sender: news@midway.uchicago.edu (News Administrator) Distribution: inet Organization: University of Chicago Lines: 173 ############################################################################ # # Name: iidecode.icn # # Title: iidecode (port of the Unix/C uudecode program to Icon) # # Author: Richard L. Goerwitz # # Version: 1.2 # ############################################################################ # # This is an Icon port of the Unix/C uudecode utility. Since # uudecode is publicly distributable BSD code, I simply grabbed a # copy, and rewrote it in Icon. The only basic functional change I # made to the program was to simplify the notion of file mode. # Everything is encodedwith 0644 permissions. Operating systems # differ so widely in how they handle this sort of thing that I # decided just not to worry about it. # # Usage is the same as the Unix uudecode command, i.e. a first # (optional) argument gives the name the file to be decoded. If this # is omitted, iidecode just uses the standard input: # # iidecode [infile] remotefilename # # Even people who do not customarily use Unix should be aware of # the uuen/decode program and file format. It is widely used, and has # been implemented on a wide variety of machines for sending 8-bit # "binaries" through networks designed for ASCII transfers only. # # BUGS: Slow. I decided to go for clarity and symmetry, rather than # speed, and so opted to do things like use ishift(i,j) instead of # straight multiplication (which under Icon v8 is much faster). # ############################################################################ # # See also: iiencode.icn # ############################################################################ procedure main(a) local in, filename, dest # optional 1st (and only) argument if *a = 1 then { filename := pop(a) if not (in := open(filename, "r")) then { write(&errout,"Can't open ",a[1],".") exit(1) } } else in := &input if *a ~= 0 then { write(&errout,"Usage: iidecode [infile] remotefile") exit (2) } # Find the "begin" line, and determine the destination file name. !in ? { tab(match("begin ")) & tab(many(&digits)) & # mode ignored tab(many(' ')) & dest := tab(0) } # If dest is null, the begin line either isn't present, or is # corrupt (which necessitates our aborting with an error msg.). if /dest then { write(&errout,"No begin line.") exit(3) } # Tilde expansion is heavily Unix dependent, and we can't always # safely write the file to the current directory. Our only choice # is to abort. if match("~",dest) then { write(&errout,"Please remove ~ from input file begin line.") exit(4) } out := open(dest, "w") decode(in, out) # decode checks for "end" line if not match("end", !in) then { write(&errout,"No end line.\n") exit(5) } exit(0) end procedure decode(in, out) # Copy from in to out, decoding as you go along. local line, chunk while line := read(in) do { if *line = 0 then { write(&errout,"Short file.\n") exit(10) } line ? { n := DEC(ord(move(1))) # Uuencode signals the end of the coded text by a space # and a line (i.e. a zero-length line, coded as a space). if n <= 0 then break while (n > 0) do { chunk := move(4) | tab(0) outdec(chunk, out, n) n -:= 3 } } } return end procedure outdec(s, f, n) # Output a group of 3 bytes (4 input characters). N is used to # tell us not to output all of the chars at the end of the file. local c1, c2, c3 c1 := iand( ior( ishift(DEC(ord(s[1])),+2), ishift(DEC(ord(s[2])),-4) ), 8r0377) c2 := iand( ior( ishift(DEC(ord(s[2])),+4), ishift(DEC(ord(s[3])),-2) ), 8r0377) c3 := iand( ior( ishift(DEC(ord(s[3])),+6), DEC(ord(s[4])) ), 8r0377) if (n >= 1) then writes(f,char(c1)) if (n >= 2) then writes(f,char(c2)) if (n >= 3) then writes(f,char(c3)) end procedure DEC(c) # single character decode return iand(c - 32, 8r077) end