home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: iiencode.icn
- #
- # Subject: Program to encode text in the style of uuencode
- #
- # Author: Richard L. Goerwitz
- #
- # Date: June 3, 1991
- #
- ###########################################################################
- #
- # Version: 1.8
- #
- ###########################################################################
- #
- # This is an Icon port of the UNIX/C uuencode utility. Since
- # uuencode is publicly distributable BSD code, I simply grabbed a
- # copy, and rewrote it in Icon. The only basic functional changes I
- # made to the program were: 1) To simplify the notion of file mode
- # (everything is encoded with 0644 permissions), and 2) to add sup-
- # port for xxencode format (which will generally pass unscathed even
- # through EBCDIC sites).
- #
- # Iiencode's usage is compatible with that of the UNIX uuencode
- # command, i.e. a first (optional) argument gives the name the file
- # to be encoded. If this is omitted, iiencode just uses the standard
- # input. The second argument specifies the name the encoded file
- # should be given when it is ultimately decoded.
- #
- # Extensions to the base uuencode command options include -x and -o.
- # An -x tells iiencode to use xxencode (rather than uuencode) format.
- # Option -o causes the following argument to be used as the file
- # iiencode is to write its output to (the default is &output). Note
- # that, on systems with newline translation (e.g. MS-DOS), the -o
- # argument should always be used.
- #
- # iiencode [infile] [-x] remote-filename [-o] output-filename
- #
- # 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). Note
- # that I followed the format of the newest BSD release, which refuses
- # to output spaces. If you want to change things back around so that
- # spaces are output, look for the string "BSD" in my comments, and
- # then (un)comment the appropriate sections of code.
- #
- ############################################################################
- #
- # See also: iidecode.icn
- #
- ############################################################################
-
-
- procedure main(a)
-
- local ofs, in_filename, out_filename, in, out, is_xx, remotename, usage
-
- usage := "usage: iiencode [infile] [-x] _
- remote-filename [-o output-filename]"
-
- # Parse arguments.
- ofs := 0
- while (ofs +:= 1) <= *a do {
- case a[ofs] of {
- "-x" : is_xx := 1
- "-o" : out_filename := a[ofs +:= 1] | stop(usage)
- default : {
- if not (/in_filename := a[ofs]) then
- remotename := a[ofs]
- }
- }
- }
-
- # If remotename is null, set it to in_filename. If it's still
- # null, then abort with usage message.
- if /(/remotename :=: in_filename) then {
- write(&errout,usage)
- exit(2)
- }
-
- # If no input filename was supplied, use &input.
- if /in_filename then
- /in := &input
- else
- in := open(in_filename) |
- stop(&errout,"Can't open input file, ",in_filename,".\n",usage)
-
- # If an output filename was specified, open it for writing.
- if \out_filename then
- out := open(out_filename, "wu") |
- stop("Can't open output file, ",out_filename,".\n",usage)
- # Set null out to &output; advise DOS users to use -o option.
- else {
- out := &output
- if find("MS-DOS",&features) then
- write(&errout, "Okay, but the -o option is recommended for DOS.")
- }
-
- # This generic version of uuencode treats file modes in a primitive
- # manner so as to be usable in a number of environments. Please
- # don't get fancy and change this unless you plan on keeping your
- # modified version on-site (or else modifying the code in such a
- # way as to avoid dependence on a specific operating system).
- writes(out, "begin 644 ",remotename,"\n")
-
- encode(out, in, is_xx)
- writes(out, "end\n")
-
- every close(in|out)
- exit(0)
-
- end
-
-
-
- procedure encode(out, in, is_xx)
-
- # Copy from in to standard output, encoding as you go along.
-
- local line
-
- if \is_xx then
- ENC := xxENC
-
- # 1 (up to) 45 character segment
- while line := reads(in, 45) do {
- writes(out, ENC(*line))
- line ? {
- while outdec(move(3), out)
- pos(0) | outdec(left(tab(0), 3, " "), out)
- }
- writes(out, "\n")
- }
- # Uuencode adds a space and newline here, which is decoded later
- # as a zero-length line (signals the end of the decoded text).
- # writes(" \n")
- # The new BSD code (compatible with the old) avoids outputting
- # spaces by writing a ` (see also how it handles ENC() below).
- if \is_xx
- then writes(out, "+\n")
- else writes(out, "`\n")
-
- end
-
-
-
- procedure outdec(s, out)
-
- # Output one group of 3 bytes (s) to standard output. This is one
- # case where C is actually more elegant than Icon. Note well!
-
- local c1, c2, c3, c4
-
- c1 := ishift(ord(s[1]),-2)
- c2 := ior(iand(ishift(ord(s[1]),+4), 8r060),
- iand(ishift(ord(s[2]),-4), 8r017))
- c3 := ior(iand(ishift(ord(s[2]),+2), 8r074),
- iand(ishift(ord(s[3]),-6), 8r003))
- c4 := iand(ord(s[3]),8r077)
- every writes(out, ENC(c1 | c2 | c3 | c4))
-
- return
-
- end
-
-
-
- procedure ENC(c)
-
- # ENC is the basic 1 character encoding procedure to make a char
- # printing.
-
- # New BSD code doesn't output spaces...
- return " " ~== char(iand(c, 8r077) + 32) | "`"
- # ...the way the old code does:
- # return char(iand(c, 8r077) + 32)
-
- end
-
-
-
- procedure xxENC(c)
-
- # ENC is the basic 1 character encoding procedure to make a char
- # printing.
-
- local k, ordval, oversizes
- static ordtbl
- initial {
- ordval := -1
- ordtbl := table()
- every k := !"+-0123456789ABCDEFGHIJKLMNOPQRST_
- UVWXYZabcdefghijklmnopqrstuvwxyz"
- do insert(ordtbl, ordval +:= 1, k)
- oversizes := 0
- }
-
- # Table lookup isn't the fastest ever, I know. If I thought about
- # it a bit longer, I'm sure I could do this using map. This would
- # require some type conversions, but I wonder whether it would still
- # be substantially faster. If anyone tries this out and times the
- # results, please communicate to me the results!
- return ordtbl[iand(c, 8r077)]
-
- end
-