Changes On Branch mingw-broken-cmdline
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch mingw-broken-cmdline Excluding Merge-Ins

This is equivalent to a diff from c42408e15b to d43165418c

2012-09-11
11:57
Merge the latest trunk changes and the mingw-broken-cmdline branch into unicode-cmdline. Closed-Leaf check-in: b19ef490fd user: drh tags: unicode-cmdline
2012-09-10
18:15
add .PHONY target to makefile, this makes "make test" work even though there already is a directory named "test" check-in: ffcdfadbda user: jan.nijtmans tags: trunk
08:21
Add some test cases Closed-Leaf check-in: d43165418c user: jan.nijtmans tags: mingw-broken-cmdline
2012-09-09
22:06
Reformat the windows command-line parser to following the Fossil style. Use the alternative command-line parser on all windows builds, not just for MinGW builds, to simplify the logic and so that the alternative parser code is testing more heavily. check-in: f575af97b2 user: drh tags: mingw-broken-cmdline
20:53
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. check-in: 047dd62604 user: jan.nijtmans tags: mingw-broken-cmdline
2012-09-08
13:13
Fix a harmless compiler warning. check-in: c42408e15b user: drh tags: trunk
2012-09-07
21:12
On windows, make "gdiff" default to using WinDiff.exe. check-in: cad57bf65d user: drh tags: trunk

Changes to src/main.c.

   328    328   #endif
   329    329     free(g.zErrMsg);
   330    330     if(g.db){
   331    331       db_close(0);
   332    332     }
   333    333   }
   334    334   
          335  +#if defined(_WIN32)
   335    336   /*
   336         -** Convert all arguments from mbcs to UTF-8. Then
          337  +** Parse the command-line arguments passed to windows.  We do this
          338  +** ourselves to work around bugs in the command-line parsing of MinGW.
          339  +** It is possible (in theory) to only use this routine when compiling
          340  +** with MinGW and to use built-in command-line parsing for MSVC and
          341  +** MinGW-64.  However, the code is here, it is efficient, and works, and
          342  +** by using it in all cases we do a better job of testing it.  If you suspect
          343  +** a bug in this code, test your theory by invoking "fossil test-echo".
          344  +**
          345  +** This routine is copied from TCL with some reformatting.
          346  +** The original comment text follows:
          347  +**
          348  +** Parse the Windows command line string into argc/argv. Done here
          349  +** because we don't trust the builtin argument parser in crt0. Windows
          350  +** applications are responsible for breaking their command line into
          351  +** arguments.
          352  +**
          353  +** 2N backslashes + quote -> N backslashes + begin quoted string
          354  +** 2N + 1 backslashes + quote -> literal
          355  +** N backslashes + non-quote -> literal
          356  +** quote + quote in a quoted string -> single quote
          357  +** quote + quote not in quoted string -> empty string
          358  +** quote -> begin quoted string
          359  +**
          360  +** Results:
          361  +** Fills argcPtr with the number of arguments and argvPtr with the array
          362  +** of arguments.
          363  +*/
          364  +#include <tchar.h>
          365  +#define tchar_isspace(X)  ((X)==TEXT(' ') || (X)==TEXT('\t'))
          366  +static void parse_windows_command_line(
          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  +  size = 2;
          381  +  for(p=cmdLine; *p!=TEXT('\0'); p++){
          382  +    if( tchar_isspace(*p) ){
          383  +      size++;
          384  +      while( tchar_isspace(*p) ){
          385  +        p++;
          386  +      }
          387  +      if( *p==TEXT('\0') ){
          388  +        break;
          389  +      }
          390  +    }
          391  +  }
          392  +
          393  +  argSpace = fossil_malloc(size * sizeof(char*)
          394  +    + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
          395  +  argv = (TCHAR**)argSpace;
          396  +  argSpace += size*(sizeof(char*)/sizeof(TCHAR));
          397  +  size--;
          398  +
          399  +  p = cmdLine;
          400  +  for(argc=0; argc<size; argc++){
          401  +    argv[argc] = arg = argSpace;
          402  +    while( tchar_isspace(*p) ){
          403  +      p++;
          404  +    }
          405  +    if (*p == TEXT('\0')) {
          406  +      break;
          407  +    }
          408  +    inquote = 0;
          409  +    slashes = 0;
          410  +    while(1){
          411  +      copy = 1;
          412  +      while( *p==TEXT('\\') ){
          413  +        slashes++;
          414  +        p++;
          415  +      }
          416  +      if( *p==TEXT('"') ){
          417  +        if( (slashes&1)==0 ){
          418  +          copy = 0;
          419  +          if( inquote && p[1]==TEXT('"') ){
          420  +            p++;
          421  +            copy = 1;
          422  +          }else{
          423  +            inquote = !inquote;
          424  +          }
          425  +        }
          426  +        slashes >>= 1;
          427  +      }
          428  +      while( slashes ){
          429  +        *arg = TEXT('\\');
          430  +        arg++;
          431  +        slashes--;
          432  +      }
          433  +      if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
          434  +        break;
          435  +      }
          436  +      if( copy!=0 ){
          437  +        *arg = *p;
          438  +        arg++;
          439  +      }
          440  +      p++;
          441  +    }
          442  +    *arg = '\0';
          443  +    argSpace = arg + 1;
          444  +  }
          445  +  argv[argc] = NULL;
          446  +  *argcPtr = argc;
          447  +  *((TCHAR ***)argvPtr) = argv;
          448  +}
          449  +#endif /* defined(_WIN32) */
          450  +
          451  +
          452  +/*
          453  +** Convert all arguments from mbcs (or unicode) to UTF-8. Then
   337    454   ** search g.argv for arguments "--args FILENAME". If found, then
   338    455   ** (1) remove the two arguments from g.argv
   339    456   ** (2) Read the file FILENAME
   340    457   ** (3) Use the contents of FILE to replace the two removed arguments:
   341    458   **     (a) Ignore blank lines in the file
   342    459   **     (b) Each non-empty line of the file is an argument, except
   343    460   **     (c) If the line begins with "-" and contains a space, it is broken
   344    461   **         into two arguments at the space.
   345    462   */
   346         -static void expand_args_option(int argc, char **argv){
          463  +static void expand_args_option(int argc, void *argv){
   347    464     Blob file = empty_blob;   /* Content of the file */
   348    465     Blob line = empty_blob;   /* One line of the file */
   349    466     unsigned int nLine;       /* Number of lines in the file*/
   350    467     unsigned int i, j, k;     /* Loop counters */
   351    468     int n;                    /* Number of bytes in one line */
   352         -  char *z;            /* General use string pointer */
   353         -  char **newArgv;     /* New expanded g.argv under construction */
          469  +  char *z;                  /* General use string pointer */
          470  +  char **newArgv;           /* New expanded g.argv under construction */
   354    471     char const * zFileName;   /* input file name */
   355    472     FILE * zInFile;           /* input FILE */
   356    473     int foundBom = -1;        /* -1= not searched yet, 0 = no; 1=yes */
   357    474   #ifdef _WIN32
   358    475     wchar_t buf[MAX_PATH];
   359    476   #endif
   360    477   
   361    478     g.argc = argc;
   362    479     g.argv = argv;
   363    480   #ifdef _WIN32
          481  +  parse_windows_command_line(&g.argc, &g.argv);
   364    482     GetModuleFileNameW(NULL, buf, MAX_PATH);
   365    483     g.argv[0] = fossil_unicode_to_utf8(buf);
          484  +#ifdef UNICODE
          485  +  for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
          486  +#else
   366    487     for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
          488  +#endif
   367    489   #endif
   368    490     for(i=1; i<g.argc-1; i++){
   369    491       z = g.argv[i];
   370    492       if( z[0]!='-' ) continue;
   371    493       z++;
   372    494       if( z[0]=='-' ) z++;
   373    495       if( z[0]==0 ) return;   /* Stop searching at "--" */
................................................................................
   398    520       if( n<=1 ) continue;
   399    521       z = blob_buffer(&line);
   400    522       z[n-1] = 0;
   401    523       if (foundBom == -1) {
   402    524         static const char bom[] = { 0xEF, 0xBB, 0xBF };
   403    525         foundBom = memcmp(z, bom, 3)==0;
   404    526         if( foundBom ) {
   405         -    	  z += 3; n -= 3;
          527  +        z += 3; n -= 3;
   406    528         }
   407    529       }
   408    530       if((n>1) && ('\r'==z[n-2])){
   409    531         if(n==2) continue /*empty line*/;
   410    532         z[n-2] = 0;
   411    533       }
   412    534       if (!foundBom) {
................................................................................
  1740   1862   **   --th-trace          trace TH1 execution (for debugging purposes)
  1741   1863   **
  1742   1864   ** See also: cgi, http, winsrv
  1743   1865   */
  1744   1866   void cmd_webserver(void){
  1745   1867     int iPort, mxPort;        /* Range of TCP ports allowed */
  1746   1868     const char *zPort;        /* Value of the --port option */
  1747         -  char *zBrowser;           /* Name of web browser program */
         1869  +  const char *zBrowser;     /* Name of web browser program */
  1748   1870     char *zBrowserCmd = 0;    /* Command to launch the web browser */
  1749   1871     int isUiCmd;              /* True if command is "ui", not "server' */
  1750   1872     const char *zNotFound;    /* The --notfound option or NULL */
  1751   1873     int flags = 0;            /* Server flags */
  1752   1874   
  1753   1875   #if defined(_WIN32)
  1754   1876     const char *zStopperFile;    /* Name of file used to terminate server */
................................................................................
  1777   1899     }
  1778   1900   #if !defined(_WIN32)
  1779   1901     /* Unix implementation */
  1780   1902     if( isUiCmd ){
  1781   1903   #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
  1782   1904       zBrowser = db_get("web-browser", 0);
  1783   1905       if( zBrowser==0 ){
  1784         -      static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
         1906  +      static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
  1785   1907         int i;
  1786   1908         zBrowser = "echo";
  1787   1909         for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
  1788   1910           if( binaryOnPath(azBrowserProg[i]) ){
  1789   1911             zBrowser = azBrowserProg[i];
  1790   1912             break;
  1791   1913           }

Changes to src/makemake.tcl.

   464    464   endif
   465    465   
   466    466   # With JSON support
   467    467   ifdef FOSSIL_ENABLE_JSON
   468    468   TCC += -DFOSSIL_ENABLE_JSON=1
   469    469   RCC += -DFOSSIL_ENABLE_JSON=1
   470    470   endif
          471  +
          472  +# Fix buggy MinGW command line parsing
          473  +ifdef MINGW_BROKEN_MAINARGS
          474  +TCC += -DMINGW_BROKEN_MAINARGS
          475  +endif
   471    476   
   472    477   #### We add the -static option here so that we can build a static
   473    478   #    executable that will run in a chroot jail.
   474    479   #
   475    480   LIB = -static
   476    481   
   477    482   # OpenSSL: Add the necessary libraries required, if enabled.

Added test/cmdline.test.

            1  +#
            2  +# Copyright (c) 2011 D. Richard Hipp
            3  +#
            4  +# This program is free software; you can redistribute it and/or
            5  +# modify it under the terms of the Simplified BSD License (also
            6  +# known as the "2-Clause License" or "FreeBSD License".)
            7  +#
            8  +# This program is distributed in the hope that it will be useful,
            9  +# but without any warranty; without even the implied warranty of
           10  +# merchantability or fitness for a particular purpose.
           11  +#
           12  +# Author contact information:
           13  +#   drh@hwaci.com
           14  +#   http://www.hwaci.com/drh/
           15  +#
           16  +############################################################################
           17  +#
           18  +# Test command line parsing
           19  +#
           20  +
           21  +proc cmd-line {testname args} {
           22  +  set i 1
           23  +  foreach {cmdline result} $args {
           24  +    fossil test-echo {*}$cmdline
           25  +    test cmd-line-$testname.$i {[lrange [split $::RESULT \n] 2 end]=="\{argv\[2\] = \[$result\]\}"}
           26  +    incr i
           27  +  }
           28  +}
           29  +cmd-line 100 abc abc {"abc"} abc
           30  +cmd-line 101 * {*} *.* {*.*}

Changes to win/Makefile.mingw.

   143    143   endif
   144    144   
   145    145   # With JSON support
   146    146   ifdef FOSSIL_ENABLE_JSON
   147    147   TCC += -DFOSSIL_ENABLE_JSON=1
   148    148   RCC += -DFOSSIL_ENABLE_JSON=1
   149    149   endif
          150  +
          151  +# Fix buggy MinGW command line parsing
          152  +ifdef MINGW_BROKEN_MAINARGS
          153  +TCC += -DMINGW_BROKEN_MAINARGS
          154  +endif
   150    155   
   151    156   #### We add the -static option here so that we can build a static
   152    157   #    executable that will run in a chroot jail.
   153    158   #
   154    159   LIB = -static
   155    160   
   156    161   # OpenSSL: Add the necessary libraries required, if enabled.