Fossil SCM

Fix ticket [906c533302]. If you want to replace the mingw command-line pa a better one (conforming to ms rules), compile with -DMINGW_BROKEN_MAINARGS. MinGW doesn't support unicode command line parsing (linker option -municode), so the option -DMINGW_BROKEN_MAINARGS can be used to fix that too.

jan.nijtmans 2012-09-09 20:53 UTC trunk
Commit 047dd626041159512720c5fd2d9663cf18c94a91
+142 -7
--- src/main.c
+++ src/main.c
@@ -331,28 +331,151 @@
331331
db_close(0);
332332
}
333333
}
334334
335335
/*
336
-** Convert all arguments from mbcs to UTF-8. Then
336
+ *-------------------------------------------------------------------------
337
+ *
338
+ * setargv --
339
+ *
340
+ * Parse the Windows command line string into argc/argv. Done here
341
+ * because we don't trust the builtin argument parser in crt0. Windows
342
+ * applications are responsible for breaking their command line into
343
+ * arguments.
344
+ *
345
+ * 2N backslashes + quote -> N backslashes + begin quoted string
346
+ * 2N + 1 backslashes + quote -> literal
347
+ * N backslashes + non-quote -> literal
348
+ * quote + quote in a quoted string -> single quote
349
+ * quote + quote not in quoted string -> empty string
350
+ * quote -> begin quoted string
351
+ *
352
+ * Results:
353
+ * Fills argcPtr with the number of arguments and argvPtr with the array
354
+ * of arguments.
355
+ *
356
+ * Side effects:
357
+ * Memory allocated.
358
+ *
359
+ *--------------------------------------------------------------------------
360
+ */
361
+
362
+#ifdef MINGW_BROKEN_MAINARGS
363
+#include <tchar.h>
364
+
365
+static void
366
+setargv(
367
+ int *argcPtr, /* Filled with number of argument strings. */
368
+ void *argvPtr) /* Filled with argument strings (malloc'd). */
369
+{
370
+ TCHAR *cmdLine, *p, *arg, *argSpace;
371
+ TCHAR **argv;
372
+ int argc, size, inquote, copy, slashes;
373
+
374
+ cmdLine = GetCommandLine();
375
+
376
+ /*
377
+ * Precompute an overly pessimistic guess at the number of arguments in
378
+ * the command line by counting non-space spans.
379
+ */
380
+
381
+ size = 2;
382
+ for (p = cmdLine; *p != TEXT('\0'); p++) {
383
+ if ((*p == TEXT(' ')) || (*p == TEXT('\t'))) { /* INTL: ISO space. */
384
+ size++;
385
+ while ((*p == TEXT(' ')) || (*p == TEXT('\t'))) { /* INTL: ISO space. */
386
+ p++;
387
+ }
388
+ if (*p == TEXT('\0')) {
389
+ break;
390
+ }
391
+ }
392
+ }
393
+
394
+ argSpace = fossil_malloc(size * sizeof(char *)
395
+ + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
396
+ argv = (TCHAR **) argSpace;
397
+ argSpace += size * (sizeof(char *)/sizeof(TCHAR));
398
+ size--;
399
+
400
+ p = cmdLine;
401
+ for (argc = 0; argc < size; argc++) {
402
+ argv[argc] = arg = argSpace;
403
+ while ((*p == TEXT(' ')) || (*p == TEXT('\t'))) { /* INTL: ISO space. */
404
+ p++;
405
+ }
406
+ if (*p == TEXT('\0')) {
407
+ break;
408
+ }
409
+
410
+ inquote = 0;
411
+ slashes = 0;
412
+ while (1) {
413
+ copy = 1;
414
+ while (*p == TEXT('\\')) {
415
+ slashes++;
416
+ p++;
417
+ }
418
+ if (*p == TEXT('"')) {
419
+ if ((slashes & 1) == 0) {
420
+ copy = 0;
421
+ if ((inquote) && (p[1] == TEXT('"'))) {
422
+ p++;
423
+ copy = 1;
424
+ } else {
425
+ inquote = !inquote;
426
+ }
427
+ }
428
+ slashes >>= 1;
429
+ }
430
+
431
+ while (slashes) {
432
+ *arg = TEXT('\\');
433
+ arg++;
434
+ slashes--;
435
+ }
436
+
437
+ if ((*p == TEXT('\0')) || (!inquote &&
438
+ ((*p == TEXT(' ')) || (*p == TEXT('\t'))))) { /* INTL: ISO space. */
439
+ break;
440
+ }
441
+ if (copy != 0) {
442
+ *arg = *p;
443
+ arg++;
444
+ }
445
+ p++;
446
+ }
447
+ *arg = '\0';
448
+ argSpace = arg + 1;
449
+ }
450
+ argv[argc] = NULL;
451
+
452
+ *argcPtr = argc;
453
+ *((TCHAR ***)argvPtr) = argv;
454
+}
455
+#endif /* MINGW_BROKEN_MAINARGS */
456
+
457
+
458
+/*
459
+** Convert all arguments from mbcs (or unicode) to UTF-8. Then
337460
** search g.argv for arguments "--args FILENAME". If found, then
338461
** (1) remove the two arguments from g.argv
339462
** (2) Read the file FILENAME
340463
** (3) Use the contents of FILE to replace the two removed arguments:
341464
** (a) Ignore blank lines in the file
342465
** (b) Each non-empty line of the file is an argument, except
343466
** (c) If the line begins with "-" and contains a space, it is broken
344467
** into two arguments at the space.
345468
*/
346
-static void expand_args_option(int argc, char **argv){
469
+static void expand_args_option(int argc, void *argv){
347470
Blob file = empty_blob; /* Content of the file */
348471
Blob line = empty_blob; /* One line of the file */
349472
unsigned int nLine; /* Number of lines in the file*/
350473
unsigned int i, j, k; /* Loop counters */
351474
int n; /* Number of bytes in one line */
352
- char *z; /* General use string pointer */
353
- char **newArgv; /* New expanded g.argv under construction */
475
+ char *z; /* General use string pointer */
476
+ char **newArgv; /* New expanded g.argv under construction */
354477
char const * zFileName; /* input file name */
355478
FILE * zInFile; /* input FILE */
356479
int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
357480
#ifdef _WIN32
358481
wchar_t buf[MAX_PATH];
@@ -359,13 +482,20 @@
359482
#endif
360483
361484
g.argc = argc;
362485
g.argv = argv;
363486
#ifdef _WIN32
487
+#ifdef MINGW_BROKEN_MAINARGS
488
+ setargv(&g.argc, &g.argv);
489
+#endif
364490
GetModuleFileNameW(NULL, buf, MAX_PATH);
365491
g.argv[0] = fossil_unicode_to_utf8(buf);
492
+#ifdef UNICODE
493
+ for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
494
+#else
366495
for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
496
+#endif
367497
#endif
368498
for(i=1; i<g.argc-1; i++){
369499
z = g.argv[i];
370500
if( z[0]!='-' ) continue;
371501
z++;
@@ -430,11 +560,16 @@
430560
}
431561
432562
/*
433563
** This procedure runs first.
434564
*/
435
-int main(int argc, char **argv){
565
+#if defined(_WIN32) && defined(UNICODE) && !defined(MINGW_BROKEN_MAINARGS)
566
+int wmain(int argc, wchar_t **argv)
567
+#else
568
+int main(int argc, char **argv)
569
+#endif
570
+{
436571
const char *zCmdName = "unknown";
437572
int idx;
438573
int rc;
439574
440575
sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -1742,11 +1877,11 @@
17421877
** See also: cgi, http, winsrv
17431878
*/
17441879
void cmd_webserver(void){
17451880
int iPort, mxPort; /* Range of TCP ports allowed */
17461881
const char *zPort; /* Value of the --port option */
1747
- char *zBrowser; /* Name of web browser program */
1882
+ const char *zBrowser; /* Name of web browser program */
17481883
char *zBrowserCmd = 0; /* Command to launch the web browser */
17491884
int isUiCmd; /* True if command is "ui", not "server' */
17501885
const char *zNotFound; /* The --notfound option or NULL */
17511886
int flags = 0; /* Server flags */
17521887
@@ -1779,11 +1914,11 @@
17791914
/* Unix implementation */
17801915
if( isUiCmd ){
17811916
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17821917
zBrowser = db_get("web-browser", 0);
17831918
if( zBrowser==0 ){
1784
- static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1919
+ static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
17851920
int i;
17861921
zBrowser = "echo";
17871922
for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
17881923
if( binaryOnPath(azBrowserProg[i]) ){
17891924
zBrowser = azBrowserProg[i];
17901925
--- src/main.c
+++ src/main.c
@@ -331,28 +331,151 @@
331 db_close(0);
332 }
333 }
334
335 /*
336 ** Convert all arguments from mbcs to UTF-8. Then
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337 ** search g.argv for arguments "--args FILENAME". If found, then
338 ** (1) remove the two arguments from g.argv
339 ** (2) Read the file FILENAME
340 ** (3) Use the contents of FILE to replace the two removed arguments:
341 ** (a) Ignore blank lines in the file
342 ** (b) Each non-empty line of the file is an argument, except
343 ** (c) If the line begins with "-" and contains a space, it is broken
344 ** into two arguments at the space.
345 */
346 static void expand_args_option(int argc, char **argv){
347 Blob file = empty_blob; /* Content of the file */
348 Blob line = empty_blob; /* One line of the file */
349 unsigned int nLine; /* Number of lines in the file*/
350 unsigned int i, j, k; /* Loop counters */
351 int n; /* Number of bytes in one line */
352 char *z; /* General use string pointer */
353 char **newArgv; /* New expanded g.argv under construction */
354 char const * zFileName; /* input file name */
355 FILE * zInFile; /* input FILE */
356 int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
357 #ifdef _WIN32
358 wchar_t buf[MAX_PATH];
@@ -359,13 +482,20 @@
359 #endif
360
361 g.argc = argc;
362 g.argv = argv;
363 #ifdef _WIN32
 
 
 
364 GetModuleFileNameW(NULL, buf, MAX_PATH);
365 g.argv[0] = fossil_unicode_to_utf8(buf);
 
 
 
366 for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
 
367 #endif
368 for(i=1; i<g.argc-1; i++){
369 z = g.argv[i];
370 if( z[0]!='-' ) continue;
371 z++;
@@ -430,11 +560,16 @@
430 }
431
432 /*
433 ** This procedure runs first.
434 */
435 int main(int argc, char **argv){
 
 
 
 
 
436 const char *zCmdName = "unknown";
437 int idx;
438 int rc;
439
440 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -1742,11 +1877,11 @@
1742 ** See also: cgi, http, winsrv
1743 */
1744 void cmd_webserver(void){
1745 int iPort, mxPort; /* Range of TCP ports allowed */
1746 const char *zPort; /* Value of the --port option */
1747 char *zBrowser; /* Name of web browser program */
1748 char *zBrowserCmd = 0; /* Command to launch the web browser */
1749 int isUiCmd; /* True if command is "ui", not "server' */
1750 const char *zNotFound; /* The --notfound option or NULL */
1751 int flags = 0; /* Server flags */
1752
@@ -1779,11 +1914,11 @@
1779 /* Unix implementation */
1780 if( isUiCmd ){
1781 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1782 zBrowser = db_get("web-browser", 0);
1783 if( zBrowser==0 ){
1784 static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1785 int i;
1786 zBrowser = "echo";
1787 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1788 if( binaryOnPath(azBrowserProg[i]) ){
1789 zBrowser = azBrowserProg[i];
1790
--- src/main.c
+++ src/main.c
@@ -331,28 +331,151 @@
331 db_close(0);
332 }
333 }
334
335 /*
336 *-------------------------------------------------------------------------
337 *
338 * setargv --
339 *
340 * Parse the Windows command line string into argc/argv. Done here
341 * because we don't trust the builtin argument parser in crt0. Windows
342 * applications are responsible for breaking their command line into
343 * arguments.
344 *
345 * 2N backslashes + quote -> N backslashes + begin quoted string
346 * 2N + 1 backslashes + quote -> literal
347 * N backslashes + non-quote -> literal
348 * quote + quote in a quoted string -> single quote
349 * quote + quote not in quoted string -> empty string
350 * quote -> begin quoted string
351 *
352 * Results:
353 * Fills argcPtr with the number of arguments and argvPtr with the array
354 * of arguments.
355 *
356 * Side effects:
357 * Memory allocated.
358 *
359 *--------------------------------------------------------------------------
360 */
361
362 #ifdef MINGW_BROKEN_MAINARGS
363 #include <tchar.h>
364
365 static void
366 setargv(
367 int *argcPtr, /* Filled with number of argument strings. */
368 void *argvPtr) /* Filled with argument strings (malloc'd). */
369 {
370 TCHAR *cmdLine, *p, *arg, *argSpace;
371 TCHAR **argv;
372 int argc, size, inquote, copy, slashes;
373
374 cmdLine = GetCommandLine();
375
376 /*
377 * Precompute an overly pessimistic guess at the number of arguments in
378 * the command line by counting non-space spans.
379 */
380
381 size = 2;
382 for (p = cmdLine; *p != TEXT('\0'); p++) {
383 if ((*p == TEXT(' ')) || (*p == TEXT('\t'))) { /* INTL: ISO space. */
384 size++;
385 while ((*p == TEXT(' ')) || (*p == TEXT('\t'))) { /* INTL: ISO space. */
386 p++;
387 }
388 if (*p == TEXT('\0')) {
389 break;
390 }
391 }
392 }
393
394 argSpace = fossil_malloc(size * sizeof(char *)
395 + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
396 argv = (TCHAR **) argSpace;
397 argSpace += size * (sizeof(char *)/sizeof(TCHAR));
398 size--;
399
400 p = cmdLine;
401 for (argc = 0; argc < size; argc++) {
402 argv[argc] = arg = argSpace;
403 while ((*p == TEXT(' ')) || (*p == TEXT('\t'))) { /* INTL: ISO space. */
404 p++;
405 }
406 if (*p == TEXT('\0')) {
407 break;
408 }
409
410 inquote = 0;
411 slashes = 0;
412 while (1) {
413 copy = 1;
414 while (*p == TEXT('\\')) {
415 slashes++;
416 p++;
417 }
418 if (*p == TEXT('"')) {
419 if ((slashes & 1) == 0) {
420 copy = 0;
421 if ((inquote) && (p[1] == TEXT('"'))) {
422 p++;
423 copy = 1;
424 } else {
425 inquote = !inquote;
426 }
427 }
428 slashes >>= 1;
429 }
430
431 while (slashes) {
432 *arg = TEXT('\\');
433 arg++;
434 slashes--;
435 }
436
437 if ((*p == TEXT('\0')) || (!inquote &&
438 ((*p == TEXT(' ')) || (*p == TEXT('\t'))))) { /* INTL: ISO space. */
439 break;
440 }
441 if (copy != 0) {
442 *arg = *p;
443 arg++;
444 }
445 p++;
446 }
447 *arg = '\0';
448 argSpace = arg + 1;
449 }
450 argv[argc] = NULL;
451
452 *argcPtr = argc;
453 *((TCHAR ***)argvPtr) = argv;
454 }
455 #endif /* MINGW_BROKEN_MAINARGS */
456
457
458 /*
459 ** Convert all arguments from mbcs (or unicode) to UTF-8. Then
460 ** search g.argv for arguments "--args FILENAME". If found, then
461 ** (1) remove the two arguments from g.argv
462 ** (2) Read the file FILENAME
463 ** (3) Use the contents of FILE to replace the two removed arguments:
464 ** (a) Ignore blank lines in the file
465 ** (b) Each non-empty line of the file is an argument, except
466 ** (c) If the line begins with "-" and contains a space, it is broken
467 ** into two arguments at the space.
468 */
469 static void expand_args_option(int argc, void *argv){
470 Blob file = empty_blob; /* Content of the file */
471 Blob line = empty_blob; /* One line of the file */
472 unsigned int nLine; /* Number of lines in the file*/
473 unsigned int i, j, k; /* Loop counters */
474 int n; /* Number of bytes in one line */
475 char *z; /* General use string pointer */
476 char **newArgv; /* New expanded g.argv under construction */
477 char const * zFileName; /* input file name */
478 FILE * zInFile; /* input FILE */
479 int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
480 #ifdef _WIN32
481 wchar_t buf[MAX_PATH];
@@ -359,13 +482,20 @@
482 #endif
483
484 g.argc = argc;
485 g.argv = argv;
486 #ifdef _WIN32
487 #ifdef MINGW_BROKEN_MAINARGS
488 setargv(&g.argc, &g.argv);
489 #endif
490 GetModuleFileNameW(NULL, buf, MAX_PATH);
491 g.argv[0] = fossil_unicode_to_utf8(buf);
492 #ifdef UNICODE
493 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
494 #else
495 for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
496 #endif
497 #endif
498 for(i=1; i<g.argc-1; i++){
499 z = g.argv[i];
500 if( z[0]!='-' ) continue;
501 z++;
@@ -430,11 +560,16 @@
560 }
561
562 /*
563 ** This procedure runs first.
564 */
565 #if defined(_WIN32) && defined(UNICODE) && !defined(MINGW_BROKEN_MAINARGS)
566 int wmain(int argc, wchar_t **argv)
567 #else
568 int main(int argc, char **argv)
569 #endif
570 {
571 const char *zCmdName = "unknown";
572 int idx;
573 int rc;
574
575 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -1742,11 +1877,11 @@
1877 ** See also: cgi, http, winsrv
1878 */
1879 void cmd_webserver(void){
1880 int iPort, mxPort; /* Range of TCP ports allowed */
1881 const char *zPort; /* Value of the --port option */
1882 const char *zBrowser; /* Name of web browser program */
1883 char *zBrowserCmd = 0; /* Command to launch the web browser */
1884 int isUiCmd; /* True if command is "ui", not "server' */
1885 const char *zNotFound; /* The --notfound option or NULL */
1886 int flags = 0; /* Server flags */
1887
@@ -1779,11 +1914,11 @@
1914 /* Unix implementation */
1915 if( isUiCmd ){
1916 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1917 zBrowser = db_get("web-browser", 0);
1918 if( zBrowser==0 ){
1919 static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1920 int i;
1921 zBrowser = "echo";
1922 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1923 if( binaryOnPath(azBrowserProg[i]) ){
1924 zBrowser = azBrowserProg[i];
1925
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -466,10 +466,15 @@
466466
# With JSON support
467467
ifdef FOSSIL_ENABLE_JSON
468468
TCC += -DFOSSIL_ENABLE_JSON=1
469469
RCC += -DFOSSIL_ENABLE_JSON=1
470470
endif
471
+
472
+# Fix buggy MinGW command line parsing
473
+ifdef MINGW_BROKEN_MAINARGS
474
+TCC += -DMINGW_BROKEN_MAINARGS
475
+endif
471476
472477
#### We add the -static option here so that we can build a static
473478
# executable that will run in a chroot jail.
474479
#
475480
LIB = -static
476481
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -466,10 +466,15 @@
466 # With JSON support
467 ifdef FOSSIL_ENABLE_JSON
468 TCC += -DFOSSIL_ENABLE_JSON=1
469 RCC += -DFOSSIL_ENABLE_JSON=1
470 endif
 
 
 
 
 
471
472 #### We add the -static option here so that we can build a static
473 # executable that will run in a chroot jail.
474 #
475 LIB = -static
476
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -466,10 +466,15 @@
466 # With JSON support
467 ifdef FOSSIL_ENABLE_JSON
468 TCC += -DFOSSIL_ENABLE_JSON=1
469 RCC += -DFOSSIL_ENABLE_JSON=1
470 endif
471
472 # Fix buggy MinGW command line parsing
473 ifdef MINGW_BROKEN_MAINARGS
474 TCC += -DMINGW_BROKEN_MAINARGS
475 endif
476
477 #### We add the -static option here so that we can build a static
478 # executable that will run in a chroot jail.
479 #
480 LIB = -static
481
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145145
# With JSON support
146146
ifdef FOSSIL_ENABLE_JSON
147147
TCC += -DFOSSIL_ENABLE_JSON=1
148148
RCC += -DFOSSIL_ENABLE_JSON=1
149149
endif
150
+
151
+# Fix buggy MinGW command line parsing
152
+ifdef MINGW_BROKEN_MAINARGS
153
+TCC += -DMINGW_BROKEN_MAINARGS
154
+endif
150155
151156
#### We add the -static option here so that we can build a static
152157
# executable that will run in a chroot jail.
153158
#
154159
LIB = -static
155160
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145 # With JSON support
146 ifdef FOSSIL_ENABLE_JSON
147 TCC += -DFOSSIL_ENABLE_JSON=1
148 RCC += -DFOSSIL_ENABLE_JSON=1
149 endif
 
 
 
 
 
150
151 #### We add the -static option here so that we can build a static
152 # executable that will run in a chroot jail.
153 #
154 LIB = -static
155
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145 # With JSON support
146 ifdef FOSSIL_ENABLE_JSON
147 TCC += -DFOSSIL_ENABLE_JSON=1
148 RCC += -DFOSSIL_ENABLE_JSON=1
149 endif
150
151 # Fix buggy MinGW command line parsing
152 ifdef MINGW_BROKEN_MAINARGS
153 TCC += -DMINGW_BROKEN_MAINARGS
154 endif
155
156 #### We add the -static option here so that we can build a static
157 # executable that will run in a chroot jail.
158 #
159 LIB = -static
160

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button