SDL_main.c, placed in the public domain by Sam Lantinga 4/13/98
The WinMain function -- calls your program's main() function
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#define DIR_SEPERATOR "/"
#include "SDL.h"
#include "SDL_main.h"
#ifdef main
# undef main
#endif
#define STDOUT_FILE "stdout.txt"
#define STDERR_FILE "stderr.txt"
#undef SDL_isspace
#define SDL_isspace(a) ((a) == ' ' || (a) == '\t')
static int stdioRedirectEnabled = 0;
static char stdoutPath[MAX_PATH];
static char stderrPath[MAX_PATH];
static void UnEscapeQuotes( char *arg )
{
char *last = NULL;
while( *arg ) {
if( *arg == '"' && *last == '\\' ) {
char *c_curr = arg;
char *c_last = last;
while( *c_curr ) {
*c_last = *c_curr;
c_last = c_curr;
c_curr++;
}
*c_last = '\0';
}
last = arg;
arg++;
}
}
static int ParseCommandLine(char *cmdline, char **argv)
{
char *bufp;
char *lastp = NULL;
int argc, last_argc;
argc = last_argc = 0;
for ( bufp = cmdline; *bufp; ) {
while ( SDL_isspace(*bufp) ) {
++bufp;
}
if ( *bufp == '"' ) {
++bufp;
if ( *bufp ) {
if ( argv ) {
argv[argc] = bufp;
}
++argc;
}
while ( *bufp && ( *bufp != '"' || (lastp && *lastp == '\\') ) ) {
lastp = bufp;
++bufp;
}
} else {
if ( *bufp ) {
if ( argv ) {
argv[argc] = bufp;
}
++argc;
}
while ( *bufp && ! SDL_isspace(*bufp) ) {
++bufp;
}
}
if ( *bufp ) {
if ( argv ) {
*bufp = '\0';
}
++bufp;
}
if( argv && last_argc != argc ) {
UnEscapeQuotes( argv[last_argc] );
}
last_argc = argc;
}
if ( argv ) {
argv[argc] = NULL;
}
return(argc);
}
static void ShowError(const char *title, const char *message)
{
#ifdef USE_MESSAGEBOX
MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK);
#else
fprintf(stderr, "%s: %s\n", title, message);
#endif
}
static BOOL OutOfMemory(void)
{
ShowError("Fatal Error", "Out of memory - aborting");
return FALSE;
}
calling conventions may differ... */
static void cleanup(void)
{
SDL_Quit();
}
static void cleanup_output(void) {
FILE *file;
int empty;
fclose(stdout);
fclose(stderr);
if (!stdioRedirectEnabled) {
return;
}
if ( stdoutPath[0] ) {
file = fopen(stdoutPath, "rb");
if ( file ) {
empty = (fgetc(file) == EOF) ? 1 : 0;
fclose(file);
if ( empty ) {
remove(stdoutPath);
}
}
}
if ( stderrPath[0] ) {
file = fopen(stderrPath, "rb");
if ( file ) {
empty = (fgetc(file) == EOF) ? 1 : 0;
fclose(file);
if ( empty ) {
remove(stderrPath);
}
}
}
}
static void redirect_output(void)
{
DWORD pathlen;
char path[MAX_PATH];
FILE *newfp;
pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path));
while ( pathlen > 0 && path[pathlen] != '\\' ) {
--pathlen;
}
path[pathlen] = '\0';
SDL_strlcpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
newfp = freopen(stdoutPath, "w", stdout);
if ( newfp == NULL ) {
#if !defined(stdout)
stdout = fopen(stdoutPath, "w");
#else
newfp = fopen(stdoutPath, "w");
if ( newfp ) {
*stdout = *newfp;
}
#endif
}
SDL_strlcpy( stderrPath, path, SDL_arraysize(stderrPath) );
SDL_strlcat( stderrPath, DIR_SEPERATOR STDERR_FILE, SDL_arraysize(stderrPath) );
newfp = freopen(stderrPath, "w", stderr);
if ( newfp == NULL ) {
#if !defined(stderr)
stderr = fopen(stderrPath, "w");
#else
newfp = fopen(stderrPath, "w");
if ( newfp ) {
*stderr = *newfp;
}
#endif
}
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
setbuf(stderr, NULL);
stdioRedirectEnabled = 1;
}
#if defined(_MSC_VER)
#define console_main main
#endif
int console_main(int argc, char *argv[])
{
size_t n;
char *bufp, *appname;
int status;
appname = argv[0];
if ( (bufp=SDL_strrchr(argv[0], '\\')) != NULL ) {
appname = bufp+1;
} else
if ( (bufp=SDL_strrchr(argv[0], '/')) != NULL ) {
appname = bufp+1;
}
if ( (bufp=SDL_strrchr(appname, '.')) == NULL )
n = SDL_strlen(appname);
else
n = (bufp-appname);
bufp = SDL_stack_alloc(char, n+1);
if ( bufp == NULL ) {
return OutOfMemory();
}
SDL_strlcpy(bufp, appname, n+1);
appname = bufp;
if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
ShowError("WinMain() error", SDL_GetError());
return(FALSE);
}
atexit(cleanup_output);
atexit(cleanup);
We still need to pass in the application handle so that
DirectInput will initialize properly when SDL_RegisterApp()
is called later in the video initialization.
*/
SDL_SetModuleHandle(GetModuleHandle(NULL));
status = SDL_main(argc, argv);
exit(status);
return 0;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
HMODULE handle;
char **argv;
int argc;
char *cmdline;
char *env_str;
char *bufp;
size_t nLen;
keep them open. This is a hack.. hopefully it will be fixed
someday. DDHELP.EXE starts up the first time DDRAW.DLL is loaded.
*/
handle = LoadLibrary(TEXT("DDRAW.DLL"));
if ( handle != NULL ) {
FreeLibrary(handle);
}
if ((env_str = SDL_getenv("SDL_STDIO_REDIRECT"))) {
if (SDL_atoi(env_str)) {
redirect_output();
}
}
#ifndef NO_STDIO_REDIRECT
else {
redirect_output();
}
#endif
bufp = GetCommandLine();
nLen = SDL_strlen(bufp)+1;
cmdline = SDL_stack_alloc(char, nLen);
if ( cmdline == NULL ) {
return OutOfMemory();
}
SDL_strlcpy(cmdline, bufp, nLen);
argc = ParseCommandLine(cmdline, NULL);
argv = SDL_stack_alloc(char*, argc+1);
if ( argv == NULL ) {
return OutOfMemory();
}
ParseCommandLine(cmdline, argv);
console_main(argc, argv);
return 0;
}