T プログラミング SPARC List 6 Li st 6 109 : 1 10 : 1 12 : 113 : 第 1 14 : 115 : 116 : 118 : 119 : 120 : 121 : 122 : } ・ 123 : 124 : barcode 8(num, moji) 125 : char n 諞冂 [MOJILEN] : char moj i ロ [ MO 引し EN 」 : 126 : 127 : 128 : char x [ MO 引し EN] : 129 : char xx [ MO 引し EN] : 130 : char kai [MOJILEN] : 131 : char *pt ・ 132 : WORD i; 133 : char num2 [- し ABE し NUM] [MOJ ILEN] : 134 : swi tch (Gbark i (d) { 135 : 136 : case 5 : 137 : case 15 : 138 : Gketa = 12 : 139 : break; 140 : case 6 : 141 : case 16 : 142 : Gketa ニ 7 : 143 : break : 144 : 145 : 146 : 147 : 148 : 149 : strcpy(num[i], number ) : strcpy(moji [i], samen 十十 if( samen % Gpsamen) { : Gkasan; 150 : 151 : 152 : 153 : barcode_0 (num2, moj i ) : 154 : return ( の : 155 : 156 : } 157 : 158 : barcode_O(num,moji charr 00j i [MOJ ILENj : 160 : 161 : switch(Gbarkind) { 162 : 163 : case 1 : barl nw7 (num, moj i , NONHEX) : 164 : 165 : break : 166 : case 2 : 167 : barInw7(num,moji, HEX) : 168 : break : 169 : case 3 : 170 : barl cd39 (num, moj i ) : 171 : break : 172 : case 4 : 173 : barl cd39c (num. moj i ) : 174 : break ; 175 : case 5 : barl jan (num, moj i ) : 176 : 177 : break : 178 : case 6 : 179 : barl jans (num, moj i) : 180 : break : 181 : case 7 : 182 : bar1205(num, moji) : 183 : break; 184 : case 8 : 185 : barl 205C (num, moj i ) : 186 : break : 187 : 188 : return ( 0 ) : 189 : } right(kai, pt, Gketa strcpy(num2[i], kai barcode_8 (num, moj i) : form_feed ( ) : fcl ose (stdprn) : return ( 0 ) : fortom(), 0 , Gnppg) { strcpy(), num[i]) : strcpy (xx, " 000000000000000 " pt=strcat(xx, x) : 置にタイトルおよび文字列を表示する。 ・ DBOXSTR. SUN(List 5 ) ポックス型の罫線を引き , 指定の位置 に文字列 strl を表示する関数 pw text は , 文字列を表示する SunView 独 自の関数て、ある。 ・ BARLASE6. SUN(List 6 ) バーコードのプリント関連の関数 この関数は , デバイスファイルをオープ ンし , プリンタを直接制御している。本関 数の、、ミソ〃は叩 en と fdopen を使用している 点にある。まず , open 関数よりファイルハ ンドルを得 , それを用いて , ioctl 関数によ る制御を行う。これだけて、は printf などの関 数が使用て、きないのて、 , fdopen を使用して オープンしなおしている。 marknws の操作方法 marknws は , SPARC LT て開発したもの て、あるが , 基本的には SunView のみを使用 しているのて、 , 多くの SUN ワークステーシ ョン上て、稼働可能なはずてある ( 実際にソフ トバンクの SUN ワークステーションにイン ストールして操作したところ問題なく動い た。 SUN ワークステーションて注意すべき 点は , 以下に述べるプリンタデバイスを正 SPARC LT プログラミング 87 ・ SELBOXDP. SUN(List 4 ) タイトルを表示しつつ , ポックスを表 示する関数 Gbox から x 座標および y 座標を得 , その位 Fig. 3 ma 「 knws のメニュー画面 日 、 p “い : 1 ー CASSETTE— d v tt Etl T TA 0
なのか , 難しいのかを , 直属て、ない上司に 最近 , CASE はどの程度普及しています 説明することも困難て、す。私たちは , 「ソフ か ? まだ手探りの段階なのでしようか ? トウェアシステムにも , 標準設計図を整備 Wasserman 尺度は 2 , 3 あります。ひとっ する必要がある」と信じています。プログラ は , 当社をはじめ , CASE を手掛けているメ ーカーの開発実績を見ることて、す。当社は ム構造についても , データ構造についても いえることて、す。また , その設計図は視覚 長い道のりを経て , さまざまなプラットホ ームて、動く先進的な製品を作ってきました。 的て、なければいけません。システムを一定 一方 , CASE 製品を持っているプログラマを の観点から正確に表し , なおかっ , 複雑す という 数え , 使っていない人の数を引く , ぎて閉ロすることがないように十分に抽象 方法て、測るなら , CASE 環境が実際に使われ 的て、あるべきて、す。大型システムを理解す ているのは , 公平にいって 10 % 程度て、しょ るのに時間がかかるのは , 仕様書が複雑す う。それにはいくつか理由があります。第 ぎるからて、す。 1 は , CASE を使うことにどんな意味がある 先ほど , まだ CASE 技術を使っていない かわかっていないことて、す。メンテナンス プログラマが多いとおっしゃいました。な プログラミングや , ローレベルライプラリ ぜでしようか ? を使った作業をしているかぎり , CASE ツー Wasserman いろいろな要素が絡み合って ルがどんなに役立つのか , 直ちに理解て、き います。あなたは , そのマイクロカセット るものて、はありません。 レコーダーを購入してインタビューに臨み トすることて、す。今日 , CASE 環境や , 解析 ましたね。それは , 買ったほうが仕事の生 ツール , 設計ツール , プログラミング環境 産性が上がると考えたからて、す。レコーダ CASE 普及の鍵 などを採用している組織は , 何らかのソフ ーに投資すればインタビューがやりやすく トウェア工程を決めています。おそらくさ なる。投資の効果はあなたにとってかなり ほど厳密て、はないて、しようが , 一応の工程 現世代の CASE ツールは , 解析や設計やプ 明白だったわけて、す。このようにツールに を決めてあるはずて、す。これに対し , ほか ログラミングに構造化の手法を取り入れて 投資するときはいって、も , 何か新しい機能 いる人たちだけに , それなりの恩恵をもた の多くの組織は , いわゆるプログラミング が保証されなければなりません。多くの人 たとえば 環境を利用しています。つまり , らすと思います。しかし , ほかの工学分野 は , 自動ツールの働きに非現実的な期待感 と比べると , 私たちにはまだやるべきこと を抱いています。 工デイタ , コンノヾイラ , デノヾッガなどの C コ がたくさん残っています。ソフトウェア開 よくこんな話を引き合いに出すのて、す。 ードを生成するために役立つツールてす。 手元にひどいプログラムがある。アセンプ 発をソフトウェア工学に変えようと本気て、 そのいい例が TurboC て、す。非常に手頃な 思うなら , 一定の条件を整えなければなり ラて、書かれていて , ドキュメントはなく , 価格て、あり , PC て、動き , て、きることはかな ません。まず , 秩序を持たねばなりません。 設計もなく , バグが混じっている。そこて り限られていますが , きわめてうまくこな 土木工学や電気工学 , そのほかあらゆる確 明日朝起きたら , オプジェクト指向言語て、 します。こうした環境を使っている人たち 立された工学には , 設計図のようなはっき 書き直し , 完全なドキュメントをつけ , 長 も ,CASE がソフトウェア開発工程全体をサ ポートし , 小さなプロジェクトだけて、なく りしたものがあります。配線図なして、ハー きにわたってメンテナンスてきるようにし ドウェアが成り立って、しようか ? 大きなプロジェクトもカバーすれば , 移行 ちょっと虫がよすぎますよね。 ところ たい・ が , ソフトウェア工学には , 標準設計図が て、も , こんな願望を持っている人は大勢い を検討するて、しよう。 CASE は , 長期的に は , ソフトウェア制作過程て、生じる作業の ないのて、す。ほかと比較してばかげた感じ ます。もし CASE ツールがそうしたことをす っかりやってくれるなら , 大助かりてす。 がするかもしれませんが , まぎれもない事 多くを自動サポートする予定て、す。 実て、す。 それと , ソフトウェアディベロッパには , みんな先を争って買うて、しよう。 大きな問題がありますね。既存のコードを 「この C コードは全部 , ' 80 年代に書いたも ほとんどのプログラマは , 現在 , 完全に どうやってメンテナンスするか ? 新しい テキストべースて作業しています。文字て、 のなんだ。設計はしたはずだが , コードを 書かれた仕様書を読み , テキストエデイタ アプリケーションをどうやって開発するか ? 見るともはや理解てきない。頼むから , 再 同僚や上司とどのように意思の疎通を図る を使い , ローレベルて、デバッグしています。 設計を手伝ってくれないか」。実際のとこ か ? ドキュメントはどうするか ? これ 視覚表現は一切ありません。そのため , 新 たに組織に加わった人にシステム構造を説 らは本当に厄介な問題て、す。 CASE を成功さ こうした間題に真っ向から 明するのは大仕事て、す。このシステムはど せるためには , ぶつかっていかねばなりません。 んな動きをするのか , ある間題がなぜ簡単
1 C 十十の cin や cout の現状の定義の中には , ( 少なくとも Turbo C 十十が提供している ) stream. h とは非互換な部分があるのて、す。 Turbo C 十十の TPROGRAMMER'S GUIDE 』の 3 章が「 C 十十のストリーム」とな っていて , その章の終わりに , 「旧ストリー ムのコードを使用するなら iostream. h て、はな く stream. h をインクルードして旧ストリー ムのライプラリをリンクする必要がありま す」と書いてあります。 指定しなくても リンクされる L 旧と そうでない L 旧 私の YLIBYi•ィレクトリには , ちゃんと OLDSTRMx. LIB ファイルが存在している ぞ ! なぜ , 未定義シンポルエラーになる のだ ? すると , 神のお告げ。 「 TCC. EXE がリンカを spawn ( または exec) するとき , YLIBY からデフォルトてリンク するのは , C0x. OBJ と Cx. LIB だけじゃ。そ のほかのファイルはすべて , コマンド行て、 明示的に指定してやる必要がある。 GRAPHICS. LIB の場合がそうじゃっただろ う。お前は忘れたのか ! 」 というわけて , Turbo C 十十の stream. h に は (AT&T などとの ) 非互換な部分がある , と思い込んだドジは , この神のお告げによ って解決したのてすが , 今回の本題てある ドジは , こちらて、はないのて、す。 本題を , 以下に述べます。 ( その前に , 実際面てのいちばんたいせつな #include <stream. h> という行を書いて , さらにいちいち OLDSTR Mx. LIB を明示的にリンクさせるのは少々面 倒てす。そこ <ZC 十十用のコードの # include く stream. hPP > の行は , Turb0 C 十十用には #include < iostream. h > に書 104 C MAGAZINE 1991 7 き換えるだけて OK て、す。 cin や cout を単純に 使う , というレベルては , ストリームの仕 様の新旧はまったく問題にならないようて 四苦ハ苦 文字と数値の違いに す ) 。 を , default: goto start ; どうやら , プログラムは終了しません。プログラムは ろが , キーポード上のどのキーを押しても , りました。そこて、 , ランさせました。 ニングて、コンパイルされ , . EXE がてきあが コードはすんなりと無ェラー & 無ウォー へと , case のオペランドを変更したのてす。 値てはなく , 文字 ' 1 ' などの文字コードの値 と書き換えました。つまり 1 などという整数 case ' 3 '. case ' 2 '. case ' 1 '. case 3 : case 2. case 1 : ると判断して , 私はてつきり , 原著者のタイプミスてあ て入力てきるコードてはありませんよ ! ーポード上の , 普通の文字キーだけを押し ば , きわめて特殊な制御コードてすよ。キ ASCII の文字コードて , 1 や 2 や 3 といえ 2 , 3 などとなっています。 か ? だのに , case 文のオペランドは , 1 , 字キーの < 文字コード > て、はないてしよう すから , そのストアされる値は , 押した文 カ値を変数 keypress にストアしているのて だって , cin て、キーポード入力をして , 入 持ちになるのて、はないてしようか。 についてあまり知らない人は , ? ? ? という気 例を見て , C を少し使える人 , そして C 十十 さて本題のドジてす 0List 1 のプログラム の文ばかり , えんえんと実行しているよう てす。 そこて , コードの姿を元に戻しました。 つまり ' 1 ' などと文字コードに書き換えた箇 所を , 元の 1 などの , 単なる整数値へと戻し たのてす。 そのコンパイル結果てあるプログラムは , 無事に実行され , メッセージも正しく表示 され , 正しく終了することがてきました。 なんてやー ! ? なんて、 , 文字 ' 1 ' が , ことわりもなく勝手 に , 整数値 1 になるんやー ? こて、また神のお告げ。 「 cin や cout は , scanf( ) や printf( ) の , %d, % f などに相当する変換を , プログラマが指定 しなくても引数のデータ型を見て , 勝手に 自動的にやってくれるのじゃ。この場合 , kyepress のデータ型が int だから , % d 指定の 場合と同じく , < 数字文字 > をく数値 > へと char keypress ; を , int keypress ; は , などの < 文字コード > の姿のままのコード case ' 1 ' : そこて , いくっか実験してみました。 ・・・なーるほど。 変換を試してみる テフォルトのテータ型 変換して , 変数にストアするのじゃ ! 」 す。 ' 1 ' すなわち当の文字コード〃は , 10 進 などと入力してやると , 正常に動作しま ポードから 1 , 2 , 3 などてはなく , 49 固 , 50 のままコンパイルしたプログラムは , キー 文字コード > てある状態て , keypress が int 一方 , このように case のオペランドがく ード ( コードバリュー ) が入るからてす。 作します。 char なら , keypress には文字コ と書き換えてコンパイルすると , 正常に動
プログラミング添削 Li st 1 あります。それは何て、しようか ? みなさ んも記事を読み進める前に付録ディスクに 収録されている川原さんのプログラムを読 んて、考えてみてください ・関数の設計 関数の入出力設計 さて List 1 に示している KeyCodeCheck 関 数が事実上のメインとなる部分てす。 まずこの関数は基本的に入出力がまった くないことに気づきます。確かにその場て カーソルキーなどを用いて自由自在に文字 列を入力てきます。しかし関数の終了時に どこにもその文字列を格納していません。 つまり , この関数はデモンストレーション 関数と呼ぶべきものてあり , 実用関数とは いえません。 さらに実際にアプリケーションを作成す るときは , 既存の文字列を編集てきなくて はなりません。 たとえばファイル名を入力する場合を考 えてください。毎回毎回最初からキーを打 つのは大変てすね。 以上の問題点を解決するには次のような 方針を立て , 抜本的な改良が必要てす。 く方針 1 > 文字列を受け取り , それを自由に ( 1 行内 で ) 編集できるようにする。ただしヌル文字 列を受け取った場合は新規入力とする。関 数終了時には受け取った文字列に編集・入力 後の文字列を格納する。 このように関数を設計する際は入出力の 仕様をはっきりさせましよう。一見同じ動 作をするような関数ても入出力の仕様が異 なれば , その内容も変わってくるものてす。 川原さんのプログラムは動作のみを追求し ているようて、す。 0 1 人ワ】 00 -4 ・ - -0 ー 8 0 ・ー・ワ 0 っ 0 -4 - -0 ー 8 0 1 より 0 っ 0 4 ・ - -0 ー 8 0 1 0 乙っ 0 -4 - -0 ー 8 0 1 人ワレっ 0 ・ ^ 0 ー 8 0 14 っ 0 00 -4 ・ ^ 0 ー 8 0 11 っ 0 ・ 4 ・′ 0 ー 8 0 14 っ 0 っ 0 -4 ・′ 0 ワ 3 っ 0 っ 0 0 乙ワ 0 っ 0 っ 0 っ 0 っ 0 っ 0 っ 0 っ 0 っ 0 っ 0 っ 0 っ 0 00 っ 0 っ 0 4 -4 -4 -414 ・ 4 -4 ・ 4 4 -4 -0 -0 - -0 - -0 -0 - -0 -. 0 -0 -0 - -0 CD e-O C•D CD ^ 0 CD CD c-O CD 7 ・ - 々ー行ー行ー行ーーっー々ーーー 8 8 8 8 8 8 8 8 8 8 0 》 9 0 》 int cn, max, ptype, gtype, kanjiflag; unsigned int code, byte; ニ OFF; kanjiflag max while ( ( code = GetKeyCode() ) ! = CR ) { switch ( code ) { case ESC break : case RIGHT ・ if ( cn く max ) { gtype = GetChar( P し EPT + cn, PTOP, TYPEI ) : if ( cn く CMAX ー gtype ) { cn 十 = gtype; CursorPosition( P し EPT 十 cn, PTOP ) : break , case し EFT if ( cn > 0 ) { = GetChar( P し EFT + cn ー 1 , PTOP, TYPEI ) ; CursorPosition( P し EPT + cn, PTOP ) : break ; case DEL ・ if ( cn く max ) { = GetChar( P し EFT + cn, PTOP, TYPEI ) : gtype Char し Sh ift ( P し EFT + cn, PTOP, gtype, max ー cn - gtype ) : = gtype; max break ; case BS if ( cn > 0 ) { gtype = GetChar( PLEFT 十 cn - 1 , PTOP, TYPEI ) : CharLSh i ft ( P し EFT 十 cn ー gtype, PTOP, gtype, max ー gtype : = gtype : max CursorPosition( PLEFT 十 cn, PTOP ) : break : case UP case DOWN ・ case INS case HCLR case TAB break; default if ( kanjiflag = OFF ) { if ( SJISCharaType( code, 0 , TYPE2 ) ! = HI ) { byte = COde : kanj i 日 ag = ON : } 引 se i f ( max く CMAX ) { CharRShift( PLEFT 十 max ー 1 , PTOP, HA, max ー cn ) : PutChar( PLEFT + cn, PTOP, code, 0 , HI ) : if ( cn く CMAX - HA ) { CursorPosition( P し EFT 十 cn + HA, PTOP ) : cn 十十 : max 十十 : } else if ( max + 1 く CMAX ) { = SJISCharaType( byte, code, TYPEI ) : ptype PutChar( PLEFT + cn, PTOP, byte, code, ptype ) : if ( cn く CMAX ー ptype ) { CursorPosition( P し EFT 十 cn + ptype, PTOP ) : cn 十ニ ptype; max 十 = ptype; kanjiflag = OFP; } 引 se kanjiflag = OFF; break; cn ) : CharRShift( PLEFT 十 max ー 1 , PTOP, ptype, max - cn ) : 関数を設計する際は動作だけではなく 入出力を明確にすること プログラミング添削 135
SPARC プログラミング List 1 Li st 2 68 : 69 : 70 : 72 : 78 : 79 : 80 : 83 : 84 : 85 : 86 : 87 : 88 : 89 : 92 : 94 : 95 : 96 : 97 : 98 : 99 : 100 : 101 : 102 : 103 : 104 : 105 : 106 : } 107 : 108 : static void 109 : do_cmd2(which) 1 10 : int which; 112 : i nt status : 113 : swi tch ()h i (h) { case 0 : i f (fork ( ) = 0 ) { 115 : exec l("/usr/b i n/texted i t". i t" , Gdbfnan. の : wa i t (&status) : 116 : 117 : break : 118 : 119 : 120 : } 121 : 122 : static void 123 : do_command ()h i ch) 124 : int which; 126 : i nt status ; 127 : switch(which) { 128 : case 0 : transvar ( ) : 129 : if(Gsnum ← 0 Ⅱ引 n 礪く = 0 llGkasan く = の { 130 : myerror ( " パラメータを指定して下さい " ) : 131 : 132 : bar Iase6 ( 引 j i kan, 引 paper, 引 prtdev) : 133 : break : 134 : case 1 : pitems() : 135 : break : 136 : 137 : , 138 : } 139 : 140 : static void 141 : do_cmd3(which) 142 : int which; 143 : { 144 : i nt status : switch(which) { 145 : 146 : case 0 : 147 : case 1 : 148 : case 2 : 149 : pitems2() : 150 : break ; 151 : 152 : ー 153 : } 11 CNJ っ 0 4- ・し 4 し 4 し、 ,. cd cd ・ 0 cd cd 0 1 ーワ 0 ワ 0 . 十し十レ 4 し十 ) 0. 0. ・ 0 Q) Cn a. a. 0. 0 0. 十レ一十し十レ十し 4 し十し・ー ・ー一 CO tn Ø 十レ し 0 0 1 ーっ 0 っ 0 - -0 ^ 0 っー 8 0 、 1 ワ CO -4 : -0 cD っー 8 0 ・ワ 0 っ 0 ・ 4 ・ - -0 ー 8 ソ 0 ワ 0 っ 0 ワ 0 っ朝っ 0 ワ 0 っ 0 ワ 0 っ 0 っ 3 っ朝ワ 0 っしり乙っ乙ワ】っ乙 0 乙ワ 3 ワ 0 ワ乙っ乙 else if( boxin(xpos,ypos,&Gbox[12J) ) { mmenuset (canvas, event. Gnumrow tb l, &Gsnumrow) : else if( boxin(xpos,ypos,&Gbox[13]) ) { mmenuset (canvas, event, Gketa tb l, &Gsketa) : else if( boxin(xpos,ypos,&Gbox[14]) ) { mmenuset (canvas, event, Gup_tb し &Gsup) : else if( boxin(xpos, ypos, &Gbox[15]) ) { mmenuset (canvas, event. Gco ⅱ nt_tb l, &Gsco ⅱ (t) : else if( boxin(xpos,ms,&Gbox[16]) ) { mmenuset (canvas, event, Gmoj i row_tb I, &Gsmoj i row) : else if( boxin(xpos,ypos. &G面X[17]) ) { mmenuset (canvas, event, Gj i kan tb l, &Gsj i kan) : else if( boxin(xpos, ypos,&Gbox[18]) ) { sel ect i on=mmenusel (canvas, event, Grenpr_tb I, &Gsrenpr) : if(seIection>=0) { do-command (sel ect i (n) : else if( boxin(xpos,ypos, & G 面 x [ 19 ] ) ) { se lect i on=mmenuse l(canvas, event, Gf ⅱ epr_tb I, &Gsf ⅱ epr) : if(seIection>=0) { do_cmd2(seIection) : else if( boxin(xpos, ypos, & G x [ 20 ] ) ) { mmenuset (canvas, event, Gd i rectpr_tb l, &Gsd i rectpr) : else if( u)xin(xpos.ypos,&Gbox[21]) ) { quitproc(base_frame) : strcpy(kasan, (char * ) anel-get-value(lkasan) strcpy(psamen, char * panel_get_value(lpsamen strcpy (pnum char * panel_get-value(lpnum) (uns i gned long) atol ( snum ) : Gsnum (unsigned long)atol( lnum ) : Glnum uns i gned long) at01 ( kasan) : Gkasan Gpsamen= uns i gned char atO i ( psamen) : (unsigned char atOi ( pnum) : Gpnum i f (Gkasan Gkasan ニ 1 し : i f (Gpsamen ー Gpsamen ニ 1 if(Gpnum Gpnum window_set(pframe,WIN SHOW, FA し SE, の : List MYPROC. SUN 1 : #def i ne EXTN extern 2 : #def i ne EXTERN extern 3 : 4 : #include く setjnp. h> 5 : 6 : #include く suntool/sunview. h> 7 : #include く suntool/canvas. h> 8 : 9 : # i nc lude ” smarknva. h ” 10 : #include ” dbarvar5. h ” 11 : #include "vartype. h" 12 : 13 : void do command() : 14 : void do-cmd2() : 15 : void dO - c 3 ( ) : 16 : 17 : VOid 18 : myproc (canvas, event) 19 : Canvas canvas; 20 : Event *event : 21 : { 22 : SHORT xpos, ypos, selection; 23 : Menu my_menu : 24 : SHORT i, var; 25 : 26 : xpos=event_x (event) : ypos=event-y(event) : 28 : if(event id(event)==MS RIGHT) 29 : 30 : mmenuset (canvas, event, Gprtdev_tb l, &Gsprtdev) : 33 : if( boxin(xpos,ypos,&Gbox[I]) ) { 34 : mmenuset (canvas, event, Gprtk i nd_tb I, &Gsprtk i (d) : 35 : 36 : else if( boxin(xpos. ypos, &Gbox[2]) ) { mmenuset(canvas, event, Gbarkind_tbl, &Gsbarkind) : 38 : 39 : else if( boxin(xpos,ypos,&GboxC3]) ) { 40 : mmenuset(canvas,event, GlatElkind_tbl, &GsIabel) : 42 : else if( boxin (xpos, ypos, &Gbox[4]) ) { 43 : mmenuset (canvas, event, Gpaper_tb I, &Gspaper) : 44 : 45 : else if( boxin(xpos,ypos,&Gbox[5]) ) { 46 : selection=mmenusel(canvas, event, Gfile tbl, &Gsfile) : if(seIection>=0){ 48 : do-cmd3 (sel ect i (n) : 49 : 50 : else if( boxin(xpos, ypos, &Gbox[6]) ) { 52 : mmenuset (canvas. event, GCOI unn_tb l, &GscoI umn) : 53 : 54 : else if( ypos, & Gbox [ 7 ] ) ) { 55 : mmenuset(canvas, event, Grow tbl, &Gsrow) : 56 : 57 : else if( ) { 58 : mmenuset (canvas, event, Gba i tb l, &Gsba i) : 59 : 60 : else if( boxin(xpos, ypos, &Gbox[9]) ) { mmenuset (canvas. event, Gbhe i ght_tb l. &Gsbhe i ght) : 62 : 63 : else if( *. Y8S・&G面X[10]) ) { 64 : mmenuset(canvas, event,Gleft_tbl, &GsIeft) : 65 : 66 : else if( boxin(xpos,ypos,&Gbox[II]) ) { mmenuset (canvas, event. Gka i gyo_tb l, &Gska i gyo) : 32 : List FlLLTOP2. SUN 1 : #def i ne EXTN extern 2 : #def i ne EXTERN extern 3 : 4 : #include く setjmp. h> 5 : 6 : #include く suntool/sunview. h> 7 : #include く suntool/canvas. h> 8 : 9 : # i ncl ude ” smarknva. h ” SPARC LT プログラミング 85
インタど コンピュータネットワーク対応 CASE 製品を 出している DE 社は現在 , 120 人の従業員 を抱えており , ' 90 年 6 月までの 12 か月間の歳 入は 1 , 400 万ドルという。日本では , ( 株 ) 工 スアールエーを代理店として ,IDE 社製品の 漢字パージョンをリリースしている。また , 英国に子会社を持ち , 欧州各地にディスト リビュータを有する。 IDE 社は , CASE ソフトウェアの開発販 売 , サポート , トレーニング , コンサルテ イングサービスを行っている。主力製品は Software Through Pictures である。 Soft wareThrough Pictures を使うと , グラフィ カルエデイタ , ドキュメント準備システム , バージョン管理 , ロッキング / アクセス管 理 , オプジェクト注釈を統合一体化でき , セントラルレポジトリがすべて共有になる。 この製品は , 構造化とオプジェクト指向の 両面をサポートし , 構造解析 , 工ンティテ ィ関係モデリング , 構造イヒ設計 , リアルタ 技術の開発に着手した。ソフトウェア設計 Dr. Wasserman と イム要求仕様 , ユーサソフトウェア工学 , 手法とソフトウェア工学環境についての専 IDE オプジェクト指向構造化設計が内包されて 門課程でも教鞭を執った。また , ピーター いる。グラフィカルエデイタは , マルチュ フリーマン氏とともに , 広く読まれている コンピュータ支援ソフトウェア工学 ( CASE ) ーザ対応のオプジェクト指向レポジトリを ガイドブック『 Software Design Tech は , 比較的新しい分野だ。その開拓者たち 通じてつながっている。さらに , 設計規則 niques 』 (IEEE プレス刊 ) を 4 版編集したほか , をチェックするためのプログラムも含まれ は , 依然 , 今日のコンピュータ業界の現場 Software DeveIopment Environments 』の 編者でもある。有力紙『 Methodman 』では , に深く関わっている。 CASE 専門メーカーの ている。 オプジェクト指向構造設計 ( OOSD ) とは , うちでもかなり革新的な会社のひとつが , Ada によるソフトウェア開発方法論の諸条件 ・ワッサーマン氏率い剳 DE ( イ を説いた。 ソフトウェアシステムを設計する際の表記 アンソニ ンタラクテイプ・ディベロップメント・エ シリコンバレーの古典的パターンで , ワ 法の一種で DE 社のワッサーマン , ピータ ッサーマン氏は ' 83 年自宅ロ DE 社を設立し ンバイロンメンツ ) 社である。 ・パーカー ( UCSF 時代のワッサーマン氏 ワッサーマン氏は , 1964 年 , カリフォル た。その主たる目的は , カリフォルニア大 の教え子で , 現 DE 研究開発副社長 ) , ポ ニア大学バークレー校で数学と物理学を修 学時代に開発・普及を手掛けた , RAPID/ プ・ミューラーの 3 氏が考案した。概念は , 了。 68 年にはウイスコンシン大学マジソン USE という遷移図工デイタ CASE ツールをサ コンスタンチンの「構造化設計」およびプー ポートすることだったコ DE 社は , 旗あげ以 フの「オプジェクト指向設計」に基づいてい 校でコンピュータ科学の修士・博士号を取 来 , 業界初の偉業をいくつも成し遂げた。 る。 OOSD の基礎単位は , 構造化設計にみら った。その後 , カリフォルニア大学サンフ ランシスコ校 ( UCSF ) およびバークレー校 れるモジュール , オプジェクト指向プログ たとえば ' 85 年には , セントラルレポジトリ で , コンピュータ科学を教えながら研究を を通じてツールを統合する CASE 製品を初め ラミングにみられるクラス , そしてクラス つづけ , 大型ソフトウェアシステム向け CASE て発表した。 ' 86 年には初の X Window Sys に同時実行機能を追加するモニタである。 16 C MAGAZINE 1991 7
lnformation from Compiler Makers とプロトタイプて near または far と ラムに渡す引数がなくてもヌル文 明示的に記述してある関数てす。 字列を学えないといけません。 DOS 異なるメモリモデルてコンパイル の内部コマンドを実行する場合は , されたモジュールをリンクしよう COMMAND.COM をロードする とすると , リンカはエラーを生成 必要があります。それから内部コ します。リンカがほかのセグメン マンドの /C を , Exec('A:.COM トに存在するオプジェクトへの MAND.COM/, '/C DIR * . near 参照に出会うと , fixup のため PAS') : というように指示します。 に 4 バイトアドレスを 2 バイトに取 最後に , Exec の失敗にはメモリ っておくようにてきません。そこ 不足が考えられます。これに対処 <fixup overflow" が発生します。 するには , 最大ヒープサイズを可 TurboC 十十ては , 異なるメモリ 能なかぎり低い値にセットします。 モデルてコンパイルされたオプジ これは $M 指令 , または IDE の ェクトモジュールを混在している Options/Memory Sizes メニュー 場合がほとんどてす。 こては , を使用してください たとえば , small モデルのオプジ $ M 指令の使用をお勧めします。プ ェクトを large モデルのファイルに ログラムをどのようにコンパイル リンクするときてす。解決方法と しても , 正しいメモリアロケーシ しては , リンクするすべてのオプ ョンを保証します。 ジェクトファイルを削除して同じ Q メモリモデルて再構築を行うこと Turbo C 十十では複数のモジ てす。 ュールをリンクするときに , リン near および far のキーワードを明 カカ 0fixup ove ow ″を出力しま 示的に使ってポインタのデフォル すがどうしたらよいですか ? トサイズをオーバライドするとこ A のエラーメッセージが発生します。 プログラムをコンパイルする しかし , ほとんどの場合は , 関数 ときに , コンパイラはすべての関 呼びしが原因て、す。どの場合て 数に対して参照を行います。この fixup overflow" は呼ばれて 参照は , 関数のアドレス ( リンカが いる関数と呼び出したモジュール 呼び出されるまて確定しない ) て埋 をリポートするのて , 問題の場所 められます ( または "fixed up" され を見つけることはそう難しくない ます ) 。 てしよう。 tiny, small, compact メモリモ デルを使用している場合 , これら ・お知らせ の参照はデフォルトては near ( 2 バ 引越などて住所変更のあった方 イト ) コールとなります。 med は , ユーザ ID 番号とともに新しい ium, large, huge< コンノヾイノレす 住所を郵送にてご連絡ください。 ると , 関数はほかのセグメントに 住所変更のご連絡いただけない場 存在する可能性があるのて , 生成 合は , アップデートそのほかのご された関数の参照はデフォルトて は far ( 4 バイト ) になります。 案内を郵送てきない場合がありま ただひとつの例外は , 関数定義 す。 TabIe 1 Textmode() 関数のバラメータ変更 Turbo C2.0 Tu rbo C 十十 1 .0 内容 VL8025 N8025 漢字表示可 BG8025 E8025 簡易グラフィック表示 intdos( ) を使用した曜日取得プログラム 1 : #include く stdio. h> 2 : #include く dos. h 〉 3 : 4 : char getyobi (void) 6 : union REGS regs : 7 : 8 : regs. h. ah = 0x2a; 9 : intdos (®s, ®s) : return(regs. h. (l) : 12 : } 13 : 14 : void main(void) 15 : { Char yobi : 20 : 22 : 23 : 24 : 25 : 26 : 30 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 42 : 44 : 46 : } List 1 = getyob i ( ) : YOb i printf("lt is " ) : switch (yobi) { case 0 printf("sunday") : break : case 1 printf("monday") ; break : case 2 printf("tuesday") : break : case 3 printf("wednesday") : break : case 4 printf("thursday") : break : case 5 printf("friday ” ): break : case 6 printf("saturday") : break : printf(" today. Yn つ : lnformation from Compi 厄「 Makers 159
るのて、す。自動ツールを使うからといって , しているわけて、はないんてす。あくまて、解 ろ , こんな相談をもちかけてくるソフトウ 決策のひとって、す。オプジェクト指向て、物 創造性が損なわれることは決してないと田 ェアディベロッパは大勢います。つい最近 います。相変わらず , いい設計も , 悪い設 まて、 , CASE 業界て、はそうした要望にうまく 事を処理すると , ソフトウェアの質が向上 計も可能て、す。ツールを使わないて、腕が立 応えられませんて、した。しかし今 , すばら し , 再使用が可能になり , いろいろとほか つ設計者なら , CASE ツールはその創造能力 の要望もかなうと考えるかもしれません。 しい対応策を用意しました。当社が 6 月に出 を奪うものて、はありません。 荷予定の新製品は , 既存のコードを読み込 ' とは , いくっかの方 しかし , フいった , 面て、相当の投資を必要とします。再使用を み , プログラミング環境や設計ツールを経 オフ、ジェクト指向設計と 例にとれば , 「ライプラリを持っことはすば 由して , グラフィカル表現に戻し , それを CASE CASE レポジトリに入れ , 編集し , コードと らしいじゃないか」といいますが , 図書館の 設計を一致させ , 最終的にオプジェクト指 閲覧室へ行ったはいいけれど , 問題の解決 オプジェクト指向技術は , ソフトウェ 向設計を取り出すことがて、きるというもの に誰も手を貸してくれない状況を想像して ア設計をどのように変えてきていますか ? て、す。一部の非常に特殊なニーズを追及し みてください。これこそ , 多くの組織がや wasserman 私たちは技術をつねに少しず ってきたことなのて、す。再使用がて、きるラ ています。 つ拡張してきました。 ' 85 年には , レポジト イプラリを作ろう , この再使用ライプラリ また , 見たところ , 少し歯車が噛み合っ リとなる共有リレーショナルデータベース をどこからか買おう , それて、環境が魔法の てきたようて、す。何の疑いもなく CASE ツー ルを採用した初期購入者の間て、 , サクセス を追加しました。 ' 86 年には , X Window ごとく一変する , と期待します。て、も , そ System 製品を出荷しました。ほとんどの人 ストーリーが生まれ始めています。トレー うはいきません。 オプジェクト指向技術がソフトウェア設 ニングに投資して本格的に方法論を学ばう が X Window System とは何かを少しも知 らないころて、す。また , 早くから , オプジ とする人たちも , さまざまなアプリケーシ 計プログラミングをどのように変えている ェクト指向について考え始めました。オプ ョン分野から大勢集まっています。 CASE は かて、すか ? まだ効果はあまり現れていま せん。注目度は高く , オプジェクト指向の ジェクト指向言語は , 徐々に注目され始め ワープロソフトとは違います。ディスクトッ ていましたが , オプジェクト指向設計につ 設計やプログラミングに投資しようとする プに表示して , マニュアルと見比べながら ( あるいはマニュアルも読まずに ) 使えるも いてはあまり進展していませんて、した。オ 人もたくさんいます。 IDE 社としても , C 十十 プジェクト指向システムをどのように設計 のて、はありません。 CASE は , 互いにインタ に取り組む予定て、す。基本的には C について ラクテイプなつながりを持たねばならない するか ? その設計をどうやって表すか ? やったことと同じて、す。ツール統合 , C 十十 そして結局行き当たったのが , オプジェク 開発環境 , 設計ツール , パプリッシングッ ツールの集合て、す。結果はすぐに現れない ト指向構造化設計と呼ぶものて、した。この て、しようが , CASE を本当に生かすために ール , 自在に活用て、きる機能 , そのほか , ードウェア , ツール , トレーニング 最初の形態は設計図て、す。先ほどの , 「ソフ C から C 十十への移行を手助けするプランも あります。すて、に , 「 C から C 十十へ」と題し トウェアの標準設計図をどうやって持っか ? 」 に投資する必要があります。 「プログラマは並外れた天才であり , 直 という点て、す。オプジェクト指向構造化設 た教育コンサルティングサービスを行って 感に基づいて , ほとんど孤立して作業する。 T は , 構造化プログラムとオプジェクト指 います。また , おもしろい方向として , C コ したがって , CASE などの開発方法論は , 個 向プログラムの両方の構造を示せる設計図 ードから , 当社の C 開発環境の設計生成機能 人の創造性のひらめきを妨げる」という考え として考えられました。どんな特定のプロ を使って , 設計段階に戻ることもて、きます。 方についてはいかがですか ? そうすれば , 構造化設計から , オプジェク グラミング言語からも独立して , C 十十て、プ wasserman その迷信は何としても打ち崩 ログラミングすることに落ち着く人も , ほ ト指向概念を含んだ混合設計へ徐々に移行 かの言語を選ぶつもりの人も , 同じように て、きます。これが , C から C 十十へ移行させ したいと思います。ムスタングにしろ , ジ る方法て、す。技術は完成しています。難し ャガーにしろ , フェラーリにしろ , 非常に サポートするのが狙いて、した。 では , それがなぜ重要なのでしようか ? いのは , 今いる場所からオプジェクト指向 創造的な自動車が開発チームによって組織 なぜこんなことをするんでしようか ? 化された工程の下て、設計・完成されている を生かせる場所へ移る過渡期をどう乗り切 今日 , オプジェクト指向の設 るかて、す。 て、はありませんか。マッダ・ミアータ ( 日 Wasserman t や言語は , 実際にはごくわずかしか利用 本名 : ユーノスロードスター ) をご覧なさ されていません。注目はかなり集めていま い。従来とはまったく異なった創造的なも のが , 組織化された設計工程 , 組織化され すが , ほとんどの組織を見るかぎり , 上級 た製造工程の枠組みの中て、作られています 技術グループが使っているだけとか , 単に 目をつけているだけとか , 安くて失敗して よ。ツールの制約の中て、も , 創造性は十分 もかまわないからとの理山て、 Turbo C 十十 に発揮て、きます。コンヒ。ュータ支援を生か を買った人がいる程度て、す。それほど浸透 せば , その創造性をいっそう楽に引き出せ 一三ロ 二一一い 20 C MAGAZINE 1991 7
RASTER. X の割り込み処理 ( 抜粋 ) スクロール量の更新も行っています。 次に次回の割り込みラスター位置を CRTC レジスタに設定し , 次回割り込み時にスク ロールレジスタに設定するデータを用意し ます。 83 行の IRTE ( ) はマクロて , GCC に の関数が割り込み処理関数てあることを通 知します。 X68000 版 GCC て、は Turbo C のよ うに独自の予約語を拡張した割り込み処理 を実装していないのて , このようなマクロ を interupt. h( スペルが違います , 承知の上 てこうしてあります ) に定義して利用してい ます。詳しい内容はヘッダとコンパイラの ドキュメントを参照してください Fig. 3 はこの割り込み処理関数の GCC ての コンパイル結果例てす ( 最適化オプションに よって結果は異なります ) 。割り込み処理関 数ては GCC が通常保存しないレジスタもす べてスタックに保存します。 68000CPU は 32 ビットレジスタがスタックを除いても 15 個も あるのて , 毎回全レジスタを退避するのはオ ーバヘッドが大きすぎるのて , GCC て、は処 理が破壊するレジスタのみ退避するように 工夫してあります。処理の最後は rts てなく 例外処理からの復帰て、ある rte を使って通常 の処理に戻ります。 実際にはスクロール設定値は内部タイミ ングのズレて , 1 ~ 2 ラスターくらいプレが 発生します。サンプルプログラムて、はグラ フィックデタがかなりいいかげんなのて、 , このチラッキがかなり気になります。本格 的にこれを利用する場合は画面を構成する グラフィックデータを十分吟味し , 割り込 みラスター位置周辺のデータは 1 ~ 2 ライン スクロールがプレを起こしても見えないよ うに配慮する必要があります。つまり , 縦 方向 2 ~ 3 ラインをまったく同じ色て塗りつ ぶしておけばこのプレは見えなくなります。 割り込み処理のテパッグ 先月と今月 ( おそらく今後も ) はその処理 のほとんどが割り込みて行われ , 通常処理 を行う main( ) はほとんど何もしない関数に なっています。割り込み処理は通常はアセ List 1 : / * スクロールレジスタと同等の構造体 * / 2 : 3 : typedef struct { 4 : short scO_x_reg; 5 : short scO_y_reg; 6 : short scl x_reg: 7 : short scl_y_reg; 8 : short sc2_x_reg; 9 : short sc2_y_reg; 10 : short sc3_x_reg; short sc3_y_reg; 12 : } CRTC_REG,• 13 : 14 : / * スクロール用データ * / 15 : 16 : static CRTC_REG scroll_data; 17 : 18 : / * 部分スクロール用ワーク * / 20 : static short add_vaI[4] = { 0 , 0 , 0 , の : 21 : 22 : / * ラスター割込処理ルーチン * / 23 : 24 : static short int count 25 : 26 : stat i C VO i d 27 : scroll ( ) / * スクロールレジスタアドレス * / 29 : CRTC REG *crtc = (CRTC_REG * ) 0Xe80018 ; 30 : 31 : / * ラスター位置指定レジスタアドレス * / 32 : 33 : (short * ) 0Xe80012 : short *next_ i nter 34 : 35 : short val 36 : short next; / * スクロールレジスタに書き込む * / 38 : 39 : scroll data; *crtc 40 : / * 割り込み回数をカウントしてスクロール値を 41 : 決定する * / 42 : sw itch (count) 43 : 44 : 45 : case 0 : 46 : count 十十 : add-val [ 0 ] + = 1 : 48 : val = add_va Ⅱ 0 ] : 49 : ニ 322 : next 50 : break; case 1 : 52 : count 十十 : add-val[l] + = 2 : 54 : val ニ add_val[l]; 55 : next = 354 : 56 : break : 57 : case 2 : 58 : count 十十 : add-val [ 2 ] + ニ 3 : 59 : val ニ add_vaI[2] : 60 : 61 : next = 418 : 62 : break; case 3 : 63 : 64 : count 十十 : add-val [ 3 ] + = 4 : 65 : = add-val [ 3 ] : 66 : val 67 : next = 450 : 68 : break : 69 : default: 70 : count next break : 128 C MAGAZINE 1 1 7
いう経験がないのて , 同書の翻訳作業に伴 てしようがね。 ることを宣言しています。 というわけて , これまて、 , こういうスト それから , cout を利用して「 1 か 2 か 3 およ うプログラムの手入力 ( ディスクが付いてな び [RETURN] キーを押せ」というメッセ リーム入出力のオプジェクトを真面目に相 い ! ) およびコンパイル , テストランが , 私 ージを画面に出力します。 にとって , 実質的に C 十十事始めとなりまし 手にしなかったのてすが , ところがどっこ い ! cin, cout は , そんな単純なペット動 そして , cin を利用してキーポードから変 というのが今回のドジの 物て、はなかった , 数 keypress への入力を行います。 一筋縄ではいかない 話題てあります。 それから , switch 構文の中て , keypress CIn, cout の値によって , 「あなたは 1 を押した」などの stream. h と メッセージ表示へ分岐します。押したキー 雑誌の C 十十入門記事などには , cin とい iostream. h うオプジェクトを利用したキーポード入力 が 1 , 2 , 3 以外のときは , ラベル start: へ戻り や , cout というオプジェクトを利用したコ 同書の 3 章は「プログラムの制御」と題し ます。 ンソール出力の文が , 必ずといってよいほ て , if, while, switch.. case などのいわゆる まず , C 十十のヘッダファイルの拡張子 が . hpp て、あるのは , ZC 十十などの固有性て 制御構文が初心者レベルて、解説されていま ど登場します。 す。 TurboC 十十はヘッダファイルの拡張 す。 int X : その中の , switch 文と goto 文を説明する 子を . h に統一しています。そこて、 , cin > > int x ; 箇所のコード例に , List 1 のようなのがあり #include <stream. hpp> cout < く "This is a string*n" ます。 こては , 本に載っているコード例 の行を , に , main() や #include の枠を適当につけて #include <stream. h> といった具合に。 こういうオプジェクトは , もちろん C 十十 と書き換えます。 TurboC 十十は , 古い AT & 引用します。 まあ , 説明の必要もないと思いますが , T C 十十 1.2 とのコードの互換性を図るた の言語本体に属するものてはないし , まあ printf( ) や scanf( ) をやや便利にオプジェクト 一応 , このプログラムが行うことを簡単に めに , stream. h を提供しています。 しかし , #include < stream. h > てコンノヾ 説明しましよう。 化したものだろうぐらいに思って , これま イルしてみると , 未定義シンポルエラーが 最初に , int 型のローカル変数を 1 個使用す ての私はこういった ( cin や c 。 ut が登場する ) ること , それを kyepress という名て、参照す いくつか出ます。すなわち , どうやら Turbo コードに対して , 真剣な関心を払わずにき ました。オプジェクトの名前に最初感じた switch 文と goto 文を説明するコード例 違和感も , 頭の c 〃が *console" を意味す ることがわかれば , 解消します。 > > , < < という妙な記法も , 「 C 十十の演 算子オーバロードじゃ ! 」と , 水戸黄門の葵 の紋入り印篭を見せつけられたならば , 黙 って納得するしかない・ こういう皮肉 を書きたくなるのは , オーバロードされて も演算子の優先順序は変わらない , 現在の C 十十の規約が , 現実世界に対するわ れわれの常識的な感覚にそぐわない事態を 招来してしまう場合がときどきあるからて す。 しかし , 演算子の優先順序を , ダイナミ ックに , 文脈依存て可変にせよ , と要求し たら , コンパイラ作家は困りはててしまう とか , LiSt をりいい、リーい ) い 1 : #include く stream. hpp> 2 : 3 : ma i n ( ) 5 : int keypress; 2 or 3 and [RETURN]Yn" ・ 6 : cout くく” Press 1 , 〃これは goto 用のラベル 7 : start: 8 : cin 〉 > keypress; switch( keypress ) { 9 : case 1 : cout くく "You pressed 1Yn ・ case 2 : cout くく "You pressed 2Yn ・ case 3 : cout くく "You pressed default : goto start; 15 : } break; break; break; C 言語フォーラム 103