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(®, 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(®,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: }