Skip to content

Commit d33a40b

Browse files
author
Pascal Beyer
committed
Refactor the premain code to make the stupid __argc, __argv and __wargv work. This sucks but at least the raddebugger compiles and runs now.
1 parent 40b6d37 commit d33a40b

File tree

11 files changed

+344
-553
lines changed

11 files changed

+344
-553
lines changed

examples/raddebugger.bat

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
:: @echo off
2+
3+
git clone https://github.com/EpicGamesExt/raddebugger.git --branch v0.9.21-alpha --recursive --depth 1
4+
cd raddebugger || exit /b 1
5+
6+
git checkout *
7+
git clean -xdf
8+
9+
mkdir build
10+
11+
:: Trick the build script into using hlc instead of cl
12+
echo hlc %%* > build\cl.bat || exit /b 1
13+
14+
:: Generate a manifest file
15+
echo int main(){} > arst.c || exit /b 1
16+
17+
cl arst.c /link /manifestdependency:"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'" || exit /b 1
18+
move arst.exe.manifest build\raddbg.exe.manifest || exit /b 1
19+
20+
:: We are ready to build, build all of it!
21+
:: radlink does not build yet
22+
call build raddbg || exit /b 1
23+
24+
cd ..
25+

examples/raylib.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ cd build
1111
cmake .. -G Ninja -D CMAKE_C_COMPILER="C:\Projects\Headerless-C-Compiler\hlc.exe" || exit /b 1
1212
ninja || exit /b 1
1313

14-
:: cd ..\..
14+
cd ..\..
1515

implicit/pre_WinMain.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
#pragma comment(lib, "kernel32")
2+
#include "pre_main_common.c"
33

44
static typedef void * HANDLE;
55
static typedef struct HINSTANCE__ *HINSTANCE;
@@ -38,6 +38,9 @@ __declspec(dllimport) void GetStartupInfoA(struct _STARTUPINFOA *lpStartupInfo);
3838
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
3939

4040
void _start(void){
41+
42+
pre_main_common();
43+
4144
struct _STARTUPINFOA StartupInfo;
4245
GetStartupInfoA(&StartupInfo);
4346

implicit/pre_main.c

Lines changed: 2 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,11 @@
11

2-
#define true 1
3-
#define false 0
4-
5-
#pragma comment(lib, "kernel32")
6-
7-
static int character_is_whitespace(char c){
8-
return (c == '\v') || (c == '\t') || (c == '\f') || (c == ' ');
9-
}
10-
11-
12-
// arguments:
13-
// 'command_line' = the unprocessed command line received by calling 'GetCommandLineA'
14-
// 'command_line_size' = the size of the command line, not including the zero_terminator
15-
// 'out_buffer' = a buffer that is at least as long as the command line,
16-
// which will recieve the processed command line as serial zero_terminated strings
17-
// the return value is the amount of arguments we got.
18-
static int windows_parse_command_line__internal(char *command_line, __int64 command_line_size, char *out_buffer){
19-
20-
// According to msdn:
21-
// 1) Arguments are delimited by white space, which is either a space or tab.
22-
// 2) The first argument must be valid and is the program name. Can be in quotes.
23-
// Everything else does not apply.
24-
// 3) Quotes give rise to arguements that conain spaces.
25-
// Double quotes ("") in qotes give rise to a single quote.
26-
// If the command line ends before ending the last argument then all character read so far are
27-
// the last argument
28-
// 4) \" is just ".
29-
// 5) \ is just \ if it does not precedes a ".
30-
// 6) if there are an even number of \ preceeding ", then they get halved and the " is a delimiter
31-
// 7) if there are an add number of \ preceeding ", then they get halved and the last \" is just ".
32-
33-
34-
// Examples: argv[1] argv[2] argv[3]
35-
// 1) "abc" d e -> abc d e
36-
// 2) a\\b d"e f"g h -> a\\b de fg h
37-
// 3) a\\\"b c d -> a\"b c d
38-
// 4) a\\\\"b c" d -> a\\ b c d
39-
40-
char *at = out_buffer;
41-
42-
// if 'in_quotes' we are also 'in_argument'
43-
int in_quotes = false;
44-
int in_argument = false;
45-
46-
int amount_of_arguments = 0;
47-
48-
for(__int64 i = 0; i < command_line_size; ){
49-
// @note: accsessing command_line[i + 1] is save because of zero termination
50-
// assert(!in_quotes || in_argument);
51-
52-
if(command_line[i] == '\\'){
53-
if(!in_argument){
54-
in_argument = true;
55-
amount_of_arguments++;
56-
}
57-
58-
int amount_of_slashes = 0;
59-
for(; i < command_line_size; i++){
60-
if(command_line[i] != '\\') break;
61-
amount_of_slashes += 1;
62-
}
63-
64-
if(command_line[i] == '"'){
65-
// emit one slash for every pair of slashes
66-
for(int s = 0; s < amount_of_slashes/2; s++) *at++ = '\\';
67-
68-
if(amount_of_slashes & 1){
69-
*at++ = '"'; // it was escaped
70-
i++; // eat the '"'
71-
}else{
72-
continue;
73-
}
74-
}else{
75-
// just emit all the slashes
76-
for(int s = 0; s < amount_of_slashes; s++) *at++ = '\\';
77-
}
78-
}else if(command_line[i] == '"'){
79-
if(!in_quotes){
80-
i++; // skip the '"'
81-
in_quotes = true;
82-
83-
if(!in_argument){
84-
in_argument = true; // if the argument started with quotes ("asd"bcd -> asdbcd)
85-
amount_of_arguments++;
86-
}
87-
}else{
88-
if(command_line[i + 1] == '"'){
89-
i += 2;
90-
*at++ = '"';
91-
}else{
92-
i++;
93-
in_quotes = false;
94-
}
95-
}
96-
}else if(character_is_whitespace(command_line[i])){
97-
if(in_quotes){
98-
*at++ = command_line[i];
99-
}else if(in_argument){
100-
in_argument = false; // end the argument
101-
*at++ = 0;
102-
}else{
103-
// do nothing we are currently in whitespace
104-
}
105-
i++;
106-
}else{
107-
*at++ = command_line[i]; // always just output the character
108-
i++;
109-
if(!in_argument){
110-
in_argument = true;
111-
amount_of_arguments++;
112-
}
113-
}
114-
}
115-
*at++ = 0; // zero terminate
116-
117-
return amount_of_arguments;
118-
}
119-
120-
__declspec(dllimport) void* GlobalAlloc(unsigned int uFlags, unsigned __int64 dwBytes);
121-
__declspec(dllimport) char* GetCommandLineA(void);
122-
__declspec(dllimport) __declspec(noreturn) void ExitProcess(unsigned int uExitCode);
2+
#include "pre_main_common.c"
1233

1244
int main(int argc, char *argv[]);
1255

1266
int _start(void){
127-
char *command_line = GetCommandLineA();
128-
129-
unsigned __int64 command_line_size = 0;
130-
for(char *it = command_line; *it; it++) command_line_size++;
131-
132-
#define GMEM_FIXED 0
133-
char *preped_command_line = (char *)GlobalAlloc(GMEM_FIXED, command_line_size + 1);
134-
int argc = windows_parse_command_line__internal(command_line, command_line_size, preped_command_line);
1357

136-
char **argv = (char **)GlobalAlloc(GMEM_FIXED, (argc + 1) * sizeof(char *));
137-
char *at = preped_command_line;
138-
for(int i = 0; i < argc; i++){
139-
argv[i] = at;
140-
while(*at++); // skip to past the next zero_terminator
141-
}
142-
argv[argc] = 0;
8+
pre_main_common();
1439

14410
int exit_code = main(argc, argv);
14511

0 commit comments

Comments
 (0)