グローバル関数 ローカル関数
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: * それ以降のmssMallocやmssFreeの呼び出し内容が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: }