連載 LittIe Language srekcah@sra. CO. jp 自由きままに GNU AWK(3) AWK の近況 う噂を耳にしました。これもおもしろそうなので、ぜひ論 から C 十十への変換プログラムに関する発表がある、とい す。また、 USENIX の C 十十コンファレンスでは AWK にみられ、実際に販売されているプログラムもあるようで AWK から C への変換プログラムのアイデアは文献 [ 1 ] もひろがってきます。 とができます。また、自然言語処理などの応用分野 [ 6 ] [ 7 ] で使われるさまざまな構文の解析部を簡単に作成するこ yacc のような構文解析部生成系があれば、コンパイラ す。 たいと言っていたのですが、こちらはどうもまだのようで れ、 AASL のほうもコンファレンスでは近日中にポストし するものです。 awf はすでに UUNET のニュースに流さ AASL は、文法を入力して awk のソースコードを生成 成した、という報告です。 や yacc ( 構文解析部生成コマンド ) もどきの AASL を作 ていました。内容は、 AWK を使って roff もどきの awf As A Major Systems Programming Language) となっ なシステムプログラミング言語としての AWK 」 (Awk ました [ 5 ] 。なかなかうまいタイトルがついていて、「主要 コンファレンスで AWK の活用事例について発表があり だいぶ前のことになりますが、 1991 年冬の USENIX りあげました。今回はすこし大きな例をお目にかけましょ 以前の GNU AWK の回では、い X 関連のものをと 106 文を読んでみたいものです。 AWK ⅲ AWK に向けて 言語を扱っていて興味深いのは、言語変換やプートスト ラップーー自分で自分自身を作りだすことです ()S など では、その開発システムや、プートストラッピングの仕組 みをあれこれ考えるのが楽しみ ) 。そんなわけで、 AWK の 活用について発表を聞き、 AWK を使って自前で AWK を生成するシステムを作ろうと思いたちました。 AASL に対抗して、ある言語文法を与え、その構文解析 をおこなう AWK のプログラムを自動生成するメカニズ ム (yacc あるいは Bison / AWK ) を目標にします。自動生 成するプログラムも、 AWK で記述してあれは統一がとれ てきれいなものになります。なお、 Bison は yacc 互換の GNU ソフトウェアで、詳細については文献 [ 6 ] [ 7 ] を参照 してください。 さて具体的なプログラムに入る前に、構文解析やその生 成系など、コンパイラ関係の用語を紹介しておきましよう。 コン / ヾイラ コンパイラの内部構成は、一般的に図 1 のようになって います。 字句解析部では、ソースプログラムから 1 文字すっ読み 取り、数値や id といったひとかたまりの文字、、トークン〃 に分解します。構文解析部では、そのトークンを入力とし て文法のどの要素に一致するかを調べます。意味解析部で は、調べた文法にしたがって対応するオプジェクト・コー ドに変換していきます。オプジェクト・コードは機械語と はかぎりません。中間語 ( n 項組やリスト表現 ) の表現です。 最適化部では、文字どおりオプジェクトを最適化します。 UNIX MAGAZINE 1991.7
LJN Ⅸ流プログラ % cat penv. c mam(argc , argv, envp) ミング 9 int char char char argc ; * 矼空ロ ; *envp[] ; *Ptr; if (argc > 1 ) { if (ptr = ( 矼 *)getenv(argv[l])) { puts (ptr) ; exit ( の ; exit(l) ; } else { while ( * e 取 ) { puts (*envp++) ; exit ( 0 ) ; とても簡単でしよう ? 環境変数すべての値が必要なら envp を用いるほうがよいのですが、特定のものだけなら getenv のほうが簡単です。 さて、当初の目的に戻りましよう。環境変数が設定され ゝていればその値を、そうでなければデフォルトの値を用い る、ということでしたね。すでに準備は整っていますから、 さっそくプログラムを見ていくことにしましよう。 % cat prog ・ c main(argc, 矼空 ) int argc ; char char if ( ! (str = (char *)getenv("STRING"))) { "default string' str puts (str) ; このプログラムは、 STRING という環境変数に値が設 定されていればその値を、そうでない場合にはデフォルト の文字列 "default string" を出力します。 今回は、環境変数をプログラムから利用する方法につい てお話ししました。かならす設定しておきたいオプション などは、環境変数で指定できればプログラムも使いやすく なります。具体的にカスタマイズする方法にはあまり触れ ませんでしたが、以前に説明したオプションによるカスタ マイズを参考にしてください。実際には、環境変数はオプ UNIX MAGAZINE 1991.7 ションよりもさきに設定しておくのが普通です。なぜなら、 環境変数で設定してあるものをオプションで別の値に変え ることが可能だからです。環境変数の処理をあとにしてし まうと、オプションを指定しても環境変数の設定のほうが 優先されてしまい、オプションを設定する意味がなくなっ てしまいます。 さて、次回もコマンドのカスタマイズに関連したお話で すが、環境変数ではなくファイルを使ってみることにしま しよう。 153 ( いまいすみ・たかし東京工業大学 )
連載 / Li Language— リスト 5 テパッグ清報の出力 % a. out 1 Starting parse Entering state 0 Reducing 0 values via ロ 11e 1 (line 18 ) , state stack now 0 Entering state 0 Start1ng parse @ext12 % a. out debug NO at end of input ・ Shifting token 0 ((null)) , Entering state 22 Reading a token: NO at end Of input ・ Entering state 1 Reducing 0 values via rule 1 (line 18 ) , state stack now 0 Shifting token 258 (NUM) , Entering state 2 Next tOken is 258 (NUM) Reading a token: 2 10 Entering state 1 ←人力文字列 Reduc1ng 1 value via ru1e 5 (line 26 ) , state stack no 0 1 Entering state 7 Reading a tOken: Next tOken is 94 ( ” , ) Shifting token 94 ( 冖 ' ) , Entering state 14 Reading a token: Next tOken is 258 ( 肌 ) Shifting tOken 258 (NUM) , Entering state 2 Reducing 1 value via rule 5 (line 26 ) , state stack れ OW 0 1 7 14 er 土れ g state 21 Reading a token: Next tOken is 10 ( '\n') Reducing 3 values via ロ 11e 11 (line 32 ) , state stack no 0 1 Entering state 7 Next token is 10 ( ' \ Ⅱ ' ) Shifting token 10 ( ' \ ) , Entering state 15 Reducing 2 values via rule 4 (line 23 ) , state stack no 0 1 Fmtering state 6 1024 Reducing 2 values via ロ 11e 2 (line 19 ) , state stack no 0 補足 . Bison について NO 曾 at end of input. Shifting token 0 ( ( 取 u11 ) ) , Entering state 22 Reading a token: NO at end Of input. Entering state 1 ←ここで団 F 文字を人力 本題からはすれますが、こで使用している Bison の使 用例も示しておきましよう。これは、 Bison が生成した C 言語の構文解析ルーチンが動くことを示します。 1024 2 10 % a. out % cc —DYYDEBUG tl . tab. c —lm 2 10 % a. out % cc —DYYDEBUG tl . tab. c —lm ラムを記述する際には、たいへん役立ちました。 助けになります ( リスト 5 ) 。今回の一連の AWK プログ の内部状態が分かり、文法のデバッグや内部動作の理解の yydebug という変数を true にすれば、構文解析ルーチン ( 末尾のリスト 10 ) 。このなかで YYDEBUG を定義して 例として使用した tl. y は、文献 [ 8 ] を参考にしました 110 今回は、 LR 構文解析コマンドを作り、そのテストとテス トに必要なデータを作る仕組みまでを紹介しました。これ については、文献 [ 7 ] がよい刺激になりました。世のなかに は、旧い AWK(GAWK は新しい AWK の機能をサポー トしている ) を使って nroff や yacc もどきを作っている 人がいる、ということです。それが記憶に残っているとこ ろへ、なにげなく AWK のバイプル [ 1 ] をめくっていると 構文解析プログラムの例が 2 、 3 でているではありません か。これなら、文法を与えてやれはその構文解析プログラ ムができそうだと考えたわけです。 そこでコンパイラの専門書をあたってみると、 yacc や Bison が採用している LR 構文解析を使うのが一般的な ようで、アルゴリズムとその説明が詳しくでていたので実 際に作ってみました。いわば、、トーイ構文解析プログラム〃 です。参考文献の例と同様に動作するかどうかを確かめる ために、そこで採用されている記述方法をそのまま用い、 構文解析表としました。 しかし構文解断表を生成するプログラムを作る前には、 後日談 UNIX MAGAZINE 1991.7
7 U-TERM 94 資料請求 N 。 00A TEL. 03 ー 3590 ー 52 Ⅱ ( 代表 ) FAX. 03 ー 3590 ー 5353 〒ロー東京都豊島区池袋 2 ー 437 池袋青柳ビル lnformation and Mathematical Science Laboratory,Inc. 第情報数理研究所 開発及び販売 価格 48 , 000 円 ( 消費税は別途 ) そ也多彩な機能満載、しかも低価格実現 の操作。 イル送受信が自在。コマンドは、 UNIX の cu と同様 UNIX ホストと DOS ファイルの間でのテキストファ ・ファイル転送機能 らの選択。 フロー制御は XON / XOFF による制御法と信号法か 使用可、しかも、その高速処理は群を抜く。 75baud から、 19200baud ( クロック 10MHz 以上 ) まで うち 1 チャンネルを選択使用。 RS- 232C 拡張インタフェースポード 3 チャンネルの ・通信機能 ードを含む。これらは、ローカルに変更可。 カーソルの形状変更、プリンクの有無などの制御コ 位互換を持つように拡張されている。ビジカレベル、 JIS と重複する画面消去コードを除き、 PC9801 と上 ・画面制御機能 ード。カラーでの出力も可。 テクトロニクス 4014 端末に準拠したグラフィックモ ■グラフィック機能 るため、 EUC コードや DEC コードにも完全に対応。 サポート。 JIS 初期値と JIS 現在値を任意に変更でき 択。 JIS のモードでは、全ての文字コード拡張手順を 文字コードは、 JIS か MS 漢字コードの 2 種類から選 ・日本語機能 パソコンが UNIX WS の有能な端末に 曰ト機能のし花 M (MS-DOS ノヾージョン 3 コ以降 ) EPSON-PC286 シリーズ用 NEC ー PC 98 田シリーズ用 ロック単位です。コマンドのなかには cat のようにバッフ アリングをやめるオプションが用意されているものもあり ますが、すべてにあるわけではありません。このため、困 ったことになる場合があります。たとえは、次のようなコ マンドの実行を考えてみましよう。 % vmstat 10 3 ー sed —n p ー cat vmstat は 10 秒間隔で 3 回メッセージを出力しますが、 中間の sed の出力パイプを介しているためにプロック・バ ッファリングされて、 30 秒経過するまで何も表示されす、 最後に全部の出力がまとめて表示されます。これはつまら ない例ですが、このようなパイプの使い方をしたくなるこ とはあるものです。 これは、 pty を使えは次のようにして解決できます。 % vmstat 10 3 ー pty ー 0 sed -n p ー cat sed は、 pty コマンドの引数に指定すると別の pty 上で 実行されるため、標準出力は端末とみなされて行バッファ リングがおこなわれます。 オプション一 O はおましないと思ってください。しつは、 この使い方にはすこし問題があります。 pty で実行された コマンドが EOF を受け取ってくれないのです。マニュア ルにも、これはあまり好ましくない制約でいすれ解消する つもりだ、と書かれています。とりあえすは C です。 端末じゃないとイヤ スクリーンエデイタのⅵをデモするシェルスクリプト を作ってみましよう。次のような内容の videmo というフ ァイルを作ります。 # ! /bin/sh echO ' : e ! /etc/temcap sleep 3 echo ーⅡ FFAFADAD ' sleep 3 echo ーⅡ sleep 3 echO ・ これを実行してパイプでⅵに送れば、 /etc/termcap を 開き、時間をおいて何回かスクロールして、最後に終了し てくれるはすです。しかし、やってみるとどうもうまくい UNIX MAGAZINE 1991.7
連載 . / / 凵眈 { printf("\t%. 10gⅥ", $ 1 ) : } exp '\n' Language¯ リスト 9 文う態リ変換プログラム (tran-grammar) in-gramar = 0 { next; } / - % % $ / { in-grammar + + ; next; } BEGIN {in—gramar = 0 ; lhs gawk ' #or(l) の処理。前に登録した s を使う next ; read-and-print(), granunar) ; gramar 、 = lhs = substr($l, 1 , length($l) ー 1 ) ; # "lhs : " という文字列を仮定 # 1 を読み込み、登録と出力をおこなう read-and-print(), gramar 、 ) ; granunar = lhs ”ー > next ・ 、 anuna-l 、 = , next;} %token 訊 #include く math. h> #define YYSffPE double #include く ctype ・ h> / * lnfix notation calculator--calc * / リスト Bison の入力ファイル例 ( t に y ) { next;} exit(0) ; for (i = start; i く = NF; + + ) { function read-and-print(start, gramar) { # START 番目の項目から読み込んで、 GR.M()R に追加したあと出力する break; if (i = ) break; print grarnmar ・ gramar = gra-mar break; else if ()i ~ た % / ) break; if ( 1 = ) break; if (i = ) else if ()i = = 野 e 。て (s) / * Ca11ed by yyparse on error * / # コメントをスキップ # 実行部をスキップ # で始まる部分もスキップ %left NEG %right ' / * negataon--unary mnus / * exponentiation / * Gramar f0110 響 s * / input: line: / * empty string * / input line char *s; printf ( " な " , s) ; yylex ( ) int c; ⅶ 11e ()c = getchar ( ) ) if (c = = ' Ⅱ isdxglt (c)) ungetc (), stdin) ; scanf ("%lf" ylv 訌 ) : て et Ⅱロ 1 M 川・ if (c = EOF) return 0 ; return C,• exp exp exp , 十 , exp exp exp exp exp %prec exp main (argc, 矼空 ) char * 矼空ロ ; (argc > 1 ) int argc; yyde yyparse( ・ 116 '\t') / * sk1P vhlte space * / / * process numbers * / / * return end—of—file * / / * return single chars * / UNIX MAGAZINE 1991.7
0 ワロ OITlROn フローチャート・ OLLO が自在に描ける。エンジニアのみなさん、 図形機能つき DZ ー X 日本語ワープロ誕生で エンジニアのみなさんの喜ぶ顔が目に浮かぶよ設計者から事務処理の方まで、ワークステーシ うでドキュメント作成に欠かせないイラスト ョンでのドキュメント作成が驚くほど、便利に簡 やフローチャート C)LLQ ( テータフローダイヤ単になりました。 グラム ) などの図形か自在に描けるようになり X ー・ーを利用して「楕円」「四角」「菱形」 ました。従来の文字・罫線機能の日本語ワード 「直線・斜め線」「円弧径」などの図形や、太い・細い プロセッサ「ロ / ZOPU.J 」に、図形機能を追 実線・点線などの線が描けます・キーボードのほか 加した「 / ZOFUJ ー図形」の誕生です。もにマウスがこ利用できます・画面上には <(< サイズ ちろん、操作性、手軽さは従来の「ロ / ZOF ーベージ、メニューを同時に表示しています・図形の 」の良さをそのまま活かしています。開発者・ 編集も自在に行なえます。 うんー 図形機能つき LJN Ⅸ日本語ワーフロ 中一 OTE - 図形 \ 128.000 ( 税別 ) 2 Open Window(Sun) にも対応 適応機種 オムロン「 LUNA シリーズ」全機種 サンマイクロ「 Sun3, SPARC station, server 」 富士通「 S ファミリー」、東芝「 AS シリーズ」、 新日鉄「 NSSun シリーズ」 松 F 「ソルポーンシリーズ」等 IJN Ⅸ日本語ワードフロセッサ 好評 dp/NOTE 発売中 オムロンソフトウェア株式会社 SP 事業推進センタ 〒 604 京都市中京区烏丸通四条上ル京都フクトクヒル TEL075 ( 223 ) 0631 代 FAX075 ( 223 ) 5834 資料請求 N 。 . 9
連載 . / ーー凵 # 構文解析表の読込み Language read—pars*ng table(action, goto) ; # 構文解析 if (debug) printf("init stack\n") ; init—stack() ; sp1it()O " $ " , input) ; if (debug) # 文法の読込み print F Ⅱ . 日語ー化 " : accept. \Ⅱ" else print "stdin: accpt ・ \n" parse(input, action, goto) printf("now parse\n\n") ; ⅱ (debug) printf("first input = l%s l\n", input[l]) ; if ( $ 0 ~ /End Of Grammar/) printf("gr = (%s)\n" , $ の : if (debug) 1 ; getline く file > 0 : for (i function read—grammar(rule) { return• rule[i] = $ 0 ; print myname exit(l) ; # 構文解析表を読み込む cannot find of Grammar mark. " ・ function read—parsing—table(action, FSsave = FS ・ if (debug) printf("readxn id\n") ; if (getline く file く 1 ) { goto) { print myname cannot get id table. " ・ printf("idl%sl\n", (i) ; if (debug) fo て (i = 2 ; i く = NF; i + + ) { exit ( 2 ) ; if (debug) 1 ; i く = NF for (j printf "nid=%d\n" , nid) ; if ()e ) nid = i + + ー 1 ; break; id [i printf("nontem[%d] = ーなー " , 」 , $i); if (getline <file く 1 ) { while ( 1 ) { printf("readin table\n") ; if (debug) printf "nnt=%d\n", nnt) ; if (de nnt = NF ー nid ー 1 ; れ 0 Ⅱー tel 測 inal [ j + + ] = $i; 112 for (i = 1 ; i く = nid; i + + ) { printf("table = (%s)\n" , $ 0 ) ; if (debug) break; if ( $ 0 ~ /End Of Tab1e/) exit(l) ; print myname : cannot find Of Tab1e mark't ・ # 人力文字列の最後に " $ " を加えておく # 結果を出力する # 非終端子記号 # i 己号 # id と非終端子一覧を読む # それぞれのエントリのとり込み UNIX MAGAZINE 1991.7
連載 UNIX Communication Notes % ypmatch neverheard hosts. byname Can' t match key neverheard in map hosts. byname. Reason: Ⅱ 0 such key in map ・ となります。検索のルールは、以下のとおりです。 検索が成功する。部分文字列での一致はしない。 ・んが複数指定された場合には、以下の例のようにそれ ゝ ・んとマップ内のキーが完全に一致した場合にかぎり、 / ぞれのキーにマッチしたものが出力される。 % ypmatch jupiter neptune hosts. byname 133.1.12.55 Jupiter Jupiter. ics. osaka-u ・ ac ・ JP 133.1.12.254 neptune neptune. ICS. osaka—u. ac ・ JP ypmatch には、マップ名として passwd をえた場合 に passwd. byname として処理する機能があります。 の passwd をゞニックネーム (nickname)" と呼び、次ペ % ypmatch —k jupiter hosts. byname ypmatch では、次のオプションが利用できます。 ージの表 2 に示したものだけが定義されています。 -d 襯砒ツ 川 4 切のサーバーに対して問い合わせます。 検索結果を表示するとき、キーもあわせて表示します。 たとえば、前掲の例では、 jupiter: 133.1.12.55 jupiter jupiter. ics. osaka-u. ac ・ JP というように、行頭にキーが表示されます。このオプシ ョンは、 netgroup などを調べる場合に便利です。 プションをつけると hosts が hosts. byname に展開さ ニックネームの展開を抑制します。以下の例では、 -t オ ゝ れないことを示しています。 Use "group" for map group ・ b 坦 e " Use 'tpasswd't for map passwd. byname" % ypmatch —x ます。標準では、次のように表示されます。 ニックネームがどのように設定されているかを表示し ¯X Can't match key jupiter in map hosts. % ypmatch —t Jupiter hosts 133.1.12.55 Jupiter Jupiter. ics. osaka¯u ・ ac ・ JP % ypmatch jupiter hosts Reason: 0 such map in server' S domain. Use "networks" for map "networks. byaddr' Use "hosts" for map "hosts. byname' Use "protocols" for map protocols. bynumber' % ypcat passwd. byname Use for tservlces. byname Use "aliases" for map "mail. aliases' Use "ethers" for map "ethers. byname' ypcat ypcat は、指定したマップの内容を表示するコマンドで す。たとえはマップ passwd. byname を見るには、次のよ うにします。 yamaguti : t1FbxJ0vrqvcU: 6001 : 600 : Suguru Yamaguchi : /home/raicho/suguru: /bin/bash UNIX MAGAZINE 1991.7 77
引数をつけると、それと同し名前の環境変数の値が出力さ れます。 次は B シェルの場合です。 B シェルの場合も printenv コマンドで環境変数の値が出力できます。ところが、 setenv コマンドや unsetenv コマンドは使えません。これ らは C シェルの内部コマンドであり、 B シェルには同名の コマンドがないからです。だからといって環境変数が設定 できないわけではありません。シェル変数をすこし細工す シェル変数名 = 値 シェル変数は通常、 れば、環境変数として使えるのです。 という形式で代入します。こうして代入したシェル変数を、 ( シェル変数名 = 値 , ; シェル変数名 = 値 , export シェル変数名 export シェル変数名 とすれば、シェル変数は環境変数となります。 B シェルを 使っている場合には、 unsetenv に対応するような取消し 方法はありません。しかし一時的に環境変数を設定してコ マンドを実行することは可能です。その場合は、 シェル変数名 = 値 . . シェル変数名 = 値コマンド引数 とします。このとき実行するコマンドに対しては、指定し たシェル変数と値のペアが環境変数として設定されます。 このあと実行するコマンドには、なんの影響もおよばしま 同しことは、次のようにしても実現できます。 せん。 ; コマンド引数 ... ) これらは B シェルの機能ですが、同等の機能を C シェル (setenv 環境変数値 , setenv 環境変数値 ; コマンド とします。カッコで囲まれたコマンドはサプシェルで実行 されるので環境変数の割当ては有効ですが、カッコの外で は無効になります。つまり、一日勺に環境変数が設定でき るのです。 B シェルで環境変数を使う B シェルを用いたプログラムを書くときは、変数にはシ ェル変数を使います。しつは、シェルプログラムのなかで は環境変数はシェル変数と同様に扱えます。ためしに、環 境変数 STRING に設定された文字列を出力するプログ ラムを作ってみましよう。 string % str—test % setenv S ・ IRING test—test % str_test % setenv STRING test-test echo $STRING # ! /bin/sh % cat str—test string このプログラムは、通常は正しく動作します。 148 の場合を見てください。 しかし次 で実現することもできます。この場合は、 引数 ... ) % unsetenv SIRING % str_test ります。今回は、後者の機能を使ってみることにしましょ されていなければなにかの値を使用するなど、いろいろあ は、変数の値を設定とは別のものにするとか、変数が設定 よって動作を変えられる変数の置換機能があります。これ という形式にします。 B シェルには、変数の設定の有無に $ 変数名 のように シェル変数の値を参照するには、さきほどのプログラム こんなときにはシェル変数の置換機能を利用します。 場合、デフォルトの値を使うようにしなけれはなりません。 このように環境変数 STRING の値が設定されていない 今回は環境変数をオプションとして使おうとしています。 プログラムは次のようになります。 という形式で使用します。これを応用すると、さきほどの $ { 変数名 = 代人する値 } つ。これは、 UNIX MAGAZINE 1991.7
連載 / / Li Language return; else { print myname exit(l) ; { . 髯幻 ル . ト . 0. 0 ・ 1 function init—stack ( ) { function push(s) { stackC + + sp] = s; t>> いり ; リスト 7 実行列 2 @ext12 % LR-parser grammar—and—state¯table dump=l tl debug=l ー く stack> Ⅱ 0 ー ー id * id + id $ $ Ⅱ くく input>> く stack> Ⅱ 0 id 5 ー ー * id + id $ $ Ⅱ くく input>> [ 6 ] F ー > id く stack> Ⅱ 0 F 3 [ 4 ] T ー > F Ⅱ 0 T 2 く stack> Ⅱ 0 T 2 * 7 ー く stack> Ⅱ 0 T 2 * 7 id 5 く stack> id Ⅱ く stack> 0 T 2 * 7 F 10 [ 3 ] T ー > T * F Ⅱ く stack> 0 T 2 [ 2 ] E ー > T く stack> Ⅱ 0 E 1 く stack> Ⅱ 0 E 1 + 6 ー く stack> Ⅱ 0 E 1 + 6 id 5 [ 6 ] F ー > id く stack> Ⅱ 0 E 1 + 6 F 3 [ 4 ] T ー > F く stack> Ⅱ 0 E 1 + 6 T 9 [ 1 ] E ー > E + T く stack> Ⅱ 0 E 1 tl: accept ・ id $ init stack first input = は田 no 響 parse く stack> Ⅱ 0 ー ー * id + id $ $ Ⅱ くく input>> * id + id $ $ Ⅱ くく input>> id + id $ $ Ⅱ くく input>> くく xnput>> くく土れ put > > くく 1 れ put > > くく input>> ー id $ $ Ⅱ くく input>> くく put > > くく input>> くくれ put > > くく input>> ーポードから人力した文字列 ← - キ ー id $ $ Ⅱ くく input>> now in は引 action=(s5) , entry(s) , 5 く stack> Ⅱ 0 id 5 ー くく input>> ー nov ⅲ action=(r6) , entry(r) , 6 eliminate 2 stack top = 0 , a = F to = 3 ] F → id く stack> Ⅱ 0 F 3 ー くく input>> ー れ。ⅲー引 114 UNIX MAGAZINE 1991.7