| 1 | #if WIN32 |
|---|
| 2 | #include <windows.h> |
|---|
| 3 | #include <share.h> |
|---|
| 4 | #endif |
|---|
| 5 | |
|---|
| 6 | #include "muscle.h" |
|---|
| 7 | #include <stdio.h> |
|---|
| 8 | #include <stdlib.h> |
|---|
| 9 | #include <stdarg.h> |
|---|
| 10 | #include <string.h> |
|---|
| 11 | #include <math.h> |
|---|
| 12 | #include <assert.h> |
|---|
| 13 | #include <time.h> |
|---|
| 14 | #include <errno.h> |
|---|
| 15 | |
|---|
| 16 | #ifndef MAX_PATH |
|---|
| 17 | #define MAX_PATH 260 |
|---|
| 18 | #endif |
|---|
| 19 | |
|---|
| 20 | static char g_strListFileName[MAX_PATH]; |
|---|
| 21 | static bool g_bListFileAppend = false; |
|---|
| 22 | |
|---|
| 23 | static SEQWEIGHT g_SeqWeight = SEQWEIGHT_Undefined; |
|---|
| 24 | |
|---|
| 25 | void SetSeqWeightMethod(SEQWEIGHT Method) |
|---|
| 26 | { |
|---|
| 27 | g_SeqWeight = Method; |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | SEQWEIGHT GetSeqWeightMethod() |
|---|
| 31 | { |
|---|
| 32 | return g_SeqWeight; |
|---|
| 33 | } |
|---|
| 34 | |
|---|
| 35 | void SetListFileName(const char *ptrListFileName, bool bAppend) |
|---|
| 36 | { |
|---|
| 37 | assert(strlen(ptrListFileName) < MAX_PATH); |
|---|
| 38 | strcpy(g_strListFileName, ptrListFileName); |
|---|
| 39 | g_bListFileAppend = bAppend; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | void Log(const char szFormat[], ...) |
|---|
| 43 | { |
|---|
| 44 | if (0 == g_strListFileName[0]) |
|---|
| 45 | return; |
|---|
| 46 | |
|---|
| 47 | static FILE *f = NULL; |
|---|
| 48 | const char *mode; |
|---|
| 49 | if (g_bListFileAppend) |
|---|
| 50 | mode = "a"; |
|---|
| 51 | else |
|---|
| 52 | mode = "w"; |
|---|
| 53 | if (NULL == f) |
|---|
| 54 | f = _fsopen(g_strListFileName, mode, _SH_DENYNO); |
|---|
| 55 | if (NULL == f) |
|---|
| 56 | { |
|---|
| 57 | perror(g_strListFileName); |
|---|
| 58 | exit(EXIT_NotStarted); |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | char szStr[4096]; |
|---|
| 62 | va_list ArgList; |
|---|
| 63 | va_start(ArgList, szFormat); |
|---|
| 64 | vsprintf(szStr, szFormat, ArgList); |
|---|
| 65 | fprintf(f, "%s", szStr); |
|---|
| 66 | fflush(f); |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | const char *GetTimeAsStr() |
|---|
| 70 | { |
|---|
| 71 | static char szStr[32]; |
|---|
| 72 | time_t t; |
|---|
| 73 | time(&t); |
|---|
| 74 | struct tm *ptmCurrentTime = localtime(&t); |
|---|
| 75 | strcpy(szStr, asctime(ptmCurrentTime)); |
|---|
| 76 | assert('\n' == szStr[24]); |
|---|
| 77 | szStr[24] = 0; |
|---|
| 78 | return szStr; |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | // Exit immediately with error message, printf-style. |
|---|
| 82 | void Quit(const char szFormat[], ...) |
|---|
| 83 | { |
|---|
| 84 | va_list ArgList; |
|---|
| 85 | char szStr[4096]; |
|---|
| 86 | |
|---|
| 87 | va_start(ArgList, szFormat); |
|---|
| 88 | vsprintf(szStr, szFormat, ArgList); |
|---|
| 89 | |
|---|
| 90 | fprintf(stderr, "\n*** ERROR *** %s\n", szStr); |
|---|
| 91 | |
|---|
| 92 | Log("\n*** FATAL ERROR *** "); |
|---|
| 93 | Log("%s\n", szStr); |
|---|
| 94 | Log("Stopped %s\n", GetTimeAsStr()); |
|---|
| 95 | |
|---|
| 96 | #ifdef WIN32 |
|---|
| 97 | if (IsDebuggerPresent()) |
|---|
| 98 | { |
|---|
| 99 | int iBtn = MessageBox(NULL, szStr, "muscle", MB_ICONERROR | MB_OKCANCEL); |
|---|
| 100 | if (IDCANCEL == iBtn) |
|---|
| 101 | Break(); |
|---|
| 102 | } |
|---|
| 103 | #endif |
|---|
| 104 | exit(EXIT_FatalError); |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | void Warning(const char szFormat[], ...) |
|---|
| 108 | { |
|---|
| 109 | va_list ArgList; |
|---|
| 110 | char szStr[4096]; |
|---|
| 111 | |
|---|
| 112 | va_start(ArgList, szFormat); |
|---|
| 113 | vsprintf(szStr, szFormat, ArgList); |
|---|
| 114 | |
|---|
| 115 | fprintf(stderr, "\n*** WARNING *** %s\n", szStr); |
|---|
| 116 | Log("\n*** WARNING *** %s\n", szStr); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | // Remove leading and trailing blanks from string |
|---|
| 120 | void TrimBlanks(char szStr[]) |
|---|
| 121 | { |
|---|
| 122 | TrimLeadingBlanks(szStr); |
|---|
| 123 | TrimTrailingBlanks(szStr); |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | void TrimLeadingBlanks(char szStr[]) |
|---|
| 127 | { |
|---|
| 128 | size_t n = strlen(szStr); |
|---|
| 129 | while (szStr[0] == ' ') |
|---|
| 130 | { |
|---|
| 131 | memmove(szStr, szStr+1, n); |
|---|
| 132 | szStr[--n] = 0; |
|---|
| 133 | } |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | void TrimTrailingBlanks(char szStr[]) |
|---|
| 137 | { |
|---|
| 138 | size_t n = strlen(szStr); |
|---|
| 139 | while (n > 0 && szStr[n-1] == ' ') |
|---|
| 140 | szStr[--n] = 0; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | bool Verbose() |
|---|
| 144 | { |
|---|
| 145 | return true; |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | SCORE StrToScore(const char *pszStr) |
|---|
| 149 | { |
|---|
| 150 | return (SCORE) atof(pszStr); |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | void StripWhitespace(char szStr[]) |
|---|
| 154 | { |
|---|
| 155 | unsigned uOutPos = 0; |
|---|
| 156 | unsigned uInPos = 0; |
|---|
| 157 | while (char c = szStr[uInPos++]) |
|---|
| 158 | if (' ' != c && '\t' != c && '\n' != c && '\r' != c) |
|---|
| 159 | szStr[uOutPos++] = c; |
|---|
| 160 | szStr[uOutPos] = 0; |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | void StripGaps(char szStr[]) |
|---|
| 164 | { |
|---|
| 165 | unsigned uOutPos = 0; |
|---|
| 166 | unsigned uInPos = 0; |
|---|
| 167 | while (char c = szStr[uInPos++]) |
|---|
| 168 | if ('-' != c) |
|---|
| 169 | szStr[uOutPos++] = c; |
|---|
| 170 | szStr[uOutPos] = 0; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | bool IsValidSignedInteger(const char *Str) |
|---|
| 174 | { |
|---|
| 175 | if (0 == strlen(Str)) |
|---|
| 176 | return false; |
|---|
| 177 | if ('+' == *Str || '-' == *Str) |
|---|
| 178 | ++Str; |
|---|
| 179 | while (char c = *Str++) |
|---|
| 180 | if (!isdigit(c)) |
|---|
| 181 | return false; |
|---|
| 182 | return true; |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | bool IsValidInteger(const char *Str) |
|---|
| 186 | { |
|---|
| 187 | if (0 == strlen(Str)) |
|---|
| 188 | return false; |
|---|
| 189 | while (char c = *Str++) |
|---|
| 190 | if (!isdigit(c)) |
|---|
| 191 | return false; |
|---|
| 192 | return true; |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | // Is c valid as first character in an identifier? |
|---|
| 196 | bool isidentf(char c) |
|---|
| 197 | { |
|---|
| 198 | return isalpha(c) || '_' == c; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | // Is c valid character in an identifier? |
|---|
| 202 | bool isident(char c) |
|---|
| 203 | { |
|---|
| 204 | return isalpha(c) || isdigit(c) || '_' == c; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | bool IsValidIdentifier(const char *Str) |
|---|
| 208 | { |
|---|
| 209 | if (!isidentf(Str[0])) |
|---|
| 210 | return false; |
|---|
| 211 | while (char c = *Str++) |
|---|
| 212 | if (!isident(c)) |
|---|
| 213 | return false; |
|---|
| 214 | return true; |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | void SetLogFile() |
|---|
| 218 | { |
|---|
| 219 | const char *strFileName = ValueOpt("loga"); |
|---|
| 220 | if (0 != strFileName) |
|---|
| 221 | g_bListFileAppend = true; |
|---|
| 222 | else |
|---|
| 223 | strFileName = ValueOpt("log"); |
|---|
| 224 | if (0 == strFileName) |
|---|
| 225 | return; |
|---|
| 226 | strcpy(g_strListFileName, strFileName); |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | // Get filename, stripping any extension and directory parts. |
|---|
| 230 | void NameFromPath(const char szPath[], char szName[], unsigned uBytes) |
|---|
| 231 | { |
|---|
| 232 | if (0 == uBytes) |
|---|
| 233 | return; |
|---|
| 234 | const char *pstrLastSlash = strrchr(szPath, '/'); |
|---|
| 235 | const char *pstrLastBackslash = strrchr(szPath, '\\'); |
|---|
| 236 | const char *pstrLastDot = strrchr(szPath, '.'); |
|---|
| 237 | const char *pstrLastSep = pstrLastSlash > pstrLastBackslash ? |
|---|
| 238 | pstrLastSlash : pstrLastBackslash; |
|---|
| 239 | const char *pstrBegin = pstrLastSep ? pstrLastSep + 1 : szPath; |
|---|
| 240 | const char *pstrEnd = pstrLastDot ? pstrLastDot - 1 : szPath + strlen(szPath); |
|---|
| 241 | unsigned uNameLength = (unsigned) (pstrEnd - pstrBegin + 1); |
|---|
| 242 | if (uNameLength > uBytes - 1) |
|---|
| 243 | uNameLength = uBytes - 1; |
|---|
| 244 | memcpy(szName, pstrBegin, uNameLength); |
|---|
| 245 | szName[uNameLength] = 0; |
|---|
| 246 | } |
|---|
| 247 | |
|---|
| 248 | char *strsave(const char *s) |
|---|
| 249 | { |
|---|
| 250 | char *ptrCopy = strdup(s); |
|---|
| 251 | if (0 == ptrCopy) |
|---|
| 252 | Quit("Out of memory"); |
|---|
| 253 | return ptrCopy; |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | bool IsValidFloatChar(char c) |
|---|
| 257 | { |
|---|
| 258 | return isdigit(c) || '.' == c || 'e' == c || 'E' == c || 'd' == c || |
|---|
| 259 | 'D' == c || '.' == c || '+' == c || '-' == c; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | void Call_MY_ASSERT(const char *file, int line, bool b, const char *msg) |
|---|
| 263 | { |
|---|
| 264 | if (b) |
|---|
| 265 | return; |
|---|
| 266 | Quit("%s(%d): MY_ASSERT(%s)", file, line, msg); |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | static size_t g_MemTotal; |
|---|
| 270 | |
|---|
| 271 | void MemPlus(size_t Bytes, char *Where) |
|---|
| 272 | { |
|---|
| 273 | g_MemTotal += Bytes; |
|---|
| 274 | Log("+%10u %6u %6u %s\n", |
|---|
| 275 | (unsigned) Bytes, |
|---|
| 276 | (unsigned) GetMemUseMB(), |
|---|
| 277 | (unsigned) (g_MemTotal/1000000), |
|---|
| 278 | Where); |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | void MemMinus(size_t Bytes, char *Where) |
|---|
| 282 | { |
|---|
| 283 | g_MemTotal -= Bytes; |
|---|
| 284 | Log("-%10u %6u %6u %s\n", |
|---|
| 285 | (unsigned) Bytes, |
|---|
| 286 | (unsigned) GetMemUseMB(), |
|---|
| 287 | (unsigned) (g_MemTotal/1000000), |
|---|
| 288 | Where); |
|---|
| 289 | } |
|---|