MUSASHI C source: xtjoin.c
0001: /*============================================================================*/
0002: /* 変更履歴 */
0003: /*----------------------------------------------------------------------------*/
0004: /* 1.0 : 新しいAPIに対応 2003/06/20 */
0005: /* 1.1 : 数値でソートしたキーを持つデータの動作不具合対処(API) 2003/08/07 */
0006: /*============================================================================*/
0007:
0008: #include <musashi.h>
0009: #include <stdlib.h>
0010:
0011: #include <xtjoinHelp.h>
0012: struct mssComHelp comHelp={
0013: "xtjoin", /* コマンド名 */
0014: "1.1", /* バージョン */
0015: HELPT, /* コマンドタイトル */
0016: HELPS, /* 要約 */
0017: HELPE, /* 利用例 */
0018: HELPR, /* 参照コマンド */
0019: HELPA, /* 作者情報 */
0020: HELPB, /* バグレポート情報 */
0021: HELPH /* ホームページ */
0022: };
0023:
0024: extern struct mssGlobalVariables mssGV;
0025:
0026: /*--グローバル変数*/
0027: static int fcT; /*トラの項目数*/
0028: static int fcM; /*マスの項目数*/
0029: static int statT; /*readFRK(Tra)のステータス*/
0030: static int statM; /*readFRK(Mst)のステータス*/
0031: static struct mssFPW *op;
0032: static MssOptKEY *OPTTKY;
0033: static MssOptKEY *OPTMKY;
0034: static MssOptFLD *OPTFLD;
0035:
0036: /**
0037: * # FUNCTION #
0038: * 現在読み込まれているTraとMstのキーの値を比較する
0039: */
0040: int keyCmp(
0041: struct mssFldRecDbl *frdT,
0042: struct mssFldRec *frM){
0043: int cmp;
0044: int i;
0045: int fnT;
0046: int fnM;
0047:
0048: if(frdT->eof) return(1); /*T>M*/
0049: if(statM==EOF) return(-1); /*T<M*/
0050:
0051: for(i=0; i<OPTTKY->flds->cnt; i++){
0052: fnT=MssFlds2num(OPTTKY->flds,i);
0053: fnM=MssFlds2num(OPTMKY->flds,i);
0054: cmp = strcmp(*(frdT->pnt[frdT->new]+fnT),*(frM ->pnt+fnM));
0055: if(cmp>0) return(1); /*T>M*/
0056: if(cmp<0) return(-1);/*T<M*/
0057: }
0058: return(0);
0059: }
0060:
0061: /**
0062: * # FUNCTION #
0063: * マスター項目としてstr配列のcnt個の要素を書き出す。
0064: * 行末の改行を出力する。
0065: */
0066: void writeMstFld(int cnt, char **str){
0067: int i;
0068: for(i=0; i<cnt-1; i++){
0069: mssWriteStr(*(str+MssFlds2num(OPTFLD->flds,i)),op);
0070: mssWriteDlm(op);
0071: }
0072: mssWriteStr(*(str+MssFlds2num(OPTFLD->flds,i)),op);
0073: mssWriteRet(op);
0074: }
0075:
0076: /**
0077: * # FUNCTION #
0078: * マスター項目として、cnt個のNULL値として書き出す。
0079: * 行末の改行を出力する。
0080: */
0081: void writeMstNul(int cnt){
0082: int i;
0083: for(i=0; i<cnt-1; i++){
0084: mssWriteNull(op); mssWriteDlm(op);
0085: }
0086: mssWriteNull(op); mssWriteRet(op);
0087: }
0088:
0089: /**
0090: * # FUNCTION #
0091: * トランザクション項目としてstr配列のcnt個の要素を書き出す。
0092: * 行末はスペースを出力する。
0093: */
0094: void writeTraFld(int cnt, char **str){
0095: int i;
0096: for(i=0; i<cnt; i++){
0097: mssWriteStr(*(str+i),op);
0098: mssWriteDlm(op);
0099: }
0100: }
0101:
0102: /**
0103: * # FUNCTION #
0104: * トランザクションキー項目の値が、にマスターキー項目に存在しないとき、
0105: * トランザクションのキー項目は、マスターの項目(str)を参照しながら出力し、
0106: * その他のトランザクション項目はNULL値を出力する。
0107: */
0108: void writeTraByMst(char **str){
0109: int kv;
0110: int i;
0111: for(i=0; i<fcT; i++){
0112: kv=*(OPTTKY->fldNo2optNo+i);
0113: if(kv!=-1){
0114: mssWriteStr(*(str+MssFlds2num(OPTMKY->flds,kv)),op);
0115: mssWriteDlm(op);
0116: }else{
0117: mssWriteNull(op); mssWriteDlm(op);
0118: }
0119: }
0120: }
0121:
0122: void writeTM(struct mssFldRecDbl *frdT,struct mssFldRec *frM){
0123:
0124: /*マスターがEOFの時*/
0125: if(frM==NULL){
0126: writeTraFld(frdT->fldCnt,frdT->pnt[frdT->new]);
0127: writeMstNul(OPTFLD->flds->cnt);
0128: mssGV.outCnt++;
0129:
0130: /*トラがEOFの時*/
0131: }else if(frdT==NULL){
0132: writeTraByMst(frM->pnt);
0133: writeMstFld(OPTFLD->flds->cnt,frM->pnt);
0134: mssGV.outCnt++;
0135:
0136: /*トラ、マスターの両方ある場合*/
0137: }else{
0138: writeTraFld(frdT->fldCnt,frdT->pnt[frdT->new]);
0139: writeMstFld(OPTFLD->flds->cnt,frM->pnt);
0140: mssGV.outCnt++;
0141: }
0142: }
0143:
0144: void writeNulMstHash(struct mssHashFld *hash){
0145: struct mssHashNodeFld *node;
0146: int i,j;
0147:
0148: for(i=0; i<hash->hashVal; i++){ /*全hash値を見る*/
0149: node=*(hash->node+i);
0150: while(node != NULL){ /*hash値がiのノードを全て見る*/
0151: if(!node->endFlg){ /*そのノードが1回も検索されていなければ*/
0152: for(j=0; j<node->recCnt; j++){
0153: writeTraByMst(*(node->rec+j));
0154: writeMstFld(OPTFLD->flds->cnt,*(node->rec+j));
0155: mssGV.outCnt++;
0156: }
0157: }
0158: node=node->next;
0159: }
0160: }
0161: }
0162:
0163: void writeTMhash(struct mssFldRec *frT,struct mssHashNodeFld *hn){
0164:
0165: /*マスターがNULLの時*/
0166: if(hn==NULL){
0167: writeTraFld(frT->fldCnt,frT->pnt);
0168: writeMstNul(OPTFLD->flds->cnt);
0169: mssGV.outCnt++;
0170:
0171: /*トラ、マスターの両方ある場合*/
0172: }else{
0173: writeTraFld(frT->fldCnt,frT->pnt);
0174: writeMstFld(OPTFLD->flds->cnt,*hn->rec);
0175: mssGV.outCnt++;
0176: }
0177: }
0178:
0179: /*============================================================================*/
0180: /* version 1.00 2000/07/07 初期作成 hamuro */
0181: /*============================================================================*/
0182: int main(int argc, char *argv[]){
0183: /*============================================================================*/
0184: /* オプション宣言&定義 */
0185: /*============================================================================*/
0186: /*----------------------------------------------------------------------------*/
0187: /* 入力キー項目 */
0188: /*----------------------------------------------------------------------------*/
0189: MssOptKEY optTKY={
0190: OKEY, /* オプションタイプ */
0191: "k", /* キーワード(複数文字は不可) */
0192: 1, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0193: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0194: "i", /* 対象とする入力データのキーワード(GUIで利用) */
0195: 0, /* デフォルト(このオプションが指定されなかったときの動作を指定) */
0196: /* 1:全ての行を異るキー値として扱う */
0197: /* 2:全ての行を同じキー値として扱う) */
0198: /* 0:その他(上記の意味解釈がない) */
0199: TKYT, /* このオプションのタイトル(Helpで表示) */
0200: TKYC /* このオプションのコメント(Helpで表示) */
0201: };
0202:
0203: /*----------------------------------------------------------------------------*/
0204: /* 参照キー項目 */
0205: /*----------------------------------------------------------------------------*/
0206: MssOptKEY optMKY={
0207: OKEY, /* オプションタイプ */
0208: "K", /* キーワード(複数文字は不可) */
0209: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0210: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0211: "m", /* 対象とする入力データのキーワード(GUIで利用) */
0212: 0, /* デフォルト(このオプションが指定されなかったときの動作を指定) */
0213: /* 1:全ての行を異るキー値として扱う */
0214: /* 2:全ての行を同じキー値として扱う) */
0215: /* 0:その他(上記の意味解釈がない) */
0216: MKYT, /* このオプションのタイトル(Helpで表示) */
0217: MKYC /* このオプションのコメント(Helpで表示) */
0218: };
0219:
0220: /*----------------------------------------------------------------------------*/
0221: /* 参照ファイル */
0222: /*----------------------------------------------------------------------------*/
0223: MssOptINF optMST={
0224: OINF, /* オプションタイプ */
0225: "m", /* キーワード(複数文字は不可) */
0226: 1, /* 0:オプション, 1:必須 */
0227: 1, /* 指定可能の最大ファイル数 */
0228: 0, /*1:file not foundのエラーで終了しない 0:する */
0229: MSTT, /* このオプションのタイトル(Helpで表示) */
0230: MSTC /* このオプションのコメント(Helpで表示) */
0231: };
0232:
0233: /*----------------------------------------------------------------------------*/
0234: /* 結合項目 */
0235: /*----------------------------------------------------------------------------*/
0236: MssOptFLD optFLD={
0237: OFLD, /* オプションタイプ */
0238: "f", /* キーワード(複数文字は不可) */
0239: 1, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0240: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0241: "m", /* 対象とする入力データのキーワード(GUIで利用) */
0242: 1, /* 正規表現を許可するかどうか(0:不可,1:可) */
0243: 1, /* 新項目名を指定できるかどうか(0:不可,1:可) */
0244: NULL, /* 項目オプション(%以下)で指定可能な文字 */
0245: /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能 */
0246: FLDT, /* このオプションのタイトル(Helpで表示) */
0247: FLDC, /* このオプションのコメント(Helpで表示) */
0248: FLDF /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る */
0249: };
0250:
0251: /*----------------------------------------------------------------------------*/
0252: /* マスターouterJoin */
0253: /*----------------------------------------------------------------------------*/
0254: MssOptFLG optMNL={
0255: OFLG, /* オプションタイプ */
0256: "N", /* キーワード(複数文字は不可) */
0257: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0258: MNLT, /* このオプションのタイトル(Helpで表示) */
0259: MNLC /* このオプションのコメント(Helpで表示) */
0260: };
0261:
0262: /*----------------------------------------------------------------------------*/
0263: /* 入力outerJoin */
0264: /*----------------------------------------------------------------------------*/
0265: MssOptFLG optTNL={
0266: OFLG, /* オプションタイプ */
0267: "n", /* キーワード(複数文字は不可) */
0268: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0269: TNLT, /* このオプションのタイトル(Helpで表示) */
0270: TNLC /* このオプションのコメント(Helpで表示) */
0271: };
0272:
0273: /*----------------------------------------------------------------------------*/
0274: /* 強制ハッシュJoin */
0275: /*----------------------------------------------------------------------------*/
0276: MssOptINT optHAS={
0277: OINT, /* オプションタイプ */
0278: "H", /* キーワード(複数文字は不可) */
0279: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0280: 1001, /* デフォルト(数値として指定) */
0281: 11, /* 最小値 */
0282: 100001, /* 最大値 */
0283: HAST, /* このオプションのタイトル(Helpで表示) */
0284: HASC /* このオプションのコメント(Helpで表示) */
0285: };
0286:
0287: /*----------------------------------------------------------------------------*/
0288: /* 入力ファイル */
0289: /*----------------------------------------------------------------------------*/
0290: MssOptINF optINF={
0291: OINF, /* オプションタイプ */
0292: "i", /* キーワード(複数文字は不可) */
0293: 0, /* 0:オプション, 1:必須 */
0294: 1, /* 指定可能の最大ファイル数 */
0295: 0, /*1:file not foundのエラーで終了しない 0:する */
0296: INFT, /* このオプションのタイトル(Helpで表示) */
0297: INFC /* このオプションのコメント(Helpで表示) */
0298: };
0299:
0300: /*----------------------------------------------------------------------------*/
0301: /* 出力ファイル */
0302: /*----------------------------------------------------------------------------*/
0303: MssOptOTF optOTF={
0304: OOTF, /* オプションタイプ */
0305: "o", /* キーワード(複数文字は不可) */
0306: 0, /* 0:オプション, 1:必須 */
0307: OTFT, /* このオプションのタイトル(Helpで表示) */
0308: OTFC /* このオプションのコメント(Helpで表示) */
0309: };
0310:
0311: /*----------------------------------------------------------------------------*/
0312: /* 圧縮出力 */
0313: /*----------------------------------------------------------------------------*/
0314: MssOptFLG optZIP={
0315: OFLG, /* オプションタイプ */
0316: "z", /* キーワード(複数文字は不可) */
0317: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0318: ZIPT, /* このオプションのタイトル(Helpで表示) */
0319: ZIPC /* このオプションのコメント(Helpで表示) */
0320: };
0321:
0322: /*----------------------------------------------------------------------------*/
0323: /* plain text */
0324: /*----------------------------------------------------------------------------*/
0325: MssOptFLG optTXT={
0326: OFLG, /* オプションタイプ */
0327: "t", /* キーワード(複数文字は不可) */
0328: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0329: TXTT, /* このオプションのタイトル(Helpで表示) */
0330: TXTC /* このオプションのコメント(Helpで表示) */
0331: };
0332:
0333: /*----------------------------------------------------------------------------*/
0334: /* ワークファイル用ディレクトリ名 */
0335: /*----------------------------------------------------------------------------*/
0336: MssOptSTR optTMP={
0337: OSTR, /* オプションタイプ */
0338: "T", /* キーワード(複数文字は不可) */
0339: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0340: MssTempDir, /* デフォルト */
0341: 1, /* 文字列の最小長 */
0342: MssFileNameMaxLen, /* 文字列の最大長 */
0343: TMPT, /* このオプションのタイトル(Helpで表示) */
0344: TMPC /* このオプションのコメント(Helpで表示) */
0345: };
0346:
0347: /*----------------------------------------------------------------------------*/
0348: /* オプションをまとめる */
0349: /*----------------------------------------------------------------------------*/
0350: void *opt[]={&optTKY,&optMKY,&optMST,&optFLD,&optMNL,&optTNL,&optHAS,
0351: &optINF,&optOTF,&optZIP,&optTXT,&optTMP,NULL};
0352:
0353: /*============================================================================*/
0354: /* 変数宣言&定義 */
0355: /*============================================================================*/
0356: struct mssHeader *hdT; /*入力ファイル用<head>タグ格納構造体*/
0357: struct mssHeader *hdM; /*参照ファイル用<head>タグ格納構造体*/
0358: struct mssHeader *hdo; /*出力ファイル用<head>タグ格納構造体*/
0359: struct mssFPR *fprT;/*入力ファイル構造体 */
0360: struct mssFPR *fprM;/*参照ファイル構造体 */
0361: struct mssFPW *fpw; /*出力ファイル構造体 */
0362: struct mssFields *sfT; /*ソート項目構造体 */
0363: struct mssFields *sfM; /*ソート項目構造体 */
0364: int sortedT; /*ソート済チェック用 */
0365: int sortedM; /*ソート済チェック用 */
0366:
0367: /*hash joinにて*/
0368: struct mssFldRec *frT =NULL;
0369: struct mssFldRecMax *frmM=NULL;
0370:
0371: /*key break joinにて*/
0372: struct mssFldRecDbl *frdT=NULL;
0373: struct mssFldRec *frM =NULL;
0374:
0375: struct mssFileInfo *fi=NULL; /*マスターのファイル情報*/
0376:
0377: struct mssHashFld *hash;
0378: struct mssHashNodeFld *hn;
0379:
0380:
0381: /*マスターを一行でも書いたときon -tnullと単なるキーブレークを見分ける*/
0382: int mstw;
0383:
0384: int mstIsSmall;
0385: int procType;
0386: int kc;
0387: int i;
0388:
0389: /*----------------------------------------------------------------------------*/
0390: /* 前処理 */
0391: /*----------------------------------------------------------------------------*/
0392: mssInit(argc,argv,&comHelp); /* シグナル処理などの初期化 */
0393: mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ */
0394: mssSetOption(opt,argc,argv); /* コマンドオプションの設定 */
0395:
0396: /*-Kが指定されていなければ-kをコピーする*/
0397: if(!optMKY.set){
0398: mssCpyOptKey(&optMKY,&optTKY);
0399: }
0400:
0401: fprT=mssOpenFPR(optINF.str,4); /*ファイルオープン*/
0402: fprM=mssOpenFPR(optMST.str,128); /*マスターファイルオープン*/
0403: hdT=mssReadHeader(fprT); /*項目名情報の読み込み*/
0404: hdM=mssReadHeader(fprM); /*項目名情報の読み込み*/
0405:
0406: mssSetOptKey(&optTKY, hdT); /* オプション項目をヘッダー項目に関連づけ*/
0407: mssSetOptKey(&optMKY, hdM); /* オプション項目をヘッダー項目に関連づけ*/
0408: mssSetOptFld(&optFLD, hdM); /* オプション項目をヘッダー項目に関連づけ*/
0409:
0410: /*traソート項目の作成*/
0411: sfT=mssInitFields();
0412: mssAddFieldsByFields(sfT,optTKY.flds);/* -k 項目をソート項目としてセット */
0413: mssSetFieldsSortPriority(sfT); /* ソート優先順位番号を登録順にふる */
0414: sortedT=mssChkSorted(sfT,hdT); /* ソート済かチェック */
0415:
0416: /*mstソート項目の作成*/
0417: sfM=mssInitFields();
0418: mssAddFieldsByFields(sfM,optMKY.flds);/* -k 項目をソート項目としてセット */
0419: mssSetFieldsSortPriority(sfM); /* ソート優先順位番号を登録順にふる */
0420: sortedM=mssChkSorted(sfM,hdM); /* ソート済かチェック */
0421:
0422: /*強制hashでなければ一万行を上限にマスターの情報を取得*/
0423: if(!optHAS.set){
0424: fi=mssGetFileInfo(optMST.str,10000);
0425:
0426: /*強制hashならば全行マスターの情報を取得*/
0427: }else{
0428: fi=mssGetFileInfo(optMST.str,0);
0429: }
0430:
0431: /*----------------------------------------------------------------------------*/
0432: /*前処理 */
0433: /*----------------------------------------------------------------------------*/
0434: /* Traは大きいという前提で考える*/
0435: /* TraSrt MstSrt MstSmall */
0436: /* 無 無 小 hash (1)*/
0437: /* 無 無 大 Tsrt+Msrt + keyBreak(2)*/
0438: /* 無 済 小 hash (1)*/
0439: /* 無 済 大 Tsrt + keyBreak(3)*/
0440: /* 済 無 小 Msrt + keyBreak(4)*/
0441: /* 済 無 大 Msrt + keyBreak(4)*/
0442: /* 済 済 小 keyBreak(5)*/
0443: /* 済 済 大 keyBreak(5)*/
0444:
0445: /*マスタが小さいかどうかのチェック*/
0446: if(!fi->readEnd){ /*最後まで読み切っていない*/
0447: mstIsSmall=0;
0448: }else{ /*その他は、smallであると判断*/
0449: mstIsSmall=1;
0450: }
0451: mssFree(fi);
0452:
0453: /*処理タイプの決定*/
0454: if(sortedT==1){
0455: if(sortedM==1){
0456: if(mstIsSmall) procType=5;
0457: else procType=5;
0458: }else{
0459: if(mstIsSmall) procType=4;
0460: else procType=4;
0461: }
0462: }else{
0463: if(sortedM==1){
0464: if(mstIsSmall) procType=1;
0465: else procType=3;
0466: }else{
0467: if(mstIsSmall) procType=1;
0468: else procType=2;
0469: }
0470: }
0471:
0472: /*強制hashの時は、強制的にtype1*/
0473: if(optHAS.set) procType=1;
0474:
0475: /*----------------------------------------------------------------------------*/
0476: /*出力ヘッダーの作成と出力 */
0477: /*----------------------------------------------------------------------------*/
0478: /*出力ヘッダーの初期化(タイトル等のコピー)*/
0479: hdo=mssInitCpyHeader(hdT);
0480:
0481: /*入力ヘッダの全項目を追加*/
0482: mssAddFieldsByFields(hdo->flds,hdT->flds);
0483:
0484: /*新項目名を追加する*/
0485: mssAddFieldsByStrList(hdo->flds,optFLD.newNam,optFLD.cnt);
0486:
0487: if(procType==2 || procType==3){
0488: mssSetFieldsSort(hdo->flds,sfT);
0489: }
0490:
0491: /*標準出力オープン+ヘッダーの出力*/
0492: fpw=mssOpenFPW(optOTF.str,optZIP.set,0);
0493: mssWriteHeader(hdo, fpw);
0494:
0495: /*----------------------------------------------------------------------------*/
0496: /*メインルーチン */
0497: /*----------------------------------------------------------------------------*/
0498: /*グローバル変数セット*/
0499: fcT=hdT->flds->cnt;
0500: fcM=hdM->flds->cnt;
0501: OPTTKY=&optTKY;
0502: OPTMKY=&optMKY;
0503: OPTFLD=&optFLD;
0504: op=fpw;
0505:
0506: /*hash join*/
0507: if(procType==1){
0508:
0509: /*ハッシュテーブルの作成*/
0510: frmM =mssInitFRM(fcM);
0511: mssReadFRM(fprM,frmM);
0512:
0513: /*全行読み込んでるはずなのでeofフラグがたっているはず*/
0514: if(!frmM->eof) {
0515: mssShowErrMsg("internal error in xtjoin by hash");
0516: mssEnd(mssErrorNoDefault);
0517: }
0518: hash=mssInitHashFld(optHAS.val,optMKY.flds);
0519: for(i=0; i<frmM->recCnt; i++){
0520: mssHashInsertFld(hash, frmM->pnt+i*frmM->fldCnt);
0521: }
0522: /*mssShowHashFld(hash, frmM->fldCnt);*/
0523:
0524: frT =mssInitFldRec(fcT);
0525: while(1){
0526: statT=mssReadFldRec(fprT,frT);
0527:
0528: /*Tra Endの時*/
0529: if(statT==EOF){
0530: if(optMNL.set) writeNulMstHash(hash);
0531: break;
0532: }
0533:
0534: mssGV.inCnt++;
0535:
0536: /*Traのキー項目値がMstにあるかどうか*/
0537: hn=mssHashMemberFld(hash, frT->pnt, optTKY.flds);
0538: if(hn==NULL && !optTNL.set) continue;
0539:
0540: /*書き出し*/
0541: writeTMhash(frT,hn);
0542: }
0543:
0544: mssFreeFRM(frmM);
0545: mssFreeFldRec(frT);
0546: mssFreeHashFld(hash);
0547:
0548: }else{
0549:
0550: frdT=mssInitFRD(fcT);
0551: frM =mssInitFldRec(fcM);
0552: if(sortedT!=1){
0553: fprT=mssReopenFPRsort(fprT,4,sfT,hdT->flds->cnt,optTMP.str);
0554: }
0555: if(sortedM!=1){
0556: fprM=mssReopenFPRsort(fprM,4,sfM,hdM->flds->cnt,optTMP.str);
0557: }
0558:
0559: /*トラ読み込み*/
0560: statT=mssReadFRD(fprT,frdT);
0561:
0562: /*マスタ読み込み*/
0563: statM=mssReadFldRec(fprM,frM); mstw=0;
0564: while(1){
0565:
0566: /*Tra,Mst両方Endの時*/
0567: if(frdT->eof==1 && statM==EOF) break;
0568:
0569: /*TraだけEndの時*/
0570: if(frdT->eof==1){
0571: if(!optMNL.set) break;
0572: }
0573:
0574: /*MstだけEndの時*/
0575: if(statM==EOF){
0576: if(!optTNL.set) break;
0577: }
0578:
0579: kc=keyCmp(frdT,frM);
0580: if(kc == 1){ /*T>M*/
0581: if(optMNL.set && mstw==0) writeTM(NULL,frM);
0582: statM=mssReadFldRec(fprM,frM); mstw=0;
0583: }else if(kc ==-1){ /*T<M*/
0584: if(optTNL.set) writeTM(frdT,NULL);
0585: statT=mssReadFRD(fprT,frdT);
0586: mssGV.inCnt++;
0587: }else{ /*T==M*/
0588: writeTM(frdT,frM);
0589: mstw=1;
0590: statT=mssReadFRD(fprT,frdT);
0591: mssGV.inCnt++;
0592: }
0593: }
0594: mssFreeFRD(frdT);
0595: mssFreeFldRec(frM);
0596: }
0597:
0598: /*----------------------------------------------------------------------------*/
0599: /*フッター出力&終了処理 */
0600: /*----------------------------------------------------------------------------*/
0601: mssWriteFooter(fpw); /*フッターの出力 */
0602: mssCloseFPR(fprT); /*入力ファイルのクローズ */
0603: mssCloseFPR(fprM); /*入力ファイルのクローズ */
0604: mssCloseFPW(fpw); /*出力ファイルのクローズ */
0605: mssFreeFields(sfT); /*ソート項目構造体の領域開放 */
0606: mssFreeFields(sfM); /*ソート項目構造体の領域開放 */
0607: mssFreeHeader(hdT); /*入力ヘッダ領域開放 */
0608: mssFreeHeader(hdM); /*入力ヘッダ領域開放 */
0609: mssFreeHeader(hdo); /*出力ヘッダ領域開放 */
0610: mssFreeOption(opt); /*オプション領域開放 */
0611: mssShowEndMsg(); /* 完了メッセージ */
0612: mssEnd(mssExitSuccess); /* 終了 */
0613: return(0); /* to avoid warning message */
0614: }