MUSASHI C source: csv2xt.c


0001: /*============================================================================*/ 
0002: /* 変更履歴                                                                   */ 
0003: /*----------------------------------------------------------------------------*/ 
0004: /* 1.0   : 新しいAPIに対応(2003/06)                                           */ 
0005: /*============================================================================*/ 
0006: #include <musashi.h
0007: #include <stdlib.h> 
0008: #include <string.h> 
0009:  
0010: #include <csv2xtHelp.h> 
0011: struct mssComHelp comHelp={ 
0012:   "csv2xt",       /* コマンド名       */ 
0013:   "1.0",          /* バージョン       */ 
0014:   HELPT,          /* コマンドタイトル */ 
0015:   HELPS,          /* 要約             */ 
0016:   HELPE,          /* 利用例           */ 
0017:   HELPR,          /* 参照コマンド     */ 
0018:   HELPA,          /* 作者情報         */ 
0019:   HELPB,          /* バグレポート情報 */ 
0020:   HELPH           /* ホームページ     */ 
0021: }; 
0022:  
0023: extern struct mssGlobalVariables mssGV; 
0024:  
0025: char **tokCsvByChr(char *string, char tok, int *cnt){ 
0026:   char *str; 
0027:   char *pos; 
0028:   char **list=NULL; 
0029:   int outQuote; 
0030:  
0031:   *cnt=0; 
0032:   str=string; 
0033:  
0034:   pos=str; 
0035:   outQuote=1; /*""の外ならば1、さもなければ-1*/ 
0036:   while(1){ 
0037:     if(*str=='"') outQuote=outQuote*(-1); 
0038:       if( (outQuote==1 && *str==tok) || *str=='\0'){ 
0039:         list=mssRealloc(list,sizeof(char *)*(*cnt+1),"tokByChr"); 
0040:         *(list+*cnt)=pos; 
0041:         (*cnt)++; 
0042:         pos=str+1; 
0043:         if(*str=='\0') break; 
0044:         *str='\0'; 
0045:       } 
0046:     str++; 
0047:   } 
0048:   return(list); 
0049: } 
0050:  
0051: char *conv(char *str,char spcChr){ 
0052:   char *start; 
0053:  
0054:   start=str; 
0055:   if(*str=='"'){ 
0056:     str++; 
0057:     start++; 
0058:   } 
0059:  
0060:   while(*str!='\0'){ 
0061:     if(*str=='"'){ 
0062:       *str='\0'; 
0063:       break; 
0064:     } 
0065:     if(*str==' '){ 
0066:       *str=spcChr; 
0067:     } 
0068:     str++; 
0069:   } 
0070:   return(start); 
0071: } 
0072:  
0073:  
0074: int main(int argc, char *argv[]){ 
0075: /*============================================================================*/ 
0076: /* オプション宣言&定義                                                       */ 
0077: /*============================================================================*/ 
0078: /*----------------------------------------------------------------------------*/ 
0079: /* 一行目を項目名とみなすフラグ                                               */ 
0080: /*----------------------------------------------------------------------------*/ 
0081:   MssOptFLG optHFD={ 
0082:     OFLG,   /* オプションタイプ                                             */ 
0083:     "F",    /* キーワード(複数文字は不可)                                   */ 
0084:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0085:     HFDT,   /* このオプションのタイトル(Helpで表示)                         */ 
0086:     HFDC    /* このオプションのコメント(Helpで表示)                         */ 
0087:   }; 
0088:  
0089: /*----------------------------------------------------------------------------*/ 
0090: /* 新項目名                                                                   */ 
0091: /*----------------------------------------------------------------------------*/ 
0092:   MssOptSLS optFNM={ 
0093:     OSLS,   /* オプションタイプ                                             */ 
0094:     "a",    /* キーワード(複数文字は不可)                                   */ 
0095:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0096:     NULL,   /* デフォルト(文字列)                                           */ 
0097:     MssFieldMaxCnt, /* カンマで区切られる要素数の最大値                     */ 
0098:     1,      /* 各要素の文字列長の最小値                                     */ 
0099:     MssFieldNameMaxLen,/* 各要素の文字列長の最大値                          */ 
0100:     0,      /* 1:要素にコロンを指定できる,0:不可  ex) aaaa:xxxxx            */ 
0101:     FNMT,   /* このオプションのタイトル(Helpで表示)                         */ 
0102:     FNMC    /* このオプションのコメント(Helpで表示)                         */ 
0103:   };  
0104:  
0105: /*----------------------------------------------------------------------------*/ 
0106: /* タイトル                                                                   */ 
0107: /*----------------------------------------------------------------------------*/ 
0108:   MssOptSTR optTIT={ 
0109:     OSTR,   /* オプションタイプ                                             */ 
0110:     "l",    /* キーワード(複数文字は不可)                                   */ 
0111:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0112:     NULL,   /* デフォルト                                                   */ 
0113:     0,      /* 文字列の最小長                                               */ 
0114:     MssTitleMaxLen,    /* 文字列の最大長                                    */ 
0115:     TITT,   /* このオプションのタイトル(Helpで表示)                         */ 
0116:     TITC    /* このオプションのコメント(Helpで表示)                         */ 
0117:   }; 
0118:  
0119: /*----------------------------------------------------------------------------*/ 
0120: /* コメント                                                                   */ 
0121: /*----------------------------------------------------------------------------*/ 
0122:   MssOptSTR optCOM={ 
0123:     OSTR,   /* オプションタイプ                                             */ 
0124:     "c",    /* キーワード(複数文字は不可)                                   */ 
0125:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0126:     NULL,   /* デフォルト                                                   */ 
0127:     0,      /* 文字列の最小長                                               */ 
0128:     MssCommentMaxLen,/* 文字列の最大長                                      */ 
0129:     COMT,   /* このオプションのタイトル(Helpで表示)                         */ 
0130:     COMC    /* このオプションのコメント(Helpで表示)                         */ 
0131:   }; 
0132:  
0133: /*----------------------------------------------------------------------------*/ 
0134: /* spaceを何に変換するか                                                      */ 
0135: /*----------------------------------------------------------------------------*/ 
0136:   MssOptSTR optSPC={  
0137:     OSTR,   /* オプションタイプ                                             */ 
0138:     "S",    /* キーワード(複数文字は不可)                                   */ 
0139:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0140:     "_",    /* デフォルト                                                   */ 
0141:     1,      /* 文字列の最小長                                               */ 
0142:     1,      /* 文字列の最大長                                               */ 
0143:     SPCT,   /* このオプションのタイトル(Helpで表示)                         */ 
0144:     SPCC    /* このオプションのコメント(Helpで表示)                         */ 
0145:   }; 
0146:  
0147: /*----------------------------------------------------------------------------*/ 
0148: /* インポートファイル                                                         */ 
0149: /*----------------------------------------------------------------------------*/ 
0150:   MssOptINF optIMP={ 
0151:     OINF,   /* オプションタイプ                                             */ 
0152:     "I",    /* キーワード(複数文字は不可)                                   */ 
0153:     0,      /* 0:オプション, 1:必須                                         */ 
0154:     1,      /* 指定可能の最大ファイル数                                     */ 
0155:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0156:     IMPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0157:     IMPC    /* このオプションのコメント(Helpで表示)                         */ 
0158:   }; 
0159:  
0160: /*----------------------------------------------------------------------------*/ 
0161: /* 入力ファイル                                                               */ 
0162: /*----------------------------------------------------------------------------*/ 
0163:   MssOptINF optINF={ 
0164:     OINF,   /* オプションタイプ                                             */ 
0165:     "i",    /* キーワード(複数文字は不可)                                   */ 
0166:     0,      /* 0:オプション, 1:必須                                         */ 
0167:     1,      /* 指定可能の最大ファイル数                                     */ 
0168:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0169:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0170:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0171:   }; 
0172:  
0173: /*----------------------------------------------------------------------------*/ 
0174: /* 出力ファイル                                                               */ 
0175: /*----------------------------------------------------------------------------*/ 
0176:   MssOptOTF optOTF={ 
0177:     OOTF,   /* オプションタイプ                                             */ 
0178:     "o",    /* キーワード(複数文字は不可)                                   */ 
0179:     0,      /* 0:オプション, 1:必須                                         */ 
0180:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0181:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0182:   }; 
0183:  
0184: /*----------------------------------------------------------------------------*/ 
0185: /* 圧縮出力                                                                   */ 
0186: /*----------------------------------------------------------------------------*/ 
0187:   MssOptFLG optZIP={ 
0188:     OFLG,   /* オプションタイプ                                             */ 
0189:     "z",    /* キーワード(複数文字は不可)                                   */ 
0190:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0191:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0192:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0193:   }; 
0194:  
0195: /*----------------------------------------------------------------------------*/ 
0196: /* オプションをまとめる                                                       */ 
0197: /*----------------------------------------------------------------------------*/ 
0198:   void *opt[]={&optHFD,&optFNM,&optTIT,&optCOM,&optSPC,&optIMP, 
0199:                &optINF,&optOTF,&optZIP,NULL}; 
0200:  
0201: /*============================================================================*/ 
0202: /* 変数宣言&定義                                                             */ 
0203: /*============================================================================*/ 
0204:   struct mssHeader *hdi; /*テキストファイル用<head>タグ格納構造体*/ 
0205:   struct mssHeader *hdI; /*-I入力ファイル用<head>タグ格納構造体*/ 
0206:   struct mssHeader *hdo; /*出力ファイル用<head>タグ格納構造体*/ 
0207:   struct mssFPR    *fpr; /*入力ファイル構造体*/ 
0208:   struct mssFPR    *fpr2;/*インポートファイル構造体*/ 
0209:   struct mssFPW    *fpw; /*出力ファイル構造体*/ 
0210:   struct mssFldRec *fr;  /*項目-行バッファ構造体*/ 
0211:   struct mssRec    *rec; /*行バッファ構造体*/ 
0212:  
0213:   char         **fldLst; 
0214:   char          *str; 
0215:   int            fldCnt; 
0216:   int            i; 
0217:  
0218: /*----------------------------------------------------------------------------*/ 
0219: /* 前処理                                                                     */ 
0220: /*----------------------------------------------------------------------------*/ 
0221:   mssInit(argc,argv,&comHelp);        /* シグナル処理などの初期化     */ 
0222:   mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ                       */ 
0223:   mssSetOption(opt,argc,argv);        /* コマンドオプションの設定     */ 
0224:   fpr=mssOpenFPR(optINF.str,4);       /* 入力ファイルオープン         */ 
0225:  
0226: /*prnOption(opt);*/ 
0227: /*prnHeader(hdi);*/ 
0228:  
0229:   /*-I,-F,-a,いずれも指定されなかったとき*/ 
0230:   if(!optIMP.set && !optHFD.set && !optFNM.set){ 
0231:     mssShowErrMsg("choose one option in -a,-F,-I"); 
0232:     mssEnd(mssErrorNoDefault); 
0233:   } 
0234:  
0235:   /*-I,-F,-a,の中で2つ以上指定された*/ 
0236:   if(optIMP.set+optHFD.set+optFNM.set > 1){ 
0237:     mssShowErrMsg("choose one option in -a,-F,-I"); 
0238:     mssEnd(mssErrorNoDefault); 
0239:   } 
0240:      
0241:   mssGV.txtFlg=1;            /* 強制的にon*/ 
0242:   hdi=mssReadHeader(fpr);    /* ヘッダの読み込み             */ 
0243:   mssGV.txtFlg=0;            /* そしてoff*/ 
0244:  
0245: /*----------------------------------------------------------------------------*/ 
0246: /*出力ヘッダーの作成と出力                                                    */ 
0247: /*----------------------------------------------------------------------------*/ 
0248:   fr=mssInitFldRec(hdi->flds->cnt); 
0249:   rec=mssInitRec(); 
0250:  
0251:   if(optIMP.set){ /*-Iフラグon (ヘッダーのインポート)*/ 
0252:     fpr2=mssOpenFPR(optIMP.str,4);             /*インポートファイルオープン*/ 
0253:     hdI=mssReadHeader(fpr2);                   /*項目名情報の読み込み*/ 
0254:     hdo=mssInitCpyHeader(hdI);                 /*出力ヘッダー初期化*/ 
0255:     mssAddFieldsByFields(hdo->flds,hdI->flds); /*hdIヘッダーの項目情報をコピー*/ 
0256:     mssCloseFPR(fpr2);                         /*インポートファイルクローズ*/ 
0257:   }else{ 
0258:     /*出力ヘッダー初期化*/ 
0259:     hdo=mssInitHeader(optTIT.str,optCOM.str); 
0260:  
0261:     /*項目情報の設定*/ 
0262:  
0263:     /*-Fフラグon*/ 
0264:     if(optHFD.set){ 
0265:       if( EOF == mssReadRec(fpr,rec) ){ 
0266:         mssShowErrMsg("can not read input file"); 
0267:         mssEnd(mssErrorNoDefault); 
0268:       } 
0269:       fldLst=tokCsvByChr(rec->pnt,',',&fldCnt); 
0270:       for(i=0; i<fldCnt; i++){ 
0271:         *(fldLst+i)=conv(*(fldLst+i),*optSPC.str); 
0272:         if(*(fldLst+i)=='\0'){ 
0273:           mssShowErrMsg("detected null in field name"); 
0274:           mssEnd(mssErrorNoDefault); 
0275:         } 
0276:       } 
0277:       mssAddFieldsByStrList(hdo->flds, fldLst, fldCnt); 
0278:       mssFree(fldLst); 
0279:     } 
0280:  
0281:     /*-aが指定されたとき*/ 
0282:     if(optFNM.set){ 
0283:       mssAddFieldsByStrList(hdo->flds, optFNM.strList, optFNM.cnt); 
0284:     } 
0285:   } 
0286:  
0287:   /*標準出力オープン+ヘッダーの出力*/ 
0288:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); 
0289:   mssWriteHeader(hdo,fpw); 
0290:  
0291: /*----------------------------------------------------------------------------*/ 
0292: /*メインルーチン                                                              */ 
0293: /*----------------------------------------------------------------------------*/ 
0294:  
0295:   while( EOF != mssReadRec(fpr,rec)){ 
0296:     mssGV.inCnt++; 
0297:     fldLst=tokCsvByChr(rec->pnt,',',&fldCnt); 
0298:     if(fldCnt!=hdo->flds->cnt) { 
0299:       mssShowErrMsg("detected different number of fields in line %d(header has %d, but a record has %d)",mssGV.inCnt,hdo->flds->cnt,fldCnt); 
0300:       mssEnd(mssErrorNoDefault); 
0301:     } 
0302:     for(i=0; i<fldCnt; i++){ 
0303:       str=conv(*(fldLst+i),*optSPC.str); 
0304:       if(*str=='\0'){ 
0305:         mssWriteStr("*",fpw); 
0306:         if(i==fldCnt-1) mssWriteRet(fpw); 
0307:         else            mssWriteDlm(fpw); 
0308:       }else{ 
0309:         mssWriteStr(str,fpw); 
0310:         if(i==fldCnt-1) mssWriteRet(fpw); 
0311:         else            mssWriteDlm(fpw); 
0312:       } 
0313:     } 
0314:     mssFree(fldLst); 
0315:     mssGV.outCnt++; 
0316:   } 
0317:  
0318:   mssFreeRec(rec); 
0319:   mssFreeFldRec(fr); 
0320:  
0321: /*----------------------------------------------------------------------------*/ 
0322: /*フッター出力&終了処理                                                       */ 
0323: /*----------------------------------------------------------------------------*/ 
0324:   mssWriteFooter(fpw);    /*フッターの出力*/ 
0325:   mssCloseFPR(fpr);       /*入力ファイルのクローズ*/ 
0326:   mssCloseFPW(fpw);       /*出力ファイルのクローズ*/ 
0327:   mssFreeHeader(hdi);     /*入力ヘッダ領域開放*/ 
0328:   mssFreeHeader(hdo);     /*出力ヘッダ領域開放*/ 
0329:   mssFreeOption(opt);     /*オプション領域開放*/ 
0330:   mssShowEndMsg();        /*完了メッセージ*/ 
0331:   mssEnd(mssExitSuccess); /*終了*/ 
0332:   return(0); /* to avoid warning message*/ 
0333: }