半角全角判定(文字数取得機能追加)

半角全角判定 - 永字八法の焼き直し。
※2011-01-15 書きなおし。

パートA

mov %0,100
numalias is_zen_result,%0:inc %0
numalias is_zen_target,%0:inc %0
numalias is_zen_cmp,%0:inc %0
numalias is_zen_len,%0:inc %0
numalias letter_result,%0:inc %0
numalias letter_base,%0:inc %0
numalias letter_loop,%0:inc %0
numalias letter_len,%0:inc %0
numalias cut_base,%0:inc %0
numalias cut_head,%0:inc %0
numalias cut_rest,%0:inc %0
numalias cut_len,%0:inc %0
numalias cut2_base,%0:inc %0
numalias cut2_left,%0:inc %0
numalias cut2_right,%0:inc %0
numalias cut2_temp,%0:inc %0

defsub is_zenkaku
defsub is_hankaku
defsub letter_len
defsub letter_num
defsub cut_head_letter
defsub cut_text
defsub is_ja

パートB

;==================
; is_zenkaku
;==================
; 文字列を与え、その文字列の先頭の文字が全角かどうか判定する。
; 第一引数:結果を受け取る数値変数
; 第二引数:判定対象の文字列(変数)
; 結果は、0が半角、1が全角
; 依存:なし
*is_zenkaku
getparam i%is_zen_result,$is_zen_target
mov %%is_zen_result,0
cmp %is_zen_cmp,$is_zen_target,"゚":   if %is_zen_cmp>0 mov %%is_zen_result,1:return
cmp %is_zen_cmp,$is_zen_target,"。":notif %is_zen_cmp<0 return
cmp %is_zen_cmp,$is_zen_target,"~":   if %is_zen_cmp>0 mov %%is_zen_result,1:return
return

;==================
; is_hankaku
;==================
; 文字列を与え、その文字列の先頭の文字が半角かどうか判定する。
; 第一引数:結果を受け取る数値変数
; 第二引数:判定対象の文字列(変数)
; 結果は、0が全角、1が半角
; 依存:is_zenkaku
*is_hankaku
getparam i%is_zen_result,$is_zen_target
is_zenkaku %%is_zen_result,$is_zen_target
mov %%is_zen_result,1-%%is_zen_result
return

;==================
; letter_len
;==================
; 文字列を与え、その文字列の先頭の文字が、1バイトか2バイトかを判定する。
; 第一引数:結果を受け取る数値変数
; 第二引数:判定対象の文字列(変数)
; 結果は、0が文字列無し、1が半角、2が全角
; 依存:is_zenkaku
*letter_len
getparam i%is_zen_result,$is_zen_target
mov %%is_zen_result,0
if $is_zen_target="" return
is_zenkaku %%is_zen_result,$is_zen_target
inc %%is_zen_result
return

;==================
; letter_num
;==================
; 文字列を与え、その文字列が文字数でどれだけの長さになるかを返す。
; 第一引数:結果を受け取る数値変数
; 第二引数:判定対象の文字列(変数)
; 結果は、文字数
; 依存:letter_len
*letter_num
getparam i%letter_result,$letter_base
mov %%letter_result,0 ; 初期設定
if $letter_base="" return ; 空文字列なら、0を返す。
len %letter_base,$letter_base ; バイト長さを取得
if %letter_base=1 mov %%letter_result,1:return ; 1バイト長さなら、1を返す。
mov %letter_loop,0 ; 初期設定その2
*letter_num_loop
mid $letter_loop,$letter_base,%letter_loop,1 ; 一文字を取得
letter_len %letter_len,$letter_loop ; その文字の全角半角判定
inc %%letter_result ; 一文字は一文字
add %letter_loop,%letter_len ; 文字のバイト数分ずらす。
if %letter_loop<%letter_base goto *letter_num_loop
return

;==================
; cut_head_letter
;==================
; 文字列を与えると、1バイトか2バイトかを判別して、その先頭の文字を返す。
; 第一引数:分割したい文字列
; 第二引数:先頭の文字列を受ける文字列変数
; 第三引数:先頭の文字を落とした残りを受ける文字列変数
; 依存:letter_len
; 第一引数と第三引数を同じ文字列変数を使うと便利かも。
*cut_head_letter
getparam $cut_base,s%cut_head,s%cut_rest
mov $%cut_head,"" ; 初期設定
mov $%cut_rest,"" ; 初期設定
if $cut_base="" return ; ショートカット
len %cut_base,$cut_base
if %cut_base=1 mov $%cut_head,$cut_base:return ; ショートカットその2
letter_len %cut_len,$cut_base ; 先頭の文字の長さを取得。
if %cut_len=%cut_base mov $%cut_head,$cut_base:return ; ショートカットその3
; それ以外ならば、
mid $%cut_head,$cut_base,0,%cut_len ; 先頭から1文字ないし2文字を取得
mid $%cut_rest,$cut_base,%cut_len,%cut_base-%cut_len ; 残りを格納
return

;==================
; cut_text
;==================
; 文字列と数値を与えると、その文字数で分割して返す。
; 第一引数:分割したい文字列
; 第二引数:何文字で分割するか。
; 第三引数:先頭から第二引数の文字列
; 第四引数:残りの文字列
; 依存:cut_head_letter
; 数値を140にすると、Twitterに使える。
*cut_text
getparam $cut2_base,%cut2_base,s%cut2_left,s%cut2_right
mov $%cut2_left,""
mov $%cut2_right,""
if $cut2_base="" return ; ショートカット
*cut_text_loop
cut_head_letter $cut2_base,$cut2_temp,$cut2_base ; 分割して$cut2_tempに入れる。
add $%cut2_left,$cut2_temp
if $cut2_base="" return
dec %cut2_base
if %cut2_base>0 goto *cut_text_loop
mov $%cut2_right,$cut2_base ; 残りを入れる。
return

;==================
; is_ja
;==================
; 文字列を与え、その文字列に2byte文字が含まれているかどうかを返す。
; 第一引数:結果を受け取る数値変数
; 第二引数:判定対象の文字列(変数)
; 結果は、0が全て半角、1が全角が含まれる。
; 依存:なし
*is_ja
getparam i%is_zen_result,$is_zen_target ; 結果を格納する変数,対象の文字列
mov %%is_zen_result,0 ; 結果を0で初期化
len %is_zen_len,$is_zen_target ; 対象の文字列の長さを取得
mov %is_zen_target,-1 ; 対象も文字列へのカーソル
*is_ja_loop
inc %is_zen_target ; カーソルを一つすすめる。
if %is_zen_len-2 < %is_zen_target return ; 残り文字数が2未満ならば、0で回答
mid $is_zen_len,$is_zen_target,%is_zen_target,2 ; カーソル位置から2文字を取得。
cmp %is_zen_cmp,$is_zen_len,"゚":   if %is_zen_cmp>0 mov %%is_zen_result,1:return
cmp %is_zen_cmp,$is_zen_len,"。":notif %is_zen_cmp<0 goto *is_ja_loop ; ループする。
cmp %is_zen_cmp,$is_zen_len,"~":   if %is_zen_cmp>0 mov %%is_zen_result,1:return
goto *is_ja_loop ; ループする。

何が変わったか。

なんか微妙な修正。それから、is_ja命令を追加した。
is_ja命令は、第2引数の文字列に日本語が混じっていれば1を、そうでなければ0を第一引数の変数に返す命令。

is_jaって何に使うの?

arc.nsaの中を2バイト文字のファイル名で探そうとするとバグります。その回避のため、実際に読み込む前に色々調査したり加工したりするのに必要です。忍者のように。