macro.h マニュアル

(The documentation of macro.h)

Last Update: 2021/11/30


macro.hでは ymaeda_opentoolsで共通に用いるマクロが定義されている。 定数マクロと関数形式マクロがある。 各マクロの定義を以下に示す。
Macros commnly used by ymaeda_opentools are defined in macro.h. Both constant macros and function-type macros are present. Definitions of individual macros are shown below.

◆共通事項 (Notes common to all macros)


◆目次(Table of contents)



マクロ名(Macro name):
     ENGLISH_MODE

(Value):
     値を持たない。
     This macro has no value.

メッセージの出力言語を切り替えるためのマクロ。 「定義されているか否か」によって切り替える。 このマクロが定義されている場合はメッセージが英語で表示される。 マクロが定義されていない場合はメッセージが日本語で表示される。
A macro to switch the language of messages. The language is switched based on whether this macro is defined or not. If this macro is defined, messages are displayed in English; otherwise messages are displayed in Japanese.


マクロ名(Macro name):
     pi

(Value):
     M_PI

円周率\(\pi\)。 円周率をM_PI(C言語組み込みマクロ)よりも簡潔に表現するために定義した。
A circular constant \(\pi\). This macro was defined to more briefly express the circular constant than M_PI (a built-in macro in C language).


マクロ名(Macro name):
     strsize

(Value):
     1024

文字列に用いるchar型配列のデフォルトの長さ(\0を含む)。 ymaeda_opentoolsではオーバーフロー対策を簡単に行うため、 ほぼ全ての文字列の配列長をstrsizeに統一している。
The default length for char-type arrays that represent strings (including \0). To easily avoid overflows, ymaeda_opentools commonly uses strsize as the length of arrays for almost all strings.


マクロ名(Macro name):
     secIn1min

(Value):
     60

1分間の秒数。
The number of seconds in a minute.


マクロ名(Macro name):
     minIn1hour

(Value):
     60

1時間の「分」の数。
The number of minutes in a hour.


マクロ名(Macro name):
     hourIn1day

(Value):
     24

1日の時間数。
The number of hours in a day.


マクロ名(Macro name):
     ZERO_THRESHOLD

(Value):
     1.0e-08

実数を0であると見なすための閾値。 一般に実数の等号判定は容易でないが (例えば「if((1.0/3.0)∗3.0==1.0)」はfalseとなる)、 閾値を用いることで等号判定が可能になる。 関数doublecmp(doublemath.h)のマニュアルも参照。
A threshold value to regard a real number to be zero. Although identifying equality of two real numbers is generally not easy (for example, “if((1.0/3.0)∗3.0==1.0)” is false), the identification is possible by using the threshold. Also see the documentation of function doublecmp (doublemath.h).


マクロ名(Macro name):
     nMsgRoute

(Value):
     20

保存するメッセージ出力経路の数。 メッセージ出力経路とは例えば
というような情報のことである。 エラーメッセージの表示時にこうした情報を合わせて出力することで エラー箇所の特定が容易になる。 そのためにはメッセージの出力経路を保存しておく必要があり、 最大でいくつまで保存するかを決めるのがこのマクロである。
The number of message output routes to be preserved. The message output routes are, for example, the information as below:
This kind of information facilitates identification of actual errors that caused the error message. To realize outputting this kind of information, the message output routes must be stored; the maximum number of routes to be stored is determined by this macro.


マクロ名(Macro name):
     sRoute

(Value):
     setMsgRoute(__FILE__,__FUNCTION__,__LINE__)

関数setMsgRoute (msg.h)の短縮形。 setMsgRouteは関数呼び出しの直前に用いて メッセージ出力経路(マクロnMsgRouteの解説参照)を追加する関数である。 頻繁に用いるのでコードを簡潔にするためにこのマクロを用いる。
An abbreviated form of function setMsgRoute (msg.h). This function is used immediately before every function call to add a message output route; see the description of macro nMsgRoute for the message output route. As this function is frequently used, this abbreviated form is used to make the code brief.


マクロ名(Macro name):
     pRoute

(Value):
     printMsgRoute(__FILE__,__FUNCTION__,__LINE__)

関数printMsgRoute (msg.h)の短縮形。 printMsgRouteはメッセージ出力の直前に用いて メッセージ出力経路(マクロnMsgRouteの解説参照)を表示する関数である。 頻繁に用いるのでコードを簡潔にするためにこのマクロを用いる。
An abbreviated form of function printMsgRoute (msg.h). This function is used immediately before displaying a message to show message output routes; see the description of macro nMsgRoute for the message output routes. As this function is frequently used, this abbreviated form is used to make the code brief.


マクロ名(Macro name):
     rRoute

(Value):
     removeMsgRoute()

関数removeMsgRoute (msg.h)の短縮形。 removeMsgRouteは関数呼び出しの直後に用いて メッセージ出力経路(マクロnMsgRouteの解説参照)の最後の1要素を削除する関数である。 頻繁に用いるのでコードを簡潔にするためにこのマクロを用いる。
An abbreviated form of function removeMsgRoute (msg.h). This function is used immediately after every function call to remove the last component of message output routes; see the description of macro nMsgRoute for the message output routes. As this function is frequently used, this abbreviated form is used to make the code brief.


マクロ名(Macro name):
     TRUE

(Value):
     1

真偽値(真)を表すマクロ。
A macro to represent a logical value of true.


マクロ名(Macro name):
     FALSE

(Value):
     0

真偽値(偽)を表すマクロ。
A macro to represent a logical value of false.


マクロ名(Macro name):
     YES

(Value):
     1

質問の答えが「はい」であることを表すマクロ。
A macro to represent that the answer of a question is “yes”.


マクロ名(Macro name):
     NO

(Value):
     0

質問の答えが「いいえ」であることを表すマクロ。
A macro to represent that the answer of a question is “no”.


マクロ名(Macro name):
     LITTLE_ENDIAN

(Value):
     1234

バイトの並びがリトルエンディアンであることを表すマクロ。
A macro to represent that the byte order is a little endian.


マクロ名(Macro name):
     BIG_ENDIAN

(Value):
     4321

バイトの並びがビッグエンディアンであることを表すマクロ。
A macro to represent that the byte order is a big endian.


マクロ名(Macro name):
     BYTE_ORDER

(Value):
     LITTLE_ENDIAN

使用するコンピュータにおけるバイトの並び。
The byte order in the computer used.


マクロ名(Macro name):
     MINIMUM_LONG_BYTE

(Value):
     4

C言語規格(ANSI-C)において許容されるlong型変数の最小バイト数。 但しCHAR_BITがC言語規格(ANSI-C)で許容される最小値を取ることを前提とする (この前提は1バイト=8ビットであるという意味であり、 ANSI-Cでは1バイトは8ビット以上であれば良いが ほぼ全てのマシン環境で1バイト=8ビットになっていると思われる)。
The minimum allowed number of bytes of long-type variables in the C language standard (ANSI-C), given that CHAR_BIT takes the minimum allowed number in the standard; this assumption means that 1 byte is composed of 8 bits, which seems to be satisfied in almost all computer environments, although ANSI-C allows that 1 byte is greater than or equal to 8 bits.


マクロ名(Macro name):
     MINIMUM_SHORT_BYTE

(Value):
     2

C言語規格(ANSI-C)において許容されるshort型変数の最小バイト数。 但しCHAR_BITがC言語規格(ANSI-C)で許容される最小値を取ることを前提とする (この前提は1バイト=8ビットであるという意味であり、 ANSI-Cでは1バイトは8ビット以上であれば良いが ほぼ全てのマシン環境で1バイト=8ビットになっていると思われる)。
The minimum allowed number of bytes of short-type variables in the C language standard (ANSI-C), given that CHAR_BIT takes the minimum allowed number in the standard; this assumption means that 1 byte is composed of 8 bits, which seems to be satisfied in almost all computer environments, although ANSI-C allows that 1 byte is greater than or equal to 8 bits.


マクロ名(Macro name):
     inputParameterValue_s(name)

(Value):
    if(strcmp(parameterName,#name)==0){
        strcpy(name,parameterValue);
        flag.name##_specified=1;
        continue;
    }

パラメータ名とパラメータ値の組の形式で指定されたパラメータを 文字列変数(char型配列)に格納する処理を簡潔に書くための関数形式マクロ。
A function-type macro to realize a brief code to preserve a parameter, specified in a form of a combination of parameter name and value, into a string variable (i.e., a char-type array).

データ解析においては様々にパラメータを変えて計算を繰り返す場合が多い。 ymaeda_opentoolsのプログラムでは パラメータはコマンドライン引数や設定ファイルで与える。 設定ミスを起きにくくするため、 パラメータ値単独ではなくパラメータ名とパラメータ値の組で指定する方式にしている。 その結果、パラメータ名とパラメータ値の組を読み込んで処理する必要が出てくる。
In data analyses, computations are usually repeated with various sets of parameters. In the programs of ymaeda_opentools, the parameters are specified either by command-line arguments or configuration files. To avoid human errors in the parameter settings, each parameter is specified as a pair of the parameter name and value, instead of the parameter value alone. As a result, the programs need to read and process the pair of parameter name and value.

また、ymaeda_opentoolsのプログラムでは パラメータの登場順を自由としている。 その結果、パラメータはどのような順番で登場するか事前に分からず、 各パラメータが指定されたか否かを情報として保存する必要がある。 このような仕様を前提として パラメータの読み込み処理のコードを出来る限り簡潔に書けるように 考案したのがこのマクロである。
In addition, the order of the parameters is arbitrary in the programs of ymaeda_opentools. As a result, the order of the parameters is not known in advance, and it is needed to keep information on whether each parameter was specified. This macro supports writing a code as briefly as possible to read the parameters specified in that way.

このマクロの使い方は以下の通りである。
The usage of this macro is as follows.

  1. プログラム内で
    を宣言する。
    Declare the following variables:
    • A variable for a string (a char-type array of fixed size) with the same name as the parameter name;
    • A structure with a name flag, that has an integer member with a name “parameter name_specified”;
    • A variable for a string (char-type arrays of fixed size) with the name parameterName; and
    • A variable for a string (char-type arrays of fixed size) with the name parameterValue.
  2. flagのメンバ「パラメータ名_specified」の値を0に初期化する。
    Initialize the member “parameter name_specified”; of flag to 0.
  3. コマンドライン引数や設定ファイルから パラメータ名を変数parameterNameに、 パラメータ値を変数parameterValueに読み込む。
    From command-line arguments or configuration files, read the name and value of each parameter to the variables parameterName and parameterValue, respectively.
  4. その後に
        inputParameterValue_s(パラメータ名);
    と書く。これにより、パラメータ名と同じ名前の変数に値がコピーされ、 flagのメンバ「パラメータ名_specified」の値が1に変化する。
    After that, write
        inputParameterValue_s(parameter name);
    by which the parameter value is copied to the variable that has the same name as the parameter name, and the member “parameter name_specified” of flag changes to 1.

flagのメンバ「パラメータ名_specified」は そのパラメータの値がコマンドライン引数で指定されたか否かを示すもので、 指定された場合に1、指定されない場合に0となる。 後でこの情報を様々な分岐処理に利用できる。 特に「パラメータ名が指定されない場合にエラー終了」という処理は マクロcheckParameterSpecifiedFlagを用いて簡単に実行できる。
The member “parameter name_specified” of flag indicates whether the value of that parameter was specified by command-line arguments or not; 1 if specified, 0 otherwise. This information would be useful in various branch operations later. Especially, an operation of “finish the program as an error if the parameter was not specified” can easily be implemented by macro checkParameterSpecifiedFlag.

このマクロを用いたサンプルコードを以下に示す。
A sample code using this macro is shown below.

#include <inc.h>

struct TF_flag
{
    int parameter1_specified;
    int parameter2_specified;
    int parameter3_specified;
};

int main(int ARGC,char ∗ARGV[])
{
    char parameter1[strsize];
    char parameter2[strsize];
    char parameter3[strsize];
    struct TF_flag flag;
    char parameterName[strsize];
    char parameterValue[strsize];
    int n;

    flag.parameter1_specified=0;
    flag.parameter2_specified=0;
    flag.parameter3_specified=0;

    for(n=1;n<ARGC;n++){
         if(ARGV[n][0]==′-′ && ARGV[n][1]==′-′){
             decomposeString(&(ARGV[n][2]),′=′,parameterName,parameterValue);
             inputParameterValue_s(parameter1);
             inputParameterValue_s(parameter2);
             inputParameterValue_s(parameter3);
        }
    }

    …
}

このサンプルコードではparameter1, parameter2, parameter3という 3つのパラメータがあり、 それらの値を「--パラメータ名=パラメータ値」の形式の コマンドライン引数で指定する。紫色の部分がこのマクロである。本来ならば
if(strcmp(parameterName,"parameter1")==0){
    strcpy(parameter1,parameterValue);
    flag.parameter1_specified=1;
    continue;
}

if(strcmp(parameterName,"parameter2")==0){
    strcpy(parameter2,parameterValue);
    flag.parameter2_specified=1;
    continue;
}

if(strcmp(parameterName,"parameter3")==0){
    strcpy(parameter3,parameterValue);
    flag.parameter3_specified=1;
    continue;
}
と書かなければならなかったところ、マクロを用いることで3行で済んでいる。
The sample code above has three parameters parameter1, parameter2, and parameter3, which are specified by command-line arguments of a format “--parameter name=parameter value”. Purple represents this macro. Without the macro, the code had to be the second sample of 15 purple lines above, which was simplified to the three purple lines with the use of the macro.


マクロ名(Macro name):
     inputParameterValue_d(name)

(Value):
    if(strcmp(parameterName,#name)==0){
        sRoute;
        name=CKatof(parameterValue);
        rRoute;
        flag.name##_specified=1;
        continue;
    }

パラメータ名とパラメータ値の組の形式で指定されたパラメータを 実数値(double型)変数に格納する処理を簡潔に書くための関数形式マクロ。
A function-type macro to realize a brief code to preserve a parameter, specified in a form of a combination of parameter name and value, into a real number (double-type) variable.

実数値を取るパラメータ用である点を除いて マクロinputParameterValue_sと同じである。 パラメータの格納先の変数はdouble型を用いる。 すなわち、マクロinputParameterValue_sの説明中のサンプルコードにおいて
char parameter1[strsize];
としていた部分を
double parameter1;
とする必要がある。 なお変数parameterValueの方は文字列(固定長のchar型配列)とする。 すなわちパラメータ値は一旦文字列として変数parameterValueに読み込んだ上で マクロ内で数値に変換する。
Same as the macro inputParameterValue_s except that this macro is for parameters that take a real number. Use double-type for the variable to preserve the parameter. This means that
char parameter1[strsize];
in the sample code of the description of macro inputParameterValue_s needs to be replaced by
double parameter1;
while the variable parameterValue should be a string (a char-type array of fixed size) even in this case; the value of the parameter is first read into the variable parameterValue as a string and then converted to a numerical value in the macro.


マクロ名(Macro name):
     inputParameterValue_i(name)

(Value):
    if(strcmp(parameterName,#name)==0){
        sRoute;
        name=CKatoi(parameterValue);
        rRoute;
        flag.name##_specified=1;
        continue;
    }

パラメータ名とパラメータ値の組の形式で指定されたパラメータを 整数値(int型)変数に格納する処理を簡潔に書くための関数形式マクロ。
A function-type macro to realize a brief code to preserve a parameter, specified in a form of a combination of parameter name and value, into an integer (int-type) variable.

整数値を取るパラメータ用である点を除いて マクロinputParameterValue_sと同じである。 パラメータの格納先の変数はint型を用いる。 すなわち、マクロinputParameterValue_sの説明中のサンプルコードにおいて
char parameter1[strsize];
としていた部分を
int parameter1;
とする必要がある。 なお変数parameterValueの方は文字列(固定長のchar型配列)とする。 すなわちパラメータ値は一旦文字列として変数parameterValueに読み込んだ上で マクロ内で数値に変換する。
Same as the macro inputParameterValue_s except that this macro is for parameters that take an integer. Use int-type for the variable to preserve the parameter. This means that
char parameter1[strsize];
in the sample code of the description of macro inputParameterValue_s needs to be replaced by
int parameter1;
while the variable parameterValue should be a string (a char-type array of fixed size) even in this case; the value of the parameter is first read into the variable parameterValue as a string and then converted to a numerical value in the macro.


マクロ名(Macro name):
     checkParameterSpecifiedFlag(name)

(Value):
    if(flag.name##specified==0){
         pRoute;
         fprintf(stderr,"エラー : パラメータ\"%s\" は省略できません。\n",#name);
         exit(1);
    }
    if(flag.name##specified==0){
         pRoute;
         fprintf(stderr,"ERROR : Parameter \"%s\" cannot be omitted.\n",#name);
         exit(1);
    }

省略不可のパラメータが指定されたかをチェックして 未指定の場合にエラー終了するコードを 簡潔に書くためのマクロ。
A macro to briefly write a code to check if an unomittable parameter was specified and to finish the program as an error if the parameter was not specified.

このマクロは マクロinputParameterValue_s, inputParameterValue_d, inputParameterValue_i とセットで用いることを前提とする。 マクロinputParameterValue_sの説明に書いたように、 「パラメータ名_specified」の名前の整数メンバを持つflagという名前の構造体を宣言し、 そのメンバの値を0に初期化しておく。 マクロinputParameterValue_s, inputParameterValue_d, inputParameterValue_i を用いてパラメータを読み込むと flagのメンバ「パラメータ名_specified」の値が1に変化する。 すなわちパラメータ一式の読み込み後、flagのメンバ「パラメータ名_specified」は パラメータが未指定ならば0、指定済みならば1となっている。 これを前提としてパラメータの指定有無のチェックが行われる。
This macro is assumed to be used with the macros inputParameterValue_s, inputParameterValue_d, and inputParameterValue_i.
As was explained by the description of macro inputParameterValue_s, the user must declare a structure with a name flag that has an integer member with a name “parameter name_specified”, and initialize the value to 0. Then, reading the parameter by the macro inputParameterValue_s, inputParameterValue_d, or inputParameterValue_i, the value of member “parameter name_specified” of flag changes to 1. Therefore, after reading the parameters, the value of the member “parameter name_specified” of flag is 0 if the parameter was not specified, and 1 if specified. This is the assumption of this macro when checking if the parameter was specified.

このマクロを用いたサンプルコードを以下に示す。
A sample code using this macro is shown below.

#include <inc.h>

struct TF_flag
{
    int parameter1_specified;
    int parameter2_specified;
    int parameter3_specified;
};

int main(int ARGC,char ∗ARGV[])
{
    char parameter1[strsize];
    double parameter2;
    int parameter3;
    struct TF_flag flag;
    char parameterName[strsize];
    char parameterValue[strsize];
    int n;

    flag.parameter1_specified=0;
    flag.parameter2_specified=0;
    flag.parameter3_specified=0;

    for(n=1;n<ARGC;n++){
         if(ARGV[n][0]==′-′ && ARGV[n][1]==′-′){
             decomposeString(&(ARGV[n][2]),′=′,parameterName,parameterValue);
             inputParameterValue_s(parameter1);
             inputParameterValue_d(parameter2);
             inputParameterValue_i(parameter3);
        }
    }

    checkParameterSpecifiedFlag(parameter1);
    checkParameterSpecifiedFlag(parameter2);
    checkParameterSpecifiedFlag(parameter3);

    …
}