home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
ipl
/
progs
/
iiencode.icn
< prev
next >
Wrap
Text File
|
2001-05-02
|
7KB
|
218 lines
############################################################################
#
# File: iiencode.icn
#
# Subject: Program to encode text in the style of uuencode
#
# Author: Richard L. Goerwitz, enhanced by Frank J. Lhota
#
# Date: May 2, 2001
#
###########################################################################
#
# This file is in the public domain.
#
############################################################################
#
# Version: 2.0
#
###########################################################################
#
# 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]
#
#
# FIXES: Speeded up substantially (more than twice as fast on my
# machine) by using a more icon-ish algorithm. We encode in two
# steps:
#
# 1) We first "unpack" the bytes by taking groups of 3 bytes (24
# bits) and spreading them out by inserting two 0 bits before
# every block of 6 bits. The result is that each group of 3
# bytes is unpacked to 4 "small bytes", each <<= "\x3F".
# 2) The unpacked bytes are mapped to the coded line by using the
# Icon map function.
#
# There are numerous advantages to this approach. The Icon map
# function is much faster than the 'C'-ish alternatives. We can
# process the file one line at a time. Also, the different encoding
# mechanisms (old BSD, new BSD, xxencode) can be produces by simply
# using different map parameters.
#
############################################################################
#
# See also: iidecode.icn
#
############################################################################
link options
procedure main ( a )
local in_filename, out_filename, in, out, is_xx, remotename, opt
# Parse arguments.
opt := options ( a, "-o:-x", Usage )
is_xx := opt [ "x" ]
out_filename := opt [ "o" ]
case *a of {
1 :
in_filename := remotename := a [ 1 ]
2 :
{
in_filename := a [ 1 ]
remotename := a [ 2 ]
}
default :
Usage ( "", write, 2 )
}
# If no input filename was supplied, use &input.
if /in_filename then
in := &input
else
in := open ( in_filename, "ru" ) |
Usage ( "Can't open input file " || in_filename || "." )
# If an output filename was specified, open it for writing.
if /out_filename then
out := &output
else
out := open ( out_filename, "w" ) |
Usage ( "Can't open output file " || out_filename || "." )
# 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).
write ( out, "begin 644 ", remotename )
encode ( out, in, is_xx )
write ( out, "end" )
every close ( ( &input ~=== in ) | ( &output ~=== out ) )
exit ( 0 )
end
###########################################################################
#
# Writes msg and the Usage line to &errout using the output procedure Show,
# which defaults to stop. If Show does not stop processing and \errcode,
# exit with errcode.
#
###########################################################################
procedure Usage ( msg, Show, errcode )
static usage
initial usage := "usage: iiencode [infile] [-x] _
remote-filename [-o output-filename]"
/Show := stop
Show ( &errout, msg, "\n", usage )
exit ( \errcode )
return msg
end
###########################################################################
#
# Reads all of file in, encodes it, and writes the encoded lines to out.
# "uu" encoding is used unless \is_xx, in which case "xx" encoding is used.
#
###########################################################################
procedure encode ( out, in, is_xx )
# Copy from in to out, encoding as you go along.
local line, coded
static unpacked
initial unpacked := "_
\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F_
\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F_
\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F_
\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
if \is_xx then {
coded := "_
+-0123456789ABCD_
EFGHIJKLMNOPQRST_
UVWXYZabcdefghij_
klmnopqrstuvwxyz"
}
else {
#
# To get the BSD old code, replace the next 2 lines with:
# coded := " _
# !\"#$%&'()*+,-./_
#
coded := "_
`!\"#$%&'()*+,-./_
0123456789:;<=>?_
@ABCDEFGHIJKLMNO_
PQRSTUVWXYZ[\\]^_"
}
# 1 (up to) 45 character segment
while line := reads ( in, 45 ) do {
write ( out,
map ( char ( *line ) || unpack ( line ), unpacked, coded )
)
}
# Output a zero-length line.
write ( out, coded [ 1 ] )
end
###########################################################################
#
# Takes groups of 3 bytes in s and expands the groups to 4 bytes. Each
# byte in the unpacked group has 2 zero high bits, i.e. is <<= "\x3F".
# If *s is not divisible by 3, we pad s with blanks on the right
# to make up the last group.
#
###########################################################################
procedure unpack ( s )
local n, grp
s ? {
s := ""
while grp := ( move ( 3 ) | left ( "" ~== tab ( 0 ), 3 ) ) do
{
n := 0
grp ? while n := ord ( move ( 1 ) ) + ( n * 16r100 )
s ||:=
char ( ishift ( iand ( n, 16rFC0000 ), -18 ) ) ||
char ( ishift ( iand ( n, 16r03F000 ), -12 ) ) ||
char ( ishift ( iand ( n, 16r000FC0 ), - 6 ) ) ||
char ( iand ( n, 16r00003F ) )
}
}
return s
end