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(v=vs.71).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. */
297 HeapValidate(GetProcessHeap(), 0, NULL
);
302 __argv
= (char**)malloc(sizeof(char*));
307 _pgmptr
= _strdup(__argv
[0]);
309 // if (new_mode) _set_new_mode(*new_mode);
315 void __wgetmainargs(int* argc
, wchar_t*** wargv
, wchar_t*** wenv
,
316 int expand_wildcards
, int* new_mode
)
318 int i
, doexpand
, slashesAdded
, escapedQuote
, inQuotes
, bufferIndex
, anyLetter
;
322 /* missing threading init */
325 doexpand
= expand_wildcards
;
326 escapedQuote
= FALSE
;
332 if (__wargv
&& __winitenv
)
342 len
= wcslen(_wcmdln
);
343 buffer
= malloc(sizeof(wchar_t) * len
);
345 // Reference: https://msdn.microsoft.com/en-us/library/a1y7w461(v=vs.71).aspx
348 // Arguments are delimited by white space, which is either a space or a tab.
349 if (i
>= len
|| ((_wcmdln
[i
] == ' ' || _wcmdln
[i
] == '\t') && !inQuotes
))
351 // Handle the case when empty spaces are in the end of the cmdline
354 wexpand(wcsndup(buffer
, bufferIndex
), doexpand
);
356 // Copy the last element from buffer and quit the loop
362 while (_wcmdln
[i
] == ' ' || _wcmdln
[i
] == '\t')
367 escapedQuote
= FALSE
;
373 if (_wcmdln
[i
] == '\\')
375 buffer
[bufferIndex
++] = _wcmdln
[i
];
378 escapedQuote
= FALSE
;
382 if (_wcmdln
[i
] == '\"')
384 if (slashesAdded
> 0)
386 if (slashesAdded
% 2 == 0)
388 // If an even number of backslashes is followed by a double quotation mark, then one backslash (\)
389 // is placed in the argv array for every pair of backslashes (\\), and the double quotation mark (")
390 // is interpreted as a string delimiter.
391 bufferIndex
-= slashesAdded
/ 2;
395 // If an odd number of backslashes is followed by a double quotation mark, then one backslash (\)
396 // is placed in the argv array for every pair of backslashes (\\) and the double quotation mark is
397 // interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark (")
398 // to be placed in argv.
399 bufferIndex
-= slashesAdded
/ 2 + 1;
400 buffer
[bufferIndex
++] = '\"';
408 else if (!inQuotes
&& i
> 0 && _wcmdln
[i
- 1] == '\"' && !escapedQuote
)
410 buffer
[bufferIndex
++] = '\"';
416 escapedQuote
= FALSE
;
417 inQuotes
= !inQuotes
;
418 doexpand
= inQuotes
? FALSE
: expand_wildcards
;
423 buffer
[bufferIndex
++] = _wcmdln
[i
];
425 escapedQuote
= FALSE
;
429 /* Free the temporary buffer. */
432 HeapValidate(GetProcessHeap(), 0, NULL
);
437 __wargv
= (wchar_t**)malloc(sizeof(wchar_t*));
442 _wpgmptr
= _wcsdup(__wargv
[0]);
444 // if (new_mode) _set_new_mode(*new_mode);
450 int* __p___argc(void)
458 char*** __p___argv(void)
466 wchar_t*** __p___wargv(void)