グローバル関数 ローカル関数 構造体、共用体、列挙体
mssCalCompile
mssCalFree
mssCalReadFuncIsFRD
mssCalReadFuncIsFRK
mssCalReadFuncIsFldRec
mssCalShowTree
mssCalculate
argHaveNull
cal_Exp
cal_Sqrt
cal_abs
cal_addOperator
cal_age
cal_andOperator
cal_calculate_sub
cal_cat
cal_chkCal
cal_chkProcType
cal_chkUsedPrvFldRsl
cal_datefmt
cal_day
cal_dayadd
cal_divOperator
cal_down
cal_dt2jd
cal_eqNOperator
cal_eqSOperator
cal_evalFldsConst
cal_fix
cal_fixdec
cal_fldCnt
cal_freeStrMalAdd
cal_geNOperator
cal_geSOperator
cal_gtNOperator
cal_gtSOperator
cal_if
cal_isFunc
cal_isOpe
cal_jd2date
cal_jd2time
cal_keyCnt
cal_keyLine
cal_keyNo
cal_leNOperator
cal_leSOperator
cal_leapyear
cal_left
cal_length
cal_line
cal_lineCmp
cal_ln
cal_log
cal_log10
cal_log2
cal_ltNOperator
cal_ltSOperator
cal_max
cal_min
cal_modOperator
cal_mulOperator
cal_neNOperator
cal_neSOperator
cal_not
cal_now
cal_nrand
cal_orOperator
cal_pi
cal_power
cal_prvField
cal_prvResult
cal_rand
cal_regOperator
cal_regexEnd
cal_regexLen
cal_regexStart
cal_right
cal_round
cal_sepCal
cal_sepOpeTok
cal_setFuncAdd
cal_setOpeTok
cal_subOperator
cal_substr
cal_sum
cal_time
cal_timeadd
cal_timefmt
cal_today
cal_topField
cal_topResult
cal_up
day365
dayweek
funcArgType
getLowPriOpe
initCalFunc
jd2ut
removePar
setStrMalAdd
ut2jd
validDate
validTime
struct OpeTbl
0001: /**
0002: * # CHAPTER #
0003: * ============================================================================
0004: * xtcal等で利用される計算式に関する関数
0005: * ============================================================================
0006: * 【扱うデータ型】
0007: * 内部的には数値型(double型)と文字列型(char *)のみを扱う。
0008: *
0009: * 【型変換】
0010: * 原則的に、各演算子および関数には引数と返値にデフォルトの型が定められている。
0011: * 定数や項目値については、各関数の指定するデフォルトの型に変換される。
0012: *
0013: * 次に、関数の引数の型と、その引数で関数が指定されていたときの、その戻り値に
0014: * 型の不一致が起こった場合を考える。例えば"length(sqrt($a))"を例にすると、
0015: * length関数は、デフォルトで引数として文字列型をとり、sqrt関数は数値を返す。
0016: * この時、sqrt関数の計算結果を文字列型に変換し、length関数に渡す。
0017: * 文字列->数値変換はatof関数を用いている。
0018: * この型変換は、原則的にcal_calculate関数にてコマンド実行時に行われる。
0019: * ただし例外として、関数の引数として未定型を定義できる。
0020: * 例えば、if関数を考える。ifは第一引数の条件式が真ならば第二引数、偽ならば
0021: * 第三引数を返す。この時、第二引数と第三引数の型は、ユーザの指定に依存する。
0022: * 例えば、"if($a>1,sqrt($a),today()"の計算式を考えると、第二引数のsqrtは
0023: * 数値を返し、第三引数のtoday関数は文字列を返す。
0024: * このようなケースでは、関数のデフォルトの型を未定義型にしておく。
0025: * 未定義型とその他の固定された型との違いは、未定義型の場合はcal_calculate関数
0026: * にて型変換を行わないことにある。
0027: * よって、関数を実装する場合、引数の型をS,Nにすれば、その関数には、
0028: * 必ず指定の型の値が引数として渡されることが保証される。
0029: *
0030: * 【定数の与え方】
0031: * 定数は文字列であってもダブルクオーテーション(")で囲う必要はない。
0032: * ex. cat(abc,def,ghi,_) sqrt(10)
0033: *
0034: * 【項目名の指定方法】
0035: * "$項目名"のように'$'記号を先頭につける。これは定数との区別をするため。
0036: * 可変引数をとる関数(ex. sum,cat)については、ワイルドカードを用いることが可能。
0037: * 例えば、"sum($数量[ab])"と指定すると、"sum($数量a,$数量b)"と指定したと
0038: * 等しくなる。但し、内部的には、"sum($数量[ab])"と"sum($数量a,$数量b)"の
0039: * mssCal構造体での格納方法は異なる。前者はcal->arg[0]->fldsに二つの項目がセット
0040: * され、後者は、cal->arg[0]->fldsに"$数量a"が、cal-arg[1]->fldsに"$数量b"が
0041: * それぞれセットされる。
0042: * また万能マッチの'*'の利用は注意が必要である。もし、"sum($数量*)"と指定した
0043: * 場合、'*'記号を乗算演算子として解釈すべきか、ワイルドカードとして解釈すべき
0044: * か、判断がつかない。現在のところ乗算演算子として解釈してしまう。
0045: * そこで'*'のワイルドカードを利用する時は、sum($(数量*))のように、
0046: * 項目名識別括弧を利用する。
0047: *
0048: * 【各関数で確保した文字列領域の開放】
0049: * 各ユーザ定義関数で確保された文字列領域は、setStrMalAdd(char *)関数を用いて、
0050: * そのアドレスを登録しておく。そのアドレスは、cal_calculate関数を実行するたび
0051: * に開放される。
0052: *
0053: * 【日付について】
0054: * 日付は8桁の文字列(yyyymmdd)で与える。
0055: * グレゴリオ歴の初日(1582年10月15日)より有効。
0056: *
0057: */
0058:
0059: #include <mssCal.h>
0060: #include <mssConfig.h>
0061: #include <mssBase.h>
0062: #include <mssValue.h>
0063:
0064: #include <stdio.h>
0065: #include <stdlib.h>
0066: #include <string.h>
0067: #include <ctype.h>
0068: #include <sys/types.h>
0069: #include <sys/time.h>
0070: #include <regex.h>
0071: #include <math.h>
0072: #include <float.h>
0073: #include <errno.h>
0074:
0075: /* 内部の関数が用いるデータタイプ*/
0076: #define N 1 /*数値型*/
0077: #define S 2 /*文字列型*/
0078: #define M 64 /*可変引数*/
0079: #define X 128 /*未定義型*/
0080: #define E 256 /*終端*/
0081:
0082: /* 構造体calのタイプ*/
0083: #define NODE 0
0084: #define LEAF 1
0085: #define CONST 2
0086: #define FIELD 3
0087:
0088: /**
0089: * # STRUCT #
0090: * 優先順位の高い関数、演算子を見つけるための構造体
0091: */
0092: struct OpeTbl {
0093: char *add; /*アドレス*/
0094: int num; /*出現順序*/
0095: int pri; /*演算子優先順位*/
0096: struct Func *func;
0097: };
0098:
0099: struct OpeLst {
0100: struct OpeTbl *tbl;
0101: int cnt;
0102: };
0103:
0104: extern struct mssGlobalVariables mssGV;
0105:
0106: static int UsedTopResult=0;
0107: static int UsedPrvResult=0;
0108: static int UsedTopField=0;
0109: static int UsedPrvField=0;
0110: static struct mssFldRec *Fr=NULL;
0111: static struct mssFldRecDbl *Frd=NULL;
0112: static struct mssFldRecKey *Frk=NULL;
0113:
0114: static struct PrvRslStruct {
0115: MssValue val;
0116: char buf[MssRecordMaxLen];
0117: } PrvRsl,TopRsl;
0118:
0119: static struct PrvFldStruct {
0120: char *pnt[MssFieldMaxCnt];
0121: char buf[MssRecordMaxLen];
0122: } PrvFld,TopFld;
0123:
0124:
0125: /* 文字列操作処理をおこなう演算子や関数で確保されたメモリ領域を後でfreeするために記憶させる領域 */
0126: char *strMalAdd[256]; /*実際の各関数でstr処理をしてmallocした*/
0127: /*アドレス一覧*/
0128: int strMalCnt; /*その件数*/
0129:
0130: /**
0131: * # FUNCTION #
0132: * 文字列操作処理で確保されたメモリ領域をクリア
0133: */
0134: static void cal_freeStrMalAdd(void)
0135: {
0136: int i;
0137: for(i=0; i<strMalCnt; i++){
0138: mssFree(strMalAdd[i]);
0139: }
0140: strMalCnt=0;
0141: }
0142:
0143: /**
0144: * # FUNCTION #
0145: * 文字列操作処理で確保されたメモリ領域を登録
0146: */
0147: static void setStrMalAdd(char *str)
0148: {
0149: if(strMalCnt==100){
0150: mssShowErrMsg("too many string operation");
0151: mssEnd(mssErrorNoDefault);
0152: }
0153: strMalAdd[strMalCnt++]=str;
0154: }
0155:
0156: /**
0157: * # SECTION #
0158: * ----------------------------------------------------------------------------
0159: * 演算子および関数の定義
0160: * ----------------------------------------------------------------------------
0161: * 各演算子や関数での引数の型の扱いに関するルール
0162: * 1. 関数が扱う型はMssValue型で、内部的には"double"(数値と論理値)と
0163: * "char *"(文字列)のみで処理する。
0164: * 2. 引数の型に合わないMssValueが引数に渡された時、各関数の実行時に型変換される。
0165: */
0166:
0167: /**
0168: * # FUNCTION #
0169: * +(加算)演算子
0170: * 与え方: 数値1 + 数値2
0171: * 返値: 上記式演算結果
0172: */
0173: static MssValue cal_addOperator(struct mssCal *cal)
0174: {
0175: return(mssVadd(cal->arg[0].val[0],cal->arg[1].val[0]));
0176: }
0177:
0178: /**
0179: * # FUNCTION #
0180: * -(減算)演算子
0181: * 与え方: 数値1 - 数値2
0182: * 返値: 上記式演算結果
0183: */
0184: static MssValue cal_subOperator(struct mssCal *cal)
0185: {
0186: return(mssVsub(cal->arg[0].val[0],cal->arg[1].val[0]));
0187: }
0188:
0189: /**
0190: * # FUNCTION #
0191: * *(乗算)演算子
0192: * 与え方: 数値1 * 数値2
0193: * 返値: 上記式演算結果
0194: */
0195: static MssValue cal_mulOperator(struct mssCal *cal)
0196: {
0197: return(mssVmul(cal->arg[0].val[0],cal->arg[1].val[0]));
0198: }
0199:
0200: /**
0201: * # FUNCTION #
0202: * /(除算)演算子
0203: * 与え方: 数値1 / 数値2
0204: * 返値: 上記式演算結果
0205: */
0206: static MssValue cal_divOperator(struct mssCal *cal)
0207: {
0208: return(mssVdiv(cal->arg[0].val[0],cal->arg[1].val[0]));
0209: }
0210:
0211: /**
0212: * # FUNCTION #
0213: * %(剰余)演算子
0214: * 与え方: 数値1 % 数値2
0215: * 返値: 上記式演算結果
0216: */
0217: static MssValue cal_modOperator(struct mssCal *cal)
0218: {
0219: return(mssVmod(cal->arg[0].val[0],cal->arg[1].val[0]));
0220: }
0221:
0222: /**
0223: * # FUNCTION #
0224: * ==(数値比較:equal)演算子
0225: * 与え方: 数値1 == 数値2
0226: * 返値: 0:条件不一致, 1:条件一致
0227: */
0228: static MssValue cal_eqNOperator(struct mssCal *cal)
0229: {
0230: int rsl;
0231: MssValue v;
0232: mssVinit(&v,DBL);
0233:
0234: rsl=mssVcmp(cal->arg[0].val[0], OPE_EQ, cal->arg[1].val[0]);
0235:
0236: if(rsl==-1) MssVnull(v);
0237: else v.v.d=(double)rsl;
0238:
0239: return(v);
0240: }
0241:
0242: /**
0243: * # FUNCTION #
0244: * <>(数値比較:not equal)演算子
0245: * 与え方: 数値1 <> 数値2
0246: * 返値: 0:条件不一致, 1:条件一致
0247: */
0248: static MssValue cal_neNOperator(struct mssCal *cal)
0249: {
0250: int rsl;
0251: MssValue v;
0252: mssVinit(&v,DBL);
0253:
0254: rsl=mssVcmp(cal->arg[0].val[0], OPE_NE, cal->arg[1].val[0]);
0255:
0256: if(rsl==-1) MssVnull(v);
0257: else v.v.d=(double)rsl;
0258:
0259: return(v);
0260: }
0261:
0262: /**
0263: * # FUNCTION #
0264: * >=(数値比較:greater or equal)演算子
0265: * 与え方: 数値1 >= 数値2
0266: * 返値: 0:条件不一致, 1:条件一致
0267: */
0268: static MssValue cal_geNOperator(struct mssCal *cal)
0269: {
0270: int rsl;
0271: MssValue v;
0272: mssVinit(&v,DBL);
0273:
0274: rsl=mssVcmp(cal->arg[0].val[0], OPE_GE, cal->arg[1].val[0]);
0275:
0276: if(rsl==-1) MssVnull(v);
0277: else v.v.d=(double)rsl;
0278:
0279: return(v);
0280: }
0281:
0282: /**
0283: * # FUNCTION #
0284: * <=(数値比較:less or equal)演算子
0285: * 与え方: 数値1 <= 数値2
0286: * 返値: 0:条件不一致, 1:条件一致
0287: */
0288: static MssValue cal_leNOperator(struct mssCal *cal)
0289: {
0290: int rsl;
0291: MssValue v;
0292: mssVinit(&v,DBL);
0293:
0294: rsl=mssVcmp(cal->arg[0].val[0], OPE_LE, cal->arg[1].val[0]);
0295:
0296: if(rsl==-1) MssVnull(v);
0297: else v.v.d=(double)rsl;
0298:
0299: return(v);
0300: }
0301:
0302: /**
0303: * # FUNCTION #
0304: * >(数値比較:greater)演算子
0305: * 与え方: 数値1 > 数値2
0306: * 返値: 0:条件不一致, 1:条件一致
0307: */
0308: static MssValue cal_gtNOperator(struct mssCal *cal)
0309: {
0310: int rsl;
0311: MssValue v;
0312: mssVinit(&v,DBL);
0313:
0314: rsl=mssVcmp(cal->arg[0].val[0], OPE_GT, cal->arg[1].val[0]);
0315:
0316: if(rsl==-1) MssVnull(v);
0317: else v.v.d=(double)rsl;
0318:
0319: return(v);
0320: }
0321:
0322: /**
0323: * # FUNCTION #
0324: * <(数値比較:less)演算子
0325: * 与え方: 数値1 < 数値2
0326: * 返値: 0:条件不一致, 1:条件一致
0327: */
0328: static MssValue cal_ltNOperator(struct mssCal *cal)
0329: {
0330: int rsl;
0331: MssValue v;
0332: mssVinit(&v,DBL);
0333:
0334: rsl=mssVcmp(cal->arg[0].val[0], OPE_LT, cal->arg[1].val[0]);
0335:
0336: if(rsl==-1) MssVnull(v);
0337: else v.v.d=(double)rsl;
0338:
0339: return(v);
0340: }
0341:
0342: /**
0343: * # FUNCTION #
0344: * ==(文字列比較:equal)演算子
0345: * 与え方: 文字列1 -eq 文字列2
0346: * 返値: 0:条件不一致, 1:条件一致
0347: */
0348: static MssValue cal_eqSOperator(struct mssCal *cal)
0349: {
0350: int rsl;
0351: MssValue v;
0352: mssVinit(&v,DBL);
0353:
0354: rsl=mssVcmp(cal->arg[0].val[0], OPE_EQ, cal->arg[1].val[0]);
0355:
0356: if(rsl==-1) MssVnull(v);
0357: else v.v.d=(double)rsl;
0358:
0359: return(v);
0360: }
0361:
0362: /**
0363: * # FUNCTION #
0364: * !=(文字列比較:not equal)演算子
0365: * 与え方: 文字列1 -ne 文字列2
0366: * 返値: 0:条件不一致, 1:条件一致
0367: */
0368: static MssValue cal_neSOperator(struct mssCal *cal)
0369: {
0370: int rsl;
0371: MssValue v;
0372: mssVinit(&v,DBL);
0373:
0374: rsl=mssVcmp(cal->arg[0].val[0], OPE_NE, cal->arg[1].val[0]);
0375:
0376: if(rsl==-1) MssVnull(v);
0377: else v.v.d=(double)rsl;
0378:
0379: return(v);
0380: }
0381:
0382: /**
0383: * # FUNCTION #
0384: * >=(文字列比較:greater or equal)演算子
0385: * 与え方: 文字列1 -ge 文字列2
0386: * 返値: 0:条件不一致, 1:条件一致
0387: */
0388: static MssValue cal_geSOperator(struct mssCal *cal)
0389: {
0390: int rsl;
0391: MssValue v;
0392: mssVinit(&v,DBL);
0393:
0394: rsl=mssVcmp(cal->arg[0].val[0], OPE_GE, cal->arg[1].val[0]);
0395:
0396: if(rsl==-1) MssVnull(v);
0397: else v.v.d=(double)rsl;
0398:
0399: return(v);
0400: }
0401:
0402: /**
0403: * # FUNCTION #
0404: * <=(文字列比較:less or equal)演算子
0405: * 与え方: 文字列1 -le 文字列2
0406: * 返値: 0:条件不一致, 1:条件一致
0407: */
0408: static MssValue cal_leSOperator(struct mssCal *cal)
0409: {
0410: int rsl;
0411: MssValue v;
0412: mssVinit(&v,DBL);
0413:
0414: rsl=mssVcmp(cal->arg[0].val[0], OPE_LE, cal->arg[1].val[0]);
0415:
0416: if(rsl==-1) MssVnull(v);
0417: else v.v.d=(double)rsl;
0418:
0419: return(v);
0420: }
0421:
0422: /**
0423: * # FUNCTION #
0424: * >(文字列比較:greater)演算子
0425: * 与え方: 文字列1 -gt 文字列2
0426: * 返値: 0:条件不一致, 1:条件一致
0427: */
0428: static MssValue cal_gtSOperator(struct mssCal *cal)
0429: {
0430: int rsl;
0431: MssValue v;
0432: mssVinit(&v,DBL);
0433:
0434: rsl=mssVcmp(cal->arg[0].val[0], OPE_GT, cal->arg[1].val[0]);
0435:
0436: if(rsl==-1) MssVnull(v);
0437: else v.v.d=(double)rsl;
0438:
0439: return(v);
0440: }
0441:
0442: /**
0443: * # FUNCTION #
0444: * <(文字列比較:less)演算子
0445: * 与え方: 文字列1 -lt 文字列2
0446: * 返値: 0:条件不一致, 1:条件一致
0447: */
0448: static MssValue cal_ltSOperator(struct mssCal *cal)
0449: {
0450: int rsl;
0451: MssValue v;
0452: mssVinit(&v,DBL);
0453:
0454: rsl=mssVcmp(cal->arg[0].val[0], OPE_LT, cal->arg[1].val[0]);
0455:
0456: if(rsl==-1) MssVnull(v);
0457: else v.v.d=(double)rsl;
0458:
0459: return(v);
0460: }
0461:
0462: /**
0463: * # FUNCTION #
0464: * ||(論理和)演算子
0465: * 与え方: 数値1 || 数値2
0466: * 数値1、数値2のいずれかが1の時1を返し、それ以外の場合は0を返す。
0467: */
0468: static MssValue cal_orOperator(struct mssCal *cal)
0469: {
0470: MssValue v;
0471: mssVinit(&v,DBL);
0472:
0473: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul ){
0474: MssVnull(v);
0475: }else{
0476: if(cal->arg[0].val[0].v.d==1 || cal->arg[1].val[0].v.d==1){
0477: v.v.d=1;
0478: }else{
0479: v.v.d=0;
0480: }
0481: }
0482: return(v);
0483: }
0484:
0485: /**
0486: * # FUNCTION #
0487: * &&(論理積)演算子
0488: * 与え方: 数値1 && 数値2
0489: * 数値1、数値2ともに1の時1を返し、それ以外の場合は0を返す。
0490: */
0491: static MssValue cal_andOperator(struct mssCal *cal)
0492: {
0493: MssValue v;
0494: mssVinit(&v,DBL);
0495:
0496: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul ){
0497: MssVnull(v);
0498: }else{
0499: if(cal->arg[0].val[0].v.d==1 && cal->arg[1].val[0].v.d==1){
0500: v.v.d=1;
0501: }else{
0502: v.v.d=0;
0503: }
0504: }
0505: return(v);
0506: }
0507:
0508: /**
0509: * # FUNCTION #
0510: * if関数
0511: * 与え方: if(数値,value1,value2)
0512: * 数値が1の時はvalue1を、それ以外の時はvalue2を返す。
0513: * value1,value2の型変換は行わず、そのまま返す。
0514: * 数値がNULLの場合、STR型のNULL値を返す。
0515: */
0516: static MssValue cal_if(struct mssCal *cal)
0517: {
0518: MssValue v;
0519: mssVinit(&v,STR);
0520:
0521: if(cal->arg[0].val[0].nul){
0522: MssVnull(v);
0523: }else{
0524: if(cal->arg[0].val[0].v.d==1)
0525: v=cal->arg[1].val[0];
0526: else
0527: v=cal->arg[2].val[0];
0528: }
0529: return(v);
0530: }
0531:
0532: /**
0533: * # FUNCTION #
0534: * not関数
0535: * 与え方: not(数値)
0536: * 数値が0の時は1を、それ以外の時は0を返す。
0537: * その他の場合は、NULL値を返す。
0538: */
0539: static MssValue cal_not(struct mssCal *cal)
0540: {
0541: MssValue v;
0542: mssVinit(&v,DBL);
0543:
0544: if(cal->arg[0].val[0].nul){
0545: MssVnull(v);
0546: }else{
0547: if(cal->arg[0].val[0].v.d ==0 ){
0548: v.v.d = 1;
0549: }else{
0550: v.v.d = 0;
0551: }
0552: }
0553: return(v);
0554: }
0555:
0556: /**
0557: * # FUNCTION #
0558: * sum関数
0559: * 与え方: sum(数値1,数値2,...,数値n)
0560: * 数値1から数値nまでを合計し、その値を返す。
0561: * その中に一つでもNULL値があると、NULL値を返す。
0562: * sum関数では、項目名の指定にワイルドカードが利用できる。
0563: */
0564: static MssValue cal_sum(struct mssCal *cal)
0565: {
0566: MssValue v;
0567: int i,j;
0568: mssVinit(&v,DBL);
0569:
0570: for(i=0; i<cal->argCnt; i++){
0571: for(j=0; j<cal->arg[i].valCnt; j++){
0572: if(cal->arg[i].val[j].nul){
0573: MssVnull(v); return(v);
0574: }else{
0575: v.v.d += cal->arg[i].val[j].v.d;
0576: }
0577: }
0578: }
0579: return(v);
0580: }
0581:
0582: /**
0583: * # FUNCTION #
0584: * min関数
0585: * 与え方: min(数値1,数値2,...,数値n)
0586: * 数値1から数値nの中で最小値を返す。
0587: * その中に一つでもNULL値があると、NULL値を返す。
0588: * min関数では、項目名の指定にワイルドカードが利用できる。
0589: */
0590: static MssValue cal_min(struct mssCal *cal)
0591: {
0592: MssValue v;
0593: int i,j;
0594: mssVinit(&v,DBL);
0595:
0596: mssVclearMax(&v);
0597: for(i=0; i<cal->argCnt; i++){
0598: for(j=0; j<cal->arg[i].valCnt; j++){
0599: if(cal->arg[i].val[j].nul){
0600: MssVnull(v); return(v);
0601: }else{
0602: if(v.v.d > cal->arg[i].val[j].v.d){
0603: v.v.d = cal->arg[i].val[j].v.d;
0604: }
0605: }
0606: }
0607: }
0608: return(v);
0609: }
0610:
0611: /**
0612: * # FUNCTION #
0613: * max関数
0614: * 与え方: max(数値1,数値2,...,数値n)
0615: * 数値1から数値nの中で最小値を返す。
0616: * その中に一つでもNULL値があると、NULL値を返す。
0617: * maxn関数では、項目名の指定にワイルドカードが利用できる。
0618: */
0619: static MssValue cal_max(struct mssCal *cal)
0620: {
0621: MssValue v;
0622: int i,j;
0623: mssVinit(&v,DBL);
0624:
0625: mssVclearMin(&v);
0626: for(i=0; i<cal->argCnt; i++){
0627: for(j=0; j<cal->arg[i].valCnt; j++){
0628: if(cal->arg[i].val[j].nul){
0629: MssVnull(v); return(v);
0630: }else{
0631: if(v.v.d < cal->arg[i].val[j].v.d){
0632: v.v.d = cal->arg[i].val[j].v.d;
0633: }
0634: }
0635: }
0636: }
0637: return(v);
0638: }
0639:
0640:
0641: /**
0642: * # FUNCTION #
0643: * log関数
0644: * 与え方: log(数値1,数値2)
0645: * 数値2を底とする数値1の対数を返す。
0646: * 数値1もしくは数値2が0以下の場合はNULL値を返す。
0647: */
0648: static MssValue cal_log(struct mssCal *cal)
0649: {
0650: MssValue v;
0651: double rsl1=0;
0652: double rsl2=0;
0653: mssVinit(&v,DBL);
0654:
0655: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul ){
0656: MssVnull(v);
0657: }else{
0658: if(cal->arg[0].val[0].v.d <=0 || cal->arg[1].val[0].v.d <=0){
0659: MssVnull(v);
0660: }else{
0661: rsl1=log(cal->arg[0].val[0].v.d);
0662: rsl2=log(cal->arg[1].val[0].v.d);
0663:
0664: if(rsl2==0){
0665: MssVnull(v);
0666: }else{
0667: v.v.d = rsl1/rsl2;
0668: }
0669: }
0670: }
0671: return(v);
0672: }
0673:
0674: /**
0675: * # FUNCTION #
0676: * log2関数
0677: * 与え方: log2(数値)
0678: * 2を底とする数値の対数を返す。
0679: * 数値が0以下の場合はNULL値を返す。
0680: */
0681: static MssValue cal_log2(struct mssCal *cal)
0682: {
0683: MssValue v;
0684: mssVinit(&v,DBL);
0685:
0686: if(cal->arg[0].val[0].nul){
0687: MssVnull(v);
0688: }else{
0689: if(cal->arg[0].val[0].v.d <=0 ){
0690: MssVnull(v);
0691: }else{
0692: v.v.d=log(cal->arg[0].val[0].v.d)/log(2);
0693: }
0694: }
0695: return(v);
0696: }
0697:
0698: /**
0699: * # FUNCTION #
0700: * log関数
0701: * 与え方: log10(数値)
0702: * 10を底とする数値の対数を返す。
0703: * 数値が0以下の場合はNULL値を返す。
0704: */
0705: static MssValue cal_log10(struct mssCal *cal)
0706: {
0707: MssValue v;
0708: mssVinit(&v,DBL);
0709:
0710: if(cal->arg[0].val[0].nul){
0711: MssVnull(v);
0712: }else{
0713: if(cal->arg[0].val[0].v.d <=0 ){
0714: MssVnull(v);
0715: }else{
0716: v.v.d = log10(cal->arg[0].val[0].v.d);
0717: }
0718: }
0719: return(v);
0720: }
0721:
0722: /**
0723: * # FUNCTION #
0724: * ln関数
0725: * 与え方: ln(数値)
0726: * 数値の自然対数を返す。
0727: * 数値が0以下の場合はNULL値を返す。
0728: */
0729: static MssValue cal_ln(struct mssCal *cal)
0730: {
0731: MssValue v;
0732: mssVinit(&v,DBL);
0733:
0734: if(cal->arg[0].val[0].nul){
0735: MssVnull(v);
0736: }else{
0737: if(cal->arg[0].val[0].v.d <=0 ){
0738: MssVnull(v); return(v);
0739: }else{
0740: v.v.d = log(cal->arg[0].val[0].v.d);
0741: }
0742: }
0743: return(v);
0744: }
0745:
0746: /**
0747: * # FUNCTION #
0748: * rand関数
0749: * 与え方: rand(最小値,種類数,乱数の種)
0750: * 最小値以上の連続する整数から、種類数の疑似乱数を返す。
0751: * すなわち、最小値から"最小値+種類数-1"の整数の疑似乱数を生成する。
0752: * 乱数の種が-1の時、時間に応じた乱数の種を用いる。
0753: * ex) rand(2,3,1): 2,3,4 のいずれかの値を返す。
0754: * 種類数が1以下、もしくはRAND_MAXを超えていればエラー&終了。
0755: */
0756: static MssValue cal_rand(struct mssCal *cal)
0757: {
0758: MssValue v;
0759: static double unit=0;
0760: mssVinit(&v,DBL);
0761:
0762: if(mssGV.inCnt==1){
0763: /*乱数の単位*/
0764: if(cal->arg[1].val[0].v.d<=1 || cal->arg[1].val[0].v.d>(double)RAND_MAX) {
0765: mssShowErrMsg("the second parameter must be in a range 2-%d.",RAND_MAX);
0766: mssEnd(mssErrorNoDefault);
0767: }
0768: unit=(double)(RAND_MAX) / ((double)(cal->arg[1].val[0].v.d - 1) );
0769: /*乱数の種*/
0770: mssInitRand((int)cal->arg[2].val[0].v.d);
0771: }
0772:
0773: v.v.d = (double)(int)(cal->arg[0].val[0].v.d+(double)rand()/unit+0.5);
0774: return(v);
0775: }
0776:
0777: /**
0778: * # FUNCTION #
0779: * nrand関数
0780: * 与え方: nrand(平均値,標準偏差,乱数の種)
0781: * 正規分布に基づいた疑似乱数を返す。
0782: * 正規分布は、平均値、標準偏差を与えることによって決まる。
0783: * 乱数の種が-1の時、時間に応じた乱数の種を用いる。
0784: *
0785: * 【求め方】
0786: * 平均0、標準偏差1の正規分布関数:y=1/sqrt(2*pi) * e^(-x^2/2)
0787: * x=0の時、最大値y=1/sqrt(2*pi)となる。
0788: * ここでa=1/sqrt(2*pi)と置くと
0789: * y=a*e^(-x^2/2)
0790: * またe^(-x^2/2)=sqrt(1/e)^(x^2)で、sqrt(1/e)は定数なのでesとおくと
0791: * y=a*es^(x^2)となる ---- (1)
0792: * yの最大値が1、最小値が0となるように基準化すると
0793: * y=(1)式/最大値a = es^(x^2) となる
0794: *
0795: * ここで正規分布に従った乱数を求める手順は
0796: * 1) xを乱数で与えyの値を求める
0797: * 2) 再び乱数rを求める
0798: * 3) r<=y ならば、その時のxの値を乱数侯補とし、そうでなければ1)に戻る
0799: * 4) 乱数侯補xがパラメータで指定された乱数の種類数に収まらなければ1)に戻る
0800: * 5) 乱数侯補xを乱数として採用する
0801: * ただし平均を中心としてマイナスとプラスがあるので、乱数を求める毎に切替える。
0802: */
0803: static MssValue cal_nrand(struct mssCal *cal)
0804: {
0805: MssValue v;
0806: double negpos;
0807: static double a;
0808: static double es;
0809: double x,y; /*基準化された正規分布におけるx,y*/
0810: double r; /*xに代入する乱数*/
0811: mssVinit(&v,DBL);
0812:
0813: if(mssGV.inCnt==1){
0814:
0815: /*定数部分の計算*/
0816: a =1/sqrt(2*M_PI);
0817: es=sqrt(1/M_E);
0818:
0819: /*乱数の種*/
0820: mssInitRand((int)cal->arg[2].val[0].v.d);
0821: }
0822:
0823: if((double)rand()/RAND_MAX>0.5)negpos=1;
0824: else negpos=-1;
0825:
0826: do {
0827: x=(double)4*(double)rand()/RAND_MAX; /*0から1の乱数*/
0828: r=(double)rand()/RAND_MAX;
0829: y=pow(es,x*x);
0830: }while(r>y);
0831:
0832: v.v.d = negpos*x*cal->arg[1].val[0].v.d+cal->arg[0].val[0].v.d;
0833:
0834: return(v);
0835: }
0836:
0837: /**
0838: * # FUNCTION #
0839: * cal->arg[i]の中に一つでもNULL値があれば1を返す。それ以外は0を返す。
0840: */
0841: static int argHaveNull(struct mssCal *cal)
0842: {
0843: int i,j;
0844: for(i=0; i<cal->argCnt; i++){
0845: for(j=0; j<cal->arg[i].valCnt; j++){
0846: if(cal->arg[i].val[j].nul){
0847: return(1);
0848: }
0849: }
0850: }
0851: return(0);
0852: }
0853:
0854: /**
0855: * # FUNCTION #
0856: * cat関数
0857: * 与え方: cat(文字列1,文字列2,...,文字列n,区切り文字)
0858: * 文字列1から文字列2を区切り文字をはさんで結合し、その結果を返す。
0859: * その中に一つでもNULL値があると、NULL値を返す。
0860: * cat関数では、項目名の指定にワイルドカードが利用できる。
0861: * 区切り文字にスペースがある場合は"_"に変換される。
0862: */
0863: static MssValue cal_cat(struct mssCal *cal)
0864: {
0865: int i,j;
0866: MssValue v;
0867: char *token;
0868: int tokenLen;
0869: int len;
0870: mssVinit(&v,STR);
0871:
0872: if(argHaveNull(cal)) {
0873: MssVnull(v);
0874: return(v);
0875: }
0876:
0877: /*デリミタの設定*/
0878: token=cal->arg[cal->argCnt-1].val[0].v.s;
0879: tokenLen=strlen(token);
0880: for(i=0;i<tokenLen; i++){
0881: if(*(token+i)==' ') *(token+i)='_';
0882: }
0883:
0884: len=strlen(cal->arg[0].val[0].v.s)+1;
0885: v.v.s=mssMalloc(len,"cal_cat");
0886: strcpy(v.v.s, cal->arg[0].val[0].v.s);
0887:
0888: for(j=1; j<cal->arg[0].valCnt; j++){
0889: len += strlen(cal->arg[0].val[j].v.s)+tokenLen;
0890: v.v.s=mssReallocLim(v.v.s,len,MssFieldMaxLen,"cal_cat");
0891: strcat(v.v.s, token);
0892: strcat(v.v.s, cal->arg[0].val[j].v.s);
0893: }
0894:
0895: for(i=1; i<cal->argCnt-1; i++){
0896: for(j=0; j<cal->arg[i].valCnt; j++){
0897: len += strlen(cal->arg[i].val[j].v.s)+tokenLen;
0898: v.v.s=mssReallocLim(v.v.s,len,MssFieldMaxLen,"cal_cat");
0899: strcat(v.v.s, token);
0900: strcat(v.v.s, cal->arg[i].val[j].v.s);
0901: }
0902: }
0903: setStrMalAdd(v.v.s);
0904: return(v);
0905: }
0906:
0907: /**
0908: * # FUNCTION #
0909: * length関数
0910: * 与え方: length(文字列)
0911: * 文字列の長さをバイト数で返す。
0912: */
0913: static MssValue cal_length(struct mssCal *cal)
0914: {
0915: MssValue v;
0916: mssVinit(&v,DBL);
0917:
0918: if(argHaveNull(cal)) {
0919: MssVnull(v);
0920: return(v);
0921: }
0922:
0923: v.v.d=(double)strlen(cal->arg[0].val[0].v.s);
0924: return(v);
0925: }
0926:
0927: /**
0928: * # FUNCTION #
0929: * fix関数
0930: * 与え方: fix(文字列,文字数,位置,詰める文字)
0931: * 「文字列」を「文字数」の固定長に変換した文字列を返す。
0932: * 文字数はバイト数で指定する。
0933: * 固定長にする場合、文字列の長さが「文字数」より短い場合、
0934: * パディング(詰める)文字を「詰める文字」で指定する。
0935: * パディング文字にスペースは指定できない。
0936: * また、パディングする際に、文字列を左右のどちらにそろえるかを
0937: * 「位置」に"R"(右)もしくは"L"(左)を与えることによって指定する。
0938: * 「文字列」の長さが「文字数」より長い場合、「位置」がLの時は「文字列」の右側
0939: * の超過分が削られ、Rの時は左側が削られる。
0940: */
0941: static MssValue cal_fix(struct mssCal *cal)
0942: {
0943: int i;
0944: MssValue v;
0945: char *str;
0946: char rl;
0947: char pad;
0948: int len;
0949: int sl;
0950: int padLen;
0951: int strLen;
0952: int pos;
0953:
0954: mssVinit(&v,STR);
0955:
0956: if(argHaveNull(cal)) {
0957: MssVnull(v);
0958: return(v);
0959: }
0960:
0961: str = cal->arg[0].val[0].v.s;
0962: len = (int)cal->arg[1].val[0].v.d;
0963: rl = *cal->arg[2].val[0].v.s;
0964: pad = *cal->arg[3].val[0].v.s;
0965: sl=strlen(str);
0966:
0967: if(isspace(pad)) {
0968: mssShowErrMsg("padding charactor cannot be a space");
0969: mssEnd(mssErrorNoDefault);
0970: }
0971:
0972: if(len>=MssFieldMaxLen) {
0973: mssShowErrMsg("second parameter in [fix] function must be in a rage of 1-%d",MssFieldMaxLen-1);
0974: mssEnd(mssErrorNoDefault);
0975: }
0976:
0977: v.v.s=mssMalloc(len+1,"cal_fix");
0978: if(sl>len){ padLen=0 ; strLen=len; }
0979: else { padLen=len-sl; strLen=sl ; }
0980:
0981: switch(rl){
0982: case 'L':
0983: pos=0;
0984: for(i=0; i<strLen; i++) {
0985: *(v.v.s+pos)=*(str+i);
0986: pos++;
0987: }
0988: for(i=0; i<padLen; i++) {
0989: *(v.v.s+pos)=pad;
0990: pos++;
0991: }
0992: *(v.v.s+pos)='\0';
0993: break;
0994: case 'R':
0995: pos=len-1;
0996: for(i=sl-1; i>=sl-strLen; i--) {
0997: *(v.v.s+pos)=*(str+i);
0998: pos--;
0999: }
1000: for(i=0; i<padLen; i++) {
1001: *(v.v.s+pos)=pad;
1002: pos--;
1003: }
1004: *(v.v.s+len)='\0';
1005: break;
1006: default:
1007: mssShowErrMsg("specify [R] or [L] in the third parameter in [fix] function.");
1008: mssEnd(mssErrorNoDefault);
1009: break;
1010: }
1011:
1012: setStrMalAdd(v.v.s);
1013: return(v);
1014: }
1015:
1016: /**
1017: * # FUNCTION #
1018: * left関数
1019: * 与え方: left(文字列,文字数)
1020: * 「文字列」の左から「文字数」の文字列を切りだし、その値を返す。
1021: * 文字数はバイト数で指定する。
1022: * 「文字数」が「文字列」の長さより長ければ、「文字列」をそのまま返す。
1023: */
1024: static MssValue cal_left(struct mssCal *cal)
1025: {
1026: MssValue v;
1027: char *str;
1028: int len;
1029: int sl;
1030: int strLen;
1031:
1032: mssVinit(&v,STR);
1033:
1034: if(argHaveNull(cal)) {
1035: MssVnull(v);
1036: return(v);
1037: }
1038:
1039: str = cal->arg[0].val[0].v.s;
1040: len = (int)cal->arg[1].val[0].v.d;
1041: sl=strlen(str);
1042:
1043: if(len>=MssFieldMaxLen) {
1044: mssShowErrMsg("invalid length specified in [left] function");
1045: mssEnd(mssErrorNoDefault);
1046: }
1047:
1048: if(sl>len) strLen=len;
1049: else strLen=sl ;
1050: v.v.s=mssMalloc(strLen+1,"cal_left");
1051: strncpy(v.v.s,str,strLen);
1052: *(v.v.s+strLen)='\0';
1053: setStrMalAdd(v.v.s);
1054: return(v);
1055: }
1056:
1057: /**
1058: * # FUNCTION #
1059: * right関数
1060: * 与え方: right(文字列,文字数)
1061: * 「文字列」の右から「文字数」の文字列を切りだし、その値を返す。
1062: * 文字数はバイト数で指定する。
1063: * 「文字数」が「文字列」の長さより長ければ、「文字列」をそのまま返す。
1064: */
1065: static MssValue cal_right(struct mssCal *cal)
1066: {
1067: MssValue v;
1068: char *str;
1069: int len;
1070: int sl;
1071: int strLen;
1072:
1073: mssVinit(&v,STR);
1074:
1075: if(argHaveNull(cal)) {
1076: MssVnull(v);
1077: return(v);
1078: }
1079:
1080: str = cal->arg[0].val[0].v.s;
1081: len = (int)cal->arg[1].val[0].v.d;
1082: sl=strlen(str);
1083:
1084: if(len>=MssFieldMaxLen || len <=0) {
1085: mssShowErrMsg("invalid length specified in [right] function");
1086: mssEnd(mssErrorNoDefault);
1087: }
1088:
1089: if(sl>len) strLen=len;
1090: else strLen=sl ;
1091: v.v.s=mssMalloc(strLen+1,"cal_left");
1092: strncpy(v.v.s,str+(sl-strLen),strLen);
1093: *(v.v.s+strLen)='\0';
1094: setStrMalAdd(v.v.s);
1095: return(v);
1096: }
1097:
1098: /**
1099: * # FUNCTION #
1100: * substr関数
1101: * 与え方: substr(文字列,開始位置,終了位置)
1102: * 「文字列」の「開始位置」から「終了位置」の文字列を切りだし、その値を返す。
1103: * 「終了位置」が「文字列」の末尾を超えた場合は、終了位置が末尾に変更される。
1104: * 「開始位置」、「終了位置」ともに末尾を超えた場合は、NULL値を返す。
1105: * 「開始位置」、「終了位置」が0以下の数字の場合はエラー終了する。
1106: */
1107: static MssValue cal_substr(struct mssCal *cal)
1108: {
1109: MssValue v;
1110: char *str;
1111: int from;
1112: int to;
1113: int len;
1114: int sl;
1115:
1116: mssVinit(&v,STR);
1117:
1118: if(argHaveNull(cal)) {
1119: MssVnull(v);
1120: return(v);
1121: }
1122:
1123: str = cal->arg[0].val[0].v.s;
1124: from = (int)cal->arg[1].val[0].v.d;
1125: to = (int)cal->arg[2].val[0].v.d;
1126: sl=strlen(str);
1127:
1128: if(from>to) mssSwapInt(&from,&to);
1129: len=to-from+1;
1130:
1131: if(len>=MssFieldMaxLen || len<=0 || from<=0 || to<=0) {
1132: mssShowErrMsg("invalid length specified in [substr] function");
1133: mssEnd(mssErrorNoDefault);
1134: }
1135:
1136: /*スタート位置が文字列長を超えていたらNULL*/
1137: if(from>sl) {
1138: MssVnull(v);
1139: return(v);
1140: }
1141:
1142: /*エンド位置が文字列長を超えていたら、文字列の最後に変える*/
1143: if(to>sl) to=sl;
1144:
1145: len=to-from+1;
1146:
1147: v.v.s=mssMalloc(len+1,"cal_left");
1148: strncpy(v.v.s,str+from-1,len);
1149: *(v.v.s+len)='\0';
1150: setStrMalAdd(v.v.s);
1151: return(v);
1152: }
1153:
1154: /**
1155: * # FUNCTION #
1156: * =~比較演算子
1157: * 与え方: 文字列=~正規表現
1158: * 文字列が正規表現にマッチすれば1、しなければ0を返す。
1159: * ただし、正規表現のコンパイルは、データの一行目を処理の時のみ行われる。
1160: * 正規表現として、Extended Regular Expression(ERE)を用いている。
1161: */
1162: static MssValue cal_regOperator(struct mssCal *cal)
1163: {
1164:
1165: MssValue v;
1166:
1167: int rsl;
1168: char *str;
1169: char *reg;
1170: mssVinit(&v,DBL);
1171:
1172: if(mssGV.inCnt==1){
1173: reg=cal->arg[1].val[0].v.s;
1174: if(regcomp(&cal->regex,reg,REG_EXTENDED) ){
1175: mssShowErrMsg("error in compiling regex");
1176: mssEnd(mssErrorNoDefault);
1177: }
1178: }
1179:
1180: if(cal->arg[0].val[0].nul) {
1181: MssVnull(v);
1182: return(v);
1183: }
1184:
1185: str=cal->arg[0].val[0].v.s;
1186:
1187: rsl=regexec(&cal->regex, str, 0, NULL,0);
1188: if(rsl!=0){
1189: v.v.d=0;
1190: }else{
1191: v.v.d=1;
1192: }
1193: return(v);
1194: }
1195:
1196: /**
1197: * # FUNCTION #
1198: * regexEnd関数
1199: * 与え方: regexEnd(文字列,正規表現)
1200: * 文字列の中で、正規表現にマッチする終端位置を返す。
1201: * ただし、正規表現のコンパイルは、データの一行目を処理の時のみ行われる。
1202: * 正規表現として、Extended Regular Expression(ERE)を用いている。
1203: */
1204: static MssValue cal_regexEnd(struct mssCal *cal)
1205: {
1206:
1207: MssValue v;
1208: regmatch_t matchPnt;
1209:
1210: int rsl;
1211: char *str;
1212: char *reg;
1213: mssVinit(&v,DBL);
1214:
1215: if(mssGV.inCnt==1){
1216: reg=cal->arg[1].val[0].v.s;
1217:
1218: if(regcomp(&cal->regex,reg,REG_EXTENDED) ){
1219: mssShowErrMsg("error in compiling regex");
1220: mssEnd(mssErrorNoDefault);
1221: }
1222: }
1223:
1224: if(cal->arg[0].val[0].nul) {
1225: MssVnull(v);
1226: return(v);
1227: }
1228:
1229: str=cal->arg[0].val[0].v.s;
1230:
1231: rsl=regexec(&cal->regex, str, 1, &matchPnt,0);
1232: if(rsl!=0){
1233: MssVnull(v);
1234: }else{
1235: v.v.d=matchPnt.rm_eo;
1236: }
1237: return(v);
1238: }
1239:
1240: /**
1241: * # FUNCTION #
1242: * regexStart関数
1243: * 与え方: regexStart(文字列,正規表現)
1244: * 文字列の中で、正規表現にマッチする開始位置を返す。
1245: * ただし、正規表現のコンパイルは、データの一行目を処理の時のみ行われる。
1246: * 正規表現として、Extended Regular Expression(ERE)を用いている。
1247: */
1248: static MssValue cal_regexStart(struct mssCal *cal)
1249: {
1250:
1251: MssValue v;
1252: regmatch_t matchPnt;
1253:
1254: int rsl;
1255: char *str;
1256: char *reg;
1257: mssVinit(&v,DBL);
1258:
1259: if(mssGV.inCnt==1){
1260: reg=cal->arg[1].val[0].v.s;
1261:
1262: if(regcomp(&cal->regex,reg,REG_EXTENDED) ){
1263: mssShowErrMsg("error in compiling regex");
1264: mssEnd(mssErrorNoDefault);
1265: }
1266: }
1267:
1268: if(cal->arg[0].val[0].nul) {
1269: MssVnull(v);
1270: return(v);
1271: }
1272:
1273: str=cal->arg[0].val[0].v.s;
1274:
1275: rsl=regexec(&cal->regex, str, 1, &matchPnt,0);
1276: if(rsl!=0){
1277: MssVnull(v);
1278: }else{
1279: v.v.d=matchPnt.rm_so+1;
1280: }
1281: return(v);
1282: }
1283:
1284: /**
1285: * # FUNCTION #
1286: * regexLen関数
1287: * 与え方: regexStart(文字列,正規表現)
1288: * 文字列の中で、正規表現にマッチする部分文字列の長さをバイト数として返す。
1289: * ただし、正規表現のコンパイルは、データの一行目を処理の時のみ行われる。
1290: * 正規表現として、Extended Regular Expression(ERE)を用いている。
1291: */
1292: static MssValue cal_regexLen(struct mssCal *cal)
1293: {
1294:
1295: MssValue v;
1296: regmatch_t matchPnt;
1297:
1298: int rsl;
1299: char *str;
1300: char *reg;
1301: mssVinit(&v,DBL);
1302:
1303: if(cal->arg[0].val[0].nul) {
1304: MssVnull(v);
1305: return(v);
1306: }
1307:
1308: str=cal->arg[0].val[0].v.s;
1309: if(mssGV.inCnt==1){
1310: reg=cal->arg[1].val[0].v.s;
1311:
1312: if(regcomp(&cal->regex,reg,REG_EXTENDED) ){
1313: mssShowErrMsg("error in compiling regex");
1314: mssEnd(mssErrorNoDefault);
1315: }
1316: }
1317:
1318: rsl=regexec(&cal->regex, str, 1, &matchPnt,0);
1319: if(rsl!=0){
1320: MssVnull(v);
1321: }else{
1322: v.v.d=matchPnt.rm_eo-matchPnt.rm_so;
1323: }
1324: return(v);
1325: }
1326:
1327: /**
1328: * # FUNCTION #
1329: * pi関数
1330: * 与え方: pi()
1331: * πの値を返す。
1332: */
1333: static MssValue cal_pi(struct mssCal *cal)
1334: {
1335: MssValue v;
1336: mssVinit(&v,DBL);
1337:
1338: v.v.d=M_PI;
1339: return(v);
1340: }
1341:
1342: /**
1343: * # FUNCTION #
1344: * sqrt関数
1345: * 与え方: sqrt(数値)
1346: * 数値の平方根を返す。数値がマイナスの時はNULL値を返す。
1347: */
1348: static MssValue cal_Sqrt(struct mssCal *cal)
1349: {
1350: MssValue v;
1351: mssVinit(&v,DBL);
1352:
1353: if(cal->arg[0].val[0].nul || cal->arg[0].val[0].v.d<0){
1354: MssVnull(v);
1355: }else{
1356: v.v.d = sqrt(cal->arg[0].val[0].v.d);
1357: }
1358: return(v);
1359: }
1360:
1361: /**
1362: * # FUNCTION #
1363: * exp関数
1364: * 与え方: exp(数値)
1365: * e(ネイピア数)底とする指数「数値」の累乗(e^x)を返す。
1366: * 計算結果が大きすぎる場合はNULL値を返す。
1367: */
1368: static MssValue cal_Exp(struct mssCal *cal)
1369: {
1370: MssValue v;
1371: mssVinit(&v,DBL);
1372:
1373: if(cal->arg[0].val[0].nul){
1374: MssVnull(v);
1375: return(v);
1376: }
1377: v.v.d = exp(cal->arg[0].val[0].v.d);
1378:
1379: if(v.v.d == HUGE_VAL) {
1380: MssVnull(v);
1381: }
1382: return(v);
1383: }
1384:
1385: /**
1386: * # FUNCTION #
1387: * power関数
1388: * 与え方: power(数値1,数値2)
1389: * 「数値1」の「数値2」乗を計算し、その値を返す。
1390: * 計算結果が大きすぎたり、小さすぎた場合はNULL値を返す。
1391: */
1392: static MssValue cal_power(struct mssCal *cal)
1393: {
1394: MssValue v;
1395: mssVinit(&v,DBL);
1396:
1397: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
1398: MssVnull(v);
1399: return(v);
1400: }
1401: v.v.d = pow(cal->arg[0].val[0].v.d,cal->arg[1].val[0].v.d);
1402:
1403: if(v.v.d == HUGE_VAL || v.v.d == ERANGE) {
1404: MssVnull(v);
1405: }
1406: return(v);
1407: }
1408:
1409: /**
1410: * # FUNCTION #
1411: * abs関数
1412: * 与え方: abs(数値)
1413: * 「数値」の絶対値を返す。
1414: */
1415: static MssValue cal_abs(struct mssCal *cal)
1416: {
1417: MssValue v;
1418: mssVinit(&v,DBL);
1419:
1420: if(cal->arg[0].val[0].nul){
1421: MssVnull(v);
1422: return(v);
1423: }
1424: if(cal->arg[0].val[0].v.d<0){
1425: v.v.d=cal->arg[0].val[0].v.d * (-1);
1426: }else{
1427: v.v.d=cal->arg[0].val[0].v.d;
1428: }
1429: return(v);
1430: }
1431:
1432: /**
1433: * # FUNCTION #
1434: * up関数
1435: * 与え方: up(数値,基準値)
1436: * 数値を基準値にしたがって切り上げ、その値を返す。
1437: * 基準値には、切り上げた結果数値の単位を指定する。
1438: * 例えば、123.456という数値に対する計算結果は以下のとおり。
1439: * 基準値 結果
1440: * 1 124 -> 結果は1の倍数
1441: * 0.1 123.5 -> 結果は0.1の倍数
1442: * 10 130
1443: * 0.5 123.5
1444: */
1445: static MssValue cal_up(struct mssCal *cal)
1446: {
1447: MssValue v;
1448: mssVinit(&v,DBL);
1449:
1450: if(cal->arg[0].val[0].nul ||
1451: cal->arg[1].val[0].nul ||
1452: cal->arg[1].val[0].v.d<=0 ){
1453: MssVnull(v);
1454: return(v);
1455: }
1456:
1457: v.v.d=ceil(cal->arg[0].val[0].v.d/cal->arg[1].val[0].v.d)*cal->arg[1].val[0].v.d;
1458:
1459: return(v);
1460: }
1461:
1462: /**
1463: * # FUNCTION #
1464: * down関数
1465: * 与え方: down(数値,基準値)
1466: * 数値を基準値にしたがって切り下げ、その値を返す。
1467: * 基準値には、切り下げた結果数値の単位を指定する。
1468: * 例えば、123.456という数値に対する計算結果は以下のとおり。
1469: * 基準値 結果
1470: * 1 123 -> 結果は1の倍数
1471: * 0.1 123.4 -> 結果は0.1の倍数
1472: * 10 120
1473: * 0.5 123.0
1474: */
1475: static MssValue cal_down(struct mssCal *cal)
1476: {
1477: MssValue v;
1478: double diff;
1479: mssVinit(&v,DBL);
1480:
1481: if(cal->arg[0].val[0].nul ||
1482: cal->arg[1].val[0].nul ||
1483: cal->arg[1].val[0].v.d<=0 ){
1484: MssVnull(v);
1485: return(v);
1486: }
1487:
1488: v.v.d=ceil(cal->arg[0].val[0].v.d/cal->arg[1].val[0].v.d)*cal->arg[1].val[0].v.d;
1489: diff=v.v.d - cal->arg[0].val[0].v.d;
1490: if(diff > DBL0 || diff < -DBL0 ){
1491: v.v.d -= cal->arg[1].val[0].v.d;
1492: }
1493:
1494: return(v);
1495: }
1496:
1497: /**
1498: * # FUNCTION #
1499: * round関数
1500: * 与え方: round(数値,基準値)
1501: * 数値を基準値にしたがって四捨五入し、その値を返す。
1502: * 基準値には、四捨五入した結果数値の単位を指定する。
1503: * 正確にいえば、四捨五入ではなく、基準値の整数倍の数値集合の中で最も近い数値
1504: * を返す。
1505: * 例えば、123.456という数値に対する計算結果は以下のとおり。
1506: * 基準値 結果
1507: * 1 123 -> 結果は1の倍数
1508: * 0.1 123.5 -> 結果は0.1の倍数
1509: * 10 120
1510: * 0.5 123.5
1511: */
1512: static MssValue cal_round(struct mssCal *cal)
1513: {
1514: MssValue v;
1515: double v0;
1516: double v1;
1517: double vint;
1518: mssVinit(&v,DBL);
1519:
1520: if(cal->arg[0].val[0].nul ||
1521: cal->arg[1].val[0].nul ||
1522: cal->arg[1].val[0].v.d<=0 ){
1523: MssVnull(v);
1524: return(v);
1525: }
1526:
1527: v0=cal->arg[0].val[0].v.d;
1528: v1=cal->arg[1].val[0].v.d;
1529: if(v0<0) modf((v0-(v1/2)-DBL0)/v1,&vint);
1530: else modf((v0+(v1/2)+DBL0)/v1,&vint);
1531: v.v.d=vint*v1;
1532:
1533: return(v);
1534: }
1535:
1536: /**
1537: * # FUNCTION #
1538: * fixdec関数
1539: * 与え方: up(数値,小数点以下桁数)
1540: * 数値の小数点以下の桁数を、指定した値でそろえ、文字列として返す。
1541: */
1542: static MssValue cal_fixdec(struct mssCal *cal)
1543: {
1544: char buf[256];
1545: char fmt[20];
1546: MssValue v;
1547: mssVinit(&v,STR);
1548:
1549: if(cal->arg[0].val[0].nul ||
1550: cal->arg[1].val[0].nul ||
1551: cal->arg[1].val[0].v.d<0 ||
1552: cal->arg[1].val[0].v.d>6 ){
1553: MssVnull(v);
1554: return(v);
1555: }
1556:
1557: fmt[0]='%';
1558: fmt[1]='.';
1559: sprintf(&fmt[2],"%df",(int)cal->arg[1].val[0].v.d);
1560:
1561: sprintf(buf,fmt,cal->arg[0].val[0].v.d);
1562:
1563: v.v.s=mssStrdup(buf);
1564:
1565: setStrMalAdd(v.v.s);
1566: return(v);
1567: }
1568:
1569:
1570: /**
1571: * # FUNCTION #
1572: * 有効な日付なら1をそうでなければ0を返す。
1573: */
1574: static int validDate(char *d)
1575: {
1576: /*長さチェック*/
1577: if(strlen(d) != 8) return(0);
1578:
1579: /*グレゴリオ歴初日より小さければ無効*/
1580: if(strcmp(d,"15821015")<0) return(0);
1581:
1582: return(1);
1583: }
1584:
1585: /**
1586: * # FUNCTION #
1587: * 有効な時刻なら1をそうでなければ0を返す。
1588: */
1589: static int validTime(char *d)
1590: {
1591: /*長さチェック*/
1592: if(strlen(d) != 6) return(0);
1593:
1594: return(1);
1595: }
1596:
1597: /**
1598: * # FUNCTION #
1599: *年月日時分秒からユリウス日を求める。
1600: * ただしグレゴリオ歴であることが前提
1601: * 文字列として与えられた、日付、時刻を引数にとり、日数.時刻のdouble型を返す。
1602: * http://alfin.mine.utsunomiya-u.ac.jp/~niy/algo/u/ut2jd.html を修正して利用
1603: */
1604: static double ut2jd(char *date, char *time)
1605: {
1606: int year,month,day,hour,min,sec;
1607: char buf[5];
1608: double d;
1609: long j;
1610:
1611: strncpy(buf,date ,4); buf[4]='\0'; year =atoi(buf);
1612: strncpy(buf,date+4,2); buf[2]='\0'; month=atoi(buf);
1613: strncpy(buf,date+6,2); buf[2]='\0'; day =atoi(buf);
1614: strncpy(buf,time ,2); buf[2]='\0'; hour =atoi(buf);
1615: strncpy(buf,time+2,2); buf[2]='\0'; min =atoi(buf);
1616: strncpy(buf,time+4,2); buf[2]='\0'; sec =atoi(buf);
1617:
1618: if (month <= 2) {
1619: year--;
1620: month += 12;
1621: }
1622:
1623: if (hour < 12) {
1624: j = 0;
1625: d = 0.5;
1626: } else {
1627: j = 1;
1628: d = -0.5;
1629: }
1630: d += (hour*3600L + min*60 + sec)/86400.0;
1631:
1632: j += year/4;
1633: j+= 2 - year/100 + year/400;
1634: j += 1720994L + year*365L + (month+1)*30 + (month+1)*3/5 + day;
1635:
1636: d=d+(double)j;
1637: return(d);
1638: }
1639:
1640: /**
1641: * # FUNCTION #
1642: * ユリウス日から年月日時分秒を求める。
1643: * ただしグレゴリオ歴であることが前提
1644: * 日数.時刻のdouble型で与えたユリウス日から、日付、時刻の文字列ポインタの
1645: * 位置に年月日、時分秒をセットする。
1646: * 計算結果がグリゴリオ歴でなければ-1を返す。
1647: * http://alfin.mine.utsunomiya-u.ac.jp/~niy/algo/j/jd2ut.html を修正して利用
1648: */
1649: static int jd2ut(char *date, char *time, double d)
1650: {
1651: long c, k, e, s;
1652: int year,month,day,hour,min,sec;
1653: long j;
1654:
1655: j=(long)floor(d);
1656: d=d-(double)j;
1657:
1658: if (d >= 0.5) {
1659: j++;
1660: d -= 0.5;
1661: } else d += 0.5;
1662:
1663: if (j >= 2299161) j = j + 1 + (j-1867216)/36524 - (j-1867216)/146096;
1664: j += 1524;
1665:
1666: c = (j - 122.1)/365.25;
1667: k = 365L*c + c/4;
1668: e = (j - k)/30.6001;
1669:
1670: year = c - 4716;
1671: month = e - 1;
1672: if (month > 12) {
1673: (month) -= 12;
1674: (year)++;
1675: }
1676: day = j - k - (long)(30.6*e);
1677:
1678: s = d * 86400 + 0.5;
1679: hour = s / 3600;
1680: min = (s % 3600) / 60;
1681: sec = s % 60;
1682:
1683: sprintf(date,"%04d%02d%02d",year,month,day);
1684: sprintf(time,"%02d%02d%02d",hour,min,sec);
1685:
1686: /*グレゴリオ歴かどうか判定*/
1687: if( (year)*366+(month)*31+(day) < 1582*366+10*31+15 ) {
1688: return(-1);
1689: }else{
1690: return(0);
1691: }
1692: }
1693:
1694: /**
1695: * # FUNCTION #
1696: * 日付から曜日番号を求める(ツェラーの公式)。
1697: * 0:日, 1:月, 2:火, 3:水, 4:木, 5:金, 6:土
1698: * 出所:平林雅英「C言語によるプログラム辞典第1巻」,技術評論社,平成4年,p292.
1699: */
1700: static int dayweek(char *date)
1701: {
1702: char buf[5];
1703: int year,month,day;
1704:
1705: strncpy(buf,date ,4); buf[4]='\0'; year =atoi(buf);
1706: strncpy(buf,date+4,2); buf[2]='\0'; month=atoi(buf);
1707: strncpy(buf,date+6,2); buf[2]='\0'; day =atoi(buf);
1708:
1709: if(month<=2) year--,month+=12;
1710: return( (year+year/4-year/100+year/400+(13*month+8)/5+day)%7 );
1711: }
1712:
1713: /**
1714: * # FUNCTION #
1715: * 日付から、その年の1月1日からの経過日数求める。
1716: */
1717: static int day365(char *date)
1718: {
1719: char base[9];
1720: double fJD;
1721: double tJD;
1722:
1723: strncpy(base,date,4); base[4]='\0';
1724: strcat(base,"0101");
1725: fJD=ut2jd(base,"000000");
1726: tJD=ut2jd(date,"000000");
1727:
1728: return( (int)tJD-(int)fJD );
1729: }
1730:
1731:
1732: /**
1733: * # FUNCTION #
1734: * ut2jd関数
1735: * 与え方: ud2jd(日付,時刻)
1736: * 「日付」の「時刻」をユリウス通日に変換し、その値を返す。
1737: * ユリウス通日とは、整数部にBC4712年1月1日正午からの経過日数をもち、
1738: * 小数部にあまりの時間をもった実数である。
1739: * ただし、グレゴリオ歴の範囲内でない日付は無効としNULLを返す。
1740: * ex. 1991年6月15日0時0分0秒 -> 2448422.5
1741: */
1742: static MssValue cal_dt2jd(struct mssCal *cal)
1743: {
1744: MssValue v;
1745:
1746: char *v0;
1747: char *v1;
1748:
1749: mssVinit(&v,DBL);
1750:
1751: if(cal->arg[0].val[0].nul){
1752: MssVnull(v);
1753: return(v);
1754: }
1755: v0 =cal->arg[0].val[0].v.s;
1756: v1 =cal->arg[1].val[0].v.s;
1757:
1758: if(!validDate(v0) || !validTime(v1)){
1759: MssVnull(v);
1760: return(v);
1761: }
1762:
1763: v.v.d=ut2jd(v0,v1);
1764: return(v);
1765: }
1766:
1767: /**
1768: * # FUNCTION #
1769: * jd2date関数
1770: * 与え方: jd2date(ユリウス通日)
1771: * 「ユリウス通日」から日付を計算しその値を返す。
1772: * ex. 2448422.5 -> 19910615
1773: */
1774: static MssValue cal_jd2date(struct mssCal *cal)
1775: {
1776: MssValue v;
1777: char bufD[9];
1778: char bufT[7];
1779:
1780: mssVinit(&v,STR);
1781:
1782: if(cal->arg[0].val[0].nul){
1783: MssVnull(v);
1784: return(v);
1785: }
1786:
1787: if(-1 == jd2ut(bufD,bufT,cal->arg[0].val[0].v.d)){
1788: MssVnull(v);
1789: return(v);
1790: }
1791:
1792: v.v.s=mssStrdup(bufD);
1793: setStrMalAdd(v.v.s);
1794: return(v);
1795: }
1796:
1797: /**
1798: * # FUNCTION #
1799: * jd2time関数
1800: * 与え方: jd2time(ユリウス通日)
1801: * 「ユリウス通日」から時刻を計算しその値を返す。
1802: * ex. 2448422.5 -> 19910615
1803: */
1804: static MssValue cal_jd2time(struct mssCal *cal)
1805: {
1806: MssValue v;
1807: char bufD[9];
1808: char bufT[7];
1809:
1810: mssVinit(&v,STR);
1811:
1812: if(cal->arg[0].val[0].nul){
1813: MssVnull(v);
1814: return(v);
1815: }
1816:
1817: if(-1 == jd2ut(bufD,bufT,cal->arg[0].val[0].v.d)){
1818: MssVnull(v);
1819: return(v);
1820: }
1821:
1822: v.v.s=mssStrdup(bufT);
1823: setStrMalAdd(v.v.s);
1824: return(v);
1825: }
1826:
1827:
1828: /**
1829: * # FUNCTION #
1830: * leapyear関数
1831: * 与え方: leapyear(日付)
1832: * 「日付」の年が閏年であれば1を、そうでなければ0を返す。
1833: */
1834: static MssValue cal_leapyear(struct mssCal *cal)
1835: {
1836: MssValue v;
1837:
1838: char buf[5];
1839: char *v0;
1840: int year;
1841:
1842: mssVinit(&v,DBL);
1843:
1844: if(cal->arg[0].val[0].nul){
1845: MssVnull(v);
1846: return(v);
1847: }
1848: v0=cal->arg[0].val[0].v.s;
1849:
1850: if(!validDate(v0)){
1851: MssVnull(v);
1852: return(v);
1853: }
1854:
1855: strncpy(buf,v0,4);
1856: buf[4]='\0';
1857: year=atoi(buf);
1858:
1859: v.v.d=(double)( (year%4==0 && year%100!= 0) || year%400==0 );
1860: return(v);
1861: }
1862:
1863: /**
1864: * # FUNCTION #
1865: * datefmt関数
1866: * 与え方: datefmt(日付,フォーマット)
1867: * 「日付」文字列をフォーマットに従い変換し、その値を返す。
1868: * 日付は8桁の文字列(ex.20030520)で与えられる。
1869: * フォーマットには任意の文字列を与えることができる。
1870: * ただし、フォーマットの中の空白文字類は全て"_"に変換される。
1871: * 以下の特殊記号列は、日付を特定の文字列に変換する。
1872: *
1873: * 記号 意味 例(20030514) 例(20030105)
1874: * %Y 年 2003 2003
1875: * %M 月 05 01
1876: * %m 英語月名 May Jan
1877: * %D 日 20 05
1878: * %d 1月1日からの経過日数 123 4
1879: * %w 週番号(1月1日を第1週開始日とする) 20 1
1880: * %s その週の開始日付 20030514 20030101
1881: * %W 曜日番号 2 0
1882: * (0:日,1:月,2:火,3:水,4:木,5:金,6:土)
1883: * 曜日の算出にはツェラーの公式を用いている
1884: * %e 英語曜日(Sun,Mon,Tsu,Wed,Thu,Fri,Sat) Tue Sun
1885: * %E 曜日番号+英語曜日 2Tue 0Sun
1886: * %j 日本語曜日(日月火水木金土) 火 日
1887: * %J 曜日番号+日本語曜日 2火 0日
1888: * %% %を出力 % %
1889: *
1890: * 例)
1891: * datefmt("20030514","%Y年%M月%D日") -> 2003年05月14日
1892: */
1893: static MssValue cal_datefmt(struct mssCal *cal)
1894: {
1895: MssValue v;
1896: struct mssStrings *hs;
1897: struct tm *lct;
1898: time_t caltime;
1899: int fmtlen;
1900: char buf[10];
1901: char date[9];
1902: char time[7];
1903: char *v0;
1904: char *v1;
1905: int dow;
1906: int i;
1907: int tmp;
1908: char *wday1[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
1909: char *wday2[]={"日","月","火","水","木","金","土"};
1910: char *emon[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
1911: mssVinit(&v,STR);
1912:
1913: hs=mssInitStrings();
1914:
1915: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
1916: MssVnull(v);
1917: return(v);
1918: }
1919: v0 =cal->arg[0].val[0].v.s;
1920: v1 =cal->arg[1].val[0].v.s;
1921:
1922: if(!validDate(v0)){
1923: MssVnull(v);
1924: return(v);
1925: }
1926:
1927: fmtlen=strlen(v1);
1928: if(fmtlen>=MssFieldMaxLen){
1929: MssVnull(v);
1930: return(v);
1931: }
1932: for(i=0; i<fmtlen; i++){
1933: if(isspace(*(v1+i))) *(v1+i)='_';
1934: }
1935:
1936: caltime = mssStrToTime(cal->arg[0].val[0].v.s);
1937: if(caltime == -1){
1938: MssVnull(v);
1939: return(v);
1940: }else{
1941: lct = localtime(&caltime);
1942: v.v.d = lct->tm_wday;
1943: }
1944:
1945: i=0;
1946: while(*v1!='\0' && i<MssFieldMaxLen-4){
1947: if(*v1=='%'){
1948: switch(*(v1+1)){
1949: case 'Y':
1950: strncpy(buf,v0,4); buf[4]='\0';
1951: mssCatStrings(hs,buf);
1952: v1=v1+2;
1953: break;
1954: case 'M':
1955: strncpy(buf,v0+4,2); buf[2]='\0';
1956: mssCatStrings(hs,buf);
1957: v1=v1+2;
1958: break;
1959: case 'm':
1960: strncpy(buf,v0+4,2); buf[2]='\0';
1961: mssCatStrings(hs,emon[atoi(buf)-1]);
1962: v1=v1+2;
1963: break;
1964: case 'D':
1965: strncpy(buf,v0+6,2); buf[2]='\0';
1966: mssCatStrings(hs,buf);
1967: v1=v1+2;
1968: break;
1969: case 'd': /*1月1日からの経過日数 */
1970: sprintf(buf,"%d",day365(v0));
1971: mssCatStrings(hs,buf);
1972: v1=v1+2;
1973: break;
1974: case 'w': /*週番号*/
1975: sprintf(buf,"%d",day365(v0)/7);
1976: mssCatStrings(hs,buf);
1977: v1=v1+2;
1978: break;
1979: case 's': /*週開始日付*/
1980: tmp=day365(v0)%7;
1981: jd2ut(date,time,ut2jd(v0,"000000")-(double)tmp);
1982: mssCatStrings(hs,date);
1983: v1=v1+2;
1984: break;
1985: case 'W': /*曜日番号*/
1986: dow=(int)dayweek(v0);
1987: sprintf(buf,"%d",dow);
1988: mssCatStrings(hs,buf);
1989: v1=v1+2;
1990: break;
1991: case 'e': /*英語曜日*/
1992: dow=(int)dayweek(v0);
1993: mssCatStrings(hs,wday1[dow]);
1994: v1=v1+2;
1995: break;
1996: case 'E': /*曜日番号+英語曜日*/
1997: dow=(int)dayweek(v0);
1998: sprintf(buf,"%d%s",dow,wday1[dow]);
1999: mssCatStrings(hs,buf);
2000: v1=v1+2;
2001: break;
2002: case 'j': /*日本語曜日*/
2003: dow=(int)dayweek(v0);
2004: mssCatStrings(hs,wday2[dow]);
2005: v1=v1+2;
2006: break;
2007: case 'J': /*曜日番号+日本語曜日 */
2008: dow=(int)dayweek(v0);
2009: sprintf(buf,"%d%s",dow,wday2[dow]);
2010: mssCatStrings(hs,buf);
2011: v1=v1+2;
2012: break;
2013: case '%': /*%*/
2014: buf[0]='%'; buf[1]='\0';
2015: mssCatStrings(hs,buf);
2016: v1=v1+2;
2017: break;
2018: default:
2019: mssCatnStrings(hs,v1,1);
2020: v1++;
2021: break;
2022: }
2023: }else{
2024: mssCatnStrings(hs,v1,1);
2025: v1++;
2026: }
2027: }
2028: v.v.s=mssStrdup(hs->str);
2029: setStrMalAdd(v.v.s);
2030: mssFreeStrings(hs);
2031: return(v);
2032: }
2033:
2034: /**
2035: * # FUNCTION #
2036: * timefmt関数
2037: * 与え方: timefmt(時刻,フォーマット)
2038: * 「時刻」文字列をフォーマットに従い変換し、その値を返す。
2039: * 時刻は6桁の文字列(ex.150257)で与えられる。
2040: * フォーマットには任意の文字列を与えることができる。
2041: * ただし、フォーマットの中の空白文字類は全て"_"に変換される。
2042: * 以下の特殊記号列は、時刻を特定の文字列に変換する。
2043: *
2044: * 記号 意味 例(150257) 例(101101)
2045: * %H 時(24時間表記) 15 10
2046: * %h 時(12時間表記) 3 10
2047: * %e AM or PM PM AM
2048: * %j 午前 or 午後 午後 午前
2049: * %M 分 02 11
2050: * %S 秒 57 01
2051: * %% %を出力 % %
2052: *
2053: * 例)
2054: * timefmt("101101","%H:%M:%S") -> 10:11:01
2055: * timefmt("150257","%j%h:%M:%S") -> 午後03:92:57
2056: */
2057: static MssValue cal_timefmt(struct mssCal *cal)
2058: {
2059: MssValue v;
2060: struct mssStrings *hs;
2061: int fmtlen;
2062: char buf[20];
2063: char hour[3];
2064: char minute[3];
2065: char second[3];
2066: char *v0;
2067: char *v1;
2068: int i;
2069: mssVinit(&v,STR);
2070:
2071: hs=mssInitStrings();
2072:
2073: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
2074: MssVnull(v);
2075: return(v);
2076: }
2077: v0 =cal->arg[0].val[0].v.s;
2078: v1 =cal->arg[1].val[0].v.s;
2079:
2080: if(!validTime(v0)){
2081: MssVnull(v);
2082: return(v);
2083: }
2084:
2085: fmtlen=strlen(v1);
2086: if(fmtlen>=MssFieldMaxLen){
2087: MssVnull(v);
2088: return(v);
2089: }
2090: for(i=0; i<fmtlen; i++){
2091: if(isspace(*(v1+i))) *(v1+i)='_';
2092: }
2093:
2094: strncpy(hour ,v0 ,2); hour[2] ='\0';
2095: strncpy(minute,v0+2,2); minute[2]='\0';
2096: strncpy(second,v0+4,2); second[2]='\0';
2097: i=0;
2098: while(*v1!='\0' && i<MssFieldMaxLen-2){
2099: if(*v1=='%'){
2100: switch(*(v1+1)){
2101: case 'H':
2102: mssCatStrings(hs,hour);
2103: v1=v1+2;
2104: break;
2105: case 'h':
2106: sprintf(buf,"%02d",(atoi(hour)-1)%12+1);
2107: mssCatStrings(hs,buf);
2108: v1=v1+2;
2109: break;
2110: case 'e':
2111: if(atoi(hour)<12) sprintf(buf,"AM");
2112: else sprintf(buf,"PM");
2113: mssCatStrings(hs,buf);
2114: v1=v1+2;
2115: break;
2116: case 'j':
2117: if(atoi(hour)<12) sprintf(buf,"午前");
2118: else sprintf(buf,"午後");
2119: mssCatStrings(hs,buf);
2120: v1=v1+2;
2121: break;
2122: case 'M':
2123: mssCatStrings(hs,minute);
2124: v1=v1+2;
2125: break;
2126: case 'S':
2127: mssCatStrings(hs,second);
2128: v1=v1+2;
2129: break;
2130: case '%': /*%*/
2131: buf[0]='%'; buf[1]='\0';
2132: mssCatStrings(hs,buf);
2133: v1=v1+2;
2134: break;
2135: default:
2136: mssCatnStrings(hs,v1,1);
2137: v1++;
2138: break;
2139: }
2140: }else{
2141: mssCatnStrings(hs,v1,1);
2142: v1++;
2143: }
2144: }
2145: v.v.s=mssStrdup(hs->str);
2146: setStrMalAdd(v.v.s);
2147: mssFreeStrings(hs);
2148: return(v);
2149: }
2150:
2151: /**
2152: * # FUNCTION #
2153: * day関数
2154: * 与え方: day(日付1,日付2)
2155: * 「日付1」から「日付2」までの日数を返す。
2156: * 扱うことのできる日付は1582年10月15日〜9999年12月31日まで。
2157: */
2158: static MssValue cal_day(struct mssCal *cal)
2159: {
2160: MssValue v;
2161:
2162: char *v0;
2163: char *v1;
2164: double JD0;
2165: double JD1;
2166:
2167: mssVinit(&v,DBL);
2168:
2169: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
2170: MssVnull(v);
2171: return(v);
2172: }
2173: v0 =cal->arg[0].val[0].v.s;
2174: v1 =cal->arg[1].val[0].v.s;
2175:
2176: if(!validDate(v0) || !validDate(v1)){
2177: MssVnull(v);
2178: return(v);
2179: }
2180:
2181: JD0=ut2jd(v0,"000000");
2182: JD1=ut2jd(v1,"000000");
2183:
2184: v.v.d = JD0-JD1;
2185: return(v);
2186: }
2187:
2188: /**
2189: * # FUNCTION #
2190: * time関数
2191: * 与え方: time(時刻1,時刻2)
2192: * 「時刻1」から「時刻2」までの秒数を返す。
2193: */
2194: static MssValue cal_time(struct mssCal *cal)
2195: {
2196: MssValue v;
2197:
2198: time_t fSec;
2199: time_t tSec;
2200: struct tm fTm;
2201: struct tm tTm;
2202:
2203: char fBuf[20];
2204: char tBuf[20];
2205: char *v0;
2206: char *v1;
2207: mssVinit(&v,DBL);
2208:
2209: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
2210: MssVnull(v);
2211: return(v);
2212: }
2213: v0 =cal->arg[0].val[0].v.s;
2214: v1 =cal->arg[1].val[0].v.s;
2215:
2216: if(!validTime(v0) || !validTime(v1)){
2217: MssVnull(v);
2218: return(v);
2219: }
2220:
2221: fTm.tm_year =-1900+2001 ; tTm.tm_year =-1900+2001;
2222: fTm.tm_mon =-1+1 ; tTm.tm_mon =-1+1;
2223: fTm.tm_mday =1 ; tTm.tm_mday =1;
2224: fTm.tm_isdst=-1 ; tTm.tm_isdst=-1;
2225:
2226: strncpy(fBuf,v0,2); fBuf[2]='\0';
2227: fTm.tm_hour=atoi(fBuf);
2228:
2229: strncpy(tBuf,v1,2); tBuf[2]='\0';
2230: tTm.tm_hour=atoi(tBuf);
2231:
2232: strncpy(fBuf,v0+2,2); fBuf[2]='\0';
2233: fTm.tm_min=atoi(fBuf);
2234:
2235: strncpy(tBuf,v1+2,2); tBuf[2]='\0';
2236: tTm.tm_min=atoi(tBuf);
2237:
2238: strncpy(fBuf,v0+4,2); fBuf[2]='\0';
2239: fTm.tm_sec=atoi(fBuf);
2240:
2241: strncpy(tBuf,v1+4,2); tBuf[2]='\0';
2242: tTm.tm_sec=atoi(tBuf);
2243:
2244: fSec=mktime(&fTm);
2245: tSec=mktime(&tTm);
2246: if( fSec==(time_t)-1 || tSec==(time_t)-1 ){
2247: MssVnull(v);
2248: return(v);
2249: }
2250: v.v.d = (double)difftime(fSec,tSec);
2251: return(v);
2252: }
2253:
2254: /**
2255: * # FUNCTION #
2256: * today()
2257: * 現在の日付を返す。
2258: */
2259: static MssValue cal_today(struct mssCal *cal)
2260: {
2261: MssValue v;
2262: struct tm *tp;
2263: long Tim;
2264: mssVinit(&v,STR);
2265:
2266: time(&Tim);
2267: tp=localtime(&Tim);
2268: v.v.s=mssMalloc(9,"cal_today");
2269: sprintf(v.v.s,"%04d%02d%02d",tp->tm_year+1900,tp->tm_mon+1,tp->tm_mday);
2270: setStrMalAdd(v.v.s);
2271: return(v);
2272: }
2273:
2274: /**
2275: * # FUNCTION #
2276: * now関数
2277: * 与え方: now()
2278: * 現在の時刻を返す。
2279: */
2280: static MssValue cal_now(struct mssCal *cal)
2281: {
2282: MssValue v;
2283: struct tm *tp;
2284: long Tim;
2285: mssVinit(&v,STR);
2286:
2287: time(&Tim);
2288: tp=localtime(&Tim);
2289: v.v.s=mssMalloc(7,"cal_now");
2290: sprintf(v.v.s,"%02d%02d%02d",tp->tm_hour,tp->tm_min,tp->tm_sec);
2291: setStrMalAdd(v.v.s);
2292: return(v);
2293: }
2294:
2295: /**
2296: * # FUNCTION #
2297: * age関数
2298: * 与え方: age(日付1,日付2)
2299: * 年齢を返す。言い替えれば、日付1から日付2までの経過年数を返す。
2300: */
2301: static MssValue cal_age(struct mssCal *cal)
2302: {
2303: MssValue v;
2304: int age;
2305: int y1,y2,m1,m2,d1,d2;
2306: char *v0;
2307: char *v1;
2308: char buf[20];
2309: char buf2[20];
2310: mssVinit(&v,DBL);
2311:
2312: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
2313: MssVnull(v);
2314: return(v);
2315: }
2316: v0 =cal->arg[0].val[0].v.s;
2317: v1 =cal->arg[1].val[0].v.s;
2318:
2319: if(!validDate(v0) || !validDate(v1)){
2320: MssVnull(v);
2321: return(v);
2322: }
2323:
2324: strncpy(buf,v0,4);
2325: buf[4]='\0';
2326: y1 = atoi(buf);
2327:
2328: strncpy(buf2,v1,4);
2329: buf2[4]='\0';
2330: y2 = atoi(buf2);
2331:
2332: strncpy(buf,v0+4,2);
2333: buf[2]='\0';
2334: m1 = atoi(buf);
2335:
2336: strncpy(buf2,v1+4,2);
2337: buf2[2]='\0';
2338: m2 = atoi(buf2);
2339:
2340: strncpy(buf,v0+6,2);
2341: buf[2]='\0';
2342: d1 = atoi(buf);
2343:
2344: strncpy(buf2,v1+6,2);
2345: buf2[2]='\0';
2346: d2 = atoi(buf2);
2347:
2348: age = y1 - y2;
2349: if(m1 < m2){
2350: age--;
2351: }else{
2352: if(m1 == m2){
2353: if(d1 < d2){
2354: age--;
2355: }
2356: }
2357: }
2358: v.v.d = (double)age;
2359: return(v);
2360: }
2361:
2362: /**
2363: * # FUNCTION #
2364: * dayadd関数
2365: * 与え方: dayadd(日付,日数)
2366: * 「日付」に「日数」を加えた日付を返す。
2367: */
2368: static MssValue cal_dayadd(struct mssCal *cal)
2369: {
2370:
2371: MssValue v;
2372: char bufD[10];
2373: char bufT[10];
2374: char *v0;
2375: double jd;
2376: mssVinit(&v,STR);
2377:
2378: if(cal->arg[0].val[0].nul || cal->arg[1].val[0].nul){
2379: MssVnull(v);
2380: return(v);
2381: }
2382:
2383: v0 =cal->arg[0].val[0].v.s;
2384: if(!validDate(v0)){
2385: MssVnull(v);
2386: return(v);
2387: }
2388:
2389: jd=ut2jd(v0,"000000");
2390: jd+=cal->arg[1].val[0].v.d;
2391: jd2ut(bufD,bufT,jd);
2392: v.v.s=mssStrdup(bufD);
2393: setStrMalAdd(v.v.s);
2394: return(v);
2395: }
2396:
2397: /**
2398: * # FUNCTION #
2399: * timeadd関数
2400: * 与え方: timeadd(時刻,秒数)
2401: * 「時刻」に秒数を加えた時刻を返す。
2402: */
2403: static MssValue cal_timeadd(struct mssCal *cal)
2404: {
2405:
2406: MssValue v;
2407: char buf[3];
2408: char *vt;
2409: struct tm time;
2410: struct tm *timeR;
2411: time_t t;
2412: mssVinit(&v,STR);
2413:
2414: if(cal->arg[0].val[0].nul||cal->arg[1].val[0].nul){
2415: MssVnull(v);
2416: return(v);
2417: }
2418: vt =cal->arg[0].val[0].v.s;
2419:
2420: if(!validTime(vt)){
2421: MssVnull(v);
2422: return(v);
2423: }
2424:
2425: time.tm_year = -1900+2001;
2426: time.tm_mon = -1+1;
2427: time.tm_mday = 1;
2428:
2429: /*時*/
2430: strncpy(buf,vt+0,2); buf[2]='\0';
2431: time.tm_hour = atoi(buf);
2432:
2433: /*分*/
2434: strncpy(buf,vt+2,2); buf[2]='\0';
2435: time.tm_min = atoi(buf);
2436:
2437: /*秒*/
2438: strncpy(buf,vt+4,2); buf[2]='\0';
2439: time.tm_sec = atoi(buf);
2440:
2441: /*季節調整無効*/
2442: time.tm_isdst=-1;
2443:
2444: /*暦時間計算*/
2445: t=mktime(&time);
2446:
2447: t += (int)cal->arg[1].val[0].v.d;
2448: timeR=localtime(&t);
2449:
2450: v.v.s= mssMalloc(sizeof(char)*16,"timeadd");
2451: sprintf(v.v.s,"%02d%02d%02d", timeR->tm_hour, timeR->tm_min, timeR->tm_sec);
2452: setStrMalAdd(v.v.s);
2453: return(v);
2454: }
2455:
2456:
2457: /**
2458: * # FUNCTION #
2459: * line関数
2460: * 与え方: line()
2461: * 現在処理中の行番号を返す。
2462: */
2463: static MssValue cal_line(struct mssCal *cal)
2464: {
2465: MssValue v;
2466: mssVinit(&v,DBL);
2467: v.v.d = (double)mssGV.inCnt;
2468: return(v);
2469: }
2470:
2471: /**
2472: * # FUNCTION #
2473: * keyLine関数
2474: * 与え方: keyLine()
2475: * 現在処理中のキー内行番号を返す。
2476: * キー内行番号とは、キー項目の値が同じ行の中での行番号のことで、異るキー値が
2477: * 始まると、再び1にもどる。
2478: * この関数は"-k"パラメータでキー項目を指定しなければならない。
2479: * また、同じキー値での並びを考慮したければ、"-s"パラメータを利用する。
2480: */
2481: static MssValue cal_keyLine(struct mssCal *cal)
2482: {
2483: MssValue v;
2484: mssVinit(&v,DBL);
2485: v.v.d = (double)mssGV.keyLine;
2486: return(v);
2487: }
2488:
2489: /**
2490: * # FUNCTION #
2491: * keyCnt関数
2492: * 与え方: keyCnt()
2493: * 現在処理中のキーの行数を返す。
2494: * この関数は"-k"パラメータでキー項目を指定しなければならない。
2495: */
2496: static MssValue cal_keyCnt(struct mssCal *cal)
2497: {
2498: MssValue v;
2499: mssVinit(&v,DBL);
2500: v.v.d = (double)mssGV.keyCnt;
2501: return(v);
2502: }
2503:
2504: /**
2505: * # FUNCTION #
2506: * keyNo関数
2507: * 与え方: keyNo()
2508: * 現在処理中のキー番号を返す。
2509: * キー番号は、異るキー値が出現するたびにインクリメントされる。
2510: * この関数は"-k"パラメータでキー項目を指定しなければならない。
2511: */
2512: static MssValue cal_keyNo(struct mssCal *cal)
2513: {
2514: MssValue v;
2515: mssVinit(&v,DBL);
2516: v.v.d = (double)mssGV.keyNo;
2517: return(v);
2518: }
2519:
2520: /**
2521: * # FUNCTION #
2522: * fldCnt関数
2523: * 与え方: fldCnt()
2524: * 現在処理注の項目数を返す。
2525: * 全ての行において、同じ値を返すことになる。
2526: */
2527: static MssValue cal_fldCnt(struct mssCal *cal)
2528: {
2529: MssValue v;
2530: mssVinit(&v,DBL);
2531: v.v.d = (double)mssGV.inFldCnt;
2532: return(v);
2533: }
2534:
2535: /**
2536: * # FUNCTION #
2537: * prvResult関数
2538: * 与え方: prvResult()
2539: * 現在処理中の行の一行前の結果を返す(文字列としてでなくMssValueとして)
2540: * mssReadFRKが読み込み関数の場合: 同一キーにおける先頭行が現在の場合はNULL
2541: * mssReadFldRec,mssReadFRDが読み込み関数の場合: 先頭行の場合はNULL
2542: */
2543: static MssValue cal_prvResult(struct mssCal *cal)
2544: {
2545: MssValue v;
2546:
2547: v=PrvRsl.val;
2548: if(v.vType==STR && !v.nul){
2549: v.v.s=mssStrdup(PrvRsl.val.v.s);
2550: setStrMalAdd(v.v.s);
2551: }
2552:
2553: return(v);
2554: }
2555:
2556: /**
2557: * # FUNCTION #
2558: * topResult関数
2559: * 与え方: topResult()
2560: * 先頭行の結果を返す(文字列としてでなくMssValueとして)
2561: * mssReadFRKが読み込み関数の場合: 同一キーにおける先頭行の結果
2562: * mssReadFldRec,mssReadFRDが読み込み関数の場合: データの一行目の結果
2563: */
2564: static MssValue cal_topResult(struct mssCal *cal)
2565: {
2566: MssValue v;
2567:
2568: v=TopRsl.val;
2569: if(v.vType==STR && !v.nul){
2570: v.v.s=mssStrdup(TopRsl.val.v.s);
2571: setStrMalAdd(v.v.s);
2572: }
2573: return(v);
2574: }
2575:
2576: /**
2577: * # FUNCTION #
2578: * prvField関数
2579: * 与え方: prvField(項目名)
2580: * 現在処理中の行の一行前の指定の「項目名」の値を返す。
2581: * (文字列としてでなくMssValueとして)
2582: * mssReadFRKが読み込み関数の場合: 同一キーにおける先頭行が現在の場合はNULL
2583: * mssReadFldRec,mssReadFRDが読み込み関数の場合: 先頭行の場合はNULL
2584: */
2585: static MssValue cal_prvField(struct mssCal *cal)
2586: {
2587: MssValue v;
2588: char *str;
2589:
2590: mssVinit(&v,STR);
2591: if(PrvFld.pnt[0]==NULL){
2592: MssVnull(v);
2593: }else{
2594: str=PrvFld.pnt[(*(cal->arg[0].flds->fi))->num];
2595: if(*str==MssNullChr){
2596: MssVnull(v);
2597: }else{
2598: v.v.s=mssStrdup(str);
2599: setStrMalAdd(v.v.s);
2600: }
2601: }
2602: return(v);
2603: }
2604:
2605: /**
2606: * # FUNCTION #
2607: * topField関数
2608: * 与え方: topField(項目名)
2609: * 先頭行の指定の「項目名」の値を返す(文字列としてでなくMssValueとして)
2610: * mssReadFRKが読み込み関数の場合: 同一キーにおける先頭行の結果
2611: * mssReadFldRec,mssReadFRDが読み込み関数の場合: データの一行目の結果
2612: */
2613: static MssValue cal_topField(struct mssCal *cal)
2614: {
2615: MssValue v;
2616: char *str;
2617:
2618: mssVinit(&v,STR);
2619: if(TopFld.pnt[0]==NULL){
2620: MssVnull(v);
2621: }else{
2622: str=TopFld.pnt[(*(cal->arg[0].flds->fi))->num];
2623: if(*str==MssNullChr){
2624: MssVnull(v);
2625: }else{
2626: v.v.s=mssStrdup(str);
2627: setStrMalAdd(v.v.s);
2628: }
2629: }
2630: return(v);
2631: }
2632:
2633: /**
2634: * # FUNCTION #
2635: * lineCmp関数
2636: * 与え方: lineCmp(項目名1,項目名2,...,項目名n)
2637: * 指定されたn個の項目について、現在処理中の行と一行前の行の値を比較し、
2638: * 全て同じなら0を返す。現在行<前行なら-1,現在行>前行なら1を返す。
2639: * この関数は読み込み関数の種類に関係なく同じ動作をする。
2640: * 比較する項目にNULL値が含まれていればNULL値を返す。
2641: * 先頭行は、現在行>前行として扱う(すなわち1を返す)。
2642: */
2643: static MssValue cal_lineCmp(struct mssCal *cal)
2644: {
2645:
2646: int i,j;
2647: int cmp;
2648: int fldNo;
2649: MssValue v;
2650:
2651: mssVinit(&v,DBL);
2652:
2653: v.v.d=0;
2654:
2655: /*最初行の時は異なる行として返す*/
2656: if(mssGV.inCnt==1){
2657: for(i=0; i<cal->argCnt; i++){
2658: for(j=0; j<cal->arg[i].valCnt; j++){
2659: if(cal->arg[i].val[j].nul){
2660: MssVnull(v);
2661: return(v);
2662: }
2663: }
2664: }
2665: v.v.d=1;
2666: return(v);
2667: }
2668:
2669: for(i=0; i<cal->argCnt; i++){
2670: for(j=0; j<cal->arg[i].valCnt; j++){
2671: fldNo=MssFlds2num(cal->arg[i].flds,i);
2672: if(cal->arg[i].val[j].nul || MssIsNull(PrvFld.pnt[fldNo]) ){
2673: MssVnull(v);
2674: return(v);
2675: }
2676: cmp=strcmp(cal->arg[i].val[j].v.s,PrvFld.pnt[fldNo]);
2677: if(cmp<0) {
2678: v.v.d=-1;
2679: return(v);
2680: }
2681: if(cmp>0) {
2682: v.v.d=1;
2683: return(v);
2684: }
2685: }
2686: }
2687: v.v.d=0;
2688: return(v);
2689: }
2690:
2691: /**
2692: * 利用可能関数の設定
2693: * 引数の最大個数はMaxCalArgで定義
2694: * name : 関数名もしくは演算記号
2695: * type : 0:関数 1:演算子
2696: * priority : 演算子の演算優先順位(数字が低い方が優先順位が高い)
2697: * 関数の優先順位は最も高いので、常に"1"とする。
2698: * argType: 引数の型 N:数値,S:文字列,X:不定,M:前引数型の0個以上の繰り返し
2699: * retType: 返す値の型 N:数値, S:文字列, X:不定
2700: * procType : 利用可能なデータの読み込みタイプ
2701: * 現在のところ、readFldRec,readFRD,readFRKの三つのみ対応している。
2702: * 3ビット列の右からreadFldRec,readFRD,readFRKの順で、
2703: * 対応する箇所にビットをたてる。
2704: * 1 : readFldRec
2705: * 2 : readFRD
2706: * 4 : readFRK
2707: * もし、readFRKの読み込み関数を利用したときのみ利用可能にしたければ
2708: * procTypeは4とする。全ての読み込み関数で利用可能であれば7(1+2+4)
2709: * とする。通常、一行単位の処理のみを行うのであれば7となる。
2710: * functionAddress: 実際の関数アドレス
2711: * priorityは演算子のみ影響する。関数の優先順位もとりあえずここで定義しているが
2712: *
2713: * 注1) "-"演算子と"-eq"演算子。
2714: * コマンドの実行時に指定された計算式の演算子を探す際には
2715: * 以下のリストに出現順序で文字列マッチングをしている。もし、"-"演算子
2716: * が"-eq"演算子より先に登録されていれば、たとえ引数で"-eq"を指定していても
2717: * "-"演算子としてマッチングされてしまう。そこで、以下のリスト登録時には
2718: * 同じ先頭文字列を持つ演算子については、全体の文字列長が長い
2719: * 方を先に登録すること。
2720: * また、関数に関してはそのようなことを気づかう必要なし。
2721: *
2722: * 注2) 最後のdummyは、終端の検出のため。実際にはtype==-1で判断している。
2723: * 注3) 演算子の演算優先順位の値(priority)は以下の文献に基づく。
2724: * 平林雅秀「ANCI C/C++事典」,共立出版,1996,p.708.
2725: */
2726: struct Func func[]={
2727: /* name ,type
2728: ,priority
2729: ,argType[],retType
2730: ,procType
2731: ,functionAddress*/
2732: {"*" ,1, 4,{N,N,E} ,N ,7 ,cal_mulOperator},
2733: {"/" ,1, 4,{N,N,E} ,N ,7 ,cal_divOperator},
2734: {"%" ,1, 4,{N,N,E} ,N ,7 ,cal_modOperator},
2735: {"<>" ,1, 7,{N,N,E} ,N ,7 ,cal_neNOperator},
2736: {"<=" ,1, 7,{N,N,E} ,N ,7 ,cal_leNOperator},
2737: {"<" ,1, 7,{N,N,E} ,N ,7 ,cal_ltNOperator},
2738: {">=" ,1, 7,{N,N,E} ,N ,7 ,cal_geNOperator},
2739: {">" ,1, 7,{N,N,E} ,N ,7 ,cal_gtNOperator},
2740: {"==" ,1, 7,{N,N,E} ,N ,7 ,cal_eqNOperator},
2741: {"-le" ,1, 7,{S,S,E} ,N ,7 ,cal_leSOperator},
2742: {"-lt" ,1, 7,{S,S,E} ,N ,7 ,cal_ltSOperator},
2743: {"-ge" ,1, 7,{S,S,E} ,N ,7 ,cal_geSOperator},
2744: {"-gt" ,1, 7,{S,S,E} ,N ,7 ,cal_gtSOperator},
2745: {"-ne" ,1, 7,{S,S,E} ,N ,7 ,cal_neSOperator},
2746: {"-eq" ,1, 7,{S,S,E} ,N ,7 ,cal_eqSOperator},
2747: {"=~" ,1, 7,{S,S,E} ,N ,7 ,cal_regOperator},
2748: {"+" ,1, 5,{N,N,E} ,N ,7 ,cal_addOperator},
2749: {"-" ,1, 5,{N,N,E} ,N ,7 ,cal_subOperator},
2750: {"||" ,1,13,{N,N,E} ,N ,7 ,cal_orOperator},
2751: {"&&" ,1,12,{N,N,E} ,N ,7 ,cal_andOperator},
2752:
2753: {"age" ,0, 1,{S,S,E} ,N ,7 ,cal_age},
2754: {"datefmt" ,0, 1,{S,S,E} ,S ,7 ,cal_datefmt},
2755: {"dayadd" ,0, 1,{S,N,E} ,S ,7 ,cal_dayadd},
2756: {"day" ,0, 1,{S,S,E} ,N ,7 ,cal_day},
2757: {"timefmt" ,0, 1,{S,S,E} ,S ,7 ,cal_timefmt},
2758: {"timeadd" ,0, 1,{S,N,E} ,S ,7 ,cal_timeadd},
2759: {"time" ,0, 1,{S,S,E} ,N ,7 ,cal_time},
2760: {"now" ,0, 1,{E} ,S ,7 ,cal_now},
2761: {"today" ,0, 1,{E} ,S ,7 ,cal_today},
2762: {"dt2jd" ,0, 1,{S,S,E} ,N ,7 ,cal_dt2jd},
2763: {"jd2date" ,0, 1,{N,E} ,S ,7 ,cal_jd2date},
2764: {"jd2time" ,0, 1,{N,E} ,S ,7 ,cal_jd2time},
2765: {"leapyear" ,0, 1,{S,E} ,N ,7 ,cal_leapyear},
2766:
2767: {"sum" ,0, 1,{N,M,E} ,N ,7 ,cal_sum},
2768: {"min" ,0, 1,{N,M,E} ,N ,7 ,cal_min},
2769: {"max" ,0, 1,{N,M,E} ,N ,7 ,cal_max},
2770: {"sqrt" ,0, 1,{N,E} ,N ,7 ,cal_Sqrt},
2771: {"power" ,0, 1,{N,N,E} ,N ,7 ,cal_power},
2772: {"abs" ,0, 1,{N,E} ,N ,7 ,cal_abs},
2773: {"up" ,0, 1,{N,N,E} ,N ,7 ,cal_up},
2774: {"down" ,0, 1,{N,N,E} ,N ,7 ,cal_down},
2775: {"round" ,0, 1,{N,N,E} ,N ,7 ,cal_round},
2776: {"fixdec" ,0, 1,{N,N,E} ,S ,7 ,cal_fixdec},
2777: {"pi" ,0, 1,{E} ,N ,7 ,cal_pi},
2778: {"exp" ,0, 1,{N,E} ,N ,7 ,cal_Exp},
2779: {"ln" ,0, 1,{N,E} ,N ,7 ,cal_ln},
2780: {"log10" ,0, 1,{N,E} ,N ,7 ,cal_log10},
2781: {"log2" ,0, 1,{N,E} ,N ,7 ,cal_log2},
2782: {"log" ,0, 1,{N,N,E} ,N ,7 ,cal_log},
2783:
2784: {"rand" ,0, 1,{N,N,N,E},N ,7 ,cal_rand},
2785: {"nrand" ,0, 1,{N,N,N,E},N ,7 ,cal_nrand},
2786:
2787: {"cat" ,0, 1,{S,M,S,E},S ,7 ,cal_cat},
2788: {"length" ,0, 1,{S,E} ,N ,7 ,cal_length},
2789: {"fix" ,0, 1,{S,N,S,S,E},S ,7 ,cal_fix},
2790: {"right" ,0, 1,{S,N,E} ,S ,7 ,cal_right},
2791: {"left" ,0, 1,{S,N,E} ,S ,7 ,cal_left},
2792: {"substr" ,0, 1,{S,N,N,E},S ,7 ,cal_substr},
2793: {"regexStart" ,0, 1,{S,S,E} ,N ,7 ,cal_regexStart},
2794: {"regexEnd" ,0, 1,{S,S,E} ,N ,7 ,cal_regexEnd},
2795: {"regexLen" ,0, 1,{S,S,E} ,N ,7 ,cal_regexLen},
2796:
2797: {"not" ,0, 1,{N,E} ,N ,7 ,cal_not},
2798: {"if" ,0, 1,{N,X,X,E},X ,7 ,cal_if},
2799: {"isnull" ,0, 1,{S,E} ,N ,7 ,cal_not},
2800:
2801: {"lineCmp" ,0, 1,{S,M,E} ,N ,7 ,cal_lineCmp},
2802:
2803: {"prvField" ,0, 1,{N,E} ,S ,7 ,cal_prvField},
2804: {"topField" ,0, 1,{N,E} ,S ,7 ,cal_topField},
2805: {"prvResult" ,0, 1,{E} ,X ,7 ,cal_prvResult},
2806: {"topResult" ,0, 1,{E} ,X ,7 ,cal_topResult},
2807: {"keyLine" ,0, 1,{E} ,N ,4 ,cal_keyLine},
2808: {"keyCnt" ,0, 1,{E} ,N ,4 ,cal_keyCnt},
2809: {"keyNo" ,0, 1,{E} ,N ,4 ,cal_keyNo},
2810: {"line" ,0, 1,{E} ,N ,7 ,cal_line},
2811: {"fldCnt" ,0, 1,{E} ,N ,7 ,cal_fldCnt},
2812: {"dummy" ,-1,-1,{E} ,E ,0 ,NULL}
2813: };
2814:
2815: /**
2816: * # FUNCTION #
2817: * Func構造体のargType[]をチェックし、argCnt,argMul,mulBcnt,mulAcnt変数を
2818: * セットする。
2819: * 可変引数を表すMは一つしかないことが前提である。
2820: * argCnt : 最低限必要な引数の数
2821: * argMul : 可変引数を含むかどうか
2822: * mulBcnt: 可変引数の前に何個引数があるか
2823: * mulAcnt: 可変引数の後に何個引数があるか
2824: *
2825: * 例えば、argType[]={S,N,S,N,S,M,S,S,S} の時(可変引数を含むとき)
2826: * argCnt =8
2827: * argMul =1
2828: * mulBcnt=4
2829: * mulAcnt=3
2830: *
2831: * 例えば、argType[]={S,N,S} の時(可変引数を含まないとき)
2832: * argCnt =3
2833: * argMul =0
2834: * mulBcnt=0
2835: * mulAcnt=0
2836: */
2837: static void initCalFunc(void)
2838: {
2839: int i,j;
2840:
2841: /*初期化*/
2842: i=0;
2843: while(func[i].type!=-1){
2844: func[i].argCnt =0;
2845: func[i].argMul =0;
2846: func[i].mulBcnt=0;
2847: func[i].mulAcnt=0;
2848: i++;
2849: }
2850:
2851: i=0;
2852: while(func[i].type!=-1){
2853: j=0;
2854: while(func[i].argType[j]!=E){
2855: if(func[i].argType[j]==M){
2856: func[i].argMul =1;
2857: func[i].mulBcnt =j-1;
2858: }
2859: j++;
2860: }
2861:
2862: /*func->argCntは、最低限必要な引数の数 */
2863: if(func[i].argMul) func[i].argCnt=j-1;
2864: else func[i].argCnt=j;
2865:
2866: if(func[i].argMul==1){
2867: func[i].mulAcnt=j-func[i].mulBcnt-2;
2868: }
2869: i++;
2870: }
2871: }
2872:
2873: /**
2874: * # FUNCTION #
2875: * 与えられた文字(文字列)が演算子かどうかを判断する。
2876: * 登録された演算子記号にマッチすれば真(1)、そうでなければ偽(0)を返す。
2877: */
2878: static int cal_isOpe(char *str)
2879: {
2880: int i;
2881:
2882: i=0;
2883: /*演算子のチェック*/
2884: while(func[i].type!=-1){ /*func配列の終端チェック*/
2885: if(func[i].type==1){ /*演算子ならば*/
2886: if( 0==strncmp(func[i].name,str,strlen(func[i].name)) )
2887: return(1);
2888: }
2889: i++;
2890: }
2891: return(0);
2892: }
2893:
2894: /**
2895: * # FUNCTION #
2896: * 与えられた先頭文字列が登録された関数名かどうかを判断する。
2897: * 括弧以外の文字列+"("で関数と判断する(ex. "sum(" )。
2898: * 関数と判断されても、登録されていない関数であればエラー終了する。
2899: * 関数であれば真(1)、そうでなければ偽(0)を返す。
2900: */
2901: static int cal_isFunc(char *str)
2902: {
2903: int i;
2904: int len;
2905: char *parPos; /*括弧の位置*/
2906: char *orgStr;
2907: orgStr=str;
2908:
2909: /*最初の一文字が括弧ということは、それは関数でない*/
2910: if(*str=='(')return(0);
2911:
2912: /*strを走査し'('が出てきたら関数型である。演算子が出て来れば関数でない。*/
2913: while(1){
2914: if(*str=='('){
2915: parPos=str;
2916: break;
2917: }
2918: if(cal_isOpe(str)) return(0);
2919: if(*str=='\0') return(0);
2920: str++;
2921: }
2922:
2923: /*しかし$(の時に限って関数でない*/
2924: if(*(str-1)=='$') return(0);
2925:
2926: /*関数のチェック*/
2927: str=orgStr;
2928: i=0;
2929: while(func[i].type!=-1){ /*func配列の終端チェック*/
2930: if(func[i].type==0){ /*関数ならば*/
2931: len=strlen(func[i].name);
2932: if( 0==strncmp(func[i].name,str,len) ){
2933: if(*(str+len)=='(') return(1);
2934: }
2935: }
2936: i++;
2937: }
2938: *parPos='\0';
2939: mssShowErrMsg("I don't know such a function : %s",str);
2940: mssEnd(mssErrorNoDefault);
2941: return(0);
2942: }
2943:
2944: /**
2945: * # FUNCTION #
2946: * strで与えられた名前の関数、演算子のC関数アドレスを返す。
2947: * 登録がなければエラー終了
2948: */
2949: static struct Func *cal_setFuncAdd(char *str)
2950: {
2951: int len;
2952: int i=0;
2953:
2954: while(1){
2955:
2956: /*関数リストを最後まで読みきったらエラー*/
2957: if(func[i].type==-1)break;
2958:
2959: len=strlen(func[i].name);
2960: if(0==strncmp(str,func[i].name,len)){
2961: return(&func[i]);
2962: }
2963: i++;
2964: }
2965: mssShowErrMsg("I don't know the function:%s\n",str);
2966: mssEnd(mssErrorNoDefault);
2967: return(0);
2968: }
2969:
2970: /**
2971: * # FUNCTION #
2972: * 文字列としての計算式のチェックおよび修正
2973: * チェック事項は、以下のとおり。
2974: * 1) 括弧の対応関係(括弧の数)が正しいか
2975: *
2976: * 修正事項は、以下のとおり。
2977: * 1) 不必要なスペースもしくは改行の除去
2978: *
2979: */
2980: static char *cal_chkCal(char *str)
2981: {
2982: int i;
2983: int parCnt; /*括弧を飛ばすときに括弧のレベルをカウントする変数*/
2984: char *buf; /*チェック後の文字列*/
2985: char *bufTop;
2986:
2987: /*括弧の数をチェック*/
2988: parCnt=0;
2989: for(i=0; i<strlen(str); i++){
2990: if(*(str+i)=='(') parCnt++;
2991: if(*(str+i)==')') parCnt--;
2992: }
2993: if(parCnt!=0){
2994: mssShowErrMsg("mismatch of '(' and ')'\n");
2995: mssEnd(mssErrorNoDefault);
2996: }
2997:
2998: /* 不必要なスペースの除去*/
2999: buf=mssMalloc(sizeof(char)*strlen(str)+1,"chkCal");
3000: bufTop=buf;
3001: while(*str!='\0'){
3002: /* '"'が出現したら次の'"'まで無条件でコピーする*/
3003: if(*str=='"'){
3004: *buf=*str;
3005: buf++; str++;
3006: while(*str!='"' && *str!='\0'){
3007: if(*str!='\n'){
3008: *buf=*str;
3009: buf++; str++;
3010: }
3011: }
3012: if(*str=='\0') {
3013: mssShowErrMsg("mismatch of \"\"");
3014: mssEnd(mssErrorNoDefault);
3015: }
3016: }
3017:
3018: /* '$('が出現したら次の')'まで無条件でコピーする*/
3019: if(*str=='$' && *(str+1)=='('){
3020: *buf=*str; buf++; str++;
3021: *buf=*str; buf++; str++;
3022: while(*str!=')' && *str!='\0'){
3023: if(*str!='\n'){
3024: *buf=*str;
3025: buf++; str++;
3026: }
3027: }
3028: if(*str=='\0') {
3029: mssShowErrMsg("mismatch of '(' and ')'");
3030: mssEnd(mssErrorNoDefault);
3031: }
3032: }
3033:
3034: /*スペースもしくは改行は詰める*/
3035: if(*str!=' ' && *str!='\n'){
3036: *buf=*str;
3037: buf++;
3038: }
3039: str++;
3040: }
3041: *buf='\0';
3042: /*printf("after removing redundant spaces : %s\n",bufTop);*/
3043: return(bufTop);
3044: }
3045:
3046:
3047: /**
3048: * # FUNCTION #
3049: * 演算子もしくは関数のシンボル(str)およびそのアドレスをopeLstに登録する。
3050: */
3051: static char *cal_setOpeTok(struct OpeLst *opeLst, char *str)
3052: {
3053:
3054: opeLst->tbl=mssRealloc(opeLst->tbl, sizeof(struct OpeTbl)*(opeLst->cnt+1),"OpeTok");
3055: (opeLst->tbl+opeLst->cnt)->add=str;
3056: (opeLst->tbl+opeLst->cnt)->num=opeLst->cnt;
3057: (opeLst->tbl+opeLst->cnt)->func=cal_setFuncAdd(str);
3058: str+=strlen((opeLst->tbl+opeLst->cnt)->func->name);
3059: opeLst->cnt++;
3060: return(str);
3061: }
3062:
3063: /**
3064: * # FUNCTION #
3065: * strで与えられた計算式の、演算子もしくは関数のアドレスへのリストを作成する。
3066: * 括弧で囲まれた中の演算子もしくは関数は、対象外とする。
3067: * 例えば、str="($a+$b)/10"の時、括弧内の"+"は対象とされない。
3068: * また、関数の引数に現れる演算子や関数も、対象外とする。
3069: * str="sum($a,$b,sqrt($c),$d+$e)"の時、"sqrt($c)","$d+$e"は評価されない。
3070: * 関数はstr文字列に一切手を加えない
3071: * $a+$b/$c
3072: * + +--- (opeLst->opeTbl+1)->add
3073: * | (opeLst->opeTbl+1)->func
3074: * (opeLst->opeTbl+0)->add : アドレス
3075: * (opeLst->opeTbl+0)->func : 関数へのポインタ
3076: * opeLst->cnt = 2 "+"と"/"で2つの演算子を使っているという意味
3077: */
3078: static void cal_sepOpeTok( struct OpeLst *opeLst, char *str)
3079: {
3080: int opeCnt; /*演算子の数*/
3081: char *orgStr;
3082: char *tmpStr;
3083: int i;
3084: opeLst->cnt=0;
3085: opeLst->tbl=NULL;
3086:
3087: orgStr=str;
3088: /*まず演算子をさがす*/
3089: while(*str!='\0'){
3090:
3091: if(*str=='(') {
3092: str=mssSkipStrBlock(str,'(',')'); /*括弧を飛ばす*/
3093: continue;
3094: }
3095:
3096: if(*str=='"') {
3097: str=mssSkipStrBlock(str,'"','"'); /*"を飛ばす*/
3098: if(str==NULL) {
3099: mssShowErrMsg("mismatch of \"\"");
3100: mssEnd(mssErrorNoDefault);
3101: }
3102: continue;
3103: }
3104: if(cal_isOpe(str)){
3105: str=cal_setOpeTok(opeLst,str); /*opeLstに登録&strを演算子長分増す*/
3106: }else{
3107: str++;
3108: }
3109: }
3110:
3111: /*次に関数をさがす*/
3112: /*関数は先頭かもしくは演算子の次のみ*/
3113: str=orgStr;
3114: opeCnt=opeLst->cnt;
3115:
3116: if(cal_isFunc(str)){
3117: str=cal_setOpeTok(opeLst,str); /*opeLstに登録&strを演算子長分増す*/
3118: }
3119:
3120: for(i=0; i<opeCnt; i++){
3121: tmpStr=(opeLst->tbl+i)->add+strlen((opeLst->tbl+i)->func->name);
3122: if( cal_isFunc(tmpStr) ){
3123: str=cal_setOpeTok(opeLst,tmpStr); /*opeLstに登録&strを演算子長分増す*/
3124: }
3125: }
3126: }
3127:
3128: /**
3129: * # FUNCTION #
3130: * 外側の括弧を外す (a+b) -> a+b , ((a+b)) -> a+b
3131: * 新たに文字列領域を確保することなく、括弧を外した後の文字列先頭アドレスを
3132: * 返す。
3133: */
3134: static char *removePar(char *str)
3135: {
3136:
3137: char *orgStr=str;
3138:
3139: if(*str!='(')return(str);
3140: str=mssSkipStrBlock(str,'(',')');
3141: if(*str=='\0'){
3142: *orgStr='\0';
3143: *(str-1)='\0';
3144: orgStr=removePar(++orgStr);
3145: }
3146: return(orgStr);
3147: }
3148:
3149: /**
3150: * # FUNCTION #
3151: * 優先順位の最も低い演算子もしくは関数を見付ける。
3152: * 優先順位が同じなら出現順序が後の演算子もしくは関数
3153: */
3154: static struct OpeTbl *getLowPriOpe(struct OpeLst *opeLst)
3155: {
3156: int minPri=-1;
3157: int minNum=0;
3158: int i;
3159:
3160: for(i=0; i<opeLst->cnt; i++){
3161: if(minPri<=(opeLst->tbl+i)->func->priority){ /*優先順位が低ければ*/
3162: minPri=(opeLst->tbl+i)->func->priority;
3163: minNum=i;
3164: }
3165: }
3166: return(opeLst->tbl+minNum);
3167: }
3168:
3169: /**
3170: * # FUNCTION #
3171: * 数式を評価し、優先順位に従って、cal構造体のツリーを構築する
3172: * 構築の際には、一つの演算子もしくは関数ごとに再帰呼び出しにて。
3173: * ツリーのレベルの深いノードが優先順位の高い演算もしくは関数である。
3174: * 関数もしくは演算子が一つもなければNULLを返す。
3175: *
3176: * 例1)
3177: * str="$val+10/$unit"
3178: * cal->func=addOperator
3179: * ->argCnt=2
3180: * ->arg[0].str="$val"
3181: * ->arg[1].str="10/$unit"
3182: * ->arg[1].node->func=divOperator
3183: * ->argCnt=2
3184: * ->arrg[0].str="10"
3185: * ->arrg[1].str="$unit"
3186: *
3187: * 例2)
3188: * str="($val+10)/sum($a,$b,$c)"
3189: * cal->func=divOperator
3190: * ->argCnt=2
3191: * ->arg[0].str="$val+10"
3192: * ->arg[0].node->func=addOperator
3193: * ->argCnt=2
3194: * ->arrg[0].str="$val"
3195: * ->arrg[1].str="10"
3196: * ->arg[1].str="sum($a,$b,$c)"
3197: * ->arg[1].node->func=divOperator
3198: * ->argCnt=3
3199: * ->arrg[0].str="$a"
3200: * ->arrg[1].str="$b"
3201: * ->arrg[2].str="$c"
3202: *
3203: * またこの関数では、計算式の関数の引数の数のチェック、また二項演算子であれば、
3204: * 左右に値があるかどうかのチェックも行う。
3205: */
3206: static struct mssCal *cal_sepCal(char *str, struct mssCal *parent)
3207: {
3208:
3209: struct OpeLst opeLst;
3210: struct mssCal *cal;
3211: struct mssCal *argCal;
3212: struct OpeTbl *ope;
3213: char *tmpPos;
3214: char *tmpStr;
3215: char *prePos;
3216: char buf[1024];
3217: int i;
3218:
3219: /*外側の括弧は外す (a+b) -> a+b*/
3220: str=removePar(str);
3221:
3222: /*現在の文字列に関して、並列な演算子を探索し、それらをopeLst構造体にセット*/
3223: cal_sepOpeTok(&opeLst,str);
3224:
3225: /*演算子もしくは関数が無ければNULLでリターン*/
3226: if(opeLst.cnt==0) return(NULL);
3227:
3228: /*優先順位の最も低い演算子を見付ける*/
3229: ope=getLowPriOpe(&opeLst);
3230: /*printf("ope=%s %d\n",ope->add,ope->num);*/
3231:
3232: /*メモリ確保+親ノードとの結合*/
3233: cal=mssCalloc(sizeof(struct mssCal),"sepCal");
3234: cal->parent=parent; /*親ノード*/
3235:
3236: /*最も低い優先順位の演算子によって文字列を2つに分ける*/
3237: /* (a+b)/c -> (a+b)'\0'c*/
3238: /* + +*/
3239: /* | |*/
3240: /* str ope->add*/
3241:
3242: /*&&& 関数の場合
3243: 関数の引数をセット
3244: X='\0'とすると
3245: sum(abc,(a+b),sum(a+b,c))
3246: --->>>
3247: sum(abcX(a+b)Xsum(a+b,c)X
3248: | | | +arg[2]
3249: | + +arg[1]
3250: + arg[0]
3251: ope->add or str
3252: cal->argCnt=3 */
3253: if( ope->func->type == 0 ){
3254: cal->func=ope->func; /*関数のアドレスをセット*/
3255:
3256: /*関数名(をスキップ*/
3257: tmpPos = ope->add;
3258: while( *(tmpPos++)!='(' );
3259:
3260: /* ','によるトークン分解*/
3261: prePos=tmpPos;
3262: cal->argCnt=0;
3263:
3264: if( *prePos != ')' ){ /* 'abc()'引数なしでない場合*/
3265: while(1){
3266: if(*tmpPos=='(') tmpPos=mssSkipStrBlock(tmpPos,'(',')');
3267: if(*tmpPos=='"'){
3268: tmpPos=mssSkipStrBlock(tmpPos,'"','"');
3269: if(tmpPos==NULL) {
3270: mssShowErrMsg("mismatch of \"\"");
3271: mssEnd(mssErrorNoDefault);
3272: }
3273: }
3274:
3275: if(*tmpPos==',' || *tmpPos==')'){
3276: cal->arg[cal->argCnt].str=prePos; /*引数のセット*/
3277: prePos=tmpPos+1;
3278: cal->argCnt++; /*引数の数のインクリメント*/
3279: if(*tmpPos==')'){
3280: *tmpPos='\0';
3281: break;
3282: }else{
3283: *tmpPos='\0';
3284: }
3285: }
3286: tmpPos++;
3287: }
3288: }
3289:
3290: /*引数のチェック*/
3291: if(cal->func->argMul == 0){ /*可変引数でない場合*/
3292: if(cal->func->argCnt != cal->argCnt){
3293: mssShowErrMsg("the number of arguments is wrong in [%s]\n",cal->func->name);
3294: mssEnd(mssErrorNoDefault);
3295: }
3296: }else{
3297: if(cal->argCnt>MaxCalArg){
3298: mssShowErrMsg("the number of arguments must be less than %d in [%s]\n",MaxCalArg,cal->func->name);
3299: mssEnd(mssErrorNoDefault);
3300: }
3301: if(cal->func->argCnt > cal->argCnt){
3302: mssShowErrMsg("the number of arguments is wrong [%s]\n",cal->func->name);
3303: mssEnd(mssErrorNoDefault);
3304: }
3305: }
3306:
3307: /*
3308: &&& 演算子の場合
3309: X='\0'とすると
3310: (a+b)/cX
3311: ->
3312: (a+b)XcX
3313: + |+
3314: arg[0]|
3315: | |arg[1]
3316: str +
3317: ope->add
3318: cal->argCnt=2*/
3319: }else{
3320: /*演算子のアドレスをセット*/
3321: cal->func=ope->func;
3322:
3323: /*一項演算子*/
3324: if(cal->func->argCnt == 1){
3325: /*左側の引数があればエラー*/
3326: if(ope->add!=str){
3327: mssShowErrMsg("一項演算子\"%s\"の左に引数がある\n",cal->func->name);
3328: mssEnd(mssErrorNoDefault);
3329: }
3330:
3331: /*右の引数*/
3332: cal->arg[0].str=ope->add+strlen(cal->func->name);/*演算子の長さ分ずらす */
3333:
3334: /* 引数があるかどうかチェック*/
3335: if(*cal->arg[0].str=='\0'){
3336: mssShowErrMsg("演算子\"%s\"の右の引数がない\n",cal->func->name);
3337: mssEnd(mssErrorNoDefault);
3338: }
3339: cal->argCnt=1;
3340: *ope->add='\0';
3341:
3342: /*二項演算子(二項までしか対応していない)*/
3343: }else{
3344: /*左の引数*/
3345: cal->arg[0].str=str;
3346:
3347: /*右の引数*/
3348: cal->arg[1].str=ope->add+strlen(cal->func->name); /*演算子の長さ分ずらす*/
3349:
3350: /* 引数があるかどうかチェック*/
3351: if(*cal->arg[0].str=='\0'){
3352: mssShowErrMsg("演算子\"%s\"の左の引数がない\n",cal->func->name);
3353: mssEnd(mssErrorNoDefault);
3354: }
3355: if(*cal->arg[1].str=='\0'){
3356: mssShowErrMsg("演算子\"%s\"の右の引数がない\n",cal->func->name);
3357: mssEnd(mssErrorNoDefault);
3358: }
3359: cal->argCnt=2;
3360: *ope->add='\0';
3361: }
3362: }
3363:
3364: /*引数を物理的にコピーする(opeLst.tblをfreeするため)*/
3365: for(i=0; i<cal->argCnt; i++){
3366: tmpStr=cal->arg[i].str;
3367: cal->arg[i].str=mssStrdup(tmpStr);
3368: }
3369: mssFree(opeLst.tbl);
3370:
3371: /*再帰呼出でreallocされてアドレスが変わる可能性があるので*/
3372: /*アドレスを固定するのではなく、現在の番号をローカルに利用する*/
3373: for(i=0; i<cal->argCnt; i++){
3374: strcpy(buf,cal->arg[i].str);
3375: argCal=cal_sepCal(buf,cal); /*再帰Call*/
3376: if(argCal==NULL){
3377: cal->arg[i].type=LEAF;
3378: }else{
3379: cal->arg[i].type=NODE;
3380: cal->arg[i].node=argCal;
3381: }
3382: }
3383: return(cal);
3384: }
3385:
3386: /**
3387: * # FUNCTION #
3388: * 計算式をツリー構造で表示(debug用)。
3389: */
3390: void mssCalShowTree(struct mssCal *cal,int level){
3391:
3392: int i,j;
3393:
3394: for(i=0; i<level; i++){
3395: printf(" ");
3396: }
3397: printf("%s ",cal->func->name);
3398: for(i=0; i<cal->argCnt; i++){
3399: printf("%s",cal->arg[i].str);
3400: switch(cal->arg[i].type){
3401: case FIELD:
3402: printf("[fld:");
3403: for(j=0; j<cal->arg[i].flds->cnt; j++){
3404: printf("%d(%d) ",(*(cal->arg[i].flds->fi+j))->num,cal->arg[i].datType);
3405: }
3406: printf("]");
3407: break;
3408: case CONST:
3409: switch(cal->arg[i].datType){
3410: case N:
3411: printf("[cstnum:%g]",cal->arg[i].constant.v.d); break;
3412: case S:
3413: printf("[cstStr:%s]",cal->arg[i].constant.v.s); break;
3414: case X:
3415: printf("[unknown]"); break;
3416: }
3417: }
3418: printf(" ");
3419: }
3420: printf("\n");
3421:
3422: level++;
3423: for(i=0; i<cal->argCnt; i++){
3424: if(cal->arg[i].type==NODE)
3425: mssCalShowTree(cal->arg[i].node,level);
3426: }
3427: }
3428:
3429:
3430: /**
3431: * # FUNCTION #
3432: * 実引数の位置番号から、その引数のデータ型を返す。
3433: * (可変引数のためにややこしい)
3434: */
3435: static int funcArgType(int argNum,struct mssCal *cal){
3436: if(cal->func->argMul){ /*可変引数が含まれる場合*/
3437: /* S,N,S,N,S,M,S,S,S の時 */
3438: /* ~~~~~~~ */
3439: /* argNumがここの場合 */
3440: if(argNum<cal->func->mulBcnt){
3441: return(cal->func->argType[argNum]);
3442: }
3443: /* S,N,S,N,S,M,S,S,S の時 */
3444: /* ~~~~~ */
3445: /* argNumがここの場合 */
3446: if(argNum>=cal->argCnt - cal->func->mulAcnt){
3447: return(cal->func->argType[argNum-(cal->argCnt-cal->func->argCnt)+1]);
3448: }
3449: /* S,N,S,N,S,M,S,S,S の時 */
3450: /* ~~~ */
3451: /* argNumがここの場合 */
3452: return(cal->func->argType[cal->func->mulBcnt]);
3453: }else{ /*可変引数が含まれていない場合*/
3454: return(cal->func->argType[argNum]);
3455: }
3456: }
3457:
3458: /**
3459: * # FUNCTION #
3460: * 定数と項目変数の評価
3461: * 項目名にワイルドカードが指定されていれば、それも評価する。
3462: * 評価された複数の項目名はcal->arg[i]->fldsにセットされる。
3463: * リーフからトップへ評価し、返す値の型は上位の引数の型に合わせる)
3464: */
3465: static void cal_evalFldsConst(
3466: struct mssCal *cal,
3467: struct mssHeader *hd) { /*項目を番号で指定するかどうか*/
3468:
3469: int i;
3470: char *str;
3471: char *tmpStr;
3472: char *s;
3473:
3474: /*NODEの再帰処理*/
3475: for(i=0; i<cal->argCnt; i++){
3476: if( cal->arg[i].type == NODE){
3477: cal_evalFldsConst(cal->arg[i].node, hd);
3478: }
3479: }
3480:
3481: /*----------------------------------------*/
3482: /*引数の処理 */
3483: /*----------------------------------------*/
3484: for(i=0; i<cal->argCnt; i++){
3485:
3486: /*データタイプをcal->funcからもってくる*/
3487: cal->arg[i].datType=funcArgType(i,cal);
3488: switch(cal->arg[i].type){
3489:
3490: /*引数が関数や演算子を含まない場合*/
3491: case LEAF:
3492: /*項目の場合*/
3493: if( *cal->arg[i].str == '$' ){
3494: if( *(cal->arg[i].str+1) == '(' ){ /*$(Date*)の時*/
3495: tmpStr=mssSkipStrBlock(cal->arg[i].str+1,'(',')');
3496: *(tmpStr-1)='\0';
3497: str=cal->arg[i].str+2;
3498: }else{
3499: str=cal->arg[i].str+1;
3500: }
3501: cal->arg[i].type = FIELD;
3502: cal->arg[i].flds = mssInitFields();
3503: mssAddFieldsByFldInfoList(cal->arg[i].flds,
3504: mssFldGlbNam2Add(hd->flds,str));
3505:
3506: /*定数の場合*/
3507: }else{
3508: /*実際の定数の型と関数が要求する引数の型が合わない場合は
3509: 関数の型に合わせる*/
3510: cal->arg[i].type = CONST;
3511: s=cal->arg[i].str;
3512: if(*s == '"'){ /*実際の定数はS*/
3513: tmpStr=mssSkipStrBlock(s,'"','"');
3514: if(tmpStr==NULL) {
3515: mssShowErrMsg("\"の数がおかしい");
3516: mssEnd(mssErrorNoDefault);
3517: }
3518: *(tmpStr-1) = '\0';
3519: s++;
3520: }
3521: switch(cal->arg[i].datType) {
3522: case N:
3523: mssVinit(&cal->arg[i].constant,DBL);
3524: cal->arg[i].constant.v.d = atof(s);
3525: break;
3526: case S:
3527: case X: /*未定義型の場合は、文字列として値をセットする*/
3528: mssVinit(&cal->arg[i].constant,STR);
3529: cal->arg[i].constant.v.s = s;
3530: break;
3531: }
3532: }
3533: break;
3534:
3535: } /* switch*/
3536: } /*for i<argCnt*/
3537:
3538: /*返値タイプの設定*/
3539: cal->retType=cal->func->retType;
3540: }
3541:
3542: /**
3543: * # FUNCTION #
3544: * mssCal構造体に納められた全関数(演算子)のうち、利用しているデータ読込関数
3545: * で可能でない関数(演算子)が含まれていないかチェックする。
3546: * 含まれていれば、エラーメッセージを表示して終了する。
3547: */
3548: static void cal_chkProcType(struct mssCal *cal, unsigned char procType)
3549: {
3550: int i;
3551:
3552: if( (cal->func->procType & procType) == 0 ){
3553: mssShowErrMsg("cannot use the function [%s] in this command, or try it again with -k option if possible",cal->func->name);
3554: mssEnd(mssErrorNoDefault);
3555: }
3556: for(i=0; i<cal->argCnt; i++){
3557: if(cal->arg[i].type==NODE)
3558: cal_chkProcType(cal->arg[i].node,procType);
3559: }
3560: }
3561:
3562: /**
3563: * # FUNCTION #
3564: * 前行、トップ行、前行結果、トップ行結果を利用する関数が含まれているかチェック
3565: * し、含まれていれば、グローバル変数である、
3566: * UsedPrvResult,UsedTopResult,UsedPrvField,UsedTopFieldフラグをセットする。
3567: */
3568: static void cal_chkUsedPrvFldRsl(struct mssCal *cal)
3569: {
3570: int i;
3571:
3572: if( 0==strcmp(cal->func->name,"prvResult") ){
3573: UsedPrvResult=1;
3574: return;
3575: }
3576: if( 0==strcmp(cal->func->name,"topResult") ){
3577: UsedTopResult=1;
3578: return;
3579: }
3580: if( 0==strcmp(cal->func->name,"prvField") ){
3581: UsedPrvField=1;
3582: return;
3583: }
3584: if( 0==strcmp(cal->func->name,"lineCmp") ){
3585: UsedPrvField=1;
3586: return;
3587: }
3588: if( 0==strcmp(cal->func->name,"topField") ){
3589: UsedTopField=1;
3590: return;
3591: }
3592: for(i=0; i<cal->argCnt; i++){
3593: if(cal->arg[i].type==NODE){
3594: cal_chkUsedPrvFldRsl(cal->arg[i].node);
3595: }
3596: }
3597: }
3598:
3599: /**
3600: * # FUNCTION #
3601: * データ読込関数をreadFldRecに設定登録する。
3602: */
3603: void mssCalReadFuncIsFldRec(struct mssCal *cal,struct mssFldRec *fr)
3604: {
3605: Fr=fr;
3606: cal_chkProcType(cal, 1);
3607: cal_chkUsedPrvFldRsl(cal);
3608: }
3609:
3610: /**
3611: * # FUNCTION #
3612: * データ読込関数をreadFRDに設定登録する。
3613: */
3614: void mssCalReadFuncIsFRD(struct mssCal *cal,struct mssFldRecDbl *frd)
3615: {
3616: Frd=frd;
3617: cal_chkProcType(cal, 2);
3618: cal_chkUsedPrvFldRsl(cal);
3619: }
3620:
3621: /**
3622: * # FUNCTION #
3623: * データ読込関数をreadFRKに設定登録する。
3624: */
3625: void mssCalReadFuncIsFRK(struct mssCal *cal,struct mssFldRecKey *frk)
3626: {
3627: Frk=frk;
3628: cal_chkProcType(cal, 4);
3629: cal_chkUsedPrvFldRsl(cal);
3630: }
3631:
3632: /**
3633: * # FUNCTION #
3634: * カレント行(pnt)において計算を再帰的に実行し、その結果を返す。
3635: * 計算結果の値の型が呼び出し側の型に一致しない場合は型変換を行う。
3636: */
3637: static MssValue cal_calculate_sub(struct mssCal *cal, char **pnt)
3638: {
3639:
3640: int i,j;
3641: int fldNo;
3642: MssValue val;
3643: for(i=0; i<cal->argCnt; i++){
3644: switch(cal->arg[i].type){
3645: case NODE:
3646: cal->arg[i].val[0] = cal_calculate_sub(cal->arg[i].node,pnt);
3647: cal->arg[i].valCnt = 1;
3648: break;
3649: case CONST:
3650: cal->arg[i].val[0] = cal->arg[i].constant;
3651: cal->arg[i].valCnt = 1;
3652: break;
3653: case FIELD:
3654: for(j=0; j<cal->arg[i].flds->cnt; j++){
3655: fldNo=MssFlds2num(cal->arg[i].flds,j);
3656:
3657: cal->arg[i].val[j].nul =0;/*nul初期化*/
3658: if( MssIsNull(*(pnt+fldNo)) ){
3659: MssVnull(cal->arg[i].val[j]);
3660: continue;
3661: }
3662:
3663: switch(cal->arg[i].datType){
3664: case N:
3665: mssVinit(&cal->arg[i].val[j],DBL);
3666: cal->arg[i].val[j].v.d =atof(*(pnt+fldNo));
3667: break;
3668: case S:
3669: case X: /*未定義型の場合は、文字列として値をセットする*/
3670: mssVinit(&cal->arg[i].val[j],STR);
3671: cal->arg[i].val[j].v.s =*(pnt+fldNo);
3672: break;
3673: default:
3674: mssShowErrMsg("internal error\n");
3675: mssEnd(mssErrorNoDefault);
3676: }
3677: }
3678: cal->arg[i].valCnt = j;
3679: break;
3680: }
3681: }
3682:
3683: /*型変換*/
3684: for(i=0; i<cal->argCnt; i++){
3685: /*文字列型→数値型変換*/
3686: if(cal->arg[i].datType==N && cal->arg[i].val[0].vType==STR){
3687: for(j=0; j<cal->arg[i].valCnt; j++){
3688: cal->arg[i].val[j]=mssVs2d(cal->arg[i].val[j]);
3689: }
3690: continue;
3691: }
3692:
3693: /*数値型→文字列型変換*/
3694: if(cal->arg[i].datType==S && cal->arg[i].val[0].vType==DBL){
3695: for(j=0; j<cal->arg[i].valCnt; j++){
3696: cal->arg[i].val[j]=mssVd2s(cal->arg[i].val[j]);
3697: }
3698: continue;
3699: }
3700: }
3701:
3702: /* 実際の関数呼び出し */
3703: val=(cal->func->pnt)(cal);
3704:
3705: return( val );
3706: }
3707:
3708: static void setRslVal(struct PrvRslStruct *prv, MssValue *rsl)
3709: {
3710: prv->val=*rsl;
3711: if(rsl->vType==STR && !rsl->nul){
3712: strcpy(prv->buf,rsl->v.s);
3713: prv->val.v.s=prv->buf;
3714: }
3715: }
3716:
3717: static void clearRslVal(struct PrvRslStruct *prv)
3718: {
3719: MssVnull(prv->val); /*先頭行結果を入れる変数のクリア*/
3720: }
3721:
3722: static void setFldVal(struct PrvFldStruct *prv, char **pnt, int fldCnt)
3723: {
3724: int chrCnt=0;
3725: char *str;
3726: int i;
3727:
3728: for(i=0; i<fldCnt; i++){
3729: prv->pnt[i]=&prv->buf[chrCnt];
3730: if(pnt==NULL){
3731: prv->buf[chrCnt++]=MssNullChr;
3732: prv->buf[chrCnt++]='\0';
3733: }else{
3734: str=*(pnt+i);
3735: while(*str!='\0'){
3736: prv->buf[chrCnt++]=*str++;
3737: }
3738: prv->buf[chrCnt++]='\0';
3739: }
3740: }
3741: }
3742:
3743: static void clearFldVal(struct PrvFldStruct *prv)
3744: {
3745: prv->pnt[0]=NULL; /*前行項目を入れる変数のクリア*/
3746: }
3747:
3748: static void setTopField(void)
3749: {
3750: if(Frk!=NULL){
3751: if(Frk->curRecNo==1) setFldVal(&TopFld,Frk->pnt,Frk->fldCnt);
3752: }else if(Frd!=NULL){
3753: if(mssGV.inCnt ==1) setFldVal(&TopFld,Frd->pnt[Frd->new],Frd->fldCnt);
3754: }else if(Fr!=NULL){
3755: if(mssGV.inCnt ==1) setFldVal(&TopFld,Fr->pnt,Fr->fldCnt);
3756: }
3757: }
3758:
3759: static void setPrvField(void)
3760: {
3761: if(Frk!=NULL){
3762: if(Frk->curRecNo==Frk->keyRecCnt){
3763: clearFldVal(&PrvFld);
3764: }else{
3765: setFldVal(&PrvFld,Frk->pnt,Frk->fldCnt);
3766: }
3767: }else if(Frd!=NULL){
3768: setFldVal(&PrvFld,Frd->pnt[Frd->new],Frd->fldCnt);
3769: }else if(Fr!=NULL){
3770: setFldVal(&PrvFld,Fr->pnt,Fr->fldCnt);
3771: }
3772: }
3773:
3774: static void setTopResult(MssValue rsl)
3775: {
3776: if(Frk!=NULL){
3777: if(Frk->curRecNo==1) setRslVal(&TopRsl,&rsl);
3778: if(Frk->curRecNo==Frk->keyRecCnt){
3779: clearRslVal(&PrvRsl);
3780: }
3781: }else if(Frd!=NULL){
3782: if(mssGV.inCnt ==1) setRslVal(&TopRsl,&rsl);
3783: }else if(Fr!=NULL){
3784: if(mssGV.inCnt ==1) setRslVal(&TopRsl,&rsl);
3785: }
3786: }
3787:
3788: static void setPrvResult(MssValue rsl)
3789: {
3790: if(Frk!=NULL){
3791: if(Frk->curRecNo==Frk->keyRecCnt){
3792: clearRslVal(&PrvRsl);
3793: }else{
3794: setRslVal(&PrvRsl,&rsl);
3795: }
3796: }else if(Frd!=NULL){
3797: setRslVal(&PrvRsl,&rsl);
3798: }else if(Fr!=NULL){
3799: setRslVal(&PrvRsl,&rsl);
3800: }
3801: }
3802:
3803: /**
3804: * # FUNCTION #
3805: * カレント行(pnt)において計算を実行し、その結果を返す。
3806: * 現在行や結果を保存しておく必要があれば(prvField(),prvResult()など)、
3807: * 保存しておく。
3808: */
3809: MssValue mssCalculate(struct mssCal *cal, char **pnt)
3810: {
3811: MssValue rsl;
3812:
3813: /*先頭行項目のセット*/
3814: if(UsedTopField) setTopField();
3815:
3816: /*計算式の中で確保されたstr領域を開放*/
3817: cal_freeStrMalAdd();
3818:
3819: /*計算式評価*/
3820: rsl=cal_calculate_sub(cal,pnt);
3821:
3822: /*前行項目のセット*/
3823: if(UsedPrvField !=0) setPrvField();
3824:
3825: /*先頭行計算結果のセット*/
3826: if(UsedTopResult!=0) setTopResult(rsl);
3827:
3828: /*前行計算結果のセット*/
3829: if(UsedPrvResult!=0) setPrvResult(rsl);
3830:
3831: return(rsl);
3832: }
3833:
3834: /**
3835: * # FUNCTION #
3836: * 計算式(str)を評価し、Cal構造体(ツリー構造による式の表現)を設定する。
3837: * ツリーのトップノードへのポインタを返す。
3838: * ヘッダー(hd)は、計算式内の項目名を解決するために利用する。
3839: */
3840: struct mssCal *mssCalCompile(char *str, struct mssHeader *hd)
3841: {
3842: struct mssCal *cal=NULL;
3843:
3844: initCalFunc(); /*func[]の未定義変数のセット*/
3845: str=cal_chkCal(str); /*数式事前チェック(余分スペースの除去)*/
3846: cal=cal_sepCal(str,cal); /*数式をトークン分割しツリー構造にする*/
3847:
3848: if(cal==NULL){
3849: mssShowErrMsg("cannot find any operators or functions");
3850: mssEnd(mssErrorNoDefault);
3851: }
3852: cal_evalFldsConst(cal, hd); /*引数の評価(変数や定数を展開)*/
3853: /*mssCalShowTree(cal,0);*/
3854:
3855: mssGV.inFldCnt=hd->flds->cnt; /*入力データの項目数をグローバル変数に登録*/
3856:
3857: MssVnull(PrvRsl.val); /*前行結果を入れる変数のクリア*/
3858: MssVnull(TopRsl.val); /*先頭行結果を入れる変数のクリア*/
3859: PrvFld.pnt[0]=NULL; /*前行項目を入れる変数のクリア*/
3860: TopFld.pnt[0]=NULL; /*先頭行項目を入れる変数のクリア*/
3861:
3862: return(cal);
3863: }
3864:
3865: /**
3866: * # FUNCTION #
3867: * 式評価ツリーの領域開放
3868: */
3869: void mssCalFree(struct mssCal *cal)
3870: {
3871: int i;
3872:
3873: cal_freeStrMalAdd();
3874:
3875: for(i=0; i<cal->argCnt; i++){
3876: if(cal->arg[i].type==NODE){
3877: mssCalFree(cal->arg[i].node);
3878: mssFree(cal->arg[i].str);
3879: }else{
3880: if(cal->arg[i].type == FIELD){
3881: mssFreeFields(cal->arg[i].flds);
3882: }
3883: mssFree(cal->arg[i].node);
3884: mssFree(cal->arg[i].str);
3885: }
3886: }
3887: mssFree(cal);
3888: }