MUSASHI C source: xtcommon.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 <xtcommonHelp.h>  
0012: struct mssComHelp comHelp={  
0013:   "xtcommon",     /* コマンド名       */  
0014:   "1.0",          /* バージョン       */  
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 statT; /*readFRK(Tra)のステータス*/  
0028: static int statM; /*readFRK(Mst)のステータス*/  
0029: static MssOptKEY *OPTTKY;  
0030: static MssOptKEY *OPTMKY;  
0031:   
0032: int keyCmp(  
0033:   struct mssFldRec *frT,  
0034:   struct mssFldRec *frM){  
0035:   int cmp;  
0036:   int i;  
0037:   int fnT;  
0038:   int fnM;  
0039:   
0040:   if(statT==EOF) return(1);  /*T>M*/  
0041:   if(statM==EOF) return(-1); /*T<M*/  
0042:   
0043:   for(i=0; i<OPTTKY->flds->cnt; i++){  
0044:     fnT=MssFlds2num(OPTTKY->flds,i);  
0045:     fnM=MssFlds2num(OPTMKY->flds,i);  
0046:     cmp = strcmp(*(frT->pnt+fnT),*(frM ->pnt+fnM));  
0047:     if(cmp>0) return(1); /*T>M*/  
0048:     if(cmp<0) return(-1);/*T<M*/  
0049:   }  
0050:   return(0);  
0051: }  
0052:   
0053: int main(int argc, char *argv[]){  
0054: /*============================================================================*/  
0055: /* オプション宣言&定義                                                       */  
0056: /*============================================================================*/  
0057: /*----------------------------------------------------------------------------*/  
0058: /* 入力キー項目                                                               */  
0059: /*----------------------------------------------------------------------------*/  
0060:   MssOptKEY optTKY={  
0061:     OKEY,   /* オプションタイプ                                             */  
0062:     "k",    /* キーワード(複数文字は不可)                                   */  
0063:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */  
0064:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */  
0065:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */  
0066:     0,      /* デフォルト(このオプションが指定されなかったときの動作を指定) */  
0067:             /* 1:全ての行を異るキー値として扱う                             */  
0068:             /* 2:全ての行を同じキー値として扱う)                            */  
0069:             /* 0:その他(上記の意味解釈がない)                               */  
0070:     TKYT,   /* このオプションのタイトル(Helpで表示)                         */  
0071:     TKYC    /* このオプションのコメント(Helpで表示)                         */  
0072:   };  
0073:   
0074: /*----------------------------------------------------------------------------*/  
0075: /* 参照キー項目                                                               */  
0076: /*----------------------------------------------------------------------------*/  
0077:   MssOptKEY optMKY={  
0078:     OKEY,   /* オプションタイプ                                             */  
0079:     "K",    /* キーワード(複数文字は不可)                                   */  
0080:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */  
0081:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */  
0082:     "m",    /* 対象とする入力データのキーワード(GUIで利用)                  */  
0083:     0,      /* デフォルト(このオプションが指定されなかったときの動作を指定) */  
0084:             /* 1:全ての行を異るキー値として扱う                             */  
0085:             /* 2:全ての行を同じキー値として扱う)                            */  
0086:             /* 0:その他(上記の意味解釈がない)                               */  
0087:     MKYT,   /* このオプションのタイトル(Helpで表示)                         */  
0088:     MKYC    /* このオプションのコメント(Helpで表示)                         */  
0089:   };  
0090:   
0091: /*----------------------------------------------------------------------------*/  
0092: /* 参照ファイル                                                               */  
0093: /*----------------------------------------------------------------------------*/  
0094:   MssOptINF optMST={  
0095:     OINF,   /* オプションタイプ                                             */  
0096:     "m",    /* キーワード(複数文字は不可)                                   */  
0097:     1,      /* 0:オプション, 1:必須                                         */  
0098:     1,      /* 指定可能の最大ファイル数                                     */  
0099:     0,      /*1:file not foundのエラーで終了しない 0:する                   */  
0100:     MSTT,   /* このオプションのタイトル(Helpで表示)                         */  
0101:     MSTC    /* このオプションのコメント(Helpで表示)                         */  
0102:   };  
0103:   
0104: /*----------------------------------------------------------------------------*/  
0105: /* アンマッチ出力ファイル                                                     */  
0106: /*----------------------------------------------------------------------------*/  
0107:   MssOptOTF optNOF={  
0108:     OOTF,   /* オプションタイプ                                             */  
0109:     "u",    /* キーワード(複数文字は不可)                                   */  
0110:     0,      /* 0:オプション, 1:必須                                         */  
0111:     NOFT,   /* このオプションのタイトル(Helpで表示)                         */  
0112:     NOFC    /* このオプションのコメント(Helpで表示)                         */  
0113:   };  
0114:   
0115: /*----------------------------------------------------------------------------*/  
0116: /* 強制ハッシュ                                                               */  
0117: /*----------------------------------------------------------------------------*/  
0118:   MssOptINT optHAS={  
0119:     OINT,   /* オプションタイプ                                             */  
0120:     "H",    /* キーワード(複数文字は不可)                                   */  
0121:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */  
0122:     1001,   /* デフォルト(数値として指定)                                   */  
0123:     11,     /* 最小値                                                       */  
0124:     100001, /* 最大値                                                       */  
0125:     HAST,   /* このオプションのタイトル(Helpで表示)                         */  
0126:     HASC    /* このオプションのコメント(Helpで表示)                         */  
0127:   };          
0128:   
0129: /*----------------------------------------------------------------------------*/  
0130: /* 条件反転転フラグ(アンマッチを出力)                                         */  
0131: /*----------------------------------------------------------------------------*/  
0132:   MssOptFLG optREV={  
0133:     OFLG,   /* オプションタイプ                                             */  
0134:     "r",    /* キーワード(複数文字は不可)                                   */  
0135:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */  
0136:     REVT,   /* このオプションのタイトル(Helpで表示)                         */  
0137:     REVC    /* このオプションのコメント(Helpで表示)                         */  
0138:   };  
0139:     
0140: /*----------------------------------------------------------------------------*/  
0141: /* 入力ファイル                                                               */  
0142: /*----------------------------------------------------------------------------*/  
0143:   MssOptINF optINF={  
0144:     OINF,   /* オプションタイプ                                             */  
0145:     "i",    /* キーワード(複数文字は不可)                                   */  
0146:     0,      /* 0:オプション, 1:必須                                         */  
0147:     1,      /* 指定可能の最大ファイル数                                     */  
0148:     0,      /*1:file not foundのエラーで終了しない 0:する                   */  
0149:     INFT,   /* このオプションのタイトル(Helpで表示)                         */  
0150:     INFC    /* このオプションのコメント(Helpで表示)                         */  
0151:   };  
0152:   
0153: /*----------------------------------------------------------------------------*/  
0154: /* 出力ファイル                                                               */  
0155: /*----------------------------------------------------------------------------*/  
0156:   MssOptOTF optOTF={  
0157:     OOTF,   /* オプションタイプ                                             */  
0158:     "o",    /* キーワード(複数文字は不可)                                   */  
0159:     0,      /* 0:オプション, 1:必須                                         */  
0160:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */  
0161:     OTFC    /* このオプションのコメント(Helpで表示)                         */  
0162:   };  
0163:       
0164: /*----------------------------------------------------------------------------*/  
0165: /* 圧縮出力                                                                   */  
0166: /*----------------------------------------------------------------------------*/  
0167:   MssOptFLG optZIP={  
0168:     OFLG,   /* オプションタイプ                                             */  
0169:     "z",    /* キーワード(複数文字は不可)                                   */  
0170:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */  
0171:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */  
0172:     ZIPC    /* このオプションのコメント(Helpで表示)                         */  
0173:   };  
0174:       
0175: /*----------------------------------------------------------------------------*/  
0176: /* plain text                                                                 */  
0177: /*----------------------------------------------------------------------------*/  
0178:   MssOptFLG optTXT={  
0179:     OFLG,   /* オプションタイプ                                             */  
0180:     "t",    /* キーワード(複数文字は不可)                                   */  
0181:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */  
0182:     TXTT,   /* このオプションのタイトル(Helpで表示)                         */  
0183:     TXTC    /* このオプションのコメント(Helpで表示)                         */  
0184:   };  
0185:   
0186: /*----------------------------------------------------------------------------*/  
0187: /* ワークファイル用ディレクトリ名                                             */  
0188: /*----------------------------------------------------------------------------*/  
0189:   MssOptSTR optTMP={  
0190:     OSTR,   /* オプションタイプ                                             */  
0191:     "T",    /* キーワード(複数文字は不可)                                   */  
0192:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */  
0193:     MssTempDir, /* デフォルト                                               */  
0194:     1,      /* 文字列の最小長                                               */  
0195:     MssFileNameMaxLen,  /* 文字列の最大長                                   */  
0196:     TMPT,   /* このオプションのタイトル(Helpで表示)                         */  
0197:     TMPC    /* このオプションのコメント(Helpで表示)                         */  
0198:   };  
0199:   
0200: /*----------------------------------------------------------------------------*/  
0201: /* オプションをまとめる                                                       */  
0202: /*----------------------------------------------------------------------------*/  
0203:   void *opt[]={&optTKY,&optMKY,&optMST,&optNOF,&optREV,&optHAS,  
0204:                &optINF,&optOTF,&optZIP,&optTXT,&optTMP,NULL};  
0205:   
0206: /*============================================================================*/  
0207: /* 変数宣言&定義                                                             */  
0208: /*============================================================================*/  
0209:   struct mssHeader    *hdT;  /*入力ファイル用<head>タグ格納構造体*/  
0210:   struct mssHeader    *hdM;  /*参照ファイル用<head>タグ格納構造体*/  
0211:   struct mssHeader    *hdo;  /*出力ファイル用<head>タグ格納構造体*/  
0212:   struct mssFPR       *fprT; /*入力ファイル構造体                */  
0213:   struct mssFPR       *fprM; /*参照ファイル構造体                */  
0214:   struct mssFPW       *fpw;  /*出力ファイル構造体                */  
0215:   struct mssFPW       *fpw2; /*アンマッチ出力ファイル構造体      */  
0216:   struct mssFields    *sfT;  /*ソート項目構造体                  */  
0217:   struct mssFields    *sfM;  /*ソート項目構造体                  */  
0218:   int sortedT;               /*ソート済チェック用                */  
0219:   int sortedM;               /*ソート済チェック用                */  
0220:   
0221:   /*hash joinにて*/  
0222:   struct mssFldRec    *frT =NULL;  
0223:   struct mssFldRecMax *frmM=NULL;  
0224:   
0225:   /*key break joinにて*/  
0226:   struct mssFldRec    *frM =NULL;  
0227:   
0228:   struct mssFileInfo  *fi=NULL; /*マスターのファイル情報*/  
0229:   
0230:   struct mssHashFld     *hash=NULL;  
0231:   struct mssHashNodeFld *hn;  
0232:   
0233:   int mstIsSmall;  
0234:   int procType;  
0235:   int kc;  
0236:   int i;  
0237:   
0238: /*----------------------------------------------------------------------------*/  
0239: /* 前処理                                                                     */  
0240: /*----------------------------------------------------------------------------*/  
0241:   mssInit(argc,argv,&comHelp);       /* シグナル処理などの初期化              */  
0242:   mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ                                */  
0243:   mssSetOption(opt,argc,argv);       /* コマンドオプションの設定              */  
0244:   
0245:   /*-Kが指定されていなければ-kをコピーする*/  
0246:   if(!optMKY.set){  
0247:     mssCpyOptKey(&optMKY,&optTKY);  
0248:   }  
0249:   
0250:   fprT=mssOpenFPR(optINF.str,4);    /*ファイルオープン*/  
0251:   fprM=mssOpenFPR(optMST.str,128);  /*マスターファイルオープン*/  
0252:   hdT=mssReadHeader(fprT);          /*項目名情報の読み込み*/  
0253:   hdM=mssReadHeader(fprM);          /*項目名情報の読み込み*/  
0254:   
0255:   mssSetOptKey(&optTKY, hdT);       /* オプション項目をヘッダー項目に関連づけ*/  
0256:   mssSetOptKey(&optMKY, hdM);       /* オプション項目をヘッダー項目に関連づけ*/  
0257:   
0258:   /*traソート項目の作成*/  
0259:   sfT=mssInitFields();  
0260:   mssAddFieldsByFields(sfT,optTKY.flds);/* -k 項目をソート項目としてセット    */  
0261:   mssSetFieldsSortPriority(sfT);        /* ソート優先順位番号を登録順にふる   */  
0262:   sortedT=mssChkSorted(sfT,hdT);        /* ソート済かチェック                 */  
0263:   
0264:   /*mstソート項目の作成*/  
0265:   sfM=mssInitFields();  
0266:   mssAddFieldsByFields(sfM,optMKY.flds);/* -k 項目をソート項目としてセット    */  
0267:   mssSetFieldsSortPriority(sfM);        /* ソート優先順位番号を登録順にふる   */  
0268:   sortedM=mssChkSorted(sfM,hdM);        /* ソート済かチェック                 */  
0269:   
0270:   /*強制hashでなければ一万行を上限にマスターの情報を取得*/  
0271:   if(!optHAS.set){  
0272:     fi=mssGetFileInfo(optMST.str,10000);  
0273:   
0274:   /*強制hashならば全行マスターの情報を取得*/  
0275:   }else{   
0276:     fi=mssGetFileInfo(optMST.str,0);  
0277:   }  
0278:     
0279: /*----------------------------------------------------------------------------*/  
0280: /*前処理                                                                      */  
0281: /*----------------------------------------------------------------------------*/  
0282: /* Traは大きいという前提で考える*/  
0283: /* TraSrt MstSrt MstSmall */  
0284: /* 無     無   小 hash                (1)*/  
0285: /* 無     無   大 Tsrt+Msrt + keyBreak(2)*/  
0286: /* 無     済   小 hash                (1)*/  
0287: /* 無     済   大 Tsrt      + keyBreak(3)*/  
0288: /* 済     無   小 Msrt      + keyBreak(4)*/  
0289: /* 済     無   大 Msrt      + keyBreak(4)*/  
0290: /* 済     済   小             keyBreak(5)*/  
0291: /* 済     済   大             keyBreak(5)*/  
0292:   
0293:   /*マスタが小さいかどうかのチェック*/  
0294:   if(!fi->readEnd){  /*最後まで読み切っていない*/  
0295:     mstIsSmall=0;      
0296:   }else{             /*その他は、smallであると判断*/  
0297:     mstIsSmall=1;  
0298:   }  
0299:   mssFree(fi);  
0300:   
0301:   /*処理タイプの決定*/  
0302:   if(sortedT){  
0303:     if(sortedM){  
0304:       if(mstIsSmall) procType=5;  
0305:       else           procType=5;  
0306:     }else{  
0307:       if(mstIsSmall) procType=4;  
0308:       else           procType=4;  
0309:     }  
0310:   }else{  
0311:     if(sortedM){  
0312:       if(mstIsSmall) procType=1;  
0313:       else           procType=3;  
0314:     }else{  
0315:       if(mstIsSmall) procType=1;  
0316:       else           procType=2;  
0317:     }  
0318:   }  
0319:   
0320:   /*強制hashの時は、強制的にtype1*/  
0321:   if(optHAS.set) procType=1;  
0322:   
0323: /*----------------------------------------------------------------------------*/  
0324: /*出力ヘッダーの作成と出力                                                    */  
0325: /*----------------------------------------------------------------------------*/  
0326:   /*出力ヘッダーの初期化(タイトル等のコピー)*/  
0327:   hdo=mssInitCpyHeader(hdT);  
0328:     
0329:   /*入力ヘッダの全項目を追加*/  
0330:   mssAddFieldsByFields(hdo->flds,hdT->flds);  
0331:     
0332:   if(procType==2 || procType==3){  
0333:     mssSetFieldsSort(hdo->flds,sfT);  
0334:   }  
0335:     
0336:   /*標準出力オープン+ヘッダーの出力*/  
0337:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0);  
0338:   mssWriteHeader(hdo, fpw);  
0339:   
0340:   /*条件不一致出力オープン+ヘッダーの出力*/  
0341:   if(optNOF.set){  
0342:     fpw2=mssOpenFPW(optNOF.str,0,0);  
0343:     mssWriteHeader(hdo, fpw2);  
0344:   }else{  
0345:     fpw2=NULL;  
0346:   }  
0347:   
0348: /*----------------------------------------------------------------------------*/  
0349: /*メインルーチン*/  
0350: /*----------------------------------------------------------------------------*/  
0351:   /*グローバル変数セット*/  
0352:   OPTTKY=&optTKY;  
0353:   OPTMKY=&optMKY;  
0354:   
0355:   if(procType==1){  
0356:   
0357:     /*ハッシュテーブルの作成*/  
0358:     frmM =mssInitFRM(hdM->flds->cnt);  
0359:     mssReadFRM(fprM,frmM);  
0360:   
0361:     /*全行読み込んでるはずなのでeofフラグがたっているはず*/  
0362:     if(!frmM->eof) {  
0363:       mssShowErrMsg("internal error in xtcommon by hash");  
0364:       mssEnd(mssErrorNoDefault);  
0365:     }  
0366:     hash=mssInitHashFld(optHAS.val,optMKY.flds);  
0367:     for(i=0; i<frmM->recCnt; i++){  
0368:       mssHashInsertFld(hash, frmM->pnt+i*frmM->fldCnt);  
0369:     }  
0370: /*mssShowHashFld(hash, frmM->fldCnt);*/  
0371:   
0372:     frT =mssInitFldRec(hdT->flds->cnt);  
0373:   
0374:     while(1){  
0375:       statT=mssReadFldRec(fprT,frT);  
0376:   
0377:       /*Tra Endの時*/  
0378:       if(statT==EOF){  
0379:         break;  
0380:       }  
0381:   
0382:       mssGV.inCnt++;  
0383:   
0384:       /*Mstセット*/  
0385:       hn=mssHashMemberFld(hash, frT->pnt, optTKY.flds);  
0386:   
0387:       /*match*/  
0388:       if(hn!=NULL){  
0389:         if(optREV.set){  
0390:           if(optNOF.set) mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw2);  
0391:         }else{  
0392:           mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw);  
0393:           mssGV.outCnt++;  
0394:         }  
0395:   
0396:       /*unmatch*/  
0397:       }else{  
0398:         if(optREV.set){  
0399:           mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw);  
0400:           mssGV.outCnt++;  
0401:         }else{  
0402:           if(optNOF.set) mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw2);  
0403:         }  
0404:       }  
0405:     }  
0406:   
0407:     mssFreeFRM(frmM);  
0408:     mssFreeFldRec(frT);  
0409:     mssFreeHashFld(hash);  
0410:   
0411:   }else{  
0412:   
0413:     frT =mssInitFldRec(hdT->flds->cnt);  
0414:     frM =mssInitFldRec(hdM->flds->cnt);  
0415:     if(!sortedT){  
0416:       fprT=mssReopenFPRsort(fprT,4,sfT,hdT->flds->cnt,optTMP.str);  
0417:     }  
0418:     if(!sortedM){  
0419:       fprM=mssReopenFPRsort(fprM,4,sfM,hdM->flds->cnt,optTMP.str);  
0420:     }  
0421:   
0422:     /*トラ読み込み*/  
0423:     statT=mssReadFldRec(fprT,frT);  
0424:     mssGV.inCnt++;  
0425:   
0426:     /*マスタ読み込み*/  
0427:     statM=mssReadFldRec(fprM,frM);  
0428:   
0429:     while(1){  
0430:   
0431:       /*Tra,Mst両方Endの時*/  
0432:       /*if(statT==EOF || statM==EOF) break;*/  
0433:       if(statT==EOF) break;  
0434:   
0435:       kc=keyCmp(frT,frM);  
0436:       if(kc == 1){       /*T>M*/  
0437:         statM=mssReadFldRec(fprM,frM);  
0438:       }else if(kc ==-1){ /*T<M*/  
0439:         if(optREV.set){  
0440:           mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw);  
0441:           mssGV.outCnt++;  
0442:         }else{  
0443:           if(optNOF.set) mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw2);  
0444:         }  
0445:         statT=mssReadFldRec(fprT,frT);  
0446:         mssGV.inCnt++;  
0447:       }else{             /*T==M*/  
0448:         if(optREV.set){  
0449:           if(optNOF.set) mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw2);  
0450:         }else{  
0451:           mssWriteFld(frT->pnt, frT->fldCnt, "\n", fpw);  
0452:           mssGV.outCnt++;  
0453:         }  
0454:         statT=mssReadFldRec(fprT,frT);  
0455:         mssGV.inCnt++;  
0456:       }  
0457:     }  
0458:     mssFreeFldRec(frT);  
0459:     mssFreeFldRec(frM);  
0460:   }  
0461:   
0462:   
0463: /*----------------------------------------------------------------------------*/  
0464: /*フッター出力&終了処理                                                       */  
0465: /*----------------------------------------------------------------------------*/  
0466:   mssWriteFooter(fpw);    /*フッターの出力              */  
0467:   mssWriteFooter(fpw2);   /*フッターの出力              */  
0468:   mssCloseFPW(fpw);       /*出力ファイルのクローズ      */  
0469:   mssCloseFPW(fpw2);      /*条件不一致ファイルのクローズ*/  
0470:   mssCloseFPR(fprT);      /*入力ファイルのクローズ      */  
0471:   mssCloseFPR(fprM);      /*入力ファイルのクローズ      */  
0472:   mssFreeFields(sfT);     /*ソート項目構造体の領域開放  */  
0473:   mssFreeFields(sfM);     /*ソート項目構造体の領域開放  */  
0474:   mssFreeHeader(hdT);     /*入力ヘッダ領域開放          */  
0475:   mssFreeHeader(hdM);     /*入力ヘッダ領域開放          */  
0476:   mssFreeHeader(hdo);     /*出力ヘッダ領域開放          */  
0477:   mssFreeOption(opt);     /*オプション領域開放          */  
0478:   mssShowEndMsg();        /* 完了メッセージ             */  
0479:   mssEnd(mssExitSuccess); /* 終了                       */  
0480:   return(0);              /* to avoid warning message   */  
0481: }