MUSASHI C source: mssHeader.c


グローバル関数
mssAddFieldsByFields mssAddFieldsByFldInfo mssAddFieldsByFldInfoList mssAddFieldsByStr mssAddFieldsByStrList mssAddHeadOrOptFields mssChkSorted mssClearFieldsSort mssCreateBlankXtFile mssFldGlbNam2Add mssFldNam2Add mssFldNam2Num mssFldNum2Add mssFldNum2SrtNum mssFldNum2SrtPri mssFldNum2SrtRev mssFreeFields mssFreeFldInfo mssFreeHeader mssInitCpyHeader mssInitFields mssInitFldInfo mssInitHeader mssInitSetHeader mssReadHeader mssSetFieldsSequenceNum mssSetFieldsSort mssSetFieldsSortPriority mssSetFldInfoComment mssSetFldInfoLength mssSetFldInfoName mssSetFldInfoNum mssSetFldInfoSort mssSetHeaderRecCnt mssSetOptFld mssSetOptKey mssShowFields mssShowFldInfo mssShowHeader mssUpdateFieldsSortPriority mssWriteFldInfo mssWriteFooter mssWriteHeader


ローカル関数
chkInfFldName chkOtfFldName cmpUpdHeader evalOptFldNameGlob setFldNo2optNo setNewFldNam


0001: /** 
0002:  * # CHAPTER # 
0003:  * ============================================================================ 
0004:  * XMLtableのヘッダーを扱う関数 
0005:  * 2002/08/07 mssSetOptKey: numFlg,revFlgをクリア追加 
0006:  * ============================================================================ 
0007:  */ 
0008:  
0009: #include <mssHeader.h
0010: #include <mssXml.h
0011: #include <mssXtTag.h
0012:  
0013: #include <stdio.h> 
0014: #include <stdlib.h> 
0015: #include <string.h> 
0016: #include <fnmatch.h> 
0017:  
0018: /* ############ グローバル変数 ##############*/ 
0019: /*テキストフラグ*/ 
0020: extern struct mssGlobalVariables mssGV; 
0021:  
0022: /** 
0023:  * # SECTION # 
0024:  *-----------------------------------------------------------------------------  
0025:  * mssFldInfo構造体の項目名、項目番号、アドレス、などの相互変換 
0026:  *-----------------------------------------------------------------------------  
0027:  */ 
0028:  
0029: /** 
0030:  * # DOCUMENT # 
0031:  * ここでの関数はreadHeader関数にてHeader構造体をセットした後に利用可能となる。 
0032:  */ 
0033:  
0034: /** 
0035:  * # FUNCTION # 
0036:  * mssFldInfo構造体の領域確保&初期化 
0037:  */ 
0038: struct mssFldInfo *mssInitFldInfo() 
0039: { 
0040:   struct mssFldInfo *fi; 
0041:  
0042:   fi=mssMalloc(sizeof(struct mssFldInfo),"initFldInfo"); 
0043:  
0044:   fi->num=0; 
0045:   fi->name=NULL; 
0046:   fi->priority=0; 
0047:   fi->revFlg=0; 
0048:   fi->numFlg=0; 
0049:   fi->length=0; 
0050:   fi->comment=NULL; 
0051:  
0052:   return(fi); 
0053: } 
0054:  
0055: /** 
0056:  * # FUNCTION # 
0057:  * mssFldInfo構造体の領域開放 
0058:  */ 
0059: void mssFreeFldInfostruct mssFldInfo *fi) 
0060: { 
0061:  
0062:   if(fi!=NULL){ 
0063:     mssFree(fi->name); 
0064:     mssFree(fi->comment); 
0065:   } 
0066:   mssFree(fi); 
0067: } 
0068:  
0069: /** 
0070:  * # FUNCTION # 
0071:  * mssFldInfoの出力(デバッグ用) 
0072:  */ 
0073: void mssShowFldInfo(struct mssFldInfo *fi) 
0074: { 
0075:   printf("\tnum=%d name=%s priority=%d revFlg=%d numFlg=%d comment=%s\n", 
0076:        fi->num, fi->name, fi->priority, fi->revFlg, fi->numFlg, fi->comment); 
0077: } 
0078:  
0079: /** 
0080:  * # FUNCTION # 
0081:  * numで指定された番号の項目をmssFields構造体のmssFldInfo構造体(flds->fi)から 
0082:  * 探し、見つかればそのポインタを返す。 
0083:  * 見つからなければエラーを表示して終了する。 
0084:  * ここで指定されるnumは内部での項目番号で、0から始まる。 
0085:  */ 
0086: struct mssFldInfo *mssFldNum2Add(struct mssFields *flds, int num) 
0087: { 
0088:   int i; 
0089:  
0090:   for(i=0; i<flds->cnt; i++){ 
0091:     if( num==MssFlds2num(flds,i) ){ 
0092:       return( *(flds->fi+i) ); 
0093:     } 
0094:   } 
0095:   mssShowErrMsg("internal error field number not found : [%d]",num); 
0096:   mssEnd(mssErrorNoDefault); 
0097:   return(NULL); /*コンパイル警告を避けるため*/ 
0098: } 
0099:  
0100: /** 
0101:  * # FUNCTION # 
0102:  * nameで指定された名前の項目をmssFields構造体のmssFldInfo構造体(flds->fi)から 
0103:  * 探し、見つかればそのポインタを返す。 
0104:  * 見つからなければエラーを表示して終了する。 
0105:  */ 
0106: struct mssFldInfo *mssFldNam2Add(struct mssFields *flds, char *name) 
0107: { 
0108:   int i; 
0109:  
0110:   for(i=0; i<flds->cnt; i++){ 
0111:     if( 0==strcmp(MssFlds2name(flds,i), name) ){ 
0112:       return( *(flds->fi+i) ); 
0113:     } 
0114:   } 
0115:   mssShowErrMsg("field name or number not found : [%s]",name); 
0116:   mssEnd(mssErrorNoDefault); 
0117:   return(NULL); /*コンパイル警告を避けるため*/ 
0118: } 
0119:  
0120: /** 
0121:  * # FUNCTION # 
0122:  * nameで指定されたワイルドカード(*,?など)を含む項目名をmssFields構造体の 
0123:  * mssFldInfo構造体(flds->fi)から探し、マッチしたポインタ全てを返す。 
0124:  * 一つもマッチしなければエラーを表示して終了する。 
0125:  */ 
0126: struct mssFldInfo **mssFldGlbNam2Add(struct mssFields *flds, char *name) 
0127: { 
0128:   int i; 
0129:   int cnt=0; 
0130:   struct mssFldInfo **fiList=NULL; 
0131:  
0132:   for(i=0; i<flds->cnt; i++){ 
0133:  
0134:     /*項目名のワイルドカードマッチング*/ 
0135:     if( 0==fnmatch(name,(*(flds->fi+i))->name,0) ){ 
0136:  
0137:       /*領域確保*/ 
0138:       fiList = mssRealloc(fiList,sizeof(struct mssFldInfo *)*(cnt+1), 
0139:         "FldGlbNam2Add"); 
0140:       *(fiList+cnt) = *(flds->fi+i); 
0141:       cnt++; 
0142:     } 
0143:   } 
0144:   if( cnt == 0 ) { 
0145:     mssShowErrMsg("field name not found : [%s]",name); 
0146:     mssEnd(mssErrorNoDefault); 
0147:   } 
0148:  
0149:   /*終端のNULLを追加*/ 
0150:   fiList = mssRealloc(fiList,sizeof(struct mssFldInfo *)*(cnt+1),"fldRegN2A"); 
0151:   *(fiList+cnt) = NULL; 
0152:  
0153:   return(fiList); 
0154: } 
0155:  
0156: /** 
0157:  * # FUNCTION # 
0158:  * nameで指定された名前の項目をmssFields構造体のmssFldInfo構造体(flds->fi)から 
0159:  * 探し、見つかればその項目番号を返す。 
0160:  * 見つからなければエラーを表示して終了する。 
0161:  * 注) 項目番号とは、XMLtableの<field no="1">要素のno属性の値から1を引いた数。 
0162:  */ 
0163: int mssFldNam2Num(struct mssFields *flds, char *name) 
0164: { 
0165:   int i; 
0166:   int namLen; 
0167:  
0168:   namLen=strlen(name); 
0169:   for(i=0; i<flds->cnt; i++){ 
0170:     if( 0==strcmp((*(flds->fi+i))->name, name) ){ 
0171:       return( (*(flds->fi+i))->num ); 
0172:     } 
0173:   } 
0174:   mssShowErrMsg("field name or number not found : [%s]",name); 
0175:   mssEnd(mssErrorNoDefault); 
0176:   return(0); /*とりあえず*/ 
0177: } 
0178:  
0179: /** 
0180:  * # FUNCTION # 
0181:  * numで指定された項目番号をmssFields構造体のmssFldInfo構造体(flds->fi)から 
0182:  * 探し、ソート優先順位番号の値を返す。 
0183:  * ありえない項目番号が指定されたときは、エラーを表示して終了する。 
0184:  * 注1) 項目番号とは、XMLtableの<field no="1">要素のno属性の値から1を引いた数。 
0185:  * 注2) ソート優先順位番号とは、XMLtableの<sort priority="1">要素のpriority 
0186:  *      属性の値のこと。 
0187:  */ 
0188: int mssFldNum2SrtPri(struct mssFields *flds, int num) 
0189: { 
0190:   int i; 
0191:  
0192:   if( num<0 || num>flds->cnt-1 ) { 
0193:     mssShowErrMsg("Internal Error: field number not found : [%d]",num); 
0194:     mssEnd(mssErrorNoDefault); 
0195:   } 
0196:  
0197:   for(i=0; i<flds->cnt; i++){ 
0198:     if( (*(flds->fi+i))->num == num ){ 
0199:       return( (*(flds->fi+i))->priority ); 
0200:     } 
0201:   } 
0202:   return(0); 
0203: } 
0204:  
0205: /** 
0206:  * # FUNCTION # 
0207:  * numで指定された項目番号をmssFields構造体のmssFldInfo構造体(flds->fi)から 
0208:  * 探し、その項目が逆順ソートの指定があれば1、そうでなければ0を返す。 
0209:  * ありえない項目番号が指定されたときは、エラーを表示して終了する。 
0210:  * 注1) 項目番号とは、XMLtableの<field no="1">要素のno属性の値から1を引いた数。 
0211:  * 注2) 逆順ソート指定とは、XMLtableの<reverse/>要素のこと。 
0212:  */ 
0213: int mssFldNum2SrtRev(struct mssFields *flds, int num) 
0214: { 
0215:   int i; 
0216:  
0217:   if( num<0 || num>flds->cnt-1 ) { 
0218:     mssShowErrMsg("Internal Error: field number not found : [%d]",num); 
0219:     mssEnd(mssErrorNoDefault); 
0220:   } 
0221:  
0222:   for(i=0; i<flds->cnt; i++){ 
0223:     if( (*(flds->fi+i))->num == num ){ 
0224:       return( (*(flds->fi+i))->revFlg ); 
0225:     } 
0226:   } 
0227:   return(0); 
0228: } 
0229:  
0230: /** 
0231:  * # FUNCTION # 
0232:  * numで指定された項目番号をmssFields構造体のmssFldInfo構造体(flds->fi)から 
0233:  * 探し、その項目が数値ソートの指定があれば1、そうでなければ0を返す。 
0234:  * ありえない項目番号が指定されたときは、エラーを表示して終了する。 
0235:  * 注1) 項目番号とは、XMLtableの<field no="1">要素のno属性の値から1を引いた数。 
0236:  * 注2) 数値ソート指定とは、XMLtableの<numeric/>要素のこと。 
0237:  */ 
0238: int mssFldNum2SrtNum(struct mssFields *flds, int num) 
0239: { 
0240:   int i; 
0241:  
0242:   if( num<0 || num>flds->cnt-1 ) { 
0243:     mssShowErrMsg("Internal Error: field number not found : [%d]",num); 
0244:     mssEnd(mssErrorNoDefault); 
0245:   } 
0246:  
0247:   for(i=0; i<flds->cnt; i++){ 
0248:     if( (*(flds->fi+i))->num == num ){ 
0249:       return( (*(flds->fi+i))->numFlg ); 
0250:     } 
0251:   } 
0252:   return(0); 
0253: } 
0254:  
0255: /** 
0256:  * # SECTION # 
0257:  *-----------------------------------------------------------------------------  
0258:  * mssHeader構造体を扱う関数 
0259:  *-----------------------------------------------------------------------------  
0260:  */ 
0261:  
0262: /** 
0263:  * # FUNCTION # 
0264:  * ヘッダ構造体の領域開放 
0265:  */ 
0266: void mssFreeHeader(struct mssHeader *hd) 
0267: { 
0268:   mssFree(hd->title  ); 
0269:   mssFree(hd->comment); 
0270:   mssFreeFields(hd->flds); 
0271:   mssFree(hd->xmlver); 
0272:   mssFree(hd->xmlenc); 
0273:   mssFree(hd); 
0274: } 
0275:  
0276: /** 
0277:  * # FUNCTION # 
0278:  * タイトル(title)とコメント(comment)を引数にしてHeader構造体の生成および 
0279:  * 初期化を行う。 
0280:  */ 
0281: struct mssHeader *mssInitHeader(char *title, char *comment) 
0282: { 
0283:  
0284:   struct mssHeader *hd; 
0285:  
0286:   hd=mssMalloc( sizeof(struct mssHeader),"initHeader" ); 
0287:  
0288:   hd->title  = mssStrdup(title); 
0289:   hd->comment= mssStrdup(comment); 
0290:   hd->xmlver = mssStrdup(MssXmlDefVer); 
0291:   hd->xmlenc = mssStrdup(MssXmlDefEnc); 
0292:   hd->version= MssXtDefVer
0293:   hd->flds   = mssInitFields(); 
0294:   hd->recCnt = -1; 
0295:  
0296:   return(hd); 
0297: } 
0298:  
0299: /** 
0300:  * # FUNCTION # 
0301:  * mssHeader構造体を生成し、oldで指定した既存のヘッダー情報(項目情報は除く)を 
0302:  * コピーする。 
0303:  * コピーする情報は、title,comment,xmlver,xmlencで、その他は初期化する。 
0304:  * version はMssXtDefVerで初期化される。 
0305:  * コピーの際はmssStrdupを利用するので、 
0306:  * 既存のヘッダー情報(文字列)をポインタで共有することはない。 
0307:  */ 
0308: struct mssHeader *mssInitCpyHeader(struct mssHeader *old) 
0309: { 
0310:   struct mssHeader *hd; 
0311:  
0312:   hd=mssMalloc( sizeof(struct mssHeader),"initCpyHeader" ); 
0313:  
0314:   if(NULL!=old->title)   hd->title  = mssStrdup(old->title); 
0315:   else                   hd->title  = NULL; 
0316:  
0317:   if(NULL!=old->comment) hd->comment= mssStrdup(old->comment); 
0318:   else                   hd->comment= NULL; 
0319:  
0320:   if(NULL!=old->xmlver)  hd->xmlver = mssStrdup(old->xmlver); 
0321:   else                   hd->xmlver = NULL; 
0322:    
0323:   if(NULL!=old->xmlenc)  hd->xmlenc = mssStrdup(old->xmlenc); 
0324:   else                   hd->xmlenc = NULL; 
0325:  
0326:   hd->version = MssXtDefVer
0327:   hd->flds    = mssInitFields(); 
0328:   hd->recCnt  = -1; 
0329:  
0330:   return(hd); 
0331: } 
0332:  
0333: /** 
0334:  * # FUNCTION # 
0335:  * mssHeader構造体を生成し、引数で指定した文字列でヘッダー情報を設定する。 
0336:  * 設定する情報は、title,comment,xmlver,xmlenc,versionで、その他は初期化する。 
0337:  * 設定の際はmssStrdupを利用するので、 
0338:  * 引数の文字列をポインタで共有することはない。 
0339:  */ 
0340: struct mssHeader *mssInitSetHeader( char *title, char *comment, char *xmlver, char *xmlenc, int version) 
0341: { 
0342:   struct mssHeader *hd; 
0343:  
0344:   hd=mssMalloc( sizeof(struct mssHeader),"initCpyHeader" ); 
0345:  
0346:   if(NULL!=title)   hd->title  = mssStrdup(title); 
0347:   else              hd->title  = NULL; 
0348:  
0349:   if(NULL!=comment) hd->comment= mssStrdup(comment); 
0350:   else              hd->comment= NULL; 
0351:  
0352:   if(NULL!=xmlver)  hd->xmlver = mssStrdup(xmlver); 
0353:   else              hd->xmlver = NULL; 
0354:    
0355:   if(NULL!=xmlenc)  hd->xmlenc = mssStrdup(xmlenc); 
0356:   else              hd->xmlenc = NULL; 
0357:  
0358:   hd->version= version; 
0359:  
0360:   hd->flds    = mssInitFields(); 
0361:   hd->recCnt = -1; 
0362:  
0363:   return(hd); 
0364: } 
0365:  
0366: /** 
0367:  * # FUNCTION # 
0368:  * mssHeader構造体のレコード数(recCnt)をセットする。 
0369:  */ 
0370: void mssSetHeaderRecCnt(struct mssHeader *hd, int recCnt) 
0371: { 
0372:   hd->recCnt=recCnt; 
0373: } 
0374:  
0375: /** 
0376:  * # SECTION # 
0377:  *-----------------------------------------------------------------------------  
0378:  * mssFields,mssFldInfo構造体を扱う関数 
0379:  *-----------------------------------------------------------------------------  
0380:  */ 
0381:  
0382: /** 
0383:  * # FUNCTION # 
0384:  * mssFields構造体の初期化 
0385:  */ 
0386: struct mssFields *mssInitFields() 
0387: { 
0388:   struct mssFields *flds; 
0389:   flds=mssMalloc(sizeof(struct mssFields),"initFields"); 
0390:   flds->fi=NULL; 
0391:   flds->cnt=0; 
0392:   return(flds); 
0393: } 
0394:  
0395: /** 
0396:  * # FUNCTION # 
0397:  * mssFields構造体の領域開放 
0398:  */ 
0399: void mssFreeFields(struct mssFields *flds) 
0400: { 
0401:   int i; 
0402:   if(flds!=NULL){ 
0403:     for(i=0; i<flds->cnt; i++){ 
0404:       mssFreeFldInfo(*(flds->fi+i)); 
0405:     } 
0406:     mssFree(flds->fi); 
0407:   } 
0408:   mssFree(flds); 
0409: } 
0410:  
0411: /** 
0412:  * # FUNCTION # 
0413:  * ヘッダー項目情報の出力(デバッグ用) 
0414:  */ 
0415: void mssShowFields(struct mssFields *flds) 
0416: { 
0417:   int i; 
0418:   for(i=0; i<flds->cnt; i++){ 
0419:     printf("fld[%d]:",i); 
0420:     mssShowFldInfo(*(flds->fi+i)); 
0421:   } 
0422: } 
0423:  
0424:  
0425: /** 
0426:  * # FUNCTION # 
0427:  * mssUpdateSortPriority関数で利用するソートの比較関数 
0428:  */ 
0429: static int cmpUpdHeader(const void **a, const void **b) 
0430: { 
0431:   if((int)*a > (int)*b) return(1); 
0432:   else                  return(-1); 
0433: } 
0434:  
0435: /** 
0436:  * # FUNCTION # 
0437:  * mssFields構造体のソート情報を検査し、妥当でないソート情報を削除する。 
0438:  * この関数が使われる状況 
0439:  *   入力データの一部のヘッダー項目情報を新しいヘッダー項目情報として作成した時 
0440:  *   元のソートpriorityが正しくなくなる可能性がある。例えば、入力データに 
0441:  *   a,b,c,dの4つの項目があったとして、ソートのpriorityはa,b,cの順であったと 
0442:  *   する(a=1,b=2,c=3)。すなわち、項目a,b,cでソートされているとする。 
0443:  *   この時、a,c,dの3項目を新しい項目として抜きだしたとき、ソートのpriorityは 
0444:  *   正しくなくなる。項目aではソートされているが、cではソートされていない。 
0445:  *   そこで、この関数は、項目aのpriorityは1のままで、項目cのソートpriority 
0446:  *   を消去する。 
0447:  */ 
0448: void mssUpdateFieldsSortPriority(struct mssFields *flds) 
0449: { 
0450:   int list[MssFieldMaxCnt]; 
0451:   int listCnt; 
0452:   int i; 
0453:   int until; 
0454:  
0455:   if(mssGV.txtFlg) return; 
0456:  
0457:   /*ソートされている項目のpriority番号をlist配列にセット*/ 
0458:   listCnt=0; 
0459:   for(i=0; i<flds->cnt; i++){ 
0460:     if((*(flds->fi+i))->priority != 0){ 
0461:       list[listCnt++]=(*(flds->fi+i))->priority; 
0462:     } 
0463:   } 
0464:  
0465:   /*list配列を並べ変えて、priority番号が断絶or重複している箇所をuntilに入れる*/ 
0466:   /*list[]=1,2,3,5 の時、3まではOKだがそれ以降は断絶。そこでuntil=3 */ 
0467:   /*list[]=1,2,2,3 の時、最初の2まではOKだがそれ以降は重複。そこでuntil=2 */ 
0468:   until=0; 
0469:   if(listCnt!=0){ 
0470:     qsort(list,listCnt,sizeof(int), 
0471:                (int (*)(const void *,const void *))cmpUpdHeader); 
0472:  
0473:     for(i=0; i<listCnt; i++){ 
0474:       if((i+1)!=list[i]) break; 
0475:     } 
0476:     until=i; 
0477:   } 
0478:  
0479:   /*断絶(until)より上のpriorityを消す*/ 
0480:   for(i=0; i<flds->cnt; i++){ 
0481:     if((*(flds->fi+i))->priority > until){ 
0482:       (*(flds->fi+i))->priority = 0; 
0483:       (*(flds->fi+i))->revFlg   = 0; 
0484:       (*(flds->fi+i))->numFlg   = 0; 
0485:     } 
0486:   } 
0487: } 
0488:  
0489: /** 
0490:  * # FUNCTION # 
0491:  * mssFldInfo構造体のソート情報(priority,revFlg,numFlg)をセットする。 
0492:  */ 
0493: void mssSetFldInfoSort(struct mssFldInfo *fi, int prioriy, int revFlg,int numFlg) 
0494: { 
0495:   fi->priority = prioriy; 
0496:   fi->revFlg   = revFlg; 
0497:   fi->numFlg   = numFlg; 
0498: } 
0499:  
0500: /** 
0501:  * # FUNCTION # 
0502:  * fldsのソート情報をクリアする。 
0503:  */ 
0504: void mssClearFieldsSort(struct mssFields *flds) 
0505: { 
0506:   int i; 
0507:  
0508:   if(mssGV.txtFlg) return; 
0509:  
0510:   for(i=0; i<flds->cnt; i++){ 
0511:     mssSetFldInfoSort(*(flds->fi+i),0,0,0); 
0512:   } 
0513: } 
0514:  
0515: /** 
0516:  * # FUNCTION # 
0517:  * fldsのソート情報を一旦クリアし、sfの全ソート情報をコピーする。 
0518:  */ 
0519: void mssSetFieldsSort(struct mssFields *flds, struct mssFields *sortFlds) 
0520: { 
0521:   int i; 
0522:   int no; 
0523:  
0524:   /*一旦、flds上の全てのソート情報をクリアする*/ 
0525:   mssClearFieldsSort(flds); 
0526:  
0527:   for(i=0; i<sortFlds->cnt; i++){ 
0528:     no = MssFlds2num(sortFlds,i); 
0529:     MssFlds2priority(flds,no)= i+1; 
0530:     MssFlds2revFlg(flds,no)  = MssFlds2revFlg(sortFlds,i); 
0531:     MssFlds2numFlg(flds,no)  = MssFlds2numFlg(sortFlds,i); 
0532:   } 
0533: } 
0534:  
0535: /** 
0536:  * # FUNCTION # 
0537:  * fldsに含まれる全項目について、登録された順番にソート優先順位番号をふる。 
0538:  */ 
0539: void mssSetFieldsSortPriority(struct mssFields *flds) 
0540: { 
0541:   int i; 
0542:  
0543:   for(i=0; i<flds->cnt; i++){ 
0544:     MssFlds2priority(flds,i)= i+1; 
0545:   } 
0546: } 
0547:  
0548: /** 
0549:  * # FUNCTION # 
0550:  * mssFldInfo構造体の項目長情報(lenght)をセットする。 
0551:  * この情報は、固定長項目にする時にセットする。 
0552:  */ 
0553: void mssSetFldInfoLength(struct mssFldInfo *fi, int length) 
0554: { 
0555:   fi->length = length; 
0556: } 
0557:  
0558: /** 
0559:  * # FUNCTION # 
0560:  * mssFldInfo構造体の項目番号を、numによってセットする。 
0561:  * データ上では1から始まる番号だが、内部的には0から始まる番号。 
0562:  * そこでここでは、numには内部の番号として与えること。 
0563:  */ 
0564: void mssSetFldInfoNum(struct mssFldInfo *fi, int num) 
0565: { 
0566:   fi->num      = num; 
0567: } 
0568:  
0569: /** 
0570:  * # FUNCTION # 
0571:  * mssFldInfo構造体の項目名を、name によってセットする。 
0572:  */ 
0573: void mssSetFldInfoName(struct mssFldInfo *fi, char *name) 
0574: { 
0575:   fi->name     = mssStrdup(name); 
0576: } 
0577:  
0578: /** 
0579:  * # FUNCTION # 
0580:  * mssFldInfo構造体のコメントを、commentによってセットする。 
0581:  */ 
0582: void mssSetFldInfoComment(struct mssFldInfo *fi, char *comment) 
0583: { 
0584:   fi->comment = mssStrdup(comment); 
0585: } 
0586:  
0587: /** 
0588:  * # FUNCTION # 
0589:  * mssFields構造体の全FldInfo構造体のnum(項目番号)に、0から始まる連番にセット 
0590:  * する。 
0591:  */ 
0592: void mssSetFieldsSequenceNum(struct mssFields *flds) 
0593: { 
0594:   int i; 
0595:  
0596:   for(i=0; i<flds->cnt; i++){ 
0597:     MssFlds2num(flds,i)=i; 
0598:   } 
0599: } 
0600:  
0601: /** 
0602:  * # FUNCTION # 
0603:  * mssFields構造体に、文字列として指定された項目名を追加する。 
0604:  * ソート情報などはクリアされる。 
0605:  */ 
0606: void mssAddFieldsByStr(struct mssFields *flds, char *str) 
0607: { 
0608:   flds->fi=mssRealloc(flds->fi,sizeof(struct mssFldInfo *)*(flds->cnt+1), 
0609:                         "AddFieldsByStr"); 
0610:   *(flds->fi+flds->cnt) = mssInitFldInfo(); 
0611:  
0612:   mssSetFldInfoNum(*(flds->fi+flds->cnt),flds->cnt); 
0613:   mssSetFldInfoName(*(flds->fi+flds->cnt),str); 
0614:   mssSetFldInfoSort(*(flds->fi+flds->cnt),0,0,0); 
0615:   mssSetFldInfoLength(*(flds->fi+flds->cnt),0); 
0616:   mssSetFldInfoComment(*(flds->fi+flds->cnt),NULL); 
0617:  
0618:   flds->cnt++; 
0619: } 
0620:  
0621: /** 
0622:  * # FUNCTION # 
0623:  * mssFields構造体に、文字列リストとして指定された項目名を追加する。 
0624:  * ソート情報などはクリアされる。 
0625:  */ 
0626: void mssAddFieldsByStrList(struct mssFields *flds, char **str, int cnt) 
0627: { 
0628:   int i; 
0629:  
0630:   for(i=0; i<cnt; i++){ 
0631:     mssAddFieldsByStr(flds,*(str+i)); 
0632:   } 
0633: } 
0634:  
0635: /** 
0636:  * # FUNCTION # 
0637:  * mssFields構造体に、指定されたmssFldInfoを追加する。 
0638:  */ 
0639: void mssAddFieldsByFldInfo(struct mssFields *flds, struct mssFldInfo *fi) 
0640: { 
0641:   struct mssFldInfo *ofi; 
0642:  
0643:   flds->fi=mssRealloc(flds->fi,sizeof(struct mssFldInfo *)*(flds->cnt+1), 
0644:                       "AddFldInfo"); 
0645:   *(flds->fi+flds->cnt) = mssInitFldInfo(); 
0646:   ofi=*(flds->fi+flds->cnt); 
0647:  
0648:   mssSetFldInfoNum(ofi,fi->num); 
0649:   mssSetFldInfoName(ofi,fi->name); 
0650:   mssSetFldInfoSort(ofi,fi->priority,fi->revFlg,fi->numFlg); 
0651:   mssSetFldInfoLength(ofi,fi->length); 
0652:   mssSetFldInfoComment(ofi,fi->comment); 
0653:  
0654:   flds->cnt++; 
0655: } 
0656:  
0657: /** 
0658:  * # FUNCTION # 
0659:  * mssFields構造体fldsに、指定された複数のmssFldInfo構造体fiを追加する。 
0660:  * fiの最後の要素はNULLでなければならない。 
0661:  * 例えばmssFldGlbNam2Addで取得した複数のmssFldInfoリストは最後の要素はNULL 
0662:  * で終っているので、そのまま利用できる。 
0663:  */ 
0664: void mssAddFieldsByFldInfoList(struct mssFields *flds, struct mssFldInfo **fi) 
0665: { 
0666:   int i; 
0667:  
0668:   for(i=0;;i++){ 
0669:     if( *(fi+i) == NULL ) break; 
0670:     mssAddFieldsByFldInfo(flds, *(fi+i)); 
0671:   } 
0672: } 
0673:  
0674: /** 
0675:  * # FUNCTION # 
0676:  * mssFields構造体に、指定されたmssFields構造体の全てのmssFldInfoを追加する。 
0677:  * 項目番号、項目名、ソート情報など全てが、そのまま追加コピーされる。 
0678:  */ 
0679: void mssAddFieldsByFields(struct mssFields *flds, struct mssFields *addFlds) 
0680: { 
0681:   int i; 
0682:  
0683:   for(i=0; i<addFlds->cnt; i++){ 
0684:     mssAddFieldsByFldInfo(flds, *(addFlds->fi+i)); 
0685:   } 
0686: } 
0687:  
0688: /** 
0689:  * # FUNCTION # 
0690:  * mssFields構造体に、オプション上で指定されたmssFields構造体とヘッダー上の 
0691:  * mssFields構造体とを追加する。この時、オプションで指定されている項目は、 
0692:  * 新項目名を追加し、そうでない項目はヘッダーの項目を追加する。 
0693:  */ 
0694: void mssAddHeadOrOptFields(struct mssFields *flds, struct mssHeader *hd, MssOptFLD *optFld) 
0695: { 
0696:   int i; 
0697:   int num; 
0698:  
0699:   for(i=0; i<hd->flds->cnt; i++){ 
0700:     mssAddFieldsByFldInfo(flds, *(hd->flds->fi+i)); 
0701:  
0702:     /*オプションで指定されなかった項目*/ 
0703:     num=*(optFld->fldNo2optNo+i); 
0704:     if(*(optFld->fldNo2optNo+i)!=-1){ 
0705:       mssSetFldInfoNum(*(flds->fi+flds->cnt-1), i); 
0706:       mssSetFldInfoName(*(flds->fi+flds->cnt-1), *(optFld->newNam+num)); 
0707:       mssSetFldInfoSort(*(flds->fi+flds->cnt-1),0,0,0); 
0708:       mssSetFldInfoLength(*(flds->fi+flds->cnt-1),0); 
0709:       mssSetFldInfoComment(*(flds->fi+flds->cnt-1), NULL); 
0710:     } 
0711:   } 
0712: } 
0713:  
0714: /** 
0715:  * # SECTION # 
0716:  *-----------------------------------------------------------------------------  
0717:  * mssHeader構造体の入出力関数 
0718:  *-----------------------------------------------------------------------------  
0719:  */ 
0720:  
0721: /** 
0722:  * # FUNCTION # 
0723:  * 入力ファイルの項目名チェック 
0724:  */ 
0725: static void chkInfFldName(struct mssHeader *hd, struct mssFPR *fp ) 
0726: { 
0727:   char *fName; 
0728:   int i,j; 
0729:  
0730:   /*ファイル名セット*/ 
0731:   if(fp->fName==NULL) fName="stdin"; 
0732:   else                fName=fp->fName; 
0733:  
0734:   /*項目名NULLチェック*/ 
0735:   for(i=0; i<hd->flds->cnt; i++){ 
0736:     if(NULL==(*(hd->flds->fi+i))->name){ 
0737:       mssShowErrMsg("name of %dth field is null in %s",i+1,fName); 
0738:       mssEnd(mssErrorNoDefault); 
0739:     } 
0740:   } 
0741:  
0742:   /*項目名重複チェック*/ 
0743:   for(i=0; i<hd->flds->cnt-1; i++){ 
0744:     for(j=i+1; j<hd->flds->cnt; j++){ 
0745:       if(0==strcmp((*(hd->flds->fi+i))->name,(*(hd->flds->fi+j))->name)){ 
0746:         mssShowErrMsg("same field names in %s: %s",fName,(*(hd->flds->fi+j))->name); 
0747:         mssEnd(mssErrorNoDefault); 
0748:       } 
0749:     } 
0750:   } 
0751: } 
0752:  
0753: /** 
0754:  * # FUNCTION # 
0755:  * 出力ファイルの項目名チェック 
0756:  */ 
0757: static void chkOtfFldName(struct mssHeader *hd, struct mssFPW *fp ) 
0758: { 
0759:   char *fName; 
0760:   int i,j; 
0761:  
0762:   /*ファイル名セット*/ 
0763:   if(fp->fName==NULL)           fName="stdout"; 
0764:   else if(fp->fName==(char *)1) fName="stderr"; 
0765:   else                          fName=fp->fName; 
0766:  
0767:   /*項目名NULLチェック*/ 
0768:   for(i=0; i<hd->flds->cnt; i++){ 
0769:     if(NULL==(*(hd->flds->fi+i))->name){ 
0770:       mssShowErrMsg("name of %dth field is null in %s",i+1,fName); 
0771:       mssEnd(mssErrorNoDefault); 
0772:     } 
0773:   } 
0774:  
0775:   /*項目名重複チェック*/ 
0776:   for(i=0; i<hd->flds->cnt-1; i++){ 
0777:     for(j=i+1; j<hd->flds->cnt; j++){ 
0778:       if(0==strcmp((*(hd->flds->fi+i))->name,(*(hd->flds->fi+j))->name)){ 
0779:         mssShowErrMsg("same field names in %s: %s",fName,(*(hd->flds->fi+j))->name); 
0780:         mssEnd(mssErrorNoDefault); 
0781:       } 
0782:     } 
0783:   } 
0784: } 
0785:  
0786:  
0787: /** 
0788:  * # FUNCTION # 
0789:  * mssFldInfo構造体情報をヘッダー情報として書き出す。 
0790:  */ 
0791: void mssWriteFldInfostruct mssFldInfo *fi, int version, struct mssFPW *fp) 
0792: { 
0793:   struct mssXmlTag *fieldTag; 
0794:   struct mssXmlTag *sortTag; 
0795:   struct mssXmlTag *revTag; 
0796:   struct mssXmlTag *numTag; 
0797:   char *str; 
0798:  
0799:   switch(version){ 
0800:   /*XMLtable version 1.0*/ 
0801:   case 10: 
0802:     /* <field no="1"> */ 
0803:     fieldTag=mssInitXmlTag("field",NULL); 
0804:     mssAddXmlTagAttributeInt(fieldTag,"no",fi->num+1,NULL); 
0805:     str=mssXmlTag2startTag(fieldTag, NULL); 
0806:     mssWriteStr(str,fp); mssFree(str); 
0807:  
0808:     /* <name>fieldName</name> */ 
0809:     mssWriteXmlTagStr(0,"name",fi->name,0,NULL,fp); 
0810:  
0811:     /* <sort priority="1"><numeric/><reverse/></sort>*/ 
0812:     if(0 != fi->priority){ 
0813:       sortTag=mssInitXmlTag("sort",NULL); 
0814:       mssAddXmlTagAttributeInt(sortTag,"priority",fi->priority,NULL); 
0815:       str=mssXmlTag2startTag(sortTag, NULL); 
0816:       mssWriteStr(str,fp); mssFree(str); 
0817:       if(fi->revFlg){ 
0818:         revTag=mssInitXmlTag("reverse",NULL); 
0819:         str=mssXmlTag2emptyTag(revTag, NULL); 
0820:         mssWriteStr(str,fp); mssFree(str); 
0821:         mssFreeXmlTag(revTag); 
0822:       } 
0823:       if(fi->numFlg){ 
0824:         numTag=mssInitXmlTag("numeric",NULL); 
0825:         str=mssXmlTag2emptyTag(numTag, NULL); 
0826:         mssWriteStr(str,fp); mssFree(str); 
0827:         mssFreeXmlTag(numTag); 
0828:       } 
0829:       str=mssXmlTag2endTag(sortTag, NULL); 
0830:       mssWriteStr(str,fp); mssFree(str); 
0831:       mssFreeXmlTag(sortTag); 
0832:     } 
0833:  
0834:     /*<length>10</length>*/ 
0835:     if(fi->length!=0){ 
0836:       mssWriteXmlTagInt(0,"length",fi->length,0,NULL,fp); 
0837:     } 
0838:  
0839:     /*</field>*/ 
0840:     str=mssXmlTag2endTag(fieldTag, NULL); 
0841:     mssWriteStr(str,fp); mssFree(str); 
0842:     mssFreeXmlTag(fieldTag); 
0843:     mssWriteRet(fp); 
0844:     break; 
0845:  
0846:     /*XMLtable version 1.1*/ 
0847:     /*<field num="1" name="項目名" sort="1" numeric="1" reverse="1" length="10">項目コメント<field> */ 
0848:   case 11: 
0849:     fieldTag=mssInitXmlTag("field",NULL); 
0850:     mssAddXmlTagAttributeInt(fieldTag,"no"  ,fi->num+1,NULL); 
0851:     mssAddXmlTagAttributeStr(fieldTag,"name",fi->name ,NULL); 
0852:     if(0 != fi->priority){ 
0853:       mssAddXmlTagAttributeInt(fieldTag,"sort",fi->priority ,NULL); 
0854:       if(fi->numFlg){ 
0855:         mssAddXmlTagAttributeInt(fieldTag,"numeric",1 ,NULL); 
0856:       } 
0857:       if(fi->revFlg){ 
0858:         mssAddXmlTagAttributeInt(fieldTag,"reverse",1 ,NULL); 
0859:       } 
0860:     } 
0861:     if(fi->length!=0){ 
0862:       mssAddXmlTagAttributeInt(fieldTag,"length",fi->length ,NULL); 
0863:     } 
0864:     mssWriteXmlStartTag(fieldTag, NULL, fp); 
0865:     if(fi->comment!=NULL){ 
0866:       mssWriteStr(fi->comment,fp); 
0867:     } 
0868:     mssWriteXmlEndTag(fieldTag, NULL, fp); 
0869:     mssWriteRet(fp); 
0870:     break; 
0871:  
0872:   default: 
0873:     mssShowErrMsg("Internal Error: invalid XMLtable version"); 
0874:     mssEnd(mssErrorNoDefault); 
0875:   } 
0876: } 
0877:  
0878: /** 
0879:  * # FUNCTION # 
0880:  * ヘッダーの書き出し。 
0881:  */ 
0882: void mssWriteHeaderstruct mssHeader *hd, struct mssFPW *fp) 
0883: { 
0884:   struct mssXmlTag *xtTag; 
0885:   struct mssXmlTag *hdTag; 
0886:   int i; 
0887:   char *version=NULL; 
0888:   char verStr[2][4]={"1.0","1.1"}; 
0889:  
0890:   if(mssGV.txtFlg)return; 
0891:  
0892:   switch(hd->version){ 
0893:   case 10: 
0894:     version=verStr[0]; 
0895:     break; 
0896:   case 11: 
0897:     version=verStr[1]; 
0898:     break; 
0899:   default: 
0900:     mssShowErrMsg("Internal Error: invalid XMLtable version"); 
0901:     mssEnd(mssErrorNoDefault); 
0902:   } 
0903:  
0904:   chkOtfFldName(hd,fp); /*出力項目名のチェック*/ 
0905:  
0906:   mssWriteXmlDeclaration( hd->xmlver, hd->xmlenc ,fp); 
0907:  
0908:   /*xmlTableヘッダーの書き出し<xmltbl version="1.1">*/ 
0909:   xtTag=mssInitXmlTag("xmltbl",NULL); 
0910:   mssAddXmlTagAttributeStr(xtTag,"version",version,NULL); 
0911:   mssWriteXmlStartTag(xtTag,NULL,fp); 
0912:   mssFreeXmlTag(xtTag); 
0913:   mssWriteRet(fp); 
0914:  
0915:   /*<header>*/ 
0916:   hdTag=mssInitXmlTag("header",NULL); 
0917:   mssWriteXmlStartTag(hdTag,NULL,fp); 
0918:   mssWriteRet(fp); 
0919:  
0920:   /*<title>*/ 
0921:   mssWriteXmlTagStr(0,"title",hd->title,1,NULL,fp); 
0922:  
0923:   /*<comment>*/ 
0924:   mssWriteXmlTagStr(0,"comment",hd->comment,1,NULL,fp); 
0925:  
0926:   /*<field>*/ 
0927:   for(i=0; i<hd->flds->cnt; i++){    /*ヘッダーの項目タグを出力*/ 
0928:     mssWriteFldInfo(*(hd->flds->fi+i), hd->version, fp); 
0929:   } 
0930:  
0931:   /*<recCnt>*/ 
0932:   if(-1 != hd->recCnt){ 
0933:     mssWriteXmlTagInt(0,"recCnt",hd->recCnt,1,NULL,fp); 
0934:   } 
0935:  
0936:   /*</header>*/ 
0937:   mssWriteXmlEndTag(hdTag,NULL,fp); 
0938:   mssWriteRet(fp); 
0939:   mssFreeXmlTag(hdTag); 
0940:  
0941:   /*<body><![CDATA[*/ 
0942:   mssWriteStr(MssBeginBodyString, fp) ; mssWriteRet(fp); 
0943:   mssGV.writeHeaderFlg=1; 
0944: } 
0945:  
0946: /** 
0947:  * # FUNCTION # 
0948:  * フッターの書き出し。 
0949:  */ 
0950: void mssWriteFooter(struct mssFPW *fp) 
0951: { 
0952:  
0953:   if(fp==NULL) return; 
0954:   if(mssGV.txtFlg) return; 
0955:   mssWriteStr(MssEndBodyString, fp) ; mssWriteRet(fp); 
0956:   mssWriteStr("</xmltbl>", fp)  ; mssWriteRet(fp); 
0957:  
0958:   mssGV.writeFooterFlg=1; 
0959: } 
0960:  
0961: /** 
0962:  * # FUNCTION # 
0963:  * 空データのxmlTableを作成する。 
0964:  * 与えられたfldCnt個の項目名fldNameから、xmlTableヘッダーの項目を作成する。 
0965:  * この関数は、xtmkdata,xtcalenderコマンドのように、新しくデータを作成する際に 
0966:  * 利用される。既に必要な項目名を伴った空データがあれば、入力データを伴った 
0967:  * 処理フローがそのまま利用可能となる。 
0968:  */ 
0969: void mssCreateBlankXtFile(char **fldName, int fldCnt, char *fname) 
0970: { 
0971:   struct mssHeader *hd; 
0972:   struct mssFPW *fpw; 
0973:   hd=mssMalloc( sizeof(struct mssHeader),"mkBlankXtFile" ); 
0974:  
0975:   hd->title  = NULL; 
0976:   hd->comment= NULL; 
0977:   hd->xmlver = mssStrdup(MssXmlDefVer); 
0978:   hd->xmlenc = mssStrdup(MssXmlDefEnc); 
0979:   hd->version= MssXtDefVer
0980:   hd->flds   = mssInitFields(); 
0981:   hd->recCnt = -1; 
0982:  
0983:   mssAddFieldsByStrList(hd->flds,fldName,fldCnt); 
0984:  
0985:   /*標準出力オープン+ヘッダー、フッターの出力*/ 
0986:   fpw=mssOpenFPW(fname, 0, 0); 
0987:   mssWriteHeader(hd, fpw); 
0988:   mssWriteFooter(fpw); 
0989:   mssCloseFPW(fpw); 
0990:   mssFreeHeader(hd); 
0991: } 
0992:  
0993:  
0994:  
0995: static char numChr[MssFieldMaxCnt][4]; /*項目番号としての項目名用*/ 
0996:  
0997: /** 
0998:  * # FUNCTION # 
0999:  * ヘッダー情報の読み込み。 
1000:  */ 
1001: struct mssHeader *mssReadHeaderstruct mssFPR *fp) 
1002: { 
1003:  
1004:   struct mssHeader *hd; 
1005:   struct mssStrings *head; 
1006:   struct mssStrings *title; 
1007:   struct mssStrings *comment; 
1008:   struct mssStrings *recCnt; 
1009:   struct mssStrings *field; 
1010:   struct mssStrings *sort; 
1011:  
1012:   char *tmpStr; 
1013:   char *pos; 
1014:   char *str; 
1015:   int i; 
1016:   int datFldCnt;  /*データ上の項目数*/ 
1017:   int fldNum; 
1018:   int priority; 
1019:   int revFlg; 
1020:   int numFlg; 
1021:   int length; 
1022:   hd=mssMalloc( sizeof(struct mssHeader),"readHeader" ); 
1023:   hd->flds=mssInitFields(); 
1024:  
1025:   /*---------------------------- plainTextの場合*/ 
1026:   if(mssGV.txtFlg){ 
1027:     datFldCnt = mssGetFldCntOnData(fp); /*データ上の項目数をカウント*/ 
1028:     hd->title   = NULL;        /*タイトル*/ 
1029:     hd->comment = NULL;        /*コメント*/ 
1030:     hd->recCnt  = -1;          /*レコード数*/ 
1031:     hd->xmlver  = NULL;        /*xml version*/ 
1032:     hd->xmlenc  = NULL;        /*xml encoding*/ 
1033:     /*項目のメモリの確保*/ 
1034:     hd->flds->cnt = 0;   /*項目数*/ 
1035:     for(i=0; i<datFldCnt; i++){ 
1036:       sprintf(numChr[i+1],"%d",i+1); 
1037:       mssAddFieldsByStr(hd->flds, mssStrdup(numChr[i+1])); 
1038:     } 
1039:   /*---------------------------- xmlTblの場合*/ 
1040:   }else{ 
1041:  
1042:     mssReadSetTop(hd, fp); /*xmlのバージョンとencもセットする*/ 
1043:  
1044:     /*全ヘッダー(<header>....</header>)をファイルからメモリにセット*/ 
1045:     head=mssReadTag("header", fp); 
1046:     if(head==NULL){ 
1047:       mssShowErrMsg("cannot find header tag"); 
1048:       mssEnd(mssErrorNoDefault); 
1049:     } 
1050:  
1051:     /*タイトルの取得*/ 
1052:     title=mssGetTag("title", head->str, &pos); 
1053:     if(title!=NULL){ 
1054:       hd->title=mssGetTagCont(title->str,"title",1); /*titleタグ内の内容を取得*/ 
1055:       mssFreeStrings(title); 
1056:     }else{ 
1057:       hd->title=NULL; 
1058:     } 
1059:  
1060:     /*コメントの取得*/ 
1061:     comment=mssGetTag("comment", head->str, &pos); 
1062:     if(comment!=NULL){ 
1063:       hd->comment=mssGetTagCont(comment->str,"comment",0); 
1064:       mssFreeStrings(comment); 
1065:     }else{ 
1066:       hd->comment=NULL; 
1067:     } 
1068:  
1069:     /*レコード数の取得*/ 
1070:     hd->recCnt=-1; 
1071:     recCnt=mssGetTag("recCnt", head->str, &pos); 
1072:     if(recCnt!=NULL){ 
1073:       str=mssGetTagCont(recCnt->str,"recCnt",1); 
1074:       if( NULL!= str ) hd->recCnt=atoi(str); 
1075:       mssFree(str); 
1076:       mssFreeStrings(recCnt); 
1077:     }else{ 
1078:       hd->recCnt=-1; 
1079:     } 
1080:  
1081:     /*項目情報の取得*/ 
1082:     tmpStr=head->str; 
1083:     while(1) { 
1084:       /*fieldタグのセット*/ 
1085:       field=mssGetTag("field", tmpStr, &pos); 
1086:       if( NULL == field ){ 
1087:          break; 
1088:       } 
1089:  
1090:       /*検索対象を一文字ずらすことで、次のfieldの検索に備える*/ 
1091:       tmpStr=pos+1; 
1092:  
1093:       switch(hd->version){ 
1094:       case 10: 
1095:         /*項目名*/ 
1096:         str = mssGetTagCont(field->str, "name",1); 
1097:         if(str!=NULL){ 
1098:           mssAddFieldsByStr(hd->flds, str); 
1099:           mssFree(str); 
1100:         }else{ 
1101:           mssShowErrMsg("Internal Error: invalid filed number"); 
1102:           mssEnd(mssErrorNoDefault); 
1103:         } 
1104:  
1105:         /*項目番号*/ 
1106:         str = mssGetTagAtt(field->str, "field", "no"); 
1107:         if(str!=NULL){ 
1108:           fldNum=atoi(str); 
1109:           if(fldNum>0 && fldNum<MssFieldMaxCnt){ 
1110:             mssSetFldInfoNum(*(hd->flds->fi+hd->flds->cnt-1), fldNum-1); 
1111:           }else{ 
1112:             mssShowErrMsg("Internal Error: invalid filed number"); 
1113:             mssEnd(mssErrorNoDefault); 
1114:           } 
1115:           mssFree(str); 
1116:         }else{ 
1117:           mssShowErrMsg("Internal Error: invalid filed number"); 
1118:           mssEnd(mssErrorNoDefault); 
1119:         } 
1120:  
1121:         /*sortタグのセット (このタグがなければ0がセットされる)*/ 
1122:         priority = 0; 
1123:         revFlg   = 0; 
1124:         numFlg   = 0; 
1125:         sort=mssGetTag("sort", field->str, &pos); 
1126:         if( NULL != sort ){ 
1127:           str = mssGetTagAtt(sort->str, "sort", "priority"); 
1128:           priority = atoi(str); 
1129:           revFlg   = mssGetNullTag(sort->str, "reverse"); 
1130:           numFlg   = mssGetNullTag(sort->str, "numeric"); 
1131:           mssFree(str); 
1132:           mssFreeStrings(sort); 
1133:         } 
1134:         mssSetFldInfoSort(*(hd->flds->fi+hd->flds->cnt-1), 
1135:                                                       priority,revFlg,numFlg); 
1136:  
1137:         /*lenghtタグのセット*/ 
1138:         str = mssGetTagCont(field->str, "length",1); 
1139:         if(str!=NULL) length = atoi(str); 
1140:         else          length = 0; 
1141:         mssFree(str); 
1142:         mssSetFldInfoLength(*(hd->flds->fi+hd->flds->cnt-1),length); 
1143:         break; 
1144:  
1145:       case 11: 
1146:         /*項目名*/ 
1147:         str = mssGetTagAtt(field->str, "field", "name"); 
1148:         if(str!=NULL){ 
1149:           mssAddFieldsByStr(hd->flds, str); 
1150:           mssFree(str); 
1151:         }else{ 
1152:           mssShowErrMsg("Internal Error: invalid filed number"); 
1153:           mssEnd(mssErrorNoDefault); 
1154:         } 
1155:  
1156:         /*項目番号*/ 
1157:         str = mssGetTagAtt(field->str, "field", "no"); 
1158:         if(str!=NULL){ 
1159:           fldNum=atoi(str); 
1160:           if(fldNum>0 && fldNum<MssFieldMaxCnt){ 
1161:             mssSetFldInfoNum(*(hd->flds->fi+hd->flds->cnt-1), fldNum-1); 
1162:           }else{ 
1163:             mssShowErrMsg("Internal Error: invalid filed number"); 
1164:             mssEnd(mssErrorNoDefault); 
1165:           } 
1166:           mssFree(str); 
1167:         }else{ 
1168:           mssShowErrMsg("Internal Error: invalid filed number"); 
1169:           mssEnd(mssErrorNoDefault); 
1170:         } 
1171:  
1172:         /*ソート情報*/ 
1173:         priority = 0; 
1174:         revFlg   = 0; 
1175:         numFlg   = 0; 
1176:         str = mssGetTagAtt(field->str, "field", "sort"); 
1177:         if(str!=NULL){ 
1178:           priority=atoi(str); 
1179:           mssFree(str); 
1180:           str = mssGetTagAtt(field->str, "field", "numeric"); 
1181:           if(str!=NULL){ 
1182:             numFlg=atoi(str); 
1183:             if(numFlg!=0 && numFlg!=1){ 
1184:               mssShowErrMsg("Internal Error: invalid numeric value"); 
1185:               mssEnd(mssErrorNoDefault); 
1186:             } 
1187:             mssFree(str); 
1188:           } 
1189:  
1190:           str = mssGetTagAtt(field->str, "field", "reverse"); 
1191:           if(str!=NULL){ 
1192:             revFlg=atoi(str); 
1193:             if(revFlg!=0 && revFlg!=1){ 
1194:               mssShowErrMsg("Internal Error: invalid reverse value"); 
1195:               mssEnd(mssErrorNoDefault); 
1196:             } 
1197:             mssFree(str); 
1198:           } 
1199:           mssSetFldInfoSort(*(hd->flds->fi+hd->flds->cnt-1), 
1200:                                                       priority,revFlg,numFlg); 
1201:         } 
1202:  
1203:         /*コメント*/ 
1204:         str=mssGetTagCont(field->str,"field",0); 
1205:         mssSetFldInfoComment(*(hd->flds->fi+hd->flds->cnt-1), str); 
1206:         mssFree(str); 
1207:         break; 
1208:  
1209:       default: 
1210:         mssShowErrMsg("Internal Error: invalid XMLtable version"); 
1211:         mssEnd(mssErrorNoDefault); 
1212:       } 
1213:       mssFreeStrings(field); 
1214:     } 
1215:     mssFreeStrings(head); 
1216:  
1217:     mssSkipToBody(fp); 
1218:   } 
1219:  
1220:   chkInfFldName(hd,fp); /*入力項目名のチェック*/ 
1221:   return(hd); 
1222: } 
1223:  
1224: /** 
1225:  * # FUNCTION # 
1226:  * ヘッダー情報の出力(デバッグ用) 
1227:  */ 
1228: void mssShowHeader(struct mssHeader *hd) 
1229: { 
1230:   printf("====================================\n"); 
1231:   printf("         Header Information         \n"); 
1232:   printf("====================================\n"); 
1233:   printf("XML Table version : %d\n",hd->version); 
1234:   printf("title : %s\n",hd->title); 
1235:   printf("comment : %s\n",hd->comment); 
1236:   printf("fldCnt : %d\n",hd->flds->cnt); 
1237:   mssShowFields(hd->flds); 
1238: } 
1239:  
1240: /** 
1241:  * # FUNCTION # 
1242:  * mssFields構造体に格納されているソート情報とheaderのソート情報を比較し 
1243:  * mssFieldsのソート情報から見て全て一致していればソート済とみなす。 
1244:  * numeric,reverseなしで、ソートの優先順位が一致していれば1を返す。 
1245:  * numeric,reverseありで、ソートの優先順位が一致していれば2を返す。 
1246:  */ 
1247: int mssChkSortedstruct mssFields *sf, struct mssHeader *hd) 
1248: { 
1249:  
1250:   int i; 
1251:  
1252:   /*キーが指定されていない場合(same,diff)はソートされているとみなす*/ 
1253:   if(sf->cnt<1) return(1); 
1254:  
1255:   /*テキストの場合はソートされているとみなす*/ 
1256:   if(mssGV.txtFlg) return(1); 
1257:  
1258:   /*sfの各項目とhdの各項目を比較する*/ 
1259:   for(i=0; i<sf->cnt; i++){ 
1260:     if(mssFldNum2SrtRev(hd->flds,(*(sf->fi+i))->num) != (*(sf->fi+i))->revFlg){ 
1261:       return(0); 
1262:     } 
1263:     if(mssFldNum2SrtNum(hd->flds,(*(sf->fi+i))->num) != (*(sf->fi+i))->numFlg){ 
1264:       return(0); 
1265:     } 
1266:     if(mssFldNum2SrtPri(hd->flds,(*(sf->fi+i))->num)-1 != i ) { 
1267:       return(0); 
1268:     } 
1269:   } 
1270:  
1271:   /*次にnumeric,reverseが指定されているかを検査*/ 
1272:   for(i=0; i<sf->cnt; i++){ 
1273:     if( (*(sf->fi+i))->revFlg) return(2); 
1274:     if( (*(sf->fi+i))->numFlg) return(2); 
1275:   } 
1276:   return(1); 
1277: } 
1278:  
1279: /** 
1280:  * # SECTION # 
1281:  *-----------------------------------------------------------------------------  
1282:  * MssOptFLD,OptKey 関連関数 
1283:  *-----------------------------------------------------------------------------  
1284:  */ 
1285:  
1286: /** 
1287:  * # FUNCTION # 
1288:  * 入力データの何番目の項目が、オプションとして指定された何番目の項目かについて 
1289:  * の情報を返す。 
1290:  *   ex.)  
1291:  *     入力データ項目名:a  b  c  d  e 
1292:  *     -f c,e,a の時 
1293:  *     配列{2,-1,0,-1,1}を返す。 
1294:  */ 
1295: static int *setFldNo2optNo(struct mssFields *flds, int headFldCnt) 
1296: { 
1297:   int i,j; 
1298:   int *fldNo2optNo; 
1299:  
1300:   fldNo2optNo=mssMalloc(sizeof(int)*headFldCnt,"setFldNo2optNo"); 
1301:   for(i=0; i<headFldCnt; i++){ 
1302:     *(fldNo2optNo+i)=-1; 
1303:   } 
1304:   j=0; 
1305:   for(i=0; i<flds->cnt; i++){ 
1306:     *(fldNo2optNo+ MssFlds2num(flds,i))=j++; 
1307:   } 
1308:   return(fldNo2optNo); 
1309: } 
1310:  
1311: /** 
1312:  * # FUNCTION # 
1313:  * 新項目名を作成し、その文字列を返す。 
1314:  * 通常、新項目名は "-f nam:newNam"の形式で指定される。 
1315:  * このとき、namとnewNameを引数にして新しい項目名を生成し、その文字列を返す 
1316:  * この関数では次の事項に基づいて、新項目名を生成する。 
1317:  * 1. newNamに'&'文字が含まれていれば、その文字をnamに置換する。 
1318:  * 2. 1で置換した結果新項目名の長さがMssFieldMaxLenを超えるとエラー&停止 
1319:  * 3. newNamがNULLならば、namを返す。 
1320:  * 4. 新項目名のために新たな文字列領域を確保するので、nam,newNameとの干渉 
1321:  *    はない。 
1322:  *   ex.)  
1323:  *     newNam = NULL        , nam="Jan" -> return("Jan") 
1324:  *     newNam = "amount(&)" , nam="Jan" -> return("amount(Jan)") 
1325:  */ 
1326: static char *setNewFldNam(char *newNam,char *nam) 
1327: { 
1328:   char retStr[MssFieldMaxLen]; /*展開される新しい項目名の一時バッファ*/ 
1329:   char *namPnt; 
1330:   int  i; 
1331:  
1332:   i=0; 
1333:   if(newNam==NULL){ 
1334:     namPnt=nam; 
1335:     while(*namPnt!='\0'){ 
1336:       retStr[i++]=*namPnt++; 
1337:       if(i>=MssFieldMaxLen-1){ 
1338:         mssShowErrMsg("new field name exceed maximum length:%s",nam); 
1339:         mssEnd(mssErrorNoDefault); 
1340:       } 
1341:     } 
1342:  
1343:   }else{ 
1344:     while(*newNam!='\0'){ 
1345:       if(*newNam=='&'){ 
1346:         namPnt=nam; 
1347:         while(*namPnt!='\0'){ 
1348:           retStr[i++]=*namPnt++; 
1349:           if(i>=MssFieldMaxLen-1){ 
1350:             mssShowErrMsg("new field name exceed maximum length:%s",nam); 
1351:             mssEnd(mssErrorNoDefault); 
1352:           } 
1353:         } 
1354:         newNam++; 
1355:       }else{ 
1356:         retStr[i++]=*newNam++; 
1357:         if(i>=MssFieldMaxLen-1){ 
1358:           mssShowErrMsg("new field name exceed maximum length:%s",nam); 
1359:          mssEnd(mssErrorNoDefault); 
1360:         } 
1361:       } 
1362:     } 
1363:   } 
1364:   retStr[i]='\0'; 
1365:   return(mssStrdup(retStr)); 
1366: } 
1367:  
1368: /** 
1369:  * # FUNCTION # 
1370:  * MssOptFLD構造体についてoptFld->namに指定されたワイルドカードを評価し、 
1371:  * optFld->nam,newNam,fldOptを更新する。そのときワイルドカードの評価対象は 
1372:  * flds項目とする。 
1373:  * オプションをセットする関数mssSetOptionでは、ワイルドカードの展開はしない。 
1374:  * そこでこの関数にてワイルドカード評価対象項目を指定して初めて展開が可能と 
1375:  * なる。 
1376:  *   ex.) 
1377:  *    flds->nam={"customer","date","amount1","amount2"} 
1378:  *    optFld->flds->nam={"amount*"} 
1379:  *    -->> optFld->flds->nam={"amount1","amount2"} 
1380:  */ 
1381: static void evalOptFldNameGlob(MssOptFLD *optFLD, struct mssFields *flds) 
1382: { 
1383:   struct mssFldInfo **fiList; 
1384:   char **name=NULL; 
1385:   char **newName=NULL; 
1386:   char **fldOpt=NULL; 
1387:  
1388:   int fiCnt=0; 
1389:   int cnt=0; 
1390:   int i; 
1391:  
1392:   for(i=0 ; i<optFLD->cnt ; i++) { /*オプションで指定された各項目毎に*/ 
1393:     /*WCにマッチする項目リストがfiListに代入される(最後はNULLで終る)*/ 
1394:     fiCnt=0; 
1395:  
1396:     /*glob指定OKなら展開する*/ 
1397:     if(optFLD->globFlg) { 
1398:       fiList = mssFldGlbNam2Add(flds,*(optFLD->nam+i)); 
1399:  
1400:     /*glob指定NGなら単に項目名のAddressを取得する*/ 
1401:     }else{ 
1402:       fiList = mssCalloc(sizeof(struct mssFldInfo *) * 2,"evalGlob"); 
1403:       *fiList = mssFldNam2Add(flds,*(optFLD->nam+i)); 
1404:     } 
1405:  
1406:     while( *(fiList+fiCnt) != NULL ){ 
1407:  
1408:       /*ワイルドカード展開後、optFld->maxCntを越えたらエラーのチェック*/ 
1409:       if(cnt>=optFLD->maxCnt){ 
1410:         mssShowErrMsg("the max number of fields in the option is %d: -%s %s", 
1411:           optFLD->maxCnt,optFLD->keyWord,optFLD->str); 
1412:         mssEnd(mssErrorNoDefault); 
1413:       } 
1414:  
1415:       /*項目名*/ 
1416:       name=mssRealloc(name,sizeof(char *)*(cnt+1), "evalOptFldNameGlob"); 
1417:       *(name+cnt) = mssStrdup((*(fiList+fiCnt))->name); 
1418:  
1419:       /*新項目名*/ 
1420:       newName=mssRealloc(newName,sizeof(char *)*(cnt+1), "evalOptFldNameGlob"); 
1421:       *(newName+cnt)=setNewFldNam(*(optFLD->newNam+i),*(name+cnt)); 
1422:  
1423:       /*項目オプション*/ 
1424:       fldOpt=mssRealloc(fldOpt,sizeof(char *)*(cnt+1), "evalOptFldNameGlob"); 
1425:       *(fldOpt+cnt)=mssStrdup(*(optFLD->fldOpt+i)); 
1426:  
1427:       fiCnt++; 
1428:       cnt++; 
1429:     } 
1430:     mssFree(fiList); 
1431:   } 
1432:  
1433:   mssFree(optFLD->nam   ); 
1434:   mssFree(optFLD->newNam); 
1435:   mssFree(optFLD->fldOpt); 
1436:  
1437:   optFLD->nam   =name; 
1438:   optFLD->newNam=newName; 
1439:   optFLD->fldOpt=fldOpt; 
1440:   optFLD->cnt   =cnt; 
1441: } 
1442:  
1443: /** 
1444:  * # FUNCTION # 
1445:  * optFLD構造体の項目をヘッダーの項目と突き合わせて以下の3つの設定をおこなう 
1446:  * 1.MssOptFLDで指定された項目名(nam)に含まれるワイルドカードを評価し、 
1447:  *   optFld->nam,newNam,fldOptを更新する。 
1448:  * 2.optFLD->fldsに、ヘッダーの対応する項目情報をコピーする。 
1449:  * 3.ヘッダーの項目番号->オプションの指定位置の配列を設定。 
1450:  *   ex.) -f customer%r,date:DATE%rn,amt*:new(&) 
1451:  *             optFLD->nam   ={"customer","date","amt*"} 
1452:  *             optFLD->newNam={NULL,"DATE","new(&)"} 
1453:  *             optFLD->fldOpt={"r","rn",NULL} 
1454:  *        入力データのヘッダー={"customer","class","date","time","amt1","amt2"} 
1455:  *           -->> 
1456:  *        optFLD->nam   ={"customer,"date","amt1","amt2"} 
1457:  *        optFLD->newNam={"customer,"DATE","new(amt1)","new(amt2)"} 
1458:  *        optFLD->fldOpt={"r","rn",NULL,NULL} 
1459:  *        optFLD->fldNo2optNo={0,-1,1,-1,2,3} 
1460:  *        optFLD->flds->fi 
1461:  *                 ->num ={0,2,4,5} 
1462:  *                 ->name={"customer","date","amt1","amt2"} 
1463:  */ 
1464: void mssSetOptFld(MssOptFLD *optFLD, struct mssHeader *hd) 
1465: { 
1466:   int i; 
1467:   int rev,num; 
1468:  
1469:   optFLD->flds=mssInitFields(); 
1470:  
1471:   /*ワイルドカードの評価*/ 
1472:   evalOptFldNameGlob(optFLD, hd->flds); 
1473:  
1474:   /*optFLDで指定された項目名のヘッダー項目へのポインタを登録*/ 
1475:   for(i=0 ; i<optFLD->cnt ; i++) { 
1476:     mssAddFieldsByFldInfo(optFLD->flds, mssFldNam2Add(hd->flds,*(optFLD->nam+i))); 
1477:  
1478:     /*新項目名があれば登録*/ 
1479:     if(optFLD->newFlg){ 
1480:       if(0 != strcmp(*(optFLD->nam+i), *(optFLD->newNam+i)) ){ 
1481:         mssSetFldInfoName(*(optFLD->flds->fi+optFLD->flds->cnt-1), 
1482:                           *(optFLD->newNam+i)); 
1483:       } 
1484:     } 
1485:  
1486:     /* 昇順/降順、文字順/数値順のフラグを設定 */ 
1487:     rev=mssIsFldOptOn(optFLD,i,'r'); 
1488:     num=mssIsFldOptOn(optFLD,i,'n'); 
1489:     mssSetFldInfoSort(*(optFLD->flds->fi+i),0,rev,num); 
1490:   } 
1491:  
1492:   /*項目番号flagの設定*/ 
1493:   optFLD->fldNo2optNo=setFldNo2optNo(optFLD->flds,hd->flds->cnt); 
1494: } 
1495:  
1496: /** 
1497:  * # FUNCTION # 
1498:  * MssOptKEY構造体の項目をヘッダーの項目と突き合わせて以下の3つのことをおこなう 
1499:  * 1.optFLD->fldsに、ヘッダーの対応する項目情報をコピーする。 
1500:  * 2.ヘッダーの項目番号->オプションの指定位置の配列を設定。 
1501:  * 3.同一項目を複数指定していればエラーで終了する 
1502:  *   ex.) -f customer,date 
1503:  *             optFLD->nam   ={"customer","date"} 
1504:  *        入力データのヘッダー={"customer","class","date","time","amt1","amt2"} 
1505:  *           -->> 
1506:  *        optFLD->fldNo2optNo={0,-1,1,-1,-1,-1} 
1507:  *        optFLD->flds->fi 
1508:  *                 ->num ={0,2} 
1509:  *                 ->name={"customer","date"} 
1510:  */ 
1511: void mssSetOptKey(MssOptKEY *optKEY, struct mssHeader *hd) 
1512: { 
1513:   int i,j; 
1514:  
1515:   optKEY->flds=mssInitFields(); 
1516:  
1517:   /*optKEYで指定された項目名のヘッダー項目へのポインタを登録*/ 
1518:   for(i=0 ; i<optKEY->cnt ; i++) { 
1519:     mssAddFieldsByFldInfo(optKEY->flds, mssFldNam2Add(hd->flds,*(optKEY->nam+i))); 
1520:     mssSetFldInfoSort(*(optKEY->flds->fi+i),0,0,0); 
1521:   } 
1522:  
1523:   /*optKEYで同じ項目が指定されたらエラー*/ 
1524:   for(i=0 ; i<optKEY->cnt-1 ; i++) { 
1525:     for(j=i+1 ; j<optKEY->cnt ; j++) { 
1526:       if( MssFlds2num(optKEY->flds,i)==MssFlds2num(optKEY->flds,j) ){ 
1527:         mssShowErrMsg("can not specify a same field in key field(s)"); 
1528:         mssEnd(mssErrorNoDefault); 
1529:       } 
1530:     } 
1531:   } 
1532:  
1533:   /*項目番号flagの設定*/ 
1534:   optKEY->fldNo2optNo=setFldNo2optNo(optKEY->flds,hd->flds->cnt); 
1535: }