📄 l_cmd.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// cmdlib.c
#include "l_cmd.h"
#include "l_log.h"
#include "l_mem.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifndef SIN
#define SIN
#endif //SIN
#if defined(WIN32) || defined(_WIN32)
#include <direct.h>
#else
#include <unistd.h>
#endif
#ifdef NeXT
#include <libc.h>
#endif
#define BASEDIRNAME "quake2"
#define PATHSEPERATOR '/'
// set these before calling CheckParm
int myargc;
char **myargv;
char com_token[1024];
qboolean com_eof;
qboolean archive;
char archivedir[1024];
/*
===================
ExpandWildcards
Mimic unix command line expansion
===================
*/
#define MAX_EX_ARGC 1024
int ex_argc;
char *ex_argv[MAX_EX_ARGC];
#ifdef _WIN32
#include "io.h"
void ExpandWildcards (int *argc, char ***argv)
{
struct _finddata_t fileinfo;
int handle;
int i;
char filename[1024];
char filebase[1024];
char *path;
ex_argc = 0;
for (i=0 ; i<*argc ; i++)
{
path = (*argv)[i];
if ( path[0] == '-'
|| ( !strstr(path, "*") && !strstr(path, "?") ) )
{
ex_argv[ex_argc++] = path;
continue;
}
handle = _findfirst (path, &fileinfo);
if (handle == -1)
return;
ExtractFilePath (path, filebase);
do
{
sprintf (filename, "%s%s", filebase, fileinfo.name);
ex_argv[ex_argc++] = copystring (filename);
} while (_findnext( handle, &fileinfo ) != -1);
_findclose (handle);
}
*argc = ex_argc;
*argv = ex_argv;
}
#else
void ExpandWildcards (int *argc, char ***argv)
{
}
#endif
#ifdef WINBSPC
#include <windows.h>
HWND program_hwnd;
void SetProgramHandle(HWND hwnd)
{
program_hwnd = hwnd;
} //end of the function SetProgramHandle
/*
=================
Error
For abnormal program terminations in windowed apps
=================
*/
void Error (char *error, ...)
{
va_list argptr;
char text[1024];
char text2[1024];
int err;
err = GetLastError ();
va_start(argptr, error);
vsprintf(text, error, argptr);
va_end(argptr);
sprintf(text2, "%s\nGetLastError() = %i", text, err);
MessageBox(program_hwnd, text2, "Error", 0 /* MB_OK */ );
Log_Write(text);
Log_Close();
exit(1);
} //end of the function Error
void Warning(char *szFormat, ...)
{
char szBuffer[256];
va_list argptr;
va_start (argptr, szFormat);
vsprintf(szBuffer, szFormat, argptr);
va_end (argptr);
MessageBox(program_hwnd, szBuffer, "Warning", MB_OK);
Log_Write(szBuffer);
} //end of the function Warning
#else
/*
=================
Error
For abnormal program terminations in console apps
=================
*/
void Error (char *error, ...)
{
va_list argptr;
char text[1024];
va_start(argptr, error);
vsprintf(text, error, argptr);
va_end(argptr);
printf("ERROR: %s\n", text);
Log_Write(text);
Log_Close();
exit (1);
} //end of the function Error
void Warning(char *warning, ...)
{
va_list argptr;
char text[1024];
va_start(argptr, warning);
vsprintf(text, warning, argptr);
va_end(argptr);
printf("WARNING: %s\n", text);
Log_Write(text);
} //end of the function Warning
#endif
//only printf if in verbose mode
qboolean verbose = true;
void qprintf(char *format, ...)
{
va_list argptr;
#ifdef WINBSPC
char buf[2048];
#endif //WINBSPC
if (!verbose)
return;
va_start(argptr,format);
#ifdef WINBSPC
vsprintf(buf, format, argptr);
WinBSPCPrint(buf);
#else
vprintf(format, argptr);
#endif //WINBSPC
va_end(argptr);
} //end of the function qprintf
void Com_Error(int level, char *error, ...)
{
va_list argptr;
char text[1024];
va_start(argptr, error);
vsprintf(text, error, argptr);
va_end(argptr);
Error(text);
} //end of the funcion Com_Error
void Com_Printf( const char *fmt, ... )
{
va_list argptr;
char text[1024];
va_start(argptr, fmt);
vsprintf(text, fmt, argptr);
va_end(argptr);
Log_Print(text);
} //end of the funcion Com_Printf
/*
qdir will hold the path up to the quake directory, including the slash
f:\quake\
/raid/quake/
gamedir will hold qdir + the game directory (id1, id2, etc)
*/
char qdir[1024];
char gamedir[1024];
void SetQdirFromPath (char *path)
{
char temp[1024];
char *c;
int len;
if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
{ // path is partial
Q_getwd (temp);
strcat (temp, path);
path = temp;
}
// search for "quake2" in path
len = strlen(BASEDIRNAME);
for (c=path+strlen(path)-1 ; c != path ; c--)
if (!Q_strncasecmp (c, BASEDIRNAME, len))
{
strncpy (qdir, path, c+len+1-path);
qprintf ("qdir: %s\n", qdir);
c += len+1;
while (*c)
{
if (*c == '/' || *c == '\\')
{
strncpy (gamedir, path, c+1-path);
qprintf ("gamedir: %s\n", gamedir);
return;
}
c++;
}
Error ("No gamedir in %s", path);
return;
}
Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
}
char *ExpandArg (char *path)
{
static char full[1024];
if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
{
Q_getwd (full);
strcat (full, path);
}
else
strcpy (full, path);
return full;
}
char *ExpandPath (char *path)
{
static char full[1024];
if (!qdir)
Error ("ExpandPath called without qdir set");
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
return path;
sprintf (full, "%s%s", qdir, path);
return full;
}
char *ExpandPathAndArchive (char *path)
{
char *expanded;
char archivename[1024];
expanded = ExpandPath (path);
if (archive)
{
sprintf (archivename, "%s/%s", archivedir, path);
QCopyFile (expanded, archivename);
}
return expanded;
}
char *copystring(char *s)
{
char *b;
b = GetMemory(strlen(s)+1);
strcpy (b, s);
return b;
}
/*
================
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
}
void Q_getwd (char *out)
{
#if defined(WIN32) || defined(_WIN32)
getcwd (out, 256);
strcat (out, "\\");
#else
getwd(out);
strcat(out, "/");
#endif
}
void Q_mkdir (char *path)
{
#ifdef WIN32
if (_mkdir (path) != -1)
return;
#else
if (mkdir (path, 0777) != -1)
return;
#endif
if (errno != EEXIST)
Error ("mkdir %s: %s",path, strerror(errno));
}
/*
============
FileTime
returns -1 if not present
============
*/
int FileTime (char *path)
{
struct stat buf;
if (stat (path,&buf) == -1)
return -1;
return buf.st_mtime;
}
/*
==============
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;
do
{
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
}
} while (c1);
return 0; // strings are equal
}
int Q_strcasecmp (char *s1, char *s2)
{
return Q_strncasecmp (s1, s2, 99999);
}
int Q_stricmp (char *s1, char *s2)
{
return Q_strncasecmp (s1, s2, 99999);
}
void Q_strncpyz( char *dest, const char *src, int destsize ) {
strncpy( dest, src, destsize-1 );
dest[destsize-1] = 0;
}
char *strupr (char *start)
{
char *in;
in = start;
while (*in)
{
*in = toupper(*in);
in++;
}
return start;
}
char *strlower (char *start)
{
char *in;
in = start;
while (*in)
{
*in = tolower(*in);
in++;
}
return start;
}
/*
=============================================================================
MISC FUNCTIONS
=============================================================================
*/
/*
=================
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<myargc;i++)
{
if ( !Q_strcasecmp(check, myargv[i]) )
return i;
}
return 0;
}
/*
================
Q_filelength
================
*/
int Q_filelength (FILE *f)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -