C99に対応した標準Cライブラリの実装レポートを行っていきます。

プロフィール 

Author:高木信尚

ホームページ
ブログ

最近の記事 

最近のコメント 

最近のトラックバック 

月別アーカイブ 

カテゴリー 

ブロとも申請フォーム 

この人とブロともになる

ホーム 全記事一覧 << 前ページ 次ページ >>

 

2008/10/07 11:48|

 

今回は多バイト文字からワイド文字に変換するためのmbtowc関数です。mbtowc関数はmblen関数とほとんど変わりません。実際、mblen関数は、

mbtowc(NULL, s, n)

と等価だからです。つまり、mbtowc関数とmblen関数の違いは、変換結果を格納するかどうかの違いでしかありません。それでは実装です。

#include <stddef.h>

int mbtowc(wchar_t *pwc, const char *s, size_t n)
{
  if (s == NULL || *s == '\0' || n == 0)
    return 0;
  if (pwc != NULL)
    *pwc = (unsigned char)*s;
  return 1;
}

現時点では、"C"ロケールにしか対応しない方針ですので、多バイト文字をそのままワイド文字に置き換えています。ここで、(unsigned char)でキャストしているのは、値を0〜UCHAR_MAXにするためです。すなわち、0x80〜0xffの範囲の値に対する対策です。
2006/06/14 15:37|一般ユーティリティTB:0CM:3

 

mblen関数は、多バイト文字を構成するバイト数を求めるための関数です。ただし、現在のところ、扱っているのが"C"ロケールだけですので、有効な多バイト文字のバイト数は常に1になります。

この関数の基本的な機能は単純なのですが、付随する機能がいろいろとあります。

まず、引数に空ポインタを渡した場合の動作ですが、多バイト文字がシフトシーケンスに依存する場合は非0を、そうでなければ0を返します。今回の実装では、シフトシーケンスに依存するエンコーディングは使用しませんので、この場合は0を返すことになります。

次に、先頭の1バイトが'\0'の場合にも0を返します。他には、サイズとして0を渡した場合にも0を返すことになります。それでは実装です。

#include <stddef.h>

int mblen(const char *s, size_t n)
{
  if (s == NULL || *s == '\0' || n == 0)
    return 0;
  return 1;
}

*sの値をもう少し詳しく見て、有効な文字かどうかを判別してもよいのでしょうが、とりあえずナル文字以外は何でもOKという仕様にしておきます。
2006/06/13 00:16|一般ユーティリティTB:0CM:0

 

前回は擬似乱数の種を設定するsrand関数でしたので、今回は実際に擬似乱数を発生させるrand関数について書くことにします。

実際の関数の実装に先立って、擬似乱数として返す値の最大値を表す RAND_MAX マクロを定義する必要があります。このマクロの値は、ほとんどの処理系で32767ですので、今回の実装もそれにあわせることにします。

#define RAND_MAX 32767

次に、実際の関数の実装に入ります。rand関数は、srand関数のときに現れた静的変数 next を共有しますので、srand関数と同じ翻訳単位で定義する必要があります。あとは、擬似乱数の計算処理、より正確には next の更新処理の部分の排他制御が必要なのが特徴です。

int rand(void)
{
  int loc = vsns_ini() || sns_loc();
  if (!loc)
    loc_cpu();

  next = next * 1103515245 + 12345;
  int result = (unsigned int)(next / 65536) % (RAND_MAX+1);

  if (!loc)
    unl_cpu();
  return result;
}

擬似乱数の生成に使用する計算式は、標準規格の例と同じ単純なものです。擬似乱数の性能自体は対して高くありませんが、rand関数の用途の多くは、ちょっとした乱数が欲しいときに使うといったものでしょうから、これで十分です。

数値シミュレーションのようなものをH8で行うことがあるのかどうかは不明ですが、より高性能な擬似乱数が必要な場合は、アプリケーション側でM系乱数などのアルゴリズムを用いて、別途関数を作成することになると思います。
2006/06/12 13:32|一般ユーティリティTB:0CM:0

 

srand関数は、乱数の種を設定するための関数です。この関数で、適切に種を設定しないと、rand関数は常に同じ数列を返すことになります。

ところで、乱数の種としてsrand関数に渡す値には、time関数の返却値を使うことが多いようですが、今回の実装では、time関数はデフォルトでは (time_t)-1 を返すことになりそうですので、あらかじめお断りしておきます。

それでは実装です(2006/06/08 若干間違いがあったので修正しました)。

#include <kernel.h>

static unsigned long next = 1UL;

void srand(unsigned int seed)
{
#ifdef __H8300__
  int loc = vsns_ini() || sns_loc();
  if (!loc)
    loc_cpu();
#endif
  next = seed;
#ifdef __H8300__
  if (!loc)
    unl_cpu();
#endif
}

H8/300の場合、unsigned long型のオブジェクトへの代入はアトミックオペレーションにならないため、loc_cpuで排他制御を行っています。もっとも、現状のTOPPERS/JSPカーネルは、H8/300に対応していないので、このような措置は不要かもしれませんが、とりあえずこうしておきます。

2006/06/05 22:12|一般ユーティリティTB:0CM:0

 

多くの処理系では、system関数を使うと子プロセスを呼び出すことができるので、system関数は子プロセスを呼び出すための関数だと勘違いされている方も多いようです。実際には、system関数はコマンドプロセッサを呼び出すためのものです。

コマンドプロセッサというのは、普通はシェルと呼ばれることが多いと思います。Unixではshですし、Windowsではcommand.comやcmd.exeがこれに当たります。今回の実行環境では、コマンドプロセッサに相当するものは存在しません。

system関数の引数にNULLを渡すと、コマンドプロセッサを利用できるかどうかを調べることができます。非0が返ると使用可、0が返ると使用不可です。そして、引数にNULL以外を渡すと、処理系定義の値が返ってきます。多くの場合、ここで子プロセスの終了コードが返ってくるわけです。

今回の実装では、面倒なので、system関数は常に0を返すことにしてもよいのですが、誤使用に備えて、NULLを渡したときには0を、NULL以外を渡したときはEXIT_FAILUREを返すようにします。

#include <stdlib.h>

int system(const char *s)
{
  return s == NULL ? 0 : EXIT_FAILURE;
}

この関数も、規格の要求を満たすためだけのものですが、コマンドプロセッサを自作する場合には、実際にそれを呼び出すようにしてもよいでしょう。
2006/06/02 10:55|一般ユーティリティTB:0CM:0

ホーム 全記事一覧 << 前ページ 次ページ >>

ブログ内検索 

お勧め書籍 

RSSフィード 

リンク 

このブログをリンクに追加する

Powered By FC2ブログ 

Powered By FC2ブログ
ブログやるならFC2ブログ

Copyright(C) 2006 TAKAGI Nobuhisa All rights reserved.
Powered by FC2ブログ. 無料ホームページ アフィリエイト レンタルサーバー FC2ブログ 一戸建て template designed by 遥かなるわらしべ長者への挑戦.