log.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. #ifdef SYSTEM_WIN32
  2. #pragma warning(disable:4996)
  3. #endif
  4. #ifdef HAVE_CONFIG_H
  5. #include "config.h"
  6. #endif
  7. #ifdef ZHLT_NETVIS
  8. #ifdef SYSTEM_WIN32
  9. #define WIN32_LEAN_AND_MEAN
  10. #include <windows.h>
  11. #endif
  12. #endif
  13. #ifdef STDC_HEADERS
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #endif
  18. #ifdef HAVE_UNISTD_H
  19. #include <unistd.h>
  20. #endif
  21. #ifdef ZHLT_NETVIS
  22. #include "../netvis/c2cpp.h"
  23. #endif
  24. #include "cmdlib.h"
  25. #include "messages.h"
  26. #include "hlassert.h"
  27. #include "log.h"
  28. #include "filelib.h"
  29. #include <windows.h>
  30. char* g_Program = "Uninitialized variable ::g_Program";
  31. char g_Mapname[_MAX_PATH] = "Uninitialized variable ::g_Mapname";
  32. developer_level_t g_developer = DEFAULT_DEVELOPER;
  33. bool g_verbose = DEFAULT_VERBOSE;
  34. bool g_log = DEFAULT_LOG;
  35. unsigned long g_clientid = 0;
  36. unsigned long g_nextclientid = 0;
  37. static FILE* CompileLog = NULL;
  38. static bool fatal = false;
  39. bool g_noConColors = false;
  40. ////////
  41. void ResetTmpFiles()
  42. {
  43. if (g_log)
  44. {
  45. char filename[_MAX_PATH];
  46. safe_snprintf(filename, _MAX_PATH, "%s.bsp", g_Mapname);
  47. _unlink(filename);
  48. safe_snprintf(filename, _MAX_PATH, "%s.inc", g_Mapname);
  49. _unlink(filename);
  50. safe_snprintf(filename, _MAX_PATH, "%s.p0", g_Mapname);
  51. _unlink(filename);
  52. safe_snprintf(filename, _MAX_PATH, "%s.p1", g_Mapname);
  53. _unlink(filename);
  54. safe_snprintf(filename, _MAX_PATH, "%s.p2", g_Mapname);
  55. _unlink(filename);
  56. safe_snprintf(filename, _MAX_PATH, "%s.p3", g_Mapname);
  57. _unlink(filename);
  58. safe_snprintf(filename, _MAX_PATH, "%s.prt", g_Mapname);
  59. _unlink(filename);
  60. safe_snprintf(filename, _MAX_PATH, "%s.pts", g_Mapname);
  61. _unlink(filename);
  62. safe_snprintf(filename, _MAX_PATH, "%s.lin", g_Mapname);
  63. _unlink(filename);
  64. safe_snprintf(filename, _MAX_PATH, "%s.wic", g_Mapname);
  65. _unlink(filename);
  66. }
  67. }
  68. void ResetLog()
  69. {
  70. if (g_log)
  71. {
  72. char logfilename[_MAX_PATH];
  73. safe_snprintf(logfilename, _MAX_PATH, "%s.log", g_Mapname);
  74. _unlink(logfilename);
  75. }
  76. }
  77. void ResetErrorLog()
  78. {
  79. if (g_log)
  80. {
  81. char logfilename[_MAX_PATH];
  82. safe_snprintf(logfilename, _MAX_PATH, "%s.err", g_Mapname);
  83. _unlink(logfilename);
  84. }
  85. }
  86. void CheckForErrorLog()
  87. {
  88. if (g_log)
  89. {
  90. char logfilename[_MAX_PATH];
  91. safe_snprintf(logfilename, _MAX_PATH, "%s.err", g_Mapname);
  92. if (q_exists(logfilename))
  93. {
  94. Log(">> There was a problem compiling the map.\n"
  95. ">> Check the file %s.log for the cause.\n",
  96. g_Mapname);
  97. exit(1);
  98. }
  99. }
  100. }
  101. ///////
  102. void LogError(const char* const message)
  103. {
  104. if (g_log && CompileLog)
  105. {
  106. char logfilename[_MAX_PATH];
  107. FILE* ErrorLog = NULL;
  108. safe_snprintf(logfilename, _MAX_PATH, "%s.err", g_Mapname);
  109. ErrorLog = fopen(logfilename, "a");
  110. if (ErrorLog)
  111. {
  112. fprintf(ErrorLog, "%s: %s\n", g_Program, message);
  113. fflush(ErrorLog);
  114. fclose(ErrorLog);
  115. ErrorLog = NULL;
  116. }
  117. else
  118. {
  119. fprintf(stderr, "ERROR: Could not open error logfile %s", logfilename);
  120. fflush(stderr);
  121. }
  122. }
  123. }
  124. void CDECL OpenLog(const int clientid)
  125. {
  126. if (g_log)
  127. {
  128. char logfilename[_MAX_PATH];
  129. #ifdef ZHLT_NETVIS
  130. #ifdef SYSTEM_WIN32
  131. if (clientid)
  132. {
  133. char computername[MAX_COMPUTERNAME_LENGTH + 1];
  134. unsigned long size = sizeof(computername);
  135. if (!GetComputerName(computername, &size))
  136. {
  137. safe_strncpy(computername, "unknown", sizeof(computername));
  138. }
  139. safe_snprintf(logfilename, _MAX_PATH, "%s-%s-%d.log", g_Mapname, computername, clientid);
  140. }
  141. else
  142. #endif
  143. #ifdef SYSTEM_POSIX
  144. if (clientid)
  145. {
  146. char computername[_MAX_PATH];
  147. unsigned long size = sizeof(computername);
  148. if (gethostname(computername, size))
  149. {
  150. safe_strncpy(computername, "unknown", sizeof(computername));
  151. }
  152. safe_snprintf(logfilename, _MAX_PATH, "%s-%s-%d.log", g_Mapname, computername, clientid);
  153. }
  154. #endif
  155. #endif
  156. {
  157. safe_snprintf(logfilename, _MAX_PATH, "%s.log", g_Mapname);
  158. }
  159. CompileLog = fopen(logfilename, "a");
  160. if (!CompileLog)
  161. {
  162. fprintf(stderr, "ERROR: Could not open logfile %s", logfilename);
  163. fflush(stderr);
  164. }
  165. }
  166. }
  167. void CDECL CloseLog()
  168. {
  169. if (g_log && CompileLog)
  170. {
  171. LogEnd();
  172. fflush(CompileLog);
  173. fclose(CompileLog);
  174. CompileLog = NULL;
  175. }
  176. }
  177. //
  178. // Every function up to this point should check g_log, the functions below should not
  179. //
  180. #ifdef SYSTEM_WIN32
  181. // AJM: fprintf/flush wasnt printing newline chars correctly (prefixed with \r) under win32
  182. // due to the fact that those streams are in byte mode, so this function prefixes
  183. // all \n with \r automatically.
  184. // NOTE: system load may be more with this method, but there isnt that much logging going
  185. // on compared to the time taken to compile the map, so its negligable.
  186. void Safe_WriteLog(const char* const message)
  187. {
  188. const char* c;
  189. if (!CompileLog)
  190. return;
  191. c = &message[0];
  192. while (1)
  193. {
  194. if (!*c)
  195. return; // end of string
  196. if (*c == '\n')
  197. fputc('\r', CompileLog);
  198. fputc(*c, CompileLog);
  199. c++;
  200. }
  201. }
  202. #endif
  203. void WriteLog(const char* const message)
  204. {
  205. #ifndef SYSTEM_WIN32
  206. if (CompileLog)
  207. {
  208. fprintf(CompileLog, message);
  209. fflush(CompileLog);
  210. }
  211. #else
  212. Safe_WriteLog(message);
  213. #endif
  214. fprintf(stdout, message);
  215. fflush(stdout);
  216. }
  217. // =====================================================================================
  218. // CheckFatal
  219. // =====================================================================================
  220. void CheckFatal()
  221. {
  222. if (fatal)
  223. {
  224. hlassert(false);
  225. exit(1);
  226. }
  227. }
  228. #define MAX_ERROR 2048
  229. #define MAX_WARNING 2048
  230. #define MAX_MESSAGE 2048
  231. // =====================================================================================
  232. // Error
  233. // for formatted error messages, fatals out
  234. // =====================================================================================
  235. void CDECL Error(const char* const error, ...)
  236. {
  237. char message[MAX_ERROR];
  238. char message2[MAX_ERROR];
  239. va_list argptr;
  240. /*#if defined( SYSTEM_WIN32 ) && !defined( __MINGW32__ ) && !defined( __BORLANDC__ )
  241. {
  242. char* wantint3 = getenv("WANTINT3");
  243. if (wantint3)
  244. {
  245. if (atoi(wantint3))
  246. {
  247. __asm
  248. {
  249. int 3;
  250. }
  251. }
  252. }
  253. }
  254. #endif*/
  255. va_start(argptr, error);
  256. _vsnprintf_s(message, MAX_ERROR, error, argptr);
  257. va_end(argptr);
  258. safe_snprintf(message2, MAX_MESSAGE, "Error: %s\n", message);
  259. ConColor(CONCOLOR_RED, CONCOLOR_BGDEF_BLACK); //SILENCER
  260. WriteLog(message2);
  261. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK); //SILENCER
  262. LogError(message2);
  263. fatal = 1;
  264. CheckFatal();
  265. }
  266. // =====================================================================================
  267. // Fatal
  268. // For formatted 'fatal' warning messages
  269. // automatically appends an extra newline to the message
  270. // This function sets a flag that the compile should abort before completing
  271. // =====================================================================================
  272. void CDECL Fatal(assume_msgs msgid, const char* const warning, ...)
  273. {
  274. char message[MAX_WARNING];
  275. char message2[MAX_WARNING];
  276. va_list argptr;
  277. va_start(argptr, warning);
  278. _vsnprintf_s(message, MAX_WARNING, warning, argptr);
  279. va_end(argptr);
  280. safe_snprintf(message2, MAX_MESSAGE, "Error: %s\n", message);
  281. ConColor(CONCOLOR_RED, CONCOLOR_BGDEF_BLACK); //SILENCER
  282. WriteLog(message2);
  283. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK); //SILENCER
  284. LogError(message2);
  285. {
  286. char message[MAX_MESSAGE];
  287. const MessageTable_t* msg = GetAssume(msgid);
  288. safe_snprintf(message, MAX_MESSAGE, "%s\nDescription: %s\nHowto Fix: %s\n", msg->title, msg->text, msg->howto);
  289. PrintOnce(message);
  290. }
  291. fatal = 1;
  292. }
  293. // =====================================================================================
  294. // PrintOnce
  295. // This function is only callable one time. Further calls will be ignored
  296. // =====================================================================================
  297. void CDECL PrintOnce(const char* const warning, ...)
  298. {
  299. char message[MAX_WARNING];
  300. char message2[MAX_WARNING];
  301. va_list argptr;
  302. static int count = 0;
  303. if (count > 0) // make sure it only gets called once
  304. {
  305. return;
  306. }
  307. count++;
  308. va_start(argptr, warning);
  309. _vsnprintf_s(message, MAX_WARNING, warning, argptr);
  310. va_end(argptr);
  311. safe_snprintf(message2, MAX_MESSAGE, "Error: %s\n", message);
  312. WriteLog(message2);
  313. LogError(message2);
  314. }
  315. // =====================================================================================
  316. // Warning
  317. // For formatted warning messages
  318. // automatically appends an extra newline to the message
  319. // =====================================================================================
  320. void CDECL Warning(const char* const warning, ...)
  321. {
  322. char message[MAX_WARNING];
  323. char message2[MAX_WARNING];
  324. va_list argptr;
  325. va_start(argptr, warning);
  326. _vsnprintf_s(message, MAX_WARNING, warning, argptr);
  327. va_end(argptr);
  328. safe_snprintf(message2, MAX_MESSAGE, "Warning: %s\n", message);
  329. ConColor(CONCOLOR_YELLOW, CONCOLOR_BGDEF_BLACK); //SILENCER
  330. WriteLog(message2);
  331. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK); //SILENCER
  332. }
  333. // =====================================================================================
  334. // Verbose
  335. // Same as log but only prints when in verbose mode
  336. // =====================================================================================
  337. void CDECL Verbose(const char* const warning, ...)
  338. {
  339. if (g_verbose)
  340. {
  341. char message[MAX_MESSAGE];
  342. va_list argptr;
  343. va_start(argptr, warning);
  344. _vsnprintf_s(message, MAX_MESSAGE, warning, argptr);
  345. va_end(argptr);
  346. WriteLog(message);
  347. }
  348. }
  349. // =====================================================================================
  350. // Developer
  351. // Same as log but only prints when in developer mode
  352. // =====================================================================================
  353. void CDECL Developer(developer_level_t level, const char* const warning, ...)
  354. {
  355. if (level <= g_developer)
  356. {
  357. char message[MAX_MESSAGE];
  358. va_list argptr;
  359. va_start(argptr, warning);
  360. _vsnprintf_s(message, MAX_MESSAGE, warning, argptr);
  361. va_end(argptr);
  362. WriteLog(message);
  363. }
  364. }
  365. // =====================================================================================
  366. // DisplayDeveloperLevel
  367. // =====================================================================================
  368. static void DisplayDeveloperLevel()
  369. {
  370. char message[MAX_MESSAGE];
  371. safe_strncpy(message, "Developer messages enabled : [", MAX_MESSAGE);
  372. if (g_developer >= DEVELOPER_LEVEL_MEGASPAM)
  373. {
  374. safe_strncat(message, "MegaSpam ", MAX_MESSAGE);
  375. }
  376. if (g_developer >= DEVELOPER_LEVEL_SPAM)
  377. {
  378. safe_strncat(message, "Spam ", MAX_MESSAGE);
  379. }
  380. if (g_developer >= DEVELOPER_LEVEL_FLUFF)
  381. {
  382. safe_strncat(message, "Fluff ", MAX_MESSAGE);
  383. }
  384. if (g_developer >= DEVELOPER_LEVEL_MESSAGE)
  385. {
  386. safe_strncat(message, "Message ", MAX_MESSAGE);
  387. }
  388. if (g_developer >= DEVELOPER_LEVEL_WARNING)
  389. {
  390. safe_strncat(message, "Warning ", MAX_MESSAGE);
  391. }
  392. if (g_developer >= DEVELOPER_LEVEL_ERROR)
  393. {
  394. safe_strncat(message, "Error", MAX_MESSAGE);
  395. }
  396. if (g_developer)
  397. {
  398. safe_strncat(message, "]\n", MAX_MESSAGE);
  399. Log(message);
  400. }
  401. }
  402. // =====================================================================================
  403. // Log
  404. // For formatted log output messages
  405. // =====================================================================================
  406. void CDECL Log(const char* const warning, ...)
  407. {
  408. char message[MAX_MESSAGE];
  409. va_list argptr;
  410. va_start(argptr, warning);
  411. _vsnprintf_s(message, MAX_MESSAGE, warning, argptr);
  412. va_end(argptr);
  413. WriteLog(message);
  414. }
  415. // =====================================================================================
  416. // LogArgs
  417. // =====================================================================================
  418. static void LogArgs(int argc, char** argv)
  419. {
  420. int i;
  421. Log("Command line: ");
  422. for (i = 0; i < argc; i++) {
  423. if (strchr(argv[i], ' ')) {
  424. Log("\"%s\"", argv[i]);
  425. } else {
  426. Log("%s ", argv[i]);
  427. }
  428. }
  429. Log("\n");
  430. }
  431. // =====================================================================================
  432. // Banner
  433. // =====================================================================================
  434. void Banner()
  435. {
  436. // SILENCER -->
  437. // Made this whole section a lot better, as in, more dynamic
  438. // Message block - keep line lengths the same or the code below will screw up
  439. char message_block[] =
  440. " Super Half-Life Compilation Tools -- Custom Build. \n"
  441. " Based on code modifications by Sean 'Zoner' Cavanaugh. \n"
  442. " Based on Valve's version, modified with permission. \n"
  443. " Further development done by Silencer and Protector. \n"
  444. " Submit detailed bug reports to [email protected]. ";
  445. int linelength = 0;
  446. int lines = 1;
  447. bool gotlength = false;
  448. const int msgblen = (int)strlen(message_block);
  449. for(int i = 0; i < msgblen; i++) {
  450. if(message_block[i] != '\n') {
  451. if(!gotlength) {
  452. linelength++;
  453. }
  454. } else {
  455. lines++;
  456. gotlength = true;
  457. }
  458. }
  459. ConColor(CONCOLOR_BGDEF_BLACK, CONCOLOR_TXTDEF_WHITE);
  460. Log(" %s " ZHLT_VERSIONSTRING " " HACK_VERSIONSTRING " (%s) ", g_Program, __DATE__);
  461. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK);
  462. Log("\n");
  463. for(int i = 0; i < lines; i++) {
  464. ConColor(CONCOLOR_BGDEF_BLACK, CONCOLOR_TXTDEF_WHITE);
  465. Log(" ");
  466. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK);
  467. char line[128];
  468. int j = 0;
  469. while(j < linelength && j < 127) {
  470. line[j] = message_block[(i * (linelength + 1)) + j];
  471. j++;
  472. }
  473. line[j] = '\0';
  474. Log(line);
  475. ConColor(CONCOLOR_BGDEF_BLACK, CONCOLOR_TXTDEF_WHITE);
  476. Log(" ");
  477. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK);
  478. Log("\n");
  479. }
  480. // <-- SILENCER
  481. }
  482. // =====================================================================================
  483. // LogStart
  484. // =====================================================================================
  485. void LogStart(int argc, char** argv)
  486. {
  487. Banner();
  488. ConColor(CONCOLOR_BGDEF_BLACK, CONCOLOR_TXTDEF_WHITE); //SILENCER
  489. Log(" ----- BEGIN %s ----- ", g_Program);
  490. ConColor(CONCOLOR_TXTDEF_WHITE, CONCOLOR_BGDEF_BLACK); //SILENCER
  491. Log("\n\n");
  492. LogArgs(argc, argv);
  493. DisplayDeveloperLevel();
  494. }
  495. // =====================================================================================
  496. // LogEnd
  497. // =====================================================================================
  498. void LogEnd()
  499. {
  500. Log("\n----- END %s -----\n\n\n\n", g_Program);
  501. }
  502. // =====================================================================================
  503. // hlassume
  504. // =====================================================================================
  505. void hlassume(bool exp, assume_msgs msgid) // Removed option to append info messages again, because it slowed down tools
  506. {
  507. if (!exp)
  508. {
  509. /*//SILENCER: Commenting this feature out// SILENCER -->
  510. char* check;
  511. char appendmsgdefault[2048] = "Info: No additional information given.";
  512. va_list p_args;
  513. va_start(p_args, msgid);
  514. if((check = va_arg(p_args, char*)) != NULL) {
  515. safe_snprintf(appendmsg, 2047, "Info: %s", check);
  516. }
  517. va_end(p_args);
  518. // <-- SILENCER*/
  519. char message[MAX_MESSAGE];
  520. const MessageTable_t* msg = GetAssume(msgid);
  521. safe_snprintf(message, MAX_MESSAGE, "%s\nDescription: %s\nHowto Fix: %s\n", msg->title, msg->text, msg->howto);
  522. Error(message);
  523. }
  524. }
  525. // =====================================================================================
  526. // seconds_to_hhmm
  527. // =====================================================================================
  528. static void seconds_to_hhmm(unsigned int elapsed_time, unsigned& days, unsigned& hours, unsigned& minutes, unsigned& seconds)
  529. {
  530. seconds = elapsed_time % 60;
  531. elapsed_time /= 60;
  532. minutes = elapsed_time % 60;
  533. elapsed_time /= 60;
  534. hours = elapsed_time % 24;
  535. elapsed_time /= 24;
  536. days = elapsed_time;
  537. }
  538. // =====================================================================================
  539. // LogTimeElapsed
  540. // =====================================================================================
  541. void LogTimeElapsed(float elapsed_time)
  542. {
  543. unsigned days = 0;
  544. unsigned hours = 0;
  545. unsigned minutes = 0;
  546. unsigned seconds = 0;
  547. seconds_to_hhmm(elapsed_time, days, hours, minutes, seconds);
  548. if (days)
  549. {
  550. Log("%.2f seconds elapsed [%ud %uh %um %us]\n", elapsed_time, days, hours, minutes, seconds);
  551. }
  552. else if (hours)
  553. {
  554. Log("%.2f seconds elapsed [%uh %um %us]\n", elapsed_time, hours, minutes, seconds);
  555. }
  556. else if (minutes)
  557. {
  558. Log("%.2f seconds elapsed [%um %us]\n", elapsed_time, minutes, seconds);
  559. }
  560. else
  561. {
  562. Log("%.2f seconds elapsed\n", elapsed_time);
  563. }
  564. }
  565. // SILENCER -->
  566. void ConColor(const short c_text_color, const short c_background_color) {
  567. if(!g_noConColors) {
  568. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (16 * c_background_color) + c_text_color);
  569. }
  570. }
  571. // <-- SILENCER