MUSASHI C source: xt2html.c
0001: /*============================================================================*/
0002: /* 変更履歴 */
0003: /*----------------------------------------------------------------------------*/
0004: /* 1.0 : 新しいAPIに対応(2003/06) */
0005: /*============================================================================*/
0006:
0007: #include <musashi.h>
0008: #include <stdlib.h>
0009: #include <string.h>
0010:
0011: #include <xt2htmlHelp.h>
0012: struct mssComHelp comHelp={
0013: "xt2html", /* コマンド名 */
0014: "1.1", /* バージョン */
0015: HELPT, /* コマンドタイトル */
0016: HELPS, /* 要約 */
0017: HELPE, /* 利用例 */
0018: HELPR, /* 参照コマンド */
0019: HELPA, /* 作者情報 */
0020: HELPB, /* バグレポート情報 */
0021: HELPH /* ホームページ */
0022: };
0023:
0024: extern struct mssGlobalVariables mssGV;
0025:
0026: int keyBreak(char **old, char **new, int fldNo)
0027: {
0028: if( 0!=strcmp(*(old+fldNo),*(new+fldNo)) ){
0029: return(1);
0030: }else{
0031: return(0);
0032: }
0033: }
0034:
0035: void cpyToOldRec(char **old, char **new, int fldCnt)
0036: {
0037: int i;
0038: for(i=0; i<fldCnt; i++){
0039: mssFree(*(old+i));
0040: *(old+i)=mssStrdup(*(new+i));
0041: }
0042: }
0043:
0044: int main(int argc, char *argv[]){
0045: /*============================================================================*/
0046: /* オプション宣言&定義 */
0047: /*============================================================================*/
0048: /*----------------------------------------------------------------------------*/
0049: /* キー項目 */
0050: /*----------------------------------------------------------------------------*/
0051: MssOptKEY optKEY={
0052: OKEY, /* オプションタイプ */
0053: "k", /* キーワード(複数文字は不可) */
0054: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0055: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0056: "i", /* 対象とする入力データのキーワード(GUIで利用) */
0057: 1, /* デフォルト(このオプションが指定されなかったときの動作を指定) */
0058: /* 1:全ての行を異るキー値として扱う */
0059: /* 2:全ての行を同じキー値として扱う) */
0060: KEYT, /* このオプションのタイトル(Helpで表示) */
0061: KEYC /* このオプションのコメント(Helpで表示) */
0062: };
0063:
0064: /*----------------------------------------------------------------------------*/
0065: /* 右詰め対象項目 */
0066: /*----------------------------------------------------------------------------*/
0067: MssOptFLD optRIT={
0068: OFLD, /* オプションタイプ */
0069: "R", /* キーワード(複数文字は不可) */
0070: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0071: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0072: "i", /* 対象とする入力データのキーワード(GUIで利用) */
0073: 1, /* 正規表現を許可するかどうか(0:不可,1:可) */
0074: 0, /* 新項目名を指定できるかどうか(0:不可,1:可) */
0075: NULL, /* 項目オプション(%以下)で指定可能な文字 */
0076: /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能 */
0077: RITT, /* このオプションのタイトル(Helpで表示) */
0078: RITC, /* このオプションのコメント(Helpで表示) */
0079: RITF /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る */
0080: };
0081:
0082: /*----------------------------------------------------------------------------*/
0083: /* 中央揃え対象項目 */
0084: /*----------------------------------------------------------------------------*/
0085: MssOptFLD optCNT={
0086: OFLD, /* オプションタイプ */
0087: "C", /* キーワード(複数文字は不可) */
0088: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0089: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0090: "i", /* 対象とする入力データのキーワード(GUIで利用) */
0091: 1, /* 正規表現を許可するかどうか(0:不可,1:可) */
0092: 0, /* 新項目名を指定できるかどうか(0:不可,1:可) */
0093: NULL, /* 項目オプション(%以下)で指定可能な文字 */
0094: /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能 */
0095: CNTT, /* このオプションのタイトル(Helpで表示) */
0096: CNTC, /* このオプションのコメント(Helpで表示) */
0097: CNTF /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る */
0098: };
0099:
0100: /*----------------------------------------------------------------------------*/
0101: /* シーケンシャル処理 */
0102: /*----------------------------------------------------------------------------*/
0103: MssOptFLG optSEQ={
0104: OFLG, /* オプションタイプ */
0105: "q", /* キーワード(複数文字は不可) */
0106: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0107: SEQT, /* このオプションのタイトル(Helpで表示) */
0108: SEQC /* このオプションのコメント(Helpで表示) */
0109: };
0110:
0111: /*----------------------------------------------------------------------------*/
0112: /* 入力ファイル */
0113: /*----------------------------------------------------------------------------*/
0114: MssOptINF optINF={
0115: OINF, /* オプションタイプ */
0116: "i", /* キーワード(複数文字は不可) */
0117: 0, /* 0:オプション, 1:必須 */
0118: 1, /* 指定可能の最大ファイル数 */
0119: 0, /*1:file not foundのエラーで終了しない 0:する */
0120: INFT, /* このオプションのタイトル(Helpで表示) */
0121: INFC /* このオプションのコメント(Helpで表示) */
0122: };
0123:
0124: /*----------------------------------------------------------------------------*/
0125: /* 出力ファイル */
0126: /*----------------------------------------------------------------------------*/
0127: MssOptOTF optOTF={
0128: OOTF, /* オプションタイプ */
0129: "o", /* キーワード(複数文字は不可) */
0130: 0, /* 0:オプション, 1:必須 */
0131: OTFT, /* このオプションのタイトル(Helpで表示) */
0132: OTFC /* このオプションのコメント(Helpで表示) */
0133: };
0134:
0135: /*----------------------------------------------------------------------------*/
0136: /* 圧縮出力 */
0137: /*----------------------------------------------------------------------------*/
0138: MssOptFLG optZIP={
0139: OFLG, /* オプションタイプ */
0140: "z", /* キーワード(複数文字は不可) */
0141: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0142: ZIPT, /* このオプションのタイトル(Helpで表示) */
0143: ZIPC /* このオプションのコメント(Helpで表示) */
0144: };
0145:
0146: /*----------------------------------------------------------------------------*/
0147: /* ワークファイル用ディレクトリ名 */
0148: /*----------------------------------------------------------------------------*/
0149: MssOptSTR optTMP={
0150: OSTR, /* オプションタイプ */
0151: "T", /* キーワード(複数文字は不可) */
0152: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0153: MssTempDir, /* デフォルト */
0154: 1, /* 文字列の最小長 */
0155: MssFileNameMaxLen, /* 文字列の最大長 */
0156: TMPT, /* このオプションのタイトル(Helpで表示) */
0157: TMPC /* このオプションのコメント(Helpで表示) */
0158: };
0159:
0160: /*----------------------------------------------------------------------------*/
0161: /* オプションをまとめる */
0162: /*----------------------------------------------------------------------------*/
0163: void *opt[]={&optKEY,&optRIT,&optCNT,&optSEQ,&optINF,&optOTF,&optZIP,&optTMP,NULL};
0164:
0165: /*============================================================================*/
0166: /* 変数宣言&定義 */
0167: /*============================================================================*/
0168: struct mssHeader *hdi; /*入力ファイル用<head>タグ格納構造体*/
0169:
0170: struct mssFPR *fpr; /*入力ファイル構造体*/
0171: struct mssFPW *fpw; /*出力ファイル構造体*/
0172: struct mssFldRecKey *frk=NULL;/*キー単位バッファ構造体 */
0173: struct mssFields *sf; /*ソート項目構造体 */
0174: struct mssFldRec *fr=NULL;/*項目バッファ構造体*/
0175: int sorted; /*ソート済チェック用 */
0176:
0177: struct mssXmlTag *htmlTag;
0178: struct mssXmlTag *headTag;
0179: struct mssXmlTag *metaTag;
0180: struct mssXmlTag *bodyTag;
0181: struct mssXmlTag *tableTag;
0182: struct mssXmlTag *trTag;
0183: struct mssXmlTag *thTag;
0184: struct mssXmlTag *tdTag;
0185:
0186: MssOptKEY pkey; /*最も外側のキー項目*/
0187:
0188: char **oldRec;
0189: int recNo;
0190: int fldNo;
0191: int cmp;
0192: int *rspan;
0193: int rspanCnt;
0194: char *str;
0195: int i,j,k;
0196:
0197: /*------------------------------------------------------------------------------
0198: パラメータ処理
0199: ------------------------------------------------------------------------------*/
0200: mssInit(argc,argv,&comHelp); /* シグナル処理などの初期化 */
0201: mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ */
0202: mssSetOption(opt,argc,argv); /* コマンドオプションの設定 */
0203: fpr=mssOpenFPR(optINF.str,4); /* 入力ファイルオープン */
0204: hdi=mssReadHeader(fpr); /* ヘッダの読み込み */
0205: mssSetOptKey(&optKEY, hdi); /* -k 項目をヘッダー項目に関連づける */
0206: mssSetOptFld(&optRIT, hdi); /* -R 項目をヘッダー項目に関連づける */
0207: mssSetOptFld(&optCNT, hdi); /* -C 項目をヘッダー項目に関連づける */
0208:
0209: /*ソート項目の作成*/
0210: sf=mssInitFields();
0211: mssAddFieldsByFields(sf,optKEY.flds); /* -k 項目をソート項目としてセット */
0212: mssSetFieldsSortPriority(sf); /* ソート優先順位番号を登録順にふる */
0213: sorted=mssChkSorted(sf,hdi); /* ソート済かチェック */
0214:
0215: /*mssShowOption(opt);*/
0216: /*mssShowHeader(hdi);*/
0217:
0218: /*----------------------------------------------------------------------------*/
0219: /*出力ヘッダーの作成と出力 */
0220: /*----------------------------------------------------------------------------*/
0221: /*標準出力オープン+ヘッダーの出力*/
0222: fpw=mssOpenFPW(optOTF.str,optZIP.set,0);
0223:
0224: /* <html> */
0225: htmlTag=mssInitXmlTag("html",NULL);
0226: mssWriteXmlStartTag(htmlTag,NULL,fpw);
0227: mssWriteRet(fpw);
0228:
0229: /* <head> */
0230: headTag=mssInitXmlTag("head",NULL);
0231: mssWriteXmlStartTag(headTag,NULL,fpw);
0232: mssWriteRet(fpw);
0233:
0234: /* <meta> */
0235: str=mssCatTwoStrings("text/html;Content-Type;charset=",hdi->xmlenc);
0236: metaTag=mssInitXmlTag("meta",NULL);
0237: mssAddXmlTagAttributeStr(metaTag,"http-equiv", "Content-Type", NULL);
0238: mssAddXmlTagAttributeStr(metaTag,"content" , str, NULL);
0239:
0240: /* <title> */
0241: mssWriteXmlTagStr(0,"TITLE",hdi->title,1,NULL,fpw);
0242:
0243: /* </head> */
0244: mssWriteXmlEndTag(headTag,NULL,fpw);
0245: mssWriteRet(fpw);
0246:
0247: /* <body> */
0248: bodyTag=mssInitXmlTag("BODY",NULL);
0249: mssWriteXmlStartTag(bodyTag,NULL,fpw);
0250: mssWriteRet(fpw);
0251:
0252: /* <h1>タイトル</H1> */
0253: mssWriteXmlTagStr(0,"H1",hdi->title,1,NULL,fpw);
0254:
0255: /* <P>コメント</P> */
0256: mssWriteXmlTagStr(0,"P",hdi->comment,1,NULL,fpw);
0257:
0258: /* <table border="1"> */
0259: tableTag=mssInitXmlTag("table",NULL);
0260: mssAddXmlTagAttributeStr(tableTag,"border", "1", NULL);
0261: mssWriteXmlStartTag(tableTag,NULL,fpw);
0262: mssWriteRet(fpw);
0263:
0264: /* <TR> */
0265: trTag=mssInitXmlTag("TR",NULL);
0266: mssWriteXmlStartTag(trTag,NULL,fpw);
0267: mssWriteRet(fpw);
0268:
0269: /* <TH>項目名</TH> */
0270: for(i=0; i<hdi->flds->cnt; i++){
0271: thTag=mssInitXmlTag("TH",NULL);
0272:
0273: /*文字位置*/
0274: /*
0275: if(optRIT.set){
0276: if(*(optRIT.fldNo2optNo+i) != -1){
0277: mssAddXmlTagAttributeStr(thTag,"ALIGN","right",NULL);
0278: }
0279: }
0280: if(optCNT.set){
0281: if(*(optCNT.fldNo2optNo+i) != -1){
0282: mssAddXmlTagAttributeStr(thTag,"ALIGN","center",NULL);
0283: }
0284: }
0285: */
0286:
0287: /*THのバックのカラー*/
0288: mssAddXmlTagAttributeStr(thTag,"BGCOLOR","#00ffff",NULL);
0289:
0290: /*THの出力*/
0291: mssWriteXmlStartTag(thTag,NULL,fpw);
0292: mssWriteXmlContent(MssFlds2name(hdi->flds,i),NULL,fpw);
0293: mssWriteXmlEndTag(thTag,NULL,fpw);
0294: mssFreeXmlTag(thTag);
0295: }
0296:
0297: /* </TR> */
0298: mssWriteXmlEndTag(trTag,NULL,fpw);
0299: mssWriteRet(fpw);
0300:
0301: /*----------------------------------------------------------------------------*/
0302: /*メインルーチン */
0303: /*----------------------------------------------------------------------------*/
0304: /*キーがセットされていれば*/
0305: if(optKEY.set){
0306: /*最初の項目のみpkeyにセットする*/
0307: pkey.set=0;
0308: pkey.diffSame=optKEY.diffSame;
0309: pkey.cnt=1;
0310: pkey.flds=mssInitFields();
0311: mssAddFieldsByFldInfo(pkey.flds,*(optKEY.flds->fi+0));
0312:
0313: /*ソートが必用ならばソートしてソート済みファイルとしてオープン*/
0314: if(!optSEQ.set && !sorted)
0315: fpr=mssReopenFPRsort(fpr,4,sf,hdi->flds->cnt,optTMP.str);
0316:
0317: /*FRK構造体の初期化*/
0318: frk=mssInitFRK(hdi->flds->cnt, &pkey,optTMP.str);
0319:
0320: /*oldRecの初期化*/
0321: oldRec=mssMalloc(sizeof(char*)*hdi->flds->cnt, "xt2html");
0322: for(i=0; i<hdi->flds->cnt; i++){
0323: *(oldRec+i)=mssStrdup("");
0324: }
0325:
0326: while(1){
0327: /*データ読み込み*/
0328: if(EOF==mssReadFRK(fpr,frk)) break;
0329: mssGV.inCnt+=frk->keyRecCnt;
0330: rspan=mssMalloc(sizeof(int)*frk->keyRecCnt*optKEY.flds->cnt,"xt2html");
0331:
0332: /*各キー項目の値がいくつの行を結合するかを計算*/
0333: recNo=0;
0334: while( EOF != mssReadFldRecFRK(frk) ){
0335:
0336: /* -k no1,no2,no3 の時、no1の値が同じ行のデータがfrkに読み込まれている
0337: そこで、no1,no2,no3についてのキーブレーク表を作成する(rspan)
0338: no1 no2 no3 rspan
0339: k a x 1 1 1
0340: k a x 0 0 0
0341: k a y -> 0 0 1
0342: k b y 0 1 1
0343: k b y 0 0 0
0344: k b z 0 0 1
0345: */
0346: for(i=1; i<optKEY.flds->cnt; i++){
0347: cmp=keyBreak(oldRec,frk->pnt,MssFlds2num(optKEY.flds,i));
0348: *(rspan+recNo*optKEY.flds->cnt+i)=cmp;
0349: if(cmp==1){
0350: for(j=i+1; j<optKEY.flds->cnt; j++){
0351: i++;
0352: *(rspan+recNo*optKEY.flds->cnt+j)=cmp;
0353: }
0354: }
0355: }
0356: cpyToOldRec(oldRec,frk->pnt,frk->fldCnt);
0357: recNo++;
0358: }
0359: *rspan=1;
0360: for(i=1; i<frk->keyRecCnt; i++){
0361: *(rspan+i*optKEY.flds->cnt+0)=0;
0362: }
0363:
0364: /* 上記で作成したキーブレーク表から、rowspanの数値(各項目の結合行数)
0365: を求める。
0366: rspan rspan
0367: 1 1 3 2
0368: 0 0 0 0
0369: 0 1 -> 0 1
0370: 1 1 3 2
0371: 0 0 0 0
0372: 0 1 0 1
0373: */
0374: for(i=0; i<frk->keyRecCnt; i++){
0375: for(j=0; j<optKEY.flds->cnt; j++){
0376: if(*(rspan+i*optKEY.flds->cnt+j) == 1 ){
0377: rspanCnt=1;
0378: for(k=i+1; k<frk->keyRecCnt; k++){
0379: if(*(rspan+k*optKEY.flds->cnt+j) == 1 ) break;
0380: rspanCnt++;
0381: }
0382: *(rspan+i*optKEY.flds->cnt+j) = rspanCnt;
0383: }
0384: }
0385: }
0386:
0387: /*
0388: for(i=0; i<frk->keyRecCnt; i++){
0389: printf("%d: ",i);
0390: for(j=0; j<optKEY.flds->cnt; j++){
0391: printf("%d ",*(rspan+i*optKEY.flds->cnt+j));
0392: }
0393: printf("\n");
0394: }
0395: */
0396:
0397: /*出力*/
0398: mssSeekTopFRK(frk);
0399: recNo=0;
0400: while( EOF != mssReadFldRecFRK(frk) ){
0401: /* <tr> */
0402: mssWriteXmlStartTag(trTag,NULL,fpw);
0403:
0404: fldNo=0;
0405: for(i=0; i<frk->fldCnt; i++){
0406: tdTag=mssInitXmlTag("TD",NULL);
0407:
0408: /*-kで指定された項目なら*/
0409: if(*(optKEY.fldNo2optNo+i) != -1){
0410: /*TDが必要ならROWSPANを設定、必要なければcontinure*/
0411: if( *(rspan+recNo*optKEY.flds->cnt+fldNo) != 0){
0412: mssAddXmlTagAttributeInt(tdTag,"ROWSPAN",
0413: *(rspan+recNo*optKEY.flds->cnt+fldNo), NULL);
0414: fldNo++;
0415: }else{
0416: fldNo++;
0417: continue;
0418: }
0419: }
0420:
0421: /*文字位置*/
0422:
0423: if(optRIT.set){
0424: if(*(optRIT.fldNo2optNo+i) != -1){
0425: mssAddXmlTagAttributeStr(tdTag,"ALIGN","right",NULL);
0426: }
0427: }
0428: if(optCNT.set){
0429: if(*(optCNT.fldNo2optNo+i) != -1){
0430: mssAddXmlTagAttributeStr(tdTag,"ALIGN","center",NULL);
0431: }
0432: }
0433:
0434: /*TDの出力*/
0435: mssWriteXmlStartTag(tdTag,NULL,fpw);
0436: mssWriteXmlContent(*(frk->pnt+i),NULL,fpw);
0437: mssWriteXmlEndTag(tdTag,NULL,fpw);
0438: mssFreeXmlTag(tdTag);
0439: }
0440:
0441: /* </TR> */
0442: mssWriteXmlEndTag(trTag,NULL,fpw);
0443: mssWriteRet(fpw);
0444: mssGV.outCnt++;
0445: recNo++;
0446: }
0447: mssFree(rspan);
0448: }
0449:
0450: /*oldRecの開放*/
0451: for(i=0; i<hdi->flds->cnt; i++){
0452: mssFree(*(oldRec+i));
0453: }
0454: mssFree(oldRec);
0455: mssFreeFRK(frk);
0456:
0457: /*キーがセットされていない*/
0458: }else{
0459: fr=mssInitFldRec(hdi->flds->cnt);
0460: while( EOF != mssReadFldRec(fpr,fr) ){
0461: mssGV.inCnt++;
0462:
0463: /* <TR> */
0464: mssWriteXmlStartTag(trTag,NULL,fpw);
0465:
0466: /* <TD> */
0467: for(i=0; i<fr->fldCnt; i++){
0468: tdTag=mssInitXmlTag("TD",NULL);
0469:
0470: /*文字位置*/
0471: if(optRIT.set){
0472: if(*(optRIT.fldNo2optNo+i) != -1){
0473: mssAddXmlTagAttributeStr(tdTag,"ALIGN","right",NULL);
0474: }
0475: }
0476: if(optCNT.set){
0477: if(*(optCNT.fldNo2optNo+i) != -1){
0478: mssAddXmlTagAttributeStr(tdTag,"ALIGN","center",NULL);
0479: }
0480: }
0481: /*TDの出力*/
0482: mssWriteXmlStartTag(tdTag,NULL,fpw);
0483: mssWriteXmlContent(*(fr->pnt+i),NULL,fpw);
0484: mssWriteXmlEndTag(tdTag,NULL,fpw);
0485: mssFreeXmlTag(tdTag);
0486: }
0487:
0488: /* </TR> */
0489: mssWriteXmlEndTag(trTag,NULL,fpw);
0490: mssWriteRet(fpw);
0491:
0492: mssGV.outCnt++;
0493: }
0494: }
0495:
0496: /* </table> */
0497: mssWriteXmlEndTag(tableTag,NULL,fpw);
0498: mssWriteRet(fpw);
0499:
0500: /* </body> */
0501: mssWriteXmlEndTag(bodyTag,NULL,fpw);
0502: mssWriteRet(fpw);
0503:
0504: /* </html> */
0505: mssWriteXmlEndTag(htmlTag,NULL,fpw);
0506: mssWriteRet(fpw);
0507:
0508: /*各種開放*/
0509: mssFreeXmlTag(trTag);
0510: mssFreeXmlTag(htmlTag);
0511: mssFreeXmlTag(headTag);
0512: mssFreeXmlTag(metaTag);
0513: mssFreeXmlTag(bodyTag);
0514: mssFreeXmlTag(tableTag);
0515:
0516: /*----------------------------------------------------------------------------*/
0517: /*フッター出力&終了処理 */
0518: /*----------------------------------------------------------------------------*/
0519: mssCloseFPR(fpr); /*入力ファイルのクローズ*/
0520: mssCloseFPW(fpw); /*出力ファイルのクローズ*/
0521: mssFreeHeader(hdi); /*入力ヘッダ領域開放*/
0522: mssFreeOption(opt); /*オプション領域開放*/
0523: mssShowEndMsg(); /*完了メッセージ*/
0524: mssEnd(mssExitSuccess); /*終了*/
0525: return(0); /* to avoid warning message*/
0526: }