#include "defines.h"
#include "amacro.h"
#include "vsiki.h"

unchar *NumVarRead(unchar *str,long *num,int *md,long *p,int *status,VARSYS *gvar,VARSYS *lvar)
/* 数字・変数読み取り（ローカル変数対応）*/
/* NumVarReadはコマンドラインで使われることを想定しないため、１文字コードは'〜'固定である */
{
int ret,base=10,minus=0; /* デフォルトは１０進数 */
unsint c;
unchar *str0,*vname; /* 変数名格納エリア */
	vname=alloca(gvar->vlmax+1); /* +1 for EOS */
	if (vname==NULL) {
		*status=VARNMEM; /* スタックが足りない */
		return(NULL);
	}
	*p=0; /* 変数以外は０となる */
	if (md!=NULL) *md=0; /* 数値の場合は０となる */
	str0=str;
	*status=VOK;
	if (*str=='-') { /* 符号がある時 */
		minus=1;
		str++; /* 次の文字が数値１文字目になる */
	}
	switch (*str) { /* １文字目で判断 */
		case '\'': /* １文字（２バイトコード対応）*/
			str++; /* 'を飛ばす */
			c=*str++;
			if (check_kanji1(c)) c=(c<<8)|*str++;
			/* 'で括る必要がある */
			if (*str++!='\'') { /* 括られていない */
				*status=VSCHERR;
				return(NULL);
			}
			*num=(long)c;
			return(str);
		case '%': /* ２進数 */
			base=2;
			break;
		case '@': /* ８進数 */
			base=8;
			break;
		case '$': /* １６進数 */
			base=16;
			break;
	}
	/* 数字か変数 */
	if (base==10) {	/* 変数となるのは前に数値識別子(%,@,$)がないときのみ */
	    c=*str;
	    if (c<'0'||c>'9') { /* 最初の文字が数字でない時：変数の可能性有り */
		if (!(isalnum(c) || iskana(c) || c=='_' || check_kanji1(c))) {
			*status=VARILL; /* 変数名が異常 */
			return(NULL);
		}
		/* 変数名読みだし */
		str=read_var_name(str,vname,gvar->vlmax);
		if (str==NULL) {
			*status=VARLONG; /* 変数名長すぎ */
			return(NULL);
		}
		/* その変数がすでにあるかどうかチェック */
		ret=var_read2(vname,num,md,p,gvar,lvar);
		if (ret==VARNDEF) { /* ない -> 定義... */
			if (gvar->mode&BIT15) { /* 要別定義モード */
				*status=ret;
				return(NULL);
			}
			/* 未定義変数は数値未確定定義する */
			/* vsikiだけでは再代入不可変数は作れない */
				*p=var_define(vname,VKAKU
					,(lvar==NULL||lvar->vwork==NULL
						||lvar==gvar)? gvar:lvar);
			if (*p<0) {
				switch (*p) {
					case -1: *status=VAROVER; break;
					case -2: *status=VARDBL;  break;
				}
				return(NULL);
			}
			*p=-*p;
			goto SNR1;
		} /* 確定済み変数の時はその内容数値 */
		if (ret!=0) { // エラー
			*status=ret;
			return(NULL);
		}
		goto SNR1;
	    } /* 最初の１文字が数字の時は数字とみなす */
	} else {str++; str0++;}/* 進数記号をはずす */
	/* base進数の文字列を数値に直す：base=2〜10,16 */
	atoi3b(str,num,base,0,&str);
    SNR1:;
	if (str==str0) {
		*status=VSNONE; /* 数字が１文字もない時はエラー */
		return(NULL);
	}
	if (minus) *num=-(*num); /* 正常時のみ符号処理をする */
	return(str);
}
