]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge commit '84881a66140ad93d0b6cd4d55efbbb459bd91f48' into master-merge
authorThomas Debesse <dev@illwieckz.net>
Tue, 21 Jun 2022 02:22:18 +0000 (04:22 +0200)
committerThomas Debesse <dev@illwieckz.net>
Tue, 21 Jun 2022 02:22:18 +0000 (04:22 +0200)
1  2 
tools/quake3/common/scriplib.c
tools/quake3/common/vfs.c
tools/quake3/common/vfs.h
tools/quake3/q3map2/bspfile_abstract.c
tools/quake3/q3map2/main.c
tools/quake3/q3map2/shaders.c

index 3caa6879111b777558dcd348c71fd66777bea49f,7a5079ead40ee1d19a39da4b9bbd6c10135511f6..7655aa8f25eaa74237be4bc05c449f5bfd058fb7
@@@ -175,7 -175,7 +175,7 @@@ void UnGetToken( void )
  
  qboolean EndOfScript( qboolean crossline ){
        if ( !crossline ) {
-               Error( "Line %i is incomplete\n",scriptline );
+               Error( "Line %i is incomplete\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
        }
  
        if ( !strcmp( script->filename, "memory buffer" ) ) {
@@@ -227,14 -227,14 +227,14 @@@ qboolean GetToken( qboolean crossline )
  // skip space
  //
  skipspace:
 -      while ( *script->script_p <= 32 )
 +      while ( script->script_p < script->end_p && *script->script_p <= 32 )
        {
                if ( script->script_p >= script->end_p ) {
                        return EndOfScript( crossline );
                }
                if ( *script->script_p++ == '\n' ) {
                        if ( !crossline ) {
-                               Error( "Line %i is incomplete\n",scriptline );
+                               Error( "Line %i is incomplete\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
                        }
                        script->line++;
                        scriptline = script->line;
        if ( *script->script_p == ';' || *script->script_p == '#'
                 || ( script->script_p[0] == '/' && script->script_p[1] == '/' ) ) {
                if ( !crossline ) {
-                       Error( "Line %i is incomplete\n",scriptline );
+                       Error( "Line %i is incomplete\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
                }
                while ( *script->script_p++ != '\n' )
                        if ( script->script_p >= script->end_p ) {
        // /* */ comments
        if ( script->script_p[0] == '/' && script->script_p[1] == '*' ) {
                if ( !crossline ) {
-                       Error( "Line %i is incomplete\n",scriptline );
+                       Error( "Line %i is incomplete\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
                }
                script->script_p += 2;
                while ( script->script_p[0] != '*' && script->script_p[1] != '/' )
                                break;
                        }
                        if ( token_p == &token[MAXTOKEN] ) {
-                               Error( "Token too large on line %i\n",scriptline );
+                               Error( "Token too large on line %i\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
                        }
                }
                script->script_p++;
                                break;
                        }
                        if ( token_p == &token[MAXTOKEN] ) {
-                               Error( "Token too large on line %i\n",scriptline );
+                               Error( "Token too large on line %i\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
                        }
                }
        }
index b4f38690c2d5a517cb5f0807ef69e83f15c4612e,362bffe1e6499bfbb8bf0ac60a4ffa58b4bcca16..f741da7c80ed9b6b01acdd086ca7d01545a84bda
@@@ -50,7 -50,7 +50,7 @@@
  #include "mathlib.h"
  #include "inout.h"
  #include "vfs.h"
 -#include <minizip/unzip.h>
 +#include <unzip.h>
  #include <glib.h>
  #define GARUX_DISABLE_BAD_MINIZ
  #ifndef GARUX_DISABLE_BAD_MINIZ
@@@ -59,6 -59,7 +59,7 @@@
  
  typedef struct
  {
+       char* unzFilePath;
        char*   name;
        unzFile zipfile;
        unz_file_pos zippos;
@@@ -75,6 -76,7 +76,7 @@@ static int g_numDirs
  char g_strForbiddenDirs[VFS_MAXDIRS][PATH_MAX + 1];
  int g_numForbiddenDirs = 0;
  static gboolean g_bUsePak = TRUE;
+ char g_strLoadedFileLocation[1024];
  
  // =============================================================================
  // Static functions
@@@ -124,6 -126,8 +126,8 @@@ static void vfsInitPakFile( const char 
        }
        unzGoToFirstFile( uf );
  
+       char* unzFilePath = strdup( filename );
        for ( i = 0; i < gi.number_entry; i++ )
        {
                char filename_inzip[NAME_MAX];
                file->name = strdup( filename_lower );
                file->size = file_info.uncompressed_size;
                file->zipfile = uf;
+               file->unzFilePath = unzFilePath;
                file->zippos = pos;
  
                if ( ( i + 1 ) < gi.number_entry ) {
@@@ -192,7 -197,6 +197,7 @@@ void vfsInitDirectory( const char *pat
        }
  
        if ( g_numDirs == VFS_MAXDIRS ) {
 +              Sys_FPrintf( SYS_WRN, "WARNING: too many VFS directories, can't init %s\n", path );
                return;
        }
  
  
                                        if ( ext != NULL && ( !Q_stricmp( ext, ".pk3dir" ) || !Q_stricmp( ext, ".dpkdir" ) ) ) {
                                                if ( g_numDirs == VFS_MAXDIRS ) {
 +                                                      g_free( dirlist );
                                                        continue;
                                                }
                                                snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s/%s", path, name );
                                        }
  
                                        if ( ext == NULL || ( Q_stricmp( ext, ".pk3" ) != 0 && Q_stricmp( ext, ".dpk" ) != 0 ) ) {
 +                                              g_free( dirlist );
                                                continue;
                                        }
                                }
@@@ -337,6 -339,7 +342,7 @@@ void vfsShutdown()
        while ( g_pakFiles )
        {
                VFS_PAKFILE* file = (VFS_PAKFILE*)g_pakFiles->data;
+               free( file->unzFilePath );
                free( file->name );
                free( file );
                g_pakFiles = g_slist_remove( g_pakFiles, file );
@@@ -375,56 -378,6 +381,56 @@@ int vfsGetFileCount( const char *filena
        return count;
  }
  
 +static qboolean isSymlink(const unz_file_info64 *fileInfo) {
 +      // see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h
 +      // redefine so it works outside of Unices
 +      const unsigned long Q3MAP_S_IFMT = 00170000;
 +      const unsigned long Q3MAP_S_IFLNK = 0120000;
 +      // see https://trac.edgewall.org/attachment/ticket/8919/ZipDownload.patch
 +      const unsigned long PKZIP_EXTERNAL_ATTR_FILE_TYPE_SHIFT = 16;
 +
 +      unsigned long attr = fileInfo->external_fa >> PKZIP_EXTERNAL_ATTR_FILE_TYPE_SHIFT;
 +      return (attr & Q3MAP_S_IFMT) == Q3MAP_S_IFLNK;
 +}
 +
 +// The zip format has a maximum filename size of 64K
 +static const int MAX_FILENAME_BUF = 65537;
 +
 +/* The symlink implementation is ported from Dæmon engine implementation by slipher which was a complete rewrite of one illwieckz did on Dæmon by taking inspiration from Darkplaces engine.
 +
 +See:
 +
 +- https://github.com/DaemonEngine/Daemon/blob/master/src/common/FileSystem.cpp
 +- https://gitlab.com/xonotic/darkplaces/-/blob/div0-stable/fs.c
 +
 +Some words by slipher:
 +
 +> Symlinks are a bad feature which you should not use. Therefore, the implementation is as
 +> slow as possible with a full iteration of the archive performed for each symlink.
 +
 +> The symlink path `relative` must be relative to the symlink's location.
 +> Only supports paths consisting of "../" 0 or more times, followed by non-magical path components.
 +*/
 +void resolveSymlinkPath( const char* base, const char* relative, char* resolved ){
 +
 +      base = g_path_get_dirname( base );
 +
 +      while( g_str_has_prefix( relative, "../" ) )
 +      {
 +              if ( base[0] == '\0' )
 +              {
 +                      Sys_FPrintf( SYS_WRN, "Error while reading symbolic link: \"%s\": no such directory\n", base );
 +                      resolved[0] = '\0';
 +                      return;
 +              }
 +
 +              base = g_path_get_dirname( base );
 +              relative += 3;
 +      }
 +
 +      snprintf( resolved, MAX_FILENAME_BUF, "%s/%s", base, relative);
 +}
 +
  // NOTE: when loading a file, you have to allocate one extra byte and set it to \0
  int vfsLoadFile( const char *filename, void **bufferptr, int index ){
        int i, count = 0;
  
        // filename is a full path
        if ( index == -1 ) {
+               strcpy( g_strLoadedFileLocation, filename );
                long len;
                FILE *f;
  
        }
  
        *bufferptr = NULL;
 -      strcpy( fixed, filename );
 +      strncpy( fixed, filename, sizeof( fixed ) );
        vfsFixDOSName( fixed );
        lower = g_ascii_strdown( fixed, -1 );
  
                strcat( tmp, filename );
                if ( access( tmp, R_OK ) == 0 ) {
                        if ( count == index ) {
+                               strcpy( g_strLoadedFileLocation, tmp );
                                long len;
                                FILE *f;
  
                }
        }
  
 +      // Do not resolve more than 5 recursive symbolic links to
 +      // prevent circular symbolic links.
 +      int max_symlink_depth = 5;
 +
 +      openSymlinkTarget:
        for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
        {
                VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
                }
  
                if ( count == index ) {
+                       strcpy( g_strLoadedFileLocation, file->unzFilePath );
+                       strcat( g_strLoadedFileLocation, " :: " );
+                       strcat( g_strLoadedFileLocation, filename );
  
                if ( unzGoToFilePos( file->zipfile, &file->zippos ) != UNZ_OK ) {
                        return -1;
                                return -1;
                        }
  
 +                      unz_file_info64 fileInfo;
 +                      if ( unzGetCurrentFileInfo64( file->zipfile, &fileInfo, filename, sizeof(filename), NULL, 0, NULL, 0 ) != UNZ_OK ) {
 +                              return -1;
 +                      }
 +
                        *bufferptr = safe_malloc( file->size + 1 );
                        // we need to end the buffer with a 0
                        ( (char*) ( *bufferptr ) )[file->size] = 0;
  
                        i = unzReadCurrentFile( file->zipfile, *bufferptr, file->size );
                        unzCloseCurrentFile( file->zipfile );
 +
 +                      if ( isSymlink( &fileInfo ) ) {
 +                              Sys_FPrintf( SYS_VRB, "Found symbolic link: \"%s\"\n", filename );
 +
 +                              if ( max_symlink_depth == 0 ) {
 +                                      Sys_FPrintf( SYS_WRN, "Maximum symbolic link depth reached\n" );
 +                                      g_free( lower );
 +                                      return -1;
 +                              }
 +
 +                              max_symlink_depth--;
 +
 +                              const char* relative = (const char*) *bufferptr;
 +                              char resolved[MAX_FILENAME_BUF];
 +
 +                              resolveSymlinkPath( file->name, relative, resolved );
 +
 +                              Sys_FPrintf( SYS_VRB, "Resolved symbolic link: \"%s\"\n", resolved );
 +
 +                              g_free( lower );
 +                              strncpy( fixed, resolved, sizeof( fixed ) );
 +                              vfsFixDOSName( fixed );
 +                              lower = g_ascii_strdown( fixed, -1 );
 +
 +                              // slow as possible full iteration of the archive
 +                              goto openSymlinkTarget;
 +                      }
 +
                        if ( i < 0 ) {
 +                              g_free( lower );
                                return -1;
                        }
                        else{
  
                count++;
        }
 +
        g_free( lower );
        return -1;
  }
index f821d886ec760bc28402cbf397455f07108cc6bd,019bfed74df689c51ba0df6bf084c1ca430a8626..706314d42d1d5c747cdc56258a53c078d5ae26bc
  
  // to get PATH_MAX
  #include <stdio.h>
 -#if GDEF_OS_LINUX || GDEF_OS_MACOS
 -#include <dirent.h>
 -#include <unistd.h>
 -#else
 +
 +#if GDEF_OS_WINDOWS
  #include <wtypes.h>
  #include <io.h>
  
  #endif
  
  #define S_ISDIR( mode ) ( mode & _S_IFDIR )
 +#else // !GDEF_OS_WINDOWS
 +#include <dirent.h>
 +#include <unistd.h>
 +#endif // !GDEF_OS_WINDOWS
 +
 +#ifndef PATH_MAX
  #define PATH_MAX 260
 +#endif // PATH_MAX
 +
 +// PATH_MAX
 +#if defined( __FreeBSD__ )
 +#include <sys/syslimits.h>
  #endif
  
 -#define VFS_MAXDIRS 64
 +// Multiple pakpaths with many pk3dirs can lead
 +// to high list of VFS directories
 +#define VFS_MAXDIRS 256
  
  void vfsInitDirectory( const char *path );
  void vfsShutdown();
@@@ -73,5 -62,6 +73,6 @@@ qboolean vfsPackFile_Absolute_Path( con
  
  extern char g_strForbiddenDirs[VFS_MAXDIRS][PATH_MAX + 1];
  extern int g_numForbiddenDirs;
+ extern char g_strLoadedFileLocation[1024];
  
  #endif // _VFS_H_
index 55d358f0e69b65c9d5aa859bcb5036f12beb3d98,a42ba5ed01bd37ee5898930d23dc2ea8bc33b5c8..7286b039a3391fe0ad648d5645fc52ea5a6b38f9
@@@ -94,7 -94,9 +94,7 @@@ void SetDrawVerts( int n )
        numBSPDrawVerts = n;
        numBSPDrawVertsBuffer = numBSPDrawVerts;
  
 -      bspDrawVerts = safe_malloc_info( sizeof( bspDrawVert_t ) * numBSPDrawVertsBuffer, "IncDrawVerts" );
 -
 -      memset( bspDrawVerts, 0, n * sizeof( bspDrawVert_t ) );
 +      bspDrawVerts = safe_malloc0_info( sizeof( bspDrawVert_t ) * numBSPDrawVertsBuffer, "IncDrawVerts" );
  }
  
  int numBSPDrawSurfacesBuffer = 0;
@@@ -105,7 -107,9 +105,7 @@@ void SetDrawSurfacesBuffer()
  
        numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
  
 -      bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
 -
 -      memset( bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( bspDrawSurface_t ) );
 +      bspDrawSurfaces = safe_malloc0_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
  }
  
  void SetDrawSurfaces( int n ){
        numBSPDrawSurfaces = n;
        numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
  
 -      bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
 -
 -      memset( bspDrawSurfaces, 0, n * sizeof( bspDrawSurface_t ) );
 +      bspDrawSurfaces = safe_malloc0_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
  }
  
  void BSPFilesCleanup(){
@@@ -344,16 -350,14 +344,16 @@@ int CopyLump_Allocate( bspHeader_t *hea
  void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length ){
        bspLump_t   *lump;
  
 -
        /* add lump to bsp file header */
        lump = &header->lumps[ lumpNum ];
        lump->offset = LittleLong( ftell( file ) );
        lump->length = LittleLong( length );
  
        /* write lump to file */
 -      SafeWrite( file, data, ( length + 3 ) & ~3 );
 +      SafeWrite( file, data, length );
 +
 +      /* write padding zeros */
 +      SafeWrite( file, (const byte[3]){ 0, 0, 0 }, ( ( length + 3 ) & ~3 ) - length );
  }
  
  
@@@ -391,8 -395,7 +391,7 @@@ void PartialLoadBSPFile( const char *fi
        PartialLoadIBSPFile( filename );
  
        /* PartialSwapBSPFile() */
-       int i, j;
-       shaderInfo_t    *si;
+       int i;
  
        /* shaders (don't swap the name) */
        for ( i = 0; i < numBSPShaders ; i++ )
@@@ -532,7 -535,8 +531,7 @@@ epair_t *ParseEPair( void )
  
  
        /* allocate and clear new epair */
 -      e = safe_malloc( sizeof( epair_t ) );
 -      memset( e, 0, sizeof( epair_t ) );
 +      e = safe_malloc0( sizeof( epair_t ) );
  
        /* handle key */
        if ( strlen( token ) >= ( MAX_KEY - 1 ) ) {
@@@ -647,9 -651,6 +646,9 @@@ if (nocmdline
  
        for ( i = beginArgs; i < endArgs; ++i )
        {
 +              if ( argv[i] == NULL ) {
 +                      continue;
 +              }
                if ( outpos != sentinel && i != beginArgs ) {
                        *outpos++ = ' ';
                }
index 344ededccc47cbf7bd476fa16b64ceeac713c5eb,bfcd53adf65b75a4046e255381bb86fa708577ba..b0e6fa1969bd0d7bc248552c2acaba8bfb05bdd0
@@@ -683,8 -683,8 +683,8 @@@ skipEXfile
                                break;
                        }
                        if ( strcmp( token, "{" ) ) {
-                                       Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
-                                               temp, scriptline, token );
+                                       Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s",
+                                               temp, scriptline, token, g_strLoadedFileLocation );
                        }
  
                        while ( 1 )
                                break;
                        }
                        if ( strcmp( token, "{" ) ) {
-                                       Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
-                                               temp, scriptline, token );
+                                       Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s",
+                                               temp, scriptline, token, g_strLoadedFileLocation );
                        }
  
                        qboolean hasmap = qfalse;
@@@ -1685,8 -1685,8 +1685,8 @@@ skipEXrefile
                                break;
                        }
                        if ( strcmp( token, "{" ) ) {
-                                       Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
-                                               temp, scriptline, token );
+                                       Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s\nFile location be: %s",
+                                               temp, scriptline, token, g_strLoadedFileLocation );
                        }
                        strcat( shaderText, "\n{" );
                        qboolean hasmap = qfalse;
@@@ -2097,16 -2097,14 +2097,16 @@@ int main( int argc, char **argv )
                /* -help */
                if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" )
                        || !strcmp( argv[ i ], "-help" ) ) {
 -                      HelpMain(argv[i+1]);
 +                      HelpMain( ( i + 1 < argc ) ? argv[ i + 1 ] : NULL );
                        return 0;
                }
  
                /* -connect */
                if ( !strcmp( argv[ i ], "-connect" ) ) {
 -                      argv[ i ] = NULL;
 -                      i++;
 +                      if ( ++i >= argc || !argv[ i ] ) {
 +                              Error( "Out of arguments: No address specified after %s", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
                        Broadcast_Setup( argv[ i ] );
                        argv[ i ] = NULL;
                }
  
                /* patch subdivisions */
                else if ( !strcmp( argv[ i ], "-subdivisions" ) ) {
 -                      argv[ i ] = NULL;
 -                      i++;
 +                      if ( ++i >= argc || !argv[ i ] ) {
 +                              Error( "Out of arguments: No value specified after %s", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
                        patchSubdivisions = atoi( argv[ i ] );
                        argv[ i ] = NULL;
                        if ( patchSubdivisions <= 0 ) {
  
                /* threads */
                else if ( !strcmp( argv[ i ], "-threads" ) ) {
 -                      argv[ i ] = NULL;
 -                      i++;
 +                      if ( ++i >= argc || !argv[ i ] ) {
 +                              Error( "Out of arguments: No value specified after %s", argv[ i - 1 ] );
 +                      }
 +                      argv[ i - 1 ] = NULL;
                        numthreads = atoi( argv[ i ] );
                        argv[ i ] = NULL;
                }
  
        Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
        Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
 -      Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
 +      Sys_Printf( RADIANT_NAME "    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
        Sys_Printf( "%s\n", Q3MAP_MOTD );
        Sys_Printf( "%s\n", argv[0] );
  
  
        /* ydnar: otherwise create a bsp */
        else{
 +              /* used to write Smokin'Guns like tex file */
 +              compile_map = qtrue;
 +
                r = BSPMain( argc, argv );
        }
  
index cfa0db86047362e2777b73bf949bf9e1c1c60e2f,0f8b56b47834a08321a46ee1db280433a934179f..3c26a1cda270a3064cd4d495b751344af8590861
@@@ -947,17 -947,17 +947,17 @@@ void Parse1DMatrixAppend( char *buffer
  
  
        if ( !GetTokenAppend( buffer, qtrue ) || strcmp( token, "(" ) ) {
-               Error( "Parse1DMatrixAppend(): line %d: ( not found!", scriptline );
+               Error( "Parse1DMatrixAppend(): line %d: ( not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
        }
        for ( i = 0; i < x; i++ )
        {
                if ( !GetTokenAppend( buffer, qfalse ) ) {
-                       Error( "Parse1DMatrixAppend(): line %d: Number not found!", scriptline );
+                       Error( "Parse1DMatrixAppend(): line %d: Number not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
                }
                m[ i ] = atof( token );
        }
        if ( !GetTokenAppend( buffer, qtrue ) || strcmp( token, ")" ) ) {
-               Error( "Parse1DMatrixAppend(): line %d: ) not found!", scriptline );
+               Error( "Parse1DMatrixAppend(): line %d: ) not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
        }
  }
  
@@@ -1019,12 -1019,12 +1019,12 @@@ static void ParseShaderFile( const cha
                }
                if ( strcmp( token, "{" ) ) {
                        if ( si != NULL ) {
-                               Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s",
-                                          filename, scriptline, token, si->shader );
+                               Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s\nFile location be: %s\n",
+                                          filename, scriptline, token, si->shader, g_strLoadedFileLocation );
                        }
                        else{
-                               Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s",
-                                          filename, scriptline, token );
+                               Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nFile location be: %s\n",
+                                          filename, scriptline, token, g_strLoadedFileLocation );
                        }
                }
  
                        else if ( !Q_stricmp( token, "sun" ) /* sof2 */ || !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) ) {
                                float a, b;
                                sun_t       *sun;
 -                              qboolean ext;
 -
 +                              qboolean ext = qfalse;
  
                                /* ydnar: extended sun directive? */
                                if ( !Q_stricmp( token, "q3map_sunext" ) ) {
                                }
  
                                /* allocate sun */
 -                              sun = safe_malloc( sizeof( *sun ) );
 -                              memset( sun, 0, sizeof( *sun ) );
 +                              sun = safe_malloc0( sizeof( *sun ) );
  
                                /* set style */
                                sun->style = si->lightStyle;
                                        surfaceModel_t  *model;
  
                                        /* allocate new model and attach it */
 -                                      model = safe_malloc( sizeof( *model ) );
 -                                      memset( model, 0, sizeof( *model ) );
 +                                      model = safe_malloc0( sizeof( *model ) );
                                        model->next = si->surfaceModel;
                                        si->surfaceModel = model;
  
  
  
                                        /* allocate new foliage struct and attach it */
 -                                      foliage = safe_malloc( sizeof( *foliage ) );
 -                                      memset( foliage, 0, sizeof( *foliage ) );
 +                                      foliage = safe_malloc0( sizeof( *foliage ) );
                                        foliage->next = si->foliage;
                                        si->foliage = foliage;
  
                                        alpha = ( !Q_stricmp( token, "q3map_alphaGen" ) || !Q_stricmp( token, "q3map_alphaMod" ) ) ? 1 : 0;
  
                                        /* allocate new colormod */
 -                                      cm = safe_malloc( sizeof( *cm ) );
 -                                      memset( cm, 0, sizeof( *cm ) );
 +                                      cm = safe_malloc0( sizeof( *cm ) );
  
                                        /* attach to shader */
                                        if ( si->colorMod == NULL ) {