MUSASHI C source: mssBase.c


グローバル関数
mssCalloc mssCatStrings mssCatTwoStrings mssCatnStrings mssEnd mssFree mssFreeStrList mssFreeStrings mssFtoA mssGenRand mssGenRand01 mssGetStrList mssInit mssInitRand mssInitStrList mssInitStrings mssIsValidStr mssItoA mssMalloc mssPutStrList mssRealloc mssReallocLim mssSetSignalHandler mssShowAllocInf mssShowEndMsg mssShowErrMsg mssShowStartMsg mssSkipStrBlock mssStrToTime mssStrdup mssSwapDbl mssSwapInt mssSwapLng mssTokByChr


ローカル関数
addAllocInf delTmpFile isQuiet printCmdLine sigEnd sigErrEnd


0001: /** 
0002:  * # CHAPTER # 
0003:  * ============================================================================ 
0004:  * MUSASHIで用いられる基本的な関数 
0005:  * ============================================================================ 
0006:  */ 
0007:  
0008: #include <mssBase.h
0009: #include <mssConfig.h
0010: #include <mssOutput.h
0011:  
0012: #include <stdio.h> 
0013: #include <stdlib.h> 
0014: #include <stdarg.h> 
0015: #include <string.h> 
0016: #include <unistd.h> 
0017: #include <sys/time.h> 
0018: #include <dirent.h> 
0019: #include <signal.h> 
0020: #include <float.h> 
0021: #include <limits.h> 
0022: #include <math.h> 
0023:  
0024: /* ############ グローバル変数 ##############*/ 
0025: struct mssGlobalVariables mssGV; 
0026:  
0027: /** 
0028:  * # SECTION # 
0029:  * ---------------------------------------------------------------------------- 
0030:  * シグナル処理、メッセージ処理 
0031:  * ---------------------------------------------------------------------------- 
0032:  */ 
0033:  
0034: /** 
0035:  * # FUNCTION # 
0036:  * 異常終了時の一時ファイル削除 
0037:  */ 
0038: static void delTmpFile() 
0039: { 
0040:   DIR *dp; 
0041:   struct dirent *dir; 
0042:   int len; 
0043:   char prefix[MssFileNameMaxLen]; 
0044:   char fname[MssFileNameMaxLen]; 
0045:  
0046:   sprintf(prefix,"xt##%d-",getpid()); 
0047:  
0048:   len=strlen(prefix); 
0049:  
0050:   if((dp = opendir(mssGV.tmpPath)) == NULL) { 
0051:     mssShowErrMsg("can't open directory %s\n", mssGV.tmpPath); 
0052:     mssEnd(mssErrorNoDefault); 
0053:   } 
0054:   while ((dir = readdir(dp)) != NULL) { 
0055:     if (dir->d_ino == 0) continue; /*removedファイルのスキップ*/ 
0056:     if(0==strncmp(dir->d_name,prefix,len)){ 
0057:       /*fprintf(stderr,"%s\n", dir->d_name);*/ 
0058:       strcpy(fname,mssGV.tmpPath); 
0059:       strcat(fname,"/"); 
0060:       strcat(fname,dir->d_name); 
0061:       unlink(fname); 
0062:     } 
0063:   } 
0064:   closedir(dp); 
0065: } 
0066:   
0067: /** 
0068:  * # FUNCTION # 
0069:  * シグナルによるエラー終了 
0070:  */ 
0071: static void sigErrEnd(int sig) 
0072: { 
0073:   if(sig==2){ 
0074:     mssShowErrMsg("interrupt by user (CTR^C)"); 
0075:   }else{ 
0076:     mssShowErrMsg("end by signal (%d)",sig); 
0077:   } 
0078:   mssEnd(mssErrorNoDefault); 
0079: } 
0080:  
0081: /** 
0082:  * # FUNCTION # 
0083:  * シグナルによる正常終了 
0084:  */ 
0085: static void sigEnd(int sig) 
0086: { 
0087:   mssShowEndMsg(); 
0088:   mssEnd(mssExitSuccess); 
0089: } 
0090:  
0091: /** 
0092:  * # FUNCTION # 
0093:  *シグナル補足の登録(一時ファイルを利用する時) 
0094:  */ 
0095: void mssSetSignalHandler() 
0096: { 
0097:   signal( SIGSEGV, (void (*)())sigErrEnd ); 
0098:   signal( SIGPIPE, (void (*)())sigEnd ); 
0099:   signal( SIGKILL, (void (*)())sigErrEnd ); 
0100:   signal( SIGINT , (void (*)())sigErrEnd ); 
0101: } 
0102:  
0103: /** 
0104:  * # FUNCTION # 
0105:  * メッセージを出すかどうかを判定 
0106:  * コマンドラインで -Q を指定したらQuietモード 
0107:  * 環境変数 mssQuiet の値が1ならQuietモード 
0108:  * その他の場合は NoQuietモード 
0109:  * extern変数QuietはsetOptionでセットされる 
0110:  * 返値: 1:Quietモード, 0:NoQuietモード 
0111:  */ 
0112: static int isQuiet() 
0113: { 
0114:   char *envVal; 
0115:  
0116:   if(mssGV.quiet) return 1; 
0117:   envVal=getenv("mssQuiet"); 
0118:   if(envVal==NULL) return 0; 
0119:   if(*envVal=='1') return 1; 
0120:   return 0; 
0121: } 
0122:  
0123: /** 
0124:  * # FUNCTION # 
0125:  * グローバル変数(mssGV構造体)のセットおよびシグナル補足の登録 
0126:  * 通常、コマンドの最初に呼び出される関数 
0127:  */ 
0128: void mssInit(int argc, char **argv, struct mssComHelp *comHelp) 
0129: { 
0130:  
0131:   /*グローバル変数の初期化および設定*/ 
0132:   mssGV.comHelp=comHelp; 
0133:   mssGV.inCnt=0; 
0134:   mssGV.outCnt=0; 
0135:   mssGV.keyNo=0; 
0136:   mssGV.keyCnt=0; 
0137:   mssGV.keyLine=0; 
0138:   mssGV.inFldCnt=0; 
0139:   mssGV.quiet=0; 
0140:   mssGV.argc=argc; 
0141:   mssGV.argv=argv; 
0142:   mssGV.tmpPath=MssTempDir
0143:   mssGV.txtFlg=0; 
0144:   mssGV.allocDeb=0; 
0145:   mssGV.allocInf=NULL; 
0146:   mssGV.allocCnt=0; 
0147:   mssGV.writeHeaderFlg=0; 
0148:   mssGV.writeFooterFlg=0; 
0149:   mssGV.usedTempFileFlg=0; 
0150:  
0151:   /*シグナル処理の登録*/ 
0152:   mssSetSignalHandler(); 
0153: } 
0154:  
0155: /** 
0156:  * # FUNCTION # 
0157:  * 終了時に呼び出される関数 
0158:  */ 
0159: void mssEnd(int status) 
0160: { 
0161:   if(mssGV.usedTempFileFlg) delTmpFile(); 
0162:   signal( SIGSEGV, SIG_IGN ); 
0163:   signal( SIGPIPE, SIG_IGN ); 
0164:   signal( SIGKILL, SIG_IGN ); 
0165:   signal( SIGINT , SIG_IGN ); 
0166:   exit(status); 
0167: } 
0168:  
0169:  
0170: /** 
0171:  * # SECTION # 
0172:  * ---------------------------------------------------------------------------- 
0173:  * メモリ領域確保、開放関連 
0174:  * ---------------------------------------------------------------------------- 
0175:  */ 
0176:  
0177: /** 
0178:  * # DOCUMENT # 
0179:  * メモリ領域確保、開放に関するデバッグツールの使い方  
0180:  * 1: ソースで "extern struct MssGlobalVariable mssGV;"と宣言する。 
0181:  * 2: メモリ領域確保と開放の対応関係を調べたいブロックの前で 
0182:  *    "mssGV.allocDeb=1;"とする。 
0183:  *    それ以降のmssMallocmssFreeの呼び出し内容がmssGV.allocInf構造体に 
0184:  *    記録されることになる。 
0185:  * 3: ブロックの後でmssGV.allocDeb=0に戻し、記録をそこまでとする。 
0186:  * 4:その後にmssShowAllocInf()を呼び出せば、どのmssMallocがどのmssFreeで開放され 
0187:  * たかの対応関係リストが出力される。出力される結果表の2列目が-1であれば 
0188:  * 対応関係が見付からなかったこと(開放しわすれ)を意味する。 
0189:  */ 
0190:  
0191: /** 
0192:  * # FUNCTION # 
0193:  * メモリ領域確保、開放の情報をグローバル変数に追加する 
0194:  */ 
0195: static void addAllocInf(int func, void *add, char *msg) 
0196: { 
0197:   mssGV.allocInf 
0198:     =realloc(mssGV.allocInf,sizeof(struct mssAllocInf)*(mssGV.allocCnt+1)); 
0199:   (mssGV.allocInf+mssGV.allocCnt)->func=func; 
0200:   (mssGV.allocInf+mssGV.allocCnt)->add =add; 
0201:   (mssGV.allocInf+mssGV.allocCnt)->cnt =mssGV.allocFreeCnt; 
0202:   (mssGV.allocInf+mssGV.allocCnt)->msg =strdup(msg); 
0203:   (mssGV.allocInf+mssGV.allocCnt)->refNo=-1; 
0204:   mssGV.allocCnt++; 
0205: } 
0206:  
0207: /** 
0208:  * # FUNCTION # 
0209:  * メモリ領域確保、開放の一覧表を表示する 
0210:  * 表の各項目の意味は左から、 
0211:  * 1: シーケンス番号 
0212:  * 2: 対応するシーケンス番号 
0213:  * 3: 呼び出された関数名 
0214:  * 4: 領域のアドレス(Freeの場合は0) 
0215:  * 5: コメント(Freeの場合はNULL) 
0216:  */ 
0217: void mssShowAllocInf(void) 
0218: { 
0219:   int i,j; 
0220:  
0221:   for(i=mssGV.allocCnt-1; i>0; i--){ 
0222:     if( (mssGV.allocInf+i)->func==0 && (mssGV.allocInf+i)->refNo==-1 ){ 
0223:       for(j=i-1; j>=0; j--){ 
0224:         if( (mssGV.allocInf+i)->add==(mssGV.allocInf+j)->add && 
0225:             (mssGV.allocInf+j)->refNo==-1 && 
0226:             (mssGV.allocInf+j)->func!=0   ){ 
0227:           (mssGV.allocInf+i)->refNo=j; 
0228:           (mssGV.allocInf+j)->refNo=i; 
0229:           break; 
0230:         } 
0231:       } 
0232:     } 
0233:   } 
0234:  
0235:   for(i=0; i<mssGV.allocCnt; i++){ 
0236:     fprintf(stderr,"%3d : %d %d %p %d %s\n", 
0237:     i, 
0238:     (mssGV.allocInf+i)->refNo, 
0239:     (mssGV.allocInf+i)->func, 
0240:     (mssGV.allocInf+i)->add , 
0241:     (mssGV.allocInf+i)->cnt , 
0242:     (mssGV.allocInf+i)->msg ); 
0243:   } 
0244: } 
0245:  
0246: /** 
0247:  * # FUNCTION # 
0248:  * 領域開放 
0249:  *   アドレスが NULLなら何もしない 
0250:  */ 
0251: void mssFree(void *add) 
0252: { 
0253:   if(add!=NULL){ 
0254:     if(mssGV.allocDeb){ 
0255:       addAllocInf(0,add,""); 
0256:       mssGV.allocFreeCnt--; 
0257:     } 
0258:     free(add); 
0259:     //add=NULL; 
0260:   } 
0261: } 
0262:  
0263: /** 
0264:  * # FUNCTION # 
0265:  * callocによる領域確保 
0266:  */ 
0267: void *mssCalloc(int size, char *errMsg) 
0268: { 
0269:   void *p; 
0270:   p=calloc(size,1); 
0271:   if(p==NULL){ 
0272:     mssShowErrMsg("memory allocation error in [%s]",errMsg); 
0273:     mssEnd(mssErrorNoDefault); 
0274:   } 
0275:   if(mssGV.allocDeb) { 
0276:     mssGV.allocFreeCnt++; 
0277:     addAllocInf(1,p,errMsg); 
0278:   } 
0279:   return(p); 
0280: } 
0281:  
0282: /** 
0283:  * # FUNCTION # 
0284:  * mallocによる領域確保 
0285:  */ 
0286: void *mssMalloc(int size, char *errMsg) 
0287: { 
0288:   void *p; 
0289:   p=malloc(size); 
0290:   if(p==NULL){ 
0291:     mssShowErrMsg("memory allocation error in [%s]",errMsg); 
0292:     mssEnd(mssErrorNoDefault); 
0293:   } 
0294:   if(mssGV.allocDeb){ 
0295:     mssGV.allocFreeCnt++; 
0296:     addAllocInf(2,p,errMsg); 
0297:   } 
0298:   return(p); 
0299: } 
0300:  
0301: /** 
0302:  * # FUNCTION # 
0303:  * reallocによる領域確保 
0304:  */ 
0305: void *mssRealloc(void *ptr, int size, char *errMsg) 
0306: { 
0307:   void *p; 
0308:   p=realloc(ptr,size); 
0309:   if(p==NULL){ 
0310:     mssShowErrMsg("memory allocation error in [%s]",errMsg); 
0311:     mssEnd(mssErrorNoDefault); 
0312:   } 
0313:   if(mssGV.allocDeb && ptr==NULL){ 
0314:     mssGV.allocFreeCnt++; 
0315:     addAllocInf(3,p,errMsg); 
0316:   } 
0317:   return(p); 
0318: } 
0319:  
0320: /** 
0321:  * # FUNCTION # 
0322:  * 確保するサイズ指定ができるreallocによる領域確保 
0323:  */ 
0324: void *mssReallocLim(void *ptr, int size,int lim, char *errMsg) 
0325: { 
0326:   void *p; 
0327:  
0328:   if(size>lim){ 
0329:     mssShowErrMsg("exceed memory limitation of %d byte in [%s]",lim,errMsg); 
0330:     mssEnd(mssErrorNoDefault); 
0331:   } 
0332:   p=realloc(ptr,size); 
0333:   if(p==NULL){ 
0334:     mssShowErrMsg("memory allocation error in [%s]",errMsg); 
0335:     mssEnd(mssErrorNoDefault); 
0336:   } 
0337:   if(mssGV.allocDeb && ptr==NULL) { 
0338:     mssGV.allocFreeCnt++; 
0339:     addAllocInf(4,p,errMsg); 
0340:   } 
0341:   return(p); 
0342: } 
0343:  
0344: /** 
0345:  * # FUNCTION # 
0346:  * strdupによる文字列コピー 
0347:  */ 
0348: char *mssStrdup(char *s) 
0349: { 
0350:   char *S; 
0351:   if(s==NULL) return(NULL); 
0352:   S=strdup(s); 
0353:   if(mssGV.allocDeb) { 
0354:     mssGV.allocFreeCnt++; 
0355:     addAllocInf(5,S,""); 
0356:   } 
0357:   return(S); 
0358: } 
0359:  
0360: /** 
0361:  * # SECTION # 
0362:  * ---------------------------------------------------------------------------- 
0363:  * mssStrings構造体関連の関数群 
0364:  * ---------------------------------------------------------------------------- 
0365:  */ 
0366:  
0367: /** 
0368:  * # DOCUMENT # 
0369:  * ここの関数群の目的は、文字列を併合(Concatenate)し新しい文字列領域を 
0370:  * 作成することを容易に実現することにある。 
0371:  * 
0372:  * 利用例) 
0373:  *   1: struct mssStrings *s; 
0374:  *   2: s=mssInitStrings();  mssStrings構造体の初期化 
0375:  *   3: catStrings(s,"abc"); "abc"という文字列をセット 
0376:  *   4: catStrings(s,"xyz"); "xyz"という文字列を追加 
0377:  *   5: catStrings(s,"opq"); "opq"という文字列を追加 
0378:  *   6: freeStrings(s);      mssStrings構造体領域を開放 
0379:  *   上記の5:番目までの処理にて、s->str="abcxyzopq", s->cnt=9、となる。 
0380:  * 
0381:  * 併合される各文字列に対してアクセスしたい場合は、StrList関連の関数群を使う。 
0382:  */ 
0383:  
0384: /** 
0385:  * # FUNCTION # 
0386:  * mssStrings構造体の初期化 
0387:  */ 
0388: struct mssStrings *mssInitStrings() 
0389: { 
0390:   struct mssStrings *s; 
0391:   s=mssMalloc(sizeof(struct mssStrings),"initStrings"); 
0392:   s->str=NULL; 
0393:   s->cnt=0; 
0394:   return(s); 
0395: } 
0396:  
0397: /** 
0398:  * # FUNCTION # 
0399:  * mssStrings構造体領域の開放 
0400:  */ 
0401: void mssFreeStrings(struct mssStrings *s) 
0402: { 
0403:   mssFree(s->str); 
0404:   mssFree(s); 
0405: } 
0406:  
0407: /** 
0408:  * # FUNCTION # 
0409:  * mssStrings構造体に文字列を追加する 
0410:  */ 
0411: void mssCatStrings(struct mssStrings *s, char *str) 
0412: { 
0413:   int cnt=s->cnt; 
0414:   s->cnt += strlen(str); 
0415:   s->str=mssRealloc(s->str,sizeof(char)* (s->cnt+1),"catStrings"); 
0416:   if(cnt==0) strcpy(s->str,str); 
0417:   else       strcat(s->str,str); 
0418: } 
0419:  
0420: /** 
0421:  * # FUNCTION # 
0422:  * mssStrings構造体に文字列をn文字追加する 
0423:  */ 
0424: void mssCatnStrings(struct mssStrings *s, char *str, int n) 
0425: { 
0426:   int cnt=s->cnt; 
0427:   s->cnt += n; 
0428:   s->str=mssRealloc(s->str,sizeof(char)* (s->cnt+1),"catnStrings"); 
0429:   if(cnt==0) strncpy(s->str,str,n); 
0430:   else       strncat(s->str,str,n); 
0431:   *(s->str+s->cnt)='\0'; 
0432: } 
0433:  
0434: /** 
0435:  * # SECTION # 
0436:  * ---------------------------------------------------------------------------- 
0437:  * mssStrList構造体関連の関数群 
0438:  * ---------------------------------------------------------------------------- 
0439:  */ 
0440:  
0441: /** 
0442:  * # DOCUMENT # 
0443:  * この関数群の目的は、可変長文字列の一次元配列を効率的に作成することにある。 
0444:  * 内部的には、文字列を一つのメモリ領域に併合(Concatenate)し 
0445:  * 新しい一つの文字列領域を作成し、そして各文字列へのアクセスを 
0446:  * 文字位置ポインタ(文字列領域の先頭からのバイト数)によって参照する。 
0447:  * 配列の要素は0から始まる。 
0448:  * 
0449:  * 利用例) 
0450:  *   1: struct mssStrList *s; 
0451:  *   2: s=mssInitStrList();  mssStrList構造体の初期化 
0452:  *   3: mssPutStrList(s,"abc"); "abc"という文字列を要素0にセット 
0453:  *   4: mssPutStrList(s,"xyz"); "xyz"という文字列を要素1にセット 
0454:  *   5: mssPutStrList(s,"opq"); "opq"という文字列を要素2にセット 
0455:  *   6: mssFreeStrList(s);      mssStrList構造体領域を開放 
0456:  *   上記の5:番目までの処理にて記録された文字列は以下のようにmssGetStrList関数 
0457:  *   にて参照できる。 
0458:  *     mssGetStrList(s,0)=="abc" 
0459:  *     mssGetStrList(s,1)=="xyz" 
0460:  *     mssGetStrList(s,2)=="opq" 
0461:  *   要素の数は s->cntにて参照できる。上記の例では3。 
0462:  *   セットされた文字列全体の総文字数は s->chrCntで参照できる。上記の例では9。 
0463:  */ 
0464:  
0465: /** 
0466:  * # FUNCTION # 
0467:  * mssStrList構造体の初期化 
0468:  */ 
0469: struct mssStrList *mssInitStrList() 
0470: { 
0471:   struct mssStrList *s; 
0472:   s=mssMalloc(sizeof(struct mssStrList),"initStrList"); 
0473:   s->chrCnt=0; 
0474:   s->cnt=0; 
0475:   s->str=NULL; 
0476:   s->pointer=NULL; 
0477:   return(s); 
0478: } 
0479:  
0480: /** 
0481:  * # FUNCTION # 
0482:  * mssStrList構造体領域の開放 
0483:  */ 
0484: void mssFreeStrList(struct mssStrList *s) 
0485: { 
0486:   if(s==NULL)return; 
0487:   mssFree(s->str); 
0488:   mssFree(s->pointer); 
0489:   mssFree(s); 
0490: } 
0491:  
0492: /** 
0493:  * # FUNCTION # 
0494:  * mssStrList構造体に文字列を追加する 
0495:  */ 
0496: void mssPutStrList(struct mssStrList *s, char *str) 
0497: { 
0498:  
0499:   int len; 
0500:  
0501:   /*行の文字列のコピー*/ 
0502:   len = strlen(str)+1; /*+1は'\0'のため*/ 
0503:   s->chrCnt += len; 
0504:   s->str=mssRealloc(s->str,sizeof(char)* s->chrCnt,"putStrList"); 
0505:  
0506:   strncpy(s->str+s->chrCnt-len,str,len-1); /*文字のみをコピー*/ 
0507:   *(s->str+s->chrCnt-1)='\0';              /*'\0'をケツにつける*/ 
0508:  
0509:   /*行の文字数配列の更新(文字列領域の先頭からの文字数をポインタとして利用*/ 
0510:   s->pointer=mssRealloc(s->pointer,sizeof(int)*(s->cnt+1),"putStrList"); 
0511:   *(s->pointer+s->cnt)=s->chrCnt-len; 
0512:  
0513:   s->cnt++; /*レコード数をカウントアップ*/ 
0514: } 
0515:  
0516: /** 
0517:  * # FUNCTION # 
0518:  * mssStrList構造体のn番目の要素へのポインタを返す。 
0519:  * 指定した要素番号が要素数より大きい場合はNULLを返す。 
0520:  */ 
0521: char *mssGetStrList(struct mssStrList *s,int n) 
0522: { 
0523:   if( n>=s->cnt ) return(NULL); 
0524:   return(s->str+*(s->pointer+n)); 
0525: } 
0526:  
0527: /** 
0528:  * # SECTION # 
0529:  * ---------------------------------------------------------------------------- 
0530:  * 二変数のswap 
0531:  * ---------------------------------------------------------------------------- 
0532:  */ 
0533:  
0534: /** 
0535:  * # FUNCTION # 
0536:  * int型変数のswap 
0537:  */ 
0538: void mssSwapInt(int *x, int *y) 
0539: { 
0540:   int tmp; 
0541:   tmp=*x; *x=*y; *y=tmp; 
0542: } 
0543:  
0544: /** 
0545:  * # FUNCTION # 
0546:  * long型変数のswap 
0547:  */ 
0548: void mssSwapLng(long *x, long *y) 
0549: { 
0550:   long tmp; 
0551:   tmp=*x; *x=*y; *y=tmp; 
0552: } 
0553:  
0554: /** 
0555:  * # FUNCTION # 
0556:  * double型変数のswap 
0557:  */ 
0558: void mssSwapDbl(double *x, double *y) 
0559: { 
0560:   double tmp; 
0561:   tmp=*x; *x=*y; *y=tmp; 
0562: } 
0563:  
0564:  
0565: /** 
0566:  * # SECTION # 
0567:  * ---------------------------------------------------------------------------- 
0568:  * 型変換の関数群 
0569:  * ---------------------------------------------------------------------------- 
0570:  */ 
0571:  
0572: /** 
0573:  * # FUNCTION # 
0574:  * 文字列の日付からtime_t型日付値に変換 
0575:  */ 
0576: time_t mssStrToTime(char *str) 
0577: { 
0578:   char buf[20]; 
0579:   time_t caltime; 
0580:   struct tm worktm; 
0581:  
0582:   strncpy(buf, str, 4); /*最初の文字から4文字コピーする,添字のから格納*/ 
0583:   buf[4] = '\0'; 
0584:  
0585:   /*0から数えて4つ目に空文字を代入*/ 
0586:   worktm.tm_year = atoi(buf) - 1900; /*暦時間にするために1900引く*/ 
0587:  
0588:   strncpy(buf, str+4, 2); 
0589:   buf[2] = '\0'; 
0590:   worktm.tm_mon = atoi(buf) - 1;    /*暦時間にするために1900引く*/ 
0591:  
0592:   strncpy(buf, str+6, 2); 
0593:   buf[2] = '\0'; 
0594:   worktm.tm_mday = atoi(buf); 
0595:   worktm.tm_hour = 0; 
0596:   worktm.tm_min = 0; 
0597:   worktm.tm_sec = 0; 
0598:  
0599:   if((caltime = mktime(&worktm)) == -1){ /*mktimeにより暦時間に変換*/ 
0600:     return(-1); 
0601:   } 
0602:   return(caltime); 
0603: } 
0604:  
0605: /** 
0606:  * # FUNCTION # 
0607:  * int型数値を文字列に変換 
0608:  */ 
0609: char *mssItoA(int num) 
0610: { 
0611:   char buf[100]; 
0612:   sprintf(buf,"%d",num); 
0613:   return(mssStrdup(buf)); 
0614: } 
0615:  
0616: /** 
0617:  * # FUNCTION # 
0618:  * double型数値を文字列に変換 
0619:  * 小数点以下の無意味な0は取り除かれる。(ex. 1.560000 -> 1.56, 1.0 -> 1) 
0620:  */ 
0621: char *mssFtoA(double num) 
0622: { 
0623:   int i = 0; 
0624:   char buf[2048]; 
0625:  
0626:   sprintf(buf,"%f",num); 
0627:   while(buf[i]!='\0') i++; 
0628:   while(1) { 
0629:     i--; 
0630:     if(buf[i]=='.') {buf[i]='\0';break;} 
0631:     if(buf[i]=='0') {buf[i]='\0';} 
0632:     else        break; 
0633:   } 
0634:   return(mssStrdup(buf)); 
0635: } 
0636:  
0637: /** 
0638:  * # SECTION # 
0639:  * ---------------------------------------------------------------------------- 
0640:  * 乱数関連の関数群 
0641:  * ---------------------------------------------------------------------------- 
0642:  */ 
0643:  
0644: /** 
0645:  * # FUNCTION # 
0646:  * 乱数シードの設定 
0647:  * 乱数シードを設定し、そのシード(数値)を返す 
0648:  * 引数seedに-1を与えたときは、現在時刻をシードとして用いる。 
0649:  */ 
0650: int mssInitRand(int seed) 
0651: { 
0652:   time_t  long_time;       /*乱数の種用の時間構造体*/                          
0653:   struct tm     *nt;       /*同上*/ 
0654:   int usedSeed; 
0655:  
0656:   if(seed==-1){ 
0657:     time(&long_time); 
0658:     nt = localtime(&long_time); 
0659:     usedSeed=nt->tm_hour*10000+nt->tm_min*100+nt->tm_sec; 
0660:   }else{ 
0661:     usedSeed=seed; 
0662:   } 
0663:   srand(usedSeed); 
0664:   return(usedSeed); 
0665: }      
0666:  
0667: /** 
0668:  * # FUNCTION # 
0669:  * 与えられた0以上の整数範囲の乱数を生成し、その値を返す。 
0670:  * 整数範囲のチェックはしていないので、アプリケーション側でチェックすること。 
0671:  */ 
0672: int mssGenRand(int from, int to) 
0673: { 
0674:   double unit; 
0675:  
0676:   unit=((double)RAND_MAX+1)/(double)(to-from+1); 
0677:   return( (int)((double)rand()/unit) ); 
0678: } 
0679:  
0680: /** 
0681:  * # FUNCTION # 
0682:  * 0以上1以下の実数乱数を発生させる。 
0683:  */ 
0684: double mssGenRand01() 
0685: { 
0686:   return( (double)rand()/(double)RAND_MAX ); 
0687: } 
0688:  
0689: /** 
0690:  * # SECTION # 
0691:  * ---------------------------------------------------------------------------- 
0692:  * 文字列操作のための各種関数 
0693:  * ---------------------------------------------------------------------------- 
0694:  */ 
0695:  
0696: /** 
0697:  * # FUNCTION # 
0698:  * 二つの文字列を連結し新しい文字列を返す。 
0699:  * もとの二つの文字列には一切変更を加えない。 
0700:  * 新たな領域を確保する。 
0701:  */ 
0702: char *mssCatTwoStrings(char *str1, char *str2) 
0703: { 
0704:   char *str; 
0705:   int len; 
0706:   int len1=0; 
0707:   int len2=0; 
0708:  
0709:   if(str1!=NULL){ 
0710:     len1=strlen(str1); 
0711:   } 
0712:  
0713:   if(str2!=NULL){ 
0714:     len2=strlen(str2); 
0715:   } 
0716:   len=len1+len2; 
0717:  
0718:   if(len==0) return(mssStrdup("")); 
0719:  
0720:   str=mssMalloc(sizeof(char)*(len+1),"catTwoStrings"); 
0721:   *str='\0'; 
0722:   if(len1!=0) strcat(str,str1); 
0723:   if(len2!=0) strcat(str,str2); 
0724:   return(str); 
0725: } 
0726:   
0727: /** 
0728:  * # FUNCTION # 
0729:  * 括弧などで囲まれた文字列ブロックをスキップし、その次の位置を返す。 
0730:  * 指定されたstartChr,endCharがなかったり、括弧の対応関係がおかしければNULLを 
0731:  * 返す。 
0732:  * 括弧の種類は開始括弧文字と終了括弧文字で指定する。 
0733:  * 開始括弧文字と終了括弧文字が同じ場合は、ネストを考慮できないので、 
0734:  * 次の括弧文字までをスキップすることになる。 
0735:  * 例1)                      例2)                    例3) 
0736:  * abc(aaa*(aaa-ccc))xyz     abc"aaa*"aaa-ccc""xyz   ab(aaa) 
0737:  *    ^              ^          ^     ^              ^      ^ 
0738:  *   str          返す位置     str    返す位置       str    返す位置 
0739:  */ 
0740: char *mssSkipStrBlock(char *str, char startChr, char endChr) 
0741: { 
0742:   int cnt=0; 
0743:   int same=0; 
0744:  
0745:   if(startChr==endChr) same=1; 
0746:  
0747:   while(1) { 
0748:     if(*str=='\0'){ 
0749:       return(NULL); 
0750:     }else if(*str==startChr){ 
0751:       cnt++; 
0752:     }else if(*str==endChr){ 
0753:       cnt--; 
0754:     } 
0755:     str++; 
0756:     if( cnt==0        ) break; 
0757:     if( cnt==2 && same) break; 
0758:   } 
0759:   return(str); 
0760: } 
0761:  
0762: /** 
0763:  * # FUNCTION # 
0764:  * 文字列のトークン分割を行い、文字列ポインタ(char **)を返す。 
0765:  * 引数dupを1とした時は、オリジナルの文字列をmssStrdupしてからトークン分割を 
0766:  * 行うのでオリジナルの文字列は一切変更されない。 
0767:  * 一方で、引数dupに0(1以外)を指定すると、オリジナルの文字列に対してトークン 
0768:  * 分割を行うので、オリジナルの文字は変更される。 
0769:  * トークン分割された文字列の数は引数cntポインタで示された 
0770:  * 整数変数にセットされる。 
0771:  * 
0772:  * なお、引数dupを1としてこの関数を用いてトークン分割した場合、 
0773:  * 新たに確保された文字列領域を開放するには、文字列ポインタの最初の 
0774:  * 要素(アドレス)のみ開放すればよい。 
0775:  * 利用例) 
0776:  *   char **s; 
0777:  *   int cnt; 
0778:  *   s=mssTokByChr("abc,efg,hij", ',', &cnt, 1); 
0779:  *   Free(*s); 
0780:  * 
0781:  *   結果 *(s+0)=="abc" 
0782:  *        *(s+1)=="efg" 
0783:  *        *(s+2)=="hij" 
0784:  *           cnt==3; 
0785:  */ 
0786: char **mssTokByChr(char *string, char tok, int *cnt, int dup) 
0787: { 
0788:   char *str; 
0789:   char *pos; 
0790:   char **list=NULL; 
0791:  
0792:   *cnt=0; 
0793:   if(dup) str=mssStrdup(string); 
0794:   else    str=string; 
0795:  
0796:   pos=str; 
0797:   while(1){ 
0798:     if(*str==tok || *str=='\0'){ 
0799:       list=mssRealloc(list,sizeof(char *)*(*cnt+1),"tokByChr"); 
0800:       *(list+*cnt)=pos; 
0801:       (*cnt)++; 
0802:       pos=str+1; 
0803:       if(*str=='\0') break; 
0804:       *str='\0'; 
0805:     } 
0806:     str++; 
0807:   } 
0808:   return(list); 
0809: } 
0810:  
0811: /** 
0812:  * # FUNCTION # 
0813:  * 妥当な文字列かどうかチェックする。 
0814:  * 妥当な文字列とは、NULLもしくは長さ0の文字列のこと。 
0815:  */ 
0816: int mssIsValidStr(char *str) 
0817: { 
0818:   if(str==NULL || *str=='\0') return(0); 
0819:   return(1); 
0820: } 
0821:  
0822: /** 
0823:  * # SECTION # 
0824:  * ---------------------------------------------------------------------------- 
0825:  * メッセージの出力関連の関数 
0826:  * ---------------------------------------------------------------------------- 
0827:  */ 
0828:  
0829: /** 
0830:  * # FUNCTION # 
0831:  * コマンドラインを書き出す 
0832:  * argvに改行が含まれていればスペースに変換して出力する 
0833:  */ 
0834: static void printCmdLine(struct mssFPW *fp) 
0835: { 
0836:   int i,j,len; 
0837:   char *str; 
0838:  
0839:  
0840:   mssWriteStr("\"",fp); 
0841:   for(i=0; i<mssGV.argc; i++){ 
0842:     len=strlen(*(mssGV.argv+i)); 
0843:     str=mssMalloc(sizeof(char)*(len+1),"printCmdLine"); 
0844:     for(j=0; j<len; j++){ 
0845:       if('\n'!=*(*(mssGV.argv+i)+j)){ 
0846:         *(str+j)=*(*(mssGV.argv+i)+j); 
0847:       }else{ 
0848:         *(str+j)=' '; 
0849:       } 
0850:     } 
0851:     *(str+j)='\0'; 
0852:     mssWriteStr(str,fp); 
0853:     mssFree(str); 
0854:  
0855:     if(i!=mssGV.argc-1){ 
0856:       mssWriteStr(" ",fp); 
0857:     }else{ 
0858:       mssWriteStr("\"",fp); 
0859:     } 
0860:   } 
0861: }  
0862:  
0863: /** 
0864:  * # FUNCTION # 
0865:  * 開始メッセージ 
0866:  * 出力例) #START# 2996 2003/04/11 21:56:37 "xtcut -f customer -i dat.xt" 
0867:  *   #START#に続いて、プロセス番号,日付,時刻,コマンドライン 
0868:  */ 
0869: void mssShowStartMsg() 
0870: { 
0871:   struct mssFPW *fp; 
0872:  
0873:   if(!isQuiet()){ 
0874:     fp=mssOpenFPW((char *)1,0,0); /*標準エラー出力オープン*/ 
0875:     mssWriteStr("#START# ",fp); 
0876:     mssWriteInt(getpid(),fp); 
0877:     mssWriteStr(" ",fp); 
0878:     mssWriteDate(fp,1); 
0879:     mssWriteStr(" ",fp); 
0880:     mssWriteTime(fp,1); 
0881:     mssWriteStr(" ",fp); 
0882:     printCmdLine(fp); 
0883:     mssWriteRet(fp); 
0884:     mssCloseFPW(fp); 
0885:   } 
0886: } 
0887:  
0888: /** 
0889:  * # FUNCTION # 
0890:  * 正常終了メッセージ 
0891:  * 出力例) 
0892:  *   #END# 2999 2003/04/11 21:59:21 "xtcut -f customer -i xxcc.xt" in=25 out=25 
0893:  *   #END#に続いて、プロセス番号,日付,時刻,コマンドライン,入力件数,出力件数 
0894:  */ 
0895: void mssShowEndMsg() 
0896: { 
0897:   struct mssFPW *fp; 
0898:  
0899:   if(!isQuiet()){ 
0900:     fp=mssOpenFPW((char *)1,0,0); /*標準エラー出力オープン*/ 
0901:     mssWriteStr("#END# ",fp); 
0902:     mssWriteInt(getpid(),fp); 
0903:     mssWriteStr(" ",fp); 
0904:     mssWriteDate(fp,1); 
0905:     mssWriteStr(" ",fp); 
0906:     mssWriteTime(fp,1); 
0907:     mssWriteStr(" ",fp); 
0908:     printCmdLine(fp); 
0909:     mssWriteStr(" in="  ,fp); 
0910:     mssWriteInt(mssGV.inCnt  ,fp); 
0911:     mssWriteStr(" out=",fp); 
0912:     mssWriteInt(mssGV.outCnt ,fp); 
0913:     mssWriteRet(fp); 
0914:     mssCloseFPW(fp); 
0915:   } 
0916: } 
0917:  
0918: /** 
0919:  * # FUNCTION # 
0920:  * エラー終了メッセージ 
0921:  * メッセージに含まれる改行は全て"_"に変換される。 
0922:  * 出力例) #ERROR# 2996 "xtcut" "option -f is mandatory" 
0923:  *   #ERROR#に続いて,プロセス番号,コマンドライン,エラーメッセージ 
0924:  */ 
0925: void mssShowErrMsg(char *msg, ...) 
0926: { 
0927:   char tmp[1024]; 
0928:   va_list args; 
0929:   struct mssFPW *fp; 
0930:   int i; 
0931:  
0932:   if(isQuiet()) return; 
0933:  
0934:   va_start(args,msg); 
0935:   vsprintf(tmp,msg,args); 
0936:  
0937:   /*改行を_に変換*/ 
0938:   for(i=0;;i++){ 
0939:     if(tmp[i]=='\0') break; 
0940:     if(tmp[i]=='\n') tmp[i]='_'; 
0941:   } 
0942:  
0943:   fp=mssOpenFPW((char *)1,0,0); /*標準エラー出力オープン*/ 
0944:   mssWriteStr("#ERROR# ",fp); 
0945:   mssWriteInt(getpid(),fp); 
0946:   mssWriteStr(" ",fp); 
0947:   printCmdLine(fp); 
0948:   mssWriteStr(" \"",fp); 
0949:   mssWriteStr(tmp,fp); 
0950:   mssWriteStr("\"",fp); 
0951:   mssWriteRet(fp); 
0952:   mssCloseFPW(fp); 
0953: }