適切な処理て、あるかどうかの責任はプログラマにあ ります。 ロ抽象テータ型 一般に高級言語と呼ばれている PascaI や FOR TRAN などて、は , 機械語のような情報の表現は言語 処理系がおおい隠します。そのため , プログラマは 数値がコンピュータ内部て、 , どのように表現されて いるかを意識することなくプログラミングすること がて、きます (List2 参照 )。たとえば , PascaI て、は表 1 の ような基本データ型とそれらを取り扱う演算操作が 用意されています。 このように , 具体的なデータ構造や実装方法など が隠され , それらに用意された操作だけによって操 作されるデータは , 抽象化データと呼ばれ , そうし た型は抽象データ型と呼ばれます ( 注 3 ) 今まて、多くの言語て、は , 抽象データ型は言語組み 込みの型だけのものがほとんどて、した ( 注 4 ) 。 C 十十て、 は , 前回まて、に紹介したクラスの機能により , ほば 完全な抽象データ型を定義し , 既存の型体系に組み 込んぞ使用することがて、きます。 ロ抽象テータ型の実装例 まず , 抽象データ型の設計および実装の例として , 基本的なデータ構造をクラスて、定義する例を示すこ こて、は , 有名かっ簡単なデータ構造 とにします。 = 0 to 10 do [ 表 1 ] Pasc 引の組み込みテータ型 型名 integer boolean Char 取り扱う情報の型 実数型 ( 実数値 , 3.14 など ) 整数型 ( 整数値 , 245 など ) 論理型 ( 論理値 ,TRUEor FALSE) 文字型 ( 通常アスキーコード化された文字 ) て、あるスタック (stack) を取り上げることにします。 ロスタックとは データ構造やアルゴリズムの教科書には , 文字列 (string), リスト (list) , 木 (tree) などのいくつかの基 本的なデータ構造が載っています。ここて、は , その なかて、も比較的実装が簡単そうなスタックを例に取 り上げます。スタックは後入れ先出しバッフアのデ ータ構造て、 , その動作は積み木を積み上げるのに似 ています ( 注 5 ) 。スタックの操作は , ただふたつのみ て、 , スタックの最上部に情報をひとつ積む操作は push (Fig. 3(a) → (b), (b) → (c)), スタックの最上部から 情報をひとっ下ろす操作は p 。 p ( Fig. 3 ( c ) → ( d ) ) と呼 ばれます。たとえば , Fig. 3 の例て、は最後の p 叩操作 て、 , 値 75 が取り出されます。 ロ試作版 ( prototype ) 乍成 まず手始めに , スタックに相当する抽象データ型 の実装例を作成してみます。この実装例て、は , スタ ックて、扱う情報のデータ型および情報の数量をあら かじめ決めます。 Pascal Language (Sun pascal) のプログラム例 List 2 program sample (output) : var inch: integer; cm : rea I : beg i n for inch inch * 2. 54 : writeln(inch, end; end. inch Fig. 3 スタック操作の様子 begin push 100 100 push75 (c) 75 100 POP 100 75 注 3 C 言語は機械語のよう なビットの列を意識した操 作と高級言語のような抽象 的な操作の両方が可能なの て、 , システム記述て、は威力 を発揮する。 注 4 いくつかの言語 ( は , 集合データ型としてレコー ド型や構造体が用意されて いるが , それらは内部表現 を意識する必要があるため , 完全な抽象データ型とはい えないだろう。 注 5 スタック構造を作業領 域に使用するコンヒ。ュータ はスタックマシン (stack machine) と呼ばれる。この 種のコンヒ。ュータは実現が 容易 ( あるため , 仮想機械 (virtual machine) として使 われることが多い C 十十プログラミング入門 83
MS - ロ OS プログラミング入門 List 2 524 : 525 : unsigned long dumy: 526 : unsigned long palette; 527 : 528 : getpal ettenumr : 529 : struct GETDISPPORT 530 : 531 : 532 : unsigned long duny: 533 : unsigned int y; 534 : 535 : getd i SPPOrt : 536 : 537 : struct GETINT 538 : 539 : unsigned long dumy; 540 : unsigned long y; 541 : 542 : getint; 543 : } 544 : GrpData; 545 : 502 : 503 : 504 : 505 : 506 : 507 : 508 : 509 : 5 10 : 512 : 513 : 514 : 5 : 516 : 517 : 5 18 : 5 19 : 520 : 521 : 522 : 523 : getborder : struct GETDISPSWITCH unsigned long duny; unsigned Char SYh; getd i spswi tch : struct GETPALETTENUM / * NO. 38 / 1 指定座標のパレット番号の取得本 / uns i g ned long structaddr : な VRAM 構造体のアドレス unsigned int x: / 本拾得したい x 座標 unsigned int y: / ネ拾得したい y 座標 getpal ettenum; / * 上記の構造体にパラメータが格納されると , 同じ構造体に / 事 long で値が返されるので構造体をパラメータの設定用と戻り / * 値用に分けている struct GETPA し ETTENUMR / * N0. 38 / 2 指定座標のパレット番号の戻り なダミー / * パレッ ト番号 な NO. 37. 表示スイッチの取得 なダミー / * 表示スイッチ / * 間 . 39. 表示領域の取得 / * ダミー な拾得したい y 座標 / * NO. 40. 中断処理ルーチンの取得り なダミー 事 / / 事中断処理ルーチンのアドレスり [ 表 4 ] 8 色 / 8 色モード [ 表 3 ] 描画フラグ [ 表 5 ] 塗りつぶしフラグ ◆ C 言語を使用する実際例 プラック 0 塗りつぶしを行わない 線種バターンお プルー List1 プログラムに従ってサンプルプログ 1 指定のノヾレット番号で塗りつぶし よび線幅を省略 レッド を行う ( 省路したときは , 線の色と 丁 線種ノヾターンの ラムを作成する。内容としては , 線幅 4 ドット マゼンタ 同じ色で塗りつぶしを行う ) み指定 2 4 グリーン ユーサが指定する 1 バイトのタイ 0 の四角形を画面いつばいに赤て、描いてから 線幅のみ指定 5 シアン ルノヾターンで塗りつぶしを行う 1 1 線種パターンお 6 イエロー 3 ユーサが指定する 2 バイトのタイ 四角形内を黄色て、塗りつぶす。さらにその よび線幅を指定 フ ホワイト ルノヾターンで塗りつぶしを行う 上に三角形を描いて右へ 320 ドット分 ( ー 320 ) すかどうかを指定するフラグて、ある。この 移動させる。四角形のパラメータブロック 条件に従ってパラメータを設定する。線幅 場合 , 塗りつぶすのて、フラグを 01H に指定し を指定しないときは , 00H を指定する。 は構造体にすべて反映させてある。構造体 線色の指定は , モノクロ , 8 色 / 8 色 , 8 色 / ている。塗りつぶしに関するコードを表 5 を List3 に示す。 に示す。 4096 色 , 16 色 / 4096 色があるが , よく使う 8 List3 の構造体に必要なパラメータをセッ 塗りつぶしを指定した場合 , 塗りつぶし トして , 実行させるだけて、よい。必要なパ 色 / 8 色モードのカラーコードを表 4 に示す。 の色は塗りつぶしカラーパレット番号を指 ラメータと実際の値を表 2 のように定義す 線色の設定には , 表 4 のカラーコードのう 定しないと , 線色て、指定したカラーコード ちどれかを指定する。ここて、は 2 ( レッド ) を る。なお , 提供されている機能のいくつか が使用される。 こて、は塗りつぶしカラー 使用している。次に線幅を指定するが , 指 において , タイルバターンを使用するもの パレット番号を 6 ( イエロー ) に指定してい 定範囲は 0 ~ 15 が可能て、ある。基本の線幅は があるが , 構造体は使用するものと , しな 1 ドットて、描かれ , 指定数値は 1 ドット単位 る。以上のように設定して実行させるとコ いものに分けて列記してあることに注意し ードが返ってくる。アセンプラの場合は , て、増加する。増加方向は描く線の仰角が 45 てほしい。 AX に設定される。 予約パラメータ , ラスタオペレーション 度以下の場合 , 上下方向に増加する。この 正常終了 番号は必ず 0 に設定する。スタート位置を とき指定力ラーコードが奇数なら , 下方向 0 指定パラメータに誤り ( 0 , 0 ) として終了位置を ( 639 , 399 ) に設定し に 1 ドット増える。仰角が 45 度以上の場合は 01 作業領域の不足 ている。さらに線幅の指定を行うために描 左右方向に増加する。このとき指定力ラー 02 コードが奇数なら , 右側に 1 ドット増える。 演算のオーパフロー 画フラグを 10H に指定している。なお描画フ 03 その次は , 描いた四角形の内側を塗りつぶ 未定義の関数を使用 ラグの設定条件は表 3 のとおりて、ある。この 04 終了時における判定は , 0 かどうかを調べ [ 表 2 ] バラメータの値の定義 ることて、 , 異常終了の検査を行うのが一般 G 「 pData. cyoul . 「 ese 「 ved 的な方法て、ある。こうして作成したのが List4 G 「 pData . cyou 1 ・ OP と List5 ゼある。さらに詳しい点は実際のソ G 「 pData. cyou 1 . Sta 「 tX G 「 pData. cyou 1 . sta 「 ty ースを参照してもらいたい G 「 pData. cyou 1. endx G 「 pData. cyoul . endy G 「 pData. cyoul.flag G 「 pData. cyou 1. palette G 「 pData. cyou 1. linetype GrpData. cyou 1. fillflag G 「 pData. cyou 1. fillpalette 予約パラメータ ラスタオペレーション番号 開始 x 座標 開始 y 座標 終了 x 座標 終了 y 座標 描画フラグ 線の色を決めるパレット番号 線の幅 塗りつぶしフラグ 塗りつぶしカラーパレット番号 = 639 = 399 =Ox10 0 c プログラマのための MS - DOS プログラミング入門 77
6 コンヾイラ に int ) のて、 , 本来の戻り値の型に変換するノ ードを生成します ( 25 ~ 30 行 ) 。関数呼び出 しを表す本構造は Fig. 5 のようになります。 制造 C のような近代的なプログラミング言語て、 は , 制御構造を表す文 ( if , while, do, for , case など ) をもっています。しかし , 機械語には , このような制御構造に直接対 応する命令はありません ( 実際には , 1 。叩命 令を備えている CPU もありますが , このよ うな命令は , 一般的なループ処理を行うと いうよりも , あるパターンのループを最適 化する命令と位置づけするのが適当て、しょ コンパイラがオプジェクトコードを生成 するときには , これらの制御構造を条件ジ ャンプ命令 ( C 言語て、は , if goto ・・・ ) に変換します。機械語の条件ジャンプ文は , C 言語て、の if ( 条件 ) goto ラベル ; に相当するものて、す。 たとえば , while ( 条件 ) を , if ・・ goto 文を使って書き直すと , again : if ( ! 条件 ) gotO exit 100P ; 文 造文は , 条件ジャンプに帰結させることが となります。このように , すべての制御構 exit 100P . goto again ; 文 Fig. 5 関数の木構造 ①バラメータがないとき ③バラメータが n 個のとき op_ FUNC 工 関数 ↓ ②バラメータがひとつのとき 1 番目のバラメータ 2 番目のバラメータ n 番目のバラメータ n ー 1 番目のバラメータ 1 番目の バラメータ の内部を詳解 て、き , また実際に生成されるコード中て、は 条件ジャンプによって表現されているわけ て、す。 ところて、 , 式の説明をしているときに 急に制御構造の話をしたのて、 , 不思議に思 われる方もいらっしやると思います。この 理由は , 式と制御構造とは密接な関係があ るためて、す。 bo 式の扱い 制御構造の「条件」は , 論理値てなければ なりません。つまり , 条件が成立すれば真 , 成立しなければ偽 , という 2 とおりのどちら かに決められなければならないわけて、す。 Pascal などの型にうるさい (strongly typed) 言語て、は , 真か偽かの論理値を表す論理型 ( またはプール型 ) という独立した型が規定 されているのがふつうて、す。比較演算の結 果は論理型になり , 論理演算 ( and , or など ) は論理型のオペランドを取り , その結果も また論理型になります。 それに対して , C 言語て、は , 論理型を導入 せずに , int 型て、代用しています。論理値と してみた場合 , 0 以外が真 , 0 が偽と判断さ れます。比較演算子の結果は int 型て、 , 真な ら 1 , 偽なら 0 と定められています。このよ うに , C て、は , 論理値と数値とを区別せず に , 混同して使用するようになっており , PascaI とは対照的て、す。 また , C 言語て、は , 条件演算子 ( ? : ) , 論理 AND 演算子 (&&), 論理 OR 演算子 ( 凵 ) は , 外見上はふつうの演算子てすが , 実は 内部に制御構造を隠しもっている点にも注 意しなければなりません。 コード生成という面からみると , C 言語の 場合 , 定義に従った素朴なインプリメント を行った場合 , 比較演算のコードはたいへ yacc による C コンバイラブログラミング 69 ない ( つまり , 真てある ) ならば , 関数 f00 を そして , 後半ては , ax レジス・タの内容が 0 て 1 , 偽なら 0 を ax レジズタにセットします。 (Fig. 6(a))0 前半て、は , a = = b が真ならば ん非効率なものになってしまいます
工 NTEGER * 2 s CFAR,REFER ENCE] ( 11 ) 國 ライックライプラリ 例 具体的な例としてふたつのサンプルプロ グラムを掲載します。 List2 は , ビューポー トとウインドウ座標を使い , 画面を 4 分割し てそれぞれに 3 次元グラフを描かせます。 List3 はフォント関数を使い文字を描きます。 0 CGRAPH. FI はソースファイルごとに最 62 CMAGAZINE 19 3 初に 1 回インクルードしてください 取り扱い方が違い , 後者て、は文字列の長さ はコンパイラが管理していますが , 前者は ヌル文字 ( 値が 0 の文字 ) を終端とするという 規則があるだけて、す。あとは文字列へのポ インタを操作するのみて、コンパイラはまっ たく関知しません。グラフィックライプラ リて、扱う文字列は C の文字列の規則に従わな ければなりません。つまり , グラフィック ライプラリに渡す文字列には , C の属性をつ けるか , 自分て、文字列の最後にヌル文字を つけなければなりません。 ・ getvideoconfig C て、のプロトタイプ宣言は , struct videoconfig far * far cdecl getvideoconfig 國 (struct videoconfig far * ) ; 國 て、す。引数として構造体 videoconfig への far ポインタをもちます。値として構造体 videocoonfig への far:* インタを返します が , これは引数として渡したポインタがそ のまま返されるだけなのて、 , この値を使う 必要がなく , サプルーチンとして宣言しま す。この関数て、は構造体を受け渡さなけれ ばならないのて、すが , FORTRAN て、は構造 体が定義て、きません。しかし , この構造体 ⅵ deoconfig は要素がすべて同じ型の short な のて、 , FOTRAN 側て、は , INTEGER * 2 の 配列として定義て、きます。 INTERFACE TO SUBROUTINE 国 10 : C 22 : C 23 : C 24 : C 35 : C 36 : C 41 : C 45 : C 49 : C 52 : C 57 : 100 68 : 200 89 : C 92 : C List 3 FONT. FOR サンプルプログラム P 0 N T . F 0 R font. fo 「 /link fgraph. lib 89 / 12 / 04 By Tatsuo Takura ソースファイルの最初に C G R A P H . P I をインクルードさせます 5 : 8 : 9 : 12 : 13 : 17 : 20 : 25 : 26 : 28 : 29 : 30 : 32 : 33 : 34 : 37 : 38 : 39 : 40 : 42 : 43 : 44 : 46 : 48 : 50 : 53 : 54 : 55 : 56 : 58 : 59 : 60 : 62 : 63 : 64 : 65 : 66 : 69 : 78 : 80 : 82 : 83 : 85 : 86 : 87 : 90 : 93 : 84 : 7 : $INC し UDE: 'CGRAPH. ドド PROGRAM FONT プログラム単位毎に C G R A P H . F D をインクルードさせます 11 : $INC し UDE: 'CGRAPH. PD' CHARACTER*64 CHARACTER*IO CHARACTER*20 INTEGER*2 INTEGER*2 fontpath option(4) text strend,i xy ② DATA option / 't"helv" •t"preview フォントの登録 ・ t ・ 'script' •t"systen 十 AL 工 AS:' getvideoconfig [FAR,C, getvideoconfig'] (s) 國 グラフィック関数に渡す文字列は C の文字列にしなければなりません フォントファイルを設定します IF(registerfonts('*. PON ℃ ). し T. の THEN ・フォントファ信のテ・イレクトリを指定してください・ READ(*, (A ) ・ ) fontpath strend = INDEX(fontpath, fontpath(strend:strend + 6) 響 . PON'C IF(registerfonts(fontpath). し T. の STOP ・フォントファイルが見つかりません・ ENDIF ビデオモードを 1 6 色グラフィックにします 8 色または白黒のマシンではここの値を変えてください IF(setvideonode($98RESS16C0 し (R) . EQ. の の STOP ・グラフィックモードが設定できません・ 十 READ(), ENDIF WR ITE ( もの ' フォントが設定できません第 E し SE CAL し outgtext (' これはフォントの見本です . CA しし田 ovetO ( 0. 150. xy) IF(setfont(text). EQ. の THEN text = option(4) / / 'h8w6b'C ENDIF WR ITE ( も * ) ・フォントが設定できません・ E し SE CAL し outgtext ( ・これはフォントの見本です . CÅしし田 oveto ( 0.50 , xy) IF(setfont(text). EQ. の THEN text = option ( 3 ) / / ・ h18w8b ・ C CA しし clearscreen($GC し EÅRSCREEN) REÅD(), 事 ) CONTINUE ENDIF WR ITE ( も事 ) ' フォントが設定できません・ ELSE CA しし outgtext( ・ FONT sanples. ℃ ) CAL し noveto ( 0. i 本 100 , xy) IF(setfont(text). EQ. の THEN text : option(i) / / ・ h50W50b ℃ DO 200 i=l,3 CA しし clearscreen($GC し EARSCREEN) READ(), め CONT INU E ENDIP WR ITE ← . * ) をフォントが設定できません・ E し SE CA しし outgtext( ・ This is FONT sanples. ・ C) 文字を表示します CA しし noveto ( 0. i * 100. xy) 表示する位置を決めます IF(setfont(text) . EQ. の THEN text = option(i) / / ・ h12 7b ℃ 使用するフォントを設定します DO 100 i=1,3 CA しし cIearscreen($GC し EARSCREEN) 画面を消去します END ー = setvideonode($DEFAU し TMODE) ビデオモードを元に戻します CA しし unregisterfonts() フォント用に確保していたメモリ領域を解放します
す。これらのツールもやはり PM バージョン て、 SDK Ver. 1.1 に含まれているものを使い くリンカ > リンカは SDK Ver. 1 . 1 て、提供されるマイ クロソフトセグメントエグゼキュータブル リンカ link. exe を使います。このリンカは . リアルとプロテクトの両モードのアプリケ ーションやダイナミックリンクライプラリ を作成することが可能て、す。コマンドライ ンから外部参照を処理するインポートライ プラリとモジュール定義ファイルが与えら えた場合 , リンカは OS/2 アプリケーション を作成します。 くインクルードファイル > PM アプリケーションは SDK に含まれる OS2. h というへッダファイルをインクルード します。アプリケーションによっては必す しもすべてのデファインや構造体をインク ルードする必要はありませんから ,#include 命令の前に define 文を用いて必要な部分を 明示し , 指定範囲部分だけをインクルード します。 OS2. h は与えられた条件に基づいて BSE. h, PM. h をインクルードし , さらにお のおのが , OS / 2 カーネルや PM の API のため のデファイン・構造体の宣言・関数プロト タイプの定義などを行っているヘッダファ イルの指定された範囲をインクルードしま す。この階層的なインクルードの構造とへ ッダファイルの関係を Fig. 2 に示します。 くライプラリ > PM アプリケーションて、 C の標準関数を使 用する場合には , プロテクトモードに対応 した標準ライプラリ xLIBCEP. LIB をリンク します。ライプラリ名はセットアップの時 点て、設定て、きますから , プロテクトモード をデフォルトにする場合は指定によって , xLIBCE. LIB という名前にすることもて、き ます。 OS / 2 システムの提供する API はダイ ナミックライプラリて、 , ひとって、も使用す る場合は必ず OS2. LIB をリンクしなければ なりません。もちろん PM アプリケーション の場合は必須て、す。また , あまり頻繁には 行われないと思われますが ( 500 とも 800 とも いわれるシステムコールを備え , さらに拡 張予定 ? ) , 従来の DOS における外部 ( ュー ザ ) ライプラリ構築して , それをリンクする ことも可能て、す。 く各種リソースエデイタ > PM アプリケーションは各種リソースをも っことによって , その開発と保守を効率化 しています。ダイアログボックス , メニュ ーなどのテキストて、定義て、きるリソースは * . RC の拡張子をもつリソース定義ファイル に直接記述することも可能て、すが , PM 上て、 稼働する SDK 付属のリソースエデイタを使 用することにより , 実際のインタフェイス を確認しながらリソースを作成することが リソース記述 可能になっています。また , ファイル中にインクルードされるアイコン , フォントなどのバイナリデータはこれを使 用しないと作成不可能ともいえます。おの おののエデイタは操作性が統一されており , リソース記述のための時間を大幅に短縮し てくれます。 以下に SDK 付属のエデイタを使って編集 可能なリソースを記しますがこのほかにも ストリン アクセラレータキー , メニュー グテープルなどのリソースがあります。 くダイアログボックスエデイタ > 最新 / 入門 PMBITMAP. H PMWIN. H PMSHL. H MORD. H PMGPI. H PMFONT. H PMDEV. H PM. H—PMAVIO. H OBSESUB. H BSEERR. H BSEDOS. H BSE. H—BSEDEV. H 0S2. h—OS2DEF. H Fig. 2 インクルードファイルの構成 ステートメントをもっダイアログテンプレ ロールウインドウの座標やそれを定義する スト形式のファイルて、 , おのおののコント 存します。このうち , * . dlg は ASCII テキ * . res, * . dlg , * . h というファイルを保 イアログボックス ) は , 保存処理を行うと 場合 ( 新しいインクルードファイルをもつダ トロールに対して識別シンポルを設定した 新規にダイアログボックスを作成しコン り短縮することがて、きます。 マはインタフェイス部分の設計時間をかな み合わせていきます。このため , プログラ を , ポインティングデバイスを使用して組 類以上用意されたコントロールウインドウ チェックポックス , ラジオボタンなど 20 種 スクローノレノヾー イタて、はタイトルバー , 工デイタて、定義することがて、きます。工デ 述するダイアログボ、ツクステンプレートは すが , その中におかれるコントロールを記 スからのメッセージの処理は * . c て、行いま 対話が可能になります。ダイアログボック スを開くことによりューザとプログラムの PM アプリケーションて、ダイアログボック [ 表 1 ] define 文によるヘッダファイルインクルードの例 [ 表 2 ] リソースの種類 ( 通常使用されるもの ) #define INCL PM #define INCI WIN #define INCL GPI #define INCL AVIO #define INCL BASE #define INCL DOS #define INCL SUB すべての PM ファンクションと構造体をインクルード すべての W 爪ファンクションと構造体をインクルード すべての G 曰ファンクションをインクルード すべてのアドバンスドⅥ O ファンクションをインクルード すべての OS / 2 の BASE ファンクションをインクルード すべての DOS ファンクションをインクルード すべての KB 日 , MOU . Ⅵ 0 ファンクションをインクルード 日 T MENU RT DIALOG RT BITMAP 日 T POINTER RT STRING RT FONT RT_FONTD 旧 RT RECDATA 日 T MASSAGE RT ACCELTABLE メニューテンプレート ダイアログボックステンプレート ピットマップ アイコン , マウスポインタ テキスト フォント フォントティレクトリィ キーボードアクセラレータテープル メッセージ文字列 プログラマ定義文字列 特集最新 OS / 2 入門 47
GAI.C List 1 0 : lnregs. X. aX : ニ ( (int)&G し ) : inregs. X. bX int86(0xcd, &inregs, &outregs) : 111 : 1 12 : 1 14 : 115 : func-0() 116 : int return( (*(GL- 〉 FUNC[O])) ((unsigned long) ( int far * ) &GrpData) ) : 118 : 119 : } 120 : func-l ( ) 121 : int 122 : return( (*(G し ->FUNC[I])) ((unsigned long) ( int far *)&GrpData) ) : 123 : 124 : 125 : func-3() 126 : int 128 : GrpData. mode. structaddr : 0 : 129 : GrpData. mode. mode = 0X0101 : 130 : return( (*(GL- 〉 FUNC[3])) ((unsigned long) ( int far *)&GrpData) ) : 131 : 132 : 133 : 134 : int func-ll() 135 136 : GrpData. setswitch. swh = 137 : 138 : return( (*(GL->FUNC[II])) ((unsigned long) ( int far *)&GrpData) ) : 139 : 140 : int func_14() 141 : 142 : 143 : GrpData. clear. param 144 : return( ←()い〉 FUNC[14])) ((unsigned long) ( int far *)&GrpData) ) : 145 : 146 147 : 148 : 2 : Progranned by 3 : Dat ed Version Pur posed 10 : CompiIed 14 : #include く stdio. h> 15 : #include く coniO. h 〉 16 : #include く dos. h> 17 : #include "ga. h ” 19 : union REGS inregs, outregs; 20 : struct SREGS segs : 21 : 22 : void gaddr(void) : 23 : int func-O(void) : 24 : int func_l (void) : 25 : int func_3(void) : 26 : int func-ll(void) : 27 : int func-14(void) : 28 : 29 : PILE *fp; 30 : int main( void ) 31 : 32 : { 33 : int n: 34 : 35 : グラフィックスドライバが登録されているどうかを調べる 37 : 38 : if( (fp=f 叩 en("GRAPH $ \ 0 ". 39 : fclose(fp) : 40 : 41 : 42 : 43 : 44 : 45 : 46 : 47 : 48 : / * 工ントリテープルの先頭アドレスの取得 49 : 50 : gaddr() : n = func-0() : 52 : / * グラフィックス初期化り if( n 〉 0 ) 53 : 54 : fprintf(stderr, 55 : ”グラフィックの開始でエラーが発生しました Yn" 56 : fprintf(stderr, ”工ラーコード exit(l); 58 : 59 : 62 : 63 : 64 : 66 : 68 : 69 : 79 : 80 : t2: 85 : 86 : 87 : 88 : 89 : 90 : 92 : 95 : 96 : 98 : 99 : 100 : 101 : 102 : 103 : 104 : 105 : 106 : 107 : } 108 : 109 : void gaddr() 110 : A. Ak itu 1990-01-11 グラフィックスをプログラムするためのプロトタイプ Q U I C K ー C , M S C が稼働 qcl /AS /0x /WI /la:yqc gal. c GA. H List 2 printf("GRAPH. SYS が登録されていません \ n " ) : return( 0 ) : Header file for Graphics し ibrary 5 : Creator A. Akitu 7 : dated 1990 ー 01 ー 11 9 : 1 1 : struct FuncEntryTag int (far pascal * FUNC[41]) (unsigned long) : 15 : far * G し : 17 : union GrpDataTag unsigned int work [ 1024 ] : 19 : 20 : / * NO. 0. 構造体は無し * / / * NO. l. 構造体は無し * / 22 : 23 : struct VRAM / * N0. 2 仮想 VRAM の生成 * / 24 : 25 : long structaddr: / * 仮想 VRAM の構造体アドレス * / 26 : unsigned / * 仮±VRAM のアドレス unsigned long addr; int / * X 方向のドット数 28 : unsigned X : 29 : int / * Y 方向のドット数 unsigned Y : 30 : p ー ane : / * プレーン数 unsigned int 32 : 33 : 34 : 35 : 36 : 37 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 49 : 50 : 52 : 53 : 54 : 55 : 56 : 58 : 59 : 60 : 62 : 63 : 64 : 65 : = func_3() : n if( n 〉 0 ) fprintf(stderr, ”表示モードの設定でエラーが発生しました Yn" fprintf(stderr, ”工ラーコード exit(l); / * 表示モードの設定 * / [Xd] Yn". puts("Yxlb[2J") : / * テキストクリアー * / puts("Yxlb[>5h"); / * OPF り カーソル puts( ” Yxlb[>1h ” ): ファンク ー表示 0F P * / ションキ ニ func_14() : / * クリアー * / n if( n 〉 0 ) ”画面の消去でエラーが発生しました Yn") : fprintf(stderr. fprintf(stderr. ”、エラー - コ・一ド ex i t ( l) : 丿 Vram: struct MODE / * NO. 3. 表示モードの設定 * / / * 仮想 VRAM 構造体アドレス * / unsigned long structaddr: node : / * 表示モード unsigned int / * 表示スウィッチの設定 */ : func-ll ( ) : n if( n > 0 ) fprintf(stderr," 表示スウィッチの設定でエラーが発生しました Yn つ : fprintf(stderr, " 工ラー・コ -- ド ex i t ( l) : mod e : struct SETDROWP しÅNE / * NO. 4. 描画プレーンの設定 * / / * 仮想 VRAM 構造体アドレス * / unsigned long structaddr; / * 描画プレーン unsigned long setdrowplane: struct SETDISPP し ANE / * NO. 5. 表示プレーンの設定 * / / * ダミ unsigned long dummy; / * 表示プレーン * / unsigned long mode : setdispplane: struct SETPA し ETTE / * NO. 6 , トの設定 * / パレッ unsigned long dummy; unsigned long palette; unsigned long mode; setpalette; ビューポート領域の設定 * / struct SETVIEWPORT / * NO. 7. / * 仮想 VRAM のアドレス unsigned long structaddr; fpr i ntf (stdout. "Yn このプログラムは , プロトタイププログラムです Yn " fp 「 intf ( stdout. " この間にユーザプログラムを入れてください \ n " ) : puts("Yxlb[>51"); / * カーソル ON * / puts("Yxlb(>ll"); / * ファンクションキー表示 ON * / n = func-l() : / * グラフィックスの終了 * / if( n 〉 0 ) fprintf(stderr. " グラフィックスの終了でエラーが発生しました yn つ : fprintf(stderr, ”工ラーコード exit(l); 号ド トコ ミレラ ダバカ 74 CMAGAZINE 19 3
LIB から 9 つのモジュールを取り出し , 同様 ようにプログラムしなければなりません。 に作成します。 ひとつひとつの関数やサプルーチンを説 明すると , かなりの量になってしまいます。 ルードファイル 基本的な仕様は QC と同じなのて、 , QC のグラ フィックライプラリリファレンスを参照し QC のグラフィック関数を FORTRAN から てください。 QC のグラフィックライプラリ 呼び出すことになるわけて、すから , 当然 との具体的な相違については , FGRAPH. INTERFACE 文て、関数やサカレーチンの属 C とふたつのインクルードファイルを参照し 性 , および仮引数の型の宣言をしなければ てください なりません。各コンパイル単位ごとに と RTRAN との INTERFACE 文を記述することはたいへん フェイス て、す。グラフィックライプラリ内のすべて ラに指示しなければなりません。 setvideo の関数とサプルーチンの INTERFACE 文を mode は C の far 関数。キーワード FAR と C を , こて、簡単に C と FORTRAN とのインタ 使いこの関数に FAR と C の属性をつけます。 己述したファイル CGRAPH. FI ( 付録ディス フェイスについて説明したいと思います。 クに収録 ) を作成します。この CGRAPH. FI C の short は 2 バイトの整数てすから , 関数と マイクロソフトの言語はミックスドランゲ 引数を INTEGER * 2 て、宣言します。 FOR をメタコマンド $ INCLUDE て、コンパイル単 ージプログラミングのために , 標準の C や 位ごとにインクルードさせて使用します。 TRAN て、の INTEGER は , デフォルトて、は FORTRAN の文法にいくつかのキーワード 4 バイト整数て、あることに注意してくださ 次に , プログラム単位ごとに各関数とサ が拡張されています (Fig. 2 参照 ) 。このう プルーチンの宣言が必要て、す。また , グラ い。実際に INTERFACE 文を書くと , ち , FORTRAN の FAR, HUGE, NEAR と フィックライプラリて、使用するパラメータ INTERFACE TO FUNCTION C の far, huge, near はメモリモデルのた の定義も必要て、す。これらも一括して setvideomode(mode) 國 めに拡張されたキーワードて、すが , 、ツク integer * 2 setvideomode CFAR, CGRAPH. FD ( 付録ディスクに収録 ) とい スドランゲージプログラミングて、も使うこ c],mode 國 うファイルに記述します。この CGRAPH. とが多いのて、載せました。ひとつひとつの FD もプログラム単位ごとにインクルードさ 詳しい意味については , マニュアルを参照 となります。これて、もよいのて、すが , 標準 せて使用します。 してください。いくつかの関数を例にして , の FORTRAN の文字セットに ( アンダース どのように FORTRAN から C とのインタフ C グラフィック コア ) が入っていないことから , を名前に ェイスを取っているかを説明しましよう。 ップラリとの相違 使うのは一般的て、はありません。そこて、関 ・ setvideomode 数名を ALIAS を使い setvideomode に変更 仕様に大きな違いはありませんが , いく この関数の C て、のプロトタイプ宣言は , します。 MS-C て、は名前をコードとして生成 つか注意点があります。 short far cdecl setvideomode するとき , 先頭にを付加した名前として出 まず , FORTRAN て、は構造体の定義がて、 (short); 國 きないのて , 配列として定義するようにし 力します。 FORTRAN て、はこのようなこと となっています。これは , setvideomode と てあります。 FORTRAN て、は各構造体は はせずにそのままの名前を出力しますが , いう名前て、 far コールて、呼び出され , short 型 C の属性がつけられた名前には自動的にを Fig. 1 のように定義します。変数名は自由に の引数をもち s れ ort 型の値を返す C の関数と つけてかまいません。構造体を関数値とす 付加します。 ALIAS を使らてコード上の名 いう意味をもっています。この関数を FOR る関数はサプルーチンとして引数を介して 前を指定するときにはこのような自動的な TRAN から呼び出すためには , INTER 値を戻すようにし , ウインドウ座標関係の 付加をしません。したがって , setvideomode FACE 文を使い上記の意味を忠実にコンパイ 関数は構造体 wxycoord を引数としない形 3D. FOR にしてあります。また , て始まるパラメー サンプルプログラム 3 D . F 0 R タは $ て、始まるようにしてあります。 3D. FOR /link fgraph. lib グラフィック関数に渡す文字列は , ヌル BY Tatsuo Takura 文字て終了するようにしなければなりませ ん。したがって , 文字列に C 属性を指定する か , 文字列の最後にヌル文字をつけ加える 60 CMAGAZINE 19 3 Fig. 2 拡張されたキー ワード ・ FORTRAN ALIAS FA 日 HUGE PASCAL REFERENCE VALUE VARYING cdecl far huge near EXTERN NEAR fO 「 a n pascal 一三ロ List 2 89 / 12 / 04 5 : $DEC し ARE 6 : ソースファイルの最初に C G RA P H . F I をインクルードさせます 8 : $INC し UDE: 'CGRAPH. FI'
List 2 / * 開始 y 座標 unsigned int starty : / * 終了 x 座標 uns i gned int end x : / * 終了 x 座標 uns i gned int endy; / * 点画フラグ unsigned 日 ag : Char / * 線の色を決めるパレット番号 unsigned long palette; / * 線の福 unsigned Char cirtype: unsigned Char dummy; / * 線の線種パターン長 unsigned Char linepattern: / * 線種パターン unsigned int pattern : ″拡張線種パターン int 本 / uns i g ned extpattern; / * 塗りっぷしフラグ f i Ⅱ f lag : unsigned Char / * 塗りつぶしカラーパレット番号事 / unsigned long fillcolor; circlel; ″ NO. 20 / 2 円の描画 . タイルバターンを使用する * / struct CIRC し E2 / * 予約パラメータ unsigned long reserved : / * ラスタオペレーション番号 unsigned int OP : / * x 座標 unsigned int 事 / / * y 座標 unsigned int / * 半径 unsigned int / * 開始 x 座標 unsigned int startx; / * 開始 y 座標 unsigned int starty; ″終了 x 座標 unsigned int endX : / * 終了 x 座標 unsigned int endy; / 事点画フラグ unsigned Char f 信 g : unsigned / * 線の色を決めるパレット番号 long palette; / * 線の幅 unsigned Char cirtype; unsigned Char dumny; / * 線の線種パターン長 unsigned Char linepattern: / * 線種パターン unsigned int pattern; / * 拡張線種パターン unsigned int extpattern; / 事換りつぶしフラグ unsigned char f i Ⅱ f lag : / * 塗りつふタイルバターン長 int patternl : long patternaddr; / * タイルバターンの格納アドレス unsigned c ircl e2 : / * NO. 21 / 1 楕円の描画 . タイルバターンを使用しない * / struct DAENI long 予約パラメータ unsigned reserved : / * ラスタオペレーション番号 unsigned int OP : / * x 座標 unsigned int CX . / * y 座標 unsigned int CY : / * x 方向の半径 unsigned int rX . / * y 方向の半径 unsigned int / * 開始 x 座標 unsigned int startx: / * 開始 y 座標 unsigned int sta rty : / * 終了 x 座標 unsigned int endx: / * 終了 y 座標 unsigned int endy; / * 点画フラグ unsigned Char f lag : / * 線の色を決めるパレット番号 unsigned long palette: / * 線の幅 unsigned Char cirtype: unsigned Char dummy; / * 線の線種パターン長 unsigned linepattern; char ″線種パターン unsigned int pattern; / * 拡張線種パターン unsigned int extpattern; / * 塗りつぶしフラグ unsigned Char f i Ⅱ fl ag : / * 塗りつぶしカラーパレット番号 * / unsigned long fillcolor; daenl : struct DAEN2 / * NO. 21 / 2 情円の描画 . タイルバターンを使用する * / long / * 予約パラメータ uns i gned reserved : / * ラスタオペレーション番号 unsigned int OP : / * x 座標 uns i gned int / * y 座標 uns i gned int / * x 方向の半径 unsigned int rx : / * y 方向の半径 unsigned int / * 開始 x 座標 uns i gned int sta rtx : / * 開始 y 座標 uns i gned int starty; / 本終了 x 座標 uns i gned int endX : / 本終了 y 座標 uns i gned int endy; / * 点画フラグ uns i g ned Char f 信 g : / 本線の色を決めるパレット番号 long unsigned pal ette : / * 線の幅 unsigned Char cirtype: unsigned Char dunmy: ″線の線種パターン長 uns i gned Char linepattern; / * 線種パターン uns i gned int pattern: / 事拡張線種パターン unsigned int extpattern; / * 塗りっぷしフラグ unsigned Char f i 日 f lag : ″塗りつぶしタイルバターン長 unsigned int pat tern に / 本タイルバターンの格納アドレス unsigned long patternaddr; daen2 : struct 円しし / * NO. 22. 閉鎖領域の塗りつぶし * / uns i gned / * 予約パラメータ long reserved , / * ラスタオペレーン番号 uns i gned int OP : / * 描画開始 x 座標 uns i gned int xl; yl: 描画開始 y 座標 unsigned int / ま境界を表わすパレット番号 unsigned long palette; / 事塗りつぶしフラグ unsigned Char f i Ⅱ f lag ; unsigned Char dumny; / * 塗りつぶしハ・しット番号 / ハ・しット長 int unsigned pat tern : ″タイルバターン格納アドレス unsigned long patternaddr; ″作業領域の先頭アドレス unsigned long workaddr: / * 作業領域の大きさ unsigned int workerea : 393 : 394 : 395 : 396 : 397 : 398 : 399 : 400 : 401 : 402 : 403 : 404 : 405 : 406 : 407 : 408 : 409 : 410 : 411 : 412 : 413 : 414 : 415 : 416 : 418 : 419 : 420 : 4 幻 : 422 : 423 : 424 : 425 : 426 : 427 : 428 : 429 : 430 : 431 : 432 : 433 : 434 : 435 : 436 : 437 : 438 : 439 : 440 : 441 : 442 : 443 : 444 : 445 : 446 : 447 : 448 : 449 : 450 : 451 : 452 : 453 : 454 : 455 : 456 : 457 : 458 : 459 : 460 : 46 に 462 : 463 : 464 : 465 : 466 : 467 : 468 : 469 : 470 : 471 : 472 : 473 : 474 : 475 : 476 : 477 : 478 : 479 : 480 : 481 : 482 : 483 : 484 : 485 : 486 : 487 : 488 : 489 : 490 : 491 : 492 : 493 : 494 : 495 : 496 : 497 : 498 : 499 : 500 : 501 : unsigned int 「 dO wnx : uns i g ned int rdowny : int unsigned mensiz: unsigned long nenaddr; glnage; struct GIMAGESET unsigned long reserved : unsigned int unsigned int lupx: int unsigned lupy; unsigned int mensiz, unsigned long menaddr; unsigned Char cswitch: uns i gned long foreground : uns i gned long background; g inageset : struct COPY / * NO. 25. 転送領域 unsigned long sstructaddr; ソース側 VRÅM アドレス unsigned int / * ソース側左上 X 座標 S ー u px : unsigned int / 事ソース側左上 Y 座標 SiUPY; / 事ソース側右下 X 座標 unsigned int srdownx; unsigned int / * ソース側右下 Y 座標 srdowny; uns i gned / * ディスト側 VRAM アドレス long dstructaddr; / 事ラスタオペレーション番号 uns i gned int OP : dlupx. / * デスト側左上 X 座標 unsigned int unsigned int / * デスト側左上 Y 座標 dlupy; な X 方向倍率 uns i g ned int int / * Y 方向倍率 uns i gned Y : / * 裏かえし unsigned Char riverse: unsigned Char / * 回転 rotate : 284 : 285 : 286 : 287 : 288 : 289 : 290 : 291 : 292 : 293 : 294 : 295 : 296 : 297 : 298 : 299 : 300 : 301 : 302 : 303 : 304 : 305 : 306 : 307 : 308 : 309 : 310 : 3 1 1 : 312 : 313 : 314 : 315 : 引 6 : 317 : 318 : 引 9 : 320 : 321 : 322 : 323 : 324 : 325 : 326 : 327 : 328 : 329 : 330 : 331 : 332 : 333 : 334 : 335 : 336 : 337 : 338 : 339 : 340 : 341 : 342 : 343 : 344 : 345 : 346 : 347 : 348 : 349 : 350 : 351 : 352 : 353 : 354 : 355 : 356 : 357 : 358 : 359 : 360 : 361 : 362 : 363 : 364 : 365 : 366 : 367 : 368 : 369 : 370 : 371 : 372 : 373 : 374 : 375 : 376 : 377 : 378 : 379 : 380 : 381 : 382 : 383 : 384 : 385 : 386 : 387 : 388 : 389 : 390 : 391 : 392 : / * 右下 x 座標 / * 右下 y 座標 / * メモリサイズの大きさ / * メモリ格納アドレス / * NO. 24. グラフィックイメージの設定 * / / * 予約パラメータ / * ラスタオペレーン番号 / * 左上 x 座標 / * 左上 y 座標 / * メモリサイズの大きさ / * メモリ格納アドレス / * カラースイッチ / * フォワグラウンドカラー パックグラウンドカラー COPY : struct MOVE unsigned long reserved : int unsigned int int Y : uns i gned Char cflag; / * NO. 26. 転送移動 / * 予約パラメータ / * ラスタオペレーション番号 / * X 方向移動ドット数 / * Y 方向移動ドット数 クリアフラグ nove : / * NO. 27. 構造体は無し * / / * NO. 28. 構造体は無し * / str uct 田 SPMODE unsigned long structaddr: Unsigned int dmode: dispnode: struct GETDROWP し ANE unsigned long structaddr: unsigned long duny; getdrowpl ane : struct GETDISPP し ANB unsigned long dumy: unsigned long structaddr; getdispplane: struct GETPA し ETTE unsigned long dumy: unsigned long structaddr; getpalette; struct GETVIEWPORT unsigned long structaddr: unsigned int lupx; unsigned int lupy; int rdownx : unsigned unsigned int rdowny : getviewport: / * NO. 34. フォアーグラウンドカラーの拾得 * / struct G ETFOREG ROUND / * VRAM 構造体のアドレス unsigned long structaddr; フォアーグラウンドカラー unsigned long palettenumber:/* get foreground を パックグラウンドカラーの拾得 * / struct GETBACKGROUND / * NO. 35. / 本 VRAH 構造体のアドレス unsigned long structaddr; unsigned long palettenunber:/* バックグラウンドカラー getbackground; struct GETBORDER unsigned long dumy: unsigned long CO ー 0 「 : / ま NO 認 9. 表示モードの取得 / * VRAM 構造体のアドレス / * 表示モード / ま NO. 30. 描画プレーンの取得 / * VRAM 構造体のアドレス / * ダミ / * NO. 31, 表示プレーンの取得 / * ダミ / * VRAM 構造体のアドレス / * NO. 32. パレットの取得 / * ダミー / * パレット番号 / * NO. 33. ビューポート領域の取得り / * VRAM 構造体のアドレス / * ビューポート領域左上 x 座標 / * ビューポート領域左上 y 座標 / * ビューポート領域右下 x 座標 / * ビューポート領域右下 y 座標 f i Ⅱ : ″ NO. 23. グラフィックイメージの取得事 / struct GIMAGE / 本予約パラメータ 事 / reserved : unsigned long / 事左上 x 座標 unsigned int lupx; ″左上 y 座標 unsigned int lupy : な NO. 36. ポーダカラーの取得 / * ダミー / まポーダカラー 76 CMAGAZINE 19 3
五ロ はじめて学ぶ C プログラミンク (e) のことて、すが , ここて、は関数のデータ型 れた表記方法て、す。したがって , タイプ 1 の と呼びます。データ型そのものについては , 形式は古い C 言語処理系て、はサポートされて 11 月号て、解説しましたのて、そちらを参照し いないのて、 , コンパイルエラーになってし ていただきたいのて、すが , 基本的に変数の まいます。とくに C 言語がもともと搭載され データ型はそのまま関数の型として用いる ている UNIX マシンなどて、は , タイプ 1 が使 ことがて、きます。 int, char, double, float えない C 言語て、ある場合が多いかと思われま といった基本データ型のほかに , 修飾子を す ( もっともスーパーユーザが手を打ってい つけたデータ型についても関数の型として るかもしれませんが ) 。タイプ 1 とタイプ 2 の 認められます。さらにポインタや構造体も 実際の働きの違いはあとて、述べる関数プロ OK て、す ( 構造体については処理系による ) 。 トタイプ宣言の項目を参照してください ただポインタと構造体については , まだそ しばらくは両方の形て、関数を書くこととし れ自体の説明をしていないのて、今回は割愛 ます。 させていただきます。 6-2-2 関数の型 ところて、 ListI, 2 の例て、は , 関数の値は int こて、は関数の型として int 以外 型て、した 変数にデータ型があったように , 関数に の例をいくっかご紹介していきましよう。 List3 は , 引数を調べて小文字だったら大 もデータ型といったものが存在します。正 文字の値を返し , そうて、なければ「引数が小 確にいえば , 関数が返す値の型 ( return val Lis. t 2 関数の例タイプ 1 2 : 4 : int add2(int x, int int z) return(x 十 y 十 2 ) : 6 : List 2 ・ 関数の例タイプ 2 2 : 4 : int add2(), Y, z) 5 : int X, y, 2 : return(x 十 y 十 2 ) : 7 : Fig. 1 関数の基本形 〇タイプ 1 List 3 型名 関数名 ( 引数型宣言並び ) 関数内変数宣 実行文 る す 換 変 に をプ 字イ 文タ 文 英 1 0 乙 -4 -- 0 CD ー 8 0 》 0 1 よ 0 乙っ 0 -4 戸 0 《 0 ー lower-to-upper (char letter) Char c; if (('a ・← letter) & & (letter ← letter C return (c) : } else { printf ( " 引数が小文字ではありません \ n " ) : return (letter) : 〇タイプ 2 型名 関数名 ( 引数名並び ) 引数型宣言 関数内変数宣 実行文 List 3 1 0 乙っ 0 -4- ド 0 ー 8 0 》 0 1 ーっ 0 っ 0 -4 ・ 0 ー 8 英文小文字を大文字に変換する ( タイプ 2 ) lower-to-upper(letter) letter: きますから , return(a 十 b); とすれば , a 十 b の結果が戻り値となります ( カッコは省略可能て、す ) 。したがって , List1 のプログラムはもっと簡単に書くこともて、 きます (List2, List2')0 さて , 関数の型には Fig. 1 に示すように ふたつのタイプがあります。これらの違い を説明しましよう。実はタイプ 1 は 1988 年末 に出された ANSI 規格案に , 新たに盛り込ま Char c; letter) & & (letter ← letter C return (c) : ⅲ t f ( " 引数が小文字ではありません Yn" ) : return (letter) : はじめて学ぶ C プログラミング 113
します。 expDesca1ed( ) は , 左辺と右辺の 型が等しいことをチェックしてから , Fig. 3 ②の木構造を組み立てます。ポインタどう しの減算は , OP DESCALESUB となりま ータ 関数呼び出しの処理 ( exp. c より ) *expFuncall (EXPR *fun, List 3 1 : public EXPR TREE *param list) す。 を行うときに , スケーリングをするコード DESCALESUB については , コード生成 0 SCALEADD, op SCALESUB, op 関数呼び出し を生成するようにします。 い関数呼び出して、は ,paramlist には NULL になっています。パラメータがひとつもな パラメータリストは , Fig. 4 のような形式 存在を説明するのは , ややこしいて、すね ) 。 ( 「関数を処理する関数」という自己言及的な ータリストを表す木構造へのポインタて、す す。 2 番目のパラメータ paramlist は , パラメ 呼び出す関数を表す木構造へのポインタて、 受け取ります。 1 番目のパラメータ fun は , exp uncall ( ) は , ふたつのパラメータを 理するのは , expFuncall( ) て、す (List3) 。 るかを見てみましよう。関数呼び出しを処 次に関数呼び出しがどのように処理され Fig. 4 バラメータリスト が渡されます。 3 : 4 : 5 : 6 : 7 : 9 : 14 : 20 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : TREE TYPE *type; EXPR *param, *X; if (fun = NULL) type ニ fun->type; return NU しし : if (isFunction(type)) = type->father; type else if (isP0inter(type) & & isFunction(type->father) ) { type->father->father; type } e I se { error ("function or pointer tO function required") : return NU しし : for (p ニ paramlist; p ! = NU しし & & p ! ニ ERROR; p = p->first) { (EXPR *)p->second,• param = NU しし) if (param return NU し L,• if (isNumeric(param->type)) (TREE *)coerce(param, p—>second = makeN0de2 (OP-FUNC, , TYPE_INTEGER, X if (type = TYPE-CHAR) return coerce (X, else if (isP0inter(type)) return makeN0deI (op-It0R, ・ R' type, e ー S e return x; fun, (EXPR *)paraml ist) : まず , はじめに NULL のチェックをしま パラメータ fun が , ①関数 す ( 7 行 ) 。次に そのもの , ②関数へのポインタ , のいずれ かて、あることをチェックし , これら以外て、 あれば , 工ラーとします ( 9 ~ 16 行 ) 。そし て , OK-C あれば , パラメータリストを順に たどりながら , char → int の変換を行います ( 17 ~ 23 行 ) 。 24 行目の makeNode2( ) への呼び出して、 , 実際に関数呼び出しの木構造が作られます。 Cm コンパイラて、は , 関数の戻り値はつねに AX レジスタに返る ( = 関数の戻り値はつね 68 ①バラメータがないとき paramIist=NULL ②バラメータが 1 個のとき paramlist CMAGAZINE 19 3 1 番目のバラメータ ③バラメータが n 個のとき paramlist 1 番目のノヾラメータ 2 番目のバラメータ n ー 1 番目のバラメータ n 番目のノヾラメ