/** 
 * @file sample.c
 * 
 * @brief コーディングスタイルのサンプルコード（ソースファイル版）
 *
 * 見ためを統一するためのコーディングスタイルのルールと見本。
 * また信頼性や保守性のために守るべき幾つかのコーディングルールと見本。
 * ここに載せているのは実装者によってマチマチだと思われる項目の統一が目的。
 * 上級者の多くが守っていると思われる項目は別途資料を参照。
 * ヘッダーファイルの見本もあるので参照のこと。
 *
 * @author Lily <bt@k5-n.com>
 *
 * @date $Id$
 *
 * <!-- Copyright(C) 2006 Lily -->
 */

/*
 * ### 守るべきルール（実装者によって違う物を統一する） ###
 *
 * ■ 見た目の統一
 * 関数の波括弧は改行して行の先頭に
 * if, while, for, switch等の制御文の波括弧は改行無しでその行に記述し前に空白
 * if, while, for, switch等の制御式を囲う左括弧の前に空白を入れる
 * 関数の左括弧の前には空白を入れない
 * 演算子の前後は空白を入れる。ただし次の演算子を除く [] -> .（ピリオド） ,（コンマ）
 * ,（コンマ）の後は空白を入れる。ただしマクロ引数のコンマは除く
 * 字下げは１タブで４。スペースに展開しない
 *
 * ■ コメント
 * コメントはC言語スタイルでC++スタイルは使わない
 * 長文コメントは今まさにここと同じようにする
 * 関数の前にDoxygenスタイルの関数説明を入れる
 * ファイルの先頭にDoxygenスタイルのファイル説明を入れる
 *
 * ■ 信頼性のためのルール
 * １ビット幅のビットフィールドにはunsigned int型を使用
 * １ビット幅でないビットフィールドにはsigned intかunsigned int型を使用
 *
 * ■ コードの保守性（見やすさ）のためのルール
 * 真偽値でない値の０でないかどうかの比較では、!= 0を省略しない
 * 関数宣言の引数名は省略せず、関数定義と同様とする
 * ソース記述順序はinclude, define, 型宣言, グローバル変数, 関数宣言とする
 * #elseや#endifにはコメントを入れ，対応関係を明確にする。
 * if文の後が１行でも波括弧はつける
 * 継続行では演算子を行の最後に書く
 * ソースコードを無効にするときは #if 0 を使い、無効にした理由を記述
 * ヘッダファイルは重複取り込みに対応させる（記述方法はヘッダファイルサンプル参照）
 *
 * ■ 移植性のためのルール
 * プログラムはC90の規格に一致させる
 * 未定義や未規定の動作に依存した書き方をしない
 * 符号指定のないchar型は文字にだけしか使用しない
 * ビット位置が意識されたデータに対してはビットフィールドは使用しない
 *
 * ■ 命名規則
 * 下線で始まる名前は利用しない
 * 基本的に#defineされる定数名やマクロは全て大文字にする
 * ただしセッターやゲッターなど、グローバル変数をラップするためのマクロは小文字
 * その際の命名規則は外部公開関数の命名規則に従う
 * enumで定義する定数は全て大文字にする
 * 大文字と小文字の差しかない２つの名前は使用しない
 * 外部に公開するグローバル変数にはg_[モジュール名]_というプリフィクスを付ける
 * 外部に公開する関数にはモジュール名のプリフィックスをつける
 * staticなグローバル変数は、後ろに_（アンダーバー）を付ける
 * 外部に公開する関数や変数にはわかりやすい名前をつける
 * マクロとenum定数以外では小文字を使用し、名前の中で語をわけるのには下線を使う
 * 関数名は能動的な動詞を基本とし、必要ならその後に名詞をつける
 */

/* ルール説明のコメントには###を先頭につけてある */

#include "sample.h"

/* ###defineされる定数名やマクロは全て大文字にする */
#define BASE_NUM	(0)
#define MAX(a,b)	((a)>(b)?(a):(b))

/* ###enumで定義する定数は全て大文字にする */
enum color {
	RED, GREEN, BLUE
};

/* ###１ビット幅のビットフィールドにはunsigned int型を使用 */
/* ###１ビット幅でないビットフィールドにはsigned intかunsigned int型を使用 */
/* ###ビット位置が意識されたデータに対してはビットフィールドは使用しない */
struct control {
	unsigned int init:1;
	unsigned int err:1;
	signed int errno:6;		/* 符号つきなのでsigned int */
};
 
/* ###外部に公開するグローバル変数にはg_[モジュール名]_というプリフィクスを付ける */
/*
 * ###外部に公開する関数や変数にはわかりやすい名前をつける。
 * （出来る限り単語を省略しないこと）
 */
/* ###マクロとenum定数以外では小文字を使用し、名前の中で語をわけるのには下線を使う */
unsigned short g_sample_initialized_value;

/* ###staticなグローバル変数は、後ろに_（アンダーバー）を付ける */
/* ###符号指定のないchar型は文字にだけしか使用しない */
static signed char errno_;

/* ###関数の左括弧の前には空白を入れない */
static int init(void);

/* ###外部に公開する関数にはモジュール名のプリフィクスを付ける */
/* ###関数名は能動的な動詞を基本とし、必要ならその後に名詞をつける */
/** 
 * @brief ###関数の説明を書く
 * 
 * @param arg1 ###引数の説明を書く
 * @param arg2 ###引数の説明を書く
 * 
 * @return ###戻り値の説明を書く
 */
int sample_execute(int arg1, int arg2)	/* ###コンマの後に空白を入れる */
{	/* ###関数の波括弧は改行して行の先頭に */
	int a, b, c;

	init();
	a = c = BASE_NUM;

	/* ###制御文の波括弧はその行で前に空白。左括弧の前に空白。 */
	/* ###else ifがある場合は必ずelseを書き、何もしないならDO NOTHINGと書く */
	/* ### 真偽値でない値の０でないかどうかの比較では、!= 0を省略しない */
	if (arg1 != 0) {
		/* ###演算子の前後に空白 */
		a = arg1 + arg2;	/* ###行末コメントはタブで離して書く */
		c = arg1 * arg2;	/* ###行末コメントが続く場合は字下げを揃える */
		/*
		 * ###長文コメントはこのようなスタイルで、
		 * 複数行に渡って記述することができる。
		 * コメントの字下げ位置を所属するブロックに合わせる。
		 */
	} else if (arg2 != 0) {
		a = 0;
		c = 0;
	} else {
		/* DO NOTHING */
	}

	/* ###if文の後が１行でも波括弧はつける */
	if (arg1 == arg2) {
		a = 0;
	}

	/* ###継続行では演算子を行の最後に書く */
	b = arg1 * arg2 + arg1 * arg1 + arg2 * arg2 +
		a * arg1 + a * arg2;

	/* ###継続行では演算子を行の最後に書く */
	if (arg1 == 0 && b = 0 &&
			arg2 == 0) {
		a = 0;
	}

	/* ###switchではbreakがないときはFALL THROUGHと書いて明示する */
	/* ###switchでは必ずdefaultを書き、何もしないならDO NOTHINGと書く */
	switch (a) {
	case 0:
		c += b;
		break;
	case 1:
		b += a;
		/* FALL THROUGH */
	case 2:
		c += MAX(a, b);
		break;
	default:
		/* DO NOTHING */
		break;
	}

#if 0	/* デバッグのため一時的に無効化 */
	/* ###ソースコードを無効にするときは #if 0 を使い、無効にした理由を記述 */
	if (c == 0) {
		c = 1;
	}
#endif	/* 0 */

	return (a + b + c);
}

