С момента одного из моих постов, несколько человек попросили показать пример утилитки (или исходника на 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)
Пример вывода программы (UUE):
begin 644 50px-Yozh.jpg M_]C_X 02D9)1@ ! 0$ 2 !( #_VP!# 8$!08%! 8&!08'!P8("A *"@D) M"A0.#PP0%Q08&!<4%A8:'24?&ALC'!86("P@(R8G*2HI&1\M,"TH,"4H*2C_ MVP!# 0<'!PH("A,*"A,H&A8:*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H M*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"C_P 1" P #(# 2( A$! Q$!_begin 644 50px-Yozh.jpg M_]C_X 02D9)1@ ! 0$ 2 !( #_VP!# 8$!08%! 8&!08'!P8("A *"@D) M"A0.#PP0%Q08&!<4%A8:'24?&ALC'!86("P@(R8G*2HI&1\M,"TH,"4H*2C_ MVP!# 0<'!PH("A,*"A,H&A8:*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H M*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"C_P 1" P #(# 2( A$! Q$!_\0 M&P @(# 0 !P@ !@,$!0+_Q T$ " 0,# @4# 08' M ! @,$!1$ !B$2,0<405%A$R)Q%18C,D*Q\"5#4I'!T=+_Q 8 0$! 0$! M # @ !!/_$ " 1 (" @(" P ! A$#$B$B M!#%1-TEG.W(9X+K5B))(DPP7 ,AE*X7V ZAP!W.JI%X# M;WN-9YJ]54;5;J"[RR_4)QP!GOG&-1B4YMPQ"'Z;?<"70'." M&P @(# 0 !P@ !@,$!0+_Q T$ " 0,# @4# 08' M ! @,$!1$ !B$2,0<405%A$R)Q%18C,D*Q\"5#4I'!T=+_Q 8 0$! 0$! M # @ !!/_$ " 1 (" @(" P ! A$#$B$B M!#%1-TEG.W(9X+K5B))(DPP7 ,AE*X7V ZAP!W.JI%X# M;WN-9YJ]54;5;J"[RR_4)QP!GOG&-1B4Y MPQ"'Z;?<"70'." Вот собственно и все 🙂
UPD: К сожалению, я больше уже не фидошник 🙁