Rev.01 1997/11/24 風つかい ■ Icon > Icon散歩道 はじめに 風つかい Iconは アリゾナ大学の Ralph E Griswold教授のグループによって開発されてい るテキスト処理言語です。 Iconは テキスト解析に 威力を発揮する 豊富なデータ構造と 強力な制御構造を を備えています。 英語の国で開発されている言語ですが、日本語の処理も不自由 しませんし、もっともっと使われてよい言語と思います。 しかし、未だ 日本語の入門書が ありませんので、 AWKについて、ある程度の 知識を お持ちになっている方を 対象として、入門講座を書きました。 ・テキスト解析言語Icon入門講座 ---AWKerのための Icon入門--- ・Icon日記 ---テキスト解析言語Icon入門講座2--- ・Icon雑記帳 ---テキスト解析言語Icon入門講座3--- この Icon散歩道は その続編として、その後 作ったプログラムや 前の 講座で 書き落とした ものを、まとめたものです。 前の 3編の講座と いっしょに ご覧になって Iconを使って頂けると うれしい です。 Iconのプログラムおよびライブラリーは、次の所から 入手できます。 http://www.cs.arizona.edu/icon/index.html この講座は、主に PCVANのPIGのテキストデータ処理会議室にアップロードした ものに加筆・修正を行ったものです。 Iconは PDSですので、この入門講座も同じ扱いとします。(転載・編集自由) (This textbook is in the public domain.) 目次 はじめに (1) 再び構造体 tree表示(1) (2) suspend...do... (3) 再び5クイーン (4) 再び構造体 tree表示(2) (5) 再び構造体 tree表示(3) (6) 再び wild.icn(1) (7) 再び wild.icn(2) (8) 再び dir2tree (9) 再び x2tree(1) (10) 再び x2tree(2) (11) Icon迷い道 (1)system() (12) Icon迷い道 (2)download数 集計 (13) Icon迷い道 (3)CSV:定義ファイルの読込 (14) Icon迷い道 (4)CSV:定義ファイルの解析 (15) Icon迷い道 (5)CSV:拡張子変更(1) (16) Icon迷い道 (6)CSV:拡張子変更(2) (17) Icon迷い道 (7)CSV:CSV2TB (18) Icon迷い道 (8)CSV:TB2CSV (19) ちょっと Icon(1)data整形(1) (20) ちょっと Icon(2)data整形(2) (21) ちょっと Icon(3)data整形(3) (22) ちょっと Icon(4)data整形(4) (23) Icon回り道 (1)重複しないランダムな10個の数(1) (24) Icon回り道 (2)重複しないランダムな10個の数(2) (25) Icon回り道 (3)重複しないランダムな10個の数(3) (26) Icon回り道 (4)Usageが... (27) Icon回り道 (5)a < b が、値を持つ (28) ちょっと Icon(5)Wicon beta8 (29) ちょっと Icon(6)Icon Newsletter No.53 (30) ちょっと Icon(7)Icon Ver.9.3(Windows95/NT) むすび 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> BGM: 愛の言霊/サザン・オールスターズ (iconlec4.txt 1997/11/24) ■ Icon > Icon散歩道(1) 再び 構造体tree表示(1)風つかい Icon雑記帳 に引き続き、Icon迷い道 じゃなかった Icon散歩道 を始めます。 今回こそは、テキスト解析らしい programを作ってみたいと思います。 テキスト解析といっても、 ・簡単な数式解析 と ・簡単なアセンブラ あたり を目標にしています。 と、思っていたのですが、Icon雑記帳を読み返していたら、う〜む。ミスが 見つかりました。 その修正から始めます。 Icon入門講座をやっていまして、アップロードする原稿や programは、その前 に、チェックしている つもりなのですが、大抵 1つや 2つのミスが 含まれて います。 しかし、気がつくのは、大抵、アップロードした後に、自分のメッセージを 読みだしコマンドで、読んだ時です。 もう手遅れのタイミングです。 アップロードするまでは、若干緊張しています。 それが終わった後に、少し ホッとした気分で、自分のメッセージを読み返す訳なのですが、 そういう時に 自分のミスが見つかります。別の自分にならないと、見つからないみたいです。 書いた後に、1日位 寝かせておいて、その後に もう1回チェックすると良い のですが、こらえ性が無くて。 修行が足りないな〜。 と、言うわけで、Icon雑記帳(19)の x2tree03.icnの修正版です。 内容は、コメントに書き込んでありますので、ご覧下さい。 -----^ X2TREE05.ICN ( date:97-05-06 time:01:17 ) -----------" #↑listの serial No suspend " " || x2tree(x,"") #↑初期化フラグ end procedure x2tree(x,init) # generator # show the tree structure of x static T # serial No 登録用 set登録用 table static宣言を して # おかないと、再帰したときに、未定義 errorとなる。 if \init then { # Rev.1.2 T := table() T["list"] := set() # ここは、table(set())とすると、全て同じ setが T["set"] := set() # 割り当てられてしまうので、個別に初期化する。 T["table"] := set() if (t := type(x)) == ("list" | "set" | "table") then insert(T[t],serial(x)) # serial Noを T[type(x)]に登録 } n := *x # 枝の末端検出用カウンタ every xx := !x do { # 構造体の要素を1つ づつ取り出す n -:= 1 case t := type(xx) of { # 構造体のタイプにより、 "string" : suspend "+ " || left(t,7) || " " || jimage(xx) #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m := serial(xx)) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend "+ <" || t || " " || string(m) || ">" suspend (if n > 0 then "| " else " ") || x2tree(xx) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return "+ <" || t || " " || string(m) || "> (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend "+ " || left(t,7) || " " || image(xx) } } end # test driver procedure main() #listの test L1 := ["A","B"] L2 := ["C","D"] L3 := ["E","F"] put(L1,L2) put(L2,L3) put(L1,L3) # 別枝 test put(L3,L1) # listの再帰 every write(x2t(L1) \20) # \20は、テストをドジッた時に、20個で止めるため。 write() #tableの test T := table() T["A"] := "G" T["C"] := L2[1] T["E"] := L3 T[L1] := L1[1] put(L3,T) # tableの再帰 every write(x2t(T) \20) write() #setの test L4 := ["H","I"] S1 := set(["L","M"]) S := set(["J","K",L4]) insert(S,S1) insert(S1,S) # setの再帰 every write(x2t(S) \20) end -----$ X2TREE05.ICN ( lines:98 words:380 ) ----------------- + string "A" + string "B" + | + string "C" | + string "D" | + | + string "E" | + string "F" | + (Recursion) + + string "E" + string "F" + (Recursion) + string "C" + | + string "E" | + string "F" | + | | + string "A" | | + string "B" | | + | | | + string "C" | | | + string "D" | | | + (Recursion) | | + (Recursion) | +
(Recursion) + string "A" + string "G" + string "K" + | + string "M" | + string "L" | + (Recursion) + | + string "H" | + string "I" + string "J" -----$ X2TREE05 ( lines:42 words:155 ) --------------------- BGM: Goodbye Day /来生たかお (icon_301.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(2) suspend...do... 風つかい 前回、Icon雑記帳(19)で取り上げた x2tree03.icnのミスを 修正しました が、私は、どうも suspend...do...の構文が、理解できていない と思います。 そこで、動作確認の実験 programを作ってみました。 こういう構成の programです。 main() test_a() test_b() ------------------ ------------------ ------------------ | main() | | | | | | every test_a() <--- suspend...test_b() <--- suspend... | | | | do... | | do... | ----------------- ------------------ ------------------ 実験 programです。 -----^ DO_01.ICN ( date:97-05-04 time:23:28 ) -------------- BGM: いとおしいグレイ/篠原美也子 (icon_302.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(3) 再び 5クイーン 風つかい 前回 suspend...do...の構文 の動作確認を 行いましたが、他の programでも 誤解して 使っているところが 無いかと、探しました。 Icon日記の 5-Queensの programでも、Queenの置き直しのところで、使ってい ます。 ここは、特に do...を使う必要は、ありませんね。 -----^ 5QUEEN1D.ICN ( date:97-05-04 time:20:02 ) ----------- BGM: いとおしいグレイ/篠原美也子 (icon_303.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(4) 再び 構造体tree表示(2)風つかい Icon散歩道(1)で、x2tree03.icnの ミス修正版を 説明しましたが、どうし て ミスに気がついたか というと、実は、Version Upをしようと、思いまして、 テスト・ケースを増やしてみて、気がつきました。 今回は、その Version Upです。 Iconの tableは、AWKでいう 連想配列です。 tableは、key と valueを持っています。 前の programでは、valueしか表示し ません。 x2treeは、programの動作確認 のための toolとして作りましたが、 tableでは、value表示だけでなく、key表示も欲しい! ということで、key表示を追加します。 尚、Iconでは、keyにも 構造体(list,set,table)が、使えます。 しかし、keyに 構造体を使っても、そちらは tree表示はしません。 (そんな 複雑 tree表示は、思いつかないよ〜。) -----^ X2TREE06.ICN ( date:97-05-05 time:03:26 ) -----------" #↑listの serial No suspend " " || x2tree(x,"") #↑初期化フラグ end procedure x2tree(x,init) # generator # show the tree structure of x static T # serial No 登録用 set登録用 table static宣言を して # おかないと、再帰したときに、未定義 errorとなる。 if \init then { # 初期化を initialでやると、同じ program内で別の # 構造体 tree表示のために、再び x2tを 呼んだ時に # 実行されなくて状態が残るので、フラグで初期化指示 T := table() T["list"] := set() # ここは、table(set())とすると、全て同じ setが T["set"] := set() # 割り当てられてしまうので、個別に初期化する。 T["table"] := set() if (t := type(x)) == ("list" | "set" | "table") then insert(T[t],serial(x)) # serial Noを T[type(x)]に登録 } n := *x # 枝の末端検出用カウンタ if (tt := type(x)) ~== "table" then { # not table every xx := !x do { # 構造体の要素を1つ づつ取り出す n -:= 1 t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) case t of { # 構造体のタイプにより、 "string" : suspend val_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp suspend (if n > 0 then "| " else " ") || x2tree(xx) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp } } } else { # table every xkey := key(x) do { # tableの keyを1つ づつ取り出す n -:= 1 tk := type(xkey) xx := x[xkey] t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) key_disp := if tk == ("list" | "set" | "table") then " <- <" || tk || " " || string(serial(xkey)) || ">" else " <- " || left(tk,7) || jimage(xkey) case t of { # 構造体のタイプにより、 "string" : suspend val_disp || key_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp || key_disp suspend (if n > 0 then "| " else " ") || x2tree(xx) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || key_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp || key_disp } } } end # test driver procedure main() #listの test L1 := ["A","B"] L2 := ["C","D"] L3 := ["E","F"] put(L1,L2) put(L2,L3) put(L1,L3) # 別枝 test put(L3,L1) # listの再帰 every write(x2t(L1) \20) # \20は、テストをドジッた時に、20個で止めるため。 write() #tableの test T := table() T["A"] := "G" T["C"] := L2[1] T["E"] := L3 T[L1] := L1[1] put(L3,T) # tableの再帰 every write(x2t(T) \20) write() #setの test L4 := ["H","I"] S1 := set(["L","M"]) S := set(["J","K",L4]) insert(S,S1) insert(S1,S) # setの再帰 every write(x2t(S) \20) end -----$ X2TREE06.ICN ( lines:133 words:507 ) ---------------- BGM: いとおしいグレイ/篠原美也子 (icon_304.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(5) 再び 構造体tree表示(3)風つかい x2treeに、tableの key表示を追加した programの動作結果です。 tableの部分が、若干、混みあった表示になりますが、test toolですので、 まあ、いんじゃない。 と、納得しましょう。 -----^ X2TREE06 ( date:97-05-05 time:03:26 ) --------------- + string "A" + string "B" + | + string "C" | + string "D" | + | + string "E" | + string "F" | + (Recursion) + + string "E" + string "F" + (Recursion)
+ string "C" <- string "C" + <- string "E" | + string "E" | + string "F" | + | | + string "A" | | + string "B" | | + | | | + string "C" | | | + string "D" | | | + (Recursion) | | + (Recursion) | +
(Recursion) + string "A" <- + string "G" <- string "A" + string "K" + | + string "H" | + string "I" + | + string "M" | + string "L" | + (Recursion) + string "J" -----$ X2TREE06 ( lines:42 words:167 ) --------------------- BGM: そのままの君でいて/岡本真夜 (icon_305.txt 1997/05/05 PCVAN PIG) ■ Icon > Icon散歩道(6) 再び wild.icn(1) 風つかい 近ごろ、"再び" というタイトルが多いですね〜。う〜む。以前の講座のミス が、みつかるのが多いな〜。 ということで、今回は Icon入門講座(16)で 作った wild.icnの修正版で す。 Iconの Program 例えば、abcd.icnを compileして、動かした結果のfile名を 以前は、abcd.txtとしていたんですが、txtの拡張子をつけるのも面倒というこ とで、近ごろは、ただ abcdとしています。 これを、YAB形式にしようと、IYAB(Icon入門講座(18))を動かすとどうも 結果がオカシくなります。 調べてみますと、IYABは、拡張子無しの file名を指定するとおかしくなりま す。 更に調べると、iyab.icnは、wild.icnを linkしていますが、wild.icnで既に オカシイ。 あれれ、wild.icnは、拡張子なしの file名の手当をしていたはず だか??? と、思って、良くみると、あれま、ミスコーディング をしていま す。 if not upto('.',line) then line ||= "." というミスをやらかしていました。 つう、ことで、修正版です。 -----^ WILD.ICN ( date:97-05-10 time:00:42 ) --------------->" || tmp) # "dir"発行 } close(dir) } default : { # file指定 if not upto('.',arg) then arg ||:= "." # Rev.1.4 system("dir " || arg || " >>" || tmp) # "dir"発行 } } # end of case } # end of every } # end of else dir := open(tmp) | stop("cannot open " || tmp) # fileオープン # "dir" の結果格納 fileから、file指定部分を 抜き出して listへ。 while line := read(dir) do # tmp fileから1行づつ読込。 put(fn_list,dir2lst(line)) # file情報を抜き出して、 # listへ格納 close(dir) remove(tmp) # 証拠隠滅 #################### # command解析終了 #################### if *fn_list = 0 then fail # 該当 file無し else return fn_list end -----$ WILD.ICN ( lines:65 words:298 ) --------------------- wild.rst # Rev.1.2 1997/05/05 windy 拡張子無しのテストケース追加 # Rev.1.1 1996/12/01 windy # This file is in the public domain. link wild, show_l procedure main() write("test for wild.icn\n") # "abc" という名前のファイルは存在しないこと。 write((L := ["abc"])[1]) show_wl(wild(L)) | write(L[1],"は見つからない。\n") # wild card write((L := ["*.*"])[1]) show_wl(wild(L)) write((L := ["*.icn"])[1]) show_wl(wild(L)) write((L := ["wi*.*"])[1]) show_wl(wild(L)) # response file write((L := ["@WILD_FL.DAT"])[1]) show_wl(wild(L)) # 複数指定 every writes(" ",!(L := ["*.icn","*.dat"])) ; write() show_wl(wild(L)) # "AAA", "AAA.TXT" の 2つの fileを用意しておくこと。 every writes(" ",!(L := ["AAA"])) ; write() # 追加 Rev.1.2 show_wl(wild(L)) write((L := ["wild~.*"])[1]) show_wl(wild(L)) end -----$ WILD~.ICN ( lines:39 words:102 ) -------------------- BGM: 河よりも長くゆるやかに/篠原美也子 (icon_306.txt 1997/05/10 PCVAN PIG) ■ Icon > Icon散歩道(7) 再び wild.icn(2) 風つかい PIG広場の方で、fileの名前と拡張子を 入れ換える 話題が 出ています。 そのネタをいただいて、Iconでやったらということで、programを 作ってみま した。 Iconには、fileの rename関数があります。 wild.icnで、該当 fileを 探して rename関数で、renameするという programです。 この programでは、log.* ファイルの拡張子とファイル名を入れ換え、その後 もう1度、入れ換えて、元に戻しています。 -----^ REN01.ICN ( date:97-05-10 time:00:37 ) --------------拡張子") every LL := !L do { s := top_cut("\\",LL[1]) # 現file名から directory部を 削除 # ↑file名 LLL := split(s,".") # file名を "."で分割して listへ write(s," -> ",s2 := LLL[2] || "." || LLL[1]) # 動作モニター #↑拡張子 ↑file名 rename(s,s2) # rename } return end -----$ REN01.ICN ( lines:28 words:109 ) --------------------拡張子 LOG.97 -> 97.LOG LOG.95 -> 95.LOG LOG.96 -> 96.LOG file名<->拡張子 95.LOG -> LOG.95 96.LOG -> LOG.96 97.LOG -> LOG.97 -----$ REN01 ( lines:10 words:20 ) ------------------------- BGM: 河よりも長くゆるやかに/篠原美也子 (icon_307.txt 1997/05/10 PCVAN PIG) ■ Icon > Icon散歩道(8) 再び dir2tree 風つかい ミスが多い と言いつつ、相変わらず、やっていますね〜。 再び wild.icn(7)-> 再び wild.icn(2) ですね。 (このテキストでは直っています。) ところで、Icon入門講座シリーズを、アリゾナ大学の Icon-WEBに 置いて頂く ように、Icon入門講座 (ICON_LEC.LZH)と Icon日記 (ICONLEC2.LZH) の fileを Icon Projectに、送ってお願いしていたんですが、置いて頂けました。場所は、 ftp://ftp.cs.arizona.edu/icon/contrib/Japanese/ です。 /icon/contrib/ は 寄贈 program (contribution)の directoryです。 ここに、Japaneseという directoryを作っていただきました。 英文なら E-mailか FTPで、送ればいいんですが、日本語の SHIFT-JISの file ですので、printしたものと、FDを送ってみました。 とても、全文を英訳する力は、ありませんので、 「 printed materialの programの部分で 内容は 想像して下さい。」 と お願いした文章を、四苦八苦して 書きました。(汗) 近ごろ、カタカナ部分を なるべく 英語で書いていますが それは Icon Project で、内容を 想像しやすいように ということで、やっています。(あはは) 内容は、こちらにアップしたものと 殆ど同じです。(その後 みつかった文章 や綴り(特に英語)の誤記を多少 修正しています。program自体は同じです。) さて、今回は、Icon雑記帳(20)〜(22)で、やりました dir2tree の修 正です。 dir2treeは、私のHDDの Icon関係 directoryの中の sub-directoryで test しました。 で 先日、Icon雑記帳の fileを、Icon-Projectの送ろうと そのFD の directory treeを、表示しようとしましたら、programが、コケました。 root directoryじゃ、動かなひ〜。 dir /s の command を 実行したときに、 ・root directoryでは A:\とか directory名称の後ろに、\ が、つきますが ・sub-directoryでは、つきません。 \ がつく caseの手当を忘れていました。つうことで、その点を修正しました。 -----^ D2TREE.ICN ( date:97-05-10 time:00:48 ) ------------- 0 then args[1] else "" tmp := "$$$tmp.$$$" # テンポラリファイル名設定 # ↓環境変数に、テンポラリーディレクトリ名が、設定してあればファイル名 # の前に追加 if s := getenv("TMP") then tmp := s || "\\" || tmp # コマンドラインの ディレクトリー名指定 をもとに、"dir /s" コマンド を # 発行して tmpへ出力 system("dir /s " || dir_name || " >" || tmp) # directory data sample ↓こんなデータが tmpに格納されます。 #1 16 #ディレクトリは D:\ICON\LEC24\TEST_A # #. 97-04-29 21:51 . #.. 97-04-29 21:51 .. #TEST_B 97-04-29 21:52 TEST_B #BBB TXT 10 97-04-29 21:56 BBB.TXT #TEST_CCC TXT 15 97-04-29 21:57 TEST_CCC.TXT #TEST_C 97-04-29 21:55 TEST_C #AAA 6 97-04-29 21:56 AAA # 3 個 31 バイトのファイルがあります # #一覧のファイル総数: ###################### # dir /s (dir_name)結果から、directory毎の情報を listへ 登録 ###################### dir := open(tmp) | stop("cannot open " || tmp) # tmpファイルオープン L_dir := [] # directory情報登録用 list T_dir := table() # sub-directory list参照 table while line := read(dir) do { # directory情報を directory毎に、一旦 list(LL)にまとめて、登録する。 line ? { #↓listにまとめた directory情報を登録 if find("個") then put(\T_dir[c_dir] | L_dir,LL) #↑tableに c_dirが存在すれば if match(" ") then next # ごみ行を無視 if match("一") then break # "一覧の..."が来たら終わり L := p_split() # lineを " "で分割→[1]:開始位置 # [2]:要素 #↓lineの1番目の要素 case L[1][2] of { "ディレクトリは" : { LL := [] # directory data buffer # ↓lineの2番目の要素の開始位置 if line[-1] == "\\" then c_dir := line[L[2][1] : -1] # root対応 else c_dir := line[L[2][1] : 0] # put(LL,[c_dir]) #↑listにして LLに追加 } "." : next # 無視 ".." : put(LL[1],line) # その directory自身の情報。 # トップの directory以外では必要 # ないが、全てにつき格納 default : { if find("") # sub-directoryだったら then { put(LL,LLL := [line]) # 内容を bufferに追加 insert(T_dir,c_dir || "\\" || L[1][2] ,LLL) # ↑sub-directory名称を keyにして tableへ登録 } else put(LL,line) # 通常 fileならそのまま追加 } } # end of case } # end of line ? } # end of while close(dir) remove(tmp) # delete tmp ####################### # directory情報の表示 ####################### # every write(x2t(L_dir) \25) # list 内容確認用表示 # every write(x2t(T_dir) \25) # table内容確認用表示 # stop() every write(d2t(L_dir)) end ######################## # directory tree表示 ######################## procedure d2t(L) # top directoryの名前/time_stamp処理 L1 := get(L) # Lには1個しか要素が無い。それを取り出す。 L2 := get(L1) # そのまた top (directory_name,time_stamp)を取り出す。 dir_top := L2[2][14:-3] | "\\ " # top directoryの名前と time stamp ↓root directory対応 suspend L2[1] || dir_top suspend " " || d2tree(L1) # tree化処理 # ↑tree書出し初期位置 end procedure d2tree(L) # directoryの処理 # show the tree structure of directory n := *L # Lの size(末尾要素検出用) every LL := !L do { # listの要素を1つづつ取り出す n -:= 1 # 要素カウンタ−1 case t := type(LL) of { # 要素の typeにより、 "string" : suspend "+ " || LL # file "list" : { # sub-directory suspend "+ " || get(LL) # sub-directory自体表示 LLL := get(LL) # sub-directoryの中身を取り出し get(LLL) # 先頭要素を読み飛ばし #↓最後の要素でないなら suspend (if n > 0 then "| " else " ") || d2tree(LLL) } default : stop("error") } } end ######################## # stringを cを区切りにして分割して、開始位置と要素を返す。 ######################## # 動作は、Icon入門講座(7) Iconの特徴(5)スキャンを参考にして下さい。 procedure p_split(line,c) /c := ' \t' # default /line := &subject # default list := [] # 戻り値用 list line ? { while tab(ps := upto(~c)) do put(list,[ps,tab(pe := many(~c))]) } return list end -----$ D2TREE.ICN ( lines:141 words:544 ) ------------------ BGM: 河よりも長くゆるやかに/篠原美也子 (icon_308.txt 1997/05/11 PCVAN PIG) ■ Icon > Icon散歩道(9) 再び x2tree(1) 風つかい まず、前回の 「再び dir2tree」の続きです。 FDの root directoryからの treeを 表示してみました。 -----^ ICON_FD2.DIR ( date:97-05-10 time:23:55 ) ----------- + NOT_ARCH 97-05-03 21:00 NOT_ARCH | + ICON_LEC DOC 3,038 97-04-23 23:17 ICON_LEC.DOC | + ICON_LEC TXT 116,916 97-04-23 23:15 ICON_LEC.TXT | + ICONLEC2 DOC 2,686 97-04-23 23:19 ICONLEC2.DOC | + ICONLEC2 TXT 125,700 97-04-23 23:20 ICONLEC2.TXT | + ICONLEC3 DOC 2,746 97-05-08 12:47 ICONLEC3.DOC | + ICONLEC3 TXT 105,141 97-05-08 12:47 ICONLEC3.TXT + OTHER 97-05-03 21:00 OTHER | + ICON_LEC ENG 3,109 97-04-23 23:30 ICON_LEC.ENG | + ICONLEC2 ENG 2,869 97-04-23 23:32 ICONLEC2.ENG | + ICONLEC3 ENG 2,924 97-05-09 20:00 ICONLEC3.ENG | + CONTRIB TXT 2,309 97-04-26 13:57 CONTRIB.TXT | + CONTRIB2 TXT 752 97-05-09 19:39 CONTRIB2.TXT + ICON_LEC LZH 42,239 97-04-26 10:07 ICON_LEC.LZH + ICONLEC2 LZH 44,737 97-04-26 10:07 ICONLEC2.LZH + ICONLEC3 LZH 33,723 97-05-08 12:48 ICONLEC3.LZH -----$ ICON_FD2.DIR ( lines:17 words:123 ) -----------------" #↑listの serial No ss := repl(" ", \step | 0) suspend " " || ss || x2tree(x,ss,"") #↑初期化フラグ end procedure x2tree(x,ss,init) # generator # show the tree structure of x static T # serial No 登録用 set登録用 table static宣言をして # おかないと、再帰したときに、未定義 errorとなる。 if \init then { # 初期化を initialでやると、同じ program内で別の # 構造体 tree表示のために、再び x2tを 呼んだ時に # 実行されなくて状態が残るので、フラグで初期化指示 T := table() T["list"] := set() # ここは、table(set())とすると、全て同じ setが T["set"] := set() # 割り当てられてしまうので、個別に初期化する。 T["table"] := set() if (t := type(x)) == ("list" | "set" | "table") then insert(T[t],serial(x)) # serial Noを T[type(x)]に登録 } n := *x # 枝の末端検出用カウンタ if (tt := type(x)) ~== "table" then { # not table every xx := !x do { # 構造体の要素を1つ づつ取り出す n -:= 1 t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) case t of { # 構造体のタイプにより、 "string" : suspend val_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp suspend (if n > 0 then "| " else " ") || ss || ss || x2tree(xx,ss) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp } } } else { # table every xkey := key(x) do { # tableの keyを1つ づつ取り出す n -:= 1 tk := type(xkey) xx := x[xkey] t := type(xx) val_disp := if t == ("list" | "set" | "table") then "+ <" || t || " " || string(m := serial(xx)) || ">" else "+ " || left(t,7) || jimage(xx) key_disp := if tk == ("list" | "set" | "table") then " <- <" || tk || " " || string(serial(xkey)) || ">" else " <- " || left(tk,7) || jimage(xkey) case t of { # 構造体のタイプにより、 "string" : suspend val_disp || key_disp #↓list,set,tableなら、typeを書出して、その中身をまた解析する。 "list" | "set" | "table" : { #↓再帰構造で なければ。(T[type(xx)] に既に登録済みなら再帰構造) if not member(T[t],m) then { insert(T[t],m) # serial Noを T[type(xx)]へ登録 suspend val_disp || key_disp suspend (if n > 0 then "| " else " ") || ss || ss || x2tree(xx,ss) #↑枝の途中 #↑枝の末端 # 再帰↑ delete(T[t],m) #←serial No 登録を削除 } else { # 再帰構造 ならば、書き出すとキリが無いので打止め return val_disp || key_disp || " (Recursion)" } } #↓その他なら、typeと値を書き出す。 default : suspend val_disp || key_disp } } } end -----$ X2TREE07.ICN ( lines:101 words:448 ) ---------------- BGM: 河よりも長くゆるやかに/篠原美也子 (icon_309.txt 1997/05/11 PCVAN PIG) ■ Icon > Icon散歩道(10) 再び x2tree(2) 風つかい 前回の 「再び x2tree」の続きです。test programとその結果です。 test programが長くなりましたので、分けました。 -----^ X2TREE7~.ICN ( date:97-05-08 time:21:54 ) ----------- + string "A" + string "B" + | + string "C" | + string "D" | + | + string "E" | + string "F" | + (Recursion) + + string "E" + string "F" + (Recursion)
+ string "C" <- string "C" + <- string "E" | + string "E" | + string "F" | + | | + string "A" | | + string "B" | | + | | | + string "C" | | | + string "D" | | | + (Recursion) | | + (Recursion) | +
(Recursion) + string "A" <- + string "G" <- string "A" + string "K" + | + string "H" | + string "I" + | + string "M" | + string "L" | + (Recursion) + string "J" + string "A" + string "B" + | + string "C" | + string "D" | + | + string "E" | + string "F" | + (Recursion) + + string "E" + string "F" + (Recursion) + string "K" + | + string "H" | + string "I" + | + string "M" | + string "L" | + (Recursion) + string "J"
+ string "C" <- string "C" + <- string "E" | + string "E" | + string "F" | + | | + string "A" | | + string "B" | | + | | | + string "C" | | | + string "D" | | | + (Recursion) | | + (Recursion) | +
(Recursion) + string "A" <- + string "G" <- string "A" + string "A" + string "B" + | + string "C" | + string "D" | + | + string "E" | + string "F" | + (Recursion) + + string "E" + string "F" + (Recursion) + string "K" + | + string "H" | + string "I" + | + string "M" | + string "L" | + (Recursion) + string "J"
+ string "C" <- string "C" + <- string "E" | + string "E" | + string "F" | + | | + string "A" | | + string "B" | | + | | | + string "C" | | | + string "D" | | | + (Recursion) | | + (Recursion) | +
(Recursion) + string "A" <- + string "G" <- string "A" -----$ X2TREE07 ( lines:124 words:501 ) -------------------- BGM: 河よりも長くゆるやかに/篠原美也子 (icon_310.txt 1997/05/11 PCVAN PIG) ■ Icon > Icon迷い道(1) system() 風つかい Icon散歩道の方では、次は 多項式の展開 をやってみるつもりなんですが、 結構 道が険しくて、次のお話しが書けません。 (a+b+c)^2 を a^2+b^2+c^2+2ab+2ac+2bcに、変換する程度の処理を、考えて いるのですが、どうやって programを 組めば良いのか 思いつきません。 そちらは、しばらく考えてみるとして、何にも書かないのもさみしいので、 近ごろ書いた programを紹介します。 niftyと PCVANの log fileから OSL/Libraryの Icon関係 fileタイトルの部分 を抜き出すものです。 YOTさんの ygrepを使わさせて頂いています。 ygrepの引数になる文字列を作って、system()関数に与えるだけです。 MS-DOSの batch programで書ける内容ですが、re-directが できないとかの 制限がありますので、Iconから呼んでいます。 command line引数に、日付(月日)を与えると その日付の log fileを、 与えなければ、その日の log fileを検索します。 map関数を使って、 keywordの &dateから日付を 抜き出しています。 &dateは、1997/06/04という形式をしています。これから 0604の部分を 抜き出すものです。 すると、使っている式は map("679A","123456789A","1997/06/04") となります。 map関数は、本来は文字変換の関数です。 その解釈ですと、前の式は 文字列 "679A"を 次の 規則で変換することになります。 1 -> 1 すると、ご覧のように "679A"は、ちょうど月日の部分 2 -> 9 の数字に変換されます。 3 -> 9 ちょっと、パズルみたいですが、このやり方を 覚えて 4 -> 7 おくと便利です。 5 -> / 部分文字列指定の 6 -> 0 &date[[6:8] || &date[9:0] 7 -> 6 と同じ結果になります。 8 -> / 9 -> 0 A -> 4 さて、 programです。 -----^ IDLG.ICN ( date:97-06-04 time:23:49 ) --------------- idlg.icn # comment追加 # idl.icn Rev.1.2 1997/06/01 windy 不正 date検出強化 # idl.icn Rev.1.1 1997/05/23 windy Kazetuskai H.S. # YOTさんの ygrep(超高速・多機能 grep)を使用。 # Usage: idlg または idlg MMDD procedure main(args) # 日付指定が あればその日付 無ければその日 の log fileを対象にする。 # ↓format変換(月日抜き出し) date := right(numeric(args[1]),4,"0") | map("679A","123456789A",&date) # 1997/06/04の形式↑ # ygrepの呼び出しパラメータ生成 # nifty用 ↓ OR検索 s1 := "ygrep \"{icon,bipl,de386}.*lzh\"" || " nif" || date || ".log " # PCVAN用 ↓一致行の前の行も出力 s2 := "ygrep -B1 \"{icon,bipl,de386}.*lzh\"" || " van" || date || ".log " write(&errout,s1) system(s1) # nifty log検索 write(&errout,s2) system(s2) # PCVAN log検索 end -----$ IDLG.ICN ( lines:26 words:105 ) --------------------- BGM: 河よりも長くゆるやかに/篠原美也子 (icon_351.txt 1997/06/06 PCVAN PIG) ■ Icon > Icon迷い道(2)download数 集計 風つかい 前回、Iconから ygrepを呼んで、log fileから Icon関係 fileのタイトル行を 切り出す programをご覧にいれました。 更に 集計表まで 出してくれるといい ということで、Iconだけで集計 programを書いてみました。 -----^ DL970607 ( date:97-06-07 time:00:35 ) --------------- PIG SLABO PFL FGALTS file計 BIPL.LZH - 11 - 19 30 DE386.LZH - 12 - 40 52 ICONLEC3.LZH 3 11 3 46 63 ICONLEC2.LZH 3 16 41 67 127 ICON_LEC.LZH 6 32 91 134 263 ------------------------------------------------ SIG/forum計 12 82 135 306 535 -----$ DL970607 ( lines:8 words:43 ) ----------------------- idl.icn # comment追加 # idl2.icn Rev.1.1 1997/06/04 windy Kazetsukai H.S. # This file is in the public domain. # Usage: idl または idl MMDD procedure main(args) # download数 格納 list(2重 list) #↓ [1]:PIG [2]:SLABO [3]:FPL [4]:FGALTS L := [ [ 0 ,0, 0 ,0], # L[1] ICON_LEC.LZH [ 0 ,0, 0 ,0], # L[2] ICONLEC2.LZH [ 0 ,0, 0 ,0], # L[3] ICONLEC3.LZH ["-",0,"-",0], # L[4] DE386.LZH PIG,FPLには uploadしていない。 ["-",0,"-",0] ] # L[5] BIPL.LZH PIG,FPLには uploadしていない。 # file名称 作成 # command line引数が数字に変換できれば、file日付に使う。できなければ、 # その日の日付を file日付に使う。 f_date := right(numeric(args[1]),4,"0") | map("679A","123456789A",&date) #↑ &dateの 6,7,9,10番目の文字を抜き出す。(map関数の応用) # &dateは 1997/06/04の形式 f_nif := "nif" || f_date || ".log " # nifty log file名生成 f_van := "van" || f_date || ".log " # PCVAN log file名生成 #################### # nifty 処理 #################### # nifty log file例 #1 16 33 37 # 17 PFF01531 96/12/08 41893 130 B ICON_LEC.LZH テキスト処理言語Icon入門講座 dir_nif := open(f_nif) | stop("cannot open ",f_nif) write(&errout,f_nif) size_nif := 15 # Icon関係 file検出のための照合字数 while line := read(dir_nif) do { # log fileを1行づつ読み込んで nn := numeric(line[33:37]) # download数 切り出し case line[1:size_nif+1] of { # download数を listに登録 " 17 PFF01531 " : L[1][4] := nn # FGALTS ICON_LEC.LZH " 20 PFF01531 " : L[2][4] := nn # FGALTS ICONLEC2.LZH " 21 PFF01531 " : L[3][4] := nn # FGALTS ICONLEC3.LZH " 163 PFF01531 " : L[4][4] := nn # FGALTS DE386_93.LZH " 124 PFF01531 " : L[5][4] := nn # FGALTS BIPL93.LZH " 78 PFF01531 " : L[1][3] := nn # FPL ICONLEC1.LZH " 81 PFF01531 " : L[2][3] := nn # FPL ICONLEC2.LZH " 82 PFF01531 " : L[3][3] := nn # FPL ICONLEC3.LZH } } close(dir_nif) #################### # PCVAN処理 #################### # PCVAN log file 例 #1 19 52 59 # 219.ICON_LEC.DOC TRA11936 96/12/ 8 0002421 0000032 # ICON_LEC.LZH TRA11936 96/12/ 8 0041893 0000032 dir_van := open(f_van) | stop("cannot open ",f_van) write(&errout,f_van) size_van := 18 # Icon関係 file検出のための照合字数 while line := read(dir_van) do { # log fileを1行づつ読み込んで nn := numeric(line[52:59]) # download数 切り出し case line[1:size_van+1] of { # SIG検出 (" 219.ICON_LEC.DOC " | " 243.ICONLEC2.DOC " | " 256.ICONLEC3.DOC " ) : mode := "LAB" # SLABO処理中 (" 79.ICON_LEC.DOC " | " 84.ICONLEC2.DOC " | " 89.ICONLEC3.DOC ") : mode := "PIG" # PIG処理中 # download数を listに登録 " ICON_LEC.LZH " : if mode == "LAB" then L[1][2] := nn # SLABO else L[1][1] := (nn-1) # PIG # download test分 ↑ " ICONLEC2.LZH " : if mode == "LAB" then L[2][2] := nn # SLABO else L[2][1] := nn # PIG " ICONLEC3.LZH " : if mode == "LAB" then L[3][2] := nn # SLABO else L[3][1] := nn # PIG " DE386_93.LZH " : L[4][2] := nn # SLABO " BIPL93.LZH " : L[5][2] := nn # SLABO } } close(dir_van) #################### # 表にして出力 #################### f_name := [ "ICON_LEC.LZH ", # file名称 list "ICONLEC2.LZH ", "ICONLEC3.LZH ", "DE386.LZH ", "BIPL.LZH ", "SIG/forum計 " ] size_f_name := *f_name[1] sig := [ " PIG", # SIG/forum名称 list " SLABO", " PFL", " FGALTS", " file計" ] size_sig := *sig[1] # 日付生成 ↓fdateに"/"を挿入。(map関数の応用) writes(left("<" || &date[1:6] || map("12/34",1234,f_date) || ">",size_f_name)) every writes(!sig) # SIG/forum名出力 write() L_sum_col := [0,0,0,0,0] # SIG/forum毎の download数 集計用 list every i := *L to 1 by -1 do { # listの末尾から(逆順出力のため) writes(f_name[i]) # file名出力 sum_line := 0 # file毎の download数 集計 every j := 1 to *L[i] do { writes(right((nnn := L[i][j]),size_sig)) # file毎 download数 sum_line +:= (nnnn := numeric(nnn) | 0) # 数字なら足し込む L_sum_col[j] +:= nnnn # 数字なら足し込む } write(right(sum_line,size_sig)) # file毎 daownload数 出力 L_sum_col[-1] +:= sum_line # 総計に足し込む } write(repl("-",*L_sum_col * size_sig +size_f_name)) # 仕切り線 writes(f_name[-1]) # "SIG/forum計 "の文字を出力 # (f_nameの最後の要素) every writes(right(!L_sum_col,size_sig)) # SIG/forum毎の計 write() end -----$ IDL.ICN ( lines:131 words:617 ) --------------------- PIG SLABO FPL FGALTS file計 BIPL.LZH - 14 - 33 47 DE386.LZH - 17 - 89 106 ICONLEC3.LZH 3 12 18 95 128 ICONLEC2.LZH 5 16 56 111 188 ICON_LEC.LZH 7 34 109 196 346 ------------------------------------------------ SIG/forum計 15 93 183 524 815 -----$ DL971124 ( lines:8 words:43 ) ----------------------- BGM: 河よりも長くゆるやかに/篠原美也子 (icon_352.txt 1997/06/07 PCVAN PIG) ■ Icon > Icon迷い道(3)CSV:定義ファイルの読込 風つかい 夏の盛りから、担当している 某 projectの関係で、某所に拉致されており ましたが、一区切りつきましたので娑婆に戻って、気がつけばもう秋深し。 Icon講座は、どこまで書いたか記憶の彼方です。 確か、CSVデータ(コンマ区切りデータ)を、 表形式の テキストデータに 変換するprogram を作って upload しようとしていた ような 気がします。 リハビリと兼ねて、思い出しながら 続きをやってみたい と思います。 しかし、某 projectは未だ続いていますので、Icon講座が 途絶えましたら、 また 某所に拉致されたな と思って下さい。(笑) さて、CSVデータというのは、こんなデータです。 "なかやまみほ","中山美穂",1970,3,1,"O",158,80,60,84,45,"東京都小金井市" コンマ区切りのデータで、文字列は " で くくってあります。 文字列中に " が 現れる場合は、"" で表わすものとします。 CSVといっても、細かい点で仕様が違うものが、いくつかあるようですが、ここ ではこの仕様とします。 例のようなデータが並んでいる データファイルを、表形式のデータへ 変換した り、表形式のデータを逆に CSVデータへ変換するものを作ってみます。 例のデータを表形式にするためには、各欄を何文字の表にするかの情報をどこか で定義しないといけません。 たとえばこんな感じです。各欄の文字数を定義する ついでに、文字か数字かの情報もまとめて定義しています。 -----^ CSV2TB.CFG ( date:97-10-27 time:00:02 ) ------------- 表データ 変換指定ファイル #################### # 行頭が "#"あるいは行に "="が含まれ無いなら、無視。(コメント) # 処理対象ファイル名の先頭の文字にて、処理指定を識別する。 # ファイル識別文字("="の手前の文字)は、英字大文字。 # 変換指示は、","区切りのデータを何桁のデータとして扱うかを、指示。 # 変換指定例 # s14 : 14桁の文字列、n4 : 4桁の数字、s0 : その欄は無視(n0でも良い) # csvデータより、指定桁が大きい場合は、後ろに " "が追加される。 # 変換指定が無い部分の csvデータは無視される。 #################### # テスト用サンプルデータ # "なかやまみほ","中山美穂",1970,3,1,"O",158,80,60,84,45,"東京都小金井市",10 SAM= s13 s9 n4 n2n2 s0 n3 n3 n3 n3 n3 s12 n2 -----$ CSV2TB.CFG ( lines:17 words:52 ) -------------------- + string "ABC" + string "abc_ini" + string "DEFG" + string "デーイーエフジー" + string "hijk" + string "123,456" + string "hijk" + string "123,456,789" + string "lmno" + string "lmnoだ" + string "pqrs" + string "" + string "lmn" + string "lmnだ" lmnoだ lmnoだ lmnだ error -----$ GET_INIL ( lines:20 words:50 ) ---------------------- BGM: Smile/岡本真夜 (icon_353.txt 1997/10/27 PCVAN PIG) ■ Icon > Icon迷い道(4)CSV:定義ファイルの解析 風つかい 今日は、定義ファイルの解析の部分をやります。定義ファイルは、CSVデータと 並べて次のように指定したいのです。 SAM= s4 s1 n1n2 n3 s16 # "地球","E",1,15,256,"ちきゅうはまるい" 順に、地球 -> s4 E -> s1 1 -> n1 15 -> n2 256 -> n3 ちきゅうはまるい -> s16 と指定している訳です。 programでは、CSVデータの欄に対応した指定を listに格納しておくことに します。 前回の定義ファイルの読込みでは、 SAM= s4 s1 n1n2 n3 s16 という stirngを ["SAM"," s4 s1 n1n2 n3 s16"] と 変換して、"SAM"で listデータを サーチして、" s4 s1 n1n2 n3 s16" という文字列を 取り出すところまで 済んでいます。 今回は、この指定文字列を、欄毎の指定が順に詰まった listへ変換する部分 を作ります。 指定が全てスペース区切りなら、以前紹介しました splitとかで listに変換 できるのですが、今回のデータは スペースが無い部分もあります ので、 別の 方法が必要です。 指定が、アルファベット1文字と数字の組み合わせですので、その組み合わせ を検索して、listに順に格納する procedureを作ります。 こういう データ変換 procedureを 簡単に作れるところが、Iconの良いところ です。 というところで、programです。 Test programも一緒に入れています。 -----^ CN_SPLIT.ICN ( date:97-10-29 time:00:42 ) ----------- [s4,s1,n1,n2,n3,s16] と変換 # "地球","E",1,15,256,"ちきゅうはまるい" # 備考 : csvデータを表データに変換するプログラムのために作成 # 上の例の用に、データ例と並べて指定が可能なプログラムにするため procedure cn_split(s,c1,c2) /s := &subject # default /c1 := &letters # 英文字の大文字・小文字のセット /c2 := &digits # 数字のセット '0123456789' L := [] # 戻り値用 list s ? { while tab(upto(c1)) do { # c1迄スキップ ss := "" # ss := tab(many(c1)) # c1以外の文字迄スキップし、その間の文字 # を ssへ put(L,ss ||:= tab(many(c2))) # c2以外の文字迄スキップし、その間の文字 # を ssへ足しこむ } } return L end -----$ CN_SPLIT.ICN ( lines:42 words:140 ) ----------------- BGM: Smile/岡本真夜 (icon_354.txt 1997/10/29 PCVAN PIG) ■ Icon > Icon迷い道(5)CSV:拡張子変更(1) 風つかい さて、今日は 拡張子を変更する procedureについて説明します。この procedure は、CSVデータのファイル名を foo.csvとしますと、CSVデータを表形式データに変換 したデータのファイルは拡張子を変えて、foo.txtという名称にするためのものです。 まず ファイル名の '.' の前の部分と 後ろの部分を分ける procedureを作ります。 早速、programです。 -----^ DOT.ICN ( date:97-10-30 time:00:33 ) ---------------- BGM: Blow by Blow / Jeff Beck (icon_355.txt 1997/10/30 PCVAN PIG) ■ Icon > Icon迷い道(6)CSV:拡張子変更(2) 風つかい さて、拡張子を変更する procedureのつづきです。 前回 作りました '.' の前の 部分と 後ろの部分を分ける procedureを使って、拡張子を変更したりチェックした りする procedureを作ります。 -----^ EXT.ICN ( date:97-10-30 time:00:48 ) ---------------- BGM: Blow by Blow / Jeff Beck (icon_356.txt 1997/10/30 PCVAN PIG) ■ Icon > Icon迷い道(7)CSV:CSV2TB 風つかい さて、CSVデータを表形式データへ変換する programのまとめです。 CSVデータのファイルから、1行ずつデータを読込んで、CSVデータを表形式データ に変換して、書き出していきます。 -----^ CSV2TB.ICN ( date:97-10-26 time:21:08 ) ------------- ",f_new) # 動作モニター # display form data # every writes(&errout," ",!form) ; write(&errout) # main no := 0 # モニター用表示の行番号初期値 while line := read(intext) do { # ファイルを1行ずつ読み込み、 write(outtext,csv2tb(line,form)) # form指定に従い変換 writes(&errout," ",right(no +:= 1,4)) # モニター用表示 } write(&errout,"") # カーサー復帰 # close files (無くても動く) close(intext) close(outtext) end #################### # csvデータ1行変換 procedure #################### # args : [1]: string csvデータ(1行)、[2]: list 変換指定文字+桁の list、 # [3]: 桁揃え追加文字 # value: string 表形式に変換された文字列(1行) procedure csv2tb(line,form,s_fill) /s_fill := " " # 指定が無ければ、spaceと見なす。 # 原データ中の spaceと桁揃えのために付加する spaceを区別を # する時使用。例えば、データ中の " "を "_"とかに変換する。 if line[1] == "#" then { # 行の先頭が "#"ならコメント行 return line } l_list := split_csv(line) # 行データを、","区切りで、listに変換。 ################## # 指定桁合わせ ################## i := 1 # 欄番号 s_line := "" # 文字列足し込み用の空文字列 while i <= *form do { # 変換指定の数分、ループ if not (form[i][2:0] == "0") then { # 0桁指定でなければ if form[i][1] == "s" # 文字列指定だったら、左詰め then s_line ||:= (left(map(string(l_list[i])," ",s_fill), form[i][2:0]) || " ") # 数字指定だったら、右詰め else s_line ||:= (right(l_list[i],form[i][2:0]) || " ") } i +:= 1 } return s_line[1:-1] # 末尾の spaceの つけ過ぎを削除。 end #################### # csvデータを listに変換 #################### # args : string csvデータ(1行) # 文字列データは 両端を \" で囲まれているものとする。 # 文字列中の \"は、\"\"で表わされているものとする。 # value: list 欄データを順に listに詰めたもの # 備考 : 3状態の状態遷移マシン state : "init": 初期状態, # "string":文字列処理状態, "number":数字処理状態 procedure split_csv(line) state := "init" # 動作状態管理変数に、初期状態をセット # "string":文字列処理状態, "number":数字処理状態 L := [] # 戻り値用 空 list line ? { repeat { # write(&errout,&pos," ",state) case state of { "init" : { # 初期状態 buf := "" # 文字列足し込み用バッファー初期化 s := move(1) | fail # 次の1文字を get if s == "\"" # stringデータの始め記号なら then state := "string" # 状態 -> 文字列処理 else { state := "number" # 状態 -> 数字処理 move(-1) # &pos戻し } } "number" : { # 数字データ処理状態 put(L,tab(upto(',') | 0)) # 次の ","迄の文字列を list Lに追加 move(1) | break # skip "," または行末でループを抜ける。 state := "init" # 状態 -> 初期状態 } "string" : { # 文字列データ処理状態 buf ||:= tab(upto("\"")) # 次の "\""迄の文字列を bufに追加 move(1) # skip \"(必ずあるはず。) if (s := move(1)) # 行末チェック then { # 行末でなければ if s == "," # データ区切り記号 then { # 前の \"は、stringの終わりだった。 put(L,buf) # bufの内容を listへ追加 state := "init" # 状態 -> 初期状態 } else { # 前の \"は、escapeだった。 buf ||:= s # bufに足し込み state := "string" # 状態 -> 文字列処理 } } else { # 行末なのでループを抜ける。 put(L,buf) # bufの内容を listへ追加 break } } default : stop("state error") # ここへは、来ないハズ。 } } } return L end -----$ CSV2TB.ICN ( lines:162 words:594 ) ------------------ BGM: Sun & Moon/岡本真夜 (icon_357.txt 1997/10/31 PCVAN PIG) ■ Icon > Icon迷い道(8)CSV:CSV2TB 風つかい さて、今回は、表形式データを CSVデータへ変換する programです。この program でも、定義ファイルを使いますが、次のような形式です。 -----^ TB2CSV.CFG ( date:97-10-26 time:21:20 ) ------------- csvファイル変換指定ファイル #################### # 行頭が "#"あるいは行に "="が含まれ無いなら、無視。(コメント) # 処理対象ファイル名の先頭文字にて、処理指定を識別する。 # ファイル識別文字("="の手前の文字)は、英字大文字。 # 変換指示は、 # s: 文字データ先頭指示、n: 数字データ先頭指示、d: 削除データ先頭指示 #################### # テスト用サンプルデータ #なかやまみほ 中山美穂 1970 3 1 O 158 80 60 84 45 東京都小金井 SAM=s ds dn dn dn dsdn dn dn dn dn ds -----$ TB2CSV.CFG ( lines:13 words:47 ) -------------------- ",f_new) # 動作モニター # display form data # every writes(&errout," ",!form) ; write(&errout) # main no := 0 # モニター用表示の行番号初期値 while line := read(intext) do { # ファイルを1行ずつ読み込み、 write(outtext,tb2csv(line,form)) # form指定に従い変換 writes(&errout," ",right(no +:= 1,4)) # モニター用表示 } write(&errout,"") # カーサー復帰 # close files (無くても動く) close(intext) close(outtext) end #################### # 表データ -> csvデータ1行変換 procedure #################### # args : [1]: string 表データ(1行)、[2]: list 変換指定(2重 list) # value: string csv形式に変換された文字列(1行) procedure tb2csv(s,L) ss := "" every i := 1 to *L do { ss ||:= case (LL := L[i])[1] of { "s" : { "\"" || replace(s[LL[2]:LL[3]],"\"","\"\"") || "\"\," } "n" : { s[LL[2]:LL[3]] || "\,"} # "d" の部分は無視する。 } } return ss[1:-1] end #↑最後の余分な "\,"を削除 -----$ TB2CSV.ICN ( lines:73 words:275 ) ------------------- BGM: Sun & Moon/岡本真夜 (icon_358.txt 1997/10/31 PCVAN PIG) ■ Icon > ちょっと Icon(1)data整形 風つかい (niftyserveの FGALTSに「AWK天国/なんだ簡単じゃねえか!」という会議室が ありますが、そこで data整形の話題が でました。 それをネタに FGALTSの「スクリプト天国/何でもかんでも」の会議室で、 Iconの紹介を したものです。) 次のような dataを -----^ TEST03.DAT ( date:97-05-17 time:13:32 ) -------------kekka # data sample(/line) : 1,"A" # This file is in the public domain. BEGIN{ FS = "," # 行内の data区切りを ","に変更 No = 0 # データ種別番号 n = 1 # (同一データ種別番号の)データ個数カウンタ N = 3 # 区切り数 } { if($1 != No){ # data種別 Noが変わったら No = $1 # data種別 No更新 if(n % N != 1 ){ print ""} # top dataで無ければ、改行出力 n = 1 # data個数 reset } if(n % N == 1) { # N個 区切りの先頭ならデータ種別 No出力 # printf($1) # printf($1 FS $2) # Rev1.2 } # printf(FS $2) # printf(FS $3 FS $4) # Rev1.2 if(n % N == 0) { print ""} # N個 区切り数最後なら、改行出力 n++ # data数カウントアップ } END{ if(n % N != 1) { print ""} # 最後の行が N個でなければ、改行出力 } -----$ SHAPE01.AWK ( lines:33 words:147 ) ------------------kekka # data sample(/line) : 1,"A" # shape01.awk を、そのまま、Iconに移し変えたもの。 # This file is in the public domain. link split6 procedure main(args) # ↑command line 引数 (list) Usage := "shape01 data_file >kekka" # command line 引数チェック(引数が無ければ使用方法表示) if *args = 0 then stop(Usage) # data fileオープン(エラーならエラー表示) dir := open(args[1]) | stop("cannot open ",args[1]) # ↑command line引数の1番目 fs := '\,' # 行内の data区切り No := 0 # データ種別番号 n := 1 # (同一データ種別番号の)データ個数カウンタ N := 3 # 区切り数 while line := read(dir) do { # 1行づつ順次読み込んで、 L := split(line,fs) # fsにて dataを分割して、listへ if numeric(L[1]) ~= No then { # データ種別 Noが変わったら if (n % N) ~= 1 then write() # top dataで無ければ、改行出力 No := numeric(L[1]) # データ種別 No更新 n := 1 # data個数 reset } if (n % N) = 1 then writes(No) # N個 区切りの先頭ならデータ種別 No出力 # if (n % N) = 1 then writes(No,fs,L[2]) # writes(fs,L[2]) # データ出力 # writes(fs,L[3],fs,L[4]) # データ出力 if (n % N) = 0 then write() # N個 区切り数最後なら、改行出力 n +:= 1 # data数カウントアップ } if (n % N) ~= 1 then write() # 最後の行が N個でなければ、改行出力 end # 解説 # *args : argsの size(この場合は、引数の個数) # stop(s) : 文字列 sを出力して、programを stopする関数 # read() : text-mode file 読み込み関数 # numeric : 文字→数字変換関数 # = : 数字の比較 # := : 代入 # +:= : n +:= m は、 n := n +m の略記 # ~ : 否定 # writes : printf 相当(改行無し出力) # write : print 相当(改行付き出力) # "abc" : 文字列 abc # 'xyz' : 'x' 'y' 'z' を要素とする集合 # L[3] : L (list)の 3番目の要素 # link : 他の fileの procedureを linkする指定 -----$ SHAPE01.ICN ( lines:57 words:273 ) ------------------ BGM: Vivien/篠原美也子 (nif0516a.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > ちょっと Icon(2)data整形 風つかい 1行データを 3個づつまとめる データ整形 の お話しの続きです。 前回の programで使っている 文字列分割の procedureです。 -----^ SPLIT6.ICN ( date:97-05-17 time:13:09 ) ------------- BGM: Vivien/篠原美也子 (nif0516b.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > ちょっと Icon(3)data整形 風つかい 1行データを 3個づつまとめる データ整形 の お話しの続きです。 前の programに Iconの機能を、多少ちりばめてみます。 でも、同じ機能の programですから、動いた結果は同じです。(汗) ・読み込んだ dataの各行の分割のところで、最初の ","で、行データを分割す るプログラムにします。 ・行データを、table(AWKの連想配列)に格納します。 (格納する必要は 無いのですが、tableのサンプルとして。) そうしますと、AWKの連想配列と同じく、取り出すときに、格納した順番とは なりません。 そこで、tableに格納した dataを keyで sortして出力します。 tableは sortすると、listになります。( dataに順番を与えるには、listに しないといけないので、Iconの言語仕様が そうなっています。) ・出力処理で、Iconでは、せっかく case構文が、サポートされています ので、使ってみます。 多少、動作が分かりやすくなると思います。 ・整形結果を 出力した後に、使った tableと listの構造が どうなってい るかを、x2tという procedureを使って書き出します。(これは、参考用 です。本来の動作とは関係ありません。) x2tを説明しますと、 Icon入門講座1〜3全部を、説明しないといけなく なりますので、まあ そういう機能の procedureだと、 ここでは、考えて 下さい。(Icon入門講座3(19)の x2tree03 にミス修正(汗)と機能 アップ(tableの場合 valueだけでなく keyも出力するように) したもの です。) -----^ SHAPE02.ICN ( date:97-05-17 time:10:17 ) ------------kekka # data sample(/line) : 1,"A" # This file is in the public domain. link x2tree06 procedure main(args) Usage := "shape02 data_file >kekka" if *args = 0 then stop(Usage) dir := open(args[1]) | stop("cannot open ",args[1]) fs := '\,' # 行内の data区切り N := 3 # 区切り数 T1 := table() # tableを生成(初期値 無し) while line := read(dir) do { # 1行づつ順次読み込んで、 line ? { # lineを走査対象として ps := upto(fs) # ps : lineの中で、最初に fsが見つかった位置 n := numeric(line[1:ps]) # lineの psより前の部分を数字変換 s := line[ps+1:0] # lineの psより後の部分 /T1[n] := [] # table T1の keyに、nが無ければ、nを key # として valueに [] (空 list)を 登録 put(T1[n],s) # tableの key n の value (list)に sを追加 } } L1 := sort(T1,1) # T1 を keyで sortし、 listへ変換 write("整形結果") every L2 := !L1 do { # L1から、要素(list) を順次取り出して No := L2[1] # 1番目の要素(数字)を Noに代入 n := 0 # 同じ Noの要素のカウンタ every s := !L2[2] do { # 2番目の要素(list) から要素(文字列)を # 順次取り出して n +:= 1 # 同じ Noの要素のカウンタ +1 case (n % N) of { # nを Nで割った余りによって 1 : { writes(No) # No出力 writes(fs,s) } # データ出力 2 : writes(fs,s) 0 : { writes(fs,s) write() } # 改行出力 default : stop("case error") # それ以外だったら } } if (n % N) ~= 0 then write() # 最後の出力行の要素数が、N以外だったら } # 改行出力 # 動作参考用 write("\nT1 (table) 構\造") # "構" は "\x8d5c" なので、"\x5c"を補う。 every write(x2t(T1)) # x2tは 構造体の内容を tree表示する procedure # x2tree06.icnに含まれる。 write("\nL1 (list) 構\造") every write(x2t(L1)) end # 解説 # /T1[n] : T1[n]の null (未定義) check # table : table(AWKの連想配列)を生成 ()内には、初期値を指定できる # every ... !L : 構造体 Lの要素を順次取り出して -----$ SHAPE02.ICN ( lines:61 words:277 ) ------------------ + <- integer18 | + string "遊佐 未森" + <- integer10 | + string "竹内 まりあ" | + string "中島 みゆき" | + string "中山 美穂" | + string "中村 あゆみ" | + string "久松 史奈" | + string "松任谷 由美" | + string "森川 美穂" | + string "山下 久美子" + <- integer7 | + string "篠原 ともえ" | + string "篠原 美也子" | + string "篠原 涼子" + <- integer1 | + string "相川 七瀬" | + string "安室 奈美恵" + <- integer3 + string "大黒 摩季" + string "岡本 真夜" + string "尾崎 亜美" + string "辛島 美登里" L1 (list) 構造 + | + integer1 | + | + string "相川 七瀬" | + string "安室 奈美恵" + | + integer3 | + | + string "大黒 摩季" | + string "岡本 真夜" | + string "尾崎 亜美" | + string "辛島 美登里" + | + integer7 | + | + string "篠原 ともえ" | + string "篠原 美也子" | + string "篠原 涼子" + | + integer10 | + | + string "竹内 まりあ" | + string "中島 みゆき" | + string "中山 美穂" | + string "中村 あゆみ" | + string "久松 史奈" | + string "松任谷 由美" | + string "森川 美穂" | + string "山下 久美子" + + integer18 + + string "遊佐 未森" -----$ SHAPE02 ( lines:71 words:285 ) ---------------------- BGM: Vivien/篠原美也子 (nif0516b.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > ちょっと Icon(4)data整形 風つかい 相変わらず、1行データを 3個づつまとめる データ整形 の お話しの 続きです。 前回の programの出力部分に generatorを使ってみます。 generatorと いうのは、procedureで、複数の結果を、順次返す機能 を、持っている ものを言います。 でも、全体は、同じ 機能の programですから、 動いた結果も、相変わ らず 同じです。(笑) -----^ SHAPE03.ICN ( date:97-05-17 time:10:46 ) ------------kekka # data sample(/line) : "1","A" # This file is in the public domain. link retrieve procedure main(args) Usage := "shape03 data_file >kekka" if *args = 0 then stop(Usage) # command line 引数 check dir := open(args[1]) | stop("cannot open ",args[1]) # file open # 初期設定 fs := '\,' # 行内の data区切り N := 3 # 区切り数 T1 := table() # 空の tableを生成 # data fileを読み込み tableに格納 (tableは AWKの連想配列と同じ) while line := read(dir) do { # 1行づつ順次読み込んで、 line ? { # 読み込んだ 行を 走査対象として ps := upto(fs) # 最初の fsの位置を得る n := numeric(line[1:ps]) # fsより前が n (numeric :文字→数字変換) s := line[ps+1:0] # fsより後が s /T1[n] := [] # T1に nが keyとして存在しないなら # T1に nを keyとして、空 listを登録 put(T1[n],s) # tableの key n の value (list)に sを追加 } } L1 := sort(T1,1) # T1を keyで sort(結果は listの list) write("整形結果") every L2 := !L1 do { # L1の要素を 順次取り出して No := L2[1] # data種別 No every L3 := retrieve(L2[2],3) do { # L2[2]の要素を 3個づつ取り出す。 writes(No) # data種別 No を出力 every writes(fs,!L3) # L3の要素を 順次出力 write() } } end -----$ SHAPE03.ICN ( lines:43 words:194 ) ------------------ BGM: Vivien/篠原美也子 (nif0516c.txt 1997/05/16 niftyserve fgalts, 1997/05/17 PCVAN SLABO) ■ Icon > Icon回り道(1)重複しないランダムな 10個の数 風つかい (PCVANの SLABOで、乱数の話題がでていました。Iconで乱数をつかったこと がありませんでしたので、話題に相乗りして Iconでもやってみました。 テーマは、3桁の重複しない乱数を得る、というものです。) ということで、私も Iconの乱数機能を 使ったことが、ありませんでした ので、どういう programになるか やってみました。。 Iconでは、?10 と書きますと、1〜10迄の乱数を発生できます。 正確には 乱数列の最初の数字を得ることができます。 同じ program内で、次にこの式 (?10) を 実行すると、乱数列の2番目の 数字が得られます。 ちなみ、文字列では、?"ABCDEFG" と書くと "ABCDEFG"から randomに1文 字(1-byte character)取り出せます。 Iconでは、この乱数列は programを何度実行しても同じ乱数列となります。 違う乱数列を得るためには、keywordの &randomを変えると可能だそうです。 1 〜 n までの randomな数 を m個 発生させる programは次のようになり ます。 -----^ RANDOM01.ICN ( date:97-05-30 time:23:22 ) ----------- BGM: 河よりも長くゆるやかに/篠原美也子 (pcv0531a.txt 1997/05/31 PCVAN SLABO) ■ Icon > Icon回り道(2)重複しないランダムな 10個の数 風つかい 続きです。 乱数列 program実行の度に、同じ乱数列が出てくるのでは、まずい ときには、乱数の種を 乱数にする procedureが BIPL(Icon基本 library)に 有り ますので、それを linkして、乱数列発生の前に実行します。 -----^ RANDOM04.ICN ( date:97-05-31 time:14:41 ) -----------> random04 を3回実行した時の結果です。 -----^ RANDOM04 ( date:97-05-31 time:14:42 ) --------------- BGM: 河よりも長くゆるやかに/篠原美也子 (pcv0531b.txt 1997/05/31 PCVAN SLABO) ■ Icon > Icon回り道(3)重複しないランダムな 10個の数 風つかい 3桁の数字という条件で、そのものズバリ 文字数が3桁 というやり方を書き落と しました。そういう条件の場合は、次のようになります。 -----^ RANDOM07.ICN ( date:97-06-01 time:23:49 ) ----------- BGM: そのままの君でいて/岡本真夜 (pcv0601a.txt 1997/06/01 PCVAN SLABO) ■ Icon > Icon回り道(4)Usageが... 風つかい あれれ、random02.icnから random07.icnまで、全部 Usageのファイル名が random01のままですね。あはは。よくやります。 人手で修正するので、漏れがでますので、プログラム自身で作らせようと こんな procedureを作ってみました。 Iconには、プログラム名称を示す keywordがあります。 &prognameです。 &prognameには、ディレクトリー付きのファイル名が入ります。 Usageでは、ディレクトリーと拡張子は、通常 不要ですので、それを削除 して使います。 top_cut()という procedureで、ディレクトリーを削除して、 top_get()という procedureで、拡張子を除いています。 (参考に &prognameそのものも表示するようにしています。) -----^ EXE_NAME.ICN ( date:97-06-02 time:19:06 ) ----------- BGM: そのままの君でいて/岡本真夜 (pcv0601b.txt 1997/06/01 PCVAN SLABO) ■ Icon > Icon回り道(5)a < b が値をもつ 風つかい (Iconでは、比較式は成功すると、右辺の値を取りますが、その説明を PCVANの SLABOの会議室で ちょっと説明しましたので、参考になるかと。) 一般的に、比較式は、成立すれば、右辺の値を持ちます。 例えば、 3 < 5 の値は、 5 です。 "A" << "B" の値は、 "B" です。 ですから、 write(3 < 5) は、"5" を出力しますし、 write("A" << "B") は、"B" を出力します。 ( < は数字の比較。<< は文字列の比較です。 write()は、数字の場合は 文字に変換して出力します。) 実際には、右辺を変数にして、変数が比較条件に一致すれば出力する というような表現に使います。 Iconでは、比較式に限らず、全ての式が値を持ちます。 そこで、 write(if n < m then "NNN" else "MMM") というような表現もできます。これは、 if n < m then write("NNN") else write("MMM") と同じことになります。じゃあ、この式の値はどうなるかというと、 write()は引数と同じ値を持ちますので、出力文字と同じ値になります。 write(if n < m then write("NNN") else write("MMM")) は、同じ文字を2度出力します。 さて、条件が成立しない場合ですが、その場合はその式は【失敗】します。 【失敗する】というのは、その式が無いのと同じということになります。 値としては nullとなります。というか、値が無いという言い方が良いかも しれません。 Iconの関数は、nullが引数ですと、通常は、その関数自体が失敗します。 この仕様のために、表現を非常にコンパクトにできることも多いです。 動作サンプルを次ぎに。 -----^ A_B.ICN ( date:97-06-06 time:20:17 ) ---------------- 5) # この式は失敗します。 write("A" << "B") n := 3 m := 5 write(if n < m then "NNN" else "MMM") if n < m then write("NNNN") else write("MMMM") write(if n < m then write("NNNNN") else write("MMMMM")) end -----$ A_B.ICN ( lines:12 words:52 ) ----------------------- a_b とした時の結果です。 -----^ A_B ( date:97-06-06 time:20:17 ) -------------------- BGM: 河よりも長くゆるやかに/篠原美也子 (pcv0606a.txt 1997/06/06 PCVAN SLABO) ■ Icon > ちょっと Icon(5)Wicon beta8 風つかい Iconの WindowsNT/95対応版を近ごろいじっています。 日本語は未だ画面に うまく出せないのですが、ちょっとご紹介します。 Iconは、Arizona大学の Griswold教授(のグループ)が開発していますが、 WindowsNT/95対応の Icon(Wicon)は、Arizona大学にいて、その後 Texas大学 San Antonio校(UTSA)に移った Jeffery教授(のグループ)が開発しています。 現在は、beta版で 8版になっています。 次の所から入手できます。 ftp://ringer.cs.utsa.edu/pub/icon/nt/graphics/ Index of /pub/icon/nt/graphics/ Name Last modified Size docs.zip 26-Feb-97 16:47 38K gprocs.zip 26-Feb-97 01:43 501K iconhelp.zip 05-Mar-97 12:53 145K keysyms.icn 08-Feb-96 00:00 3K procs.zip 26-Feb-97 01:43 339K READ.ME 06-Mar-97 00:53 4K vdefns.icn 17-Jun-97 01:53 1K vib.zip 26-Feb-97 02:31 122K vibsrc.zip 26-Feb-97 01:43 261K wi.bat 06-Mar-97 00:50 209K wi.icn 06-Mar-97 00:50 14K wi.zip 06-Mar-97 00:52 54K wicon.zip 06-Mar-97 01:26 339K ftp://ftp.cs.arizona.edu/icon/beta/windows Index of /icon/beta/windows Name Last modified Size docs.zip 06-Mar-97 20:12 38K gprocs.zip 06-Mar-97 20:12 501K iconhelp.zip 06-Mar-97 20:13 145K keysyms.icn 06-Mar-97 20:23 3K procs.zip 06-Mar-97 20:16 339K READ.ME 06-Mar-97 20:21 4K vib.zip 06-Mar-97 20:18 122K vibsrc.zip 06-Mar-97 20:18 261K wi.icn 06-Mar-97 20:23 14K wi.zip 06-Mar-97 20:19 54K wicon.zip 06-Mar-97 20:20 339K UTSAが originalで、後で Arizona大学へも登録されたみたいです。 MS-DOS版の Iconは、特に日本語対応版というのはありませんが、文字列 を 1byte単位で、走査・加工する機能が備わっていますので、日本語対応は 特に、Icon処理系をいじらなくても、Icon Programmer側で処理できます。 Windows版も、日本語文字が画面に出せさえすれば、後は programmer側と しては不便は無いと思って、なんとか日本語が表示できないかと色々試して います。 Windows版の Iconは、起動した状態で、2つの Windowが開きます。 1つは、editor-windowで、もう1つは console-windowです。 ・editor-windowでは、日本語入力は、問題ありません。表示もOKだし 保存して再度読みだしても大丈夫です。 行末のCRLFが、CRCRLFになるようですが、動作は問題ありません。 ・console-windowは、標準出力を表示する windowですが、日本語を出力 すると化けます。 ・programで、windowが開けます。開いた windowには、フォント指定が できます。 日本語のフォント指定も有効なものがあります。 FixedSys と System は指定すると有効みたいです。 しかし、特定コードを含む文字はうまく表示できません。 Shift-JISコードを出力する次のような programを作って試してみました。 -----^ JCHAR02W.ICN ( date:97-07-05 time:21:53 ) ----------- ",s1,"7E") WWrite("<0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F>") every n2 := 16r40 to 16r7E do { # Shift-JIS文字出力(前半) if ((16r40 < n2) % 32 = 0) then WWrite() # 32文字で改行 WWrites(char(n1) || char(n2)) # otuput each character(2 bytes) } WWrite() WWrite() WWrite(s1 := hexstring(n1,2),"80 -> ",s1,"FC") WWrite("<0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F>") every n2 := 16r80 to 16rFC do { # Shift-JIS文字出力(後半) if ((16r80 < n2) % 32 = 0) then WWrite() WWrites(char(n1) || char(n2)) # output each character(2 bytes) } WWrite() WDone() # q/Qキー入力待ち(Qまたはqを押すと windowを close) return end -----$ JCHAR02W.ICN ( lines:41 words:245 ) ----------------- 917E <0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F> 繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙 疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻 9180 -> 91FC <0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F> 操早曹巣槍槽??燥争痩相窓糟総綜聡草荘葬??藻??走送遭鎗????像増憎臓 蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰 詑?チ堕妥惰打柁舵楕陀駄騨体堆対?マ?ミ帯待怠態戴?ヨ泰滞胎腿苔袋貸退?゚ 隊????代台大第醍題鷹滝瀧??啄??托??????濯琢託鐸濁諾????蛸只 という結果で、?の部分の文字がうまく表示できません。 (MS-DOSで動く同じ programの出力に、Windows版の画面で化ける部分の 修正を加えたものです。 ?は画面上は縦長■表示になっています。) 元々英語版の WindowsNT/95用に開発されていますが、MS-DOS版のように、 日本語版の Windows上で動かして、日本語文字表示が、ほぼ支障ないように なるといいなと思っています。 ということで、 Jeffery教授に、日本語版 Windows95で、動かしたときの レポートを 送っています。 日本語表示を検討してみよう言っていただいて いますので、日本語もほぼ支障なく表示できる版ができるかもしれません。 なにか参考書が無いかと聞かれましたので、私も読んでいないのですが、 "Developing International Software for Windows 95 and Windows NT" という本を紹介しました。役に立つと良いのですが。 あちらには、日本語版 Windows95やNTはありませんので、テスト版を作って いただいて、こちらでテストすることになります。 ほぼ日本語表示に支障無い版ができましたら、またお知らせします。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) BGM: 泣けちゃうほどせつないけれど/岡本真夜 (pcv0705a.txt 1997/07/05 PCVAN PIG,SLABO,niftyserve FPL,FGALTS) ■ Icon > ちょっと Icon(6)Icon Newsletter No.53 風つかい Iconのサポートは、アリゾナ大学の Icon Project で行っていますが、年2回、 Newsletterを発行しています。 以前は、希望者に冊子で配布していましたが、現在は WEBで見ることができ ます。 No.53が公開されていましたので、ご興味のある方は、のぞいて見て下さい。 http://www.cs.arizona.edu/icon/newsletter/inl53/inl53.html No. 53 -- August 1, 1997 Contents Icon in Java Icon Documentation in Japanese Handbook of Programming Languages Icon Analyst Promotional Offer Programming Visualization Course No.50以降は、http://www.cs.arizona.edu/icon/newsletter/inl.html から linkが張ってあります。 目次をご参考に。 No. 52 -- April 1, 1997 Contents Mail-Order Program Material Teaching Icon Web Links Native Interface Components in Windows Icon 9.3 Programming Language Handbook From Our Mail Knowledge Explorer No. 51 -- December 1, 1996 Contents Third Edition of The Icon Programming Language Graphics Programming Book Version 9.3 of Icon Version 9.3 of the Program Library New MS-DOS Implementation Icon in Java Teaching Icon Web Links Chicon No. 50 -- August 1, 1996 Contents Third Edition of the Icon Book New Implementations of Icon Icon for Chinese Computing Teaching Icon Book Sale! Web Links From Our Mail 尚、No.44以降は、次の所に pdf形式で置いてあります。 pdf形式ファイルの表示 には Acrobat Readerが必要ですが、http://www.adobe.co.jp/ から入手できます。 ftp://ftp.cs.arizona.edu/icon/doc inl44.pdf 10-Aug-95 00:00 124K inl45.pdf 10-Aug-95 00:00 187K inl46.pdf 17-Oct-95 00:00 270K inl47.pdf 25-Nov-95 00:00 268K inl48.pdf 25-Nov-95 00:00 378K inl49.pdf 17-Mar-96 00:00 550K inl50.pdf 14-Jul-96 00:00 563K inl51.pdf 05-Dec-96 00:00 508K inl52.pdf 27-Mar-97 22:31 82K <-これはサイズがおかしいですね。 壊れているみたい。 (現在は、正常なものに置換されて います。) おまけに、Icon関係の WEB LINKをあげておきます。 http://www.cs.arizona.edu/icon/index.html http://www.cs.utsa.edu/research/icon/icon.html http://www.nmt.edu/tcc/help/lang/icon/homepage.html http://www.eleves.ens.fr:8080/home/espie/icon/ http://www.crl.com/~spm/unicon/ 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) (pcv0801a.txt 1997/08/01 PCVAN PIG,SLABO,niftyserve FPL,FGALTS) ■ Icon > ちょっと Icon(7)Icon Ver9.3 (Windows95/NT) 風つかい Iconの Windows95/NT版が、新しい版がリリースされてました。 今度の版は、フォントは限定されますが、日本語も画面に出せます。 Iconは、Arizona大学の Griswold教授(のグループ)が 開発していますが、 WindowsNT/95対応の Icon(Wicon)は、Arizona大学にいて、その後 Texas大学 San Antonio校(UTSA) に移った Jeffery教授(のグループ)が開発しています。 Windows95/NT版ファイルは、次のところから入手できます。 ftp://ringer.cs.utsa.edu/pub/icon/nt/graphics/ README 4 Kb Fri Aug 08 16:13:00 1997 docs.zip 34 Kb Fri Aug 08 05:49:00 1997 Zip Compressed Data iconhelp.zip 605 Kb Fri Aug 08 05:50:00 1997 Zip Compressed Data ipl.zip 866 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data keysyms.icn 3 Kb Thu Feb 08 00:00:00 1996 vib.zip 119 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data vibsrc.zip 96 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data wi.zip 53 Kb Fri Aug 08 05:52:00 1997 Zip Compressed Data wicon.zip 631 Kb Fri Aug 08 05:53:00 1997 Zip Compressed Data 中身は、 README : 説明 docs.zip : Document iconhelp.zip : Help file ipl.zip : BIPL,GIPLの Procedure keysyms.icn : GIPL(基本ライブラリー)に含まれるが修正されているとのこと。 vib.zip : Visual Interface Builder (Iconで書かれたグラフィック インターフェース作成 ツールです。) vibsrc.zip : 同上のソース wi.zip : ランチャー wicon.zip : コンパイラ(ソースから中間言語生成)と(中間言語)の 実行解釈実行 となっています。 実際に動かすには、この他に BIPLが必要です。また、Graphicのサンプルプログラム は、GIPL(グラフィックライブラリー)に入っています。 ipl.zipは、GIPLの内 procedureを取り出したものです。 BIPLと GIPLは次の所にあります。 ftp://ftp.cs.arizona.edu/icon/library/ README 1 Kb Sun Feb 16 13:08:00 1997 VQUEENS.NOTE 197 bytes Sun Jan 05 00:00:00 1997 bipl.lzh 1190 Kb Wed Nov 27 00:00:00 1996 bipl.sea.hqx 1652 Kb Wed Nov 27 00:00:00 1996 Macintosh BinHex Archive bipl.tar.Z 1445 Kb Thu Nov 28 00:00:00 1996 Compressed Data bipl.tar.gz 967 Kb Sun Feb 16 13:05:00 1997 GNU Zip Compressed Data gipl.lzh 1092 Kb Wed Nov 27 00:00:00 1996 gipl.sea.hqx 1486 Kb Wed Nov 27 00:00:00 1996 Macintosh BinHex Archive gipl.tar.Z 1821 Kb Thu Nov 28 00:00:00 1996 Compressed Data gipl.tar.gz 1200 Kb Sun Feb 16 13:05:00 1997 GNU Zip Compressed Data info.lzh 16 Kb Wed Nov 27 00:00:00 1996 info.sea.hqx 40 Kb Wed Nov 27 00:00:00 1996 Macintosh BinHex Archive info.tar.Z 20 Kb Wed Nov 27 00:00:00 1996 Compressed Data info.tar.gz 14 Kb Sun Feb 16 13:05:00 1997 GNU Zip Compressed Data vqueens.icn 7 Kb Sun Jan 05 00:00:00 1997 インストールはこんな感じです。 【ディスクへの格納】 D:\ +wicon | | | +wi.bat <--- wi.zipから | +noop.bat <--- wicon.zipから | +wicont.exe <--- wicon.zipから | +wiconx.exe <--- wicon.zipから | +xxxx.hlp <--- iconhelp.zipから | | | +gipl | +include | | +aaa.icn <--- GIPLの include関係ファイルをそのまま入れる | +procs | | +bbb.u1 <--- GIPLの procedureを 中間言語にして入れておく | | +bbb.u2 | +progs | | +ccc.icn <--- GIPLのプログラム | +my_procs | | +ddd.u1 <--- 自分で作成した procedure | | +ddd.u2 | +my_progs | +fff.icn | +bipl | +include | | +hhh.icn <--- BIPLの include関係ファイルをそのまま入れる | +procs | | +iii.u1 <--- BIPLの procedureを 中間言語にして入れておく | | +iii.u2 | | | +progs | | +jjj.icn <--- BIPLの プログラム | +my_procs | | +kkk.u1 <--- 自分で作成した procedure | | +kkk.u2 | +my_progs | +lll.icn | という風にディスクに格納します。 【環境変数の設定】 次の4つの環境変数をセットしておきます。 IPATH=d:\gipl\procs d:\gipl\my_procs d:\bipl\procs d:\bipl\my_procs LPATH=d:\gipl\include d:\bipl\include ICONFONT=FixedSys WICONLOG=d:\wicon\Wicon.log IPATH は中間言語形式にした Iconの procedureを入れておくと、他のプログラム からの link指定で、その procedureを引用できるディレクトリーの指定です。 LPATH は ソースプログラムの一部として、他のプログラムの $include 指定で その プログラムを引用できるディレクトリーの指定です。 ICONFONT は、使用フォントの指定です。私の環境では、FixedSysと Systemが 有効みたいです。 WICONLOG は、動作ログのファイル指定みたいです。(よく分からないのですが 指定しないと、コンパイルの度に指定しろとメッセージがでるもので。) 【起動】 WI.BATを起動すると、Wiconが起動されて、エディターウィンドウが開きます。 そこから、Iconのソースプログラムを選択するか新しいソースファイル名を入力 して、プログラムを修正/作成して、コンパイル(make)すれば、実行モジュール ができます。 この辺は、実際に動かして見たほうが早いでしょう。 【サンプル】 GIPLにサンプルが入っていますので、動かしてみて下さい。 その中の GPXTEST.ICNは、GIPLのサンプルプログラムで、グラフィック機能の動作 テストのプログラムです。面白い絵がでてきます。 尚、vqueens.icnは修正版があります。GIPLの中のものは、ファイル不足エラーがで ます。修正版が ftp://ftp.cs.arizona.edu/icon/library/vqueens.icn にあります。 【プログラムソース】 プログラムソースは、 ftp://ringer.cs.utsa.edu/pub/icon/nt/src/ にあります。 README 2 Kb Wed Aug 06 01:48:00 1997 c.zip 155 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data cmn.zip 72 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data h.zip 83 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data msvc50.zip 15 Kb Wed Aug 06 00:39:00 1997 Zip Compressed Data p.zip 42 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data r.zip 364 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data rtl.zip 100 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data rtt.exe 275 Kb Fri Jan 26 00:00:00 1996 Binary Executable t.zip 88 Kb Tue Aug 05 15:32:00 1997 Zip Compressed Data wincap.zip 40 Kb Thu Feb 01 00:00:00 1996 Zip Compressed Data 【日本語の扱い】 Iconの文字列処理は、1バイト単位で行います。日本語の文字の区切りを意識し たプログラム以外では、支障は起きません。日本語の文字の区切りを意識するの が必要ならそういう procedureを組めば可能です。 しかし、画面出力はまた別問題です。Windows95/NT環境で、画面の文字を出力す る際には、現バージョンでは 次の制限があります。 ・フォントの制限 フォント指定が、自由にはできない。FixedSysと Systemの指定は有効みた いです。 ・日本語出力のやり方 コンソールウィンドウへの日本語文字出力や、生成したウィンドウへの日本 語文字出力では、バイト単位で出力すると文字が化けます。文字(2バイト) 単位で出力すれば大丈夫でした。 ですから、文字列を表示させるには、支障はありません。 (また、ファイルに出力する分には問題ありません) 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) (pcv0810a.txt 1997/08/10 PCVAN PIG,SLABO,niftyserve FPL,FGALTS) ■ Icon > Icon散歩道 むすび 風つかい 散歩道では、テキスト解析をやろうと思っていたのですが、殆ど 以前の講座 のミス修正と 思いつき programの解説になってしまいました。 散歩道で予定していました 数式解析とかは 全然 手をつけていませんが 秋も 終わりですので、この辺で Icon散歩道 を終わることにします。 お付き合いいただきまして、ありがとうございました。 では、また、お会いする日まで。 風つかい (TRA11936@biglobe.ne.jp/PFF01531@niftyserve.or.jp) < IconのWWWは、http://www.cs.arizona.edu/icon/index.html> (iconlec4.txt 1997/11/24)