第5章 変数・構造体・マクロ定義

5.1 定数定義

MQLIBに関係する全ての定数は、ファイルmqstrs.hで定義されている。このファイルはmqdb.hでインクルードされているので、改めてインクルードする必要はない。また定数のうち、エラー番号関連のものはmqerror.hで、関数番号及び関数名についてはmqfunc.hで定義されている(第5.5節参照)。
mqstrs.hで定義されている定数については、巻末の第A4章に一覧表がある。

5.2 列挙型変数定義

現在定義されている列挙型変数は次の通りである。

5.2.1 MQAM

MQAMは、ヘッダにアクセスする際に、読み込んだ、あるいはファイルに書き込 むためのヘッダ情報を一時的に蓄える方法を指定する変数である。但し、MqRead()及びMqCreate() によるアクセスの場合には、この変数による制御は適用されない。
typedef enum { MQ_DIRECT, MQ_TMP, MQ_SHM, MQ_EMS } MQAM;
各変数の意味は次の通りである。
MQ_DIRECT
データファイルに直接アクセスしてヘッダの読み書きを行なう。これは標準入出力に対しては無効であり、エラーとなる。
MQ_TMP
ヘッダの内容を一時ファイルに書き出した上で、アクセスする。ファイルの読み出しの場合には、読み出されたヘッダの内容が一時ファイルに書き出され、ファイルの書き出しの場合には、書き出したいヘッダ情報が一時ファイルに書き出される。一時ファイルが作成されるディレクトリは /tmp である。一時ファイルの名称は、次のようになる。

mqdb.[プロセス番号].[ファイル記述子]

ここで、プロセス番号は現在実行中のプログラムのプロセス番号であり、ファイル記述しはアクセスしているファイルに適用されているファイル記述子である。なお、同名のファイルが存在した場合には、強制的に上書きされる
(注1)。このファイルは、MqOpen() 関数 (C言語) またはMQOPEN()サブルーチン (FORTRAN) が呼び出された時に自動的に作成され、MqClose() (C言語) または MQCLOS() (FORTRAN) が呼び出された時に自動的に削除される(注2)
(注1)ファイル名の性質上、同名のファイルが存在する可能性はほぼないと考えてよい。但し、/tmpを数台のコンピュータ間で共用している場合などには、別のプログラムで使用していた一時ファイルが上書きされることがあり得るので、注意する必要がある。
(注2)但し、プログラムが外部から強制終了された場合や、内部エラーなどによ り異常終了した場合には、一時ファイルが残ったままとなる。
MQ_SHM(未実装)
ヘッダの内容を共有メモリに蓄積する。
MQ_EMS(未実装)
ヘッダの内容を EMS メモリに蓄積する。MS-DOS以外では利用できない。
MqInit()関数(サブルーチン)を呼びだし、MQLIBを初期化した直後は、ファイルアクセス方法は MQ_TMP となる。
本変数は、MqFile構造体内で使用される(
第5.3.3節参照)。

5.2.2 MQDF

MQDFは、月震の元ファイルにおけるデータのフォーマットの種類を示す。
typedef enum { MQ_OLD, MQ_NEW } MQDF;
本変数において、MQ_OLDは元ファイルのデータフォーマットがOLDフォーマットであることを、MQ_NEWはNEWフォーマットであることを示す。なお、アポロ月震データのフォーマットについては、寺薗(1992)などに詳述されている。

5.2.3 MQDT

MQDTは、月震のデータの種別を表すための列挙型変数である。
typedef enum { MQ_LP, MQ_SP, MQ_TIDAL }  MQDT;
本変数において、MQ_LPは長周期データを、MQ_SPは短周期データを、MQ_TIDALは潮汐データを表す。

5.2.4 MQFT

MQFTは、MQDBフォーマットファイルのフォーマットの種類を示す。
typedef enum { MQ_FULLTEXT, MQ_COMPOSITE, MQ_XDR }    MQFT;
MQ_FULLTEXTは、ヘッダ部、データ部共にテキストデータであることを示し、MQ_COMPOSITEは、ヘッダ部のみがテキストで、データ部はバイナリ出力されていることを示す。なお、このバイナリ出力部は機種、処理系及びCPUのバイトオーダに依存するため、MQ_COMPOSITEファイルについては、異機種間、あるいは異なる処理系でコンパイルされたライブラリ間でのデータの互換性は保証されない。
MQ_XDRは、XDRライブラリを利用したデータ表現形式によるフォーマットである。XDRライブラリを使用した場合には、データ部はバイナリ出力であるが、異機種間、あるいは異なる処理系でコンパイルされたライブラリ間でのデータ互換性は保証される。なお、MQDBにおけるデータ表現形式について詳しくは、
「月震データベース仕様書」に述べられている。

5.2.5 MQIO

MQIOは、アクセスするファイルの種類を指定する。MqRead及びMqCreate 関数を利用してファイルにアクセスする場合には、本変数の指定は意味を持たない。
typedef enum { MQ_FILE, MQ_STDIN, MQ_STDOUT, MQ_STDERR } MQIO;
各変数の意味は次の通り。
MQ_FILE
通常のファイルに対して入出力を行なう。
MQ_STDIN
標準入力から読み込む。
MQ_STDOUT
標準出力へ書き出す。
MQ_STDERR
標準エラー出力へ書き出す。なお、標準エラー出力は本来、エラーメッセージの出力のための用意されているものであって、データの出力先として利用することは好ましくない。端末へのデータ出力などでは、なるべくMQ_STDOUTを利用する。
本変数は、MqFile構造体内で使用される(
第5.3.3節参照)。MqOpen()またはMQOPEN()関数/サブルーチンにおいて、MQRW変数(第5.2.7節参照)にMQ_WRITEがセットされている際に、MQIO変数にMQ_STDINを指定するとエラーとなる。同様に、MQRW変数にMQ_READがセットされされている状況で、MQIO変数にMQ_STDOUTを指定してもエラーとなる。

5.2.6 MqMode

MqModeは、月震の観測モードを表すための列挙型変数である。
typedef enum { MQ_PEAKED, MQ_FLAT }      MqMode;
本変数において、MQ_PEAKEDは peaked モードでの観測、MQ_FLATはflatモードでの観測が行なわれたことを示す。

5.2.7 MQRW

MQRWは、MQDBフォーマットファイルへのアクセスの形態を指定する。
MqRead及びMqCreate関数を利用してファイルにアクセスする場合に は、本変数の指定は意味を持たない。
typedef enum { MQ_READ, MQ_WRITE, MQ_UNKNOWN } MQRW;
MQ_READは読み出しを、MQ_WRITEは書き出しを意味する。MQ_UNKNOWNはアクセス形態が未決定であることを意味するため、MQLIB内でこの状態のままファイルアクセスが行なわれるとエラーとなる。
本変数は、MqFile構造体内で使用される(
第5.3.3節参照)。

5.2.8 MqStat

この列挙型変数は、ヘッダへのアクセスの成功/失敗を記録するために、状況変数 MqStatusで利用される(第5.6節参照)。
typedef enum { MQ_NOACCESS, MQ_SUCCESS, MQ_FAIL } MqStat;
MQ_NOACCESSは、該当するヘッダのアクセスが行なわれなかったことを示し、MQ_SUCCESSは、アクセスが成功した時にセットされる。MQ_FAILは、アクセスが失敗した際の値である。

5.2.9 MqYesNo

MqYesNoは、ヘッダの読み書きなどにおいてアクセスするヘッダを特定するために用いられる(第5.3.1節参照)。また一般的に、yes 及び no を表す Boolean 変数としての利用も可能である。
typedef enum { MQ_YES, MQ_NO } MqYesNo;

5.3 構造体定義

MQLIBにおいて現在定義されているデータ構造体は次の通りである。

5.3.1 MqAccess

MqAccessは、月震データファイルのヘッダへのアクセスを制御するための構造体であり、主に MqRead(), MqCreate() 関数を利用したファイルアクセスの際に、アクセスするヘッダを指定するために用いられる。
ヘッダを読みとる際に MqRead()関数を利用する場合には、この構造体変数に値MQ_YESがセットされているヘッダだけが読みとられる。他のヘッダについては読みとりが行なわれない。
ヘッダを作成する際に MqCreate() 関数を利用する場合には、この構造体変数にMQ_YESがセットされているヘッダだけが作成される。他のヘッダは作成されない。
typedef struct {
    MqYesNo  AveAmp;       /* 平均振幅 */
    MqYesNo  Channels;     /* チャンネル数 */
    MqYesNo  DataCreDate;  /* データ作成日時 */
    MqYesNo  DataFormat;   /* 元ファイルのデータフォーマット */
    MqYesNo  DataModDate;  /* データの更新日時 */
    MqYesNo  DataType;     /* データ種別 ( OLD/NEW ) */
    MqYesNo  EndRecord;    /* 元ファイルのデータ終了レコード数 */
    MqYesNo  MaxAmp;       /* 最大振幅 */
    MqYesNo  NumOfData;    /* データ数 */
    MqYesNo  ObsMode;      /* 観測モード ( PEAKED / FLAT ) */
    MqYesNo  OrgFileName;  /* 元データのファイル名 */
    MqYesNo  SampRate;     /* サンプリング間隔 */
    MqYesNo  Station;      /* 観測ステーション */
    MqYesNo  StartRecord;  /* 元ファイルのデータ開始レコード数 */
    MqYesNo  StartTime;    /* データの開始時刻 */
    MqYesNo  TapeNumber;   /* テープ番号 */
    }    MqAccess;

5.3.2 MqAmp

MqAmpは、最大振幅やサンプリング間隔など、チャンネルによって値が異なり得る情報を格納するための構造体である。チャンネルによって値が異なっている場合には、メンバ channels には 1 以上の数値が格納される。すべてのチャンネルで同じ値をとるときには、channelsには 1 がセットされる。
typedef struct {
    unsigned short  channels;         /* データのチャンネル数 */
    double     data[MQCHANNELMAX+1];  /* データ */
    }   MqAmp;

5.3.3 MqFile

MqFile は、MQLIBにおいてファイル入出力の管理のために用いられる(MqRead() 及び MqCreate() 関数を利用した場合を除く)。
typedef struct {
    MqYesNo   InUse;      /* ファイル記述子が使用されているかどうかのフラグ */
    MQAM      accmethod;  /* アクセス方法 */
    MQIO      iostream;   /* 入出力の方法(ファイル、標準入出力) */
    MQRW      ReadWrite;  /* 入出力の方向(入力か出力か) */
    char     *filename;   /* 実際のファイル名 */
    MqLibInfo libinfo;    /* 読みとられたライブラリ情報 */
本変数は、プログラム内ではグローバル変数 MqFilDesc として使用される。

5.3.4 MqHeader

MqHeader構造体は、ヘッダのデータをやりとりするための情報を格納する構造体である。この構造体は MqRead() 及び MqCreate() 関数内で、ヘッダのデータを構造体単位で授受するために使われる。
typedef struct MqHeader    {
    MqAmp           AveAmp;       /* 平均振幅 */
    unsigned short  Channels;     /* チャンネル数 */
    MQDF            DataFormat;   /* データのフォーマット */
    MQDT            DataType;     /* データ種別 */
    unsigned long   EndRecord;    /* 元ファイルにおけるデータ終了レコード数 */
    MQFT            FileType;     /* データファイル種別 */
    MqAmp           MaxAmp;       /* 最大振幅 */
    time_t          ModDate;      /* 修正日時 */
    unsigned long   NumOfData;    /* データ数 */
    MqMode          ObsMode;      /* 観測モード */
    char            OrgFile[FILENAME_MAX];  /* 元のデータファイル名 */
    MqAmp           SampRate;     /* サンプリング間隔 */
    unsigned long   StartRecord;  /* 元ファイルにおけるデータ開始レコード数 */
    MqTime          StartTime;    /* データの開始時刻 */
    unsigned short  Station;      /* 観測ステーション */
    unsigned short  TapeNumber;   /* テープ番号 */
    }    MqHeader;
個々の変数名はヘッダに対応する。変数の内容については、
「月震データベース仕様」に述べられている。

5.3.5 MqLibVer

MqLibVer構造体は、MQDBフォーマットで記述されたデータファイルの先頭行に記されている、ライブラリについての情報を受渡しするための構造体である。この構造体は、以下のようになっている。
typedef struct {
    char  LibType[2];        /* ライブラリ種類識別子 */
    char  Release;           /* リリース番号 */
    char  Major;             /* メジャー番号 */
    char  Minor;             /* マイナー番号 */
    }   MqLibVer;
LibTypeには、英文字2文字で記されるライブラリ種類識別子が入る。Releasemajorminorには、それぞれ、ライブラリ番号、メジャー番号、マイナー番号が格納される。但し、それぞれの変数の型は char 型であり、数字ではありながら shortlong などではない。
同様に、LibType もライブラリ識別子の英2文字分しか領域が用意されておらず、通常のC言語における文字列のように、最後が\0 とはなっていない。従って、LibTypeから通常の文字列変数などにコピーする際、あるいはその逆の操作を行なう際、strcpy()などの通常の文字列関数を利用するとメモリエラーを引き起こす可能性がある。strncpy()関数などを利用するか、直接文字列を代入するようにプログラムを組む必要がある。

5.3.6 MqLibInfo

MqLibInfoは、MQDBフォーマットファイル先頭行に記されている情報全てを受 渡しするための構造体である。形は以下のようになっており、上記 MqLibVer にプログラム署名の情報が加わっただけである。本構造体を利用する際の注意点など は、上記MqLibInfo の場合と基本的に同じである。
typedef struct {
    MqLibVer    LibVer;                    /* ライブラリのバージョン */
    char        ProgSign[MQPROGSIGNLEN];   /* プログラム署名 */
    }   MqLibInfo;

5.3.7 MqTime

MqTimeは、主に月震のデータ開始時刻を格納するために利用される構造体であり、次のような形式となっている。
typedef struct {
    unsigned short    year;     /* 年 */
    unsigned short    day;      /* 日 ( 1 から 366 ) */
    unsigned short    hour;     /* 時 ( 0 から 23 ) */
    unsigned short    minute;   /* 分 ( 0 から 59 ) */
    unsigned short    second;   /* 秒 ( 0 から 59 ) */
    unsigned short    ms;       /* マイクロ秒 ( 0 から 999 ) */
    }  MqTime;

5.4 マクロ定義

MQLIBとしての独自のマクロ定義は比較的少なく、下に挙げてあるだけである。但し、エラー番号及び関数の番号は全てマクロによって定義されている。これについては、巻末付録第A3章に全て表として掲載されている。
#define MQFILENAMELEN    12  /* ファイル名の長さ */
#define MQFILDESCMAX     16  /* 使用できるファイル記述子の数 */
#define MQLIBVERLEN       5  /* ライブラリ番号の最大長 */
#define MQPROGSIGNLEN    16  /* プログラム署名の最大の長さ(バイト) */
#define MQHDRLENMAX    1024  /* ヘッダの最大の長さ(バイト) */
#define MQHDRLINEMAX     80  /* ヘッダにおける1行の長さの最大値 */
#define MQCHANNELMAX    255  /* 最大チャンネル数 */
#define MQTOPLINEMIN     12  /* 先頭行の長さの最小値(バイト) */
また、MQLIBのライブラリ種別、リリース番号、メジャー番号、マイナー番号も、マ クロで定義されている。
#define MQLIB_LIBTYPE   "MQ"    /* ライブラリ種別 */
#define MQLIB_RELEASE     1     /* リリース番号 */
#define MQLIB_MAJOR       0     /* メジャー番号 */
#define MQLIB_MINOR       0     /* マイナー番号 */
その他に、次のようなマクロ定義が mqdb.h 内に記述されている。これらは直接 MQLIB の動作には関係しないが、ユーザ・プログラム内で利用することもできる。このうち FILENAME_MAX は、本来 ANSI C 対応の処理系であれば stdio.h などで定義されているはずであり、MQLIB では未定義の場合のみ、改めて定義し直している。従って、処理系で既に FILENAME_MAX が定義されている場合には、そちらが優先される。
#define MQ_TRUE        1   /* Boolean 型変数 */
#define MQ_FALSE       0   /* Boolean 型変数 */
#define FILENAME_MAX 255   /* ファイル名の最大長 */

5.5 エラー番号・関数番号定義

エラー番号及びエラーレベルは、全てエラー関連の変数・マクロを定義しているファイル mqerror.h に定義されている。このヘッダファイルは、ライブラリ作成時に、エラー番号、エラーレベル(後述)及びそれに対応するエラーメッセージを記述したファイル mqerror.list 、及び、元となるファイル mqerror.tmpl から、自動的に生成される。
また、エラーが発生した場合、その関数及びサブルーチンの名前が自動的に番号でセットされる。この関数の番号を「関数番号」といい、これらは mqfunc.h で定義されている。MQLIB内でエラーが発生すると、mqerror.h内で定義されているグローバル変数 MqErr に値がセットされる。この変数は次のような構造体となっており、各メンバーは次のような意味を持つ。
struct {
    unsigned long  errno;  /* エラー番号 */
    unsigned long  func;   /* エラーが発生した関数の番号  */
    unsigned short level;  /* エラーのレベル */
    unsigned short warn;   /* エラーメッセージを出力するエラーのレベル */
    }  MqErr;
エラー番号については後述する。
MQLIBでは、エラーに対し、エラー番号と、そのエラーの重大度を表すエラーレベルの 2 種類の情報が定義される。エラーのレベルは各エラーについて一意に決められており、エラーのレベルによって処理が異なる(
第1.1節参照)。
関数番号は、該当する関数・サブルーチン名を全て大文字に直したマクロ名で定義されている。例えば、MqCreateの関数番号のマクロ名はMQCREATEである。
実際の関数名は、グローバル変数**MqFuncNameに定義されており、配列の番号にマクロ名を指定すれば、実際の関数名が入った文字列の先頭ポインタが得られる。例えば、次の printf 文は(大変つまらない例ではあるが)、MQCREATEで示される関数の名前(当然MqCreateである)を出力する。
printf( "%s\n", MqFuncName[MQCREATE] );
MQLIBの関数は、最初に必ず関数番号をセットするようになっている。そのため、エラーが起きた場合、必ずその関数番号が参照される。但し、MQLIB関数がさらに上のMQLIB関数から呼び出されている場合などは、必ずしもエラーの原因が該当する関数ではない場合もあるので、デバッグなどの際には注意する必要がある。
構造体の中で、warnはユーザが直接操作することが可能である。このメンバは、エラーメッセージをどのレベルのエラーが発生した場合に出力するかを制御する。MQLIBでは、エラーメッセージは本メンバ以上のレベルのエラーが発生した場合に出力される。例えば、warnEMQ_FATAL となっている場合には、エラーレベルがFATAL の場合にのみエラーが出力される。
warnの制御は、本メンバに直接変数を代入することによっても可能であるが、間違いを防ぐために、なるべくユーティリティ関数 MqSetWarnLevel() を利用するようにする。
プログラム中では、エラー番号やエラーが発生した関数の番号などを自由に参照できる。しかし、将来にわたってこれらの番号は変更され得るので、エラー番号、関数番号とも、マクロ名を使用することが望ましい。全エラー番号とその意味については、巻末の第A3章に一覧表がある。

5.6 状況変数

MQLIB内では、ヘッダの読み込みの成功/失敗や、ライブラリのバージョンなどを、 定数として保持してあり、必要に応じてユーザプログラムから参照することができる。 これらの変数は状況変数(condition variable)という。上節で述べたエラー番 号もこのような変数の一種と考えることができるが、MQLIB内では、MqErr構造体の他に、次の 3 つの構造体が状況変数として定義されている。

5.6.1 MqStatus構造体

本構造体は、MqStat列挙型定数を利用しており、ヘッダアクセスの成功/失敗を記録している。ヘッダへのアクセスが正常に終了した場合には、各ヘッダに対応する構造体メンバに MQ_SUCCESS が記録され、失敗した場合には MQ_FAIL が代入される。なお、ヘッダにアクセスしなかった場合には、該当する構造体メンバには MQ_NOACCESS が代入される。この代入は、プログラム初頭において MqInit() 関数(C言語)、MQINIT() サブルーチン(FORTRAN)が呼ばれた際に行なわれるので、この関数またはサブルーチンが呼ばれていない場合、本構造体の内容は保証されない。
MqStatus構造体の内容は次の通りである。
struct {
    MqStat  AveAmp;       /* 平均振幅 */
    MqStat  Channels;     /* チャンネル数 */
    MqStat  DataCreDate;  /* データ作成日時 */
    MqStat  DataFormat;   /* 元ファイルのデータフォーマット */
    MqStat  DataModDate;  /* データ修正日時 */
    MqStat  DataType;     /* データ種別 */
    MqStat  EndRecord;    /* データの終了レコード */
    MqStat  FileType;     /* ファイルフォーマット */
    MqStat  MaxAmp;       /* 最大振幅 */
    MqStat  NumOfData;    /* データ数 */
    MqStat  ObsMode;      /* 観測モード */
    MqStat  OrgFileName;  /* 元データのファイル名 */
    MqStat  SampRate;     /* サンプリング間隔 */
    MqStat  Station;      /* 観測点 */
    MqStat  StartRecord;  /* データの開始レコード */
    MqStat  StartTime;    /* データの開始時刻 */
    MqStat  TapeNumber;   /* テープ番号 */
    } MqStatus;

5.6.2 MqLibVersion構造体

本構造体には、MQLIBのバージョンが保存されている。本変数は、MqInit() 関数(C言語)、またはMQINIT()サブルーチン(FORTRAN)によって初期化される。またMQLIBを利用してMQDBフォーマットファイルを作成する場合、本構造体の情報を利用して先頭行を作成する。
MqLibVersion構造体はMqLibVer型の構造体で(
第5.3.5節参照)、そのメンバは次のようになっている。

メンバの型 メンバ名 内容
char LibType[2] MQDBライブラリ識別子
char Release MQDBリリース番号
char Major MQDBメジャー番号
char Minor MQDBマイナー番号

5.6.3 MqFilDesc構造体配列

本構造体配列は、MqOpen() または MQOPEN() 関数/サブルーチンによってオープンされたファイルについての情報を管理するための変数であり、配列は 16 個確保される。従って、MqOpen() または MQOPEN() を利用して同時にオープンできる MQDBフォーマットファイルの数は 16 個となる。
(注)MqRead() 及び MqCreate() 関数を利用した場合には、このよ うな制限はない。
MqFilDescMqFile型構造体(
第5.3.3節参照)の配列で、配列の添字がファイル記述子の番号に対応する。
MqOpen() または MQOPEN() サブルーチンが呼ばれると、未使用で最も若いファイル記述子番号が新たに割り当てられ、必要な情報がセットされた上で、そのファイル記述子番号がプログラムに返される。この情報は、MqClose() または MQCLOS() 関数/サブルーチンによってファイル記述子の割当が解除され、番号が破棄されるまで変更することはできない。
▲このページの先頭へ


前の章へ

目次へ

次の章へ
月震ホームページへ
terakinizers!!トップへ