MUSASHI C source: xtsep.c


0001: /*============================================================================*/ 
0002: /* 変更履歴                                                                   */ 
0003: /*----------------------------------------------------------------------------*/ 
0004: /* 1.0 : 新しいAPIに対応 2003/06/20                                           */ 
0005: /* 1.1 : -d $a$bのように連続する項目名の指定での不具合修正 2003/08/07         */ 
0006: /* 1.2 : setFLdNameの無限ループ修正  2003/08/07                               */ 
0007: /*============================================================================*/ 
0008:  
0009: #include <musashi.h
0010: #include <stdlib.h> 
0011: #include <string.h> 
0012:  
0013: #include <xtsepHelp.h> 
0014: struct mssComHelp comHelp={ 
0015:   "xtsep",        /* コマンド名       */ 
0016:   "1.2",          /* バージョン       */ 
0017:   HELPT,          /* コマンドタイトル */ 
0018:   HELPS,          /* 要約             */ 
0019:   HELPE,          /* 利用例           */ 
0020:   HELPR,          /* 参照コマンド     */ 
0021:   HELPA,          /* 作者情報         */ 
0022:   HELPB,          /* バグレポート情報 */ 
0023:   HELPH           /* ホームページ     */ 
0024: }; 
0025:  
0026: extern struct mssGlobalVariables mssGV; 
0027:  
0028: /*パス内容構造体*/ 
0029: struct Path { 
0030:   char *str[50]; 
0031:   struct mssFields *flds; 
0032:   char *endStr; 
0033:   int cnt; 
0034:   char *optStr; /*オプションの指定形式に変換したもの*/ 
0035: }; 
0036:  
0037: /*------------------------------------------------------------------------------ 
0038: 項目名をbufに設定し、項目名の次のポインタを返す 
0039: $は\0に変換 
0040: ex) 
0041: str=$Customer/aaa/$(Date).gz 
0042: buf="Customer" 
0043: end="/aaa/$(Date).gz" 
0044: ------------------------------------------------------------------------------*/ 
0045: char *setFldName(char *buf,char *str){ 
0046:   char *end; 
0047:   int i=0; 
0048:  
0049:   *str='\0'; /* $は\0に変換 */ 
0050:  
0051:   str++; 
0052:   if(*str=='('){ 
0053:     end=mssSkipStrBlock(str,'(',')'); 
0054:     *(end-1)='\0'; 
0055:     strcpy(buf,str+1); 
0056:   }else{ 
0057:     end=str; 
0058:     while(*end!='/' && *end!='\0' && *end!='$'){ 
0059:       if(i>=MssFieldNameMaxLen){ 
0060:         mssShowErrMsg("too long field name on -d"); 
0061:         mssEnd(mssErrorNoDefault); 
0062:       } 
0063:       *(buf+i)=*end; 
0064:       end++; i++; 
0065:     } 
0066:     *(buf+i)='\0'; 
0067:   } 
0068:   return(end); 
0069: } 
0070:  
0071: /*------------------------------------------------------------------------------ 
0072: -dオプションからPath構造体にセットする。 
0073: ex) 
0074: -d /tmp/$Customer/aaa/$(Date).gz 
0075: p->str[0]="/tmp/"   ,   p->fld[0]=$Cusotmer 
0076: p->str[1]="/aaa/"   ,   p->fld[1]=$Date 
0077: p->endStr=".gz" 
0078: p->cnt=2 
0079: p->optStr="Customer,Date" 
0080: ------------------------------------------------------------------------------*/ 
0081: struct Path *setPath(char *path, struct mssHeader *hd){ 
0082:   struct Path *p; 
0083:   char buf[MssFieldNameMaxLen]; 
0084:   char opt[1024]; 
0085:   char *str; 
0086:  
0087:   p=mssCalloc(sizeof(struct Path),"setOptFld"); 
0088:   p->flds=mssInitFields(); 
0089:   p->cnt=0; 
0090:   opt[0]='\0'; 
0091:  
0092:   str=path; 
0093:   while(*path!='\0'){ 
0094:     if(*path=='$'){ 
0095:       if(p->cnt>=50){ 
0096:         mssShowErrMsg("too many field names on -d"); 
0097:         mssEnd(mssErrorNoDefault); 
0098:       } 
0099:  
0100:       /*項目のセット*/ 
0101:       path=setFldName(buf,path); 
0102:       strcat(opt,buf); strcat(opt,","); 
0103:       mssAddFieldsByFldInfo(p->flds,mssFldNam2Add(hd->flds,buf)); 
0104:  
0105:       /*項目の前の文字のセット*/ 
0106:       p->str[p->cnt]=str; 
0107:       str=path; 
0108:  
0109:       /*カウントアップ*/ 
0110:       p->cnt++; 
0111:     }else{ 
0112:       path++; 
0113:     } 
0114:   } 
0115:   if(p->cnt==0){ 
0116:     mssShowErrMsg("no field name on -d"); 
0117:     mssEnd(mssErrorNoDefault); 
0118:   } 
0119:   p->endStr=str; 
0120:  
0121:   opt[strlen(opt)-1]='\0'; 
0122:   p->optStr=mssStrdup(opt); 
0123:  
0124:   return(p); 
0125: } 
0126:  
0127: /*------------------------------------------------------------------------------ 
0128: Path構造体と実際のデータレコードから、実ファイル名を設定する 
0129: ------------------------------------------------------------------------------*/ 
0130: void setPathName( 
0131:   char *pathName, 
0132:   struct Path *path, 
0133:   struct mssFldRecDbl *frd, 
0134:   MssOptKEY *optKey){ 
0135:  
0136:   int i; 
0137:   int len=1; /*1は末尾文字'\0'のため*/ 
0138:  
0139:   *pathName='\0'; 
0140:   for(i=0; i<path->cnt; i++){ 
0141:     /*ファイル名長のチェック*/ 
0142:     len+=strlen(path->str[i])+strlen(*frd->pnt[frd->new]); 
0143:     if(len>=MssFileNameMaxLen) { 
0144:       mssShowErrMsg("path name exceed 1024 charactors"); 
0145:       mssEnd(mssErrorNoDefault); 
0146:     } 
0147:  
0148:     /*文字列とデータ値を連結していく*/ 
0149:     strcat(pathName,path->str[i]); 
0150:     strcat(pathName,*(frd->pnt[frd->new]+MssFlds2num(path->flds,i))); 
0151:   } 
0152:   /*最後の末尾の文字列を連結*/ 
0153:   len+=strlen(path->endStr); 
0154:   if(len>=MssFileNameMaxLen){ 
0155:     mssShowErrMsg("path name exceed 1024 charactors"); 
0156:     mssEnd(mssErrorNoDefault); 
0157:   } 
0158:   strcat(pathName,path->endStr); 
0159: } 
0160:  
0161: int main(int argc, char *argv[]){ 
0162: /*============================================================================*/ 
0163: /* オプション宣言&定義                                                       */ 
0164: /*============================================================================*/ 
0165: /*----------------------------------------------------------------------------*/ 
0166: /* キー項目(内部的に利用、パラメータでは指定できない                          */ 
0167: /*----------------------------------------------------------------------------*/ 
0168:   MssOptKEY optKEY={ 
0169:     OKEY,   /* オプションタイプ                                             */ 
0170:     "k",    /* キーワード(複数文字は不可)                                   */ 
0171:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0172:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */ 
0173:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */ 
0174:     2,      /* デフォルト(このオプションが指定されなかったときの動作を指定) */ 
0175:             /* 1:全ての行を異るキー値として扱う                             */ 
0176:             /* 2:全ての行を同じキー値として扱う)                            */ 
0177:   }; 
0178:  
0179: /*----------------------------------------------------------------------------*/ 
0180: /* 出力ファイル名                                                             */ 
0181: /*----------------------------------------------------------------------------*/ 
0182:   MssOptSTR optDIR={ 
0183:     OSTR,   /* オプションタイプ                                             */ 
0184:     "d",    /* キーワード(複数文字は不可)                                   */ 
0185:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0186:     NULL  , /* デフォルト                                                   */ 
0187:     1,      /* 文字列の最小長                                               */ 
0188:     MssFileNameMaxLen,  /* 文字列の最大長                                   */ 
0189:     DIRT,   /* このオプションのタイトル(Helpで表示)                         */ 
0190:     DIRC    /* このオプションのコメント(Helpで表示)                         */ 
0191:   }; 
0192:  
0193: /*----------------------------------------------------------------------------*/ 
0194: /* 強制ディレクトリ作成                                                       */ 
0195: /*----------------------------------------------------------------------------*/ 
0196:   MssOptFLG optFRC={ 
0197:     OFLG,   /* オプションタイプ                                             */ 
0198:     "p",    /* キーワード(複数文字は不可)                                   */ 
0199:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0200:     FRCT,   /* このオプションのタイトル(Helpで表示)                         */ 
0201:     FRCC    /* このオプションのコメント(Helpで表示)                         */ 
0202:   }; 
0203:  
0204:  
0205: /*----------------------------------------------------------------------------*/ 
0206: /* 入力ファイル                                                               */ 
0207: /*----------------------------------------------------------------------------*/ 
0208:   MssOptINF optINF={ 
0209:     OINF,   /* オプションタイプ                                             */ 
0210:     "i",    /* キーワード(複数文字は不可)                                   */ 
0211:     0,      /* 0:オプション, 1:必須                                         */ 
0212:     1,      /* 指定可能の最大ファイル数                                     */ 
0213:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0214:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0215:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0216:   }; 
0217:  
0218: /*----------------------------------------------------------------------------*/ 
0219: /* 圧縮出力                                                                   */ 
0220: /*----------------------------------------------------------------------------*/ 
0221:   MssOptFLG optZIP={ 
0222:     OFLG,   /* オプションタイプ                                             */ 
0223:     "z",    /* キーワード(複数文字は不可)                                   */ 
0224:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0225:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0226:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0227:   }; 
0228:      
0229: /*----------------------------------------------------------------------------*/ 
0230: /* plain text                                                                 */ 
0231: /*----------------------------------------------------------------------------*/ 
0232:   MssOptFLG optTXT={ 
0233:     OFLG,   /* オプションタイプ                                             */ 
0234:     "t",    /* キーワード(複数文字は不可)                                   */ 
0235:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0236:     TXTT,   /* このオプションのタイトル(Helpで表示)                         */ 
0237:     TXTC    /* このオプションのコメント(Helpで表示)                         */ 
0238:   }; 
0239:  
0240: /*----------------------------------------------------------------------------*/ 
0241: /* ワークファイル用ディレクトリ名                                             */ 
0242: /*----------------------------------------------------------------------------*/ 
0243:   MssOptSTR optTMP={ 
0244:     OSTR,   /* オプションタイプ                                             */ 
0245:     "T",    /* キーワード(複数文字は不可)                                   */ 
0246:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0247:     MssTempDir, /* デフォルト                                               */ 
0248:     1,      /* 文字列の最小長                                               */ 
0249:     MssFileNameMaxLen,  /* 文字列の最大長                                   */ 
0250:     TMPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0251:     TMPC    /* このオプションのコメント(Helpで表示)                         */ 
0252:   }; 
0253:      
0254: /*----------------------------------------------------------------------------*/ 
0255: /* オプションをまとめる                                                       */ 
0256: /*----------------------------------------------------------------------------*/ 
0257:   void *opt[]={&optDIR,&optFRC,&optINF,&optZIP,&optTXT,&optTMP,NULL}; 
0258:      
0259: /*============================================================================*/ 
0260: /* 変数宣言&定義                                                             */ 
0261: /*============================================================================*/ 
0262:   struct mssHeader    *hdi; /*入力ファイル用<head>タグ格納構造体*/ 
0263:   struct mssHeader    *hdo; /*出力ファイル用<head>タグ格納構造体*/ 
0264:   struct mssFPR       *fpr; /*入力ファイル構造体                */ 
0265:   struct mssFPW       *fpw=NULL; /*出力ファイル構造体                */ 
0266:   struct mssFldRecDbl *frd; /*項目-二行バッファ構造体           */ 
0267:   struct mssFields    *sf;  /*ソート項目構造体                  */ 
0268:   int sorted;               /*ソート済チェック用                */ 
0269:  
0270:   struct Path *path; 
0271:   char pathName[MssFileNameMaxLen]; 
0272:   int count; 
0273:  
0274: /*----------------------------------------------------------------------------*/ 
0275: /* 前処理                                                                     */ 
0276: /*----------------------------------------------------------------------------*/ 
0277:   mssInit(argc,argv,&comHelp);       /* シグナル処理などの初期化              */ 
0278:   mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ                                */ 
0279:   mssSetOption(opt,argc,argv);       /* コマンドオプションの設定              */ 
0280:   fpr=mssOpenFPR(optINF.str,4);      /* 入力ファイルオープン                  */ 
0281:   hdi=mssReadHeader(fpr);            /* ヘッダの読み込み                      */ 
0282:  
0283:   path=setPath(optDIR.str,hdi);   /*path情報をセット*/ 
0284:  
0285:   /* optKeyをここで強制定義する*/ 
0286:   optKEY.set=1; 
0287:   optKEY.str=mssStrdup(path->optStr); 
0288:   optKEY.cnt=0; 
0289:   optKEY.nam=mssTokByChr(optKEY.str,',',&optKEY.cnt,1); /*,によるトークン分割*/ 
0290:   optKEY.diffSame=0; 
0291:   mssSetOptKey(&optKEY, hdi);        /* -k 項目をヘッダー項目に関連づける     */ 
0292:  
0293:   /*ソート項目の作成*/ 
0294:   sf=mssInitFields(); 
0295:   mssAddFieldsByFields(sf,optKEY.flds); /* -k 項目をソート項目としてセット    */ 
0296:   mssSetFieldsSortPriority(sf);         /* ソート優先順位番号を登録順にふる   */ 
0297:   sorted=mssChkSorted(sf,hdi);          /* ソート済かチェック                 */ 
0298:  
0299: /*----------------------------------------------------------------------------*/ 
0300: /*出力ヘッダーの作成と出力                                                    */ 
0301: /*----------------------------------------------------------------------------*/ 
0302:   /*出力ヘッダーの初期化(タイトル等のコピー)*/ 
0303:   hdo=mssInitCpyHeader(hdi); 
0304:      
0305:   /*入力ヘッダの全項目を追加*/ 
0306:   mssAddFieldsByFields(hdo->flds,hdi->flds);                                 
0307:      
0308:   /*ソートする必要があるならばsfのソート情報を反映*/                         
0309:   if(!sorted){ 
0310:     mssSetFieldsSort(hdo->flds,sf); 
0311:   } 
0312:  
0313: /*----------------------------------------------------------------------------*/ 
0314: /*メインルーチン                                                              */ 
0315: /*----------------------------------------------------------------------------*/ 
0316:   /*ソートが必用ならばソートしてソート済みファイルとしてオープン*/ 
0317:   if(!sorted) 
0318:     fpr=mssReopenFPRsort(fpr,4,sf,hdi->flds->cnt,optTMP.str); 
0319:  
0320:   frd=mssInitFRD(hdi->flds->cnt); 
0321:   while( EOF!=mssReadFRD(fpr,frd) ){ 
0322:  
0323:     if(mssGV.inCnt==0){ 
0324:       setPathName(pathName,path,frd,&optKEY); 
0325:       fpw=mssOpenFPW(pathName,optZIP.set,optFRC.set); 
0326:       mssWriteHeader(hdo, fpw); 
0327:     } 
0328:  
0329:     /*キーブレイク時の処理*/ 
0330:     if(mssKeyBreak(frd, &optKEY)){ 
0331:       mssWriteFooter(fpw);    /*フッターの出力*/ 
0332:       mssCloseFPW(fpw);                /*出力ファイルのクローズ*/ 
0333:       if(frd->eof) break; 
0334:       setPathName(pathName,path,frd,&optKEY); 
0335:       fpw=mssOpenFPW(pathName,optZIP.set,optFRC.set); 
0336:       mssWriteHeader(hdo, fpw); 
0337:     } 
0338:  
0339:     mssGV.inCnt++; 
0340:     count++; 
0341:  
0342:     /*通常行の処理*/ 
0343:     mssWriteFld(frd->pnt[frd->new],frd->fldCnt,"\n",fpw); 
0344:     mssGV.outCnt++; 
0345:   } 
0346:   mssFreeFRD(frd); 
0347:   mssFreeFields(path->flds); 
0348:   mssFree(path->optStr); 
0349:   mssFree(path); 
0350:   mssFree(optKEY.str); 
0351:   mssFree(*optKEY.nam); 
0352:   mssFree(optKEY.nam); 
0353:  
0354: /*----------------------------------------------------------------------------*/ 
0355: /*フッター出力&終了処理                                                       */ 
0356: /*----------------------------------------------------------------------------*/ 
0357:   mssCloseFPR(fpr);       /*入力ファイルのクローズ      */ 
0358:   mssFreeFields(sf);      /* ソート項目構造体の領域開放 */ 
0359:   mssFreeHeader(hdi);     /* 入力ヘッダ領域開放         */ 
0360:   mssFreeHeader(hdo);     /* 出力ヘッダ領域開放         */ 
0361:   mssFreeOption(opt);     /* オプション領域開放         */ 
0362:   mssShowEndMsg();        /* 完了メッセージ             */ 
0363:   mssEnd(mssExitSuccess); /* 終了                       */ 
0364:   return(0);              /* to avoid warning message   */ 
0365: }