С момента одного из моих постов, несколько человек попросили показать пример утилитки (или исходника на Icon), так вот сейчас по заявкам граждан я покажу свою утилитку для кодирования файлов в UUE.
Зачем нужно такое кодирование ?
Ну, я - фидошник, и иногда мне приходиться отсылать файлы с помощью Фидонета, а как известно, многие узлы не пропускают через себя письма со вложенными в них файлами, и поэтому была изобретена такая хитрость : файл кодируется с помощью UUE-кодера и результат кодирования вставляется прямо в письмо. Здесь фишка в том, что результат UUE-кодирования состоит только из печатных символов, а именно это и необходимо для вставки файла в письмо.
Вообщем, написание программы кодирования в UUE-формат стало одним из первых моих серьезных экспериментов (поэтому собственно прошу программистов не пинать сильно) - и наглядно показало мне возможности Icon.
Ну,а теперь по просьбам трудящихся, я вставляю сюда код утилитки :
procedure main(argv)
local f,o,r,r2
# получаем первый аргумент (имя входного файла) и если оно не задано
# возвращаем ошибку
# также инициализируем строку-накопитель f
r:=argv[1]
if /r then stop("no 1th argument!")
f:=""
# получаем второй аргумент (имя выходного файла) и если оно не задано
# то берем текущую дату в качестве имени, а в качестве расширения
# ставим .uue (проводим преобразование строки с датой,заменяя в ней
# все символы / на _)
r2:=argv[2]
if /r2 then r2:=map(string(&date)||".uue","/","_")
# открытие входного и выходного файла
g:=open(r,"ru")
t:=open(r2,"cw")
# запись первой строки uue
z:="begin 644 uue"||r[((*r)-3)+:4]
write(t,z)
# запускаем процедуру преобразования в uue
# если строка f содержит 60 символов,то записываем
# ее с символом М впереди
# иначе записываем эту строку с другим символом,
# отражающим ее размер
while f:=f||(|rd(g)) do {
if *f=60 then {
write(t,"M"||f)
f:=""
}
}
if (*f~=0)&(*f<60) then {
o:=(((*f)*6)/8)+32
write(t,char(o)||f)
}
# запись конечной строки и символа защиты от повреждения
write(t,"`\n","end")
end
# перевод в двоичную систему,8-битный формат
procedure to_bin(x)
local r,s,n
n:=x
s:=""
while n>=1 do {
r:=n%2
s:=s||r
n:=integer(n/2)
}
s:=reverse(s)
while *s~=8 do {
s:="0"||s
}
return string(s)
end
# перевод двоичного числа в десятичное
procedure to_dec(d)
local b,i,v
b:=0
v:=reverse(d)
every i:=1 to *d do {
b:=b+((2^(i-1))*v[i])
}
return b
end
# преобразование трех байт в четверку из 6 битов
# и интерпретация их как символов ASCII
procedure rd(g)
local s,d,t,a1,a2,a3,a4,v
d:=""
v:=""
while s:=reads(g,3) do {
every t:=1 to *s do {
d:=d||to_bin(ord(s[t]))
}
while *d~=24 do {
d:=d||"0"
}
a1:=char(to_dec(d[1+:6])+32)
a2:=char(to_dec(d[7+:6])+32)
a3:=char(to_dec(d[13+:6])+32)
a4:=char(to_dec(d[19+:6])+32)
v:=a1||a2||a3||a4
return v
}
end
Сохраняем все это в файл uue.icn (*.icn - расширение файлов с исходными кодами программ на Icon) по возможности правим (лучше всего в jEdit, т.к как у него есть подсветка синтаксиса Icon) и затем запукаем на выполнение:
icont uue.icn -x входной_файл [выходной файл]
(в квадратных скобках я указал необязательный параметр. Т.е если путь к выходному файлу задан не будет, то в текущей директории после работы программы появится файла вида год_месяц_число.uue)
Вот собственно и все!)