#include #include #include #include #include #include #include #include #include "../game/q_shared.h" #include "../qcommon/qcommon.h" //=============================================================================== // Used to determine CD Path static char programpath[MAX_OSPATH]; /* ================ Sys_Milliseconds ================ */ int curtime; int sys_timeBase; int Sys_Milliseconds (void) { struct timeval tp; struct timezone tzp; gettimeofday(&tp, &tzp); if (!sys_timeBase) { sys_timeBase = tp.tv_sec; return tp.tv_usec/1000; } curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000; return curtime; } void Sys_Mkdir( const char *path ) { mkdir (path, 0777); } //============================================ /* Like glob_match, but match PATTERN against any final segment of TEXT. */ static int glob_match_after_star(char *pattern, char *text) { register char *p = pattern, *t = text; register char c, c1; while ((c = *p++) == '?' || c == '*') if (c == '?' && *t++ == '\0') return 0; if (c == '\0') return 1; if (c == '\\') c1 = *p; else c1 = c; while (1) { if ((c == '[' || *t == c1) && glob_match(p - 1, t)) return 1; if (*t++ == '\0') return 0; } } /* Return nonzero if PATTERN has any special globbing chars in it. */ static int glob_pattern_p(char *pattern) { register char *p = pattern; register char c; int open = 0; while ((c = *p++) != '\0') switch (c) { case '?': case '*': return 1; case '[': /* Only accept an open brace if there is a close */ open++; /* brace to match it. Bracket expressions must be */ continue; /* complete, according to Posix.2 */ case ']': if (open) return 1; continue; case '\\': if (*p++ == '\0') return 0; } return 0; } /* Match the pattern PATTERN against the string TEXT; return 1 if it matches, 0 otherwise. A match means the entire string TEXT is used up in matching. In the pattern string, `*' matches any sequence of characters, `?' matches any character, [SET] matches any character in the specified set, [!SET] matches any character not in the specified set. A set is composed of characters or ranges; a range looks like character hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the set of characters allowed in C identifiers. Any other character in the pattern must be matched exactly. To suppress the special syntactic significance of any of `[]*?!-\', and match the character exactly, precede it with a `\'. */ int glob_match(char *pattern, char *text) { register char *p = pattern, *t = text; register char c; while ((c = *p++) != '\0') switch (c) { case '?': if (*t == '\0') return 0; else ++t; break; case '\\': if (*p++ != *t++) return 0; break; case '*': return glob_match_after_star(p, t); case '[': { register char c1 = *t++; int invert; if (!c1) return (0); invert = ((*p == '!') || (*p == '^')); if (invert) p++; c = *p++; while (1) { register char cstart = c, cend = c; if (c == '\\') { cstart = *p++; cend = cstart; } if (c == '\0') return 0; c = *p++; if (c == '-' && *p != ']') { cend = *p++; if (cend == '\\') cend = *p++; if (cend == '\0') return 0; c = *p++; } if (c1 >= cstart && c1 <= cend) goto match; if (c == ']') break; } if (!invert) return 0; break; match: /* Skip the rest of the [...] construct that already matched. */ while (c != ']') { if (c == '\0') return 0; c = *p++; if (c == '\0') return 0; else if (c == '\\') ++p; } if (invert) return 0; break; } default: if (c != *t++) return 0; } return *t == '\0'; } //============================================ #define MAX_FOUND_FILES 0x1000 char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs ) { struct dirent *d; char *p; DIR *fdir; qboolean dironly = wantsubs; char search[MAX_OSPATH]; int nfiles; char **listCopy; char *list[MAX_FOUND_FILES]; int flag; int i; struct stat st; int extLen; if ( !extension) extension = ""; if ( extension[0] == '/' && extension[1] == 0 ) { extension = ""; dironly = qtrue; } extLen = strlen( extension ); // search nfiles = 0; if ((fdir = opendir(directory)) == NULL) { *numfiles = 0; return NULL; } while ((d = readdir(fdir)) != NULL) { Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name); if (stat(search, &st) == -1) continue; if ((dironly && !(st.st_mode & S_IFDIR)) || (!dironly && (st.st_mode & S_IFDIR))) continue; if (*extension) { if ( strlen( d->d_name ) < strlen( extension ) || Q_stricmp( d->d_name + strlen( d->d_name ) - strlen( extension ), extension ) ) { continue; // didn't match } } if ( nfiles == MAX_FOUND_FILES - 1 ) break; list[ nfiles ] = CopyString( d->d_name ); nfiles++; } list[ nfiles ] = 0; closedir(fdir); // return a copy of the list *numfiles = nfiles; if ( !nfiles ) { return NULL; } listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) ); for ( i = 0 ; i < nfiles ; i++ ) { listCopy[i] = list[i]; } listCopy[i] = NULL; return listCopy; } void Sys_FreeFileList( char **list ) { int i; if ( !list ) { return; } for ( i = 0 ; list[i] ; i++ ) { Z_Free( list[i] ); } Z_Free( list ); } char *Sys_Cwd( void ) { static char cwd[MAX_OSPATH]; getcwd( cwd, sizeof( cwd ) - 1 ); cwd[MAX_OSPATH-1] = 0; return cwd; } void SetProgramPath(char *path) { char *p; Q_strncpyz(programpath, path, sizeof(programpath)); if ((p = strrchr(programpath, '/')) != NULL) *p = 0; // remove program name, leave only path } char *Sys_DefaultCDPath(void) { if (*programpath) return programpath; else return Sys_Cwd(); } char *Sys_DefaultBasePath(void) { char *p; static char basepath[MAX_OSPATH]; int e; if ((p = getenv("HOME")) != NULL) { Q_strncpyz(basepath, p, sizeof(basepath)); Q_strcat(basepath, sizeof(basepath), "/.q3a"); if (mkdir(basepath, 0777)) { if (errno != EEXIST) Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", basepath, strerror(errno), errno); } return basepath; } return ""; // assume current dir } //============================================ int Sys_GetProcessorId( void ) { return CPUID_GENERIC; } void Sys_ShowConsole( int visLevel, qboolean quitOnClose ) { }