#include "xlog.h" #include <stdarg.h>
#include <stdio.h>
#define WIN 1
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN
#include <windows.h>
#else
#include <time.h>
#endif
char xslt_buf[];
char fname[30]; int generate_xslt(char *fname);
int generate_xslt(char *fname)
{
if ( fname == NULL || fname[0] == '\0' || (exists_file(fname) == TRUE) )
return FALSE;
FILE *f = NULL;
if ( (f = fopen(fname,"w")) == NULL )
return FALSE;
fprintf( f, xslt_buf );
fclose(f);
return TRUE;
}
int exists_file( char *filen )
{
struct stat fst;
if ( stat( filen, &fst) == -1 )
return FALSE; return TRUE;
}
void end_log( void )
{
FILE *xml;
if ( (xml = fopen(fname,"a")) == NULL )
return; fprintf( xml, " </Logs>\n" );
fprintf( xml, "</RunTimeLog>\n" );
fflush(xml);
fclose(xml);
}
void init_log( void )
{
#ifdef WIN
SYSTEMTIME tm;
#else
time_t rawtime;
struct tm *t;
#endif
FILE *xml;
char date[15];
char time[15];
static int xlognum = 1;
if ( exists_file("log") == FALSE )
system( "mkdir log" );
if ( exists_file("log/xslt.xsl") == FALSE )
generate_xslt("log/xslt.xsl");
sprintf( fname, "log/%d-xlog.xml", xlognum );
for ( ; (exists_file( fname ) == TRUE) ; xlognum++ ) sprintf( fname, "log/%d-xlog.xml", xlognum );
if ((xml = fopen(fname, "w")) == NULL)
return;
#ifdef WIN
GetLocalTime(&tm); sprintf( time, "%2d:%2d:%2d", tm.wHour, tm.wMinute, tm.wSecond );
sprintf( date, "%s, %s %d, %d", (tm.wDayOfWeek == 0 ? "Sunday" :
(tm.wDayOfWeek == 1 ? "Monday" :
(tm.wDayOfWeek == 2 ? "Tuesday" :
(tm.wDayOfWeek == 3 ? "Wednesday" :
(tm.wDayOfWeek == 4 ? "Thursday" :
(tm.wDayOfWeek == 5 ? "Friday" :
(tm.wDayOfWeek == 6 ? "Saturday" : "Error" ) ) ) ) ) ) ),
(tm.wMonth == 1 ? "January" :
(tm.wMonth == 2 ? "February" :
(tm.wMonth == 3 ? "March" :
(tm.wMonth == 4 ? "April" :
(tm.wMonth == 5 ? "May" :
(tm.wMonth == 6 ? "June" :
(tm.wMonth == 7 ? "July" :
(tm.wMonth == 8 ? "August" :
(tm.wMonth == 9 ? "September" :
(tm.wMonth == 10 ? "October" :
(tm.wMonth == 11 ? "November" :
(tm.wMonth == 12 ? "December" : "Error" ) ) ) ) ) ) ) ) ) ) ) ),
tm.wDay, tm.wYear );
#else
rawtime = time(NULL);
t = localtime( &rawtime );
sprintf( time, "%2d:%2d:%2d", t.tm_hour, t.tm_min, t.tm_sec );
sprintf( date, "%s, %s %d, %d", (t.tm_wday == 0 ? "Sunday" :
(t.tm_wday == 1 ? "Monday" :
(t.tm_wday == 2 ? "Tuesday" :
(t.tm_wday == 3 ? "Wednesday" :
(t.tm_wday == 4 ? "Thursday" :
(t.tm_wday == 5 ? "Friday" :
(t.tm_wday == 6 ? "Saturday" : "Error" ) ) ) ) ) ) ),
(t.tm_mon == 0 ? "January" :
(t.tm_mon == 1 ? "February" :
(t.tm_mon == 2 ? "March" :
(t.tm_mon == 3 ? "April" :
(t.tm_mon == 4 ? "May" :
(t.tm_mon == 5 ? "June" :
(t.tm_mon == 6 ? "July" :
(t.tm_mon == 7 ? "August" :
(t.tm_mon == 8 ? "September" :
(t.tm_mon == 9 ? "October" :
(t.tm_mon == 10 ? "November" :
(t.tm_mon == 11 ? "December" : "Error" ) ) ) ) ) ) ) ) ) ) ) ),
t.tm_mday, t.tm_year );
#endif
fprintf( xml, "<?xml version=\"1.0\" standalone=\"yes\" ?>\n" );
fprintf( xml, "<?xml-stylesheet type=\"text/xsl\" href=\"xslt.xsl\" ?>\n\n" );
fprintf( xml, "<RunTimeLog>\n" );
fprintf( xml, " <Header>\n" );
fprintf( xml, " <Date>%s</Date>\n", date );
fprintf( xml, " <TimeCreated>%s</TimeCreated>\n", time );
fprintf( xml, " </Header>\n" );
fprintf( xml, " <Logs>\n" );
fclose(xml);
end_log();
}
void log_it(char *Fname, const char *txt, ...)
{
FILE *fp;
char buf[3072];
char file_name[128];
static int log_num = 0;
va_list args;
va_start(args, txt);
vsprintf(buf, txt, args);
va_end(args);
if ( exists_file("log") == FALSE )
system( "mkdir log" );
if ( Fname && Fname[0] != '\0' )
sprintf( file_name, "log/%s.txt", Fname );
else
sprintf( file_name, "log/log.txt" );
if ((fp = fopen(file_name, "a")) == NULL)
return;
if ( log_num == 0 )
{
fprintf( fp, "\n\n\n\n\n------------------------\n" ); log_num++;
}
else
log_num++;
fprintf(fp, "%d. %s\n", log_num, buf);
fclose(fp);
}
int xml_fprintf( FILE *fp, const char *tag, const char *txt, short embed )
{
char spacer[51];
int i = 0;
if ( fp == NULL )
{
glog( "Xml_fprintf: Null file", 0 );
return FALSE;
}
if ( (tag == NULL || tag[0] == '\0' ) || (txt == NULL || txt[0] == '\0') )
{
glog( "Xml_fprintf: Null string", 0 );
return FALSE;
}
if ( embed > 50 )
embed = 50;
for ( i = 0; i < embed; i++ )
spacer[i] = ' ';
spacer[i++] = '\0';
fprintf( fp, "%s<%s>%s</%s>\n", spacer, tag, txt, tag );
return TRUE;
}
void seek_starting(FILE *fp)
{
if ( fp == NULL )
return;
short done = FALSE;
fseek( fp, 0, SEEK_SET );
while ( done == FALSE )
{
char a,b;
for ( ; ; )
if ( (a = (char)fgetc(fp)) == '<' )
break;
if ( (b = (char)fgetc(fp)) == '/' )
{
char tmp[5];
short i;
for ( i = 0; i < 4; i++ )
tmp[i] = (char)fgetc(fp);
tmp[4] = '\0';
if ( !stricmp("Logs",tmp) ) {
done = TRUE;
fseek( fp, -7, SEEK_CUR ); }
}
}
}
void log_entry( char *source_file, char *function, int line, const int type, const char *message, ... )
{
static int num = 0; char time[16];
char linen[32];
FILE *xml;
if ( (xml = fopen(fname,"r+")) == NULL )
return;
seek_starting(xml);
if ( source_file == NULL || source_file[0] == '\0' )
{
glog( "Log_entry: Bad source_file string!", 0 );
return;
}
if ( function == NULL || function[0] == '\0' )
{
glog( "Log_entry: Bad function name!", 0 );
return;
}
if ( message == NULL || message[0] == '\0' )
{
glog( "Log_entry: Bad message string!", 0 );
return;
}
#ifdef WIN
SYSTEMTIME tm;
GetLocalTime(&tm);
sprintf( time, "%2d:%2d:%2d", tm.wHour, tm.wMinute, tm.wSecond );
#else
time_t rawtime;
struct tm * t;
time ( &rawtime );
t = localtime( &rawtime );
sprintf( time, "%2d:%2d:%2d", t.tm_hour, t.tm_min, t.tm_sec );
#endif
char typen[16];
char buf[3072];
va_list args;
va_start(args, message);
vsprintf(buf, message, args);
va_end(args);
num++;
sprintf( linen, "%d", line );
sprintf( typen, "%s", type == COMMENT ? "Comment" :
(type == ERR ? "Error" :
(type == WARNING ? "Warning" :
(type == EVENT ? "Event" :
(type == DEBUG ? "Debug" :
(type == MESSAGE ? "Game Message" : "Unknown" ) ) ) ) ) );
fprintf( xml, " <LogEvent id=\"%d\">\n", num );
xml_fprintf( xml, "Type", typen, 8 );
xml_fprintf( xml, "File", source_file, 8 );
xml_fprintf( xml, "Function", function, 8 );
xml_fprintf( xml, "Line", linen, 8 );
xml_fprintf( xml, "Message", buf, 8 );
xml_fprintf( xml, "Time", time, 8 );
fprintf( xml, " </LogEvent>\n\n" );
fflush(xml);
fclose(xml);
end_log(); }
char xslt_buf[] =
{
"\n\
<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n\n\
\
<!-- This document was originally created by: Jack \"jollyjeffers\" Hoxley and Oli \"evolutional\" Wilkinson -->\n\
<!-- The original article can be found at: http://www.gamedev.net/reference/programming/features/xmltech/ -->\n\
<!-- Modified to fit the X-Log Library by Nick \"Odis\" Cash -->\n\n\
\
<!-- This following section is the entry point for parsing the associated XML -->\n\
<!-- document. It hands out parsing to the relevent subsections and generally links -->\n\
<xsl:template match=\"/\">\n\n\
\
<html>\n\
<head>\n\
<title>Log File Viewer</title>\n\
</head>\n\
<body>\n\
<font face=\"Arial\" size=\"5\" color=\"#2060AA\">\n\
<b>\n\
<u>\n\
Run-Time Log\n\
</u>\n\
</b>\n\
</font>\n\
<br/>\n\
<xsl:apply-templates select=\"RunTimeLog/Header\"/>\n\
<br/>\n\
<br/>\n\
<b>\n\
<font face=\"Arial\" size=\"3\" color=\"#000000\">\n\
Details of selected log entries:\n\
</font>\n\
</b>\n\
<br/>\n\
<br/>\n\
<table border=\"1\" width=\"100%%\" cellspacing=\"0\" cellpadding=\"0\" bordercolorlight=\"#000000\" bordercolordark=\"#ffffff\" bordercolor=\"#000000\">\n\
<tr>\n\
<td width=\"3%%\" bgcolor=\"#000000\"><font size=\"2\" face=\"Arial\" color=\"#FFFFFF\"><b><center>#</center></b></font></td>\n\
<td width=\"20%%\" bgcolor=\"#000000\"><font size=\"2\" face=\"Arial\" color=\"#FFFFFF\"><b><center>Time</center></b></font></td>\n\
<td width=\"23%%\" bgcolor=\"#000000\"><font size=\"2\" face=\"Arial\" color=\"#FFFFFF\"><b><center>File</center></b></font></td>\n\
<td width=\"50%%\" bgcolor=\"#000000\"><font size=\"2\" face=\"Arial\" color=\"#FFFFFF\"><b><center>Function</center></b></font></td>\n\
<td width=\"4%%\" bgcolor=\"#000000\"><font size=\"2\" face=\"Arial\" color=\"#FFFFFF\"><b><center>Line</center></b></font></td>\n\
</tr>\n\
<xsl:apply-templates select=\"RunTimeLog/Logs/LogEvent\"/>\n\
</table>\n\
\n\
</body>\n\
</html>\n\
\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This next template match is for the log header, that is the general session -->\n\
<!-- information and run-time system statistics/configuration -->\n\
<xsl:template match=\"Header\">\n\
\n\
<br/>\n\
<b>\n\
<font face=\"Arial\" size=\"3\" color=\"#000000\">\n\
File information:\n\
</font>\n\
</b>\n\
<br/>\n\
<font face=\"Arial\" size=\"2\" color=\"#000000\">\n\
Date:\n\
</font>\n\
<i>\n\
<font face=\"Arial\" size=\"2\" color=\"#808080\">\n\
<xsl:value-of select=\"Date\"/>\n\
</font>\n\
</i>\n\
<br/>\n\
<font face=\"Arial\" size=\"2\" color=\"#000000\">\n\
This log file was created at:\n\
</font>\n\
<i>\n\
<font face=\"Arial\" size=\"2\" color=\"#808080\">\n\
<xsl:value-of select=\"TimeCreated\"/>\n\
</font>\n\
</i>\n\
<br/>\n\
<font face=\"Arial\" size=\"2\" color=\"#000000\">\n\
Total logged events:\n\
</font>\n\
<i>\n\
<font face=\"Arial\" size=\"2\" color=\"#808080\">\n\
<xsl:copy-of select=\"count(../Logs/LogEvent)\"/>\n\
</font>\n\
</i>\n\
\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This template match is for each log entry, filtered according to the selected -->\n\
<!-- type of event filter. For each log entry we add a row to the table. -->\n\
<xsl:template match=\"LogEvent\">\n\
<xsl:choose>\n\
<xsl:when test=\"Type=\'Game Message\'\">\n\
<tr bgcolor=\"#80FF80\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#AAFFAA\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
<xsl:when test=\"Type=\'Unknown\'\">\n\
<tr bgcolor=\"#EEEEEE\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#AAAAAA\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
<xsl:when test=\"Type=\'Error\'\">\n\
<tr bgcolor=\"#FF8080\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#FFAAAA\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
<xsl:when test=\"Type='Warning'\">\n\
<tr bgcolor=\"#FFAA80\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#FFDDAA\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
<xsl:when test=\"Type=\'Event\'\">\n\
<tr bgcolor=\"#8080FF\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#AAAAFF\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
<xsl:when test=\"Type=\'Debug\'\">\n\
<tr bgcolor=\"#FFFF80\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#FFFF99\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
<xsl:when test=\"Type=\'Comment\'\">\n\
<tr bgcolor=\"#FF8020\" valign=\"middle\" align=\"center\">\n\
\n\
<td>\n\
<font size=\"2\" face=\"Arial\" color=\"#202020\">\n\
<center>\n\
<xsl:value-of select=\"@id\"/>\n\
</center>\n\
</font>\n\
</td>\n\
\n\
<xsl:apply-templates select=\"Time\"/>\n\
<xsl:apply-templates select=\"File\"/>\n\
<xsl:apply-templates select=\"Function\"/>\n\
<xsl:apply-templates select=\"Line\"/>\n\
\n\
</tr>\n\
<tr bgcolor=\"#FFAA80\">\n\
<xsl:apply-templates select=\"Message\"/>\n\
</tr>\n\
</xsl:when>\n\
</xsl:choose>\n\
\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This match is for the formatted time output associate with each log entry -->\n\
<xsl:template match=\"Time\">\n\
<td>\n\
<font size=\"2\" face=\"Courier New\" color=\"#404040\">\n\
<center>\n\
<xsl:apply-templates/>\n\
</center>\n\
</font>\n\
</td>\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This match is for the source code filename where this entry originated from -->\n\
<xsl:template match=\"File\">\n\
<td>\n\
<font size=\"2\" face=\"Courier New\" color=\"#404040\">\n\
<xsl:apply-templates/>\n\
</font>\n\
</td>\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This match outputs the qualified function name where the entry was created -->\n\
<xsl:template match=\"Function\">\n\
<td>\n\
<font size=\"2\" face=\"Courier New\" color=\"#404040\">\n\
<xsl:apply-templates/>\n\
</font>\n\
</td>\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This outputs the line number for the given source code file. -->\n\
<xsl:template match=\"Line\">\n\
<td>\n\
<font size=\"2\" face=\"Courier New\" color=\"#404040\">\n\
<center>\n\
<xsl:apply-templates/>\n\
</center>\n\
</font>\n\
</td>\n\
</xsl:template>\n\
\n\
\n\
\n\
<!-- This match outputs the raw 'Message' data that's sttached to this log entry. -->\n\
<xsl:template match=\"Message\">\n\
<td bgcolor=\"#FFFFFF\">\n\
</td>\n\
<td colspan=\"4\">\n\
<font size=\"2\" face=\"Arial\" color=\"#000000\">\n\
<b>\n\
<i>\n\
<xsl:apply-templates/>\n\
</i>\n\
</b>\n\
</font>\n\
</td>\n\
</xsl:template>\n\
\n\
\n\
\n\
</xsl:stylesheet>\n\
"
};