refactor paths related codes

This commit is contained in:
Garux 2020-01-24 02:47:33 +03:00
parent 437004713f
commit 80e95ac165
12 changed files with 132 additions and 191 deletions

View File

@ -413,7 +413,6 @@ static void ASE_SkipRestOfLine( void ){
static void ASE_KeyMAP_DIFFUSE( const char *token ){
char bitmap[1024];
char filename[1024];
int i = 0;
strcpy( filename, gl_filename );
@ -429,36 +428,18 @@ static void ASE_KeyMAP_DIFFUSE( const char *token ){
}
/* convert backslash to slash */
while ( bitmap[i] )
{
if ( bitmap[i] == '\\' ) {
bitmap[i] = '/';
}
i++;
}
FixDOSName( bitmap );
/* remove filename from path */
for ( i = strlen( filename ); i > 0; i-- )
{
if ( filename[i] == '/' ) {
filename[i] = '\0';
break;
}
}
strclear( path_get_last_separator( filename ) );
/* replaces a relative path with a full path */
if ( bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/' ) {
while ( bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/' )
if ( !strncmp( bitmap, "../", 3 ) ) {
while ( !strncmp( bitmap, "../", 3 ) )
{
/* remove last item from path */
for ( i = strlen( filename ); i > 0; i-- )
{
if ( filename[i] == '/' ) {
filename[i] = '\0';
break;
}
}
strcpy( bitmap, &bitmap[3] );
strclear( path_get_last_separator( filename ) );
memmove( bitmap, &bitmap[3], sizeof( bitmap ) - 3 );
}
strcat( filename, "/" );
strcat( filename, bitmap );
@ -467,7 +448,7 @@ static void ASE_KeyMAP_DIFFUSE( const char *token ){
if ( strstr( bitmap, gamedir ) ) {
strcpy( ase.materials[ase.numMaterials].name, strstr( bitmap, gamedir ) + strlen( gamedir ) );
Sys_Printf( "material name: \'%s\'\n", strstr( bitmap, gamedir ) + strlen( gamedir ) );
Sys_Printf( "material name: \'%s\'\n", ase.materials[ase.numMaterials].name );
}
else
{

View File

@ -48,7 +48,6 @@
#endif
#define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
#define PATHSEPERATOR '/'
#ifdef SAFE_MALLOC
// FIXME switch to -std=c99 or above to use proper %zu format specifier for size_t
@ -166,16 +165,11 @@ char gamedir[1024];
char writedir[1024];
void SetQdirFromPath( const char *path ){
char temp[1024];
const char *c;
const char *sep;
int len, count;
if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
Q_getwd( temp );
strcat( temp, path );
path = temp;
}
path = ExpandArg( path );
// search for "quake2" in path
@ -190,7 +184,7 @@ void SetQdirFromPath( const char *path ){
// so we need to add up how much to the next separator
sep = c + len;
count = 1;
while ( *sep && *sep != '/' && *sep != '\\' )
while ( !strempty( sep ) && !path_separator( *sep ) )
{
sep++;
count++;
@ -202,17 +196,16 @@ void SetQdirFromPath( const char *path ){
c += len + count;
while ( *c )
{
if ( *c == '/' || *c == '\\' ) {
if ( path_separator( *c ) ) {
strncpy( gamedir, path, c + 1 - path );
FixDOSName( gamedir );
Sys_Printf( "gamedir: %s\n", gamedir );
if ( !writedir[0] ) {
if ( strempty( writedir ) ) {
strcpy( writedir, gamedir );
}
else if ( writedir[strlen( writedir ) - 1] != '/' ) {
writedir[strlen( writedir )] = '/';
writedir[strlen( writedir ) + 1] = 0;
else{
path_add_slash( writedir );
}
return;
@ -229,29 +222,25 @@ void SetQdirFromPath( const char *path ){
char *ExpandArg( const char *path ){
static char full[1024];
if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
Q_getwd( full );
strcat( full, path );
if ( path_is_absolute( path ) ) {
strcpy( full, path );
}
else{
strcpy( full, path );
Q_getwd( full );
strcat( full, path );
}
return full;
}
char *ExpandPath( const char *path ){
static char full[1024];
if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
if ( path_is_absolute( path ) ) {
strcpy( full, path );
return full;
}
else{
sprintf( full, "%s%s", qdir, path );
return full;
}
char *copystring( const char *src ){
const size_t size = strlen( src ) + 1;
return memcpy( safe_malloc( size ), src, size );
return full;
}
@ -287,14 +276,13 @@ double I_FloatTime( void ){
void Q_getwd( char *out ){
#ifdef WIN32
_getcwd( out, 256 );
strcat( out, "\\" );
#else
// Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
if ( !getcwd( out, 256 ) ) {
*out = 0;
strclear( out );
}
strcat( out, "/" );
#endif
path_add_slash( out );
FixDOSName( out );
}
@ -306,29 +294,20 @@ void Q_mkdir( const char *path ){
while ( retry-- )
{
#ifdef WIN32
const char *q = NULL;
if ( _mkdir( path ) != -1 ) {
return;
}
if ( errno == ENOENT ) {
p = strrchr( path, '/' );
q = strrchr( path, '\\' );
if ( q && ( !p || q < p ) ) {
p = q;
}
}
#else
if ( mkdir( path, 0777 ) != -1 ) {
return;
}
if ( errno == ENOENT ) {
p = strrchr( path, '/' );
}
#endif
if ( p ) {
strncpy( parentbuf, path, sizeof( parentbuf ) );
if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
parentbuf[p - path] = 0;
if ( errno == ENOENT ) {
p = path_get_last_separator( path );
}
if ( !strempty( p ) ) {
strcpyQ( parentbuf, path, p - path + 1 );
if ( ( p - path ) < (ptrdiff_t) sizeof( parentbuf ) ) {
Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
Q_mkdir( parentbuf );
continue;
@ -436,15 +415,23 @@ skipwhite:
return data;
}
char *strlower( char *start ){
char *in;
in = start;
while ( *in )
{
*in = tolower( *in );
in++;
//http://stackoverflow.com/questions/27303062/strstr-function-like-that-ignores-upper-or-lower-case
//chux: Somewhat tricky to match the corner cases of strstr() with inputs like "x","", "","x", "",""
char *stristr( const char* haystack, const char* needle ) {
do {
const char* h = haystack;
const char* n = needle;
while ( tolower( (unsigned char)*h ) == tolower( (unsigned char)*n ) && *n ) {
h++;
n++;
}
return start;
if ( *n == 0 ) {
return (char *)haystack;
}
} while ( *haystack++ );
return 0;
}
/*
@ -698,15 +685,23 @@ qboolean path_is_absolute( const char* path ){
#endif
}
static inline qboolean path_separator( const char c ){
return c == '/' || c == '\\';
/// \brief Returns a pointer to the last slash or to terminating null character if not found.
char* path_get_last_separator( const char* path ){
const char *end = path + strlen( path );
const char *src = end;
while ( src != path ){
if( path_separator( *--src ) )
return src;
}
return end;
}
/// \brief Returns a pointer to the first character of the filename component of \p path.
char* path_get_filename_start( const char* path ){
const char *src = path + strlen( path );
while ( src != path && !path_separator( *( src - 1 ) ) ){
while ( src != path && !path_separator( src[-1] ) ){
--src;
}
return src;
@ -717,10 +712,9 @@ char* path_get_filename_base_end( const char* path ){
const char *end = path + strlen( path );
const char *src = end;
while ( src != path && !path_separator( *src ) ){
while ( src != path && !path_separator( *--src ) ){
if( *src == '.' )
return src;
--src;
}
return end;
}
@ -731,14 +725,20 @@ char* path_get_extension( const char* path ){
const char *end = path + strlen( path );
const char *src = end;
while ( src != path && !path_separator( *src ) ){
while ( src != path && !path_separator( *--src ) ){
if( *src == '.' )
return src + 1;
--src;
}
return end;
}
/// \brief Appends trailing slash, unless \p path is empty or already has slash.
void path_add_slash( char *path ){
char* end = path + strlen( path );
if ( end != path && !path_separator( end[-1] ) )
strcat( end, "/" );
}
//
// if path doesnt have a .EXT, append extension
// (extension should include the .)
@ -1012,7 +1012,6 @@ unsigned short CRC_Value( unsigned short crcvalue ){
*/
void CreatePath( const char *path ){
const char *ofs;
char c;
char dir[1024];
#ifdef _WIN32
@ -1030,8 +1029,7 @@ void CreatePath( const char *path ){
for ( ofs = path + 1 ; *ofs ; ofs++ )
{
c = *ofs;
if ( c == '/' || c == '\\' ) { // create the directory
if ( path_separator( *ofs ) ) { // create the directory
memcpy( dir, path, ofs - path );
dir[ ofs - path ] = 0;
Q_mkdir( dir );

View File

@ -86,7 +86,16 @@ static inline qboolean strempty( const char* string ){
static inline void strclear( char* string ){
*string = '\0';
}
char *strlower( char *in );
static inline char *strlower( char *string ){
for( char *in = string; *in; ++in )
*in = tolower( *in );
return string;
}
static inline char *copystring( const char *src ){ // version of strdup() with safe_malloc()
const size_t size = strlen( src ) + 1;
return memcpy( safe_malloc( size ), src, size );
}
char* stristr( const char* haystack, const char* needle );
#ifdef WIN32
#define Q_stricmp stricmp
#define Q_strncasecmp strnicmp
@ -136,10 +145,16 @@ int TryLoadFile( const char *filename, void **bufferptr );
void SaveFile( const char *filename, const void *buffer, int count );
qboolean FileExists( const char *filename );
static inline qboolean path_separator( const char c ){
return c == '/' || c == '\\';
}
qboolean path_is_absolute( const char* path );
char* path_get_last_separator( const char* path );
char* path_get_filename_start( const char* path );
char* path_get_filename_base_end( const char* path );
char* path_get_extension( const char* path );
void path_add_slash( char *path );
void DefaultExtension( char *path, const char *extension );
void DefaultPath( char *path, const char *basepath );
void StripFilename( char *path );
@ -170,8 +185,6 @@ char *COM_Parse( char *data );
extern char com_token[1024];
extern qboolean com_eof;
char *copystring( const char *src ); // version of strdup() with safe_malloc()
void CRC_Init( unsigned short *crcvalue );
void CRC_ProcessByte( unsigned short *crcvalue, byte data );

View File

@ -77,15 +77,6 @@ char g_strLoadedFileLocation[1024];
// =============================================================================
// Static functions
static void vfsAddSlash( char *str ){
int n = strlen( str );
if ( n > 0 ) {
if ( str[n - 1] != '\\' && str[n - 1] != '/' ) {
strcat( str, "/" );
}
}
}
//!\todo Define globally or use heap-allocated string.
#define NAME_MAX 255
@ -152,21 +143,15 @@ void vfsInitDirectory( const char *path ){
for ( j = 0; j < g_numForbiddenDirs; ++j )
{
char* dbuf = g_strdup( path );
if ( *dbuf && dbuf[strlen( dbuf ) - 1] == '/' ) {
dbuf[strlen( dbuf ) - 1] = 0;
}
const char *p = strrchr( dbuf, '/' );
p = ( p ? ( p + 1 ) : dbuf );
if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) {
g_free( dbuf );
break;
}
g_free( dbuf );
}
if ( j < g_numForbiddenDirs ) {
char* dbuf = strdup( path );
if ( !strempty( dbuf ) && path_separator( dbuf[strlen( dbuf ) - 1] ) ) // del trailing slash
strclear( &dbuf[strlen( dbuf ) - 1] );
if ( matchpattern( path_get_filename_start( dbuf ), g_strForbiddenDirs[j], TRUE ) ) {
free( dbuf );
return;
}
free( dbuf );
}
if ( g_numDirs == VFS_MAXDIRS ) {
return;
@ -177,7 +162,7 @@ void vfsInitDirectory( const char *path ){
strncpy( g_strDirs[g_numDirs], path, PATH_MAX );
g_strDirs[g_numDirs][PATH_MAX] = 0;
FixDOSName( g_strDirs[g_numDirs] );
vfsAddSlash( g_strDirs[g_numDirs] );
path_add_slash( g_strDirs[g_numDirs] );
g_numDirs++;
if ( g_bUsePak ) {
@ -209,7 +194,7 @@ void vfsInitDirectory( const char *path ){
}
snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s/%s", path, name );
FixDOSName( g_strDirs[g_numDirs] );
vfsAddSlash( g_strDirs[g_numDirs] );
path_add_slash( g_strDirs[g_numDirs] );
++g_numDirs;
}
}

View File

@ -586,9 +586,7 @@ void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets,
strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );
strcpy( matnamebuf, filename );
if ( strrchr( matnamebuf, '/' ) ) {
*( strrchr( matnamebuf, '/' ) + 1 ) = 0;
}
StripFilename( matnamebuf );
strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );
if ( strstr( matnamebuf, gamedir ) ) {

View File

@ -45,7 +45,7 @@ void Cmd_Grab( void ){
GetToken( qfalse );
if ( token[0] == '/' || token[0] == '\\' ) {
if ( path_separator( token[0] ) ) {
sprintf( savename, "%s%s.pcx", writedir, token + 1 );
}
else{
@ -53,7 +53,7 @@ void Cmd_Grab( void ){
}
if ( g_release ) {
if ( token[0] == '/' || token[0] == '\\' ) {
if ( path_separator( token[0] ) ) {
sprintf( dest, "%s.pcx", token + 1 );
}
else{

View File

@ -653,9 +653,7 @@ static void BuildBaseFrame( const char *filename, ObjectAnimationFrame_t *pOAF )
strcpy( shaderName, filename );
}
if ( strrchr( shaderName, '/' ) )
*( strrchr( shaderName, '/' ) + 1 ) = 0;
StripFilename( shaderName );
strcpy( shaderName, pOAF->surfaces[i]->materialname );
*/
@ -724,22 +722,18 @@ static void BuildBaseFrame( const char *filename, ObjectAnimationFrame_t *pOAF )
}
static int LoadModelFile( const char *filename, polyset_t **psets, int *numpolysets ){
int time1;
char file1[1024];
const char *frameFile;
printf( "---------------------\n" );
if ( filename[1] != ':' ) {
frameFile = filename;
sprintf( file1, "%s/%s", g_cddir, frameFile );
if ( !path_is_absolute( filename ) ) {
sprintf( file1, "%s/%s", g_cddir, filename );
}
else
{
strcpy( file1, filename );
}
time1 = FileTime( file1 );
if ( time1 == -1 ) {
if ( FileTime( file1 ) == -1 ) {
Error( "%s doesn't exist", file1 );
}
@ -1176,8 +1170,7 @@ void SkinFrom3DS( const char *filename ){
strcpy( name, filename );
}
if ( strrchr( name, '/' ) )
*( strrchr( name, '/' ) + 1 ) = 0;
StripFilename( name );
*/
strcpy( name, psets[i].materialname );
strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, name );
@ -1902,9 +1895,7 @@ static void ConvertASE( const char *filename, int type, qboolean grabAnims ){
numSurfaces = GetSurfaceAnimations( surfaceAnimations, "u_", -1, -1, g_data.maxUpperFrames );
numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
strcpy( outfilename, filename );
if ( strrchr( outfilename, '/' ) ) {
*( strrchr( outfilename, '/' ) + 1 ) = 0;
}
StripFilename( outfilename );
if ( g_data.currentLod == 0 ) {
strcat( outfilename, "upper.md3" );
@ -1936,9 +1927,7 @@ static void ConvertASE( const char *filename, int type, qboolean grabAnims ){
numSurfaces = GetSurfaceAnimations( surfaceAnimations, "l_", g_data.lowerSkipFrameStart, g_data.lowerSkipFrameEnd, -1 );
numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
strcpy( outfilename, filename );
if ( strrchr( outfilename, '/' ) ) {
*( strrchr( outfilename, '/' ) + 1 ) = 0;
}
StripFilename( outfilename );
if ( g_data.currentLod == 0 ) {
strcat( outfilename, "lower.md3" );
@ -1969,9 +1958,7 @@ static void ConvertASE( const char *filename, int type, qboolean grabAnims ){
numSurfaces = GetSurfaceAnimations( surfaceAnimations, "h_", -1, -1, g_data.maxHeadFrames );
numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
strcpy( outfilename, filename );
if ( strrchr( outfilename, '/' ) ) {
*( strrchr( outfilename, '/' ) + 1 ) = 0;
}
StripFilename( outfilename );
if ( g_data.currentLod == 0 ) {
strcat( outfilename, "head.md3" );

View File

@ -29,9 +29,6 @@
#define MAX_POLYSETS 64
#if defined ( __linux__ ) || defined ( __APPLE__ )
#define strlwr strlower
#endif
typedef struct
{
long len;

View File

@ -104,7 +104,7 @@ static inline void tex2list( StrList* texlist, StrList* EXtex, StrList* rEXtex )
Check if newcoming res is unique
*/
static inline void res2list( StrList* list, const char* res ){
while ( *res == '\\' || *res == '/' ){ // kill prepended slashes
while ( path_separator( *res ) ){ // kill prepended slashes
++res;
}
if ( *res == '\0') // empty

View File

@ -436,19 +436,19 @@ void MiniMapMakeSampleOffsets(){
void MergeRelativePath( char *out, const char *absolute, const char *relative ){
const char *endpos = absolute + strlen( absolute );
while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) )
while ( endpos != absolute && path_separator( endpos[-1] ) )
--endpos;
while ( relative[0] == '.' && relative[1] == '.' && ( relative[2] == '/' || relative[2] == '\\' ) )
while ( !strncmp( relative, "../", 3 ) || !strncmp( relative, "..\\", 3 ) )
{
relative += 3;
while ( endpos != absolute )
{
--endpos;
if ( *endpos == '/' || *endpos == '\\' ) {
if ( path_separator( *endpos ) ) {
break;
}
}
while ( endpos != absolute && ( endpos[-1] == '/' || endpos[-1] == '\\' ) )
while ( endpos != absolute && path_separator( endpos[-1] ) )
--endpos;
}
memcpy( out, absolute, endpos - absolute );

View File

@ -101,20 +101,12 @@ char *LokiGetHomeDir( void ){
*/
void LokiInitPaths( char *argv0 ){
char *home;
if ( !homePath ) {
/* get home dir */
home = LokiGetHomeDir();
if ( home == NULL ) {
home = ".";
homePath = LokiGetHomeDir();
if ( homePath == NULL ) {
homePath = ".";
}
/* set home path */
homePath = home;
}
else{
home = homePath;
}
#ifndef Q_UNIX
@ -131,10 +123,7 @@ void LokiInitPaths( char *argv0 ){
/* do some path divining */
strcpyQ( temp, argv0, sizeof( temp ) );
if ( strrchr( temp, '/' ) ) {
argv0 = strrchr( argv0, '/' ) + 1;
}
else if ( path ) {
if ( strempty( path_get_last_separator( temp ) ) && path ) {
/*
This code has a special behavior when q3map2 is a symbolic link.
@ -158,10 +147,10 @@ void LokiInitPaths( char *argv0 ){
last = path;
/* go through each : segment of path */
while ( last[ 0 ] != '\0' && found == qfalse )
while ( !strempty( last ) && found == qfalse )
{
/* null out temp */
temp[ 0 ] = '\0';
strclear( temp );
/* find next chunk */
last = strchr( path, ':' );
@ -171,7 +160,7 @@ void LokiInitPaths( char *argv0 ){
/* found home dir candidate */
if ( *path == '~' ) {
strcpyQ( temp, home, sizeof( temp ) );
strcpyQ( temp, homePath, sizeof( temp ) );
path++;
}
@ -197,8 +186,8 @@ void LokiInitPaths( char *argv0 ){
if "q3map2" is "/opt/radiant/tools/q3map2",
installPath is "/opt/radiant"
*/
*( strrchr( installPath, '/' ) ) = '\0';
*( strrchr( installPath, '/' ) ) = '\0';
strclear( path_get_last_separator( installPath ) );
strclear( path_get_last_separator( installPath ) );
}
#endif
}
@ -382,7 +371,7 @@ void AddPakPath( char *path ){
*/
void InitPaths( int *argc, char **argv ){
int i, j, k, len, len2;
int i, j, k;
char temp[ MAX_OS_PATH ];
@ -514,28 +503,21 @@ void InitPaths( int *argc, char **argv ){
/* if there is no base path set, figure it out */
if ( numBasePaths == 0 ) {
/* this is another crappy replacement for SetQdirFromPath() */
len2 = strlen( game->magic );
for ( i = 0; i < *argc && numBasePaths == 0; i++ )
{
/* extract the arg */
strcpy( temp, argv[ i ] );
FixDOSName( temp );
len = strlen( temp );
Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
/* this is slow, but only done once */
for ( j = 0; j < ( len - len2 ); j++ )
{
/* check for the game's magic word */
if ( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 ) {
char* found = stristr( temp, game->magic );
if( found ){
/* now find the next slash and nuke everything after it */
while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
temp[ j ] = '\0';
found = strchr( found, '/' );
if( found )
strclear( found );
/* add this as a base path */
AddBasePath( temp );
break;
}
}
}