7 extern wchar_t* _wcmdln
;
11 extern wchar_t*_wpgmptr
;
13 extern char**_environ
;
20 wchar_t**__wargv
= NULL
;
23 extern wchar_t **__winitenv
;
25 char* strndup(char const* name
, size_t len
)
27 char *s
= malloc(len
+ 1);
36 wchar_t* wcsndup(wchar_t* name
, size_t len
)
38 wchar_t *s
= malloc((len
+ 1) * sizeof(wchar_t));
41 memcpy(s
, name
, len
*sizeof(wchar_t));
47 #define SIZE (4096 / sizeof(char*))
49 int wadd(wchar_t* name
)
52 if ((__argc
% SIZE
) == 0)
55 _new
= malloc(sizeof(wchar_t*) * (1 + SIZE
));
57 _new
= realloc(__wargv
, sizeof(wchar_t*) * (__argc
+ 1 + SIZE
));
62 __wargv
[__argc
++] = name
;
63 __wargv
[__argc
] = NULL
;
67 int wexpand(wchar_t* name
, int expand_wildcards
)
73 wchar_t buffer
[MAX_PATH
];
76 if (expand_wildcards
&& (s
= wcspbrk(name
, L
"*?")))
78 hFile
= FindFirstFileW(name
, &fd
);
79 if (hFile
!= INVALID_HANDLE_VALUE
)
81 while(s
!= name
&& *s
!= L
'/' && *s
!= L
'\\')
84 if (*s
== L
'/' || *s
== L
'\\')
86 wcsncpy(buffer
, name
, pos
);
89 if (!(fd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
91 wcscpy(&buffer
[pos
], fd
.cFileName
);
92 if (wadd(_wcsdup(buffer
)) < 0)
100 while(FindNextFileW(hFile
, &fd
));
117 if ((__argc
% SIZE
) == 0)
120 _new
= malloc(sizeof(char*) * (1 + SIZE
));
122 _new
= realloc(__argv
, sizeof(char*) * (__argc
+ 1 + SIZE
));
127 __argv
[__argc
++] = name
;
128 __argv
[__argc
] = NULL
;
132 int aexpand(char* name
, int expand_wildcards
)
137 BOOLEAN first
= TRUE
;
138 char buffer
[MAX_PATH
];
141 if (expand_wildcards
&& (s
= strpbrk(name
, "*?")))
143 hFile
= FindFirstFileA(name
, &fd
);
144 if (hFile
!= INVALID_HANDLE_VALUE
)
146 while(s
!= name
&& *s
!= '/' && *s
!= '\\')
149 if (*s
== '/' || *s
== '\\')
151 strncpy(buffer
, name
, pos
);
154 if (!(fd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
156 strcpy(&buffer
[pos
], fd
.cFileName
);
157 if (aadd(_strdup(buffer
)) < 0)
165 while(FindNextFileA(hFile
, &fd
));
182 void __getmainargs(int* argc
, char*** argv
, char*** env
, int expand_wildcards
, int* new_mode
)
184 int i
, doexpand
, slashesAdded
, escapedQuote
, inQuotes
, bufferIndex
, anyLetter
;
188 /* missing threading init */
191 doexpand
= expand_wildcards
;
192 escapedQuote
= FALSE
;
198 if (__argv
&& _environ
)
208 len
= strlen(_acmdln
);
209 buffer
= malloc(sizeof(char) * len
);
211 // Reference: https://msdn.microsoft.com/en-us/library/a1y7w461.aspx
214 // Arguments are delimited by white space, which is either a space or a tab.
215 if (i
>= len
|| ((_acmdln
[i
] == ' ' || _acmdln
[i
] == '\t') && !inQuotes
))
217 // Handle the case when empty spaces are in the end of the cmdline
220 aexpand(strndup(buffer
, bufferIndex
), doexpand
);
222 // Copy the last element from buffer and quit the loop
228 while (_acmdln
[i
] == ' ' || _acmdln
[i
] == '\t')
233 escapedQuote
= FALSE
;
239 if (_acmdln
[i
] == '\\')
241 buffer
[bufferIndex
++] = _acmdln
[i
];
244 escapedQuote
= FALSE
;
248 if (_acmdln
[i
] == '\"')
250 if (slashesAdded
> 0)
252 if (slashesAdded
% 2 == 0)
254 // If an even number of backslashes is followed by a double quotation mark, then one backslash (\)
255 // is placed in the argv array for every pair of backslashes (\\), and the double quotation mark (")
256 // is interpreted as a string delimiter.
257 bufferIndex
-= slashesAdded
/ 2;
261 // If an odd number of backslashes is followed by a double quotation mark, then one backslash (\)
262 // is placed in the argv array for every pair of backslashes (\\) and the double quotation mark is
263 // interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark (")
264 // to be placed in argv.
265 bufferIndex
-= slashesAdded
/ 2 + 1;
266 buffer
[bufferIndex
++] = '\"';
274 else if (!inQuotes
&& i
> 0 && _acmdln
[i
- 1] == '\"' && !escapedQuote
)
276 buffer
[bufferIndex
++] = '\"';
282 escapedQuote
= FALSE
;
283 inQuotes
= !inQuotes
;
284 doexpand
= inQuotes
? FALSE
: expand_wildcards
;
289 buffer
[bufferIndex
++] = _acmdln
[i
];
291 escapedQuote
= FALSE
;
295 /* Free the temporary buffer. */
301 __argv
= (char**)malloc(sizeof(char*));
307 _pgmptr
= malloc(MAX_PATH
* sizeof(char));
310 if (!GetModuleFileNameA(NULL
, _pgmptr
, MAX_PATH
))
313 _pgmptr
[MAX_PATH
- 1] = '\0';
317 _pgmptr
= _strdup(__argv
[0]);
320 HeapValidate(GetProcessHeap(), 0, NULL
);
322 // if (new_mode) _set_new_mode(*new_mode);
328 void __wgetmainargs(int* argc
, wchar_t*** wargv
, wchar_t*** wenv
,
329 int expand_wildcards
, int* new_mode
)
331 int i
, doexpand
, slashesAdded
, escapedQuote
, inQuotes
, bufferIndex
, anyLetter
;
335 /* missing threading init */
338 doexpand
= expand_wildcards
;
339 escapedQuote
= FALSE
;
345 if (__wargv
&& __winitenv
)
355 len
= wcslen(_wcmdln
);
356 buffer
= malloc(sizeof(wchar_t) * len
);
358 // Reference: https://msdn.microsoft.com/en-us/library/a1y7w461.aspx
361 // Arguments are delimited by white space, which is either a space or a tab.
362 if (i
>= len
|| ((_wcmdln
[i
] == ' ' || _wcmdln
[i
] == '\t') && !inQuotes
))
364 // Handle the case when empty spaces are in the end of the cmdline
367 wexpand(wcsndup(buffer
, bufferIndex
), doexpand
);
369 // Copy the last element from buffer and quit the loop
375 while (_wcmdln
[i
] == ' ' || _wcmdln
[i
] == '\t')
380 escapedQuote
= FALSE
;
386 if (_wcmdln
[i
] == '\\')
388 buffer
[bufferIndex
++] = _wcmdln
[i
];
391 escapedQuote
= FALSE
;
395 if (_wcmdln
[i
] == '\"')
397 if (slashesAdded
> 0)
399 if (slashesAdded
% 2 == 0)
401 // If an even number of backslashes is followed by a double quotation mark, then one backslash (\)
402 // is placed in the argv array for every pair of backslashes (\\), and the double quotation mark (")
403 // is interpreted as a string delimiter.
404 bufferIndex
-= slashesAdded
/ 2;
408 // If an odd number of backslashes is followed by a double quotation mark, then one backslash (\)
409 // is placed in the argv array for every pair of backslashes (\\) and the double quotation mark is
410 // interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark (")
411 // to be placed in argv.
412 bufferIndex
-= slashesAdded
/ 2 + 1;
413 buffer
[bufferIndex
++] = '\"';
421 else if (!inQuotes
&& i
> 0 && _wcmdln
[i
- 1] == '\"' && !escapedQuote
)
423 buffer
[bufferIndex
++] = '\"';
429 escapedQuote
= FALSE
;
430 inQuotes
= !inQuotes
;
431 doexpand
= inQuotes
? FALSE
: expand_wildcards
;
436 buffer
[bufferIndex
++] = _wcmdln
[i
];
438 escapedQuote
= FALSE
;
442 /* Free the temporary buffer. */
448 __wargv
= (wchar_t**)malloc(sizeof(wchar_t*));
454 _wpgmptr
= malloc(MAX_PATH
* sizeof(wchar_t));
457 if (!GetModuleFileNameW(NULL
, _wpgmptr
, MAX_PATH
))
460 _wpgmptr
[MAX_PATH
- 1] = '\0';
464 _wpgmptr
= _wcsdup(__wargv
[0]);
467 HeapValidate(GetProcessHeap(), 0, NULL
);
469 // if (new_mode) _set_new_mode(*new_mode);
475 int* __p___argc(void)
483 char*** __p___argv(void)
491 wchar_t*** __p___wargv(void)