Calculate🐧Forum

Простой UUE-кодер

#1

С момента одного из моих постов, несколько человек попросили показать пример утилитки (или исходника на 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)

Вот собственно и все!)

Mastodon Mastodon