MUSASHI C source: xtsed.c


0001: /*============================================================================*/ 
0002: /* 変更履歴                                                                   */ 
0003: /*----------------------------------------------------------------------------*/ 
0004: /* 1.0 : 新しいAPIに対応 2003/06/20                                           */ 
0005: /*============================================================================*/ 
0006:  
0007: #include <musashi.h
0008: #include <stdlib.h> 
0009: #include <string.h> 
0010: #include <sys/types.h> 
0011: #include <regex.h> 
0012:  
0013: #include <xtsedHelp.h> 
0014: struct mssComHelp comHelp={ 
0015:   "xtsed",        /* コマンド名       */ 
0016:   "1.0",          /* バージョン       */ 
0017:   HELPT,          /* コマンドタイトル */ 
0018:   HELPS,          /* 要約             */ 
0019:   HELPE,          /* 利用例           */ 
0020:   HELPR,          /* 参照コマンド     */ 
0021:   HELPA,          /* 作者情報         */ 
0022:   HELPB,          /* バグレポート情報 */ 
0023:   HELPH           /* ホームページ     */ 
0024: };   
0025:              
0026: extern struct mssGlobalVariables mssGV; 
0027:  
0028: /*置換文字(-v)を"&"でトークン分割した文字列リストを格納する構造体*/ 
0029: /*"&"の意味は、マッチした文字列に置き換えられる、ということ*/ 
0030: struct { 
0031:   int cnt; 
0032:   char **strList; 
0033: } REP; 
0034:  
0035: int   GLB; /*グローバル置換フラグ*/ 
0036: struct mssStrings *RepStr; 
0037: regex_t REG; 
0038:  
0039: static void repCat(char *str, regmatch_t *mp){ 
0040:   int i; 
0041:  
0042:   mssCatStrings(RepStr,*(REP.strList+0)); 
0043:   for(i=1; i<REP.cnt; i++){ 
0044:     mssCatnStrings(RepStr,str+mp->rm_so,mp->rm_eo-mp->rm_so); 
0045:     mssCatStrings(RepStr,*(REP.strList+i)); 
0046:   } 
0047: } 
0048:  
0049: /*文字列strのマッチした箇所を-vの文字で置き換え、RepStrにセット*/ 
0050: /*ex) str="abcde" reg="cd" v="###" -> RepStr="ab###" */ 
0051: static char *setRepStr(char *str){ 
0052:   regmatch_t mp; 
0053:  
0054:   if( 0!=regexec(&REG, str, 1, &mp,0) ){ 
0055:     mssCatStrings(RepStr,str);           /*マッチしなければstrをcat*/ 
0056:     return(NULL); 
0057:   }else{ 
0058:     mssCatnStrings(RepStr,str,mp.rm_so); /*マッチ位置までの文字列をcat*/ 
0059:     repCat(str,&mp);                  /*置換文字列をcatする*/ 
0060:     str=str+mp.rm_eo;                 /*次の文字列の先頭をセット*/ 
0061:     return(str); 
0062:   } 
0063: } 
0064:  
0065: static char *getRepStr(char *str){ 
0066:    
0067:   if(MssIsNull(str)) return(MssNullStr); 
0068:   mssFreeStrings(RepStr); 
0069:   RepStr=mssInitStrings(); 
0070:  
0071:   if(GLB){ 
0072:     while(1) { 
0073:       if( NULL == (str=setRepStr(str)) ){ 
0074:         break; 
0075:       } 
0076:     } 
0077:   }else{ 
0078:     str=setRepStr(str); 
0079:     if(NULL!=str) mssCatStrings(RepStr,str); 
0080:   } 
0081:   if(RepStr->cnt >= MssFieldMaxLen){ 
0082:     return(MssNullStr); 
0083:   }else if(mssIsValidStr(RepStr->str)){ 
0084:     return(RepStr->str); 
0085:   }else{ 
0086:     return(MssNullStr); 
0087:   } 
0088: } 
0089:  
0090: int main(int argc, char *argv[]){ 
0091: /*============================================================================*/ 
0092: /* オプション宣言&定義                                                       */ 
0093: /*============================================================================*//*----------------------------------------------------------------------------*/ 
0094: /* 対象項目                                                                   */ 
0095: /*----------------------------------------------------------------------------*/ 
0096:   MssOptFLD optFLD={ 
0097:     OFLD,   /* オプションタイプ                                             */ 
0098:     "f",    /* キーワード(複数文字は不可)                                   */ 
0099:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0100:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */ 
0101:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */ 
0102:     1,      /* 正規表現を許可するかどうか(0:不可,1:可)                      */ 
0103:     1,      /* 新項目名を指定できるかどうか(0:不可,1:可)                    */ 
0104:     NULL,   /* 項目オプション(%以下)で指定可能な文字                        */ 
0105:             /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能     */ 
0106:     FLDT,   /* このオプションのタイトル(Helpで表示)                         */ 
0107:     FLDC,   /* このオプションのコメント(Helpで表示)                         */ 
0108:     FLDF    /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る   */ 
0109:   }; 
0110:  
0111: /*----------------------------------------------------------------------------*/ 
0112: /* 正規表現                                                                   */ 
0113: /*----------------------------------------------------------------------------*/ 
0114:   MssOptSTR optREG={ 
0115:     OSTR,   /* オプションタイプ                                             */ 
0116:     "c",    /* キーワード(複数文字は不可)                                   */ 
0117:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0118:     NULL,   /* デフォルト                                                   */ 
0119:     1,      /* 文字列の最小長                                               */ 
0120:     100,    /* 文字列の最大長                                               */ 
0121:     REGT,   /* このオプションのタイトル(Helpで表示)                         */ 
0122:     REGC    /* このオプションのコメント(Helpで表示)                         */ 
0123:   }; 
0124:  
0125: /*----------------------------------------------------------------------------*/ 
0126: /* 置換文字列                                                                 */ 
0127: /*----------------------------------------------------------------------------*/ 
0128:   MssOptSTR optREP={ 
0129:     OSTR,   /* オプションタイプ                                             */ 
0130:     "v",    /* キーワード(複数文字は不可)                                   */ 
0131:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0132:     NULL,   /* デフォルト                                                   */ 
0133:     0,      /* 文字列の最小長                                               */ 
0134:     100,    /* 文字列の最大長                                               */ 
0135:     REPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0136:     REPC    /* このオプションのコメント(Helpで表示)                         */ 
0137:   }; 
0138:       
0139: /*----------------------------------------------------------------------------*/ 
0140: /* 新しい項目として出力するフラグ                                             */ 
0141: /*----------------------------------------------------------------------------*/ 
0142:   MssOptFLG optNEW={ 
0143:     OFLG,   /* オプションタイプ                                             */ 
0144:     "A",    /* キーワード(複数文字は不可)                                   */ 
0145:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0146:     NEWT,   /* このオプションのタイトル(Helpで表示)                         */ 
0147:     NEWC    /* このオプションのコメント(Helpで表示)                         */ 
0148:   }; 
0149:  
0150: /*----------------------------------------------------------------------------*/ 
0151: /* グローバル置換フラグ                                                       */ 
0152: /*----------------------------------------------------------------------------*/ 
0153:   MssOptFLG optGLB={ 
0154:     OFLG,   /* オプションタイプ                                             */ 
0155:     "g",    /* キーワード(複数文字は不可)                                   */ 
0156:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0157:     GLBT,   /* このオプションのタイトル(Helpで表示)                         */ 
0158:     GLBC    /* このオプションのコメント(Helpで表示)                         */ 
0159:   }; 
0160:  
0161: /*----------------------------------------------------------------------------*/ 
0162: /* 入力ファイル                                                               */ 
0163: /*----------------------------------------------------------------------------*/ 
0164:   MssOptINF optINF={ 
0165:     OINF,   /* オプションタイプ                                             */ 
0166:     "i",    /* キーワード(複数文字は不可)                                   */ 
0167:     0,      /* 0:オプション, 1:必須                                         */ 
0168:     1,      /* 指定可能の最大ファイル数                                     */ 
0169:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0170:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0171:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0172:   }; 
0173:    
0174: /*----------------------------------------------------------------------------*/ 
0175: /* 出力ファイル                                                               */ 
0176: /*----------------------------------------------------------------------------*/ 
0177:   MssOptOTF optOTF={ 
0178:     OOTF,   /* オプションタイプ                                             */ 
0179:     "o",    /* キーワード(複数文字は不可)                                   */ 
0180:     0,      /* 0:オプション, 1:必須                                         */ 
0181:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0182:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0183:   }; 
0184:  
0185: /*----------------------------------------------------------------------------*/ 
0186: /* 圧縮出力                                                                   */ 
0187: /*----------------------------------------------------------------------------*/ 
0188:   MssOptFLG optZIP={ 
0189:     OFLG,   /* オプションタイプ                                             */ 
0190:     "z",    /* キーワード(複数文字は不可)                                   */ 
0191:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0192:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0193:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0194:   }; 
0195:  
0196: /*----------------------------------------------------------------------------*/ 
0197: /* plain text                                                                 */ 
0198: /*----------------------------------------------------------------------------*/ 
0199:   MssOptFLG optTXT={ 
0200:     OFLG,   /* オプションタイプ                                             */ 
0201:     "t",    /* キーワード(複数文字は不可)                                   */ 
0202:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0203:     TXTT,   /* このオプションのタイトル(Helpで表示)                         */ 
0204:     TXTC    /* このオプションのコメント(Helpで表示)                         */ 
0205:   }; 
0206:  
0207: /*----------------------------------------------------------------------------*/ 
0208: /* オプションをまとめる                                                       */ 
0209: /*----------------------------------------------------------------------------*/ 
0210:   void *opt[]={&optFLD,&optREG,&optREP,&optNEW,&optGLB, 
0211:                &optINF,&optOTF,&optZIP,&optTXT,NULL}; 
0212:  
0213: /*============================================================================*/ 
0214: /* 変数宣言&定義                                                             */ 
0215: /*============================================================================*/ 
0216:   struct mssHeader    *hdi; /*入力ファイル用<head>タグ格納構造体*/ 
0217:   struct mssHeader    *hdo; /*出力ファイル用<head>タグ格納構造体*/ 
0218:   struct mssFPR       *fpr; /*入力ファイル構造体                */ 
0219:   struct mssFPW       *fpw; /*出力ファイル構造体                */ 
0220:   struct mssFldRec    *fr;  /*項目-行バッファ構造体             */ 
0221:  
0222:   int i; 
0223:   char *pos; 
0224:   char tmp[MssFieldMaxLen]; 
0225:  
0226: /*----------------------------------------------------------------------------*/ 
0227: /* 前処理                                                                     */ 
0228: /*----------------------------------------------------------------------------*/ 
0229:   mssInit(argc,argv,&comHelp);       /* シグナル処理などの初期化              */ 
0230:   mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ                                */ 
0231:   mssSetOption(opt,argc,argv);       /* コマンドオプションの設定              */ 
0232:   fpr=mssOpenFPR(optINF.str,4);      /* 入力ファイルオープン                  */ 
0233:   hdi=mssReadHeader(fpr);            /* ヘッダの読み込み                      */ 
0234:   mssSetOptFld(&optFLD, hdi);        /* -f 項目をヘッダー項目に関連づける     */ 
0235:  
0236:   if( strchr(optREP.str,'*') != NULL ){ 
0237:     mssShowErrMsg("-v can not have NULL character"); 
0238:     mssEnd(mssErrorNoDefault); 
0239:   } 
0240:  
0241:   /*置換文字列の"&"によるトークン分割*/ 
0242:   /*ただし、\&のようなエスケープを処理するために、一旦&を*に変換して作成*/ 
0243:   /* "*"は指定できない文字なのでOK*/ 
0244:   /* また無意味な"\"は除外*/ 
0245:   i=0; 
0246:   pos=optREP.str; 
0247:   while(*pos!='\0'){ 
0248:     if(*pos=='\\'){ 
0249:       if( *(pos+1) == '&' ){ 
0250:         tmp[i]='&'; 
0251:         i++; 
0252:         pos++; 
0253:       } 
0254:     }else if(*pos=='&'){ 
0255:       tmp[i]='*'; i++; 
0256:     }else{ 
0257:       tmp[i]=*pos; i++; 
0258:     } 
0259:     pos++; 
0260:   } 
0261:   tmp[i]='\0'; 
0262:  
0263:   REP.strList=mssTokByChr(tmp,'*',&REP.cnt,1); 
0264:  
0265:   GLB =optGLB.set; /*グローバル置換*/ 
0266:  
0267:   /*正規表現のコンパイル*/ 
0268:   if(regcomp(&REG,optREG.str,REG_EXTENDED) ){ 
0269:     mssShowErrMsg("error in compiling regex"); 
0270:     mssEnd(mssErrorNoDefault); 
0271:   } 
0272:  
0273: /*----------------------------------------------------------------------------*/ 
0274: /*出力ヘッダーの作成と出力                                                    */ 
0275: /*----------------------------------------------------------------------------*/ 
0276:   /*出力ヘッダーの初期化(タイトル等のコピー)*/ 
0277:   hdo=mssInitCpyHeader(hdi); 
0278:  
0279:   /*入力ヘッダの全項目を追加*/ 
0280:  
0281:   /*新項目名を追加する*/ 
0282:   if(optNEW.set){ 
0283:     mssAddFieldsByFields(hdo->flds,hdi->flds); 
0284:     mssAddFieldsByStrList(hdo->flds,optFLD.newNam,optFLD.cnt); 
0285:  
0286:   /*-fで指定された項目は-fから、その他は入力ヘッダから項目を追加する*/ 
0287:   }else{ 
0288:     mssAddHeadOrOptFields(hdo->flds,hdi,&optFLD); 
0289:   } 
0290:  
0291:   /*標準出力オープン+ヘッダーの出力*/ 
0292:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); 
0293:   mssWriteHeader(hdo, fpw); 
0294:  
0295: /*----------------------------------------------------------------------------*/ 
0296: /*メインルーチン                                                              */ 
0297: /*----------------------------------------------------------------------------*/ 
0298:  
0299:   fr=mssInitFldRec(hdi->flds->cnt); 
0300:   RepStr=mssInitStrings(); 
0301:   while( EOF != mssReadFldRec(fpr,fr) ){ 
0302:     mssGV.inCnt++; 
0303:  
0304:     /*新項目追加の場合*/ 
0305:     if(optNEW.set){ 
0306:       mssWriteFld(fr->pnt,fr->fldCnt,"",fpw); 
0307:       for(i=0; i<optFLD.flds->cnt; i++){ 
0308:         mssWriteDlm(fpw); 
0309:         mssWriteStr(getRepStr(*(fr->pnt+MssFlds2num(optFLD.flds,i))),fpw); 
0310:       } 
0311:       mssWriteRet(fpw); 
0312:  
0313:     /*新項目置換の場合*/ 
0314:     }else{ 
0315:       for(i=0; i<hdi->flds->cnt; i++){ 
0316:         if( *(optFLD.fldNo2optNo+i)==-1){ 
0317:           mssWriteStr(*(fr->pnt+MssFlds2num(hdi->flds,i)),fpw); 
0318:         }else{ 
0319:           mssWriteStr(getRepStr(*(fr->pnt+MssFlds2num(hdi->flds,i))),fpw); 
0320:         } 
0321:         if(i==hdi->flds->cnt-1) mssWriteRet(fpw); 
0322:         else                    mssWriteDlm(fpw); 
0323:       } 
0324:     } 
0325:     mssGV.outCnt++; 
0326:   } 
0327:   mssFreeFldRec(fr); 
0328:   mssFreeStrings(RepStr); 
0329:   mssFree(*REP.strList); 
0330:   mssFree(REP.strList); 
0331:  
0332: /*----------------------------------------------------------------------------*/ 
0333: /*フッター出力&終了処理                                                       */ 
0334: /*----------------------------------------------------------------------------*/ 
0335: /*printf("allocCnt=%d\n",getAllocCnt());*/ 
0336:   mssWriteFooter(fpw);     /* フッターの出力             */ 
0337:   mssCloseFPR(fpr);        /* 入力ファイルのクローズ     */ 
0338:   mssCloseFPW(fpw);        /* 出力ファイルのクローズ     */ 
0339:   mssFreeHeader(hdi);      /* 入力ヘッダ領域開放         */ 
0340:   mssFreeHeader(hdo);      /* 出力ヘッダ領域開放         */ 
0341:   mssFreeOption(opt);      /* オプション領域開放         */ 
0342:   mssShowEndMsg();         /* 完了メッセージ             */ 
0343:   mssEnd(mssExitSuccess);  /* 終了                       */                    
0344:   return(0);               /* to avoid warning message   */ 
0345: }