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: }