Develop and Download Open Source Software

Browse Subversion Repository

Diff of /branches/mty-makai/mty.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 250 by notanpe, Wed Dec 22 09:04:00 2010 UTC revision 252 by notanpe, Mon Dec 27 03:23:48 2010 UTC
# Line 9  Line 9 
9   */   */
10    
11  #include <assert.h>  #include <assert.h>
 #include <ctype.h>  
 #include <errno.h>  
 #include <limits.h>  
 #include <stdarg.h>  
12  #include <stddef.h>  #include <stddef.h>
13  #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  
 #include <string.h>  
14  #include <time.h>  #include <time.h>
15  #include <sys/timeb.h>  #include <sys/timeb.h>
 #include <sys/types.h>  
   
 #ifndef __ICL  
  #include <unistd.h>  
  #include <libgen.h>  
 #endif /* not __ICL */  
   
 #include <limits.h>  
 #ifdef REON  
  #ifdef ONI  
   #include <onigposix.h>  
  #else /* ONI */  
   /* #include <rxposix.h> */  
   #include <regex.h>  
  #endif /* ONI */  
 #endif /* REON */  
16    
17  #if defined(WIN32)  #if defined(WIN32)
18    
# Line 47  Line 25 
25    
26  #endif  #endif
27    
 #include "config.h"  
 #include "cp932.h"  
 #include "crypt64.h"  
28  #include "desconst.h"  #include "desconst.h"
29  #include "expr_parse.h"  #include "expr_parse.h"
30    #include "hit.h"
31    #include "key.h"
32    #include "log.h"
33  #include "scoreboard.h"  #include "scoreboard.h"
34  #include "synth.h"  #include "synth.h"
 #include "tr64.h"  
 #include "translate.h"  
35  #include "util.h"  #include "util.h"
 #include "wdict.h"  
   
 #define TRIP_LEN 10  
   
 #define MAKAI_TRUE  1  
 #define MAKAI_FALSE 0  
   
 #define MIN_THREAD  1  
 #define MAX_THREAD 32  
 int     nThread = 0;  
 uint64_t        pmask = 0;  
   
 #define MIN_UME 3  
 #define MAX_UME 6  
 unsigned char   umeStr[10];  
 int     umeLen;  
   
 FILE    *nfp;   /* 全数 */  
 FILE    *cfp;   /* ち */  
 FILE    *tfp;   /* ↑以外の特殊検索 */  
 #ifdef REON  
 FILE    *rfp;   /* 正規表現 */  
 #endif /* REON */  
36    
37  /*  static HANDLE mutex_key;
  Cygwin 32bit  
  time_t = long = int  
  INT_MIN                              -2147483648  
  INT_MAX                               2147483647  
  (2009 - 1970)  * 365 * 24 * 60 * 60 = 1229904000  
  2147483647 - 1229904000 =              917579647  
  10y * 365 * 24 * 60 * 60 =             315360000  
   
  perl -e 'use POSIX;printf(strftime("%Y/%m/%d %T\n",localtime (1234567890)));'  
 */  
 #define MIN_SOFF -1229904000  
 #define MAX_SOFF   315360000  
 unsigned int    seed;  
 int     seedOffset;  
 int     verbose;  
   
 #define   MAX_GEAR   10  
 #define   MIN_GEAR    1  
 #define   DEF_GEAR   10  
 int     gear;  
   
 #ifdef KEYLOG  
 #define   KEY_LOG_FILE   "keylog.txt"  
 int     keyLog = MAKAI_FALSE;  
 #endif /* KEYLOG */  
   
 #ifdef SELF  
 #define   SELF_LIM_CNT   50  
 #define   SELF_LIM_SEC   60 * 60 * 1000 /* 1h */  
 #endif /* SELF */  
   
 unsigned char   saltChar[2];  
   
 #ifdef ALLKEY  
 unsigned char   fixedSaltChar[2];  
 #endif /* ALLKEY */  
38    
39  /* CRYPT64 記述子 */  /* CRYPT64 記述子 */
40  static  static
# Line 126  struct CRYPT64_DESC const *const crypt64 Line 43  struct CRYPT64_DESC const *const crypt64
43    &crypt64_desc,    &crypt64_desc,
44  };  };
45    
46  /* 鍵クラス */  /* 速度評価用 */
47  static  static int n_cpus;
48  struct  static uint64_t loop_cpu[1024];
 {  
   unsigned short map[256];  
 } kcls[8 + 8];  
   
 /* 拡張鍵クラス */  
 #define KCLS_DT0 64  
 #define KCLS_DT1 128  
 #define KCLS_K2 256  
   
 int     special = 0;  
 #define ST_ALLN 1      /* 全数 */  
 #define ST_NIKO 1<<0x1 /* 二構 */  
 #define ST_BUOO 1<<0x8 /* ぶお */  
 #define ST_DOSU 1<<0x9 /* 怒数 */  
 #define ST_CHIN 1<<0xb /* ちん Uni では感嘆用のフラグ */  
 #define ST_EROI 1<<0xc /* エロ Uni では拡飛のフラグ */  
 #define ST_HREN 1<<0xd /* 飛連 */  
 #define ST_YAKU 1<<0xe /* 八雲 */  
   
 #ifdef REON  
 #define REGEXPLEN 1024  
 char regExpStr[REGEXPLEN];  
 regex_t regExp;  
 #endif /* REON */  
   
 void  
 comment( str )  
 char    *str;  
 {  
   if ( strlen( str ) >= 4 ) {  
    if ( str[1] == '[' && str[3] == ']' ) {  
     switch ( str[2] ) {  
      case '0': special |= ST_ALLN; break;  
      case '1': special |= ST_NIKO; break;  
      case '8': special |= ST_BUOO; break;  
      case '9': special |= (ST_DOSU | ST_ALLN); break;  
      case 'd': special |= ST_HREN; break;  
      case 'e': special |= ST_YAKU; break;  
      case 'Y': special |= ST_CHIN; break;  
      case 'Z': special |= ST_EROI; break;  
 #ifdef KEYLOG  
      case 'K': keyLog = MAKAI_TRUE; break;  
 #endif /* KEYLOG */  
      case 'S':  
       seedOffset = atoi( str + 4 );  
       if ( seedOffset < MIN_SOFF || seedOffset > MAX_SOFF ) {  
        fprintf( stderr, "乱数の種のオフセットは、%d 以上 %d 以下で指定してね。\n", MIN_SOFF, MAX_SOFF );  
        fprintf( stderr, "%d は範囲外なので無視します。\n", seedOffset );  
        seedOffset = 0;  
       }  
       break;  
      case 'R':  
 #ifdef REON  
       if ( strlen( str ) >= REGEXPLEN ) {  
        fprintf( stderr, "正規表現 (%s) が長すぎ", str );  
        exit( 1 );  
       }  
       strcpy( regExpStr, str + 4 );  
       if ( regcomp( &regExp, regExpStr, REG_NOSUB|REG_EXTENDED ) != 0 ) {  
        fprintf( stderr, "正規表現 (%s) がおかしい?\n", str );  
        exit( 1 );  
       }  
 #else /* REON */  
       fprintf( stderr, "このバイナリは、正規表現をサポートしていません。\n" );  
       fprintf( stderr, "%s は無視します。\n", str );  
 #endif /* REON */  
       break;  
     }  
    }  
   }  
 }  
   
 #ifndef ALLKEY  
 /* 指定されたクラスと入っているキーから、classify を行う */  
 void  
 key_make_map(uint8_t *key, int n)  
 {  
   int i, j;  
   unsigned c = kcls[n].map[key[n]];  
   
   /* 最後の部分は class map を生成する必要ナシ */  
 /* MAKAI memo  
  6byte 埋めた時の挙動  
  下の方の if (n == 6) と矛盾  
 */  
   if ( n >= 6 ) return;  
   
   for ( i = 0; i < 256; i++ ) {  
    unsigned bm = 0;  
    if ( c & KCLS_K1 ) {  
     if ( cp932[256 * key[n] + i] & KCLS_K1 ) {  
      bm |= KCLS_K2 | (cp932[256 * key[n] + i] & KCLS_DT1);  
     }  
     if ( cp932[256 * (key[n] ^ 0x80) + i] & KCLS_K1 ) {  
      bm |= KCLS_K2 | (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_DT1);  
     }  
    }  
    if ( c & (KCLS_AN | KCLS_KA | KCLS_K2) ) {  
     for ( j = 0; j < 256; j++ ) {  
      bm |= cp932[256 * i + j] & (KCLS_AN | KCLS_KA | KCLS_K1 | KCLS_DT0);  
     }  
    }  
    kcls[n + 1].map[i] = bm;  
    if ( i >= 128 && !(n == 0 || n == 1) ) {  
     kcls[n + 1].map[i - 128] |= kcls[n + 1].map[i];  
    }  
   }  
   
   if ( n < 6 ) kcls[n + 1].map[0x00] = kcls[n + 1].map[0x80] = 0;  
 #if 0  
   if ( n == 6 ) kcls[7].map[0x00] |= KCLS_AN;  
 #endif /* 0 */  
 }  
 #endif /* not ALLKEY */  
   
 /* マップから文字を拾ってセット */  
 unsigned  
 key_set(int n, unsigned ch)  
 {  
   int cnt = 0, i;  
   
 #ifdef NOMORE  
   ch %= 256;  
 #endif /* NOMORE */  
   
   for ( i = 0; i < 256; i++ ) {  
    if ( kcls[n].map[i] ) {  
     if ( ch-- == 0 ) return i;  
     cnt++;  
    }  
    if ( n != 1 && n != 2 && i >= 127 ) break;  
   }  
   /* 見つからなかったのでもいっぺん */  
   assert( cnt > 0 );  
   ch %= cnt;  
   for ( i = 0; i < 256; i++ ) {  
    if ( kcls[n].map[i] ) {  
     if ( ch-- == 0 ) return i;  
    }  
   }  
   assert( !"not matched" );  
   return 0;  
 }  
   
 /* bitwise key をセット */  
 static  
 void  
 key_set64(struct KEY *key64,  
                   int n,  
                   unsigned k,  
                   unsigned vk,  
                   unsigned sk)  
 {  
   int i, j;  
   if (!((vk | sk) & 0x7F))  
         return;  
   
   for (i = 0; i < 7; i++)  
         {  
           if (n == 7 && i < N_STRIDE) continue;  
           if (sk & (1 << i))  
                 {  
                   /* セット */  
                   int o = tr_pc1[n][6 - i] - 1;  
                   if (o < 28)  
                         {  
                           assert(o >= 0);  
                           for (j = 0; j < N_ALU; j++)  
                                 key64->k[0][0][o].a[j]  
                                 = key64->k[0][1][o].a[j]  
                                   = -!!(k & (1 << i));  
                         }  
                   else  
                         {  
                           assert(o >= 28);  
                           assert(o < 56);  
                           for (j = 0; j < N_ALU; j++)  
                                 key64->k[1][0][o - 28].a[j]  
                                   = key64->k[1][1][o - 28].a[j]  
                                   = -!!(k & (1 << i));  
                         }  
                 }  
           else if (vk & (1 << i))  
                 {  
                   /* 反転 */  
                   int o = tr_pc1[n][6 - i] - 1;  
                   if (o < 28)  
                         {  
                           assert(o >= 0);  
                           for (j = 0; j < N_ALU; j++)  
                           key64->k[0][0][o].a[j]  
                                 = key64->k[0][1][o].a[j]  
                                 = ~key64->k[0][0][o].a[j];  
                         }  
                   else  
                         {  
                           assert(o >= 28);  
                           assert(o < 56);  
                           for (j = 0; j < N_ALU; j++)  
                                 key64->k[1][0][o - 28].a[j]  
                                 = key64->k[1][1][o - 28].a[j]  
                                 = ~key64->k[1][0][o - 28].a[j];  
                         }  
                 }  
         }  
 }  
   
 /* 指定されたクラスの開始値にリセット  
    直前の文字のクラスに縛られる */  
 int  
 key_reset(uint8_t *key, int n)  
 {  
   static char   firstCall = 1;  
   
   if ( firstCall ) {  
    firstCall = 0;  
   } else {  
    if ( umeStr[0] != '\0' && n == 0 ) {  
      exit( 0 );  
    }  
   }  
   
   if (n >= 8)  
         return 1;  
   if (n == 7)  
         {  
           key[7] = 0;  
           return 1;  
         }  
   
   if ( n >= umeLen ) {  
 #ifdef ALLKEY  
    for ( ; n < 7; n++ ) {  
     key[n] = 1;  
    }  
    key[7] = 0;  
    return 1;  
 #else /* ALLKEY */  
    key[n] = key_set(n, 0);  
 #endif /* ALLKEY */  
   } else {  
    if ( umeStr[0] == '\0' ) {  
 #ifdef ALLKEY  
     key[n] = rand() % 0x7f + 1;  
 #else /* ALLKEY */  
     key[n] = key_set(n, rand());  
 #endif /* ALLKEY */  
    } else {  
     key[n] = umeStr[n];  
    }  
 #ifdef KEYLOG  
    /* 検索空間の記録 */  
    if ( keyLog && (n == umeLen - 1) ) {  
     FILE        *fp;  
     int i;  
         struct timeb    tb;  
         struct tm       *plt;  
   
         ftime( &tb );  
         plt = localtime( &tb.time );  
   
 #ifdef OLDDEBUG  
     printf( "\nそぉーるとちぇーんじ!\n" );  
 #endif /* DEBUG */  
     if ( (fp = fopen( KEY_LOG_FILE, "at" )) == NULL ) {  
      perror( KEY_LOG_FILE );  
      exit( 1 );  
     }  
     for ( i = 0; i < umeLen; i++ ) {  
      fprintf( fp, "%02x", key[i] );  
     }  
     fprintf( fp, "\t%04d/%02d/%02d %02d:%02d:%02d.%03d\n",  
              plt->tm_year + 1900, plt->tm_mon + 1, plt->tm_mday,  
              plt->tm_hour, plt->tm_min, plt->tm_sec, tb.millitm );  
     fclose( fp );  
    }  
 #endif /* KEYLOG */  
   }  
   
 #if DEBUG>=3  
   printf("key[%d]=%02X ncls=%04X\n", n, key[n], kcls[n].map[key[n]]);  
 #endif  
   
 #ifndef ALLKEY  
   /* セットされた文字を元に、次キャラの文字クラスを決める */  
   key_make_map(key, n);  
 #endif /* not ALLKEY */  
   
   return key_reset(key, n + 1);  
 }  
   
 /* 指定された鍵空間の中で、キーをひとつ進める  
    安全にインクリメントできた場合 true を返す */  
 static  
 int  
 key_inc(uint8_t *key, int n)  
 {  
 #if 0  
 if ( n != 7 ) {  
 printf( "%d : %02x %02x %02x %02x %02x %02x %02x %02x\n",  
         n, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7] );  
 }  
 #endif /* 0 */  
   
   if ( n >= 8 ) {  
    return 0;  
   } else if ( n == 7 ) {  
 /* MAKAI memo  
 2^N_STRIDE がいっぺんに計算する個数  
  MMX 6  : 64 個  
  SSE2 7 : 128 個  
 このため最後のバイトの進め方が変わる  
 */  
    uint8_t      o_k = (key[7] + (1 << N_STRIDE)) & 0x7F;  
    if ( !o_k ) {  
     return 0;   /* インクリメントできなかったときは次へ進めず待つ */  
    } else {  
     key[7] = o_k;  
     return 1;  
    }  
   } else if ( key_inc( key, n+1 ) ) {  
    return 1;  
   }  
   
   /* Salt はインクリメントしない約束にする */  
   if ( n == 1 || n == 2 ) {  
    return 1;  
   }  
   
 #ifdef ALLKEY  
   key[n] = ( key[n] & 0x7F ) + 1;  
   if ( key[n] >= 0x80 ) {  
    key[n] = 0xFF;       /* 次に突入させないため */  
    return 0;  
   }  
   key_reset( key, n + 1 );  
   return 1;  
 #endif /* ALLKEY */  
   
   /* 実際に増やしてみる */  
   assert( n >= 3 );  
   for ( ;; ) {  
           if (n <= 3  
                   && !(key[n] & 0x80)  
                   && kcls[n].map[key[n] ^ 0x80] & (KCLS_DT0))  
                 {  
                   /* 半角カタカナの1バイト目 */  
                   key[n] ^= 0x80;  
                 }  
           else  
                 {  
                   key[n] = (key[n] & 0x7F) + 1;  
                   if (key[n] >= 0x80)  
                         {  
                           key[n] = 0xFF;        /* 次に突入させないため */  
                           return 0;  
                         }  
                 }  
   
           if (kcls[n].map[key[n]])  
                 {  
 #ifndef ALLKEY  
                   key_make_map(key, n);  
 #endif /* not ALLKEY */  
                   key_reset(key, n + 1);  
                   return 1;  
                 }  
         }  
 }  
   
 /* 鍵を完全にリセットする  
    Saltもセットし直す */  
 static  
 void  
 key_init(uint8_t *key)  
 {  
   int i, j;  
   
   key[8] = 0;  
   
 #ifndef ALLKEY  
   /* 初期マップを組む */  
   for ( i = 0; i < 256; i++ ) {  
    unsigned bm = 0;  
   
    for ( j = 0; j < 256; j++ ) {  
     bm |= cp932[256 * i + j];  
    }  
    kcls[0].map[i] = bm & (KCLS_AN | KCLS_KA | KCLS_K1);  
    if ( i >= 128 ) {  
     kcls[0].map[i - 128] |= kcls[0].map[i];  
    }  
   }  
 #endif /* not ALLKEY */  
   
   key_reset(key, 0);  
 }  
   
 /***************************************************************  
  *  
  *      固定キーの生成  
  *  
  *      一見 Big Endian に非対応のように見えるだろうが  
  *      随所でに散らばっている kludge により  
  *      ALU_T が 64 ビットである限り、これで問題なく動く。  
  *  
  */  
   
 static  
 void  
 key_init_sk(struct KEY *key)  
 {  
   int i, j;  
   int o;  
   uint64_t m;  
   
   for (i = 5, m = 0xFFFFFFFF00000000ULL;  
            i >= 0;  
            m ^= (m >> (1 << --i)))  
         {  
           o = tr_pc1[7][6 - i] - 1;  
 #if DEBUG>=2  
           printf("%d:%d->%2d: %08X%08X\n",  
                          N_Q, i, o,  
                          (unsigned)(m >> 32),  
                          (unsigned)m);  
 #endif  
           for (j = 0; j < N_Q; j++)  
                 if (o < 28)  
                   key->k[0][0][o     ].q[j] = key->k[0][1][o     ].q[j] = m;  
                 else  
                   key->k[1][0][o - 28].q[j] = key->k[1][1][o - 28].q[j] = m;  
         }  
 #if N_STRIDE==7  
   /* bit 6 は Little Endian として扱う */  
   o = 0;  
   assert(tr_pc1[7][0] - 1 == o);  
   assert(N_Q == 2);  
   key->k[0][0][o].q[0] = key->k[0][1][o].q[0] = 0x0000000000000000ULL;  
   key->k[0][0][o].q[1] = key->k[0][1][o].q[1] = 0xFFFFFFFFFFFFFFFFULL;  
 #endif  
 }  
   
 /***************************************************************  
  *  
  *      Salt のセット  
  *      オペランドのオフセットを書き換えて回ってるので注意  
  *  
  */  
   
 void  
 set_salt(CODE_T *code,  
                  struct CRYPT64_DESC const *desc,  
                  uint8_t const *k)  
 {  
   int   i, j;  
   
   static unsigned char  *s2c = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";  
   
   for ( i = 0; i < 2; i++ ) {  
    unsigned     s;  
 #ifdef ALLKEY  
    if ( fixedSaltChar[0] != '\0' ) {  
     saltChar[i] = fixedSaltChar[i];  
     for ( s = 0; s2c[s] != '\0' && s2c[s] != saltChar[i]; s++ )  
      ;  
         assert( s2c[s] != '\0' );  
    } else {  
     s = rand() % 64;  
     saltChar[i] = s2c[s];  
    }  
 #else /* ALLKEY */  
    s = k[1 + i] & 255;  
    if (s > 'z')  
     s = 0;  
    else if (s >= 'a')  
     s = s - 'a' + 2 + 10 + 26;  
    else if (s >= 'A')  
     s = s - 'A' + 2 + 10;  
    else if (s >= '.')  
     s = s - '.';  
    else  
     s = 0;  
 #ifdef OTAKU  
 {  
    unsigned s2;  
    do {  
     s2 = rand() % 64;  
    } while ( s == s2 );  
    s = s2;  
 }  
 #endif /* OTAKU */  
    saltChar[i] = s2c[s];  
 #endif /* ALLKEY */  
   
    for ( j = 0; j < 6; j++ ) {  
     if ( s & (1 << j) ) {  
      LSALT( desc, code, 0, i, j,  0 ) = sizeof(WS_T) * (((4*i+j+15) & 31) - 16);  
      LSALT( desc, code, 0, i, j, 24 ) = sizeof(WS_T) * (((4*i+j- 1) & 31) - 16);  
     } else {  
      LSALT( desc, code, 0, i, j,  0 ) = sizeof(WS_T) * (((4*i+j- 1) & 31) - 16);  
      LSALT( desc, code, 0, i, j, 24 ) = sizeof(WS_T) * (((4*i+j+15) & 31) - 16);  
     }  
     LSALT( desc, code, 0, i, j, 12 ) = sizeof(WS_T) * (((4*i+j+ 7) & 31) - 16);  
     LSALT( desc, code, 0, i, j, 36 ) = sizeof(WS_T) * (((4*i+j+23) & 31) - 16);  
    }  
   }  
 }  
49    
50  #define USEC_SEC 1000   /* 1秒 */  #define USEC_SEC 1000   /* 1秒 */
51    
# Line 661  usec(void) Line 70  usec(void)
70    return (uint64_t)USEC_SEC * sec + msec;    return (uint64_t)USEC_SEC * sec + msec;
71  }  }
72    
 static  
 int  
 log_printf(FILE *ofp, char const *fmt, ...)  
 {  
   int r;  
   va_list ap;  
   va_start(ap, fmt);  
   
   if ( ofp != nfp ) {  
    vfprintf(stdout, fmt, ap);  
   }  
   
   r = vfprintf(ofp, fmt, ap);  
   va_end(ap);  
 #ifdef HITEXIT  
   exit( 0 );  
 #endif /* HITEXIT */  
   if (r > 0)  
         return r;  
   perror("log_printf");  
   exit(errno);  
 }  
   
 static  
 void  
 hit( fp, hash, key, kk, k, kind, dotrans )  
 FILE    *fp;  
 char    *hash;  
 uint8_t *key;  
 int     kk;  
 int     k;  
 unsigned char   *kind;  
 int     dotrans;  
 {  
   struct timeb  tb;  
   struct tm     *plt;  
   int   namaKey;  
   uint8_t       buf[32];  
   
   ftime( &tb );  
   plt = localtime( &tb.time );  
   
   memcpy( buf, key, 8 );  
   buf[8] = buf[9] = 0;  
   buf[7] = (buf[7] & -(1 << N_STRIDE) & 0x7F) + ALU_BITS * kk + k;  
   
   namaKey = MAKAI_TRUE;  
 #ifndef NAMA  
   if ( dotrans ) {  
    if ( translate( buf, 0, 1 ) ) {  
     namaKey = MAKAI_FALSE;  
    }  
   }  
 #endif /* NAMA */  
   
   if ( namaKey ) {  
    log_printf( fp, "◆%s ##%02x%02x%02x%02x%02x%02x%02x%02x%c%c"  
                "\t%04d/%02d/%02d %02d:%02d:%02d.%03d"  
                " %s 生\n",  
                hash,  
                buf[0], buf[1], buf[2], buf[3],  
                buf[4], buf[5], buf[6], buf[7],  
                saltChar[0], saltChar[1],  
                plt->tm_year + 1900, plt->tm_mon + 1, plt->tm_mday,  
                plt->tm_hour, plt->tm_min, plt->tm_sec, tb.millitm,  
                kind );  
   } else {  
    log_printf( fp, "◆%s #%s"  
                "\t%04d/%02d/%02d %02d:%02d:%02d.%03d"  
                "\t(%02X %02X %02X %02X %02X %02X %02X %02X/%02X)"  
                " %s\n",  
                hash,  
                buf,  
                plt->tm_year + 1900, plt->tm_mon + 1, plt->tm_mday,  
                plt->tm_hour, plt->tm_min, plt->tm_sec, tb.millitm,  
                buf[0], buf[1], buf[2], buf[3], buf[4],  
                buf[5], buf[6], buf[7], buf[8],  
                kind );  
   }  
 }  
   
73  /***************************************************************  /***************************************************************
74   *   *
75   *      CPU capabilities を取得   *      CPU capabilities を取得
# Line 852  packet_create(int n,   /* パケット数 */ Line 180  packet_create(int n,   /* パケット数 */
180   *   *
181   */   */
182    
 #define NQ_CRYPT        64  
 #define NQ_CMP          32  
   
183  #if defined(__GNUC__)  #if defined(__GNUC__)
184    
185  typedef int32_t ATOMWORD_T;  typedef int32_t ATOMWORD_T;
# Line 905  typedef DWORD THREAD_TIMEOUT_T; Line 230  typedef DWORD THREAD_TIMEOUT_T;
230  #define THREAD_INFINITE INFINITE  #define THREAD_INFINITE INFINITE
231    
232  typedef HANDLE THREAD_TH_T;  typedef HANDLE THREAD_TH_T;
 typedef HANDLE THREAD_EV_T;  
233    
234  #define thread_sleep(n) Sleep(n)  #define thread_sleep(n) Sleep(n)
235  #define thread_create(th, proc, arg) {(th) = (HANDLE)_beginthread(proc, 8192, arg);}  #define thread_create(th, proc, arg) {(th) = (HANDLE)_beginthread(proc, 8192, arg);}
 #define thread_create_event(ev, f) {(ev) = CreateEvent(NULL, TRUE, f, NULL);}  
 #define thread_signal_event(ev) SetEvent(ev)  
 #define thread_clear_event(ev) ResetEvent(ev)  
236  #define thread_get_tid()        GetCurrentThread()  #define thread_get_tid()        GetCurrentThread()
237  #define thread_set_priority(tid,n)      SetThreadPriority(tid, n)  #define thread_set_priority(tid,n)      SetThreadPriority(tid, n)
 #if 0  
 #undef thread_set_priority  
 #endif  
238  #define thread_set_affinity(tid,m)      SetThreadAffinityMask(tid, (DWORD_PTR)1 << (m))  #define thread_set_affinity(tid,m)      SetThreadAffinityMask(tid, (DWORD_PTR)1 << (m))
239    
240  static  #elif defined(_POSIX_SOURCE)
 int  
 thread_wait_event(THREAD_EV_T ev, DWORD tmo)  
 {  
   DWORD r = WaitForSingleObject(ev, tmo);  
   return (r < 0  
                   ? r  
                   : (r == WAIT_TIMEOUT  
                          ? -1  
                          : r));  
 }  
   
 #elif defined(_POSIX_SOURCE)  || defined(__FreeBSD__)  
241    
242  #include <pthread.h>  #include <pthread.h>
243  #include <unistd.h>  #include <unistd.h>
# Line 949  typedef int THREAD_TIMEOUT_T; Line 255  typedef int THREAD_TIMEOUT_T;
255  #define THREAD_PRIORITY_IDLE    16  #define THREAD_PRIORITY_IDLE    16
256    
257  typedef pthread_t THREAD_TH_T;  typedef pthread_t THREAD_TH_T;
 typedef struct  
 {  
   pthread_mutex_t       m;  
   pthread_cond_t        c;  
   int volatile          f;  
 } THREAD_EV_T;  
258    
259  #define thread_sleep(n) (usleep(1000 * (n)) != EINVAL || sleep((n) / 1000))  #define thread_sleep(n) (usleep(1000 * (n)) != EINVAL || sleep((n) / 1000))
260  #define thread_create(th, proc, arg) thread_create_p(&(th), proc, arg)  #define thread_create(th, proc, arg) thread_create_p(&(th), proc, arg)
 #define thread_create_event(ev, f) thread_create_event_p(&(ev), f)  
 #define thread_signal_event(ev) thread_set_event_p(&(ev), 1)  
 #define thread_clear_event(ev) thread_set_event_p(&(ev), 0)  
 #define thread_wait_event(ev,tmo) thread_wait_event_p(&(ev), tmo)  
261    
262  static  static
263  void  void
# Line 970  thread_create_p(pthread_t *th, NORETURN Line 266  thread_create_p(pthread_t *th, NORETURN
266    pthread_create(th, NULL, (void *(*)(void *))proc, param);    pthread_create(th, NULL, (void *(*)(void *))proc, param);
267  }  }
268    
 static  
 void  
 thread_create_event_p(THREAD_EV_T *ev, int f)  
 {  
   ev->f = f;  
   pthread_cond_init(&ev->c, NULL);  
   pthread_mutex_init(&ev->m, NULL);  
 }  
   
 static  
 void  
 thread_set_event_p(THREAD_EV_T *ev, int f)  
 {  
   pthread_mutex_lock(&ev->m);  
   if (ev->f != f)  
         {  
           ev->f = f;  
           pthread_cond_broadcast(&ev->c);  
         }  
   pthread_mutex_unlock(&ev->m);  
 }  
   
 static  
 int  
 thread_wait_event_p(THREAD_EV_T *ev, int a_tmo)  
 {  
   int timeout = a_tmo;  
   struct timeval now;  
   struct timespec tmo;  
   int r;  
   
   pthread_mutex_lock(&ev->m);  
   
   /* 現在時刻からタイムアウト時刻を求める  
          めんどくせー */  
   gettimeofday(&now, NULL);  
   tmo.tv_sec = now.tv_sec + (timeout / 1000);  
   timeout %= 1000;  
   timeout *= 1000;  
   if (now.tv_usec >= 1000000 - timeout)  
         {  
           timeout -= 1000000;  
           tmo.tv_sec++;  
         }  
   tmo.tv_nsec = 1000 * (now.tv_usec + timeout);  
   r = 0;  
   while (!ev->f)  
         {  
           r = pthread_cond_timedwait(&ev->c, &ev->m, &tmo);  
           if (r == ETIMEDOUT  
                   && a_tmo < THREAD_INFINITE)  
                 break;  
         }  
   
   pthread_mutex_unlock(&ev->m);  
   
   return (r == ETIMEDOUT  
                   ? (ETIMEDOUT < 0 ? ETIMEDOUT : -1)  
                   : 0);  
 }  
   
269  #if defined(__linux__)  #if defined(__linux__)
270    
271  /* デフォルトスケジューリングポリシーでは  /* デフォルトスケジューリングポリシーでは
# Line 1065  struct THREAD_PARAM Line 300  struct THREAD_PARAM
300  {  {
301    /* 以下は共通情報のコピー */    /* 以下は共通情報のコピー */
302    CODE_T *code;    CODE_T *code;
303    THREAD_EV_T *p_ev_ks_activated;    off_t code_cmp;
304    ATOMWORD_T volatile *p_nidle;         /* 待ちに入ったら増加 */    unsigned seed;
305    
306    /* 以下はスレッド固有 */    /* 以下はスレッド固有 */
307  #ifdef thread_set_priority  #ifdef thread_set_priority
   THREAD_TH_T th;  
308    int pri;    int pri;
309  #endif  #endif
310  };  };
311    
312  static  static
 volatile ATOMWORD_T wp_crypt, rp_crypt;  
 static  
 struct PACKET_CRYPT64 *volatile q_crypt[NQ_CRYPT];  
   
 static  
 volatile ATOMWORD_T wp_cmp, rp_cmp;  
 static  
 struct PACKET_CRYPT64 *volatile q_cmp[NQ_CMP];  
   
 static  
313  uint64_t  uint64_t
314  thread_avail(void)  thread_avail(void)
315  {  {
# Line 1107  thread_avail(void) Line 331  thread_avail(void)
331                   (unsigned)mask,                   (unsigned)mask,
332                   (unsigned)mask_s);                   (unsigned)mask_s);
333  #endif  #endif
 /* todo WIN32 でないときの n 倍表示 */  
334    if (popcnt64(mask_s) == 1)    if (popcnt64(mask_s) == 1)
335          /* 何も言うまい */;          /* 何も言うまい */;
336    else if (mask == mask_s)    else if (mask == mask_s)
# Line 1133  thread_avail(void) Line 356  thread_avail(void)
356            m |= 1ULL << i;            m |= 1ULL << i;
357    
358    return m;    return m;
   
 #elif defined( __FreeBSD__ )  
   
 #include <sys/sysctl.h>  
   
   int   i;  
   uint64_t m;  
   int nCPU;  
   int mib[2];  
   size_t len;  
   
   mib[0] = CTL_HW;  
   mib[1] = HW_NCPU;  
   len = sizeof( nCPU );  
   sysctl( mib, 2, &nCPU, &len, NULL, 0 );  
   m = (1ULL << nCPU) - 1;  
   
   return m;  
   
 #elif defined( __sun__ )  
   
 #include <sys/unistd.h>  
 #include <sys/processor.h>  
   
   uint64_t m;  
   processorid_t i, cpuid_max;  
   
   m = 0;  
   cpuid_max = sysconf( _SC_CPUID_MAX );  
   for ( i = 0; i <= cpuid_max; i++ ) {  
    if ( p_online( i, P_STATUS ) == P_ONLINE ) {  
     m |= 1ULL << i;  
    }  
   }  
   
   return m;  
   
359  #else  #else
360    
361    /* XXX プロセッサ数を調べ上げてください */    /* XXX プロセッサ数を調べ上げてください */
# Line 1180  thread_avail(void) Line 366  thread_avail(void)
366    
367  static  static
368  NORETURN  NORETURN
369  thread_crypt64(void *a_param)  thread_crypt64_new(void *a_param)
370  {  {
371    struct THREAD_PARAM *param = a_param;          struct THREAD_PARAM *param = a_param;
372    CODE_T *code = param->code;          CODE_T *code = param->code;
373    struct PACKET_CRYPT64 *pkt;          CODE_T *cmp = code + param->code_cmp;
374  #ifdef thread_set_priority          struct KS_KEY key;
375    THREAD_TH_T th = thread_get_tid();          struct PACKET_CRYPT64 *pkt = packet_create(16, 1024, key.key);
376    thread_set_priority(th, param->pri);          uint64_t *ploop;
377  #endif          THREAD_TH_T th = thread_get_tid();
378    
379    for(;;)          WaitForSingleObject(mutex_key, INFINITE);
380          {  
381            ATOMWORD_T rp;          ploop = &loop_cpu[n_cpus++];
382            ATOMWORD_T wp;  
383            srand(usec() ^ param->seed ^ (unsigned)th);
384            key_init(&key);
385            ReleaseMutex(mutex_key);
386    
           /* キューから要求を取り出す */  
           for (;;)  
                 {  
                   while ((rp = rp_crypt,  
                                   WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp, NQ_CRYPT)  
                                   /*|| q_crypt[WRAP(rp, NQ_CRYPT)] == NULL*/))  
                         {  
                           THREAD_TIMEOUT_T tmo = (WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp, NQ_CRYPT)  
                                                                           ? THREAD_INFINITE  
                                                                           : 1);  
                           int r;  
   
                           /* 寝た */  
                           if (tmo == THREAD_INFINITE)  
                                 {  
                                   LOCK_INC(param->p_nidle);  
                                 }  
   
                           /* 要求待ち */  
                           r = thread_wait_event(*param->p_ev_ks_activated, tmo);  
   
                           if (tmo == THREAD_INFINITE)  
                                 {  
                                   /* 起こされた */  
                                   LOCK_DEC(param->p_nidle);  
                                 }  
                           else if (r >= 0)  
                                 {  
                                   /* もうちょっと寝てみる */  
                                   thread_sleep(tmo);  
                                 }  
   
                           /* 自らの優先度を戻す  
                                  (外からブーストされてるかも) */  
387  #ifdef thread_set_priority  #ifdef thread_set_priority
388                            if (r >= 0)          thread_set_priority(th, param->pri);
                                 thread_set_priority(th, param->pri);  
389  #endif  #endif
                         }  
   
                   if (LOCK_CAS(&rp_crypt, rp + 1, rp) != rp)  
                         continue;  
                   rp = WRAP(rp, NQ_CRYPT);  
                   break;  
                 }  
   
           pkt = q_crypt[rp];  
           assert(pkt != NULL);  
           pkt = LOCK_CASP(&q_crypt[rp], NULL, pkt);  
           assert(pkt != NULL);  
   
           /* 実行してみる */  
           CALL_CRYPT64(code, &pkt->key64, &pkt->param64);  
390    
391            /* 結果をキューにたたき込む */          for (;;)
392            for (;;)          {
393                    do
394                  {                  {
395                    while ((wp = wp_cmp,                          int j;
396                                    WRAP(rp_cmp - 1, NQ_CMP) == WRAP(wp, NQ_CMP))                          for (j = 0; j < 8; j++)
                                  || q_cmp[WRAP(wp, NQ_CMP)] != NULL)  
397                          {                          {
398  #if DEBUG>=1                                  key_set64(&pkt->key64, j, key.key[j], key.key[j] ^ pkt->uk.key[j], 0);
399                            fprintf(stderr,                                  pkt->uk.key[j] = key.key[j];
                                           "q_cmp stalled(%d,%d) %p\n",  
                                           (unsigned)WRAP(wp, NQ_CMP),  
                                           (unsigned)WRAP(rp_cmp - 1, NQ_CMP),  
                                           q_cmp[WRAP(wp, NQ_CMP)]);  
 #endif  
                           thread_sleep(1);  
400                          }                          }
401                            CALL_CRYPT64(code,
402                    if (LOCK_CAS(&wp_cmp, wp + 1, wp) != wp)                                                   &pkt->key64,
403                          continue;                                                   &pkt->param64);
404                    wp = WRAP(wp, NQ_CMP);                          CALL_CMP64(cmp,
405                    break;                                             pkt->param64.hit,
406                                               pkt->param64.lr);
407                            check_hit(pkt, pkt->param64.hit);
408                            *ploop += N_ALU * ALU_BITS;
409                  }                  }
410                    while (key_inc(&key, 6, 8) || key_inc(&key, KEY_SHUFFLE_POS, 8));
411    
412            pkt = LOCK_CASP(&q_cmp[wp], pkt, NULL);                  WaitForSingleObject(mutex_key, INFINITE);
413            assert(pkt == NULL);                  key_reset(&key, 0);
414                    ReleaseMutex(mutex_key);
415          }          }
 }  
   
 char  
 *bname( char *path )  
 {  
   char  *p;  
416    
417  #ifdef OLDEBUG          /* notreached */
   printf( "path <%s>\n", path );  
 #endif /* DEBUG */  
   
   for ( p = path; *p != '\0'; p++ )  
    ;  
   while ( *p != '/' && *p != '\\' && p != path ) {  
    if ( *p == '.' ) {  
     *p = '\0';  
    }  
    p--;  
   }  
   if ( p != path ) {  
    p++;  
   }  
   
 #ifdef OLDEBUG  
   printf( "p <%s>\n", p );  
 #endif /* DEBUG */  
   
   return( p );  
 }  
   
 void  
 usage( path )  
 char    *path;  
 {  
   char  *myName;  
   
   myName = bname( path );  
 #ifdef ALLKEY  
   printf( "%s [-t num] [-m mask] [-s num] [-g num] [-k salt] [-v] [\"str\"]\n", myName );  
 #else /* ALLKEY */  
   printf( "%s [-t num] [-m mask] [-s num] [-g num] [-v] [\"str\"]\n", myName );  
 #endif /* ALLKEY */  
   printf( " -t num : 検索スレッド数 ( %d ≦ num ≦ %d )\n",  
            MIN_THREAD, MAX_THREAD );  
   printf( " -m mask : 実行する CPU を指定するマスク ( 1 ビット ≦ mask のビット数 ≦ %d ビット )\n",  
           MAX_THREAD );  
   printf( " -s num : 乱数の種 ( 1 ≦ num ≦ %u )\n", UINT_MAX );  
   printf( " -g num : がんばりぐあい ( %d (やる気なし) ≦ num ≦ %d (フルパワー), デフォルトは、%d )\n", MIN_GEAR, MAX_GEAR, DEF_GEAR );  
 #ifdef ALLKEY  
   printf( " -k salt : 塩を指定\n" );  
 #endif /* ALLKEY */  
   printf( " -v : 冗長メッセージ\n" );  
   printf( " str : 先頭に埋め込む文字列 ( %d ≦ str のバイト数 ≦ %d )\n",  
            MIN_UME, MAX_UME );  
 }  
   
 /* ヒット時には出力ファイルへのポインタを返す */  
 FILE *  
 checkSpecial( trip, kind )  
 char    *trip;  
 unsigned char   *kind;  
 {  
   if ( special & ST_CHIN ) {  
    /* ^Chi(r */  
    if ( trip[0] == 'C' && trip[1] == 'h' && trip[2] == 'i' &&  
         trip[3] == 'n' && trip[4] == 'k' && trip[5] == 'o' ) {  
     strcpy( kind, "ち" );  
     return( cfp );  
    }  
   }  
   
   if ( special & ST_BUOO ) {  
    /* ぶお [A-Za-z]aoo[A-Za-z]uoo$ */  
    if ( trip[3] == 'a' && trip[4] == 'o' && trip[5] == 'o' &&  
         trip[7] == 'u' && trip[8] == 'o' && trip[9] == 'o' &&  
         isalpha( trip[2] ) && isalpha( trip[6] ) ) {  
     strcpy( kind, "ぶ" );  
     return( tfp );  
    }  
   }  
   
   if ( special & ST_EROI ) {  
    int  i;  
    /* エロい人型二構 その 1 looooloooo */  
    if ( trip[0] == trip[5] &&  
         trip[1] == trip[2] && trip[1] == trip[3] && trip[1] == trip[4] &&  
         trip[1] == trip[6] && trip[1] == trip[7] && trip[1] == trip[8] &&  
         trip[1] == trip[9] ) {  
     strcpy( kind, "エ" );  
     return( tfp );  
    }  
    /* エロい人型二構 その 2 [./] */  
    for ( i = 0; i < TRIP_LEN; i++ ) {  
     if ( trip[i] != '.' && trip[i] != '/' ) {  
      goto NOEROI;  
     }  
    }  
    strcpy( kind, "エ" );  
    return( tfp );  
   }  
   NOEROI:  
   
   if ( special & ST_NIKO ) {  
    /* 二構 */  
    int  i;  
    char ch1, ch2;  
    ch1 = trip[0];  
    for ( i = 1; i < TRIP_LEN; i++ ) {  
     if ( trip[i] != ch1 ) break;  
    }  
    ch2 = trip[i];  
    for ( ; i < TRIP_LEN; i++ ) {  
     if ( trip[i] != ch1 && trip[i] != ch2 ) goto NONIKO;  
    }  
    strcpy( kind, "二" );  
    return( tfp );  
   }  
   NONIKO:  
   
   if ( special & ST_YAKU ) {  
    /* 八雲 */  
    if ( trip[0] == trip[1] && trip[0] == trip[2] &&  
         trip[3] == trip[4] && trip[3] == trip[5] &&  
         trip[6] == trip[7] && trip[6] == trip[8] && trip[9] == '.' ) {  
     strcpy( kind, "八" );  
     return( tfp );  
    }  
   }  
   
   /* 飛連関連のコードは、セロリン ◆Celeron/rc 作 */  
   if ( special & ST_HREN ) {  
    /* 飛連 */  
    int  w, x = 0, y = 0;  
    for ( w = 0; w < TRIP_LEN; w++ ) {  
     if ( trip[w] == trip[0] ) x += 1;  
     if ( trip[w] == trip[1] ) y += 1;  
     if ( x >= 8 || y >= 8 ) {  
      strcpy( kind, "飛" );  
      return( tfp );  
     }  
    }  
   }  
   
   if ( special & ST_ALLN ) {  
    /* 全数 か 怒数 */  
    if ( isdigit( trip[0] ) && isdigit( trip[1] ) && isdigit( trip[2] ) &&  
         isdigit( trip[3] ) && isdigit( trip[4] ) && isdigit( trip[5] ) &&  
         isdigit( trip[6] ) && isdigit( trip[7] ) && isdigit( trip[8] ) &&  
         isdigit( trip[9] ) ) {  
     if ( special & ST_DOSU ) {  
      /* 全数 & 回文 */  
      if ( trip[0] == trip[9] && trip[1] == trip[8] && trip[2] == trip[7] &&  
           trip[3] == trip[6] && trip[4] == trip[5] ) {  
       strcpy( kind, "怒" );  
       return( tfp );  
      }  
      /* 全数 & 双連 */  
      if ( trip[0] == trip[1] && trip[2] == trip[3] && trip[4] == trip[5] &&  
           trip[6] == trip[7] && trip[8] == trip[9] ) {  
       strcpy( kind, "怒" );  
       return( tfp );  
      }  
      /* 全数 & 山彦 */  
      if ( trip[0] == trip[5] && trip[1] == trip[6] && trip[2] == trip[7] &&  
           trip[3] == trip[8] && trip[4] == trip[9] ) {  
       strcpy( kind, "怒" );  
       return( tfp );  
      }  
      /* 最大と最小は、純 8 連で出るので削除 */  
     } else {  
      strcpy( kind, "数" );  
      return( nfp );  
     }  
    }  
   }  
   
   return( NULL );  
418  }  }
419    
420  /***************************************************************  /***************************************************************
# Line 1465  main(int argc, char *argv[]) Line 428  main(int argc, char *argv[])
428  {  {
429    int i;    int i;
430    int mincnt;    int mincnt;
   int nblk_hit, nblk_total;  
   int nap_hit, nap_total;  
431    CODE_T *code = NULL;    CODE_T *code = NULL;
432    off_t code_cmp;    off_t code_cmp;
   FILE *ofp;  
433    FILE *sfp;    /* scoreboard */    FILE *sfp;    /* scoreboard */
434    struct ITREE *root_expr;    struct ITREE *root_expr;
435    uint64_t proc_mask;    uint64_t proc_mask;
   int ks_activated;  
   static THREAD_EV_T event_ks_activated;  
   static ATOMWORD_T volatile nidle;  
436    struct THREAD_PARAM *threads = NULL;    struct THREAD_PARAM *threads = NULL;
437    int nthreads;    int nthreads;
   int npkts;  
   struct PACKET_CRYPT64 *pkts, *pkt_hit;  
   uint64_t pkts_vacant;  
438    int tn;    int tn;
439    int cr;    int cr;
440    
441    /* 鍵文字列 */    /* 鍵文字列 */
442    uint8_t key[8 + 8];    struct KS_KEY key;
   
   int xhash_loaded;  
   
 #if defined(WIN32)  
 #define YOUSUMI 6  
   int   maxSpeed; /* 一秒間に検索した個数の最大値 (YOUSUMI 回計測中) */  
   int   sCnt; /* 速度を表示した回数 */  
   int   lCntMax; /* Sleep() のためのループ最大値 */  
   int   lCnt; /* Sleep() のためのループカウンタ */  
 #endif /* WIN32 */  
443    
444  #define UPDATE_INTERVAL 8       /* 速度表示の間隔 秒 */  #define UPDATE_INTERVAL 8       /* 速度表示の間隔 秒 */
445    struct status {    struct status {
# Line 1506  main(int argc, char *argv[]) Line 450  main(int argc, char *argv[])
450    } status;    } status;
451    uint64_t curTime;    uint64_t curTime;
452    uint32_t upd_int = 0;    uint32_t upd_int = 0;
453    /*
454     平均速度 (trips/s) * UPDATE_INTERVAL が UINT32_MAX を超えると発狂する。
455     UINT32_MAX = 4294967295, 平均速度 = 100Mtrips/s なら、
456     4294967295 / (100 * 1000 * 1000) = 42.949 秒まで。(和良
457     LOOP_FACTOR が平均速度より十分小さければ、ほぼ指定間隔になる。
458     LOOP_FACTOR * UINT32_MAX + LOOP_FACOTR 個検索するとオーバーフローする。w
459     */
460    
461  #if defined(WIN32)    if (!cpuid_issupported())
462    SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );          {
463    maxSpeed = 0;            fprintf(stderr, "この環境で走らせることが想定されていません。\n");
464    sCnt = 0;            exit(1);
465    lCntMax = 0;          }
   lCnt = 0;  
 #endif  
466    
467  {    assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
   int   optChar;  
   extern char   *optarg;  
   extern int    optind;  
   char  *chPtr;  
   
   nThread = 0;  
   pmask = 0;  
   seed = 0;  
   seedOffset = 0; /* コマンドラインオプションではないが、ここで初期化 */  
   verbose = 0;  
   gear = DEF_GEAR;  
 #ifdef ALLKEY  
   fixedSaltChar[0] = '\0';  
   while ( (optChar = getopt(argc, argv, "t:m:s:g:k:vh")) != EOF ) {  
 #else /* ALLKEY */  
   while ( (optChar = getopt(argc, argv, "t:m:s:g:vh")) != EOF ) {  
 #endif /* ALLKEY */  
    switch ( optChar ) {  
     case 't':  
      nThread = atoi( optarg );  
      if ( nThread < MIN_THREAD || nThread > MAX_THREAD ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      break;  
     case 'm':  
      if ( strlen( optarg ) > MAX_THREAD ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      for ( chPtr = optarg; *chPtr != '\0'; chPtr++ ) {  
       pmask <<= 1;  
       switch ( *chPtr ) {  
        case '0':  
         /* なにもしない */  
         break;  
        case '1':  
         pmask |= 1;  
         break;  
        default:  
         usage( argv[0] );  
         exit( 1 );  
         break;  
       }  
      }  
      if ( pmask < MIN_THREAD ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      break;  
     case 's':  
      if ( optarg[0] == '-' ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      seed = (unsigned int)atoi( optarg );  
      if ( seed < 1 || seed > UINT_MAX ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      break;  
     case 'g':  
      gear = atoi( optarg );  
      if ( gear < MIN_GEAR || gear > MAX_GEAR ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      break;  
 #ifdef ALLKEY  
     case 'k':  
      if ( strlen( optarg ) != 2 ) {  
       usage( argv[0] );  
       exit( 1 );  
      }  
      for ( i = 0; i < 2; i++ ) {  
       if ( !isdigit( optarg[i] ) && !isalpha( optarg[i] ) &&  
            optarg[i] != '.' && optarg[i] != '/' ) {  
        usage( argv[0] );  
        exit( 1 );  
       }  
       fixedSaltChar[i] = optarg[i];  
      }  
      break;  
 #endif /* ALLKEY */  
     case 'v':  
      verbose = 1;  
      break;  
     case 'h':  
      usage( argv[0] );  
      exit( 0 );  
      break;  
     default:  
      usage( argv[0] );  
      exit( 1 );  
    }  
   }  
   
   switch ( argc - optind ) {  
    case 0:  
     umeStr[0] = '\0';  
     umeLen = KEY_SHUFFLE_POS;  
     break;  
    case 1:  
     strcpy( umeStr, argv[optind] );  
     umeLen = strlen( umeStr );  
     if ( umeLen < MIN_UME || umeLen > MAX_UME ) {  
      usage( argv[0] );  
      exit( 1 );  
     }  
     break;  
    default:  
     usage( argv[0] );  
     exit( 1 );  
   }  
 }  
 #ifdef REON  
   regExpStr[0] = '\0';  
 #endif /* REON */  
   
 #ifdef NAMA  
   fprintf(stderr, "生キーバージョン\n");  
   fprintf(stderr, "万が一、トリップが化けた場合、\n");  
   fprintf(stderr, "http://trip.is-a-geek.net/test/read.cgi/ra8bbs/1217089930/\n");  
   fprintf(stderr, "に報告すると次のバージョンで改善されるかも。\n\n");  
 #endif /* NAMA */  
   
 #ifdef MAKEY  
   fprintf(stderr, "魔キー空間バージョンにつき、シロウトにはおすすめできない。\n\n");  
 #endif /* MAKEY */  
   
 #ifdef ALLKEY  
   fprintf(stderr, "真・全空間バージョンにつき、シロウトにはおすすめできない。\n\n");  
 #endif /* MAKEY */  
   
   if ( !cpuid_issupported() ) {  
    fprintf( stderr, "この環境で走らせることが想定されていません。\n" );  
    exit( 1 );  
   }  
468    
469    assert( (1 << N_STRIDE) == N_ALU * ALU_BITS );    mutex_key = CreateMutex(NULL, FALSE, NULL);
470    
471    /* タゲ読み込み */    /* タゲ読み込み */
472    root_expr = expr_parse( "target.txt" );    root_expr = expr_parse("target.txt");
   
   if ( verbose ) {  
    printf( "特殊検索オプション : " );  
    if ( special & ST_DOSU ) {  
     printf( "怒数 " );  
    } else {  
     if ( special & ST_ALLN ) {  
      printf( "全数 " );  
     }  
    }  
    if ( special & ST_EROI ) {  
     printf( "エロ " );  
    }  
    if ( special & ST_NIKO ) {  
     printf( "二構 " );  
    }  
    if ( special & ST_BUOO ) {  
     printf( "ぶお " );  
    }  
    if ( special & ST_CHIN ) {  
     printf( "ちん " );  
    }  
    if ( special & ST_HREN ) {  
     printf( "飛連 " );  
    }  
    if ( special & ST_YAKU ) {  
     printf( "八雲 " );  
    }  
    if ( special ) {  
     printf( "オン!\n" );  
    } else {  
     printf( "オールオフ!\n" );  
    }  
    if ( seedOffset != 0 ) {  
     printf( "乱数の種のオフセット = %d\n", seedOffset );  
    }  
 #ifdef REON  
    if ( regExpStr[0] != '\0' ) {  
     printf( "正規表現 : %s\n", regExpStr );  
    }  
 #endif /* REON */  
    if ( gear != DEF_GEAR ) {  
     printf( "がんばりぐあい : %d\n", gear );  
    }  
 #ifdef KEYLOG  
    if ( keyLog == MAKAI_TRUE ) {  
     printf( "検索したキー空間のロギング\n" );  
    }  
 #endif /* KEYLOG */  
   }  
473    
474    /* コードを生成・展開    /* コードを生成・展開
475           起動予定スレッド数に応じて           起動予定スレッド数に応じて
476           生成するコードを変える */           生成するコードを変える */
477    sfp = scoreboard_open();    sfp = scoreboard_open();
478    /* prologue & コアループ */    fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp);     /* prologue & コアループ */
479    fwrite( crypt64_descs[0]->pro, 1,    proc_mask = thread_avail();
           crypt64_descs[0]->cmp_pro - crypt64_descs[0]->pro, sfp );  
   
    /* proc_mask に使用する CPU のマスクをセット */  
   if ( pmask == 0 ) {  
    /* 指定がなければ、使える CPU 全部 */  
    proc_mask = thread_avail();  
   } else {  
    /* 指定された CPU の存在チェック。だが、今は Win32 のコードしかない。 */  
 #ifdef WIN32  
    DWORD_PTR    processMask, systemMask;  
    if ( GetProcessAffinityMask( GetCurrentProcess(), &processMask, &systemMask )  
         == 0 ) {  
     printf( "CPU の割り当てに失敗 その 1\n" );  
     exit( 1 );  
    }  
    if ( (processMask & pmask) != pmask ) {  
     printf( "そんな CPU はねぇ!\n" );  
     exit( 1 );  
    }  
 #endif /* WIN32 */  
   
    proc_mask = pmask;  
    printf( "CPU : " );  
    for ( i = 0; i < MAX_THREAD; i++ ) {  
     if ( pmask & 1 ) {  
      printf( "%d ", i );  
     }  
     pmask >>= 1;  
    }  
    printf( "を使用します。\n" );  
480    
481      /* CPU の割り当て。だが、今は Wi(r */  #if 0
482  #ifdef WIN32    if (0&&proc_mask == 1U)
483     if ( SetProcessAffinityMask( GetCurrentProcess(), proc_mask ) == 0 ) {          {
484      printf( "CPU の割り当てに失敗 その 2\n" );            /* single */
485      exit( 1 );            code_cmp = 0;
486     }          }
487  #endif /* WIN32 */    else
488    }  #endif
489            {
490    /* スレッド数の指定がない場合は、proc_mask からゲッツ */            /* multi */
491    if ( nThread == 0 ) {            fwrite(crypt64_descs[0]->ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->ep, sfp);        /* epilogue */
492     nThread = popcnt64( proc_mask );  
493    }            /* 比較器のみを生成(前半) */
494              code_cmp = ftell(sfp);
495    fprintf( stderr, "%d 個の検索スレッドを生成\n", nThread );            fseek(sfp, (-code_cmp) & 63, SEEK_CUR);
496              code_cmp = ftell(sfp);
497    if ( nThread == 1 ) {            fwrite(crypt64_descs[0]->pro, 1, crypt64_descs[0]->crypt - crypt64_descs[0]->pro, sfp);       /* prologue */
498     npkts = 1;          }
    pkts_vacant = 1;  
    code_cmp = 0;  
   } else {  
    /* epilogue */  
    fwrite( crypt64_descs[0]->ep, 1,  
            crypt64_descs[0]->ep_end - crypt64_descs[0]->ep, sfp );  
    /* 比較器のみを生成(前半) */  
    code_cmp = ftell( sfp );  
    fseek( sfp, (-code_cmp) & 63, SEEK_CUR );  
    code_cmp = ftell( sfp );  
    /* prologue */  
    fwrite( crypt64_descs[0]->pro, 1,  
            crypt64_descs[0]->crypt - crypt64_descs[0]->pro, sfp );  
    npkts = 64;  
    pkts_vacant = (uint64_t)-1;  /* (1 << 64) - 1 を計算したくない */  
   }  
499    
500    /* 比較部を生成 */    /* 比較部を生成 */
501    /* 比較器準備 */    fwrite(crypt64_descs[0]->cmp_pro, 1, crypt64_descs[0]->cmp_ep - crypt64_descs[0]->cmp_pro, sfp);      /* 比較器準備 */
502    fwrite( crypt64_descs[0]->cmp_pro, 1,    tn = synth_synthesize(sfp, root_expr);
503            crypt64_descs[0]->cmp_ep - crypt64_descs[0]->cmp_pro, sfp );    fwrite(crypt64_descs[0]->cmp_ep, 1, crypt64_descs[0]->ep_end - crypt64_descs[0]->cmp_ep, sfp);        /* epilogue */
504    tn = synth_synthesize( sfp, root_expr );  
   /* epilogue */  
   fwrite( crypt64_descs[0]->cmp_ep, 1,  
           crypt64_descs[0]->ep_end - crypt64_descs[0]->cmp_ep, sfp );  
505    /* コードをメモリに貼り付ける */    /* コードをメモリに貼り付ける */
506    code = scoreboard_map( sfp );    code = scoreboard_map(sfp);
507    
508    /* キーの初期化 */    /* キーの初期化 */
509    if ( seed == 0 ) {    WaitForSingleObject(mutex_key, INFINITE);
510     seed = (unsigned int)time( NULL ) + seedOffset;    srand(usec());
511    }    key_init(&key);
512    if ( verbose ) {    ReleaseMutex(mutex_key);
513     printf( "乱数の種 = %u\n", seed );    set_salt(code, crypt64_descs[0], key.key);
   }  
   srand( seed );  
   
 #ifdef KEYCHK  
 {  
   int   i;  
   
   for ( i = 0; i < 100000; i++ ) {  
    printf( "%02x %02x %02x %02x %02x %02x %02x %02x\n",  
            key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7] );  
    key_init( key );  
   }  
   exit( 0 );  
 }  
 #endif /* KEYCHK */  
514    
515    key_init( key );    if (log_open("log.txt") != 0) return 1;
   set_salt( code, crypt64_descs[0], key );  
516    
517    /* 演算パケットを作成 */    WaitForSingleObject(mutex_key, INFINITE);
   pkts = packet_create( npkts, tn, key );  
   pkt_hit = &pkts[npkts - 1];  
518    
519    /* 働くおじさんを量産 */    /* 働くおじさんを量産 */
   thread_create_event( event_ks_activated, 1 );  
   ks_activated = 1;  
520    nthreads = 0;    nthreads = 0;
521    if ( code_cmp ) {    if (code_cmp)
522     THREAD_TH_T h;          {
523     int ots = -1;            THREAD_TH_T h;
524     threads = calloc( 2 * nThread, sizeof(*threads) );            int ots = -1;
525     for ( i = 0; i < nThread; i++ ) {            threads = calloc(2 * popcnt64(proc_mask), sizeof(*threads));
526      if ( ots < 0 ) {            for (i = 0; i < 64; i++)
527       /* 自分自身のスケジューリング                  if (proc_mask & (1ULL << i))
528          こーゆー系のアプリは低めに設定するのが吉(かも) */                    {
529                            if (0&&ots < 0)
530                              {
531                                    /* 自分自身のスケジューリング
532                                       こーゆー系のアプリは低めに設定するのが吉(かも) */
533  #ifdef WIN32  #ifdef WIN32
534       h = GetCurrentProcess();                                  h = GetCurrentProcess();
535  /* todo 基本優先度の設定が二箇所にある */                                  SetPriorityClass(h, BELOW_NORMAL_PRIORITY_CLASS);
536       SetPriorityClass( h, BELOW_NORMAL_PRIORITY_CLASS );  #endif
537  #endif  #if defined(thread_set_priority)
538  #if defined( thread_set_priority )                                  /* 心の隙間お埋めします */
539       /* 心の隙間お埋めします */                                  threads[nthreads].code = code;
540       threads[nthreads].code = code;                                  threads[nthreads].code_cmp = code_cmp;
541       threads[nthreads].p_ev_ks_activated = &event_ks_activated;                                  threads[nthreads].seed = rand();
542       threads[nthreads].p_nidle = &nidle;                                  threads[nthreads].pri = THREAD_PRIORITY_IDLE;
543       threads[nthreads].pri = THREAD_PRIORITY_IDLE;                                  thread_create(h, thread_crypt64_new, &threads[nthreads]);
544       thread_create( h, thread_crypt64, &threads[nthreads] );                                  nthreads++;
545       threads[nthreads].th = h;  #endif
546       nthreads++;                                  if (!code_cmp)
547  #endif                                    break;
548       if ( !code_cmp ) break;  
549       /* 自分自身の残りの設定を、あとでやる */                                  /* 自分自身の残りの設定を、あとでやる */
550       ots = i;                                  ots = i;
551      } else {                            }
552       /* 他スレッドは、やや低めの優先度で。 */                          else
553       threads[nthreads].code = code;                            {
554       threads[nthreads].p_ev_ks_activated = &event_ks_activated;                                  /* 他スレッドは、やや低めの優先度で。 */
555       threads[nthreads].p_nidle = &nidle;                                  threads[nthreads].code = code;
556                                    threads[nthreads].code_cmp = code_cmp;
557                                    threads[nthreads].seed = rand();
558  #ifdef thread_set_priority  #ifdef thread_set_priority
559       threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;                                  //threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;
560                                    threads[nthreads].pri = THREAD_PRIORITY_LOWEST;
561  #endif  #endif
562       thread_create( h, thread_crypt64, &threads[nthreads] );                                  thread_create(h, thread_crypt64_new, &threads[nthreads]);
563    #ifdef thread_get_tid
564                                    thread_set_affinity(h, i);
565    #endif
566                                    nthreads++;
567    #if 1
568                                    /* IDLE */
569                                    threads[nthreads].code = code;
570                                    threads[nthreads].code_cmp = code_cmp;
571                                    threads[nthreads].seed = rand();
572  #ifdef thread_set_priority  #ifdef thread_set_priority
573       threads[nthreads].th = h;                                  threads[nthreads].pri = THREAD_PRIORITY_IDLE;
574    #endif
575                                    thread_create(h, thread_crypt64_new, &threads[nthreads]);
576    #ifdef thread_get_tid
577                                    SetThreadAffinityMask(h, proc_mask);
578    #endif
579                                    nthreads++;
580    #endif
581                              }
582                      }
583    #ifdef thread_get_tid
584              if (ots)
585                    thread_set_affinity(thread_get_tid(), ots);
586  #endif  #endif
587       nthreads++;          }
588      }  
589     }    fprintf(stderr, "検索開始!\n");
590    }    ReleaseMutex(mutex_key);
   
   if ( (ofp = fopen( "log.txt", "at" )) == NULL ) {  
    perror( "log.txt" );  
    return errno;  
   }  
   setvbuf(ofp, NULL, _IONBF, BUFSIZ);  
   
   if ( (tfp = fopen( "logspe.txt", "at" )) == NULL ) {  
    perror( "logspe.txt" );  
    return errno;  
   }  
   setvbuf( tfp, NULL, _IONBF, BUFSIZ );  
   if ( (nfp = fopen( "lognum.txt", "at" )) == NULL ) {  
    perror( "lognum.txt" );  
    return errno;  
   }  
   setvbuf( nfp, NULL, _IONBF, BUFSIZ );  
   if ( (cfp = fopen( "logchi.txt", "at" )) == NULL ) {  
    perror( "logchi.txt" );  
    return errno;  
   }  
   setvbuf( cfp, NULL, _IONBF, BUFSIZ );  
 #ifdef REON  
   if ( (rfp = fopen( "logreg.txt", "at" )) == NULL ) {  
    perror( "logreg.txt" );  
    return errno;  
   }  
   setvbuf( rfp, NULL, _IONBF, BUFSIZ );  
 #endif /* REON */  
591    
592    mincnt = 0x7FFFFFFF;    mincnt = 0x7FFFFFFF;
593    nblk_hit = nblk_total = 0;  
   nap_hit = nap_total = 0;  
594    cr = 0;    cr = 0;
595    memset( &status, 0, sizeof( struct status ) );    memset( &status, 0, sizeof( struct status ) );
596    status.startTime = status.lastTime = usec();    status.startTime = status.lastTime = usec();
597    
 #ifdef MINAST  
 #undef assert  
 #define assert(x)  
 #endif /* MINAST */  
   
 #ifdef SCTEST  
 {  
   int   i;  
   
   for ( i = 1; i < SCTEST; i++ ) {  
    key_reset( key, 0 );  
   }  
   exit( 0 );  
 }  
 #endif /* SCTEST */  
   
598    /* 探索ループだぞっと */    /* 探索ループだぞっと */
599    for ( ;; ) {    for (;;)
600     struct PACKET_CRYPT64 *pkt_c;          {
601     uint64_t cnt;            Sleep(5000);
 #if DEBUG>=1  
    int cnt1, cnt2;  
 #endif  
    int k, kk;  
602    
603     /* 比較器候補(may be NULL)            /* 速度計測 */
604        先にキューから取り出す */            status.loop = 0;
605     pkt_c = q_cmp[WRAP( rp_cmp, NQ_CMP )];            for (i = 0; i < n_cpus; i++) status.loop += loop_cpu[i];
    if ( pkt_c != NULL && WRAP( rp_cmp, NQ_CMP ) != WRAP( wp_cmp, NQ_CMP ) ) {  
     pkt_c = LOCK_CASP( &q_cmp[WRAP( rp_cmp, NQ_CMP )], NULL, pkt_c );  
     assert( pkt_c != NULL );  
     LOCK_INC( &rp_cmp );  
     /* パケットを vacant に回しておく */  
     pkts_vacant |= 1ULL << (pkt_c - pkts);  
    }  
   
    /* Saltチェンジ待ち */  
    if ( !ks_activated ) {  
     ATOMWORD_T rp;  
     if ( pkt_c == NULL ) {  
      if ( (rp = rp_crypt, WRAP( rp, NQ_CRYPT ) != WRAP( wp_crypt, NQ_CRYPT ))  
           && LOCK_CAS( &rp_crypt, rp + 1, rp ) == rp ) {  
       /* !ks_activate 状態では、自らも要求キューをやっつけにいく */  
       rp = WRAP( rp, NQ_CRYPT );  
       pkt_c = q_crypt[rp];  
       assert( pkt_c != NULL );  
       pkt_c = LOCK_CASP( &q_crypt[rp], NULL, pkt_c );  
       assert( pkt_c != NULL );  
       assert( pkt_c != pkt_hit );  
       CALL_CRYPT64( code, &pkt_c->key64, &pkt_c->param64 );  
       /* パケットを vacant に回しておく */  
       pkts_vacant |= 1ULL << (pkt_c - pkts);  
      } else {  
       /* やはりすることがないのでまったりと過ごす */  
       if ( nidle != nthreads ) thread_sleep(1);  
      }  
     }  
     if ( nidle == nthreads ) {  
      assert( WRAP( rp_crypt, NQ_CRYPT ) == WRAP( wp_crypt, NQ_CRYPT ) );  
      /* Salt チェンジが可能 */  
      set_salt( code, crypt64_descs[0], key );  
      if ( nthreads ) thread_signal_event( event_ks_activated );  
      ks_activated = 1;  
     }  
    }  
   
    /* 鍵をキューにたたき込みまくる */  
    if ( !ks_activated ) {  
     /* 鍵を登録しない */  
     ;  
    } else {  
     for ( i = npkts - 1; i >= 0; i-- ) {  
      if ( pkts_vacant & (1ULL << i) ) {  
       int j;  
       if ( i == npkts - 1 ) {  
        /* 前段で、働くおじさんから結果をもらっていたら、何もしない */  
        if ( pkt_c != NULL ) continue;  
       } else {  
        /* 前段で取り出したばかりの働くおじさんは、尊重する */  
        if ( &pkts[i] == pkt_c ) continue;  
        /* queue full の場合は見送る */  
        /* XXX 16 はてきとう */  
        if ( WRAP( wp_crypt, NQ_CRYPT ) == WRAP( rp_crypt - 16, NQ_CRYPT )  
             || q_crypt[WRAP( wp_crypt, NQ_CRYPT )] != NULL ) break;  
       }  
       /* 鍵のセット */  
       for ( j = 0; j < 8; j++ ) {  
        key_set64( &pkts[i].key64, j, key[j], key[j] ^ pkts[i].uk.key[j], 0 );  
        pkts[i].uk.key[j] = key[j];  
       }  
       if ( i == npkts - 1 ) {  
        /* 次段で CRYPT64->CMP */  
        assert(pkt_c == NULL);  
        pkt_c = &pkts[i];  
        assert( pkt_c == pkt_hit );  
       } else {  
        /* キューにたたき込む */  
        while ( LOCK_CASP( &q_crypt[WRAP( wp_crypt, NQ_CRYPT )], &pkts[i], NULL )  
                != NULL ) {  
         /* 設計上はここに来ない */  
         fprintf( stderr,  
                  "q_crypt を汚してるのは誰だ? (rp=%3d, wp=%3d, v=%08X%08X)\n",  
                  (unsigned)WRAP( rp_crypt, NQ_CRYPT ),  
                  (unsigned)WRAP( wp_crypt, NQ_CRYPT ),  
                  (unsigned)( pkts_vacant >> 32 ),  
                  (unsigned)pkts_vacant );  
         thread_sleep( 1000 );  
        }  
        LOCK_INC( &wp_crypt );  
        pkts_vacant ^= 1ULL << i;  
        assert( !(pkts_vacant & (1ULL << i)) );  /* 削れ */  
       }  
       /* 鍵増加はこんなところに移動! */  
       assert( ks_activated );  
       if ( !key_inc( key, 6 ) && !key_inc( key, umeLen ) ) {  
        /* 鍵のシャッフル q_crypt が捌けるまで、set_salt() はできない */  
 #if DEBUG>=1  
        fprintf( stderr, "********************************SHUFFLE!\n" );  
 #endif  
        if ( nthreads ) thread_clear_event( event_ks_activated );  
        key_reset( key, 0 );  
        /* キューの鍵が捌けるまでアイドル状態に */  
        ks_activated = 0;  
        /* スレッドをブーストして回る */  
 #ifdef thread_set_priority  
        for ( j = 0; j < nthreads; j++ ) {  
         assert( threads != NULL );  
         thread_set_priority( threads[j].th, THREAD_PRIORITY_NORMAL );  
        }  
 #endif  
        /* ループ続行はもはや不要 */  
        break;  
       }  
      }  
     }  
    }  
    /* することがなくなっている場合 */  
    if ( pkt_c == NULL ) {  
     assert( !ks_activated );  
     continue;  
    }  
    /* 呼ぶ!  
       LR 初期化は、サブモジュール内で行うべし  
       FASTCALL に準じた呼び出しのため、  
       ホントはいろいろレジスタが破壊されるハズ…なんだが。 */  
    if ( pkt_c != pkt_hit ) {  
     assert( code_cmp != 0 );  
     cnt = CALL_CMP64( code + code_cmp, pkt_hit->param64.hit,  
                       pkt_c->param64.lr );  
    } else {  
     /* ようやく自スレッドで回せる */  
     cnt = CALL_CRYPT64( code, &pkt_c->key64, &pkt_c->param64 );  
     if ( code_cmp ) {  
      cnt = CALL_CMP64( code + code_cmp, pkt_c->param64.hit,  
                        pkt_c->param64.lr );  
     }  
    }  
    /* ヒットしたときの処理  
       key および lr は pkt_c に合致判定は pkt_hit に入っているハズ */  
    xhash_loaded = 0;  
    for ( kk = 0; kk < N_ALU; kk++ ) {  
     ALU_T t;  
     static uint64_t xhash[64];  
     if ( special  
 #ifdef REON  
          || regExpStr[0] != '\0'  
 #endif /* REON */  
        ) {  
      CALL_TR64( &pkt_c->param64.lr[0][0].q[kk / (N_ALU / N_Q)], xhash );  
      xhash_loaded = 1;  
     }  
     if ( !(kk & (N_ALU / N_Q - 1)) ) nblk_total++, xhash_loaded = 0;  
     if ( special  
 #ifdef REON  
          || regExpStr[0] != '\0'  
 #endif /* REON */  
        ) {  
      char hash[16];  
      FILE       *lfp;  
      unsigned char      kind[3];  
      for ( k = 0; k < ALU_BITS; k++ ) {  
       for ( i = 1; i < 11; i++ ) {  
        unsigned c = 0;  
        c = (xhash[(ALU_BITS * kk + k) & 63] >> (6 * (i - 1))) & 0x3F;  
        hash[i - 1] = C64[c];  
       }  
       hash[10] = 0;  
 #ifdef REON  
       if ( regExpStr[0] != '\0' ) {  
        if ( regexec( &regExp, hash, (size_t)0, NULL, 0 ) == 0 ) {  
         if ( cr ) fprintf( stderr, "\n" );  
         cr = 0;  
 #ifdef NAMA  
         hit( rfp, hash, pkt_c->uk.key, kk, k, "正", MAKAI_FALSE );  
 #else /* NAMA */  
         hit( rfp, hash, pkt_c->uk.key, kk, k, "正", MAKAI_TRUE );  
 #endif /* NAMA */  
        }  
       }  
 #endif /* REON */  
       if ( special ) {  
        if ( (lfp = checkSpecial( hash, kind )) != NULL ) {  
         if ( cr ) fprintf( stderr, "\n" );  
         cr = 0;  
 #ifdef NAMA  
         hit( lfp, hash, pkt_c->uk.key, kk, k, kind, MAKAI_FALSE );  
 #else /* NAMA */  
         hit( lfp, hash, pkt_c->uk.key, kk, k, kind, MAKAI_TRUE );  
 #endif /* NAMA */  
        }  
       }  
      }  
     }  
   
     t = pkt_hit->param64.hit[HIT_ANY].a[kk];  
     if ( !t ) continue;  
     nap_total += ALU_BITS;  
     for ( k = 0; k < ALU_BITS; k++ ) {  
      char hash[16];  
      int        hitLen;  
      if ( !(t & ((ALU_T)1 << k)) ) continue;  
      nap_hit++;  
      /* 転置 */  
      if ( !xhash_loaded ) {  
       nblk_hit++;  
       CALL_TR64( &pkt_c->param64.lr[0][0].q[kk / (N_ALU / N_Q)], xhash );  
       xhash_loaded = 1;  
      }  
      /* 辞書を調べる */  
      hitLen = 0;  
      if ( !((pkt_hit->param64.hit[HIT_BOOL].a[kk] & ((ALU_T)1 << k))  
             || (hitLen = wdict_ishit( pkt_hit->param64.hit, kk, k,  
                                       xhash[(ALU_BITS * kk + k) & 0x3F]))) )  
       continue;  
      for ( i = 1; i < 11; i++ ) {  
       unsigned c;  
       c = (xhash[(ALU_BITS * kk + k) & 63] >> (6 * (i - 1))) & 0x3F;  
       hash[i - 1] = C64[c];  
      }  
      hash[10] = 0;  
      if ( cr ) fprintf( stderr, "\n" );  
      cr = 0;  
 {  
      unsigned char      len[10];  
 #ifdef SELF  
      static hitCount = 0;  
 #endif /* SELF */  
   
      sprintf( len, "%02d", hitLen );  
      if ( hitLen < 10 ) {  
       /* たまたま後ろに区切り文字が付いた場合、一桁目を E にする */  
       if ( hash[hitLen] == '.' || hash[hitLen] == '/' ) {  
        len[0] = 'E';  
       }  
      }  
   
 #if SEQ > 0 /* だがしかし、SEQ == 8 の場合しか考えてない */  
      /* 連モノの処理方法をちゃんと追いかけるべきだが、めんどくさいのでこれで */  
      if ( hitLen == 0 ) [  
       char      ref;  
       ref = hash[2];  
       if ( ref == hash[3] && ref == hash[4] && ref == hash[5] &&  
            ref == hash[6] && ref == hash[7] ) {  
        if ( ref == hash[0] && ref == hash[1] ) {  
         strcpy( len, "勝" );  
        }  
        if ( ref == hash[1] && ref == hash[8] ) {  
         strcpy( len, "勝" );  
        }  
        if ( ref == hash[8] && ref == hash[9] ) {  
         strcpy( len, "勝" );  
        }  
       }  
      }  
 #endif /* SEQ */  
   
 #ifdef NAMA  
      hit( ofp, hash, pkt_c->uk.key, kk, k, len, MAKAI_FALSE );  
 #else /* NAMA */  
      hit( ofp, hash, pkt_c->uk.key, kk, k, len, MAKAI_TRUE );  
 #endif /* NAMA */  
   
 #ifdef SELF  
      hitCount++;  
      if ( hitCount >= SELF_LIM_CNT ) {  
       exit( 0 );  
      }  
 #endif /* SELF */  
 }  
     }  
    }  
606    
607     /* 速度計測 */            if (status.loop >= status.lastloop + upd_int
608     status.loop += N_ALU * ALU_BITS;                    && (curTime = usec()) != status.lastTime)
609                    {
610                      uint64_t diffTime;
611                      int a, b, c;
612                      /* 通算(単位 ktrips/sec) */
613                      diffTime = curTime - status.startTime;
614                      a = status.loop / ((1000 / USEC_SEC) * diffTime);
615    
616                      /* 区間(単位 trips/sec) */
617                      diffTime = curTime - status.lastTime;
618                      b = USEC_SEC * (status.loop - status.lastloop) / diffTime;
619    
620                      /* 予測 */
621                      c = UPDATE_INTERVAL * b;
622    
623                      /* 立ち上がりなど、誤差があり upd_int が小さすぎたときは
624                             いきなり全補正せず 1 秒(==b)づつ収斂させる。 */
625                      upd_int = (upd_int + b < c
626                                             ? upd_int + b
627                                             : c);
628    
629  /* -g オプション用のコードは、Win32 用しかない */                    status.lastTime = curTime;
630  /* todo UNIX 系用コードも要るかな */                    status.lastloop = status.loop;
631  #if defined(WIN32)  #if DEBUG>=1
632     if ( sCnt >= YOUSUMI ) {                    fprintf(stderr,
633      lCnt++;                            "%5d/%5d(%3d%%)",
634      if ( lCnt > lCntMax ) {                            nblk_hit, nblk_total, 100 * nblk_hit / nblk_total);
635       Sleep( (DWORD)10 );                    nblk_hit = nblk_total = 0;
636       lCnt = 0;                    if (nap_total)
637      }                          fprintf(stderr,
638     }                                  "  %5d/%5d(%3d%%)",
639  #endif /* WIN32 */                                  nap_hit, nap_total, 100 * nap_hit / nap_total);
640                      else
641     if ( status.loop >= status.lastloop + upd_int                          fprintf(stderr,
642          && (curTime = usec()) != status.lastTime ) {                                          "  -----/-----(---%%)");
643      uint64_t diffTime;                    nap_hit = nap_total = 0;
644      int a, b, c;  #endif
645      /* 通算(単位 ktrips/sec) */                    fprintf(stderr,
646      diffTime = curTime - status.startTime;                                    "%4d.%03dMtrips/s [%4d.%06dMtrips/s]\r",
647  #ifdef SELF                                    a / 1000, a % 1000,
648      if ( diffTime >= SELF_LIM_SEC ) {                                    b / 1000000, b % 1000000);
649       exit( 0 );                    cr++;
650      }                  }
651  #endif /* SELF */          }
     a = status.loop / ((1000 / USEC_SEC) * diffTime);  
 #ifdef BENCH  
     if ( (diffTime / USEC_SEC) > (BENCH * 60) ) {  
      fprintf( stderr, "\n%6dktrips/s\n", a );  
      exit( 0 );  
     }  
 #endif /* BENCH */  
     /* 区間(単位 trips/sec) */  
     diffTime = curTime - status.lastTime;  
     b = USEC_SEC * (status.loop - status.lastloop) / diffTime;  
 #if defined(WIN32)  
     if ( gear != DEF_GEAR ) {  
      if ( sCnt < YOUSUMI ) {  
       if ( b > maxSpeed ) {  
        maxSpeed = b;  
        /* x = l/s * (gear / (10 - gear)) / 100 */  
        lCntMax = maxSpeed / (N_ALU * ALU_BITS) * (gear * 1000 / (10 - gear)) / 100000;  
        if ( lCntMax < 1 ) {  
         lCntMax = 1;  
        }  
       }  
       sCnt++;  
      }  
     }  
 #endif /* WIN32 */  
     /* 予測 */  
     c = UPDATE_INTERVAL * b;  
     /* 立ち上がりなど、誤差があり upd_int が小さすぎたときは  
        いきなり全補正せず 1 秒(==b)づつ収斂させる。 */  
     upd_int = ( upd_int + b < c ? upd_int + b : c );  
     status.lastTime = curTime;  
     status.lastloop = status.loop;  
     fprintf( stderr, "%6dktrips/s [%6d.%03dktrips/s]\r",  
              a, b / 1000, b % 1000 );  
     cr++;  
    }  
   }  
652    
653    return 0;    return 0;
654  }  }

Legend:
Removed from v.250  
changed lines
  Added in v.252

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26