このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1247438792/574 
# [1] 授業単元:プログラミング序論演習 
# [2] 問題文(含コード&リンク): CUI上で動くメーラーを作れ 

:- op(850,fx,rm).
rm(File) :-
        concat_atom(['rm -f ',File],S),
        system(S),!.

% *** user: mail / 1 ***
mail(max) :-
        'メール数の確認'(N),
        mail(N),!.
mail(0) :-
        reconsult('listing/最終メール番号#1.pro'),
        'メール数の確認'(N),
        '最終メール番号'(N2),
        M is N2 - N,
        (
                M < 0,
                mail(M),
                retract('最終メール番号'(_)),
                asserta('最終メール番号'(N)),
                '最終メール番号の保存'
        ;
                M = 0
        ;
                M > 0,
                retract('最終メール番号'(_)),
                asserta('最終メール番号'(N)),
                '最終メール番号の保存'
        ),
        !.
mail(0) :-
        !.
mail(N) :-
        N < 0,
        !,
        'メール数の確認'(Max),
        rm tempmsg,
        abolish('受信先アドレス' / 1),
        reconsult('listing/最終メール番号#1.pro'),
        for(-1,M,N),
        open(tempmsg,append,Output),
        M2 is Max + M + 1,
        write(Output,'\n\n'),
        '返信入力表示'(Output,M2),
        close(Output),
        M = N,
        exists(tempmsg,read),
        cat tempmsg,
        '最終メール番号の保存',
        !.
mail(N) :-
        N > 0,
        rm tempmsg,
        rm tempmsg2,
        rm tempmsg3,
        myhostname(Myhostname),
        'メールを読む'(N),
        ! 'cat tempmsg | nkf -We',
        write('\n'),
        !.
mail(N) :-
        \+(N = 0),
        exists(tempmsg,read),
        ! 'cat tempmsg | nkf -We',
        write('\n'),
        !.

% *** user: mail10 / 1 ***
mail10(N) :-
        integer(N),
        N < 0,
        'メールの数を調べる'(Max),
        S is Max + N + 1,
        for(S,M,Max),
        write_formatted('\n#%t\n',[M]),
        mail10(M),
        M = Max,
        !.
mail10(S - E) :-
        for(S,N,E),
        write_formatted('\n#%t\n',[N]),
        mail10(N),
        N = E,
        !.
mail10(N) :-
        integer(N),
        \+(N = 0),
        N > 0,
        rm tempmsg,
        rm tempmsg2,
        rm tempmsg3,
        myhostname(Myhostname),
        'メールを読む'(N),
        shs('cat tempmsg | nkf -We',L),
        member(A,L,R2),
        subatomic(A,1,7,'Status:'),
        for(1,M,10),
        list_nth(M,R2,X),
        write_formatted('%t\n',[X]),
        M = 10,
        !.

% *** user: 'メール数の確認' / 2 ***
'メール数の確認'(_メールボックス,_メール数) :-
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        repeat,
        get_line(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メール数),
        \+(_メール数 = 'lock.'),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メール数の確認' / 1 ***
'メール数の確認'(_メール数) :-
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        repeat,
        stream_read(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メール数),
        \+(_メール数 = 'lock.'),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メールの数を調べる' / 1 ***
'メールの数を調べる'(_メールの数) :-
        'メールサーバ'(_メールサーバ),
        'クライアント通信確立'(_メールサーバ,110,_差し込み口),
        (
                error_protect('私書箱'(_私書箱),fail)
        ;
                \+(error_protect('私書箱'(_),fail)),
                _私書箱 = takao
        ),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        get_line(_入力,A),
        write_formatted(_出力,'USER %t\r\n',[_私書箱]),
        flush_output(_出力),
        'メールパスワードの送付'(_メールボックス,_入力,_出力),
        repeat,
        get_line(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メールの数),
        \+(_メールの数 = 'lock.'),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        ! .

% *** user: 'メールを読む' / 6 ***
'メールを読む'(_メールボックス,N,A,B,C,X) :-
        integer(N),
        N > 0,
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_メールボックス,_入力,_出力),
        'メールパスワードの送付'(_メールボックス,_入力,_出力),
        get_line(_入力,C),
        write_formatted(_出力,'RETR %t\r\n',[N]),
        flush_output(_出力),
        pop3_message_get(_入力,X),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        get_line(_入力,D),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.


% *** user: 'メールを読む' / 5 ***
'メールを読む'(L,A,B,C,X) :-
        list(L),
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        (
                error_protect('私書箱'(_私書箱),fail)
        ;
                \+(error_protect('私書箱'(_私書箱),fail)),
                _私書箱 = default
        ),
        open(_差し込み口,read,_入力,A),
        open(_差し込み口,write,_出力,B),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        get_line(_入力,C),
        (
                member(N,L),
                write_formatted(_出力,'RETR %t\r\n',[N]),
                flush_output(_出力),
                pop3_message_get(_入力,X),
                write(_出力,'QUIT\r\n'),
                flush_output(_出力),
                fail
        ;
                true
        ),
        get_line(_入力,D),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

'メールを読む'(N,A,B,C,X) :-
        integer(N),
        N > 0,
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,110,_差し込み口),
        (
                error_protect('私書箱'(_私書箱),fail)
        ;
                \+(error_protect('私書箱'(_私書箱),fail)),
                _私書箱 = default
        ),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        pop3_message_get(_入力,X),
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        get_line(_入力,D),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メールを読む' / 2 ***
'メールを読む'(N,X) :-
        var(X),
        integer(N),
        N =< 0,
        'メール数の確認'(_メール数),
        M is _メール数 + N + 1,
        'メールを読む'(M,_,_,_,X),
        concat_atom(X,'\n',_文),
        open(tempmsg,append,_出力2),
        write_formatted(_出力2,'%t',[_文]),
        flush_output(_出力2),
        close(_出力2),
        !.
'メールを読む'(N,FILE) :-
        \+(var(FILE)),
        integer(N),
        N =< 0,
        'メールサーバアドレス'(_メールサーバアドレス),
        'クライアント通信確立'(_メールサーバアドレス,110,_差し込み口),
        (
                FILE = '',
                tmpnam(FILE_1)
        ;
                \+(FILE = ''),
                FILE = FILE_1
        ),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールを読むの一'(N,FILE_1,_入力,_出力),
        close(_入力),
        close(_出力),
        socket_shutdown(_差し込み口),
        !.

% *** user: 'メールを読むの一' / 4 ***
'メールを読むの一'(N,FILE,_入力,_出力) :-
        'メールユーザ名の送付'(_入力,_出力),
        'メールパスワードの送付'(_入力,_出力),
        'メール数の取得'(_入力,_メール数),
        _限界数 is _メール数 + N + 1,
        'メールの取得'(_入力,_出力,FILE,_メール数,_限界数),
        'メールサーバを切り離す'(_入力,_出力),
        !.

% *** user: 'メールの取得' / 5 ***
'メールの取得'(_入力,_出力,FILE,Max,M) :-
        open(FILE,append,_出力2),
        write(_出力2,'\n'),
        for(Max,U,M),
        write_formatted(_出力,'RETR %t\r\n',[U]),
        flush_output(_出力),
        pop3_message_rw(_入力,_出力2),
        write(_出力2,'.\n'),
        U = M,
        write(_出力2,'\n'),
        close(_出力2),
        !.

% *** user: pop3_message_rw / 2 ***
pop3_message_rw(Input,Output) :-
        repeat,
        get_line(Input,S),
        replace_all(S,'\r','',S2),
        (
                subatomic(S,1,1,'.')
        ;
                S = end_of_file
        ;
                S2 = [],
                write(Output,'\n'),
                fail
        ;
                \+(S2 = []),
                write_formatted(Output,'%t\n',[S2]),
                fail
        ),!.

% *** user: pop3_message_get / 2 ***
pop3_message_get(A,B) :-
        findall(E,(repeat ,
                           get_line(A,C) ,
                           replace_all(C,'\r','',D) ,
                           (sub_atom(C,0,1,'.') , (!) , fail ;
                                C = end_of_file , (!) , fail ;
                                D = [] , E = '\n' ;
                                not D = [] , E = D)),B),!.

% *** user: 'メール数の取得' / 2 ***
'メール数の取得'(_入力,_メール数) :-
        get_line(_入力,C),
        split(C,[' '],L),
        list_nth(4,L,_メール数).

% *** user: 'メールパスワードの送付' / 3 ***
'メールパスワードの送付'(_メールボックス,_入力,_出力,B) :-
        メールパスワード(_メールボックス,_メールパスワード),
        get_line(_入力,B),
        write_formatted(_出力,'PASS %t\r\n',[_メールパスワード]),
        flush_output(_出力).

% *** user: 'メールパスワードの送付' / 2 ***
'メールパスワードの送付'(_入力,_出力) :-
        メールパスワード(_メールパスワード),
        get_line(_入力,B),
        write_formatted(_出力,'PASS %t\r\n',[_メールパスワード]),
        flush_output(_出力).

% *** user: 'メールユーザ名の送付' / 3 ***
'メールユーザ名の送付'(_メールボックス,_入力,_出力,A) :-
        メールユーザ(_メールボックス,_メールユーザ),
        get_line(_入力,A),
        write_formatted(_出力,'USER %t\r\n',[_メールボックス]),
        flush_output(_出力).

'メールユーザ名の送付'(_入力,_出力) :-
        メールユーザ(_メールユーザ),
        get_line(_入力,A),
        write_formatted(_出力,'USER %t\r\n',[_メールユーザ]),
        flush_output(_出力).

% *** user: 'メールサーバを切り離す' / 2 ***
'メールサーバを切り離す'(_入力,_出力) :-
        write(_出力,'QUIT\r\n'),
        flush_output(_出力),
        get_line(_入力,D),!.

smtp_iso(From,To,Subject,'文'(_文)) :-
        tmpnam(TMPNAM),
        tmpnam(TMPNAM2),
        open(TMPNAM,write,Output),
        write_formatted(Output,'%t\n',[_文]),
        close(Output),
        concat(['nkf -e -j ',TMPNAM,' >',TMPNAM2],S),
        system(S),
        smtp_iso(Input,Output,From,To,Subject,TMPNAM2,_診断),
        unlink(TMPNAM),
        unlink(TMPNAM2),!.
smtp_iso(From,To,Subject,File) :-
        \+(list(File)),
        tmpnam(TMPFILE),
        concat(['nkf -e -j ',File,' >',TMPFILE],S1),
        base64(Subject,Subject64),
        sprintf('=?iso-2022-jp?B?%t?=',[Subject64],MimeSubject),
        smtp_server(Host),
        smtp_iso(Host,From,To,MimeSubject,TMPFILE,_診断),
        unlink(TMPFILE),!.

smtp_iso(From,To,Subject,Files) :-
        list(Files),
        smtp_plus(Files,File1,Boundary),
        tmpnam(TMPFILE),
        concat(['cat ',File1,' | nkf -e -j >',TMPFILE],S1),
        base64(Subject,Subject64),
        sprintf('=?iso-2022-jp?B?%t?=',[Subject64],MimeSubject),
        smtp_server(Host),
        stmp_iso(Host,From,To,MimeSubject,TMPFILE,Boundary,_診断),!.

% *** user: smtp_iso / 2 ***
smtp_iso(To,(?- _質問)) :-
        tmpnam(TMPNAM),
        tell(TMPNAM),
        write_formatted('%q.\n',[(?- _質問)]),
        told,
        smtp_iso(To,'prolog@takao.ozaki.name','質問',TMPNAM),
        ! .

% *** user: smtp_iso / 6 ***
smtp_iso(_送信元,_送信先,MimeSubject,File,Data,_診断) :-
        'メールサーバー'(_メールサーバー),
        'クライアント通信確立'(_メールサーバー,38,_差し込み口),
        open(_差し込み口,read,_入力),
        open(_差し込み口,write,_出力),
        'メールユーザ名の送付'(_メールボックス,_入力,_出力),
        'メールパスワードの送付'(_メールボックス,_入力,_出力),
        send_helo(Input,Output,Domain),
        send_from_to(Input,Output,_送信元,_送信先),
        send_data(Input,Output,Subject,_送信元,_送信先,Data),
        send_quit(Input,Output),
        shutdown(_差し込み口),!.

send_helo(Input,Output,Domain) :-
        write_formatted(Output,'HELO %t\r\n',[Domain]),
        read(Input,_),
        write_formatted(Output,'EHLO %t\r\n',[Domain]),
        read(Input,_),!.

send_from_to(Input,Output,From,To) :-
        write_formatted(Output,'MAIL FROM: %t\r\n',[From]),
        stream_read(Input,_),
        write_formatted(Output,'RCPT TO: %t\r\n',[To]),
        stream_read(Input,_),!.

send_data(Input,Output,Subject,From,To,Data) :-
        write_formatted('DATA\r\n',[]),
        stream_read(Input,_),
        write_formatted(Output,'Subject: %t\r\nFrom: %t\r\nTo: %t\r\n\r\n',[Subject,From,To]),
        write_formatted(Output,'%t',[Data]),
        get_line(Input,_),!.

send_quit(Input,Output) :-
        write_formatted(Output,'QUIT\r\n'),
        get_line(Input,_),!.

% *** user: smtp_plus / 3 ***
smtp_plus(FileList,File,Boundary) :-
        FileList = [File1|R],
        tmpnam(A1),
        tmpnam(A2),
        tmpnam(A3),
        Boundary = '------------000402050407020604050408',
        smtp_plus_base64_encode(R,FileList2),
        tmpnam(File),
        tell(File),
        write('This is a multi-part message in MIME format.\n'),
        smtp_plus_1(Boundary,File1),
        smtp_plus_2(Boundary,FileList2,R),
        told,!.

% *** user: smtp_plus_1 / 2 ***
smtp_plus_1(Boundary,File) :-
        write_formatted('--%t\n',[Boundary]),
        write('Content-Type: text/plain; charset=EUC-JP\n'),
        write('Content-Transfer-Encoding: 8bit\n\n'),
        open(File,read,Fp),
        repeat,
        get_code(Fp,X),
        (
                X = -1
        ;
                name(Y,[X]),
                write_formatted('%t',[Y]),
                fail
        ),
        write('\n'),
        write('\n'),
        close(Fp),!.

% *** user: smtp_plus_2 / 3 ***
smtp_plus_2(Boundary,[],_) :-
        write_formatted('\n--%t--\n',[Boundary]),
        write('.\n\n'),!.
smtp_plus_2(Boundary,[File|R],[File_1|R2]) :-
        smtp_file_suffix(File,Suffix),
        smtp_file_mime(Suffix,Mime),
        write_formatted('\n--%t\n',[Boundary]),
        write_formatted('Content-Type: %t;\n',[Mime]),
        write_formatted(' name="%t"\n',[File_1]),
        write('Content-Transfer-Encoding: base64\n'),
        write('Content-Disposition: inline;\n'),
        write_formatted(' filename="%t"\n\n',[File_1]),
        open(File,read,Fp),
        repeat,
        get_code(Fp,X),
        (
                X = -1
        ;
                name(Y,[X]),
                write_formatted('%t',[Y]),
                fail
        ),
        close(Fp),
        smtp_plus_2(Boundary,R,R2).

% *** user: smtp_plus_2 / 2 ***
smtp_plus_2(_,[]) :-
        write('.\n\n'),!.
smtp_plus_2(Boundary,[File|R]) :-
        smtp_file_suffix(File,Suffix),
        smtp_file_mime(Suffix,Mime),
        write_formatted('--%t\n',[Boundary]),
        write_formatted('Content-Type: %t;\n',[Mime]),
        write_formatted(' name="%t"\n',[File]),
        write('Content-Transfer-Encoding: base64\n'),
        write('Content-Disposition: inline;\n'),
        write_formatted(' filename="%t"\n\n',[File]),
        open(File,read,Fp),
        repeat,
        get_code(Fp,X),
        (
                X = -1
        ;
                name(Y,[X]),
                write_formatted('%t',[Y]),
                fail
        ),
        close(Fp),
        write_formatted('\n--%t--\n',[Boundary]),
        smtp_plus_2(Boundary,R).

% *** user: smtp_plus / 2 ***
smtp_plus(FileList,File) :-
        FileList = [File1|R],
        tmpnam(A1),
        tmpnam(A2),
        tmpnam(A3),
        concat([--------------------,A1,A2,A3],AX),
        replace_all(AX,'/tmp/','',Boundary),
        smtp_plus_base64_encode(R,FileList2),
        tmpnam(File),
        tell(File),
        write('Content-Type: multipart/mixed;\n'),
        write_formatted(' boundary="%t"\n\n',[Boundary]),
        write('This is multi-part message in MIME format.\n'),
        smtp_plus_1(Boundary,File1),
        smtp_plus_2(Boundary,FileList2),
        told,
        !.

% *** user: smtp_file_mime / 2 ***
smtp_file_mime(jpg,'image/jpeg') :- !.
smtp_file_mime(jpeg,'image/jpeg') :- !.
smtp_file_mime(txt,'text/plain') :- !.
smtp_file_mime(xls,xls) :- !.
smtp_file_mime(csv,csv) :- !.
smtp_file_mime(html,'text/html') :- !.
smtp_file_mime(ps,'application/postscript') :- !.
smtp_file_mime(pdf,'application/postscript') :- !.
smtp_file_mime(_,'text/plain') :- !.

% *** user: smtp_file_suffix / 2 ***
smtp_file_suffix(File,Suffix) :-
        decompcons(File,L),
        (
                smtp_file_suffix_2(L,L2),
                concat(L2,Suffix)
        ;
                \+(smtp_file_suffix_2(L,_)),
                Suffix = txt
        ),!.

% *** user: smtp_file_suffix_2 / 2 ***
smtp_file_suffix_2(['.'|R],R) :- !.
smtp_file_suffix_2([_|R1],R2) :-
        smtp_file_suffix_2(R1,R2).

% *** user: smtp_plus_base64_encode / 2 ***
smtp_plus_base64_encode([],[]) :-!.
smtp_plus_base64_encode([File1|R1],[File2|R2]) :-
        base64_file_encode(File1,File2),
        smtp_plus_base64_encode(R1,R2).

% *** user: 'クライアント通信確立' / 3 ***
'クライアント通信確立'(_ホスト,_サービス,_差し込み口) :-
        '定数'(_サービス),
        !,
        net_service(_サービス,tcp,_舫),
        socket(internet,stream,_差し込み口),
        host_addr(_ホスト,Addr),
        socket_connect(_差し込み口,Addr : _舫).
'クライアント通信確立'(_ホスト,_舫,_差し込み口) :-
        '整数'(_舫),
        !,
        socket(internet,stream,_差し込み口),
        socket_connect(_差し込み口,_ホスト : _舫).

% *** user: get_line / 2 ***
get_line(Stream,S) :-
        error_protect(get_code(Stream,X_4),X_4 = -1),
        get_line_1(Stream,X_4,L_4,[]),
        atom_codes(S,L_4),
        ! .

get_line_1(Stream,10,[],[]) :- !.
get_line_1(Stream,10,L,L2) :-
        !,
        reverse(L2,L).
get_line_1(Stream,10,L_4,[13|L1_4]) :-
        !,
        reverse(L1_4,L_4).
get_line_1(Stream,31,L_4,L1_4) :-
        !,
        reverse(L1_4,L_4).
get_line_1(Stream,-1,L,[A|L1]) :-
        reverse([A|L1],L).
get_line_1(Stream,-1,[101,110,100,95,111,102,95,102,105,108,101],L2) :-
        !.
get_line_1(Stream,X_4,L_4,L1_4) :-
        error_protect(get_code(Stream,Y_4),Y_4 = -1),
        !,
        get_line_1(Stream,Y_4,L_4,[X_4|L1_4]).

base64g(Atom,X) :-
        replace_all(Atom,' ','',Atom2),
        base64(X,Atom2) .

base64s(Atom,X) :-
        \+(var(Atom)),
        name2(Atom,L1),
        base64_2(L1,Y),
        concat_atom(Y,X) .

base64(Atom,X) :-
        \+(var(Atom)),
        atom_codes(Atom,L1),
        kjtoeuc(CodeList,L1),
        base64_2(CodeList,Y),
        concat_atom(Y,X),!.
base64(X,Atom) :-
        var(X),
        atom_chars(Atom,List),
        base64_1(Y,List),
        concat_atom(Y,Y2),
        atom_codes(Y2,Codes),
        kjtoeuc(Codes,Y3),
        atom_codes(X,Y3),!.

base64_1([],[]) :- !.
base64_1(X,[A,B,C,=]) :-
        base64_table(A1,A),
        base64_table(B1,B),
        base64_table(C1,C),
        append(A1,B1,L1),
        append(L1,C1,L),
        base64_a2b(Y,L),
        base64_1(Z,R),
        append(Y,Z,X).
base64_1(X,[A,B,=,=]) :-
        base64_table(A1,A),
        base64_table(B1,B),
        append(A1,B1,L),
        base64_a2b(Y,L),
        base64_1(Z,R),
        append(Y,Z,X).
base64_1(X,[A,B,C,D|R]) :-
        base64_table(A1,A),
        base64_table(B1,B),
        base64_table(C1,C),
        base64_table(D1,D),
        append(A1,B1,L1),
        append(L1,C1,L2),
        append(L2,D1,L),
        base64_a2b(Y,L),
        base64_1(Z,R),
        append(Y,Z,X).

base64_table([0,0,0,0,0,0],'A').
base64_table([0,0,0,0,0,1],'B').
base64_table([0,0,0,0,1,0],'C').
base64_table([0,0,0,0,1,1],'D').
base64_table([0,0,0,1,0,0],'E').
base64_table([0,0,0,1,0,1],'F').
base64_table([0,0,0,1,1,0],'G').
base64_table([0,0,0,1,1,1],'H').
base64_table([0,0,1,0,0,0],'I').
base64_table([0,0,1,0,0,1],'J').
base64_table([0,0,1,0,1,0],'K').
base64_table([0,0,1,0,1,1],'L').
base64_table([0,0,1,1,0,0],'M').
base64_table([0,0,1,1,0,1],'N').
base64_table([0,0,1,1,1,0],'O').
base64_table([0,0,1,1,1,1],'P').
base64_table([0,1,0,0,0,0],'Q').
base64_table([0,1,0,0,0,1],'R').
base64_table([0,1,0,0,1,0],'S').
base64_table([0,1,0,0,1,1],'T').
base64_table([0,1,0,1,0,0],'U').
base64_table([0,1,0,1,0,1],'V').
base64_table([0,1,0,1,1,0],'W').
base64_table([0,1,0,1,1,1],'X').
base64_table([0,1,1,0,0,0],'Y').
base64_table([0,1,1,0,0,1],'Z').
base64_table([0,1,1,0,1,0],a).
base64_table([0,1,1,0,1,1],b).
base64_table([0,1,1,1,0,0],c).
base64_table([0,1,1,1,0,1],d).
base64_table([0,1,1,1,1,0],e).
base64_table([0,1,1,1,1,1],f).
base64_table([1,0,0,0,0,0],g).
base64_table([1,0,0,0,0,1],h).
base64_table([1,0,0,0,1,0],i).
base64_table([1,0,0,0,1,1],j).
base64_table([1,0,0,1,0,0],k).
base64_table([1,0,0,1,0,1],l).
base64_table([1,0,0,1,1,0],m).
base64_table([1,0,0,1,1,1],n).
base64_table([1,0,1,0,0,0],o).
base64_table([1,0,1,0,0,1],p).
base64_table([1,0,1,0,1,0],q).
base64_table([1,0,1,0,1,1],r).
base64_table([1,0,1,1,0,0],s).
base64_table([1,0,1,1,0,1],t).
base64_table([1,0,1,1,1,0],u).
base64_table([1,0,1,1,1,1],v).
base64_table([1,1,0,0,0,0],w).
base64_table([1,1,0,0,0,1],x).
base64_table([1,1,0,0,1,0],y).
base64_table([1,1,0,0,1,1],z).
base64_table([1,1,0,1,0,0],'0').
base64_table([1,1,0,1,0,1],'1').
base64_table([1,1,0,1,1,0],'2').
base64_table([1,1,0,1,1,1],'3').
base64_table([1,1,1,0,0,0],'4').
base64_table([1,1,1,0,0,1],'5').
base64_table([1,1,1,0,1,0],'6').
base64_table([1,1,1,0,1,1],'7').
base64_table([1,1,1,1,0,0],'8').
base64_table([1,1,1,1,0,1],'9').
base64_table([1,1,1,1,1,0],+).
base64_table([1,1,1,1,1,1],/).
base64_table([A,B,C,D],X) :-
        base64_table([A,B,C,D,0,0],X).
base64_table([A,B],X) :-
        base64_table([A,B,0,0,0,0],X).

base64_a2b([],[]).
base64_a2b([Atom|R],[A,B,C,D,E,F,G,H|R2]) :-
        atob(Atom,[A,B,C,D,E,F,G,H]),
        base64_a2b(R,R2).

base64_2([],[]) :- !.
base64_2([A,B,C|R],X) :-
        base64_i2b([A,B,C],L),
        base64_3(L,Z),
        base64_2(R,R2),
        append(Z,R2,X),!.
base64_2([A,B],X) :-
        base64_i2b([A,B],L),
        base64_3(L,Z),
        append(Z,[=],X),!.
base64_2([Y],X) :-
        base64_i2b([Y],L),
        base64_3(L,Z),
        append(Z,[=,=],X),!.

base64_3([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X],[Z1,Z2,Z3,Z4]) :-
        base64_table([A,B,C,D,E,F],Z1),
        base64_table([G,H,I,J,K,L],Z2),
        base64_table([M,N,O,P,Q,R],Z3),
        base64_table([S,T,U,V,W,X],Z4),!.
base64_3([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],[Z1,Z2,Z3]) :-
        base64_table([A,B,C,D,E,F],Z1),
        base64_table([G,H,I,J,K,L],Z2),
        base64_table([M,N,O,P],Z3),!.
base64_3([A,B,C,D,E,F,G,H],[Z1,Z2]) :-
        base64_table([A,B,C,D,E,F],Z1),
        base64_table([G,H],Z2).

base64_i2b([],[]) :- !.
base64_i2b([X|R],[1,B,C,D,E,F,G,H|R2]) :-
        var(X),
        itob(X,[1,B,C,D,E,F,G,H]),
        base64_i2b(R,R2),!.
base64_i2b([X|R],[0,B,C,D,E,F,G,H|R2]) :-
        var(X),
        itob(U,[0,B,C,D,E,F,G,H]),
        X is U - 128,
        base64_i2b(R,R2),!.
base64_i2b([Code|R],[A,B,C,D,E,F,G,H|R2]) :-
        itob(Code,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,A,B,C,D,E,F,G,H]),
        base64_i2b(R,R2) .

name2(X,Y) :-
        atom(X),
        strlen(X,Len),
        findall(N,(for(1,M,Len) , char_code1(X,M,N1) , (N1 < 0 , N is N1 + 256 ; N1 >= 0 , N = N1)),Y),!.
name2(A,[N]) :-
        atomic(A),
        name(A,[N]),!.
name2(A,L) :-
        var(A),
        name21(L,L2),
        atom_codes(A,L2),!.

name21([],[]) :- !.
name21([N1,N2|R],[N|R2]) :-
        N1 > 127,
        N2 > 127,
        N is N1 * 256 + N2,
        name21(R,R2),!.
name21([N1,N2|R],[N|R2]) :-
        N1 > 127,
        N2 < 128,
        N is N1 * 256 + N2,
        name21(R,R2),!.
name21([N1|R],[N1|R2]) :-
        name21(R,R2).

itob(N,L) :-
        itob(N,[],L1),
        length(L1,Len),
        Len2 is 8 - Len,
        length(L2,Len2),
        all(L2,0),
        append(L2,L1,L).

itob(0,X,X) :- !.
itob(N,Y,X) :-
        M is N mod 2,
        N2 is N // 2,
        itob(N2,[M|Y],X).