686 lines
10 KiB
C++
686 lines
10 KiB
C++
// cmdlib.c
|
|
|
|
#include "stdafx.h"
|
|
#include "qe3.h"
|
|
#include "cmdlib.h"
|
|
|
|
#define PATHSEPERATOR '/'
|
|
|
|
char com_token[1024];
|
|
qboolean com_eof;
|
|
|
|
/*
|
|
================
|
|
I_FloatTime
|
|
================
|
|
*/
|
|
double I_FloatTime (void)
|
|
{
|
|
time_t t;
|
|
|
|
time (&t);
|
|
|
|
return t;
|
|
#if 0
|
|
// more precise, less portable
|
|
struct timeval tp;
|
|
struct timezone tzp;
|
|
static int secbase;
|
|
|
|
gettimeofday(&tp, &tzp);
|
|
|
|
if (!secbase)
|
|
{
|
|
secbase = tp.tv_sec;
|
|
return tp.tv_usec/1000000.0;
|
|
}
|
|
|
|
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
COM_Parse
|
|
|
|
Parse a token out of a string
|
|
==============
|
|
*/
|
|
char *COM_Parse (char *data)
|
|
{
|
|
int c;
|
|
int len;
|
|
|
|
len = 0;
|
|
com_token[0] = 0;
|
|
|
|
if (!data)
|
|
return NULL;
|
|
|
|
// skip whitespace
|
|
skipwhite:
|
|
while ( (c = *data) <= ' ')
|
|
{
|
|
if (c == 0)
|
|
{
|
|
com_eof = true;
|
|
return NULL; // end of file;
|
|
}
|
|
data++;
|
|
}
|
|
|
|
// skip // comments
|
|
if (c=='/' && data[1] == '/')
|
|
{
|
|
while (*data && *data != '\n')
|
|
data++;
|
|
goto skipwhite;
|
|
}
|
|
|
|
|
|
// handle quoted strings specially
|
|
if (c == '\"')
|
|
{
|
|
data++;
|
|
do
|
|
{
|
|
c = *data++;
|
|
if (c=='\"')
|
|
{
|
|
com_token[len] = 0;
|
|
return data;
|
|
}
|
|
com_token[len] = c;
|
|
len++;
|
|
} while (1);
|
|
}
|
|
|
|
// parse single characters
|
|
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
|
{
|
|
com_token[len] = c;
|
|
len++;
|
|
com_token[len] = 0;
|
|
return data+1;
|
|
}
|
|
|
|
// parse a regular word
|
|
do
|
|
{
|
|
com_token[len] = c;
|
|
data++;
|
|
len++;
|
|
c = *data;
|
|
if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
|
|
break;
|
|
} while (c>32);
|
|
|
|
com_token[len] = 0;
|
|
return data;
|
|
}
|
|
|
|
|
|
int Q_strncasecmp (char *s1, char *s2, int n)
|
|
{
|
|
int c1, c2;
|
|
|
|
while (1)
|
|
{
|
|
c1 = *s1++;
|
|
c2 = *s2++;
|
|
|
|
if (!n--)
|
|
return 0; // strings are equal until end point
|
|
|
|
if (c1 != c2)
|
|
{
|
|
if (c1 >= 'a' && c1 <= 'z')
|
|
c1 -= ('a' - 'A');
|
|
if (c2 >= 'a' && c2 <= 'z')
|
|
c2 -= ('a' - 'A');
|
|
if (c1 != c2)
|
|
return -1; // strings not equal
|
|
}
|
|
if (!c1)
|
|
return 0; // strings are equal
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int Q_strcasecmp (char *s1, char *s2)
|
|
{
|
|
return Q_strncasecmp (s1, s2, 99999);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
MISC FUNCTIONS
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
|
|
int argc;
|
|
char *argv[MAX_NUM_ARGVS];
|
|
|
|
/*
|
|
============
|
|
ParseCommandLine
|
|
============
|
|
*/
|
|
void ParseCommandLine (char *lpCmdLine)
|
|
{
|
|
argc = 1;
|
|
argv[0] = "programname";
|
|
|
|
while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
|
|
{
|
|
while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
|
|
lpCmdLine++;
|
|
|
|
if (*lpCmdLine)
|
|
{
|
|
argv[argc] = lpCmdLine;
|
|
argc++;
|
|
|
|
while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
|
|
lpCmdLine++;
|
|
|
|
if (*lpCmdLine)
|
|
{
|
|
*lpCmdLine = 0;
|
|
lpCmdLine++;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=================
|
|
CheckParm
|
|
|
|
Checks for the given parameter in the program's command line arguments
|
|
Returns the argument number (1 to argc-1) or 0 if not present
|
|
=================
|
|
*/
|
|
int CheckParm (char *check)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1;i<argc;i++)
|
|
{
|
|
if ( !Q_strcasecmp(check, argv[i]) )
|
|
return i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
Q_filelength
|
|
================
|
|
*/
|
|
int Q_filelength (FILE *f)
|
|
{
|
|
int pos;
|
|
int end;
|
|
|
|
pos = ftell (f);
|
|
fseek (f, 0, SEEK_END);
|
|
end = ftell (f);
|
|
fseek (f, pos, SEEK_SET);
|
|
|
|
return end;
|
|
}
|
|
|
|
|
|
FILE *SafeOpenWrite (const char *filename)
|
|
{
|
|
FILE *f;
|
|
|
|
f = fopen(filename, "wb");
|
|
|
|
if (!f)
|
|
Error ("Error opening %s: %s",filename,strerror(errno));
|
|
|
|
return f;
|
|
}
|
|
|
|
FILE *SafeOpenRead (const char *filename)
|
|
{
|
|
FILE *f;
|
|
|
|
f = fopen(filename, "rb");
|
|
|
|
if (!f)
|
|
Error ("Error opening %s: %s",filename,strerror(errno));
|
|
|
|
return f;
|
|
}
|
|
|
|
|
|
void SafeRead (FILE *f, void *buffer, int count)
|
|
{
|
|
if ( (int)fread (buffer, 1, count, f) != count)
|
|
Error ("File read failure");
|
|
}
|
|
|
|
|
|
void SafeWrite (FILE *f, void *buffer, int count)
|
|
{
|
|
if ( (int)fwrite (buffer, 1, count, f) != count)
|
|
Error ("File read failure");
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
==============
|
|
LoadFile
|
|
==============
|
|
*/
|
|
int LoadFile (const char *filename, void **bufferptr)
|
|
{
|
|
FILE *f;
|
|
int length;
|
|
void *buffer;
|
|
|
|
*bufferptr = NULL;
|
|
|
|
if (filename == NULL || strlen(filename) == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
f = fopen (filename, "rb");
|
|
if (!f)
|
|
{
|
|
return -1;
|
|
}
|
|
length = Q_filelength (f);
|
|
|
|
//============
|
|
int iMallocAddBodge = 0;
|
|
|
|
char sLine[512];
|
|
strcpy(sLine,filename);
|
|
strlwr(sLine);
|
|
char *p = strstr(sLine,".jpg");
|
|
if (p)
|
|
{
|
|
iMallocAddBodge = 4096; // keep this in sync with the equate INPUT_BUF_SIZE in the jpeg headers
|
|
}
|
|
|
|
//============
|
|
|
|
buffer = qmalloc (length+1 + iMallocAddBodge);
|
|
((char *)buffer)[length] = 0;
|
|
SafeRead (f, buffer, length);
|
|
fclose (f);
|
|
|
|
*bufferptr = buffer;
|
|
return length;
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
LoadFileNoCrash
|
|
|
|
returns -1 length if not present
|
|
==============
|
|
*/
|
|
int LoadFileNoCrash (const char *filename, void **bufferptr)
|
|
{
|
|
FILE *f;
|
|
int length;
|
|
void *buffer;
|
|
|
|
f = fopen (filename, "rb");
|
|
if (!f)
|
|
return -1;
|
|
length = Q_filelength (f);
|
|
buffer = qmalloc (length+1);
|
|
((char *)buffer)[length] = 0;
|
|
SafeRead (f, buffer, length);
|
|
fclose (f);
|
|
|
|
*bufferptr = buffer;
|
|
return length;
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
SaveFile
|
|
==============
|
|
*/
|
|
void SaveFile (const char *filename, void *buffer, int count)
|
|
{
|
|
FILE *f;
|
|
|
|
f = SafeOpenWrite (filename);
|
|
SafeWrite (f, buffer, count);
|
|
fclose (f);
|
|
}
|
|
|
|
|
|
|
|
void DefaultExtension (char *path, char *extension)
|
|
{
|
|
char *src;
|
|
//
|
|
// if path doesn't have a .EXT, append extension
|
|
// (extension should include the .)
|
|
//
|
|
src = path + strlen(path) - 1;
|
|
|
|
while (*src != PATHSEPERATOR && src != path)
|
|
{
|
|
if (*src == '.')
|
|
return; // it has an extension
|
|
src--;
|
|
}
|
|
|
|
strcat (path, extension);
|
|
}
|
|
|
|
|
|
void DefaultPath (char *path, char *basepath)
|
|
{
|
|
char temp[128];
|
|
|
|
if (path[0] == PATHSEPERATOR)
|
|
return; // absolute path location
|
|
strcpy (temp,path);
|
|
strcpy (path,basepath);
|
|
strcat (path,temp);
|
|
}
|
|
|
|
|
|
void StripFilename (char *path)
|
|
{
|
|
int length;
|
|
|
|
length = strlen(path)-1;
|
|
while (length > 0 && path[length] != PATHSEPERATOR)
|
|
length--;
|
|
path[length] = 0;
|
|
}
|
|
|
|
void StripExtension (char *path)
|
|
{
|
|
int length;
|
|
|
|
length = strlen(path)-1;
|
|
while (length > 0 && path[length] != '.')
|
|
{
|
|
length--;
|
|
if (path[length] == '/')
|
|
return; // no extension
|
|
}
|
|
if (length)
|
|
path[length] = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
====================
|
|
Extract file parts
|
|
====================
|
|
*/
|
|
void ExtractFilePath (char *path, char *dest)
|
|
{
|
|
char *src;
|
|
|
|
src = path + strlen(path) - 1;
|
|
|
|
//
|
|
// back up until a \ or the start
|
|
//
|
|
while (src != path && *(src-1) != PATHSEPERATOR)
|
|
src--;
|
|
|
|
memcpy (dest, path, src-path);
|
|
dest[src-path] = 0;
|
|
}
|
|
|
|
void ExtractFileName (char *path, char *dest)
|
|
{
|
|
char *src;
|
|
|
|
src = path + strlen(path) - 1;
|
|
|
|
//
|
|
// back up until a \ or the start
|
|
//
|
|
while (src != path && *(src-1) != '/'
|
|
&& *(src-1) != '\\' )
|
|
src--;
|
|
|
|
while (*src)
|
|
{
|
|
*dest++ = *src++;
|
|
}
|
|
*dest = 0;
|
|
}
|
|
|
|
void ExtractFileBase (char *path, char *dest)
|
|
{
|
|
char *src;
|
|
|
|
src = path + strlen(path) - 1;
|
|
|
|
//
|
|
// back up until a \ or the start
|
|
//
|
|
while (src != path && *(src-1) != '/'
|
|
&& *(src-1) != '\\' )
|
|
src--;
|
|
|
|
while (*src && *src != '.')
|
|
{
|
|
*dest++ = *src++;
|
|
}
|
|
*dest = 0;
|
|
}
|
|
|
|
void ExtractFileExtension (char *path, char *dest)
|
|
{
|
|
char *src;
|
|
|
|
src = path + strlen(path) - 1;
|
|
|
|
//
|
|
// back up until a . or the start
|
|
//
|
|
while (src != path && *(src-1) != '.')
|
|
src--;
|
|
if (src == path)
|
|
{
|
|
*dest = 0; // no extension
|
|
return;
|
|
}
|
|
|
|
strcpy (dest,src);
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
ParseNum / ParseHex
|
|
==============
|
|
*/
|
|
int ParseHex (char *hex)
|
|
{
|
|
char *str;
|
|
int num;
|
|
|
|
num = 0;
|
|
str = hex;
|
|
|
|
while (*str)
|
|
{
|
|
num <<= 4;
|
|
if (*str >= '0' && *str <= '9')
|
|
num += *str-'0';
|
|
else if (*str >= 'a' && *str <= 'f')
|
|
num += 10 + *str-'a';
|
|
else if (*str >= 'A' && *str <= 'F')
|
|
num += 10 + *str-'A';
|
|
else
|
|
Error ("Bad hex number: %s",hex);
|
|
str++;
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
|
|
int ParseNum (char *str)
|
|
{
|
|
if (str[0] == '$')
|
|
return ParseHex (str+1);
|
|
if (str[0] == '0' && str[1] == 'x')
|
|
return ParseHex (str+2);
|
|
return atol (str);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
BYTE ORDER FUNCTIONS
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
#ifdef _SGI_SOURCE
|
|
#define __BIG_ENDIAN__
|
|
#endif
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
short LittleShort (short l)
|
|
{
|
|
byte b1,b2;
|
|
|
|
b1 = l&255;
|
|
b2 = (l>>8)&255;
|
|
|
|
return (b1<<8) + b2;
|
|
}
|
|
|
|
short BigShort (short l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
|
|
int LittleLong (int l)
|
|
{
|
|
byte b1,b2,b3,b4;
|
|
|
|
b1 = l&255;
|
|
b2 = (l>>8)&255;
|
|
b3 = (l>>16)&255;
|
|
b4 = (l>>24)&255;
|
|
|
|
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
|
}
|
|
|
|
int BigLong (int l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
|
|
float LittleFloat (float l)
|
|
{
|
|
union {byte b[4]; float f;} in, out;
|
|
|
|
in.f = l;
|
|
out.b[0] = in.b[3];
|
|
out.b[1] = in.b[2];
|
|
out.b[2] = in.b[1];
|
|
out.b[3] = in.b[0];
|
|
|
|
return out.f;
|
|
}
|
|
|
|
float BigFloat (float l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
|
|
short BigShort (short l)
|
|
{
|
|
byte b1,b2;
|
|
|
|
b1 = l&255;
|
|
b2 = (l>>8)&255;
|
|
|
|
return (b1<<8) + b2;
|
|
}
|
|
|
|
short LittleShort (short l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
|
|
int BigLong (int l)
|
|
{
|
|
byte b1,b2,b3,b4;
|
|
|
|
b1 = l&255;
|
|
b2 = (l>>8)&255;
|
|
b3 = (l>>16)&255;
|
|
b4 = (l>>24)&255;
|
|
|
|
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
|
}
|
|
|
|
int LittleLong (int l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
float BigFloat (float l)
|
|
{
|
|
union {byte b[4]; float f;} in, out;
|
|
|
|
in.f = l;
|
|
out.b[0] = in.b[3];
|
|
out.b[1] = in.b[2];
|
|
out.b[2] = in.b[1];
|
|
out.b[3] = in.b[0];
|
|
|
|
return out.f;
|
|
}
|
|
|
|
float LittleFloat (float l)
|
|
{
|
|
return l;
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|